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