Adapt session interrupt callback to focus callback
[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 #define TMP_CODE
21
22 _session_interrupt_info_s g_session_interrupt_cb_table = {0, 0, NULL, NULL};
23 _volume_changed_info_s g_volume_changed_cb_table = {0, NULL, NULL};
24 _focus_watch_info_s g_focus_watch_cb_table = {-1, NULL, NULL};
25 _device_connected_info_s g_device_connected_cb_table = {0, NULL, NULL};
26 _device_changed_info_s g_device_info_changed_cb_table = {0, NULL, NULL};
27
28 sound_session_type_e g_cached_session = -1;
29 _session_mode_e g_cached_session_mode = -1;
30
31 /* These variables will be removed when session features are deprecated. */
32 extern int g_stream_info_count;
33 extern pthread_mutex_t g_stream_info_count_mutex;
34 pthread_mutex_t g_interrupt_cb_mutex, g_device_info_cb_mutex, g_device_conn_cb_mutex, g_volume_cb_mutex;
35
36 #ifdef TMP_CODE
37 /*temporary variable for set/get voip session mode. When 2.4  feature for routing is fully implemented, it will be removed.*/
38 sound_session_voip_mode_e tmp_mode = -1;
39 #endif
40
41 int sound_manager_get_max_volume (sound_type_e type, int *max)
42 {
43         const char *volume_type = NULL;
44         unsigned int max_level = 0;
45         int ret = MM_ERROR_NONE;
46
47         if (max == NULL)
48                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
49
50         if (type >= SOUND_TYPE_NUM || type < 0)
51                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
52         ret = __convert_sound_type (type, &volume_type);
53         if (ret == MM_ERROR_NONE) {
54                 ret = __get_volume_max_level("out", volume_type, &max_level);
55                 if (ret == MM_ERROR_NONE)
56                         *max = (int)max_level -1;       // actual volume step can be max step - 1
57         }
58
59         return __convert_sound_manager_error_code(__func__, ret);
60 }
61
62 int sound_manager_set_volume (sound_type_e type, int volume)
63 {
64         int ret = MM_ERROR_NONE;
65
66         if (type >= SOUND_TYPE_NUM || type < 0)
67                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
68         if (volume < 0)
69                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
70
71         ret = mm_sound_volume_set_value(type, volume);
72         LOGI("returns : type=%d, volume=%d, ret=%p", type, volume, ret);
73
74         return __convert_sound_manager_error_code(__func__, ret);
75 }
76
77 int sound_manager_get_volume (sound_type_e type, int *volume)
78 {
79         int ret = MM_ERROR_NONE;
80         unsigned int uvolume;
81
82         if (type >= SOUND_TYPE_NUM || type < 0)
83                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
84         if (volume == NULL)
85                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
86
87         ret = mm_sound_volume_get_value(type, &uvolume);
88         if (ret == MM_ERROR_NONE)
89                 *volume = uvolume;
90
91         LOGI("returns : type=%d, volume=%d, ret=%p", type, *volume, ret);
92
93         return __convert_sound_manager_error_code(__func__, ret);
94 }
95
96 int sound_manager_set_current_sound_type (sound_type_e type)
97 {
98         int ret = MM_ERROR_NONE;
99
100         if (type >= SOUND_TYPE_NUM || type < 0)
101                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
102
103         ret = mm_sound_volume_primary_type_set(type);
104
105         return __convert_sound_manager_error_code(__func__, ret);
106 }
107
108 int sound_manager_get_current_sound_type (sound_type_e *type)
109 {
110         int ret = MM_ERROR_NONE;
111         volume_type_t mm_sound_vol_type = VOLUME_TYPE_UNKNOWN;
112         char *volume_type = NULL;
113
114         if (type == NULL)
115                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
116
117         ret  = mm_sound_volume_primary_type_get(&mm_sound_vol_type);
118         if (ret == MM_ERROR_NONE) {
119                 if (mm_sound_vol_type == VOLUME_TYPE_UNKNOWN) {
120                         /* get the volume type of the current playing stream */
121                         ret = __get_current_volume_type ("out", &volume_type);
122                         if (ret == MM_ERROR_NONE) {
123                                 ret = __convert_sound_type_to_enum (volume_type, type);
124                                 free(volume_type);
125                         }
126                 } else {
127                         *type = mm_sound_vol_type;
128                 }
129         }
130         LOGI("returns : type=%d, ret=%p", *type, ret);
131
132         return __convert_sound_manager_error_code(__func__, ret);
133 }
134
135 int sound_manager_unset_current_sound_type (void)
136 {
137         int ret = MM_ERROR_NONE;
138
139         ret = mm_sound_volume_primary_type_set(VOLUME_TYPE_UNKNOWN);
140
141         return __convert_sound_manager_error_code(__func__, ret);
142 }
143
144 int sound_manager_set_volume_changed_cb (sound_manager_volume_changed_cb callback, void* user_data)
145 {
146         int ret = MM_ERROR_NONE;
147         unsigned int subs_id = 0;
148
149         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_volume_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
150
151         ret = mm_sound_add_volume_changed_callback((mm_sound_volume_changed_cb)callback, user_data, &subs_id);
152         if (ret == MM_ERROR_NONE) {
153                 g_volume_changed_cb_table.subs_id = subs_id;
154                 g_volume_changed_cb_table.user_cb = (sound_manager_volume_changed_cb)callback;
155                 g_volume_changed_cb_table.user_data = user_data;
156         }
157
158         SM_LEAVE_CRITICAL_SECTION(&g_volume_cb_mutex);
159
160         return __convert_sound_manager_error_code(__func__, ret);
161 }
162
163 int sound_manager_unset_volume_changed_cb (void)
164 {
165         int ret = MM_ERROR_NONE;
166
167         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_volume_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
168
169         if (g_volume_changed_cb_table.subs_id > 0) {
170                 ret = mm_sound_remove_volume_changed_callback(g_volume_changed_cb_table.subs_id);
171                 if (ret == MM_ERROR_NONE) {
172                         g_volume_changed_cb_table.subs_id = 0;
173                         g_volume_changed_cb_table.user_cb = NULL;
174                         g_volume_changed_cb_table.user_data = NULL;
175                 }
176         } else {
177                 ret = MM_ERROR_SOUND_INTERNAL;
178         }
179
180         SM_LEAVE_CRITICAL_SECTION(&g_volume_cb_mutex);
181
182         return __convert_sound_manager_error_code(__func__, ret);
183 }
184
185 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)
186 {
187         int ret = MM_ERROR_NONE;
188
189         LOGI(">> enter");
190
191         SM_NULL_ARG_CHECK(stream_info);
192         SM_NULL_ARG_CHECK(callback);
193
194         if (g_session_interrupt_cb_table.is_registered)
195                 return __convert_sound_manager_error_code(__func__, MM_ERROR_SOUND_INTERNAL);
196
197         sound_stream_info_s *stream_h = malloc(sizeof(sound_stream_info_s));
198         if (!stream_h) {
199                 ret = MM_ERROR_OUT_OF_MEMORY;
200         } else {
201                 memset(stream_h, 0, sizeof(sound_stream_info_s));
202                 ret = __convert_stream_type(stream_type, &stream_h->stream_type);
203                 if (ret == MM_ERROR_NONE) {
204                         ret = _make_pa_connection_and_register_focus(stream_h, callback, user_data);
205                         if (ret == MM_ERROR_NONE) {
206                                 *stream_info = (sound_stream_info_h)stream_h;
207                                 LOGI("<< leave : stream_h(%p), index(%u), user_cb(%p), cnt(%d), ret(%p)", stream_h, stream_h->index, stream_h->user_cb, g_stream_info_count, ret);
208                         }
209                 }
210                 if (ret) {
211                         free(stream_h);
212                 }
213         }
214
215         return __convert_sound_manager_error_code(__func__, ret);
216 }
217
218 int sound_manager_destroy_stream_information (sound_stream_info_h stream_info)
219 {
220         int ret = MM_ERROR_NONE;
221         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
222
223         LOGI(">> enter");
224
225         SM_INSTANCE_CHECK(stream_h);
226
227         ret = _destroy_pa_connection_and_unregister_focus(stream_h);
228
229         LOGI("<< leave : cnt(%d), ret(%p)", g_stream_info_count, ret);
230
231         return __convert_sound_manager_error_code(__func__, ret);
232 }
233
234 int sound_manager_add_device_for_stream_routing (sound_stream_info_h stream_info, sound_device_h device)
235 {
236         int ret = MM_ERROR_NONE;
237         int i = 0;
238         int j = 0;
239         bool added_successfully = false;
240         char *device_type_str = NULL;
241         int device_id = 0;
242         mm_sound_device_type_e device_type;
243         mm_sound_device_io_direction_e device_direction;
244         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
245
246         LOGI(">> enter");
247
248         SM_INSTANCE_CHECK(stream_h);
249         SM_NULL_ARG_CHECK(device);
250
251         if (stream_h->stream_conf_info.route_type == STREAM_ROUTE_TYPE_MANUAL) {
252                 ret = mm_sound_get_device_id(device, &device_id);
253                 if (ret) {
254                         return __convert_sound_manager_error_code(__func__, ret);
255                 }
256                 ret = mm_sound_get_device_type(device, &device_type);
257                 if (ret) {
258                         return __convert_sound_manager_error_code(__func__, ret);
259                 }
260                 ret = __convert_device_type(device_type, &device_type_str);
261                 if (ret) {
262                         return __convert_sound_manager_error_code(__func__, ret);
263                 }
264                 ret = mm_sound_get_device_io_direction(device, &device_direction);
265                 if (ret) {
266                         return __convert_sound_manager_error_code(__func__, ret);
267                 }
268                 if (device_direction == MM_SOUND_DEVICE_IO_DIRECTION_IN || device_direction == MM_SOUND_DEVICE_IO_DIRECTION_BOTH) {
269                         for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
270                                 if (stream_h->stream_conf_info.avail_in_devices[i]) {
271                                         if (!strncmp(stream_h->stream_conf_info.avail_in_devices[i], device_type_str, SOUND_DEVICE_TYPE_LEN)) {
272                                                 for (j = 0; j < AVAIL_DEVICES_MAX; j++) {
273                                                         if (!stream_h->manual_route_info.route_in_devices[j]) {
274                                                                 stream_h->manual_route_info.route_in_devices[j] = (unsigned int)device_id;
275                                                                 added_successfully = true;
276                                                                 break;
277                                                         }
278                                                         if (stream_h->manual_route_info.route_in_devices[j] == (unsigned int)device_id) {
279                                                                 /* it was already set */
280                                                                 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_DUPLICATED);
281                                                         }
282                                                 }
283                                         }
284                                 } else {
285                                         break;
286                                 }
287                         }
288                 }
289                 if (device_direction == MM_SOUND_DEVICE_IO_DIRECTION_OUT || device_direction == MM_SOUND_DEVICE_IO_DIRECTION_BOTH) {
290                         for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
291                                 if (stream_h->stream_conf_info.avail_out_devices[i]) {
292                                         if (!strncmp(stream_h->stream_conf_info.avail_out_devices[i], device_type_str, SOUND_DEVICE_TYPE_LEN)) {
293                                                 for (j = 0; j < AVAIL_DEVICES_MAX; j++) {
294                                                         if (!stream_h->manual_route_info.route_out_devices[j]) {
295                                                                 stream_h->manual_route_info.route_out_devices[j] = (unsigned int)device_id;
296                                                                 added_successfully = true;
297                                                                 break;
298                                                         }
299                                                         if (stream_h->manual_route_info.route_out_devices[j] == (unsigned int)device_id) {
300                                                                 /* it was already set */
301                                                                 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_DUPLICATED);
302                                                         }
303                                                 }
304                                         }
305                                 } else {
306                                         break;
307                                 }
308                         }
309                 }
310         }
311
312         if (!added_successfully) {
313                 ret = MM_ERROR_POLICY_INTERNAL;
314         }
315
316         LOGI("<< leave : ret(%p)", ret);
317
318         return __convert_sound_manager_error_code(__func__, ret);
319 }
320
321 int sound_manager_remove_device_for_stream_routing (sound_stream_info_h stream_info, sound_device_h device)
322 {
323         int ret = MM_ERROR_NONE;
324         int i = 0;
325         int j = 0;
326         bool removed_successfully = false;
327         char *device_type_str = NULL;
328         int device_id = 0;
329         mm_sound_device_type_e device_type;
330         mm_sound_device_io_direction_e device_direction;
331         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
332
333         LOGI(">> enter");
334
335         SM_INSTANCE_CHECK(stream_h);
336         SM_NULL_ARG_CHECK(device);
337
338         if (stream_h->stream_conf_info.route_type == STREAM_ROUTE_TYPE_MANUAL) {
339                 ret = mm_sound_get_device_id(device, &device_id);
340                 if (ret) {
341                         return __convert_sound_manager_error_code(__func__, ret);
342                 }
343                 ret = mm_sound_get_device_type(device, &device_type);
344                 if (ret) {
345                         return __convert_sound_manager_error_code(__func__, ret);
346                 }
347                 ret = __convert_device_type(device_type, &device_type_str);
348                 ret = mm_sound_get_device_io_direction(device, &device_direction);
349                 if (ret) {
350                         return __convert_sound_manager_error_code(__func__, ret);
351                 }
352                 if (device_direction == MM_SOUND_DEVICE_IO_DIRECTION_IN || device_direction == MM_SOUND_DEVICE_IO_DIRECTION_BOTH) {
353                         for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
354                                 if (stream_h->stream_conf_info.avail_in_devices[i]) {
355                                         if (!strncmp(stream_h->stream_conf_info.avail_in_devices[i], device_type_str, SOUND_DEVICE_TYPE_LEN)) {
356                                                 for (j = 0; j < AVAIL_DEVICES_MAX; j++) {
357                                                         if (stream_h->manual_route_info.route_in_devices[j] == (unsigned int)device_id) {
358                                                                 removed_successfully = true;
359                                                                 stream_h->manual_route_info.route_in_devices[j] = 0;
360                                                                 break;
361                                                         }
362                                                 }
363                                         }
364                                 } else {
365                                         break;
366                                 }
367                         }
368                 }
369                 if (device_direction == MM_SOUND_DEVICE_IO_DIRECTION_OUT || device_direction == MM_SOUND_DEVICE_IO_DIRECTION_BOTH) {
370                         for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
371                                 if (stream_h->stream_conf_info.avail_out_devices[i]) {
372                                         if (!strncmp(stream_h->stream_conf_info.avail_out_devices[i], device_type_str, SOUND_DEVICE_TYPE_LEN)) {
373                                                 for (j = 0; j < AVAIL_DEVICES_MAX; j++) {
374                                                         if (stream_h->manual_route_info.route_out_devices[j] == (unsigned int)device_id) {
375                                                                 removed_successfully = true;
376                                                                 stream_h->manual_route_info.route_out_devices[j] = 0;
377                                                                 break;
378                                                         }
379                                                 }
380                                         }
381                                 } else {
382                                         break;
383                                 }
384                         }
385                 }
386         }
387
388         if (!removed_successfully) {
389                 ret = MM_ERROR_INVALID_ARGUMENT;
390         }
391
392         LOGI("<< leave : ret(%p)", ret);
393
394         return __convert_sound_manager_error_code(__func__, ret);
395 }
396
397 int sound_manager_apply_stream_routing (sound_stream_info_h stream_info)
398 {
399         int ret = MM_ERROR_NONE;
400         int i = 0;
401         bool need_to_apply = false;
402         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
403
404         LOGI(">> enter");
405
406         SM_INSTANCE_CHECK(stream_h);
407
408         if (stream_h->stream_conf_info.route_type == STREAM_ROUTE_TYPE_MANUAL) {
409                 for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
410                         if (stream_h->manual_route_info.route_in_devices[i]) {
411                                 need_to_apply = true;
412                                 break;
413                         }
414                         if (stream_h->manual_route_info.route_out_devices[i]) {
415                                 need_to_apply = true;
416                                 break;
417                         }
418                 }
419                 if (need_to_apply) {
420                         ret = __set_manual_route_info(stream_h->index, &stream_h->manual_route_info);
421                 } else {
422                         __convert_sound_manager_error_code(__func__, MM_ERROR_SOUND_INVALID_STATE);
423                 }
424         } else {
425                 ret = MM_ERROR_SOUND_INVALID_STATE;
426         }
427
428         LOGI("<< leave : ret(%p)", ret);
429
430         return __convert_sound_manager_error_code(__func__, ret);
431 }
432
433 int sound_manager_acquire_focus (sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask, const char *additional_info)
434 {
435         int ret = MM_ERROR_NONE;
436         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
437
438         LOGI(">> enter");
439
440         SM_INSTANCE_CHECK(stream_h);
441
442         ret = mm_sound_acquire_focus(stream_h->index, (mm_sound_focus_type_e)focus_mask, additional_info);
443         if (ret == MM_ERROR_NONE) {
444                 stream_h->acquired_focus |= focus_mask;
445                 __update_focus_status(stream_h->index, (unsigned int)stream_h->acquired_focus);
446         }
447
448         LOGI("<< leave : ret(%p)", ret);
449
450         return __convert_sound_manager_error_code(__func__, ret);
451 }
452
453 int sound_manager_release_focus (sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask, const char *additional_info)
454 {
455         int ret = MM_ERROR_NONE;
456         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
457
458         LOGI(">> enter");
459
460         SM_INSTANCE_CHECK(stream_h);
461
462         ret = mm_sound_release_focus(stream_h->index, (mm_sound_focus_type_e)focus_mask, additional_info);
463         if (ret == MM_ERROR_NONE) {
464                 stream_h->acquired_focus &= ~focus_mask;
465                 __update_focus_status(stream_h->index, (unsigned int)stream_h->acquired_focus);
466         }
467
468         LOGI("<< leave : ret(%p)", ret);
469
470         return __convert_sound_manager_error_code(__func__, ret);
471 }
472
473 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)
474 {
475         int ret = MM_ERROR_NONE;
476         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
477
478         LOGI(">> enter");
479
480         SM_INSTANCE_CHECK(stream_h);
481         if (!state_for_playback && !state_for_recording)
482                 ret = MM_ERROR_INVALID_ARGUMENT;
483
484         if (state_for_playback)
485                 *state_for_playback = (stream_h->acquired_focus & SOUND_STREAM_FOCUS_FOR_PLAYBACK)?SOUND_STREAM_FOCUS_STATE_ACQUIRED:SOUND_STREAM_FOCUS_STATE_RELEASED;
486         if (state_for_recording)
487                 *state_for_recording = (stream_h->acquired_focus & SOUND_STREAM_FOCUS_FOR_RECORDING)?SOUND_STREAM_FOCUS_STATE_ACQUIRED:SOUND_STREAM_FOCUS_STATE_RELEASED;
488
489         LOGI("<< leave : acquired_focus(%p)", stream_h->acquired_focus);
490
491         return __convert_sound_manager_error_code(__func__, ret);
492 }
493
494 int sound_manager_set_focus_state_watch_cb (sound_stream_focus_mask_e focus_mask, sound_stream_focus_state_watch_cb callback, void *user_data)
495 {
496         int ret = MM_ERROR_NONE;
497         int id = -1;
498
499         LOGI(">> enter");
500
501         SM_NULL_ARG_CHECK(callback);
502         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, SOUND_MANAGER_ERROR_INTERNAL);
503
504         if (!g_focus_watch_cb_table.user_cb) {
505                 SM_REF_FOR_STREAM_INFO(g_stream_info_count, ret);
506                 ret = mm_sound_set_focus_watch_callback((mm_sound_focus_type_e)focus_mask, _focus_watch_callback, user_data, &id);
507                 if (ret == MM_ERROR_NONE) {
508                         g_focus_watch_cb_table.index = id;
509                         g_focus_watch_cb_table.user_cb = callback;
510                         g_focus_watch_cb_table.user_data = user_data;
511                 }
512         } else {
513                 ret = MM_ERROR_SOUND_INTERNAL;
514         }
515
516         SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
517
518         LOGI("<< leave : cnt(%d), ret(%p)", g_stream_info_count, ret);
519
520         return __convert_sound_manager_error_code(__func__, ret);
521 }
522
523 int sound_manager_unset_focus_state_watch_cb (void)
524 {
525         int ret = MM_ERROR_NONE;
526
527         LOGI(">> enter");
528
529         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, SOUND_MANAGER_ERROR_INTERNAL);
530
531         if (g_focus_watch_cb_table.user_cb) {
532                 ret = mm_sound_unset_focus_watch_callback(g_focus_watch_cb_table.index);
533                 if (ret == MM_ERROR_NONE) {
534                         g_focus_watch_cb_table.index = -1;
535                         g_focus_watch_cb_table.user_cb = NULL;
536                         g_focus_watch_cb_table.user_data = NULL;
537                         SM_UNREF_FOR_STREAM_INFO(g_stream_info_count, ret);
538                 } else {
539                         ret = MM_ERROR_SOUND_INTERNAL;
540                 }
541         } else {
542                 ret = MM_ERROR_SOUND_INTERNAL;
543         }
544
545         SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
546
547         LOGI("<< leave : cnt(%d), ret(%p)", g_stream_info_count, ret);
548
549         return __convert_sound_manager_error_code(__func__, ret);
550 }
551
552 int sound_manager_set_session_type (sound_session_type_e type)
553 {
554         int ret = MM_ERROR_NONE;
555         int cur_session = -1;
556         int new_session = MM_SESSION_TYPE_MEDIA;
557
558         LOGI(">> enter : type=%d", type);
559
560         if (type < SOUND_SESSION_TYPE_MEDIA || type >  SOUND_SESSION_TYPE_VOIP)
561                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
562
563         /* it is not supported both session and stream feature at the same time */
564         if (g_stream_info_count)
565                 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
566
567         switch (type) {
568         case SOUND_SESSION_TYPE_MEDIA:
569                 new_session = MM_SESSION_TYPE_MEDIA;
570                 break;
571         case SOUND_SESSION_TYPE_ALARM:
572                 new_session = MM_SESSION_TYPE_ALARM;
573                 break;
574         case SOUND_SESSION_TYPE_NOTIFICATION:
575                 new_session = MM_SESSION_TYPE_NOTIFY;
576                 break;
577         case SOUND_SESSION_TYPE_EMERGENCY:
578                 new_session = MM_SESSION_TYPE_EMERGENCY;
579                 break;
580         case SOUND_SESSION_TYPE_VOIP:
581                 new_session = MM_SESSION_TYPE_VOIP;
582                 break;
583         }
584
585         /* valid session check */
586         ret = mm_session_get_current_type(&cur_session);
587         if (ret == MM_ERROR_NONE) {
588                 if (cur_session == MM_SESSION_TYPE_MEDIA_RECORD) {
589                         if (type > SOUND_SESSION_TYPE_MEDIA) {
590                                 LOGE("<< leave : Could not set this type(%d) during camera/recorder/audio-io(in)/radio", type);
591                                 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
592                         }
593                 }
594                 if (cur_session == MM_SESSION_TYPE_VIDEOCALL ||
595                         cur_session >= MM_SESSION_TYPE_VOICE_RECOGNITION) {
596                         return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
597                 }
598         }
599
600         if (g_session_interrupt_cb_table.is_registered) {
601                 if (new_session == cur_session ||
602                         ((new_session == SOUND_SESSION_TYPE_MEDIA) && (cur_session == MM_SESSION_TYPE_MEDIA_RECORD))) {
603                         LOGI("<< leave : already set type=%d, ret=%p", type, ret);
604                         return SOUND_MANAGER_ERROR_NONE;
605                 } else {
606                         ret = mm_session_finish();
607                         if (ret != MM_ERROR_NONE) {
608                                 return __convert_sound_manager_error_code(__func__, ret);
609                         }
610                         g_session_interrupt_cb_table.is_registered = 0;
611                         g_cached_session_mode = -1;
612                 }
613         }
614         ret = mm_session_init_ex(new_session , __session_interrupt_cb, NULL);
615         if (ret == MM_ERROR_NONE) {
616                 g_session_interrupt_cb_table.is_registered = 1;
617         }
618         if (new_session == MM_SESSION_TYPE_VOIP || new_session == MM_SESSION_TYPE_CALL) {
619                 /* set default sub-session for voip */
620                 ret = mm_session_set_subsession (MM_SUBSESSION_TYPE_RINGTONE, MM_SUBSESSION_OPTION_NONE);
621                 if (ret != MM_ERROR_NONE) {
622                         return __convert_sound_manager_error_code(__func__, ret);
623                 }
624                 g_cached_session_mode = _SESSION_MODE_RINGTONE;
625         }
626         LOGI("<< leave : type=%d, ret=%p", type, ret);
627
628         return __convert_sound_manager_error_code(__func__, ret);
629 }
630
631 int sound_manager_get_session_type (sound_session_type_e *type)
632 {
633         int ret = MM_ERROR_NONE;
634         int cur_session;
635
636         if (type == NULL)
637                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
638         ret = mm_session_get_current_type(&cur_session);
639         if (ret != 0) {
640                 LOGW("session hasn't been set, setting default session");
641                 cur_session = SOUND_SESSION_TYPE_DEFAULT;
642                 ret = mm_session_init_ex(cur_session, __session_interrupt_cb, NULL);
643                 if (ret == 0) {
644                         g_session_interrupt_cb_table.is_registered = 1;
645                 }
646         }
647         if ((cur_session > MM_SESSION_TYPE_EMERGENCY) &&
648                         (cur_session != MM_SESSION_TYPE_VOIP)) {
649                 if (g_cached_session != -1)
650                         cur_session = g_cached_session;
651                 else //will be never reach here. just prevent code
652                         cur_session = SOUND_SESSION_TYPE_DEFAULT;
653         }
654
655         switch (cur_session) {
656         case MM_SESSION_TYPE_MEDIA:
657         case MM_SESSION_TYPE_MEDIA_RECORD:
658                 *type = SOUND_SESSION_TYPE_MEDIA;
659                 break;
660         case MM_SESSION_TYPE_ALARM:
661                 *type = SOUND_SESSION_TYPE_ALARM;
662                 break;
663         case MM_SESSION_TYPE_NOTIFY:
664                 *type = SOUND_SESSION_TYPE_NOTIFICATION;
665                 break;
666         case MM_SESSION_TYPE_EMERGENCY:
667                 *type = SOUND_SESSION_TYPE_EMERGENCY;
668                 break;
669         case MM_SESSION_TYPE_VOIP:
670                 *type = SOUND_SESSION_TYPE_VOIP;
671                 break;
672         default:
673                 *type = cur_session;
674                 break;
675         }
676
677         LOGI("returns : type=%d, ret=%p", *type, ret);
678
679         return 0;
680 }
681
682 int sound_manager_set_media_session_option (sound_session_option_for_starting_e s_option, sound_session_option_for_during_play_e d_option)
683 {
684         int ret = MM_ERROR_NONE;
685         int session = 0;
686         int session_option = 0;
687         int updated = 0;
688
689         LOGI(">> enter : option for starting=%d, for during play=%d", s_option, d_option);
690
691         if (s_option < 0 || s_option >  SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START)
692                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
693         if (d_option < 0 || d_option >  SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY)
694                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
695
696         ret = mm_session_get_current_information(&session, &session_option);
697         if (ret != 0 || !g_session_interrupt_cb_table.is_registered) {
698                 LOGW("session hasn't been set, setting default session");
699                 ret = mm_session_init_ex(MM_SESSION_TYPE_MEDIA, __session_interrupt_cb, NULL);
700                 if (ret == 0) {
701                         g_session_interrupt_cb_table.is_registered = 1;
702                 }
703         } else if (ret == 0 && session > MM_SESSION_TYPE_MEDIA) {
704                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
705                         if (!g_session_interrupt_cb_table.is_registered) {
706                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
707                                 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
708                         }
709                 } else {
710                         return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
711                 }
712         }
713
714         switch (s_option) {
715         case SOUND_SESSION_OPTION_MIX_WITH_OTHERS_WHEN_START:
716                 if (session_option & MM_SESSION_OPTION_PAUSE_OTHERS) {
717                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_PAUSE_OTHERS);
718                         if (ret) {
719                                 return __convert_sound_manager_error_code(__func__, ret);
720                         }
721                         updated = 1;
722                 }
723                 break;
724         case SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START:
725                 if (!(session_option & MM_SESSION_OPTION_PAUSE_OTHERS)) {
726                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_PAUSE_OTHERS);
727                         if (ret) {
728                                 return __convert_sound_manager_error_code(__func__, ret);
729                         }
730                         updated = 1;
731                 }
732                 break;
733         }
734
735         switch (d_option) {
736         case SOUND_SESSION_OPTION_INTERRUPTIBLE_DURING_PLAY:
737                 if (session_option & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
738                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_UNINTERRUPTIBLE);
739                         if (ret) {
740                                 return __convert_sound_manager_error_code(__func__, ret);
741                         }
742                         updated = 1;
743                 }
744                 break;
745         case SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY:
746                 if (!(session_option & MM_SESSION_OPTION_UNINTERRUPTIBLE)) {
747                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_UNINTERRUPTIBLE);
748                         if (ret) {
749                                 return __convert_sound_manager_error_code(__func__, ret);
750                         }
751                         updated = 1;
752                 }
753                 break;
754         }
755
756         if (updated) {
757                 LOGI("<< leave : updated");
758         } else {
759                 LOGI("<< leave : already set same option(%x), skip it", session_option);
760         }
761
762         return __convert_sound_manager_error_code(__func__, ret);
763 }
764
765 int sound_manager_get_media_session_option (sound_session_option_for_starting_e *s_option, sound_session_option_for_during_play_e *d_option)
766 {
767         int ret = MM_ERROR_NONE;
768         int session = 0;
769         int session_options = 0;
770
771         LOGI(">> enter");
772
773         if (s_option == NULL || d_option == NULL)
774                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
775
776         ret = mm_session_get_current_information(&session, &session_options);
777         if (ret != 0) {
778                 ret = mm_session_init_ex(MM_SESSION_TYPE_MEDIA, __session_interrupt_cb, NULL);
779                 if (ret == 0) {
780                         g_session_interrupt_cb_table.is_registered = 1;
781                 }
782         } else if (session > SOUND_SESSION_TYPE_MEDIA) {
783                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
784                         if (!g_session_interrupt_cb_table.is_registered) {
785                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
786                                 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
787                         }
788                 } else {
789                         return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
790                 }
791         }
792         /* get option */
793         if (session_options & MM_SESSION_OPTION_PAUSE_OTHERS) {
794                 *s_option = SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START;
795         } else {
796                 *s_option = SOUND_SESSION_OPTION_MIX_WITH_OTHERS_WHEN_START;
797         }
798         if (session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
799                 *d_option = SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY;
800         } else {
801                 *d_option = SOUND_SESSION_OPTION_INTERRUPTIBLE_DURING_PLAY;
802         }
803
804         LOGI("<< leave : option for starting=%d, for during play=%d", *s_option, *d_option);
805
806         return SOUND_MANAGER_ERROR_NONE;
807 }
808
809 int sound_manager_set_media_session_resumption_option (sound_session_option_for_resumption_e option)
810 {
811         int ret = MM_ERROR_NONE;
812         int session = 0;
813         int session_option = 0;
814         int updated = 0;
815
816         LOGI(">> enter : option for resumption=%d (0:by system, 1:by system or media paused)", option);
817
818         if (option < SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM || option > SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED)
819                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
820
821         ret = mm_session_get_current_information(&session, &session_option);
822         if (ret != 0 || !g_session_interrupt_cb_table.is_registered) {
823                 LOGW("session hasn't been set, setting default session");
824                 ret = mm_session_init_ex(MM_SESSION_TYPE_MEDIA, __session_interrupt_cb, NULL);
825                 if (ret == 0) {
826                         g_session_interrupt_cb_table.is_registered = 1;
827                 }
828         } else if (ret == 0 && session > MM_SESSION_TYPE_MEDIA) {
829                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
830                         if (!g_session_interrupt_cb_table.is_registered) {
831                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
832                                 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
833                         }
834                 } else {
835                         return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
836                 }
837         }
838
839         switch (option) {
840         case SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM:
841                 if (session_option & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED) {
842                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED);
843                         if (ret) {
844                                 return __convert_sound_manager_error_code(__func__, ret);
845                         }
846                         updated = 1;
847                 }
848                 break;
849         case SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED:
850                 if (!(session_option & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED)) {
851                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED);
852                         if (ret) {
853                                 return __convert_sound_manager_error_code(__func__, ret);
854                         }
855                         updated = 1;
856                 }
857                 break;
858         }
859
860         if (updated) {
861                 LOGI("<< leave : updated");
862         } else {
863                 LOGI("<< leave : already set same option(%x), skip it", session_option);
864         }
865
866         return __convert_sound_manager_error_code(__func__, ret);
867 }
868
869 int sound_manager_get_media_session_resumption_option (sound_session_option_for_resumption_e *option)
870 {
871         int ret = MM_ERROR_NONE;
872         int session = 0;
873         int session_options = 0;
874
875         LOGI(">> enter");
876
877         if (option == NULL)
878                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
879         ret = mm_session_get_current_information(&session, &session_options);
880         if (ret != 0) {
881                 LOGW("session hasn't been set, setting default session");
882                 ret = mm_session_init_ex(MM_SESSION_TYPE_MEDIA, __session_interrupt_cb, NULL);
883                 if (ret == 0) {
884                         g_session_interrupt_cb_table.is_registered = 1;
885                 }
886         } else if (session > SOUND_SESSION_TYPE_MEDIA) {
887                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
888                         if (!g_session_interrupt_cb_table.is_registered) {
889                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
890                                 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
891                         }
892                 } else {
893                         return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
894                 }
895         }
896         /* get option */
897         if (session_options & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED) {
898                 *option = SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED;
899         } else {
900                 *option = SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM;
901         }
902
903         LOGI("<< leave : option for resumption=%d (0:by system, 1:by system or media paused)", *option);
904
905         return SOUND_MANAGER_ERROR_NONE;
906 }
907
908 int sound_manager_set_voip_session_mode (sound_session_voip_mode_e mode)
909 {
910         int ret = MM_ERROR_NONE;
911         int session = 0;
912         int session_options = 0;
913
914         LOGI(">> enter : mode=%d", mode);
915
916         ret = mm_session_get_current_information(&session, &session_options);
917         if (ret != MM_ERROR_NONE) {
918                 return __convert_sound_manager_error_code(__func__, ret);
919         } else if (session != MM_SESSION_TYPE_VOIP) {
920                 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
921         }
922         if (mode < SOUND_SESSION_VOIP_MODE_RINGTONE || mode > SOUND_SESSION_VOIP_MODE_VOICE_WITH_BLUETOOTH) {
923                 ret = MM_ERROR_INVALID_ARGUMENT;
924                 return __convert_sound_manager_error_code(__func__, ret);
925         }
926         ret = __set_session_mode ((_session_mode_e)mode);
927
928 #ifdef TMP_CODE
929         /* temporary code. When 2.4 feature for routing is fully implemented, it will be removed. */
930         tmp_mode = mode;
931 #endif
932
933         LOGI("<< leave : session=%p, mode=%d, ret=%p", session, mode, ret);
934
935         return __convert_sound_manager_error_code(__func__, ret);
936 }
937
938 int sound_manager_get_voip_session_mode (sound_session_voip_mode_e *mode)
939 {
940         int ret = MM_ERROR_NONE;
941         int session = 0;
942         int session_options = 0;
943 #ifndef TMP_CODE
944         _session_mode_e _mode = 0;
945 #endif
946
947         if (mode == NULL) {
948                 LOGI("mode is null");
949                 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
950         }
951
952         ret = mm_session_get_current_information(&session, &session_options);
953         if (ret != MM_ERROR_NONE) {
954                 LOGI("session = %d, option = %d", session, session_options);
955                 return __convert_sound_manager_error_code(__func__, ret);
956         } else if (session != MM_SESSION_TYPE_VOIP) {
957                 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
958         }
959
960 #ifdef TMP_CODE
961         /* temporary code. When 2.4 feature for routing is fully implemented, it will be removed. */
962         *mode = tmp_mode;
963 #else
964         ret = __get_session_mode(&_mode);
965         if (ret == MM_ERROR_NONE)
966                 *mode = (sound_session_voip_mode_e)_mode;
967 #endif
968
969         LOGI("returns : session=%p, mode=%d, ret=%p", session, *mode, ret);
970
971         return __convert_sound_manager_error_code(__func__, ret);
972 }
973
974 int sound_manager_set_session_interrupted_cb (sound_session_interrupted_cb callback, void *user_data)
975 {
976         int ret = MM_ERROR_NONE;
977         unsigned int subs_id = 0;
978
979         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_interrupt_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
980
981         if (callback == NULL) {
982                 ret = MM_ERROR_INVALID_ARGUMENT;
983                 goto finish;
984         }
985
986         /* it is not supported both session and stream feature at the same time */
987         if (g_stream_info_count) {
988                 ret =  MM_ERROR_POLICY_INTERNAL;
989                 goto finish;
990         }
991
992         if (g_session_interrupt_cb_table.is_registered == 0) {
993                 ret = mm_sound_add_device_connected_callback(SOUND_DEVICE_ALL_MASK, (mm_sound_device_connected_cb)_device_connected_cb, NULL, &subs_id);
994                 if (ret)
995                         goto finish;
996                 ret = mm_sound_focus_set_session_interrupt_callback((mm_sound_focus_session_interrupt_cb)_focus_session_interrupt_cb, NULL);
997                 if (ret) {
998                         if(mm_sound_remove_device_connected_callback(subs_id) != MM_ERROR_NONE)
999                                 LOGW("mm_sound_remove_device_connected_callback failed");
1000                         goto finish;
1001                 }
1002                 g_session_interrupt_cb_table.is_registered = 1;
1003                 g_session_interrupt_cb_table.subs_id = subs_id;
1004         }
1005
1006         g_session_interrupt_cb_table.user_cb = (sound_session_interrupted_cb)callback;
1007         g_session_interrupt_cb_table.user_data = user_data;
1008
1009 finish:
1010         SM_LEAVE_CRITICAL_SECTION(&g_interrupt_cb_mutex);
1011         return __convert_sound_manager_error_code(__func__, ret);
1012 }
1013
1014 int sound_manager_unset_session_interrupted_cb (void)
1015 {
1016         int ret = MM_ERROR_NONE;
1017
1018         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_interrupt_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1019
1020         if (g_session_interrupt_cb_table.user_cb) {
1021                 ret = mm_sound_focus_unset_session_interrupt_callback();
1022                 if (ret) {
1023                         if(mm_sound_remove_device_connected_callback(g_session_interrupt_cb_table.subs_id) != MM_ERROR_NONE)
1024                                 LOGW("mm_sound_remove_device_connected_callback failed");
1025                         goto finish;
1026                 }
1027                 ret = mm_sound_remove_device_connected_callback(g_session_interrupt_cb_table.subs_id);
1028                 if (ret)
1029                         goto finish;
1030                 g_session_interrupt_cb_table.subs_id = 0;
1031                 g_session_interrupt_cb_table.user_cb = NULL;
1032                 g_session_interrupt_cb_table.user_data = NULL;
1033                 g_session_interrupt_cb_table.is_registered = 0;
1034         } else {
1035                 ret = MM_ERROR_SOUND_INTERNAL;
1036         }
1037
1038 finish:
1039         SM_LEAVE_CRITICAL_SECTION(&g_interrupt_cb_mutex);
1040         return __convert_sound_manager_error_code(__func__, ret);
1041 }
1042
1043 int sound_manager_get_current_device_list (sound_device_mask_e device_mask, sound_device_list_h *device_list)
1044 {
1045         int ret = MM_ERROR_NONE;
1046         ret = mm_sound_get_current_device_list((mm_sound_device_flags_e)device_mask, device_list);
1047
1048         return __convert_sound_manager_error_code(__func__, ret);
1049 }
1050
1051 int sound_manager_get_next_device (sound_device_list_h device_list, sound_device_h *device)
1052 {
1053         int ret = MM_ERROR_NONE;
1054         ret = mm_sound_get_next_device(device_list, device);
1055
1056         return __convert_sound_manager_error_code(__func__, ret);
1057 }
1058
1059 int sound_manager_get_prev_device (sound_device_list_h device_list, sound_device_h *device)
1060 {
1061         int ret = MM_ERROR_NONE;
1062         ret = mm_sound_get_prev_device(device_list, device);
1063
1064         return __convert_sound_manager_error_code(__func__, ret);
1065 }
1066
1067 int sound_manager_get_device_type (sound_device_h device, sound_device_type_e *type)
1068 {
1069         int ret = MM_ERROR_NONE;
1070         ret = mm_sound_get_device_type(device, (mm_sound_device_type_e*)type);
1071
1072         return __convert_sound_manager_error_code(__func__, ret);
1073 }
1074
1075 int sound_manager_get_device_io_direction (sound_device_h device, sound_device_io_direction_e *io_direction)
1076 {
1077         int ret = MM_ERROR_NONE;
1078         mm_sound_device_io_direction_e mm_sound_io_direction;
1079         ret = mm_sound_get_device_io_direction(device, &mm_sound_io_direction);
1080         if (ret == MM_ERROR_NONE) {
1081                 ret = __convert_device_io_direction(mm_sound_io_direction, io_direction);
1082         }
1083
1084         return __convert_sound_manager_error_code(__func__, ret);
1085 }
1086
1087 int sound_manager_get_device_id (sound_device_h device, int *id)
1088 {
1089         int ret = MM_ERROR_NONE;
1090         ret = mm_sound_get_device_id(device, id);
1091
1092         return __convert_sound_manager_error_code(__func__, ret);
1093 }
1094
1095 int sound_manager_get_device_name (sound_device_h device, char **name)
1096 {
1097         int ret = MM_ERROR_NONE;
1098         ret = mm_sound_get_device_name(device, name);
1099
1100         return __convert_sound_manager_error_code(__func__, ret);
1101 }
1102
1103 int sound_manager_get_device_state (sound_device_h device, sound_device_state_e *state)
1104 {
1105         int ret = MM_ERROR_NONE;
1106         ret = mm_sound_get_device_state(device, (mm_sound_device_state_e*)state);
1107
1108         return __convert_sound_manager_error_code(__func__, ret);
1109 }
1110
1111 int sound_manager_set_device_connected_cb (sound_device_mask_e device_mask, sound_device_connected_cb callback, void *user_data)
1112 {
1113         int ret = MM_ERROR_NONE;
1114         unsigned int subs_id = 0;
1115
1116         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_conn_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1117
1118         ret = mm_sound_add_device_connected_callback((mm_sound_device_flags_e)device_mask, (mm_sound_device_connected_cb)callback, user_data, &subs_id);
1119         if (ret == MM_ERROR_NONE) {
1120                 g_device_connected_cb_table.subs_id = subs_id;
1121                 g_device_connected_cb_table.user_cb = (sound_device_connected_cb)callback;
1122                 g_device_connected_cb_table.user_data = user_data;
1123         }
1124
1125         SM_LEAVE_CRITICAL_SECTION(&g_device_conn_cb_mutex);
1126
1127         return __convert_sound_manager_error_code(__func__, ret);
1128 }
1129
1130 int sound_manager_unset_device_connected_cb (void)
1131 {
1132         int ret = MM_ERROR_NONE;
1133
1134         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_conn_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1135
1136         if (g_device_connected_cb_table.subs_id > 0) {
1137                 ret = mm_sound_remove_device_connected_callback(g_device_connected_cb_table.subs_id);
1138                 if (ret == MM_ERROR_NONE) {
1139                         g_device_connected_cb_table.subs_id = 0;
1140                         g_device_connected_cb_table.user_cb = NULL;
1141                         g_device_connected_cb_table.user_data = NULL;
1142                 }
1143         } else {
1144                 ret = MM_ERROR_SOUND_INTERNAL;
1145         }
1146
1147         SM_LEAVE_CRITICAL_SECTION(&g_device_conn_cb_mutex);
1148
1149         return __convert_sound_manager_error_code(__func__, ret);
1150 }
1151
1152 int sound_manager_set_device_information_changed_cb (sound_device_mask_e device_mask, sound_device_information_changed_cb callback, void *user_data)
1153 {
1154         int ret = MM_ERROR_NONE;
1155         unsigned int subs_id = 0;
1156
1157         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_info_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1158
1159         ret = mm_sound_add_device_information_changed_callback((mm_sound_device_flags_e)device_mask, (mm_sound_device_info_changed_cb)callback, user_data, &subs_id);
1160         if (ret == MM_ERROR_NONE) {
1161                 g_device_info_changed_cb_table.subs_id = subs_id;
1162                 g_device_info_changed_cb_table.user_cb = (sound_device_information_changed_cb)callback;
1163                 g_device_info_changed_cb_table.user_data = user_data;
1164         }
1165
1166         SM_LEAVE_CRITICAL_SECTION(&g_device_info_cb_mutex);
1167
1168         return __convert_sound_manager_error_code(__func__, ret);
1169 }
1170
1171 int sound_manager_unset_device_information_changed_cb (void)
1172 {
1173         int ret = MM_ERROR_NONE;
1174
1175         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_info_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1176
1177         if (g_device_info_changed_cb_table.subs_id) {
1178                 ret = mm_sound_remove_device_information_changed_callback(g_device_info_changed_cb_table.subs_id);
1179                 if (ret == MM_ERROR_NONE) {
1180                         g_device_info_changed_cb_table.subs_id = 0;
1181                         g_device_info_changed_cb_table.user_cb = NULL;
1182                         g_device_info_changed_cb_table.user_data = NULL;
1183                 }
1184         } else {
1185                 ret = MM_ERROR_SOUND_INTERNAL;
1186         }
1187
1188         SM_LEAVE_CRITICAL_SECTION(&g_device_info_cb_mutex);
1189
1190         return __convert_sound_manager_error_code(__func__, ret);
1191 }
1192
1193 __attribute__ ((destructor))
1194 void __sound_manager_finalize (void)
1195 {
1196         int ret = MM_ERROR_NONE;
1197
1198         if (g_session_interrupt_cb_table.is_registered) {
1199                 LOGI("<ENTER>");
1200                 ret = mm_session_finish();
1201                 if (ret != MM_ERROR_NONE) {
1202                         LOGE("[%s] failed to mm_session_finish(), ret(%p)", __func__, ret);
1203                 }
1204                 g_session_interrupt_cb_table.is_registered = 0;
1205                 LOGI("<LEAVE>");
1206         }
1207 }
1208
1209 __attribute__ ((constructor))
1210 void __sound_manager_initialize (void)
1211 {
1212
1213 }