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"
41 #include "../include/mm_sound_common.h"
42 #include "../include/mm_sound_focus.h"
44 #define _ENABLE_KEYTONE /* Temporal test code */
46 /* #define FOCUS_INTEGRATION */
49 int (*callback)(int, void *, void *, int); /* msg_type(pid) client callback & client data info */
54 MMHandleType plughandle;
60 #ifdef FOCUS_INTEGRATION
64 mm_sound_focus_type_e current_focus_type;
68 } __mmsound_mgr_codec_handle_t;
70 static MMSoundPluginType *g_codec_plugins = NULL;
71 static __mmsound_mgr_codec_handle_t g_slots[MANAGER_HANDLE_MAX];
72 static mmsound_codec_interface_t g_plugins[MM_SOUND_SUPPORTED_CODEC_NUM];
73 static pthread_mutex_t g_slot_mutex;
74 static pthread_mutex_t codec_wave_mutex;
75 static int _MMSoundMgrCodecStopCallback(int param);
76 static int _MMSoundMgrCodecGetEmptySlot(int *slotid);
77 static int _MMSoundMgrCodecRegisterInterface(MMSoundPluginType *plugin);
80 #define STATUS_SOUND 3
82 #define SOUND_SLOT_START 0
84 #ifdef FOCUS_INTEGRATION
86 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, int option, const char *ext_info, void *user_data)
89 int slotid = (int)user_data;
90 int result = MM_ERROR_NONE;
92 debug_warning ("focus callback called -> focus_stae(%d), reasoun_for_change(%s)", focus_state, reason_for_change ? reason_for_change : "N/A");
94 if(g_slots[slotid].session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE){
95 debug_warning ("session option is UNINTERRUPTIBLE, nothing to do with focus");
98 if (focus_state == FOCUS_IS_RELEASED) {
99 g_slots[slotid].current_focus_type = FOCUS_FOR_BOTH&(~focus_type);
100 debug_warning ("focus is released -> stop playing");
101 result = MMSoundMgrCodecStop(slotid);
102 if (result != MM_ERROR_NONE) {
103 debug_log("result error %d\n", result);
110 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* ext_info, void *user_data)
112 int slotid = (int)user_data;
113 int result = MM_ERROR_NONE;
115 debug_warning ("focus callback called -> focus_stae(%d), reasoun_for_change(%s)", focus_state, reason_for_change ? reason_for_change : "N/A");
117 if(g_slots[slotid].session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE){
118 debug_warning ("session option is UNINTERRUPTIBLE, nothing to do with focus");
121 if (focus_state == FOCUS_IS_ACQUIRED) {
122 debug_warning ("focus is released -> stop playing");
123 result = MMSoundMgrCodecStop(slotid);
124 if (result != MM_ERROR_NONE) {
125 debug_log("result error %d\n", result);
133 void sound_codec_device_connected_callback(MMSoundDevice_t device, bool is_connected, void *user_data)
135 int slotid = (int)user_data;
136 int result = MM_ERROR_NONE;
137 mm_sound_device_type_e type;
139 debug_warning ("device_connected_callback called");
141 if (mm_sound_get_device_type (device, &type) != MM_ERROR_NONE) {
142 debug_error("getting device type failed");
145 case MM_SOUND_DEVICE_TYPE_AUDIOJACK:
146 case MM_SOUND_DEVICE_TYPE_BLUETOOTH_A2DP:
147 case MM_SOUND_DEVICE_TYPE_BLUETOOTH_SCO:
148 case MM_SOUND_DEVICE_TYPE_HDMI:
149 case MM_SOUND_DEVICE_TYPE_MIRRORING:
150 case MM_SOUND_DEVICE_TYPE_USB_AUDIO:
152 debug_warning("sound device unplugged");
153 result = MMSoundMgrCodecStop(slotid);
154 if (result != MM_ERROR_NONE) {
155 debug_error("MMSoundMgrCodecStop error %d\n", result);
157 result = mm_sound_remove_device_connected_callback(g_slots[slotid].subs_id);
158 if (result != MM_ERROR_NONE) {
159 debug_error("mm_sound_remove_device_connected_callback error %d\n", result);
170 int MMSoundMgrCodecInit(const char *targetdir)
177 memset (g_slots, 0, sizeof(g_slots));
179 if(pthread_mutex_init(&g_slot_mutex, NULL)) {
180 debug_error("pthread_mutex_init failed\n");
181 return MM_ERROR_SOUND_INTERNAL;
184 if(pthread_mutex_init(&codec_wave_mutex, NULL)) {
185 debug_error("pthread_mutex_init failed\n");
186 return MM_ERROR_SOUND_INTERNAL;
189 for (count = 0; count < MANAGER_HANDLE_MAX; count++) {
190 g_slots[count].status = STATUS_IDLE;
191 g_slots[count].plughandle = 0;
194 if (g_codec_plugins) {
195 debug_warning("Please Check Init twice\n");
196 MMSoundPluginRelease(g_codec_plugins);
199 MMSoundPluginScan(targetdir, MM_SOUND_PLUGIN_TYPE_CODEC, &g_codec_plugins);
200 if (g_codec_plugins) {
201 while (g_codec_plugins[loop].type != MM_SOUND_PLUGIN_TYPE_NONE) {
202 _MMSoundMgrCodecRegisterInterface(&g_codec_plugins[loop++]);
207 return MM_ERROR_NONE;
210 int MMSoundMgrCodecFini(void)
214 memset(g_plugins, 0, sizeof(mmsound_codec_interface_t) * MM_SOUND_SUPPORTED_CODEC_NUM);
215 MMSoundPluginRelease(g_codec_plugins);
216 g_codec_plugins = NULL;
217 pthread_mutex_destroy(&g_slot_mutex);
218 pthread_mutex_destroy(&codec_wave_mutex);
220 return MM_ERROR_NONE;
224 int MMSoundMgrCodecPlay(int *slotid, const mmsound_mgr_codec_param_t *param)
227 mmsound_codec_info_t info;
228 mmsound_codec_param_t codec_param;
229 int err = MM_ERROR_NONE;
230 #ifdef FOCUS_INTEGRATION
231 int need_focus_unregister = 0;
238 for (count = 0; g_plugins[count].GetSupportTypes; count++) {
240 if (g_plugins[count].Parse(param->source, &info) == MM_ERROR_NONE)
244 /*The count num means codec type WAV, MP3 */
245 debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, count);
247 if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
248 debug_error("unsupported file type %d\n", count);
249 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
254 debug_msg("Get New handle\n");
257 err = _MMSoundMgrCodecGetEmptySlot(slotid);
258 if (err != MM_ERROR_NONE || *slotid < 0) {
259 debug_error("Empty g_slot is not found\n");
263 codec_param.tone = param->tone;
264 codec_param.volume_config = param->volume_config;
265 codec_param.repeat_count = param->repeat_count;
266 codec_param.volume = param->volume;
267 codec_param.source = param->source;
268 codec_param.priority = param->priority;
269 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
270 codec_param.param = *slotid;
271 codec_param.pid = (int)param->param;
272 codec_param.handle_route = param->handle_route;
273 codec_param.codec_wave_mutex = &codec_wave_mutex;
274 codec_param.stream_index = param->stream_index;
275 MMSOUND_STRNCPY(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
276 pthread_mutex_lock(&g_slot_mutex);
278 debug_msg("After Slot_mutex LOCK\n");
281 #ifdef FOCUS_INTEGRATION
283 * Register FOCUS here
286 if (param->session_type != MM_SESSION_TYPE_CALL &&
287 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
288 param->session_type != MM_SESSION_TYPE_VOIP &&
289 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
290 param->enable_session) {
292 unsigned int subs_id = 0;
294 err = mm_sound_add_device_connected_callback(MM_SOUND_DEVICE_STATE_ACTIVATED_FLAG, (mm_sound_device_connected_cb)sound_codec_device_connected_callback, (void*) *slotid, &subs_id);
296 debug_error("mm_sound_add_device_connected_callback failed [0x%x]", err);
297 pthread_mutex_unlock(&g_slot_mutex);
298 return MM_ERROR_POLICY_INTERNAL;
300 g_slots[*slotid].subs_id = subs_id;
302 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) {
303 debug_warning("session option is PAUSE_OTHERS -> acquire focus");
304 err = mm_sound_focus_get_id((int *)(¶m->focus_handle));
305 err = mm_sound_register_focus_for_session(param->focus_handle, (int)param->param, "media", sound_codec_focus_callback, (void*)*slotid);
307 debug_error("mm_sound_register_focus_for_session failed [0x%x]", err);
308 pthread_mutex_unlock(&g_slot_mutex);
309 return MM_ERROR_POLICY_INTERNAL;
311 err = mm_sound_acquire_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
313 debug_error("mm_sound_acquire_focus failed [0x%x]", err);
314 err = mm_sound_unregister_focus(param->focus_handle);
315 pthread_mutex_unlock(&g_slot_mutex);
316 return MM_ERROR_POLICY_INTERNAL;
318 g_slots[*slotid].current_focus_type = FOCUS_FOR_BOTH;
319 } else if (param->session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
321 debug_warning("session option is UNINTERRUPTIBLE, nothing to do with focus");
323 debug_warning("need to set focus watch callback");
324 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));
326 debug_error("mm_sound_set_focus_watch_callback_for_session failed [0x%x]", err);
327 pthread_mutex_unlock(&g_slot_mutex);
328 return MM_ERROR_POLICY_INTERNAL;
335 /* Codec id WAV or MP3 */
336 g_slots[*slotid].pluginid = count;
337 g_slots[*slotid].param = param->param; /* This arg is used callback data */
338 g_slots[*slotid].session_type = param->session_type;
339 g_slots[*slotid].session_options = param->session_options;
340 #ifdef FOCUS_INTEGRATION
341 g_slots[*slotid].focus_handle = param->focus_handle;
342 g_slots[*slotid].focus_wcb_id = param->focus_wcb_id;
344 g_slots[*slotid].enable_session = true;
345 g_slots[*slotid].pid = (int)param->param;
348 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
350 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
351 debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
352 if (err != MM_ERROR_NONE) {
353 debug_error("Plugin create fail : 0x%08X\n", err);
354 g_slots[*slotid].status = STATUS_IDLE;
355 pthread_mutex_unlock(&g_slot_mutex);
356 debug_warning("After Slot_mutex UNLOCK\n");
357 #ifdef FOCUS_INTEGRATION
358 if (param->focus_handle) {
359 need_focus_unregister = 1;
365 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
366 if (err != MM_ERROR_NONE) {
367 debug_error("Fail to play : 0x%08X\n", err);
368 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
369 #ifdef FOCUS_INTEGRATION
370 if (param->focus_handle) {
371 need_focus_unregister = 1;
376 pthread_mutex_unlock(&g_slot_mutex);
378 debug_msg("After Slot_mutex UNLOCK\n");
382 #ifdef FOCUS_INTEGRATION
383 if(param->session_type != MM_SESSION_TYPE_CALL &&
384 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
385 param->session_type != MM_SESSION_TYPE_VOIP &&
386 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
387 param->enable_session &&
388 need_focus_unregister == 1) {
390 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) {
391 err = mm_sound_release_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
392 if(mm_sound_unregister_focus(param->focus_handle) || err) {
393 debug_error("focus cleaning up failed[0x%x]", err);
394 return MM_ERROR_POLICY_INTERNAL;
396 } else if (~(param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
397 err = mm_sound_unset_focus_watch_callback(param->focus_wcb_id);
399 debug_error("focus watch cleaning up failed[0x%x]", err);
400 return MM_ERROR_POLICY_INTERNAL;
413 int MMSoundMgrCodecPlayWithStreamInfo(int *slotid, const mmsound_mgr_codec_param_t *param)
416 mmsound_codec_info_t info;
417 mmsound_codec_param_t codec_param;
418 int err = MM_ERROR_NONE;
424 for (count = 0; g_plugins[count].GetSupportTypes; count++) {
426 if (g_plugins[count].Parse(param->source, &info) == MM_ERROR_NONE)
430 /*The count num means codec type WAV, MP3 */
431 debug_msg("Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->repeat_count, param->volume, count);
433 if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
434 debug_error("unsupported file type %d\n", count);
435 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
439 err = _MMSoundMgrCodecGetEmptySlot(slotid);
440 if (err != MM_ERROR_NONE || *slotid < 0) {
441 debug_error("Empty g_slot is not found\n");
445 codec_param.volume_config = -1; //setting volume config to -1 since using stream info instead of volume type
446 codec_param.repeat_count = param->repeat_count;
447 codec_param.volume = param->volume;
448 codec_param.source = param->source;
449 codec_param.priority = param->priority;
450 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
451 codec_param.param = *slotid;
452 codec_param.pid = (int)param->param;
453 codec_param.handle_route = param->handle_route;
454 codec_param.codec_wave_mutex = &codec_wave_mutex;
455 codec_param.stream_index = param->stream_index;
456 MMSOUND_STRNCPY(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
457 pthread_mutex_lock(&g_slot_mutex);
459 debug_msg("After Slot_mutex LOCK\n");
462 /* Codec id WAV or MP3 */
463 g_slots[*slotid].pluginid = count;
464 g_slots[*slotid].param = param->param; /* This arg is used callback data */
466 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
468 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
469 debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
470 if (err != MM_ERROR_NONE) {
471 debug_error("Plugin create fail : 0x%08X\n", err);
472 g_slots[*slotid].status = STATUS_IDLE;
473 pthread_mutex_unlock(&g_slot_mutex);
474 debug_warning("After Slot_mutex UNLOCK\n");
478 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
479 if (err != MM_ERROR_NONE) {
480 debug_error("Fail to play : 0x%08X\n", err);
481 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
484 pthread_mutex_unlock(&g_slot_mutex);
486 debug_msg("After Slot_mutex UNLOCK\n");
499 #define DTMF_PLUGIN_COUNT 2
500 int MMSoundMgrCodecPlayDtmf(int *slotid, const mmsound_mgr_codec_param_t *param)
504 mmsound_codec_info_t info;
505 mmsound_codec_param_t codec_param;
506 int err = MM_ERROR_NONE;
507 #ifdef FOCUS_INTEGRATION
508 int need_focus_unregister = 0;
515 for (count = 0; g_plugins[count].GetSupportTypes; count++) {
517 codec_type = g_plugins[count].GetSupportTypes();
518 if(codec_type && (MM_SOUND_SUPPORTED_CODEC_DTMF == codec_type[0]))
522 /*The count num means codec type DTMF */
523 debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, count);
525 if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
526 debug_error("unsupported file type %d\n", count);
527 printf("unsupported file type %d\n", count);
528 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
533 debug_msg("Get New handle\n");
536 err = _MMSoundMgrCodecGetEmptySlot(slotid);
537 if(err != MM_ERROR_NONE || *slotid < 0)
539 debug_error("Empty g_slot is not found\n");
543 codec_param.tone = param->tone;
544 codec_param.priority = 0;
545 codec_param.volume_config = param->volume_config;
546 codec_param.repeat_count = param->repeat_count;
547 codec_param.volume = param->volume;
548 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
549 codec_param.param = *slotid;
550 codec_param.pid = (int)param->param;
551 codec_param.stream_index = param->stream_index;
552 MMSOUND_STRNCPY(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
554 pthread_mutex_lock(&g_slot_mutex);
556 debug_msg("After Slot_mutex LOCK\n");
559 #ifdef FOCUS_INTEGRATION
562 * Register FOCUS here
565 if (param->session_type != MM_SESSION_TYPE_CALL &&
566 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
567 param->session_type != MM_SESSION_TYPE_VOIP &&
568 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
569 param->enable_session) {
571 unsigned int subs_id = 0;
573 err = mm_sound_add_device_connected_callback(MM_SOUND_DEVICE_STATE_ACTIVATED_FLAG, (mm_sound_device_connected_cb)sound_codec_device_connected_callback, (void*) *slotid, &subs_id);
575 debug_error("mm_sound_add_device_connected_callback failed [0x%x]", err);
576 pthread_mutex_unlock(&g_slot_mutex);
577 return MM_ERROR_POLICY_INTERNAL;
579 g_slots[*slotid].subs_id = subs_id;
581 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) {
582 debug_warning("session option is PAUSE_OTHERS -> acquire focus");
583 err = mm_sound_focus_get_id((int *)(¶m->focus_handle));
584 err = mm_sound_register_focus_for_session(param->focus_handle, (int)param->param, "media", sound_codec_focus_callback, (void*)*slotid);
586 debug_error("mm_sound_register_focus failed [0x%x]", err);
587 pthread_mutex_unlock(&g_slot_mutex);
588 return MM_ERROR_POLICY_INTERNAL;
590 err = mm_sound_acquire_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
592 debug_error("mm_sound_acquire_focus failed [0x%x]", err);
593 err = mm_sound_unregister_focus(param->focus_handle);
594 pthread_mutex_unlock(&g_slot_mutex);
595 return MM_ERROR_POLICY_INTERNAL;
597 g_slots[*slotid].current_focus_type = FOCUS_FOR_BOTH;
598 } else if (param->session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
600 debug_warning("session option is UNINTERRUPTIBLE, nothing to do with focus");
602 debug_warning("need to set focus watch callback");
603 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));
605 debug_error("mm_sound_set_focus_watch_callback failed [0x%x]", err);
606 pthread_mutex_unlock(&g_slot_mutex);
607 return MM_ERROR_POLICY_INTERNAL;
613 g_slots[*slotid].pluginid = count;
614 g_slots[*slotid].param = param->param; /* This arg is used callback data */
615 g_slots[*slotid].session_type = param->session_type;
616 g_slots[*slotid].session_options = param->session_options;
617 #ifdef FOCUS_INTEGRATION
618 g_slots[*slotid].focus_handle= param->focus_handle;
619 g_slots[*slotid].focus_wcb_id= param->focus_wcb_id;
621 g_slots[*slotid].enable_session = param->enable_session;
622 g_slots[*slotid].pid = (int)param->param;
625 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
628 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
629 debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
630 if (err != MM_ERROR_NONE) {
631 debug_error("Plugin create fail : 0x%08X\n", err);
632 g_slots[*slotid].status = STATUS_IDLE;
633 pthread_mutex_unlock(&g_slot_mutex);
634 debug_warning("After Slot_mutex UNLOCK\n");
635 #ifdef FOCUS_INTEGRATION
636 need_focus_unregister = 1;
641 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
642 if (err != MM_ERROR_NONE) {
643 debug_error("Fail to play : 0x%08X\n", err);
644 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
645 #ifdef FOCUS_INTEGRATION
646 need_focus_unregister = 1;
650 pthread_mutex_unlock(&g_slot_mutex);
652 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
654 debug_msg("After Slot_mutex UNLOCK\n")
658 #ifdef FOCUS_INTEGRATION
659 if (param->session_type != MM_SESSION_TYPE_CALL &&
660 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
661 param->session_type != MM_SESSION_TYPE_VOIP &&
662 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
663 param->enable_session &&
664 need_focus_unregister == 1) {
666 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) {
667 err = mm_sound_release_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
668 if(mm_sound_unregister_focus(param->focus_handle) || err) {
669 debug_error("focus cleaning up failed[0x%x]", err);
670 return MM_ERROR_POLICY_INTERNAL;
672 } else if (~(param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
673 err = mm_sound_unset_focus_watch_callback(param->focus_wcb_id);
675 debug_error("focus watch cleaning up failed[0x%x]", err);
676 return MM_ERROR_POLICY_INTERNAL;
689 int MMSoundMgrCodecPlayDtmfWithStreamInfo(int *slotid, const mmsound_mgr_codec_param_t *param)
693 mmsound_codec_info_t info;
694 mmsound_codec_param_t codec_param;
695 int err = MM_ERROR_NONE;
701 for (count = 0; g_plugins[count].GetSupportTypes; count++) {
703 codec_type = g_plugins[count].GetSupportTypes();
704 if(codec_type && (MM_SOUND_SUPPORTED_CODEC_DTMF == codec_type[0]))
708 /*The count num means codec type DTMF */
709 debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, count);
711 if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
712 debug_error("unsupported file type %d\n", count);
713 printf("unsupported file type %d\n", count);
714 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
719 debug_msg("Get New handle\n");
722 err = _MMSoundMgrCodecGetEmptySlot(slotid);
723 if(err != MM_ERROR_NONE || *slotid < 0)
725 debug_error("Empty g_slot is not found\n");
729 codec_param.tone = param->tone;
730 codec_param.priority = 0;
731 codec_param.repeat_count = param->repeat_count;
732 codec_param.volume = param->volume;
733 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
734 codec_param.param = *slotid;
735 codec_param.pid = (int)param->param;
736 codec_param.volume_config = -1; //setting volume config to -1 since using stream info instead of volume type
737 codec_param.stream_index = param->stream_index;
738 MMSOUND_STRNCPY(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
740 pthread_mutex_lock(&g_slot_mutex);
742 debug_msg("After Slot_mutex LOCK\n");
744 g_slots[*slotid].pluginid = count;
745 g_slots[*slotid].param = param->param; /* This arg is used callback data */
746 g_slots[*slotid].enable_session = param->enable_session;
749 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
752 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
753 debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
754 if (err != MM_ERROR_NONE) {
755 debug_error("Plugin create fail : 0x%08X\n", err);
756 g_slots[*slotid].status = STATUS_IDLE;
757 pthread_mutex_unlock(&g_slot_mutex);
758 debug_warning("After Slot_mutex UNLOCK\n");
762 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
763 if (err != MM_ERROR_NONE) {
764 debug_error("Fail to play : 0x%08X\n", err);
765 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
768 pthread_mutex_unlock(&g_slot_mutex);
770 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
772 debug_msg("After Slot_mutex UNLOCK\n");
784 int MMSoundMgrCodecStop(const int slotid)
786 int err = MM_ERROR_NONE;
788 debug_enter("(Slotid : [%d])\n", slotid);
790 if (slotid < 0 || MANAGER_HANDLE_MAX <= slotid) {
791 return MM_ERROR_INVALID_ARGUMENT;
794 pthread_mutex_lock (&g_slot_mutex);
796 debug_msg("After Slot_mutex LOCK\n");
798 if (g_slots[slotid].status == STATUS_IDLE) {
799 err = MM_ERROR_SOUND_INVALID_STATE;
800 debug_warning("The playing slots is not found, Slot ID : [%d]\n", slotid);
804 debug_msg("Found slot, Slotid [%d] State [%d]\n", slotid, g_slots[slotid].status);
807 err = g_plugins[g_slots[slotid].pluginid].Stop(g_slots[slotid].plughandle);
808 if (err != MM_ERROR_NONE) {
809 debug_error("Fail to STOP Code : 0x%08X\n", err);
811 debug_msg("Found slot, Slotid [%d] State [%d]\n", slotid, g_slots[slotid].status);
813 pthread_mutex_unlock(&g_slot_mutex);
815 debug_msg("After Slot_mutex UNLOCK\n");
817 debug_leave("(err : 0x%08X)\n", err);
821 #ifdef FOCUS_INTEGRATION
822 int MMSoundMgrCodecClearFocus(int pid)
824 int err = MM_ERROR_NONE;
827 debug_enter("(pid : [%d])\n", pid);
829 pthread_mutex_lock (&g_slot_mutex);
831 for (slotid = 0 ; slotid < MANAGER_HANDLE_MAX ; slotid++) {
832 if (g_slots[slotid].pid == pid) {
833 if (g_slots[slotid].focus_handle || g_slots[slotid].focus_wcb_id) {
834 if(g_slots[slotid].session_type != MM_SESSION_TYPE_CALL &&
835 g_slots[slotid].session_type != MM_SESSION_TYPE_VIDEOCALL &&
836 g_slots[slotid].session_type != MM_SESSION_TYPE_VOIP &&
837 g_slots[slotid].session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
838 g_slots[slotid].enable_session ) {
839 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) {
840 err = mm_sound_release_focus(g_slots[slotid].focus_handle, FOCUS_FOR_BOTH, NULL);
842 debug_error("mm_sound_release_focus failed [0x%x]", err);
844 if(mm_sound_unregister_focus(g_slots[slotid].focus_handle) || err) {
845 debug_error("Focus clean up failed [0x%x]", err);
846 err = MM_ERROR_POLICY_INTERNAL;
849 } else if (~(g_slots[slotid].session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
850 err = mm_sound_unset_focus_watch_callback(g_slots[slotid].focus_wcb_id);
852 debug_error("mm_sound_unset_focus_watch_callback failed [0x%x]", err);
853 err = MM_ERROR_POLICY_INTERNAL;
858 if(mm_sound_remove_device_connected_callback(g_slots[slotid].subs_id) != MM_ERROR_NONE)
859 debug_error("mm_sound_remove_device_connected_callback() failed");
860 g_slots[slotid].focus_handle = 0;
861 g_slots[slotid].focus_wcb_id = 0;
862 g_slots[slotid].subs_id = 0;
868 pthread_mutex_unlock(&g_slot_mutex);
869 debug_leave("(err : 0x%08X)\n", err);
875 static int _MMSoundMgrCodecStopCallback(int param)
877 int err = MM_ERROR_NONE;
879 debug_enter("(Slot : %d)\n", param);
881 if (param < 0 || param >= MANAGER_HANDLE_MAX) {
882 debug_error ("Slot index param [%d] is invalid", param);
883 return MM_ERROR_INVALID_ARGUMENT;
886 pthread_mutex_lock(&g_slot_mutex);
887 debug_msg("[CODEC MGR] Slot_mutex lock done\n");
889 #ifdef FOCUS_INTEGRATION
891 * Unregister FOCUS here
893 debug_msg("[CODEC MGR] enable_session %d ",g_slots[param].enable_session);
895 if (g_slots[param].focus_handle || g_slots[param].focus_wcb_id) {
896 if(g_slots[param].session_type != MM_SESSION_TYPE_CALL &&
897 g_slots[param].session_type != MM_SESSION_TYPE_VIDEOCALL &&
898 g_slots[param].session_type != MM_SESSION_TYPE_VOIP &&
899 g_slots[param].session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
900 g_slots[param].enable_session ) {
901 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) {
902 if(g_slots[param].current_focus_type != FOCUS_NONE) {
903 err = mm_sound_release_focus(g_slots[param].focus_handle, g_slots[param].current_focus_type, NULL);
905 debug_error("mm_sound_release_focus failed [0x%x]", err);
908 if(mm_sound_unregister_focus(g_slots[param].focus_handle) || err) {
909 debug_error("Focus clean up failed [0x%x]", err);
910 pthread_mutex_unlock(&g_slot_mutex);
911 return MM_ERROR_POLICY_INTERNAL;
913 } else if (~(g_slots[param].session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
914 err = mm_sound_unset_focus_watch_callback(g_slots[param].focus_wcb_id);
916 debug_error("mm_sound_unset_focus_watch_callback failed [0x%x]", err);
917 pthread_mutex_unlock(&g_slot_mutex);
918 return MM_ERROR_POLICY_INTERNAL;
922 if(mm_sound_remove_device_connected_callback(g_slots[param].subs_id) != MM_ERROR_NONE)
923 debug_error("mm_sound_remove_device_connected_callback() failed");
927 __mm_sound_mgr_ipc_notify_play_file_end(param);
929 debug_msg("Client callback msg_type (instance) : [%d]\n", (int)g_slots[param].param);
930 debug_msg("Handle allocated handle : [0x%08X]\n", g_slots[param].plughandle);
931 err = g_plugins[g_slots[param].pluginid].Destroy(g_slots[param].plughandle);
933 debug_critical("[CODEC MGR] Fail to destroy slot number : [%d] err [0x%x]\n", param, err);
935 memset(&g_slots[param], 0, sizeof(__mmsound_mgr_codec_handle_t));
936 g_slots[param].status = STATUS_IDLE;
937 pthread_mutex_unlock(&g_slot_mutex);
938 debug_msg("[CODEC MGR] Slot_mutex done\n");
943 static int _MMSoundMgrCodecGetEmptySlot(int *slot)
946 int err = MM_ERROR_NONE;
951 debug_msg("Codec slot ID : [%d]\n", *slot);
952 pthread_mutex_lock(&g_slot_mutex);
954 debug_msg("After Slot_mutex LOCK\n");
957 for (count = SOUND_SLOT_START; count < MANAGER_HANDLE_MAX ; count++) {
958 if (g_slots[count].status == STATUS_IDLE) {
959 g_slots[count].status = STATUS_SOUND;
963 pthread_mutex_unlock(&g_slot_mutex);
965 debug_msg("After Slot_mutex UNLOCK\n");
968 if (count < MANAGER_HANDLE_MAX) {
969 debug_msg("New handle allocated (codec slot ID : [%d])\n", count);
973 debug_warning("Handle is full handle : [%d]\n", count);
975 /* Temporal code for reset */
977 g_slots[count].status = STATUS_IDLE;
979 err = MM_ERROR_SOUND_INTERNAL;
989 static int _MMSoundMgrCodecRegisterInterface(MMSoundPluginType *plugin)
991 int err = MM_ERROR_NONE;
993 void *getinterface = NULL;
999 /* find emptry slot */
1000 for (count = 0; count < MM_SOUND_SUPPORTED_CODEC_NUM; count++) {
1001 if (g_plugins[count].GetSupportTypes == NULL)
1005 if (count == MM_SOUND_SUPPORTED_CODEC_NUM) {
1006 debug_critical("The plugin support type is not valid\n");
1007 return MM_ERROR_COMMON_OUT_OF_RANGE;
1010 err = MMSoundPluginGetSymbol(plugin, CODEC_GET_INTERFACE_FUNC_NAME, &getinterface);
1011 if (err != MM_ERROR_NONE) {
1012 debug_error("Get Symbol CODEC_GET_INTERFACE_FUNC_NAME is fail : %x\n", err);
1015 debug_msg("interface[%p] empty_slot[%d]\n", getinterface, count);
1017 err = MMSoundPlugCodecCastGetInterface(getinterface)(&g_plugins[count]);
1018 if (err != MM_ERROR_NONE) {
1019 debug_error("Get interface fail : %x\n", err);
1022 /* If error occur, clean interface */
1023 memset(&g_plugins[count], 0, sizeof(mmsound_codec_interface_t));
1025 if (g_plugins[count].SetThreadPool)
1026 g_plugins[count].SetThreadPool(MMSoundThreadPoolRun);