diff options
Diffstat (limited to 'tizen-audio-routing.c')
-rw-r--r-- | tizen-audio-routing.c | 336 |
1 files changed, 336 insertions, 0 deletions
diff --git a/tizen-audio-routing.c b/tizen-audio-routing.c new file mode 100644 index 0000000..8be716b --- /dev/null +++ b/tizen-audio-routing.c @@ -0,0 +1,336 @@ +/* + * audio-hal + * + * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> + +#include "tizen-audio-internal.h" +#include "tizen-audio-impl.h" + +/* #define DEBUG_TIMING */ + +static device_type_t outDeviceTypes[] = { + { AUDIO_DEVICE_OUT_SPEAKER, "Speaker" }, + { AUDIO_DEVICE_OUT_JACK, "Headphones" }, + { AUDIO_DEVICE_OUT_BT_SCO, "Bluetooth" }, + { AUDIO_DEVICE_OUT_AUX, "Line" }, + { AUDIO_DEVICE_OUT_HDMI, "HDMI" }, + { 0, 0 }, +}; + +static device_type_t inDeviceTypes[] = { + { AUDIO_DEVICE_IN_MAIN_MIC, "MainMic" }, + { AUDIO_DEVICE_IN_JACK, "HeadsetMic" }, + { AUDIO_DEVICE_IN_BT_SCO, "BT Mic" }, + { 0, 0 }, +}; + +static const char* mode_to_verb_str[] = { + AUDIO_USE_CASE_VERB_HIFI, +}; + +static uint32_t __convert_device_string_to_enum(const char* device_str, uint32_t direction) +{ + uint32_t device = 0; + + if (!strncmp(device_str, "builtin-speaker", MAX_NAME_LEN)) { + device = AUDIO_DEVICE_OUT_SPEAKER; + } else if (!strncmp(device_str, "builtin-receiver", MAX_NAME_LEN)) { + device = AUDIO_DEVICE_OUT_RECEIVER; + } else if ((!strncmp(device_str, "audio-jack", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_OUT)) { + device = AUDIO_DEVICE_OUT_JACK; + } else if ((!strncmp(device_str, "bt-sco", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_OUT)) { + device = AUDIO_DEVICE_OUT_BT_SCO; + } else if (!strncmp(device_str, "aux", MAX_NAME_LEN)) { + device = AUDIO_DEVICE_OUT_AUX; + } else if (!strncmp(device_str, "hdmi", MAX_NAME_LEN)) { + device = AUDIO_DEVICE_OUT_HDMI; + } else if ((!strncmp(device_str, "builtin-mic", MAX_NAME_LEN))) { + device = AUDIO_DEVICE_IN_MAIN_MIC; + } else if ((!strncmp(device_str, "audio-jack", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_IN)) { + device = AUDIO_DEVICE_IN_JACK; + } else if ((!strncmp(device_str, "bt-sco", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_IN)) { + device = AUDIO_DEVICE_IN_BT_SCO; + } else { + device = AUDIO_DEVICE_NONE; + } + AUDIO_LOG_INFO("device type(%s), enum(0x%x)", device_str, device); + return device; +} + +static audio_return_t __set_devices(audio_hal_t *ah, const char *verb, device_info_t *devices, uint32_t num_of_devices) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + uint32_t new_device = 0; + const char *active_devices[MAX_DEVICES] = {NULL,}; + int i = 0, j = 0, dev_idx = 0; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(devices, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(num_of_devices, AUDIO_ERR_PARAMETER); + + if (num_of_devices > MAX_DEVICES) { + num_of_devices = MAX_DEVICES; + AUDIO_LOG_ERROR("error: num_of_devices"); + return AUDIO_ERR_PARAMETER; + } + + if (devices[0].direction == AUDIO_DIRECTION_OUT) { + ah->device.active_out &= 0x0; + if (ah->device.active_in) { + /* check the active in devices */ + for (j = 0; j < inDeviceTypes[j].type; j++) { + if (((ah->device.active_in & (~AUDIO_DEVICE_IN)) & inDeviceTypes[j].type)) + active_devices[dev_idx++] = inDeviceTypes[j].name; + } + } + } else if (devices[0].direction == AUDIO_DIRECTION_IN) { + ah->device.active_in &= 0x0; + if (ah->device.active_out) { + /* check the active out devices */ + for (j = 0; j < outDeviceTypes[j].type; j++) { + if (ah->device.active_out & outDeviceTypes[j].type) + active_devices[dev_idx++] = outDeviceTypes[j].name; + } + } + } + + for (i = 0; i < num_of_devices; i++) { + new_device = __convert_device_string_to_enum(devices[i].type, devices[i].direction); + if (new_device & AUDIO_DEVICE_IN) { + for (j = 0; j < inDeviceTypes[j].type; j++) { + if (new_device == inDeviceTypes[j].type) { + active_devices[dev_idx++] = inDeviceTypes[j].name; + ah->device.active_in |= new_device; + } + } + } else { + for (j = 0; j < outDeviceTypes[j].type; j++) { + if (new_device == outDeviceTypes[j].type) { + active_devices[dev_idx++] = outDeviceTypes[j].name; + ah->device.active_out |= new_device; + } + } + } + } + + if (active_devices[0] == NULL) { + AUDIO_LOG_ERROR("Failed to set device: active device is NULL"); + return AUDIO_ERR_PARAMETER; + } + + audio_ret = _ucm_set_devices(ah, verb, active_devices); + if (audio_ret) + AUDIO_LOG_ERROR("Failed to set device: error = %d", audio_ret); + + return audio_ret; +} + +static audio_return_t __update_route_ap_playback_capture(audio_hal_t *ah, audio_route_info_t *route_info) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + device_info_t *devices = NULL; + const char *verb = mode_to_verb_str[VERB_NORMAL]; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(route_info, AUDIO_ERR_PARAMETER); + + devices = route_info->device_infos; + + /* To Do: Set modifiers */ + /* int mod_idx = 0; */ + /* const char *modifiers[MAX_MODIFIERS] = {NULL,}; */ + + AUDIO_LOG_INFO("update_route_ap_playback_capture++ "); + + audio_ret = __set_devices(ah, verb, devices, route_info->num_of_devices); + if (audio_ret) { + AUDIO_LOG_ERROR("Failed to set devices: error = 0x%x", audio_ret); + return audio_ret; + } + ah->device.mode = VERB_NORMAL; + + /* To Do: Set modifiers */ + /* + if (!strncmp("voice_recognition", route_info->role, MAX_NAME_LEN)) { + modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_VOICESEARCH; + } else if ((!strncmp("alarm", route_info->role, MAX_NAME_LEN))||(!strncmp("notifiication", route_info->role, MAX_NAME_LEN))) { + if (ah->device.active_out &= AUDIO_DEVICE_OUT_JACK) + modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_DUAL_MEDIA; + else + modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_MEDIA; + } else { + if (ah->device.active_in) + modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_CAMCORDING; + else + modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_MEDIA; + } + audio_ret = _audio_ucm_set_modifiers (ah, verb, modifiers); + */ + + return audio_ret; +} + +static audio_return_t __update_route_voip(audio_hal_t *ah, device_info_t *devices, int32_t num_of_devices) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + const char *verb = mode_to_verb_str[VERB_NORMAL]; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(devices, AUDIO_ERR_PARAMETER); + + AUDIO_LOG_INFO("update_route_voip++"); + + audio_ret = __set_devices(ah, verb, devices, num_of_devices); + if (audio_ret) { + AUDIO_LOG_ERROR("Failed to set devices: error = 0x%x", audio_ret); + return audio_ret; + } + /* FIXME. If necessary, set VERB_VOIP */ + ah->device.mode = VERB_NORMAL; + + /* TO DO: Set modifiers */ + return audio_ret; +} + +static audio_return_t __update_route_reset(audio_hal_t *ah, uint32_t direction) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + const char *active_devices[MAX_DEVICES] = {NULL,}; + int i = 0, dev_idx = 0; + + /* FIXME: If you need to reset, set verb inactive */ + /* const char *verb = NULL; */ + /* verb = AUDIO_USE_CASE_VERB_INACTIVE; */ + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + + AUDIO_LOG_INFO("update_route_reset++, direction(0x%x)", direction); + + if (direction == AUDIO_DIRECTION_OUT) { + ah->device.active_out &= 0x0; + if (ah->device.active_in) { + /* check the active in devices */ + for (i = 0; i < inDeviceTypes[i].type; i++) { + if (((ah->device.active_in & (~AUDIO_DEVICE_IN)) & inDeviceTypes[i].type)) { + active_devices[dev_idx++] = inDeviceTypes[i].name; + AUDIO_LOG_INFO("added for in : %s", inDeviceTypes[i].name); + } + } + } + } else { + ah->device.active_in &= 0x0; + if (ah->device.active_out) { + /* check the active out devices */ + for (i = 0; i < outDeviceTypes[i].type; i++) { + if (ah->device.active_out & outDeviceTypes[i].type) { + active_devices[dev_idx++] = outDeviceTypes[i].name; + AUDIO_LOG_INFO("added for out : %s", outDeviceTypes[i].name); + } + } + } + } + + if (active_devices[0] == NULL) { + AUDIO_LOG_DEBUG("active device is NULL, no need to update."); + return AUDIO_RET_OK; + } + + if ((audio_ret = _ucm_set_devices(ah, mode_to_verb_str[ah->device.mode], active_devices))) + AUDIO_LOG_ERROR("failed to _ucm_set_devices(), ret(0x%x)", audio_ret); + + return audio_ret; +} + +audio_return_t _audio_routing_init(audio_hal_t *ah) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + + ah->device.active_in = 0x0; + ah->device.active_out = 0x0; + ah->device.mode = VERB_NORMAL; + + if ((audio_ret = _ucm_init(ah))) + AUDIO_LOG_ERROR("failed to _ucm_init(), ret(0x%x)", audio_ret); + + return audio_ret; +} + +audio_return_t _audio_routing_deinit(audio_hal_t *ah) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + + if ((audio_ret = _ucm_deinit(ah))) + AUDIO_LOG_ERROR("failed to _ucm_deinit(), ret(0x%x)", audio_ret); + + return audio_ret; +} + +audio_return_t audio_update_route(void *audio_handle, audio_route_info_t *info) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + audio_hal_t *ah = (audio_hal_t *)audio_handle; + device_info_t *devices = NULL; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(info->role, AUDIO_ERR_PARAMETER); + + AUDIO_LOG_INFO("role:%s", info->role); + + devices = info->device_infos; + + if (!strncmp("voip", info->role, MAX_NAME_LEN)) { + if ((audio_ret = __update_route_voip(ah, devices, info->num_of_devices))) + AUDIO_LOG_WARN("update voip route return 0x%x", audio_ret); + + } else if (!strncmp("reset", info->role, MAX_NAME_LEN)) { + if ((audio_ret = __update_route_reset(ah, devices->direction))) + AUDIO_LOG_WARN("update reset return 0x%x", audio_ret); + + } else { + /* need to prepare for "alarm","notification","emergency","voice-information","voice-recognition","ringtone" */ + if ((audio_ret = __update_route_ap_playback_capture(ah, info))) + AUDIO_LOG_WARN("update playback route return 0x%x", audio_ret); + } + return audio_ret; +} + +audio_return_t audio_update_route_option(void *audio_handle, audio_route_option_t *option) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + audio_hal_t *ah = (audio_hal_t *)audio_handle; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(option, AUDIO_ERR_PARAMETER); + + AUDIO_LOG_INFO("role:%s, name:%s, value:%d", option->role, option->name, option->value); + + return audio_ret; +} |