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>
33 #include "include/mm_sound_mgr_common.h"
34 #include "include/mm_sound_mgr_codec.h"
35 #include "include/mm_sound_plugin_codec.h"
36 #include "include/mm_sound_thread_pool.h"
38 #include "include/mm_sound_mgr_asm.h"
42 #define _ENABLE_KEYTONE /* Temporal test code */
45 int (*callback)(int, void *, void *); /* msg_type(pid) client callback & client data info */
50 MMHandleType plughandle;
56 } __mmsound_mgr_codec_handle_t;
58 static MMSoundPluginType *g_codec_plugins = NULL;
59 static __mmsound_mgr_codec_handle_t g_slots[MANAGER_HANDLE_MAX];
60 static mmsound_codec_interface_t g_plugins[MM_SOUND_SUPPORTED_CODEC_NUM];
61 static pthread_mutex_t g_slot_mutex;
63 static int _MMSoundMgrCodecStopCallback(int param);
64 static int _MMSoundMgrCodecFindKeytoneSlot(int *slotid);
65 static int _MMSoundMgrCodecGetEmptySlot(int *slotid);
66 static int _MMSoundMgrCodecFindLocaleSlot(int *slotid);
67 static int _MMSoundMgrCodecRegisterInterface(MMSoundPluginType *plugin);
70 #define STATUS_KEYTONE 1
71 #define STATUS_LOCALE 2
72 #define STATUS_SOUND 3
74 #define SOUND_SLOT_START 0
79 sound_codec_asm_callback(int handle, ASM_event_sources_t event_src, ASM_sound_commands_t command, unsigned int sound_status, void* cb_data)
81 int slotid = (int)cb_data;
82 int result = MM_ERROR_NONE;
83 ASM_cb_result_t cb_res = ASM_CB_RES_NONE;
85 debug_log("Got audio session callback msg for session_handle %d\n", handle);
89 case ASM_COMMAND_STOP:
90 case ASM_COMMAND_PAUSE:
91 debug_log("Got msg from asm to Stop or Pause %d\n", command);
92 result = MMSoundMgrCodecStop(slotid);
93 cb_res = ASM_CB_RES_STOP;
95 case ASM_COMMAND_RESUME:
96 case ASM_COMMAND_PLAY:
97 debug_log("Got msg from asm to Play or Resume %d\n", command);
98 cb_res = ASM_CB_RES_NONE;;
106 int MMSoundMgrCodecInit(const char *targetdir)
113 memset (g_slots, 0, sizeof(g_slots));
115 if(pthread_mutex_init(&g_slot_mutex, NULL)) {
116 debug_error("pthread_mutex_init failed [%s][%d]\n", __func__, __LINE__);
117 return MM_ERROR_SOUND_INTERNAL;
120 for (count = 0; count < MANAGER_HANDLE_MAX; count++) {
121 g_slots[count].status = STATUS_IDLE;
122 g_slots[count].plughandle = -1;
125 if (g_codec_plugins) {
126 debug_warning("Please Check Init twice\n");
127 MMSoundPluginRelease(g_codec_plugins);
130 MMSoundPluginScan(targetdir, MM_SOUND_PLUGIN_TYPE_CODEC, &g_codec_plugins);
132 while (g_codec_plugins[loop].type != MM_SOUND_PLUGIN_TYPE_NONE) {
133 _MMSoundMgrCodecRegisterInterface(&g_codec_plugins[loop++]);
137 return MM_ERROR_NONE;
140 int MMSoundMgrCodecFini(void)
144 memset(g_plugins, 0, sizeof(mmsound_codec_interface_t) * MM_SOUND_SUPPORTED_CODEC_NUM);
145 MMSoundPluginRelease(g_codec_plugins);
146 g_codec_plugins = NULL;
147 pthread_mutex_destroy(&g_slot_mutex);
150 return MM_ERROR_NONE;
154 int MMSoundMgrCodecPlay(int *slotid, const mmsound_mgr_codec_param_t *param)
157 mmsound_codec_info_t info;
158 mmsound_codec_param_t codec_param;
159 int err = MM_ERROR_NONE;
161 int need_asm_unregister = 0;
165 debug_msg("DTMF : [%d]\n",param->tone);
166 debug_msg("Repeat : [%d]\n",param->repeat_count);
167 debug_msg("Volume : [%f]\n",param->volume);
169 for (count = 0; g_plugins[count].GetSupportTypes; count++) {
171 if (g_plugins[count].Parse(param->source, &info) == MM_ERROR_NONE)
175 debug_msg("Find plugin codec ::: [%d]\n", count); /*The count num means codec type WAV, MP3 */
177 if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
178 debug_error("unsupported file type %d\n", count);
179 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
184 if (param->keytone == 1) {
185 /* Find keytone slot */
186 err = _MMSoundMgrCodecFindKeytoneSlot(slotid);
187 /* Not First connect */
188 if (err == MM_ERROR_NONE) {
189 if(g_slots[*slotid].status != STATUS_IDLE) {
190 MMSoundMgrCodecStop(*slotid);
192 debug_msg("Key tone : Stop to Play !!!\n");
194 codec_param.keytone = param->keytone;
195 } else if (param->keytone == 2) {
196 /* Find keytone slot */
197 err = _MMSoundMgrCodecFindLocaleSlot(slotid);
198 /* Not First connect */
199 if (err == MM_ERROR_NONE) {
200 if(g_slots[*slotid].status != STATUS_IDLE) {
201 MMSoundMgrCodecStop(*slotid);
203 debug_msg("Key tone : Stop to Play !!!\n");
205 codec_param.keytone = param->keytone;
207 debug_msg("Get New handle\n");
208 codec_param.keytone = 0;
211 err = _MMSoundMgrCodecGetEmptySlot(slotid);
212 if (err != MM_ERROR_NONE) {
213 debug_error("Empty g_slot is not found\n");
217 codec_param.tone = param->tone;
218 codec_param.volume_config = param->volume_config;
219 codec_param.repeat_count = param->repeat_count;
220 codec_param.volume = param->volume;
221 codec_param.source = param->source;
222 codec_param.priority = param->priority;
223 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
224 codec_param.param = *slotid;
225 codec_param.pid = (int)param->param;
226 codec_param.handle_route = param->handle_route;
228 pthread_mutex_lock(&g_slot_mutex);
229 debug_msg("After Slot_mutex LOCK\n");
231 /* In case of KEYTONE */
232 if (param->keytone == 1)
233 g_slots[*slotid].status = STATUS_KEYTONE;
235 /* In case of LOCALE */
236 if (param->keytone == 2) /* KeyTone */
237 g_slots[*slotid].status = STATUS_LOCALE;
243 if(param->session_type != ASM_EVENT_CALL && param->session_type != ASM_EVENT_VIDEOCALL) {
245 if(!ASM_register_sound((int)param->param, ¶m->session_handle, param->session_type, ASM_STATE_PLAYING,
246 sound_codec_asm_callback, (void*)*slotid, ASM_RESOURCE_NONE, &errorcode)) {
248 if(!ASM_register_sound_ex((int)param->param, ¶m->session_handle, param->session_type, ASM_STATE_PLAYING,
249 sound_codec_asm_callback, (void*)*slotid, ASM_RESOURCE_NONE, &errorcode, __asm_process_message)) {
251 debug_critical("ASM_register_sound() failed %d\n", errorcode);
252 pthread_mutex_unlock(&g_slot_mutex);
253 return MM_ERROR_POLICY_INTERNAL;
258 /* Codec id WAV or MP3 */
259 g_slots[*slotid].pluginid = count;
260 g_slots[*slotid].callback = param->callback;
261 g_slots[*slotid].msgcallback = param->msgcallback;
262 g_slots[*slotid].msgdata = param->msgdata;
263 g_slots[*slotid].param = param->param; /* This arg is used callback data */
264 g_slots[*slotid].session_type = param->session_type;
265 g_slots[*slotid].session_handle = param->session_handle;
267 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
271 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
272 debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
273 if (err != MM_ERROR_NONE) {
274 debug_error("Plugin create fail : 0x%08X\n", err);
275 g_slots[*slotid].status = STATUS_IDLE;
276 pthread_mutex_unlock(&g_slot_mutex);
277 debug_warning("After Slot_mutex UNLOCK\n");
278 need_asm_unregister = 1;
282 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
283 if (err != MM_ERROR_NONE) {
284 debug_error("Fail to play : 0x%08X\n", err);
285 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
286 need_asm_unregister = 1;
289 pthread_mutex_unlock(&g_slot_mutex);
290 debug_msg("After Slot_mutex UNLOCK\n");
293 if(param->session_type != ASM_EVENT_CALL && param->session_type != ASM_EVENT_VIDEOCALL && need_asm_unregister == 1) {
295 if(!ASM_unregister_sound(param->session_handle, param->session_type, &errorcode)) {
297 if(!ASM_unregister_sound_ex(param->session_handle, param->session_type, &errorcode,__asm_process_message)) {
299 debug_error("Unregister sound failed 0x%X\n", errorcode);
300 return MM_ERROR_POLICY_INTERNAL;
309 #define DTMF_PLUGIN_COUNT 2
310 int MMSoundMgrCodecPlayDtmf(int *slotid, const mmsound_mgr_codec_param_t *param)
314 mmsound_codec_info_t info;
315 mmsound_codec_param_t codec_param;
316 int err = MM_ERROR_NONE;
320 debug_msg("DTMF : [%d]\n",param->tone);
321 debug_msg("Repeat : [%d]\n",param->repeat_count);
322 debug_msg("Volume : [%f]\n",param->volume);
324 for (count = 0; g_plugins[count].GetSupportTypes; count++) {
326 codec_type = g_plugins[count].GetSupportTypes();
327 if(codec_type && (MM_SOUND_SUPPORTED_CODEC_DTMF == codec_type[0]))
331 debug_msg("Find plugin codec ::: [%d]\n", count); /*The count num means codec type DTMF */
333 if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
334 debug_error("unsupported file type %d\n", count);
335 printf("unsupported file type %d\n", count);
336 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
340 debug_msg("Get New handle\n");
341 codec_param.keytone = 0;
343 err = _MMSoundMgrCodecGetEmptySlot(slotid);
344 if(err != MM_ERROR_NONE)
346 debug_error("Empty g_slot is not found\n");
350 codec_param.tone = param->tone;
351 codec_param.priority = 0;
352 codec_param.volume_config = param->volume_config;
353 codec_param.repeat_count = param->repeat_count;
354 codec_param.volume = param->volume;
355 codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
356 codec_param.param = *slotid;
357 codec_param.pid = (int)param->param;
359 pthread_mutex_lock(&g_slot_mutex);
360 debug_msg("After Slot_mutex LOCK\n");
367 int need_asm_unregister = 0;
369 if(param->session_type != ASM_EVENT_CALL && param->session_type != ASM_EVENT_VIDEOCALL) {
371 if(!ASM_register_sound((int)param->param, ¶m->session_handle, param->session_type, ASM_STATE_PLAYING,
372 sound_codec_asm_callback, (void*)*slotid, ASM_RESOURCE_NONE, &errorcode)) {
374 if(!ASM_register_sound_ex((int)param->param, ¶m->session_handle, param->session_type, ASM_STATE_PLAYING,
375 sound_codec_asm_callback, (void*)*slotid, ASM_RESOURCE_NONE, &errorcode, __asm_process_message)) {
377 debug_critical("ASM_register_sound() failed %d\n", errorcode);
378 pthread_mutex_unlock(&g_slot_mutex);
379 return MM_ERROR_POLICY_INTERNAL;
383 g_slots[*slotid].pluginid = count;
384 g_slots[*slotid].callback = param->callback;
385 g_slots[*slotid].param = param->param; /* This arg is used callback data */
386 g_slots[*slotid].session_type = param->session_type;
387 g_slots[*slotid].session_handle = param->session_handle;
389 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
391 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
392 debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
393 if (err != MM_ERROR_NONE) {
394 debug_error("Plugin create fail : 0x%08X\n", err);
395 g_slots[*slotid].status = STATUS_IDLE;
396 pthread_mutex_unlock(&g_slot_mutex);
397 debug_warning("After Slot_mutex UNLOCK\n");
398 need_asm_unregister = 1;
402 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
403 if (err != MM_ERROR_NONE) {
404 debug_error("Fail to play : 0x%08X\n", err);
405 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
406 need_asm_unregister = 1;
409 pthread_mutex_unlock(&g_slot_mutex);
411 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
412 debug_msg("After Slot_mutex UNLOCK\n")
421 int MMSoundMgrCodecStop(const int slotid)
423 int err = MM_ERROR_NONE;
425 debug_enter("(Slotid : [%d])\n", slotid);
427 if (slotid < 0 || MANAGER_HANDLE_MAX <= slotid) {
428 return MM_ERROR_INVALID_ARGUMENT;
431 pthread_mutex_lock (&g_slot_mutex);
432 debug_msg("After Slot_mutex LOCK\n");
433 if (g_slots[slotid].status == STATUS_IDLE) {
434 err = MM_ERROR_SOUND_INVALID_STATE;
435 debug_warning("The playing slots is not found, Slot ID : [%d]\n", slotid);
438 debug_msg("Found slot, Slotid [%d] State [%d]\n", slotid, g_slots[slotid].status);
440 err = g_plugins[g_slots[slotid].pluginid].Stop(g_slots[slotid].plughandle);
441 if (err != MM_ERROR_NONE) {
442 debug_error("Fail to STOP Code : 0x%08X\n", err);
444 debug_msg("Found slot, Slotid [%d] State [%d]\n", slotid, g_slots[slotid].status);
446 pthread_mutex_unlock(&g_slot_mutex);
447 debug_msg("After Slot_mutex UNLOCK\n");
448 debug_leave("(err : 0x%08X)\n", err);
453 static int _MMSoundMgrCodecStopCallback(int param)
455 int err = MM_ERROR_NONE;
457 debug_enter("(Slot : %d)\n", param);
459 pthread_mutex_lock(&g_slot_mutex);
460 debug_msg("[CODEC MGR] Slot_mutex lock done\n");
464 * Unregister ASM here
469 if(g_slots[param].session_type != ASM_EVENT_CALL && g_slots[param].session_type != ASM_EVENT_VIDEOCALL) {
470 debug_msg("[CODEC MGR] ASM unregister\n");
472 if(!ASM_unregister_sound(g_slots[param].session_handle, g_slots[param].session_type, &errorcode)) {
474 if(!ASM_unregister_sound_ex(g_slots[param].session_handle, g_slots[param].session_type, &errorcode, __asm_process_message)) {
476 debug_error("[CODEC MGR] Unregister sound failed 0x%X\n", errorcode);
482 if (g_slots[param].msgcallback) {
483 debug_msg("[CODEC MGR] msgcallback : %p\n", g_slots[param].msgcallback);
484 debug_msg("[CODEC MGR] msg data : %p\n", g_slots[param].msgdata);
485 debug_msg("[CODEC MGR] mgr codec callback : %p\n", g_slots[param].callback);
486 g_slots[param].callback((int)g_slots[param].param, g_slots[param].msgcallback, g_slots[param].msgdata); /*param means client msg_type */
488 debug_msg("Client callback msg_type (instance) : [%d]\n", (int)g_slots[param].param);
489 debug_msg("Handle allocated handle : [0x%08X]\n", g_slots[param].plughandle);
490 err = g_plugins[g_slots[param].pluginid].Destroy(g_slots[param].plughandle);
492 debug_critical("[CODEC MGR] Fail to destroy slot number : [%d] err [0x%x]\n", param, err);
494 memset(&g_slots[param], 0, sizeof(__mmsound_mgr_codec_handle_t));
495 g_slots[param].status = STATUS_IDLE;
496 pthread_mutex_unlock(&g_slot_mutex);
497 debug_msg("[CODEC MGR] Slot_mutex done\n");
502 static int _MMSoundMgrCodecFindKeytoneSlot(int *slotid)
505 int err = MM_ERROR_NONE;
509 pthread_mutex_lock(&g_slot_mutex);
510 debug_warning("After Slot_mutex LOCK\n");
512 for (count = SOUND_SLOT_START; count < MANAGER_HANDLE_MAX ; count++) {
513 if (g_slots[count].status == STATUS_KEYTONE) {
517 pthread_mutex_unlock(&g_slot_mutex);
518 debug_warning("After Slot_mutex UNLOCK\n");
519 if (count < MANAGER_HANDLE_MAX) {
520 debug_msg("Found keytone handle allocated (Slot : [%d])\n", count);
524 debug_warning("Handle is full handle [KEY TONE] : [%d]\n", count);
525 err = MM_ERROR_SOUND_INTERNAL;
533 static int _MMSoundMgrCodecFindLocaleSlot(int *slotid)
536 int err = MM_ERROR_NONE;
540 pthread_mutex_lock(&g_slot_mutex);
541 debug_warning("After Slot_mutex LOCK\n");
543 for (count = SOUND_SLOT_START; count < MANAGER_HANDLE_MAX ; count++) {
544 if (g_slots[count].status == STATUS_LOCALE) {
548 pthread_mutex_unlock(&g_slot_mutex);
550 debug_warning("After Slot_mutex UNLOCK\n");
551 if (count < MANAGER_HANDLE_MAX) {
552 debug_msg("Found locale handle allocated (Slot : [%d])\n", count);
556 debug_warning("Handle is full handle [KEY TONE] \n");
557 err = MM_ERROR_SOUND_INTERNAL;
565 static int _MMSoundMgrCodecGetEmptySlot(int *slot)
568 int err = MM_ERROR_NONE;
571 debug_msg("Codec slot ID : [%d]\n", *slot);
572 pthread_mutex_lock(&g_slot_mutex);
573 debug_msg("After Slot_mutex LOCK\n");
575 for (count = SOUND_SLOT_START; count < MANAGER_HANDLE_MAX ; count++) {
576 if (g_slots[count].status == STATUS_IDLE) {
577 g_slots[count].status = STATUS_SOUND;
581 pthread_mutex_unlock(&g_slot_mutex);
582 debug_msg("After Slot_mutex UNLOCK\n");
584 if (count < MANAGER_HANDLE_MAX) {
585 debug_msg("New handle allocated (codec slot ID : [%d])\n", count);
589 debug_warning("Handle is full handle : [%d]\n", count);
591 /* Temporal code for reset */
593 g_slots[count].status = STATUS_IDLE;
595 err = MM_ERROR_SOUND_INTERNAL;
603 static int _MMSoundMgrCodecRegisterInterface(MMSoundPluginType *plugin)
605 int err = MM_ERROR_NONE;
607 void *getinterface = NULL;
611 /* find emptry slot */
612 for (count = 0; count < MM_SOUND_SUPPORTED_CODEC_NUM; count++) {
613 if (g_plugins[count].GetSupportTypes == NULL)
617 if (count == MM_SOUND_SUPPORTED_CODEC_NUM) {
618 debug_critical("The plugin support type is not valid\n");
619 return MM_ERROR_COMMON_OUT_OF_RANGE;
622 debug_msg("Empty slot find : %d\n", count);
624 err = MMSoundPluginGetSymbol(plugin, CODEC_GET_INTERFACE_FUNC_NAME, &getinterface);
625 if (err != MM_ERROR_NONE) {
626 debug_error("Get Symbol CODEC_GET_INTERFACE_FUNC_NAME is fail : %x\n", err);
629 debug_msg("Getinterface name : %s\n", (char*)getinterface );
631 err = MMSoundPlugCodecCastGetInterface(getinterface)(&g_plugins[count]);
632 if (err != MM_ERROR_NONE) {
633 debug_error("Get interface fail : %x\n", err);
636 /* If error occur, clean interface */
637 memset(&g_plugins[count], 0, sizeof(mmsound_codec_interface_t));
639 if (g_plugins[count].SetThreadPool)
640 g_plugins[count].SetThreadPool(MMSoundThreadPoolRun);