Apache CloudStack Administration Guide
Backups
Monitoring
SNMP
CloudStack will send alerts for a number of
Syslog
AMQP
JMX
API Queries
Usage
Tuning
Configuration Parameters
System Reliability and Availability
HA for Management Server
The CloudStack Management Server should be deployed in a multi-node
configuration such that it is not susceptible to individual server failures.
The Management Server itself (as distinct from the MySQL database) is
stateless and may be placed behind a load balancer.
Normal operation of Hosts is not impacted by an outage of all Management
Serves. All guest VMs will continue to work.
When the Management Server is down, no new VMs can be created, and the end
user and admin UI, API, dynamic load distribution, and HA will cease to work.
Management Server Load Balancing
CloudStack can use a load balancer to provide a virtual IP for multiple
Management Servers. The administrator is responsible for creating the load
balancer rules for the Management Servers. The application requires
persistence or stickiness across multiple sessions. The following chart lists
the ports that should be load balanced and whether or not persistence is
required.
Source port |
Destination port |
Protocol |
Persistence Required? |
80 or 443 |
8080 (or 20400 with AJP) |
HTTP (or AJP) |
Yes |
8250 |
8250 |
TCP |
Yes |
In addition to above settings, the administrator is responsible for setting
the ‘host’ global config value from the management server IP to load balancer
virtual IP address. If the ‘host’ value is not set to the VIP for Port 8250
and one of your management servers crashes, the UI is still available but the
system VMs will not be able to contact the management server.
Limiting the Rate of API Requests
You can limit the rate at which API requests can be placed for each account.
This is useful to avoid malicious attacks on the Management Server, prevent
performance degradation, and provide fairness to all accounts.
If the number of API calls exceeds the threshold, an error message is returned
for any additional API calls. The caller will have to retry these API calls at
another time.
Configuring the API Request Rate
To control the API request rate, use the following global configuration
settings:
api.throttling.enabled - Enable/Disable API throttling. By default, this
setting is false, so API throttling is not enabled.
api.throttling.interval (in seconds) - Time interval during which the
number of API requests is to be counted. When the interval has passed, the
API count is reset to 0.
api.throttling.max - Maximum number of APIs that can be placed within the
api.throttling.interval period.
api.throttling.cachesize - Cache size for storing API counters. Use a value
higher than the total number of accounts managed by the cloud. One cache
entry is needed for each account, to store the running API total for that
account.
Limitations on API Throttling
The following limitations exist in the current implementation of this feature:
In a deployment with multiple Management Servers, the cache is not
synchronized across them. In this case, CloudStack might not be able to
ensure that only the exact desired number of API requests are allowed. In
the worst case, the number of API calls that might be allowed is (number
of Management Servers) * (api.throttling.max)
.
The API commands resetApiLimit and getApiLimit are limited to the
Management Server where the API is invoked.
HA-Enabled Virtual Machines
The user can specify a virtual machine as HA-enabled. By default, all virtual
router VMs and Elastic Load Balancing VMs are automatically configured as
HA-enabled. When an HA-enabled VM crashes, CloudStack detects the crash and
restarts the VM automatically within the same Availability Zone. HA is never
performed across different Availability Zones. CloudStack has a conservative
policy towards restarting VMs and ensures that there will never be two
instances of the same VM running at the same time. The Management Server
attempts to start the VM on another Host in the same cluster.
VM HA is not supported when the VM is using local storage.
Dedicated HA Hosts
One or more hosts can be designated for use only by HA-enabled VMs that are
restarting due to a host failure. Setting up a pool of such dedicated HA hosts
as the recovery destination for all HA-enabled VMs is useful to:
Make it easier to determine which VMs have been restarted as part of the
CloudStack high-availability function. If a VM is running on a dedicated HA
host, then it must be an HA-enabled VM whose original host failed. (With
one exception: It is possible for an administrator to manually migrate any
VM to a dedicated HA host.).
Keep HA-enabled VMs from restarting on hosts which may be reserved for
other purposes.
The dedicated HA option is set through a special host tag when the host is
created. To allow the administrator to dedicate hosts to only HA-enabled VMs,
set the global configuration variable ha.tag to the desired tag (for example,
“ha_host”), and restart the Management Server. Enter the value in the Host
Tags field when adding the host(s) that you want to dedicate to HA-enabled VMs.
Primary Storage Outage and Data Loss
When a primary storage outage occurs the hypervisor immediately stops all VMs
stored on that storage device. Guests that are marked for HA will be restarted
as soon as practical when the primary storage comes back on line. With NFS,
the hypervisor may allow the virtual machines to continue running depending on
the nature of the issue. For example, an NFS hang will cause the guest VMs to
be suspended until storage connectivity is restored.Primary storage is not
designed to be backed up. Individual volumes in primary storage can be backed
up using snapshots.
Secondary Storage Outage and Data Loss
For a Zone that has only one secondary storage server, a secondary storage
outage will have feature level impact to the system but will not impact
running guest VMs. It may become impossible to create a VM with the selected
template for a user. A user may also not be able to save snapshots or
examine/restore saved snapshots. These features will automatically be
available when the secondary storage comes back online.
Secondary storage data loss will impact recently added user data including
templates, snapshots, and ISO images. Secondary storage should be backed up
periodically. Multiple secondary storage servers can be provisioned within
each zone to increase the scalability of the system.
Managing System VMs
CloudStack uses several types of system virtual machines to perform tasks in
the cloud. In general CloudStack manages these system VMs and creates, starts,
and stops them as needed based on scale and immediate needs. However, the
administrator should be aware of them and their roles to assist in debugging
issues.
You can configure the system.vm.random.password parameter to create a random
system VM password to ensure higher security. If you reset the value for
system.vm.random.password to true and restart the Management Server, a random
password is generated and stored encrypted in the database. You can view the
decrypted password under the system.vm.password global parameter on the
CloudStack UI or by calling the listConfigurations API.
The System VM Template
The System VMs come from a single template. The System VM has the following
characteristics:
Debian 6.0 (“Squeeze”), 2.6.32 kernel with the latest security patches from
the Debian security APT repository
Has a minimal set of packages installed thereby reducing the attack surface
32-bit for enhanced performance on Xen/VMWare
pvops kernel with Xen PV drivers, KVM virtio drivers, and VMware tools for
optimum performance on all hypervisors
Xen tools inclusion allows performance monitoring
Latest versions of HAProxy, iptables, IPsec, and Apache from debian
repository ensures improved security and speed
Latest version of JRE from Sun/Oracle ensures improved security and speed
Accessing System VMs
It may sometimes be necessary to access System VMs for diagnostics of certain
issues, for example if you are experiencing SSVM (Secondary Storage VM)
connection issues. Use the steps below in order to connect to the SSH console
of a running System VM.
Accessing System VMs over the network requires the use of private keys and
connecting to System VMs SSH Daemon on port 3922. XenServer/KVM Hypervisors
store this key at /root/.ssh/id_rsa.cloud on each CloudStack agent. To access
System VMs running on ESXi, the key is stored on the management server at
/var/lib/cloudstack/management/.ssh/id_rsa.
Find the details of the System VM
Log in with admin privileges to the CloudStack UI.
Click Infrastructure, then System VMs, and then click the name of a
running VM.
Take a note of the ‘Host’, ‘Private IP Address’ and ‘Link Local IP
Address’ of the System VM you wish to access.
XenServer/KVM Hypervisors
Connect to the Host of which the System VM is running.
SSH to the ‘Link Local IP Address’ of the System VM from the Host on
which the VM is running.
Format: ssh -i <path-to-private-key> <link-local-ip> -p 3922
Example: root@faith:~# ssh -i /root/.ssh/id_rsa.cloud <IP_ADDRESS> -p 3922
ESXi Hypervisors
Connect to your CloudStack Management Server.
ESXi users should SSH to the private IP address of the System VM.
Format: ssh -i <path-to-private-key> <vm-private-ip> -p 3922
Example: root@management:~# ssh -i /var/lib/cloudstack/management/.ssh/id_rsa <IP_ADDRESS> -p 3922
Multiple System VM Support for VMware
Every CloudStack zone has single System VM for template processing tasks such
as downloading templates, uploading templates, and uploading ISOs. In a zone
where VMware is being used, additional System VMs can be launched to process
VMware-specific tasks such as taking snapshots and creating private templates.
The CloudStack management server launches additional System VMs for
VMware-specific tasks as the load increases. The management server monitors
and weights all commands sent to these System VMs and performs dynamic load
balancing and scaling-up of more System VMs.
Console Proxy
The Console Proxy is a type of System Virtual Machine that has a role in
presenting a console view via the web UI. It connects the user’s browser to
the VNC port made available via the hypervisor for the console of the guest.
Both the administrator and end user web UIs offer a console connection.
Clicking a console icon brings up a new window. The AJAX code downloaded into
that window refers to the public IP address of a console proxy VM. There is
exactly one public IP address allocated per console proxy VM. The AJAX
application connects to this IP. The console proxy then proxies the connection
to the VNC port for the requested VM on the Host hosting the guest.
The console proxy VM will periodically report its active session count to the
Management Server. The default reporting interval is five seconds. This can be
changed through standard Management Server configuration with the parameter
consoleproxy.loadscan.interval.
Assignment of guest VM to console proxy is determined by first determining if
the guest VM has a previous session associated with a console proxy. If it
does, the Management Server will assign the guest VM to the target Console
Proxy VM regardless of the load on the proxy VM. Failing that, the first
available running Console Proxy VM that has the capacity to handle new
sessions is used.
Console proxies can be restarted by administrators but this will interrupt
existing console sessions for users.
Using a SSL Certificate for the Console Proxy
The console viewing functionality uses a dynamic DNS service under the domain
name realhostip.com to assist in providing SSL security to console sessions.
The console proxy is assigned a public IP address. In order to avoid browser
warnings for mismatched SSL certificates, the URL for the new console window
is set to the form of https://aaa-bbb-ccc-ddd.realhostip.com. You will see
this URL during console session creation. CloudStack includes the
realhostip.com SSL certificate in the console proxy VM. Of course, CloudStack
cannot know about the DNS A records for our customers’ public IPs prior to
shipping the software. CloudStack therefore runs a dynamic DNS server that is
authoritative for the realhostip.com domain. It maps the aaa-bbb-ccc-ddd part
of the DNS name to the IP address aaa.bbb.ccc.ddd on lookups. This allows the
browser to correctly connect to the console proxy’s public IP, where it then
expects and receives a SSL certificate for realhostip.com, and SSL is set up
without browser warnings.
Changing the Console Proxy SSL Certificate and Domain
If the administrator prefers, it is possible for the URL of the customer’s
console session to show a domain other than realhostip.com. The administrator
can customize the displayed domain by selecting a different domain and
uploading a new SSL certificate and private key. The domain must run a DNS
service that is capable of resolving queries for addresses of the form
aaa-bbb-ccc-ddd.your.domain to an IPv4 IP address in the form aaa.bbb.ccc.ddd,
for example, <IP_ADDRESS>. To change the console proxy domain, SSL certificate,
and private key:
Set up dynamic name resolution or populate all possible DNS names in your
public IP range into your existing DNS server with the format
aaa-bbb-ccc-ddd.company.com -> aaa.bbb.ccc.ddd.
Generate the private key and certificate signing request (CSR). When you
are using openssl to generate private/public key pairs and CSRs, for the
private key that you are going to paste into the CloudStack UI, be sure to
convert it into PKCS#8 format.
Generate a new 2048-bit private key
openssl genrsa -des3 -out yourprivate.key 2048
Generate a new certificate CSR
openssl req -new -key yourprivate.key -out yourcertificate.csr
Head to the website of your favorite trusted Certificate Authority,
purchase an SSL certificate, and submit the CSR. You should receive a
valid certificate in return
Convert your private key format into PKCS#8 encrypted format.
openssl pkcs8 -topk8 -in yourprivate.key -out yourprivate.pkcs8.encrypted.key
Convert your PKCS#8 encrypted private key into the PKCS#8 format that is
compliant with CloudStack
openssl pkcs8 -in yourprivate.pkcs8.encrypted.key -out yourprivate.pkcs8.key
In the Update SSL Certificate screen of the CloudStack UI, paste the following:
The certificate you’ve just generated.
The private key you’ve just generated.
The desired new domain name; for example, company.com
The desired new domain name; for example, company.com
This stops all currently running console proxy VMs, then restarts them with
the new certificate and key. Users might notice a brief interruption in
console availability.
The Management Server generates URLs of the form “aaa-bbb-ccc-ddd.company.com”
after this change is made. The new console requests will be served with the
new DNS domain name, certificate, and key.
Virtual Router
The virtual router is a type of System Virtual Machine. The virtual router is
one of the most frequently used service providers in CloudStack. The end user
has no direct access to the virtual router. Users can ping the virtual router
and take actions that affect it (such as setting up port forwarding), but
users do not have SSH access into the virtual router.
Virtual routers can be restarted by administrators, but this will interrupt
public network access and other services for end users. A basic test in
debugging networking issues is to attempt to ping the virtual router from a
guest VM. Some of the characteristics of the virtual router are determined by
its associated system service offering..
Configuring the Virtual Router
You can set the following:
IP range
Supported network services
Default domain name for the network serviced by the virtual router
Gateway IP address
How often CloudStack fetches network usage statistics from CloudStack
virtual routers. If you want to collect traffic metering data from the
virtual router, set the global configuration parameter
router.stats.interval. If you are not using the virtual router to gather
network usage statistics, set it to 0.
Upgrading a Virtual Router with System Service Offerings
When CloudStack creates a virtual router, it uses default settings which are
defined in a default system service offering. See Section 8.2, “System Service
Offerings”. All the virtual routers in a single guest network use the same
system service offering. You can upgrade the capabilities of the virtual
router by creating and applying a custom system service offering.
Define your custom system service offering.
Associate the system service offering with a network offering.
Apply the network offering to the network where you want the virtual routers
to use the new system service offering.
Best Practices for Virtual Routers
Restarting a virtual router from a hypervisor console deletes all the
iptables rules. To work around this issue, stop the virtual router and
start it from the CloudStack UI.
Do not use the destroyRouter API when only one router is available in the
network, because restartNetwork API with the cleanup=false parameter can’t
recreate it later. If you want to destroy and recreate the single router
available in the network, use the restartNetwork API with the cleanup=true
parameter.
Secondary Storage VM
In addition to the hosts, CloudStack’s Secondary Storage VM mounts and writes
to secondary storage. Submissions to secondary storage go through the
Secondary Storage VM. The Secondary Storage VM can retrieve templates and ISO
images from URLs using a variety of protocols. The secondary storage VM
provides a background task that takes care of a variety of secondary storage
activities: downloading a new template to a Zone, copying templates between
Zones, and snapshot backups. The administrator can log in to the secondary
storage VM if needed.
Storage Administration
Hypervisor Host Management
Maintenance mode
Maintenance mode makes a host unavailable to have new virtual machines
allocated to it. It also starts a process by which running virtual machines
are live migrated to other available hosts within the same cluster. It should
be noted that the live migration is not universally perfect, and you may end
up with recalcitrant virtual machines which are unable to be live migrated.
This can be due to lack of hypervisor-specific tooling or other problems.
vCenter and Maintenance mode
To enter maintenance mode on a vCenter host, both vCenter and CloudStack must
be used in concert. CloudStack and vCenter have separate maintenance modes
that work closely together.
Place the host into CloudStack’s “scheduled maintenance” mode. This does
not invoke the vCenter maintenance mode, but only causes VMs to be migrated
off the host When the CloudStack maintenance mode is requested, the host
first moves into the Prepare for Maintenance state. In this state it cannot
be the target of new guest VM starts. Then all VMs will be migrated off the
server. Live migration will be used to move VMs off the host. This allows
the guests to be migrated to other hosts with no disruption to the guests.
After this migration is completed, the host will enter the Ready for
Maintenance mode.
Wait for the “Ready for Maintenance” indicator to appear in the UI.
Now use vCenter to perform whatever actions are necessary to maintain the
host. During this time, the host cannot be the target of new VM allocations.
When the maintenance tasks are complete, take the host out of maintenance
mode as follows:
First use vCenter to exit the vCenter maintenance mode. This makes the
host ready for CloudStack to reactivate it.
Then use CloudStack’s administrator UI to cancel the CloudStack
maintenance mode When the host comes back online, the VMs that were
migrated off of it may be migrated back to it manually and new VMs can
be added.
XenServer Maintenance Mode
XenServer, you can take a server offline temporarily by using the Maintenance
Mode feature in XenCenter. When you place a server into Maintenance Mode, all
running VMs are automatically migrated from it to another host in the same
pool. If the server is the pool master, a new master will also be selected for
the pool. While a server is Maintenance Mode, you cannot create or start any
VMs on it.
To place a XenServer host in Maintenace Mode
In the Resources pane, select the server, then do one of the following:
Right-click, then click Enter Maintenance Mode on the shortcut menu.
On the Server menu, click Enter Maintenance Mode.
Click Enter Maintenance Mode.
The server’s status in the Resources pane shows when all running VMs have been
successfully migrated off the server.
To take a Xenserver host out of Maintenance mode
In the Resources pane, select the server, then do one of the following:
Right-click, then click Exit Maintenance Mode on the shortcut menu.
On the Server menu, click Exit Maintenance Mode.
Click Exit Maintenance Mode.
Disabling and enabling Zones, Pods, and Clusters
You can enable or disable a zone, pod, or cluster without permanently removing
it from the cloud. This is useful for maintenance or when there are problems
that make a portion of the cloud infrastructure unreliable. No new allocations
will be made to a disabled zone, pod, or cluster until its state is returned
to Enabled. When a zone, pod, or cluster is first added to the cloud, it is
Disabled by default.
To disable and enable a zone, pod, or cluster:
Log in to the CloudStack UI as administrator
In the left navigation bar, click Infrastructure.
In Zones, click View More.
If you are disabling or enabling a zone, find the name of the zone in the
list, and click the Enable/Disable button.
If you are disabling or enabling a pod or cluster, click the name of the
zone that contains the pod or cluster.
Click the Compute tab.
In the Pods or Clusters node of the diagram, click View All.
Click the pod or cluster name in the list.
Click the Enable/Disable button.
Removing hypervisor hosts
Hosts can be removed from the cloud as needed. The procedure to remove a host
depends on the hypervisor type.
Removing XenServer and KVM Hosts
A node cannot be removed from a cluster until it has been placed in
maintenance mode. This will ensure that all of the VMs on it have been
migrated to other Hosts. To remove a Host from CloudStack:
Place the node in maintenance mode.
For KVM, stop the cloud-agent service.
Use the UI option to remove the node.
Then you may power down the Host, re-use its IP address, re-install it, etc
Removing vSphere Hosts
To remove this type of host, first place it in maintenance mode, as described
above. Then use CloudStack to remove the host. CloudStack will not direct
commands to a host that has been removed using CloudStack. However, the host
may still exist in the vCenter cluster.
Changing hypervisor host password
The password for a XenServer Node, KVM Node, or vSphere Node may be changed in
the database. Note that all Nodes in a Cluster must have the same password.
To change a hosts password:
Identify all hosts in the cluster.
Change the password on all hosts in the cluster. Now the password for the
host and the password known to CloudStack will not match. Operations on the
cluster will fail until the two passwords match.
Get the list of host IDs for the host in the cluster where you are changing
the password. You will need to access the database to determine these host
IDs. For each hostname “h” (or vSphere cluster) that you are changing the
password for, execute:
mysql> select id from cloud.host where name like '%h%';
Update the passwords for the host in the database. In this example, we
change the passwords for hosts with IDs 5, 10, and 12 to “password”.
mysql> update cloud.host set password='password' where id=5 or id=10 or id=12;
Overprovisioning and Service Offering Limits
CPU and memory (RAM) over-provisioning factors can be set for each cluster to
change the number of VMs that can run on each host in the cluster. This helps
optimize the use of resources. By increasing the over-provisioning ratio, more
resource capacity will be used. If the ratio is set to 1, no over-provisioning
is done.
The administrator can also set global default over-provisioning ratios in the
cpu.overprovisioning.factor and mem.overprovisioning.factor global
configuration variables. The default value of these variables is 1:
over-provisioning is turned off by default.
Over-provisioning ratios are dynamically substituted in CloudStack’s capacity
calculations. For example:
Capacity = 2 GB
Over-provisioning factor = 2
Capacity after over-provisioning = 4 GB
With this configuration, suppose you deploy 3 VMs of 1 GB each:
Used = 3 GB
Free = 1 GB
The administrator can specify a memory over-provisioning ratio, and can
specify both CPU and memory over-provisioning ratios on a per-cluster basis.
In any given cloud, the optimum number of VMs for each host is affected by
such things as the hypervisor, storage, and hardware configuration. These may
be different for each cluster in the same cloud. A single global
over-provisioning setting can not provide the best utilization for all the
different clusters in the cloud. It has to be set for the lowest common
denominator. The per-cluster setting provides a finer granularity for better
utilization of resources, no matter where the CloudStack placement algorithm
decides to place a VM.
The overprovisioning settings can be used along with dedicated resources
(assigning a specific cluster to an account) to effectively offer different
levels of service to different accounts. For example, an account paying for a
more expensive level of service could be assigned to a dedicated cluster with
an over-provisioning ratio of 1, and a lower-paying account to a cluster with
a ratio of 2.
When a new host is added to a cluster, CloudStack will assume the host has the
capability to perform the CPU and RAM over-provisioning which is configured
for that cluster. It is up to the administrator to be sure the host is
actually suitable for the level of over-provisioning which has been set.
Limitations on over-provisioning in KVM and XenServer
In XenServer, due to a constraint of this hypervisor, you can not use an
over-provisioning factor greater than 4.
KVM can not manage memory allocation to VMs dynamically. CloudStack sets the
minimum and maximum amount of memory that a VM can use. The hypervisor adjusts
the memory within the set limits based on the memory contention.
Requirements for Over-Provisioning
Several prerequisites are required in order for over-provisioning to function
properly. The feature is dependent on the OS type, hypervisor capabilities,
and certain scripts. It is the administrator’s responsibility to ensure that
these requirements are met.
Balloon Driver
All VMs should have a balloon driver installed in them. The hypervisor
communicates with the balloon driver to free up and make the memory available
to a VM.
XenServer
The balloon driver can be found as a part of xen pv or PVHVM drivers. The xen
pvhvm drivers are included in upstream linux kernels 2.6.36+.
VMware
The balloon driver can be found as a part of the VMware tools. All the VMs
that are deployed in a over-provisioned cluster should have the VMware tools
installed.
KVM
All VMs are required to support the virtio drivers. These drivers are
installed in all Linux kernel versions 2.6.25 and greater. The administrator
must set CONFIG_VIRTIO_BALLOON=y in the virtio configuration.
Hypervisor capabilities
The hypervisor must be capable of using the memory ballooning.
XenServer
The DMC (Dynamic Memory Control) capability of the hypervisor should be
enabled. Only XenServer Advanced and above versions have this feature.
VMware, KVM
Memory ballooning is supported by default.
Setting Over-Provisioning Rations
There are two ways the root admin can set CPU and RAM over-provisioning ratios.
First, the global configuration settings cpu.overprovisioning.factor and
mem.overprovisioning.factor will be applied when a new cluster is created.
Later, the ratios can be modified for an existing cluster.
Only VMs deployed after the change are affected by the new setting. If you
want VMs deployed before the change to adopt the new over-provisioning ratio,
you must stop and restart the VMs. When this is done, CloudStack recalculates
or scales the used and reserved capacities based on the new over-provisioning
ratios, to ensure that CloudStack is correctly tracking the amount of free
capacity.
To change the over-provisioning ratios for an existing cluster:
Log in as administrator to the CloudStack UI.
In the left navigation bar, click Infrastructure.
Under Clusters, click View All.
Select the cluster you want to work with, and click the Edit button.
Fill in your desired over-provisioning multipliers in the fields CPU
overcommit ratio and RAM overcommit ratio. The value which is intially
shown in these fields is the default value inherited from the global
configuration settings.
Service Offering Limits and Over-Provisioning
Service offering limits (e.g. 1 GHz, 1 core) are strictly enforced for core
count. For example, a guest with a service offering of one core will have only
one core available to it regardless of other activity on the Host.
Service offering limits for gigahertz are enforced only in the presence of
contention for CPU resources. For example, suppose that a guest was created
with a service offering of 1 GHz on a Host that has 2 GHz cores, and that
guest is the only guest running on the Host. The guest will have the full
2 GHz available to it. When multiple guests are attempting to use the CPU a
weighting factor is used to schedule CPU resources. The weight is based on the
clock speed in the service offering. Guests receive a CPU allocation that is
proportionate to the GHz in the service offering. For example, a guest created
from a 2 GHz service offering will receive twice the CPU allocation as a guest
created from a 1 GHz service offering. CloudStack does not perform memory
over-provisioning.


