[PATCH] Hack
David Henningsson
david.henningsson at canonical.com
Fri Mar 30 08:10:11 PDT 2012
Signed-off-by: David Henningsson <david.henningsson at canonical.com>
---
src/modules/alsa/alsa-sink.c | 65 ++++++++++++++++++++++++++++++++++++++++--
src/pulsecore/sink.c | 10 ++++++
src/pulsecore/sink.h | 4 ++
5 files changed, 80 insertions(+), 7 deletions(-)
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index ea5188c..43a8cde 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -106,6 +106,7 @@ struct userdata {
snd_mixer_t *mixer_handle;
pa_alsa_path_set *mixer_path_set;
pa_alsa_path *mixer_path;
+ pa_atomic_t mixer_dirty;
pa_cvolume hardware_volume;
@@ -1210,8 +1211,10 @@ static int ctl_mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) {
if (!PA_SINK_IS_LINKED(u->sink->state))
return 0;
- if (u->sink->suspend_cause & PA_SUSPEND_SESSION)
+ if (u->sink->suspend_cause & PA_SUSPEND_SESSION) {
+ pa_atomic_store(&u->mixer_dirty, 1);
return 0;
+ }
if (mask & SND_CTL_EVENT_MASK_VALUE) {
pa_sink_get_volume(u->sink, TRUE);
@@ -1230,8 +1233,10 @@ static int io_mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) {
if (mask == SND_CTL_EVENT_MASK_REMOVE)
return 0;
- if (u->sink->suspend_cause & PA_SUSPEND_SESSION)
+ if (u->sink->suspend_cause & PA_SUSPEND_SESSION) {
+ pa_atomic_store(&u->mixer_dirty, 1);
return 0;
+ }
if (mask & SND_CTL_EVENT_MASK_VALUE)
pa_sink_update_volume_and_mute(u->sink);
@@ -1454,8 +1459,8 @@ static int sink_set_port_cb(pa_sink *s, pa_device_port *p) {
pa_assert(u->mixer_handle);
data = PA_DEVICE_PORT_DATA(p);
-
pa_assert_se(u->mixer_path = data->path);
+
pa_alsa_path_select(u->mixer_path, u->mixer_handle);
mixer_volume_init(u);
@@ -1471,6 +1476,59 @@ static int sink_set_port_cb(pa_sink *s, pa_device_port *p) {
return 0;
}
+struct sink_message_set_port {
+ pa_device_port *port;
+ int ret;
+};
+
+static void sink_update_suspend_cause_cb(pa_sink *s) {
+ struct userdata *u = s->userdata;
+ pa_assert(u);
+
+ pa_log_debug("mixer_dirty = %d", pa_atomic_load(&u->mixer_dirty));
+
+ if (s->suspend_cause & PA_SUSPEND_SESSION)
+ return;
+ if (pa_atomic_load(&u->mixer_dirty) == 0)
+ return;
+ /* This might look racy but isn't: If somebody sets mixer_dirty exactly here,
+ it'll be handled just fine */
+ pa_atomic_store(&u->mixer_dirty, 0);
+
+/* if (s->get_mute)
+ s->get_mute(s);
+ if (s->get_volume)
+ s->get_volume(s);*/
+ pa_log_debug("=== DIWIC === %d", s->flags & PA_SINK_DEFERRED_VOLUME);
+
+ if (s->active_port && s->set_port) {
+ pa_cvolume old_volume;
+ pa_bool_t old_mute;
+ old_volume = *pa_sink_get_volume(s, FALSE);
+ old_mute = pa_sink_get_mute(s, FALSE);
+
+ if (s->flags & PA_SINK_DEFERRED_VOLUME) {
+ struct sink_message_set_port msg = { .port = s->active_port, .ret = 0 };
+ pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_PORT, &msg, 0, NULL) == 0);
+ }
+ else
+ s->set_port(s, s->active_port);
+
+ pa_sink_get_volume(s, TRUE);
+ pa_sink_get_mute(s, TRUE);
+ pa_sink_set_volume(s, &old_volume, TRUE, FALSE);
+ pa_sink_set_mute(s, old_mute, FALSE);
+
+
+ }
+ else {
+ if (s->set_mute)
+ s->set_mute(s);
+ if (s->set_volume)
+ s->set_volume(s);
+ }
+}
+
static void sink_update_requested_latency_cb(pa_sink *s) {
struct userdata *u = s->userdata;
size_t before;
@@ -2244,6 +2302,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
u->sink->update_requested_latency = sink_update_requested_latency_cb;
u->sink->set_state = sink_set_state_cb;
u->sink->set_port = sink_set_port_cb;
+ u->sink->update_suspend_cause = sink_update_suspend_cause_cb;
if (u->sink->alternate_sample_rate)
u->sink->update_rate = sink_update_rate_cb;
u->sink->userdata = u;
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 2d214cf..f8cac69 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -159,6 +159,7 @@ static void reset_callbacks(pa_sink *s) {
s->set_mute = NULL;
s->request_rewind = NULL;
s->update_requested_latency = NULL;
+ s->update_suspend_cause = NULL;
s->set_port = NULL;
s->get_formats = NULL;
s->set_formats = NULL;
@@ -797,11 +798,14 @@ int pa_sink_update_status(pa_sink*s) {
/* Called from main context */
int pa_sink_suspend(pa_sink *s, pa_bool_t suspend, pa_suspend_cause_t cause) {
+ pa_suspend_cause_t old_cause;
pa_sink_assert_ref(s);
pa_assert_ctl_context();
pa_assert(PA_SINK_IS_LINKED(s->state));
pa_assert(cause != 0);
+ old_cause = s->suspend_cause;
+
if (suspend) {
s->suspend_cause |= cause;
s->monitor_source->suspend_cause |= cause;
@@ -810,6 +814,12 @@ int pa_sink_suspend(pa_sink *s, pa_bool_t suspend, pa_suspend_cause_t cause) {
s->monitor_source->suspend_cause &= ~cause;
}
+ if (old_cause == s->suspend_cause)
+ return 0;
+
+ if (s->update_suspend_cause)
+ s->update_suspend_cause(s);
+
if ((pa_sink_get_state(s) == PA_SINK_SUSPENDED) == !!s->suspend_cause)
return 0;
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index 56fa735..8966854 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -202,6 +202,10 @@ struct pa_sink {
* set this callback. */
pa_sink_cb_t set_mute; /* may be NULL */
+ /* Called when suspend cause has been updated. Called from main
+ * context. */
+ pa_sink_cb_t update_suspend_cause; /* may be NULL */
+
/* Called when a rewind request is issued. Called from IO thread
* context. */
pa_sink_cb_t request_rewind; /* may be NULL */
--
1.7.9.1
--------------070608030201060803040200--
More information about the pulseaudio-discuss
mailing list