[pulseaudio-discuss] Setting the volume via API has no effect
Hugo Osvaldo Barrera
hugo at barrera.io
Wed Aug 20 06:38:26 PDT 2014
On 2014-08-20 15:18, Buddy Butterfly wrote:
> Am 20.08.2014 um 14:37 schrieb Hugo Osvaldo Barrera:
> > Hi,
> >
> > First of all, sorry for the rather long and verbose email, but I'd like to be
> > as specific as possible.
> >
> > I'm trying to write my own volume control application, and first of all,
> > started fiddling with the pulseaudio api (with a threaded main loop).
> >
> > I've gotten the sinks, the volume, etc, but when I _set_ a volume, it has no
> > effect. The API reports success, but pavucontrol reveals that it has not
> > changes (also, if I set it to 0%, I can still hear stuff like vlc, etc).
> >
> > The code is a bit long, but pretty clear. Build with:
> >
> > clang -Wall pulse.c -o pulse `pkg-config --cflags --libs libpulse-simple`
> >
> > Here's the code in question:
> >
> > #include <stdio.h>
> > #include <pulse/introspect.h>
> > #include <pulse/context.h>
> > #include <pulse/thread-mainloop.h>
> > #include <pulse/error.h>
> > #include <unistd.h>
> > #include <stdlib.h>
> >
> > int sink_count = 0;
> > // FIXME: list that can handle more than 5
> > pa_sink_info sinks[5];
> >
> > void vol_success(pa_context *c, int success, void *userdata) {
> > int i = *(int*) userdata;
> > printf("Card %d, success: %d.\n", i, success);
> > free(userdata);
> > }
> >
> > void sinks_callback(pa_context *c, const pa_sink_info *i, int eol, void *userdata) {
> > if (!eol) {
> > printf("Got sink %d (mute: %d, vol: %.2fdB): %s - %s.\n", i->index, i->mute,
> > pa_sw_volume_to_dB(i->volume.values[0]), i->description, i->name);
> > sinks[sink_count++] = *i;
> > }
> > else {
> > printf("Got all the sinks! :D\n\n");
> > pa_volume_t volume = PA_VOLUME_NORM;
> >
> > for (int i = 0; i < sink_count; i++) {
> > // Copy this value because we might alter it before the other thread consumes it.
> > int *idx = malloc(sizeof(int)); *idx = i;
> > pa_cvolume vols = sinks[i].volume;
> > pa_cvolume_set(&vols, vols.channels, volume);
> >
> > printf("Volume being set to %d (%.2fdB) on card %d (%d channels), (was %.2fdB)\n",
> > volume, pa_sw_volume_to_dB(volume), *idx, vols.channels,
> > pa_sw_volume_to_dB(sinks[i].volume.values[0]));
> >
> > pa_operation* o = pa_context_set_sink_input_volume(c, *idx, &vols, vol_success, idx);
> > if (!o) {
> > printf("\nError setting volume for sink: %s\n", pa_strerror(pa_context_errno(c)));
> > exit(-15);
> > }
> > pa_operation_unref(o);
> > }
> > }
> > }
> >
> > void context_state_callback(pa_context* c, void* userdata) {
> > pa_operation* o;
> > switch (pa_context_get_state(c)) {
> > case PA_CONTEXT_UNCONNECTED:
> > case PA_CONTEXT_CONNECTING:
> > case PA_CONTEXT_AUTHORIZING:
> > case PA_CONTEXT_SETTING_NAME:
> > printf(". "); fflush(NULL);
> > break;
> > case PA_CONTEXT_READY:
> > printf("SUCCESS!\n\n");
> > o = pa_context_get_sink_info_list(c, sinks_callback, NULL);
> > if (!o) {
> > printf("Error getting sinks: %s\n", pa_strerror(pa_context_errno(c)));
> > exit(-13);
> > }
> > pa_operation_unref(o);
> > break;
> > case PA_CONTEXT_FAILED:
> > printf("The connection failed or was disconnected.\n");
> > exit(-11);
> > case PA_CONTEXT_TERMINATED:
> > printf("The connection was terminated cleanly.\n");
> > exit(-12);
> > default:
> > printf("Unexpected context state.\n");
> > }
> > }
> >
> > int main(void) {
> > // create loop
> > pa_threaded_mainloop* loop = pa_threaded_mainloop_new();
> > if (!loop) {
> > printf("Failed to create main loop.\n");
> > exit(-1);
> > }
> >
> > // start loop
> > if (pa_threaded_mainloop_start(loop)) {
> > printf("Failed to start main loop.\n");
> > exit(-2);
> > }
> >
> > // get the api
> > pa_mainloop_api* api = pa_threaded_mainloop_get_api(loop);
> > if (!api) {
> > printf("Failed to get api.\n");
> > exit(-3);
> > }
> >
> > // get a context
> > pa_context *c = pa_context_new(api, "volctl3");
> > if (!c) {
> > printf("Failed to get context.\n");
> > exit(-4);
> > }
> >
> > // set a callback for context state changes
> > pa_context_set_state_callback(c, context_state_callback, NULL);
> >
> > pa_threaded_mainloop_lock(loop);
> >
> > // connect
> > printf("About to connect: ");
> > if (pa_context_connect(c, NULL, PA_CONTEXT_NOFLAGS, NULL)) {
> > printf("FAILED!\n");
> > exit(-5);
> > }
> >
> > pa_threaded_mainloop_unlock(loop);
> >
> > // Sleep to keep the thread alive. Note that an actuall app would do stuff
> > // here.
> > sleep(15);
> >
> > return 0;
> > }
> >
> > // END OF CODE
> >
> > Am I going something wrong, or have I hit a bug?
> >
> > Thanks,
> >
> >
> >
> >
>
> Just a quick one. Do you have flat-volumes on or off? Don't know if that
> matters. Try setting "flat-volumes = no" in /etc/pulse/daemon.conf.
>
This didn't change anything, regrettably. Also, *no* volume changes take any
effect, AFAIK, flat-volumes should have different results, but some values
should make a difference anyway.
--
Hugo Osvaldo Barrera
A: Because we read from top to bottom, left to right.
Q: Why should I start my reply below the quoted text?
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/pulseaudio-discuss/attachments/20140820/51c0071a/attachment.sig>
More information about the pulseaudio-discuss
mailing list