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 */
47 int (*callback)(int, void *, void *, int); /* msg_type(pid) client callback & client data info */
52 MMHandleType plughandle;
61 mm_sound_focus_type_e current_focus_type;
64 } __mmsound_mgr_codec_handle_t;
66 static MMSoundPluginType *g_codec_plugins = NULL;
67 static __mmsound_mgr_codec_handle_t g_slots[MANAGER_HANDLE_MAX];
68 static mmsound_codec_interface_t g_plugins[MM_SOUND_SUPPORTED_CODEC_NUM];
69 static pthread_mutex_t g_slot_mutex;
70 static pthread_mutex_t codec_wave_mutex;
71 static int _MMSoundMgrCodecStopCallback(int param);
72 static int _MMSoundMgrCodecGetEmptySlot(int *slotid);
73 static int _MMSoundMgrCodecRegisterInterface(MMSoundPluginType *plugin);
76 #define STATUS_SOUND 3
78 #define SOUND_SLOT_START 0
80 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)
83 int slotid = (int)user_data;
84 int result = MM_ERROR_NONE;
86 debug_warning ("focus callback called -> focus_stae(%d), reasoun_for_change(%s)", focus_state, reason_for_change ? reason_for_change : "N/A");
88 if(g_slots[slotid].session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE){
89 debug_warning ("session option is UNINTERRUPTIBLE, nothing to do with focus");
92 if (focus_state == FOCUS_IS_RELEASED) {
93 g_slots[slotid].current_focus_type = FOCUS_FOR_BOTH&(~focus_type);
94 debug_warning ("focus is released -> stop playing");
95 result = MMSoundMgrCodecStop(slotid);
96 if (result != MM_ERROR_NONE) {
97 debug_log("result error %d\n", result);
104 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)
106 int slotid = (int)user_data;
107 int result = MM_ERROR_NONE;
109 debug_warning ("focus callback called -> focus_stae(%d), reasoun_for_change(%s)", focus_state, reason_for_change ? reason_for_change : "N/A");
111 if(g_slots[slotid].session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE){
112 debug_warning ("session option is UNINTERRUPTIBLE, nothing to do with focus");
115 if (focus_state == FOCUS_IS_ACQUIRED) {
116 debug_warning ("focus is released -> stop playing");
117 result = MMSoundMgrCodecStop(slotid);
118 if (result != MM_ERROR_NONE) {
119 debug_log("result error %d\n", result);
126 void sound_codec_device_connected_callback(MMSoundDevice_t device, bool is_connected, void *user_data)
128 int slotid = (int)user_data;
129 int result = MM_ERROR_NONE;
130 mm_sound_device_type_e type;
132 debug_warning ("device_connected_callback called");
134 if (mm_sound_get_device_type (device, &type) != MM_ERROR_NONE) {
135 debug_error("getting device type failed");
138 case MM_SOUND_DEVICE_TYPE_AUDIOJACK:
139 case MM_SOUND_DEVICE_TYPE_BLUETOOTH:
140 case MM_SOUND_DEVICE_TYPE_HDMI:
141 case MM_SOUND_DEVICE_TYPE_MIRRORING:
142 case MM_SOUND_DEVICE_TYPE_USB_AUDIO:
144 debug_warning("sound device unplugged");
145 result = MMSoundMgrCodecStop(slotid);
146 if (result != MM_ERROR_NONE) {
147 debug_error("MMSoundMgrCodecStop error %d\n", result);
149 result = mm_sound_remove_device_connected_callback(g_slots[slotid].subs_id);
150 if (result != MM_ERROR_NONE) {
151 debug_error("mm_sound_remove_device_connected_callback error %d\n", result);
161 int MMSoundMgrCodecInit(const char *targetdir)
168 memset (g_slots, 0, sizeof(g_slots));
170 if(pthread_mutex_init(&g_slot_mutex, NULL)) {
171 debug_error("pthread_mutex_init failed\n");
172 return MM_ERROR_SOUND_INTERNAL;
175 if(pthread_mutex_init(&codec_wave_mutex, NULL)) {
176 debug_error("pthread_mutex_init failed\n");
177 return MM_ERROR_SOUND_INTERNAL;
180 for (count = 0; count < MANAGER_HANDLE_MAX; count++) {
181 g_slots[count].status = STATUS_IDLE;
182 g_slots[count].plughandle = 0;
185 if (g_codec_plugins) {
186 debug_warning("Please Check Init twice\n");
187 MMSoundPluginRelease(g_codec_plugins);
190 MMSoundPluginScan(targetdir, MM_SOUND_PLUGIN_TYPE_CODEC, &g_codec_plugins);
191 if (g_codec_plugins) {
192 while (g_codec_plugins[loop].type != MM_SOUND_PLUGIN_TYPE_NONE) {
193 _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 || *slotid < 0) {
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 MMSOUND_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->enable_session) {
280 unsigned int subs_id = 0;
282 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);
284 debug_error("mm_sound_add_device_connected_callback failed [0x%x]", err);
285 pthread_mutex_unlock(&g_slot_mutex);
286 return MM_ERROR_POLICY_INTERNAL;
288 g_slots[*slotid].subs_id = subs_id;
290 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) {
291 debug_warning("session option is PAUSE_OTHERS -> acquire focus");
292 err = mm_sound_focus_get_id((int *)(¶m->focus_handle));
293 err = mm_sound_register_focus_for_session(param->focus_handle, (int)param->param, "media", sound_codec_focus_callback, (void*)*slotid);
295 debug_error("mm_sound_register_focus_for_session failed [0x%x]", err);
296 pthread_mutex_unlock(&g_slot_mutex);
297 return MM_ERROR_POLICY_INTERNAL;
299 err = mm_sound_acquire_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
301 debug_error("mm_sound_acquire_focus failed [0x%x]", err);
302 err = mm_sound_unregister_focus(param->focus_handle);
303 pthread_mutex_unlock(&g_slot_mutex);
304 return MM_ERROR_POLICY_INTERNAL;
306 g_slots[*slotid].current_focus_type = FOCUS_FOR_BOTH;
307 } else if (param->session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
309 debug_warning("session option is UNINTERRUPTIBLE, nothing to do with focus");
311 debug_warning("need to set focus watch callback");
312 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));
314 debug_error("mm_sound_set_focus_watch_callback_for_session failed [0x%x]", err);
315 pthread_mutex_unlock(&g_slot_mutex);
316 return MM_ERROR_POLICY_INTERNAL;
322 /* Codec id WAV or MP3 */
323 g_slots[*slotid].pluginid = count;
324 g_slots[*slotid].param = param->param; /* This arg is used callback data */
325 g_slots[*slotid].session_type = param->session_type;
326 g_slots[*slotid].session_options = param->session_options;
327 g_slots[*slotid].focus_handle = param->focus_handle;
328 g_slots[*slotid].focus_wcb_id = param->focus_wcb_id;
329 g_slots[*slotid].enable_session = true;
330 g_slots[*slotid].pid = (int)param->param;
333 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
335 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
336 debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
337 if (err != MM_ERROR_NONE) {
338 debug_error("Plugin create fail : 0x%08X\n", err);
339 g_slots[*slotid].status = STATUS_IDLE;
340 pthread_mutex_unlock(&g_slot_mutex);
341 debug_warning("After Slot_mutex UNLOCK\n");
342 if (param->focus_handle) {
343 need_focus_unregister = 1;
348 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
349 if (err != MM_ERROR_NONE) {
350 debug_error("Fail to play : 0x%08X\n", err);
351 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
352 if (param->focus_handle) {
353 need_focus_unregister = 1;
357 pthread_mutex_unlock(&g_slot_mutex);
359 debug_msg("After Slot_mutex UNLOCK\n");
363 if(param->session_type != MM_SESSION_TYPE_CALL &&
364 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
365 param->session_type != MM_SESSION_TYPE_VOIP &&
366 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
367 param->enable_session &&
368 need_focus_unregister == 1) {
370 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) {
371 err = mm_sound_release_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
372 if(mm_sound_unregister_focus(param->focus_handle) || err) {
373 debug_error("focus cleaning up failed[0x%x]", err);
374 return MM_ERROR_POLICY_INTERNAL;
376 } else if (~(param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
377 err = mm_sound_unset_focus_watch_callback(param->focus_wcb_id);
379 debug_error("focus watch cleaning up failed[0x%x]", err);
380 return MM_ERROR_POLICY_INTERNAL;
392 int MMSoundMgrCodecPlayWithStreamInfo(int *slotid, const mmsound_mgr_codec_param_t *param)
395 mmsound_codec_info_t info;
396 mmsound_codec_param_t codec_param;
397 int err = MM_ERROR_NONE;
403 for (count = 0; g_plugins[count].GetSupportTypes; count++) {
405 if (g_plugins[count].Parse(param->source, &info) == MM_ERROR_NONE)
409 /*The count num means codec type WAV, MP3 */
410 debug_msg("Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->repeat_count, param->volume, count);
412 if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
413 debug_error("unsupported file type %d\n", count);
414 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
418 err = _MMSoundMgrCodecGetEmptySlot(slotid);
419 if (err != MM_ERROR_NONE || *slotid < 0) {
420 debug_error("Empty g_slot is not found\n");
424 codec_param.volume_config = -1; //setting volume config to -1 since using stream info instead of volume type
425 codec_param.repeat_count = param->repeat_count;
426 codec_param.volume = param->volume;
427 codec_param.source = param->source;
428 codec_param.priority = param->priority;
429 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
430 codec_param.param = *slotid;
431 codec_param.pid = (int)param->param;
432 codec_param.handle_route = param->handle_route;
433 codec_param.codec_wave_mutex = &codec_wave_mutex;
434 codec_param.stream_index = param->stream_index;
435 MMSOUND_STRNCPY(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
436 pthread_mutex_lock(&g_slot_mutex);
438 debug_msg("After Slot_mutex LOCK\n");
441 /* Codec id WAV or MP3 */
442 g_slots[*slotid].pluginid = count;
443 g_slots[*slotid].param = param->param; /* This arg is used callback data */
445 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
447 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
448 debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
449 if (err != MM_ERROR_NONE) {
450 debug_error("Plugin create fail : 0x%08X\n", err);
451 g_slots[*slotid].status = STATUS_IDLE;
452 pthread_mutex_unlock(&g_slot_mutex);
453 debug_warning("After Slot_mutex UNLOCK\n");
457 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
458 if (err != MM_ERROR_NONE) {
459 debug_error("Fail to play : 0x%08X\n", err);
460 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
463 pthread_mutex_unlock(&g_slot_mutex);
465 debug_msg("After Slot_mutex UNLOCK\n");
478 #define DTMF_PLUGIN_COUNT 2
479 int MMSoundMgrCodecPlayDtmf(int *slotid, const mmsound_mgr_codec_param_t *param)
483 mmsound_codec_info_t info;
484 mmsound_codec_param_t codec_param;
485 int err = MM_ERROR_NONE;
486 int need_focus_unregister = 0;
492 for (count = 0; g_plugins[count].GetSupportTypes; count++) {
494 codec_type = g_plugins[count].GetSupportTypes();
495 if(codec_type && (MM_SOUND_SUPPORTED_CODEC_DTMF == codec_type[0]))
499 /*The count num means codec type DTMF */
500 debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, count);
502 if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
503 debug_error("unsupported file type %d\n", count);
504 printf("unsupported file type %d\n", count);
505 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
510 debug_msg("Get New handle\n");
513 err = _MMSoundMgrCodecGetEmptySlot(slotid);
514 if(err != MM_ERROR_NONE || *slotid < 0)
516 debug_error("Empty g_slot is not found\n");
520 codec_param.tone = param->tone;
521 codec_param.priority = 0;
522 codec_param.volume_config = param->volume_config;
523 codec_param.repeat_count = param->repeat_count;
524 codec_param.volume = param->volume;
525 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
526 codec_param.param = *slotid;
527 codec_param.pid = (int)param->param;
528 codec_param.stream_index = param->stream_index;
529 MMSOUND_STRNCPY(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
531 pthread_mutex_lock(&g_slot_mutex);
533 debug_msg("After Slot_mutex LOCK\n");
538 * Register FOCUS here
541 if (param->session_type != MM_SESSION_TYPE_CALL &&
542 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
543 param->session_type != MM_SESSION_TYPE_VOIP &&
544 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
545 param->enable_session) {
547 unsigned int subs_id = 0;
549 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);
551 debug_error("mm_sound_add_device_connected_callback failed [0x%x]", err);
552 pthread_mutex_unlock(&g_slot_mutex);
553 return MM_ERROR_POLICY_INTERNAL;
555 g_slots[*slotid].subs_id = subs_id;
557 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) {
558 debug_warning("session option is PAUSE_OTHERS -> acquire focus");
559 err = mm_sound_focus_get_id((int *)(¶m->focus_handle));
560 err = mm_sound_register_focus_for_session(param->focus_handle, (int)param->param, "media", sound_codec_focus_callback, (void*)*slotid);
562 debug_error("mm_sound_register_focus failed [0x%x]", err);
563 pthread_mutex_unlock(&g_slot_mutex);
564 return MM_ERROR_POLICY_INTERNAL;
566 err = mm_sound_acquire_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
568 debug_error("mm_sound_acquire_focus failed [0x%x]", err);
569 err = mm_sound_unregister_focus(param->focus_handle);
570 pthread_mutex_unlock(&g_slot_mutex);
571 return MM_ERROR_POLICY_INTERNAL;
573 g_slots[*slotid].current_focus_type = FOCUS_FOR_BOTH;
574 } else if (param->session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
576 debug_warning("session option is UNINTERRUPTIBLE, nothing to do with focus");
578 debug_warning("need to set focus watch callback");
579 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));
581 debug_error("mm_sound_set_focus_watch_callback failed [0x%x]", err);
582 pthread_mutex_unlock(&g_slot_mutex);
583 return MM_ERROR_POLICY_INTERNAL;
588 g_slots[*slotid].pluginid = count;
589 g_slots[*slotid].param = param->param; /* This arg is used callback data */
590 g_slots[*slotid].session_type = param->session_type;
591 g_slots[*slotid].session_options = param->session_options;
592 g_slots[*slotid].focus_handle= param->focus_handle;
593 g_slots[*slotid].focus_wcb_id= param->focus_wcb_id;
594 g_slots[*slotid].enable_session = param->enable_session;
595 g_slots[*slotid].pid = (int)param->param;
598 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
601 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
602 debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
603 if (err != MM_ERROR_NONE) {
604 debug_error("Plugin create fail : 0x%08X\n", err);
605 g_slots[*slotid].status = STATUS_IDLE;
606 pthread_mutex_unlock(&g_slot_mutex);
607 debug_warning("After Slot_mutex UNLOCK\n");
608 need_focus_unregister = 1;
612 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
613 if (err != MM_ERROR_NONE) {
614 debug_error("Fail to play : 0x%08X\n", err);
615 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
616 need_focus_unregister = 1;
619 pthread_mutex_unlock(&g_slot_mutex);
621 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
623 debug_msg("After Slot_mutex UNLOCK\n")
627 if (param->session_type != MM_SESSION_TYPE_CALL &&
628 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
629 param->session_type != MM_SESSION_TYPE_VOIP &&
630 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
631 param->enable_session &&
632 need_focus_unregister == 1) {
634 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) {
635 err = mm_sound_release_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
636 if(mm_sound_unregister_focus(param->focus_handle) || err) {
637 debug_error("focus cleaning up failed[0x%x]", err);
638 return MM_ERROR_POLICY_INTERNAL;
640 } else if (~(param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
641 err = mm_sound_unset_focus_watch_callback(param->focus_wcb_id);
643 debug_error("focus watch cleaning up failed[0x%x]", err);
644 return MM_ERROR_POLICY_INTERNAL;
656 int MMSoundMgrCodecPlayDtmfWithStreamInfo(int *slotid, const mmsound_mgr_codec_param_t *param)
660 mmsound_codec_info_t info;
661 mmsound_codec_param_t codec_param;
662 int err = MM_ERROR_NONE;
668 for (count = 0; g_plugins[count].GetSupportTypes; count++) {
670 codec_type = g_plugins[count].GetSupportTypes();
671 if(codec_type && (MM_SOUND_SUPPORTED_CODEC_DTMF == codec_type[0]))
675 /*The count num means codec type DTMF */
676 debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, count);
678 if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
679 debug_error("unsupported file type %d\n", count);
680 printf("unsupported file type %d\n", count);
681 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
686 debug_msg("Get New handle\n");
689 err = _MMSoundMgrCodecGetEmptySlot(slotid);
690 if(err != MM_ERROR_NONE || *slotid < 0)
692 debug_error("Empty g_slot is not found\n");
696 codec_param.tone = param->tone;
697 codec_param.priority = 0;
698 codec_param.repeat_count = param->repeat_count;
699 codec_param.volume = param->volume;
700 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
701 codec_param.param = *slotid;
702 codec_param.pid = (int)param->param;
703 codec_param.volume_config = -1; //setting volume config to -1 since using stream info instead of volume type
704 codec_param.stream_index = param->stream_index;
705 MMSOUND_STRNCPY(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
707 pthread_mutex_lock(&g_slot_mutex);
709 debug_msg("After Slot_mutex LOCK\n");
711 g_slots[*slotid].pluginid = count;
712 g_slots[*slotid].param = param->param; /* This arg is used callback data */
713 g_slots[*slotid].enable_session = param->enable_session;
716 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
719 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
720 debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
721 if (err != MM_ERROR_NONE) {
722 debug_error("Plugin create fail : 0x%08X\n", err);
723 g_slots[*slotid].status = STATUS_IDLE;
724 pthread_mutex_unlock(&g_slot_mutex);
725 debug_warning("After Slot_mutex UNLOCK\n");
729 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
730 if (err != MM_ERROR_NONE) {
731 debug_error("Fail to play : 0x%08X\n", err);
732 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
735 pthread_mutex_unlock(&g_slot_mutex);
737 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
739 debug_msg("After Slot_mutex UNLOCK\n");
751 int MMSoundMgrCodecStop(const int slotid)
753 int err = MM_ERROR_NONE;
755 debug_enter("(Slotid : [%d])\n", slotid);
757 if (slotid < 0 || MANAGER_HANDLE_MAX <= slotid) {
758 return MM_ERROR_INVALID_ARGUMENT;
761 pthread_mutex_lock (&g_slot_mutex);
763 debug_msg("After Slot_mutex LOCK\n");
765 if (g_slots[slotid].status == STATUS_IDLE) {
766 err = MM_ERROR_SOUND_INVALID_STATE;
767 debug_warning("The playing slots is not found, Slot ID : [%d]\n", slotid);
771 debug_msg("Found slot, Slotid [%d] State [%d]\n", slotid, g_slots[slotid].status);
774 err = g_plugins[g_slots[slotid].pluginid].Stop(g_slots[slotid].plughandle);
775 if (err != MM_ERROR_NONE) {
776 debug_error("Fail to STOP Code : 0x%08X\n", err);
778 debug_msg("Found slot, Slotid [%d] State [%d]\n", slotid, g_slots[slotid].status);
780 pthread_mutex_unlock(&g_slot_mutex);
782 debug_msg("After Slot_mutex UNLOCK\n");
784 debug_leave("(err : 0x%08X)\n", err);
789 int MMSoundMgrCodecClearFocus(int pid)
791 int err = MM_ERROR_NONE;
794 debug_enter("(pid : [%d])\n", pid);
796 pthread_mutex_lock (&g_slot_mutex);
798 for (slotid = 0 ; slotid < MANAGER_HANDLE_MAX ; slotid++) {
799 if (g_slots[slotid].pid == pid) {
800 if (g_slots[slotid].focus_handle || g_slots[slotid].focus_wcb_id) {
801 if(g_slots[slotid].session_type != MM_SESSION_TYPE_CALL &&
802 g_slots[slotid].session_type != MM_SESSION_TYPE_VIDEOCALL &&
803 g_slots[slotid].session_type != MM_SESSION_TYPE_VOIP &&
804 g_slots[slotid].session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
805 g_slots[slotid].enable_session ) {
806 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) {
807 err = mm_sound_release_focus(g_slots[slotid].focus_handle, FOCUS_FOR_BOTH, NULL);
809 debug_error("mm_sound_release_focus failed [0x%x]", err);
811 if(mm_sound_unregister_focus(g_slots[slotid].focus_handle) || err) {
812 debug_error("Focus clean up failed [0x%x]", err);
813 err = MM_ERROR_POLICY_INTERNAL;
816 } else if (~(g_slots[slotid].session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
817 err = mm_sound_unset_focus_watch_callback(g_slots[slotid].focus_wcb_id);
819 debug_error("mm_sound_unset_focus_watch_callback failed [0x%x]", err);
820 err = MM_ERROR_POLICY_INTERNAL;
825 if(mm_sound_remove_device_connected_callback(g_slots[slotid].subs_id) != MM_ERROR_NONE)
826 debug_error("mm_sound_remove_device_connected_callback() failed");
827 g_slots[slotid].focus_handle = 0;
828 g_slots[slotid].focus_wcb_id = 0;
829 g_slots[slotid].subs_id = 0;
835 pthread_mutex_unlock(&g_slot_mutex);
836 debug_leave("(err : 0x%08X)\n", err);
842 static int _MMSoundMgrCodecStopCallback(int param)
844 int err = MM_ERROR_NONE;
846 debug_enter("(Slot : %d)\n", param);
848 if (param < 0 || param >= MANAGER_HANDLE_MAX) {
849 debug_error ("Slot index param [%d] is invalid", param);
850 return MM_ERROR_INVALID_ARGUMENT;
853 pthread_mutex_lock(&g_slot_mutex);
854 debug_msg("[CODEC MGR] Slot_mutex lock done\n");
857 * Unregister FOCUS here
859 debug_msg("[CODEC MGR] enable_session %d ",g_slots[param].enable_session);
861 if (g_slots[param].focus_handle || g_slots[param].focus_wcb_id) {
862 if(g_slots[param].session_type != MM_SESSION_TYPE_CALL &&
863 g_slots[param].session_type != MM_SESSION_TYPE_VIDEOCALL &&
864 g_slots[param].session_type != MM_SESSION_TYPE_VOIP &&
865 g_slots[param].session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
866 g_slots[param].enable_session ) {
867 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) {
868 if(g_slots[param].current_focus_type != FOCUS_NONE) {
869 err = mm_sound_release_focus(g_slots[param].focus_handle, g_slots[param].current_focus_type, NULL);
871 debug_error("mm_sound_release_focus failed [0x%x]", err);
874 if(mm_sound_unregister_focus(g_slots[param].focus_handle) || err) {
875 debug_error("Focus clean up failed [0x%x]", err);
876 pthread_mutex_unlock(&g_slot_mutex);
877 return MM_ERROR_POLICY_INTERNAL;
879 } else if (~(g_slots[param].session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
880 err = mm_sound_unset_focus_watch_callback(g_slots[param].focus_wcb_id);
882 debug_error("mm_sound_unset_focus_watch_callback failed [0x%x]", err);
883 pthread_mutex_unlock(&g_slot_mutex);
884 return MM_ERROR_POLICY_INTERNAL;
888 if(mm_sound_remove_device_connected_callback(g_slots[param].subs_id) != MM_ERROR_NONE)
889 debug_error("mm_sound_remove_device_connected_callback() failed");
892 __mm_sound_mgr_ipc_notify_play_file_end(param);
894 debug_msg("Client callback msg_type (instance) : [%d]\n", (int)g_slots[param].param);
895 debug_msg("Handle allocated handle : [0x%08X]\n", g_slots[param].plughandle);
896 err = g_plugins[g_slots[param].pluginid].Destroy(g_slots[param].plughandle);
898 debug_critical("[CODEC MGR] Fail to destroy slot number : [%d] err [0x%x]\n", param, err);
900 memset(&g_slots[param], 0, sizeof(__mmsound_mgr_codec_handle_t));
901 g_slots[param].status = STATUS_IDLE;
902 pthread_mutex_unlock(&g_slot_mutex);
903 debug_msg("[CODEC MGR] Slot_mutex done\n");
908 static int _MMSoundMgrCodecGetEmptySlot(int *slot)
911 int err = MM_ERROR_NONE;
916 debug_msg("Codec slot ID : [%d]\n", *slot);
917 pthread_mutex_lock(&g_slot_mutex);
919 debug_msg("After Slot_mutex LOCK\n");
922 for (count = SOUND_SLOT_START; count < MANAGER_HANDLE_MAX ; count++) {
923 if (g_slots[count].status == STATUS_IDLE) {
924 g_slots[count].status = STATUS_SOUND;
928 pthread_mutex_unlock(&g_slot_mutex);
930 debug_msg("After Slot_mutex UNLOCK\n");
933 if (count < MANAGER_HANDLE_MAX) {
934 debug_msg("New handle allocated (codec slot ID : [%d])\n", count);
938 debug_warning("Handle is full handle : [%d]\n", count);
940 /* Temporal code for reset */
942 g_slots[count].status = STATUS_IDLE;
944 err = MM_ERROR_SOUND_INTERNAL;
954 static int _MMSoundMgrCodecRegisterInterface(MMSoundPluginType *plugin)
956 int err = MM_ERROR_NONE;
958 void *getinterface = NULL;
964 /* find emptry slot */
965 for (count = 0; count < MM_SOUND_SUPPORTED_CODEC_NUM; count++) {
966 if (g_plugins[count].GetSupportTypes == NULL)
970 if (count == MM_SOUND_SUPPORTED_CODEC_NUM) {
971 debug_critical("The plugin support type is not valid\n");
972 return MM_ERROR_COMMON_OUT_OF_RANGE;
975 err = MMSoundPluginGetSymbol(plugin, CODEC_GET_INTERFACE_FUNC_NAME, &getinterface);
976 if (err != MM_ERROR_NONE) {
977 debug_error("Get Symbol CODEC_GET_INTERFACE_FUNC_NAME is fail : %x\n", err);
980 debug_msg("interface[%p] empty_slot[%d]\n", getinterface, count);
982 err = MMSoundPlugCodecCastGetInterface(getinterface)(&g_plugins[count]);
983 if (err != MM_ERROR_NONE) {
984 debug_error("Get interface fail : %x\n", err);
987 /* If error occur, clean interface */
988 memset(&g_plugins[count], 0, sizeof(mmsound_codec_interface_t));
990 if (g_plugins[count].SetThreadPool)
991 g_plugins[count].SetThreadPool(MMSoundThreadPoolRun);