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"
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;
60 mm_sound_focus_type_e current_focus_type;
63 } __mmsound_mgr_codec_handle_t;
65 static MMSoundPluginType *g_codec_plugins = NULL;
66 static __mmsound_mgr_codec_handle_t g_slots[MANAGER_HANDLE_MAX];
67 static mmsound_codec_interface_t g_plugins[MM_SOUND_SUPPORTED_CODEC_NUM];
68 static pthread_mutex_t g_slot_mutex;
69 static pthread_mutex_t codec_wave_mutex;
70 static int _MMSoundMgrCodecStopCallback(int param);
71 static int _MMSoundMgrCodecGetEmptySlot(int *slotid);
72 static int _MMSoundMgrCodecRegisterInterface(MMSoundPluginType *plugin);
75 #define STATUS_SOUND 3
77 #define SOUND_SLOT_START 0
79 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)
82 int slotid = (int)user_data;
83 int result = MM_ERROR_NONE;
85 debug_warning ("focus callback called -> focus_stae(%d), reasoun_for_change(%s)", focus_state, reason_for_change ? reason_for_change : "N/A");
87 if(g_slots[slotid].session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE){
88 debug_warning ("session option is UNINTERRUPTIBLE, nothing to do with focus");
91 if (focus_state == FOCUS_IS_RELEASED) {
92 g_slots[slotid].current_focus_type = FOCUS_FOR_BOTH&(~focus_type);
93 debug_warning ("focus is released -> stop playing");
94 result = MMSoundMgrCodecStop(slotid);
95 if (result != MM_ERROR_NONE) {
96 debug_log("result error %d\n", result);
103 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)
105 int slotid = (int)user_data;
106 int result = MM_ERROR_NONE;
108 debug_warning ("focus callback called -> focus_stae(%d), reasoun_for_change(%s)", focus_state, reason_for_change ? reason_for_change : "N/A");
110 if(g_slots[slotid].session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE){
111 debug_warning ("session option is UNINTERRUPTIBLE, nothing to do with focus");
114 if (focus_state == FOCUS_IS_ACQUIRED) {
115 debug_warning ("focus is released -> stop playing");
116 result = MMSoundMgrCodecStop(slotid);
117 if (result != MM_ERROR_NONE) {
118 debug_log("result error %d\n", result);
125 int MMSoundMgrCodecInit(const char *targetdir)
132 memset (g_slots, 0, sizeof(g_slots));
134 if(pthread_mutex_init(&g_slot_mutex, NULL)) {
135 debug_error("pthread_mutex_init failed\n");
136 return MM_ERROR_SOUND_INTERNAL;
139 if(pthread_mutex_init(&codec_wave_mutex, NULL)) {
140 debug_error("pthread_mutex_init failed\n");
141 return MM_ERROR_SOUND_INTERNAL;
144 for (count = 0; count < MANAGER_HANDLE_MAX; count++) {
145 g_slots[count].status = STATUS_IDLE;
146 g_slots[count].plughandle = 0;
149 if (g_codec_plugins) {
150 debug_warning("Please Check Init twice\n");
151 MMSoundPluginRelease(g_codec_plugins);
154 MMSoundPluginScan(targetdir, MM_SOUND_PLUGIN_TYPE_CODEC, &g_codec_plugins);
156 while (g_codec_plugins[loop].type != MM_SOUND_PLUGIN_TYPE_NONE) {
157 _MMSoundMgrCodecRegisterInterface(&g_codec_plugins[loop++]);
161 return MM_ERROR_NONE;
164 int MMSoundMgrCodecFini(void)
168 memset(g_plugins, 0, sizeof(mmsound_codec_interface_t) * MM_SOUND_SUPPORTED_CODEC_NUM);
169 MMSoundPluginRelease(g_codec_plugins);
170 g_codec_plugins = NULL;
171 pthread_mutex_destroy(&g_slot_mutex);
172 pthread_mutex_destroy(&codec_wave_mutex);
174 return MM_ERROR_NONE;
178 int MMSoundMgrCodecPlay(int *slotid, const mmsound_mgr_codec_param_t *param)
181 mmsound_codec_info_t info;
182 mmsound_codec_param_t codec_param;
183 int err = MM_ERROR_NONE;
184 int need_focus_unregister = 0;
190 for (count = 0; g_plugins[count].GetSupportTypes; count++) {
192 if (g_plugins[count].Parse(param->source, &info) == MM_ERROR_NONE)
196 /*The count num means codec type WAV, MP3 */
197 debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, count);
199 if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
200 debug_error("unsupported file type %d\n", count);
201 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
206 debug_msg("Get New handle\n");
209 err = _MMSoundMgrCodecGetEmptySlot(slotid);
210 if (err != MM_ERROR_NONE) {
211 debug_error("Empty g_slot is not found\n");
215 codec_param.tone = param->tone;
216 codec_param.volume_config = param->volume_config;
217 codec_param.repeat_count = param->repeat_count;
218 codec_param.volume = param->volume;
219 codec_param.source = param->source;
220 codec_param.priority = param->priority;
221 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
222 codec_param.param = *slotid;
223 codec_param.pid = (int)param->param;
224 codec_param.handle_route = param->handle_route;
225 codec_param.codec_wave_mutex = &codec_wave_mutex;
226 codec_param.stream_index = param->stream_index;
227 strncpy(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
228 pthread_mutex_lock(&g_slot_mutex);
230 debug_msg("After Slot_mutex LOCK\n");
234 * Register FOCUS here
237 if (param->session_type != MM_SESSION_TYPE_CALL &&
238 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
239 param->session_type != MM_SESSION_TYPE_VOIP &&
240 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
241 param->priority != HANDLE_PRIORITY_SOLO &&
242 param->enable_session) {
244 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) {
245 debug_warning("session option is PAUSE_OTHERS -> acquire focus");
246 err = mm_sound_focus_get_id((int *)(¶m->focus_handle));
247 err = mm_sound_register_focus_for_session(param->focus_handle, (int)param->param, "media", sound_codec_focus_callback, (void*)*slotid);
249 debug_error("mm_sound_register_focus_for_session failed [0x%x]", err);
250 pthread_mutex_unlock(&g_slot_mutex);
251 return MM_ERROR_POLICY_INTERNAL;
253 err = mm_sound_acquire_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
255 debug_error("mm_sound_acquire_focus failed [0x%x]", err);
256 err = mm_sound_unregister_focus(param->focus_handle);
257 pthread_mutex_unlock(&g_slot_mutex);
258 return MM_ERROR_POLICY_INTERNAL;
260 g_slots[*slotid].current_focus_type = FOCUS_FOR_BOTH;
261 } else if (param->session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
263 debug_warning("session option is UNINTERRUPTIBLE, nothing to do with focus");
265 debug_warning("need to set focus watch callback");
266 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));
268 debug_error("mm_sound_set_focus_watch_callback_for_session failed [0x%x]", err);
269 err = mm_sound_unregister_focus(param->focus_handle);
270 pthread_mutex_unlock(&g_slot_mutex);
271 return MM_ERROR_POLICY_INTERNAL;
277 /* Codec id WAV or MP3 */
278 g_slots[*slotid].pluginid = count;
279 g_slots[*slotid].param = param->param; /* This arg is used callback data */
280 g_slots[*slotid].session_type = param->session_type;
281 g_slots[*slotid].session_options = param->session_options;
282 g_slots[*slotid].focus_handle = param->focus_handle;
283 g_slots[*slotid].focus_wcb_id = param->focus_wcb_id;
284 g_slots[*slotid].enable_session = true;
285 g_slots[*slotid].pid = (int)param->param;
287 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
289 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
290 debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
291 if (err != MM_ERROR_NONE) {
292 debug_error("Plugin create fail : 0x%08X\n", err);
293 g_slots[*slotid].status = STATUS_IDLE;
294 pthread_mutex_unlock(&g_slot_mutex);
295 debug_warning("After Slot_mutex UNLOCK\n");
296 if (param->focus_handle) {
297 need_focus_unregister = 1;
302 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
303 if (err != MM_ERROR_NONE) {
304 debug_error("Fail to play : 0x%08X\n", err);
305 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
306 if (param->focus_handle) {
307 need_focus_unregister = 1;
311 pthread_mutex_unlock(&g_slot_mutex);
313 debug_msg("After Slot_mutex UNLOCK\n");
317 if(param->session_type != MM_SESSION_TYPE_CALL &&
318 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
319 param->session_type != MM_SESSION_TYPE_VOIP &&
320 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
321 param->enable_session &&
322 need_focus_unregister == 1) {
324 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) {
325 err = mm_sound_release_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
326 if(mm_sound_unregister_focus(param->focus_handle) || err) {
327 debug_error("focus cleaning up failed[0x%x]", err);
328 return MM_ERROR_POLICY_INTERNAL;
330 } else if (~(param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
331 err = mm_sound_unset_focus_watch_callback(param->focus_wcb_id);
333 debug_error("focus watch cleaning up failed[0x%x]", err);
334 return MM_ERROR_POLICY_INTERNAL;
346 int MMSoundMgrCodecPlayWithStreamInfo(int *slotid, const mmsound_mgr_codec_param_t *param)
349 mmsound_codec_info_t info;
350 mmsound_codec_param_t codec_param;
351 int err = MM_ERROR_NONE;
357 for (count = 0; g_plugins[count].GetSupportTypes; count++) {
359 if (g_plugins[count].Parse(param->source, &info) == MM_ERROR_NONE)
363 /*The count num means codec type WAV, MP3 */
364 debug_msg("Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->repeat_count, param->volume, count);
366 if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
367 debug_error("unsupported file type %d\n", count);
368 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
372 err = _MMSoundMgrCodecGetEmptySlot(slotid);
373 if (err != MM_ERROR_NONE) {
374 debug_error("Empty g_slot is not found\n");
378 codec_param.volume_config = -1; //setting volume config to -1 since using stream info instead of volume type
379 codec_param.repeat_count = param->repeat_count;
380 codec_param.volume = param->volume;
381 codec_param.source = param->source;
382 codec_param.priority = param->priority;
383 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
384 codec_param.param = *slotid;
385 codec_param.pid = (int)param->param;
386 codec_param.handle_route = param->handle_route;
387 codec_param.codec_wave_mutex = &codec_wave_mutex;
388 codec_param.stream_index = param->stream_index;
389 strncpy(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
390 pthread_mutex_lock(&g_slot_mutex);
392 debug_msg("After Slot_mutex LOCK\n");
395 /* Codec id WAV or MP3 */
396 g_slots[*slotid].pluginid = count;
397 g_slots[*slotid].param = param->param; /* This arg is used callback data */
399 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
401 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
402 debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
403 if (err != MM_ERROR_NONE) {
404 debug_error("Plugin create fail : 0x%08X\n", err);
405 g_slots[*slotid].status = STATUS_IDLE;
406 pthread_mutex_unlock(&g_slot_mutex);
407 debug_warning("After Slot_mutex UNLOCK\n");
411 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
412 if (err != MM_ERROR_NONE) {
413 debug_error("Fail to play : 0x%08X\n", err);
414 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
417 pthread_mutex_unlock(&g_slot_mutex);
419 debug_msg("After Slot_mutex UNLOCK\n");
432 #define DTMF_PLUGIN_COUNT 2
433 int MMSoundMgrCodecPlayDtmf(int *slotid, const mmsound_mgr_codec_param_t *param)
437 mmsound_codec_info_t info;
438 mmsound_codec_param_t codec_param;
439 int err = MM_ERROR_NONE;
440 int need_focus_unregister = 0;
446 for (count = 0; g_plugins[count].GetSupportTypes; count++) {
448 codec_type = g_plugins[count].GetSupportTypes();
449 if(codec_type && (MM_SOUND_SUPPORTED_CODEC_DTMF == codec_type[0]))
453 /*The count num means codec type DTMF */
454 debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, count);
456 if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
457 debug_error("unsupported file type %d\n", count);
458 printf("unsupported file type %d\n", count);
459 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
464 debug_msg("Get New handle\n");
467 err = _MMSoundMgrCodecGetEmptySlot(slotid);
468 if(err != MM_ERROR_NONE)
470 debug_error("Empty g_slot is not found\n");
474 codec_param.tone = param->tone;
475 codec_param.priority = 0;
476 codec_param.volume_config = param->volume_config;
477 codec_param.repeat_count = param->repeat_count;
478 codec_param.volume = param->volume;
479 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
480 codec_param.param = *slotid;
481 codec_param.pid = (int)param->param;
482 codec_param.stream_index = param->stream_index;
483 strncpy(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
485 pthread_mutex_lock(&g_slot_mutex);
487 debug_msg("After Slot_mutex LOCK\n");
492 * Register FOCUS here
495 if (param->session_type != MM_SESSION_TYPE_CALL &&
496 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
497 param->session_type != MM_SESSION_TYPE_VOIP &&
498 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
499 param->enable_session) {
501 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) {
502 debug_warning("session option is PAUSE_OTHERS -> acquire focus");
503 err = mm_sound_focus_get_id((int *)(¶m->focus_handle));
504 err = mm_sound_register_focus_for_session(param->focus_handle, (int)param->param, "media", sound_codec_focus_callback, (void*)*slotid);
506 debug_error("mm_sound_register_focus failed [0x%x]", err);
507 pthread_mutex_unlock(&g_slot_mutex);
508 return MM_ERROR_POLICY_INTERNAL;
510 err = mm_sound_acquire_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
512 debug_error("mm_sound_acquire_focus failed [0x%x]", err);
513 err = mm_sound_unregister_focus(param->focus_handle);
514 pthread_mutex_unlock(&g_slot_mutex);
515 return MM_ERROR_POLICY_INTERNAL;
517 g_slots[*slotid].current_focus_type = FOCUS_FOR_BOTH;
518 } else if (param->session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
520 debug_warning("session option is UNINTERRUPTIBLE, nothing to do with focus");
522 debug_warning("need to set focus watch callback");
523 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));
525 debug_error("mm_sound_set_focus_watch_callback failed [0x%x]", err);
526 err = mm_sound_unregister_focus(param->focus_handle);
527 pthread_mutex_unlock(&g_slot_mutex);
528 return MM_ERROR_POLICY_INTERNAL;
533 g_slots[*slotid].pluginid = count;
534 g_slots[*slotid].param = param->param; /* This arg is used callback data */
535 g_slots[*slotid].session_type = param->session_type;
536 g_slots[*slotid].session_options = param->session_options;
537 g_slots[*slotid].focus_handle= param->focus_handle;
538 g_slots[*slotid].focus_wcb_id= param->focus_wcb_id;
539 g_slots[*slotid].enable_session = param->enable_session;
540 g_slots[*slotid].pid = (int)param->param;
543 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
546 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
547 debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
548 if (err != MM_ERROR_NONE) {
549 debug_error("Plugin create fail : 0x%08X\n", err);
550 g_slots[*slotid].status = STATUS_IDLE;
551 pthread_mutex_unlock(&g_slot_mutex);
552 debug_warning("After Slot_mutex UNLOCK\n");
553 need_focus_unregister = 1;
557 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
558 if (err != MM_ERROR_NONE) {
559 debug_error("Fail to play : 0x%08X\n", err);
560 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
561 need_focus_unregister = 1;
564 pthread_mutex_unlock(&g_slot_mutex);
566 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
568 debug_msg("After Slot_mutex UNLOCK\n")
572 if (param->session_type != MM_SESSION_TYPE_CALL &&
573 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
574 param->session_type != MM_SESSION_TYPE_VOIP &&
575 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
576 param->enable_session &&
577 need_focus_unregister == 1) {
579 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) {
580 err = mm_sound_release_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
581 if(mm_sound_unregister_focus(param->focus_handle) || err) {
582 debug_error("focus cleaning up failed[0x%x]", err);
583 return MM_ERROR_POLICY_INTERNAL;
585 } else if (~(param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
586 err = mm_sound_unset_focus_watch_callback(param->focus_wcb_id);
588 debug_error("focus watch cleaning up failed[0x%x]", err);
589 return MM_ERROR_POLICY_INTERNAL;
601 int MMSoundMgrCodecPlayDtmfWithStreamInfo(int *slotid, const mmsound_mgr_codec_param_t *param)
605 mmsound_codec_info_t info;
606 mmsound_codec_param_t codec_param;
607 int err = MM_ERROR_NONE;
613 for (count = 0; g_plugins[count].GetSupportTypes; count++) {
615 codec_type = g_plugins[count].GetSupportTypes();
616 if(codec_type && (MM_SOUND_SUPPORTED_CODEC_DTMF == codec_type[0]))
620 /*The count num means codec type DTMF */
621 debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, count);
623 if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
624 debug_error("unsupported file type %d\n", count);
625 printf("unsupported file type %d\n", count);
626 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
631 debug_msg("Get New handle\n");
634 err = _MMSoundMgrCodecGetEmptySlot(slotid);
635 if(err != MM_ERROR_NONE)
637 debug_error("Empty g_slot is not found\n");
641 codec_param.tone = param->tone;
642 codec_param.priority = 0;
643 codec_param.repeat_count = param->repeat_count;
644 codec_param.volume = param->volume;
645 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
646 codec_param.param = *slotid;
647 codec_param.pid = (int)param->param;
648 codec_param.volume_config = -1; //setting volume config to -1 since using stream info instead of volume type
649 codec_param.stream_index = param->stream_index;
650 strncpy(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
652 pthread_mutex_lock(&g_slot_mutex);
654 debug_msg("After Slot_mutex LOCK\n");
656 g_slots[*slotid].pluginid = count;
657 g_slots[*slotid].param = param->param; /* This arg is used callback data */
658 g_slots[*slotid].enable_session = param->enable_session;
661 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
664 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
665 debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
666 if (err != MM_ERROR_NONE) {
667 debug_error("Plugin create fail : 0x%08X\n", err);
668 g_slots[*slotid].status = STATUS_IDLE;
669 pthread_mutex_unlock(&g_slot_mutex);
670 debug_warning("After Slot_mutex UNLOCK\n");
674 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
675 if (err != MM_ERROR_NONE) {
676 debug_error("Fail to play : 0x%08X\n", err);
677 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
680 pthread_mutex_unlock(&g_slot_mutex);
682 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
684 debug_msg("After Slot_mutex UNLOCK\n");
696 int MMSoundMgrCodecStop(const int slotid)
698 int err = MM_ERROR_NONE;
700 debug_enter("(Slotid : [%d])\n", slotid);
702 if (slotid < 0 || MANAGER_HANDLE_MAX <= slotid) {
703 return MM_ERROR_INVALID_ARGUMENT;
706 pthread_mutex_lock (&g_slot_mutex);
708 debug_msg("After Slot_mutex LOCK\n");
710 if (g_slots[slotid].status == STATUS_IDLE) {
711 err = MM_ERROR_SOUND_INVALID_STATE;
712 debug_warning("The playing slots is not found, Slot ID : [%d]\n", slotid);
716 debug_msg("Found slot, Slotid [%d] State [%d]\n", slotid, g_slots[slotid].status);
719 err = g_plugins[g_slots[slotid].pluginid].Stop(g_slots[slotid].plughandle);
720 if (err != MM_ERROR_NONE) {
721 debug_error("Fail to STOP Code : 0x%08X\n", err);
723 debug_msg("Found slot, Slotid [%d] State [%d]\n", slotid, g_slots[slotid].status);
725 pthread_mutex_unlock(&g_slot_mutex);
727 debug_msg("After Slot_mutex UNLOCK\n");
729 debug_leave("(err : 0x%08X)\n", err);
734 int MMSoundMgrCodecClearFocus(int pid)
736 int err = MM_ERROR_NONE;
739 debug_enter("(pid : [%d])\n", pid);
741 pthread_mutex_lock (&g_slot_mutex);
743 for (slotid = 0 ; slotid < MANAGER_HANDLE_MAX ; slotid++) {
744 if (g_slots[slotid].pid == pid) {
745 if (g_slots[slotid].focus_handle || g_slots[slotid].focus_wcb_id) {
746 if(g_slots[slotid].session_type != MM_SESSION_TYPE_CALL &&
747 g_slots[slotid].session_type != MM_SESSION_TYPE_VIDEOCALL &&
748 g_slots[slotid].session_type != MM_SESSION_TYPE_VOIP &&
749 g_slots[slotid].session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
750 g_slots[slotid].enable_session ) {
751 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) {
752 err = mm_sound_release_focus(g_slots[slotid].focus_handle, FOCUS_FOR_BOTH, NULL);
754 debug_error("mm_sound_release_focus failed [0x%x]", err);
756 if(mm_sound_unregister_focus(g_slots[slotid].focus_handle) || err) {
757 debug_error("Focus clean up failed [0x%x]", err);
758 err = MM_ERROR_POLICY_INTERNAL;
761 } else if (~(g_slots[slotid].session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
762 err = mm_sound_unset_focus_watch_callback(g_slots[slotid].focus_wcb_id);
764 debug_error("mm_sound_unset_focus_watch_callback failed [0x%x]", err);
765 err = MM_ERROR_POLICY_INTERNAL;
770 g_slots[slotid].focus_handle = 0;
771 g_slots[slotid].focus_wcb_id = 0;
777 pthread_mutex_unlock(&g_slot_mutex);
778 debug_leave("(err : 0x%08X)\n", err);
784 static int _MMSoundMgrCodecStopCallback(int param)
786 int err = MM_ERROR_NONE;
788 debug_enter("(Slot : %d)\n", param);
790 pthread_mutex_lock(&g_slot_mutex);
791 debug_msg("[CODEC MGR] Slot_mutex lock done\n");
795 * Unregister FOCUS here
797 debug_msg("[CODEC MGR] enable_session %d ",g_slots[param].enable_session);
799 if (g_slots[param].focus_handle || g_slots[param].focus_wcb_id) {
800 if(g_slots[param].session_type != MM_SESSION_TYPE_CALL &&
801 g_slots[param].session_type != MM_SESSION_TYPE_VIDEOCALL &&
802 g_slots[param].session_type != MM_SESSION_TYPE_VOIP &&
803 g_slots[param].session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
804 g_slots[param].enable_session ) {
805 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) {
806 if(g_slots[param].current_focus_type != FOCUS_NONE) {
807 err = mm_sound_release_focus(g_slots[param].focus_handle, g_slots[param].current_focus_type, NULL);
809 debug_error("mm_sound_release_focus failed [0x%x]", err);
812 if(mm_sound_unregister_focus(g_slots[param].focus_handle) || err) {
813 debug_error("Focus clean up failed [0x%x]", err);
814 pthread_mutex_unlock(&g_slot_mutex);
815 return MM_ERROR_POLICY_INTERNAL;
817 } else if (~(g_slots[param].session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
818 err = mm_sound_unset_focus_watch_callback(g_slots[param].focus_wcb_id);
820 debug_error("mm_sound_unset_focus_watch_callback failed [0x%x]", err);
821 pthread_mutex_unlock(&g_slot_mutex);
822 return MM_ERROR_POLICY_INTERNAL;
828 __mm_sound_mgr_ipc_notify_play_file_end(param);
830 debug_msg("Client callback msg_type (instance) : [%d]\n", (int)g_slots[param].param);
831 debug_msg("Handle allocated handle : [0x%08X]\n", g_slots[param].plughandle);
832 err = g_plugins[g_slots[param].pluginid].Destroy(g_slots[param].plughandle);
834 debug_critical("[CODEC MGR] Fail to destroy slot number : [%d] err [0x%x]\n", param, err);
836 memset(&g_slots[param], 0, sizeof(__mmsound_mgr_codec_handle_t));
837 g_slots[param].status = STATUS_IDLE;
838 pthread_mutex_unlock(&g_slot_mutex);
839 debug_msg("[CODEC MGR] Slot_mutex done\n");
844 static int _MMSoundMgrCodecGetEmptySlot(int *slot)
847 int err = MM_ERROR_NONE;
852 debug_msg("Codec slot ID : [%d]\n", *slot);
853 pthread_mutex_lock(&g_slot_mutex);
855 debug_msg("After Slot_mutex LOCK\n");
858 for (count = SOUND_SLOT_START; count < MANAGER_HANDLE_MAX ; count++) {
859 if (g_slots[count].status == STATUS_IDLE) {
860 g_slots[count].status = STATUS_SOUND;
864 pthread_mutex_unlock(&g_slot_mutex);
866 debug_msg("After Slot_mutex UNLOCK\n");
869 if (count < MANAGER_HANDLE_MAX) {
870 debug_msg("New handle allocated (codec slot ID : [%d])\n", count);
874 debug_warning("Handle is full handle : [%d]\n", count);
876 /* Temporal code for reset */
878 g_slots[count].status = STATUS_IDLE;
880 err = MM_ERROR_SOUND_INTERNAL;
890 static int _MMSoundMgrCodecRegisterInterface(MMSoundPluginType *plugin)
892 int err = MM_ERROR_NONE;
894 void *getinterface = NULL;
900 /* find emptry slot */
901 for (count = 0; count < MM_SOUND_SUPPORTED_CODEC_NUM; count++) {
902 if (g_plugins[count].GetSupportTypes == NULL)
906 if (count == MM_SOUND_SUPPORTED_CODEC_NUM) {
907 debug_critical("The plugin support type is not valid\n");
908 return MM_ERROR_COMMON_OUT_OF_RANGE;
911 err = MMSoundPluginGetSymbol(plugin, CODEC_GET_INTERFACE_FUNC_NAME, &getinterface);
912 if (err != MM_ERROR_NONE) {
913 debug_error("Get Symbol CODEC_GET_INTERFACE_FUNC_NAME is fail : %x\n", err);
916 debug_msg("interface[%p] empty_slot[%d]\n", getinterface, count);
918 err = MMSoundPlugCodecCastGetInterface(getinterface)(&g_plugins[count]);
919 if (err != MM_ERROR_NONE) {
920 debug_error("Get interface fail : %x\n", err);
923 /* If error occur, clean interface */
924 memset(&g_plugins[count], 0, sizeof(mmsound_codec_interface_t));
926 if (g_plugins[count].SetThreadPool)
927 g_plugins[count].SetThreadPool(MMSoundThreadPoolRun);