apply focus for playing tone/wav
[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 #include <mm_session.h>
33
34 #include "include/mm_sound_mgr_common.h"
35 #include "include/mm_sound_mgr_codec.h"
36 #include "include/mm_sound_plugin_codec.h"
37 #include "include/mm_sound_thread_pool.h"
38 #include "include/mm_sound_pa_client.h"
39 #include "../include/mm_sound_focus.h"
40
41
42
43 #define _ENABLE_KEYTONE /* Temporal test code */
44
45 typedef struct {
46         int (*callback)(int, void *, void *, int);      /* msg_type(pid) client callback & client data info */
47         void *param;
48         int pid;
49         void *msgcallback;
50         void *msgdata;
51         MMHandleType plughandle;
52
53         int pluginid;
54         int status;
55         int session_type;
56         int session_options;
57         int focus_handle;
58         int focus_wcb_id;
59
60         bool enable_session;
61  } __mmsound_mgr_codec_handle_t;
62
63 static MMSoundPluginType *g_codec_plugins = NULL;
64 static __mmsound_mgr_codec_handle_t g_slots[MANAGER_HANDLE_MAX];
65 static mmsound_codec_interface_t g_plugins[MM_SOUND_SUPPORTED_CODEC_NUM];
66 static pthread_mutex_t g_slot_mutex;
67 static pthread_mutex_t codec_wave_mutex;
68 static int _MMSoundMgrCodecStopCallback(int param);
69 static int _MMSoundMgrCodecFindKeytoneSlot(int *slotid);
70 static int _MMSoundMgrCodecGetEmptySlot(int *slotid);
71 static int _MMSoundMgrCodecFindLocaleSlot(int *slotid);
72 static int _MMSoundMgrCodecRegisterInterface(MMSoundPluginType *plugin);
73
74 #define STATUS_IDLE 0
75 #define STATUS_SOUND 3
76
77 #define SOUND_SLOT_START 0
78
79 void sound_codec_focus_callback(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e focus_state, const char *reason_for_change, const char *additional_info, void *user_data)
80 {
81
82         int slotid = (int)user_data;
83         int result = MM_ERROR_NONE;
84
85         debug_warning ("focus callback called -> focus_stae(%d), reasoun_for_change(%s)", focus_state, reason_for_change ? reason_for_change : "N/A");
86
87         if(g_slots[slotid].session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE){
88                 debug_warning ("session option is UNINTERRUPTIBLE, nothing to do with focus");
89                 return;
90         }
91         if (focus_state == FOCUS_IS_RELEASED) {
92                 debug_warning ("focus is released -> stop playing");
93                 result = MMSoundMgrCodecStop(slotid);
94                 if (result != MM_ERROR_NONE) {
95                         debug_log("result error %d\n", result);
96                 }
97
98         }
99         return;
100 }
101
102 void sound_codec_focus_watch_callback(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e focus_state, const char *reason_for_change, const char* additional_info, void *user_data)
103 {
104         int slotid = (int)user_data;
105         int result = MM_ERROR_NONE;
106
107         debug_warning ("focus callback called -> focus_stae(%d), reasoun_for_change(%s)", focus_state, reason_for_change ? reason_for_change : "N/A");
108
109         if(g_slots[slotid].session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE){
110                 debug_warning ("session option is UNINTERRUPTIBLE, nothing to do with focus");
111                 return;
112         }
113         if (focus_state == FOCUS_IS_ACQUIRED) {
114                 debug_warning ("focus is released -> stop playing");
115                 result = MMSoundMgrCodecStop(slotid);
116                 if (result != MM_ERROR_NONE) {
117                         debug_log("result error %d\n", result);
118                 }
119
120         }
121         return;
122 }
123
124 int MMSoundMgrCodecInit(const char *targetdir)
125 {
126         int loop = 0;
127         int count = 0;
128
129         debug_enter("\n");
130
131         memset (g_slots, 0, sizeof(g_slots));
132
133         if(pthread_mutex_init(&g_slot_mutex, NULL)) {
134                 debug_error("pthread_mutex_init failed\n");
135                 return MM_ERROR_SOUND_INTERNAL;
136         }
137
138         if(pthread_mutex_init(&codec_wave_mutex, NULL)) {
139                 debug_error("pthread_mutex_init failed\n");
140                 return MM_ERROR_SOUND_INTERNAL;
141         }
142
143         for (count = 0; count < MANAGER_HANDLE_MAX; count++) {
144                 g_slots[count].status = STATUS_IDLE;
145                 g_slots[count].plughandle = 0;
146         }
147
148         if (g_codec_plugins) {
149                 debug_warning("Please Check Init twice\n");
150                 MMSoundPluginRelease(g_codec_plugins);
151         }
152
153         MMSoundPluginScan(targetdir, MM_SOUND_PLUGIN_TYPE_CODEC, &g_codec_plugins);
154
155         while (g_codec_plugins[loop].type != MM_SOUND_PLUGIN_TYPE_NONE) {
156                 _MMSoundMgrCodecRegisterInterface(&g_codec_plugins[loop++]);
157         }
158
159         debug_leave("\n");
160         return MM_ERROR_NONE;
161 }
162
163 int MMSoundMgrCodecFini(void)
164 {
165         debug_enter("\n");
166
167         memset(g_plugins, 0, sizeof(mmsound_codec_interface_t) * MM_SOUND_SUPPORTED_CODEC_NUM);
168         MMSoundPluginRelease(g_codec_plugins);
169         g_codec_plugins = NULL;
170         pthread_mutex_destroy(&g_slot_mutex);
171         pthread_mutex_destroy(&codec_wave_mutex);
172         debug_leave("\n");
173         return MM_ERROR_NONE;
174 }
175
176
177 int MMSoundMgrCodecPlay(int *slotid, const mmsound_mgr_codec_param_t *param)
178 {
179         int count = 0;
180         mmsound_codec_info_t info;
181         mmsound_codec_param_t codec_param;
182         int err = MM_ERROR_NONE;
183         int errorcode = 0;
184         int need_focus_unregister = 0;
185
186 #ifdef DEBUG_DETAIL
187         debug_enter("\n");
188 #endif
189
190         for (count = 0; g_plugins[count].GetSupportTypes; count++) {
191                 /* Find codec */
192                 if (g_plugins[count].Parse(param->source, &info) == MM_ERROR_NONE)
193                         break;
194         }
195
196         /*The count num means codec type WAV, MP3 */
197         debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, count);
198
199         if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
200                 debug_error("unsupported file type %d\n", count);
201                 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
202                 goto cleanup;
203         }
204
205 #ifdef DEBUG_DETAIL
206         debug_msg("Get New handle\n");
207 #endif
208
209         err = _MMSoundMgrCodecGetEmptySlot(slotid);
210         if (err != MM_ERROR_NONE) {
211                 debug_error("Empty g_slot is not found\n");
212                 goto cleanup;
213         }
214
215         codec_param.tone = param->tone;
216         codec_param.volume_config = param->volume_config;
217         codec_param.repeat_count = param->repeat_count;
218         codec_param.volume = param->volume;
219         codec_param.source = param->source;
220         codec_param.priority = param->priority;
221         codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
222         codec_param.param = *slotid;
223         codec_param.pid = (int)param->param;
224         codec_param.handle_route = param->handle_route;
225         codec_param.codec_wave_mutex = &codec_wave_mutex;
226         codec_param.stream_index = param->stream_index;
227         strncpy(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
228         pthread_mutex_lock(&g_slot_mutex);
229 #ifdef DEBUG_DETAIL
230         debug_msg("After Slot_mutex LOCK\n");
231 #endif
232
233         /*
234          * Register FOCUS here
235          */
236
237         if (param->session_type != MM_SESSION_TYPE_CALL &&
238                 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
239                 param->session_type != MM_SESSION_TYPE_VOIP &&
240                 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
241                 param->priority != HANDLE_PRIORITY_SOLO &&
242                 param->enable_session) {
243
244                 if ((param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS) || param->session_type == MM_SESSION_TYPE_ALARM || param->session_type == MM_SESSION_TYPE_NOTIFY || param->session_type == MM_SESSION_TYPE_EMERGENCY) {
245                         debug_warning("session option is PAUSE_OTHERS -> acquire focus");
246                         err = mm_sound_focus_get_id((int *)(&param->focus_handle));
247                         err = mm_sound_register_focus(param->focus_handle, "media", sound_codec_focus_callback, (void*)*slotid);
248                         if (err) {
249                                 debug_error("mm_sound_register_focus failed [0x%x]", err);
250                                 pthread_mutex_unlock(&g_slot_mutex);
251                                 return MM_ERROR_POLICY_INTERNAL;
252                         }
253                         err = mm_sound_acquire_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
254                         if (err) {
255                                 debug_error("mm_sound_acquire_focus failed [0x%x]", err);
256                                 err = mm_sound_unregister_focus(param->focus_handle);
257                                 pthread_mutex_unlock(&g_slot_mutex);
258                                 return MM_ERROR_POLICY_INTERNAL;
259                         }
260                 } else if (param->session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
261                         /* do nothing */
262                         debug_warning("session option is UNINTERRUPTIBLE, nothing to do with focus");
263                 } else {
264                         debug_warning("need to set focus watch callback");
265                         err = mm_sound_set_focus_watch_callback(FOCUS_FOR_BOTH, sound_codec_focus_watch_callback, (void*)*slotid, (int *)(&param->focus_wcb_id));
266                         if (err) {
267                                 debug_error("mm_sound_set_focus_watch_callback failed [0x%x]", err);
268                                 err = mm_sound_unregister_focus(param->focus_handle);
269                                 pthread_mutex_unlock(&g_slot_mutex);
270                                 return MM_ERROR_POLICY_INTERNAL;
271                         }
272                 }
273         }
274         //
275
276         /* Codec id WAV or MP3 */
277         g_slots[*slotid].pluginid = count;
278         g_slots[*slotid].param    = param->param;               /* This arg is used callback data */
279         g_slots[*slotid].session_type = param->session_type;
280         g_slots[*slotid].session_options = param->session_options;
281         g_slots[*slotid].focus_handle = param->focus_handle;
282         g_slots[*slotid].focus_wcb_id = param->focus_wcb_id;
283         g_slots[*slotid].enable_session = true;
284         g_slots[*slotid].pid = (int)param->param;
285
286         debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
287
288         err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
289         debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
290         if (err != MM_ERROR_NONE) {
291                 debug_error("Plugin create fail : 0x%08X\n", err);
292                 g_slots[*slotid].status = STATUS_IDLE;
293                 pthread_mutex_unlock(&g_slot_mutex);
294                 debug_warning("After Slot_mutex UNLOCK\n");
295                 if (param->focus_handle) {
296                         need_focus_unregister = 1;
297                 }
298                 goto cleanup;
299         }
300
301         err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
302         if (err != MM_ERROR_NONE) {
303                 debug_error("Fail to play : 0x%08X\n", err);
304                 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
305                 if (param->focus_handle) {
306                         need_focus_unregister = 1;
307                 }
308         }
309
310         pthread_mutex_unlock(&g_slot_mutex);
311 #ifdef DEBUG_DETAIL
312         debug_msg("After Slot_mutex UNLOCK\n");
313 #endif
314
315 cleanup:
316         if(param->session_type != MM_SESSION_TYPE_CALL &&
317                 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
318                 param->session_type != MM_SESSION_TYPE_VOIP &&
319                 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
320                 param->enable_session &&
321                 need_focus_unregister == 1) {
322
323                 if (param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS || param->session_type == MM_SESSION_TYPE_ALARM || param->session_type == MM_SESSION_TYPE_NOTIFY || param->session_type == MM_SESSION_TYPE_EMERGENCY) {
324                         err = mm_sound_release_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
325                         if(mm_sound_unregister_focus(param->focus_handle) || err) {
326                                 debug_error("focus cleaning up failed[0x%x]", err);
327                                 return MM_ERROR_POLICY_INTERNAL;
328                         }
329                 } else if (~(param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
330                         err = mm_sound_unset_focus_watch_callback(param->focus_wcb_id);
331                         if (err) {
332                                 debug_error("focus watch cleaning up failed[0x%x]", err);
333                                 return MM_ERROR_POLICY_INTERNAL;
334                         }
335                 }
336         }
337
338 #ifdef DEBUG_DETAIL
339         debug_leave("\n");
340 #endif
341
342         return err;
343 }
344
345 int MMSoundMgrCodecPlayWithStreamInfo(int *slotid, const mmsound_mgr_codec_param_t *param)
346 {
347         int count = 0;
348         mmsound_codec_info_t info;
349         mmsound_codec_param_t codec_param;
350         int err = MM_ERROR_NONE;
351         int errorcode = 0;
352
353 #ifdef DEBUG_DETAIL
354         debug_enter("\n");
355 #endif
356
357         for (count = 0; g_plugins[count].GetSupportTypes; count++) {
358                 /* Find codec */
359                 if (g_plugins[count].Parse(param->source, &info) == MM_ERROR_NONE)
360                         break;
361         }
362
363         /*The count num means codec type WAV, MP3 */
364         debug_msg("Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->repeat_count, param->volume, count);
365
366         if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
367                 debug_error("unsupported file type %d\n", count);
368                 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
369                 goto cleanup;
370         }
371
372         err = _MMSoundMgrCodecGetEmptySlot(slotid);
373         if (err != MM_ERROR_NONE) {
374                 debug_error("Empty g_slot is not found\n");
375                 goto cleanup;
376         }
377
378         codec_param.volume_config = -1; //setting volume config to -1 since using stream info instead of volume type
379         codec_param.repeat_count = param->repeat_count;
380         codec_param.volume = param->volume;
381         codec_param.source = param->source;
382         codec_param.priority = param->priority;
383         codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
384         codec_param.param = *slotid;
385         codec_param.pid = (int)param->param;
386         codec_param.handle_route = param->handle_route;
387         codec_param.codec_wave_mutex = &codec_wave_mutex;
388         codec_param.stream_index = param->stream_index;
389         strncpy(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
390         pthread_mutex_lock(&g_slot_mutex);
391 #ifdef DEBUG_DETAIL
392         debug_msg("After Slot_mutex LOCK\n");
393 #endif
394
395         /* Codec id WAV or MP3 */
396         g_slots[*slotid].pluginid = count;
397         g_slots[*slotid].param    = param->param;               /* This arg is used callback data */
398
399         debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
400
401         err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
402         debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
403         if (err != MM_ERROR_NONE) {
404                 debug_error("Plugin create fail : 0x%08X\n", err);
405                 g_slots[*slotid].status = STATUS_IDLE;
406                 pthread_mutex_unlock(&g_slot_mutex);
407                 debug_warning("After Slot_mutex UNLOCK\n");
408                 goto cleanup;
409         }
410
411         err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
412         if (err != MM_ERROR_NONE) {
413                 debug_error("Fail to play : 0x%08X\n", err);
414                 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
415         }
416
417         pthread_mutex_unlock(&g_slot_mutex);
418 #ifdef DEBUG_DETAIL
419         debug_msg("After Slot_mutex UNLOCK\n");
420 #endif
421
422 cleanup:
423
424 #ifdef DEBUG_DETAIL
425         debug_leave("\n");
426 #endif
427
428         return err;
429
430 }
431
432 #define DTMF_PLUGIN_COUNT 2
433 int MMSoundMgrCodecPlayDtmf(int *slotid, const mmsound_mgr_codec_param_t *param)
434 {
435         int count = 0;
436         int *codec_type;
437         mmsound_codec_info_t info;
438         mmsound_codec_param_t codec_param;
439         int err = MM_ERROR_NONE;
440         int errorcode = 0;
441         int need_focus_unregister = 0;
442
443 #ifdef DEBUG_DETAIL
444         debug_enter("\n");
445 #endif
446
447         for (count = 0; g_plugins[count].GetSupportTypes; count++) {
448                 /* Find codec */
449                 codec_type = g_plugins[count].GetSupportTypes();
450                 if(codec_type && (MM_SOUND_SUPPORTED_CODEC_DTMF == codec_type[0]))
451                         break;
452         }
453
454         /*The count num means codec type DTMF */
455         debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, count);
456
457         if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
458                 debug_error("unsupported file type %d\n", count);
459                 printf("unsupported file type %d\n", count);
460                 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
461                 goto cleanup;
462         }
463
464 #ifdef DEBUG_DETAIL
465         debug_msg("Get New handle\n");
466 #endif
467
468         err = _MMSoundMgrCodecGetEmptySlot(slotid);
469         if(err != MM_ERROR_NONE)
470         {
471                 debug_error("Empty g_slot is not found\n");
472                 goto cleanup;
473         }
474
475         codec_param.tone = param->tone;
476         codec_param.priority = 0;
477         codec_param.volume_config = param->volume_config;
478         codec_param.repeat_count = param->repeat_count;
479         codec_param.volume = param->volume;
480         codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
481         codec_param.param = *slotid;
482         codec_param.pid = (int)param->param;
483         codec_param.stream_index = param->stream_index;
484         strncpy(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
485
486         pthread_mutex_lock(&g_slot_mutex);
487 #ifdef DEBUG_DETAIL
488         debug_msg("After Slot_mutex LOCK\n");
489 #endif
490
491         //
492         /*
493          * Register FOCUS here
494          */
495
496         if (param->session_type != MM_SESSION_TYPE_CALL &&
497                 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
498                 param->session_type != MM_SESSION_TYPE_VOIP &&
499                 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
500                 param->enable_session)  {
501
502                 if ((param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS) || param->session_type == MM_SESSION_TYPE_ALARM || param->session_type == MM_SESSION_TYPE_NOTIFY || param->session_type == MM_SESSION_TYPE_EMERGENCY) {
503                         debug_warning("session option is PAUSE_OTHERS -> acquire focus");
504                         err = mm_sound_focus_get_id((int *)(&param->focus_handle));
505                         err = mm_sound_register_focus(param->focus_handle, "media", sound_codec_focus_callback, (void*)*slotid);
506                         if (err) {
507                                 debug_error("mm_sound_register_focus failed [0x%x]", err);
508                                 pthread_mutex_unlock(&g_slot_mutex);
509                                 return MM_ERROR_POLICY_INTERNAL;
510                         }
511                         err = mm_sound_acquire_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
512                         if (err) {
513                                 debug_error("mm_sound_acquire_focus failed [0x%x]", err);
514                                 err = mm_sound_unregister_focus(param->focus_handle);
515                                 pthread_mutex_unlock(&g_slot_mutex);
516                                 return MM_ERROR_POLICY_INTERNAL;
517                         }
518                 } else if (param->session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
519                         /* do nothing */
520                         debug_warning("session option is UNINTERRUPTIBLE, nothing to do with focus");
521                 } else {
522                         debug_warning("need to set focus watch callback");
523                         err = mm_sound_set_focus_watch_callback(FOCUS_FOR_BOTH, sound_codec_focus_watch_callback, (void*)*slotid, (int *)(&param->focus_wcb_id));
524                         if (err) {
525                                 debug_error("mm_sound_set_focus_watch_callback failed [0x%x]", err);
526                                 err = mm_sound_unregister_focus(param->focus_handle);
527                                 pthread_mutex_unlock(&g_slot_mutex);
528                                 return MM_ERROR_POLICY_INTERNAL;
529                         }
530                 }
531         }
532
533         g_slots[*slotid].pluginid = count;
534         g_slots[*slotid].param    = param->param;               /* This arg is used callback data */
535         g_slots[*slotid].session_type = param->session_type;
536         g_slots[*slotid].session_options = param->session_options;
537         g_slots[*slotid].focus_handle= param->focus_handle;
538         g_slots[*slotid].focus_wcb_id= param->focus_wcb_id;
539         g_slots[*slotid].enable_session = param->enable_session;
540         g_slots[*slotid].pid = (int)param->param;
541
542 #ifdef DEBUG_DETAIL
543         debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
544 #endif
545
546         err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
547         debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
548         if (err != MM_ERROR_NONE) {
549                 debug_error("Plugin create fail : 0x%08X\n", err);
550                 g_slots[*slotid].status = STATUS_IDLE;
551                 pthread_mutex_unlock(&g_slot_mutex);
552                 debug_warning("After Slot_mutex UNLOCK\n");
553                 need_focus_unregister = 1;
554                 goto cleanup;
555         }
556
557         err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
558         if (err != MM_ERROR_NONE) {
559                 debug_error("Fail to play : 0x%08X\n", err);
560                 g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
561                 need_focus_unregister = 1;
562         }
563
564         pthread_mutex_unlock(&g_slot_mutex);
565
566         debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
567 #ifdef DEBUG_DETAIL
568         debug_msg("After Slot_mutex UNLOCK\n")
569 #endif
570
571 cleanup:
572         if (param->session_type != MM_SESSION_TYPE_CALL &&
573                 param->session_type != MM_SESSION_TYPE_VIDEOCALL &&
574                 param->session_type != MM_SESSION_TYPE_VOIP &&
575                 param->session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
576                 param->enable_session &&
577                 need_focus_unregister == 1) {
578
579                 if (param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS || param->session_type == MM_SESSION_TYPE_ALARM || param->session_type == MM_SESSION_TYPE_NOTIFY || param->session_type == MM_SESSION_TYPE_EMERGENCY) {
580                         err = mm_sound_release_focus(param->focus_handle, FOCUS_FOR_BOTH, NULL);
581                         if(mm_sound_unregister_focus(param->focus_handle) || err) {
582                                 debug_error("focus cleaning up failed[0x%x]", err);
583                                 return MM_ERROR_POLICY_INTERNAL;
584                         }
585                 } else if (~(param->session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
586                         err = mm_sound_unset_focus_watch_callback(param->focus_wcb_id);
587                         if (err) {
588                                 debug_error("focus watch cleaning up failed[0x%x]", err);
589                                 return MM_ERROR_POLICY_INTERNAL;
590                         }
591                 }
592         }
593
594 #ifdef DEBUG_DETAIL
595         debug_leave("\n");
596 #endif
597
598         return err;
599 }
600
601 MMSoundMgrCodecPlayDtmfWithStreamInfo(int *slotid, const mmsound_mgr_codec_param_t *param)
602 {
603         int count = 0;
604         int *codec_type;
605         mmsound_codec_info_t info;
606         mmsound_codec_param_t codec_param;
607         int err = MM_ERROR_NONE;
608         int errorcode = 0;
609
610 #ifdef DEBUG_DETAIL
611         debug_enter("\n");
612 #endif
613
614         for (count = 0; g_plugins[count].GetSupportTypes; count++) {
615                 /* Find codec */
616                 codec_type = g_plugins[count].GetSupportTypes();
617                 if(codec_type && (MM_SOUND_SUPPORTED_CODEC_DTMF == codec_type[0]))
618                         break;
619         }
620
621         /*The count num means codec type DTMF */
622         debug_msg("DTMF[%d] Repeat[%d] Volume[%f] plugin_codec[%d]\n", param->tone, param->repeat_count, param->volume, count);
623
624         if (g_plugins[count].GetSupportTypes == NULL) { /* Codec not found */
625                 debug_error("unsupported file type %d\n", count);
626                 printf("unsupported file type %d\n", count);
627                 err = MM_ERROR_SOUND_UNSUPPORTED_MEDIA_TYPE;
628                 goto cleanup;
629         }
630
631 #ifdef DEBUG_DETAIL
632         debug_msg("Get New handle\n");
633 #endif
634
635         err = _MMSoundMgrCodecGetEmptySlot(slotid);
636         if(err != MM_ERROR_NONE)
637         {
638                 debug_error("Empty g_slot is not found\n");
639                 goto cleanup;
640         }
641
642         codec_param.tone = param->tone;
643         codec_param.priority = 0;
644         codec_param.repeat_count = param->repeat_count;
645         codec_param.volume = param->volume;
646         codec_param.stop_cb = _MMSoundMgrCodecStopCallback;
647         codec_param.param = *slotid;
648         codec_param.pid = (int)param->param;
649         codec_param.volume_config = -1; //setting volume config to -1 since using stream info instead of volume type
650         codec_param.stream_index = param->stream_index;
651         strncpy(codec_param.stream_type, param->stream_type, MM_SOUND_STREAM_TYPE_LEN);
652
653         pthread_mutex_lock(&g_slot_mutex);
654 #ifdef DEBUG_DETAIL
655         debug_msg("After Slot_mutex LOCK\n");
656 #endif
657                 g_slots[*slotid].pluginid = count;
658                 g_slots[*slotid].param    = param->param;               /* This arg is used callback data */
659                 g_slots[*slotid].enable_session = param->enable_session;
660
661 #ifdef DEBUG_DETAIL
662                 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
663 #endif
664
665                 err = g_plugins[g_slots[*slotid].pluginid].Create(&codec_param, &info, &(g_slots[*slotid].plughandle));
666                 debug_msg("Created audio handle : [%d]\n", g_slots[*slotid].plughandle);
667                 if (err != MM_ERROR_NONE) {
668                         debug_error("Plugin create fail : 0x%08X\n", err);
669                         g_slots[*slotid].status = STATUS_IDLE;
670                         pthread_mutex_unlock(&g_slot_mutex);
671                         debug_warning("After Slot_mutex UNLOCK\n");
672                         goto cleanup;
673                 }
674
675                 err = g_plugins[g_slots[*slotid].pluginid].Play(g_slots[*slotid].plughandle);
676                 if (err != MM_ERROR_NONE) {
677                         debug_error("Fail to play : 0x%08X\n", err);
678                         g_plugins[g_slots[*slotid].pluginid].Destroy(g_slots[*slotid].plughandle);
679                 }
680
681                 pthread_mutex_unlock(&g_slot_mutex);
682
683                 debug_msg("Using Slotid : [%d] Slot Status : [%d]\n", *slotid, g_slots[*slotid].status);
684 #ifdef DEBUG_DETAIL
685                 debug_msg("After Slot_mutex UNLOCK\n");
686 #endif
687
688         cleanup:
689 #ifdef DEBUG_DETAIL
690                 debug_leave("\n");
691 #endif
692
693                 return err;
694
695 }
696
697 int MMSoundMgrCodecStop(const int slotid)
698 {
699         int err = MM_ERROR_NONE;
700
701         debug_enter("(Slotid : [%d])\n", slotid);
702
703         if (slotid < 0 || MANAGER_HANDLE_MAX <= slotid) {
704                 return MM_ERROR_INVALID_ARGUMENT;
705         }
706
707         pthread_mutex_lock (&g_slot_mutex);
708 #ifdef DEBUG_DETAIL
709         debug_msg("After Slot_mutex LOCK\n");
710 #endif
711         if (g_slots[slotid].status == STATUS_IDLE) {
712                 err = MM_ERROR_SOUND_INVALID_STATE;
713                 debug_warning("The playing slots is not found, Slot ID : [%d]\n", slotid);
714                 goto cleanup;
715         }
716 #ifdef DEBUG_DETAIL
717         debug_msg("Found slot, Slotid [%d] State [%d]\n", slotid, g_slots[slotid].status);
718 #endif
719
720         err = g_plugins[g_slots[slotid].pluginid].Stop(g_slots[slotid].plughandle);
721         if (err != MM_ERROR_NONE) {
722                 debug_error("Fail to STOP Code : 0x%08X\n", err);
723         }
724         debug_msg("Found slot, Slotid [%d] State [%d]\n", slotid, g_slots[slotid].status);
725 cleanup:
726         pthread_mutex_unlock(&g_slot_mutex);
727 #ifdef DEBUG_DETAIL
728         debug_msg("After Slot_mutex UNLOCK\n");
729 #endif
730         debug_leave("(err : 0x%08X)\n", err);
731
732         return err;
733 }
734
735 int MMSoundMgrCodecClearFocus(int pid)
736 {
737         int err = MM_ERROR_NONE;
738         int slotid;
739
740         debug_enter("(pid : [%d])\n", pid);
741
742         pthread_mutex_lock (&g_slot_mutex);
743
744         for (slotid = 0 ; slotid < MANAGER_HANDLE_MAX ; slotid++) {
745                 if (g_slots[slotid].pid == pid) {
746                         if (g_slots[slotid].focus_handle || g_slots[slotid].focus_wcb_id) {
747                                 if(g_slots[slotid].session_type != MM_SESSION_TYPE_CALL &&
748                                         g_slots[slotid].session_type != MM_SESSION_TYPE_VIDEOCALL &&
749                                         g_slots[slotid].session_type != MM_SESSION_TYPE_VOIP &&
750                                         g_slots[slotid].session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
751                                         g_slots[slotid].enable_session ) {
752                                         if ((g_slots[slotid].session_options & MM_SESSION_OPTION_PAUSE_OTHERS) || g_slots[slotid].session_type == MM_SESSION_TYPE_ALARM || g_slots[slotid].session_type == MM_SESSION_TYPE_NOTIFY || g_slots[slotid].session_type == MM_SESSION_TYPE_EMERGENCY) {
753                                                 err = mm_sound_release_focus(g_slots[slotid].focus_handle, FOCUS_FOR_BOTH, NULL);
754                                                 if (err) {
755                                                         debug_error("mm_sound_release_focus failed [0x%x]", err);
756                                                 }
757                                                 if(mm_sound_unregister_focus(g_slots[slotid].focus_handle) || err) {
758                                                         debug_error("Focus clean up failed [0x%x]", err);
759                                                         pthread_mutex_unlock(&g_slot_mutex);
760                                                         return MM_ERROR_POLICY_INTERNAL;
761                                                 }
762                                         } else if (~(g_slots[slotid].session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
763                                                 err = mm_sound_unset_focus_watch_callback(g_slots[slotid].focus_wcb_id);
764                                                 if (err) {
765                                                         debug_error("mm_sound_unset_focus_watch_callback failed [0x%x]", err);
766                                                         pthread_mutex_unlock(&g_slot_mutex);
767                                                         return MM_ERROR_POLICY_INTERNAL;
768                                                 }
769                                         }
770                                 }
771                                 g_slots[slotid].focus_handle = 0;
772                                 g_slots[slotid].focus_wcb_id = 0;
773                         }
774                 }
775         }
776
777 cleanup:
778         pthread_mutex_unlock(&g_slot_mutex);
779         debug_leave("(err : 0x%08X)\n", err);
780
781         return err;
782 }
783
784
785 static int _MMSoundMgrCodecStopCallback(int param)
786 {
787         int err = MM_ERROR_NONE;
788
789         debug_enter("(Slot : %d)\n", param);
790
791         pthread_mutex_lock(&g_slot_mutex);
792         debug_msg("[CODEC MGR] Slot_mutex lock done\n");
793
794
795         /*
796          * Unregister FOCUS here
797          */
798
799         int errorcode = 0;
800         debug_msg("[CODEC MGR] enable_session %d ",g_slots[param].enable_session);
801
802         if (g_slots[param].focus_handle || g_slots[param].focus_wcb_id) {
803                 if(g_slots[param].session_type != MM_SESSION_TYPE_CALL &&
804                         g_slots[param].session_type != MM_SESSION_TYPE_VIDEOCALL &&
805                         g_slots[param].session_type != MM_SESSION_TYPE_VOIP &&
806                         g_slots[param].session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
807                         g_slots[param].enable_session ) {
808                         if ((g_slots[param].session_options & MM_SESSION_OPTION_PAUSE_OTHERS) || g_slots[param].session_type == MM_SESSION_TYPE_ALARM || g_slots[param].session_type == MM_SESSION_TYPE_NOTIFY || g_slots[param].session_type == MM_SESSION_TYPE_EMERGENCY) {
809                                 err = mm_sound_release_focus(g_slots[param].focus_handle, FOCUS_FOR_BOTH, NULL);
810                                 if (err) {
811                                         debug_error("mm_sound_release_focus failed [0x%x]", err);
812                                 }
813                                 if(mm_sound_unregister_focus(g_slots[param].focus_handle) || err) {
814                                         debug_error("Focus clean up failed [0x%x]", err);
815                                         pthread_mutex_unlock(&g_slot_mutex);
816                                         return MM_ERROR_POLICY_INTERNAL;
817                                 }
818                         } else if (~(g_slots[param].session_options & MM_SESSION_OPTION_PAUSE_OTHERS)) {
819                                 err = mm_sound_unset_focus_watch_callback(g_slots[param].focus_wcb_id);
820                                 if (err) {
821                                         debug_error("mm_sound_unset_focus_watch_callback failed [0x%x]", err);
822                                         pthread_mutex_unlock(&g_slot_mutex);
823                                         return MM_ERROR_POLICY_INTERNAL;
824                                 }
825                         }
826                 }
827         }
828
829         __mm_sound_mgr_ipc_notify_play_file_end(param);
830
831         debug_msg("Client callback msg_type (instance) : [%d]\n", (int)g_slots[param].param);
832         debug_msg("Handle allocated handle : [0x%08X]\n", g_slots[param].plughandle);
833         err = g_plugins[g_slots[param].pluginid].Destroy(g_slots[param].plughandle);
834         if (err < 0 ) {
835                 debug_critical("[CODEC MGR] Fail to destroy slot number : [%d] err [0x%x]\n", param, err);
836         }
837         memset(&g_slots[param], 0, sizeof(__mmsound_mgr_codec_handle_t));
838         g_slots[param].status = STATUS_IDLE;
839         pthread_mutex_unlock(&g_slot_mutex);
840         debug_msg("[CODEC MGR] Slot_mutex done\n");
841
842         return err;
843 }
844
845 static int _MMSoundMgrCodecGetEmptySlot(int *slot)
846 {
847         int count = 0;
848         int err = MM_ERROR_NONE;
849
850 #ifdef DEBUG_DETAIL
851         debug_enter("\n");
852 #endif
853         debug_msg("Codec slot ID : [%d]\n", *slot);
854         pthread_mutex_lock(&g_slot_mutex);
855 #ifdef DEBUG_DETAIL
856         debug_msg("After Slot_mutex LOCK\n");
857 #endif
858
859         for (count = SOUND_SLOT_START; count < MANAGER_HANDLE_MAX ; count++) {
860                 if (g_slots[count].status == STATUS_IDLE) {
861                         g_slots[count].status = STATUS_SOUND;
862                         break;
863                 }
864         }
865         pthread_mutex_unlock(&g_slot_mutex);
866 #ifdef DEBUG_DETAIL
867         debug_msg("After Slot_mutex UNLOCK\n");
868 #endif
869
870         if (count < MANAGER_HANDLE_MAX) {
871                 debug_msg("New handle allocated (codec slot ID : [%d])\n", count);
872                 *slot = count;
873                 err =  MM_ERROR_NONE;
874         } else {
875                 debug_warning("Handle is full handle : [%d]\n", count);
876                 *slot = -1;
877                 /* Temporal code for reset */
878                 while(count--) {
879                         g_slots[count].status = STATUS_IDLE;
880                 }
881                 err =  MM_ERROR_SOUND_INTERNAL;
882         }
883
884 #ifdef DEBUG_DETAIL
885         debug_leave("\n");
886 #endif
887
888         return err;
889 }
890
891 static int _MMSoundMgrCodecRegisterInterface(MMSoundPluginType *plugin)
892 {
893         int err = MM_ERROR_NONE;
894         int count = 0;
895         void *getinterface = NULL;
896
897 #ifdef DEBUG_DETAIL
898         debug_enter("\n");
899 #endif
900
901         /* find emptry slot */
902         for (count = 0; count < MM_SOUND_SUPPORTED_CODEC_NUM; count++) {
903                 if (g_plugins[count].GetSupportTypes == NULL)
904                         break;
905         }
906
907         if (count == MM_SOUND_SUPPORTED_CODEC_NUM) {
908                 debug_critical("The plugin support type is not valid\n");
909                 return MM_ERROR_COMMON_OUT_OF_RANGE;
910         }
911
912         err = MMSoundPluginGetSymbol(plugin, CODEC_GET_INTERFACE_FUNC_NAME, &getinterface);
913         if (err != MM_ERROR_NONE) {
914                 debug_error("Get Symbol CODEC_GET_INTERFACE_FUNC_NAME is fail : %x\n", err);
915                 goto cleanup;
916         }
917         debug_msg("interface[%p] empty_slot[%d]\n", getinterface, count);
918
919         err = MMSoundPlugCodecCastGetInterface(getinterface)(&g_plugins[count]);
920         if (err != MM_ERROR_NONE) {
921                 debug_error("Get interface fail : %x\n", err);
922
923 cleanup:
924                 /* If error occur, clean interface */
925                 memset(&g_plugins[count], 0, sizeof(mmsound_codec_interface_t));
926         } else {
927                 if (g_plugins[count].SetThreadPool)
928                         g_plugins[count].SetThreadPool(MMSoundThreadPoolRun);
929         }
930
931 #ifdef DEBUG_DETAIL
932         debug_leave("\n");
933 #endif
934
935         return err;
936 }
937