Technical Notices
Here you could find some technical notes which are relative to the design of the final interface and the idl files.
- The interface respects the recommendations of the CAPE-OPEN Methods&Tools group. Find its guidelines and conventions in the CO-CD document.
For instance, the types definition and errors handling in the ICapeUtility.idl file are the result from the Methods&Tools group work.- Don't forget the CAPE-OPEN Common Services inside the CAPE-OPEN Concepts Document.
Particularly the Parameter concept allows to include some specific items within the interface.- By reason of diverse thinks, there is no defined module within the interface and it's a shame.
- The objects belonging to the interface follow the specifications from the CORBA LifeCycleService (Specification-November 1996).
- The numerical calculation (perform() method) can't be interrupted by the client side.
- The interface doesn't support the calculation status concept (to show the state of a running or interrupted numerical calculation).
- Keep in mind that the final interface diagram is compliant with the CORBA architecture. For the Microsoft COM, it's clear that the design could be (slightly or not) different.
Somehow the current idl files are specific to CORBA.


[gecode-users] Gecode 5.0.0 released
Christian Schulte
cschulte at kth.se
Wed Oct 26 12:27:13 CEST 2016
Dear all,
We are happy to announce that Gecode 5.0.0 has been released on October 25,
2016. Here is an excerpt from the changelog:
This release adds a number of new features and fixes many bugs (some rather
serious), so it is recommended to switch as soon as possible to this
release. Some highlights are: re-added limited discrepancy search (LDS);
added sequential and parallel portfolio-based search (PBS); added support
for groups of propagators and branchers; added extensive tracing
functionality based on groups; propagators can be disabled and re-enabled;
support for arbitrary memory allocators; changed the notion of "integer
consistency level" to the more expressive concept "integer propagation
level".
Cheers
Christian
--
Christian Schulte, www.gecode.org/~schulte
Professor of Computer Science, KTH, cschulte at kth.se
Expert Researcher, SICS, cschulte at sics.se
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 4599 bytes
Desc: not available
URL: <http://www.gecode.org/pipermail/users/attachments/20161026/7d4d702b/attachment.bin>
More information about the users
mailing list


