Remove unused include statement
[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 <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <poll.h>
26 #include <sys/stat.h>
27 #include <fcntl.h>
28 #include <unistd.h>
29 #include <errno.h>
30 #include <signal.h>
31
32 #include <pthread.h>
33 #include <semaphore.h>
34
35 #include <mm_error.h>
36 #include <mm_debug.h>
37
38 #include "include/mm_sound.h"
39 #include "include/mm_sound_client.h"
40 #include "include/mm_sound_proxy.h"
41 #include "include/mm_sound_common.h"
42 #include "include/mm_sound_device.h"
43 #include "include/mm_sound_stream.h"
44
45 #include <mm_session.h>
46 #include <mm_session_private.h>
47
48 #include <glib.h>
49 #if defined(__GSOURCE_CALLBACK__)
50 #include <sys/poll.h>
51 #endif
52
53 #define CLIENT_HANDLE_MAX 256
54
55 #define FOCUS_HANDLE_MAX 512
56 #define FOCUS_HANDLE_INIT_VAL -1
57 #define CONFIG_ENABLE_RETCB
58
59 #define VOLUME_TYPE_LEN 64
60
61 struct sigaction system_int_old_action;
62 struct sigaction system_abrt_old_action;
63 struct sigaction system_segv_old_action;
64 struct sigaction system_term_old_action;
65 struct sigaction system_sys_old_action;
66 struct sigaction system_xcpu_old_action;
67
68 struct callback_data {
69         void *user_cb;
70         void *user_data;
71         void *extra_data;
72         guint subs_id;
73 };
74
75 #define GET_CB_DATA(_cb_data, _func, _userdata, _extradata) \
76         do { \
77                 _cb_data = (struct callback_data*) g_malloc0(sizeof(struct callback_data)); \
78                 _cb_data->user_cb = _func; \
79                 _cb_data->user_data = _userdata; \
80                 _cb_data->extra_data = _extradata; \
81         } while (0)
82
83
84 typedef struct {
85         int focus_tid;
86         int handle;
87         int focus_fd;
88         GSourceFuncs* g_src_funcs;
89         GPollFD* g_poll_fd;
90         GSource* focus_src;
91         bool is_used;
92         bool auto_reacquire;
93         GMutex focus_lock;
94         mm_sound_focus_changed_cb focus_callback;
95         mm_sound_focus_changed_watch_cb watch_callback;
96         void* user_data;
97
98         bool is_for_session;    /* will be removed when the session concept is completely left out*/
99 } focus_sound_info_t;
100
101 typedef struct {
102         int pid;
103         int handle;
104         int type;
105         int state;
106         char stream_type[MAX_STREAM_TYPE_LEN];
107         char name[MM_SOUND_NAME_NUM];
108 } focus_cb_data_lib;
109
110 typedef struct {
111         mm_sound_focus_session_interrupt_cb user_cb;
112         void* user_data;
113 } focus_session_interrupt_info_t;
114
115 typedef struct {
116         /* handle to watch end of playing */
117         int watching_handle;
118         /* subscription id to unsubscribe when handle ended */
119         unsigned subs_id;
120 } play_sound_end_callback_data_t;
121
122 typedef gboolean (*focus_gLoopPollHandler_t)(gpointer d);
123
124 GThread *g_focus_thread;
125 GMainLoop *g_focus_loop;
126 focus_sound_info_t g_focus_sound_handle[FOCUS_HANDLE_MAX];
127 focus_session_interrupt_info_t g_focus_session_interrupt_info = {NULL, NULL};
128
129 /* global variables for device list */
130 static pthread_mutex_t g_id_mutex = PTHREAD_MUTEX_INITIALIZER;
131
132 guint g_focus_signal_handle = 0;
133 gboolean g_need_emergent_exit = FALSE;
134
135 void _system_signal_handler(int signo)
136 {
137         int ret = MM_ERROR_NONE;
138         sigset_t old_mask, all_mask;
139
140         debug_error("Got signal : signo(%d)", signo);
141
142         /* signal block */
143
144         sigfillset(&all_mask);
145         sigprocmask(SIG_BLOCK, &all_mask, &old_mask);
146
147         if (g_need_emergent_exit) {
148                 ret = mm_sound_proxy_emergent_exit(getpid());
149                 if (ret == MM_ERROR_NONE)
150                         debug_msg("[Client] Success to emergnet_exit\n");
151                 else
152                         debug_error("[Client] Error occurred : 0x%x \n",ret);
153         }
154
155         sigprocmask(SIG_SETMASK, &old_mask, NULL);
156         /* signal unblock */
157
158         switch (signo) {
159         case SIGINT:
160                 sigaction(SIGINT, &system_int_old_action, NULL);
161                 raise( signo);
162                 break;
163         case SIGABRT:
164                 sigaction(SIGABRT, &system_abrt_old_action, NULL);
165                 raise( signo);
166                 break;
167         case SIGSEGV:
168                 sigaction(SIGSEGV, &system_segv_old_action, NULL);
169                 raise( signo);
170                 break;
171         case SIGTERM:
172                 sigaction(SIGTERM, &system_term_old_action, NULL);
173                 raise( signo);
174                 break;
175         case SIGSYS:
176                 sigaction(SIGSYS, &system_sys_old_action, NULL);
177                 raise( signo);
178                 break;
179         case SIGXCPU:
180                 sigaction(SIGXCPU, &system_xcpu_old_action, NULL);
181                 raise( signo);
182                 break;
183         default:
184                 break;
185         }
186
187         debug_error("signal handling end");
188 }
189
190 int mm_sound_client_initialize(void)
191 {
192         int ret = MM_ERROR_NONE;
193         debug_fenter();
194
195         mm_sound_proxy_initialize();
196
197
198         struct sigaction system_action;
199         system_action.sa_handler = _system_signal_handler;
200         system_action.sa_flags = SA_NOCLDSTOP;
201
202         sigemptyset(&system_action.sa_mask);
203
204         sigaction(SIGINT, &system_action, &system_int_old_action);
205         sigaction(SIGABRT, &system_action, &system_abrt_old_action);
206         sigaction(SIGSEGV, &system_action, &system_segv_old_action);
207         sigaction(SIGTERM, &system_action, &system_term_old_action);
208         sigaction(SIGSYS, &system_action, &system_sys_old_action);
209         sigaction(SIGXCPU, &system_action, &system_xcpu_old_action);
210
211         debug_fleave();
212         return ret;
213 }
214
215 int mm_sound_client_finalize(void)
216 {
217         int ret = MM_ERROR_NONE;
218
219         debug_fenter();
220
221         if (g_need_emergent_exit) {
222                 ret = mm_sound_proxy_emergent_exit(getpid());
223                 if (ret == MM_ERROR_NONE)
224                         debug_msg("[Client] Success to emergnet_exit\n");
225                 else
226                         debug_error("[Client] Error occurred : 0x%x \n",ret);
227         }
228
229         sigaction(SIGINT, &system_int_old_action, NULL);
230         sigaction(SIGABRT, &system_abrt_old_action, NULL);
231         sigaction(SIGSEGV, &system_segv_old_action, NULL);
232         sigaction(SIGTERM, &system_term_old_action, NULL);
233         sigaction(SIGSYS, &system_sys_old_action, NULL);
234         sigaction(SIGXCPU, &system_xcpu_old_action, NULL);
235
236         ret = mm_sound_proxy_finalize();
237
238
239 #ifdef USE_FOCUS
240
241         if (g_focus_thread) {
242                 g_main_loop_quit(g_focus_loop);
243                 g_thread_join(g_focus_thread);
244                 debug_log("after thread join");
245                 g_main_loop_unref(g_focus_loop);
246                 g_focus_thread = NULL;
247         }
248
249 #endif
250
251         debug_fleave();
252         return ret;
253 }
254
255 void mm_sound_convert_volume_type_to_stream_type(int volume_type, char *stream_type)
256 {
257         switch (volume_type) {
258         case VOLUME_TYPE_SYSTEM:
259                 MMSOUND_STRNCPY(stream_type, "system", MM_SOUND_STREAM_TYPE_LEN);
260                 break;
261         case VOLUME_TYPE_NOTIFICATION:
262                 MMSOUND_STRNCPY(stream_type, "notification", MM_SOUND_STREAM_TYPE_LEN);
263                 break;
264         case VOLUME_TYPE_ALARM:
265                 MMSOUND_STRNCPY(stream_type, "alarm", MM_SOUND_STREAM_TYPE_LEN);
266                 break;
267         case VOLUME_TYPE_RINGTONE:
268                 MMSOUND_STRNCPY(stream_type, "ringtone-voip", MM_SOUND_STREAM_TYPE_LEN);
269                 break;
270         case VOLUME_TYPE_MEDIA:
271                 MMSOUND_STRNCPY(stream_type, "media", MM_SOUND_STREAM_TYPE_LEN);
272                 break;
273         case VOLUME_TYPE_CALL:
274                 MMSOUND_STRNCPY(stream_type, "call-voice", MM_SOUND_STREAM_TYPE_LEN);
275                 break;
276         case VOLUME_TYPE_VOIP:
277                 MMSOUND_STRNCPY(stream_type, "voip", MM_SOUND_STREAM_TYPE_LEN);
278                 break;
279         case VOLUME_TYPE_VOICE:
280                 MMSOUND_STRNCPY(stream_type, "voice-recognition", MM_SOUND_STREAM_TYPE_LEN);
281                 break;
282         default:
283                 MMSOUND_STRNCPY(stream_type, "media", MM_SOUND_STREAM_TYPE_LEN);
284                 break;
285         }
286
287         debug_error("volume type (%d) converted to stream type (%s)", volume_type, stream_type);
288
289 }
290
291 /*****************************************************************************************
292                             DBUS SUPPORTED FUNCTIONS
293 ******************************************************************************************/
294
295 void _mm_sound_client_focus_signal_callback(mm_sound_signal_name_t signal, int value, void *user_data)
296 {
297         int ret = MM_ERROR_NONE;
298
299         debug_fenter();
300         debug_error("focus signal received, value = %d", value);
301
302         if (value == 1) {
303                 ret = mm_sound_proxy_clear_focus(getpid());
304                 if (ret)
305                         debug_error("clear focus failed ret = 0x%x", ret);
306                 mm_sound_unsubscribe_signal(g_focus_signal_handle);
307                 g_focus_signal_handle = 0;
308         }
309 }
310
311 int mm_sound_client_play_tone(int number, int volume_config, double volume, int time, int *handle, bool enable_session)
312 {
313         int ret = MM_ERROR_NONE;
314 //       int instance = -1;     /* instance is unique to communicate with server : client message queue filter type */
315         int volume_type = MM_SOUND_VOLUME_CONFIG_TYPE(volume_config);
316         char stream_type[MM_SOUND_STREAM_TYPE_LEN] = {0, };
317
318          debug_fenter();
319
320         /* read session information */
321         int session_type = MM_SESSION_TYPE_MEDIA;
322         int session_options = 0;
323         int is_focus_registered = 0;
324
325         ret = mm_sound_get_signal_value(MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS, &is_focus_registered);
326         if (ret) {
327                 debug_error("mm_sound_get_signal_value failed [0x%x]", ret);
328                 return MM_ERROR_POLICY_INTERNAL;
329         }
330
331         if (is_focus_registered)
332                 enable_session = false;
333
334         if (enable_session) {
335                 if (MM_ERROR_NONE != _mm_session_util_read_information(-1, &session_type, &session_options)) {
336                         debug_warning("[Client] Read Session Information failed. use default \"media\" type\n");
337                         session_type = MM_SESSION_TYPE_MEDIA;
338
339                         if(MM_ERROR_NONE != mm_session_init(session_type)) {
340                                 debug_critical("[Client] MMSessionInit() failed\n");
341                                 return MM_ERROR_POLICY_INTERNAL;
342                         }
343                 }
344         }
345
346          // instance = getpid();
347          //debug_log("[Client] pid for client ::: [%d]\n", instance);
348
349          /* Send msg */
350          debug_msg("[Client] Input number : %d\n", number);
351          /* Send req memory */
352
353         mm_sound_convert_volume_type_to_stream_type(volume_type, stream_type);
354         ret = mm_sound_proxy_play_tone(number, time, volume, volume_config,
355                                         session_type, session_options, getpid(), enable_session, handle, stream_type, -1);
356
357         if (enable_session && !g_focus_signal_handle) {
358                 ret = mm_sound_subscribe_signal(MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS, &g_focus_signal_handle, _mm_sound_client_focus_signal_callback, NULL);
359                 if (ret) {
360                         debug_error("mm_sound_subscribe_signal failed [0x%x]", ret);
361                         return MM_ERROR_POLICY_INTERNAL;
362                 }
363         }
364
365         debug_fleave();
366         return ret;
367 }
368
369 int mm_sound_client_play_tone_with_stream_info(int tone, char *stream_type, int stream_id, double volume, int duration, int *handle)
370 {
371         int ret = MM_ERROR_NONE;
372
373         debug_fenter();
374
375         ret = mm_sound_proxy_play_tone_with_stream_info(getpid(), tone, stream_type, stream_id, volume, duration, handle);
376
377         debug_fleave();
378         return ret;
379 }
380
381 static void _mm_sound_stop_callback_wrapper_func(int ended_handle, void *userdata)
382 {
383         struct callback_data *cb_data = (struct callback_data*) userdata;
384         play_sound_end_callback_data_t *end_cb_data = (play_sound_end_callback_data_t*) cb_data->extra_data;
385
386         debug_log("[Wrapper CB][Play Stop] ended_handle : %d", ended_handle);
387
388         if (cb_data == NULL) {
389                 debug_warning("stop callback data null");
390                 return;
391         }
392         if (ended_handle == end_cb_data->watching_handle) {
393                 debug_log("Interested playing handle end : %d", ended_handle);
394                 ((mm_sound_stop_callback_func)(cb_data->user_cb))(cb_data->user_data, ended_handle);
395                 if (mm_sound_proxy_remove_play_sound_end_callback(end_cb_data->subs_id) != MM_ERROR_NONE)
396                         debug_error("mm_sound_client_dbus_remove_play_file_end_callback failed");
397         } else {
398                 debug_log("Not interested playing handle : %d", ended_handle);
399         }
400 }
401
402 static void play_end_callback_data_free_func(void *data)
403 {
404         struct callback_data *cb_data = (struct callback_data*) data;
405         play_sound_end_callback_data_t *end_cb_data = (play_sound_end_callback_data_t*) cb_data->extra_data;
406
407         g_free(end_cb_data);
408 }
409
410 int mm_sound_client_play_sound(MMSoundPlayParam *param, int tone, int *handle)
411 {
412         int ret = MM_ERROR_NONE;
413         int session_type = MM_SESSION_TYPE_MEDIA;
414         int session_options = 0;
415         int is_focus_registered = 0;
416 //      int instance = -1;      /* instance is unique to communicate with server : client message queue filter type */
417         int volume_type = MM_SOUND_VOLUME_CONFIG_TYPE(param->volume_config);
418         char stream_type[MM_SOUND_STREAM_TYPE_LEN] = {0, };
419         struct callback_data *cb_data = NULL;
420         play_sound_end_callback_data_t *end_cb_data;
421
422         debug_fenter();
423
424         /* read session information */
425
426         ret = mm_sound_get_signal_value(MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS, &is_focus_registered);
427         if (ret) {
428                 debug_error("mm_sound_get_signal_value failed [0x%x]", ret);
429                 return MM_ERROR_POLICY_INTERNAL;
430         }
431
432         if (is_focus_registered)
433                 param->skip_session = true;
434
435         if (param->skip_session == false) {
436                 if(MM_ERROR_NONE != _mm_session_util_read_information(-1, &session_type, &session_options)) {
437                         debug_warning("[Client] Read MMSession Type failed. use default \"media\" type\n");
438                         session_type = MM_SESSION_TYPE_MEDIA;
439
440                         if(MM_ERROR_NONE != mm_session_init(session_type)) {
441                                 debug_critical("[Client] MMSessionInit() failed\n");
442                                 return MM_ERROR_POLICY_INTERNAL;
443                         }
444                 }
445         }
446
447         /* Send msg */
448         if ((param->mem_ptr && param->mem_size)) {
449                 // Play memory, deprecated
450                 return MM_ERROR_INVALID_ARGUMENT;
451         }
452
453         mm_sound_convert_volume_type_to_stream_type(volume_type, stream_type);
454         ret = mm_sound_proxy_play_sound(param->filename, tone, param->loop, param->volume, param->volume_config,
455                                          param->priority, session_type, session_options, getpid(), param->handle_route,
456                                          !param->skip_session, handle, stream_type, -1);
457         if (ret != MM_ERROR_NONE) {
458                 debug_error("Play Sound Failed");
459                 goto failed;
460         }
461         if (param->callback) {
462                 end_cb_data = (play_sound_end_callback_data_t *) g_malloc0(sizeof(play_sound_end_callback_data_t));
463                 end_cb_data->watching_handle = *handle;
464                 GET_CB_DATA(cb_data, param->callback, param->data, end_cb_data);
465
466                 ret = mm_sound_proxy_add_play_sound_end_callback(_mm_sound_stop_callback_wrapper_func, cb_data, play_end_callback_data_free_func, &end_cb_data->subs_id);
467                 if (ret != MM_ERROR_NONE) {
468                         debug_error("Add callback for play sound(%d) Failed", *handle);
469                 }
470         }
471         if (!param->skip_session && !g_focus_signal_handle) {
472                 ret = mm_sound_subscribe_signal(MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS, &g_focus_signal_handle, _mm_sound_client_focus_signal_callback, NULL);
473                 if (ret) {
474                         debug_error("mm_sound_subscribe_signal failed [0x%x]", ret);
475                         return MM_ERROR_POLICY_INTERNAL;
476                 }
477         }
478
479 failed:
480
481         debug_fleave();
482         return ret;
483 }
484
485 int mm_sound_client_play_sound_with_stream_info(MMSoundPlayParam *param, int *handle, char* stream_type, int stream_id)
486 {
487         int ret = MM_ERROR_NONE;
488         struct callback_data *cb_data = NULL;
489         play_sound_end_callback_data_t *end_cb_data;
490
491         ret = mm_sound_proxy_play_sound_with_stream_info(param->filename, param->loop, param->volume,
492                                          param->priority, getpid(), param->handle_route, handle, stream_type, stream_id);
493         if (ret != MM_ERROR_NONE) {
494                 debug_error("Play Sound Failed");
495                 goto failed;
496         }
497         if (param->callback) {
498                 end_cb_data = (play_sound_end_callback_data_t *) g_malloc0(sizeof(play_sound_end_callback_data_t));
499                 end_cb_data->watching_handle = *handle;
500                 GET_CB_DATA(cb_data, param->callback, param->data, end_cb_data);
501
502                 ret = mm_sound_proxy_add_play_sound_end_callback(_mm_sound_stop_callback_wrapper_func, cb_data, play_end_callback_data_free_func, &end_cb_data->subs_id);
503                 if (ret != MM_ERROR_NONE) {
504                         debug_error("Add callback for play sound(%d) Failed", *handle);
505                 }
506         }
507
508 failed:
509
510         debug_fleave();
511         return ret;
512
513 }
514
515 int mm_sound_client_stop_sound(int handle)
516 {
517         int ret = MM_ERROR_NONE;
518         debug_fenter();
519
520         if (handle < 0 || handle > CLIENT_HANDLE_MAX) {
521                 ret = MM_ERROR_INVALID_ARGUMENT;
522                 return ret;
523         }
524
525         ret = mm_sound_proxy_stop_sound(handle);
526
527         debug_fleave();
528         return ret;
529 }
530
531 static int _mm_sound_client_device_list_dump (GList *device_list)
532 {
533         int ret = MM_ERROR_NONE;
534         GList *list = NULL;
535         mm_sound_device_t *device_node = NULL;
536         int count = 0;
537         if (!device_list) {
538                 debug_error("Device list NULL, cannot dump list");
539                 return MM_ERROR_SOUND_INTERNAL;
540         }
541
542         debug_log("======================== device list : start ==========================\n");
543         for (list = device_list; list != NULL; list = list->next) {
544                 device_node = (mm_sound_device_t *)list->data;
545                 if (device_node) {
546                         debug_log(" list idx[%d]: type[%17s], id[%02d], io_direction[%d], state[%d], name[%s]\n",
547                                                 count++, device_node->type, device_node->id, device_node->io_direction, device_node->state, device_node->name);
548                 }
549         }
550         debug_log("======================== device list : end ============================\n");
551
552         return ret;
553 }
554
555 int mm_sound_client_get_current_connected_device_list(int device_flags, mm_sound_device_list_t *device_list)
556 {
557         int ret = MM_ERROR_NONE;
558         debug_fenter();
559
560         if (!device_list) {
561                 debug_error("Device list NULL");
562                 ret = MM_ERROR_COMMON_INVALID_ARGUMENT;
563                 goto failed;
564         }
565
566         if ((ret = mm_sound_proxy_get_current_connected_device_list(device_flags, &device_list->list)) != MM_ERROR_NONE) {
567                 debug_error("[Client] failed to get current connected device list with dbus, ret[0x%x]", ret);
568                 goto failed;
569         }
570         if (!device_list->list) {
571                 debug_error("Got device list null");
572                 ret = MM_ERROR_SOUND_NO_DATA;
573                 goto failed;
574         }
575         _mm_sound_client_device_list_dump(device_list->list);
576
577 failed:
578         debug_fleave();
579         return ret;
580 }
581
582 static bool is_device_match_flags(const char *device_type, int io_direction, int state, int device_flags)
583 {
584         int io_direction_flag = device_flags & DEVICE_IO_DIRECTION_FLAGS;
585         int state_flag = device_flags & DEVICE_STATE_FLAGS;
586         int type_flag = device_flags & DEVICE_TYPE_FLAGS;
587         char builtin_prefix[] = "builtin";
588
589         if (device_flags == DEVICE_ALL_FLAG)
590                 return TRUE;
591
592         switch (io_direction_flag) {
593         case DEVICE_IO_DIRECTION_IN_FLAG:
594                 if (io_direction != DEVICE_IO_DIRECTION_IN)
595                         return FALSE;
596                 break;
597         case DEVICE_IO_DIRECTION_OUT_FLAG:
598                 if (io_direction != DEVICE_IO_DIRECTION_OUT)
599                         return FALSE;
600                 break;
601         case DEVICE_IO_DIRECTION_BOTH_FLAG:
602                 if (io_direction != DEVICE_IO_DIRECTION_BOTH)
603                         return FALSE;
604                 break;
605         default:
606                 break;
607         }
608
609         switch (state_flag) {
610         case DEVICE_STATE_DEACTIVATED_FLAG:
611                 if (state != DEVICE_STATE_DEACTIVATED)
612                         return FALSE;
613                 break;
614         case DEVICE_STATE_ACTIVATED_FLAG:
615                 if (state != DEVICE_STATE_ACTIVATED)
616                         return FALSE;
617                 break;
618         default:
619                 break;
620         }
621
622         switch (type_flag) {
623         case DEVICE_TYPE_INTERNAL_FLAG:
624                 if (strncmp(device_type, builtin_prefix, strlen(builtin_prefix)) != 0)
625                         return FALSE;
626                 break;
627         case DEVICE_TYPE_EXTERNAL_FLAG:
628                 if (strncmp(device_type, builtin_prefix, strlen(builtin_prefix)) == 0)
629                         return FALSE;
630                 break;
631         default:
632                 break;
633         }
634
635         return TRUE;
636 }
637
638 static void _mm_sound_device_connected_callback_wrapper_func(int device_id, const char *device_type, int io_direction, int state, const char *name, gboolean is_connected, void *userdata)
639 {
640         mm_sound_device_t device_h;
641         struct callback_data *cb_data = (struct callback_data*) userdata;
642         int device_flags = (int) cb_data->extra_data;
643
644         debug_log("[Wrapper CB][Device Connnected] device_id : %d, device_type : %s, direction : %d, state : %d, name : %s, is_connected : %d",
645                           device_id, device_type, io_direction, state, name, is_connected);
646
647         if (cb_data == NULL) {
648                 debug_warning("device connected changed callback data null");
649                 return;
650         }
651         if (!is_device_match_flags(device_type, io_direction, state, device_flags))
652                 return;
653
654         device_h.id = device_id;
655         device_h.io_direction = io_direction;
656         device_h.state = state;
657         MMSOUND_STRNCPY(device_h.name, name, MAX_DEVICE_NAME_NUM);
658         MMSOUND_STRNCPY(device_h.type, device_type, MAX_DEVICE_TYPE_STR_LEN);
659
660         ((mm_sound_device_connected_cb)(cb_data->user_cb))(&device_h, is_connected, cb_data->user_data);
661 }
662
663 int mm_sound_client_add_device_connected_callback(int device_flags, mm_sound_device_connected_cb func, void* userdata, unsigned int *subs_id)
664 {
665         int ret = MM_ERROR_NONE;
666         struct callback_data *cb_data = NULL;
667
668         debug_fenter();
669
670         GET_CB_DATA(cb_data, func, userdata, (void*) device_flags);
671
672         ret = mm_sound_proxy_add_device_connected_callback(device_flags, _mm_sound_device_connected_callback_wrapper_func, cb_data, g_free, subs_id);
673         if (ret != MM_ERROR_NONE)
674                 g_need_emergent_exit = TRUE;
675
676         debug_fleave();
677         return ret;
678 }
679
680 int mm_sound_client_remove_device_connected_callback(unsigned int subs_id)
681 {
682         int ret = MM_ERROR_NONE;
683         debug_fenter();
684
685         ret = mm_sound_proxy_remove_device_connected_callback(subs_id);
686
687         debug_fleave();
688         return ret;
689 }
690
691 static void _mm_sound_device_info_changed_callback_wrapper_func(int device_id, const char *device_type, int io_direction, int state, const char *name, int changed_device_info_type, void *userdata)
692 {
693         mm_sound_device_t device_h;
694         struct callback_data *cb_data = (struct callback_data*) userdata;
695         int device_flags = (int) cb_data->extra_data;
696
697         debug_log("[Wrapper CB][Device Info Changed] device_id : %d, device_type : %s, direction : %d, state : %d, name : %s, changed_info_type : %d",
698                           device_id, device_type, io_direction, state, name, changed_device_info_type);
699
700         if (cb_data == NULL) {
701                 debug_warning("device info changed callback data null");
702                 return;
703         }
704         if (!is_device_match_flags(device_type, io_direction, state, device_flags))
705                 return;
706
707         device_h.id = device_id;
708         device_h.io_direction = io_direction;
709         device_h.state = state;
710         MMSOUND_STRNCPY(device_h.name, name, MAX_DEVICE_NAME_NUM);
711         MMSOUND_STRNCPY(device_h.type, device_type, MAX_DEVICE_TYPE_STR_LEN);
712
713         ((mm_sound_device_info_changed_cb)(cb_data->user_cb))(&device_h, changed_device_info_type, cb_data->user_data);
714 }
715
716 int mm_sound_client_add_device_info_changed_callback(int device_flags, mm_sound_device_info_changed_cb func, void *userdata, unsigned int *subs_id)
717 {
718         int ret = MM_ERROR_NONE;
719         struct callback_data *cb_data = (struct callback_data*) userdata;
720
721         debug_fenter();
722
723         GET_CB_DATA(cb_data, func, userdata, (void *) device_flags);
724
725         ret = mm_sound_proxy_add_device_info_changed_callback(device_flags, _mm_sound_device_info_changed_callback_wrapper_func, cb_data, g_free, subs_id);
726
727         debug_fleave();
728         return ret;
729 }
730
731 int mm_sound_client_remove_device_info_changed_callback(unsigned int subs_id)
732 {
733         int ret = MM_ERROR_NONE;
734         debug_fenter();
735
736         ret =  mm_sound_proxy_remove_device_info_changed_callback(subs_id);
737
738         debug_fleave();
739         return ret;
740
741 }
742
743 int __convert_volume_type_to_str(int volume_type, char **volume_type_str)
744 {
745         int ret = MM_ERROR_NONE;
746
747         if (!volume_type_str) {
748                 return MM_ERROR_COMMON_INVALID_ARGUMENT;
749         }
750
751         switch (volume_type) {
752         case VOLUME_TYPE_SYSTEM:
753                 *volume_type_str = "system";
754                 break;
755         case VOLUME_TYPE_NOTIFICATION:
756                 *volume_type_str = "notification";
757                 break;
758         case VOLUME_TYPE_ALARM:
759                 *volume_type_str = "alarm";
760                 break;
761         case VOLUME_TYPE_RINGTONE:
762                 *volume_type_str = "ringtone";
763                 break;
764         case VOLUME_TYPE_MEDIA:
765                 *volume_type_str = "media";
766                 break;
767         case VOLUME_TYPE_CALL:
768                 *volume_type_str = "call";
769                 break;
770         case VOLUME_TYPE_VOIP:
771                 *volume_type_str = "voip";
772                 break;
773         case VOLUME_TYPE_VOICE:
774                 *volume_type_str = "voice";
775                 break;
776         }
777         if (!strncmp(*volume_type_str,"", VOLUME_TYPE_LEN)) {
778                 debug_error("could not find the volume_type[%d] in this switch case statement", volume_type);
779                 ret = MM_ERROR_SOUND_INTERNAL;
780         } else {
781                 debug_log("volume_type[%s]", *volume_type_str);
782         }
783         return ret;
784 }
785
786 static int __convert_volume_type_to_int(const char *volume_type_str, volume_type_t *volume_type)
787 {
788         int ret = MM_ERROR_NONE;
789
790         if (!volume_type || !volume_type_str) {
791                 return MM_ERROR_COMMON_INVALID_ARGUMENT;
792         }
793
794         if (!strncmp(volume_type_str, "system", VOLUME_TYPE_LEN)) {
795                 *volume_type = VOLUME_TYPE_SYSTEM;
796         } else if (!strncmp(volume_type_str, "notification", VOLUME_TYPE_LEN)) {
797                 *volume_type = VOLUME_TYPE_NOTIFICATION;
798         } else if (!strncmp(volume_type_str, "alarm", VOLUME_TYPE_LEN)) {
799                 *volume_type = VOLUME_TYPE_ALARM;
800         } else if (!strncmp(volume_type_str, "ringtone", VOLUME_TYPE_LEN)) {
801                 *volume_type = VOLUME_TYPE_RINGTONE;
802         } else if (!strncmp(volume_type_str, "media", VOLUME_TYPE_LEN)) {
803                 *volume_type = VOLUME_TYPE_MEDIA;
804         } else if (!strncmp(volume_type_str, "call", VOLUME_TYPE_LEN)) {
805                 *volume_type = VOLUME_TYPE_CALL;
806         } else if (!strncmp(volume_type_str, "voip", VOLUME_TYPE_LEN)) {
807                 *volume_type = VOLUME_TYPE_VOIP;
808         } else if (!strncmp(volume_type_str, "voice", VOLUME_TYPE_LEN)) {
809                 *volume_type = VOLUME_TYPE_VOICE;
810         } else {
811                 debug_log("Invalid volume type : [%s]", volume_type_str);
812                 ret = MM_ERROR_SOUND_INTERNAL;
813         }
814
815         return ret;
816 }
817
818 int mm_sound_client_set_volume_by_type(const int volume_type, const unsigned int volume_level)
819 {
820         int ret = MM_ERROR_NONE;
821         char *type_str = NULL;
822         debug_fenter();
823
824         if ((ret = __convert_volume_type_to_str(volume_type, &type_str)) != MM_ERROR_NONE) {
825                 debug_error("volume type convert failed");
826                 goto failed;
827         }
828
829         ret = mm_sound_proxy_set_volume_by_type(type_str, volume_level);
830
831 failed:
832         debug_fleave();
833         return ret;
834 }
835
836 static void _mm_sound_volume_changed_callback_wrapper_func(const char *direction, const char *volume_type_str, int volume_level, void *userdata)
837 {
838         volume_type_t volume_type = 0;
839         struct callback_data *cb_data = (struct callback_data *) userdata;
840
841         debug_log("[Wrapper CB][Volume Changed] direction : %s, volume_type : %s, volume_level : %d", direction, volume_type_str, volume_level);
842
843         if (cb_data == NULL) {
844                 debug_warning("volume changed callback data null");
845                 return;
846         }
847
848         if (__convert_volume_type_to_int(volume_type_str, &volume_type) != MM_ERROR_NONE) {
849                 debug_error("volume type convert failed");
850                 return;
851         }
852         debug_log("Call volume changed user cb, direction : %s, vol_type : %s(%d), level : %u", direction, volume_type_str, volume_type, volume_level);
853         ((mm_sound_volume_changed_cb)(cb_data->user_cb))(volume_type, volume_level, cb_data->user_data);
854 }
855
856 int mm_sound_client_add_volume_changed_callback(mm_sound_volume_changed_cb func, void* userdata, unsigned int *subs_id)
857 {
858         int ret = MM_ERROR_NONE;
859         struct callback_data *cb_data = NULL;
860
861         debug_fenter();
862
863         GET_CB_DATA(cb_data, func, userdata, NULL);
864
865         ret = mm_sound_proxy_add_volume_changed_callback(_mm_sound_volume_changed_callback_wrapper_func, cb_data, g_free, subs_id);
866
867         debug_fleave();
868
869         return ret;
870 }
871
872 int mm_sound_client_remove_volume_changed_callback(unsigned int subs_id)
873 {
874         int ret = MM_ERROR_NONE;
875         debug_fenter();
876
877         ret = mm_sound_proxy_remove_volume_changed_callback(subs_id);
878
879         debug_fleave();
880         return ret;
881 }
882
883 #ifdef USE_FOCUS
884 int mm_sound_client_set_session_interrupt_callback(mm_sound_focus_session_interrupt_cb callback, void* user_data)
885 {
886         int ret = MM_ERROR_NONE;
887
888         debug_fenter();
889
890         if (!callback)
891                 return MM_ERROR_INVALID_ARGUMENT;
892
893         g_focus_session_interrupt_info.user_cb = callback;
894         g_focus_session_interrupt_info.user_data = user_data;
895
896         debug_fleave();
897         return ret;
898 }
899
900 int mm_sound_client_unset_session_interrupt_callback(void)
901 {
902         int ret = MM_ERROR_NONE;
903
904         debug_fenter();
905
906         if (!g_focus_session_interrupt_info.user_cb) {
907                 debug_error("no callback to unset");
908                 return MM_ERROR_SOUND_INTERNAL;
909         }
910
911         g_focus_session_interrupt_info.user_cb = NULL;
912         g_focus_session_interrupt_info.user_data = NULL;
913
914         debug_fleave();
915         return ret;
916 }
917
918 static gpointer _focus_thread_func(gpointer data)
919 {
920         debug_log(">>> thread func..ID of this thread(%u)\n", (unsigned int)pthread_self());
921         g_main_loop_run(g_focus_loop);
922         debug_log("<<< quit thread func..\n");
923         return NULL;
924 }
925
926 static gboolean _focus_fd_check(GSource * source)
927 {
928         GSList *fd_list;
929         GPollFD *temp;
930
931         if (!source) {
932                 debug_error("GSource is null");
933                 return FALSE;
934         }
935         fd_list = source->poll_fds;
936         if (!fd_list) {
937                 debug_error("fd_list is null");
938                 return FALSE;
939         }
940         do {
941                 temp = (GPollFD*)fd_list->data;
942                 if (!temp) {
943                         debug_error("fd_list->data is null");
944                         return FALSE;
945                 }
946                 if (temp->revents & (POLLIN | POLLPRI)) {
947                         return TRUE;
948                 }
949                 fd_list = fd_list->next;
950         } while (fd_list);
951
952         return FALSE; /* there is no change in any fd state */
953 }
954
955 static gboolean _focus_fd_prepare(GSource *source, gint *timeout)
956 {
957         return FALSE;
958 }
959
960 static gboolean _focus_fd_dispatch(GSource *source,     GSourceFunc callback, gpointer user_data)
961 {
962         callback(user_data);
963         return TRUE;
964 }
965
966
967 static int _focus_find_index_by_handle(int handle)
968 {
969         int i = 0;
970         for(i = 0; i< FOCUS_HANDLE_MAX; i++) {
971                 if (handle == g_focus_sound_handle[i].handle) {
972                         //debug_msg("found index(%d) for handle(%d)", i, handle);
973                         if (handle == FOCUS_HANDLE_INIT_VAL) {
974                                 return -1;
975                         }
976                         return i;
977                 }
978         }
979         return -1;
980 }
981
982 static gboolean _focus_callback_handler(gpointer d)
983 {
984         GPollFD *data = (GPollFD*)d;
985         int count;
986         int tid = 0;
987         int focus_index = 0;
988         focus_cb_data_lib cb_data;
989         debug_log(">>> focus_callback_handler()..ID of this thread(%u)\n", (unsigned int)pthread_self());
990
991         memset(&cb_data, 0, sizeof(focus_cb_data_lib));
992
993         if (!data) {
994                 debug_error("GPollFd is null");
995                 return FALSE;
996         }
997         if (data->revents & (POLLIN | POLLPRI)) {
998                 int changed_state = -1;
999
1000                 count = read(data->fd, &cb_data, sizeof(cb_data));
1001                 if (count < 0){
1002                         char str_error[256];
1003                         strerror_r(errno, str_error, sizeof(str_error));
1004                         debug_error("GpollFD read fail, errno=%d(%s)",errno, str_error);
1005                         return FALSE;
1006                 }
1007                 changed_state = cb_data.state;
1008                 focus_index = _focus_find_index_by_handle(cb_data.handle);
1009                 if (focus_index == -1) {
1010                         debug_error("Could not find index");
1011                         return FALSE;
1012                 }
1013
1014                 g_mutex_lock(&g_focus_sound_handle[focus_index].focus_lock);
1015
1016                 tid = g_focus_sound_handle[focus_index].focus_tid;
1017
1018                 if (changed_state != -1) {
1019                         debug_error("Got and start CB : TID(%d), handle(%d), type(%d), state(%d,(DEACTIVATED(0)/ACTIVATED(1)), trigger(%s)", tid, cb_data.handle, cb_data.type, cb_data.state, cb_data.stream_type);
1020                         if (g_focus_sound_handle[focus_index].focus_callback== NULL) {
1021                                         debug_error("callback is null..");
1022                                         g_mutex_unlock(&g_focus_sound_handle[focus_index].focus_lock);
1023                                         return FALSE;
1024                         }
1025                         debug_error("[CALLBACK(%p) START]",g_focus_sound_handle[focus_index].focus_callback);
1026                         (g_focus_sound_handle[focus_index].focus_callback)(cb_data.handle, cb_data.type, cb_data.state, cb_data.stream_type, cb_data.name, g_focus_sound_handle[focus_index].user_data);
1027                         debug_error("[CALLBACK END]");
1028                         if (g_focus_session_interrupt_info.user_cb) {
1029                                 debug_error("sending session interrupt callback(%p)", g_focus_session_interrupt_info.user_cb);
1030                                 (g_focus_session_interrupt_info.user_cb)(cb_data.state, cb_data.stream_type, false, g_focus_session_interrupt_info.user_data);
1031                         }
1032                 }
1033 #ifdef CONFIG_ENABLE_RETCB
1034
1035                                 int rett = 0;
1036                                 int tmpfd = -1;
1037                                 unsigned int buf = 0;
1038                                 char *filename2 = g_strdup_printf("/tmp/FOCUS.%d.%dr", g_focus_sound_handle[focus_index].focus_tid, cb_data.handle);
1039                                 tmpfd = open(filename2, O_WRONLY | O_NONBLOCK);
1040                                 if (tmpfd < 0) {
1041                                         char str_error[256];
1042                                         strerror_r(errno, str_error, sizeof(str_error));
1043                                         debug_error("[RETCB][Failed(May Server Close First)]tid(%d) fd(%d) %s errno=%d(%s)\n", tid, tmpfd, filename2, errno, str_error);
1044                                         g_free(filename2);
1045                                         g_mutex_unlock(&g_focus_sound_handle[focus_index].focus_lock);
1046                                         return FALSE;
1047                                 }
1048                                 buf = (unsigned int)((0x0000ffff & cb_data.handle) |(g_focus_sound_handle[focus_index].auto_reacquire << 16));
1049                                 rett = write(tmpfd, &buf, sizeof(buf));
1050                                 close(tmpfd);
1051                                 g_free(filename2);
1052                                 debug_msg("[RETCB] tid(%d) finishing CB (write=%d)\n", tid, rett);
1053 #endif
1054         }
1055
1056         g_mutex_unlock(&g_focus_sound_handle[focus_index].focus_lock);
1057
1058         return TRUE;
1059 }
1060
1061 static gboolean _focus_watch_callback_handler( gpointer d)
1062 {
1063         GPollFD *data = (GPollFD*)d;
1064         int count;
1065         int tid = 0;
1066         int focus_index = 0;
1067         focus_cb_data_lib cb_data;
1068
1069         debug_fenter();
1070
1071         memset(&cb_data, 0, sizeof(focus_cb_data_lib));
1072
1073         if (!data) {
1074                 debug_error("GPollFd is null");
1075                 return FALSE;
1076         }
1077         if (data->revents & (POLLIN | POLLPRI)) {
1078                 count = read(data->fd, &cb_data, sizeof(cb_data));
1079                 if (count < 0){
1080                         char str_error[256];
1081                         strerror_r(errno, str_error, sizeof(str_error));
1082                         debug_error("GpollFD read fail, errno=%d(%s)",errno, str_error);
1083                         return FALSE;
1084                 }
1085
1086                 focus_index = _focus_find_index_by_handle(cb_data.handle);
1087                 if (focus_index == -1) {
1088                         debug_error("Could not find index");
1089                         return FALSE;
1090                 }
1091
1092                 debug_error("lock focus_lock = %p", &g_focus_sound_handle[focus_index].focus_lock);
1093                 g_mutex_lock(&g_focus_sound_handle[focus_index].focus_lock);
1094
1095                 tid = g_focus_sound_handle[focus_index].focus_tid;
1096
1097                 debug_error("Got and start CB : TID(%d), handle(%d), type(%d), state(%d,(DEACTIVATED(0)/ACTIVATED(1)), trigger(%s)", tid, cb_data.handle,  cb_data.type, cb_data.state, cb_data.stream_type);
1098
1099                 if (g_focus_sound_handle[focus_index].watch_callback == NULL) {
1100                         debug_msg("callback is null..");
1101                 } else {
1102                         debug_msg("[CALLBACK(%p) START]",g_focus_sound_handle[focus_index].watch_callback);
1103                         (g_focus_sound_handle[focus_index].watch_callback)(cb_data.handle, cb_data.type, cb_data.state, cb_data.stream_type, cb_data.name, g_focus_sound_handle[focus_index].user_data);
1104                         debug_msg("[CALLBACK END]");
1105                         if (g_focus_session_interrupt_info.user_cb) {
1106                                 debug_error("sending session interrupt callback(%p)", g_focus_session_interrupt_info.user_cb);
1107                                 (g_focus_session_interrupt_info.user_cb)(cb_data.state, cb_data.stream_type, true, g_focus_session_interrupt_info.user_data);
1108                         }
1109                 }
1110
1111 #ifdef CONFIG_ENABLE_RETCB
1112
1113                         int rett = 0;
1114                         int tmpfd = -1;
1115                         int buf = -1;
1116                         char *filename2 = g_strdup_printf("/tmp/FOCUS.%d.wchr", g_focus_sound_handle[focus_index].focus_tid);
1117                         tmpfd = open(filename2, O_WRONLY | O_NONBLOCK);
1118                         if (tmpfd < 0) {
1119                                 char str_error[256];
1120                                 strerror_r(errno, str_error, sizeof(str_error));
1121                                 debug_error("[RETCB][Failed(May Server Close First)]tid(%d) fd(%d) %s errno=%d(%s)\n", tid, tmpfd, filename2, errno, str_error);
1122                                 g_free(filename2);
1123                                 g_mutex_unlock(&g_focus_sound_handle[focus_index].focus_lock);
1124                                 return FALSE;
1125                         }
1126                         buf = cb_data.handle;
1127                         rett = write(tmpfd, &buf, sizeof(buf));
1128                         close(tmpfd);
1129                         g_free(filename2);
1130                         debug_msg("[RETCB] tid(%d) finishing CB (write=%d)\n", tid, rett);
1131
1132 #endif
1133
1134         }
1135
1136         debug_error("unlock focus_lock = %p", &g_focus_sound_handle[focus_index].focus_lock);
1137         g_mutex_unlock(&g_focus_sound_handle[focus_index].focus_lock);
1138
1139         debug_fleave();
1140
1141
1142         return TRUE;
1143 }
1144
1145 static void _focus_open_callback(int index, bool is_for_watching)
1146 {
1147         mode_t pre_mask;
1148         char *filename;
1149
1150         debug_fenter();
1151
1152         if (is_for_watching) {
1153                 filename = g_strdup_printf("/tmp/FOCUS.%d.wch", g_focus_sound_handle[index].focus_tid);
1154         } else {
1155                 filename = g_strdup_printf("/tmp/FOCUS.%d.%d", g_focus_sound_handle[index].focus_tid, g_focus_sound_handle[index].handle);
1156         }
1157         pre_mask = umask(0);
1158         if (mknod(filename, S_IFIFO|0666, 0)) {
1159                 debug_error("mknod() failure, errno(%d)", errno);
1160         }
1161         umask(pre_mask);
1162         g_focus_sound_handle[index].focus_fd = open( filename, O_RDWR|O_NONBLOCK);
1163         if (g_focus_sound_handle[index].focus_fd == -1) {
1164                 debug_error("Open fail : index(%d), file open error(%d)", index, errno);
1165         } else {
1166                 debug_log("Open sucess : index(%d), filename(%s), fd(%d)", index, filename, g_focus_sound_handle[index].focus_fd);
1167         }
1168         g_free(filename);
1169         filename = NULL;
1170
1171 #ifdef CONFIG_ENABLE_RETCB
1172         char *filename2;
1173
1174         if (is_for_watching) {
1175                 filename2 = g_strdup_printf("/tmp/FOCUS.%d.wchr", g_focus_sound_handle[index].focus_tid);
1176         } else {
1177                 filename2 = g_strdup_printf("/tmp/FOCUS.%d.%dr", g_focus_sound_handle[index].focus_tid, g_focus_sound_handle[index].handle);
1178         }
1179         pre_mask = umask(0);
1180         if (mknod(filename2, S_IFIFO | 0666, 0)) {
1181                 debug_error("mknod() failure, errno(%d)", errno);
1182         }
1183         umask(pre_mask);
1184         g_free(filename2);
1185         filename2 = NULL;
1186 #endif
1187         debug_fleave();
1188
1189 }
1190
1191 void _focus_close_callback(int index, bool is_for_watching)
1192 {
1193         debug_fenter();
1194
1195         if (g_focus_sound_handle[index].focus_fd < 0) {
1196                 debug_error("Close fail : fd error.");
1197         } else {
1198                 char *filename;
1199                 if (is_for_watching) {
1200                         filename = g_strdup_printf("/tmp/FOCUS.%d.wch", g_focus_sound_handle[index].focus_tid);
1201                 } else {
1202                         filename = g_strdup_printf("/tmp/FOCUS.%d.%d", g_focus_sound_handle[index].focus_tid, g_focus_sound_handle[index].handle);
1203                 }
1204                 close(g_focus_sound_handle[index].focus_fd);
1205                 if (remove(filename)) {
1206                         debug_error("remove() failure, filename(%s), errno(%d)", filename, errno);
1207                 }
1208                 debug_log("Close Sucess : index(%d), filename(%s)", index, filename);
1209                 g_free(filename);
1210                 filename = NULL;
1211         }
1212
1213 #ifdef CONFIG_ENABLE_RETCB
1214         char *filename2;
1215
1216         if (is_for_watching) {
1217                 filename2 = g_strdup_printf("/tmp/FOCUS.%d.wchr", g_focus_sound_handle[index].focus_tid);
1218         } else {
1219                 filename2 = g_strdup_printf("/tmp/FOCUS.%d.%dr", g_focus_sound_handle[index].focus_tid, g_focus_sound_handle[index].handle);
1220         }
1221
1222         /* Defensive code - wait until callback timeout although callback is removed */
1223         int buf = MM_ERROR_NONE; //no need to specify cb result to server, just notice if the client got the callback properly or not
1224         int tmpfd = -1;
1225         char str_error[256];
1226
1227         tmpfd = open(filename2, O_WRONLY | O_NONBLOCK);
1228         if (tmpfd < 0) {
1229                 strerror_r(errno, str_error, sizeof(str_error));
1230                 debug_warning("could not open file(%s) (may server close it first), tid(%d) fd(%d) %s errno=%d(%s)",
1231                         filename2, g_focus_sound_handle[index].focus_tid, tmpfd, filename2, errno, str_error);
1232         } else {
1233                 ssize_t written;
1234                 debug_msg("write MM_ERROR_NONE(tid:%d) for waiting server", g_focus_sound_handle[index].focus_tid);
1235                 written = write(tmpfd, &buf, sizeof(buf));
1236                 if (written == -1) {
1237                     strerror_r(errno, str_error, sizeof(str_error));
1238                     debug_warning("write failed, %s", str_error);
1239                 }
1240                 close(tmpfd);
1241         }
1242
1243         if (remove(filename2)) {
1244                 debug_error("remove() failure, filename(%s), errno(%d)", filename2, errno);
1245         }
1246         g_free(filename2);
1247         filename2 = NULL;
1248 #endif
1249
1250 }
1251
1252 static bool _focus_add_sound_callback(int index, int fd, gushort events, focus_gLoopPollHandler_t p_gloop_poll_handler )
1253 {
1254         GSource* g_src = NULL;
1255         GSourceFuncs *g_src_funcs = NULL;               /* handler function */
1256         guint gsource_handle;
1257         GPollFD *g_poll_fd = NULL;                      /* file descriptor */
1258
1259         debug_fenter();
1260
1261         g_mutex_init(&g_focus_sound_handle[index].focus_lock);
1262
1263         /* 1. make GSource Object */
1264         g_src_funcs = (GSourceFuncs *)g_malloc(sizeof(GSourceFuncs));
1265         if (!g_src_funcs) {
1266                 debug_error("g_malloc failed on g_src_funcs");
1267                 return false;
1268         }
1269
1270         g_src_funcs->prepare = _focus_fd_prepare;
1271         g_src_funcs->check = _focus_fd_check;
1272         g_src_funcs->dispatch = _focus_fd_dispatch;
1273         g_src_funcs->finalize = NULL;
1274         g_src = g_source_new(g_src_funcs, sizeof(GSource));
1275         if (!g_src) {
1276                 debug_error("g_malloc failed on m_readfd");
1277                 return false;
1278         }
1279         g_focus_sound_handle[index].focus_src = g_src;
1280         g_focus_sound_handle[index].g_src_funcs = g_src_funcs;
1281
1282         /* 2. add file description which used in g_loop() */
1283         g_poll_fd = (GPollFD *)g_malloc(sizeof(GPollFD));
1284         if (!g_poll_fd) {
1285                 debug_error("g_malloc failed on g_poll_fd");
1286                 return false;
1287         }
1288         g_poll_fd->fd = fd;
1289         g_poll_fd->events = events;
1290         g_focus_sound_handle[index].g_poll_fd = g_poll_fd;
1291
1292         /* 3. combine g_source object and file descriptor */
1293         g_source_add_poll(g_src, g_poll_fd);
1294         gsource_handle = g_source_attach(g_src, g_main_loop_get_context(g_focus_loop));
1295         if (!gsource_handle) {
1296                 debug_error(" Failed to attach the source to context");
1297                 return false;
1298         }
1299         //g_source_unref(g_src);
1300
1301         /* 4. set callback */
1302         g_source_set_callback(g_src, p_gloop_poll_handler,(gpointer)g_poll_fd, NULL);
1303
1304         debug_log(" g_malloc:g_src_funcs(%#X),g_poll_fd(%#X)  g_source_add_poll:g_src_id(%d)  g_source_set_callback:errno(%d)",
1305                                 g_src_funcs, g_poll_fd, gsource_handle, errno);
1306
1307         debug_fleave();
1308         return true;
1309
1310
1311 }
1312
1313 static bool _focus_remove_sound_callback(int index, gushort events)
1314 {
1315         bool ret = true;
1316
1317         debug_fenter();
1318
1319         g_mutex_clear(&g_focus_sound_handle[index].focus_lock);
1320
1321         GSourceFuncs *g_src_funcs = g_focus_sound_handle[index].g_src_funcs;
1322         GPollFD *g_poll_fd = g_focus_sound_handle[index].g_poll_fd;     /* store file descriptor */
1323         if (!g_poll_fd) {
1324                 debug_error("g_poll_fd is null..");
1325                 ret = false;
1326                 goto init_handle;
1327         }
1328         g_poll_fd->fd = g_focus_sound_handle[index].focus_fd;
1329         g_poll_fd->events = events;
1330
1331         if (!g_focus_sound_handle[index].focus_src) {
1332                 debug_error("FOCUS_sound_handle[%d].focus_src is null..", index);
1333                 goto init_handle;
1334         }
1335         debug_log(" g_source_remove_poll : fd(%d), event(%x), errno(%d)", g_poll_fd->fd, g_poll_fd->events, errno);
1336         g_source_remove_poll(g_focus_sound_handle[index].focus_src, g_poll_fd);
1337
1338 init_handle:
1339
1340         if (g_focus_sound_handle[index].focus_src) {
1341                 g_source_destroy(g_focus_sound_handle[index].focus_src);
1342                 if (!g_source_is_destroyed (g_focus_sound_handle[index].focus_src)) {
1343                         debug_warning(" failed to g_source_destroy(), focus_src(0x%p)", g_focus_sound_handle[index].focus_src);
1344                 }
1345         }
1346         debug_log(" g_free : g_src_funcs(%#X), g_poll_fd(%#X)", g_src_funcs, g_poll_fd);
1347
1348         if (g_src_funcs) {
1349                 g_free(g_src_funcs);
1350                 g_src_funcs = NULL;
1351         }
1352         if (g_poll_fd) {
1353                 g_free(g_poll_fd);
1354                 g_poll_fd = NULL;
1355         }
1356
1357         g_focus_sound_handle[index].g_src_funcs = NULL;
1358         g_focus_sound_handle[index].g_poll_fd = NULL;
1359         g_focus_sound_handle[index].focus_src = NULL;
1360         g_focus_sound_handle[index].focus_callback = NULL;
1361         g_focus_sound_handle[index].watch_callback = NULL;
1362
1363         debug_fleave();
1364         return ret;
1365 }
1366
1367
1368 static void _focus_add_callback(int index, bool is_for_watching)
1369 {
1370         debug_fenter();
1371         if (!is_for_watching) {
1372                 if (!_focus_add_sound_callback(index, g_focus_sound_handle[index].focus_fd, (gushort)POLLIN | POLLPRI, _focus_callback_handler)) {
1373                         debug_error("failed to _focus_add_sound_callback()");
1374                         //return false;
1375                 }
1376         } else { // need to check if it's necessary
1377                 if (!_focus_add_sound_callback(index, g_focus_sound_handle[index].focus_fd, (gushort)POLLIN | POLLPRI, _focus_watch_callback_handler)) {
1378                         debug_error("failed to _focus_add_sound_callback()");
1379                         //return false;
1380                 }
1381         }
1382         debug_fleave();
1383 }
1384
1385 static void _focus_remove_callback(int index)
1386 {
1387         debug_fenter();
1388         if (!_focus_remove_sound_callback(index, (gushort)POLLIN | POLLPRI)) {
1389                 debug_error("failed to __focus_remove_sound_callback()");
1390                 //return false;
1391         }
1392         debug_fleave();
1393 }
1394
1395 static void _focus_init_callback(int index, bool is_for_watching)
1396 {
1397         debug_fenter();
1398         _focus_open_callback(index, is_for_watching);
1399         _focus_add_callback(index, is_for_watching);
1400         debug_fleave();
1401 }
1402
1403 static void _focus_destroy_callback(int index, bool is_for_watching)
1404 {
1405         debug_fenter();
1406         _focus_remove_callback(index);
1407         _focus_close_callback(index, is_for_watching);
1408         debug_fleave();
1409 }
1410
1411 int mm_sound_client_get_unique_id(int *id)
1412 {
1413         int ret = MM_ERROR_NONE;
1414
1415         MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_id_mutex, MM_ERROR_SOUND_INTERNAL);
1416         debug_fenter();
1417
1418         if (!id)
1419                 ret = MM_ERROR_INVALID_ARGUMENT;
1420         else
1421                 ret = mm_sound_proxy_get_unique_id(id);
1422
1423         debug_fleave();
1424         MMSOUND_LEAVE_CRITICAL_SECTION(&g_id_mutex);
1425
1426         return ret;
1427 }
1428
1429 int mm_sound_client_is_focus_cb_thread(GThread *mine, bool *result)
1430 {
1431         int ret = MM_ERROR_NONE;
1432
1433         if (!mine || !result)
1434                 ret = MM_ERROR_INVALID_ARGUMENT;
1435         else {
1436                 if (mine == g_focus_thread)
1437                         *result = true;
1438                 else
1439                         *result = false;
1440         }
1441
1442         return ret;
1443 }
1444
1445 int mm_sound_client_register_focus(int id, int pid, const char *stream_type, mm_sound_focus_changed_cb callback, bool is_for_session, void* user_data)
1446 {
1447         int ret = MM_ERROR_NONE;
1448         int instance;
1449         int index = 0;
1450         debug_fenter();
1451
1452         instance = pid;
1453
1454         for (index = 0; index < FOCUS_HANDLE_MAX - 1; index++) {
1455                 if (g_focus_sound_handle[index].is_used == false) {
1456                         g_focus_sound_handle[index].is_used = true;
1457                         break;
1458                 }
1459         }
1460
1461         g_focus_sound_handle[index].focus_tid = instance;
1462         g_focus_sound_handle[index].handle = id;
1463         g_focus_sound_handle[index].focus_callback = callback;
1464         g_focus_sound_handle[index].user_data = user_data;
1465         g_focus_sound_handle[index].is_for_session = is_for_session;
1466         g_focus_sound_handle[index].auto_reacquire = true;
1467
1468         ret = mm_sound_proxy_register_focus(id, pid, stream_type, callback, is_for_session, user_data);
1469
1470         if (ret == MM_ERROR_NONE) {
1471                 debug_msg("[Client] Success to register focus\n");
1472                 g_need_emergent_exit = TRUE;
1473                 if (!g_focus_thread) {
1474                         GMainContext* focus_context = g_main_context_new ();
1475                         g_focus_loop = g_main_loop_new (focus_context, FALSE);
1476                         g_main_context_unref(focus_context);
1477                         g_focus_thread = g_thread_new("focus-callback-thread", _focus_thread_func, NULL);
1478                         if (g_focus_thread == NULL) {
1479                                 debug_error ("could not create thread..");
1480                                 g_main_loop_unref(g_focus_loop);
1481                                 g_focus_sound_handle[index].is_used = false;
1482                                 ret = MM_ERROR_SOUND_INTERNAL;
1483                                 goto cleanup;
1484                         }
1485                 }
1486         } else {
1487                 debug_error("[Client] Error occurred : 0x%x \n",ret);
1488                 g_focus_sound_handle[index].is_used = false;
1489                 goto cleanup;
1490         }
1491
1492         _focus_init_callback(index, false);
1493
1494 cleanup:
1495
1496         debug_fleave();
1497         return ret;
1498 }
1499
1500 int mm_sound_client_unregister_focus(int id)
1501 {
1502         int ret = MM_ERROR_NONE;
1503         int instance;
1504         int index = -1;
1505         debug_fenter();
1506
1507         index = _focus_find_index_by_handle(id);
1508         if (index == -1) {
1509                 debug_error("Could not find index");
1510                 return MM_ERROR_INVALID_ARGUMENT;
1511         }
1512         instance = g_focus_sound_handle[index].focus_tid;
1513
1514         if (!g_mutex_trylock(&g_focus_sound_handle[index].focus_lock)) {
1515                 debug_warning("maybe focus_callback is being called, try one more time..");
1516                 usleep(2500000); // 2.5 sec
1517                 if (g_mutex_trylock(&g_focus_sound_handle[index].focus_lock)) {
1518                         debug_msg("finally got focus_lock");
1519                 }
1520         }
1521
1522         ret = mm_sound_proxy_unregister_focus(instance, id, g_focus_sound_handle[index].is_for_session);
1523
1524         if (ret == MM_ERROR_NONE)
1525                 debug_msg("[Client] Success to unregister focus\n");
1526         else
1527                 debug_error("[Client] Error occurred : 0x%x \n",ret);
1528
1529         g_mutex_unlock(&g_focus_sound_handle[index].focus_lock);
1530
1531         _focus_destroy_callback(index, false);
1532         g_focus_sound_handle[index].focus_fd = 0;
1533         g_focus_sound_handle[index].focus_tid = 0;
1534         g_focus_sound_handle[index].handle = 0;
1535         g_focus_sound_handle[index].is_used = false;
1536
1537         debug_fleave();
1538         return ret;
1539 }
1540
1541 int mm_sound_client_set_focus_reacquisition(int id, bool reacquisition)
1542 {
1543         int ret = MM_ERROR_NONE;
1544         int instance;
1545         int index = -1;
1546         bool result;
1547
1548         debug_fenter();
1549
1550         index = _focus_find_index_by_handle(id);
1551         if (index == -1) {
1552                 debug_error("Could not find index");
1553                 return MM_ERROR_INVALID_ARGUMENT;
1554         }
1555         instance = g_focus_sound_handle[index].focus_tid;
1556
1557         ret = mm_sound_client_is_focus_cb_thread(g_thread_self(), &result);
1558         if (ret) {
1559                 debug_error("[Client] mm_sound_client_is_focus_cb_thread failed");
1560                 goto cleanup;
1561         } else if (!result) {
1562                 ret = mm_sound_proxy_set_foucs_reacquisition(instance, id, reacquisition);
1563                 if (ret == MM_ERROR_NONE) {
1564                         debug_msg("[Client] Success to set focus reacquisition\n");
1565                 } else {
1566                         debug_error("[Client] Error occurred : 0x%x \n",ret);
1567                         goto cleanup;
1568                 }
1569         } else {
1570                 debug_warning("[Client] Inside the focus cb thread, bypassing dbus method call");
1571         }
1572
1573         g_focus_sound_handle[index].auto_reacquire = reacquisition;
1574
1575 cleanup:
1576
1577         debug_fleave();
1578         return ret;
1579 }
1580
1581 int mm_sound_client_get_focus_reacquisition(int id, bool *reacquisition)
1582 {
1583         int ret = MM_ERROR_NONE;
1584         int index = -1;
1585
1586         debug_fenter();
1587
1588         if (!reacquisition) {
1589                 debug_error("Invalid parameter");
1590                 return MM_ERROR_INVALID_ARGUMENT;
1591         }
1592
1593         index = _focus_find_index_by_handle(id);
1594         if (index == -1) {
1595                 debug_error("Could not find index");
1596                 return MM_ERROR_INVALID_ARGUMENT;
1597         }
1598
1599         *reacquisition = g_focus_sound_handle[index].auto_reacquire;
1600
1601         debug_fleave();
1602         return ret;
1603 }
1604
1605 int mm_sound_client_get_acquired_focus_stream_type(int focus_type, char **stream_type, char **additional_info)
1606 {
1607         int ret = MM_ERROR_NONE;
1608
1609         debug_fenter();
1610
1611         ret = mm_sound_proxy_get_acquired_focus_stream_type(focus_type, stream_type, additional_info);
1612         if (ret == MM_ERROR_NONE)
1613                 debug_msg("[Client] Success to get stream type of acquired focus, stream_type(%s), additional_info(%s)\n", *stream_type, *additional_info);
1614         else
1615                 debug_error("[Client] Error occurred : 0x%x \n",ret);
1616
1617         debug_fleave();
1618         return ret;
1619 }
1620
1621 int mm_sound_client_acquire_focus(int id, mm_sound_focus_type_e type, const char *option)
1622 {
1623         int ret = MM_ERROR_NONE;
1624         int instance;
1625         int index = -1;
1626
1627         debug_fenter();
1628
1629         index = _focus_find_index_by_handle(id);
1630         if (index == -1) {
1631                 debug_error("Could not find index");
1632                 return MM_ERROR_INVALID_ARGUMENT;
1633         }
1634         instance = g_focus_sound_handle[index].focus_tid;
1635
1636         ret = mm_sound_proxy_acquire_focus(instance, id, type, option, g_focus_sound_handle[index].is_for_session);
1637
1638         if (ret == MM_ERROR_NONE)
1639                 debug_msg("[Client] Success to acquire focus\n");
1640         else
1641                 debug_error("[Client] Error occurred : 0x%x \n",ret);
1642
1643         debug_fleave();
1644         return ret;
1645 }
1646
1647 int mm_sound_client_release_focus(int id, mm_sound_focus_type_e type, const char *option)
1648 {
1649         int ret = MM_ERROR_NONE;
1650         int instance;
1651         int index = -1;
1652         debug_fenter();
1653
1654         index = _focus_find_index_by_handle(id);
1655         if (index == -1) {
1656                 debug_error("Could not find index");
1657                 return MM_ERROR_INVALID_ARGUMENT;
1658         }
1659         instance = g_focus_sound_handle[index].focus_tid;
1660
1661         ret = mm_sound_proxy_release_focus(instance, id, type, option, g_focus_sound_handle[index].is_for_session);
1662
1663         if (ret == MM_ERROR_NONE)
1664                 debug_msg("[Client] Success to release focus\n");
1665         else
1666                 debug_error("[Client] Error occurred : 0x%x \n",ret);
1667
1668
1669         debug_fleave();
1670         return ret;
1671 }
1672
1673 int mm_sound_client_set_focus_watch_callback(int pid, mm_sound_focus_type_e focus_type, mm_sound_focus_changed_watch_cb callback, bool is_for_session, void* user_data, int *id)
1674 {
1675         int ret = MM_ERROR_NONE;
1676         int instance;
1677         int index = 0;
1678         debug_fenter();
1679
1680         if (!id)
1681                 return MM_ERROR_INVALID_ARGUMENT;
1682
1683         //pthread_mutex_lock(&g_thread_mutex2);
1684
1685         instance = pid;
1686
1687         ret = mm_sound_proxy_get_unique_id(id);
1688         if (ret)
1689                 return ret;
1690
1691         for (index = 0; index < FOCUS_HANDLE_MAX - 1; index++) {
1692                 if (g_focus_sound_handle[index].is_used == false) {
1693                         g_focus_sound_handle[index].is_used = true;
1694                         break;
1695                 }
1696         }
1697
1698         g_focus_sound_handle[index].focus_tid = instance;
1699         g_focus_sound_handle[index].handle = *id;
1700         g_focus_sound_handle[index].watch_callback = callback;
1701         g_focus_sound_handle[index].user_data = user_data;
1702         g_focus_sound_handle[index].is_for_session = is_for_session;
1703
1704         ret = mm_sound_proxy_set_focus_watch_callback(pid, g_focus_sound_handle[index].handle, focus_type, callback, is_for_session, user_data);
1705
1706         if (ret == MM_ERROR_NONE) {
1707                 debug_msg("[Client] Success to watch focus");
1708                 g_need_emergent_exit = TRUE;
1709                 if (!g_focus_thread) {
1710                         GMainContext* focus_context = g_main_context_new ();
1711                         g_focus_loop = g_main_loop_new (focus_context, FALSE);
1712                         g_main_context_unref(focus_context);
1713                         g_focus_thread = g_thread_new("focus-callback-thread", _focus_thread_func, NULL);
1714                         if (g_focus_thread == NULL) {
1715                                 debug_error ("could not create thread..");
1716                                 g_main_loop_unref(g_focus_loop);
1717                                 ret = MM_ERROR_SOUND_INTERNAL;
1718                                 goto cleanup;
1719                         }
1720                 }
1721         } else {
1722                 debug_error("[Client] Error occurred : 0x%x",ret);
1723                 goto cleanup;
1724         }
1725
1726         _focus_init_callback(index, true);
1727
1728 cleanup:
1729
1730         if (ret) {
1731                 g_focus_sound_handle[index].is_used = false;
1732         }
1733
1734         debug_fleave();
1735         return ret;
1736 }
1737
1738 int mm_sound_client_unset_focus_watch_callback(int id)
1739 {
1740         int ret = MM_ERROR_NONE;
1741         int index = -1;
1742         debug_fenter();
1743
1744         index = _focus_find_index_by_handle(id);
1745         if (index == -1) {
1746                 debug_error("Could not find index");
1747                 return MM_ERROR_INVALID_ARGUMENT;
1748         }
1749
1750         g_mutex_lock(&g_focus_sound_handle[index].focus_lock);
1751
1752         ret = mm_sound_proxy_unset_focus_watch_callback(g_focus_sound_handle[index].focus_tid, g_focus_sound_handle[index].handle, g_focus_sound_handle[index].is_for_session);
1753
1754         if (ret == MM_ERROR_NONE)
1755                 debug_msg("[Client] Success to unwatch focus\n");
1756         else
1757                 debug_error("[Client] Error occurred : 0x%x \n",ret);
1758
1759
1760         g_mutex_unlock(&g_focus_sound_handle[index].focus_lock);
1761
1762         _focus_destroy_callback(index, true);
1763         g_focus_sound_handle[index].focus_fd = 0;
1764         g_focus_sound_handle[index].focus_tid = 0;
1765         g_focus_sound_handle[index].handle = 0;
1766         g_focus_sound_handle[index].is_used = false;
1767
1768         debug_fleave();
1769         return ret;
1770 }
1771 #endif
1772
1773
1774 int mm_sound_client_add_test_callback(mm_sound_test_cb func, void* user_data, unsigned int *subs_id)
1775 {
1776         int ret = MM_ERROR_NONE;
1777
1778         debug_fenter();
1779
1780         ret = mm_sound_proxy_add_test_callback(func, user_data, g_free, subs_id);
1781
1782         debug_fleave();
1783         return ret;
1784 }
1785
1786 int mm_sound_client_remove_test_callback(unsigned int subs_id)
1787 {
1788         int ret = MM_ERROR_NONE;
1789         debug_fenter();
1790
1791         ret = mm_sound_proxy_remove_test_callback(subs_id);
1792
1793         debug_fleave();
1794         return ret;
1795 }
1796
1797
1798 int mm_sound_client_test(int a, int b, int* getv)
1799 {
1800         int ret = MM_ERROR_NONE;
1801
1802         debug_fenter();
1803
1804         ret = mm_sound_proxy_test(a, b, getv);
1805         debug_log("%d * %d -> result : %d", a, b, *getv);
1806
1807         debug_fleave();
1808
1809         return ret;
1810 }