tizenaudio-policy: Apply new loopback module management 04/256504/3 accepted/tizen/unified/20210413.021247 submit/tizen/20210412.112307
authorSangchul Lee <sc11.lee@samsung.com>
Tue, 6 Apr 2021 02:24:46 +0000 (11:24 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Wed, 7 Apr 2021 08:34:11 +0000 (17:34 +0900)
Comparing with the previous logic, it is now possible to
load multiple loopback modules.
 - Each loopback module can be loaded per parent id.
 - Loading trigger point is moved from route_change_hook_cb()
   to select_device_by_manual_routing()

It relates to VPR-402.

[Version] 13.0.60
[Issue Type] New feature

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

index e0f63c5..3310887 100644 (file)
@@ -1,6 +1,6 @@
 Name:             pulseaudio-modules-tizen
 Summary:          Pulseaudio modules for Tizen
-Version:          13.0.59
+Version:          13.0.60
 Release:          0
 Group:            Multimedia/Audio
 License:          LGPL-2.1+
index bb3a727..2efbc89 100644 (file)
@@ -182,8 +182,6 @@ struct userdata {
     struct {
         int32_t latency_msec;
         int32_t adjust_sec;
-        pa_sink *sink;
-        pa_source *source;
     } loopback_args;
     pa_time_event *time_event_bt_sco_close;
 };
@@ -581,46 +579,6 @@ unload:
     pa_hashmap_remove_and_free(u->loopback_modules, (const void*)parent_id);
 }
 
-/* Load/Unload module-loopback */
-static void update_loopback_module(struct userdata *u, bool load) {
-    char *args = NULL;
-    const char *volume_type;
-
-    pa_assert(u);
-
-    if (load && u->loopback_args.sink && u->loopback_args.source) {
-        if (!u->loopback_args.latency_msec)
-            u->loopback_args.latency_msec = LOOPBACK_DEFAULT_LATENCY_MSEC;
-        if (!u->loopback_args.adjust_sec)
-            u->loopback_args.adjust_sec = LOOPBACK_DEFAULT_ADJUST_SEC;
-
-        volume_type = pa_stream_manager_get_volume_type(u->stream_manager, STREAM_SINK_INPUT, STREAM_ROLE_LOOPBACK);
-        args = pa_sprintf_malloc("sink=%s source=%s latency_msec=%d adjust_time=%d sink_input_properties=%s=%s",
-                                 u->loopback_args.sink->name, u->loopback_args.source->name,
-                                 u->loopback_args.latency_msec, u->loopback_args.adjust_sec,
-                                 PA_PROP_MEDIA_TIZEN_VOLUME_TYPE, volume_type);
-        if (u->module_loopback)
-            pa_module_unload(u->module_loopback, true);
-
-        if (pa_module_load(&u->module_loopback, u->core, MODULE_LOOPBACK, args))
-            pa_log_error("failed to load module-loopback with (%s)", args);
-        else
-            pa_log_info("  -- load module-loopback with (%s)", args);
-        pa_xfree(args);
-
-    } else if (!load) {
-        if (u->module_loopback) {
-            pa_module_unload(u->module_loopback, true);
-            u->module_loopback = NULL;
-            u->loopback_args.sink = NULL;
-            u->loopback_args.source = NULL;
-            pa_log_info("  -- unload module-loopback");
-        }
-    } else {
-        pa_log_error("  -- failed to update loopback module");
-    }
-}
-
 static pa_sink *load_combine_sink_module(struct userdata *u, const char *combine_sink_name, pa_sink *sink1, pa_sink *sink2, pa_sink_input *stream)
 {
     pa_module **combine_sink_module = NULL;
@@ -1016,6 +974,14 @@ static void select_device_by_manual_routing(struct userdata *u, pa_stream_manage
                 else
                     *(data->proper_source) = pa_tz_device_get_source(device, data->device_role);
             }
+            /* Update in/out devices for the loopback module arguments and load the module. */
+            if (pa_safe_streq(data->stream_role, STREAM_ROLE_LOOPBACK)) {
+                if ((data->stream_type == STREAM_SINK_INPUT) && (dm_device_direction & DM_DEVICE_DIRECTION_OUT))
+                    update_loopback_module_args(u, data->parent_id, pa_tz_device_get_sink(device, NULL), NULL);
+                else if ((data->stream_type == STREAM_SOURCE_OUTPUT) && (dm_device_direction & DM_DEVICE_DIRECTION_IN))
+                    update_loopback_module_args(u, data->parent_id, NULL, pa_tz_device_get_source(device, NULL));
+                load_loopback_module_by_parent_id(u, data->parent_id);
+            }
         }
     }
 }
