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