[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