tizen 2.3 release
[framework/api/sound-manager.git] / src / sound_manager.c
1 /*
2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18 #define LOG_TAG "TIZEN_N_SOUND_MANAGER"
19
20 #include <sound_manager.h>
21 #include <sound_manager_private.h>
22
23 typedef struct {
24         void *user_data;
25         sound_manager_volume_changed_cb user_cb;
26 }_changed_volume_info_s;
27
28 _session_interrupt_info_s g_session_interrupt_cb_table = {0, NULL, NULL};
29 _volume_changed_info_s g_volume_changed_cb_table = {NULL, NULL};
30 _device_connected_info_s g_device_connected_cb_table = {NULL, NULL};
31 _device_changed_info_s g_device_info_changed_cb_table = {NULL, NULL};
32
33 sound_session_type_e g_cached_session = -1;
34 sound_session_voip_mode_e g_cached_voip_mode = -1;
35
36 int sound_manager_get_max_volume(sound_type_e type, int *max)
37 {
38         int volume;
39         if(max == NULL)
40                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
41
42         if(type >= SOUND_TYPE_NUM || type < 0)
43                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
44         int ret = mm_sound_volume_get_step(type, &volume);
45
46         if(ret == 0)
47                 *max = volume -1;       // actual volume step can be max step - 1
48
49         return __convert_sound_manager_error_code(__func__, ret);
50 }
51
52 int sound_manager_set_volume(sound_type_e type, int volume)
53 {
54         if(type >= SOUND_TYPE_NUM || type < 0)
55                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
56         if(volume < 0)
57                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
58
59         int ret = mm_sound_volume_set_value(type, volume);
60         LOGI("returns : type=%d, volume=%d, ret=0x%x", type, volume, ret);
61
62         return __convert_sound_manager_error_code(__func__, ret);
63 }
64
65 int sound_manager_get_volume(sound_type_e type, int *volume)
66 {
67         unsigned int uvolume;
68         if(type >= SOUND_TYPE_NUM || type < 0)
69                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
70         if(volume == NULL)
71                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
72         int ret = mm_sound_volume_get_value(type, &uvolume);
73
74         if(ret == 0)
75                 *volume = uvolume;
76
77         LOGI("returns : type=%d, volume=%d, ret=0x%x", type, *volume, ret);
78
79         return __convert_sound_manager_error_code(__func__, ret);
80 }
81
82 int sound_manager_set_current_sound_type(sound_type_e type)
83 {
84         int ret = MM_ERROR_NONE;
85         if(type >= SOUND_TYPE_NUM || type < 0)
86                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
87
88         ret = mm_sound_volume_primary_type_set(type);
89
90         return __convert_sound_manager_error_code(__func__, ret);
91 }
92
93 int sound_manager_get_current_sound_type(sound_type_e *type)
94 {
95         int ret = MM_ERROR_NONE;
96         if(type == NULL)
97                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
98         ret = mm_sound_volume_get_current_playing_type((volume_type_t *)type);
99
100         LOGI("returns : type=%d, ret=0x%x", *type, ret);
101
102         return __convert_sound_manager_error_code(__func__, ret);
103 }
104
105 int sound_manager_unset_current_sound_type(void)
106 {
107         int ret = MM_ERROR_NONE;
108         ret = mm_sound_volume_primary_type_clear();
109
110         return __convert_sound_manager_error_code(__func__, ret);
111 }
112
113 int sound_manager_set_volume_changed_cb(sound_manager_volume_changed_cb callback, void* user_data)
114 {
115         int ret = MM_ERROR_NONE;
116         ret = mm_sound_add_volume_changed_callback((mm_sound_volume_changed_cb)callback, user_data);
117         if (ret == MM_ERROR_NONE) {
118                 g_volume_changed_cb_table.user_cb = (sound_manager_volume_changed_cb)callback;
119                 g_volume_changed_cb_table.user_data = user_data;
120         }
121
122         return __convert_sound_manager_error_code(__func__, ret);
123 }
124
125 int sound_manager_unset_volume_changed_cb(void)
126 {
127         int ret = MM_ERROR_NONE;
128         if (g_volume_changed_cb_table.user_cb) {
129                 ret = mm_sound_remove_volume_changed_callback();
130                 if (ret == MM_ERROR_NONE) {
131                         g_volume_changed_cb_table.user_cb = NULL;
132                         g_volume_changed_cb_table.user_data = NULL;
133                 }
134         } else {
135                 ret = MM_ERROR_SOUND_INTERNAL;
136         }
137
138         return __convert_sound_manager_error_code(__func__, ret);
139 }
140
141 int sound_manager_set_session_type(sound_session_type_e type)
142 {
143         int ret = MM_ERROR_NONE;
144         int cur_session = -1;
145         int new_session = MM_SESSION_TYPE_MEDIA;
146
147         LOGI(">> enter : type=%d", type);
148
149         if(type < SOUND_SESSION_TYPE_MEDIA || type >  SOUND_SESSION_TYPE_VOIP)
150                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
151
152         switch(type) {
153         case SOUND_SESSION_TYPE_MEDIA:
154                 new_session = MM_SESSION_TYPE_MEDIA;
155                 break;
156         case SOUND_SESSION_TYPE_ALARM:
157                 new_session = MM_SESSION_TYPE_ALARM;
158                 break;
159         case SOUND_SESSION_TYPE_NOTIFICATION:
160                 new_session = MM_SESSION_TYPE_NOTIFY;
161                 break;
162         case SOUND_SESSION_TYPE_EMERGENCY:
163                 new_session = MM_SESSION_TYPE_EMERGENCY;
164                 break;
165         case SOUND_SESSION_TYPE_VOIP:
166                 new_session = MM_SESSION_TYPE_VOIP;
167                 break;
168         }
169
170         /* valid session check */
171         ret = mm_session_get_current_type(&cur_session);
172         if(ret == 0) {
173                 if (cur_session == MM_SESSION_TYPE_MEDIA_RECORD) {
174                         if (type > SOUND_SESSION_TYPE_MEDIA) {
175                                 LOGE("<< leave : Could not set this type(%d) during camera/recorder/audio-io(in)/radio", type);
176                                 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
177                         }
178                 }
179                 if (cur_session == MM_SESSION_TYPE_CALL ||
180                         cur_session == MM_SESSION_TYPE_VIDEOCALL ||
181                         cur_session >= MM_SESSION_TYPE_VOICE_RECOGNITION) {
182                         return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
183                 }
184         }
185
186         if(g_session_interrupt_cb_table.is_registered) {
187                 if (new_session == cur_session ||
188                         ((new_session == SOUND_SESSION_TYPE_MEDIA) && (cur_session == MM_SESSION_TYPE_MEDIA_RECORD))) {
189                         LOGI("<< leave : already set type=%d, ret=0x%x", type, ret);
190                         return SOUND_MANAGER_ERROR_NONE;
191                 } else {
192                         ret = mm_session_finish();
193                         if (ret != MM_ERROR_NONE) {
194                                 return __convert_sound_manager_error_code(__func__, ret);
195                         }
196                         g_session_interrupt_cb_table.is_registered = 0;
197                         g_cached_voip_mode = -1;
198                 }
199         }
200         ret = mm_session_init_ex(new_session , __session_interrupt_cb, NULL);
201         if(ret == 0){
202                 g_session_interrupt_cb_table.is_registered = 1;
203         }
204         if (new_session == MM_SESSION_TYPE_VOIP) {
205                 /* set default sub-session for voip */
206                 ret = mm_session_set_subsession (MM_SUBSESSION_TYPE_RINGTONE, MM_SUBSESSION_OPTION_NONE);
207                 if (ret != MM_ERROR_NONE) {
208                         return __convert_sound_manager_error_code(__func__, ret);
209                 }
210                 g_cached_voip_mode = SOUND_SESSION_VOIP_MODE_RINGTONE;
211         }
212         LOGI("<< leave : type=%d, ret=0x%x", type, ret);
213
214         return __convert_sound_manager_error_code(__func__, ret);
215 }
216
217 int sound_manager_get_session_type(sound_session_type_e *type)
218 {
219         int ret = MM_ERROR_NONE;
220         int cur_session;
221
222         if( type == NULL )
223                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
224         ret = mm_session_get_current_type(&cur_session);
225         if (ret != 0)
226                 cur_session = SOUND_SESSION_TYPE_DEFAULT;
227         if ((cur_session > MM_SESSION_TYPE_EMERGENCY) && (cur_session != MM_SESSION_TYPE_VOIP)) {
228                 if( g_cached_session != -1 )
229                         cur_session = g_cached_session;
230                 else //will be never reach here. just prevent code
231                         cur_session = SOUND_SESSION_TYPE_DEFAULT;
232         }
233
234         switch(cur_session) {
235         case MM_SESSION_TYPE_MEDIA:
236         case MM_SESSION_TYPE_MEDIA_RECORD:
237                 *type = SOUND_SESSION_TYPE_MEDIA;
238                 break;
239         case MM_SESSION_TYPE_ALARM:
240                 *type = SOUND_SESSION_TYPE_ALARM;
241                 break;
242         case MM_SESSION_TYPE_NOTIFY:
243                 *type = SOUND_SESSION_TYPE_NOTIFICATION;
244                 break;
245         case MM_SESSION_TYPE_EMERGENCY:
246                 *type = SOUND_SESSION_TYPE_EMERGENCY;
247                 break;
248         case MM_SESSION_TYPE_VOIP:
249                 *type = SOUND_SESSION_TYPE_VOIP;
250                 break;
251         default:
252                 *type = cur_session;
253                 break;
254         }
255
256         LOGI("returns : type=%d, ret=0x%x", *type, ret);
257
258         return 0;
259 }
260
261 int sound_manager_set_media_session_option(sound_session_option_for_starting_e s_option, sound_session_option_for_during_play_e d_option)
262 {
263         int ret = MM_ERROR_NONE;
264         int session = 0;
265         int session_option = 0;
266         int updated = 0;
267
268         LOGI(">> enter : option for starting=%d, for during play=%d", s_option, d_option);
269
270         if(s_option < 0 || s_option >  SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START)
271                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
272         if(d_option < 0 || d_option >  SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY)
273                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
274
275         ret = mm_session_get_current_information(&session, &session_option);
276         if ( ret != 0 || !g_session_interrupt_cb_table.is_registered) {
277                 LOGW("need to set session type first");
278                 return __convert_sound_manager_error_code(__func__, ret);
279         } else if ( ret == 0 && session > MM_SESSION_TYPE_MEDIA ) {
280                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
281                         if (!g_session_interrupt_cb_table.is_registered) {
282                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
283                                 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
284                         }
285                 } else {
286                         return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
287                 }
288         }
289
290         switch (s_option) {
291         case SOUND_SESSION_OPTION_MIX_WITH_OTHERS_WHEN_START:
292                 if (session_option & MM_SESSION_OPTION_PAUSE_OTHERS) {
293                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_PAUSE_OTHERS);
294                         if(ret){
295                                 return __convert_sound_manager_error_code(__func__, ret);
296                         }
297                         updated = 1;
298                 }
299                 break;
300         case SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START:
301                 if (!(session_option & MM_SESSION_OPTION_PAUSE_OTHERS)) {
302                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_PAUSE_OTHERS);
303                         if(ret){
304                                 return __convert_sound_manager_error_code(__func__, ret);
305                         }
306                         updated = 1;
307                 }
308                 break;
309         }
310
311         switch (d_option) {
312         case SOUND_SESSION_OPTION_INTERRUPTIBLE_DURING_PLAY:
313                 if (session_option & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
314                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_UNINTERRUPTIBLE);
315                         if(ret){
316                                 return __convert_sound_manager_error_code(__func__, ret);
317                         }
318                         updated = 1;
319                 }
320                 break;
321         case SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY:
322                 if (!(session_option & MM_SESSION_OPTION_UNINTERRUPTIBLE)) {
323                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_UNINTERRUPTIBLE);
324                         if(ret){
325                                 return __convert_sound_manager_error_code(__func__, ret);
326                         }
327                         updated = 1;
328                 }
329                 break;
330         }
331
332         if (updated) {
333                 LOGI("<< leave : updated");
334         } else {
335                 LOGI("<< leave : already set same option(%x), skip it", session_option);
336         }
337
338         return __convert_sound_manager_error_code(__func__, ret);
339 }
340
341 int sound_manager_get_media_session_option(sound_session_option_for_starting_e *s_option, sound_session_option_for_during_play_e *d_option)
342 {
343         int ret = MM_ERROR_NONE;
344         int session = 0;
345         int session_options = 0;
346
347         LOGI(">> enter");
348
349         if( s_option == NULL || d_option == NULL )
350                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
351
352         ret = mm_session_get_current_information(&session, &session_options);
353         if( ret != 0 ) {
354                 return __convert_sound_manager_error_code(__func__, ret);
355         } else if (session > SOUND_SESSION_TYPE_MEDIA ) {
356                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
357                         if (!g_session_interrupt_cb_table.is_registered) {
358                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
359                                 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
360                         }
361                 } else {
362                         return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
363                 }
364         }
365         /* get option */
366         if (session_options & MM_SESSION_OPTION_PAUSE_OTHERS) {
367                 *s_option = SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START;
368         } else {
369                 *s_option = SOUND_SESSION_OPTION_MIX_WITH_OTHERS_WHEN_START;
370         }
371         if (session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
372                 *d_option = SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY;
373         } else {
374                 *d_option = SOUND_SESSION_OPTION_INTERRUPTIBLE_DURING_PLAY;
375         }
376
377         LOGI("<< leave : option for starting=%d, for during play=%d", *s_option, *d_option);
378
379         return SOUND_MANAGER_ERROR_NONE;
380 }
381
382 int sound_manager_set_media_session_resumption_option(sound_session_option_for_resumption_e option)
383 {
384         int ret = MM_ERROR_NONE;
385         int session = 0;
386         int session_option = 0;
387         int updated = 0;
388
389         LOGI(">> enter : option for resumption=%d (0:by system, 1:by system or media paused)", option);
390
391         if(option < SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM || option > SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED)
392                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
393
394         ret = mm_session_get_current_information(&session, &session_option);
395         if ( ret != 0 || !g_session_interrupt_cb_table.is_registered) {
396                 LOGW("need to set session type first");
397                 return __convert_sound_manager_error_code(__func__, ret);
398         } else if ( ret == 0 && session > MM_SESSION_TYPE_MEDIA ) {
399                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
400                         if (!g_session_interrupt_cb_table.is_registered) {
401                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
402                                 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
403                         }
404                 } else {
405                         return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
406                 }
407         }
408
409         switch (option) {
410         case SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM:
411                 if (session_option & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED) {
412                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED);
413                         if(ret){
414                                 return __convert_sound_manager_error_code(__func__, ret);
415                         }
416                         updated = 1;
417                 }
418                 break;
419         case SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED:
420                 if (!(session_option & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED)) {
421                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED);
422                         if(ret){
423                                 return __convert_sound_manager_error_code(__func__, ret);
424                         }
425                         updated = 1;
426                 }
427                 break;
428         }
429
430         if (updated) {
431                 LOGI("<< leave : updated");
432         } else {
433                 LOGI("<< leave : already set same option(%x), skip it", session_option);
434         }
435
436         return __convert_sound_manager_error_code(__func__, ret);
437 }
438
439 int sound_manager_get_media_session_resumption_option(sound_session_option_for_resumption_e *option)
440 {
441         int ret = MM_ERROR_NONE;
442         int session = 0;
443         int session_options = 0;
444
445         LOGI(">> enter");
446
447         if( option == NULL )
448                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
449         ret = mm_session_get_current_information(&session, &session_options);
450         if( ret != 0 ) {
451                 return __convert_sound_manager_error_code(__func__, ret);
452         } else if (session > SOUND_SESSION_TYPE_MEDIA ) {
453                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
454                         if (!g_session_interrupt_cb_table.is_registered) {
455                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
456                                 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
457                         }
458                 } else {
459                         return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
460                 }
461         }
462         /* get option */
463         if (session_options & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED) {
464                 *option = SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED;
465         } else {
466                 *option = SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM;
467         }
468
469         LOGI("<< leave : option for resumption=%d (0:by system, 1:by system or media paused)", *option);
470
471         return SOUND_MANAGER_ERROR_NONE;
472 }
473
474 int sound_manager_set_voip_session_mode(sound_session_voip_mode_e mode)
475 {
476         int ret = MM_ERROR_NONE;
477         int session = 0;
478         int session_options = 0;
479
480         LOGI(">> enter : mode=%d", mode);
481
482         ret = mm_session_get_current_information(&session, &session_options);
483         if( ret != MM_ERROR_NONE ) {
484                 return __convert_sound_manager_error_code(__func__, ret);
485         } else if (session != MM_SESSION_TYPE_VOIP ) {
486                 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
487         }
488
489         if(mode < SOUND_SESSION_VOIP_MODE_RINGTONE || mode > SOUND_SESSION_VOIP_MODE_VOICE_WITH_BLUETOOTH) {
490                 ret = MM_ERROR_INVALID_ARGUMENT;
491                 return __convert_sound_manager_error_code(__func__, ret);
492         }
493
494         if (mode == SOUND_SESSION_VOIP_MODE_RINGTONE) {
495                 /* sub-session */
496                 if (g_cached_voip_mode != mode) {
497                         ret = mm_session_set_subsession (MM_SUBSESSION_TYPE_RINGTONE, MM_SUBSESSION_OPTION_NONE);
498                         if (ret != MM_ERROR_NONE) {
499                                 return __convert_sound_manager_error_code(__func__, ret);
500                         }
501                 }
502                 g_cached_voip_mode = mode;
503         } else {
504                 mm_sound_route route;
505                 bool need_to_check_device = false;
506                 bool do_subsession = true;
507                 switch (mode) {
508                 case SOUND_SESSION_VOIP_MODE_RINGTONE:
509                         do_subsession = false;
510                         break;
511                 case SOUND_SESSION_VOIP_MODE_VOICE_WITH_BUILTIN_RECEIVER:
512                         route = MM_SOUND_ROUTE_IN_MIC_OUT_RECEIVER;
513                         break;
514                 case SOUND_SESSION_VOIP_MODE_VOICE_WITH_BUILTIN_SPEAKER:
515                         route = MM_SOUND_ROUTE_IN_MIC_OUT_SPEAKER;
516                         break;
517                 case SOUND_SESSION_VOIP_MODE_VOICE_WITH_AUDIO_JACK:
518                         route = MM_SOUND_ROUTE_IN_MIC_OUT_HEADPHONE;
519                         need_to_check_device = true;
520                         break;
521                 case SOUND_SESSION_VOIP_MODE_VOICE_WITH_BLUETOOTH:
522                         route = MM_SOUND_ROUTE_INOUT_BLUETOOTH;
523                         need_to_check_device = true;
524                         break;
525                 }
526
527                 if (need_to_check_device) {
528                         int w_ret = MM_ERROR_NONE;
529                         MMSoundDeviceList_t device_list;
530                         MMSoundDevice_t device;
531                         do_subsession = false;
532
533                         ret = mm_sound_get_current_device_list(MM_SOUND_DEVICE_STATE_DEACTIVATED_FLAG, &device_list);
534                         if (ret != MM_ERROR_NONE) {
535                                 return __convert_sound_manager_error_code(__func__, ret);
536                         } else {
537                                 while ((w_ret = mm_sound_get_next_device(device_list, &device)) == MM_ERROR_NONE) {
538                                         mm_sound_device_type_e type;
539                                         ret = mm_sound_get_device_type(device, &type);
540                                         if (ret != MM_ERROR_NONE)
541                                                 return __convert_sound_manager_error_code(__func__, ret);
542
543                                         switch (mode) {
544                                         case SOUND_SESSION_VOIP_MODE_VOICE_WITH_AUDIO_JACK:
545                                                 if (type == MM_SOUND_DEVICE_TYPE_AUDIOJACK)
546                                                         do_subsession = true;
547                                                 break;
548                                         case SOUND_SESSION_VOIP_MODE_VOICE_WITH_BLUETOOTH:
549                                                 if (type == MM_SOUND_DEVICE_TYPE_BLUETOOTH) {
550                                                         mm_sound_device_io_direction_e io_direction;
551                                                         ret = mm_sound_get_device_io_direction(device, &io_direction);
552                                                         if (ret != MM_ERROR_NONE)
553                                                                 return __convert_sound_manager_error_code(__func__, ret);
554                                                         if (io_direction == MM_SOUND_DEVICE_IO_DIRECTION_BOTH)
555                                                                 do_subsession = true;
556                                                 }
557                                                 break;
558                                         default:
559                                                 break;
560                                         }
561                                 }
562                         }
563                 }
564                 /* sub-session */
565                 if (do_subsession && (g_cached_voip_mode != mode)) {
566                         ret = mm_session_set_subsession (MM_SUBSESSION_TYPE_VOICE, MM_SUBSESSION_OPTION_NONE);
567                         if (ret != MM_ERROR_NONE) {
568                                 return __convert_sound_manager_error_code(__func__, ret);
569                         }
570                         /* route */
571                         ret = mm_sound_set_active_route(route);
572                         if (ret != MM_ERROR_NONE) {
573                                 return __convert_sound_manager_error_code(__func__, ret);
574                         }
575                         g_cached_voip_mode = mode;
576                 } else {
577                         if (!do_subsession)
578                                 ret = MM_ERROR_SOUND_INTERNAL;
579                 }
580         }
581
582         LOGI("<< leave : session=%p, mode=%d, ret=0x%x", session, mode, ret);
583
584         return __convert_sound_manager_error_code(__func__, ret);
585 }
586
587 int sound_manager_get_voip_session_mode(sound_session_voip_mode_e *mode)
588 {
589         int ret = MM_ERROR_NONE;
590         int session = 0;
591         int session_options = 0;
592         int subsession = 0;
593
594         if(mode == NULL) {
595                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
596         }
597
598         ret = mm_session_get_current_information(&session, &session_options);
599         if( ret != MM_ERROR_NONE ) {
600                 return __convert_sound_manager_error_code(__func__, ret);
601         } else if (session != MM_SESSION_TYPE_VOIP ) {
602                 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
603         }
604
605         ret = mm_session_get_subsession ((mm_subsession_t *)&subsession);
606         if(ret != MM_ERROR_NONE) {
607                 return __convert_sound_manager_error_code(__func__, ret);
608         }
609         switch (subsession) {
610         case MM_SUBSESSION_TYPE_VOICE:
611         {
612                 int w_ret = MM_ERROR_NONE;
613                 bool need_to_out = false;
614                 MMSoundDeviceList_t device_list;
615                 MMSoundDevice_t device;
616                 ret = mm_sound_get_current_device_list(MM_SOUND_DEVICE_STATE_ACTIVATED_FLAG, &device_list);
617                 if (ret != MM_ERROR_NONE) {
618                         return __convert_sound_manager_error_code(__func__, ret);
619                 } else {
620                         while ((w_ret = mm_sound_get_next_device(device_list, &device)) == MM_ERROR_NONE) {
621                                 mm_sound_device_type_e type;
622                                 ret = mm_sound_get_device_type(device, &type);
623                                 if (ret != MM_ERROR_NONE)
624                                         return __convert_sound_manager_error_code(__func__, ret);
625                                 switch (type) {
626                                 case MM_SOUND_DEVICE_TYPE_BUILTIN_SPEAKER:
627                                         *mode = SOUND_SESSION_VOIP_MODE_VOICE_WITH_BUILTIN_SPEAKER;
628                                         need_to_out = true;
629                                         break;
630                                 case MM_SOUND_DEVICE_TYPE_BUILTIN_RECEIVER:
631                                         *mode = SOUND_SESSION_VOIP_MODE_VOICE_WITH_BUILTIN_RECEIVER;
632                                         need_to_out = true;
633                                         break;
634                                 case MM_SOUND_DEVICE_TYPE_AUDIOJACK:
635                                         *mode = SOUND_SESSION_VOIP_MODE_VOICE_WITH_AUDIO_JACK;
636                                         need_to_out = true;
637                                         break;
638                                 case MM_SOUND_DEVICE_TYPE_BLUETOOTH:
639                                         *mode = SOUND_SESSION_VOIP_MODE_VOICE_WITH_BLUETOOTH;
640                                         need_to_out = true;
641                                         break;
642                                 default:
643                                         break;
644                                 }
645                                 if (need_to_out)
646                                         break;
647                         }
648                 }
649         }
650                 break;
651         case MM_SUBSESSION_TYPE_RINGTONE:
652                 *mode = SOUND_SESSION_VOIP_MODE_RINGTONE;
653                 break;
654         default:
655                 break;
656         }
657
658         LOGI("returns : session=%p, mode=%d, ret=0x%x", session, *mode, ret);
659
660         return __convert_sound_manager_error_code(__func__, ret);
661 }
662
663 int sound_manager_set_session_interrupted_cb(sound_session_interrupted_cb callback, void *user_data)
664 {
665         int ret = MM_ERROR_NONE;
666         if(callback == NULL)
667                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
668
669         if(g_session_interrupt_cb_table.is_registered ==0){
670                 ret = mm_session_init_ex(SOUND_SESSION_TYPE_DEFAULT /*default*/ , __session_interrupt_cb, NULL);
671                 if(ret != 0)
672                         return __convert_sound_manager_error_code(__func__, ret);
673                 g_session_interrupt_cb_table.is_registered = 1;
674         }
675
676         g_session_interrupt_cb_table.user_cb = (sound_session_interrupted_cb)callback;
677         g_session_interrupt_cb_table.user_data = user_data;
678         return SOUND_MANAGER_ERROR_NONE;
679 }
680
681 int sound_manager_unset_session_interrupted_cb(void)
682 {
683         int ret = MM_ERROR_NONE;
684         if (g_session_interrupt_cb_table.user_cb) {
685                 g_session_interrupt_cb_table.user_cb = NULL;
686                 g_session_interrupt_cb_table.user_data = NULL;
687         } else {
688                 ret = MM_ERROR_SOUND_INTERNAL;
689         }
690         return __convert_sound_manager_error_code(__func__, ret);
691 }
692
693 int sound_manager_get_current_device_list(sound_device_mask_e device_mask, sound_device_list_h *device_list)
694 {
695         int ret = MM_ERROR_NONE;
696         ret = mm_sound_get_current_device_list((mm_sound_device_flags_e)device_mask, device_list);
697
698         return __convert_sound_manager_error_code(__func__, ret);
699 }
700
701 int sound_manager_get_next_device (sound_device_list_h device_list, sound_device_h *device)
702 {
703         int ret = MM_ERROR_NONE;
704         ret = mm_sound_get_next_device(device_list, device);
705
706         return __convert_sound_manager_error_code(__func__, ret);
707 }
708
709 int sound_manager_get_prev_device (sound_device_list_h device_list, sound_device_h *device)
710 {
711         int ret = MM_ERROR_NONE;
712         ret = mm_sound_get_prev_device(device_list, device);
713
714         return __convert_sound_manager_error_code(__func__, ret);
715 }
716
717 int sound_manager_get_device_type (sound_device_h device, sound_device_type_e *type)
718 {
719         int ret = MM_ERROR_NONE;
720         ret = mm_sound_get_device_type(device, (mm_sound_device_type_e*)type);
721
722         return __convert_sound_manager_error_code(__func__, ret);
723 }
724
725 int sound_manager_get_device_io_direction (sound_device_h device, sound_device_io_direction_e *io_direction)
726 {
727         int ret = MM_ERROR_NONE;
728         ret = mm_sound_get_device_io_direction(device, (mm_sound_device_io_direction_e*)io_direction);
729
730         return __convert_sound_manager_error_code(__func__, ret);
731 }
732
733 int sound_manager_get_device_id (sound_device_h device, int *id)
734 {
735         int ret = MM_ERROR_NONE;
736         ret = mm_sound_get_device_id(device, id);
737
738         return __convert_sound_manager_error_code(__func__, ret);
739 }
740
741 int sound_manager_get_device_name (sound_device_h device, char **name)
742 {
743         int ret = MM_ERROR_NONE;
744         ret = mm_sound_get_device_name(device, name);
745
746         return __convert_sound_manager_error_code(__func__, ret);
747 }
748
749 int sound_manager_get_device_state (sound_device_h device, sound_device_state_e *state)
750 {
751         int ret = MM_ERROR_NONE;
752         ret = mm_sound_get_device_state(device, (mm_sound_device_state_e*)state);
753
754         return __convert_sound_manager_error_code(__func__, ret);
755 }
756
757 int sound_manager_set_device_connected_cb (sound_device_mask_e device_mask, sound_device_connected_cb callback, void *user_data)
758 {
759         int ret = MM_ERROR_NONE;
760         ret = mm_sound_add_device_connected_callback((mm_sound_device_flags_e)device_mask, (mm_sound_device_connected_cb)callback, user_data);
761         if (ret == MM_ERROR_NONE) {
762                 g_device_connected_cb_table.user_cb = (sound_device_connected_cb)callback;
763                 g_device_connected_cb_table.user_data = user_data;
764         }
765
766         return __convert_sound_manager_error_code(__func__, ret);
767 }
768
769 int sound_manager_unset_device_connected_cb (void)
770 {
771         int ret = MM_ERROR_NONE;
772         if (g_device_connected_cb_table.user_cb) {
773                 ret = mm_sound_remove_device_connected_callback();
774                 if (ret == MM_ERROR_NONE) {
775                         g_device_connected_cb_table.user_cb = NULL;
776                         g_device_connected_cb_table.user_data = NULL;
777                 }
778         } else {
779                 ret = MM_ERROR_SOUND_INTERNAL;
780         }
781
782         return __convert_sound_manager_error_code(__func__, ret);
783 }
784
785 int sound_manager_set_device_information_changed_cb (sound_device_mask_e device_mask, sound_device_information_changed_cb callback, void *user_data)
786 {
787         int ret = MM_ERROR_NONE;
788         ret = mm_sound_add_device_information_changed_callback((mm_sound_device_flags_e)device_mask, (mm_sound_device_info_changed_cb)callback, user_data);
789         if (ret == MM_ERROR_NONE) {
790                 g_device_info_changed_cb_table.user_cb = (sound_device_information_changed_cb)callback;
791                 g_device_info_changed_cb_table.user_data = user_data;
792         }
793
794         return __convert_sound_manager_error_code(__func__, ret);
795 }
796
797 int sound_manager_unset_device_information_changed_cb (void)
798 {
799         int ret = MM_ERROR_NONE;
800         if (g_device_info_changed_cb_table.user_cb) {
801                 ret = mm_sound_remove_device_information_changed_callback();
802                 if (ret == MM_ERROR_NONE) {
803                         g_device_info_changed_cb_table.user_cb = NULL;
804                         g_device_info_changed_cb_table.user_data = NULL;
805                 }
806         } else {
807                 ret = MM_ERROR_SOUND_INTERNAL;
808         }
809
810         return __convert_sound_manager_error_code(__func__, ret);
811 }
812
813 __attribute__ ((destructor))
814 void __sound_manager_finalize(void)
815 {
816         int ret = MM_ERROR_NONE;
817
818         if(g_session_interrupt_cb_table.is_registered){
819                 LOGI("<ENTER>");
820                 ret = mm_session_finish();
821                 if (ret != MM_ERROR_NONE) {
822                         LOGE("[%s] failed to mm_session_finish(), ret(0x%x)", __func__, ret);
823                 }
824                 g_session_interrupt_cb_table.is_registered = 0;
825                 LOGI("<LEAVE>");
826         }
827 }
828
829 __attribute__ ((constructor))
830 void __sound_manager_initialize(void)
831 {
832
833 }