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