#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_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_CHECK_STREAM_EXIST_BY_PID "CheckStreamExistByPid"
/* signal */
#define STREAM_MANAGER_SIGNAL_NAME_VOLUME_CHANGED "VolumeChanged"
#define STREAM_MANAGER_SIGNAL_NAME_COMMAND "Command"
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_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);
METHOD_HANDLER_UPDATE_FOCUS_STATUS,
METHOD_HANDLER_UPDATE_FOCUS_STATUS_BY_FOCUS_ID,
METHOD_HANDLER_UPDATE_RESTRICTION,
+ METHOD_HANDLER_CHECK_STREAM_EXIST_BY_PID,
METHOD_HANDLER_MAX
};
static pa_dbus_arg_info update_restriction_args[] = { { "name", "s", "in" },
{ "value", "u", "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"};
+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", "uss"};
static pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = {
[METHOD_HANDLER_GET_STREAM_INFO] = {
.arguments = update_restriction_args,
.n_arguments = sizeof(update_restriction_args) / sizeof(pa_dbus_arg_info),
.receive_cb = handle_update_restriction },
+ [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";
" <arg name=\"value\" direction=\"in\" type=\"u\"/>" \
" <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\"/>" \
set_media_active_device(m);
}
+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) {
+ pa_log_info("found matching stream(%p, index:%u)", stream, GET_STREAM_INDEX(stream, type));
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
static void update_devices_and_trigger_routing(pa_stream_manager *m, stream_parent *sp, stream_type_t type) {
void *stream = NULL;
pa_idxset *idx_streams = 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_INDEX_ERROR],
+ 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_INDEX_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_INDEX_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;