Add missing implementations
[platform/adaptation/emulator/audio-hal-emul.git] / tizen-audio-routing.c
1 /*
2  * audio-hal
3  *
4  * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
5  *
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
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "tizen-audio-internal.h"
29 #include "tizen-audio-impl.h"
30
31 /* #define DEBUG_TIMING */
32
33 static device_type_s outDeviceTypes[] = {
34     { AUDIO_DEVICE_OUT_SPEAKER, "Speaker" },
35     { AUDIO_DEVICE_OUT_JACK, "Headphones" },
36     { AUDIO_DEVICE_OUT_BT_SCO, "Bluetooth" },
37     { AUDIO_DEVICE_OUT_AUX, "Line" },
38     { AUDIO_DEVICE_OUT_HDMI, "HDMI" },
39     { 0, 0 },
40 };
41
42 static device_type_s inDeviceTypes[] = {
43     { AUDIO_DEVICE_IN_MAIN_MIC, "MainMic" },
44     { AUDIO_DEVICE_IN_JACK, "HeadsetMic" },
45     { AUDIO_DEVICE_IN_BT_SCO, "BT Mic" },
46     { 0, 0 },
47 };
48
49 static uint32_t __convert_device_string_to_enum(const char* device_str, uint32_t direction)
50 {
51     uint32_t device = 0;
52
53     if (!strncmp(device_str, "builtin-speaker", MAX_NAME_LEN)) {
54         device = AUDIO_DEVICE_OUT_SPEAKER;
55     } else if (!strncmp(device_str, "builtin-receiver", MAX_NAME_LEN)) {
56         device = AUDIO_DEVICE_OUT_RECEIVER;
57     } else if ((!strncmp(device_str, "audio-jack", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_OUT)) {
58         device = AUDIO_DEVICE_OUT_JACK;
59     } else if ((!strncmp(device_str, "bt-sco", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_OUT)) {
60         device = AUDIO_DEVICE_OUT_BT_SCO;
61     } else if (!strncmp(device_str, "aux", MAX_NAME_LEN)) {
62         device = AUDIO_DEVICE_OUT_AUX;
63     } else if (!strncmp(device_str, "hdmi", MAX_NAME_LEN)) {
64         device = AUDIO_DEVICE_OUT_HDMI;
65     } else if ((!strncmp(device_str, "builtin-mic", MAX_NAME_LEN))) {
66         device = AUDIO_DEVICE_IN_MAIN_MIC;
67     } else if ((!strncmp(device_str, "audio-jack", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_IN)) {
68         device = AUDIO_DEVICE_IN_JACK;
69     } else if ((!strncmp(device_str, "bt-sco", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_IN)) {
70         device = AUDIO_DEVICE_IN_BT_SCO;
71     } else {
72         device = AUDIO_DEVICE_NONE;
73     }
74     AUDIO_LOG_INFO("device type(%s), enum(0x%x)", device_str, device);
75     return device;
76 }
77
78 static audio_return_e __set_devices(audio_hal_s *ah, device_info_s *devices, uint32_t num_of_devices)
79 {
80     audio_return_e audio_ret = AUDIO_RET_OK;
81     uint32_t new_device = 0;
82     const char *active_devices[MAX_DEVICES] = {NULL,};
83     int i = 0, j = 0, dev_idx = 0;
84
85     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
86     AUDIO_RETURN_VAL_IF_FAIL(devices, AUDIO_ERR_PARAMETER);
87     AUDIO_RETURN_VAL_IF_FAIL(num_of_devices, AUDIO_ERR_PARAMETER);
88
89     if (num_of_devices > MAX_DEVICES) {
90         num_of_devices = MAX_DEVICES;
91         AUDIO_LOG_ERROR("error: num_of_devices");
92         return AUDIO_ERR_PARAMETER;
93     }
94
95     if (devices[0].direction == AUDIO_DIRECTION_OUT) {
96         ah->device.active_out &= 0x0;
97         if (ah->device.active_in) {
98             /* check the active in devices */
99             for (j = 0; j < inDeviceTypes[j].type; j++) {
100                 if (((ah->device.active_in & (~AUDIO_DEVICE_IN)) & inDeviceTypes[j].type))
101                     active_devices[dev_idx++] = inDeviceTypes[j].name;
102             }
103         }
104     } else if (devices[0].direction == AUDIO_DIRECTION_IN) {
105         ah->device.active_in &= 0x0;
106         if (ah->device.active_out) {
107             /* check the active out devices */
108             for (j = 0; j < outDeviceTypes[j].type; j++) {
109                 if (ah->device.active_out & outDeviceTypes[j].type)
110                     active_devices[dev_idx++] = outDeviceTypes[j].name;
111             }
112         }
113     }
114
115     for (i = 0; i < num_of_devices; i++) {
116         new_device = __convert_device_string_to_enum(devices[i].type, devices[i].direction);
117         if (new_device & AUDIO_DEVICE_IN) {
118             for (j = 0; j < inDeviceTypes[j].type; j++) {
119                 if (new_device == inDeviceTypes[j].type) {
120                     active_devices[dev_idx++] = inDeviceTypes[j].name;
121                     ah->device.active_in |= new_device;
122                 }
123             }
124         } else {
125             for (j = 0; j < outDeviceTypes[j].type; j++) {
126                 if (new_device == outDeviceTypes[j].type) {
127                     active_devices[dev_idx++] = outDeviceTypes[j].name;
128                     ah->device.active_out |= new_device;
129                 }
130             }
131         }
132     }
133
134     if (active_devices[0] == NULL) {
135         AUDIO_LOG_ERROR("Failed to set device: active device is NULL");
136         return AUDIO_ERR_PARAMETER;
137     }
138
139     return audio_ret;
140 }
141
142 static audio_return_e __update_route_ap_playback_capture(audio_hal_s *ah, audio_route_info_s *route_info)
143 {
144     audio_return_e audio_ret = AUDIO_RET_OK;
145     device_info_s *devices = NULL;
146
147     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
148     AUDIO_RETURN_VAL_IF_FAIL(route_info, AUDIO_ERR_PARAMETER);
149
150     devices = route_info->device_infos;
151
152     AUDIO_LOG_INFO("update_route_ap_playback_capture++ ");
153
154     audio_ret = __set_devices(ah, devices, route_info->num_of_devices);
155     if (audio_ret) {
156         AUDIO_LOG_ERROR("Failed to set devices: error = 0x%x", audio_ret);
157         return audio_ret;
158     }
159
160     return audio_ret;
161 }
162
163 static audio_return_e __update_route_voip(audio_hal_s *ah, device_info_s *devices, int32_t num_of_devices)
164 {
165     audio_return_e audio_ret = AUDIO_RET_OK;
166
167     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
168     AUDIO_RETURN_VAL_IF_FAIL(devices, AUDIO_ERR_PARAMETER);
169
170     AUDIO_LOG_INFO("update_route_voip++");
171
172     audio_ret = __set_devices(ah, devices, num_of_devices);
173     if (audio_ret) {
174         AUDIO_LOG_ERROR("Failed to set devices: error = 0x%x", audio_ret);
175         return audio_ret;
176     }
177
178     return audio_ret;
179 }
180
181 static audio_return_e __update_route_reset(audio_hal_s *ah, uint32_t direction)
182 {
183     audio_return_e audio_ret = AUDIO_RET_OK;
184     const char *active_devices[MAX_DEVICES] = {NULL,};
185     int i = 0, dev_idx = 0;
186
187     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
188
189     AUDIO_LOG_INFO("update_route_reset++, direction(0x%x)", direction);
190
191     if (direction == AUDIO_DIRECTION_OUT) {
192         ah->device.active_out &= 0x0;
193         if (ah->device.active_in) {
194             /* check the active in devices */
195             for (i = 0; i < inDeviceTypes[i].type; i++) {
196                 if (((ah->device.active_in & (~AUDIO_DEVICE_IN)) & inDeviceTypes[i].type)) {
197                     active_devices[dev_idx++] = inDeviceTypes[i].name;
198                     AUDIO_LOG_INFO("added for in : %s", inDeviceTypes[i].name);
199                 }
200             }
201         }
202     } else {
203         ah->device.active_in &= 0x0;
204         if (ah->device.active_out) {
205             /* check the active out devices */
206             for (i = 0; i < outDeviceTypes[i].type; i++) {
207                 if (ah->device.active_out & outDeviceTypes[i].type) {
208                     active_devices[dev_idx++] = outDeviceTypes[i].name;
209                     AUDIO_LOG_INFO("added for out : %s", outDeviceTypes[i].name);
210                 }
211             }
212         }
213     }
214
215     if (active_devices[0] == NULL) {
216         AUDIO_LOG_DEBUG("active device is NULL, no need to update.");
217         return AUDIO_RET_OK;
218     }
219
220     return audio_ret;
221 }
222
223 audio_return_e _audio_routing_init(audio_hal_s *ah)
224 {
225     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
226
227     ah->device.active_in = 0x0;
228     ah->device.active_out = 0x0;
229
230     return AUDIO_RET_OK;
231 }
232
233 audio_return_e _audio_routing_deinit(audio_hal_s *ah)
234 {
235     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
236
237     return AUDIO_RET_OK;
238 }
239
240 #define LOOPBACK_ARG_LATENCY_MSEC      30
241 #define LOOPBACK_ARG_ADJUST_TIME_SEC   3
242 audio_return_e audio_update_route(void *audio_handle, audio_route_info_s *info)
243 {
244     audio_return_e audio_ret = AUDIO_RET_OK;
245     audio_hal_s *ah = (audio_hal_s *)audio_handle;
246     device_info_s *devices = NULL;
247
248     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
249     AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER);
250     AUDIO_RETURN_VAL_IF_FAIL(info->role, AUDIO_ERR_PARAMETER);
251
252     AUDIO_LOG_INFO("role:%s", info->role);
253
254     devices = info->device_infos;
255
256     if (!strncmp("voip", info->role, MAX_NAME_LEN)) {
257         if ((audio_ret = __update_route_voip(ah, devices, info->num_of_devices)))
258             AUDIO_LOG_WARN("update voip route return 0x%x", audio_ret);
259
260     } else if (!strncmp("reset", info->role, MAX_NAME_LEN)) {
261         if ((audio_ret = __update_route_reset(ah, devices->direction)))
262             AUDIO_LOG_WARN("update reset return 0x%x", audio_ret);
263
264     } else {
265         /* send latency and adjust time for loopback */
266         if (!strncmp("loopback", info->role, MAX_NAME_LEN)) {
267             _audio_comm_send_message(ah, "loopback::latency", LOOPBACK_ARG_LATENCY_MSEC);
268             _audio_comm_send_message(ah, "loopback::adjust_time", LOOPBACK_ARG_ADJUST_TIME_SEC);
269         }
270         /* need to prepare for "alarm","notification","emergency","voice-information","voice-recognition","ringtone" */
271         if ((audio_ret = __update_route_ap_playback_capture(ah, info)))
272             AUDIO_LOG_WARN("update playback route return 0x%x", audio_ret);
273     }
274     return audio_ret;
275 }
276
277 audio_return_e audio_update_route_option(void *audio_handle, audio_route_option_s *option)
278 {
279     audio_return_e audio_ret = AUDIO_RET_OK;
280     audio_hal_s *ah = (audio_hal_s *)audio_handle;
281
282     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
283     AUDIO_RETURN_VAL_IF_FAIL(option, AUDIO_ERR_PARAMETER);
284
285     AUDIO_LOG_INFO("role:%s, name:%s, value:%d", option->role, option->name, option->value);
286
287     return audio_ret;
288 }