Update @since_tizen doxygen tag due to profile merge
[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 STREAM_MEDIA                     "media"
23 #define STREAM_SYSTEM                    "system"
24 #define STREAM_ALARM                     "alarm"
25 #define STREAM_NOTIFICATION              "notification"
26 #define STREAM_VOICE_INFORMATION         "voice-information"
27 #define STREAM_VOICE_RECOGNITION         "voice-recognition"
28 #define STREAM_VOICE_RECOGNITION_SERVICE "voice-recognition-service"
29 #define STREAM_VOIP                      "voip"
30 #define STREAM_CALL_VOICE                "call-voice"
31 #define STREAM_CALL_VIDEO                "call-video"
32 #define STREAM_RINGTONE_VOIP             "ringtone-voip"
33 #define STREAM_RINGTONE_CALL             "ringtone-call"
34 #define STREAM_RINGBACKTONE_CALL         "ringbacktone-call"
35 #define STREAM_EMERGENCY                 "emergency"
36 #define STREAM_SOLO                      "solo"
37 #define STREAM_RADIO                     "radio"
38 #define STREAM_LOOPBACK                  "loopback"
39 #define STREAM_LOOPBACK_MIRRORING        "loopback-mirroring"
40 #define STREAM_COMPRESSED_MEDIA          "compressed-media"
41 #define STREAM_NETWORK_SOURCE_MEDIA      "network-source-media"
42 #define STREAM_EXT_MEDIA                 "ext-media"
43
44 #define DBUS_METHOD_TIMEOUT                                     5000
45
46 #define PA_BUS_NAME                                             "org.pulseaudio.Server"
47
48 #define PA_STREAM_MANAGER_OBJECT_PATH                           "/org/pulseaudio/StreamManager"
49 #define PA_STREAM_MANAGER_INTERFACE                             "org.pulseaudio.StreamManager"
50 #define PA_STREAM_MANAGER_METHOD_NAME_GET_STREAM_INFO           "GetStreamInfo"
51 #define PA_STREAM_MANAGER_METHOD_NAME_SET_STREAM_ROUTE_DEVICES  "SetStreamRouteDevices"
52 #define PA_STREAM_MANAGER_METHOD_NAME_SET_STREAM_ROUTE_OPTION   "SetStreamRouteOption"
53 #define PA_STREAM_MANAGER_METHOD_NAME_SET_STREAM_PREFERRED_DEVICE   "SetStreamPreferredDevice"
54 #define PA_STREAM_MANAGER_METHOD_NAME_GET_STREAM_PREFERRED_DEVICE   "GetStreamPreferredDevice"
55 #define PA_STREAM_MANAGER_METHOD_NAME_SET_STREAM_PREEMPTIVE_DEVICE  "SetStreamPreemptiveDevice"
56 #define PA_STREAM_MANAGER_METHOD_NAME_GET_STREAM_PREEMPTIVE_DEVICE  "GetStreamPreemptiveDevice"
57 #define PA_STREAM_MANAGER_METHOD_NAME_GET_VOLUME_MAX_LEVEL      "GetVolumeMaxLevel"
58 #define PA_STREAM_MANAGER_METHOD_NAME_GET_VOLUME_LEVEL          "GetVolumeLevel"
59 #define PA_STREAM_MANAGER_METHOD_NAME_SET_VOLUME_LEVEL          "SetVolumeLevel"
60 #define PA_STREAM_MANAGER_METHOD_NAME_SET_VOLUME_RATIO          "SetVolumeRatio"
61 #define PA_STREAM_MANAGER_METHOD_NAME_GET_CURRENT_VOLUME_TYPE   "GetCurrentVolumeType"
62 #define PA_STREAM_MANAGER_METHOD_NAME_GET_CURRENT_MEDIA_ROUTING_PATH "GetCurrentMediaRoutingPath"
63 #define PA_STREAM_MANAGER_METHOD_NAME_UPDATE_FOCUS_STATUS       "UpdateFocusStatus"
64 #define PA_STREAM_MANAGER_METHOD_NAME_CHECK_STREAM_EXIST_BY_PID "CheckStreamExistByPid"
65 #define PA_STREAM_MANAGER_METHOD_NAME_ACTIVATE_DUCKING          "ActivateDucking"
66 #define PA_STREAM_MANAGER_METHOD_NAME_GET_DUCKING_STATE         "GetDuckingState"
67 #define PA_STREAM_MANAGER_METHOD_NAME_GET_LASTEST_STREAM_PID    "GetPidOfLatestStream"
68 #define PA_STREAM_MANAGER_METHOD_NAME_PUBLISH_LOCAL_DEVICE      "PublishLocalDevice"
69 #define PA_STREAM_MANAGER_METHOD_NAME_DISCOVER_REMOTE_DEVICE    "DiscoverRemoteDevice"
70 #define PA_STREAM_MANAGER_METHOD_NAME_SET_REMOTE_PERMISSION     "SetRemotePermission"
71 #define PA_STREAM_MANAGER_METHOD_NAME_SET_RPI_PLAYBACK_ROUTE    "SetRpiPlaybackRoute"
72
73 #define PA_STREAM_MANAGER_SIGNAL_NAME_REMOTE_FOUND              "RemoteFound"
74
75 #define PA_DEVICE_MANAGER_OBJECT_PATH                           "/org/pulseaudio/DeviceManager"
76 #define PA_DEVICE_MANAGER_INTERFACE                             "org.pulseaudio.DeviceManager"
77 #define PA_DEVICE_MANAGER_METHOD_NAME_IS_DEVICE_RUNNING_BY_ID   "IsDeviceRunningById"
78 #define PA_DEVICE_MANAGER_METHOD_NAME_GET_SUPPORTED_SAMPLE_FORMATS "GetSupportedSampleFormats"
79 #define PA_DEVICE_MANAGER_METHOD_NAME_SET_SAMPLE_FORMAT         "SetSampleFormat"
80 #define PA_DEVICE_MANAGER_METHOD_NAME_GET_SAMPLE_FORMAT         "GetSampleFormat"
81 #define PA_DEVICE_MANAGER_METHOD_NAME_GET_SUPPORTED_SAMPLE_RATES   "GetSupportedSampleRates"
82 #define PA_DEVICE_MANAGER_METHOD_NAME_SET_SAMPLE_RATE           "SetSampleRate"
83 #define PA_DEVICE_MANAGER_METHOD_NAME_GET_SAMPLE_RATE           "GetSampleRate"
84 #define PA_DEVICE_MANAGER_METHOD_NAME_SET_AVOID_RESAMPLING      "SetAvoidResampling"
85 #define PA_DEVICE_MANAGER_METHOD_NAME_GET_AVOID_RESAMPLING      "GetAvoidResampling"
86 #define PA_DEVICE_MANAGER_METHOD_NAME_SET_SPECIFIC_STREAM       "SetSpecificStreamOnly"
87 #define PA_DEVICE_MANAGER_METHOD_NAME_GET_SPECIFIED_STREAM      "GetSpecifiedStream"
88 #define PA_DEVICE_MANAGER_METHOD_NAME_SET_ACM_MODE              "SetAcmMode"
89
90 #define VCONF_PATH_PREFIX_VOLUME                                "file/private/sound/volume/"
91 #define VCONF_PATH_MAX                                          64
92
93 #define VCONF_SOUND_RPI_PLAYBACK_ROUTE                          "file/private/sound/rpi_playback_route"
94
95 #define SM_SOUND_TYPE_CHECK(x_sound_type, x_error) \
96 if (!strncmp(x_sound_type, "system", strlen(x_sound_type)) || \
97         !strncmp(x_sound_type, "notification", strlen(x_sound_type)) || \
98         !strncmp(x_sound_type, "alarm", strlen(x_sound_type)) || \
99         !strncmp(x_sound_type, "ringtone", strlen(x_sound_type)) || \
100         !strncmp(x_sound_type, "media", strlen(x_sound_type)) || \
101         !strncmp(x_sound_type, "call", strlen(x_sound_type)) || \
102         !strncmp(x_sound_type, "voip", strlen(x_sound_type)) || \
103         !strncmp(x_sound_type, "voice", strlen(x_sound_type))) \
104         return x_error; \
105
106 #define SM_INTERNAL_SOUND_TYPE_CHECK(x_sound_type, x_error) \
107 if (!strncmp(x_sound_type, "bixby", strlen(x_sound_type))) \
108         return x_error; \
109
110 #define SOUND_MANAGER_STREAM_NO_METHOD                  0
111 #define SOUND_MANAGER_STREAM_NO_REFERENCE_DEVICE        0
112
113 //LCOV_EXCL_START
114 int _convert_dbus_error(const char *error_msg)
115 {
116         int ret = MM_ERROR_NONE;
117
118         if (!error_msg)
119                 return MM_ERROR_SOUND_INTERNAL;
120
121         if (strstr(error_msg, "InvalidArgument"))
122                 ret = MM_ERROR_INVALID_ARGUMENT;
123         else if (strstr(error_msg, "InvalidOperation"))
124                 ret = MM_ERROR_SOUND_INVALID_OPERATION;
125         else if (strstr(error_msg, "PolicyInternal"))
126                 ret = MM_ERROR_POLICY_INTERNAL;
127         else if (strstr(error_msg, "AccessDenied"))
128                 ret = MM_ERROR_SOUND_PERMISSION_DENIED;
129         else
130                 ret = MM_ERROR_SOUND_INTERNAL;
131
132         LOGE("%s => 0x%x", error_msg, ret);
133
134         return ret;
135 }
136 //LCOV_EXCL_STOP
137
138 int _convert_sound_manager_error_code(const char *func, int code)
139 {
140         int ret = SOUND_MANAGER_ERROR_NONE;
141         char *errorstr = NULL;
142
143         switch (code) {
144         case MM_ERROR_FILE_WRITE:
145         case MM_ERROR_INVALID_HANDLE:
146         case MM_ERROR_SOUND_INVALID_OPERATION:
147                 ret = SOUND_MANAGER_ERROR_INVALID_OPERATION;
148                 errorstr = "INVALID_OPERATION";
149                 break;
150         case MM_ERROR_NONE:
151                 ret = SOUND_MANAGER_ERROR_NONE;
152                 errorstr = "ERROR_NONE";
153                 break;
154         case MM_ERROR_INVALID_ARGUMENT:
155         case MM_ERROR_SOUND_INVALID_POINTER:
156                 ret = SOUND_MANAGER_ERROR_INVALID_PARAMETER;
157                 errorstr = "INVALID_PARAMETER";
158                 break;
159         case MM_ERROR_SOUND_PERMISSION_DENIED:
160                 //LCOV_EXCL_START
161                 ret = SOUND_MANAGER_ERROR_PERMISSION_DENIED;
162                 errorstr = "PERMISSION_DENIED";
163                 break;
164                 //LCOV_EXCL_STOP
165         case MM_ERROR_SOUND_NO_DATA:
166                 ret = SOUND_MANAGER_ERROR_NO_DATA;
167                 errorstr = "NO_DATA";
168                 break;
169         case MM_ERROR_SOUND_INTERNAL:
170         case MM_ERROR_SOUND_VOLUME_CAPTURE_ONLY:
171         case MM_ERROR_OUT_OF_MEMORY:
172         case MM_ERROR_SOUND_SERVER_DISCONNECTED:
173                 //LCOV_EXCL_START
174                 ret = SOUND_MANAGER_ERROR_INTERNAL;
175                 errorstr = "INTERNAL";
176                 //LCOV_EXCL_STOP
177                 break;
178         case MM_ERROR_POLICY_DUPLICATED:
179         case MM_ERROR_POLICY_INTERNAL:
180         case MM_ERROR_POLICY_BLOCKED:
181                 ret = SOUND_MANAGER_ERROR_POLICY;
182                 errorstr = "POLICY";
183                 break;
184         case MM_ERROR_SOUND_VOLUME_NO_INSTANCE:
185                 ret = SOUND_MANAGER_ERROR_NO_PLAYING_SOUND;
186                 errorstr = "NO_PLAYING_SOUND";
187                 break;
188         case MM_ERROR_NOT_SUPPORT_API:
189                 ret = SOUND_MANAGER_ERROR_NOT_SUPPORTED;
190                 errorstr = "NOT_SUPPORTED";
191                 break;
192         case MM_ERROR_SOUND_INVALID_STATE:
193                 ret = SOUND_MANAGER_ERROR_INVALID_STATE;
194                 errorstr = "INVALID_STATE";
195                 break;
196         default:
197                 //LCOV_EXCL_START
198                 LOGW("it should not be reached here, this error(0x%x) should be defined.", code);
199                 ret = SOUND_MANAGER_ERROR_INTERNAL;
200                 errorstr = "INTERNAL";
201                 break;
202                 //LCOV_EXCL_STOP
203         }
204         if (ret)
205                 LOGE("[%s] >> leave : %s(0x%08x), mm_error(0x%08x)", func, errorstr, ret, code);
206         else
207                 LOGD("[%s] >> leave : %s(0x%08x)", func, errorstr, ret);
208
209         return ret;
210 }
211
212 int _convert_stream_type(sound_stream_type_e stream_type_enum, char **stream_type)
213 {
214         SM_ARG_CHECK(stream_type);
215
216         switch (stream_type_enum) {
217         case SOUND_STREAM_TYPE_MEDIA:
218                 *stream_type = STREAM_MEDIA;
219                 break;
220         case SOUND_STREAM_TYPE_SYSTEM:
221                 *stream_type = STREAM_SYSTEM;
222                 break;
223         case SOUND_STREAM_TYPE_ALARM:
224                 *stream_type = STREAM_ALARM;
225                 break;
226         case SOUND_STREAM_TYPE_NOTIFICATION:
227                 *stream_type = STREAM_NOTIFICATION;
228                 break;
229         case SOUND_STREAM_TYPE_EMERGENCY:
230                 *stream_type = STREAM_EMERGENCY;
231                 break;
232         case SOUND_STREAM_TYPE_VOICE_INFORMATION:
233                 *stream_type = STREAM_VOICE_INFORMATION;
234                 break;
235         case SOUND_STREAM_TYPE_VOICE_RECOGNITION:
236                 *stream_type = STREAM_VOICE_RECOGNITION;
237                 break;
238         case SOUND_STREAM_TYPE_RINGTONE_VOIP:
239                 *stream_type = STREAM_RINGTONE_VOIP;
240                 break;
241         case SOUND_STREAM_TYPE_VOIP:
242                 *stream_type = STREAM_VOIP;
243                 break;
244         case SOUND_STREAM_TYPE_MEDIA_EXTERNAL_ONLY:
245                 *stream_type = STREAM_EXT_MEDIA;
246                 break;
247         default:
248                 //LCOV_EXCL_START
249                 LOGE("could not find the stream_type[%d] in this switch case statement", stream_type_enum);
250                 return SOUND_MANAGER_ERROR_INTERNAL;
251                 //LCOV_EXCL_STOP
252         }
253
254         LOGI("stream_type[%s]", *stream_type);
255
256         return SOUND_MANAGER_ERROR_NONE;
257 }
258
259 //LCOV_EXCL_START
260 int _convert_stream_type_for_internal(sound_stream_type_internal_e stream_type_enum, char **stream_type)
261 {
262         SM_ARG_CHECK(stream_type);
263
264         switch (stream_type_enum) {
265         case SOUND_STREAM_TYPE_RINGTONE_CALL:
266                 *stream_type = STREAM_RINGTONE_CALL;
267                 break;
268         case SOUND_STREAM_TYPE_RINGBACKTONE_CALL:
269                 *stream_type = STREAM_RINGBACKTONE_CALL;
270                 break;
271         case SOUND_STREAM_TYPE_VOICE_CALL:
272                 *stream_type = STREAM_CALL_VOICE;
273                 break;
274         case SOUND_STREAM_TYPE_VIDEO_CALL:
275                 *stream_type = STREAM_CALL_VIDEO;
276                 break;
277         case SOUND_STREAM_TYPE_RADIO:
278                 *stream_type = STREAM_RADIO;
279                 break;
280         case SOUND_STREAM_TYPE_LOOPBACK:
281                 *stream_type = STREAM_LOOPBACK;
282                 break;
283         case SOUND_STREAM_TYPE_LOOPBACK_MIRRORING:
284                 *stream_type = STREAM_LOOPBACK_MIRRORING;
285                 break;
286         case SOUND_STREAM_TYPE_SOLO:
287                 *stream_type = STREAM_SOLO;
288                 break;
289         case SOUND_STREAM_TYPE_VOICE_RECOGNITION_SERVICE:
290                 *stream_type = STREAM_VOICE_RECOGNITION_SERVICE;
291                 break;
292         case SOUND_STREAM_TYPE_MEDIA_COMPRESSED:
293                 *stream_type = STREAM_COMPRESSED_MEDIA;
294                 break;
295 #ifndef TIZEN_FEATURE_TV_PROD
296         case SOUND_STREAM_TYPE_MEDIA_NETWORK_SOURCE:
297                 *stream_type = STREAM_NETWORK_SOURCE_MEDIA;
298                 break;
299 #endif
300         default:
301                 LOGE("could not find the stream_type[%d] in this switch case statement", stream_type_enum);
302                 return SOUND_MANAGER_ERROR_INTERNAL;
303         }
304         LOGI("stream_type_for_internal[%s]", *stream_type);
305
306         return SOUND_MANAGER_ERROR_NONE;
307 }
308
309 void _set_focus_availability(sound_stream_info_s *stream_info)
310 {
311         if (stream_info == NULL || stream_info->stream_type == NULL) {
312                 LOGE("invalid argument");
313                 return;
314         }
315         if (!strncmp(stream_info->stream_type, STREAM_SOLO, SOUND_STREAM_TYPE_LEN) ||
316                 !strncmp(stream_info->stream_type, STREAM_RADIO, SOUND_STREAM_TYPE_LEN) ||
317                 !strncmp(stream_info->stream_type, STREAM_LOOPBACK_MIRRORING, SOUND_STREAM_TYPE_LEN)) {
318                 stream_info->is_focus_unavailable = true;
319                 LOGI("this stream_type[%s] does not support focus", stream_info->stream_type);
320         }
321
322         return;
323 }
324 //LCOV_EXCL_STOP
325
326 int _convert_stream_type_to_change_reason(const char *stream_type, sound_stream_focus_change_reason_e *change_reason)
327 {
328         SM_ARG_CHECK(stream_type);
329         SM_ARG_CHECK(change_reason);
330
331         if (!strncmp(stream_type, STREAM_MEDIA, SOUND_STREAM_TYPE_LEN) ||
332                 !strncmp(stream_type, STREAM_COMPRESSED_MEDIA, SOUND_STREAM_TYPE_LEN) ||
333                 !strncmp(stream_type, STREAM_RADIO, SOUND_STREAM_TYPE_LEN) ||
334                 !strncmp(stream_type, STREAM_LOOPBACK, SOUND_STREAM_TYPE_LEN)) {
335                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA;
336
337         } else if (!strncmp(stream_type, STREAM_SYSTEM, SOUND_STREAM_TYPE_LEN)) {
338                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_SYSTEM;//LCOV_EXCL_LINE
339
340         } else if (!strncmp(stream_type, STREAM_ALARM, SOUND_STREAM_TYPE_LEN)) {
341                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_ALARM;
342
343         } else if (!strncmp(stream_type, STREAM_NOTIFICATION, SOUND_STREAM_TYPE_LEN)) {
344                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_NOTIFICATION;
345
346         } else if (!strncmp(stream_type, STREAM_EMERGENCY, SOUND_STREAM_TYPE_LEN)) {
347                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_EMERGENCY;//LCOV_EXCL_LINE
348
349         } else if (!strncmp(stream_type, STREAM_VOICE_INFORMATION, SOUND_STREAM_TYPE_LEN)) {
350                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_INFORMATION;//LCOV_EXCL_LINE
351
352         } else if (!strncmp(stream_type, STREAM_VOICE_RECOGNITION, SOUND_STREAM_TYPE_LEN) ||
353                         !strncmp(stream_type, STREAM_VOICE_RECOGNITION_SERVICE, SOUND_STREAM_TYPE_LEN)) {
354                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_RECOGNITION;
355
356         } else if (!strncmp(stream_type, STREAM_RINGTONE_VOIP, SOUND_STREAM_TYPE_LEN) ||
357                         !strncmp(stream_type, STREAM_RINGTONE_CALL, SOUND_STREAM_TYPE_LEN) ||
358                         !strncmp(stream_type, STREAM_RINGBACKTONE_CALL, SOUND_STREAM_TYPE_LEN)) {
359                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_RINGTONE;
360
361         } else if (!strncmp(stream_type, STREAM_VOIP, SOUND_STREAM_TYPE_LEN)) {
362                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_VOIP;
363
364         } else if (!strncmp(stream_type, STREAM_CALL_VOICE, SOUND_STREAM_TYPE_LEN) ||
365                         !strncmp(stream_type, STREAM_CALL_VIDEO, SOUND_STREAM_TYPE_LEN)) {
366                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_CALL;//LCOV_EXCL_LINE
367
368         } else if (!strncmp(stream_type, STREAM_EXT_MEDIA, SOUND_STREAM_TYPE_LEN)) {
369                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA_EXTERNAL_ONLY;
370
371         } else {
372                 //LCOV_EXCL_START
373                 LOGE("not supported stream_type(%s)", stream_type);
374                 return SOUND_MANAGER_ERROR_INVALID_PARAMETER;
375                 //LCOV_EXCL_STOP
376         }
377
378         return SOUND_MANAGER_ERROR_NONE;
379 }
380
381 static int __get_dbus_connection(GDBusConnection **conn)
382 {
383         GError *err = NULL;
384
385         *conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
386         if (!(*conn) || err) {
387                 //LCOV_EXCL_START
388                 LOGE("g_bus_get_sync() error (%s)", err ? err->message : NULL);
389                 if (err)
390                         g_error_free(err);
391                 return SOUND_MANAGER_ERROR_INTERNAL;
392                 //LCOV_EXCL_STOP
393         }
394
395         return SOUND_MANAGER_ERROR_NONE;
396 }
397
398 int _convert_sound_type(sound_type_e sound_type, const char **volume_type)
399 {
400         SM_ARG_CHECK(volume_type);
401
402         switch (sound_type) {
403         case SOUND_TYPE_SYSTEM:
404                 *volume_type = "system";
405                 break;
406         case SOUND_TYPE_NOTIFICATION:
407                 *volume_type = "notification";
408                 break;
409         case SOUND_TYPE_ALARM:
410                 *volume_type = "alarm";
411                 break;
412         case SOUND_TYPE_RINGTONE:
413                 *volume_type = "ringtone";
414                 break;
415         case SOUND_TYPE_MEDIA:
416                 *volume_type = "media";
417                 break;
418         case SOUND_TYPE_CALL:
419                 *volume_type = "call";
420                 break;
421         case SOUND_TYPE_VOIP:
422                 *volume_type = "voip";
423                 break;
424         case SOUND_TYPE_VOICE:
425                 *volume_type = "voice";
426                 break;
427         }
428         LOGI("volume_type[%s]", *volume_type);
429
430         return SOUND_MANAGER_ERROR_NONE;
431 }
432
433 //LCOV_EXCL_START
434 int _convert_sound_type_for_internal(sound_type_internal_e sound_type, const char **volume_type)
435 {
436         SM_ARG_CHECK(volume_type);
437
438         switch (sound_type) {
439         case SOUND_TYPE_BIXBY:
440                 *volume_type = "bixby";
441                 break;
442         }
443         LOGI("volume_type[%s]", *volume_type);
444
445         return SOUND_MANAGER_ERROR_NONE;
446 }
447 //LCOV_EXCL_STOP
448
449 int _convert_sound_type_to_enum(const char *sound_type, sound_type_e *sound_type_enum)
450 {
451         SM_ARG_CHECK(sound_type);
452         SM_ARG_CHECK(sound_type_enum);
453
454         if (!strncmp(sound_type, "system", strlen(sound_type))) {
455                 *sound_type_enum = SOUND_TYPE_SYSTEM;//LCOV_EXCL_LINE
456         } else if (!strncmp(sound_type, "notification", strlen(sound_type))) {
457                 *sound_type_enum = SOUND_TYPE_NOTIFICATION;//LCOV_EXCL_LINE
458         } else if (!strncmp(sound_type, "alarm", strlen(sound_type))) {
459                 *sound_type_enum = SOUND_TYPE_ALARM;
460         } else if (!strncmp(sound_type, "ringtone", strlen(sound_type))) {
461                 *sound_type_enum = SOUND_TYPE_RINGTONE;//LCOV_EXCL_LINE
462         } else if (!strncmp(sound_type, "media", strlen(sound_type))) {
463                 *sound_type_enum = SOUND_TYPE_MEDIA;
464         } else if (!strncmp(sound_type, "call", strlen(sound_type))) {
465                 *sound_type_enum = SOUND_TYPE_CALL;//LCOV_EXCL_LINE
466         } else if (!strncmp(sound_type, "voip", strlen(sound_type))) {
467                 *sound_type_enum = SOUND_TYPE_VOIP;
468         } else if (!strncmp(sound_type, "voice", strlen(sound_type))) {
469                 *sound_type_enum = SOUND_TYPE_VOICE;
470         } else {
471                 //LCOV_EXCL_START
472                 SM_INTERNAL_SOUND_TYPE_CHECK(sound_type, SOUND_MANAGER_ERROR_NO_PLAYING_SOUND);
473                 LOGE("not supported sound_type(%s)", sound_type);
474                 return SOUND_MANAGER_ERROR_INVALID_PARAMETER;
475                 //LCOV_EXCL_STOP
476         }
477
478         return SOUND_MANAGER_ERROR_NONE;
479 }
480 //LCOV_EXCL_START
481 int _convert_sound_type_to_enum_for_internal(const char *sound_type, sound_type_internal_e *sound_type_enum)
482 {
483         SM_ARG_CHECK(sound_type);
484         SM_ARG_CHECK(sound_type_enum);
485
486         if (!strncmp(sound_type, "bixby", strlen(sound_type))) {
487                 *sound_type_enum = SOUND_TYPE_BIXBY;
488         } else {
489                 SM_SOUND_TYPE_CHECK(sound_type, SOUND_MANAGER_ERROR_NO_PLAYING_SOUND);
490                 LOGE("not supported internal sound_type(%s)", sound_type);
491                 return SOUND_MANAGER_ERROR_INVALID_PARAMETER;
492         }
493
494         return SOUND_MANAGER_ERROR_NONE;
495 }
496
497 int _convert_device_type_enum_to_str(sound_device_type_e device_type, char **device_type_str)
498 {
499         SM_ARG_CHECK(device_type_str);
500
501         switch (device_type) {
502         case SOUND_DEVICE_BUILTIN_SPEAKER:
503                 *device_type_str = "builtin-speaker";
504                 break;
505         case SOUND_DEVICE_BUILTIN_RECEIVER:
506                 *device_type_str = "builtin-receiver";
507                 break;
508         case SOUND_DEVICE_BUILTIN_MIC:
509                 *device_type_str = "builtin-mic";
510                 break;
511         case SOUND_DEVICE_AUDIO_JACK:
512                 *device_type_str = "audio-jack";
513                 break;
514         case SOUND_DEVICE_BLUETOOTH_MEDIA:
515                 *device_type_str = "bt-a2dp";
516                 break;
517         case SOUND_DEVICE_BLUETOOTH_VOICE:
518                 *device_type_str = "bt-sco";
519                 break;
520         case SOUND_DEVICE_HDMI:
521                 *device_type_str = "hdmi";
522                 break;
523         case SOUND_DEVICE_USB_AUDIO:
524                 *device_type_str = "usb-audio";
525                 break;
526         case SOUND_DEVICE_FORWARDING:
527                 *device_type_str = "forwarding";
528                 break;
529         case SOUND_DEVICE_NETWORK:
530                 *device_type_str = "network";
531                 break;
532         default:
533                 LOGE("could not find the device_type[%d] in this switch case statement", device_type);
534                 return SOUND_MANAGER_ERROR_INTERNAL;
535         }
536
537         LOGI("device_type[%s]", *device_type_str);
538
539         return SOUND_MANAGER_ERROR_NONE;
540 }
541
542 int _convert_device_type_str_to_enum(const char *device_type_str, sound_device_type_e *device_type)
543 {
544         SM_ARG_CHECK(device_type_str);
545         SM_ARG_CHECK(device_type);
546
547         if (!strncmp(device_type_str, "builtin-speaker", SOUND_DEVICE_TYPE_LEN)) {
548                 *device_type = SOUND_DEVICE_BUILTIN_SPEAKER;
549
550         } else if (!strncmp(device_type_str, "builtin-receiver", SOUND_DEVICE_TYPE_LEN)) {
551                 *device_type = SOUND_DEVICE_BUILTIN_RECEIVER;
552
553         } else if (!strncmp(device_type_str, "builtin-mic", SOUND_DEVICE_TYPE_LEN)) {
554                 *device_type = SOUND_DEVICE_BUILTIN_MIC;
555
556         } else if (!strncmp(device_type_str, "audio-jack", SOUND_DEVICE_TYPE_LEN)) {
557                 *device_type = SOUND_DEVICE_AUDIO_JACK;
558         } else if (!strncmp(device_type_str, "hdmi", SOUND_DEVICE_TYPE_LEN)) {
559                 *device_type = SOUND_DEVICE_HDMI;
560
561         } else if (!strncmp(device_type_str, "usb-audio", SOUND_DEVICE_TYPE_LEN)) {
562                 *device_type = SOUND_DEVICE_USB_AUDIO;
563
564         } else if (!strncmp(device_type_str, "bt-a2dp", SOUND_DEVICE_TYPE_LEN)) {
565                 *device_type = SOUND_DEVICE_BLUETOOTH_MEDIA;
566
567         } else if (!strncmp(device_type_str, "bt-sco", SOUND_DEVICE_TYPE_LEN)) {
568                 *device_type = SOUND_DEVICE_BLUETOOTH_VOICE;
569
570         } else if (!strncmp(device_type_str, "network", SOUND_DEVICE_TYPE_LEN)) {
571                 *device_type = SOUND_DEVICE_NETWORK;
572
573         } else {
574                 LOGE("not supported device_type(%s)", device_type_str);
575                 return SOUND_MANAGER_ERROR_INVALID_PARAMETER;
576         }
577
578         LOGI("device_type[%s, %d]", device_type_str, *device_type);
579
580         return SOUND_MANAGER_ERROR_NONE;
581 }
582 //LCOV_EXCL_STOP
583 int _convert_device_type(mm_sound_device_type_e device_type, sound_device_type_e *sound_device_type)
584 {
585         SM_ARG_CHECK(sound_device_type);
586
587         switch (device_type) {
588         case MM_SOUND_DEVICE_TYPE_BUILTIN_SPEAKER:
589                 *sound_device_type = SOUND_DEVICE_BUILTIN_SPEAKER;
590                 break;
591         case MM_SOUND_DEVICE_TYPE_BUILTIN_RECEIVER:
592                 *sound_device_type = SOUND_DEVICE_BUILTIN_RECEIVER;
593                 break;
594         case MM_SOUND_DEVICE_TYPE_BUILTIN_MIC:
595                 *sound_device_type = SOUND_DEVICE_BUILTIN_MIC;
596                 break;
597         //LCOV_EXCL_START
598         case MM_SOUND_DEVICE_TYPE_AUDIOJACK:
599                 *sound_device_type = SOUND_DEVICE_AUDIO_JACK;
600                 break;
601         case MM_SOUND_DEVICE_TYPE_BLUETOOTH_A2DP:
602                 *sound_device_type = SOUND_DEVICE_BLUETOOTH_MEDIA;
603                 break;
604         case MM_SOUND_DEVICE_TYPE_BLUETOOTH_SCO:
605                 *sound_device_type = SOUND_DEVICE_BLUETOOTH_VOICE;
606                 break;
607         case MM_SOUND_DEVICE_TYPE_HDMI:
608                 *sound_device_type = SOUND_DEVICE_HDMI;
609                 break;
610         case MM_SOUND_DEVICE_TYPE_USB_AUDIO:
611                 *sound_device_type = SOUND_DEVICE_USB_AUDIO;
612                 break;
613         case MM_SOUND_DEVICE_TYPE_MIRRORING:
614                 *sound_device_type = SOUND_DEVICE_FORWARDING;
615                 break;
616         case MM_SOUND_DEVICE_TYPE_NETWORK:
617                 *sound_device_type = SOUND_DEVICE_NETWORK;
618                 break;
619         default:
620                 LOGE("not supported device_type(%d)", device_type);
621                 return SOUND_MANAGER_ERROR_INVALID_PARAMETER;
622         //LCOV_EXCL_STOP
623         }
624
625         LOGI("device_type[%d]", *sound_device_type);
626
627         return SOUND_MANAGER_ERROR_NONE;
628 }
629
630 int _convert_device_io_direction(mm_sound_device_io_direction_e io_direction, sound_device_io_direction_e *device_io_direction)
631 {
632         SM_ARG_CHECK(device_io_direction);
633
634         switch (io_direction) {
635         case MM_SOUND_DEVICE_IO_DIRECTION_IN:
636                 *device_io_direction = SOUND_DEVICE_IO_DIRECTION_IN;
637                 break;
638         case MM_SOUND_DEVICE_IO_DIRECTION_OUT:
639                 *device_io_direction = SOUND_DEVICE_IO_DIRECTION_OUT;
640                 break;
641         case MM_SOUND_DEVICE_IO_DIRECTION_BOTH:
642                 *device_io_direction = SOUND_DEVICE_IO_DIRECTION_BOTH;
643                 break;
644         }
645
646         LOGI("device_io_direction[%d]", *device_io_direction);
647
648         return SOUND_MANAGER_ERROR_NONE;
649 }
650 //LCOV_EXCL_START
651 const char* _convert_api_name(native_api_e api_name)
652 {
653         switch (api_name) {
654         case NATIVE_API_SOUND_MANAGER:
655                 return "sound-manager";
656         case NATIVE_API_PLAYER:
657                 return "player";
658         case NATIVE_API_WAV_PLAYER:
659                 return "wav-player";
660         case NATIVE_API_TONE_PLAYER:
661                 return "tone-player";
662         case NATIVE_API_AUDIO_IO:
663                 return "audio-io";
664         case NATIVE_API_RECORDER:
665                 return "recorder";
666         case NATIVE_API_WEBRTC:
667                 return "webrtc";
668         default:
669                 return NULL;
670         }
671 }
672
673 int _convert_sample_format_enum_to_str(sound_sample_format_e format, const char **format_str)
674 {
675         SM_ARG_CHECK(format_str);
676
677         switch (format) {
678         case SOUND_SAMPLE_FORMAT_U8:
679                 *format_str = "u8";
680                 break;
681         case SOUND_SAMPLE_FORMAT_S16_LE:
682                 *format_str = "s16le";
683                 break;
684         case SOUND_SAMPLE_FORMAT_S24_LE:
685                 *format_str = "s24le";
686                 break;
687         case SOUND_SAMPLE_FORMAT_S24_32_LE:
688                 *format_str = "s24-32le";
689                 break;
690         default:
691                 LOGE("could not find format[%d] in this switch case statement", format);
692                 return SOUND_MANAGER_ERROR_INTERNAL;
693         }
694
695         return SOUND_MANAGER_ERROR_NONE;
696 }
697
698 int _convert_sample_format_str_to_enum(const char *format_str, sound_sample_format_e *format)
699 {
700         SM_ARG_CHECK(format_str);
701         SM_ARG_CHECK(format);
702
703         if (!strncmp(format_str, "u8", SOUND_SAMPLE_FORMAT_LEN) || !strncmp(format_str, "8", SOUND_SAMPLE_FORMAT_LEN)) {
704                 *format = SOUND_SAMPLE_FORMAT_U8;
705         } else if (!strncmp(format_str, "s16le", SOUND_SAMPLE_FORMAT_LEN)) {
706                 *format = SOUND_SAMPLE_FORMAT_S16_LE;
707         } else if (!strncmp(format_str, "s24le", SOUND_SAMPLE_FORMAT_LEN)) {
708                 *format = SOUND_SAMPLE_FORMAT_S24_LE;
709         } else if (!strncmp(format_str, "s24-32le", SOUND_SAMPLE_FORMAT_LEN)) {
710                 *format = SOUND_SAMPLE_FORMAT_S24_32_LE;
711         } else {
712                 LOGE("not supported sample format(%s)", format_str);
713                 return SOUND_MANAGER_ERROR_INVALID_PARAMETER;
714         }
715
716         LOGI("format[%s, %d]", format_str, *format);
717
718         return SOUND_MANAGER_ERROR_NONE;
719 }
720
721 int _convert_sample_rate_enum_to_uint(sound_sample_rate_e rate, unsigned int *sample_rate)
722 {
723         SM_ARG_CHECK(sample_rate);
724
725         switch (rate) {
726         case SOUND_SAMPLE_RATE_8000:
727                 *sample_rate = 8000;
728                 break;
729         case SOUND_SAMPLE_RATE_16000:
730                 *sample_rate = 16000;
731                 break;
732         case SOUND_SAMPLE_RATE_22050:
733                 *sample_rate = 22050;
734                 break;
735         case SOUND_SAMPLE_RATE_44100:
736                 *sample_rate = 44100;
737                 break;
738         case SOUND_SAMPLE_RATE_48000:
739                 *sample_rate = 48000;
740                 break;
741         case SOUND_SAMPLE_RATE_88200:
742                 *sample_rate = 88200;
743                 break;
744         case SOUND_SAMPLE_RATE_96000:
745                 *sample_rate = 96000;
746                 break;
747         case SOUND_SAMPLE_RATE_192000:
748                 *sample_rate = 192000;
749                 break;
750         default:
751                 LOGE("not supported sample rate(%u)", rate);
752                 return SOUND_MANAGER_ERROR_INVALID_PARAMETER;
753         }
754
755         return SOUND_MANAGER_ERROR_NONE;
756 }
757
758 int _convert_sample_rate_to_enum(unsigned int rate, sound_sample_rate_e *rate_e)
759 {
760         SM_ARG_CHECK(rate_e);
761
762         switch (rate) {
763         case 8000:
764                 *rate_e = SOUND_SAMPLE_RATE_8000;
765                 break;
766         case 16000:
767                 *rate_e = SOUND_SAMPLE_RATE_16000;
768                 break;
769         case 22050:
770                 *rate_e = SOUND_SAMPLE_RATE_22050;
771                 break;
772         case 44100:
773                 *rate_e = SOUND_SAMPLE_RATE_44100;
774                 break;
775         case 48000:
776                 *rate_e = SOUND_SAMPLE_RATE_48000;
777                 break;
778         case 88200:
779                 *rate_e = SOUND_SAMPLE_RATE_88200;
780                 break;
781         case 96000:
782                 *rate_e = SOUND_SAMPLE_RATE_96000;
783                 break;
784         case 192000:
785                 *rate_e = SOUND_SAMPLE_RATE_192000;
786                 break;
787         default:
788                 LOGE("not supported sample rate(%u)", rate);
789                 return SOUND_MANAGER_ERROR_INVALID_PARAMETER;
790         }
791
792         LOGI("rate[%d, %d]", rate, *rate_e);
793
794         return SOUND_MANAGER_ERROR_NONE;
795 }
796 //LCOV_EXCL_STOP
797
798 int _return_val_if_not_usb_device(sound_device_h device, int ret_val)
799 {
800         mm_sound_device_type_e type;
801
802         if (mm_sound_get_device_type(device, &type))
803                 return ret_val;
804
805         if (type != MM_SOUND_DEVICE_TYPE_USB_AUDIO)     {
806                 LOGE("device type is not USB AUDIO");
807                 return ret_val;
808         }
809
810         return SOUND_MANAGER_ERROR_NONE;
811 }
812
813 //LCOV_EXCL_START
814 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)
815 {
816         int ret = MM_ERROR_NONE;
817         sound_stream_focus_change_reason_e change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA;
818         sound_stream_info_s *stream_info;
819
820         LOGI(">> enter");
821
822         if (!user_data) {
823                 LOGE("user_data is null");
824                 goto LEAVE;
825         }
826
827         stream_info = (sound_stream_info_s *)user_data;
828         if (stream_info->focus_id != index) {
829                 LOGE("index is not valid, (%d, %d)", stream_info->focus_id, index);
830                 goto LEAVE;
831         }
832
833         if ((ret = _convert_stream_type_to_change_reason(reason, &change_reason)) != SOUND_MANAGER_ERROR_NONE) {
834                 LOGE("failed to _convert_stream_type_to_enum(), reason(%s), err(0x%08x)", reason, ret);
835                 goto LEAVE;
836         }
837
838         SM_ENTER_CRITICAL_SECTION(&stream_info->focus_cb_mutex);
839
840         if (state == FOCUS_IS_RELEASED)
841                 stream_info->acquired_focus &= ~focus_type;
842         else if (state == FOCUS_IS_ACQUIRED)
843                 stream_info->acquired_focus |= focus_type;
844
845         if (state == FOCUS_IS_ACQUIRED)
846                 _update_focus_status(stream_info->pa_info.index, (unsigned int)stream_info->acquired_focus);
847
848         LOGI("[FOCUS USER CALLBACK(%p) START]", stream_info->user_cb);
849         stream_info->user_cb((sound_stream_info_h)stream_info, focus_type, state, change_reason,
850                                                 option, extra_info, stream_info->user_data);
851         LOGI("[FOCUS USER CALLBACK(%p) END]", stream_info->user_cb);
852
853         if (state == FOCUS_IS_RELEASED)
854                 _update_focus_status(stream_info->pa_info.index, (unsigned int)stream_info->acquired_focus);
855
856         if (state == FOCUS_IS_RELEASED)
857                 stream_info->prev_acquired_focus &= ~focus_type;
858         else if (state == FOCUS_IS_ACQUIRED)
859                 stream_info->prev_acquired_focus |= focus_type;
860
861         SM_LEAVE_CRITICAL_SECTION(&stream_info->focus_cb_mutex);
862
863 LEAVE:
864         LOGI("<< leave");
865
866         return;
867 }
868
869 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)
870 {
871         int ret = MM_ERROR_NONE;
872         sound_stream_focus_change_reason_e change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA;
873         _focus_watch_info_s *watch_info;
874
875         LOGI(">> enter");
876
877         if (!user_data) {
878                 LOGE("user_data is null");
879                 goto LEAVE;
880         }
881
882         watch_info = (_focus_watch_info_s *)user_data;
883         if (watch_info->id != index) {
884                 LOGE("index is not valid, (%d, %d)", watch_info->id, index);
885                 goto LEAVE;
886         }
887
888         if ((ret = _convert_stream_type_to_change_reason(reason, &change_reason)) != SOUND_MANAGER_ERROR_NONE) {
889                 LOGE("failed to _convert_stream_type_to_enum(), reason(%s), err(0x%08x)", reason, ret);
890                 goto LEAVE;
891         }
892
893         LOGI("[FOCUS WATCH USER CALLBACK(%p, id:%d) START]", watch_info->user_cb, index);
894         watch_info->user_cb(index, focus_type, state, change_reason, extra_info, watch_info->user_data);
895         LOGI("[FOCUS WATCH USER CALLBACK(%p) END]", watch_info->user_cb);
896
897 LEAVE:
898         LOGI("<< leave");
899
900         return;
901 }
902 //LCOV_EXCL_STOP
903
904 void _pa_context_state_cb(pa_context *c, void *userdata)
905 {
906         pa_context_state_t state;
907         sound_pa_info_s *pa_info = (sound_pa_info_s *)userdata;
908
909         if (!c) {
910                 LOGE("pa_context is null");
911                 return;
912         }
913
914         if (!pa_info) {
915                 LOGE("pa_info is null");
916                 return;
917         }
918
919         state = pa_context_get_state(c);
920
921         LOGI("pa_info[%p] context state[%d]", pa_info, state);
922
923         if (state == PA_CONTEXT_FAILED) {
924                 pa_info->is_disconnected = true;
925                 LOGE("PA DISCONNECTED");
926         }
927
928         switch (state) {
929         case PA_CONTEXT_READY:
930         case PA_CONTEXT_TERMINATED:
931         case PA_CONTEXT_FAILED:
932                 pa_threaded_mainloop_signal(pa_info->mainloop, 0);
933                 break;
934         case PA_CONTEXT_UNCONNECTED:
935         case PA_CONTEXT_CONNECTING:
936         case PA_CONTEXT_AUTHORIZING:
937         case PA_CONTEXT_SETTING_NAME:
938                 break;
939         }
940
941         return;
942 }
943
944 //LCOV_EXCL_START
945 void _pa_stream_state_cb(pa_stream *s, void *userdata)
946 {
947         pa_stream_state_t state;
948         virtual_sound_stream_info_s *vstream_h = (virtual_sound_stream_info_s*)userdata;
949
950         if (!s) {
951                 LOGE("pa_stream is null");
952                 return;
953         }
954
955         if (!vstream_h) {
956                 LOGE("vstream_h is null");
957                 return;
958         }
959
960         state = pa_stream_get_state(s);
961         LOGI("vstream_h[%p] index[%d] state[%d]", vstream_h, pa_stream_get_index(s), state);
962
963         switch (state) {
964         case PA_STREAM_READY:
965         case PA_STREAM_FAILED:
966         case PA_STREAM_TERMINATED:
967                 pa_threaded_mainloop_signal(vstream_h->pa_mainloop, 0);
968                 break;
969         case PA_STREAM_UNCONNECTED:
970         case PA_STREAM_CREATING:
971                 break;
972         }
973
974         return;
975 }
976 //LCOV_EXCL_STOP
977
978 int _get_stream_conf_info(const char *stream_type, stream_conf_info_s *info)
979 {
980         int ret = SOUND_MANAGER_ERROR_NONE;
981         GVariant *result = NULL;
982         GVariant *child = NULL;
983         GDBusConnection *conn = NULL;
984         GError *err = NULL;
985         GVariantIter iter;
986         GVariant *item = NULL;
987         gchar *name = NULL;
988         gsize size = 0;
989         int i = 0;
990
991         SM_ARG_CHECK(stream_type);
992         SM_ARG_CHECK(info);
993
994         if ((ret = __get_dbus_connection(&conn)) != SOUND_MANAGER_ERROR_NONE)
995                 return ret;
996
997         result = g_dbus_connection_call_sync(conn,
998                                                         PA_BUS_NAME,
999                                                         PA_STREAM_MANAGER_OBJECT_PATH,
1000                                                         PA_STREAM_MANAGER_INTERFACE,
1001                                                         PA_STREAM_MANAGER_METHOD_NAME_GET_STREAM_INFO,
1002                                                         g_variant_new("(s)", stream_type),
1003                                                         G_VARIANT_TYPE("(vvvvvv)"),
1004                                                         G_DBUS_CALL_FLAGS_NONE,
1005                                                         DBUS_METHOD_TIMEOUT,
1006                                                         NULL,
1007                                                         &err);
1008         if (!result || err) {
1009                 //LCOV_EXCL_START
1010                 LOGE("g_dbus_connection_call_sync() for GET_STREAM_INFO error (%s)", err ? err->message : NULL);
1011                 if (err)
1012                         g_error_free(err);
1013                 ret = SOUND_MANAGER_ERROR_INTERNAL;
1014                 goto LEAVE;
1015                 //LCOV_EXCL_STOP
1016         }
1017
1018         /* get priority */
1019         child = g_variant_get_child_value(result, 0);
1020         item = g_variant_get_variant(child);
1021         info->priority = g_variant_get_int32(item);
1022         g_variant_unref(item);
1023         g_variant_unref(child);
1024         LOGI("priority(%d)", info->priority);
1025
1026         /* get route type */
1027         child = g_variant_get_child_value(result, 1);
1028         item = g_variant_get_variant(child);
1029         info->route_type = g_variant_get_int32(item);
1030         g_variant_unref(item);
1031         g_variant_unref(child);
1032         LOGI("route_type(%d)", info->route_type);
1033
1034         /* get volume types */
1035         child = g_variant_get_child_value(result, 2);
1036         item = g_variant_get_variant(child);
1037         g_variant_iter_init(&iter, item);
1038         while (g_variant_iter_loop(&iter, "&s", &name)) {
1039                 if (name && !strncmp(name, "none", strlen("none")))
1040                         continue;
1041                 /* we use volume type only for out direction */
1042                 if (name) {
1043                         LOGI(" volume-type : %s", name);
1044                         info->volume_type = strdup(name);
1045                         break;
1046                 }
1047         }
1048         g_variant_unref(item);
1049         g_variant_unref(child);
1050
1051         /* get available in-devices */
1052         child = g_variant_get_child_value(result, 3);
1053         item = g_variant_get_variant(child);
1054         size = g_variant_n_children(item);
1055         LOGI("num of avail-in-devices are %"G_GSIZE_FORMAT, size);
1056         g_variant_iter_init(&iter, item);
1057         i = 0;
1058         while (g_variant_iter_loop(&iter, "&s", &name)) {
1059                 if (size == 1 && !strncmp(name, "none", strlen("none"))) {
1060                         LOGI(" in-device is [%s], skip it", name);
1061                         break;
1062                 }
1063                 LOGI(" in-device name : %s", name);
1064                 info->avail_in_devices[i++] = strdup(name);
1065         }
1066         g_variant_unref(item);
1067         g_variant_unref(child);
1068
1069         /* get available out-devices */
1070         child = g_variant_get_child_value(result, 4);
1071         item = g_variant_get_variant(child);
1072         size = g_variant_n_children(item);
1073         LOGI("num of avail-out-devices are %"G_GSIZE_FORMAT, size);
1074         g_variant_iter_init(&iter, item);
1075         i = 0;
1076         while (g_variant_iter_loop(&iter, "&s", &name)) {
1077                 if (size == 1 && !strncmp(name, "none", strlen("none"))) {
1078                         LOGI(" out-device is [%s], skip it", name);
1079                         break;
1080                 }
1081                 LOGI(" out-device name : %s", name);
1082                 info->avail_out_devices[i++] = strdup(name);
1083         }
1084         g_variant_unref(item);
1085         g_variant_unref(child);
1086
1087         /* get available frameworks */
1088         child = g_variant_get_child_value(result, 5);
1089         item = g_variant_get_variant(child);
1090         size = g_variant_n_children(item);
1091         LOGI("num of avail-frameworks are %"G_GSIZE_FORMAT, size);
1092         g_variant_iter_init(&iter, item);
1093         i = 0;
1094         while (g_variant_iter_loop(&iter, "&s", &name)) {
1095                 if (size == 1 && !strncmp(name, "none", strlen("none"))) {
1096                         LOGI(" framework is [%s], skip it", name);//LCOV_EXCL_LINE
1097                         break;
1098                 }
1099                 LOGI(" framework name : %s", name);
1100                 info->avail_frameworks[i++] = strdup(name);
1101         }
1102         g_variant_unref(item);
1103         g_variant_unref(child);
1104
1105         if (info->priority == -1) {
1106                 LOGE("could not find the info of stream type(%s)", stream_type);//LCOV_EXCL_LINE
1107                 ret = SOUND_MANAGER_ERROR_NOT_SUPPORTED;
1108         }
1109
1110 LEAVE:
1111         if (result)
1112                 g_variant_unref(result);
1113         g_object_unref(conn);
1114
1115         return ret;
1116 }
1117
1118 int _set_manual_route_info(unsigned int index, manual_route_info_s *info)
1119 {
1120         int ret = SOUND_MANAGER_ERROR_NONE;
1121         int i = 0;
1122         GVariantBuilder *builder_for_in_devices;
1123         GVariantBuilder *builder_for_out_devices;
1124         GVariant *result = NULL;
1125         GDBusConnection *conn = NULL;
1126         GError *err = NULL;
1127         const gchar *dbus_ret = NULL;
1128
1129         SM_ARG_CHECK(info);
1130
1131         if ((ret = __get_dbus_connection(&conn)) != SOUND_MANAGER_ERROR_NONE)
1132                 return ret;
1133
1134         LOGI("index[%u]", index);
1135
1136         builder_for_in_devices = g_variant_builder_new(G_VARIANT_TYPE("au"));
1137         builder_for_out_devices = g_variant_builder_new(G_VARIANT_TYPE("au"));
1138         if (!builder_for_in_devices || !builder_for_out_devices) {
1139                 LOGE("failed to g_variant_builder_new(), builder_for_in_devices(%p), builder_for_out_devices(%p)",
1140                         builder_for_in_devices, builder_for_out_devices);
1141                 ret = SOUND_MANAGER_ERROR_INTERNAL;
1142                 goto LEAVE;
1143         }
1144         for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
1145                 if (!info->route_in_devices[i])
1146                         break;
1147                 g_variant_builder_add(builder_for_in_devices, "u", info->route_in_devices[i]);
1148                 LOGI("[IN] device_id:%u", info->route_in_devices[i]);
1149         }
1150         for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
1151                 if (!info->route_out_devices[i])
1152                         break;
1153                 g_variant_builder_add(builder_for_out_devices, "u", info->route_out_devices[i]);
1154                 LOGI("[OUT] device_id:%u", info->route_out_devices[i]);
1155         }
1156
1157         result = g_dbus_connection_call_sync(conn,
1158                                                         PA_BUS_NAME,
1159                                                         PA_STREAM_MANAGER_OBJECT_PATH,
1160                                                         PA_STREAM_MANAGER_INTERFACE,
1161                                                         PA_STREAM_MANAGER_METHOD_NAME_SET_STREAM_ROUTE_DEVICES,
1162                                                         g_variant_new("(uauau)", index, builder_for_in_devices, builder_for_out_devices),
1163                                                         G_VARIANT_TYPE("(s)"),
1164                                                         G_DBUS_CALL_FLAGS_NONE,
1165                                                         DBUS_METHOD_TIMEOUT,
1166                                                         NULL,
1167                                                         &err);
1168         if (!result || err) {
1169                 //LCOV_EXCL_START
1170                 LOGE("g_dbus_connection_call_sync() for SET_STREAM_ROUTE_DEVICES error (%s)", err ? err->message : NULL);
1171                 if (err)
1172                         g_error_free(err);
1173                 ret = SOUND_MANAGER_ERROR_INTERNAL;
1174                 goto LEAVE;
1175                 //LCOV_EXCL_STOP
1176         }
1177
1178         g_variant_get(result, "(&s)", &dbus_ret);
1179
1180         if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret)))
1181                 ret = SOUND_MANAGER_ERROR_INTERNAL;
1182         else
1183                 info->is_set = true;
1184
1185         LOGI("dbus_ret[%s] ret[0x%x]", dbus_ret, ret);
1186
1187 LEAVE:
1188         if (result)
1189                 g_variant_unref(result);
1190         if (builder_for_in_devices)
1191                 g_variant_builder_unref(builder_for_in_devices);
1192         if (builder_for_out_devices)
1193                 g_variant_builder_unref(builder_for_out_devices);
1194         g_object_unref(conn);
1195
1196         return ret;
1197 }
1198
1199 //LCOV_EXCL_START
1200 int _set_route_option(unsigned int index, const char *name, int value)
1201 {
1202         int ret = SOUND_MANAGER_ERROR_NONE;
1203         GVariant *result = NULL;
1204         GDBusConnection *conn = NULL;
1205         GError *err = NULL;
1206         const gchar *dbus_ret = NULL;
1207
1208         SM_ARG_CHECK(name);
1209
1210         if ((ret = __get_dbus_connection(&conn)) != SOUND_MANAGER_ERROR_NONE)
1211                 return ret;
1212
1213         LOGI("index[%u] name[%s] value[%d]", index, name, value);
1214
1215         result = g_dbus_connection_call_sync(conn,
1216                                                         PA_BUS_NAME,
1217                                                         PA_STREAM_MANAGER_OBJECT_PATH,
1218                                                         PA_STREAM_MANAGER_INTERFACE,
1219                                                         PA_STREAM_MANAGER_METHOD_NAME_SET_STREAM_ROUTE_OPTION,
1220                                                         g_variant_new("(usi)", index, name, value),
1221                                                         G_VARIANT_TYPE("(s)"),
1222                                                         G_DBUS_CALL_FLAGS_NONE,
1223                                                         DBUS_METHOD_TIMEOUT,
1224                                                         NULL,
1225                                                         &err);
1226         if (!result || err) {
1227                 LOGE("g_dbus_connection_call_sync() for SET_STREAM_ROUTE_OPTION error (%s)", err ? err->message : NULL);
1228                 if (err)
1229                         g_error_free(err);
1230                 ret = SOUND_MANAGER_ERROR_INTERNAL;
1231                 goto LEAVE;
1232         }
1233
1234         g_variant_get(result, "(&s)", &dbus_ret);
1235
1236         if (!strncmp("STREAM_MANAGER_RETURN_ERROR_NO_STREAM", dbus_ret, strlen(dbus_ret)))
1237                 ret = SOUND_MANAGER_ERROR_INVALID_STATE;
1238         else if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret)))
1239                 ret = SOUND_MANAGER_ERROR_INTERNAL;
1240
1241         LOGI("dbus_ret[%s] ret[0x%x]", dbus_ret, ret);
1242
1243 LEAVE:
1244         if (result)
1245                 g_variant_unref(result);
1246         g_object_unref(conn);
1247
1248         return ret;
1249 }
1250 //LCOV_EXCL_STOP
1251
1252 int _get_volume_max_level(const char *direction, const char *volume_type, unsigned int *max_level)
1253 {
1254         int ret = SOUND_MANAGER_ERROR_NONE;
1255         GVariant *result = NULL;
1256         GDBusConnection *conn = NULL;
1257         GError *err = NULL;
1258         const gchar *dbus_ret = NULL;
1259
1260         SM_ARG_CHECK(direction);
1261         SM_ARG_CHECK(volume_type);
1262         SM_ARG_CHECK(max_level);
1263
1264         if ((ret = __get_dbus_connection(&conn)) != SOUND_MANAGER_ERROR_NONE)
1265                 return ret;
1266
1267         result = g_dbus_connection_call_sync(conn,
1268                                                         PA_BUS_NAME,
1269                                                         PA_STREAM_MANAGER_OBJECT_PATH,
1270                                                         PA_STREAM_MANAGER_INTERFACE,
1271                                                         PA_STREAM_MANAGER_METHOD_NAME_GET_VOLUME_MAX_LEVEL,
1272                                                         g_variant_new("(ss)", direction, volume_type),
1273                                                         G_VARIANT_TYPE("(us)"),
1274                                                         G_DBUS_CALL_FLAGS_NONE,
1275                                                         DBUS_METHOD_TIMEOUT,
1276                                                         NULL,
1277                                                         &err);
1278         if (!result || err) {
1279                 //LCOV_EXCL_START
1280                 LOGE("g_dbus_connection_call_sync() for GET_VOLUME_MAX_LEVEL error (%s)", err ? err->message : NULL);
1281                 if (err)
1282                         g_error_free(err);
1283                 ret = SOUND_MANAGER_ERROR_INTERNAL;
1284                 goto LEAVE;
1285                 //LCOV_EXCL_STOP
1286         }
1287
1288         g_variant_get(result, "(u&s)", max_level, &dbus_ret);
1289
1290         if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret)))
1291                 ret = SOUND_MANAGER_ERROR_INTERNAL;//LCOV_EXCL_LINE
1292         else
1293                 LOGI("max_level[%u]", *max_level);
1294
1295         LOGI("dbus_ret[%s] ret[0x%x]", dbus_ret, ret);
1296
1297 LEAVE:
1298         if (result)
1299                 g_variant_unref(result);
1300         g_object_unref(conn);
1301
1302         return ret;
1303 }
1304
1305 //LCOV_EXCL_START
1306 int _get_volume_level(const char *direction, const char *volume_type, unsigned int *level)
1307 {
1308         int ret = SOUND_MANAGER_ERROR_NONE;
1309         GVariant *result = NULL;
1310         GDBusConnection *conn = NULL;
1311         GError *err = NULL;
1312         const gchar *dbus_ret = NULL;
1313
1314         SM_ARG_CHECK(direction);
1315         SM_ARG_CHECK(volume_type);
1316         SM_ARG_CHECK(level);
1317
1318         if ((ret = __get_dbus_connection(&conn)) != SOUND_MANAGER_ERROR_NONE)
1319                 return ret;
1320
1321         result = g_dbus_connection_call_sync(conn,
1322                                                         PA_BUS_NAME,
1323                                                         PA_STREAM_MANAGER_OBJECT_PATH,
1324                                                         PA_STREAM_MANAGER_INTERFACE,
1325                                                         PA_STREAM_MANAGER_METHOD_NAME_GET_VOLUME_LEVEL,
1326                                                         g_variant_new("(ss)", direction, volume_type),
1327                                                         G_VARIANT_TYPE("(us)"),
1328                                                         G_DBUS_CALL_FLAGS_NONE,
1329                                                         DBUS_METHOD_TIMEOUT,
1330                                                         NULL,
1331                                                         &err);
1332         if (!result || err) {
1333                 LOGE("g_dbus_connection_call_sync() for GET_VOLUME_LEVEL error (%s)", err ? err->message : NULL);
1334                 if (err)
1335                         g_error_free(err);
1336                 ret = SOUND_MANAGER_ERROR_INTERNAL;
1337                 goto LEAVE;
1338         }
1339
1340         g_variant_get(result, "(u&s)", level, &dbus_ret);
1341
1342         if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret)))
1343                 ret = SOUND_MANAGER_ERROR_INTERNAL;
1344         else
1345                 LOGI("level[%u]", *level);
1346
1347         LOGI("dbus_ret[%s] ret[0x%x]", dbus_ret, ret);
1348
1349 LEAVE:
1350         if (result)
1351                 g_variant_unref(result);
1352         g_object_unref(conn);
1353
1354         return ret;
1355 }
1356
1357 int _set_volume_level(const char *direction, const char *volume_type, unsigned int level)
1358 {
1359         int ret = SOUND_MANAGER_ERROR_NONE;
1360         GVariant *result = NULL;
1361         GDBusConnection *conn = NULL;
1362         GError *err = NULL;
1363         const gchar *dbus_ret = NULL;
1364         int vret = 0;
1365         char volume_path[VCONF_PATH_MAX] = {0,};
1366
1367         SM_ARG_CHECK(direction);
1368         SM_ARG_CHECK(volume_type);
1369
1370         if ((ret = __get_dbus_connection(&conn)) != SOUND_MANAGER_ERROR_NONE)
1371                 return ret;
1372
1373         result = g_dbus_connection_call_sync(conn,
1374                                                         PA_BUS_NAME,
1375                                                         PA_STREAM_MANAGER_OBJECT_PATH,
1376                                                         PA_STREAM_MANAGER_INTERFACE,
1377                                                         PA_STREAM_MANAGER_METHOD_NAME_SET_VOLUME_LEVEL,
1378                                                         g_variant_new("(ssu)", direction, volume_type, level),
1379                                                         G_VARIANT_TYPE("(s)"),
1380                                                         G_DBUS_CALL_FLAGS_NONE,
1381                                                         DBUS_METHOD_TIMEOUT,
1382                                                         NULL,
1383                                                         &err);
1384         if (!result || err) {
1385                 LOGE("g_dbus_connection_call_sync() for SET_VOLUME_LEVEL error (%s)", err ? err->message : NULL);
1386                 if (err)
1387                         g_error_free(err);
1388                 ret = SOUND_MANAGER_ERROR_INTERNAL;
1389                 goto LEAVE;
1390         }
1391
1392         g_variant_get(result, "(&s)", &dbus_ret);
1393
1394         if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret)))
1395                 ret = SOUND_MANAGER_ERROR_INTERNAL;
1396         else {
1397                 /* Set volume value to VCONF */
1398                 snprintf(volume_path, sizeof(volume_path)-1, "%s%s", VCONF_PATH_PREFIX_VOLUME, volume_type);
1399                 if ((vret = vconf_set_int(volume_path, (int)level)))
1400                         LOGE("vconf_set_int(%s) failed..ret[%d]\n", volume_path, vret);
1401         }
1402
1403         LOGI("dbus_ret[%s] ret[0x%x]", dbus_ret, ret);
1404
1405 LEAVE:
1406         if (result)
1407                 g_variant_unref(result);
1408         g_object_unref(conn);
1409
1410         return ret;
1411 }
1412 //LCOV_EXCL_STOP
1413
1414 int _get_current_volume_type(const char *direction, char **volume_type)
1415 {
1416         int ret = SOUND_MANAGER_ERROR_NONE;
1417         GVariant *result = NULL;
1418         GDBusConnection *conn = NULL;
1419         GError *err = NULL;
1420         const gchar *dbus_volume_type = NULL;
1421         const gchar *dbus_ret = NULL;
1422
1423         SM_ARG_CHECK(direction);
1424         SM_ARG_CHECK(volume_type);
1425
1426         if ((ret = __get_dbus_connection(&conn)) != SOUND_MANAGER_ERROR_NONE)
1427                 return ret;
1428
1429         result = g_dbus_connection_call_sync(conn,
1430                                                         PA_BUS_NAME,
1431                                                         PA_STREAM_MANAGER_OBJECT_PATH,
1432                                                         PA_STREAM_MANAGER_INTERFACE,
1433                                                         PA_STREAM_MANAGER_METHOD_NAME_GET_CURRENT_VOLUME_TYPE,
1434                                                         g_variant_new("(s)", direction),
1435                                                         G_VARIANT_TYPE("(ss)"),
1436                                                         G_DBUS_CALL_FLAGS_NONE,
1437                                                         DBUS_METHOD_TIMEOUT,
1438                                                         NULL,
1439                                                         &err);
1440         if (!result || err) {
1441                 //LCOV_EXCL_START
1442                 LOGE("g_dbus_connection_call_sync() for GET_CURRENT_VOLUME_TYPE error (%s)", err ? err->message : NULL);
1443                 if (err)
1444                         g_error_free(err);
1445                 ret = SOUND_MANAGER_ERROR_INTERNAL;
1446                 goto LEAVE;
1447                 //LCOV_EXCL_STOP
1448         }
1449
1450         g_variant_get(result, "(&s&s)", &dbus_volume_type, &dbus_ret);
1451
1452         if (!strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret))) {
1453                 ret = SOUND_MANAGER_ERROR_NONE;//LCOV_EXCL_LINE
1454                 *volume_type = strdup(dbus_volume_type);//LCOV_EXCL_LINE
1455                 LOGI("volume_type[%s]", *volume_type);
1456         } else if (!strncmp("STREAM_MANAGER_RETURN_ERROR_NO_STREAM", dbus_ret, strlen(dbus_ret))) {
1457                 ret = SOUND_MANAGER_ERROR_NO_PLAYING_SOUND;
1458         } else {
1459                 ret = SOUND_MANAGER_ERROR_INTERNAL;//LCOV_EXCL_LINE
1460         }
1461
1462         LOGI("dbus_ret[%s] ret[0x%x]", dbus_ret, ret);
1463
1464 LEAVE:
1465         if (result)
1466                 g_variant_unref(result);
1467         g_object_unref(conn);
1468
1469         return ret;
1470 }
1471
1472 int _get_current_media_routing_path(const char *direction, int *device_id, sound_device_type_e *device_type)
1473 {
1474         int ret = SOUND_MANAGER_ERROR_NONE;
1475         GVariant *result = NULL;
1476         GDBusConnection *conn = NULL;
1477         GError *err = NULL;
1478         const gchar *dbus_device_type = NULL;
1479         const gchar *dbus_ret = NULL;
1480         unsigned int dbus_device_id;
1481
1482         SM_ARG_CHECK(direction);
1483         SM_ARG_CHECK(device_id);
1484         SM_ARG_CHECK(device_type);
1485
1486         if ((ret = __get_dbus_connection(&conn)) != SOUND_MANAGER_ERROR_NONE)
1487                 return ret;
1488
1489         result = g_dbus_connection_call_sync(conn,
1490                                                         PA_BUS_NAME,
1491                                                         PA_STREAM_MANAGER_OBJECT_PATH,
1492                                                         PA_STREAM_MANAGER_INTERFACE,
1493                                                         PA_STREAM_MANAGER_METHOD_NAME_GET_CURRENT_MEDIA_ROUTING_PATH,
1494                                                         g_variant_new("(s)", direction),
1495                                                         G_VARIANT_TYPE("(uss)"),
1496                                                         G_DBUS_CALL_FLAGS_NONE,
1497                                                         DBUS_METHOD_TIMEOUT,
1498                                                         NULL,
1499                                                         &err);
1500         if (!result || err) {
1501                 //LCOV_EXCL_START
1502                 LOGE("g_dbus_connection_call_sync() for GET_CURRENT_MEDIA_ROUTING_PATH error (%s)", err ? err->message : NULL);
1503                 if (err)
1504                         g_error_free(err);
1505                 ret = SOUND_MANAGER_ERROR_INTERNAL;
1506                 goto LEAVE;
1507                 //LCOV_EXCL_STOP
1508         }
1509
1510         g_variant_get(result, "(u&s&s)", &dbus_device_id, &dbus_device_type, &dbus_ret);
1511
1512         if (!strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret))) {
1513                 *device_id = (int)dbus_device_id;
1514                 if (_convert_device_type_str_to_enum(dbus_device_type, device_type) < 0)
1515                         ret = SOUND_MANAGER_ERROR_INTERNAL;//LCOV_EXCL_LINE
1516         } else {
1517                 ret = (!strncmp("none", dbus_device_type, strlen(dbus_device_type))) ?
1518                         SOUND_MANAGER_ERROR_NO_DATA : SOUND_MANAGER_ERROR_INTERNAL;
1519         }
1520
1521         LOGI("dbus_ret[%s] ret[0x%x]", dbus_ret, ret);
1522
1523 LEAVE:
1524         if (result)
1525                 g_variant_unref(result);
1526         g_object_unref(conn);
1527
1528         return ret;
1529 }
1530
1531 void _update_focus_status(unsigned int index, unsigned int acquired_focus_status)
1532 {
1533         GVariant *result = NULL;
1534         GDBusConnection *conn = NULL;
1535         GError *err = NULL;
1536         const gchar *dbus_ret = NULL;
1537
1538         if (__get_dbus_connection(&conn))
1539                 return;
1540
1541         result = g_dbus_connection_call_sync(conn,
1542                                                         PA_BUS_NAME,
1543                                                         PA_STREAM_MANAGER_OBJECT_PATH,
1544                                                         PA_STREAM_MANAGER_INTERFACE,
1545                                                         PA_STREAM_MANAGER_METHOD_NAME_UPDATE_FOCUS_STATUS,
1546                                                         g_variant_new("(uu)", index, acquired_focus_status),
1547                                                         G_VARIANT_TYPE("(s)"),
1548                                                         G_DBUS_CALL_FLAGS_NONE,
1549                                                         DBUS_METHOD_TIMEOUT,
1550                                                         NULL,
1551                                                         &err);
1552         if (!result || err) {
1553                 //LCOV_EXCL_START
1554                 LOGE("g_dbus_connection_call_sync() for UPDATE_FOCUS_STATUS error (%s)", err ? err->message : NULL);
1555                 if (err)
1556                         g_error_free(err);
1557                 goto LEAVE;
1558                 //LCOV_EXCL_STOP
1559         }
1560         g_variant_get(result, "(&s)", &dbus_ret);
1561         LOGI("g_dbus_connection_call_sync() success, method return value is (%s)", dbus_ret);
1562         if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret)))
1563                 LOGE("failed to UPDATE_FOCUS_STATUS error (%s)", dbus_ret);//LCOV_EXCL_LINE
1564
1565 LEAVE:
1566         if (result)
1567                 g_variant_unref(result);
1568         g_object_unref(conn);
1569 }
1570
1571 //LCOV_EXCL_START
1572 int _is_device_running_by_id(int device_id, bool *is_running)
1573 {
1574         int ret = SOUND_MANAGER_ERROR_NONE;
1575         GVariant *result = NULL;
1576         GDBusConnection *conn = NULL;
1577         GError *err = NULL;
1578         gboolean _is_running;
1579
1580         SM_ARG_CHECK(is_running);
1581
1582         if ((ret = __get_dbus_connection(&conn)) != SOUND_MANAGER_ERROR_NONE)
1583                 return ret;
1584
1585         result = g_dbus_connection_call_sync(conn,
1586                                                                           PA_BUS_NAME,
1587                                                                           PA_DEVICE_MANAGER_OBJECT_PATH,
1588                                                                           PA_DEVICE_MANAGER_INTERFACE,
1589                                                                           PA_DEVICE_MANAGER_METHOD_NAME_IS_DEVICE_RUNNING_BY_ID,
1590                                                                           g_variant_new("(i)", device_id),
1591                                                                           G_VARIANT_TYPE("(b)"),
1592                                                                           G_DBUS_CALL_FLAGS_NONE,
1593                                                                           DBUS_METHOD_TIMEOUT,
1594                                                                           NULL,
1595                                                                           &err);
1596         if (err) {
1597                 LOGE("g_dbus_connection_call_sync() for IS_DEVICE_RUNNING_BY_ID error (%s)", err->message);
1598                 ret = _convert_sound_manager_error_code(__func__, _convert_dbus_error(err->message));
1599                 g_error_free(err);
1600                 goto LEAVE;
1601         } else {
1602                 g_variant_get(result, "(b)", &_is_running);
1603                 *is_running = (bool)_is_running;
1604                 LOGI("device_id[%d] is [%s]", device_id, *is_running ? "Running" : "Not running");
1605         }
1606
1607 LEAVE:
1608         if (result)
1609                 g_variant_unref(result);
1610         g_object_unref(conn);
1611
1612         return ret;
1613 }
1614
1615 #define SM_SAMPLE_FORMAT_NUM    4 /* check declaration of sound_sample_format_e */
1616 int _get_supported_sample_formats(int device_id, sound_sample_format_e **formats, unsigned int *num)
1617 {
1618         int ret = SOUND_MANAGER_ERROR_NONE;
1619         GVariant *result = NULL;
1620         GDBusConnection *conn = NULL;
1621         GError *err = NULL;
1622         GVariantIter *iter = NULL;
1623         gchar *format_str;
1624         unsigned int iter_num;
1625         unsigned int elem_num = 0;
1626         sound_sample_format_e format;
1627         sound_sample_format_e sm_formats[SM_SAMPLE_FORMAT_NUM] = {0, };
1628
1629         SM_ARG_CHECK(formats);
1630         SM_ARG_CHECK(num);
1631
1632         if ((ret = __get_dbus_connection(&conn)) != SOUND_MANAGER_ERROR_NONE)
1633                 return ret;
1634
1635         result = g_dbus_connection_call_sync(conn,
1636                                                         PA_BUS_NAME,
1637                                                         PA_DEVICE_MANAGER_OBJECT_PATH,
1638                                                         PA_DEVICE_MANAGER_INTERFACE,
1639                                                         PA_DEVICE_MANAGER_METHOD_NAME_GET_SUPPORTED_SAMPLE_FORMATS,
1640                                                         g_variant_new("(i)", device_id),
1641                                                         G_VARIANT_TYPE("(as)"),
1642                                                         G_DBUS_CALL_FLAGS_NONE,
1643                                                         DBUS_METHOD_TIMEOUT,
1644                                                         NULL,
1645                                                         &err);
1646         if (!result || err) {
1647                 LOGE("g_dbus_connection_call_sync() for GET_SUPPORTED_SAMPLE_FORMATS error (%s)", err ? err->message : NULL);
1648                 ret = _convert_sound_manager_error_code(__func__, _convert_dbus_error(err ? err->message : NULL));
1649                 if (err)
1650                         g_error_free(err);
1651                 goto LEAVE;
1652         }
1653
1654         g_variant_get(result, "(as)", &iter);
1655         if ((iter_num = (unsigned int) g_variant_iter_n_children(iter)) == 0) {
1656                 LOGE("could not get supported sample formats");
1657                 ret = SOUND_MANAGER_ERROR_INTERNAL;
1658                 goto LEAVE;
1659         }
1660
1661         while (g_variant_iter_loop(iter, "&s", &format_str)) {
1662                 if (_convert_sample_format_str_to_enum((const char *)format_str, &format) != SOUND_MANAGER_ERROR_NONE)
1663                         continue;
1664                 elem_num++;
1665                 sm_formats[elem_num - 1] = format;
1666         }
1667
1668         if (elem_num == 0) {
1669                 LOGE("could not find supported sample formats");
1670                 ret = SOUND_MANAGER_ERROR_INTERNAL;
1671                 goto LEAVE;
1672         }
1673
1674         if (!(*formats = (sound_sample_format_e *) calloc(elem_num, sizeof(sound_sample_format_e)))) {
1675                 LOGE("failed to calloc(), elem_num(%d)", elem_num);
1676                 ret = SOUND_MANAGER_ERROR_INTERNAL;
1677                 goto LEAVE;
1678         } else {
1679                 memcpy(*formats, sm_formats, elem_num * sizeof(sound_sample_format_e));
1680         }
1681
1682         *num = elem_num;
1683
1684         LOGI("num[%d]", *num);
1685
1686 LEAVE:
1687         if (iter)
1688                 g_variant_iter_free(iter);
1689         if (result)
1690                 g_variant_unref(result);
1691         g_object_unref(conn);
1692
1693         return ret;
1694 }
1695
1696 int _set_sample_format(int device_id, sound_sample_format_e format)
1697 {
1698         int ret = SOUND_MANAGER_ERROR_NONE;
1699         GDBusConnection *conn = NULL;
1700         GVariant *result = NULL;
1701         GError *err = NULL;
1702         const char *format_str = NULL;
1703
1704         if ((ret = __get_dbus_connection(&conn)) != SOUND_MANAGER_ERROR_NONE)
1705                 return ret;
1706
1707         if ((ret = _convert_sample_format_enum_to_str(format, &format_str)) != SOUND_MANAGER_ERROR_NONE)
1708                 return ret;
1709
1710         result = g_dbus_connection_call_sync(conn,
1711                                                 PA_BUS_NAME,
1712                                                 PA_DEVICE_MANAGER_OBJECT_PATH,
1713                                                 PA_DEVICE_MANAGER_INTERFACE,
1714                                                 PA_DEVICE_MANAGER_METHOD_NAME_SET_SAMPLE_FORMAT,
1715                                                 g_variant_new("(is)", device_id, format_str),
1716                                                 NULL,
1717                                                 G_DBUS_CALL_FLAGS_NONE,
1718                                                 DBUS_METHOD_TIMEOUT,
1719                                                 NULL,
1720                                                 &err);
1721         if (err) {
1722                 LOGE("g_dbus_connection_call_sync() for SET_SAMPLE_FORMAT error (%s)", err->message);
1723                 ret = _convert_sound_manager_error_code(__func__, _convert_dbus_error(err->message));
1724                 g_error_free(err);
1725         }
1726
1727         if (result)
1728                 g_variant_unref(result);
1729
1730         g_object_unref(conn);
1731
1732         return ret;
1733 }
1734
1735 int _get_sample_format(int device_id, sound_sample_format_e *format)
1736 {
1737         int ret = SOUND_MANAGER_ERROR_NONE;
1738         GVariant *result = NULL;
1739         GDBusConnection *conn = NULL;
1740         GError *err = NULL;
1741         gchar *format_str;
1742         sound_sample_format_e format_e;
1743
1744         SM_ARG_CHECK(format);
1745
1746         if ((ret = __get_dbus_connection(&conn)) != SOUND_MANAGER_ERROR_NONE)
1747                 return ret;
1748
1749         result = g_dbus_connection_call_sync(conn,
1750                                                         PA_BUS_NAME,
1751                                                         PA_DEVICE_MANAGER_OBJECT_PATH,
1752                                                         PA_DEVICE_MANAGER_INTERFACE,
1753                                                         PA_DEVICE_MANAGER_METHOD_NAME_GET_SAMPLE_FORMAT,
1754                                                         g_variant_new("(i)", device_id),
1755                                                         G_VARIANT_TYPE("(s)"),
1756                                                         G_DBUS_CALL_FLAGS_NONE,
1757                                                         DBUS_METHOD_TIMEOUT,
1758                                                         NULL,
1759                                                         &err);
1760         if (!result || err) {
1761                 LOGE("g_dbus_connection_call_sync() for GET_SAMPLE_FORMAT error (%s)", err ? err->message : NULL);
1762                 ret = _convert_sound_manager_error_code(__func__, _convert_dbus_error(err ? err->message : NULL));
1763                 if (err)
1764                         g_error_free(err);
1765                 goto LEAVE;
1766         }
1767         g_variant_get(result, "(&s)", &format_str);
1768         if ((ret = _convert_sample_format_str_to_enum((const char *)format_str, &format_e)) == SOUND_MANAGER_ERROR_NONE)
1769                 *format = format_e;
1770
1771 LEAVE:
1772         if (result)
1773                 g_variant_unref(result);
1774         g_object_unref(conn);
1775
1776         return ret;
1777 }
1778
1779 #define SM_SAMPLE_RATE_NUM    8 /* check declaration of sound_sample_rate_e */
1780 int _get_supported_sample_rates(int device_id, sound_sample_rate_e **rates, unsigned int *num)
1781 {
1782         int ret = SOUND_MANAGER_ERROR_NONE;
1783         GVariant *result = NULL;
1784         GDBusConnection *conn = NULL;
1785         GError *err = NULL;
1786         GVariantIter *iter = NULL;
1787         unsigned int rate;
1788         unsigned int iter_num;
1789         unsigned int elem_num = 0;
1790         sound_sample_rate_e rate_e;
1791         sound_sample_rate_e sm_rates[SM_SAMPLE_RATE_NUM] = {0, };
1792
1793         SM_ARG_CHECK(rates);
1794         SM_ARG_CHECK(num);
1795
1796         if ((ret = __get_dbus_connection(&conn)) != SOUND_MANAGER_ERROR_NONE)
1797                 return ret;
1798
1799         result = g_dbus_connection_call_sync(conn,
1800                                                         PA_BUS_NAME,
1801                                                         PA_DEVICE_MANAGER_OBJECT_PATH,
1802                                                         PA_DEVICE_MANAGER_INTERFACE,
1803                                                         PA_DEVICE_MANAGER_METHOD_NAME_GET_SUPPORTED_SAMPLE_RATES,
1804                                                         g_variant_new("(i)", device_id),
1805                                                         G_VARIANT_TYPE("(au)"),
1806                                                         G_DBUS_CALL_FLAGS_NONE,
1807                                                         DBUS_METHOD_TIMEOUT,
1808                                                         NULL,
1809                                                         &err);
1810         if (!result || err) {
1811                 LOGE("g_dbus_connection_call_sync() for GET_SUPPORTED_SAMPLE_RATES error (%s)", err ? err->message : NULL);
1812                 ret = _convert_sound_manager_error_code(__func__, _convert_dbus_error(err ? err->message : NULL));
1813                 if (err)
1814                         g_error_free(err);
1815                 goto LEAVE;
1816         }
1817
1818         g_variant_get(result, "(au)", &iter);
1819         if ((iter_num = (unsigned int) g_variant_iter_n_children(iter)) == 0) {
1820                 LOGE("could not get supported sample rates");
1821                 ret = SOUND_MANAGER_ERROR_INTERNAL;
1822                 goto LEAVE;
1823         }
1824
1825         while (g_variant_iter_loop(iter, "u", &rate)) {
1826                 if (_convert_sample_rate_to_enum(rate, &rate_e) != SOUND_MANAGER_ERROR_NONE)
1827                         continue;
1828                 elem_num++;
1829                 sm_rates[elem_num - 1] = rate_e;
1830         }
1831
1832         if (elem_num == 0) {
1833                 LOGE("could not find supported sample rates");
1834                 ret = SOUND_MANAGER_ERROR_INTERNAL;
1835                 goto LEAVE;
1836         }
1837
1838         if (!(*rates = (sound_sample_rate_e *) calloc(elem_num, sizeof(sound_sample_rate_e)))) {
1839                 LOGE("failed to calloc(), elem_num(%d)", elem_num);
1840                 ret = SOUND_MANAGER_ERROR_INTERNAL;
1841                 goto LEAVE;
1842         } else {
1843                 memcpy(*rates, sm_rates, elem_num * sizeof(sound_sample_rate_e));
1844         }
1845
1846         *num = elem_num;
1847
1848         LOGI("num[%d]", *num);
1849
1850 LEAVE:
1851         if (iter)
1852                 g_variant_iter_free(iter);
1853         if (result)
1854                 g_variant_unref(result);
1855         g_object_unref(conn);
1856
1857         return ret;
1858 }
1859
1860 int _set_sample_rate(int device_id, sound_sample_rate_e rate)
1861 {
1862         int ret = SOUND_MANAGER_ERROR_NONE;
1863         GDBusConnection *conn = NULL;
1864         GVariant *result = NULL;
1865         GError *err = NULL;
1866         unsigned int _rate;
1867
1868         if ((ret = __get_dbus_connection(&conn)) != SOUND_MANAGER_ERROR_NONE)
1869                 return ret;
1870
1871         if ((ret = _convert_sample_rate_enum_to_uint(rate, &_rate)) != SOUND_MANAGER_ERROR_NONE)
1872                 return ret;
1873
1874         result = g_dbus_connection_call_sync(conn,
1875                                                 PA_BUS_NAME,
1876                                                 PA_DEVICE_MANAGER_OBJECT_PATH,
1877                                                 PA_DEVICE_MANAGER_INTERFACE,
1878                                                 PA_DEVICE_MANAGER_METHOD_NAME_SET_SAMPLE_RATE,
1879                                                 g_variant_new("(iu)", device_id, _rate),
1880                                                 NULL,
1881                                                 G_DBUS_CALL_FLAGS_NONE,
1882                                                 DBUS_METHOD_TIMEOUT,
1883                                                 NULL,
1884                                                 &err);
1885         if (err) {
1886                 LOGE("g_dbus_connection_call_sync() for SET_SAMPLE_RATE error (%s)", err->message);
1887                 ret = _convert_sound_manager_error_code(__func__, _convert_dbus_error(err->message));
1888                 g_error_free(err);
1889         }
1890
1891         if (result)
1892                 g_variant_unref(result);
1893
1894         g_object_unref(conn);
1895
1896         return ret;
1897 }
1898
1899 int _get_sample_rate(int device_id, sound_sample_rate_e *rate)
1900 {
1901         int ret = SOUND_MANAGER_ERROR_NONE;
1902         GVariant *result = NULL;
1903         GDBusConnection *conn = NULL;
1904         GError *err = NULL;
1905         unsigned int _rate;
1906         sound_sample_rate_e rate_e;
1907
1908         SM_ARG_CHECK(rate);
1909
1910         if ((ret = __get_dbus_connection(&conn)) != SOUND_MANAGER_ERROR_NONE)
1911                 return ret;
1912
1913         result = g_dbus_connection_call_sync(conn,
1914                                                         PA_BUS_NAME,
1915                                                         PA_DEVICE_MANAGER_OBJECT_PATH,
1916                                                         PA_DEVICE_MANAGER_INTERFACE,
1917                                                         PA_DEVICE_MANAGER_METHOD_NAME_GET_SAMPLE_RATE,
1918                                                         g_variant_new("(i)", device_id),
1919                                                         G_VARIANT_TYPE("(u)"),
1920                                                         G_DBUS_CALL_FLAGS_NONE,
1921                                                         DBUS_METHOD_TIMEOUT,
1922                                                         NULL,
1923                                                         &err);
1924         if (!result || err) {
1925                 LOGE("g_dbus_connection_call_sync() for GET_SAMPLE_RATE error (%s)", err ? err->message : NULL);
1926                 ret = _convert_sound_manager_error_code(__func__, _convert_dbus_error(err ? err->message : NULL));
1927                 if (err)
1928                         g_error_free(err);
1929                 goto LEAVE;
1930         }
1931         g_variant_get(result, "(u)", &_rate);
1932         if ((ret = _convert_sample_rate_to_enum(_rate, &rate_e)) == SOUND_MANAGER_ERROR_NONE)
1933                 *rate = rate_e;
1934
1935 LEAVE:
1936         if (result)
1937                 g_variant_unref(result);
1938         g_object_unref(conn);
1939
1940         return ret;
1941 }
1942
1943 int _set_avoid_resampling(int device_id, bool enable)
1944 {
1945         int ret = SOUND_MANAGER_ERROR_NONE;
1946         GDBusConnection *conn = NULL;
1947         GVariant *result = NULL;
1948         GError *err = NULL;
1949
1950         if ((ret = __get_dbus_connection(&conn)) != SOUND_MANAGER_ERROR_NONE)
1951                 return ret;
1952
1953         result = g_dbus_connection_call_sync(conn,
1954                                                 PA_BUS_NAME,
1955                                                 PA_DEVICE_MANAGER_OBJECT_PATH,
1956                                                 PA_DEVICE_MANAGER_INTERFACE,
1957                                                 PA_DEVICE_MANAGER_METHOD_NAME_SET_AVOID_RESAMPLING,
1958                                                 g_variant_new("(ib)", device_id, enable),
1959                                                 NULL,
1960                                                 G_DBUS_CALL_FLAGS_NONE,
1961                                                 DBUS_METHOD_TIMEOUT,
1962                                                 NULL,
1963                                                 &err);
1964         if (err) {
1965                 LOGE("g_dbus_connection_call_sync() for SET_AVOID_RESAMPLING error (%s)", err->message);
1966                 ret = _convert_sound_manager_error_code(__func__, _convert_dbus_error(err->message));
1967                 g_error_free(err);
1968         }
1969
1970         if (result)
1971                 g_variant_unref(result);
1972
1973         g_object_unref(conn);
1974
1975         return ret;
1976 }
1977
1978 int _get_avoid_resampling(int device_id, bool *enabled)
1979 {
1980         int ret = SOUND_MANAGER_ERROR_NONE;
1981         GVariant *result = NULL;
1982         GDBusConnection *conn = NULL;
1983         GError *err = NULL;
1984         gboolean _enabled;
1985
1986         SM_ARG_CHECK(enabled);
1987
1988         if ((ret = __get_dbus_connection(&conn)) != SOUND_MANAGER_ERROR_NONE)
1989                 return ret;
1990
1991         result = g_dbus_connection_call_sync(conn,
1992                                                         PA_BUS_NAME,
1993                                                         PA_DEVICE_MANAGER_OBJECT_PATH,
1994                                                         PA_DEVICE_MANAGER_INTERFACE,
1995                                                         PA_DEVICE_MANAGER_METHOD_NAME_GET_AVOID_RESAMPLING,
1996                                                         g_variant_new("(i)", device_id),
1997                                                         G_VARIANT_TYPE("(b)"),
1998                                                         G_DBUS_CALL_FLAGS_NONE,
1999                                                         DBUS_METHOD_TIMEOUT,
2000                                                         NULL,
2001                                                         &err);
2002         if (!result || err) {
2003                 LOGE("g_dbus_connection_call_sync() for GET_AVOID_RESAMPLING error (%s)", err ? err->message : NULL);
2004                 ret = _convert_sound_manager_error_code(__func__, _convert_dbus_error(err ? err->message : NULL));
2005                 if (err)
2006                         g_error_free(err);
2007                 goto LEAVE;
2008         }
2009
2010         g_variant_get(result, "(b)", &_enabled);
2011         *enabled = (bool)_enabled;
2012
2013         LOGI("enabled[%d]", *enabled);
2014
2015 LEAVE:
2016         if (result)
2017                 g_variant_unref(result);
2018         g_object_unref(conn);
2019
2020         return ret;
2021 }
2022
2023 int _set_media_stream_only(int device_id, bool enable)
2024 {
2025         int ret = SOUND_MANAGER_ERROR_NONE;
2026         GDBusConnection *conn = NULL;
2027         GVariant *result = NULL;
2028         GError *err = NULL;
2029         const char *stream_type;
2030
2031         if ((ret = __get_dbus_connection(&conn)) != SOUND_MANAGER_ERROR_NONE)
2032                 return ret;
2033
2034         if (enable)
2035                 stream_type = STREAM_MEDIA;
2036         else
2037                 stream_type = "none";
2038
2039         result = g_dbus_connection_call_sync(conn,
2040                                                 PA_BUS_NAME,
2041                                                 PA_DEVICE_MANAGER_OBJECT_PATH,
2042                                                 PA_DEVICE_MANAGER_INTERFACE,
2043                                                 PA_DEVICE_MANAGER_METHOD_NAME_SET_SPECIFIC_STREAM,
2044                                                 g_variant_new("(is)", device_id, stream_type),
2045                                                 NULL,
2046                                                 G_DBUS_CALL_FLAGS_NONE,
2047                                                 DBUS_METHOD_TIMEOUT,
2048                                                 NULL,
2049                                                 &err);
2050         if (err) {
2051                 LOGE("g_dbus_connection_call_sync() for SET_SPECIFIC_STREAM error (%s)", err->message);
2052                 ret = _convert_sound_manager_error_code(__func__, _convert_dbus_error(err->message));
2053                 g_error_free(err);
2054         }
2055
2056         if (result)
2057                 g_variant_unref(result);
2058
2059         g_object_unref(conn);
2060
2061         return ret;
2062 }
2063
2064 int _get_media_stream_only(int device_id, bool *enabled)
2065 {
2066         int ret = SOUND_MANAGER_ERROR_NONE;
2067         GVariant *result = NULL;
2068         GDBusConnection *conn = NULL;
2069         GError *err = NULL;
2070         char *stream_type;
2071
2072         SM_ARG_CHECK(enabled);
2073
2074         if ((ret = __get_dbus_connection(&conn)) != SOUND_MANAGER_ERROR_NONE)
2075                 return ret;
2076
2077         result = g_dbus_connection_call_sync(conn,
2078                                                         PA_BUS_NAME,
2079                                                         PA_DEVICE_MANAGER_OBJECT_PATH,
2080                                                         PA_DEVICE_MANAGER_INTERFACE,
2081                                                         PA_DEVICE_MANAGER_METHOD_NAME_GET_SPECIFIED_STREAM,
2082                                                         g_variant_new("(i)", device_id),
2083                                                         G_VARIANT_TYPE("(s)"),
2084                                                         G_DBUS_CALL_FLAGS_NONE,
2085                                                         DBUS_METHOD_TIMEOUT,
2086                                                         NULL,
2087                                                         &err);
2088         if (!result || err) {
2089                 LOGE("g_dbus_connection_call_sync() for GET_SPECIFIED_STREAM error (%s)", err ? err->message : NULL);
2090                 ret = _convert_sound_manager_error_code(__func__, _convert_dbus_error(err ? err->message : NULL));
2091                 if (err)
2092                         g_error_free(err);
2093                 goto LEAVE;
2094         }
2095
2096         g_variant_get(result, "(&s)", &stream_type);
2097         if (!strncmp(stream_type, STREAM_MEDIA, SOUND_STREAM_TYPE_LEN))
2098                 *enabled = true;
2099         else
2100                 *enabled = false;
2101
2102         LOGI("enabled[%d]", *enabled);
2103
2104 LEAVE:
2105         if (result)
2106                 g_variant_unref(result);
2107         g_object_unref(conn);
2108
2109         return ret;
2110 }
2111 //LCOV_EXCL_STOP
2112
2113 int _make_pa_connection(sound_pa_info_s *pa_info, const char *context_name)
2114 {
2115         int pa_ret = PA_OK;
2116
2117         SM_ARG_CHECK(pa_info);
2118
2119         if (!(pa_info->mainloop = pa_threaded_mainloop_new()))
2120                 goto PA_ERROR;
2121
2122         if (!(pa_info->context = pa_context_new(pa_threaded_mainloop_get_api(pa_info->mainloop), context_name)))
2123                 goto PA_ERROR;
2124
2125         pa_context_set_state_callback(pa_info->context, _pa_context_state_cb, pa_info);
2126
2127         if (pa_context_connect(pa_info->context, NULL, 0, NULL) < 0) {
2128                 pa_ret = pa_context_errno(pa_info->context);//LCOV_EXCL_LINE
2129                 goto PA_ERROR;
2130         }
2131
2132         pa_threaded_mainloop_lock(pa_info->mainloop);
2133
2134         if (pa_threaded_mainloop_start(pa_info->mainloop) < 0)
2135                 goto PA_ERROR_WITH_UNLOCK;
2136
2137         /* wait for ready state of the context */
2138         for (;;) {
2139                 pa_context_state_t state;
2140                 state = pa_context_get_state(pa_info->context);
2141                 if (state == PA_CONTEXT_READY)
2142                         break;
2143                 if (!PA_CONTEXT_IS_GOOD(state)) {
2144                         pa_ret = pa_context_errno(pa_info->context);//LCOV_EXCL_LINE
2145                         goto PA_ERROR_WITH_UNLOCK;
2146                 }
2147                 pa_threaded_mainloop_wait(pa_info->mainloop);
2148         }
2149
2150         /* get index of this context */
2151         pa_info->index = pa_context_get_index(pa_info->context);
2152
2153         pa_threaded_mainloop_unlock(pa_info->mainloop);
2154
2155         return SOUND_MANAGER_ERROR_NONE;
2156 //LCOV_EXCL_START
2157 PA_ERROR_WITH_UNLOCK:
2158         pa_threaded_mainloop_unlock(pa_info->mainloop);
2159
2160 PA_ERROR:
2161         _destroy_pa_connection(pa_info);
2162         LOGE("pa_ret %d", pa_ret);
2163
2164         return SOUND_MANAGER_ERROR_INTERNAL;
2165 //LCOV_EXCL_STOP
2166 }
2167
2168 int _make_pa_connection_and_register_focus(sound_stream_info_s *stream_h, sound_stream_focus_state_changed_cb callback, void *user_data)
2169 {
2170         int ret = SOUND_MANAGER_ERROR_NONE;
2171         int mm_ret = MM_ERROR_NONE;
2172         int i = 0;
2173         bool is_focus_cb_thread = false;
2174
2175         if ((mm_ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread, NULL)) != MM_ERROR_NONE)
2176                 return _convert_sound_manager_error_code(__func__, mm_ret);
2177
2178         if (is_focus_cb_thread)
2179                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
2180
2181         /* get configuration information of this stream type */
2182         if ((ret = _get_stream_conf_info(stream_h->stream_type, &stream_h->stream_conf_info)) != SOUND_MANAGER_ERROR_NONE)
2183                 return ret;
2184
2185         LOGI("stream_conf_info : stream type[%s], priority[%d], route type[%d]",
2186                 stream_h->stream_type, stream_h->stream_conf_info.priority, stream_h->stream_conf_info.route_type);
2187
2188         if ((ret = _make_pa_connection(&stream_h->pa_info, "SOUND_MANAGER_STREAM_INFO")) != SOUND_MANAGER_ERROR_NONE)
2189                 goto ERROR;
2190
2191         /* register focus */
2192         if (!stream_h->is_focus_unavailable) {
2193                 mm_ret = mm_sound_register_focus(stream_h->stream_type, _focus_state_change_callback, stream_h, &stream_h->focus_id);
2194                 if (mm_ret == MM_ERROR_NONE) {
2195                         stream_h->user_cb = callback;
2196                         stream_h->user_data = user_data;
2197                 } else {
2198                         LOGE("failed to register focus, ret(0x%x)", mm_ret);//LCOV_EXCL_LINE
2199                         ret = _convert_sound_manager_error_code(__func__, mm_ret);
2200                         goto ERROR;
2201                 }
2202         }
2203         goto SUCCESS;
2204 //LCOV_EXCL_START
2205 ERROR:
2206         for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
2207                 SM_SAFE_FREE(stream_h->stream_conf_info.avail_in_devices[i]);
2208                 SM_SAFE_FREE(stream_h->stream_conf_info.avail_out_devices[i]);
2209         }
2210         for (i = 0; i < AVAIL_FRAMEWORKS_MAX; i++)
2211                 SM_SAFE_FREE(stream_h->stream_conf_info.avail_frameworks[i]);
2212
2213         SM_SAFE_FREE(stream_h->stream_conf_info.volume_type);
2214
2215         _destroy_pa_connection(&stream_h->pa_info);
2216 //LCOV_EXCL_STOP
2217 SUCCESS:
2218         return ret;
2219 }
2220
2221 void _destroy_pa_connection(sound_pa_info_s *pa_info)
2222 {
2223         if (!pa_info) {
2224                 LOGW("NULL pa info - skip..");
2225                 return;
2226         }
2227
2228         LOGI("[%p][%p]", pa_info->mainloop, pa_info->context);
2229
2230         if (pa_info->mainloop)
2231                 pa_threaded_mainloop_stop(pa_info->mainloop);
2232
2233         if (pa_info->context) {
2234                 pa_context_disconnect(pa_info->context);
2235                 pa_context_unref(pa_info->context);
2236                 pa_info->context = NULL;
2237         }
2238
2239         if (pa_info->mainloop) {
2240                 pa_threaded_mainloop_free(pa_info->mainloop);
2241                 pa_info->mainloop = NULL;
2242         }
2243 }
2244
2245 int _destroy_pa_connection_and_unregister_focus(sound_stream_info_s *stream_h)
2246 {
2247         int i = 0;
2248         int ret = SOUND_MANAGER_ERROR_NONE;
2249         int mm_ret = MM_ERROR_NONE;
2250         bool is_focus_cb_thread = false;
2251
2252         if ((mm_ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread, NULL)) != MM_ERROR_NONE)
2253                 return _convert_sound_manager_error_code(__func__, mm_ret);
2254
2255         if (is_focus_cb_thread)
2256                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
2257
2258         _destroy_pa_connection(&stream_h->pa_info);
2259
2260         /* unregister focus */
2261         if (!stream_h->is_focus_unavailable) {
2262                 mm_ret = mm_sound_unregister_focus(stream_h->focus_id);
2263                 if (mm_ret) {
2264                         LOGE("failed to unregister focus, ret(0x%x)", mm_ret);//LCOV_EXCL_LINE
2265                         ret = _convert_sound_manager_error_code(__func__, mm_ret);
2266                 }
2267         }
2268
2269         for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
2270                 SM_SAFE_FREE(stream_h->stream_conf_info.avail_in_devices[i]);
2271                 SM_SAFE_FREE(stream_h->stream_conf_info.avail_out_devices[i]);
2272         }
2273         for (i = 0; i < AVAIL_FRAMEWORKS_MAX; i++)
2274                 SM_SAFE_FREE(stream_h->stream_conf_info.avail_frameworks[i]);
2275
2276         SM_SAFE_FREE(stream_h->stream_conf_info.volume_type);
2277
2278         return ret;
2279 }
2280
2281 //LCOV_EXCL_START
2282 static int __dbus_method_call(const char *method, GVariant *param, GVariant **reply)
2283 {
2284         GDBusConnection *conn = NULL;
2285         GVariant *_reply = NULL;
2286         GError *err = NULL;
2287         int ret;
2288
2289         if (!method || !param) {
2290                 LOGE("invalid parameter");
2291                 ret = SOUND_MANAGER_ERROR_INVALID_PARAMETER;
2292                 goto error;
2293         }
2294
2295         if ((ret = __get_dbus_connection(&conn)) != SOUND_MANAGER_ERROR_NONE) {
2296                 ret = SOUND_MANAGER_ERROR_INVALID_OPERATION;
2297                 goto error;
2298         }
2299
2300         _reply = g_dbus_connection_call_sync(conn, PA_BUS_NAME,
2301                 PA_STREAM_MANAGER_OBJECT_PATH,
2302                 PA_STREAM_MANAGER_INTERFACE,
2303                 method, param, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
2304
2305         g_object_unref(conn);
2306
2307         if (!_reply) {
2308                 ret =  _convert_dbus_error(err->message);
2309                 LOGE("g_dbus_connection_call_sync() method(%s), err-msg(%s)", method, err->message);
2310                 g_error_free(err);
2311                 return ret;
2312         }
2313
2314         if (reply)
2315                 *reply = _reply;
2316         else
2317                 g_variant_unref(_reply);
2318
2319         return SOUND_MANAGER_ERROR_NONE;
2320
2321 error:
2322         if (param)
2323                 g_variant_unref(param);
2324
2325         return ret;
2326 }
2327
2328 // not thread-safe
2329 static struct _publish_info {
2330         GDBusConnection *conn;
2331         guint subs_id;
2332         struct _cb_info {
2333                 sound_manager_remote_client_connected_cb cb;
2334                 void *userdata;
2335         } cb_info;
2336 } publish_info;
2337
2338 #define REMOTE_CLIENT_BIT_TYPE_MASK 0x80000000
2339 #define REMOTE_CLIENT_BIT_TYPE 31
2340
2341 static void __internal_cb(GDBusConnection *connection, const gchar *sender_name,
2342                                         const gchar *object_path, const gchar *interface_name,
2343                                         const gchar *signal_name,GVariant *params, gpointer userdata)
2344 {
2345         struct _cb_info *cb_info = (struct _cb_info *)userdata;
2346
2347         if (cb_info && cb_info->cb) {
2348                 gint32 type;
2349                 guint32 id;
2350                 gboolean is_connected;
2351                 gchar *name, *description;
2352
2353                 g_variant_get(params, "(iub&s&s)", &type, &id, &is_connected, &name, &description);
2354
2355                 LOGE("type(%d), id(%u), is_connected(%d), name(%s), description(%s)",
2356                                 type, id, is_connected, name, description);
2357
2358                 /* MSB:input or output, others:index */
2359                 id = id | (type << REMOTE_CLIENT_BIT_TYPE);
2360                 cb_info->cb(id, name, type, description, is_connected, cb_info->userdata);
2361         }
2362 }
2363
2364 static int __subscribe_remote_devices(sound_manager_remote_client_connected_cb callback, void *userdata)
2365 {
2366         int ret;
2367         struct _cb_info *cb_info = &(publish_info.cb_info);
2368
2369         if (publish_info.subs_id > 0) {
2370                 LOGE("already subscribed remote device");
2371                 return SOUND_MANAGER_ERROR_INTERNAL;
2372         }
2373
2374         if ((ret = __get_dbus_connection(&publish_info.conn)) != SOUND_MANAGER_ERROR_NONE)
2375                 return ret;
2376
2377         cb_info->cb = callback;
2378         cb_info->userdata = userdata;
2379
2380         publish_info.subs_id = g_dbus_connection_signal_subscribe(publish_info.conn, NULL,
2381                                         PA_STREAM_MANAGER_INTERFACE,
2382                                         PA_STREAM_MANAGER_SIGNAL_NAME_REMOTE_FOUND,
2383                                         PA_STREAM_MANAGER_OBJECT_PATH, NULL, G_DBUS_SIGNAL_FLAGS_NONE,
2384                                         __internal_cb, cb_info, NULL);
2385         if (publish_info.subs_id == 0) {
2386                 g_object_unref(publish_info.conn);
2387                 LOGE("subscription failed");
2388                 return SOUND_MANAGER_ERROR_INTERNAL;
2389         }
2390
2391         LOGI("subscribe remote devices. subs_id %d", publish_info.subs_id);
2392
2393         return SOUND_MANAGER_ERROR_NONE;
2394 }
2395
2396 static int __unsubscribe_remote_devices(void)
2397 {
2398         int ret;
2399
2400         if (publish_info.subs_id == 0) {
2401                 LOGE("invalid subs_id(%d)", publish_info.subs_id);
2402                 return SOUND_MANAGER_ERROR_INTERNAL;
2403         }
2404
2405         if ((ret = __get_dbus_connection(&publish_info.conn)) != SOUND_MANAGER_ERROR_NONE)
2406                 return ret;
2407
2408         g_dbus_connection_signal_unsubscribe(publish_info.conn, publish_info.subs_id);
2409
2410         if (publish_info.conn) {
2411                 g_object_unref(publish_info.conn);
2412                 publish_info.conn = NULL;
2413         }
2414
2415         publish_info.subs_id = 0;
2416
2417         LOGI("unsubscribe remote devices state subs_id %d", publish_info.subs_id);
2418
2419         return SOUND_MANAGER_ERROR_NONE;
2420 }
2421
2422 int _publish_local_device(sound_manager_remote_client_connected_cb callback, void *user_data)
2423 {
2424         int ret;
2425
2426         LOGI("publish local device callback(%p), userdata(%p)", callback, user_data);
2427
2428         ret = __subscribe_remote_devices(callback, user_data);
2429         if (ret != SOUND_MANAGER_ERROR_NONE) {
2430                 LOGE("subscribe failed");
2431                 return ret;
2432         }
2433
2434         ret = __dbus_method_call(PA_STREAM_MANAGER_METHOD_NAME_PUBLISH_LOCAL_DEVICE, g_variant_new("(b)", TRUE), NULL);
2435         if (ret != SOUND_MANAGER_ERROR_NONE) {
2436                 if (__unsubscribe_remote_devices())
2437                         LOGE("unsubscribe failed");
2438
2439                 LOGE("publish local device failed");
2440
2441                 return ret;
2442         }
2443
2444         return ret;
2445 }
2446
2447 int _unpublish_local_device(void)
2448 {
2449         int ret;
2450
2451         ret = __dbus_method_call(PA_STREAM_MANAGER_METHOD_NAME_PUBLISH_LOCAL_DEVICE, g_variant_new("(b)", FALSE), NULL);
2452         if (ret != SOUND_MANAGER_ERROR_NONE) {
2453                 LOGE("unpublish local device failed");
2454                 return ret;
2455         }
2456
2457         ret = __unsubscribe_remote_devices();
2458         if (ret != SOUND_MANAGER_ERROR_NONE) {
2459                 LOGE("unsubscribe failed");
2460                 return ret;
2461         }
2462
2463         return ret;
2464 }
2465
2466 int _discover_remote_device(bool enable)
2467 {
2468         return __dbus_method_call(PA_STREAM_MANAGER_METHOD_NAME_DISCOVER_REMOTE_DEVICE,
2469                                         g_variant_new("(b)", (gboolean)enable), NULL);
2470 }
2471
2472 int _set_remote_permission(int id, bool allowed)
2473 {
2474         int ret;
2475         int index = (id << 1) >> 1;
2476         char *type = id & REMOTE_CLIENT_BIT_TYPE_MASK ? "source-output" : "sink-input";
2477
2478         LOGI("id(%d), allowed(%d), index(%d), type(%s)", id, allowed, index, type);
2479
2480         ret = __dbus_method_call(PA_STREAM_MANAGER_METHOD_NAME_SET_REMOTE_PERMISSION,
2481                                         g_variant_new("(sub)", type, index, (gboolean)allowed), NULL);
2482         if (ret != SOUND_MANAGER_ERROR_NONE)
2483                 LOGE("update proplist failed");
2484
2485         return ret;
2486 }
2487
2488 int _set_rpi_playback_route(sound_rpi_playback_route_type type)
2489 {
2490         int ret;
2491
2492         LOGI("set rpi playback route : %u", type);
2493
2494         ret = __dbus_method_call(PA_STREAM_MANAGER_METHOD_NAME_SET_RPI_PLAYBACK_ROUTE, g_variant_new("(u)", type), NULL);
2495         if (ret != SOUND_MANAGER_ERROR_NONE)
2496                 LOGE("_set_rpi_playback_route failed");
2497
2498         return ret;
2499 }
2500
2501 int _get_rpi_playback_route(sound_rpi_playback_route_type *type)
2502 {
2503         int route_type;
2504         int ret;
2505
2506         ret = vconf_get_int(VCONF_SOUND_RPI_PLAYBACK_ROUTE, &route_type);
2507         if (ret != 0) {
2508                 LOGE("Failed to get vconf [%s], err [%d]", VCONF_SOUND_RPI_PLAYBACK_ROUTE, ret);
2509                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
2510         }
2511
2512         LOGI("current rpi playback route : %u", route_type);
2513         *type = route_type;
2514
2515         return SOUND_MANAGER_ERROR_NONE;
2516 }
2517
2518 //LCOV_EXCL_STOP
2519
2520 static int __check_manual_route_type(sound_stream_info_s *stream_info)
2521 {
2522         SM_ARG_CHECK(stream_info);
2523
2524         if (stream_info->stream_conf_info.route_type != STREAM_ROUTE_TYPE_MANUAL &&
2525                 stream_info->stream_conf_info.route_type != STREAM_ROUTE_TYPE_MANUAL_EXT) {
2526                 LOGE("route type is not manual or manual-ext");
2527                 return SOUND_MANAGER_ERROR_POLICY;
2528         }
2529
2530         return SOUND_MANAGER_ERROR_NONE;
2531 }
2532
2533 static int __check_auto_route_type(sound_stream_info_s *stream_info)
2534 {
2535         SM_ARG_CHECK(stream_info);
2536
2537         if (stream_info->stream_conf_info.route_type != STREAM_ROUTE_TYPE_AUTO &&
2538                 stream_info->stream_conf_info.route_type != STREAM_ROUTE_TYPE_AUTO_LAST_CONNECTED) {
2539                 LOGE("route type is not auto or auto-last-connected");
2540                 return SOUND_MANAGER_ERROR_POLICY;
2541         }
2542
2543         return SOUND_MANAGER_ERROR_NONE;
2544 }
2545
2546 static int __add_device_to_stream_info(sound_stream_info_s *stream_info, int device_id, mm_sound_device_io_direction_e device_direction, char *device_type_str)
2547 {
2548         int i, j;
2549         bool added_successfully = false;
2550
2551         SM_ARG_CHECK(stream_info);
2552         SM_ARG_CHECK(device_type_str);
2553
2554         if (device_direction == MM_SOUND_DEVICE_IO_DIRECTION_IN || device_direction == MM_SOUND_DEVICE_IO_DIRECTION_BOTH) {
2555                 for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
2556                         if (!stream_info->stream_conf_info.avail_in_devices[i])
2557                                 break;
2558                         if (strncmp(stream_info->stream_conf_info.avail_in_devices[i], device_type_str, SOUND_DEVICE_TYPE_LEN))
2559                                 continue;
2560
2561                         for (j = 0; j < AVAIL_DEVICES_MAX; j++) {
2562                                 if (!stream_info->manual_route_info.route_in_devices[j]) {
2563                                         stream_info->manual_route_info.route_in_devices[j] = (unsigned int)device_id;
2564                                         added_successfully = true;
2565                                         break;
2566                                 }
2567                                 if (stream_info->manual_route_info.route_in_devices[j] == (unsigned int)device_id) {
2568                                         LOGE("failed to add device, this IN/BOTH-device[type:%s, id:%d] has been already set", device_type_str, device_id);
2569                                         return SOUND_MANAGER_ERROR_POLICY;
2570                                 }
2571                         }
2572                 }
2573         }
2574         if (device_direction == MM_SOUND_DEVICE_IO_DIRECTION_OUT || device_direction == MM_SOUND_DEVICE_IO_DIRECTION_BOTH) {
2575                 for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
2576                         if (!stream_info->stream_conf_info.avail_out_devices[i])
2577                                 break;
2578                         if (strncmp(stream_info->stream_conf_info.avail_out_devices[i], device_type_str, SOUND_DEVICE_TYPE_LEN))
2579                                 continue;
2580
2581                         for (j = 0; j < AVAIL_DEVICES_MAX; j++) {
2582                                 if (!stream_info->manual_route_info.route_out_devices[j]) {
2583                                         stream_info->manual_route_info.route_out_devices[j] = (unsigned int)device_id;
2584                                         added_successfully = true;
2585                                         break;
2586                                 }
2587                                 if (stream_info->manual_route_info.route_out_devices[j] == (unsigned int)device_id) {
2588                                         LOGE("failed to add device, this OUT/BOTH-device[type:%s, id:%d] has been already set", device_type_str, device_id);
2589                                         return SOUND_MANAGER_ERROR_POLICY;
2590                                 }
2591                         }
2592                 }
2593         }
2594
2595         if (!added_successfully) {
2596                 LOGE("failed to add device, not supported device[type:%s, id:%d]", device_type_str, device_id);
2597                 return SOUND_MANAGER_ERROR_POLICY;
2598         }
2599
2600         return SOUND_MANAGER_ERROR_NONE;
2601 }
2602
2603 static int __remove_device_from_stream_info(sound_stream_info_s *stream_info, int device_id, mm_sound_device_io_direction_e device_direction, char *device_type_str)
2604 {
2605         int i, j;
2606         bool removed_successfully = false;
2607
2608         SM_ARG_CHECK(stream_info);
2609         SM_ARG_CHECK(device_type_str);
2610
2611         if (device_direction == MM_SOUND_DEVICE_IO_DIRECTION_IN || device_direction == MM_SOUND_DEVICE_IO_DIRECTION_BOTH) {
2612                 for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
2613                         if (!stream_info->stream_conf_info.avail_in_devices[i])
2614                                 break;
2615                         if (strncmp(stream_info->stream_conf_info.avail_in_devices[i], device_type_str, SOUND_DEVICE_TYPE_LEN))
2616                                 continue;
2617
2618                         for (j = 0; j < AVAIL_DEVICES_MAX; j++) {
2619                                 if (stream_info->manual_route_info.route_in_devices[j] == (unsigned int)device_id) {
2620                                         removed_successfully = true;
2621                                         stream_info->manual_route_info.route_in_devices[j] = 0;
2622                                         break;
2623                                 }
2624                         }
2625                 }
2626         }
2627         if (device_direction == MM_SOUND_DEVICE_IO_DIRECTION_OUT || device_direction == MM_SOUND_DEVICE_IO_DIRECTION_BOTH) {
2628                 for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
2629                         if (!stream_info->stream_conf_info.avail_out_devices[i])
2630                                 break;
2631                         if (strncmp(stream_info->stream_conf_info.avail_out_devices[i], device_type_str, SOUND_DEVICE_TYPE_LEN))
2632                                 continue;
2633
2634                         for (j = 0; j < AVAIL_DEVICES_MAX; j++) {
2635                                 if (stream_info->manual_route_info.route_out_devices[j] == (unsigned int)device_id) {
2636                                         removed_successfully = true;
2637                                         stream_info->manual_route_info.route_out_devices[j] = 0;
2638                                         break;
2639                                 }
2640                         }
2641                 }
2642         }
2643
2644         if (!removed_successfully) {
2645                 LOGE("failed to remove device, could not find this device[type:%s, id:%d]", device_type_str, device_id);
2646                 return SOUND_MANAGER_ERROR_INVALID_PARAMETER;
2647         }
2648
2649         return SOUND_MANAGER_ERROR_NONE;
2650 }
2651
2652 static int __is_available_device(sound_stream_info_s *stream_info, sound_device_h device, bool *available)
2653 {
2654         int ret = SOUND_MANAGER_ERROR_NONE;
2655         int mm_ret = MM_ERROR_NONE;
2656         int i = 0;
2657         mm_sound_device_type_e mm_sound_device_type;
2658         sound_device_type_e device_type;
2659         char *device_type_str = NULL;
2660         char *avail_device_item = NULL;
2661         mm_sound_device_io_direction_e device_direction;
2662         bool found = false;
2663
2664         SM_ARG_CHECK(stream_info);
2665         SM_ARG_CHECK(device);
2666
2667         if ((mm_ret = mm_sound_get_device_type(device, &mm_sound_device_type)) != MM_ERROR_NONE)
2668                 return _convert_sound_manager_error_code(__func__, mm_ret);
2669         if ((ret = _convert_device_type(mm_sound_device_type, &device_type)) != SOUND_MANAGER_ERROR_NONE)
2670                 return ret;
2671         if ((ret = _convert_device_type_enum_to_str(device_type, &device_type_str)) != SOUND_MANAGER_ERROR_NONE)
2672                 return ret;
2673         if ((mm_ret = mm_sound_get_device_io_direction(device, &device_direction)) != MM_ERROR_NONE)
2674                 return _convert_sound_manager_error_code(__func__, mm_ret);
2675
2676         if (device_direction & MM_SOUND_DEVICE_IO_DIRECTION_OUT) {
2677                 for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
2678                         if (!(avail_device_item = stream_info->stream_conf_info.avail_out_devices[i]))
2679                                 break;
2680                         if (!strncmp(avail_device_item, device_type_str, strlen(device_type_str)))
2681                                 found = true;
2682                 }
2683                 if (!found) {
2684                         LOGE("[OUT] this device(%s) is not available for this stream_info(%s)", device_type_str, stream_info->stream_type);
2685                         *available = false;
2686                         return SOUND_MANAGER_ERROR_NONE;
2687                 }
2688         }
2689
2690         if (device_direction & MM_SOUND_DEVICE_IO_DIRECTION_IN) {
2691                 found = false;
2692                 for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
2693                         if (!(avail_device_item = stream_info->stream_conf_info.avail_in_devices[i]))
2694                                 break;
2695                         if (!strncmp(avail_device_item, device_type_str, strlen(device_type_str)))
2696                                 found = true;
2697                 }
2698                 if (!found) {
2699                         LOGE("[IN] this device(%s) is not available for this stream_info(%s)", device_type_str, stream_info->stream_type);
2700                         *available = false;
2701                         return SOUND_MANAGER_ERROR_NONE;
2702                 }
2703         }
2704
2705         *available = true;
2706
2707         return SOUND_MANAGER_ERROR_NONE;
2708 }
2709
2710 int _add_device_for_stream_routing(sound_stream_info_s *stream_info, sound_device_h device)
2711 {
2712         int ret = SOUND_MANAGER_ERROR_NONE;
2713         int mm_ret = MM_ERROR_NONE;
2714         char *device_type_str = NULL;
2715         int device_id = 0;
2716         mm_sound_device_type_e mm_sound_device_type;
2717         mm_sound_device_io_direction_e device_direction;
2718         sound_device_type_e device_type;
2719
2720         SM_ARG_CHECK(stream_info);
2721         SM_ARG_CHECK(device);
2722
2723         if ((ret = __check_manual_route_type(stream_info)) != SOUND_MANAGER_ERROR_NONE)
2724                 return ret;
2725
2726         if ((mm_ret = mm_sound_get_device_id(device, &device_id)) != MM_ERROR_NONE)
2727                 return _convert_sound_manager_error_code(__func__, mm_ret);
2728         if ((mm_ret = mm_sound_get_device_type(device, &mm_sound_device_type)) != MM_ERROR_NONE)
2729                 return _convert_sound_manager_error_code(__func__, mm_ret);
2730         if ((ret = _convert_device_type(mm_sound_device_type, &device_type)) != SOUND_MANAGER_ERROR_NONE)
2731                 return ret;
2732         if ((ret = _convert_device_type_enum_to_str(device_type, &device_type_str)) != SOUND_MANAGER_ERROR_NONE)
2733                 return ret;
2734         if ((mm_ret = mm_sound_get_device_io_direction(device, &device_direction)) != MM_ERROR_NONE)
2735                 return _convert_sound_manager_error_code(__func__, mm_ret);
2736
2737         if ((ret = __add_device_to_stream_info(stream_info, device_id, device_direction, device_type_str)) != SOUND_MANAGER_ERROR_NONE)
2738                 return ret;
2739
2740         LOGI("*** added device[type:%s, id:%d]", device_type_str, device_id);
2741
2742         return SOUND_MANAGER_ERROR_NONE;
2743 }
2744
2745 int _remove_device_for_stream_routing(sound_stream_info_s *stream_info, sound_device_h device)
2746 {
2747         int ret = SOUND_MANAGER_ERROR_NONE;
2748         int mm_ret = MM_ERROR_NONE;
2749         char *device_type_str = NULL;
2750         int device_id = 0;
2751         mm_sound_device_type_e mm_sound_device_type;
2752         mm_sound_device_io_direction_e device_direction;
2753         sound_device_type_e device_type;
2754
2755         SM_ARG_CHECK(stream_info);
2756         SM_ARG_CHECK(device);
2757
2758         if ((ret = __check_manual_route_type(stream_info)) != SOUND_MANAGER_ERROR_NONE)
2759                 return ret;
2760
2761         if ((mm_ret = mm_sound_get_device_id(device, &device_id)) != MM_ERROR_NONE)
2762                 return _convert_sound_manager_error_code(__func__, mm_ret);
2763         if ((mm_ret = mm_sound_get_device_type(device, &mm_sound_device_type)) != MM_ERROR_NONE)
2764                 return _convert_sound_manager_error_code(__func__, mm_ret);
2765         if ((ret = _convert_device_type(mm_sound_device_type, &device_type)) != SOUND_MANAGER_ERROR_NONE)
2766                 return ret;
2767         if ((ret = _convert_device_type_enum_to_str(device_type, &device_type_str)) != SOUND_MANAGER_ERROR_NONE)
2768                 return ret;
2769         if ((mm_ret = mm_sound_get_device_io_direction(device, &device_direction)) != MM_ERROR_NONE)
2770                 return _convert_sound_manager_error_code(__func__, mm_ret);
2771
2772         if ((ret = __remove_device_from_stream_info(stream_info, device_id, device_direction, device_type_str)) != SOUND_MANAGER_ERROR_NONE)
2773                 return ret;
2774
2775         LOGI("*** removed device[type:%s, id:%d]", device_type_str, device_id);
2776
2777         return SOUND_MANAGER_ERROR_NONE;
2778 }
2779
2780 int _remove_all_devices_for_stream_routing(sound_stream_info_s *stream_info)
2781 {
2782         int ret = SOUND_MANAGER_ERROR_NONE;
2783         int i;
2784
2785         SM_ARG_CHECK(stream_info);
2786
2787         if ((ret = __check_manual_route_type(stream_info)) != SOUND_MANAGER_ERROR_NONE)
2788                 return ret;
2789
2790         for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
2791                 stream_info->manual_route_info.route_in_devices[i] = 0;
2792                 stream_info->manual_route_info.route_out_devices[i] = 0;
2793         }
2794
2795         stream_info->manual_route_info.is_set = false;
2796
2797         LOGI("*** removed all devices");
2798
2799         return SOUND_MANAGER_ERROR_NONE;
2800 }
2801 //LCOV_EXCL_START
2802 int _add_device_id_for_stream_routing(sound_stream_info_s *stream_info, int device_id)
2803 {
2804         int ret = SOUND_MANAGER_ERROR_NONE;
2805         int mm_ret = MM_ERROR_NONE;
2806         char *device_type_str = NULL;
2807         mm_sound_device_type_e mm_sound_device_type;
2808         mm_sound_device_io_direction_e device_direction;
2809         sound_device_type_e device_type;
2810         MMSoundDevice_t device = NULL;
2811
2812         SM_ARG_CHECK(stream_info);
2813
2814         if ((ret = __check_manual_route_type(stream_info)) != SOUND_MANAGER_ERROR_NONE)
2815                 return ret;
2816
2817         if ((mm_ret = mm_sound_get_device_by_id(device_id, &device)) != MM_ERROR_NONE)
2818                 return _convert_sound_manager_error_code(__func__, mm_ret);
2819         if ((mm_ret = mm_sound_get_device_type(device, &mm_sound_device_type)) != MM_ERROR_NONE) {
2820                 ret = _convert_sound_manager_error_code(__func__, mm_ret);
2821                 goto LEAVE;
2822         }
2823         if ((ret = _convert_device_type(mm_sound_device_type, &device_type)) != SOUND_MANAGER_ERROR_NONE)
2824                 goto LEAVE;
2825         if ((ret = _convert_device_type_enum_to_str(device_type, &device_type_str)) != SOUND_MANAGER_ERROR_NONE)
2826                 goto LEAVE;
2827         if ((mm_ret = mm_sound_get_device_io_direction(device, &device_direction)) != MM_ERROR_NONE) {
2828                 ret = _convert_sound_manager_error_code(__func__, mm_ret);
2829                 goto LEAVE;
2830         }
2831
2832         if ((ret = __add_device_to_stream_info(stream_info, device_id, device_direction, device_type_str)) != SOUND_MANAGER_ERROR_NONE)
2833                 goto LEAVE;
2834
2835         LOGI("*** added device by id[type:%s, id:%d]", device_type_str, device_id);
2836
2837 LEAVE:
2838         if (device)
2839                 mm_sound_free_device(device);
2840         return ret;
2841 }
2842
2843 int _remove_device_id_for_stream_routing(sound_stream_info_s *stream_info, int device_id)
2844 {
2845         int ret = SOUND_MANAGER_ERROR_NONE;
2846         int mm_ret = MM_ERROR_NONE;
2847         char *device_type_str = NULL;
2848         mm_sound_device_type_e mm_sound_device_type;
2849         mm_sound_device_io_direction_e device_direction;
2850         sound_device_type_e device_type;
2851         MMSoundDevice_t device = NULL;
2852
2853         SM_ARG_CHECK(stream_info);
2854
2855         if ((ret = __check_manual_route_type(stream_info)) != SOUND_MANAGER_ERROR_NONE)
2856                 return ret;
2857
2858         if ((mm_ret = mm_sound_get_device_by_id(device_id, &device)) != MM_ERROR_NONE)
2859                 return _convert_sound_manager_error_code(__func__, mm_ret);
2860         if ((mm_ret = mm_sound_get_device_type(device, &mm_sound_device_type)) != MM_ERROR_NONE) {
2861                 ret = _convert_sound_manager_error_code(__func__, mm_ret);
2862                 goto LEAVE;
2863         }
2864         if ((ret = _convert_device_type(mm_sound_device_type, &device_type)) != SOUND_MANAGER_ERROR_NONE)
2865                 goto LEAVE;
2866         if ((ret = _convert_device_type_enum_to_str(device_type, &device_type_str)) != SOUND_MANAGER_ERROR_NONE)
2867                 goto LEAVE;
2868         if ((mm_ret = mm_sound_get_device_io_direction(device, &device_direction)) != MM_ERROR_NONE) {
2869                 ret = _convert_sound_manager_error_code(__func__, mm_ret);
2870                 goto LEAVE;
2871         }
2872
2873         if ((ret = __remove_device_from_stream_info(stream_info, device_id, device_direction, device_type_str)) != SOUND_MANAGER_ERROR_NONE)
2874                 goto LEAVE;
2875
2876         LOGI("*** removed device by id[type:%s, id:%d]", device_type_str, device_id);
2877
2878 LEAVE:
2879         if (device)
2880                 mm_sound_free_device(device);
2881         return ret;
2882 }
2883 //LCOV_EXCL_STOP
2884 int _apply_stream_routing(sound_stream_info_s *stream_info)
2885 {
2886         int i = 0;
2887
2888         SM_ARG_CHECK(stream_info);
2889
2890         if (stream_info->stream_conf_info.route_type != STREAM_ROUTE_TYPE_MANUAL &&
2891                 stream_info->stream_conf_info.route_type != STREAM_ROUTE_TYPE_MANUAL_EXT) {
2892                 LOGE("route type is not manual or manual-ext");//LCOV_EXCL_LINE
2893                 /* Differ from others, it uses SOUND_INTERNAL error.
2894                  * ACR process is required prior to changing error value. */
2895                 return SOUND_MANAGER_ERROR_INTERNAL;//LCOV_EXCL_LINE
2896         }
2897
2898         for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
2899                 if (stream_info->manual_route_info.route_in_devices[i] ||
2900                     stream_info->manual_route_info.route_out_devices[i])
2901                         return _set_manual_route_info(stream_info->pa_info.index, &stream_info->manual_route_info);
2902         }
2903
2904         return SOUND_MANAGER_ERROR_INVALID_STATE;
2905 }
2906
2907 //LCOV_EXCL_START
2908 int _create_virtual_stream(sound_stream_info_s *stream_info, virtual_sound_stream_info_s **virtual_stream)
2909 {
2910         bool result = false;
2911         const char *name = NULL;
2912         int i = 0;
2913
2914         SM_ARG_CHECK(stream_info);
2915         SM_ARG_CHECK(virtual_stream);
2916
2917         /* check if this stream_info is available for virtual stream */
2918         name = _convert_api_name(NATIVE_API_SOUND_MANAGER);
2919         for (i = 0; i < AVAIL_FRAMEWORKS_MAX; i++) {
2920                 if (stream_info->stream_conf_info.avail_frameworks[i] && !strncmp(stream_info->stream_conf_info.avail_frameworks[i], name, strlen(name))) {
2921                         result = true;
2922                         break;
2923                 }
2924         }
2925         LOGI("stream_type[%s], native api[%s], is_available[%d]", stream_info->stream_type, name, result);
2926         if (!result)
2927                 return SOUND_MANAGER_ERROR_NOT_SUPPORTED;
2928
2929         (*virtual_stream) = malloc(sizeof(virtual_sound_stream_info_s));
2930         if (!(*virtual_stream))
2931                 return SOUND_MANAGER_ERROR_INTERNAL;
2932
2933         memset((*virtual_stream), 0, sizeof(virtual_sound_stream_info_s));
2934         (*virtual_stream)->stream_type = stream_info->stream_type;
2935         (*virtual_stream)->pa_mainloop = stream_info->pa_info.mainloop;
2936         (*virtual_stream)->pa_context = stream_info->pa_info.context;
2937         (*virtual_stream)->pa_proplist = pa_proplist_new();
2938         pa_proplist_sets((*virtual_stream)->pa_proplist, PA_PROP_MEDIA_ROLE, (*virtual_stream)->stream_type);
2939         pa_proplist_setf((*virtual_stream)->pa_proplist, PA_PROP_MEDIA_PARENT_ID, "%u", stream_info->pa_info.index);
2940         (*virtual_stream)->state = _VSTREAM_STATE_READY;
2941         (*virtual_stream)->stream_info = stream_info;
2942
2943         return SOUND_MANAGER_ERROR_NONE;
2944 }
2945
2946 int _destroy_virtual_stream(virtual_sound_stream_info_s *virtual_stream)
2947 {
2948         SM_ARG_CHECK(virtual_stream);
2949         SM_STATE_CHECK(virtual_stream, _VSTREAM_STATE_READY);
2950
2951         virtual_stream->pa_mainloop = NULL;
2952         virtual_stream->pa_context = NULL;
2953         if (virtual_stream->pa_proplist)
2954                 pa_proplist_free(virtual_stream->pa_proplist);
2955
2956         virtual_stream->stream_info->vstream = NULL;
2957
2958         SM_SAFE_FREE(virtual_stream);
2959
2960         return SOUND_MANAGER_ERROR_NONE;
2961 }
2962
2963 int _start_virtual_stream(virtual_sound_stream_info_s *virtual_stream)
2964 {
2965         int ret = SOUND_MANAGER_ERROR_NONE;
2966         int pa_ret = PA_OK;
2967         int i = 0;
2968         int io_direction = 0;
2969         pa_sample_spec ss;
2970         pa_channel_map maps;
2971
2972         SM_ARG_CHECK(virtual_stream);
2973         SM_STATE_CHECK(virtual_stream, _VSTREAM_STATE_READY);
2974
2975         /* fill up with default value */
2976         ss.channels = 2;
2977         ss.rate = 44100;
2978         ss.format = PA_SAMPLE_S16LE;
2979         pa_channel_map_init_auto(&maps, ss.channels, PA_CHANNEL_MAP_ALSA);
2980
2981         /* check direction of this stream */
2982         if (virtual_stream->stream_info->stream_conf_info.avail_in_devices[0] != NULL)
2983                 io_direction |= SOUND_STREAM_DIRECTION_INPUT;
2984         if (virtual_stream->stream_info->stream_conf_info.avail_out_devices[0] != NULL)
2985                 io_direction |= SOUND_STREAM_DIRECTION_OUTPUT;
2986
2987         pa_threaded_mainloop_lock(virtual_stream->pa_mainloop);
2988
2989         for (i = 0; i < SOUND_STREAM_DIRECTION_MAX; i++) {
2990                 if (io_direction & (i + 1)) {
2991                         virtual_stream->pa_stream[i] = pa_stream_new_with_proplist(virtual_stream->pa_context, "VIRTUAL_STREAM", &ss, &maps, virtual_stream->pa_proplist);
2992                         if (virtual_stream->pa_stream[i] == NULL) {
2993                                 LOGE("failed to pa_stream_new_with_proplist()");
2994                                 pa_ret = pa_context_errno(virtual_stream->pa_context);
2995                                 ret = SOUND_MANAGER_ERROR_INTERNAL;
2996                                 goto ERROR_WITH_UNLOCK;
2997                         }
2998                         pa_stream_set_state_callback(virtual_stream->pa_stream[i], _pa_stream_state_cb, virtual_stream);
2999
3000                         if ((i + 1) == SOUND_STREAM_DIRECTION_OUTPUT) {
3001                                 pa_ret = pa_stream_connect_playback(virtual_stream->pa_stream[i], NULL, NULL, 0, NULL, NULL);
3002                                 if (pa_ret < 0) {
3003                                         LOGE("failed to pa_stream_connect_playback()");
3004                                         pa_ret = pa_context_errno(virtual_stream->pa_context);
3005                                         ret = SOUND_MANAGER_ERROR_INTERNAL;
3006                                         goto ERROR_WITH_UNLOCK;
3007                                 }
3008                         } else if ((i + 1) == SOUND_STREAM_DIRECTION_INPUT) {
3009                                 pa_ret = pa_stream_connect_record(virtual_stream->pa_stream[i], NULL, NULL, 0);
3010                                 if (pa_ret < 0) {
3011                                         LOGE("failed to pa_stream_connect_record()");
3012                                         pa_ret = pa_context_errno(virtual_stream->pa_context);
3013                                         ret = SOUND_MANAGER_ERROR_INTERNAL;
3014                                         goto ERROR_WITH_UNLOCK;
3015                                 }
3016                         }
3017
3018                         /* wait for ready state of the stream */
3019                         for (;;) {
3020                                 pa_stream_state_t state;
3021                                 state = pa_stream_get_state(virtual_stream->pa_stream[i]);
3022                                 if (state == PA_STREAM_READY)
3023                                         break;
3024                                 if (!PA_STREAM_IS_GOOD(state)) {
3025                                         LOGE("stream(%d) is not good, state : %d", i, state);
3026                                         pa_ret = pa_context_errno(virtual_stream->pa_context);
3027                                         ret = SOUND_MANAGER_ERROR_INTERNAL;
3028                                         goto ERROR_WITH_UNLOCK;
3029                                 }
3030
3031                                 pa_threaded_mainloop_wait(virtual_stream->pa_mainloop);
3032                         }
3033                 }
3034         }
3035         virtual_stream->state = _VSTREAM_STATE_RUNNING;
3036
3037         pa_threaded_mainloop_unlock(virtual_stream->pa_mainloop);
3038
3039         return SOUND_MANAGER_ERROR_NONE;
3040
3041 ERROR_WITH_UNLOCK:
3042         pa_threaded_mainloop_unlock(virtual_stream->pa_mainloop);
3043
3044         for (i = 0; i < SOUND_STREAM_DIRECTION_MAX; i++) {
3045                 if (virtual_stream->pa_stream[i]) {
3046                         pa_stream_unref(virtual_stream->pa_stream[i]);
3047                         virtual_stream->pa_stream[i] = NULL;
3048                 }
3049         }
3050         LOGE("pa_ret(%d)", pa_ret);
3051         return ret;
3052 }
3053
3054 int _stop_virtual_stream(virtual_sound_stream_info_s *virtual_stream)
3055 {
3056         int i = 0;
3057         int ret = 0;
3058
3059         SM_ARG_CHECK(virtual_stream);
3060         SM_STATE_CHECK(virtual_stream, _VSTREAM_STATE_RUNNING);
3061
3062         pa_threaded_mainloop_lock(virtual_stream->pa_mainloop);
3063
3064         for (i = 0; i < SOUND_STREAM_DIRECTION_MAX; i++) {
3065                 if (!virtual_stream->pa_stream[i])
3066                         continue;
3067
3068                 LOGI("[%d] disconnecting vstream_h[%p] index[%d] state[%d]",
3069                          i, virtual_stream, pa_stream_get_index(virtual_stream->pa_stream[i]), pa_stream_get_state(virtual_stream->pa_stream[i]));
3070
3071                 ret = pa_stream_disconnect(virtual_stream->pa_stream[i]);
3072                 if (ret == 0) {
3073                         /* wait for terminated state of the stream */
3074                         for (;;) {
3075                                 pa_stream_state_t state = pa_stream_get_state(virtual_stream->pa_stream[i]);
3076                                 if (state == PA_STREAM_TERMINATED)
3077                                         break;
3078                                 pa_threaded_mainloop_wait(virtual_stream->pa_mainloop);
3079                         }
3080                 } else {
3081                         LOGE("[%d] disconnection failed for vstream_h[%p] index[%d], ret[%d][%s]",
3082                                  i, virtual_stream, pa_stream_get_index(virtual_stream->pa_stream[i]), ret, pa_strerror(ret));
3083                 }
3084
3085                 pa_stream_unref(virtual_stream->pa_stream[i]);
3086                 virtual_stream->pa_stream[i] = NULL;
3087         }
3088
3089         pa_threaded_mainloop_unlock(virtual_stream->pa_mainloop);
3090
3091         virtual_stream->state = _VSTREAM_STATE_READY;
3092
3093         return SOUND_MANAGER_ERROR_NONE;
3094 }
3095
3096 int _set_volume_ratio(uint32_t stream_index, sound_stream_direction_e direction, double ratio)
3097 {
3098         int ret = SOUND_MANAGER_ERROR_NONE;
3099         GDBusConnection *conn = NULL;
3100         GError *err = NULL;
3101         GVariant *result = NULL;
3102         const gchar *dbus_ret = NULL;
3103
3104         if ((ret = __get_dbus_connection(&conn)) != SOUND_MANAGER_ERROR_NONE)
3105                 return ret;
3106
3107         result = g_dbus_connection_call_sync(conn,
3108                                                 PA_BUS_NAME,
3109                                                 PA_STREAM_MANAGER_OBJECT_PATH,
3110                                                 PA_STREAM_MANAGER_INTERFACE,
3111                                                 PA_STREAM_MANAGER_METHOD_NAME_SET_VOLUME_RATIO,
3112                                                 g_variant_new("(sud)", (direction == SOUND_STREAM_DIRECTION_OUTPUT) ? "out" : "in", stream_index, ratio),
3113                                                 G_VARIANT_TYPE("(s)"),
3114                                                 G_DBUS_CALL_FLAGS_NONE,
3115                                                 DBUS_METHOD_TIMEOUT,
3116                                                 NULL,
3117                                                 &err);
3118         if (!result || err) {
3119                 LOGE("g_dbus_connection_call_sync() for SET_VOLUME_RATIO error (%s)", err ? err->message : NULL);
3120                 ret = _convert_sound_manager_error_code(__func__, _convert_dbus_error(err ? err->message : NULL));
3121                 if (err)
3122                         g_error_free(err);
3123                 goto LEAVE;
3124         }
3125
3126         g_variant_get(result, "(&s)", &dbus_ret);
3127
3128         if (!strncmp("STREAM_MANAGER_RETURN_ERROR_INVALID_ARGUMENT", dbus_ret, strlen(dbus_ret)))
3129                 ret = SOUND_MANAGER_ERROR_INVALID_PARAMETER;
3130         else if (!strncmp("STREAM_MANAGER_RETURN_ERROR_NO_STREAM", dbus_ret, strlen(dbus_ret)))
3131                 ret = SOUND_MANAGER_ERROR_NO_DATA;
3132         else if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret)))
3133                 ret = SOUND_MANAGER_ERROR_INTERNAL;
3134
3135         LOGI("dbus_ret[%s] ret[0x%x]", dbus_ret, ret);
3136
3137 LEAVE:
3138         if (result)
3139                 g_variant_unref(result);
3140         g_object_unref(conn);
3141
3142         return ret;
3143 }
3144
3145 int _set_virtual_stream_volume(virtual_sound_stream_info_s *virtual_stream, double ratio)
3146 {
3147         int ret = SOUND_MANAGER_ERROR_NONE;
3148         int i = 0;
3149         uint32_t index;
3150
3151         SM_ARG_CHECK(virtual_stream);
3152         SM_STATE_CHECK(virtual_stream, _VSTREAM_STATE_RUNNING);
3153
3154         pa_threaded_mainloop_lock(virtual_stream->pa_mainloop);
3155
3156         for (i = 0; i < SOUND_STREAM_DIRECTION_MAX; i++) {
3157                 if (virtual_stream->pa_stream[i]) {
3158                         index = pa_stream_get_index(virtual_stream->pa_stream[i]);
3159                         if ((ret = _set_volume_ratio(index, i + 1, ratio)) != SOUND_MANAGER_ERROR_NONE) {
3160                                 if (ret == SOUND_MANAGER_ERROR_NO_DATA) {
3161                                         LOGE("something wrong, no match index of %u", index);
3162                                         ret = SOUND_MANAGER_ERROR_INTERNAL;
3163                                 }
3164                                 break;
3165                         }
3166                 }
3167         }
3168
3169         pa_threaded_mainloop_unlock(virtual_stream->pa_mainloop);
3170
3171         return ret;
3172 }
3173
3174 int _set_acm_master_mode(bool on)
3175 {
3176         int ret = SOUND_MANAGER_ERROR_NONE;
3177         GVariant *result = NULL;
3178         GDBusConnection *conn = NULL;
3179         GError *err = NULL;
3180
3181         if ((ret = __get_dbus_connection(&conn)) != SOUND_MANAGER_ERROR_NONE)
3182                 return ret;
3183
3184         result = g_dbus_connection_call_sync(conn,
3185                                                                           PA_BUS_NAME,
3186                                                                           PA_DEVICE_MANAGER_OBJECT_PATH,
3187                                                                           PA_DEVICE_MANAGER_INTERFACE,
3188                                                                           PA_DEVICE_MANAGER_METHOD_NAME_SET_ACM_MODE,
3189                                                                           g_variant_new("(u)", (unsigned int)on),
3190                                                                           NULL,
3191                                                                           G_DBUS_CALL_FLAGS_NONE,
3192                                                                           DBUS_METHOD_TIMEOUT,
3193                                                                           NULL,
3194                                                                           &err);
3195         if (err) {
3196                 LOGE("g_dbus_connection_call_sync() for SET ACM MODE error (%s)", err->message);
3197                 ret = _convert_sound_manager_error_code(__func__, _convert_dbus_error(err->message));
3198                 g_error_free(err);
3199                 goto LEAVE;
3200         } else {
3201                 LOGI("ACM master mode [%s]", on ? "ON" : "OFF");
3202         }
3203
3204 LEAVE:
3205         if (result)
3206                 g_variant_unref(result);
3207         g_object_unref(conn);
3208
3209         return ret;
3210 }
3211
3212 int _activate_ducking(uint32_t stream_index, bool enable, const char *target_stream, uint32_t duration, double ratio)
3213 {
3214         int ret = SOUND_MANAGER_ERROR_NONE;
3215         GDBusConnection *conn = NULL;
3216         GError *err = NULL;
3217         GVariant *result = NULL;
3218         const gchar *dbus_ret = NULL;
3219
3220         if ((ret = __get_dbus_connection(&conn)) != SOUND_MANAGER_ERROR_NONE)
3221                 return ret;
3222
3223         result = g_dbus_connection_call_sync(conn,
3224                 PA_BUS_NAME,
3225                 PA_STREAM_MANAGER_OBJECT_PATH,
3226                 PA_STREAM_MANAGER_INTERFACE,
3227                 PA_STREAM_MANAGER_METHOD_NAME_ACTIVATE_DUCKING,
3228                 g_variant_new("(ubsud)", stream_index, enable, target_stream, duration, ratio),
3229                 G_VARIANT_TYPE("(s)"),
3230                 G_DBUS_CALL_FLAGS_NONE,
3231                 DBUS_METHOD_TIMEOUT,
3232                 NULL,
3233                 &err);
3234         if (!result || err) {
3235                 LOGE("g_dbus_connection_call_sync() for ACTIVATE_DUCKING error");
3236                 ret = _convert_sound_manager_error_code(__func__, _convert_dbus_error(err ? err->message : NULL));
3237                 if (err)
3238                         g_error_free(err);
3239                 goto LEAVE;
3240         }
3241
3242         g_variant_get(result, "(&s)", &dbus_ret);
3243         if (!strncmp("STREAM_MANAGER_RETURN_ERROR_INVALID_STATE", dbus_ret, strlen(dbus_ret)))
3244                 ret = SOUND_MANAGER_ERROR_INVALID_STATE;
3245         else if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret)))
3246                 ret = SOUND_MANAGER_ERROR_INTERNAL;
3247
3248         LOGI("dbus_ret[%s] ret[0x%x]", dbus_ret, ret);
3249
3250 LEAVE:
3251         if (result)
3252                 g_variant_unref(result);
3253         g_object_unref(conn);
3254
3255         return ret;
3256 }
3257
3258 int _get_ducking_state(sound_pa_info_s *pa_info, bool *is_ducked)
3259 {
3260         int ret = SOUND_MANAGER_ERROR_NONE;
3261         gboolean _is_ducked = FALSE;
3262         GDBusConnection *conn = NULL;
3263         GError *err = NULL;
3264         GVariant *result = NULL;
3265         const gchar *dbus_ret = NULL;
3266
3267         SM_ARG_CHECK(pa_info);
3268         SM_ARG_CHECK(is_ducked);
3269
3270         if (pa_info->is_disconnected) {
3271                 LOGE("server disconnected");
3272                 return SOUND_MANAGER_ERROR_INTERNAL;
3273         }
3274
3275         if ((ret = __get_dbus_connection(&conn)) != SOUND_MANAGER_ERROR_NONE)
3276                 return ret;
3277
3278         result = g_dbus_connection_call_sync(conn,
3279                 PA_BUS_NAME,
3280                 PA_STREAM_MANAGER_OBJECT_PATH,
3281                 PA_STREAM_MANAGER_INTERFACE,
3282                 PA_STREAM_MANAGER_METHOD_NAME_GET_DUCKING_STATE,
3283                 g_variant_new("(u)", pa_info->index),
3284                 G_VARIANT_TYPE("(bs)"),
3285                 G_DBUS_CALL_FLAGS_NONE,
3286                 DBUS_METHOD_TIMEOUT,
3287                 NULL,
3288                 &err);
3289         if (!result || err) {
3290                 LOGE("g_dbus_connection_call_sync() for GET_DUCKING_STATE error");
3291                 ret = _convert_sound_manager_error_code(__func__, _convert_dbus_error(err ? err->message : NULL));
3292                 if (err)
3293                         g_error_free(err);
3294                 goto LEAVE;
3295         }
3296
3297         g_variant_get(result, "(b&s)", &_is_ducked, &dbus_ret);
3298
3299         if (!strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret))) {
3300                 *is_ducked = (bool)_is_ducked;
3301                 LOGI("is_ducked[%d]", *is_ducked);
3302         } else {
3303                 ret = SOUND_MANAGER_ERROR_INTERNAL;
3304         }
3305
3306         LOGI("dbus_ret[%s] ret[0x%x]", dbus_ret, ret);
3307
3308 LEAVE:
3309         if (result)
3310                 g_variant_unref(result);
3311         g_object_unref(conn);
3312
3313         return ret;
3314 }
3315
3316 static int __invoke_ipc_set_preferred_device_id(sound_stream_info_s *stream_info, int device_id, sound_device_io_direction_e io_direction, sound_device_io_direction_e req_direction)
3317 {
3318         int ret = SOUND_MANAGER_ERROR_NONE;
3319         GVariant *result = NULL;
3320         GDBusConnection *conn = NULL;
3321         GError *err = NULL;
3322         const gchar *dbus_ret = NULL;
3323         const gchar *direction_str;
3324         int i;
3325
3326         SM_ARG_CHECK(stream_info);
3327
3328         if ((ret = __get_dbus_connection(&conn)) != SOUND_MANAGER_ERROR_NONE)
3329                 return ret;
3330
3331         for (i = SOUND_DEVICE_IO_DIRECTION_IN; i < SOUND_DEVICE_IO_DIRECTION_BOTH; i++) {
3332                 if (device_id) {
3333                         if (!(io_direction & (i + 1)))
3334                                 continue;
3335                 } else {
3336                         if (!((req_direction + 1) & (i + 1)))
3337                                 continue;
3338                 }
3339                 direction_str = (i == SOUND_DEVICE_IO_DIRECTION_IN) ? "in" : "out";
3340
3341                 result = g_dbus_connection_call_sync(conn,
3342                         PA_BUS_NAME,
3343                         PA_STREAM_MANAGER_OBJECT_PATH,
3344                         PA_STREAM_MANAGER_INTERFACE,
3345                         PA_STREAM_MANAGER_METHOD_NAME_SET_STREAM_PREFERRED_DEVICE,
3346                         g_variant_new("(usu)", stream_info->pa_info.index, direction_str, (unsigned int)device_id),
3347                         NULL,
3348                         G_DBUS_CALL_FLAGS_NONE,
3349                         DBUS_METHOD_TIMEOUT,
3350                         NULL,
3351                         &err);
3352                 if (!result || err) {
3353                         LOGE("g_dbus_connection_call_sync() for SET PREFERRED DEVICE error (%s)", err ? err->message : NULL);
3354                         ret = _convert_sound_manager_error_code(__func__, _convert_dbus_error(err ? err->message : NULL));
3355                         if (err)
3356                                 g_error_free(err);
3357                         goto LEAVE;
3358                 }
3359
3360                 LOGI("Preferred device(id:%d, direction:%s) is set to PA context(%u)", device_id, direction_str, stream_info->pa_info.index);
3361
3362                 g_variant_get(result, "(&s)", &dbus_ret);
3363
3364                 if (!strncmp("STREAM_MANAGER_RETURN_ERROR_DEVICE_NOT_FOUND", dbus_ret, strlen(dbus_ret)))
3365                         ret = SOUND_MANAGER_ERROR_INVALID_PARAMETER;
3366                 else if (!strncmp("STREAM_MANAGER_RETURN_POLICY", dbus_ret, strlen(dbus_ret)))
3367                         ret = SOUND_MANAGER_ERROR_POLICY;
3368                 else if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret)))
3369                         ret = SOUND_MANAGER_ERROR_INTERNAL;
3370
3371                 LOGI("dbus_ret[%s] ret[0x%x]", dbus_ret, ret);
3372
3373                 if (ret)
3374                         goto LEAVE;
3375
3376                 if (i == SOUND_DEVICE_IO_DIRECTION_IN)
3377                         stream_info->preferred_device_info.in = device_id;
3378                 else
3379                         stream_info->preferred_device_info.out = device_id;
3380         }
3381
3382 LEAVE:
3383         if (result)
3384                 g_variant_unref(result);
3385         g_object_unref(conn);
3386
3387         return ret;
3388 }
3389
3390 int _set_preferred_device(sound_stream_info_s *stream_info, sound_device_io_direction_e direction, sound_device_h device)
3391 {
3392         int ret = SOUND_MANAGER_ERROR_NONE;
3393         int mm_ret = MM_ERROR_NONE;
3394         bool available = false;
3395         int device_id = 0;
3396         mm_sound_device_io_direction_e io_direction = MM_SOUND_DEVICE_IO_DIRECTION_IN;
3397
3398         SM_ARG_CHECK(stream_info);
3399
3400         /* allow only auto route type */
3401         if ((ret = __check_auto_route_type(stream_info)) != SOUND_MANAGER_ERROR_NONE)
3402                 return ret;
3403
3404         /* check if this device belongs to available devices of the stream info */
3405         /* In case device is null, it's for unsetting preferred device, device_id will be 0. */
3406         if (device) {
3407                 if ((ret = __is_available_device(stream_info, device, &available)) != SOUND_MANAGER_ERROR_NONE)
3408                         return ret;
3409                 if (!available)
3410                         return SOUND_MANAGER_ERROR_POLICY;
3411                 if ((mm_ret = mm_sound_get_device_id(device, &device_id)) != MM_ERROR_NONE)
3412                         return _convert_sound_manager_error_code(__func__, mm_ret);
3413                 if ((mm_ret = mm_sound_get_device_io_direction(device, &io_direction)) != MM_ERROR_NONE)
3414                         return _convert_sound_manager_error_code(__func__, mm_ret);
3415                 if (!(io_direction & (direction + 1)) || ((int)io_direction < (int)(direction + 1))) {
3416                         LOGE("device direction(0x%x), request direction(0x%x)", io_direction, (direction + 1));
3417                         return SOUND_MANAGER_ERROR_INVALID_PARAMETER;
3418                 }
3419         }
3420
3421         return __invoke_ipc_set_preferred_device_id(stream_info, device_id, io_direction, direction);
3422 }
3423
3424 int _set_preferred_device_id(sound_stream_info_s *stream_info, sound_device_io_direction_e direction, int device_id)
3425 {
3426         int ret = SOUND_MANAGER_ERROR_NONE;
3427         int mm_ret = MM_ERROR_NONE;
3428         bool available = false;
3429         mm_sound_device_io_direction_e io_direction = MM_SOUND_DEVICE_IO_DIRECTION_IN;
3430
3431         SM_ARG_CHECK(stream_info);
3432
3433         /* allow only auto route type */
3434         if ((ret = __check_auto_route_type(stream_info)) != SOUND_MANAGER_ERROR_NONE)
3435                 return ret;
3436
3437         /* check if this device belongs to available devices of the stream info */
3438         /* In case device_id is 0, it's for unsetting preferred device. */
3439         if (device_id) {
3440                 MMSoundDevice_t device = NULL;
3441
3442                 if ((mm_ret = mm_sound_get_device_by_id(device_id, &device)) != MM_ERROR_NONE) {
3443                         LOGE("failed to mm_sound_get_device_by_id()");
3444                         return _convert_sound_manager_error_code(__func__, mm_ret);
3445                 }
3446                 if ((ret = __is_available_device(stream_info, (sound_device_h)device, &available)) != SOUND_MANAGER_ERROR_NONE)
3447                         goto device_free;
3448                 if (!available) {
3449                         ret = SOUND_MANAGER_ERROR_POLICY;
3450                         goto device_free;
3451                 }
3452                 if ((mm_ret = mm_sound_get_device_io_direction(device, &io_direction)) != MM_ERROR_NONE) {
3453                         ret = _convert_sound_manager_error_code(__func__, mm_ret);
3454                         goto  device_free;
3455                 }
3456                 if (!(io_direction & (direction + 1)) || ((int)io_direction < (int)(direction + 1))) {
3457                         LOGE("device direction(0x%x), request direction(0x%x)", io_direction, (direction + 1));
3458                         ret = SOUND_MANAGER_ERROR_INVALID_PARAMETER;
3459                 }
3460 device_free:
3461                 mm_sound_free_device(device);
3462                 if (ret)
3463                         return ret;
3464         }
3465
3466         return __invoke_ipc_set_preferred_device_id(stream_info, device_id, io_direction, direction);
3467 }
3468
3469 int _get_preferred_device(sound_stream_info_s *stream_info, int *in_device_id, int *out_device_id)
3470 {
3471         int ret = SOUND_MANAGER_ERROR_NONE;
3472         GDBusConnection *conn = NULL;
3473         GError *err = NULL;
3474         GVariant *result = NULL;
3475         const gchar *dbus_ret = NULL;
3476         unsigned int _in_device_id;
3477         unsigned int _out_device_id;
3478
3479         SM_ARG_CHECK(stream_info);
3480
3481         if ((ret = __get_dbus_connection(&conn)) != SOUND_MANAGER_ERROR_NONE)
3482                 return ret;
3483
3484         result = g_dbus_connection_call_sync(conn,
3485                 PA_BUS_NAME,
3486                 PA_STREAM_MANAGER_OBJECT_PATH,
3487                 PA_STREAM_MANAGER_INTERFACE,
3488                 PA_STREAM_MANAGER_METHOD_NAME_GET_STREAM_PREFERRED_DEVICE,
3489                 g_variant_new("(u)", stream_info->pa_info.index),
3490                 G_VARIANT_TYPE("(uus)"),
3491                 G_DBUS_CALL_FLAGS_NONE,
3492                 DBUS_METHOD_TIMEOUT,
3493                 NULL,
3494                 &err);
3495         if (!result || err) {
3496                 LOGE("g_dbus_connection_call_sync() for GET_STREAM_PREFERRED_DEVICE error");
3497                 ret = _convert_sound_manager_error_code(__func__, _convert_dbus_error(err ? err->message : NULL));
3498                 if (err)
3499                         g_error_free(err);
3500                 goto LEAVE;
3501         }
3502
3503         g_variant_get(result, "(uu&s)", &_in_device_id, &_out_device_id, &dbus_ret);
3504
3505         if (!strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret))) {
3506                 if (in_device_id) {
3507                         if (stream_info->preferred_device_info.in != _in_device_id) {
3508                                 LOGE("mismatching id [prev: %d, curr: %d]", stream_info->preferred_device_info.in, _in_device_id);
3509                                 ret = SOUND_MANAGER_ERROR_INTERNAL;
3510                         } else {
3511                                 *in_device_id = _in_device_id;
3512                                 LOGI("preferred device id[in:%d]", *in_device_id);
3513                         }
3514                 }
3515                 if (out_device_id) {
3516                         if (stream_info->preferred_device_info.out != _out_device_id) {
3517                                 LOGE("mismatching id [prev: %d, curr: %d]", stream_info->preferred_device_info.out, _out_device_id);
3518                                 ret = SOUND_MANAGER_ERROR_INTERNAL;
3519                         } else {
3520                                 *out_device_id = _out_device_id;
3521                                 LOGI("preferred device id[out:%d]", *out_device_id);
3522                         }
3523                 }
3524         } else {
3525                 ret = SOUND_MANAGER_ERROR_INTERNAL;
3526         }
3527
3528         LOGI("dbus_ret[%s] ret[0x%x]", dbus_ret, ret);
3529
3530 LEAVE:
3531         if (result)
3532                 g_variant_unref(result);
3533         g_object_unref(conn);
3534
3535         return ret;
3536 }
3537
3538 static int __invoke_ipc_set_preemptive_device(sound_stream_type_e stream_type, sound_device_io_direction_e io_direction, int device_id)
3539 {
3540         int ret = SOUND_MANAGER_ERROR_NONE;
3541         GVariant *result = NULL;
3542         GDBusConnection *conn = NULL;
3543         GError *err = NULL;
3544         const gchar *dbus_ret = NULL;
3545         const gchar *direction_str;
3546         char *stream_type_str;
3547         int i;
3548
3549         if ((ret = _convert_stream_type(stream_type, &stream_type_str)) != SOUND_MANAGER_ERROR_NONE)
3550                 return ret;
3551
3552         if ((ret = __get_dbus_connection(&conn)) != SOUND_MANAGER_ERROR_NONE)
3553                 return ret;
3554
3555         for (i = SOUND_DEVICE_IO_DIRECTION_IN; i < SOUND_DEVICE_IO_DIRECTION_BOTH; i++) {
3556                 if (io_direction != SOUND_DEVICE_IO_DIRECTION_BOTH && io_direction != i)
3557                         continue;
3558                 direction_str = (i == SOUND_DEVICE_IO_DIRECTION_IN) ? "in" : "out";
3559
3560                 result = g_dbus_connection_call_sync(conn,
3561                         PA_BUS_NAME,
3562                         PA_STREAM_MANAGER_OBJECT_PATH,
3563                         PA_STREAM_MANAGER_INTERFACE,
3564                         PA_STREAM_MANAGER_METHOD_NAME_SET_STREAM_PREEMPTIVE_DEVICE,
3565                         g_variant_new("(ssu)", stream_type_str, direction_str, (unsigned int)device_id),
3566                         NULL,
3567                         G_DBUS_CALL_FLAGS_NONE,
3568                         DBUS_METHOD_TIMEOUT,
3569                         NULL,
3570                         &err);
3571                 if (!result || err) {
3572                         LOGE("g_dbus_connection_call_sync() for SET_STREAM_PREEMPTIVE_DEVICE, direction(%s) error (%s)",
3573                                         direction_str, err ? err->message : NULL);
3574                         ret = _convert_sound_manager_error_code(__func__, _convert_dbus_error(err ? err->message : NULL));
3575                         if (err)
3576                                 g_error_free(err);
3577                         if (result) {
3578                                 g_variant_unref(result);
3579                                 result = NULL;
3580                         }
3581                         continue;
3582                 }
3583
3584                 LOGI("Preemptive device(id:%d, direction:%s) is set", device_id, direction_str);
3585
3586                 g_variant_get(result, "(&s)", &dbus_ret);
3587
3588                 if (!strncmp("STREAM_MANAGER_RETURN_INVALID_ARGUMENT", dbus_ret, strlen(dbus_ret)))
3589                         ret = SOUND_MANAGER_ERROR_INVALID_PARAMETER;
3590                 else if (!strncmp("STREAM_MANAGER_RETURN_POLICY", dbus_ret, strlen(dbus_ret)))
3591                         ret = SOUND_MANAGER_ERROR_POLICY;
3592                 else if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret)))
3593                         ret = SOUND_MANAGER_ERROR_INTERNAL;
3594
3595                 LOGI("dbus_ret[%s] ret[0x%x]", dbus_ret, ret);
3596
3597                 if (ret)
3598                         goto LEAVE;
3599         }
3600
3601 LEAVE:
3602         if (result)
3603                 g_variant_unref(result);
3604         g_object_unref(conn);
3605
3606         return ret;
3607 }
3608
3609 static int __invoke_ipc_get_preemptive_device(sound_stream_type_e stream_type, int *in_device_id, int *out_device_id)
3610 {
3611         int ret = SOUND_MANAGER_ERROR_NONE;
3612         GDBusConnection *conn = NULL;
3613         GError *err = NULL;
3614         GVariant *result = NULL;
3615         const gchar *dbus_ret = NULL;
3616         unsigned int _in_device_id;
3617         unsigned int _out_device_id;
3618         char *stream_type_str;
3619
3620         if ((ret = _convert_stream_type(stream_type, &stream_type_str)) != SOUND_MANAGER_ERROR_NONE)
3621                 return ret;
3622
3623         if ((ret = __get_dbus_connection(&conn)) != SOUND_MANAGER_ERROR_NONE)
3624                 return ret;
3625
3626         result = g_dbus_connection_call_sync(conn,
3627                 PA_BUS_NAME,
3628                 PA_STREAM_MANAGER_OBJECT_PATH,
3629                 PA_STREAM_MANAGER_INTERFACE,
3630                 PA_STREAM_MANAGER_METHOD_NAME_GET_STREAM_PREEMPTIVE_DEVICE,
3631                 g_variant_new("(s)", stream_type_str),
3632                 G_VARIANT_TYPE("(uus)"),
3633                 G_DBUS_CALL_FLAGS_NONE,
3634                 DBUS_METHOD_TIMEOUT,
3635                 NULL,
3636                 &err);
3637         if (!result || err) {
3638                 LOGE("g_dbus_connection_call_sync() for GET_STREAM_PREEMPTIVE_DEVICE error");
3639                 ret = _convert_sound_manager_error_code(__func__, _convert_dbus_error(err ? err->message : NULL));
3640                 if (err)
3641                         g_error_free(err);
3642                 goto LEAVE;
3643         }
3644         g_variant_get(result, "(uu&s)", &_in_device_id, &_out_device_id, &dbus_ret);
3645
3646         if (!strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret))) {
3647                 if (in_device_id) {
3648                         *in_device_id = _in_device_id;
3649                         LOGI("preemptive device id[in:%d]", *in_device_id);
3650                 }
3651                 if (out_device_id) {
3652                         *out_device_id = _out_device_id;
3653                         LOGI("preemptive device id[out:%d]", *out_device_id);
3654                 }
3655         } else {
3656                 ret = SOUND_MANAGER_ERROR_INTERNAL;
3657         }
3658
3659         LOGI("dbus_ret[%s] ret[0x%x]", dbus_ret, ret);
3660
3661 LEAVE:
3662         if (result)
3663                 g_variant_unref(result);
3664         g_object_unref(conn);
3665
3666         return ret;
3667 }
3668
3669 int _set_preemptive_device(sound_stream_type_e stream_type, sound_device_io_direction_e direction, int device_id)
3670 {
3671         return __invoke_ipc_set_preemptive_device(stream_type, direction, device_id);
3672 }
3673
3674 int _get_preemptive_device(sound_stream_type_e stream_type, int *in_device_id, int *out_device_id)
3675 {
3676         return __invoke_ipc_get_preemptive_device(stream_type, in_device_id, out_device_id);
3677 }
3678
3679 int _get_latest_stream_pid(int stream_type, unsigned int *pid)
3680 {
3681         int ret = SOUND_MANAGER_ERROR_NONE;
3682         GDBusConnection *conn = NULL;
3683         GError *err = NULL;
3684         GVariant *result = NULL;
3685         GVariantBuilder *builder_for_stream_types;
3686         const gchar *dbus_ret = NULL;
3687         unsigned int _pid;
3688
3689         SM_ARG_CHECK(pid);
3690
3691         if ((ret = __get_dbus_connection(&conn)) != SOUND_MANAGER_ERROR_NONE)
3692                 return ret;
3693
3694         builder_for_stream_types = g_variant_builder_new(G_VARIANT_TYPE("as"));
3695         if (!builder_for_stream_types) {
3696                 LOGE("failed to g_variant_builder_new()");
3697                 ret = SOUND_MANAGER_ERROR_INTERNAL;
3698                 goto LEAVE;
3699         }
3700
3701         if (stream_type & STREAM_TYPE_MEDIA)
3702                 g_variant_builder_add(builder_for_stream_types, "s", STREAM_MEDIA);
3703         if (stream_type & STREAM_TYPE_SYSTEM)
3704                 g_variant_builder_add(builder_for_stream_types, "s", STREAM_SYSTEM);
3705         if (stream_type & STREAM_TYPE_ALARM)
3706                 g_variant_builder_add(builder_for_stream_types, "s", STREAM_ALARM);
3707         if (stream_type & STREAM_TYPE_NOTIFICATION)
3708                 g_variant_builder_add(builder_for_stream_types, "s", STREAM_NOTIFICATION);
3709         if (stream_type & STREAM_TYPE_EMERGENCY)
3710                 g_variant_builder_add(builder_for_stream_types, "s", STREAM_EMERGENCY);
3711         if (stream_type & STREAM_TYPE_VOICE_INFORMATION)
3712                 g_variant_builder_add(builder_for_stream_types, "s", STREAM_VOICE_INFORMATION);
3713
3714         result = g_dbus_connection_call_sync(conn,
3715                 PA_BUS_NAME,
3716                 PA_STREAM_MANAGER_OBJECT_PATH,
3717                 PA_STREAM_MANAGER_INTERFACE,
3718                 PA_STREAM_MANAGER_METHOD_NAME_GET_LASTEST_STREAM_PID,
3719                 g_variant_new("(sas)", "out", builder_for_stream_types),
3720                 G_VARIANT_TYPE("(us)"),
3721                 G_DBUS_CALL_FLAGS_NONE,
3722                 DBUS_METHOD_TIMEOUT,
3723                 NULL,
3724                 &err);
3725         if (!result || err) {
3726                 LOGE("g_dbus_connection_call_sync() for GET_LASTEST_STREAM_PID error");
3727                 ret = _convert_sound_manager_error_code(__func__, _convert_dbus_error(err ? err->message : NULL));
3728                 if (err)
3729                         g_error_free(err);
3730                 goto LEAVE;
3731         }
3732
3733         g_variant_get(result, "(u&s)", &_pid, &dbus_ret);
3734
3735         if (!strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret)))
3736                 *pid = _pid;
3737         else if (!strncmp("STREAM_MANAGER_RETURN_ERROR_NO_STREAM", dbus_ret, strlen(dbus_ret)))
3738                 ret = SOUND_MANAGER_ERROR_NO_DATA;
3739         else
3740                 ret = SOUND_MANAGER_ERROR_INTERNAL;
3741
3742         LOGI("dbus_ret[%s] ret[0x%x]", dbus_ret, ret);
3743
3744 LEAVE:
3745         if (builder_for_stream_types)
3746                 g_variant_builder_unref(builder_for_stream_types);
3747         if (result)
3748                 g_variant_unref(result);
3749         g_object_unref(conn);
3750
3751         return ret;
3752 }
3753
3754 #define CONTAINER_FILE "/run/systemd/container"
3755 #define DBUS_HOST_SYSTEM_BUS_ADDRESS "unix:path=/run/host/dbus/system_bus_socket"
3756
3757 static GDBusConnection * __get_host_dbus_connection()
3758 {
3759         GDBusConnection *conn = NULL;
3760
3761         g_autoptr(GError) err = NULL;
3762
3763         if (access(CONTAINER_FILE, F_OK) != 0) {
3764                 LOGE("Not in container....");
3765                 return NULL;
3766         }
3767
3768         conn = g_dbus_connection_new_for_address_sync(DBUS_HOST_SYSTEM_BUS_ADDRESS,
3769                                 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
3770                                 NULL, NULL, &err);
3771         if (!conn)
3772                 LOGE("g_dbus_connection_new_for_address_sync() error (%s)", err ? err->message : "(null)");
3773
3774         return conn;
3775 }
3776
3777 int _set_host_volume_level(const char *direction, const char *volume_type, unsigned int level)
3778 {
3779         int ret = SOUND_MANAGER_ERROR_NONE;
3780         const gchar *dbus_ret = NULL;
3781
3782         g_autoptr(GVariant) result = NULL;
3783         g_autoptr(GDBusConnection) conn = NULL;
3784         g_autoptr(GError) err = NULL;
3785
3786         SM_ARG_CHECK(direction);
3787         SM_ARG_CHECK(volume_type);
3788
3789         if (!(conn = __get_host_dbus_connection()))
3790                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
3791
3792         result = g_dbus_connection_call_sync(conn,
3793                                                         PA_BUS_NAME,
3794                                                         PA_STREAM_MANAGER_OBJECT_PATH,
3795                                                         PA_STREAM_MANAGER_INTERFACE,
3796                                                         PA_STREAM_MANAGER_METHOD_NAME_SET_VOLUME_LEVEL,
3797                                                         g_variant_new("(ssu)", direction, volume_type, level),
3798                                                         G_VARIANT_TYPE("(s)"),
3799                                                         G_DBUS_CALL_FLAGS_NONE,
3800                                                         DBUS_METHOD_TIMEOUT,
3801                                                         NULL,
3802                                                         &err);
3803         if (!result)
3804                 return _convert_sound_manager_error_code(__func__, _convert_dbus_error(err ? err->message : NULL));
3805
3806         g_variant_get(result, "(&s)", &dbus_ret);
3807
3808         if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret)))
3809                 ret = SOUND_MANAGER_ERROR_INTERNAL;
3810
3811         LOGI("dbus_ret[%s] ret[0x%x]", dbus_ret, ret);
3812
3813         return ret;
3814 }
3815
3816 int _get_host_volume_level(const char *direction, const char *volume_type, unsigned int *level)
3817 {
3818         int ret = SOUND_MANAGER_ERROR_NONE;
3819         const gchar *dbus_ret = NULL;
3820
3821         g_autoptr(GVariant) result = NULL;
3822         g_autoptr(GDBusConnection) conn = NULL;
3823         g_autoptr(GError) err = NULL;
3824
3825         SM_ARG_CHECK(direction);
3826         SM_ARG_CHECK(volume_type);
3827         SM_ARG_CHECK(level);
3828
3829         if (!(conn = __get_host_dbus_connection()))
3830                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
3831
3832         result = g_dbus_connection_call_sync(conn,
3833                                                         PA_BUS_NAME,
3834                                                         PA_STREAM_MANAGER_OBJECT_PATH,
3835                                                         PA_STREAM_MANAGER_INTERFACE,
3836                                                         PA_STREAM_MANAGER_METHOD_NAME_GET_VOLUME_LEVEL,
3837                                                         g_variant_new("(ss)", direction, volume_type),
3838                                                         G_VARIANT_TYPE("(us)"),
3839                                                         G_DBUS_CALL_FLAGS_NONE,
3840                                                         DBUS_METHOD_TIMEOUT,
3841                                                         NULL,
3842                                                         &err);
3843         if (!result)
3844                 return _convert_sound_manager_error_code(__func__, _convert_dbus_error(err ? err->message : NULL));
3845
3846         g_variant_get(result, "(u&s)", level, &dbus_ret);
3847
3848         if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret)))
3849                 ret = SOUND_MANAGER_ERROR_INTERNAL;
3850         else
3851                 LOGI("level[%u]", *level);
3852
3853         LOGI("dbus_ret[%s] ret[0x%x]", dbus_ret, ret);
3854
3855         return ret;
3856 }
3857
3858 int _set_effect_method_with_reference(sound_stream_info_h stream_info, sound_effect_method_with_reference_e method, sound_device_h device)
3859 {
3860         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
3861
3862         int ret;
3863         int device_id;
3864         char *device_name;
3865
3866         SM_ARG_CHECK(stream_h);
3867         SM_ARG_CHECK(device);
3868
3869         if (!stream_h->stream_conf_info.avail_in_devices[0]) {
3870                 LOGE("stream_h[%p, %s] does not support any input devices", stream_h, stream_h->stream_type);
3871                 return SOUND_MANAGER_ERROR_POLICY;
3872         }
3873
3874         if ((ret = mm_sound_get_device_id(device, &device_id)) != MM_ERROR_NONE)
3875                 return _convert_sound_manager_error_code(__func__, ret);
3876
3877         if ((ret = mm_sound_get_device_name(device, &device_name)) != MM_ERROR_NONE)
3878                 return _convert_sound_manager_error_code(__func__, ret);
3879
3880         if (method == SOUND_MANAGER_STREAM_NO_METHOD ||
3881                 device_id == SOUND_MANAGER_STREAM_NO_REFERENCE_DEVICE)
3882                 return SOUND_MANAGER_ERROR_INVALID_PARAMETER;
3883
3884         stream_h->sound_effect.reference_method = method;
3885         stream_h->sound_effect.reference_device_id = device_id;
3886
3887         LOGI("set a effect. stream_h[%p, %s], method[%d], reference device[id:%d, name:%s]",
3888                 stream_h, stream_h->stream_type, method, device_id, device_name);
3889
3890         return SOUND_MANAGER_ERROR_NONE;
3891 }
3892
3893 int _get_effect_method_with_reference(sound_stream_info_h stream_info, sound_effect_method_with_reference_e *method, int *device_id)
3894 {
3895         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
3896
3897         SM_ARG_CHECK(stream_h);
3898         SM_ARG_CHECK(method);
3899         SM_ARG_CHECK(device_id);
3900
3901         if (stream_h->sound_effect.reference_method == SOUND_MANAGER_STREAM_NO_METHOD) {
3902                 LOGI("reference method isn't set yet");
3903                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
3904         }
3905
3906         if (stream_h->sound_effect.reference_device_id == SOUND_MANAGER_STREAM_NO_REFERENCE_DEVICE) {
3907                 LOGI("reference method device isn't set yet");
3908                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
3909         }
3910
3911         *method = stream_h->sound_effect.reference_method;
3912         *device_id = stream_h->sound_effect.reference_device_id;
3913
3914         LOGI("get a effect. stream_h[%p, %s] get sound effect. method(%d), reference device[id:%d]",
3915                 stream_h, stream_h->stream_type, *method, *device_id);
3916
3917         return SOUND_MANAGER_ERROR_NONE;
3918 }
3919
3920 int _set_effect_method(sound_stream_info_h stream_info, int method)
3921 {
3922         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
3923
3924         SM_ARG_CHECK(stream_h);
3925
3926         if (!stream_h->stream_conf_info.avail_in_devices[0]) {
3927                 LOGE("stream_h[%p, %s] does not support any input devices", stream_h, stream_h->stream_type);
3928                 return SOUND_MANAGER_ERROR_POLICY;
3929         }
3930
3931         if (method == SOUND_MANAGER_STREAM_NO_METHOD)
3932                 return SOUND_MANAGER_ERROR_INVALID_PARAMETER;
3933
3934         stream_h->sound_effect.method = method;
3935
3936         LOGI("set effects. stream_h[%p, %s] method[0x%x]", stream_h, stream_h->stream_type, method);
3937
3938         return SOUND_MANAGER_ERROR_NONE;
3939 }
3940
3941 int _get_effect_method(sound_stream_info_h stream_info, int *method)
3942 {
3943         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
3944
3945         SM_ARG_CHECK(stream_h);
3946         SM_ARG_CHECK(method);
3947
3948         if (stream_h->sound_effect.method == SOUND_MANAGER_STREAM_NO_METHOD) {
3949                 LOGI("method aren't set yet");
3950                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
3951         }
3952
3953         *method = stream_h->sound_effect.method;
3954
3955         LOGI("get effects. stream_h[%p, %s] method[0x%x]", stream_h, stream_h->stream_type, *method);
3956
3957         return SOUND_MANAGER_ERROR_NONE;
3958 }
3959
3960 //LCOV_EXCL_STOP