stream-manager-dbus: Add direction argument to the DBus method - set preferred device 41/210241/2 accepted/tizen/unified/20190717.220448 submit/tizen/20190717.085922
authorSangchul Lee <sc11.lee@samsung.com>
Wed, 17 Jul 2019 06:38:46 +0000 (15:38 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Wed, 17 Jul 2019 06:45:03 +0000 (15:45 +0900)
  server          : org.pulseaudio.Server
  object path     : /org/pulseaudio/StreamManager
  interface       : org.pulseaudio.StreamManager

  method name     : SetStreamPreferredDevice
  method argument : unsigned int for stream index
                    string for io direction ('in' or 'out')
                    unsigned int for device id
  return value    : string for return message
                    - success          : "STREAM_MANAGER_RETURN_OK"
                    - no match found   : "STREAM_MANAGER_RETURN_ERROR_DEVICE_NOT_FOUND"
                    - policy error     : "STREAM_MANAGER_RETURN_ERROR_POLICY"
                    - internal error   : "STREAM_MANAGER_RETURN_ERROR_INTERNAL"

[Version] 11.1.59
[Issue type] Improvement

Change-Id: I1a3b6b1e27438f4e5aace0f430d2afbc9b3d0bf7
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
src/stream-manager.c
src/stream-manager.h

index 5b9b038..3d5462c 100644 (file)
@@ -1,6 +1,6 @@
 Name:             pulseaudio-modules-tizen
 Summary:          Pulseaudio modules for Tizen
-Version:          11.1.58
+Version:          11.1.59
 Release:          0
 Group:            Multimedia/Audio
 License:          LGPL-2.1+
index 81df35e..651f95a 100644 (file)
@@ -131,6 +131,7 @@ pa_dbus_interface_info stream_manager_interface_info = {
     "  </method>"                                                            \
     "  <method name=\"STREAM_MANAGER_METHOD_NAME_SET_STREAM_PREFERRED_DEVICE\">" \
     "   <arg name=\"parent_id\" direction=\"in\" type=\"u\"/>"               \
+    "   <arg name=\"io_direction\" direction=\"in\" type=\"s\"/>"            \
     "   <arg name=\"device_id\" direction=\"in\" type=\"u\"/>"               \
     "   <arg name=\"ret_msg\" direction=\"out\" type=\"s\"/>"                \
     "  </method>"                                                            \
index 4d0ab37..9491a90 100644 (file)
@@ -86,6 +86,7 @@ static pa_dbus_arg_info set_stream_route_option_args[]  = { { "parent_id", "u",
                                                                 { "value", "i", "in" },
                                                            { "ret_msg", "s", "out" } };
 static pa_dbus_arg_info set_stream_preferred_device_args[]  = { { "parent_id", "u", "in" },
+                                                             { "io_direction", "s", "in" },
                                                                 { "device_id", "u", "in" },
                                                                { "ret_msg", "s", "out" } };
 static pa_dbus_arg_info set_volume_level_args[]  = { { "io_direction", "s", "in" },
@@ -168,7 +169,7 @@ static const char* signature_args_for_in[] = {
     "",         /* METHOD_HANDLER_GET_STREAM_LIST */
     "uauau",    /* METHOD_HANDLER_SET_STREAM_ROUTE_DEVICES */
     "usi",      /* METHOD_HANDLER_SET_STREAM_ROUTE_OPTION */
-    "uu",       /* METHOD_HANDLER_SET_STREAM_PREFERRED_DEVICE */
+    "usu",      /* METHOD_HANDLER_SET_STREAM_PREFERRED_DEVICE */
     "ssu",      /* METHOD_HANDLER_SET_VOLUME_LEVEL */
     "ss",       /* METHOD_HANDLER_GET_VOLUME_LEVEL */
     "ss",       /* METHOD_HANDLER_GET_VOLUME_MAX_LEVEL */
@@ -635,17 +636,26 @@ static void handle_set_stream_route_option(DBusConnection *conn, DBusMessage *ms
 }
 
 static void handle_set_stream_preferred_device(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+    const char *device_direction = NULL;
     uint32_t sp_id = 0;
     uint32_t device_id = 0;
     uint32_t idx;
     uint32_t count = 0;
+    stream_direction_t direction;
     pa_tz_device *device;
+    pa_tz_device *prev_device;
     const char *device_role;
     const char *prev_device_type;
     const char *prev_device_role;
     stream_parent *sp = NULL;
     void *stream;
-    ret_msg_t ret = RET_MSG_OK;
+    pa_idxset *streams;
+    pa_proplist *props;
+    pa_proplist *device_props;
+    uint32_t stream_index;
+    pa_hashmap *devices;
+    void *new_device = NULL;
+   ret_msg_t ret = RET_MSG_OK;
     DBusMessage *reply = NULL;
 
     pa_stream_manager *m = (pa_stream_manager*)userdata;
@@ -656,9 +666,10 @@ static void handle_set_stream_preferred_device(DBusConnection *conn, DBusMessage
 
     pa_assert_se(dbus_message_get_args(msg, NULL,
                                        DBUS_TYPE_UINT32, &sp_id,
+                                       DBUS_TYPE_STRING, &device_direction,
                                        DBUS_TYPE_UINT32, &device_id,
                                        DBUS_TYPE_INVALID));
-    pa_log_info("stream parent id[%u], device_id[%u]", sp_id, device_id);
+    pa_log_info("stream parent id[%u], device direction[%s], device_id[%u]", sp_id, device_direction, device_id);
 
     pa_assert_se((reply = dbus_message_new_method_return(msg)));
 
@@ -668,15 +679,24 @@ static void handle_set_stream_preferred_device(DBusConnection *conn, DBusMessage
         goto finish;
     }
 
+    if (pa_safe_streq(device_direction, "in"))
+        direction = STREAM_DIRECTION_IN;
+    else if (pa_safe_streq(device_direction, "out"))
+        direction = STREAM_DIRECTION_OUT;
+    else {
+        ret = RET_MSG_ERROR_INVALID_ARGUMENT;
+        goto finish;
+    }
+
     if (device_id == 0) {
         /* in case of unset */
-        if (!sp->preferred_device.type) {
+        if (!sp->preferred_device.types[direction]) {
             pa_log_debug("it is already unset");
             goto finish;
         }
         /* get a device of default role from previous device type */
-        if (!(device = pa_device_manager_get_device(m->dm, sp->preferred_device.type))) {
-            pa_log_error("could not get device[%s]", sp->preferred_device.type);
+        if (!(device = pa_device_manager_get_device(m->dm, sp->preferred_device.types[direction]))) {
+            pa_log_error("could not get device[%s]", sp->preferred_device.types[direction]);
             ret = RET_MSG_ERROR_DEVICE_NOT_FOUND;
             goto finish;
         }
@@ -688,11 +708,6 @@ static void handle_set_stream_preferred_device(DBusConnection *conn, DBusMessage
             ret = RET_MSG_ERROR_DEVICE_NOT_FOUND;
             goto finish;
         }
-        if (sp->preferred_device.type && !pa_streq(sp->preferred_device.type, device->type)) {
-            pa_log_error("already set preferred device(%s, %s), unset it first", sp->preferred_device.type, sp->preferred_device.role);
-            ret = RET_MSG_ERROR_INTERNAL;
-            goto finish;
-        }
         pa_log_debug("requested preferred device type(%s), id(%u)", pa_tz_device_get_type(device), pa_tz_device_get_id(device));
     }
 
@@ -714,60 +729,69 @@ static void handle_set_stream_preferred_device(DBusConnection *conn, DBusMessage
     /* get default role of the device */
     device_role = pa_tz_device_get_role(device, NULL);
 
-    sp->preferred_device.role = pa_safe_streq(device_role, DEVICE_ROLE_NORMAL) ? NULL : device_role;
-    sp->preferred_device.type = sp->preferred_device.role ? device->type : NULL;
-    pa_log_info("preferred device role is set to [%s] of device type[%s]", sp->preferred_device.role, device->type);
+    sp->preferred_device.roles[direction] = pa_safe_streq(device_role, DEVICE_ROLE_NORMAL) ? NULL : device_role;
+    sp->preferred_device.types[direction] = sp->preferred_device.roles[direction] ? device->type : NULL;
 
-    count = pa_idxset_size(sp->idx_sink_inputs);
-    PA_IDXSET_FOREACH(stream, sp->idx_sink_inputs, idx) {
-        if (pa_safe_streq(device_role, DEVICE_ROLE_NORMAL))
-            pa_proplist_unset(GET_STREAM_PROPLIST(stream, STREAM_SINK_INPUT),
-                                PA_PROP_MEDIA_ROUTE_AUTO_PREFERRED_DEVICE_ROLE);
-        else
-            pa_proplist_sets(GET_STREAM_PROPLIST(stream, STREAM_SINK_INPUT),
-                                PA_PROP_MEDIA_ROUTE_AUTO_PREFERRED_DEVICE_ROLE,
-                                device_role);
+    pa_log_info("preferred device role is set to [%s] of device type[%s], direction[%s]",
+            sp->preferred_device.roles[direction], device->type, direction == STREAM_DIRECTION_OUT ? "out" :  "in");
 
-        prev_device_type = pa_proplist_gets(GET_STREAM_PROPLIST(stream, STREAM_SINK_INPUT), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV);
-        if (pa_safe_streq(prev_device_type, device->type)) {
-            prev_device_role = pa_proplist_gets(PA_SINK_INPUT(stream)->sink->proplist, PA_PROP_DEVICE_ROLE);
-            pa_log_debug("move stream[%u]: [%s][%s -> %s]",
-                            PA_SINK_INPUT(stream)->index, prev_device_type, prev_device_role, device_role);
-            if (!pa_safe_streq(prev_device_role, device_role)) {
-                pa_sink *new_sink = pa_hashmap_get(device->playback_devices, device_role);
-                pa_sink_input_move_to(stream, new_sink, false);
-                if (count == 1)
-                    /* Use PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_FOCUS_CHANGED here.
-                     * It's not about the focus change, but this command exactly does what is needed here
-                     * including updating the highest priority, find the next stream to be set to HAL as well as
-                     * change the state of the builtin-device that use internal codec. */
-                    process_stream(m, stream, STREAM_SINK_INPUT, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_FOCUS_CHANGED, false);
-            }
-        }
-        count--;
+    if (direction == STREAM_DIRECTION_OUT) {
+        streams = sp->idx_sink_inputs;
+        devices = device->playback_devices;
+    } else {
+        streams = sp->idx_source_outputs;
+        devices = device->capture_devices;
     }
-    count = pa_idxset_size(sp->idx_source_outputs);
-    PA_IDXSET_FOREACH(stream, sp->idx_source_outputs, idx) {
+
+    count = pa_idxset_size(streams);
+    PA_IDXSET_FOREACH(stream, streams, idx) {
+        props = GET_STREAM_PROPLIST(stream, (direction == STREAM_DIRECTION_OUT) ?
+                        STREAM_SINK_INPUT : STREAM_SOURCE_OUTPUT);
+        pa_log_info("stream index(%u), props %p", (direction == STREAM_DIRECTION_OUT) ? PA_SINK_INPUT(stream)->index : PA_SOURCE_OUTPUT(stream)->index, props);
+        device_props = (direction == STREAM_DIRECTION_OUT) ?
+                        PA_SINK_INPUT(stream)->sink->proplist : PA_SOURCE_OUTPUT(stream)->source->proplist;
+        stream_index = (direction == STREAM_DIRECTION_OUT) ?
+                        PA_SINK_INPUT(stream)->index : PA_SOURCE_OUTPUT(stream)->index;
+
         if (pa_safe_streq(device_role, DEVICE_ROLE_NORMAL))
-            pa_proplist_unset(GET_STREAM_PROPLIST(stream, STREAM_SOURCE_OUTPUT),
-                                PA_PROP_MEDIA_ROUTE_AUTO_PREFERRED_DEVICE_ROLE);
+            pa_proplist_unset(props, PA_PROP_MEDIA_ROUTE_AUTO_PREFERRED_DEVICE_ROLE);
         else
-            pa_proplist_sets(GET_STREAM_PROPLIST(stream, STREAM_SOURCE_OUTPUT),
-                                PA_PROP_MEDIA_ROUTE_AUTO_PREFERRED_DEVICE_ROLE,
-                                device_role);
+            pa_proplist_sets(props, PA_PROP_MEDIA_ROUTE_AUTO_PREFERRED_DEVICE_ROLE, device_role);
+
+        prev_device_type = pa_proplist_gets(props, PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV);
+        prev_device_role = pa_proplist_gets(device_props, PA_PROP_DEVICE_ROLE);
 
-        prev_device_type = pa_proplist_gets(GET_STREAM_PROPLIST(stream, STREAM_SOURCE_OUTPUT), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV);
         if (pa_safe_streq(prev_device_type, device->type)) {
-            prev_device_role = pa_proplist_gets(PA_SOURCE_OUTPUT(stream)->source->proplist, PA_PROP_DEVICE_ROLE);
-            pa_log_debug("move stream[%u]: [%s][%s -> %s]",
-                            PA_SOURCE_OUTPUT(stream)->index, prev_device_type, prev_device_role, device_role);
+            /* If the request is for the same device type,
+             * new device role should be applied - move streams. */
             if (!pa_safe_streq(prev_device_role, device_role)) {
-                pa_source *new_source = pa_hashmap_get(device->capture_devices, device_role);
-                pa_source_output_move_to(stream, new_source, false);
-                if (count == 1)
-                    process_stream(m, stream, STREAM_SOURCE_OUTPUT, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_FOCUS_CHANGED, false);
+                new_device = pa_hashmap_get(devices, device_role);
+                pa_log_debug("move stream[%u]: [%s][%s -> %s]",
+                        stream_index, prev_device_type, prev_device_role, device_role);
             }
+        } else {
+            /* If the request is for a different device type,
+             * check the previous device role and move streams to default role if needed. */
+            prev_device = pa_device_manager_get_device(m->dm, prev_device_type);
+            new_device = pa_hashmap_first((direction == STREAM_DIRECTION_OUT) ?
+                                    prev_device->playback_devices : prev_device->capture_devices);
+            device_props = (direction == STREAM_DIRECTION_OUT) ? PA_SINK(new_device)->proplist : PA_SOURCE(new_device)->proplist;
+            pa_log_debug("may move stream[%u] to default role: [%s][%s -> %s]",
+                    stream_index, prev_device_type, prev_device_role, pa_proplist_gets(device_props, PA_PROP_DEVICE_ROLE));
+        }
+        if (new_device) {
+            if (direction == STREAM_DIRECTION_OUT)
+                pa_sink_input_move_to(stream, PA_SINK(new_device), false);
+            else
+                pa_source_output_move_to(stream, PA_SOURCE(new_device), false);
         }
+        if (count == 1)
+        /* Use PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_FOCUS_CHANGED here.
+         * It's not about the focus change, but this command exactly does what is needed here
+         * including updating the highest priority, find the next stream to be set to HAL as well as
+         * change the state of the builtin-device that use internal codec. */
+            process_stream(m, stream, (direction == STREAM_DIRECTION_OUT) ? STREAM_SINK_INPUT : STREAM_SOURCE_OUTPUT,
+                            PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_FOCUS_CHANGED, false);
         count--;
     }
 
index e2496f3..ab5488d 100644 (file)
@@ -188,8 +188,8 @@ typedef struct _stream_parent {
     focus_acquired_status_t focus_status;
     stream_route_type_t route_type;
     struct _preferred_device {
-        const char *role;
-        const char *type;
+        const char *roles[STREAM_DIRECTION_MAX];
+        const char *types[STREAM_DIRECTION_MAX];
     } preferred_device;
 } stream_parent;
 
index 53b45db..9c6a00b 100644 (file)
@@ -1117,10 +1117,10 @@ static void update_preferred_device_role(pa_stream_manager *m, void *stream, str
         return;
     }
 
-    if (sp->preferred_device.role)
+    if (sp->preferred_device.roles[type])
         pa_proplist_sets(GET_STREAM_NEW_PROPLIST(stream, type),
                         PA_PROP_MEDIA_ROUTE_AUTO_PREFERRED_DEVICE_ROLE,
-                        sp->preferred_device.role);
+                        sp->preferred_device.roles[type]);
 }
 
 static bool update_stream_parent_info(pa_stream_manager *m, process_command_type_t command, stream_type_t type, void *stream) {
index 8221dee..2838ab7 100644 (file)
@@ -74,10 +74,10 @@ do { \
 } while (0)
 
 #define GET_STREAM_NEW_PROPLIST(stream, type) \
-      (type == STREAM_SINK_INPUT ? ((pa_sink_input_new_data*)stream)->proplist : ((pa_source_output_new_data*)stream)->proplist)
+      ((type) == STREAM_SINK_INPUT ? ((pa_sink_input_new_data*)stream)->proplist : ((pa_source_output_new_data*)stream)->proplist)
 
 #define GET_STREAM_PROPLIST(stream, type) \
-      (type == STREAM_SINK_INPUT ? ((pa_sink_input*)stream)->proplist : ((pa_source_output*)stream)->proplist)
+      ((type) == STREAM_SINK_INPUT ? ((pa_sink_input*)stream)->proplist : ((pa_source_output*)stream)->proplist)
 
 #define STREAM_ROLE_MEDIA                     "media"
 #define STREAM_ROLE_RINGTONE_CALL             "ringtone-call"