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