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 handle_get_pid_of_latest_stream(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" },
{ "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", "s", "ssss", "s", "sss", "uss"};
+static pa_dbus_arg_info get_pid_of_latest_stream_args[] = { { "io_direction", "s", "in" },
+ { "stream_types", "as", "in" },
+ { "pid", "u", "out" },
+ { "ret_msg", "s", "out" } };
+static const char* signature_args_for_in[] = { "s", "", "uauau", "usi", "ssu", "ss", "ss", "ssu", "ss", "s", "s", "uu", "iu", "su", "s", "ssss", "s", "sss", "uss","sas"};
static pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = {
[METHOD_HANDLER_GET_STREAM_INFO] = {
.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 },
+ [METHOD_HANDLER_GET_PID_OF_LATEST_STREAM] = {
+ .method_name = STREAM_MANAGER_METHOD_NAME_GET_PID_OF_LATEST_STREAM,
+ .arguments = get_pid_of_latest_stream_args,
+ .n_arguments = sizeof(get_pid_of_latest_stream_args) / sizeof(pa_dbus_arg_info),
+ .receive_cb = handle_get_pid_of_latest_stream },
};
static DBusHandlerResult handle_introspect(DBusConnection *conn, DBusMessage *msg, void *userdata) {
dbus_message_unref(reply);
}
+static bool find_the_lastest_stream(pa_stream_manager *m, stream_type_t type, const char ** stream_roles, int length, uint32_t *pid) {
+ void *stream = NULL;
+ uint32_t idx = 0;
+ const char *role;
+ const char *app_pid_str = NULL;
+ uint32_t latest_pid = 0;
+ pa_usec_t latest_time = 0;
+ uint32_t tmp_pid = 0;
+ pa_usec_t tmp_time = 0;
+ int i;
+
+ pa_assert(m);
+ pa_assert(stream_roles);
+ pa_assert(pid);
+
+ PA_IDXSET_FOREACH(stream, (type == STREAM_SINK_INPUT) ? m->core->sink_inputs : m->core->source_outputs, idx) {
+ if (!CHECK_STREAM_RUNNING(stream, type)) {
+ pa_log_debug("stream(%p, index:%u) is not in running state, skip it.", stream, GET_STREAM_INDEX(stream, type));
+ continue;
+ }
+
+ for (i = 0; i <length; i++) {
+ tmp_pid = 0;
+ tmp_time = 0;
+
+ role = pa_proplist_gets(GET_STREAM_PROPLIST(stream, type), PA_PROP_MEDIA_ROLE);
+ if (!pa_safe_streq(stream_roles[i], role))
+ continue;
+
+ app_pid_str = pa_proplist_gets(GET_STREAM_PROPLIST(stream, type), PA_PROP_APPLICATION_PROCESS_ID_ORIGIN);
+ if (app_pid_str && !pa_atou(app_pid_str, &tmp_pid)) {
+ pa_log_debug("found a stream(pid.origin:%u, index:%u) that matches requested stream role[%s]", tmp_pid, GET_STREAM_INDEX(stream, type), stream_roles[i]);
+ } else {
+ 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, &tmp_pid))
+ pa_log_debug("found a stream(pid:%u, index:%u) that matches requested stream role[%s]", tmp_pid, GET_STREAM_INDEX(stream, type), stream_roles[i]);
+ }
+ if (tmp_pid) {
+ tmp_time = GET_STREAM_LAST_RUN_TIME(stream, type);
+ if (latest_time <= tmp_time) {
+ latest_time = tmp_time;
+ latest_pid = tmp_pid;
+ }
+ }
+ }
+ }
+
+ if (latest_pid > 0) {
+ *pid = latest_pid;
+ pa_log_info("found the stream(pid:%u)", *pid);
+ return true;
+ }
+
+ pa_log_info("no match is found");
+ return false;
+}
+
+static void handle_get_pid_of_latest_stream(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ const char *direction;
+ const char **types;
+ int length;
+ stream_type_t stream_type = STREAM_SINK_INPUT;
+ uint32_t pid = 0;
+ ret_msg_t ret_msg = RET_MSG_OK;
+
+ 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_ARRAY, DBUS_TYPE_STRING, &types, &length,
+ DBUS_TYPE_INVALID));
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+
+ if (pa_safe_streq(direction, "in"))
+ stream_type = STREAM_SOURCE_OUTPUT;
+ else if (pa_safe_streq(direction, "out"))
+ stream_type = STREAM_SINK_INPUT;
+ else {
+ pa_log_error("invalid direction[%s]", direction);
+ goto invalid_argument;
+ }
+
+ if (length <= 0) {
+ pa_log_error("At least one stream type should be contained");
+ goto invalid_argument;
+ }
+
+ if (!find_the_lastest_stream(m, stream_type, types, length, &pid))
+ ret_msg = RET_MSG_ERROR_NO_STREAM;
+
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_UINT32, &pid, DBUS_TYPE_INVALID));
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[ret_msg],
+ DBUS_TYPE_INVALID));
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+ return;
+
+invalid_argument:
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_UINT32, &pid, DBUS_TYPE_INVALID));
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_ERROR_INVALID_ARGUMENT],
+ DBUS_TYPE_INVALID));
+ 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;