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