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