[pulseaudio-discuss] [PATCH v2 4/9] dbus: Track stream moves with hooks

Tanu Kaskinen tanuk at iki.fi
Wed Feb 20 10:23:59 PST 2013


---
 src/modules/dbus/iface-stream.c |   96 ++++++++++++++++++++-------------------
 1 file changed, 50 insertions(+), 46 deletions(-)

diff --git a/src/modules/dbus/iface-stream.c b/src/modules/dbus/iface-stream.c
index c6dc1c9..7eb7631 100644
--- a/src/modules/dbus/iface-stream.c
+++ b/src/modules/dbus/iface-stream.c
@@ -60,6 +60,7 @@ struct pa_dbusiface_stream {
 
     pa_dbus_protocol *dbus_protocol;
     pa_subscription *subscription;
+    pa_hook_slot *move_finish_slot;
     pa_hook_slot *send_event_slot;
 };
 
@@ -662,7 +663,6 @@ static void handle_kill(DBusConnection *conn, DBusMessage *msg, void *userdata)
 static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
     pa_dbusiface_stream *s = userdata;
     DBusMessage *signal_msg = NULL;
-    const char *new_device_path = NULL;
     uint32_t new_sample_rate = 0;
     pa_proplist *new_proplist = NULL;
     unsigned i = 0;
@@ -682,44 +682,6 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t
               || ((s->type == STREAM_TYPE_RECORD)
                    && ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT)));
 
-    if (s->type == STREAM_TYPE_PLAYBACK) {
-        pa_sink *new_sink = s->sink_input->sink;
-
-        if (s->sink != new_sink) {
-            pa_sink_unref(s->sink);
-            s->sink = pa_sink_ref(new_sink);
-
-            new_device_path = pa_dbusiface_core_get_sink_path(s->core, new_sink);
-
-            pa_assert_se(signal_msg = dbus_message_new_signal(s->path,
-							      PA_DBUSIFACE_STREAM_INTERFACE,
-							      signals[SIGNAL_DEVICE_UPDATED].name));
-            pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &new_device_path, DBUS_TYPE_INVALID));
-
-            pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg);
-            dbus_message_unref(signal_msg);
-            signal_msg = NULL;
-        }
-    } else {
-        pa_source *new_source = s->source_output->source;
-
-        if (s->source != new_source) {
-            pa_source_unref(s->source);
-            s->source = pa_source_ref(new_source);
-
-            new_device_path = pa_dbusiface_core_get_source_path(s->core, new_source);
-
-            pa_assert_se(signal_msg = dbus_message_new_signal(s->path,
-							      PA_DBUSIFACE_STREAM_INTERFACE,
-							      signals[SIGNAL_DEVICE_UPDATED].name));
-            pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &new_device_path, DBUS_TYPE_INVALID));
-
-            pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg);
-            dbus_message_unref(signal_msg);
-            signal_msg = NULL;
-        }
-    }
-
     new_sample_rate = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->sample_spec.rate : s->source_output->sample_spec.rate;
 
     if (s->sample_rate != new_sample_rate) {
@@ -800,6 +762,42 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t
     }
 }
 
