Merge "Removed unused result variable from sound_codec_asm_callback" into tizen
[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         ASM_cb_result_t cb_res = ASM_CB_RES_NONE;
83
84         debug_log("Got audio session callback msg for session_handle %d\n", handle);
85
86         switch(command)
87         {
88         case ASM_COMMAND_STOP:
89         case ASM_COMMAND_PAUSE:
90                 debug_log("Got msg from asm to Stop or Pause %d\n", command);
91                 MMSoundMgrCodecStop(slotid);
92                 cb_res = ASM_CB_RES_STOP;
93                 break;
94         case ASM_COMMAND_RESUME:
95         case ASM_COMMAND_PLAY:
96                 debug_log("Got msg from asm to Play or Resume %d\n", command);
97                 cb_res = ASM_CB_RES_NONE;;
98         default:
99                 break;
100         }
101         return cb_res;
102 }
103
104
105 int MMSoundMgrCodecInit(const char *targetdir)
106 {
107         int loop = 0;
108         int count = 0;
109
110         debug_enter("\n");
111
112         memset (g_slots, 0, sizeof(g_slots));
113
114         if(pthread_mutex_init(&g_slot_mutex, NULL)) {
115                 debug_error("pthread_mutex_init failed [%s][%d]\n", __func__, __LINE__);
116                 return MM_ERROR_SOUND_INTERNAL;
117         }
118
119         for (count = 0; count < MANAGER_HANDLE_MAX; count++) {
120                 g_slots[count].status = STATUS_IDLE;
121                 g_slots[count].plughandle = -1;
122         }
123
124         if (g_codec_plugins) {
125                 debug_warning("Please Check Init twice\n");
126                 MMSoundPluginRelease(g_codec_plugins);
127         }
128
129         MMSoundPluginScan(targetdir, MM_SOUND_PLUGIN_TYPE_CODEC, &g_codec_plugins);
130
131         while (g_codec_plugins[loop].type != MM_SOUND_PLUGIN_TYPE_NONE) {
132                 _MMSoundMgrCodecRegisterInterface(&g_codec_plugins[loop++]);
133         }
134
135         debug_leave("\n");
136         return MM_ERROR_NONE;
137 }
138
139 int MMSoundMgrCodecFini(void)
140 {
141         debug_enter("\n");
142
143         memset(g_plugins, 0, sizeof(mmsound_codec_interface_t) * MM_SOUND_SUPPORTED_CODEC_NUM);
144         MMSoundPluginRelease(g_codec_plugins);
145         g_codec_plugins = NULL;
146         pthread_mutex_destroy(&g_slot_mutex);
147
148         debug_leave("\n");
149         return MM_ERROR_NONE;
150 }
151
152
153 int MMSoundMgrCodecPlay(int *slotid, const mmsound_mgr_codec_param_t *param)
154 {
155         int count = 0;
156         mmsound_codec_info_t info;
157         mmsound_codec_param_t codec_param;
158         int err = MM_ERROR_NONE;
159         int errorcode = 0;
160         int need_asm_unregister = 0;
161
162         debug_enter("\n");
163
164         debug_msg("DTMF : [%d]\n",param->tone);
165         debug_msg("Repeat : [%d]\n",param->repeat_count);
166         debug_msg("Volume : [%f]\n",param->volume);
167
168         for (count = 0; g_plugins[count].GetSupportTypes; count++) {
169                 /* Find codec */
170                 if (g_plugins[count].Parse(param->source, &info) == MM_ERROR_NONE)
171                         break;
172         }
173
174         debug_msg("Find plugin codec ::: [%d]\n", count);       /*The count num means codec type WAV, MP3 */
175
176         if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
177                 debug_error("unsupported file type %d\n", count);
178                 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
179                 goto cleanup;
180         }
181
182         /* KeyTone */
183         if (param->keytone == 1) {
184                 /* Find keytone slot */
185                 err = _MMSoundMgrCodecFindKeytoneSlot(slotid);
186                 /* Not First connect */
187                 if (err == MM_ERROR_NONE) {
188                         if(g_slots[*slotid].status != STATUS_IDLE) {
189                                 MMSoundMgrCodecStop(*slotid);
190                         }
191                         debug_msg("Key tone : Stop to Play !!!\n");
192                 }
193                 codec_param.keytone = param->keytone;
194         } else if (param->keytone == 2) {
195                 /* Find keytone slot */
196                 err = _MMSoundMgrCodecFindLocaleSlot(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 {
206                 debug_msg("Get New handle\n");
207                 codec_param.keytone = 0;
208         }
209
210         err = _MMSoundMgrCodecGetEmptySlot(slotid);
211         if (err != MM_ERROR_NONE) {
212                 debug_error("Empty g_slot is not found\n");
213                 goto cleanup;
214         }
215
216         codec_param.tone = param->tone;
217         codec_param.volume_config = param->volume_config;
218         codec_param.repeat_count = param->repeat_count;
219         codec_param.volume = param->volume;
220         codec_param.source = param->source;
221         codec_param.priority = param->priority;
222         codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
223         codec_param.param = *slotid;
224         codec_param.pid = (int)param->param;
225         codec_param.handle_route = param->handle_route;
226
227         pthread_mutex_lock(&g_slot_mutex);
228         debug_msg("After Slot_mutex LOCK\n");
229
230         /* In case of KEYTONE */
231         if (param->keytone == 1)
232                 g_slots[*slotid].status = STATUS_KEYTONE;
233
234         /* In case of LOCALE */
235         if (param->keytone == 2) /* KeyTone */
236                 g_slots[*slotid].status = STATUS_LOCALE;                
237
238         /*
239          * Register ASM here
240          */
241
242         if(param->session_type != ASM_EVENT_CALL && param->session_type != ASM_EVENT_VIDEOCALL) {
243 #ifdef MURPHY
244                 if(!ASM_register_sound((int)param->param, &param->session_handle, param->session_type, ASM_STATE_PLAYING,
245                                                                 sound_codec_asm_callback, (void*)*slotid, ASM_RESOURCE_NONE, &errorcode))       {
246 #else
247                 if(!ASM_register_sound_ex((int)param->param, &param->session_handle, param->session_type, ASM_STATE_PLAYING,
248                                                                 sound_codec_asm_callback, (void*)*slotid, ASM_RESOURCE_NONE, &errorcode, __asm_process_message))        {
249 #endif
250                         debug_critical("ASM_register_sound() failed %d\n", errorcode);
251                         pthread_mutex_unlock(&g_slot_mutex);
252                         return MM_ERROR_POLICY_INTERNAL;
253                 }
254         }
255         //
256
257         /* Codec id WAV or MP3 */
258         g_slots[*slotid].pluginid = count;
259         g_slots[*slotid].callback = param->callback;
260         g_slots[*slotid].msgcallback = param->msgcallback;
261         g_slots[*slotid].msgdata = param->msgdata;
262         g_slots[*slotid].param    = param->param;               /* This arg is used callback data */
263         g_slots[*slotid].session_type = param->session_type;
264         g_slots[*slotid].session_handle = param->session_handle;
265         
266         debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
267
268
269
270         err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
271         debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
272         if (err != MM_ERROR_NONE) {
273                 debug_error("Plugin create fail : 0x%08X\n", err);
274                 g_slots[*slotid].status = STATUS_IDLE;
275                 pthread_mutex_unlock(&g_slot_mutex);
276                 debug_warning("After Slot_mutex UNLOCK\n");
277                 need_asm_unregister = 1;
278                 goto cleanup;
279         }
280
281         err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
282         if (err != MM_ERROR_NONE) {
283                 debug_error("Fail to play : 0x%08X\n", err);
284                 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
285                 need_asm_unregister = 1;
286         }
287
288         pthread_mutex_unlock(&g_slot_mutex);
289         debug_msg("After Slot_mutex UNLOCK\n");
290
291 cleanup:
292         if(param->session_type != ASM_EVENT_CALL  && param->session_type != ASM_EVENT_VIDEOCALL && need_asm_unregister == 1) {
293 #ifdef MURPHY
294                 if(!ASM_unregister_sound(param->session_handle, param->session_type, &errorcode)) {
295 #else
296                 if(!ASM_unregister_sound_ex(param->session_handle, param->session_type, &errorcode,__asm_process_message)) {
297 #endif
298                         debug_error("Unregister sound failed 0x%X\n", errorcode);
299                         return MM_ERROR_POLICY_INTERNAL;
300                 }
301         }
302
303         debug_leave("\n");
304
305         return err;
306 }
307
308 #define DTMF_PLUGIN_COUNT 2
309 int MMSoundMgrCodecPlayDtmf(int *slotid, const mmsound_mgr_codec_param_t *param)
310 {
311         int count = 0;
312         int *codec_type;
313         mmsound_codec_info_t info;
314         mmsound_codec_param_t codec_param;
315         int err = MM_ERROR_NONE;
316         
317         debug_enter("\n");
318
319         debug_msg("DTMF : [%d]\n",param->tone);
320         debug_msg("Repeat : [%d]\n",param->repeat_count);
321         debug_msg("Volume : [%f]\n",param->volume);
322         
323         for (count = 0; g_plugins[count].GetSupportTypes; count++) {
324                 /* Find codec */
325                 codec_type = g_plugins[count].GetSupportTypes();
326                 if(codec_type && (MM_SOUND_SUPPORTED_CODEC_DTMF == codec_type[0]))
327                         break;
328         }
329         
330         debug_msg("Find plugin codec ::: [%d]\n", count);       /*The count num means codec type DTMF */
331
332         if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
333                 debug_error("unsupported file type %d\n", count);
334                 printf("unsupported file type %d\n", count);
335                 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
336                 goto cleanup;
337         }
338
339         debug_msg("Get New handle\n");
340         codec_param.keytone = 0;
341
342         err = _MMSoundMgrCodecGetEmptySlot(slotid);
343         if(err != MM_ERROR_NONE)
344         {
345                 debug_error("Empty g_slot is not found\n");
346                 goto cleanup;
347         }
348
349         codec_param.tone = param->tone;
350         codec_param.priority = 0;
351         codec_param.volume_config = param->volume_config;
352         codec_param.repeat_count = param->repeat_count;
353         codec_param.volume = param->volume;
354         codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
355         codec_param.param = *slotid;
356         codec_param.pid = (int)param->param;
357
358         pthread_mutex_lock(&g_slot_mutex);
359         debug_msg("After Slot_mutex LOCK\n");
360         
361         //
362         /*
363          * Register ASM here
364          */
365         int errorcode = 0;
366         int need_asm_unregister = 0;
367
368         if(param->session_type != ASM_EVENT_CALL && param->session_type != ASM_EVENT_VIDEOCALL) {
369 #ifdef MURPHY
370                 if(!ASM_register_sound((int)param->param, &param->session_handle, param->session_type, ASM_STATE_PLAYING,
371                                                                 sound_codec_asm_callback, (void*)*slotid, ASM_RESOURCE_NONE, &errorcode)) {
372 #else
373                 if(!ASM_register_sound_ex((int)param->param, &param->session_handle, param->session_type, ASM_STATE_PLAYING,
374                                                                 sound_codec_asm_callback, (void*)*slotid, ASM_RESOURCE_NONE, &errorcode, __asm_process_message)) {
375 #endif
376                         debug_critical("ASM_register_sound() failed %d\n", errorcode);
377                         pthread_mutex_unlock(&g_slot_mutex);
378                         return MM_ERROR_POLICY_INTERNAL;
379                 }
380         }
381
382         g_slots[*slotid].pluginid = count;
383         g_slots[*slotid].callback = param->callback;
384         g_slots[*slotid].param    = param->param;               /* This arg is used callback data */
385         g_slots[*slotid].session_type = param->session_type;
386         g_slots[*slotid].session_handle = param->session_handle;
387         
388         debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
389
390         err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
391         debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
392         if (err != MM_ERROR_NONE) {
393                 debug_error("Plugin create fail : 0x%08X\n", err);
394                 g_slots[*slotid].status = STATUS_IDLE;
395                 pthread_mutex_unlock(&g_slot_mutex);
396                 debug_warning("After Slot_mutex UNLOCK\n");
397                 need_asm_unregister = 1;
398                 goto cleanup;
399         }
400
401         err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
402         if (err != MM_ERROR_NONE) {
403                 debug_error("Fail to play : 0x%08X\n", err);
404                 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
405                 need_asm_unregister = 1;
406         }
407         
408         pthread_mutex_unlock(&g_slot_mutex);
409
410         debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
411         debug_msg("After Slot_mutex UNLOCK\n")
412
413 cleanup:                
414         debug_leave("\n");
415
416         return err;
417 }
418
419
420 int MMSoundMgrCodecStop(const int slotid)
421 {
422         int err = MM_ERROR_NONE;
423
424         debug_enter("(Slotid : [%d])\n", slotid);
425
426         if (slotid < 0 || MANAGER_HANDLE_MAX <= slotid) {
427                 return MM_ERROR_INVALID_ARGUMENT;
428         }
429
430         pthread_mutex_lock (&g_slot_mutex);
431         debug_msg("After Slot_mutex LOCK\n");
432         if (g_slots[slotid].status == STATUS_IDLE) {
433                 err = MM_ERROR_SOUND_INVALID_STATE;
434                 debug_warning("The playing slots is not found, Slot ID : [%d]\n", slotid);
435                 goto cleanup;
436         }
437         debug_msg("Found slot, Slotid [%d] State [%d]\n", slotid, g_slots[slotid].status);
438
439         err = g_plugins[g_slots[slotid].pluginid].Stop(g_slots[slotid].plughandle);
440         if (err != MM_ERROR_NONE) {
441                 debug_error("Fail to STOP Code : 0x%08X\n", err);
442         }
443         debug_msg("Found slot, Slotid [%d] State [%d]\n", slotid, g_slots[slotid].status);
444 cleanup:
445         pthread_mutex_unlock(&g_slot_mutex);
446         debug_msg("After Slot_mutex UNLOCK\n");
447         debug_leave("(err : 0x%08X)\n", err);
448
449         return err;
450 }
451
452 static int _MMSoundMgrCodecStopCallback(int param)
453 {
454         int err = MM_ERROR_NONE;
455
456         debug_enter("(Slot : %d)\n", param);
457
458         pthread_mutex_lock(&g_slot_mutex);
459         debug_msg("[CODEC MGR] Slot_mutex lock done\n");
460
461
462         /*
463          * Unregister ASM here
464          */
465
466         int errorcode = 0;
467
468         if(g_slots[param].session_type != ASM_EVENT_CALL && g_slots[param].session_type != ASM_EVENT_VIDEOCALL) {
469                 debug_msg("[CODEC MGR] ASM unregister\n");
470 #ifdef MURPHY
471                 if(!ASM_unregister_sound(g_slots[param].session_handle, g_slots[param].session_type, &errorcode)) {
472 #else
473                 if(!ASM_unregister_sound_ex(g_slots[param].session_handle, g_slots[param].session_type, &errorcode, __asm_process_message)) {
474 #endif
475                         debug_error("[CODEC MGR] Unregister sound failed 0x%X\n", errorcode);
476                 }
477         }
478
479
480
481         if (g_slots[param].msgcallback) {
482                 debug_msg("[CODEC MGR] msgcallback : %p\n", g_slots[param].msgcallback);
483                 debug_msg("[CODEC MGR] msg data : %p\n", g_slots[param].msgdata);
484                 debug_msg("[CODEC MGR] mgr codec callback : %p\n", g_slots[param].callback);
485                 g_slots[param].callback((int)g_slots[param].param, g_slots[param].msgcallback, g_slots[param].msgdata);         /*param means client msg_type */
486         }
487         debug_msg("Client callback msg_type (instance) : [%d]\n", (int)g_slots[param].param);
488         debug_msg("Handle allocated handle : [0x%08X]\n", g_slots[param].plughandle);
489         err = g_plugins[g_slots[param].pluginid].Destroy(g_slots[param].plughandle);
490         if (err < 0 ) {
491                 debug_critical("[CODEC MGR] Fail to destroy slot number : [%d] err [0x%x]\n", param, err);
492         }
493         memset(&g_slots[param], 0, sizeof(__mmsound_mgr_codec_handle_t));
494         g_slots[param].status = STATUS_IDLE;
495         pthread_mutex_unlock(&g_slot_mutex);
496         debug_msg("[CODEC MGR] Slot_mutex done\n");
497
498         return err;
499 }
500
501 static int _MMSoundMgrCodecFindKeytoneSlot(int *slotid)
502 {
503         int count = 0;
504         int err = MM_ERROR_NONE;
505
506         debug_enter("\n");
507
508         pthread_mutex_lock(&g_slot_mutex);
509         debug_warning("After Slot_mutex LOCK\n");
510
511         for (count = SOUND_SLOT_START; count < MANAGER_HANDLE_MAX ; count++) {
512                 if (g_slots[count].status == STATUS_KEYTONE) {
513                         break;
514                 }
515         }
516         pthread_mutex_unlock(&g_slot_mutex);
517         debug_warning("After Slot_mutex UNLOCK\n");
518         if (count < MANAGER_HANDLE_MAX) {
519                 debug_msg("Found keytone handle allocated (Slot : [%d])\n", count);
520                 *slotid = count;
521                 err =  MM_ERROR_NONE;
522         } else {
523                 debug_warning("Handle is full handle [KEY TONE] : [%d]\n", count);
524                 err =  MM_ERROR_SOUND_INTERNAL;
525         }
526
527         debug_leave("\n");
528
529         return err;
530 }
531
532 static int _MMSoundMgrCodecFindLocaleSlot(int *slotid)
533 {
534         int count = 0;
535         int err = MM_ERROR_NONE;
536
537         debug_enter("\n");
538
539         pthread_mutex_lock(&g_slot_mutex);
540         debug_warning("After Slot_mutex LOCK\n");
541
542         for (count = SOUND_SLOT_START; count < MANAGER_HANDLE_MAX ; count++) {
543                 if (g_slots[count].status == STATUS_LOCALE) {
544                         break;
545                 }
546         }
547         pthread_mutex_unlock(&g_slot_mutex);
548
549         debug_warning("After Slot_mutex UNLOCK\n");
550         if (count < MANAGER_HANDLE_MAX) {
551                 debug_msg("Found locale handle allocated (Slot : [%d])\n", count);
552                 *slotid = count;
553                 err =  MM_ERROR_NONE;
554         } else {
555                 debug_warning("Handle is full handle [KEY TONE] \n");
556                 err =  MM_ERROR_SOUND_INTERNAL;
557         }
558
559         debug_leave("\n");
560
561         return err;
562 }
563
564 static int _MMSoundMgrCodecGetEmptySlot(int *slot)
565 {
566         int count = 0;
567         int err = MM_ERROR_NONE;
568
569         debug_enter("\n");
570         debug_msg("Codec slot ID : [%d]\n", *slot);
571         pthread_mutex_lock(&g_slot_mutex);
572         debug_msg("After Slot_mutex LOCK\n");
573
574         for (count = SOUND_SLOT_START; count < MANAGER_HANDLE_MAX ; count++) {
575                 if (g_slots[count].status == STATUS_IDLE) {
576                         g_slots[count].status = STATUS_SOUND;
577                         break;
578                 }
579         }
580         pthread_mutex_unlock(&g_slot_mutex);
581         debug_msg("After Slot_mutex UNLOCK\n");
582
583         if (count < MANAGER_HANDLE_MAX) {
584                 debug_msg("New handle allocated (codec slot ID : [%d])\n", count);
585                 *slot = count;
586                 err =  MM_ERROR_NONE;
587         } else {
588                 debug_warning("Handle is full handle : [%d]\n", count);
589                 *slot = -1;
590                 /* Temporal code for reset */
591                 while(count--) {
592                         g_slots[count].status = STATUS_IDLE;
593                 }
594                 err =  MM_ERROR_SOUND_INTERNAL;
595         }
596
597         debug_leave("\n");
598
599         return err;
600 }
601
602 static int _MMSoundMgrCodecRegisterInterface(MMSoundPluginType *plugin)
603 {
604         int err = MM_ERROR_NONE;
605         int count = 0;
606         void *getinterface = NULL;
607
608         debug_enter("\n");
609
610         /* find emptry slot */
611         for (count = 0; count < MM_SOUND_SUPPORTED_CODEC_NUM; count++) {
612                 if (g_plugins[count].GetSupportTypes == NULL)
613                         break;
614         }
615
616         if (count == MM_SOUND_SUPPORTED_CODEC_NUM) {
617                 debug_critical("The plugin support type is not valid\n");
618                 return MM_ERROR_COMMON_OUT_OF_RANGE;
619         }
620         
621         debug_msg("Empty slot find : %d\n", count);
622
623         err = MMSoundPluginGetSymbol(plugin, CODEC_GET_INTERFACE_FUNC_NAME, &getinterface);
624         if (err != MM_ERROR_NONE) {
625                 debug_error("Get Symbol CODEC_GET_INTERFACE_FUNC_NAME is fail : %x\n", err);
626                 goto cleanup;
627         }
628         debug_msg("Getinterface name : %s\n", (char*)getinterface );
629
630         err = MMSoundPlugCodecCastGetInterface(getinterface)(&g_plugins[count]);
631         if (err != MM_ERROR_NONE) {
632                 debug_error("Get interface fail : %x\n", err);
633
634 cleanup: 
635                 /* If error occur, clean interface */
636                 memset(&g_plugins[count], 0, sizeof(mmsound_codec_interface_t));
637         } else {
638                 if (g_plugins[count].SetThreadPool)
639                         g_plugins[count].SetThreadPool(MMSoundThreadPoolRun);
640         }
641
642         debug_leave("\n");
643
644         return err;
645 }
646