Add new API for getting the sound type of the stream info handle
[platform/core/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 #include "sound_manager.h"
18 #include "sound_manager_private.h"
19
20
21 _session_interrupt_info_s g_session_interrupt_cb_table = {0, 0, NULL, NULL};
22 _volume_changed_info_s g_volume_changed_cb_table = {0, NULL, NULL};
23 _focus_watch_info_s g_focus_watch_cb_table = {-1, NULL, NULL};
24 _device_connected_info_s g_device_connected_cb_table = {0, NULL, NULL};
25 _device_changed_info_s g_device_info_changed_cb_table = {0, NULL, NULL};
26
27 sound_session_type_e g_cached_session = -1;
28 _session_mode_e g_cached_session_mode = -1;
29 int g_cached_voip_device_id = -1;
30 extern sound_stream_info_s *g_voip_stream_info;
31 extern virtual_sound_stream_info_s *g_voip_vstream_h;
32
33 /* These variables will be removed when session features are deprecated. */
34 extern int g_stream_info_count;
35 extern pthread_mutex_t g_stream_info_count_mutex;
36 pthread_mutex_t g_interrupt_cb_mutex, g_device_info_cb_mutex, g_device_conn_cb_mutex, g_volume_cb_mutex;
37
38 int sound_manager_get_max_volume(sound_type_e type, int *max)
39 {
40         const char *volume_type = NULL;
41         unsigned int max_level = 0;
42         int ret = MM_ERROR_NONE;
43
44         if (max == NULL)
45                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
46
47         if (type >= SOUND_TYPE_NUM || type < 0)
48                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
49         ret = _convert_sound_type(type, &volume_type);
50         if (ret == MM_ERROR_NONE) {
51                 ret = _get_volume_max_level("out", volume_type, &max_level);
52                 if (ret == MM_ERROR_NONE)
53                         *max = (int)max_level -1;       /* actual volume step can be max step - 1 */
54         }
55
56         return _convert_sound_manager_error_code(__func__, ret);
57 }
58
59 int sound_manager_set_volume(sound_type_e type, int volume)
60 {
61         int ret = MM_ERROR_NONE;
62
63         if (type >= SOUND_TYPE_NUM || type < 0)
64                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
65         if (volume < 0)
66                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
67
68         ret = mm_sound_volume_set_value(type, volume);
69         LOGI("returns : type=%d, volume=%d, ret=%p", type, volume, ret);
70
71         return _convert_sound_manager_error_code(__func__, ret);
72 }
73
74 int sound_manager_get_volume(sound_type_e type, int *volume)
75 {
76         int ret = MM_ERROR_NONE;
77         unsigned int uvolume;
78
79         if (type >= SOUND_TYPE_NUM || type < 0)
80                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
81         if (volume == NULL)
82                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
83
84         ret = mm_sound_volume_get_value(type, &uvolume);
85         if (ret == MM_ERROR_NONE)
86                 *volume = uvolume;
87
88         LOGI("returns : type=%d, volume=%d, ret=%p", type, *volume, ret);
89
90         return _convert_sound_manager_error_code(__func__, ret);
91 }
92
93 int sound_manager_set_current_sound_type(sound_type_e type)
94 {
95         int ret = MM_ERROR_NONE;
96
97         if (type >= SOUND_TYPE_NUM || type < 0)
98                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
99
100         ret = mm_sound_volume_primary_type_set(type);
101
102         return _convert_sound_manager_error_code(__func__, ret);
103 }
104
105 int sound_manager_get_current_sound_type(sound_type_e *type)
106 {
107         int ret = MM_ERROR_NONE;
108         volume_type_t mm_sound_vol_type = VOLUME_TYPE_UNKNOWN;
109         char *volume_type = NULL;
110
111         if (type == NULL)
112                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
113
114         ret  = mm_sound_volume_primary_type_get(&mm_sound_vol_type);
115         if (ret == MM_ERROR_NONE) {
116                 if (mm_sound_vol_type == VOLUME_TYPE_UNKNOWN) {
117                         /* get the volume type of the current playing stream */
118                         ret = _get_current_volume_type("out", &volume_type);
119                         if (ret == MM_ERROR_NONE)
120                                 ret = _convert_sound_type_to_enum((const char*)volume_type, type);
121                 } else {
122                         *type = mm_sound_vol_type;
123                 }
124         }
125         LOGI("returns : type=%d, ret=%p", *type, ret);
126
127         return _convert_sound_manager_error_code(__func__, ret);
128 }
129
130 int sound_manager_unset_current_sound_type(void)
131 {
132         int ret = MM_ERROR_NONE;
133
134         ret = mm_sound_volume_primary_type_set(VOLUME_TYPE_UNKNOWN);
135
136         return _convert_sound_manager_error_code(__func__, ret);
137 }
138
139 int sound_manager_set_volume_changed_cb(sound_manager_volume_changed_cb callback, void* user_data)
140 {
141         int ret = MM_ERROR_NONE;
142         unsigned int subs_id = 0;
143
144         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_volume_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
145
146         ret = mm_sound_add_volume_changed_callback((mm_sound_volume_changed_cb)callback, user_data, &subs_id);
147         if (ret == MM_ERROR_NONE) {
148                 g_volume_changed_cb_table.subs_id = subs_id;
149                 g_volume_changed_cb_table.user_cb = (sound_manager_volume_changed_cb)callback;
150                 g_volume_changed_cb_table.user_data = user_data;
151         }
152
153         SM_LEAVE_CRITICAL_SECTION(&g_volume_cb_mutex);
154
155         return _convert_sound_manager_error_code(__func__, ret);
156 }
157
158 int sound_manager_unset_volume_changed_cb(void)
159 {
160         int ret = MM_ERROR_NONE;
161
162         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_volume_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
163
164         if (g_volume_changed_cb_table.subs_id > 0) {
165                 ret = mm_sound_remove_volume_changed_callback(g_volume_changed_cb_table.subs_id);
166                 if (ret == MM_ERROR_NONE) {
167                         g_volume_changed_cb_table.subs_id = 0;
168                         g_volume_changed_cb_table.user_cb = NULL;
169                         g_volume_changed_cb_table.user_data = NULL;
170                 }
171         } else {
172                 ret = MM_ERROR_SOUND_INTERNAL;
173         }
174
175         SM_LEAVE_CRITICAL_SECTION(&g_volume_cb_mutex);
176
177         return _convert_sound_manager_error_code(__func__, ret);
178 }
179
180 int sound_manager_create_stream_information(sound_stream_type_e stream_type, sound_stream_focus_state_changed_cb callback, void *user_data, sound_stream_info_h *stream_info)
181 {
182         int ret = MM_ERROR_NONE;
183
184         LOGI(">> enter");
185
186         SM_NULL_ARG_CHECK(stream_info);
187         SM_NULL_ARG_CHECK(callback);
188
189         if (g_session_interrupt_cb_table.is_registered)
190                 return _convert_sound_manager_error_code(__func__, MM_ERROR_SOUND_INTERNAL);
191
192         sound_stream_info_s *stream_h = malloc(sizeof(sound_stream_info_s));
193         if (!stream_h) {
194                 ret = MM_ERROR_OUT_OF_MEMORY;
195         } else {
196                 memset(stream_h, 0, sizeof(sound_stream_info_s));
197                 ret = _convert_stream_type(stream_type, &stream_h->stream_type);
198                 if (ret == MM_ERROR_NONE) {
199                         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, MM_ERROR_SOUND_INTERNAL);
200                         ret = _make_pa_connection_and_register_focus(stream_h, callback, user_data);
201                         if (ret == MM_ERROR_NONE) {
202                                 *stream_info = (sound_stream_info_h)stream_h;
203                                 SM_REF_FOR_STREAM_INFO(g_stream_info_count, ret);
204                                 LOGI("<< leave : stream_h(%p), index(%u), user_cb(%p), cnt(%d), ret(%p)", stream_h, stream_h->index, stream_h->user_cb, g_stream_info_count, ret);
205                         }
206                         SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
207                 }
208                 if (ret)
209                         free(stream_h);
210         }
211
212         return _convert_sound_manager_error_code(__func__, ret);
213 }
214
215 int sound_manager_destroy_stream_information(sound_stream_info_h stream_info)
216 {
217         int ret = MM_ERROR_NONE;
218         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
219
220         LOGI(">> enter");
221
222         SM_INSTANCE_CHECK(stream_h);
223
224         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, MM_ERROR_SOUND_INTERNAL);
225         ret = _destroy_pa_connection_and_unregister_focus(stream_h);
226         free(stream_h);
227         stream_h = NULL;
228         SM_UNREF_FOR_STREAM_INFO(g_stream_info_count, ret);
229         SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
230
231         LOGI("<< leave : cnt(%d), ret(%p)", g_stream_info_count, ret);
232
233         return _convert_sound_manager_error_code(__func__, ret);
234 }
235
236 int sound_manager_add_device_for_stream_routing(sound_stream_info_h stream_info, sound_device_h device)
237 {
238         int ret = MM_ERROR_NONE;
239         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
240
241         LOGI(">> enter");
242
243         ret = _add_device_for_stream_routing(stream_h, device);
244
245         LOGI("<< leave : ret(%p)", ret);
246
247         return _convert_sound_manager_error_code(__func__, ret);
248 }
249
250 int sound_manager_remove_device_for_stream_routing(sound_stream_info_h stream_info, sound_device_h device)
251 {
252         int ret = MM_ERROR_NONE;
253         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
254
255         LOGI(">> enter");
256
257         ret = _remove_device_for_stream_routing(stream_h, device);
258
259         LOGI("<< leave : ret(%p)", ret);
260
261         return _convert_sound_manager_error_code(__func__, ret);
262 }
263
264 int sound_manager_apply_stream_routing(sound_stream_info_h stream_info)
265 {
266         int ret = MM_ERROR_NONE;
267         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
268
269         LOGI(">> enter");
270
271         ret = _apply_stream_routing(stream_h);
272
273         LOGI("<< leave : ret(%p)", ret);
274
275         return _convert_sound_manager_error_code(__func__, ret);
276 }
277
278 int sound_manager_acquire_focus(sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask, const char *additional_info)
279 {
280         int ret = MM_ERROR_NONE;
281         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
282
283         LOGI(">> enter");
284
285         SM_INSTANCE_CHECK(stream_h);
286
287         ret = mm_sound_acquire_focus(stream_h->index, (mm_sound_focus_type_e)focus_mask, additional_info);
288         if (ret == MM_ERROR_NONE) {
289                 stream_h->acquired_focus |= focus_mask;
290                 _update_focus_status(stream_h->index, (unsigned int)stream_h->acquired_focus);
291         }
292
293         LOGI("<< leave : ret(%p)", ret);
294
295         return _convert_sound_manager_error_code(__func__, ret);
296 }
297
298 int sound_manager_release_focus(sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask, const char *additional_info)
299 {
300         int ret = MM_ERROR_NONE;
301         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
302
303         LOGI(">> enter");
304
305         SM_INSTANCE_CHECK(stream_h);
306
307         ret = mm_sound_release_focus(stream_h->index, (mm_sound_focus_type_e)focus_mask, additional_info);
308         if (ret == MM_ERROR_NONE) {
309                 stream_h->acquired_focus &= ~focus_mask;
310                 _update_focus_status(stream_h->index, (unsigned int)stream_h->acquired_focus);
311         }
312
313         LOGI("<< leave : ret(%p)", ret);
314
315         return _convert_sound_manager_error_code(__func__, ret);
316 }
317
318 int sound_manager_get_focus_state(sound_stream_info_h stream_info, sound_stream_focus_state_e *state_for_playback, sound_stream_focus_state_e *state_for_recording)
319 {
320         int ret = MM_ERROR_NONE;
321         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
322
323         LOGI(">> enter");
324
325         SM_INSTANCE_CHECK(stream_h);
326         if (!state_for_playback && !state_for_recording)
327                 ret = MM_ERROR_INVALID_ARGUMENT;
328
329         if (state_for_playback)
330                 *state_for_playback = ((stream_h->acquired_focus & SOUND_STREAM_FOCUS_FOR_PLAYBACK) ? (SOUND_STREAM_FOCUS_STATE_ACQUIRED) : (SOUND_STREAM_FOCUS_STATE_RELEASED));
331         if (state_for_recording)
332                 *state_for_recording = ((stream_h->acquired_focus & SOUND_STREAM_FOCUS_FOR_RECORDING) ? (SOUND_STREAM_FOCUS_STATE_ACQUIRED) : (SOUND_STREAM_FOCUS_STATE_RELEASED));
333
334         LOGI("<< leave : acquired_focus(%p)", stream_h->acquired_focus);
335
336         return _convert_sound_manager_error_code(__func__, ret);
337 }
338
339 int sound_manager_get_sound_type(sound_stream_info_h stream_info, sound_type_e *sound_type)
340 {
341         int ret = MM_ERROR_NONE;
342         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
343
344         LOGI(">> enter");
345
346         SM_INSTANCE_CHECK(stream_h);
347         SM_NULL_ARG_CHECK(sound_type);
348
349         ret = _convert_sound_type_to_enum(stream_h->stream_conf_info.volume_type, sound_type);
350
351         LOGI("<< leave : sound type(%d)", *sound_type);
352
353         return _convert_sound_manager_error_code(__func__, ret);
354 }
355
356 int sound_manager_set_focus_state_watch_cb(sound_stream_focus_mask_e focus_mask, sound_stream_focus_state_watch_cb callback, void *user_data)
357 {
358         int ret = MM_ERROR_NONE;
359         int id = -1;
360
361         LOGI(">> enter");
362
363         SM_NULL_ARG_CHECK(callback);
364         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, SOUND_MANAGER_ERROR_INTERNAL);
365
366         if (!g_focus_watch_cb_table.user_cb) {
367                 SM_REF_FOR_STREAM_INFO(g_stream_info_count, ret);
368                 ret = mm_sound_set_focus_watch_callback((mm_sound_focus_type_e)focus_mask, _focus_watch_callback, user_data, &id);
369                 if (ret == MM_ERROR_NONE) {
370                         g_focus_watch_cb_table.index = id;
371                         g_focus_watch_cb_table.user_cb = callback;
372                         g_focus_watch_cb_table.user_data = user_data;
373                 }
374         } else {
375                 ret = MM_ERROR_SOUND_INTERNAL;
376         }
377
378         SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
379
380         LOGI("<< leave : cnt(%d), ret(%p)", g_stream_info_count, ret);
381
382         return _convert_sound_manager_error_code(__func__, ret);
383 }
384
385 int sound_manager_unset_focus_state_watch_cb(void)
386 {
387         int ret = MM_ERROR_NONE;
388
389         LOGI(">> enter");
390
391         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, SOUND_MANAGER_ERROR_INTERNAL);
392
393         if (g_focus_watch_cb_table.user_cb) {
394                 ret = mm_sound_unset_focus_watch_callback(g_focus_watch_cb_table.index);
395                 if (ret == MM_ERROR_NONE) {
396                         g_focus_watch_cb_table.index = -1;
397                         g_focus_watch_cb_table.user_cb = NULL;
398                         g_focus_watch_cb_table.user_data = NULL;
399                         SM_UNREF_FOR_STREAM_INFO(g_stream_info_count, ret);
400                 } else {
401                         ret = MM_ERROR_SOUND_INTERNAL;
402                 }
403         } else {
404                 ret = MM_ERROR_SOUND_INTERNAL;
405         }
406
407         SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
408
409         LOGI("<< leave : cnt(%d), ret(%p)", g_stream_info_count, ret);
410
411         return _convert_sound_manager_error_code(__func__, ret);
412 }
413
414 int sound_manager_set_session_type(sound_session_type_e type)
415 {
416         int ret = MM_ERROR_NONE;
417         int cur_session = -1;
418         int new_session = MM_SESSION_TYPE_MEDIA;
419
420         LOGI(">> enter : type=%d", type);
421
422         if (type < SOUND_SESSION_TYPE_MEDIA || type >  SOUND_SESSION_TYPE_VOIP)
423                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
424
425         /* it is not supported both session and stream feature at the same time */
426         if (g_stream_info_count) {
427                 LOGE("Could not set this type(%d) because of being used stream feature", type);
428                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
429         }
430
431         switch (type) {
432         case SOUND_SESSION_TYPE_MEDIA:
433                 new_session = MM_SESSION_TYPE_MEDIA;
434                 break;
435         case SOUND_SESSION_TYPE_ALARM:
436                 new_session = MM_SESSION_TYPE_ALARM;
437                 break;
438         case SOUND_SESSION_TYPE_NOTIFICATION:
439                 new_session = MM_SESSION_TYPE_NOTIFY;
440                 break;
441         case SOUND_SESSION_TYPE_EMERGENCY:
442                 new_session = MM_SESSION_TYPE_EMERGENCY;
443                 break;
444         case SOUND_SESSION_TYPE_VOIP:
445                 new_session = MM_SESSION_TYPE_VOIP;
446                 break;
447         }
448
449         /* valid session check */
450         ret = mm_session_get_current_type(&cur_session);
451         if (ret == MM_ERROR_NONE) {
452                 if (cur_session == MM_SESSION_TYPE_MEDIA_RECORD) {
453                         if (type > SOUND_SESSION_TYPE_MEDIA) {
454                                 LOGE("<< leave : Could not set this type(%d) during camera/recorder/audio-io(in)/radio", type);
455                                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
456                         }
457                 }
458         }
459
460         if (g_session_interrupt_cb_table.is_registered) {
461                 if (new_session == cur_session ||
462                         ((new_session == SOUND_SESSION_TYPE_MEDIA) && (cur_session == MM_SESSION_TYPE_MEDIA_RECORD))) {
463                         LOGI("<< leave : already set type=%d, ret=%p", type, ret);
464                         return SOUND_MANAGER_ERROR_NONE;
465                 } else {
466                         ret = mm_session_finish();
467                         if (ret != MM_ERROR_NONE)
468                                 return _convert_sound_manager_error_code(__func__, ret);
469
470                         g_session_interrupt_cb_table.is_registered = 0;
471                         if (cur_session == MM_SESSION_TYPE_VOIP) {
472                                 g_cached_session_mode = -1;
473                                 g_cached_voip_device_id = -1;
474                                 if (g_voip_vstream_h) {
475                                         _stop_virtual_stream(g_voip_vstream_h);
476                                         _destroy_virtual_stream(g_voip_vstream_h);
477                                         g_voip_vstream_h = NULL;
478                                 }
479                                 /*voip stream destruction*/
480                                 if (g_voip_stream_info) {
481                                         ret = _destroy_pa_connection_and_unregister_focus(g_voip_stream_info);
482                                         free(g_voip_stream_info);
483                                         g_voip_stream_info = NULL;
484                                         if (ret != MM_ERROR_NONE)
485                                                 return _convert_sound_manager_error_code(__func__, ret);
486                                 }
487                         }
488                 }
489         }
490         ret = mm_session_init(new_session);
491         if (ret == MM_ERROR_NONE)
492                 g_session_interrupt_cb_table.is_registered = 1;
493
494         LOGI("<< leave : type=%d, ret=%p", type, ret);
495
496         return _convert_sound_manager_error_code(__func__, ret);
497 }
498
499 int sound_manager_get_session_type(sound_session_type_e *type)
500 {
501         int ret = MM_ERROR_NONE;
502         int cur_session;
503
504         if (type == NULL)
505                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
506         ret = mm_session_get_current_type(&cur_session);
507         if (ret != 0) {
508                 LOGW("session hasn't been set, setting default session");
509                 cur_session = SOUND_SESSION_TYPE_DEFAULT;
510                 ret = mm_session_init(cur_session);
511                 if (ret == 0)
512                         g_session_interrupt_cb_table.is_registered = 1;
513         }
514         if ((cur_session > MM_SESSION_TYPE_EMERGENCY) &&
515                         (cur_session != MM_SESSION_TYPE_VOIP)) {
516                 if (g_cached_session != -1)
517                         cur_session = g_cached_session;
518                 else /* will be never reach here. just prevent code */
519                         cur_session = SOUND_SESSION_TYPE_DEFAULT;
520         }
521
522         switch (cur_session) {
523         case MM_SESSION_TYPE_MEDIA:
524         case MM_SESSION_TYPE_MEDIA_RECORD:
525                 *type = SOUND_SESSION_TYPE_MEDIA;
526                 break;
527         case MM_SESSION_TYPE_ALARM:
528                 *type = SOUND_SESSION_TYPE_ALARM;
529                 break;
530         case MM_SESSION_TYPE_NOTIFY:
531                 *type = SOUND_SESSION_TYPE_NOTIFICATION;
532                 break;
533         case MM_SESSION_TYPE_EMERGENCY:
534                 *type = SOUND_SESSION_TYPE_EMERGENCY;
535                 break;
536         case MM_SESSION_TYPE_VOIP:
537                 *type = SOUND_SESSION_TYPE_VOIP;
538                 break;
539         default:
540                 *type = cur_session;
541                 break;
542         }
543
544         LOGI("returns : type=%d, ret=%p", *type, ret);
545
546         return 0;
547 }
548
549 int sound_manager_set_media_session_option(sound_session_option_for_starting_e s_option, sound_session_option_for_during_play_e d_option)
550 {
551         int ret = MM_ERROR_NONE;
552         int session = 0;
553         int session_option = 0;
554         int updated = 0;
555
556         LOGI(">> enter : option for starting=%d, for during play=%d", s_option, d_option);
557
558         if (s_option < 0 || s_option >  SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START)
559                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
560         if (d_option < 0 || d_option >  SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY)
561                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
562
563         ret = mm_session_get_current_information(&session, &session_option);
564         if (ret != 0 || !g_session_interrupt_cb_table.is_registered) {
565                 LOGW("session hasn't been set, setting default session");
566                 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
567                 if (ret == 0)
568                         g_session_interrupt_cb_table.is_registered = 1;
569
570         } else if (ret == 0 && session > MM_SESSION_TYPE_MEDIA) {
571                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
572                         if (!g_session_interrupt_cb_table.is_registered) {
573                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
574                                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
575                         }
576                 } else {
577                         return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
578                 }
579         }
580
581         switch (s_option) {
582         case SOUND_SESSION_OPTION_MIX_WITH_OTHERS_WHEN_START:
583                 if (session_option & MM_SESSION_OPTION_PAUSE_OTHERS) {
584                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_PAUSE_OTHERS);
585                         if (ret)
586                                 return _convert_sound_manager_error_code(__func__, ret);
587
588                         updated = 1;
589                 }
590                 break;
591         case SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START:
592                 if (!(session_option & MM_SESSION_OPTION_PAUSE_OTHERS)) {
593                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_PAUSE_OTHERS);
594                         if (ret)
595                                 return _convert_sound_manager_error_code(__func__, ret);
596
597                         updated = 1;
598                 }
599                 break;
600         }
601
602         switch (d_option) {
603         case SOUND_SESSION_OPTION_INTERRUPTIBLE_DURING_PLAY:
604                 if (session_option & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
605                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_UNINTERRUPTIBLE);
606                         if (ret)
607                                 return _convert_sound_manager_error_code(__func__, ret);
608
609                         updated = 1;
610                 }
611                 break;
612         case SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY:
613                 if (!(session_option & MM_SESSION_OPTION_UNINTERRUPTIBLE)) {
614                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_UNINTERRUPTIBLE);
615                         if (ret)
616                                 return _convert_sound_manager_error_code(__func__, ret);
617
618                         updated = 1;
619                 }
620                 break;
621         }
622
623         if (updated)
624                 LOGI("<< leave : updated");
625         else
626                 LOGI("<< leave : already set same option(%x), skip it", session_option);
627
628         return _convert_sound_manager_error_code(__func__, ret);
629 }
630
631 int sound_manager_get_media_session_option(sound_session_option_for_starting_e *s_option, sound_session_option_for_during_play_e *d_option)
632 {
633         int ret = MM_ERROR_NONE;
634         int session = 0;
635         int session_options = 0;
636
637         LOGI(">> enter");
638
639         if (s_option == NULL || d_option == NULL)
640                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
641
642         ret = mm_session_get_current_information(&session, &session_options);
643         if (ret != 0) {
644                 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
645                 if (ret == 0)
646                         g_session_interrupt_cb_table.is_registered = 1;
647
648         } else if (session > SOUND_SESSION_TYPE_MEDIA) {
649                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
650                         if (!g_session_interrupt_cb_table.is_registered) {
651                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
652                                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
653                         }
654                 } else
655                         return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
656         }
657         /* get option */
658         if (session_options & MM_SESSION_OPTION_PAUSE_OTHERS)
659                 *s_option = SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START;
660         else
661                 *s_option = SOUND_SESSION_OPTION_MIX_WITH_OTHERS_WHEN_START;
662
663         if (session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE)
664                 *d_option = SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY;
665         else
666                 *d_option = SOUND_SESSION_OPTION_INTERRUPTIBLE_DURING_PLAY;
667
668         LOGI("<< leave : option for starting=%d, for during play=%d", *s_option, *d_option);
669
670         return SOUND_MANAGER_ERROR_NONE;
671 }
672
673 int sound_manager_set_media_session_resumption_option(sound_session_option_for_resumption_e option)
674 {
675         int ret = MM_ERROR_NONE;
676         int session = 0;
677         int session_option = 0;
678         int updated = 0;
679
680         LOGI(">> enter : option for resumption=%d (0:by system, 1:by system or media paused)", option);
681
682         if (option < SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM || option > SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED)
683                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
684
685         ret = mm_session_get_current_information(&session, &session_option);
686         if (ret != 0 || !g_session_interrupt_cb_table.is_registered) {
687                 LOGW("session hasn't been set, setting default session");
688                 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
689                 if (ret == 0)
690                         g_session_interrupt_cb_table.is_registered = 1;
691
692         } else if (ret == 0 && session > MM_SESSION_TYPE_MEDIA) {
693                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
694                         if (!g_session_interrupt_cb_table.is_registered) {
695                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
696                                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
697                         }
698                 } else
699                         return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
700
701         }
702
703         switch (option) {
704         case SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM:
705                 if (session_option & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED) {
706                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED);
707                         if (ret)
708                                 return _convert_sound_manager_error_code(__func__, ret);
709
710                         updated = 1;
711                 }
712                 break;
713         case SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED:
714                 if (!(session_option & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED)) {
715                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED);
716                         if (ret)
717                                 return _convert_sound_manager_error_code(__func__, ret);
718
719                         updated = 1;
720                 }
721                 break;
722         }
723
724         if (updated)
725                 LOGI("<< leave : updated");
726         else
727                 LOGI("<< leave : already set same option(%x), skip it", session_option);
728
729         return _convert_sound_manager_error_code(__func__, ret);
730 }
731
732 int sound_manager_get_media_session_resumption_option(sound_session_option_for_resumption_e *option)
733 {
734         int ret = MM_ERROR_NONE;
735         int session = 0;
736         int session_options = 0;
737
738         LOGI(">> enter");
739
740         if (option == NULL)
741                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
742         ret = mm_session_get_current_information(&session, &session_options);
743         if (ret != 0) {
744                 LOGW("session hasn't been set, setting default session");
745                 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
746                 if (ret == 0)
747                         g_session_interrupt_cb_table.is_registered = 1;
748
749         } else if (session > SOUND_SESSION_TYPE_MEDIA) {
750                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
751                         if (!g_session_interrupt_cb_table.is_registered) {
752                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
753                                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
754                         }
755                 } else
756                         return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
757         }
758         /* get option */
759         if (session_options & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED)
760                 *option = SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED;
761         else
762                 *option = SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM;
763
764         LOGI("<< leave : option for resumption=%d (0:by system, 1:by system or media paused)", *option);
765
766         return SOUND_MANAGER_ERROR_NONE;
767 }
768
769 int sound_manager_set_voip_session_mode(sound_session_voip_mode_e mode)
770 {
771         int ret = MM_ERROR_NONE;
772         int session = 0;
773         int session_options = 0;
774
775         LOGI(">> enter : mode=%d", mode);
776
777         ret = mm_session_get_current_information(&session, &session_options);
778         if (ret != MM_ERROR_NONE)
779                 return _convert_sound_manager_error_code(__func__, ret);
780         else if (session != MM_SESSION_TYPE_VOIP)
781                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
782
783         if (mode < SOUND_SESSION_VOIP_MODE_RINGTONE || mode > SOUND_SESSION_VOIP_MODE_VOICE_WITH_BLUETOOTH) {
784                 ret = MM_ERROR_INVALID_ARGUMENT;
785                 return _convert_sound_manager_error_code(__func__, ret);
786         }
787         ret = _set_session_mode((_session_mode_e)mode);
788
789         LOGI("<< leave : session=%p, mode=%d, ret=%p", session, mode, ret);
790
791         return _convert_sound_manager_error_code(__func__, ret);
792 }
793
794 int sound_manager_get_voip_session_mode(sound_session_voip_mode_e *mode)
795 {
796         int ret = MM_ERROR_NONE;
797         int session = 0;
798         int session_options = 0;
799
800         if (mode == NULL) {
801                 LOGI("mode is null");
802                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
803         }
804
805         ret = mm_session_get_current_information(&session, &session_options);
806         if (ret != MM_ERROR_NONE) {
807                 LOGI("session = %d, option = %d", session, session_options);
808                 return _convert_sound_manager_error_code(__func__, ret);
809         } else if (session != MM_SESSION_TYPE_VOIP || g_cached_session_mode == -1)
810                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
811
812         *mode = (sound_session_voip_mode_e)g_cached_session_mode;
813
814         LOGI("returns : session=%p, mode=%d, ret=%p", session, *mode, ret);
815
816         return _convert_sound_manager_error_code(__func__, ret);
817 }
818
819 int sound_manager_set_session_interrupted_cb(sound_session_interrupted_cb callback, void *user_data)
820 {
821         int ret = MM_ERROR_NONE;
822         unsigned int subs_id = 0;
823
824         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_interrupt_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
825
826         if (callback == NULL) {
827                 ret = MM_ERROR_INVALID_ARGUMENT;
828                 goto finish;
829         }
830
831         /* it is not supported both session and stream feature at the same time */
832         if (g_stream_info_count) {
833                 ret =  MM_ERROR_POLICY_INTERNAL;
834                 goto finish;
835         }
836
837         if (g_session_interrupt_cb_table.user_cb == NULL) {
838                 ret = mm_sound_add_device_connected_callback(SOUND_DEVICE_ALL_MASK, (mm_sound_device_connected_cb)_device_connected_cb, NULL, &subs_id);
839                 if (ret)
840                         goto finish;
841                 ret = mm_sound_focus_set_session_interrupt_callback((mm_sound_focus_session_interrupt_cb)_focus_session_interrupt_cb, NULL);
842                 if (ret) {
843                         if (mm_sound_remove_device_connected_callback(subs_id) != MM_ERROR_NONE)
844                                 LOGW("mm_sound_remove_device_connected_callback failed");
845                         goto finish;
846                 }
847                 g_session_interrupt_cb_table.subs_id = subs_id;
848         }
849         g_session_interrupt_cb_table.user_cb = (sound_session_interrupted_cb)callback;
850         g_session_interrupt_cb_table.user_data = user_data;
851
852 finish:
853         SM_LEAVE_CRITICAL_SECTION(&g_interrupt_cb_mutex);
854         return _convert_sound_manager_error_code(__func__, ret);
855 }
856
857 int sound_manager_unset_session_interrupted_cb(void)
858 {
859         int ret = MM_ERROR_NONE;
860
861         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_interrupt_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
862
863         if (g_session_interrupt_cb_table.user_cb) {
864                 ret = mm_sound_focus_unset_session_interrupt_callback();
865                 if (ret) {
866                         if (mm_sound_remove_device_connected_callback(g_session_interrupt_cb_table.subs_id) != MM_ERROR_NONE)
867                                 LOGW("mm_sound_remove_device_connected_callback failed");
868                         goto finish;
869                 }
870                 ret = mm_sound_remove_device_connected_callback(g_session_interrupt_cb_table.subs_id);
871                 if (ret)
872                         goto finish;
873                 g_session_interrupt_cb_table.subs_id = 0;
874                 g_session_interrupt_cb_table.user_cb = NULL;
875                 g_session_interrupt_cb_table.user_data = NULL;
876         } else {
877                 ret = MM_ERROR_SOUND_INTERNAL;
878         }
879
880 finish:
881         SM_LEAVE_CRITICAL_SECTION(&g_interrupt_cb_mutex);
882         return _convert_sound_manager_error_code(__func__, ret);
883 }
884
885 int sound_manager_get_current_device_list(sound_device_mask_e device_mask, sound_device_list_h *device_list)
886 {
887         int ret = MM_ERROR_NONE;
888         ret = mm_sound_get_current_device_list((mm_sound_device_flags_e)device_mask, device_list);
889
890         return _convert_sound_manager_error_code(__func__, ret);
891 }
892
893 int sound_manager_get_next_device(sound_device_list_h device_list, sound_device_h *device)
894 {
895         int ret = MM_ERROR_NONE;
896         ret = mm_sound_get_next_device(device_list, device);
897
898         return _convert_sound_manager_error_code(__func__, ret);
899 }
900
901 int sound_manager_get_prev_device(sound_device_list_h device_list, sound_device_h *device)
902 {
903         int ret = MM_ERROR_NONE;
904         ret = mm_sound_get_prev_device(device_list, device);
905
906         return _convert_sound_manager_error_code(__func__, ret);
907 }
908
909 int sound_manager_get_device_type(sound_device_h device, sound_device_type_e *type)
910 {
911         int ret = MM_ERROR_NONE;
912         ret = mm_sound_get_device_type(device, (mm_sound_device_type_e*)type);
913
914         return _convert_sound_manager_error_code(__func__, ret);
915 }
916
917 int sound_manager_get_device_io_direction(sound_device_h device, sound_device_io_direction_e *io_direction)
918 {
919         int ret = MM_ERROR_NONE;
920         mm_sound_device_io_direction_e mm_sound_io_direction;
921         ret = mm_sound_get_device_io_direction(device, &mm_sound_io_direction);
922         if (ret == MM_ERROR_NONE)
923                 ret = _convert_device_io_direction(mm_sound_io_direction, io_direction);
924
925         return _convert_sound_manager_error_code(__func__, ret);
926 }
927
928 int sound_manager_get_device_id(sound_device_h device, int *id)
929 {
930         int ret = MM_ERROR_NONE;
931         ret = mm_sound_get_device_id(device, id);
932
933         return _convert_sound_manager_error_code(__func__, ret);
934 }
935
936 int sound_manager_get_device_name(sound_device_h device, char **name)
937 {
938         int ret = MM_ERROR_NONE;
939         ret = mm_sound_get_device_name(device, name);
940
941         return _convert_sound_manager_error_code(__func__, ret);
942 }
943
944 int sound_manager_get_device_state(sound_device_h device, sound_device_state_e *state)
945 {
946         int ret = MM_ERROR_NONE;
947         ret = mm_sound_get_device_state(device, (mm_sound_device_state_e*)state);
948
949         return _convert_sound_manager_error_code(__func__, ret);
950 }
951
952 int sound_manager_set_device_connected_cb(sound_device_mask_e device_mask, sound_device_connected_cb callback, void *user_data)
953 {
954         int ret = MM_ERROR_NONE;
955         unsigned int subs_id = 0;
956
957         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_conn_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
958
959         ret = mm_sound_add_device_connected_callback((mm_sound_device_flags_e)device_mask, (mm_sound_device_connected_cb)callback, user_data, &subs_id);
960         if (ret == MM_ERROR_NONE) {
961                 g_device_connected_cb_table.subs_id = subs_id;
962                 g_device_connected_cb_table.user_cb = (sound_device_connected_cb)callback;
963                 g_device_connected_cb_table.user_data = user_data;
964         }
965
966         SM_LEAVE_CRITICAL_SECTION(&g_device_conn_cb_mutex);
967
968         return _convert_sound_manager_error_code(__func__, ret);
969 }
970
971 int sound_manager_unset_device_connected_cb(void)
972 {
973         int ret = MM_ERROR_NONE;
974
975         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_conn_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
976
977         if (g_device_connected_cb_table.subs_id > 0) {
978                 ret = mm_sound_remove_device_connected_callback(g_device_connected_cb_table.subs_id);
979                 if (ret == MM_ERROR_NONE) {
980                         g_device_connected_cb_table.subs_id = 0;
981                         g_device_connected_cb_table.user_cb = NULL;
982                         g_device_connected_cb_table.user_data = NULL;
983                 }
984         } else
985                 ret = MM_ERROR_SOUND_INTERNAL;
986
987         SM_LEAVE_CRITICAL_SECTION(&g_device_conn_cb_mutex);
988
989         return _convert_sound_manager_error_code(__func__, ret);
990 }
991
992 int sound_manager_set_device_information_changed_cb(sound_device_mask_e device_mask, sound_device_information_changed_cb callback, void *user_data)
993 {
994         int ret = MM_ERROR_NONE;
995         unsigned int subs_id = 0;
996
997         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_info_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
998
999         ret = mm_sound_add_device_information_changed_callback((mm_sound_device_flags_e)device_mask, (mm_sound_device_info_changed_cb)callback, user_data, &subs_id);
1000         if (ret == MM_ERROR_NONE) {
1001                 g_device_info_changed_cb_table.subs_id = subs_id;
1002                 g_device_info_changed_cb_table.user_cb = (sound_device_information_changed_cb)callback;
1003                 g_device_info_changed_cb_table.user_data = user_data;
1004         }
1005
1006         SM_LEAVE_CRITICAL_SECTION(&g_device_info_cb_mutex);
1007
1008         return _convert_sound_manager_error_code(__func__, ret);
1009 }
1010
1011 int sound_manager_unset_device_information_changed_cb(void)
1012 {
1013         int ret = MM_ERROR_NONE;
1014
1015         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_info_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1016
1017         if (g_device_info_changed_cb_table.subs_id) {
1018                 ret = mm_sound_remove_device_information_changed_callback(g_device_info_changed_cb_table.subs_id);
1019                 if (ret == MM_ERROR_NONE) {
1020                         g_device_info_changed_cb_table.subs_id = 0;
1021                         g_device_info_changed_cb_table.user_cb = NULL;
1022                         g_device_info_changed_cb_table.user_data = NULL;
1023                 }
1024         } else {
1025                 ret = MM_ERROR_SOUND_INTERNAL;
1026         }
1027
1028         SM_LEAVE_CRITICAL_SECTION(&g_device_info_cb_mutex);
1029
1030         return _convert_sound_manager_error_code(__func__, ret);
1031 }
1032
1033 __attribute__ ((destructor))
1034 void __sound_manager_finalize(void)
1035 {
1036         int ret = MM_ERROR_NONE;
1037
1038         if (g_session_interrupt_cb_table.is_registered) {
1039                 LOGI("<ENTER>");
1040                 ret = mm_session_finish();
1041                 if (ret != MM_ERROR_NONE)
1042                         LOGE("[%s] failed to mm_session_finish(), ret(%p)", __func__, ret);
1043
1044                 g_session_interrupt_cb_table.is_registered = 0;
1045                 LOGI("<LEAVE>");
1046         }
1047 }
1048
1049 __attribute__ ((constructor))
1050 void __sound_manager_initialize(void)
1051 {
1052
1053 }