4 * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
29 #include "tizen-audio-internal.h"
30 #include "tizen-audio-impl.h"
34 /* #define DEBUG_TIMING */
36 static device_type_s outDeviceTypes[] = {
37 { AUDIO_DEVICE_OUT_SPEAKER, "Speaker" },
38 { AUDIO_DEVICE_OUT_BT_SCO, "Bluetooth" },
39 { AUDIO_DEVICE_OUT_AUX, "Line" },
40 { AUDIO_DEVICE_OUT_HDMI, "HDMI" },
44 static device_type_s inDeviceTypes[] = {
45 { AUDIO_DEVICE_IN_BT_SCO, "BT Mic" },
49 static const char* mode_to_verb_str[] = {
50 AUDIO_USE_CASE_VERB_HIFI,
53 static uint32_t __convert_device_string_to_enum(const char* device_str, uint32_t direction)
57 if (!strncmp(device_str, "builtin-speaker", MAX_NAME_LEN)) {
58 device = AUDIO_DEVICE_OUT_SPEAKER;
59 } else if (!strncmp(device_str, "builtin-receiver", MAX_NAME_LEN)) {
60 device = AUDIO_DEVICE_OUT_RECEIVER;
61 } else if ((!strncmp(device_str, "audio-jack", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_OUT)) {
62 device = AUDIO_DEVICE_OUT_JACK;
63 } else if ((!strncmp(device_str, "bt-sco", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_OUT)) {
64 device = AUDIO_DEVICE_OUT_BT_SCO;
65 } else if (!strncmp(device_str, "aux", MAX_NAME_LEN)) {
66 device = AUDIO_DEVICE_OUT_AUX;
67 } else if (!strncmp(device_str, "hdmi", MAX_NAME_LEN)) {
68 device = AUDIO_DEVICE_OUT_HDMI;
69 } else if ((!strncmp(device_str, "builtin-mic", MAX_NAME_LEN))) {
70 device = AUDIO_DEVICE_IN_MAIN_MIC;
71 } else if ((!strncmp(device_str, "audio-jack", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_IN)) {
72 device = AUDIO_DEVICE_IN_JACK;
73 } else if ((!strncmp(device_str, "bt-sco", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_IN)) {
74 device = AUDIO_DEVICE_IN_BT_SCO;
76 device = AUDIO_DEVICE_NONE;
78 AUDIO_LOG_INFO("device type(%s), enum(0x%x)", device_str, device);
82 static audio_return_e __set_devices(audio_hal_s *ah, const char *verb, device_info_s *devices, uint32_t num_of_devices)
84 audio_return_e audio_ret = AUDIO_RET_OK;
85 uint32_t new_device = 0;
86 const char *active_devices[MAX_DEVICES] = {NULL,};
87 int i = 0, j = 0, dev_idx = 0;
89 AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
90 AUDIO_RETURN_VAL_IF_FAIL(devices, AUDIO_ERR_PARAMETER);
91 AUDIO_RETURN_VAL_IF_FAIL(num_of_devices, AUDIO_ERR_PARAMETER);
93 if (num_of_devices > MAX_DEVICES) {
94 num_of_devices = MAX_DEVICES;
95 AUDIO_LOG_ERROR("error: num_of_devices");
96 return AUDIO_ERR_PARAMETER;
99 if (devices[0].direction == AUDIO_DIRECTION_OUT) {
100 ah->device.active_out &= 0x0;
101 if (ah->device.active_in) {
102 /* check the active in devices */
103 for (j = 0; j < inDeviceTypes[j].type; j++) {
104 if (((ah->device.active_in & (~AUDIO_DEVICE_IN)) & inDeviceTypes[j].type))
105 active_devices[dev_idx++] = inDeviceTypes[j].name;
108 } else if (devices[0].direction == AUDIO_DIRECTION_IN) {
109 ah->device.active_in &= 0x0;
110 if (ah->device.active_out) {
111 /* check the active out devices */
112 for (j = 0; j < outDeviceTypes[j].type; j++) {
113 if (ah->device.active_out & outDeviceTypes[j].type)
114 active_devices[dev_idx++] = outDeviceTypes[j].name;
119 for (i = 0; i < num_of_devices; i++) {
120 new_device = __convert_device_string_to_enum(devices[i].type, devices[i].direction);
121 if (new_device & AUDIO_DEVICE_IN) {
122 for (j = 0; j < inDeviceTypes[j].type; j++) {
123 if (new_device == inDeviceTypes[j].type) {
124 active_devices[dev_idx++] = inDeviceTypes[j].name;
125 ah->device.active_in |= new_device;
129 for (j = 0; j < outDeviceTypes[j].type; j++) {
130 if (new_device == outDeviceTypes[j].type) {
131 active_devices[dev_idx++] = outDeviceTypes[j].name;
132 ah->device.active_out |= new_device;
138 if (active_devices[0] == NULL) {
139 AUDIO_LOG_ERROR("Failed to set device: active device is NULL");
140 return AUDIO_ERR_PARAMETER;
143 /* Routing path is set only via __audio_routing_playback_rpi3() function, do nothing here. */
148 static audio_return_e __update_route_ap_playback_capture(audio_hal_s *ah, audio_route_info_s *route_info)
150 audio_return_e audio_ret = AUDIO_RET_OK;
151 device_info_s *devices = NULL;
152 const char *verb = mode_to_verb_str[VERB_NORMAL];
154 AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
155 AUDIO_RETURN_VAL_IF_FAIL(route_info, AUDIO_ERR_PARAMETER);
157 devices = route_info->device_infos;
159 /* To Do: Set modifiers */
160 /* int mod_idx = 0; */
161 /* const char *modifiers[MAX_MODIFIERS] = {NULL,}; */
163 AUDIO_LOG_INFO("update_route_ap_playback_capture++ ");
165 audio_ret = __set_devices(ah, verb, devices, route_info->num_of_devices);
167 AUDIO_LOG_ERROR("Failed to set devices: error = 0x%x", audio_ret);
170 ah->device.mode = VERB_NORMAL;
172 /* Routing path is set only via __audio_routing_playback_rpi3() function, do nothing here. */
177 static audio_return_e __update_route_voip(audio_hal_s *ah, device_info_s *devices, int32_t num_of_devices)
179 audio_return_e audio_ret = AUDIO_RET_OK;
180 const char *verb = mode_to_verb_str[VERB_NORMAL];
182 AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
183 AUDIO_RETURN_VAL_IF_FAIL(devices, AUDIO_ERR_PARAMETER);
185 AUDIO_LOG_INFO("update_route_voip++");
187 audio_ret = __set_devices(ah, verb, devices, num_of_devices);
189 AUDIO_LOG_ERROR("Failed to set devices: error = 0x%x", audio_ret);
192 /* FIXME. If necessary, set VERB_VOIP */
193 ah->device.mode = VERB_NORMAL;
195 /* TO DO: Set modifiers */
199 static audio_return_e __update_route_reset(audio_hal_s *ah, uint32_t direction)
201 audio_return_e audio_ret = AUDIO_RET_OK;
202 const char *active_devices[MAX_DEVICES] = {NULL,};
203 int i = 0, dev_idx = 0;
205 /* FIXME: If you need to reset, set verb inactive */
206 /* const char *verb = NULL; */
207 /* verb = AUDIO_USE_CASE_VERB_INACTIVE; */
209 AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
211 AUDIO_LOG_INFO("update_route_reset++, direction(0x%x)", direction);
213 if (direction == AUDIO_DIRECTION_OUT) {
214 ah->device.active_out &= 0x0;
215 if (ah->device.active_in) {
216 /* check the active in devices */
217 for (i = 0; i < inDeviceTypes[i].type; i++) {
218 if (((ah->device.active_in & (~AUDIO_DEVICE_IN)) & inDeviceTypes[i].type)) {
219 active_devices[dev_idx++] = inDeviceTypes[i].name;
220 AUDIO_LOG_INFO("added for in : %s", inDeviceTypes[i].name);
225 ah->device.active_in &= 0x0;
226 if (ah->device.active_out) {
227 /* check the active out devices */
228 for (i = 0; i < outDeviceTypes[i].type; i++) {
229 if (ah->device.active_out & outDeviceTypes[i].type) {
230 active_devices[dev_idx++] = outDeviceTypes[i].name;
231 AUDIO_LOG_INFO("added for out : %s", outDeviceTypes[i].name);
237 if (active_devices[0] == NULL) {
238 AUDIO_LOG_DEBUG("active device is NULL, no need to update.");
242 /* Routing path is set only via __audio_routing_playback_rpi3() function, do nothing here. */
247 static void __audio_routing_playback_rpi3(audio_hal_s *ah)
252 ret = vconf_get_int(VCONFKEY_SOUND_RPI_PLAYBACK_ROUTE, &type);
254 AUDIO_LOG_ERROR("Failed to get vconf [%s], err [%d]", VCONFKEY_SOUND_RPI_PLAYBACK_ROUTE, ret);
258 _mixer_control_set_value(ah, "PCM Playback Route", type);
261 audio_return_e _audio_routing_init(audio_hal_s *ah)
263 audio_return_e audio_ret = AUDIO_RET_OK;
265 AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
267 ah->device.active_in = 0x0;
268 ah->device.active_out = 0x0;
269 ah->device.mode = VERB_NORMAL;
271 /* additional setting for rpi3 playback route mixer control */
272 __audio_routing_playback_rpi3(ah);
277 audio_return_e _audio_routing_deinit(audio_hal_s *ah)
279 audio_return_e audio_ret = AUDIO_RET_OK;
281 AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
286 audio_return_e audio_update_route(void *audio_handle, audio_route_info_s *info)
288 audio_return_e audio_ret = AUDIO_RET_OK;
289 audio_hal_s *ah = (audio_hal_s *)audio_handle;
290 device_info_s *devices = NULL;
292 AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
293 AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER);
294 AUDIO_RETURN_VAL_IF_FAIL(info->role, AUDIO_ERR_PARAMETER);
296 AUDIO_LOG_INFO("role:%s", info->role);
298 devices = info->device_infos;
300 if (!strncmp("voip", info->role, MAX_NAME_LEN)) {
301 if ((audio_ret = __update_route_voip(ah, devices, info->num_of_devices)))
302 AUDIO_LOG_WARN("update voip route return 0x%x", audio_ret);
304 } else if (!strncmp("reset", info->role, MAX_NAME_LEN)) {
305 if ((audio_ret = __update_route_reset(ah, devices->direction)))
306 AUDIO_LOG_WARN("update reset return 0x%x", audio_ret);
309 /* need to prepare for "alarm","notification","emergency","voice-information","voice-recognition","ringtone" */
310 if ((audio_ret = __update_route_ap_playback_capture(ah, info)))
311 AUDIO_LOG_WARN("update playback route return 0x%x", audio_ret);
316 audio_return_e audio_update_route_option(void *audio_handle, audio_route_option_s *option)
318 audio_return_e audio_ret = AUDIO_RET_OK;
319 audio_hal_s *ah = (audio_hal_s *)audio_handle;
322 AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
323 AUDIO_RETURN_VAL_IF_FAIL(option, AUDIO_ERR_PARAMETER);
325 AUDIO_LOG_INFO("role:%s, name:%s, value:%d", option->role, option->name, option->value);
327 if (!strcmp("rpi playback route", option->name)) {
328 audio_ret = _mixer_control_set_value(ah, "PCM Playback Route", option->value);
329 if (audio_ret == AUDIO_RET_OK) {
330 ret = vconf_set_int(VCONFKEY_SOUND_RPI_PLAYBACK_ROUTE, option->value);
332 AUDIO_LOG_ERROR("Failed to set vconf [%s], err [%d]", VCONFKEY_SOUND_RPI_PLAYBACK_ROUTE, ret);
333 return AUDIO_ERR_INTERNAL;