src/modules/dbus/iface-card.c | 69 ++--- src/modules/dbus/iface-client.c | 34 +- src/modules/dbus/iface-core.c | 511 ++++++++++++++++++++++++---------------- src/modules/dbus/iface-device.c | 121 +++++++-- src/modules/dbus/iface-stream.c | 179 +++++++++----- src/pulsecore/core.h | 2 src/pulsecore/namereg.c | 2 7 files changed, 589 insertions(+), 329 deletions(-)
New commits: commit 42eac216cf470f36e4be853b46c8105f4621a9f7 Author: Juho Hämäläinen <juho.hamalai...@tieto.com> Date: Thu Mar 19 13:50:50 2015 +0200 dbus: Use hooks for default sink and source changes [Fixes by David Henningsson <david.hennings...@canonical.com>] diff --git a/src/modules/dbus/iface-core.c b/src/modules/dbus/iface-core.c index 3d58754..41a75b1 100644 --- a/src/modules/dbus/iface-core.c +++ b/src/modules/dbus/iface-core.c @@ -109,6 +109,8 @@ struct pa_dbusiface_core { pa_sink *fallback_sink; pa_source *fallback_source; + pa_hook_slot *default_sink_changed_slot; + pa_hook_slot *default_source_changed_slot; pa_hook_slot *card_put_slot; pa_hook_slot *card_unlink_slot; pa_hook_slot *sink_input_put_slot; @@ -1576,76 +1578,14 @@ static void handle_stop_listening_for_signal(DBusConnection *conn, DBusMessage * static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { pa_dbusiface_core *c = userdata; - pa_dbusiface_device *device_iface = NULL; pa_dbusiface_sample *sample_iface = NULL; pa_dbusiface_module *module_iface = NULL; DBusMessage *signal_msg = NULL; const char *object_path = NULL; - pa_sink *new_fallback_sink = NULL; - pa_source *new_fallback_source = NULL; pa_assert(c); switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) { - case PA_SUBSCRIPTION_EVENT_SERVER: - new_fallback_sink = pa_namereg_get_default_sink(core); - new_fallback_source = pa_namereg_get_default_source(core); - - if (c->fallback_sink != new_fallback_sink) { - if (c->fallback_sink) - pa_sink_unref(c->fallback_sink); - c->fallback_sink = new_fallback_sink ? pa_sink_ref(new_fallback_sink) : NULL; - - if (c->fallback_sink) { - pa_assert_se(device_iface = pa_hashmap_get(c->sinks_by_index, PA_UINT32_TO_PTR(c->fallback_sink->index))); - object_path = pa_dbusiface_device_get_path(device_iface); - - pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, - PA_DBUS_CORE_INTERFACE, - signals[SIGNAL_FALLBACK_SINK_UPDATED].name))); - pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); - pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); - dbus_message_unref(signal_msg); - signal_msg = NULL; - - } else { - pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, - PA_DBUS_CORE_INTERFACE, - signals[SIGNAL_FALLBACK_SINK_UNSET].name))); - pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); - dbus_message_unref(signal_msg); - signal_msg = NULL; - } - } - - if (c->fallback_source != new_fallback_source) { - if (c->fallback_source) - pa_source_unref(c->fallback_source); - c->fallback_source = new_fallback_source ? pa_source_ref(new_fallback_source) : NULL; - - if (c->fallback_source) { - pa_assert_se(device_iface = pa_hashmap_get(c->sources_by_index, PA_UINT32_TO_PTR(c->fallback_source->index))); - object_path = pa_dbusiface_device_get_path(device_iface); - - pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, - PA_DBUS_CORE_INTERFACE, - signals[SIGNAL_FALLBACK_SOURCE_UPDATED].name))); - pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); - pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); - dbus_message_unref(signal_msg); - signal_msg = NULL; - - } else { - pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, - PA_DBUS_CORE_INTERFACE, - signals[SIGNAL_FALLBACK_SOURCE_UNSET].name))); - pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); - dbus_message_unref(signal_msg); - signal_msg = NULL; - } - } - break; - case PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE: if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { pa_scache_entry *sample = NULL; @@ -1721,6 +1661,82 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3 } } +static pa_hook_result_t default_sink_changed_cb(void *hook_data, void *call_data, void *slot_data) { + pa_dbusiface_core *c = slot_data; + pa_sink *new_fallback_sink = call_data; + pa_dbusiface_device *device_iface; + const char *object_path; + DBusMessage *signal_msg = NULL; + + pa_assert(c); + + if (c->fallback_sink != new_fallback_sink) { + if (c->fallback_sink) + pa_sink_unref(c->fallback_sink); + c->fallback_sink = new_fallback_sink ? pa_sink_ref(new_fallback_sink) : NULL; + + if (c->fallback_sink) { + pa_assert_se((device_iface = pa_hashmap_get(c->sinks_by_index, PA_UINT32_TO_PTR(c->fallback_sink->index)))); + object_path = pa_dbusiface_device_get_path(device_iface); + + pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_FALLBACK_SINK_UPDATED].name))); + pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + + } else { + pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_FALLBACK_SINK_UNSET].name))); + } + } + + if (signal_msg) { + pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); + dbus_message_unref(signal_msg); + } + + return PA_HOOK_OK; +} + +static pa_hook_result_t default_source_changed_cb(void *hook_data, void *call_data, void *slot_data) { + pa_dbusiface_core *c = slot_data; + pa_source *new_fallback_source = call_data; + pa_dbusiface_device *device_iface; + const char *object_path; + DBusMessage *signal_msg = NULL; + + pa_assert(c); + + if (c->fallback_source != new_fallback_source) { + if (c->fallback_source) + pa_source_unref(c->fallback_source); + c->fallback_source = new_fallback_source ? pa_source_ref(new_fallback_source) : NULL; + + if (c->fallback_source) { + pa_assert_se((device_iface = pa_hashmap_get(c->sources_by_index, PA_UINT32_TO_PTR(c->fallback_source->index)))); + object_path = pa_dbusiface_device_get_path(device_iface); + + pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_FALLBACK_SOURCE_UPDATED].name))); + pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + + } else { + pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_FALLBACK_SOURCE_UNSET].name))); + } + } + + if (signal_msg) { + pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); + dbus_message_unref(signal_msg); + } + + return PA_HOOK_OK; +} + static pa_hook_result_t card_put_cb(void *hook_data, void *call_data, void *slot_data) { pa_dbusiface_core *c = slot_data; pa_card *card = call_data; @@ -2114,6 +2130,10 @@ pa_dbusiface_core *pa_dbusiface_core_new(pa_core *core) { c->clients = pa_hashmap_new_full(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func, NULL, (pa_free_cb_t) pa_dbusiface_client_free); c->fallback_sink = pa_namereg_get_default_sink(core); c->fallback_source = pa_namereg_get_default_source(core); + c->default_sink_changed_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_DEFAULT_SINK_CHANGED], + PA_HOOK_NORMAL, default_sink_changed_cb, c); + c->default_source_changed_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_DEFAULT_SOURCE_CHANGED], + PA_HOOK_NORMAL, default_source_changed_cb, c); c->card_put_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_CARD_PUT], PA_HOOK_NORMAL, card_put_cb, c); c->card_unlink_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_CARD_UNLINK], @@ -2204,6 +2224,8 @@ void pa_dbusiface_core_free(pa_dbusiface_core *c) { pa_hashmap_free(c->samples); pa_hashmap_free(c->modules); pa_hashmap_free(c->clients); + pa_hook_slot_free(c->default_sink_changed_slot); + pa_hook_slot_free(c->default_source_changed_slot); pa_hook_slot_free(c->card_put_slot); pa_hook_slot_free(c->card_unlink_slot); pa_hook_slot_free(c->sink_input_put_slot); commit 3bb69ebfc2abffd106426e0c14bf034f5ebce319 Author: Juho Hämäläinen <juho.hamalai...@tieto.com> Date: Thu Mar 19 13:50:47 2015 +0200 dbus: Use hooks for put and unlink Use hooks for all events that have core hooks defined. Some events handled in iface-core don't have hooks so leave those for later. diff --git a/src/modules/dbus/iface-core.c b/src/modules/dbus/iface-core.c index 4563b3f..3d58754 100644 --- a/src/modules/dbus/iface-core.c +++ b/src/modules/dbus/iface-core.c @@ -109,6 +109,14 @@ struct pa_dbusiface_core { pa_sink *fallback_sink; pa_source *fallback_source; + pa_hook_slot *card_put_slot; + pa_hook_slot *card_unlink_slot; + pa_hook_slot *sink_input_put_slot; + pa_hook_slot *sink_input_unlink_slot; + pa_hook_slot *source_output_put_slot; + pa_hook_slot *source_output_unlink_slot; + pa_hook_slot *client_put_slot; + pa_hook_slot *client_unlink_slot; pa_hook_slot *sink_put_slot; pa_hook_slot *sink_unlink_slot; pa_hook_slot *source_put_slot; @@ -1568,12 +1576,9 @@ static void handle_stop_listening_for_signal(DBusConnection *conn, DBusMessage * static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { pa_dbusiface_core *c = userdata; - pa_dbusiface_card *card_iface = NULL; pa_dbusiface_device *device_iface = NULL; - pa_dbusiface_stream *stream_iface = NULL; pa_dbusiface_sample *sample_iface = NULL; pa_dbusiface_module *module_iface = NULL; - pa_dbusiface_client *client_iface = NULL; DBusMessage *signal_msg = NULL; const char *object_path = NULL; pa_sink *new_fallback_sink = NULL; @@ -1641,215 +1646,291 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3 } break; - case PA_SUBSCRIPTION_EVENT_CARD: + case PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE: if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { - if (!(card_iface = pa_hashmap_get(c->cards, PA_UINT32_TO_PTR(idx)))) { - pa_card *card = NULL; + pa_scache_entry *sample = NULL; - if (!(card = pa_idxset_get_by_index(core->cards, idx))) - return; /* The card was removed immediately after creation. */ + if (!(sample = pa_idxset_get_by_index(core->scache, idx))) + return; /* The sample was removed immediately after creation. */ - card_iface = pa_dbusiface_card_new(c, card); - pa_hashmap_put(c->cards, PA_UINT32_TO_PTR(idx), card_iface); + if (!(sample_iface = pa_hashmap_get(c->samples, PA_UINT32_TO_PTR(idx)))) { + sample_iface = pa_dbusiface_sample_new(c, sample); + pa_hashmap_put(c->samples, PA_UINT32_TO_PTR(idx), sample_iface); } - object_path = pa_dbusiface_card_get_path(card_iface); + object_path = pa_dbusiface_sample_get_path(sample_iface); pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, PA_DBUS_CORE_INTERFACE, - signals[SIGNAL_NEW_CARD].name))); + signals[SIGNAL_NEW_SAMPLE].name))); pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - if (!(card_iface = pa_hashmap_remove(c->cards, PA_UINT32_TO_PTR(idx)))) + if (!(sample_iface = pa_hashmap_remove(c->samples, PA_UINT32_TO_PTR(idx)))) return; - object_path = pa_dbusiface_card_get_path(card_iface); + object_path = pa_dbusiface_sample_get_path(sample_iface); pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, PA_DBUS_CORE_INTERFACE, - signals[SIGNAL_CARD_REMOVED].name))); + signals[SIGNAL_SAMPLE_REMOVED].name))); pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); - pa_dbusiface_card_free(card_iface); + pa_dbusiface_sample_free(sample_iface); } break; - case PA_SUBSCRIPTION_EVENT_SINK_INPUT: + case PA_SUBSCRIPTION_EVENT_MODULE: if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { - pa_sink_input *sink_input = NULL; + pa_module *module = NULL; - if (!(sink_input = pa_idxset_get_by_index(core->sink_inputs, idx))) - return; /* The sink input was removed immediately after creation. */ + if (!(module = pa_idxset_get_by_index(core->modules, idx))) + return; /* The module was removed immediately after creation. */ - if (!(stream_iface = pa_hashmap_get(c->playback_streams, PA_UINT32_TO_PTR(idx)))) { - stream_iface = pa_dbusiface_stream_new_playback(c, sink_input); - pa_hashmap_put(c->playback_streams, PA_UINT32_TO_PTR(idx), stream_iface); + if (!(module_iface = pa_hashmap_get(c->modules, PA_UINT32_TO_PTR(idx)))) { + module_iface = pa_dbusiface_module_new(module); + pa_hashmap_put(c->modules, PA_UINT32_TO_PTR(idx), module_iface); } - object_path = pa_dbusiface_stream_get_path(stream_iface); + object_path = pa_dbusiface_module_get_path(module_iface); pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, PA_DBUS_CORE_INTERFACE, - signals[SIGNAL_NEW_PLAYBACK_STREAM].name))); + signals[SIGNAL_NEW_MODULE].name))); pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - if (!(stream_iface = pa_hashmap_remove(c->playback_streams, PA_UINT32_TO_PTR(idx)))) + if (!(module_iface = pa_hashmap_remove(c->modules, PA_UINT32_TO_PTR(idx)))) return; - object_path = pa_dbusiface_stream_get_path(stream_iface); + object_path = pa_dbusiface_module_get_path(module_iface); pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, PA_DBUS_CORE_INTERFACE, - signals[SIGNAL_PLAYBACK_STREAM_REMOVED].name))); + signals[SIGNAL_MODULE_REMOVED].name))); pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); - pa_dbusiface_stream_free(stream_iface); + pa_dbusiface_module_free(module_iface); } break; + } - case PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT: - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { - pa_source_output *source_output = NULL; + if (signal_msg) { + pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); + dbus_message_unref(signal_msg); + } +} - if (!(source_output = pa_idxset_get_by_index(core->source_outputs, idx))) - return; /* The source output was removed immediately after creation. */ +static pa_hook_result_t card_put_cb(void *hook_data, void *call_data, void *slot_data) { + pa_dbusiface_core *c = slot_data; + pa_card *card = call_data; + pa_dbusiface_card *card_iface = NULL; + const char *object_path; + DBusMessage *signal_msg; - if (!(stream_iface = pa_hashmap_get(c->record_streams, PA_UINT32_TO_PTR(idx)))) { - stream_iface = pa_dbusiface_stream_new_record(c, source_output); - pa_hashmap_put(c->record_streams, PA_UINT32_TO_PTR(idx), stream_iface); - } + pa_assert(c); + pa_assert(card); - object_path = pa_dbusiface_stream_get_path(stream_iface); + card_iface = pa_dbusiface_card_new(c, card); + pa_assert_se(pa_hashmap_put(c->cards, PA_UINT32_TO_PTR(card->index), card_iface) >= 0); - pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, - PA_DBUS_CORE_INTERFACE, - signals[SIGNAL_NEW_RECORD_STREAM].name))); - pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + object_path = pa_dbusiface_card_get_path(card_iface); - } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - if (!(stream_iface = pa_hashmap_remove(c->record_streams, PA_UINT32_TO_PTR(idx)))) - return; + pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_NEW_CARD].name))); + pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); - object_path = pa_dbusiface_stream_get_path(stream_iface); + pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); + dbus_message_unref(signal_msg); - pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, - PA_DBUS_CORE_INTERFACE, - signals[SIGNAL_RECORD_STREAM_REMOVED].name))); - pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + return PA_HOOK_OK; +} - pa_dbusiface_stream_free(stream_iface); - } - break; +static pa_hook_result_t card_unlink_cb(void *hook_data, void *call_data, void *slot_data) { + pa_dbusiface_core *c = slot_data; + pa_card *card = call_data; + pa_dbusiface_card *card_iface; + const char *object_path; + DBusMessage *signal_msg; - case PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE: - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { - pa_scache_entry *sample = NULL; + pa_assert(c); + pa_assert(card); - if (!(sample = pa_idxset_get_by_index(core->scache, idx))) - return; /* The sample was removed immediately after creation. */ + pa_assert_se((card_iface = pa_hashmap_remove(c->cards, PA_UINT32_TO_PTR(card->index)))); - if (!(sample_iface = pa_hashmap_get(c->samples, PA_UINT32_TO_PTR(idx)))) { - sample_iface = pa_dbusiface_sample_new(c, sample); - pa_hashmap_put(c->samples, PA_UINT32_TO_PTR(idx), sample_iface); - } + object_path = pa_dbusiface_card_get_path(card_iface); - object_path = pa_dbusiface_sample_get_path(sample_iface); + pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_CARD_REMOVED].name))); + pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); - pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, - PA_DBUS_CORE_INTERFACE, - signals[SIGNAL_NEW_SAMPLE].name))); - pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + pa_dbusiface_card_free(card_iface); - } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - if (!(sample_iface = pa_hashmap_remove(c->samples, PA_UINT32_TO_PTR(idx)))) - return; + pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); + dbus_message_unref(signal_msg); - object_path = pa_dbusiface_sample_get_path(sample_iface); + return PA_HOOK_OK; +} - pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, - PA_DBUS_CORE_INTERFACE, - signals[SIGNAL_SAMPLE_REMOVED].name))); - pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); +static pa_hook_result_t sink_input_put_cb(void *hook_data, void *call_data, void *slot_data) { + pa_dbusiface_core *c = slot_data; + pa_sink_input *sink_input = call_data; + pa_dbusiface_stream *stream_iface; + const char *object_path; + DBusMessage *signal_msg; - pa_dbusiface_sample_free(sample_iface); - } - break; + pa_assert(c); + pa_assert(sink_input); - case PA_SUBSCRIPTION_EVENT_MODULE: - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { - pa_module *module = NULL; + stream_iface = pa_dbusiface_stream_new_playback(c, sink_input); + pa_assert_se(pa_hashmap_put(c->playback_streams, PA_UINT32_TO_PTR(sink_input->index), stream_iface) >= 0); - if (!(module = pa_idxset_get_by_index(core->modules, idx))) - return; /* The module was removed immediately after creation. */ + object_path = pa_dbusiface_stream_get_path(stream_iface); - if (!(module_iface = pa_hashmap_get(c->modules, PA_UINT32_TO_PTR(idx)))) { - module_iface = pa_dbusiface_module_new(module); - pa_hashmap_put(c->modules, PA_UINT32_TO_PTR(idx), module_iface); - } + pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_NEW_PLAYBACK_STREAM].name))); + pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); - object_path = pa_dbusiface_module_get_path(module_iface); + pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); + dbus_message_unref(signal_msg); - pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, - PA_DBUS_CORE_INTERFACE, - signals[SIGNAL_NEW_MODULE].name))); - pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + return PA_HOOK_OK; +} - } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - if (!(module_iface = pa_hashmap_remove(c->modules, PA_UINT32_TO_PTR(idx)))) - return; +static pa_hook_result_t sink_input_unlink_cb(void *hook_data, void *call_data, void *slot_data) { + pa_dbusiface_core *c = slot_data; + pa_sink_input *sink_input = call_data; + pa_dbusiface_stream *stream_iface; + const char *object_path; + DBusMessage *signal_msg; - object_path = pa_dbusiface_module_get_path(module_iface); + pa_assert(c); + pa_assert(sink_input); - pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, - PA_DBUS_CORE_INTERFACE, - signals[SIGNAL_MODULE_REMOVED].name))); - pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + pa_assert_se((stream_iface = pa_hashmap_remove(c->playback_streams, PA_UINT32_TO_PTR(sink_input->index)))); - pa_dbusiface_module_free(module_iface); - } - break; + object_path = pa_dbusiface_stream_get_path(stream_iface); - case PA_SUBSCRIPTION_EVENT_CLIENT: - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { - pa_client *client = NULL; + pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_PLAYBACK_STREAM_REMOVED].name))); + pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); - if (!(client = pa_idxset_get_by_index(core->clients, idx))) - return; /* The client was removed immediately after creation. */ + pa_dbusiface_stream_free(stream_iface); - if (!(client_iface = pa_hashmap_get(c->clients, PA_UINT32_TO_PTR(idx)))) { - client_iface = pa_dbusiface_client_new(c, client); - pa_hashmap_put(c->clients, PA_UINT32_TO_PTR(idx), client_iface); - } + pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); + dbus_message_unref(signal_msg); - object_path = pa_dbusiface_client_get_path(client_iface); + return PA_HOOK_OK; +} - pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, - PA_DBUS_CORE_INTERFACE, - signals[SIGNAL_NEW_CLIENT].name))); - pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); +static pa_hook_result_t source_output_put_cb(void *hook_data, void *call_data, void *slot_data) { + pa_dbusiface_core *c = slot_data; + pa_source_output *source_output = call_data; + pa_dbusiface_stream *stream_iface; + const char *object_path; + DBusMessage *signal_msg; - } else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - if (!(client_iface = pa_hashmap_remove(c->clients, PA_UINT32_TO_PTR(idx)))) - return; + pa_assert(c); + pa_assert(source_output); - object_path = pa_dbusiface_client_get_path(client_iface); + stream_iface = pa_dbusiface_stream_new_record(c, source_output); + pa_assert_se(pa_hashmap_put(c->record_streams, PA_UINT32_TO_PTR(source_output->index), stream_iface) >= 0); - pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, - PA_DBUS_CORE_INTERFACE, - signals[SIGNAL_CLIENT_REMOVED].name))); - pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + object_path = pa_dbusiface_stream_get_path(stream_iface); - pa_dbusiface_client_free(client_iface); - } - break; - } + pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_NEW_RECORD_STREAM].name))); + pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); - if (signal_msg) { - pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); - dbus_message_unref(signal_msg); - } + pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); + dbus_message_unref(signal_msg); + + return PA_HOOK_OK; +} + +static pa_hook_result_t source_output_unlink_cb(void *hook_data, void *call_data, void *slot_data) { + pa_dbusiface_core *c = slot_data; + pa_source_output *source_output = call_data; + pa_dbusiface_stream *stream_iface; + const char *object_path; + DBusMessage *signal_msg; + + pa_assert(c); + pa_assert(source_output); + + pa_assert_se((stream_iface = pa_hashmap_remove(c->record_streams, PA_UINT32_TO_PTR(source_output->index)))); + + object_path = pa_dbusiface_stream_get_path(stream_iface); + + pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_RECORD_STREAM_REMOVED].name))); + pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + + pa_dbusiface_stream_free(stream_iface); + + pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); + dbus_message_unref(signal_msg); + + return PA_HOOK_OK; +} + +static pa_hook_result_t client_put_cb(void *hook_data, void *call_data, void *slot_data) { + pa_dbusiface_core *c = slot_data; + pa_client *client = call_data; + pa_dbusiface_client *client_iface; + const char *object_path; + DBusMessage *signal_msg; + + pa_assert(c); + pa_assert(client); + + client_iface = pa_dbusiface_client_new(c, client); + pa_assert_se(pa_hashmap_put(c->clients, PA_UINT32_TO_PTR(client->index), client_iface) >= 0); + + object_path = pa_dbusiface_client_get_path(client_iface); + + pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_NEW_CLIENT].name))); + pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + + pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); + dbus_message_unref(signal_msg); + + return PA_HOOK_OK; +} + +static pa_hook_result_t client_unlink_cb(void *hook_data, void *call_data, void *slot_data) { + pa_dbusiface_core *c = slot_data; + pa_client *client = call_data; + pa_dbusiface_client *client_iface; + const char *object_path; + DBusMessage *signal_msg; + + pa_assert(c); + pa_assert(client); + + pa_assert_se((client_iface = pa_hashmap_remove(c->clients, PA_UINT32_TO_PTR(client->index)))); + + object_path = pa_dbusiface_client_get_path(client_iface); + + pa_assert_se((signal_msg = dbus_message_new_signal(PA_DBUS_CORE_OBJECT_PATH, + PA_DBUS_CORE_INTERFACE, + signals[SIGNAL_CLIENT_REMOVED].name))); + pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + + pa_dbusiface_client_free(client_iface); + + pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); + dbus_message_unref(signal_msg); + + return PA_HOOK_OK; } static pa_hook_result_t sink_put_cb(void *hook_data, void *call_data, void *slot_data) { @@ -2033,6 +2114,22 @@ pa_dbusiface_core *pa_dbusiface_core_new(pa_core *core) { c->clients = pa_hashmap_new_full(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func, NULL, (pa_free_cb_t) pa_dbusiface_client_free); c->fallback_sink = pa_namereg_get_default_sink(core); c->fallback_source = pa_namereg_get_default_source(core); + c->card_put_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_CARD_PUT], + PA_HOOK_NORMAL, card_put_cb, c); + c->card_unlink_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_CARD_UNLINK], + PA_HOOK_NORMAL, card_unlink_cb, c); + c->sink_input_put_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], + PA_HOOK_NORMAL, sink_input_put_cb, c); + c->sink_input_unlink_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK], + PA_HOOK_NORMAL, sink_input_unlink_cb, c); + c->source_output_put_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PUT], + PA_HOOK_NORMAL, source_output_put_cb, c); + c->source_output_unlink_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK], + PA_HOOK_NORMAL, source_output_unlink_cb, c); + c->client_put_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_CLIENT_PUT], + PA_HOOK_NORMAL, client_put_cb, c); + c->client_unlink_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_CLIENT_UNLINK], + PA_HOOK_NORMAL, client_unlink_cb, c); c->sink_put_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_NORMAL, sink_put_cb, c); c->sink_unlink_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_NORMAL, sink_unlink_cb, c); c->source_put_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_SOURCE_PUT], PA_HOOK_NORMAL, source_put_cb, c); @@ -2107,6 +2204,14 @@ void pa_dbusiface_core_free(pa_dbusiface_core *c) { pa_hashmap_free(c->samples); pa_hashmap_free(c->modules); pa_hashmap_free(c->clients); + pa_hook_slot_free(c->card_put_slot); + pa_hook_slot_free(c->card_unlink_slot); + pa_hook_slot_free(c->sink_input_put_slot); + pa_hook_slot_free(c->sink_input_unlink_slot); + pa_hook_slot_free(c->source_output_put_slot); + pa_hook_slot_free(c->source_output_unlink_slot); + pa_hook_slot_free(c->client_put_slot); + pa_hook_slot_free(c->client_unlink_slot); pa_hook_slot_free(c->sink_put_slot); pa_hook_slot_free(c->sink_unlink_slot); pa_hook_slot_free(c->source_put_slot); commit 297fdb5c2586a6bcd1274b7559e59b2cd55071ff Author: Juho Hämäläinen <juho.hamalai...@tieto.com> Date: Thu Mar 19 13:50:49 2015 +0200 namereg: Fire hooks for default sink and source changes diff --git a/src/pulsecore/namereg.c b/src/pulsecore/namereg.c index b2320c0..47bfc08 100644 --- a/src/pulsecore/namereg.c +++ b/src/pulsecore/namereg.c @@ -257,6 +257,7 @@ pa_sink* pa_namereg_set_default_sink(pa_core*c, pa_sink *s) { if (c->default_sink != s) { c->default_sink = s; + pa_hook_fire(&c->hooks[PA_CORE_HOOK_DEFAULT_SINK_CHANGED], c->default_sink); pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SERVER|PA_SUBSCRIPTION_EVENT_CHANGE, PA_INVALID_INDEX); } @@ -271,6 +272,7 @@ pa_source* pa_namereg_set_default_source(pa_core*c, pa_source *s) { if (c->default_source != s) { c->default_source = s; + pa_hook_fire(&c->hooks[PA_CORE_HOOK_DEFAULT_SOURCE_CHANGED], c->default_source); pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SERVER|PA_SUBSCRIPTION_EVENT_CHANGE, PA_INVALID_INDEX); } commit 88d672449370e83825797188abc1c9199c9c0281 Author: Juho Hämäläinen <juho.hamalai...@tieto.com> Date: Thu Mar 19 13:50:48 2015 +0200 core: Add hooks for default sink and source changes diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h index 8570d47..9fefd1b 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -126,6 +126,8 @@ typedef enum pa_core_hook { PA_CORE_HOOK_CARD_PROFILE_AVAILABLE_CHANGED, PA_CORE_HOOK_PORT_AVAILABLE_CHANGED, PA_CORE_HOOK_PORT_LATENCY_OFFSET_CHANGED, + PA_CORE_HOOK_DEFAULT_SINK_CHANGED, + PA_CORE_HOOK_DEFAULT_SOURCE_CHANGED, PA_CORE_HOOK_MAX } pa_core_hook_t; commit 86fcc3f44518d020f824d50b7806b48b891e9119 Author: Juho Hämäläinen <juho.hamalai...@tieto.com> Date: Thu Mar 19 13:50:46 2015 +0200 dbus: Use state changed hook for sink-input and source-output rate changes diff --git a/src/modules/dbus/iface-stream.c b/src/modules/dbus/iface-stream.c index 566759e..ade62ca 100644 --- a/src/modules/dbus/iface-stream.c +++ b/src/modules/dbus/iface-stream.c @@ -62,6 +62,7 @@ struct pa_dbusiface_stream { pa_hook_slot *volume_changed_slot; pa_hook_slot *mute_changed_slot; pa_hook_slot *proplist_changed_slot; + pa_hook_slot *state_changed_slot; }; static void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata); @@ -830,6 +831,20 @@ static pa_hook_result_t proplist_changed_cb(void *hook_data, void *call_data, vo return PA_HOOK_OK; } +static pa_hook_result_t state_changed_cb(void *hook_data, void *call_data, void *slot_data) { + pa_dbusiface_stream *s = slot_data; + + pa_assert(s); + + if ((s->type == STREAM_TYPE_PLAYBACK && s->sink_input != call_data) || + (s->type == STREAM_TYPE_RECORD && s->source_output != call_data)) + return PA_HOOK_OK; + + check_and_signal_rate(s); + + 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; @@ -906,6 +921,8 @@ pa_dbusiface_stream *pa_dbusiface_stream_new_playback(pa_dbusiface_core *core, p PA_HOOK_NORMAL, mute_changed_cb, s); s->proplist_changed_slot = pa_hook_connect(&sink_input->core->hooks[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED], PA_HOOK_NORMAL, proplist_changed_cb, s); + s->state_changed_slot = pa_hook_connect(&sink_input->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], + PA_HOOK_NORMAL, state_changed_cb, s); pa_assert_se(pa_dbus_protocol_add_interface(s->dbus_protocol, s->path, &stream_interface_info, s) >= 0); @@ -942,6 +959,8 @@ pa_dbusiface_stream *pa_dbusiface_stream_new_record(pa_dbusiface_core *core, pa_ PA_HOOK_NORMAL, mute_changed_cb, s); s->proplist_changed_slot = pa_hook_connect(&source_output->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PROPLIST_CHANGED], PA_HOOK_NORMAL, proplist_changed_cb, s); + s->state_changed_slot = pa_hook_connect(&source_output->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_STATE_CHANGED], + PA_HOOK_NORMAL, state_changed_cb, s); pa_assert_se(pa_dbus_protocol_add_interface(s->dbus_protocol, s->path, &stream_interface_info, s) >= 0); @@ -968,6 +987,7 @@ void pa_dbusiface_stream_free(pa_dbusiface_stream *s) { pa_hook_slot_free(s->volume_changed_slot); pa_hook_slot_free(s->mute_changed_slot); pa_hook_slot_free(s->proplist_changed_slot); + pa_hook_slot_free(s->state_changed_slot); pa_xfree(s->path); pa_xfree(s); commit 7f83817eddc91f6a2f017e658c00625aeec65b2f Author: Juho Hämäläinen <juho.hamalai...@tieto.com> Date: Thu Mar 19 13:50:45 2015 +0200 dbus: Use hooks for sink-input and source-output events diff --git a/src/modules/dbus/iface-stream.c b/src/modules/dbus/iface-stream.c index 144817d..566759e 100644 --- a/src/modules/dbus/iface-stream.c +++ b/src/modules/dbus/iface-stream.c @@ -57,8 +57,11 @@ struct pa_dbusiface_stream { bool has_volume; pa_dbus_protocol *dbus_protocol; - pa_subscription *subscription; pa_hook_slot *send_event_slot; + pa_hook_slot *move_finish_slot; + pa_hook_slot *volume_changed_slot; + pa_hook_slot *mute_changed_slot; + pa_hook_slot *proplist_changed_slot; }; static void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata); @@ -657,28 +660,37 @@ static void handle_kill(DBusConnection *conn, DBusMessage *msg, void *userdata) pa_dbus_send_empty_reply(conn, msg); } -static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { - pa_dbusiface_stream *s = userdata; +static void check_and_signal_rate(pa_dbusiface_stream *s) { DBusMessage *signal_msg = NULL; - const char *new_device_path = NULL; uint32_t new_sample_rate = 0; - pa_proplist *new_proplist = NULL; - unsigned i = 0; - pa_assert(c); pa_assert(s); - if ((s->type == STREAM_TYPE_PLAYBACK && idx != s->sink_input->index) - || (s->type == STREAM_TYPE_RECORD && idx != s->source_output->index)) - return; + new_sample_rate = (s->type == STREAM_TYPE_PLAYBACK) + ? s->sink_input->sample_spec.rate + : s->source_output->sample_spec.rate; - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_CHANGE) - return; + if (s->sample_rate != new_sample_rate) { + s->sample_rate = new_sample_rate; - pa_assert(((s->type == STREAM_TYPE_PLAYBACK) - && ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT)) - || ((s->type == STREAM_TYPE_RECORD) - && ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT))); + pa_assert_se(signal_msg = dbus_message_new_signal(s->path, + PA_DBUSIFACE_STREAM_INTERFACE, + signals[SIGNAL_SAMPLE_RATE_UPDATED].name)); + pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_UINT32, &s->sample_rate, DBUS_TYPE_INVALID)); + + pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg); + dbus_message_unref(signal_msg); + } +} + +static pa_hook_result_t move_finish_cb(void *hook_data, void *call_data, void *slot_data) { + pa_dbusiface_stream *s = slot_data; + const char *new_device_path = NULL; + DBusMessage *signal_msg = NULL; + + if ((s->type == STREAM_TYPE_PLAYBACK && s->sink_input != call_data) || + (s->type == STREAM_TYPE_RECORD && s->source_output != call_data)) + return PA_HOOK_OK; if (s->type == STREAM_TYPE_PLAYBACK) { pa_sink *new_sink = s->sink_input->sink; @@ -696,7 +708,6 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t 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; @@ -714,54 +725,62 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t 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) { - s->sample_rate = new_sample_rate; + check_and_signal_rate(s); - pa_assert_se(signal_msg = dbus_message_new_signal(s->path, - PA_DBUSIFACE_STREAM_INTERFACE, - signals[SIGNAL_SAMPLE_RATE_UPDATED].name)); - pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_UINT32, &s->sample_rate, DBUS_TYPE_INVALID)); + return PA_HOOK_OK; +} - pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg); - dbus_message_unref(signal_msg); - signal_msg = NULL; - } +static pa_hook_result_t volume_changed_cb(void *hook_data, void *call_data, void *slot_data) { + pa_dbusiface_stream *s = slot_data; + DBusMessage *signal_msg = NULL; + unsigned i = 0; - if (s->type == STREAM_TYPE_PLAYBACK) { - bool new_mute = false; + if ((s->type == STREAM_TYPE_PLAYBACK && s->sink_input != call_data) || + (s->type == STREAM_TYPE_RECORD && s->source_output != call_data)) + return PA_HOOK_OK; - if (s->has_volume) { - pa_cvolume new_volume; + if (s->type == STREAM_TYPE_PLAYBACK && s->has_volume) { + pa_cvolume new_volume; - pa_sink_input_get_volume(s->sink_input, &new_volume, true); + pa_sink_input_get_volume(s->sink_input, &new_volume, true); - if (!pa_cvolume_equal(&s->volume, &new_volume)) { - dbus_uint32_t volume[PA_CHANNELS_MAX]; - dbus_uint32_t *volume_ptr = volume; + if (!pa_cvolume_equal(&s->volume, &new_volume)) { + dbus_uint32_t volume[PA_CHANNELS_MAX]; + dbus_uint32_t *volume_ptr = volume; - s->volume = new_volume; + s->volume = new_volume; - for (i = 0; i < s->volume.channels; ++i) - volume[i] = s->volume.values[i]; + for (i = 0; i < s->volume.channels; ++i) + volume[i] = s->volume.values[i]; - pa_assert_se(signal_msg = dbus_message_new_signal(s->path, - PA_DBUSIFACE_STREAM_INTERFACE, - signals[SIGNAL_VOLUME_UPDATED].name)); - pa_assert_se(dbus_message_append_args(signal_msg, - DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &volume_ptr, s->volume.channels, - DBUS_TYPE_INVALID)); + pa_assert_se(signal_msg = dbus_message_new_signal(s->path, + PA_DBUSIFACE_STREAM_INTERFACE, + signals[SIGNAL_VOLUME_UPDATED].name)); + pa_assert_se(dbus_message_append_args(signal_msg, + DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &volume_ptr, s->volume.channels, + DBUS_TYPE_INVALID)); - pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg); - dbus_message_unref(signal_msg); - signal_msg = NULL; - } + pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg); + dbus_message_unref(signal_msg); } + } + + return PA_HOOK_OK; +} + +static pa_hook_result_t mute_changed_cb(void *hook_data, void *call_data, void *slot_data) { + pa_dbusiface_stream *s = slot_data; + DBusMessage *signal_msg = NULL; + + if ((s->type == STREAM_TYPE_PLAYBACK && s->sink_input != call_data) || + (s->type == STREAM_TYPE_RECORD && s->source_output != call_data)) + return PA_HOOK_OK; + + if (s->type == STREAM_TYPE_PLAYBACK) { + bool new_mute = false; new_mute = s->sink_input->muted; @@ -779,6 +798,18 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t } } + return PA_HOOK_OK; +} + +static pa_hook_result_t proplist_changed_cb(void *hook_data, void *call_data, void *slot_data) { + pa_dbusiface_stream *s = slot_data; + DBusMessage *signal_msg = NULL; + pa_proplist *new_proplist = NULL; + + if ((s->type == STREAM_TYPE_PLAYBACK && s->sink_input != call_data) || + (s->type == STREAM_TYPE_RECORD && s->source_output != call_data)) + return PA_HOOK_OK; + new_proplist = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->proplist : s->source_output->proplist; if (!pa_proplist_equal(s->proplist, new_proplist)) { @@ -794,8 +825,9 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg); dbus_message_unref(signal_msg); - signal_msg = NULL; } + + return PA_HOOK_OK; } static pa_hook_result_t send_event_cb(void *hook_data, void *call_data, void *slot_data) { @@ -862,11 +894,18 @@ pa_dbusiface_stream *pa_dbusiface_stream_new_playback(pa_dbusiface_core *core, p s->mute = sink_input->muted; 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->send_event_slot = pa_hook_connect(&sink_input->core->hooks[PA_CORE_HOOK_SINK_INPUT_SEND_EVENT], PA_HOOK_NORMAL, send_event_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->volume_changed_slot = pa_hook_connect(&sink_input->core->hooks[PA_CORE_HOOK_SINK_INPUT_VOLUME_CHANGED], + PA_HOOK_NORMAL, volume_changed_cb, s); + s->mute_changed_slot = pa_hook_connect(&sink_input->core->hooks[PA_CORE_HOOK_SINK_INPUT_MUTE_CHANGED], + PA_HOOK_NORMAL, mute_changed_cb, s); + s->proplist_changed_slot = pa_hook_connect(&sink_input->core->hooks[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED], + PA_HOOK_NORMAL, proplist_changed_cb, s); pa_assert_se(pa_dbus_protocol_add_interface(s->dbus_protocol, s->path, &stream_interface_info, s) >= 0); @@ -891,11 +930,18 @@ pa_dbusiface_stream *pa_dbusiface_stream_new_record(pa_dbusiface_core *core, pa_ s->proplist = pa_proplist_copy(source_output->proplist); 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->send_event_slot = pa_hook_connect(&source_output->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_SEND_EVENT], PA_HOOK_NORMAL, send_event_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->volume_changed_slot = pa_hook_connect(&source_output->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_VOLUME_CHANGED], + PA_HOOK_NORMAL, volume_changed_cb, s); + s->mute_changed_slot = pa_hook_connect(&source_output->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MUTE_CHANGED], + PA_HOOK_NORMAL, mute_changed_cb, s); + s->proplist_changed_slot = pa_hook_connect(&source_output->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PROPLIST_CHANGED], + PA_HOOK_NORMAL, proplist_changed_cb, s); pa_assert_se(pa_dbus_protocol_add_interface(s->dbus_protocol, s->path, &stream_interface_info, s) >= 0); @@ -917,8 +963,11 @@ void pa_dbusiface_stream_free(pa_dbusiface_stream *s) { 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_hook_slot_free(s->volume_changed_slot); + pa_hook_slot_free(s->mute_changed_slot); + pa_hook_slot_free(s->proplist_changed_slot); pa_xfree(s->path); pa_xfree(s); commit 5087af78d50409ddcb9ef33b7c2df8896b4cb96d Author: Juho Hämäläinen <juho.hamalai...@tieto.com> Date: Thu Mar 19 13:50:44 2015 +0200 dbus: Use hooks for sink and source events diff --git a/src/modules/dbus/iface-device.c b/src/modules/dbus/iface-device.c index efa4141..2c370a8 100644 --- a/src/modules/dbus/iface-device.c +++ b/src/modules/dbus/iface-device.c @@ -94,8 +94,13 @@ struct pa_dbusiface_device { pa_device_port *active_port; pa_proplist *proplist; + pa_hook_slot *volume_changed_slot; + pa_hook_slot *mute_changed_slot; + pa_hook_slot *state_changed_slot; + pa_hook_slot *port_changed_slot; + pa_hook_slot *proplist_changed_slot; + pa_dbus_protocol *dbus_protocol; - pa_subscription *subscription; }; enum property_handler_index { @@ -1077,30 +1082,15 @@ static void handle_source_get_all(DBusConnection *conn, DBusMessage *msg, void * dbus_message_unref(reply); } -static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { - pa_dbusiface_device *d = userdata; +static pa_hook_result_t volume_changed_cb(void *hook_data, void *call_data, void *slot_data) { + pa_dbusiface_device *d = slot_data; DBusMessage *signal_msg = NULL; const pa_cvolume *new_volume = NULL; - bool new_mute = false; - pa_sink_state_t new_sink_state = 0; - pa_source_state_t new_source_state = 0; - pa_device_port *new_active_port = NULL; - pa_proplist *new_proplist = NULL; unsigned i = 0; - pa_assert(c); - pa_assert(d); - - if ((d->type == PA_DEVICE_TYPE_SINK && idx != d->sink->index) || (d->type == PA_DEVICE_TYPE_SOURCE && idx != d->source->index)) - return; - - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_CHANGE) - return; - - pa_assert(((d->type == PA_DEVICE_TYPE_SINK) - && ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK)) - || ((d->type == PA_DEVICE_TYPE_SOURCE) - && ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE))); + if ((d->type == PA_DEVICE_TYPE_SINK && d->sink != call_data) || + (d->type == PA_DEVICE_TYPE_SOURCE && d->source != call_data)) + return PA_HOOK_OK; new_volume = (d->type == PA_DEVICE_TYPE_SINK) ? pa_sink_get_volume(d->sink, false) @@ -1124,10 +1114,23 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t pa_dbus_protocol_send_signal(d->dbus_protocol, signal_msg); dbus_message_unref(signal_msg); - signal_msg = NULL; } - new_mute = (d->type == PA_DEVICE_TYPE_SINK) ? pa_sink_get_mute(d->sink, false) : pa_source_get_mute(d->source, false); + return PA_HOOK_OK; +} + +static pa_hook_result_t mute_changed_cb(void *hook_data, void *call_data, void *slot_data) { + pa_dbusiface_device *d = slot_data; + DBusMessage *signal_msg = NULL; + bool new_mute = false; + + if ((d->type == PA_DEVICE_TYPE_SINK && d->sink != call_data) || + (d->type == PA_DEVICE_TYPE_SOURCE && d->source != call_data)) + return PA_HOOK_OK; + + new_mute = (d->type == PA_DEVICE_TYPE_SINK) + ? pa_sink_get_mute(d->sink, false) + : pa_source_get_mute(d->source, false); if (d->mute != new_mute) { d->mute = new_mute; @@ -1139,9 +1142,21 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t pa_dbus_protocol_send_signal(d->dbus_protocol, signal_msg); dbus_message_unref(signal_msg); - signal_msg = NULL; } + return PA_HOOK_OK; +} + +static pa_hook_result_t state_changed_cb(void *hook_data, void *call_data, void *slot_data) { + pa_dbusiface_device *d = slot_data; + DBusMessage *signal_msg = NULL; + pa_sink_state_t new_sink_state = 0; + pa_source_state_t new_source_state = 0; + + if ((d->type == PA_DEVICE_TYPE_SINK && d->sink != call_data) || + (d->type == PA_DEVICE_TYPE_SOURCE && d->source != call_data)) + return PA_HOOK_OK; + if (d->type == PA_DEVICE_TYPE_SINK) new_sink_state = pa_sink_get_state(d->sink); else @@ -1165,9 +1180,20 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t pa_dbus_protocol_send_signal(d->dbus_protocol, signal_msg); dbus_message_unref(signal_msg); - signal_msg = NULL; } + return PA_HOOK_OK; +} + +static pa_hook_result_t port_changed_cb(void *hook_data, void *call_data, void *slot_data) { + pa_dbusiface_device *d = slot_data; + DBusMessage *signal_msg = NULL; + pa_device_port *new_active_port = NULL; + + if ((d->type == PA_DEVICE_TYPE_SINK && d->sink != call_data) || + (d->type == PA_DEVICE_TYPE_SOURCE && d->source != call_data)) + return PA_HOOK_OK; + new_active_port = (d->type == PA_DEVICE_TYPE_SINK) ? d->sink->active_port : d->source->active_port; if (d->active_port != new_active_port) { @@ -1183,9 +1209,20 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t pa_dbus_protocol_send_signal(d->dbus_protocol, signal_msg); dbus_message_unref(signal_msg); - signal_msg = NULL; } + return PA_HOOK_OK; +} + +static pa_hook_result_t proplist_changed_cb(void *hook_data, void *call_data, void *slot_data) { + pa_dbusiface_device *d = slot_data; + DBusMessage *signal_msg = NULL; + pa_proplist *new_proplist = NULL; + + if ((d->type == PA_DEVICE_TYPE_SINK && d->sink != call_data) || + (d->type == PA_DEVICE_TYPE_SOURCE && d->source != call_data)) + return PA_HOOK_OK; + new_proplist = (d->type == PA_DEVICE_TYPE_SINK) ? d->sink->proplist : d->source->proplist; if (!pa_proplist_equal(d->proplist, new_proplist)) { @@ -1201,8 +1238,9 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t pa_dbus_protocol_send_signal(d->dbus_protocol, signal_msg); dbus_message_unref(signal_msg); - signal_msg = NULL; } + + return PA_HOOK_OK; } pa_dbusiface_device *pa_dbusiface_device_new_sink(pa_dbusiface_core *core, pa_sink *sink) { @@ -1226,7 +1264,16 @@ pa_dbusiface_device *pa_dbusiface_device_new_sink(pa_dbusiface_core *core, pa_si d->active_port = sink->active_port; d->proplist = pa_proplist_copy(sink->proplist); d->dbus_protocol = pa_dbus_protocol_get(sink->core); - d->subscription = pa_subscription_new(sink->core, PA_SUBSCRIPTION_MASK_SINK, subscription_cb, d); + d->volume_changed_slot = pa_hook_connect(&sink->core->hooks[PA_CORE_HOOK_SINK_VOLUME_CHANGED], + PA_HOOK_NORMAL, volume_changed_cb, d); + d->mute_changed_slot = pa_hook_connect(&sink->core->hooks[PA_CORE_HOOK_SINK_MUTE_CHANGED], + PA_HOOK_NORMAL, mute_changed_cb, d); + d->state_changed_slot = pa_hook_connect(&sink->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], + PA_HOOK_NORMAL, state_changed_cb, d); + d->port_changed_slot = pa_hook_connect(&sink->core->hooks[PA_CORE_HOOK_SINK_PORT_CHANGED], + PA_HOOK_NORMAL, port_changed_cb, d); + d->proplist_changed_slot = pa_hook_connect(&sink->core->hooks[PA_CORE_HOOK_SINK_PROPLIST_CHANGED], + PA_HOOK_NORMAL, proplist_changed_cb, d); PA_HASHMAP_FOREACH(port, sink->ports, state) { pa_dbusiface_device_port *p = pa_dbusiface_device_port_new(d, sink->core, port, d->next_port_index++); @@ -1260,7 +1307,16 @@ pa_dbusiface_device *pa_dbusiface_device_new_source(pa_dbusiface_core *core, pa_ d->active_port = source->active_port; d->proplist = pa_proplist_copy(source->proplist); d->dbus_protocol = pa_dbus_protocol_get(source->core); - d->subscription = pa_subscription_new(source->core, PA_SUBSCRIPTION_MASK_SOURCE, subscription_cb, d); + d->volume_changed_slot = pa_hook_connect(&source->core->hooks[PA_CORE_HOOK_SOURCE_VOLUME_CHANGED], + PA_HOOK_NORMAL, volume_changed_cb, d); + d->mute_changed_slot = pa_hook_connect(&source->core->hooks[PA_CORE_HOOK_SOURCE_MUTE_CHANGED], + PA_HOOK_NORMAL, mute_changed_cb, d); + d->state_changed_slot = pa_hook_connect(&source->core->hooks[PA_CORE_HOOK_SOURCE_STATE_CHANGED], + PA_HOOK_NORMAL, state_changed_cb, d); + d->port_changed_slot = pa_hook_connect(&source->core->hooks[PA_CORE_HOOK_SOURCE_PORT_CHANGED], + PA_HOOK_NORMAL, port_changed_cb, d); + d->proplist_changed_slot = pa_hook_connect(&source->core->hooks[PA_CORE_HOOK_SOURCE_PROPLIST_CHANGED], + PA_HOOK_NORMAL, proplist_changed_cb, d); PA_HASHMAP_FOREACH(port, source->ports, state) { pa_dbusiface_device_port *p = pa_dbusiface_device_port_new(d, source->core, port, d->next_port_index++); @@ -1276,6 +1332,12 @@ pa_dbusiface_device *pa_dbusiface_device_new_source(pa_dbusiface_core *core, pa_ void pa_dbusiface_device_free(pa_dbusiface_device *d) { pa_assert(d); + pa_hook_slot_free(d->volume_changed_slot); + pa_hook_slot_free(d->mute_changed_slot); + pa_hook_slot_free(d->state_changed_slot); + pa_hook_slot_free(d->port_changed_slot); + pa_hook_slot_free(d->proplist_changed_slot); + pa_assert_se(pa_dbus_protocol_remove_interface(d->dbus_protocol, d->path, device_interface_info.name) >= 0); if (d->type == PA_DEVICE_TYPE_SINK) { @@ -1289,7 +1351,6 @@ void pa_dbusiface_device_free(pa_dbusiface_device *d) { pa_hashmap_free(d->ports); pa_proplist_free(d->proplist); pa_dbus_protocol_unref(d->dbus_protocol); - pa_subscription_free(d->subscription); pa_xfree(d->path); pa_xfree(d); commit 36c3f01cb2d5053bf3ed353fa70f1330608ef646 Author: Juho Hämäläinen <juho.hamalai...@tieto.com> Date: Thu Mar 19 13:50:43 2015 +0200 dbus: Use hooks for client proplist changes diff --git a/src/modules/dbus/iface-client.c b/src/modules/dbus/iface-client.c index 76ad427..455ea45 100644 --- a/src/modules/dbus/iface-client.c +++ b/src/modules/dbus/iface-client.c @@ -39,8 +39,9 @@ struct pa_dbusiface_client { char *path; pa_proplist *proplist; + pa_hook_slot *client_proplist_changed_slot; + pa_dbus_protocol *dbus_protocol; - pa_subscription *subscription; }; static void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata); @@ -381,27 +382,24 @@ static void handle_remove_properties(DBusConnection *conn, DBusMessage *msg, voi pa_dbus_send_empty_reply(conn, msg); - if (changed) + if (changed) { + pa_hook_fire(&c->client->core->hooks[PA_CORE_HOOK_CLIENT_PROPLIST_CHANGED], c->client); pa_subscription_post(c->client->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_CHANGE, c->client->index); + } dbus_free_string_array(keys); } -static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { - pa_dbusiface_client *c = userdata; - DBusMessage *signal_msg = NULL; +static pa_hook_result_t client_proplist_changed_cb(void *hook_data, void *call_data, void *slot_data) { + pa_dbusiface_client *c = slot_data; + pa_client *client = call_data; + DBusMessage *signal_msg; - pa_assert(core); - pa_assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_CLIENT); pa_assert(c); + pa_assert(client); - /* We can't use idx != c->client->index, because the c->client pointer may - * be stale at this point. */ - if (pa_idxset_get_by_index(core->clients, idx) != c->client) - return; - - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_CHANGE) - return; + if (c->client != client) + return PA_HOOK_OK; if (!pa_proplist_equal(c->proplist, c->client->proplist)) { DBusMessageIter msg_iter; @@ -416,8 +414,9 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3 pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); dbus_message_unref(signal_msg); - signal_msg = NULL; } + + return PA_HOOK_OK; } pa_dbusiface_client *pa_dbusiface_client_new(pa_dbusiface_core *core, pa_client *client) { @@ -432,7 +431,8 @@ pa_dbusiface_client *pa_dbusiface_client_new(pa_dbusiface_core *core, pa_client c->path = pa_sprintf_malloc("%s/%s%u", PA_DBUS_CORE_OBJECT_PATH, OBJECT_NAME, client->index); c->proplist = pa_proplist_copy(client->proplist); c->dbus_protocol = pa_dbus_protocol_get(client->core); - c->subscription = pa_subscription_new(client->core, PA_SUBSCRIPTION_MASK_CLIENT, subscription_cb, c); + c->client_proplist_changed_slot = pa_hook_connect(&client->core->hooks[PA_CORE_HOOK_CLIENT_PROPLIST_CHANGED], + PA_HOOK_NORMAL, client_proplist_changed_cb, c); pa_assert_se(pa_dbus_protocol_add_interface(c->dbus_protocol, c->path, &client_interface_info, c) >= 0); @@ -444,9 +444,9 @@ void pa_dbusiface_client_free(pa_dbusiface_client *c) { pa_assert_se(pa_dbus_protocol_remove_interface(c->dbus_protocol, c->path, client_interface_info.name) >= 0); + pa_hook_slot_free(c->client_proplist_changed_slot); pa_proplist_free(c->proplist); pa_dbus_protocol_unref(c->dbus_protocol); - pa_subscription_free(c->subscription); pa_xfree(c->path); pa_xfree(c); commit c324255e3ead80e85f873b0995f5ddc9a2904454 Author: Juho Hämäläinen <juho.hamalai...@tieto.com> Date: Thu Mar 19 13:50:42 2015 +0200 dbus: Use hooks for card profile events diff --git a/src/modules/dbus/iface-card.c b/src/modules/dbus/iface-card.c index da975c8..d0f13c9 100644 --- a/src/modules/dbus/iface-card.c +++ b/src/modules/dbus/iface-card.c @@ -59,9 +59,9 @@ struct pa_dbusiface_card { pa_proplist *proplist; pa_hook_slot *card_profile_added_slot; + pa_hook_slot *card_profile_changed_slot; pa_dbus_protocol *dbus_protocol; - pa_subscription *subscription; }; enum property_handler_index { @@ -432,37 +432,8 @@ static void handle_get_profile_by_name(DBusConnection *conn, DBusMessage *msg, v pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &profile_path); } -static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { - pa_dbusiface_card *c = userdata; - DBusMessage *signal_msg = NULL; - - pa_assert(core); - pa_assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_CARD); - pa_assert(c); - - /* We can't use idx != c->card->index, because the c->card pointer may - * be stale at this point. */ - if (pa_idxset_get_by_index(core->cards, idx) != c->card) - return; - - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_CHANGE) - return; - - if (c->active_profile != c->card->active_profile) { - const char *object_path; - - c->active_profile = c->card->active_profile; - object_path = pa_dbusiface_card_profile_get_path(pa_hashmap_get(c->profiles, c->active_profile->name)); - - pa_assert_se(signal_msg = dbus_message_new_signal(c->path, - PA_DBUSIFACE_CARD_INTERFACE, - signals[SIGNAL_ACTIVE_PROFILE_UPDATED].name)); - pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); - - pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); - dbus_message_unref(signal_msg); - signal_msg = NULL; - } +static void check_card_proplist(pa_dbusiface_card *c) { + DBusMessage *signal_msg; if (!pa_proplist_equal(c->proplist, c->card->proplist)) { DBusMessageIter msg_iter; @@ -477,10 +448,35 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3 pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); dbus_message_unref(signal_msg); - signal_msg = NULL; } } +static pa_hook_result_t card_profile_changed_cb(void *hook_data, void *call_data, void *slot_data) { + pa_dbusiface_card *c = slot_data; + pa_card_profile *profile = call_data; + const char *object_path; + DBusMessage *signal_msg; + + if (profile->card != c->card) + return PA_HOOK_OK; + + c->active_profile = c->card->active_profile; + + object_path = pa_dbusiface_card_profile_get_path(pa_hashmap_get(c->profiles, c->active_profile->name)); + + pa_assert_se(signal_msg = dbus_message_new_signal(c->path, + PA_DBUSIFACE_CARD_INTERFACE, + signals[SIGNAL_ACTIVE_PROFILE_UPDATED].name)); + pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID)); + + pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); + dbus_message_unref(signal_msg); + + check_card_proplist(c); + + return PA_HOOK_OK; +} + static pa_hook_result_t card_profile_added_cb(void *hook_data, void *call_data, void *slot_data) { pa_core *core = hook_data; pa_dbusiface_card *c = slot_data; @@ -506,6 +502,8 @@ static pa_hook_result_t card_profile_added_cb(void *hook_data, void *call_data, pa_dbus_protocol_send_signal(c->dbus_protocol, signal_msg); dbus_message_unref(signal_msg); + check_card_proplist(c); + return PA_HOOK_OK; } @@ -527,7 +525,6 @@ pa_dbusiface_card *pa_dbusiface_card_new(pa_dbusiface_core *core, pa_card *card) c->active_profile = card->active_profile; c->proplist = pa_proplist_copy(card->proplist); c->dbus_protocol = pa_dbus_protocol_get(card->core); - c->subscription = pa_subscription_new(card->core, PA_SUBSCRIPTION_MASK_CARD, subscription_cb, c); PA_HASHMAP_FOREACH(profile, card->profiles, state) { pa_dbusiface_card_profile *p = pa_dbusiface_card_profile_new(c, card->core, profile, c->next_profile_index++); @@ -536,6 +533,8 @@ pa_dbusiface_card *pa_dbusiface_card_new(pa_dbusiface_core *core, pa_card *card) pa_assert_se(pa_dbus_protocol_add_interface(c->dbus_protocol, c->path, &card_interface_info, c) >= 0); + c->card_profile_changed_slot = pa_hook_connect(&card->core->hooks[PA_CORE_HOOK_CARD_PROFILE_CHANGED], PA_HOOK_NORMAL, + card_profile_changed_cb, c); c->card_profile_added_slot = pa_hook_connect(&card->core->hooks[PA_CORE_HOOK_CARD_PROFILE_ADDED], PA_HOOK_NORMAL, card_profile_added_cb, c); @@ -548,11 +547,11 @@ void pa_dbusiface_card_free(pa_dbusiface_card *c) { pa_assert_se(pa_dbus_protocol_remove_interface(c->dbus_protocol, c->path, card_interface_info.name) >= 0); pa_hook_slot_free(c->card_profile_added_slot); + pa_hook_slot_free(c->card_profile_changed_slot); pa_hashmap_free(c->profiles); pa_proplist_free(c->proplist); pa_dbus_protocol_unref(c->dbus_protocol); - pa_subscription_free(c->subscription); pa_xfree(c->path); pa_xfree(c);
_______________________________________________ pulseaudio-commits mailing list pulseaudio-commits@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pulseaudio-commits