Rebase code with tizen 2.3 with following additional changes
[platform/core/multimedia/libmm-sound.git] / server / mm_sound_mgr_codec.c
1 /*
2  * libmm-sound
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Seungbae Shin <seungbae.shin@samsung.com>
7  *
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
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
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.
19  *
20  */
21
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <pthread.h>
26
27 #include <mm_source.h>
28 #include <mm_error.h>
29 #include <mm_types.h>
30 #include <mm_debug.h>
31 #include <mm_ipc.h>
32
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"
37 #include "include/mm_sound_pa_client.h"
38 #include "include/mm_sound_mgr_asm.h"
39
40
41
42 #define _ENABLE_KEYTONE /* Temporal test code */
43
44 typedef struct {
45         int (*callback)(int, void *, void *, int);      /* msg_type(pid) client callback & client data info */
46         void *param;
47         int pid;
48         void *msgcallback;
49         void *msgdata;
50         MMHandleType plughandle;
51
52         int pluginid;
53         int status;
54         int session_type;
55         int session_options;
56         int session_handle;
57
58         bool enable_session;
59  } __mmsound_mgr_codec_handle_t;
60
61 static MMSoundPluginType *g_codec_plugins = NULL;
62 static __mmsound_mgr_codec_handle_t g_slots[MANAGER_HANDLE_MAX];
63 static mmsound_codec_interface_t g_plugins[MM_SOUND_SUPPORTED_CODEC_NUM];
64 static pthread_mutex_t g_slot_mutex;
65 static pthread_mutex_t codec_wave_mutex;
66 static int _MMSoundMgrCodecStopCallback(int param);
67 static int _MMSoundMgrCodecFindKeytoneSlot(int *slotid);
68 static int _MMSoundMgrCodecGetEmptySlot(int *slotid);
69 static int _MMSoundMgrCodecFindLocaleSlot(int *slotid);
70 static int _MMSoundMgrCodecRegisterInterface(MMSoundPluginType *plugin);
71
72 #define STATUS_IDLE 0
73 #define STATUS_KEYTONE 1
74 #define STATUS_LOCALE 2
75 #define STATUS_SOUND 3
76
77 #define SOUND_SLOT_START 0
78
79
80
81 ASM_cb_result_t
82 sound_codec_asm_callback(int handle, ASM_event_sources_t event_src, ASM_sound_commands_t command, unsigned int sound_status, void* cb_data)
83 {
84         int slotid = (int)cb_data;
85         int result = MM_ERROR_NONE;
86         ASM_cb_result_t cb_res = ASM_CB_RES_NONE;
87
88         debug_log("Got audio session callback msg for session_handle %d\n", handle);
89
90         switch(command)
91         {
92         case ASM_COMMAND_STOP:
93         case ASM_COMMAND_PAUSE:
94                 debug_log("Got msg from asm to Stop or Pause %d\n", command);
95                 result = MMSoundMgrCodecStop(slotid);
96                 if (result != MM_ERROR_NONE) {
97                         debug_log("result error %d\n", result);
98                 }
99                 cb_res = ASM_CB_RES_STOP;
100                 break;
101         case ASM_COMMAND_RESUME:
102         case ASM_COMMAND_PLAY:
103                 debug_log("Got msg from asm to Play or Resume %d\n", command);
104                 cb_res = ASM_CB_RES_NONE;;
105         default:
106                 break;
107         }
108         return cb_res;
109 }
110
111
112 int MMSoundMgrCodecInit(const char *targetdir)
113 {
114         int loop = 0;
115         int count = 0;
116
117         debug_enter("\n");
118
119         memset (g_slots, 0, sizeof(g_slots));
120
121         if(pthread_mutex_init(&g_slot_mutex, NULL)) {
122                 debug_error("pthread_mutex_init failed\n");
123                 return MM_ERROR_SOUND_INTERNAL;
124         }
125
126         if(pthread_mutex_init(&codec_wave_mutex, NULL)) {
127                 debug_error("pthread_mutex_init failed\n");
128                 return MM_ERROR_SOUND_INTERNAL;
129         }
130
131         for (count = 0; count < MANAGER_HANDLE_MAX; count++) {
132                 g_slots[count].status = STATUS_IDLE;
133                 g_slots[count].plughandle = 0;
134         }
135
136         if (g_codec_plugins) {
137                 debug_warning("Please Check Init twice\n");
138                 MMSoundPluginRelease(g_codec_plugins);
139         }
140
141         MMSoundPluginScan(targetdir, MM_SOUND_PLUGIN_TYPE_CODEC, &g_codec_plugins);
142
143         while (g_codec_plugins[loop].type != MM_SOUND_PLUGIN_TYPE_NONE) {
144                 _MMSoundMgrCodecRegisterInterface(&g_codec_plugins[loop++]);
145         }
146
147         debug_leave("\n");
148         return MM_ERROR_NONE;
149 }
150
151 int MMSoundMgrCodecFini(void)
152 {
153         debug_enter("\n");
154
155         memset(g_plugins, 0, sizeof(mmsound_codec_interface_t) * MM_SOUND_SUPPORTED_CODEC_NUM);
156         MMSoundPluginRelease(g_codec_plugins);
157         g_codec_plugins = NULL;
158         pthread_mutex_destroy(&g_slot_mutex);
159         pthread_mutex_destroy(&codec_wave_mutex);
160         debug_leave("\n");
161         return MM_ERROR_NONE;
162 }
163
164
165 int MMSoundMgrCodecPlay(int *slotid, const mmsound_mgr_codec_param_t *param)
166 {
167         int count = 0;
168         mmsound_codec_info_t info;
169         mmsound_codec_param_t codec_param;
170         int err = MM_ERROR_NONE;
171         int errorcode = 0;
172         int need_asm_unregister = 0;
173
174 #ifdef DEBUG_DETAIL
175         debug_enter("\n");
176 #endif
177
178         for (count = 0; g_plugins[count].GetSupportTypes; count++) {
179                 /* Find codec */
180                 if (g_plugins[count].Parse(param->source, &info) == MM_ERROR_NONE)
181                         break;
182         }
183
184         /*The count num means codec type WAV, MP3 */
185         debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, count);
186
187         if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
188                 debug_error("unsupported file type %d\n", count);
189                 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
190                 goto cleanup;
191         }
192
193         /* KeyTone */
194         if (param->keytone == 1) {
195                 /* Find keytone slot */
196                 err = _MMSoundMgrCodecFindKeytoneSlot(slotid);
197                 /* Not First connect */
198                 if (err == MM_ERROR_NONE) {
199                         if(g_slots[*slotid].status != STATUS_IDLE) {
200                                 MMSoundMgrCodecStop(*slotid);
201                         }
202                         debug_msg("Key tone : Stop to Play !!!\n");
203                 }
204                 codec_param.keytone = param->keytone;
205         } else if (param->keytone == 2) {
206                 /* Find keytone slot */
207                 err = _MMSoundMgrCodecFindLocaleSlot(slotid);
208                 /* Not First connect */
209                 if (err == MM_ERROR_NONE) {
210                         if(g_slots[*slotid].status != STATUS_IDLE) {
211                                 MMSoundMgrCodecStop(*slotid);
212                         }
213                         debug_msg("Key tone : Stop to Play !!!\n");
214                 }
215                 codec_param.keytone = param->keytone;
216         } else {
217 #ifdef DEBUG_DETAIL
218                 debug_msg("Get New handle\n");
219 #endif
220                 codec_param.keytone = 0;
221         }
222
223         err = _MMSoundMgrCodecGetEmptySlot(slotid);
224         if (err != MM_ERROR_NONE) {
225                 debug_error("Empty g_slot is not found\n");
226                 goto cleanup;
227         }
228
229         codec_param.tone = param->tone;
230         codec_param.volume_config = param->volume_config;
231         codec_param.repeat_count = param->repeat_count;
232         codec_param.volume = param->volume;
233         codec_param.source = param->source;
234         codec_param.priority = param->priority;
235         codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
236         codec_param.param = *slotid;
237         codec_param.pid = (int)param->param;
238         codec_param.handle_route = param->handle_route;
239         codec_param.codec_wave_mutex = &codec_wave_mutex;
240         pthread_mutex_lock(&g_slot_mutex);
241 #ifdef DEBUG_DETAIL
242         debug_msg("After Slot_mutex LOCK\n");
243 #endif
244
245         /* In case of KEYTONE */
246         if (param->keytone == 1)
247                 g_slots[*slotid].status = STATUS_KEYTONE;
248
249         /* In case of LOCALE */
250         if (param->keytone == 2) /* KeyTone */
251                 g_slots[*slotid].status = STATUS_LOCALE;
252
253         /*
254          * Register ASM here
255          */
256         if (param->session_type != ASM_EVENT_CALL &&
257                 param->session_type != ASM_EVENT_VIDEOCALL &&
258                 param->session_type != ASM_EVENT_VOIP &&
259                 param->session_type != ASM_EVENT_VOICE_RECOGNITION &&
260                 param->priority != HANDLE_PRIORITY_SOLO &&
261                 param->enable_session) {
262                 if(!ASM_register_sound_ex((int)param->param, (int *)(&param->session_handle), param->session_type, ASM_STATE_NONE,
263                                                                 sound_codec_asm_callback, (void*)*slotid, ASM_RESOURCE_NONE, &errorcode, __asm_process_message)) {
264                         debug_critical("ASM_register_sound_ex() failed 0x%X\n", errorcode);
265                         pthread_mutex_unlock(&g_slot_mutex);
266                         return MM_ERROR_POLICY_INTERNAL;
267                 }
268                 if(param->session_options) {
269                         if(!ASM_set_session_option(param->session_handle, param->session_options, &errorcode)) {
270                                 debug_error("ASM_set_session_option() failed 0x%x\n", errorcode);
271                         }
272                 }
273                 if(!ASM_set_sound_state_ex(param->session_handle, param->session_type, ASM_STATE_PLAYING, ASM_RESOURCE_NONE, &errorcode, __asm_process_message)) {
274                         debug_critical("ASM_set_sound_state_ex() failed 0x%X\n", errorcode);
275                         pthread_mutex_unlock(&g_slot_mutex);
276                         if(!ASM_unregister_sound_ex(param->session_handle, param->session_type, &errorcode,__asm_process_message)) {
277                                 debug_error("ASM_unregister_sound_ex() failed 0x%X\n", errorcode);
278                         }
279                         return MM_ERROR_POLICY_INTERNAL;
280                 }
281         }
282         //
283
284         /* Codec id WAV or MP3 */
285         g_slots[*slotid].pluginid = count;
286         g_slots[*slotid].callback = param->callback;
287         g_slots[*slotid].msgcallback = param->msgcallback;
288         g_slots[*slotid].msgdata = param->msgdata;
289         g_slots[*slotid].param    = param->param;               /* This arg is used callback data */
290         g_slots[*slotid].session_type = param->session_type;
291         g_slots[*slotid].session_options = param->session_options;
292         g_slots[*slotid].session_handle = param->session_handle;
293         g_slots[*slotid].enable_session = true;
294
295         debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
296
297         err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
298         debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
299         if (err != MM_ERROR_NONE) {
300                 debug_error("Plugin create fail : 0x%08X\n", err);
301                 g_slots[*slotid].status = STATUS_IDLE;
302                 pthread_mutex_unlock(&g_slot_mutex);
303                 debug_warning("After Slot_mutex UNLOCK\n");
304                 if (param->session_handle) {
305                         need_asm_unregister = 1;
306                 }
307                 goto cleanup;
308         }
309
310         err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
311         if (err != MM_ERROR_NONE) {
312                 debug_error("Fail to play : 0x%08X\n", err);
313                 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
314                 if (param->session_handle) {
315                         need_asm_unregister = 1;
316                 }
317         }
318
319         pthread_mutex_unlock(&g_slot_mutex);
320 #ifdef DEBUG_DETAIL
321         debug_msg("After Slot_mutex UNLOCK\n");
322 #endif
323
324 cleanup:
325         if(param->session_type != ASM_EVENT_CALL &&
326                 param->session_type != ASM_EVENT_VIDEOCALL &&
327                 param->session_type != ASM_EVENT_VOIP &&
328                 param->session_type != ASM_EVENT_VOICE_RECOGNITION &&
329                 param->enable_session &&
330                 need_asm_unregister == 1) {
331                 if(!ASM_set_sound_state_ex(param->session_handle, param->session_type, ASM_STATE_STOP, ASM_RESOURCE_NONE, &errorcode, __asm_process_message)) {
332                         debug_critical("ASM_set_sound_state_ex() failed 0x%X\n", errorcode);
333                 }
334                 if(!ASM_unregister_sound_ex(param->session_handle, param->session_type, &errorcode,__asm_process_message)) {
335                         debug_error("ASM_unregister_sound_ex() failed 0x%X\n", errorcode);
336                         return MM_ERROR_POLICY_INTERNAL;
337                 }
338         }
339
340 #ifdef DEBUG_DETAIL
341         debug_leave("\n");
342 #endif
343
344         return err;
345 }
346
347 #define DTMF_PLUGIN_COUNT 2
348 int MMSoundMgrCodecPlayDtmf(int *slotid, const mmsound_mgr_codec_param_t *param)
349 {
350         int count = 0;
351         int *codec_type;
352         mmsound_codec_info_t info;
353         mmsound_codec_param_t codec_param;
354         int err = MM_ERROR_NONE;
355         int errorcode = 0;
356         int need_asm_unregister = 0;
357
358 #ifdef DEBUG_DETAIL
359         debug_enter("\n");
360 #endif
361
362         for (count = 0; g_plugins[count].GetSupportTypes; count++) {
363                 /* Find codec */
364                 codec_type = g_plugins[count].GetSupportTypes();
365                 if(codec_type && (MM_SOUND_SUPPORTED_CODEC_DTMF == codec_type[0]))
366                         break;
367         }
368
369         /*The count num means codec type DTMF */
370         debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, count);
371
372         if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
373                 debug_error("unsupported file type %d\n", count);
374                 printf("unsupported file type %d\n", count);
375                 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
376                 goto cleanup;
377         }
378
379 #ifdef DEBUG_DETAIL
380         debug_msg("Get New handle\n");
381 #endif
382         codec_param.keytone = 0;
383
384         err = _MMSoundMgrCodecGetEmptySlot(slotid);
385         if(err != MM_ERROR_NONE)
386         {
387                 debug_error("Empty g_slot is not found\n");
388                 goto cleanup;
389         }
390
391         codec_param.tone = param->tone;
392         codec_param.priority = 0;
393         codec_param.volume_config = param->volume_config;
394         codec_param.repeat_count = param->repeat_count;
395         codec_param.volume = param->volume;
396         codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
397         codec_param.param = *slotid;
398         codec_param.pid = (int)param->param;
399
400         pthread_mutex_lock(&g_slot_mutex);
401 #ifdef DEBUG_DETAIL
402         debug_msg("After Slot_mutex LOCK\n");
403 #endif
404
405         //
406         /*
407          * Register ASM here
408          */
409
410         if (param->session_type != ASM_EVENT_CALL &&
411                 param->session_type != ASM_EVENT_VIDEOCALL &&
412                 param->session_type != ASM_EVENT_VOIP &&
413                 param->session_type != ASM_EVENT_VOICE_RECOGNITION &&
414                 param->enable_session)  {
415                 if(!ASM_register_sound_ex((int)param->param, (int *)(&param->session_handle), param->session_type, ASM_STATE_NONE,
416                                                                 sound_codec_asm_callback, (void*)*slotid, ASM_RESOURCE_NONE, &errorcode, __asm_process_message)) {
417                         debug_critical("ASM_register_sound_ex() failed 0x%X\n", errorcode);
418                         pthread_mutex_unlock(&g_slot_mutex);
419                         return MM_ERROR_POLICY_INTERNAL;
420                 }
421                 if(param->session_options) {
422                         if(!ASM_set_session_option(param->session_handle, param->session_options, &errorcode)) {
423                                 debug_error("ASM_set_session_option() failed 0x%x\n", errorcode);
424                         }
425                 }
426                 if(!ASM_set_sound_state_ex(param->session_handle, param->session_type, ASM_STATE_PLAYING, ASM_RESOURCE_NONE, &errorcode, __asm_process_message)) {
427                         debug_critical("ASM_set_sound_state_ex() failed 0x%X\n", errorcode);
428                         pthread_mutex_unlock(&g_slot_mutex);
429                         if(!ASM_unregister_sound_ex(param->session_handle, param->session_type, &errorcode,__asm_process_message)) {
430                                 debug_error("ASM_unregister_sound_ex() failed 0x%X\n", errorcode);
431                         }
432                         return MM_ERROR_POLICY_INTERNAL;
433                 }
434         }
435
436         g_slots[*slotid].pluginid = count;
437         g_slots[*slotid].callback = param->callback;
438         g_slots[*slotid].param    = param->param;               /* This arg is used callback data */
439         g_slots[*slotid].session_type = param->session_type;
440         g_slots[*slotid].session_options = param->session_options;
441         g_slots[*slotid].session_handle = param->session_handle;
442         g_slots[*slotid].enable_session = param->enable_session;
443
444 #ifdef DEBUG_DETAIL
445         debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
446 #endif
447
448         err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
449         debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
450         if (err != MM_ERROR_NONE) {
451                 debug_error("Plugin create fail : 0x%08X\n", err);
452                 g_slots[*slotid].status = STATUS_IDLE;
453                 pthread_mutex_unlock(&g_slot_mutex);
454                 debug_warning("After Slot_mutex UNLOCK\n");
455                 need_asm_unregister = 1;
456                 goto cleanup;
457         }
458
459         err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
460         if (err != MM_ERROR_NONE) {
461                 debug_error("Fail to play : 0x%08X\n", err);
462                 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
463                 need_asm_unregister = 1;
464         }
465
466         pthread_mutex_unlock(&g_slot_mutex);
467
468         debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
469 #ifdef DEBUG_DETAIL
470         debug_msg("After Slot_mutex UNLOCK\n")
471 #endif
472
473 cleanup:
474         if (param->session_type != ASM_EVENT_CALL &&
475                 param->session_type != ASM_EVENT_VIDEOCALL &&
476                 param->session_type != ASM_EVENT_VOIP &&
477                 param->session_type != ASM_EVENT_VOICE_RECOGNITION &&
478                 param->enable_session &&
479                 need_asm_unregister == 1) {
480                 if(!ASM_unregister_sound_ex(param->session_handle, param->session_type, &errorcode,__asm_process_message)) {
481                         debug_error("Unregister sound failed 0x%X\n", errorcode);
482                         return MM_ERROR_POLICY_INTERNAL;
483                 }
484         }
485
486 #ifdef DEBUG_DETAIL
487         debug_leave("\n");
488 #endif
489
490         return err;
491 }
492
493
494 int MMSoundMgrCodecStop(const int slotid)
495 {
496         int err = MM_ERROR_NONE;
497
498         debug_enter("(Slotid : [%d])\n", slotid);
499
500         if (slotid < 0 || MANAGER_HANDLE_MAX <= slotid) {
501                 return MM_ERROR_INVALID_ARGUMENT;
502         }
503
504         pthread_mutex_lock (&g_slot_mutex);
505 #ifdef DEBUG_DETAIL
506         debug_msg("After Slot_mutex LOCK\n");
507 #endif
508         if (g_slots[slotid].status == STATUS_IDLE) {
509                 err = MM_ERROR_SOUND_INVALID_STATE;
510                 debug_warning("The playing slots is not found, Slot ID : [%d]\n", slotid);
511                 goto cleanup;
512         }
513 #ifdef DEBUG_DETAIL
514         debug_msg("Found slot, Slotid [%d] State [%d]\n", slotid, g_slots[slotid].status);
515 #endif
516
517         err = g_plugins[g_slots[slotid].pluginid].Stop(g_slots[slotid].plughandle);
518         if (err != MM_ERROR_NONE) {
519                 debug_error("Fail to STOP Code : 0x%08X\n", err);
520         }
521         debug_msg("Found slot, Slotid [%d] State [%d]\n", slotid, g_slots[slotid].status);
522 cleanup:
523         pthread_mutex_unlock(&g_slot_mutex);
524 #ifdef DEBUG_DETAIL
525         debug_msg("After Slot_mutex UNLOCK\n");
526 #endif
527         debug_leave("(err : 0x%08X)\n", err);
528
529         return err;
530 }
531
532 static int _MMSoundMgrCodecStopCallback(int param)
533 {
534         int err = MM_ERROR_NONE;
535
536         debug_enter("(Slot : %d)\n", param);
537
538         pthread_mutex_lock(&g_slot_mutex);
539         debug_msg("[CODEC MGR] Slot_mutex lock done\n");
540
541
542         /*
543          * Unregister ASM here
544          */
545
546         int errorcode = 0;
547         debug_msg("[CODEC MGR] enable_session %d ",g_slots[param].enable_session);
548
549         if (g_slots[param].session_handle) {
550                 if(g_slots[param].session_type != ASM_EVENT_CALL &&
551                         g_slots[param].session_type != ASM_EVENT_VIDEOCALL &&
552                         g_slots[param].session_type != ASM_EVENT_VOIP &&
553                         g_slots[param].session_type != ASM_EVENT_VOICE_RECOGNITION &&
554                         g_slots[param].enable_session ) {
555                         if(!ASM_set_sound_state_ex(g_slots[param].session_handle, g_slots[param].session_type, ASM_STATE_STOP, ASM_RESOURCE_NONE, &errorcode, __asm_process_message)) {
556                                 debug_error("[CODEC MGR] ASM_set_sound_state_ex() failed 0x%X\n", errorcode);
557                         }
558                         debug_msg("[CODEC MGR] ASM unregister\n");
559                         if(!ASM_unregister_sound_ex(g_slots[param].session_handle, g_slots[param].session_type, &errorcode, __asm_process_message)) {
560                                 debug_error("[CODEC MGR] ASM_unregister_sound_ex() failed 0x%X\n", errorcode);
561                         }
562                 }
563         }
564
565         if (g_slots[param].msgcallback) {
566                 debug_msg("[CODEC MGR] msgcallback : %p\n", g_slots[param].msgcallback);
567                 debug_msg("[CODEC MGR] msg data : %p\n", g_slots[param].msgdata);
568                 debug_msg("[CODEC MGR] mgr codec callback : %p\n", g_slots[param].callback);
569                 g_slots[param].callback((int)g_slots[param].param, g_slots[param].msgcallback, g_slots[param].msgdata, param);          /*param means client msg_type */
570         }
571         debug_msg("Client callback msg_type (instance) : [%d]\n", (int)g_slots[param].param);
572         debug_msg("Handle allocated handle : [0x%08X]\n", g_slots[param].plughandle);
573         err = g_plugins[g_slots[param].pluginid].Destroy(g_slots[param].plughandle);
574         if (err < 0 ) {
575                 debug_critical("[CODEC MGR] Fail to destroy slot number : [%d] err [0x%x]\n", param, err);
576         }
577         memset(&g_slots[param], 0, sizeof(__mmsound_mgr_codec_handle_t));
578         g_slots[param].status = STATUS_IDLE;
579         pthread_mutex_unlock(&g_slot_mutex);
580         debug_msg("[CODEC MGR] Slot_mutex done\n");
581
582         return err;
583 }
584
585 static int _MMSoundMgrCodecFindKeytoneSlot(int *slotid)
586 {
587         int count = 0;
588         int err = MM_ERROR_NONE;
589
590 #ifdef DEBUG_DETAIL
591         debug_enter("\n");
592 #endif
593
594         pthread_mutex_lock(&g_slot_mutex);
595 #ifdef DEBUG_DETAIL
596         debug_warning("After Slot_mutex LOCK\n");
597 #endif
598
599         for (count = SOUND_SLOT_START; count < MANAGER_HANDLE_MAX ; count++) {
600                 if (g_slots[count].status == STATUS_KEYTONE) {
601                         break;
602                 }
603         }
604         pthread_mutex_unlock(&g_slot_mutex);
605 #ifdef DEBUG_DETAIL
606         debug_warning("After Slot_mutex UNLOCK\n");
607 #endif
608         if (count < MANAGER_HANDLE_MAX) {
609                 debug_msg("Found keytone handle allocated (Slot : [%d])\n", count);
610                 *slotid = count;
611                 err =  MM_ERROR_NONE;
612         } else {
613                 debug_warning("Handle is full handle [KEY TONE] : [%d]\n", count);
614                 err =  MM_ERROR_SOUND_INTERNAL;
615         }
616
617 #ifdef DEBUG_DETAIL
618         debug_leave("\n");
619 #endif
620
621         return err;
622 }
623
624 static int _MMSoundMgrCodecFindLocaleSlot(int *slotid)
625 {
626         int count = 0;
627         int err = MM_ERROR_NONE;
628
629 #ifdef DEBUG_DETAIL
630         debug_enter("\n");
631 #endif
632
633         pthread_mutex_lock(&g_slot_mutex);
634 #ifdef DEBUG_DETAIL
635         debug_warning("After Slot_mutex LOCK\n");
636 #endif
637
638         for (count = SOUND_SLOT_START; count < MANAGER_HANDLE_MAX ; count++) {
639                 if (g_slots[count].status == STATUS_LOCALE) {
640                         break;
641                 }
642         }
643         pthread_mutex_unlock(&g_slot_mutex);
644
645 #ifdef DEBUG_DETAIL
646         debug_warning("After Slot_mutex UNLOCK\n");
647 #endif
648         if (count < MANAGER_HANDLE_MAX) {
649                 debug_msg("Found locale handle allocated (Slot : [%d])\n", count);
650                 *slotid = count;
651                 err =  MM_ERROR_NONE;
652         } else {
653                 debug_warning("Handle is full handle [KEY TONE] \n");
654                 err =  MM_ERROR_SOUND_INTERNAL;
655         }
656
657 #ifdef DEBUG_DETAIL
658         debug_leave("\n");
659 #endif
660
661         return err;
662 }
663
664 static int _MMSoundMgrCodecGetEmptySlot(int *slot)
665 {
666         int count = 0;
667         int err = MM_ERROR_NONE;
668
669 #ifdef DEBUG_DETAIL
670         debug_enter("\n");
671 #endif
672         debug_msg("Codec slot ID : [%d]\n", *slot);
673         pthread_mutex_lock(&g_slot_mutex);
674 #ifdef DEBUG_DETAIL
675         debug_msg("After Slot_mutex LOCK\n");
676 #endif
677
678         for (count = SOUND_SLOT_START; count < MANAGER_HANDLE_MAX ; count++) {
679                 if (g_slots[count].status == STATUS_IDLE) {
680                         g_slots[count].status = STATUS_SOUND;
681                         break;
682                 }
683         }
684         pthread_mutex_unlock(&g_slot_mutex);
685 #ifdef DEBUG_DETAIL
686         debug_msg("After Slot_mutex UNLOCK\n");
687 #endif
688
689         if (count < MANAGER_HANDLE_MAX) {
690                 debug_msg("New handle allocated (codec slot ID : [%d])\n", count);
691                 *slot = count;
692                 err =  MM_ERROR_NONE;
693         } else {
694                 debug_warning("Handle is full handle : [%d]\n", count);
695                 *slot = -1;
696                 /* Temporal code for reset */
697                 while(count--) {
698                         g_slots[count].status = STATUS_IDLE;
699                 }
700                 err =  MM_ERROR_SOUND_INTERNAL;
701         }
702
703 #ifdef DEBUG_DETAIL
704         debug_leave("\n");
705 #endif
706
707         return err;
708 }
709
710 static int _MMSoundMgrCodecRegisterInterface(MMSoundPluginType *plugin)
711 {
712         int err = MM_ERROR_NONE;
713         int count = 0;
714         void *getinterface = NULL;
715
716 #ifdef DEBUG_DETAIL
717         debug_enter("\n");
718 #endif
719
720         /* find emptry slot */
721         for (count = 0; count < MM_SOUND_SUPPORTED_CODEC_NUM; count++) {
722                 if (g_plugins[count].GetSupportTypes == NULL)
723                         break;
724         }
725
726         if (count == MM_SOUND_SUPPORTED_CODEC_NUM) {
727                 debug_critical("The plugin support type is not valid\n");
728                 return MM_ERROR_COMMON_OUT_OF_RANGE;
729         }
730
731         err = MMSoundPluginGetSymbol(plugin, CODEC_GET_INTERFACE_FUNC_NAME, &getinterface);
732         if (err != MM_ERROR_NONE) {
733                 debug_error("Get Symbol CODEC_GET_INTERFACE_FUNC_NAME is fail : %x\n", err);
734                 goto cleanup;
735         }
736         debug_msg("interface[%s] empty_slot[%d]\n", (char*)getinterface, count);
737
738         err = MMSoundPlugCodecCastGetInterface(getinterface)(&g_plugins[count]);
739         if (err != MM_ERROR_NONE) {
740                 debug_error("Get interface fail : %x\n", err);
741
742 cleanup:
743                 /* If error occur, clean interface */
744                 memset(&g_plugins[count], 0, sizeof(mmsound_codec_interface_t));
745         } else {
746                 if (g_plugins[count].SetThreadPool)
747                         g_plugins[count].SetThreadPool(MMSoundThreadPoolRun);
748         }
749
750 #ifdef DEBUG_DETAIL
751         debug_leave("\n");
752 #endif
753
754         return err;
755 }
756