Updated version and changelog.
[profile/ivi/libmm-sound.git] / mm_sound.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 <memory.h>
24 #include <unistd.h>
25 #include <pthread.h>
26 #include <stdio.h>
27 #include <sys/types.h>
28 #include <fcntl.h>
29
30 #include <sys/stat.h>
31 #include <errno.h>
32 #include <avsystem.h>
33
34 #include <vconf.h>
35 #include <mm_types.h>
36 #include <mm_error.h>
37 #include <mm_message.h>
38 #include <mm_debug.h>
39 #include "include/mm_sound_private.h"
40 #include "include/mm_sound.h"
41 #include "include/mm_sound_utils.h"
42 #include "include/mm_sound_client.h"
43 #include "include/mm_ipc.h"
44 #include "include/mm_sound_common.h"
45
46
47 #include <audio-session-manager.h>
48 #include <mm_session.h>
49 #include <mm_session_private.h>
50
51 #define MAX_FILE_LENGTH 256
52 #define MAX_MEMORY_SIZE 1048576 /* Max memory size 1024*1024 (1MB) */
53 #define _MIN_SYSTEM_SAMPLERATE  8000
54 #define _MAX_SYSTEM_SAMPLERATE  48000
55 #define MIN_TONE_PLAY_TIME 300
56
57 typedef struct {
58         volume_callback_fn      func;
59         void*                           data;
60         volume_type_t           type;
61 }volume_cb_param;
62
63 volume_cb_param g_volume_param[VOLUME_TYPE_MAX];
64
65 static pthread_mutex_t _volume_mutex = PTHREAD_MUTEX_INITIALIZER;
66
67 #define PCM_LOCK_INTERNAL(LOCK) do { pthread_mutex_lock(LOCK); } while (0)
68 #define PCM_UNLOCK_INTERNAL(LOCK) do { pthread_mutex_unlock(LOCK); } while (0)
69 #define PCM_LOCK_DESTROY_INTERNAL(LOCK) do { pthread_mutex_destroy(LOCK); } while (0)
70
71 typedef struct {
72         avsys_handle_t          audio_handle;
73         int                                     asm_handle;
74         ASM_sound_events_t      asm_event;
75
76         bool                            is_started;
77         bool                            is_playback;
78         bool                            skip_session;
79         pthread_mutex_t pcm_mutex_internal;
80         MMMessageCallback       msg_cb;
81         void *msg_cb_param;
82
83
84 } mm_sound_pcm_t;
85
86 static int _pcm_sound_start (MMSoundPcmHandle_t handle);
87 static int _pcm_sound_stop_internal (MMSoundPcmHandle_t handle);
88 static int _pcm_sound_stop(MMSoundPcmHandle_t handle);
89
90 static void __sound_pcm_send_message (mm_sound_pcm_t *pcmHandle, int message, int code);
91
92 static int __validate_volume(volume_type_t type, int value)
93 {
94         if (value < 0)
95                 return -1;
96
97         switch (type)
98         {
99         case VOLUME_TYPE_CALL:
100         case VOLUME_TYPE_VOIP:
101                 if (value >= AVSYS_AUDIO_VOLUME_MAX_BASIC) {
102                         return -1;
103                 }
104                 break;
105         case VOLUME_TYPE_SYSTEM:
106         case VOLUME_TYPE_MEDIA:
107         case VOLUME_TYPE_ALARM:
108         case VOLUME_TYPE_EXT_JAVA:
109         case VOLUME_TYPE_NOTIFICATION:
110         case VOLUME_TYPE_RINGTONE:
111                 if (value >= AVSYS_AUDIO_VOLUME_MAX_MULTIMEDIA) {
112                         return -1;
113                 }
114                 break;
115         case VOLUME_TYPE_EXT_ANDROID:
116                 if (value >= AVSYS_AUDIO_VOLUME_MAX_SINGLE) {
117                         return -1;
118                 }
119                 break;
120         default:
121                 return -1;
122                 break;
123         }
124         return 0;
125 }
126
127 static void volume_changed_cb(keynode_t* node, void* data)
128 {
129         volume_cb_param* param = (volume_cb_param*) data;
130
131         debug_msg("%s changed callback called\n",vconf_keynode_get_name(node));
132
133         MMSOUND_ENTER_CRITICAL_SECTION( &_volume_mutex )
134
135         if(param && (param->func != NULL)) {
136                 debug_msg("funcion 0x%x\n", param->func);
137                 ((volume_callback_fn)param->func)(param->data);
138         }
139
140         MMSOUND_LEAVE_CRITICAL_SECTION( &_volume_mutex )
141 }
142
143 EXPORT_API
144 int mm_sound_volume_add_callback(volume_type_t type, volume_callback_fn func, void* user_data)
145 {
146         debug_fenter();
147
148         /* Check input param */
149         if (type < 0 || type >= VOLUME_TYPE_MAX) {
150                 return MM_ERROR_INVALID_ARGUMENT;
151         }
152         if (!func) {
153                 debug_warning("callback function is null\n");
154                 return MM_ERROR_INVALID_ARGUMENT;
155         }
156
157         MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN( &_volume_mutex, MM_ERROR_SOUND_INTERNAL );
158
159         g_volume_param[type].func = func;
160         g_volume_param[type].data = user_data;
161         g_volume_param[type].type = type;
162
163         MMSOUND_LEAVE_CRITICAL_SECTION( &_volume_mutex );
164
165         return _mm_sound_volume_add_callback(type, volume_changed_cb, (void*)&g_volume_param[type]);
166 }
167
168 EXPORT_API
169 int mm_sound_volume_remove_callback(volume_type_t type)
170 {
171         debug_fenter();
172
173         if(type < 0 || type >=VOLUME_TYPE_MAX) {
174                 return MM_ERROR_INVALID_ARGUMENT;
175         }
176
177         MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN( &_volume_mutex, MM_ERROR_SOUND_INTERNAL );
178
179         g_volume_param[type].func = NULL;
180         g_volume_param[type].data = NULL;
181         g_volume_param[type].type = type;
182
183         MMSOUND_LEAVE_CRITICAL_SECTION( &_volume_mutex );
184
185         return _mm_sound_volume_remove_callback(type, volume_changed_cb);
186 }
187
188 EXPORT_API
189 int mm_sound_get_volume_step(volume_type_t type, int *step)
190 {
191         printf("\n**********\n\nTHIS FUNCTION HAS DEFPRECATED [%s]\n\n \
192                         use mm_sound_volume_get_step() instead\n\n**********\n", __func__);
193         return mm_sound_volume_get_step(type, step);
194 }
195
196 EXPORT_API
197 int mm_sound_volume_get_step(volume_type_t type, int *step)
198 {
199         int err;
200
201         debug_fenter();
202
203         /* Check input param */
204         if (step == NULL) {
205                 debug_error("second parameter is null\n");
206                 return MM_ERROR_INVALID_ARGUMENT;
207         }
208         if (type < 0 || type >= VOLUME_TYPE_MAX) {
209                 debug_error("Invalid type value %d\n", (int)type);
210                 return MM_ERROR_INVALID_ARGUMENT;
211         }
212
213         err = avsys_audio_get_volume_max_ex((int)type, step);
214         if (AVSYS_FAIL(err)) {
215                 err = MM_ERROR_INVALID_ARGUMENT;
216         }
217
218         debug_fleave();
219         return MM_ERROR_NONE;
220 }
221
222 EXPORT_API
223 int mm_sound_volume_set_value(volume_type_t type, const unsigned int value)
224 {
225         int ret = MM_ERROR_NONE;
226
227         debug_fenter();
228
229         /* Check input param */
230         if (0 > __validate_volume(type, (int)value)) {
231                 debug_error("invalid volume type %d, value %u\n", type, value);
232                 return MM_ERROR_INVALID_ARGUMENT;
233         }
234
235         ret = _mm_sound_volume_set_value_by_type(type, value);
236         if (ret == MM_ERROR_NONE) {
237                 /* update shared memory value */
238                 if (AVSYS_FAIL(avsys_audio_set_volume_by_type(type, (int)value))) {
239                         debug_error("Can not set volume to shared memory 0x%x\n", ret);
240                 }
241         }
242
243         debug_fleave();
244         return ret;
245 }
246
247 EXPORT_API
248 int mm_sound_volume_get_value(volume_type_t type, unsigned int *value)
249 {
250         int ret = MM_ERROR_NONE;
251
252         debug_fenter();
253
254         /* Check input param */
255         if (value == NULL)
256                 return MM_ERROR_INVALID_ARGUMENT;
257         if (type < 0 || type >= VOLUME_TYPE_MAX) {
258                 debug_error("invalid volume type value %d\n", type);
259                 return MM_ERROR_INVALID_ARGUMENT;
260         }
261
262         ret = _mm_sound_volume_get_value_by_type(type, value);
263
264         debug_fleave();
265         return ret;
266 }
267
268 EXPORT_API
269 int mm_sound_volume_primary_type_set(volume_type_t type)
270 {
271         pid_t mypid;
272         int ret = MM_ERROR_NONE;
273
274         /* Check input param */
275         if(type < 0 || type >= VOLUME_TYPE_MAX)
276                 return MM_ERROR_INVALID_ARGUMENT;
277
278         debug_fenter();
279
280         mypid = getpid();
281         if(AVSYS_FAIL(avsys_audio_set_primary_volume((int)mypid, type))) {
282                 debug_error("Can not set primary volume [%d, %d]\n", mypid, type);
283                 ret = MM_ERROR_SOUND_INTERNAL;
284         }
285
286         debug_fleave();
287         return ret;
288 }
289
290 EXPORT_API
291 int mm_sound_volume_primary_type_clear()
292 {
293         pid_t mypid;
294         int ret = MM_ERROR_NONE;
295
296         debug_fenter();
297
298         mypid = getpid();
299         if(AVSYS_FAIL(avsys_audio_clear_primary_volume((int)mypid))) {
300                 debug_error("Can not clear primary volume [%d]\n", mypid);
301                 ret = MM_ERROR_SOUND_INTERNAL;
302         }
303
304         debug_fleave();
305         return ret;
306 }
307
308 EXPORT_API
309 int mm_sound_volume_get_current_playing_type(volume_type_t *type)
310 {
311         int result = AVSYS_STATE_SUCCESS;
312         int voltype = AVSYS_AUDIO_VOLUME_TYPE_RINGTONE;
313         int ret = MM_ERROR_NONE;
314
315         debug_fenter();
316
317         /* Check input param */
318         if(type == NULL) {
319                 return MM_ERROR_INVALID_ARGUMENT;
320         }
321
322         result = avsys_audio_get_current_playing_volume_type(&voltype);
323         switch (result)
324         {
325         case AVSYS_STATE_SUCCESS:
326                 *type = voltype;
327                 break;
328         case AVSYS_STATE_ERR_ALLOCATION:
329                 ret = MM_ERROR_SOUND_VOLUME_NO_INSTANCE;
330                 break;
331         case AVSYS_STATE_ERR_INVALID_MODE:
332                 ret = MM_ERROR_SOUND_VOLUME_CAPTURE_ONLY;
333                 break;
334         default:
335                 ret = MM_ERROR_SOUND_INTERNAL;
336                 break;
337         }
338         debug_log("avsys_audio_get_current_playing_volume_type() = %x, ret = %x, type = %d\n", result, ret, *type);
339
340         debug_fleave();
341         return ret;
342 }
343
344 ///////////////////////////////////
345 ////     MMSOUND PCM APIs
346 ///////////////////////////////////
347
348
349 int _get_asm_event_type(ASM_sound_events_t *type)
350 {
351         int     sessionType = MM_SESSION_TYPE_SHARE;
352         ASM_sound_events_t asm_event;
353
354         if(type == NULL)
355                 return MM_ERROR_SOUND_INVALID_POINTER;
356
357         /* read session type */
358         if(_mm_session_util_read_type(-1, &sessionType) < 0) {
359                 debug_log("Read Session Type failed. Set default \"Share\" type\n");
360                 sessionType = MM_SESSION_TYPE_SHARE;
361                 if(mm_session_init(sessionType) < 0) {
362                         debug_error("mm_session_init() failed\n");
363                         return MM_ERROR_SOUND_INTERNAL;
364                 }
365         }
366
367         /* convert MM_SESSION_TYPE to ASM_EVENT_TYPE */
368         switch (sessionType)
369         {
370         case MM_SESSION_TYPE_SHARE:
371                 asm_event = ASM_EVENT_SHARE_MMSOUND;
372                 break;
373         case MM_SESSION_TYPE_EXCLUSIVE:
374                 asm_event = ASM_EVENT_EXCLUSIVE_MMSOUND;
375                 break;
376         case MM_SESSION_TYPE_NOTIFY:
377                 asm_event = ASM_EVENT_NOTIFY;
378                 break;
379         case MM_SESSION_TYPE_ALARM:
380                 asm_event = ASM_EVENT_ALARM;
381                 break;
382         case MM_SESSION_TYPE_CALL:
383                 asm_event = ASM_EVENT_CALL;
384                 break;
385         case MM_SESSION_TYPE_VIDEOCALL:
386                 asm_event = ASM_EVENT_VIDEOCALL;
387                 break;
388         case MM_SESSION_TYPE_RICH_CALL:
389                 asm_event = ASM_EVENT_RICH_CALL;
390                 break;
391         case MM_SESSION_TYPE_EMERGENCY:
392                 asm_event = ASM_EVENT_EMERGENCY;
393                 break;
394         default:
395                 debug_error("Unexpected %d\n", sessionType);
396                 return MM_ERROR_SOUND_INTERNAL;
397         }
398
399         *type = asm_event;
400         return MM_ERROR_NONE;
401 }
402
403 static void __sound_pcm_send_message (mm_sound_pcm_t *pcmHandle, int message, int code)
404 {
405         int ret = 0;
406         if (pcmHandle->msg_cb) {
407                 MMMessageParamType msg;
408                 msg.union_type = MM_MSG_UNION_CODE;
409                 msg.code = code;
410
411                 debug_log ("calling msg callback(%p) with message(%d), code(%d), msg callback param(%p)\n",
412                                 pcmHandle->msg_cb, message, msg.code, pcmHandle->msg_cb_param);
413                 ret = pcmHandle->msg_cb(message, &msg, pcmHandle->msg_cb_param);
414                 debug_log ("msg callback returned (%d)\n", ret);
415         } else {
416                 debug_log ("No pcm msg callback\n");
417         }
418 }
419
420 ASM_cb_result_t sound_pcm_asm_callback(int handle, ASM_event_sources_t event_src, ASM_sound_commands_t command, unsigned int sound_status, void *cb_data)
421 {
422         mm_sound_pcm_t *pcmHandle = (mm_sound_pcm_t *)cb_data;
423         ASM_cb_result_t cb_res = ASM_CB_RES_IGNORE;
424
425         /* Check input param */
426         if(pcmHandle == NULL) {
427                 debug_error("sound_pcm_asm_callback cb_data is null\n");
428                 return cb_res;
429         }
430
431         debug_log ("command = %d, handle = %p, is_started = %d\n",command, pcmHandle, pcmHandle->is_started);
432         switch(command)
433         {
434         case ASM_COMMAND_STOP:
435                 /* Do stop */
436                 PCM_LOCK_INTERNAL(&pcmHandle->pcm_mutex_internal);
437                 _pcm_sound_stop_internal (pcmHandle);
438                 PCM_UNLOCK_INTERNAL(&pcmHandle->pcm_mutex_internal);
439                 cb_res = ASM_CB_RES_PAUSE;
440                 break;
441
442         case ASM_COMMAND_RESUME:
443                 cb_res = ASM_CB_RES_IGNORE;
444                 break;
445
446         case ASM_COMMAND_PAUSE:
447         case ASM_COMMAND_PLAY:
448         case ASM_COMMAND_NONE:
449                 debug_error ("Not an expected case!!!!\n");
450                 break;
451         }
452
453         /* execute user callback if callback available */
454         __sound_pcm_send_message (pcmHandle, MM_MESSAGE_SOUND_PCM_INTERRUPTED, event_src);
455
456         return cb_res;
457 }
458
459 EXPORT_API
460 int mm_sound_pcm_capture_open(MMSoundPcmHandle_t *handle, const unsigned int rate, MMSoundPcmChannel_t channel, MMSoundPcmFormat_t format)
461 {
462         avsys_audio_param_t param;
463         mm_sound_pcm_t *pcmHandle = NULL;
464         int size = 0;
465         int result = AVSYS_STATE_SUCCESS;
466         int errorcode = 0;
467         int ret_mutex = 0;
468         debug_fenter();
469         memset(&param, 0, sizeof(avsys_audio_param_t));
470
471
472         if (rate < _MIN_SYSTEM_SAMPLERATE || rate > _MAX_SYSTEM_SAMPLERATE) {
473                 debug_error("unsupported sample rate %u", rate);
474                 return MM_ERROR_SOUND_DEVICE_INVALID_SAMPLERATE;
475         } else {
476                 param.samplerate = rate;
477         }
478
479         switch(channel)
480         {
481         case MMSOUND_PCM_MONO:
482                 param.channels = 1;
483                 break;
484         case MMSOUND_PCM_STEREO:
485                 param.channels = 2;
486                 break;
487
488         default:
489                 debug_error("Unsupported channel type\n");
490                 return MM_ERROR_SOUND_DEVICE_INVALID_CHANNEL;
491         }
492
493         switch(format)
494         {
495         case MMSOUND_PCM_U8:
496                 param.format = AVSYS_AUDIO_FORMAT_8BIT;
497                 break;
498         case MMSOUND_PCM_S16_LE:
499                 param.format = AVSYS_AUDIO_FORMAT_16BIT;
500                 break;
501         default:
502                 debug_error("Unsupported format type\n");
503                 return MM_ERROR_SOUND_DEVICE_INVALID_FORMAT;
504         }
505
506         pcmHandle = calloc(sizeof(mm_sound_pcm_t), 1);
507         if(pcmHandle == NULL)
508                 return MM_ERROR_OUT_OF_MEMORY;
509
510         ret_mutex = pthread_mutex_init(&pcmHandle->pcm_mutex_internal, NULL);
511         if(ret_mutex != 0)
512         {
513                 free(pcmHandle);
514                 return MM_ERROR_OUT_OF_MEMORY;
515         }
516
517         /* Register ASM */
518         /* get session type */
519         if(MM_ERROR_NONE != _get_asm_event_type(&pcmHandle->asm_event)) {
520                 PCM_LOCK_DESTROY_INTERNAL(&pcmHandle->pcm_mutex_internal);
521                 free(pcmHandle);
522                 return MM_ERROR_POLICY_INTERNAL;
523         }
524         /* register asm */
525         if(pcmHandle->asm_event != ASM_EVENT_CALL && pcmHandle->asm_event != ASM_EVENT_VIDEOCALL) {
526                 if(!ASM_register_sound(-1, &pcmHandle->asm_handle, pcmHandle->asm_event,
527                                 /* ASM_STATE_PLAYING */ ASM_STATE_NONE, sound_pcm_asm_callback, (void*)pcmHandle, ASM_RESOURCE_NONE, &errorcode))
528                 {
529                         debug_error("ASM_register_sound() failed 0x%x\n", errorcode);
530                         PCM_LOCK_DESTROY_INTERNAL(&pcmHandle->pcm_mutex_internal);
531                         free(pcmHandle);
532                         return MM_ERROR_POLICY_BLOCKED;
533                 }
534         }
535
536         /* Open */
537         param.mode = AVSYS_AUDIO_MODE_INPUT;
538         param.vol_type = AVSYS_AUDIO_VOLUME_TYPE_SYSTEM; //dose not effect at capture mode
539         param.priority = AVSYS_AUDIO_PRIORITY_0;                //This does not affect anymore.
540         result = avsys_audio_open(&param, &pcmHandle->audio_handle, &size);
541         if(AVSYS_FAIL(result)) {
542                 debug_error("Device Open Error 0x%x\n", result);
543                 PCM_LOCK_DESTROY_INTERNAL(&pcmHandle->pcm_mutex_internal);
544                 free(pcmHandle);
545                 return MM_ERROR_SOUND_DEVICE_NOT_OPENED;
546         }
547
548         pcmHandle->is_playback = false;
549
550         /* Set handle to return */
551         *handle = (MMSoundPcmHandle_t)pcmHandle;
552         debug_fleave();
553         return size;
554 }
555
556 static int _pcm_sound_start (MMSoundPcmHandle_t handle)
557 {
558         mm_sound_pcm_t *pcmHandle = (mm_sound_pcm_t*)handle;
559         int errorcode = 0;
560         int ret = 0;
561
562         debug_fenter();
563
564         /* Check input param */
565         if(pcmHandle == NULL) {
566                 debug_error ("Handle is null, return Invalid Argument\n");
567                 ret = MM_ERROR_INVALID_ARGUMENT;
568                 goto NULL_HANDLE;
569         }
570
571         PCM_LOCK_INTERNAL(&pcmHandle->pcm_mutex_internal);
572
573         if (pcmHandle->skip_session == false) {
574                 /* ASM set state to PLAYING */
575                 if (!ASM_set_sound_state(pcmHandle->asm_handle, pcmHandle->asm_event, ASM_STATE_PLAYING, ASM_RESOURCE_NONE, &errorcode)) {
576                         debug_error("ASM_set_sound_state(PLAYING) failed 0x%x\n", errorcode);
577                         ret = MM_ERROR_POLICY_BLOCKED;
578                         goto EXIT;
579                 }
580         }
581
582         /* Update State */
583         pcmHandle->is_started = true;
584
585         /* Un-Cork */
586         ret = avsys_audio_cork(pcmHandle->audio_handle, 0);
587
588 EXIT:
589         PCM_UNLOCK_INTERNAL(&pcmHandle->pcm_mutex_internal);
590
591 NULL_HANDLE:
592         debug_fleave();
593         return ret;
594 }
595
596
597 EXPORT_API
598 int mm_sound_pcm_capture_start(MMSoundPcmHandle_t handle)
599 {
600         int ret = MM_ERROR_NONE;
601         debug_fenter();
602
603
604         ret = _pcm_sound_start (handle);
605         if (ret != MM_ERROR_NONE)  {
606                 debug_error ("_pcm_sound_start() failed (%x)\n", ret);
607                 goto EXIT;
608         }
609
610 EXIT:
611         debug_fleave();
612         return ret;
613 }
614
615 static int _pcm_sound_stop_internal (MMSoundPcmHandle_t handle)
616 {
617         mm_sound_pcm_t *pcmHandle = (mm_sound_pcm_t*)handle;
618
619         /* Check input param */
620         if(pcmHandle == NULL)
621                 return MM_ERROR_INVALID_ARGUMENT;
622
623         /* Check State */
624         if (pcmHandle->is_started == false) {
625                 debug_warning ("Can't stop because not started\n");
626                 return MM_ERROR_SOUND_INVALID_STATE;
627         }
628
629         /* Drain if playback mode */
630         if (pcmHandle->is_playback) {
631                 if(AVSYS_FAIL(avsys_audio_drain(pcmHandle->audio_handle))) {
632                         debug_error("drain failed\n");
633                 }
634         }
635
636         /* Update State */
637         pcmHandle->is_started = false;
638
639         /* Cork */
640         return avsys_audio_cork(pcmHandle->audio_handle, 1);
641 }
642
643 static int _pcm_sound_stop(MMSoundPcmHandle_t handle)
644 {
645         mm_sound_pcm_t *pcmHandle = (mm_sound_pcm_t*)handle;
646         int errorcode = 0;
647         int ret = MM_ERROR_NONE;
648
649         debug_fenter();
650
651         /* Check input param */
652         if(pcmHandle == NULL) {
653                 debug_error ("Handle is null, return Invalid Argument\n");
654                 ret = MM_ERROR_INVALID_ARGUMENT;
655                 goto NULL_HANDLE;
656         }
657
658         PCM_LOCK_INTERNAL(&pcmHandle->pcm_mutex_internal);
659
660         /* Do stop procedure */
661         ret = _pcm_sound_stop_internal(handle);
662         if (ret == MM_ERROR_NONE) {
663                 /* Set ASM State to STOP */
664                 if (pcmHandle->skip_session == false) {
665                         if (!ASM_set_sound_state(pcmHandle->asm_handle, pcmHandle->asm_event, ASM_STATE_STOP, ASM_RESOURCE_NONE, &errorcode)) {
666                                 debug_error("ASM_set_sound_state(STOP) failed 0x%x\n", errorcode);
667                                 ret = MM_ERROR_POLICY_BLOCKED;
668                                 goto EXIT;
669                         }
670                 }
671         }
672
673         debug_log ("pcm sound [%p] stopped success!!!\n", handle);
674
675 EXIT:
676         PCM_UNLOCK_INTERNAL(&pcmHandle->pcm_mutex_internal);
677 NULL_HANDLE:
678         debug_fleave();
679         return ret;
680 }
681
682
683 EXPORT_API
684 int mm_sound_pcm_capture_stop(MMSoundPcmHandle_t handle)
685 {
686         int ret = 0;
687         debug_fenter();
688
689         ret = _pcm_sound_stop(handle);
690
691         debug_fleave();
692         return ret;
693 }
694
695
696 EXPORT_API
697 int mm_sound_pcm_capture_read(MMSoundPcmHandle_t handle, void *buffer, const unsigned int length )
698 {
699         int ret = 0;
700         mm_sound_pcm_t *pcmHandle = (mm_sound_pcm_t*)handle;
701
702         /* Check input param */
703         if(pcmHandle == NULL) {
704                 debug_error ("Handle is null, return Invalid Argument\n");
705                 ret =  MM_ERROR_INVALID_ARGUMENT;
706                 goto NULL_HANDLE;
707         }
708         PCM_LOCK_INTERNAL(&pcmHandle->pcm_mutex_internal);
709
710         if(buffer == NULL) {
711                 debug_error("Invalid buffer pointer\n");
712                 ret = MM_ERROR_SOUND_INVALID_POINTER;
713                 goto EXIT;
714         }
715         if(length == 0 ) {
716                 debug_error ("length is 0, return 0\n");
717                 ret = 0;
718                 goto EXIT;
719         }
720
721         /* Check State : return fail if not started */
722         if (!pcmHandle->is_started) {
723                 /*  not started, return fail */
724                 debug_error ("Not started yet, return Invalid State \n");
725                 ret = MM_ERROR_SOUND_INVALID_STATE;
726                 goto EXIT;
727         }
728
729         /* Read */
730         ret = avsys_audio_read(pcmHandle->audio_handle, buffer, length);
731
732 EXIT:
733         PCM_UNLOCK_INTERNAL(&pcmHandle->pcm_mutex_internal);
734 NULL_HANDLE:
735         return ret;
736 }
737
738 EXPORT_API
739 int mm_sound_pcm_capture_close(MMSoundPcmHandle_t handle)
740 {
741         int result = MM_ERROR_NONE;
742         mm_sound_pcm_t *pcmHandle = (mm_sound_pcm_t*)handle;
743         int errorcode = 0;
744
745         debug_fenter();
746         /* Check input param */
747         if(pcmHandle == NULL) {
748                 debug_error ("Handle is null, return Invalid Argument\n");
749                 result = MM_ERROR_INVALID_ARGUMENT;
750                 goto NULL_HDL;
751         }
752         PCM_LOCK_INTERNAL(&pcmHandle->pcm_mutex_internal);
753         /* Close */
754         result = avsys_audio_close(pcmHandle->audio_handle);
755         if(AVSYS_FAIL(result)) {
756                 debug_error("handle close failed 0x%X", result);
757                 result = MM_ERROR_SOUND_INTERNAL;
758                 goto EXIT;
759         }
760
761         /* Unregister ASM */
762         if(pcmHandle->asm_event != ASM_EVENT_CALL && pcmHandle->asm_event != ASM_EVENT_VIDEOCALL) {
763                 if(!ASM_unregister_sound(pcmHandle->asm_handle, pcmHandle->asm_event, &errorcode)) {
764                 debug_error("ASM_unregister failed in %s with 0x%x\n", __func__, errorcode);
765                         result = MM_ERROR_SOUND_INTERNAL;
766                         goto EXIT;
767         }
768     }
769
770         debug_log ("pcm capture sound [%p] closed success!!!\n", handle);
771
772 EXIT:
773         PCM_UNLOCK_INTERNAL(&pcmHandle->pcm_mutex_internal);
774 NULL_HDL:
775         /* Free handle */
776         if (pcmHandle) {
777                 PCM_LOCK_DESTROY_INTERNAL(&pcmHandle->pcm_mutex_internal);
778                 free(pcmHandle);
779                 pcmHandle = NULL;
780         }
781         debug_fleave();
782         return result;
783 }
784
785 EXPORT_API
786 int mm_sound_pcm_set_message_callback (MMSoundPcmHandle_t handle, MMMessageCallback callback, void *user_param)
787 {
788         mm_sound_pcm_t *pcmHandle =  (mm_sound_pcm_t*)handle;
789
790         if(pcmHandle == NULL || callback == NULL)
791                 return MM_ERROR_INVALID_ARGUMENT;
792
793         pcmHandle->msg_cb = callback;
794         pcmHandle->msg_cb_param = user_param;
795
796         debug_log ("set pcm message callback (%p,%p)\n", callback, user_param);
797
798         return MM_ERROR_NONE;
799 }
800
801
802 EXPORT_API
803 int mm_sound_pcm_play_open_ex (MMSoundPcmHandle_t *handle, const unsigned int rate, MMSoundPcmChannel_t channel, MMSoundPcmFormat_t format, int volume_config, ASM_sound_events_t asm_event)
804 {
805         avsys_audio_param_t param;
806         mm_sound_pcm_t *pcmHandle = NULL;
807         int size = 0;
808         int result = AVSYS_STATE_SUCCESS;
809         int errorcode = 0;
810         int volume_type = MM_SOUND_VOLUME_CONFIG_TYPE(volume_config);
811         int ret_mutex = 0;
812
813         debug_fenter();
814         memset(&param, 0, sizeof(avsys_audio_param_t));
815
816         /* Check input param */
817         if (volume_type < 0 || volume_type >= VOLUME_TYPE_MAX) {
818                 debug_error("Volume type is invalid %d\n", volume_type);
819                 return MM_ERROR_INVALID_ARGUMENT;
820         }
821         if (rate < _MIN_SYSTEM_SAMPLERATE || rate > _MAX_SYSTEM_SAMPLERATE) {
822                 debug_error("unsupported sample rate %u", rate);
823                 return MM_ERROR_SOUND_DEVICE_INVALID_SAMPLERATE;
824         } else {
825                 param.samplerate = rate;
826         }
827
828         switch(channel)
829         {
830         case MMSOUND_PCM_MONO:
831                 param.channels = 1;
832                 break;
833         case MMSOUND_PCM_STEREO:
834                 param.channels = 2;
835                 break;
836         default:
837                 debug_error("Unsupported channel type\n");
838                 return MM_ERROR_SOUND_DEVICE_INVALID_CHANNEL;
839         }
840
841         switch(format)
842         {
843         case MMSOUND_PCM_U8:
844                 param.format = AVSYS_AUDIO_FORMAT_8BIT;
845                 break;
846         case MMSOUND_PCM_S16_LE:
847                 param.format = AVSYS_AUDIO_FORMAT_16BIT;
848                 break;
849         default:
850                 debug_error("Unsupported format type\n");
851                 return MM_ERROR_SOUND_DEVICE_INVALID_FORMAT;
852         }
853
854         pcmHandle = calloc(sizeof(mm_sound_pcm_t),1);
855         if(pcmHandle == NULL)
856                 return MM_ERROR_OUT_OF_MEMORY;
857
858         ret_mutex = pthread_mutex_init(&pcmHandle->pcm_mutex_internal, NULL);
859         if(ret_mutex != 0)
860         {
861                 free(pcmHandle);
862                 return MM_ERROR_OUT_OF_MEMORY;
863         }
864
865         /* Register ASM */
866         debug_log ("session start : input asm_event = %d-------------\n", asm_event);
867         if (asm_event == ASM_EVENT_MONITOR) {
868                 debug_log ("Skip SESSION for event (%d)\n", asm_event);
869                 pcmHandle->skip_session = true;
870         } else if (asm_event == ASM_EVENT_NONE) {
871                 /* get session type */
872                 if(MM_ERROR_NONE != _get_asm_event_type(&pcmHandle->asm_event)) {
873                         debug_error ("_get_asm_event_type failed....\n");
874                         PCM_LOCK_DESTROY_INTERNAL(&pcmHandle->pcm_mutex_internal);
875                         free(pcmHandle);
876                         return MM_ERROR_POLICY_INTERNAL;
877                 }
878
879                 if(pcmHandle->asm_event != ASM_EVENT_CALL && pcmHandle->asm_event != ASM_EVENT_VIDEOCALL) {
880                         /* register asm */
881                         if(!ASM_register_sound(-1, &pcmHandle->asm_handle, pcmHandle->asm_event,
882                                         ASM_STATE_NONE, sound_pcm_asm_callback, (void*)pcmHandle, ASM_RESOURCE_NONE, &errorcode)) {
883                                 debug_error("ASM_register_sound() failed 0x%x\n", errorcode);
884                                 PCM_LOCK_DESTROY_INTERNAL(&pcmHandle->pcm_mutex_internal);
885                                 free(pcmHandle);
886                                 return MM_ERROR_POLICY_BLOCKED;
887                         }
888                 }
889         } else {
890                 /* register asm using asm_event input */
891                 if(!ASM_register_sound(-1, &pcmHandle->asm_handle, asm_event,
892                                 ASM_STATE_NONE, NULL, (void*)pcmHandle, ASM_RESOURCE_NONE, &errorcode)) {
893                         debug_error("ASM_register_sound() failed 0x%x\n", errorcode);
894                         PCM_LOCK_DESTROY_INTERNAL(&pcmHandle->pcm_mutex_internal);
895                         free(pcmHandle);
896                         return MM_ERROR_POLICY_BLOCKED;
897                 }
898         }
899
900         param.mode = AVSYS_AUDIO_MODE_OUTPUT;
901         param.vol_type = volume_config;
902         param.priority = AVSYS_AUDIO_PRIORITY_0;
903
904 //      avsys_audio_ampon();
905
906         /* Open */
907         debug_log ("avsys open -------------\n");
908         result = avsys_audio_open(&param, &pcmHandle->audio_handle, &size);
909         if(AVSYS_FAIL(result)) {
910                 debug_error("Device Open Error 0x%x\n", result);
911                 PCM_LOCK_DESTROY_INTERNAL(&pcmHandle->pcm_mutex_internal);
912                 free(pcmHandle);
913                 return MM_ERROR_SOUND_DEVICE_NOT_OPENED;
914         }
915
916         pcmHandle->is_playback = true;
917
918         /* Set handle to return */
919         *handle = (MMSoundPcmHandle_t)pcmHandle;
920         debug_fleave();
921         return size;
922 }
923
924 EXPORT_API
925 int mm_sound_pcm_play_open_no_session(MMSoundPcmHandle_t *handle, const unsigned int rate, MMSoundPcmChannel_t channel, MMSoundPcmFormat_t format)
926 {
927         return mm_sound_pcm_play_open_ex (handle, rate, channel, format, VOLUME_TYPE_SYSTEM, ASM_EVENT_MONITOR);
928 }
929
930 EXPORT_API
931 int mm_sound_pcm_play_open(MMSoundPcmHandle_t *handle, const unsigned int rate, MMSoundPcmChannel_t channel, MMSoundPcmFormat_t format, const volume_type_t vol_type)
932 {
933         return mm_sound_pcm_play_open_ex (handle, rate, channel, format, vol_type, ASM_EVENT_NONE);
934 }
935
936 EXPORT_API
937 int mm_sound_pcm_play_start(MMSoundPcmHandle_t handle)
938 {
939         int ret = 0;
940         debug_fenter();
941
942         ret = _pcm_sound_start (handle);
943
944         debug_fleave();
945         return ret;
946
947 }
948
949
950 EXPORT_API
951 int mm_sound_pcm_play_stop(MMSoundPcmHandle_t handle)
952 {
953         int ret = 0;
954         debug_fenter();
955
956         ret = _pcm_sound_stop(handle);
957
958         debug_fleave();
959         return ret;
960 }
961
962
963 EXPORT_API
964 int mm_sound_pcm_play_write(MMSoundPcmHandle_t handle, void* ptr, unsigned int length_byte)
965 {
966         int ret = 0;
967         mm_sound_pcm_t *pcmHandle = (mm_sound_pcm_t*)handle;
968
969         /* Check input param */
970         if(pcmHandle == NULL) {
971                 debug_error ("Handle is null, return Invalid Argument\n");
972                 ret = MM_ERROR_INVALID_ARGUMENT;
973                 goto NULL_HANDLE;
974         }
975
976         PCM_LOCK_INTERNAL(&pcmHandle->pcm_mutex_internal);
977
978         if(ptr == NULL) {
979                 debug_error("Invalid buffer pointer\n");
980                 ret = MM_ERROR_SOUND_INVALID_POINTER;
981                 goto EXIT;
982         }
983         if(length_byte == 0 ) {
984                 debug_error ("length is 0, return 0\n");
985                 ret = 0;
986                 goto EXIT;
987         }
988
989         /* Check State : return fail if not started */
990         if (!pcmHandle->is_started) {
991                 /* not started, return fail */
992                 debug_error ("Not started yet, return Invalid State \n");
993                 ret = MM_ERROR_SOUND_INVALID_STATE;
994                 goto EXIT;
995         }
996
997         /* Write */
998         ret = avsys_audio_write(pcmHandle->audio_handle, ptr, length_byte);
999
1000 EXIT:   
1001         PCM_UNLOCK_INTERNAL(&pcmHandle->pcm_mutex_internal);
1002 NULL_HANDLE:
1003         return ret;
1004 }
1005
1006 EXPORT_API
1007 int mm_sound_pcm_play_close(MMSoundPcmHandle_t handle)
1008 {
1009         int result = MM_ERROR_NONE;
1010         mm_sound_pcm_t *pcmHandle = (mm_sound_pcm_t*)handle;
1011         int errorcode = 0;
1012
1013         debug_fenter();
1014         /* Check input param */
1015         if(pcmHandle == NULL) {
1016                 debug_error ("Handle is null, return Invalid Argument\n");
1017                 result = MM_ERROR_INVALID_ARGUMENT;
1018                 goto NULL_HANDLE;
1019         }
1020         PCM_LOCK_INTERNAL(&pcmHandle->pcm_mutex_internal);
1021         /* Drain if needed */
1022         if (pcmHandle->is_started) {
1023                 /* stop() is not called before close(), drain is needed */
1024                 if(AVSYS_FAIL(avsys_audio_drain(pcmHandle->audio_handle))) {
1025                         debug_error("drain failed\n");
1026                         result = MM_ERROR_SOUND_INTERNAL;
1027                         goto EXIT;
1028                 }
1029         }
1030         pcmHandle->is_started = false;
1031         /* Close */
1032         result = avsys_audio_close(pcmHandle->audio_handle);
1033         if(AVSYS_FAIL(result)) {
1034                 debug_error("handle close failed 0x%X", result);
1035                 result = MM_ERROR_SOUND_INTERNAL;
1036                 goto EXIT;
1037         }
1038
1039         if (pcmHandle->skip_session == false) {
1040                 /* Unregister ASM */
1041                 if(pcmHandle->asm_event != ASM_EVENT_CALL && pcmHandle->asm_event != ASM_EVENT_VIDEOCALL) {
1042                         if(!ASM_unregister_sound(pcmHandle->asm_handle, pcmHandle->asm_event, &errorcode)) {
1043                                 debug_error("ASM_unregister failed in %s with 0x%x\n",__func__, errorcode);
1044                                 result = MM_ERROR_SOUND_INTERNAL;
1045                                 goto EXIT;
1046                         }
1047                 }
1048         }
1049
1050         debug_log ("pcm play sound [%p] closed success!!!\n", handle);
1051
1052
1053 EXIT:
1054         PCM_UNLOCK_INTERNAL(&pcmHandle->pcm_mutex_internal);
1055 NULL_HANDLE:
1056         if (pcmHandle) {
1057                 /* Free handle */
1058                 PCM_LOCK_DESTROY_INTERNAL(&pcmHandle->pcm_mutex_internal);
1059                 free(pcmHandle);
1060                 pcmHandle= NULL;
1061         }
1062         debug_fleave();
1063         return result;
1064 }
1065
1066 ///////////////////////////////////
1067 ////     MMSOUND PLAY APIs
1068 ///////////////////////////////////
1069 static inline void _mm_sound_fill_play_param(MMSoundPlayParam *param, const char *filename, int volume_config, mm_sound_stop_callback_func callback, void *data, int priority, int handle_route)
1070 {
1071         param->filename = filename;
1072         param->volume = 0; //volume value dose not effect anymore
1073         param->callback = callback;
1074         param->data = data;
1075         param->loop = 1;
1076         param->volume_config = volume_config;
1077         param->priority = priority;
1078         param->handle_route = handle_route;
1079 }
1080
1081 EXPORT_API
1082 int mm_sound_play_loud_solo_sound_no_restore(const char *filename, int volume_config, mm_sound_stop_callback_func callback, void *data, int *handle)
1083 {
1084         MMSoundPlayParam param = { 0, };
1085
1086         _mm_sound_fill_play_param(&param, filename, volume_config, callback, data, AVSYS_AUDIO_PRIORITY_SOLO, MM_SOUND_HANDLE_ROUTE_SPEAKER_NO_RESTORE);
1087         return mm_sound_play_sound_ex(&param, handle);
1088 }
1089
1090 EXPORT_API
1091 int mm_sound_play_loud_solo_sound(const char *filename, int volume_config, mm_sound_stop_callback_func callback, void *data, int *handle)
1092 {
1093         MMSoundPlayParam param = { 0, };
1094
1095         _mm_sound_fill_play_param(&param, filename, volume_config, callback, data, AVSYS_AUDIO_PRIORITY_SOLO, MM_SOUND_HANDLE_ROUTE_SPEAKER);
1096         return mm_sound_play_sound_ex(&param, handle);
1097 }
1098
1099 EXPORT_API
1100 int mm_sound_play_solo_sound(const char *filename, int volume_config, mm_sound_stop_callback_func callback, void *data, int *handle)
1101 {
1102         MMSoundPlayParam param = { 0, };
1103
1104         _mm_sound_fill_play_param(&param, filename, volume_config, callback, data, AVSYS_AUDIO_PRIORITY_SOLO, MM_SOUND_HANDLE_ROUTE_USING_CURRENT);
1105         return mm_sound_play_sound_ex(&param, handle);
1106 }
1107
1108 EXPORT_API
1109 int mm_sound_play_sound(const char *filename, int volume_config, mm_sound_stop_callback_func callback, void *data, int *handle)
1110 {
1111         MMSoundPlayParam param = { 0, };
1112
1113         _mm_sound_fill_play_param(&param, filename, volume_config, callback, data, AVSYS_AUDIO_PRIORITY_NORMAL, MM_SOUND_HANDLE_ROUTE_USING_CURRENT);
1114         return mm_sound_play_sound_ex(&param, handle);
1115 }
1116
1117 EXPORT_API
1118 int mm_sound_play_sound_ex(MMSoundPlayParam *param, int *handle)
1119 {
1120         int err;
1121         int lhandle = -1;
1122         int volume_type = MM_SOUND_VOLUME_CONFIG_TYPE(param->volume_config);
1123
1124         debug_fenter();
1125
1126         /* Check input param */
1127         if (param == NULL) {
1128                 debug_error("param is null\n");
1129                 return MM_ERROR_INVALID_ARGUMENT;
1130         }
1131         if (param->filename == NULL) {
1132                 debug_error("filename is NULL\n");
1133                 return MM_ERROR_SOUND_FILE_NOT_FOUND;
1134         }
1135         if (volume_type < 0 || volume_type >= VOLUME_TYPE_MAX) {
1136                 debug_error("Volume type is invalid %d\n", volume_type);
1137                 return MM_ERROR_INVALID_ARGUMENT;
1138         }
1139
1140         /* Play sound */
1141         err = MMSoundClientPlaySound(param, 0, 0, &lhandle);
1142         if (err < 0) {
1143                 debug_error("Failed to play sound\n");
1144                 return err;
1145         }
1146
1147         /* Set handle to return */
1148         if (handle) {
1149                 *handle = lhandle;
1150         } else {
1151                 debug_critical("The sound hadle cannot be get [%d]\n", lhandle);
1152         }
1153
1154         debug_fleave();
1155         return MM_ERROR_NONE;
1156 }
1157
1158
1159 EXPORT_API
1160 int mm_sound_stop_sound(int handle)
1161 {
1162         int err;
1163
1164         debug_fenter();
1165
1166         /* Stop sound */
1167         err = MMSoundClientStopSound(handle);
1168         if (err < 0) {
1169                 debug_error("Fail to stop sound\n");
1170                 return err;
1171         }
1172
1173         debug_fleave();
1174         return MM_ERROR_NONE;
1175 }
1176
1177 ///////////////////////////////////
1178 ////     MMSOUND TONE APIs
1179 ///////////////////////////////////
1180 EXPORT_API
1181 int mm_sound_play_tone (MMSoundTone_t num, int volume_config, const double volume, const int duration, int *handle)
1182 {
1183         int lhandle = -1;
1184         int err = MM_ERROR_NONE;
1185         int volume_type = MM_SOUND_VOLUME_CONFIG_TYPE(volume_config);
1186
1187         debug_fenter();
1188
1189         /* Check input param */
1190         if (duration < -1) {
1191                 debug_error("number is invalid %d\n", duration);
1192                 return MM_ERROR_INVALID_ARGUMENT;
1193         }
1194         if (num < MM_SOUND_TONE_DTMF_0 || num >= MM_SOUND_TONE_NUM) {
1195                 debug_error("TONE Value is invalid %d\n", num);
1196                 return MM_ERROR_INVALID_ARGUMENT;
1197         }
1198         if (volume_type < 0 || volume_type >= VOLUME_TYPE_MAX) {
1199                 debug_error("Volume type is invalid %d\n", volume_type);
1200                 return MM_ERROR_INVALID_ARGUMENT;
1201         }
1202         if (volume < 0.0 || volume > 1.0) {
1203                 debug_error("Volume Value is invalid %d\n", volume);
1204                 return MM_ERROR_INVALID_ARGUMENT;
1205         }
1206
1207         /* Play tone */
1208         debug_msg("Call MMSoundClientPlayTone\n");
1209         err = MMSoundClientPlayTone(num, volume_config, volume, duration, &lhandle);
1210         if (err < 0) {
1211                 debug_error("Failed to play sound\n");
1212                 return err;
1213         }
1214
1215         /* Set handle to return */
1216         if (handle)
1217                 *handle = lhandle;
1218         else
1219                 debug_critical("The sound handle cannot be get [%d]\n", lhandle);
1220
1221         debug_fleave();
1222         return MM_ERROR_NONE;
1223 }
1224
1225 ///////////////////////////////////
1226 ////     MMSOUND ROUTING APIs
1227 ///////////////////////////////////
1228 EXPORT_API
1229 int mm_sound_set_path(int gain, int output, int input, int option)
1230 {
1231         int err;
1232
1233         debug_fenter();
1234
1235         debug_msg("gain: 0x%02X, output: %d, input: %d, option: 0x%x\n", gain, output, input, option);
1236
1237         err = avsys_audio_set_path_ex( gain, output, input, option);
1238         if (err < 0) {
1239                 debug_error("avsys_audio_set_path() failed\n");
1240                 return MM_ERROR_SOUND_INTERNAL;
1241         }
1242
1243         debug_fleave();
1244         return MM_ERROR_NONE;
1245 }
1246
1247 EXPORT_API
1248 int mm_sound_get_path(int *gain, int *output, int *input, int *option)
1249 {
1250         int err;
1251
1252         debug_fenter();
1253
1254         err = avsys_audio_get_path_ex( gain, output, input, option);
1255         if (err < 0) {
1256                 debug_error("SoundCtlPathGet() failed\n");
1257                 return MM_ERROR_SOUND_INTERNAL;
1258         }
1259
1260         debug_msg("gain: 0x%02X, output: %d, input: %d, option: 0x%x\n", *gain, *output, *input, *option);
1261
1262         debug_fleave();
1263         return MM_ERROR_NONE;
1264 }
1265
1266 #ifdef PULSE_CLIENT
1267 enum {
1268         USE_PA_SINK_ALSA = 0,
1269         USE_PA_SINK_A2DP,
1270 };
1271 EXPORT_API
1272 int mm_sound_route_set_system_policy (system_audio_route_t route)
1273 {
1274         return MM_ERROR_NONE;
1275 }
1276
1277
1278 EXPORT_API
1279 int mm_sound_route_get_system_policy (system_audio_route_t *route)
1280 {
1281         return MM_ERROR_NONE;
1282 }
1283
1284
1285 EXPORT_API
1286 int mm_sound_route_get_a2dp_status (bool *connected, char **bt_name)
1287 {
1288         int ret = MM_ERROR_NONE;
1289
1290         debug_fenter();
1291
1292         if (connected == NULL || bt_name == NULL) {
1293                 debug_error ("argument is not valid\n");
1294                 return MM_ERROR_INVALID_ARGUMENT; 
1295         } 
1296
1297         ret = MMSoundClientIsBtA2dpOn (connected, bt_name);
1298         debug_msg ("connected=[%d] bt_name[%s]\n", *connected, *bt_name);
1299         if (ret < 0) {
1300                 debug_error("MMSoundClientIsBtA2dpOn() Failed\n");
1301                 return ret;
1302         }
1303
1304         debug_fleave();
1305
1306         return ret;
1307 }
1308
1309 EXPORT_API
1310 int mm_sound_route_get_playing_device(system_audio_route_device_t *dev)
1311 {
1312         mm_sound_device_in device_in = MM_SOUND_DEVICE_IN_NONE;
1313         mm_sound_device_out device_out = MM_SOUND_DEVICE_OUT_NONE;
1314
1315         if(!dev)
1316                 return MM_ERROR_INVALID_ARGUMENT;
1317
1318         if(MM_ERROR_NONE != mm_sound_get_active_device(&device_in, &device_out)) {
1319                 debug_error("Can not get active device info\n");
1320                 return MM_ERROR_SOUND_INTERNAL;
1321         }
1322
1323         switch(device_out)
1324         {
1325         case MM_SOUND_DEVICE_OUT_SPEAKER:
1326                 *dev = SYSTEM_AUDIO_ROUTE_PLAYBACK_DEVICE_HANDSET;
1327                 break;
1328         case MM_SOUND_DEVICE_OUT_BT_A2DP:
1329                 *dev = SYSTEM_AUDIO_ROUTE_PLAYBACK_DEVICE_BLUETOOTH;
1330                 break;
1331         case MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY:
1332                 *dev = SYSTEM_AUDIO_ROUTE_PLAYBACK_DEVICE_EARPHONE;
1333                 break;
1334         default:
1335                 *dev = SYSTEM_AUDIO_ROUTE_PLAYBACK_DEVICE_NONE;
1336                 break;
1337         }
1338
1339         return MM_ERROR_NONE;
1340 }
1341
1342 EXPORT_API
1343 int mm_sound_route_add_change_callback(audio_route_policy_changed_callback_fn func, void *user_data)
1344 {
1345         /* Deprecated */
1346         return MM_ERROR_NONE;
1347 }
1348
1349 EXPORT_API
1350 int mm_sound_route_remove_change_callback()
1351 {
1352         /* Deprecated */
1353         return MM_ERROR_NONE;
1354 }
1355
1356 #endif /* PULSE_CLIENT */
1357
1358 EXPORT_API
1359 int mm_sound_system_get_capture_status(system_audio_capture_status_t *status)
1360 {
1361         int err = AVSYS_STATE_SUCCESS;
1362         int on_capture = 0;
1363
1364         if(!status)
1365                 return MM_ERROR_INVALID_ARGUMENT;
1366
1367         err = avsys_audio_get_capture_status(&on_capture);
1368         if(err < 0) {
1369                 debug_error("Can not get capture status with 0x%x\n", err);
1370                 return MM_ERROR_SOUND_INTERNAL;
1371         }
1372
1373         if(on_capture)
1374                 *status = SYSTEM_AUDIO_CAPTURE_ACTIVE;
1375         else
1376                 *status = SYSTEM_AUDIO_CAPTURE_NONE;
1377
1378         return MM_ERROR_NONE;
1379 }
1380
1381 EXPORT_API
1382 int mm_sound_is_route_available(mm_sound_route route, bool *is_available)
1383 {
1384         int ret = MM_ERROR_NONE;
1385
1386         debug_fenter();
1387
1388         if (!_mm_sound_is_route_valid(route)) {
1389                 debug_error("route is invalid %d\n", route);
1390                 return MM_ERROR_INVALID_ARGUMENT;
1391         }
1392         if (!is_available)
1393         {
1394                 debug_error("is_available is invalid\n");
1395                 return MM_ERROR_INVALID_ARGUMENT;
1396         }
1397
1398         ret = _mm_sound_client_is_route_available(route, is_available);
1399         if (ret < 0) {
1400                 debug_error("Can not check given route is available\n");
1401         }
1402
1403         debug_fleave();
1404         return ret;
1405 }
1406
1407 EXPORT_API
1408 int mm_sound_foreach_available_route_cb(mm_sound_available_route_cb available_route_cb, void *user_data)
1409 {
1410         int ret = MM_ERROR_NONE;
1411
1412         debug_fenter();
1413
1414         if (!available_route_cb)
1415         {
1416                 debug_error("available_route_cb is invalid\n");
1417                 return MM_ERROR_INVALID_ARGUMENT;
1418         }
1419
1420         ret = _mm_sound_client_foreach_available_route_cb(available_route_cb, user_data);
1421         if (ret < 0) {
1422                 debug_error("Can not set foreach available route callback\n");
1423         }
1424
1425         debug_fleave();
1426         return ret;
1427 }
1428
1429 EXPORT_API
1430 int mm_sound_set_active_route(mm_sound_route route)
1431 {
1432         int ret = MM_ERROR_NONE;
1433
1434         debug_fenter();
1435
1436         if (!_mm_sound_is_route_valid(route)) {
1437                 debug_error("route is invalid %d\n", route);
1438                 return MM_ERROR_INVALID_ARGUMENT;
1439         }
1440
1441         ret = _mm_sound_client_set_active_route(route);
1442         if (ret < 0) {
1443                 debug_error("Can not set active route\n");
1444         }
1445
1446         debug_fleave();
1447         return ret;
1448 }
1449
1450
1451 EXPORT_API
1452 int mm_sound_get_active_device(mm_sound_device_in *device_in, mm_sound_device_out *device_out)
1453 {
1454         int ret = MM_ERROR_NONE;
1455
1456         debug_fenter();
1457
1458         if (device_in == NULL || device_out == NULL) {
1459                 debug_error("argument is not valid\n");
1460                 return MM_ERROR_INVALID_ARGUMENT;
1461         }
1462
1463         ret = _mm_sound_client_get_active_device(device_in, device_out);
1464         if (ret < 0) {
1465                 debug_error("Can not add active device callback\n");
1466         }
1467
1468         debug_fleave();
1469         return ret;
1470 }
1471
1472 EXPORT_API
1473 int mm_sound_add_active_device_changed_callback(mm_sound_active_device_changed_cb func, void *user_data)
1474 {
1475         int ret = MM_ERROR_NONE;
1476
1477         debug_fenter();
1478
1479         if (func == NULL) {
1480                 debug_error("argument is not valid\n");
1481                 return MM_ERROR_INVALID_ARGUMENT;
1482         }
1483
1484         ret = _mm_sound_client_add_active_device_changed_callback(func, user_data);
1485         if (ret < 0) {
1486                 debug_error("Can not add active device changed callback\n");
1487         }
1488
1489         debug_fleave();
1490         return ret;
1491 }
1492
1493 EXPORT_API
1494 int mm_sound_remove_active_device_changed_callback(void)
1495 {
1496         int ret = MM_ERROR_NONE;
1497
1498         debug_fenter();
1499
1500         ret = _mm_sound_client_remove_active_device_changed_callback();
1501         if (ret < 0) {
1502                 debug_error("Can not remove active device changed callback\n");
1503         }
1504
1505         debug_fleave();
1506         return ret;
1507 }
1508
1509 EXPORT_API
1510 int mm_sound_add_available_route_changed_callback(mm_sound_available_route_changed_cb func, void *user_data)
1511 {
1512         int ret = MM_ERROR_NONE;
1513
1514         debug_fenter();
1515
1516         if (func == NULL) {
1517                 debug_error("argument is not valid\n");
1518                 return MM_ERROR_INVALID_ARGUMENT;
1519         }
1520
1521         ret = _mm_sound_client_add_available_route_changed_callback(func, user_data);
1522         if (ret < 0) {
1523                 debug_error("Can not add available route changed callback\n");
1524         }
1525
1526         debug_fleave();
1527         return ret;
1528 }
1529
1530 EXPORT_API
1531 int mm_sound_remove_available_route_changed_callback(void)
1532 {
1533         int ret = MM_ERROR_NONE;
1534
1535         debug_fenter();
1536
1537         ret = _mm_sound_client_remove_available_route_changed_callback();
1538         if (ret < 0) {
1539                 debug_error("Can not remove available route changed callback\n");
1540         }
1541
1542         debug_fleave();
1543         return ret;
1544 }
1545
1546 __attribute__ ((destructor))
1547 void __mmfsnd_finalize(void)
1548 {
1549         debug_fenter();
1550
1551         MMSoundClientCallbackFini();
1552
1553         debug_fleave();
1554 }
1555
1556 __attribute__ ((constructor))
1557 void __mmfsnd_initialize(void)
1558 {
1559         /* Will be Fixed */
1560 }