Fix coverity issues
[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         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
277
278         LOGI(">> enter");
279
280         SM_INSTANCE_CHECK(stream_h);
281
282         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
283                 return _convert_sound_manager_error_code(__func__, ret);
284
285         if (stream_h->is_focus_unavailable) {
286                 LOGE("acquiring focus is not allowed for this stream type(%s)", stream_h->stream_type);
287                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
288         }
289
290         if (stream_h->user_cb == NULL) {
291                 LOGE("focus state changed callback should be set before acquiring focus");
292                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
293         }
294
295         if (!is_focus_cb_thread) {
296                 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL);
297                 SM_ENTER_CRITICAL_SECTION_WITH_UNLOCK_AND_RETURN(&stream_h->focus_state_mutex, &stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL);
298         } else {
299                 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_state_mutex, MM_ERROR_SOUND_INTERNAL);
300         }
301
302         if (stream_h->acquired_focus & focus_mask) {
303                 LOGE("invalid state: focus_mask[0x%x], acquired_focus[0x%x]", focus_mask, stream_h->acquired_focus);
304                 ret = MM_ERROR_SOUND_INVALID_STATE;
305                 goto LEAVE;
306         }
307
308         if (is_focus_cb_thread && ((stream_h->prev_acquired_focus & ~stream_h->acquired_focus) & focus_mask)) {
309                 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]",
310                         focus_mask, stream_h->acquired_focus, stream_h->prev_acquired_focus);
311                 ret = MM_ERROR_POLICY_INTERNAL;
312                 goto LEAVE;
313         }
314
315         ret = mm_sound_acquire_focus_with_option(stream_h->focus_id, (mm_sound_focus_type_e)focus_mask, sound_behavior, extra_info);
316         if (ret == MM_ERROR_NONE) {
317                 stream_h->acquired_focus |= focus_mask;
318                 stream_h->prev_acquired_focus |= focus_mask;
319                 _update_focus_status(stream_h->pa_index, (unsigned int)stream_h->acquired_focus);
320         }
321
322         LOGI("acquired_focus[0x%x], prev[0x%x]", stream_h->acquired_focus, stream_h->prev_acquired_focus);
323
324 LEAVE:
325         SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_state_mutex);
326         if (!is_focus_cb_thread)
327                 SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_cb_mutex);
328
329         return _convert_sound_manager_error_code(__func__, ret);
330 }
331
332 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)
333 {
334         int ret = MM_ERROR_NONE;
335         bool is_focus_cb_thread = false;
336         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
337
338         LOGI(">> enter");
339
340         SM_INSTANCE_CHECK(stream_h);
341
342         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
343                 return _convert_sound_manager_error_code(__func__, ret);
344
345         if (!is_focus_cb_thread) {
346                 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL);
347                 SM_ENTER_CRITICAL_SECTION_WITH_UNLOCK_AND_RETURN(&stream_h->focus_state_mutex, &stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL);
348         } else {
349                 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_state_mutex, MM_ERROR_SOUND_INTERNAL);
350         }
351
352         if (!(stream_h->acquired_focus & focus_mask)) {
353                 LOGE("invalid state: focus_mask[0x%x], acquired_focus[0x%x]", focus_mask, stream_h->acquired_focus);
354                 ret = MM_ERROR_SOUND_INVALID_STATE;
355                 goto LEAVE;
356         }
357
358         if (is_focus_cb_thread && ((stream_h->prev_acquired_focus & stream_h->acquired_focus) != focus_mask)) {
359                 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]",
360                         focus_mask, stream_h->acquired_focus, stream_h->prev_acquired_focus);
361                 ret = MM_ERROR_SOUND_INVALID_STATE;
362                 goto LEAVE;
363         }
364
365         ret = mm_sound_release_focus_with_option(stream_h->focus_id, (mm_sound_focus_type_e)focus_mask, sound_behavior, extra_info);
366         if (ret == MM_ERROR_NONE) {
367                 stream_h->acquired_focus &= ~focus_mask;
368                 stream_h->prev_acquired_focus &= ~focus_mask;
369                 _update_focus_status(stream_h->pa_index, (unsigned int)stream_h->acquired_focus);
370         }
371
372         LOGI("acquired_focus[0x%x], prev[0x%x]", stream_h->acquired_focus, stream_h->prev_acquired_focus);
373
374 LEAVE:
375         SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_state_mutex);
376         if (!is_focus_cb_thread)
377                 SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_cb_mutex);
378
379         return _convert_sound_manager_error_code(__func__, ret);
380 }
381
382 int sound_manager_acquire_focus_all(sound_stream_info_h stream_info, int sound_behavior, const char *extra_info)
383 {
384         int ret = MM_ERROR_NONE;
385         int focus_mask = SOUND_STREAM_FOCUS_FOR_BOTH;
386         bool is_focus_cb_thread = false;
387         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
388
389         LOGI(">> enter");
390
391         SM_INSTANCE_CHECK(stream_h);
392
393         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
394                 return _convert_sound_manager_error_code(__func__, ret);
395
396         if (stream_h->is_focus_unavailable) {
397                 LOGE("acquiring focus is not allowed for this stream type(%s)", stream_h->stream_type);
398                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
399         }
400
401         if (stream_h->user_cb == NULL) {
402                 LOGE("focus state changed callback should be set before acquiring focus");
403                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
404         }
405
406         if (!is_focus_cb_thread) {
407                 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL);
408                 SM_ENTER_CRITICAL_SECTION_WITH_UNLOCK_AND_RETURN(&stream_h->focus_state_mutex, &stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL);
409         } else {
410                 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_state_mutex, MM_ERROR_SOUND_INTERNAL);
411         }
412
413         if (is_focus_cb_thread && (stream_h->prev_acquired_focus > stream_h->acquired_focus)) {
414                 LOGE("just lost focus in this callback, it is not allowed to acquire all again. acquired_focus[0x%x], prev[0x%x]",
415                         stream_h->acquired_focus, stream_h->prev_acquired_focus);
416                 ret = MM_ERROR_POLICY_INTERNAL;
417                 goto LEAVE;
418         }
419
420         focus_mask = SOUND_STREAM_FOCUS_FOR_BOTH & ~(stream_h->acquired_focus);
421         if (!focus_mask) {
422                 LOGI("PLAYBACK/RECORDING focuses have already been ACQUIRED");
423                 ret = MM_ERROR_NONE;
424                 goto LEAVE;
425         }
426
427         ret = mm_sound_acquire_focus_with_option(stream_h->focus_id, (mm_sound_focus_type_e)focus_mask, sound_behavior, extra_info);
428         if (ret == MM_ERROR_NONE) {
429                 stream_h->acquired_focus |= focus_mask;
430                 stream_h->prev_acquired_focus |= focus_mask;
431                 _update_focus_status(stream_h->pa_index, (unsigned int)stream_h->acquired_focus);
432         }
433
434 LEAVE:
435         SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_state_mutex);
436         if (!is_focus_cb_thread)
437                 SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_cb_mutex);
438
439         return _convert_sound_manager_error_code(__func__, ret);
440 }
441
442 int sound_manager_release_focus_all(sound_stream_info_h stream_info, int sound_behavior, const char *extra_info)
443 {
444         int ret = MM_ERROR_NONE;
445         bool is_focus_cb_thread = false;
446         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
447
448         LOGI(">> enter");
449
450         SM_INSTANCE_CHECK(stream_h);
451
452         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
453                 return _convert_sound_manager_error_code(__func__, ret);
454
455         if (!is_focus_cb_thread) {
456                 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL);
457                 SM_ENTER_CRITICAL_SECTION_WITH_UNLOCK_AND_RETURN(&stream_h->focus_state_mutex, &stream_h->focus_cb_mutex, MM_ERROR_SOUND_INTERNAL);
458         } else {
459                 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_state_mutex, MM_ERROR_SOUND_INTERNAL);
460         }
461
462         if (is_focus_cb_thread && (stream_h->prev_acquired_focus < stream_h->acquired_focus)) {
463                 LOGE("just acquired focus in this callback, it is not allowed to release all again. acquired_focus[0x%x], prev[0x%x]",
464                         stream_h->acquired_focus, stream_h->prev_acquired_focus);
465                 ret = MM_ERROR_POLICY_INTERNAL;
466                 goto LEAVE;
467         }
468
469         if (!stream_h->acquired_focus) {
470                 LOGI("PLAYBACK/RECORDING focuses have already been RELEASED");
471                 ret = MM_ERROR_NONE;
472                 goto LEAVE;
473         }
474
475         ret = mm_sound_release_focus_with_option(stream_h->focus_id, (mm_sound_focus_type_e)stream_h->acquired_focus, sound_behavior, extra_info);
476         if (ret == MM_ERROR_NONE) {
477                 stream_h->acquired_focus = 0;
478                 stream_h->prev_acquired_focus = 0;
479                 _update_focus_status(stream_h->pa_index, (unsigned int)stream_h->acquired_focus);
480         }
481
482 LEAVE:
483         SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_state_mutex);
484         if (!is_focus_cb_thread)
485                 SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_cb_mutex);
486
487         return _convert_sound_manager_error_code(__func__, ret);
488 }
489
490 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)
491 {
492         int ret = MM_ERROR_NONE;
493         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
494
495         LOGI(">> enter");
496
497         SM_INSTANCE_CHECK(stream_h);
498         if (!state_for_playback && !state_for_recording)
499                 return SOUND_MANAGER_ERROR_INVALID_PARAMETER;
500
501         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&stream_h->focus_state_mutex, MM_ERROR_SOUND_INTERNAL);
502
503         if (state_for_playback)
504                 *state_for_playback = ((stream_h->acquired_focus & SOUND_STREAM_FOCUS_FOR_PLAYBACK) ? (SOUND_STREAM_FOCUS_STATE_ACQUIRED) : (SOUND_STREAM_FOCUS_STATE_RELEASED));
505         if (state_for_recording)
506                 *state_for_recording = ((stream_h->acquired_focus & SOUND_STREAM_FOCUS_FOR_RECORDING) ? (SOUND_STREAM_FOCUS_STATE_ACQUIRED) : (SOUND_STREAM_FOCUS_STATE_RELEASED));
507
508         LOGI("acquired_focus(0x%x)", stream_h->acquired_focus);
509
510         SM_LEAVE_CRITICAL_SECTION(&stream_h->focus_state_mutex);
511
512         return _convert_sound_manager_error_code(__func__, ret);
513 }
514
515 int sound_manager_deliver_focus(sound_stream_info_h source, sound_stream_info_h destination, sound_stream_focus_mask_e focus_mask)
516 {
517         int ret = MM_ERROR_NONE;
518         sound_stream_info_s *src_stream_h = (sound_stream_info_s*)source;
519         sound_stream_info_s *dst_stream_h = (sound_stream_info_s*)destination;
520         bool is_focus_cb_thread = false;
521
522         LOGI(">> enter");
523
524         SM_INSTANCE_CHECK(src_stream_h);
525         SM_INSTANCE_CHECK(dst_stream_h);
526
527         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
528                 return _convert_sound_manager_error_code(__func__, ret);
529
530         if (is_focus_cb_thread) {
531                 LOGE("not allowed calling this function in focus(watch) callback");
532                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
533         }
534
535         if (src_stream_h->focus_id == dst_stream_h->focus_id) {
536                 LOGE("not allowed because both handles have same id(%u)", src_stream_h->focus_id);
537                 return SOUND_MANAGER_ERROR_INVALID_PARAMETER;
538         }
539
540         if (src_stream_h->is_focus_unavailable || dst_stream_h->is_focus_unavailable) {
541                 LOGE("focus is unavailable for source(%d)/destination(%d)",
542                         src_stream_h->is_focus_unavailable, dst_stream_h->is_focus_unavailable);
543                 return SOUND_MANAGER_ERROR_POLICY;
544         }
545
546         if (!(src_stream_h->acquired_focus & focus_mask) || (src_stream_h->acquired_focus < focus_mask)) {
547                 LOGE("could not deliver the request focus(0x%x), current acquired focus(0x%x)",
548                         focus_mask, src_stream_h->acquired_focus);
549                 return SOUND_MANAGER_ERROR_INVALID_STATE;
550         }
551
552         if (dst_stream_h->user_cb == NULL) {
553                 LOGE("focus state changed callback should be set to destination handle");
554                 return SOUND_MANAGER_ERROR_POLICY;
555         }
556
557         ret = mm_sound_deliver_focus(src_stream_h->focus_id, dst_stream_h->focus_id, (mm_sound_focus_type_e)focus_mask);
558         if (ret == MM_ERROR_NONE) {
559                 src_stream_h->acquired_focus &= ~focus_mask;
560                 src_stream_h->prev_acquired_focus &= ~focus_mask;
561                 dst_stream_h->acquired_focus |= focus_mask;
562                 dst_stream_h->prev_acquired_focus |= focus_mask;
563         }
564
565         return _convert_sound_manager_error_code(__func__, ret);
566 }
567
568 int sound_manager_is_stream_on_device(sound_stream_info_h stream_info, sound_device_h device, bool *is_on)
569 {
570         int ret = MM_ERROR_NONE;
571         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
572
573         LOGI(">> enter");
574
575         SM_NULL_ARG_CHECK(stream_h);
576         SM_NULL_ARG_CHECK(device);
577         SM_NULL_ARG_CHECK(is_on);
578
579         ret = mm_sound_is_stream_on_device(stream_h->pa_index, device, is_on);
580
581         return _convert_sound_manager_error_code(__func__, ret);
582 }
583
584 int sound_manager_get_current_media_playback_device_type(sound_device_type_e *device_type)
585 {
586         int ret = MM_ERROR_NONE;
587
588         LOGI(">> enter");
589
590         SM_NULL_ARG_CHECK(device_type);
591
592         ret = _get_current_media_routing_path("out", device_type);
593
594         return _convert_sound_manager_error_code(__func__, ret);
595 }
596
597 int sound_manager_get_current_playback_focus(sound_stream_focus_change_reason_e *acquired_by, int *flags, char **extra_info)
598 {
599         int ret = MM_ERROR_NONE;
600         char *stream_type_str = NULL;
601         char *extra_info_str = NULL;
602         int option = 0;
603         bool is_focus_cb_thread = false;
604
605         LOGI(">> enter");
606
607         SM_NULL_ARG_CHECK(acquired_by);
608         SM_NULL_ARG_CHECK(flags);
609
610         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
611                 return _convert_sound_manager_error_code(__func__, ret);
612
613         if (is_focus_cb_thread) {
614                 LOGE("this API should not be called in focus callback");
615                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
616         }
617
618         ret = mm_sound_get_stream_type_of_acquired_focus((int)SOUND_STREAM_FOCUS_FOR_PLAYBACK, &stream_type_str, &option, &extra_info_str);
619         if (ret == MM_ERROR_NONE) {
620                 LOGI("current acquired PLAYBACK focus : stream_type[%s]", stream_type_str);
621                 ret = _convert_stream_type_to_change_reason(stream_type_str, acquired_by);
622                 if (ret == MM_ERROR_NONE) {
623                         LOGI("                                : reason[%d], flags[0x%x], extra_info[%s]", *acquired_by, option, extra_info_str);
624                         *flags = option;
625                         if (extra_info)
626                                 *extra_info = strdup(extra_info_str);
627                 }
628                 SM_SAFE_FREE(stream_type_str);
629                 SM_SAFE_FREE(extra_info_str);
630         }
631
632         return _convert_sound_manager_error_code(__func__, ret);
633 }
634
635 int sound_manager_get_current_recording_focus(sound_stream_focus_change_reason_e *acquired_by, int *flags, char **extra_info)
636 {
637         int ret = MM_ERROR_NONE;
638         char *stream_type_str = NULL;
639         char *extra_info_str = NULL;
640         int option = 0;
641         bool is_focus_cb_thread = false;
642
643         LOGI(">> enter");
644
645         SM_NULL_ARG_CHECK(acquired_by);
646         SM_NULL_ARG_CHECK(flags);
647
648         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
649                 return _convert_sound_manager_error_code(__func__, ret);
650
651         if (is_focus_cb_thread) {
652                 LOGE("this API should not be called in focus callback");
653                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
654         }
655
656         ret = mm_sound_get_stream_type_of_acquired_focus((int)SOUND_STREAM_FOCUS_FOR_RECORDING, &stream_type_str, &option, &extra_info_str);
657         if (ret == MM_ERROR_NONE) {
658                 LOGI("current acquired RECORDING focus : stream_type[%s]", stream_type_str);
659                 ret = _convert_stream_type_to_change_reason(stream_type_str, acquired_by);
660                 if (ret == MM_ERROR_NONE) {
661                         LOGI("                                 : reason[%d], flags[0x%x], extra_info[%s]", *acquired_by, option, extra_info_str);
662                         *flags = option;
663                         if (extra_info)
664                                 *extra_info = strdup(extra_info_str);
665                 }
666                 SM_SAFE_FREE(stream_type_str);
667                 SM_SAFE_FREE(extra_info_str);
668         }
669
670         return _convert_sound_manager_error_code(__func__, ret);
671 }
672
673 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)
674 {
675         int ret = MM_ERROR_NONE;
676         int i = 0;
677
678         LOGI(">> enter");
679
680         SM_NULL_ARG_CHECK(callback);
681         SM_NULL_ARG_CHECK(id);
682
683         for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++)
684                 if (focus_watch_info_arr[i].id == 0)
685                         break;
686         if (i == SOUND_STREAM_INFO_ARR_MAX) {
687                 //LCOV_EXCL_START
688                 LOGE("focus watch info array is full");
689                 ret = MM_ERROR_SOUND_INTERNAL;
690                 goto LEAVE;
691                 //LCOV_EXCL_STOP
692         }
693
694         ret = mm_sound_set_focus_watch_callback((mm_sound_focus_type_e)focus_mask, _focus_watch_callback, &focus_watch_info_arr[i], id);
695         if (ret == MM_ERROR_NONE) {
696                 focus_watch_info_arr[i].id = *id;
697                 focus_watch_info_arr[i].user_data = user_data;
698                 focus_watch_info_arr[i].user_cb = callback;
699         }
700
701 LEAVE:
702         LOGD("id(%d)", *id);
703
704         return _convert_sound_manager_error_code(__func__, ret);
705 }
706
707 int sound_manager_remove_focus_state_watch_cb(int id)
708 {
709         int ret = MM_ERROR_NONE;
710         int i = 0;
711
712         LOGI(">> enter");
713
714         for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++)
715                 if (focus_watch_info_arr[i].id == id)
716                         break;
717         if (i == SOUND_STREAM_INFO_ARR_MAX) {
718                 LOGE("cound not find item in focus watch info array for this id(%d)", id);
719                 ret = MM_ERROR_INVALID_ARGUMENT;
720                 goto LEAVE;
721         }
722
723         ret = mm_sound_unset_focus_watch_callback(id);
724         if (ret == MM_ERROR_NONE) {
725                 focus_watch_info_arr[i].id = 0;
726                 focus_watch_info_arr[i].user_data = NULL;
727                 focus_watch_info_arr[i].user_cb = NULL;
728         }
729
730 LEAVE:
731         return _convert_sound_manager_error_code(__func__, ret);
732 }
733
734 int sound_manager_get_device_list(int device_mask, sound_device_list_h *device_list)
735 {
736         int ret = MM_ERROR_NONE;
737
738         ret = mm_sound_get_device_list(device_mask, device_list);
739
740         return _convert_sound_manager_error_code(__func__, ret);
741 }
742
743 int sound_manager_free_device_list(sound_device_list_h device_list)
744 {
745         int ret = MM_ERROR_NONE;
746
747         ret = mm_sound_free_device_list(device_list);
748
749         return _convert_sound_manager_error_code(__func__, ret);
750 }
751
752 int sound_manager_get_next_device(sound_device_list_h device_list, sound_device_h *device)
753 {
754         int ret = MM_ERROR_NONE;
755
756         ret = mm_sound_get_next_device(device_list, device);
757
758         return _convert_sound_manager_error_code(__func__, ret);
759 }
760
761 int sound_manager_get_prev_device(sound_device_list_h device_list, sound_device_h *device)
762 {
763         int ret = MM_ERROR_NONE;
764
765         ret = mm_sound_get_prev_device(device_list, device);
766
767         return _convert_sound_manager_error_code(__func__, ret);
768 }
769
770 int sound_manager_get_device_type(sound_device_h device, sound_device_type_e *type)
771 {
772         int ret = MM_ERROR_NONE;
773         mm_sound_device_type_e mm_sound_device_type;
774
775         ret = mm_sound_get_device_type(device, &mm_sound_device_type);
776         if (ret == MM_ERROR_NONE)
777                 ret = _convert_device_type(mm_sound_device_type, type);
778
779         return _convert_sound_manager_error_code(__func__, ret);
780 }
781
782 int sound_manager_get_device_io_direction(sound_device_h device, sound_device_io_direction_e *io_direction)
783 {
784         int ret = MM_ERROR_NONE;
785         mm_sound_device_io_direction_e mm_sound_io_direction;
786
787         ret = mm_sound_get_device_io_direction(device, &mm_sound_io_direction);
788         if (ret == MM_ERROR_NONE)
789                 ret = _convert_device_io_direction(mm_sound_io_direction, io_direction);
790
791         return _convert_sound_manager_error_code(__func__, ret);
792 }
793
794 int sound_manager_get_device_id(sound_device_h device, int *id)
795 {
796         int ret = MM_ERROR_NONE;
797
798         ret = mm_sound_get_device_id(device, id);
799
800         return _convert_sound_manager_error_code(__func__, ret);
801 }
802
803 int sound_manager_get_device_name(sound_device_h device, char **name)
804 {
805         int ret = MM_ERROR_NONE;
806
807         ret = mm_sound_get_device_name(device, name);
808
809         return _convert_sound_manager_error_code(__func__, ret);
810 }
811
812 int sound_manager_is_device_running(sound_device_h device, bool *is_running)
813 {
814         int ret = MM_ERROR_NONE;
815
816         LOGI(">> enter");
817
818         SM_INSTANCE_CHECK(device);
819         SM_NULL_ARG_CHECK(is_running);
820
821         ret = mm_sound_is_device_running(device, is_running);
822
823         return _convert_sound_manager_error_code(__func__, ret);
824 }
825
826 int sound_manager_get_device_state(sound_device_h device, sound_device_state_e *state)
827 {
828         int ret = MM_ERROR_NONE;
829
830         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release.", __func__);
831         ret = mm_sound_get_device_state(device, (mm_sound_device_state_e*)state);
832
833         return _convert_sound_manager_error_code(__func__, ret);
834 }
835
836 int sound_manager_add_device_connection_changed_cb(int device_mask, sound_device_connection_changed_cb callback, void *user_data, int *id)
837 {
838         int ret = MM_ERROR_NONE;
839
840         SM_NULL_ARG_CHECK(callback);
841         SM_NULL_ARG_CHECK(id);
842
843         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);
844
845         return _convert_sound_manager_error_code(__func__, ret);
846 }
847
848 int sound_manager_remove_device_connection_changed_cb(int id)
849 {
850         int ret = MM_ERROR_NONE;
851
852         if (id < 0)
853                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
854
855         ret = mm_sound_remove_device_connected_callback((unsigned int)id);
856
857         return _convert_sound_manager_error_code(__func__, ret);
858 }
859
860 int sound_manager_add_device_running_changed_cb(int device_mask, sound_device_running_changed_cb callback, void *user_data, int *id)
861 {
862         int ret = MM_ERROR_NONE;
863
864         SM_NULL_ARG_CHECK(callback);
865         SM_NULL_ARG_CHECK(id);
866
867         ret = mm_sound_add_device_running_changed_callback(device_mask, (mm_sound_device_running_changed_cb)callback, user_data, (unsigned int*)id);
868
869         return _convert_sound_manager_error_code(__func__, ret);
870 }
871
872 int sound_manager_remove_device_running_changed_cb(int id)
873 {
874         int ret = MM_ERROR_NONE;
875
876         if (id < 0)
877                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
878
879         ret = mm_sound_remove_device_running_changed_callback((unsigned int)id);
880
881         return _convert_sound_manager_error_code(__func__, ret);
882 }
883
884 int sound_manager_add_device_state_changed_cb(int device_mask, sound_device_state_changed_cb callback, void *user_data, int *id)
885 {
886         int ret = MM_ERROR_NONE;
887
888         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release.", __func__);
889         SM_NULL_ARG_CHECK(callback);
890         SM_NULL_ARG_CHECK(id);
891
892         ret = mm_sound_add_device_state_changed_callback(device_mask, (mm_sound_device_state_changed_cb)callback, user_data, (unsigned int*)id);
893
894         return _convert_sound_manager_error_code(__func__, ret);
895 }
896
897 int sound_manager_remove_device_state_changed_cb(int id)
898 {
899         int ret = MM_ERROR_NONE;
900
901         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release.", __func__);
902         if (id < 0)
903                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
904
905         ret = mm_sound_remove_device_state_changed_callback((unsigned int)id);
906
907         return _convert_sound_manager_error_code(__func__, ret);
908 }
909
910 __attribute__ ((destructor))
911 void __sound_manager_finalize(void)
912 {
913
914 }
915
916 __attribute__ ((constructor))
917 void __sound_manager_initialize(void)
918 {
919
920 }