stream-manager: A stream of manual route type should acquire focus to ensure its... 32/110832/1 accepted/tizen/common/20170123.182445 accepted/tizen/ivi/20170125.085024 accepted/tizen/mobile/20170125.084910 accepted/tizen/tv/20170125.084931 accepted/tizen/wearable/20170125.084956 submit/tizen/20170123.131118
authorSangchul Lee <sc11.lee@samsung.com>
Tue, 17 Jan 2017 08:00:25 +0000 (17:00 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Wed, 18 Jan 2017 07:24:42 +0000 (23:24 -0800)
Previously, a stream of manual route type takes priority over streams of other route type even if they have focus.
Now it is changed that the manual route type stream should get focus to ensure its routing path.

[Version] 5.0.127
[Profile] Common
[Issue Type] Feature enhancement

Change-Id: Ib03469019e95b1938a99b9ec64049096c9982755
Signed-off-by: Sangchul Lee <sc11.lee@samsung.com>
(cherry picked from commit a3bb5c3f1f76430654cd1cdd6feeb46f720c7313)

packaging/pulseaudio-modules-tizen.spec
src/stream-manager-priv.h
src/stream-manager.c
src/stream-manager.h

index 6a4b9f9..badf388 100644 (file)
@@ -1,6 +1,6 @@
 Name:             pulseaudio-modules-tizen
 Summary:          Pulseaudio modules for Tizen
-Version:          5.0.126
+Version:          5.0.127
 Release:          0
 Group:            Multimedia/Audio
 License:          LGPL-2.1+
index 114de89..621f9a2 100644 (file)
@@ -57,6 +57,9 @@ typedef enum _stream_direction {
 #define GET_STREAM_SAMPLE_SPEC(stream, type) \
       (type == STREAM_SINK_INPUT ? ((pa_sink_input*)stream)->sample_spec : ((pa_source_output*)stream)->sample_spec)
 
+#define GET_STREAM_INDEX(stream, type) \
+      (type == STREAM_SINK_INPUT ? ((pa_sink_input*)stream)->index : ((pa_source_output*)stream)->index)
+
 #define GET_FOCUS_STATUS(focus, type) \
       (type == STREAM_SINK_INPUT ? (focus & STREAM_FOCUS_ACQUIRED_PLAYBACK) : (focus & STREAM_FOCUS_ACQUIRED_CAPTURE))
 
@@ -105,6 +108,7 @@ typedef struct _stream_parent {
     pa_idxset *idx_route_in_devices;
     pa_idxset *idx_route_out_devices;
     focus_acquired_status_t focus_status;
+    stream_route_type_t route_type;
 } stream_parent;
 
 struct _stream_manager {
index da63680..8c86793 100644 (file)
@@ -487,6 +487,53 @@ static bool stream_is_call_family(pa_object *stream) {
     return false;
 }
 
+static int32_t convert_route_type(const char *route_type_str, stream_route_type_t *route_type) {
+    int ret = 0;
+
+    pa_assert(route_type);
+    pa_assert(route_type_str);
+
+    if (pa_streq("auto", route_type_str))
+        *route_type = STREAM_ROUTE_TYPE_AUTO;
+    else if (pa_streq("auto-last-connected", route_type_str))
+        *route_type = STREAM_ROUTE_TYPE_AUTO_LAST_CONNECTED;
+    else if (pa_streq("auto-all", route_type_str))
+        *route_type = STREAM_ROUTE_TYPE_AUTO_ALL;
+    else if (pa_streq("manual", route_type_str))
+        *route_type = STREAM_ROUTE_TYPE_MANUAL;
+    else if (pa_streq("manual-ext", route_type_str))
+        *route_type = STREAM_ROUTE_TYPE_MANUAL_EXT;
+    else {
+        ret = -1;
+        pa_log_error("Not supported route_type(%s)", route_type_str);
+    }
+
+    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) {
+    const char *route_type_str = NULL;
+
+    pa_assert(stream);
+    pa_assert(stream_route_type);
+
+    if (is_new_data)
+        route_type_str = pa_proplist_gets(GET_STREAM_NEW_PROPLIST(stream, stream_type), PA_PROP_MEDIA_ROLE_ROUTE_TYPE);
+    else
+        route_type_str = pa_proplist_gets(GET_STREAM_PROPLIST(stream, stream_type), PA_PROP_MEDIA_ROLE_ROUTE_TYPE);
+    if (!route_type_str) {
+        pa_log_warn("could not get route type from the stream(%p)", stream);
+        return -1;
+     }
+
+    if (pa_atoi(route_type_str, (int32_t*)stream_route_type)) {
+        pa_log_error("could not convert route_type_str(%s) to int", route_type_str);
+        return -1;
+    }
+
+    return 0;
+}
+
 static int32_t get_available_streams(pa_stream_manager *m, stream_list *list) {
     void *state = NULL;
     stream_info *s = NULL;
@@ -945,6 +992,66 @@ static void set_initial_active_device(pa_stream_manager *m) {
     set_media_active_device(m);
 }
 
+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;
+    uint32_t idx = 0;
+    void *cur_highest_priority_stream = NULL;
+    focus_acquired_status_t acquired_status = STREAM_FOCUS_ACQUIRED_NONE;
+    stream_route_type_t route_type = STREAM_ROUTE_TYPE_DEFAULT;
+
+    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;
+        acquired_status = STREAM_FOCUS_ACQUIRED_PLAYBACK;
+    } else {
+        idx_streams = sp->idx_source_outputs;
+        cur_highest_priority_stream = (void*)m->cur_highest_priority.source_output;
+        acquired_status = STREAM_FOCUS_ACQUIRED_CAPTURE;
+    }
+
+    /* 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)) {
+                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;
+                }
+            } else
+                return;
+        }
+    }
+
+    /* 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);
+            do_notify(m, NOTIFY_COMMAND_SELECT_PROPER_SINK_OR_SOURCE_FOR_INIT, type, false, stream);
+        }
+    } else if (cur_highest_priority_stream) {
+        /* trigger only when the stream parent has focus */
+        if ((sp->focus_status & acquired_status) && 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);
+            do_notify(m, NOTIFY_COMMAND_CHANGE_ROUTE_START, type, false, cur_highest_priority_stream);
+            if (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);
+            }
+        }
+    }
+}
+
 static void handle_set_stream_route_devices(DBusConnection *conn, DBusMessage *msg, void *userdata) {
     uint32_t id = 0;
     int i = 0;
@@ -954,10 +1061,7 @@ static void handle_set_stream_route_devices(DBusConnection *conn, DBusMessage *m
     int list_len_out = 0;
     uint32_t idx = 0;
     uint32_t *device_id = NULL;
-    void *stream = NULL;
     stream_parent *sp = NULL;
-    const char *route_type_str = NULL;
-    stream_route_type_t route_type;
     DBusMessage *reply = NULL;
     pa_stream_manager *m = (pa_stream_manager*)userdata;
 
@@ -981,88 +1085,36 @@ static void handle_set_stream_route_devices(DBusConnection *conn, DBusMessage *m
             pa_log_error("invalid arguments");
             goto fail;
         }
-
-        if (sp->idx_route_in_devices) {
-            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]);
-                }
-            }
-            PA_IDXSET_FOREACH(stream, sp->idx_source_outputs, idx) {
-                /* find route type of stream */
-                route_type_str = pa_proplist_gets(GET_STREAM_PROPLIST(stream, STREAM_SOURCE_OUTPUT), PA_PROP_MEDIA_ROLE_ROUTE_TYPE);
-                if (route_type_str) {
-                    pa_log_debug(" -- the route type of source_output that belongs to this parent id[%u] is [%s]", id, route_type_str);
-                    break;
-                }
-            }
-            /* if any stream that belongs to this id has been activated, do notify right away */
-            if (IS_ROUTE_TYPE_FOR_EXTERNAL_DEV(route_type_str, route_type)) {
-                PA_IDXSET_FOREACH(stream, sp->idx_source_outputs, idx) {
-                    pa_log_debug(" -- source_output[%p] belongs to this parent id[%u], do notify for the select proper source", stream, id);
-                    do_notify(m, NOTIFY_COMMAND_SELECT_PROPER_SINK_OR_SOURCE_FOR_INIT, STREAM_SOURCE_OUTPUT, false, stream);
-                }
-            } else 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 route change",
-                            (m->cur_highest_priority.source_output)->index, id);
-                    do_notify(m, NOTIFY_COMMAND_CHANGE_ROUTE_START, STREAM_SOURCE_OUTPUT, false, m->cur_highest_priority.source_output);
-                    if (stream_is_call_family(PA_OBJECT(m->cur_highest_priority.source_output)) && m->on_call) {
-                        pa_log_info("set active device for new call route device");
-                        change_active_route_for_call(PA_OBJECT(m->cur_highest_priority.source_output), false, m);
-                    }
-                }
-            }
-        } else {
-            pa_log_error("failed to update, idx_route_in_devices[%p]", sp->idx_route_in_devices);
+        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);
             goto fail;
         }
 