@@ -1171,13 +1137,6 @@ static void reset_route(struct userdata *u, stream_type_t stream_type) {
 
     pa_assert(u);
 
-    if (u->module_loopback) {
-        if (stream_type == STREAM_SINK_INPUT && u->loopback_args.sink->use_internal_codec)
-            update_loopback_module(u, false);
-        else if (stream_type == STREAM_SOURCE_OUTPUT && u->loopback_args.source->use_internal_codec)
-            update_loopback_module(u, false);
-    }
-
     /* update BT SCO: close */
     update_bt_sco_state(u, false, true, NULL);
 
@@ -1684,13 +1643,6 @@ static pa_hook_result_t handle_manual_routing(struct userdata *u, pa_stream_mana
                 /* update BT SCO: close */
                 update_bt_sco_state(u, false, false, NULL);
             }
-            /* Check for in/out devices in case of loopback */
-            if (pa_safe_streq(data->stream_role, STREAM_ROLE_LOOPBACK)) {
-                if ((data->stream_type == STREAM_SINK_INPUT) && (dm_device_direction & DM_DEVICE_DIRECTION_OUT))
-                    u->loopback_args.sink = pa_tz_device_get_sink(*device, NULL);
-                else if ((data->stream_type == STREAM_SOURCE_OUTPUT) && (dm_device_direction & DM_DEVICE_DIRECTION_IN))
-                    u->loopback_args.source = pa_tz_device_get_source(*device, NULL);
-            }
 
             if (IS_AVAILABLE_DIRECTION(data->stream_type, dm_device_direction)) {
                 if ((use_internal_codec = pa_tz_device_is_use_internal_codec(*device)))
@@ -1700,11 +1652,6 @@ static pa_hook_result_t handle_manual_routing(struct userdata *u, pa_stream_mana
             }
         }
     }
-    if (pa_safe_streq(data->stream_role, STREAM_ROLE_LOOPBACK)) {
-        /* load module-loopback */
-        if (u->loopback_args.sink && u->loopback_args.source)
-            update_loopback_module(u, true);
-    }
 
     return PA_HOOK_OK;
 }
@@ -1767,18 +1714,8 @@ static pa_hook_result_t route_change_hook_cb(pa_core *c, pa_stream_manager_hook_
     route_info.role = data->stream_role;
 
     if (IS_AUTO_ROUTE_TYPE_SERIES(data->route_type)) {
-        pa_idxset *conn_devices = NULL;
-
-        /* unload module-loopback */
-        if (u->module_loopback) {
-            if (data->stream_type == STREAM_SINK_INPUT && u->loopback_args.sink->use_internal_codec)
-                update_loopback_module(u, false);
-            else if (data->stream_type == STREAM_SOURCE_OUTPUT && u->loopback_args.source->use_internal_codec)
-                update_loopback_module(u, false);
-        }
+        pa_idxset *conn_devices = pa_device_manager_get_device_list(u->device_manager);
 
-        /* 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) {
             if ((result = handle_auto_or_auto_all_routing(u, data, &route_info, conn_devices, &device)))
                 return result;
@@ -1820,6 +1757,13 @@ static pa_hook_result_t stream_connection_changed_hook_cb(pa_core *c, pa_stream_
                 data->is_connected ? "connected" : "disconnected",
                 data->stream, data->stream_type, data->stream_role, data->parent_id);
 
+    if (pa_safe_streq(data->stream_role, STREAM_ROLE_LOOPBACK) && !data->is_connected) {
+        pa_sink_input *i = data->stream_type == STREAM_SINK_INPUT ? (pa_sink_input *)data->stream : NULL;
+        pa_source_output *o = data->stream_type == STREAM_SINK_INPUT ? NULL : (pa_source_output *)data->stream;
+
+        unload_loopback_modules_by_stream_disconnect(u, data->parent_id, i, o);
+    }
+
     return PA_HOOK_OK;
 }
 
@@ -1920,17 +1864,11 @@ static pa_hook_result_t device_connection_changed_hook_cb(pa_core *c, pa_tz_devi
             /* unload combine sink for external devices */
             unload_combine_sink_module(u, SINK_NAME_COMBINED_EX, null_sink);
 
-            /* unload loopback module */
-            if (u->module_loopback)
-                if (u->loopback_args.sink == pa_tz_device_get_sink(conn->device, NULL))
-                    update_loopback_module(u, false);
-        }
-    if (device_direction & DM_DEVICE_DIRECTION_IN) {
-        /* unload loopback module */
-        if (u->module_loopback)
-            if (u->loopback_args.source == pa_tz_device_get_source(conn->device, NULL))
-                update_loopback_module(u, false);
+            unload_loopback_modules_by_device_disconnect(u, pa_tz_device_get_sink(conn->device, NULL), NULL);
         }
+
+        if (device_direction & DM_DEVICE_DIRECTION_IN)
+            unload_loopback_modules_by_device_disconnect(u, NULL, pa_tz_device_get_source(conn->device, NULL));
     }
 
     return PA_HOOK_OK;
index 15c1191..8043287 100644 (file)
@@ -2103,7 +2103,7 @@ static process_stream_result_t handle_command_prepare(pa_stream_manager *m, void
     update_preferred_device_role(m, stream, type);
 
     /* check if it is a virtual stream */
-    if (check_name_is_vstream(stream, type, is_new_data)) {
+    if (check_name_is_vstream(stream, type, is_new_data) && !pa_safe_streq(role, STREAM_ROLE_LOOPBACK)) {
         pa_log_debug("skip notifying for selecting sink/source, rather set it to null sink/source");
         /* set it to null sink/source */
         if (is_new_data)