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