pulse_mixer: wait for get_volume() operation to complete

The pa_context_get_sink_input_info() function is asynchronous, and
after it returns, libpulse does not guarantee that the operation has
completed yet; in fact, it is not likely.  Explicitly wait for the
operation to complete.

The code for the new pulse_wait_for_operation() function was inspired
by mplayer and xine code.
This commit is contained in:
Max Kellermann 2009-03-27 16:44:36 +01:00
parent 1a411b1ced
commit 8258457b43

View File

@ -45,6 +45,36 @@ struct pulse_mixer {
};
/**
* \brief waits for a pulseaudio operation to finish, frees it and
* unlocks the mainloop
* \param operation the operation to wait for
* \return true if operation has finished normally (DONE state),
* false otherwise
*/
static bool
pulse_wait_for_operation(struct pa_threaded_mainloop *mainloop,
struct pa_operation *operation)
{
pa_operation_state_t state;
assert(mainloop != NULL);
assert(operation != NULL);
pa_threaded_mainloop_lock(mainloop);
state = pa_operation_get_state(operation);
while (state == PA_OPERATION_RUNNING) {
pa_threaded_mainloop_wait(mainloop);
state = pa_operation_get_state(operation);
}
pa_operation_unref(operation);
pa_threaded_mainloop_unlock(mainloop);
return state == PA_OPERATION_DONE;
}
static void
sink_input_cb(G_GNUC_UNUSED pa_context *context, const pa_sink_input_info *i,
int eol, void *userdata)
@ -91,6 +121,8 @@ sink_input_vol(G_GNUC_UNUSED pa_context *context, const pa_sink_input_info *i,
g_debug("sink input vol %s, index %d ", i->name, i->index);
pm->volume = i->volume;
pa_threaded_mainloop_signal(pm->mainloop, 0);
}
static void
@ -292,7 +324,8 @@ pulse_mixer_get_volume(struct mixer *mixer)
return false;
}
pa_operation_unref(o);
if (!pulse_wait_for_operation(pm->mainloop, o))
return false;
ret = (int)((100*(pa_cvolume_avg(&pm->volume)+1))/PA_VOLUME_NORM);
g_debug("volume %d", ret);