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