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