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