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