Add new API to deliver focus to another stream info handle without invoking focus...
[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 int g_cached_voip_device_id2 = -1;
33 extern sound_stream_info_s *g_voip_stream_info;
34 extern sound_stream_info_s *g_voip_ringtone_stream_info;
35 extern virtual_sound_stream_info_s *g_voip_vstream_h;
36 extern virtual_sound_stream_info_s *g_voip_ringtone_vstream_h;
37
38 /* These variables will be removed when session features are deprecated. */
39 extern int g_stream_info_count;
40 extern pthread_mutex_t g_stream_info_count_mutex;
41 pthread_mutex_t g_session_mutex = PTHREAD_MUTEX_INITIALIZER;
42 pthread_mutex_t g_interrupt_cb_mutex = PTHREAD_MUTEX_INITIALIZER;
43 pthread_mutex_t g_device_info_cb_mutex = PTHREAD_MUTEX_INITIALIZER;
44 pthread_mutex_t g_device_conn_cb_mutex = PTHREAD_MUTEX_INITIALIZER;
45 pthread_mutex_t g_volume_cb_mutex = PTHREAD_MUTEX_INITIALIZER;
46
47 int sound_manager_get_max_volume(sound_type_e type, int *max)
48 {
49         const char *volume_type = NULL;
50         unsigned int max_level = 0;
51         int ret = MM_ERROR_NONE;
52
53         SM_NULL_ARG_CHECK(max);
54         if (type >= SOUND_TYPE_NUM || type < 0)
55                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
56
57         ret = _convert_sound_type(type, &volume_type);
58         if (ret == MM_ERROR_NONE) {
59                 ret = _get_volume_max_level(DIRECTION_OUT_STR, volume_type, &max_level);
60                 if (ret == MM_ERROR_NONE)
61                         *max = (int)max_level -1;       /* actual volume step can be max step - 1 */
62         }
63
64         return _convert_sound_manager_error_code(__func__, ret);
65 }
66
67 int sound_manager_set_volume(sound_type_e type, int volume)
68 {
69         int ret = MM_ERROR_NONE;
70
71         if (type >= SOUND_TYPE_NUM || type < 0)
72                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
73         if (volume < 0)
74                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
75
76         ret = mm_sound_volume_set_value(type, volume);
77         LOGI("type=%d, volume=%d", type, volume);
78
79         return _convert_sound_manager_error_code(__func__, ret);
80 }
81
82 int sound_manager_get_volume(sound_type_e type, int *volume)
83 {
84         int ret = MM_ERROR_NONE;
85         unsigned int uvolume;
86
87         if (type >= SOUND_TYPE_NUM || type < 0)
88                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
89         if (volume == NULL)
90                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
91
92         ret = mm_sound_volume_get_value(type, &uvolume);
93         if (ret == MM_ERROR_NONE)
94                 *volume = uvolume;
95
96         LOGI("type=%d, volume=%d", type, *volume);
97
98         return _convert_sound_manager_error_code(__func__, ret);
99 }
100
101 int sound_manager_set_current_sound_type(sound_type_e type)
102 {
103         int ret = MM_ERROR_NONE;
104
105         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release.", __func__);
106         if (type >= SOUND_TYPE_NUM || type < 0)
107                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
108
109         ret = mm_sound_volume_primary_type_set(type);
110
111         return _convert_sound_manager_error_code(__func__, ret);
112 }
113
114 int sound_manager_get_current_sound_type(sound_type_e *type)
115 {
116         int ret = MM_ERROR_NONE;
117         volume_type_t mm_sound_vol_type = VOLUME_TYPE_UNKNOWN;
118         char *volume_type = NULL;
119
120         if (type == NULL)
121                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
122
123         ret  = mm_sound_volume_primary_type_get(&mm_sound_vol_type);
124         if (ret == MM_ERROR_NONE) {
125                 if (mm_sound_vol_type == VOLUME_TYPE_UNKNOWN) {
126                         /* get the volume type of the current playing stream */
127                         ret = _get_current_volume_type(DIRECTION_OUT_STR, &volume_type);
128                         if (ret == MM_ERROR_NONE)
129                                 ret = _convert_sound_type_to_enum((const char*)volume_type, type);
130                 } else {
131                         *type = mm_sound_vol_type;
132                 }
133         }
134         LOGI("type=%d", *type);
135
136         return _convert_sound_manager_error_code(__func__, ret);
137 }
138
139 int sound_manager_unset_current_sound_type(void)
140 {
141         int ret = MM_ERROR_NONE;
142
143         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release.", __func__);
144         ret = mm_sound_volume_primary_type_set(VOLUME_TYPE_UNKNOWN);
145
146         return _convert_sound_manager_error_code(__func__, ret);
147 }
148
149 int sound_manager_set_volume_changed_cb(sound_manager_volume_changed_cb callback, void* user_data)
150 {
151         int ret = MM_ERROR_NONE;
152         unsigned int subs_id = 0;
153
154         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. "
155                 "Use sound_manager_add_volume_changed_cb() instead.", __func__);
156
157         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_volume_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
158
159         ret = mm_sound_add_volume_changed_callback((mm_sound_volume_changed_cb)callback, user_data, &subs_id);
160         if (ret == MM_ERROR_NONE) {
161                 g_volume_changed_cb_table.subs_id = subs_id;
162                 g_volume_changed_cb_table.user_cb = (sound_manager_volume_changed_cb)callback;
163                 g_volume_changed_cb_table.user_data = user_data;
164         }
165
166         SM_LEAVE_CRITICAL_SECTION(&g_volume_cb_mutex);
167
168         return _convert_sound_manager_error_code(__func__, ret);
169 }
170
171 int sound_manager_unset_volume_changed_cb(void)
172 {
173         int ret = MM_ERROR_NONE;
174
175         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. "
176                 "Use sound_manager_remove_volume_changed_cb() instead.", __func__);
177
178         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_volume_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
179
180         if (g_volume_changed_cb_table.subs_id > 0) {
181                 ret = mm_sound_remove_volume_changed_callback(g_volume_changed_cb_table.subs_id);
182                 if (ret == MM_ERROR_NONE) {
183                         g_volume_changed_cb_table.subs_id = 0;
184                         g_volume_changed_cb_table.user_cb = NULL;
185                         g_volume_changed_cb_table.user_data = NULL;
186                 }
187         } else {
188                 ret = MM_ERROR_SOUND_INTERNAL;
189         }
190
191         SM_LEAVE_CRITICAL_SECTION(&g_volume_cb_mutex);
192
193         return _convert_sound_manager_error_code(__func__, ret);
194 }
195
196 int sound_manager_add_volume_changed_cb(sound_manager_volume_changed_cb callback, void *user_data, int *id)
197 {
198         int ret = MM_ERROR_NONE;
199
200         if (!callback || !id)
201                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
202
203         ret = mm_sound_add_volume_changed_callback((mm_sound_volume_changed_cb)callback, user_data, (unsigned int*)id);
204
205         return _convert_sound_manager_error_code(__func__, ret);
206 }
207
208 int sound_manager_remove_volume_changed_cb(int id)
209 {
210         int ret = MM_ERROR_NONE;
211
212         if (id < 0)
213                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
214
215         ret = mm_sound_remove_volume_changed_callback(id);
216
217         return _convert_sound_manager_error_code(__func__, ret);
218 }
219
220 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)
221 {
222         int ret = MM_ERROR_NONE;
223
224         LOGI(">> enter");
225
226         SM_NULL_ARG_CHECK(stream_info);
227
228         if (g_session_interrupt_cb_table.is_registered)
229                 return _convert_sound_manager_error_code(__func__, MM_ERROR_SOUND_INTERNAL);
230
231         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, MM_ERROR_SOUND_INTERNAL);
232
233         sound_stream_info_s *stream_h = malloc(sizeof(sound_stream_info_s));
234         if (!stream_h) {
235                 ret = MM_ERROR_OUT_OF_MEMORY;
236                 goto LEAVE;
237         }
238
239         memset(stream_h, 0, sizeof(sound_stream_info_s));
240         ret = _convert_stream_type(stream_type, &stream_h->stream_type);
241         if (ret == MM_ERROR_NONE) {
242                 ret = _make_pa_connection_and_register_focus(stream_h, false, callback, user_data);
243                 if (ret == MM_ERROR_NONE) {
244                         *stream_info = (sound_stream_info_h)stream_h;
245                         SM_REF_FOR_STREAM_INFO(g_stream_info_count, ret);
246                         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);
247                 }
248         }
249
250 LEAVE:
251         if (ret)
252                 SM_SAFE_FREE(stream_h);
253
254         SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
255
256         return _convert_sound_manager_error_code(__func__, ret);
257 }
258
259 int sound_manager_destroy_stream_information(sound_stream_info_h stream_info)
260 {
261         int ret = MM_ERROR_NONE;
262         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
263
264         LOGI(">> enter");
265
266         SM_INSTANCE_CHECK(stream_h);
267
268         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, MM_ERROR_SOUND_INTERNAL);
269         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_state_mutex, MM_ERROR_SOUND_INTERNAL);
270         ret = _destroy_pa_connection_and_unregister_focus(stream_h);
271         SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_state_mutex);
272         if (ret == MM_ERROR_NONE) {
273                 SM_SAFE_FREE(stream_h);
274                 SM_UNREF_FOR_STREAM_INFO(g_stream_info_count);
275         }
276         SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
277
278         LOGD("cnt(%d)", g_stream_info_count);
279
280         return _convert_sound_manager_error_code(__func__, ret);
281 }
282
283 int sound_manager_get_sound_type(sound_stream_info_h stream_info, sound_type_e *sound_type)
284 {
285         int ret = MM_ERROR_NONE;
286         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
287
288         LOGI(">> enter");
289
290         SM_INSTANCE_CHECK(stream_h);
291         SM_NULL_ARG_CHECK(sound_type);
292
293         if (stream_h->stream_conf_info.volume_type == NULL) {
294                 ret = MM_ERROR_SOUND_NO_DATA;
295                 goto LEAVE;
296         }
297
298         ret = _convert_sound_type_to_enum(stream_h->stream_conf_info.volume_type, sound_type);
299         LOGI("sound type(%d)", *sound_type);
300
301 LEAVE:
302         return _convert_sound_manager_error_code(__func__, ret);
303 }
304
305 int sound_manager_add_device_for_stream_routing(sound_stream_info_h stream_info, sound_device_h device)
306 {
307         int ret = MM_ERROR_NONE;
308         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
309
310         LOGI(">> enter");
311
312         ret = _add_device_for_stream_routing(stream_h, device);
313
314         return _convert_sound_manager_error_code(__func__, ret);
315 }
316
317 int sound_manager_remove_device_for_stream_routing(sound_stream_info_h stream_info, sound_device_h device)
318 {
319         int ret = MM_ERROR_NONE;
320         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
321
322         LOGI(">> enter");
323
324         ret = _remove_device_for_stream_routing(stream_h, device);
325
326         return _convert_sound_manager_error_code(__func__, ret);
327 }
328
329 int sound_manager_apply_stream_routing(sound_stream_info_h stream_info)
330 {
331         int ret = MM_ERROR_NONE;
332         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
333
334         LOGI(">> enter");
335
336         ret = _apply_stream_routing(stream_h);
337
338         return _convert_sound_manager_error_code(__func__, ret);
339 }
340
341 int sound_manager_set_focus_reacquisition(sound_stream_info_h stream_info, bool enable)
342 {
343         int ret = MM_ERROR_NONE;
344         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
345
346         LOGI(">> enter");
347
348         SM_INSTANCE_CHECK(stream_h);
349
350         ret = mm_sound_set_focus_reacquisition(stream_h->index, enable);
351
352         LOGI("enable(%d)", enable);
353
354         return _convert_sound_manager_error_code(__func__, ret);
355 }
356
357 int sound_manager_get_focus_reacquisition(sound_stream_info_h stream_info, bool *enabled)
358 {
359         int ret = MM_ERROR_NONE;
360         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
361
362         LOGI(">> enter");
363
364         SM_INSTANCE_CHECK(stream_h);
365         SM_NULL_ARG_CHECK(enabled);
366
367         ret = mm_sound_get_focus_reacquisition(stream_h->index, enabled);
368
369         LOGI("enabled(%d)", *enabled);
370
371         return _convert_sound_manager_error_code(__func__, ret);
372 }
373
374 int sound_manager_acquire_focus(sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask, int sound_behavior, const char *extra_info)
375 {
376         int ret = MM_ERROR_NONE;
377         bool is_focus_cb_thread = false;
378         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
379
380         LOGI(">> enter");
381
382         SM_INSTANCE_CHECK(stream_h);
383
384         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
385                 return _convert_sound_manager_error_code(__func__, ret);
386
387         if (stream_h->is_focus_unavailable) {
388                 LOGE("acquiring focus is not allowed for this stream type(%s)", stream_h->stream_type);
389                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
390         }
391
392         if (stream_h->user_cb == NULL) {
393                 LOGE("focus state changed callback should be set before acquiring focus");
394                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
395         }
396
397         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_state_mutex, MM_ERROR_SOUND_INTERNAL);
398
399         if (stream_h->acquired_focus & focus_mask) {
400                 LOGE("invalid state: focus_mask[0x%x], acquired_focus[0x%x]", focus_mask, stream_h->acquired_focus);
401                 ret = MM_ERROR_SOUND_INVALID_STATE;
402                 goto LEAVE;
403         }
404
405         if (is_focus_cb_thread && ((stream_h->prev_acquired_focus | ~stream_h->acquired_focus) & SOUND_STREAM_FOCUS_FOR_BOTH) != focus_mask) {
406                 LOGE("just lost focus in this callback, it is not allowed to acquire the focus[0x%x] again. acquired_focus[0x%x], prev[0x%x]",
407                         focus_mask, stream_h->acquired_focus, stream_h->prev_acquired_focus);
408                 ret = MM_ERROR_POLICY_INTERNAL;
409                 goto LEAVE;
410         }
411
412         ret = mm_sound_acquire_focus_with_option(stream_h->index, (mm_sound_focus_type_e)focus_mask, sound_behavior, extra_info);
413         if (ret == MM_ERROR_NONE) {
414                 stream_h->acquired_focus |= focus_mask;
415                 stream_h->prev_acquired_focus |= focus_mask;
416                 _update_focus_status(stream_h->index, (unsigned int)stream_h->acquired_focus);
417         }
418
419         LOGI("acquired_focus[0x%x], prev[0x%x]", stream_h->acquired_focus, stream_h->prev_acquired_focus);
420
421 LEAVE:
422         SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_state_mutex);
423
424         return _convert_sound_manager_error_code(__func__, ret);
425 }
426
427 int sound_manager_release_focus(sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask, int sound_behavior, const char *extra_info)
428 {
429         int ret = MM_ERROR_NONE;
430         bool is_focus_cb_thread = false;
431         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
432
433         LOGI(">> enter");
434
435         SM_INSTANCE_CHECK(stream_h);
436
437         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
438                 return _convert_sound_manager_error_code(__func__, ret);
439
440         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_state_mutex, MM_ERROR_SOUND_INTERNAL);
441
442         if (!(stream_h->acquired_focus & focus_mask)) {
443                 LOGE("invalid state: focus_mask[0x%x], acquired_focus[0x%x]", focus_mask, stream_h->acquired_focus);
444                 ret = MM_ERROR_SOUND_INVALID_STATE;
445                 goto LEAVE;
446         }
447
448         if (is_focus_cb_thread && ((stream_h->prev_acquired_focus & stream_h->acquired_focus) != focus_mask)) {
449                 LOGE("just acquired focus in this callback, it is not allowed to release the focus[0x%x] again. acquired_focus[0x%x], prev[0x%x]",
450                         focus_mask, stream_h->acquired_focus, stream_h->prev_acquired_focus);
451                 ret = MM_ERROR_SOUND_INVALID_STATE;
452                 goto LEAVE;
453         }
454
455         ret = mm_sound_release_focus_with_option(stream_h->index, (mm_sound_focus_type_e)focus_mask, sound_behavior, extra_info);
456         if (ret == MM_ERROR_NONE) {
457                 stream_h->acquired_focus &= ~focus_mask;
458                 stream_h->prev_acquired_focus &= ~focus_mask;
459                 _update_focus_status(stream_h->index, (unsigned int)stream_h->acquired_focus);
460         }
461
462         LOGI("acquired_focus[0x%x], prev[0x%x]", stream_h->acquired_focus, stream_h->prev_acquired_focus);
463
464 LEAVE:
465         SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_state_mutex);
466
467         return _convert_sound_manager_error_code(__func__, ret);
468 }
469
470 int sound_manager_acquire_focus_all(sound_stream_info_h stream_info, int sound_behavior, const char *extra_info)
471 {
472         int ret = MM_ERROR_NONE;
473         int focus_mask = SOUND_STREAM_FOCUS_FOR_BOTH;
474         bool is_focus_cb_thread = false;
475         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
476
477         LOGI(">> enter");
478
479         SM_INSTANCE_CHECK(stream_h);
480
481         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
482                 return _convert_sound_manager_error_code(__func__, ret);
483
484         if (stream_h->is_focus_unavailable) {
485                 LOGE("acquiring focus is not allowed for this stream type(%s)", stream_h->stream_type);
486                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
487         }
488
489         if (stream_h->user_cb == NULL) {
490                 LOGE("focus state changed callback should be set before acquiring focus");
491                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
492         }
493
494         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_state_mutex, MM_ERROR_SOUND_INTERNAL);
495
496         if (is_focus_cb_thread && (stream_h->prev_acquired_focus > stream_h->acquired_focus)) {
497                 LOGE("just lost focus in this callback, it is not allowed to acquire all again. acquired_focus[0x%x], prev[0x%x]",
498                         stream_h->acquired_focus, stream_h->prev_acquired_focus);
499                 ret = MM_ERROR_POLICY_INTERNAL;
500                 goto LEAVE;
501         }
502
503         focus_mask = SOUND_STREAM_FOCUS_FOR_BOTH & ~(stream_h->acquired_focus);
504         if (!focus_mask) {
505                 LOGI("PLAYBACK/RECORDING focuses have already been ACQUIRED");
506                 ret = MM_ERROR_NONE;
507                 goto LEAVE;
508         }
509
510         ret = mm_sound_acquire_focus_with_option(stream_h->index, (mm_sound_focus_type_e)focus_mask, sound_behavior, extra_info);
511         if (ret == MM_ERROR_NONE) {
512                 stream_h->acquired_focus |= focus_mask;
513                 stream_h->prev_acquired_focus |= focus_mask;
514                 _update_focus_status(stream_h->index, (unsigned int)stream_h->acquired_focus);
515         }
516
517 LEAVE:
518         SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_state_mutex);
519
520         return _convert_sound_manager_error_code(__func__, ret);
521 }
522
523 int sound_manager_release_focus_all(sound_stream_info_h stream_info, int sound_behavior, const char *extra_info)
524 {
525         int ret = MM_ERROR_NONE;
526         bool is_focus_cb_thread = false;
527         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
528
529         LOGI(">> enter");
530
531         SM_INSTANCE_CHECK(stream_h);
532
533         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
534                 return _convert_sound_manager_error_code(__func__, ret);
535
536         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_state_mutex, MM_ERROR_SOUND_INTERNAL);
537
538         if (is_focus_cb_thread && (stream_h->prev_acquired_focus < stream_h->acquired_focus)) {
539                 LOGE("just acquired focus in this callback, it is not allowed to release all again. acquired_focus[0x%x], prev[0x%x]",
540                         stream_h->acquired_focus, stream_h->prev_acquired_focus);
541                 ret = MM_ERROR_POLICY_INTERNAL;
542                 goto LEAVE;
543         }
544
545         if (!stream_h->acquired_focus) {
546                 LOGI("PLAYBACK/RECORDING focuses have already been RELEASED");
547                 ret = MM_ERROR_NONE;
548                 goto LEAVE;
549         }
550
551         ret = mm_sound_release_focus_with_option(stream_h->index, (mm_sound_focus_type_e)stream_h->acquired_focus, sound_behavior, extra_info);
552         if (ret == MM_ERROR_NONE) {
553                 stream_h->acquired_focus = 0;
554                 stream_h->prev_acquired_focus = 0;
555                 _update_focus_status(stream_h->index, (unsigned int)stream_h->acquired_focus);
556         }
557
558 LEAVE:
559         SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_state_mutex);
560
561         return _convert_sound_manager_error_code(__func__, ret);
562 }
563
564 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)
565 {
566         int ret = MM_ERROR_NONE;
567         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
568
569         LOGI(">> enter");
570
571         SM_INSTANCE_CHECK(stream_h);
572         if (!state_for_playback && !state_for_recording)
573                 return SOUND_MANAGER_ERROR_INVALID_PARAMETER;
574
575         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_state_mutex, MM_ERROR_SOUND_INTERNAL);
576
577         if (state_for_playback)
578                 *state_for_playback = ((stream_h->acquired_focus & SOUND_STREAM_FOCUS_FOR_PLAYBACK) ? (SOUND_STREAM_FOCUS_STATE_ACQUIRED) : (SOUND_STREAM_FOCUS_STATE_RELEASED));
579         if (state_for_recording)
580                 *state_for_recording = ((stream_h->acquired_focus & SOUND_STREAM_FOCUS_FOR_RECORDING) ? (SOUND_STREAM_FOCUS_STATE_ACQUIRED) : (SOUND_STREAM_FOCUS_STATE_RELEASED));
581
582         LOGI("acquired_focus(0x%x)", stream_h->acquired_focus);
583
584         SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_state_mutex);
585
586         return _convert_sound_manager_error_code(__func__, ret);
587 }
588
589 int sound_manager_deliver_focus(sound_stream_info_h source, sound_stream_info_h destination, sound_stream_focus_mask_e focus_mask)
590 {
591         int ret = MM_ERROR_NONE;
592         sound_stream_info_s *src_stream_h = (sound_stream_info_s*)source;
593         sound_stream_info_s *dst_stream_h = (sound_stream_info_s*)destination;
594         bool is_focus_cb_thread = false;
595
596         LOGI(">> enter");
597
598         SM_INSTANCE_CHECK(src_stream_h);
599         SM_INSTANCE_CHECK(dst_stream_h);
600
601         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
602                 return _convert_sound_manager_error_code(__func__, ret);
603
604         if (is_focus_cb_thread) {
605                 LOGE("not allowed calling this function in focus(watch) callback");
606                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
607         }
608
609         if (src_stream_h->index == dst_stream_h->index) {
610                 LOGE("not allowed because both handles have same index(%u)", src_stream_h->index);
611                 return SOUND_MANAGER_ERROR_INVALID_PARAMETER;
612         }
613
614         if (src_stream_h->is_focus_unavailable || dst_stream_h->is_focus_unavailable) {
615                 LOGE("focus is unavailable for source(%d)/destination(%d)",
616                         src_stream_h->is_focus_unavailable, dst_stream_h->is_focus_unavailable);
617                 return SOUND_MANAGER_ERROR_POLICY;
618         }
619
620         if (!(src_stream_h->acquired_focus & focus_mask) || (src_stream_h->acquired_focus < focus_mask)) {
621                 LOGE("could not deliver the request focus(0x%x), current acquired focus(0x%x)",
622                         focus_mask, src_stream_h->acquired_focus);
623                 return SOUND_MANAGER_ERROR_INVALID_STATE;
624         }
625
626         if (dst_stream_h->user_cb == NULL) {
627                 LOGE("focus state changed callback should be set to destination handle");
628                 return SOUND_MANAGER_ERROR_POLICY;
629         }
630
631         ret = mm_sound_deliver_focus(src_stream_h->index, dst_stream_h->index, (mm_sound_focus_type_e)focus_mask);
632         if (ret == MM_ERROR_NONE) {
633                 src_stream_h->acquired_focus &= ~focus_mask;
634                 src_stream_h->prev_acquired_focus &= ~focus_mask;
635                 dst_stream_h->acquired_focus |= focus_mask;
636                 dst_stream_h->prev_acquired_focus |= focus_mask;
637         }
638
639         return _convert_sound_manager_error_code(__func__, ret);
640 }
641
642 int sound_manager_is_stream_on_device(sound_stream_info_h stream_info, sound_device_h device, bool *is_on)
643 {
644         int ret = MM_ERROR_NONE;
645         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
646
647         LOGI(">> enter");
648
649         SM_NULL_ARG_CHECK(stream_h);
650         SM_NULL_ARG_CHECK(device);
651         SM_NULL_ARG_CHECK(is_on);
652
653         ret = mm_sound_is_stream_on_device(stream_h->index, device, is_on);
654
655         return _convert_sound_manager_error_code(__func__, ret);
656 }
657
658 int sound_manager_get_current_media_playback_device_type(sound_device_type_e *device_type)
659 {
660         int ret = MM_ERROR_NONE;
661
662         LOGI(">> enter");
663
664         SM_NULL_ARG_CHECK(device_type);
665
666         ret = _get_current_media_routing_path("out", device_type);
667
668         return _convert_sound_manager_error_code(__func__, ret);
669 }
670
671 int sound_manager_get_current_playback_focus(sound_stream_focus_change_reason_e *acquired_by, int *flags, char **extra_info)
672 {
673         int ret = MM_ERROR_NONE;
674         char *stream_type_str = NULL;
675         char *extra_info_str = NULL;
676         int option = 0;
677         bool is_focus_cb_thread = false;
678
679         LOGI(">> enter");
680
681         SM_NULL_ARG_CHECK(acquired_by);
682         SM_NULL_ARG_CHECK(flags);
683
684         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
685                 return _convert_sound_manager_error_code(__func__, ret);
686
687         if (is_focus_cb_thread) {
688                 LOGE("this API should not be called in focus callback");
689                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
690         }
691
692         ret = mm_sound_get_stream_type_of_acquired_focus((int)SOUND_STREAM_FOCUS_FOR_PLAYBACK, &stream_type_str, &option, &extra_info_str);
693         if (ret == MM_ERROR_NONE) {
694                 LOGI("current acquired PLAYBACK focus : stream_type[%s]", stream_type_str);
695                 ret = _convert_stream_type_to_change_reason(stream_type_str, acquired_by);
696                 if (ret == MM_ERROR_NONE) {
697                         LOGI("                                : reason[%d], flags[0x%x], extra_info[%s]", *acquired_by, option, extra_info_str);
698                         *flags = option;
699                         if (extra_info)
700                                 *extra_info = extra_info_str;
701                         else
702                                 SM_SAFE_FREE(extra_info_str);
703                 }
704                 SM_SAFE_FREE(stream_type_str);
705         }
706
707         return _convert_sound_manager_error_code(__func__, ret);
708 }
709
710 int sound_manager_get_current_recording_focus(sound_stream_focus_change_reason_e *acquired_by, int *flags, char **extra_info)
711 {
712         int ret = MM_ERROR_NONE;
713         char *stream_type_str = NULL;
714         char *extra_info_str = NULL;
715         int option = 0;
716         bool is_focus_cb_thread = false;
717
718         LOGI(">> enter");
719
720         SM_NULL_ARG_CHECK(acquired_by);
721         SM_NULL_ARG_CHECK(flags);
722
723         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
724                 return _convert_sound_manager_error_code(__func__, ret);
725
726         if (is_focus_cb_thread) {
727                 LOGE("this API should not be called in focus callback");
728                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
729         }
730
731         ret = mm_sound_get_stream_type_of_acquired_focus((int)SOUND_STREAM_FOCUS_FOR_RECORDING, &stream_type_str, &option, &extra_info_str);
732         if (ret == MM_ERROR_NONE) {
733                 LOGI("current acquired RECORDING focus : stream_type[%s]", stream_type_str);
734                 ret = _convert_stream_type_to_change_reason(stream_type_str, acquired_by);
735                 if (ret == MM_ERROR_NONE) {
736                         LOGI("                                 : reason[%d], flags[0x%x], extra_info[%s]", *acquired_by, option, extra_info_str);
737                         *flags = option;
738                         if (extra_info)
739                                 *extra_info = extra_info_str;
740                         else
741                                 SM_SAFE_FREE(extra_info_str);
742                 }
743                 SM_SAFE_FREE(stream_type_str);
744         }
745
746         return _convert_sound_manager_error_code(__func__, ret);
747 }
748
749 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)
750 {
751         int ret = MM_ERROR_NONE;
752         int i = 0;
753
754         LOGI(">> enter");
755
756         SM_NULL_ARG_CHECK(callback);
757         SM_NULL_ARG_CHECK(id);
758         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, SOUND_MANAGER_ERROR_INTERNAL);
759
760         for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++)
761                 if (focus_watch_info_arr[i].id == 0)
762                         break;
763         if (i == SOUND_STREAM_INFO_ARR_MAX) {
764                 LOGE("focus watch info array is full");
765                 ret = MM_ERROR_SOUND_INTERNAL;
766                 goto LEAVE;
767         }
768
769         ret = mm_sound_set_focus_watch_callback((mm_sound_focus_type_e)focus_mask, _focus_watch_callback, &focus_watch_info_arr[i], id);
770         if (ret == MM_ERROR_NONE) {
771                 SM_REF_FOR_STREAM_INFO(g_stream_info_count, ret);
772                 focus_watch_info_arr[i].id = *id;
773                 focus_watch_info_arr[i].user_data = user_data;
774                 focus_watch_info_arr[i].user_cb = callback;
775         }
776
777 LEAVE:
778         SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
779
780         LOGD("cnt(%d), id(%d)", g_stream_info_count, *id);
781
782         return _convert_sound_manager_error_code(__func__, ret);
783 }
784
785 int sound_manager_remove_focus_state_watch_cb(int id)
786 {
787         int ret = MM_ERROR_NONE;
788         int i = 0;
789
790         LOGI(">> enter");
791
792         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, SOUND_MANAGER_ERROR_INTERNAL);
793
794         for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++)
795                 if (focus_watch_info_arr[i].id == id)
796                         break;
797         if (i == SOUND_STREAM_INFO_ARR_MAX) {
798                 LOGE("cound not find item in focus watch info array for this id(%d)", id);
799                 ret = MM_ERROR_INVALID_ARGUMENT;
800                 goto LEAVE;
801         }
802
803         ret = mm_sound_unset_focus_watch_callback(id);
804         if (ret == MM_ERROR_NONE) {
805                 SM_UNREF_FOR_STREAM_INFO(g_stream_info_count);
806                 focus_watch_info_arr[i].id = 0;
807                 focus_watch_info_arr[i].user_data = NULL;
808                 focus_watch_info_arr[i].user_cb = NULL;
809         }
810
811 LEAVE:
812         SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
813
814         LOGD("cnt(%d)", g_stream_info_count);
815
816         return _convert_sound_manager_error_code(__func__, ret);
817 }
818
819 int sound_manager_set_session_type(sound_session_type_e type)
820 {
821         int ret = MM_ERROR_NONE;
822         int cur_session = -1;
823         int new_session = MM_SESSION_TYPE_MEDIA;
824         bool mic_enable = false;
825
826         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
827         LOGI(">> enter : type=%d", type);
828
829         if (type < SOUND_SESSION_TYPE_MEDIA || type >  SOUND_SESSION_TYPE_VOIP)
830                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
831
832         /* If session type is VOIP but MIC is not enabled, return false */
833         if (type == SOUND_SESSION_TYPE_VOIP) {
834                 ret = system_info_get_platform_bool(FEATURE_MICROPHONE, &mic_enable);
835                 LOGI("system_info_platform [%s]=[%d], ret[%d]", FEATURE_MICROPHONE, mic_enable, ret);
836                 if (ret != SYSTEM_INFO_ERROR_NONE || !mic_enable)
837                         return _convert_sound_manager_error_code(__func__, MM_ERROR_NOT_SUPPORT_API);
838         }
839
840         /* it is not supported both session and stream feature at the same time */
841         if (g_stream_info_count) {
842                 LOGE("Could not set this type(%d) because of being used stream feature", type);
843                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
844         }
845
846         switch (type) {
847         case SOUND_SESSION_TYPE_MEDIA:
848                 new_session = MM_SESSION_TYPE_MEDIA;
849                 break;
850         case SOUND_SESSION_TYPE_ALARM:
851                 new_session = MM_SESSION_TYPE_ALARM;
852                 break;
853         case SOUND_SESSION_TYPE_NOTIFICATION:
854                 new_session = MM_SESSION_TYPE_NOTIFY;
855                 break;
856         case SOUND_SESSION_TYPE_EMERGENCY:
857                 new_session = MM_SESSION_TYPE_EMERGENCY;
858                 break;
859         case SOUND_SESSION_TYPE_VOIP:
860                 new_session = MM_SESSION_TYPE_VOIP;
861                 break;
862         }
863
864         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_session_mutex, SOUND_MANAGER_ERROR_INTERNAL);
865
866         /* valid session check */
867         ret = mm_session_get_current_type(&cur_session);
868         if (ret == MM_ERROR_NONE) {
869                 if (cur_session == MM_SESSION_TYPE_MEDIA_RECORD) {
870                         if (type > SOUND_SESSION_TYPE_MEDIA) {
871                                 LOGE("Could not set this type(%d) during camera/recorder/audio-io(in)/radio", type);
872                                 ret = MM_ERROR_POLICY_INTERNAL;
873                                 goto LEAVE;
874                         }
875                 }
876         }
877
878         if (g_session_interrupt_cb_table.is_registered) {
879                 if (new_session == cur_session ||
880                         ((new_session == SOUND_SESSION_TYPE_MEDIA) && (cur_session == MM_SESSION_TYPE_MEDIA_RECORD))) {
881                         LOGI("already set type=%d, ret=0x%x", type, ret);
882                         goto LEAVE;
883                 }
884
885                 ret = mm_session_finish();
886                 if (ret != MM_ERROR_NONE)
887                         goto LEAVE;
888
889                 g_session_interrupt_cb_table.is_registered = 0;
890                 if (cur_session == MM_SESSION_TYPE_VOIP) {
891                         /* De-initialize regarding VoIP session */
892                         g_cached_session_mode = -1;
893                         g_cached_voip_device_id = -1;
894                         g_cached_voip_device_id2 = -1;
895                         if (g_voip_vstream_h) {
896                                 _stop_progress_virtual_stream(g_voip_vstream_h);
897                                 g_voip_vstream_h = NULL;
898                         }
899                         if (g_voip_ringtone_vstream_h) {
900                                 _stop_progress_virtual_stream(g_voip_ringtone_vstream_h);
901                                 g_voip_ringtone_vstream_h = NULL;
902                         }
903                         if (g_voip_ringtone_stream_info) {
904                                 if ((ret = mm_sound_release_focus(g_voip_ringtone_stream_info->index, g_voip_ringtone_stream_info->acquired_focus, EXT_INFO_VOIP_SESSION)))
905                                         LOGE("failed to release focus for ringtone-voip stream info, ret(0x%x)", ret);
906                         } else if (g_voip_stream_info) {
907                                 if ((ret = mm_sound_release_focus(g_voip_stream_info->index, g_voip_stream_info->acquired_focus, EXT_INFO_VOIP_SESSION)))
908                                         LOGE("failed to release focus for voip stream info, ret(0x%x)", ret);
909                         }
910                         if (g_voip_stream_info) {
911                                 ret = _destroy_pa_connection_and_unregister_focus(g_voip_stream_info);
912                                 SM_SAFE_FREE(g_voip_stream_info);
913                                 if (ret != MM_ERROR_NONE)
914                                         goto LEAVE;
915                         }
916                         if (g_voip_ringtone_stream_info) {
917                                 ret = _destroy_pa_connection_and_unregister_focus(g_voip_ringtone_stream_info);
918                                 SM_SAFE_FREE(g_voip_ringtone_stream_info);
919                                 if (ret != MM_ERROR_NONE)
920                                         goto LEAVE;
921                         }
922                 }
923         }
924         ret = mm_session_init(new_session);
925         if (ret == MM_ERROR_NONE)
926                 g_session_interrupt_cb_table.is_registered = 1;
927
928         LOGI("type=%d", type);
929 LEAVE:
930         SM_LEAVE_CRITICAL_SECTION(&g_session_mutex);
931
932         return _convert_sound_manager_error_code(__func__, ret);
933 }
934
935 int sound_manager_get_session_type(sound_session_type_e *type)
936 {
937         int ret = MM_ERROR_NONE;
938         int cur_session;
939
940         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release.", __func__);
941         if (type == NULL)
942                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
943
944         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_session_mutex, SOUND_MANAGER_ERROR_INVALID_PARAMETER);
945
946         ret = mm_session_get_current_type(&cur_session);
947         if (ret != MM_ERROR_NONE) {
948                 LOGW("session hasn't been set, setting default session");
949                 cur_session = SOUND_SESSION_TYPE_DEFAULT;
950                 ret = mm_session_init(cur_session);
951                 if (ret == MM_ERROR_NONE)
952                         g_session_interrupt_cb_table.is_registered = 1;
953         }
954         if ((cur_session > MM_SESSION_TYPE_EMERGENCY) &&
955                         (cur_session != MM_SESSION_TYPE_VOIP)) {
956                 if (g_cached_session != -1)
957                         cur_session = g_cached_session;
958                 else /* will be never reached here. just prevent code */
959                         cur_session = SOUND_SESSION_TYPE_DEFAULT;
960         }
961
962         switch (cur_session) {
963         case MM_SESSION_TYPE_MEDIA:
964         case MM_SESSION_TYPE_MEDIA_RECORD:
965                 *type = SOUND_SESSION_TYPE_MEDIA;
966                 break;
967         case MM_SESSION_TYPE_ALARM:
968                 *type = SOUND_SESSION_TYPE_ALARM;
969                 break;
970         case MM_SESSION_TYPE_NOTIFY:
971                 *type = SOUND_SESSION_TYPE_NOTIFICATION;
972                 break;
973         case MM_SESSION_TYPE_EMERGENCY:
974                 *type = SOUND_SESSION_TYPE_EMERGENCY;
975                 break;
976         case MM_SESSION_TYPE_VOIP:
977                 *type = SOUND_SESSION_TYPE_VOIP;
978                 break;
979         default:
980                 *type = cur_session;
981                 break;
982         }
983
984         LOGI("type=%d", *type);
985
986         SM_LEAVE_CRITICAL_SECTION(&g_session_mutex);
987
988         return SOUND_MANAGER_ERROR_NONE;
989 }
990
991 int sound_manager_set_media_session_option(sound_session_option_for_starting_e s_option, sound_session_option_for_during_play_e d_option)
992 {
993         int ret = MM_ERROR_NONE;
994         int session = 0;
995         int session_option = 0;
996         int updated = 0;
997
998         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
999         LOGI(">> enter : option for starting=%d, for during play=%d", s_option, d_option);
1000
1001         if (s_option < 0 || s_option >  SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START)
1002                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
1003         if (d_option < 0 || d_option >  SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY)
1004                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
1005
1006         ret = mm_session_get_current_information(&session, &session_option);
1007         if (ret != 0 || !g_session_interrupt_cb_table.is_registered) {
1008                 LOGW("session hasn't been set, setting default session");
1009                 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
1010                 if (ret == 0)
1011                         g_session_interrupt_cb_table.is_registered = 1;
1012
1013         } else if (ret == 0 && session > MM_SESSION_TYPE_MEDIA) {
1014                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
1015                         if (!g_session_interrupt_cb_table.is_registered) {
1016                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
1017                                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
1018                         }
1019                 } else {
1020                         return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
1021                 }
1022         }
1023
1024         switch (s_option) {
1025         case SOUND_SESSION_OPTION_MIX_WITH_OTHERS_WHEN_START:
1026                 if (session_option & MM_SESSION_OPTION_PAUSE_OTHERS) {
1027                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_PAUSE_OTHERS);
1028                         if (ret)
1029                                 return _convert_sound_manager_error_code(__func__, ret);
1030
1031                         updated = 1;
1032                 }
1033                 break;
1034         case SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START:
1035                 if (!(session_option & MM_SESSION_OPTION_PAUSE_OTHERS)) {
1036                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_PAUSE_OTHERS);
1037                         if (ret)
1038                                 return _convert_sound_manager_error_code(__func__, ret);
1039
1040                         updated = 1;
1041                 }
1042                 break;
1043         }
1044
1045         switch (d_option) {
1046         case SOUND_SESSION_OPTION_INTERRUPTIBLE_DURING_PLAY:
1047                 if (session_option & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
1048                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_UNINTERRUPTIBLE);
1049                         if (ret)
1050                                 return _convert_sound_manager_error_code(__func__, ret);
1051
1052                         updated = 1;
1053                 }
1054                 break;
1055         case SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY:
1056                 if (!(session_option & MM_SESSION_OPTION_UNINTERRUPTIBLE)) {
1057                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_UNINTERRUPTIBLE);
1058                         if (ret)
1059                                 return _convert_sound_manager_error_code(__func__, ret);
1060
1061                         updated = 1;
1062                 }
1063                 break;
1064         }
1065
1066         if (updated)
1067                 LOGI("updated");
1068         else
1069                 LOGI("already set same option(%x), skip it", session_option);
1070
1071         return _convert_sound_manager_error_code(__func__, ret);
1072 }
1073
1074 int sound_manager_get_media_session_option(sound_session_option_for_starting_e *s_option, sound_session_option_for_during_play_e *d_option)
1075 {
1076         int ret = MM_ERROR_NONE;
1077         int session = 0;
1078         int session_options = 0;
1079
1080         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
1081         LOGI(">> enter");
1082
1083         if (s_option == NULL || d_option == NULL)
1084                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
1085
1086         ret = mm_session_get_current_information(&session, &session_options);
1087         if (ret != 0) {
1088                 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
1089                 if (ret == 0)
1090                         g_session_interrupt_cb_table.is_registered = 1;
1091
1092         } else if (session > SOUND_SESSION_TYPE_MEDIA) {
1093                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
1094                         if (!g_session_interrupt_cb_table.is_registered) {
1095                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
1096                                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
1097                         }
1098                 } else
1099                         return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
1100         }
1101         /* get option */
1102         if (session_options & MM_SESSION_OPTION_PAUSE_OTHERS)
1103                 *s_option = SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START;
1104         else
1105                 *s_option = SOUND_SESSION_OPTION_MIX_WITH_OTHERS_WHEN_START;
1106
1107         if (session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE)
1108                 *d_option = SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY;
1109         else
1110                 *d_option = SOUND_SESSION_OPTION_INTERRUPTIBLE_DURING_PLAY;
1111
1112         LOGI(" option for starting=%d, for during play=%d", *s_option, *d_option);
1113
1114         return SOUND_MANAGER_ERROR_NONE;
1115 }
1116
1117 int sound_manager_set_media_session_resumption_option(sound_session_option_for_resumption_e option)
1118 {
1119         int ret = MM_ERROR_NONE;
1120         int session = 0;
1121         int session_option = 0;
1122         int updated = 0;
1123
1124         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
1125         LOGI(">> enter : option for resumption=%d (0:by system, 1:by system or media paused)", option);
1126
1127         if (option < SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM || option > SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED)
1128                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
1129
1130         ret = mm_session_get_current_information(&session, &session_option);
1131         if (ret != 0 || !g_session_interrupt_cb_table.is_registered) {
1132                 LOGW("session hasn't been set, setting default session");
1133                 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
1134                 if (ret == 0)
1135                         g_session_interrupt_cb_table.is_registered = 1;
1136
1137         } else if (ret == 0 && session > MM_SESSION_TYPE_MEDIA) {
1138                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
1139                         if (!g_session_interrupt_cb_table.is_registered) {
1140                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
1141                                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
1142                         }
1143                 } else
1144                         return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
1145
1146         }
1147
1148         switch (option) {
1149         case SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM:
1150                 if (session_option & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED) {
1151                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED);
1152                         if (ret)
1153                                 return _convert_sound_manager_error_code(__func__, ret);
1154
1155                         updated = 1;
1156                 }
1157                 break;
1158         case SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED:
1159                 if (!(session_option & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED)) {
1160                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED);
1161                         if (ret)
1162                                 return _convert_sound_manager_error_code(__func__, ret);
1163
1164                         updated = 1;
1165                 }
1166                 break;
1167         }
1168
1169         if (updated)
1170                 LOGI("updated");
1171         else
1172                 LOGI("already set same option(0x%x), skip it", session_option);
1173
1174         return _convert_sound_manager_error_code(__func__, ret);
1175 }
1176
1177 int sound_manager_get_media_session_resumption_option(sound_session_option_for_resumption_e *option)
1178 {
1179         int ret = MM_ERROR_NONE;
1180         int session = 0;
1181         int session_options = 0;
1182
1183         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
1184         LOGI(">> enter");
1185
1186         if (option == NULL)
1187                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
1188
1189         ret = mm_session_get_current_information(&session, &session_options);
1190         if (ret != 0) {
1191                 LOGW("session hasn't been set, setting default session");
1192                 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
1193                 if (ret == 0)
1194                         g_session_interrupt_cb_table.is_registered = 1;
1195
1196         } else if (session > SOUND_SESSION_TYPE_MEDIA) {
1197                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
1198                         if (!g_session_interrupt_cb_table.is_registered) {
1199                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
1200                                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
1201                         }
1202                 } else
1203                         return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
1204         }
1205         /* get option */
1206         if (session_options & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED)
1207                 *option = SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED;
1208         else
1209                 *option = SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM;
1210
1211         LOGI("option for resumption=%d (0:by system, 1:by system or media paused)", *option);
1212
1213         return SOUND_MANAGER_ERROR_NONE;
1214 }
1215
1216 int sound_manager_set_voip_session_mode(sound_session_voip_mode_e mode)
1217 {
1218         int ret = MM_ERROR_NONE;
1219         int session = 0;
1220         int session_options = 0;
1221
1222         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
1223         LOGI(">> enter : mode=%d", mode);
1224
1225         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_session_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1226
1227         ret = mm_session_get_current_information(&session, &session_options);
1228         if (ret != MM_ERROR_NONE)
1229                 goto LEAVE;
1230
1231         if (session != MM_SESSION_TYPE_VOIP) {
1232                 ret = MM_ERROR_POLICY_INTERNAL;
1233                 goto LEAVE;
1234         }
1235
1236         if (mode < SOUND_SESSION_VOIP_MODE_RINGTONE || mode > SOUND_SESSION_VOIP_MODE_VOICE_WITH_BLUETOOTH) {
1237                 ret = MM_ERROR_INVALID_ARGUMENT;
1238                 goto LEAVE;
1239         }
1240
1241         ret = _set_session_mode((_session_mode_e)mode);
1242
1243         LOGI("session=%d, mode=%d(0:RINGTONE 1:MIC_RCV 2:MIC_SPK 3:EAR 4:BT)", session, mode);
1244
1245 LEAVE:
1246         SM_LEAVE_CRITICAL_SECTION(&g_session_mutex);
1247
1248         return _convert_sound_manager_error_code(__func__, ret);
1249 }
1250
1251 int sound_manager_get_voip_session_mode(sound_session_voip_mode_e *mode)
1252 {
1253         int ret = MM_ERROR_NONE;
1254         int session = 0;
1255         int session_options = 0;
1256
1257         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
1258
1259         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_session_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1260
1261         if (mode == NULL) {
1262                 LOGE("mode is null");
1263                 ret = MM_ERROR_INVALID_ARGUMENT;
1264                 goto LEAVE;
1265         }
1266
1267         ret = mm_session_get_current_information(&session, &session_options);
1268         if (ret != MM_ERROR_NONE) {
1269                 LOGI("session = %d, option = %d", session, session_options);
1270                 goto LEAVE;
1271         }
1272
1273         if (session != MM_SESSION_TYPE_VOIP || g_cached_session_mode == -1) {
1274                 ret = MM_ERROR_POLICY_INTERNAL;
1275                 goto LEAVE;
1276         }
1277
1278         *mode = (sound_session_voip_mode_e)g_cached_session_mode;
1279
1280         LOGI("session=%d, mode=%d", session, *mode);
1281
1282 LEAVE:
1283         SM_LEAVE_CRITICAL_SECTION(&g_session_mutex);
1284
1285         return _convert_sound_manager_error_code(__func__, ret);
1286 }
1287
1288 int sound_manager_set_session_interrupted_cb(sound_session_interrupted_cb callback, void *user_data)
1289 {
1290         int ret = MM_ERROR_NONE;
1291         unsigned int subs_id = 0;
1292
1293         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
1294         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_interrupt_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1295
1296         if (callback == NULL) {
1297                 ret = MM_ERROR_INVALID_ARGUMENT;
1298                 goto LEAVE;
1299         }
1300
1301         /* it is not supported both session and stream feature at the same time */
1302         if (g_stream_info_count) {
1303                 ret =  MM_ERROR_POLICY_INTERNAL;
1304                 goto LEAVE;
1305         }
1306
1307         if (g_session_interrupt_cb_table.user_cb == NULL) {
1308                 if ((ret = mm_sound_add_device_connected_callback(SOUND_DEVICE_ALL_MASK, (mm_sound_device_connected_cb)_device_connected_cb, NULL, &subs_id))) {
1309                         ret = MM_ERROR_INVALID_ARGUMENT;
1310                         goto LEAVE;
1311                 }
1312                 if ((ret = mm_sound_focus_set_session_interrupt_callback((mm_sound_focus_session_interrupt_cb)_focus_session_interrupt_cb, NULL))) {
1313                         if (mm_sound_remove_device_connected_callback(subs_id) != MM_ERROR_NONE)
1314                                 LOGW("mm_sound_remove_device_connected_callback failed");
1315                         ret = MM_ERROR_INVALID_ARGUMENT;
1316                         goto LEAVE;
1317                 }
1318                 g_session_interrupt_cb_table.subs_id = subs_id;
1319         }
1320         g_session_interrupt_cb_table.user_cb = (sound_session_interrupted_cb)callback;
1321         g_session_interrupt_cb_table.user_data = user_data;
1322
1323 LEAVE:
1324         SM_LEAVE_CRITICAL_SECTION(&g_interrupt_cb_mutex);
1325
1326         return _convert_sound_manager_error_code(__func__, ret);
1327 }
1328
1329 int sound_manager_unset_session_interrupted_cb(void)
1330 {
1331         int ret = MM_ERROR_NONE;
1332
1333         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release.", __func__);
1334         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_interrupt_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1335
1336         if (!g_session_interrupt_cb_table.user_cb) {
1337                 ret = MM_ERROR_SOUND_INTERNAL;
1338                 goto LEAVE;
1339         }
1340
1341         if ((ret = mm_sound_focus_unset_session_interrupt_callback())) {
1342                 if (mm_sound_remove_device_connected_callback(g_session_interrupt_cb_table.subs_id) != MM_ERROR_NONE)
1343                         LOGW("mm_sound_remove_device_connected_callback failed");
1344                 ret = MM_ERROR_SOUND_INTERNAL;
1345                 goto LEAVE;
1346         }
1347
1348         if ((ret = mm_sound_remove_device_connected_callback(g_session_interrupt_cb_table.subs_id))) {
1349                 ret = MM_ERROR_SOUND_INTERNAL;
1350                 goto LEAVE;
1351         }
1352
1353         g_session_interrupt_cb_table.subs_id = 0;
1354         g_session_interrupt_cb_table.user_cb = NULL;
1355         g_session_interrupt_cb_table.user_data = NULL;
1356
1357 LEAVE:
1358         SM_LEAVE_CRITICAL_SECTION(&g_interrupt_cb_mutex);
1359
1360         return _convert_sound_manager_error_code(__func__, ret);
1361 }
1362
1363 int sound_manager_get_current_device_list(sound_device_mask_e device_mask, sound_device_list_h *device_list)
1364 {
1365         int ret = MM_ERROR_NONE;
1366
1367         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_get_device_list() instead.", __func__);
1368         ret = mm_sound_get_current_device_list(device_mask, device_list);
1369
1370         return _convert_sound_manager_error_code(__func__, ret);
1371 }
1372
1373 int sound_manager_get_device_list(int device_mask, sound_device_list_h *device_list)
1374 {
1375         int ret = MM_ERROR_NONE;
1376
1377         ret = mm_sound_get_device_list(device_mask, device_list);
1378
1379         return _convert_sound_manager_error_code(__func__, ret);
1380 }
1381
1382 int sound_manager_free_device_list(sound_device_list_h device_list)
1383 {
1384         int ret = MM_ERROR_NONE;
1385
1386         ret = mm_sound_free_device_list(device_list);
1387
1388         return _convert_sound_manager_error_code(__func__, ret);
1389 }
1390
1391 int sound_manager_get_next_device(sound_device_list_h device_list, sound_device_h *device)
1392 {
1393         int ret = MM_ERROR_NONE;
1394
1395         ret = mm_sound_get_next_device(device_list, device);
1396
1397         return _convert_sound_manager_error_code(__func__, ret);
1398 }
1399
1400 int sound_manager_get_prev_device(sound_device_list_h device_list, sound_device_h *device)
1401 {
1402         int ret = MM_ERROR_NONE;
1403
1404         ret = mm_sound_get_prev_device(device_list, device);
1405
1406         return _convert_sound_manager_error_code(__func__, ret);
1407 }
1408
1409 int sound_manager_get_device_type(sound_device_h device, sound_device_type_e *type)
1410 {
1411         int ret = MM_ERROR_NONE;
1412         mm_sound_device_type_e mm_sound_device_type;
1413
1414         ret = mm_sound_get_device_type(device, &mm_sound_device_type);
1415         if (ret == MM_ERROR_NONE)
1416                 ret = _convert_device_type(mm_sound_device_type, type);
1417
1418         return _convert_sound_manager_error_code(__func__, ret);
1419 }
1420
1421 int sound_manager_get_device_io_direction(sound_device_h device, sound_device_io_direction_e *io_direction)
1422 {
1423         int ret = MM_ERROR_NONE;
1424         mm_sound_device_io_direction_e mm_sound_io_direction;
1425
1426         ret = mm_sound_get_device_io_direction(device, &mm_sound_io_direction);
1427         if (ret == MM_ERROR_NONE)
1428                 ret = _convert_device_io_direction(mm_sound_io_direction, io_direction);
1429
1430         return _convert_sound_manager_error_code(__func__, ret);
1431 }
1432
1433 int sound_manager_get_device_id(sound_device_h device, int *id)
1434 {
1435         int ret = MM_ERROR_NONE;
1436
1437         ret = mm_sound_get_device_id(device, id);
1438
1439         return _convert_sound_manager_error_code(__func__, ret);
1440 }
1441
1442 int sound_manager_get_device_name(sound_device_h device, char **name)
1443 {
1444         int ret = MM_ERROR_NONE;
1445
1446         ret = mm_sound_get_device_name(device, name);
1447
1448         return _convert_sound_manager_error_code(__func__, ret);
1449 }
1450
1451 int sound_manager_get_device_state(sound_device_h device, sound_device_state_e *state)
1452 {
1453         int ret = MM_ERROR_NONE;
1454
1455         ret = mm_sound_get_device_state(device, (mm_sound_device_state_e*)state);
1456
1457         return _convert_sound_manager_error_code(__func__, ret);
1458 }
1459
1460 int sound_manager_set_device_connected_cb(sound_device_mask_e device_mask, sound_device_connected_cb callback, void *user_data)
1461 {
1462         int ret = MM_ERROR_NONE;
1463         unsigned int subs_id = 0;
1464
1465         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. "
1466                 "Use sound_manager_add_device_connection_changed_cb() instead.", __func__);
1467
1468         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_conn_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1469
1470         ret = mm_sound_add_device_connected_callback((mm_sound_device_flags_e)device_mask, (mm_sound_device_connected_cb)callback, user_data, &subs_id);
1471         if (ret == MM_ERROR_NONE) {
1472                 g_device_connected_cb_table.subs_id = subs_id;
1473                 g_device_connected_cb_table.user_cb = (sound_device_connected_cb)callback;
1474                 g_device_connected_cb_table.user_data = user_data;
1475         }
1476
1477         SM_LEAVE_CRITICAL_SECTION(&g_device_conn_cb_mutex);
1478
1479         return _convert_sound_manager_error_code(__func__, ret);
1480 }
1481
1482 int sound_manager_unset_device_connected_cb(void)
1483 {
1484         int ret = MM_ERROR_NONE;
1485
1486         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. "
1487                 "Use sound_manager_remove_device_connection_changed_cb() instead.", __func__);
1488
1489         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_conn_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1490
1491         if (g_device_connected_cb_table.subs_id == 0) {
1492                 ret = MM_ERROR_SOUND_INTERNAL;
1493                 goto LEAVE;
1494         }
1495
1496         ret = mm_sound_remove_device_connected_callback(g_device_connected_cb_table.subs_id);
1497         if (ret == MM_ERROR_NONE) {
1498                 g_device_connected_cb_table.subs_id = 0;
1499                 g_device_connected_cb_table.user_cb = NULL;
1500                 g_device_connected_cb_table.user_data = NULL;
1501         }
1502
1503 LEAVE:
1504         SM_LEAVE_CRITICAL_SECTION(&g_device_conn_cb_mutex);
1505
1506         return _convert_sound_manager_error_code(__func__, ret);
1507 }
1508
1509 int sound_manager_add_device_connection_changed_cb(int device_mask, sound_device_connected_cb callback, void *user_data, int *id)
1510 {
1511         int ret = MM_ERROR_NONE;
1512
1513         if (!callback || !id)
1514                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
1515
1516         ret = mm_sound_add_device_connected_callback((mm_sound_device_flags_e)device_mask, (mm_sound_device_connected_cb)callback, user_data, (unsigned int*)id);
1517
1518         return _convert_sound_manager_error_code(__func__, ret);
1519 }
1520
1521 int sound_manager_remove_device_connection_changed_cb(int id)
1522 {
1523         int ret = MM_ERROR_NONE;
1524
1525         if (id < 0)
1526                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
1527
1528         ret = mm_sound_remove_device_connected_callback((unsigned int)id);
1529
1530         return _convert_sound_manager_error_code(__func__, ret);
1531 }
1532
1533 int sound_manager_set_device_information_changed_cb(sound_device_mask_e device_mask, sound_device_information_changed_cb callback, void *user_data)
1534 {
1535         int ret = MM_ERROR_NONE;
1536         unsigned int subs_id = 0;
1537
1538         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. "
1539                 "Use sound_manager_add_device_state_changed_cb() instead.", __func__);
1540         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_info_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1541
1542         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);
1543         if (ret == MM_ERROR_NONE) {
1544                 g_device_info_changed_cb_table.subs_id = subs_id;
1545                 g_device_info_changed_cb_table.user_cb = (sound_device_information_changed_cb)callback;
1546                 g_device_info_changed_cb_table.user_data = user_data;
1547         }
1548
1549         SM_LEAVE_CRITICAL_SECTION(&g_device_info_cb_mutex);
1550
1551         return _convert_sound_manager_error_code(__func__, ret);
1552 }
1553
1554 int sound_manager_unset_device_information_changed_cb(void)
1555 {
1556         int ret = MM_ERROR_NONE;
1557
1558         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. "
1559                 "Use sound_manager_remove_device_state_changed_cb() instead.", __func__);
1560         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_info_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1561
1562         if (g_device_info_changed_cb_table.subs_id == 0) {
1563                 ret = MM_ERROR_SOUND_INTERNAL;
1564                 goto LEAVE;
1565         }
1566
1567         ret = mm_sound_remove_device_information_changed_callback(g_device_info_changed_cb_table.subs_id);
1568         if (ret == MM_ERROR_NONE) {
1569                 g_device_info_changed_cb_table.subs_id = 0;
1570                 g_device_info_changed_cb_table.user_cb = NULL;
1571                 g_device_info_changed_cb_table.user_data = NULL;
1572         }
1573
1574 LEAVE:
1575         SM_LEAVE_CRITICAL_SECTION(&g_device_info_cb_mutex);
1576
1577         return _convert_sound_manager_error_code(__func__, ret);
1578 }
1579
1580 int sound_manager_add_device_state_changed_cb(int device_mask, sound_device_state_changed_cb callback, void *user_data, int *id)
1581 {
1582         int ret = MM_ERROR_NONE;
1583
1584         if (!callback || !id)
1585                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
1586
1587         ret = mm_sound_add_device_state_changed_callback(device_mask, (mm_sound_device_state_changed_cb)callback, user_data, (unsigned int*)id);
1588
1589         return _convert_sound_manager_error_code(__func__, ret);
1590 }
1591
1592 int sound_manager_remove_device_state_changed_cb(int id)
1593 {
1594         int ret = MM_ERROR_NONE;
1595
1596         if (id < 0)
1597                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
1598
1599         ret = mm_sound_remove_device_state_changed_callback((unsigned int)id);
1600
1601         return _convert_sound_manager_error_code(__func__, ret);
1602 }
1603
1604 __attribute__ ((destructor))
1605 void __sound_manager_finalize(void)
1606 {
1607         int ret = MM_ERROR_NONE;
1608
1609         if (g_session_interrupt_cb_table.is_registered) {
1610                 LOGI("<ENTER>");
1611                 ret = mm_session_finish();
1612                 if (ret != MM_ERROR_NONE)
1613                         LOGE("[%s] failed to mm_session_finish(), ret(0x%x)", __func__, ret);
1614
1615                 g_session_interrupt_cb_table.is_registered = 0;
1616                 LOGI("<LEAVE>");
1617         }
1618 }
1619
1620 __attribute__ ((constructor))
1621 void __sound_manager_initialize(void)
1622 {
1623
1624 }