route_info->num_of_devices -1, type, direction, id);
}
+static pa_hook_result_t update_combine_sink_and_bt_sco(struct userdata *u, pa_stream_manager_hook_data_for_route *data,
+ pa_tz_device *device, const char *stream_role, const char *dm_device_type,
+ pa_sink **combine_sink_arg1, pa_sink **combine_sink_arg2) {
+ pa_sink *sink = NULL;
+
+ pa_assert(u);
+ pa_assert(data);
+ pa_assert(device);
+
+ switch (data->route_type) {
+ case STREAM_ROUTE_TYPE_AUTO: {
+ /* unload combine sink */
+ if (data->stream_type == STREAM_SINK_INPUT) {
+ if ((sink = pa_tz_device_get_sink(device, data->device_role)))
+ unload_combine_sink_module(u, SINK_NAME_COMBINED, sink);
+ else
+ pa_log_error("[ROUTE][AUTO] could not get sink");
+ }
+ if (pa_safe_streq(dm_device_type, DEVICE_TYPE_BT_SCO)) {
+ if (IS_ROLE_AVAILABLE_BT_SCO_OPEN(stream_role)) {
+ if (update_bt_sco_state(u, true, false, stream_role)) {
+ pa_log_error(" ** could not open BT SCO");
+ return PA_HOOK_CANCEL;
+ }
+ update_bt_sco_option(u, stream_role);
+ }
+ return PA_HOOK_OK;
+ }
+ update_bt_sco_state(u, false, false, NULL);
+ break;
+ }
+ case STREAM_ROUTE_TYPE_AUTO_ALL: {
+ pa_source *source = NULL;
+ uint32_t s_idx = 0;
+ void *s = NULL;
+ stream_route_type_t route_type;
+
+ update_bt_sco_state(u, false, false, NULL);
+
+ /* find the proper sink/source */
+ /* currently, we support two sinks for combining */
+ if (data->stream_type == STREAM_SINK_INPUT && u->module_combine_sink) {
+ sink = (pa_sink*)pa_namereg_get(u->core, SINK_NAME_COMBINED, PA_NAMEREG_SINK);
+ pa_log_info("[ROUTE][AUTO_ALL] found the combine_sink already existed");
+
+ } else if (data->stream_type == STREAM_SINK_INPUT && !*combine_sink_arg1) {
+ sink = *combine_sink_arg1 = pa_tz_device_get_sink(device, data->device_role);
+ if (sink)
+ pa_log_info("[ROUTE][AUTO_ALL] combine_sink_arg1[%s], combine_sink_arg2[%p]", sink->name, *combine_sink_arg2);
+
+ } else if (data->stream_type == STREAM_SINK_INPUT && !*combine_sink_arg2) {
+ sink = *combine_sink_arg2 = pa_tz_device_get_sink(device, data->device_role);
+ if (sink && !pa_safe_streq(sink->name, (*combine_sink_arg1)->name)) {
+ pa_log_info("[ROUTE][AUTO_ALL] combine_sink_arg2[%s]", sink->name);
+ /* load combine sink */
+ if (!u->module_combine_sink) {
+ char *args = pa_sprintf_malloc("sink_name=%s slaves=\"%s,%s\"",
+ SINK_NAME_COMBINED, (*combine_sink_arg1)->name, (*combine_sink_arg2)->name);
+ pa_log_info("[ROUTE][AUTO_ALL] combined sink is not prepared, now load module[%s]", args);
+ u->module_combine_sink = pa_module_load(u->core, MODULE_COMBINE_SINK, args);
+ pa_xfree(args);
+ }
+ if ((sink = (pa_sink*)pa_namereg_get(u->core, SINK_NAME_COMBINED, PA_NAMEREG_SINK))) {
+ PA_IDXSET_FOREACH(s, (*combine_sink_arg1)->inputs, s_idx) {
+ if (s == data->stream) {
+ pa_sink_input_move_to(s, sink, false);
+ pa_log_info("[ROUTE][AUTO_ALL] *** sink-nput(%p,%u) moves to sink(%p,%s)",
+ s, ((pa_sink_input*)s)->index, sink, sink->name);
+ }
+ }
+ }
+ }
+
+ } else if (data->stream_type == STREAM_SOURCE_OUTPUT) {
+ source = pa_tz_device_get_source(device, data->device_role);
+ }
+
+ if (data->origins_from_new_data) {
+ if (data->stream_type == STREAM_SINK_INPUT)
+ *(data->proper_sink) = sink;
+ else
+ *(data->proper_source) = source;
+ break;
+ }
+ /* move sink-inputs/source-outputs if needed */
+ if (!data->idx_streams)
+ break;
+ PA_IDXSET_FOREACH(s, data->idx_streams, s_idx) { /* data->idx_streams: null_sink */
+ if (pa_stream_manager_get_route_type(s, data->stream_type, false, &route_type) ||
+ (route_type != STREAM_ROUTE_TYPE_AUTO_ALL))
+ continue;
+ if ((data->stream_type == STREAM_SINK_INPUT) && (sink && (sink != ((pa_sink_input*)s)->sink))) {
+ pa_sink_input_move_to(s, sink, false);
+ pa_log_info("[ROUTE][AUTO_ALL] *** sink-input(%p,%u) moves to sink(%p,%s)",
+ s, ((pa_sink_input*)s)->index, sink, sink->name);
+ } else if ((data->stream_type == STREAM_SOURCE_OUTPUT) && (source && (source != ((pa_source_output*)s)->source))) {
+ pa_source_output_move_to(s, source, false);
+ pa_log_info("[ROUTE][AUTO_ALL] *** source-output(%p,%u) moves to source(%p,%s)",
+ s, ((pa_source_output*)s)->index, source, source->name);
+ }
+ }
+ break;
+ }
+ default:
+ pa_log_error("it can not be here, route_type(%d)", data->route_type);
+ break;
+ }
+ return PA_HOOK_OK;
+}
+
+static pa_hook_result_t handle_auto_or_auto_all_routing(struct userdata *u, pa_stream_manager_hook_data_for_route *data,
+ hal_route_info *route_info, pa_idxset *conn_devices, pa_tz_device **device) {
+ const char *device_type = NULL;
+ const char *dm_device_type = NULL;
+ dm_device_direction_t dm_device_direction = DM_DEVICE_DIRECTION_NONE;
+ uint32_t dm_device_id = 0;
+ uint32_t idx = 0;
+ uint32_t conn_idx = 0;
+ bool use_internal_codec = false;
+ pa_sink *combine_sink_arg1 = NULL;
+ pa_sink *combine_sink_arg2 = NULL;
+
+ pa_assert(u);
+ pa_assert(data);
+ pa_assert(route_info);
+ pa_assert(conn_devices);
+ pa_assert(device);
+
+ PA_IDXSET_FOREACH(device_type, data->idx_avail_devices, idx) {
+ pa_log_debug("[ROUTE][AUTO(_ALL)] avail_device[%u] for this role[%-16s]: type[%-16s]", idx, route_info->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_debug(" ** found a matched device: type[%-16s], direction[0x%x]", dm_device_type, dm_device_direction);
+ if (skip_usb_device(data->stream_role, *device))
+ continue;
+ if ((use_internal_codec = pa_tz_device_is_use_internal_codec(*device))) {
+ /* if it needs to skip it, keep going to next device for proper UCM setting */
+ if (skip_device(data->stream_role, dm_device_type))
+ continue;
+ if (skip_bt_sco_device(u, data->stream_role, dm_device_type))
+ continue;
+ fill_device_info(route_info, dm_device_type, CONVERT_TO_HAL_DIRECTION(data->stream_type), dm_device_id);
+ break;
+ }
+ pa_log_debug(" -- it does not use internal audio codec, skip it");
+ break;
+ }
+ if (*device == 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 update_combine_sink_and_bt_sco(u, data, *device, route_info->role, dm_device_type, NULL, NULL);
+
+ } else if (data->route_type == STREAM_ROUTE_TYPE_AUTO_ALL) {
+ update_combine_sink_and_bt_sco(u, data, *device, NULL, NULL, &combine_sink_arg1, &combine_sink_arg2);
+ }
+ }
+ return PA_HOOK_OK;
+}
+
+static pa_hook_result_t handle_auto_last_connected_routing(struct userdata *u, pa_stream_manager_hook_data_for_route *data,
+ hal_route_info *route_info, pa_idxset *conn_devices, pa_tz_device **device) {
+ pa_tz_device *latest_device = NULL;
+ const char *device_type = NULL;
+ const char *latest_device_type = NULL;
+ const char *dm_device_type = NULL;
+ dm_device_direction_t dm_device_direction = DM_DEVICE_DIRECTION_NONE;
+ uint32_t dm_device_id = 0;
+ uint32_t idx = 0;
+ uint32_t conn_idx = 0;
+ pa_usec_t creation_time = 0;
+ pa_usec_t latest_creation_time = 0;
+ bool use_internal_codec = false;
+ pa_sink *sink = NULL;
+
+ pa_assert(u);
+ pa_assert(data);
+ pa_assert(route_info);
+ pa_assert(conn_devices);
+ pa_assert(device);
+
+ PA_IDXSET_FOREACH(device_type, data->idx_avail_devices, idx) {
+ pa_log_debug("[ROUTE][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_usb_device(data->stream_role, *device))
+ continue;
+ if ((use_internal_codec = pa_tz_device_is_use_internal_codec(*device))) {
+ /* if it needs to skip it, keep going to next device for proper UCM setting */
+ if (skip_device(data->stream_role, dm_device_type) ||
+ skip_bt_sco_device(u, data->stream_role, dm_device_type))
+ 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)) {
+ 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 activated device if it is found */
+ if (latest_device) {
+ dm_device_type = pa_tz_device_get_type(latest_device);
+ dm_device_id = pa_tz_device_get_id(latest_device);
+ if ((use_internal_codec = pa_tz_device_is_use_internal_codec(latest_device)))
+ fill_device_info(route_info, dm_device_type, CONVERT_TO_HAL_DIRECTION(data->stream_type), dm_device_id);
+ else
+ pa_log_debug(" -- it does not use internal audio codec, skip it");
+
+ 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);
+
+ /* unload combine sink */
+ if (data->stream_type == STREAM_SINK_INPUT) {
+ if ((sink = pa_tz_device_get_sink(latest_device, data->device_role)))
+ unload_combine_sink_module(u, SINK_NAME_COMBINED, sink);
+ else
+ pa_log_error("[ROUTE][AUTO_LAST_CONN] could not get sink");
+ }
+
+ if (pa_safe_streq(dm_device_type, DEVICE_TYPE_BT_SCO)) {
+ if (IS_ROLE_AVAILABLE_BT_SCO_OPEN(route_info->role)) {
+ if (update_bt_sco_state(u, true, false, route_info->role)) {
+ pa_log_error(" ** could not open BT SCO");
+ return PA_HOOK_CANCEL;
+ }
+ update_bt_sco_option(u, route_info->role);
+ }
+ } else {
+ update_bt_sco_state(u, false, false, NULL);
+ }
+
+ /* Update device with latest_device to use be used later in this function */
+ *device = latest_device;
+ }
+
+ return PA_HOOK_OK;
+}
+
+static pa_hook_result_t handle_manual_routing(struct userdata *u, pa_stream_manager_hook_data_for_route *data,
+ hal_route_info *route_info, pa_tz_device **device) {
+ const char *device_type = NULL;
+ const char *dm_device_type = NULL;
+ dm_device_direction_t dm_device_direction = DM_DEVICE_DIRECTION_NONE;
+ bool use_internal_codec = false;
+ uint32_t idx = 0;
+ uint32_t d_idx = 0;
+ uint32_t *device_id = NULL;
+
+ pa_assert(u);
+ pa_assert(data);
+ pa_assert(route_info);
+ pa_assert(device);
+
+ PA_IDXSET_FOREACH(device_type, data->idx_avail_devices, idx) {
+ pa_log_info("[ROUTE][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, d_idx) {
+ pa_log_debug(" -- manual_device[%u] for this role[%-16s]: device_id(%u)", idx, data->stream_role, *device_id);
+ if (!(*device = pa_device_manager_get_device_by_id(u->device_manager, *device_id)))
+ continue;
+ dm_device_type = pa_tz_device_get_type(*device);
+ if (!pa_safe_streq(device_type, dm_device_type))
+ continue;
+ dm_device_direction = pa_tz_device_get_direction(*device);
+ pa_log_debug(" ** found a matched device: type[%-16s], direction[0x%x]",
+ dm_device_type, dm_device_direction);
+ /* Check for availability for opening Bluetooth SCO */
+ if (pa_safe_streq(dm_device_type, DEVICE_TYPE_BT_SCO) && IS_ROLE_AVAILABLE_BT_SCO_OPEN(route_info->role)) {
+ /* update BT SCO: open */
+ if (update_bt_sco_state(u, true, false, route_info->role)) {
+ pa_log_error(" ** could not open BT SCO");
+ return PA_HOOK_CANCEL;
+ }
+ update_bt_sco_option(u, route_info->role);
+ } else {
+ /* 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)))
+ fill_device_info(route_info, dm_device_type, CONVERT_TO_HAL_DIRECTION(data->stream_type), *device_id);
+ else
+ pa_log_debug(" -- it does not use internal audio codec, skip it");
+ }
+ }
+ }
+ 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;
+}
+
/* Change the route setting according to the data from argument.
* This function is called only when it needs to change routing path via HAL.
* - stream is null
* 2. Update the state of devices.
* 3. Call HAL API to apply the routing setting. */
static pa_hook_result_t route_change_hook_cb(pa_core *c, pa_stream_manager_hook_data_for_route *data, struct userdata *u) {
- uint32_t idx = 0;
hal_route_info route_info = {NULL, NULL, 0};
- uint32_t *device_id = NULL;
- uint32_t dm_device_id = 0;
- stream_route_type_t route_type;
- const char *device_type = NULL;
pa_tz_device *device = NULL;
- 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;
- bool use_internal_codec = false;
+ pa_hook_result_t result;
pa_assert(c);
pa_assert(data);
route_info.role = data->stream_role;
if (IS_AUTO_ROUTE_TYPE_SERIES(data->route_type)) {
- uint32_t conn_idx = 0;
pa_idxset *conn_devices = NULL;
/* unload module-loopback */
/* 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("[ROUTE][AUTO(_ALL)] avail_device[%u] for this role[%-16s]: type[%-16s]", idx, route_info.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_debug(" ** found a matched device: type[%-16s], direction[0x%x]", dm_device_type, dm_device_direction);
- if (skip_usb_device(data->stream_role, device))
- continue;
- use_internal_codec = pa_tz_device_is_use_internal_codec(device);
- if (use_internal_codec) {
- /* if it needs to skip it, keep going to next device for proper UCM setting */
- if (skip_device(data->stream_role, dm_device_type))
- continue;
- if (skip_bt_sco_device(u, data->stream_role, dm_device_type))
- continue;
- fill_device_info(&route_info, dm_device_type, CONVERT_TO_HAL_DIRECTION(data->stream_type), dm_device_id);
- } else
- pa_log_debug(" -- it does not use internal audio codec, skip it");
- break;
- }
- }
- if (device == 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);
-
- /* unload combine sink */
- if (data->stream_type == STREAM_SINK_INPUT) {
- if ((sink = pa_tz_device_get_sink(device, data->device_role)))
- unload_combine_sink_module(u, SINK_NAME_COMBINED, sink);
- else
- pa_log_error("[ROUTE][AUTO] could not get sink");
- }
-
- if (pa_safe_streq(dm_device_type, DEVICE_TYPE_BT_SCO)) {
- if (IS_ROLE_AVAILABLE_BT_SCO_OPEN(route_info.role)) {
- if (update_bt_sco_state(u, true, false, route_info.role)) {
- pa_log_error(" ** could not open BT SCO");
- return PA_HOOK_CANCEL;
- }
- update_bt_sco_option(u, route_info.role);
- }
- } else {
- update_bt_sco_state(u, false, false, NULL);
- }
-
- break;
- } else if (data->route_type == STREAM_ROUTE_TYPE_AUTO_ALL) {
- uint32_t s_idx = 0;
- void *s = NULL;
-
- update_bt_sco_state(u, false, false, NULL);
-
- /* find the proper sink/source */
- /* currently, we support two sinks for combining */
- if (data->stream_type == STREAM_SINK_INPUT && u->module_combine_sink) {
- sink = (pa_sink*)pa_namereg_get(u->core, SINK_NAME_COMBINED, PA_NAMEREG_SINK);
- pa_log_info("[ROUTE][AUTO_ALL] found the combine_sink already existed");
- } else if (data->stream_type == STREAM_SINK_INPUT && !combine_sink_arg1) {
- sink = combine_sink_arg1 = pa_tz_device_get_sink(device, data->device_role);
- if (sink)
- pa_log_info("[ROUTE][AUTO_ALL] combine_sink_arg1[%s], combine_sink_arg2[%p]", sink->name, combine_sink_arg2);
- else
- pa_log_error("[ROUTE][AUTO_ALL] could not get sink from pa_device_manager_get_sink");
- } else if (data->stream_type == STREAM_SINK_INPUT && !combine_sink_arg2) {
- sink = combine_sink_arg2 = pa_tz_device_get_sink(device, data->device_role);
- if (sink && !pa_safe_streq(sink->name, combine_sink_arg1->name)) {
- pa_log_info("[ROUTE][AUTO_ALL] combine_sink_arg2[%s]", sink->name);
- /* load combine sink */
- if (!u->module_combine_sink) {
- char *args = pa_sprintf_malloc("sink_name=%s slaves=\"%s,%s\"", SINK_NAME_COMBINED, combine_sink_arg1->name, combine_sink_arg2->name);
- pa_log_info("[ROUTE][AUTO_ALL] combined sink is not prepared, now load module[%s]", args);
- u->module_combine_sink = pa_module_load(u->core, MODULE_COMBINE_SINK, args);
- pa_xfree(args);
- }
- if ((sink = (pa_sink*)pa_namereg_get(u->core, SINK_NAME_COMBINED, PA_NAMEREG_SINK))) {
- PA_IDXSET_FOREACH(s, combine_sink_arg1->inputs, s_idx) {
- if (s == data->stream) {
- pa_sink_input_move_to(s, sink, false);
- pa_log_info("[ROUTE][AUTO_ALL] *** sink-nput(%p,%u) moves to sink(%p,%s)",
- s, ((pa_sink_input*)s)->index, sink, sink->name);
- }
- }
- } else
- pa_log_error("[ROUTE][AUTO_ALL] could not get combine_sink");
- }
- } else if (data->stream_type == STREAM_SOURCE_OUTPUT)
- source = pa_tz_device_get_source(device, data->device_role);
+ if ((result = handle_auto_or_auto_all_routing(u, data, &route_info, conn_devices, &device)))
+ return result;
- if (data->origins_from_new_data) {
- if (data->stream_type == STREAM_SINK_INPUT)
- *(data->proper_sink) = sink;
- else
- *(data->proper_source) = source;
- } else {
- /* move sink-inputs/source-outputs if needed */
- if (!data->idx_streams)
- continue;
- PA_IDXSET_FOREACH(s, data->idx_streams, s_idx) { /* data->idx_streams: null_sink */
- if (pa_stream_manager_get_route_type(s, data->stream_type, false, &route_type))
- continue;
- if (route_type != STREAM_ROUTE_TYPE_AUTO_ALL)
- continue;
- if ((data->stream_type == STREAM_SINK_INPUT) && (sink && (sink != ((pa_sink_input*)s)->sink))) {
- pa_sink_input_move_to(s, sink, false);
- pa_log_info("[ROUTE][AUTO_ALL] *** sink-input(%p,%u) moves to sink(%p,%s)",
- s, ((pa_sink_input*)s)->index, sink, sink->name);
- } else if ((data->stream_type == STREAM_SOURCE_OUTPUT) && (source && (source != ((pa_source_output*)s)->source))) {
- pa_source_output_move_to(s, source, false);
- pa_log_info("[ROUTE][AUTO_ALL] *** source-output(%p,%u) moves to source(%p,%s)",
- s, ((pa_source_output*)s)->index, source, source->name);
- }
- }
- }
- }
- }
} 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("[ROUTE][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_usb_device(data->stream_role, device))
- continue;
- use_internal_codec = pa_tz_device_is_use_internal_codec(device);
- if (use_internal_codec) {
- /* if it needs to skip it, keep going to next device for proper UCM setting */
- if (skip_device(data->stream_role, dm_device_type))
- continue;
- if (skip_bt_sco_device(u, data->stream_role, dm_device_type))
- 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)) {
- 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 activated device if it is found */
- if (latest_device) {
- dm_device_type = pa_tz_device_get_type(latest_device);
- dm_device_id = pa_tz_device_get_id(latest_device);
- use_internal_codec = pa_tz_device_is_use_internal_codec(latest_device);
- if (use_internal_codec)
- fill_device_info(&route_info, dm_device_type, CONVERT_TO_HAL_DIRECTION(data->stream_type), dm_device_id);
- else
- pa_log_debug(" -- it does not use internal audio codec, skip it");
-
- 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);
-
- /* unload combine sink */
- if (data->stream_type == STREAM_SINK_INPUT) {
- if ((sink = pa_tz_device_get_sink(latest_device, data->device_role)))
- unload_combine_sink_module(u, SINK_NAME_COMBINED, sink);
- else
- pa_log_error("[ROUTE][AUTO_LAST_CONN] could not get sink");
- }
-
- if (pa_safe_streq(dm_device_type, DEVICE_TYPE_BT_SCO)) {
- if (IS_ROLE_AVAILABLE_BT_SCO_OPEN(route_info.role)) {
- if (update_bt_sco_state(u, true, false, route_info.role)) {
- pa_log_error(" ** could not open BT SCO");
- return PA_HOOK_CANCEL;
- }
- update_bt_sco_option(u, route_info.role);
- }
- } else {
- update_bt_sco_state(u, false, false, NULL);
- }
-
- /* Update device with latest_device to use be used later in this function */
- device = latest_device;
- }
+ if ((result = handle_auto_last_connected_routing(u, data, &route_info, conn_devices, &device)))
+ return result;
}
} else if (data->route_type == STREAM_ROUTE_TYPE_MANUAL) {
- uint32_t d_idx = 0;
-
- PA_IDXSET_FOREACH(device_type, data->idx_avail_devices, idx) {
- pa_log_info("[ROUTE][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, d_idx) {
- pa_log_debug(" -- manual_device[%u] for this role[%-16s]: device_id(%u)", idx, data->stream_role, *device_id);
- if (!(device = pa_device_manager_get_device_by_id(u->device_manager, *device_id)))
- continue;
- dm_device_type = pa_tz_device_get_type(device);
- if (!pa_safe_streq(device_type, dm_device_type))
- continue;
- dm_device_direction = pa_tz_device_get_direction(device);
- pa_log_debug(" ** found a matched device: type[%-16s], direction[0x%x]",
- dm_device_type, dm_device_direction);
- /* Check for availability for opening Bluetooth SCO */
- if (pa_safe_streq(dm_device_type, DEVICE_TYPE_BT_SCO) && IS_ROLE_AVAILABLE_BT_SCO_OPEN(route_info.role)) {
- /* update BT SCO: open */
- if (update_bt_sco_state(u, true, false, route_info.role)) {
- pa_log_error(" ** could not open BT SCO");
- return PA_HOOK_CANCEL;
- }
- update_bt_sco_option(u, route_info.role);
- } else {
- /* 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)) {
- use_internal_codec = pa_tz_device_is_use_internal_codec(device);
- if (use_internal_codec)
- fill_device_info(&route_info, dm_device_type, CONVERT_TO_HAL_DIRECTION(data->stream_type), *device_id);
- else
- pa_log_debug(" -- it does not use internal audio codec, skip it");
- }
- }
- }
- 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);
- }
+ if ((result = handle_manual_routing(u, data, &route_info, &device)))
+ return result;
}
route_change_move_streams(u, data, device);