4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Seungbae Shin <seungbae.shin@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
27 #include <sys/types.h>
37 #include <mm_message.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"
47 #include <audio-session-manager.h>
48 #include <mm_session.h>
49 #include <mm_session_private.h>
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
58 volume_callback_fn func;
63 volume_cb_param g_volume_param[VOLUME_TYPE_MAX];
65 static pthread_mutex_t _volume_mutex = PTHREAD_MUTEX_INITIALIZER;
68 avsys_handle_t audio_handle;
70 ASM_sound_events_t asm_event;
75 MMMessageCallback msg_cb;
81 static int _pcm_sound_start (MMSoundPcmHandle_t handle);
82 static int _pcm_sound_stop_internal (MMSoundPcmHandle_t handle);
83 static int _pcm_sound_stop(MMSoundPcmHandle_t handle);
85 static void __sound_pcm_send_message (mm_sound_pcm_t *pcmHandle, int message, int code);
87 int _validate_volume(volume_type_t type, int value)
94 case VOLUME_TYPE_CALL:
95 if (value >= AVSYS_AUDIO_VOLUME_MAX_BASIC) {
99 case VOLUME_TYPE_SYSTEM:
100 case VOLUME_TYPE_MEDIA:
101 case VOLUME_TYPE_ALARM:
102 case VOLUME_TYPE_EXT_JAVA:
103 case VOLUME_TYPE_NOTIFICATION:
104 case VOLUME_TYPE_RINGTONE:
105 if (value >= AVSYS_AUDIO_VOLUME_MAX_MULTIMEDIA) {
109 case VOLUME_TYPE_EXT_ANDROID:
110 if (value >= AVSYS_AUDIO_VOLUME_MAX_SINGLE) {
121 void volume_changed_cb(keynode_t* node, void* data)
123 volume_cb_param* param = (volume_cb_param*) data;
125 debug_msg("%s changed callback called\n",vconf_keynode_get_name(node));
127 MMSOUND_ENTER_CRITICAL_SECTION( &_volume_mutex )
129 if(param && (param->func != NULL)) {
130 debug_msg("funcion 0x%x\n", param->func);
131 ((volume_callback_fn)param->func)(param->data);
134 MMSOUND_LEAVE_CRITICAL_SECTION( &_volume_mutex )
138 int mm_sound_volume_add_callback(volume_type_t type, volume_callback_fn func, void* user_data)
140 char *keystr[] = {VCONF_KEY_VOLUME_TYPE_SYSTEM, VCONF_KEY_VOLUME_TYPE_NOTIFICATION, VCONF_KEY_VOLUME_TYPE_ALARM,
141 VCONF_KEY_VOLUME_TYPE_RINGTONE, VCONF_KEY_VOLUME_TYPE_MEDIA, VCONF_KEY_VOLUME_TYPE_CALL,
142 VCONF_KEY_VOLUME_TYPE_ANDROID,VCONF_KEY_VOLUME_TYPE_JAVA};
146 /* Check input param */
147 if(type < VOLUME_TYPE_SYSTEM || type >=VOLUME_TYPE_MAX) {
148 return MM_ERROR_INVALID_ARGUMENT;
151 debug_warning("callback function is null\n");
152 return MM_ERROR_INVALID_ARGUMENT;
155 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN( &_volume_mutex, MM_ERROR_SOUND_INTERNAL )
157 g_volume_param[type].func = func;
158 g_volume_param[type].data = user_data;
159 g_volume_param[type].type = type;
161 MMSOUND_LEAVE_CRITICAL_SECTION( &_volume_mutex )
163 return vconf_notify_key_changed(keystr[type], volume_changed_cb, (void*)&g_volume_param[type]);
167 int mm_sound_volume_remove_callback(volume_type_t type)
169 char *keystr[] = {VCONF_KEY_VOLUME_TYPE_SYSTEM, VCONF_KEY_VOLUME_TYPE_NOTIFICATION, VCONF_KEY_VOLUME_TYPE_ALARM,
170 VCONF_KEY_VOLUME_TYPE_RINGTONE, VCONF_KEY_VOLUME_TYPE_MEDIA, VCONF_KEY_VOLUME_TYPE_CALL,
171 VCONF_KEY_VOLUME_TYPE_ANDROID,VCONF_KEY_VOLUME_TYPE_JAVA};
174 if(type < VOLUME_TYPE_SYSTEM || type >=VOLUME_TYPE_MAX) {
175 return MM_ERROR_INVALID_ARGUMENT;
178 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN( &_volume_mutex, MM_ERROR_SOUND_INTERNAL )
180 g_volume_param[type].func = NULL;
181 g_volume_param[type].data = NULL;
182 g_volume_param[type].type = type;
184 MMSOUND_LEAVE_CRITICAL_SECTION( &_volume_mutex )
186 return vconf_ignore_key_changed(keystr[type], volume_changed_cb);
190 int mm_sound_get_volume_step(volume_type_t type, int *step)
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);
198 int mm_sound_volume_get_step(volume_type_t type, int *step)
204 /* Check input param */
206 debug_error("second parameter is null\n");
207 return MM_ERROR_INVALID_ARGUMENT;
209 if(type < VOLUME_TYPE_SYSTEM || type >= VOLUME_TYPE_MAX) {
210 debug_error("Invalid type value %d\n", (int)type);
211 return MM_ERROR_INVALID_ARGUMENT;
214 err = avsys_audio_get_volume_max_ex((int)type, step);
215 if (AVSYS_FAIL(err)) {
216 err = MM_ERROR_INVALID_ARGUMENT;
220 return MM_ERROR_NONE;
224 int mm_sound_volume_set_value(volume_type_t type, const unsigned int value)
226 int ret = MM_ERROR_NONE;
227 char *keystr[] = {VCONF_KEY_VOLUME_TYPE_SYSTEM, VCONF_KEY_VOLUME_TYPE_NOTIFICATION, VCONF_KEY_VOLUME_TYPE_ALARM,
228 VCONF_KEY_VOLUME_TYPE_RINGTONE, VCONF_KEY_VOLUME_TYPE_MEDIA, VCONF_KEY_VOLUME_TYPE_CALL,
229 VCONF_KEY_VOLUME_TYPE_ANDROID,VCONF_KEY_VOLUME_TYPE_JAVA};
231 #ifdef SEPARATE_EARPHONE_VOLUME
232 system_audio_route_device_t dev = 0;
237 /* Check input param */
238 if (0 > _validate_volume(type, (int)value)) {
239 debug_error("invalid volume type %d, value %u\n", type, value);
240 return MM_ERROR_INVALID_ARGUMENT;
243 #ifdef SEPARATE_EARPHONE_VOLUME
244 /* Get volume value from VCONF */
245 if (vconf_get_int(keystr[type], &vconf_value)){
246 debug_error("Can not get %s as %d\n", keystr[type], vconf_value);
247 return MM_ERROR_SOUND_INTERNAL;
250 /* Calculate volume value of current device */
251 mm_sound_route_get_playing_device(&dev);
252 if (dev == SYSTEM_AUDIO_ROUTE_PLAYBACK_DEVICE_EARPHONE) {
253 vconf_value = 0x10000 | (vconf_value & 0x00FF) | (value << 8);
254 debug_log("volume_set_value [earphone] %d(0x%04x)", value, vconf_value);
256 vconf_value = (vconf_value & 0xFF00) | value;
257 debug_log("volume_set_value [speaker] %d(0x%04x)", value, vconf_value);
263 /* Set volume value to VCONF */
264 if (vconf_set_int(keystr[type], vconf_value)) {
265 debug_error("Can not set %s as %d\n", keystr[type], vconf_value);
266 ret = MM_ERROR_SOUND_INTERNAL;
268 /* update shared memory value */
269 ret = avsys_audio_set_volume_by_type(type, value);
270 if (AVSYS_FAIL(ret)) {
271 debug_error("Can not set volume to shared memory 0x%x\n", ret);
280 int mm_sound_volume_get_value(volume_type_t type, unsigned int *value)
282 int ret = MM_ERROR_NONE;
283 char *keystr[] = {VCONF_KEY_VOLUME_TYPE_SYSTEM, VCONF_KEY_VOLUME_TYPE_NOTIFICATION, VCONF_KEY_VOLUME_TYPE_ALARM,
284 VCONF_KEY_VOLUME_TYPE_RINGTONE, VCONF_KEY_VOLUME_TYPE_MEDIA, VCONF_KEY_VOLUME_TYPE_CALL,
285 VCONF_KEY_VOLUME_TYPE_ANDROID,VCONF_KEY_VOLUME_TYPE_JAVA};
287 #ifdef SEPARATE_EARPHONE_VOLUME
288 system_audio_route_device_t dev = 0;
293 /* Check input param */
295 return MM_ERROR_INVALID_ARGUMENT;
296 if (type < 0 || type >= VOLUME_TYPE_MAX) {
297 debug_error("invalid volume type value %d\n", type);
298 return MM_ERROR_INVALID_ARGUMENT;
301 /* Get volume value from VCONF */
302 if (vconf_get_int(keystr[type], &vconf_value)) {
303 debug_error("Can not get value of %s\n", keystr[type]);
304 ret = MM_ERROR_SOUND_INTERNAL;
307 #ifdef SEPARATE_EARPHONE_VOLUME
308 /* Get volume value of current device */
309 mm_sound_route_get_playing_device(&dev);
310 if (dev == SYSTEM_AUDIO_ROUTE_PLAYBACK_DEVICE_EARPHONE) {
311 *value = (vconf_value >> 8) & 0x00FF;
312 debug_log("volume_get_value [earphone] %d(0x%04x)", *value, vconf_value);
314 *value = vconf_value & 0x00FF;
315 debug_log("volume_get_value [speaker] %d(0x%04x)", *value, vconf_value);
318 *value = vconf_value;
326 int mm_sound_volume_primary_type_set(volume_type_t type)
329 int ret = MM_ERROR_NONE;
331 /* Check input param */
332 if(type < VOLUME_TYPE_SYSTEM || type >= VOLUME_TYPE_MAX)
333 return MM_ERROR_INVALID_ARGUMENT;
338 if(AVSYS_FAIL(avsys_audio_set_primary_volume((int)mypid, type))) {
339 debug_error("Can not set primary volume [%d, %d]\n", mypid, type);
340 ret = MM_ERROR_SOUND_INTERNAL;
348 int mm_sound_volume_primary_type_clear()
351 int ret = MM_ERROR_NONE;
356 if(AVSYS_FAIL(avsys_audio_clear_primary_volume((int)mypid))) {
357 debug_error("Can not clear primary volume [%d]\n", mypid);
358 ret = MM_ERROR_SOUND_INTERNAL;
366 int mm_sound_volume_get_current_playing_type(volume_type_t *type)
368 int result = AVSYS_STATE_SUCCESS;
369 int voltype = AVSYS_AUDIO_VOLUME_TYPE_SYSTEM;
373 /* Check input param */
375 return MM_ERROR_INVALID_ARGUMENT;
378 result = avsys_audio_get_current_playing_volume_type(&voltype);
379 if(result == AVSYS_STATE_SUCCESS) {
381 return MM_ERROR_NONE;
382 } else if(result ==AVSYS_STATE_ERR_ALLOCATION ) {
383 return MM_ERROR_SOUND_VOLUME_NO_INSTANCE;
384 } else if(result == AVSYS_STATE_ERR_INVALID_MODE) {
385 return MM_ERROR_SOUND_VOLUME_CAPTURE_ONLY;
387 return MM_ERROR_SOUND_INTERNAL;
391 ///////////////////////////////////
392 //// MMSOUND PCM APIs
393 ///////////////////////////////////
396 int _get_asm_event_type(ASM_sound_events_t *type)
398 int sessionType = MM_SESSION_TYPE_SHARE;
399 ASM_sound_events_t asm_event;
402 return MM_ERROR_SOUND_INVALID_POINTER;
404 /* read session type */
405 if(_mm_session_util_read_type(-1, &sessionType) < 0) {
406 debug_log("Read Session Type failed. Set default \"Share\" type\n");
407 sessionType = MM_SESSION_TYPE_SHARE;
408 if(mm_session_init(sessionType) < 0) {
409 debug_error("mm_session_init() failed\n");
410 return MM_ERROR_SOUND_INTERNAL;
414 /* convert MM_SESSION_TYPE to ASM_EVENT_TYPE */
417 case MM_SESSION_TYPE_SHARE:
418 asm_event = ASM_EVENT_SHARE_MMSOUND;
420 case MM_SESSION_TYPE_EXCLUSIVE:
421 asm_event = ASM_EVENT_EXCLUSIVE_MMSOUND;
423 case MM_SESSION_TYPE_NOTIFY:
424 asm_event = ASM_EVENT_NOTIFY;
426 case MM_SESSION_TYPE_ALARM:
427 asm_event = ASM_EVENT_ALARM;
429 case MM_SESSION_TYPE_CALL:
430 asm_event = ASM_EVENT_CALL;
432 case MM_SESSION_TYPE_VIDEOCALL:
433 asm_event = ASM_EVENT_VIDEOCALL;
436 debug_error("Unexpected %d\n", sessionType);
437 return MM_ERROR_SOUND_INTERNAL;
441 return MM_ERROR_NONE;
444 static void __sound_pcm_send_message (mm_sound_pcm_t *pcmHandle, int message, int code)
447 if (pcmHandle->msg_cb) {
448 MMMessageParamType msg;
449 msg.union_type = MM_MSG_UNION_CODE;
452 debug_log ("calling msg callback(%p) with message(%d), code(%d), msg callback param(%p)\n",
453 pcmHandle->msg_cb, message, msg.code, pcmHandle->msg_cb_param);
454 ret = pcmHandle->msg_cb(message, &msg, pcmHandle->msg_cb_param);
455 debug_log ("msg callback returned (%d)\n", ret);
457 debug_log ("No pcm msg callback\n");
461 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)
463 mm_sound_pcm_t *pcmHandle = NULL;
464 ASM_cb_result_t cb_res = ASM_CB_RES_IGNORE;
466 /* Check input param */
467 pcmHandle = (mm_sound_pcm_t *)cb_data;
468 if(pcmHandle == NULL) {
469 debug_error("sound_pcm_asm_callback cb_data is null\n");
473 debug_log ("command = %d, handle = %p, is_started = %d\n",command, pcmHandle, pcmHandle->is_started);
476 case ASM_COMMAND_STOP:
478 _pcm_sound_stop_internal (pcmHandle);
479 cb_res = ASM_CB_RES_PAUSE;
482 case ASM_COMMAND_RESUME:
483 cb_res = ASM_CB_RES_IGNORE;
486 case ASM_COMMAND_PAUSE:
487 case ASM_COMMAND_PLAY:
488 case ASM_COMMAND_NONE:
489 debug_error ("Not an expected case!!!!\n");
493 /* execute user callback if callback available */
494 __sound_pcm_send_message (pcmHandle, MM_MESSAGE_SOUND_PCM_INTERRUPTED, event_src);
500 int mm_sound_pcm_capture_open(MMSoundPcmHandle_t *handle, const unsigned int rate, MMSoundPcmChannel_t channel, MMSoundPcmFormat_t format)
502 avsys_audio_param_t param;
503 mm_sound_pcm_t *pcmHandle = NULL;
505 int result = AVSYS_STATE_SUCCESS;
509 memset(¶m, 0, sizeof(avsys_audio_param_t));
512 if (rate < _MIN_SYSTEM_SAMPLERATE || rate > _MAX_SYSTEM_SAMPLERATE) {
513 debug_error("unsupported sample rate %u", rate);
514 return MM_ERROR_SOUND_DEVICE_INVALID_SAMPLERATE;
516 param.samplerate = rate;
521 case MMSOUND_PCM_MONO:
524 case MMSOUND_PCM_STEREO:
529 debug_error("Unsupported channel type\n");
530 return MM_ERROR_SOUND_DEVICE_INVALID_CHANNEL;
536 param.format = AVSYS_AUDIO_FORMAT_8BIT;
538 case MMSOUND_PCM_S16_LE:
539 param.format = AVSYS_AUDIO_FORMAT_16BIT;
542 debug_error("Unsupported format type\n");
543 return MM_ERROR_SOUND_DEVICE_INVALID_FORMAT;
546 pcmHandle = calloc(sizeof(mm_sound_pcm_t), 1);
547 if(pcmHandle == NULL)
548 return MM_ERROR_OUT_OF_MEMORY;
551 /* get session type */
552 if(MM_ERROR_NONE != _get_asm_event_type(&pcmHandle->asm_event)) {
554 return MM_ERROR_POLICY_INTERNAL;
557 if(pcmHandle->asm_event != ASM_EVENT_CALL && pcmHandle->asm_event != ASM_EVENT_VIDEOCALL) {
558 if(!ASM_register_sound(-1, &pcmHandle->asm_handle, pcmHandle->asm_event,
559 /* ASM_STATE_PLAYING */ ASM_STATE_NONE, sound_pcm_asm_callback, (void*)pcmHandle, ASM_RESOURCE_NONE, &errorcode))
561 debug_error("ASM_register_sound() failed 0x%x\n", errorcode);
563 return MM_ERROR_POLICY_BLOCKED;
568 param.mode = AVSYS_AUDIO_MODE_INPUT;
569 param.vol_type = AVSYS_AUDIO_VOLUME_TYPE_SYSTEM; //dose not effect at capture mode
570 param.priority = AVSYS_AUDIO_PRIORITY_0; //This does not affect anymore.
571 result = avsys_audio_open(¶m, &pcmHandle->audio_handle, &size);
572 if(AVSYS_FAIL(result)) {
573 debug_error("Device Open Error 0x%x\n", result);
575 return MM_ERROR_SOUND_DEVICE_NOT_OPENED;
578 pcmHandle->is_playback = false;
580 /* Set handle to return */
581 *handle = (MMSoundPcmHandle_t)pcmHandle;
587 static int _pcm_sound_start (MMSoundPcmHandle_t handle)
589 mm_sound_pcm_t *pcmHandle = NULL;
594 /* Check input param */
595 pcmHandle = (mm_sound_pcm_t*)handle;
596 if(pcmHandle == NULL) {
597 debug_error ("Handle is null, return Invalid Argument\n");
598 return MM_ERROR_INVALID_ARGUMENT;
601 /* ASM set state to PLAYING */
602 if (!ASM_set_sound_state(pcmHandle->asm_handle, pcmHandle->asm_event, ASM_STATE_PLAYING, ASM_RESOURCE_NONE, &errorcode)) {
603 debug_error("ASM_set_sound_state(PLAYING) failed 0x%x\n", errorcode);
604 return MM_ERROR_POLICY_BLOCKED;
608 pcmHandle->is_started = true;
613 return avsys_audio_cork(pcmHandle->audio_handle, 0);
618 int mm_sound_pcm_capture_start(MMSoundPcmHandle_t handle)
620 int ret = MM_ERROR_NONE;
622 ret = _pcm_sound_start (handle);
623 if (ret != MM_ERROR_NONE) {
624 debug_error ("_pcm_sound_start() failed (%x)\n", ret);
631 static int _pcm_sound_stop_internal (MMSoundPcmHandle_t handle)
633 mm_sound_pcm_t *pcmHandle = NULL;
635 /* Check input param */
636 pcmHandle = (mm_sound_pcm_t*)handle;
637 if(pcmHandle == NULL)
638 return MM_ERROR_INVALID_ARGUMENT;
641 if (pcmHandle->is_started == false) {
642 debug_warning ("Can't stop because not started\n");
643 return MM_ERROR_SOUND_INVALID_STATE;
646 /* Drain if playback mode */
647 if (pcmHandle->is_playback) {
648 if(AVSYS_FAIL(avsys_audio_drain(pcmHandle->audio_handle))) {
649 debug_error("drain failed\n");
654 pcmHandle->is_started = false;
657 return avsys_audio_cork(pcmHandle->audio_handle, 1);
660 static int _pcm_sound_stop(MMSoundPcmHandle_t handle)
662 mm_sound_pcm_t *pcmHandle = NULL;
664 int ret = MM_ERROR_NONE;
668 /* Check input param */
669 pcmHandle = (mm_sound_pcm_t*)handle;
670 if(pcmHandle == NULL) {
671 debug_error ("Handle is null, return Invalid Argument\n");
672 return MM_ERROR_INVALID_ARGUMENT;
675 /* Do stop procedure */
676 ret = _pcm_sound_stop_internal(handle);
677 if (ret == MM_ERROR_NONE) {
678 /* Set ASM State to STOP */
679 if (!ASM_set_sound_state(pcmHandle->asm_handle, pcmHandle->asm_event, ASM_STATE_STOP, ASM_RESOURCE_NONE, &errorcode)) {
680 debug_error("ASM_set_sound_state(STOP) failed 0x%x\n", errorcode);
681 ret = MM_ERROR_POLICY_BLOCKED;
685 debug_log ("pcm sound [%p] stopped success!!!\n", handle);
694 int mm_sound_pcm_capture_stop(MMSoundPcmHandle_t handle)
696 return _pcm_sound_stop (handle);
701 int mm_sound_pcm_capture_read(MMSoundPcmHandle_t handle, void *buffer, const unsigned int length )
703 mm_sound_pcm_t *pcmHandle = NULL;
705 /* Check input param */
706 pcmHandle = (mm_sound_pcm_t*)handle;
707 if(pcmHandle == NULL) {
708 debug_error ("Handle is null, return Invalid Argument\n");
709 return MM_ERROR_INVALID_ARGUMENT;
712 debug_error("Invalid buffer pointer\n");
713 return MM_ERROR_SOUND_INVALID_POINTER;
716 debug_error ("length is 0, return 0\n");
720 /* Check State : return fail if not started */
721 if (!pcmHandle->is_started) {
722 /* not started, return fail */
723 debug_error ("Not started yet, return Invalid State \n");
724 return MM_ERROR_SOUND_INVALID_STATE;
728 return avsys_audio_read(pcmHandle->audio_handle, buffer, length);
732 int mm_sound_pcm_capture_close(MMSoundPcmHandle_t handle)
734 int result = MM_ERROR_NONE;
735 mm_sound_pcm_t *pcmHandle = NULL;
740 /* Check input param */
741 pcmHandle = (mm_sound_pcm_t*)handle;
742 if(pcmHandle == NULL) {
743 debug_error ("Handle is null, return Invalid Argument\n");
744 return MM_ERROR_INVALID_ARGUMENT;
748 result = avsys_audio_close(pcmHandle->audio_handle);
749 if(AVSYS_FAIL(result)) {
750 debug_error("handle close failed 0x%X", result);
751 result = MM_ERROR_SOUND_INTERNAL;
755 if(pcmHandle->asm_event != ASM_EVENT_CALL && pcmHandle->asm_event != ASM_EVENT_VIDEOCALL) {
756 if(!ASM_unregister_sound(pcmHandle->asm_handle, pcmHandle->asm_event, &errorcode)) {
757 debug_error("ASM_unregister failed in %s with 0x%x\n", __func__, errorcode);
762 free(pcmHandle); pcmHandle= NULL;
769 int mm_sound_pcm_set_message_callback (MMSoundPcmHandle_t handle, MMMessageCallback callback, void *user_param)
771 mm_sound_pcm_t *pcmHandle = (mm_sound_pcm_t*)handle;
773 if(pcmHandle == NULL || callback == NULL)
774 return MM_ERROR_INVALID_ARGUMENT;
776 pcmHandle->msg_cb = callback;
777 pcmHandle->msg_cb_param = user_param;
779 debug_log ("set pcm message callback (%p,%p)\n", callback, user_param);
781 return MM_ERROR_NONE;
786 int mm_sound_pcm_play_open_ex (MMSoundPcmHandle_t *handle, const unsigned int rate, MMSoundPcmChannel_t channel, MMSoundPcmFormat_t format, const volume_type_t vol_type, ASM_sound_events_t asm_event)
788 avsys_audio_param_t param;
789 mm_sound_pcm_t *pcmHandle = NULL;
791 int result = AVSYS_STATE_SUCCESS;
792 int lvol_type = vol_type;
796 memset(¶m, 0, sizeof(avsys_audio_param_t));
798 /* Check input param */
800 debug_error("Volume type should not be negative value\n");
801 return MM_ERROR_INVALID_ARGUMENT;
803 if(vol_type >= VOLUME_TYPE_MAX) {
804 debug_error("Volume type should be under VOLUME_TYPE_MAX\n");
805 return MM_ERROR_INVALID_ARGUMENT;
807 if(rate < _MIN_SYSTEM_SAMPLERATE || rate > _MAX_SYSTEM_SAMPLERATE) {
808 debug_error("unsupported sample rate %u", rate);
809 return MM_ERROR_SOUND_DEVICE_INVALID_SAMPLERATE;
811 param.samplerate = rate;
816 case MMSOUND_PCM_MONO:
819 case MMSOUND_PCM_STEREO:
823 debug_error("Unsupported channel type\n");
824 return MM_ERROR_SOUND_DEVICE_INVALID_CHANNEL;
830 param.format = AVSYS_AUDIO_FORMAT_8BIT;
832 case MMSOUND_PCM_S16_LE:
833 param.format = AVSYS_AUDIO_FORMAT_16BIT;
836 debug_error("Unsupported format type\n");
837 return MM_ERROR_SOUND_DEVICE_INVALID_FORMAT;
840 pcmHandle = calloc(sizeof(mm_sound_pcm_t),1);
841 if(pcmHandle == NULL)
842 return MM_ERROR_OUT_OF_MEMORY;
845 debug_log ("session start : input asm_event = %d-------------\n", asm_event);
846 if (asm_event == ASM_EVENT_NONE) {
847 if(pcmHandle->asm_event != ASM_EVENT_CALL && pcmHandle->asm_event != ASM_EVENT_VIDEOCALL) {
848 /* get session type */
849 if(MM_ERROR_NONE != _get_asm_event_type(&pcmHandle->asm_event)) {
850 debug_error ("_get_asm_event_type failed....\n");
852 return MM_ERROR_POLICY_INTERNAL;
856 if(!ASM_register_sound(-1, &pcmHandle->asm_handle, pcmHandle->asm_event,
857 ASM_STATE_NONE, sound_pcm_asm_callback, (void*)pcmHandle, ASM_RESOURCE_NONE, &errorcode)) {
858 debug_error("ASM_register_sound() failed 0x%x\n", errorcode);
860 return MM_ERROR_POLICY_BLOCKED;
864 /* register asm using asm_event input */
865 if(!ASM_register_sound(-1, &pcmHandle->asm_handle, asm_event,
866 ASM_STATE_NONE, NULL, (void*)pcmHandle, ASM_RESOURCE_NONE, &errorcode)) {
867 debug_error("ASM_register_sound() failed 0x%x\n", errorcode);
869 return MM_ERROR_POLICY_BLOCKED;
873 param.mode = AVSYS_AUDIO_MODE_OUTPUT;
874 param.vol_type = lvol_type;
875 param.priority = AVSYS_AUDIO_PRIORITY_0;
877 // avsys_audio_ampon();
880 debug_log ("avsys open -------------\n");
881 result = avsys_audio_open(¶m, &pcmHandle->audio_handle, &size);
882 if(AVSYS_FAIL(result)) {
883 debug_error("Device Open Error 0x%x\n", result);
885 return MM_ERROR_SOUND_DEVICE_NOT_OPENED;
888 pcmHandle->is_playback = true;
890 /* Set handle to return */
891 *handle = (MMSoundPcmHandle_t)pcmHandle;
898 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)
900 return mm_sound_pcm_play_open_ex (handle, rate, channel, format, vol_type, ASM_EVENT_NONE);
904 int mm_sound_pcm_play_start(MMSoundPcmHandle_t handle)
906 return _pcm_sound_start (handle);
911 int mm_sound_pcm_play_stop(MMSoundPcmHandle_t handle)
913 return _pcm_sound_stop(handle);
918 int mm_sound_pcm_play_write(MMSoundPcmHandle_t handle, void* ptr, unsigned int length_byte)
920 mm_sound_pcm_t *pcmHandle = NULL;
922 /* Check input param */
923 pcmHandle = (mm_sound_pcm_t*)handle;
924 if(pcmHandle == NULL) {
925 debug_error ("Handle is null, return Invalid Argument\n");
926 return MM_ERROR_INVALID_ARGUMENT;
929 debug_error("Invalid buffer pointer\n");
930 return MM_ERROR_SOUND_INVALID_POINTER;
932 if(length_byte == 0 ) {
933 debug_error ("length is 0, return 0\n");
937 /* Check State : return fail if not started */
938 if (!pcmHandle->is_started) {
939 /* not started, return fail */
940 debug_error ("Not started yet, return Invalid State \n");
941 return MM_ERROR_SOUND_INVALID_STATE;
945 return avsys_audio_write(pcmHandle->audio_handle, ptr, length_byte);
949 int mm_sound_pcm_play_close(MMSoundPcmHandle_t handle)
951 int result = AVSYS_STATE_SUCCESS;
952 mm_sound_pcm_t *pcmHandle = NULL;
957 /* Check input param */
958 pcmHandle = (mm_sound_pcm_t*)handle;
959 if(pcmHandle == NULL) {
960 debug_error ("Handle is null, return Invalid Argument\n");
961 return MM_ERROR_INVALID_ARGUMENT;
964 /* Drain if needed */
965 if (pcmHandle->is_started) {
966 /* stop() is not called before close(), drain is needed */
967 if(AVSYS_FAIL(avsys_audio_drain(pcmHandle->audio_handle))) {
968 debug_error("drain failed\n");
973 result = avsys_audio_close(pcmHandle->audio_handle);
974 if(AVSYS_FAIL(result)) {
975 debug_error("handle close failed 0x%X", result);
976 result = MM_ERROR_SOUND_INTERNAL;
980 if(pcmHandle->asm_event != ASM_EVENT_CALL && pcmHandle->asm_event != ASM_EVENT_VIDEOCALL) {
981 if(!ASM_unregister_sound(pcmHandle->asm_handle, pcmHandle->asm_event, &errorcode)) {
982 debug_error("ASM_unregister failed in %s with 0x%x\n",__func__, errorcode);
986 debug_log ("pcm sound [%p] closed success!!!\n", handle);
989 free(pcmHandle); pcmHandle= NULL;
996 ///////////////////////////////////
997 //// MMSOUND PLAY APIs
998 ///////////////////////////////////
1000 int mm_sound_play_loud_solo_sound(const char *filename, const volume_type_t volume_type, mm_sound_stop_callback_func callback, void *data, int *handle)
1002 MMSoundParamType param = { 0, };
1005 int lvol_type = volume_type;
1009 /* Check input param */
1010 if(filename == NULL) {
1011 debug_error("filename is NULL\n");
1012 return MM_ERROR_SOUND_FILE_NOT_FOUND;
1014 if(volume_type < 0 || volume_type >= VOLUME_TYPE_MAX) {
1015 debug_error("Volume type should not be negative value\n");
1016 return MM_ERROR_INVALID_ARGUMENT;
1020 param.filename = filename;
1021 param.volume = 0; //volume value dose not effect anymore
1022 param.callback = callback;
1025 param.volume_table = lvol_type;
1026 param.priority = AVSYS_AUDIO_PRIORITY_SOLO;
1027 param.handle_route = MM_SOUND_HANDLE_ROUTE_SPEAKER;
1029 err = MMSoundClientPlaySound(¶m, 0, 0, &lhandle);
1031 debug_error("Failed to play sound\n");
1035 /* Set handle to return */
1039 debug_critical("The sound handle cannot be get [%d]\n", lhandle);
1043 return MM_ERROR_NONE;
1047 int mm_sound_play_solo_sound(const char *filename, const volume_type_t volume_type, mm_sound_stop_callback_func callback, void *data, int *handle)
1049 MMSoundParamType param = { 0, };
1052 int lvol_type = volume_type;
1056 /* Check input param */
1057 if(filename == NULL) {
1058 debug_error("filename is NULL\n");
1059 return MM_ERROR_SOUND_FILE_NOT_FOUND;
1061 if(volume_type < 0 || volume_type >= VOLUME_TYPE_MAX) {
1062 debug_error("Volume type should not be negative value\n");
1063 return MM_ERROR_INVALID_ARGUMENT;
1067 param.filename = filename;
1068 param.volume = 0; /* volume value dose not effect anymore */
1069 param.callback = callback;
1072 param.volume_table = lvol_type;
1073 param.priority = AVSYS_AUDIO_PRIORITY_SOLO;
1074 param.handle_route = MM_SOUND_HANDLE_ROUTE_USING_CURRENT;
1076 err = MMSoundClientPlaySound(¶m, 0, 0, &lhandle);
1078 debug_error("Failed to play sound\n");
1082 /* Set handle to return */
1086 debug_critical("The sound handle cannot be get [%d]\n", lhandle);
1090 return MM_ERROR_NONE;
1095 int mm_sound_play_sound(const char *filename, const volume_type_t volume_type, mm_sound_stop_callback_func callback, void *data, int *handle)
1097 MMSoundParamType param = { 0, };
1100 int lvol_type = volume_type;
1104 /* Check input param */
1105 if(filename == NULL) {
1106 debug_error("filename is NULL\n");
1107 return MM_ERROR_SOUND_FILE_NOT_FOUND;
1109 if(volume_type < 0) {
1110 debug_error("Volume type should not be negative value\n");
1111 return MM_ERROR_INVALID_ARGUMENT;
1113 if(volume_type >= VOLUME_TYPE_MAX) {
1114 debug_error("Volume type should be under VOLUME_TYPE_MAX\n");
1115 return MM_ERROR_INVALID_ARGUMENT;
1119 param.filename = filename;
1120 param.volume = 0; /* volume value dose not effect anymore */
1121 param.callback = callback;
1124 param.volume_table = lvol_type;
1125 param.priority = AVSYS_AUDIO_PRIORITY_NORMAL;
1126 param.handle_route = MM_SOUND_HANDLE_ROUTE_USING_CURRENT;
1128 err = MMSoundClientPlaySound(¶m, 0, 0, &lhandle);
1130 debug_error("Failed to play sound\n");
1134 /* Set handle to return */
1138 debug_critical("The sound handle cannot be get [%d]\n", lhandle);
1142 return MM_ERROR_NONE;
1147 int mm_sound_play_sound_ex(MMSoundParamType *param, int *handle)
1154 /* Check input param */
1155 if (param == NULL) {
1156 debug_error("param is null\n");
1157 return MM_ERROR_INVALID_ARGUMENT;
1161 err = MMSoundClientPlaySound(param, 0, 0, &lhandle);
1163 debug_error("Failed to play sound\n");
1167 /* Set handle to return */
1171 debug_critical("The sound hadle cannot be get [%d]\n", lhandle);
1175 return MM_ERROR_NONE;
1180 int mm_sound_stop_sound(int handle)
1187 err = MMSoundClientStopSound(handle);
1189 debug_error("Fail to stop sound\n");
1194 return MM_ERROR_NONE;
1197 ///////////////////////////////////
1198 //// MMSOUND TONE APIs
1199 ///////////////////////////////////
1201 int mm_sound_play_tone (MMSoundTone_t num, const volume_type_t vol_type, const double volume, const int duration, int *handle)
1204 int err = MM_ERROR_NONE;
1208 /* Check input param */
1210 debug_error("number is invalid %d\n", duration);
1211 return MM_ERROR_INVALID_ARGUMENT;
1213 if(num < MM_SOUND_TONE_DTMF_0 || num >= MM_SOUND_TONE_NUM) {
1214 debug_error("TONE Value is invalid %d\n", num);
1215 return MM_ERROR_INVALID_ARGUMENT;
1217 if(vol_type < VOLUME_TYPE_SYSTEM || vol_type >= VOLUME_TYPE_MAX) {
1218 debug_error("Volume Type is invalid %d\n", vol_type);
1219 return MM_ERROR_INVALID_ARGUMENT;
1221 if(volume < 0.0 || volume > 1.0) {
1222 debug_error("Volume Value is invalid %d\n", vol_type);
1223 return MM_ERROR_INVALID_ARGUMENT;
1227 debug_msg("Call MMSoundClientPlayTone\n");
1228 err = MMSoundClientPlayTone (num, vol_type, volume, duration, &lhandle);
1230 debug_error("Failed to play sound\n");
1234 /* Set handle to return */
1238 debug_critical("The sound handle cannot be get [%d]\n", lhandle);
1241 return MM_ERROR_NONE;
1244 ///////////////////////////////////
1245 //// MMSOUND ROUTING APIs
1246 ///////////////////////////////////
1248 int mm_sound_set_path(int gain, int output, int input, int option)
1254 debug_msg("gain: 0x%02X, output: %d, input: %d, option: 0x%x\n", gain, output, input, option);
1256 err = avsys_audio_set_path_ex( gain, output, input, option);
1258 debug_error("avsys_audio_set_path() failed\n");
1259 return MM_ERROR_SOUND_INTERNAL;
1263 return MM_ERROR_NONE;
1267 int mm_sound_get_path(int *gain, int *output, int *input, int *option)
1273 err = avsys_audio_get_path_ex( gain, output, input, option);
1275 debug_error("SoundCtlPathGet() failed\n");
1276 return MM_ERROR_SOUND_INTERNAL;
1279 debug_msg("gain: 0x%02X, output: %d, input: %d, option: 0x%x\n", *gain, *output, *input, *option);
1282 return MM_ERROR_NONE;
1287 USE_PA_SINK_ALSA = 0,
1291 int mm_sound_route_set_system_policy (system_audio_route_t route)
1293 return MM_ERROR_NONE;
1298 int mm_sound_route_get_system_policy (system_audio_route_t *route)
1300 return MM_ERROR_NONE;
1305 int mm_sound_route_get_a2dp_status (int *connected, char **bt_name)
1307 int ret = MM_ERROR_NONE;
1311 if (connected == NULL || bt_name == NULL) {
1312 debug_error ("argument is not valid\n");
1313 return MM_ERROR_INVALID_ARGUMENT;
1316 ret = MMSoundClientIsBtA2dpOn (connected, bt_name);
1317 debug_msg ("connected=[%d] bt_name[%s]\n", *connected, *bt_name);
1319 debug_error("MMSoundClientIsBtA2dpOn() Failed\n");
1329 int mm_sound_route_get_playing_device(system_audio_route_device_t *dev)
1331 mm_sound_device_in device_in = MM_SOUND_DEVICE_IN_NONE;
1332 mm_sound_device_out device_out = MM_SOUND_DEVICE_OUT_NONE;
1335 return MM_ERROR_INVALID_ARGUMENT;
1337 if(MM_ERROR_NONE != mm_sound_get_active_device(&device_in, &device_out)) {
1338 debug_error("Can not get active device info\n");
1339 return MM_ERROR_SOUND_INTERNAL;
1344 case MM_SOUND_DEVICE_OUT_SPEAKER:
1345 *dev = SYSTEM_AUDIO_ROUTE_PLAYBACK_DEVICE_HANDSET;
1347 case MM_SOUND_DEVICE_OUT_BT_A2DP:
1348 *dev = SYSTEM_AUDIO_ROUTE_PLAYBACK_DEVICE_BLUETOOTH;
1350 case MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY:
1351 *dev = SYSTEM_AUDIO_ROUTE_PLAYBACK_DEVICE_EARPHONE;
1354 *dev = SYSTEM_AUDIO_ROUTE_PLAYBACK_DEVICE_NONE;
1358 return MM_ERROR_NONE;
1362 int mm_sound_route_add_change_callback(audio_route_policy_changed_callback_fn func, void *user_data)
1365 return MM_ERROR_NONE;
1369 int mm_sound_route_remove_change_callback()
1372 return MM_ERROR_NONE;
1375 #endif /* PULSE_CLIENT */
1378 int mm_sound_system_get_capture_status(system_audio_capture_status_t *status)
1380 int err = AVSYS_STATE_SUCCESS;
1384 return MM_ERROR_INVALID_ARGUMENT;
1386 err = avsys_audio_get_capture_status(&on_capture);
1388 debug_error("Can not get capture status with 0x%x\n", err);
1389 return MM_ERROR_SOUND_INTERNAL;
1393 *status = SYSTEM_AUDIO_CAPTURE_ACTIVE;
1395 *status = SYSTEM_AUDIO_CAPTURE_NONE;
1397 return MM_ERROR_NONE;
1401 int mm_sound_is_route_available(mm_sound_route route, bool *is_available)
1403 int ret = MM_ERROR_NONE;
1407 if (!_mm_sound_is_route_valid(route)) {
1408 debug_error("route is invalid %d\n", route);
1409 return MM_ERROR_INVALID_ARGUMENT;
1413 debug_error("is_available is invalid\n");
1414 return MM_ERROR_INVALID_ARGUMENT;
1417 ret = _mm_sound_client_is_route_available(route, is_available);
1419 debug_error("Can not check given route is available\n");
1427 int mm_sound_foreach_available_route_cb(mm_sound_available_route_cb available_route_cb, void *user_data)
1429 int ret = MM_ERROR_NONE;
1433 if (!available_route_cb)
1435 debug_error("available_route_cb is invalid\n");
1436 return MM_ERROR_INVALID_ARGUMENT;
1439 ret = _mm_sound_client_foreach_available_route_cb(available_route_cb, user_data);
1441 debug_error("Can not set foreach available route callback\n");
1449 int mm_sound_set_active_route(mm_sound_route route)
1451 int ret = MM_ERROR_NONE;
1455 if (!_mm_sound_is_route_valid(route)) {
1456 debug_error("route is invalid %d\n", route);
1457 return MM_ERROR_INVALID_ARGUMENT;
1460 ret = _mm_sound_client_set_active_route(route);
1462 debug_error("Can not set active route\n");
1471 int mm_sound_get_active_device(mm_sound_device_in *device_in, mm_sound_device_out *device_out)
1473 int ret = MM_ERROR_NONE;
1477 if (device_in == NULL || device_out == NULL) {
1478 debug_error("argument is not valid\n");
1479 return MM_ERROR_INVALID_ARGUMENT;
1482 ret = _mm_sound_client_get_active_device(device_in, device_out);
1484 debug_error("Can not add active device callback\n");
1492 int mm_sound_add_active_device_changed_callback(mm_sound_active_device_changed_cb func, void *user_data)
1494 int ret = MM_ERROR_NONE;
1499 debug_error("argument is not valid\n");
1500 return MM_ERROR_INVALID_ARGUMENT;
1503 ret = _mm_sound_client_add_active_device_changed_callback(func, user_data);
1505 debug_error("Can not add active device changed callback\n");
1513 int mm_sound_remove_active_device_changed_callback(void)
1515 int ret = MM_ERROR_NONE;
1519 ret = _mm_sound_client_remove_active_device_changed_callback();
1521 debug_error("Can not remove active device changed callback\n");
1529 int mm_sound_add_available_route_changed_callback(mm_sound_available_route_changed_cb func, void *user_data)
1531 int ret = MM_ERROR_NONE;
1536 debug_error("argument is not valid\n");
1537 return MM_ERROR_INVALID_ARGUMENT;
1540 ret = _mm_sound_client_add_available_route_changed_callback(func, user_data);
1542 debug_error("Can not add available route changed callback\n");
1550 int mm_sound_remove_available_route_changed_callback(void)
1552 int ret = MM_ERROR_NONE;
1556 ret = _mm_sound_client_remove_available_route_changed_callback();
1558 debug_error("Can not remove available route changed callback\n");
1565 __attribute__ ((destructor))
1566 void __mmfsnd_finalize(void)
1570 MMSoundClientCallbackFini();
1575 __attribute__ ((constructor))
1576 void __mmfsnd_initialize(void)