-        if (sp->idx_route_out_devices) {
-            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]);
-                }
-            }
-            PA_IDXSET_FOREACH(stream, sp->idx_sink_inputs, idx) {
-                /* find route type of stream */
-                route_type_str = pa_proplist_gets(GET_STREAM_PROPLIST(stream, STREAM_SINK_INPUT), PA_PROP_MEDIA_ROLE_ROUTE_TYPE);
-                if (route_type_str) {
-                    pa_log_debug(" -- the route type of sink_input that belongs to this parent id[%u] is [%s]", id, route_type_str);
-                    break;
-                }
+        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 any stream that belongs to this id has been activated, do notify right away */
-            if (IS_ROUTE_TYPE_FOR_EXTERNAL_DEV(route_type_str, route_type)) {
-                PA_IDXSET_FOREACH(stream, sp->idx_sink_inputs, idx) {
-                    pa_log_debug(" -- sink_input[%p] belongs to this parent id[%u], do notify for the select proper sink", stream, id);
-                    do_notify(m, NOTIFY_COMMAND_SELECT_PROPER_SINK_OR_SOURCE_FOR_INIT, STREAM_SINK_INPUT, false, stream);
-                }
-            } else 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 route change",
-                            (m->cur_highest_priority.sink_input)->index, id);
-                    do_notify(m, NOTIFY_COMMAND_CHANGE_ROUTE_START, STREAM_SINK_INPUT, false, m->cur_highest_priority.sink_input);
-                    if (stream_is_call_family(PA_OBJECT(m->cur_highest_priority.sink_input)) && m->on_call) {
-                        pa_log_info("set active device for new call route device");
-                        change_active_route_for_call(PA_OBJECT(m->cur_highest_priority.sink_input), false, m);
-                    }
-                }
+        }
+        update_devices_and_trigger_routing(m, sp, STREAM_SOURCE_OUTPUT);
+
+        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]);
             }
