[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