sink, source: Assign to s->muted from only one place

Forcing all mute changes to go through set_mute() makes it easier to
check where the muted field is changed, and it also allows us to have
only one place where notifications for changed mute are sent.
This commit is contained in:
Tanu Kaskinen 2014-04-15 13:56:10 +03:00
parent dbd2a8f851
commit e4a7625ba8
7 changed files with 87 additions and 64 deletions

View file

@ -1395,18 +1395,17 @@ static void sink_write_volume_cb(pa_sink *s) {
} }
} }
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; struct userdata *u = s->userdata;
bool b;
pa_assert(u); pa_assert(u);
pa_assert(u->mixer_path); pa_assert(u->mixer_path);
pa_assert(u->mixer_handle); pa_assert(u->mixer_handle);
if (pa_alsa_path_get_mute(u->mixer_path, u->mixer_handle, &b) < 0) if (pa_alsa_path_get_mute(u->mixer_path, u->mixer_handle, mute) < 0)
return; return -1;
s->muted = b; return 0;
} }
static void sink_set_mute_cb(pa_sink *s) { static void sink_set_mute_cb(pa_sink *s) {
@ -2390,8 +2389,12 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
if (u->sink->set_mute) if (u->sink->set_mute)
u->sink->set_mute(u->sink); u->sink->set_mute(u->sink);
} else { } else {
if (u->sink->get_mute) if (u->sink->get_mute) {
u->sink->get_mute(u->sink); 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) if ((data.volume_is_set || data.muted_is_set) && u->sink->write_volume)

View file

@ -1277,18 +1277,17 @@ static void source_write_volume_cb(pa_source *s) {
} }
} }
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; struct userdata *u = s->userdata;
bool b;
pa_assert(u); pa_assert(u);
pa_assert(u->mixer_path); pa_assert(u->mixer_path);
pa_assert(u->mixer_handle); pa_assert(u->mixer_handle);
if (pa_alsa_path_get_mute(u->mixer_path, u->mixer_handle, &b) < 0) if (pa_alsa_path_get_mute(u->mixer_path, u->mixer_handle, mute) < 0)
return; return -1;
s->muted = b; return 0;
} }
static void source_set_mute_cb(pa_source *s) { static void source_set_mute_cb(pa_source *s) {
@ -2088,8 +2087,12 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
if (u->source->set_mute) if (u->source->set_mute)
u->source->set_mute(u->source); u->source->set_mute(u->source);
} else { } else {
if (u->source->get_mute) if (u->source->get_mute) {
u->source->get_mute(u->source); 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) if ((data.volume_is_set || data.muted_is_set) && u->source->write_volume)

View file

@ -571,18 +571,23 @@ static void sink_set_mute(pa_sink *s) {
} }
} }
static void sink_get_mute(pa_sink *s) { static int sink_get_mute(pa_sink *s, bool *mute) {
struct userdata *u = s->userdata; struct userdata *u = s->userdata;
audio_info_t info; audio_info_t info;
pa_assert(u); pa_assert(u);
if (u->fd >= 0) { if (u->fd < 0)
if (ioctl(u->fd, AUDIO_GETINFO, &info) < 0) return -1;
pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno));
else if (ioctl(u->fd, AUDIO_GETINFO, &info) < 0) {
s->muted = !!info.output_muted; pa_log("AUDIO_GETINFO: %s", pa_cstrerror(errno));
return -1;
} }
*mute = info.output_muted;
return 0;
} }
static void process_rewind(struct userdata *u) { static void process_rewind(struct userdata *u) {

View file

@ -508,7 +508,7 @@ void pa_sink_set_write_volume_callback(pa_sink *s, pa_sink_cb_t cb) {
pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); 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); pa_assert(s);
s->get_mute = cb; s->get_mute = cb;
@ -2228,21 +2228,15 @@ bool pa_sink_get_mute(pa_sink *s, bool force_refresh) {
pa_assert_ctl_context(); pa_assert_ctl_context();
pa_assert(PA_SINK_IS_LINKED(s->state)); pa_assert(PA_SINK_IS_LINKED(s->state));
if (s->refresh_muted || force_refresh) { if ((s->refresh_muted || force_refresh) && s->get_mute) {
bool old_muted = s->muted; bool mute;
if (!(s->flags & PA_SINK_DEFERRED_VOLUME) && s->get_mute) if (s->flags & PA_SINK_DEFERRED_VOLUME) {
s->get_mute(s); if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MUTE, &mute, 0, NULL) >= 0)
pa_sink_mute_changed(s, mute);
pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MUTE, NULL, 0, NULL) == 0); } else {
if (s->get_mute(s, &mute) >= 0)
if (old_muted != s->muted) { pa_sink_mute_changed(s, mute);
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);
} }
} }
@ -2750,7 +2744,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
case PA_SINK_MESSAGE_GET_MUTE: case PA_SINK_MESSAGE_GET_MUTE:
if (s->flags & PA_SINK_DEFERRED_VOLUME && s->get_mute) if (s->flags & PA_SINK_DEFERRED_VOLUME && s->get_mute)
s->get_mute(s); return s->get_mute(s, userdata);
return 0; return 0;

