Fix svace defects
[platform/core/multimedia/libmm-sound.git] / mm_sound_device.c
1 /*
2  * libmm-sound
3  *
4  * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Sangchul Lee <sc11.lee@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include <stdlib.h>
23 #include <unistd.h>
24
25 #include <mm_debug.h>
26
27 #include "include/mm_sound.h"
28 #include "include/mm_sound_device.h"
29 #include "include/mm_sound_client.h"
30
31 #define VOLUME_TYPE_LEN 64
32
33 mm_sound_device_list_t *g_device_list;
34
35 static int _check_for_valid_mask (int flags)
36 {
37         int ret = MM_ERROR_NONE;
38         bool at_least_cond = false;
39
40         if (flags > 0 && flags <= MM_SOUND_DEVICE_ALL_FLAG) {
41                 if (flags & MM_SOUND_DEVICE_IO_DIRECTION_IN_FLAG)
42                         at_least_cond = true;
43                 if (!at_least_cond && (flags & MM_SOUND_DEVICE_IO_DIRECTION_OUT_FLAG))
44                         at_least_cond = true;
45                 if (!at_least_cond && (flags & MM_SOUND_DEVICE_IO_DIRECTION_BOTH_FLAG))
46                         at_least_cond = true;
47                 if (!at_least_cond && (flags & MM_SOUND_DEVICE_TYPE_INTERNAL_FLAG))
48                         at_least_cond = true;
49                 if (!at_least_cond && (flags & MM_SOUND_DEVICE_TYPE_EXTERNAL_FLAG))
50                         at_least_cond = true;
51                 if (!at_least_cond && (flags & MM_SOUND_DEVICE_STATE_DEACTIVATED_FLAG))
52                         at_least_cond = true;
53                 if (!at_least_cond && (flags & MM_SOUND_DEVICE_STATE_ACTIVATED_FLAG))
54                         at_least_cond = true;
55         } else {
56                 ret = MM_ERROR_INVALID_ARGUMENT;
57         }
58         if (!at_least_cond) {
59                 ret = MM_ERROR_INVALID_ARGUMENT;
60         }
61         if (ret) {
62                 debug_error("flags[0x%x] is not valid\n", flags);
63         }
64         return ret;
65 }
66
67 static int __convert_device_type_to_enum (char *device_type, mm_sound_device_type_e *device_type_enum)
68 {
69         int ret = MM_ERROR_NONE;
70
71         if (!device_type || !device_type_enum) {
72                 return MM_ERROR_INVALID_ARGUMENT;
73         }
74
75         if (!strncmp(device_type, "builtin-speaker", VOLUME_TYPE_LEN)) {
76                 *device_type_enum = MM_SOUND_DEVICE_TYPE_BUILTIN_SPEAKER;
77         } else if (!strncmp(device_type, "builtin-receiver", VOLUME_TYPE_LEN)) {
78                 *device_type_enum = MM_SOUND_DEVICE_TYPE_BUILTIN_RECEIVER;
79         } else if (!strncmp(device_type, "builtin-mic", VOLUME_TYPE_LEN)) {
80                 *device_type_enum = MM_SOUND_DEVICE_TYPE_BUILTIN_MIC;
81         } else if (!strncmp(device_type, "audio-jack", VOLUME_TYPE_LEN)) {
82                 *device_type_enum = MM_SOUND_DEVICE_TYPE_AUDIOJACK;
83         } else if (!strncmp(device_type, "bt", VOLUME_TYPE_LEN)) {
84                 *device_type_enum = MM_SOUND_DEVICE_TYPE_BLUETOOTH;
85         } else if (!strncmp(device_type, "hdmi", VOLUME_TYPE_LEN)) {
86                 *device_type_enum = MM_SOUND_DEVICE_TYPE_HDMI;
87         } else if (!strncmp(device_type, "forwarding", VOLUME_TYPE_LEN)) {
88                 *device_type_enum = MM_SOUND_DEVICE_TYPE_MIRRORING;
89         } else if (!strncmp(device_type, "usb-audio", VOLUME_TYPE_LEN)) {
90                 *device_type_enum = MM_SOUND_DEVICE_TYPE_USB_AUDIO;
91         } else {
92                 ret = MM_ERROR_INVALID_ARGUMENT;
93                 debug_error("not supported device_type(%s), err(0x%08x)", device_type, ret);
94         }
95
96         return ret;
97 }
98
99 static int __free_device_list(mm_sound_device_list_t *device_list_t)
100 {
101         if (!device_list_t)
102                 return MM_ERROR_INVALID_ARGUMENT;
103
104         debug_log("free device list %p", device_list_t);
105         g_list_free_full(device_list_t->list, g_free);
106         g_free(device_list_t);
107
108         return MM_ERROR_NONE;
109 }
110
111 EXPORT_API
112 int mm_sound_add_device_connected_callback(mm_sound_device_flags_e flags, mm_sound_device_connected_cb func, void *user_data, unsigned int *subs_id)
113 {
114         int ret = MM_ERROR_NONE;
115
116         if (func == NULL || subs_id == NULL) {
117                 debug_error("argument is not valid\n");
118                 return MM_ERROR_INVALID_ARGUMENT;
119         }
120         ret = _check_for_valid_mask(flags);
121         if (ret == MM_ERROR_NONE) {
122                 ret = mm_sound_client_add_device_connected_callback(flags, func, user_data, subs_id);
123                 if (ret < 0) {
124                         debug_error("Could not add device connected callback, ret = %x\n", ret);
125                 }
126         }
127
128         return ret;
129 }
130
131 EXPORT_API
132 int mm_sound_remove_device_connected_callback(unsigned int subs_id)
133 {
134         int ret = MM_ERROR_NONE;
135
136         ret = mm_sound_client_remove_device_connected_callback(subs_id);
137         if (ret < 0) {
138                 debug_error("Could not remove device connected callback, ret = %x\n", ret);
139         }
140
141         return ret;
142 }
143
144 EXPORT_API
145 int mm_sound_add_device_information_changed_callback(mm_sound_device_flags_e flags, mm_sound_device_info_changed_cb func, void *user_data, unsigned int *subs_id)
146 {
147         int ret = MM_ERROR_NONE;
148
149         if (func == NULL || subs_id == NULL) {
150                 debug_error("argument is not valid\n");
151                 return MM_ERROR_INVALID_ARGUMENT;
152         }
153         ret = _check_for_valid_mask(flags);
154         if (ret == MM_ERROR_NONE) {
155                 ret = mm_sound_client_add_device_info_changed_callback(flags, func, user_data, subs_id);
156                 if (ret < 0) {
157                         debug_error("Could not add device information changed callback, ret = %x\n", ret);
158                 }
159         }
160
161         return ret;
162 }
163
164 EXPORT_API
165 int mm_sound_remove_device_information_changed_callback(unsigned int subs_id)
166 {
167         int ret = MM_ERROR_NONE;
168
169         ret = mm_sound_client_remove_device_info_changed_callback(subs_id);
170         if (ret < 0) {
171                 debug_error("Could not remove device information changed callback, ret = %x\n", ret);
172         }
173
174         return ret;
175 }
176
177 EXPORT_API
178 int mm_sound_get_current_device_list(mm_sound_device_flags_e flags, MMSoundDeviceList_t *device_list)
179 {
180         int ret = MM_ERROR_NONE;
181
182         if (!device_list) {
183                 return MM_ERROR_INVALID_ARGUMENT;
184         }
185         ret = _check_for_valid_mask(flags);
186         if (ret != MM_ERROR_NONE) {
187                 debug_error("mask[0x%x] is invalid, ret=0x%x", flags, ret);
188                 return ret;
189         }
190
191         /* free previously allocated list */
192         if (g_device_list != NULL)
193                 __free_device_list(g_device_list);
194
195         if (!(g_device_list = g_malloc0(sizeof(mm_sound_device_list_t)))) {
196                 debug_error("[Client] Allocate device list failed");
197                 return MM_ERROR_SOUND_INTERNAL;
198         }
199
200         g_device_list->is_new_device_list = true;
201
202         ret = mm_sound_client_get_current_connected_device_list(flags, g_device_list);
203         if (ret < 0) {
204                 debug_error("Could not get current connected device list, ret = %x\n", ret);
205                 g_free(g_device_list);
206                 g_device_list = NULL;
207         } else {
208                 *device_list = g_device_list;
209         }
210
211         return ret;
212 }
213
214 EXPORT_API
215 int mm_sound_get_device_list(int flags, MMSoundDeviceList_t *device_list)
216 {
217         int ret = MM_ERROR_NONE;
218         mm_sound_device_list_t *_device_list;
219
220         if (!device_list) {
221                 return MM_ERROR_INVALID_ARGUMENT;
222         }
223         ret = _check_for_valid_mask(flags);
224         if (ret != MM_ERROR_NONE) {
225                 debug_error("mask[0x%x] is invalid, ret=0x%x", flags, ret);
226                 return ret;
227         }
228
229         if (!(_device_list = g_malloc0(sizeof(mm_sound_device_list_t)))) {
230                 debug_error("[Client] Allocate device list failed");
231                 return MM_ERROR_SOUND_INTERNAL;
232         }
233
234         _device_list->is_new_device_list = true;
235
236         ret = mm_sound_client_get_current_connected_device_list(flags, _device_list);
237         if (ret < 0) {
238                 debug_error("Could not get current connected device list, ret = %x\n", ret);
239                 g_free(_device_list);
240         } else {
241                 *device_list = _device_list;
242         }
243
244         return ret;
245 }
246
247 EXPORT_API
248 int mm_sound_free_device_list(MMSoundDeviceList_t device_list)
249 {
250         return __free_device_list((mm_sound_device_list_t*) device_list);
251 }
252
253 EXPORT_API
254 int mm_sound_get_next_device (MMSoundDeviceList_t device_list, MMSoundDevice_t *device)
255 {
256         int ret = MM_ERROR_NONE;
257         mm_sound_device_list_t *device_list_t = NULL;
258         GList *node = NULL;
259         if (!device_list || !device) {
260                 return MM_ERROR_INVALID_ARGUMENT;
261         }
262         device_list_t = (mm_sound_device_list_t*) device_list;
263         if (device_list_t->is_new_device_list) {
264                 node = g_list_first(device_list_t->list);
265         } else {
266                 node = g_list_next(device_list_t->list);
267         }
268         if (!node) {
269                 ret = MM_ERROR_SOUND_NO_DATA;
270         } else {
271                 if (device_list_t->is_new_device_list) {
272                         device_list_t->is_new_device_list = false;
273                 } else {
274                         device_list_t->list = node;
275                 }
276                 *device = (mm_sound_device_t*)node->data;
277                 debug_log("next device[0x%x]\n", *device);
278         }
279         return ret;
280 }
281
282 EXPORT_API
283 int mm_sound_get_prev_device (MMSoundDeviceList_t device_list, MMSoundDevice_t *device)
284 {
285         int ret = MM_ERROR_NONE;
286         mm_sound_device_list_t *device_list_t = NULL;
287         GList *node = NULL;
288         if (!device_list || !device) {
289                 return MM_ERROR_INVALID_ARGUMENT;
290         }
291         device_list_t = (mm_sound_device_list_t*) device_list;
292         node = g_list_previous(device_list_t->list);
293         if (!node) {
294                 ret = MM_ERROR_SOUND_NO_DATA;
295                 debug_error("Could not get previous device, ret = %x\n", ret);
296         } else {
297                 device_list_t->list = node;
298                 *device = (mm_sound_device_t*)node->data;
299                 debug_log("previous device[0x%x]\n", *device);
300         }
301         return ret;
302 }
303
304 EXPORT_API
305 int mm_sound_get_device_type(MMSoundDevice_t device_h, mm_sound_device_type_e *type)
306 {
307         mm_sound_device_t *device = (mm_sound_device_t*)device_h;
308         if(!device || !type) {
309                 debug_error("invalid argument\n");
310                 return MM_ERROR_INVALID_ARGUMENT;
311         }
312         __convert_device_type_to_enum(device->type, type);
313         debug_log("device_handle:0x%x, type:%d\n", device, *type);
314
315         return MM_ERROR_NONE;
316 }
317
318 EXPORT_API
319 int mm_sound_get_device_io_direction(MMSoundDevice_t device_h, mm_sound_device_io_direction_e *io_direction)
320 {
321         mm_sound_device_t *device = (mm_sound_device_t*)device_h;
322         if(!device) {
323                 debug_error("invalid handle\n");
324                 return MM_ERROR_INVALID_ARGUMENT;
325         }
326         *io_direction = device->io_direction;
327         debug_log("device_handle:0x%x, io_direction:%d (1:IN,2:OUT,3:INOUT)\n", device, *io_direction);
328
329         return MM_ERROR_NONE;
330 }
331
332 EXPORT_API
333 int mm_sound_get_device_id(MMSoundDevice_t device_h, int *id)
334 {
335         mm_sound_device_t *device = (mm_sound_device_t*)device_h;
336         if(!device) {
337                 debug_error("invalid handle\n");
338                 return MM_ERROR_INVALID_ARGUMENT;
339         }
340         *id = device->id;
341         debug_log("device_handle:0x%x, id:%d\n", device, *id);
342
343         return MM_ERROR_NONE;
344 }
345
346 EXPORT_API
347 int mm_sound_get_device_state(MMSoundDevice_t device_h, mm_sound_device_state_e *state)
348 {
349         mm_sound_device_t *device = (mm_sound_device_t*)device_h;
350         if(!device) {
351                 debug_error("invalid handle\n");
352                 return MM_ERROR_INVALID_ARGUMENT;
353         }
354         *state = device->state;
355         debug_log("device_handle:0x%x, state:%d (0:INACTIVATED,1:ACTIVATED)\n", device, *state);
356
357         return MM_ERROR_NONE;
358 }
359
360 EXPORT_API
361 int mm_sound_get_device_name(MMSoundDevice_t device_h, char **name)
362 {
363         mm_sound_device_t *device = (mm_sound_device_t*)device_h;
364         if(!device) {
365                 debug_error("invalid handle\n");
366                 return MM_ERROR_INVALID_ARGUMENT;
367         }
368         *name = device->name;
369         debug_log("device_handle:0x%x, name:%s\n", device, *name);
370
371         return MM_ERROR_NONE;
372 }
373
374 EXPORT_API
375 int mm_sound_get_device_bt_avail_mode(MMSoundDevice_t device_h, int *avail_mode)
376 {
377         mm_sound_device_type_e type;
378         mm_sound_device_t *device = (mm_sound_device_t*)device_h;
379
380         if (!device || !avail_mode) {
381                 debug_error("invalid argument\n");
382                 return MM_ERROR_INVALID_ARGUMENT;
383         }
384
385         __convert_device_type_to_enum(device->type, &type);
386         if (type != MM_SOUND_DEVICE_TYPE_BLUETOOTH) {
387                 debug_error("invalid device type(%s)\n", device->type);
388                 return MM_ERROR_INVALID_ARGUMENT;
389         }
390
391         *avail_mode = device->avail_mode;
392         debug_log("device_handle:0x%p, avail mode:%d\n", device, *avail_mode);
393
394         return MM_ERROR_NONE;
395 }
396