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