rebase code with tizen 2.3
[platform/core/multimedia/libmm-session.git] / mm_session.c
1 /*
2  * libmm-session
3  *
4  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Seungbae Shin <seungbae.shin at samsung.com>, Sangchul Lee <sc11.lee at 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 <stdio.h>
23 #include <unistd.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <mm_session_private.h>
28 #include <mm_error.h>
29 #include <mm_debug.h>
30 #include <errno.h>
31 #include <audio-session-manager.h>
32 #include <glib.h>
33 #include <pthread.h>
34
35 #define EXPORT_API __attribute__((__visibility__("default")))
36 #define MAX_FILE_LENGTH 256
37
38 #define TRY_LOCK(x, x_ret) \
39 do {\
40     x_ret = pthread_mutex_trylock(&(x));\
41     if(x_ret != 0) {\
42         debug_warning("Mutex trylock failed, (0x%x)",x_ret);\
43     }\
44 } while(0)
45 #define LOCK(x) \
46 do {\
47     if(pthread_mutex_lock(&(x)) != 0) {\
48         debug_error("Mutex lock error");\
49     }\
50 } while(0)
51 #define UNLOCK(x) \
52 do {\
53     if(pthread_mutex_unlock(&(x)) != 0) {\
54         debug_error("Mutex unlock error");\
55     }\
56 } while(0)
57 #define DESTROY(x) \
58 do {\
59     if(pthread_mutex_destroy(&(x)) != 0) {\
60         debug_error("Mutex destroy error");\
61     }\
62 } while(0)
63
64 typedef struct {
65         session_callback_fn fn;
66         void* data;
67         session_msg_t msg;
68         session_event_t event;
69 }session_monitor_t;
70
71 typedef struct {
72         watch_callback_fn fn;
73         void* data;
74         session_watch_event_t event;
75         session_watch_state_t state;
76 }session_watch_t;
77
78 int g_asm_handle = -1;
79 int g_session_type = -1;
80 int g_monitor_asm_handle = -1;
81 session_monitor_t g_monitor_data;
82 session_watch_t g_watch_data;
83
84 pthread_mutex_t g_mutex_monitor = PTHREAD_MUTEX_INITIALIZER;
85
86 ASM_cb_result_t asm_monitor_callback(int handle, ASM_event_sources_t event_src, ASM_sound_commands_t command, unsigned int sound_status, void* cb_data);
87 ASM_cb_result_t asm_watch_callback(int handle, ASM_sound_events_t sound_event, ASM_sound_states_t sound_state, void* cb_data);
88 static session_event_t _translate_from_event_src_to_mm_session(ASM_event_sources_t event_src);
89 static session_watch_event_t _translate_from_asm_event_to_mm_session(ASM_sound_events_t sound_event);
90 static ASM_sound_events_t _translate_from_mm_session_to_asm_event(session_watch_event_t watch_event);
91 static ASM_sound_states_t _translate_from_mm_session_to_asm_state(session_watch_state_t watch_state);
92
93
94 EXPORT_API
95 int mm_session_init(int sessiontype)
96 {
97         debug_fenter();
98         return mm_session_init_ex(sessiontype, NULL, NULL);
99         debug_fleave();
100 }
101
102 EXPORT_API
103 int mm_session_init_ex(int sessiontype, session_callback_fn callback, void* user_param)
104 {
105         int error = 0;
106         int result = MM_ERROR_NONE;
107         int ltype = 0;
108         bool do_not_update_session_info = false;
109         pthread_mutex_init(&g_mutex_monitor, NULL);
110         debug_fenter();
111         debug_log("type : %d", sessiontype);
112
113         if (sessiontype < MM_SESSION_TYPE_MEDIA || sessiontype >= MM_SESSION_TYPE_NUM) {
114                 debug_error("Invalid argument %d",sessiontype);
115                 return MM_ERROR_INVALID_ARGUMENT;
116         }
117
118         result = _mm_session_util_read_type(-1, &ltype);
119         if (MM_ERROR_INVALID_HANDLE != result) {
120                 if ((ltype == MM_SESSION_TYPE_MEDIA_RECORD) && sessiontype == MM_SESSION_TYPE_MEDIA) {
121                         /* already set by mm-camcorder, mm-sound(pcm in), keep going */
122                         do_not_update_session_info = true;
123                 } else {
124                         debug_error("Session already initialized. Please finish current session first");
125                         return MM_ERROR_POLICY_DUPLICATED;
126                 }
127         }
128
129         /* Monitor Callback */
130         if (NULL == callback) {
131                 debug_warning("Null callback function");
132         } else {
133                 if (sessiontype != MM_SESSION_TYPE_RECORD_AUDIO &&
134                         sessiontype != MM_SESSION_TYPE_RECORD_VIDEO ) {
135                         g_monitor_data.fn = callback;
136                         g_monitor_data.data = user_param;
137                         LOCK(g_mutex_monitor);
138                         if(!ASM_register_sound(-1, &g_monitor_asm_handle, ASM_EVENT_MONITOR, ASM_STATE_NONE, asm_monitor_callback, (void*)&g_monitor_data, ASM_RESOURCE_NONE, &error)) {
139                                 debug_error("Can not register monitor");
140                                 UNLOCK(g_mutex_monitor);
141                                 return MM_ERROR_INVALID_HANDLE;
142                         }
143                         UNLOCK(g_mutex_monitor);
144                 }
145         }
146
147         /* Register here for call session types */
148         if (sessiontype == MM_SESSION_TYPE_CALL) {
149                 if(!ASM_register_sound(-1, &g_asm_handle, ASM_EVENT_CALL, ASM_STATE_PLAYING, NULL, NULL, ASM_RESOURCE_NONE, &error)) {
150                         goto REGISTER_FAILURE;
151                 }
152         } else if (sessiontype == MM_SESSION_TYPE_VIDEOCALL) {
153                 if(!ASM_register_sound(-1, &g_asm_handle, ASM_EVENT_VIDEOCALL, ASM_STATE_PLAYING, NULL, NULL, ASM_RESOURCE_CAMERA|ASM_RESOURCE_VIDEO_OVERLAY, &error)) {
154                         goto REGISTER_FAILURE;
155                 }
156         } else if (sessiontype == MM_SESSION_TYPE_VOIP) {
157                 if(!ASM_register_sound(-1, &g_asm_handle, ASM_EVENT_VOIP, ASM_STATE_PLAYING, NULL, NULL, ASM_RESOURCE_NONE, &error)) {
158                         goto REGISTER_FAILURE;
159                 }
160         }
161         /* Register here for advanced session types (using asm_sub_event) */
162           else if (sessiontype == MM_SESSION_TYPE_VOICE_RECOGNITION) {
163                 if(!ASM_register_sound(-1, &g_asm_handle, ASM_EVENT_VOICE_RECOGNITION, ASM_STATE_NONE, NULL, NULL, ASM_RESOURCE_NONE, &error)) {
164                         goto REGISTER_FAILURE;
165                 }
166         } else if (sessiontype == MM_SESSION_TYPE_RECORD_AUDIO) {
167                 if(!ASM_register_sound(-1, &g_asm_handle, ASM_EVENT_MMCAMCORDER_AUDIO, ASM_STATE_NONE, NULL, NULL, ASM_RESOURCE_NONE, &error)) {
168                         goto REGISTER_FAILURE;
169                 }
170         } else if (sessiontype == MM_SESSION_TYPE_RECORD_VIDEO) {
171                 if(!ASM_register_sound(-1, &g_asm_handle, ASM_EVENT_MMCAMCORDER_VIDEO, ASM_STATE_NONE, NULL, NULL, ASM_RESOURCE_CAMERA|ASM_RESOURCE_VIDEO_OVERLAY|ASM_RESOURCE_HW_ENCODER, &error)) {
172                         goto REGISTER_FAILURE;
173                 }
174         }
175
176         g_session_type = sessiontype;
177
178         if (!do_not_update_session_info) {
179                 result = _mm_session_util_write_type(-1, sessiontype);
180                 if (MM_ERROR_NONE != result) {
181                         debug_error("Write type failed");
182                         if (sessiontype == MM_SESSION_TYPE_CALL) {
183                                 ASM_unregister_sound(g_asm_handle, ASM_EVENT_CALL, &error);
184                         } else if (sessiontype == MM_SESSION_TYPE_VIDEOCALL) {
185                                 ASM_unregister_sound(g_asm_handle, ASM_EVENT_VIDEOCALL, &error);
186                         } else if (sessiontype == MM_SESSION_TYPE_VOIP) {
187                                 ASM_unregister_sound(g_asm_handle, ASM_EVENT_VOIP, &error);
188                         } else if (sessiontype == MM_SESSION_TYPE_VOICE_RECOGNITION) {
189                                 ASM_unregister_sound(g_asm_handle, ASM_EVENT_VOICE_RECOGNITION, &error);
190                         } else if (sessiontype == MM_SESSION_TYPE_RECORD_AUDIO) {
191                                 ASM_unregister_sound(g_asm_handle, ASM_EVENT_MMCAMCORDER_AUDIO, &error);
192                         } else if (sessiontype == MM_SESSION_TYPE_RECORD_VIDEO) {
193                                 ASM_unregister_sound(g_asm_handle, ASM_EVENT_MMCAMCORDER_VIDEO, &error);
194                         } else {
195                                 LOCK(g_mutex_monitor);
196                                 ASM_unregister_sound(g_monitor_asm_handle, ASM_EVENT_MONITOR, &error);
197                                 UNLOCK(g_mutex_monitor);
198                         }
199                         g_asm_handle = -1;
200                         g_session_type = -1;
201                         return result;
202                 }
203         }
204
205         debug_fleave();
206
207         return MM_ERROR_NONE;
208
209 REGISTER_FAILURE:
210         debug_error("failed to ASM_register_sound(), sessiontype(%d), error(0x%x)", sessiontype, error);
211         switch (error) {
212         case ERR_ASM_POLICY_CANNOT_PLAY:
213                 return MM_ERROR_POLICY_BLOCKED;
214         case ERR_ASM_POLICY_CANNOT_PLAY_BY_CALL:
215                 return MM_ERROR_POLICY_BLOCKED_BY_CALL;
216         case ERR_ASM_POLICY_CANNOT_PLAY_BY_ALARM:
217                 return MM_ERROR_POLICY_BLOCKED_BY_ALARM;
218         default:
219                 break;
220         }
221         return MM_ERROR_INVALID_HANDLE;
222 }
223
224 EXPORT_API
225 int mm_session_update_option(session_update_type_t update_type, int options)
226 {
227         int error = 0;
228         int result = MM_ERROR_NONE;
229         int ltype = 0;
230         int loption = 0;
231
232         debug_log("update_type: %d(0:Add, 1:Remove), options: %x", update_type, options);
233
234         if (update_type < 0 || update_type >= MM_SESSION_UPDATE_TYPE_NUM) {
235                 debug_error("Invalid update_type value(%d)", update_type);
236                 return MM_ERROR_INVALID_ARGUMENT;
237         }
238         if (options < 0) {
239                 debug_error("Invalid options value(%x)", options);
240                 return MM_ERROR_INVALID_ARGUMENT;
241         }
242
243         result = _mm_session_util_read_information(-1, &ltype, &loption);
244         if (result) {
245                 debug_error("failed to _mm_session_util_read_information(), ret(%x)", result);
246                 return result;
247         }
248         debug_log("[current] session_type: %d, session_option: %x", ltype, loption);
249
250         if (update_type == MM_SESSION_UPDATE_TYPE_ADD) {
251                 loption |= options;
252         } else if (update_type == MM_SESSION_UPDATE_TYPE_REMOVE) {
253                 loption &= ~options;
254         }
255
256         result = _mm_session_util_write_information(-1, ltype, loption);
257         if (result) {
258                 debug_error("failed to _mm_session_util_write_information(), ret(%x)", result);
259                 return result;
260         }
261
262         debug_log("[updated] session_type: %d, session_option: %x", ltype, loption);
263
264
265         return MM_ERROR_NONE;
266 }
267
268 EXPORT_API
269 int mm_session_add_watch_callback(int watchevent, int watchstate, watch_callback_fn callback, void* user_param)
270 {
271         int result = MM_ERROR_NONE;
272         int error = 0;
273         int sessiontype = 0;
274
275         debug_fenter();
276
277         result = _mm_session_util_read_type(-1, &sessiontype);
278         if (result) {
279                 debug_error("failed to _mm_session_util_read_type(), result(%d), maybe session is not created", result);
280                 return result;
281         }
282         debug_log("type : %d", sessiontype);
283
284         if (sessiontype < MM_SESSION_TYPE_MEDIA || sessiontype >= MM_SESSION_TYPE_NUM) {
285                 debug_error("Invalid session type %d", sessiontype);
286                 return MM_ERROR_INVALID_ARGUMENT;
287         }
288
289         if (watchevent < MM_SESSION_WATCH_EVENT_CALL || watchevent >= MM_SESSION_WATCH_EVENT_NUM) {
290                 debug_error("Invalid watch event %d", watchevent);
291                 return MM_ERROR_INVALID_ARGUMENT;
292         }
293
294         if (watchstate < MM_SESSION_WATCH_STATE_STOP || watchstate >= MM_SESSION_WATCH_STATE_NUM) {
295                 debug_error("Invalid watch state %d", watchstate);
296                 return MM_ERROR_INVALID_ARGUMENT;
297         }
298
299         /* Register a watch callback */
300         if (NULL == callback) {
301                 debug_error("Null callback function");
302         } else {
303                 g_watch_data.fn = callback;
304                 g_watch_data.data = user_param;
305                 if (!ASM_set_watch_session (-1, _translate_from_mm_session_to_asm_event(watchevent), _translate_from_mm_session_to_asm_state(watchstate), asm_watch_callback, (void*)&g_watch_data, &error)) {
306                         debug_error("Could not register a watcher(event:%d, state:%d), error(0x%x)", watchevent, watchstate, error);
307                         return MM_ERROR_INVALID_HANDLE;
308                 }
309         }
310
311         debug_fleave();
312
313         return result;
314 }
315
316 EXPORT_API
317 int mm_session_get_current_type(int *sessiontype)
318 {
319         int result = MM_ERROR_NONE;
320         int ltype = 0;
321
322         debug_fenter();
323
324         if (sessiontype == NULL) {
325                 debug_error("input argument is NULL\n");
326                 return MM_ERROR_INVALID_ARGUMENT;
327         }
328
329         result = _mm_session_util_read_type(-1, &ltype);
330         if (result == MM_ERROR_NONE) {
331                 debug_log("Current process session type = [%d]\n", ltype);
332                 *sessiontype = ltype;
333         } else {
334                 debug_error("failed to get current process session type!!\n");
335         }
336
337         debug_fleave();
338
339         return result;
340 }
341
342 EXPORT_API
343 int mm_session_get_current_information(int *session_type, int *session_options)
344 {
345         int result = MM_ERROR_NONE;
346         int ltype = 0;
347         int loption = 0;
348
349         debug_fenter();
350
351         if (session_type == NULL) {
352                 debug_error("input argument is NULL\n");
353                 return MM_ERROR_INVALID_ARGUMENT;
354         }
355
356         result = _mm_session_util_read_information(-1, &ltype, &loption);
357         if (result == MM_ERROR_NONE) {
358                 debug_log("Current process session type = [%d], options = [%x]\n", ltype, loption);
359                 *session_type = ltype;
360                 *session_options = loption;
361         } else {
362                 debug_error("failed to get current process session type, option!!\n");
363         }
364
365         debug_fleave();
366
367         return result;
368 }
369
370 EXPORT_API
371 int mm_session_finish(void)
372 {
373         int error = 0;
374         int result = MM_ERROR_NONE;
375         int sessiontype = MM_SESSION_TYPE_MEDIA;
376         ASM_sound_states_t state = ASM_STATE_NONE;
377
378         debug_fenter();
379
380         result = _mm_session_util_read_type(-1, &sessiontype);
381         if (MM_ERROR_NONE != result) {
382                 debug_error("Can not read current type");
383                 DESTROY(g_mutex_monitor);
384                 return result;
385         }
386
387         /* Unregister call session type here */
388         if (sessiontype == MM_SESSION_TYPE_CALL) {
389                 if (!ASM_unregister_sound(g_asm_handle, ASM_EVENT_CALL, &error)) {
390                         goto INVALID_HANDLE;
391                 }
392         } else if (sessiontype == MM_SESSION_TYPE_VIDEOCALL) {
393                 if (!ASM_unregister_sound(g_asm_handle, ASM_EVENT_VIDEOCALL, &error)) {
394                         goto INVALID_HANDLE;
395                 }
396         } else if (sessiontype == MM_SESSION_TYPE_VOIP) {
397                 if (!ASM_unregister_sound(g_asm_handle, ASM_EVENT_VOIP, &error)) {
398                         goto INVALID_HANDLE;
399                 }
400         }
401         /* Unregister advanced session type here */
402         else if (sessiontype == MM_SESSION_TYPE_VOICE_RECOGNITION) {
403                 if (!ASM_unregister_sound(g_asm_handle, ASM_EVENT_VOICE_RECOGNITION, &error)) {
404                         goto INVALID_HANDLE;
405                 }
406         } else if (sessiontype == MM_SESSION_TYPE_RECORD_AUDIO) {
407                 if (!ASM_unregister_sound(g_asm_handle, ASM_EVENT_MMCAMCORDER_AUDIO, &error)) {
408                         goto INVALID_HANDLE;
409                 }
410         } else if (sessiontype == MM_SESSION_TYPE_RECORD_VIDEO) {
411                 if (!ASM_unregister_sound(g_asm_handle, ASM_EVENT_MMCAMCORDER_VIDEO, &error)) {
412                         goto INVALID_HANDLE;
413                 }
414         }
415         if (g_asm_handle != -1) {
416                 g_asm_handle = -1;
417         }
418
419
420         /* Check monitor handle */
421         TRY_LOCK(g_mutex_monitor, error);
422         if (!error) {
423                 if(g_monitor_asm_handle != -1) {
424                         if(!ASM_get_process_session_state(g_monitor_asm_handle, &state, &error)) {
425                                 debug_error("[%s] Can not get process status", __func__);
426                                 UNLOCK(g_mutex_monitor);
427                                 DESTROY(g_mutex_monitor);
428                                 return MM_ERROR_POLICY_INTERNAL;
429                         } else {
430                                 switch(state) {
431                                 case ASM_STATE_NONE:
432                                         break;
433                                 case ASM_STATE_PLAYING:
434                                 case ASM_STATE_WAITING:
435                                 case ASM_STATE_STOP:
436                                 case ASM_STATE_PAUSE:
437                                         debug_error("[%s] MSL instance still alive", __func__);
438                                         UNLOCK(g_mutex_monitor);
439                                         DESTROY(g_mutex_monitor);
440                                         return MM_ERROR_POLICY_BLOCKED;
441                                 }
442                         }
443                         /* Unregister monitor */
444                         if(!ASM_unregister_sound(g_monitor_asm_handle, ASM_EVENT_MONITOR, &error)) {
445                                 debug_error("ASM unregister monitor failed");
446                                 UNLOCK(g_mutex_monitor);
447                                 goto INVALID_HANDLE;
448                         } else {
449                                 debug_log("ASM unregister monitor success");
450                                 g_monitor_asm_handle = -1;
451                                 g_monitor_data.fn = NULL;
452                                 g_monitor_data.data = NULL;
453                         }
454                 }
455                 UNLOCK(g_mutex_monitor);
456                 DESTROY(g_mutex_monitor);
457         }
458
459         result = _mm_session_util_delete_information(-1);
460         if(result != MM_ERROR_NONE)
461                 return result;
462
463         debug_fleave();
464
465         return MM_ERROR_NONE;
466
467 INVALID_HANDLE:
468         DESTROY(g_mutex_monitor);
469         debug_error("failed to ASM_unregister_sound(), sessiontype(%d)", sessiontype);
470         return MM_ERROR_INVALID_HANDLE;
471 }
472
473 EXPORT_API
474 int mm_session_remove_watch_callback(int watchevent, int watchstate)
475 {
476         int result = MM_ERROR_NONE;
477         int error = 0;
478         int sessiontype = 0;
479
480         debug_fenter();
481
482         result = _mm_session_util_read_type(-1, &sessiontype);
483         if(result) {
484                 debug_error("failed to _mm_session_util_read_type(), result(%d), maybe session is not created", result);
485                 return result;
486         }
487         debug_log("type : %d", sessiontype);
488
489         if(sessiontype < MM_SESSION_TYPE_MEDIA || sessiontype >= MM_SESSION_TYPE_NUM) {
490                 debug_error("Invalid session type %d", sessiontype);
491                 return MM_ERROR_INVALID_ARGUMENT;
492         }
493
494         if(watchevent < MM_SESSION_WATCH_EVENT_CALL || watchevent >= MM_SESSION_WATCH_EVENT_NUM) {
495                 debug_error("Invalid watch event %d", watchevent);
496                 return MM_ERROR_INVALID_ARGUMENT;
497         }
498
499         if(watchstate < MM_SESSION_WATCH_STATE_STOP || watchstate >= MM_SESSION_WATCH_STATE_NUM) {
500                 debug_error("Invalid watch state %d", watchstate);
501                 return MM_ERROR_INVALID_ARGUMENT;
502         }
503
504         /* Unregister a watch callback */
505         if(!ASM_unset_watch_session (_translate_from_mm_session_to_asm_event(watchevent), _translate_from_mm_session_to_asm_state(watchstate), &error)) {
506                 debug_error("Could not unregister a watcher(event:%d, state:%d), error(0x%x)", watchevent, watchstate, error);
507                 return MM_ERROR_INVALID_HANDLE;
508         } else {
509                 g_watch_data.fn = NULL;
510                 g_watch_data.data = NULL;
511         }
512
513         debug_fleave();
514
515         return result;
516 }
517
518 EXPORT_API
519 int mm_session_set_subsession(mm_subsession_t subsession, mm_subsession_option_t option)
520 {
521         int error = 0;
522         int ret = 0;
523
524         debug_fenter();
525
526         if (g_asm_handle == -1) {
527                 debug_error ("call session is not started...\n");
528                 return MM_ERROR_INVALID_HANDLE;
529         }
530         if (g_session_type == -1 || g_session_type < MM_SESSION_TYPE_CALL || g_session_type >= MM_SESSION_TYPE_NUM ) {
531                 debug_error ("session type is null, or out of bound(%d)\n", g_session_type);
532                 return MM_ERROR_INVALID_HANDLE;
533         }
534
535         if (subsession >= MM_SUBSESSION_TYPE_VOICE && subsession <= MM_SUBSESSION_TYPE_MEDIA) {
536                 if (g_session_type < MM_SESSION_TYPE_CALL || g_session_type > MM_SESSION_TYPE_VOIP) {
537                         debug_error ("Not support this subsession(%d) of CALL session_type(%d)\n", subsession, g_session_type);
538                         return MM_ERROR_INVALID_HANDLE;
539                 }
540         } else if (subsession == MM_SUBSESSION_TYPE_INIT) {
541                 if (g_session_type != MM_SESSION_TYPE_VOICE_RECOGNITION &&
542                         g_session_type != MM_SESSION_TYPE_RECORD_AUDIO &&
543                         g_session_type != MM_SESSION_TYPE_RECORD_VIDEO) {
544                         debug_error ("Not support this subsession(%d) of the session_type(%d)\n", subsession, g_session_type);
545                         return MM_ERROR_INVALID_HANDLE;
546                 }
547         } else if (subsession == MM_SUBSESSION_TYPE_RECORD_STEREO ||
548                                 subsession == MM_SUBSESSION_TYPE_RECORD_MONO) {
549                 if (g_session_type < MM_SESSION_TYPE_RECORD_AUDIO || g_session_type > MM_SESSION_TYPE_RECORD_VIDEO) {
550                         debug_error ("Not support this subsession(%d) of the session_type(%d)\n", subsession, g_session_type);
551                         return MM_ERROR_INVALID_HANDLE;
552                 }
553         }
554
555         if(option < MM_SUBSESSION_OPTION_NONE || option >= MM_SUBSESSION_OPTION_NUM) {
556                 debug_error ("option(%d) is not valid\n", option);
557                 return MM_ERROR_INVALID_ARGUMENT;
558         }
559
560         ret = ASM_set_subsession (g_asm_handle, (ASM_sound_sub_sessions_t)subsession, option, &error);
561         if (!ret) {
562                 debug_error("ASM_set_subsession() failed, Set subsession to [%d] failed 0x%X\n\n", subsession, error);
563                 return MM_ERROR_SOUND_INTERNAL;
564         }
565
566         debug_fleave();
567
568         return MM_ERROR_NONE;
569 }
570
571 EXPORT_API
572 int mm_session_get_subsession(mm_subsession_t *subsession)
573 {
574         int error = 0;
575         int ret = 0;
576
577         debug_fenter();
578
579         if(g_asm_handle == -1) {
580                 debug_error ("call session is not started...\n");
581                 return MM_ERROR_INVALID_HANDLE;
582         }
583         if(g_session_type == -1 || g_session_type < MM_SESSION_TYPE_CALL || g_session_type >= MM_SESSION_TYPE_NUM ) {
584                 debug_error ("Not support this session_type(%d)\n", g_session_type);
585                 return MM_ERROR_INVALID_HANDLE;
586         }
587
588         ret = ASM_get_subsession (g_asm_handle, (ASM_sound_sub_sessions_t*)subsession, &error);
589         if (!ret) {
590                 debug_error("ASM_get_subsession() failed 0x%X\n\n", error);
591                 return MM_ERROR_SOUND_INTERNAL;
592         }
593
594         debug_log("ASM_get_subsession returned [%d]\n", *subsession);
595         debug_fleave();
596
597         return MM_ERROR_NONE;
598 }
599
600 EXPORT_API
601 int mm_session_set_subevent(mm_session_sub_t subevent)
602 {
603         int error = 0;
604         int ret = 0;
605
606         debug_fenter();
607
608         if(g_asm_handle == -1) {
609                 debug_error ("session is not started...\n");
610                 return MM_ERROR_INVALID_HANDLE;
611         }
612         if(g_session_type == -1 ||  g_session_type < MM_SESSION_TYPE_VOICE_RECOGNITION || g_session_type >= MM_SESSION_TYPE_NUM ) {
613                 debug_error ("not support this session_type(%d)\n", g_session_type);
614                 return MM_ERROR_INVALID_ARGUMENT;
615         }
616
617         ret = ASM_set_subevent (g_asm_handle, (ASM_sound_sub_events_t)subevent, &error);
618         if (!ret) {
619                 debug_error("ASM_set_subevent() failed, Set subevent to [%d] failed 0x%X\n\n", subevent, error);
620                 switch (error) {
621                 case ERR_ASM_POLICY_CANNOT_PLAY:
622                 case ERR_ASM_POLICY_CANNOT_PLAY_BY_PROFILE:
623                 case ERR_ASM_POLICY_CANNOT_PLAY_BY_CUSTOM:
624                         return MM_ERROR_POLICY_BLOCKED;
625                 case ERR_ASM_POLICY_CANNOT_PLAY_BY_CALL:
626                         return MM_ERROR_POLICY_BLOCKED_BY_CALL;
627                 case ERR_ASM_POLICY_CANNOT_PLAY_BY_ALARM:
628                         return MM_ERROR_POLICY_BLOCKED_BY_ALARM;
629                 }
630                 return MM_ERROR_SOUND_INTERNAL;
631         }
632
633         debug_fleave();
634
635         return MM_ERROR_NONE;
636 }
637
638 EXPORT_API
639 int mm_session_get_subevent(mm_session_sub_t *subevent)
640 {
641         int error = 0;
642         int ret = 0;
643         debug_fenter();
644
645         if(g_asm_handle == -1) {
646                 debug_error ("session is not started...\n");
647                 return MM_ERROR_INVALID_HANDLE;
648         }
649         if(g_session_type == -1 ||  g_session_type < MM_SESSION_TYPE_VOICE_RECOGNITION || g_session_type >= MM_SESSION_TYPE_NUM ) {
650                 debug_error ("not support this session_type(%d)\n", g_session_type);
651                 return MM_ERROR_INVALID_ARGUMENT;
652         }
653
654         ret = ASM_get_subevent (g_asm_handle, (ASM_sound_sub_events_t*)subevent, &error);
655         if (!ret) {
656                 debug_error("ASM_get_subevent() failed 0x%X\n\n", error);
657                 return MM_ERROR_SOUND_INTERNAL;
658         }
659
660         debug_log("ASM_get_subevent returned [%d]\n", *subevent);
661         debug_fleave();
662
663         return MM_ERROR_NONE;
664 }
665
666 EXPORT_API
667 int mm_session_reset_resumption_info(void)
668 {
669         int error = 0;
670         int ret = 0;
671
672         debug_fenter();
673
674         if(g_asm_handle == -1) {
675                 debug_error ("call series or voice recognition session is not started...\n");
676                 return MM_ERROR_INVALID_HANDLE;
677         }
678         if(g_session_type == -1 || g_session_type < MM_SESSION_TYPE_MEDIA || g_session_type >= MM_SESSION_TYPE_NUM ) {
679                 debug_error ("not support this session_type(%d)\n", g_session_type);
680                 return MM_ERROR_INVALID_ARGUMENT;
681         }
682         ret = ASM_reset_resumption_info (g_asm_handle, &error);
683         if (!ret) {
684                 debug_error("ASM_reset_resumption_info() failed 0x%X\n\n", error);
685                 return MM_ERROR_SOUND_INTERNAL;
686         }
687
688         debug_leave();
689
690         return MM_ERROR_NONE;
691 }
692
693 EXPORT_API
694 int _mm_session_util_delete_information(int app_pid)
695 {
696         pid_t mypid;
697         char filename[MAX_FILE_LENGTH];
698
699         if(app_pid == -1)
700                 mypid = getpid();
701         else
702                 mypid = (pid_t)app_pid;
703
704         ////// DELETE SESSION TYPE /////////
705         snprintf(filename, sizeof(filename)-1, "/tmp/mm_session_%d",mypid);
706         if(-1 ==  unlink(filename))
707                 return MM_ERROR_FILE_NOT_FOUND;
708         ////// DELETE SESSION TYPE /////////
709
710         return MM_ERROR_NONE;
711 }
712
713 EXPORT_API
714 int _mm_session_util_write_type(int app_pid, int sessiontype)
715 {
716         pid_t mypid;
717         int fd = -1;
718         char filename[MAX_FILE_LENGTH];
719
720         if(sessiontype < MM_SESSION_TYPE_MEDIA || sessiontype >= MM_SESSION_TYPE_NUM) {
721                 return MM_ERROR_INVALID_ARGUMENT;
722         }
723
724         if(app_pid == -1)
725                 mypid = getpid();
726         else
727                 mypid = (pid_t)app_pid;
728
729         ////// WRITE SESSION TYPE /////////
730         snprintf(filename, sizeof(filename)-1, "/tmp/mm_session_%d",mypid);
731         fd = open(filename, O_WRONLY | O_CREAT, 0644 );
732         if(fd < 0) {
733                 debug_error("open() failed with %d",errno);
734                 return MM_ERROR_FILE_WRITE;
735         }
736         sessiontype = sessiontype << 16;
737         write(fd, &sessiontype, sizeof(int));
738         if(0 > fchmod (fd, 00777)) {
739                 debug_error("fchmod failed with %d", errno);
740         } else {
741                 debug_warning("write sessiontype(%d) to /tmp/mm_session_%d", sessiontype >> 16, mypid);
742         }
743         close(fd);
744         ////// WRITE SESSION TYPE /////////
745
746         return MM_ERROR_NONE;
747 }
748
749 EXPORT_API
750 int _mm_session_util_read_type(int app_pid, int *sessiontype)
751 {
752         pid_t mypid;
753         int fd = -1;
754         char filename[MAX_FILE_LENGTH];
755
756         debug_fenter();
757
758         if(sessiontype == NULL)
759                 return MM_ERROR_INVALID_ARGUMENT;
760
761         if(app_pid == -1)
762                 mypid = getpid();
763         else
764                 mypid = (pid_t)app_pid;
765
766         ////// READ SESSION TYPE /////////
767         snprintf(filename, sizeof(filename)-1, "/tmp/mm_session_%d",mypid);
768         fd = open(filename, O_RDONLY);
769         if(fd < 0) {
770                 return MM_ERROR_INVALID_HANDLE;
771         }
772         read(fd, sessiontype, sizeof(int));
773         *sessiontype = *sessiontype >> 16;
774         debug_warning("read sessiontype(%d) from /tmp/mm_session_%d", *sessiontype, mypid);
775         close(fd);
776         ////// READ SESSION TYPE /////////
777
778         debug_fleave();
779
780         return MM_ERROR_NONE;
781 }
782
783 EXPORT_API
784 int _mm_session_util_write_information(int app_pid, int session_type, int flags)
785 {
786         pid_t mypid;
787         int fd = -1;
788         char filename[MAX_FILE_LENGTH];
789         int result_info = 0;
790
791         if(session_type < MM_SESSION_TYPE_MEDIA || session_type >= MM_SESSION_TYPE_NUM) {
792                 return MM_ERROR_INVALID_ARGUMENT;
793         }
794         if(flags < 0) {
795                 return MM_ERROR_INVALID_ARGUMENT;
796         }
797
798         if(app_pid == -1) {
799                 mypid = getpid();
800         } else {
801                 mypid = (pid_t)app_pid;
802         }
803
804         ////// WRITE SESSION INFO /////////
805         snprintf(filename, sizeof(filename)-1, "/tmp/mm_session_%d",mypid);
806         fd = open(filename, O_WRONLY | O_CREAT, 0644 );
807         if(fd < 0) {
808                 debug_error("open() failed with %d",errno);
809                 return MM_ERROR_FILE_WRITE;
810         }
811
812         result_info = (flags) | (session_type << 16);
813         write(fd, &result_info, sizeof(int));
814         if(0 > fchmod (fd, 00777)) {
815                 debug_error("fchmod failed with %d", errno);
816         } else {
817                 debug_warning("write session information(%x) to /tmp/mm_session_%d", result_info, mypid);
818         }
819         close(fd);
820         ////// WRITE SESSION INFO /////////
821
822         return MM_ERROR_NONE;
823 }
824
825 EXPORT_API
826 int _mm_session_util_read_information(int app_pid, int *session_type, int *flags)
827 {
828         pid_t mypid;
829         int fd = -1;
830         char filename[MAX_FILE_LENGTH];
831         int result_info = 0;
832
833         debug_fenter();
834
835         if(session_type == NULL || flags == NULL) {
836                 return MM_ERROR_INVALID_ARGUMENT;
837         }
838
839         if(app_pid == -1) {
840                 mypid = getpid();
841         } else {
842                 mypid = (pid_t)app_pid;
843         }
844
845         ////// READ SESSION INFO /////////
846         snprintf(filename, sizeof(filename)-1, "/tmp/mm_session_%d",mypid);
847         fd = open(filename, O_RDONLY);
848         if(fd < 0) {
849                 return MM_ERROR_INVALID_HANDLE;
850         }
851         read(fd, &result_info, sizeof(int));
852         *session_type = result_info >> 16;
853         *flags = result_info & 0x0000ffff;
854
855         debug_warning("read session_type(%d), session_option(%x) from /tmp/mm_session_%d", *session_type, *flags, mypid);
856         close(fd);
857         ////// READ SESSION INFO /////////
858
859         debug_fleave();
860
861         return MM_ERROR_NONE;
862 }
863
864 gboolean _asm_monitor_cb(gpointer *data)
865 {
866         session_monitor_t* monitor = (session_monitor_t*)data;
867         debug_fenter();
868
869         if (monitor) {
870                 if (monitor->fn) {
871                         monitor->fn(monitor->msg, monitor->event, monitor->data);
872                 }
873         }
874         debug_fleave();
875
876         return FALSE;
877 }
878
879 gboolean _asm_watch_cb(gpointer *data)
880 {
881         session_watch_t* watch_h = (session_watch_t*)data;
882         debug_fenter();
883
884         if (watch_h) {
885                 if (watch_h->fn) {
886                         watch_h->fn(watch_h->event, watch_h->state, watch_h->data);
887                 }
888         }
889         debug_fleave();
890
891         return FALSE;
892 }
893
894 static session_event_t _translate_from_event_src_to_mm_session(ASM_event_sources_t event_src)
895 {
896         switch (event_src)
897         {
898         case ASM_EVENT_SOURCE_CALL_START:
899         case ASM_EVENT_SOURCE_CALL_END:
900                 return MM_SESSION_EVENT_CALL;
901
902         case ASM_EVENT_SOURCE_EARJACK_UNPLUG:
903                 return MM_SESSION_EVENT_EARJACK_UNPLUG;
904
905         case ASM_EVENT_SOURCE_RESOURCE_CONFLICT:
906                 return MM_SESSION_EVENT_RESOURCE_CONFLICT;
907
908         case ASM_EVENT_SOURCE_ALARM_START:
909         case ASM_EVENT_SOURCE_ALARM_END:
910                 return MM_SESSION_EVENT_ALARM;
911
912         case ASM_EVENT_SOURCE_NOTIFY_START:
913         case ASM_EVENT_SOURCE_NOTIFY_END:
914                 return MM_SESSION_EVENT_NOTIFICATION;
915
916         case ASM_EVENT_SOURCE_EMERGENCY_START:
917         case ASM_EVENT_SOURCE_EMERGENCY_END:
918                 return MM_SESSION_EVENT_EMERGENCY;
919
920         case ASM_EVENT_SOURCE_MEDIA:
921         case ASM_EVENT_SOURCE_OTHER_PLAYER_APP:
922         default:
923                 return MM_SESSION_EVENT_MEDIA;
924         }
925 }
926
927 static session_watch_event_t _translate_from_asm_event_to_mm_session(ASM_sound_events_t sound_event)
928 {
929         switch (sound_event)
930         {
931         case ASM_EVENT_CALL:
932                 return MM_SESSION_WATCH_EVENT_CALL;
933         case ASM_EVENT_VIDEOCALL:
934                 return MM_SESSION_WATCH_EVENT_VIDEO_CALL;
935         case ASM_EVENT_ALARM:
936                 return MM_SESSION_WATCH_EVENT_ALARM;
937         default:
938                 return MM_SESSION_WATCH_EVENT_IGNORE;
939         }
940 }
941
942 static ASM_sound_events_t _translate_from_mm_session_to_asm_event(session_watch_event_t watch_event)
943 {
944         switch (watch_event)
945         {
946         case MM_SESSION_WATCH_EVENT_CALL:
947                 return ASM_EVENT_CALL;
948         case MM_SESSION_WATCH_EVENT_VIDEO_CALL:
949                 return ASM_EVENT_VIDEOCALL;
950         case MM_SESSION_WATCH_EVENT_ALARM:
951                 return ASM_EVENT_ALARM;
952         default:
953                 return ASM_EVENT_NONE;
954         }
955 }
956
957 static ASM_sound_states_t _translate_from_mm_session_to_asm_state(session_watch_state_t watch_state)
958 {
959         switch (watch_state)
960         {
961         case MM_SESSION_WATCH_STATE_STOP:
962                 return ASM_STATE_STOP;
963         case MM_SESSION_WATCH_STATE_PLAYING:
964                 return ASM_STATE_PLAYING;
965         default:
966                 return ASM_STATE_NONE;
967         }
968 }
969
970 ASM_cb_result_t
971 asm_monitor_callback(int handle, ASM_event_sources_t event_src, ASM_sound_commands_t command, unsigned int sound_status, void* cb_data)
972 {
973         ASM_cb_result_t cb_res = ASM_CB_RES_NONE;
974         session_monitor_t *monitor = (session_monitor_t*)cb_data;
975
976         debug_log("monitor callback called for handle %d, event_src %d", handle, event_src);
977         if(!monitor) {
978                 debug_log("monitor instance is null\n");
979                 return ASM_CB_RES_IGNORE;
980         }
981
982         switch(command)
983         {
984         case ASM_COMMAND_STOP:
985         case ASM_COMMAND_PAUSE:
986                 //call session_callback_fn for stop here
987                 if(monitor->fn) {
988                         monitor->msg = MM_SESSION_MSG_STOP;
989                         monitor->event = _translate_from_event_src_to_mm_session (event_src);
990                         g_idle_add((GSourceFunc)_asm_monitor_cb, (gpointer)monitor);
991                 }
992                 cb_res = (command == ASM_COMMAND_STOP)? ASM_CB_RES_STOP : ASM_CB_RES_PAUSE;
993                 break;
994
995         case ASM_COMMAND_RESUME:
996         case ASM_COMMAND_PLAY:
997                 //call session_callback_fn for resume here
998                 if(monitor->fn) {
999                         monitor->msg = MM_SESSION_MSG_RESUME;
1000                         monitor->event = _translate_from_event_src_to_mm_session (event_src);
1001                         g_idle_add((GSourceFunc)_asm_monitor_cb, (gpointer)monitor);
1002                 }
1003                 cb_res = ASM_CB_RES_IGNORE;
1004                 break;
1005
1006         default:
1007                 break;
1008         }
1009         return cb_res;
1010 }
1011
1012 ASM_cb_result_t
1013 asm_watch_callback(int handle, ASM_sound_events_t sound_event, ASM_sound_states_t sound_state, void* cb_data)
1014 {
1015         ASM_cb_result_t cb_res = ASM_CB_RES_NONE;
1016         session_watch_t *watch_handle = (session_watch_t*)cb_data;
1017
1018         debug_log("watch callback called for handle %d, sound_event %d, sound_state %d", handle, sound_event, sound_state);
1019         if(!watch_handle) {
1020                 debug_log("watch_handle instance is null\n");
1021                 return ASM_CB_RES_IGNORE;
1022         }
1023
1024         switch(sound_state) {
1025         case ASM_STATE_PLAYING:
1026                 if(watch_handle->fn) {
1027                         watch_handle->event = _translate_from_asm_event_to_mm_session(sound_event);
1028                         watch_handle->state = MM_SESSION_WATCH_STATE_PLAYING;
1029                         if (watch_handle->event == MM_SESSION_WATCH_EVENT_IGNORE) {
1030                                 cb_res = ASM_CB_RES_IGNORE;
1031                                 debug_error("sound_event(%d) is not valid..", sound_event);
1032                         } else {
1033                                 g_idle_add((GSourceFunc)_asm_watch_cb, (gpointer)watch_handle);
1034                         }
1035                 }
1036                 break;
1037         case ASM_STATE_STOP:
1038                 if(watch_handle->fn) {
1039                         watch_handle->event = _translate_from_asm_event_to_mm_session(sound_event);
1040                         watch_handle->state = MM_SESSION_WATCH_STATE_STOP;
1041                         if (watch_handle->event == MM_SESSION_WATCH_EVENT_IGNORE) {
1042                                 debug_error("sound_event(%d) is not valid..", sound_event);
1043                                 cb_res = ASM_CB_RES_IGNORE;
1044                         } else {
1045                                 g_idle_add((GSourceFunc)_asm_watch_cb, (gpointer)watch_handle);
1046                         }
1047                 }
1048                 break;
1049         default:
1050                 debug_error("sound_state(%d) is not valid..", sound_state);
1051                 cb_res = ASM_CB_RES_IGNORE;
1052                 break;
1053         }
1054         return cb_res;
1055 }
1056
1057 __attribute__ ((destructor))
1058 void __mmsession_finalize(void)
1059 {
1060         int error=0;
1061
1062         debug_fenter();
1063
1064         TRY_LOCK(g_mutex_monitor, error);
1065         if (!error) {
1066                 if(g_monitor_asm_handle != -1) {
1067                         /* Unregister monitor */
1068                         if(!ASM_unregister_sound(g_monitor_asm_handle, ASM_EVENT_MONITOR, &error)) {
1069                                 debug_error("ASM unregister monitor failed");
1070                         } else {
1071                                 debug_log("ASM unregister monitor success");
1072                                 g_monitor_asm_handle = -1;
1073                                 g_monitor_data.fn = NULL;
1074                                 g_monitor_data.data = NULL;
1075                         }
1076                 }
1077                 UNLOCK(g_mutex_monitor);
1078                 DESTROY(g_mutex_monitor);
1079         }
1080         _mm_session_util_delete_information(-1);
1081
1082         debug_fleave();
1083 }
1084
1085 __attribute__ ((constructor))
1086 void __mmsession_initialize(void)
1087 {
1088
1089 }
1090