-        } else {
-            pa_log_error("failed to update, idx_route_out_devices[%p]", sp->idx_route_out_devices);
-            goto fail;
         }
+        update_devices_and_trigger_routing(m, sp, STREAM_SINK_INPUT);
+
         pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[RET_MSG_INDEX_OK], DBUS_TYPE_INVALID));
     } else {
         pa_log_error("could not find matching client for this parent_id[%u]", id);
@@ -1655,53 +1707,6 @@ static void send_command_signal(DBusConnection *conn, const char *name, int valu
 }
 #endif
 
-static int32_t convert_route_type(stream_route_type_t *route_type, const char *route_type_string) {
-    int ret = 0;
-
-    pa_assert(route_type);
-    pa_assert(route_type_string);
-
-    if (pa_streq("auto", route_type_string))
-        *route_type = STREAM_ROUTE_TYPE_AUTO;
-    else if (pa_streq("auto-last-connected", route_type_string))
-        *route_type = STREAM_ROUTE_TYPE_AUTO_LAST_CONNECTED;
-    else if (pa_streq("auto-all", route_type_string))
-        *route_type = STREAM_ROUTE_TYPE_AUTO_ALL;
-    else if (pa_streq("manual", route_type_string))
-        *route_type = STREAM_ROUTE_TYPE_MANUAL;
-    else if (pa_streq("manual-ext", route_type_string))
-        *route_type = STREAM_ROUTE_TYPE_MANUAL_EXT;
-    else {
-        ret = -1;
-        pa_log_error("Not supported route_type(%s)", route_type_string);
-    }
-
-    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) {
-    const char *route_type_str = NULL;
-
-    pa_assert(stream);
-    pa_assert(stream_route_type);
-
-    if (is_new_data)
-        route_type_str = pa_proplist_gets(GET_STREAM_NEW_PROPLIST(stream, stream_type), PA_PROP_MEDIA_ROLE_ROUTE_TYPE);
-    else
-        route_type_str = pa_proplist_gets(GET_STREAM_PROPLIST(stream, stream_type), PA_PROP_MEDIA_ROLE_ROUTE_TYPE);
-    if (!route_type_str) {
-        pa_log_warn("could not get route type from the stream(%p)", stream);
-        return -1;
-     }
-
-    if (pa_atoi(route_type_str, (int32_t*)stream_route_type)) {
-        pa_log_error("could not convert route_type_str(%s) to int", route_type_str);
-        return -1;
-    }
-
-    return 0;
-}
-
 static void dump_stream_map(pa_stream_manager *m) {
     stream_info *s = NULL;
     const char *role = NULL;
@@ -1861,7 +1866,7 @@ static int init_stream_map(pa_stream_manager *m) {
                     goto fail;
                 }
                 if (json_object_object_get_ex(array_item_o, STREAM_MAP_STREAM_ROUTE_TYPE, &item_o) && json_object_is_type(item_o, json_type_string)) {
-                    if (convert_route_type(&(s->route_type), json_object_get_string(item_o))) {
+                    if (convert_route_type(json_object_get_string(item_o), &(s->route_type))) {
                         pa_log_error("convert stream route-type failed");
                         goto fail;
                     }
@@ -2234,7 +2239,7 @@ static bool update_stream_parent_info(pa_stream_manager *m, process_command_type
         pa_log_debug("p_idx(%s), idx(%u)", p_idx, parent_idx);
         sp = pa_hashmap_get(m->stream_parents, (const void*)parent_idx);
         if (sp) {
-            uint32_t idx = (type == STREAM_SINK_INPUT) ? ((pa_sink_input*)stream)->index : ((pa_source_output*)stream)->index;
+            uint32_t idx = GET_STREAM_INDEX(stream, type);
             if (command == PROCESS_COMMAND_ADD_PARENT_ID) {
                 /* append this stream to the parent stream info. */
                 pa_log_debug(" - append this stream(%p, %u) to the list. sp(%p), stream_type(%d)", stream, idx, sp, type);
@@ -2765,7 +2770,7 @@ static void do_notify(pa_stream_manager *m, notify_command_type_t command, strea
         if (s) {
             stream_conn_info.role = pa_proplist_gets(GET_STREAM_PROPLIST(s, type), PA_PROP_MEDIA_ROLE);
             stream_conn_info.direction = (type == STREAM_SINK_INPUT) ? DIRECTION_OUT : DIRECTION_IN;
-            stream_conn_info.idx = (type == STREAM_SINK_INPUT) ? ((pa_sink_input*)s)->index : ((pa_source_output*)s)->index;
+            stream_conn_info.idx = GET_STREAM_INDEX(s, type);
             stream_conn_info.is_connected = (command == NOTIFY_COMMAND_INFORM_STREAM_CONNECTED) ? true : false;
             pa_hal_interface_notify_stream_connection_changed(m->hal, &stream_conn_info);
         }
@@ -3598,8 +3603,8 @@ static void update_sink_or_source_as_device_change(stream_route_type_t stream_ro
                         } else
                             pa_log_error("  -- could not find current device type for s->source(%p)", ((pa_source_output*)s)->source);
                     } else
-                        pa_log_debug("no need to move for stream(%p, idx:%u)", s, (stream_type == STREAM_SINK_INPUT ?
-                                     ((pa_sink_input*)s)->index : ((pa_source_output*)s)->index));
+                        pa_log_debug("no need to move for stream(%p, idx:%u)", s, GET_STREAM_INDEX(s, stream_type));
+
                     if (available) {
                         cached_prev_dev_list[cnt++].device_type = cur_device_type;
                         /* trigger to update routing path */
index 306b844..f677285 100644 (file)
 #define CONVERT_TO_DEVICE_ROLE(x_stream_role, x_device_role) \
 do { \
     pa_assert(x_stream_role); \
-    if (pa_streq(x_stream_role, STREAM_ROLE_CALL_VOICE)) \
+    if (pa_safe_streq(x_stream_role, STREAM_ROLE_CALL_VOICE)) \
         x_device_role = DEVICE_ROLE_CALL_VOICE; \
-    else if (pa_streq(x_stream_role, STREAM_ROLE_CALL_VIDEO)) \
+    else if (pa_safe_streq(x_stream_role, STREAM_ROLE_CALL_VIDEO)) \
         x_device_role = DEVICE_ROLE_CALL_VIDEO; \
-    else if (pa_streq(x_stream_role, STREAM_ROLE_VOIP)) \
+    else if (pa_safe_streq(x_stream_role, STREAM_ROLE_VOIP)) \
         x_device_role = DEVICE_ROLE_VOIP; \
     else \
         x_device_role = DEVICE_ROLE_NORMAL; \
@@ -82,6 +82,7 @@ typedef enum stream_route_type {
     STREAM_ROUTE_TYPE_AUTO_ALL,           /* A stream is routed automatically to several devices simultaneously. */
     STREAM_ROUTE_TYPE_MANUAL,             /* A stream is routed manually to the device(s) selected by user. */
     STREAM_ROUTE_TYPE_MANUAL_EXT,         /* A stream is routed manually only to the external device(s) selected by user. */
+    STREAM_ROUTE_TYPE_DEFAULT = STREAM_ROUTE_TYPE_AUTO, /* default (auto based on priority) */
 } stream_route_type_t;
 
 typedef struct _hook_call_data_for_select {