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 <mm_source.h>
32 #include <mm_session.h>
34 #include "include/mm_sound_mgr_common.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"
39 #include "include/mm_sound_pa_client.h"
40 #include "../include/mm_sound_focus.h"
41 #include "../include/mm_sound_device.h"
45 #define _ENABLE_KEYTONE /* Temporal test code */
48 int (*callback)(int, void *, void *, int); /* msg_type(pid) client callback & client data info */
53 MMHandleType plughandle;
62 mm_sound_focus_type_e current_focus_type;
65 } __mmsound_mgr_codec_handle_t;
67 static MMSoundPluginType *g_codec_plugins = NULL;
68 static __mmsound_mgr_codec_handle_t g_slots[MANAGER_HANDLE_MAX];
69 static mmsound_codec_interface_t g_plugins[MM_SOUND_SUPPORTED_CODEC_NUM];
70 static pthread_mutex_t g_slot_mutex;
71 static pthread_mutex_t codec_wave_mutex;
72 static int _MMSoundMgrCodecStopCallback(int param);
73 static int _MMSoundMgrCodecGetEmptySlot(int *slotid);
74 static int _MMSoundMgrCodecRegisterInterface(MMSoundPluginType *plugin);
77 #define STATUS_SOUND 3
79 #define SOUND_SLOT_START 0
81 void sound_codec_focus_callback(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e focus_state, const char *reason_for_change, const char *additional_info, void *user_data)
84 int slotid = (int)user_data;
85 int result = MM_ERROR_NONE;
87 debug_warning ("focus callback called -> focus_stae(%d), reasoun_for_change(%s)", focus_state, reason_for_change ? reason_for_change : "N/A");
89 if(g_slots[slotid].session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE){
90 debug_warning ("session option is UNINTERRUPTIBLE, nothing to do with focus");
93 if (focus_state == FOCUS_IS_RELEASED) {
94 g_slots[slotid].current_focus_type = FOCUS_FOR_BOTH&(~focus_type);
95 debug_warning ("focus is released -> stop playing");
96 result = MMSoundMgrCodecStop(slotid);
97 if (result != MM_ERROR_NONE) {
98 debug_log("result error %d\n", result);
105 void sound_codec_focus_watch_callback(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e focus_state, const char *reason_for_change, const char* additional_info, void *user_data)
107 int slotid = (int)user_data;
108 int result = MM_ERROR_NONE;
110 debug_warning ("focus callback called -> focus_stae(%d), reasoun_for_change(%s)", focus_state, reason_for_change ? reason_for_change : "N/A");
112 if(g_slots[slotid].session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE){
113 debug_warning ("session option is UNINTERRUPTIBLE, nothing to do with focus");
116 if (focus_state == FOCUS_IS_ACQUIRED) {
117 debug_warning ("focus is released -> stop playing");
118 result = MMSoundMgrCodecStop(slotid);
119 if (result != MM_ERROR_NONE) {
120 debug_log("result error %d\n", result);
127 void sound_codec_device_connected_callback(MMSoundDevice_t device, bool is_connected, void *user_data)
129 int slotid = (int)user_data;
130 int result = MM_ERROR_NONE;
131 mm_sound_device_type_e type;
133 debug_warning ("device_connected_callback called");
135 if (mm_sound_get_device_type (device, &type) != MM_ERROR_NONE) {
136 debug_error("getting device type failed");
139 case MM_SOUND_DEVICE_TYPE_AUDIOJACK:
140 case MM_SOUND_DEVICE_TYPE_BLUETOOTH:
141 case MM_SOUND_DEVICE_TYPE_HDMI:
142 case MM_SOUND_DEVICE_TYPE_MIRRORING:
143 case MM_SOUND_DEVICE_TYPE_USB_AUDIO:
145 debug_warning("sound device unplugged");
146 result = MMSoundMgrCodecStop(slotid);
147 if (result != MM_ERROR_NONE) {
148 debug_error("MMSoundMgrCodecStop error %d\n", result);
150 result = mm_sound_remove_device_connected_callback(g_slots[slotid].subs_id);
151 if (result != MM_ERROR_NONE) {
152 debug_error("mm_sound_remove_device_connected_callback error %d\n", result);
162 int MMSoundMgrCodecInit(const char *targetdir)
169 memset (g_slots, 0, sizeof(g_slots));
171 if(pthread_mutex_init(&g_slot_mutex, NULL)) {
172 debug_error("pthread_mutex_init failed\n");
173 return MM_ERROR_SOUND_INTERNAL;
176 if(pthread_mutex_init(&codec_wave_mutex, NULL)) {
177 debug_error("pthread_mutex_init failed\n");
178 return MM_ERROR_SOUND_INTERNAL;
181 for (count = 0; count < MANAGER_HANDLE_MAX; count++) {
182 g_slots[count].status = STATUS_IDLE;
183 g_slots[count].plughandle = 0;
186 if (g_codec_plugins) {
187 debug_warning("Please Check Init twice\n");
188 MMSoundPluginRelease(g_codec_plugins);
191 MMSoundPluginScan(targetdir, MM_SOUND_PLUGIN_TYPE_CODEC, &g_codec_plugins);
193 while (g_codec_plugins[loop].type != MM_SOUND_PLUGIN_TYPE_NONE) {
194 _MMSoundMgrCodecRegisterInterface(&g_codec_plugins[loop++]);
198 return MM_ERROR_NONE;
201 int MMSoundMgrCodecFini(void)
205 memset(g_plugins, 0, sizeof(mmsound_codec_interface_t) * MM_SOUND_SUPPORTED_CODEC_NUM);
206 MMSoundPluginRelease(g_codec_plugins);
207 g_codec_plugins = NULL;
208 pthread_mutex_destroy(&g_slot_mutex);
209 pthread_mutex_destroy(&codec_wave_mutex);
211 return MM_ERROR_NONE;
215 int MMSoundMgrCodecPlay(int *slotid, const mmsound_mgr_codec_param_t *param)
218 mmsound_codec_info_t info;
219 mmsound_codec_param_t codec_param;
220 int err = MM_ERROR_NONE;
221 int need_focus_unregister = 0;
227 for (count = 0; g_plugins[count].GetSupportTypes; count++) {
229 if (g_plugins[count].Parse(param->source, &info) == MM_ERROR_NONE)
233 /*The count num means codec type WAV, MP3 */
234 debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, count);
236 if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
237 debug_error("unsupported file type %d\n", count);
238 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
243 debug_msg("Get New handle\n");
246 err = _MMSoundMgrCodecGetEmptySlot(slotid);
247 if (err != MM_ERROR_NONE) {
248 debug_error("Empty g_slot is not found\n");
252 codec_param.tone = param->tone;
253 codec_param.volume_config = param->volume_config;
254 codec_param.repeat_count = param->repeat_count;
255 codec_param.volume = param->volume;
256 codec_param.source = param->source;
257 codec_param.priority = param->priority;
258 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
259 codec_param.param = *slotid;
260 codec_param.pid = (int)param->param;
261 codec_param.handle_route = param->handle_route;
262 codec_param.codec_wave_mutex = &codec_wave_mutex;
263 codec_param.stream_index = param->stream_index;
264 strncpy(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
265 pthread_mutex_lock(&g_slot_mutex);
267 debug_msg("After Slot_mutex LOCK\n");
271 * Register FOCUS here
274 if (param->session_type != MM_SESSION_TYPE_CALL &&
275 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
276 param->session_type != MM_SESSION_TYPE_VOIP &&
277 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
278 param->priority != HANDLE_PRIORITY_SOLO &&
279 param->enable_session) {
281 unsigned int subs_id = 0;
283 err = mm_sound_add_device_connected_callback(MM_SOUND_DEVICE_STATE_ACTIVATED_FLAG, (mm_sound_device_connected_cb)sound_codec_device_connected_callback, *slotid, &subs_id);
285 debug_error("mm_sound_add_device_connected_callback failed [0x%x]", err);
286 pthread_mutex_unlock(&g_slot_mutex);
287 return MM_ERROR_POLICY_INTERNAL;
289 g_slots[*slotid].subs_id = subs_id;
291 if ((param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS) || param->session_type == MM_SESSION_TYPE_ALARM || param->session_type == MM_SESSION_TYPE_NOTIFY || param->session_type == MM_SESSION_TYPE_EMERGENCY) {
292 debug_warning("session option is PAUSE_OTHERS -> acquire focus");
293 err = mm_sound_focus_get_id((int *)(¶m->focus_handle));
294 err = mm_sound_register_focus_for_session(param->focus_handle, (int)param->param, "media", sound_codec_focus_callback, (void*)*slotid);
296 debug_error("mm_sound_register_focus_for_session failed [0x%x]", err);
297 pthread_mutex_unlock(&g_slot_mutex);
298 return MM_ERROR_POLICY_INTERNAL;
300 err = mm_sound_acquire_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
302 debug_error("mm_sound_acquire_focus failed [0x%x]", err);
303 err = mm_sound_unregister_focus(param->focus_handle);
304 pthread_mutex_unlock(&g_slot_mutex);
305 return MM_ERROR_POLICY_INTERNAL;
307 g_slots[*slotid].current_focus_type = FOCUS_FOR_BOTH;
308 } else if (param->session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
310 debug_warning("session option is UNINTERRUPTIBLE, nothing to do with focus");
312 debug_warning("need to set focus watch callback");
313 err = mm_sound_set_focus_watch_callback_for_session((int)param->param, FOCUS_FOR_BOTH, sound_codec_focus_watch_callback, (void*)*slotid, (int *)(¶m->focus_wcb_id));
315 debug_error("mm_sound_set_focus_watch_callback_for_session failed [0x%x]", err);
316 pthread_mutex_unlock(&g_slot_mutex);
317 return MM_ERROR_POLICY_INTERNAL;
323 /* Codec id WAV or MP3 */
324 g_slots[*slotid].pluginid = count;
325 g_slots[*slotid].param = param->param; /* This arg is used callback data */
326 g_slots[*slotid].session_type = param->session_type;
327 g_slots[*slotid].session_options = param->session_options;
328 g_slots[*slotid].focus_handle = param->focus_handle;
329 g_slots[*slotid].focus_wcb_id = param->focus_wcb_id;
330 g_slots[*slotid].enable_session = true;
331 g_slots[*slotid].pid = (int)param->param;
334 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
336 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
337 debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
338 if (err != MM_ERROR_NONE) {
339 debug_error("Plugin create fail : 0x%08X\n", err);
340 g_slots[*slotid].status = STATUS_IDLE;
341 pthread_mutex_unlock(&g_slot_mutex);
342 debug_warning("After Slot_mutex UNLOCK\n");
343 if (param->focus_handle) {
344 need_focus_unregister = 1;
349 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
350 if (err != MM_ERROR_NONE) {
351 debug_error("Fail to play : 0x%08X\n", err);
352 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
353 if (param->focus_handle) {
354 need_focus_unregister = 1;
358 pthread_mutex_unlock(&g_slot_mutex);
360 debug_msg("After Slot_mutex UNLOCK\n");
364 if(param->session_type != MM_SESSION_TYPE_CALL &&
365 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
366 param->session_type != MM_SESSION_TYPE_VOIP &&
367 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
368 param->enable_session &&
369 need_focus_unregister == 1) {
371 if (param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS || param->session_type == MM_SESSION_TYPE_ALARM || param->session_type == MM_SESSION_TYPE_NOTIFY || param->session_type == MM_SESSION_TYPE_EMERGENCY) {
372 err = mm_sound_release_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
373 if(mm_sound_unregister_focus(param->focus_handle) || err) {
374 debug_error("focus cleaning up failed[0x%x]", err);
375 return MM_ERROR_POLICY_INTERNAL;
377 } else if (~(param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
378 err = mm_sound_unset_focus_watch_callback(param->focus_wcb_id);
380 debug_error("focus watch cleaning up failed[0x%x]", err);
381 return MM_ERROR_POLICY_INTERNAL;
393 int MMSoundMgrCodecPlayWithStreamInfo(int *slotid, const mmsound_mgr_codec_param_t *param)
396 mmsound_codec_info_t info;
397 mmsound_codec_param_t codec_param;
398 int err = MM_ERROR_NONE;
404 for (count = 0; g_plugins[count].GetSupportTypes; count++) {
406 if (g_plugins[count].Parse(param->source, &info) == MM_ERROR_NONE)
410 /*The count num means codec type WAV, MP3 */
411 debug_msg("Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->repeat_count, param->volume, count);
413 if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
414 debug_error("unsupported file type %d\n", count);
415 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
419 err = _MMSoundMgrCodecGetEmptySlot(slotid);
420 if (err != MM_ERROR_NONE) {
421 debug_error("Empty g_slot is not found\n");
425 codec_param.volume_config = -1; //setting volume config to -1 since using stream info instead of volume type
426 codec_param.repeat_count = param->repeat_count;
427 codec_param.volume = param->volume;
428 codec_param.source = param->source;
429 codec_param.priority = param->priority;
430 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
431 codec_param.param = *slotid;
432 codec_param.pid = (int)param->param;
433 codec_param.handle_route = param->handle_route;
434 codec_param.codec_wave_mutex = &codec_wave_mutex;
435 codec_param.stream_index = param->stream_index;
436 strncpy(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
437 pthread_mutex_lock(&g_slot_mutex);
439 debug_msg("After Slot_mutex LOCK\n");
442 /* Codec id WAV or MP3 */
443 g_slots[*slotid].pluginid = count;
444 g_slots[*slotid].param = param->param; /* This arg is used callback data */
446 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
448 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
449 debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
450 if (err != MM_ERROR_NONE) {
451 debug_error("Plugin create fail : 0x%08X\n", err);
452 g_slots[*slotid].status = STATUS_IDLE;
453 pthread_mutex_unlock(&g_slot_mutex);
454 debug_warning("After Slot_mutex UNLOCK\n");
458 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
459 if (err != MM_ERROR_NONE) {
460 debug_error("Fail to play : 0x%08X\n", err);
461 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
464 pthread_mutex_unlock(&g_slot_mutex);
466 debug_msg("After Slot_mutex UNLOCK\n");
479 #define DTMF_PLUGIN_COUNT 2
480 int MMSoundMgrCodecPlayDtmf(int *slotid, const mmsound_mgr_codec_param_t *param)
484 mmsound_codec_info_t info;
485 mmsound_codec_param_t codec_param;
486 int err = MM_ERROR_NONE;
487 int need_focus_unregister = 0;
493 for (count = 0; g_plugins[count].GetSupportTypes; count++) {
495 codec_type = g_plugins[count].GetSupportTypes();
496 if(codec_type && (MM_SOUND_SUPPORTED_CODEC_DTMF == codec_type[0]))
500 /*The count num means codec type DTMF */
501 debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, count);
503 if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
504 debug_error("unsupported file type %d\n", count);
505 printf("unsupported file type %d\n", count);
506 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
511 debug_msg("Get New handle\n");
514 err = _MMSoundMgrCodecGetEmptySlot(slotid);
515 if(err != MM_ERROR_NONE)
517 debug_error("Empty g_slot is not found\n");
521 codec_param.tone = param->tone;
522 codec_param.priority = 0;
523 codec_param.volume_config = param->volume_config;
524 codec_param.repeat_count = param->repeat_count;
525 codec_param.volume = param->volume;
526 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
527 codec_param.param = *slotid;
528 codec_param.pid = (int)param->param;
529 codec_param.stream_index = param->stream_index;
530 strncpy(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
532 pthread_mutex_lock(&g_slot_mutex);
534 debug_msg("After Slot_mutex LOCK\n");
539 * Register FOCUS here
542 if (param->session_type != MM_SESSION_TYPE_CALL &&
543 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
544 param->session_type != MM_SESSION_TYPE_VOIP &&
545 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
546 param->enable_session) {
548 unsigned int subs_id = 0;
550 err = mm_sound_add_device_connected_callback(MM_SOUND_DEVICE_STATE_ACTIVATED_FLAG, (mm_sound_device_connected_cb)sound_codec_device_connected_callback, *slotid, &subs_id);
552 debug_error("mm_sound_add_device_connected_callback failed [0x%x]", err);
553 pthread_mutex_unlock(&g_slot_mutex);
554 return MM_ERROR_POLICY_INTERNAL;
556 g_slots[*slotid].subs_id = subs_id;
558 if ((param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS) || param->session_type == MM_SESSION_TYPE_ALARM || param->session_type == MM_SESSION_TYPE_NOTIFY || param->session_type == MM_SESSION_TYPE_EMERGENCY) {
559 debug_warning("session option is PAUSE_OTHERS -> acquire focus");
560 err = mm_sound_focus_get_id((int *)(¶m->focus_handle));
561 err = mm_sound_register_focus_for_session(param->focus_handle, (int)param->param, "media", sound_codec_focus_callback, (void*)*slotid);
563 debug_error("mm_sound_register_focus failed [0x%x]", err);
564 pthread_mutex_unlock(&g_slot_mutex);
565 return MM_ERROR_POLICY_INTERNAL;
567 err = mm_sound_acquire_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
569 debug_error("mm_sound_acquire_focus failed [0x%x]", err);
570 err = mm_sound_unregister_focus(param->focus_handle);
571 pthread_mutex_unlock(&g_slot_mutex);
572 return MM_ERROR_POLICY_INTERNAL;
574 g_slots[*slotid].current_focus_type = FOCUS_FOR_BOTH;
575 } else if (param->session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
577 debug_warning("session option is UNINTERRUPTIBLE, nothing to do with focus");
579 debug_warning("need to set focus watch callback");
580 err = mm_sound_set_focus_watch_callback_for_session((int)param->param, FOCUS_FOR_BOTH, sound_codec_focus_watch_callback, (void*)*slotid, (int *)(¶m->focus_wcb_id));
582 debug_error("mm_sound_set_focus_watch_callback failed [0x%x]", err);
583 pthread_mutex_unlock(&g_slot_mutex);
584 return MM_ERROR_POLICY_INTERNAL;
589 g_slots[*slotid].pluginid = count;
590 g_slots[*slotid].param = param->param; /* This arg is used callback data */
591 g_slots[*slotid].session_type = param->session_type;
592 g_slots[*slotid].session_options = param->session_options;
593 g_slots[*slotid].focus_handle= param->focus_handle;
594 g_slots[*slotid].focus_wcb_id= param->focus_wcb_id;
595 g_slots[*slotid].enable_session = param->enable_session;
596 g_slots[*slotid].pid = (int)param->param;
599 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
602 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
603 debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
604 if (err != MM_ERROR_NONE) {
605 debug_error("Plugin create fail : 0x%08X\n", err);
606 g_slots[*slotid].status = STATUS_IDLE;
607 pthread_mutex_unlock(&g_slot_mutex);
608 debug_warning("After Slot_mutex UNLOCK\n");
609 need_focus_unregister = 1;
613 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
614 if (err != MM_ERROR_NONE) {
615 debug_error("Fail to play : 0x%08X\n", err);
616 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
617 need_focus_unregister = 1;
620 pthread_mutex_unlock(&g_slot_mutex);
622 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
624 debug_msg("After Slot_mutex UNLOCK\n")
628 if (param->session_type != MM_SESSION_TYPE_CALL &&
629 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
630 param->session_type != MM_SESSION_TYPE_VOIP &&
631 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
632 param->enable_session &&
633 need_focus_unregister == 1) {
635 if (param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS || param->session_type == MM_SESSION_TYPE_ALARM || param->session_type == MM_SESSION_TYPE_NOTIFY || param->session_type == MM_SESSION_TYPE_EMERGENCY) {
636 err = mm_sound_release_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
637 if(mm_sound_unregister_focus(param->focus_handle) || err) {
638 debug_error("focus cleaning up failed[0x%x]", err);
639 return MM_ERROR_POLICY_INTERNAL;
641 } else if (~(param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
642 err = mm_sound_unset_focus_watch_callback(param->focus_wcb_id);
644 debug_error("focus watch cleaning up failed[0x%x]", err);
645 return MM_ERROR_POLICY_INTERNAL;
657 int MMSoundMgrCodecPlayDtmfWithStreamInfo(int *slotid, const mmsound_mgr_codec_param_t *param)
661 mmsound_codec_info_t info;
662 mmsound_codec_param_t codec_param;
663 int err = MM_ERROR_NONE;
669 for (count = 0; g_plugins[count].GetSupportTypes; count++) {
671 codec_type = g_plugins[count].GetSupportTypes();
672 if(codec_type && (MM_SOUND_SUPPORTED_CODEC_DTMF == codec_type[0]))
676 /*The count num means codec type DTMF */
677 debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, count);
679 if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
680 debug_error("unsupported file type %d\n", count);
681 printf("unsupported file type %d\n", count);
682 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
687 debug_msg("Get New handle\n");
690 err = _MMSoundMgrCodecGetEmptySlot(slotid);
691 if(err != MM_ERROR_NONE)
693 debug_error("Empty g_slot is not found\n");
697 codec_param.tone = param->tone;
698 codec_param.priority = 0;
699 codec_param.repeat_count = param->repeat_count;
700 codec_param.volume = param->volume;
701 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
702 codec_param.param = *slotid;
703 codec_param.pid = (int)param->param;
704 codec_param.volume_config = -1; //setting volume config to -1 since using stream info instead of volume type
705 codec_param.stream_index = param->stream_index;
706 strncpy(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
708 pthread_mutex_lock(&g_slot_mutex);
710 debug_msg("After Slot_mutex LOCK\n");
712 g_slots[*slotid].pluginid = count;
713 g_slots[*slotid].param = param->param; /* This arg is used callback data */
714 g_slots[*slotid].enable_session = param->enable_session;
717 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
720 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
721 debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
722 if (err != MM_ERROR_NONE) {
723 debug_error("Plugin create fail : 0x%08X\n", err);
724 g_slots[*slotid].status = STATUS_IDLE;
725 pthread_mutex_unlock(&g_slot_mutex);
726 debug_warning("After Slot_mutex UNLOCK\n");
730 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
731 if (err != MM_ERROR_NONE) {
732 debug_error("Fail to play : 0x%08X\n", err);
733 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
736 pthread_mutex_unlock(&g_slot_mutex);
738 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
740 debug_msg("After Slot_mutex UNLOCK\n");
752 int MMSoundMgrCodecStop(const int slotid)
754 int err = MM_ERROR_NONE;
756 debug_enter("(Slotid : [%d])\n", slotid);
758 if (slotid < 0 || MANAGER_HANDLE_MAX <= slotid) {
759 return MM_ERROR_INVALID_ARGUMENT;
762 pthread_mutex_lock (&g_slot_mutex);
764 debug_msg("After Slot_mutex LOCK\n");
766 if (g_slots[slotid].status == STATUS_IDLE) {
767 err = MM_ERROR_SOUND_INVALID_STATE;
768 debug_warning("The playing slots is not found, Slot ID : [%d]\n", slotid);
772 debug_msg("Found slot, Slotid [%d] State [%d]\n", slotid, g_slots[slotid].status);
775 err = g_plugins[g_slots[slotid].pluginid].Stop(g_slots[slotid].plughandle);
776 if (err != MM_ERROR_NONE) {
777 debug_error("Fail to STOP Code : 0x%08X\n", err);
779 debug_msg("Found slot, Slotid [%d] State [%d]\n", slotid, g_slots[slotid].status);
781 pthread_mutex_unlock(&g_slot_mutex);
783 debug_msg("After Slot_mutex UNLOCK\n");
785 debug_leave("(err : 0x%08X)\n", err);
790 int MMSoundMgrCodecClearFocus(int pid)
792 int err = MM_ERROR_NONE;
795 debug_enter("(pid : [%d])\n", pid);
797 pthread_mutex_lock (&g_slot_mutex);
799 for (slotid = 0 ; slotid < MANAGER_HANDLE_MAX ; slotid++) {
800 if (g_slots[slotid].pid == pid) {
801 if (g_slots[slotid].focus_handle || g_slots[slotid].focus_wcb_id) {
802 if(g_slots[slotid].session_type != MM_SESSION_TYPE_CALL &&
803 g_slots[slotid].session_type != MM_SESSION_TYPE_VIDEOCALL &&
804 g_slots[slotid].session_type != MM_SESSION_TYPE_VOIP &&
805 g_slots[slotid].session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
806 g_slots[slotid].enable_session ) {
807 if ((g_slots[slotid].session_options & MM_SESSION_OPTION_PAUSE_OTHERS) || g_slots[slotid].session_type == MM_SESSION_TYPE_ALARM || g_slots[slotid].session_type == MM_SESSION_TYPE_NOTIFY || g_slots[slotid].session_type == MM_SESSION_TYPE_EMERGENCY) {
808 err = mm_sound_release_focus(g_slots[slotid].focus_handle, FOCUS_FOR_BOTH, NULL);
810 debug_error("mm_sound_release_focus failed [0x%x]", err);
812 if(mm_sound_unregister_focus(g_slots[slotid].focus_handle) || err) {
813 debug_error("Focus clean up failed [0x%x]", err);
814 err = MM_ERROR_POLICY_INTERNAL;
817 } else if (~(g_slots[slotid].session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
818 err = mm_sound_unset_focus_watch_callback(g_slots[slotid].focus_wcb_id);
820 debug_error("mm_sound_unset_focus_watch_callback failed [0x%x]", err);
821 err = MM_ERROR_POLICY_INTERNAL;
826 if(mm_sound_remove_device_connected_callback(g_slots[slotid].subs_id) != MM_ERROR_NONE)
827 debug_error("mm_sound_remove_device_connected_callback() failed");
828 g_slots[slotid].focus_handle = 0;
829 g_slots[slotid].focus_wcb_id = 0;
830 g_slots[slotid].subs_id = 0;
836 pthread_mutex_unlock(&g_slot_mutex);
837 debug_leave("(err : 0x%08X)\n", err);
843 static int _MMSoundMgrCodecStopCallback(int param)
845 int err = MM_ERROR_NONE;
847 debug_enter("(Slot : %d)\n", param);
849 pthread_mutex_lock(&g_slot_mutex);
850 debug_msg("[CODEC MGR] Slot_mutex lock done\n");
854 * Unregister FOCUS here
856 debug_msg("[CODEC MGR] enable_session %d ",g_slots[param].enable_session);
858 if (g_slots[param].focus_handle || g_slots[param].focus_wcb_id) {
859 if(g_slots[param].session_type != MM_SESSION_TYPE_CALL &&
860 g_slots[param].session_type != MM_SESSION_TYPE_VIDEOCALL &&
861 g_slots[param].session_type != MM_SESSION_TYPE_VOIP &&
862 g_slots[param].session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
863 g_slots[param].enable_session ) {
864 if ((g_slots[param].session_options & MM_SESSION_OPTION_PAUSE_OTHERS) || g_slots[param].session_type == MM_SESSION_TYPE_ALARM || g_slots[param].session_type == MM_SESSION_TYPE_NOTIFY || g_slots[param].session_type == MM_SESSION_TYPE_EMERGENCY) {
865 if(g_slots[param].current_focus_type != FOCUS_NONE) {
866 err = mm_sound_release_focus(g_slots[param].focus_handle, g_slots[param].current_focus_type, NULL);
868 debug_error("mm_sound_release_focus failed [0x%x]", err);
871 if(mm_sound_unregister_focus(g_slots[param].focus_handle) || err) {
872 debug_error("Focus clean up failed [0x%x]", err);
873 pthread_mutex_unlock(&g_slot_mutex);
874 return MM_ERROR_POLICY_INTERNAL;
876 } else if (~(g_slots[param].session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
877 err = mm_sound_unset_focus_watch_callback(g_slots[param].focus_wcb_id);
879 debug_error("mm_sound_unset_focus_watch_callback failed [0x%x]", err);
880 pthread_mutex_unlock(&g_slot_mutex);
881 return MM_ERROR_POLICY_INTERNAL;
885 if(mm_sound_remove_device_connected_callback(g_slots[param].subs_id) != MM_ERROR_NONE)
886 debug_error("mm_sound_remove_device_connected_callback() failed");
889 __mm_sound_mgr_ipc_notify_play_file_end(param);
891 debug_msg("Client callback msg_type (instance) : [%d]\n", (int)g_slots[param].param);
892 debug_msg("Handle allocated handle : [0x%08X]\n", g_slots[param].plughandle);
893 err = g_plugins[g_slots[param].pluginid].Destroy(g_slots[param].plughandle);
895 debug_critical("[CODEC MGR] Fail to destroy slot number : [%d] err [0x%x]\n", param, err);
897 memset(&g_slots[param], 0, sizeof(__mmsound_mgr_codec_handle_t));
898 g_slots[param].status = STATUS_IDLE;
899 pthread_mutex_unlock(&g_slot_mutex);
900 debug_msg("[CODEC MGR] Slot_mutex done\n");
905 static int _MMSoundMgrCodecGetEmptySlot(int *slot)
908 int err = MM_ERROR_NONE;
913 debug_msg("Codec slot ID : [%d]\n", *slot);
914 pthread_mutex_lock(&g_slot_mutex);
916 debug_msg("After Slot_mutex LOCK\n");
919 for (count = SOUND_SLOT_START; count < MANAGER_HANDLE_MAX ; count++) {
920 if (g_slots[count].status == STATUS_IDLE) {
921 g_slots[count].status = STATUS_SOUND;
925 pthread_mutex_unlock(&g_slot_mutex);
927 debug_msg("After Slot_mutex UNLOCK\n");
930 if (count < MANAGER_HANDLE_MAX) {
931 debug_msg("New handle allocated (codec slot ID : [%d])\n", count);
935 debug_warning("Handle is full handle : [%d]\n", count);
937 /* Temporal code for reset */
939 g_slots[count].status = STATUS_IDLE;
941 err = MM_ERROR_SOUND_INTERNAL;
951 static int _MMSoundMgrCodecRegisterInterface(MMSoundPluginType *plugin)
953 int err = MM_ERROR_NONE;
955 void *getinterface = NULL;
961 /* find emptry slot */
962 for (count = 0; count < MM_SOUND_SUPPORTED_CODEC_NUM; count++) {
963 if (g_plugins[count].GetSupportTypes == NULL)
967 if (count == MM_SOUND_SUPPORTED_CODEC_NUM) {
968 debug_critical("The plugin support type is not valid\n");
969 return MM_ERROR_COMMON_OUT_OF_RANGE;
972 err = MMSoundPluginGetSymbol(plugin, CODEC_GET_INTERFACE_FUNC_NAME, &getinterface);
973 if (err != MM_ERROR_NONE) {
974 debug_error("Get Symbol CODEC_GET_INTERFACE_FUNC_NAME is fail : %x\n", err);
977 debug_msg("interface[%p] empty_slot[%d]\n", getinterface, count);
979 err = MMSoundPlugCodecCastGetInterface(getinterface)(&g_plugins[count]);
980 if (err != MM_ERROR_NONE) {
981 debug_error("Get interface fail : %x\n", err);
984 /* If error occur, clean interface */
985 memset(&g_plugins[count], 0, sizeof(mmsound_codec_interface_t));
987 if (g_plugins[count].SetThreadPool)
988 g_plugins[count].SetThreadPool(MMSoundThreadPoolRun);