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.
34 #include <mm_session.h>
38 #include "include/mm_sound_mgr_common.h"
39 #include "include/mm_sound_mgr_codec.h"
40 #include "include/mm_sound_mgr_ipc.h"
41 #include "include/mm_sound_plugin_codec.h"
42 #include "include/mm_sound_thread_pool.h"
44 #include "../include/mm_sound_common.h"
45 #include "../include/mm_sound_focus.h"
47 #define SHUTDOWN_TIMEOUT_SEC 10
49 #define STATUS_SOUND 3
50 #define SOUND_SLOT_START 0
51 #define FOCUS_INTEGRATION
54 int (*callback)(int, void *, void *, int); /* msg_type(pid) client callback & client data info */
59 MMHandleType plughandle;
65 #ifdef FOCUS_INTEGRATION
69 mm_sound_focus_type_e current_focus_type;
74 } __mmsound_mgr_codec_handle_t;
76 static MMSoundPluginType *g_codec_plugins = NULL;
77 static __mmsound_mgr_codec_handle_t g_slots[MANAGER_HANDLE_MAX];
78 static mmsound_codec_interface_t g_plugins[MM_SOUND_SUPPORTED_CODEC_NUM];
79 static pthread_mutex_t g_slot_mutex;
80 GSourceFunc g_shutdown_cb;
83 #define SLOT_LOCK() do { pthread_mutex_lock(&g_slot_mutex); /* debug_msg("After Slot_mutex LOCK\n"); */ } while (0)
84 #define SLOT_UNLOCK() do { pthread_mutex_unlock(&g_slot_mutex); /* debug_msg("After Slot_mutex UNLOCK\n"); */ } while (0)
86 static int _MMSoundMgrCodecRegisterInterface(MMSoundPluginType *plugin);
87 static int _MMSoundMgrCodecStopCallback(int param);
90 #ifdef FOCUS_INTEGRATION
92 static void _handle_focus_event(int slotid, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e focus_state, bool is_watch)
94 int result = MM_ERROR_NONE;
96 if (g_slots[slotid].session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
97 debug_warning("session option is UNINTERRUPTIBLE, nothing to do with focus");
101 if (focus_state == FOCUS_IS_RELEASED) {
103 g_slots[slotid].current_focus_type = FOCUS_FOR_BOTH & (~focus_type);
104 debug_warning("focus is released -> stop playing");
106 result = MMSoundMgrCodecStop(slotid);
107 if (result != MM_ERROR_NONE)
108 debug_error("result error 0x%X", result);
112 static void _sound_codec_focus_callback(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e focus_state,
113 const char *reason_for_change, int option, const char *ext_info, void *user_data)
115 debug_warning("focus callback called -> focus_state(%d), reason_for_change(%s)",
116 focus_state, reason_for_change ? reason_for_change : "N/A");
118 _handle_focus_event((int)user_data, focus_type, focus_state, false);
121 static void _sound_codec_focus_watch_callback(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e focus_state,
122 const char *reason_for_change, const char *ext_info, void *user_data)
124 debug_warning("focus watch callback called -> focus_state(%d), reason_for_change(%s)",
125 focus_state, reason_for_change ? reason_for_change : "N/A");
127 _handle_focus_event((int)user_data, focus_type, focus_state, true);
130 static void _sound_codec_device_connected_callback(MMSoundDevice_t device, bool is_connected, void *user_data)
132 int slotid = (int)user_data;
133 int result = MM_ERROR_NONE;
134 mm_sound_device_type_e type;
136 debug_warning ("device_connected_callback called : handle[%p], connected[%d], slotid[%d]", device, is_connected, slotid);
138 if (mm_sound_get_device_type (device, &type) != MM_ERROR_NONE) {
139 debug_error("getting device type failed");
144 case MM_SOUND_DEVICE_TYPE_AUDIOJACK:
145 case MM_SOUND_DEVICE_TYPE_BLUETOOTH:
146 case MM_SOUND_DEVICE_TYPE_HDMI:
147 case MM_SOUND_DEVICE_TYPE_MIRRORING:
148 case MM_SOUND_DEVICE_TYPE_USB_AUDIO:
150 debug_warning("sound device unplugged");
151 result = MMSoundMgrCodecStop(slotid);
152 if (result != MM_ERROR_NONE)
153 debug_error("MMSoundMgrCodecStop error %d\n", result);
155 result = mm_sound_remove_device_connected_callback(g_slots[slotid].subs_id);
156 if (result != MM_ERROR_NONE)
157 debug_error("mm_sound_remove_device_connected_callback error %d\n", result);
167 /* FIXME : critical section for g_timer_id? */
168 static void _mm_sound_mgr_codec_shutdown_timer_start()
170 if (g_timer_id > 0) {
171 debug_error("Already active timer [%d] exists", g_timer_id);
176 g_timer_id = g_timeout_add_seconds(SHUTDOWN_TIMEOUT_SEC, g_shutdown_cb, NULL);
177 debug_error("TIMER : new timer [%d]", g_timer_id);
179 debug_warning("No Timer started due to invalid shutdown callback");
183 static void _mm_sound_mgr_codec_shutdown_timer_stop()
185 if (g_timer_id > 0) {
186 debug_error("TIMER : remove timer id [%d]", g_timer_id);
187 g_source_remove(g_timer_id);
190 debug_log("No Timer to stop...");
194 static int _mm_sound_mgr_codec_slot_get_empty(int *slot)
197 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])\n", slotid);
212 _mm_sound_mgr_codec_shutdown_timer_stop();
215 debug_warning("Handle is full handle : [%d]\n", slotid);
217 /* Temporal code for reset */
219 g_slots[slotid].status = STATUS_IDLE;
221 err = MM_ERROR_SOUND_INTERNAL;
229 static gboolean _mm_sound_mgr_codec_slot_is_empty()
233 for (slotid = SOUND_SLOT_START; slotid < MANAGER_HANDLE_MAX ; slotid++) {
234 if (g_slots[slotid].status == STATUS_SOUND)
238 return (slotid == MANAGER_HANDLE_MAX) ? TRUE : FALSE;
241 static void _mm_sound_mgr_codec_slot_clear(int slotid)
243 memset(&g_slots[slotid], 0, sizeof(__mmsound_mgr_codec_handle_t));
244 g_slots[slotid].status = STATUS_IDLE;
246 debug_error("SlotID [%d] cleared", slotid);
249 int MMSoundMgrCodecInit(const char *targetdir, GSourceFunc _shutdown_cb)
256 memset(g_slots, 0, sizeof(g_slots));
258 if (pthread_mutex_init(&g_slot_mutex, NULL)) {
259 debug_error("pthread_mutex_init failed\n");
260 return MM_ERROR_SOUND_INTERNAL;
263 for (slotid = 0; slotid < MANAGER_HANDLE_MAX; slotid++)
264 _mm_sound_mgr_codec_slot_clear(slotid);
266 if (g_codec_plugins) {
267 debug_warning("Please Check Init twice\n");
268 MMSoundPluginRelease(g_codec_plugins);
271 MMSoundPluginScan(targetdir, MM_SOUND_PLUGIN_TYPE_CODEC, &g_codec_plugins);
272 if (g_codec_plugins) {
273 while (g_codec_plugins[loop].type != MM_SOUND_PLUGIN_TYPE_NONE) {
274 _MMSoundMgrCodecRegisterInterface(&g_codec_plugins[loop++]);
279 g_shutdown_cb = _shutdown_cb;
281 debug_warning("shutdown callback is NULL");
284 return MM_ERROR_NONE;
287 int MMSoundMgrCodecFini(void)
291 memset(g_plugins, 0, sizeof(mmsound_codec_interface_t) * MM_SOUND_SUPPORTED_CODEC_NUM);
292 MMSoundPluginRelease(g_codec_plugins);
293 g_codec_plugins = NULL;
294 pthread_mutex_destroy(&g_slot_mutex);
297 return MM_ERROR_NONE;
300 static int _MMSoundMgrCodecFindCodecPluginID(enum MMSoundSupportedCodec codec_to_find)
305 for (plugin_id = 0; plugin_id < MM_SOUND_SUPPORTED_CODEC_NUM; plugin_id++) {
306 if (g_plugins[plugin_id].GetSupportTypes) {
307 codec_type = g_plugins[plugin_id].GetSupportTypes();
308 if (codec_type[0] == codec_to_find)
316 int MMSoundMgrCodecPlay(int *slotid, const mmsound_mgr_codec_param_t *param)
319 mmsound_codec_info_t info;
320 mmsound_codec_param_t codec_param;
321 int err = MM_ERROR_NONE;
323 #ifdef FOCUS_INTEGRATION
324 int need_focus_unregister = 0;
330 plugin_id = _MMSoundMgrCodecFindCodecPluginID(MM_SOUND_SUPPORTED_CODEC_WAVE);
331 if (plugin_id == -1) {
332 debug_error("Could not find proper codec plugin!!!");
333 err = MM_ERROR_SOUND_INTERNAL;
337 err = g_plugins[plugin_id].Parse(param->pfilename, &info);
338 if (err != MM_ERROR_NONE) {
339 debug_error("Could not parse file [%s] by plugin[%d]\n", param->pfilename, plugin_id);
343 debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, plugin_id);
346 debug_msg("Get New handle\n");
349 err = _mm_sound_mgr_codec_slot_get_empty(slotid);
350 if (err != MM_ERROR_NONE || *slotid < 0) {
351 debug_error("Empty g_slot is not found\n");
355 codec_param.tone = param->tone;
356 codec_param.volume_config = param->volume_config;
357 codec_param.repeat_count = param->repeat_count;
358 codec_param.volume = param->volume;
359 codec_param.pfilename = param->pfilename;
360 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
361 codec_param.param = *slotid;
362 codec_param.pid = (int)param->param;
363 codec_param.stream_index = param->stream_index;
364 MMSOUND_STRNCPY(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
367 #ifdef FOCUS_INTEGRATION
369 * Register FOCUS here
372 if (param->session_type != MM_SESSION_TYPE_CALL &&
373 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
374 param->session_type != MM_SESSION_TYPE_VOIP &&
375 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
376 param->enable_session) {
378 unsigned int subs_id = 0;
380 err = mm_sound_add_device_connected_callback(MM_SOUND_DEVICE_STATE_ACTIVATED_FLAG,
381 (mm_sound_device_connected_cb)_sound_codec_device_connected_callback,
382 (void*) *slotid, &subs_id);
384 debug_error("mm_sound_add_device_connected_callback failed [0x%x]", err);
386 return MM_ERROR_POLICY_INTERNAL;
388 g_slots[*slotid].subs_id = subs_id;
390 if ((param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS) ||
391 param->session_type == MM_SESSION_TYPE_ALARM ||
392 param->session_type == MM_SESSION_TYPE_NOTIFY ||
393 param->session_type == MM_SESSION_TYPE_EMERGENCY) {
394 debug_warning("session option is PAUSE_OTHERS -> acquire focus");
395 err = mm_sound_focus_get_id((int *)(¶m->focus_handle));
396 err = mm_sound_register_focus_for_session(param->focus_handle, (int)param->param, "media", _sound_codec_focus_callback, (void*)*slotid);
398 debug_error("mm_sound_register_focus_for_session failed [0x%x]", err);
400 return MM_ERROR_POLICY_INTERNAL;
402 err = mm_sound_acquire_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
404 debug_error("mm_sound_acquire_focus failed [0x%x]", err);
405 err = mm_sound_unregister_focus(param->focus_handle);
407 return MM_ERROR_POLICY_INTERNAL;
409 g_slots[*slotid].current_focus_type = FOCUS_FOR_BOTH;
410 } else if (param->session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
412 debug_warning("session option is UNINTERRUPTIBLE, nothing to do with focus");
414 debug_warning("need to set focus watch callback");
415 err = mm_sound_set_focus_watch_callback_for_session((int)param->param, FOCUS_FOR_BOTH, _sound_codec_focus_watch_callback,
416 (void*)*slotid, (int *)(¶m->focus_wcb_id));
418 debug_error("mm_sound_set_focus_watch_callback_for_session failed [0x%x]", err);
420 return MM_ERROR_POLICY_INTERNAL;
427 /* Codec id WAV or MP3 */
428 g_slots[*slotid].pluginid = plugin_id;
429 g_slots[*slotid].param = param->param; /* This arg is used callback data */
430 g_slots[*slotid].session_type = param->session_type;
431 g_slots[*slotid].session_options = param->session_options;
432 #ifdef FOCUS_INTEGRATION
433 g_slots[*slotid].focus_handle = param->focus_handle;
434 g_slots[*slotid].focus_wcb_id = param->focus_wcb_id;
436 g_slots[*slotid].enable_session = true;
437 g_slots[*slotid].pid = (int)param->param;
440 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
442 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
443 debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
444 if (err != MM_ERROR_NONE) {
445 debug_error("Plugin create fail : 0x%08X\n", err);
446 g_slots[*slotid].status = STATUS_IDLE;
448 #ifdef FOCUS_INTEGRATION
449 if (param->focus_handle) {
450 need_focus_unregister = 1;
456 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
457 if (err != MM_ERROR_NONE) {
458 debug_error("Fail to play : 0x%08X\n", err);
459 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
460 #ifdef FOCUS_INTEGRATION
461 if (param->focus_handle) {
462 need_focus_unregister = 1;
470 if (_mm_sound_mgr_codec_slot_is_empty())
471 _mm_sound_mgr_codec_shutdown_timer_start();
473 #ifdef FOCUS_INTEGRATION
474 if (param->session_type != MM_SESSION_TYPE_CALL &&
475 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
476 param->session_type != MM_SESSION_TYPE_VOIP &&
477 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
478 param->enable_session &&
479 need_focus_unregister == 1) {
481 if ((param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS) ||
482 param->session_type == MM_SESSION_TYPE_ALARM ||
483 param->session_type == MM_SESSION_TYPE_NOTIFY ||
484 param->session_type == MM_SESSION_TYPE_EMERGENCY) {
485 err = mm_sound_release_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
486 if (mm_sound_unregister_focus(param->focus_handle) || err) {
487 debug_error("focus cleaning up failed[0x%x]", err);
488 return MM_ERROR_POLICY_INTERNAL;
490 } else if (~(param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
491 err = mm_sound_unset_focus_watch_callback(param->focus_wcb_id);
493 debug_error("focus watch cleaning up failed[0x%x]", err);
494 return MM_ERROR_POLICY_INTERNAL;
508 int MMSoundMgrCodecPlayWithStreamInfo(int *slotid, const mmsound_mgr_codec_param_t *param)
511 mmsound_codec_info_t info;
512 mmsound_codec_param_t codec_param;
513 int err = MM_ERROR_NONE;
518 plugin_id = _MMSoundMgrCodecFindCodecPluginID(MM_SOUND_SUPPORTED_CODEC_WAVE);
519 if (plugin_id == -1) {
520 debug_error("Could not find proper codec plugin!!!");
521 err = MM_ERROR_SOUND_INTERNAL;
525 err = g_plugins[plugin_id].Parse(param->pfilename, &info);
526 if (err != MM_ERROR_NONE) {
527 debug_error("Could not parse file [%s] by plugin[%d]\n", param->pfilename, plugin_id);
531 err = _mm_sound_mgr_codec_slot_get_empty(slotid);
532 if (err != MM_ERROR_NONE || *slotid < 0) {
533 debug_error("Empty g_slot is not found\n");
537 codec_param.volume_config = -1; //setting volume config to -1 since using stream info instead of volume type
538 codec_param.repeat_count = param->repeat_count;
539 codec_param.volume = param->volume;
540 codec_param.pfilename = param->pfilename;
541 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
542 codec_param.param = *slotid;
543 codec_param.pid = (int)param->param;
544 codec_param.stream_index = param->stream_index;
545 MMSOUND_STRNCPY(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
548 /* Codec id WAV or MP3 */
549 g_slots[*slotid].pluginid = plugin_id;
550 g_slots[*slotid].param = param->param; /* This arg is used callback data */
552 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
554 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
555 debug_msg("Created audio handle : [%p]\n", g_slots[*slotid].plughandle);
556 if (err != MM_ERROR_NONE) {
557 debug_error("Plugin create fail : 0x%08X\n", err);
558 g_slots[*slotid].status = STATUS_IDLE;
563 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
564 if (err != MM_ERROR_NONE) {
565 debug_error("Fail to play : 0x%08X\n", err);
566 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
572 if (_mm_sound_mgr_codec_slot_is_empty())
573 _mm_sound_mgr_codec_shutdown_timer_start();
583 #define DTMF_PLUGIN_COUNT 2
584 int MMSoundMgrCodecPlayDtmf(int *slotid, const mmsound_mgr_codec_param_t *param)
588 mmsound_codec_info_t info;
589 mmsound_codec_param_t codec_param;
590 int err = MM_ERROR_NONE;
591 #ifdef FOCUS_INTEGRATION
592 int need_focus_unregister = 0;
599 for (plugin_id = 0; g_plugins[plugin_id].GetSupportTypes; plugin_id++) {
601 codec_type = g_plugins[plugin_id].GetSupportTypes();
602 if (codec_type && (MM_SOUND_SUPPORTED_CODEC_DTMF == codec_type[0]))
606 /*The count num means codec type DTMF */
607 debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, plugin_id);
609 if (g_plugins[plugin_id].GetSupportTypes == NULL) { /* Codec not found */
610 debug_error("unsupported file type %d\n", plugin_id);
611 printf("unsupported file type %d\n", plugin_id);
612 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
617 debug_msg("Get New handle\n");
620 err = _mm_sound_mgr_codec_slot_get_empty(slotid);
621 if (err != MM_ERROR_NONE || *slotid < 0) {
622 debug_error("Empty g_slot is not found\n");
626 codec_param.tone = param->tone;
627 codec_param.volume_config = param->volume_config;
628 codec_param.repeat_count = param->repeat_count;
629 codec_param.volume = param->volume;
630 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
631 codec_param.param = *slotid;
632 codec_param.pid = (int)param->param;
633 codec_param.stream_index = param->stream_index;
634 MMSOUND_STRNCPY(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
637 #ifdef FOCUS_INTEGRATION
640 * Register FOCUS here
643 if (param->session_type != MM_SESSION_TYPE_CALL &&
644 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
645 param->session_type != MM_SESSION_TYPE_VOIP &&
646 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
647 param->enable_session) {
649 unsigned int subs_id = 0;
651 err = mm_sound_add_device_connected_callback(MM_SOUND_DEVICE_STATE_ACTIVATED_FLAG,
652 (mm_sound_device_connected_cb)_sound_codec_device_connected_callback,
653 (void*) *slotid, &subs_id);
655 debug_error("mm_sound_add_device_connected_callback failed [0x%x]", err);
657 return MM_ERROR_POLICY_INTERNAL;
659 g_slots[*slotid].subs_id = subs_id;
661 if ((param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS) ||
662 param->session_type == MM_SESSION_TYPE_ALARM ||
663 param->session_type == MM_SESSION_TYPE_NOTIFY ||
664 param->session_type == MM_SESSION_TYPE_EMERGENCY) {
665 debug_warning("session option is PAUSE_OTHERS -> acquire focus");
666 err = mm_sound_focus_get_id((int *)(¶m->focus_handle));
667 err = mm_sound_register_focus_for_session(param->focus_handle, (int)param->param, "media", _sound_codec_focus_callback, (void*)*slotid);
669 debug_error("mm_sound_register_focus failed [0x%x]", err);
671 return MM_ERROR_POLICY_INTERNAL;
673 err = mm_sound_acquire_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
675 debug_error("mm_sound_acquire_focus failed [0x%x]", err);
676 err = mm_sound_unregister_focus(param->focus_handle);
678 return MM_ERROR_POLICY_INTERNAL;
680 g_slots[*slotid].current_focus_type = FOCUS_FOR_BOTH;
681 } else if (param->session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
683 debug_warning("session option is UNINTERRUPTIBLE, nothing to do with focus");
685 debug_warning("need to set focus watch callback");
686 err = mm_sound_set_focus_watch_callback_for_session((int)param->param, FOCUS_FOR_BOTH, _sound_codec_focus_watch_callback,
687 (void*)*slotid, (int *)(¶m->focus_wcb_id));
689 debug_error("mm_sound_set_focus_watch_callback failed [0x%x]", err);
691 return MM_ERROR_POLICY_INTERNAL;
697 g_slots[*slotid].pluginid = plugin_id;
698 g_slots[*slotid].param = param->param; /* This arg is used callback data */
699 g_slots[*slotid].session_type = param->session_type;
700 g_slots[*slotid].session_options = param->session_options;
701 #ifdef FOCUS_INTEGRATION
702 g_slots[*slotid].focus_handle= param->focus_handle;
703 g_slots[*slotid].focus_wcb_id= param->focus_wcb_id;
705 g_slots[*slotid].enable_session = param->enable_session;
706 g_slots[*slotid].pid = (int)param->param;
709 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
712 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
713 debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
714 if (err != MM_ERROR_NONE) {
715 debug_error("Plugin create fail : 0x%08X\n", err);
716 g_slots[*slotid].status = STATUS_IDLE;
718 #ifdef FOCUS_INTEGRATION
719 need_focus_unregister = 1;
724 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
725 if (err != MM_ERROR_NONE) {
726 debug_error("Fail to play : 0x%08X\n", err);
727 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
728 #ifdef FOCUS_INTEGRATION
729 need_focus_unregister = 1;
734 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
737 #ifdef FOCUS_INTEGRATION
738 if (param->session_type != MM_SESSION_TYPE_CALL &&
739 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
740 param->session_type != MM_SESSION_TYPE_VOIP &&
741 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
742 param->enable_session &&
743 need_focus_unregister == 1) {
745 if ((param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS) ||
746 param->session_type == MM_SESSION_TYPE_ALARM ||
747 param->session_type == MM_SESSION_TYPE_NOTIFY ||
748 param->session_type == MM_SESSION_TYPE_EMERGENCY) {
749 err = mm_sound_release_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
750 if (mm_sound_unregister_focus(param->focus_handle) || err) {
751 debug_error("focus cleaning up failed[0x%x]", err);
752 return MM_ERROR_POLICY_INTERNAL;
754 } else if (~(param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
755 err = mm_sound_unset_focus_watch_callback(param->focus_wcb_id);
757 debug_error("focus watch cleaning up failed[0x%x]", err);
758 return MM_ERROR_POLICY_INTERNAL;
771 int MMSoundMgrCodecPlayDtmfWithStreamInfo(int *slotid, const mmsound_mgr_codec_param_t *param)
775 mmsound_codec_info_t info;
776 mmsound_codec_param_t codec_param;
777 int err = MM_ERROR_NONE;
783 for (plugin_id = 0; g_plugins[plugin_id].GetSupportTypes; plugin_id++) {
785 codec_type = g_plugins[plugin_id].GetSupportTypes();
786 if (codec_type && (MM_SOUND_SUPPORTED_CODEC_DTMF == codec_type[0]))
790 /*The count num means codec type DTMF */
791 debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, plugin_id);
793 if (g_plugins[plugin_id].GetSupportTypes == NULL) { /* Codec not found */
794 debug_error("unsupported file type %d\n", plugin_id);
795 printf("unsupported file type %d\n", plugin_id);
796 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
801 debug_msg("Get New handle\n");
804 err = _mm_sound_mgr_codec_slot_get_empty(slotid);
805 if (err != MM_ERROR_NONE || *slotid < 0)
807 debug_error("Empty g_slot is not found\n");
811 codec_param.tone = param->tone;
812 codec_param.repeat_count = param->repeat_count;
813 codec_param.volume = param->volume;
814 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
815 codec_param.param = *slotid;
816 codec_param.pid = (int)param->param;
817 codec_param.volume_config = -1; //setting volume config to -1 since using stream info instead of volume type
818 codec_param.stream_index = param->stream_index;
819 MMSOUND_STRNCPY(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
822 g_slots[*slotid].pluginid = plugin_id;
823 g_slots[*slotid].param = param->param; /* This arg is used callback data */
824 g_slots[*slotid].enable_session = param->enable_session;
827 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
830 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
831 debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
832 if (err != MM_ERROR_NONE) {
833 debug_error("Plugin create fail : 0x%08X\n", err);
834 g_slots[*slotid].status = STATUS_IDLE;
839 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
840 if (err != MM_ERROR_NONE) {
841 debug_error("Fail to play : 0x%08X\n", err);
842 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
846 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
857 int MMSoundMgrCodecStop(const int slotid)
859 int err = MM_ERROR_NONE;
861 debug_enter("(Slotid : [%d])\n", slotid);
863 if (slotid < 0 || MANAGER_HANDLE_MAX <= slotid) {
864 return MM_ERROR_INVALID_ARGUMENT;
868 if (g_slots[slotid].status == STATUS_IDLE) {
869 err = MM_ERROR_SOUND_INVALID_STATE;
870 debug_warning("The playing slots is not found, Slot ID : [%d]\n", slotid);
874 debug_msg("Found slot, Slotid [%d] State [%d]\n", slotid, g_slots[slotid].status);
877 g_slots[slotid].stop_by_user = true;
879 err = g_plugins[g_slots[slotid].pluginid].Stop(g_slots[slotid].plughandle);
880 if (err != MM_ERROR_NONE) {
881 debug_error("Fail to STOP Code : 0x%08X\n", err);
886 debug_leave("(err : 0x%08X)\n", err);
890 #ifdef FOCUS_INTEGRATION
891 int MMSoundMgrCodecClearFocus(int pid)
893 int err = MM_ERROR_NONE;
896 debug_enter("(pid : [%d])\n", pid);
900 for (slotid = 0 ; slotid < MANAGER_HANDLE_MAX ; slotid++) {
901 if (g_slots[slotid].pid == pid) {
902 if (g_slots[slotid].focus_handle || g_slots[slotid].focus_wcb_id) {
903 if (g_slots[slotid].session_type != MM_SESSION_TYPE_CALL &&
904 g_slots[slotid].session_type != MM_SESSION_TYPE_VIDEOCALL &&
905 g_slots[slotid].session_type != MM_SESSION_TYPE_VOIP &&
906 g_slots[slotid].session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
907 g_slots[slotid].enable_session ) {
908 if ((g_slots[slotid].session_options & MM_SESSION_OPTION_PAUSE_OTHERS) ||
909 g_slots[slotid].session_type == MM_SESSION_TYPE_ALARM ||
910 g_slots[slotid].session_type == MM_SESSION_TYPE_NOTIFY ||
911 g_slots[slotid].session_type == MM_SESSION_TYPE_EMERGENCY) {
912 err = mm_sound_release_focus(g_slots[slotid].focus_handle, FOCUS_FOR_BOTH, NULL);
914 debug_error("mm_sound_release_focus failed [0x%x]", err);
916 if (mm_sound_unregister_focus(g_slots[slotid].focus_handle) || err) {
917 debug_error("Focus clean up failed [0x%x]", err);
918 err = MM_ERROR_POLICY_INTERNAL;
921 } else if (~(g_slots[slotid].session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
922 err = mm_sound_unset_focus_watch_callback(g_slots[slotid].focus_wcb_id);
924 debug_error("mm_sound_unset_focus_watch_callback failed [0x%x]", err);
925 err = MM_ERROR_POLICY_INTERNAL;
930 if (mm_sound_remove_device_connected_callback(g_slots[slotid].subs_id) != MM_ERROR_NONE)
931 debug_error("mm_sound_remove_device_connected_callback() failed");
932 g_slots[slotid].focus_handle = 0;
933 g_slots[slotid].focus_wcb_id = 0;
934 g_slots[slotid].subs_id = 0;
941 debug_leave("(err : 0x%08X)\n", err);
947 static int _MMSoundMgrCodecStopCallback(int param)
949 int err = MM_ERROR_NONE;
951 debug_enter("(Slot : %d)\n", param);
953 if (param < 0 || param >= MANAGER_HANDLE_MAX) {
954 debug_error ("Slot index param [%d] is invalid", param);
955 return MM_ERROR_INVALID_ARGUMENT;
958 if (g_slots[param].stop_by_user == false) {
962 #ifdef FOCUS_INTEGRATION
964 * Unregister FOCUS here
966 debug_msg("[CODEC MGR] enable_session %d ",g_slots[param].enable_session);
968 if (g_slots[param].focus_handle || g_slots[param].focus_wcb_id) {
969 if (g_slots[param].session_type != MM_SESSION_TYPE_CALL &&
970 g_slots[param].session_type != MM_SESSION_TYPE_VIDEOCALL &&
971 g_slots[param].session_type != MM_SESSION_TYPE_VOIP &&
972 g_slots[param].session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
973 g_slots[param].enable_session ) {
974 if ((g_slots[param].session_options & MM_SESSION_OPTION_PAUSE_OTHERS) ||
975 g_slots[param].session_type == MM_SESSION_TYPE_ALARM ||
976 g_slots[param].session_type == MM_SESSION_TYPE_NOTIFY ||
977 g_slots[param].session_type == MM_SESSION_TYPE_EMERGENCY) {
978 if (g_slots[param].current_focus_type != FOCUS_NONE) {
979 err = mm_sound_release_focus(g_slots[param].focus_handle, g_slots[param].current_focus_type, NULL);
981 debug_error("mm_sound_release_focus failed [0x%x]", err);
984 if (mm_sound_unregister_focus(g_slots[param].focus_handle) || err) {
985 debug_error("Focus clean up failed [0x%x]", err);
986 err = MM_ERROR_POLICY_INTERNAL;
989 } else if (~(g_slots[param].session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
990 err = mm_sound_unset_focus_watch_callback(g_slots[param].focus_wcb_id);
992 debug_error("mm_sound_unset_focus_watch_callback failed [0x%x]", err);
993 err = MM_ERROR_POLICY_INTERNAL;
998 if (mm_sound_remove_device_connected_callback(g_slots[param].subs_id) != MM_ERROR_NONE)
999 debug_error("mm_sound_remove_device_connected_callback() failed");
1003 if (g_slots[param].stop_by_user == false) {
1004 __mm_sound_mgr_ipc_notify_play_file_end(param);
1005 debug_msg("Client callback msg_type (instance) : [%d]\n", (int)g_slots[param].param);
1008 debug_msg("Handle allocated handle : [0x%08X]\n", g_slots[param].plughandle);
1009 err = g_plugins[g_slots[param].pluginid].Destroy(g_slots[param].plughandle);
1011 debug_critical("[CODEC MGR] Fail to destroy slot number : [%d] err [0x%x]\n", param, err);
1013 _mm_sound_mgr_codec_slot_clear(param);
1014 if (_mm_sound_mgr_codec_slot_is_empty())
1015 _mm_sound_mgr_codec_shutdown_timer_start();
1018 if (g_slots[param].stop_by_user == false) {
1029 static int _MMSoundMgrCodecRegisterInterface(MMSoundPluginType *plugin)
1031 int err = MM_ERROR_NONE;
1033 void *getinterface = NULL;
1039 /* find emptry slot */
1040 for (plugin_id = 0; plugin_id < MM_SOUND_SUPPORTED_CODEC_NUM; plugin_id++) {
1041 if (g_plugins[plugin_id].GetSupportTypes == NULL)
1045 if (plugin_id == MM_SOUND_SUPPORTED_CODEC_NUM) {
1046 debug_critical("The plugin support type is not valid\n");
1047 return MM_ERROR_COMMON_OUT_OF_RANGE;
1050 err = MMSoundPluginGetSymbol(plugin, CODEC_GET_INTERFACE_FUNC_NAME, &getinterface);
1051 if (err != MM_ERROR_NONE) {
1052 debug_error("Get Symbol CODEC_GET_INTERFACE_FUNC_NAME is fail : %x\n", err);
1055 debug_msg("interface[%p] empty_slot[%d]\n", getinterface, plugin_id);
1057 err = MMSoundPlugCodecCastGetInterface(getinterface)(&g_plugins[plugin_id]);
1058 if (err != MM_ERROR_NONE) {
1059 debug_error("Get interface fail : %x\n", err);
1062 /* If error occur, clean interface */
1063 memset(&g_plugins[plugin_id], 0, sizeof(mmsound_codec_interface_t));
1065 if (g_plugins[plugin_id].SetThreadPool)
1066 g_plugins[plugin_id].SetThreadPool(MMSoundThreadPoolRun);