Features
- Post from the omnibox by typing "adn" <space> "msg" <enter>
- Post to ADN buttons on Twitter share intents
- View profiles from the omnibox by typing "adn" <space> "name" <down> <down> <enter>
- View #hashtag posts from the omnibox by typing "adn" <space> "hashtag" <down> <down> <down> <enter>


CAVP_DPL ~ cfL[1] + cfL[2] * PSXC + cfL[3] * QCXC + cfL[4] * MACHX + cfL[5] * AKRD
CAVP_DPR ~ cfR[1] + cfR[2] * PSXC + cfR[3] * QCXC + cfR[4] * MACHX + cfR[5] * AKRD
where the coefficients are as follows:


The jQuery Validation Plugin provides drop-in validation for your existing forms, while making all kinds of customizations to fit your application really easy.
This project is looking for help! You can donate to the ongoing pledgie campaign and help spread the word. If you’ve used the plugin, or plan to use, consider a donation - any amount will help.
You can find the plan for how to spend the money on the pledgie page.
Include jQuery and the plugin on a page. Then select a form to validate and call the validate
method.
```html
```
For more information on how to setup a rules and customizations, check the documentation.
Follow the jQuery style guide, even if existing code doesn’t. Add unit tests for any new or changed functionality. Lint and test your code using Grunt.
If you’ve wrote custom methods that you’d like to contribute to additional-methods.js, create a branch, add the method there and send a pull request for that branch.
Copyright (c) 2013 Jörn Zaefferer Licensed under the MIT license.


---
layout: base
lang: en
ref: contact & support
permalink: /contact/
title: Get in touch
description:
lead: Getting in touch with Veil is just a click away.
---
{% capture header %}
Get in touch
{% endcapture %}
{% include header.html content=header %}
{% include footer.html %}


Card Charged Succesfully!!
CHECK OUT
Shipping Address
Name:
Email:
Street 1:
Street 2:
City
State:
Alabama
Alaska
Arizona
Arkansas
California
Colorado
Connecticut
Delaware
District of Columbia
Florida
Georgia
Hawaii
Idaho
Illinois
Indiana
Iowa
Kansas
Kentucky
Louisiana
Maine
Maryland
Massachusetts
Michigan
Minnesota
Mississippi
Missouri
Montana
Nebraska
Nevada
New Hampshire
New Jersey
New Mexico
New York
North Carolina
North Dakota
Ohio
Oklahoma
Oregon
Pennsylvania
Rhode Island
South Carolina
South Dakota
Tennessee
Texas
Utah
Vermont
Virginia
Washington
West Virginia
Wisconsin
Wyoming
Zip
Card Information
Card Number:
CVV:
Expiration Date:
Postal Code:
Price:
Pay with card
Pay with a Digital Wallet
Apple Pay for Web not enabled
Masterpass not enabled


4 writes to ThrowOnRunspaceOpenError
System.Management.Automation (4)
engine\InitialSessionState.cs (2)
1361
iss.
ThrowOnRunspaceOpenError
= true;
1654
ss.
ThrowOnRunspaceOpenError
= this.ThrowOnRunspaceOpenError;
engine\Modules\ModuleCmdletBase.cs (1)
2118
iss.
ThrowOnRunspaceOpenError
= true;
engine\remoting\server\serverremotesession.cs (1)
817
rsSessionStateToUse.
ThrowOnRunspaceOpenError
= true;
13 references to ThrowOnRunspaceOpenError
System.Management.Automation (13)
engine\InitialSessionState.cs (13)
1654
ss.ThrowOnRunspaceOpenError = this.
ThrowOnRunspaceOpenError
;
2185
if (this.
ThrowOnRunspaceOpenError
)
2201
if (this.
ThrowOnRunspaceOpenError
)
2437
ThrowOnRunspaceOpenError
)
2896
if (
ThrowOnRunspaceOpenError
)
2911
if (
ThrowOnRunspaceOpenError
)
3153
if (!
ThrowOnRunspaceOpenError
)
3160
if (!
ThrowOnRunspaceOpenError
)
3214
if (
ThrowOnRunspaceOpenError
)
3637
if (this.
ThrowOnRunspaceOpenError
|| this.RefreshTypeAndFormatSetting)
3649
if (this.
ThrowOnRunspaceOpenError
)
3745
if (this.
ThrowOnRunspaceOpenError
|| this.RefreshTypeAndFormatSetting)
3759
if ((this.
ThrowOnRunspaceOpenError
|| this.RefreshTypeAndFormatSetting) && hasErrors)


