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.
28 #include <mm_source.h>
33 #include <mm_session.h>
35 #include "include/mm_sound_mgr_common.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"
40 #include "include/mm_sound_pa_client.h"
41 #include "../include/mm_sound_common.h"
42 #include "../include/mm_sound_focus.h"
43 #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);
192 if (g_codec_plugins) {
193 while (g_codec_plugins[loop].type != MM_SOUND_PLUGIN_TYPE_NONE) {
194 _MMSoundMgrCodecRegisterInterface(&g_codec_plugins[loop++]);
199 return MM_ERROR_NONE;
202 int MMSoundMgrCodecFini(void)
206 memset(g_plugins, 0, sizeof(mmsound_codec_interface_t) * MM_SOUND_SUPPORTED_CODEC_NUM);
207 MMSoundPluginRelease(g_codec_plugins);
208 g_codec_plugins = NULL;
209 pthread_mutex_destroy(&g_slot_mutex);
210 pthread_mutex_destroy(&codec_wave_mutex);
212 return MM_ERROR_NONE;
216 int MMSoundMgrCodecPlay(int *slotid, const mmsound_mgr_codec_param_t *param)
219 mmsound_codec_info_t info;
220 mmsound_codec_param_t codec_param;
221 int err = MM_ERROR_NONE;
222 int need_focus_unregister = 0;
228 for (count = 0; g_plugins[count].GetSupportTypes; count++) {
230 if (g_plugins[count].Parse(param->source, &info) == MM_ERROR_NONE)
234 /*The count num means codec type WAV, MP3 */
235 debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, count);
237 if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
238 debug_error("unsupported file type %d\n", count);
239 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
244 debug_msg("Get New handle\n");
247 err = _MMSoundMgrCodecGetEmptySlot(slotid);
248 if (err != MM_ERROR_NONE || *slotid < 0) {
249 debug_error("Empty g_slot is not found\n");
253 codec_param.tone = param->tone;
254 codec_param.volume_config = param->volume_config;
255 codec_param.repeat_count = param->repeat_count;
256 codec_param.volume = param->volume;
257 codec_param.source = param->source;
258 codec_param.priority = param->priority;
259 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
260 codec_param.param = *slotid;
261 codec_param.pid = (int)param->param;
262 codec_param.handle_route = param->handle_route;
263 codec_param.codec_wave_mutex = &codec_wave_mutex;
264 codec_param.stream_index = param->stream_index;
265 MMSOUND_STRNCPY(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
266 pthread_mutex_lock(&g_slot_mutex);
268 debug_msg("After Slot_mutex LOCK\n");
272 * Register FOCUS here
275 if (param->session_type != MM_SESSION_TYPE_CALL &&
276 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
277 param->session_type != MM_SESSION_TYPE_VOIP &&
278 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
279 param->priority != HANDLE_PRIORITY_SOLO &&
280 param->enable_session) {
282 unsigned int subs_id = 0;
284 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);
286 debug_error("mm_sound_add_device_connected_callback failed [0x%x]", err);
287 pthread_mutex_unlock(&g_slot_mutex);
288 return MM_ERROR_POLICY_INTERNAL;
290 g_slots[*slotid].subs_id = subs_id;
292 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) {
293 debug_warning("session option is PAUSE_OTHERS -> acquire focus");
294 err = mm_sound_focus_get_id((int *)(¶m->focus_handle));
295 err = mm_sound_register_focus_for_session(param->focus_handle, (int)param->param, "media", sound_codec_focus_callback, (void*)*slotid);
297 debug_error("mm_sound_register_focus_for_session failed [0x%x]", err);
298 pthread_mutex_unlock(&g_slot_mutex);
299 return MM_ERROR_POLICY_INTERNAL;
301 err = mm_sound_acquire_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
303 debug_error("mm_sound_acquire_focus failed [0x%x]", err);
304 err = mm_sound_unregister_focus(param->focus_handle);
305 pthread_mutex_unlock(&g_slot_mutex);
306 return MM_ERROR_POLICY_INTERNAL;
308 g_slots[*slotid].current_focus_type = FOCUS_FOR_BOTH;
309 } else if (param->session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
311 debug_warning("session option is UNINTERRUPTIBLE, nothing to do with focus");
313 debug_warning("need to set focus watch callback");
314 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));
316 debug_error("mm_sound_set_focus_watch_callback_for_session failed [0x%x]", err);
317 pthread_mutex_unlock(&g_slot_mutex);
318 return MM_ERROR_POLICY_INTERNAL;
324 /* Codec id WAV or MP3 */
325 g_slots[*slotid].pluginid = count;
326 g_slots[*slotid].param = param->param; /* This arg is used callback data */
327 g_slots[*slotid].session_type = param->session_type;
328 g_slots[*slotid].session_options = param->session_options;
329 g_slots[*slotid].focus_handle = param->focus_handle;
330 g_slots[*slotid].focus_wcb_id = param->focus_wcb_id;
331 g_slots[*slotid].enable_session = true;
332 g_slots[*slotid].pid = (int)param->param;
335 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
337 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
338 debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
339 if (err != MM_ERROR_NONE) {
340 debug_error("Plugin create fail : 0x%08X\n", err);
341 g_slots[*slotid].status = STATUS_IDLE;
342 pthread_mutex_unlock(&g_slot_mutex);
343 debug_warning("After Slot_mutex UNLOCK\n");
344 if (param->focus_handle) {
345 need_focus_unregister = 1;
350 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
351 if (err != MM_ERROR_NONE) {
352 debug_error("Fail to play : 0x%08X\n", err);
353 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
354 if (param->focus_handle) {
355 need_focus_unregister = 1;
359 pthread_mutex_unlock(&g_slot_mutex);
361 debug_msg("After Slot_mutex UNLOCK\n");
365 if(param->session_type != MM_SESSION_TYPE_CALL &&
366 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
367 param->session_type != MM_SESSION_TYPE_VOIP &&
368 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
369 param->enable_session &&
370 need_focus_unregister == 1) {
372 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) {
373 err = mm_sound_release_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
374 if(mm_sound_unregister_focus(param->focus_handle) || err) {
375 debug_error("focus cleaning up failed[0x%x]", err);
376 return MM_ERROR_POLICY_INTERNAL;
378 } else if (~(param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
379 err = mm_sound_unset_focus_watch_callback(param->focus_wcb_id);
381 debug_error("focus watch cleaning up failed[0x%x]", err);
382 return MM_ERROR_POLICY_INTERNAL;
394 int MMSoundMgrCodecPlayWithStreamInfo(int *slotid, const mmsound_mgr_codec_param_t *param)
397 mmsound_codec_info_t info;
398 mmsound_codec_param_t codec_param;
399 int err = MM_ERROR_NONE;
405 for (count = 0; g_plugins[count].GetSupportTypes; count++) {
407 if (g_plugins[count].Parse(param->source, &info) == MM_ERROR_NONE)
411 /*The count num means codec type WAV, MP3 */
412 debug_msg("Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->repeat_count, param->volume, count);
414 if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
415 debug_error("unsupported file type %d\n", count);
416 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
420 err = _MMSoundMgrCodecGetEmptySlot(slotid);
421 if (err != MM_ERROR_NONE || *slotid < 0) {
422 debug_error("Empty g_slot is not found\n");
426 codec_param.volume_config = -1; //setting volume config to -1 since using stream info instead of volume type
427 codec_param.repeat_count = param->repeat_count;
428 codec_param.volume = param->volume;
429 codec_param.source = param->source;
430 codec_param.priority = param->priority;
431 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
432 codec_param.param = *slotid;
433 codec_param.pid = (int)param->param;
434 codec_param.handle_route = param->handle_route;
435 codec_param.codec_wave_mutex = &codec_wave_mutex;
436 codec_param.stream_index = param->stream_index;
437 MMSOUND_STRNCPY(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
438 pthread_mutex_lock(&g_slot_mutex);
440 debug_msg("After Slot_mutex LOCK\n");
443 /* Codec id WAV or MP3 */
444 g_slots[*slotid].pluginid = count;
445 g_slots[*slotid].param = param->param; /* This arg is used callback data */
447 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
449 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
450 debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
451 if (err != MM_ERROR_NONE) {
452 debug_error("Plugin create fail : 0x%08X\n", err);
453 g_slots[*slotid].status = STATUS_IDLE;
454 pthread_mutex_unlock(&g_slot_mutex);
455 debug_warning("After Slot_mutex UNLOCK\n");
459 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
460 if (err != MM_ERROR_NONE) {
461 debug_error("Fail to play : 0x%08X\n", err);
462 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
465 pthread_mutex_unlock(&g_slot_mutex);
467 debug_msg("After Slot_mutex UNLOCK\n");
480 #define DTMF_PLUGIN_COUNT 2
481 int MMSoundMgrCodecPlayDtmf(int *slotid, const mmsound_mgr_codec_param_t *param)
485 mmsound_codec_info_t info;
486 mmsound_codec_param_t codec_param;
487 int err = MM_ERROR_NONE;
488 int need_focus_unregister = 0;
494 for (count = 0; g_plugins[count].GetSupportTypes; count++) {
496 codec_type = g_plugins[count].GetSupportTypes();
497 if(codec_type && (MM_SOUND_SUPPORTED_CODEC_DTMF == codec_type[0]))
501 /*The count num means codec type DTMF */
502 debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, count);
504 if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
505 debug_error("unsupported file type %d\n", count);
506 printf("unsupported file type %d\n", count);
507 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
512 debug_msg("Get New handle\n");
515 err = _MMSoundMgrCodecGetEmptySlot(slotid);
516 if(err != MM_ERROR_NONE || *slotid < 0)
518 debug_error("Empty g_slot is not found\n");
522 codec_param.tone = param->tone;
523 codec_param.priority = 0;
524 codec_param.volume_config = param->volume_config;
525 codec_param.repeat_count = param->repeat_count;
526 codec_param.volume = param->volume;
527 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
528 codec_param.param = *slotid;
529 codec_param.pid = (int)param->param;
530 codec_param.stream_index = param->stream_index;
531 MMSOUND_STRNCPY(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
533 pthread_mutex_lock(&g_slot_mutex);
535 debug_msg("After Slot_mutex LOCK\n");
540 * Register FOCUS here
543 if (param->session_type != MM_SESSION_TYPE_CALL &&
544 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
545 param->session_type != MM_SESSION_TYPE_VOIP &&
546 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
547 param->enable_session) {
549 unsigned int subs_id = 0;
551 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);
553 debug_error("mm_sound_add_device_connected_callback failed [0x%x]", err);
554 pthread_mutex_unlock(&g_slot_mutex);
555 return MM_ERROR_POLICY_INTERNAL;
557 g_slots[*slotid].subs_id = subs_id;
559 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) {
560 debug_warning("session option is PAUSE_OTHERS -> acquire focus");
561 err = mm_sound_focus_get_id((int *)(¶m->focus_handle));
562 err = mm_sound_register_focus_for_session(param->focus_handle, (int)param->param, "media", sound_codec_focus_callback, (void*)*slotid);
564 debug_error("mm_sound_register_focus failed [0x%x]", err);
565 pthread_mutex_unlock(&g_slot_mutex);
566 return MM_ERROR_POLICY_INTERNAL;
568 err = mm_sound_acquire_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
570 debug_error("mm_sound_acquire_focus failed [0x%x]", err);
571 err = mm_sound_unregister_focus(param->focus_handle);
572 pthread_mutex_unlock(&g_slot_mutex);
573 return MM_ERROR_POLICY_INTERNAL;
575 g_slots[*slotid].current_focus_type = FOCUS_FOR_BOTH;
576 } else if (param->session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
578 debug_warning("session option is UNINTERRUPTIBLE, nothing to do with focus");
580 debug_warning("need to set focus watch callback");
581 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));
583 debug_error("mm_sound_set_focus_watch_callback failed [0x%x]", err);
584 pthread_mutex_unlock(&g_slot_mutex);
585 return MM_ERROR_POLICY_INTERNAL;
590 g_slots[*slotid].pluginid = count;
591 g_slots[*slotid].param = param->param; /* This arg is used callback data */
592 g_slots[*slotid].session_type = param->session_type;
593 g_slots[*slotid].session_options = param->session_options;
594 g_slots[*slotid].focus_handle= param->focus_handle;
595 g_slots[*slotid].focus_wcb_id= param->focus_wcb_id;
596 g_slots[*slotid].enable_session = param->enable_session;
597 g_slots[*slotid].pid = (int)param->param;
600 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
603 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
604 debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
605 if (err != MM_ERROR_NONE) {
606 debug_error("Plugin create fail : 0x%08X\n", err);
607 g_slots[*slotid].status = STATUS_IDLE;
608 pthread_mutex_unlock(&g_slot_mutex);
609 debug_warning("After Slot_mutex UNLOCK\n");
610 need_focus_unregister = 1;
614 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
615 if (err != MM_ERROR_NONE) {
616 debug_error("Fail to play : 0x%08X\n", err);
617 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
618 need_focus_unregister = 1;
621 pthread_mutex_unlock(&g_slot_mutex);
623 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
625 debug_msg("After Slot_mutex UNLOCK\n")
629 if (param->session_type != MM_SESSION_TYPE_CALL &&
630 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
631 param->session_type != MM_SESSION_TYPE_VOIP &&
632 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
633 param->enable_session &&
634 need_focus_unregister == 1) {
636 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) {
637 err = mm_sound_release_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
638 if(mm_sound_unregister_focus(param->focus_handle) || err) {
639 debug_error("focus cleaning up failed[0x%x]", err);
640 return MM_ERROR_POLICY_INTERNAL;
642 } else if (~(param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
643 err = mm_sound_unset_focus_watch_callback(param->focus_wcb_id);
645 debug_error("focus watch cleaning up failed[0x%x]", err);
646 return MM_ERROR_POLICY_INTERNAL;
658 int MMSoundMgrCodecPlayDtmfWithStreamInfo(int *slotid, const mmsound_mgr_codec_param_t *param)
662 mmsound_codec_info_t info;
663 mmsound_codec_param_t codec_param;
664 int err = MM_ERROR_NONE;
670 for (count = 0; g_plugins[count].GetSupportTypes; count++) {
672 codec_type = g_plugins[count].GetSupportTypes();
673 if(codec_type && (MM_SOUND_SUPPORTED_CODEC_DTMF == codec_type[0]))
677 /*The count num means codec type DTMF */
678 debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, count);
680 if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
681 debug_error("unsupported file type %d\n", count);
682 printf("unsupported file type %d\n", count);
683 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
688 debug_msg("Get New handle\n");
691 err = _MMSoundMgrCodecGetEmptySlot(slotid);
692 if(err != MM_ERROR_NONE || *slotid < 0)
694 debug_error("Empty g_slot is not found\n");
698 codec_param.tone = param->tone;
699 codec_param.priority = 0;
700 codec_param.repeat_count = param->repeat_count;
701 codec_param.volume = param->volume;
702 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
703 codec_param.param = *slotid;
704 codec_param.pid = (int)param->param;
705 codec_param.volume_config = -1; //setting volume config to -1 since using stream info instead of volume type
706 codec_param.stream_index = param->stream_index;
707 MMSOUND_STRNCPY(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
709 pthread_mutex_lock(&g_slot_mutex);
711 debug_msg("After Slot_mutex LOCK\n");
713 g_slots[*slotid].pluginid = count;
714 g_slots[*slotid].param = param->param; /* This arg is used callback data */
715 g_slots[*slotid].enable_session = param->enable_session;
718 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
721 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
722 debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
723 if (err != MM_ERROR_NONE) {
724 debug_error("Plugin create fail : 0x%08X\n", err);
725 g_slots[*slotid].status = STATUS_IDLE;
726 pthread_mutex_unlock(&g_slot_mutex);
727 debug_warning("After Slot_mutex UNLOCK\n");
731 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
732 if (err != MM_ERROR_NONE) {
733 debug_error("Fail to play : 0x%08X\n", err);
734 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
737 pthread_mutex_unlock(&g_slot_mutex);
739 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
741 debug_msg("After Slot_mutex UNLOCK\n");
753 int MMSoundMgrCodecStop(const int slotid)
755 int err = MM_ERROR_NONE;
757 debug_enter("(Slotid : [%d])\n", slotid);
759 if (slotid < 0 || MANAGER_HANDLE_MAX <= slotid) {
760 return MM_ERROR_INVALID_ARGUMENT;
763 pthread_mutex_lock (&g_slot_mutex);
765 debug_msg("After Slot_mutex LOCK\n");
767 if (g_slots[slotid].status == STATUS_IDLE) {
768 err = MM_ERROR_SOUND_INVALID_STATE;
769 debug_warning("The playing slots is not found, Slot ID : [%d]\n", slotid);
773 debug_msg("Found slot, Slotid [%d] State [%d]\n", slotid, g_slots[slotid].status);
776 err = g_plugins[g_slots[slotid].pluginid].Stop(g_slots[slotid].plughandle);
777 if (err != MM_ERROR_NONE) {
778 debug_error("Fail to STOP Code : 0x%08X\n", err);
780 debug_msg("Found slot, Slotid [%d] State [%d]\n", slotid, g_slots[slotid].status);
782 pthread_mutex_unlock(&g_slot_mutex);
784 debug_msg("After Slot_mutex UNLOCK\n");
786 debug_leave("(err : 0x%08X)\n", err);
791 int MMSoundMgrCodecClearFocus(int pid)
793 int err = MM_ERROR_NONE;
796 debug_enter("(pid : [%d])\n", pid);
798 pthread_mutex_lock (&g_slot_mutex);
800 for (slotid = 0 ; slotid < MANAGER_HANDLE_MAX ; slotid++) {
801 if (g_slots[slotid].pid == pid) {
802 if (g_slots[slotid].focus_handle || g_slots[slotid].focus_wcb_id) {
803 if(g_slots[slotid].session_type != MM_SESSION_TYPE_CALL &&
804 g_slots[slotid].session_type != MM_SESSION_TYPE_VIDEOCALL &&
805 g_slots[slotid].session_type != MM_SESSION_TYPE_VOIP &&
806 g_slots[slotid].session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
807 g_slots[slotid].enable_session ) {
808 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) {
809 err = mm_sound_release_focus(g_slots[slotid].focus_handle, FOCUS_FOR_BOTH, NULL);
811 debug_error("mm_sound_release_focus failed [0x%x]", err);
813 if(mm_sound_unregister_focus(g_slots[slotid].focus_handle) || err) {
814 debug_error("Focus clean up failed [0x%x]", err);
815 err = MM_ERROR_POLICY_INTERNAL;
818 } else if (~(g_slots[slotid].session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
819 err = mm_sound_unset_focus_watch_callback(g_slots[slotid].focus_wcb_id);
821 debug_error("mm_sound_unset_focus_watch_callback failed [0x%x]", err);
822 err = MM_ERROR_POLICY_INTERNAL;
827 if(mm_sound_remove_device_connected_callback(g_slots[slotid].subs_id) != MM_ERROR_NONE)
828 debug_error("mm_sound_remove_device_connected_callback() failed");
829 g_slots[slotid].focus_handle = 0;
830 g_slots[slotid].focus_wcb_id = 0;
831 g_slots[slotid].subs_id = 0;
837 pthread_mutex_unlock(&g_slot_mutex);
838 debug_leave("(err : 0x%08X)\n", err);
844 static int _MMSoundMgrCodecStopCallback(int param)
846 int err = MM_ERROR_NONE;
848 debug_enter("(Slot : %d)\n", param);
850 pthread_mutex_lock(&g_slot_mutex);
851 debug_msg("[CODEC MGR] Slot_mutex lock done\n");
855 * Unregister FOCUS here
857 debug_msg("[CODEC MGR] enable_session %d ",g_slots[param].enable_session);
859 if (g_slots[param].focus_handle || g_slots[param].focus_wcb_id) {
860 if(g_slots[param].session_type != MM_SESSION_TYPE_CALL &&
861 g_slots[param].session_type != MM_SESSION_TYPE_VIDEOCALL &&
862 g_slots[param].session_type != MM_SESSION_TYPE_VOIP &&
863 g_slots[param].session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
864 g_slots[param].enable_session ) {
865 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) {
866 if(g_slots[param].current_focus_type != FOCUS_NONE) {
867 err = mm_sound_release_focus(g_slots[param].focus_handle, g_slots[param].current_focus_type, NULL);
869 debug_error("mm_sound_release_focus failed [0x%x]", err);
872 if(mm_sound_unregister_focus(g_slots[param].focus_handle) || err) {
873 debug_error("Focus clean up failed [0x%x]", err);
874 pthread_mutex_unlock(&g_slot_mutex);
875 return MM_ERROR_POLICY_INTERNAL;
877 } else if (~(g_slots[param].session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
878 err = mm_sound_unset_focus_watch_callback(g_slots[param].focus_wcb_id);
880 debug_error("mm_sound_unset_focus_watch_callback failed [0x%x]", err);
881 pthread_mutex_unlock(&g_slot_mutex);
882 return MM_ERROR_POLICY_INTERNAL;
886 if(mm_sound_remove_device_connected_callback(g_slots[param].subs_id) != MM_ERROR_NONE)
887 debug_error("mm_sound_remove_device_connected_callback() failed");
890 __mm_sound_mgr_ipc_notify_play_file_end(param);
892 debug_msg("Client callback msg_type (instance) : [%d]\n", (int)g_slots[param].param);
893 debug_msg("Handle allocated handle : [0x%08X]\n", g_slots[param].plughandle);
894 err = g_plugins[g_slots[param].pluginid].Destroy(g_slots[param].plughandle);
896 debug_critical("[CODEC MGR] Fail to destroy slot number : [%d] err [0x%x]\n", param, err);
898 memset(&g_slots[param], 0, sizeof(__mmsound_mgr_codec_handle_t));
899 g_slots[param].status = STATUS_IDLE;
900 pthread_mutex_unlock(&g_slot_mutex);
901 debug_msg("[CODEC MGR] Slot_mutex done\n");
906 static int _MMSoundMgrCodecGetEmptySlot(int *slot)
909 int err = MM_ERROR_NONE;
914 debug_msg("Codec slot ID : [%d]\n", *slot);
915 pthread_mutex_lock(&g_slot_mutex);
917 debug_msg("After Slot_mutex LOCK\n");
920 for (count = SOUND_SLOT_START; count < MANAGER_HANDLE_MAX ; count++) {
921 if (g_slots[count].status == STATUS_IDLE) {
922 g_slots[count].status = STATUS_SOUND;
926 pthread_mutex_unlock(&g_slot_mutex);
928 debug_msg("After Slot_mutex UNLOCK\n");
931 if (count < MANAGER_HANDLE_MAX) {
932 debug_msg("New handle allocated (codec slot ID : [%d])\n", count);
936 debug_warning("Handle is full handle : [%d]\n", count);
938 /* Temporal code for reset */
940 g_slots[count].status = STATUS_IDLE;
942 err = MM_ERROR_SOUND_INTERNAL;
952 static int _MMSoundMgrCodecRegisterInterface(MMSoundPluginType *plugin)
954 int err = MM_ERROR_NONE;
956 void *getinterface = NULL;
962 /* find emptry slot */
963 for (count = 0; count < MM_SOUND_SUPPORTED_CODEC_NUM; count++) {
964 if (g_plugins[count].GetSupportTypes == NULL)
968 if (count == MM_SOUND_SUPPORTED_CODEC_NUM) {
969 debug_critical("The plugin support type is not valid\n");
970 return MM_ERROR_COMMON_OUT_OF_RANGE;
973 err = MMSoundPluginGetSymbol(plugin, CODEC_GET_INTERFACE_FUNC_NAME, &getinterface);
974 if (err != MM_ERROR_NONE) {
975 debug_error("Get Symbol CODEC_GET_INTERFACE_FUNC_NAME is fail : %x\n", err);
978 debug_msg("interface[%p] empty_slot[%d]\n", getinterface, count);
980 err = MMSoundPlugCodecCastGetInterface(getinterface)(&g_plugins[count]);
981 if (err != MM_ERROR_NONE) {
982 debug_error("Get interface fail : %x\n", err);
985 /* If error occur, clean interface */
986 memset(&g_plugins[count], 0, sizeof(mmsound_codec_interface_t));
988 if (g_plugins[count].SetThreadPool)
989 g_plugins[count].SetThreadPool(MMSoundThreadPoolRun);