e90c7382c7fc08773ce1c566d4276262fc8475ed
[platform/core/api/sound-manager.git] / src / sound_manager.c
1 /*
2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "sound_manager.h"
18 #include "sound_manager_private.h"
19
20 static int ducking_arr_count;
21 static unsigned int ducking_cb_subs_id;
22 static pthread_mutex_t ducking_mutex;
23 static sound_stream_ducking_s *ducking_arr[SOUND_DUCKING_ARR_MAX];
24
25 _focus_watch_info_s focus_watch_info_arr[SOUND_STREAM_INFO_ARR_MAX];
26
27 static void _ducking_state_changed_cb(int pa_index, bool is_ducked, void *user_data)
28 {
29         int i = 0;
30
31         SM_ENTER_CRITICAL_SECTION(&ducking_mutex);
32
33         for (i = 0 ; i < SOUND_DUCKING_ARR_MAX ; i++) {
34                 if (ducking_arr[i] && ducking_arr[i]->pa_info.index == pa_index)
35                         break;
36         }
37
38         if (i < SOUND_DUCKING_ARR_MAX) {
39                 LOGI("ducking state changed [i:%d,ducked:%u]", pa_index, is_ducked);
40
41                 if (ducking_arr[i]->user_cb)
42                         ducking_arr[i]->user_cb((sound_stream_ducking_h)ducking_arr[i], is_ducked, ducking_arr[i]->user_data);
43                 else
44                         LOGW("no user callback for pa_index %d", pa_index);
45         } else {
46                 LOGE("could not found for pa_index %d", pa_index);
47         }
48
49         SM_LEAVE_CRITICAL_SECTION(&ducking_mutex);
50
51         return;
52 }
53
54 int sound_manager_get_max_volume(sound_type_e type, int *max)
55 {
56         const char *volume_type = NULL;
57         unsigned int max_level = 0;
58         int ret = MM_ERROR_NONE;
59
60         SM_NULL_ARG_CHECK(max);
61         if (type >= SOUND_TYPE_NUM)
62                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
63
64         ret = _convert_sound_type(type, &volume_type);
65         if (ret == MM_ERROR_NONE) {
66                 ret = _get_volume_max_level(DIRECTION_OUT_STR, volume_type, &max_level);
67                 if (ret == MM_ERROR_NONE)
68                         *max = (int)max_level -1;       /* actual volume step can be max step - 1 */
69         }
70
71         return _convert_sound_manager_error_code(__func__, ret);
72 }
73
74 int sound_manager_set_volume(sound_type_e type, int volume)
75 {
76         int ret = MM_ERROR_NONE;
77
78         if (type >= SOUND_TYPE_NUM)
79                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
80         if (volume < 0)
81                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
82
83         ret = mm_sound_volume_set_value(type, volume);
84         LOGI("type=%d, volume=%d", type, volume);
85
86         return _convert_sound_manager_error_code(__func__, ret);
87 }
88
89 int sound_manager_get_volume(sound_type_e type, int *volume)
90 {
91         int ret = MM_ERROR_NONE;
92         unsigned int uvolume;
93
94         if (type >= SOUND_TYPE_NUM)
95                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
96         if (volume == NULL)
97                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
98
99         ret = mm_sound_volume_get_value(type, &uvolume);
100         if (ret == MM_ERROR_NONE)
101                 *volume = uvolume;
102
103         LOGI("type=%d, volume=%d", type, *volume);
104
105         return _convert_sound_manager_error_code(__func__, ret);
106 }
107
108 int sound_manager_get_current_sound_type(sound_type_e *type)
109 {
110         int ret = MM_ERROR_NONE;
111         char *volume_type = NULL;
112
113         if (type == NULL)
114                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
115
116         /* get the volume type of the current playing stream */
117         ret = _get_current_volume_type(DIRECTION_OUT_STR, &volume_type);
118         if (ret == MM_ERROR_NONE) {
119                 ret = _convert_sound_type_to_enum((const char*)volume_type, type);
120                 if (ret == MM_ERROR_NONE)
121                         LOGI("type=%d", *type);
122         }
123
124         return _convert_sound_manager_error_code(__func__, ret);
125 }
126
127 int sound_manager_add_volume_changed_cb(sound_manager_volume_changed_cb callback, void *user_data, int *id)
128 {
129         int ret = MM_ERROR_NONE;
130
131         if (!callback || !id)
132                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
133
134         ret = mm_sound_add_volume_changed_callback((mm_sound_volume_changed_cb)callback, user_data, (unsigned int*)id);
135
136         return _convert_sound_manager_error_code(__func__, ret);
137 }
138
139 int sound_manager_remove_volume_changed_cb(int id)
140 {
141         int ret = MM_ERROR_NONE;
142
143         if (id < 0)
144                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
145
146         ret = mm_sound_remove_volume_changed_callback(id);
147
148         return _convert_sound_manager_error_code(__func__, ret);
149 }
150
151 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)
152 {
153         int ret = MM_ERROR_NONE;
154
155         LOGI(">> enter");
156
157         SM_NULL_ARG_CHECK(stream_info);
158
159         sound_stream_info_s *stream_h = malloc(sizeof(sound_stream_info_s));
160         if (!stream_h) {
161                 ret = MM_ERROR_OUT_OF_MEMORY;
162                 goto LEAVE;
163         }
164
165         memset(stream_h, 0, sizeof(sound_stream_info_s));
166         ret = _convert_stream_type(stream_type, &stream_h->stream_type);
167         if (ret == MM_ERROR_NONE) {
168                 ret = _make_pa_connection_and_register_focus(stream_h, callback, user_data);
169                 if (ret == MM_ERROR_NONE) {
170                         *stream_info = (sound_stream_info_h)stream_h;
171                         LOGI("stream_h(%p), pa_index(%u), focus_id(%d), user_cb(%p), ret(0x%x)",
172                                 stream_h, stream_h->pa_info.index, stream_h->focus_id, stream_h->user_cb, ret);
173                 }
174         }
175
176 LEAVE:
177         if (ret)
178                 SM_SAFE_FREE(stream_h);
179
180         return _convert_sound_manager_error_code(__func__, ret);
181 }
182
183 int sound_manager_destroy_stream_information(sound_stream_info_h stream_info)
184 {
185         int ret = MM_ERROR_NONE;
186         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
187
188         LOGI(">> enter");
189
190         SM_INSTANCE_CHECK(stream_h);
191
192         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->vstream_mutex, SOUND_MANAGER_ERROR_INTERNAL);
193         if (stream_h->vstream) {
194                 LOGE("virtual stream is still alive");
195                 SM_LEAVE_CRITICAL_SECTION(&stream_h->vstream_mutex);
196                 return _convert_sound_manager_error_code(__func__, MM_ERROR_SOUND_INVALID_OPERATION);
197         }
198         SM_LEAVE_CRITICAL_SECTION(&stream_h->vstream_mutex);
199
200         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_state_mutex, MM_ERROR_SOUND_INTERNAL);
201         ret = _destroy_pa_connection_and_unregister_focus(stream_h);
202         SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_state_mutex);
203         if (ret == MM_ERROR_NONE)
204                 SM_SAFE_FREE(stream_h);
205
206         return _convert_sound_manager_error_code(__func__, ret);
207 }
208
209 int sound_manager_get_sound_type(sound_stream_info_h stream_info, sound_type_e *sound_type)
210 {
211         int ret = MM_ERROR_NONE;
212         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
213
214         LOGI(">> enter");
215
216         SM_INSTANCE_CHECK(stream_h);
217         SM_NULL_ARG_CHECK(sound_type);
218
219         if (stream_h->stream_conf_info.volume_type == NULL) {
220                 ret = MM_ERROR_SOUND_NO_DATA;
221                 goto LEAVE;
222         }
223
224         ret = _convert_sound_type_to_enum(stream_h->stream_conf_info.volume_type, sound_type);
225         LOGI("sound type(%d)", *sound_type);
226
227 LEAVE:
228         return _convert_sound_manager_error_code(__func__, ret);
229 }
230
231 int sound_manager_add_device_for_stream_routing(sound_stream_info_h stream_info, sound_device_h device)
232 {
233         int ret = MM_ERROR_NONE;
234         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
235
236         LOGI(">> enter");
237
238         ret = _add_device_for_stream_routing(stream_h, device);
239
240         return _convert_sound_manager_error_code(__func__, ret);
241 }
242
243 int sound_manager_remove_device_for_stream_routing(sound_stream_info_h stream_info, sound_device_h device)
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         ret = _remove_device_for_stream_routing(stream_h, device);
251
252         return _convert_sound_manager_error_code(__func__, ret);
253 }
254
255 int sound_manager_remove_all_devices_for_stream_routing(sound_stream_info_h stream_info)
256 {
257         int ret = MM_ERROR_NONE;
258         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
259
260         LOGI(">> enter");
261
262         ret = _remove_all_devices_for_stream_routing(stream_h);
263
264         return _convert_sound_manager_error_code(__func__, ret);
265 }
266
267 int sound_manager_apply_stream_routing(sound_stream_info_h stream_info)
268 {
269         int ret = MM_ERROR_NONE;
270         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
271
272         LOGI(">> enter");
273
274         ret = _apply_stream_routing(stream_h);
275
276         return _convert_sound_manager_error_code(__func__, ret);
277 }
278
279 int sound_manager_set_stream_preferred_device(sound_stream_info_h stream_info, sound_device_io_direction_e io_direction, sound_device_h device)
280 {
281         int ret = MM_ERROR_NONE;
282         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
283
284         SM_NULL_ARG_CHECK(stream_h);
285
286         ret = _set_preferred_device(stream_h, io_direction, device);
287
288         return _convert_sound_manager_error_code(__func__, ret);
289 }
290
291 int sound_manager_get_stream_preferred_device(sound_stream_info_h stream_info, int *in_device_id, int *out_device_id)
292 {
293         int ret = MM_ERROR_NONE;
294         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
295
296         SM_NULL_ARG_CHECK(stream_h);
297         SM_NULL_ARG_CHECK(in_device_id || out_device_id);
298
299         ret = _get_preferred_device(stream_h, in_device_id, out_device_id);
300
301         return _convert_sound_manager_error_code(__func__, ret);
302 }
303
304 int sound_manager_set_focus_reacquisition(sound_stream_info_h stream_info, bool enable)
305 {
306         int ret = MM_ERROR_NONE;
307         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
308
309         LOGI(">> enter");
310
311         SM_INSTANCE_CHECK(stream_h);
312
313         ret = mm_sound_set_focus_reacquisition(stream_h->focus_id, enable);
314
315         LOGI("enable(%d)", enable);
316
317         return _convert_sound_manager_error_code(__func__, ret);
318 }
319
320 int sound_manager_get_focus_reacquisition(sound_stream_info_h stream_info, bool *enabled)
321 {
322         int ret = MM_ERROR_NONE;
323         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
324
325         LOGI(">> enter");
326
327         SM_INSTANCE_CHECK(stream_h);
328         SM_NULL_ARG_CHECK(enabled);
329
330         ret = mm_sound_get_focus_reacquisition(stream_h->focus_id, enabled);
331
332         LOGI("enabled(%d)", *enabled);
333
334         return _convert_sound_manager_error_code(__func__, ret);
335 }
336
337 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)
338 {
339         int ret = MM_ERROR_NONE;
340         bool is_focus_cb_thread = false;
341         bool is_focus_watch_cb_thread = false;
342         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
343
344         LOGI(">> enter");
345
346         SM_INSTANCE_CHECK(stream_h);
347
348         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread, &is_focus_watch_cb_thread)))
349                 return _convert_sound_manager_error_code(__func__, ret);
350
351         if (stream_h->is_focus_unavailable) {
352                 LOGE("acquiring focus is not allowed for this stream type(%s)", stream_h->stream_type);
353                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
354         }
355
356         if (stream_h->user_cb == NULL) {
357                 LOGE("focus state changed callback should be set before acquiring focus");
358                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
359         }
360
361         if (!is_focus_cb_thread) {
362                 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL);
363                 SM_ENTER_CRITICAL_SECTION_WITH_UNLOCK_AND_RETURN(&stream_h->focus_state_mutex, &stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL);
364         } else {
365                 /* If it is inside of the watch cb and if the previous request of this process has not been finished yet,
366                  * the focus state mutex could be still locked. Therefore, it returns error here. */
367                 if (is_focus_watch_cb_thread && stream_h->is_requesting) {
368                         LOGE("It is not allowed in watch cb thread during the previous request has not been finished yet");
369                         return _convert_sound_manager_error_code(__func__, MM_ERROR_SOUND_INVALID_OPERATION);
370                 }
371                 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_state_mutex, MM_ERROR_SOUND_INTERNAL);
372         }
373
374         if (stream_h->acquired_focus & focus_mask) {
375                 LOGE("invalid state: focus_mask[0x%x], acquired_focus[0x%x]", focus_mask, stream_h->acquired_focus);
376                 ret = MM_ERROR_SOUND_INVALID_STATE;
377                 goto LEAVE;
378         }
379
380         if (is_focus_cb_thread && ((stream_h->prev_acquired_focus & ~stream_h->acquired_focus) & focus_mask)) {
381                 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]",
382                         focus_mask, stream_h->acquired_focus, stream_h->prev_acquired_focus);
383                 ret = MM_ERROR_POLICY_INTERNAL;
384                 goto LEAVE;
385         }
386
387         stream_h->is_requesting = true;
388
389         ret = mm_sound_acquire_focus_with_option(stream_h->focus_id, (mm_sound_focus_type_e)focus_mask, sound_behavior, extra_info);
390         if (ret == MM_ERROR_NONE) {
391                 stream_h->acquired_focus |= focus_mask;
392                 stream_h->prev_acquired_focus |= focus_mask;
393                 _update_focus_status(stream_h->pa_info.index, (unsigned int)stream_h->acquired_focus);
394         }
395
396         LOGI("acquired_focus[0x%x], prev[0x%x]", stream_h->acquired_focus, stream_h->prev_acquired_focus);
397
398 LEAVE:
399         stream_h->is_requesting = false;
400         SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_state_mutex);
401         if (!is_focus_cb_thread)
402                 SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_cb_mutex);
403
404         return _convert_sound_manager_error_code(__func__, ret);
405 }
406
407 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)
408 {
409         int ret = MM_ERROR_NONE;
410         bool is_focus_cb_thread = false;
411         bool is_focus_watch_cb_thread = false;
412         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
413
414         LOGI(">> enter");
415
416         SM_INSTANCE_CHECK(stream_h);
417
418         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread, &is_focus_watch_cb_thread)))
419                 return _convert_sound_manager_error_code(__func__, ret);
420
421         if (!is_focus_cb_thread) {
422                 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL);
423                 SM_ENTER_CRITICAL_SECTION_WITH_UNLOCK_AND_RETURN(&stream_h->focus_state_mutex, &stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL);
424         } else {
425                 /* If it is inside of the watch cb and if the previous request of this process has not been finished yet,
426                  * the focus state mutex could be still locked. Therefore, it returns error here. */
427                 if (is_focus_watch_cb_thread && stream_h->is_requesting) {
428                         LOGE("It is not allowed in watch cb thread during the previous request has not been finished yet");
429                         return _convert_sound_manager_error_code(__func__, MM_ERROR_SOUND_INVALID_OPERATION);
430                 }
431                 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_state_mutex, MM_ERROR_SOUND_INTERNAL);
432         }
433
434         if (!(stream_h->acquired_focus & focus_mask)) {
435                 LOGE("invalid state: focus_mask[0x%x], acquired_focus[0x%x]", focus_mask, stream_h->acquired_focus);
436                 ret = MM_ERROR_SOUND_INVALID_STATE;
437                 goto LEAVE;
438         }
439
440         if (is_focus_cb_thread && ((stream_h->prev_acquired_focus & stream_h->acquired_focus) != focus_mask)) {
441                 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]",
442                         focus_mask, stream_h->acquired_focus, stream_h->prev_acquired_focus);
443                 ret = MM_ERROR_SOUND_INVALID_STATE;
444                 goto LEAVE;
445         }
446
447         stream_h->is_requesting = true;
448
449         ret = mm_sound_release_focus_with_option(stream_h->focus_id, (mm_sound_focus_type_e)focus_mask, sound_behavior, extra_info);
450         if (ret == MM_ERROR_NONE) {
451                 stream_h->acquired_focus &= ~focus_mask;
452                 stream_h->prev_acquired_focus &= ~focus_mask;
453                 _update_focus_status(stream_h->pa_info.index, (unsigned int)stream_h->acquired_focus);
454         }
455
456         LOGI("acquired_focus[0x%x], prev[0x%x]", stream_h->acquired_focus, stream_h->prev_acquired_focus);
457
458 LEAVE:
459         stream_h->is_requesting = false;
460         SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_state_mutex);
461         if (!is_focus_cb_thread)
462                 SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_cb_mutex);
463
464         return _convert_sound_manager_error_code(__func__, ret);
465 }
466
467 int sound_manager_acquire_focus_all(sound_stream_info_h stream_info, int sound_behavior, const char *extra_info)
468 {
469         int ret = MM_ERROR_NONE;
470         int focus_mask = SOUND_STREAM_FOCUS_FOR_BOTH;
471         bool is_focus_cb_thread = false;
472         bool is_focus_watch_cb_thread = false;
473         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
474
475         LOGI(">> enter");
476
477         SM_INSTANCE_CHECK(stream_h);
478
479         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread, &is_focus_watch_cb_thread)))
480                 return _convert_sound_manager_error_code(__func__, ret);
481
482         if (stream_h->is_focus_unavailable) {
483                 LOGE("acquiring focus is not allowed for this stream type(%s)", stream_h->stream_type);
484                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
485         }
486
487         if (stream_h->user_cb == NULL) {
488                 LOGE("focus state changed callback should be set before acquiring focus");
489                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
490         }
491
492         if (!is_focus_cb_thread) {
493                 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL);
494                 SM_ENTER_CRITICAL_SECTION_WITH_UNLOCK_AND_RETURN(&stream_h->focus_state_mutex, &stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL);
495         } else {
496                 /* If it is inside of the watch cb and if the previous request of this process has not been finished yet,
497                  * the focus state mutex could be still locked. Therefore, it returns error here. */
498                 if (is_focus_watch_cb_thread && stream_h->is_requesting) {
499                         LOGE("It is not allowed in watch cb thread during the previous request has not been finished yet");
500                         return _convert_sound_manager_error_code(__func__, MM_ERROR_SOUND_INVALID_OPERATION);
501                 }
502                 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_state_mutex, MM_ERROR_SOUND_INTERNAL);
503         }
504
505         if (is_focus_cb_thread && (stream_h->prev_acquired_focus > stream_h->acquired_focus)) {
506                 LOGE("just lost focus in this callback, it is not allowed to acquire all again. acquired_focus[0x%x], prev[0x%x]",
507                         stream_h->acquired_focus, stream_h->prev_acquired_focus);
508                 ret = MM_ERROR_POLICY_INTERNAL;
509                 goto LEAVE;
510         }
511
512         focus_mask = SOUND_STREAM_FOCUS_FOR_BOTH & ~(stream_h->acquired_focus);
513         if (!focus_mask) {
514                 LOGI("PLAYBACK/RECORDING focuses have already been ACQUIRED");
515                 ret = MM_ERROR_NONE;
516                 goto LEAVE;
517         }
518
519         stream_h->is_requesting = true;
520
521         ret = mm_sound_acquire_focus_with_option(stream_h->focus_id, (mm_sound_focus_type_e)focus_mask, sound_behavior, extra_info);
522         if (ret == MM_ERROR_NONE) {
523                 stream_h->acquired_focus |= focus_mask;
524                 stream_h->prev_acquired_focus |= focus_mask;
525                 _update_focus_status(stream_h->pa_info.index, (unsigned int)stream_h->acquired_focus);
526         }
527
528 LEAVE:
529         stream_h->is_requesting = false;
530         SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_state_mutex);
531         if (!is_focus_cb_thread)
532                 SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_cb_mutex);
533
534         return _convert_sound_manager_error_code(__func__, ret);
535 }
536
537 int sound_manager_release_focus_all(sound_stream_info_h stream_info, int sound_behavior, const char *extra_info)
538 {
539         int ret = MM_ERROR_NONE;
540         bool is_focus_cb_thread = false;
541         bool is_focus_watch_cb_thread = false;
542         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
543
544         LOGI(">> enter");
545
546         SM_INSTANCE_CHECK(stream_h);
547
548         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread, &is_focus_watch_cb_thread)))
549                 return _convert_sound_manager_error_code(__func__, ret);
550
551         if (!is_focus_cb_thread) {
552                 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL);
553                 SM_ENTER_CRITICAL_SECTION_WITH_UNLOCK_AND_RETURN(&stream_h->focus_state_mutex, &stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL);
554         } else {
555                 /* If it is inside of the watch cb and if the previous request of this process has not been finished yet,
556                  * the focus state mutex could be still locked. Therefore, it returns error here. */
557                 if (is_focus_watch_cb_thread && stream_h->is_requesting) {
558                         LOGE("It is not allowed in watch cb thread during the previous request has not been finished yet");
559                         return _convert_sound_manager_error_code(__func__, MM_ERROR_SOUND_INVALID_OPERATION);
560                 }
561                 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_state_mutex, MM_ERROR_SOUND_INTERNAL);
562         }
563
564         if (is_focus_cb_thread && (stream_h->prev_acquired_focus < stream_h->acquired_focus)) {
565                 LOGE("just acquired focus in this callback, it is not allowed to release all again. acquired_focus[0x%x], prev[0x%x]",
566                         stream_h->acquired_focus, stream_h->prev_acquired_focus);
567                 ret = MM_ERROR_POLICY_INTERNAL;
568                 goto LEAVE;
569         }
570
571         if (!stream_h->acquired_focus) {
572                 LOGI("PLAYBACK/RECORDING focuses have already been RELEASED");
573                 ret = MM_ERROR_NONE;
574                 goto LEAVE;
575         }
576
577         stream_h->is_requesting = true;
578
579         ret = mm_sound_release_focus_with_option(stream_h->focus_id, (mm_sound_focus_type_e)stream_h->acquired_focus, sound_behavior, extra_info);
580         if (ret == MM_ERROR_NONE) {
581                 stream_h->acquired_focus = 0;
582                 stream_h->prev_acquired_focus = 0;
583                 _update_focus_status(stream_h->pa_info.index, (unsigned int)stream_h->acquired_focus);
584         }
585
586 LEAVE:
587         stream_h->is_requesting = false;
588         SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_state_mutex);
589         if (!is_focus_cb_thread)
590                 SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_cb_mutex);
591
592         return _convert_sound_manager_error_code(__func__, ret);
593 }
594
595 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)
596 {
597         int ret = MM_ERROR_NONE;
598         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
599
600         LOGI(">> enter");
601
602         SM_INSTANCE_CHECK(stream_h);
603         if (!state_for_playback && !state_for_recording)
604                 return SOUND_MANAGER_ERROR_INVALID_PARAMETER;
605
606         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_state_mutex, MM_ERROR_SOUND_INTERNAL);
607
608         if (state_for_playback)
609                 *state_for_playback = ((stream_h->acquired_focus & SOUND_STREAM_FOCUS_FOR_PLAYBACK) ? (SOUND_STREAM_FOCUS_STATE_ACQUIRED) : (SOUND_STREAM_FOCUS_STATE_RELEASED));
610         if (state_for_recording)
611                 *state_for_recording = ((stream_h->acquired_focus & SOUND_STREAM_FOCUS_FOR_RECORDING) ? (SOUND_STREAM_FOCUS_STATE_ACQUIRED) : (SOUND_STREAM_FOCUS_STATE_RELEASED));
612
613         LOGI("acquired_focus(0x%x)", stream_h->acquired_focus);
614
615         SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_state_mutex);
616
617         return _convert_sound_manager_error_code(__func__, ret);
618 }
619
620 int sound_manager_deliver_focus(sound_stream_info_h source, sound_stream_info_h destination, sound_stream_focus_mask_e focus_mask)
621 {
622         int ret = MM_ERROR_NONE;
623         sound_stream_info_s *src_stream_h = (sound_stream_info_s*)source;
624         sound_stream_info_s *dst_stream_h = (sound_stream_info_s*)destination;
625         bool is_focus_cb_thread = false;
626
627         LOGI(">> enter");
628
629         SM_INSTANCE_CHECK(src_stream_h);
630         SM_INSTANCE_CHECK(dst_stream_h);
631
632         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread, NULL)))
633                 return _convert_sound_manager_error_code(__func__, ret);
634
635         if (is_focus_cb_thread) {
636                 LOGE("not allowed calling this function in focus(watch) callback");
637                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
638         }
639
640         if (src_stream_h->focus_id == dst_stream_h->focus_id) {
641                 LOGE("not allowed because both handles have same id(%u)", src_stream_h->focus_id);
642                 return SOUND_MANAGER_ERROR_INVALID_PARAMETER;
643         }
644
645         if (src_stream_h->is_focus_unavailable || dst_stream_h->is_focus_unavailable) {
646                 LOGE("focus is unavailable for source(%d)/destination(%d)",
647                         src_stream_h->is_focus_unavailable, dst_stream_h->is_focus_unavailable);
648                 return SOUND_MANAGER_ERROR_POLICY;
649         }
650
651         if (!(src_stream_h->acquired_focus & focus_mask) || (src_stream_h->acquired_focus < focus_mask)) {
652                 LOGE("could not deliver the request focus(0x%x), current acquired focus(0x%x)",
653                         focus_mask, src_stream_h->acquired_focus);
654                 return SOUND_MANAGER_ERROR_INVALID_STATE;
655         }
656
657         if (dst_stream_h->user_cb == NULL) {
658                 LOGE("focus state changed callback should be set to destination handle");
659                 return SOUND_MANAGER_ERROR_POLICY;
660         }
661
662         ret = mm_sound_deliver_focus(src_stream_h->focus_id, dst_stream_h->focus_id, (mm_sound_focus_type_e)focus_mask);
663         if (ret == MM_ERROR_NONE) {
664                 src_stream_h->acquired_focus &= ~focus_mask;
665                 src_stream_h->prev_acquired_focus &= ~focus_mask;
666                 dst_stream_h->acquired_focus |= focus_mask;
667                 dst_stream_h->prev_acquired_focus |= focus_mask;
668         }
669
670         return _convert_sound_manager_error_code(__func__, ret);
671 }
672
673 int sound_manager_is_stream_on_device(sound_stream_info_h stream_info, sound_device_h device, bool *is_on)
674 {
675         int ret = MM_ERROR_NONE;
676         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
677
678         LOGI(">> enter");
679
680         SM_NULL_ARG_CHECK(stream_h);
681         SM_NULL_ARG_CHECK(device);
682         SM_NULL_ARG_CHECK(is_on);
683
684         ret = mm_sound_is_stream_on_device(stream_h->pa_info.index, device, is_on);
685
686         return _convert_sound_manager_error_code(__func__, ret);
687 }
688
689 int sound_manager_get_current_media_playback_device_type(sound_device_type_e *device_type)
690 {
691         int ret = MM_ERROR_NONE;
692
693         LOGI(">> enter");
694
695         SM_NULL_ARG_CHECK(device_type);
696
697         ret = _get_current_media_routing_path("out", device_type);
698
699         return _convert_sound_manager_error_code(__func__, ret);
700 }
701
702 int sound_manager_get_current_playback_focus(sound_stream_focus_change_reason_e *acquired_by, int *flags, char **extra_info)
703 {
704         int ret = MM_ERROR_NONE;
705         char *stream_type_str = NULL;
706         char *extra_info_str = NULL;
707         int option = 0;
708         bool is_focus_cb_thread = false;
709
710         LOGI(">> enter");
711
712         SM_NULL_ARG_CHECK(acquired_by);
713         SM_NULL_ARG_CHECK(flags);
714
715         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread, NULL)))
716                 return _convert_sound_manager_error_code(__func__, ret);
717
718         if (is_focus_cb_thread) {
719                 LOGE("this API should not be called in focus callback");
720                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
721         }
722
723         ret = mm_sound_get_stream_type_of_acquired_focus((int)SOUND_STREAM_FOCUS_FOR_PLAYBACK, &stream_type_str, &option, &extra_info_str);
724         if (ret == MM_ERROR_NONE) {
725                 LOGI("current acquired PLAYBACK focus : stream_type[%s]", stream_type_str);
726                 ret = _convert_stream_type_to_change_reason(stream_type_str, acquired_by);
727                 if (ret == MM_ERROR_NONE) {
728                         LOGI("                                : reason[%d], flags[0x%x], extra_info[%s]", *acquired_by, option, extra_info_str);
729                         *flags = option;
730                         if (extra_info)
731                                 *extra_info = strdup(extra_info_str);
732                 }
733                 SM_SAFE_FREE(stream_type_str);
734                 SM_SAFE_FREE(extra_info_str);
735         }
736
737         return _convert_sound_manager_error_code(__func__, ret);
738 }
739
740 int sound_manager_get_current_recording_focus(sound_stream_focus_change_reason_e *acquired_by, int *flags, char **extra_info)
741 {
742         int ret = MM_ERROR_NONE;
743         char *stream_type_str = NULL;
744         char *extra_info_str = NULL;
745         int option = 0;
746         bool is_focus_cb_thread = false;
747
748         LOGI(">> enter");
749
750         SM_NULL_ARG_CHECK(acquired_by);
751         SM_NULL_ARG_CHECK(flags);
752
753         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread, NULL)))
754                 return _convert_sound_manager_error_code(__func__, ret);
755
756         if (is_focus_cb_thread) {
757                 LOGE("this API should not be called in focus callback");
758                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
759         }
760
761         ret = mm_sound_get_stream_type_of_acquired_focus((int)SOUND_STREAM_FOCUS_FOR_RECORDING, &stream_type_str, &option, &extra_info_str);
762         if (ret == MM_ERROR_NONE) {
763                 LOGI("current acquired RECORDING focus : stream_type[%s]", stream_type_str);
764                 ret = _convert_stream_type_to_change_reason(stream_type_str, acquired_by);
765                 if (ret == MM_ERROR_NONE) {
766                         LOGI("                                 : reason[%d], flags[0x%x], extra_info[%s]", *acquired_by, option, extra_info_str);
767                         *flags = option;
768                         if (extra_info)
769                                 *extra_info = strdup(extra_info_str);
770                 }
771                 SM_SAFE_FREE(stream_type_str);
772                 SM_SAFE_FREE(extra_info_str);
773         }
774
775         return _convert_sound_manager_error_code(__func__, ret);
776 }
777
778 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)
779 {
780         int ret = MM_ERROR_NONE;
781         int i = 0;
782
783         LOGI(">> enter");
784
785         SM_NULL_ARG_CHECK(callback);
786         SM_NULL_ARG_CHECK(id);
787
788         for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++)
789                 if (focus_watch_info_arr[i].id == 0)
790                         break;
791         if (i == SOUND_STREAM_INFO_ARR_MAX) {
792                 //LCOV_EXCL_START
793                 LOGE("focus watch info array is full");
794                 ret = MM_ERROR_SOUND_INTERNAL;
795                 goto LEAVE;
796                 //LCOV_EXCL_STOP
797         }
798
799         ret = mm_sound_set_focus_watch_callback((mm_sound_focus_type_e)focus_mask, _focus_watch_callback, &focus_watch_info_arr[i], id);
800         if (ret == MM_ERROR_NONE) {
801                 focus_watch_info_arr[i].id = *id;
802                 focus_watch_info_arr[i].user_data = user_data;
803                 focus_watch_info_arr[i].user_cb = callback;
804         }
805
806 LEAVE:
807         LOGD("id(%d)", *id);
808
809         return _convert_sound_manager_error_code(__func__, ret);
810 }
811
812 int sound_manager_remove_focus_state_watch_cb(int id)
813 {
814         int ret = MM_ERROR_NONE;
815         int i = 0;
816
817         LOGI(">> enter");
818
819         for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++)
820                 if (focus_watch_info_arr[i].id == id)
821                         break;
822         if (i == SOUND_STREAM_INFO_ARR_MAX) {
823                 LOGE("cound not find item in focus watch info array for this id(%d)", id);
824                 ret = MM_ERROR_INVALID_ARGUMENT;
825                 goto LEAVE;
826         }
827
828         ret = mm_sound_unset_focus_watch_callback(id);
829         if (ret == MM_ERROR_NONE) {
830                 focus_watch_info_arr[i].id = 0;
831                 focus_watch_info_arr[i].user_data = NULL;
832                 focus_watch_info_arr[i].user_cb = NULL;
833         }
834
835 LEAVE:
836         return _convert_sound_manager_error_code(__func__, ret);
837 }
838
839 int sound_manager_get_device_list(int device_mask, sound_device_list_h *device_list)
840 {
841         int ret = MM_ERROR_NONE;
842
843         ret = mm_sound_get_device_list(device_mask, device_list);
844
845         return _convert_sound_manager_error_code(__func__, ret);
846 }
847
848 int sound_manager_free_device_list(sound_device_list_h device_list)
849 {
850         int ret = MM_ERROR_NONE;
851
852         ret = mm_sound_free_device_list(device_list);
853
854         return _convert_sound_manager_error_code(__func__, ret);
855 }
856
857 int sound_manager_get_next_device(sound_device_list_h device_list, sound_device_h *device)
858 {
859         int ret = MM_ERROR_NONE;
860
861         ret = mm_sound_get_next_device(device_list, device);
862
863         return _convert_sound_manager_error_code(__func__, ret);
864 }
865
866 int sound_manager_get_prev_device(sound_device_list_h device_list, sound_device_h *device)
867 {
868         int ret = MM_ERROR_NONE;
869
870         ret = mm_sound_get_prev_device(device_list, device);
871
872         return _convert_sound_manager_error_code(__func__, ret);
873 }
874
875 int sound_manager_get_device_type(sound_device_h device, sound_device_type_e *type)
876 {
877         int ret = MM_ERROR_NONE;
878         mm_sound_device_type_e mm_sound_device_type;
879
880         ret = mm_sound_get_device_type(device, &mm_sound_device_type);
881         if (ret == MM_ERROR_NONE)
882                 ret = _convert_device_type(mm_sound_device_type, type);
883
884         return _convert_sound_manager_error_code(__func__, ret);
885 }
886
887 int sound_manager_get_device_io_direction(sound_device_h device, sound_device_io_direction_e *io_direction)
888 {
889         int ret = MM_ERROR_NONE;
890         mm_sound_device_io_direction_e mm_sound_io_direction;
891
892         ret = mm_sound_get_device_io_direction(device, &mm_sound_io_direction);
893         if (ret == MM_ERROR_NONE)
894                 ret = _convert_device_io_direction(mm_sound_io_direction, io_direction);
895
896         return _convert_sound_manager_error_code(__func__, ret);
897 }
898
899 int sound_manager_get_device_id(sound_device_h device, int *id)
900 {
901         int ret = MM_ERROR_NONE;
902
903         ret = mm_sound_get_device_id(device, id);
904
905         return _convert_sound_manager_error_code(__func__, ret);
906 }
907
908 int sound_manager_get_device_name(sound_device_h device, char **name)
909 {
910         int ret = MM_ERROR_NONE;
911
912         ret = mm_sound_get_device_name(device, name);
913
914         return _convert_sound_manager_error_code(__func__, ret);
915 }
916
917 int sound_manager_is_device_running(sound_device_h device, bool *is_running)
918 {
919         int ret = MM_ERROR_NONE;
920
921         LOGI(">> enter");
922
923         SM_INSTANCE_CHECK(device);
924         SM_NULL_ARG_CHECK(is_running);
925
926         ret = mm_sound_is_device_running(device, is_running);
927
928         return _convert_sound_manager_error_code(__func__, ret);
929 }
930
931 int sound_manager_get_device_state(sound_device_h device, sound_device_state_e *state)
932 {
933         int ret = MM_ERROR_NONE;
934
935         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release.", __func__);
936         ret = mm_sound_get_device_state(device, (mm_sound_device_state_e*)state);
937
938         return _convert_sound_manager_error_code(__func__, ret);
939 }
940
941 int sound_manager_get_supported_sample_formats(sound_device_h device, sound_sample_format_e **formats, unsigned int *num_of_elems)
942 {
943         int ret = MM_ERROR_NONE;
944         int device_id;
945
946         SM_INSTANCE_CHECK(device);
947         SM_NULL_ARG_CHECK(formats);
948         SM_NULL_ARG_CHECK(num_of_elems);
949
950         if ((ret = _return_val_if_not_usb_device(device, SOUND_MANAGER_ERROR_INVALID_OPERATION)))
951                 return ret;
952
953         if (!(ret = mm_sound_get_device_id(device, &device_id)))
954                 ret = _get_supported_sample_formats(device_id, formats, num_of_elems);
955
956         return _convert_sound_manager_error_code(__func__, ret);
957 }
958
959 int sound_manager_set_sample_format(sound_device_h device, sound_sample_format_e format)
960 {
961         int ret = MM_ERROR_NONE;
962         int device_id;
963
964         SM_INSTANCE_CHECK(device);
965
966         if ((ret = _return_val_if_not_usb_device(device, SOUND_MANAGER_ERROR_INVALID_OPERATION)))
967                 return ret;
968
969         if (!(ret = mm_sound_get_device_id(device, &device_id)))
970                 ret = _set_sample_format(device_id, format);
971
972         return _convert_sound_manager_error_code(__func__, ret);
973 }
974
975 int sound_manager_get_sample_format(sound_device_h device, sound_sample_format_e *format)
976 {
977         int ret = MM_ERROR_NONE;
978         int device_id;
979
980         SM_INSTANCE_CHECK(device);
981         SM_NULL_ARG_CHECK(format);
982
983         if ((ret = _return_val_if_not_usb_device(device, SOUND_MANAGER_ERROR_INVALID_OPERATION)))
984                 return ret;
985
986         if (!(ret = mm_sound_get_device_id(device, &device_id)))
987                 ret = _get_sample_format(device_id, format);
988
989         return _convert_sound_manager_error_code(__func__, ret);
990 }
991
992 int sound_manager_get_supported_sample_rates(sound_device_h device, sound_sample_rate_e **rates, unsigned int *num_of_elems)
993 {
994         int ret = MM_ERROR_NONE;
995         int device_id;
996
997         SM_INSTANCE_CHECK(device);
998         SM_NULL_ARG_CHECK(rates);
999         SM_NULL_ARG_CHECK(num_of_elems);
1000
1001         if ((ret = _return_val_if_not_usb_device(device, SOUND_MANAGER_ERROR_INVALID_OPERATION)))
1002                 return ret;
1003
1004         if (!(ret = mm_sound_get_device_id(device, &device_id)))
1005                 ret = _get_supported_sample_rates(device_id, rates, num_of_elems);
1006
1007         return _convert_sound_manager_error_code(__func__, ret);
1008 }
1009
1010 int sound_manager_set_sample_rate(sound_device_h device, sound_sample_rate_e rate)
1011 {
1012         int ret = MM_ERROR_NONE;
1013         int device_id;
1014
1015         SM_INSTANCE_CHECK(device);
1016
1017         if ((ret = _return_val_if_not_usb_device(device, SOUND_MANAGER_ERROR_INVALID_OPERATION)))
1018                 return ret;
1019
1020         if (!(ret = mm_sound_get_device_id(device, &device_id)))
1021                 ret = _set_sample_rate(device_id, rate);
1022
1023         return _convert_sound_manager_error_code(__func__, ret);
1024 }
1025
1026 int sound_manager_get_sample_rate(sound_device_h device, sound_sample_rate_e *rate)
1027 {
1028         int ret = MM_ERROR_NONE;
1029         int device_id;
1030
1031         SM_INSTANCE_CHECK(device);
1032         SM_NULL_ARG_CHECK(rate);
1033
1034         if ((ret = _return_val_if_not_usb_device(device, SOUND_MANAGER_ERROR_INVALID_OPERATION)))
1035                 return ret;
1036
1037         if (!(ret = mm_sound_get_device_id(device, &device_id)))
1038                 ret = _get_sample_rate(device_id, rate);
1039
1040         return _convert_sound_manager_error_code(__func__, ret);
1041 }
1042
1043 int sound_manager_set_avoid_resampling(sound_device_h device, bool enable)
1044 {
1045         int ret = MM_ERROR_NONE;
1046         int device_id;
1047
1048         SM_INSTANCE_CHECK(device);
1049
1050         if ((ret = _return_val_if_not_usb_device(device, SOUND_MANAGER_ERROR_INVALID_OPERATION)))
1051                 return ret;
1052
1053         if (!(ret = mm_sound_get_device_id(device, &device_id)))
1054                 ret = _set_avoid_resampling(device_id, enable);
1055
1056         return _convert_sound_manager_error_code(__func__, ret);
1057 }
1058
1059 int sound_manager_get_avoid_resampling(sound_device_h device, bool *enabled)
1060 {
1061         int ret = MM_ERROR_NONE;
1062         int device_id;
1063
1064         SM_INSTANCE_CHECK(device);
1065         SM_NULL_ARG_CHECK(enabled);
1066
1067         if ((ret = _return_val_if_not_usb_device(device, SOUND_MANAGER_ERROR_INVALID_OPERATION)))
1068                 return ret;
1069
1070         if (!(ret = mm_sound_get_device_id(device, &device_id)))
1071                 ret = _get_avoid_resampling(device_id, enabled);
1072
1073         return _convert_sound_manager_error_code(__func__, ret);
1074 }
1075
1076 int sound_manager_set_media_stream_only(sound_device_h device, bool enable)
1077 {
1078         int ret = MM_ERROR_NONE;
1079         int device_id;
1080
1081         SM_INSTANCE_CHECK(device);
1082
1083         if ((ret = _return_val_if_not_usb_device(device, SOUND_MANAGER_ERROR_INVALID_OPERATION)))
1084                 return ret;
1085
1086         if (!(ret = mm_sound_get_device_id(device, &device_id)))
1087                 ret = _set_media_stream_only(device_id, enable);
1088
1089         return _convert_sound_manager_error_code(__func__, ret);
1090 }
1091
1092 int sound_manager_get_media_stream_only(sound_device_h device, bool *enabled)
1093 {
1094         int ret = MM_ERROR_NONE;
1095         int device_id;
1096
1097         SM_INSTANCE_CHECK(device);
1098         SM_NULL_ARG_CHECK(enabled);
1099
1100         if ((ret = _return_val_if_not_usb_device(device, SOUND_MANAGER_ERROR_INVALID_OPERATION)))
1101                 return ret;
1102
1103         if (!(ret = mm_sound_get_device_id(device, &device_id)))
1104                 ret = _get_media_stream_only(device_id, enabled);
1105
1106         return _convert_sound_manager_error_code(__func__, ret);
1107 }
1108
1109 int sound_manager_add_device_connection_changed_cb(int device_mask, sound_device_connection_changed_cb callback, void *user_data, int *id)
1110 {
1111         int ret = MM_ERROR_NONE;
1112
1113         SM_NULL_ARG_CHECK(callback);
1114         SM_NULL_ARG_CHECK(id);
1115
1116         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);
1117
1118         return _convert_sound_manager_error_code(__func__, ret);
1119 }
1120
1121 int sound_manager_remove_device_connection_changed_cb(int id)
1122 {
1123         int ret = MM_ERROR_NONE;
1124
1125         if (id < 0)
1126                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
1127
1128         ret = mm_sound_remove_device_connected_callback((unsigned int)id);
1129
1130         return _convert_sound_manager_error_code(__func__, ret);
1131 }
1132
1133 int sound_manager_add_device_running_changed_cb(int device_mask, sound_device_running_changed_cb callback, void *user_data, int *id)
1134 {
1135         int ret = MM_ERROR_NONE;
1136
1137         SM_NULL_ARG_CHECK(callback);
1138         SM_NULL_ARG_CHECK(id);
1139
1140         ret = mm_sound_add_device_running_changed_callback(device_mask, (mm_sound_device_running_changed_cb)callback, user_data, (unsigned int*)id);
1141
1142         return _convert_sound_manager_error_code(__func__, ret);
1143 }
1144
1145 int sound_manager_remove_device_running_changed_cb(int id)
1146 {
1147         int ret = MM_ERROR_NONE;
1148
1149         if (id < 0)
1150                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
1151
1152         ret = mm_sound_remove_device_running_changed_callback((unsigned int)id);
1153
1154         return _convert_sound_manager_error_code(__func__, ret);
1155 }
1156
1157 int sound_manager_add_device_state_changed_cb(int device_mask, sound_device_state_changed_cb callback, void *user_data, int *id)
1158 {
1159         int ret = MM_ERROR_NONE;
1160
1161         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release.", __func__);
1162         SM_NULL_ARG_CHECK(callback);
1163         SM_NULL_ARG_CHECK(id);
1164
1165         ret = mm_sound_add_device_state_changed_callback(device_mask, (mm_sound_device_state_changed_cb)callback, user_data, (unsigned int*)id);
1166
1167         return _convert_sound_manager_error_code(__func__, ret);
1168 }
1169
1170 int sound_manager_remove_device_state_changed_cb(int id)
1171 {
1172         int ret = MM_ERROR_NONE;
1173
1174         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release.", __func__);
1175         if (id < 0)
1176                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
1177
1178         ret = mm_sound_remove_device_state_changed_callback((unsigned int)id);
1179
1180         return _convert_sound_manager_error_code(__func__, ret);
1181 }
1182
1183 int sound_manager_create_stream_ducking(sound_stream_type_e target_stream, sound_stream_ducking_state_changed_cb callback, void *user_data, sound_stream_ducking_h *stream_ducking)
1184 {
1185         int i = 0;
1186         int ret = MM_ERROR_NONE;
1187         sound_stream_ducking_s *new_ducking = NULL;
1188
1189         SM_NULL_ARG_CHECK(stream_ducking);
1190
1191         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&ducking_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1192
1193         for (i = 0 ; i < SOUND_DUCKING_ARR_MAX ; i++)
1194                 if (ducking_arr[i] == NULL)
1195                         break;
1196
1197         if (i == SOUND_DUCKING_ARR_MAX) {
1198                 LOGE("ducking array is full");
1199                 ret = MM_ERROR_SOUND_INTERNAL;
1200                 goto LEAVE;
1201         }
1202
1203         new_ducking = (sound_stream_ducking_s *)calloc(1, sizeof(sound_stream_ducking_s));
1204         if (!new_ducking) {
1205                 ret = MM_ERROR_OUT_OF_MEMORY;
1206                 goto LEAVE;
1207         }
1208
1209         ret = _convert_stream_type(target_stream, &new_ducking->target_stream);
1210         if (ret != MM_ERROR_NONE)
1211                 goto LEAVE;
1212
1213         ret = _make_pa_connection(&new_ducking->pa_info, "SOUND_MANAGER_STREAM_DUCKING");
1214
1215 LEAVE:
1216         if (ret == MM_ERROR_NONE) {
1217                 if (++ducking_arr_count == 1) {
1218                         /* subscribe ducking finished signal */
1219                         ret = mm_sound_add_ducking_state_changed_callback((mm_sound_ducking_state_changed_cb)_ducking_state_changed_cb,
1220                                 NULL, &ducking_cb_subs_id);
1221                         if (ret != MM_ERROR_NONE) {
1222                                 ducking_arr_count = 0;
1223                                 goto LEAVE;
1224                         }
1225
1226                         LOGI("ducking state changed cb subs id %d", ducking_cb_subs_id);
1227                 }
1228
1229                 new_ducking->user_cb = callback;
1230                 new_ducking->user_data = user_data;
1231
1232                 ducking_arr[i] = new_ducking;
1233                 *stream_ducking = (sound_stream_ducking_h)new_ducking;
1234
1235                 LOGI("new stream_ducking(%p), target_stream(%s), pa_index(%u), user_cb(%p)",
1236                         new_ducking, new_ducking->target_stream, new_ducking->pa_info.index, new_ducking->user_cb);
1237         } else {
1238                 if (new_ducking) {
1239                         _destroy_pa_connection(&new_ducking->pa_info);
1240                         free(new_ducking);
1241                 }
1242         }
1243
1244         SM_LEAVE_CRITICAL_SECTION(&ducking_mutex);
1245
1246         return _convert_sound_manager_error_code(__func__, ret);
1247 }
1248
1249 int sound_manager_destroy_stream_ducking(sound_stream_ducking_h stream_ducking)
1250 {
1251         int i = 0;
1252         int ret = MM_ERROR_NONE;
1253         bool is_ducked = false;
1254         sound_stream_ducking_s *ducking = (sound_stream_ducking_s*)stream_ducking;
1255
1256         LOGI(">> enter %p", ducking);
1257
1258         SM_INSTANCE_CHECK(ducking);
1259
1260         ret = _get_ducking_state(&ducking->pa_info, &is_ducked);
1261         if (ret != MM_ERROR_NONE && ret != MM_ERROR_SOUND_SERVER_DISCONNECTED)
1262                 return _convert_sound_manager_error_code(__func__, ret);
1263
1264         if (is_ducked) {
1265                 LOGE("ducked now, it should be deactivated first.");
1266                 return SOUND_MANAGER_ERROR_INVALID_STATE;
1267         }
1268
1269         LOGI("destroy stream ducking(%p)", ducking);
1270
1271         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&ducking_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1272
1273         _destroy_pa_connection(&ducking->pa_info);
1274
1275         for (i = 0 ; i < SOUND_DUCKING_ARR_MAX ; i++)
1276                 if (ducking_arr[i] == ducking)
1277                         ducking_arr[i] = NULL;
1278
1279         if (--ducking_arr_count == 0) {
1280                 /* unsubscribe ducking finished signal */
1281                 if (mm_sound_remove_ducking_state_changed_callback(ducking_cb_subs_id) != MM_ERROR_NONE)
1282                         LOGW("mm_sound_remove_ducking_state_changed_callback(id:%u) failed", ducking_cb_subs_id);
1283
1284                 ducking_cb_subs_id = 0;
1285         }
1286
1287         free(ducking);
1288
1289         SM_LEAVE_CRITICAL_SECTION(&ducking_mutex);
1290
1291         return _convert_sound_manager_error_code(__func__, MM_ERROR_NONE);
1292 }
1293
1294 int sound_manager_is_ducked(sound_stream_ducking_h stream_ducking, bool *is_ducked)
1295 {
1296         int ret = MM_ERROR_NONE;
1297         sound_stream_ducking_s *ducking = (sound_stream_ducking_s*)stream_ducking;
1298
1299         LOGI(">> enter %p", ducking);
1300
1301         SM_INSTANCE_CHECK(ducking);
1302         SM_NULL_ARG_CHECK(is_ducked);
1303
1304         ret = _get_ducking_state(&ducking->pa_info, is_ducked);
1305
1306         return _convert_sound_manager_error_code(__func__, ret);
1307 }
1308
1309 int sound_manager_activate_ducking(sound_stream_ducking_h stream_ducking, unsigned int duration, double ratio)
1310 {
1311         int ret = MM_ERROR_NONE;
1312         bool is_ducked = false;
1313         sound_stream_ducking_s *ducking = (sound_stream_ducking_s*)stream_ducking;
1314
1315         if (duration > 3000 || ratio >= 1.0 || ratio < 0.0) {
1316                 LOGE("Invalid params : duration(%u) or ratio(%lf)", duration, ratio);
1317                 return SOUND_MANAGER_ERROR_INVALID_PARAMETER;
1318         }
1319
1320         LOGI(">> enter %p - duration(%u), ratio(%lf)", ducking, duration, ratio);
1321
1322         SM_INSTANCE_CHECK(ducking);
1323
1324         ret = _get_ducking_state(&ducking->pa_info, &is_ducked);
1325         if (ret != MM_ERROR_NONE)
1326                 return _convert_sound_manager_error_code(__func__, ret);
1327
1328         if (is_ducked) {
1329                 LOGE("already ducked");
1330                 return SOUND_MANAGER_ERROR_INVALID_STATE;
1331         }
1332
1333         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&ducking_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1334
1335         ret = _activate_ducking(ducking->pa_info.index,
1336                 true, ducking->target_stream, (uint32_t)duration, ratio);
1337
1338         if (ret == MM_ERROR_NONE) {
1339                 ducking->duration = duration;
1340                 ducking->ratio = ratio;
1341         }
1342
1343         SM_LEAVE_CRITICAL_SECTION(&ducking_mutex);
1344
1345         return _convert_sound_manager_error_code(__func__, ret);
1346 }
1347
1348 int sound_manager_deactivate_ducking(sound_stream_ducking_h stream_ducking)
1349 {
1350         int ret = MM_ERROR_NONE;
1351         bool is_ducked = false;
1352         sound_stream_ducking_s *ducking = (sound_stream_ducking_s*)stream_ducking;
1353
1354         LOGI(">> enter %p", ducking);
1355
1356         SM_INSTANCE_CHECK(ducking);
1357
1358         ret = _get_ducking_state(&ducking->pa_info, &is_ducked);
1359         if (ret != MM_ERROR_NONE)
1360                 return _convert_sound_manager_error_code(__func__, ret);
1361
1362         if (!is_ducked) {
1363                 LOGE("not ducked");
1364                 return SOUND_MANAGER_ERROR_INVALID_STATE;
1365         }
1366
1367         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&ducking_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1368
1369         ret = _activate_ducking(ducking->pa_info.index,
1370                 false, ducking->target_stream, (uint32_t)ducking->duration, ducking->ratio);
1371
1372         SM_LEAVE_CRITICAL_SECTION(&ducking_mutex);
1373
1374         return _convert_sound_manager_error_code(__func__, ret);
1375 }