--- /dev/null
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2017 Sangchul Lee <sc11.lee@samsung.com>
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_DBUS
+
+#include "stream-manager-priv.h"
+#include "stream-manager-dbus-priv.h"
+#include "stream-manager-volume-priv.h"
+#include "stream-manager-filter-priv.h"
+#include "stream-manager-restriction-priv.h"
+
+const char *dbus_str_none = "none";
+const char* stream_manager_dbus_ret_str[] = {"STREAM_MANAGER_RETURN_OK",
+ "STREAM_MANAGER_RETURN_ERROR_INTERNAL",
+ "STREAM_MANAGER_RETURN_ERROR_NO_STREAM",
+ "STREAM_MANAGER_RETURN_ERROR_INVALID_ARGUMENT",
+ "STREAM_MANAGER_RETURN_ERROR_DEVICE_NOT_FOUND",
+ "STREAM_MANAGER_RETURN_ERROR_POLICY"};
+
+static DBusHandlerResult handle_introspect(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static DBusHandlerResult handle_methods(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_get_stream_info(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_get_stream_list(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_set_stream_route_devices(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_set_stream_route_option(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_set_volume_level(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_get_volume_level(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_get_volume_max_level(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_set_volume_mute(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_get_volume_mute(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_get_current_volume_type(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_get_current_media_routing_path(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_update_focus_status(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_update_focus_status_by_focus_id(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_update_restriction(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_set_filter(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_unset_filter(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_control_filter(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_check_stream_exist_by_pid(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void send_volume_changed_signal(DBusConnection *conn, const char *direction, const char *volume_type, const uint32_t volume_level);
+
+static pa_dbus_arg_info get_stream_info_args[] = { { "stream_type", "s", "in" },
+ { "priority", "i", "out" },
+ { "route_type", "i", "out" },
+ { "volume_types", "as", "out" },
+ { "avail_in_devices", "as", "out" },
+ { "avail_out_devices", "as", "out" },
+ { "avail_frameworks", "as", "out"} };
+static pa_dbus_arg_info get_stream_list_args[] = { { "stream_type", "as", "out" },
+ { "priority", "ai", "out" } };
+static pa_dbus_arg_info set_stream_route_devices_args[] = { { "parent_id", "u", "in" },
+ { "route_in_devices", "au", "in" },
+ { "route_out_devices", "au", "in" },
+ { "ret_msg", "s", "out" } };
+static pa_dbus_arg_info set_stream_route_option_args[] = { { "parent_id", "u", "in" },
+ { "name", "s", "in" },
+ { "value", "i", "in" },
+ { "ret_msg", "s", "out" } };
+static pa_dbus_arg_info set_volume_level_args[] = { { "io_direction", "s", "in" },
+ { "type", "s", "in" },
+ { "level", "u", "in" },
+ { "ret_msg", "s", "out" } };
+static pa_dbus_arg_info get_volume_level_args[] = { { "io_direction", "s", "in" },
+ { "type", "s", "in" },
+ { "level", "u", "out" },
+ { "ret_msg", "s", "out" } };
+static pa_dbus_arg_info get_volume_max_level_args[] = { { "io_direction", "s", "in" },
+ { "type", "s", "in" },
+ { "level", "u", "out" },
+ { "ret_msg", "s", "out" } };
+static pa_dbus_arg_info set_volume_mute_args[] = { { "io_direction", "s", "in" },
+ { "type", "s", "in" },
+ { "on", "u", "in" },
+ { "ret_msg", "s", "out" } };
+static pa_dbus_arg_info get_volume_mute_args[] = { { "io_direction", "s", "in" },
+ { "type", "s", "in" },
+ { "on", "u", "out" },
+ { "ret_msg", "s", "out" } };
+static pa_dbus_arg_info get_current_volume_type_args[] = { { "io_direction", "s", "in" },
+ { "type", "s", "out" },
+ { "ret_msg", "s", "out" } };
+static pa_dbus_arg_info get_current_media_routing_path_args[] = { { "io_direction", "s", "in" },
+ { "device_type", "s", "out" },
+ { "ret_msg", "s", "out" } };
+static pa_dbus_arg_info update_focus_status_args[] = { { "parent_id", "u", "in" },
+ { "focus_status", "u", "in" },
+ { "ret_msg", "s", "out" } };
+static pa_dbus_arg_info update_focus_status_by_focus_id_args[] = { { "focus_id", "i", "in" },
+ { "focus_status", "u", "in" },
+ { "ret_msg", "s", "out" } };
+static pa_dbus_arg_info update_restriction_args[] = { { "name", "s", "in" },
+ { "value", "u", "in" },
+ { "ret_msg", "s", "out" } };
+static pa_dbus_arg_info set_filter_args[] = { { "filter_name", "s", "in" },
+ { "filter_parameters", "s", "in" },
+ { "filter_group", "s", "in" },
+ { "stream_type", "s", "in" },
+ { "ret_msg", "s", "out" } };
+static pa_dbus_arg_info unset_filter_args[] = { { "stream_type", "s", "in" },
+ { "ret_msg", "s", "out" } };
+static pa_dbus_arg_info control_filter_args[] = { { "filter_name", "s", "in" },
+ { "filter_controls", "s", "in" },
+ { "stream_type", "s", "in" },
+ { "ret_msg", "s", "out" } };
+static pa_dbus_arg_info check_stream_exist_by_pid_args[] = { { "pid", "u", "in" },
+ { "stream_type", "s", "in" },
+ { "io_direction", "s", "in" },
+ { "ret_msg", "s", "out" } };
+static const char* signature_args_for_in[] = { "s", "", "uauau", "usi", "ssu", "ss", "ss", "ssu", "ss", "s", "s", "uu", "iu", "su", "ssss", "s", "sss", "uss"};
+
+static pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = {
+ [METHOD_HANDLER_GET_STREAM_INFO] = {
+ .method_name = STREAM_MANAGER_METHOD_NAME_GET_STREAM_INFO,
+ .arguments = get_stream_info_args,
+ .n_arguments = sizeof(get_stream_info_args) / sizeof(pa_dbus_arg_info),
+ .receive_cb = handle_get_stream_info },
+ [METHOD_HANDLER_GET_STREAM_LIST] = {
+ .method_name = STREAM_MANAGER_METHOD_NAME_GET_STREAM_LIST,
+ .arguments = get_stream_list_args,
+ .n_arguments = sizeof(get_stream_list_args) / sizeof(pa_dbus_arg_info),
+ .receive_cb = handle_get_stream_list },
+ [METHOD_HANDLER_SET_STREAM_ROUTE_DEVICES] = {
+ .method_name = STREAM_MANAGER_METHOD_NAME_SET_STREAM_ROUTE_DEVICES,
+ .arguments = set_stream_route_devices_args,
+ .n_arguments = sizeof(set_stream_route_devices_args) / sizeof(pa_dbus_arg_info),
+ .receive_cb = handle_set_stream_route_devices },
+ [METHOD_HANDLER_SET_STREAM_ROUTE_OPTION] = {
+ .method_name = STREAM_MANAGER_METHOD_NAME_SET_STREAM_ROUTE_OPTION,
+ .arguments = set_stream_route_option_args,
+ .n_arguments = sizeof(set_stream_route_option_args) / sizeof(pa_dbus_arg_info),
+ .receive_cb = handle_set_stream_route_option },
+ [METHOD_HANDLER_SET_VOLUME_LEVEL] = {
+ .method_name = STREAM_MANAGER_METHOD_NAME_SET_VOLUME_LEVEL,
+ .arguments = set_volume_level_args,
+ .n_arguments = sizeof(set_volume_level_args) / sizeof(pa_dbus_arg_info),
+ .receive_cb = handle_set_volume_level },
+ [METHOD_HANDLER_GET_VOLUME_LEVEL] = {
+ .method_name = STREAM_MANAGER_METHOD_NAME_GET_VOLUME_LEVEL,
+ .arguments = get_volume_level_args,
+ .n_arguments = sizeof(get_volume_level_args) / sizeof(pa_dbus_arg_info),
+ .receive_cb = handle_get_volume_level },
+ [METHOD_HANDLER_GET_VOLUME_MAX_LEVEL] = {
+ .method_name = STREAM_MANAGER_METHOD_NAME_GET_VOLUME_MAX_LEVEL,
+ .arguments = get_volume_max_level_args,
+ .n_arguments = sizeof(get_volume_max_level_args) / sizeof(pa_dbus_arg_info),
+ .receive_cb = handle_get_volume_max_level },
+ [METHOD_HANDLER_SET_VOLUME_MUTE] = {
+ .method_name = STREAM_MANAGER_METHOD_NAME_SET_VOLUME_MUTE,
+ .arguments = set_volume_mute_args,
+ .n_arguments = sizeof(set_volume_mute_args) / sizeof(pa_dbus_arg_info),
+ .receive_cb = handle_set_volume_mute },
+ [METHOD_HANDLER_GET_VOLUME_MUTE] = {
+ .method_name = STREAM_MANAGER_METHOD_NAME_GET_VOLUME_MUTE,
+ .arguments = get_volume_mute_args,
+ .n_arguments = sizeof(get_volume_mute_args) / sizeof(pa_dbus_arg_info),
+ .receive_cb = handle_get_volume_mute },
+ [METHOD_HANDLER_GET_CURRENT_VOLUME_TYPE] = {
+ .method_name = STREAM_MANAGER_METHOD_NAME_GET_CURRENT_VOLUME_TYPE,
+ .arguments = get_current_volume_type_args,
+ .n_arguments = sizeof(get_current_volume_type_args) / sizeof(pa_dbus_arg_info),
+ .receive_cb = handle_get_current_volume_type },
+ [METHOD_HANDLER_GET_CURRENT_MEDIA_ROUTING_PATH] = {
+ .method_name = STREAM_MANAGER_METHOD_NAME_GET_CURRENT_MEDIA_ROUTING_PATH,
+ .arguments = get_current_media_routing_path_args,
+ .n_arguments = sizeof(get_current_media_routing_path_args) / sizeof(pa_dbus_arg_info),
+ .receive_cb = handle_get_current_media_routing_path },
+ [METHOD_HANDLER_UPDATE_FOCUS_STATUS] = {
+ .method_name = STREAM_MANAGER_METHOD_NAME_UPDATE_FOCUS_STATUS,
+ .arguments = update_focus_status_args,
+ .n_arguments = sizeof(update_focus_status_args) / sizeof(pa_dbus_arg_info),
+ .receive_cb = handle_update_focus_status },
+ [METHOD_HANDLER_UPDATE_FOCUS_STATUS_BY_FOCUS_ID] = {
+ .method_name = STREAM_MANAGER_METHOD_NAME_UPDATE_FOCUS_STATUS_BY_FOCUS_ID,
+ .arguments = update_focus_status_by_focus_id_args,
+ .n_arguments = sizeof(update_focus_status_by_focus_id_args) / sizeof(pa_dbus_arg_info),
+ .receive_cb = handle_update_focus_status_by_focus_id },
+ [METHOD_HANDLER_UPDATE_RESTRICTION] = {
+ .method_name = STREAM_MANAGER_METHOD_NAME_UPDATE_RESTRICTION,
+ .arguments = update_restriction_args,
+ .n_arguments = sizeof(update_restriction_args) / sizeof(pa_dbus_arg_info),
+ .receive_cb = handle_update_restriction },
+ [METHOD_HANDLER_SET_FILTER] = {
+ .method_name = STREAM_MANAGER_METHOD_NAME_SET_FILTER,
+ .arguments = set_filter_args,
+ .n_arguments = sizeof(set_filter_args) / sizeof(pa_dbus_arg_info),
+ .receive_cb = handle_set_filter },
+ [METHOD_HANDLER_UNSET_FILTER] = {
+ .method_name = STREAM_MANAGER_METHOD_NAME_UNSET_FILTER,
+ .arguments = unset_filter_args,
+ .n_arguments = sizeof(unset_filter_args) / sizeof(pa_dbus_arg_info),
+ .receive_cb = handle_unset_filter },
+ [METHOD_HANDLER_CONTROL_FILTER] = {
+ .method_name = STREAM_MANAGER_METHOD_NAME_CONTROL_FILTER,
+ .arguments = control_filter_args,
+ .n_arguments = sizeof(control_filter_args) / sizeof(pa_dbus_arg_info),
+ .receive_cb = handle_control_filter },
+ [METHOD_HANDLER_CHECK_STREAM_EXIST_BY_PID] = {
+ .method_name = STREAM_MANAGER_METHOD_NAME_CHECK_STREAM_EXIST_BY_PID,
+ .arguments = check_stream_exist_by_pid_args,
+ .n_arguments = sizeof(check_stream_exist_by_pid_args) / sizeof(pa_dbus_arg_info),
+ .receive_cb = handle_check_stream_exist_by_pid },
+};
+
+static DBusHandlerResult handle_introspect(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ const char *xml = STREAM_MGR_INTROSPECT_XML;
+ DBusMessage *r = NULL;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(userdata);
+
+ pa_assert_se(r = dbus_message_new_method_return(msg));
+ pa_assert_se(dbus_message_append_args(r, DBUS_TYPE_STRING, &xml, DBUS_TYPE_INVALID));
+
+ if (r) {
+ pa_assert_se(dbus_connection_send((conn), r, NULL));
+ dbus_message_unref(r);
+ }
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static void handle_get_stream_list(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ stream_list list;
+ DBusMessage *reply = NULL;
+ DBusMessageIter msg_iter;
+ pa_stream_manager *m = (pa_stream_manager*)userdata;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(m);
+
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_INVALID));
+ pa_log_info("handle_get_stream_list() dbus method is called");
+
+ memset(&list, 0, sizeof(stream_list));
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+ dbus_message_iter_init_append(reply, &msg_iter);
+ if (!get_available_streams(m, &list)) {
+ pa_dbus_append_basic_array_variant(&msg_iter, DBUS_TYPE_STRING, &list.types, list.num_of_streams);
+ pa_dbus_append_basic_array_variant(&msg_iter, DBUS_TYPE_INT32, &list.priorities, list.num_of_streams);
+ } else {
+ pa_dbus_append_basic_array_variant(&msg_iter, DBUS_TYPE_STRING, NULL, 0);
+ pa_dbus_append_basic_array_variant(&msg_iter, DBUS_TYPE_INT32, NULL, 0);
+ }
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static void handle_get_stream_info(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ char *type;
+ stream_info_per_type info;
+ DBusMessage *reply = NULL;
+ DBusMessageIter msg_iter;
+ pa_stream_manager *m = (pa_stream_manager*)userdata;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(m);
+
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_STRING, &type,
+ DBUS_TYPE_INVALID));
+ pa_log_info("handle_get_stream_info(), type[%s]", type);
+
+ memset(&info, 0, sizeof(stream_info_per_type));
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+ dbus_message_iter_init_append(reply, &msg_iter);
+ get_stream_info(m, type, &info);
+ pa_dbus_append_basic_variant(&msg_iter, DBUS_TYPE_INT32, &info.priority);
+ pa_dbus_append_basic_variant(&msg_iter, DBUS_TYPE_INT32, &info.route_type);
+ pa_dbus_append_basic_array_variant(&msg_iter, DBUS_TYPE_STRING, &info.volume_types, STREAM_DIRECTION_MAX);
+ pa_dbus_append_basic_array_variant(&msg_iter, DBUS_TYPE_STRING, &info.avail_in_devices, info.num_of_in_devices);
+ pa_dbus_append_basic_array_variant(&msg_iter, DBUS_TYPE_STRING, &info.avail_out_devices, info.num_of_out_devices);
+ pa_dbus_append_basic_array_variant(&msg_iter, DBUS_TYPE_STRING, &info.avail_frameworks, info.num_of_frameworks);
+
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static bool check_all_requested_devices_connected(pa_stream_manager *m, uint32_t *device_list, uint32_t length) {
+ pa_idxset *dm_device_list;
+ uint32_t found_count = 0;
+ uint32_t i = 0;
+
+ pa_assert(m);
+ pa_assert(device_list);
+
+ dm_device_list = pa_device_manager_get_device_list(m->dm);
+
+ for (i = 0; i < length; i++) {
+ pa_tz_device *dm_device;
+ uint32_t dm_device_id;
+ uint32_t idx = 0;
+
+ PA_IDXSET_FOREACH(dm_device, dm_device_list, idx) {
+ dm_device_id = pa_tz_device_get_id(dm_device);
+ if (device_list[i] == dm_device_id) {
+ pa_log_debug("device[%u] is connected", dm_device_id);
+ found_count++;
+ if (length == found_count)
+ return true;
+ break;
+ }
+ }
+ }
+
+ return false;
+}
+
+static ret_msg_t update_devices_and_trigger_routing(pa_stream_manager *m, stream_parent *sp, stream_type_t type) {
+ void *stream = NULL;
+ pa_idxset *idx_streams = NULL;
+ uint32_t idx = 0;
+ void *cur_highest_priority_stream = NULL;
+ stream_route_type_t route_type = STREAM_ROUTE_TYPE_DEFAULT;
+ ret_msg_t ret = RET_MSG_OK;
+
+ pa_assert(m);
+ pa_assert(sp);
+
+ if (type == STREAM_SINK_INPUT) {
+ idx_streams = sp->idx_sink_inputs;
+ cur_highest_priority_stream = (void*)m->cur_highest_priority.sink_input;
+ } else {
+ idx_streams = sp->idx_source_outputs;
+ cur_highest_priority_stream = (void*)m->cur_highest_priority.source_output;
+ }
+
+ /* update route type of this stream parent */
+ if (sp->route_type == STREAM_ROUTE_TYPE_DEFAULT) {
+ PA_IDXSET_FOREACH(stream, idx_streams, idx) {
+ /* find route type of stream */
+ if (get_route_type(stream, type, false, &route_type))
+ return RET_MSG_ERROR_INTERNAL;
+
+ if (route_type == STREAM_ROUTE_TYPE_MANUAL ||
+ route_type == STREAM_ROUTE_TYPE_MANUAL_EXT) {
+ sp->route_type = route_type;
+ pa_log_info(" -- the route type is [%d]", route_type);
+ } else {
+ pa_log_error(" -- the route type is not valid[%d]", route_type);
+ return RET_MSG_ERROR_POLICY;
+ }
+ }
+ }
+
+ /* if any stream that belongs to this id has been activated, do notify right away */
+ if (sp->route_type == STREAM_ROUTE_TYPE_MANUAL_EXT) {
+ PA_IDXSET_FOREACH(stream, idx_streams, idx) {
+ pa_log_debug(" -- stream->index[%u] belongs to this stream parent[%p], do notify for the select proper source",
+ GET_STREAM_INDEX(stream, type), sp);
+ ret = do_notify(m, NOTIFY_COMMAND_SELECT_PROPER_SINK_OR_SOURCE_FOR_INIT, type, false, stream);
+ }
+ } else {
+ /* trigger only when it occupies routing path */
+ if (cur_highest_priority_stream && pa_idxset_get_by_data(idx_streams, cur_highest_priority_stream, NULL)) {
+ pa_log_debug(" -- cur_highest_priority_stream->index[%u] belongs to this stream_parent[%p], do notify for the route change",
+ GET_STREAM_INDEX(cur_highest_priority_stream, type), sp);
+ ret = do_notify(m, NOTIFY_COMMAND_CHANGE_ROUTE_START, type, false, cur_highest_priority_stream);
+ if (!ret && stream_is_call_family(PA_OBJECT(cur_highest_priority_stream)) && m->on_call) {
+ pa_log_info("set active device for new call route device");
+ change_active_route_for_call(m, PA_OBJECT(cur_highest_priority_stream), false);
+ }
+ }
+ }
+
+ return ret;
+}
+
+static void handle_set_stream_route_devices(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ uint32_t id = 0;
+ int i = 0;
+ uint32_t *in_device_list = NULL;
+ uint32_t *out_device_list = NULL;
+ int list_len_in = 0;
+ int list_len_out = 0;
+ uint32_t idx = 0;
+ uint32_t *device_id = NULL;
+ stream_parent *sp = NULL;
+ DBusMessage *reply = NULL;
+ pa_stream_manager *m = (pa_stream_manager*)userdata;
+ ret_msg_t ret = RET_MSG_OK;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(m);
+
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_UINT32, &id,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &in_device_list, &list_len_in,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &out_device_list, &list_len_out,
+ DBUS_TYPE_INVALID));
+ pa_log_info("handle_set_stream_route_devices(), id[%u], in_device_list[%p]:length[%d], out_device_list[%p]:length[%d]",
+ id, in_device_list, list_len_in, out_device_list, list_len_out);
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+
+ sp = pa_hashmap_get(m->stream_parents, (const void*)id);
+ if (!sp) {
+ pa_log_error("could not find matching client for this parent_id[%u]", id);
+ ret = RET_MSG_ERROR_INTERNAL;
+ goto finish;
+ }
+ if (!in_device_list && !out_device_list) {
+ pa_log_error("invalid arguments");
+ ret = RET_MSG_ERROR_INVALID_ARGUMENT;
+ goto finish;
+ }
+ if (!sp->idx_route_in_devices || !sp->idx_route_out_devices) {
+ pa_log_error("failed to update, idx_route_in_devices[%p], idx_route_out_devices[%p]",
+ sp->idx_route_in_devices, sp->idx_route_out_devices);
+ ret = RET_MSG_ERROR_INTERNAL;
+ goto finish;
+ }
+
+ /* check if all the requested devices are connected now */
+ if (in_device_list && !check_all_requested_devices_connected(m, in_device_list, list_len_in)) {
+ pa_log_error("could not find requested in-devices");
+ ret = RET_MSG_ERROR_DEVICE_NOT_FOUND;
+ goto finish;
+ }
+ if (out_device_list && !check_all_requested_devices_connected(m, out_device_list, list_len_out)) {
+ pa_log_error("could not find requested out-devices");
+ ret = RET_MSG_ERROR_DEVICE_NOT_FOUND;
+ goto finish;
+ }
+
+ PA_IDXSET_FOREACH(device_id, sp->idx_route_in_devices, idx) {
+ pa_idxset_remove_by_data(sp->idx_route_in_devices, device_id, NULL);
+ pa_xfree(device_id);
+ }
+ if (in_device_list && list_len_in) {
+ for (i = 0; i < list_len_in; i++) {
+ pa_idxset_put(sp->idx_route_in_devices, pa_xmemdup(&in_device_list[i], sizeof(uint32_t)), NULL);
+ pa_log_debug(" -- [in] device id:%u", in_device_list[i]);
+ }
+ }
+ if ((ret = update_devices_and_trigger_routing(m, sp, STREAM_SOURCE_OUTPUT)))
+ goto finish;
+
+ PA_IDXSET_FOREACH(device_id, sp->idx_route_out_devices, idx) {
+ pa_idxset_remove_by_data(sp->idx_route_out_devices, device_id, NULL);
+ pa_xfree(device_id);
+ }
+ if (out_device_list && list_len_out) {
+ for (i = 0; i < list_len_out; i++) {
+ pa_idxset_put(sp->idx_route_out_devices, pa_xmemdup(&out_device_list[i], sizeof(uint32_t)), NULL);
+ pa_log_debug(" -- [out] device id:%u", out_device_list[i]);
+ }
+ }
+ if ((ret = update_devices_and_trigger_routing(m, sp, STREAM_SINK_INPUT)))
+ goto finish;
+
+finish:
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[ret], DBUS_TYPE_INVALID));
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static void handle_set_stream_route_option(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ uint32_t id = 0;
+ const char *name = NULL;
+ int32_t value = 0;
+ bool updated = false;
+ stream_parent *sp = NULL;
+ stream_route_option route_option;
+ DBusMessage *reply = NULL;
+ pa_stream_manager *m = (pa_stream_manager*)userdata;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(m);
+
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_UINT32, &id,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_INT32, &value,
+ DBUS_TYPE_INVALID));
+ pa_log_info("handle_set_stream_route_option(), name[%s], value[%d]", name, value);
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+
+ sp = pa_hashmap_get(m->stream_parents, (const void*)id);
+ if (sp) {
+ if (name) {
+ route_option.name = name;
+ route_option.value = value;
+
+ /* if any stream that belongs to this id has been activated, do notify right away */
+ if (m->cur_highest_priority.sink_input) {
+ if (pa_idxset_get_by_data(sp->idx_sink_inputs, m->cur_highest_priority.sink_input, NULL)) {
+ pa_log_debug(" -- cur_highest_priority.sink_input->index[%u] belongs to this parent id[%u], do notify for the options",
+ (m->cur_highest_priority.sink_input)->index, id);
+ do_notify(m, NOTIFY_COMMAND_UPDATE_ROUTE_OPTION, STREAM_SINK_INPUT, false, &route_option);
+ updated = true;
+ }
+ }
+ if (m->cur_highest_priority.source_output) {
+ if (pa_idxset_get_by_data(sp->idx_source_outputs, m->cur_highest_priority.source_output, NULL)) {
+ pa_log_debug(" -- cur_highest_priority.source_output->index[%u] belongs to this parent id[%u], do notify for the options",
+ (m->cur_highest_priority.source_output)->index, id);
+ do_notify(m, NOTIFY_COMMAND_UPDATE_ROUTE_OPTION, STREAM_SOURCE_OUTPUT, false, &route_option);
+ updated = true;
+ }
+ }
+ if (!updated) {
+ pa_log_error("invalid state");
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_NO_STREAM], DBUS_TYPE_INVALID));
+ } else
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_OK], DBUS_TYPE_INVALID));
+ } else {
+ pa_log_error("invalid arguments");
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INVALID_ARGUMENT], DBUS_TYPE_INVALID));
+ }
+
+ } else {
+ pa_log_error("could not find matching client for this parent_id[%u]", id);
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
+ }
+
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static void handle_set_volume_level(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ const char *direction = NULL;
+ const char *type = NULL;
+ uint32_t level = 0;
+ stream_type_t stream_type = STREAM_SINK_INPUT;
+ DBusMessage *reply = NULL;
+ pa_stream_manager *m = (pa_stream_manager*)userdata;
+ int ret = 0;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(m);
+
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_STRING, &direction,
+ DBUS_TYPE_STRING, &type,
+ DBUS_TYPE_UINT32, &level,
+ DBUS_TYPE_INVALID));
+ pa_log_info("handle_set_volume_level(), direction[%s], type[%s], level[%u]", direction, type, level);
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+
+ if (pa_streq(direction, "in"))
+ stream_type = STREAM_SOURCE_OUTPUT;
+ else if (pa_streq(direction, "out"))
+ stream_type = STREAM_SINK_INPUT;
+ else {
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
+ ret = -1;
+ goto finish;
+ }
+
+ if ((ret = set_volume_level_by_type(m, stream_type, type, level)))
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
+ else
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_OK], DBUS_TYPE_INVALID));
+
+finish:
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+
+ if (!ret)
+ send_volume_changed_signal(conn, direction, type, level);
+}
+
+static void handle_get_volume_level(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ const char *direction = NULL;
+ const char *type = NULL;
+ uint32_t level = 0;
+ stream_type_t stream_type = STREAM_SINK_INPUT;
+ DBusMessage *reply = NULL;
+ pa_stream_manager *m = (pa_stream_manager*)userdata;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(m);
+
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_STRING, &direction,
+ DBUS_TYPE_STRING, &type,
+ DBUS_TYPE_INVALID));
+ pa_log_info("handle_get_volume_level(), direction(%s), type(%s)", direction, type);
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+
+ if (pa_streq(direction, "in"))
+ stream_type = STREAM_SOURCE_OUTPUT;
+ else if (pa_streq(direction, "out"))
+ stream_type = STREAM_SINK_INPUT;
+ else {
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_UINT32, 0, DBUS_TYPE_INVALID));
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
+ goto finish;
+ }
+
+ if (get_volume_level_by_type(m, GET_VOLUME_CURRENT_LEVEL, stream_type, type, &level)) {
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_UINT32, 0, DBUS_TYPE_INVALID));
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
+ } else {
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_UINT32, &level, DBUS_TYPE_INVALID));
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_OK], DBUS_TYPE_INVALID));
+ }
+
+finish:
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static void handle_get_volume_max_level(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ const char *direction = NULL;
+ const char *type = NULL;
+ uint32_t level = 0;
+ stream_type_t stream_type = STREAM_SINK_INPUT;
+ DBusMessage *reply = NULL;
+ pa_stream_manager *m = (pa_stream_manager*)userdata;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(m);
+
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_STRING, &direction,
+ DBUS_TYPE_STRING, &type,
+ DBUS_TYPE_INVALID));
+ pa_log_info("handle_get_volume_max_level(), direction[%s], type[%s]", direction, type);
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+
+ if (pa_streq(direction, "in"))
+ stream_type = STREAM_SOURCE_OUTPUT;
+ else if (pa_streq(direction, "out"))
+ stream_type = STREAM_SINK_INPUT;
+ else {
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_UINT32, 0, DBUS_TYPE_INVALID));
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
+ goto finish;
+ }
+
+ if (get_volume_level_by_type(m, GET_VOLUME_MAX_LEVEL, stream_type, type, &level)) {
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_UINT32, 0, DBUS_TYPE_INVALID));
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
+ } else {
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_UINT32, &level, DBUS_TYPE_INVALID));
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_OK], DBUS_TYPE_INVALID));
+ }
+finish:
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static void handle_set_volume_mute(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ const char *direction = NULL;
+ const char *type = NULL;
+ uint32_t do_mute = 0;
+ stream_type_t stream_type = STREAM_SINK_INPUT;
+ DBusMessage *reply = NULL;
+ pa_stream_manager *m = (pa_stream_manager*)userdata;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(m);
+
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_STRING, &direction,
+ DBUS_TYPE_STRING, &type,
+ DBUS_TYPE_UINT32, &do_mute,
+ DBUS_TYPE_INVALID));
+ pa_log_info("handle_set_volume_mute(), direction[%s], type[%s], do_mute[%u]", direction, type, do_mute);
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+
+ if (pa_streq(direction, "in"))
+ stream_type = STREAM_SOURCE_OUTPUT;
+ else if (pa_streq(direction, "out"))
+ stream_type = STREAM_SINK_INPUT;
+ else {
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
+ goto finish;
+ }
+
+ if (set_volume_mute_by_type(m, stream_type, type, (bool)do_mute))
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
+ else
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_OK], DBUS_TYPE_INVALID));
+
+finish:
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static void handle_get_volume_mute(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ const char *direction = NULL;
+ const char *type = NULL;
+ uint32_t is_muted = 0;
+ stream_type_t stream_type = STREAM_SINK_INPUT;
+ DBusMessage *reply = NULL;
+ pa_stream_manager *m = (pa_stream_manager*)userdata;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(m);
+
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_STRING, &direction,
+ DBUS_TYPE_STRING, &type,
+ DBUS_TYPE_INVALID));
+ pa_log_info("handle_get_volume_mute(), direction[%s], type[%s]", direction, type);
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+
+ if (pa_streq(direction, "in"))
+ stream_type = STREAM_SOURCE_OUTPUT;
+ else if (pa_streq(direction, "out"))
+ stream_type = STREAM_SINK_INPUT;
+ else {
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_UINT32, 0, DBUS_TYPE_INVALID));
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
+ goto fail;
+ }
+
+ if (get_volume_mute_by_type(m, stream_type, type, (bool*)&is_muted)) {
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_UINT32, 0, DBUS_TYPE_INVALID));
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
+ } else {
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_UINT32, &is_muted, DBUS_TYPE_INVALID));
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_OK], DBUS_TYPE_INVALID));
+ }
+
+fail:
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static void handle_get_current_volume_type(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ const char *direction = NULL;
+ const char *type = NULL;
+ void *s = NULL;
+ stream_type_t stream_type = STREAM_SINK_INPUT;
+ DBusMessage *reply = NULL;
+ pa_stream_manager *m = (pa_stream_manager*)userdata;
+ uint32_t idx = 0;
+ pa_idxset *streams = NULL;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(m);
+
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_STRING, &direction,
+ DBUS_TYPE_INVALID));
+ pa_log_info("handle_get_current_volume_type(), direction[%s]", direction);
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+
+ if (pa_streq(direction, "in")) {
+ stream_type = STREAM_SOURCE_OUTPUT;
+ streams = m->core->source_outputs;
+ } else if (pa_streq(direction, "out")) {
+ stream_type = STREAM_SINK_INPUT;
+ streams = m->core->sink_inputs;
+ } else {
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &dbus_str_none, DBUS_TYPE_INVALID));
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
+ goto fail;
+ }
+
+ /* Get a volume type of a stream that has the max priority role among all the running streams regardless of devices.
+ Note that it does not represent any focus status of a stream rather only checking the priority of it */
+ if (pa_idxset_size(streams)) {
+ int cur_max_priority = 0;
+ const char *cur_max_type = NULL;
+ const char *role = NULL;
+ stream_info *s_info;
+
+ PA_IDXSET_FOREACH(s, streams, idx) {
+ if (!CHECK_STREAM_RUNNING(s, stream_type))
+ continue;
+ if (!(type = pa_proplist_gets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_TIZEN_VOLUME_TYPE)))
+ continue;
+ if (!(role = pa_proplist_gets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_ROLE)))
+ continue;
+ if ((s_info = pa_hashmap_get(m->stream_infos, role))) {
+ if (s_info->priority >= cur_max_priority) {
+ cur_max_priority = s_info->priority;
+ cur_max_type = type;
+ pa_log_info("updated, volume type of the max priority stream(%u): %s", GET_STREAM_INDEX(s, stream_type), cur_max_type);
+ }
+ }
+ }
+ type = cur_max_type;
+ }
+
+ if (type) {
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &type, DBUS_TYPE_INVALID));
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_OK], DBUS_TYPE_INVALID));
+ } else {
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &dbus_str_none, DBUS_TYPE_INVALID));
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_NO_STREAM], DBUS_TYPE_INVALID));
+ }
+
+fail:
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static void handle_get_current_media_routing_path(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ const char *direction = NULL;
+ const char *device_type = NULL;
+ dm_device_direction_t dm_device_direction = DM_DEVICE_DIRECTION_NONE;
+ stream_info *s = NULL;
+ DBusMessage *reply = NULL;
+ pa_tz_device *device = NULL;
+ pa_stream_manager *m = (pa_stream_manager*)userdata;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(m);
+
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_STRING, &direction,
+ DBUS_TYPE_INVALID));
+ pa_log_info("handle_get_current_media_routing_path(), direction[%s]", direction);
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+
+ if (pa_streq(direction, "in")) {
+ dm_device_direction = DM_DEVICE_DIRECTION_IN;
+ } else if (pa_streq(direction, "out")) {
+ dm_device_direction = DM_DEVICE_DIRECTION_OUT;
+ } else {
+ pa_log_error("invalid direction[%s]", direction);
+ goto fail;
+ }
+
+ if ((s = pa_hashmap_get(m->stream_infos, STREAM_ROLE_MEDIA)) == NULL) {
+ pa_log_error("could not find media role");
+ goto fail;
+ }
+
+ if (s->route_type == STREAM_ROUTE_TYPE_AUTO) {
+ device = get_media_auto_device(m, dm_device_direction);
+ } else if (s->route_type == STREAM_ROUTE_TYPE_AUTO_LAST_CONNECTED) {
+ device = get_media_last_device(m, dm_device_direction);
+ } else {
+ pa_log_error("unexpected routing type for media[%d]", s->route_type);
+ goto fail;
+ }
+
+ if (device) {
+ device_type = pa_tz_device_get_type(device);
+ goto success;
+ } else {
+ pa_log_error("could not found matched device");
+ }
+
+fail:
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &dbus_str_none, DBUS_TYPE_INVALID));
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+ return;
+success:
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &device_type, DBUS_TYPE_INVALID));
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_OK], DBUS_TYPE_INVALID));
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static void handle_update_focus_status(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ uint32_t id = 0;
+ uint32_t idx = 0;
+ uint32_t count = 0;
+ uint32_t acquired_focus_status = 0;
+ stream_parent *sp = NULL;
+ void *stream = NULL;
+ DBusMessage *reply = NULL;
+ pa_stream_manager *m = (pa_stream_manager*)userdata;
+ int prev_status = STREAM_FOCUS_ACQUIRED_NONE;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(m);
+
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_UINT32, &id,
+ DBUS_TYPE_UINT32, &acquired_focus_status,
+ DBUS_TYPE_INVALID));
+ pa_log_info("handle_update_focus_status(), id[%u], acquired_focus_status[0x%x]", id, acquired_focus_status);
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+
+ if ((sp = pa_hashmap_get(m->stream_parents, (const void*)id))) {
+ if (sp->focus_status != acquired_focus_status) {
+ /* need to update */
+ prev_status = sp->focus_status;
+ sp->focus_status = acquired_focus_status;
+ if (((prev_status ^ sp->focus_status) & STREAM_FOCUS_ACQUIRED_PLAYBACK) && sp->idx_sink_inputs) {
+ count = pa_idxset_size(sp->idx_sink_inputs);
+ PA_IDXSET_FOREACH(stream, sp->idx_sink_inputs, idx) {
+ pa_proplist_sets(GET_STREAM_PROPLIST(stream, STREAM_SINK_INPUT), PA_PROP_MEDIA_FOCUS_STATUS,
+ GET_FOCUS_STATUS(sp->focus_status, STREAM_SINK_INPUT) ? STREAM_FOCUS_STATE_ACQUIRED : STREAM_FOCUS_STATE_RELEASED);
+ if (--count == 0)
+ process_stream(m, stream, STREAM_SINK_INPUT, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_FOCUS_CHANGED, false);
+ }
+ }
+ if (((prev_status ^ sp->focus_status) & STREAM_FOCUS_ACQUIRED_CAPTURE) && sp->idx_source_outputs) {
+ count = pa_idxset_size(sp->idx_source_outputs);
+ PA_IDXSET_FOREACH(stream, sp->idx_source_outputs, idx) {
+ pa_proplist_sets(GET_STREAM_PROPLIST(stream, STREAM_SOURCE_OUTPUT), PA_PROP_MEDIA_FOCUS_STATUS,
+ GET_FOCUS_STATUS(sp->focus_status, STREAM_SOURCE_OUTPUT) ? STREAM_FOCUS_STATE_ACQUIRED : STREAM_FOCUS_STATE_RELEASED);
+ if (--count == 0)
+ process_stream(m, stream, STREAM_SOURCE_OUTPUT, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_FOCUS_CHANGED, false);
+ }
+ }
+ } else
+ pa_log_debug("same as before, skip updating focus status[0x%x]", acquired_focus_status);
+
+ } else {
+ pa_log_error("could not find matching client for this parent_id[%u]", id);
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
+ goto fail;
+ }
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_OK], DBUS_TYPE_INVALID));
+fail:
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static void handle_update_focus_status_by_focus_id(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ int32_t id = 0;
+ uint32_t idx = 0;
+ uint32_t acquired_focus_status = 0;
+ int32_t focus_id = 0;
+ const char *focus_id_str;
+ pa_sink_input *i = NULL;
+ DBusMessage *reply = NULL;
+ pa_stream_manager *m = (pa_stream_manager*)userdata;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(m);
+
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_INT32, &id,
+ DBUS_TYPE_UINT32, &acquired_focus_status,
+ DBUS_TYPE_INVALID));
+ pa_log_info("handle_update_focus_status_by_focus_id(), id[%d], acquired_focus_status[0x%x]", id, acquired_focus_status);
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+
+ /* Currently, we only support sink-inputs */
+ PA_IDXSET_FOREACH(i, m->core->sink_inputs, idx) {
+ if ((focus_id_str = pa_proplist_gets(GET_STREAM_PROPLIST(i, STREAM_SINK_INPUT), PA_PROP_MEDIA_FOCUS_ID))) {
+ if (pa_atoi(focus_id_str, &focus_id))
+ continue;
+ if (id == focus_id) {
+ pa_log_info("found matching sink-input(%p, %u) - focus_id(%d)", i, i->index, id);
+ pa_proplist_sets(GET_STREAM_PROPLIST(i, STREAM_SINK_INPUT), PA_PROP_MEDIA_FOCUS_STATUS,
+ acquired_focus_status ? STREAM_FOCUS_STATE_ACQUIRED : STREAM_FOCUS_STATE_RELEASED);
+ process_stream(m, i, STREAM_SINK_INPUT, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_FOCUS_CHANGED, false);
+
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_OK], DBUS_TYPE_INVALID));
+ goto success;
+ }
+ }
+ }
+ pa_log_error("could not find matching stream for this focus_id[%i]", id);
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
+success:
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static void handle_update_restriction(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ const char *name;
+ uint32_t value = 0;
+ DBusMessage *reply = NULL;
+ pa_stream_manager *m = (pa_stream_manager*)userdata;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(m);
+
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_UINT32, &value,
+ DBUS_TYPE_INVALID));
+ pa_log_info("handle_update_restriction(), name[%s], value[%u]", name, value);
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+
+ if (handle_restrictions(m, name, value) < 0) {
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
+ goto fail;
+ }
+
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_OK], DBUS_TYPE_INVALID));
+fail:
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static void handle_set_filter(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ const char *filter_name, *filter_parameters, *filter_group, *stream_type;
+ DBusMessage *reply = NULL;
+ pa_stream_manager *m = (pa_stream_manager*)userdata;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(m);
+
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_STRING, &filter_name,
+ DBUS_TYPE_STRING, &filter_parameters,
+ DBUS_TYPE_STRING, &filter_group,
+ DBUS_TYPE_STRING, &stream_type,
+ DBUS_TYPE_INVALID));
+ pa_log_info("handle_set_filter(), filter_name[%s], filter_parameters[%s], filter_group[%s], stream_type[%s]", filter_name,
+ filter_parameters, filter_group, stream_type);
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+
+ /* Set filter sink according to stream type */
+ if (update_filter(m, filter_name, filter_parameters, filter_group, stream_type) < 0) {
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL],
+ DBUS_TYPE_INVALID));
+ goto fail;
+ }
+
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_OK],
+ DBUS_TYPE_INVALID));
+
+fail:
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static void handle_unset_filter(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ const char *stream_type;
+ DBusMessage *reply = NULL;
+ pa_stream_manager *m = (pa_stream_manager*)userdata;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(m);
+
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_STRING, &stream_type,
+ DBUS_TYPE_INVALID));
+ pa_log_info("handle_unset_filter(), stream_type[%s]", stream_type);
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+
+ /* Unset filter sink according to stream type */
+ if (update_filter(m, NULL, NULL, NULL, stream_type) < 0) {
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL],
+ DBUS_TYPE_INVALID));
+ goto fail;
+ }
+
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_OK],
+ DBUS_TYPE_INVALID));
+
+fail:
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static void handle_control_filter(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ const char *filter_name, *filter_controls, *stream_type;
+ DBusMessage *reply = NULL;
+ pa_stream_manager *m = (pa_stream_manager*)userdata;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(m);
+
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_STRING, &filter_name,
+ DBUS_TYPE_STRING, &filter_controls,
+ DBUS_TYPE_STRING, &stream_type,
+ DBUS_TYPE_INVALID));
+ pa_log_info("handle_control_filter(), filter_name[%s], filter_controls[%s], stream_type[%s]", filter_name, filter_controls,
+ stream_type);
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+
+ /* Control parameters to filter sink */
+ if (control_filter(m, filter_name, filter_controls, stream_type, conn) < 0) {
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL],
+ DBUS_TYPE_INVALID));
+ goto fail;
+ }
+
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_OK],
+ DBUS_TYPE_INVALID));
+fail:
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+#define PA_PROP_MEDIA_FROM "media.from" /* It will be removed when the session concept is completely left out */
+static bool check_stream_exist_by_pid(pa_stream_manager *m, uint32_t pid, const char *stream_role, stream_type_t type) {
+ void *stream = NULL;
+ uint32_t idx = 0;
+ const char *role = NULL;
+ const char *app_pid_str = NULL;
+ uint32_t app_pid = 0;
+
+ pa_assert(m);
+ pa_assert(stream_role);
+
+ pa_log_info("check_stream_exist_by_pid(), pid[%u], role[%s], type[%d]", pid, stream_role, type);
+
+ PA_IDXSET_FOREACH(stream, (type == STREAM_SINK_INPUT) ? m->core->sink_inputs : m->core->source_outputs, idx) {
+ role = pa_proplist_gets(GET_STREAM_PROPLIST(stream, type), PA_PROP_MEDIA_ROLE);
+ if (!pa_safe_streq(role, stream_role))
+ continue;
+
+ if (!CHECK_STREAM_RUNNING(stream, type)) {
+ pa_log_info("stream(%p, index:%u) is not in running state, skip it.", stream, GET_STREAM_INDEX(stream, type));
+ continue;
+ }
+
+ app_pid_str = pa_proplist_gets(GET_STREAM_PROPLIST(stream, type), PA_PROP_APPLICATION_PROCESS_ID);
+ if (app_pid_str && !pa_atou(app_pid_str, &app_pid)) {
+ if (app_pid == pid) {
+ const char *media_from = NULL;
+ pa_log_info("found matching stream(%p, index:%u)", stream, GET_STREAM_INDEX(stream, type));
+
+ /* This is an exception case for session backward compatibility,
+ * It will be removed when the session concept is completely left out. */
+ media_from = pa_proplist_gets(GET_STREAM_PROPLIST(stream, type), PA_PROP_MEDIA_FROM);
+ if (pa_safe_streq(media_from, "openAL")) {
+ pa_log_info("stream(%p, index:%u) is from openAL, skip it.", stream, GET_STREAM_INDEX(stream, type));
+ continue;
+ }
+
+ return true;
+ }
+ }
+
+ /* Here we checks muse-server client pid also. It will be removed when the session concept is completely left out. */
+ app_pid_str = pa_proplist_gets(GET_STREAM_PROPLIST(stream, type), "mused.client_pid");
+ if (app_pid_str && !pa_atou(app_pid_str, &app_pid)) {
+ if (app_pid == pid) {
+ pa_log_info("found matching stream(%p, index:%u) of muse-server", stream, GET_STREAM_INDEX(stream, type));
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static void handle_check_stream_exist_by_pid(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ uint32_t pid = 0;
+ const char *type;
+ const char *direction;
+ stream_type_t stream_type = STREAM_SINK_INPUT;
+ DBusMessage *reply = NULL;
+ pa_stream_manager *m = (pa_stream_manager*)userdata;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(m);
+
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_UINT32, &pid,
+ DBUS_TYPE_STRING, &type,
+ DBUS_TYPE_STRING, &direction,
+ DBUS_TYPE_INVALID));
+ pa_log_info("handle_check_stream_exist_by_pid(), pid[%u], type[%s], direction[%s]", pid, type, direction);
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+
+ if (pa_streq(direction, "in"))
+ stream_type = STREAM_SOURCE_OUTPUT;
+ else if (pa_streq(direction, "out"))
+ stream_type = STREAM_SINK_INPUT;
+ else {
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INVALID_ARGUMENT],
+ DBUS_TYPE_INVALID));
+ goto fail;
+ }
+
+ if (!check_stream_exist_by_pid(m, pid, type, stream_type)) {
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_NO_STREAM],
+ DBUS_TYPE_INVALID));
+ goto fail;
+ }
+
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_OK],
+ DBUS_TYPE_INVALID));
+fail:
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static DBusHandlerResult handle_methods(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ int idx = 0;
+ pa_stream_manager *m = (pa_stream_manager*)userdata;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(m);
+
+ for (idx = 0; idx < METHOD_HANDLER_MAX; idx++) {
+ if (dbus_message_is_method_call(msg, STREAM_MANAGER_INTERFACE, method_handlers[idx].method_name)) {
+ pa_log_debug("Message signature [%s] (Expected [%s])", dbus_message_get_signature(msg), signature_args_for_in[idx]);
+ if (pa_streq(dbus_message_get_signature(msg), signature_args_for_in[idx])) {
+ method_handlers[idx].receive_cb(conn, msg, userdata);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ } else {
+ pa_log_warn("Wrong Argument Signature");
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_SIGNATURE, "Wrong Signature, Expected %s", signature_args_for_in[idx]);
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+ }
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static DBusHandlerResult method_handler_for_vt(DBusConnection *c, DBusMessage *m, void *userdata) {
+ pa_stream_manager *u = (pa_stream_manager*)userdata;
+ const char *path, *interface, *member;
+
+ pa_assert(c);
+ pa_assert(m);
+ pa_assert(u);
+
+ path = dbus_message_get_path(m);
+ interface = dbus_message_get_interface(m);
+ member = dbus_message_get_member(m);
+
+ pa_log_debug("dbus: path=%s, interface=%s, member=%s", path, interface, member);
+
+ if (!pa_streq(path, STREAM_MANAGER_OBJECT_PATH))
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ if (dbus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
+ return handle_introspect(c, m, u);
+ } else {
+ return handle_methods(c, m, u);
+ }
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static void send_volume_changed_signal(DBusConnection *conn, const char *direction, const char *volume_type, const uint32_t volume_level) {
+ DBusMessage *signal_msg;
+ DBusMessageIter msg_iter;
+
+ pa_assert(conn);
+ pa_assert(direction);
+ pa_assert(volume_type);
+
+ pa_log_debug("Send volume changed signal: direction(%s), type(%s), level(%d)", direction, volume_type, volume_level);
+
+ pa_assert_se(signal_msg = dbus_message_new_signal(STREAM_MANAGER_OBJECT_PATH, STREAM_MANAGER_INTERFACE, STREAM_MANAGER_SIGNAL_NAME_VOLUME_CHANGED));
+ dbus_message_iter_init_append(signal_msg, &msg_iter);
+
+ dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &direction);
+ dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &volume_type);
+ dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_UINT32, &volume_level);
+
+ pa_assert_se(dbus_connection_send(conn, signal_msg, NULL));
+ dbus_message_unref(signal_msg);
+ return;
+}
+
+void send_command_signal(DBusConnection *conn, const char *name, int value) {
+ DBusMessage *signal_msg;
+ DBusMessageIter msg_iter;
+
+ pa_assert(conn);
+ pa_assert(name);
+
+ pa_log_debug("Send command signal: name(%s), value(%d)", name, value);
+
+ pa_assert_se(signal_msg = dbus_message_new_signal(STREAM_MANAGER_OBJECT_PATH, STREAM_MANAGER_INTERFACE, STREAM_MANAGER_SIGNAL_NAME_COMMAND));
+ dbus_message_iter_init_append(signal_msg, &msg_iter);
+
+ dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &name);
+ dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_INT32, &value);
+
+ pa_assert_se(dbus_connection_send(conn, signal_msg, NULL));
+ dbus_message_unref(signal_msg);
+}
+
+int32_t init_dbus(pa_stream_manager *m) {
+ pa_assert(m);
+
+#ifdef USE_DBUS_PROTOCOL
+ m->dbus_protocol = pa_dbus_protocol_get(m->core);
+ pa_assert_se(pa_dbus_protocol_add_interface(m->dbus_protocol, STREAM_MANAGER_OBJECT_PATH, &stream_manager_interface_info, m) >= 0);
+ pa_assert_se(pa_dbus_protocol_register_extension(m->dbus_protocol, STREAM_MANAGER_INTERFACE) >= 0);
+#else
+ DBusError err;
+ pa_dbus_connection *conn = NULL;
+ static const DBusObjectPathVTable vtable = {
+ .message_function = method_handler_for_vt,
+ };
+
+ dbus_error_init(&err);
+
+ if (!(conn = pa_dbus_bus_get(m->core, DBUS_BUS_SYSTEM, &err)) || dbus_error_is_set(&err)) {
+ if (conn) {
+ pa_dbus_connection_unref(conn);
+ }
+ pa_log_error("Unable to contact D-Bus system bus: %s: %s", err.name, err.message);
+ return -1;
+ } else {
+ pa_log_notice("Got dbus connection");
+ }
+ m->dbus_conn = conn;
+ pa_assert_se(dbus_connection_register_object_path(pa_dbus_connection_get(conn), STREAM_MANAGER_OBJECT_PATH, &vtable, m));
+#endif
+ return 0;
+}
+
+void deinit_dbus(pa_stream_manager *m) {
+ pa_assert(m);
+
+#ifdef USE_DBUS_PROTOCOL
+ if (m->dbus_protocol) {
+ pa_assert_se(pa_dbus_protocol_unregister_extension(m->dbus_protocol, STREAM_MANAGER_INTERFACE) >= 0);
+ pa_assert_se(pa_dbus_protocol_remove_interface(m->dbus_protocol, STREAM_MANAGER_OBJECT_PATH, stream_manager_interface_info.name) >= 0);
+ pa_dbus_protocol_unref(m->dbus_protocol);
+ m->dbus_protocol = NULL;
+ }
+#else
+ if (m->dbus_conn) {
+ if (!dbus_connection_unregister_object_path(pa_dbus_connection_get(m->dbus_conn), STREAM_MANAGER_OBJECT_PATH))
+ pa_log_error("failed to unregister object path");
+ m->dbus_conn = NULL;
+ }
+#endif
+}
+
+#endif
\ No newline at end of file
#include "stream-manager-volume-priv.h"
#include "stream-manager-restriction-priv.h"
#include "stream-manager-filter-priv.h"
-
#ifdef HAVE_DBUS
-#define ARR_ARG_MAX 32
-#define STREAM_MANAGER_OBJECT_PATH "/org/pulseaudio/StreamManager"
-#define STREAM_MANAGER_INTERFACE "org.pulseaudio.StreamManager"
-/* method */
-#define STREAM_MANAGER_METHOD_NAME_GET_STREAM_INFO "GetStreamInfo"
-#define STREAM_MANAGER_METHOD_NAME_GET_STREAM_LIST "GetStreamList"
-#define STREAM_MANAGER_METHOD_NAME_SET_STREAM_ROUTE_DEVICES "SetStreamRouteDevices"
-#define STREAM_MANAGER_METHOD_NAME_SET_STREAM_ROUTE_OPTION "SetStreamRouteOption"
-#define STREAM_MANAGER_METHOD_NAME_SET_VOLUME_LEVEL "SetVolumeLevel"
-#define STREAM_MANAGER_METHOD_NAME_GET_VOLUME_LEVEL "GetVolumeLevel"
-#define STREAM_MANAGER_METHOD_NAME_GET_VOLUME_MAX_LEVEL "GetVolumeMaxLevel"
-#define STREAM_MANAGER_METHOD_NAME_SET_VOLUME_MUTE "SetVolumeMute"
-#define STREAM_MANAGER_METHOD_NAME_GET_VOLUME_MUTE "GetVolumeMute"
-#define STREAM_MANAGER_METHOD_NAME_GET_CURRENT_VOLUME_TYPE "GetCurrentVolumeType" /* The type that belongs to the stream of the current max priority */
-#define STREAM_MANAGER_METHOD_NAME_GET_CURRENT_MEDIA_ROUTING_PATH "GetCurrentMediaRoutingPath"
-#define STREAM_MANAGER_METHOD_NAME_UPDATE_FOCUS_STATUS "UpdateFocusStatus"
-#define STREAM_MANAGER_METHOD_NAME_UPDATE_RESTRICTION "UpdateRestriction"
-#define STREAM_MANAGER_METHOD_NAME_UPDATE_FOCUS_STATUS_BY_FOCUS_ID "UpdateFocusStatusByFocusId" /* Similar to UpdateFocusStatus but using focus id, it is only for backward compatibility */
-#define STREAM_MANAGER_METHOD_NAME_SET_FILTER "SetFilter"
-#define STREAM_MANAGER_METHOD_NAME_UNSET_FILTER "UnsetFilter"
-#define STREAM_MANAGER_METHOD_NAME_CONTROL_FILTER "ControlFilter"
-#define STREAM_MANAGER_METHOD_NAME_CHECK_STREAM_EXIST_BY_PID "CheckStreamExistByPid"
-/* signal */
-#define STREAM_MANAGER_SIGNAL_NAME_VOLUME_CHANGED "VolumeChanged"
-#define STREAM_MANAGER_SIGNAL_NAME_COMMAND "Command"
+#include "stream-manager-dbus-priv.h"
+#endif
#define IS_AVAILABLE_DIRECTION(stream_type, device_direction) \
((stream_type == STREAM_SINK_INPUT) ? (device_direction & DM_DEVICE_DIRECTION_OUT) : (device_direction & DM_DEVICE_DIRECTION_IN))
#define GET_DIRECTION(stream) \
((pa_sink_input_isinstance(stream)) ? DM_DEVICE_DIRECTION_OUT : DM_DEVICE_DIRECTION_IN)
-
-static DBusHandlerResult method_handler_for_vt(DBusConnection *c, DBusMessage *m, void *userdata);
-static DBusHandlerResult handle_introspect(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static DBusHandlerResult handle_methods(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_get_stream_info(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_get_stream_list(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_set_stream_route_devices(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_set_stream_route_option(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_set_volume_level(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_get_volume_level(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_get_volume_max_level(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_set_volume_mute(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_get_volume_mute(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_get_current_volume_type(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_get_current_media_routing_path(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_update_focus_status(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_update_focus_status_by_focus_id(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_update_restriction(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_set_filter(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_unset_filter(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_control_filter(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_check_stream_exist_by_pid(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void send_volume_changed_signal(DBusConnection *conn, const char *direction, const char *volume_type, const uint32_t volume_level);
-static void send_command_signal(DBusConnection *conn, const char *name, int value);
-
-enum method_handler_index {
- METHOD_HANDLER_GET_STREAM_INFO,
- METHOD_HANDLER_GET_STREAM_LIST,
- METHOD_HANDLER_SET_STREAM_ROUTE_DEVICES,
- METHOD_HANDLER_SET_STREAM_ROUTE_OPTION,
- METHOD_HANDLER_SET_VOLUME_LEVEL,
- METHOD_HANDLER_GET_VOLUME_LEVEL,
- METHOD_HANDLER_GET_VOLUME_MAX_LEVEL,
- METHOD_HANDLER_SET_VOLUME_MUTE,
- METHOD_HANDLER_GET_VOLUME_MUTE,
- METHOD_HANDLER_GET_CURRENT_VOLUME_TYPE,
- METHOD_HANDLER_GET_CURRENT_MEDIA_ROUTING_PATH,
- METHOD_HANDLER_UPDATE_FOCUS_STATUS,
- METHOD_HANDLER_UPDATE_FOCUS_STATUS_BY_FOCUS_ID,
- METHOD_HANDLER_UPDATE_RESTRICTION,
- METHOD_HANDLER_SET_FILTER,
- METHOD_HANDLER_UNSET_FILTER,
- METHOD_HANDLER_CONTROL_FILTER,
- METHOD_HANDLER_CHECK_STREAM_EXIST_BY_PID,
- METHOD_HANDLER_MAX
-};
-
-static pa_dbus_arg_info get_stream_info_args[] = { { "stream_type", "s", "in" },
- { "priority", "i", "out" },
- { "route_type", "i", "out" },
- { "volume_types", "as", "out" },
- { "avail_in_devices", "as", "out" },
- { "avail_out_devices", "as", "out" },
- { "avail_frameworks", "as", "out"} };
-static pa_dbus_arg_info get_stream_list_args[] = { { "stream_type", "as", "out" },
- { "priority", "ai", "out" } };
-static pa_dbus_arg_info set_stream_route_devices_args[] = { { "parent_id", "u", "in" },
- { "route_in_devices", "au", "in" },
- { "route_out_devices", "au", "in" },
- { "ret_msg", "s", "out" } };
-static pa_dbus_arg_info set_stream_route_option_args[] = { { "parent_id", "u", "in" },
- { "name", "s", "in" },
- { "value", "i", "in" },
- { "ret_msg", "s", "out" } };
-static pa_dbus_arg_info set_volume_level_args[] = { { "io_direction", "s", "in" },
- { "type", "s", "in" },
- { "level", "u", "in" },
- { "ret_msg", "s", "out" } };
-static pa_dbus_arg_info get_volume_level_args[] = { { "io_direction", "s", "in" },
- { "type", "s", "in" },
- { "level", "u", "out" },
- { "ret_msg", "s", "out" } };
-static pa_dbus_arg_info get_volume_max_level_args[] = { { "io_direction", "s", "in" },
- { "type", "s", "in" },
- { "level", "u", "out" },
- { "ret_msg", "s", "out" } };
-static pa_dbus_arg_info set_volume_mute_args[] = { { "io_direction", "s", "in" },
- { "type", "s", "in" },
- { "on", "u", "in" },
- { "ret_msg", "s", "out" } };
-static pa_dbus_arg_info get_volume_mute_args[] = { { "io_direction", "s", "in" },
- { "type", "s", "in" },
- { "on", "u", "out" },
- { "ret_msg", "s", "out" } };
-static pa_dbus_arg_info get_current_volume_type_args[] = { { "io_direction", "s", "in" },
- { "type", "s", "out" },
- { "ret_msg", "s", "out" } };
-static pa_dbus_arg_info get_current_media_routing_path_args[] = { { "io_direction", "s", "in" },
- { "device_type", "s", "out" },
- { "ret_msg", "s", "out" } };
-static pa_dbus_arg_info update_focus_status_args[] = { { "parent_id", "u", "in" },
- { "focus_status", "u", "in" },
- { "ret_msg", "s", "out" } };
-static pa_dbus_arg_info update_focus_status_by_focus_id_args[] = { { "focus_id", "i", "in" },
- { "focus_status", "u", "in" },
- { "ret_msg", "s", "out" } };
-static pa_dbus_arg_info update_restriction_args[] = { { "name", "s", "in" },
- { "value", "u", "in" },
- { "ret_msg", "s", "out" } };
-static pa_dbus_arg_info set_filter_args[] = { { "filter_name", "s", "in" },
- { "filter_parameters", "s", "in" },
- { "filter_group", "s", "in" },
- { "stream_type", "s", "in" },
- { "ret_msg", "s", "out" } };
-static pa_dbus_arg_info unset_filter_args[] = { { "stream_type", "s", "in" },
- { "ret_msg", "s", "out" } };
-static pa_dbus_arg_info control_filter_args[] = { { "filter_name", "s", "in" },
- { "filter_controls", "s", "in" },
- { "stream_type", "s", "in" },
- { "ret_msg", "s", "out" } };
-static pa_dbus_arg_info check_stream_exist_by_pid_args[] = { { "pid", "u", "in" },
- { "stream_type", "s", "in" },
- { "io_direction", "s", "in" },
- { "ret_msg", "s", "out" } };
-static const char* signature_args_for_in[] = { "s", "", "uauau", "usi", "ssu", "ss", "ss", "ssu", "ss", "s", "s", "uu", "iu", "su", "ssss", "s", "sss", "uss"};
-
-static pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = {
- [METHOD_HANDLER_GET_STREAM_INFO] = {
- .method_name = STREAM_MANAGER_METHOD_NAME_GET_STREAM_INFO,
- .arguments = get_stream_info_args,
- .n_arguments = sizeof(get_stream_info_args) / sizeof(pa_dbus_arg_info),
- .receive_cb = handle_get_stream_info },
- [METHOD_HANDLER_GET_STREAM_LIST] = {
- .method_name = STREAM_MANAGER_METHOD_NAME_GET_STREAM_LIST,
- .arguments = get_stream_list_args,
- .n_arguments = sizeof(get_stream_list_args) / sizeof(pa_dbus_arg_info),
- .receive_cb = handle_get_stream_list },
- [METHOD_HANDLER_SET_STREAM_ROUTE_DEVICES] = {
- .method_name = STREAM_MANAGER_METHOD_NAME_SET_STREAM_ROUTE_DEVICES,
- .arguments = set_stream_route_devices_args,
- .n_arguments = sizeof(set_stream_route_devices_args) / sizeof(pa_dbus_arg_info),
- .receive_cb = handle_set_stream_route_devices },
- [METHOD_HANDLER_SET_STREAM_ROUTE_OPTION] = {
- .method_name = STREAM_MANAGER_METHOD_NAME_SET_STREAM_ROUTE_OPTION,
- .arguments = set_stream_route_option_args,
- .n_arguments = sizeof(set_stream_route_option_args) / sizeof(pa_dbus_arg_info),
- .receive_cb = handle_set_stream_route_option },
- [METHOD_HANDLER_SET_VOLUME_LEVEL] = {
- .method_name = STREAM_MANAGER_METHOD_NAME_SET_VOLUME_LEVEL,
- .arguments = set_volume_level_args,
- .n_arguments = sizeof(set_volume_level_args) / sizeof(pa_dbus_arg_info),
- .receive_cb = handle_set_volume_level },
- [METHOD_HANDLER_GET_VOLUME_LEVEL] = {
- .method_name = STREAM_MANAGER_METHOD_NAME_GET_VOLUME_LEVEL,
- .arguments = get_volume_level_args,
- .n_arguments = sizeof(get_volume_level_args) / sizeof(pa_dbus_arg_info),
- .receive_cb = handle_get_volume_level },
- [METHOD_HANDLER_GET_VOLUME_MAX_LEVEL] = {
- .method_name = STREAM_MANAGER_METHOD_NAME_GET_VOLUME_MAX_LEVEL,
- .arguments = get_volume_max_level_args,
- .n_arguments = sizeof(get_volume_max_level_args) / sizeof(pa_dbus_arg_info),
- .receive_cb = handle_get_volume_max_level },
- [METHOD_HANDLER_SET_VOLUME_MUTE] = {
- .method_name = STREAM_MANAGER_METHOD_NAME_SET_VOLUME_MUTE,
- .arguments = set_volume_mute_args,
- .n_arguments = sizeof(set_volume_mute_args) / sizeof(pa_dbus_arg_info),
- .receive_cb = handle_set_volume_mute },
- [METHOD_HANDLER_GET_VOLUME_MUTE] = {
- .method_name = STREAM_MANAGER_METHOD_NAME_GET_VOLUME_MUTE,
- .arguments = get_volume_mute_args,
- .n_arguments = sizeof(get_volume_mute_args) / sizeof(pa_dbus_arg_info),
- .receive_cb = handle_get_volume_mute },
- [METHOD_HANDLER_GET_CURRENT_VOLUME_TYPE] = {
- .method_name = STREAM_MANAGER_METHOD_NAME_GET_CURRENT_VOLUME_TYPE,
- .arguments = get_current_volume_type_args,
- .n_arguments = sizeof(get_current_volume_type_args) / sizeof(pa_dbus_arg_info),
- .receive_cb = handle_get_current_volume_type },
- [METHOD_HANDLER_GET_CURRENT_MEDIA_ROUTING_PATH] = {
- .method_name = STREAM_MANAGER_METHOD_NAME_GET_CURRENT_MEDIA_ROUTING_PATH,
- .arguments = get_current_media_routing_path_args,
- .n_arguments = sizeof(get_current_media_routing_path_args) / sizeof(pa_dbus_arg_info),
- .receive_cb = handle_get_current_media_routing_path },
- [METHOD_HANDLER_UPDATE_FOCUS_STATUS] = {
- .method_name = STREAM_MANAGER_METHOD_NAME_UPDATE_FOCUS_STATUS,
- .arguments = update_focus_status_args,
- .n_arguments = sizeof(update_focus_status_args) / sizeof(pa_dbus_arg_info),
- .receive_cb = handle_update_focus_status },
- [METHOD_HANDLER_UPDATE_FOCUS_STATUS_BY_FOCUS_ID] = {
- .method_name = STREAM_MANAGER_METHOD_NAME_UPDATE_FOCUS_STATUS_BY_FOCUS_ID,
- .arguments = update_focus_status_by_focus_id_args,
- .n_arguments = sizeof(update_focus_status_by_focus_id_args) / sizeof(pa_dbus_arg_info),
- .receive_cb = handle_update_focus_status_by_focus_id },
- [METHOD_HANDLER_UPDATE_RESTRICTION] = {
- .method_name = STREAM_MANAGER_METHOD_NAME_UPDATE_RESTRICTION,
- .arguments = update_restriction_args,
- .n_arguments = sizeof(update_restriction_args) / sizeof(pa_dbus_arg_info),
- .receive_cb = handle_update_restriction },
- [METHOD_HANDLER_SET_FILTER] = {
- .method_name = STREAM_MANAGER_METHOD_NAME_SET_FILTER,
- .arguments = set_filter_args,
- .n_arguments = sizeof(set_filter_args) / sizeof(pa_dbus_arg_info),
- .receive_cb = handle_set_filter },
- [METHOD_HANDLER_UNSET_FILTER] = {
- .method_name = STREAM_MANAGER_METHOD_NAME_UNSET_FILTER,
- .arguments = unset_filter_args,
- .n_arguments = sizeof(unset_filter_args) / sizeof(pa_dbus_arg_info),
- .receive_cb = handle_unset_filter },
- [METHOD_HANDLER_CONTROL_FILTER] = {
- .method_name = STREAM_MANAGER_METHOD_NAME_CONTROL_FILTER,
- .arguments = control_filter_args,
- .n_arguments = sizeof(control_filter_args) / sizeof(pa_dbus_arg_info),
- .receive_cb = handle_control_filter },
- [METHOD_HANDLER_CHECK_STREAM_EXIST_BY_PID] = {
- .method_name = STREAM_MANAGER_METHOD_NAME_CHECK_STREAM_EXIST_BY_PID,
- .arguments = check_stream_exist_by_pid_args,
- .n_arguments = sizeof(check_stream_exist_by_pid_args) / sizeof(pa_dbus_arg_info),
- .receive_cb = handle_check_stream_exist_by_pid },
-};
-
-const char *dbus_str_none = "none";
-const char* stream_manager_dbus_ret_str[] = {"STREAM_MANAGER_RETURN_OK",
- "STREAM_MANAGER_RETURN_ERROR_INTERNAL",
- "STREAM_MANAGER_RETURN_ERROR_NO_STREAM",
- "STREAM_MANAGER_RETURN_ERROR_INVALID_ARGUMENT",
- "STREAM_MANAGER_RETURN_ERROR_DEVICE_NOT_FOUND",
- "STREAM_MANAGER_RETURN_ERROR_POLICY"};
-typedef enum {
- RET_MSG_OK,
- RET_MSG_ERROR_INTERNAL,
- RET_MSG_ERROR_NO_STREAM,
- RET_MSG_ERROR_INVALID_ARGUMENT,
- RET_MSG_ERROR_DEVICE_NOT_FOUND,
- RET_MSG_ERROR_POLICY,
-} ret_msg_t;
-
-#ifdef USE_DBUS_PROTOCOL
-
-static pa_dbus_interface_info stream_manager_interface_info = {
- .name = STREAM_MANAGER_INTERFACE,
- .method_handlers = method_handlers,
- .n_method_handlers = METHOD_HANDLER_MAX,
- .property_handlers = ,
- .n_property_handlers = ,
- .get_all_properties_cb =,
- .signals =,
- .n_signals =
-};
-
-#else
-
-#define STREAM_MGR_INTROSPECT_XML \
- DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
- "<node>" \
- " <interface name=\"STREAM_MANAGER_INTERFACE\">" \
- " <method name=\"STREAM_MANAGER_METHOD_NAME_GET_STREAM_INFO\">" \
- " <arg name=\"stream_type\" direction=\"in\" type=\"s\"/>" \
- " <arg name=\"priority\" direction=\"out\" type=\"i\"/>" \
- " <arg name=\"route_type\" direction=\"out\" type=\"i\"/>" \
- " <arg name=\"volume_types\" direction=\"out\" type=\"as\"/>" \
- " <arg name=\"avail_in_devices\" direction=\"out\" type=\"as\"/>" \
- " <arg name=\"avail_out_devices\" direction=\"out\" type=\"as\"/>" \
- " <arg name=\"avail_frameworks\" direction=\"out\" type=\"as\"/>" \
- " </method>" \
- " <method name=\"STREAM_MANAGER_METHOD_NAME_GET_STREAM_LIST\">" \
- " <arg name=\"stream_type\" direction=\"in\" type=\"as\"/>" \
- " <arg name=\"priority\" direction=\"in\" type=\"ai\"/>" \
- " </method>" \
- " <method name=\"STREAM_MANAGER_METHOD_NAME_SET_STREAM_ROUTE_DEVICES\">"\
- " <arg name=\"parent_id\" direction=\"in\" type=\"u\"/>" \
- " <arg name=\"route_in_devices\" direction=\"in\" type=\"au\"/>" \
- " <arg name=\"route_out_devices\" direction=\"in\" type=\"au\"/>" \
- " <arg name=\"ret_msg\" direction=\"out\" type=\"s\"/>" \
- " </method>" \
- " <method name=\"STREAM_MANAGER_METHOD_NAME_SET_STREAM_ROUTE_OPTION\">" \
- " <arg name=\"parent_id\" direction=\"in\" type=\"u\"/>" \
- " <arg name=\"name\" direction=\"in\" type=\"s\"/>" \
- " <arg name=\"value\" direction=\"in\" type=\"i\"/>" \
- " <arg name=\"ret_msg\" direction=\"out\" type=\"s\"/>" \
- " </method>" \
- " <method name=\"STREAM_MANAGER_METHOD_NAME_SET_VOLUME_LEVEL\">" \
- " <arg name=\"io_direction\" direction=\"in\" type=\"s\"/>" \
- " <arg name=\"type\" direction=\"in\" type=\"s\"/>" \
- " <arg name=\"level\" direction=\"in\" type=\"u\"/>" \
- " <arg name=\"ret_msg\" direction=\"out\" type=\"s\"/>" \
- " </method>" \
- " <method name=\"STREAM_MANAGER_METHOD_NAME_GET_VOLUME_LEVEL\">" \
- " <arg name=\"io_direction\" direction=\"in\" type=\"s\"/>" \
- " <arg name=\"type\" direction=\"in\" type=\"s\"/>" \
- " <arg name=\"level\" direction=\"out\" type=\"u\"/>" \
- " <arg name=\"ret_msg\" direction=\"out\" type=\"s\"/>" \
- " </method>" \
- " <method name=\"STREAM_MANAGER_METHOD_NAME_GET_VOLUME_MAX_LEVEL\">" \
- " <arg name=\"io_direction\" direction=\"in\" type=\"s\"/>" \
- " <arg name=\"type\" direction=\"in\" type=\"s\"/>" \
- " <arg name=\"level\" direction=\"out\" type=\"u\"/>" \
- " <arg name=\"ret_msg\" direction=\"out\" type=\"s\"/>" \
- " </method>" \
- " <method name=\"STREAM_MANAGER_METHOD_NAME_SET_VOLUME_MUTE\">" \
- " <arg name=\"io_direction\" direction=\"in\" type=\"s\"/>" \
- " <arg name=\"type\" direction=\"in\" type=\"s\"/>" \
- " <arg name=\"on\" direction=\"in\" type=\"u\"/>" \
- " <arg name=\"ret_msg\" direction=\"out\" type=\"s\"/>" \
- " </method>" \
- " <method name=\"STREAM_MANAGER_METHOD_NAME_GET_VOLUME_MUTE\">" \
- " <arg name=\"io_direction\" direction=\"in\" type=\"s\"/>" \
- " <arg name=\"type\" direction=\"in\" type=\"s\"/>" \
- " <arg name=\"on\" direction=\"out\" type=\"u\"/>" \
- " <arg name=\"ret_msg\" direction=\"out\" type=\"s\"/>" \
- " </method>" \
- " <method name=\"STREAM_MANAGER_METHOD_NAME_GET_CURRENT_VOLUME_TYPE\">" \
- " <arg name=\"io_direction\" direction=\"in\" type=\"s\"/>" \
- " <arg name=\"type\" direction=\"out\" type=\"s\"/>" \
- " <arg name=\"ret_msg\" direction=\"out\" type=\"s\"/>" \
- " </method>" \
- " <method name=\"STREAM_MANAGER_METHOD_NAME_GET_CURRENT_MEDIA_ROUTING_PATH\">" \
- " <arg name=\"io_direction\" direction=\"in\" type=\"s\"/>" \
- " <arg name=\"device_type\" direction=\"out\" type=\"s\"/>" \
- " <arg name=\"ret_msg\" direction=\"out\" type=\"s\"/>" \
- " </method>" \
- " <method name=\"STREAM_MANAGER_METHOD_NAME_UPDATE_FOCUS_STATUS\">" \
- " <arg name=\"parent_id\" direction=\"in\" type=\"u\"/>" \
- " <arg name=\"focus_status\" direction=\"in\" type=\"u\"/>" \
- " <arg name=\"ret_msg\" direction=\"out\" type=\"s\"/>" \
- " </method>" \
- " <method name=\"STREAM_MANAGER_METHOD_NAME_UPDATE_FOCUS_STATUS_BY_FOCUS_ID\">" \
- " <arg name=\"focus_id\" direction=\"in\" type=\"i\"/>" \
- " <arg name=\"focus_status\" direction=\"in\" type=\"u\"/>" \
- " <arg name=\"ret_msg\" direction=\"out\" type=\"s\"/>" \
- " </method>" \
- " <method name=\"STREAM_MANAGER_METHOD_NAME_UPDATE_RESTRICTION\">" \
- " <arg name=\"name\" direction=\"in\" type=\"s\"/>" \
- " <arg name=\"value\" direction=\"in\" type=\"u\"/>" \
- " <arg name=\"ret_msg\" direction=\"out\" type=\"s\"/>" \
- " </method>" \
- " <method name=\"STREAM_MANAGER_METHOD_NAME_SET_FILTER\">" \
- " <arg name=\"filter_name\" direction=\"in\" type=\"s\"/>" \
- " <arg name=\"filter_parameters\" direction=\"in\" type=\"s\"/>" \
- " <arg name=\"filter_group\" direction=\"in\" type=\"s\"/>" \
- " <arg name=\"stream_type\" direction=\"in\" type=\"s\"/>" \
- " <arg name=\"ret_msg\" direction=\"out\" type=\"s\"/>" \
- " </method>" \
- " <method name=\"STREAM_MANAGER_METHOD_NAME_UNSET_FILTER\">" \
- " <arg name=\"stream_type\" direction=\"in\" type=\"s\"/>" \
- " <arg name=\"ret_msg\" direction=\"out\" type=\"s\"/>" \
- " </method>" \
- " <method name=\"STREAM_MANAGER_METHOD_NAME_CONTROL_FILTER\">" \
- " <arg name=\"filter_name\" direction=\"in\" type=\"s\"/>" \
- " <arg name=\"filter_controls\" direction=\"in\" type=\"s\"/>" \
- " <arg name=\"stream_type\" direction=\"in\" type=\"s\"/>" \
- " <arg name=\"ret_msg\" direction=\"out\" type=\"s\"/>" \
- " </method>" \
- " <method name=\"STREAM_MANAGER_METHOD_NAME_CHECK_STREAM_EXIST_BY_PID\">" \
- " <arg name=\"pid\" direction=\"in\" type=\"u\"/>" \
- " <arg name=\"stream_type\" direction=\"in\" type=\"s\"/>" \
- " <arg name=\"io_direction\" direction=\"in\" type=\"s\"/>" \
- " <arg name=\"ret_msg\" direction=\"out\" type=\"s\"/>" \
- " </method>" \
- " <signal name=\"STREAM_MANAGER_SIGNAL_NAME_VOLUME_CHANGED\">" \
- " <arg name=\"direction\" type=\"s\"/>" \
- " <arg name=\"volume_type\" type=\"s\"/>" \
- " <arg name=\"volume_level\" type=\"u\"/>" \
- " </signal>" \
- " <signal name=\"STREAM_MANAGER_SIGNAL_NAME_COMMAND\">" \
- " <arg name=\"name\" type=\"s\"/>" \
- " <arg name=\"value\" type=\"i\"/>" \
- " </signal>" \
- " </interface>" \
- " <interface name=\"org.freedesktop.DBus.Introspectable\">" \
- " <method name=\"Introspect\">" \
- " <arg name=\"data\" type=\"s\" direction=\"out\"/>" \
- " </method>" \
- " </interface>" \
- "</node>"
-#endif
-
-#endif
+#define CONVERT_TO_DEVICE_DIRECTION(stream_type) \
+ ((stream_type == STREAM_SINK_INPUT) ? DM_DEVICE_DIRECTION_OUT : DM_DEVICE_DIRECTION_IN)
#define STREAM_MANAGER_CLIENT_NAME "SOUND_MANAGER_STREAM_INFO" /* The client via sound-manager */
#define VIRTUAL_STREAM_NAME "VIRTUAL_STREAM" /* The virtual stream created by sound-manager */
#define DEFAULT_ROLE "media"
#define SKIP_ROLE "skip"
#define ACTIVE_DEV_REMOVED "removed"
+#define STRING_NONE "none"
/* There are some streams that need to be skipped.
* In other words, we do not care about streams that have a name of listed as below */
#define NAME_FOR_SKIP_MAX 1
const char* stream_manager_media_names_for_skip[NAME_FOR_SKIP_MAX] = {"pulsesink probe"};
-#define STREAM_FOCUS_STATE_RELEASED "0"
-#define STREAM_FOCUS_STATE_ACQUIRED "1"
-
#define MUTE_KEY "mute_by_device_disconnection"
#define TIMED_UNMUTE_USEC 300000
-typedef enum _process_stream_result {
- PROCESS_STREAM_RESULT_OK,
- PROCESS_STREAM_RESULT_STOP,
- PROCESS_STREAM_RESULT_SKIP,
-} process_stream_result_t;
-
-typedef enum _process_command_type {
- PROCESS_COMMAND_PREPARE,
- PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_STARTED,
- PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_ENDED,
- PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_FOCUS_CHANGED,
- PROCESS_COMMAND_UPDATE_VOLUME,
- PROCESS_COMMAND_ADD_PARENT_ID,
- PROCESS_COMMAND_REMOVE_PARENT_ID,
- PROCESS_COMMAND_UPDATE_BUFFER_ATTR,
- PROCESS_COMMAND_APPLY_FILTER,
-} process_command_type_t;
-
-typedef enum _notify_command_type {
- NOTIFY_COMMAND_SELECT_PROPER_SINK_OR_SOURCE_FOR_INIT,
- NOTIFY_COMMAND_CHANGE_ROUTE_START,
- NOTIFY_COMMAND_CHANGE_ROUTE_END,
- NOTIFY_COMMAND_UPDATE_ROUTE_OPTION,
- NOTIFY_COMMAND_INFORM_STREAM_CONNECTED,
- NOTIFY_COMMAND_INFORM_STREAM_DISCONNECTED,
-} notify_command_type_t;
-
const char* process_command_type_str[] = {
"PREPARE",
"CHANGE_ROUTE_BY_STREAM_STARTED",
#define STREAM_MAP_STREAM_AVAIL_OUT_DEVICES "avail-out-devices"
#define STREAM_MAP_STREAM_AVAIL_FRAMEWORKS "avail-frameworks"
-#define AVAIL_DEVICES_MAX 16
-#define AVAIL_FRAMEWORKS_MAX 16
-#define AVAIL_STREAMS_MAX 32
-typedef struct _stream_info_per_type {
- int32_t priority;
- int32_t route_type;
- int32_t num_of_in_devices;
- int32_t num_of_out_devices;
- int32_t num_of_frameworks;
- const char *volume_types[STREAM_DIRECTION_MAX];
- const char *avail_in_devices[AVAIL_DEVICES_MAX];
- const char *avail_out_devices[AVAIL_DEVICES_MAX];
- const char *avail_frameworks[AVAIL_FRAMEWORKS_MAX];
-} stream_info_per_type;
-typedef struct _stream_list {
- int32_t num_of_streams;
- char *types[AVAIL_STREAMS_MAX];
- int32_t priorities[AVAIL_STREAMS_MAX];
-} stream_list;
-typedef struct _stream_route_option {
- const char *name;
- int32_t value;
-} stream_route_option;
-
-#define CONVERT_TO_DEVICE_DIRECTION(stream_type) \
- ((stream_type == STREAM_SINK_INPUT) ? DM_DEVICE_DIRECTION_OUT : DM_DEVICE_DIRECTION_IN)
-
-static ret_msg_t do_notify(pa_stream_manager *m, notify_command_type_t command, stream_type_t type, bool is_new_data, void *user_data);
-static process_stream_result_t process_stream(pa_stream_manager *m, void *stream, stream_type_t type, process_command_type_t command, bool is_new_data);
-
-static bool stream_is_call_family(pa_object *stream) {
+bool stream_is_call_family(pa_object *stream) {
const char *stream_role;
pa_proplist *prop;
return ret;
}
-static int32_t get_route_type(void *stream, stream_type_t stream_type, bool is_new_data, stream_route_type_t *stream_route_type) {
+int32_t get_route_type(void *stream, stream_type_t stream_type, bool is_new_data, stream_route_type_t *stream_route_type) {
const char *route_type_str = NULL;
pa_assert(stream);
return 0;
}
-static int32_t get_available_streams(pa_stream_manager *m, stream_list *list) {
- void *state = NULL;
- stream_info *s = NULL;
- char *role = NULL;
- int i = 0;
-
- pa_log_info("get_available_streams");
- if (m->stream_infos) {
- while ((s = pa_hashmap_iterate(m->stream_infos, &state, (const void**)&role))) {
- if (i < AVAIL_STREAMS_MAX) {
- list->priorities[i] = s->priority;
- list->types[i++] = role;
- pa_log_debug(" [%d] stream_type[%s], priority[%d]", i-1, role, s->priority);
- } else {
- pa_log_error(" out of range, [%d]", i);
- break;
- }
- }
- list->num_of_streams = i;
- pa_log_debug(" num_of_streams[%d]", i);
- } else {
- pa_log_error("stream_map is not initialized..");
- return -1;
- }
- return 0;
-}
-
-static int32_t get_stream_info(pa_stream_manager *m, const char *stream_role, stream_info_per_type *info) {
+int32_t get_stream_info(pa_stream_manager *m, const char *stream_role, stream_info_per_type *info) {
uint32_t idx = 0;
char *name;
int i = 0;
/* set variables for error */
info->priority = -1;
info->num_of_in_devices = info->num_of_out_devices = info->num_of_frameworks = 1;
- info->volume_types[0] = info->volume_types[1] = dbus_str_none;
- info->avail_in_devices[0] = dbus_str_none;
- info->avail_out_devices[0] = dbus_str_none;
- info->avail_frameworks[0] = dbus_str_none;
+ info->volume_types[0] = info->volume_types[1] = STRING_NONE;
+ info->avail_in_devices[0] = STRING_NONE;
+ info->avail_out_devices[0] = STRING_NONE;
+ info->avail_frameworks[0] = STRING_NONE;
pa_log_error("could not find the stream_role : %s", stream_role);
return -1;
}
return 0;
}
-#ifdef HAVE_DBUS
-static DBusHandlerResult handle_introspect(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- const char *xml = STREAM_MGR_INTROSPECT_XML;
- DBusMessage *r = NULL;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(userdata);
-
- pa_assert_se(r = dbus_message_new_method_return(msg));
- pa_assert_se(dbus_message_append_args(r, DBUS_TYPE_STRING, &xml, DBUS_TYPE_INVALID));
-
- if (r) {
- pa_assert_se(dbus_connection_send((conn), r, NULL));
- dbus_message_unref(r);
- }
-
- return DBUS_HANDLER_RESULT_HANDLED;
-}
-
-static void handle_get_stream_list(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- stream_list list;
- DBusMessage *reply = NULL;
- DBusMessageIter msg_iter;
- pa_stream_manager *m = (pa_stream_manager*)userdata;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(m);
-
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_INVALID));
- pa_log_info("handle_get_stream_list() dbus method is called");
+int32_t get_available_streams(pa_stream_manager *m, stream_list *list) {
+ void *state = NULL;
+ stream_info *s = NULL;
+ char *role = NULL;
+ int i = 0;
- memset(&list, 0, sizeof(stream_list));
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
- dbus_message_iter_init_append(reply, &msg_iter);
- if (!get_available_streams(m, &list)) {
- pa_dbus_append_basic_array_variant(&msg_iter, DBUS_TYPE_STRING, &list.types, list.num_of_streams);
- pa_dbus_append_basic_array_variant(&msg_iter, DBUS_TYPE_INT32, &list.priorities, list.num_of_streams);
+ pa_log_info("get_available_streams");
+ if (m->stream_infos) {
+ while ((s = pa_hashmap_iterate(m->stream_infos, &state, (const void**)&role))) {
+ if (i < AVAIL_STREAMS_MAX) {
+ list->priorities[i] = s->priority;
+ list->types[i++] = role;
+ pa_log_debug(" [%d] stream_type[%s], priority[%d]", i-1, role, s->priority);
+ } else {
+ pa_log_error(" out of range, [%d]", i);
+ break;
+ }
+ }
+ list->num_of_streams = i;
+ pa_log_debug(" num_of_streams[%d]", i);
} else {
- pa_dbus_append_basic_array_variant(&msg_iter, DBUS_TYPE_STRING, NULL, 0);
- pa_dbus_append_basic_array_variant(&msg_iter, DBUS_TYPE_INT32, NULL, 0);
+ pa_log_error("stream_map is not initialized..");
+ return -1;
}
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static void handle_get_stream_info(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- char *type;
- stream_info_per_type info;
- DBusMessage *reply = NULL;
- DBusMessageIter msg_iter;
- pa_stream_manager *m = (pa_stream_manager*)userdata;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(m);
-
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_STRING, &type,
- DBUS_TYPE_INVALID));
- pa_log_info("handle_get_stream_info(), type[%s]", type);
-
- memset(&info, 0, sizeof(stream_info_per_type));
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
- dbus_message_iter_init_append(reply, &msg_iter);
- get_stream_info(m, type, &info);
- pa_dbus_append_basic_variant(&msg_iter, DBUS_TYPE_INT32, &info.priority);
- pa_dbus_append_basic_variant(&msg_iter, DBUS_TYPE_INT32, &info.route_type);
- pa_dbus_append_basic_array_variant(&msg_iter, DBUS_TYPE_STRING, &info.volume_types, STREAM_DIRECTION_MAX);
- pa_dbus_append_basic_array_variant(&msg_iter, DBUS_TYPE_STRING, &info.avail_in_devices, info.num_of_in_devices);
- pa_dbus_append_basic_array_variant(&msg_iter, DBUS_TYPE_STRING, &info.avail_out_devices, info.num_of_out_devices);
- pa_dbus_append_basic_array_variant(&msg_iter, DBUS_TYPE_STRING, &info.avail_frameworks, info.num_of_frameworks);
-
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
+ return 0;
}
-
-static stream_parent* get_stream_parent(pa_object *stream, pa_stream_manager *m) {
+static stream_parent* get_stream_parent(pa_stream_manager *m, pa_object *stream) {
pa_proplist *prop;
const char *parent_id;
uint32_t parent_id_u;
- pa_assert(stream);
pa_assert(m);
+ pa_assert(stream);
if (pa_sink_input_isinstance(stream))
prop = PA_SINK_INPUT(stream)->proplist;
return pa_hashmap_get(m->stream_parents, (const void*)parent_id_u);
}
-static pa_idxset* get_route_devices(pa_object *stream, pa_stream_manager *m) {
+static pa_idxset* get_route_devices(pa_stream_manager *m, pa_object *stream) {
stream_parent *sp;
- pa_assert(stream);
pa_assert(m);
+ pa_assert(stream);
- if ((sp = get_stream_parent(stream, m)) == NULL) {
+ if ((sp = get_stream_parent(m, stream)) == NULL) {
pa_log_error("No stream parent for this stream");
return NULL;
}
return sp->idx_route_in_devices;
}
-static pa_idxset* get_avail_device_types(const char *stream_role, dm_device_direction_t direction, pa_stream_manager *m) {
+static pa_idxset* get_avail_device_types(pa_stream_manager *m, const char *stream_role, dm_device_direction_t direction) {
stream_info *si;
- pa_assert(stream_role);
pa_assert(m);
+ pa_assert(stream_role);
if (!(si = pa_hashmap_get(m->stream_infos, stream_role))) {
pa_log_warn("not supported role[%s]", stream_role);
return si->idx_avail_out_devices;
}
-static void activate_device_only(pa_tz_device *device, pa_stream_manager *m) {
+static void activate_device_only(pa_stream_manager *m, pa_tz_device *device) {
pa_idxset *device_list;
pa_tz_device *device_iter;
uint32_t device_idx, id, others_id;
dm_device_state_t others_state;
char *device_type;
- pa_assert(device);
pa_assert(m);
+ pa_assert(device);
direction = pa_tz_device_get_direction(device);
id = pa_tz_device_get_id(device);
return ;
}
-static pa_tz_device* get_media_auto_device(dm_device_direction_t find_direction, pa_stream_manager *m) {
+pa_tz_device* get_media_auto_device(pa_stream_manager *m, dm_device_direction_t find_direction) {
pa_idxset *avail_device_types;
char *device_type;
pa_tz_device *device;
dm_device_direction_t direction;
uint32_t idx;
+ pa_assert(m);
+
pa_log_info("get media auto device for %d", find_direction);
if (find_direction == DM_DEVICE_DIRECTION_BOTH) {
return NULL;
}
- avail_device_types = get_avail_device_types(STREAM_ROLE_MEDIA, find_direction, m);
+ avail_device_types = get_avail_device_types(m, STREAM_ROLE_MEDIA, find_direction);
if (!avail_device_types) {
pa_log_error("No avail device types for media");
return NULL;
return NULL;
}
-static pa_tz_device* get_media_last_device(dm_device_direction_t find_direction, pa_stream_manager *m) {
+pa_tz_device* get_media_last_device(pa_stream_manager *m, dm_device_direction_t find_direction) {
char *device_type;
pa_tz_device *next_device, *latest_device = NULL;
pa_usec_t creation_time = 0;
pa_idxset *avail_device_types;
uint32_t idx, id;
+ pa_assert(m);
+
pa_log_info("get media last device for %d", find_direction);
/* Only can get playback or capture device one by one */
return NULL;
}
- avail_device_types = get_avail_device_types(STREAM_ROLE_MEDIA, find_direction, m);
+ avail_device_types = get_avail_device_types(m, STREAM_ROLE_MEDIA, find_direction);
if (!avail_device_types) {
pa_log_error("No avail device types for media");
return NULL;
/* select device which of type is in avail_device_types, and highest priority in
* route_device */
-static pa_tz_device* select_device_from_avail_device_types(pa_idxset *avail_device_types,
- pa_idxset *route_devices, pa_stream_manager *m) {
+static pa_tz_device* select_device_from_avail_device_types(pa_stream_manager *m,
+ pa_idxset *avail_device_types, pa_idxset *route_devices) {
char *device_type;
uint32_t route_device_idx, device_type_idx;
uint32_t *route_device_id;
pa_tz_device *device, *candidate = NULL;
+ pa_assert(m);
+
if (avail_device_types == NULL)
return NULL;
if (route_devices == NULL)
}
/* stream should be one of 'call-voice' or 'call-video' or 'voip' */
-static int change_active_route_for_call(pa_object *stream, bool stream_start, pa_stream_manager *m) {
+int change_active_route_for_call(pa_stream_manager *m, pa_object *stream, bool stream_start) {
pa_tz_device *device;
pa_idxset *avail_device_types, *route_devices;
pa_proplist *prop;
const char *stream_role;
- pa_assert(stream);
pa_assert(m);
pa_assert(m->stream_parents);
+ pa_assert(stream);
pa_log_info("Call virtual stream %s, change active device", stream_start ? "start" : "change");
return -1;
}
- avail_device_types = get_avail_device_types(stream_role, GET_DIRECTION(stream), m);
+ avail_device_types = get_avail_device_types(m, stream_role, GET_DIRECTION(stream));
if (!avail_device_types) {
pa_log_error("No avail device typs for [%s]", stream_role);
return -1;
}
- route_devices = get_route_devices(stream, m);
+ route_devices = get_route_devices(m, stream);
if (!route_devices) {
pa_log_error("No route devices for this stream");
return -1;
}
- device = select_device_from_avail_device_types(avail_device_types, route_devices, m);
+ device = select_device_from_avail_device_types(m, avail_device_types, route_devices);
if (!device) {
pa_log_error("Failed to select device to activate on call state");
return -1;
}
- activate_device_only(device, m);
+ activate_device_only(m, device);
return 0;
}
}
if (media_info->route_type == STREAM_ROUTE_TYPE_AUTO) {
- playback_device = get_media_auto_device(DM_DEVICE_DIRECTION_OUT, m);
- capture_device = get_media_auto_device(DM_DEVICE_DIRECTION_IN, m);
+ playback_device = get_media_auto_device(m, DM_DEVICE_DIRECTION_OUT);
+ capture_device = get_media_auto_device(m, DM_DEVICE_DIRECTION_IN);
} else if(media_info->route_type == STREAM_ROUTE_TYPE_AUTO_LAST_CONNECTED) {
- playback_device = get_media_last_device(DM_DEVICE_DIRECTION_OUT, m);
- capture_device = get_media_last_device(DM_DEVICE_DIRECTION_IN, m);
+ playback_device = get_media_last_device(m, DM_DEVICE_DIRECTION_OUT);
+ capture_device = get_media_last_device(m, DM_DEVICE_DIRECTION_IN);
} else {
pa_log_error("unexpected routing type for media[%d]", media_info->route_type);
return;
}
if (playback_device)
- activate_device_only(playback_device, m);
+ activate_device_only(m, playback_device);
else
pa_log_info("There is no playback-device");
if (capture_device)
- activate_device_only(capture_device, m);
+ activate_device_only(m, capture_device);
else
pa_log_info("There is no capture-device");
}
set_media_active_device(m);
}
-#define PA_PROP_MEDIA_FROM "media.from" /* It will be removed when the session concept is completely left out */
-static bool check_stream_exist_by_pid(pa_stream_manager *m, uint32_t pid, const char *stream_role, stream_type_t type) {
- void *stream = NULL;
- uint32_t idx = 0;
- const char *role = NULL;
- const char *app_pid_str = NULL;
- uint32_t app_pid = 0;
-
- pa_assert(m);
- pa_assert(stream_role);
-
- pa_log_info("check_stream_exist_by_pid(), pid[%u], role[%s], type[%d]", pid, stream_role, type);
-
- PA_IDXSET_FOREACH(stream, (type == STREAM_SINK_INPUT) ? m->core->sink_inputs : m->core->source_outputs, idx) {
- role = pa_proplist_gets(GET_STREAM_PROPLIST(stream, type), PA_PROP_MEDIA_ROLE);
- if (!pa_safe_streq(role, stream_role))
- continue;
-
- if (!CHECK_STREAM_RUNNING(stream, type)) {
- pa_log_info("stream(%p, index:%u) is not in running state, skip it.", stream, GET_STREAM_INDEX(stream, type));
- continue;
- }
-
- app_pid_str = pa_proplist_gets(GET_STREAM_PROPLIST(stream, type), PA_PROP_APPLICATION_PROCESS_ID);
- if (app_pid_str && !pa_atou(app_pid_str, &app_pid)) {
- if (app_pid == pid) {
- const char *media_from = NULL;
- pa_log_info("found matching stream(%p, index:%u)", stream, GET_STREAM_INDEX(stream, type));
-
- /* This is an exception case for session backward compatibility,
- * It will be removed when the session concept is completely left out. */
- media_from = pa_proplist_gets(GET_STREAM_PROPLIST(stream, type), PA_PROP_MEDIA_FROM);
- if (pa_safe_streq(media_from, "openAL")) {
- pa_log_info("stream(%p, index:%u) is from openAL, skip it.", stream, GET_STREAM_INDEX(stream, type));
- continue;
- }
-
- return true;
- }
- }
-
- /* Here we checks muse-server client pid also. It will be removed when the session concept is completely left out. */
- app_pid_str = pa_proplist_gets(GET_STREAM_PROPLIST(stream, type), "mused.client_pid");
- if (app_pid_str && !pa_atou(app_pid_str, &app_pid)) {
- if (app_pid == pid) {
- pa_log_info("found matching stream(%p, index:%u) of muse-server", stream, GET_STREAM_INDEX(stream, type));
- return true;
- }
- }
- }
-
- return false;
-}
-
-static ret_msg_t update_devices_and_trigger_routing(pa_stream_manager *m, stream_parent *sp, stream_type_t type) {
- void *stream = NULL;
- pa_idxset *idx_streams = NULL;
- uint32_t idx = 0;
- void *cur_highest_priority_stream = NULL;
- stream_route_type_t route_type = STREAM_ROUTE_TYPE_DEFAULT;
- ret_msg_t ret = RET_MSG_OK;
-
- pa_assert(m);
- pa_assert(sp);
-
- if (type == STREAM_SINK_INPUT) {
- idx_streams = sp->idx_sink_inputs;
- cur_highest_priority_stream = (void*)m->cur_highest_priority.sink_input;
- } else {
- idx_streams = sp->idx_source_outputs;
- cur_highest_priority_stream = (void*)m->cur_highest_priority.source_output;
- }
-
- /* update route type of this stream parent */
- if (sp->route_type == STREAM_ROUTE_TYPE_DEFAULT) {
- PA_IDXSET_FOREACH(stream, idx_streams, idx) {
- /* find route type of stream */
- if (get_route_type(stream, type, false, &route_type))
- return RET_MSG_ERROR_INTERNAL;
-
- if (route_type == STREAM_ROUTE_TYPE_MANUAL ||
- route_type == STREAM_ROUTE_TYPE_MANUAL_EXT) {
- sp->route_type = route_type;
- pa_log_info(" -- the route type is [%d]", route_type);
- } else {
- pa_log_error(" -- the route type is not valid[%d]", route_type);
- return RET_MSG_ERROR_POLICY;
- }
- }
- }
-
- /* if any stream that belongs to this id has been activated, do notify right away */
- if (sp->route_type == STREAM_ROUTE_TYPE_MANUAL_EXT) {
- PA_IDXSET_FOREACH(stream, idx_streams, idx) {
- pa_log_debug(" -- stream->index[%u] belongs to this stream parent[%p], do notify for the select proper source",
- GET_STREAM_INDEX(stream, type), sp);
- ret = do_notify(m, NOTIFY_COMMAND_SELECT_PROPER_SINK_OR_SOURCE_FOR_INIT, type, false, stream);
- }
- } else {
- /* trigger only when it occupies routing path */
- if (cur_highest_priority_stream && pa_idxset_get_by_data(idx_streams, cur_highest_priority_stream, NULL)) {
- pa_log_debug(" -- cur_highest_priority_stream->index[%u] belongs to this stream_parent[%p], do notify for the route change",
- GET_STREAM_INDEX(cur_highest_priority_stream, type), sp);
- ret = do_notify(m, NOTIFY_COMMAND_CHANGE_ROUTE_START, type, false, cur_highest_priority_stream);
- if (!ret && stream_is_call_family(PA_OBJECT(cur_highest_priority_stream)) && m->on_call) {
- pa_log_info("set active device for new call route device");
- change_active_route_for_call(PA_OBJECT(cur_highest_priority_stream), false, m);
- }
- }
- }
-
- return ret;
-}
-
-static bool check_all_requested_devices_connected(pa_stream_manager *m, uint32_t *device_list, uint32_t length) {
- pa_idxset *dm_device_list;
- uint32_t found_count = 0;
- uint32_t i = 0;
-
- pa_assert(m);
- pa_assert(device_list);
-
- dm_device_list = pa_device_manager_get_device_list(m->dm);
-
- for (i = 0; i < length; i++) {
- pa_tz_device *dm_device;
- uint32_t dm_device_id;
- uint32_t idx = 0;
-
- PA_IDXSET_FOREACH(dm_device, dm_device_list, idx) {
- dm_device_id = pa_tz_device_get_id(dm_device);
- if (device_list[i] == dm_device_id) {
- pa_log_debug("device[%u] is connected", dm_device_id);
- found_count++;
- if (length == found_count)
- return true;
- break;
- }
- }
- }
-
- return false;
-}
-
-static void handle_set_stream_route_devices(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- uint32_t id = 0;
- int i = 0;
- uint32_t *in_device_list = NULL;
- uint32_t *out_device_list = NULL;
- int list_len_in = 0;
- int list_len_out = 0;
- uint32_t idx = 0;
- uint32_t *device_id = NULL;
- stream_parent *sp = NULL;
- DBusMessage *reply = NULL;
- pa_stream_manager *m = (pa_stream_manager*)userdata;
- ret_msg_t ret = RET_MSG_OK;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(m);
-
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_UINT32, &id,
- DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &in_device_list, &list_len_in,
- DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &out_device_list, &list_len_out,
- DBUS_TYPE_INVALID));
- pa_log_info("handle_set_stream_route_devices(), id[%u], in_device_list[%p]:length[%d], out_device_list[%p]:length[%d]",
- id, in_device_list, list_len_in, out_device_list, list_len_out);
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
-
- sp = pa_hashmap_get(m->stream_parents, (const void*)id);
- if (!sp) {
- pa_log_error("could not find matching client for this parent_id[%u]", id);
- ret = RET_MSG_ERROR_INTERNAL;
- goto finish;
- }
- if (!in_device_list && !out_device_list) {
- pa_log_error("invalid arguments");
- ret = RET_MSG_ERROR_INVALID_ARGUMENT;
- goto finish;
- }
- if (!sp->idx_route_in_devices || !sp->idx_route_out_devices) {
- pa_log_error("failed to update, idx_route_in_devices[%p], idx_route_out_devices[%p]",
- sp->idx_route_in_devices, sp->idx_route_out_devices);
- ret = RET_MSG_ERROR_INTERNAL;
- goto finish;
- }
-
- /* check if all the requested devices are connected now */
- if (in_device_list && !check_all_requested_devices_connected(m, in_device_list, list_len_in)) {
- pa_log_error("could not find requested in-devices");
- ret = RET_MSG_ERROR_DEVICE_NOT_FOUND;
- goto finish;
- }
- if (out_device_list && !check_all_requested_devices_connected(m, out_device_list, list_len_out)) {
- pa_log_error("could not find requested out-devices");
- ret = RET_MSG_ERROR_DEVICE_NOT_FOUND;
- goto finish;
- }
-
- PA_IDXSET_FOREACH(device_id, sp->idx_route_in_devices, idx) {
- pa_idxset_remove_by_data(sp->idx_route_in_devices, device_id, NULL);
- pa_xfree(device_id);
- }
- if (in_device_list && list_len_in) {
- for (i = 0; i < list_len_in; i++) {
- pa_idxset_put(sp->idx_route_in_devices, pa_xmemdup(&in_device_list[i], sizeof(uint32_t)), NULL);
- pa_log_debug(" -- [in] device id:%u", in_device_list[i]);
- }
- }
- if ((ret = update_devices_and_trigger_routing(m, sp, STREAM_SOURCE_OUTPUT)))
- goto finish;
-
- PA_IDXSET_FOREACH(device_id, sp->idx_route_out_devices, idx) {
- pa_idxset_remove_by_data(sp->idx_route_out_devices, device_id, NULL);
- pa_xfree(device_id);
- }
- if (out_device_list && list_len_out) {
- for (i = 0; i < list_len_out; i++) {
- pa_idxset_put(sp->idx_route_out_devices, pa_xmemdup(&out_device_list[i], sizeof(uint32_t)), NULL);
- pa_log_debug(" -- [out] device id:%u", out_device_list[i]);
- }
- }
- if ((ret = update_devices_and_trigger_routing(m, sp, STREAM_SINK_INPUT)))
- goto finish;
-
-finish:
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[ret], DBUS_TYPE_INVALID));
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static void handle_set_stream_route_option(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- uint32_t id = 0;
- const char *name = NULL;
- int32_t value = 0;
- bool updated = false;
- stream_parent *sp = NULL;
- stream_route_option route_option;
- DBusMessage *reply = NULL;
- pa_stream_manager *m = (pa_stream_manager*)userdata;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(m);
-
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_UINT32, &id,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_INT32, &value,
- DBUS_TYPE_INVALID));
- pa_log_info("handle_set_stream_route_option(), name[%s], value[%d]", name, value);
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
-
- sp = pa_hashmap_get(m->stream_parents, (const void*)id);
- if (sp) {
- if (name) {
- route_option.name = name;
- route_option.value = value;
-
- /* if any stream that belongs to this id has been activated, do notify right away */
- if (m->cur_highest_priority.sink_input) {
- if (pa_idxset_get_by_data(sp->idx_sink_inputs, m->cur_highest_priority.sink_input, NULL)) {
- pa_log_debug(" -- cur_highest_priority.sink_input->index[%u] belongs to this parent id[%u], do notify for the options",
- (m->cur_highest_priority.sink_input)->index, id);
- do_notify(m, NOTIFY_COMMAND_UPDATE_ROUTE_OPTION, STREAM_SINK_INPUT, false, &route_option);
- updated = true;
- }
- }
- if (m->cur_highest_priority.source_output) {
- if (pa_idxset_get_by_data(sp->idx_source_outputs, m->cur_highest_priority.source_output, NULL)) {
- pa_log_debug(" -- cur_highest_priority.source_output->index[%u] belongs to this parent id[%u], do notify for the options",
- (m->cur_highest_priority.source_output)->index, id);
- do_notify(m, NOTIFY_COMMAND_UPDATE_ROUTE_OPTION, STREAM_SOURCE_OUTPUT, false, &route_option);
- updated = true;
- }
- }
- if (!updated) {
- pa_log_error("invalid state");
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_NO_STREAM], DBUS_TYPE_INVALID));
- } else
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_OK], DBUS_TYPE_INVALID));
- } else {
- pa_log_error("invalid arguments");
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INVALID_ARGUMENT], DBUS_TYPE_INVALID));
- }
-
- } else {
- pa_log_error("could not find matching client for this parent_id[%u]", id);
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
- }
-
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static void handle_set_volume_level(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- const char *direction = NULL;
- const char *type = NULL;
- uint32_t level = 0;
- stream_type_t stream_type = STREAM_SINK_INPUT;
- DBusMessage *reply = NULL;
- pa_stream_manager *m = (pa_stream_manager*)userdata;
- int ret = 0;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(m);
-
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_STRING, &direction,
- DBUS_TYPE_STRING, &type,
- DBUS_TYPE_UINT32, &level,
- DBUS_TYPE_INVALID));
- pa_log_info("handle_set_volume_level(), direction[%s], type[%s], level[%u]", direction, type, level);
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
-
- if (pa_streq(direction, "in"))
- stream_type = STREAM_SOURCE_OUTPUT;
- else if (pa_streq(direction, "out"))
- stream_type = STREAM_SINK_INPUT;
- else {
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
- ret = -1;
- goto finish;
- }
-
- if ((ret = set_volume_level_by_type(m, stream_type, type, level)))
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
- else
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_OK], DBUS_TYPE_INVALID));
-
-finish:
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-
- if (!ret)
- send_volume_changed_signal(conn, direction, type, level);
-}
-
-static void handle_get_volume_level(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- const char *direction = NULL;
- const char *type = NULL;
- uint32_t level = 0;
- stream_type_t stream_type = STREAM_SINK_INPUT;
- DBusMessage *reply = NULL;
- pa_stream_manager *m = (pa_stream_manager*)userdata;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(m);
-
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_STRING, &direction,
- DBUS_TYPE_STRING, &type,
- DBUS_TYPE_INVALID));
- pa_log_info("handle_get_volume_level(), direction(%s), type(%s)", direction, type);
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
-
- if (pa_streq(direction, "in"))
- stream_type = STREAM_SOURCE_OUTPUT;
- else if (pa_streq(direction, "out"))
- stream_type = STREAM_SINK_INPUT;
- else {
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_UINT32, 0, DBUS_TYPE_INVALID));
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
- goto finish;
- }
-
- if (get_volume_level_by_type(m, GET_VOLUME_CURRENT_LEVEL, stream_type, type, &level)) {
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_UINT32, 0, DBUS_TYPE_INVALID));
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
- } else {
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_UINT32, &level, DBUS_TYPE_INVALID));
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_OK], DBUS_TYPE_INVALID));
- }
-
-finish:
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static void handle_get_volume_max_level(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- const char *direction = NULL;
- const char *type = NULL;
- uint32_t level = 0;
- stream_type_t stream_type = STREAM_SINK_INPUT;
- DBusMessage *reply = NULL;
- pa_stream_manager *m = (pa_stream_manager*)userdata;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(m);
-
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_STRING, &direction,
- DBUS_TYPE_STRING, &type,
- DBUS_TYPE_INVALID));
- pa_log_info("handle_get_volume_max_level(), direction[%s], type[%s]", direction, type);
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
-
- if (pa_streq(direction, "in"))
- stream_type = STREAM_SOURCE_OUTPUT;
- else if (pa_streq(direction, "out"))
- stream_type = STREAM_SINK_INPUT;
- else {
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_UINT32, 0, DBUS_TYPE_INVALID));
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
- goto finish;
- }
-
- if (get_volume_level_by_type(m, GET_VOLUME_MAX_LEVEL, stream_type, type, &level)) {
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_UINT32, 0, DBUS_TYPE_INVALID));
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
- } else {
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_UINT32, &level, DBUS_TYPE_INVALID));
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_OK], DBUS_TYPE_INVALID));
- }
-finish:
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static void handle_set_volume_mute(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- const char *direction = NULL;
- const char *type = NULL;
- uint32_t do_mute = 0;
- stream_type_t stream_type = STREAM_SINK_INPUT;
- DBusMessage *reply = NULL;
- pa_stream_manager *m = (pa_stream_manager*)userdata;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(m);
-
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_STRING, &direction,
- DBUS_TYPE_STRING, &type,
- DBUS_TYPE_UINT32, &do_mute,
- DBUS_TYPE_INVALID));
- pa_log_info("handle_set_volume_mute(), direction[%s], type[%s], do_mute[%u]", direction, type, do_mute);
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
-
- if (pa_streq(direction, "in"))
- stream_type = STREAM_SOURCE_OUTPUT;
- else if (pa_streq(direction, "out"))
- stream_type = STREAM_SINK_INPUT;
- else {
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
- goto finish;
- }
-
- if (set_volume_mute_by_type(m, stream_type, type, (bool)do_mute))
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
- else
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_OK], DBUS_TYPE_INVALID));
-
-finish:
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static void handle_get_volume_mute(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- const char *direction = NULL;
- const char *type = NULL;
- uint32_t is_muted = 0;
- stream_type_t stream_type = STREAM_SINK_INPUT;
- DBusMessage *reply = NULL;
- pa_stream_manager *m = (pa_stream_manager*)userdata;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(m);
-
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_STRING, &direction,
- DBUS_TYPE_STRING, &type,
- DBUS_TYPE_INVALID));
- pa_log_info("handle_get_volume_mute(), direction[%s], type[%s]", direction, type);
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
-
- if (pa_streq(direction, "in"))
- stream_type = STREAM_SOURCE_OUTPUT;
- else if (pa_streq(direction, "out"))
- stream_type = STREAM_SINK_INPUT;
- else {
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_UINT32, 0, DBUS_TYPE_INVALID));
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
- goto fail;
- }
-
- if (get_volume_mute_by_type(m, stream_type, type, (bool*)&is_muted)) {
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_UINT32, 0, DBUS_TYPE_INVALID));
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
- } else {
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_UINT32, &is_muted, DBUS_TYPE_INVALID));
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_OK], DBUS_TYPE_INVALID));
- }
-
-fail:
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static void handle_get_current_volume_type(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- const char *direction = NULL;
- const char *type = NULL;
- void *s = NULL;
- stream_type_t stream_type = STREAM_SINK_INPUT;
- DBusMessage *reply = NULL;
- pa_stream_manager *m = (pa_stream_manager*)userdata;
- uint32_t idx = 0;
- pa_idxset *streams = NULL;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(m);
-
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_STRING, &direction,
- DBUS_TYPE_INVALID));
- pa_log_info("handle_get_current_volume_type(), direction[%s]", direction);
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
-
- if (pa_streq(direction, "in")) {
- stream_type = STREAM_SOURCE_OUTPUT;
- streams = m->core->source_outputs;
- } else if (pa_streq(direction, "out")) {
- stream_type = STREAM_SINK_INPUT;
- streams = m->core->sink_inputs;
- } else {
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &dbus_str_none, DBUS_TYPE_INVALID));
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
- goto fail;
- }
-
- /* Get a volume type of a stream that has the max priority role among all the running streams regardless of devices.
- Note that it does not represent any focus status of a stream rather only checking the priority of it */
- if (pa_idxset_size(streams)) {
- int cur_max_priority = 0;
- const char *cur_max_type = NULL;
- const char *role = NULL;
- stream_info *s_info;
-
- PA_IDXSET_FOREACH(s, streams, idx) {
- if (!CHECK_STREAM_RUNNING(s, stream_type))
- continue;
- if (!(type = pa_proplist_gets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_TIZEN_VOLUME_TYPE)))
- continue;
- if (!(role = pa_proplist_gets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_ROLE)))
- continue;
- if ((s_info = pa_hashmap_get(m->stream_infos, role))) {
- if (s_info->priority >= cur_max_priority) {
- cur_max_priority = s_info->priority;
- cur_max_type = type;
- pa_log_info("updated, volume type of the max priority stream(%u): %s", GET_STREAM_INDEX(s, stream_type), cur_max_type);
- }
- }
- }
- type = cur_max_type;
- }
-
- if (type) {
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &type, DBUS_TYPE_INVALID));
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_OK], DBUS_TYPE_INVALID));
- } else {
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &dbus_str_none, DBUS_TYPE_INVALID));
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_NO_STREAM], DBUS_TYPE_INVALID));
- }
-
-fail:
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static void handle_get_current_media_routing_path(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- const char *direction = NULL;
- const char *device_type = NULL;
- dm_device_direction_t dm_device_direction = DM_DEVICE_DIRECTION_NONE;
- stream_info *s = NULL;
- DBusMessage *reply = NULL;
- pa_tz_device *device = NULL;
- pa_stream_manager *m = (pa_stream_manager*)userdata;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(m);
-
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_STRING, &direction,
- DBUS_TYPE_INVALID));
- pa_log_info("handle_get_current_media_routing_path(), direction[%s]", direction);
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
-
- if (pa_streq(direction, "in")) {
- dm_device_direction = DM_DEVICE_DIRECTION_IN;
- } else if (pa_streq(direction, "out")) {
- dm_device_direction = DM_DEVICE_DIRECTION_OUT;
- } else {
- pa_log_error("invalid direction[%s]", direction);
- goto fail;
- }
-
- if ((s = pa_hashmap_get(m->stream_infos, STREAM_ROLE_MEDIA)) == NULL) {
- pa_log_error("could not find media role");
- goto fail;
- }
-
- if (s->route_type == STREAM_ROUTE_TYPE_AUTO) {
- device = get_media_auto_device(dm_device_direction, m);
- } else if (s->route_type == STREAM_ROUTE_TYPE_AUTO_LAST_CONNECTED) {
- device = get_media_last_device(dm_device_direction, m);
- } else {
- pa_log_error("unexpected routing type for media[%d]", s->route_type);
- goto fail;
- }
-
- if (device) {
- device_type = pa_tz_device_get_type(device);
- goto success;
- } else {
- pa_log_error("could not found matched device");
- }
-
-fail:
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &dbus_str_none, DBUS_TYPE_INVALID));
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
- return;
-success:
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &device_type, DBUS_TYPE_INVALID));
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_OK], DBUS_TYPE_INVALID));
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static void handle_update_focus_status(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- uint32_t id = 0;
- uint32_t idx = 0;
- uint32_t count = 0;
- uint32_t acquired_focus_status = 0;
- stream_parent *sp = NULL;
- void *stream = NULL;
- DBusMessage *reply = NULL;
- pa_stream_manager *m = (pa_stream_manager*)userdata;
- int prev_status = STREAM_FOCUS_ACQUIRED_NONE;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(m);
-
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_UINT32, &id,
- DBUS_TYPE_UINT32, &acquired_focus_status,
- DBUS_TYPE_INVALID));
- pa_log_info("handle_update_focus_status(), id[%u], acquired_focus_status[0x%x]", id, acquired_focus_status);
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
-
- if ((sp = pa_hashmap_get(m->stream_parents, (const void*)id))) {
- if (sp->focus_status != acquired_focus_status) {
- /* need to update */
- prev_status = sp->focus_status;
- sp->focus_status = acquired_focus_status;
- if (((prev_status ^ sp->focus_status) & STREAM_FOCUS_ACQUIRED_PLAYBACK) && sp->idx_sink_inputs) {
- count = pa_idxset_size(sp->idx_sink_inputs);
- PA_IDXSET_FOREACH(stream, sp->idx_sink_inputs, idx) {
- pa_proplist_sets(GET_STREAM_PROPLIST(stream, STREAM_SINK_INPUT), PA_PROP_MEDIA_FOCUS_STATUS,
- GET_FOCUS_STATUS(sp->focus_status, STREAM_SINK_INPUT) ? STREAM_FOCUS_STATE_ACQUIRED : STREAM_FOCUS_STATE_RELEASED);
- if (--count == 0)
- process_stream(m, stream, STREAM_SINK_INPUT, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_FOCUS_CHANGED, false);
- }
- }
- if (((prev_status ^ sp->focus_status) & STREAM_FOCUS_ACQUIRED_CAPTURE) && sp->idx_source_outputs) {
- count = pa_idxset_size(sp->idx_source_outputs);
- PA_IDXSET_FOREACH(stream, sp->idx_source_outputs, idx) {
- pa_proplist_sets(GET_STREAM_PROPLIST(stream, STREAM_SOURCE_OUTPUT), PA_PROP_MEDIA_FOCUS_STATUS,
- GET_FOCUS_STATUS(sp->focus_status, STREAM_SOURCE_OUTPUT) ? STREAM_FOCUS_STATE_ACQUIRED : STREAM_FOCUS_STATE_RELEASED);
- if (--count == 0)
- process_stream(m, stream, STREAM_SOURCE_OUTPUT, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_FOCUS_CHANGED, false);
- }
- }
- } else
- pa_log_debug("same as before, skip updating focus status[0x%x]", acquired_focus_status);
-
- } else {
- pa_log_error("could not find matching client for this parent_id[%u]", id);
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
- goto fail;
- }
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_OK], DBUS_TYPE_INVALID));
-fail:
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static void handle_update_focus_status_by_focus_id(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- int32_t id = 0;
- uint32_t idx = 0;
- uint32_t acquired_focus_status = 0;
- int32_t focus_id = 0;
- const char *focus_id_str;
- pa_sink_input *i = NULL;
- DBusMessage *reply = NULL;
- pa_stream_manager *m = (pa_stream_manager*)userdata;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(m);
-
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_INT32, &id,
- DBUS_TYPE_UINT32, &acquired_focus_status,
- DBUS_TYPE_INVALID));
- pa_log_info("handle_update_focus_status_by_focus_id(), id[%d], acquired_focus_status[0x%x]", id, acquired_focus_status);
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
-
- /* Currently, we only support sink-inputs */
- PA_IDXSET_FOREACH(i, m->core->sink_inputs, idx) {
- if ((focus_id_str = pa_proplist_gets(GET_STREAM_PROPLIST(i, STREAM_SINK_INPUT), PA_PROP_MEDIA_FOCUS_ID))) {
- if (pa_atoi(focus_id_str, &focus_id))
- continue;
- if (id == focus_id) {
- pa_log_info("found matching sink-input(%p, %u) - focus_id(%d)", i, i->index, id);
- pa_proplist_sets(GET_STREAM_PROPLIST(i, STREAM_SINK_INPUT), PA_PROP_MEDIA_FOCUS_STATUS,
- acquired_focus_status ? STREAM_FOCUS_STATE_ACQUIRED : STREAM_FOCUS_STATE_RELEASED);
- process_stream(m, i, STREAM_SINK_INPUT, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_FOCUS_CHANGED, false);
-
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_OK], DBUS_TYPE_INVALID));
- goto success;
- }
- }
- }
- pa_log_error("could not find matching stream for this focus_id[%i]", id);
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
-success:
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static void handle_update_restriction(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- const char *name;
- uint32_t value = 0;
- DBusMessage *reply = NULL;
- pa_stream_manager *m = (pa_stream_manager*)userdata;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(m);
-
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_UINT32, &value,
- DBUS_TYPE_INVALID));
- pa_log_info("handle_update_restriction(), name[%s], value[%u]", name, value);
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
-
- if (handle_restrictions(m, name, value) < 0) {
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL], DBUS_TYPE_INVALID));
- goto fail;
- }
-
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_OK], DBUS_TYPE_INVALID));
-fail:
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static void handle_set_filter(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- const char *filter_name, *filter_parameters, *filter_group, *stream_type;
- DBusMessage *reply = NULL;
- pa_stream_manager *m = (pa_stream_manager*)userdata;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(m);
-
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_STRING, &filter_name,
- DBUS_TYPE_STRING, &filter_parameters,
- DBUS_TYPE_STRING, &filter_group,
- DBUS_TYPE_STRING, &stream_type,
- DBUS_TYPE_INVALID));
- pa_log_info("handle_set_filter(), filter_name[%s], filter_parameters[%s], filter_group[%s], stream_type[%s]", filter_name,
- filter_parameters, filter_group, stream_type);
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
-
- /* Set filter sink according to stream type */
- if (update_filter(m, filter_name, filter_parameters, filter_group, stream_type) < 0) {
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL],
- DBUS_TYPE_INVALID));
- goto fail;
- }
-
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_OK],
- DBUS_TYPE_INVALID));
-
-fail:
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static void handle_unset_filter(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- const char *stream_type;
- DBusMessage *reply = NULL;
- pa_stream_manager *m = (pa_stream_manager*)userdata;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(m);
-
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_STRING, &stream_type,
- DBUS_TYPE_INVALID));
- pa_log_info("handle_unset_filter(), stream_type[%s]", stream_type);
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
-
- /* Unset filter sink according to stream type */
- if (update_filter(m, NULL, NULL, NULL, stream_type) < 0) {
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL],
- DBUS_TYPE_INVALID));
- goto fail;
- }
-
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_OK],
- DBUS_TYPE_INVALID));
-
-fail:
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static void handle_control_filter(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- const char *filter_name, *filter_controls, *stream_type;
- DBusMessage *reply = NULL;
- pa_stream_manager *m = (pa_stream_manager*)userdata;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(m);
-
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_STRING, &filter_name,
- DBUS_TYPE_STRING, &filter_controls,
- DBUS_TYPE_STRING, &stream_type,
- DBUS_TYPE_INVALID));
- pa_log_info("handle_control_filter(), filter_name[%s], filter_controls[%s], stream_type[%s]", filter_name, filter_controls,
- stream_type);
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
-
- /* Control parameters to filter sink */
- if (control_filter(m, filter_name, filter_controls, stream_type, conn) < 0) {
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INTERNAL],
- DBUS_TYPE_INVALID));
- goto fail;
- }
-
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_OK],
- DBUS_TYPE_INVALID));
-fail:
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static void handle_check_stream_exist_by_pid(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- uint32_t pid = 0;
- const char *type;
- const char *direction;
- stream_type_t stream_type = STREAM_SINK_INPUT;
- DBusMessage *reply = NULL;
- pa_stream_manager *m = (pa_stream_manager*)userdata;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(m);
-
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_UINT32, &pid,
- DBUS_TYPE_STRING, &type,
- DBUS_TYPE_STRING, &direction,
- DBUS_TYPE_INVALID));
- pa_log_info("handle_check_stream_exist_by_pid(), pid[%u], type[%s], direction[%s]", pid, type, direction);
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
-
- if (pa_streq(direction, "in"))
- stream_type = STREAM_SOURCE_OUTPUT;
- else if (pa_streq(direction, "out"))
- stream_type = STREAM_SINK_INPUT;
- else {
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INVALID_ARGUMENT],
- DBUS_TYPE_INVALID));
- goto fail;
- }
-
- if (!check_stream_exist_by_pid(m, pid, type, stream_type)) {
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_NO_STREAM],
- DBUS_TYPE_INVALID));
- goto fail;
- }
-
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_OK],
- DBUS_TYPE_INVALID));
-fail:
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static DBusHandlerResult handle_methods(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- int idx = 0;
- pa_stream_manager *m = (pa_stream_manager*)userdata;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(m);
-
- for (idx = 0; idx < METHOD_HANDLER_MAX; idx++) {
- if (dbus_message_is_method_call(msg, STREAM_MANAGER_INTERFACE, method_handlers[idx].method_name)) {
- pa_log_debug("Message signature [%s] (Expected [%s])", dbus_message_get_signature(msg), signature_args_for_in[idx]);
- if (pa_streq(dbus_message_get_signature(msg), signature_args_for_in[idx])) {
- method_handlers[idx].receive_cb(conn, msg, userdata);
- return DBUS_HANDLER_RESULT_HANDLED;
- } else {
- pa_log_warn("Wrong Argument Signature");
- pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_SIGNATURE, "Wrong Signature, Expected %s", signature_args_for_in[idx]);
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- }
- }
- }
-
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
-
-static DBusHandlerResult method_handler_for_vt(DBusConnection *c, DBusMessage *m, void *userdata) {
- pa_stream_manager *u = (pa_stream_manager*)userdata;
- const char *path, *interface, *member;
-
- pa_assert(c);
- pa_assert(m);
- pa_assert(u);
-
- path = dbus_message_get_path(m);
- interface = dbus_message_get_interface(m);
- member = dbus_message_get_member(m);
-
- pa_log_debug("dbus: path=%s, interface=%s, member=%s", path, interface, member);
-
- if (!pa_streq(path, STREAM_MANAGER_OBJECT_PATH))
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
- if (dbus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
- return handle_introspect(c, m, u);
- } else {
- return handle_methods(c, m, u);
- }
-
- return DBUS_HANDLER_RESULT_HANDLED;
-}
-
-static void send_volume_changed_signal(DBusConnection *conn, const char *direction, const char *volume_type, const uint32_t volume_level) {
- DBusMessage *signal_msg;
- DBusMessageIter msg_iter;
-
- pa_assert(conn);
- pa_assert(direction);
- pa_assert(volume_type);
-
- pa_log_debug("Send volume changed signal: direction(%s), type(%s), level(%d)", direction, volume_type, volume_level);
-
- pa_assert_se(signal_msg = dbus_message_new_signal(STREAM_MANAGER_OBJECT_PATH, STREAM_MANAGER_INTERFACE, STREAM_MANAGER_SIGNAL_NAME_VOLUME_CHANGED));
- dbus_message_iter_init_append(signal_msg, &msg_iter);
-
- dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &direction);
- dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &volume_type);
- dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_UINT32, &volume_level);
-
- pa_assert_se(dbus_connection_send(conn, signal_msg, NULL));
- dbus_message_unref(signal_msg);
- return;
-}
-
-static void send_command_signal(DBusConnection *conn, const char *name, int value) {
- DBusMessage *signal_msg;
- DBusMessageIter msg_iter;
-
- pa_assert(conn);
- pa_assert(name);
-
- pa_log_debug("Send command signal: name(%s), value(%d)", name, value);
-
- pa_assert_se(signal_msg = dbus_message_new_signal(STREAM_MANAGER_OBJECT_PATH, STREAM_MANAGER_INTERFACE, STREAM_MANAGER_SIGNAL_NAME_COMMAND));
- dbus_message_iter_init_append(signal_msg, &msg_iter);
-
- dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &name);
- dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_INT32, &value);
-
- pa_assert_se(dbus_connection_send(conn, signal_msg, NULL));
- dbus_message_unref(signal_msg);
-}
-#endif
-
static void dump_stream_map(pa_stream_manager *m) {
stream_info *s = NULL;
const char *role = NULL;
}
}
-static ret_msg_t do_notify(pa_stream_manager *m, notify_command_type_t command, stream_type_t type, bool is_new_data, void *user_data) {
+ret_msg_t do_notify(pa_stream_manager *m, notify_command_type_t command, stream_type_t type, bool is_new_data, void *user_data) {
pa_stream_manager_hook_data_for_select hook_call_select_data;
pa_stream_manager_hook_data_for_route hook_call_route_data;
hal_stream_connection_info stream_conn_info;
}
}
-static process_stream_result_t process_stream(pa_stream_manager *m, void *stream, stream_type_t type, process_command_type_t command, bool is_new_data) {
+process_stream_result_t process_stream(pa_stream_manager *m, void *stream, stream_type_t type, process_command_type_t command, bool is_new_data) {
process_stream_result_t result = PROCESS_STREAM_RESULT_OK;
const char *role = NULL;
const char *route_type_str = NULL;
process_stream(m, i, STREAM_SINK_INPUT, PROCESS_COMMAND_ADD_PARENT_ID, false);
process_stream(m, i, STREAM_SINK_INPUT, PROCESS_COMMAND_APPLY_FILTER, false);
if (stream_is_call_family(PA_OBJECT(i))) {
- change_active_route_for_call(PA_OBJECT(i), true, m);
+ change_active_route_for_call(m, PA_OBJECT(i), true);
m->on_call = true;
}
update_mirroring_streams(m, o, true);
process_stream(m, o, STREAM_SOURCE_OUTPUT, PROCESS_COMMAND_ADD_PARENT_ID, false);
if (stream_is_call_family(PA_OBJECT(o))) {
- change_active_route_for_call(PA_OBJECT(o), true, m);
+ change_active_route_for_call(m, PA_OBJECT(o), true);
m->on_call = true;
}
}
static int32_t init_ipc(pa_stream_manager *m) {
- DBusError err;
- pa_dbus_connection *conn = NULL;
- static const DBusObjectPathVTable vtable = {
- .message_function = method_handler_for_vt,
- };
-
pa_assert(m);
pa_log_info("Initialization for IPC");
#ifdef HAVE_DBUS
-#ifdef USE_DBUS_PROTOCOL
- m->dbus_protocol = pa_dbus_protocol_get(m->core);
- pa_assert_se(pa_dbus_protocol_add_interface(m->dbus_protocol, STREAM_MANAGER_OBJECT_PATH, &stream_manager_interface_info, m) >= 0);
- pa_assert_se(pa_dbus_protocol_register_extension(m->dbus_protocol, STREAM_MANAGER_INTERFACE) >= 0);
-#else
-
- dbus_error_init(&err);
-
- if (!(conn = pa_dbus_bus_get(m->core, DBUS_BUS_SYSTEM, &err)) || dbus_error_is_set(&err)) {
- if (conn) {
- pa_dbus_connection_unref(conn);
- }
- pa_log_error("Unable to contact D-Bus system bus: %s: %s", err.name, err.message);
- goto fail;
- } else {
- pa_log_notice("Got dbus connection");
- }
- m->dbus_conn = conn;
- pa_assert_se(dbus_connection_register_object_path(pa_dbus_connection_get(conn), STREAM_MANAGER_OBJECT_PATH, &vtable, m));
-#endif
+ if ((init_dbus(m)))
+ return -1;
#else
pa_log_error("DBUS is not supported\n");
- goto fail;
+ return -1
#endif
-
return 0;
-fail:
- pa_log_error("failed to initialize stream manager ipc");
- return -1;
}
static void deinit_ipc(pa_stream_manager *m) {
pa_assert(m);
#ifdef HAVE_DBUS
-#ifdef USE_DBUS_PROTOCOL
- if (m->dbus_protocol) {
- pa_assert_se(pa_dbus_protocol_unregister_extension(m->dbus_protocol, STREAM_MANAGER_INTERFACE) >= 0);
- pa_assert_se(pa_dbus_protocol_remove_interface(m->dbus_protocol, STREAM_MANAGER_OBJECT_PATH, stream_manager_interface_info.name) >= 0);
- pa_dbus_protocol_unref(m->dbus_protocol);
- m->dbus_protocol = NULL;
- }
-#else
- if (m->dbus_conn) {
- if (!dbus_connection_unregister_object_path(pa_dbus_connection_get(m->dbus_conn), STREAM_MANAGER_OBJECT_PATH))
- pa_log_error("failed to unregister object path");
- m->dbus_conn = NULL;
- }
-#endif
+ deinit_dbus(m);
#endif
}