5 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
7 * Contact: Seungbae Shin <seungbae.shin@samsung.com>
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
32 #include <mm_session.h>
36 #include "include/mm_sound_mgr_codec.h"
37 #include "include/mm_sound_mgr_ipc.h"
38 #include "include/mm_sound_plugin_codec.h"
39 #include "include/mm_sound_thread_pool.h"
41 #include "../include/mm_sound_common.h"
42 #include "../include/mm_sound_focus.h"
43 #include "../include/mm_sound.h"
45 #define SHUTDOWN_TIMEOUT_SEC 10
47 #define STATUS_SOUND 3
48 #define SOUND_SLOT_START 0
49 #define FOCUS_INTEGRATION
50 #define MANAGER_HANDLE_MAX 256
53 int (*callback)(int, void *, void *, int); /* msg_type(pid) client callback & client data info */
58 MMHandleType plughandle;
64 #ifdef FOCUS_INTEGRATION
68 mm_sound_focus_type_e current_focus_type;
73 } __mmsound_mgr_codec_handle_t;
75 static MMSoundPluginType *g_codec_plugins = NULL;
76 static __mmsound_mgr_codec_handle_t g_slots[MANAGER_HANDLE_MAX];
77 static mmsound_codec_interface_t g_plugins[MM_SOUND_SUPPORTED_CODEC_NUM];
78 static pthread_mutex_t g_slot_mutex;
79 GSourceFunc g_shutdown_cb;
82 #define SLOT_LOCK() do { pthread_mutex_lock(&g_slot_mutex); /* debug_msg("After Slot_mutex LOCK"); */ } while (0)
83 #define SLOT_UNLOCK() do { pthread_mutex_unlock(&g_slot_mutex); /* debug_msg("After Slot_mutex UNLOCK"); */ } while (0)
85 static int _MMSoundMgrCodecRegisterInterface(MMSoundPluginType *plugin);
86 static int _MMSoundMgrCodecStopCallback(int param);
89 #ifdef FOCUS_INTEGRATION
91 static void _handle_focus_event(int slotid, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e focus_state, bool is_watch)
93 int result = MM_ERROR_NONE;
95 if (g_slots[slotid].session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
96 debug_warning("session option is UNINTERRUPTIBLE, nothing to do with focus");
100 if (focus_state == FOCUS_IS_RELEASED) {
102 g_slots[slotid].current_focus_type = FOCUS_FOR_BOTH & (~focus_type);
103 debug_warning("focus is released -> stop playing");
105 result = MMSoundMgrCodecStop(slotid);
106 if (result != MM_ERROR_NONE)
107 debug_error("result error 0x%X", result);
111 static void _sound_codec_focus_callback(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e focus_state,
112 const char *reason_for_change, int option, const char *ext_info, void *user_data)
114 debug_warning("focus callback called -> focus_state(%d), reason_for_change(%s)",
115 focus_state, reason_for_change ? reason_for_change : "N/A");
117 _handle_focus_event((int)user_data, focus_type, focus_state, false);
120 static void _sound_codec_focus_watch_callback(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e focus_state,
121 const char *reason_for_change, const char *ext_info, void *user_data)
123 debug_warning("focus watch callback called -> focus_state(%d), reason_for_change(%s)",
124 focus_state, reason_for_change ? reason_for_change : "N/A");
126 _handle_focus_event((int)user_data, focus_type, focus_state, true);
129 static void _sound_codec_device_connected_callback(MMSoundDevice_t device, bool is_connected, void *user_data)
131 int slotid = (int)user_data;
132 int result = MM_ERROR_NONE;
133 mm_sound_device_type_e type;
135 debug_warning("device_connected_callback called : handle[%p], connected[%d], slotid[%d]", device, is_connected, slotid);
137 if (mm_sound_get_device_type(device, &type) != MM_ERROR_NONE) {
138 debug_error("getting device type failed");
143 case MM_SOUND_DEVICE_TYPE_AUDIOJACK:
144 case MM_SOUND_DEVICE_TYPE_BLUETOOTH:
145 case MM_SOUND_DEVICE_TYPE_HDMI:
146 case MM_SOUND_DEVICE_TYPE_MIRRORING:
147 case MM_SOUND_DEVICE_TYPE_USB_AUDIO:
149 debug_warning("sound device unplugged");
150 result = MMSoundMgrCodecStop(slotid);
151 if (result != MM_ERROR_NONE)
152 debug_error("MMSoundMgrCodecStop error %d", result);
154 result = mm_sound_remove_device_connected_callback(g_slots[slotid].subs_id);
155 if (result != MM_ERROR_NONE)
156 debug_error("mm_sound_remove_device_connected_callback error %d", result);
166 /* FIXME : critical section for g_timer_id? */
167 static void _mm_sound_mgr_codec_shutdown_timer_start()
169 if (g_timer_id > 0) {
170 debug_error("Already active timer [%d] exists", g_timer_id);
175 g_timer_id = g_timeout_add_seconds(SHUTDOWN_TIMEOUT_SEC, g_shutdown_cb, NULL);
176 debug_error("TIMER : new timer [%d]", g_timer_id);
178 debug_warning("No Timer started due to invalid shutdown callback");
182 static void _mm_sound_mgr_codec_shutdown_timer_stop()
184 if (g_timer_id > 0) {
185 debug_error("TIMER : remove timer id [%d]", g_timer_id);
186 g_source_remove(g_timer_id);
189 debug_log("No Timer to stop...");
193 static int _mm_sound_mgr_codec_slot_get_empty(int *slot)
196 int err = MM_ERROR_NONE;
201 for (slotid = SOUND_SLOT_START; slotid < MANAGER_HANDLE_MAX ; slotid++) {
202 if (g_slots[slotid].status == STATUS_IDLE) {
203 g_slots[slotid].status = STATUS_SOUND;
208 if (slotid < MANAGER_HANDLE_MAX) {
209 debug_msg("New handle allocated (codec slot ID : [%d])", slotid);
214 /* FIXME: avoiding infinite wait is required */
215 debug_warning("Handle is full..wait for a while and will retry...");
219 _mm_sound_mgr_codec_shutdown_timer_stop();
226 static gboolean _mm_sound_mgr_codec_slot_is_empty()
230 for (slotid = SOUND_SLOT_START; slotid < MANAGER_HANDLE_MAX ; slotid++) {
231 if (g_slots[slotid].status == STATUS_SOUND)
235 return (slotid == MANAGER_HANDLE_MAX) ? TRUE : FALSE;
238 static void _mm_sound_mgr_codec_slot_clear(int slotid)
240 memset(&g_slots[slotid], 0, sizeof(__mmsound_mgr_codec_handle_t));
241 g_slots[slotid].status = STATUS_IDLE;
243 debug_error("SlotID [%d] cleared", slotid);
246 int MMSoundMgrCodecInit(const char *targetdir, GSourceFunc _shutdown_cb)
253 memset(g_slots, 0, sizeof(g_slots));
255 if (pthread_mutex_init(&g_slot_mutex, NULL)) {
256 debug_error("pthread_mutex_init failed");
257 return MM_ERROR_SOUND_INTERNAL;
260 for (slotid = 0; slotid < MANAGER_HANDLE_MAX; slotid++)
261 _mm_sound_mgr_codec_slot_clear(slotid);
263 if (g_codec_plugins) {
264 debug_warning("Please Check Init twice");
265 MMSoundPluginRelease(g_codec_plugins);
268 MMSoundPluginScan(targetdir, MM_SOUND_PLUGIN_TYPE_CODEC, &g_codec_plugins);
269 if (g_codec_plugins) {
270 while (g_codec_plugins[loop].type != MM_SOUND_PLUGIN_TYPE_NONE)
271 _MMSoundMgrCodecRegisterInterface(&g_codec_plugins[loop++]);
275 g_shutdown_cb = _shutdown_cb;
277 debug_warning("shutdown callback is NULL");
280 return MM_ERROR_NONE;
283 int MMSoundMgrCodecFini(void)
287 memset(g_plugins, 0, sizeof(mmsound_codec_interface_t) * MM_SOUND_SUPPORTED_CODEC_NUM);
288 MMSoundPluginRelease(g_codec_plugins);
289 g_codec_plugins = NULL;
290 pthread_mutex_destroy(&g_slot_mutex);
293 return MM_ERROR_NONE;
296 static int _MMSoundMgrCodecFindCodecPluginID(enum MMSoundSupportedCodec codec_to_find)
301 for (plugin_id = 0; plugin_id < MM_SOUND_SUPPORTED_CODEC_NUM; plugin_id++) {
302 if (g_plugins[plugin_id].GetSupportTypes) {
303 codec_type = g_plugins[plugin_id].GetSupportTypes();
304 if (codec_type[0] == codec_to_find)
312 int MMSoundMgrCodecPlay(int *slotid, const mmsound_mgr_codec_param_t *param)
315 mmsound_codec_info_t info;
316 mmsound_codec_param_t codec_param;
317 int err = MM_ERROR_NONE;
319 #ifdef FOCUS_INTEGRATION
320 int need_focus_unregister = 0;
326 plugin_id = _MMSoundMgrCodecFindCodecPluginID(MM_SOUND_SUPPORTED_CODEC_WAVE);
327 if (plugin_id == -1) {
328 debug_error("Could not find proper codec plugin!!!");
329 err = MM_ERROR_SOUND_INTERNAL;
333 err = g_plugins[plugin_id].Parse(param->pfilename, &info);
334 if (err != MM_ERROR_NONE) {
335 debug_error("Could not parse file [%s] by plugin[%d]", param->pfilename, plugin_id);
339 debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]", param->tone, param->repeat_count, param->volume, plugin_id);
342 debug_msg("Get New handle");
345 err = _mm_sound_mgr_codec_slot_get_empty(slotid);
346 if (err != MM_ERROR_NONE || *slotid < 0) {
347 debug_error("Empty g_slot is not found");
351 codec_param.tone = param->tone;
352 codec_param.volume_config = param->volume_config;
353 codec_param.repeat_count = param->repeat_count;
354 codec_param.volume = param->volume;
355 codec_param.pfilename = param->pfilename;
356 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
357 codec_param.param = *slotid;
358 codec_param.pid = (int)param->param;
359 codec_param.stream_index = param->stream_index;
360 MMSOUND_STRNCPY(codec_param.stream_type, param->stream_type, MAX_STREAM_TYPE_LEN);
363 #ifdef FOCUS_INTEGRATION
365 * Register FOCUS here
368 if (param->session_type != MM_SESSION_TYPE_CALL &&
369 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
370 param->session_type != MM_SESSION_TYPE_VOIP &&
371 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
372 param->enable_session) {
374 unsigned int subs_id = 0;
376 err = mm_sound_add_device_connected_callback(MM_SOUND_DEVICE_STATE_ACTIVATED_FLAG,
377 (mm_sound_device_connected_cb)_sound_codec_device_connected_callback,
378 (void*) *slotid, &subs_id);
380 debug_error("mm_sound_add_device_connected_callback failed [0x%x]", err);
382 return MM_ERROR_POLICY_INTERNAL;
384 g_slots[*slotid].subs_id = subs_id;
386 if ((param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS) ||
387 param->session_type == MM_SESSION_TYPE_ALARM ||
388 param->session_type == MM_SESSION_TYPE_NOTIFY ||
389 param->session_type == MM_SESSION_TYPE_EMERGENCY) {
390 debug_warning("session option is PAUSE_OTHERS -> acquire focus");
391 err = mm_sound_focus_get_id((int *)(¶m->focus_handle));
392 err = mm_sound_register_focus_for_session(param->focus_handle, (int)param->param, "media", _sound_codec_focus_callback, (void*)*slotid);
394 debug_error("mm_sound_register_focus_for_session failed [0x%x]", err);
396 return MM_ERROR_POLICY_INTERNAL;
398 err = mm_sound_acquire_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
400 debug_error("mm_sound_acquire_focus failed [0x%x]", err);
401 err = mm_sound_unregister_focus(param->focus_handle);
403 return MM_ERROR_POLICY_INTERNAL;
405 g_slots[*slotid].current_focus_type = FOCUS_FOR_BOTH;
406 } else if (param->session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
408 debug_warning("session option is UNINTERRUPTIBLE, nothing to do with focus");
410 debug_warning("need to set focus watch callback");
411 err = mm_sound_set_focus_watch_callback_for_session((int)param->param, FOCUS_FOR_BOTH, _sound_codec_focus_watch_callback,
412 (void*)*slotid, (int *)(¶m->focus_wcb_id));
414 debug_error("mm_sound_set_focus_watch_callback_for_session failed [0x%x]", err);
416 return MM_ERROR_POLICY_INTERNAL;
423 /* Codec id WAV or MP3 */
424 g_slots[*slotid].pluginid = plugin_id;
425 g_slots[*slotid].param = param->param; /* This arg is used callback data */
426 g_slots[*slotid].session_type = param->session_type;
427 g_slots[*slotid].session_options = param->session_options;
428 #ifdef FOCUS_INTEGRATION
429 g_slots[*slotid].focus_handle = param->focus_handle;
430 g_slots[*slotid].focus_wcb_id = param->focus_wcb_id;
432 g_slots[*slotid].enable_session = true;
433 g_slots[*slotid].pid = (int)param->param;
436 debug_msg("Using Slotid : [%d] Slot Status : [%d]", *slotid, g_slots[*slotid].status);
438 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
439 debug_msg("Created audio handle : [%p]", g_slots[*slotid].plughandle);
440 if (err != MM_ERROR_NONE) {
441 debug_error("Plugin create fail : 0x%08X", err);
442 g_slots[*slotid].status = STATUS_IDLE;
444 #ifdef FOCUS_INTEGRATION
445 if (param->focus_handle)
446 need_focus_unregister = 1;
451 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
452 if (err != MM_ERROR_NONE) {
453 debug_error("Fail to play : 0x%08X", err);
454 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
455 #ifdef FOCUS_INTEGRATION
456 if (param->focus_handle)
457 need_focus_unregister = 1;
464 if (_mm_sound_mgr_codec_slot_is_empty())
465 _mm_sound_mgr_codec_shutdown_timer_start();
467 #ifdef FOCUS_INTEGRATION
468 if (param->session_type != MM_SESSION_TYPE_CALL &&
469 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
470 param->session_type != MM_SESSION_TYPE_VOIP &&
471 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
472 param->enable_session &&
473 need_focus_unregister == 1) {
475 if ((param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS) ||
476 param->session_type == MM_SESSION_TYPE_ALARM ||
477 param->session_type == MM_SESSION_TYPE_NOTIFY ||
478 param->session_type == MM_SESSION_TYPE_EMERGENCY) {
479 err = mm_sound_release_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
480 if (mm_sound_unregister_focus(param->focus_handle) || err) {
481 debug_error("focus cleaning up failed[0x%x]", err);
482 return MM_ERROR_POLICY_INTERNAL;
484 } else if (!(param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
485 err = mm_sound_unset_focus_watch_callback(param->focus_wcb_id);
487 debug_error("focus watch cleaning up failed[0x%x]", err);
488 return MM_ERROR_POLICY_INTERNAL;
502 int MMSoundMgrCodecPlayWithStreamInfo(int *slotid, const mmsound_mgr_codec_param_t *param)
505 mmsound_codec_info_t info;
506 mmsound_codec_param_t codec_param;
507 int err = MM_ERROR_NONE;
512 plugin_id = _MMSoundMgrCodecFindCodecPluginID(MM_SOUND_SUPPORTED_CODEC_WAVE);
513 if (plugin_id == -1) {
514 debug_error("Could not find proper codec plugin!!!");
515 err = MM_ERROR_SOUND_INTERNAL;
519 err = g_plugins[plugin_id].Parse(param->pfilename, &info);
520 if (err != MM_ERROR_NONE) {
521 debug_error("Could not parse file [%s] by plugin[%d]", param->pfilename, plugin_id);
525 err = _mm_sound_mgr_codec_slot_get_empty(slotid);
526 if (err != MM_ERROR_NONE || *slotid < 0) {
527 debug_error("Empty g_slot is not found");
531 codec_param.volume_config = -1; //setting volume config to -1 since using stream info instead of volume type
532 codec_param.repeat_count = param->repeat_count;
533 codec_param.volume = param->volume;
534 codec_param.pfilename = param->pfilename;
535 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
536 codec_param.param = *slotid;
537 codec_param.pid = (int)param->param;
538 codec_param.stream_index = param->stream_index;
539 MMSOUND_STRNCPY(codec_param.stream_type, param->stream_type, MAX_STREAM_TYPE_LEN);
542 /* Codec id WAV or MP3 */
543 g_slots[*slotid].pluginid = plugin_id;
544 g_slots[*slotid].param = param->param; /* This arg is used callback data */
546 debug_msg("Using Slotid : [%d] Slot Status : [%d]", *slotid, g_slots[*slotid].status);
548 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
549 debug_msg("Created audio handle : [%p]", g_slots[*slotid].plughandle);
550 if (err != MM_ERROR_NONE) {
551 debug_error("Plugin create fail : 0x%08X", err);
552 g_slots[*slotid].status = STATUS_IDLE;
557 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
558 if (err != MM_ERROR_NONE) {
559 debug_error("Fail to play : 0x%08X", err);
560 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
566 if (_mm_sound_mgr_codec_slot_is_empty())
567 _mm_sound_mgr_codec_shutdown_timer_start();
577 #define DTMF_PLUGIN_COUNT 2
578 int MMSoundMgrCodecPlayDtmf(int *slotid, const mmsound_mgr_codec_param_t *param)
581 mmsound_codec_info_t info;
582 mmsound_codec_param_t codec_param;
583 int err = MM_ERROR_NONE;
584 #ifdef FOCUS_INTEGRATION
585 int need_focus_unregister = 0;
591 plugin_id = _MMSoundMgrCodecFindCodecPluginID(MM_SOUND_SUPPORTED_CODEC_DTMF);
592 if (plugin_id == -1) {
593 debug_error("Could not find proper codec plugin!!!");
594 err = MM_ERROR_SOUND_INTERNAL;
598 /*The count num means codec type DTMF */
599 debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]", param->tone, param->repeat_count, param->volume, plugin_id);
601 if (g_plugins[plugin_id].GetSupportTypes == NULL) { /* Codec not found */
602 debug_error("unsupported file type %d", plugin_id);
603 printf("unsupported file type %d", plugin_id);
604 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
609 debug_msg("Get New handle");
612 err = _mm_sound_mgr_codec_slot_get_empty(slotid);
613 if (err != MM_ERROR_NONE || *slotid < 0) {
614 debug_error("Empty g_slot is not found");
618 codec_param.tone = param->tone;
619 codec_param.volume_config = param->volume_config;
620 codec_param.repeat_count = param->repeat_count;
621 codec_param.volume = param->volume;
622 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
623 codec_param.param = *slotid;
624 codec_param.pid = (int)param->param;
625 codec_param.stream_index = param->stream_index;
626 MMSOUND_STRNCPY(codec_param.stream_type, param->stream_type, MAX_STREAM_TYPE_LEN);
629 #ifdef FOCUS_INTEGRATION
632 * Register FOCUS here
635 if (param->session_type != MM_SESSION_TYPE_CALL &&
636 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
637 param->session_type != MM_SESSION_TYPE_VOIP &&
638 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
639 param->enable_session) {
641 unsigned int subs_id = 0;
643 err = mm_sound_add_device_connected_callback(MM_SOUND_DEVICE_STATE_ACTIVATED_FLAG,
644 (mm_sound_device_connected_cb)_sound_codec_device_connected_callback,
645 (void*) *slotid, &subs_id);
647 debug_error("mm_sound_add_device_connected_callback failed [0x%x]", err);
649 return MM_ERROR_POLICY_INTERNAL;
651 g_slots[*slotid].subs_id = subs_id;
653 if ((param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS) ||
654 param->session_type == MM_SESSION_TYPE_ALARM ||
655 param->session_type == MM_SESSION_TYPE_NOTIFY ||
656 param->session_type == MM_SESSION_TYPE_EMERGENCY) {
657 debug_warning("session option is PAUSE_OTHERS -> acquire focus");
658 err = mm_sound_focus_get_id((int *)(¶m->focus_handle));
659 err = mm_sound_register_focus_for_session(param->focus_handle, (int)param->param, "media", _sound_codec_focus_callback, (void*)*slotid);
661 debug_error("mm_sound_register_focus failed [0x%x]", err);
663 return MM_ERROR_POLICY_INTERNAL;
665 err = mm_sound_acquire_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
667 debug_error("mm_sound_acquire_focus failed [0x%x]", err);
668 err = mm_sound_unregister_focus(param->focus_handle);
670 return MM_ERROR_POLICY_INTERNAL;
672 g_slots[*slotid].current_focus_type = FOCUS_FOR_BOTH;
673 } else if (param->session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
675 debug_warning("session option is UNINTERRUPTIBLE, nothing to do with focus");
677 debug_warning("need to set focus watch callback");
678 err = mm_sound_set_focus_watch_callback_for_session((int)param->param, FOCUS_FOR_BOTH, _sound_codec_focus_watch_callback,
679 (void*)*slotid, (int *)(¶m->focus_wcb_id));
681 debug_error("mm_sound_set_focus_watch_callback failed [0x%x]", err);
683 return MM_ERROR_POLICY_INTERNAL;
689 g_slots[*slotid].pluginid = plugin_id;
690 g_slots[*slotid].param = param->param; /* This arg is used callback data */
691 g_slots[*slotid].session_type = param->session_type;
692 g_slots[*slotid].session_options = param->session_options;
693 #ifdef FOCUS_INTEGRATION
694 g_slots[*slotid].focus_handle = param->focus_handle;
695 g_slots[*slotid].focus_wcb_id = param->focus_wcb_id;
697 g_slots[*slotid].enable_session = param->enable_session;
698 g_slots[*slotid].pid = (int)param->param;
701 debug_msg("Using Slotid : [%d] Slot Status : [%d]", *slotid, g_slots[*slotid].status);
704 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
705 debug_msg("Created audio handle : [%p]", g_slots[*slotid].plughandle);
706 if (err != MM_ERROR_NONE) {
707 debug_error("Plugin create fail : 0x%08X", err);
708 g_slots[*slotid].status = STATUS_IDLE;
710 #ifdef FOCUS_INTEGRATION
711 need_focus_unregister = 1;
716 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
717 if (err != MM_ERROR_NONE) {
718 debug_error("Fail to play : 0x%08X", err);
719 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
720 #ifdef FOCUS_INTEGRATION
721 need_focus_unregister = 1;
726 debug_msg("Using Slotid : [%d] Slot Status : [%d]", *slotid, g_slots[*slotid].status);
729 #ifdef FOCUS_INTEGRATION
730 if (param->session_type != MM_SESSION_TYPE_CALL &&
731 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
732 param->session_type != MM_SESSION_TYPE_VOIP &&
733 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
734 param->enable_session &&
735 need_focus_unregister == 1) {
737 if ((param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS) ||
738 param->session_type == MM_SESSION_TYPE_ALARM ||
739 param->session_type == MM_SESSION_TYPE_NOTIFY ||
740 param->session_type == MM_SESSION_TYPE_EMERGENCY) {
741 err = mm_sound_release_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
742 if (mm_sound_unregister_focus(param->focus_handle) || err) {
743 debug_error("focus cleaning up failed[0x%x]", err);
744 return MM_ERROR_POLICY_INTERNAL;
746 } else if (!(param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
747 err = mm_sound_unset_focus_watch_callback(param->focus_wcb_id);
749 debug_error("focus watch cleaning up failed[0x%x]", err);
750 return MM_ERROR_POLICY_INTERNAL;
763 int MMSoundMgrCodecPlayDtmfWithStreamInfo(int *slotid, const mmsound_mgr_codec_param_t *param)
766 mmsound_codec_info_t info;
767 mmsound_codec_param_t codec_param;
768 int err = MM_ERROR_NONE;
773 plugin_id = _MMSoundMgrCodecFindCodecPluginID(MM_SOUND_SUPPORTED_CODEC_DTMF);
774 if (plugin_id == -1) {
775 debug_error("Could not find proper codec plugin!!!");
776 err = MM_ERROR_SOUND_INTERNAL;
780 /*The count num means codec type DTMF */
781 debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]", param->tone, param->repeat_count, param->volume, plugin_id);
783 if (g_plugins[plugin_id].GetSupportTypes == NULL) { /* Codec not found */
784 debug_error("unsupported file type %d", plugin_id);
785 printf("unsupported file type %d", plugin_id);
786 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
791 debug_msg("Get New handle");
794 err = _mm_sound_mgr_codec_slot_get_empty(slotid);
795 if (err != MM_ERROR_NONE || *slotid < 0) {
796 debug_error("Empty g_slot is not found");
800 codec_param.tone = param->tone;
801 codec_param.repeat_count = param->repeat_count;
802 codec_param.volume = param->volume;
803 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
804 codec_param.param = *slotid;
805 codec_param.pid = (int)param->param;
806 codec_param.volume_config = -1; //setting volume config to -1 since using stream info instead of volume type
807 codec_param.stream_index = param->stream_index;
808 MMSOUND_STRNCPY(codec_param.stream_type, param->stream_type, MAX_STREAM_TYPE_LEN);
811 g_slots[*slotid].pluginid = plugin_id;
812 g_slots[*slotid].param = param->param; /* This arg is used callback data */
813 g_slots[*slotid].enable_session = param->enable_session;
816 debug_msg("Using Slotid : [%d] Slot Status : [%d]", *slotid, g_slots[*slotid].status);
819 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
820 debug_msg("Created audio handle : [%p]", g_slots[*slotid].plughandle);
821 if (err != MM_ERROR_NONE) {
822 debug_error("Plugin create fail : 0x%08X", err);
823 g_slots[*slotid].status = STATUS_IDLE;
828 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
829 if (err != MM_ERROR_NONE) {
830 debug_error("Fail to play : 0x%08X", err);
831 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
835 debug_msg("Using Slotid : [%d] Slot Status : [%d]", *slotid, g_slots[*slotid].status);
846 int MMSoundMgrCodecStop(const int slotid)
848 int err = MM_ERROR_NONE;
850 debug_enter("(Slotid : [%d])", slotid);
852 if (slotid < 0 || MANAGER_HANDLE_MAX <= slotid)
853 return MM_ERROR_INVALID_ARGUMENT;
856 if (g_slots[slotid].status == STATUS_IDLE) {
857 err = MM_ERROR_SOUND_INVALID_STATE;
858 debug_warning("The playing slots is not found, Slot ID : [%d]", slotid);
862 debug_msg("Found slot, Slotid [%d] State [%d]", slotid, g_slots[slotid].status);
865 g_slots[slotid].stop_by_user = true;
867 err = g_plugins[g_slots[slotid].pluginid].Stop(g_slots[slotid].plughandle);
868 if (err != MM_ERROR_NONE)
869 debug_error("Fail to STOP Code : 0x%08X", err);
873 debug_leave("(err : 0x%08X)", err);
877 #ifdef FOCUS_INTEGRATION
878 int MMSoundMgrCodecClearFocus(int pid)
880 int err = MM_ERROR_NONE;
883 debug_enter("(pid : [%d])", pid);
887 for (slotid = 0 ; slotid < MANAGER_HANDLE_MAX ; slotid++) {
888 if (g_slots[slotid].pid == pid) {
889 if (g_slots[slotid].focus_handle || g_slots[slotid].focus_wcb_id) {
890 if (g_slots[slotid].session_type != MM_SESSION_TYPE_CALL &&
891 g_slots[slotid].session_type != MM_SESSION_TYPE_VIDEOCALL &&
892 g_slots[slotid].session_type != MM_SESSION_TYPE_VOIP &&
893 g_slots[slotid].session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
894 g_slots[slotid].enable_session) {
895 if ((g_slots[slotid].session_options & MM_SESSION_OPTION_PAUSE_OTHERS) ||
896 g_slots[slotid].session_type == MM_SESSION_TYPE_ALARM ||
897 g_slots[slotid].session_type == MM_SESSION_TYPE_NOTIFY ||
898 g_slots[slotid].session_type == MM_SESSION_TYPE_EMERGENCY) {
899 err = mm_sound_release_focus(g_slots[slotid].focus_handle, FOCUS_FOR_BOTH, NULL);
901 debug_error("mm_sound_release_focus failed [0x%x]", err);
903 if (mm_sound_unregister_focus(g_slots[slotid].focus_handle) || err) {
904 debug_error("Focus clean up failed [0x%x]", err);
905 err = MM_ERROR_POLICY_INTERNAL;
908 } else if (!(g_slots[slotid].session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
909 err = mm_sound_unset_focus_watch_callback(g_slots[slotid].focus_wcb_id);
911 debug_error("mm_sound_unset_focus_watch_callback failed [0x%x]", err);
912 err = MM_ERROR_POLICY_INTERNAL;
917 if (mm_sound_remove_device_connected_callback(g_slots[slotid].subs_id) != MM_ERROR_NONE)
918 debug_error("mm_sound_remove_device_connected_callback() failed");
919 g_slots[slotid].focus_handle = 0;
920 g_slots[slotid].focus_wcb_id = 0;
921 g_slots[slotid].subs_id = 0;
928 debug_leave("(err : 0x%08X)", err);
934 static int _MMSoundMgrCodecStopCallback(int param)
936 int err = MM_ERROR_NONE;
938 if (param < 0 || param >= MANAGER_HANDLE_MAX) {
939 debug_error("Slot index param [%d] is invalid", param);
940 return MM_ERROR_INVALID_ARGUMENT;
943 debug_enter("(Slot : %d) stop-by-user : %d", param, g_slots[param].stop_by_user);
945 if (g_slots[param].stop_by_user == false)
948 #ifdef FOCUS_INTEGRATION
950 * Unregister FOCUS here
952 debug_msg("[CODEC MGR] enable_session %d ", g_slots[param].enable_session);
954 if (g_slots[param].focus_handle || g_slots[param].focus_wcb_id) {
955 if (g_slots[param].session_type != MM_SESSION_TYPE_CALL &&
956 g_slots[param].session_type != MM_SESSION_TYPE_VIDEOCALL &&
957 g_slots[param].session_type != MM_SESSION_TYPE_VOIP &&
958 g_slots[param].session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
959 g_slots[param].enable_session) {
960 if ((g_slots[param].session_options & MM_SESSION_OPTION_PAUSE_OTHERS) ||
961 g_slots[param].session_type == MM_SESSION_TYPE_ALARM ||
962 g_slots[param].session_type == MM_SESSION_TYPE_NOTIFY ||
963 g_slots[param].session_type == MM_SESSION_TYPE_EMERGENCY) {
964 if (g_slots[param].current_focus_type != FOCUS_NONE) {
965 err = mm_sound_release_focus(g_slots[param].focus_handle, g_slots[param].current_focus_type, NULL);
967 debug_error("mm_sound_release_focus failed [0x%x]", err);
969 if (mm_sound_unregister_focus(g_slots[param].focus_handle) || err) {
970 debug_error("Focus clean up failed [0x%x]", err);
971 err = MM_ERROR_POLICY_INTERNAL;
974 } else if (!(g_slots[param].session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
975 err = mm_sound_unset_focus_watch_callback(g_slots[param].focus_wcb_id);
977 debug_error("mm_sound_unset_focus_watch_callback failed [0x%x]", err);
978 err = MM_ERROR_POLICY_INTERNAL;
983 if (mm_sound_remove_device_connected_callback(g_slots[param].subs_id) != MM_ERROR_NONE)
984 debug_error("mm_sound_remove_device_connected_callback() failed");
988 __mm_sound_mgr_ipc_notify_play_file_end(param);
989 debug_msg("Client callback msg_type (instance) : [%d]", (int)g_slots[param].param);
991 debug_msg("Handle allocated handle : [0x%08X]", g_slots[param].plughandle);
992 err = g_plugins[g_slots[param].pluginid].Destroy(g_slots[param].plughandle);
994 debug_critical("[CODEC MGR] Fail to destroy slot number : [%d] err [0x%x]", param, err);
996 _mm_sound_mgr_codec_slot_clear(param);
997 if (_mm_sound_mgr_codec_slot_is_empty())
998 _mm_sound_mgr_codec_shutdown_timer_start();
1001 if (g_slots[param].stop_by_user == false)
1011 static int _MMSoundMgrCodecRegisterInterface(MMSoundPluginType *plugin)
1013 int err = MM_ERROR_NONE;
1015 void *getinterface = NULL;
1021 /* find emptry slot */
1022 for (plugin_id = 0; plugin_id < MM_SOUND_SUPPORTED_CODEC_NUM; plugin_id++) {
1023 if (g_plugins[plugin_id].GetSupportTypes == NULL)
1027 if (plugin_id == MM_SOUND_SUPPORTED_CODEC_NUM) {
1028 debug_critical("The plugin support type is not valid");
1029 return MM_ERROR_COMMON_OUT_OF_RANGE;
1032 err = MMSoundPluginGetSymbol(plugin, CODEC_GET_INTERFACE_FUNC_NAME, &getinterface);
1033 if (err != MM_ERROR_NONE) {
1034 debug_error("Get Symbol CODEC_GET_INTERFACE_FUNC_NAME is fail : %x", err);
1037 debug_msg("interface[%p] empty_slot[%d]", getinterface, plugin_id);
1039 err = MMSoundPlugCodecCastGetInterface(getinterface)(&g_plugins[plugin_id]);
1040 if (err != MM_ERROR_NONE) {
1041 debug_error("Get interface fail : %x", err);
1044 /* If error occur, clean interface */
1045 memset(&g_plugins[plugin_id], 0, sizeof(mmsound_codec_interface_t));
1047 if (g_plugins[plugin_id].SetThreadPool)
1048 g_plugins[plugin_id].SetThreadPool(MMSoundThreadPoolRun);