+static pa_hook_result_t move_finish_cb(void *hook_data, void *call_data, void *slot_data) {
+    pa_dbusiface_stream *s = slot_data;
+    DBusMessage *signal_msg = NULL;
+    const char *device_path;
+
+    pa_assert(call_data);
+    pa_assert(s);
+
+    if (s->type == STREAM_TYPE_PLAYBACK) {
+        pa_sink_input *input = call_data;
+
+        if (input != s->sink_input || input->sink == s->sink)
+            return PA_HOOK_OK;
+
+        s->sink = input->sink;
+        device_path = pa_dbusiface_core_get_sink_path(s->core, s->sink);
+    } else {
+        pa_source_output *output = call_data;
+
+        if (output != s->source_output || output->source == s->source)
+            return PA_HOOK_OK;
+
+        device_path = pa_dbusiface_core_get_source_path(s->core, s->source);
+    }
+
+    pa_assert_se(signal_msg = dbus_message_new_signal(s->path,
+                                                      PA_DBUSIFACE_STREAM_INTERFACE,
+                                                      signals[SIGNAL_DEVICE_UPDATED].name));
+    pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &device_path, DBUS_TYPE_INVALID));
+
+    pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg);
+    dbus_message_unref(signal_msg);
+
+    return PA_HOOK_OK;
+}
+
 static pa_hook_result_t send_event_cb(void *hook_data, void *call_data, void *slot_data) {
     pa_dbusiface_stream *s = slot_data;
     DBusMessage *signal_msg = NULL;
@@ -852,7 +850,7 @@ pa_dbusiface_stream *pa_dbusiface_stream_new_playback(pa_dbusiface_core *core, p
     s->sink_input = pa_sink_input_ref(sink_input);
     s->type = STREAM_TYPE_PLAYBACK;
     s->path = pa_sprintf_malloc("%s/%s%u", PA_DBUS_CORE_OBJECT_PATH, PLAYBACK_OBJECT_NAME, sink_input->index);
-    s->sink = pa_sink_ref(sink_input->sink);
+    s->sink = sink_input->sink;
     s->sample_rate = sink_input->sample_spec.rate;
     s->has_volume = pa_sink_input_is_volume_readable(sink_input);
 
@@ -865,6 +863,10 @@ pa_dbusiface_stream *pa_dbusiface_stream_new_playback(pa_dbusiface_core *core, p
     s->proplist = pa_proplist_copy(sink_input->proplist);
     s->dbus_protocol = pa_dbus_protocol_get(sink_input->core);
     s->subscription = pa_subscription_new(sink_input->core, PA_SUBSCRIPTION_MASK_SINK_INPUT, subscription_cb, s);
+    s->move_finish_slot = pa_hook_connect(&sink_input->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FINISH],
+                                          PA_HOOK_NORMAL,
+                                          move_finish_cb,
+                                          s);
     s->send_event_slot = pa_hook_connect(&sink_input->core->hooks[PA_CORE_HOOK_SINK_INPUT_SEND_EVENT],
                                          PA_HOOK_NORMAL,
                                          send_event_cb,
@@ -886,7 +888,7 @@ pa_dbusiface_stream *pa_dbusiface_stream_new_record(pa_dbusiface_core *core, pa_
     s->source_output = pa_source_output_ref(source_output);
     s->type = STREAM_TYPE_RECORD;
     s->path = pa_sprintf_malloc("%s/%s%u", PA_DBUS_CORE_OBJECT_PATH, RECORD_OBJECT_NAME, source_output->index);
-    s->source = pa_source_ref(source_output->source);
+    s->source = source_output->source;
     s->sample_rate = source_output->sample_spec.rate;
     pa_cvolume_init(&s->volume);
     s->mute = FALSE;
@@ -894,6 +896,10 @@ pa_dbusiface_stream *pa_dbusiface_stream_new_record(pa_dbusiface_core *core, pa_
     s->has_volume = FALSE;
     s->dbus_protocol = pa_dbus_protocol_get(source_output->core);
     s->subscription = pa_subscription_new(source_output->core, PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscription_cb, s);
+    s->move_finish_slot = pa_hook_connect(&source_output->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_FINISH],
+                                          PA_HOOK_NORMAL,
+                                          move_finish_cb,
+                                          s);
     s->send_event_slot = pa_hook_connect(&source_output->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_SEND_EVENT],
                                          PA_HOOK_NORMAL,
                                          send_event_cb,
@@ -909,18 +915,16 @@ void pa_dbusiface_stream_free(pa_dbusiface_stream *s) {
 
     pa_assert_se(pa_dbus_protocol_remove_interface(s->dbus_protocol, s->path, stream_interface_info.name) >= 0);
 
-    if (s->type == STREAM_TYPE_PLAYBACK) {
+    if (s->type == STREAM_TYPE_PLAYBACK)
         pa_sink_input_unref(s->sink_input);
-        pa_sink_unref(s->sink);
-    } else {
+    else
         pa_source_output_unref(s->source_output);
-        pa_source_unref(s->source);
-    }
 
     pa_proplist_free(s->proplist);
     pa_dbus_protocol_unref(s->dbus_protocol);
     pa_subscription_free(s->subscription);
     pa_hook_slot_free(s->send_event_slot);
+    pa_hook_slot_free(s->move_finish_slot);
 
     pa_xfree(s->path);
     pa_xfree(s);
-- 
1.7.10.4



More information about the pulseaudio-discuss mailing list