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