--- 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