Is used to add, update, or delete line items in a Cart .
More...
|
| enum class | LineItemChangeType { Add
, Remove
, Update
} |
| |
|
| void | AddOrUpdate (ProductVariant variant, long? quantity=null, Dictionary< string, string > customAttributes=null) |
| | Adds or updates a line item using a ProductVariant . More...
|
| |
| void | AddOrUpdate (Product product, Dictionary< string, string > selectedOptions, long? quantity=null, Dictionary< string, string > customAttributes=null) |
| | Adds a new line item using a Product and selected options. If an existing line item exists for the variant id, then that line item will be updated. More...
|
| |
| List< CartLineItem > | All () |
| | Returns all Line Items that have been created. More...
|
| |
| CartLineItem | Get (string variantId) |
| | Returns one Line Item based on a variant id. If no line item exists for the variant id null will be returned. More...
|
| |
| CartLineItem | Get (ProductVariant variant) |
| | Returns one Line Item based on a ProductVariant . If no line item exists for the variant, null will be returned. More...
|
| |
| CartLineItem | Get (Product product, Dictionary< string, string > selectedOptions) |
| | Returns one Line Item based on a product and selected options. If no line item exists for the matching variant, null will be returned. More...
|
| |
| bool | Delete (string variantId) |
| | Deletes one Line Item based on a variant id. If a line item was deleted, true will be returned. If no line items were deleted, false will be returned. More...
|
| |
| bool | Delete (ProductVariant variant) |
| | Deletes one Line Item based on a ProductVariant . If a line item was deleted, true will be returned. If no line items were deleted, false will be returned. More...
|
| |
| bool | Delete (Product product, Dictionary< string, string > selectedOptions) |
| | Deletes one Line Item based on a Product and selected options. If a line item was deleted, true will be returned. If no line item was deleted, false will be returned. More...
|
| |
| void | Reset () |
| | Deletes all line items More...
|
| |
|
void | UpdateLineItemsFromCheckoutLineItems (List< CheckoutLineItem > checkoutLineItems) |
| |
|
|
bool | IsSaved [get] |
| |
|
decimal | Subtotal [get] |
| |
|
|
LineItemChangeHandler | OnChange |
| |
Is used to add, update, or delete line items in a Cart
.
◆ AddOrUpdate() [1/2]
| void Shopify.Unity.SDK.CartLineItems.AddOrUpdate |
( |
Product |
product, |
|
|
Dictionary< string, string > |
selectedOptions, |
|
|
long? |
quantity = null , |
|
|
Dictionary< string, string > |
customAttributes = null |
|
) |
| |
|
inline |
Adds a new line item using a Product and selected options. If an existing line item exists for the variant id, then that line item will be updated.
- Parameters
-
| product | product to check selected options against |
| selectedOptions | a Dictionary used to define user selected options |
| quantity | the number of items you'd like to order for variantId |
| customAttributes | customAttributes can be used to define extra information for this line item |
Throws when no matching variant could be found for selected options in product
Cart cart = ShopifyBuy.Client().Cart();
Dictionary<string, string> selectedOptions = new Dictionary<string, string>() {
{"Size", "Small"},
{"Color", "Red"}
};
cart.LineItems.AddOrUpdate(product, selectedOptions, 3);
◆ AddOrUpdate() [2/2]
| void Shopify.Unity.SDK.CartLineItems.AddOrUpdate |
( |
ProductVariant |
variant, |
|
|
long? |
quantity = null , |
|
|
Dictionary< string, string > |
customAttributes = null |
|
) |
| |
|
inline |
Adds or updates a line item using a ProductVariant .
- Parameters
-
| variant | ProductVariant whose id will be used to create or update a line item |
| quantity | the number of items you'd like to order for variantId |
| customAttributes | can be used to define extra information for this line item |
Cart cart = ShopifyBuy.Client().Cart();
cart.LineItems.AddOrUpdate(variant, 3);
◆ All()
Returns all Line Items that have been created.
Cart cart = ShopifyBuy.Client().Cart();
Debug.Log("The cart has " + cart.LineItems.All().Count + " line items");
◆ Delete() [1/3]
| bool Shopify.Unity.SDK.CartLineItems.Delete |
( |
Product |
product, |
|
|
Dictionary< string, string > |
selectedOptions |
|
) |
| |
|
inline |
Deletes one Line Item based on a Product and selected options. If a line item was deleted, true
will be returned. If no line item was deleted, false
will be returned.
- Parameters
-
| product | product whose options will be used to determine which line item is deleted |
| selectedOptions | a Dictionary used to define user selected options |
Cart cart = ShopifyBuy.Client().Cart();
Dictionary<string, string> selectedOptions = new Dictionary<string, string>() {
{"Size", "Small"},
{"Color", "Red"}
};
Debug.Log("Did delete? " + cart.LineItems.Delete(product, selectedOptions));
◆ Delete() [2/3]
Deletes one Line Item based on a ProductVariant . If a line item was deleted, true
will be returned. If no line items were deleted, false
will be returned.
- Parameters
-
| variant | variant to provide the ID to delete a line item |
Cart cart = ShopifyBuy.Client().Cart();
Debug.Log("Did delete? " + cart.LineItems.Delete(variant));
◆ Delete() [3/3]
| bool Shopify.Unity.SDK.CartLineItems.Delete |
( |
string |
variantId | ) |
|
|
inline |
Deletes one Line Item based on a variant id. If a line item was deleted, true
will be returned. If no line items were deleted, false
will be returned.
- Parameters
-
| variantId | variant id used to delete a line item |
Cart cart = ShopifyBuy.Client().Cart();
Debug.Log("Did delete? " + cart.LineItems.Delete(variantId));
◆ Get() [1/3]
| CartLineItem Shopify.Unity.SDK.CartLineItems.Get |
( |
Product |
product, |
|
|
Dictionary< string, string > |
selectedOptions |
|
) |
| |
|
inline |
Returns one Line Item based on a product and selected options. If no line item exists for the matching variant, null
will be returned.
- Parameters
-
| product | product whose options will be selected |
| selectedOptions | a Dictionary used to define user selected options |
Cart cart = ShopifyBuy.Client().Cart();
Dictionary<string, string> selectedOptions = new Dictionary<string, string>() {
{"Size", "Small"},
{"Color", "Red"}
};
Debug.Log(cart.LineItems.Get(product, selectedOptions).quantity);
◆ Get() [2/3]
Returns one Line Item based on a ProductVariant . If no line item exists for the variant, null
will be returned.
- Parameters
-
| variant | variant whose variant id used to create a line item |
Cart cart = ShopifyBuy.Client().Cart();
Debug.Log(cart.LineItems.Get(variant).quantity);
◆ Get() [3/3]
| CartLineItem Shopify.Unity.SDK.CartLineItems.Get |
( |
string |
variantId | ) |
|
|
inline |
Returns one Line Item based on a variant id. If no line item exists for the variant id null
will be returned.
- Parameters
-
| variantId | variant id used to create a line item |
Cart cart = ShopifyBuy.Client().Cart();
Debug.Log(cart.LineItems.Get(variantId).quantity);
◆ Reset()
| void Shopify.Unity.SDK.CartLineItems.Reset |
( |
| ) |
|
|
inline |
The documentation for this class was generated from the following file:
- Assets/Shopify/Unity/SDK/CartLineItems.cs


dtdobject
Class DtdGroupingElement
java.lang.Object
|
+--dtdobject.DtdGroupingElement
- public class DtdGroupingElement
- extends java.lang.Object
|
Constructor Summary |
DtdGroupingElement(java.lang.String name,
int occurrence)
DtdGroupingElement()
only constructor for DtdGroupingElement. |
|
Method Summary |
java.lang.String |
dtdToText()
dtdToText()
Convert a virtual DTD specfication given by this object into a String
that can be printed in a window, file, or other such output gizmo. |
java.lang.String |
getName()
getName()
Return the name of the DtdGroupingElement. |
int |
getOccurrence()
getOccurrence()
Return the occurrence rating of the DtdGroupingElement. |
void |
setOccurrence(int occurrence)
setOccurrence()
Set the occurrence rating of the DtdGroupingElement. |
| Methods inherited from class java.lang.Object |
, clone, equals, finalize, getClass, hashCode, notify, notifyAll, registerNatives, toString, wait, wait, wait |
elementName
protected java.lang.String elementName
elementOccurrence
protected int elementOccurrence
DtdGroupingElement
public DtdGroupingElement(java.lang.String name,
int occurrence)
- DtdGroupingElement()
only constructor for DtdGroupingElement.
#parameter: name
the name of the new subgroup to be inserted.
#parameter: occurrence
MAY -> the subgroup appears 0 to many times.
MUST -> the subgroup appears at least once.
setOccurrence
public void setOccurrence(int occurrence)
- setOccurrence()
Set the occurrence rating of the DtdGroupingElement.
#parameter: occurrence
MAY -> the subgroup appears 0 to many times.
MUST -> the subgroup appears at least once.
getName
public java.lang.String getName()
- getName()
Return the name of the DtdGroupingElement.
#returns: String
getOccurrence
public int getOccurrence()
- getOccurrence()
Return the occurrence rating of the DtdGroupingElement.
#returns: int
dtdToText
public java.lang.String dtdToText()
- dtdToText()
Convert a virtual DTD specfication given by this object into a String
that can be printed in a window, file, or other such output gizmo.
#returns: String


The Chaupal JP2P Architecture aims to provide a generic container
structure for JAVA based peer to peer (P2P) applications, and tools to
make the development of P2P applications a lot easier. The architecture
contains a number of bundles, divided over three (GitHub) projects, that
each add a layer of functionality to Java P2P. The bundles that make
Chaupal are depicted below
At the bottom we see the JXSE 2.8x library, formerly known as JXTA
TM.
The code of this library is divided over a number of bundles that make
JXSE-LIB.Although these are OSGI bundles, they have no dependencies with
OSGI, so they can be deployed as POJO's., In other words, if you put the
bundles in your classpath, you should be able to deploy a JXTA
TM
application, as if you were using the regular JAR...
..but with one big difference! If you rermove, say,
net.jxse.jetty-
you will
not end up with runtime exceptions. Instead,
you will not be able to use the JXTA
tm HTTP service provided
by Jetty. This is a big advantage if you only need TCP endpoint services
for your applications. Another example are the two databases - derby and
H2- which are shipped with the standard JXTA
TM jar; you can
select one or the other for your application, but both jars need to be
available on the classpath. The modular approach provided by OSGI
allows, you to select the jar (bundle) you need, and skip the other.This
way you application can really benefit from light-weight components
without any unnecessary clutter!
One bundle uses the others: net.jxse.practical.jxta, which implements
the code of the corresponding
book.
With respect to the original code, the 2.8x version of JXTA
TM
makes a functional distinction between:
- net.jxta: core functionality
- net.jxta.platform: configuration code (i.e. NetworkManager and
NetworkConfigurator)
- Third party additions (Jetty, Netty, Derby, etc.)
The level of J
P2P Core implements the JP2P container. This is
also a bundle which can be used as a POJO. The container is not
dependent on JXTA
TM either. This is handled by the
net.jp2p.jxta bundle. Only at the level of the four bundles that
complete the JP2P core package, the specific OSGI dependency is made,
all of which provide specific services for the JP2P
container:net,chaupal: general services:
- net.jp2p.jxse.compatibility: a bridge that allows existing JXTATM
code to run on the JP2P container
- net.jp2p.chaupal.jxta: JXTATM services
- net.jp2p.chaupal.jxta.platofrm: JXTATM platform
services.
These four bundles use the OSGI declarative service mechanism to
register their services to the JP2P container. If one of these bundles
is not available or not started, the corresponding JP2P services are not
registered, and cannot be used by the JP2P container.
At the top level, there are three bundles that are specific to Eclipse
and Equinox, and these provide tools for the Eclipse RCP, such as
templates, perspectives and, in the particular case of
net.jp2p.chaupal.equinox, jp2p services that has dependencies with
equinox code. This bundle will therefore not work on Apache Felix or
Knopflerfish without additional handwork.


L2Advanced
Write your current Security Password !
Current Password:
Write a new Security Password !
Requests :
Uppecase
,
Number
and a
Symbol
.
Example :
#High5
(
#
- Symbol
H
- Uppercase and
5
- Number)
New Password:
L2Advanced


soil carbon conservation species biodiversity threatened sites variables {border-style px;} #ffffff;} plots surrogate surrogates planning PEBANPA areas random abiotic data plant used SAI based network important number using values environmental use Conservation land px; scores {font-family Soil Southern font-size forest importance optimal Biology Patagonia Peri [], assess double; factors high protected relatively represented variable (Fig. Figure approach border-color border-width extinction grid.. identifying inclusion information models networks permanent plot plots. rich soils solid; stocks value {font-style {font-weight (). ./cobi. Albuquerque Beier Commons Creative Global Nature area bold courier; developed developing ecosystems elaborated elaboration em; global identify model network. organic potential predict presence priority pt;} significantly site spatial species, species. subset threats variables, water zero


Hello, Welcome to my page !
Work Experience
Worked as a
Pharmacist
in State Bank of India,Patna(India)
Worked as Hospital Pharmacist in Paras Hospital,Patna(India)
Recently, was working with Sears as a Cashier


