Updated version and changelog.
[profile/ivi/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 <string.h>
24 #include <sys/shm.h>
25 #include <sys/mman.h>
26 #include <sys/stat.h>
27 #include <fcntl.h>
28 #include <sys/msg.h>
29 #include <assert.h>
30 #include <errno.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_msg.h"
40 #include "include/mm_sound_client.h"
41
42 #include <mm_session.h>
43 #include <mm_session_private.h>
44
45 #define __DIRECT_CALLBACK__
46 //#define __GIDLE_CALLBACK__
47
48 #include <glib.h>
49 #if defined(__GSOURCE_CALLBACK__)
50 #include <sys/poll.h>
51 #endif
52
53 #define MEMTYPE_SUPPORT_MAX (1024 * 1024) /* 1MB */
54 #define MEMTYPE_TRANS_PER_MAX (128 * 1024) /* 128K */
55
56
57 int g_msg_scsnd;        /* global msg queue id sound client snd */
58 int g_msg_scrcv;        /* global msg queue id sound client rcv */
59 int g_msg_sccb;         /* global msg queue id sound client callback */
60
61 /* callback */
62 struct __callback_param
63 {
64         mm_sound_stop_callback_func     callback;
65     void                    *data;
66 };
67
68 pthread_t g_thread;
69 static int g_exit_thread = 0;
70 int g_thread_id = -1;
71 int g_mutex_initted = -1;
72 pthread_mutex_t g_thread_mutex;
73
74 static void* callbackfunc(void *param);
75
76 /* manage IPC (msg contorl) */
77 static int __MMIpcCBSndMsg(mm_ipc_msg_t *msg);
78 static int __MMIpcRecvMsg(int msgtype, mm_ipc_msg_t *msg);
79 static int __MMIpcSndMsg(mm_ipc_msg_t *msg);
80 static int __MMIpcCBRecvMsg(int msgtype, mm_ipc_msg_t *msg);
81 static int __MMSoundGetMsg(void);
82
83 int MMSoundClientInit(void)
84 {
85         int ret = MM_ERROR_NONE;
86         debug_fenter();
87
88         debug_fleave();
89         return ret;
90 }
91
92 int MMSoundClientCallbackFini(void)
93 {
94         mm_ipc_msg_t msgsnd={0,};
95         int ret = MM_ERROR_NONE;
96         
97         debug_fenter();
98
99         /* When the the callback thread is not created, do not wait destory thread */
100         /* g_thread_id is initialized : -1 */
101         /* g_thread_id is set to 0, when the callback thread is created */
102         if (g_thread_id != -1)
103         {
104                 msgsnd.sound_msg.msgtype = MM_SOUND_MSG_INF_DESTROY_CB;
105                 msgsnd.sound_msg.msgid = getpid();
106                 ret = __MMIpcCBSndMsg(&msgsnd);
107                 if (ret != MM_ERROR_NONE)
108                 {
109                         debug_critical("[Client] Fail to send message\n");
110                 }
111                 /* wait for leave callback thread */
112                 while (g_exit_thread == 0)
113                         usleep(30000);
114                 g_exit_thread = 0;
115         }
116
117         if (g_mutex_initted != -1)
118         {
119                 pthread_mutex_destroy(&g_thread_mutex);
120                 g_mutex_initted = -1;
121         }
122         debug_fleave();
123         return MM_ERROR_NONE;
124 }
125
126 #if defined(__GSOURCE_CALLBACK__)
127 gboolean sndcb_fd_check(GSource * source)
128 {
129         GSList *fd_list;
130         fd_list = source->poll_fds;
131         GPollFD* temp;
132
133         do
134         {
135                 temp = (GPollFD*)fd_list->data;
136                 if (temp->revents & (POLLIN|POLLPRI))
137                         return TRUE;
138                 fd_list = fd_list->next;
139         }while(fd_list);
140
141         return FALSE; /* there is no change in any fd state */
142 }
143
144 gboolean sndcb_fd_prepare(GSource *source, gint *timeout)
145 {
146         return FALSE;
147 }
148
149 gboolean sndcb_fd_dispatch(GSource *source,     GSourceFunc callback, gpointer user_data)
150 {
151         callback(user_data);
152         return TRUE;
153 }
154 #endif
155 gboolean RunCallback(gpointer *data)
156 {
157         mm_ipc_msg_t* msg = NULL;
158
159         debug_msg("[Client] execute mm_sound stop callback function\n");
160
161         msg = (mm_ipc_msg_t*)data;
162         ((mm_sound_stop_callback_func)msg->sound_msg.callback)(msg->sound_msg.cbdata);
163
164         return FALSE;
165 }
166
167 static void* callbackfunc(void *param)
168 {
169         int ret = MM_ERROR_SOUND_INTERNAL;
170         mm_ipc_msg_t *msgrcv = NULL;
171         int run = 1;
172         int instance;
173
174         debug_fenter();
175
176         instance = getpid();
177         debug_msg("[Client] callback thread for [%d] is created\n", instance);
178
179         msgrcv = (mm_ipc_msg_t*)malloc(sizeof(mm_ipc_msg_t));
180         if(NULL == msgrcv)
181         {
182                 debug_critical("[Client] Failed to memory allocation\n");
183                 return NULL;
184         }
185
186         while(run)
187         {
188 #if defined(__GSOURCE_CALLBACK__)
189                 int eventFd = 0;
190                 gchar* eventFile = NULL;
191                 GSource* cmd_fd_gsrc = NULL;
192                 GSourceFuncs *src_funcs = NULL;         // handler function
193                 guint gsource_handle;
194                 GPollFD *g_fd_cmd = NULL;                       // file descriptor
195 #endif
196
197                 debug_warning("[Client] Waiting message\n");
198                 ret = __MMIpcCBRecvMsg(instance, msgrcv);
199                 if (ret != MM_ERROR_NONE)
200                 {
201                         debug_error("[Client] Fail to receive msg in callback\n");
202                         continue;
203                 }
204
205                 debug_msg("[Client] Receive msgtype : [%d]\n", msgrcv->sound_msg.msgtype);
206
207                 switch (msgrcv->sound_msg.msgtype)
208                 {
209                 case MM_SOUND_MSG_INF_STOP_CB:
210                         debug_msg("[Client] callback : %p\n", msgrcv->sound_msg.callback);
211                         debug_msg("[Client] data : %p\n", msgrcv->sound_msg.cbdata);
212
213                         if (msgrcv->sound_msg.callback)
214                         {
215 #if defined(__DIRECT_CALLBACK__)
216                                 ((mm_sound_stop_callback_func)msgrcv->sound_msg.callback)(msgrcv->sound_msg.cbdata);
217 #elif defined(__GIDLE_CALLBACK__)
218                                 guint eventid = 0;
219                                 eventid = g_idle_add((GSourceFunc)RunCallback, (gpointer)msgrcv);
220                                 debug_msg("[Client] Event Source ID : %d\n", eventid);
221
222 #elif defined(__GSOURCE_CALLBACK__)
223                                 char eventBuf[3]="OK";
224                                 ////////////////////////
225                                 // 0. Make event source
226                                 eventFile = g_strdup_printf("/tmp/%d_0x%08x_0x%08x", instance, (unsigned int)msgrcv->sound_msg.callback, (unsigned int)msgrcv->sound_msg.cbdata);
227                                 eventFd = open(eventFile, O_RDWR|O_CREAT);
228                                 if(eventFd == -1)
229                                 {
230                                         debug_critical("Event File creation failed\n");
231                                         break;
232                                 }
233
234                                 // 1. make GSource Object
235                                 src_funcs = (GSourceFuncs *)g_malloc(sizeof(GSourceFuncs));
236                                 if(!src_funcs){
237                                         debug_error("MMSoundCallback :  g_malloc failed on g_src_funcs");
238                                         break;
239                                 }
240                                 src_funcs->prepare = sndcb_fd_prepare;
241                                 src_funcs->check = sndcb_fd_check;
242                                 src_funcs->dispatch = sndcb_fd_dispatch;
243                                 src_funcs->finalize = NULL;
244                                 cmd_fd_gsrc = g_source_new(src_funcs,sizeof(GSource));
245                                 if(!cmd_fd_gsrc){
246                                         debug_error("MMSoundCallback : g_malloc failed on m_readfd");
247                                         break;
248                                 }
249
250                                 // 2. add file description which used in g_loop()
251                                 g_fd_cmd = (GPollFD*)g_malloc(sizeof(GPollFD));
252                                 g_fd_cmd->fd = eventFd;
253                                 g_fd_cmd->events = POLLIN|POLLPRI;
254
255                                 // 3. combine g_source object and file descriptor
256                                 g_source_add_poll(cmd_fd_gsrc,g_fd_cmd);
257                                 gsource_handle = g_source_attach(cmd_fd_gsrc, NULL);
258                                 if(!gsource_handle){
259                                         debug_error("MMSoundCallback : Error: Failed to attach the source to context");
260                                         break;
261                                 }
262
263                                 // 4. set callback
264                                 g_source_set_callback(cmd_fd_gsrc,RunCallback,(gpointer)g_fd_cmd,NULL);
265                                 debug_msg("MMSoundCallback : g_source_set_callback() done\n")
266
267                                 // 5. Set Event
268                                 write(eventFd, eventBuf, sizeof(eventBuf));
269                                 sleep(1);
270                                 // 6. Cleanup
271                                 close(eventFd);
272                                 unlink(eventFile);
273                                 g_source_remove_poll(cmd_fd_gsrc, g_fd_cmd);
274                                 g_source_remove(gsource_handle);
275                                 if(g_fd_cmd)
276                                         free(g_fd_cmd);
277                                 if(src_funcs)
278                                         free(src_funcs);
279                                 if(eventFile)
280                                         g_free(eventFile);
281                                 ////////////////////////
282 #endif
283                         }
284                         break;
285                 case MM_SOUND_MSG_INF_DESTROY_CB:
286                         run = 0;
287                         break;
288
289                 case MM_SOUND_MSG_INF_ACTIVE_DEVICE_CB:
290                         debug_msg("[Client] device_in : %p\n", msgrcv->sound_msg.device_in);
291                         debug_msg("[Client] device_out : %p\n", msgrcv->sound_msg.device_out);
292                         debug_msg("[Client] callback : %p\n", msgrcv->sound_msg.callback);
293                         debug_msg("[Client] data : %p\n", msgrcv->sound_msg.cbdata);
294
295                         if (msgrcv->sound_msg.callback)
296                         {
297                                 ((mm_sound_active_device_changed_cb)msgrcv->sound_msg.callback)(msgrcv->sound_msg.device_in, msgrcv->sound_msg.device_out, msgrcv->sound_msg.cbdata);
298                         }
299                         break;
300                 case MM_SOUND_MSG_INF_AVAILABLE_ROUTE_CB:
301                         debug_msg("[Client] callback : %p\n", msgrcv->sound_msg.callback);
302                         debug_msg("[Client] data : %p\n", msgrcv->sound_msg.cbdata);
303
304                         if (msgrcv->sound_msg.callback)
305                         {
306                                 int route_index;
307                                 mm_sound_route route;
308
309                                 for (route_index = 0; route_index < sizeof(msgrcv->sound_msg.route_list) / sizeof(int); route_index++) {
310                                         route = msgrcv->sound_msg.route_list[route_index];
311                                         if (route == 0)
312                                                 break;
313                                         if (msgrcv->sound_msg.is_available) {
314                                                 debug_msg("[Client] available route : %d\n", route);
315                                         } else {
316                                                 debug_msg("[Client] unavailable route : %d\n", route);
317                                         }
318                                         ((mm_sound_available_route_changed_cb)msgrcv->sound_msg.callback)(route, msgrcv->sound_msg.is_available, msgrcv->sound_msg.cbdata);
319                                 }
320                         }
321                         break;
322                 default:
323                         /* Unexpected msg */
324                         debug_msg("Receive wrong msg in callback func\n");
325                         break;
326                 }
327         }
328         if(msgrcv)
329                 free(msgrcv);
330
331         g_exit_thread = 1;
332         debug_msg("[Client] callback [%d] is leaved\n", instance);
333         debug_fleave();
334         return NULL;
335 }
336
337 static int __mm_sound_client_get_msg_queue(void)
338 {
339         int ret = MM_ERROR_NONE;
340
341         if (g_mutex_initted == -1)
342         {
343                 pthread_mutex_init(&g_thread_mutex, NULL);
344                 debug_msg("[Client] mutex initialized. \n");
345                 g_mutex_initted = 1;
346
347                 /* Get msg queue id */
348                 ret = __MMSoundGetMsg();
349                 if(ret != MM_ERROR_NONE)
350                 {
351                         debug_critical("[Client] Fail to get message queue id\n");
352                 }
353         }
354
355         return ret;
356 }
357
358 int MMSoundClientPlayTone(int number, int volume_config, double volume, int time, int *handle)
359 {
360         mm_ipc_msg_t msgrcv = {0,};
361         mm_ipc_msg_t msgsnd = {0,};
362
363         int ret = MM_ERROR_NONE;
364         int instance = -1;      /* instance is unique to communicate with server : client message queue filter type */
365
366         debug_fenter();
367
368         if (__mm_sound_client_get_msg_queue() != MM_ERROR_NONE)
369                 return ret;
370
371         /* read mm-session type */
372         int sessionType = MM_SESSION_TYPE_SHARE;
373         if(MM_ERROR_NONE != _mm_session_util_read_type(-1, &sessionType))
374         {
375                 debug_warning("[Client] Read MMSession Type failed. use default \"share\" type\n");
376                 sessionType = MM_SESSION_TYPE_SHARE;
377
378                 if(MM_ERROR_NONE != mm_session_init(sessionType))
379                 {
380                         debug_critical("[Client] MMSessionInit() failed\n");
381                         return MM_ERROR_POLICY_INTERNAL;
382                 }
383         }
384
385         instance = getpid();
386         debug_msg("[Client] pid for client ::: [%d]\n", instance);
387
388         pthread_mutex_lock(&g_thread_mutex);
389
390         /* Send msg */
391         debug_msg("[Client] Input number : %d\n", number);
392         /* Send req memory */
393         msgsnd.sound_msg.msgtype = MM_SOUND_MSG_REQ_DTMF;
394         msgsnd.sound_msg.msgid = instance;
395         msgsnd.sound_msg.session_type = sessionType;//asm_session_type;
396         msgsnd.sound_msg.volume = volume;//This does not effect anymore
397         msgsnd.sound_msg.volume_config = volume_config;
398         msgsnd.sound_msg.tone = number;
399         msgsnd.sound_msg.handle = -1;
400         msgsnd.sound_msg.repeat = time;
401
402         ret = __MMIpcSndMsg(&msgsnd);
403         if (ret != MM_ERROR_NONE)
404         {
405                 debug_error("[Client] Fail to send msg\n");
406                 goto cleanup;
407         }
408
409         /* Receive */
410         ret = __MMIpcRecvMsg(instance, &msgrcv);
411         if (ret != MM_ERROR_NONE)
412         {
413                 debug_error("[Client] Fail to recieve msg\n");
414                 goto cleanup;
415         }
416
417         switch (msgrcv.sound_msg.msgtype)
418         {
419         case MM_SOUND_MSG_RES_DTMF:
420                 *handle = msgrcv.sound_msg.handle;
421                 if(*handle == -1)
422                         debug_error("[Client] The handle is not get\n");
423
424                 debug_msg("[Client] Success to play sound sound handle : [%d]\n", *handle);
425                 break;
426         case MM_SOUND_MSG_RES_ERROR:
427                 debug_error("[Client] Error occurred \n");
428                 ret = msgrcv.sound_msg.code;
429                 goto cleanup;
430                 break;
431         default:
432                 debug_critical("[Client] Unexpected state with communication \n");
433                 ret = msgrcv.sound_msg.code;
434                 goto cleanup;
435                 break;
436         }
437 cleanup:
438         pthread_mutex_unlock(&g_thread_mutex);
439
440         debug_fleave();
441         return ret;
442 }
443
444
445 int MMSoundClientPlaySound(MMSoundPlayParam *param, int tone, int keytone, int *handle)
446 {
447         mm_ipc_msg_t msgrcv = {0,};
448         mm_ipc_msg_t msgsnd = {0,};
449         unsigned char* sharedmem = NULL;
450
451         int ret = MM_ERROR_NONE;
452         int instance = -1;      /* instance is unique to communicate with server : client message queue filter type */
453
454         char shm_name[512];
455         void *mmap_buf = NULL;
456         static int keybase = 0;
457         int shm_fd = -1;
458
459         debug_fenter();
460         memset(shm_name, 0, sizeof(shm_name));
461
462         ret = __mm_sound_client_get_msg_queue();
463         if (ret != MM_ERROR_NONE)
464                 return ret;
465
466         /* read mm-session type */
467         int sessionType = MM_SESSION_TYPE_SHARE;
468         if(MM_ERROR_NONE != _mm_session_util_read_type(-1, &sessionType))
469         {
470                 debug_warning("[Client] Read MMSession Type failed. use default \"share\" type\n");
471                 sessionType = MM_SESSION_TYPE_SHARE;
472
473                 if(MM_ERROR_NONE != mm_session_init(sessionType))
474                 {
475                         debug_critical("[Client] MMSessionInit() failed\n");
476                         return MM_ERROR_POLICY_INTERNAL;
477                 }
478         }
479
480
481         instance = getpid();
482         debug_msg("[Client] pid for client ::: [%d]\n", instance);
483
484         /* callback */
485         /* callback thread is created just once & when the callback is exist */
486         if (param->callback)
487         {
488                 if (g_thread_id == -1)
489                 {
490                         g_thread_id = pthread_create(&g_thread, NULL, callbackfunc, NULL);
491                         if (g_thread_id == -1)
492                         {
493                                 debug_critical("[Client] Fail to create thread %s\n", strerror(errno));
494                                 return MM_ERROR_SOUND_INTERNAL;
495                         }
496                 }
497         }
498
499         pthread_mutex_lock(&g_thread_mutex);
500
501         /* Send msg */
502         if ((param->mem_ptr && param->mem_size))
503         {
504                 debug_msg("The memptr : [%p]\n", param->mem_ptr);
505                 debug_msg("The memptr : [%d]\n", param->mem_size);
506                 /* Limitted memory size */
507                 if (param->mem_ptr && param->mem_size > MEMTYPE_SUPPORT_MAX)
508                 {
509                         debug_msg("[Client] Memory size is too big. We support size of media to 1MB\n");
510                         goto cleanup;
511                 }
512
513                 debug_msg("[Client] memory size : %d\n", param->mem_size);
514                 snprintf(shm_name, sizeof(shm_name)-1, "%d_%d", instance, keybase);
515                 debug_msg("[Client] The shm_path : [%s]\n", shm_name);
516                 keybase++;
517
518                 shm_fd = shm_open(shm_name, O_RDWR |O_CREAT, 0666);
519                 if(shm_fd < 0)
520                 {
521                         perror("[Client] Fail create shm_open\n");
522                         debug_error("[Client] Fail to create shm_open\n");
523                         goto cleanup;
524                 }
525
526                 if(ftruncate(shm_fd, param->mem_size) == -1)
527                 {
528                         debug_error("[Client] Fail to ftruncate\n");
529                         goto cleanup;
530                 }
531
532                 mmap_buf = mmap (0, MEMTYPE_SUPPORT_MAX, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
533                 if (mmap_buf == MAP_FAILED)
534                 {
535                         debug_error("[Client] MMAP failed \n");
536                         goto cleanup;
537                 }
538                 
539                 sharedmem = mmap_buf;
540
541                 if(ret != MM_ERROR_NONE)
542                 {
543                         debug_error("[Client] Not allocated shared memory");
544                         goto cleanup;
545                 }
546                 debug_msg("[Client] Sheared mem ptr : %p\n", sharedmem);
547                 debug_msg("[Client] Sheared key : [%d]\n", 1);
548                 /* Send req memory */
549                 msgsnd.sound_msg.msgtype = MM_SOUND_MSG_REQ_MEMORY;
550                 msgsnd.sound_msg.msgid = instance;
551                 msgsnd.sound_msg.callback = (void*)(param->callback);
552                 msgsnd.sound_msg.cbdata = (void*)(param->data);
553                 msgsnd.sound_msg.memptr = (int)sharedmem;
554                 msgsnd.sound_msg.sharedkey = 1;         /* In case of shared memory file name */
555                 msgsnd.sound_msg.session_type = sessionType;//asm_session_type;
556                 msgsnd.sound_msg.priority = param->priority;
557
558                 
559                 strncpy(msgsnd.sound_msg.filename, shm_name, 512);
560                 debug_msg("[Client] shm_name : %s\n", msgsnd.sound_msg.filename);
561                 
562                 msgsnd.sound_msg.memsize = param->mem_size;
563                 msgsnd.sound_msg.volume = param->volume;
564                 msgsnd.sound_msg.tone = tone;
565                 msgsnd.sound_msg.handle = -1;
566                 msgsnd.sound_msg.repeat = param->loop;
567                 msgsnd.sound_msg.volume_config = param->volume_config;
568                 msgsnd.sound_msg.keytone = keytone;
569                 msgsnd.sound_msg.handle_route = param->handle_route;
570
571                 /* Send req memory */
572                 debug_msg("[Client] Shared mem ptr %p, %p, size %d\n", sharedmem, param->mem_ptr, param->mem_size);
573                 memcpy(sharedmem, param->mem_ptr, param->mem_size);
574                 
575
576                 if (close(shm_fd) == -1)
577                 {
578                         debug_error("[Client] Fail to close file\n");
579                         ret = MM_ERROR_SOUND_INTERNAL;
580                         goto cleanup;
581                 }
582                 
583                 ret = __MMIpcSndMsg(&msgsnd);
584                 if (ret != MM_ERROR_NONE)
585                 {
586                         debug_error("[Client] Fail to send msg\n");
587                         goto cleanup;
588                 }
589         }
590         else
591         {
592                 /* File type set for send msg */
593                 msgsnd.sound_msg.msgtype = MM_SOUND_MSG_REQ_FILE;
594                 msgsnd.sound_msg.msgid = instance;
595                 msgsnd.sound_msg.callback = (void*)(param->callback);
596                 msgsnd.sound_msg.cbdata = (void*)(param->data);
597                 msgsnd.sound_msg.volume = param->volume;
598                 msgsnd.sound_msg.tone = tone;
599                 msgsnd.sound_msg.handle = -1;
600                 msgsnd.sound_msg.repeat = param->loop;
601                 msgsnd.sound_msg.volume_config = param->volume_config;
602                 msgsnd.sound_msg.session_type = sessionType;//asm_session_type;
603                 msgsnd.sound_msg.priority = param->priority;
604                 msgsnd.sound_msg.handle_route = param->handle_route;
605
606                 if((strlen(param->filename)) < FILE_PATH)
607                 {
608                         strncpy(msgsnd.sound_msg.filename, param->filename, sizeof(msgsnd.sound_msg.filename)-1);
609                 }
610                 else
611                 {
612                         debug_error("File name is over count\n");
613                         ret = MM_ERROR_SOUND_INVALID_PATH;
614                 }
615                         
616                 msgsnd.sound_msg.keytone = keytone;
617
618                 debug_msg("[Client] callback : %p\n", msgsnd.sound_msg.callback);
619                 debug_msg("[Client] cbdata : %p\n", msgsnd.sound_msg.cbdata);
620
621                 ret = __MMIpcSndMsg(&msgsnd);
622                 if (ret != MM_ERROR_NONE)
623                 {
624                         debug_error("[Client] Fail to send msg\n");
625                         goto cleanup;
626                 }
627         }
628
629         
630         /* Receive */
631         ret = __MMIpcRecvMsg(instance, &msgrcv);
632         if (ret != MM_ERROR_NONE)
633         {
634                 debug_error("[Client] Fail to recieve msg\n");
635                 goto cleanup;
636         }
637
638         switch (msgrcv.sound_msg.msgtype)
639         {
640         case MM_SOUND_MSG_RES_FILE:
641                 *handle = msgrcv.sound_msg.handle;
642                 debug_msg("[Client] Success to play sound sound handle : [%d]\n", *handle);
643                 break;
644         case MM_SOUND_MSG_RES_MEMORY:
645                 *handle = msgrcv.sound_msg.handle;
646                 if(*handle == -1)
647                         debug_error("[Client] The handle is not get\n");
648
649                 shm_unlink(shm_name);
650                 if (ret != MM_ERROR_NONE)
651                 {
652                         debug_critical("[Client] Fail to remove shared memory, must be checked\n");
653                         goto cleanup;
654                 }
655                 debug_msg("[Client] Success to play sound sound handle : [%d]\n", *handle);
656                 break;
657         case MM_SOUND_MSG_RES_ERROR:
658                 debug_error("[Client] Error occurred \n");
659                 ret = msgrcv.sound_msg.code;
660                 goto cleanup;
661                 break;
662         default:
663                 debug_critical("[Client] Unexpected state with communication \n");
664                 ret = msgrcv.sound_msg.code;
665                 goto cleanup;
666                 break;
667         }
668 cleanup:
669         pthread_mutex_unlock(&g_thread_mutex);
670
671         debug_fleave();
672         return ret;
673 }
674
675 int MMSoundClientStopSound(int handle)
676 {
677         mm_ipc_msg_t msgrcv = {0,};
678         mm_ipc_msg_t msgsnd = {0,};
679         int ret = MM_ERROR_NONE;
680         int instance;
681
682         debug_fenter();
683         debug_msg("[Client] The stop audio handle ::: [%d]\n", handle);
684
685         instance = getpid();
686
687         if (handle < 0)
688         {
689                 ret = MM_ERROR_INVALID_ARGUMENT;
690                 return ret;
691         }
692         
693         if (__mm_sound_client_get_msg_queue() != MM_ERROR_NONE)
694                 return ret;
695
696         pthread_mutex_lock(&g_thread_mutex);
697         
698         /* Send req STOP */
699         msgsnd.sound_msg.msgtype = MM_SOUND_MSG_REQ_STOP;
700         msgsnd.sound_msg.msgid = instance;
701         msgsnd.sound_msg.handle = handle;               /* handle means audio handle slot id */
702         
703         ret = __MMIpcSndMsg(&msgsnd);
704         if (ret != MM_ERROR_NONE)
705         {
706                 debug_error("Fail to send msg\n");
707                 goto cleanup;
708         }
709
710         /* Recieve */
711         ret = __MMIpcRecvMsg(instance, &msgrcv);
712         if (ret != MM_ERROR_NONE)
713         {
714                 debug_error("[Client] Fail to recieve msg\n");
715                 goto cleanup;
716         }
717         switch (msgrcv.sound_msg.msgtype)
718         {
719         case MM_SOUND_MSG_RES_STOP:
720                 debug_msg("[Client] Success to stop sound\n");
721                 break;
722         case MM_SOUND_MSG_RES_ERROR:
723                 debug_error("[Client] Error occurred \n");
724                 ret = msgrcv.sound_msg.code;
725                 goto cleanup;
726                 break;
727         default:
728                 debug_critical("[Client] Unexpected state with communication \n");
729                 ret = msgrcv.sound_msg.code;
730                 goto cleanup;
731                 break;
732         }
733
734 cleanup:
735         pthread_mutex_unlock(&g_thread_mutex);
736
737
738         debug_fleave();
739         return ret;
740 }
741
742 int _mm_sound_client_is_route_available(mm_sound_route route, bool *is_available)
743 {
744         mm_ipc_msg_t msgrcv = {0,};
745         mm_ipc_msg_t msgsnd = {0,};
746         int ret = MM_ERROR_NONE;
747         int instance;
748
749         debug_fenter();
750
751         *is_available = FALSE;
752
753         if (__mm_sound_client_get_msg_queue() != MM_ERROR_NONE)
754                 return ret;
755
756         pthread_mutex_lock(&g_thread_mutex);
757
758         instance = getpid();
759         /* Send REQ_IS_ROUTE_AVAILABLE */
760         msgsnd.sound_msg.msgtype = MM_SOUND_MSG_REQ_IS_ROUTE_AVAILABLE;
761         msgsnd.sound_msg.msgid = instance;
762         msgsnd.sound_msg.route = route;
763
764         if (__MMIpcSndMsg(&msgsnd) != MM_ERROR_NONE)
765                 goto cleanup;
766
767         /* Recieve */
768         if (__MMIpcRecvMsg(instance, &msgrcv) != MM_ERROR_NONE)
769                 goto cleanup;
770
771         switch (msgrcv.sound_msg.msgtype)
772         {
773         case MM_SOUND_MSG_RES_IS_ROUTE_AVAILABLE:
774                 *is_available = msgrcv.sound_msg.is_available;
775                 debug_msg("[Client] Success to check given route is available %d\n", *is_available);
776                 break;
777         case MM_SOUND_MSG_RES_ERROR:
778                 debug_error("[Client] Error occurred \n");
779                 ret = msgrcv.sound_msg.code;
780                 goto cleanup;
781                 break;
782         default:
783                 debug_critical("[Client] Unexpected state with communication \n");
784                 ret = msgrcv.sound_msg.code;
785                 goto cleanup;
786                 break;
787         }
788
789 cleanup:
790         pthread_mutex_unlock(&g_thread_mutex);
791
792         debug_fleave();
793         return ret;
794 }
795
796 static int _handle_foreach_callback(mm_ipc_msg_t *msg)
797 {
798         int route_index;
799         mm_sound_route route;
800
801         debug_fenter();
802
803         if (msg->sound_msg.callback == NULL) {
804                 debug_error ("[Client] Foreach callback is [%p], cbdata = %p => exit",
805                                 msg->sound_msg.callback, msg->sound_msg.cbdata);
806                 return MM_ERROR_SOUND_INTERNAL;
807         }
808
809         for (route_index = 0; route_index < MM_SOUND_ROUTE_NUM; route_index++) {
810                 route = msg->sound_msg.route_list[route_index];
811                 if (route == 0)
812                         break;
813                 debug_msg("[Client] available route : %d\n", route);
814                 if (((mm_sound_available_route_cb)msg->sound_msg.callback)(route, msg->sound_msg.cbdata) == false) {
815                         debug_msg ("[Client] user doesn't want anymore. quit loop!!\n");
816                         break;
817                 }
818         }
819
820         debug_fleave();
821
822         return MM_ERROR_NONE;
823 }
824
825 int _mm_sound_client_foreach_available_route_cb(mm_sound_available_route_cb available_route_cb, void *user_data)
826 {
827         mm_ipc_msg_t msgrcv = {0,};
828         mm_ipc_msg_t msgsnd = {0,};
829         int ret = MM_ERROR_NONE;
830         int instance;
831
832         debug_fenter();
833
834         if (__mm_sound_client_get_msg_queue() != MM_ERROR_NONE)
835                 return ret;
836
837         pthread_mutex_lock(&g_thread_mutex);
838
839         instance = getpid();
840         /* Send REQ_FOREACH_AVAILABLE_ROUTE_CB */
841         msgsnd.sound_msg.msgtype = MM_SOUND_MSG_REQ_FOREACH_AVAILABLE_ROUTE_CB;
842         msgsnd.sound_msg.msgid = instance;
843         msgsnd.sound_msg.callback = (void *)available_route_cb;
844         msgsnd.sound_msg.cbdata = (void *)user_data;
845
846         if (__MMIpcSndMsg(&msgsnd) != MM_ERROR_NONE)
847                 goto cleanup;
848
849         /* Recieve */
850         if (__MMIpcRecvMsg(instance, &msgrcv) != MM_ERROR_NONE)
851                 goto cleanup;
852
853         switch (msgrcv.sound_msg.msgtype)
854         {
855         case MM_SOUND_MSG_RES_FOREACH_AVAILABLE_ROUTE_CB:
856                 debug_msg("[Client] Success to set foreach available route callback\n");
857                 msgrcv.sound_msg.callback = (void *)available_route_cb;
858                 msgrcv.sound_msg.cbdata = (void *)user_data;
859                 ret = _handle_foreach_callback (&msgrcv);
860                 break;
861         case MM_SOUND_MSG_RES_ERROR:
862                 debug_error("[Client] Error occurred \n");
863                 ret = msgrcv.sound_msg.code;
864                 goto cleanup;
865                 break;
866         default:
867                 debug_critical("[Client] Unexpected state with communication \n");
868                 ret = msgrcv.sound_msg.code;
869                 goto cleanup;
870                 break;
871         }
872
873 cleanup:
874         pthread_mutex_unlock(&g_thread_mutex);
875
876         debug_fleave();
877         return ret;
878 }
879
880 int _mm_sound_client_set_active_route(mm_sound_route route)
881 {
882         mm_ipc_msg_t msgrcv = {0,};
883         mm_ipc_msg_t msgsnd = {0,};
884         int ret = MM_ERROR_NONE;
885         int instance;
886
887         debug_fenter();
888
889         if (__mm_sound_client_get_msg_queue() != MM_ERROR_NONE)
890                 return ret;
891
892         pthread_mutex_lock(&g_thread_mutex);
893
894         instance = getpid();
895         /* Send REQ_SET_ACTIVE_ROUTE */
896         msgsnd.sound_msg.msgtype = MM_SOUND_MSG_REQ_SET_ACTIVE_ROUTE;
897         msgsnd.sound_msg.msgid = instance;
898         msgsnd.sound_msg.route = route;
899
900         if (__MMIpcSndMsg(&msgsnd) != MM_ERROR_NONE)
901                 goto cleanup;
902
903         /* Recieve */
904         if (__MMIpcRecvMsg(instance, &msgrcv) != MM_ERROR_NONE)
905                 goto cleanup;
906
907         switch (msgrcv.sound_msg.msgtype)
908         {
909         case MM_SOUND_MSG_RES_SET_ACTIVE_ROUTE:
910                 debug_msg("[Client] Success to add active device callback\n");
911                 break;
912         case MM_SOUND_MSG_RES_ERROR:
913                 debug_error("[Client] Error occurred \n");
914                 ret = msgrcv.sound_msg.code;
915                 goto cleanup;
916                 break;
917         default:
918                 debug_critical("[Client] Unexpected state with communication \n");
919                 ret = msgrcv.sound_msg.code;
920                 goto cleanup;
921                 break;
922         }
923
924 cleanup:
925         pthread_mutex_unlock(&g_thread_mutex);
926
927         debug_fleave();
928         return ret;
929 }
930
931 int _mm_sound_client_get_active_device(mm_sound_device_in *device_in, mm_sound_device_out *device_out)
932 {
933         mm_ipc_msg_t msgrcv = {0,};
934         mm_ipc_msg_t msgsnd = {0,};
935         int ret = MM_ERROR_NONE;
936         int instance;
937
938         debug_fenter();
939
940         if (__mm_sound_client_get_msg_queue() != MM_ERROR_NONE)
941                 return ret;
942
943         pthread_mutex_lock(&g_thread_mutex);
944
945         instance = getpid();
946         /* Send REQ_GET_ACTIVE_DEVICE */
947         msgsnd.sound_msg.msgtype = MM_SOUND_MSG_REQ_GET_ACTIVE_DEVICE;
948         msgsnd.sound_msg.msgid = instance;
949
950         if (__MMIpcSndMsg(&msgsnd) != MM_ERROR_NONE)
951                 goto cleanup;
952
953         /* Recieve */
954         if (__MMIpcRecvMsg(instance, &msgrcv) != MM_ERROR_NONE)
955                 goto cleanup;
956
957         switch (msgrcv.sound_msg.msgtype)
958         {
959         case MM_SOUND_MSG_RES_GET_ACTIVE_DEVICE:
960                 *device_in = msgrcv.sound_msg.device_in;
961                 *device_out = msgrcv.sound_msg.device_out;
962                 debug_msg("[Client] Success to get active device %d %d\n", *device_in, *device_out);
963                 break;
964         case MM_SOUND_MSG_RES_ERROR:
965                 debug_error("[Client] Error occurred \n");
966                 ret = msgrcv.sound_msg.code;
967                 goto cleanup;
968                 break;
969         default:
970                 debug_critical("[Client] Unexpected state with communication \n");
971                 ret = msgrcv.sound_msg.code;
972                 goto cleanup;
973                 break;
974         }
975
976 cleanup:
977         pthread_mutex_unlock(&g_thread_mutex);
978
979         debug_fleave();
980         return ret;
981 }
982
983 int _mm_sound_client_add_active_device_changed_callback(mm_sound_active_device_changed_cb func, void* user_data)
984 {
985         mm_ipc_msg_t msgrcv = {0,};
986         mm_ipc_msg_t msgsnd = {0,};
987         int ret = MM_ERROR_NONE;
988         int instance;
989
990         debug_fenter();
991
992         if (__mm_sound_client_get_msg_queue() != MM_ERROR_NONE)
993                 return ret;
994
995         pthread_mutex_lock(&g_thread_mutex);
996
997         instance = getpid();
998         /* Send REQ_ADD_ACTIVE_DEVICE_CB */
999         msgsnd.sound_msg.msgtype = MM_SOUND_MSG_REQ_ADD_ACTIVE_DEVICE_CB;
1000         msgsnd.sound_msg.msgid = instance;
1001         msgsnd.sound_msg.callback = func;
1002         msgsnd.sound_msg.cbdata = user_data;
1003
1004         if (__MMIpcSndMsg(&msgsnd) != MM_ERROR_NONE)
1005                 goto cleanup;
1006
1007         /* Recieve */
1008         if (__MMIpcRecvMsg(instance, &msgrcv) != MM_ERROR_NONE)
1009                 goto cleanup;
1010
1011         switch (msgrcv.sound_msg.msgtype)
1012         {
1013         case MM_SOUND_MSG_RES_ADD_ACTIVE_DEVICE_CB:
1014                 debug_msg("[Client] Success to add active device callback\n");
1015                 if (g_thread_id == -1)
1016                 {
1017                         g_thread_id = pthread_create(&g_thread, NULL, callbackfunc, NULL);
1018                         if (g_thread_id == -1)
1019                         {
1020                                 debug_critical("[Client] Fail to create thread %s\n", strerror(errno));
1021                                 ret = MM_ERROR_SOUND_INTERNAL;
1022                                 goto cleanup;
1023                         }
1024                 }
1025                 break;
1026         case MM_SOUND_MSG_RES_ERROR:
1027                 debug_error("[Client] Error occurred \n");
1028                 ret = msgrcv.sound_msg.code;
1029                 goto cleanup;
1030                 break;
1031         default:
1032                 debug_critical("[Client] Unexpected state with communication \n");
1033                 ret = msgrcv.sound_msg.code;
1034                 goto cleanup;
1035                 break;
1036         }
1037
1038 cleanup:
1039         pthread_mutex_unlock(&g_thread_mutex);
1040
1041         debug_fleave();
1042         return ret;
1043 }
1044
1045 int _mm_sound_client_remove_active_device_changed_callback(void)
1046 {
1047         mm_ipc_msg_t msgrcv = {0,};
1048         mm_ipc_msg_t msgsnd = {0,};
1049         int ret = MM_ERROR_NONE;
1050         int instance;
1051
1052         debug_fenter();
1053
1054         if (__mm_sound_client_get_msg_queue() != MM_ERROR_NONE)
1055                 return ret;
1056
1057         pthread_mutex_lock(&g_thread_mutex);
1058
1059         instance = getpid();
1060         /* Send REQ_REMOVE_ACTIVE_DEVICE_CB */
1061         msgsnd.sound_msg.msgtype = MM_SOUND_MSG_REQ_REMOVE_ACTIVE_DEVICE_CB;
1062         msgsnd.sound_msg.msgid = instance;
1063
1064         if (__MMIpcSndMsg(&msgsnd) != MM_ERROR_NONE)
1065                 goto cleanup;
1066
1067         /* Recieve */
1068         if (__MMIpcRecvMsg(instance, &msgrcv) != MM_ERROR_NONE)
1069                 goto cleanup;
1070
1071         switch (msgrcv.sound_msg.msgtype)
1072         {
1073         case MM_SOUND_MSG_RES_REMOVE_ACTIVE_DEVICE_CB:
1074                 debug_msg("[Client] Success to remove active device callback\n");
1075                 break;
1076         case MM_SOUND_MSG_RES_ERROR:
1077                 debug_error("[Client] Error occurred \n");
1078                 ret = msgrcv.sound_msg.code;
1079                 goto cleanup;
1080                 break;
1081         default:
1082                 debug_critical("[Client] Unexpected state with communication \n");
1083                 ret = msgrcv.sound_msg.code;
1084                 goto cleanup;
1085                 break;
1086         }
1087
1088 cleanup:
1089         pthread_mutex_unlock(&g_thread_mutex);
1090
1091         debug_fleave();
1092         return ret;
1093 }
1094
1095 int _mm_sound_client_add_available_route_changed_callback(mm_sound_available_route_changed_cb func, void* user_data)
1096 {
1097         mm_ipc_msg_t msgrcv = {0,};
1098         mm_ipc_msg_t msgsnd = {0,};
1099         int ret = MM_ERROR_NONE;
1100         int instance;
1101
1102         debug_fenter();
1103
1104         if (__mm_sound_client_get_msg_queue() != MM_ERROR_NONE)
1105                 return ret;
1106
1107         pthread_mutex_lock(&g_thread_mutex);
1108
1109         instance = getpid();
1110         /* Send REQ_ADD_AVAILABLE_ROUTE_CB */
1111         msgsnd.sound_msg.msgtype = MM_SOUND_MSG_REQ_ADD_AVAILABLE_ROUTE_CB;
1112         msgsnd.sound_msg.msgid = instance;
1113         msgsnd.sound_msg.callback = func;
1114         msgsnd.sound_msg.cbdata = user_data;
1115
1116         if (__MMIpcSndMsg(&msgsnd) != MM_ERROR_NONE)
1117                 goto cleanup;
1118
1119         /* Recieve */
1120         if (__MMIpcRecvMsg(instance, &msgrcv) != MM_ERROR_NONE)
1121                 goto cleanup;
1122
1123         switch (msgrcv.sound_msg.msgtype)
1124         {
1125         case MM_SOUND_MSG_RES_ADD_AVAILABLE_ROUTE_CB:
1126                 debug_msg("[Client] Success to add available route callback\n");
1127                 if (g_thread_id == -1)
1128                 {
1129                         g_thread_id = pthread_create(&g_thread, NULL, callbackfunc, NULL);
1130                         if (g_thread_id == -1)
1131                         {
1132                                 debug_critical("[Client] Fail to create thread %s\n", strerror(errno));
1133                                 ret = MM_ERROR_SOUND_INTERNAL;
1134                                 goto cleanup;
1135                         }
1136                 }
1137                 break;
1138         case MM_SOUND_MSG_RES_ERROR:
1139                 debug_error("[Client] Error occurred \n");
1140                 ret = msgrcv.sound_msg.code;
1141                 goto cleanup;
1142                 break;
1143         default:
1144                 debug_critical("[Client] Unexpected state with communication \n");
1145                 ret = msgrcv.sound_msg.code;
1146                 goto cleanup;
1147                 break;
1148         }
1149
1150 cleanup:
1151         pthread_mutex_unlock(&g_thread_mutex);
1152
1153         debug_fleave();
1154         return ret;
1155 }
1156
1157 int _mm_sound_client_remove_available_route_changed_callback(void)
1158 {
1159         mm_ipc_msg_t msgrcv = {0,};
1160         mm_ipc_msg_t msgsnd = {0,};
1161         int ret = MM_ERROR_NONE;
1162         int instance;
1163
1164         debug_fenter();
1165
1166         if (__mm_sound_client_get_msg_queue() != MM_ERROR_NONE)
1167                 return ret;
1168
1169         pthread_mutex_lock(&g_thread_mutex);
1170
1171         instance = getpid();
1172         /* Send REQ_REMOVE_AVAILABLE_ROUTE_CB */
1173         msgsnd.sound_msg.msgtype = MM_SOUND_MSG_REQ_REMOVE_AVAILABLE_ROUTE_CB;
1174         msgsnd.sound_msg.msgid = instance;
1175
1176         if (__MMIpcSndMsg(&msgsnd) != MM_ERROR_NONE)
1177                 goto cleanup;
1178
1179         /* Recieve */
1180         if (__MMIpcRecvMsg(instance, &msgrcv) != MM_ERROR_NONE)
1181                 goto cleanup;
1182
1183         switch (msgrcv.sound_msg.msgtype)
1184         {
1185         case MM_SOUND_MSG_RES_REMOVE_AVAILABLE_ROUTE_CB:
1186                 debug_msg("[Client] Success to remove available route callback\n");
1187                 break;
1188         case MM_SOUND_MSG_RES_ERROR:
1189                 debug_error("[Client] Error occurred \n");
1190                 ret = msgrcv.sound_msg.code;
1191                 goto cleanup;
1192                 break;
1193         default:
1194                 debug_critical("[Client] Unexpected state with communication \n");
1195                 ret = msgrcv.sound_msg.code;
1196                 goto cleanup;
1197                 break;
1198         }
1199
1200 cleanup:
1201         pthread_mutex_unlock(&g_thread_mutex);
1202
1203         debug_fleave();
1204         return ret;
1205 }
1206
1207 static int __MMIpcCBSndMsg(mm_ipc_msg_t *msg)
1208 {
1209         /* rcv message */
1210         msg->msg_type = msg->sound_msg.msgid;
1211         if (msgsnd(g_msg_sccb, msg,DSIZE, 0)== -1)
1212         {
1213                 if(errno == EACCES)
1214                 {
1215                         debug_warning("[Client] Not acces.\n");
1216                 }
1217                 else if(errno == EAGAIN)
1218                 {
1219                         debug_warning("[Client] Blocked process [msgflag & IPC_NOWAIT != 0]\n");
1220                 }
1221                 else if(errno == EIDRM)
1222                 {
1223                         debug_warning("[Client] Removed msgid from system\n");
1224                 }
1225                 else if(errno == EINTR)
1226                 {
1227                         debug_warning("[Client] Iterrrupted by singnal\n");
1228                 }
1229                 else if(errno == EINVAL)
1230                 {
1231                         debug_warning("[Client] Invalid msgid or msgtype < 1 or out of data size \n");
1232                 }
1233                 debug_critical("[Client] Fail to callback send message msgid : [%d] \n", g_msg_sccb);
1234                 return MM_ERROR_COMMON_UNKNOWN;
1235         }
1236         return MM_ERROR_NONE;
1237 }
1238
1239 static int __MMIpcCBRecvMsg(int msgtype, mm_ipc_msg_t *msg)
1240 {
1241         /* rcv message */
1242         if(msgrcv(g_msg_sccb, msg, DSIZE, msgtype, 0) == -1)
1243         {
1244                 if(errno == E2BIG)
1245                 {
1246                         debug_warning("[Client] Not acces.\n");
1247                 }
1248                 else if(errno == EACCES)
1249                 {
1250                         debug_warning("[Client] Access denied\n");
1251                 }
1252                 else if(errno == ENOMSG)
1253                 {
1254                         debug_warning("[Client] Blocked process [msgflag & IPC_NOWAIT != 0]\n");
1255                 }
1256                 else if(errno == EIDRM)
1257                 {
1258                         debug_warning("[Client] Removed msgid from system\n");
1259                 }
1260                 else if(errno == EINTR)
1261                 {
1262                         debug_warning("[Client] Iterrrupted by singnal\n");
1263                 }
1264                 else if(errno == EINVAL)
1265                 {
1266                         debug_warning("[Client] Invalid msgid \n");
1267                 }
1268
1269                 debug_error("[Client] Fail to callback receive msgid : [%d] \n", g_msg_sccb);
1270                 return MM_ERROR_COMMON_UNKNOWN;
1271         }
1272         return MM_ERROR_NONE;
1273 }
1274
1275 static int __MMIpcRecvMsg(int msgtype, mm_ipc_msg_t *msg)
1276 {
1277         int retry_count = 0;
1278
1279         /* rcv message */
1280         while (msgrcv(g_msg_scrcv, msg, DSIZE, msgtype, IPC_NOWAIT) == -1) {
1281                 if (errno == ENOMSG) {
1282                         if (retry_count < 20000) { /* usec is 10^-6 sec so, 5ms * 20000 = 10sec. */
1283                                 usleep(5000);
1284                                 retry_count++;
1285                                 continue;
1286                         } else {
1287                                 return MM_ERROR_SOUND_INTERNAL;
1288                         }
1289                 } else if (errno == E2BIG) {
1290                         debug_warning("[Client] Not acces.\n");
1291                 } else if (errno == EACCES) {
1292                         debug_warning("[Client] Access denied\n");
1293                 } else if (errno == ENOMSG) {
1294                         debug_warning("[Client] Blocked process [msgflag & IPC_NOWAIT != 0]\n");
1295                 } else if (errno == EIDRM) {
1296                         debug_warning("[Client] Removed msgid from system\n");
1297                 } else if (errno == EINTR) {
1298                         debug_warning("[Client] Iterrrupted by singnal\n");
1299                         continue;
1300                 } else if (errno == EINVAL) {
1301                         debug_warning("[Client] Invalid msgid \n");
1302                 }
1303
1304                 debug_error("[Client] Fail to recive msgid : [%d] \n", g_msg_scrcv);
1305                 return MM_ERROR_COMMON_UNKNOWN;
1306         }
1307         debug_log("[Client] Retry %d times when receive msg\n", retry_count);
1308         return MM_ERROR_NONE;
1309 }
1310
1311 static int __MMIpcSndMsg(mm_ipc_msg_t *msg)
1312 {
1313         /* rcv message */
1314         msg->msg_type = msg->sound_msg.msgid;
1315         if (msgsnd(g_msg_scsnd, msg,DSIZE, 0) == -1)
1316         {
1317                 if (errno == EACCES) {
1318                         debug_warning("[Client] Not access.\n");
1319                 } else if (errno == EAGAIN) {
1320                         debug_warning("[Client] Blocked process msgflag & IPC_NOWAIT != 0]\n");
1321                 } else if (errno == EIDRM) {
1322                         debug_warning("[Client] Removed msgid from system\n");
1323                 } else if (errno == EINTR) {
1324                         debug_warning("[Client] Iterrrupted by singnal\n");
1325                 } else if (errno == EINVAL) {
1326                         debug_warning("Invalid msgid or msgtype < 1 or out of data size \n");
1327                 } else if (errno == EFAULT) {
1328                         debug_warning("[Client] The address pointed to by msgp isn't accessible \n");
1329                 } else if (errno == ENOMEM) {
1330                         debug_warning("[Client] The system does not have enough memory to make a copy of the message pointed to by msgp\n");
1331                 }
1332
1333                 debug_critical("[Client] Fail to send message msgid : [%d] \n", g_msg_scsnd);
1334                 return MM_ERROR_SOUND_INTERNAL;
1335         }
1336         return MM_ERROR_NONE;
1337 }
1338
1339 static int __MMSoundGetMsg(void)
1340 {
1341         /* Init message queue, generate msgid for communication to server */
1342         /* The key value to get msgid is defined "mm_sound_msg.h". Shared with server */
1343         
1344         debug_fenter();
1345         
1346         /* get msg queue rcv, snd, cb */
1347         g_msg_scsnd = msgget(ftok(KEY_BASE_PATH, RCV_MSG), 0666);
1348         g_msg_scrcv = msgget(ftok(KEY_BASE_PATH, SND_MSG), 0666);
1349         g_msg_sccb = msgget(ftok(KEY_BASE_PATH, CB_MSG), 0666);
1350
1351         if ((g_msg_scsnd == -1 || g_msg_scrcv == -1 || g_msg_sccb == -1) != MM_ERROR_NONE) {
1352                 if (errno == EACCES) {
1353                         debug_warning("Require ROOT permission.\n");
1354                 } else if (errno == ENOMEM) {
1355                         debug_warning("System memory is empty.\n");
1356                 } else if(errno == ENOSPC) {
1357                         debug_warning("Resource is empty.\n");
1358                 }
1359                 debug_error("Fail to GET msgid\n");
1360                 return MM_ERROR_SOUND_INTERNAL;
1361         }
1362         
1363         debug_msg("Get msg queue id from server : [%d]\n", g_msg_scsnd);
1364         debug_msg("Get msg queue id from server : [%d]\n", g_msg_scrcv);
1365         debug_msg("Get msg queue id from server : [%d]\n", g_msg_sccb);
1366         
1367         debug_fleave();
1368         return MM_ERROR_NONE;
1369 }
1370
1371 #ifdef PULSE_CLIENT
1372
1373 int MMSoundClientIsBtA2dpOn (bool *connected, char** bt_name)
1374 {
1375         mm_ipc_msg_t msgrcv = {0,};
1376         mm_ipc_msg_t msgsnd = {0,};
1377         int ret = MM_ERROR_NONE;
1378         int instance;
1379
1380         debug_fenter();
1381
1382         instance = getpid();    
1383
1384         if (__mm_sound_client_get_msg_queue() != MM_ERROR_NONE)
1385                 return ret;
1386
1387         pthread_mutex_lock(&g_thread_mutex);
1388
1389         /* Send req  */
1390         msgsnd.sound_msg.msgtype = MM_SOUND_MSG_REQ_IS_BT_A2DP_ON;
1391         msgsnd.sound_msg.msgid = instance;
1392
1393         ret = __MMIpcSndMsg(&msgsnd);
1394         if (ret != MM_ERROR_NONE)
1395         {
1396                 debug_error("Fail to send msg\n");
1397                 goto cleanup;
1398         }
1399
1400         /* Recieve */
1401         ret = __MMIpcRecvMsg(instance, &msgrcv);
1402         if (ret != MM_ERROR_NONE)
1403         {
1404                 debug_error("Fail to recieve msg\n");
1405                 goto cleanup;
1406         }
1407         switch (msgrcv.sound_msg.msgtype)
1408         {
1409                 case MM_SOUND_MSG_RES_IS_BT_A2DP_ON:
1410                         debug_msg("Success to get IS_BT_A2DP_ON [%d][%s]\n", msgrcv.sound_msg.code, msgrcv.sound_msg.filename);
1411                         *connected  = (bool)msgrcv.sound_msg.code;
1412                         if (*connected)
1413                                 *bt_name = strdup (msgrcv.sound_msg.filename);
1414                         else
1415                                 *bt_name = NULL;
1416                         break;
1417                 case MM_SOUND_MSG_RES_ERROR:
1418                         debug_error("Error occurred \n");
1419                         ret = msgrcv.sound_msg.code;
1420                         goto cleanup;
1421                         break;
1422                 default:
1423                         debug_critical("Unexpected state with communication \n");
1424                         ret = msgrcv.sound_msg.code;
1425                         goto cleanup;
1426                         break;
1427         }
1428
1429 cleanup:
1430                 pthread_mutex_unlock(&g_thread_mutex);
1431
1432         debug_fleave();
1433         return ret;
1434 }
1435
1436 #endif // PULSE_CLIENT