[pulseaudio-discuss] Setting the volume via API has no effect

Buddy Butterfly buddy.butterfly at web.de
Wed Aug 20 06:18:33 PDT 2014


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,
> 
> 
> 
> _______________________________________________
> pulseaudio-discuss mailing list
> pulseaudio-discuss at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss
> 

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.




More information about the pulseaudio-discuss mailing list