Home
To keep this website up please contact me cattails AT dokos.net
We at Cat Tails partner with local volunteers and fosters in
order to provide a loving and caring environment for cats while we look for their furever home.
Since we keep cats in homes, and not cages, we are able to see their true personality and help
you find the cat that fits you and your life the best. We are "changing the world one cat at a time."
As another part of our mission to help provide cats with a safe and healthy life, we focus on four values:
- Commitment
- Compassion
- Respect
- Responsibility


MANIFESTO A film review by Thomas E. Billings Copyright 1989 Thomas E. Billings
Synopsis: Set in an undisclosed country in Central Europe in 1920, the film follows the adventures of a beautiful, but oversexed, young woman. Together with her bumbling friends, she is involved in a plot to kill the King. A sophisticated and very sly comedy, which pokes fun at socialism and revolutionaries. Very good, but I suspect that much of the humor will be missed by most viewers.
Yugoslavia (in English, not dubbed!), color, 1988, 94 minutes. Director/Writer: Dusan Makavejev
This is the latest work by Dusan Makavejev, who is best known in the U.S. for a previous film, THE COCA-COLA KID. The current film is a lighthearted farce, a kind of parody of socialism and revolutionaries. The plot is rather thin at times, but it is funny enough that boredom is unlikely.
The story follows Svetlana, a very beautiful young woman who returns, in 1920, to the small town in Central Europe she was born and raised in. Based on her behavior, one gets the impression that she is afflicted with nymphomania, for she proceeds immediately to rekindle old passions and start new ones.
Svetlana's motivations for returning home are soon made clear. The King is soon to visit her hometown, and Svetlana is involved in a group of clumsy, inept and incompetent revolutionaries who are plotting to murder the King! What makes things more interesting is that "the King" who visits is actually a fake; the real King is already in the town, working with the police (also clumsy and incompetent) to try to uncover the revolutionaries. Even more interesting, the real King is oversexed and has a foot fetish!
The result of this ridiculous situation is a real comedy of errors, which are made in great abundance by all the characters here. Much of the humor is a pointed satire of socialism, as the police are ridiculed often. The police literally hide in practically every closet in this film! Another example, more subtle, is the scene where a political prisoner is put in an insane asylum by the police. There he is locked in a large circular wheel. The prisoner loves to run in place in the wheel, expending great effort, and shouting pro- socialist slogans all the time. The irony of this scene is very nice; the man in the wheel works very hard, yet produces nothing but political rhetoric. Can you think of a better parody of socialism?
Although I enjoyed the film very much, particularly its nice satire of socialism and revolutionaries, much of the humor is rather subtle. Thus I wonder how much of the humor will be effectively lost on a general audience. As to technical aspects, the photography (much of which was shot on location) is beautiful, and the acting is really very good.
Thus I make a conditional recommendation for the movie, i.e., worth seeing if you appreciate subtle satire, much of it political. Also, in case anyone is curious as to why a Yugoslavian film would be made in English, the film is a Cannon/Golan-Globus Production, made specifically for the international market.
Distribution. Now in its initial U.S. run, showing at a limited number of theaters (probably the art houses).
Reviewer: Thomas E. Billings, Department of Statistics University of California, Berkeley
.
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


%
load 'templates/icons.rb'
icons = getGroupedIcons()
image_width = 888
version = '0.7.3'
icon_count = icons.length
spacing = 10
total_spacing = spacing * icon_count
icon_size = (image_width - total_spacing) / icon_count
%>
Techno-Font <%= version %>
Usage
To use the font, include assets/techno-font.css as well as the fonts in your project.
Or just link to it using RawGit (served via MaxCDN’s network):
Use the CSS classes listed below like this:
<% icons.each do |name, value| %>
tf-<%= name %>
<% end %>


