On 02/20/2013 07:23 PM, Tanu Kaskinen wrote: > --- > src/modules/dbus/iface-core.c | 173 +++++++++++++++++------------------------ > 1 file changed, 72 insertions(+), 101 deletions(-) > > diff --git a/src/modules/dbus/iface-core.c b/src/modules/dbus/iface-core.c > index a9716bc..4621726 100644 > --- a/src/modules/dbus/iface-core.c > +++ b/src/modules/dbus/iface-core.c > @@ -108,9 +108,8 @@ struct pa_dbusiface_core { > pa_hashmap *modules; > pa_hashmap *clients; > > - 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 *sink_put_slot; > pa_hook_slot *sink_unlink_slot; > pa_hook_slot *source_put_slot; > @@ -677,13 +676,12 @@ static void handle_get_fallback_sink(DBusConnection *conn, DBusMessage *msg, voi > pa_assert(msg); > pa_assert(c); > > - if (!c->fallback_sink) { > - pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, > - "There are no sinks, and therefore no fallback sink either."); > + if (!c->core->default_sink) { > + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "No fallback sink set."); > return; > } Is there a reason for using core->default_sink instead of pa_namereg_get_default_sink? E g, the native protocol (e g pactl stat) uses pa_namereg_get_default_sink instead of the direct pointer. As for the other dbus patches (and "core: Add hooks for default device changes"), I looked them briefly through and saw nothing to remark on. With the disclaimer that I don't know the dbus stuff very well, but I'd just say it's a very welcome fix, if it fixes the occasional crashes on device unplug. > > - pa_assert_se((fallback_sink = pa_hashmap_get(c->sinks_by_index, PA_UINT32_TO_PTR(c->fallback_sink->index)))); > + pa_assert_se((fallback_sink = pa_hashmap_get(c->sinks_by_index, PA_UINT32_TO_PTR(c->core->default_sink->index)))); > object_path = pa_dbusiface_device_get_path(fallback_sink); > > pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &object_path); > @@ -699,12 +697,6 @@ static void handle_set_fallback_sink(DBusConnection *conn, DBusMessage *msg, DBu > pa_assert(iter); > pa_assert(c); > > - if (!c->fallback_sink) { > - pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, > - "There are no sinks, and therefore no fallback sink either."); > - return; > - } > - > dbus_message_iter_get_basic(iter, &object_path); > > if (!(fallback_sink = pa_hashmap_get(c->sinks_by_path, object_path))) { > @@ -765,13 +757,12 @@ static void handle_get_fallback_source(DBusConnection *conn, DBusMessage *msg, v > pa_assert(msg); > pa_assert(c); > > - if (!c->fallback_source) { > - pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, > - "There are no sources, and therefore no fallback source either."); > + if (!c->core->default_source) { > + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "No fallback source set."); > return; > } > > - pa_assert_se((fallback_source = pa_hashmap_get(c->sources_by_index, PA_UINT32_TO_PTR(c->fallback_source->index)))); > + pa_assert_se((fallback_source = pa_hashmap_get(c->sources_by_index, PA_UINT32_TO_PTR(c->core->default_source->index)))); > object_path = pa_dbusiface_device_get_path(fallback_source); > > pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &object_path); > @@ -787,12 +778,6 @@ static void handle_set_fallback_source(DBusConnection *conn, DBusMessage *msg, D > pa_assert(iter); > pa_assert(c); > > - if (!c->fallback_source) { > - pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, > - "There are no sources, and therefore no fallback source either."); > - return; > - } > - > dbus_message_iter_get_basic(iter, &object_path); > > if (!(fallback_source = pa_hashmap_get(c->sources_by_path, object_path))) { > @@ -1094,13 +1079,12 @@ static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdat > alternate_sample_rate = c->core->alternate_sample_rate; > cards = get_cards(c, &n_cards); > sinks = get_sinks(c, &n_sinks); > - fallback_sink = c->fallback_sink > - ? pa_dbusiface_device_get_path(pa_hashmap_get(c->sinks_by_index, PA_UINT32_TO_PTR(c->fallback_sink->index))) > + fallback_sink = c->core->default_sink > + ? pa_dbusiface_device_get_path(pa_hashmap_get(c->sinks_by_index, PA_UINT32_TO_PTR(c->core->default_sink->index))) > : NULL; > sources = get_sources(c, &n_sources); > - fallback_source = c->fallback_source > - ? pa_dbusiface_device_get_path(pa_hashmap_get(c->sources_by_index, > - PA_UINT32_TO_PTR(c->fallback_source->index))) > + fallback_source = c->core->default_source > + ? pa_dbusiface_device_get_path(pa_hashmap_get(c->sources_by_index, PA_UINT32_TO_PTR(c->core->default_source->index))) > : NULL; > playback_streams = get_playback_streams(c, &n_playback_streams); > record_streams = get_record_streams(c, &n_record_streams); > @@ -1573,77 +1557,16 @@ 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; > - 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_CARD: > if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) { > @@ -1856,6 +1779,62 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t t, uint3 > } > } > > +static pa_hook_result_t default_sink_changed_cb(pa_core *core, pa_sink *sink, pa_dbusiface_core *core_iface) { > + const char *object_path = NULL; > + DBusMessage *signal_msg = NULL; > + > + pa_assert(core); > + pa_assert(core_iface); > + > + if (sink) { > + pa_dbusiface_device *device_iface; > + > + pa_assert_se(device_iface = pa_hashmap_get(core_iface->sinks_by_index, PA_UINT32_TO_PTR(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))); > + > + pa_dbus_protocol_send_signal(core_iface->dbus_protocol, signal_msg); > + dbus_message_unref(signal_msg); > + > + return PA_HOOK_OK; > +} > + > +static pa_hook_result_t default_source_changed_cb(pa_core *core, pa_source *source, pa_dbusiface_core *core_iface) { > + const char *object_path = NULL; > + DBusMessage *signal_msg = NULL; > + > + pa_assert(core); > + pa_assert(core_iface); > + > + if (source) { > + pa_dbusiface_device *device_iface; > + > + pa_assert_se(device_iface = pa_hashmap_get(core_iface->sources_by_index, PA_UINT32_TO_PTR(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))); > + > + pa_dbus_protocol_send_signal(core_iface->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) { > pa_dbusiface_core *c = slot_data; > pa_sink *s = call_data; > @@ -2031,8 +2010,8 @@ pa_dbusiface_core *pa_dbusiface_core_new(pa_core *core) { > c->samples = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); > c->modules = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); > c->clients = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); > - 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, (pa_hook_cb_t) default_sink_changed_cb, c); > + c->default_source_changed_slot = pa_hook_connect(&core->hooks[PA_CORE_HOOK_DEFAULT_SOURCE_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) default_source_changed_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); > @@ -2049,11 +2028,6 @@ pa_dbusiface_core *pa_dbusiface_core_new(pa_core *core) { > c); > c->memstats = pa_dbusiface_memstats_new(c, core); > > - if (c->fallback_sink) > - pa_sink_ref(c->fallback_sink); > - if (c->fallback_source) > - pa_source_ref(c->fallback_source); > - > PA_IDXSET_FOREACH(card, core->cards, idx) > pa_hashmap_put(c->cards, PA_UINT32_TO_PTR(idx), pa_dbusiface_card_new(c, card)); > > @@ -2113,13 +2087,10 @@ void pa_dbusiface_core_free(pa_dbusiface_core *c) { > pa_hook_slot_free(c->source_unlink_slot); > pa_hook_slot_free(c->extension_registered_slot); > pa_hook_slot_free(c->extension_unregistered_slot); > + pa_hook_slot_free(c->default_source_changed_slot); > + pa_hook_slot_free(c->default_sink_changed_slot); > pa_dbusiface_memstats_free(c->memstats); > > - if (c->fallback_sink) > - pa_sink_unref(c->fallback_sink); > - if (c->fallback_source) > - pa_source_unref(c->fallback_source); > - > pa_dbus_protocol_unref(c->dbus_protocol); > > pa_xfree(c); > -- David Henningsson, Canonical Ltd. https://launchpad.net/~diwic