Add new APIs to communicate with one another about the predefined sound behavior...
[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 #include <system_info.h>
20
21 #define FEATURE_MICROPHONE          "http://tizen.org/feature/microphone"
22
23 _session_interrupt_info_s g_session_interrupt_cb_table = {0, 0, NULL, NULL};
24 _volume_changed_info_s g_volume_changed_cb_table = {0, NULL, NULL};
25 _device_connected_info_s g_device_connected_cb_table = {0, NULL, NULL};
26 _device_changed_info_s g_device_info_changed_cb_table = {0, NULL, NULL};
27 _focus_watch_info_s focus_watch_info_arr[SOUND_STREAM_INFO_ARR_MAX];
28
29 sound_session_type_e g_cached_session = -1;
30 _session_mode_e g_cached_session_mode = -1;
31 int g_cached_voip_device_id = -1;
32 extern sound_stream_info_s *g_voip_stream_info;
33 extern virtual_sound_stream_info_s *g_voip_vstream_h;
34
35 /* These variables will be removed when session features are deprecated. */
36 extern int g_stream_info_count;
37 extern pthread_mutex_t g_stream_info_count_mutex;
38 pthread_mutex_t g_interrupt_cb_mutex, g_device_info_cb_mutex, g_device_conn_cb_mutex, g_volume_cb_mutex;
39
40 int sound_manager_get_max_volume(sound_type_e type, int *max)
41 {
42         const char *volume_type = NULL;
43         unsigned int max_level = 0;
44         int ret = MM_ERROR_NONE;
45
46         SM_NULL_ARG_CHECK(max);
47         if (type >= SOUND_TYPE_NUM || type < 0)
48                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
49
50         ret = _convert_sound_type(type, &volume_type);
51         if (ret == MM_ERROR_NONE) {
52                 ret = _get_volume_max_level(DIRECTION_OUT_STR, volume_type, &max_level);
53                 if (ret == MM_ERROR_NONE)
54                         *max = (int)max_level -1;       /* actual volume step can be max step - 1 */
55         }
56
57         return _convert_sound_manager_error_code(__func__, ret);
58 }
59
60 int sound_manager_set_volume(sound_type_e type, int volume)
61 {
62         int ret = MM_ERROR_NONE;
63
64         if (type >= SOUND_TYPE_NUM || type < 0)
65                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
66         if (volume < 0)
67                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
68
69         ret = mm_sound_volume_set_value(type, volume);
70         LOGI("type=%d, volume=%d", type, volume);
71
72         return _convert_sound_manager_error_code(__func__, ret);
73 }
74
75 int sound_manager_get_volume(sound_type_e type, int *volume)
76 {
77         int ret = MM_ERROR_NONE;
78         unsigned int uvolume;
79
80         if (type >= SOUND_TYPE_NUM || type < 0)
81                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
82         if (volume == NULL)
83                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
84
85         ret = mm_sound_volume_get_value(type, &uvolume);
86         if (ret == MM_ERROR_NONE)
87                 *volume = uvolume;
88
89         LOGI("type=%d, volume=%d", type, *volume);
90
91         return _convert_sound_manager_error_code(__func__, ret);
92 }
93
94 int sound_manager_set_current_sound_type(sound_type_e type)
95 {
96         int ret = MM_ERROR_NONE;
97
98         if (type >= SOUND_TYPE_NUM || type < 0)
99                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
100
101         ret = mm_sound_volume_primary_type_set(type);
102
103         return _convert_sound_manager_error_code(__func__, ret);
104 }
105
106 int sound_manager_get_current_sound_type(sound_type_e *type)
107 {
108         int ret = MM_ERROR_NONE;
109         volume_type_t mm_sound_vol_type = VOLUME_TYPE_UNKNOWN;
110         char *volume_type = NULL;
111
112         if (type == NULL)
113                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
114
115         ret  = mm_sound_volume_primary_type_get(&mm_sound_vol_type);
116         if (ret == MM_ERROR_NONE) {
117                 if (mm_sound_vol_type == VOLUME_TYPE_UNKNOWN) {
118                         /* get the volume type of the current playing stream */
119                         ret = _get_current_volume_type(DIRECTION_OUT_STR, &volume_type);
120                         if (ret == MM_ERROR_NONE)
121                                 ret = _convert_sound_type_to_enum((const char*)volume_type, type);
122                 } else {
123                         *type = mm_sound_vol_type;
124                 }
125         }
126         LOGI("type=%d", *type);
127
128         return _convert_sound_manager_error_code(__func__, ret);
129 }
130
131 int sound_manager_unset_current_sound_type(void)
132 {
133         int ret = MM_ERROR_NONE;
134
135         ret = mm_sound_volume_primary_type_set(VOLUME_TYPE_UNKNOWN);
136
137         return _convert_sound_manager_error_code(__func__, ret);
138 }
139
140 int sound_manager_set_volume_changed_cb(sound_manager_volume_changed_cb callback, void* user_data)
141 {
142         int ret = MM_ERROR_NONE;
143         unsigned int subs_id = 0;
144
145         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_volume_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
146
147         ret = mm_sound_add_volume_changed_callback((mm_sound_volume_changed_cb)callback, user_data, &subs_id);
148         if (ret == MM_ERROR_NONE) {
149                 g_volume_changed_cb_table.subs_id = subs_id;
150                 g_volume_changed_cb_table.user_cb = (sound_manager_volume_changed_cb)callback;
151                 g_volume_changed_cb_table.user_data = user_data;
152         }
153
154         SM_LEAVE_CRITICAL_SECTION(&g_volume_cb_mutex);
155
156         return _convert_sound_manager_error_code(__func__, ret);
157 }
158
159 int sound_manager_unset_volume_changed_cb(void)
160 {
161         int ret = MM_ERROR_NONE;
162
163         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_volume_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
164
165         if (g_volume_changed_cb_table.subs_id > 0) {
166                 ret = mm_sound_remove_volume_changed_callback(g_volume_changed_cb_table.subs_id);
167                 if (ret == MM_ERROR_NONE) {
168                         g_volume_changed_cb_table.subs_id = 0;
169                         g_volume_changed_cb_table.user_cb = NULL;
170                         g_volume_changed_cb_table.user_data = NULL;
171                 }
172         } else {
173                 ret = MM_ERROR_SOUND_INTERNAL;
174         }
175
176         SM_LEAVE_CRITICAL_SECTION(&g_volume_cb_mutex);
177
178         return _convert_sound_manager_error_code(__func__, ret);
179 }
180
181 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)
182 {
183         int ret = MM_ERROR_NONE;
184
185         LOGI(">> enter");
186
187         SM_NULL_ARG_CHECK(stream_info);
188
189         if (g_session_interrupt_cb_table.is_registered)
190                 return _convert_sound_manager_error_code(__func__, MM_ERROR_SOUND_INTERNAL);
191
192         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, MM_ERROR_SOUND_INTERNAL);
193
194         sound_stream_info_s *stream_h = malloc(sizeof(sound_stream_info_s));
195         if (!stream_h) {
196                 ret = MM_ERROR_OUT_OF_MEMORY;
197                 goto LEAVE;
198         }
199
200         memset(stream_h, 0, sizeof(sound_stream_info_s));
201         ret = _convert_stream_type(stream_type, &stream_h->stream_type);
202         if (ret == MM_ERROR_NONE) {
203                 ret = _make_pa_connection_and_register_focus(stream_h, callback, user_data);
204                 if (ret == MM_ERROR_NONE) {
205                         *stream_info = (sound_stream_info_h)stream_h;
206                         SM_REF_FOR_STREAM_INFO(g_stream_info_count, ret);
207                         LOGI("stream_h(%p), index(%u), user_cb(%p), cnt(%d), ret(0x%x)", stream_h, stream_h->index, stream_h->user_cb, g_stream_info_count, ret);
208                 }
209         }
210
211 LEAVE:
212         if (ret && stream_h)
213                 free(stream_h);
214
215         SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
216
217         return _convert_sound_manager_error_code(__func__, ret);
218 }
219
220 int sound_manager_destroy_stream_information(sound_stream_info_h stream_info)
221 {
222         int ret = MM_ERROR_NONE;
223         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
224
225         LOGI(">> enter");
226
227         SM_INSTANCE_CHECK(stream_h);
228
229         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, MM_ERROR_SOUND_INTERNAL);
230         ret = _destroy_pa_connection_and_unregister_focus(stream_h);
231         if (ret == MM_ERROR_NONE) {
232                 free(stream_h);
233                 stream_h = NULL;
234                 SM_UNREF_FOR_STREAM_INFO(g_stream_info_count);
235         }
236         SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
237
238         LOGD("cnt(%d)", g_stream_info_count);
239
240         return _convert_sound_manager_error_code(__func__, ret);
241 }
242
243 int sound_manager_get_sound_type(sound_stream_info_h stream_info, sound_type_e *sound_type)
244 {
245         int ret = MM_ERROR_NONE;
246         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
247
248         LOGI(">> enter");
249
250         SM_INSTANCE_CHECK(stream_h);
251         SM_NULL_ARG_CHECK(sound_type);
252
253         if (stream_h->stream_conf_info.volume_type == NULL) {
254                 ret = MM_ERROR_SOUND_NO_DATA;
255                 goto LEAVE;
256         }
257
258         ret = _convert_sound_type_to_enum(stream_h->stream_conf_info.volume_type, sound_type);
259         LOGI("sound type(%d)", *sound_type);
260
261 LEAVE:
262         return _convert_sound_manager_error_code(__func__, ret);
263 }
264
265 int sound_manager_add_device_for_stream_routing(sound_stream_info_h stream_info, sound_device_h device)
266 {
267         int ret = MM_ERROR_NONE;
268         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
269
270         LOGI(">> enter");
271
272         ret = _add_device_for_stream_routing(stream_h, device);
273
274         return _convert_sound_manager_error_code(__func__, ret);
275 }
276
277 int sound_manager_remove_device_for_stream_routing(sound_stream_info_h stream_info, sound_device_h device)
278 {
279         int ret = MM_ERROR_NONE;
280         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
281
282         LOGI(">> enter");
283
284         ret = _remove_device_for_stream_routing(stream_h, device);
285
286         return _convert_sound_manager_error_code(__func__, ret);
287 }
288
289 int sound_manager_apply_stream_routing(sound_stream_info_h stream_info)
290 {
291         int ret = MM_ERROR_NONE;
292         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
293
294         LOGI(">> enter");
295
296         ret = _apply_stream_routing(stream_h);
297
298         return _convert_sound_manager_error_code(__func__, ret);
299 }
300
301 int sound_manager_set_focus_reacquisition(sound_stream_info_h stream_info, bool enable)
302 {
303         int ret = MM_ERROR_NONE;
304         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
305
306         LOGI(">> enter");
307
308         SM_INSTANCE_CHECK(stream_h);
309
310         ret = mm_sound_set_focus_reacquisition(stream_h->index, enable);
311
312         return _convert_sound_manager_error_code(__func__, ret);
313 }
314
315 int sound_manager_get_focus_reacquisition(sound_stream_info_h stream_info, bool *enabled)
316 {
317         int ret = MM_ERROR_NONE;
318         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
319
320         LOGI(">> enter");
321
322         SM_INSTANCE_CHECK(stream_h);
323         SM_NULL_ARG_CHECK(enabled);
324
325         ret = mm_sound_get_focus_reacquisition(stream_h->index, enabled);
326
327         return _convert_sound_manager_error_code(__func__, ret);
328 }
329
330 int sound_manager_acquire_focus(sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask, const char *extra_info)
331 {
332         int ret = MM_ERROR_NONE;
333         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
334
335         LOGI(">> enter");
336
337         SM_INSTANCE_CHECK(stream_h);
338
339         if (stream_h->is_focus_unavailable) {
340                 LOGE("acquiring focus is not allowed for this strema type(%s)", stream_h->stream_type);
341                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
342         }
343
344         if (stream_h->user_cb == NULL) {
345                 LOGE("focus state changed callback should be set before acquiring focus");
346                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
347         }
348
349         ret = mm_sound_acquire_focus_with_option(stream_h->index, (mm_sound_focus_type_e)focus_mask, stream_h->requesting_flags, extra_info);
350         if (ret == MM_ERROR_NONE) {
351                 stream_h->acquired_focus |= focus_mask;
352                 _update_focus_status(stream_h->index, (unsigned int)stream_h->acquired_focus);
353         }
354
355         return _convert_sound_manager_error_code(__func__, ret);
356 }
357
358 int sound_manager_release_focus(sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask, const char *extra_info)
359 {
360         int ret = MM_ERROR_NONE;
361         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
362
363         LOGI(">> enter");
364
365         SM_INSTANCE_CHECK(stream_h);
366
367         ret = mm_sound_release_focus_with_option(stream_h->index, (mm_sound_focus_type_e)focus_mask, stream_h->requesting_flags, extra_info);
368         if (ret == MM_ERROR_NONE) {
369                 stream_h->acquired_focus &= ~focus_mask;
370                 _update_focus_status(stream_h->index, (unsigned int)stream_h->acquired_focus);
371         }
372
373         return _convert_sound_manager_error_code(__func__, ret);
374 }
375
376 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)
377 {
378         int ret = MM_ERROR_NONE;
379         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
380
381         LOGI(">> enter");
382
383         SM_INSTANCE_CHECK(stream_h);
384         if (!state_for_playback && !state_for_recording) {
385                 ret = MM_ERROR_INVALID_ARGUMENT;
386                 goto LEAVE;
387         }
388
389         if (state_for_playback)
390                 *state_for_playback = ((stream_h->acquired_focus & SOUND_STREAM_FOCUS_FOR_PLAYBACK) ? (SOUND_STREAM_FOCUS_STATE_ACQUIRED) : (SOUND_STREAM_FOCUS_STATE_RELEASED));
391         if (state_for_recording)
392                 *state_for_recording = ((stream_h->acquired_focus & SOUND_STREAM_FOCUS_FOR_RECORDING) ? (SOUND_STREAM_FOCUS_STATE_ACQUIRED) : (SOUND_STREAM_FOCUS_STATE_RELEASED));
393
394         LOGI("acquired_focus(0x%x)", stream_h->acquired_focus);
395
396 LEAVE:
397         return _convert_sound_manager_error_code(__func__, ret);
398 }
399
400 int sound_manager_focus_set_requesting_behavior(sound_stream_info_h stream_info, int flags)
401 {
402         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
403
404         LOGI(">> enter");
405
406         SM_INSTANCE_CHECK(stream_h);
407         SM_RANGE_ARG_CHECK(flags,
408                                 SOUND_BEHAVIOR_NONE,
409                                 (SOUND_BEHAVIOR_NO_RESUME|SOUND_BEHAVIOR_FADING));
410
411         stream_h->requesting_flags = flags;
412
413         LOGI("the requesting sound behavior(0x%x) is set", stream_h->requesting_flags);
414
415         return SOUND_MANAGER_ERROR_NONE;
416 }
417
418 int sound_manager_focus_get_requesting_behavior(sound_stream_info_h stream_info, int *flags)
419 {
420         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
421
422         LOGI(">> enter");
423
424         SM_INSTANCE_CHECK(stream_h);
425         SM_NULL_ARG_CHECK(flags);
426
427         *flags = stream_h->requesting_flags;
428
429         LOGI("the requesting sound behavior is (0x%x)", stream_h->requesting_flags);
430
431         return SOUND_MANAGER_ERROR_NONE;
432 }
433
434 int sound_manager_focus_get_requested_behavior(sound_stream_info_h stream_info, int *flags)
435 {
436         int ret = MM_ERROR_NONE;
437         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
438         bool is_focus_cb_thread = false;
439
440         LOGI(">> enter");
441
442         SM_INSTANCE_CHECK(stream_h);
443         SM_NULL_ARG_CHECK(flags);
444
445         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
446                 _convert_sound_manager_error_code(__func__, ret);
447
448         if (!is_focus_cb_thread) {
449                 LOGE("this API should be called in focus state changed callback");
450                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
451         }
452
453         *flags = stream_h->requested_flags;
454
455         LOGI("requested sound behavior is (0x%x)", stream_h->requested_flags);
456
457         return SOUND_MANAGER_ERROR_NONE;
458 }
459
460 int sound_manager_get_current_playback_focus(sound_stream_focus_change_reason_e *acquired_by, int *flags, char **extra_info)
461 {
462         int ret = MM_ERROR_NONE;
463         char *stream_type_str = NULL;
464         char *extra_info_str = NULL;
465         int option = 0;
466         bool is_focus_cb_thread = false;
467
468         LOGI(">> enter");
469
470         SM_NULL_ARG_CHECK(acquired_by);
471         SM_NULL_ARG_CHECK(flags);
472
473         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
474                 _convert_sound_manager_error_code(__func__, ret);
475
476         if (is_focus_cb_thread) {
477                 LOGE("this API should not be called in focus callback");
478                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
479         }
480
481         ret = mm_sound_get_stream_type_of_acquired_focus((int)SOUND_STREAM_FOCUS_FOR_PLAYBACK, &stream_type_str, &option, &extra_info_str);
482         if (ret == MM_ERROR_NONE) {
483                 LOGI("current acquired PLAYBACK focus : stream_type[%s]", stream_type_str);
484                 ret = _convert_stream_type_to_change_reason(stream_type_str, acquired_by);
485                 if (ret == MM_ERROR_NONE) {
486                         LOGI("                                : reason[%d], flags[0x%x], extra_info[%s]", *acquired_by, option, extra_info_str);
487                         *flags = option;
488                         if (extra_info)
489                                 *extra_info = extra_info_str;
490                         else
491                                 free(extra_info_str);
492                 }
493         }
494
495         return _convert_sound_manager_error_code(__func__, ret);
496 }
497
498 int sound_manager_get_current_recording_focus(sound_stream_focus_change_reason_e *acquired_by, int *flags, char **extra_info)
499 {
500         int ret = MM_ERROR_NONE;
501         char *stream_type_str = NULL;
502         char *extra_info_str = NULL;
503         int option = 0;
504         bool is_focus_cb_thread = false;
505
506         LOGI(">> enter");
507
508         SM_NULL_ARG_CHECK(acquired_by);
509         SM_NULL_ARG_CHECK(flags);
510
511         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
512                 _convert_sound_manager_error_code(__func__, ret);
513
514         if (is_focus_cb_thread) {
515                 LOGE("this API should not be called in focus callback");
516                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
517         }
518
519         ret = mm_sound_get_stream_type_of_acquired_focus((int)SOUND_STREAM_FOCUS_FOR_RECORDING, &stream_type_str, &option, &extra_info_str);
520         if (ret == MM_ERROR_NONE) {
521                 LOGI("current acquired RECORDING focus : stream_type[%s]", stream_type_str);
522                 ret = _convert_stream_type_to_change_reason(stream_type_str, acquired_by);
523                 if (ret == MM_ERROR_NONE) {
524                         LOGI("                                 : reason[%d], flags[0x%x], extra_info[%s]", *acquired_by, option, extra_info_str);
525                         *flags = option;
526                         if (extra_info)
527                                 *extra_info = extra_info_str;
528                         else
529                                 free(extra_info_str);
530                 }
531         }
532
533         return _convert_sound_manager_error_code(__func__, ret);
534 }
535
536 int sound_manager_add_focus_state_watch_cb(sound_stream_focus_mask_e focus_mask, sound_stream_focus_state_watch_cb callback, void *user_data, int *id)
537 {
538         int ret = MM_ERROR_NONE;
539         int i = 0;
540
541         LOGI(">> enter");
542
543         SM_NULL_ARG_CHECK(callback);
544         SM_NULL_ARG_CHECK(id);
545         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, SOUND_MANAGER_ERROR_INTERNAL);
546
547         for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++)
548                 if (focus_watch_info_arr[i].id == 0)
549                         break;
550         if (i == SOUND_STREAM_INFO_ARR_MAX) {
551                 LOGE("focus watch info array is full");
552                 ret = MM_ERROR_SOUND_INTERNAL;
553                 goto LEAVE;
554         }
555
556         ret = mm_sound_set_focus_watch_callback((mm_sound_focus_type_e)focus_mask, _focus_watch_callback, user_data, id);
557         if (ret == MM_ERROR_NONE) {
558                 SM_REF_FOR_STREAM_INFO(g_stream_info_count, ret);
559                 focus_watch_info_arr[i].id = *id;
560                 focus_watch_info_arr[i].user_data = user_data;
561                 focus_watch_info_arr[i].user_cb = callback;
562         }
563
564 LEAVE:
565         SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
566
567         LOGD("cnt(%d), id(%d)", g_stream_info_count, *id);
568
569         return _convert_sound_manager_error_code(__func__, ret);
570 }
571
572 int sound_manager_remove_focus_state_watch_cb(int id)
573 {
574         int ret = MM_ERROR_NONE;
575         int i = 0;
576
577         LOGI(">> enter");
578
579         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, SOUND_MANAGER_ERROR_INTERNAL);
580
581         for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++)
582                 if (focus_watch_info_arr[i].id == id)
583                         break;
584         if (i == SOUND_STREAM_INFO_ARR_MAX) {
585                 LOGE("cound not find item in focus watch info array for this id(%d)", id);
586                 ret = MM_ERROR_INVALID_ARGUMENT;
587                 goto LEAVE;
588         }
589
590         ret = mm_sound_unset_focus_watch_callback(id);
591         if (ret == MM_ERROR_NONE) {
592                 SM_UNREF_FOR_STREAM_INFO(g_stream_info_count);
593                 focus_watch_info_arr[i].id = 0;
594                 focus_watch_info_arr[i].user_data = NULL;
595                 focus_watch_info_arr[i].user_cb = NULL;
596         }
597
598 LEAVE:
599         SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
600
601         LOGD("cnt(%d)", g_stream_info_count);
602
603         return _convert_sound_manager_error_code(__func__, ret);
604 }
605
606 int sound_manager_set_session_type(sound_session_type_e type)
607 {
608         int ret = MM_ERROR_NONE;
609         int cur_session = -1;
610         int new_session = MM_SESSION_TYPE_MEDIA;
611         bool mic_enable = false;
612
613         LOGI(">> enter : type=%d", type);
614
615         if (type < SOUND_SESSION_TYPE_MEDIA || type >  SOUND_SESSION_TYPE_VOIP)
616                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
617
618         /* If session type is VOIP but MIC is not enabled, return false */
619         if (type == SOUND_SESSION_TYPE_VOIP) {
620                 ret = system_info_get_platform_bool(FEATURE_MICROPHONE, &mic_enable);
621                 LOGI("system_info_platform [%s]=[%d], ret[%d]", FEATURE_MICROPHONE, mic_enable, ret);
622                 if (ret != SYSTEM_INFO_ERROR_NONE || !mic_enable)
623                         return _convert_sound_manager_error_code(__func__, MM_ERROR_NOT_SUPPORT_API);
624         }
625
626         /* it is not supported both session and stream feature at the same time */
627         if (g_stream_info_count) {
628                 LOGE("Could not set this type(%d) because of being used stream feature", type);
629                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
630         }
631
632         switch (type) {
633         case SOUND_SESSION_TYPE_MEDIA:
634                 new_session = MM_SESSION_TYPE_MEDIA;
635                 break;
636         case SOUND_SESSION_TYPE_ALARM:
637                 new_session = MM_SESSION_TYPE_ALARM;
638                 break;
639         case SOUND_SESSION_TYPE_NOTIFICATION:
640                 new_session = MM_SESSION_TYPE_NOTIFY;
641                 break;
642         case SOUND_SESSION_TYPE_EMERGENCY:
643                 new_session = MM_SESSION_TYPE_EMERGENCY;
644                 break;
645         case SOUND_SESSION_TYPE_VOIP:
646                 new_session = MM_SESSION_TYPE_VOIP;
647                 break;
648         }
649
650         /* valid session check */
651         ret = mm_session_get_current_type(&cur_session);
652         if (ret == MM_ERROR_NONE) {
653                 if (cur_session == MM_SESSION_TYPE_MEDIA_RECORD) {
654                         if (type > SOUND_SESSION_TYPE_MEDIA) {
655                                 LOGE("Could not set this type(%d) during camera/recorder/audio-io(in)/radio", type);
656                                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
657                         }
658                 }
659         }
660
661         if (g_session_interrupt_cb_table.is_registered) {
662                 if (new_session == cur_session ||
663                         ((new_session == SOUND_SESSION_TYPE_MEDIA) && (cur_session == MM_SESSION_TYPE_MEDIA_RECORD))) {
664                         LOGI("already set type=%d, ret=0x%x", type, ret);
665                         return SOUND_MANAGER_ERROR_NONE;
666                 } else {
667                         ret = mm_session_finish();
668                         if (ret != MM_ERROR_NONE)
669                                 return _convert_sound_manager_error_code(__func__, ret);
670
671                         g_session_interrupt_cb_table.is_registered = 0;
672                         if (cur_session == MM_SESSION_TYPE_VOIP) {
673                                 g_cached_session_mode = -1;
674                                 g_cached_voip_device_id = -1;
675                                 if (g_voip_vstream_h) {
676                                         _stop_virtual_stream(g_voip_vstream_h);
677                                         _destroy_virtual_stream(g_voip_vstream_h);
678                                         g_voip_vstream_h = NULL;
679                                 }
680                                 /*voip stream destruction*/
681                                 if (g_voip_stream_info) {
682                                         ret = _destroy_pa_connection_and_unregister_focus(g_voip_stream_info);
683                                         free(g_voip_stream_info);
684                                         g_voip_stream_info = NULL;
685                                         if (ret != MM_ERROR_NONE)
686                                                 return _convert_sound_manager_error_code(__func__, ret);
687                                 }
688                         }
689                 }
690         }
691         ret = mm_session_init(new_session);
692         if (ret == MM_ERROR_NONE)
693                 g_session_interrupt_cb_table.is_registered = 1;
694
695         LOGI("type=%d", type);
696
697         return _convert_sound_manager_error_code(__func__, ret);
698 }
699
700 int sound_manager_get_session_type(sound_session_type_e *type)
701 {
702         int ret = MM_ERROR_NONE;
703         int cur_session;
704
705         if (type == NULL)
706                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
707
708         ret = mm_session_get_current_type(&cur_session);
709         if (ret != MM_ERROR_NONE) {
710                 LOGW("session hasn't been set, setting default session");
711                 cur_session = SOUND_SESSION_TYPE_DEFAULT;
712                 ret = mm_session_init(cur_session);
713                 if (ret == MM_ERROR_NONE)
714                         g_session_interrupt_cb_table.is_registered = 1;
715         }
716         if ((cur_session > MM_SESSION_TYPE_EMERGENCY) &&
717                         (cur_session != MM_SESSION_TYPE_VOIP)) {
718                 if (g_cached_session != -1)
719                         cur_session = g_cached_session;
720                 else /* will be never reached here. just prevent code */
721                         cur_session = SOUND_SESSION_TYPE_DEFAULT;
722         }
723
724         switch (cur_session) {
725         case MM_SESSION_TYPE_MEDIA:
726         case MM_SESSION_TYPE_MEDIA_RECORD:
727                 *type = SOUND_SESSION_TYPE_MEDIA;
728                 break;
729         case MM_SESSION_TYPE_ALARM:
730                 *type = SOUND_SESSION_TYPE_ALARM;
731                 break;
732         case MM_SESSION_TYPE_NOTIFY:
733                 *type = SOUND_SESSION_TYPE_NOTIFICATION;
734                 break;
735         case MM_SESSION_TYPE_EMERGENCY:
736                 *type = SOUND_SESSION_TYPE_EMERGENCY;
737                 break;
738         case MM_SESSION_TYPE_VOIP:
739                 *type = SOUND_SESSION_TYPE_VOIP;
740                 break;
741         default:
742                 *type = cur_session;
743                 break;
744         }
745
746         LOGI("type=%d", *type);
747
748         return SOUND_MANAGER_ERROR_NONE;
749 }
750
751 int sound_manager_set_media_session_option(sound_session_option_for_starting_e s_option, sound_session_option_for_during_play_e d_option)
752 {
753         int ret = MM_ERROR_NONE;
754         int session = 0;
755         int session_option = 0;
756         int updated = 0;
757
758         LOGI(">> enter : option for starting=%d, for during play=%d", s_option, d_option);
759
760         if (s_option < 0 || s_option >  SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START)
761                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
762         if (d_option < 0 || d_option >  SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY)
763                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
764
765         ret = mm_session_get_current_information(&session, &session_option);
766         if (ret != 0 || !g_session_interrupt_cb_table.is_registered) {
767                 LOGW("session hasn't been set, setting default session");
768                 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
769                 if (ret == 0)
770                         g_session_interrupt_cb_table.is_registered = 1;
771
772         } else if (ret == 0 && session > MM_SESSION_TYPE_MEDIA) {
773                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
774                         if (!g_session_interrupt_cb_table.is_registered) {
775                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
776                                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
777                         }
778                 } else {
779                         return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
780                 }
781         }
782
783         switch (s_option) {
784         case SOUND_SESSION_OPTION_MIX_WITH_OTHERS_WHEN_START:
785                 if (session_option & MM_SESSION_OPTION_PAUSE_OTHERS) {
786                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_PAUSE_OTHERS);
787                         if (ret)
788                                 return _convert_sound_manager_error_code(__func__, ret);
789
790                         updated = 1;
791                 }
792                 break;
793         case SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START:
794                 if (!(session_option & MM_SESSION_OPTION_PAUSE_OTHERS)) {
795                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_PAUSE_OTHERS);
796                         if (ret)
797                                 return _convert_sound_manager_error_code(__func__, ret);
798
799                         updated = 1;
800                 }
801                 break;
802         }
803
804         switch (d_option) {
805         case SOUND_SESSION_OPTION_INTERRUPTIBLE_DURING_PLAY:
806                 if (session_option & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
807                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_UNINTERRUPTIBLE);
808                         if (ret)
809                                 return _convert_sound_manager_error_code(__func__, ret);
810
811                         updated = 1;
812                 }
813                 break;
814         case SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY:
815                 if (!(session_option & MM_SESSION_OPTION_UNINTERRUPTIBLE)) {
816                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_UNINTERRUPTIBLE);
817                         if (ret)
818                                 return _convert_sound_manager_error_code(__func__, ret);
819
820                         updated = 1;
821                 }
822                 break;
823         }
824
825         if (updated)
826                 LOGI("updated");
827         else
828                 LOGI("already set same option(%x), skip it", session_option);
829
830         return _convert_sound_manager_error_code(__func__, ret);
831 }
832
833 int sound_manager_get_media_session_option(sound_session_option_for_starting_e *s_option, sound_session_option_for_during_play_e *d_option)
834 {
835         int ret = MM_ERROR_NONE;
836         int session = 0;
837         int session_options = 0;
838
839         LOGI(">> enter");
840
841         if (s_option == NULL || d_option == NULL)
842                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
843
844         ret = mm_session_get_current_information(&session, &session_options);
845         if (ret != 0) {
846                 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
847                 if (ret == 0)
848                         g_session_interrupt_cb_table.is_registered = 1;
849
850         } else if (session > SOUND_SESSION_TYPE_MEDIA) {
851                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
852                         if (!g_session_interrupt_cb_table.is_registered) {
853                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
854                                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
855                         }
856                 } else
857                         return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
858         }
859         /* get option */
860         if (session_options & MM_SESSION_OPTION_PAUSE_OTHERS)
861                 *s_option = SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START;
862         else
863                 *s_option = SOUND_SESSION_OPTION_MIX_WITH_OTHERS_WHEN_START;
864
865         if (session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE)
866                 *d_option = SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY;
867         else
868                 *d_option = SOUND_SESSION_OPTION_INTERRUPTIBLE_DURING_PLAY;
869
870         LOGI(" option for starting=%d, for during play=%d", *s_option, *d_option);
871
872         return SOUND_MANAGER_ERROR_NONE;
873 }
874
875 int sound_manager_set_media_session_resumption_option(sound_session_option_for_resumption_e option)
876 {
877         int ret = MM_ERROR_NONE;
878         int session = 0;
879         int session_option = 0;
880         int updated = 0;
881
882         LOGI(">> enter : option for resumption=%d (0:by system, 1:by system or media paused)", option);
883
884         if (option < SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM || option > SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED)
885                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
886
887         ret = mm_session_get_current_information(&session, &session_option);
888         if (ret != 0 || !g_session_interrupt_cb_table.is_registered) {
889                 LOGW("session hasn't been set, setting default session");
890                 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
891                 if (ret == 0)
892                         g_session_interrupt_cb_table.is_registered = 1;
893
894         } else if (ret == 0 && session > MM_SESSION_TYPE_MEDIA) {
895                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
896                         if (!g_session_interrupt_cb_table.is_registered) {
897                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
898                                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
899                         }
900                 } else
901                         return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
902
903         }
904
905         switch (option) {
906         case SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM:
907                 if (session_option & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED) {
908                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED);
909                         if (ret)
910                                 return _convert_sound_manager_error_code(__func__, ret);
911
912                         updated = 1;
913                 }
914                 break;
915         case SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED:
916                 if (!(session_option & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED)) {
917                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED);
918                         if (ret)
919                                 return _convert_sound_manager_error_code(__func__, ret);
920
921                         updated = 1;
922                 }
923                 break;
924         }
925
926         if (updated)
927                 LOGI("updated");
928         else
929                 LOGI("already set same option(0x%x), skip it", session_option);
930
931         return _convert_sound_manager_error_code(__func__, ret);
932 }
933
934 int sound_manager_get_media_session_resumption_option(sound_session_option_for_resumption_e *option)
935 {
936         int ret = MM_ERROR_NONE;
937         int session = 0;
938         int session_options = 0;
939
940         LOGI(">> enter");
941
942         if (option == NULL)
943                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
944
945         ret = mm_session_get_current_information(&session, &session_options);
946         if (ret != 0) {
947                 LOGW("session hasn't been set, setting default session");
948                 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
949                 if (ret == 0)
950                         g_session_interrupt_cb_table.is_registered = 1;
951
952         } else if (session > SOUND_SESSION_TYPE_MEDIA) {
953                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
954                         if (!g_session_interrupt_cb_table.is_registered) {
955                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
956                                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
957                         }
958                 } else
959                         return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
960         }
961         /* get option */
962         if (session_options & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED)
963                 *option = SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED;
964         else
965                 *option = SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM;
966
967         LOGI("option for resumption=%d (0:by system, 1:by system or media paused)", *option);
968
969         return SOUND_MANAGER_ERROR_NONE;
970 }
971
972 int sound_manager_set_voip_session_mode(sound_session_voip_mode_e mode)
973 {
974         int ret = MM_ERROR_NONE;
975         int session = 0;
976         int session_options = 0;
977
978         LOGI(">> enter : mode=%d", mode);
979
980         ret = mm_session_get_current_information(&session, &session_options);
981         if (ret != MM_ERROR_NONE)
982                 goto LEAVE;
983
984         if (session != MM_SESSION_TYPE_VOIP) {
985                 ret = MM_ERROR_POLICY_INTERNAL;
986                 goto LEAVE;
987         }
988
989         if (mode < SOUND_SESSION_VOIP_MODE_RINGTONE || mode > SOUND_SESSION_VOIP_MODE_VOICE_WITH_BLUETOOTH) {
990                 ret = MM_ERROR_INVALID_ARGUMENT;
991                 goto LEAVE;
992         }
993
994         ret = _set_session_mode((_session_mode_e)mode);
995
996         LOGI("session=%d, mode=%d", session, mode);
997
998 LEAVE:
999         return _convert_sound_manager_error_code(__func__, ret);
1000 }
1001
1002 int sound_manager_get_voip_session_mode(sound_session_voip_mode_e *mode)
1003 {
1004         int ret = MM_ERROR_NONE;
1005         int session = 0;
1006         int session_options = 0;
1007
1008         if (mode == NULL) {
1009                 LOGE("mode is null");
1010                 ret = MM_ERROR_INVALID_ARGUMENT;
1011                 goto LEAVE;
1012         }
1013
1014         ret = mm_session_get_current_information(&session, &session_options);
1015         if (ret != MM_ERROR_NONE) {
1016                 LOGI("session = %d, option = %d", session, session_options);
1017                 goto LEAVE;
1018         }
1019
1020         if (session != MM_SESSION_TYPE_VOIP || g_cached_session_mode == -1) {
1021                 ret = MM_ERROR_POLICY_INTERNAL;
1022                 goto LEAVE;
1023         }
1024
1025         *mode = (sound_session_voip_mode_e)g_cached_session_mode;
1026
1027         LOGI("session=%d, mode=%d", session, *mode);
1028
1029 LEAVE:
1030         return _convert_sound_manager_error_code(__func__, ret);
1031 }
1032
1033 int sound_manager_set_session_interrupted_cb(sound_session_interrupted_cb callback, void *user_data)
1034 {
1035         int ret = MM_ERROR_NONE;
1036         unsigned int subs_id = 0;
1037
1038         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_interrupt_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1039
1040         if (callback == NULL) {
1041                 ret = MM_ERROR_INVALID_ARGUMENT;
1042                 goto LEAVE;
1043         }
1044
1045         /* it is not supported both session and stream feature at the same time */
1046         if (g_stream_info_count) {
1047                 ret =  MM_ERROR_POLICY_INTERNAL;
1048                 goto LEAVE;
1049         }
1050
1051         if (g_session_interrupt_cb_table.user_cb == NULL) {
1052                 ret = mm_sound_add_device_connected_callback(SOUND_DEVICE_ALL_MASK, (mm_sound_device_connected_cb)_device_connected_cb, NULL, &subs_id);
1053                 if (ret)
1054                         goto LEAVE;
1055                 ret = mm_sound_focus_set_session_interrupt_callback((mm_sound_focus_session_interrupt_cb)_focus_session_interrupt_cb, NULL);
1056                 if (ret) {
1057                         if (mm_sound_remove_device_connected_callback(subs_id) != MM_ERROR_NONE)
1058                                 LOGW("mm_sound_remove_device_connected_callback failed");
1059                         goto LEAVE;
1060                 }
1061                 g_session_interrupt_cb_table.subs_id = subs_id;
1062         }
1063         g_session_interrupt_cb_table.user_cb = (sound_session_interrupted_cb)callback;
1064         g_session_interrupt_cb_table.user_data = user_data;
1065
1066 LEAVE:
1067         SM_LEAVE_CRITICAL_SECTION(&g_interrupt_cb_mutex);
1068
1069         return _convert_sound_manager_error_code(__func__, ret);
1070 }
1071
1072 int sound_manager_unset_session_interrupted_cb(void)
1073 {
1074         int ret = MM_ERROR_NONE;
1075
1076         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_interrupt_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1077
1078         if (!g_session_interrupt_cb_table.user_cb) {
1079                 ret = MM_ERROR_SOUND_INTERNAL;
1080                 goto LEAVE;
1081         }
1082
1083         ret = mm_sound_focus_unset_session_interrupt_callback();
1084         if (ret) {
1085                 if (mm_sound_remove_device_connected_callback(g_session_interrupt_cb_table.subs_id) != MM_ERROR_NONE)
1086                         LOGW("mm_sound_remove_device_connected_callback failed");
1087                 goto LEAVE;
1088         }
1089
1090         ret = mm_sound_remove_device_connected_callback(g_session_interrupt_cb_table.subs_id);
1091         if (ret)
1092                 goto LEAVE;
1093
1094         g_session_interrupt_cb_table.subs_id = 0;
1095         g_session_interrupt_cb_table.user_cb = NULL;
1096         g_session_interrupt_cb_table.user_data = NULL;
1097
1098 LEAVE:
1099         SM_LEAVE_CRITICAL_SECTION(&g_interrupt_cb_mutex);
1100
1101         return _convert_sound_manager_error_code(__func__, ret);
1102 }
1103
1104 int sound_manager_get_current_device_list(sound_device_mask_e device_mask, sound_device_list_h *device_list)
1105 {
1106         int ret = MM_ERROR_NONE;
1107
1108         ret = mm_sound_get_current_device_list((mm_sound_device_flags_e)device_mask, device_list);
1109
1110         return _convert_sound_manager_error_code(__func__, ret);
1111 }
1112
1113 int sound_manager_free_device_list(sound_device_list_h device_list)
1114 {
1115         int ret = MM_ERROR_NONE;
1116
1117         ret = mm_sound_free_device_list(device_list);
1118
1119         return _convert_sound_manager_error_code(__func__, ret);
1120 }
1121
1122 int sound_manager_get_next_device(sound_device_list_h device_list, sound_device_h *device)
1123 {
1124         int ret = MM_ERROR_NONE;
1125
1126         ret = mm_sound_get_next_device(device_list, device);
1127
1128         return _convert_sound_manager_error_code(__func__, ret);
1129 }
1130
1131 int sound_manager_get_prev_device(sound_device_list_h device_list, sound_device_h *device)
1132 {
1133         int ret = MM_ERROR_NONE;
1134
1135         ret = mm_sound_get_prev_device(device_list, device);
1136
1137         return _convert_sound_manager_error_code(__func__, ret);
1138 }
1139
1140 int sound_manager_get_device_type(sound_device_h device, sound_device_type_e *type)
1141 {
1142         int ret = MM_ERROR_NONE;
1143
1144         ret = mm_sound_get_device_type(device, (mm_sound_device_type_e*)type);
1145
1146         return _convert_sound_manager_error_code(__func__, ret);
1147 }
1148
1149 int sound_manager_get_device_io_direction(sound_device_h device, sound_device_io_direction_e *io_direction)
1150 {
1151         int ret = MM_ERROR_NONE;
1152         mm_sound_device_io_direction_e mm_sound_io_direction;
1153
1154         ret = mm_sound_get_device_io_direction(device, &mm_sound_io_direction);
1155         if (ret == MM_ERROR_NONE)
1156                 ret = _convert_device_io_direction(mm_sound_io_direction, io_direction);
1157
1158         return _convert_sound_manager_error_code(__func__, ret);
1159 }
1160
1161 int sound_manager_get_device_id(sound_device_h device, int *id)
1162 {
1163         int ret = MM_ERROR_NONE;
1164
1165         ret = mm_sound_get_device_id(device, id);
1166
1167         return _convert_sound_manager_error_code(__func__, ret);
1168 }
1169
1170 int sound_manager_get_device_name(sound_device_h device, char **name)
1171 {
1172         int ret = MM_ERROR_NONE;
1173
1174         ret = mm_sound_get_device_name(device, name);
1175
1176         return _convert_sound_manager_error_code(__func__, ret);
1177 }
1178
1179 int sound_manager_get_device_state(sound_device_h device, sound_device_state_e *state)
1180 {
1181         int ret = MM_ERROR_NONE;
1182
1183         ret = mm_sound_get_device_state(device, (mm_sound_device_state_e*)state);
1184
1185         return _convert_sound_manager_error_code(__func__, ret);
1186 }
1187
1188 int sound_manager_set_device_connected_cb(sound_device_mask_e device_mask, sound_device_connected_cb callback, void *user_data)
1189 {
1190         int ret = MM_ERROR_NONE;
1191         unsigned int subs_id = 0;
1192
1193         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_conn_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1194
1195         ret = mm_sound_add_device_connected_callback((mm_sound_device_flags_e)device_mask, (mm_sound_device_connected_cb)callback, user_data, &subs_id);
1196         if (ret == MM_ERROR_NONE) {
1197                 g_device_connected_cb_table.subs_id = subs_id;
1198                 g_device_connected_cb_table.user_cb = (sound_device_connected_cb)callback;
1199                 g_device_connected_cb_table.user_data = user_data;
1200         }
1201
1202         SM_LEAVE_CRITICAL_SECTION(&g_device_conn_cb_mutex);
1203
1204         return _convert_sound_manager_error_code(__func__, ret);
1205 }
1206
1207 int sound_manager_unset_device_connected_cb(void)
1208 {
1209         int ret = MM_ERROR_NONE;
1210
1211         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_conn_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1212
1213         if (g_device_connected_cb_table.subs_id == 0) {
1214                 ret = MM_ERROR_SOUND_INTERNAL;
1215                 goto LEAVE;
1216         }
1217
1218         ret = mm_sound_remove_device_connected_callback(g_device_connected_cb_table.subs_id);
1219         if (ret == MM_ERROR_NONE) {
1220                 g_device_connected_cb_table.subs_id = 0;
1221                 g_device_connected_cb_table.user_cb = NULL;
1222                 g_device_connected_cb_table.user_data = NULL;
1223         }
1224
1225 LEAVE:
1226         SM_LEAVE_CRITICAL_SECTION(&g_device_conn_cb_mutex);
1227
1228         return _convert_sound_manager_error_code(__func__, ret);
1229 }
1230
1231 int sound_manager_set_device_information_changed_cb(sound_device_mask_e device_mask, sound_device_information_changed_cb callback, void *user_data)
1232 {
1233         int ret = MM_ERROR_NONE;
1234         unsigned int subs_id = 0;
1235
1236         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_info_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1237
1238         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);
1239         if (ret == MM_ERROR_NONE) {
1240                 g_device_info_changed_cb_table.subs_id = subs_id;
1241                 g_device_info_changed_cb_table.user_cb = (sound_device_information_changed_cb)callback;
1242                 g_device_info_changed_cb_table.user_data = user_data;
1243         }
1244
1245         SM_LEAVE_CRITICAL_SECTION(&g_device_info_cb_mutex);
1246
1247         return _convert_sound_manager_error_code(__func__, ret);
1248 }
1249
1250 int sound_manager_unset_device_information_changed_cb(void)
1251 {
1252         int ret = MM_ERROR_NONE;
1253
1254         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_info_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1255
1256         if (g_device_info_changed_cb_table.subs_id == 0) {
1257                 ret = MM_ERROR_SOUND_INTERNAL;
1258                 goto LEAVE;
1259         }
1260
1261         ret = mm_sound_remove_device_information_changed_callback(g_device_info_changed_cb_table.subs_id);
1262         if (ret == MM_ERROR_NONE) {
1263                 g_device_info_changed_cb_table.subs_id = 0;
1264                 g_device_info_changed_cb_table.user_cb = NULL;
1265                 g_device_info_changed_cb_table.user_data = NULL;
1266         }
1267
1268 LEAVE:
1269         SM_LEAVE_CRITICAL_SECTION(&g_device_info_cb_mutex);
1270
1271         return _convert_sound_manager_error_code(__func__, ret);
1272 }
1273
1274 __attribute__ ((destructor))
1275 void __sound_manager_finalize(void)
1276 {
1277         int ret = MM_ERROR_NONE;
1278
1279         if (g_session_interrupt_cb_table.is_registered) {
1280                 LOGI("<ENTER>");
1281                 ret = mm_session_finish();
1282                 if (ret != MM_ERROR_NONE)
1283                         LOGE("[%s] failed to mm_session_finish(), ret(0x%x)", __func__, ret);
1284
1285                 g_session_interrupt_cb_table.is_registered = 0;
1286                 LOGI("<LEAVE>");
1287         }
1288 }
1289
1290 __attribute__ ((constructor))
1291 void __sound_manager_initialize(void)
1292 {
1293
1294 }