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