aboutsummaryrefslogtreecommitdiff
path: root/src/mixer
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2009-03-27 16:44:36 +0100
committerMax Kellermann <max@duempel.org>2009-03-27 16:44:36 +0100
commit8258457b434fd24dba6025b474c2d3be8f8183d3 (patch)
tree74bd320f22862a931bc3b25e3e9a7fd429f8b53d /src/mixer
parent1a411b1cedfad5073fa545c852a6d23107a1ddd0 (diff)
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.
Diffstat (limited to 'src/mixer')
-rw-r--r--src/mixer/pulse_mixer.c35
1 files changed, 34 insertions, 1 deletions
diff --git a/src/mixer/pulse_mixer.c b/src/mixer/pulse_mixer.c
index 899ab544..f9c90191 100644
--- a/src/mixer/pulse_mixer.c
+++ b/src/mixer/pulse_mixer.c
@@ -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);