}
}
-static void sink_get_mute_cb(pa_sink *s) {
+static int sink_get_mute_cb(pa_sink *s, bool *mute) {
struct userdata *u = s->userdata;
- bool b;
pa_assert(u);
pa_assert(u->mixer_path);
pa_assert(u->mixer_handle);
- if (pa_alsa_path_get_mute(u->mixer_path, u->mixer_handle, &b) < 0)
- return;
+ if (pa_alsa_path_get_mute(u->mixer_path, u->mixer_handle, mute) < 0)
+ return -1;
- s->muted = b;
+ return 0;
}
static void sink_set_mute_cb(pa_sink *s) {
if (u->sink->set_mute)
u->sink->set_mute(u->sink);
} else {
- if (u->sink->get_mute)
- u->sink->get_mute(u->sink);
+ if (u->sink->get_mute) {
+ bool mute;
+
+ if (u->sink->get_mute(u->sink, &mute) >= 0)
+ pa_sink_set_mute(u->sink, mute, false);
+ }
}
if ((data.volume_is_set || data.muted_is_set) && u->sink->write_volume)
}
}
-static void source_get_mute_cb(pa_source *s) {
+static int source_get_mute_cb(pa_source *s, bool *mute) {
struct userdata *u = s->userdata;
- bool b;
pa_assert(u);
pa_assert(u->mixer_path);
pa_assert(u->mixer_handle);
- if (pa_alsa_path_get_mute(u->mixer_path, u->mixer_handle, &b) < 0)
- return;
+ if (pa_alsa_path_get_mute(u->mixer_path, u->mixer_handle, mute) < 0)
+ return -1;
- s->muted = b;
+ return 0;
}
static void source_set_mute_cb(pa_source *s) {
if (u->source->set_mute)
u->source->set_mute(u->source);
} else {
- if (u->source->get_mute)
- u->source->get_mute(u->source);
+ if (u->source->get_mute) {
+ bool mute;
+
+ if (u->source->get_mute(u->source, &mute) >= 0)
+ pa_source_set_mute(u->source, mute, false);
+ }
}
if ((data.volume_is_set || data.muted_is_set) && u->source->write_volume)
}
}
-static void sink_get_mute(pa_sink *s) {
+static int sink_get_mute(pa_sink *s, bool *mute) {
struct userdata *u = s->userdata;
audio_info_t info;
pa_assert(u);
- if (u->fd >= 0) {
- if (ioctl(u->fd, AUDIO_GETINFO, &info) < 0)
- pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno));
- else
- s->muted = !!info.output_muted;
+ if (u->fd < 0)
+ return -1;
+
+ if (ioctl(u->fd, AUDIO_GETINFO, &info) < 0) {
+ pa_log("AUDIO_GETINFO: %s", pa_cstrerror(errno));
+ return -1;
}
+
+ *mute = info.output_muted;
+
+ return 0;
}
static void process_rewind(struct userdata *u) {
pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
}
-void pa_sink_set_get_mute_callback(pa_sink *s, pa_sink_cb_t cb) {
+void pa_sink_set_get_mute_callback(pa_sink *s, pa_sink_get_mute_cb_t cb) {
pa_assert(s);
s->get_mute = cb;
pa_assert_ctl_context();
pa_assert(PA_SINK_IS_LINKED(s->state));
- if (s->refresh_muted || force_refresh) {
- bool old_muted = s->muted;
+ if ((s->refresh_muted || force_refresh) && s->get_mute) {
+ bool mute;
- if (!(s->flags & PA_SINK_DEFERRED_VOLUME) && s->get_mute)
- s->get_mute(s);
-
- pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MUTE, NULL, 0, NULL) == 0);
-
- if (old_muted != s->muted) {
- s->save_muted = true;
-
- pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
-
- /* Make sure the soft mute status stays in sync */
- pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_MUTE, NULL, 0, NULL) == 0);
+ if (s->flags & PA_SINK_DEFERRED_VOLUME) {
+ if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MUTE, &mute, 0, NULL) >= 0)
+ pa_sink_mute_changed(s, mute);
+ } else {
+ if (s->get_mute(s, &mute) >= 0)
+ pa_sink_mute_changed(s, mute);
}
}
case PA_SINK_MESSAGE_GET_MUTE:
if (s->flags & PA_SINK_DEFERRED_VOLUME && s->get_mute)
- s->get_mute(s);
+ return s->get_mute(s, userdata);
return 0;
/* A generic definition for void callback functions */
typedef void(*pa_sink_cb_t)(pa_sink *s);
+typedef int (*pa_sink_get_mute_cb_t)(pa_sink *s, bool *mute);
+
struct pa_sink {
pa_msgobject parent;
* set this callback. */
pa_sink_cb_t write_volume; /* may be NULL */
- /* Called when the mute setting is queried. A PA_SINK_MESSAGE_GET_MUTE
- * message will also be sent. Called from IO thread if PA_SINK_DEFERRED_VOLUME
- * flag is set otherwise from main loop context. If refresh_mute is false
- * neither this function is called nor a message is sent.
+ /* If the sink mute can change "spontaneously" (i.e. initiated by the sink
+ * implementation, not by someone else calling pa_sink_set_mute()), then
+ * the sink implementation can notify about changed mute either by calling
+ * pa_sink_mute_changed() or by calling pa_sink_get_mute() with
+ * force_refresh=true. If the implementation chooses the latter approach,
+ * it should implement the get_mute callback. Otherwise get_mute can be
+ * NULL.
+ *
+ * This is called when pa_sink_get_mute() is called with
+ * force_refresh=true. This is called from the IO thread if the
+ * PA_SINK_DEFERRED_VOLUME flag is set, otherwise this is called from the
+ * main thread. On success, the implementation is expected to return 0 and
+ * set the mute parameter that is passed as a reference. On failure, the
+ * implementation is expected to return -1.
*
* You must use the function pa_sink_set_get_mute_callback() to
* set this callback. */
- pa_sink_cb_t get_mute; /* may be NULL */
+ pa_sink_get_mute_cb_t get_mute;
/* Called when the mute setting shall be changed. A PA_SINK_MESSAGE_SET_MUTE
* message will also be sent. Called from IO thread if PA_SINK_DEFERRED_VOLUME
void pa_sink_set_get_volume_callback(pa_sink *s, pa_sink_cb_t cb);
void pa_sink_set_set_volume_callback(pa_sink *s, pa_sink_cb_t cb);
void pa_sink_set_write_volume_callback(pa_sink *s, pa_sink_cb_t cb);
-void pa_sink_set_get_mute_callback(pa_sink *s, pa_sink_cb_t cb);
+void pa_sink_set_get_mute_callback(pa_sink *s, pa_sink_get_mute_cb_t cb);
void pa_sink_set_set_mute_callback(pa_sink *s, pa_sink_cb_t cb);
void pa_sink_enable_decibel_volume(pa_sink *s, bool enable);
pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
}
-void pa_source_set_get_mute_callback(pa_source *s, pa_source_cb_t cb) {
+void pa_source_set_get_mute_callback(pa_source *s, pa_source_get_mute_cb_t cb) {
pa_assert(s);
s->get_mute = cb;
pa_assert_ctl_context();
pa_assert(PA_SOURCE_IS_LINKED(s->state));
- if (s->refresh_muted || force_refresh) {
- bool old_muted = s->muted;
+ if ((s->refresh_muted || force_refresh) && s->get_mute) {
+ bool mute;
- if (!(s->flags & PA_SOURCE_DEFERRED_VOLUME) && s->get_mute)
- s->get_mute(s);
-
- pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_MUTE, NULL, 0, NULL) == 0);
-
- if (old_muted != s->muted) {
- s->save_muted = true;
-
- pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
-
- /* Make sure the soft mute status stays in sync */
- pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_MUTE, NULL, 0, NULL) == 0);
+ if (s->flags & PA_SOURCE_DEFERRED_VOLUME) {
+ if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_MUTE, &mute, 0, NULL) >= 0)
+ pa_source_mute_changed(s, mute);
+ } else {
+ if (s->get_mute(s, &mute) >= 0)
+ pa_source_mute_changed(s, mute);
}
}
case PA_SOURCE_MESSAGE_GET_MUTE:
if (s->flags & PA_SOURCE_DEFERRED_VOLUME && s->get_mute)
- s->get_mute(s);
+ return s->get_mute(s, userdata);
return 0;
/* A generic definition for void callback functions */
typedef void(*pa_source_cb_t)(pa_source *s);
+typedef int (*pa_source_get_mute_cb_t)(pa_source *s, bool *mute);
+
struct pa_source {
pa_msgobject parent;
* set this callback. */
pa_source_cb_t write_volume; /* may be NULL */
- /* Called when the mute setting is queried. Called from main loop
- * context. If this is NULL a PA_SOURCE_MESSAGE_GET_MUTE message
- * will be sent to the IO thread instead. If refresh_mute is
- * false neither this function is called nor a message is sent.
+ /* If the source mute can change "spontaneously" (i.e. initiated by the
+ * source implementation, not by someone else calling
+ * pa_source_set_mute()), then the source implementation can notify about
+ * changed mute either by calling pa_source_mute_changed() or by calling
+ * pa_source_get_mute() with force_refresh=true. If the implementation
+ * chooses the latter approach, it should implement the get_mute callback.
+ * Otherwise get_mute can be NULL.
+ *
+ * This is called when pa_source_get_mute() is called with
+ * force_refresh=true. This is called from the IO thread if the
+ * PA_SOURCE_DEFERRED_VOLUME flag is set, otherwise this is called from the
+ * main thread. On success, the implementation is expected to return 0 and
+ * set the mute parameter that is passed as a reference. On failure, the
+ * implementation is expected to return -1.
*
* You must use the function pa_source_set_get_mute_callback() to
* set this callback. */
- pa_source_cb_t get_mute; /* may be NULL */
+ pa_source_get_mute_cb_t get_mute;
/* Called when the mute setting shall be changed. Called from main
* loop context. If this is NULL a PA_SOURCE_MESSAGE_SET_MUTE
void pa_source_set_get_volume_callback(pa_source *s, pa_source_cb_t cb);
void pa_source_set_set_volume_callback(pa_source *s, pa_source_cb_t cb);
void pa_source_set_write_volume_callback(pa_source *s, pa_source_cb_t cb);
-void pa_source_set_get_mute_callback(pa_source *s, pa_source_cb_t cb);
+void pa_source_set_get_mute_callback(pa_source *s, pa_source_get_mute_cb_t cb);
void pa_source_set_set_mute_callback(pa_source *s, pa_source_cb_t cb);
void pa_source_enable_decibel_volume(pa_source *s, bool enable);