View file

@ -58,6 +58,8 @@ static inline bool PA_SINK_IS_LINKED(pa_sink_state_t x) {
/* A generic definition for void callback functions */ /* A generic definition for void callback functions */
typedef void(*pa_sink_cb_t)(pa_sink *s); 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 { struct pa_sink {
pa_msgobject parent; pa_msgobject parent;
@ -191,14 +193,24 @@ struct pa_sink {
* set this callback. */ * set this callback. */
pa_sink_cb_t write_volume; /* may be NULL */ pa_sink_cb_t write_volume; /* may be NULL */
/* Called when the mute setting is queried. A PA_SINK_MESSAGE_GET_MUTE /* If the sink mute can change "spontaneously" (i.e. initiated by the sink
* message will also be sent. Called from IO thread if PA_SINK_DEFERRED_VOLUME * implementation, not by someone else calling pa_sink_set_mute()), then
* flag is set otherwise from main loop context. If refresh_mute is false * the sink implementation can notify about changed mute either by calling
* neither this function is called nor a message is sent. * 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 * You must use the function pa_sink_set_get_mute_callback() to
* set this callback. */ * 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 /* 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 * message will also be sent. Called from IO thread if PA_SINK_DEFERRED_VOLUME
@ -379,7 +391,7 @@ pa_sink* pa_sink_new(
void pa_sink_set_get_volume_callback(pa_sink *s, pa_sink_cb_t cb); 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_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_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_set_set_mute_callback(pa_sink *s, pa_sink_cb_t cb);
void pa_sink_enable_decibel_volume(pa_sink *s, bool enable); void pa_sink_enable_decibel_volume(pa_sink *s, bool enable);

View file

@ -459,7 +459,7 @@ void pa_source_set_write_volume_callback(pa_source *s, pa_source_cb_t cb) {
pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); 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); pa_assert(s);
s->get_mute = cb; s->get_mute = cb;
@ -1821,21 +1821,15 @@ bool pa_source_get_mute(pa_source *s, bool force_refresh) {
pa_assert_ctl_context(); pa_assert_ctl_context();
pa_assert(PA_SOURCE_IS_LINKED(s->state)); pa_assert(PA_SOURCE_IS_LINKED(s->state));
if (s->refresh_muted || force_refresh) { if ((s->refresh_muted || force_refresh) && s->get_mute) {
bool old_muted = s->muted; bool mute;
if (!(s->flags & PA_SOURCE_DEFERRED_VOLUME) && s->get_mute) if (s->flags & PA_SOURCE_DEFERRED_VOLUME) {
s->get_mute(s); if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_MUTE, &mute, 0, NULL) >= 0)
pa_source_mute_changed(s, mute);
pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_MUTE, NULL, 0, NULL) == 0); } else {
if (s->get_mute(s, &mute) >= 0)
if (old_muted != s->muted) { pa_source_mute_changed(s, mute);
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);
} }
} }
@ -2120,7 +2114,7 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
case PA_SOURCE_MESSAGE_GET_MUTE: case PA_SOURCE_MESSAGE_GET_MUTE:
if (s->flags & PA_SOURCE_DEFERRED_VOLUME && s->get_mute) if (s->flags & PA_SOURCE_DEFERRED_VOLUME && s->get_mute)
s->get_mute(s); return s->get_mute(s, userdata);
return 0; return 0;

View file

@ -58,6 +58,8 @@ static inline bool PA_SOURCE_IS_LINKED(pa_source_state_t x) {
/* A generic definition for void callback functions */ /* A generic definition for void callback functions */
typedef void(*pa_source_cb_t)(pa_source *s); 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 { struct pa_source {
pa_msgobject parent; pa_msgobject parent;
@ -158,14 +160,24 @@ struct pa_source {
* set this callback. */ * set this callback. */
pa_source_cb_t write_volume; /* may be NULL */ pa_source_cb_t write_volume; /* may be NULL */
/* Called when the mute setting is queried. Called from main loop /* If the source mute can change "spontaneously" (i.e. initiated by the
* context. If this is NULL a PA_SOURCE_MESSAGE_GET_MUTE message * source implementation, not by someone else calling
* will be sent to the IO thread instead. If refresh_mute is * pa_source_set_mute()), then the source implementation can notify about
* false neither this function is called nor a message is sent. * 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_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_source_set_get_mute_callback() to * You must use the function pa_source_set_get_mute_callback() to
* set this callback. */ * 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 /* Called when the mute setting shall be changed. Called from main
* loop context. If this is NULL a PA_SOURCE_MESSAGE_SET_MUTE * loop context. If this is NULL a PA_SOURCE_MESSAGE_SET_MUTE
@ -316,7 +328,7 @@ pa_source* pa_source_new(
void pa_source_set_get_volume_callback(pa_source *s, pa_source_cb_t cb); 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_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_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_set_set_mute_callback(pa_source *s, pa_source_cb_t cb);
void pa_source_enable_decibel_volume(pa_source *s, bool enable); void pa_source_enable_decibel_volume(pa_source *s, bool enable);