Let's start tizen audio 3.0
[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         codec_param.stream_index = param->stream_index;
241         strncpy(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
242         pthread_mutex_lock(&g_slot_mutex);
243 #ifdef DEBUG_DETAIL
244         debug_msg("After Slot_mutex LOCK\n");
245 #endif
246
247         /* In case of KEYTONE */
248         if (param->keytone == 1)
249                 g_slots[*slotid].status = STATUS_KEYTONE;
250
251         /* In case of LOCALE */
252         if (param->keytone == 2) /* KeyTone */
253                 g_slots[*slotid].status = STATUS_LOCALE;
254
255         /*
256          * Register ASM here
257          */
258         if (param->session_type != ASM_EVENT_CALL &&
259                 param->session_type != ASM_EVENT_VIDEOCALL &&
260                 param->session_type != ASM_EVENT_VOIP &&
261                 param->session_type != ASM_EVENT_VOICE_RECOGNITION &&
262                 param->priority != HANDLE_PRIORITY_SOLO &&
263                 param->enable_session) {
264                 if(!ASM_register_sound_ex((int)param->param, (int *)(&param->session_handle), param->session_type, ASM_STATE_NONE,
265                                                                 sound_codec_asm_callback, (void*)*slotid, ASM_RESOURCE_NONE, &errorcode, __asm_process_message)) {
266                         debug_critical("ASM_register_sound_ex() failed 0x%X\n", errorcode);
267                         pthread_mutex_unlock(&g_slot_mutex);
268                         return MM_ERROR_POLICY_INTERNAL;
269                 }
270                 if(param->session_options) {
271                         if(!ASM_set_session_option(param->session_handle, param->session_options, &errorcode)) {
272                                 debug_error("ASM_set_session_option() failed 0x%x\n", errorcode);
273                         }
274                 }
275                 if(!ASM_set_sound_state_ex(param->session_handle, param->session_type, ASM_STATE_PLAYING, ASM_RESOURCE_NONE, &errorcode, __asm_process_message)) {
276                         debug_critical("ASM_set_sound_state_ex() failed 0x%X\n", errorcode);
277                         pthread_mutex_unlock(&g_slot_mutex);
278                         if(!ASM_unregister_sound_ex(param->session_handle, param->session_type, &errorcode,__asm_process_message)) {
279                                 debug_error("ASM_unregister_sound_ex() failed 0x%X\n", errorcode);
280                         }
281                         return MM_ERROR_POLICY_INTERNAL;
282                 }
283         }
284         //
285
286         /* Codec id WAV or MP3 */
287         g_slots[*slotid].pluginid = count;
288         g_slots[*slotid].param    = param->param;               /* This arg is used callback data */
289         g_slots[*slotid].session_type = param->session_type;
290         g_slots[*slotid].session_options = param->session_options;
291         g_slots[*slotid].session_handle = param->session_handle;
292         g_slots[*slotid].enable_session = true;
293
294         debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
295
296         err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
297         debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
298         if (err != MM_ERROR_NONE) {
299                 debug_error("Plugin create fail : 0x%08X\n", err);
300                 g_slots[*slotid].status = STATUS_IDLE;
301                 pthread_mutex_unlock(&g_slot_mutex);
302                 debug_warning("After Slot_mutex UNLOCK\n");
303                 if (param->session_handle) {
304                         need_asm_unregister = 1;
305                 }
306                 goto cleanup;
307         }
308
309         err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
310         if (err != MM_ERROR_NONE) {
311                 debug_error("Fail to play : 0x%08X\n", err);
312                 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
313                 if (param->session_handle) {
314                         need_asm_unregister = 1;
315                 }
316         }
317
318         pthread_mutex_unlock(&g_slot_mutex);
319 #ifdef DEBUG_DETAIL
320         debug_msg("After Slot_mutex UNLOCK\n");
321 #endif
322
323 cleanup:
324         if(param->session_type != ASM_EVENT_CALL &&
325                 param->session_type != ASM_EVENT_VIDEOCALL &&
326                 param->session_type != ASM_EVENT_VOIP &&
327                 param->session_type != ASM_EVENT_VOICE_RECOGNITION &&
328                 param->enable_session &&
329                 need_asm_unregister == 1) {
330                 if(!ASM_set_sound_state_ex(param->session_handle, param->session_type, ASM_STATE_STOP, ASM_RESOURCE_NONE, &errorcode, __asm_process_message)) {
331                         debug_critical("ASM_set_sound_state_ex() failed 0x%X\n", errorcode);
332                 }
333                 if(!ASM_unregister_sound_ex(param->session_handle, param->session_type, &errorcode,__asm_process_message)) {
334                         debug_error("ASM_unregister_sound_ex() failed 0x%X\n", errorcode);
335                         return MM_ERROR_POLICY_INTERNAL;
336                 }
337         }
338
339 #ifdef DEBUG_DETAIL
340         debug_leave("\n");
341 #endif
342
343         return err;
344 }
345
346 int MMSoundMgrCodecPlayWithStreamInfo(int *slotid, const mmsound_mgr_codec_param_t *param)
347 {
348         int count = 0;
349         mmsound_codec_info_t info;
350         mmsound_codec_param_t codec_param;
351         int err = MM_ERROR_NONE;
352         int errorcode = 0;
353
354 #ifdef DEBUG_DETAIL
355         debug_enter("\n");
356 #endif
357
358         for (count = 0; g_plugins[count].GetSupportTypes; count++) {
359                 /* Find codec */
360                 if (g_plugins[count].Parse(param->source, &info) == MM_ERROR_NONE)
361                         break;
362         }
363
364         /*The count num means codec type WAV, MP3 */
365         debug_msg("Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->repeat_count, param->volume, count);
366
367         if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
368                 debug_error("unsupported file type %d\n", count);
369                 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
370                 goto cleanup;
371         }
372
373         err = _MMSoundMgrCodecGetEmptySlot(slotid);
374         if (err != MM_ERROR_NONE) {
375                 debug_error("Empty g_slot is not found\n");
376                 goto cleanup;
377         }
378
379         codec_param.volume_config = -1; //setting volume config to -1 since using stream info instead of volume type
380         codec_param.repeat_count = param->repeat_count;
381         codec_param.volume = param->volume;
382         codec_param.source = param->source;
383         codec_param.priority = param->priority;
384         codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
385         codec_param.param = *slotid;
386         codec_param.pid = (int)param->param;
387         codec_param.handle_route = param->handle_route;
388         codec_param.codec_wave_mutex = &codec_wave_mutex;
389         codec_param.stream_index = param->stream_index;
390         strncpy(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
391         pthread_mutex_lock(&g_slot_mutex);
392 #ifdef DEBUG_DETAIL
393         debug_msg("After Slot_mutex LOCK\n");
394 #endif
395
396         /* Codec id WAV or MP3 */
397         g_slots[*slotid].pluginid = count;
398         g_slots[*slotid].param    = param->param;               /* This arg is used callback data */
399
400         debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
401
402         err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
403         debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
404         if (err != MM_ERROR_NONE) {
405                 debug_error("Plugin create fail : 0x%08X\n", err);
406                 g_slots[*slotid].status = STATUS_IDLE;
407                 pthread_mutex_unlock(&g_slot_mutex);
408                 debug_warning("After Slot_mutex UNLOCK\n");
409                 goto cleanup;
410         }
411
412         err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
413         if (err != MM_ERROR_NONE) {
414                 debug_error("Fail to play : 0x%08X\n", err);
415                 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
416         }
417
418         pthread_mutex_unlock(&g_slot_mutex);
419 #ifdef DEBUG_DETAIL
420         debug_msg("After Slot_mutex UNLOCK\n");
421 #endif
422
423 cleanup:
424
425 #ifdef DEBUG_DETAIL
426         debug_leave("\n");
427 #endif
428
429         return err;
430
431 }
432
433 #define DTMF_PLUGIN_COUNT 2
434 int MMSoundMgrCodecPlayDtmf(int *slotid, const mmsound_mgr_codec_param_t *param)
435 {
436         int count = 0;
437         int *codec_type;
438         mmsound_codec_info_t info;
439         mmsound_codec_param_t codec_param;
440         int err = MM_ERROR_NONE;
441         int errorcode = 0;
442         int need_asm_unregister = 0;
443
444 #ifdef DEBUG_DETAIL
445         debug_enter("\n");
446 #endif
447
448         for (count = 0; g_plugins[count].GetSupportTypes; count++) {
449                 /* Find codec */
450                 codec_type = g_plugins[count].GetSupportTypes();
451                 if(codec_type && (MM_SOUND_SUPPORTED_CODEC_DTMF == codec_type[0]))
452                         break;
453         }
454
455         /*The count num means codec type DTMF */
456         debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, count);
457
458         if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
459                 debug_error("unsupported file type %d\n", count);
460                 printf("unsupported file type %d\n", count);
461                 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
462                 goto cleanup;
463         }
464
465 #ifdef DEBUG_DETAIL
466         debug_msg("Get New handle\n");
467 #endif
468         codec_param.keytone = 0;
469
470         err = _MMSoundMgrCodecGetEmptySlot(slotid);
471         if(err != MM_ERROR_NONE)
472         {
473                 debug_error("Empty g_slot is not found\n");
474                 goto cleanup;
475         }
476
477         codec_param.tone = param->tone;
478         codec_param.priority = 0;
479         codec_param.volume_config = param->volume_config;
480         codec_param.repeat_count = param->repeat_count;
481         codec_param.volume = param->volume;
482         codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
483         codec_param.param = *slotid;
484         codec_param.pid = (int)param->param;
485         codec_param.stream_index = param->stream_index;
486         strncpy(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
487
488         pthread_mutex_lock(&g_slot_mutex);
489 #ifdef DEBUG_DETAIL
490         debug_msg("After Slot_mutex LOCK\n");
491 #endif
492
493         //
494         /*
495          * Register ASM here
496          */
497
498         if (param->session_type != ASM_EVENT_CALL &&
499                 param->session_type != ASM_EVENT_VIDEOCALL &&
500                 param->session_type != ASM_EVENT_VOIP &&
501                 param->session_type != ASM_EVENT_VOICE_RECOGNITION &&
502                 param->enable_session)  {
503                 if(!ASM_register_sound_ex((int)param->param, (int *)(&param->session_handle), param->session_type, ASM_STATE_NONE,
504                                                                 sound_codec_asm_callback, (void*)*slotid, ASM_RESOURCE_NONE, &errorcode, __asm_process_message)) {
505                         debug_critical("ASM_register_sound_ex() failed 0x%X\n", errorcode);
506                         pthread_mutex_unlock(&g_slot_mutex);
507                         return MM_ERROR_POLICY_INTERNAL;
508                 }
509                 if(param->session_options) {
510                         if(!ASM_set_session_option(param->session_handle, param->session_options, &errorcode)) {
511                                 debug_error("ASM_set_session_option() failed 0x%x\n", errorcode);
512                         }
513                 }
514                 if(!ASM_set_sound_state_ex(param->session_handle, param->session_type, ASM_STATE_PLAYING, ASM_RESOURCE_NONE, &errorcode, __asm_process_message)) {
515                         debug_critical("ASM_set_sound_state_ex() failed 0x%X\n", errorcode);
516                         pthread_mutex_unlock(&g_slot_mutex);
517                         if(!ASM_unregister_sound_ex(param->session_handle, param->session_type, &errorcode,__asm_process_message)) {
518                                 debug_error("ASM_unregister_sound_ex() failed 0x%X\n", errorcode);
519                         }
520                         return MM_ERROR_POLICY_INTERNAL;
521                 }
522         }
523
524         g_slots[*slotid].pluginid = count;
525         g_slots[*slotid].param    = param->param;               /* This arg is used callback data */
526         g_slots[*slotid].session_type = param->session_type;
527         g_slots[*slotid].session_options = param->session_options;
528         g_slots[*slotid].session_handle = param->session_handle;
529         g_slots[*slotid].enable_session = param->enable_session;
530
531 #ifdef DEBUG_DETAIL
532         debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
533 #endif
534
535         err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
536         debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
537         if (err != MM_ERROR_NONE) {
538                 debug_error("Plugin create fail : 0x%08X\n", err);
539                 g_slots[*slotid].status = STATUS_IDLE;
540                 pthread_mutex_unlock(&g_slot_mutex);
541                 debug_warning("After Slot_mutex UNLOCK\n");
542                 need_asm_unregister = 1;
543                 goto cleanup;
544         }
545
546         err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
547         if (err != MM_ERROR_NONE) {
548                 debug_error("Fail to play : 0x%08X\n", err);
549                 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
550                 need_asm_unregister = 1;
551         }
552
553         pthread_mutex_unlock(&g_slot_mutex);
554
555         debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
556 #ifdef DEBUG_DETAIL
557         debug_msg("After Slot_mutex UNLOCK\n")
558 #endif
559
560 cleanup:
561         if (param->session_type != ASM_EVENT_CALL &&
562                 param->session_type != ASM_EVENT_VIDEOCALL &&
563                 param->session_type != ASM_EVENT_VOIP &&
564                 param->session_type != ASM_EVENT_VOICE_RECOGNITION &&
565                 param->enable_session &&
566                 need_asm_unregister == 1) {
567                 if(!ASM_unregister_sound_ex(param->session_handle, param->session_type, &errorcode,__asm_process_message)) {
568                         debug_error("Unregister sound failed 0x%X\n", errorcode);
569                         return MM_ERROR_POLICY_INTERNAL;
570                 }
571         }
572
573 #ifdef DEBUG_DETAIL
574         debug_leave("\n");
575 #endif
576
577         return err;
578 }
579
580 MMSoundMgrCodecPlayDtmfWithStreamInfo(int *slotid, const mmsound_mgr_codec_param_t *param)
581 {
582         int count = 0;
583         int *codec_type;
584         mmsound_codec_info_t info;
585         mmsound_codec_param_t codec_param;
586         int err = MM_ERROR_NONE;
587         int errorcode = 0;
588
589 #ifdef DEBUG_DETAIL
590         debug_enter("\n");
591 #endif
592
593         for (count = 0; g_plugins[count].GetSupportTypes; count++) {
594                 /* Find codec */
595                 codec_type = g_plugins[count].GetSupportTypes();
596                 if(codec_type && (MM_SOUND_SUPPORTED_CODEC_DTMF == codec_type[0]))
597                         break;
598         }
599
600         /*The count num means codec type DTMF */
601         debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, count);
602
603         if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
604                 debug_error("unsupported file type %d\n", count);
605                 printf("unsupported file type %d\n", count);
606                 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
607                 goto cleanup;
608         }
609
610 #ifdef DEBUG_DETAIL
611         debug_msg("Get New handle\n");
612 #endif
613         codec_param.keytone = 0;
614
615         err = _MMSoundMgrCodecGetEmptySlot(slotid);
616         if(err != MM_ERROR_NONE)
617         {
618                 debug_error("Empty g_slot is not found\n");
619                 goto cleanup;
620         }
621
622         codec_param.tone = param->tone;
623         codec_param.priority = 0;
624         codec_param.repeat_count = param->repeat_count;
625         codec_param.volume = param->volume;
626         codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
627         codec_param.param = *slotid;
628         codec_param.pid = (int)param->param;
629         codec_param.volume_config = -1; //setting volume config to -1 since using stream info instead of volume type
630         codec_param.stream_index = param->stream_index;
631         strncpy(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
632
633         pthread_mutex_lock(&g_slot_mutex);
634 #ifdef DEBUG_DETAIL
635         debug_msg("After Slot_mutex LOCK\n");
636 #endif
637                 g_slots[*slotid].pluginid = count;
638                 g_slots[*slotid].param    = param->param;               /* This arg is used callback data */
639                 g_slots[*slotid].enable_session = param->enable_session;
640
641 #ifdef DEBUG_DETAIL
642                 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
643 #endif
644
645                 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
646                 debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
647                 if (err != MM_ERROR_NONE) {
648                         debug_error("Plugin create fail : 0x%08X\n", err);
649                         g_slots[*slotid].status = STATUS_IDLE;
650                         pthread_mutex_unlock(&g_slot_mutex);
651                         debug_warning("After Slot_mutex UNLOCK\n");
652                         goto cleanup;
653                 }
654
655                 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
656                 if (err != MM_ERROR_NONE) {
657                         debug_error("Fail to play : 0x%08X\n", err);
658                         g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
659                 }
660
661                 pthread_mutex_unlock(&g_slot_mutex);
662
663                 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
664 #ifdef DEBUG_DETAIL
665                 debug_msg("After Slot_mutex UNLOCK\n");
666 #endif
667
668         cleanup:
669 #ifdef DEBUG_DETAIL
670                 debug_leave("\n");
671 #endif
672
673                 return err;
674
675 }
676
677 int MMSoundMgrCodecStop(const int slotid)
678 {
679         int err = MM_ERROR_NONE;
680
681         debug_enter("(Slotid : [%d])\n", slotid);
682
683         if (slotid < 0 || MANAGER_HANDLE_MAX <= slotid) {
684                 return MM_ERROR_INVALID_ARGUMENT;
685         }
686
687         pthread_mutex_lock (&g_slot_mutex);
688 #ifdef DEBUG_DETAIL
689         debug_msg("After Slot_mutex LOCK\n");
690 #endif
691         if (g_slots[slotid].status == STATUS_IDLE) {
692                 err = MM_ERROR_SOUND_INVALID_STATE;
693                 debug_warning("The playing slots is not found, Slot ID : [%d]\n", slotid);
694                 goto cleanup;
695         }
696 #ifdef DEBUG_DETAIL
697         debug_msg("Found slot, Slotid [%d] State [%d]\n", slotid, g_slots[slotid].status);
698 #endif
699
700         err = g_plugins[g_slots[slotid].pluginid].Stop(g_slots[slotid].plughandle);
701         if (err != MM_ERROR_NONE) {
702                 debug_error("Fail to STOP Code : 0x%08X\n", err);
703         }
704         debug_msg("Found slot, Slotid [%d] State [%d]\n", slotid, g_slots[slotid].status);
705 cleanup:
706         pthread_mutex_unlock(&g_slot_mutex);
707 #ifdef DEBUG_DETAIL
708         debug_msg("After Slot_mutex UNLOCK\n");
709 #endif
710         debug_leave("(err : 0x%08X)\n", err);
711
712         return err;
713 }
714
715 static int _MMSoundMgrCodecStopCallback(int param)
716 {
717         int err = MM_ERROR_NONE;
718
719         debug_enter("(Slot : %d)\n", param);
720
721         pthread_mutex_lock(&g_slot_mutex);
722         debug_msg("[CODEC MGR] Slot_mutex lock done\n");
723
724
725         /*
726          * Unregister ASM here
727          */
728
729         int errorcode = 0;
730         debug_msg("[CODEC MGR] enable_session %d ",g_slots[param].enable_session);
731
732         if (g_slots[param].session_handle) {
733                 if(g_slots[param].session_type != ASM_EVENT_CALL &&
734                         g_slots[param].session_type != ASM_EVENT_VIDEOCALL &&
735                         g_slots[param].session_type != ASM_EVENT_VOIP &&
736                         g_slots[param].session_type != ASM_EVENT_VOICE_RECOGNITION &&
737                         g_slots[param].enable_session ) {
738                         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)) {
739                                 debug_error("[CODEC MGR] ASM_set_sound_state_ex() failed 0x%X\n", errorcode);
740                         }
741                         debug_msg("[CODEC MGR] ASM unregister\n");
742                         if(!ASM_unregister_sound_ex(g_slots[param].session_handle, g_slots[param].session_type, &errorcode, __asm_process_message)) {
743                                 debug_error("[CODEC MGR] ASM_unregister_sound_ex() failed 0x%X\n", errorcode);
744                         }
745                 }
746         }
747
748         __mm_sound_mgr_ipc_notify_play_file_end(param);
749
750         debug_msg("Client callback msg_type (instance) : [%d]\n", (int)g_slots[param].param);
751         debug_msg("Handle allocated handle : [0x%08X]\n", g_slots[param].plughandle);
752         err = g_plugins[g_slots[param].pluginid].Destroy(g_slots[param].plughandle);
753         if (err < 0 ) {
754                 debug_critical("[CODEC MGR] Fail to destroy slot number : [%d] err [0x%x]\n", param, err);
755         }
756         memset(&g_slots[param], 0, sizeof(__mmsound_mgr_codec_handle_t));
757         g_slots[param].status = STATUS_IDLE;
758         pthread_mutex_unlock(&g_slot_mutex);
759         debug_msg("[CODEC MGR] Slot_mutex done\n");
760
761         return err;
762 }
763
764 static int _MMSoundMgrCodecFindKeytoneSlot(int *slotid)
765 {
766         int count = 0;
767         int err = MM_ERROR_NONE;
768
769 #ifdef DEBUG_DETAIL
770         debug_enter("\n");
771 #endif
772
773         pthread_mutex_lock(&g_slot_mutex);
774 #ifdef DEBUG_DETAIL
775         debug_warning("After Slot_mutex LOCK\n");
776 #endif
777
778         for (count = SOUND_SLOT_START; count < MANAGER_HANDLE_MAX ; count++) {
779                 if (g_slots[count].status == STATUS_KEYTONE) {
780                         break;
781                 }
782         }
783         pthread_mutex_unlock(&g_slot_mutex);
784 #ifdef DEBUG_DETAIL
785         debug_warning("After Slot_mutex UNLOCK\n");
786 #endif
787         if (count < MANAGER_HANDLE_MAX) {
788                 debug_msg("Found keytone handle allocated (Slot : [%d])\n", count);
789                 *slotid = count;
790                 err =  MM_ERROR_NONE;
791         } else {
792                 debug_warning("Handle is full handle [KEY TONE] : [%d]\n", count);
793                 err =  MM_ERROR_SOUND_INTERNAL;
794         }
795
796 #ifdef DEBUG_DETAIL
797         debug_leave("\n");
798 #endif
799
800         return err;
801 }
802
803 static int _MMSoundMgrCodecFindLocaleSlot(int *slotid)
804 {
805         int count = 0;
806         int err = MM_ERROR_NONE;
807
808 #ifdef DEBUG_DETAIL
809         debug_enter("\n");
810 #endif
811
812         pthread_mutex_lock(&g_slot_mutex);
813 #ifdef DEBUG_DETAIL
814         debug_warning("After Slot_mutex LOCK\n");
815 #endif
816
817         for (count = SOUND_SLOT_START; count < MANAGER_HANDLE_MAX ; count++) {
818                 if (g_slots[count].status == STATUS_LOCALE) {
819                         break;
820                 }
821         }
822         pthread_mutex_unlock(&g_slot_mutex);
823
824 #ifdef DEBUG_DETAIL
825         debug_warning("After Slot_mutex UNLOCK\n");
826 #endif
827         if (count < MANAGER_HANDLE_MAX) {
828                 debug_msg("Found locale handle allocated (Slot : [%d])\n", count);
829                 *slotid = count;
830                 err =  MM_ERROR_NONE;
831         } else {
832                 debug_warning("Handle is full handle [KEY TONE] \n");
833                 err =  MM_ERROR_SOUND_INTERNAL;
834         }
835
836 #ifdef DEBUG_DETAIL
837         debug_leave("\n");
838 #endif
839
840         return err;
841 }
842
843 static int _MMSoundMgrCodecGetEmptySlot(int *slot)
844 {
845         int count = 0;
846         int err = MM_ERROR_NONE;
847
848 #ifdef DEBUG_DETAIL
849         debug_enter("\n");
850 #endif
851         debug_msg("Codec slot ID : [%d]\n", *slot);
852         pthread_mutex_lock(&g_slot_mutex);
853 #ifdef DEBUG_DETAIL
854         debug_msg("After Slot_mutex LOCK\n");
855 #endif
856
857         for (count = SOUND_SLOT_START; count < MANAGER_HANDLE_MAX ; count++) {
858                 if (g_slots[count].status == STATUS_IDLE) {
859                         g_slots[count].status = STATUS_SOUND;
860                         break;
861                 }
862         }
863         pthread_mutex_unlock(&g_slot_mutex);
864 #ifdef DEBUG_DETAIL
865         debug_msg("After Slot_mutex UNLOCK\n");
866 #endif
867
868         if (count < MANAGER_HANDLE_MAX) {
869                 debug_msg("New handle allocated (codec slot ID : [%d])\n", count);
870                 *slot = count;
871                 err =  MM_ERROR_NONE;
872         } else {
873                 debug_warning("Handle is full handle : [%d]\n", count);
874                 *slot = -1;
875                 /* Temporal code for reset */
876                 while(count--) {
877                         g_slots[count].status = STATUS_IDLE;
878                 }
879                 err =  MM_ERROR_SOUND_INTERNAL;
880         }
881
882 #ifdef DEBUG_DETAIL
883         debug_leave("\n");
884 #endif
885
886         return err;
887 }
888
889 static int _MMSoundMgrCodecRegisterInterface(MMSoundPluginType *plugin)
890 {
891         int err = MM_ERROR_NONE;
892         int count = 0;
893         void *getinterface = NULL;
894
895 #ifdef DEBUG_DETAIL
896         debug_enter("\n");
897 #endif
898
899         /* find emptry slot */
900         for (count = 0; count < MM_SOUND_SUPPORTED_CODEC_NUM; count++) {
901                 if (g_plugins[count].GetSupportTypes == NULL)
902                         break;
903         }
904
905         if (count == MM_SOUND_SUPPORTED_CODEC_NUM) {
906                 debug_critical("The plugin support type is not valid\n");
907                 return MM_ERROR_COMMON_OUT_OF_RANGE;
908         }
909
910         err = MMSoundPluginGetSymbol(plugin, CODEC_GET_INTERFACE_FUNC_NAME, &getinterface);
911         if (err != MM_ERROR_NONE) {
912                 debug_error("Get Symbol CODEC_GET_INTERFACE_FUNC_NAME is fail : %x\n", err);
913                 goto cleanup;
914         }
915         debug_msg("interface[%p] empty_slot[%d]\n", getinterface, count);
916
917         err = MMSoundPlugCodecCastGetInterface(getinterface)(&g_plugins[count]);
918         if (err != MM_ERROR_NONE) {
919                 debug_error("Get interface fail : %x\n", err);
920
921 cleanup:
922                 /* If error occur, clean interface */
923                 memset(&g_plugins[count], 0, sizeof(mmsound_codec_interface_t));
924         } else {
925                 if (g_plugins[count].SetThreadPool)
926                         g_plugins[count].SetThreadPool(MMSoundThreadPoolRun);
927         }
928
929 #ifdef DEBUG_DETAIL
930         debug_leave("\n");
931 #endif
932
933         return err;
934 }
935