stream-manager-dbus: Add new DBus medhod to get the pid of the lastest stream 39/203039/1
authorSangchul Lee <sc11.lee@samsung.com>
Mon, 8 Apr 2019 07:05:13 +0000 (16:05 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Tue, 9 Apr 2019 07:16:31 +0000 (16:16 +0900)
  server          : org.pulseaudio.Server
  object path     : /org/pulseaudio/StreamManager
  interface       : org.pulseaudio.StreamManager
  method name     : GetPidOfLatestStream
  method argument : string for direction ('in' or 'out')
                    string array for stream types (e.g. 'media','alarm','notification')
  return value    : unsigned int for PID
                    string for return message
                    - success          : "STREAM_MANAGER_RETURN_OK"
                    - no match found   : "STREAM_MANAGER_RETURN_ERROR_NO_STREAM"
                    - invalid argument : "STREAM_MANAGER_RETURN_ERROR_INVALID_ARGUMENT"

[Version] 11.1.39
[Issue type] New feature

Change-Id: Idaa2f56ed5d27d001f5e4ce566b1b361d6248388
Signed-off-by: Sangchul Lee <sc11.lee@samsung.com>
packaging/pulseaudio-modules-tizen.spec
src/stream-manager-dbus-priv.h
src/stream-manager-dbus.c
src/stream-manager-priv.h

index 2c5a0ce..c44a3b8 100644 (file)
@@ -1,6 +1,6 @@
 Name:             pulseaudio-modules-tizen
 Summary:          Pulseaudio modules for Tizen
-Version:          11.1.38
+Version:          11.1.39
 Release:          0
 Group:            Multimedia/Audio
 License:          LGPL-2.1+
index 019cf9c..d464a36 100644 (file)
@@ -45,6 +45,7 @@
 #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"
+#define STREAM_MANAGER_METHOD_NAME_GET_PID_OF_LATEST_STREAM          "GetPidOfLatestStream"
 /* signal */
 #define STREAM_MANAGER_SIGNAL_NAME_VOLUME_CHANGED                    "VolumeChanged"
 #define STREAM_MANAGER_SIGNAL_NAME_COMMAND                           "Command"
@@ -69,6 +70,7 @@ enum method_handler_index {
     METHOD_HANDLER_UNSET_FILTER,
     METHOD_HANDLER_CONTROL_FILTER,
     METHOD_HANDLER_CHECK_STREAM_EXIST_BY_PID,
+    METHOD_HANDLER_GET_PID_OF_LATEST_STREAM,
     METHOD_HANDLER_MAX
 };
 
index 7afa05b..ea8eece 100644 (file)
@@ -60,6 +60,7 @@ static void handle_set_filter(DBusConnection *conn, DBusMessage *msg, void *user
 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" },
@@ -131,7 +132,11 @@ 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", "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] = {
@@ -229,6 +234,11 @@ static pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = {
         .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) {
@@ -1309,6 +1319,117 @@ fail:
     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;
index 6722e8e..c9254ad 100644 (file)
@@ -96,6 +96,9 @@ typedef enum _notify_command_type {
 #define GET_STREAM_INDEX(stream, type) \
       (type == STREAM_SINK_INPUT ? ((pa_sink_input*)stream)->index : ((pa_source_output*)stream)->index)
 
+#define GET_STREAM_LAST_RUN_TIME(stream, type) \
+      (type == STREAM_SINK_INPUT ? ((pa_sink_input*)stream)->time_of_start_to_run : ((pa_source_output*)stream)->time_of_start_to_run)
+
 #define GET_FOCUS_STATUS(focus, type) \
       (type == STREAM_SINK_INPUT ? (focus & STREAM_FOCUS_ACQUIRED_PLAYBACK) : (focus & STREAM_FOCUS_ACQUIRED_CAPTURE))