Divide case for registering focus node depending on session backward compatibility
[platform/core/api/sound-manager.git] / src / sound_manager_private.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 #include <mm_sound.h>
20 #include <vconf.h>
21
22 #define PA_BUS_NAME                                             "org.pulseaudio.Server"
23 #define PA_STREAM_MANAGER_OBJECT_PATH                           "/org/pulseaudio/StreamManager"
24 #define PA_STREAM_MANAGER_INTERFACE                             "org.pulseaudio.StreamManager"
25 #define PA_STREAM_MANAGER_METHOD_NAME_GET_STREAM_INFO           "GetStreamInfo"
26 #define PA_STREAM_MANAGER_METHOD_NAME_SET_STREAM_ROUTE_DEVICES  "SetStreamRouteDevices"
27 #define PA_STREAM_MANAGER_METHOD_NAME_SET_STREAM_ROUTE_OPTION   "SetStreamRouteOption"
28 #define PA_STREAM_MANAGER_METHOD_NAME_GET_VOLUME_MAX_LEVEL      "GetVolumeMaxLevel"
29 #define PA_STREAM_MANAGER_METHOD_NAME_GET_VOLUME_LEVEL          "GetVolumeLevel"
30 #define PA_STREAM_MANAGER_METHOD_NAME_SET_VOLUME_LEVEL          "SetVolumeLevel"
31 #define PA_STREAM_MANAGER_METHOD_NAME_GET_CURRENT_VOLUME_TYPE   "GetCurrentVolumeType"
32 #define PA_STREAM_MANAGER_METHOD_NAME_GET_CURRENT_MEDIA_ROUTING_PATH "GetCurrentMediaRoutingPath"
33 #define PA_STREAM_MANAGER_METHOD_NAME_UPDATE_FOCUS_STATUS       "UpdateFocusStatus"
34 #define VCONF_PATH_PREFIX_VOLUME                                "file/private/sound/volume/"
35 #define VCONF_PATH_MAX                                          64
36
37 extern _session_interrupt_info_s g_session_interrupt_cb_table;
38 extern _session_mode_e g_cached_session_mode;
39 extern int g_cached_voip_device_id;
40 extern _focus_watch_info_s focus_watch_info_arr[SOUND_STREAM_INFO_ARR_MAX];
41 sound_stream_info_s *sound_stream_info_arr[SOUND_STREAM_INFO_ARR_MAX];
42 sound_stream_info_s *g_voip_stream_info = NULL;
43 virtual_sound_stream_info_s *g_voip_vstream_h = NULL;
44 int g_stream_info_count = 0;
45 pthread_mutex_t g_stream_info_count_mutex = PTHREAD_MUTEX_INITIALIZER;
46
47 int _convert_sound_manager_error_code(const char *func, int code)
48 {
49         int ret = SOUND_MANAGER_ERROR_NONE;
50         char *errorstr = NULL;
51
52         switch (code) {
53         case MM_ERROR_FILE_WRITE:
54         case MM_ERROR_INVALID_HANDLE:
55         case MM_ERROR_SOUND_INVALID_OPERATION:
56                 ret = SOUND_MANAGER_ERROR_INVALID_OPERATION;
57                 errorstr = "INVALID_OPERATION";
58                 break;
59         case MM_ERROR_NONE:
60                 ret = SOUND_MANAGER_ERROR_NONE;
61                 errorstr = "ERROR_NONE";
62                 break;
63         case MM_ERROR_INVALID_ARGUMENT:
64         case MM_ERROR_SOUND_INVALID_POINTER:
65                 ret = SOUND_MANAGER_ERROR_INVALID_PARAMETER;
66                 errorstr = "INVALID_PARAMETER";
67                 break;
68         case MM_ERROR_SOUND_PERMISSION_DENIED:
69                 ret = SOUND_MANAGER_ERROR_PERMISSION_DENIED;
70                 errorstr = "PERMISSION_DENIED";
71                 break;
72         case MM_ERROR_SOUND_NO_DATA:
73                 ret = SOUND_MANAGER_ERROR_NO_DATA;
74                 errorstr = "NO_DATA";
75                 break;
76         case MM_ERROR_SOUND_INTERNAL:
77         case MM_ERROR_SOUND_VOLUME_CAPTURE_ONLY:
78         case MM_ERROR_OUT_OF_MEMORY:
79                 ret = SOUND_MANAGER_ERROR_INTERNAL;
80                 errorstr = "INTERNAL";
81                 break;
82         case MM_ERROR_POLICY_DUPLICATED:
83         case MM_ERROR_POLICY_INTERNAL:
84         case MM_ERROR_POLICY_BLOCKED:
85                 ret = SOUND_MANAGER_ERROR_POLICY;
86                 errorstr = "POLICY";
87                 break;
88         case MM_ERROR_SOUND_VOLUME_NO_INSTANCE:
89                 ret = SOUND_MANAGER_ERROR_NO_PLAYING_SOUND;
90                 errorstr = "NO_PLAYING_SOUND";
91                 break;
92         case MM_ERROR_NOT_SUPPORT_API:
93                 ret = SOUND_MANAGER_ERROR_NOT_SUPPORTED;
94                 errorstr = "NOT_SUPPORTED";
95                 break;
96         case MM_ERROR_SOUND_INVALID_STATE:
97                 ret = SOUND_MANAGER_ERROR_INVALID_STATE;
98                 errorstr = "INVALID_STATE";
99                 break;
100         default:
101                 LOGW("it should not be reached here, this error(0x%x) should be defined.", code);
102                 ret = SOUND_MANAGER_ERROR_INTERNAL;
103                 errorstr = "INTERNAL";
104                 break;
105         }
106         if (ret)
107                 LOGE("[%s] >> leave : %s(0x%08x), mm_error(0x%08x)", func, errorstr, ret, code);
108         else
109                 LOGD("[%s] >> leave : %s(0x%08x)", func, errorstr, ret);
110
111         return ret;
112 }
113
114 int _convert_stream_type(sound_stream_type_e stream_type_enum, char **stream_type)
115 {
116         int ret = MM_ERROR_NONE;
117
118         if (stream_type == NULL)
119                 return MM_ERROR_INVALID_ARGUMENT;
120
121         switch (stream_type_enum) {
122         case SOUND_STREAM_TYPE_MEDIA:
123                 *stream_type = "media";
124                 break;
125         case SOUND_STREAM_TYPE_SYSTEM:
126                 *stream_type = "system";
127                 break;
128         case SOUND_STREAM_TYPE_ALARM:
129                 *stream_type = "alarm";
130                 break;
131         case SOUND_STREAM_TYPE_NOTIFICATION:
132                 *stream_type = "notification";
133                 break;
134         case SOUND_STREAM_TYPE_EMERGENCY:
135                 *stream_type = "emergency";
136                 break;
137         case SOUND_STREAM_TYPE_VOICE_INFORMATION:
138                 *stream_type = "voice-information";
139                 break;
140         case SOUND_STREAM_TYPE_VOICE_RECOGNITION:
141                 *stream_type = "voice-recognition";
142                 break;
143         case SOUND_STREAM_TYPE_RINGTONE_VOIP:
144                 *stream_type = "ringtone-voip";
145                 break;
146         case SOUND_STREAM_TYPE_VOIP:
147                 *stream_type = "voip";
148                 break;
149         case SOUND_STREAM_TYPE_MEDIA_EXTERNAL_ONLY:
150                 *stream_type = "ext-media";
151                 break;
152         default:
153                 LOGE("could not find the stream_type[%d] in this switch case statement", stream_type_enum);
154                 ret = MM_ERROR_SOUND_INTERNAL;
155                 break;
156         }
157         LOGI("stream_type[%s]", *stream_type);
158
159         return ret;
160 }
161
162 int _convert_stream_type_for_internal(sound_stream_type_internal_e stream_type_enum, char **stream_type)
163 {
164         int ret = MM_ERROR_NONE;
165
166         if (stream_type == NULL)
167                 return MM_ERROR_INVALID_ARGUMENT;
168
169         switch (stream_type_enum) {
170         case SOUND_STREAM_TYPE_RINGTONE_CALL:
171                 *stream_type = "ringtone-call";
172                 break;
173         case SOUND_STREAM_TYPE_RINGBACKTONE_CALL:
174                 *stream_type = "ringbacktone-call";
175                 break;
176         case SOUND_STREAM_TYPE_VOICE_CALL:
177                 *stream_type = "call-voice";
178                 break;
179         case SOUND_STREAM_TYPE_VIDEO_CALL:
180                 *stream_type = "call-video";
181                 break;
182         case SOUND_STREAM_TYPE_RADIO:
183                 *stream_type = "radio";
184                 break;
185         case SOUND_STREAM_TYPE_LOOPBACK:
186                 *stream_type = "loopback";
187                 break;
188         case SOUND_STREAM_TYPE_LOOPBACK_MIRRORING:
189                 *stream_type = "loopback-mirroring";
190                 break;
191         case SOUND_STREAM_TYPE_SOLO:
192                 *stream_type = "solo";
193                 break;
194         default:
195                 LOGE("could not find the stream_type[%d] in this switch case statement", stream_type_enum);
196                 ret = MM_ERROR_SOUND_INTERNAL;
197                 break;
198         }
199         LOGI("stream_type_for_internal[%s]", *stream_type);
200
201         return ret;
202 }
203
204 void _set_focus_availability(sound_stream_info_s *stream_info)
205 {
206         if (stream_info == NULL || stream_info->stream_type == NULL) {
207                 LOGE("invalid argument");
208                 return;
209         }
210         if (!strncmp(stream_info->stream_type, "solo", SOUND_STREAM_TYPE_LEN) ||
211                 !strncmp(stream_info->stream_type, "radio", SOUND_STREAM_TYPE_LEN) ||
212                 !strncmp(stream_info->stream_type, "loopback-mirroring", SOUND_STREAM_TYPE_LEN)) {
213                 stream_info->is_focus_unavailable = true;
214                 LOGI("this stream_type[%s] does not support focus", stream_info->stream_type);
215         }
216
217         return;
218 }
219
220 int _convert_stream_type_to_change_reason(const char *stream_type, sound_stream_focus_change_reason_e *change_reason)
221 {
222         SM_NULL_ARG_CHECK_FOR_PRIV(stream_type);
223         SM_NULL_ARG_CHECK_FOR_PRIV(change_reason);
224
225         if (!strncmp(stream_type, "media", SOUND_STREAM_TYPE_LEN) ||
226                 !strncmp(stream_type, "radio", SOUND_STREAM_TYPE_LEN) ||
227                 !strncmp(stream_type, "loopback", SOUND_STREAM_TYPE_LEN)) {
228                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA;
229
230         } else if (!strncmp(stream_type, "system", SOUND_STREAM_TYPE_LEN)) {
231                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_SYSTEM;
232
233         } else if (!strncmp(stream_type, "alarm", SOUND_STREAM_TYPE_LEN)) {
234                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_ALARM;
235
236         } else if (!strncmp(stream_type, "notification", SOUND_STREAM_TYPE_LEN)) {
237                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_NOTIFICATION;
238
239         } else if (!strncmp(stream_type, "emergency", SOUND_STREAM_TYPE_LEN)) {
240                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_EMERGENCY;
241
242         } else if (!strncmp(stream_type, "voice-information", SOUND_STREAM_TYPE_LEN)) {
243                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_INFORMATION;
244
245         } else if (!strncmp(stream_type, "voice-recognition", SOUND_STREAM_TYPE_LEN)) {
246                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_RECOGNITION;
247
248         } else if (!strncmp(stream_type, "ringtone-voip", SOUND_STREAM_TYPE_LEN) ||
249                         !strncmp(stream_type, "ringtone-call", SOUND_STREAM_TYPE_LEN) ||
250                         !strncmp(stream_type, "ringbacktone-call", SOUND_STREAM_TYPE_LEN)) {
251                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_RINGTONE;
252
253         } else if (!strncmp(stream_type, "voip", SOUND_STREAM_TYPE_LEN)) {
254                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_VOIP;
255
256         } else if (!strncmp(stream_type, "call-voice", SOUND_STREAM_TYPE_LEN) ||
257                         !strncmp(stream_type, "call-video", SOUND_STREAM_TYPE_LEN)) {
258                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_CALL;
259
260         } else if (!strncmp(stream_type, "ext-media", SOUND_STREAM_TYPE_LEN)) {
261                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA_EXTERNAL_ONLY;
262
263         } else {
264                 LOGE("not supported stream_type(%s)", stream_type);
265                 return MM_ERROR_INVALID_ARGUMENT;
266         }
267
268         return MM_ERROR_NONE;
269 }
270
271 static int _convert_stream_type_to_interrupt_reason(const char *stream_type, sound_session_interrupted_code_e *change_reason)
272 {
273         SM_NULL_ARG_CHECK_FOR_PRIV(stream_type);
274         SM_NULL_ARG_CHECK_FOR_PRIV(change_reason);
275
276         if (!strncmp(stream_type, "media", SOUND_STREAM_TYPE_LEN) ||
277                 !strncmp(stream_type, "radio", SOUND_STREAM_TYPE_LEN) ||
278                 !strncmp(stream_type, "system", SOUND_STREAM_TYPE_LEN) ||
279                 !strncmp(stream_type, "voice-information", SOUND_STREAM_TYPE_LEN) ||
280                 !strncmp(stream_type, "voice-recognition", SOUND_STREAM_TYPE_LEN) ||
281                 !strncmp(stream_type, "loopback", SOUND_STREAM_TYPE_LEN) ||
282                 !strncmp(stream_type, "ext-media", SOUND_STREAM_TYPE_LEN)) {
283                 *change_reason = SOUND_SESSION_INTERRUPTED_BY_MEDIA;
284
285         } else if (!strncmp(stream_type, "alarm", SOUND_STREAM_TYPE_LEN)) {
286                 *change_reason = SOUND_SESSION_INTERRUPTED_BY_ALARM;
287
288         } else if (!strncmp(stream_type, "notification", SOUND_STREAM_TYPE_LEN)) {
289                 *change_reason = SOUND_SESSION_INTERRUPTED_BY_NOTIFICATION;
290
291         } else if (!strncmp(stream_type, "emergency", SOUND_STREAM_TYPE_LEN)) {
292                 *change_reason = SOUND_SESSION_INTERRUPTED_BY_EMERGENCY;
293
294         } else if (!strncmp(stream_type, "ringtone-voip", SOUND_STREAM_TYPE_LEN) ||
295                         !strncmp(stream_type, "ringtone-call", SOUND_STREAM_TYPE_LEN) ||
296                         !strncmp(stream_type, "ringbacktone-call", SOUND_STREAM_TYPE_LEN) ||
297                         !strncmp(stream_type, "voip", SOUND_STREAM_TYPE_LEN) ||
298                         !strncmp(stream_type, "call-voice", SOUND_STREAM_TYPE_LEN) ||
299                         !strncmp(stream_type, "call-video", SOUND_STREAM_TYPE_LEN)) {
300                 *change_reason = SOUND_SESSION_INTERRUPTED_BY_CALL;
301
302         } else {
303                 LOGE("not supported stream_type(%s)", stream_type);
304                 return MM_ERROR_INVALID_ARGUMENT;
305         }
306
307         return MM_ERROR_NONE;
308 }
309
310 int _convert_sound_type(sound_type_e sound_type, const char **volume_type)
311 {
312         SM_NULL_ARG_CHECK_FOR_PRIV(volume_type);
313
314         switch (sound_type) {
315         case SOUND_TYPE_SYSTEM:
316                 *volume_type = "system";
317                 break;
318         case SOUND_TYPE_NOTIFICATION:
319                 *volume_type = "notification";
320                 break;
321         case SOUND_TYPE_ALARM:
322                 *volume_type = "alarm";
323                 break;
324         case SOUND_TYPE_RINGTONE:
325                 *volume_type = "ringtone";
326                 break;
327         case SOUND_TYPE_MEDIA:
328                 *volume_type = "media";
329                 break;
330         case SOUND_TYPE_CALL:
331                 *volume_type = "call";
332                 break;
333         case SOUND_TYPE_VOIP:
334                 *volume_type = "voip";
335                 break;
336         case SOUND_TYPE_VOICE:
337                 *volume_type = "voice";
338                 break;
339         }
340         LOGI("volume_type[%s]", *volume_type);
341
342         return MM_ERROR_NONE;
343 }
344
345 int _convert_sound_type_to_enum(const char *sound_type, sound_type_e *sound_type_enum)
346 {
347         SM_NULL_ARG_CHECK_FOR_PRIV(sound_type);
348         SM_NULL_ARG_CHECK_FOR_PRIV(sound_type_enum);
349
350         if (!strncmp(sound_type, "system", strlen(sound_type))) {
351                 *sound_type_enum = SOUND_TYPE_SYSTEM;
352         } else if (!strncmp(sound_type, "notification", strlen(sound_type))) {
353                 *sound_type_enum = SOUND_TYPE_NOTIFICATION;
354         } else if (!strncmp(sound_type, "alarm", strlen(sound_type))) {
355                 *sound_type_enum = SOUND_TYPE_ALARM;
356         } else if (!strncmp(sound_type, "ringtone", strlen(sound_type))) {
357                 *sound_type_enum = SOUND_TYPE_RINGTONE;
358         } else if (!strncmp(sound_type, "media", strlen(sound_type))) {
359                 *sound_type_enum = SOUND_TYPE_MEDIA;
360         } else if (!strncmp(sound_type, "call", strlen(sound_type))) {
361                 *sound_type_enum = SOUND_TYPE_CALL;
362         } else if (!strncmp(sound_type, "voip", strlen(sound_type))) {
363                 *sound_type_enum = SOUND_TYPE_VOIP;
364         } else if (!strncmp(sound_type, "voice", strlen(sound_type))) {
365                 *sound_type_enum = SOUND_TYPE_VOICE;
366         } else {
367                 LOGE("not supported sound_type(%s)", sound_type);
368                 return MM_ERROR_INVALID_ARGUMENT;
369         }
370
371         return MM_ERROR_NONE;
372 }
373
374 int _convert_device_type_enum_to_str(sound_device_type_e device_type, char **device_type_str)
375 {
376         SM_NULL_ARG_CHECK_FOR_PRIV(device_type_str);
377
378         switch (device_type) {
379         case SOUND_DEVICE_BUILTIN_SPEAKER:
380                 *device_type_str = "builtin-speaker";
381                 break;
382         case SOUND_DEVICE_BUILTIN_RECEIVER:
383                 *device_type_str = "builtin-receiver";
384                 break;
385         case SOUND_DEVICE_BUILTIN_MIC:
386                 *device_type_str = "builtin-mic";
387                 break;
388         case SOUND_DEVICE_AUDIO_JACK:
389                 *device_type_str = "audio-jack";
390                 break;
391         case SOUND_DEVICE_BLUETOOTH_MEDIA:
392                 *device_type_str = "bt-a2dp";
393                 break;
394         case SOUND_DEVICE_BLUETOOTH_VOICE:
395                 *device_type_str = "bt-sco";
396                 break;
397         case SOUND_DEVICE_HDMI:
398                 *device_type_str = "hdmi";
399                 break;
400         case SOUND_DEVICE_USB_AUDIO:
401                 *device_type_str = "usb-audio";
402                 break;
403         case SOUND_DEVICE_FORWARDING:
404                 *device_type_str = "forwarding";
405                 break;
406         default:
407                 LOGE("could not find the device_type[%d] in this switch case statement", device_type);
408                 return MM_ERROR_SOUND_INTERNAL;
409         }
410
411         LOGI("device_type[%s]", *device_type_str);
412
413         return MM_ERROR_NONE;
414 }
415
416 int _convert_device_type_str_to_enum(const char *device_type_str, sound_device_type_e *device_type)
417 {
418         SM_NULL_ARG_CHECK_FOR_PRIV(device_type_str);
419         SM_NULL_ARG_CHECK_FOR_PRIV(device_type);
420
421         if (!strncmp(device_type_str, "builtin-speaker", SOUND_DEVICE_TYPE_LEN)) {
422                 *device_type = SOUND_DEVICE_BUILTIN_SPEAKER;
423
424         } else if (!strncmp(device_type_str, "builtin-receiver", SOUND_DEVICE_TYPE_LEN)) {
425                 *device_type = SOUND_DEVICE_BUILTIN_RECEIVER;
426
427         } else if (!strncmp(device_type_str, "builtin-mic", SOUND_DEVICE_TYPE_LEN)) {
428                 *device_type = SOUND_DEVICE_BUILTIN_MIC;
429
430         } else if (!strncmp(device_type_str, "audio-jack", SOUND_DEVICE_TYPE_LEN)) {
431                 *device_type = SOUND_DEVICE_AUDIO_JACK;
432
433         } else if (!strncmp(device_type_str, "hdmi", SOUND_DEVICE_TYPE_LEN)) {
434                 *device_type = SOUND_DEVICE_HDMI;
435
436         } else if (!strncmp(device_type_str, "usb-audio", SOUND_DEVICE_TYPE_LEN)) {
437                 *device_type = SOUND_DEVICE_USB_AUDIO;
438
439         } else if (!strncmp(device_type_str, "bt-a2dp", SOUND_DEVICE_TYPE_LEN)) {
440                 *device_type = SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_INFORMATION;
441
442         } else if (!strncmp(device_type_str, "bt-sco", SOUND_DEVICE_TYPE_LEN)) {
443                 *device_type = SOUND_DEVICE_BLUETOOTH_VOICE;
444
445         } else {
446                 LOGE("not supported device_type(%s)", device_type_str);
447                 return MM_ERROR_INVALID_ARGUMENT;
448         }
449
450         return MM_ERROR_NONE;
451 }
452
453 int _convert_device_type(mm_sound_device_type_e device_type, sound_device_type_e *sound_device_type)
454 {
455         switch (device_type) {
456         case MM_SOUND_DEVICE_TYPE_BUILTIN_SPEAKER:
457                 *sound_device_type = SOUND_DEVICE_BUILTIN_SPEAKER;
458                 break;
459         case MM_SOUND_DEVICE_TYPE_BUILTIN_RECEIVER:
460                 *sound_device_type = SOUND_DEVICE_BUILTIN_RECEIVER;
461                 break;
462         case MM_SOUND_DEVICE_TYPE_BUILTIN_MIC:
463                 *sound_device_type = SOUND_DEVICE_BUILTIN_MIC;
464                 break;
465         case MM_SOUND_DEVICE_TYPE_AUDIOJACK:
466                 *sound_device_type = SOUND_DEVICE_AUDIO_JACK;
467                 break;
468         case MM_SOUND_DEVICE_TYPE_BLUETOOTH_A2DP:
469                 *sound_device_type = SOUND_DEVICE_BLUETOOTH_MEDIA;
470                 break;
471         case MM_SOUND_DEVICE_TYPE_BLUETOOTH_SCO:
472                 *sound_device_type = SOUND_DEVICE_BLUETOOTH_VOICE;
473                 break;
474         case MM_SOUND_DEVICE_TYPE_HDMI:
475                 *sound_device_type = SOUND_DEVICE_HDMI;
476                 break;
477         case MM_SOUND_DEVICE_TYPE_USB_AUDIO:
478                 *sound_device_type = SOUND_DEVICE_USB_AUDIO;
479                 break;
480         case MM_SOUND_DEVICE_TYPE_MIRRORING:
481                 *sound_device_type = SOUND_DEVICE_FORWARDING;
482                 break;
483         }
484
485         return MM_ERROR_NONE;
486 }
487
488 int _convert_device_io_direction(mm_sound_device_io_direction_e io_direction, sound_device_io_direction_e *sound_io_direction)
489 {
490         SM_NULL_ARG_CHECK(sound_io_direction);
491
492         switch (io_direction) {
493         case MM_SOUND_DEVICE_IO_DIRECTION_IN:
494                 *sound_io_direction = SOUND_DEVICE_IO_DIRECTION_IN;
495                 break;
496         case MM_SOUND_DEVICE_IO_DIRECTION_OUT:
497                 *sound_io_direction = SOUND_DEVICE_IO_DIRECTION_OUT;
498                 break;
499         case MM_SOUND_DEVICE_IO_DIRECTION_BOTH:
500                 *sound_io_direction = SOUND_DEVICE_IO_DIRECTION_BOTH;
501                 break;
502         }
503
504         return MM_ERROR_NONE;
505 }
506
507 const char* _convert_api_name(native_api_e api_name)
508 {
509         const char* name = NULL;
510
511         switch (api_name) {
512         case NATIVE_API_SOUND_MANAGER:
513                 name = "sound-manager";
514                 break;
515         case NATIVE_API_PLAYER:
516                 name = "player";
517                 break;
518         case NATIVE_API_WAV_PLAYER:
519                 name = "wav-player";
520                 break;
521         case NATIVE_API_TONE_PLAYER:
522                 name = "tone-player";
523                 break;
524         case NATIVE_API_AUDIO_IO:
525                 name = "audio-io";
526                 break;
527         case NATIVE_API_RECORDER:
528                 name = "recorder";
529                 break;
530         }
531
532         return name;
533 }
534
535 void _focus_state_change_callback(int index, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e state, const char *reason, int option, const char *extra_info, void *user_data)
536 {
537         int ret = MM_ERROR_NONE;
538         int i = 0;
539         sound_stream_focus_change_reason_e change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA;
540
541         LOGI(">> enter");
542
543         ret = _convert_stream_type_to_change_reason(reason, &change_reason);
544         if (ret) {
545                 LOGE("failed to _convert_stream_type_to_enum(), reason(%s), err(0x%08x)", reason, ret);
546                 goto LEAVE;
547         }
548
549         for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++) {
550                 if (sound_stream_info_arr[i] && sound_stream_info_arr[i]->index == index) {
551                         if (state == FOCUS_IS_RELEASED)
552                                 sound_stream_info_arr[i]->acquired_focus &= ~focus_type;
553                         else if (state == FOCUS_IS_ACQUIRED)
554                                 sound_stream_info_arr[i]->acquired_focus |= focus_type;
555
556                         LOGI("[FOCUS USER CALLBACK(%p) START]", sound_stream_info_arr[i]->user_cb);
557                         sound_stream_info_arr[i]->user_cb((sound_stream_info_h)sound_stream_info_arr[i],
558                                         focus_type, state, change_reason, option, extra_info, sound_stream_info_arr[i]->user_data);
559                         LOGI("[FOCUS USER CALLBACK(%p) END]", sound_stream_info_arr[i]->user_cb);
560
561                         break;
562                 }
563         }
564         if (i == SOUND_STREAM_INFO_ARR_MAX)
565                 LOGE("could not find index(%d), failed to call user callback", index);
566
567 LEAVE:
568         LOGI("<< leave");
569
570         return;
571 }
572
573 void _focus_watch_callback(int index, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e state, const char *reason, const char *extra_info, void *user_data)
574 {
575         int ret = MM_ERROR_NONE;
576         int i = 0;
577         sound_stream_focus_change_reason_e change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA;
578
579         ret = _convert_stream_type_to_change_reason(reason, &change_reason);
580         if (ret) {
581                 LOGE("failed to _convert_stream_type_to_enum(), reason(%s), err(0x%08x)", reason, ret);
582                 goto LEAVE;
583         }
584
585         for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++) {
586                 if ((focus_watch_info_arr[i].id > 0) && (focus_watch_info_arr[i].id == index)) {
587                         LOGI("[FOCUS WATCH USER CALLBACK(%p, id:%d) START]", focus_watch_info_arr[i].user_cb, index);
588                         focus_watch_info_arr[i].user_cb(index, focus_type, state, change_reason, extra_info, focus_watch_info_arr[i].user_data);
589                         LOGI("[FOCUS WATCH USER CALLBACK(%p) END]", focus_watch_info_arr[i].user_cb);
590                         break;
591                 }
592         }
593         if (i == SOUND_STREAM_INFO_ARR_MAX)
594                 LOGE("could not find index(%d), failed to call user callback", index);
595
596 LEAVE:
597         LOGI("<< leave");
598         return;
599 }
600
601 void _pa_context_state_cb(pa_context *c, void *userdata)
602 {
603         pa_context_state_t state;
604         sound_stream_info_s *stream_info_h = (sound_stream_info_s*)userdata;
605
606         assert(c);
607
608         state = pa_context_get_state(c);
609         LOGI("[%p] context state = [%d]", stream_info_h, state);
610         switch (state) {
611         case PA_CONTEXT_READY:
612         case PA_CONTEXT_TERMINATED:
613         case PA_CONTEXT_FAILED:
614                 pa_threaded_mainloop_signal(stream_info_h->pa_mainloop, 0);
615                 break;
616         case PA_CONTEXT_UNCONNECTED:
617         case PA_CONTEXT_CONNECTING:
618         case PA_CONTEXT_AUTHORIZING:
619         case PA_CONTEXT_SETTING_NAME:
620                 break;
621         }
622
623         return;
624 }
625
626 void _pa_stream_state_cb(pa_stream *s, void * userdata)
627 {
628         pa_stream_state_t state;
629         virtual_sound_stream_info_s *vstream_h = (virtual_sound_stream_info_s*)userdata;
630
631         assert(s);
632
633         state = pa_stream_get_state(s);
634         LOGI("[%p] stream [%d] state = [%d]", vstream_h, pa_stream_get_index(s), state);
635
636         switch (state) {
637         case PA_STREAM_READY:
638         case PA_STREAM_FAILED:
639         case PA_STREAM_TERMINATED:
640                 pa_threaded_mainloop_signal(vstream_h->pa_mainloop, 0);
641                 break;
642         case PA_STREAM_UNCONNECTED:
643         case PA_STREAM_CREATING:
644                 break;
645         }
646
647         return;
648 }
649
650 int _get_stream_conf_info(const char *stream_type, stream_conf_info_s *info)
651 {
652         int ret = MM_ERROR_NONE;
653         GVariant *result = NULL;
654         GVariant *child = NULL;
655         GDBusConnection *conn = NULL;
656         GError *err = NULL;
657         GVariantIter iter;
658         GVariant *item = NULL;
659         gchar *name = NULL;
660         gsize size = 0;
661         int i = 0;
662
663         assert(stream_type);
664         assert(info);
665
666         conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
667         if (!conn && err) {
668                 LOGE("g_bus_get_sync() error (%s)", err->message);
669                 g_error_free(err);
670                 return MM_ERROR_SOUND_INTERNAL;
671         }
672         result = g_dbus_connection_call_sync(conn,
673                                                         PA_BUS_NAME,
674                                                         PA_STREAM_MANAGER_OBJECT_PATH,
675                                                         PA_STREAM_MANAGER_INTERFACE,
676                                                         PA_STREAM_MANAGER_METHOD_NAME_GET_STREAM_INFO,
677                                                         g_variant_new("(s)", stream_type),
678                                                         G_VARIANT_TYPE("(vvvvvv)"),
679                                                         G_DBUS_CALL_FLAGS_NONE,
680                                                         2000,
681                                                         NULL,
682                                                         &err);
683         if (!result && err) {
684                 LOGE("g_dbus_connection_call_sync() for GET_STREAM_INFO error (%s)", err->message);
685                 g_error_free(err);
686                 ret = MM_ERROR_SOUND_INTERNAL;
687                 goto LEAVE;
688         }
689
690         /* get priority */
691         child = g_variant_get_child_value(result, 0);
692         item = g_variant_get_variant(child);
693         info->priority = g_variant_get_int32(item);
694         g_variant_unref(item);
695         g_variant_unref(child);
696         LOGI("priority(%d)", info->priority);
697
698         /* get route type */
699         child = g_variant_get_child_value(result, 1);
700         item = g_variant_get_variant(child);
701         info->route_type = g_variant_get_int32(item);
702         g_variant_unref(item);
703         g_variant_unref(child);
704         LOGI("route_type(%d)", info->route_type);
705
706         /* get volume types */
707         child = g_variant_get_child_value(result, 2);
708         item = g_variant_get_variant(child);
709         g_variant_iter_init(&iter, item);
710         while (g_variant_iter_loop(&iter, "&s", &name)) {
711                 if (name && !strncmp(name, "none", strlen("none")))
712                         continue;
713                 /* we use volume type only for out direction */
714                 if (name) {
715                         LOGI(" volume-type : %s", name);
716                         info->volume_type = strdup(name);
717                         break;
718                 }
719         }
720         g_variant_unref(item);
721         g_variant_unref(child);
722
723         /* get availabe in-devices */
724         child = g_variant_get_child_value(result, 3);
725         item = g_variant_get_variant(child);
726         size = g_variant_n_children(item);
727         LOGI("num of avail-in-devices are %d", size);
728         g_variant_iter_init(&iter, item);
729         i = 0;
730         while (g_variant_iter_loop(&iter, "&s", &name)) {
731                 if (size == 1 && !strncmp(name, "none", strlen("none"))) {
732                         LOGI(" in-device is [%s], skip it", name);
733                         break;
734                 }
735                 LOGI(" in-device name : %s", name);
736                 info->avail_in_devices[i++] = strdup(name);
737         }
738         g_variant_unref(item);
739         g_variant_unref(child);
740
741         /* get available out-devices */
742         child = g_variant_get_child_value(result, 4);
743         item = g_variant_get_variant(child);
744         size = g_variant_n_children(item);
745         LOGI("num of avail-out-devices are %d", size);
746         g_variant_iter_init(&iter, item);
747         i = 0;
748         while (g_variant_iter_loop(&iter, "&s", &name)) {
749                 if (size == 1 && !strncmp(name, "none", strlen("none"))) {
750                         LOGI(" out-device is [%s], skip it", name);
751                         break;
752                 }
753                 LOGI(" out-device name : %s", name);
754                 info->avail_out_devices[i++] = strdup(name);
755         }
756         g_variant_unref(item);
757         g_variant_unref(child);
758
759         /* get available frameworks */
760         child = g_variant_get_child_value(result, 5);
761         item = g_variant_get_variant(child);
762         size = g_variant_n_children(item);
763         LOGI("num of avail-frameworks are %d", size);
764         g_variant_iter_init(&iter, item);
765         i = 0;
766         while (g_variant_iter_loop(&iter, "&s", &name)) {
767                 if (size == 1 && !strncmp(name, "none", strlen("none"))) {
768                         LOGI(" framework is [%s], skip it", name);
769                         break;
770                 }
771                 LOGI(" framework name : %s", name);
772                 info->avail_frameworks[i++] = strdup(name);
773         }
774         g_variant_unref(item);
775         g_variant_unref(child);
776         g_variant_unref(result);
777
778         if (info->priority == -1) {
779                 LOGE("could not find the info of stream type(%s)", stream_type);
780                 ret = MM_ERROR_NOT_SUPPORT_API;
781         }
782
783 LEAVE:
784         g_object_unref(conn);
785
786         return ret;
787 }
788
789 int _set_manual_route_info(unsigned int index, manual_route_info_s *info)
790 {
791         int ret = MM_ERROR_NONE;
792         int i = 0;
793         GVariantBuilder *builder_for_in_devices;
794         GVariantBuilder *builder_for_out_devices;
795         GVariant *result = NULL;
796         GDBusConnection *conn = NULL;
797         GError *err = NULL;
798         const gchar *dbus_ret = NULL;
799
800         assert(info);
801
802         conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
803         if (!conn) {
804                 LOGE("g_bus_get_sync() error (%s)", err->message);
805                 g_error_free(err);
806                 return MM_ERROR_SOUND_INTERNAL;
807         }
808
809         LOGI("index(%u)", index);
810
811         builder_for_in_devices = g_variant_builder_new(G_VARIANT_TYPE("au"));
812         builder_for_out_devices = g_variant_builder_new(G_VARIANT_TYPE("au"));
813         if (!builder_for_in_devices || !builder_for_out_devices) {
814                 LOGE("failed to g_variant_builder_new(), builder_for_in_devices(%p), builder_for_out_devices(%p)",
815                         builder_for_in_devices, builder_for_out_devices);
816                 ret = MM_ERROR_SOUND_INTERNAL;
817                 goto LEAVE;
818         }
819         for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
820                 if (!info->route_in_devices[i])
821                         break;
822                 g_variant_builder_add(builder_for_in_devices, "u", info->route_in_devices[i]);
823                 LOGI("[IN] device_id:%u", info->route_in_devices[i]);
824         }
825         for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
826                 if (!info->route_out_devices[i])
827                         break;
828                 g_variant_builder_add(builder_for_out_devices, "u", info->route_out_devices[i]);
829                 LOGI("[OUT] device_id:%u", info->route_out_devices[i]);
830         }
831
832         result = g_dbus_connection_call_sync(conn,
833                                                         PA_BUS_NAME,
834                                                         PA_STREAM_MANAGER_OBJECT_PATH,
835                                                         PA_STREAM_MANAGER_INTERFACE,
836                                                         PA_STREAM_MANAGER_METHOD_NAME_SET_STREAM_ROUTE_DEVICES,
837                                                         g_variant_new("(uauau)", index, builder_for_in_devices, builder_for_out_devices),
838                                                         G_VARIANT_TYPE("(s)"),
839                                                         G_DBUS_CALL_FLAGS_NONE,
840                                                         2000,
841                                                         NULL,
842                                                         &err);
843         if (!result) {
844                 LOGE("g_dbus_connection_call_sync() for SET_STREAM_ROUTE_DEVICES error (%s)", err->message);
845                 g_error_free(err);
846                 ret = MM_ERROR_SOUND_INTERNAL;
847                 goto LEAVE;
848         }
849
850         g_variant_get(result, "(&s)", &dbus_ret);
851         LOGI("g_dbus_connection_call_sync() success, method return value is (%s)", dbus_ret);
852         if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret)))
853                 ret = MM_ERROR_SOUND_INVALID_STATE;
854         else
855                 info->is_set = true;
856
857         g_variant_unref(result);
858 LEAVE:
859         if (builder_for_in_devices)
860                 g_variant_builder_unref(builder_for_in_devices);
861         if (builder_for_out_devices)
862                 g_variant_builder_unref(builder_for_out_devices);
863         g_object_unref(conn);
864
865         return ret;
866 }
867
868 int _set_route_option(unsigned int index, const char *name, int value)
869 {
870         int ret = MM_ERROR_NONE;
871         GVariant *result = NULL;
872         GDBusConnection *conn = NULL;
873         GError *err = NULL;
874         const gchar *dbus_ret = NULL;
875
876         assert(name);
877
878         conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
879         if (!conn && err) {
880                 LOGE("g_bus_get_sync() error (%s)", err->message);
881                 g_error_free(err);
882                 return MM_ERROR_SOUND_INTERNAL;
883         }
884
885         LOGI("[OPTION] %s(%d)", name, value);
886
887         result = g_dbus_connection_call_sync(conn,
888                                                         PA_BUS_NAME,
889                                                         PA_STREAM_MANAGER_OBJECT_PATH,
890                                                         PA_STREAM_MANAGER_INTERFACE,
891                                                         PA_STREAM_MANAGER_METHOD_NAME_SET_STREAM_ROUTE_OPTION,
892                                                         g_variant_new("(usi)", index, name, value),
893                                                         G_VARIANT_TYPE("(s)"),
894                                                         G_DBUS_CALL_FLAGS_NONE,
895                                                         2000,
896                                                         NULL,
897                                                         &err);
898         if (!result && err) {
899                 LOGE("g_dbus_connection_call_sync() for SET_STREAM_ROUTE_OPTION error (%s)", err->message);
900                 g_error_free(err);
901                 ret = MM_ERROR_SOUND_INTERNAL;
902                 goto LEAVE;
903         }
904
905         g_variant_get(result, "(&s)", &dbus_ret);
906         LOGI("g_dbus_connection_call_sync() success, method return value is (%s)", dbus_ret);
907         if (!strncmp("STREAM_MANAGER_RETURN_ERROR_NO_STREAM", dbus_ret, strlen(dbus_ret)))
908                 ret = MM_ERROR_SOUND_INVALID_STATE;
909         else if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret)))
910                 ret = MM_ERROR_SOUND_INTERNAL;
911
912         g_variant_unref(result);
913 LEAVE:
914         g_object_unref(conn);
915
916         return ret;
917 }
918
919 int _get_volume_max_level(const char *direction, const char *volume_type, unsigned int *max_level)
920 {
921         int ret = MM_ERROR_NONE;
922         GVariant *result = NULL;
923         GDBusConnection *conn = NULL;
924         GError *err = NULL;
925         const gchar *dbus_ret = NULL;
926
927         assert(direction);
928         assert(volume_type);
929         assert(max_level);
930
931         conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
932         if (!conn) {
933                 LOGE("g_bus_get_sync() error (%s)", err->message);
934                 g_error_free(err);
935                 return MM_ERROR_SOUND_INTERNAL;
936         }
937
938         result = g_dbus_connection_call_sync(conn,
939                                                         PA_BUS_NAME,
940                                                         PA_STREAM_MANAGER_OBJECT_PATH,
941                                                         PA_STREAM_MANAGER_INTERFACE,
942                                                         PA_STREAM_MANAGER_METHOD_NAME_GET_VOLUME_MAX_LEVEL,
943                                                         g_variant_new("(ss)", direction, volume_type),
944                                                         G_VARIANT_TYPE("(us)"),
945                                                         G_DBUS_CALL_FLAGS_NONE,
946                                                         2000,
947                                                         NULL,
948                                                         &err);
949         if (!result) {
950                 LOGE("g_dbus_connection_call_sync() for GET_VOLUME_MAX_LEVEL error (%s)", err->message);
951                 g_error_free(err);
952                 ret = MM_ERROR_SOUND_INTERNAL;
953                 goto LEAVE;
954         }
955
956         g_variant_get(result, "(u&s)", max_level, &dbus_ret);
957         LOGI("g_dbus_connection_call_sync() success, method return value is (%u, %s)", *max_level, dbus_ret);
958         if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret)))
959                 ret = MM_ERROR_SOUND_INTERNAL;
960
961         g_variant_unref(result);
962 LEAVE:
963         g_object_unref(conn);
964
965         return ret;
966 }
967
968 int _get_volume_level(const char *direction, const char *volume_type, unsigned int *level)
969 {
970         int ret = MM_ERROR_NONE;
971         GVariant *result = NULL;
972         GDBusConnection *conn = NULL;
973         GError *err = NULL;
974         const gchar *dbus_ret = NULL;
975
976         assert(direction);
977         assert(volume_type);
978         assert(level);
979
980         conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
981         if (!conn) {
982                 LOGE("g_bus_get_sync() error (%s)", err->message);
983                 g_error_free(err);
984                 return MM_ERROR_SOUND_INTERNAL;
985         }
986
987         result = g_dbus_connection_call_sync(conn,
988                                                         PA_BUS_NAME,
989                                                         PA_STREAM_MANAGER_OBJECT_PATH,
990                                                         PA_STREAM_MANAGER_INTERFACE,
991                                                         PA_STREAM_MANAGER_METHOD_NAME_GET_VOLUME_LEVEL,
992                                                         g_variant_new("(ss)", direction, volume_type),
993                                                         G_VARIANT_TYPE("(us)"),
994                                                         G_DBUS_CALL_FLAGS_NONE,
995                                                         2000,
996                                                         NULL,
997                                                         &err);
998         if (!result) {
999                 LOGE("g_dbus_connection_call_sync() for GET_VOLUME_LEVEL error (%s)", err->message);
1000                 g_error_free(err);
1001                 ret = MM_ERROR_SOUND_INTERNAL;
1002                 goto LEAVE;
1003         }
1004
1005         g_variant_get(result, "(u&s)", level, &dbus_ret);
1006         LOGI("g_dbus_connection_call_sync() success, method return value is (%u, %s)", *level, dbus_ret);
1007         if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret)))
1008                 ret = MM_ERROR_SOUND_INTERNAL;
1009
1010         g_variant_unref(result);
1011 LEAVE:
1012         g_object_unref(conn);
1013
1014         return ret;
1015 }
1016
1017 int _set_volume_level(const char *direction, const char *volume_type, unsigned int level)
1018 {
1019         int ret = MM_ERROR_NONE;
1020         GVariant *result = NULL;
1021         GDBusConnection *conn = NULL;
1022         GError *err = NULL;
1023         const gchar *dbus_ret = NULL;
1024         int vret = 0;
1025         char volume_path[VCONF_PATH_MAX] = {0,};
1026
1027         assert(direction);
1028         assert(volume_type);
1029
1030         conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1031         if (!conn) {
1032                 LOGE("g_bus_get_sync() error (%s)", err->message);
1033                 g_error_free(err);
1034                 return MM_ERROR_SOUND_INTERNAL;
1035         }
1036
1037         result = g_dbus_connection_call_sync(conn,
1038                                                         PA_BUS_NAME,
1039                                                         PA_STREAM_MANAGER_OBJECT_PATH,
1040                                                         PA_STREAM_MANAGER_INTERFACE,
1041                                                         PA_STREAM_MANAGER_METHOD_NAME_SET_VOLUME_LEVEL,
1042                                                         g_variant_new("(ssu)", direction, volume_type, level),
1043                                                         G_VARIANT_TYPE("(s)"),
1044                                                         G_DBUS_CALL_FLAGS_NONE,
1045                                                         2000,
1046                                                         NULL,
1047                                                         &err);
1048         if (!result) {
1049                 LOGE("g_dbus_connection_call_sync() for SET_VOLUME_LEVEL error (%s)", err->message);
1050                 g_error_free(err);
1051                 ret = MM_ERROR_SOUND_INTERNAL;
1052                 goto LEAVE;
1053         }
1054
1055         g_variant_get(result, "(&s)", &dbus_ret);
1056         LOGI("g_dbus_connection_call_sync() success, method return value is (%s)", dbus_ret);
1057         if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret)))
1058                 ret = MM_ERROR_SOUND_INTERNAL;
1059         else {
1060                 /* Set volume value to VCONF */
1061                 snprintf(volume_path, sizeof(volume_path)-1, "%s%s", VCONF_PATH_PREFIX_VOLUME, volume_type);
1062                 if ((vret = vconf_set_int(volume_path, (int)level)))
1063                         LOGE("vconf_set_int(%s) failed..ret[%d]\n", volume_path, vret);
1064         }
1065         g_variant_unref(result);
1066 LEAVE:
1067         g_object_unref(conn);
1068
1069         return ret;
1070 }
1071
1072 int _get_current_volume_type(const char *direction, char **volume_type)
1073 {
1074         int ret = MM_ERROR_NONE;
1075         GVariant *result = NULL;
1076         GDBusConnection *conn = NULL;
1077         GError *err = NULL;
1078         const gchar *dbus_volume_type = NULL;
1079         const gchar *dbus_ret = NULL;
1080
1081         assert(direction);
1082         assert(volume_type);
1083
1084         conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1085         if (!conn) {
1086                 LOGE("g_bus_get_sync() error (%s)", err->message);
1087                 g_error_free(err);
1088                 return MM_ERROR_SOUND_INTERNAL;
1089         }
1090
1091         result = g_dbus_connection_call_sync(conn,
1092                                                         PA_BUS_NAME,
1093                                                         PA_STREAM_MANAGER_OBJECT_PATH,
1094                                                         PA_STREAM_MANAGER_INTERFACE,
1095                                                         PA_STREAM_MANAGER_METHOD_NAME_GET_CURRENT_VOLUME_TYPE,
1096                                                         g_variant_new("(s)", direction),
1097                                                         G_VARIANT_TYPE("(ss)"),
1098                                                         G_DBUS_CALL_FLAGS_NONE,
1099                                                         2000,
1100                                                         NULL,
1101                                                         &err);
1102         if (!result) {
1103                 LOGE("g_dbus_connection_call_sync() for GET_CURRENT_VOLUME_TYPE error (%s)", err->message);
1104                 g_error_free(err);
1105                 ret = MM_ERROR_SOUND_INTERNAL;
1106                 goto LEAVE;
1107         }
1108
1109         g_variant_get(result, "(&s&s)", &dbus_volume_type, &dbus_ret);
1110         LOGI("g_dbus_connection_call_sync() success, method return value is (%s, %s)", dbus_volume_type, dbus_ret);
1111         if (!strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret))) {
1112                 ret = MM_ERROR_NONE;
1113                 *volume_type = strdup(dbus_volume_type);
1114         } else if (!strncmp("STREAM_MANAGER_RETURN_ERROR_NO_STREAM", dbus_ret, strlen(dbus_ret)))
1115                 ret = MM_ERROR_SOUND_VOLUME_NO_INSTANCE;
1116         else
1117                 ret = MM_ERROR_SOUND_INTERNAL;
1118
1119         g_variant_unref(result);
1120 LEAVE:
1121         g_object_unref(conn);
1122
1123         return ret;
1124 }
1125
1126 int _get_current_media_routing_path(const char *direction, sound_device_type_e *device_type)
1127 {
1128         int ret = MM_ERROR_NONE;
1129         GVariant *result = NULL;
1130         GDBusConnection *conn = NULL;
1131         GError *err = NULL;
1132         const gchar *dbus_device_type = NULL;
1133         const gchar *dbus_ret = NULL;
1134
1135         assert(direction);
1136         assert(device_type);
1137
1138         conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1139         if (!conn) {
1140                 LOGE("g_bus_get_sync() error (%s)", err->message);
1141                 g_error_free(err);
1142                 return MM_ERROR_SOUND_INTERNAL;
1143         }
1144
1145         result = g_dbus_connection_call_sync(conn,
1146                                                         PA_BUS_NAME,
1147                                                         PA_STREAM_MANAGER_OBJECT_PATH,
1148                                                         PA_STREAM_MANAGER_INTERFACE,
1149                                                         PA_STREAM_MANAGER_METHOD_NAME_GET_CURRENT_MEDIA_ROUTING_PATH,
1150                                                         g_variant_new("(s)", direction),
1151                                                         G_VARIANT_TYPE("(ss)"),
1152                                                         G_DBUS_CALL_FLAGS_NONE,
1153                                                         2000,
1154                                                         NULL,
1155                                                         &err);
1156         if (!result) {
1157                 LOGE("g_dbus_connection_call_sync() for GET_CURRENT_MEDIA_ROUTING_PATH error (%s)", err->message);
1158                 g_error_free(err);
1159                 ret = MM_ERROR_SOUND_INTERNAL;
1160                 goto LEAVE;
1161         }
1162
1163         g_variant_get(result, "(&s&s)", &dbus_device_type, &dbus_ret);
1164         LOGI("g_dbus_connection_call_sync() success, method return value is (%s, %s)", dbus_device_type, dbus_ret);
1165         if (!strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret))) {
1166                 ret = MM_ERROR_NONE;
1167                 if (_convert_device_type_str_to_enum(dbus_device_type, device_type) < 0)
1168                         ret = MM_ERROR_SOUND_INTERNAL;
1169         } else {
1170                 if (!strncmp("none", dbus_device_type, strlen(dbus_device_type)))
1171                         ret = MM_ERROR_SOUND_NO_DATA;
1172                 else
1173                         ret = MM_ERROR_SOUND_INTERNAL;
1174         }
1175
1176         g_variant_unref(result);
1177 LEAVE:
1178         g_object_unref(conn);
1179
1180         return ret;
1181 }
1182
1183 void _update_focus_status(unsigned int index, unsigned int acquired_focus_status)
1184 {
1185         GVariant *result = NULL;
1186         GDBusConnection *conn = NULL;
1187         GError *err = NULL;
1188         const gchar *dbus_ret = NULL;
1189
1190         conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1191         if (!conn) {
1192                 LOGE("g_bus_get_sync() error (%s)", err->message);
1193                 g_error_free(err);
1194                 return;
1195         }
1196
1197         result = g_dbus_connection_call_sync(conn,
1198                                                         PA_BUS_NAME,
1199                                                         PA_STREAM_MANAGER_OBJECT_PATH,
1200                                                         PA_STREAM_MANAGER_INTERFACE,
1201                                                         PA_STREAM_MANAGER_METHOD_NAME_UPDATE_FOCUS_STATUS,
1202                                                         g_variant_new("(uu)", index, acquired_focus_status),
1203                                                         G_VARIANT_TYPE("(s)"),
1204                                                         G_DBUS_CALL_FLAGS_NONE,
1205                                                         2000,
1206                                                         NULL,
1207                                                         &err);
1208         if (!result) {
1209                 LOGE("g_dbus_connection_call_sync() for UPDATE_FOCUS_STATUS error (%s)", err->message);
1210                 g_error_free(err);
1211                 goto LEAVE;
1212         }
1213         g_variant_get(result, "(&s)", &dbus_ret);
1214         LOGI("g_dbus_connection_call_sync() success, method return value is (%s)", dbus_ret);
1215         if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret)))
1216                 LOGE("failed to UPDATE_FOCUS_STATUS error (%s)", dbus_ret);
1217
1218         g_variant_unref(result);
1219 LEAVE:
1220         g_object_unref(conn);
1221
1222         return;
1223 }
1224
1225 void _focus_session_interrupt_cb(mm_sound_focus_state_e state, const char *reason, bool is_wcb, void *user_data)
1226 {
1227         sound_session_interrupted_code_e e;
1228         LOGE("session interrupted by [%s]", reason);
1229         if (g_session_interrupt_cb_table.user_cb) {
1230                 if (is_wcb) {
1231                         if (state == FOCUS_IS_RELEASED)
1232                                 e = SOUND_SESSION_INTERRUPTED_COMPLETED;
1233                         else
1234                                 _convert_stream_type_to_interrupt_reason(reason, &e);
1235                 } else {
1236                         if (state == FOCUS_IS_ACQUIRED)
1237                                 e = SOUND_SESSION_INTERRUPTED_COMPLETED;
1238                         else
1239                                 _convert_stream_type_to_interrupt_reason(reason, &e);
1240                 }
1241                 g_session_interrupt_cb_table.user_cb(e, g_session_interrupt_cb_table.user_data);
1242         }
1243
1244         return;
1245 }
1246
1247 void _device_connected_cb(sound_device_h device, bool is_connected, void *user_data)
1248 {
1249         mm_sound_device_type_e type;
1250         if (mm_sound_get_device_type(device, &type) != MM_ERROR_NONE) {
1251                 LOGE("getting device type failed");
1252                 return;
1253         }
1254
1255         switch (type) {
1256         case MM_SOUND_DEVICE_TYPE_AUDIOJACK:
1257         case MM_SOUND_DEVICE_TYPE_BLUETOOTH_A2DP:
1258         case MM_SOUND_DEVICE_TYPE_BLUETOOTH_SCO:
1259         case MM_SOUND_DEVICE_TYPE_HDMI:
1260         case MM_SOUND_DEVICE_TYPE_MIRRORING:
1261         case MM_SOUND_DEVICE_TYPE_USB_AUDIO:
1262                 if (!is_connected) {
1263                         LOGI("sound device unplugged");
1264                         g_session_interrupt_cb_table.user_cb(SOUND_SESSION_INTERRUPTED_BY_EARJACK_UNPLUG, g_session_interrupt_cb_table.user_data);
1265                 }
1266                 break;
1267         default:
1268                 break;
1269         }
1270
1271         return;
1272 }
1273
1274 /* This is an internal callback for the VOIP SESSION */
1275 void _voip_focus_state_change_callback(sound_stream_info_h stream_info,
1276                                                                         sound_stream_focus_mask_e focus_mask, sound_stream_focus_state_e focus_state,
1277                                                                         sound_stream_focus_change_reason_e reason, int sound_behavior, const char *extra_info, void *user_data)
1278 {
1279         sound_stream_info_s *info = (sound_stream_info_s *)stream_info;
1280         LOGI(">> enter, stream_info(%p), change_reason(%d), sound_behavior(0x%x), extra_info(%s)", stream_info, reason, sound_behavior, extra_info);
1281
1282         if (!info) {
1283                 LOGE("stream info is null");
1284                 return;
1285         }
1286
1287         if (!(info->acquired_focus & SOUND_STREAM_FOCUS_FOR_PLAYBACK) ||
1288                 !(info->acquired_focus & SOUND_STREAM_FOCUS_FOR_RECORDING)) {
1289                 /* stop virtual stream for rintone-voip or voip */
1290                 if (g_voip_vstream_h) {
1291                         /* stop virtual stream handle */
1292                         _stop_virtual_stream(g_voip_vstream_h);
1293                         /* destroy virtual stream handle */
1294                         _destroy_virtual_stream(g_voip_vstream_h);
1295                         g_voip_vstream_h = NULL;
1296                         LOGW("internal voip stream is interrupted by (%d)", reason);
1297                 }
1298         }
1299
1300         LOGI("<< leave");
1301
1302         return;
1303 }
1304
1305 int _set_session_mode(_session_mode_e mode)
1306 {
1307         int ret = MM_ERROR_NONE;
1308         int w_ret = MM_ERROR_NONE;
1309         int i_ret = SOUND_MANAGER_ERROR_NONE;
1310         bool is_found = false;
1311         MMSoundDeviceList_t device_list;
1312         MMSoundDevice_t tmp_device = NULL;
1313         MMSoundDevice_t proper_device = NULL;
1314         MMSoundDevice_t prev_device = NULL;
1315         mm_sound_device_type_e type;
1316         int id = -1;
1317
1318         if (g_cached_session_mode == mode) {
1319                 LOGW("session_mode(%d) is same as before", mode);
1320                 return ret;
1321         }
1322
1323         switch (mode) {
1324         case _SESSION_MODE_RINGTONE:
1325                 if (g_voip_vstream_h) {
1326                         /* stop vstream and destroy vstream */
1327                         _stop_virtual_stream(g_voip_vstream_h);
1328                         _destroy_virtual_stream(g_voip_vstream_h);
1329                         g_voip_vstream_h = NULL;
1330                         /* destroy stream info */
1331                         _destroy_pa_connection_and_unregister_focus(g_voip_stream_info);
1332                         free(g_voip_stream_info);
1333                         g_voip_stream_info = NULL;
1334                 }
1335                 if (!g_voip_stream_info) {
1336                         g_voip_stream_info = malloc(sizeof(sound_stream_info_s));
1337                         if (!g_voip_stream_info) {
1338                                 ret = MM_ERROR_OUT_OF_MEMORY;
1339                                 goto ERROR_CASE;
1340                         }
1341                         memset(g_voip_stream_info, 0, sizeof(sound_stream_info_s));
1342                 }
1343                 /* create stream info and acquire focus for rintone-voip stream */
1344                 g_voip_stream_info->stream_type = "ringtone-voip";
1345                 ret = _make_pa_connection_and_register_focus(g_voip_stream_info, true, _voip_focus_state_change_callback, NULL);
1346                 if (ret != MM_ERROR_NONE) {
1347                         free(g_voip_stream_info);
1348                         g_voip_stream_info = NULL;
1349                         goto ERROR_CASE;
1350                 } else {
1351                         /* acquire focus */
1352                         ret = mm_sound_acquire_focus(g_voip_stream_info->index, FOCUS_FOR_BOTH, "for voip session");
1353                         if (ret == MM_ERROR_NONE) {
1354                                 g_voip_stream_info->acquired_focus |= FOCUS_FOR_BOTH;
1355                                 _update_focus_status(g_voip_stream_info->index, (unsigned int)g_voip_stream_info->acquired_focus);
1356                         } else
1357                                 goto ERROR_CASE;
1358
1359                 }
1360                 /* create virtual stream for ringtone-voip */
1361                 i_ret = _create_virtual_stream(g_voip_stream_info, &g_voip_vstream_h);
1362                 if (i_ret == SOUND_MANAGER_ERROR_NONE) {
1363                         i_ret = _start_virtual_stream(g_voip_vstream_h);
1364                         if (i_ret != SOUND_MANAGER_ERROR_NONE)
1365                                 goto ERROR_CASE;
1366                 } else {
1367                         ret = MM_ERROR_SOUND_INTERNAL;
1368                         goto ERROR_CASE;
1369                 }
1370                 break;
1371         case _SESSION_MODE_VOICE_WITH_BUILTIN_RECEIVER: /* Built-in RCV and Built-in MIC */
1372         case _SESSION_MODE_VOICE_WITH_BUILTIN_SPEAKER:  /* Built-in SPK and Built-in MIC */
1373         case _SESSION_MODE_VOICE_WITH_AUDIO_JACK:       /* Earphone spk & mic */
1374         case _SESSION_MODE_VOICE_WITH_BLUETOOTH_SCO:    /* Bluetooth spk & mic */
1375                 /* check if the device is available now */
1376                 ret = mm_sound_get_device_list(MM_SOUND_DEVICE_ALL_FLAG, &device_list);
1377                 if (ret != MM_ERROR_NONE) {
1378                         LOGE("failed to get current device list");
1379                         goto ERROR_CASE;
1380                 } else {
1381                         while (!is_found && ((w_ret = mm_sound_get_next_device(device_list, &tmp_device)) == MM_ERROR_NONE)) {
1382                                 ret = mm_sound_get_device_type(tmp_device, &type);
1383                                 if (ret != MM_ERROR_NONE)
1384                                         goto ERROR_CASE;
1385                                 ret = mm_sound_get_device_id(tmp_device, &id);
1386                                 if (ret != MM_ERROR_NONE)
1387                                         goto ERROR_CASE;
1388                                 else {
1389                                         if (g_cached_voip_device_id != -1 && g_cached_voip_device_id == id)
1390                                                 prev_device = tmp_device;
1391                                 }
1392                                 switch (mode) {
1393                                 case _SESSION_MODE_VOICE_WITH_BUILTIN_RECEIVER:
1394                                         if (type == MM_SOUND_DEVICE_TYPE_BUILTIN_RECEIVER) {
1395                                                 is_found = true;
1396                                                 proper_device = tmp_device;
1397                                                 break;
1398                                         }
1399                                 case _SESSION_MODE_VOICE_WITH_BUILTIN_SPEAKER:
1400                                         if (type == MM_SOUND_DEVICE_TYPE_BUILTIN_SPEAKER) {
1401                                                 is_found = true;
1402                                                 proper_device = tmp_device;
1403                                                 break;
1404                                         }
1405                                 case _SESSION_MODE_VOICE_WITH_AUDIO_JACK:
1406                                         if (type == MM_SOUND_DEVICE_TYPE_AUDIOJACK) {
1407                                                 is_found = true;
1408                                                 proper_device = tmp_device;
1409                                                 break;
1410                                         }
1411                                         break;
1412                                 case _SESSION_MODE_VOICE_WITH_BLUETOOTH_SCO:
1413                                         if (type == MM_SOUND_DEVICE_TYPE_BLUETOOTH_SCO) {
1414                                                 is_found = true;
1415                                                 proper_device = tmp_device;
1416                                                 break;
1417                                         }
1418                                 default:
1419                                         break;
1420                                 }
1421                         }
1422                         if (!is_found) {
1423                                 LOGE("could not found a proper connected device for this mode(%d)", mode);
1424                                 ret = MM_ERROR_SOUND_INTERNAL;
1425                                 goto ERROR_CASE_NO_DESTROY;
1426                         }
1427                 }
1428                 /* if ok for the device, go below */
1429                 if (g_cached_session_mode == _SESSION_MODE_RINGTONE) {
1430                         /* stop vstream and destroy vstream */
1431                         _stop_virtual_stream(g_voip_vstream_h);
1432                         _destroy_virtual_stream(g_voip_vstream_h);
1433                         g_voip_vstream_h = NULL;
1434                         /* destroy stream info */
1435                         _destroy_pa_connection_and_unregister_focus(g_voip_stream_info);
1436                         free(g_voip_stream_info);
1437                         g_voip_stream_info = NULL;
1438                 }
1439                 /* create stream info and acquire focus for voip stream */
1440                 if (g_cached_session_mode == -1 || g_cached_session_mode == _SESSION_MODE_RINGTONE) {
1441                         if (!g_voip_stream_info) {
1442                                 g_voip_stream_info = malloc(sizeof(sound_stream_info_s));
1443                                 if (!g_voip_stream_info) {
1444                                         ret = MM_ERROR_OUT_OF_MEMORY;
1445                                         goto ERROR_CASE;
1446                                 }
1447                                 memset(g_voip_stream_info, 0, sizeof(sound_stream_info_s));
1448                         }
1449                         g_voip_stream_info->stream_type = "voip";
1450                         ret = _make_pa_connection_and_register_focus(g_voip_stream_info, true, _voip_focus_state_change_callback, NULL);
1451                         if (ret != MM_ERROR_NONE) {
1452                                 free(g_voip_stream_info);
1453                                 g_voip_stream_info = NULL;
1454                                 goto ERROR_CASE;
1455                         }
1456                         /* set device for routing to the device */
1457                         i_ret = _add_device_for_stream_routing(g_voip_stream_info, proper_device);
1458                         if (i_ret == SOUND_MANAGER_ERROR_NONE) {
1459                                 i_ret = _apply_stream_routing(g_voip_stream_info);
1460                                 if (i_ret != SOUND_MANAGER_ERROR_NONE)
1461                                         goto ERROR_CASE;
1462                         } else
1463                                 goto ERROR_CASE;
1464
1465                         /* acquire focus */
1466                         ret = mm_sound_acquire_focus(g_voip_stream_info->index, FOCUS_FOR_BOTH, "for voip session");
1467                         if (ret == MM_ERROR_NONE) {
1468                                 g_voip_stream_info->acquired_focus |= FOCUS_FOR_BOTH;
1469                                 _update_focus_status(g_voip_stream_info->index, (unsigned int)g_voip_stream_info->acquired_focus);
1470                         } else
1471                                 goto ERROR_CASE;
1472
1473                         /* create virtual stream for voip */
1474                         i_ret = _create_virtual_stream(g_voip_stream_info, &g_voip_vstream_h);
1475                         if (i_ret == SOUND_MANAGER_ERROR_NONE) {
1476                                 i_ret = _start_virtual_stream(g_voip_vstream_h);
1477                                 if (i_ret != SOUND_MANAGER_ERROR_NONE)
1478                                         goto ERROR_CASE;
1479                         } else
1480                                 goto ERROR_CASE;
1481
1482                 } else {
1483                         if (g_cached_voip_device_id != -1 && prev_device) {
1484                                 /* remove cached device */
1485                                 i_ret = _remove_device_for_stream_routing(g_voip_stream_info, prev_device);
1486                                 if (i_ret != SOUND_MANAGER_ERROR_NONE)
1487                                         goto ERROR_CASE;
1488                                 /* set device for routing to the device */
1489                                 i_ret = _add_device_for_stream_routing(g_voip_stream_info, proper_device);
1490                                 if (i_ret == SOUND_MANAGER_ERROR_NONE) {
1491                                         i_ret = _apply_stream_routing(g_voip_stream_info);
1492                                         if (i_ret != SOUND_MANAGER_ERROR_NONE)
1493                                                 goto ERROR_CASE;
1494                                 } else
1495                                         goto ERROR_CASE;
1496                         } else
1497                                 goto ERROR_CASE;
1498                 }
1499                 mm_sound_free_device_list(device_list);
1500                 break;
1501         }
1502         g_cached_session_mode = mode;
1503         g_cached_voip_device_id = id;
1504
1505         return ret;
1506 ERROR_CASE:
1507         if (g_voip_vstream_h) {
1508                 /* destroy virtual stream handle */
1509                 _destroy_virtual_stream(g_voip_vstream_h);
1510                 g_voip_vstream_h = NULL;
1511                 ret = MM_ERROR_SOUND_INTERNAL;
1512         }
1513         if (g_voip_stream_info) {
1514                 /* destroy stream info */
1515                 _destroy_pa_connection_and_unregister_focus(g_voip_stream_info);
1516                 free(g_voip_stream_info);
1517                 g_voip_stream_info = NULL;
1518         }
1519 ERROR_CASE_NO_DESTROY:
1520         return ret;
1521 }
1522
1523 int _make_pa_connection_and_register_focus(sound_stream_info_s *stream_h, bool is_for_session, sound_stream_focus_state_changed_cb callback, void *user_data)
1524 {
1525         int ret = MM_ERROR_NONE;
1526         int pa_ret = PA_OK;
1527         int i = 0;
1528         bool is_focus_cb_thread = false;
1529
1530         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
1531                 return ret;
1532
1533         if (is_focus_cb_thread)
1534                 return MM_ERROR_SOUND_INVALID_OPERATION;
1535
1536         if (!stream_h->is_focus_unavailable) {
1537                 for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++)
1538                         if (sound_stream_info_arr[i] == NULL)
1539                                 break;
1540                 if (i == SOUND_STREAM_INFO_ARR_MAX) {
1541                         LOGE("client sound stream info array is full");
1542                         goto PA_ERROR;
1543                 }
1544         }
1545
1546         /* get configuration information of this stream type */
1547         if ((ret = _get_stream_conf_info(stream_h->stream_type, &stream_h->stream_conf_info)))
1548                 return ret;
1549
1550         LOGI("stream_conf_info : stream type[%s], priority[%d], route type[%d]",
1551                 stream_h->stream_type, stream_h->stream_conf_info.priority, stream_h->stream_conf_info.route_type);
1552
1553         if (!(stream_h->pa_mainloop = pa_threaded_mainloop_new()))
1554                 goto PA_ERROR;
1555
1556         if (!(stream_h->pa_context = pa_context_new(pa_threaded_mainloop_get_api(stream_h->pa_mainloop), "SOUND_MANAGER_STREAM_INFO")))
1557                 goto PA_ERROR;
1558
1559         pa_context_set_state_callback(stream_h->pa_context, _pa_context_state_cb, stream_h);
1560
1561         if (pa_context_connect(stream_h->pa_context, NULL, 0, NULL) < 0) {
1562                 pa_ret = pa_context_errno(stream_h->pa_context);
1563                 goto PA_ERROR;
1564         }
1565
1566         pa_threaded_mainloop_lock(stream_h->pa_mainloop);
1567
1568         if (pa_threaded_mainloop_start(stream_h->pa_mainloop) < 0)
1569                 goto PA_ERROR_WITH_UNLOCK;
1570
1571         /* wait for ready state of the context */
1572         for (;;) {
1573                 pa_context_state_t state;
1574                 state = pa_context_get_state(stream_h->pa_context);
1575                 if (state == PA_CONTEXT_READY)
1576                         break;
1577                 if (!PA_CONTEXT_IS_GOOD(state)) {
1578                         pa_ret = pa_context_errno(stream_h->pa_context);
1579                         goto PA_ERROR_WITH_UNLOCK;
1580                 }
1581                 pa_threaded_mainloop_wait(stream_h->pa_mainloop);
1582         }
1583
1584         /* get index of this context */
1585         stream_h->index = pa_context_get_index(stream_h->pa_context);
1586
1587         pa_threaded_mainloop_unlock(stream_h->pa_mainloop);
1588
1589         /* register focus */
1590         if (!stream_h->is_focus_unavailable) {
1591                 if (is_for_session)
1592                         ret = mm_sound_register_focus_for_session(stream_h->index, getpid(), stream_h->stream_type, _focus_state_change_callback, user_data);
1593                 else
1594                         ret = mm_sound_register_focus(stream_h->index, stream_h->stream_type, _focus_state_change_callback, user_data);
1595                 if (ret == MM_ERROR_NONE) {
1596                         stream_h->user_cb = callback;
1597                         stream_h->user_data = user_data;
1598                         sound_stream_info_arr[i] = stream_h;
1599                 } else {
1600                         LOGE("failed to register focus, ret(0x%x)", ret);
1601                         /* disconnect */
1602                         goto PA_ERROR;
1603                 }
1604         }
1605         goto SUCCESS;
1606
1607 PA_ERROR_WITH_UNLOCK:
1608         pa_threaded_mainloop_unlock(stream_h->pa_mainloop);
1609
1610 PA_ERROR:
1611         for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
1612                 if (stream_h->stream_conf_info.avail_in_devices[i])
1613                         free(stream_h->stream_conf_info.avail_in_devices[i]);
1614                 else
1615                         break;
1616         }
1617         for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
1618                 if (stream_h->stream_conf_info.avail_out_devices[i])
1619                         free(stream_h->stream_conf_info.avail_out_devices[i]);
1620                 else
1621                         break;
1622         }
1623         for (i = 0; i < AVAIL_FRAMEWORKS_MAX; i++) {
1624                 if (stream_h->stream_conf_info.avail_frameworks[i])
1625                         free(stream_h->stream_conf_info.avail_frameworks[i]);
1626                 else
1627                         break;
1628         }
1629         if (stream_h->pa_context) {
1630                 pa_context_disconnect(stream_h->pa_context);
1631                 pa_context_unref(stream_h->pa_context);
1632                 stream_h->pa_context = NULL;
1633         }
1634         if (stream_h->pa_mainloop) {
1635                 pa_threaded_mainloop_free(stream_h->pa_mainloop);
1636                 stream_h->pa_mainloop = NULL;
1637         }
1638         ret = MM_ERROR_SOUND_INTERNAL;
1639         LOGE("pa_ret(%d), ret(0x%x)", pa_ret, ret);
1640
1641 SUCCESS:
1642         return ret;
1643 }
1644
1645 int _destroy_pa_connection_and_unregister_focus(sound_stream_info_s *stream_h)
1646 {
1647         int i = 0;
1648         int ret = MM_ERROR_NONE;
1649         bool is_focus_cb_thread = false;
1650
1651         ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread);
1652         if (ret)
1653                 return ret;
1654
1655         if (is_focus_cb_thread)
1656                 return MM_ERROR_SOUND_INVALID_OPERATION;
1657
1658         if (stream_h->pa_context) {
1659                 pa_context_disconnect(stream_h->pa_context);
1660                 pa_context_unref(stream_h->pa_context);
1661                 stream_h->pa_context = NULL;
1662         }
1663
1664         if (stream_h->pa_mainloop) {
1665                 pa_threaded_mainloop_free(stream_h->pa_mainloop);
1666                 stream_h->pa_mainloop = NULL;
1667         }
1668
1669         /* unregister focus */
1670         if (!stream_h->is_focus_unavailable) {
1671                 ret = mm_sound_unregister_focus(stream_h->index);
1672                 if (ret)
1673                         LOGE("failed to unregister focus, ret(0x%x)", ret);
1674         }
1675
1676         for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
1677                 if (stream_h->stream_conf_info.avail_in_devices[i])
1678                         free(stream_h->stream_conf_info.avail_in_devices[i]);
1679                 if (stream_h->stream_conf_info.avail_out_devices[i])
1680                         free(stream_h->stream_conf_info.avail_out_devices[i]);
1681         }
1682         for (i = 0; i < AVAIL_FRAMEWORKS_MAX; i++) {
1683                 if (stream_h->stream_conf_info.avail_frameworks[i])
1684                         free(stream_h->stream_conf_info.avail_frameworks[i]);
1685         }
1686
1687         for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++) {
1688                 if (sound_stream_info_arr[i] && sound_stream_info_arr[i]->index == stream_h->index) {
1689                         sound_stream_info_arr[i] = NULL;
1690                         break;
1691                 }
1692         }
1693
1694         return ret;
1695 }
1696
1697 int _add_device_for_stream_routing(sound_stream_info_s *stream_info, sound_device_h device)
1698 {
1699         int ret = MM_ERROR_NONE;
1700         int i = 0;
1701         int j = 0;
1702         bool added_successfully = false;
1703 #if 0
1704         /* not ready yet. after preparing in libmm-sound, it'll be enabled */
1705         bool use_internal_codec = false;
1706 #endif
1707         char *device_type_str = NULL;
1708         int device_id = 0;
1709         mm_sound_device_type_e mm_sound_device_type;
1710         mm_sound_device_io_direction_e device_direction;
1711         sound_device_type_e device_type;
1712
1713         SM_INSTANCE_CHECK_FOR_PRIV(stream_info);
1714         SM_NULL_ARG_CHECK_FOR_PRIV(device);
1715
1716         if (stream_info->stream_conf_info.route_type == STREAM_ROUTE_TYPE_MANUAL ||
1717                         stream_info->stream_conf_info.route_type == STREAM_ROUTE_TYPE_MANUAL_EXT) {
1718 #if 0
1719                 /* not ready yet. after preparing in libmm-sound, it'll be enabled */
1720                 if (stream_info->stream_conf_info.route_type == STREAM_ROUTE_TYPE_MANUAL_EXT) {
1721                         if ((ret = mm_sound_get_device_use_internal_codec(device, &use_internal_codec)))
1722                                 return ret;
1723                         if (use_internal_codec)
1724                                 return MM_ERROR_POLICY_INTERNAL;
1725                 }
1726 #endif
1727                 if ((ret = mm_sound_get_device_id(device, &device_id)))
1728                         return ret;
1729                 if ((ret = mm_sound_get_device_type(device, &mm_sound_device_type)))
1730                         return ret;
1731                 if (ret == MM_ERROR_NONE)
1732                         _convert_device_type(mm_sound_device_type, &device_type);
1733                 if ((ret = _convert_device_type_enum_to_str(device_type, &device_type_str)))
1734                         return ret;
1735                 if ((ret = mm_sound_get_device_io_direction(device, &device_direction)))
1736                         return ret;
1737
1738                 if (device_direction == MM_SOUND_DEVICE_IO_DIRECTION_IN || device_direction == MM_SOUND_DEVICE_IO_DIRECTION_BOTH) {
1739                         for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
1740                                 if (!stream_info->stream_conf_info.avail_in_devices[i])
1741                                         break;
1742
1743                                 if (!strncmp(stream_info->stream_conf_info.avail_in_devices[i], device_type_str, SOUND_DEVICE_TYPE_LEN)) {
1744                                         for (j = 0; j < AVAIL_DEVICES_MAX; j++) {
1745                                                 if (!stream_info->manual_route_info.route_in_devices[j]) {
1746                                                         stream_info->manual_route_info.route_in_devices[j] = (unsigned int)device_id;
1747                                                         added_successfully = true;
1748                                                         break;
1749                                                 }
1750                                                 if (stream_info->manual_route_info.route_in_devices[j] == (unsigned int)device_id) {
1751                                                         /* it was already set */
1752                                                         return MM_ERROR_POLICY_DUPLICATED;
1753                                                 }
1754                                         }
1755                                 }
1756                         }
1757                 }
1758                 if (device_direction == MM_SOUND_DEVICE_IO_DIRECTION_OUT || device_direction == MM_SOUND_DEVICE_IO_DIRECTION_BOTH) {
1759                         for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
1760                                 if (!stream_info->stream_conf_info.avail_out_devices[i])
1761                                         break;
1762
1763                                 if (!strncmp(stream_info->stream_conf_info.avail_out_devices[i], device_type_str, SOUND_DEVICE_TYPE_LEN)) {
1764                                         for (j = 0; j < AVAIL_DEVICES_MAX; j++) {
1765                                                 if (!stream_info->manual_route_info.route_out_devices[j]) {
1766                                                         stream_info->manual_route_info.route_out_devices[j] = (unsigned int)device_id;
1767                                                         added_successfully = true;
1768                                                         break;
1769                                                 }
1770                                                 if (stream_info->manual_route_info.route_out_devices[j] == (unsigned int)device_id) {
1771                                                         /* it was already set */
1772                                                         return MM_ERROR_POLICY_DUPLICATED;
1773                                                 }
1774                                         }
1775                                 }
1776                         }
1777                 }
1778         }
1779
1780         if (!added_successfully)
1781                 ret = MM_ERROR_POLICY_INTERNAL;
1782
1783         return ret;
1784 }
1785
1786 int _remove_device_for_stream_routing(sound_stream_info_s *stream_info, sound_device_h device)
1787 {
1788         int ret = MM_ERROR_NONE;
1789         int i = 0;
1790         int j = 0;
1791         bool removed_successfully = false;
1792         char *device_type_str = NULL;
1793         int device_id = 0;
1794         mm_sound_device_type_e mm_sound_device_type;
1795         mm_sound_device_io_direction_e device_direction;
1796         sound_device_type_e device_type;
1797
1798         SM_INSTANCE_CHECK_FOR_PRIV(stream_info);
1799         SM_NULL_ARG_CHECK_FOR_PRIV(device);
1800
1801         if (stream_info->stream_conf_info.route_type == STREAM_ROUTE_TYPE_MANUAL ||
1802                         stream_info->stream_conf_info.route_type == STREAM_ROUTE_TYPE_MANUAL_EXT) {
1803                 if ((ret = mm_sound_get_device_id(device, &device_id)))
1804                         return ret;
1805                 if ((ret = mm_sound_get_device_type(device, &mm_sound_device_type)))
1806                         return ret;
1807                 if (ret == MM_ERROR_NONE)
1808                         _convert_device_type(mm_sound_device_type, &device_type);
1809                 if ((ret = _convert_device_type_enum_to_str(device_type, &device_type_str)))
1810                         return ret;
1811                 if ((ret = mm_sound_get_device_io_direction(device, &device_direction)))
1812                         return ret;
1813
1814                 if (device_direction == MM_SOUND_DEVICE_IO_DIRECTION_IN || device_direction == MM_SOUND_DEVICE_IO_DIRECTION_BOTH) {
1815                         for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
1816                                 if (!stream_info->stream_conf_info.avail_in_devices[i])
1817                                         break;
1818
1819                                 if (!strncmp(stream_info->stream_conf_info.avail_in_devices[i], device_type_str, SOUND_DEVICE_TYPE_LEN)) {
1820                                         for (j = 0; j < AVAIL_DEVICES_MAX; j++) {
1821                                                 if (stream_info->manual_route_info.route_in_devices[j] == (unsigned int)device_id) {
1822                                                         removed_successfully = true;
1823                                                         stream_info->manual_route_info.route_in_devices[j] = 0;
1824                                                         break;
1825                                                 }
1826                                         }
1827                                 }
1828                         }
1829                 }
1830                 if (device_direction == MM_SOUND_DEVICE_IO_DIRECTION_OUT || device_direction == MM_SOUND_DEVICE_IO_DIRECTION_BOTH) {
1831                         for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
1832                                 if (!stream_info->stream_conf_info.avail_out_devices[i])
1833                                         break;
1834
1835                                 if (!strncmp(stream_info->stream_conf_info.avail_out_devices[i], device_type_str, SOUND_DEVICE_TYPE_LEN)) {
1836                                         for (j = 0; j < AVAIL_DEVICES_MAX; j++) {
1837                                                 if (stream_info->manual_route_info.route_out_devices[j] == (unsigned int)device_id) {
1838                                                         removed_successfully = true;
1839                                                         stream_info->manual_route_info.route_out_devices[j] = 0;
1840                                                         break;
1841                                                 }
1842                                         }
1843                                 }
1844                         }
1845                 }
1846         }
1847
1848         if (!removed_successfully)
1849                 ret = MM_ERROR_INVALID_ARGUMENT;
1850
1851         return ret;
1852 }
1853
1854 int _apply_stream_routing(sound_stream_info_s *stream_info)
1855 {
1856         int ret = MM_ERROR_NONE;
1857         int i = 0;
1858         bool need_to_apply = false;
1859
1860         SM_INSTANCE_CHECK_FOR_PRIV(stream_info);
1861
1862         if (stream_info->stream_conf_info.route_type == STREAM_ROUTE_TYPE_MANUAL ||
1863                         stream_info->stream_conf_info.route_type == STREAM_ROUTE_TYPE_MANUAL_EXT) {
1864                 for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
1865                         if (stream_info->manual_route_info.route_in_devices[i]) {
1866                                 need_to_apply = true;
1867                                 break;
1868                         }
1869                         if (stream_info->manual_route_info.route_out_devices[i]) {
1870                                 need_to_apply = true;
1871                                 break;
1872                         }
1873                 }
1874                 if (need_to_apply)
1875                         ret = _set_manual_route_info(stream_info->index, &stream_info->manual_route_info);
1876                 else
1877                         return MM_ERROR_SOUND_INVALID_STATE;
1878
1879         } else
1880                 ret = MM_ERROR_SOUND_INVALID_STATE;
1881
1882         return ret;
1883 }
1884
1885 int _create_virtual_stream(sound_stream_info_s *stream_info, virtual_sound_stream_info_s **virtual_stream)
1886 {
1887         int ret = MM_ERROR_NONE;
1888         bool result = false;
1889         const char *name = NULL;
1890         int i = 0;
1891
1892         SM_INSTANCE_CHECK_FOR_PRIV(virtual_stream);
1893         SM_INSTANCE_CHECK_FOR_PRIV(stream_info);
1894
1895         /* check if this stream_info is available for virtual stream */
1896         name = _convert_api_name(NATIVE_API_SOUND_MANAGER);
1897         for (i = 0; i < AVAIL_FRAMEWORKS_MAX; i++) {
1898                 if (stream_info->stream_conf_info.avail_frameworks[i] && !strncmp(stream_info->stream_conf_info.avail_frameworks[i], name, strlen(name))) {
1899                         result = true;
1900                         break;
1901                 }
1902         }
1903         LOGI("stream_type[%s], native api[%s], is_available[%d]", stream_info->stream_type, name, result);
1904         if (result == false) {
1905                 ret = MM_ERROR_NOT_SUPPORT_API;
1906                 goto LEAVE;
1907         }
1908
1909         (*virtual_stream) = malloc(sizeof(virtual_sound_stream_info_s));
1910         if (!(*virtual_stream)) {
1911                 ret = MM_ERROR_OUT_OF_MEMORY;
1912                 goto LEAVE;
1913         }
1914
1915         memset((*virtual_stream), 0, sizeof(virtual_sound_stream_info_s));
1916         (*virtual_stream)->stream_type = stream_info->stream_type;
1917         (*virtual_stream)->pa_mainloop = stream_info->pa_mainloop;
1918         (*virtual_stream)->pa_context = stream_info->pa_context;
1919         (*virtual_stream)->pa_proplist = pa_proplist_new();
1920         pa_proplist_sets((*virtual_stream)->pa_proplist, PA_PROP_MEDIA_ROLE, (*virtual_stream)->stream_type);
1921         pa_proplist_setf((*virtual_stream)->pa_proplist, PA_PROP_MEDIA_PARENT_ID, "%u", stream_info->index);
1922         (*virtual_stream)->state = _VSTREAM_STATE_READY;
1923         (*virtual_stream)->stream_info = stream_info;
1924
1925 LEAVE:
1926         return ret;
1927 }
1928
1929 int _destroy_virtual_stream(virtual_sound_stream_info_s *virtual_stream)
1930 {
1931         int ret = MM_ERROR_NONE;
1932
1933         SM_INSTANCE_CHECK_FOR_PRIV(virtual_stream);
1934         SM_STATE_CHECK_FOR_PRIV(virtual_stream, _VSTREAM_STATE_READY);
1935
1936         virtual_stream->pa_mainloop = NULL;
1937         virtual_stream->pa_context = NULL;
1938         if (virtual_stream->pa_proplist)
1939                 pa_proplist_free(virtual_stream->pa_proplist);
1940
1941         free(virtual_stream);
1942         virtual_stream = NULL;
1943
1944         return ret;
1945 }
1946
1947 int _start_virtual_stream(virtual_sound_stream_info_s *virtual_stream)
1948 {
1949         int ret = MM_ERROR_NONE;
1950         int pa_ret = PA_OK;
1951         int i = 0;
1952         int io_direction = 0;
1953         pa_sample_spec ss;
1954         pa_channel_map maps;
1955
1956         SM_INSTANCE_CHECK_FOR_PRIV(virtual_stream);
1957         SM_STATE_CHECK_FOR_PRIV(virtual_stream, _VSTREAM_STATE_READY);
1958
1959         if (virtual_stream->stream_info->stream_conf_info.route_type == STREAM_ROUTE_TYPE_MANUAL ||
1960                         virtual_stream->stream_info->stream_conf_info.route_type == STREAM_ROUTE_TYPE_MANUAL_EXT) {
1961                 /* check if the manual route info. is set when it comes to the manual route type */
1962                 if (virtual_stream->stream_info->manual_route_info.is_set == false) {
1963                         ret = MM_ERROR_SOUND_INVALID_STATE;
1964                         goto ERROR;
1965                 }
1966         }
1967
1968         /* fill up with default value */
1969         ss.channels = 2;
1970         ss.rate = 44100;
1971         ss.format = PA_SAMPLE_S16LE;
1972         pa_channel_map_init_auto(&maps, ss.channels, PA_CHANNEL_MAP_ALSA);
1973
1974         /* check direction of this stream */
1975         if (virtual_stream->stream_info->stream_conf_info.avail_in_devices[0] != NULL)
1976                 io_direction |= SOUND_STREAM_DIRECTION_INPUT;
1977         if (virtual_stream->stream_info->stream_conf_info.avail_out_devices[0] != NULL)
1978                 io_direction |= SOUND_STREAM_DIRECTION_OUTPUT;
1979
1980         /* LOCK the pa_threaded_mainloop */
1981         pa_threaded_mainloop_lock(virtual_stream->pa_mainloop);
1982
1983         for (i = 0; i < SOUND_STREAM_DIRECTION_MAX; i++) {
1984                 if (io_direction & (i + 1)) {
1985                         virtual_stream->pa_stream[i] = pa_stream_new_with_proplist(virtual_stream->pa_context, "VIRTUAL_STREAM", &ss, &maps, virtual_stream->pa_proplist);
1986                         if (virtual_stream->pa_stream[i] == NULL) {
1987                                 LOGE("failed to pa_stream_new_with_proplist()");
1988                                 pa_ret = pa_context_errno(virtual_stream->pa_context);
1989                                 ret = MM_ERROR_SOUND_INTERNAL;
1990                                 goto ERROR_WITH_UNLOCK;
1991                         }
1992                         pa_stream_set_state_callback(virtual_stream->pa_stream[i], _pa_stream_state_cb, virtual_stream);
1993
1994                         if ((i + 1) == SOUND_STREAM_DIRECTION_OUTPUT) {
1995                                 pa_ret = pa_stream_connect_playback(virtual_stream->pa_stream[i], NULL, NULL, 0, NULL, NULL);
1996                                 if (pa_ret < 0) {
1997                                         LOGE("failed to pa_stream_connect_playback()");
1998                                         pa_ret = pa_context_errno(virtual_stream->pa_context);
1999                                         ret = MM_ERROR_SOUND_INTERNAL;
2000                                         goto ERROR_WITH_UNLOCK;
2001                                 }
2002                         } else if ((i + 1) == SOUND_STREAM_DIRECTION_INPUT) {
2003                                 pa_ret = pa_stream_connect_record(virtual_stream->pa_stream[i], NULL, NULL, 0);
2004                                 if (pa_ret < 0) {
2005                                         LOGE("failed to pa_stream_connect_record()");
2006                                         pa_ret = pa_context_errno(virtual_stream->pa_context);
2007                                         ret = MM_ERROR_SOUND_INTERNAL;
2008                                         goto ERROR_WITH_UNLOCK;
2009                                 }
2010                         }
2011
2012                         /* wait for ready state of the stream */
2013                         for (;;) {
2014                                 pa_stream_state_t state;
2015                                 state = pa_stream_get_state(virtual_stream->pa_stream[i]);
2016                                 if (state == PA_STREAM_READY)
2017                                         break;
2018                                 if (!PA_STREAM_IS_GOOD(state)) {
2019                                         LOGE("stream(%d) is not good, state : %d", i, state);
2020                                         pa_ret = pa_context_errno(virtual_stream->pa_context);
2021                                         ret = MM_ERROR_SOUND_INTERNAL;
2022                                         goto ERROR_WITH_UNLOCK;
2023                                 }
2024
2025                                 pa_threaded_mainloop_wait(virtual_stream->pa_mainloop);
2026                         }
2027                 }
2028         }
2029         virtual_stream->state = _VSTREAM_STATE_RUNNING;
2030
2031         /* UNLOCK the pa_threaded_mainloop */
2032         pa_threaded_mainloop_unlock(virtual_stream->pa_mainloop);
2033
2034         return ret;
2035
2036 ERROR_WITH_UNLOCK:
2037         /* UNLOCK the pa_threaded_mainloop */
2038         pa_threaded_mainloop_unlock(virtual_stream->pa_mainloop);
2039
2040         for (i = 0; i < SOUND_STREAM_DIRECTION_MAX; i++) {
2041                 if (virtual_stream->pa_stream[i]) {
2042                         pa_stream_unref(virtual_stream->pa_stream[i]);
2043                         virtual_stream->pa_stream[i] = NULL;
2044                 }
2045         }
2046         LOGE("pa_ret(%d)", pa_ret);
2047
2048 ERROR:
2049         return ret;
2050 }
2051
2052 int _stop_virtual_stream(virtual_sound_stream_info_s *virtual_stream)
2053 {
2054         int ret = MM_ERROR_NONE;
2055         int i = 0;
2056
2057         SM_INSTANCE_CHECK_FOR_PRIV(virtual_stream);
2058         SM_STATE_CHECK_FOR_PRIV(virtual_stream, _VSTREAM_STATE_RUNNING);
2059
2060         /* LOCK the pa_threaded_mainloop */
2061         pa_threaded_mainloop_lock(virtual_stream->pa_mainloop);
2062
2063         for (i = 0; i < SOUND_STREAM_DIRECTION_MAX; i++) {
2064                 if (virtual_stream->pa_stream[i]) {
2065                         pa_stream_disconnect(virtual_stream->pa_stream[i]);
2066
2067                         /* wait for terminated state of the stream */
2068                         for (;;) {
2069                                 pa_stream_state_t state;
2070                                 state = pa_stream_get_state(virtual_stream->pa_stream[i]);
2071                                 if (state == PA_STREAM_TERMINATED)
2072                                         break;
2073                                 pa_threaded_mainloop_wait(virtual_stream->pa_mainloop);
2074                         }
2075
2076                         pa_stream_unref(virtual_stream->pa_stream[i]);
2077                         virtual_stream->pa_stream[i] = NULL;
2078                 }
2079         }
2080
2081         /* UNLOCK the pa_threaded_mainloop */
2082         pa_threaded_mainloop_unlock(virtual_stream->pa_mainloop);
2083
2084         virtual_stream->state = _VSTREAM_STATE_READY;
2085
2086         return ret;
2087 }