keysound: support keysound priority
[platform/core/multimedia/libmm-sound.git] / mm_sound_client.c
1 /*
2  * libmm-sound
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Seungbae Shin <seungbae.shin@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 <stdint.h>
24 #include <unistd.h>
25 #include <errno.h>
26 #include <pthread.h>
27 #include <glib.h>
28 #include <mm_error.h>
29 #include <mm_debug.h>
30 #include <vconf.h>
31
32 #include "include/mm_sound.h"
33 #include "include/mm_sound_client.h"
34 #include "include/mm_sound_proxy.h"
35 #include "include/mm_sound_common.h"
36 #include "include/mm_sound_device.h"
37 #include "include/mm_sound_stream.h"
38 #include "include/mm_sound_focus_private.h"
39
40 #define CLIENT_HANDLE_MAX 256
41 #define VOLUME_TYPE_LEN 64
42
43 #define VCONF_KEY_VOLUME_PREFIX                         "file/private/sound/volume"
44 #define VCONF_KEY_VOLUME_TYPE_SYSTEM            VCONF_KEY_VOLUME_PREFIX"/system"
45 #define VCONF_KEY_VOLUME_TYPE_NOTIFICATION      VCONF_KEY_VOLUME_PREFIX"/notification"
46 #define VCONF_KEY_VOLUME_TYPE_ALARM                     VCONF_KEY_VOLUME_PREFIX"/alarm"
47 #define VCONF_KEY_VOLUME_TYPE_RINGTONE          VCONF_KEY_VOLUME_PREFIX"/ringtone"
48 #define VCONF_KEY_VOLUME_TYPE_MEDIA                     VCONF_KEY_VOLUME_PREFIX"/media"
49 #define VCONF_KEY_VOLUME_TYPE_CALL                      VCONF_KEY_VOLUME_PREFIX"/call"
50 #define VCONF_KEY_VOLUME_TYPE_VOIP                      VCONF_KEY_VOLUME_PREFIX"/voip"
51 #define VCONF_KEY_VOLUME_TYPE_VOICE             VCONF_KEY_VOLUME_PREFIX"/voice"
52 #define VCONF_KEY_VOLUME_TYPE_ANDROID           VCONF_KEY_VOLUME_PREFIX"/fixed"
53
54 #define VCONF_KEY_MUTE_PREFIX                           "file/private/sound/mute"
55 #define VCONF_KEY_MUTE_TYPE_SYSTEM              VCONF_KEY_MUTE_PREFIX"/system"
56 #define VCONF_KEY_MUTE_TYPE_NOTIFICATION        VCONF_KEY_MUTE_PREFIX"/notification"
57 #define VCONF_KEY_MUTE_TYPE_ALARM                       VCONF_KEY_MUTE_PREFIX"/alarm"
58 #define VCONF_KEY_MUTE_TYPE_RINGTONE            VCONF_KEY_MUTE_PREFIX"/ringtone"
59 #define VCONF_KEY_MUTE_TYPE_MEDIA                       VCONF_KEY_MUTE_PREFIX"/media"
60 #define VCONF_KEY_MUTE_TYPE_CALL                        VCONF_KEY_MUTE_PREFIX"/call"
61 #define VCONF_KEY_MUTE_TYPE_VOIP                        VCONF_KEY_MUTE_PREFIX"/voip"
62 #define VCONF_KEY_MUTE_TYPE_VOICE               VCONF_KEY_MUTE_PREFIX"/voice"
63
64 /* For internal use */
65 #define VCONF_KEY_VOLUME_TYPE_BIXBY             VCONF_KEY_VOLUME_PREFIX"/bixby"
66
67 static char *g_volume_vconf[VOLUME_TYPE_MAX] = {
68         VCONF_KEY_VOLUME_TYPE_SYSTEM,           /* VOLUME_TYPE_SYSTEM */
69         VCONF_KEY_VOLUME_TYPE_NOTIFICATION,     /* VOLUME_TYPE_NOTIFICATION */
70         VCONF_KEY_VOLUME_TYPE_ALARM,            /* VOLUME_TYPE_ALARM */
71         VCONF_KEY_VOLUME_TYPE_RINGTONE,         /* VOLUME_TYPE_RINGTONE */
72         VCONF_KEY_VOLUME_TYPE_MEDIA,            /* VOLUME_TYPE_MEDIA */
73         VCONF_KEY_VOLUME_TYPE_CALL,                     /* VOLUME_TYPE_CALL */
74         VCONF_KEY_VOLUME_TYPE_VOIP,                     /* VOLUME_TYPE_VOIP */
75         VCONF_KEY_VOLUME_TYPE_VOICE,            /* VOLUME_TYPE_VOICE */
76         VCONF_KEY_VOLUME_TYPE_ANDROID           /* VOLUME_TYPE_FIXED */
77 };
78
79 static char *g_volume_vconf_internal[] = {
80         VCONF_KEY_VOLUME_TYPE_BIXBY,            /* VOLUME_TYPE_BIXBY */
81 };
82
83 static char *g_mute_vconf[] = {
84         VCONF_KEY_MUTE_TYPE_SYSTEM,             /* MUTE_TYPE_SYSTEM */
85         VCONF_KEY_MUTE_TYPE_NOTIFICATION,       /* MUTE_TYPE_NOTIFICATION */
86         VCONF_KEY_MUTE_TYPE_ALARM,              /* MUTE_TYPE_ALARM */
87         VCONF_KEY_MUTE_TYPE_RINGTONE,           /* MUTE_TYPE_RINGTONE */
88         VCONF_KEY_MUTE_TYPE_MEDIA,              /* MUTE_TYPE_MEDIA */
89         VCONF_KEY_MUTE_TYPE_CALL,                       /* MUTE_TYPE_CALL */
90         VCONF_KEY_MUTE_TYPE_VOIP,                       /* MUTE_TYPE_VOIP */
91         VCONF_KEY_MUTE_TYPE_VOICE,              /* MUTE_TYPE_VOICE */
92 };
93
94 struct callback_data {
95         void *user_cb;
96         void *user_data;
97         void *extra_data;
98         guint subs_id;
99 };
100
101 #define GET_CB_DATA(_cb_data, _func, _userdata, _extradata) \
102         do { \
103                 _cb_data = (struct callback_data*) g_try_malloc0(sizeof(struct callback_data)); \
104                 if (!_cb_data) { \
105                         debug_error("failed to allocate callback_data"); \
106                         return MM_ERROR_OUT_OF_MEMORY; \
107                 } \
108                 _cb_data->user_cb = _func; \
109                 _cb_data->user_data = _userdata; \
110                 _cb_data->extra_data = _extradata; \
111         } while (0)
112
113 static pthread_mutex_t g_index_mutex = PTHREAD_MUTEX_INITIALIZER;
114 static pthread_mutex_t g_event_mutex = PTHREAD_MUTEX_INITIALIZER;
115 static guint g_idle_event_src;
116
117 typedef struct {
118         /* handle to watch end of playing */
119         int watching_handle;
120         /* subscription id to unsubscribe when handle ended */
121         unsigned subs_id;
122 } play_sound_end_callback_data_t;
123
124 typedef struct _focus_idle_event {
125         focus_idle_event_type_e type;
126         int data;
127 } focus_idle_event_t;
128
129 int mm_sound_client_initialize(void)
130 {
131         int ret = MM_ERROR_NONE;
132
133         debug_fenter();
134
135         mm_sound_proxy_initialize();
136         g_idle_event_src = 0;
137
138         debug_fleave();
139         return ret;
140 }
141
142 int mm_sound_client_finalize(void)
143 {
144         int ret = MM_ERROR_NONE;
145
146         debug_fenter();
147
148         ret = mm_sound_proxy_finalize();
149
150         if (g_idle_event_src > 0) {
151                 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_event_mutex, MM_ERROR_SOUND_INTERNAL);
152                 g_source_remove(g_idle_event_src);
153                 MMSOUND_LEAVE_CRITICAL_SECTION(&g_event_mutex);
154         }
155
156         debug_fleave();
157         return ret;
158 }
159
160 void mm_sound_convert_volume_type_to_stream_type(int volume_type, char *stream_type)
161 {
162         switch (volume_type) {
163         case VOLUME_TYPE_SYSTEM:
164                 MMSOUND_STRNCPY(stream_type, "system", MAX_STREAM_TYPE_LEN);
165                 break;
166         case VOLUME_TYPE_NOTIFICATION:
167                 MMSOUND_STRNCPY(stream_type, "notification", MAX_STREAM_TYPE_LEN);
168                 break;
169         case VOLUME_TYPE_ALARM:
170                 MMSOUND_STRNCPY(stream_type, "alarm", MAX_STREAM_TYPE_LEN);
171                 break;
172         case VOLUME_TYPE_RINGTONE:
173                 MMSOUND_STRNCPY(stream_type, "ringtone-voip", MAX_STREAM_TYPE_LEN);
174                 break;
175         case VOLUME_TYPE_MEDIA:
176                 MMSOUND_STRNCPY(stream_type, "media", MAX_STREAM_TYPE_LEN);
177                 break;
178         case VOLUME_TYPE_CALL:
179                 MMSOUND_STRNCPY(stream_type, "call-voice", MAX_STREAM_TYPE_LEN);
180                 break;
181         case VOLUME_TYPE_VOIP:
182                 MMSOUND_STRNCPY(stream_type, "voip", MAX_STREAM_TYPE_LEN);
183                 break;
184         case VOLUME_TYPE_VOICE:
185                 MMSOUND_STRNCPY(stream_type, "voice-information", MAX_STREAM_TYPE_LEN);
186                 break;
187         default:
188                 MMSOUND_STRNCPY(stream_type, "media", MAX_STREAM_TYPE_LEN);
189                 break;
190         }
191
192         debug_msg("volume type (%d) converted to stream type (%s)", volume_type, stream_type);
193
194 }
195
196 /*****************************************************************************************
197                             DBUS SUPPORTED FUNCTIONS
198 ******************************************************************************************/
199 static int _mm_sound_client_device_list_dump(GList *device_list)
200 {
201         int ret = MM_ERROR_NONE;
202         GList *list = NULL;
203         mm_sound_device_t *device_node = NULL;
204         int count = 0;
205         if (!device_list) {
206                 debug_error("Device list NULL, cannot dump list");
207                 return MM_ERROR_SOUND_INTERNAL;
208         }
209
210         debug_log("======================== device list : start ==========================");
211         for (list = device_list; list != NULL; list = list->next) {
212                 device_node = (mm_sound_device_t *)list->data;
213                 if (device_node) {
214                         debug_log(" list idx[%d]: type[%17s], id[%02d], io_direction[%d], state[%d], name[%s]",
215                                                 count++, device_node->type, device_node->id, device_node->io_direction,
216                                                 device_node->state, device_node->name);
217                 }
218         }
219         debug_log("======================== device list : end ============================");
220
221         return ret;
222 }
223
224 int mm_sound_client_get_current_connected_device_list(int device_flags, mm_sound_device_list_t *device_list)
225 {
226         int ret = MM_ERROR_NONE;
227         debug_fenter();
228
229         if (!device_list) {
230                 debug_error("Device list NULL");
231                 ret = MM_ERROR_COMMON_INVALID_ARGUMENT;
232                 goto failed;
233         }
234
235         if ((ret = mm_sound_proxy_get_current_connected_device_list(device_flags, &device_list->list)) != MM_ERROR_NONE) {
236                 debug_error("failed to get current connected device list with dbus, ret[0x%x]", ret);
237                 goto failed;
238         }
239         if (!device_list->list) {
240                 debug_error("Got device list null");
241                 ret = MM_ERROR_SOUND_NO_DATA;
242                 goto failed;
243         }
244         _mm_sound_client_device_list_dump(device_list->list);
245
246 failed:
247         debug_fleave();
248         return ret;
249 }
250
251 int mm_sound_client_get_device_by_id(int device_id, mm_sound_device_t **device)
252 {
253         int ret = MM_ERROR_NONE;
254
255         debug_fenter();
256
257         if ((ret = mm_sound_proxy_get_device_by_id(device_id, device)) != MM_ERROR_NONE)
258                 debug_error("failed to get device by id");
259
260         debug_fleave();
261
262         return ret;
263 }
264
265 static bool device_is_match_direction(int direction, int mask)
266 {
267         if (mask == DEVICE_IO_DIRECTION_FLAGS || mask == 0)
268                 return true;
269
270         if ((mask & MM_SOUND_DEVICE_IO_DIRECTION_IN_FLAG) && (direction & MM_SOUND_DEVICE_IO_DIRECTION_IN))
271                 return true;
272         if ((mask & MM_SOUND_DEVICE_IO_DIRECTION_OUT_FLAG) && (direction & MM_SOUND_DEVICE_IO_DIRECTION_OUT))
273                 return true;
274         if ((mask & MM_SOUND_DEVICE_IO_DIRECTION_BOTH_FLAG) && (direction == MM_SOUND_DEVICE_IO_DIRECTION_BOTH))
275                 return true;
276
277         return false;
278 }
279
280 static bool device_is_match_state(int state, int mask)
281 {
282         if (mask == DEVICE_STATE_FLAGS || mask == 0)
283                 return true;
284
285         if ((mask & MM_SOUND_DEVICE_STATE_DEACTIVATED_FLAG) && (state == MM_SOUND_DEVICE_STATE_DEACTIVATED))
286                 return true;
287         if ((mask & MM_SOUND_DEVICE_STATE_ACTIVATED_FLAG) && (state == MM_SOUND_DEVICE_STATE_ACTIVATED))
288                 return true;
289
290         return false;
291 }
292
293 static bool device_is_match_type(const char *type, int mask)
294 {
295         bool is_builtin;
296         const char *builtin_prefix = "builtin";
297
298         if (mask == DEVICE_TYPE_FLAGS || mask == 0)
299                 return true;
300
301         is_builtin = !strncmp(type, builtin_prefix, strlen(builtin_prefix));
302
303         if ((mask & MM_SOUND_DEVICE_TYPE_INTERNAL_FLAG) && (is_builtin))
304                 return true;
305         if ((mask & MM_SOUND_DEVICE_TYPE_EXTERNAL_FLAG) && (!is_builtin))
306                 return true;
307
308         return false;
309 }
310
311 static bool device_is_match_with_mask(const char *type, int direction, int state, int mask)
312 {
313         if (mask == DEVICE_ALL_FLAG)
314                 return true;
315
316         return (device_is_match_direction(direction, mask & DEVICE_IO_DIRECTION_FLAGS) &&
317                         device_is_match_state(state, mask & DEVICE_STATE_FLAGS) &&
318                         device_is_match_type(type, mask & DEVICE_TYPE_FLAGS));
319 }
320
321 static int _fill_sound_device(mm_sound_device_t *device_h, int device_id, const char *device_type,
322                 int direction, int state, const char *name, int vendor_id, int product_id,
323                 int *stream_id, int stream_num, bool is_running)
324 {
325         int i;
326
327         if (stream_num > 0 && stream_id == NULL) {
328                 debug_error("stream_num is %d, but stream_id is NULL", stream_num);
329                 return -1;
330         }
331
332         if (stream_num > MAX_STREAM_ON_DEVICE) {
333                 debug_error("too many streams on this device");
334                 return -1;
335         }
336
337         device_h->id = device_id;
338         device_h->io_direction = direction;
339         device_h->state = state;
340         MMSOUND_STRNCPY(device_h->name, name, MAX_DEVICE_NAME_NUM);
341         MMSOUND_STRNCPY(device_h->type, device_type, MAX_DEVICE_TYPE_STR_LEN);
342         device_h->vendor_id = vendor_id;
343         device_h->product_id = product_id;
344         device_h->is_running = is_running;
345
346         if (stream_num > 0) {
347                 device_h->stream_num = stream_num;
348                 debug_log("%d streams on this device", stream_num);
349                 for (i = 0; i < stream_num; i++) {
350                         debug_log("  stream_id : %d", stream_id[i]);
351                         device_h->stream_id[i] = stream_id[i];
352                 }
353         } else {
354                 device_h->stream_num = 0;
355                 debug_log("There is no stream on this device");
356         }
357
358         return 0;
359 }
360
361 static void _mm_sound_device_connected_callback_wrapper_func(int device_id, const char *device_type, int io_direction,
362                                                                                                                         int state, const char *name, int vendor_id, int product_id, bool is_running,
363                                                                                                                         int *stream_id, int stream_num, bool is_connected, void *userdata)
364 {
365         mm_sound_device_t device_h;
366         struct callback_data *cb_data = (struct callback_data*) userdata;
367         int device_flags;
368
369         debug_log("[Device %s] id(%d) type(%s) direction(%d) state(%d) name(%s) is_running(%d) vendor-id(%04x) product-id(%04x)",
370                                 is_connected ? "Connected" : "Disconnected", device_id, device_type, io_direction, state, name,
371                                 is_running, vendor_id, product_id);
372
373         if (cb_data == NULL) {
374                 debug_warning("device connected changed callback data null");
375                 return;
376         }
377
378         device_flags = (int)(uintptr_t)cb_data->extra_data;
379         if (!device_is_match_with_mask(device_type, io_direction, state, device_flags))
380                 return;
381
382         if (_fill_sound_device(&device_h, device_id, device_type, io_direction, state, name,
383                                                         vendor_id, product_id, stream_id, stream_num, is_running) < 0) {
384                 debug_error("Failed to fill sound device");
385                 return;
386         }
387
388         ((mm_sound_device_connected_cb)(cb_data->user_cb))(&device_h, is_connected, cb_data->user_data);
389 }
390
391 int mm_sound_client_add_device_connected_callback(int device_flags, mm_sound_device_connected_cb func,
392                                                                                                 void* userdata, unsigned int *subs_id)
393 {
394         int ret = MM_ERROR_NONE;
395         struct callback_data *cb_data = NULL;
396
397         debug_fenter();
398
399         GET_CB_DATA(cb_data, func, userdata, (void*)(uintptr_t)device_flags);
400
401         ret = mm_sound_proxy_add_device_connected_callback(_mm_sound_device_connected_callback_wrapper_func,
402                                                                                                         cb_data, g_free, subs_id);
403
404         debug_fleave();
405         return ret;
406 }
407
408 int mm_sound_client_remove_device_connected_callback(unsigned int subs_id)
409 {
410         int ret = MM_ERROR_NONE;
411         debug_fenter();
412
413         ret = mm_sound_proxy_remove_device_connected_callback(subs_id);
414
415         debug_fleave();
416         return ret;
417 }
418
419 static void _mm_sound_device_info_changed_callback_wrapper_func(int device_id, const char *device_type, int io_direction,
420                                                                                                                                 int state, const char *name, int vendor_id, int product_id, bool is_running,
421                                                                                                                                 int *stream_id, int stream_num, int changed_device_info_type, void *userdata)
422 {
423         mm_sound_device_t device_h;
424         struct callback_data *cb_data = (struct callback_data*) userdata;
425         int device_flags;
426
427         debug_log("[Device Info Changed] id(%d) type(%s) direction(%d) state(%d) name(%s) is_running(%d) "
428                         "vendor-id(%04x) product-id(%04x) changed_info_type(%d)",
429                         device_id, device_type, io_direction, state, name, is_running, vendor_id, product_id, changed_device_info_type);
430
431         if (cb_data == NULL) {
432                 debug_warning("device info changed callback data null");
433                 return;
434         }
435
436         device_flags = (int)(uintptr_t)cb_data->extra_data;
437         if (!device_is_match_with_mask(device_type, io_direction, state, device_flags))
438                 return;
439
440         if (_fill_sound_device(&device_h, device_id, device_type, io_direction, state, name,
441                                 vendor_id, product_id, stream_id, stream_num, is_running) < 0) {
442                 debug_error("Failed to fill sound device");
443                 return;
444         }
445
446         ((mm_sound_device_info_changed_cb)(cb_data->user_cb))(&device_h, changed_device_info_type, cb_data->user_data);
447 }
448
449 int mm_sound_client_add_device_info_changed_callback(int device_flags, mm_sound_device_info_changed_cb func,
450                                                                                                         void *userdata, unsigned int *subs_id)
451 {
452         int ret = MM_ERROR_NONE;
453         struct callback_data *cb_data = (struct callback_data*) userdata;
454
455         debug_fenter();
456
457         GET_CB_DATA(cb_data, func, userdata, (void *)(uintptr_t)device_flags);
458
459         ret = mm_sound_proxy_add_device_info_changed_callback(_mm_sound_device_info_changed_callback_wrapper_func,
460                                                                                                                 cb_data, g_free, subs_id);
461
462         debug_fleave();
463         return ret;
464 }
465
466 int mm_sound_client_remove_device_info_changed_callback(unsigned int subs_id)
467 {
468         int ret = MM_ERROR_NONE;
469         debug_fenter();
470
471         ret =  mm_sound_proxy_remove_device_info_changed_callback(subs_id);
472
473         debug_fleave();
474         return ret;
475
476 }
477
478 static void _mm_sound_device_state_changed_callback_wrapper_func(int device_id, const char *device_type, int io_direction,
479                                                                                                                                 int state, const char *name, int vendor_id, int product_id,
480                                                                                                                                 bool is_running, int *stream_id, int stream_num, void *userdata)
481 {
482         mm_sound_device_t device_h;
483         struct callback_data *cb_data = (struct callback_data*) userdata;
484         int device_flags;
485
486         debug_log("[Device State Changed] id(%d) type(%s) direction(%d) state(%d) name(%s) is_running(%d) vendor-id(%04x) product-id(%04x)",
487                                 device_id, device_type, io_direction, state, name, is_running, vendor_id, product_id);
488
489         if (cb_data == NULL) {
490                 debug_warning("device state changed callback data null");
491                 return;
492         }
493
494         device_flags = (int)(uintptr_t)cb_data->extra_data;
495
496         if (!device_is_match_with_mask(device_type, io_direction, state, device_flags))
497                 return;
498
499         if (_fill_sound_device(&device_h, device_id, device_type, io_direction, state, name,
500                                 vendor_id, product_id, stream_id, stream_num, is_running) < 0) {
501                 debug_error("Failed to fill sound device");
502                 return;
503         }
504
505         ((mm_sound_device_state_changed_cb)(cb_data->user_cb))(&device_h, state, cb_data->user_data);
506 }
507
508 int mm_sound_client_add_device_state_changed_callback(int device_flags, mm_sound_device_state_changed_cb func,
509                                                                                                         void *userdata, unsigned int *id)
510 {
511         int ret = MM_ERROR_NONE;
512         struct callback_data *cb_data = (struct callback_data*) userdata;
513
514         debug_fenter();
515
516         GET_CB_DATA(cb_data, func, userdata, (void *)(uintptr_t)device_flags);
517
518         ret = mm_sound_proxy_add_device_state_changed_callback(_mm_sound_device_state_changed_callback_wrapper_func,
519                                                                                                                 cb_data, g_free, id);
520
521         debug_fleave();
522         return ret;
523 }
524
525 int mm_sound_client_remove_device_state_changed_callback(unsigned int id)
526 {
527         int ret = MM_ERROR_NONE;
528         debug_fenter();
529
530         ret =  mm_sound_proxy_remove_device_state_changed_callback(id);
531
532         debug_fleave();
533         return ret;
534 }
535
536 static void _mm_sound_device_running_changed_callback_wrapper_func(int device_id, const char *device_type, int io_direction,
537                                                                                                                                 int state, const char *name, int vendor_id, int product_id,
538                                                                                                                                 bool is_running, int *stream_id, int stream_num, void *userdata)
539 {
540         mm_sound_device_t device_h;
541         struct callback_data *cb_data = (struct callback_data*) userdata;
542         int device_flags;
543
544         debug_log("[Device Running Changed] id(%d) type(%s) direction(%d) state(%d) name(%s) is_running(%d) vendor-id(%04x), product-id(%04x)",
545                         device_id, device_type, io_direction, state, name, is_running, vendor_id, product_id);
546
547         if (cb_data == NULL) {
548                 debug_warning("device running changed callback data null");
549                 return;
550         }
551
552         device_flags = (int)(uintptr_t)cb_data->extra_data;
553
554         if (!device_is_match_with_mask(device_type, io_direction, state, device_flags))
555                 return;
556
557         if (_fill_sound_device(&device_h, device_id, device_type, io_direction, state, name,
558                                                         vendor_id, product_id, stream_id, stream_num, is_running) < 0) {
559                 debug_error("Failed to fill sound device");
560                 return;
561         }
562
563         ((mm_sound_device_running_changed_cb)(cb_data->user_cb))(&device_h, is_running, cb_data->user_data);
564 }
565
566 int mm_sound_client_add_device_running_changed_callback(int device_flags, mm_sound_device_running_changed_cb func,
567                                                                                                                 void *userdata, unsigned int *id)
568 {
569         int ret = MM_ERROR_NONE;
570         struct callback_data *cb_data = (struct callback_data*) userdata;
571
572         debug_fenter();
573
574         GET_CB_DATA(cb_data, func, userdata, (void *)(uintptr_t)device_flags);
575
576         ret = mm_sound_proxy_add_device_running_changed_callback(_mm_sound_device_running_changed_callback_wrapper_func,
577                                                                                                                         cb_data, g_free, id);
578
579         debug_fleave();
580         return ret;
581 }
582
583 int mm_sound_client_remove_device_running_changed_callback(unsigned int id)
584 {
585         int ret = MM_ERROR_NONE;
586         debug_fenter();
587
588         ret =  mm_sound_proxy_remove_device_running_changed_callback(id);
589
590         debug_fleave();
591         return ret;
592 }
593
594 int mm_sound_client_is_stream_on_device(int stream_id, int device_id, bool *is_on)
595 {
596         int ret = MM_ERROR_NONE;
597         debug_fenter();
598
599         if (!is_on) {
600                 debug_error("Invalid Parameter");
601                 ret = MM_ERROR_COMMON_INVALID_ARGUMENT;
602                 goto failed;
603         }
604
605         if ((ret = mm_sound_proxy_is_stream_on_device(stream_id, device_id, is_on)) != MM_ERROR_NONE) {
606                 debug_error("failed to query is stream on device, ret[0x%x]", ret);
607                 goto failed;
608         }
609
610 failed:
611         debug_fleave();
612         return ret;
613 }
614
615 int __convert_volume_type_to_str(volume_type_t volume_type, char **volume_type_str)
616 {
617         int ret = MM_ERROR_NONE;
618
619         if (!volume_type_str)
620                 return MM_ERROR_COMMON_INVALID_ARGUMENT;
621
622         switch (volume_type) {
623         case VOLUME_TYPE_SYSTEM:
624                 *volume_type_str = "system";
625                 break;
626         case VOLUME_TYPE_NOTIFICATION:
627                 *volume_type_str = "notification";
628                 break;
629         case VOLUME_TYPE_ALARM:
630                 *volume_type_str = "alarm";
631                 break;
632         case VOLUME_TYPE_RINGTONE:
633                 *volume_type_str = "ringtone";
634                 break;
635         case VOLUME_TYPE_MEDIA:
636                 *volume_type_str = "media";
637                 break;
638         case VOLUME_TYPE_CALL:
639                 *volume_type_str = "call";
640                 break;
641         case VOLUME_TYPE_VOIP:
642                 *volume_type_str = "voip";
643                 break;
644         case VOLUME_TYPE_VOICE:
645                 *volume_type_str = "voice";
646                 break;
647         default:
648                 debug_error("unexpected volume type [%d]", volume_type);
649                 return MM_ERROR_SOUND_INTERNAL;
650         }
651         debug_log("volume_type[%s]", *volume_type_str);
652         return ret;
653 }
654
655 int __convert_volume_type_internal_to_str(volume_type_internal_t volume_type, char **volume_type_str)
656 {
657         int ret = MM_ERROR_NONE;
658
659         if (!volume_type_str)
660                 return MM_ERROR_COMMON_INVALID_ARGUMENT;
661
662         switch (volume_type) {
663         case VOLUME_TYPE_BIXBY:
664                 *volume_type_str = "bixby";
665                 break;
666         default:
667                 debug_error("unexpected volume type [%d]", volume_type);
668                 return MM_ERROR_SOUND_INTERNAL;
669         }
670         debug_log("volume_type[%s]", *volume_type_str);
671         return ret;
672 }
673
674 static int __convert_volume_type_to_int(const char *volume_type_str, int *volume_type, bool *is_for_internal)
675 {
676         int ret = MM_ERROR_NONE;
677
678         if (!volume_type || !volume_type_str || !is_for_internal)
679                 return MM_ERROR_COMMON_INVALID_ARGUMENT;
680
681         if (!strncmp(volume_type_str, "system", VOLUME_TYPE_LEN)) {
682                 *volume_type = VOLUME_TYPE_SYSTEM;
683                 *is_for_internal = false;
684         } else if (!strncmp(volume_type_str, "notification", VOLUME_TYPE_LEN)) {
685                 *volume_type = VOLUME_TYPE_NOTIFICATION;
686                 *is_for_internal = false;
687         } else if (!strncmp(volume_type_str, "alarm", VOLUME_TYPE_LEN)) {
688                 *volume_type = VOLUME_TYPE_ALARM;
689                 *is_for_internal = false;
690         } else if (!strncmp(volume_type_str, "ringtone", VOLUME_TYPE_LEN)) {
691                 *volume_type = VOLUME_TYPE_RINGTONE;
692                 *is_for_internal = false;
693         } else if (!strncmp(volume_type_str, "media", VOLUME_TYPE_LEN)) {
694                 *volume_type = VOLUME_TYPE_MEDIA;
695                 *is_for_internal = false;
696         } else if (!strncmp(volume_type_str, "call", VOLUME_TYPE_LEN)) {
697                 *volume_type = VOLUME_TYPE_CALL;
698                 *is_for_internal = false;
699         } else if (!strncmp(volume_type_str, "voip", VOLUME_TYPE_LEN)) {
700                 *volume_type = VOLUME_TYPE_VOIP;
701                 *is_for_internal = false;
702         } else if (!strncmp(volume_type_str, "voice", VOLUME_TYPE_LEN)) {
703                 *volume_type = VOLUME_TYPE_VOICE;
704                 *is_for_internal = false;
705         /* else-if statements below are for internal use */
706         } else if (!strncmp(volume_type_str, "bixby", VOLUME_TYPE_LEN)) {
707                 *volume_type = VOLUME_TYPE_BIXBY;
708                 *is_for_internal = true;
709         } else {
710                 debug_log("Invalid volume type : [%s]", volume_type_str);
711                 ret = MM_ERROR_SOUND_INTERNAL;
712         }
713
714         return ret;
715 }
716
717 int mm_sound_client_set_volume_by_type(volume_type_t type, const unsigned int level)
718 {
719         int ret = MM_ERROR_NONE;
720         char *type_str = NULL;
721         debug_fenter();
722
723         if (type >= VOLUME_TYPE_MAX) {
724                 debug_error("invalid volume type %d", type);
725                 return MM_ERROR_INVALID_ARGUMENT;
726         }
727
728         if ((ret = __convert_volume_type_to_str(type, &type_str)) != MM_ERROR_NONE) {
729                 debug_error("volume type convert failed");
730                 goto failed;
731         }
732
733         ret = mm_sound_proxy_set_volume_by_type(type_str, level);
734
735 failed:
736         debug_fleave();
737         return ret;
738 }
739
740 int mm_sound_client_get_volume_by_type(volume_type_t type, unsigned int *level)
741 {
742         int ret = MM_ERROR_NONE;
743         int vconf_value = 0;
744
745         if (level == NULL) {
746                 debug_error("invalid argument, level is null");
747                 return MM_ERROR_INVALID_ARGUMENT;
748         }
749
750         if (type >= VOLUME_TYPE_MAX) {
751                 debug_error("invalid volume type %d", type);
752                 return MM_ERROR_INVALID_ARGUMENT;
753         }
754
755         /* Get volume value from VCONF */
756         if (vconf_get_int(g_volume_vconf[type], &vconf_value)) {
757                 debug_error("vconf_get_int(%s) failed..\n", g_volume_vconf[type]);
758                 return MM_ERROR_SOUND_INTERNAL;
759         }
760
761         *level = vconf_value;
762
763         return ret;
764 }
765
766 int mm_sound_client_set_volume_by_internal_type(volume_type_internal_t type, const unsigned int level)
767 {
768         int ret = MM_ERROR_NONE;
769         char *type_str = NULL;
770
771         debug_fenter();
772
773         if ((ret = __convert_volume_type_internal_to_str(type, &type_str)) != MM_ERROR_NONE) {
774                 debug_error("volume type convert failed");
775                 goto failed;
776         }
777
778         ret = mm_sound_proxy_set_volume_by_type(type_str, level);
779
780 failed:
781         debug_fleave();
782         return ret;
783 }
784
785 int mm_sound_client_get_volume_by_internal_type(volume_type_internal_t type, unsigned int *level)
786 {
787         int ret = MM_ERROR_NONE;
788         int vconf_value = 0;
789
790         if (level == NULL) {
791                 debug_error("invalid argument, level is null");
792                 return MM_ERROR_INVALID_ARGUMENT;
793         }
794
795         /* Get volume value from VCONF */
796         if (vconf_get_int(g_volume_vconf_internal[type], &vconf_value)) {
797                 debug_error("vconf_get_int(%s) failed..\n", g_volume_vconf_internal[type]);
798                 return MM_ERROR_SOUND_INTERNAL;
799         }
800
801         *level = vconf_value;
802
803         return ret;
804 }
805
806 static void _mm_sound_volume_changed_callback_wrapper_func(const char *direction, const char *volume_type_str,
807                                                                                                                 int volume_level, void *userdata)
808 {
809         int volume_type = 0;
810         bool is_for_internal =  false;
811         struct callback_data *cb_data = (struct callback_data *) userdata;
812
813         debug_log("direction : %s, volume_type : %s, volume_level : %d",
814                         direction, volume_type_str, volume_level);
815
816         if (cb_data == NULL) {
817                 debug_warning("volume changed callback data null");
818                 return;
819         }
820
821         if (__convert_volume_type_to_int(volume_type_str, &volume_type, &is_for_internal) != MM_ERROR_NONE) {
822                 debug_error("volume type convert failed");
823                 return;
824         }
825
826         if (!is_for_internal && !cb_data->extra_data) {
827                 debug_log("Invoke volume changed cb, direction : %s, vol_type : %s(%d), level : %u",
828                         direction, volume_type_str, volume_type, volume_level);
829                 ((mm_sound_volume_changed_cb)(cb_data->user_cb))((volume_type_t)volume_type, volume_level, cb_data->user_data);
830         } else if (is_for_internal && (cb_data->extra_data && (bool)(cb_data->extra_data))) {
831                 debug_log("Invoke internal volume changed cb, direction : %s, vol_type : %s(%d), level : %u",
832                         direction, volume_type_str, volume_type, volume_level);
833                 ((mm_sound_volume_changed_cb_internal)(cb_data->user_cb))((volume_type_internal_t)volume_type, volume_level, cb_data->user_data);
834         }
835 }
836
837 int mm_sound_client_add_volume_changed_callback(mm_sound_volume_changed_cb func, void* userdata, unsigned int *subs_id)
838 {
839         int ret = MM_ERROR_NONE;
840         struct callback_data *cb_data = NULL;
841
842         debug_fenter();
843
844         GET_CB_DATA(cb_data, func, userdata, NULL);
845
846         ret = mm_sound_proxy_add_volume_changed_callback(_mm_sound_volume_changed_callback_wrapper_func, cb_data, g_free, subs_id);
847
848         debug_fleave();
849
850         return ret;
851 }
852
853 int mm_sound_client_add_volume_changed_callback_internal(mm_sound_volume_changed_cb_internal func, void* userdata, unsigned int *subs_id)
854 {
855         int ret = MM_ERROR_NONE;
856         struct callback_data *cb_data = NULL;
857         gboolean is_for_internal = true;
858
859         debug_fenter();
860
861         GET_CB_DATA(cb_data, func, userdata, (void*)(uintptr_t)is_for_internal);
862
863         ret = mm_sound_proxy_add_volume_changed_callback(_mm_sound_volume_changed_callback_wrapper_func, cb_data, g_free, subs_id);
864
865         debug_fleave();
866
867         return ret;
868 }
869
870 int mm_sound_client_remove_volume_changed_callback(unsigned int subs_id)
871 {
872         int ret = MM_ERROR_NONE;
873         debug_fenter();
874
875         ret = mm_sound_proxy_remove_volume_changed_callback(subs_id);
876
877         debug_fleave();
878         return ret;
879 }
880
881 int mm_sound_client_set_mute_by_type(volume_type_t type, bool mute)
882 {
883         int ret = MM_ERROR_NONE;
884         char *type_str = NULL;
885
886         debug_fenter();
887
888         if (type > VOLUME_TYPE_VOICE) {
889                 debug_error("invalid volume type %d", type);
890                 return MM_ERROR_INVALID_ARGUMENT;
891         }
892
893         if ((ret = __convert_volume_type_to_str(type, &type_str)) != MM_ERROR_NONE) {
894                 debug_error("volume type convert failed");
895                 goto failed;
896         }
897
898         ret = mm_sound_proxy_set_mute_by_type(type_str, mute);
899
900 failed:
901         debug_fleave();
902         return ret;
903 }
904
905 int mm_sound_client_get_mute_by_type(volume_type_t type, bool *muted)
906 {
907         int ret = MM_ERROR_NONE;
908         int vconf_value = 0;
909
910         debug_fenter();
911
912         if (type > VOLUME_TYPE_VOICE) {
913                 debug_error("invalid volume type %d", type);
914                 return MM_ERROR_INVALID_ARGUMENT;
915         }
916
917         /* Get mute state from VCONF */
918         if (vconf_get_bool(g_mute_vconf[type], &vconf_value)) {
919                 debug_error("vconf_get_int(%s) failed..\n", g_mute_vconf[type]);
920                 return MM_ERROR_SOUND_INTERNAL;
921         }
922
923         *muted = (bool)vconf_value;
924
925         debug_fleave();
926         return ret;
927 }
928
929 int mm_sound_client_set_filter_by_type(const char *stream_type, const char *filter_name, const char *filter_parameters, const char *filter_group)
930 {
931         int ret = MM_ERROR_NONE;
932         debug_fenter();
933
934         ret = mm_sound_proxy_set_filter_by_type(stream_type, filter_name, filter_parameters, filter_group);
935
936         debug_fleave();
937         return ret;
938 }
939
940 int mm_sound_client_unset_filter_by_type(const char *stream_type)
941 {
942         int ret = MM_ERROR_NONE;
943         debug_fenter();
944
945         ret = mm_sound_proxy_unset_filter_by_type(stream_type);
946
947         debug_fleave();
948         return ret;
949 }
950
951 int mm_sound_client_control_filter_by_type(const char *stream_type, const char *filter_name, const char *filter_controls)
952 {
953         int ret = MM_ERROR_NONE;
954         debug_fenter();
955
956         ret = mm_sound_proxy_control_filter_by_type(stream_type, filter_name, filter_controls);
957
958         debug_fleave();
959         return ret;
960 }
961
962 int mm_sound_client_is_focus_cb_thread(GThread *mine, bool *result, bool *is_for_watching)
963 {
964         int ret = MM_ERROR_NONE;
965         int i = 0;
966
967         if (!mine || !result)
968                 ret = MM_ERROR_INVALID_ARGUMENT;
969         else {
970                 *result = false;
971                 for (i = 0; i < FOCUS_HANDLE_MAX; i++) {
972                         if (!g_focus_sound_handle[i].is_used)
973                                 continue;
974                         if (g_focus_sound_handle[i].focus_cb_thread == mine) {
975                                 *result = true;
976                                 if (is_for_watching)
977                                         *is_for_watching = false;
978                                 break;
979                         }
980                         if (g_focus_sound_handle[i].focus_watch_cb_thread == mine) {
981                                 *result = true;
982                                 if (is_for_watching)
983                                         *is_for_watching = true;
984                                 break;
985                         }
986                 }
987         }
988
989         return ret;
990 }
991
992 int mm_sound_client_register_focus(int pid, const char *stream_type,
993                                                                 mm_sound_focus_changed_cb callback, void* user_data, int *id)
994 {
995         int ret = MM_ERROR_NONE;
996         int index = -1;
997
998         debug_fenter();
999         MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_index_mutex, MM_ERROR_SOUND_INTERNAL);
1000
1001         if (focus_find_empty_index(&index)) {
1002                 ret = MM_ERROR_SOUND_INTERNAL;
1003                 goto cleanup;
1004         }
1005
1006         g_focus_sound_handle[index].focus_pid = pid;
1007         g_focus_sound_handle[index].focus_callback = callback;
1008         g_focus_sound_handle[index].user_data = user_data;
1009         g_focus_sound_handle[index].auto_reacquire = true;
1010
1011         ret = mm_sound_proxy_register_focus(index, stream_type, id);
1012         if (ret == MM_ERROR_NONE) {
1013                 debug_msg("Success to register focus, client_fd[%d], id[%d]", g_focus_sound_handle[index].client_fd, *id);
1014                 if (focus_init_context(index, false)) {
1015                         ret = MM_ERROR_SOUND_INTERNAL;
1016                         goto cleanup;
1017                 }
1018         } else {
1019                 debug_error("Error occurred : 0x%x", ret);
1020                 goto cleanup;
1021         }
1022
1023         g_mutex_init(&g_focus_sound_handle[index].focus_lock);
1024         focus_init_callback(index, false);
1025
1026 cleanup:
1027         if (ret != MM_ERROR_NONE && index >= 0)
1028                 g_focus_sound_handle[index].is_used = false;
1029
1030         MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex);
1031         debug_fleave();
1032
1033         return ret;
1034 }
1035
1036 int mm_sound_client_unregister_focus(int id)
1037 {
1038         int ret = MM_ERROR_NONE;
1039         int index = -1;
1040
1041         debug_fenter();
1042         MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_index_mutex, MM_ERROR_SOUND_INTERNAL);
1043
1044         index = focus_find_index_by_handle(id);
1045         if (index == -1) {
1046                 debug_error("Could not find index");
1047                 ret = MM_ERROR_INVALID_ARGUMENT;
1048                 goto cleanup;
1049         }
1050
1051         g_mutex_lock(&g_focus_sound_handle[index].focus_lock);
1052
1053         g_focus_sound_handle[index].is_destroying = true;
1054
1055         ret = mm_sound_proxy_unregister_focus(index);
1056         if (ret == MM_ERROR_NONE)
1057                 debug_msg("Success to unregister focus");
1058         else
1059                 debug_error("Error occurred : 0x%x", ret);
1060
1061         focus_deinit_callback(index, false);
1062         g_focus_sound_handle[index].focus_fd = 0;
1063         g_focus_sound_handle[index].focus_pid = 0;
1064         g_focus_sound_handle[index].client_fd = 0;
1065         g_focus_sound_handle[index].handle = 0;
1066         g_focus_sound_handle[index].is_used = false;
1067         focus_deinit_context(index, false);
1068
1069         g_mutex_unlock(&g_focus_sound_handle[index].focus_lock);
1070         g_mutex_clear(&g_focus_sound_handle[index].focus_lock);
1071
1072         g_focus_sound_handle[index].is_destroying = false;
1073 cleanup:
1074         MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex);
1075         debug_fleave();
1076         return ret;
1077 }
1078
1079 int mm_sound_client_set_focus_reacquisition(int id, bool reacquisition)
1080 {
1081         int ret = MM_ERROR_NONE;
1082         int index = -1;
1083         bool result;
1084
1085         debug_fenter();
1086
1087         MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_index_mutex, MM_ERROR_SOUND_INTERNAL);
1088
1089         index = focus_find_index_by_handle(id);
1090         if (index == -1) {
1091                 debug_error("Could not find index");
1092                 ret = MM_ERROR_INVALID_ARGUMENT;
1093                 goto cleanup;
1094         }
1095
1096         ret = mm_sound_client_is_focus_cb_thread(g_thread_self(), &result, NULL);
1097         if (ret) {
1098                 debug_error("mm_sound_client_is_focus_cb_thread failed");
1099                 goto cleanup;
1100         } else if (!result) {
1101                 ret = mm_sound_proxy_set_focus_reacquisition(index, reacquisition);
1102                 if (ret == MM_ERROR_NONE) {
1103                         debug_msg("Success to set focus reacquisition to [%d]", reacquisition);
1104                 } else {
1105                         debug_error("Error occurred : 0x%x", ret);
1106                         goto cleanup;
1107                 }
1108         } else {
1109                 debug_warning("Inside the focus cb thread, set focus reacquisition to [%d]", reacquisition);
1110         }
1111
1112         g_focus_sound_handle[index].auto_reacquire = reacquisition;
1113         debug_msg("set focus reacquisition(%d) for id(%d)", reacquisition, id);
1114
1115 cleanup:
1116         MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex);
1117         debug_fleave();
1118         return ret;
1119 }
1120
1121 int mm_sound_client_get_focus_reacquisition(int id, bool *reacquisition)
1122 {
1123         int ret = MM_ERROR_NONE;
1124         int index = -1;
1125
1126         debug_fenter();
1127
1128         if (!reacquisition) {
1129                 debug_error("Invalid parameter");
1130                 return MM_ERROR_INVALID_ARGUMENT;
1131         }
1132
1133         MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_index_mutex, MM_ERROR_SOUND_INTERNAL);
1134
1135         index = focus_find_index_by_handle(id);
1136         if (index == -1) {
1137                 debug_error("Could not find index");
1138                 ret = MM_ERROR_INVALID_ARGUMENT;
1139                 goto cleanup;
1140         }
1141
1142         *reacquisition = g_focus_sound_handle[index].auto_reacquire;
1143         debug_msg("get focus reacquisition(%d) for id(%d)", *reacquisition, id);
1144
1145 cleanup:
1146         MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex);
1147         debug_fleave();
1148         return ret;
1149 }
1150
1151 int mm_sound_client_get_acquired_focus_stream_type(int focus_type, char **stream_type, int *option, char **ext_info)
1152 {
1153         int ret = MM_ERROR_NONE;
1154
1155         debug_fenter();
1156
1157         ret = mm_sound_proxy_get_acquired_focus_stream_type(focus_type, stream_type, option, ext_info);
1158         if (ret == MM_ERROR_NONE)
1159                 debug_msg("Success to get stream type of acquired focus, stream_type(%s), ext_info(%s)",
1160                                 *stream_type, *ext_info);
1161         else
1162                 debug_error("Error occurred : 0x%x", ret);
1163
1164         debug_fleave();
1165
1166         return ret;
1167 }
1168
1169 int mm_sound_client_acquire_focus(int id, mm_sound_focus_type_e type, int option, const char *ext_info)
1170 {
1171         int ret = MM_ERROR_NONE;
1172         int index = -1;
1173
1174         debug_fenter();
1175         MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_index_mutex, MM_ERROR_SOUND_INTERNAL);
1176
1177         index = focus_find_index_by_handle(id);
1178         if (index == -1) {
1179                 debug_error("Could not find index");
1180                 ret = MM_ERROR_INVALID_ARGUMENT;
1181                 goto cleanup;
1182         }
1183
1184         ret = mm_sound_proxy_acquire_focus(index, type, option, ext_info);
1185         if (ret == MM_ERROR_NONE)
1186                 debug_msg("Success to acquire focus");
1187         else
1188                 debug_error("Error occurred : 0x%x", ret);
1189
1190 cleanup:
1191         MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex);
1192         debug_fleave();
1193         return ret;
1194 }
1195
1196 int mm_sound_client_release_focus(int id, mm_sound_focus_type_e type, int option, const char *ext_info)
1197 {
1198         int ret = MM_ERROR_NONE;
1199         int index = -1;
1200
1201         debug_fenter();
1202         MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_index_mutex, MM_ERROR_SOUND_INTERNAL);
1203
1204         index = focus_find_index_by_handle(id);
1205         if (index == -1) {
1206                 debug_error("Could not find index");
1207                 ret = MM_ERROR_INVALID_ARGUMENT;
1208                 goto cleanup;
1209         }
1210
1211         ret = mm_sound_proxy_release_focus(index, type, option, ext_info);
1212         if (ret == MM_ERROR_NONE)
1213                 debug_msg("Success to release focus");
1214         else
1215                 debug_error("Error occurred : 0x%x", ret);
1216
1217 cleanup:
1218         MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex);
1219         debug_fleave();
1220         return ret;
1221 }
1222
1223 int mm_sound_client_update_stream_focus_status(int id, unsigned int status)
1224 {
1225         int ret = MM_ERROR_NONE;
1226         debug_fenter();
1227
1228         if ((ret = mm_sound_proxy_update_stream_focus_status(id, status)) != MM_ERROR_NONE)
1229                 debug_error("failed to update stream focus status, ret[0x%x]", ret);
1230
1231         debug_fleave();
1232         return ret;
1233 }
1234
1235 int mm_sound_client_deliver_focus(int src_id, int dst_id, mm_sound_focus_type_e focus_type)
1236 {
1237         int ret = MM_ERROR_NONE;
1238         int src_index;
1239         int dst_index;
1240
1241         debug_fenter();
1242
1243         MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_index_mutex, MM_ERROR_SOUND_INTERNAL);
1244
1245         src_index = focus_find_index_by_handle(src_id);
1246         if (src_index == -1) {
1247                 debug_error("Could not find src index");
1248                 ret = MM_ERROR_INVALID_ARGUMENT;
1249                 goto cleanup;
1250         }
1251         dst_index = focus_find_index_by_handle(dst_id);
1252         if (dst_index == -1) {
1253                 debug_error("Could not find dst index");
1254                 ret = MM_ERROR_INVALID_ARGUMENT;
1255                 goto cleanup;
1256         }
1257         if (g_focus_sound_handle[src_index].focus_pid != g_focus_sound_handle[dst_index].focus_pid) {
1258                 debug_error("pid[%d/%d] are not same for dst/src",
1259                                         g_focus_sound_handle[src_index].focus_pid,
1260                                         g_focus_sound_handle[dst_index].focus_pid);
1261                 ret = MM_ERROR_SOUND_INTERNAL;
1262                 goto cleanup;
1263         }
1264
1265         if ((ret = mm_sound_proxy_deliver_focus(src_index, dst_index, focus_type)) != MM_ERROR_NONE)
1266                 debug_error("failed to deliver focus, ret[0x%x]", ret);
1267
1268 cleanup:
1269         MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex);
1270         debug_fleave();
1271         return ret;
1272 }
1273
1274 int mm_sound_client_set_focus_watch_callback(int pid, mm_sound_focus_type_e focus_type,
1275                                                                                         mm_sound_focus_changed_watch_cb callback, void* user_data, int *id)
1276 {
1277         int ret = MM_ERROR_NONE;
1278         int index = -1;
1279
1280         debug_fenter();
1281
1282         if (!id)
1283                 return MM_ERROR_INVALID_ARGUMENT;
1284
1285         MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_index_mutex, MM_ERROR_SOUND_INTERNAL);
1286
1287         if (focus_find_empty_index(&index)) {
1288                 ret = MM_ERROR_SOUND_INTERNAL;
1289                 goto cleanup;
1290         }
1291
1292         g_focus_sound_handle[index].focus_pid = pid;
1293         g_focus_sound_handle[index].watch_callback = callback;
1294         g_focus_sound_handle[index].user_data = user_data;
1295         g_focus_sound_handle[index].unset_watch_callback_requested = false;
1296
1297         ret = mm_sound_proxy_add_focus_watch_callback(index, focus_type);
1298         if (ret == MM_ERROR_NONE) {
1299                 *id = g_focus_sound_handle[index].handle;
1300                 debug_msg("Success to add watch focus cb, id(%d)", *id);
1301                 if (focus_init_context(index, true)) {
1302                         ret = MM_ERROR_SOUND_INTERNAL;
1303                         goto cleanup;
1304                 }
1305         } else {
1306                 debug_error("Error occurred : 0x%x", ret);
1307                 goto cleanup;
1308         }
1309
1310         focus_init_callback(index, true);
1311
1312 cleanup:
1313         if (ret != MM_ERROR_NONE && index >= 0)
1314                 g_focus_sound_handle[index].is_used = false;
1315
1316         MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex);
1317         debug_fleave();
1318         return ret;
1319 }
1320
1321 int mm_sound_client_request_unset_focus_watch_callback(int id)
1322 {
1323         int ret = MM_ERROR_NONE;
1324         int index = -1;
1325
1326         debug_fenter();
1327         MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_index_mutex, MM_ERROR_SOUND_INTERNAL);
1328
1329         index = focus_watch_find_index_by_handle(id);
1330         if (index == -1) {
1331                 debug_error("Could not find index");
1332                 ret = MM_ERROR_INVALID_ARGUMENT;
1333                 goto cleanup;
1334         }
1335         g_focus_sound_handle[index].unset_watch_callback_requested = true;
1336
1337 cleanup:
1338         MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex);
1339         debug_fleave();
1340         return ret;
1341 }
1342
1343 int mm_sound_client_unset_focus_watch_callback(int id)
1344 {
1345         int ret = MM_ERROR_NONE;
1346         int index = -1;
1347
1348         debug_fenter();
1349         MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_index_mutex, MM_ERROR_SOUND_INTERNAL);
1350
1351         index = focus_watch_find_index_by_handle(id);
1352         if (index == -1) {
1353                 debug_error("Could not find index");
1354                 ret = MM_ERROR_INVALID_ARGUMENT;
1355                 goto cleanup;
1356         }
1357
1358         g_mutex_lock(&g_focus_sound_handle[index].focus_lock);
1359
1360         g_focus_sound_handle[index].is_used = false;
1361
1362         ret = mm_sound_proxy_remove_focus_watch_callback(index);
1363         if (ret == MM_ERROR_NONE)
1364                 debug_msg("Success to remove watch focus cb, id(%d)", g_focus_sound_handle[index].handle);
1365         else
1366                 debug_error("Error occurred : 0x%x", ret);
1367
1368
1369         g_mutex_unlock(&g_focus_sound_handle[index].focus_lock);
1370
1371         focus_deinit_callback(index, true);
1372         g_focus_sound_handle[index].focus_fd = 0;
1373         g_focus_sound_handle[index].focus_pid = 0;
1374         g_focus_sound_handle[index].client_fd = 0;
1375         g_focus_sound_handle[index].handle = 0;
1376         focus_deinit_context(index, true);
1377
1378 cleanup:
1379         MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex);
1380         debug_fleave();
1381         return ret;
1382 }
1383
1384 static gboolean _idle_event_callback(void *data)
1385 {
1386         focus_idle_event_t *idle_event_data = (focus_idle_event_t*)data;
1387         int ret = MM_ERROR_NONE;
1388
1389         if (data == NULL) {
1390                 debug_error("data is null");
1391                 return FALSE;
1392         }
1393
1394         debug_msg("idle_event_data(%p): type(%d), data(%d)",
1395                 idle_event_data, idle_event_data->type, idle_event_data->data);
1396
1397         switch (idle_event_data->type) {
1398         case IDLE_EVENT_TYPE_UNSET_FOCUS_WATCH_CB:
1399                 if ((ret = mm_sound_client_unset_focus_watch_callback(idle_event_data->data)))
1400                         debug_error("Could not unset focus watch callback, id(%d), ret = %x", idle_event_data->data, ret);
1401                 break;
1402         case IDLE_EVENT_TYPE_UNREGISTER_FOCUS:
1403                 if ((ret = mm_sound_client_unregister_focus(idle_event_data->data)))
1404                         debug_error("Could not unregister focus, id(%d), ret = %x", idle_event_data->data, ret);
1405                 break;
1406         default:
1407                 debug_warning("invalid type(%d)", idle_event_data->type);
1408                 break;
1409         }
1410
1411         g_free(idle_event_data);
1412
1413         g_idle_event_src = 0;
1414
1415         MMSOUND_LEAVE_CRITICAL_SECTION(&g_event_mutex);
1416
1417         return FALSE;
1418 }
1419
1420 int mm_sound_client_execute_focus_func_in_main_context(focus_idle_event_type_e type, int data)
1421 {
1422         focus_idle_event_t *idle_event_data = NULL;
1423
1424         if (IDLE_EVENT_TYPE_MAX < type)
1425                 return MM_ERROR_INVALID_ARGUMENT;
1426
1427         MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_event_mutex, MM_ERROR_SOUND_INTERNAL);
1428
1429         idle_event_data = g_new0(focus_idle_event_t, 1);
1430         idle_event_data->type = type;
1431         idle_event_data->data = data;
1432
1433         g_idle_event_src = g_idle_add_full(G_PRIORITY_HIGH,
1434                                 (GSourceFunc)_idle_event_callback,
1435                                 (gpointer)idle_event_data,
1436                                 NULL);
1437
1438         return MM_ERROR_NONE;
1439 }
1440
1441 int mm_sound_client_add_ducking_state_changed_callback(mm_sound_ducking_state_changed_cb func, void* userdata, unsigned int *subs_id)
1442 {
1443         int ret = MM_ERROR_NONE;
1444         struct callback_data *cb_data = NULL;
1445
1446         debug_fenter();
1447
1448         GET_CB_DATA(cb_data, func, userdata, NULL);
1449
1450         ret = mm_sound_proxy_add_ducking_state_changed_callback((mm_sound_ducking_state_changed_wrapper_cb)func,
1451                 cb_data, g_free, subs_id);
1452
1453         debug_fleave();
1454
1455         return ret;
1456 }
1457
1458 int mm_sound_client_remove_ducking_state_changed_callback(unsigned int subs_id)
1459 {
1460         int ret = MM_ERROR_NONE;
1461         debug_fenter();
1462
1463         ret = mm_sound_proxy_remove_ducking_state_changed_callback(subs_id);
1464
1465         debug_fleave();
1466         return ret;
1467 }
1468