X-Git-Url: https://code.delx.au/pulseaudio/blobdiff_plain/7bc8a793b8ae4c46e59a444313e4d06186de1680..ef4ae785aa1d4d67b5df1c9414f6c1a144bc3460:/src/modules/dbus/iface-stream.c diff --git a/src/modules/dbus/iface-stream.c b/src/modules/dbus/iface-stream.c index 183625ba..4cbcd74f 100644 --- a/src/modules/dbus/iface-stream.c +++ b/src/modules/dbus/iface-stream.c @@ -53,9 +53,11 @@ struct pa_dbusiface_stream { }; uint32_t sample_rate; pa_cvolume volume; - pa_bool_t is_muted; + dbus_bool_t mute; pa_proplist *proplist; + bool has_volume; + pa_dbus_protocol *dbus_protocol; pa_subscription *subscription; pa_hook_slot *send_event_slot; @@ -70,9 +72,9 @@ static void handle_get_sample_format(DBusConnection *conn, DBusMessage *msg, voi static void handle_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata); static void handle_get_channels(DBusConnection *conn, DBusMessage *msg, void *userdata); static void handle_get_volume(DBusConnection *conn, DBusMessage *msg, void *userdata); -static void handle_set_volume(DBusConnection *conn, DBusMessage *msg, void *userdata); -static void handle_get_is_muted(DBusConnection *conn, DBusMessage *msg, void *userdata); -static void handle_set_is_muted(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_set_volume(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata); +static void handle_get_mute(DBusConnection *conn, DBusMessage *msg, void *userdata); +static void handle_set_mute(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata); static void handle_get_buffer_latency(DBusConnection *conn, DBusMessage *msg, void *userdata); static void handle_get_device_latency(DBusConnection *conn, DBusMessage *msg, void *userdata); static void handle_get_resample_method(DBusConnection *conn, DBusMessage *msg, void *userdata); @@ -93,7 +95,7 @@ enum property_handler_index { PROPERTY_HANDLER_SAMPLE_RATE, PROPERTY_HANDLER_CHANNELS, PROPERTY_HANDLER_VOLUME, - PROPERTY_HANDLER_IS_MUTED, + PROPERTY_HANDLER_MUTE, PROPERTY_HANDLER_BUFFER_LATENCY, PROPERTY_HANDLER_DEVICE_LATENCY, PROPERTY_HANDLER_RESAMPLE_METHOD, @@ -111,7 +113,7 @@ static pa_dbus_property_handler property_handlers[PROPERTY_HANDLER_MAX] = { [PROPERTY_HANDLER_SAMPLE_RATE] = { .property_name = "SampleRate", .type = "u", .get_cb = handle_get_sample_rate, .set_cb = NULL }, [PROPERTY_HANDLER_CHANNELS] = { .property_name = "Channels", .type = "au", .get_cb = handle_get_channels, .set_cb = NULL }, [PROPERTY_HANDLER_VOLUME] = { .property_name = "Volume", .type = "au", .get_cb = handle_get_volume, .set_cb = handle_set_volume }, - [PROPERTY_HANDLER_IS_MUTED] = { .property_name = "IsMuted", .type = "b", .get_cb = handle_get_is_muted, .set_cb = handle_set_is_muted }, + [PROPERTY_HANDLER_MUTE] = { .property_name = "Mute", .type = "b", .get_cb = handle_get_mute, .set_cb = handle_set_mute }, [PROPERTY_HANDLER_BUFFER_LATENCY] = { .property_name = "BufferLatency", .type = "t", .get_cb = handle_get_buffer_latency, .set_cb = NULL }, [PROPERTY_HANDLER_DEVICE_LATENCY] = { .property_name = "DeviceLatency", .type = "t", .get_cb = handle_get_device_latency, .set_cb = NULL }, [PROPERTY_HANDLER_RESAMPLE_METHOD] = { .property_name = "ResampleMethod", .type = "s", .get_cb = handle_get_resample_method, .set_cb = NULL }, @@ -189,6 +191,14 @@ static void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userd pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &idx); } +/* The returned string has to be freed with pa_xfree() by the caller. */ +static char *stream_to_string(pa_dbusiface_stream *s) { + if (s->type == STREAM_TYPE_PLAYBACK) + return pa_sprintf_malloc("Playback stream %u", (unsigned) s->sink_input->index); + else + return pa_sprintf_malloc("Record stream %u", (unsigned) s->source_output->index); +} + static void handle_get_driver(DBusConnection *conn, DBusMessage *msg, void *userdata) { pa_dbusiface_stream *s = userdata; const char *driver = NULL; @@ -200,12 +210,11 @@ static void handle_get_driver(DBusConnection *conn, DBusMessage *msg, void *user driver = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->driver : s->source_output->driver; if (!driver) { - if (s->type == STREAM_TYPE_PLAYBACK) - pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, - "Playback stream %u doesn't have a driver.", s->sink_input->index); - else - pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, - "Record stream %u doesn't have a driver.", s->source_output->index); + char *str = stream_to_string(s); + + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "%s doesn't have a driver.", str); + pa_xfree(str); + return; } @@ -224,12 +233,11 @@ static void handle_get_owner_module(DBusConnection *conn, DBusMessage *msg, void owner_module = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->module : s->source_output->module; if (!owner_module) { - if (s->type == STREAM_TYPE_PLAYBACK) - pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, - "Playback stream %u doesn't have an owner module.", s->sink_input->index); - else - pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, - "Record stream %u doesn't have an owner module.", s->source_output->index); + char *str = stream_to_string(s); + + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "%s doesn't have an owner module.", str); + pa_xfree(str); + return; } @@ -250,12 +258,11 @@ static void handle_get_client(DBusConnection *conn, DBusMessage *msg, void *user client = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->client : s->source_output->client; if (!client) { - if (s->type == STREAM_TYPE_PLAYBACK) - pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, - "Playback stream %u isn't associated to any client.", s->sink_input->index); - else - pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, - "Record stream %u isn't associated to any client.", s->source_output->index); + char *str = stream_to_string(s); + + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "%s isn't associated to any client.", str); + pa_xfree(str); + return; } @@ -332,8 +339,12 @@ static void handle_get_volume(DBusConnection *conn, DBusMessage *msg, void *user pa_assert(msg); pa_assert(s); - if (s->type == STREAM_TYPE_RECORD) { - pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "Record streams don't have volume."); + if (!s->has_volume) { + char *str = stream_to_string(s); + + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "%s doesn't have volume.", str); + pa_xfree(str); + return; } @@ -343,52 +354,63 @@ static void handle_get_volume(DBusConnection *conn, DBusMessage *msg, void *user pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_UINT32, volume, s->volume.channels); } -static void handle_set_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) { +static void handle_set_volume(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) { pa_dbusiface_stream *s = userdata; - unsigned stream_channels = 0; + bool volume_writable = true; + DBusMessageIter array_iter; + int stream_channels = 0; dbus_uint32_t *volume = NULL; - unsigned n_volume_entries = 0; + int n_volume_entries = 0; pa_cvolume new_vol; - unsigned i = 0; + int i = 0; pa_assert(conn); pa_assert(msg); + pa_assert(iter); pa_assert(s); - if (s->type == STREAM_TYPE_RECORD) { - pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "Record streams don't have volume."); + volume_writable = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->volume_writable : false; + + if (!s->has_volume || !volume_writable) { + char *str = stream_to_string(s); + + if (!s->has_volume) + pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "%s doesn't have volume.", str); + else if (!volume_writable) + pa_dbus_send_error(conn, msg, DBUS_ERROR_ACCESS_DENIED, "%s has read-only volume.", str); + pa_xfree(str); + return; } - pa_cvolume_init(&new_vol); - stream_channels = s->sink_input->channel_map.channels; - new_vol.channels = stream_channels; + dbus_message_iter_recurse(iter, &array_iter); + dbus_message_iter_get_fixed_array(&array_iter, &volume, &n_volume_entries); - if (pa_dbus_get_fixed_array_set_property_arg(conn, msg, DBUS_TYPE_UINT32, &volume, &n_volume_entries) < 0) - return; - - if (n_volume_entries != stream_channels) { + if (n_volume_entries != stream_channels && n_volume_entries != 1) { pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Expected %u volume entries, got %u.", stream_channels, n_volume_entries); return; } + pa_cvolume_init(&new_vol); + new_vol.channels = n_volume_entries; + for (i = 0; i < n_volume_entries; ++i) { - if (volume[i] > PA_VOLUME_MAX) { - pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Too large volume value: %u", volume[i]); + if (!PA_VOLUME_IS_VALID(volume[i])) { + pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid volume: %u", volume[i]); return; } new_vol.values[i] = volume[i]; } - pa_sink_input_set_volume(s->sink_input, &new_vol, TRUE, TRUE); + pa_sink_input_set_volume(s->sink_input, &new_vol, true, true); pa_dbus_send_empty_reply(conn, msg); } -static void handle_get_is_muted(DBusConnection *conn, DBusMessage *msg, void *userdata) { +static void handle_get_mute(DBusConnection *conn, DBusMessage *msg, void *userdata) { pa_dbusiface_stream *s = userdata; pa_assert(conn); @@ -400,29 +422,29 @@ static void handle_get_is_muted(DBusConnection *conn, DBusMessage *msg, void *us return; } - pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &s->is_muted); + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &s->mute); } -static void handle_set_is_muted(DBusConnection *conn, DBusMessage *msg, void *userdata) { +static void handle_set_mute(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) { pa_dbusiface_stream *s = userdata; - dbus_bool_t is_muted = FALSE; + dbus_bool_t mute = FALSE; pa_assert(conn); pa_assert(msg); + pa_assert(iter); pa_assert(s); - if (pa_dbus_get_basic_set_property_arg(conn, msg, DBUS_TYPE_BOOLEAN, &is_muted) < 0) - return; + dbus_message_iter_get_basic(iter, &mute); if (s->type == STREAM_TYPE_RECORD) { pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "Record streams don't have mute."); return; } - pa_sink_input_set_mute(s->sink_input, is_muted, TRUE); + pa_sink_input_set_mute(s->sink_input, mute, true); pa_dbus_send_empty_reply(conn, msg); -}; +} static void handle_get_buffer_latency(DBusConnection *conn, DBusMessage *msg, void *userdata) { pa_dbusiface_stream *s = userdata; @@ -469,6 +491,9 @@ static void handle_get_resample_method(DBusConnection *conn, DBusMessage *msg, v else resample_method = pa_resample_method_to_string(s->source_output->actual_resample_method); + if (!resample_method) + resample_method = ""; + pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &resample_method); } @@ -507,6 +532,11 @@ static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdat pa_assert(msg); pa_assert(s); + if (s->has_volume) { + for (i = 0; i < s->volume.channels; ++i) + volume[i] = s->volume.values[i]; + } + if (s->type == STREAM_TYPE_PLAYBACK) { idx = s->sink_input->index; driver = s->sink_input->driver; @@ -515,8 +545,6 @@ static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdat device = pa_dbusiface_core_get_sink_path(s->core, s->sink); sample_format = s->sink_input->sample_spec.format; channel_map = &s->sink_input->channel_map; - for (i = 0; i < s->volume.channels; ++i) - volume[i] = s->volume.values[i]; buffer_latency = pa_sink_input_get_latency(s->sink_input, &device_latency); resample_method = pa_resample_method_to_string(s->sink_input->actual_resample_method); } else { @@ -536,6 +564,8 @@ static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdat client_path = pa_dbusiface_core_get_client_path(s->core, client); for (i = 0; i < channel_map->channels; ++i) channels[i] = channel_map->map[i]; + if (!resample_method) + resample_method = ""; pa_assert_se((reply = dbus_message_new_method_return(msg))); @@ -553,13 +583,14 @@ static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdat if (client) pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CLIENT].property_name, DBUS_TYPE_OBJECT_PATH, &client_path); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DEVICE].property_name, DBUS_TYPE_OBJECT_PATH, &device); pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SAMPLE_FORMAT].property_name, DBUS_TYPE_UINT32, &sample_format); pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SAMPLE_RATE].property_name, DBUS_TYPE_UINT32, &s->sample_rate); pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CHANNELS].property_name, DBUS_TYPE_UINT32, channels, channel_map->channels); - if (s->type == STREAM_TYPE_PLAYBACK) { + if (s->has_volume) { pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_VOLUME].property_name, DBUS_TYPE_UINT32, volume, s->volume.channels); - pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_IS_MUTED].property_name, DBUS_TYPE_BOOLEAN, &s->is_muted); + pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_MUTE].property_name, DBUS_TYPE_BOOLEAN, &s->mute); } pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_BUFFER_LATENCY].property_name, DBUS_TYPE_UINT64, &buffer_latency); @@ -575,19 +606,12 @@ static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdat static void handle_move(DBusConnection *conn, DBusMessage *msg, void *userdata) { pa_dbusiface_stream *s = userdata; const char *device = NULL; - DBusError error; pa_assert(conn); pa_assert(msg); pa_assert(s); - dbus_error_init(&error); - - if (!dbus_message_get_args(msg, &error, DBUS_TYPE_STRING, &device, DBUS_TYPE_INVALID)) { - pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message); - dbus_error_free(&error); - return; - } + pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &device, DBUS_TYPE_INVALID)); if (s->type == STREAM_TYPE_PLAYBACK) { pa_sink *sink = pa_dbusiface_core_get_sink(s->core, device); @@ -597,7 +621,7 @@ static void handle_move(DBusConnection *conn, DBusMessage *msg, void *userdata) return; } - if (pa_sink_input_move_to(s->sink_input, sink, TRUE) < 0) { + if (pa_sink_input_move_to(s->sink_input, sink, true) < 0) { pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "Moving playback stream %u to sink %s failed.", s->sink_input->index, sink->name); return; @@ -610,7 +634,7 @@ static void handle_move(DBusConnection *conn, DBusMessage *msg, void *userdata) return; } - if (pa_source_output_move_to(s->source_output, source, TRUE) < 0) { + if (pa_source_output_move_to(s->source_output, source, true) < 0) { pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "Moving record stream %u to source %s failed.", s->source_output->index, source->name); return; @@ -637,7 +661,7 @@ 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 = NULL; + DBusMessage *signal_msg = NULL; const char *new_device_path = NULL; uint32_t new_sample_rate = 0; pa_proplist *new_proplist = NULL; @@ -667,14 +691,14 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t new_device_path = pa_dbusiface_core_get_sink_path(s->core, new_sink); - pa_assert_se(signal = dbus_message_new_signal(s->path, - PA_DBUSIFACE_STREAM_INTERFACE, - signals[SIGNAL_DEVICE_UPDATED].name)); - pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &new_device_path, DBUS_TYPE_INVALID)); + 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); - dbus_message_unref(signal); - signal = NULL; + 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; @@ -685,14 +709,14 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t new_device_path = pa_dbusiface_core_get_source_path(s->core, new_source); - pa_assert_se(signal = dbus_message_new_signal(s->path, - PA_DBUSIFACE_STREAM_INTERFACE, - signals[SIGNAL_DEVICE_UPDATED].name)); - pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &new_device_path, DBUS_TYPE_INVALID)); + 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); - dbus_message_unref(signal); - signal = NULL; + pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg); + dbus_message_unref(signal_msg); + signal_msg = NULL; } } @@ -701,56 +725,59 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t if (s->sample_rate != new_sample_rate) { s->sample_rate = new_sample_rate; - pa_assert_se(signal = dbus_message_new_signal(s->path, - PA_DBUSIFACE_STREAM_INTERFACE, - signals[SIGNAL_SAMPLE_RATE_UPDATED].name)); - pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_UINT32, &s->sample_rate, DBUS_TYPE_INVALID)); + 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); - dbus_message_unref(signal); - signal = NULL; + pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg); + dbus_message_unref(signal_msg); + signal_msg = NULL; } if (s->type == STREAM_TYPE_PLAYBACK) { - pa_cvolume new_volume; - pa_bool_t new_muted = FALSE; + bool new_mute = false; - pa_sink_input_get_volume(s->sink_input, &new_volume, TRUE); + if (s->has_volume) { + pa_cvolume new_volume; - if (!pa_cvolume_equal(&s->volume, &new_volume)) { - dbus_uint32_t volume[PA_CHANNELS_MAX]; - dbus_uint32_t *volume_ptr = volume; + pa_sink_input_get_volume(s->sink_input, &new_volume, true); - s->volume = new_volume; + if (!pa_cvolume_equal(&s->volume, &new_volume)) { + dbus_uint32_t volume[PA_CHANNELS_MAX]; + dbus_uint32_t *volume_ptr = volume; - for (i = 0; i < s->volume.channels; ++i) - volume[i] = s->volume.values[i]; + s->volume = new_volume; - pa_assert_se(signal = dbus_message_new_signal(s->path, - PA_DBUSIFACE_STREAM_INTERFACE, - signals[SIGNAL_VOLUME_UPDATED].name)); - pa_assert_se(dbus_message_append_args(signal, - DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &volume_ptr, s->volume.channels, - DBUS_TYPE_INVALID)); - - pa_dbus_protocol_send_signal(s->dbus_protocol, signal); - dbus_message_unref(signal); - signal = NULL; + 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_dbus_protocol_send_signal(s->dbus_protocol, signal_msg); + dbus_message_unref(signal_msg); + signal_msg = NULL; + } } - new_muted = pa_sink_input_get_mute(s->sink_input); + new_mute = s->sink_input->muted; - if (s->is_muted != new_muted) { - s->is_muted = new_muted; + if (s->mute != new_mute) { + s->mute = new_mute; - pa_assert_se(signal = dbus_message_new_signal(s->path, - PA_DBUSIFACE_STREAM_INTERFACE, - signals[SIGNAL_MUTE_UPDATED].name)); - pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_BOOLEAN, &s->is_muted, DBUS_TYPE_INVALID)); + pa_assert_se(signal_msg = dbus_message_new_signal(s->path, + PA_DBUSIFACE_STREAM_INTERFACE, + signals[SIGNAL_MUTE_UPDATED].name)); + pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_BOOLEAN, &s->mute, DBUS_TYPE_INVALID)); - pa_dbus_protocol_send_signal(s->dbus_protocol, signal); - dbus_message_unref(signal); - signal = NULL; + pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg); + dbus_message_unref(signal_msg); + signal_msg = NULL; } } @@ -761,21 +788,21 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t pa_proplist_update(s->proplist, PA_UPDATE_SET, new_proplist); - pa_assert_se(signal = dbus_message_new_signal(s->path, - PA_DBUSIFACE_STREAM_INTERFACE, - signals[SIGNAL_PROPERTY_LIST_UPDATED].name)); - dbus_message_iter_init_append(signal, &msg_iter); + pa_assert_se(signal_msg = dbus_message_new_signal(s->path, + PA_DBUSIFACE_STREAM_INTERFACE, + signals[SIGNAL_PROPERTY_LIST_UPDATED].name)); + dbus_message_iter_init_append(signal_msg, &msg_iter); pa_dbus_append_proplist(&msg_iter, s->proplist); - pa_dbus_protocol_send_signal(s->dbus_protocol, signal); - dbus_message_unref(signal); - signal = NULL; + pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg); + dbus_message_unref(signal_msg); + signal_msg = NULL; } } 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 = NULL; + DBusMessage *signal_msg = NULL; DBusMessageIter msg_iter; const char *name = NULL; pa_proplist *property_list = NULL; @@ -801,15 +828,15 @@ static pa_hook_result_t send_event_cb(void *hook_data, void *call_data, void *sl property_list = data->data; } - pa_assert_se(signal = dbus_message_new_signal(s->path, - PA_DBUSIFACE_STREAM_INTERFACE, - signals[SIGNAL_STREAM_EVENT].name)); - dbus_message_iter_init_append(signal, &msg_iter); + pa_assert_se(signal_msg = dbus_message_new_signal(s->path, + PA_DBUSIFACE_STREAM_INTERFACE, + signals[SIGNAL_STREAM_EVENT].name)); + dbus_message_iter_init_append(signal_msg, &msg_iter); pa_assert_se(dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &name)); pa_dbus_append_proplist(&msg_iter, property_list); - pa_dbus_protocol_send_signal(s->dbus_protocol, signal); - dbus_message_unref(signal); + pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg); + dbus_message_unref(signal_msg); return PA_HOOK_OK; } @@ -827,8 +854,14 @@ pa_dbusiface_stream *pa_dbusiface_stream_new_playback(pa_dbusiface_core *core, p 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->sample_rate = sink_input->sample_spec.rate; - pa_sink_input_get_volume(sink_input, &s->volume, TRUE); - s->is_muted = pa_sink_input_get_mute(sink_input); + s->has_volume = pa_sink_input_is_volume_readable(sink_input); + + if (s->has_volume) + pa_sink_input_get_volume(sink_input, &s->volume, true); + else + pa_cvolume_init(&s->volume); + + 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); @@ -856,8 +889,9 @@ pa_dbusiface_stream *pa_dbusiface_stream_new_record(pa_dbusiface_core *core, pa_ s->source = pa_source_ref(source_output->source); s->sample_rate = source_output->sample_spec.rate; pa_cvolume_init(&s->volume); - s->is_muted = FALSE; + s->mute = false; 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],