tizenaudio-policy: Use new sub-functions inside of select_proper_sink_or_source_hook_cb() 88/214188/3
authorSangchul Lee <sc11.lee@samsung.com>
Thu, 19 Sep 2019 01:19:05 +0000 (10:19 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Thu, 19 Sep 2019 01:49:31 +0000 (10:49 +0900)
It'll reduce cyclomatic complexity of SAM.

[Version] 11.1.78
[Issue Type] Refactoring

Change-Id: I371317af1c9f732154b1e271f03d86d72a67e675
Signed-off-by: Sangchul Lee <sc11.lee@samsung.com>
packaging/pulseaudio-modules-tizen.spec
src/module-tizenaudio-policy.c

index 1fd3a47..891bf20 100644 (file)
@@ -1,6 +1,6 @@
 Name:             pulseaudio-modules-tizen
 Summary:          Pulseaudio modules for Tizen
-Version:          11.1.77
+Version:          11.1.78
 Release:          0
 Group:            Multimedia/Audio
 License:          LGPL-2.1+
index de7a79e..57fc284 100644 (file)
@@ -626,6 +626,262 @@ static inline bool is_cached_device_connected(const char* device_type, stream_ty
     return false;
 }
 
+static void select_device_by_auto_or_auto_all_routing(struct userdata *u, pa_stream_manager_hook_data_for_select *data, pa_idxset *conn_devices)  {
+    const char *device_type = NULL;
+    uint32_t idx = 0;
+    uint32_t conn_idx = 0;
+    uint32_t dm_device_id = 0;
+    const char *dm_device_type = NULL;
+    dm_device_direction_t dm_device_direction = DM_DEVICE_DIRECTION_NONE;
+    pa_tz_device *device = NULL;
+
+    pa_assert(u);
+    pa_assert(data);
+    pa_assert(conn_devices);
+
+    PA_IDXSET_FOREACH(device_type, data->idx_avail_devices, idx) {
+        pa_log_debug("[SELECT][AUTO(_ALL)] avail_device[%u] for this role[%-16s]: type[%-16s]", idx, data->stream_role, device_type);
+        if (!is_cached_device_connected(device_type, data->stream_type))
+            continue;
+
+        PA_IDXSET_FOREACH(device, conn_devices, conn_idx) {
+            dm_device_type = pa_tz_device_get_type(device);
+            dm_device_direction = pa_tz_device_get_direction(device);
+            dm_device_id = pa_tz_device_get_id(device);
+            pa_log_debug("  -- type[%-16s], direction[0x%x], id[%u]",
+                            dm_device_type, dm_device_direction, dm_device_id);
+            if (!pa_safe_streq(device_type, dm_device_type) || !IS_AVAILABLE_DIRECTION(data->stream_type, dm_device_direction))
+                continue;
+            pa_log_info("  ** found a matched device: type[%-16s], direction[0x%x]", dm_device_type, dm_device_direction);
+            if (skip_bt_sco_device(u, data->stream_role, dm_device_type))
+                continue;
+            if (skip_usb_device(data->stream_role, device))
+                continue;
+
+            if (data->stream_type == STREAM_SINK_INPUT) {
+                if (data->route_type == STREAM_ROUTE_TYPE_AUTO_ALL && u->module_combine_sink) {
+                    *(data->proper_sink) = (pa_sink*)pa_namereg_get(u->core, SINK_NAME_COMBINED, PA_NAMEREG_SINK);
+                    pa_log_info("  -- found the combine-sink, set it to the sink");
+                } else {
+                    *(data->proper_sink) = pa_tz_device_get_sink(device, data->device_role);
+                }
+                if (*(data->proper_sink) == NULL)
+                    continue;
+            } else {
+                *(data->proper_source) = pa_tz_device_get_source(device, data->device_role);
+                if (*(data->proper_source) == NULL)
+                    continue;
+            }
+
+            if (data->route_type == STREAM_ROUTE_TYPE_AUTO) {
+                if (data->origins_from_new_data)
+                    pa_proplist_sets(GET_STREAM_NEW_PROPLIST(data->stream, data->stream_type),
+                                        PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, dm_device_type);
+                else
+                    pa_proplist_sets(GET_STREAM_PROPLIST(data->stream, data->stream_type),
+                                        PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, dm_device_type);
+                return;
+            }
+        }
+    }
+}
+
+static void select_device_by_auto_last_connected_routing(struct userdata *u, pa_stream_manager_hook_data_for_select *data, pa_idxset *conn_devices) {
+    const char *device_type = NULL;
+    pa_tz_device *latest_device = NULL;
+    const char *latest_device_type = NULL;
+    pa_tz_device *device = NULL;
+    uint32_t idx = 0;
+    uint32_t conn_idx = 0;
+    uint32_t dm_device_id = 0;
+    const char *dm_device_type = NULL;
+    dm_device_direction_t dm_device_direction = DM_DEVICE_DIRECTION_NONE;
+    pa_usec_t creation_time = 0;
+    pa_usec_t latest_creation_time = 0;
+
+    pa_assert(u);
+    pa_assert(data);
+    pa_assert(conn_devices);
+
+    PA_IDXSET_FOREACH(device_type, data->idx_avail_devices, idx) {
+        pa_log_debug("[SELECT][AUTO_LAST_CONN] avail_device[%u] for this role[%-16s]: type[%-16s]", idx, data->stream_role, device_type);
+        if (!is_cached_device_connected(device_type, data->stream_type))
+            continue;
+
+        PA_IDXSET_FOREACH(device, conn_devices, conn_idx) {
+            dm_device_type = pa_tz_device_get_type(device);
+            dm_device_direction = pa_tz_device_get_direction(device);
+            dm_device_id = pa_tz_device_get_id(device);
+            creation_time = pa_tz_device_get_creation_time(device);
+            pa_log_debug("  -- type[%-16s], direction[0x%x], id[%u], creation_time[%llu]",
+                            dm_device_type, dm_device_direction, dm_device_id, creation_time);
+            if (!pa_safe_streq(device_type, dm_device_type) || !IS_AVAILABLE_DIRECTION(data->stream_type, dm_device_direction))
+                continue;
+            if (skip_bt_sco_device(u, data->stream_role, dm_device_type))
+                continue;
+            if (skip_usb_device(data->stream_role, device))
+                continue;
+
+            if (!latest_device || (latest_creation_time <= creation_time)) {
+                if (device_type_is_builtin(dm_device_type) && pa_safe_streq(latest_device_type, dm_device_type)) {
+                    pa_log_info("%s %s", latest_device_type, dm_device_type);
+                    if (data->stream_type == STREAM_SINK_INPUT ?
+                                                    (void*)pa_tz_device_get_sink(latest_device, data->device_role) :
+                                                    (void*)pa_tz_device_get_source(latest_device, data->device_role))
+                        continue;
+                }
+                latest_device = device;
+                latest_creation_time = creation_time;
+                latest_device_type = dm_device_type;
+                pa_log_info("  ** updated the last connected device: type[%-16s], direction[0x%x]", dm_device_type, dm_device_direction);
+            }
+        }
+    }
+    /* update active device info. */
+    if (latest_device) {
+        if (data->stream_type == STREAM_SINK_INPUT)
+            *(data->proper_sink) = pa_tz_device_get_sink(latest_device, data->device_role);
+        else
+            *(data->proper_source) = pa_tz_device_get_source(latest_device, data->device_role);
+
+        if (data->origins_from_new_data)
+            pa_proplist_sets(GET_STREAM_NEW_PROPLIST(data->stream, data->stream_type),
+                                PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, pa_tz_device_get_type(latest_device));
+        else
+            pa_proplist_sets(GET_STREAM_PROPLIST(data->stream, data->stream_type),
+                                PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, pa_tz_device_get_type(latest_device));
+    }
+}
+
+static void select_device_by_manual_routing(struct userdata *u, pa_stream_manager_hook_data_for_select *data, pa_sink *null_sink, pa_source *null_source) {
+    const char *device_type = NULL;
+    pa_tz_device *device = NULL;
+    uint32_t *device_id = NULL;
+    uint32_t idx = 0;
+    uint32_t m_idx = 0;
+    const char *dm_device_type = NULL;
+    dm_device_direction_t dm_device_direction = DM_DEVICE_DIRECTION_NONE;
+
+    pa_assert(u);
+    pa_assert(data);
+    pa_assert(null_sink);
+    pa_assert(null_source);
+
+    PA_IDXSET_FOREACH(device_type, data->idx_avail_devices, idx) {
+        pa_log_info("[SELECT][MANUAL] avail_device[%u] for this role[%-16s]: type[%-16s]", idx, data->stream_role, device_type);
+        if (!is_cached_device_connected(device_type, data->stream_type))
+            continue;
+
+        PA_IDXSET_FOREACH(device_id, data->idx_manual_devices, m_idx) {
+            if (!(device = pa_device_manager_get_device_by_id(u->device_manager, *device_id)))
+                continue;
+            dm_device_type = pa_tz_device_get_type(device);
+            dm_device_direction = pa_tz_device_get_direction(device);
+            pa_log_debug("  -- type[%-16s], direction[0x%x], device id[%u]",
+                            dm_device_type, dm_device_direction, *device_id);
+            if (!pa_safe_streq(device_type, dm_device_type) || !IS_AVAILABLE_DIRECTION(data->stream_type, dm_device_direction))
+                continue;
+            pa_log_info("  ** found a matched device: type[%-16s], direction[0x%x]", device_type, dm_device_direction);
+            if (data->stream_type == STREAM_SINK_INPUT) {
+                if ((*(data->proper_sink)) == null_sink)
+                    pa_sink_input_move_to((pa_sink_input*)(data->stream), pa_tz_device_get_sink(device, data->device_role), false);
+                else
+                    *(data->proper_sink) = pa_tz_device_get_sink(device, data->device_role);
+            } else {
+                if ((*(data->proper_source)) == null_source)
+                    pa_source_output_move_to((pa_source_output*)(data->stream), pa_tz_device_get_source(device, data->device_role), false);
+                else
+                    *(data->proper_source) = pa_tz_device_get_source(device, data->device_role);
+            }
+        }
+    }
+}
+
+static void select_device_by_manual_external_routing(struct userdata *u, pa_stream_manager_hook_data_for_select *data) {
+    const char *device_type = NULL;
+    pa_tz_device *device = NULL;
+    uint32_t *device_id = NULL;
+    uint32_t idx = 0;
+    uint32_t m_idx = 0;
+    const char *dm_device_type = NULL;
+    dm_device_direction_t dm_device_direction = DM_DEVICE_DIRECTION_NONE;
+    pa_sink *sink = NULL;
+    pa_source *source = NULL;
+    pa_sink *combine_sink_arg1 = NULL;
+    pa_sink *combine_sink_arg2 = NULL;
+    void *stream = NULL;
+
+    pa_assert(u);
+    pa_assert(data);
+
+    PA_IDXSET_FOREACH(device_type, data->idx_avail_devices, idx) {
+        pa_log_info("[SELECT][MANUAL_EXT] avail_device[%u] for this role[%-16s]: type[%-16s]", idx, data->stream_role, device_type);
+        if (!is_cached_device_connected(device_type, data->stream_type))
+            continue;
+
+        PA_IDXSET_FOREACH(device_id, data->idx_manual_devices, m_idx) {
+            if (!(device = pa_device_manager_get_device_by_id(u->device_manager, *device_id)))
+                continue;
+            dm_device_type = pa_tz_device_get_type(device);
+            dm_device_direction = pa_tz_device_get_direction(device);
+            pa_log_debug("  -- type[%-16s], direction[0x%x], device id[%u]", dm_device_type, dm_device_direction, *device_id);
+            if (!pa_safe_streq(device_type, dm_device_type) || !IS_AVAILABLE_DIRECTION(data->stream_type, dm_device_direction))
+                continue;
+            pa_log_info("  ** found a matched device: type[%-16s], direction[0x%x]", device_type, dm_device_direction);
+            /* currently, we support two sinks for combining */
+            if (data->stream_type == STREAM_SINK_INPUT) {
+                if (!combine_sink_arg1) {
+                    if ((sink = combine_sink_arg1 = pa_tz_device_get_sink(device, NULL)))
+                        pa_log_info("  -- combine_sink_arg1[%s], combine_sink_arg2[%p]", sink->name, combine_sink_arg2);
+                    else
+                        pa_log_warn("  -- could not get combine_sink_arg1");
+                } else if (!combine_sink_arg2) {
+                    sink = combine_sink_arg2 = pa_tz_device_get_sink(device, NULL);
+                    if (sink && !pa_safe_streq(sink->name, combine_sink_arg1->name)) {
+                        uint32_t s_idx = 0;
+
+                        pa_log_info("  -- combine_sink_arg2[%s]", sink->name);
+                        /* load combine sink */
+                        if (!u->module_combine_sink_for_ex) {
+                            char *args = pa_sprintf_malloc("sink_name=%s slaves=\"%s,%s\"",
+                                                            SINK_NAME_COMBINED_EX, combine_sink_arg1->name, combine_sink_arg2->name);
+                            pa_log_info("  -- combined sink is not prepared, now load module[%s]", args);
+                            u->module_combine_sink_for_ex = pa_module_load(u->core, MODULE_COMBINE_SINK, args);
+                            pa_xfree(args);
+                        }
+                        sink = (pa_sink*)pa_namereg_get(u->core, SINK_NAME_COMBINED_EX, PA_NAMEREG_SINK);
+                        PA_IDXSET_FOREACH(stream, combine_sink_arg1->inputs, s_idx) {
+                            if (sink && stream == data->stream) {
+                                pa_sink_input_move_to(stream, sink, false);
+                                pa_log_info("  -- *** sink-input(%p,%u) moves to sink(%p,%s)", stream, ((pa_sink_input*)stream)->index, sink, sink->name);
+                                break;
+                            }
+                        }
+                    } else if (!sink) {
+                        pa_log_warn("  -- could not get combine_sink_arg2");
+                    }
+                }
+                if (data->origins_from_new_data)
+                    *(data->proper_sink) = sink;
+                else {
+                    if (((pa_sink_input*)(data->stream))->sink != sink)
+                        pa_sink_input_move_to(data->stream, sink, false);
+                }
+                continue;
+            }
+            /* source-output case */
+            if ((source = pa_tz_device_get_source(device, NULL))) {
+                if (data->origins_from_new_data)
+                    *(data->proper_source) = source;
+                else {
+                    if (((pa_source_output*)(data->stream))->source != source)
+                        pa_source_output_move_to(data->stream, source, false);
+                }
+            }
+        }
+    }
+}
+
 /* Set the proper sink(source) according to the data of the parameter.
  * - ROUTE_TYPE_AUTO(_ALL)
  *     1. Find the proper sink/source comparing between avail_devices
@@ -636,23 +892,9 @@ static inline bool is_cached_device_connected(const char* device_type, stream_ty
  *        and manual_devices that have been set by user.
  *     2. If not found, set it to null sink/source. */
 static pa_hook_result_t select_proper_sink_or_source_hook_cb(pa_core *c, pa_stream_manager_hook_data_for_select *data, struct userdata *u) {
-    uint32_t idx = 0;
-    uint32_t m_idx = 0;
-    uint32_t conn_idx = 0;
-    uint32_t *device_id = NULL;
-    uint32_t dm_device_id = 0;
-    const char *device_type = NULL;
-    const char *dm_device_type = NULL;
-    dm_device_direction_t dm_device_direction = DM_DEVICE_DIRECTION_NONE;
-    pa_tz_device *device = NULL;
     pa_idxset *conn_devices = NULL;
-    pa_sink *sink = NULL;
     pa_sink *null_sink = NULL;
-    pa_sink *combine_sink_arg1 = NULL;
-    pa_sink *combine_sink_arg2 = NULL;
-    pa_source *source = NULL;
     pa_source *null_source = NULL;
-    void *s = NULL;
 
     pa_assert(c);
     pa_assert(data);
@@ -691,202 +933,16 @@ static pa_hook_result_t select_proper_sink_or_source_hook_cb(pa_core *c, pa_stre
     if (IS_AUTO_ROUTE_TYPE_SERIES(data->route_type)) {
         /* get current connected devices */
         conn_devices = pa_device_manager_get_device_list(u->device_manager);
-        if (data->route_type == STREAM_ROUTE_TYPE_AUTO || data->route_type == STREAM_ROUTE_TYPE_AUTO_ALL) {
-            PA_IDXSET_FOREACH(device_type, data->idx_avail_devices, idx) {
-                pa_log_debug("[SELECT][AUTO(_ALL)] avail_device[%u] for this role[%-16s]: type[%-16s]", idx, data->stream_role, device_type);
-                if (!is_cached_device_connected(device_type, data->stream_type))
-                    continue;
-                PA_IDXSET_FOREACH(device, conn_devices, conn_idx) {
-                    dm_device_type = pa_tz_device_get_type(device);
-                    dm_device_direction = pa_tz_device_get_direction(device);
-                    dm_device_id = pa_tz_device_get_id(device);
-                    pa_log_debug("  -- type[%-16s], direction[0x%x], id[%u]",
-                                 dm_device_type, dm_device_direction, dm_device_id);
-                    if (pa_safe_streq(device_type, dm_device_type) && IS_AVAILABLE_DIRECTION(data->stream_type, dm_device_direction)) {
-                        pa_log_info("  ** found a matched device: type[%-16s], direction[0x%x]", dm_device_type, dm_device_direction);
-                        if (skip_bt_sco_device(u, data->stream_role, dm_device_type))
-                            continue;
-                        if (skip_usb_device(data->stream_role, device))
-                            continue;
-
-                        if (data->stream_type == STREAM_SINK_INPUT) {
-                            if (data->route_type == STREAM_ROUTE_TYPE_AUTO_ALL && u->module_combine_sink) {
-                                *(data->proper_sink) = (pa_sink*)pa_namereg_get(u->core, SINK_NAME_COMBINED, PA_NAMEREG_SINK);
-                                pa_log_info("  -- found the combine-sink, set it to the sink");
-                            } else {
-                                *(data->proper_sink) = pa_tz_device_get_sink(device, data->device_role);
-                            }
-                            if (*(data->proper_sink) == NULL)
-                                continue;
-                        } else {
-                            *(data->proper_source) = pa_tz_device_get_source(device, data->device_role);
-                            if (*(data->proper_source) == NULL)
-                                continue;
-                        }
-
-                        if (data->route_type == STREAM_ROUTE_TYPE_AUTO) {
-                            if (data->origins_from_new_data)
-                                pa_proplist_sets(GET_STREAM_NEW_PROPLIST(data->stream, data->stream_type),
-                                                    PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, dm_device_type);
-                            else
-                                pa_proplist_sets(GET_STREAM_PROPLIST(data->stream, data->stream_type),
-                                                    PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, dm_device_type);
-                            return PA_HOOK_OK;
-                        }
-                    }
-                }
-            }
-        } else if (data->route_type == STREAM_ROUTE_TYPE_AUTO_LAST_CONNECTED) {
-            pa_tz_device *latest_device = NULL;
-            const char *latest_device_type = NULL;
-            pa_usec_t creation_time = 0;
-            pa_usec_t latest_creation_time = 0;
-
-            PA_IDXSET_FOREACH(device_type, data->idx_avail_devices, idx) {
-                pa_log_debug("[SELECT][AUTO_LAST_CONN] avail_device[%u] for this role[%-16s]: type[%-16s]", idx, data->stream_role, device_type);
-                if (!is_cached_device_connected(device_type, data->stream_type))
-                    continue;
-                PA_IDXSET_FOREACH(device, conn_devices, conn_idx) {
-                    dm_device_type = pa_tz_device_get_type(device);
-                    dm_device_direction = pa_tz_device_get_direction(device);
-                    dm_device_id = pa_tz_device_get_id(device);
-                    creation_time = pa_tz_device_get_creation_time(device);
-                    pa_log_debug("  -- type[%-16s], direction[0x%x], id[%u], creation_time[%llu]",
-                                 dm_device_type, dm_device_direction, dm_device_id, creation_time);
-                    if (pa_safe_streq(device_type, dm_device_type) && IS_AVAILABLE_DIRECTION(data->stream_type, dm_device_direction)) {
-                        if (skip_bt_sco_device(u, data->stream_role, dm_device_type))
-                            continue;
-                        if (skip_usb_device(data->stream_role, device))
-                            continue;
-
-                        if (!latest_device || (latest_creation_time <= creation_time)) {
-                            if (device_type_is_builtin(dm_device_type) && pa_safe_streq(latest_device_type, dm_device_type)) {
-                                pa_log_info("%s %s", latest_device_type, dm_device_type);
-                                if (data->stream_type == STREAM_SINK_INPUT ?
-                                                                (void*)pa_tz_device_get_sink(latest_device, data->device_role) :
-                                                                (void*)pa_tz_device_get_source(latest_device, data->device_role))
-                                    continue;
-                            }
-                            latest_device = device;
-                            latest_creation_time = creation_time;
-                            latest_device_type = dm_device_type;
-                            pa_log_info("  ** updated the last connected device: type[%-16s], direction[0x%x]", dm_device_type, dm_device_direction);
-                        }
-                    }
-                }
-            }
-            /* update active device info. */
-            if (latest_device) {
-                if (data->stream_type == STREAM_SINK_INPUT)
-                    *(data->proper_sink) = pa_tz_device_get_sink(latest_device, data->device_role);
-                else
-                    *(data->proper_source) = pa_tz_device_get_source(latest_device, data->device_role);
-
-                if (data->origins_from_new_data)
-                    pa_proplist_sets(GET_STREAM_NEW_PROPLIST(data->stream, data->stream_type),
-                                        PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, pa_tz_device_get_type(latest_device));
-                else
-                    pa_proplist_sets(GET_STREAM_PROPLIST(data->stream, data->stream_type),
-                                        PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, pa_tz_device_get_type(latest_device));
-            }
-        }
+        if (data->route_type == STREAM_ROUTE_TYPE_AUTO || data->route_type == STREAM_ROUTE_TYPE_AUTO_ALL)
+            select_device_by_auto_or_auto_all_routing(u, data, conn_devices);
+        else if (data->route_type == STREAM_ROUTE_TYPE_AUTO_LAST_CONNECTED)
+            select_device_by_auto_last_connected_routing(u, data, conn_devices);
 
     } else if (data->route_type == STREAM_ROUTE_TYPE_MANUAL) {
-        PA_IDXSET_FOREACH(device_type, data->idx_avail_devices, idx) {
-            pa_log_info("[SELECT][MANUAL] avail_device[%u] for this role[%-16s]: type[%-16s]", idx, data->stream_role, device_type);
-            if (!is_cached_device_connected(device_type, data->stream_type))
-                continue;
-            PA_IDXSET_FOREACH(device_id, data->idx_manual_devices, m_idx) {
-                if (!(device = pa_device_manager_get_device_by_id(u->device_manager, *device_id)))
-                    continue;
-                dm_device_type = pa_tz_device_get_type(device);
-                dm_device_direction = pa_tz_device_get_direction(device);
-                pa_log_debug("  -- type[%-16s], direction[0x%x], device id[%u]",
-                             dm_device_type, dm_device_direction, *device_id);
-                if (pa_safe_streq(device_type, dm_device_type) && IS_AVAILABLE_DIRECTION(data->stream_type, dm_device_direction)) {
-                    pa_log_info("  ** found a matched device: type[%-16s], direction[0x%x]", device_type, dm_device_direction);
-                    if (data->stream_type == STREAM_SINK_INPUT) {
-                        if ((*(data->proper_sink)) == null_sink)
-                            pa_sink_input_move_to((pa_sink_input*)(data->stream), pa_tz_device_get_sink(device, data->device_role), false);
-                        else
-                            *(data->proper_sink) = pa_tz_device_get_sink(device, data->device_role);
-                    } else {
-                        if ((*(data->proper_source)) == null_source)
-                            pa_source_output_move_to((pa_source_output*)(data->stream), pa_tz_device_get_source(device, data->device_role), false);
-                        else
-                            *(data->proper_source) = pa_tz_device_get_source(device, data->device_role);
-                    }
-                }
-            }
-        }
+        select_device_by_manual_routing(u, data, null_sink, null_source);
 
     } else if (data->route_type == STREAM_ROUTE_TYPE_MANUAL_EXT) {
-        PA_IDXSET_FOREACH(device_type, data->idx_avail_devices, idx) {
-            pa_log_info("[SELECT][MANUAL_EXT] avail_device[%u] for this role[%-16s]: type[%-16s]", idx, data->stream_role, device_type);
-            if (!is_cached_device_connected(device_type, data->stream_type))
-                continue;
-            PA_IDXSET_FOREACH(device_id, data->idx_manual_devices, m_idx) {
-                if (!(device = pa_device_manager_get_device_by_id(u->device_manager, *device_id)))
-                    continue;
-                dm_device_type = pa_tz_device_get_type(device);
-                dm_device_direction = pa_tz_device_get_direction(device);
-                pa_log_debug("  -- type[%-16s], direction[0x%x], device id[%u]",
-                             dm_device_type, dm_device_direction, *device_id);
-                if (pa_safe_streq(device_type, dm_device_type) && IS_AVAILABLE_DIRECTION(data->stream_type, dm_device_direction)) {
-                    pa_log_info("  ** found a matched device: type[%-16s], direction[0x%x]", device_type, dm_device_direction);
-                    /* currently, we support two sinks for combining */
-                    if (data->stream_type == STREAM_SINK_INPUT) {
-                        if (!combine_sink_arg1) {
-                            if ((sink = combine_sink_arg1 = pa_tz_device_get_sink(device, NULL)))
-                                pa_log_info("  -- combine_sink_arg1[%s], combine_sink_arg2[%p]", sink->name, combine_sink_arg2);
-                            else
-                                pa_log_warn("  -- could not get combine_sink_arg1");
-                        } else if (!combine_sink_arg2) {
-                            sink = combine_sink_arg2 = pa_tz_device_get_sink(device, NULL);
-                            if (sink && !pa_safe_streq(sink->name, combine_sink_arg1->name)) {
-                                uint32_t s_idx = 0;
-
-                                pa_log_info("  -- combine_sink_arg2[%s]", sink->name);
-                                /* load combine sink */
-                                if (!u->module_combine_sink_for_ex) {
-                                    char *args = pa_sprintf_malloc("sink_name=%s slaves=\"%s,%s\"", SINK_NAME_COMBINED_EX, combine_sink_arg1->name, combine_sink_arg2->name);
-                                    pa_log_info("  -- combined sink is not prepared, now load module[%s]", args);
-                                    u->module_combine_sink_for_ex = pa_module_load(u->core, MODULE_COMBINE_SINK, args);
-                                    pa_xfree(args);
-                                }
-                                sink = (pa_sink*)pa_namereg_get(u->core, SINK_NAME_COMBINED_EX, PA_NAMEREG_SINK);
-                                PA_IDXSET_FOREACH(s, combine_sink_arg1->inputs, s_idx) {
-                                    if (sink && s == data->stream) {
-                                        pa_sink_input_move_to(s, sink, false);
-                                        pa_log_info("  -- *** sink-input(%p,%u) moves to sink(%p,%s)", s, ((pa_sink_input*)s)->index, sink, sink->name);
-                                        break;
-                                    }
-                                }
-                            } else if (!sink) {
-                                pa_log_warn("  -- could not get combine_sink_arg2");
-                            }
-                        }
-                        if (data->origins_from_new_data)
-                            *(data->proper_sink) = sink;
-                        else {
-                            if (((pa_sink_input*)(data->stream))->sink != sink)
-                                pa_sink_input_move_to(data->stream, sink, false);
-                        }
-
-                    } else if (data->stream_type == STREAM_SOURCE_OUTPUT) {
-                        if ((source = pa_tz_device_get_source(device, NULL))) {
-                            if (data->origins_from_new_data)
-                                *(data->proper_source) = source;
-                            else {
-                                if (((pa_source_output*)(data->stream))->source != source)
-                                    pa_source_output_move_to(data->stream, source, false);
-                            }
-                        } else
-                            pa_log_warn("  -- could not get source");
-                    }
-                }
-            }
-        }
+        select_device_by_manual_external_routing(u, data);
     }
 
 not_found: