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.
31 #include <mm_session.h>
35 #include "include/mm_sound_mgr_codec.h"
36 #include "include/mm_sound_mgr_ipc.h"
37 #include "include/mm_sound_plugin_codec.h"
38 #include "include/mm_sound_thread_pool.h"
40 #include "../include/mm_sound_common.h"
41 #include "../include/mm_sound_focus.h"
42 #include "../include/mm_sound.h"
44 #define SHUTDOWN_TIMEOUT_SEC 10
46 #define STATUS_SOUND 3
47 #define SOUND_SLOT_START 0
48 #define FOCUS_INTEGRATION
49 #define MANAGER_HANDLE_MAX 256
52 int (*callback)(int, void *, void *, int); /* msg_type(pid) client callback & client data info */
57 MMHandleType plughandle;
63 #ifdef FOCUS_INTEGRATION
67 mm_sound_focus_type_e current_focus_type;
72 } __mmsound_mgr_codec_handle_t;
74 static MMSoundPluginType *g_codec_plugins = NULL;
75 static __mmsound_mgr_codec_handle_t g_slots[MANAGER_HANDLE_MAX];
76 static mmsound_codec_interface_t g_plugins[MM_SOUND_SUPPORTED_CODEC_NUM];
77 static pthread_mutex_t g_slot_mutex;
78 GSourceFunc g_shutdown_cb;
81 #define SLOT_LOCK() do { pthread_mutex_lock(&g_slot_mutex); /* debug_msg("After Slot_mutex LOCK\n"); */ } while (0)
82 #define SLOT_UNLOCK() do { pthread_mutex_unlock(&g_slot_mutex); /* debug_msg("After Slot_mutex UNLOCK\n"); */ } while (0)
84 static int _MMSoundMgrCodecRegisterInterface(MMSoundPluginType *plugin);
85 static int _MMSoundMgrCodecStopCallback(int param);
88 #ifdef FOCUS_INTEGRATION
90 static void _handle_focus_event(int slotid, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e focus_state, bool is_watch)
92 int result = MM_ERROR_NONE;
94 if (g_slots[slotid].session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
95 debug_warning("session option is UNINTERRUPTIBLE, nothing to do with focus");
99 if (focus_state == FOCUS_IS_RELEASED) {
101 g_slots[slotid].current_focus_type = FOCUS_FOR_BOTH & (~focus_type);
102 debug_warning("focus is released -> stop playing");
104 result = MMSoundMgrCodecStop(slotid);
105 if (result != MM_ERROR_NONE)
106 debug_error("result error 0x%X", result);
110 static void _sound_codec_focus_callback(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e focus_state,
111 const char *reason_for_change, int option, const char *ext_info, void *user_data)
113 debug_warning("focus callback called -> focus_state(%d), reason_for_change(%s)",
114 focus_state, reason_for_change ? reason_for_change : "N/A");
116 _handle_focus_event((int)user_data, focus_type, focus_state, false);
119 static void _sound_codec_focus_watch_callback(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e focus_state,
120 const char *reason_for_change, const char *ext_info, void *user_data)
122 debug_warning("focus watch callback called -> focus_state(%d), reason_for_change(%s)",
123 focus_state, reason_for_change ? reason_for_change : "N/A");
125 _handle_focus_event((int)user_data, focus_type, focus_state, true);
128 static void _sound_codec_device_connected_callback(MMSoundDevice_t device, bool is_connected, void *user_data)
130 int slotid = (int)user_data;
131 int result = MM_ERROR_NONE;
132 mm_sound_device_type_e type;
134 debug_warning ("device_connected_callback called : handle[%p], connected[%d], slotid[%d]", device, is_connected, slotid);
136 if (mm_sound_get_device_type (device, &type) != MM_ERROR_NONE) {
137 debug_error("getting device type failed");
142 case MM_SOUND_DEVICE_TYPE_AUDIOJACK:
143 case MM_SOUND_DEVICE_TYPE_BLUETOOTH:
144 case MM_SOUND_DEVICE_TYPE_HDMI:
145 case MM_SOUND_DEVICE_TYPE_MIRRORING:
146 case MM_SOUND_DEVICE_TYPE_USB_AUDIO:
148 debug_warning("sound device unplugged");
149 result = MMSoundMgrCodecStop(slotid);
150 if (result != MM_ERROR_NONE)
151 debug_error("MMSoundMgrCodecStop error %d\n", result);
153 result = mm_sound_remove_device_connected_callback(g_slots[slotid].subs_id);
154 if (result != MM_ERROR_NONE)
155 debug_error("mm_sound_remove_device_connected_callback error %d\n", result);
165 /* FIXME : critical section for g_timer_id? */
166 static void _mm_sound_mgr_codec_shutdown_timer_start()
168 if (g_timer_id > 0) {
169 debug_error("Already active timer [%d] exists", g_timer_id);
174 g_timer_id = g_timeout_add_seconds(SHUTDOWN_TIMEOUT_SEC, g_shutdown_cb, NULL);
175 debug_error("TIMER : new timer [%d]", g_timer_id);
177 debug_warning("No Timer started due to invalid shutdown callback");
181 static void _mm_sound_mgr_codec_shutdown_timer_stop()
183 if (g_timer_id > 0) {
184 debug_error("TIMER : remove timer id [%d]", g_timer_id);
185 g_source_remove(g_timer_id);
188 debug_log("No Timer to stop...");
192 static int _mm_sound_mgr_codec_slot_get_empty(int *slot)
195 int err = MM_ERROR_NONE;
199 for (slotid = SOUND_SLOT_START; slotid < MANAGER_HANDLE_MAX ; slotid++) {
200 if (g_slots[slotid].status == STATUS_IDLE) {
201 g_slots[slotid].status = STATUS_SOUND;
206 if (slotid < MANAGER_HANDLE_MAX) {
207 debug_msg("New handle allocated (codec slot ID : [%d])\n", slotid);
210 _mm_sound_mgr_codec_shutdown_timer_stop();
213 debug_warning("Handle is full handle : [%d]\n", slotid);
215 /* Temporal code for reset */
217 g_slots[slotid].status = STATUS_IDLE;
219 err = MM_ERROR_SOUND_INTERNAL;
227 static gboolean _mm_sound_mgr_codec_slot_is_empty()
231 for (slotid = SOUND_SLOT_START; slotid < MANAGER_HANDLE_MAX ; slotid++) {
232 if (g_slots[slotid].status == STATUS_SOUND)
236 return (slotid == MANAGER_HANDLE_MAX) ? TRUE : FALSE;
239 static void _mm_sound_mgr_codec_slot_clear(int slotid)
241 memset(&g_slots[slotid], 0, sizeof(__mmsound_mgr_codec_handle_t));
242 g_slots[slotid].status = STATUS_IDLE;
244 debug_error("SlotID [%d] cleared", slotid);
247 int MMSoundMgrCodecInit(const char *targetdir, GSourceFunc _shutdown_cb)
254 memset(g_slots, 0, sizeof(g_slots));
256 if (pthread_mutex_init(&g_slot_mutex, NULL)) {
257 debug_error("pthread_mutex_init failed\n");
258 return MM_ERROR_SOUND_INTERNAL;
261 for (slotid = 0; slotid < MANAGER_HANDLE_MAX; slotid++)
262 _mm_sound_mgr_codec_slot_clear(slotid);
264 if (g_codec_plugins) {
265 debug_warning("Please Check Init twice\n");
266 MMSoundPluginRelease(g_codec_plugins);
269 MMSoundPluginScan(targetdir, MM_SOUND_PLUGIN_TYPE_CODEC, &g_codec_plugins);
270 if (g_codec_plugins) {
271 while (g_codec_plugins[loop].type != MM_SOUND_PLUGIN_TYPE_NONE) {
272 _MMSoundMgrCodecRegisterInterface(&g_codec_plugins[loop++]);
277 g_shutdown_cb = _shutdown_cb;
279 debug_warning("shutdown callback is NULL");
282 return MM_ERROR_NONE;
285 int MMSoundMgrCodecFini(void)
289 memset(g_plugins, 0, sizeof(mmsound_codec_interface_t) * MM_SOUND_SUPPORTED_CODEC_NUM);
290 MMSoundPluginRelease(g_codec_plugins);
291 g_codec_plugins = NULL;
292 pthread_mutex_destroy(&g_slot_mutex);
295 return MM_ERROR_NONE;
298 static int _MMSoundMgrCodecFindCodecPluginID(enum MMSoundSupportedCodec codec_to_find)
303 for (plugin_id = 0; plugin_id < MM_SOUND_SUPPORTED_CODEC_NUM; plugin_id++) {
304 if (g_plugins[plugin_id].GetSupportTypes) {
305 codec_type = g_plugins[plugin_id].GetSupportTypes();
306 if (codec_type[0] == codec_to_find)
314 int MMSoundMgrCodecPlay(int *slotid, const mmsound_mgr_codec_param_t *param)
317 mmsound_codec_info_t info;
318 mmsound_codec_param_t codec_param;
319 int err = MM_ERROR_NONE;
321 #ifdef FOCUS_INTEGRATION
322 int need_focus_unregister = 0;
328 plugin_id = _MMSoundMgrCodecFindCodecPluginID(MM_SOUND_SUPPORTED_CODEC_WAVE);
329 if (plugin_id == -1) {
330 debug_error("Could not find proper codec plugin!!!");
331 err = MM_ERROR_SOUND_INTERNAL;
335 err = g_plugins[plugin_id].Parse(param->pfilename, &info);
336 if (err != MM_ERROR_NONE) {
337 debug_error("Could not parse file [%s] by plugin[%d]\n", param->pfilename, plugin_id);
341 debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, plugin_id);
344 debug_msg("Get New handle\n");
347 err = _mm_sound_mgr_codec_slot_get_empty(slotid);
348 if (err != MM_ERROR_NONE || *slotid < 0) {
349 debug_error("Empty g_slot is not found\n");
353 codec_param.tone = param->tone;
354 codec_param.volume_config = param->volume_config;
355 codec_param.repeat_count = param->repeat_count;
356 codec_param.volume = param->volume;
357 codec_param.pfilename = param->pfilename;
358 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
359 codec_param.param = *slotid;
360 codec_param.pid = (int)param->param;
361 codec_param.stream_index = param->stream_index;
362 MMSOUND_STRNCPY(codec_param.stream_type, param->stream_type, MAX_STREAM_TYPE_LEN);
365 #ifdef FOCUS_INTEGRATION
367 * Register FOCUS here
370 if (param->session_type != MM_SESSION_TYPE_CALL &&
371 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
372 param->session_type != MM_SESSION_TYPE_VOIP &&
373 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
374 param->enable_session) {
376 unsigned int subs_id = 0;
378 err = mm_sound_add_device_connected_callback(MM_SOUND_DEVICE_STATE_ACTIVATED_FLAG,
379 (mm_sound_device_connected_cb)_sound_codec_device_connected_callback,
380 (void*) *slotid, &subs_id);
382 debug_error("mm_sound_add_device_connected_callback failed [0x%x]", err);
384 return MM_ERROR_POLICY_INTERNAL;
386 g_slots[*slotid].subs_id = subs_id;
388 if ((param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS) ||
389 param->session_type == MM_SESSION_TYPE_ALARM ||
390 param->session_type == MM_SESSION_TYPE_NOTIFY ||
391 param->session_type == MM_SESSION_TYPE_EMERGENCY) {
392 debug_warning("session option is PAUSE_OTHERS -> acquire focus");
393 err = mm_sound_focus_get_id((int *)(¶m->focus_handle));
394 err = mm_sound_register_focus_for_session(param->focus_handle, (int)param->param, "media", _sound_codec_focus_callback, (void*)*slotid);
396 debug_error("mm_sound_register_focus_for_session failed [0x%x]", err);
398 return MM_ERROR_POLICY_INTERNAL;
400 err = mm_sound_acquire_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
402 debug_error("mm_sound_acquire_focus failed [0x%x]", err);
403 err = mm_sound_unregister_focus(param->focus_handle);
405 return MM_ERROR_POLICY_INTERNAL;
407 g_slots[*slotid].current_focus_type = FOCUS_FOR_BOTH;
408 } else if (param->session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
410 debug_warning("session option is UNINTERRUPTIBLE, nothing to do with focus");
412 debug_warning("need to set focus watch callback");
413 err = mm_sound_set_focus_watch_callback_for_session((int)param->param, FOCUS_FOR_BOTH, _sound_codec_focus_watch_callback,
414 (void*)*slotid, (int *)(¶m->focus_wcb_id));
416 debug_error("mm_sound_set_focus_watch_callback_for_session failed [0x%x]", err);
418 return MM_ERROR_POLICY_INTERNAL;
425 /* Codec id WAV or MP3 */
426 g_slots[*slotid].pluginid = plugin_id;
427 g_slots[*slotid].param = param->param; /* This arg is used callback data */
428 g_slots[*slotid].session_type = param->session_type;
429 g_slots[*slotid].session_options = param->session_options;
430 #ifdef FOCUS_INTEGRATION
431 g_slots[*slotid].focus_handle = param->focus_handle;
432 g_slots[*slotid].focus_wcb_id = param->focus_wcb_id;
434 g_slots[*slotid].enable_session = true;
435 g_slots[*slotid].pid = (int)param->param;
438 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
440 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
441 debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
442 if (err != MM_ERROR_NONE) {
443 debug_error("Plugin create fail : 0x%08X\n", err);
444 g_slots[*slotid].status = STATUS_IDLE;
446 #ifdef FOCUS_INTEGRATION
447 if (param->focus_handle) {
448 need_focus_unregister = 1;
454 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
455 if (err != MM_ERROR_NONE) {
456 debug_error("Fail to play : 0x%08X\n", err);
457 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
458 #ifdef FOCUS_INTEGRATION
459 if (param->focus_handle) {
460 need_focus_unregister = 1;
468 if (_mm_sound_mgr_codec_slot_is_empty())
469 _mm_sound_mgr_codec_shutdown_timer_start();
471 #ifdef FOCUS_INTEGRATION
472 if (param->session_type != MM_SESSION_TYPE_CALL &&
473 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
474 param->session_type != MM_SESSION_TYPE_VOIP &&
475 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
476 param->enable_session &&
477 need_focus_unregister == 1) {
479 if ((param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS) ||
480 param->session_type == MM_SESSION_TYPE_ALARM ||
481 param->session_type == MM_SESSION_TYPE_NOTIFY ||
482 param->session_type == MM_SESSION_TYPE_EMERGENCY) {
483 err = mm_sound_release_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
484 if (mm_sound_unregister_focus(param->focus_handle) || err) {
485 debug_error("focus cleaning up failed[0x%x]", err);
486 return MM_ERROR_POLICY_INTERNAL;
488 } else if (~(param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
489 err = mm_sound_unset_focus_watch_callback(param->focus_wcb_id);
491 debug_error("focus watch cleaning up failed[0x%x]", err);
492 return MM_ERROR_POLICY_INTERNAL;
506 int MMSoundMgrCodecPlayWithStreamInfo(int *slotid, const mmsound_mgr_codec_param_t *param)
509 mmsound_codec_info_t info;
510 mmsound_codec_param_t codec_param;
511 int err = MM_ERROR_NONE;
516 plugin_id = _MMSoundMgrCodecFindCodecPluginID(MM_SOUND_SUPPORTED_CODEC_WAVE);
517 if (plugin_id == -1) {
518 debug_error("Could not find proper codec plugin!!!");
519 err = MM_ERROR_SOUND_INTERNAL;
523 err = g_plugins[plugin_id].Parse(param->pfilename, &info);
524 if (err != MM_ERROR_NONE) {
525 debug_error("Could not parse file [%s] by plugin[%d]\n", param->pfilename, plugin_id);
529 err = _mm_sound_mgr_codec_slot_get_empty(slotid);
530 if (err != MM_ERROR_NONE || *slotid < 0) {
531 debug_error("Empty g_slot is not found\n");
535 codec_param.volume_config = -1; //setting volume config to -1 since using stream info instead of volume type
536 codec_param.repeat_count = param->repeat_count;
537 codec_param.volume = param->volume;
538 codec_param.pfilename = param->pfilename;
539 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
540 codec_param.param = *slotid;
541 codec_param.pid = (int)param->param;
542 codec_param.stream_index = param->stream_index;
543 MMSOUND_STRNCPY(codec_param.stream_type, param->stream_type, MAX_STREAM_TYPE_LEN);
546 /* Codec id WAV or MP3 */
547 g_slots[*slotid].pluginid = plugin_id;
548 g_slots[*slotid].param = param->param; /* This arg is used callback data */
550 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
552 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
553 debug_msg("Created audio handle : [%p]\n", g_slots[*slotid].plughandle);
554 if (err != MM_ERROR_NONE) {
555 debug_error("Plugin create fail : 0x%08X\n", err);
556 g_slots[*slotid].status = STATUS_IDLE;
561 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
562 if (err != MM_ERROR_NONE) {
563 debug_error("Fail to play : 0x%08X\n", err);
564 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
570 if (_mm_sound_mgr_codec_slot_is_empty())
571 _mm_sound_mgr_codec_shutdown_timer_start();
581 #define DTMF_PLUGIN_COUNT 2
582 int MMSoundMgrCodecPlayDtmf(int *slotid, const mmsound_mgr_codec_param_t *param)
586 mmsound_codec_info_t info;
587 mmsound_codec_param_t codec_param;
588 int err = MM_ERROR_NONE;
589 #ifdef FOCUS_INTEGRATION
590 int need_focus_unregister = 0;
596 plugin_id = _MMSoundMgrCodecFindCodecPluginID(MM_SOUND_SUPPORTED_CODEC_DTMF);
597 if (plugin_id == -1) {
598 debug_error("Could not find proper codec plugin!!!");
599 err = MM_ERROR_SOUND_INTERNAL;
603 /*The count num means codec type DTMF */
604 debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, plugin_id);
606 if (g_plugins[plugin_id].GetSupportTypes == NULL) { /* Codec not found */
607 debug_error("unsupported file type %d\n", plugin_id);
608 printf("unsupported file type %d\n", plugin_id);
609 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
614 debug_msg("Get New handle\n");
617 err = _mm_sound_mgr_codec_slot_get_empty(slotid);
618 if (err != MM_ERROR_NONE || *slotid < 0) {
619 debug_error("Empty g_slot is not found\n");
623 codec_param.tone = param->tone;
624 codec_param.volume_config = param->volume_config;
625 codec_param.repeat_count = param->repeat_count;
626 codec_param.volume = param->volume;
627 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
628 codec_param.param = *slotid;
629 codec_param.pid = (int)param->param;
630 codec_param.stream_index = param->stream_index;
631 MMSOUND_STRNCPY(codec_param.stream_type, param->stream_type, MAX_STREAM_TYPE_LEN);
634 #ifdef FOCUS_INTEGRATION
637 * Register FOCUS here
640 if (param->session_type != MM_SESSION_TYPE_CALL &&
641 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
642 param->session_type != MM_SESSION_TYPE_VOIP &&
643 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
644 param->enable_session) {
646 unsigned int subs_id = 0;
648 err = mm_sound_add_device_connected_callback(MM_SOUND_DEVICE_STATE_ACTIVATED_FLAG,
649 (mm_sound_device_connected_cb)_sound_codec_device_connected_callback,
650 (void*) *slotid, &subs_id);
652 debug_error("mm_sound_add_device_connected_callback failed [0x%x]", err);
654 return MM_ERROR_POLICY_INTERNAL;
656 g_slots[*slotid].subs_id = subs_id;
658 if ((param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS) ||
659 param->session_type == MM_SESSION_TYPE_ALARM ||
660 param->session_type == MM_SESSION_TYPE_NOTIFY ||
661 param->session_type == MM_SESSION_TYPE_EMERGENCY) {
662 debug_warning("session option is PAUSE_OTHERS -> acquire focus");
663 err = mm_sound_focus_get_id((int *)(¶m->focus_handle));
664 err = mm_sound_register_focus_for_session(param->focus_handle, (int)param->param, "media", _sound_codec_focus_callback, (void*)*slotid);
666 debug_error("mm_sound_register_focus failed [0x%x]", err);
668 return MM_ERROR_POLICY_INTERNAL;
670 err = mm_sound_acquire_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
672 debug_error("mm_sound_acquire_focus failed [0x%x]", err);
673 err = mm_sound_unregister_focus(param->focus_handle);
675 return MM_ERROR_POLICY_INTERNAL;
677 g_slots[*slotid].current_focus_type = FOCUS_FOR_BOTH;
678 } else if (param->session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
680 debug_warning("session option is UNINTERRUPTIBLE, nothing to do with focus");
682 debug_warning("need to set focus watch callback");
683 err = mm_sound_set_focus_watch_callback_for_session((int)param->param, FOCUS_FOR_BOTH, _sound_codec_focus_watch_callback,
684 (void*)*slotid, (int *)(¶m->focus_wcb_id));
686 debug_error("mm_sound_set_focus_watch_callback failed [0x%x]", err);
688 return MM_ERROR_POLICY_INTERNAL;
694 g_slots[*slotid].pluginid = plugin_id;
695 g_slots[*slotid].param = param->param; /* This arg is used callback data */
696 g_slots[*slotid].session_type = param->session_type;
697 g_slots[*slotid].session_options = param->session_options;
698 #ifdef FOCUS_INTEGRATION
699 g_slots[*slotid].focus_handle= param->focus_handle;
700 g_slots[*slotid].focus_wcb_id= param->focus_wcb_id;
702 g_slots[*slotid].enable_session = param->enable_session;
703 g_slots[*slotid].pid = (int)param->param;
706 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
709 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
710 debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
711 if (err != MM_ERROR_NONE) {
712 debug_error("Plugin create fail : 0x%08X\n", err);
713 g_slots[*slotid].status = STATUS_IDLE;
715 #ifdef FOCUS_INTEGRATION
716 need_focus_unregister = 1;
721 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
722 if (err != MM_ERROR_NONE) {
723 debug_error("Fail to play : 0x%08X\n", err);
724 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
725 #ifdef FOCUS_INTEGRATION
726 need_focus_unregister = 1;
731 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
734 #ifdef FOCUS_INTEGRATION
735 if (param->session_type != MM_SESSION_TYPE_CALL &&
736 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
737 param->session_type != MM_SESSION_TYPE_VOIP &&
738 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
739 param->enable_session &&
740 need_focus_unregister == 1) {
742 if ((param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS) ||
743 param->session_type == MM_SESSION_TYPE_ALARM ||
744 param->session_type == MM_SESSION_TYPE_NOTIFY ||
745 param->session_type == MM_SESSION_TYPE_EMERGENCY) {
746 err = mm_sound_release_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
747 if (mm_sound_unregister_focus(param->focus_handle) || err) {
748 debug_error("focus cleaning up failed[0x%x]", err);
749 return MM_ERROR_POLICY_INTERNAL;
751 } else if (~(param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
752 err = mm_sound_unset_focus_watch_callback(param->focus_wcb_id);
754 debug_error("focus watch cleaning up failed[0x%x]", err);
755 return MM_ERROR_POLICY_INTERNAL;
768 int MMSoundMgrCodecPlayDtmfWithStreamInfo(int *slotid, const mmsound_mgr_codec_param_t *param)
772 mmsound_codec_info_t info;
773 mmsound_codec_param_t codec_param;
774 int err = MM_ERROR_NONE;
779 plugin_id = _MMSoundMgrCodecFindCodecPluginID(MM_SOUND_SUPPORTED_CODEC_DTMF);
780 if (plugin_id == -1) {
781 debug_error("Could not find proper codec plugin!!!");
782 err = MM_ERROR_SOUND_INTERNAL;
786 /*The count num means codec type DTMF */
787 debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, plugin_id);
789 if (g_plugins[plugin_id].GetSupportTypes == NULL) { /* Codec not found */
790 debug_error("unsupported file type %d\n", plugin_id);
791 printf("unsupported file type %d\n", plugin_id);
792 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
797 debug_msg("Get New handle\n");
800 err = _mm_sound_mgr_codec_slot_get_empty(slotid);
801 if (err != MM_ERROR_NONE || *slotid < 0)
803 debug_error("Empty g_slot is not found\n");
807 codec_param.tone = param->tone;
808 codec_param.repeat_count = param->repeat_count;
809 codec_param.volume = param->volume;
810 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
811 codec_param.param = *slotid;
812 codec_param.pid = (int)param->param;
813 codec_param.volume_config = -1; //setting volume config to -1 since using stream info instead of volume type
814 codec_param.stream_index = param->stream_index;
815 MMSOUND_STRNCPY(codec_param.stream_type, param->stream_type, MAX_STREAM_TYPE_LEN);
818 g_slots[*slotid].pluginid = plugin_id;
819 g_slots[*slotid].param = param->param; /* This arg is used callback data */
820 g_slots[*slotid].enable_session = param->enable_session;
823 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
826 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
827 debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
828 if (err != MM_ERROR_NONE) {
829 debug_error("Plugin create fail : 0x%08X\n", err);
830 g_slots[*slotid].status = STATUS_IDLE;
835 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
836 if (err != MM_ERROR_NONE) {
837 debug_error("Fail to play : 0x%08X\n", err);
838 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
842 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
853 int MMSoundMgrCodecStop(const int slotid)
855 int err = MM_ERROR_NONE;
857 debug_enter("(Slotid : [%d])\n", slotid);
859 if (slotid < 0 || MANAGER_HANDLE_MAX <= slotid) {
860 return MM_ERROR_INVALID_ARGUMENT;
864 if (g_slots[slotid].status == STATUS_IDLE) {
865 err = MM_ERROR_SOUND_INVALID_STATE;
866 debug_warning("The playing slots is not found, Slot ID : [%d]\n", slotid);
870 debug_msg("Found slot, Slotid [%d] State [%d]\n", slotid, g_slots[slotid].status);
873 g_slots[slotid].stop_by_user = true;
875 err = g_plugins[g_slots[slotid].pluginid].Stop(g_slots[slotid].plughandle);
876 if (err != MM_ERROR_NONE) {
877 debug_error("Fail to STOP Code : 0x%08X\n", err);
882 debug_leave("(err : 0x%08X)\n", err);
886 #ifdef FOCUS_INTEGRATION
887 int MMSoundMgrCodecClearFocus(int pid)
889 int err = MM_ERROR_NONE;
892 debug_enter("(pid : [%d])\n", pid);
896 for (slotid = 0 ; slotid < MANAGER_HANDLE_MAX ; slotid++) {
897 if (g_slots[slotid].pid == pid) {
898 if (g_slots[slotid].focus_handle || g_slots[slotid].focus_wcb_id) {
899 if (g_slots[slotid].session_type != MM_SESSION_TYPE_CALL &&
900 g_slots[slotid].session_type != MM_SESSION_TYPE_VIDEOCALL &&
901 g_slots[slotid].session_type != MM_SESSION_TYPE_VOIP &&
902 g_slots[slotid].session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
903 g_slots[slotid].enable_session ) {
904 if ((g_slots[slotid].session_options & MM_SESSION_OPTION_PAUSE_OTHERS) ||
905 g_slots[slotid].session_type == MM_SESSION_TYPE_ALARM ||
906 g_slots[slotid].session_type == MM_SESSION_TYPE_NOTIFY ||
907 g_slots[slotid].session_type == MM_SESSION_TYPE_EMERGENCY) {
908 err = mm_sound_release_focus(g_slots[slotid].focus_handle, FOCUS_FOR_BOTH, NULL);
910 debug_error("mm_sound_release_focus failed [0x%x]", err);
912 if (mm_sound_unregister_focus(g_slots[slotid].focus_handle) || err) {
913 debug_error("Focus clean up failed [0x%x]", err);
914 err = MM_ERROR_POLICY_INTERNAL;
917 } else if (~(g_slots[slotid].session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
918 err = mm_sound_unset_focus_watch_callback(g_slots[slotid].focus_wcb_id);
920 debug_error("mm_sound_unset_focus_watch_callback failed [0x%x]", err);
921 err = MM_ERROR_POLICY_INTERNAL;
926 if (mm_sound_remove_device_connected_callback(g_slots[slotid].subs_id) != MM_ERROR_NONE)
927 debug_error("mm_sound_remove_device_connected_callback() failed");
928 g_slots[slotid].focus_handle = 0;
929 g_slots[slotid].focus_wcb_id = 0;
930 g_slots[slotid].subs_id = 0;
937 debug_leave("(err : 0x%08X)\n", err);
943 static int _MMSoundMgrCodecStopCallback(int param)
945 int err = MM_ERROR_NONE;
947 debug_enter("(Slot : %d)\n", param);
949 if (param < 0 || param >= MANAGER_HANDLE_MAX) {
950 debug_error ("Slot index param [%d] is invalid", param);
951 return MM_ERROR_INVALID_ARGUMENT;
954 if (g_slots[param].stop_by_user == false) {
958 #ifdef FOCUS_INTEGRATION
960 * Unregister FOCUS here
962 debug_msg("[CODEC MGR] enable_session %d ",g_slots[param].enable_session);
964 if (g_slots[param].focus_handle || g_slots[param].focus_wcb_id) {
965 if (g_slots[param].session_type != MM_SESSION_TYPE_CALL &&
966 g_slots[param].session_type != MM_SESSION_TYPE_VIDEOCALL &&
967 g_slots[param].session_type != MM_SESSION_TYPE_VOIP &&
968 g_slots[param].session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
969 g_slots[param].enable_session ) {
970 if ((g_slots[param].session_options & MM_SESSION_OPTION_PAUSE_OTHERS) ||
971 g_slots[param].session_type == MM_SESSION_TYPE_ALARM ||
972 g_slots[param].session_type == MM_SESSION_TYPE_NOTIFY ||
973 g_slots[param].session_type == MM_SESSION_TYPE_EMERGENCY) {
974 if (g_slots[param].current_focus_type != FOCUS_NONE) {
975 err = mm_sound_release_focus(g_slots[param].focus_handle, g_slots[param].current_focus_type, NULL);
977 debug_error("mm_sound_release_focus failed [0x%x]", err);
980 if (mm_sound_unregister_focus(g_slots[param].focus_handle) || err) {
981 debug_error("Focus clean up failed [0x%x]", err);
982 err = MM_ERROR_POLICY_INTERNAL;
985 } else if (~(g_slots[param].session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
986 err = mm_sound_unset_focus_watch_callback(g_slots[param].focus_wcb_id);
988 debug_error("mm_sound_unset_focus_watch_callback failed [0x%x]", err);
989 err = MM_ERROR_POLICY_INTERNAL;
994 if (mm_sound_remove_device_connected_callback(g_slots[param].subs_id) != MM_ERROR_NONE)
995 debug_error("mm_sound_remove_device_connected_callback() failed");
999 if (g_slots[param].stop_by_user == false) {
1000 __mm_sound_mgr_ipc_notify_play_file_end(param);
1001 debug_msg("Client callback msg_type (instance) : [%d]\n", (int)g_slots[param].param);
1004 debug_msg("Handle allocated handle : [0x%08X]\n", g_slots[param].plughandle);
1005 err = g_plugins[g_slots[param].pluginid].Destroy(g_slots[param].plughandle);
1007 debug_critical("[CODEC MGR] Fail to destroy slot number : [%d] err [0x%x]\n", param, err);
1009 _mm_sound_mgr_codec_slot_clear(param);
1010 if (_mm_sound_mgr_codec_slot_is_empty())
1011 _mm_sound_mgr_codec_shutdown_timer_start();
1014 if (g_slots[param].stop_by_user == false) {
1025 static int _MMSoundMgrCodecRegisterInterface(MMSoundPluginType *plugin)
1027 int err = MM_ERROR_NONE;
1029 void *getinterface = NULL;
1035 /* find emptry slot */
1036 for (plugin_id = 0; plugin_id < MM_SOUND_SUPPORTED_CODEC_NUM; plugin_id++) {
1037 if (g_plugins[plugin_id].GetSupportTypes == NULL)
1041 if (plugin_id == MM_SOUND_SUPPORTED_CODEC_NUM) {
1042 debug_critical("The plugin support type is not valid\n");
1043 return MM_ERROR_COMMON_OUT_OF_RANGE;
1046 err = MMSoundPluginGetSymbol(plugin, CODEC_GET_INTERFACE_FUNC_NAME, &getinterface);
1047 if (err != MM_ERROR_NONE) {
1048 debug_error("Get Symbol CODEC_GET_INTERFACE_FUNC_NAME is fail : %x\n", err);
1051 debug_msg("interface[%p] empty_slot[%d]\n", getinterface, plugin_id);
1053 err = MMSoundPlugCodecCastGetInterface(getinterface)(&g_plugins[plugin_id]);
1054 if (err != MM_ERROR_NONE) {
1055 debug_error("Get interface fail : %x\n", err);
1058 /* If error occur, clean interface */
1059 memset(&g_plugins[plugin_id], 0, sizeof(mmsound_codec_interface_t));
1061 if (g_plugins[plugin_id].SetThreadPool)
1062 g_plugins[plugin_id].SetThreadPool(MMSoundThreadPoolRun);