PA_COMMUNICATOR_HOOK_UPDATE_ROUTE_OPTION,
PA_COMMUNICATOR_HOOK_DEVICE_CONNECTION_CHANGED,
PA_COMMUNICATOR_HOOK_DEVICE_INFORMATION_CHANGED,
- PA_COMMUNICATOR_HOOK_NEED_UPDATE_ROUTE,
PA_COMMUNICATOR_HOOK_MAX
} pa_communicator_hook_t;
h->intf.pcm_write = dlsym(h->dl_handle, "audio_pcm_write");
h->intf.pcm_read = dlsym(h->dl_handle, "audio_pcm_read");
if (h->intf.init) {
- /* TODO : no need to pass platform_data as second param. need to fix hal. */
- if (h->intf.init(&h->data) != AUDIO_RET_OK) {
+ if (h->intf.init(&h->data) != AUDIO_RET_OK)
pa_log_error("hal_manager init failed");
- }
}
} else {
/* Modules for dynamic loading */
#define MODULE_COMBINE_SINK "module-combine-sink"
+#define MODULE_NULL_SINK "module-null-sink"
+#define MODULE_NULL_SOURCE "module-null-source"
-/* Sink & Source names */
-#define SINK_COMBINED "sink_combined"
-#define SINK_COMBINED_EX "sink_combined_ex"
-#define SINK_NULL "sink_null"
-#define SOURCE_NULL "source_null"
+/* Name of combine sink for external route type */
+#define SINK_NAME_COMBINED_EX SINK_NAME_COMBINED"_ex"
/* Macros */
#define CONVERT_TO_DEVICE_DIRECTION(stream_type)\
pa_module *module_null_source;
};
-static void _set_device_state(dm_device *device, stream_type_t stream_type, dm_device_state_t device_state);
-
static void __load_dump_config(struct userdata *u)
{
dictionary * dict = NULL;
pa_log_info("[SELECT] select_proper_sink_or_source_hook_cb is called. (%p), stream_type(%d), stream_role(%s), route_type(%d)",
data, data->stream_type, data->stream_role, data->route_type);
- null_sink = (pa_sink*)pa_namereg_get(u->core, SINK_NULL, PA_NAMEREG_SINK);
- null_source = (pa_source*)pa_namereg_get(u->core, SOURCE_NULL, PA_NAMEREG_SOURCE);
+ null_sink = (pa_sink*)pa_namereg_get(u->core, SINK_NAME_NULL, PA_NAMEREG_SINK);
+ null_source = (pa_source*)pa_namereg_get(u->core, SOURCE_NAME_NULL, PA_NAMEREG_SOURCE);
if (!null_sink || !null_source) {
pa_log_error("[SELECT] could not get null_sink(%p) or null_source(%p)", null_sink, null_source);
return PA_HOOK_OK;
is_found = TRUE;
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_COMBINED, PA_NAMEREG_SINK);
+ *(data->proper_sink) = (pa_sink*)pa_namereg_get(u->core, SINK_NAME_COMBINED, PA_NAMEREG_SINK);
pa_log_debug(" -- found the combine-sink, set it to the sink");
} else
*(data->proper_sink) = pa_device_manager_get_sink(device, DEVICE_ROLE_NORMAL);
pa_log_debug (" -- combine_sink_arg2[%s]", sink->name);
/* load combine sink */
if (!u->module_combine_sink_for_ex) {
- args = pa_sprintf_malloc("sink_name=%s slaves=\"%s,%s\"", SINK_COMBINED_EX, combine_sink_arg1->name, combine_sink_arg2->name);
+ args = pa_sprintf_malloc("sink_name=%s slaves=\"%s,%s\"", SINK_NAME_COMBINED_EX, combine_sink_arg1->name, combine_sink_arg2->name);
pa_log_debug (" -- 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_COMBINED_EX, PA_NAMEREG_SINK);
+ 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 (s == data->stream) {
pa_sink_input_move_to(s, sink, FALSE);
/* The state of a device using internal audio codec is handled here.
* Regarding the state of an external device, those is handled in device-manager.c */
-static void _set_device_state(dm_device *device, stream_type_t stream_type, dm_device_state_t device_state) {
+static void set_device_state_if_using_internal_codec(dm_device *device, stream_type_t stream_type, dm_device_state_t device_state) {
pa_bool_t use_internal_codec = FALSE;
pa_assert(device);
- use_internal_codec = pa_device_manager_is_device_use_internal_codec(device, CONVERT_TO_DEVICE_DIRECTION(stream_type), DEVICE_ROLE_NORMAL);
- if (use_internal_codec)
+ if ((use_internal_codec = pa_device_manager_is_device_use_internal_codec(device, CONVERT_TO_DEVICE_DIRECTION(stream_type), DEVICE_ROLE_NORMAL)))
pa_device_manager_set_device_state(device, CONVERT_TO_DEVICE_DIRECTION(stream_type), device_state);
return;
}
/* Open/Close BT SCO if it is possible */
-static int _set_bt_sco_state(pa_device_manager *dm, pa_bool_t open) {
+static int set_bt_sco_state(pa_device_manager *dm, pa_bool_t open) {
dm_device_bt_sco_status_t sco_status;
pa_assert(dm);
if (pa_streq(data->stream_role, "reset")) {
/* update BT SCO: close */
- _set_bt_sco_state(u->device_manager, FALSE);
+ set_bt_sco_state(u->device_manager, FALSE);
/* get current connected devices */
conn_devices = pa_device_manager_get_device_list(u->device_manager);
device_direction = pa_device_manager_get_device_direction(device);
if (device_state == DM_DEVICE_STATE_ACTIVATED && IS_AVAILABLE_DIRECTION(data->stream_type, device_direction)) {
pa_log_debug("[ROUTE][RESET] found a matched device and set state to DE-ACTIVATED: type[%s], direction[0x%x]", dm_device_type, device_direction);
- _set_device_state(device, data->stream_type, DM_DEVICE_STATE_DEACTIVATED);
+ set_device_state_if_using_internal_codec(device, data->stream_type, DM_DEVICE_STATE_DEACTIVATED);
}
}
route_info.num_of_devices = 1;
/* unload combine sink */
if (data->stream_type==STREAM_SINK_INPUT && u->module_combine_sink) {
- pa_log_debug ("[ROUTE][RESET] unload module[%s]", SINK_COMBINED);
- combine_sink = (pa_sink*)pa_namereg_get(u->core, SINK_COMBINED, PA_NAMEREG_SINK);
- null_sink = (pa_sink*)pa_namereg_get(u->core, SINK_NULL, PA_NAMEREG_SINK);
+ pa_log_debug ("[ROUTE][RESET] unload module[%s]", SINK_NAME_COMBINED);
+ combine_sink = (pa_sink*)pa_namereg_get(u->core, SINK_NAME_COMBINED, PA_NAMEREG_SINK);
+ null_sink = (pa_sink*)pa_namereg_get(u->core, SINK_NAME_NULL, PA_NAMEREG_SINK);
if (!combine_sink || !null_sink)
pa_log_error("[ROUTE][RESET] could not get combine_sink(%p) or null_sink(%p)", combine_sink, null_sink);
else {
} else if ((data->route_type == STREAM_ROUTE_TYPE_AUTO || data->route_type == STREAM_ROUTE_TYPE_AUTO_ALL) && data->idx_avail_devices) {
/* update BT SCO: close */
- _set_bt_sco_state(u->device_manager, FALSE);
+ set_bt_sco_state(u->device_manager, FALSE);
/* get current connected devices */
conn_devices = pa_device_manager_get_device_list(u->device_manager);
pa_log_debug(" ** found a matched device and set state to ACTIVATED: type[%-16s], direction[0x%x], id[%u]",
route_info.device_infos[route_info.num_of_devices-1].type, device_direction, device_idx);
/* set device state to activated */
- _set_device_state(device, data->stream_type, DM_DEVICE_STATE_ACTIVATED);
+ set_device_state_if_using_internal_codec(device, data->stream_type, DM_DEVICE_STATE_ACTIVATED);
} else
pa_log_debug(" -- it does not use internal audio codec, skip it");
break;
PA_IDXSET_FOREACH(_device, conn_devices, conn_idx) {
if (device == _device)
continue;
- _set_device_state(_device, data->stream_type, DM_DEVICE_STATE_DEACTIVATED);
+ set_device_state_if_using_internal_codec(_device, data->stream_type, DM_DEVICE_STATE_DEACTIVATED);
}
}
/* unload combine sink */
if (data->stream_type==STREAM_SINK_INPUT && u->module_combine_sink) {
- if ((combine_sink = (pa_sink*)pa_namereg_get(u->core, SINK_COMBINED, PA_NAMEREG_SINK))) {
+ if ((combine_sink = (pa_sink*)pa_namereg_get(u->core, SINK_NAME_COMBINED, PA_NAMEREG_SINK))) {
PA_IDXSET_FOREACH (s, combine_sink->inputs, s_idx) {
pa_sink_input_move_to(s, sink, FALSE);
pa_log_debug("[ROUTE][AUTO] *** sink-input(%p,%u) moves to sink(%p,%s)", s, ((pa_sink_input*)s)->index, sink, sink->name);
} else
pa_log_error("[ROUTE][AUTO] could not get combine_sink");
- pa_log_debug ("[ROUTE][AUTO] unload module[%s]", SINK_COMBINED);
+ pa_log_debug ("[ROUTE][AUTO] unload module[%s]", SINK_NAME_COMBINED);
pa_module_unload(u->core, u->module_combine_sink, TRUE);
u->module_combine_sink = 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_COMBINED, PA_NAMEREG_SINK);
+ sink = (pa_sink*)pa_namereg_get(u->core, SINK_NAME_COMBINED, PA_NAMEREG_SINK);
pa_log_debug ("[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_device_manager_get_sink(device, DEVICE_ROLE_NORMAL);
pa_log_debug ("[ROUTE][AUTO_ALL] combine_sink_arg2[%s]", sink->name);
/* load combine sink */
if (!u->module_combine_sink) {
- args = pa_sprintf_malloc("sink_name=%s slaves=\"%s,%s\"", SINK_COMBINED, combine_sink_arg1->name, combine_sink_arg2->name);
+ args = pa_sprintf_malloc("sink_name=%s slaves=\"%s,%s\"", SINK_NAME_COMBINED, combine_sink_arg1->name, combine_sink_arg2->name);
pa_log_debug ("[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);
}
- sink = (pa_sink*)pa_namereg_get(u->core, SINK_COMBINED, PA_NAMEREG_SINK);
+ 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);
}
}
if (need_to_deactive)
- _set_device_state(_device, data->stream_type, DM_DEVICE_STATE_DEACTIVATED);
+ set_device_state_if_using_internal_codec(_device, data->stream_type, DM_DEVICE_STATE_DEACTIVATED);
}
}
pa_log_debug(" ** found a matched device: type[%-16s]", device_type);
if (pa_streq(dm_device_type, DEVICE_TYPE_BT)) {
/* update BT SCO: open */
- if (_set_bt_sco_state(u->device_manager, TRUE)) {
+ if (set_bt_sco_state(u->device_manager, TRUE)) {
pa_log_error(" ** could not open BT SCO");
continue;
}
} else {
/* update BT SCO: close */
- _set_bt_sco_state(u->device_manager, FALSE);
+ set_bt_sco_state(u->device_manager, FALSE);
}
device_direction = pa_device_manager_get_device_direction(device);
dm_device_subtype = pa_device_manager_get_device_subtype(device);
pa_log_debug(" ** found a matched device and set state to ACTIVATED: type[%-16s], direction[0x%x]",
route_info.device_infos[route_info.num_of_devices-1].type, device_direction);
/* set device state to activated */
- _set_device_state(device, data->stream_type, DM_DEVICE_STATE_ACTIVATED);
+ set_device_state_if_using_internal_codec(device, data->stream_type, DM_DEVICE_STATE_ACTIVATED);
} else
pa_log_debug(" -- it does not use internal audio codec, skip it");
}
return PA_HOOK_OK;
}
-#define MAX_CACHED_LEN 128
-typedef struct _cached_device_list {
- const char *device_type;
- int count;
-} cached_device_list;
-
-static void update_sink_or_source_as_device_connection_change(stream_route_type_t stream_route_type, stream_type_t stream_type, pa_idxset *streams, dm_device *device, pa_bool_t is_connected, struct userdata *u) {
- void *s = NULL;
- uint32_t s_idx = 0;
- const char *role = NULL;
- const char *device_type = NULL;
- const char *cur_device_type = NULL;
- const char *init_device_type = NULL;
- char *next_device_type = NULL;
- dm_device *next_device = NULL;
- dm_device *_device = NULL;
- stream_route_type_t route_type;
- pa_sink *sink = NULL;
- pa_sink *next_sink = NULL;
- pa_sink *null_sink = NULL;
- pa_source *source = NULL;
- pa_source *next_source = NULL;
- pa_source *null_source = NULL;
- pa_bool_t available = FALSE;
- pa_bool_t use_internal_codec = FALSE;
- cached_device_list cached_prev_dev_list[MAX_CACHED_LEN] = {{NULL,0},};
- uint32_t cnt = 0;
- pa_sink *combine_sink = NULL;
- pa_stream_manager_hook_data_for_update_route hook_call_update_route_data;
-
- pa_assert(streams);
- pa_assert(device);
- pa_assert(u);
-
- null_sink = (pa_sink*)pa_namereg_get(u->core, SINK_NULL, PA_NAMEREG_SINK);
- null_source = (pa_source*)pa_namereg_get(u->core, SOURCE_NULL, PA_NAMEREG_SOURCE);
- if (!null_sink || !null_source) {
- pa_log_error("[UPDATE_SINK_SOURCE] could not get null_sink(%p) or null_source(%p)", null_sink, null_source);
- return;
- }
- device_type = pa_device_manager_get_device_type(device);
-
- if (stream_route_type == STREAM_ROUTE_TYPE_AUTO) {
- pa_log_debug("[UPDATE_SINK_SOURCE][AUTO] deivce_type(%s), is_connected(%d))", device_type, is_connected);
- if (stream_type == STREAM_SINK_INPUT)
- sink = pa_device_manager_get_sink(device, DEVICE_ROLE_NORMAL);
- else
- source = pa_device_manager_get_source(device, DEVICE_ROLE_NORMAL);
-
- PA_IDXSET_FOREACH (s, streams, s_idx) { /* streams: core->source_outputs/core->sink_inputs */
- if (!pa_stream_manager_get_route_type(s, FALSE, stream_type, &route_type) && (route_type == stream_route_type)) {
- role = pa_proplist_gets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_ROLE);
- pa_log_debug(" -- idx(%u), route_type(%d), role(%s)", s_idx, route_type, role);
- if (is_connected) {
- /* CONNECTED: move a stream to the new device if possible */
- if (sink && (sink != ((pa_sink_input*)s)->sink)) {
- if ((cur_device_type = pa_proplist_gets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV))) {
- pa_stream_manager_is_available_device_for_auto_route(cur_device_type, device_type, role, stream_type, &available, u->stream_manager);
- if (available) {
- pa_sink_input_move_to(s, sink, FALSE);
- pa_log_debug(" -- *** sink-input(%p,%u) moves to sink(%p,%s), new device(%s)",
- s, ((pa_sink_input*)s)->index, sink, sink->name, device_type);
- use_internal_codec = sink->use_internal_codec;
- }
- } else
- pa_log_error(" -- could not find current device type for s->sink(%p)", ((pa_sink_input*)s)->sink);
- } else if (source && (source != ((pa_source_output*)s)->source)) {
- if ((cur_device_type = pa_proplist_gets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV))) {
- pa_stream_manager_is_available_device_for_auto_route(cur_device_type, device_type, role, stream_type, &available, u->stream_manager);
- if (available) {
- pa_source_output_move_to(s, source, FALSE);
- pa_log_debug(" -- *** source-output(%p,%u) moves to source(%p,%s), new device(%s)",
- s, ((pa_source_output*)s)->index, source, source->name, device_type);
- use_internal_codec = source->use_internal_codec;
- }
- } else
- pa_log_error(" -- could not find current device type for s->source(%p)", ((pa_source_output*)s)->source);
- }
- if (available) {
- /* update activated device */
- pa_proplist_sets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, device_type);
- if ((_device = pa_device_manager_get_device(u->device_manager, device_type)))
- _set_device_state(_device, stream_type, DM_DEVICE_STATE_ACTIVATED);
- cached_prev_dev_list[cnt++].device_type = cur_device_type;
- /* trigger to update routing path */
- memset(&hook_call_update_route_data, 0, sizeof(pa_stream_manager_hook_data_for_update_route));
- hook_call_update_route_data.stream = s;
- hook_call_update_route_data.stream_type = stream_type;
- hook_call_update_route_data.is_device_connected = is_connected;
- hook_call_update_route_data.use_internal_codec = use_internal_codec;
- pa_hook_fire(pa_communicator_hook(u->communicator.comm, PA_COMMUNICATOR_HOOK_NEED_UPDATE_ROUTE), &hook_call_update_route_data);
- }
- } else if (!is_connected) {
- /* DISCONNECTED: find a connected device that has the next priority */
- if (sink && (sink == ((pa_sink_input*)s)->sink)) {
- init_device_type = device_type;
- do {
- pa_stream_manager_find_next_priority_device_for_auto_route(device_type, role, stream_type, &next_device_type, u->stream_manager);
- pa_log_debug(" -- prev_device(%s), new_device(%s)", device_type, next_device_type);
- if (next_device_type) {
- if ((next_device = pa_device_manager_get_device(u->device_manager, next_device_type))) {
- if ((next_sink = pa_device_manager_get_sink(next_device, DEVICE_ROLE_NORMAL))) {
- /* update activated device */
- pa_proplist_sets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, next_device_type);
- _set_device_state(next_device, stream_type, DM_DEVICE_STATE_ACTIVATED);
- cached_prev_dev_list[cnt++].device_type = init_device_type;
- /* trigger to update routing path if the next device uses internal audio codec */
- if (next_sink->use_internal_codec) {
- memset(&hook_call_update_route_data, 0, sizeof(pa_stream_manager_hook_data_for_update_route));
- hook_call_update_route_data.stream = s;
- hook_call_update_route_data.stream_type = stream_type;
- hook_call_update_route_data.is_device_connected = is_connected;
- hook_call_update_route_data.use_internal_codec = next_sink->use_internal_codec;
- pa_hook_fire(pa_communicator_hook(u->communicator.comm, PA_COMMUNICATOR_HOOK_NEED_UPDATE_ROUTE), &hook_call_update_route_data);
- }
- pa_sink_input_move_to(s, next_sink, FALSE);
- pa_log_debug(" -- *** sink-input(%p,%u) moves to sink(%p,%s), new device(%s)",
- s, ((pa_sink_input*)s)->index, next_sink, next_sink->name, next_device_type);
- break;
- }
- } else {
- device_type = next_device_type;
- continue;
- }
- }
- } while (next_device_type);
-
- if (!next_device_type || !next_sink) {
- pa_sink_input_move_to(s, null_sink, FALSE);
- pa_log_debug(" -- *** sink-input(%p,%u) moves to sink(%p,%s)",
- s, ((pa_sink_input*)s)->index, null_sink, null_sink->name);
- }
-
- } else if (source && (source == ((pa_source_output*)s)->source)) {
- init_device_type = device_type;
- do {
- pa_stream_manager_find_next_priority_device_for_auto_route(device_type, role, stream_type, &next_device_type, u->stream_manager);
- pa_log_debug(" -- prev_device(%s), new_device(%s)", device_type, next_device_type);
- if (next_device_type) {
- if ((next_device = pa_device_manager_get_device(u->device_manager, next_device_type))) {
- if ((next_source = pa_device_manager_get_source(next_device, DEVICE_ROLE_NORMAL))) {
- /* update activated device */
- pa_proplist_sets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, next_device_type);
- _set_device_state(next_device, stream_type, DM_DEVICE_STATE_ACTIVATED);
- cached_prev_dev_list[cnt++].device_type = init_device_type;
- /* trigger to update routing path if the next device uses internal audio codec */
- if (next_source->use_internal_codec) {
- memset(&hook_call_update_route_data, 0, sizeof(pa_stream_manager_hook_data_for_update_route));
- hook_call_update_route_data.stream = s;
- hook_call_update_route_data.stream_type = stream_type;
- hook_call_update_route_data.is_device_connected = is_connected;
- hook_call_update_route_data.use_internal_codec = next_sink->use_internal_codec;
- pa_hook_fire(pa_communicator_hook(u->communicator.comm, PA_COMMUNICATOR_HOOK_NEED_UPDATE_ROUTE), &hook_call_update_route_data);
- }
- pa_source_output_move_to(s, next_source, FALSE);
- pa_log_debug(" -- *** source-output(%p,%u) moves to source(%p,%s), new device(%s)",
- s, ((pa_source_output*)s)->index, next_source, next_source->name, next_device_type);
- break;
- }
- } else {
- device_type = next_device_type;
- continue;
- }
- }
- } while (next_device_type);
-
- if (!next_device_type || !next_source) {
- pa_source_output_move_to(s, null_source, FALSE);
- pa_log_debug(" -- *** source-output(%p,%u) moves to source(%p,%s)",
- s, ((pa_source_output*)s)->index, null_source, null_source->name);
- }
- }
- }
- }
- }
-
- /* set device state to deactivated */
- if (cnt) {
- PA_IDXSET_FOREACH (s, streams, s_idx) { /* streams: core->source_outputs/core->sink_inputs */
- if ((cur_device_type = pa_proplist_gets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV))) {
- for (cnt = 0; cached_prev_dev_list[cnt].device_type; cnt++) {
- pa_log_warn(" -- cur_device(%s), cached_device(%s)", cur_device_type, cached_prev_dev_list[cnt].device_type);
- if (pa_streq(cur_device_type, cached_prev_dev_list[cnt].device_type))
- cached_prev_dev_list[cnt].count++;
- }
- }
- }
- if (stream_type == STREAM_SINK_INPUT) {
- combine_sink = (pa_sink*)pa_namereg_get(u->core, SINK_COMBINED, PA_NAMEREG_SINK);
- if (combine_sink && pa_idxset_size(combine_sink->inputs)) {
- pa_log_warn(" -- combine sink has streams, skip it..");
- return;
- }
- }
- for (cnt = 0; cached_prev_dev_list[cnt].device_type; cnt++) {
- if (cached_prev_dev_list[cnt].count == 0) {
- pa_log_debug(" -- device_type(%s)", cached_prev_dev_list[cnt].device_type);
- _device = pa_device_manager_get_device(u->device_manager, cached_prev_dev_list[cnt].device_type);
- if (_device)
- _set_device_state(_device, stream_type, DM_DEVICE_STATE_DEACTIVATED);
- else
- pa_log_warn(" -- _device is null");
- }
- }
- }
-
- } else if (stream_route_type == STREAM_ROUTE_TYPE_MANUAL_EXT) {
- pa_log_debug("[UPDATE_SINK_SOURCE][EXT] deivce_type(%s), is_connected(%d))", device_type, is_connected);
- if (!is_connected) {
- PA_IDXSET_FOREACH (s, streams, s_idx) { /* streams: source->outputs/sink->inputs */
- if (!pa_stream_manager_get_route_type(s, FALSE, stream_type, &route_type) && route_type == stream_route_type) {
- if (stream_type == STREAM_SOURCE_OUTPUT) {
- /* move it to null source if this role is for external device */
- pa_source_output_move_to((pa_source_output*)s, null_source, FALSE);
- pa_log_debug(" -- *** source-output(%p,%u) moves to source(%p,%s)", s, ((pa_source_output*)s)->index, null_source, null_source->name);
- } else {
- /* move it to null sink if this role is for external device */
- pa_sink_input_move_to((pa_sink_input*)s, null_sink, FALSE);
- pa_log_debug(" -- *** sink-input(%p,%u) moves to sink(%p,%s)", s, ((pa_sink_input*)s)->index, null_sink, null_sink->name);
- }
- }
- }
- } else {
- /* do nothing, it will be updated by stream-manager */
- }
- } else
- pa_log_error("[UPDATE_SINK_SOURCE] could not handle it here, stream_route_type(%d)", stream_route_type);
-
- return;
-}
-
/* Reorganize routing when a device has been connected or disconnected */
static pa_hook_result_t device_connection_changed_hook_cb(pa_core *c, pa_device_manager_hook_data_for_conn_changed *conn, struct userdata *u) {
uint32_t idx = 0;
dm_device_direction_t device_direction = DM_DEVICE_DIRECTION_OUT;
pa_sink *sink = NULL;
pa_sink *null_sink = NULL;
- pa_source *source = NULL;
- pa_source *null_source = NULL;
pa_sink *combine_sink = NULL;
pa_bool_t use_internal_codec = FALSE;
pa_idxset* conn_devices = NULL;
pa_log_info("[CONN] device_connection_changed_hook_cb is called. conn(%p), is_connected(%d), device(%p), direction(0x%x)",
conn, conn->is_connected, conn->device, device_direction);
- null_sink = (pa_sink*)pa_namereg_get(u->core, SINK_NULL, PA_NAMEREG_SINK);
- null_source = (pa_source*)pa_namereg_get(u->core, SOURCE_NULL, PA_NAMEREG_SOURCE);
- if (!null_sink || !null_source) {
- pa_log_error("[CONN] could not get null_sink(%p) or null_source(%p)", null_sink, null_source);
+ null_sink = (pa_sink*)pa_namereg_get(u->core, SINK_NAME_NULL, PA_NAMEREG_SINK);
+ if (!null_sink) {
+ pa_log_error("[CONN] could not get null_sink(%p)", null_sink);
return PA_HOOK_OK;
}
use_internal_codec = pa_device_manager_is_device_use_internal_codec(conn->device, device_direction, DEVICE_ROLE_NORMAL);
- if (!use_internal_codec) {
- /* EXTERNAL AUDIO CODEC */
- if (!conn->is_connected && (device_direction & DM_DEVICE_DIRECTION_OUT)) {
- if (u->module_combine_sink) {
- /* unload combine sink */
- if ((combine_sink = (pa_sink*)pa_namereg_get(u->core, SINK_COMBINED, PA_NAMEREG_SINK))) {
- conn_devices = pa_device_manager_get_device_list(u->device_manager);
- PA_IDXSET_FOREACH(device, conn_devices, idx) {
- device_direction = pa_device_manager_get_device_direction(device);
- if (device_direction == DM_DEVICE_DIRECTION_OUT) {
- use_internal_codec = pa_device_manager_is_device_use_internal_codec(device, device_direction, DEVICE_ROLE_NORMAL);
- if (use_internal_codec) {
- sink = pa_device_manager_get_sink(device, DEVICE_ROLE_NORMAL);
- break;
- }
- }
- }
- if (combine_sink->inputs) {
- if (!sink)
- sink = null_sink;
- PA_IDXSET_FOREACH (s, combine_sink->inputs, idx) {
- /* re-route this stream to the remaining device using internal codec */
- pa_sink_input_move_to(s, sink, FALSE);
- pa_log_debug("[CONN] *** sink-input(%p,%u) moves to sink(%p,%s)", s, ((pa_sink_input*)s)->index, sink, sink->name);
+ /* update for using combine sink case when external device is disconnected */
+ if (!use_internal_codec && !conn->is_connected && (device_direction & DM_DEVICE_DIRECTION_OUT)) {
+ if (u->module_combine_sink) {
+ /* unload combine sink */
+ if ((combine_sink = (pa_sink*)pa_namereg_get(u->core, SINK_NAME_COMBINED, PA_NAMEREG_SINK))) {
+ conn_devices = pa_device_manager_get_device_list(u->device_manager);
+ PA_IDXSET_FOREACH(device, conn_devices, idx) {
+ device_direction = pa_device_manager_get_device_direction(device);
+ if (device_direction == DM_DEVICE_DIRECTION_OUT) {
+ use_internal_codec = pa_device_manager_is_device_use_internal_codec(device, device_direction, DEVICE_ROLE_NORMAL);
+ if (use_internal_codec) {
+ sink = pa_device_manager_get_sink(device, DEVICE_ROLE_NORMAL);
+ break;
}
}
- pa_sink_suspend(combine_sink, TRUE, PA_SUSPEND_USER);
- pa_module_unload(u->core, u->module_combine_sink, TRUE);
- u->module_combine_sink = NULL;
- } else
- pa_log_error("[CONN] could not get combine_sink");
- }
- if (u->module_combine_sink_for_ex) {
- /* unload combine sink for external devices */
- if ((combine_sink = (pa_sink*)pa_namereg_get(u->core, SINK_COMBINED_EX, PA_NAMEREG_SINK))) {
- if (combine_sink->inputs) {
- PA_IDXSET_FOREACH (s, combine_sink->inputs, idx) {
- pa_sink_input_move_to(s, null_sink, FALSE);
- pa_log_debug("[CONN] *** sink-input(%p,%u) moves to sink(%p,%s)", s, ((pa_sink_input*)s)->index, null_sink, null_sink->name);
- }
+ }
+ if (combine_sink->inputs) {
+ if (!sink)
+ sink = null_sink;
+ PA_IDXSET_FOREACH (s, combine_sink->inputs, idx) {
+ /* re-route this stream to the remaining device using internal codec */
+ pa_sink_input_move_to(s, sink, FALSE);
+ pa_log_debug("[CONN] *** sink-input(%p,%u) moves to sink(%p,%s)", s, ((pa_sink_input*)s)->index, sink, sink->name);
}
- pa_sink_suspend(combine_sink, TRUE, PA_SUSPEND_USER);
- pa_module_unload(u->core, u->module_combine_sink_for_ex, TRUE);
- u->module_combine_sink_for_ex = NULL;
- } else
- pa_log_error("[CONN] could not get combine_sink_ex");
- }
- }
- if (device_direction & DM_DEVICE_DIRECTION_IN) {
- if ((source = pa_device_manager_get_source(conn->device, DEVICE_ROLE_NORMAL)))
- update_sink_or_source_as_device_connection_change(STREAM_ROUTE_TYPE_MANUAL_EXT, STREAM_SOURCE_OUTPUT, source->outputs, conn->device, conn->is_connected, u);
- else
- pa_log_error("[CONN] could not get source");
-
- update_sink_or_source_as_device_connection_change(STREAM_ROUTE_TYPE_AUTO, STREAM_SOURCE_OUTPUT, u->core->source_outputs, conn->device, conn->is_connected, u);
+ }
+ pa_sink_suspend(combine_sink, TRUE, PA_SUSPEND_USER);
+ pa_module_unload(u->core, u->module_combine_sink, TRUE);
+ u->module_combine_sink = NULL;
+ } else
+ pa_log_error("[CONN] could not get combine_sink");
}
- if (device_direction & DM_DEVICE_DIRECTION_OUT) {
- if ((sink = pa_device_manager_get_sink(conn->device, DEVICE_ROLE_NORMAL)))
- update_sink_or_source_as_device_connection_change(STREAM_ROUTE_TYPE_MANUAL_EXT, STREAM_SINK_INPUT, sink->inputs, conn->device, conn->is_connected, u);
- else
- pa_log_error("[CONN] could not get sink");
-
- update_sink_or_source_as_device_connection_change(STREAM_ROUTE_TYPE_AUTO, STREAM_SINK_INPUT, u->core->sink_inputs, conn->device, conn->is_connected, u);
+ if (u->module_combine_sink_for_ex) {
+ /* unload combine sink for external devices */
+ if ((combine_sink = (pa_sink*)pa_namereg_get(u->core, SINK_NAME_COMBINED_EX, PA_NAMEREG_SINK))) {
+ if (combine_sink->inputs) {
+ PA_IDXSET_FOREACH (s, combine_sink->inputs, idx) {
+ pa_sink_input_move_to(s, null_sink, FALSE);
+ pa_log_debug("[CONN] *** sink-input(%p,%u) moves to sink(%p,%s)", s, ((pa_sink_input*)s)->index, null_sink, null_sink->name);
+ }
+ }
+ pa_sink_suspend(combine_sink, TRUE, PA_SUSPEND_USER);
+ pa_module_unload(u->core, u->module_combine_sink_for_ex, TRUE);
+ u->module_combine_sink_for_ex = NULL;
+ } else
+ pa_log_error("[CONN] could not get combine_sink_ex");
}
-
- } else {
- /* INTERNAL AUDIO CODEC */
- if (conn->is_connected && (device_direction & DM_DEVICE_DIRECTION_IN))
- update_sink_or_source_as_device_connection_change(STREAM_ROUTE_TYPE_AUTO, STREAM_SOURCE_OUTPUT, u->core->source_outputs, conn->device, conn->is_connected, u);
- if (conn->is_connected && (device_direction & DM_DEVICE_DIRECTION_OUT))
- update_sink_or_source_as_device_connection_change(STREAM_ROUTE_TYPE_AUTO, STREAM_SINK_INPUT, u->core->sink_inputs, conn->device, conn->is_connected, u);
}
return PA_HOOK_OK;
pa_communicator_hook(u->communicator.comm, PA_COMMUNICATOR_HOOK_DEVICE_CONNECTION_CHANGED),
PA_HOOK_EARLY, (pa_hook_cb_t)device_connection_changed_hook_cb, u);
}
- u->stream_manager = pa_stream_manager_init(u->core);
-
u->device_manager = pa_device_manager_get(u->core);
+ u->stream_manager = pa_stream_manager_init(u->core);
+
/* load null sink/source */
- args = pa_sprintf_malloc("sink_name=%s", SINK_NULL);
- u->module_null_sink = pa_module_load(u->core, "module-null-sink", args);
+ args = pa_sprintf_malloc("sink_name=%s", SINK_NAME_NULL);
+ u->module_null_sink = pa_module_load(u->core, MODULE_NULL_SINK, args);
pa_xfree(args);
- args = pa_sprintf_malloc("source_name=%s", SOURCE_NULL);
- u->module_null_source = pa_module_load(u->core, "module-null-source", args);
+ args = pa_sprintf_malloc("source_name=%s", SOURCE_NAME_NULL);
+ u->module_null_source = pa_module_load(u->core, MODULE_NULL_SOURCE, args);
pa_xfree(args);
__load_dump_config(u);
STREAM_DIRECTION_MAX,
} stream_direction_t;
+#define GET_STREAM_NEW_SAMPLE_SPEC_PTR(stream, type) \
+ (type == STREAM_SINK_INPUT? &(((pa_sink_input_new_data*)stream)->sample_spec) : &(((pa_source_output_new_data*)stream)->sample_spec))
+
#define GET_STREAM_NEW_SAMPLE_SPEC(stream, type) \
(type == STREAM_SINK_INPUT? ((pa_sink_input_new_data*)stream)->sample_spec : ((pa_source_output_new_data*)stream)->sample_spec)
#define IS_FOCUS_ACQUIRED(focus, type) \
(type == STREAM_SINK_INPUT? (focus & STREAM_FOCUS_ACQUIRED_PLAYBACK) : (focus & STREAM_FOCUS_ACQUIRED_CAPTURE))
-
typedef struct _stream_info {
int32_t priority;
stream_route_type_t route_type;
struct _stream_manager {
pa_core *core;
pa_hal_manager *hal;
+ pa_device_manager *dm;
pa_hashmap *volume_infos;
pa_hashmap *volume_modifiers;
pa_hashmap *stream_infos;
struct {
pa_communicator *comm;
pa_hook_slot *comm_hook_device_connection_changed_slot;
- pa_hook_slot *comm_hook_need_update_route_slot;
} comm;
};
int32_t set_volume_level_by_type(pa_stream_manager *m, stream_type_t stream_type, const char *volume_type, uint32_t volume_level);
int32_t get_volume_level_by_type(pa_stream_manager *m, pa_volume_get_command_t command, stream_type_t stream_type, const char *volume_type, uint32_t *volume_level);
int32_t set_volume_level_by_idx(pa_stream_manager *m, stream_type_t stream_type, uint32_t idx, uint32_t volume_level);
-int32_t set_volume_level_with_new_data(pa_stream_manager *m, stream_type_t stream_type, void *nd, uint32_t volume_level);
+int32_t set_volume_level_with_new_data(pa_stream_manager *m, void *stream, stream_type_t stream_type, uint32_t volume_level);
int32_t set_volume_mute_by_type(pa_stream_manager *m, stream_type_t stream_type, const char *volume_type, pa_bool_t volume_mute);
int32_t get_volume_mute_by_type(pa_stream_manager *m, stream_type_t stream_type, const char *volume_type, pa_bool_t *volume_mute);
int32_t set_volume_mute_by_idx(pa_stream_manager *m, stream_type_t stream_type, uint32_t stream_idx, pa_bool_t volume_mute);
-int32_t set_volume_mute_with_new_data(pa_stream_manager *m, stream_type_t stream_type, void *nd, pa_bool_t volume_mute);
+int32_t set_volume_mute_with_new_data(pa_stream_manager *m, void *stream, stream_type_t stream_type, pa_bool_t volume_mute);
int32_t get_volume_mute_by_idx(pa_stream_manager *m, stream_type_t stream_type, uint32_t stream_idx, pa_bool_t *volume_mute);
#endif
#define VOLUME_INI_TUNED_PATH "/opt/system/mmfw_audio_volume.ini"
#define DEFAULT_TABLE "volumes"
+#define CONVERT_TO_HAL_DIRECTION(stream_type)\
+ ((stream_type == STREAM_SINK_INPUT) ? DIRECTION_OUT : DIRECTION_IN)
+
/* Stream */
enum gain_type {
GAIN_TYPE_DEFAULT,
static int get_volume_value(pa_stream_manager *m, stream_type_t stream_type, pa_bool_t is_hal_volume, const char *volume_type, uint32_t volume_level, double *volume_value) {
int ret = 0;
double volume_linear = 1.0;
+ volume_info *v = NULL;
+ void *volumes = NULL;
pa_assert(m);
pa_assert(volume_type);
pa_assert(volume_value);
/* Get volume value by type & level */
if (is_hal_volume) {
/* Get value from HAL */
- if (pa_hal_manager_get_volume_value(m->hal, volume_type, NULL, (stream_type==STREAM_SINK_INPUT)?DIRECTION_OUT:DIRECTION_IN, volume_level, &volume_linear)) {
+ if (pa_hal_manager_get_volume_value(m->hal, volume_type, NULL,
+ CONVERT_TO_HAL_DIRECTION(stream_type), volume_level, &volume_linear)) {
ret = -1;
goto FAILURE;
}
} else {
- volume_info *v = NULL;
- void *volumes = m->volume_infos;
/* Get value from stream-manager */
- if (volumes) {
+ if ((volumes = m->volume_infos)) {
v = pa_hashmap_get(volumes, volume_type);
if (v && v->values[stream_type].idx_volume_values) {
double *value = NULL;
goto FAILURE;
}
} else {
- pa_log_error("could not get volume value for stream_type[%d], volume_type[%s], level[%u]", stream_type, volume_type, volume_level);
+ pa_log_error("could not get volume value for stream_type[%d], volume_type[%s], level[%u]",
+ stream_type, volume_type, volume_level);
ret = -1;
goto FAILURE;
}
} else {
- pa_log_error("could not get volumes in volume infos, stream_type(%d), volume_type(%s)", stream_type, volume_type);
+ pa_log_error("could not get volumes in volume infos, stream_type(%d), volume_type(%s)",
+ stream_type, volume_type);
ret = -1;
goto FAILURE;
}
*volume_value = volume_linear;
pa_log_debug("get_volume_value() : stream_type[%d], volume_type[%s], level[%u], value[%f]",
- stream_type, volume_type, volume_level, volume_linear);
+ stream_type, volume_type, volume_level, volume_linear);
FAILURE:
return ret;
}
}
if (is_hal_volume)
- if (pa_hal_manager_set_volume_level(m->hal, volume_type, (stream_type==STREAM_SINK_INPUT)?DIRECTION_OUT:DIRECTION_IN, volume_level))
+ if (pa_hal_manager_set_volume_level(m->hal, volume_type, CONVERT_TO_HAL_DIRECTION(stream_type), volume_level))
return -1;
- volumes = m->volume_infos;
- if (volumes) {
- v = pa_hashmap_get(volumes, volume_type);
- if (v) {
+ if ((volumes = m->volume_infos)) {
+ if ((v = pa_hashmap_get(volumes, volume_type))) {
if (pa_streq(volume_type, MASTER_VOLUME_TYPE) && MASTER_VOLUME_LEVEL_MAX < volume_level) {
pa_log_error("could not set volume level of MASTER type, out of range(%u)", volume_level);
return -1;
if (get_volume_value(m, stream_type, is_hal_volume, volume_type, volume_level, &volume_linear))
return -1;
- PA_IDXSET_FOREACH(s, stream_type==STREAM_SINK_INPUT?m->core->sink_inputs:m->core->source_outputs, idx) {
+ PA_IDXSET_FOREACH(s, stream_type == STREAM_SINK_INPUT?m->core->sink_inputs:m->core->source_outputs, idx) {
if ((volume_type_str = pa_proplist_gets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_TIZEN_VOLUME_TYPE))) {
/* Get modifier for gain */
modifier_gain = pa_proplist_gets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_TIZEN_VOLUME_GAIN_TYPE);
if (modifier_gain_value) {
volume_linear *= (*modifier_gain_value);
pa_log_info("set_volume_level_by_type() : apply the modifier for the gain value(%s=>%f), result volume_linear(%f)",
- modifier_gain, *modifier_gain_value, volume_linear);
+ modifier_gain, *modifier_gain_value, volume_linear);
}
}
}
}
}
} else {
- PA_IDXSET_FOREACH(s, stream_type==STREAM_SINK_INPUT?m->core->sink_inputs:m->core->source_outputs, idx) {
+ PA_IDXSET_FOREACH(s, stream_type == STREAM_SINK_INPUT?m->core->sink_inputs:m->core->source_outputs, idx) {
if ((volume_type_str = pa_proplist_gets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_TIZEN_VOLUME_TYPE))) {
/* Get modifier for gain */
modifier_gain = pa_proplist_gets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_TIZEN_VOLUME_GAIN_TYPE);
continue;
}
/* Get volume level of this type */
- v = pa_hashmap_get(volumes, volume_type_str);
- if (v)
+ if ((v = pa_hashmap_get(volumes, volume_type_str)))
volume_level = v->values[stream_type].current_level;
else
continue;
if (modifier_gain_value) {
volume_linear *= (*modifier_gain_value);
pa_log_info("set_volume_level_by_type() : apply the modifier for the gain value(%s=>%f), result volume_linear(%f)",
- modifier_gain, *modifier_gain_value, volume_linear);
+ modifier_gain, *modifier_gain_value, volume_linear);
}
}
}
}
pa_log_debug("set_volume_level_by_type() : stream_type[%d], volume_type[%s], level[%u], value[%f]",
- stream_type, volume_type, volume_level, volume_linear);
+ stream_type, volume_type, volume_level, volume_linear);
return 0;
}
int32_t get_volume_level_by_type(pa_stream_manager *m, pa_volume_get_command_t command, stream_type_t stream_type, const char *volume_type, uint32_t *volume_level) {
int32_t ret = 0;
pa_bool_t is_hal_volume = FALSE;
+ volume_info *v = NULL;
pa_hashmap *volumes = NULL;
pa_assert(m);
pa_assert(volume_type);
/* Get level */
if (is_hal_volume) {
/* from HAL */
- if (pa_hal_manager_get_volume_level(m->hal, volume_type, (stream_type==STREAM_SINK_INPUT)?DIRECTION_OUT:DIRECTION_IN, volume_level))
+ if (pa_hal_manager_get_volume_level(m->hal, volume_type, CONVERT_TO_HAL_DIRECTION(stream_type), volume_level))
ret = -1;
} else {
/* from stream-manager */
- volumes = m->volume_infos;
- if (volumes) {
- volume_info *v = pa_hashmap_get(volumes, volume_type);
- if (v)
+ if ((volumes = m->volume_infos)) {
+ if ((v = pa_hashmap_get(volumes, volume_type)))
*volume_level = v->values[stream_type].current_level;
else {
pa_log_error("could not get volume_info, stream_type(%d), volume_type(%s)", stream_type, volume_type);
/* Get max level */
if (is_hal_volume) {
/* from HAL */
- if (pa_hal_manager_get_volume_level_max(m->hal, volume_type, (stream_type==STREAM_SINK_INPUT)?DIRECTION_OUT:DIRECTION_IN, volume_level))
+ if (pa_hal_manager_get_volume_level_max(m->hal, volume_type, CONVERT_TO_HAL_DIRECTION(stream_type), volume_level))
ret = -1;
} else {
/* from stream-manager */
- volumes = m->volume_infos;
- if (volumes) {
- volume_info *v = pa_hashmap_get(volumes, volume_type);
+ if ((volumes = m->volume_infos)) {
+ v = pa_hashmap_get(volumes, volume_type);
if (v && v->values[stream_type].idx_volume_values)
*volume_level = pa_idxset_size(v->values[stream_type].idx_volume_values);
else {
const char *modifier_gain = NULL;
pa_assert(m);
- s = pa_idxset_get_by_index(stream_type==STREAM_SINK_INPUT?m->core->sink_inputs:m->core->source_outputs, idx);
+ s = pa_idxset_get_by_index(stream_type == STREAM_SINK_INPUT?m->core->sink_inputs:m->core->source_outputs, idx);
if ((volume_type_str = pa_proplist_gets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_TIZEN_VOLUME_TYPE))) {
/* Get modifier for gain */
modifier_gain = pa_proplist_gets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_TIZEN_VOLUME_GAIN_TYPE);
}
if (is_hal_volume)
- if (pa_hal_manager_set_volume_level(m->hal, volume_type_str, (stream_type==STREAM_SINK_INPUT)?DIRECTION_OUT:DIRECTION_IN, volume_level))
+ if (pa_hal_manager_set_volume_level(m->hal, volume_type_str, CONVERT_TO_HAL_DIRECTION(stream_type), volume_level))
return -1;
if (!get_volume_value(m, stream_type, is_hal_volume, volume_type_str, volume_level, &volume_linear)) {
if (modifier_gain_value) {
volume_linear *= (*modifier_gain_value);
pa_log_info("set_volume_level_by_idx() : apply the modifier for the gain value(%s=>%f), result volume_linear(%f)",
- modifier_gain, *modifier_gain_value, volume_linear);
+ modifier_gain, *modifier_gain_value, volume_linear);
}
}
pa_cvolume_set(&cv, GET_STREAM_SAMPLE_SPEC(s, stream_type).channels, pa_sw_volume_from_linear(volume_linear));
pa_source_output_set_volume((pa_source_output*)s, &cv, TRUE, TRUE);
}
pa_log_debug("set_volume_level_by_idx() : stream_type[%d], idx[%u]=>volume_type[%s], level[%u], value[%f]",
- stream_type, idx, volume_type_str, volume_level, volume_linear);
+ stream_type, idx, volume_type_str, volume_level, volume_linear);
return 0;
}
-int32_t set_volume_level_with_new_data(pa_stream_manager *m, stream_type_t stream_type, void *nd, uint32_t volume_level) {
+int32_t set_volume_level_with_new_data(pa_stream_manager *m, void *stream, stream_type_t stream_type, uint32_t volume_level) {
pa_bool_t is_hal_volume = FALSE;
pa_cvolume cv;
double volume_linear = 1.0;
const char *volume_type_str = NULL;
const char *modifier_gain = NULL;
pa_assert(m);
+ pa_assert(stream);
- if ((volume_type_str = pa_proplist_gets(GET_STREAM_NEW_PROPLIST(nd, stream_type), PA_PROP_MEDIA_TIZEN_VOLUME_TYPE))) {
+ if ((volume_type_str = pa_proplist_gets(GET_STREAM_NEW_PROPLIST(stream, stream_type), PA_PROP_MEDIA_TIZEN_VOLUME_TYPE))) {
/* Get modifier for gain */
- modifier_gain = pa_proplist_gets(GET_STREAM_NEW_PROPLIST(nd, stream_type), PA_PROP_MEDIA_TIZEN_VOLUME_GAIN_TYPE);
+ modifier_gain = pa_proplist_gets(GET_STREAM_NEW_PROPLIST(stream, stream_type), PA_PROP_MEDIA_TIZEN_VOLUME_GAIN_TYPE);
} else {
- pa_log_debug("new_data[%p] doesn't have volume type", nd);
+ pa_log_debug("new_data[%p] doesn't have volume type", stream);
return -1;
}
}
if (is_hal_volume)
- if (pa_hal_manager_set_volume_level(m->hal, volume_type_str, (stream_type==STREAM_SINK_INPUT)?DIRECTION_OUT:DIRECTION_IN, volume_level))
+ if (pa_hal_manager_set_volume_level(m->hal, volume_type_str, CONVERT_TO_HAL_DIRECTION(stream_type), volume_level))
return -1;
if (!get_volume_value(m, stream_type, is_hal_volume, volume_type_str, volume_level, &volume_linear)) {
if (modifier_gain_value) {
volume_linear *= (*modifier_gain_value);
pa_log_info("set_volume_level_by_idx() : apply the modifier for the gain value(%s=>%f), result volume_linear(%f)",
- modifier_gain, *modifier_gain_value, volume_linear);
+ modifier_gain, *modifier_gain_value, volume_linear);
}
}
- pa_cvolume_set(&cv, GET_STREAM_NEW_SAMPLE_SPEC(nd, stream_type).channels, pa_sw_volume_from_linear(volume_linear));
+ pa_cvolume_set(&cv, GET_STREAM_NEW_SAMPLE_SPEC(stream, stream_type).channels, pa_sw_volume_from_linear(volume_linear));
if (stream_type == STREAM_SINK_INPUT)
- pa_sink_input_new_data_set_volume((pa_sink_input_new_data*)nd, &cv, TRUE);
+ pa_sink_input_new_data_set_volume((pa_sink_input_new_data*)stream, &cv, TRUE);
else if (stream_type == STREAM_SOURCE_OUTPUT)
- pa_source_output_new_data_set_volume((pa_source_output_new_data*)nd, &cv, TRUE);
+ pa_source_output_new_data_set_volume((pa_source_output_new_data*)stream, &cv, TRUE);
}
pa_log_debug("set_volume_level_with_new_data() : stream_type[%d], volume_type[%s], level[%u], value[%f]",
- stream_type, volume_type_str, volume_level, volume_linear);
+ stream_type, volume_type_str, volume_level, volume_linear);
return 0;
}
}
if (is_hal_volume)
- if (pa_hal_manager_set_volume_mute(m->hal, volume_type, (stream_type==STREAM_SINK_INPUT)?DIRECTION_OUT:DIRECTION_IN, (uint32_t)volume_mute))
+ if (pa_hal_manager_set_volume_mute(m->hal, volume_type, CONVERT_TO_HAL_DIRECTION(stream_type), (uint32_t)volume_mute))
return -1;
/* Set mute */
- volumes = m->volume_infos;
- if (volumes) {
+ if ((volumes = m->volume_infos)) {
v = pa_hashmap_get(volumes, volume_type);
if (v)
v->values[stream_type].is_muted = volume_mute;
return -1;
}
- PA_IDXSET_FOREACH(s, (stream_type==STREAM_SINK_INPUT)?m->core->sink_inputs:m->core->source_outputs, idx) {
+ PA_IDXSET_FOREACH(s, (stream_type == STREAM_SINK_INPUT) ? m->core->sink_inputs : m->core->source_outputs, idx) {
if ((volume_type_str = pa_proplist_gets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_TIZEN_VOLUME_TYPE))) {
/* do nothing */
} else {
pa_assert(volume_mute);
/* Get mute */
- volumes = m->volume_infos;
- if (volumes) {
- v = pa_hashmap_get(volumes, volume_type);
- if (v)
+ if ((volumes = m->volume_infos)) {
+ if ((v = pa_hashmap_get(volumes, volume_type)))
*volume_mute = v->values[stream_type].is_muted;
else {
pa_log_error("could not get volume_info, stream_type(%d), volume_type(%s)", stream_type, volume_type);
return 0;
}
-int32_t set_volume_mute_by_idx(pa_stream_manager *m, stream_type_t stream_type, uint32_t stream_idx, pa_bool_t volume_mute) {
+int32_t set_volume_mute_by_idx(pa_stream_manager *m, uint32_t stream_idx, stream_type_t stream_type, pa_bool_t volume_mute) {
void *s = NULL;
uint32_t idx = 0;
const char *volume_type_str = NULL;
pa_bool_t muted_by_type = FALSE;
pa_assert(m);
- pa_log_info("set_volume_mute_by_idx, stream_type:%d stream_idx:%u mute:%d", stream_type, stream_idx, volume_mute);
+ pa_log_info("set_volume_mute_by_idx, stream_idx:%u stream_type:%d mute:%d", stream_idx, stream_type, volume_mute);
if (stream_idx != (uint32_t)-1) {
- if ((s = pa_idxset_get_by_index((stream_type==STREAM_SINK_INPUT)?m->core->sink_inputs:m->core->source_outputs, stream_idx))) {
+ if ((s = pa_idxset_get_by_index((stream_type == STREAM_SINK_INPUT) ? m->core->sink_inputs : m->core->source_outputs, stream_idx))) {
if ((volume_type_str = pa_proplist_gets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_TIZEN_VOLUME_TYPE))) {
/* do nothing */
} else {
/* Get mute state of the volume type of this stream */
if (volume_type_str) {
- volumes = m->volume_infos;
- if (volumes) {
- v = pa_hashmap_get(volumes, volume_type_str);
- if (v)
+ if ((volumes = m->volume_infos)) {
+ if ((v = pa_hashmap_get(volumes, volume_type_str)))
muted_by_type = v->values[stream_type].is_muted;
} else {
pa_log_error("could not get volumes in volume map, stream_type(%d), volume_type(%s)", stream_type, volume_type_str);
}
if (!muted_by_type) {
- PA_IDXSET_FOREACH(s, (stream_type==STREAM_SINK_INPUT)?m->core->sink_inputs:m->core->source_outputs, idx) {
+ PA_IDXSET_FOREACH(s, (stream_type == STREAM_SINK_INPUT) ? m->core->sink_inputs : m->core->source_outputs, idx) {
/* Update mute of the stream if it has requested idx */
if (stream_idx == idx) {
if (stream_type == STREAM_SINK_INPUT)
return 0;
}
-int32_t get_volume_mute_by_idx(pa_stream_manager *m, stream_type_t stream_type, uint32_t stream_idx, pa_bool_t *volume_mute) {
+int32_t get_volume_mute_by_idx(pa_stream_manager *m, uint32_t stream_idx, stream_type_t stream_type, pa_bool_t *volume_mute) {
int32_t ret = 0;
void *s = NULL;
uint32_t idx = 0;
pa_assert(m);
pa_assert(volume_mute);
- PA_IDXSET_FOREACH(s, (stream_type==STREAM_SINK_INPUT)?m->core->sink_inputs:m->core->source_outputs, idx) {
+ PA_IDXSET_FOREACH(s, (stream_type == STREAM_SINK_INPUT) ? m->core->sink_inputs : m->core->source_outputs, idx) {
/* Update mute of the stream if it has requested idx */
if (stream_idx == idx) {
if (stream_type == STREAM_SINK_INPUT)
if (!s)
ret = -1;
- pa_log_info("get_volume_mute_by_idx, stream_type:%d stream_idx:%u mute:%d, ret:%d", stream_type, stream_idx, *volume_mute, ret);
+ pa_log_info("get_volume_mute_by_idx, stream_idx:%u stream_type:%d mute:%d, ret:%d", stream_idx, stream_type, *volume_mute, ret);
return ret;
}
-int32_t set_volume_mute_with_new_data(pa_stream_manager *m, stream_type_t stream_type, void *nd, pa_bool_t volume_mute) {
+int32_t set_volume_mute_with_new_data(pa_stream_manager *m, void *stream, stream_type_t stream_type, pa_bool_t volume_mute) {
pa_bool_t is_hal_volume = FALSE;
const char *volume_type_str = NULL;
pa_assert(m);
+ pa_assert(stream);
pa_log_info("set_volume_mute_with_new_data, stream_type:%d mute:%d", stream_type, volume_mute);
- if ((volume_type_str = pa_proplist_gets(GET_STREAM_NEW_PROPLIST(nd, stream_type), PA_PROP_MEDIA_TIZEN_VOLUME_TYPE))) {
+ if ((volume_type_str = pa_proplist_gets(GET_STREAM_NEW_PROPLIST(stream, stream_type), PA_PROP_MEDIA_TIZEN_VOLUME_TYPE))) {
/* do nothing */
} else {
- pa_log_debug("new_data[%p] doesn't have volume type", nd);
+ pa_log_debug("new_data[%p] doesn't have volume type", stream);
return -1;
}
}
if (is_hal_volume)
- if (pa_hal_manager_set_volume_mute(m->hal, volume_type_str, (stream_type==STREAM_SINK_INPUT)?DIRECTION_OUT:DIRECTION_IN, volume_mute))
+ if (pa_hal_manager_set_volume_mute(m->hal, volume_type_str, CONVERT_TO_HAL_DIRECTION(stream_type), volume_mute))
return -1;
if (stream_type == STREAM_SINK_INPUT)
- pa_sink_input_new_data_set_muted((pa_sink_input_new_data*)nd, volume_mute);
+ pa_sink_input_new_data_set_muted((pa_sink_input_new_data*)stream, volume_mute);
else if (stream_type == STREAM_SOURCE_OUTPUT)
- pa_source_output_new_data_set_muted((pa_source_output_new_data*)nd, volume_mute);
+ pa_source_output_new_data_set_muted((pa_source_output_new_data*)stream, volume_mute);
return 0;
}
return set_volume_mute_by_type(m, stream_type, volume_type, volume_mute);
}
-int32_t pa_stream_manager_volume_get_mute_by_idx(pa_stream_manager *m, stream_type_t stream_type, uint32_t stream_idx, pa_bool_t *volume_mute) {
- return get_volume_mute_by_idx(m, stream_type, stream_idx, volume_mute);
+int32_t pa_stream_manager_volume_get_mute_by_idx(pa_stream_manager *m, uint32_t stream_idx, stream_type_t stream_type, pa_bool_t *volume_mute) {
+ return get_volume_mute_by_idx(m, stream_idx, stream_type, volume_mute);
}
-int32_t pa_stream_manager_volume_set_mute_by_idx(pa_stream_manager *m, stream_type_t stream_type, uint32_t stream_idx, pa_bool_t volume_mute) {
- return set_volume_mute_by_idx(m, stream_type, stream_idx, volume_mute);
+int32_t pa_stream_manager_volume_set_mute_by_idx(pa_stream_manager *m, uint32_t stream_idx, stream_type_t stream_type, pa_bool_t volume_mute) {
+ return set_volume_mute_by_idx(m, stream_idx, stream_type, volume_mute);
}
#define STREAM_MANAGER_CLIENT_NAME "SOUND_MANAGER_STREAM_INFO"
#define DEFAULT_ROLE "media"
#define SKIP_ROLE "skip"
+#define ACTIVE_DEV_REMOVED "removed"
-/* There are some streams to be skipped.
+/* There are some streams that need to be skipped.
* In other words, we do not care about streams that have a name of listed as below */
#define NAME_FOR_SKIP_MAX 1
const char* stream_manager_media_names_for_skip[NAME_FOR_SKIP_MAX] = {"pulsesink probe"};
int32_t value;
} stream_route_option;
+#define CONVERT_TO_DEVICE_DIRECTION(stream_type)\
+ ((stream_type == STREAM_SINK_INPUT) ? DM_DEVICE_DIRECTION_OUT : DM_DEVICE_DIRECTION_IN)
+
static void do_notify(pa_stream_manager *m, notify_command_type_t command, stream_type_t type, pa_bool_t is_new_data, void *user_data);
-static process_stream_result_t process_stream(pa_stream_manager *m, stream_type_t type, void *stream, process_command_type_t command, pa_bool_t is_new_data);
+static process_stream_result_t process_stream(pa_stream_manager *m, void *stream, stream_type_t type, process_command_type_t command, pa_bool_t is_new_data);
static int get_available_streams(pa_stream_manager *m, stream_list *list) {
void *state = NULL;
pa_proplist_sets(GET_STREAM_PROPLIST(stream, STREAM_SINK_INPUT), PA_PROP_MEDIA_FOCUS_STATUS,
IS_FOCUS_ACQUIRED(sp->focus_status, STREAM_SINK_INPUT)?STREAM_FOCUS_PLAYBACK:STREAM_FOCUS_NONE);
if (--count == 0)
- process_stream(m, STREAM_SINK_INPUT, stream, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_FOCUS_CHANGED, FALSE);
+ process_stream(m, stream, STREAM_SINK_INPUT, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_FOCUS_CHANGED, FALSE);
}
if (sp->idx_source_outputs)
count = pa_idxset_size(sp->idx_source_outputs);
pa_proplist_sets(GET_STREAM_PROPLIST(stream, STREAM_SOURCE_OUTPUT), PA_PROP_MEDIA_FOCUS_STATUS,
IS_FOCUS_ACQUIRED(sp->focus_status, STREAM_SOURCE_OUTPUT)?STREAM_FOCUS_CAPTURE:STREAM_FOCUS_NONE);
if (--count == 0)
- process_stream(m, STREAM_SOURCE_OUTPUT, stream, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_FOCUS_CHANGED, FALSE);
+ process_stream(m, stream, STREAM_SOURCE_OUTPUT, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_FOCUS_CHANGED, FALSE);
}
} else
pa_log_debug("same as before, skip updating focus status[0x%x]", acquired_focus_status);
return;
}
-static pa_bool_t check_name_to_skip(pa_stream_manager *m, process_command_type_t command, stream_type_t type, void *stream, pa_bool_t is_new_data) {
+static pa_bool_t check_name_to_skip(pa_stream_manager *m, process_command_type_t command, void *stream, stream_type_t type, pa_bool_t is_new_data) {
pa_bool_t ret = FALSE;
const char *name = NULL;
const char *role = NULL;
return ret;
}
-static pa_bool_t update_priority_of_stream(pa_stream_manager *m, stream_type_t type, void *stream, const char *role, pa_bool_t is_new_data) {
+static pa_bool_t update_priority_of_stream(pa_stream_manager *m, void *stream, stream_type_t type, const char *role, pa_bool_t is_new_data) {
pa_bool_t ret = FALSE;
stream_info *s = NULL;
pa_assert(m);
+ pa_assert(stream);
pa_assert(m->stream_infos);
pa_assert(role);
stream_info *s = NULL;
pa_assert(m);
+ pa_assert(stream);
pa_assert(m->stream_infos);
pa_assert(role);
return ret;
}
-static pa_bool_t update_volume_type_of_stream(pa_stream_manager *m, stream_type_t type, void *stream, const char *role) {
+static pa_bool_t update_volume_type_of_stream(pa_stream_manager *m, void *stream, stream_type_t type, const char *role) {
pa_bool_t ret = FALSE;
const char *volume_type = NULL;
stream_info *s = NULL;
pa_assert(m);
+ pa_assert(stream);
pa_assert(m->stream_infos);
pa_assert(role);
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 = (type == STREAM_SINK_INPUT) ? ((pa_sink_input*)stream)->index : ((pa_source_output*)stream)->index;
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);
- pa_idxset_put(type==STREAM_SINK_INPUT?(sp->idx_sink_inputs):(sp->idx_source_outputs), stream, NULL);
+ pa_idxset_put(type == STREAM_SINK_INPUT ? (sp->idx_sink_inputs) : (sp->idx_source_outputs), stream, NULL);
return TRUE;
} else if (command == PROCESS_COMMAND_REMOVE_PARENT_ID) {
/* remove this stream from the parent stream info. */
pa_log_debug(" - remove this stream(%p, %u) from the list. sp(%p), stream_type(%d)", stream, idx, sp, type);
- pa_idxset_remove_by_data(type==STREAM_SINK_INPUT?(sp->idx_sink_inputs):(sp->idx_source_outputs), stream, NULL);
+ pa_idxset_remove_by_data(type == STREAM_SINK_INPUT ? (sp->idx_sink_inputs) : (sp->idx_source_outputs), stream, NULL);
return TRUE;
} else {
pa_log_error("invalid command(%d)", command);
pa_log_warn("stream(%p) has the route type for external device, skip it", i);
continue;
} else {
- if (type==STREAM_SINK_INPUT?!(((pa_sink_input*)i)->sink->use_internal_codec):!(((pa_source_output*)i)->source->use_internal_codec)) {
+ if (type == STREAM_SINK_INPUT ? !(((pa_sink_input*)i)->sink->use_internal_codec) : !(((pa_source_output*)i)->source->use_internal_codec)) {
pa_log_warn("stream(%p) uses external audio codec, skip it", i);
continue;
}
select_data = (pa_stream_manager_hook_data_for_select*)hook_data;
si = pa_hashmap_get(m->stream_infos, select_data->stream_role);
select_data->route_type = si->route_type;
- avail_devices = (type==STREAM_SINK_INPUT)?si->idx_avail_out_devices:si->idx_avail_in_devices;
+ avail_devices = (type == STREAM_SINK_INPUT) ? si->idx_avail_out_devices : si->idx_avail_in_devices;
list_len = pa_idxset_size(avail_devices);
device_none = pa_idxset_get_by_data(avail_devices, "none", NULL);
if (list_len == 0 || device_none) {
/* find parent idx, it's device info. and it's stream idxs */
sp = pa_hashmap_get(m->stream_parents, (const void*)parent_idx);
if (sp)
- select_data->idx_manual_devices = (type==STREAM_SINK_INPUT)?(sp->idx_route_out_devices):(sp->idx_route_in_devices);
+ select_data->idx_manual_devices = (type == STREAM_SINK_INPUT) ? (sp->idx_route_out_devices) : (sp->idx_route_in_devices);
else
pa_log_warn(" -- failed to get the stream parent of idx(%u)", parent_idx);
} else
case NOTIFY_COMMAND_CHANGE_ROUTE_END: {
route_data = (pa_stream_manager_hook_data_for_route*)hook_data;
si = pa_hashmap_get(m->stream_infos, route_data->stream_role);
- avail_devices = (type==STREAM_SINK_INPUT)?si->idx_avail_out_devices:si->idx_avail_in_devices;
+ avail_devices = (type == STREAM_SINK_INPUT) ? si->idx_avail_out_devices : si->idx_avail_in_devices;
route_data->route_type = si->route_type;
list_len = pa_idxset_size(avail_devices);
device_none = pa_idxset_get_by_data(avail_devices, "none", NULL);
route_data->idx_avail_devices = avail_devices;
if (si->route_type >= STREAM_ROUTE_TYPE_MANUAL) {
if (sp) {
- route_data->idx_manual_devices = (type==STREAM_SINK_INPUT)?(sp->idx_route_out_devices):(sp->idx_route_in_devices);
- route_data->idx_streams = (type==STREAM_SINK_INPUT)?(sp->idx_sink_inputs):(sp->idx_source_outputs);
+ route_data->idx_manual_devices = (type == STREAM_SINK_INPUT) ? (sp->idx_route_out_devices) : (sp->idx_route_in_devices);
+ route_data->idx_streams = (type == STREAM_SINK_INPUT) ? (sp->idx_sink_inputs) : (sp->idx_source_outputs);
} else
pa_log_warn(" -- failed to get the stream parent of idx(%u)", parent_idx);
}
} else {
role = pa_proplist_gets(GET_STREAM_PROPLIST(s, type), PA_PROP_MEDIA_ROLE);
hook_call_route_data.sample_spec = GET_STREAM_SAMPLE_SPEC(s, type);
- hook_call_route_data.idx_streams = (type==STREAM_SINK_INPUT)?((pa_sink_input*)s)->sink->inputs:((pa_source_output*)s)->source->outputs;
+ hook_call_route_data.idx_streams = (type == STREAM_SINK_INPUT) ? ((pa_sink_input*)s)->sink->inputs :
+ ((pa_source_output*)s)->source->outputs;
}
hook_call_route_data.stream_type = type;
hook_call_route_data.stream_role = role;
}
case NOTIFY_COMMAND_CHANGE_ROUTE_END: {
memset(&hook_call_route_data, 0, sizeof(pa_stream_manager_hook_data_for_route));
- s = (type==STREAM_SINK_INPUT)?(void*)(m->cur_highest_priority.sink_input):(void*)(m->cur_highest_priority.source_output);
+ s = (type == STREAM_SINK_INPUT) ? (void*)(m->cur_highest_priority.sink_input) :
+ (void*)(m->cur_highest_priority.source_output);
if (s) {
role = pa_proplist_gets(GET_STREAM_PROPLIST(s, type), PA_PROP_MEDIA_ROLE);
hook_call_route_data.stream_type = type;
hook_call_route_data.stream_role = role;
hook_call_route_data.sample_spec = GET_STREAM_SAMPLE_SPEC(s, type);
- hook_call_route_data.idx_streams = (type==STREAM_SINK_INPUT)?((pa_sink_input*)s)->sink->inputs:((pa_source_output*)s)->source->outputs;
+ hook_call_route_data.idx_streams = (type == STREAM_SINK_INPUT) ? ((pa_sink_input*)s)->sink->inputs :
+ ((pa_source_output*)s)->source->outputs;
fill_device_info_to_hook_data(m, &hook_call_route_data, command, type, s, is_new_data);
} else {
pa_log_info("no stream for this type(%d), need to unset route", type);
case NOTIFY_COMMAND_UPDATE_ROUTE_OPTION: {
pa_assert(user_data);
memset(&hook_call_option_data, 0, sizeof(pa_stream_manager_hook_data_for_option));
- s = (type==STREAM_SINK_INPUT)?(void*)(m->cur_highest_priority.sink_input):(void*)(m->cur_highest_priority.source_output);
+ s = (type == STREAM_SINK_INPUT) ? (void*)(m->cur_highest_priority.sink_input):
+ (void*)(m->cur_highest_priority.source_output);
if (s) {
role = pa_proplist_gets(GET_STREAM_PROPLIST(s, type), PA_PROP_MEDIA_ROLE);
hook_call_option_data.stream_role = role;
s = user_data;
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.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.is_connected = (command == NOTIFY_COMMAND_INFORM_STREAM_CONNECTED)?TRUE:FALSE;
pa_hal_manager_update_stream_connection_info(m->hal, &stream_conn_info);
}
return;
}
-static process_stream_result_t process_stream(pa_stream_manager *m, stream_type_t type, void *stream, process_command_type_t command, pa_bool_t is_new_data) {
+static process_stream_result_t process_stream(pa_stream_manager *m, void *stream, stream_type_t type, process_command_type_t command, pa_bool_t is_new_data) {
process_stream_result_t result = PROCESS_STREAM_RESULT_OK;
const char *role = NULL;
const char *route_type_str = NULL;
const char *rate_str = NULL;
const char *ch_str = NULL;
- pa_log_info(">>> process_stream(%s): stream_type(%d), stream(%p), is_new_data(%d)",
- process_command_type_str[command], type, stream, is_new_data);
+ pa_log_info(">>> process_stream(%s): stream(%p), stream_type(%d), is_new_data(%d)",
+ process_command_type_str[command], stream, type, is_new_data);
pa_assert(m);
pa_assert(stream);
- if (check_name_to_skip(m, command, type, stream, is_new_data)) {
+ if (check_name_to_skip(m, command, stream, type, is_new_data)) {
result = PROCESS_STREAM_RESULT_SKIP;
goto FAILURE;
}
((pa_sink_input_new_data*)stream)->sample_spec.rate = atoi (rate_str);
/* set channel map if it is not set by client */
if (!((pa_sink_input_new_data*)stream)->channel_map_is_set) {
- pa_channel_map_init_auto(&(((pa_sink_input_new_data*)stream)->channel_map), ((pa_sink_input_new_data*)stream)->sample_spec.channels, PA_CHANNEL_MAP_ALSA);
+ pa_channel_map_init_auto(&(((pa_sink_input_new_data*)stream)->channel_map),
+ ((pa_sink_input_new_data*)stream)->sample_spec.channels, PA_CHANNEL_MAP_ALSA);
pa_log_info("set default channel_map: channels(%u)",((pa_sink_input_new_data*)stream)->channel_map.channels);
((pa_sink_input_new_data*)stream)->channel_map_is_set = TRUE;
}
}
}
/* update the priority of this stream */
- ret = update_priority_of_stream(m, type, stream, role, is_new_data);
+ ret = update_priority_of_stream(m, stream, type, role, is_new_data);
if (ret == FALSE) {
pa_log_error("could not update the priority of '%s' role.", role);
result = PROCESS_STREAM_RESULT_STOP;
goto FAILURE;
}
/* update the volume type of this stream */
- ret = update_volume_type_of_stream(m, type, stream, role);
+ ret = update_volume_type_of_stream(m, stream, type, role);
if (ret == FALSE)
pa_log_warn("could not update the volume type of '%s' role.", role);
if (!is_new_data) {
/* update the priority of this stream */
- ret = update_priority_of_stream(m, type, stream, role, is_new_data);
+ ret = update_priority_of_stream(m, stream, type, role, is_new_data);
if (ret == FALSE) {
pa_log_error("could not update the priority of '%s' role.", role);
result = PROCESS_STREAM_RESULT_STOP;
if (need_update) {
if (is_new_data) {
do_notify(m, NOTIFY_COMMAND_CHANGE_ROUTE_START, type, TRUE, stream);
- if (type==STREAM_SINK_INPUT)
+ if (type == STREAM_SINK_INPUT)
m->cur_highest_priority.need_to_update_si = TRUE;
else
m->cur_highest_priority.need_to_update_so = TRUE;
} else {
do_notify(m, NOTIFY_COMMAND_CHANGE_ROUTE_START, type, FALSE, stream);
- if (type==STREAM_SINK_INPUT)
+ if (type == STREAM_SINK_INPUT)
m->cur_highest_priority.sink_input = stream;
else
m->cur_highest_priority.source_output = stream;
v = pa_hashmap_get(m->volume_infos, si_volume_type_str);
if (v && v->values[type].idx_volume_values) {
/* Update volume-level */
- volume_ret = set_volume_level_with_new_data(m, type, stream, v->values[type].current_level);
+ volume_ret = set_volume_level_with_new_data(m, stream, type, v->values[type].current_level);
if (volume_ret)
pa_log_error("failed to set_volume_level_by_idx(), stream_type(%d), level(%u), ret(0x%x)",
type, v->values[type].current_level, volume_ret);
/* Update volume-mute */
- volume_ret = set_volume_mute_with_new_data(m, type, stream, v->values[type].is_muted);
+ volume_ret = set_volume_mute_with_new_data(m, stream, type, v->values[type].is_muted);
if (volume_ret)
pa_log_error("failed to set_volume_mute_by_idx(), stream_type(%d), mute(%d), ret(0x%x)",
type, v->values[type].is_muted, volume_ret);
return result;
}
-static void update_buffer_attribute(pa_stream_manager *m, stream_type_t stream_type, void *new_data) {
+static void update_buffer_attribute(pa_stream_manager *m, void *new_data, stream_type_t stream_type) {
int32_t maxlength = -1;
int32_t tlength = -1;
int32_t prebuf = -1;
return;
}
info.direction = (io_direction_t)!stream_type;
- info.sample_spec = (stream_type==STREAM_SINK_INPUT)? &(((pa_sink_input_new_data*)new_data)->sample_spec):
- &(((pa_source_output_new_data*)new_data)->sample_spec);
+ info.sample_spec = GET_STREAM_NEW_SAMPLE_SPEC_PTR(new_data, stream_type);
if (!pa_hal_manager_get_buffer_attribute(m->hal, &info, (uint32_t*)&maxlength, (uint32_t*)&tlength,
(uint32_t*)&prebuf, (uint32_t*)&minreq, (uint32_t*)&fragsize)) {
pa_log_info("start sink_input_new_cb");
- process_stream(m, STREAM_SINK_INPUT, new_data, PROCESS_COMMAND_PREPARE, TRUE);
+ process_stream(m, new_data, STREAM_SINK_INPUT, PROCESS_COMMAND_PREPARE, TRUE);
/* Update buffer attributes from HAL */
- update_buffer_attribute(m, STREAM_SINK_INPUT, new_data);
- process_stream(m, STREAM_SINK_INPUT, new_data, PROCESS_COMMAND_UPDATE_VOLUME, TRUE);
- process_stream(m, STREAM_SINK_INPUT, new_data, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_STARTED, TRUE);
+ update_buffer_attribute(m, new_data, STREAM_SINK_INPUT);
+ process_stream(m, new_data, STREAM_SINK_INPUT, PROCESS_COMMAND_UPDATE_VOLUME, TRUE);
+ process_stream(m, new_data, STREAM_SINK_INPUT, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_STARTED, TRUE);
return PA_HOOK_OK;
}
pa_log_info("start sink_input_put_cb, i(%p, index:%u)", i, i->index);
- process_stream(m, STREAM_SINK_INPUT, i, PROCESS_COMMAND_ADD_PARENT_ID, FALSE);
+ process_stream(m, i, STREAM_SINK_INPUT, PROCESS_COMMAND_ADD_PARENT_ID, FALSE);
return PA_HOOK_OK;
}
pa_sink_input_assert_ref(i);
pa_log_info("start sink_input_unlink_cb, i(%p, index:%u)", i, i->index);
- process_stream(m, STREAM_SINK_INPUT, i, PROCESS_COMMAND_REMOVE_PARENT_ID, FALSE);
- process_stream(m, STREAM_SINK_INPUT, i, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_ENDED, FALSE);
+ process_stream(m, i, STREAM_SINK_INPUT, PROCESS_COMMAND_REMOVE_PARENT_ID, FALSE);
+ process_stream(m, i, STREAM_SINK_INPUT, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_ENDED, FALSE);
return PA_HOOK_OK;
}
switch(state) {
case PA_SINK_INPUT_CORKED: {
- process_stream(m, STREAM_SINK_INPUT, i, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_ENDED, FALSE);
+ process_stream(m, i, STREAM_SINK_INPUT, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_ENDED, FALSE);
break;
}
case PA_SINK_INPUT_DRAINED:
case PA_SINK_INPUT_RUNNING: {
- process_stream(m, STREAM_SINK_INPUT, i, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_STARTED, FALSE);
+ process_stream(m, i, STREAM_SINK_INPUT, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_STARTED, FALSE);
break;
}
default:
pa_log_info("start source_output_new_new_cb");
- process_stream(m, STREAM_SOURCE_OUTPUT, new_data, PROCESS_COMMAND_PREPARE, TRUE);
+ process_stream(m, new_data, STREAM_SOURCE_OUTPUT, PROCESS_COMMAND_PREPARE, TRUE);
/* Update buffer attributes from HAL */
- update_buffer_attribute(m, STREAM_SOURCE_OUTPUT, new_data);
- process_stream(m, STREAM_SOURCE_OUTPUT, new_data, PROCESS_COMMAND_UPDATE_VOLUME, TRUE);
- process_stream(m, STREAM_SOURCE_OUTPUT, new_data, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_STARTED, TRUE);
+ update_buffer_attribute(m, new_data, STREAM_SOURCE_OUTPUT);
+ process_stream(m, new_data, STREAM_SOURCE_OUTPUT, PROCESS_COMMAND_UPDATE_VOLUME, TRUE);
+ process_stream(m, new_data, STREAM_SOURCE_OUTPUT, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_STARTED, TRUE);
return PA_HOOK_OK;
}
pa_log_info("start source_output_put_cb, o(%p, index:%u)", o, o->index);
- process_stream(m, STREAM_SOURCE_OUTPUT, o, PROCESS_COMMAND_ADD_PARENT_ID, FALSE);
+ process_stream(m, o, STREAM_SOURCE_OUTPUT, PROCESS_COMMAND_ADD_PARENT_ID, FALSE);
return PA_HOOK_OK;
}
pa_log_info("start source_output_unlink_cb, o(%p, index:%u)", o, o->index);
- process_stream(m, STREAM_SOURCE_OUTPUT, o, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_ENDED, FALSE);
- process_stream(m, STREAM_SOURCE_OUTPUT, o, PROCESS_COMMAND_REMOVE_PARENT_ID, FALSE);
+ process_stream(m, o, STREAM_SOURCE_OUTPUT, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_ENDED, FALSE);
+ process_stream(m, o, STREAM_SOURCE_OUTPUT, PROCESS_COMMAND_REMOVE_PARENT_ID, FALSE);
return PA_HOOK_OK;
}
switch(state) {
case PA_SOURCE_OUTPUT_CORKED: {
- process_stream(m, STREAM_SOURCE_OUTPUT, o, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_ENDED, FALSE);
+ process_stream(m, o, STREAM_SOURCE_OUTPUT, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_ENDED, FALSE);
break;
}
case PA_SOURCE_OUTPUT_RUNNING: {
- process_stream(m, STREAM_SOURCE_OUTPUT, o, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_STARTED, FALSE);
+ process_stream(m, o, STREAM_SOURCE_OUTPUT, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_STARTED, FALSE);
break;
}
default:
return PA_HOOK_OK;
}
-/* Reorganize routing when a device using internal audio codec has been connected or disconnected */
+static void find_next_priority_device_for_auto_route(const char *cur_device_type, const char *role, stream_type_t stream_type, char **next_device_type, pa_stream_manager *m) {
+ stream_info *si = NULL;
+ pa_idxset *devices = NULL;
+ uint32_t idx = 0;
+ char *device_type = NULL;
+ pa_bool_t ret_next = FALSE;
+
+ pa_assert(m);
+ pa_assert(role);
+ pa_assert(cur_device_type);
+ pa_assert(next_device_type);
+
+ if (m->stream_infos) {
+ si = pa_hashmap_get(m->stream_infos, role);
+ if (si && si->route_type == STREAM_ROUTE_TYPE_AUTO) {
+ devices = (stream_type == STREAM_SINK_INPUT) ? si->idx_avail_out_devices : si->idx_avail_in_devices;
+ if (devices) {
+ PA_IDXSET_FOREACH(device_type, devices, idx) {
+ if (ret_next) {
+ *next_device_type = device_type;
+ pa_log_debug("found next device[%s]", *next_device_type);
+ break;
+ }
+ if (pa_streq(device_type, cur_device_type)) {
+ ret_next = TRUE;
+ continue;
+ }
+ }
+ } else
+ pa_log_error("could not found a device list for this role[%s], stream type[%d]", role, stream_type);
+ } else
+ pa_log_warn("not support this role[%s]", role);
+ } else
+ pa_log_error("stream_infos is null");
+
+ pa_log_debug("next_device_type is [%s] for role[%s]/stream_type[%d]", *next_device_type, role, stream_type);
+
+ return;
+
+FAILURE:
+ *next_device_type = NULL;
+ return;
+}
+
+/* Re-trigger for routing update for streams using auto route type */
+static void process_stream_as_device_change_for_auto_route(pa_stream_manager *m, void *stream, stream_type_t stream_type,
+ pa_bool_t is_connected, pa_bool_t use_internal_codec) {
+ stream_route_type_t route_type;
+
+ pa_assert(m);
+ pa_assert(stream);
+
+ pa_log_debug("[SM][PROCESS_STREAM_FOR_AUTO] stream(%p), stream_type(%d), is_connected(%d), use_internal_codec(%d)",
+ stream, stream_type, is_connected, use_internal_codec);
+
+ if (pa_stream_manager_get_route_type(stream, FALSE, stream_type, &route_type) || route_type != STREAM_ROUTE_TYPE_AUTO)
+ return;
+
+ if (is_connected) {
+ /* it is caused by the connection of supported device for the stream */
+ if (use_internal_codec) {
+ if (((stream_type == STREAM_SINK_INPUT) && (!m->cur_highest_priority.sink_input || (m->cur_highest_priority.sink_input != stream))) ||
+ ((stream_type == STREAM_SOURCE_OUTPUT) && (!m->cur_highest_priority.source_output || (m->cur_highest_priority.source_output != stream))))
+ process_stream(m, stream, stream_type, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_STARTED, FALSE);
+ } else
+ process_stream(m, stream, stream_type, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_ENDED, FALSE);
+ } else {
+ /* it is caused by the disconnection of external device
+ * and the supported next device of this stream using internal audio codec */
+ if (use_internal_codec)
+ process_stream(m, stream, stream_type, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_STARTED, FALSE);
+ }
+
+ return;
+}
+
+/* The state of a device using internal audio codec is handled here.
+ * Regarding the state of an external device, those is handled in device-manager.c */
+static void set_device_state_if_using_internal_codec(dm_device *device, stream_type_t stream_type, dm_device_state_t device_state) {
+ pa_bool_t use_internal_codec = FALSE;
+
+ pa_assert(device);
+
+ if ((use_internal_codec = pa_device_manager_is_device_use_internal_codec(device, CONVERT_TO_DEVICE_DIRECTION(stream_type), DEVICE_ROLE_NORMAL)))
+ pa_device_manager_set_device_state(device, CONVERT_TO_DEVICE_DIRECTION(stream_type), device_state);
+
+ return;
+}
+
+static void update_sink_or_source_as_device_change(stream_route_type_t stream_route_type, pa_idxset *streams,
+ stream_type_t stream_type, dm_device *device, pa_bool_t is_connected, pa_stream_manager *m) {
+ #define MAX_CACHED_LEN 128
+ typedef struct _cached_device_list {
+ const char *device_type;
+ int count;
+ } cached_device_list;
+ void *s = NULL;
+ uint32_t s_idx = 0;
+ const char *role = NULL;
+ const char *device_type = NULL;
+ const char *cur_device_type = NULL;
+ const char *init_device_type = NULL;
+ char *next_device_type = NULL;
+ dm_device *next_device = NULL;
+ dm_device *_device = NULL;
+ stream_route_type_t route_type;
+ pa_sink *sink = NULL;
+ pa_sink *next_sink = NULL;
+ pa_sink *null_sink = NULL;
+ pa_source *source = NULL;
+ pa_source *next_source = NULL;
+ pa_source *null_source = NULL;
+ pa_bool_t available = FALSE;
+ pa_bool_t use_internal_codec = FALSE;
+ cached_device_list cached_prev_dev_list[MAX_CACHED_LEN] = {{NULL,0},};
+ uint32_t cnt = 0;
+ pa_sink *combine_sink = NULL;
+
+ pa_assert(streams);
+ pa_assert(device);
+ pa_assert(m);
+
+ null_sink = (pa_sink*)pa_namereg_get(m->core, SINK_NAME_NULL, PA_NAMEREG_SINK);
+ null_source = (pa_source*)pa_namereg_get(m->core, SOURCE_NAME_NULL, PA_NAMEREG_SOURCE);
+ if (!null_sink || !null_source) {
+ pa_log_error("[SM][UPDATE_SINK_SOURCE] could not get null_sink(%p) or null_source(%p)", null_sink, null_source);
+ return;
+ }
+ device_type = pa_device_manager_get_device_type(device);
+
+ if (stream_route_type == STREAM_ROUTE_TYPE_AUTO) {
+ pa_log_debug("[SM][UPDATE_SINK_SOURCE][AUTO] deivce_type(%s), is_connected(%d))", device_type, is_connected);
+ if (stream_type == STREAM_SINK_INPUT)
+ sink = pa_device_manager_get_sink(device, DEVICE_ROLE_NORMAL);
+ else
+ source = pa_device_manager_get_source(device, DEVICE_ROLE_NORMAL);
+
+ PA_IDXSET_FOREACH (s, streams, s_idx) { /* streams: core->source_outputs/core->sink_inputs */
+ if (!pa_stream_manager_get_route_type(s, FALSE, stream_type, &route_type) && (route_type == stream_route_type)) {
+ role = pa_proplist_gets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_ROLE);
+ pa_log_debug(" -- idx(%u), route_type(%d), role(%s)", s_idx, route_type, role);
+ if (is_connected) {
+ /* CONNECTED: move a stream to the new device if possible */
+ if (sink && (sink != ((pa_sink_input*)s)->sink)) {
+ if ((cur_device_type = pa_proplist_gets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV))) {
+ pa_stream_manager_is_available_device_for_auto_route(cur_device_type, device_type, role, stream_type, &available, m);
+ if (available) {
+ pa_sink_input_move_to(s, sink, FALSE);
+ pa_log_debug(" -- *** sink-input(%p,%u) moves to sink(%p,%s), new device(%s)",
+ s, ((pa_sink_input*)s)->index, sink, sink->name, device_type);
+ use_internal_codec = sink->use_internal_codec;
+ }
+ } else
+ pa_log_error(" -- could not find current device type for s->sink(%p)", ((pa_sink_input*)s)->sink);
+ } else if (source && (source != ((pa_source_output*)s)->source)) {
+ if ((cur_device_type = pa_proplist_gets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV))) {
+ pa_stream_manager_is_available_device_for_auto_route(cur_device_type, device_type, role, stream_type, &available, m);
+ if (available) {
+ pa_source_output_move_to(s, source, FALSE);
+ pa_log_debug(" -- *** source-output(%p,%u) moves to source(%p,%s), new device(%s)",
+ s, ((pa_source_output*)s)->index, source, source->name, device_type);
+ use_internal_codec = source->use_internal_codec;
+ }
+ } else
+ pa_log_error(" -- could not find current device type for s->source(%p)", ((pa_source_output*)s)->source);
+ }
+ if (available) {
+ /* update activated device */
+ pa_proplist_sets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, device_type);
+ if ((_device = pa_device_manager_get_device(m->dm, device_type)))
+ set_device_state_if_using_internal_codec(_device, stream_type, DM_DEVICE_STATE_ACTIVATED);
+ cached_prev_dev_list[cnt++].device_type = cur_device_type;
+ /* trigger to update routing path */
+ process_stream_as_device_change_for_auto_route(m, s, stream_type, is_connected, use_internal_codec);
+ }
+ } else if (!is_connected) {
+ /* DISCONNECTED: find a connected device that has the next priority */
+ if (sink && (sink == ((pa_sink_input*)s)->sink)) {
+ init_device_type = device_type;
+ do {
+ find_next_priority_device_for_auto_route(device_type, role, stream_type, &next_device_type, m);
+ pa_log_debug(" -- prev_device(%s), new_device(%s)", device_type, next_device_type);
+ if (next_device_type) {
+ if ((next_device = pa_device_manager_get_device(m->dm, next_device_type))) {
+ if ((next_sink = pa_device_manager_get_sink(next_device, DEVICE_ROLE_NORMAL))) {
+ /* update activated device */
+ pa_proplist_sets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, next_device_type);
+ set_device_state_if_using_internal_codec(next_device, stream_type, DM_DEVICE_STATE_ACTIVATED);
+ cached_prev_dev_list[cnt++].device_type = init_device_type;
+ /* trigger to update routing path if the next device uses internal audio codec */
+ if (next_sink->use_internal_codec)
+ process_stream_as_device_change_for_auto_route(m, s, stream_type, is_connected, next_sink->use_internal_codec);
+
+ pa_sink_input_move_to(s, next_sink, FALSE);
+ pa_log_debug(" -- *** sink-input(%p,%u) moves to sink(%p,%s), new device(%s)",
+ s, ((pa_sink_input*)s)->index, next_sink, next_sink->name, next_device_type);
+ break;
+ }
+ } else {
+ device_type = next_device_type;
+ continue;
+ }
+ }
+ } while (next_device_type);
+
+ if (!next_device_type || !next_sink) {
+ pa_sink_input_move_to(s, null_sink, FALSE);
+ pa_log_debug(" -- *** sink-input(%p,%u) moves to sink(%p,%s)",
+ s, ((pa_sink_input*)s)->index, null_sink, null_sink->name);
+ }
+
+ } else if (source && (source == ((pa_source_output*)s)->source)) {
+ init_device_type = device_type;
+ do {
+ find_next_priority_device_for_auto_route(device_type, role, stream_type, &next_device_type, m);
+ pa_log_debug(" -- prev_device(%s), new_device(%s)", device_type, next_device_type);
+ if (next_device_type) {
+ if ((next_device = pa_device_manager_get_device(m->dm, next_device_type))) {
+ if ((next_source = pa_device_manager_get_source(next_device, DEVICE_ROLE_NORMAL))) {
+ /* update activated device */
+ pa_proplist_sets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, next_device_type);
+ set_device_state_if_using_internal_codec(next_device, stream_type, DM_DEVICE_STATE_ACTIVATED);
+ cached_prev_dev_list[cnt++].device_type = init_device_type;
+ /* trigger to update routing path if the next device uses internal audio codec */
+ if (next_source->use_internal_codec)
+ process_stream_as_device_change_for_auto_route(m, s, stream_type, is_connected, next_source->use_internal_codec);
+
+ pa_source_output_move_to(s, next_source, FALSE);
+ pa_log_debug(" -- *** source-output(%p,%u) moves to source(%p,%s), new device(%s)",
+ s, ((pa_source_output*)s)->index, next_source, next_source->name, next_device_type);
+ break;
+ }
+ } else {
+ device_type = next_device_type;
+ continue;
+ }
+ }
+ } while (next_device_type);
+
+ if (!next_device_type || !next_source) {
+ pa_source_output_move_to(s, null_source, FALSE);
+ pa_log_debug(" -- *** source-output(%p,%u) moves to source(%p,%s)",
+ s, ((pa_source_output*)s)->index, null_source, null_source->name);
+ }
+ }
+ }
+ }
+ }
+
+ /* set device state to deactivated */
+ if (cnt) {
+ PA_IDXSET_FOREACH (s, streams, s_idx) { /* streams: core->source_outputs/core->sink_inputs */
+ if ((cur_device_type = pa_proplist_gets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV))) {
+ for (cnt = 0; cached_prev_dev_list[cnt].device_type; cnt++) {
+ pa_log_warn(" -- cur_device(%s), cached_device(%s)", cur_device_type, cached_prev_dev_list[cnt].device_type);
+ if (pa_streq(cur_device_type, cached_prev_dev_list[cnt].device_type))
+ cached_prev_dev_list[cnt].count++;
+ }
+ }
+ }
+ if (stream_type == STREAM_SINK_INPUT) {
+ combine_sink = (pa_sink*)pa_namereg_get(m->core, SINK_NAME_COMBINED, PA_NAMEREG_SINK);
+ if (combine_sink && pa_idxset_size(combine_sink->inputs)) {
+ pa_log_warn(" -- combine sink has streams, skip it..");
+ return;
+ }
+ }
+ for (cnt = 0; cached_prev_dev_list[cnt].device_type; cnt++) {
+ if (cached_prev_dev_list[cnt].count == 0) {
+ pa_log_debug(" -- device_type(%s)", cached_prev_dev_list[cnt].device_type);
+ if ((_device = pa_device_manager_get_device(m->dm, cached_prev_dev_list[cnt].device_type)))
+ set_device_state_if_using_internal_codec(_device, stream_type, DM_DEVICE_STATE_DEACTIVATED);
+ else
+ pa_log_warn(" -- _device is null");
+ }
+ }
+ }
+
+ } else if (stream_route_type == STREAM_ROUTE_TYPE_MANUAL_EXT) {
+ pa_log_debug("[SM][UPDATE_SINK_SOURCE][EXT] deivce_type(%s), is_connected(%d))", device_type, is_connected);
+ if (!is_connected) {
+ PA_IDXSET_FOREACH (s, streams, s_idx) { /* streams: source->outputs/sink->inputs */
+ if (!pa_stream_manager_get_route_type(s, FALSE, stream_type, &route_type) && route_type == stream_route_type) {
+ if (stream_type == STREAM_SOURCE_OUTPUT) {
+ /* move it to null source if this role is for external device */
+ pa_source_output_move_to((pa_source_output*)s, null_source, FALSE);
+ pa_log_debug(" -- *** source-output(%p,%u) moves to source(%p,%s)", s, ((pa_source_output*)s)->index, null_source, null_source->name);
+ } else {
+ /* move it to null sink if this role is for external device */
+ pa_sink_input_move_to((pa_sink_input*)s, null_sink, FALSE);
+ pa_log_debug(" -- *** sink-input(%p,%u) moves to sink(%p,%s)", s, ((pa_sink_input*)s)->index, null_sink, null_sink->name);
+ }
+ }
+ }
+ }
+ } else
+ pa_log_error("[SM][UPDATE_SINK_SOURCE] could not handle it here, stream_route_type(%d)", stream_route_type);
+
+ return;
+}
+
+/* Reorganize routing when a device has been connected or disconnected */
static pa_hook_result_t device_connection_changed_hook_cb(pa_core *c, pa_device_manager_hook_data_for_conn_changed *data, pa_stream_manager *m) {
const char *active_dev = NULL;
const char *device_type = NULL;
pa_bool_t use_internal_codec = FALSE;
void *s = NULL;
uint32_t s_idx = 0;
+ pa_sink *sink = NULL;
+ pa_source *source = NULL;
pa_assert(c);
pa_assert(data);
device_type = pa_device_manager_get_device_type(data->device);
use_internal_codec = pa_device_manager_is_device_use_internal_codec(data->device, device_direction, DEVICE_ROLE_NORMAL);
- pa_log_info("[SM] device_connection_changed_hook_cb is called. data(%p), is_connected(%d), device(%p, %s), direction(0x%x), use_internal_codec(%d)",
+ pa_log_info("[SM][CONN] device_connection_changed_hook_cb is called. data(%p), is_connected(%d), device(%p, %s), direction(0x%x), use_internal_codec(%d)",
data, data->is_connected, data->device, device_type, device_direction, use_internal_codec);
+
+ /* Update streams belong to this external device that have MAUAL_EXT route type */
+ if (!use_internal_codec && (device_direction & DM_DEVICE_DIRECTION_IN)) {
+ if ((source = pa_device_manager_get_source(data->device, DEVICE_ROLE_NORMAL)))
+ update_sink_or_source_as_device_change(STREAM_ROUTE_TYPE_MANUAL_EXT, source->outputs,
+ STREAM_SOURCE_OUTPUT, data->device, data->is_connected, m);
+ else
+ pa_log_error("[SM][CONN] could not get source");
+ }
+ if (!use_internal_codec && (device_direction & DM_DEVICE_DIRECTION_OUT)) {
+ if ((sink = pa_device_manager_get_sink(data->device, DEVICE_ROLE_NORMAL)))
+ update_sink_or_source_as_device_change(STREAM_ROUTE_TYPE_MANUAL_EXT, sink->inputs,
+ STREAM_SINK_INPUT,data->device, data->is_connected, m);
+ else
+ pa_log_error("[SM][CONN] could not get sink");
+ }
+
+ /* Update all the streams that have AUTO route type */
+ if (device_direction & DM_DEVICE_DIRECTION_IN)
+ update_sink_or_source_as_device_change(STREAM_ROUTE_TYPE_AUTO, m->core->source_outputs,
+ STREAM_SOURCE_OUTPUT, data->device, data->is_connected, m);
+ if (device_direction & DM_DEVICE_DIRECTION_OUT)
+ update_sink_or_source_as_device_change(STREAM_ROUTE_TYPE_AUTO, m->core->sink_inputs,
+ STREAM_SINK_INPUT, data->device, data->is_connected, m);
+
+
/* If the route type of the stream is not manual, notify again */
if (m->cur_highest_priority.source_output && (device_direction & DM_DEVICE_DIRECTION_IN)) {
if (!pa_stream_manager_get_route_type(m->cur_highest_priority.source_output, FALSE, STREAM_SOURCE_OUTPUT, &route_type)) {
/* remove activated device info. if it has the AUTO route type */
active_dev = pa_proplist_gets(GET_STREAM_PROPLIST(s, STREAM_SOURCE_OUTPUT), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV);
if (pa_streq(active_dev, device_type))
- pa_proplist_sets(GET_STREAM_PROPLIST(s, STREAM_SOURCE_OUTPUT), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, "removed");
+ pa_proplist_sets(GET_STREAM_PROPLIST(s, STREAM_SOURCE_OUTPUT), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, ACTIVE_DEV_REMOVED);
}
}
do_notify(m, NOTIFY_COMMAND_CHANGE_ROUTE_START, STREAM_SOURCE_OUTPUT, FALSE, m->cur_highest_priority.source_output);
/* If the source of the cur_highest_priority stream uses external codec, it should be updated.
* As only the process_stream(PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_ENDED)
* can update the cur_highest_priority, call it here */
- process_stream(m, STREAM_SOURCE_OUTPUT, m->cur_highest_priority.source_output, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_ENDED, FALSE);
+ process_stream(m, m->cur_highest_priority.source_output, STREAM_SOURCE_OUTPUT, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_ENDED, FALSE);
}
}
}
/* remove activated device info. if it has the AUTO route type */
active_dev = pa_proplist_gets(GET_STREAM_PROPLIST(s, STREAM_SINK_INPUT), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV);
if (pa_streq(active_dev, device_type))
- pa_proplist_sets(GET_STREAM_PROPLIST(s, STREAM_SINK_INPUT), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, "removed");
+ pa_proplist_sets(GET_STREAM_PROPLIST(s, STREAM_SINK_INPUT), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, ACTIVE_DEV_REMOVED);
}
}
do_notify(m, NOTIFY_COMMAND_CHANGE_ROUTE_START, STREAM_SINK_INPUT, FALSE, m->cur_highest_priority.sink_input);
/* If the sink of the cur_highest_priority stream uses external codec, it should be updated.
* As only the process_stream(PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_ENDED)
* can update the cur_highest_priority, call it here */
- process_stream(m, STREAM_SINK_INPUT, m->cur_highest_priority.sink_input, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_ENDED, FALSE);
+ process_stream(m, m->cur_highest_priority.sink_input, STREAM_SINK_INPUT, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_ENDED, FALSE);
}
} else if (route_type == STREAM_ROUTE_TYPE_AUTO_ALL)
do_notify(m, NOTIFY_COMMAND_CHANGE_ROUTE_START, STREAM_SINK_INPUT, FALSE, m->cur_highest_priority.sink_input);
return PA_HOOK_OK;
}
-/* Re-trigger for updating audio routing regarding internal audio codec */
-static pa_hook_result_t need_update_route_hook_cb(pa_core *c, pa_stream_manager_hook_data_for_update_route *data, pa_stream_manager *m) {
- pa_assert(c);
- pa_assert(data);
- pa_assert(m);
-
- pa_log_info("[SM] need_update_route_hook_cb is called. data(%p), stream(%p), stream_type(%d), is_device_connected(%d), use_internal_codec(%d)",
- data, data->stream, data->stream_type, data->is_device_connected, data->use_internal_codec);
-
- if (data->is_device_connected) {
- /* it is caused by the connection of supported device for the stream */
- if (data->use_internal_codec) {
- if (((data->stream_type == STREAM_SINK_INPUT) && (!m->cur_highest_priority.sink_input || (m->cur_highest_priority.sink_input != data->stream))) ||
- ((data->stream_type == STREAM_SOURCE_OUTPUT) && (!m->cur_highest_priority.source_output || (m->cur_highest_priority.source_output != data->stream))))
- process_stream(m, data->stream_type, data->stream, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_STARTED, FALSE);
- } else
- process_stream(m, data->stream_type, data->stream, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_ENDED, FALSE);
- } else {
- /* it is caused by the disconnection of external device
- * and the supported next device of this stream using internal audio codec */
- if (data->use_internal_codec)
- process_stream(m, data->stream_type, data->stream, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_STARTED, FALSE);
- }
-
- return PA_HOOK_OK;
-}
-
static void subscribe_cb(pa_core *core, pa_subscription_event_type_t t, uint32_t idx, pa_stream_manager *m) {
pa_client *client = NULL;
stream_parent *sp = NULL;
uint32_t _idx = 0;
pa_core_assert_ref(core);
pa_assert(m);
+
pa_log_info("subscribe_cb() is called, t(%x), idx(%u)", t, idx);
+ if ((client = pa_idxset_get_by_index(core->clients, idx)) == NULL) {
+ pa_log_error(" - could not find any client that has idx(%u)", idx);
+ return;
+ }
+ name = pa_proplist_gets(client->proplist, PA_PROP_APPLICATION_NAME);
+ if (strncmp (name, STREAM_MANAGER_CLIENT_NAME, strlen(STREAM_MANAGER_CLIENT_NAME))) {
+ pa_log_warn(" - this is not a client(%s) that we should take care of, skip it", name);
+ return;
+ }
+
if (t == (PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_CHANGE)) {
- client = pa_idxset_get_by_index(core->clients, idx);
- if (client == NULL) {
- pa_log_error(" - could not find any client that has idx(%u)", idx);
- return;
- }
- name = pa_proplist_gets(client->proplist, PA_PROP_APPLICATION_NAME);
- if (strncmp (name, STREAM_MANAGER_CLIENT_NAME, strlen(STREAM_MANAGER_CLIENT_NAME))) {
- pa_log_warn(" - this is not a client(%s) that we should take care of, skip it", name);
- return;
- }
/* add a stream parent */
sp = pa_xmalloc0(sizeof(stream_parent));
sp->idx_sink_inputs = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
sp->idx_route_out_devices = pa_idxset_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
pa_hashmap_put(m->stream_parents, (void*)idx, sp);
pa_log_debug(" - add sp(%p), idx(%u)", sp, idx);
+
} else if (t == (PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_REMOVE)) {
/* remove the stream parent */
sp = pa_hashmap_get(m->stream_parents, (const void*)idx);
return 0;
}
-void pa_stream_manager_is_current_highest_priority(void *stream, stream_type_t stream_type, pa_bool_t *highest_priority, pa_stream_manager *m) {
- pa_assert(stream);
- pa_assert(highest_priority);
- pa_assert(m);
-
- if ((stream_type == STREAM_SINK_INPUT) && (stream == m->cur_highest_priority.sink_input)) {
- *highest_priority = TRUE;
- pa_log_debug("stream(%p) is same as cur_highest_priority.sink_input(%p)", stream, m->cur_highest_priority.sink_input);
- } else if ((stream_type == STREAM_SOURCE_OUTPUT) && (stream == m->cur_highest_priority.source_output)) {
- *highest_priority = TRUE;
- pa_log_debug("stream(%p) is same as cur_highest_priority.source_output(%p)", stream, m->cur_highest_priority.source_output);
- } else
- *highest_priority = FALSE;
-
- return;
-}
-
void pa_stream_manager_is_available_device_for_auto_route(const char *cur_device_type, const char *new_device_type, const char *role, stream_type_t stream_type, pa_bool_t *available, pa_stream_manager *m) {
stream_info *si = NULL;
pa_idxset *devices = NULL;
si = pa_hashmap_get(m->stream_infos, role);
if (si) {
*available = FALSE;
- devices = (stream_type==STREAM_SINK_INPUT)?si->idx_avail_out_devices:si->idx_avail_in_devices;
+ devices = (stream_type == STREAM_SINK_INPUT) ? si->idx_avail_out_devices : si->idx_avail_in_devices;
if (devices) {
PA_IDXSET_FOREACH(device_type, devices, idx) {
if (cur_device_type && pa_streq(device_type, cur_device_type)) {
return;
}
-void pa_stream_manager_find_next_priority_device_for_auto_route(const char *cur_device_type, const char *role, stream_type_t stream_type, char **next_device_type, pa_stream_manager *m) {
- stream_info *si = NULL;
- pa_idxset *devices = NULL;
- uint32_t idx = 0;
- char *device_type = NULL;
- pa_bool_t ret_next = FALSE;
-
- pa_assert(m);
- pa_assert(role);
- pa_assert(cur_device_type);
- pa_assert(next_device_type);
-
- if (m->stream_infos) {
- si = pa_hashmap_get(m->stream_infos, role);
- if (si) {
- devices = (stream_type==STREAM_SINK_INPUT)?si->idx_avail_out_devices:si->idx_avail_in_devices;
- if (devices) {
- PA_IDXSET_FOREACH(device_type, devices, idx) {
- if (ret_next) {
- *next_device_type = device_type;
- pa_log_debug("found next device[%s]", *next_device_type);
- break;
- }
- if (pa_streq(device_type, cur_device_type)) {
- ret_next = TRUE;
- continue;
- }
- }
- } else {
- pa_log_error("could not found a device list for this role[%s], stream type[%d]", role, stream_type);
- *next_device_type = NULL;
- }
- } else {
- pa_log_warn("not support this role[%s]", role);
- *next_device_type = NULL;
- }
- } else {
- pa_log_error("stream_infos is null");
- *next_device_type = NULL;
- }
- pa_log_debug("next_device_type is [%s] for role[%s]/stream_type[%d]", *next_device_type, role, stream_type);
-
- return;
-}
-
pa_stream_manager* pa_stream_manager_init(pa_core *c) {
pa_stream_manager *m;
m->hal = pa_hal_manager_get(c);
+ m->dm = pa_device_manager_get(c);
#ifdef HAVE_DBUS
#ifdef USE_DBUS_PROTOCOL
m->dbus_protocol = NULL;
m->source_output_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK], PA_HOOK_EARLY, (pa_hook_cb_t) source_output_unlink_cb, m);
m->source_output_state_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_STATE_CHANGED], PA_HOOK_EARLY, (pa_hook_cb_t) source_output_state_changed_cb, m);
-
m->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_CLIENT | PA_SUBSCRIPTION_MASK_SAMPLE_CACHE, (pa_subscription_cb_t)subscribe_cb, m);
m->comm.comm = pa_communicator_get(c);
m->comm.comm_hook_device_connection_changed_slot = pa_hook_connect(pa_communicator_hook(m->comm.comm,PA_COMMUNICATOR_HOOK_DEVICE_CONNECTION_CHANGED),
PA_HOOK_EARLY + 10, (pa_hook_cb_t) device_connection_changed_hook_cb, m);
- m->comm.comm_hook_need_update_route_slot = pa_hook_connect(pa_communicator_hook(m->comm.comm,PA_COMMUNICATOR_HOOK_NEED_UPDATE_ROUTE),
- PA_HOOK_EARLY, (pa_hook_cb_t) need_update_route_hook_cb, m);
return m;
if (m->comm.comm) {
if (m->comm.comm_hook_device_connection_changed_slot)
pa_hook_slot_free(m->comm.comm_hook_device_connection_changed_slot);
- if (m->comm.comm_hook_need_update_route_slot)
- pa_hook_slot_free(m->comm.comm_hook_need_update_route_slot);
pa_communicator_unref(m->comm.comm);
}
deinit_stream_map(m);
deinit_ipc(m);
+ if (m->dm)
+ pa_device_manager_unref(m->dm);
+
if (m->hal)
pa_hal_manager_unref(m->hal);
#define GET_STREAM_PROPLIST(stream, type) \
(type == STREAM_SINK_INPUT? ((pa_sink_input*)stream)->proplist : ((pa_source_output*)stream)->proplist)
+#define SINK_NAME_COMBINED "sink_combined"
+#define SINK_NAME_NULL "sink_null"
+#define SOURCE_NAME_NULL "source_null"
+
typedef struct _stream_manager pa_stream_manager;
typedef enum _stream_type {
int32_t value;
} pa_stream_manager_hook_data_for_option;
-typedef struct _hook_call_data_for_update_route {
- void *stream;
- stream_type_t stream_type;
- pa_bool_t is_device_connected;
- pa_bool_t use_internal_codec;
-} pa_stream_manager_hook_data_for_update_route;
-
int32_t pa_stream_manager_get_route_type(void *stream, pa_bool_t origins_from_new_data, stream_type_t stream_type, stream_route_type_t *stream_route_type);
-void pa_stream_manager_is_current_highest_priority(void *stream, stream_type_t stream_type, pa_bool_t *highest_priority, pa_stream_manager *m);
void pa_stream_manager_is_available_device_for_auto_route(const char *cur_device_type, const char *new_device_type, const char *role, stream_type_t stream_type, pa_bool_t *available, pa_stream_manager *m);
void pa_stream_manager_find_next_priority_device_for_auto_route(const char *cur_device_type, const char *role, stream_type_t stream_type, char **next_device_type, pa_stream_manager *m);