Remove unused destructor/constructor block
[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 _focus_watch_info_s focus_watch_info_arr[SOUND_STREAM_INFO_ARR_MAX];
21
22 int sound_manager_get_max_volume(sound_type_e type, int *max)
23 {
24         const char *volume_type = NULL;
25         unsigned int max_level = 0;
26         int ret = MM_ERROR_NONE;
27
28         SM_NULL_ARG_CHECK(max);
29         if (type >= SOUND_TYPE_NUM)
30                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
31
32         ret = _convert_sound_type(type, &volume_type);
33         if (ret == MM_ERROR_NONE) {
34                 ret = _get_volume_max_level(DIRECTION_OUT_STR, volume_type, &max_level);
35                 if (ret == MM_ERROR_NONE)
36                         *max = (int)max_level -1;       /* actual volume step can be max step - 1 */
37         }
38
39         return _convert_sound_manager_error_code(__func__, ret);
40 }
41
42 int sound_manager_set_volume(sound_type_e type, int volume)
43 {
44         int ret = MM_ERROR_NONE;
45
46         if (type >= SOUND_TYPE_NUM)
47                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
48         if (volume < 0)
49                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
50
51         ret = mm_sound_volume_set_value(type, volume);
52         LOGI("type=%d, volume=%d", type, volume);
53
54         return _convert_sound_manager_error_code(__func__, ret);
55 }
56
57 int sound_manager_get_volume(sound_type_e type, int *volume)
58 {
59         int ret = MM_ERROR_NONE;
60         unsigned int uvolume;
61
62         if (type >= SOUND_TYPE_NUM)
63                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
64         if (volume == NULL)
65                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
66
67         ret = mm_sound_volume_get_value(type, &uvolume);
68         if (ret == MM_ERROR_NONE)
69                 *volume = uvolume;
70
71         LOGI("type=%d, volume=%d", type, *volume);
72
73         return _convert_sound_manager_error_code(__func__, ret);
74 }
75
76 int sound_manager_get_current_sound_type(sound_type_e *type)
77 {
78         int ret = MM_ERROR_NONE;
79         char *volume_type = NULL;
80
81         if (type == NULL)
82                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
83
84         /* get the volume type of the current playing stream */
85         ret = _get_current_volume_type(DIRECTION_OUT_STR, &volume_type);
86         if (ret == MM_ERROR_NONE) {
87                 ret = _convert_sound_type_to_enum((const char*)volume_type, type);
88                 LOGI("type=%d", *type);
89         }
90
91         return _convert_sound_manager_error_code(__func__, ret);
92 }
93
94 int sound_manager_add_volume_changed_cb(sound_manager_volume_changed_cb callback, void *user_data, int *id)
95 {
96         int ret = MM_ERROR_NONE;
97
98         if (!callback || !id)
99                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
100
101         ret = mm_sound_add_volume_changed_callback((mm_sound_volume_changed_cb)callback, user_data, (unsigned int*)id);
102
103         return _convert_sound_manager_error_code(__func__, ret);
104 }
105
106 int sound_manager_remove_volume_changed_cb(int id)
107 {
108         int ret = MM_ERROR_NONE;
109
110         if (id < 0)
111                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
112
113         ret = mm_sound_remove_volume_changed_callback(id);
114
115         return _convert_sound_manager_error_code(__func__, ret);
116 }
117
118 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)
119 {
120         int ret = MM_ERROR_NONE;
121
122         LOGI(">> enter");
123
124         SM_NULL_ARG_CHECK(stream_info);
125
126         sound_stream_info_s *stream_h = malloc(sizeof(sound_stream_info_s));
127         if (!stream_h) {
128                 ret = MM_ERROR_OUT_OF_MEMORY;
129                 goto LEAVE;
130         }
131
132         memset(stream_h, 0, sizeof(sound_stream_info_s));
133         ret = _convert_stream_type(stream_type, &stream_h->stream_type);
134         if (ret == MM_ERROR_NONE) {
135                 ret = _make_pa_connection_and_register_focus(stream_h, callback, user_data);
136                 if (ret == MM_ERROR_NONE) {
137                         *stream_info = (sound_stream_info_h)stream_h;
138                         LOGI("stream_h(%p), pa_index(%u), focus_id(%d), user_cb(%p), ret(0x%x)",
139                                 stream_h, stream_h->pa_index, stream_h->focus_id, stream_h->user_cb, ret);
140                 }
141         }
142
143 LEAVE:
144         if (ret)
145                 SM_SAFE_FREE(stream_h);
146
147         return _convert_sound_manager_error_code(__func__, ret);
148 }
149
150 int sound_manager_destroy_stream_information(sound_stream_info_h stream_info)
151 {
152         int ret = MM_ERROR_NONE;
153         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
154
155         LOGI(">> enter");
156
157         SM_INSTANCE_CHECK(stream_h);
158
159         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_state_mutex, MM_ERROR_SOUND_INTERNAL);
160         ret = _destroy_pa_connection_and_unregister_focus(stream_h);
161         SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_state_mutex);
162         if (ret == MM_ERROR_NONE) {
163                 SM_SAFE_FREE(stream_h);
164         }
165
166         return _convert_sound_manager_error_code(__func__, ret);
167 }
168
169 int sound_manager_get_sound_type(sound_stream_info_h stream_info, sound_type_e *sound_type)
170 {
171         int ret = MM_ERROR_NONE;
172         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
173
174         LOGI(">> enter");
175
176         SM_INSTANCE_CHECK(stream_h);
177         SM_NULL_ARG_CHECK(sound_type);
178
179         if (stream_h->stream_conf_info.volume_type == NULL) {
180                 ret = MM_ERROR_SOUND_NO_DATA;
181                 goto LEAVE;
182         }
183
184         ret = _convert_sound_type_to_enum(stream_h->stream_conf_info.volume_type, sound_type);
185         LOGI("sound type(%d)", *sound_type);
186
187 LEAVE:
188         return _convert_sound_manager_error_code(__func__, ret);
189 }
190
191 int sound_manager_add_device_for_stream_routing(sound_stream_info_h stream_info, sound_device_h device)
192 {
193         int ret = MM_ERROR_NONE;
194         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
195
196         LOGI(">> enter");
197
198         ret = _add_device_for_stream_routing(stream_h, device);
199
200         return _convert_sound_manager_error_code(__func__, ret);
201 }
202
203 int sound_manager_remove_device_for_stream_routing(sound_stream_info_h stream_info, sound_device_h device)
204 {
205         int ret = MM_ERROR_NONE;
206         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
207
208         LOGI(">> enter");
209
210         ret = _remove_device_for_stream_routing(stream_h, device);
211
212         return _convert_sound_manager_error_code(__func__, ret);
213 }
214
215 int sound_manager_remove_all_devices_for_stream_routing(sound_stream_info_h stream_info)
216 {
217         int ret = MM_ERROR_NONE;
218         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
219
220         LOGI(">> enter");
221
222         ret = _remove_all_devices_for_stream_routing(stream_h);
223
224         return _convert_sound_manager_error_code(__func__, ret);
225 }
226
227 int sound_manager_apply_stream_routing(sound_stream_info_h stream_info)
228 {
229         int ret = MM_ERROR_NONE;
230         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
231
232         LOGI(">> enter");
233
234         ret = _apply_stream_routing(stream_h);
235
236         return _convert_sound_manager_error_code(__func__, ret);
237 }
238
239 int sound_manager_set_focus_reacquisition(sound_stream_info_h stream_info, bool enable)
240 {
241         int ret = MM_ERROR_NONE;
242         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
243
244         LOGI(">> enter");
245
246         SM_INSTANCE_CHECK(stream_h);
247
248         ret = mm_sound_set_focus_reacquisition(stream_h->focus_id, enable);
249
250         LOGI("enable(%d)", enable);
251
252         return _convert_sound_manager_error_code(__func__, ret);
253 }
254
255 int sound_manager_get_focus_reacquisition(sound_stream_info_h stream_info, bool *enabled)
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         SM_INSTANCE_CHECK(stream_h);
263         SM_NULL_ARG_CHECK(enabled);
264
265         ret = mm_sound_get_focus_reacquisition(stream_h->focus_id, enabled);
266
267         LOGI("enabled(%d)", *enabled);
268
269         return _convert_sound_manager_error_code(__func__, ret);
270 }
271
272 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)
273 {
274         int ret = MM_ERROR_NONE;
275         bool is_focus_cb_thread = false;
276         bool is_focus_watch_cb_thread = false;
277         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
278
279         LOGI(">> enter");
280
281         SM_INSTANCE_CHECK(stream_h);
282
283         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread, &is_focus_watch_cb_thread)))
284                 return _convert_sound_manager_error_code(__func__, ret);
285
286         if (stream_h->is_focus_unavailable) {
287                 LOGE("acquiring focus is not allowed for this stream type(%s)", stream_h->stream_type);
288                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
289         }
290
291         if (stream_h->user_cb == NULL) {
292                 LOGE("focus state changed callback should be set before acquiring focus");
293                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
294         }
295
296         if (!is_focus_cb_thread) {
297                 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL);
298                 SM_ENTER_CRITICAL_SECTION_WITH_UNLOCK_AND_RETURN(&stream_h->focus_state_mutex, &stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL);
299         } else {
300                 /* If it is inside of the watch cb and if the previous request of this process has not been finished yet,
301                  * the focus state mutex could be still locked. Therefore, it returns error here. */
302                 if (is_focus_watch_cb_thread && stream_h->is_requesting) {
303                         LOGE("It is not allowed in watch cb thread during the previous request has not been finished yet");
304                         return _convert_sound_manager_error_code(__func__, MM_ERROR_SOUND_INVALID_OPERATION);
305                 }
306                 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_state_mutex, MM_ERROR_SOUND_INTERNAL);
307         }
308
309         if (stream_h->acquired_focus & focus_mask) {
310                 LOGE("invalid state: focus_mask[0x%x], acquired_focus[0x%x]", focus_mask, stream_h->acquired_focus);
311                 ret = MM_ERROR_SOUND_INVALID_STATE;
312                 goto LEAVE;
313         }
314
315         if (is_focus_cb_thread && ((stream_h->prev_acquired_focus & ~stream_h->acquired_focus) & focus_mask)) {
316                 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]",
317                         focus_mask, stream_h->acquired_focus, stream_h->prev_acquired_focus);
318                 ret = MM_ERROR_POLICY_INTERNAL;
319                 goto LEAVE;
320         }
321
322         stream_h->is_requesting = true;
323
324         ret = mm_sound_acquire_focus_with_option(stream_h->focus_id, (mm_sound_focus_type_e)focus_mask, sound_behavior, extra_info);
325         if (ret == MM_ERROR_NONE) {
326                 stream_h->acquired_focus |= focus_mask;
327                 stream_h->prev_acquired_focus |= focus_mask;
328                 _update_focus_status(stream_h->pa_index, (unsigned int)stream_h->acquired_focus);
329         }
330
331         LOGI("acquired_focus[0x%x], prev[0x%x]", stream_h->acquired_focus, stream_h->prev_acquired_focus);
332
333 LEAVE:
334         stream_h->is_requesting = false;
335         SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_state_mutex);
336         if (!is_focus_cb_thread)
337                 SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_cb_mutex);
338
339         return _convert_sound_manager_error_code(__func__, ret);
340 }
341
342 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)
343 {
344         int ret = MM_ERROR_NONE;
345         bool is_focus_cb_thread = false;
346         bool is_focus_watch_cb_thread = false;
347         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
348
349         LOGI(">> enter");
350
351         SM_INSTANCE_CHECK(stream_h);
352
353         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread, &is_focus_watch_cb_thread)))
354                 return _convert_sound_manager_error_code(__func__, ret);
355
356         if (!is_focus_cb_thread) {
357                 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL);
358                 SM_ENTER_CRITICAL_SECTION_WITH_UNLOCK_AND_RETURN(&stream_h->focus_state_mutex, &stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL);
359         } else {
360                 /* If it is inside of the watch cb and if the previous request of this process has not been finished yet,
361                  * the focus state mutex could be still locked. Therefore, it returns error here. */
362                 if (is_focus_watch_cb_thread && stream_h->is_requesting) {
363                         LOGE("It is not allowed in watch cb thread during the previous request has not been finished yet");
364                         return _convert_sound_manager_error_code(__func__, MM_ERROR_SOUND_INVALID_OPERATION);
365                 }
366                 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_state_mutex, MM_ERROR_SOUND_INTERNAL);
367         }
368
369         if (!(stream_h->acquired_focus & focus_mask)) {
370                 LOGE("invalid state: focus_mask[0x%x], acquired_focus[0x%x]", focus_mask, stream_h->acquired_focus);
371                 ret = MM_ERROR_SOUND_INVALID_STATE;
372                 goto LEAVE;
373         }
374
375         if (is_focus_cb_thread && ((stream_h->prev_acquired_focus & stream_h->acquired_focus) != focus_mask)) {
376                 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]",
377                         focus_mask, stream_h->acquired_focus, stream_h->prev_acquired_focus);
378                 ret = MM_ERROR_SOUND_INVALID_STATE;
379                 goto LEAVE;
380         }
381
382         stream_h->is_requesting = true;
383
384         ret = mm_sound_release_focus_with_option(stream_h->focus_id, (mm_sound_focus_type_e)focus_mask, sound_behavior, extra_info);
385         if (ret == MM_ERROR_NONE) {
386                 stream_h->acquired_focus &= ~focus_mask;
387                 stream_h->prev_acquired_focus &= ~focus_mask;
388                 _update_focus_status(stream_h->pa_index, (unsigned int)stream_h->acquired_focus);
389         }
390
391         LOGI("acquired_focus[0x%x], prev[0x%x]", stream_h->acquired_focus, stream_h->prev_acquired_focus);
392
393 LEAVE:
394         stream_h->is_requesting = false;
395         SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_state_mutex);
396         if (!is_focus_cb_thread)
397                 SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_cb_mutex);
398
399         return _convert_sound_manager_error_code(__func__, ret);
400 }
401
402 int sound_manager_acquire_focus_all(sound_stream_info_h stream_info, int sound_behavior, const char *extra_info)
403 {
404         int ret = MM_ERROR_NONE;
405         int focus_mask = SOUND_STREAM_FOCUS_FOR_BOTH;
406         bool is_focus_cb_thread = false;
407         bool is_focus_watch_cb_thread = false;
408         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
409
410         LOGI(">> enter");
411
412         SM_INSTANCE_CHECK(stream_h);
413
414         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread, &is_focus_watch_cb_thread)))
415                 return _convert_sound_manager_error_code(__func__, ret);
416
417         if (stream_h->is_focus_unavailable) {
418                 LOGE("acquiring focus is not allowed for this stream type(%s)", stream_h->stream_type);
419                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
420         }
421
422         if (stream_h->user_cb == NULL) {
423                 LOGE("focus state changed callback should be set before acquiring focus");
424                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
425         }
426
427         if (!is_focus_cb_thread) {
428                 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL);
429                 SM_ENTER_CRITICAL_SECTION_WITH_UNLOCK_AND_RETURN(&stream_h->focus_state_mutex, &stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL);
430         } else {
431                 /* If it is inside of the watch cb and if the previous request of this process has not been finished yet,
432                  * the focus state mutex could be still locked. Therefore, it returns error here. */
433                 if (is_focus_watch_cb_thread && stream_h->is_requesting) {
434                         LOGE("It is not allowed in watch cb thread during the previous request has not been finished yet");
435                         return _convert_sound_manager_error_code(__func__, MM_ERROR_SOUND_INVALID_OPERATION);
436                 }
437                 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_state_mutex, MM_ERROR_SOUND_INTERNAL);
438         }
439
440         if (is_focus_cb_thread && (stream_h->prev_acquired_focus > stream_h->acquired_focus)) {
441                 LOGE("just lost focus in this callback, it is not allowed to acquire all again. acquired_focus[0x%x], prev[0x%x]",
442                         stream_h->acquired_focus, stream_h->prev_acquired_focus);
443                 ret = MM_ERROR_POLICY_INTERNAL;
444                 goto LEAVE;
445         }
446
447         focus_mask = SOUND_STREAM_FOCUS_FOR_BOTH & ~(stream_h->acquired_focus);
448         if (!focus_mask) {
449                 LOGI("PLAYBACK/RECORDING focuses have already been ACQUIRED");
450                 ret = MM_ERROR_NONE;
451                 goto LEAVE;
452         }
453
454         stream_h->is_requesting = true;
455
456         ret = mm_sound_acquire_focus_with_option(stream_h->focus_id, (mm_sound_focus_type_e)focus_mask, sound_behavior, extra_info);
457         if (ret == MM_ERROR_NONE) {
458                 stream_h->acquired_focus |= focus_mask;
459                 stream_h->prev_acquired_focus |= focus_mask;
460                 _update_focus_status(stream_h->pa_index, (unsigned int)stream_h->acquired_focus);
461         }
462
463 LEAVE:
464         stream_h->is_requesting = false;
465         SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_state_mutex);
466         if (!is_focus_cb_thread)
467                 SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_cb_mutex);
468
469         return _convert_sound_manager_error_code(__func__, ret);
470 }
471
472 int sound_manager_release_focus_all(sound_stream_info_h stream_info, int sound_behavior, const char *extra_info)
473 {
474         int ret = MM_ERROR_NONE;
475         bool is_focus_cb_thread = false;
476         bool is_focus_watch_cb_thread = false;
477         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
478
479         LOGI(">> enter");
480
481         SM_INSTANCE_CHECK(stream_h);
482
483         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread, &is_focus_watch_cb_thread)))
484                 return _convert_sound_manager_error_code(__func__, ret);
485
486         if (!is_focus_cb_thread) {
487                 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL);
488                 SM_ENTER_CRITICAL_SECTION_WITH_UNLOCK_AND_RETURN(&stream_h->focus_state_mutex, &stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL);
489         } else {
490                 /* If it is inside of the watch cb and if the previous request of this process has not been finished yet,
491                  * the focus state mutex could be still locked. Therefore, it returns error here. */
492                 if (is_focus_watch_cb_thread && stream_h->is_requesting) {
493                         LOGE("It is not allowed in watch cb thread during the previous request has not been finished yet");
494                         return _convert_sound_manager_error_code(__func__, MM_ERROR_SOUND_INVALID_OPERATION);
495                 }
496                 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_state_mutex, MM_ERROR_SOUND_INTERNAL);
497         }
498
499         if (is_focus_cb_thread && (stream_h->prev_acquired_focus < stream_h->acquired_focus)) {
500                 LOGE("just acquired focus in this callback, it is not allowed to release all again. acquired_focus[0x%x], prev[0x%x]",
501                         stream_h->acquired_focus, stream_h->prev_acquired_focus);
502                 ret = MM_ERROR_POLICY_INTERNAL;
503                 goto LEAVE;
504         }
505
506         if (!stream_h->acquired_focus) {
507                 LOGI("PLAYBACK/RECORDING focuses have already been RELEASED");
508                 ret = MM_ERROR_NONE;
509                 goto LEAVE;
510         }
511
512         stream_h->is_requesting = true;
513
514         ret = mm_sound_release_focus_with_option(stream_h->focus_id, (mm_sound_focus_type_e)stream_h->acquired_focus, sound_behavior, extra_info);
515         if (ret == MM_ERROR_NONE) {
516                 stream_h->acquired_focus = 0;
517                 stream_h->prev_acquired_focus = 0;
518                 _update_focus_status(stream_h->pa_index, (unsigned int)stream_h->acquired_focus);
519         }
520
521 LEAVE:
522         stream_h->is_requesting = false;
523         SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_state_mutex);
524         if (!is_focus_cb_thread)
525                 SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_cb_mutex);
526
527         return _convert_sound_manager_error_code(__func__, ret);
528 }
529
530 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)
531 {
532         int ret = MM_ERROR_NONE;
533         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
534
535         LOGI(">> enter");
536
537         SM_INSTANCE_CHECK(stream_h);
538         if (!state_for_playback && !state_for_recording)
539                 return SOUND_MANAGER_ERROR_INVALID_PARAMETER;
540
541         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_state_mutex, MM_ERROR_SOUND_INTERNAL);
542
543         if (state_for_playback)
544                 *state_for_playback = ((stream_h->acquired_focus & SOUND_STREAM_FOCUS_FOR_PLAYBACK) ? (SOUND_STREAM_FOCUS_STATE_ACQUIRED) : (SOUND_STREAM_FOCUS_STATE_RELEASED));
545         if (state_for_recording)
546                 *state_for_recording = ((stream_h->acquired_focus & SOUND_STREAM_FOCUS_FOR_RECORDING) ? (SOUND_STREAM_FOCUS_STATE_ACQUIRED) : (SOUND_STREAM_FOCUS_STATE_RELEASED));
547
548         LOGI("acquired_focus(0x%x)", stream_h->acquired_focus);
549
550         SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_state_mutex);
551
552         return _convert_sound_manager_error_code(__func__, ret);
553 }
554
555 int sound_manager_deliver_focus(sound_stream_info_h source, sound_stream_info_h destination, sound_stream_focus_mask_e focus_mask)
556 {
557         int ret = MM_ERROR_NONE;
558         sound_stream_info_s *src_stream_h = (sound_stream_info_s*)source;
559         sound_stream_info_s *dst_stream_h = (sound_stream_info_s*)destination;
560         bool is_focus_cb_thread = false;
561
562         LOGI(">> enter");
563
564         SM_INSTANCE_CHECK(src_stream_h);
565         SM_INSTANCE_CHECK(dst_stream_h);
566
567         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread, NULL)))
568                 return _convert_sound_manager_error_code(__func__, ret);
569
570         if (is_focus_cb_thread) {
571                 LOGE("not allowed calling this function in focus(watch) callback");
572                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
573         }
574
575         if (src_stream_h->focus_id == dst_stream_h->focus_id) {
576                 LOGE("not allowed because both handles have same id(%u)", src_stream_h->focus_id);
577                 return SOUND_MANAGER_ERROR_INVALID_PARAMETER;
578         }
579
580         if (src_stream_h->is_focus_unavailable || dst_stream_h->is_focus_unavailable) {
581                 LOGE("focus is unavailable for source(%d)/destination(%d)",
582                         src_stream_h->is_focus_unavailable, dst_stream_h->is_focus_unavailable);
583                 return SOUND_MANAGER_ERROR_POLICY;
584         }
585
586         if (!(src_stream_h->acquired_focus & focus_mask) || (src_stream_h->acquired_focus < focus_mask)) {
587                 LOGE("could not deliver the request focus(0x%x), current acquired focus(0x%x)",
588                         focus_mask, src_stream_h->acquired_focus);
589                 return SOUND_MANAGER_ERROR_INVALID_STATE;
590         }
591
592         if (dst_stream_h->user_cb == NULL) {
593                 LOGE("focus state changed callback should be set to destination handle");
594                 return SOUND_MANAGER_ERROR_POLICY;
595         }
596
597         ret = mm_sound_deliver_focus(src_stream_h->focus_id, dst_stream_h->focus_id, (mm_sound_focus_type_e)focus_mask);
598         if (ret == MM_ERROR_NONE) {
599                 src_stream_h->acquired_focus &= ~focus_mask;
600                 src_stream_h->prev_acquired_focus &= ~focus_mask;
601                 dst_stream_h->acquired_focus |= focus_mask;
602                 dst_stream_h->prev_acquired_focus |= focus_mask;
603         }
604
605         return _convert_sound_manager_error_code(__func__, ret);
606 }
607
608 int sound_manager_is_stream_on_device(sound_stream_info_h stream_info, sound_device_h device, bool *is_on)
609 {
610         int ret = MM_ERROR_NONE;
611         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
612
613         LOGI(">> enter");
614
615         SM_NULL_ARG_CHECK(stream_h);
616         SM_NULL_ARG_CHECK(device);
617         SM_NULL_ARG_CHECK(is_on);
618
619         ret = mm_sound_is_stream_on_device(stream_h->pa_index, device, is_on);
620
621         return _convert_sound_manager_error_code(__func__, ret);
622 }
623
624 int sound_manager_get_current_media_playback_device_type(sound_device_type_e *device_type)
625 {
626         int ret = MM_ERROR_NONE;
627
628         LOGI(">> enter");
629
630         SM_NULL_ARG_CHECK(device_type);
631
632         ret = _get_current_media_routing_path("out", device_type);
633
634         return _convert_sound_manager_error_code(__func__, ret);
635 }
636
637 int sound_manager_get_current_playback_focus(sound_stream_focus_change_reason_e *acquired_by, int *flags, char **extra_info)
638 {
639         int ret = MM_ERROR_NONE;
640         char *stream_type_str = NULL;
641         char *extra_info_str = NULL;
642         int option = 0;
643         bool is_focus_cb_thread = false;
644
645         LOGI(">> enter");
646
647         SM_NULL_ARG_CHECK(acquired_by);
648         SM_NULL_ARG_CHECK(flags);
649
650         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread, NULL)))
651                 return _convert_sound_manager_error_code(__func__, ret);
652
653         if (is_focus_cb_thread) {
654                 LOGE("this API should not be called in focus callback");
655                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
656         }
657
658         ret = mm_sound_get_stream_type_of_acquired_focus((int)SOUND_STREAM_FOCUS_FOR_PLAYBACK, &stream_type_str, &option, &extra_info_str);
659         if (ret == MM_ERROR_NONE) {
660                 LOGI("current acquired PLAYBACK focus : stream_type[%s]", stream_type_str);
661                 ret = _convert_stream_type_to_change_reason(stream_type_str, acquired_by);
662                 if (ret == MM_ERROR_NONE) {
663                         LOGI("                                : reason[%d], flags[0x%x], extra_info[%s]", *acquired_by, option, extra_info_str);
664                         *flags = option;
665                         if (extra_info)
666                                 *extra_info = strdup(extra_info_str);
667                 }
668                 SM_SAFE_FREE(stream_type_str);
669                 SM_SAFE_FREE(extra_info_str);
670         }
671
672         return _convert_sound_manager_error_code(__func__, ret);
673 }
674
675 int sound_manager_get_current_recording_focus(sound_stream_focus_change_reason_e *acquired_by, int *flags, char **extra_info)
676 {
677         int ret = MM_ERROR_NONE;
678         char *stream_type_str = NULL;
679         char *extra_info_str = NULL;
680         int option = 0;
681         bool is_focus_cb_thread = false;
682
683         LOGI(">> enter");
684
685         SM_NULL_ARG_CHECK(acquired_by);
686         SM_NULL_ARG_CHECK(flags);
687
688         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread, NULL)))
689                 return _convert_sound_manager_error_code(__func__, ret);
690
691         if (is_focus_cb_thread) {
692                 LOGE("this API should not be called in focus callback");
693                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
694         }
695
696         ret = mm_sound_get_stream_type_of_acquired_focus((int)SOUND_STREAM_FOCUS_FOR_RECORDING, &stream_type_str, &option, &extra_info_str);
697         if (ret == MM_ERROR_NONE) {
698                 LOGI("current acquired RECORDING focus : stream_type[%s]", stream_type_str);
699                 ret = _convert_stream_type_to_change_reason(stream_type_str, acquired_by);
700                 if (ret == MM_ERROR_NONE) {
701                         LOGI("                                 : reason[%d], flags[0x%x], extra_info[%s]", *acquired_by, option, extra_info_str);
702                         *flags = option;
703                         if (extra_info)
704                                 *extra_info = strdup(extra_info_str);
705                 }
706                 SM_SAFE_FREE(stream_type_str);
707                 SM_SAFE_FREE(extra_info_str);
708         }
709
710         return _convert_sound_manager_error_code(__func__, ret);
711 }
712
713 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)
714 {
715         int ret = MM_ERROR_NONE;
716         int i = 0;
717
718         LOGI(">> enter");
719
720         SM_NULL_ARG_CHECK(callback);
721         SM_NULL_ARG_CHECK(id);
722
723         for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++)
724                 if (focus_watch_info_arr[i].id == 0)
725                         break;
726         if (i == SOUND_STREAM_INFO_ARR_MAX) {
727                 //LCOV_EXCL_START
728                 LOGE("focus watch info array is full");
729                 ret = MM_ERROR_SOUND_INTERNAL;
730                 goto LEAVE;
731                 //LCOV_EXCL_STOP
732         }
733
734         ret = mm_sound_set_focus_watch_callback((mm_sound_focus_type_e)focus_mask, _focus_watch_callback, &focus_watch_info_arr[i], id);
735         if (ret == MM_ERROR_NONE) {
736                 focus_watch_info_arr[i].id = *id;
737                 focus_watch_info_arr[i].user_data = user_data;
738                 focus_watch_info_arr[i].user_cb = callback;
739         }
740
741 LEAVE:
742         LOGD("id(%d)", *id);
743
744         return _convert_sound_manager_error_code(__func__, ret);
745 }
746
747 int sound_manager_remove_focus_state_watch_cb(int id)
748 {
749         int ret = MM_ERROR_NONE;
750         int i = 0;
751
752         LOGI(">> enter");
753
754         for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++)
755                 if (focus_watch_info_arr[i].id == id)
756                         break;
757         if (i == SOUND_STREAM_INFO_ARR_MAX) {
758                 LOGE("cound not find item in focus watch info array for this id(%d)", id);
759                 ret = MM_ERROR_INVALID_ARGUMENT;
760                 goto LEAVE;
761         }
762
763         ret = mm_sound_unset_focus_watch_callback(id);
764         if (ret == MM_ERROR_NONE) {
765                 focus_watch_info_arr[i].id = 0;
766                 focus_watch_info_arr[i].user_data = NULL;
767                 focus_watch_info_arr[i].user_cb = NULL;
768         }
769
770 LEAVE:
771         return _convert_sound_manager_error_code(__func__, ret);
772 }
773
774 int sound_manager_get_device_list(int device_mask, sound_device_list_h *device_list)
775 {
776         int ret = MM_ERROR_NONE;
777
778         ret = mm_sound_get_device_list(device_mask, device_list);
779
780         return _convert_sound_manager_error_code(__func__, ret);
781 }
782
783 int sound_manager_free_device_list(sound_device_list_h device_list)
784 {
785         int ret = MM_ERROR_NONE;
786
787         ret = mm_sound_free_device_list(device_list);
788
789         return _convert_sound_manager_error_code(__func__, ret);
790 }
791
792 int sound_manager_get_next_device(sound_device_list_h device_list, sound_device_h *device)
793 {
794         int ret = MM_ERROR_NONE;
795
796         ret = mm_sound_get_next_device(device_list, device);
797
798         return _convert_sound_manager_error_code(__func__, ret);
799 }
800
801 int sound_manager_get_prev_device(sound_device_list_h device_list, sound_device_h *device)
802 {
803         int ret = MM_ERROR_NONE;
804
805         ret = mm_sound_get_prev_device(device_list, device);
806
807         return _convert_sound_manager_error_code(__func__, ret);
808 }
809
810 int sound_manager_get_device_type(sound_device_h device, sound_device_type_e *type)
811 {
812         int ret = MM_ERROR_NONE;
813         mm_sound_device_type_e mm_sound_device_type;
814
815         ret = mm_sound_get_device_type(device, &mm_sound_device_type);
816         if (ret == MM_ERROR_NONE)
817                 ret = _convert_device_type(mm_sound_device_type, type);
818
819         return _convert_sound_manager_error_code(__func__, ret);
820 }
821
822 int sound_manager_get_device_io_direction(sound_device_h device, sound_device_io_direction_e *io_direction)
823 {
824         int ret = MM_ERROR_NONE;
825         mm_sound_device_io_direction_e mm_sound_io_direction;
826
827         ret = mm_sound_get_device_io_direction(device, &mm_sound_io_direction);
828         if (ret == MM_ERROR_NONE)
829                 ret = _convert_device_io_direction(mm_sound_io_direction, io_direction);
830
831         return _convert_sound_manager_error_code(__func__, ret);
832 }
833
834 int sound_manager_get_device_id(sound_device_h device, int *id)
835 {
836         int ret = MM_ERROR_NONE;
837
838         ret = mm_sound_get_device_id(device, id);
839
840         return _convert_sound_manager_error_code(__func__, ret);
841 }
842
843 int sound_manager_get_device_name(sound_device_h device, char **name)
844 {
845         int ret = MM_ERROR_NONE;
846
847         ret = mm_sound_get_device_name(device, name);
848
849         return _convert_sound_manager_error_code(__func__, ret);
850 }
851
852 int sound_manager_is_device_running(sound_device_h device, bool *is_running)
853 {
854         int ret = MM_ERROR_NONE;
855
856         LOGI(">> enter");
857
858         SM_INSTANCE_CHECK(device);
859         SM_NULL_ARG_CHECK(is_running);
860
861         ret = mm_sound_is_device_running(device, is_running);
862
863         return _convert_sound_manager_error_code(__func__, ret);
864 }
865
866 int sound_manager_get_device_state(sound_device_h device, sound_device_state_e *state)
867 {
868         int ret = MM_ERROR_NONE;
869
870         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release.", __func__);
871         ret = mm_sound_get_device_state(device, (mm_sound_device_state_e*)state);
872
873         return _convert_sound_manager_error_code(__func__, ret);
874 }
875
876 int sound_manager_get_supported_sample_formats(sound_device_h device, sound_sample_format_e **formats, unsigned int *num_of_elems)
877 {
878         int ret = MM_ERROR_NONE;
879         int device_id;
880
881         SM_INSTANCE_CHECK(device);
882         SM_NULL_ARG_CHECK(formats);
883         SM_NULL_ARG_CHECK(num_of_elems);
884
885         if ((ret = _return_val_if_not_usb_device(device, SOUND_MANAGER_ERROR_INVALID_OPERATION)))
886                 return ret;
887
888         if (!(ret = mm_sound_get_device_id(device, &device_id)))
889                 ret = _get_supported_sample_formats(device_id, formats, num_of_elems);
890
891         return _convert_sound_manager_error_code(__func__, ret);
892 }
893
894 int sound_manager_set_sample_format(sound_device_h device, sound_sample_format_e format)
895 {
896         int ret = MM_ERROR_NONE;
897         int device_id;
898
899         SM_INSTANCE_CHECK(device);
900
901         if ((ret = _return_val_if_not_usb_device(device, SOUND_MANAGER_ERROR_INVALID_OPERATION)))
902                 return ret;
903
904         if (!(ret = mm_sound_get_device_id(device, &device_id)))
905                 ret = _set_sample_format(device_id, format);
906
907         return _convert_sound_manager_error_code(__func__, ret);
908 }
909
910 int sound_manager_get_sample_format(sound_device_h device, sound_sample_format_e *format)
911 {
912         int ret = MM_ERROR_NONE;
913         int device_id;
914
915         SM_INSTANCE_CHECK(device);
916         SM_NULL_ARG_CHECK(format);
917
918         if ((ret = _return_val_if_not_usb_device(device, SOUND_MANAGER_ERROR_INVALID_OPERATION)))
919                 return ret;
920
921         if (!(ret = mm_sound_get_device_id(device, &device_id)))
922                 ret = _get_sample_format(device_id, format);
923
924         return _convert_sound_manager_error_code(__func__, ret);
925 }
926
927 int sound_manager_get_supported_sample_rates(sound_device_h device, sound_sample_rate_e **rates, unsigned int *num_of_elems)
928 {
929         int ret = MM_ERROR_NONE;
930         int device_id;
931
932         SM_INSTANCE_CHECK(device);
933         SM_NULL_ARG_CHECK(rates);
934         SM_NULL_ARG_CHECK(num_of_elems);
935
936         if ((ret = _return_val_if_not_usb_device(device, SOUND_MANAGER_ERROR_INVALID_OPERATION)))
937                 return ret;
938
939         if (!(ret = mm_sound_get_device_id(device, &device_id)))
940                 ret = _get_supported_sample_rates(device_id, rates, num_of_elems);
941
942         return _convert_sound_manager_error_code(__func__, ret);
943 }
944
945 int sound_manager_set_sample_rate(sound_device_h device, sound_sample_rate_e rate)
946 {
947         int ret = MM_ERROR_NONE;
948         int device_id;
949
950         SM_INSTANCE_CHECK(device);
951
952         if ((ret = _return_val_if_not_usb_device(device, SOUND_MANAGER_ERROR_INVALID_OPERATION)))
953                 return ret;
954
955         if (!(ret = mm_sound_get_device_id(device, &device_id)))
956                 ret = _set_sample_rate(device_id, rate);
957
958         return _convert_sound_manager_error_code(__func__, ret);
959 }
960
961 int sound_manager_get_sample_rate(sound_device_h device, sound_sample_rate_e *rate)
962 {
963         int ret = MM_ERROR_NONE;
964         int device_id;
965
966         SM_INSTANCE_CHECK(device);
967         SM_NULL_ARG_CHECK(rate);
968
969         if ((ret = _return_val_if_not_usb_device(device, SOUND_MANAGER_ERROR_INVALID_OPERATION)))
970                 return ret;
971
972         if (!(ret = mm_sound_get_device_id(device, &device_id)))
973                 ret = _get_sample_rate(device_id, rate);
974
975         return _convert_sound_manager_error_code(__func__, ret);
976 }
977
978 int sound_manager_set_avoid_resampling(sound_device_h device, bool enable)
979 {
980         int ret = MM_ERROR_NONE;
981         int device_id;
982
983         SM_INSTANCE_CHECK(device);
984
985         if ((ret = _return_val_if_not_usb_device(device, SOUND_MANAGER_ERROR_INVALID_OPERATION)))
986                 return ret;
987
988         if (!(ret = mm_sound_get_device_id(device, &device_id)))
989                 ret = _set_avoid_resampling(device_id, enable);
990
991         return _convert_sound_manager_error_code(__func__, ret);
992 }
993
994 int sound_manager_get_avoid_resampling(sound_device_h device, bool *enabled)
995 {
996         int ret = MM_ERROR_NONE;
997         int device_id;
998
999         SM_INSTANCE_CHECK(device);
1000         SM_NULL_ARG_CHECK(enabled);
1001
1002         if ((ret = _return_val_if_not_usb_device(device, SOUND_MANAGER_ERROR_INVALID_OPERATION)))
1003                 return ret;
1004
1005         if (!(ret = mm_sound_get_device_id(device, &device_id)))
1006                 ret = _get_avoid_resampling(device_id, enabled);
1007
1008         return _convert_sound_manager_error_code(__func__, ret);
1009 }
1010
1011 int sound_manager_set_media_stream_only(sound_device_h device, bool enable)
1012 {
1013         int ret = MM_ERROR_NONE;
1014         int device_id;
1015
1016         SM_INSTANCE_CHECK(device);
1017
1018         if ((ret = _return_val_if_not_usb_device(device, SOUND_MANAGER_ERROR_INVALID_OPERATION)))
1019                 return ret;
1020
1021         if (!(ret = mm_sound_get_device_id(device, &device_id)))
1022                 ret = _set_media_stream_only(device_id, enable);
1023
1024         return _convert_sound_manager_error_code(__func__, ret);
1025 }
1026
1027 int sound_manager_get_media_stream_only(sound_device_h device, bool *enabled)
1028 {
1029         int ret = MM_ERROR_NONE;
1030         int device_id;
1031
1032         SM_INSTANCE_CHECK(device);
1033         SM_NULL_ARG_CHECK(enabled);
1034
1035         if ((ret = _return_val_if_not_usb_device(device, SOUND_MANAGER_ERROR_INVALID_OPERATION)))
1036                 return ret;
1037
1038         if (!(ret = mm_sound_get_device_id(device, &device_id)))
1039                 ret = _get_media_stream_only(device_id, enabled);
1040
1041         return _convert_sound_manager_error_code(__func__, ret);
1042 }
1043
1044 int sound_manager_add_device_connection_changed_cb(int device_mask, sound_device_connection_changed_cb callback, void *user_data, int *id)
1045 {
1046         int ret = MM_ERROR_NONE;
1047
1048         SM_NULL_ARG_CHECK(callback);
1049         SM_NULL_ARG_CHECK(id);
1050
1051         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);
1052
1053         return _convert_sound_manager_error_code(__func__, ret);
1054 }
1055
1056 int sound_manager_remove_device_connection_changed_cb(int id)
1057 {
1058         int ret = MM_ERROR_NONE;
1059
1060         if (id < 0)
1061                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
1062
1063         ret = mm_sound_remove_device_connected_callback((unsigned int)id);
1064
1065         return _convert_sound_manager_error_code(__func__, ret);
1066 }
1067
1068 int sound_manager_add_device_running_changed_cb(int device_mask, sound_device_running_changed_cb callback, void *user_data, int *id)
1069 {
1070         int ret = MM_ERROR_NONE;
1071
1072         SM_NULL_ARG_CHECK(callback);
1073         SM_NULL_ARG_CHECK(id);
1074
1075         ret = mm_sound_add_device_running_changed_callback(device_mask, (mm_sound_device_running_changed_cb)callback, user_data, (unsigned int*)id);
1076
1077         return _convert_sound_manager_error_code(__func__, ret);
1078 }
1079
1080 int sound_manager_remove_device_running_changed_cb(int id)
1081 {
1082         int ret = MM_ERROR_NONE;
1083
1084         if (id < 0)
1085                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
1086
1087         ret = mm_sound_remove_device_running_changed_callback((unsigned int)id);
1088
1089         return _convert_sound_manager_error_code(__func__, ret);
1090 }
1091
1092 int sound_manager_add_device_state_changed_cb(int device_mask, sound_device_state_changed_cb callback, void *user_data, int *id)
1093 {
1094         int ret = MM_ERROR_NONE;
1095
1096         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release.", __func__);
1097         SM_NULL_ARG_CHECK(callback);
1098         SM_NULL_ARG_CHECK(id);
1099
1100         ret = mm_sound_add_device_state_changed_callback(device_mask, (mm_sound_device_state_changed_cb)callback, user_data, (unsigned int*)id);
1101
1102         return _convert_sound_manager_error_code(__func__, ret);
1103 }
1104
1105 int sound_manager_remove_device_state_changed_cb(int id)
1106 {
1107         int ret = MM_ERROR_NONE;
1108
1109         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release.", __func__);
1110         if (id < 0)
1111                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
1112
1113         ret = mm_sound_remove_device_state_changed_callback((unsigned int)id);
1114
1115         return _convert_sound_manager_error_code(__func__, ret);
1116 }
1117