153a5a1b3Sopenharmony_ci/*** 253a5a1b3Sopenharmony_ci This file is part of PulseAudio. 353a5a1b3Sopenharmony_ci 453a5a1b3Sopenharmony_ci Copyright 2009 Tanu Kaskinen 553a5a1b3Sopenharmony_ci Copyright 2009 Vincent Filali-Ansary <filali.v@azurdigitalnetworks.net> 653a5a1b3Sopenharmony_ci 753a5a1b3Sopenharmony_ci PulseAudio is free software; you can redistribute it and/or modify 853a5a1b3Sopenharmony_ci it under the terms of the GNU Lesser General Public License as published 953a5a1b3Sopenharmony_ci by the Free Software Foundation; either version 2.1 of the License, 1053a5a1b3Sopenharmony_ci or (at your option) any later version. 1153a5a1b3Sopenharmony_ci 1253a5a1b3Sopenharmony_ci PulseAudio is distributed in the hope that it will be useful, but 1353a5a1b3Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 1453a5a1b3Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1553a5a1b3Sopenharmony_ci General Public License for more details. 1653a5a1b3Sopenharmony_ci 1753a5a1b3Sopenharmony_ci You should have received a copy of the GNU Lesser General Public License 1853a5a1b3Sopenharmony_ci along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. 1953a5a1b3Sopenharmony_ci***/ 2053a5a1b3Sopenharmony_ci 2153a5a1b3Sopenharmony_ci#ifdef HAVE_CONFIG_H 2253a5a1b3Sopenharmony_ci#include <config.h> 2353a5a1b3Sopenharmony_ci#endif 2453a5a1b3Sopenharmony_ci 2553a5a1b3Sopenharmony_ci#include <pulsecore/core-util.h> 2653a5a1b3Sopenharmony_ci#include <pulsecore/dbus-util.h> 2753a5a1b3Sopenharmony_ci#include <pulsecore/protocol-dbus.h> 2853a5a1b3Sopenharmony_ci 2953a5a1b3Sopenharmony_ci#include "iface-stream.h" 3053a5a1b3Sopenharmony_ci 3153a5a1b3Sopenharmony_ci#define PLAYBACK_OBJECT_NAME "playback_stream" 3253a5a1b3Sopenharmony_ci#define RECORD_OBJECT_NAME "record_stream" 3353a5a1b3Sopenharmony_ci 3453a5a1b3Sopenharmony_cienum stream_type { 3553a5a1b3Sopenharmony_ci STREAM_TYPE_PLAYBACK, 3653a5a1b3Sopenharmony_ci STREAM_TYPE_RECORD 3753a5a1b3Sopenharmony_ci}; 3853a5a1b3Sopenharmony_ci 3953a5a1b3Sopenharmony_cistruct pa_dbusiface_stream { 4053a5a1b3Sopenharmony_ci pa_dbusiface_core *core; 4153a5a1b3Sopenharmony_ci 4253a5a1b3Sopenharmony_ci union { 4353a5a1b3Sopenharmony_ci pa_sink_input *sink_input; 4453a5a1b3Sopenharmony_ci pa_source_output *source_output; 4553a5a1b3Sopenharmony_ci }; 4653a5a1b3Sopenharmony_ci enum stream_type type; 4753a5a1b3Sopenharmony_ci char *path; 4853a5a1b3Sopenharmony_ci union { 4953a5a1b3Sopenharmony_ci pa_sink *sink; 5053a5a1b3Sopenharmony_ci pa_source *source; 5153a5a1b3Sopenharmony_ci }; 5253a5a1b3Sopenharmony_ci uint32_t sample_rate; 5353a5a1b3Sopenharmony_ci pa_cvolume volume; 5453a5a1b3Sopenharmony_ci dbus_bool_t mute; 5553a5a1b3Sopenharmony_ci pa_proplist *proplist; 5653a5a1b3Sopenharmony_ci 5753a5a1b3Sopenharmony_ci bool has_volume; 5853a5a1b3Sopenharmony_ci 5953a5a1b3Sopenharmony_ci pa_dbus_protocol *dbus_protocol; 6053a5a1b3Sopenharmony_ci pa_hook_slot *send_event_slot; 6153a5a1b3Sopenharmony_ci pa_hook_slot *move_finish_slot; 6253a5a1b3Sopenharmony_ci pa_hook_slot *volume_changed_slot; 6353a5a1b3Sopenharmony_ci pa_hook_slot *mute_changed_slot; 6453a5a1b3Sopenharmony_ci pa_hook_slot *proplist_changed_slot; 6553a5a1b3Sopenharmony_ci pa_hook_slot *state_changed_slot; 6653a5a1b3Sopenharmony_ci}; 6753a5a1b3Sopenharmony_ci 6853a5a1b3Sopenharmony_cistatic void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata); 6953a5a1b3Sopenharmony_cistatic void handle_get_driver(DBusConnection *conn, DBusMessage *msg, void *userdata); 7053a5a1b3Sopenharmony_cistatic void handle_get_owner_module(DBusConnection *conn, DBusMessage *msg, void *userdata); 7153a5a1b3Sopenharmony_cistatic void handle_get_client(DBusConnection *conn, DBusMessage *msg, void *userdata); 7253a5a1b3Sopenharmony_cistatic void handle_get_device(DBusConnection *conn, DBusMessage *msg, void *userdata); 7353a5a1b3Sopenharmony_cistatic void handle_get_sample_format(DBusConnection *conn, DBusMessage *msg, void *userdata); 7453a5a1b3Sopenharmony_cistatic void handle_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata); 7553a5a1b3Sopenharmony_cistatic void handle_get_channels(DBusConnection *conn, DBusMessage *msg, void *userdata); 7653a5a1b3Sopenharmony_cistatic void handle_get_volume(DBusConnection *conn, DBusMessage *msg, void *userdata); 7753a5a1b3Sopenharmony_cistatic void handle_set_volume(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata); 7853a5a1b3Sopenharmony_cistatic void handle_get_mute(DBusConnection *conn, DBusMessage *msg, void *userdata); 7953a5a1b3Sopenharmony_cistatic void handle_set_mute(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata); 8053a5a1b3Sopenharmony_cistatic void handle_get_buffer_latency(DBusConnection *conn, DBusMessage *msg, void *userdata); 8153a5a1b3Sopenharmony_cistatic void handle_get_device_latency(DBusConnection *conn, DBusMessage *msg, void *userdata); 8253a5a1b3Sopenharmony_cistatic void handle_get_resample_method(DBusConnection *conn, DBusMessage *msg, void *userdata); 8353a5a1b3Sopenharmony_cistatic void handle_get_property_list(DBusConnection *conn, DBusMessage *msg, void *userdata); 8453a5a1b3Sopenharmony_ci 8553a5a1b3Sopenharmony_cistatic void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata); 8653a5a1b3Sopenharmony_ci 8753a5a1b3Sopenharmony_cistatic void handle_move(DBusConnection *conn, DBusMessage *msg, void *userdata); 8853a5a1b3Sopenharmony_cistatic void handle_kill(DBusConnection *conn, DBusMessage *msg, void *userdata); 8953a5a1b3Sopenharmony_ci 9053a5a1b3Sopenharmony_cienum property_handler_index { 9153a5a1b3Sopenharmony_ci PROPERTY_HANDLER_INDEX, 9253a5a1b3Sopenharmony_ci PROPERTY_HANDLER_DRIVER, 9353a5a1b3Sopenharmony_ci PROPERTY_HANDLER_OWNER_MODULE, 9453a5a1b3Sopenharmony_ci PROPERTY_HANDLER_CLIENT, 9553a5a1b3Sopenharmony_ci PROPERTY_HANDLER_DEVICE, 9653a5a1b3Sopenharmony_ci PROPERTY_HANDLER_SAMPLE_FORMAT, 9753a5a1b3Sopenharmony_ci PROPERTY_HANDLER_SAMPLE_RATE, 9853a5a1b3Sopenharmony_ci PROPERTY_HANDLER_CHANNELS, 9953a5a1b3Sopenharmony_ci PROPERTY_HANDLER_VOLUME, 10053a5a1b3Sopenharmony_ci PROPERTY_HANDLER_MUTE, 10153a5a1b3Sopenharmony_ci PROPERTY_HANDLER_BUFFER_LATENCY, 10253a5a1b3Sopenharmony_ci PROPERTY_HANDLER_DEVICE_LATENCY, 10353a5a1b3Sopenharmony_ci PROPERTY_HANDLER_RESAMPLE_METHOD, 10453a5a1b3Sopenharmony_ci PROPERTY_HANDLER_PROPERTY_LIST, 10553a5a1b3Sopenharmony_ci PROPERTY_HANDLER_MAX 10653a5a1b3Sopenharmony_ci}; 10753a5a1b3Sopenharmony_ci 10853a5a1b3Sopenharmony_cistatic pa_dbus_property_handler property_handlers[PROPERTY_HANDLER_MAX] = { 10953a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_INDEX] = { .property_name = "Index", .type = "u", .get_cb = handle_get_index, .set_cb = NULL }, 11053a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_DRIVER] = { .property_name = "Driver", .type = "s", .get_cb = handle_get_driver, .set_cb = NULL }, 11153a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_OWNER_MODULE] = { .property_name = "OwnerModule", .type = "o", .get_cb = handle_get_owner_module, .set_cb = NULL }, 11253a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_CLIENT] = { .property_name = "Client", .type = "o", .get_cb = handle_get_client, .set_cb = NULL }, 11353a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_DEVICE] = { .property_name = "Device", .type = "o", .get_cb = handle_get_device, .set_cb = NULL }, 11453a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_SAMPLE_FORMAT] = { .property_name = "SampleFormat", .type = "u", .get_cb = handle_get_sample_format, .set_cb = NULL }, 11553a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_SAMPLE_RATE] = { .property_name = "SampleRate", .type = "u", .get_cb = handle_get_sample_rate, .set_cb = NULL }, 11653a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_CHANNELS] = { .property_name = "Channels", .type = "au", .get_cb = handle_get_channels, .set_cb = NULL }, 11753a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_VOLUME] = { .property_name = "Volume", .type = "au", .get_cb = handle_get_volume, .set_cb = handle_set_volume }, 11853a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_MUTE] = { .property_name = "Mute", .type = "b", .get_cb = handle_get_mute, .set_cb = handle_set_mute }, 11953a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_BUFFER_LATENCY] = { .property_name = "BufferLatency", .type = "t", .get_cb = handle_get_buffer_latency, .set_cb = NULL }, 12053a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_DEVICE_LATENCY] = { .property_name = "DeviceLatency", .type = "t", .get_cb = handle_get_device_latency, .set_cb = NULL }, 12153a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_RESAMPLE_METHOD] = { .property_name = "ResampleMethod", .type = "s", .get_cb = handle_get_resample_method, .set_cb = NULL }, 12253a5a1b3Sopenharmony_ci [PROPERTY_HANDLER_PROPERTY_LIST] = { .property_name = "PropertyList", .type = "a{say}", .get_cb = handle_get_property_list, .set_cb = NULL } 12353a5a1b3Sopenharmony_ci}; 12453a5a1b3Sopenharmony_ci 12553a5a1b3Sopenharmony_cienum method_handler_index { 12653a5a1b3Sopenharmony_ci METHOD_HANDLER_MOVE, 12753a5a1b3Sopenharmony_ci METHOD_HANDLER_KILL, 12853a5a1b3Sopenharmony_ci METHOD_HANDLER_MAX 12953a5a1b3Sopenharmony_ci}; 13053a5a1b3Sopenharmony_ci 13153a5a1b3Sopenharmony_cistatic pa_dbus_arg_info move_args[] = { { "device", "o", "in" } }; 13253a5a1b3Sopenharmony_ci 13353a5a1b3Sopenharmony_cistatic pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = { 13453a5a1b3Sopenharmony_ci [METHOD_HANDLER_MOVE] = { 13553a5a1b3Sopenharmony_ci .method_name = "Move", 13653a5a1b3Sopenharmony_ci .arguments = move_args, 13753a5a1b3Sopenharmony_ci .n_arguments = sizeof(move_args) / sizeof(pa_dbus_arg_info), 13853a5a1b3Sopenharmony_ci .receive_cb = handle_move }, 13953a5a1b3Sopenharmony_ci [METHOD_HANDLER_KILL] = { 14053a5a1b3Sopenharmony_ci .method_name = "Kill", 14153a5a1b3Sopenharmony_ci .arguments = NULL, 14253a5a1b3Sopenharmony_ci .n_arguments = 0, 14353a5a1b3Sopenharmony_ci .receive_cb = handle_kill } 14453a5a1b3Sopenharmony_ci}; 14553a5a1b3Sopenharmony_ci 14653a5a1b3Sopenharmony_cienum signal_index { 14753a5a1b3Sopenharmony_ci SIGNAL_DEVICE_UPDATED, 14853a5a1b3Sopenharmony_ci SIGNAL_SAMPLE_RATE_UPDATED, 14953a5a1b3Sopenharmony_ci SIGNAL_VOLUME_UPDATED, 15053a5a1b3Sopenharmony_ci SIGNAL_MUTE_UPDATED, 15153a5a1b3Sopenharmony_ci SIGNAL_PROPERTY_LIST_UPDATED, 15253a5a1b3Sopenharmony_ci SIGNAL_STREAM_EVENT, 15353a5a1b3Sopenharmony_ci SIGNAL_MAX 15453a5a1b3Sopenharmony_ci}; 15553a5a1b3Sopenharmony_ci 15653a5a1b3Sopenharmony_cistatic pa_dbus_arg_info device_updated_args[] = { { "device", "o", NULL } }; 15753a5a1b3Sopenharmony_cistatic pa_dbus_arg_info sample_rate_updated_args[] = { { "sample_rate", "u", NULL } }; 15853a5a1b3Sopenharmony_cistatic pa_dbus_arg_info volume_updated_args[] = { { "volume", "au", NULL } }; 15953a5a1b3Sopenharmony_cistatic pa_dbus_arg_info mute_updated_args[] = { { "muted", "b", NULL } }; 16053a5a1b3Sopenharmony_cistatic pa_dbus_arg_info property_list_updated_args[] = { { "property_list", "a{say}", NULL } }; 16153a5a1b3Sopenharmony_cistatic pa_dbus_arg_info stream_event_args[] = { { "name", "s", NULL }, { "property_list", "a{say}", NULL } }; 16253a5a1b3Sopenharmony_ci 16353a5a1b3Sopenharmony_cistatic pa_dbus_signal_info signals[SIGNAL_MAX] = { 16453a5a1b3Sopenharmony_ci [SIGNAL_DEVICE_UPDATED] = { .name = "DeviceUpdated", .arguments = device_updated_args, .n_arguments = 1 }, 16553a5a1b3Sopenharmony_ci [SIGNAL_SAMPLE_RATE_UPDATED] = { .name = "SampleRateUpdated", .arguments = sample_rate_updated_args, .n_arguments = 1 }, 16653a5a1b3Sopenharmony_ci [SIGNAL_VOLUME_UPDATED] = { .name = "VolumeUpdated", .arguments = volume_updated_args, .n_arguments = 1 }, 16753a5a1b3Sopenharmony_ci [SIGNAL_MUTE_UPDATED] = { .name = "MuteUpdated", .arguments = mute_updated_args, .n_arguments = 1 }, 16853a5a1b3Sopenharmony_ci [SIGNAL_PROPERTY_LIST_UPDATED] = { .name = "PropertyListUpdated", .arguments = property_list_updated_args, .n_arguments = 1 }, 16953a5a1b3Sopenharmony_ci [SIGNAL_STREAM_EVENT] = { .name = "StreamEvent", .arguments = stream_event_args, .n_arguments = sizeof(stream_event_args) / sizeof(pa_dbus_arg_info) } 17053a5a1b3Sopenharmony_ci}; 17153a5a1b3Sopenharmony_ci 17253a5a1b3Sopenharmony_cistatic pa_dbus_interface_info stream_interface_info = { 17353a5a1b3Sopenharmony_ci .name = PA_DBUSIFACE_STREAM_INTERFACE, 17453a5a1b3Sopenharmony_ci .method_handlers = method_handlers, 17553a5a1b3Sopenharmony_ci .n_method_handlers = METHOD_HANDLER_MAX, 17653a5a1b3Sopenharmony_ci .property_handlers = property_handlers, 17753a5a1b3Sopenharmony_ci .n_property_handlers = PROPERTY_HANDLER_MAX, 17853a5a1b3Sopenharmony_ci .get_all_properties_cb = handle_get_all, 17953a5a1b3Sopenharmony_ci .signals = signals, 18053a5a1b3Sopenharmony_ci .n_signals = SIGNAL_MAX 18153a5a1b3Sopenharmony_ci}; 18253a5a1b3Sopenharmony_ci 18353a5a1b3Sopenharmony_cistatic void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userdata) { 18453a5a1b3Sopenharmony_ci pa_dbusiface_stream *s = userdata; 18553a5a1b3Sopenharmony_ci dbus_uint32_t idx; 18653a5a1b3Sopenharmony_ci 18753a5a1b3Sopenharmony_ci pa_assert(conn); 18853a5a1b3Sopenharmony_ci pa_assert(msg); 18953a5a1b3Sopenharmony_ci pa_assert(s); 19053a5a1b3Sopenharmony_ci 19153a5a1b3Sopenharmony_ci idx = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->index : s->source_output->index; 19253a5a1b3Sopenharmony_ci 19353a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &idx); 19453a5a1b3Sopenharmony_ci} 19553a5a1b3Sopenharmony_ci 19653a5a1b3Sopenharmony_ci/* The returned string has to be freed with pa_xfree() by the caller. */ 19753a5a1b3Sopenharmony_cistatic char *stream_to_string(pa_dbusiface_stream *s) { 19853a5a1b3Sopenharmony_ci if (s->type == STREAM_TYPE_PLAYBACK) 19953a5a1b3Sopenharmony_ci return pa_sprintf_malloc("Playback stream %u", (unsigned) s->sink_input->index); 20053a5a1b3Sopenharmony_ci else 20153a5a1b3Sopenharmony_ci return pa_sprintf_malloc("Record stream %u", (unsigned) s->source_output->index); 20253a5a1b3Sopenharmony_ci} 20353a5a1b3Sopenharmony_ci 20453a5a1b3Sopenharmony_cistatic void handle_get_driver(DBusConnection *conn, DBusMessage *msg, void *userdata) { 20553a5a1b3Sopenharmony_ci pa_dbusiface_stream *s = userdata; 20653a5a1b3Sopenharmony_ci const char *driver = NULL; 20753a5a1b3Sopenharmony_ci 20853a5a1b3Sopenharmony_ci pa_assert(conn); 20953a5a1b3Sopenharmony_ci pa_assert(msg); 21053a5a1b3Sopenharmony_ci pa_assert(s); 21153a5a1b3Sopenharmony_ci 21253a5a1b3Sopenharmony_ci driver = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->driver : s->source_output->driver; 21353a5a1b3Sopenharmony_ci 21453a5a1b3Sopenharmony_ci if (!driver) { 21553a5a1b3Sopenharmony_ci char *str = stream_to_string(s); 21653a5a1b3Sopenharmony_ci 21753a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "%s doesn't have a driver.", str); 21853a5a1b3Sopenharmony_ci pa_xfree(str); 21953a5a1b3Sopenharmony_ci 22053a5a1b3Sopenharmony_ci return; 22153a5a1b3Sopenharmony_ci } 22253a5a1b3Sopenharmony_ci 22353a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &driver); 22453a5a1b3Sopenharmony_ci} 22553a5a1b3Sopenharmony_ci 22653a5a1b3Sopenharmony_cistatic void handle_get_owner_module(DBusConnection *conn, DBusMessage *msg, void *userdata) { 22753a5a1b3Sopenharmony_ci pa_dbusiface_stream *s = userdata; 22853a5a1b3Sopenharmony_ci pa_module *owner_module = NULL; 22953a5a1b3Sopenharmony_ci const char *object_path = NULL; 23053a5a1b3Sopenharmony_ci 23153a5a1b3Sopenharmony_ci pa_assert(conn); 23253a5a1b3Sopenharmony_ci pa_assert(msg); 23353a5a1b3Sopenharmony_ci pa_assert(s); 23453a5a1b3Sopenharmony_ci 23553a5a1b3Sopenharmony_ci owner_module = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->module : s->source_output->module; 23653a5a1b3Sopenharmony_ci 23753a5a1b3Sopenharmony_ci if (!owner_module) { 23853a5a1b3Sopenharmony_ci char *str = stream_to_string(s); 23953a5a1b3Sopenharmony_ci 24053a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "%s doesn't have an owner module.", str); 24153a5a1b3Sopenharmony_ci pa_xfree(str); 24253a5a1b3Sopenharmony_ci 24353a5a1b3Sopenharmony_ci return; 24453a5a1b3Sopenharmony_ci } 24553a5a1b3Sopenharmony_ci 24653a5a1b3Sopenharmony_ci object_path = pa_dbusiface_core_get_module_path(s->core, owner_module); 24753a5a1b3Sopenharmony_ci 24853a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &object_path); 24953a5a1b3Sopenharmony_ci} 25053a5a1b3Sopenharmony_ci 25153a5a1b3Sopenharmony_cistatic void handle_get_client(DBusConnection *conn, DBusMessage *msg, void *userdata) { 25253a5a1b3Sopenharmony_ci pa_dbusiface_stream *s = userdata; 25353a5a1b3Sopenharmony_ci pa_client *client = NULL; 25453a5a1b3Sopenharmony_ci const char *object_path = NULL; 25553a5a1b3Sopenharmony_ci 25653a5a1b3Sopenharmony_ci pa_assert(conn); 25753a5a1b3Sopenharmony_ci pa_assert(msg); 25853a5a1b3Sopenharmony_ci pa_assert(s); 25953a5a1b3Sopenharmony_ci 26053a5a1b3Sopenharmony_ci client = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->client : s->source_output->client; 26153a5a1b3Sopenharmony_ci 26253a5a1b3Sopenharmony_ci if (!client) { 26353a5a1b3Sopenharmony_ci char *str = stream_to_string(s); 26453a5a1b3Sopenharmony_ci 26553a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "%s isn't associated to any client.", str); 26653a5a1b3Sopenharmony_ci pa_xfree(str); 26753a5a1b3Sopenharmony_ci 26853a5a1b3Sopenharmony_ci return; 26953a5a1b3Sopenharmony_ci } 27053a5a1b3Sopenharmony_ci 27153a5a1b3Sopenharmony_ci object_path = pa_dbusiface_core_get_client_path(s->core, client); 27253a5a1b3Sopenharmony_ci 27353a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &object_path); 27453a5a1b3Sopenharmony_ci} 27553a5a1b3Sopenharmony_ci 27653a5a1b3Sopenharmony_cistatic void handle_get_device(DBusConnection *conn, DBusMessage *msg, void *userdata) { 27753a5a1b3Sopenharmony_ci pa_dbusiface_stream *s = userdata; 27853a5a1b3Sopenharmony_ci const char *device = NULL; 27953a5a1b3Sopenharmony_ci 28053a5a1b3Sopenharmony_ci pa_assert(conn); 28153a5a1b3Sopenharmony_ci pa_assert(msg); 28253a5a1b3Sopenharmony_ci pa_assert(s); 28353a5a1b3Sopenharmony_ci 28453a5a1b3Sopenharmony_ci if (s->type == STREAM_TYPE_PLAYBACK) 28553a5a1b3Sopenharmony_ci device = pa_dbusiface_core_get_sink_path(s->core, s->sink); 28653a5a1b3Sopenharmony_ci else 28753a5a1b3Sopenharmony_ci device = pa_dbusiface_core_get_source_path(s->core, s->source); 28853a5a1b3Sopenharmony_ci 28953a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, &device); 29053a5a1b3Sopenharmony_ci} 29153a5a1b3Sopenharmony_ci 29253a5a1b3Sopenharmony_cistatic void handle_get_sample_format(DBusConnection *conn, DBusMessage *msg, void *userdata) { 29353a5a1b3Sopenharmony_ci pa_dbusiface_stream *s = userdata; 29453a5a1b3Sopenharmony_ci dbus_uint32_t sample_format = 0; 29553a5a1b3Sopenharmony_ci 29653a5a1b3Sopenharmony_ci pa_assert(conn); 29753a5a1b3Sopenharmony_ci pa_assert(msg); 29853a5a1b3Sopenharmony_ci pa_assert(s); 29953a5a1b3Sopenharmony_ci 30053a5a1b3Sopenharmony_ci sample_format = (s->type == STREAM_TYPE_PLAYBACK) 30153a5a1b3Sopenharmony_ci ? s->sink_input->sample_spec.format 30253a5a1b3Sopenharmony_ci : s->source_output->sample_spec.format; 30353a5a1b3Sopenharmony_ci 30453a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &sample_format); 30553a5a1b3Sopenharmony_ci} 30653a5a1b3Sopenharmony_ci 30753a5a1b3Sopenharmony_cistatic void handle_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata) { 30853a5a1b3Sopenharmony_ci pa_dbusiface_stream *s = userdata; 30953a5a1b3Sopenharmony_ci 31053a5a1b3Sopenharmony_ci pa_assert(conn); 31153a5a1b3Sopenharmony_ci pa_assert(msg); 31253a5a1b3Sopenharmony_ci pa_assert(s); 31353a5a1b3Sopenharmony_ci 31453a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &s->sample_rate); 31553a5a1b3Sopenharmony_ci} 31653a5a1b3Sopenharmony_ci 31753a5a1b3Sopenharmony_cistatic void handle_get_channels(DBusConnection *conn, DBusMessage *msg, void *userdata) { 31853a5a1b3Sopenharmony_ci pa_dbusiface_stream *s = userdata; 31953a5a1b3Sopenharmony_ci pa_channel_map *channel_map = NULL; 32053a5a1b3Sopenharmony_ci dbus_uint32_t channels[PA_CHANNELS_MAX]; 32153a5a1b3Sopenharmony_ci unsigned i = 0; 32253a5a1b3Sopenharmony_ci 32353a5a1b3Sopenharmony_ci pa_assert(conn); 32453a5a1b3Sopenharmony_ci pa_assert(msg); 32553a5a1b3Sopenharmony_ci pa_assert(s); 32653a5a1b3Sopenharmony_ci 32753a5a1b3Sopenharmony_ci channel_map = (s->type == STREAM_TYPE_PLAYBACK) ? &s->sink_input->channel_map : &s->source_output->channel_map; 32853a5a1b3Sopenharmony_ci 32953a5a1b3Sopenharmony_ci for (i = 0; i < channel_map->channels; ++i) 33053a5a1b3Sopenharmony_ci channels[i] = channel_map->map[i]; 33153a5a1b3Sopenharmony_ci 33253a5a1b3Sopenharmony_ci pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_UINT32, channels, channel_map->channels); 33353a5a1b3Sopenharmony_ci} 33453a5a1b3Sopenharmony_ci 33553a5a1b3Sopenharmony_cistatic void handle_get_volume(DBusConnection *conn, DBusMessage *msg, void *userdata) { 33653a5a1b3Sopenharmony_ci pa_dbusiface_stream *s = userdata; 33753a5a1b3Sopenharmony_ci dbus_uint32_t volume[PA_CHANNELS_MAX]; 33853a5a1b3Sopenharmony_ci unsigned i = 0; 33953a5a1b3Sopenharmony_ci 34053a5a1b3Sopenharmony_ci pa_assert(conn); 34153a5a1b3Sopenharmony_ci pa_assert(msg); 34253a5a1b3Sopenharmony_ci pa_assert(s); 34353a5a1b3Sopenharmony_ci 34453a5a1b3Sopenharmony_ci if (!s->has_volume) { 34553a5a1b3Sopenharmony_ci char *str = stream_to_string(s); 34653a5a1b3Sopenharmony_ci 34753a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "%s doesn't have volume.", str); 34853a5a1b3Sopenharmony_ci pa_xfree(str); 34953a5a1b3Sopenharmony_ci 35053a5a1b3Sopenharmony_ci return; 35153a5a1b3Sopenharmony_ci } 35253a5a1b3Sopenharmony_ci 35353a5a1b3Sopenharmony_ci for (i = 0; i < s->volume.channels; ++i) 35453a5a1b3Sopenharmony_ci volume[i] = s->volume.values[i]; 35553a5a1b3Sopenharmony_ci 35653a5a1b3Sopenharmony_ci pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_UINT32, volume, s->volume.channels); 35753a5a1b3Sopenharmony_ci} 35853a5a1b3Sopenharmony_ci 35953a5a1b3Sopenharmony_cistatic void handle_set_volume(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) { 36053a5a1b3Sopenharmony_ci pa_dbusiface_stream *s = userdata; 36153a5a1b3Sopenharmony_ci bool volume_writable = true; 36253a5a1b3Sopenharmony_ci DBusMessageIter array_iter; 36353a5a1b3Sopenharmony_ci int stream_channels = 0; 36453a5a1b3Sopenharmony_ci dbus_uint32_t *volume = NULL; 36553a5a1b3Sopenharmony_ci int n_volume_entries = 0; 36653a5a1b3Sopenharmony_ci pa_cvolume new_vol; 36753a5a1b3Sopenharmony_ci int i = 0; 36853a5a1b3Sopenharmony_ci 36953a5a1b3Sopenharmony_ci pa_assert(conn); 37053a5a1b3Sopenharmony_ci pa_assert(msg); 37153a5a1b3Sopenharmony_ci pa_assert(iter); 37253a5a1b3Sopenharmony_ci pa_assert(s); 37353a5a1b3Sopenharmony_ci 37453a5a1b3Sopenharmony_ci volume_writable = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->volume_writable : false; 37553a5a1b3Sopenharmony_ci 37653a5a1b3Sopenharmony_ci if (!s->has_volume || !volume_writable) { 37753a5a1b3Sopenharmony_ci char *str = stream_to_string(s); 37853a5a1b3Sopenharmony_ci 37953a5a1b3Sopenharmony_ci if (!s->has_volume) 38053a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "%s doesn't have volume.", str); 38153a5a1b3Sopenharmony_ci else if (!volume_writable) 38253a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, DBUS_ERROR_ACCESS_DENIED, "%s has read-only volume.", str); 38353a5a1b3Sopenharmony_ci pa_xfree(str); 38453a5a1b3Sopenharmony_ci 38553a5a1b3Sopenharmony_ci return; 38653a5a1b3Sopenharmony_ci } 38753a5a1b3Sopenharmony_ci 38853a5a1b3Sopenharmony_ci stream_channels = s->sink_input->channel_map.channels; 38953a5a1b3Sopenharmony_ci 39053a5a1b3Sopenharmony_ci dbus_message_iter_recurse(iter, &array_iter); 39153a5a1b3Sopenharmony_ci dbus_message_iter_get_fixed_array(&array_iter, &volume, &n_volume_entries); 39253a5a1b3Sopenharmony_ci 39353a5a1b3Sopenharmony_ci if (n_volume_entries != stream_channels && n_volume_entries != 1) { 39453a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, 39553a5a1b3Sopenharmony_ci "Expected %u volume entries, got %u.", stream_channels, n_volume_entries); 39653a5a1b3Sopenharmony_ci return; 39753a5a1b3Sopenharmony_ci } 39853a5a1b3Sopenharmony_ci 39953a5a1b3Sopenharmony_ci pa_cvolume_init(&new_vol); 40053a5a1b3Sopenharmony_ci new_vol.channels = n_volume_entries; 40153a5a1b3Sopenharmony_ci 40253a5a1b3Sopenharmony_ci for (i = 0; i < n_volume_entries; ++i) { 40353a5a1b3Sopenharmony_ci if (!PA_VOLUME_IS_VALID(volume[i])) { 40453a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Invalid volume: %u", volume[i]); 40553a5a1b3Sopenharmony_ci return; 40653a5a1b3Sopenharmony_ci } 40753a5a1b3Sopenharmony_ci new_vol.values[i] = volume[i]; 40853a5a1b3Sopenharmony_ci } 40953a5a1b3Sopenharmony_ci 41053a5a1b3Sopenharmony_ci pa_sink_input_set_volume(s->sink_input, &new_vol, true, true); 41153a5a1b3Sopenharmony_ci 41253a5a1b3Sopenharmony_ci pa_dbus_send_empty_reply(conn, msg); 41353a5a1b3Sopenharmony_ci} 41453a5a1b3Sopenharmony_ci 41553a5a1b3Sopenharmony_cistatic void handle_get_mute(DBusConnection *conn, DBusMessage *msg, void *userdata) { 41653a5a1b3Sopenharmony_ci pa_dbusiface_stream *s = userdata; 41753a5a1b3Sopenharmony_ci 41853a5a1b3Sopenharmony_ci pa_assert(conn); 41953a5a1b3Sopenharmony_ci pa_assert(msg); 42053a5a1b3Sopenharmony_ci pa_assert(s); 42153a5a1b3Sopenharmony_ci 42253a5a1b3Sopenharmony_ci if (s->type == STREAM_TYPE_RECORD) { 42353a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "Record streams don't have mute."); 42453a5a1b3Sopenharmony_ci return; 42553a5a1b3Sopenharmony_ci } 42653a5a1b3Sopenharmony_ci 42753a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &s->mute); 42853a5a1b3Sopenharmony_ci} 42953a5a1b3Sopenharmony_ci 43053a5a1b3Sopenharmony_cistatic void handle_set_mute(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) { 43153a5a1b3Sopenharmony_ci pa_dbusiface_stream *s = userdata; 43253a5a1b3Sopenharmony_ci dbus_bool_t mute = FALSE; 43353a5a1b3Sopenharmony_ci 43453a5a1b3Sopenharmony_ci pa_assert(conn); 43553a5a1b3Sopenharmony_ci pa_assert(msg); 43653a5a1b3Sopenharmony_ci pa_assert(iter); 43753a5a1b3Sopenharmony_ci pa_assert(s); 43853a5a1b3Sopenharmony_ci 43953a5a1b3Sopenharmony_ci dbus_message_iter_get_basic(iter, &mute); 44053a5a1b3Sopenharmony_ci 44153a5a1b3Sopenharmony_ci if (s->type == STREAM_TYPE_RECORD) { 44253a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "Record streams don't have mute."); 44353a5a1b3Sopenharmony_ci return; 44453a5a1b3Sopenharmony_ci } 44553a5a1b3Sopenharmony_ci 44653a5a1b3Sopenharmony_ci pa_sink_input_set_mute(s->sink_input, mute, true); 44753a5a1b3Sopenharmony_ci 44853a5a1b3Sopenharmony_ci pa_dbus_send_empty_reply(conn, msg); 44953a5a1b3Sopenharmony_ci} 45053a5a1b3Sopenharmony_ci 45153a5a1b3Sopenharmony_cistatic void handle_get_buffer_latency(DBusConnection *conn, DBusMessage *msg, void *userdata) { 45253a5a1b3Sopenharmony_ci pa_dbusiface_stream *s = userdata; 45353a5a1b3Sopenharmony_ci dbus_uint64_t buffer_latency = 0; 45453a5a1b3Sopenharmony_ci 45553a5a1b3Sopenharmony_ci pa_assert(conn); 45653a5a1b3Sopenharmony_ci pa_assert(msg); 45753a5a1b3Sopenharmony_ci pa_assert(s); 45853a5a1b3Sopenharmony_ci 45953a5a1b3Sopenharmony_ci if (s->type == STREAM_TYPE_PLAYBACK) 46053a5a1b3Sopenharmony_ci buffer_latency = pa_sink_input_get_latency(s->sink_input, NULL); 46153a5a1b3Sopenharmony_ci else 46253a5a1b3Sopenharmony_ci buffer_latency = pa_source_output_get_latency(s->source_output, NULL); 46353a5a1b3Sopenharmony_ci 46453a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT64, &buffer_latency); 46553a5a1b3Sopenharmony_ci} 46653a5a1b3Sopenharmony_ci 46753a5a1b3Sopenharmony_cistatic void handle_get_device_latency(DBusConnection *conn, DBusMessage *msg, void *userdata) { 46853a5a1b3Sopenharmony_ci pa_dbusiface_stream *s = userdata; 46953a5a1b3Sopenharmony_ci dbus_uint64_t device_latency = 0; 47053a5a1b3Sopenharmony_ci 47153a5a1b3Sopenharmony_ci pa_assert(conn); 47253a5a1b3Sopenharmony_ci pa_assert(msg); 47353a5a1b3Sopenharmony_ci pa_assert(s); 47453a5a1b3Sopenharmony_ci 47553a5a1b3Sopenharmony_ci if (s->type == STREAM_TYPE_PLAYBACK) 47653a5a1b3Sopenharmony_ci pa_sink_input_get_latency(s->sink_input, &device_latency); 47753a5a1b3Sopenharmony_ci else 47853a5a1b3Sopenharmony_ci pa_source_output_get_latency(s->source_output, &device_latency); 47953a5a1b3Sopenharmony_ci 48053a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT64, &device_latency); 48153a5a1b3Sopenharmony_ci} 48253a5a1b3Sopenharmony_ci 48353a5a1b3Sopenharmony_cistatic void handle_get_resample_method(DBusConnection *conn, DBusMessage *msg, void *userdata) { 48453a5a1b3Sopenharmony_ci pa_dbusiface_stream *s = userdata; 48553a5a1b3Sopenharmony_ci const char *resample_method = NULL; 48653a5a1b3Sopenharmony_ci 48753a5a1b3Sopenharmony_ci pa_assert(conn); 48853a5a1b3Sopenharmony_ci pa_assert(msg); 48953a5a1b3Sopenharmony_ci pa_assert(s); 49053a5a1b3Sopenharmony_ci 49153a5a1b3Sopenharmony_ci if (s->type == STREAM_TYPE_PLAYBACK) 49253a5a1b3Sopenharmony_ci resample_method = pa_resample_method_to_string(s->sink_input->actual_resample_method); 49353a5a1b3Sopenharmony_ci else 49453a5a1b3Sopenharmony_ci resample_method = pa_resample_method_to_string(s->source_output->actual_resample_method); 49553a5a1b3Sopenharmony_ci 49653a5a1b3Sopenharmony_ci if (!resample_method) 49753a5a1b3Sopenharmony_ci resample_method = ""; 49853a5a1b3Sopenharmony_ci 49953a5a1b3Sopenharmony_ci pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &resample_method); 50053a5a1b3Sopenharmony_ci} 50153a5a1b3Sopenharmony_ci 50253a5a1b3Sopenharmony_cistatic void handle_get_property_list(DBusConnection *conn, DBusMessage *msg, void *userdata) { 50353a5a1b3Sopenharmony_ci pa_dbusiface_stream *s = userdata; 50453a5a1b3Sopenharmony_ci 50553a5a1b3Sopenharmony_ci pa_assert(conn); 50653a5a1b3Sopenharmony_ci pa_assert(msg); 50753a5a1b3Sopenharmony_ci pa_assert(s); 50853a5a1b3Sopenharmony_ci 50953a5a1b3Sopenharmony_ci pa_dbus_send_proplist_variant_reply(conn, msg, s->proplist); 51053a5a1b3Sopenharmony_ci} 51153a5a1b3Sopenharmony_ci 51253a5a1b3Sopenharmony_cistatic void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata) { 51353a5a1b3Sopenharmony_ci pa_dbusiface_stream *s = userdata; 51453a5a1b3Sopenharmony_ci DBusMessage *reply = NULL; 51553a5a1b3Sopenharmony_ci DBusMessageIter msg_iter; 51653a5a1b3Sopenharmony_ci DBusMessageIter dict_iter; 51753a5a1b3Sopenharmony_ci dbus_uint32_t idx = 0; 51853a5a1b3Sopenharmony_ci const char *driver = NULL; 51953a5a1b3Sopenharmony_ci pa_module *owner_module = NULL; 52053a5a1b3Sopenharmony_ci const char *owner_module_path = NULL; 52153a5a1b3Sopenharmony_ci pa_client *client = NULL; 52253a5a1b3Sopenharmony_ci const char *client_path = NULL; 52353a5a1b3Sopenharmony_ci const char *device = NULL; 52453a5a1b3Sopenharmony_ci dbus_uint32_t sample_format = 0; 52553a5a1b3Sopenharmony_ci pa_channel_map *channel_map = NULL; 52653a5a1b3Sopenharmony_ci dbus_uint32_t channels[PA_CHANNELS_MAX]; 52753a5a1b3Sopenharmony_ci dbus_uint32_t volume[PA_CHANNELS_MAX]; 52853a5a1b3Sopenharmony_ci dbus_uint64_t buffer_latency = 0; 52953a5a1b3Sopenharmony_ci dbus_uint64_t device_latency = 0; 53053a5a1b3Sopenharmony_ci const char *resample_method = NULL; 53153a5a1b3Sopenharmony_ci unsigned i = 0; 53253a5a1b3Sopenharmony_ci 53353a5a1b3Sopenharmony_ci pa_assert(conn); 53453a5a1b3Sopenharmony_ci pa_assert(msg); 53553a5a1b3Sopenharmony_ci pa_assert(s); 53653a5a1b3Sopenharmony_ci 53753a5a1b3Sopenharmony_ci if (s->has_volume) { 53853a5a1b3Sopenharmony_ci for (i = 0; i < s->volume.channels; ++i) 53953a5a1b3Sopenharmony_ci volume[i] = s->volume.values[i]; 54053a5a1b3Sopenharmony_ci } 54153a5a1b3Sopenharmony_ci 54253a5a1b3Sopenharmony_ci if (s->type == STREAM_TYPE_PLAYBACK) { 54353a5a1b3Sopenharmony_ci idx = s->sink_input->index; 54453a5a1b3Sopenharmony_ci driver = s->sink_input->driver; 54553a5a1b3Sopenharmony_ci owner_module = s->sink_input->module; 54653a5a1b3Sopenharmony_ci client = s->sink_input->client; 54753a5a1b3Sopenharmony_ci device = pa_dbusiface_core_get_sink_path(s->core, s->sink); 54853a5a1b3Sopenharmony_ci sample_format = s->sink_input->sample_spec.format; 54953a5a1b3Sopenharmony_ci channel_map = &s->sink_input->channel_map; 55053a5a1b3Sopenharmony_ci buffer_latency = pa_sink_input_get_latency(s->sink_input, &device_latency); 55153a5a1b3Sopenharmony_ci resample_method = pa_resample_method_to_string(s->sink_input->actual_resample_method); 55253a5a1b3Sopenharmony_ci } else { 55353a5a1b3Sopenharmony_ci idx = s->source_output->index; 55453a5a1b3Sopenharmony_ci driver = s->source_output->driver; 55553a5a1b3Sopenharmony_ci owner_module = s->source_output->module; 55653a5a1b3Sopenharmony_ci client = s->source_output->client; 55753a5a1b3Sopenharmony_ci device = pa_dbusiface_core_get_source_path(s->core, s->source); 55853a5a1b3Sopenharmony_ci sample_format = s->source_output->sample_spec.format; 55953a5a1b3Sopenharmony_ci channel_map = &s->source_output->channel_map; 56053a5a1b3Sopenharmony_ci buffer_latency = pa_source_output_get_latency(s->source_output, &device_latency); 56153a5a1b3Sopenharmony_ci resample_method = pa_resample_method_to_string(s->source_output->actual_resample_method); 56253a5a1b3Sopenharmony_ci } 56353a5a1b3Sopenharmony_ci if (owner_module) 56453a5a1b3Sopenharmony_ci owner_module_path = pa_dbusiface_core_get_module_path(s->core, owner_module); 56553a5a1b3Sopenharmony_ci if (client) 56653a5a1b3Sopenharmony_ci client_path = pa_dbusiface_core_get_client_path(s->core, client); 56753a5a1b3Sopenharmony_ci for (i = 0; i < channel_map->channels; ++i) 56853a5a1b3Sopenharmony_ci channels[i] = channel_map->map[i]; 56953a5a1b3Sopenharmony_ci if (!resample_method) 57053a5a1b3Sopenharmony_ci resample_method = ""; 57153a5a1b3Sopenharmony_ci 57253a5a1b3Sopenharmony_ci pa_assert_se((reply = dbus_message_new_method_return(msg))); 57353a5a1b3Sopenharmony_ci 57453a5a1b3Sopenharmony_ci dbus_message_iter_init_append(reply, &msg_iter); 57553a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter)); 57653a5a1b3Sopenharmony_ci 57753a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_INDEX].property_name, DBUS_TYPE_UINT32, &idx); 57853a5a1b3Sopenharmony_ci 57953a5a1b3Sopenharmony_ci if (driver) 58053a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DRIVER].property_name, DBUS_TYPE_STRING, &driver); 58153a5a1b3Sopenharmony_ci 58253a5a1b3Sopenharmony_ci if (owner_module) 58353a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_OWNER_MODULE].property_name, DBUS_TYPE_OBJECT_PATH, &owner_module_path); 58453a5a1b3Sopenharmony_ci 58553a5a1b3Sopenharmony_ci if (client) 58653a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CLIENT].property_name, DBUS_TYPE_OBJECT_PATH, &client_path); 58753a5a1b3Sopenharmony_ci 58853a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DEVICE].property_name, DBUS_TYPE_OBJECT_PATH, &device); 58953a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SAMPLE_FORMAT].property_name, DBUS_TYPE_UINT32, &sample_format); 59053a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SAMPLE_RATE].property_name, DBUS_TYPE_UINT32, &s->sample_rate); 59153a5a1b3Sopenharmony_ci pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CHANNELS].property_name, DBUS_TYPE_UINT32, channels, channel_map->channels); 59253a5a1b3Sopenharmony_ci 59353a5a1b3Sopenharmony_ci if (s->has_volume) { 59453a5a1b3Sopenharmony_ci pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_VOLUME].property_name, DBUS_TYPE_UINT32, volume, s->volume.channels); 59553a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_MUTE].property_name, DBUS_TYPE_BOOLEAN, &s->mute); 59653a5a1b3Sopenharmony_ci } 59753a5a1b3Sopenharmony_ci 59853a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_BUFFER_LATENCY].property_name, DBUS_TYPE_UINT64, &buffer_latency); 59953a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DEVICE_LATENCY].property_name, DBUS_TYPE_UINT64, &device_latency); 60053a5a1b3Sopenharmony_ci pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_RESAMPLE_METHOD].property_name, DBUS_TYPE_STRING, &resample_method); 60153a5a1b3Sopenharmony_ci pa_dbus_append_proplist_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_PROPERTY_LIST].property_name, s->proplist); 60253a5a1b3Sopenharmony_ci 60353a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter)); 60453a5a1b3Sopenharmony_ci pa_assert_se(dbus_connection_send(conn, reply, NULL)); 60553a5a1b3Sopenharmony_ci dbus_message_unref(reply); 60653a5a1b3Sopenharmony_ci} 60753a5a1b3Sopenharmony_ci 60853a5a1b3Sopenharmony_cistatic void handle_move(DBusConnection *conn, DBusMessage *msg, void *userdata) { 60953a5a1b3Sopenharmony_ci pa_dbusiface_stream *s = userdata; 61053a5a1b3Sopenharmony_ci const char *device = NULL; 61153a5a1b3Sopenharmony_ci 61253a5a1b3Sopenharmony_ci pa_assert(conn); 61353a5a1b3Sopenharmony_ci pa_assert(msg); 61453a5a1b3Sopenharmony_ci pa_assert(s); 61553a5a1b3Sopenharmony_ci 61653a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &device, DBUS_TYPE_INVALID)); 61753a5a1b3Sopenharmony_ci 61853a5a1b3Sopenharmony_ci if (s->type == STREAM_TYPE_PLAYBACK) { 61953a5a1b3Sopenharmony_ci pa_sink *sink = pa_dbusiface_core_get_sink(s->core, device); 62053a5a1b3Sopenharmony_ci 62153a5a1b3Sopenharmony_ci if (!sink) { 62253a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "%s: No such sink.", device); 62353a5a1b3Sopenharmony_ci return; 62453a5a1b3Sopenharmony_ci } 62553a5a1b3Sopenharmony_ci 62653a5a1b3Sopenharmony_ci if (pa_sink_input_move_to(s->sink_input, sink, true) < 0) { 62753a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, 62853a5a1b3Sopenharmony_ci "Moving playback stream %u to sink %s failed.", s->sink_input->index, sink->name); 62953a5a1b3Sopenharmony_ci return; 63053a5a1b3Sopenharmony_ci } 63153a5a1b3Sopenharmony_ci } else { 63253a5a1b3Sopenharmony_ci pa_source *source = pa_dbusiface_core_get_source(s->core, device); 63353a5a1b3Sopenharmony_ci 63453a5a1b3Sopenharmony_ci if (!source) { 63553a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND, "%s: No such source.", device); 63653a5a1b3Sopenharmony_ci return; 63753a5a1b3Sopenharmony_ci } 63853a5a1b3Sopenharmony_ci 63953a5a1b3Sopenharmony_ci if (pa_source_output_move_to(s->source_output, source, true) < 0) { 64053a5a1b3Sopenharmony_ci pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, 64153a5a1b3Sopenharmony_ci "Moving record stream %u to source %s failed.", s->source_output->index, source->name); 64253a5a1b3Sopenharmony_ci return; 64353a5a1b3Sopenharmony_ci } 64453a5a1b3Sopenharmony_ci } 64553a5a1b3Sopenharmony_ci 64653a5a1b3Sopenharmony_ci pa_dbus_send_empty_reply(conn, msg); 64753a5a1b3Sopenharmony_ci} 64853a5a1b3Sopenharmony_ci 64953a5a1b3Sopenharmony_cistatic void handle_kill(DBusConnection *conn, DBusMessage *msg, void *userdata) { 65053a5a1b3Sopenharmony_ci pa_dbusiface_stream *s = userdata; 65153a5a1b3Sopenharmony_ci 65253a5a1b3Sopenharmony_ci pa_assert(conn); 65353a5a1b3Sopenharmony_ci pa_assert(msg); 65453a5a1b3Sopenharmony_ci pa_assert(s); 65553a5a1b3Sopenharmony_ci 65653a5a1b3Sopenharmony_ci if (s->type == STREAM_TYPE_PLAYBACK) 65753a5a1b3Sopenharmony_ci pa_sink_input_kill(s->sink_input); 65853a5a1b3Sopenharmony_ci else 65953a5a1b3Sopenharmony_ci pa_source_output_kill(s->source_output); 66053a5a1b3Sopenharmony_ci 66153a5a1b3Sopenharmony_ci pa_dbus_send_empty_reply(conn, msg); 66253a5a1b3Sopenharmony_ci} 66353a5a1b3Sopenharmony_ci 66453a5a1b3Sopenharmony_cistatic void check_and_signal_rate(pa_dbusiface_stream *s) { 66553a5a1b3Sopenharmony_ci DBusMessage *signal_msg = NULL; 66653a5a1b3Sopenharmony_ci uint32_t new_sample_rate = 0; 66753a5a1b3Sopenharmony_ci 66853a5a1b3Sopenharmony_ci pa_assert(s); 66953a5a1b3Sopenharmony_ci 67053a5a1b3Sopenharmony_ci new_sample_rate = (s->type == STREAM_TYPE_PLAYBACK) 67153a5a1b3Sopenharmony_ci ? s->sink_input->sample_spec.rate 67253a5a1b3Sopenharmony_ci : s->source_output->sample_spec.rate; 67353a5a1b3Sopenharmony_ci 67453a5a1b3Sopenharmony_ci if (s->sample_rate != new_sample_rate) { 67553a5a1b3Sopenharmony_ci s->sample_rate = new_sample_rate; 67653a5a1b3Sopenharmony_ci 67753a5a1b3Sopenharmony_ci pa_assert_se(signal_msg = dbus_message_new_signal(s->path, 67853a5a1b3Sopenharmony_ci PA_DBUSIFACE_STREAM_INTERFACE, 67953a5a1b3Sopenharmony_ci signals[SIGNAL_SAMPLE_RATE_UPDATED].name)); 68053a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_UINT32, &s->sample_rate, DBUS_TYPE_INVALID)); 68153a5a1b3Sopenharmony_ci 68253a5a1b3Sopenharmony_ci pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg); 68353a5a1b3Sopenharmony_ci dbus_message_unref(signal_msg); 68453a5a1b3Sopenharmony_ci } 68553a5a1b3Sopenharmony_ci} 68653a5a1b3Sopenharmony_ci 68753a5a1b3Sopenharmony_cistatic pa_hook_result_t move_finish_cb(void *hook_data, void *call_data, void *slot_data) { 68853a5a1b3Sopenharmony_ci pa_dbusiface_stream *s = slot_data; 68953a5a1b3Sopenharmony_ci const char *new_device_path = NULL; 69053a5a1b3Sopenharmony_ci DBusMessage *signal_msg = NULL; 69153a5a1b3Sopenharmony_ci 69253a5a1b3Sopenharmony_ci if ((s->type == STREAM_TYPE_PLAYBACK && s->sink_input != call_data) || 69353a5a1b3Sopenharmony_ci (s->type == STREAM_TYPE_RECORD && s->source_output != call_data)) 69453a5a1b3Sopenharmony_ci return PA_HOOK_OK; 69553a5a1b3Sopenharmony_ci 69653a5a1b3Sopenharmony_ci if (s->type == STREAM_TYPE_PLAYBACK) { 69753a5a1b3Sopenharmony_ci pa_sink *new_sink = s->sink_input->sink; 69853a5a1b3Sopenharmony_ci 69953a5a1b3Sopenharmony_ci if (s->sink != new_sink) { 70053a5a1b3Sopenharmony_ci pa_sink_unref(s->sink); 70153a5a1b3Sopenharmony_ci s->sink = pa_sink_ref(new_sink); 70253a5a1b3Sopenharmony_ci 70353a5a1b3Sopenharmony_ci new_device_path = pa_dbusiface_core_get_sink_path(s->core, new_sink); 70453a5a1b3Sopenharmony_ci 70553a5a1b3Sopenharmony_ci pa_assert_se(signal_msg = dbus_message_new_signal(s->path, 70653a5a1b3Sopenharmony_ci PA_DBUSIFACE_STREAM_INTERFACE, 70753a5a1b3Sopenharmony_ci signals[SIGNAL_DEVICE_UPDATED].name)); 70853a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &new_device_path, DBUS_TYPE_INVALID)); 70953a5a1b3Sopenharmony_ci 71053a5a1b3Sopenharmony_ci pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg); 71153a5a1b3Sopenharmony_ci dbus_message_unref(signal_msg); 71253a5a1b3Sopenharmony_ci } 71353a5a1b3Sopenharmony_ci } else { 71453a5a1b3Sopenharmony_ci pa_source *new_source = s->source_output->source; 71553a5a1b3Sopenharmony_ci 71653a5a1b3Sopenharmony_ci if (s->source != new_source) { 71753a5a1b3Sopenharmony_ci pa_source_unref(s->source); 71853a5a1b3Sopenharmony_ci s->source = pa_source_ref(new_source); 71953a5a1b3Sopenharmony_ci 72053a5a1b3Sopenharmony_ci new_device_path = pa_dbusiface_core_get_source_path(s->core, new_source); 72153a5a1b3Sopenharmony_ci 72253a5a1b3Sopenharmony_ci pa_assert_se(signal_msg = dbus_message_new_signal(s->path, 72353a5a1b3Sopenharmony_ci PA_DBUSIFACE_STREAM_INTERFACE, 72453a5a1b3Sopenharmony_ci signals[SIGNAL_DEVICE_UPDATED].name)); 72553a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &new_device_path, DBUS_TYPE_INVALID)); 72653a5a1b3Sopenharmony_ci 72753a5a1b3Sopenharmony_ci pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg); 72853a5a1b3Sopenharmony_ci dbus_message_unref(signal_msg); 72953a5a1b3Sopenharmony_ci } 73053a5a1b3Sopenharmony_ci } 73153a5a1b3Sopenharmony_ci 73253a5a1b3Sopenharmony_ci check_and_signal_rate(s); 73353a5a1b3Sopenharmony_ci 73453a5a1b3Sopenharmony_ci return PA_HOOK_OK; 73553a5a1b3Sopenharmony_ci} 73653a5a1b3Sopenharmony_ci 73753a5a1b3Sopenharmony_cistatic pa_hook_result_t volume_changed_cb(void *hook_data, void *call_data, void *slot_data) { 73853a5a1b3Sopenharmony_ci pa_dbusiface_stream *s = slot_data; 73953a5a1b3Sopenharmony_ci DBusMessage *signal_msg = NULL; 74053a5a1b3Sopenharmony_ci unsigned i = 0; 74153a5a1b3Sopenharmony_ci 74253a5a1b3Sopenharmony_ci if ((s->type == STREAM_TYPE_PLAYBACK && s->sink_input != call_data) || 74353a5a1b3Sopenharmony_ci (s->type == STREAM_TYPE_RECORD && s->source_output != call_data)) 74453a5a1b3Sopenharmony_ci return PA_HOOK_OK; 74553a5a1b3Sopenharmony_ci 74653a5a1b3Sopenharmony_ci if (s->type == STREAM_TYPE_PLAYBACK && s->has_volume) { 74753a5a1b3Sopenharmony_ci pa_cvolume new_volume; 74853a5a1b3Sopenharmony_ci 74953a5a1b3Sopenharmony_ci pa_sink_input_get_volume(s->sink_input, &new_volume, true); 75053a5a1b3Sopenharmony_ci 75153a5a1b3Sopenharmony_ci if (!pa_cvolume_equal(&s->volume, &new_volume)) { 75253a5a1b3Sopenharmony_ci dbus_uint32_t volume[PA_CHANNELS_MAX]; 75353a5a1b3Sopenharmony_ci dbus_uint32_t *volume_ptr = volume; 75453a5a1b3Sopenharmony_ci 75553a5a1b3Sopenharmony_ci s->volume = new_volume; 75653a5a1b3Sopenharmony_ci 75753a5a1b3Sopenharmony_ci for (i = 0; i < s->volume.channels; ++i) 75853a5a1b3Sopenharmony_ci volume[i] = s->volume.values[i]; 75953a5a1b3Sopenharmony_ci 76053a5a1b3Sopenharmony_ci pa_assert_se(signal_msg = dbus_message_new_signal(s->path, 76153a5a1b3Sopenharmony_ci PA_DBUSIFACE_STREAM_INTERFACE, 76253a5a1b3Sopenharmony_ci signals[SIGNAL_VOLUME_UPDATED].name)); 76353a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_append_args(signal_msg, 76453a5a1b3Sopenharmony_ci DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &volume_ptr, s->volume.channels, 76553a5a1b3Sopenharmony_ci DBUS_TYPE_INVALID)); 76653a5a1b3Sopenharmony_ci 76753a5a1b3Sopenharmony_ci pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg); 76853a5a1b3Sopenharmony_ci dbus_message_unref(signal_msg); 76953a5a1b3Sopenharmony_ci } 77053a5a1b3Sopenharmony_ci } 77153a5a1b3Sopenharmony_ci 77253a5a1b3Sopenharmony_ci return PA_HOOK_OK; 77353a5a1b3Sopenharmony_ci} 77453a5a1b3Sopenharmony_ci 77553a5a1b3Sopenharmony_cistatic pa_hook_result_t mute_changed_cb(void *hook_data, void *call_data, void *slot_data) { 77653a5a1b3Sopenharmony_ci pa_dbusiface_stream *s = slot_data; 77753a5a1b3Sopenharmony_ci DBusMessage *signal_msg = NULL; 77853a5a1b3Sopenharmony_ci 77953a5a1b3Sopenharmony_ci if ((s->type == STREAM_TYPE_PLAYBACK && s->sink_input != call_data) || 78053a5a1b3Sopenharmony_ci (s->type == STREAM_TYPE_RECORD && s->source_output != call_data)) 78153a5a1b3Sopenharmony_ci return PA_HOOK_OK; 78253a5a1b3Sopenharmony_ci 78353a5a1b3Sopenharmony_ci if (s->type == STREAM_TYPE_PLAYBACK) { 78453a5a1b3Sopenharmony_ci bool new_mute = false; 78553a5a1b3Sopenharmony_ci 78653a5a1b3Sopenharmony_ci new_mute = s->sink_input->muted; 78753a5a1b3Sopenharmony_ci 78853a5a1b3Sopenharmony_ci if (s->mute != new_mute) { 78953a5a1b3Sopenharmony_ci s->mute = new_mute; 79053a5a1b3Sopenharmony_ci 79153a5a1b3Sopenharmony_ci pa_assert_se(signal_msg = dbus_message_new_signal(s->path, 79253a5a1b3Sopenharmony_ci PA_DBUSIFACE_STREAM_INTERFACE, 79353a5a1b3Sopenharmony_ci signals[SIGNAL_MUTE_UPDATED].name)); 79453a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_BOOLEAN, &s->mute, DBUS_TYPE_INVALID)); 79553a5a1b3Sopenharmony_ci 79653a5a1b3Sopenharmony_ci pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg); 79753a5a1b3Sopenharmony_ci dbus_message_unref(signal_msg); 79853a5a1b3Sopenharmony_ci signal_msg = NULL; 79953a5a1b3Sopenharmony_ci } 80053a5a1b3Sopenharmony_ci } 80153a5a1b3Sopenharmony_ci 80253a5a1b3Sopenharmony_ci return PA_HOOK_OK; 80353a5a1b3Sopenharmony_ci} 80453a5a1b3Sopenharmony_ci 80553a5a1b3Sopenharmony_cistatic pa_hook_result_t proplist_changed_cb(void *hook_data, void *call_data, void *slot_data) { 80653a5a1b3Sopenharmony_ci pa_dbusiface_stream *s = slot_data; 80753a5a1b3Sopenharmony_ci DBusMessage *signal_msg = NULL; 80853a5a1b3Sopenharmony_ci pa_proplist *new_proplist = NULL; 80953a5a1b3Sopenharmony_ci 81053a5a1b3Sopenharmony_ci if ((s->type == STREAM_TYPE_PLAYBACK && s->sink_input != call_data) || 81153a5a1b3Sopenharmony_ci (s->type == STREAM_TYPE_RECORD && s->source_output != call_data)) 81253a5a1b3Sopenharmony_ci return PA_HOOK_OK; 81353a5a1b3Sopenharmony_ci 81453a5a1b3Sopenharmony_ci new_proplist = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->proplist : s->source_output->proplist; 81553a5a1b3Sopenharmony_ci 81653a5a1b3Sopenharmony_ci if (!pa_proplist_equal(s->proplist, new_proplist)) { 81753a5a1b3Sopenharmony_ci DBusMessageIter msg_iter; 81853a5a1b3Sopenharmony_ci 81953a5a1b3Sopenharmony_ci pa_proplist_update(s->proplist, PA_UPDATE_SET, new_proplist); 82053a5a1b3Sopenharmony_ci 82153a5a1b3Sopenharmony_ci pa_assert_se(signal_msg = dbus_message_new_signal(s->path, 82253a5a1b3Sopenharmony_ci PA_DBUSIFACE_STREAM_INTERFACE, 82353a5a1b3Sopenharmony_ci signals[SIGNAL_PROPERTY_LIST_UPDATED].name)); 82453a5a1b3Sopenharmony_ci dbus_message_iter_init_append(signal_msg, &msg_iter); 82553a5a1b3Sopenharmony_ci pa_dbus_append_proplist(&msg_iter, s->proplist); 82653a5a1b3Sopenharmony_ci 82753a5a1b3Sopenharmony_ci pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg); 82853a5a1b3Sopenharmony_ci dbus_message_unref(signal_msg); 82953a5a1b3Sopenharmony_ci } 83053a5a1b3Sopenharmony_ci 83153a5a1b3Sopenharmony_ci return PA_HOOK_OK; 83253a5a1b3Sopenharmony_ci} 83353a5a1b3Sopenharmony_ci 83453a5a1b3Sopenharmony_cistatic pa_hook_result_t state_changed_cb(void *hook_data, void *call_data, void *slot_data) { 83553a5a1b3Sopenharmony_ci pa_dbusiface_stream *s = slot_data; 83653a5a1b3Sopenharmony_ci 83753a5a1b3Sopenharmony_ci pa_assert(s); 83853a5a1b3Sopenharmony_ci 83953a5a1b3Sopenharmony_ci if ((s->type == STREAM_TYPE_PLAYBACK && s->sink_input != call_data) || 84053a5a1b3Sopenharmony_ci (s->type == STREAM_TYPE_RECORD && s->source_output != call_data)) 84153a5a1b3Sopenharmony_ci return PA_HOOK_OK; 84253a5a1b3Sopenharmony_ci 84353a5a1b3Sopenharmony_ci check_and_signal_rate(s); 84453a5a1b3Sopenharmony_ci 84553a5a1b3Sopenharmony_ci return PA_HOOK_OK; 84653a5a1b3Sopenharmony_ci} 84753a5a1b3Sopenharmony_ci 84853a5a1b3Sopenharmony_cistatic pa_hook_result_t send_event_cb(void *hook_data, void *call_data, void *slot_data) { 84953a5a1b3Sopenharmony_ci pa_dbusiface_stream *s = slot_data; 85053a5a1b3Sopenharmony_ci DBusMessage *signal_msg = NULL; 85153a5a1b3Sopenharmony_ci DBusMessageIter msg_iter; 85253a5a1b3Sopenharmony_ci const char *name = NULL; 85353a5a1b3Sopenharmony_ci pa_proplist *property_list = NULL; 85453a5a1b3Sopenharmony_ci 85553a5a1b3Sopenharmony_ci pa_assert(call_data); 85653a5a1b3Sopenharmony_ci pa_assert(s); 85753a5a1b3Sopenharmony_ci 85853a5a1b3Sopenharmony_ci if (s->type == STREAM_TYPE_PLAYBACK) { 85953a5a1b3Sopenharmony_ci pa_sink_input_send_event_hook_data *data = call_data; 86053a5a1b3Sopenharmony_ci 86153a5a1b3Sopenharmony_ci if (data->sink_input != s->sink_input) 86253a5a1b3Sopenharmony_ci return PA_HOOK_OK; 86353a5a1b3Sopenharmony_ci 86453a5a1b3Sopenharmony_ci name = data->event; 86553a5a1b3Sopenharmony_ci property_list = data->data; 86653a5a1b3Sopenharmony_ci } else { 86753a5a1b3Sopenharmony_ci pa_source_output_send_event_hook_data *data = call_data; 86853a5a1b3Sopenharmony_ci 86953a5a1b3Sopenharmony_ci if (data->source_output != s->source_output) 87053a5a1b3Sopenharmony_ci return PA_HOOK_OK; 87153a5a1b3Sopenharmony_ci 87253a5a1b3Sopenharmony_ci name = data->event; 87353a5a1b3Sopenharmony_ci property_list = data->data; 87453a5a1b3Sopenharmony_ci } 87553a5a1b3Sopenharmony_ci 87653a5a1b3Sopenharmony_ci pa_assert_se(signal_msg = dbus_message_new_signal(s->path, 87753a5a1b3Sopenharmony_ci PA_DBUSIFACE_STREAM_INTERFACE, 87853a5a1b3Sopenharmony_ci signals[SIGNAL_STREAM_EVENT].name)); 87953a5a1b3Sopenharmony_ci dbus_message_iter_init_append(signal_msg, &msg_iter); 88053a5a1b3Sopenharmony_ci pa_assert_se(dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &name)); 88153a5a1b3Sopenharmony_ci pa_dbus_append_proplist(&msg_iter, property_list); 88253a5a1b3Sopenharmony_ci 88353a5a1b3Sopenharmony_ci pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg); 88453a5a1b3Sopenharmony_ci dbus_message_unref(signal_msg); 88553a5a1b3Sopenharmony_ci 88653a5a1b3Sopenharmony_ci return PA_HOOK_OK; 88753a5a1b3Sopenharmony_ci} 88853a5a1b3Sopenharmony_ci 88953a5a1b3Sopenharmony_cipa_dbusiface_stream *pa_dbusiface_stream_new_playback(pa_dbusiface_core *core, pa_sink_input *sink_input) { 89053a5a1b3Sopenharmony_ci pa_dbusiface_stream *s; 89153a5a1b3Sopenharmony_ci 89253a5a1b3Sopenharmony_ci pa_assert(core); 89353a5a1b3Sopenharmony_ci pa_assert(sink_input); 89453a5a1b3Sopenharmony_ci 89553a5a1b3Sopenharmony_ci s = pa_xnew(pa_dbusiface_stream, 1); 89653a5a1b3Sopenharmony_ci s->core = core; 89753a5a1b3Sopenharmony_ci s->sink_input = pa_sink_input_ref(sink_input); 89853a5a1b3Sopenharmony_ci s->type = STREAM_TYPE_PLAYBACK; 89953a5a1b3Sopenharmony_ci s->path = pa_sprintf_malloc("%s/%s%u", PA_DBUS_CORE_OBJECT_PATH, PLAYBACK_OBJECT_NAME, sink_input->index); 90053a5a1b3Sopenharmony_ci s->sink = pa_sink_ref(sink_input->sink); 90153a5a1b3Sopenharmony_ci s->sample_rate = sink_input->sample_spec.rate; 90253a5a1b3Sopenharmony_ci s->has_volume = pa_sink_input_is_volume_readable(sink_input); 90353a5a1b3Sopenharmony_ci 90453a5a1b3Sopenharmony_ci if (s->has_volume) 90553a5a1b3Sopenharmony_ci pa_sink_input_get_volume(sink_input, &s->volume, true); 90653a5a1b3Sopenharmony_ci else 90753a5a1b3Sopenharmony_ci pa_cvolume_init(&s->volume); 90853a5a1b3Sopenharmony_ci 90953a5a1b3Sopenharmony_ci s->mute = sink_input->muted; 91053a5a1b3Sopenharmony_ci s->proplist = pa_proplist_copy(sink_input->proplist); 91153a5a1b3Sopenharmony_ci s->dbus_protocol = pa_dbus_protocol_get(sink_input->core); 91253a5a1b3Sopenharmony_ci s->send_event_slot = pa_hook_connect(&sink_input->core->hooks[PA_CORE_HOOK_SINK_INPUT_SEND_EVENT], 91353a5a1b3Sopenharmony_ci PA_HOOK_NORMAL, 91453a5a1b3Sopenharmony_ci send_event_cb, 91553a5a1b3Sopenharmony_ci s); 91653a5a1b3Sopenharmony_ci s->move_finish_slot = pa_hook_connect(&sink_input->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FINISH], 91753a5a1b3Sopenharmony_ci PA_HOOK_NORMAL, move_finish_cb, s); 91853a5a1b3Sopenharmony_ci s->volume_changed_slot = pa_hook_connect(&sink_input->core->hooks[PA_CORE_HOOK_SINK_INPUT_VOLUME_CHANGED], 91953a5a1b3Sopenharmony_ci PA_HOOK_NORMAL, volume_changed_cb, s); 92053a5a1b3Sopenharmony_ci s->mute_changed_slot = pa_hook_connect(&sink_input->core->hooks[PA_CORE_HOOK_SINK_INPUT_MUTE_CHANGED], 92153a5a1b3Sopenharmony_ci PA_HOOK_NORMAL, mute_changed_cb, s); 92253a5a1b3Sopenharmony_ci s->proplist_changed_slot = pa_hook_connect(&sink_input->core->hooks[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED], 92353a5a1b3Sopenharmony_ci PA_HOOK_NORMAL, proplist_changed_cb, s); 92453a5a1b3Sopenharmony_ci s->state_changed_slot = pa_hook_connect(&sink_input->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], 92553a5a1b3Sopenharmony_ci PA_HOOK_NORMAL, state_changed_cb, s); 92653a5a1b3Sopenharmony_ci 92753a5a1b3Sopenharmony_ci pa_assert_se(pa_dbus_protocol_add_interface(s->dbus_protocol, s->path, &stream_interface_info, s) >= 0); 92853a5a1b3Sopenharmony_ci 92953a5a1b3Sopenharmony_ci return s; 93053a5a1b3Sopenharmony_ci} 93153a5a1b3Sopenharmony_ci 93253a5a1b3Sopenharmony_cipa_dbusiface_stream *pa_dbusiface_stream_new_record(pa_dbusiface_core *core, pa_source_output *source_output) { 93353a5a1b3Sopenharmony_ci pa_dbusiface_stream *s; 93453a5a1b3Sopenharmony_ci 93553a5a1b3Sopenharmony_ci pa_assert(core); 93653a5a1b3Sopenharmony_ci pa_assert(source_output); 93753a5a1b3Sopenharmony_ci 93853a5a1b3Sopenharmony_ci s = pa_xnew(pa_dbusiface_stream, 1); 93953a5a1b3Sopenharmony_ci s->core = core; 94053a5a1b3Sopenharmony_ci s->source_output = pa_source_output_ref(source_output); 94153a5a1b3Sopenharmony_ci s->type = STREAM_TYPE_RECORD; 94253a5a1b3Sopenharmony_ci s->path = pa_sprintf_malloc("%s/%s%u", PA_DBUS_CORE_OBJECT_PATH, RECORD_OBJECT_NAME, source_output->index); 94353a5a1b3Sopenharmony_ci s->source = pa_source_ref(source_output->source); 94453a5a1b3Sopenharmony_ci s->sample_rate = source_output->sample_spec.rate; 94553a5a1b3Sopenharmony_ci pa_cvolume_init(&s->volume); 94653a5a1b3Sopenharmony_ci s->mute = false; 94753a5a1b3Sopenharmony_ci s->proplist = pa_proplist_copy(source_output->proplist); 94853a5a1b3Sopenharmony_ci s->has_volume = false; 94953a5a1b3Sopenharmony_ci s->dbus_protocol = pa_dbus_protocol_get(source_output->core); 95053a5a1b3Sopenharmony_ci s->send_event_slot = pa_hook_connect(&source_output->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_SEND_EVENT], 95153a5a1b3Sopenharmony_ci PA_HOOK_NORMAL, 95253a5a1b3Sopenharmony_ci send_event_cb, 95353a5a1b3Sopenharmony_ci s); 95453a5a1b3Sopenharmony_ci s->move_finish_slot = pa_hook_connect(&source_output->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_FINISH], 95553a5a1b3Sopenharmony_ci PA_HOOK_NORMAL, move_finish_cb, s); 95653a5a1b3Sopenharmony_ci s->volume_changed_slot = pa_hook_connect(&source_output->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_VOLUME_CHANGED], 95753a5a1b3Sopenharmony_ci PA_HOOK_NORMAL, volume_changed_cb, s); 95853a5a1b3Sopenharmony_ci s->mute_changed_slot = pa_hook_connect(&source_output->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MUTE_CHANGED], 95953a5a1b3Sopenharmony_ci PA_HOOK_NORMAL, mute_changed_cb, s); 96053a5a1b3Sopenharmony_ci s->proplist_changed_slot = pa_hook_connect(&source_output->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PROPLIST_CHANGED], 96153a5a1b3Sopenharmony_ci PA_HOOK_NORMAL, proplist_changed_cb, s); 96253a5a1b3Sopenharmony_ci s->state_changed_slot = pa_hook_connect(&source_output->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_STATE_CHANGED], 96353a5a1b3Sopenharmony_ci PA_HOOK_NORMAL, state_changed_cb, s); 96453a5a1b3Sopenharmony_ci 96553a5a1b3Sopenharmony_ci pa_assert_se(pa_dbus_protocol_add_interface(s->dbus_protocol, s->path, &stream_interface_info, s) >= 0); 96653a5a1b3Sopenharmony_ci 96753a5a1b3Sopenharmony_ci return s; 96853a5a1b3Sopenharmony_ci} 96953a5a1b3Sopenharmony_ci 97053a5a1b3Sopenharmony_civoid pa_dbusiface_stream_free(pa_dbusiface_stream *s) { 97153a5a1b3Sopenharmony_ci pa_assert(s); 97253a5a1b3Sopenharmony_ci 97353a5a1b3Sopenharmony_ci pa_assert_se(pa_dbus_protocol_remove_interface(s->dbus_protocol, s->path, stream_interface_info.name) >= 0); 97453a5a1b3Sopenharmony_ci 97553a5a1b3Sopenharmony_ci if (s->type == STREAM_TYPE_PLAYBACK) { 97653a5a1b3Sopenharmony_ci pa_sink_input_unref(s->sink_input); 97753a5a1b3Sopenharmony_ci pa_sink_unref(s->sink); 97853a5a1b3Sopenharmony_ci } else { 97953a5a1b3Sopenharmony_ci pa_source_output_unref(s->source_output); 98053a5a1b3Sopenharmony_ci pa_source_unref(s->source); 98153a5a1b3Sopenharmony_ci } 98253a5a1b3Sopenharmony_ci 98353a5a1b3Sopenharmony_ci pa_proplist_free(s->proplist); 98453a5a1b3Sopenharmony_ci pa_dbus_protocol_unref(s->dbus_protocol); 98553a5a1b3Sopenharmony_ci pa_hook_slot_free(s->send_event_slot); 98653a5a1b3Sopenharmony_ci pa_hook_slot_free(s->move_finish_slot); 98753a5a1b3Sopenharmony_ci pa_hook_slot_free(s->volume_changed_slot); 98853a5a1b3Sopenharmony_ci pa_hook_slot_free(s->mute_changed_slot); 98953a5a1b3Sopenharmony_ci pa_hook_slot_free(s->proplist_changed_slot); 99053a5a1b3Sopenharmony_ci pa_hook_slot_free(s->state_changed_slot); 99153a5a1b3Sopenharmony_ci 99253a5a1b3Sopenharmony_ci pa_xfree(s->path); 99353a5a1b3Sopenharmony_ci pa_xfree(s); 99453a5a1b3Sopenharmony_ci} 99553a5a1b3Sopenharmony_ci 99653a5a1b3Sopenharmony_ciconst char *pa_dbusiface_stream_get_path(pa_dbusiface_stream *s) { 99753a5a1b3Sopenharmony_ci pa_assert(s); 99853a5a1b3Sopenharmony_ci 99953a5a1b3Sopenharmony_ci return s->path; 100053a5a1b3Sopenharmony_ci} 1001