PulseAudio is a sound server, sitting above device drivers such as ALSA or OSS. It offers more capablilities than device drivers. PulseAudio is designed for consumer audio, to make it easy to use sound on desktops, laptops and mobile devices. Multiple sources of sound can all play to the PulseAudio server and it will mix them together and play them. Low latency is not a design goal, so it is unsuitable for professional audio.
If you have a current Linux system, PulseAudio is probably running. Test by running this from the command line:
ps agx | grep pulse
If you see a line like "/usr/bin/pulseaudio --start --log-target=syslog" then it is running already.
If it isn't running and you have it installed, then start it by
pulseaudio --start
Stopping PulseAudio isn't so easy - Carla Schroder shows how . The basic problem is that PulseAudio is set to respawn itself after it is killed. You have to turn that off by editing /etc/pulse/client.conf, changing autospawn = yes to autospawn = no, and setting daemon-binary to /bin/true. Then you can kill the processs, remove it from startup files, etc.
If you want to run another sound system (such as Jack) for a short
while, you may just want to pause PulseAudio. You do this by using
pasuspender
. This takes a command (after "--") and
will pause access by the PulseAudio server to the audio devices until
the subcommand has finished.
For example,
pasuspender -- jackd
will run the Jack server, with PulseAudio getting out of the way until it has finished.
This shows you information about the PulseAudio server, its devices and clients.
The following three screen dumps show the type of information it gives.
pavumeter
is a simple meter for showing input or output levels
of the default devices. When run by pavumeter
it shows the
playback device as in
while if it is run by pavumeter --record
it shows the record device
as in
pavucontrol
allows you to control the input and ouput volumes of the
different connected audio devices:
With these tabs, pavucontrol
is a device-level mixer,
able to control the overall volume to individual devices.
One of the special advantages of PulseAudio is that it can perform
application-level mixing. If two audio sources write to the same
PulseAudio device, the audio will be mixed to the output device.
pavucontrol
can show the multiple applications using
the Playback tab, showing all applications or all streams
currently being mixed. Each stream can have its channel volumes
individually controlled.
For example, Karaoke on the cheap can be done by setting the straight-through module for the microphone to speaker by
pactl load-module module-loopback latency_msec=1
while the Karoake file is played by a Karaoke player
such as kmid
through timidity
e.g.
kmid nightsin.kar
While these two are running, relative volumes can be controlled
by use of pavucontrol
:
The gnome-control-center sound
allows full view and control of
the attached sound devices, including selection of the default input and
output devices. It looks like
These are command line tools to record and playback sound files. They are all symbolic links to the same code, just differently named links. The default format is PCM s16. There are many options, but they don't always do quite what you want them to. For example, to play from the default record device to the default playback device with minimum latency,
pacat -r --latency-msec=1 | pacat -p --latency-msec=1
This actually has a latency of about 50 msec.
These two commands do basically the same thing. pacmd
is
the interactive version with more options.
For example pacmd
with the command
list-sinks
includes
name: <alsa_output.pci-0000_00_1b.0.analog-stereo>
driver: <module-alsa-card.c>
flags: HARDWARE HW_MUTE_CTRL HW_VOLUME_CTRL DECIBEL_VOLUME LATENCY FLAT_VOLUME DYNAMIC_LATENCY
state: SUSPENDED
suspend cause: IDLE
priority: 9959
volume: 0: 93% 1: 93%
0: -1.88 dB 1: -1.88 dB
balance 0.00
base volume: 100%
0.00 dB
volume steps: 65537
muted: no
current latency: 0.00 ms
max request: 0 KiB
max rewind: 0 KiB
monitor source: 1
sample spec: s16le 2ch 44100Hz
channel map: front-left,front-right
Stereo
used by: 0
linked by: 0
configured latency: 0.00 ms; range is 16.00 .. 2000.00 ms
card: 1 <alsa_card.pci-0000_00_1b.0>
module: 5
properties:
alsa.resolution_bits = "16"
device.api = "alsa"
device.class = "sound"
alsa.class = "generic"
alsa.subclass = "generic-mix"
alsa.name = "STAC92xx Analog"
alsa.id = "STAC92xx Analog"
alsa.subdevice = "0"
alsa.subdevice_name = "subdevice #0"
alsa.device = "0"
alsa.card = "0"
alsa.card_name = "HDA Intel PCH"
alsa.long_card_name = "HDA Intel PCH at 0xe6e60000 irq 47"
alsa.driver_name = "snd_hda_intel"
device.bus_path = "pci-0000:00:1b.0"
sysfs.path = "/devices/pci0000:00/0000:00:1b.0/sound/card0"
device.bus = "pci"
device.vendor.id = "8086"
device.vendor.name = "Intel Corporation"
device.product.id = "1c20"
device.product.name = "6 Series/C200 Series Chipset Family High Definition Audio Controller"
device.form_factor = "internal"
device.string = "front:0"
device.buffering.buffer_size = "352800"
device.buffering.fragment_size = "176400"
device.access_mode = "mmap+timer"
device.profile.name = "analog-stereo"
device.profile.description = "Analog Stereo"
device.description = "Internal Audio Analog Stereo"
alsa.mixer_name = "IDT 92HD90BXX"
alsa.components = "HDA:111d76e7,10280494,00100102"
module-udev-detect.discovered = "1"
device.icon_name = "audio-card-pci"
ports:
analog-output: Analog Output (priority 9900)
analog-output-headphones: Analog Headphones (priority 9000)
active port: <analog-output>
PulseAudio uses its own naming conventions. The names of source devices (such as microphones) can be found using code from the PulseAudio FAQ :
pactl list | grep -A2 'Source #' | grep 'Name: .*\.monitor$' | cut -d" " -f2
On my system this produces
alsa_output.pci-0000_01_00.1.hdmi-stereo.monitor
alsa_output.pci-0000_00_1b.0.analog-stereo.monitor
alsa_input.pci-0000_00_1b.0.analog-stereo
Similarly the output devices are found by
pactl list | grep -A2 'Sink #' | grep 'Name: .*\.monitor$' | cut -d" " -f2
to give
alsa_output.pci-0000_01_00.1.hdmi-stereo
alsa_output.pci-0000_00_1b.0.analog-stereo
Using pactl
you can load the module module-loopback
by
pactl load-module module-loopback latency_msec=1
When loaded, sound is internally routed from the input device to the output device. The latency is effectively zero.
If you load this module into, say. your laptop, be careful about unplugging speakers, microphones, etc. The internal speaker and microphone are close enough to set up a feedback loop. Unload module number N by
pactl unload-module N
(if you have forgotten the module number, just running pactl
will list all modules so you can identify the loopback module.).
Output from pacmd
shows PulseAudio uses ALSA.
The relationship is deeper: the default ALSA device is "hw:0"
but PulseAudio overrides that. In /etc/asound.conf
is a hook to load /etc/alsa/pulse-default.conf
and this contains
pcm.!default {
type pulse
hint {
description "Default"
}
}
which replaces the default device with a PulseAudio module.
Opening the default ALSA device will actually call into PulseAudio which will then call back into ALSA with the devices it chooses.
The source for Pulse Audio and its documentation is PulseAudio 2.0 There are two ways of programming with PulseAudio: the "simple API" and the "asynchronous API". Both are described below.
Pulse has a "simple" API and a far more complex asynchronous API. The simple API may be good enough for your needs.
The simple API has a small set of functions
pa_simple * pa_simple_new (const char *server, const char *name, pa_stream_direction_t dir, const char *dev, const char *stream_name, const pa_sample_spec *ss, const pa_channel_map *map, const pa_buffer_attr *attr, int *error)
Create a new connection to the server.
void pa_simple_free (pa_simple *s)
Close and free the connection to the server.
int pa_simple_write (pa_simple *s, const void *data, size_t bytes, int *error)
Write some data to the server.
int pa_simple_drain (pa_simple *s, int *error)
Wait until all data already written is played by the daemon.
int pa_simple_read (pa_simple *s, void *data, size_t bytes, int *error)
Read some data from the server.
pa_usec_t pa_simple_get_latency (pa_simple *s, int *error)
Return the playback latency.
int pa_simple_flush (pa_simple *s, int *error)
Flush the playback buffer.
A program to play from a file to the default output device is from the PulseAudio site. The basic structure is
The program is
pacat-simple.c
.
Rather weirdly, it does a dup2
to map the open file descriptor
onto stdin
and then reads from stdin
. This isn't
necessary - what not just read from the original file descriptor?
A program to record to a file from the default input device is from the Pulse Audio site parec-simple.c The basic structure is
Note that you need to tell PulseAudio the format to write the data, using a pa_sample_spec. Two channel, 44100hz and PCM 16 bit little-endian is chosen.
The output from this is a PCM s16 file. You can convert it to another format using Sox (e.g. sox -c 2 -r 44100 tmp.s16 tmp.wav), or import it as raw data into Audacity and play it directly.
How good are these for real-time audio? The first program can show the latency (turn the "#if 0" to "#if 1"). This code can also be copied into the second one. The results are not good:
You can combine the two programs to copy from the microphone to the speaker using a record and a playback stream. The program is pa-mic-2-speaker-simple.c :
Try running this and you will discover that the the latency is noticeable and unsatisfactory.
The simple API is ... simple. By contrast, the asynchronous API is large and complex. There are also very few examples of using this API.
Nearly all interaction with this API is asynchronous. A call is made to the PulseAudio server and when the response is ready, a library invokes a callback function that you will have passed to it when making the library call. This avoids the need for user code to either block or make polling calls.
The essential structure is
Steps (1) - (7) will be common to most applications.
The context state callback wil be called in response to changes
in the server. These are state changes such as
PA_CONTEXT_CONNECTIN
, PA_CONTEXT_SETTING_NAME
and so on. The change of relevance to most applications will be
PA_CONTEXT_READY
. This signifies that the application
can make requests of the server in its steady state.
In step (8) the application will set its own behaviour. This is done by setting up further callback functions for various operations, such as listing devices or playing audio.
The function pa_context_get_sink_info_list
will set up a callback function to list source devices by
pa_context_get_sink_info_list(c, sinklist_cb, NULL)
where c
is the context,
sinklist_cb
is the application's callback
and NULL
is user data passed to the callback.
The callback is called as
void sinklist_cb(pa_context *c, const pa_sink_info *i, int eol, void *userdata)
The parameter eol
can take three values: negative means a failure
of some kind; zero means a valid entry for
pa_sink_info
; positive means that there are no more
valid entries in the list.
The structure pa_sink_info
is defined as
struct {
const char * name;
uint32_t index;
const char * description;
pa_sample_spec sample_spec;
pa_channel_map channel_map;
uint32_t owner_module;
pa_cvolume volume;
int mute;
uint32_t monitor_source;
const char * monitor_source_name;
pa_usec_t latency;
const char * driver;
pa_sink_flags_t flags;
pa_proplist * proplist;
pa_usec_t configured_latency;
pa_volume_t base_volume;
pa_sink_state_t state;
uint32_t n_volume_steps;
uint32_t card;
uint32_t n_ports;
pa_sink_port_info ** ports;
pa_sink_port_info * active_port;
uint8_t n_formats;
pa_format_info ** formats;
} pa_sink_info
Further information about this structure is maintained in the Doxygen entry pa_sink_info Struct Reference
For information, the major fields are the name
and the
description
. The index
is an opaque index into
some data structure and is used in many PulseAudio functions.
The proplist
is a map of general information that may contain interesting information.
This can be retrieved by iterating through the map.
There is a similar callback and data structures for input devices.
A program to list input and output devices current when the application connects to the server is palist_devices.c:
On my laptop this gives (elided)
Source: name alsa_output.pci-0000_01_00.1.hdmi-stereo.monitor, description Monitor of HDMI Audio stub Digital Stereo (HDMI)
Properties are:
key: device.description, value: Monitor of HDMI Audio stub Digital Stereo (HDMI)
key: device.class, value: monitor
key: alsa.card, value: 1
key: alsa.card_name, value: HDA NVidia
key: alsa.long_card_name, value: HDA NVidia at 0xe5080000 irq 17
key: alsa.driver_name, value: snd_hda_intel
key: device.bus_path, value: pci-0000:01:00.1
key: sysfs.path, value: /devices/pci0000:00/0000:00:01.0/0000:01:00.1/sound/card1
key: device.bus, value: pci
key: device.vendor.id, value: 10de
key: device.vendor.name, value: nVidia Corporation
key: device.product.id, value: 0e08
key: device.product.name, value: HDMI Audio stub
key: device.string, value: 1
key: module-udev-detect.discovered, value: 1
key: device.icon_name, value: audio-card-pci
Source: name alsa_output.pci-0000_00_1b.0.analog-stereo.monitor, description Monitor of Internal Audio Analog Stereo
Properties are:
...
Source: name alsa_input.pci-0000_00_1b.0.analog-stereo, description Internal Audio Analog Stereo
Properties are:
...
Source: name alsa_output.usb-Creative_Technology_Ltd_SB_X-Fi_Surround_5.1_Pro_000003d0-00-Pro.analog-stereo.monitor, description Monitor of SB X-Fi Surround 5.1 Pro Analog Stereo
Properties are:
...
Source: name alsa_input.usb-Creative_Technology_Ltd_SB_X-Fi_Surround_5.1_Pro_000003d0-00-Pro.analog-stereo, description SB X-Fi Surround 5.1 Pro Analog Stereo
Properties are:
...
**No more sources
Sink: name alsa_output.pci-0000_01_00.1.hdmi-stereo, description HDMI Audio stub Digital Stereo (HDMI)
Properties are:
key: alsa.resolution_bits, value: 16
key: device.api, value: alsa
key: device.class, value: sound
key: alsa.class, value: generic
key: alsa.subclass, value: generic-mix
key: alsa.name, value: HDMI 0
key: alsa.id, value: HDMI 0
key: alsa.subdevice, value: 0
key: alsa.subdevice_name, value: subdevice #0
key: alsa.device, value: 3
key: alsa.card, value: 1
key: alsa.card_name, value: HDA NVidia
key: alsa.long_card_name, value: HDA NVidia at 0xe5080000 irq 17
key: alsa.driver_name, value: snd_hda_intel
key: device.bus_path, value: pci-0000:01:00.1
key: sysfs.path, value: /devices/pci0000:00/0000:00:01.0/0000:01:00.1/sound/card1
key: device.bus, value: pci
key: device.vendor.id, value: 10de
key: device.vendor.name, value: nVidia Corporation
key: device.product.id, value: 0e08
key: device.product.name, value: HDMI Audio stub
key: device.string, value: hdmi:1
key: device.buffering.buffer_size, value: 352768
key: device.buffering.fragment_size, value: 176384
key: device.access_mode, value: mmap+timer
key: device.profile.name, value: hdmi-stereo
key: device.profile.description, value: Digital Stereo (HDMI)
key: device.description, value: HDMI Audio stub Digital Stereo (HDMI)
key: alsa.mixer_name, value: Nvidia GPU 1c HDMI/DP
key: alsa.components, value: HDA:10de001c,10281494,00100100
key: module-udev-detect.discovered, value: 1
key: device.icon_name, value: audio-card-pci
Sink: name alsa_output.pci-0000_00_1b.0.analog-stereo, description Internal Audio Analog Stereo
Properties are:
...
Sink: name alsa_output.usb-Creative_Technology_Ltd_SB_X-Fi_Surround_5.1_Pro_000003d0-00-Pro.analog-stereo, description SB X-Fi Surround 5.1 Pro Analog Stereo
Properties are:
...
**No more sinks
An alternative program with the same effect is PulseAudio: An Async Example To Get Device Lists by Igor Brezac and Eric Connell. It doesn't follow quite as complex a route as the above, as it only queries the server for its devices. However, it uses its own state machine to track where in the callback process it is!
The last program listed the source and sink devices registered with PulseAudio at the time a connection to the server was established. However, when a new device is connected or an existing device is disconnected, PulseAudio registers a changes in the context and this can also be monitored by callbacks.
The key to doing this is to subscribe to context changes by
pa_context_subscribe
. This takes a context, a mask of
subscription events and user data. Possible values of the mask are
described at
Subscription event mask
and include PA_SUBSCRIPTION_MASK_SINK
for changes in sinks
and PA_SUBSCRIPTION_MASK_SINK_INPUT
for sink input events.
Setting the callback function to monitor these changes
is a bit odd.
The function pa_context_subscribe
takes a callback function
of type pa_context_success_cb
but this doesn't contain
information about what caused the callback.
Instead, it is better to first call
pa_context_set_subscribe_callback
which takes a
callback function of type pa_context_subscribe_cb_t
which does get passed such information and then use
NULL
for the callback inpa_context_subscribe
!
Within a pa_context_subscribe_cb_t
subscription callback, the cause of the callback can be
examined and appropriate code called. If a new subscription to a sink
is found, then information about the sink can be found by
pa_context_get_sink_info_by_index
which takes
another callback! after chasing through all these callbacks, you can
eventually get information about new devices.
Note that the callback function used by
pa_context_get_sink_info_list
and the callback
function used by pa_context_get_sink_info_by_index
are the same - the callback is called once per sink device
regardless of whether it is a singleton or one of a list
of devices.
A program to list devices on connection and also to list changes as devices are connected or disconnected is palist_devices_ongoing.c:
If you download the source for PulseAudio
from
FreeDesktop.org
you will find a program pacat.c
in the utils
directory. This program uses some of the "private" API and will not
compile using the "public" libraries. It also has
all the bells and whistles that you would expect from a production program.
I've taken
this and stripped out the complexities so that you can find your
way into this API.
The file is
parec.c:
Recording an input stream is done within a stream read callback by the
call pa_stream_peek
.
Similarly, playing an output stream is done by a stream write callback
by the call pa_stream_write
.
In the following program the callback is set within the PA_CONTEXT_READY branch of the context state change callback. The stream write callback is passed the number of bytes the consuming stream is prepared to receive, so read that number of bytes from the file and write them to the stream.
Care has to be taken at the end of file. There may be unplayed material in
PulseAudio's output buffers. This needs to be drained before the program
can exit. This is done by the function pa_stream_drain
.
On end of file, first set the stream write callback to null so that the
output stream doesn't keep calling for more input, and then drain the stream.
A stream drain complete callback will be called on completion of this, so the
program can then exit (or do something else).
In this program we include many more callbacks than in earlier ones, to show the range of features that can be monitored.
The program is pacat2.c:
With the latency set to the default, the number of bytes that can be written on each callback is 65470 bytes. This gives a minimum latency of 65470/44100 secs, or about 1500 msecs. With the latency and process time both set to 1msec, the buffer size is about 1440 bytes, for a latency of 32 msecs.
Writing a file to an output stream is simple:
read from a file into a buffer, and keep emptying the buffer by
writing to the stream. Reading from a file is straightforward:
use the standard Unix read
function. You request a read of a
number of bytes, and the read
function returns the number of bytes
actually read.
This was discussed in the last section.
The program in the PulseAudio distribution uses a more complex system. It uses I/O-ready callbacks to pass some handling to an I/O callback. This makes use of two functions:
pa_stream_writable_size
tells how many bytes can be
written to the stream
pa_stream_write
writes a number of bytes to a stream
The logic becomes: fill a buffer by reading from the file, and at the same time write as many bytes as possible from the buffer to the stream, upto the limit of the buffer size or however many bytes the stream can take, whichever is smaller.
In PulseAudio this is done asynchronously, using callback functions. The two relevant functions are
The function pa_stream_set_write_callback()
registers a
callback that will be called whenever the stream is ready to be
written to. Registering the callback looks like
pa_stream_set_write_callback(stream, stream_write_callback, NULL)
The callback is passed the stream to write to (s) and the number of bytes that can be written (length):
void stream_write_callback(pa_stream *s, size_t length, void *userdata)
A callback to read from files is registered by one of the functions
kept in the mainloop_api
table. The registering function
is io_new
and is passed a Unix file descriptor for the file
and the callback function. Reigstering the callback looks like
mainloop_api->io_new(mainloop_api,
fdin,
PA_IO_EVENT_INPUT,
stdin_callback, NULL))
The callback is passed the file descriptor (fd) to read from:
void stdin_callback(pa_mainloop_api *mainloop_api, pa_io_event *stdio_event,
int fd, pa_io_event_flags_t f, void *userdata)
(Note: the PulseAudio code does a dup2
from the source file's
descriptor to STDIN_FILENO
- which matches the name of the
function. I can't see the point of that, and their code uses fd
anyway.)
When should these callbacks be registered? The stream write callback can
be registered at any time after the stream has been created which is done by
pa_stream_new
. For the stdin callback, I could only get it
to work properly by registering it once the stream was ready i.e.
in the PA_STREAM_READY
branch of the stream state callback
function.
So after all that, what is the logic of the program?
The program to play from a file presently looks like pacat.c:
Managing latency is described at Software/PulseAudio/Documentation/Developer/Clients/LatencyControl . In brief:
In your code you then have to do the following when calling pa_stream_connect_playback() resp. pa_stream_connect_record():
- Pass PA_STREAM_ADJUST_LATENCY in the flags parameter. Only if this flag is set PA will reconfigure the low-level device's buffer size and adjust it to the latency you specify.
- Pass a pa_buffer_attr struct in the buffer_attr parameter. In the fields of this struct make sure to initialize every single field to (uint32_t) -1, with the exception of tlength (for playback) resp. fragsize (for recording). Initialize those to the latency you want to achieve. Use pa_usec_to_bytes(&ss, ...) to convert the latency from a time unit to bytes.
The extra code is:
// Set properties of the record buffer
pa_zero(buffer_attr);
buffer_attr.maxlength = (uint32_t) -1;
buffer_attr.prebuf = (uint32_t) -1;
if (latency_msec > 0) {
buffer_attr.fragsize = buffer_attr.tlength = pa_usec_to_bytes(latency_msec * PA_USEC_PER_MSEC, &sample_spec);
flags |= PA_STREAM_ADJUST_LATENCY;
} else if (latency > 0) {
buffer_attr.fragsize = buffer_attr.tlength = (uint32_t) latency;
flags |= PA_STREAM_ADJUST_LATENCY;
} else
buffer_attr.fragsize = buffer_attr.tlength = (uint32_t) -1;
if (process_time_msec > 0) {
buffer_attr.minreq = pa_usec_to_bytes(process_time_msec * PA_USEC_PER_MSEC, &sample_spec);
} else if (process_time > 0)
buffer_attr.minreq = (uint32_t) process_time;
else
buffer_attr.minreq = (uint32_t) -1;
PulseAudio also has mechanisms to estimate the latency of the devices. It uses information from timing events. A timer event callback has to be declared, as in
pa_context_rttime_new(context, pa_rtclock_now() + TIME_EVENT_USEC, time_event_callback, NULL))
The timer event callback is a "single shot" calback. It installs a stream update timer callback and sets up another timer callback:
void time_event_callback(pa_mainloop_api *m,
pa_time_event *e, const struct timeval *t,
void *userdata) {
if (stream && pa_stream_get_state(stream) == PA_STREAM_READY) {
pa_operation *o;
if (!(o = pa_stream_update_timing_info(stream, stream_update_timing_callback, NULL)))
1; //pa_log(_("pa_stream_update_timing_info() failed: %s"), pa_strerror(pa_context_errno(context)));
else
pa_operation_unref(o);
}
pa_context_rttime_restart(context, e, pa_rtclock_now() + TIME_EVENT_USEC);
The stream update timer callback can then estimate the latency:
void stream_update_timing_callback(pa_stream *s, int success, void *userdata) {
pa_usec_t l, usec;
int negative = 0;
// pa_assert(s);
fprintf(stderr, "Update timing\n");
if (!success ||
pa_stream_get_time(s, &usec) < 0 ||
pa_stream_get_latency(s, &l, &negative) < 0) {
fprintf(stderr, "Failed to get latency\n");
return;
}
fprintf(stderr, _("Time: %0.3f sec; Latency: %0.0f usec."),
(float) usec / 1000000,
(float) l * (negative?-1.0f:1.0f));
fprintf(stderr, " \r");
}
With latency left to PulseAudio by setting fragsize and tlength to -1, I got:
Time: 0.850 sec; Latency: 850365 usec.
Time: 0.900 sec; Latency: 900446 usec.
Time: 0.951 sec; Latency: 950548 usec.
Time: 1.001 sec; Latency: 1000940 usec.
Time: 1.051 sec; Latency: 50801 usec.
Time: 1.101 sec; Latency: 100934 usec.
Time: 1.151 sec; Latency: 151007 usec.
Time: 1.201 sec; Latency: 201019 usec.
Time: 1.251 sec; Latency: 251150 usec.
Time: 1.301 sec; Latency: 301160 usec.
Time: 1.351 sec; Latency: 351218 usec.
Time: 1.401 sec; Latency: 401329 usec.
Time: 1.451 sec; Latency: 451400 usec.
Time: 1.501 sec; Latency: 501465 usec.
Time: 1.551 sec; Latency: 551587 usec.
Time: 1.602 sec; Latency: 601594 usec.
With them set to 1 msec, I got:
Time: 1.599 sec; Latency: 939 usec.
Time: 1.649 sec; Latency: 1105 usec.
Time: 1.699 sec; Latency: -158 usec.
Time: 1.750 sec; Latency: 1020 usec.
Time: 1.800 sec; Latency: 397 usec.
Time: 1.850 sec; Latency: -52 usec.
Time: 1.900 sec; Latency: 1827 usec.
Time: 1.950 sec; Latency: 529 usec.
Time: 2.000 sec; Latency: -90 usec.
Time: 2.050 sec; Latency: 997 usec.
Time: 2.100 sec; Latency: 436 usec.
Time: 2.150 sec; Latency: 866 usec.
Time: 2.200 sec; Latency: 406 usec.
Time: 2.251 sec; Latency: 1461 usec.
Time: 2.301 sec; Latency: 107 usec.
Time: 2.351 sec; Latency: 1257 usec.
The program to do all this is parec-latency.c:
Combining what we have so far, we get pa-mic-2-speaker.c:
When the latency is set to 1 msec for everything, the actual latency is about 16-28 msec. I couldn't detect it.
Each device can have its input or output volume controlled by
PulseAudio. The principal calls for sinks are
pa_context_set_sink_volume_by_name
and
pa_context_set_sink_volume_by_index
with similar
calls for sources.
These calls make use of a structure pa_cvolume
.
This stucture can be manipulated using calls such as
pa_cvolume_init
pa_cvolume_set
pa_cvolume_mute
In the following program we set the volume on a particular device by reading integer values from stdin and using these to set the value. Such a loop should probably best take place in a separate thread to the PulseAudio framework. Rather than introducing application threading here, we make use of an alternative set of PulseAudio calls which set up a separate thread for the PulseAudio main loop. These calls are
pa_threaded_mainloop
instead of
pa_mainloop
pa_threaded_mainloop_get_api
instead of
pa_mainloop_get_api
pa_threaded_mainloop_start
instead of
pa_mainloop_start
The threaded calls allow us to start PulseAudio in its own thread, and leave the current thread for reading volume values. This gives the relatively simple program pavolume.c:
PulseAudio is a server that talks to devices at the bottom layer and to clients at the top layer. The clients are producers and consumers of audio. One of the roles of PulseAudio is to mix signals from different source clients to shared output devices. In order to do this, PulseAudio keeps track of registrations by clients, and can make these available to other clients by suitbale callbacks.
The program palist_clients.c is very similar to the program
palist_devices.c. The principal difference is that when the
context changes state to PA_CONTEXT_READY
the application subscribes to PA_SUBSCRIPTION_MASK_CLIENT
instead of (PA_SUBSCRIPTION_MASK_SINK|PA_SUBSCRIPTION_MASK_SOURCE)
and the subscription callback asks for pa_context_get_client_info
instead of pa_context_get_source_info
.
The program palist_clients.c is
The output on my system is (elided)
Found a new client index 0 name ConsoleKit Session /org/freedesktop/ConsoleKit/Session2 eol 0
Properties are:
key application.name, value ConsoleKit Session /org/freedesktop/ConsoleKit/Session2
key console-kit.session, value /org/freedesktop/ConsoleKit/Session2
Found a new client index 4 name XSMP Session on gnome-session as 1057eba7239ba1ec3d136359809598590100000018790044 eol 0
Properties are:
key application.name, value XSMP Session on gnome-session as 1057eba7239ba1ec3d136359809598590100000018790044
key xsmp.vendor, value gnome-session
key xsmp.client.id, value 1057eba7239ba1ec3d136359809598590100000018790044
Found a new client index 5 name GNOME Volume Control Media Keys eol 0
Properties are:
...
Found a new client index 7 name GNOME Volume Control Applet eol 0
Properties are:
...
Found a new client index 53 name Metacity eol 0
Properties are:
...
Found a new client index 54 name Firefox eol 0
Properties are:
...
Found a new client index 248 name PulseAudio Volume Control eol 0
Properties are:
...
Found a new client index 341 name test eol 0
Properties are:
...
Clients can act as sources: programs such as mplayer
and
vlc
do just that, sending streams to PulseAudio.
Other clients can act as sinks. The clients themselves are monitored
by the previous program. To monitor their activity
you set the mask on pa_subscribe_callback
to
(PA_SUBSCRIPTION_MASK_CLIENT | PA_SUBSCRIPTION_MASK_SINK_INPUT | PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT)
.
Within the subscription
callback you make calls to pa_context_get_sink_input_info
within the PA_SUBSCRIPTION_EVENT_SINK_INPUT
branch
and similarly for the source output.
The sink input callback is passed the structure
pa_sink_input_info
. This contains the familiar
name
and index
fields but also
has an integer field client
. This links the sink input
back to the index of the client responsible for the sink.
In the following program we list all the clients as well, so that
these links can followed visually. Programatically, PulseAudio makes you
keep much information (such as what clients have what indices)
yourself: this is ignored here.
The program to list clients and monitor changes in their input and output streams is pamonitor_clients.c:
The output on my system is
Found a new client index 0 name ConsoleKit Session /org/freedesktop/ConsoleKit/Session2 eol 0
Found a new client index 4 name XSMP Session on gnome-session as 1057eba7239ba1ec3d136359809598590100000018790044 eol 0
Found a new client index 5 name GNOME Volume Control Media Keys eol 0
Found a new client index 7 name GNOME Volume Control Applet eol 0
Found a new client index 53 name Metacity eol 0
Found a new client index 54 name Firefox eol 0
Found a new client index 248 name PulseAudio Volume Control eol 0
Found a new client index 342 name test eol 0
One of the significant features of PulseAudio is that not only can it
mix streams to a device, but it can also control the volume of each stream.
This is in addition to the volume control of each device.
In pavucontrol
you can see this under the Playback
tab, where the volume of playback clients can be adjusted.
Programatically this is done by calling
pa_context_set_sink_input_volume
with parameters
the index of the sink input and the volume.
In the following program we follow what we did in the
pavolume_client.c program where we set PulseAudio to run
in a separate thread and input values for the volume in the
main thread. A slight difference is that we have to wait for a client
to start up a sink input, which we do by sleeping until the
sink input callback assigns a non-zero value to the
sink_index
variable. Crude, yes. In a program such
as pavucontrol
the GUI runs in separate threads
anyway and we do not need to rsort to such simple tricks.
The program is pavolume_sink.c.
If you play a file using
e.g. mplayer
then its volume can be adjusted
by this program.
This chapter has looked at PulseAudio. This is currently the standard sound system for consumer Linux. There are a number of utilities for exploring PulseAudio. There are two APIs: the simple API and the asynchronous API. The chapter has looked at playing and recording using these APIs. Some other aspects of PulseAudio were also examined.
Latency is not a goal, and it is not designed for real-time audio. However, you can request that the latency be made small, and if PulseAudio can do it will give you reasonable performance. However, PulseAudio makes no guarantees about latency, so if a maximum latency is critical then PulseAudio may not be suitable.
PulseAudio is presently built on top of ALSA and usually interacts by making itself the default ALSA plugin.


Security QuestionsChange
For your protection, please choose 3 security questions. This way, we can verify it’s really you if there’s ever a doubt.
2-Step VerificationSetUp
Add an extra layer of security to your account by using a one-time security code in addition to your password each time you log in.


From the Vega Example Gallery
A node-link tree diagram of classes in a software package hierarchy, positioned in Cartesian coordinates using Vega’s tree transform. Adjust the parameters to see layouts suitable for general trees or cluster dendrograms.
A node-link tree diagram of classes in a software package hierarchy, positioned in polar coordinates using Vega’s tree transform. Adjust the parameters to see layouts suitable for general trees or cluster dendrograms.
Treemaps display hierarchical data as a set of nested rectangles. This example shows the software class hierarchy of the Flare visualization toolkit (a precursor to D3 and Vega). Node areas are proportional to the file size in bytes of each source code file.
A circle packing layout uses containment to convey hierarchical relationships. The layout is computed using Vega’s pack transform. This example shows the software class hierarchy of the Flare visualization toolkit; node areas are proportional to the file size in bytes of each source code file.
A sunburst diagram is a radial space-filling tree visualization, similar in spirit to a treemap. Adjacency, rather than containment, is used to depict hierarchical relationships. The layout is computed using Vega’s partition transform. This example shows the software class hierarchy of the Flare visualization toolkit; node areas are proportional to the file size in bytes of each source code file.


DataView
DataView represents a control that displays scalar and DataSet data, as shown in AdventureWorksLT.WpfApp
sample:
Features
DataView acts as root UI container for scalar and DataSet data presentation. In addition, it implements the following command handlers:
- Asynchronously data loading state.
- Scalar data editing.
- Delete selected row(s).
- Clipboard copy/paste.
Usage
Typically, DataView is added to your XAML UI, then call Show method of your presenter class to show data to the this view.
You can also add DataView as row binding via BindToDataView, to display child DataSet as sub DataView.
Implemented Commands
| Command | Input | Implementation |
|---|---|---|
| CancelDataLoad | Control template | Cancels data loading. |
| RetryDataLoad | Control template | Retries data loading. |
| ToggleEditScalars | Toggles scalar editing mode. | |
| BeginEditScalars | Begins scalar editing mode. | |
| EndEditScalars | Ends scalar editing mode. | |
| CancelEditScalars | Cancels scalar editing mode. | |
| Delete | Same as ApplicationCommands.Delete | Deletes selected row(s). |
| Copy | Same as ApplicationCommands.Copy | Copies selected row(s) to clipboard. |
| PasteAppend | Same as ApplicationCommands.Paste | Pastes append data from clipboard. |
Customizable Services
- DataView.ICommandService: Your data presenter can implement this service to change the commands implementation of this class.
- DataView.IPasteAppendService: Your data presenter can implement this interface to verify data to be pasted, for example, retrieve lookup data for foreign key, as demonstrated in
AdventureWorksLT.WpfApp
sample:
bool DataView.IPasteAppendService.Verify(IReadOnlyList<ColumnValueBag> data)
{
var foreignKeys = DataSet<Product.Ref>.Create();
for (int i = 0; i < data.Count; i++)
{
var valueBag = data[i];
var productId = valueBag.ContainsKey(_.ProductID) ? valueBag[_.ProductID] : null;
foreignKeys.AddRow((_, dataRow) =>
{
_.ProductID.SetValue(dataRow, productId);
});
}
if (!App.Execute((db, ct) => db.LookupAsync(foreignKeys, ct), Window.GetWindow(View), out var lookup))
return false;
Debug.Assert(lookup.Count == data.Count);
var product = _.Product;
for (int i = 0; i < lookup.Count; i++)
{
data[i].SetValue(product.Name, lookup._.Name[i]);
data[i].SetValue(product.ProductNumber, lookup._.ProductNumber[i]);
}
return true;
}


| DOSE: T+ 0:00 |
600 mg |
oral |
Yohimbe |
(capsule) |
| T+ 0:40 |
1200 mg |
oral |
Yohimbe |
(tea) |
I got my yohimbe in the mail awhile ago and was looking for something stronger that coffee and a new experience. Well I found it. The yohimbe had been ground to a very fine powder and it was reddish-brown. It smelled like dirt and spices, cloves? I put some on my tongue, not bad tasting but I played it safe and gel-caped in about 15 caps with .5-.7 grams each. It was 10 at night and I did not want to stay up all night.
The next day I was going to work. I'm a cook at a very nice hotel where the atmosphere is hot and sometimes tense. With orders being yelled at you and the need to get it all right and done fast.
+10 minutes into my shift I took 1 pill, minor stimulation after 40 minutes, kind of lousy for what I thought this stuff did or lack of info I knew.
Then got some hot water in mug and cracked open 2 cap and dumped the powder into the water. It turned a very dark color and the tasted and smell were better that coffee (but that's not saying much). I downed it all in about 2 minutes. The reason I made tea is it would take a least 20 minutes for the gel-caps to dissolve and a another 15 or more to kick in.
+20 min it was kicking in and I felt energized. Mild but it got stronger quick.
+30 min I was moving faster and wanted to keep moving can stop now but it was a slow day at the hotel and very little orders were coming in.
+40 min I got a erection it was not self-induced. I was happy the yohimbe lived up to its name.
 I was cleaning up, the feeling in my pelvis area was very noticeable but is was not painfully so.
I went downstairs to the bathroom and had to masturbating. The pressure in my groin was growing even stronger, walking around was humorous (I thought so). Splat in my hand at 3 min into masturbating.  I washed up and went back to work. (I know I was working in a hotel kitchen but if you're a guy you know what I'm talking about when you just have to.  The yohimbe was even more powerful effect now. I took my heart rate it was about 90 beats a min. I was folding the boxes like a mad man. Man I was jittery and felt tired but energized at the same time. Part of my body were cold like the back of my neck. My legs were sore and my groin was throbbing.... Down to the bathroom again. This time was different I lasted a whole 6 min (I timed myself) and the same more but powerful eruption happened. After that was done my face was beet red and my breathing heavy I sat on the toilet seat trying to catch my breath. I went outside to take a break the weather was good and the cool breeze felt nice.
+1.30 hours the effects were wearing off but I say I was about 60% from baseline that's when I went and typed up the report.
+2 hours about 40% from baseline feeling like I had 2 cups of coffee just now my body is feeling fine no tiredness or sore legs.
As for yohimbe I liked it. I will use it again but not for awhile.
Experience Reports are the writings and opinions of the individual authors who submit them.
Some of the activities described are dangerous and/or illegal and none are recommended by Erowid.


--- layout: barebones title: Documentation ---
Everything from first install to deploying flows
The definitive guide to using Node-RED
Recipes to help you get things done with Node-RED
How to create nodes to extend the Node-RED palette
Help to develop the core of Node-RED
Admin, runtime and storage APIs


Jaya Bachchan Scolds Paps For Clicking Pics Outside Manish Malhotra's Residence- Watch
Jaya Bachchan was spotted shouting on media persons during a visit to Manish Malhotra's residence. Watch
Veteran actor Jaya Bachchan has never been a huge fan of the paps following her around, or anyone clicking pictures of hers for that matter.  Recently, when the actor went to Manish Malhotra’s house to pay respect to the family for his father Suraj Malhotra’s death. Seeing the photographers gathered outside the Malhotra residence, Bachchan, it seems, was not happy.
She was heard telling the media persons: “You don’t have any manners na? You don’t think about what the situation is. When such an incident (death) will take place in your houses, then I want to see how you react to it.”
Jaya Bachchan came along with her daughter Shweta Bachchan Nanda in the late hours. Malhotra’s father was in his early nineties and had been unwell for a while.
Watch the videos here:
Karan Johar, Kareena Kapoor Khan, Karisma Kapoor, Gauri Khan, Kiara Advani, Raveena Tandon, Anil Thadani, Arjun Kapoor, Farah Khan, Aishwarya Rai Bachchan, Shilpa Shetty, Malaika Arora, Amrita Arora and Rohit Dhawan also visited the Malhotra residence to offer their condolences.
This is not the first time that Jaya Bachchan has taken on photographers at work in public places. In March, after coming out from Karan Johar’s mother Hiroo Johar’s 76th birthday, Jaya saw a man clicking her pictures and it left her fuming. She called the person and asked her if he asked her for her permission?
For breaking news and live news updates, like us on Facebook or follow us on Twitter and Instagram. Read more on Buzz Latest News on India.com.
Story Timeline
- 20 Nov 2019 Jaya Bachchan Scolds Paps For Clicking Pics Outside Manish Malhotra's Residence- Watch
- 07 Sep 2019 Jaya Bachchan Removing Something Off Abhishek's Blazer at Party is Basically All Moms Ever
- 02 Jul 2019 Vintage Picture of Amitabh, Jaya, Neelam, Archana Will Give You a Good Dose of Nostalgia
- 19 Apr 2019 Manish Malhotra Dances to First Class With Kiara Advani, Sonakshi Sinha And Ananya Panday at His Party - Watch Viral Video
Comments - Join the Discussion