Make ASM handling external.
[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
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 *);   /* 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_handle;
56  } __mmsound_mgr_codec_handle_t;
57
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;
62
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);
68
69 #define STATUS_IDLE 0
70 #define STATUS_KEYTONE 1
71 #define STATUS_LOCALE 2
72 #define STATUS_SOUND 3
73
74 #define SOUND_SLOT_START 0
75
76
77
78 ASM_cb_result_t
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)
80 {
81         int slotid = (int)cb_data;
82         int result = MM_ERROR_NONE;
83         ASM_cb_result_t cb_res = ASM_CB_RES_NONE;
84
85         debug_log("Got audio session callback msg for session_handle %d\n", handle);
86
87         switch(command)
88         {
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;
94                 break;
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;;
99         default:
100                 break;
101         }
102         return cb_res;
103 }
104
105
106 int MMSoundMgrCodecInit(const char *targetdir)
107 {
108         int loop = 0;
109         int count = 0;
110
111         debug_enter("\n");
112
113         memset (g_slots, 0, sizeof(g_slots));
114
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;
118         }
119
120         for (count = 0; count < MANAGER_HANDLE_MAX; count++) {
121                 g_slots[count].status = STATUS_IDLE;
122                 g_slots[count].plughandle = -1;
123         }
124
125         if (g_codec_plugins) {
126                 debug_warning("Please Check Init twice\n");
127                 MMSoundPluginRelease(g_codec_plugins);
128         }
129
130         MMSoundPluginScan(targetdir, MM_SOUND_PLUGIN_TYPE_CODEC, &g_codec_plugins);
131
132         while (g_codec_plugins[loop].type != MM_SOUND_PLUGIN_TYPE_NONE) {
133                 _MMSoundMgrCodecRegisterInterface(&g_codec_plugins[loop++]);
134         }
135
136         debug_leave("\n");
137         return MM_ERROR_NONE;
138 }
139
140 int MMSoundMgrCodecFini(void)
141 {
142         debug_enter("\n");
143
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);
148
149         debug_leave("\n");
150         return MM_ERROR_NONE;
151 }
152
153
154 int MMSoundMgrCodecPlay(int *slotid, const mmsound_mgr_codec_param_t *param)
155 {
156         int count = 0;
157         mmsound_codec_info_t info;
158         mmsound_codec_param_t codec_param;
159         int err = MM_ERROR_NONE;
160         int errorcode = 0;
161         int need_asm_unregister = 0;
162
163         debug_enter("\n");
164
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);
168
169         for (count = 0; g_plugins[count].GetSupportTypes; count++) {
170                 /* Find codec */
171                 if (g_plugins[count].Parse(param->source, &info) == MM_ERROR_NONE)
172                         break;
173         }
174
175         debug_msg("Find plugin codec ::: [%d]\n", count);       /*The count num means codec type WAV, MP3 */
176
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;
180                 goto cleanup;
181         }
182
183         /* KeyTone */
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);
191                         }
192                         debug_msg("Key tone : Stop to Play !!!\n");
193                 }
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);
202                         }
203                         debug_msg("Key tone : Stop to Play !!!\n");
204                 }
205                 codec_param.keytone = param->keytone;
206         } else {
207                 debug_msg("Get New handle\n");
208                 codec_param.keytone = 0;
209         }
210
211         err = _MMSoundMgrCodecGetEmptySlot(slotid);
212         if (err != MM_ERROR_NONE) {
213                 debug_error("Empty g_slot is not found\n");
214                 goto cleanup;
215         }
216
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;
227
228         pthread_mutex_lock(&g_slot_mutex);
229         debug_msg("After Slot_mutex LOCK\n");
230
231         /* In case of KEYTONE */
232         if (param->keytone == 1)
233                 g_slots[*slotid].status = STATUS_KEYTONE;
234
235         /* In case of LOCALE */
236         if (param->keytone == 2) /* KeyTone */
237                 g_slots[*slotid].status = STATUS_LOCALE;                
238
239         /*
240          * Register ASM here
241          */
242
243         if(param->session_type != ASM_EVENT_CALL && param->session_type != ASM_EVENT_VIDEOCALL) {
244 #ifdef MURPHY
245                 if(!ASM_register_sound((int)param->param, &param->session_handle, param->session_type, ASM_STATE_PLAYING,
246                                                                 sound_codec_asm_callback, (void*)*slotid, ASM_RESOURCE_NONE, &errorcode))       {
247 #else
248                 if(!ASM_register_sound_ex((int)param->param, &param->session_handle, param->session_type, ASM_STATE_PLAYING,
249                                                                 sound_codec_asm_callback, (void*)*slotid, ASM_RESOURCE_NONE, &errorcode, __asm_process_message))        {
250 #endif
251                         debug_critical("ASM_register_sound() failed %d\n", errorcode);
252                         pthread_mutex_unlock(&g_slot_mutex);
253                         return MM_ERROR_POLICY_INTERNAL;
254                 }
255         }
256         //
257
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;
266         
267         debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
268
269
270
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;
279                 goto cleanup;
280         }
281
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;
287         }
288
289         pthread_mutex_unlock(&g_slot_mutex);
290         debug_msg("After Slot_mutex UNLOCK\n");
291
292 cleanup:
293         if(param->session_type != ASM_EVENT_CALL  && param->session_type != ASM_EVENT_VIDEOCALL && need_asm_unregister == 1) {
294 #ifdef MURPHY
295                 if(!ASM_unregister_sound(param->session_handle, param->session_type, &errorcode)) {
296 #else
297                 if(!ASM_unregister_sound_ex(param->session_handle, param->session_type, &errorcode,__asm_process_message)) {
298 #endif
299                         debug_error("Unregister sound failed 0x%X\n", errorcode);
300                         return MM_ERROR_POLICY_INTERNAL;
301                 }
302         }
303
304         debug_leave("\n");
305
306         return err;
307 }
308
309 #define DTMF_PLUGIN_COUNT 2
310 int MMSoundMgrCodecPlayDtmf(int *slotid, const mmsound_mgr_codec_param_t *param)
311 {
312         int count = 0;
313         int *codec_type;
314         mmsound_codec_info_t info;
315         mmsound_codec_param_t codec_param;
316         int err = MM_ERROR_NONE;
317         
318         debug_enter("\n");
319
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);
323         
324         for (count = 0; g_plugins[count].GetSupportTypes; count++) {
325                 /* Find codec */
326                 codec_type = g_plugins[count].GetSupportTypes();
327                 if(codec_type && (MM_SOUND_SUPPORTED_CODEC_DTMF == codec_type[0]))
328                         break;
329         }
330         
331         debug_msg("Find plugin codec ::: [%d]\n", count);       /*The count num means codec type DTMF */
332
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;
337                 goto cleanup;
338         }
339
340         debug_msg("Get New handle\n");
341         codec_param.keytone = 0;
342
343         err = _MMSoundMgrCodecGetEmptySlot(slotid);
344         if(err != MM_ERROR_NONE)
345         {
346                 debug_error("Empty g_slot is not found\n");
347                 goto cleanup;
348         }
349
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;
358
359         pthread_mutex_lock(&g_slot_mutex);
360         debug_msg("After Slot_mutex LOCK\n");
361         
362         //
363         /*
364          * Register ASM here
365          */
366         int errorcode = 0;
367         int need_asm_unregister = 0;
368
369         if(param->session_type != ASM_EVENT_CALL && param->session_type != ASM_EVENT_VIDEOCALL) {
370 #ifdef MURPHY
371                 if(!ASM_register_sound((int)param->param, &param->session_handle, param->session_type, ASM_STATE_PLAYING,
372                                                                 sound_codec_asm_callback, (void*)*slotid, ASM_RESOURCE_NONE, &errorcode)) {
373 #else
374                 if(!ASM_register_sound_ex((int)param->param, &param->session_handle, param->session_type, ASM_STATE_PLAYING,
375                                                                 sound_codec_asm_callback, (void*)*slotid, ASM_RESOURCE_NONE, &errorcode, __asm_process_message)) {
376 #endif
377                         debug_critical("ASM_register_sound() failed %d\n", errorcode);
378                         pthread_mutex_unlock(&g_slot_mutex);
379                         return MM_ERROR_POLICY_INTERNAL;
380                 }
381         }
382
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;
388         
389         debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
390
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;
399                 goto cleanup;
400         }
401
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;
407         }
408         
409         pthread_mutex_unlock(&g_slot_mutex);
410
411         debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
412         debug_msg("After Slot_mutex UNLOCK\n")
413
414 cleanup:                
415         debug_leave("\n");
416
417         return err;
418 }
419
420
421 int MMSoundMgrCodecStop(const int slotid)
422 {
423         int err = MM_ERROR_NONE;
424
425         debug_enter("(Slotid : [%d])\n", slotid);
426
427         if (slotid < 0 || MANAGER_HANDLE_MAX <= slotid) {
428                 return MM_ERROR_INVALID_ARGUMENT;
429         }
430
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);
436                 goto cleanup;
437         }
438         debug_msg("Found slot, Slotid [%d] State [%d]\n", slotid, g_slots[slotid].status);
439
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);
443         }
444         debug_msg("Found slot, Slotid [%d] State [%d]\n", slotid, g_slots[slotid].status);
445 cleanup:
446         pthread_mutex_unlock(&g_slot_mutex);
447         debug_msg("After Slot_mutex UNLOCK\n");
448         debug_leave("(err : 0x%08X)\n", err);
449
450         return err;
451 }
452
453 static int _MMSoundMgrCodecStopCallback(int param)
454 {
455         int err = MM_ERROR_NONE;
456
457         debug_enter("(Slot : %d)\n", param);
458
459         pthread_mutex_lock(&g_slot_mutex);
460         debug_msg("[CODEC MGR] Slot_mutex lock done\n");
461
462
463         /*
464          * Unregister ASM here
465          */
466
467         int errorcode = 0;
468
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");
471 #ifdef MURPHY
472                 if(!ASM_unregister_sound(g_slots[param].session_handle, g_slots[param].session_type, &errorcode)) {
473 #else
474                 if(!ASM_unregister_sound_ex(g_slots[param].session_handle, g_slots[param].session_type, &errorcode, __asm_process_message)) {
475 #endif
476                         debug_error("[CODEC MGR] Unregister sound failed 0x%X\n", errorcode);
477                 }
478         }
479
480
481
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 */
487         }
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);
491         if (err < 0 ) {
492                 debug_critical("[CODEC MGR] Fail to destroy slot number : [%d] err [0x%x]\n", param, err);
493         }
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");
498
499         return err;
500 }
501
502 static int _MMSoundMgrCodecFindKeytoneSlot(int *slotid)
503 {
504         int count = 0;
505         int err = MM_ERROR_NONE;
506
507         debug_enter("\n");
508
509         pthread_mutex_lock(&g_slot_mutex);
510         debug_warning("After Slot_mutex LOCK\n");
511
512         for (count = SOUND_SLOT_START; count < MANAGER_HANDLE_MAX ; count++) {
513                 if (g_slots[count].status == STATUS_KEYTONE) {
514                         break;
515                 }
516         }
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);
521                 *slotid = count;
522                 err =  MM_ERROR_NONE;
523         } else {
524                 debug_warning("Handle is full handle [KEY TONE] : [%d]\n", count);
525                 err =  MM_ERROR_SOUND_INTERNAL;
526         }
527
528         debug_leave("\n");
529
530         return err;
531 }
532
533 static int _MMSoundMgrCodecFindLocaleSlot(int *slotid)
534 {
535         int count = 0;
536         int err = MM_ERROR_NONE;
537
538         debug_enter("\n");
539
540         pthread_mutex_lock(&g_slot_mutex);
541         debug_warning("After Slot_mutex LOCK\n");
542
543         for (count = SOUND_SLOT_START; count < MANAGER_HANDLE_MAX ; count++) {
544                 if (g_slots[count].status == STATUS_LOCALE) {
545                         break;
546                 }
547         }
548         pthread_mutex_unlock(&g_slot_mutex);
549
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);
553                 *slotid = count;
554                 err =  MM_ERROR_NONE;
555         } else {
556                 debug_warning("Handle is full handle [KEY TONE] \n");
557                 err =  MM_ERROR_SOUND_INTERNAL;
558         }
559
560         debug_leave("\n");
561
562         return err;
563 }
564
565 static int _MMSoundMgrCodecGetEmptySlot(int *slot)
566 {
567         int count = 0;
568         int err = MM_ERROR_NONE;
569
570         debug_enter("\n");
571         debug_msg("Codec slot ID : [%d]\n", *slot);
572         pthread_mutex_lock(&g_slot_mutex);
573         debug_msg("After Slot_mutex LOCK\n");
574
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;
578                         break;
579                 }
580         }
581         pthread_mutex_unlock(&g_slot_mutex);
582         debug_msg("After Slot_mutex UNLOCK\n");
583
584         if (count < MANAGER_HANDLE_MAX) {
585                 debug_msg("New handle allocated (codec slot ID : [%d])\n", count);
586                 *slot = count;
587                 err =  MM_ERROR_NONE;
588         } else {
589                 debug_warning("Handle is full handle : [%d]\n", count);
590                 *slot = -1;
591                 /* Temporal code for reset */
592                 while(count--) {
593                         g_slots[count].status = STATUS_IDLE;
594                 }
595                 err =  MM_ERROR_SOUND_INTERNAL;
596         }
597
598         debug_leave("\n");
599
600         return err;
601 }
602
603 static int _MMSoundMgrCodecRegisterInterface(MMSoundPluginType *plugin)
604 {
605         int err = MM_ERROR_NONE;
606         int count = 0;
607         void *getinterface = NULL;
608
609         debug_enter("\n");
610
611         /* find emptry slot */
612         for (count = 0; count < MM_SOUND_SUPPORTED_CODEC_NUM; count++) {
613                 if (g_plugins[count].GetSupportTypes == NULL)
614                         break;
615         }
616
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;
620         }
621         
622         debug_msg("Empty slot find : %d\n", count);
623
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);
627                 goto cleanup;
628         }
629         debug_msg("Getinterface name : %s\n", (char*)getinterface );
630
631         err = MMSoundPlugCodecCastGetInterface(getinterface)(&g_plugins[count]);
632         if (err != MM_ERROR_NONE) {
633                 debug_error("Get interface fail : %x\n", err);
634
635 cleanup: 
636                 /* If error occur, clean interface */
637                 memset(&g_plugins[count], 0, sizeof(mmsound_codec_interface_t));
638         } else {
639                 if (g_plugins[count].SetThreadPool)
640                         g_plugins[count].SetThreadPool(MMSoundThreadPoolRun);
641         }
642
643         debug_leave("\n");
644
645         return err;
646 }
647