9bd3424b0c4d2b487c2d017f157ea81c68509048
[platform/core/api/sound-manager.git] / src / sound_manager_private.c
1 /*
2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <sound_manager.h>
18 #include <sound_manager_private.h>
19 #include <mm_sound.h>
20 #include <vconf.h>
21
22 #define PA_BUS_NAME                                             "org.pulseaudio.Server"
23
24 #define PA_STREAM_MANAGER_OBJECT_PATH                           "/org/pulseaudio/StreamManager"
25 #define PA_STREAM_MANAGER_INTERFACE                             "org.pulseaudio.StreamManager"
26 #define PA_STREAM_MANAGER_METHOD_NAME_GET_STREAM_INFO           "GetStreamInfo"
27 #define PA_STREAM_MANAGER_METHOD_NAME_SET_STREAM_ROUTE_DEVICES  "SetStreamRouteDevices"
28 #define PA_STREAM_MANAGER_METHOD_NAME_SET_STREAM_ROUTE_OPTION   "SetStreamRouteOption"
29 #define PA_STREAM_MANAGER_METHOD_NAME_GET_VOLUME_MAX_LEVEL      "GetVolumeMaxLevel"
30 #define PA_STREAM_MANAGER_METHOD_NAME_GET_VOLUME_LEVEL          "GetVolumeLevel"
31 #define PA_STREAM_MANAGER_METHOD_NAME_SET_VOLUME_LEVEL          "SetVolumeLevel"
32 #define PA_STREAM_MANAGER_METHOD_NAME_GET_CURRENT_VOLUME_TYPE   "GetCurrentVolumeType"
33 #define PA_STREAM_MANAGER_METHOD_NAME_GET_CURRENT_MEDIA_ROUTING_PATH "GetCurrentMediaRoutingPath"
34 #define PA_STREAM_MANAGER_METHOD_NAME_UPDATE_FOCUS_STATUS       "UpdateFocusStatus"
35 #define PA_STREAM_MANAGER_METHOD_NAME_CHECK_STREAM_EXIST_BY_PID "CheckStreamExistByPid"
36
37 #define PA_DEVICE_MANAGER_OBJECT_PATH                           "/org/pulseaudio/DeviceManager"
38 #define PA_DEVICE_MANAGER_INTERFACE                             "org.pulseaudio.DeviceManager"
39 #define PA_DEVICE_MANAGER_METHOD_NAME_IS_DEVICE_RUNNING_BY_ID   "IsDeviceRunningById"
40 #define PA_DEVICE_MANAGER_METHOD_NAME_GET_SUPPORTED_SAMPLE_FORMATS "GetSupportedSampleFormats"
41 #define PA_DEVICE_MANAGER_METHOD_NAME_SET_SAMPLE_FORMAT         "SetSampleFormat"
42 #define PA_DEVICE_MANAGER_METHOD_NAME_GET_SAMPLE_FORMAT         "GetSampleFormat"
43 #define PA_DEVICE_MANAGER_METHOD_NAME_GET_SUPPORTED_SAMPLE_RATES   "GetSupportedSampleRates"
44 #define PA_DEVICE_MANAGER_METHOD_NAME_SET_SAMPLE_RATE           "SetSampleRate"
45 #define PA_DEVICE_MANAGER_METHOD_NAME_GET_SAMPLE_RATE           "GetSampleRate"
46 #define PA_DEVICE_MANAGER_METHOD_NAME_SET_AVOID_RESAMPLING      "SetAvoidResampling"
47 #define PA_DEVICE_MANAGER_METHOD_NAME_GET_AVOID_RESAMPLING      "GetAvoidResampling"
48 #define PA_DEVICE_MANAGER_METHOD_NAME_SET_SPECIFIC_STREAM       "SetSpecificStreamOnly"
49 #define PA_DEVICE_MANAGER_METHOD_NAME_GET_SPECIFIED_STREAM      "GetSpecifiedStream"
50
51 #define VCONF_PATH_PREFIX_VOLUME                                "file/private/sound/volume/"
52 #define VCONF_PATH_MAX                                          64
53
54 #define DBUS_ERR_MSG_MAX                                        24
55
56 int _convert_dbus_error(const char *error_msg)
57 {
58         int ret = MM_ERROR_NONE;
59         const char ch = '.';
60         char *ret_str;
61
62         if (!error_msg)
63                 return MM_ERROR_SOUND_INTERNAL;
64
65         /* parsing dbus error message, for example,
66          *   GDBus.Error:org.freedesktop.DBus.Error.InvalidArgs:
67          *   org.tizen.multimedia.audio.InvalidArgument */
68         if (!(ret_str = strrchr(error_msg, ch)))
69                 return MM_ERROR_SOUND_INTERNAL;
70
71         ret_str = ret_str + 1;
72         if (ret_str[0] == '\0')
73                 return MM_ERROR_SOUND_INTERNAL;
74
75         if (!strncmp(ret_str, "InvalidArgument", DBUS_ERR_MSG_MAX))
76                 ret = MM_ERROR_INVALID_ARGUMENT;
77         else if (!strncmp(ret_str, "InvalidOperation", DBUS_ERR_MSG_MAX))
78                 ret = MM_ERROR_SOUND_INVALID_OPERATION;
79         else if (!strncmp(ret_str, "PolicyInternal", DBUS_ERR_MSG_MAX))
80                 ret = MM_ERROR_POLICY_INTERNAL;
81         else
82                 ret = MM_ERROR_SOUND_INTERNAL;
83
84         LOGE("%s => 0x%x", ret_str, ret);
85
86         return ret;
87 }
88
89 int _convert_sound_manager_error_code(const char *func, int code)
90 {
91         int ret = SOUND_MANAGER_ERROR_NONE;
92         char *errorstr = NULL;
93
94         switch (code) {
95         case MM_ERROR_FILE_WRITE:
96         case MM_ERROR_INVALID_HANDLE:
97         case MM_ERROR_SOUND_INVALID_OPERATION:
98                 ret = SOUND_MANAGER_ERROR_INVALID_OPERATION;
99                 errorstr = "INVALID_OPERATION";
100                 break;
101         case MM_ERROR_NONE:
102                 ret = SOUND_MANAGER_ERROR_NONE;
103                 errorstr = "ERROR_NONE";
104                 break;
105         case MM_ERROR_INVALID_ARGUMENT:
106         case MM_ERROR_SOUND_INVALID_POINTER:
107                 ret = SOUND_MANAGER_ERROR_INVALID_PARAMETER;
108                 errorstr = "INVALID_PARAMETER";
109                 break;
110         case MM_ERROR_SOUND_PERMISSION_DENIED:
111                 //LCOV_EXCL_START
112                 ret = SOUND_MANAGER_ERROR_PERMISSION_DENIED;
113                 errorstr = "PERMISSION_DENIED";
114                 break;
115                 //LCOV_EXCL_STOP
116         case MM_ERROR_SOUND_NO_DATA:
117                 ret = SOUND_MANAGER_ERROR_NO_DATA;
118                 errorstr = "NO_DATA";
119                 break;
120         case MM_ERROR_SOUND_INTERNAL:
121         case MM_ERROR_SOUND_VOLUME_CAPTURE_ONLY:
122         case MM_ERROR_OUT_OF_MEMORY:
123                 ret = SOUND_MANAGER_ERROR_INTERNAL;
124                 errorstr = "INTERNAL";
125                 break;
126         case MM_ERROR_POLICY_DUPLICATED:
127         case MM_ERROR_POLICY_INTERNAL:
128         case MM_ERROR_POLICY_BLOCKED:
129                 ret = SOUND_MANAGER_ERROR_POLICY;
130                 errorstr = "POLICY";
131                 break;
132         case MM_ERROR_SOUND_VOLUME_NO_INSTANCE:
133                 ret = SOUND_MANAGER_ERROR_NO_PLAYING_SOUND;
134                 errorstr = "NO_PLAYING_SOUND";
135                 break;
136         case MM_ERROR_NOT_SUPPORT_API:
137                 ret = SOUND_MANAGER_ERROR_NOT_SUPPORTED;
138                 errorstr = "NOT_SUPPORTED";
139                 break;
140         case MM_ERROR_SOUND_INVALID_STATE:
141                 ret = SOUND_MANAGER_ERROR_INVALID_STATE;
142                 errorstr = "INVALID_STATE";
143                 break;
144         default:
145                 //LCOV_EXCL_START
146                 LOGW("it should not be reached here, this error(0x%x) should be defined.", code);
147                 ret = SOUND_MANAGER_ERROR_INTERNAL;
148                 errorstr = "INTERNAL";
149                 break;
150                 //LCOV_EXCL_STOP
151         }
152         if (ret)
153                 LOGE("[%s] >> leave : %s(0x%08x), mm_error(0x%08x)", func, errorstr, ret, code);
154         else
155                 LOGD("[%s] >> leave : %s(0x%08x)", func, errorstr, ret);
156
157         return ret;
158 }
159
160 int _convert_stream_type(sound_stream_type_e stream_type_enum, char **stream_type)
161 {
162         int ret = MM_ERROR_NONE;
163
164         if (stream_type == NULL)
165                 return MM_ERROR_INVALID_ARGUMENT;
166
167         switch (stream_type_enum) {
168         case SOUND_STREAM_TYPE_MEDIA:
169                 *stream_type = "media";
170                 break;
171         case SOUND_STREAM_TYPE_SYSTEM:
172                 *stream_type = "system";
173                 break;
174         case SOUND_STREAM_TYPE_ALARM:
175                 *stream_type = "alarm";
176                 break;
177         case SOUND_STREAM_TYPE_NOTIFICATION:
178                 *stream_type = "notification";
179                 break;
180         case SOUND_STREAM_TYPE_EMERGENCY:
181                 *stream_type = "emergency";
182                 break;
183         case SOUND_STREAM_TYPE_VOICE_INFORMATION:
184                 *stream_type = "voice-information";
185                 break;
186         case SOUND_STREAM_TYPE_VOICE_RECOGNITION:
187                 *stream_type = "voice-recognition";
188                 break;
189         case SOUND_STREAM_TYPE_RINGTONE_VOIP:
190                 *stream_type = "ringtone-voip";
191                 break;
192         case SOUND_STREAM_TYPE_VOIP:
193                 *stream_type = "voip";
194                 break;
195         case SOUND_STREAM_TYPE_MEDIA_EXTERNAL_ONLY:
196                 *stream_type = "ext-media";
197                 break;
198         default:
199                 LOGE("could not find the stream_type[%d] in this switch case statement", stream_type_enum);
200                 ret = MM_ERROR_SOUND_INTERNAL;
201                 break;
202         }
203         LOGI("stream_type[%s]", *stream_type);
204
205         return ret;
206 }
207
208 int _convert_stream_type_for_internal(sound_stream_type_internal_e stream_type_enum, char **stream_type)
209 {
210         int ret = MM_ERROR_NONE;
211
212         if (stream_type == NULL)
213                 return MM_ERROR_INVALID_ARGUMENT;
214
215         switch (stream_type_enum) {
216         case SOUND_STREAM_TYPE_RINGTONE_CALL:
217                 *stream_type = "ringtone-call";
218                 break;
219         case SOUND_STREAM_TYPE_RINGBACKTONE_CALL:
220                 *stream_type = "ringbacktone-call";
221                 break;
222         case SOUND_STREAM_TYPE_VOICE_CALL:
223                 *stream_type = "call-voice";
224                 break;
225         case SOUND_STREAM_TYPE_VIDEO_CALL:
226                 *stream_type = "call-video";
227                 break;
228         case SOUND_STREAM_TYPE_RADIO:
229                 *stream_type = "radio";
230                 break;
231         case SOUND_STREAM_TYPE_LOOPBACK:
232                 *stream_type = "loopback";
233                 break;
234         case SOUND_STREAM_TYPE_LOOPBACK_MIRRORING:
235                 *stream_type = "loopback-mirroring";
236                 break;
237         case SOUND_STREAM_TYPE_SOLO:
238                 *stream_type = "solo";
239                 break;
240         case SOUND_STREAM_TYPE_VOICE_RECOGNITION_SERVICE:
241                 *stream_type = "voice-recognition-service";
242                 break;
243         case SOUND_STREAM_TYPE_MEDIA_COMPRESSED:
244                 *stream_type = "compressed-media";
245                 break;
246         default:
247                 LOGE("could not find the stream_type[%d] in this switch case statement", stream_type_enum);
248                 ret = MM_ERROR_SOUND_INTERNAL;
249                 break;
250         }
251         LOGI("stream_type_for_internal[%s]", *stream_type);
252
253         return ret;
254 }
255
256 void _set_focus_availability(sound_stream_info_s *stream_info)
257 {
258         if (stream_info == NULL || stream_info->stream_type == NULL) {
259                 //LCOV_EXCL_START
260                 LOGE("invalid argument");
261                 return;
262                 //LCOV_EXCL_STOP
263         }
264         if (!strncmp(stream_info->stream_type, "solo", SOUND_STREAM_TYPE_LEN) ||
265                 !strncmp(stream_info->stream_type, "radio", SOUND_STREAM_TYPE_LEN) ||
266                 !strncmp(stream_info->stream_type, "loopback-mirroring", SOUND_STREAM_TYPE_LEN)) {
267                 stream_info->is_focus_unavailable = true;
268                 LOGI("this stream_type[%s] does not support focus", stream_info->stream_type);
269         }
270
271         return;
272 }
273
274 int _convert_stream_type_to_change_reason(const char *stream_type, sound_stream_focus_change_reason_e *change_reason)
275 {
276         SM_NULL_ARG_CHECK_FOR_PRIV(stream_type);
277         SM_NULL_ARG_CHECK_FOR_PRIV(change_reason);
278
279         if (!strncmp(stream_type, "media", SOUND_STREAM_TYPE_LEN) ||
280                 !strncmp(stream_type, "compressed-media", SOUND_STREAM_TYPE_LEN) ||
281                 !strncmp(stream_type, "radio", SOUND_STREAM_TYPE_LEN) ||
282                 !strncmp(stream_type, "loopback", SOUND_STREAM_TYPE_LEN)) {
283                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA;
284
285         } else if (!strncmp(stream_type, "system", SOUND_STREAM_TYPE_LEN)) {
286                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_SYSTEM;
287
288         } else if (!strncmp(stream_type, "alarm", SOUND_STREAM_TYPE_LEN)) {
289                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_ALARM;
290
291         } else if (!strncmp(stream_type, "notification", SOUND_STREAM_TYPE_LEN)) {
292                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_NOTIFICATION;
293
294         } else if (!strncmp(stream_type, "emergency", SOUND_STREAM_TYPE_LEN)) {
295                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_EMERGENCY;
296
297         } else if (!strncmp(stream_type, "voice-information", SOUND_STREAM_TYPE_LEN)) {
298                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_INFORMATION;
299
300         } else if (!strncmp(stream_type, "voice-recognition", SOUND_STREAM_TYPE_LEN) ||
301                         !strncmp(stream_type, "voice-recognition-service", SOUND_STREAM_TYPE_LEN)) {
302                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_RECOGNITION;
303
304         } else if (!strncmp(stream_type, "ringtone-voip", SOUND_STREAM_TYPE_LEN) ||
305                         !strncmp(stream_type, "ringtone-call", SOUND_STREAM_TYPE_LEN) ||
306                         !strncmp(stream_type, "ringbacktone-call", SOUND_STREAM_TYPE_LEN)) {
307                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_RINGTONE;
308
309         } else if (!strncmp(stream_type, "voip", SOUND_STREAM_TYPE_LEN)) {
310                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_VOIP;
311
312         } else if (!strncmp(stream_type, "call-voice", SOUND_STREAM_TYPE_LEN) ||
313                         !strncmp(stream_type, "call-video", SOUND_STREAM_TYPE_LEN)) {
314                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_CALL;
315
316         } else if (!strncmp(stream_type, "ext-media", SOUND_STREAM_TYPE_LEN)) {
317                 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA_EXTERNAL_ONLY;
318
319         } else {
320                 //LCOV_EXCL_START
321                 LOGE("not supported stream_type(%s)", stream_type);
322                 return MM_ERROR_INVALID_ARGUMENT;
323                 //LCOV_EXCL_STOP
324         }
325
326         return MM_ERROR_NONE;
327 }
328
329 static int __get_dbus_connection(GDBusConnection **conn)
330 {
331         GError *err = NULL;
332
333         *conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
334         if (!(*conn) || err) {
335                 //LCOV_EXCL_START
336                 if (err)
337                         LOGE("g_bus_get_sync() error (%s)", err->message);
338                 else
339                         LOGE("g_bus_get_sync() error");
340                 g_error_free(err);
341                 return MM_ERROR_SOUND_INTERNAL;
342                 //LCOV_EXCL_STOP
343         }
344
345         return MM_ERROR_NONE;
346 }
347
348 int _convert_sound_type(sound_type_e sound_type, const char **volume_type)
349 {
350         SM_NULL_ARG_CHECK_FOR_PRIV(volume_type);
351
352         switch (sound_type) {
353         case SOUND_TYPE_SYSTEM:
354                 *volume_type = "system";
355                 break;
356         case SOUND_TYPE_NOTIFICATION:
357                 *volume_type = "notification";
358                 break;
359         case SOUND_TYPE_ALARM:
360                 *volume_type = "alarm";
361                 break;
362         case SOUND_TYPE_RINGTONE:
363                 *volume_type = "ringtone";
364                 break;
365         case SOUND_TYPE_MEDIA:
366                 *volume_type = "media";
367                 break;
368         case SOUND_TYPE_CALL:
369                 *volume_type = "call";
370                 break;
371         case SOUND_TYPE_VOIP:
372                 *volume_type = "voip";
373                 break;
374         case SOUND_TYPE_VOICE:
375                 *volume_type = "voice";
376                 break;
377         }
378         LOGI("volume_type[%s]", *volume_type);
379
380         return MM_ERROR_NONE;
381 }
382
383 int _convert_sound_type_to_enum(const char *sound_type, sound_type_e *sound_type_enum)
384 {
385         SM_NULL_ARG_CHECK_FOR_PRIV(sound_type);
386         SM_NULL_ARG_CHECK_FOR_PRIV(sound_type_enum);
387
388         if (!strncmp(sound_type, "system", strlen(sound_type))) {
389                 *sound_type_enum = SOUND_TYPE_SYSTEM;
390         } else if (!strncmp(sound_type, "notification", strlen(sound_type))) {
391                 *sound_type_enum = SOUND_TYPE_NOTIFICATION;
392         } else if (!strncmp(sound_type, "alarm", strlen(sound_type))) {
393                 *sound_type_enum = SOUND_TYPE_ALARM;
394         } else if (!strncmp(sound_type, "ringtone", strlen(sound_type))) {
395                 *sound_type_enum = SOUND_TYPE_RINGTONE;
396         } else if (!strncmp(sound_type, "media", strlen(sound_type))) {
397                 *sound_type_enum = SOUND_TYPE_MEDIA;
398         } else if (!strncmp(sound_type, "call", strlen(sound_type))) {
399                 *sound_type_enum = SOUND_TYPE_CALL;
400         } else if (!strncmp(sound_type, "voip", strlen(sound_type))) {
401                 *sound_type_enum = SOUND_TYPE_VOIP;
402         } else if (!strncmp(sound_type, "voice", strlen(sound_type))) {
403                 *sound_type_enum = SOUND_TYPE_VOICE;
404         } else {
405                 //LCOV_EXCL_START
406                 LOGE("not supported sound_type(%s)", sound_type);
407                 return MM_ERROR_INVALID_ARGUMENT;
408                 //LCOV_EXCL_STOP
409         }
410
411         return MM_ERROR_NONE;
412 }
413
414 int _convert_device_type_enum_to_str(sound_device_type_e device_type, char **device_type_str)
415 {
416         SM_NULL_ARG_CHECK_FOR_PRIV(device_type_str);
417
418         switch (device_type) {
419         case SOUND_DEVICE_BUILTIN_SPEAKER:
420                 *device_type_str = "builtin-speaker";
421                 break;
422         case SOUND_DEVICE_BUILTIN_RECEIVER:
423                 *device_type_str = "builtin-receiver";
424                 break;
425         case SOUND_DEVICE_BUILTIN_MIC:
426                 *device_type_str = "builtin-mic";
427                 break;
428         //LCOV_EXCL_START
429         case SOUND_DEVICE_AUDIO_JACK:
430                 *device_type_str = "audio-jack";
431                 break;
432         case SOUND_DEVICE_BLUETOOTH_MEDIA:
433                 *device_type_str = "bt-a2dp";
434                 break;
435         case SOUND_DEVICE_BLUETOOTH_VOICE:
436                 *device_type_str = "bt-sco";
437                 break;
438         case SOUND_DEVICE_HDMI:
439                 *device_type_str = "hdmi";
440                 break;
441         case SOUND_DEVICE_USB_AUDIO:
442                 *device_type_str = "usb-audio";
443                 break;
444         case SOUND_DEVICE_FORWARDING:
445                 *device_type_str = "forwarding";
446                 break;
447         default:
448                 LOGE("could not find the device_type[%d] in this switch case statement", device_type);
449                 return MM_ERROR_SOUND_INTERNAL;
450         //LCOV_EXCL_STOP
451         }
452
453         LOGI("device_type[%s]", *device_type_str);
454
455         return MM_ERROR_NONE;
456 }
457
458 int _convert_device_type_str_to_enum(const char *device_type_str, sound_device_type_e *device_type)
459 {
460         SM_NULL_ARG_CHECK_FOR_PRIV(device_type_str);
461         SM_NULL_ARG_CHECK_FOR_PRIV(device_type);
462
463         if (!strncmp(device_type_str, "builtin-speaker", SOUND_DEVICE_TYPE_LEN)) {
464                 *device_type = SOUND_DEVICE_BUILTIN_SPEAKER;
465         //LCOV_EXCL_START
466         } else if (!strncmp(device_type_str, "builtin-receiver", SOUND_DEVICE_TYPE_LEN)) {
467                 *device_type = SOUND_DEVICE_BUILTIN_RECEIVER;
468
469         } else if (!strncmp(device_type_str, "builtin-mic", SOUND_DEVICE_TYPE_LEN)) {
470                 *device_type = SOUND_DEVICE_BUILTIN_MIC;
471
472         } else if (!strncmp(device_type_str, "audio-jack", SOUND_DEVICE_TYPE_LEN)) {
473                 *device_type = SOUND_DEVICE_AUDIO_JACK;
474         } else if (!strncmp(device_type_str, "hdmi", SOUND_DEVICE_TYPE_LEN)) {
475                 *device_type = SOUND_DEVICE_HDMI;
476
477         } else if (!strncmp(device_type_str, "usb-audio", SOUND_DEVICE_TYPE_LEN)) {
478                 *device_type = SOUND_DEVICE_USB_AUDIO;
479
480         } else if (!strncmp(device_type_str, "bt-a2dp", SOUND_DEVICE_TYPE_LEN)) {
481                 *device_type = SOUND_DEVICE_BLUETOOTH_MEDIA;
482
483         } else if (!strncmp(device_type_str, "bt-sco", SOUND_DEVICE_TYPE_LEN)) {
484                 *device_type = SOUND_DEVICE_BLUETOOTH_VOICE;
485
486         } else {
487                 LOGE("not supported device_type(%s)", device_type_str);
488                 return MM_ERROR_INVALID_ARGUMENT;
489         }
490         //LCOV_EXCL_STOP
491
492         return MM_ERROR_NONE;
493 }
494
495 int _convert_device_type(mm_sound_device_type_e device_type, sound_device_type_e *sound_device_type)
496 {
497         switch (device_type) {
498         case MM_SOUND_DEVICE_TYPE_BUILTIN_SPEAKER:
499                 *sound_device_type = SOUND_DEVICE_BUILTIN_SPEAKER;
500                 break;
501         case MM_SOUND_DEVICE_TYPE_BUILTIN_RECEIVER:
502                 *sound_device_type = SOUND_DEVICE_BUILTIN_RECEIVER;
503                 break;
504         case MM_SOUND_DEVICE_TYPE_BUILTIN_MIC:
505                 *sound_device_type = SOUND_DEVICE_BUILTIN_MIC;
506                 break;
507         //LCOV_EXCL_START
508         case MM_SOUND_DEVICE_TYPE_AUDIOJACK:
509                 *sound_device_type = SOUND_DEVICE_AUDIO_JACK;
510                 break;
511         case MM_SOUND_DEVICE_TYPE_BLUETOOTH_A2DP:
512                 *sound_device_type = SOUND_DEVICE_BLUETOOTH_MEDIA;
513                 break;
514         case MM_SOUND_DEVICE_TYPE_BLUETOOTH_SCO:
515                 *sound_device_type = SOUND_DEVICE_BLUETOOTH_VOICE;
516                 break;
517         case MM_SOUND_DEVICE_TYPE_HDMI:
518                 *sound_device_type = SOUND_DEVICE_HDMI;
519                 break;
520         case MM_SOUND_DEVICE_TYPE_USB_AUDIO:
521                 *sound_device_type = SOUND_DEVICE_USB_AUDIO;
522                 break;
523         case MM_SOUND_DEVICE_TYPE_MIRRORING:
524                 *sound_device_type = SOUND_DEVICE_FORWARDING;
525                 break;
526         default:
527                 LOGE("not supported device_type(%d)", device_type);
528                 return MM_ERROR_INVALID_ARGUMENT;
529         //LCOV_EXCL_STOP
530         }
531
532         return MM_ERROR_NONE;
533 }
534
535 int _convert_device_io_direction(mm_sound_device_io_direction_e io_direction, sound_device_io_direction_e *sound_io_direction)
536 {
537         SM_NULL_ARG_CHECK(sound_io_direction);
538
539         switch (io_direction) {
540         case MM_SOUND_DEVICE_IO_DIRECTION_IN:
541                 *sound_io_direction = SOUND_DEVICE_IO_DIRECTION_IN;
542                 break;
543         case MM_SOUND_DEVICE_IO_DIRECTION_OUT:
544                 *sound_io_direction = SOUND_DEVICE_IO_DIRECTION_OUT;
545                 break;
546         case MM_SOUND_DEVICE_IO_DIRECTION_BOTH:
547                 *sound_io_direction = SOUND_DEVICE_IO_DIRECTION_BOTH;
548                 break;
549         }
550
551         return MM_ERROR_NONE;
552 }
553
554 const char* _convert_api_name(native_api_e api_name)
555 {
556         const char* name = NULL;
557
558         switch (api_name) {
559         case NATIVE_API_SOUND_MANAGER:
560                 name = "sound-manager";
561                 break;
562         case NATIVE_API_PLAYER:
563                 name = "player";
564                 break;
565         case NATIVE_API_WAV_PLAYER:
566                 name = "wav-player";
567                 break;
568         case NATIVE_API_TONE_PLAYER:
569                 name = "tone-player";
570                 break;
571         case NATIVE_API_AUDIO_IO:
572                 name = "audio-io";
573                 break;
574         case NATIVE_API_RECORDER:
575                 name = "recorder";
576                 break;
577         }
578
579         return name;
580 }
581
582 int _convert_sample_format_enum_to_str(sound_sample_format_e format, char **format_str)
583 {
584         SM_NULL_ARG_CHECK_FOR_PRIV(format_str);
585
586         switch (format) {
587         case SOUND_SAMPLE_FORMAT_U8:
588                 *format_str = "u8";
589                 break;
590         case SOUND_SAMPLE_FORMAT_S16_LE:
591                 *format_str = "s16le";
592                 break;
593         case SOUND_SAMPLE_FORMAT_S24_LE:
594                 *format_str = "s24le";
595                 break;
596         case SOUND_SAMPLE_FORMAT_S24_32_LE:
597                 *format_str = "s24-32le";
598                 break;
599         default:
600                 LOGE("could not find format[%d] in this switch case statement", format);
601                 return MM_ERROR_SOUND_INTERNAL;
602         }
603
604         return MM_ERROR_NONE;
605 }
606
607 int _convert_sample_format_str_to_enum(const char *format_str, sound_sample_format_e *format)
608 {
609         SM_NULL_ARG_CHECK_FOR_PRIV(format_str);
610         SM_NULL_ARG_CHECK_FOR_PRIV(format);
611
612         if (!strncmp(format_str, "u8", SOUND_SAMPLE_FORMAT_LEN) || !strncmp(format_str, "8", SOUND_SAMPLE_FORMAT_LEN)) {
613                 *format = SOUND_SAMPLE_FORMAT_U8;
614         } else if (!strncmp(format_str, "s16le", SOUND_SAMPLE_FORMAT_LEN)) {
615                 *format = SOUND_SAMPLE_FORMAT_S16_LE;
616         } else if (!strncmp(format_str, "s24le", SOUND_SAMPLE_FORMAT_LEN)) {
617                 *format = SOUND_SAMPLE_FORMAT_S24_LE;
618         } else if (!strncmp(format_str, "s24-32le", SOUND_SAMPLE_FORMAT_LEN)) {
619                 *format = SOUND_SAMPLE_FORMAT_S24_32_LE;
620         } else {
621                 LOGE("not supported sample format(%s)", format_str);
622                 return MM_ERROR_INVALID_ARGUMENT;
623         }
624
625         return MM_ERROR_NONE;
626 }
627
628 int _convert_sample_rate_enum_to_uint(sound_sample_rate_e rate, unsigned int *sample_rate)
629 {
630         SM_NULL_ARG_CHECK_FOR_PRIV(sample_rate);
631
632         switch (rate) {
633         case SOUND_SAMPLE_RATE_8000:
634                 *sample_rate = 8000;
635                 break;
636         case SOUND_SAMPLE_RATE_16000:
637                 *sample_rate = 16000;
638                 break;
639         case SOUND_SAMPLE_RATE_22050:
640                 *sample_rate = 22050;
641                 break;
642         case SOUND_SAMPLE_RATE_44100:
643                 *sample_rate = 44100;
644                 break;
645         case SOUND_SAMPLE_RATE_48000:
646                 *sample_rate = 48000;
647                 break;
648         case SOUND_SAMPLE_RATE_88200:
649                 *sample_rate = 88200;
650                 break;
651         case SOUND_SAMPLE_RATE_96000:
652                 *sample_rate = 96000;
653                 break;
654         case SOUND_SAMPLE_RATE_192000:
655                 *sample_rate = 192000;
656                 break;
657         default:
658                 LOGE("not supported sample rate(%u)", rate);
659                 return MM_ERROR_INVALID_ARGUMENT;
660         }
661
662         return MM_ERROR_NONE;
663 }
664
665 int _convert_sample_rate_to_enum(unsigned int rate, sound_sample_rate_e *rate_e)
666 {
667         SM_NULL_ARG_CHECK_FOR_PRIV(rate_e);
668
669         switch (rate) {
670         case 8000:
671                 *rate_e = SOUND_SAMPLE_RATE_8000;
672                 break;
673         case 16000:
674                 *rate_e = SOUND_SAMPLE_RATE_16000;
675                 break;
676         case 22050:
677                 *rate_e = SOUND_SAMPLE_RATE_22050;
678                 break;
679         case 44100:
680                 *rate_e = SOUND_SAMPLE_RATE_44100;
681                 break;
682         case 48000:
683                 *rate_e = SOUND_SAMPLE_RATE_48000;
684                 break;
685         case 88200:
686                 *rate_e = SOUND_SAMPLE_RATE_88200;
687                 break;
688         case 96000:
689                 *rate_e = SOUND_SAMPLE_RATE_96000;
690                 break;
691         case 192000:
692                 *rate_e = SOUND_SAMPLE_RATE_192000;
693                 break;
694         default:
695                 LOGE("not supported sample rate(%u)", rate);
696                 return MM_ERROR_INVALID_ARGUMENT;
697         }
698
699         return MM_ERROR_NONE;
700 }
701
702 int _return_val_if_not_usb_device(sound_device_h device, int ret_val)
703 {
704         mm_sound_device_type_e type;
705
706         if (mm_sound_get_device_type(device, &type))
707                 return ret_val;
708
709         if (type != MM_SOUND_DEVICE_TYPE_USB_AUDIO)     {
710                 LOGE("device type is not USB AUDIO");
711                 return ret_val;
712         }
713
714         return MM_ERROR_NONE;
715 }
716
717 //LCOV_EXCL_START
718 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)
719 {
720         int ret = MM_ERROR_NONE;
721         sound_stream_focus_change_reason_e change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA;
722         sound_stream_info_s *stream_info;
723
724         LOGI(">> enter");
725
726         if (!user_data) {
727                 LOGE("user_data is null");
728                 goto LEAVE;
729         }
730
731         stream_info = (sound_stream_info_s *)user_data;
732         if (stream_info->focus_id != index) {
733                 LOGE("index is not valid, (%d, %d)", stream_info->focus_id, index);
734                 goto LEAVE;
735         }
736
737         if ((ret = _convert_stream_type_to_change_reason(reason, &change_reason))) {
738                 LOGE("failed to _convert_stream_type_to_enum(), reason(%s), err(0x%08x)", reason, ret);
739                 goto LEAVE;
740         }
741
742         SM_ENTER_CRITICAL_SECTION(&stream_info->focus_cb_mutex);
743
744         if (state == FOCUS_IS_RELEASED)
745                 stream_info->acquired_focus &= ~focus_type;
746         else if (state == FOCUS_IS_ACQUIRED)
747                 stream_info->acquired_focus |= focus_type;
748
749         if (state == FOCUS_IS_ACQUIRED)
750                 _update_focus_status(stream_info->pa_index, (unsigned int)stream_info->acquired_focus);
751
752         LOGI("[FOCUS USER CALLBACK(%p) START]", stream_info->user_cb);
753         stream_info->user_cb((sound_stream_info_h)stream_info, focus_type, state, change_reason,
754                                                 option, extra_info, stream_info->user_data);
755         LOGI("[FOCUS USER CALLBACK(%p) END]", stream_info->user_cb);
756
757         if (state == FOCUS_IS_RELEASED)
758                 _update_focus_status(stream_info->pa_index, (unsigned int)stream_info->acquired_focus);
759
760         if (state == FOCUS_IS_RELEASED)
761                 stream_info->prev_acquired_focus &= ~focus_type;
762         else if (state == FOCUS_IS_ACQUIRED)
763                 stream_info->prev_acquired_focus |= focus_type;
764
765         SM_LEAVE_CRITICAL_SECTION(&stream_info->focus_cb_mutex);
766
767 LEAVE:
768         LOGI("<< leave");
769
770         return;
771 }
772
773 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)
774 {
775         int ret = MM_ERROR_NONE;
776         sound_stream_focus_change_reason_e change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA;
777         _focus_watch_info_s *watch_info;
778
779         if (!user_data) {
780                 LOGE("user_data is null");
781                 goto LEAVE;
782         }
783
784         watch_info = (_focus_watch_info_s *)user_data;
785         if (watch_info->id != index) {
786                 LOGE("index is not valid, (%d, %d)", watch_info->id, index);
787                 goto LEAVE;
788         }
789
790         if ((ret = _convert_stream_type_to_change_reason(reason, &change_reason))) {
791                 LOGE("failed to _convert_stream_type_to_enum(), reason(%s), err(0x%08x)", reason, ret);
792                 goto LEAVE;
793         }
794
795         LOGI("[FOCUS WATCH USER CALLBACK(%p, id:%d) START]", watch_info->user_cb, index);
796         watch_info->user_cb(index, focus_type, state, change_reason, extra_info, watch_info->user_data);
797         LOGI("[FOCUS WATCH USER CALLBACK(%p) END]", watch_info->user_cb);
798
799 LEAVE:
800         LOGI("<< leave");
801         return;
802 }
803 //LCOV_EXCL_STOP
804
805 void _pa_context_state_cb(pa_context *c, void *userdata)
806 {
807         pa_context_state_t state;
808         sound_stream_info_s *stream_info_h = (sound_stream_info_s*)userdata;
809
810         assert(c);
811
812         state = pa_context_get_state(c);
813         LOGI("[%p] context state = [%d]", stream_info_h, state);
814         switch (state) {
815         case PA_CONTEXT_READY:
816         case PA_CONTEXT_TERMINATED:
817         case PA_CONTEXT_FAILED:
818                 pa_threaded_mainloop_signal(stream_info_h->pa_mainloop, 0);
819                 break;
820         case PA_CONTEXT_UNCONNECTED:
821         case PA_CONTEXT_CONNECTING:
822         case PA_CONTEXT_AUTHORIZING:
823         case PA_CONTEXT_SETTING_NAME:
824                 break;
825         }
826
827         return;
828 }
829
830 void _pa_stream_state_cb(pa_stream *s, void * userdata)
831 {
832         pa_stream_state_t state;
833         virtual_sound_stream_info_s *vstream_h = (virtual_sound_stream_info_s*)userdata;
834
835         assert(s);
836
837         state = pa_stream_get_state(s);
838         LOGI("[%p] stream [%d] state = [%d]", vstream_h, pa_stream_get_index(s), state);
839
840         switch (state) {
841         case PA_STREAM_READY:
842         case PA_STREAM_FAILED:
843         case PA_STREAM_TERMINATED:
844                 pa_threaded_mainloop_signal(vstream_h->pa_mainloop, 0);
845                 break;
846         case PA_STREAM_UNCONNECTED:
847         case PA_STREAM_CREATING:
848                 break;
849         }
850
851         return;
852 }
853
854 int _get_stream_conf_info(const char *stream_type, stream_conf_info_s *info)
855 {
856         int ret = MM_ERROR_NONE;
857         GVariant *result = NULL;
858         GVariant *child = NULL;
859         GDBusConnection *conn = NULL;
860         GError *err = NULL;
861         GVariantIter iter;
862         GVariant *item = NULL;
863         gchar *name = NULL;
864         gsize size = 0;
865         int i = 0;
866
867         assert(stream_type);
868         assert(info);
869
870         if ((ret = __get_dbus_connection(&conn)))
871                 return ret;
872
873         result = g_dbus_connection_call_sync(conn,
874                                                         PA_BUS_NAME,
875                                                         PA_STREAM_MANAGER_OBJECT_PATH,
876                                                         PA_STREAM_MANAGER_INTERFACE,
877                                                         PA_STREAM_MANAGER_METHOD_NAME_GET_STREAM_INFO,
878                                                         g_variant_new("(s)", stream_type),
879                                                         G_VARIANT_TYPE("(vvvvvv)"),
880                                                         G_DBUS_CALL_FLAGS_NONE,
881                                                         2000,
882                                                         NULL,
883                                                         &err);
884         if (!result || err) {
885                 LOGE("g_dbus_connection_call_sync() for GET_STREAM_INFO error (%s)", err ? err->message : NULL);
886                 g_error_free(err);
887                 ret = MM_ERROR_SOUND_INTERNAL;
888                 goto LEAVE;
889         }
890
891         /* get priority */
892         child = g_variant_get_child_value(result, 0);
893         item = g_variant_get_variant(child);
894         info->priority = g_variant_get_int32(item);
895         g_variant_unref(item);
896         g_variant_unref(child);
897         LOGI("priority(%d)", info->priority);
898
899         /* get route type */
900         child = g_variant_get_child_value(result, 1);
901         item = g_variant_get_variant(child);
902         info->route_type = g_variant_get_int32(item);
903         g_variant_unref(item);
904         g_variant_unref(child);
905         LOGI("route_type(%d)", info->route_type);
906
907         /* get volume types */
908         child = g_variant_get_child_value(result, 2);
909         item = g_variant_get_variant(child);
910         g_variant_iter_init(&iter, item);
911         while (g_variant_iter_loop(&iter, "&s", &name)) {
912                 if (name && !strncmp(name, "none", strlen("none")))
913                         continue;
914                 /* we use volume type only for out direction */
915                 if (name) {
916                         LOGI(" volume-type : %s", name);
917                         info->volume_type = strdup(name);
918                         break;
919                 }
920         }
921         g_variant_unref(item);
922         g_variant_unref(child);
923
924         /* get availabe in-devices */
925         child = g_variant_get_child_value(result, 3);
926         item = g_variant_get_variant(child);
927         size = g_variant_n_children(item);
928         LOGI("num of avail-in-devices are %d", size);
929         g_variant_iter_init(&iter, item);
930         i = 0;
931         while (g_variant_iter_loop(&iter, "&s", &name)) {
932                 if (size == 1 && !strncmp(name, "none", strlen("none"))) {
933                         LOGI(" in-device is [%s], skip it", name);
934                         break;
935                 }
936                 LOGI(" in-device name : %s", name);
937                 info->avail_in_devices[i++] = strdup(name);
938         }
939         g_variant_unref(item);
940         g_variant_unref(child);
941
942         /* get available out-devices */
943         child = g_variant_get_child_value(result, 4);
944         item = g_variant_get_variant(child);
945         size = g_variant_n_children(item);
946         LOGI("num of avail-out-devices are %d", size);
947         g_variant_iter_init(&iter, item);
948         i = 0;
949         while (g_variant_iter_loop(&iter, "&s", &name)) {
950                 if (size == 1 && !strncmp(name, "none", strlen("none"))) {
951                         LOGI(" out-device is [%s], skip it", name);
952                         break;
953                 }
954                 LOGI(" out-device name : %s", name);
955                 info->avail_out_devices[i++] = strdup(name);
956         }
957         g_variant_unref(item);
958         g_variant_unref(child);
959
960         /* get available frameworks */
961         child = g_variant_get_child_value(result, 5);
962         item = g_variant_get_variant(child);
963         size = g_variant_n_children(item);
964         LOGI("num of avail-frameworks are %d", size);
965         g_variant_iter_init(&iter, item);
966         i = 0;
967         while (g_variant_iter_loop(&iter, "&s", &name)) {
968                 if (size == 1 && !strncmp(name, "none", strlen("none"))) {
969                         LOGI(" framework is [%s], skip it", name);
970                         break;
971                 }
972                 LOGI(" framework name : %s", name);
973                 info->avail_frameworks[i++] = strdup(name);
974         }
975         g_variant_unref(item);
976         g_variant_unref(child);
977
978         if (info->priority == -1) {
979                 LOGE("could not find the info of stream type(%s)", stream_type);
980                 ret = MM_ERROR_NOT_SUPPORT_API;
981         }
982
983 LEAVE:
984         g_variant_unref(result);
985         g_object_unref(conn);
986
987         return ret;
988 }
989
990 int _set_manual_route_info(unsigned int index, manual_route_info_s *info)
991 {
992         int ret = MM_ERROR_NONE;
993         int i = 0;
994         GVariantBuilder *builder_for_in_devices;
995         GVariantBuilder *builder_for_out_devices;
996         GVariant *result = NULL;
997         GDBusConnection *conn = NULL;
998         GError *err = NULL;
999         const gchar *dbus_ret = NULL;
1000
1001         assert(info);
1002
1003         if ((ret = __get_dbus_connection(&conn)))
1004                 return ret;
1005
1006         LOGI("stream info index(%u)", index);
1007
1008         builder_for_in_devices = g_variant_builder_new(G_VARIANT_TYPE("au"));
1009         builder_for_out_devices = g_variant_builder_new(G_VARIANT_TYPE("au"));
1010         if (!builder_for_in_devices || !builder_for_out_devices) {
1011                 LOGE("failed to g_variant_builder_new(), builder_for_in_devices(%p), builder_for_out_devices(%p)",
1012                         builder_for_in_devices, builder_for_out_devices);
1013                 ret = MM_ERROR_SOUND_INTERNAL;
1014                 goto LEAVE;
1015         }
1016         for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
1017                 if (!info->route_in_devices[i])
1018                         break;
1019                 g_variant_builder_add(builder_for_in_devices, "u", info->route_in_devices[i]);
1020                 LOGI("[IN] device_id:%u", info->route_in_devices[i]);
1021         }
1022         for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
1023                 if (!info->route_out_devices[i])
1024                         break;
1025                 g_variant_builder_add(builder_for_out_devices, "u", info->route_out_devices[i]);
1026                 LOGI("[OUT] device_id:%u", info->route_out_devices[i]);
1027         }
1028
1029         result = g_dbus_connection_call_sync(conn,
1030                                                         PA_BUS_NAME,
1031                                                         PA_STREAM_MANAGER_OBJECT_PATH,
1032                                                         PA_STREAM_MANAGER_INTERFACE,
1033                                                         PA_STREAM_MANAGER_METHOD_NAME_SET_STREAM_ROUTE_DEVICES,
1034                                                         g_variant_new("(uauau)", index, builder_for_in_devices, builder_for_out_devices),
1035                                                         G_VARIANT_TYPE("(s)"),
1036                                                         G_DBUS_CALL_FLAGS_NONE,
1037                                                         2000,
1038                                                         NULL,
1039                                                         &err);
1040         if (!result || err) {
1041                 LOGE("g_dbus_connection_call_sync() for SET_STREAM_ROUTE_DEVICES error (%s)", err ? err->message : NULL);
1042                 g_error_free(err);
1043                 ret = MM_ERROR_SOUND_INTERNAL;
1044                 goto LEAVE;
1045         }
1046
1047         g_variant_get(result, "(&s)", &dbus_ret);
1048         LOGI("g_dbus_connection_call_sync() success, method return value is (%s)", dbus_ret);
1049         if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret)))
1050                 ret = MM_ERROR_SOUND_INTERNAL;
1051         else
1052                 info->is_set = true;
1053
1054 LEAVE:
1055         g_variant_unref(result);
1056         if (builder_for_in_devices)
1057                 g_variant_builder_unref(builder_for_in_devices);
1058         if (builder_for_out_devices)
1059                 g_variant_builder_unref(builder_for_out_devices);
1060         g_object_unref(conn);
1061
1062         return ret;
1063 }
1064
1065 int _set_route_option(unsigned int index, const char *name, int value)
1066 {
1067         int ret = MM_ERROR_NONE;
1068         GVariant *result = NULL;
1069         GDBusConnection *conn = NULL;
1070         GError *err = NULL;
1071         const gchar *dbus_ret = NULL;
1072
1073         assert(name);
1074
1075         if ((ret = __get_dbus_connection(&conn)))
1076                 return ret;
1077
1078         LOGI("[OPTION] %s(%d)", name, value);
1079
1080         result = g_dbus_connection_call_sync(conn,
1081                                                         PA_BUS_NAME,
1082                                                         PA_STREAM_MANAGER_OBJECT_PATH,
1083                                                         PA_STREAM_MANAGER_INTERFACE,
1084                                                         PA_STREAM_MANAGER_METHOD_NAME_SET_STREAM_ROUTE_OPTION,
1085                                                         g_variant_new("(usi)", index, name, value),
1086                                                         G_VARIANT_TYPE("(s)"),
1087                                                         G_DBUS_CALL_FLAGS_NONE,
1088                                                         2000,
1089                                                         NULL,
1090                                                         &err);
1091         if (!result || err) {
1092                 LOGE("g_dbus_connection_call_sync() for SET_STREAM_ROUTE_OPTION error (%s)", err ? err->message : NULL);
1093                 g_error_free(err);
1094                 ret = MM_ERROR_SOUND_INTERNAL;
1095                 goto LEAVE;
1096         }
1097
1098         g_variant_get(result, "(&s)", &dbus_ret);
1099         LOGI("g_dbus_connection_call_sync() success, method return value is (%s)", dbus_ret);
1100         if (!strncmp("STREAM_MANAGER_RETURN_ERROR_NO_STREAM", dbus_ret, strlen(dbus_ret)))
1101                 ret = MM_ERROR_SOUND_INVALID_STATE;
1102         else if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret)))
1103                 ret = MM_ERROR_SOUND_INTERNAL;
1104
1105 LEAVE:
1106         g_variant_unref(result);
1107         g_object_unref(conn);
1108
1109         return ret;
1110 }
1111
1112 int _get_volume_max_level(const char *direction, const char *volume_type, unsigned int *max_level)
1113 {
1114         int ret = MM_ERROR_NONE;
1115         GVariant *result = NULL;
1116         GDBusConnection *conn = NULL;
1117         GError *err = NULL;
1118         const gchar *dbus_ret = NULL;
1119
1120         assert(direction);
1121         assert(volume_type);
1122         assert(max_level);
1123
1124         if ((ret = __get_dbus_connection(&conn)))
1125                 return ret;
1126
1127         result = g_dbus_connection_call_sync(conn,
1128                                                         PA_BUS_NAME,
1129                                                         PA_STREAM_MANAGER_OBJECT_PATH,
1130                                                         PA_STREAM_MANAGER_INTERFACE,
1131                                                         PA_STREAM_MANAGER_METHOD_NAME_GET_VOLUME_MAX_LEVEL,
1132                                                         g_variant_new("(ss)", direction, volume_type),
1133                                                         G_VARIANT_TYPE("(us)"),
1134                                                         G_DBUS_CALL_FLAGS_NONE,
1135                                                         2000,
1136                                                         NULL,
1137                                                         &err);
1138         if (!result || err) {
1139                 LOGE("g_dbus_connection_call_sync() for GET_VOLUME_MAX_LEVEL error (%s)", err ? err->message : NULL);
1140                 g_error_free(err);
1141                 ret = MM_ERROR_SOUND_INTERNAL;
1142                 goto LEAVE;
1143         }
1144
1145         g_variant_get(result, "(u&s)", max_level, &dbus_ret);
1146         LOGI("g_dbus_connection_call_sync() success, method return value is (%u, %s)", *max_level, dbus_ret);
1147         if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret)))
1148                 ret = MM_ERROR_SOUND_INTERNAL;
1149
1150 LEAVE:
1151         g_variant_unref(result);
1152         g_object_unref(conn);
1153
1154         return ret;
1155 }
1156
1157 int _get_volume_level(const char *direction, const char *volume_type, unsigned int *level)
1158 {
1159         int ret = MM_ERROR_NONE;
1160         GVariant *result = NULL;
1161         GDBusConnection *conn = NULL;
1162         GError *err = NULL;
1163         const gchar *dbus_ret = NULL;
1164
1165         assert(direction);
1166         assert(volume_type);
1167         assert(level);
1168
1169         if ((ret = __get_dbus_connection(&conn)))
1170                 return ret;
1171
1172         result = g_dbus_connection_call_sync(conn,
1173                                                         PA_BUS_NAME,
1174                                                         PA_STREAM_MANAGER_OBJECT_PATH,
1175                                                         PA_STREAM_MANAGER_INTERFACE,
1176                                                         PA_STREAM_MANAGER_METHOD_NAME_GET_VOLUME_LEVEL,
1177                                                         g_variant_new("(ss)", direction, volume_type),
1178                                                         G_VARIANT_TYPE("(us)"),
1179                                                         G_DBUS_CALL_FLAGS_NONE,
1180                                                         2000,
1181                                                         NULL,
1182                                                         &err);
1183         if (!result || err) {
1184                 LOGE("g_dbus_connection_call_sync() for GET_VOLUME_LEVEL error (%s)", err ? err->message : NULL);
1185                 g_error_free(err);
1186                 ret = MM_ERROR_SOUND_INTERNAL;
1187                 goto LEAVE;
1188         }
1189
1190         g_variant_get(result, "(u&s)", level, &dbus_ret);
1191         LOGI("g_dbus_connection_call_sync() success, method return value is (%u, %s)", *level, dbus_ret);
1192         if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret)))
1193                 ret = MM_ERROR_SOUND_INTERNAL;
1194
1195 LEAVE:
1196         g_variant_unref(result);
1197         g_object_unref(conn);
1198
1199         return ret;
1200 }
1201
1202 int _set_volume_level(const char *direction, const char *volume_type, unsigned int level)
1203 {
1204         int ret = MM_ERROR_NONE;
1205         GVariant *result = NULL;
1206         GDBusConnection *conn = NULL;
1207         GError *err = NULL;
1208         const gchar *dbus_ret = NULL;
1209         int vret = 0;
1210         char volume_path[VCONF_PATH_MAX] = {0,};
1211
1212         assert(direction);
1213         assert(volume_type);
1214
1215         if ((ret = __get_dbus_connection(&conn)))
1216                 return ret;
1217
1218         result = g_dbus_connection_call_sync(conn,
1219                                                         PA_BUS_NAME,
1220                                                         PA_STREAM_MANAGER_OBJECT_PATH,
1221                                                         PA_STREAM_MANAGER_INTERFACE,
1222                                                         PA_STREAM_MANAGER_METHOD_NAME_SET_VOLUME_LEVEL,
1223                                                         g_variant_new("(ssu)", direction, volume_type, level),
1224                                                         G_VARIANT_TYPE("(s)"),
1225                                                         G_DBUS_CALL_FLAGS_NONE,
1226                                                         2000,
1227                                                         NULL,
1228                                                         &err);
1229         if (!result || err) {
1230                 LOGE("g_dbus_connection_call_sync() for SET_VOLUME_LEVEL error (%s)", err ? err->message : NULL);
1231                 g_error_free(err);
1232                 ret = MM_ERROR_SOUND_INTERNAL;
1233                 goto LEAVE;
1234         }
1235
1236         g_variant_get(result, "(&s)", &dbus_ret);
1237         LOGI("g_dbus_connection_call_sync() success, method return value is (%s)", dbus_ret);
1238         if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret)))
1239                 ret = MM_ERROR_SOUND_INTERNAL;
1240         else {
1241                 /* Set volume value to VCONF */
1242                 snprintf(volume_path, sizeof(volume_path)-1, "%s%s", VCONF_PATH_PREFIX_VOLUME, volume_type);
1243                 if ((vret = vconf_set_int(volume_path, (int)level)))
1244                         LOGE("vconf_set_int(%s) failed..ret[%d]\n", volume_path, vret);
1245         }
1246
1247 LEAVE:
1248         g_variant_unref(result);
1249         g_object_unref(conn);
1250
1251         return ret;
1252 }
1253
1254 int _get_current_volume_type(const char *direction, char **volume_type)
1255 {
1256         int ret = MM_ERROR_NONE;
1257         GVariant *result = NULL;
1258         GDBusConnection *conn = NULL;
1259         GError *err = NULL;
1260         const gchar *dbus_volume_type = NULL;
1261         const gchar *dbus_ret = NULL;
1262
1263         assert(direction);
1264         assert(volume_type);
1265
1266         if ((ret = __get_dbus_connection(&conn)))
1267                 return ret;
1268
1269         result = g_dbus_connection_call_sync(conn,
1270                                                         PA_BUS_NAME,
1271                                                         PA_STREAM_MANAGER_OBJECT_PATH,
1272                                                         PA_STREAM_MANAGER_INTERFACE,
1273                                                         PA_STREAM_MANAGER_METHOD_NAME_GET_CURRENT_VOLUME_TYPE,
1274                                                         g_variant_new("(s)", direction),
1275                                                         G_VARIANT_TYPE("(ss)"),
1276                                                         G_DBUS_CALL_FLAGS_NONE,
1277                                                         2000,
1278                                                         NULL,
1279                                                         &err);
1280         if (!result || err) {
1281                 LOGE("g_dbus_connection_call_sync() for GET_CURRENT_VOLUME_TYPE error (%s)", err ? err->message : NULL);
1282                 g_error_free(err);
1283                 ret = MM_ERROR_SOUND_INTERNAL;
1284                 goto LEAVE;
1285         }
1286
1287         g_variant_get(result, "(&s&s)", &dbus_volume_type, &dbus_ret);
1288         LOGI("g_dbus_connection_call_sync() success, method return value is (%s, %s)", dbus_volume_type, dbus_ret);
1289         if (!strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret))) {
1290                 ret = MM_ERROR_NONE;
1291                 *volume_type = strdup(dbus_volume_type);
1292         } else if (!strncmp("STREAM_MANAGER_RETURN_ERROR_NO_STREAM", dbus_ret, strlen(dbus_ret))) {
1293                 ret = MM_ERROR_SOUND_VOLUME_NO_INSTANCE;
1294         } else {
1295                 ret = MM_ERROR_SOUND_INTERNAL;
1296         }
1297
1298 LEAVE:
1299         g_variant_unref(result);
1300         g_object_unref(conn);
1301
1302         return ret;
1303 }
1304
1305 int _get_current_media_routing_path(const char *direction, sound_device_type_e *device_type)
1306 {
1307         int ret = MM_ERROR_NONE;
1308         GVariant *result = NULL;
1309         GDBusConnection *conn = NULL;
1310         GError *err = NULL;
1311         const gchar *dbus_device_type = NULL;
1312         const gchar *dbus_ret = NULL;
1313
1314         assert(direction);
1315         assert(device_type);
1316
1317         if ((ret = __get_dbus_connection(&conn)))
1318                 return ret;
1319
1320         result = g_dbus_connection_call_sync(conn,
1321                                                         PA_BUS_NAME,
1322                                                         PA_STREAM_MANAGER_OBJECT_PATH,
1323                                                         PA_STREAM_MANAGER_INTERFACE,
1324                                                         PA_STREAM_MANAGER_METHOD_NAME_GET_CURRENT_MEDIA_ROUTING_PATH,
1325                                                         g_variant_new("(s)", direction),
1326                                                         G_VARIANT_TYPE("(ss)"),
1327                                                         G_DBUS_CALL_FLAGS_NONE,
1328                                                         2000,
1329                                                         NULL,
1330                                                         &err);
1331         if (!result || err) {
1332                 LOGE("g_dbus_connection_call_sync() for GET_CURRENT_MEDIA_ROUTING_PATH error (%s)", err ? err->message : NULL);
1333                 g_error_free(err);
1334                 ret = MM_ERROR_SOUND_INTERNAL;
1335                 goto LEAVE;
1336         }
1337
1338         g_variant_get(result, "(&s&s)", &dbus_device_type, &dbus_ret);
1339         LOGI("g_dbus_connection_call_sync() success, method return value is (%s, %s)", dbus_device_type, dbus_ret);
1340         if (!strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret))) {
1341                 ret = MM_ERROR_NONE;
1342                 if (_convert_device_type_str_to_enum(dbus_device_type, device_type) < 0)
1343                         ret = MM_ERROR_SOUND_INTERNAL;
1344         } else {
1345                 if (!strncmp("none", dbus_device_type, strlen(dbus_device_type)))
1346                         ret = MM_ERROR_SOUND_NO_DATA;
1347                 else
1348                         ret = MM_ERROR_SOUND_INTERNAL;
1349         }
1350
1351 LEAVE:
1352         g_variant_unref(result);
1353         g_object_unref(conn);
1354
1355         return ret;
1356 }
1357
1358 void _update_focus_status(unsigned int index, unsigned int acquired_focus_status)
1359 {
1360         GVariant *result = NULL;
1361         GDBusConnection *conn = NULL;
1362         GError *err = NULL;
1363         const gchar *dbus_ret = NULL;
1364
1365         if (__get_dbus_connection(&conn))
1366                 return;
1367
1368         result = g_dbus_connection_call_sync(conn,
1369                                                         PA_BUS_NAME,
1370                                                         PA_STREAM_MANAGER_OBJECT_PATH,
1371                                                         PA_STREAM_MANAGER_INTERFACE,
1372                                                         PA_STREAM_MANAGER_METHOD_NAME_UPDATE_FOCUS_STATUS,
1373                                                         g_variant_new("(uu)", index, acquired_focus_status),
1374                                                         G_VARIANT_TYPE("(s)"),
1375                                                         G_DBUS_CALL_FLAGS_NONE,
1376                                                         2000,
1377                                                         NULL,
1378                                                         &err);
1379         if (!result || err) {
1380                 LOGE("g_dbus_connection_call_sync() for UPDATE_FOCUS_STATUS error (%s)", err ? err->message : NULL);
1381                 g_error_free(err);
1382                 goto LEAVE;
1383         }
1384         g_variant_get(result, "(&s)", &dbus_ret);
1385         LOGI("g_dbus_connection_call_sync() success, method return value is (%s)", dbus_ret);
1386         if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret)))
1387                 LOGE("failed to UPDATE_FOCUS_STATUS error (%s)", dbus_ret);
1388
1389 LEAVE:
1390         g_variant_unref(result);
1391         g_object_unref(conn);
1392
1393         return;
1394 }
1395
1396 int _is_device_running_by_id(int device_id, bool *is_running)
1397 {
1398         int ret = MM_ERROR_NONE;
1399         GVariant *result = NULL;
1400         GDBusConnection *conn = NULL;
1401         GError *err = NULL;
1402         gboolean _is_running;
1403
1404         assert(is_running);
1405
1406         if ((ret = __get_dbus_connection(&conn)))
1407                 return ret;
1408
1409         result = g_dbus_connection_call_sync(conn,
1410                                                                           PA_BUS_NAME,
1411                                                                           PA_DEVICE_MANAGER_OBJECT_PATH,
1412                                                                           PA_DEVICE_MANAGER_INTERFACE,
1413                                                                           PA_DEVICE_MANAGER_METHOD_NAME_IS_DEVICE_RUNNING_BY_ID,
1414                                                                           g_variant_new("(i)", device_id),
1415                                                                           G_VARIANT_TYPE("(b)"),
1416                                                                           G_DBUS_CALL_FLAGS_NONE,
1417                                                                           2000,
1418                                                                           NULL,
1419                                                                           &err);
1420         if (err) {
1421                 LOGE("g_dbus_connection_call_sync() for IS_DEVICE_RUNNING_BY_ID error (%s)", err->message);
1422                 ret = _convert_dbus_error(err->message);
1423                 g_error_free(err);
1424                 goto LEAVE;
1425         } else {
1426                 g_variant_get(result, "(b)", &_is_running);
1427                 *is_running = (bool)_is_running;
1428                 LOGI("device(id:%d) is (%s)", device_id, *is_running ? "Running" : "Not running");
1429         }
1430
1431 LEAVE:
1432         g_variant_unref(result);
1433         g_object_unref(conn);
1434
1435         return ret;
1436 }
1437 //LCOV_EXCL_START
1438 #define SM_SAMPLE_FORMAT_NUM    4 /* check declaration of sound_sample_format_e */
1439 int _get_supported_sample_formats(int device_id, sound_sample_format_e **formats, unsigned int *num)
1440 {
1441         int ret = MM_ERROR_NONE;
1442         GVariant *result = NULL;
1443         GDBusConnection *conn = NULL;
1444         GError *err = NULL;
1445         GVariantIter *iter = NULL;
1446         gchar *format_str;
1447         unsigned int iter_num;
1448         unsigned int elem_num = 0;
1449         sound_sample_format_e format;
1450         sound_sample_format_e sm_formats[SM_SAMPLE_FORMAT_NUM] = {0, };
1451
1452         SM_NULL_ARG_CHECK_FOR_PRIV(formats);
1453         SM_NULL_ARG_CHECK_FOR_PRIV(num);
1454
1455         if ((ret = __get_dbus_connection(&conn)))
1456                 return ret;
1457
1458         result = g_dbus_connection_call_sync(conn,
1459                                                         PA_BUS_NAME,
1460                                                         PA_DEVICE_MANAGER_OBJECT_PATH,
1461                                                         PA_DEVICE_MANAGER_INTERFACE,
1462                                                         PA_DEVICE_MANAGER_METHOD_NAME_GET_SUPPORTED_SAMPLE_FORMATS,
1463                                                         g_variant_new("(i)", device_id),
1464                                                         G_VARIANT_TYPE("(as)"),
1465                                                         G_DBUS_CALL_FLAGS_NONE,
1466                                                         2000,
1467                                                         NULL,
1468                                                         &err);
1469         if (!result || err) {
1470                 LOGE("g_dbus_connection_call_sync() for GET_SUPPORTED_SAMPLE_FORMATS error (%s)", err ? err->message : NULL);
1471                 ret = _convert_dbus_error(err ? err->message : NULL);
1472                 g_error_free(err);
1473                 goto LEAVE;
1474         }
1475
1476         g_variant_get(result, "(as)", &iter);
1477         if ((iter_num = (unsigned int) g_variant_iter_n_children(iter)) == 0) {
1478                 LOGE("could not get supported sample formats");
1479                 ret = MM_ERROR_SOUND_INTERNAL;
1480                 goto LEAVE;
1481         }
1482
1483         while (g_variant_iter_loop(iter, "&s", &format_str)) {
1484                 if (_convert_sample_format_str_to_enum((const char *)format_str, &format))
1485                         continue;
1486                 LOGI("%s(enum:%u) is supported", format_str, format);
1487                 elem_num++;
1488                 sm_formats[elem_num - 1] = format;
1489         }
1490
1491         if (elem_num == 0) {
1492                 LOGE("could not find supported sample formats");
1493                 ret = MM_ERROR_SOUND_INTERNAL;
1494                 goto LEAVE;
1495         }
1496
1497         if (!(*formats = (sound_sample_format_e *) calloc(elem_num, sizeof(sound_sample_format_e)))) {
1498                 LOGE("failed to calloc(), elem_num(%d)", elem_num);
1499                 ret = MM_ERROR_SOUND_INTERNAL;
1500                 goto LEAVE;
1501         } else {
1502                 memcpy(*formats, sm_formats, elem_num * sizeof(sound_sample_format_e));
1503         }
1504
1505         *num = elem_num;
1506
1507 LEAVE:
1508         g_variant_iter_free(iter);
1509         g_variant_unref(result);
1510         g_object_unref(conn);
1511
1512         return ret;
1513 }
1514
1515 int _set_sample_format(int device_id, sound_sample_format_e format)
1516 {
1517         int ret = MM_ERROR_NONE;
1518         GDBusConnection *conn = NULL;
1519         GError *err = NULL;
1520         char *format_str = NULL;
1521
1522         if ((ret = __get_dbus_connection(&conn)))
1523                 return ret;
1524
1525         if ((ret = _convert_sample_format_enum_to_str(format, &format_str)))
1526                 return ret;
1527
1528         g_dbus_connection_call_sync(conn,
1529                                                 PA_BUS_NAME,
1530                                                 PA_DEVICE_MANAGER_OBJECT_PATH,
1531                                                 PA_DEVICE_MANAGER_INTERFACE,
1532                                                 PA_DEVICE_MANAGER_METHOD_NAME_SET_SAMPLE_FORMAT,
1533                                                 g_variant_new("(is)", device_id, format_str),
1534                                                 NULL,
1535                                                 G_DBUS_CALL_FLAGS_NONE,
1536                                                 2000,
1537                                                 NULL,
1538                                                 &err);
1539         if (err) {
1540                 LOGE("g_dbus_connection_call_sync() for SET_SAMPLE_FORMAT error (%s)", err->message);
1541                 ret = _convert_dbus_error(err->message);
1542                 g_error_free(err);
1543         }
1544
1545         g_object_unref(conn);
1546
1547         return ret;
1548 }
1549
1550 int _get_sample_format(int device_id, sound_sample_format_e *format)
1551 {
1552         int ret = MM_ERROR_NONE;
1553         GVariant *result = NULL;
1554         GDBusConnection *conn = NULL;
1555         GError *err = NULL;
1556         gchar *format_str;
1557         sound_sample_format_e format_e;
1558
1559         SM_NULL_ARG_CHECK_FOR_PRIV(format);
1560
1561         if ((ret = __get_dbus_connection(&conn)))
1562                 return ret;
1563
1564         result = g_dbus_connection_call_sync(conn,
1565                                                         PA_BUS_NAME,
1566                                                         PA_DEVICE_MANAGER_OBJECT_PATH,
1567                                                         PA_DEVICE_MANAGER_INTERFACE,
1568                                                         PA_DEVICE_MANAGER_METHOD_NAME_GET_SAMPLE_FORMAT,
1569                                                         g_variant_new("(i)", device_id),
1570                                                         G_VARIANT_TYPE("(s)"),
1571                                                         G_DBUS_CALL_FLAGS_NONE,
1572                                                         2000,
1573                                                         NULL,
1574                                                         &err);
1575         if (!result || err) {
1576                 LOGE("g_dbus_connection_call_sync() for GET_SAMPLE_FORMAT error (%s)", err ? err->message : NULL);
1577                 ret = _convert_dbus_error(err ? err->message : NULL);
1578                 g_error_free(err);
1579                 goto LEAVE;
1580         }
1581         g_variant_get(result, "(&s)", &format_str);
1582         if (_convert_sample_format_str_to_enum((const char *)format_str, &format_e))
1583                 ret = MM_ERROR_SOUND_INTERNAL;
1584         else
1585                 *format = format_e;
1586
1587         g_variant_unref(result);
1588
1589 LEAVE:
1590         g_object_unref(conn);
1591
1592         return ret;
1593 }
1594
1595 #define SM_SAMPLE_RATE_NUM    8 /* check declaration of sound_sample_rate_e */
1596 int _get_supported_sample_rates(int device_id, sound_sample_rate_e **rates, unsigned int *num)
1597 {
1598         int ret = MM_ERROR_NONE;
1599         GVariant *result = NULL;
1600         GDBusConnection *conn = NULL;
1601         GError *err = NULL;
1602         GVariantIter *iter = NULL;
1603         unsigned int rate;
1604         unsigned int iter_num;
1605         unsigned int elem_num = 0;
1606         sound_sample_rate_e rate_e;
1607         sound_sample_rate_e sm_rates[SM_SAMPLE_RATE_NUM] = {0, };
1608
1609         SM_NULL_ARG_CHECK_FOR_PRIV(rates);
1610         SM_NULL_ARG_CHECK_FOR_PRIV(num);
1611
1612         if ((ret = __get_dbus_connection(&conn)))
1613                 return ret;
1614
1615         result = g_dbus_connection_call_sync(conn,
1616                                                         PA_BUS_NAME,
1617                                                         PA_DEVICE_MANAGER_OBJECT_PATH,
1618                                                         PA_DEVICE_MANAGER_INTERFACE,
1619                                                         PA_DEVICE_MANAGER_METHOD_NAME_GET_SUPPORTED_SAMPLE_RATES,
1620                                                         g_variant_new("(i)", device_id),
1621                                                         G_VARIANT_TYPE("(au)"),
1622                                                         G_DBUS_CALL_FLAGS_NONE,
1623                                                         2000,
1624                                                         NULL,
1625                                                         &err);
1626         if (!result || err) {
1627                 LOGE("g_dbus_connection_call_sync() for GET_SUPPORTED_SAMPLE_RATES error (%s)", err ? err->message : NULL);
1628                 ret = _convert_dbus_error(err ? err->message : NULL);
1629                 g_error_free(err);
1630                 goto LEAVE;
1631         }
1632
1633         g_variant_get(result, "(au)", &iter);
1634         if ((iter_num = (unsigned int) g_variant_iter_n_children(iter)) == 0) {
1635                 LOGE("could not get supported sample rates");
1636                 ret = MM_ERROR_SOUND_INTERNAL;
1637                 goto LEAVE;
1638         }
1639
1640         while (g_variant_iter_loop(iter, "u", &rate)) {
1641                 if (_convert_sample_rate_to_enum(rate, &rate_e))
1642                         continue;
1643                 LOGI("%u(enum:%u) is supported", rate, rate_e);
1644                 elem_num++;
1645                 sm_rates[elem_num - 1] = rate_e;
1646         }
1647
1648         if (elem_num == 0) {
1649                 LOGE("could not find supported sample rates");
1650                 ret = MM_ERROR_SOUND_INTERNAL;
1651                 goto LEAVE;
1652         }
1653
1654         if (!(*rates = (sound_sample_rate_e *) calloc(elem_num, sizeof(sound_sample_rate_e)))) {
1655                 LOGE("failed to calloc(), elem_num(%d)", elem_num);
1656                 ret = MM_ERROR_SOUND_INTERNAL;
1657                 goto LEAVE;
1658         } else {
1659                 memcpy(*rates, sm_rates, elem_num * sizeof(sound_sample_rate_e));
1660         }
1661
1662         *num = elem_num;
1663
1664 LEAVE:
1665         g_variant_iter_free(iter);
1666         g_variant_unref(result);
1667         g_object_unref(conn);
1668
1669         return ret;
1670 }
1671
1672 int _set_sample_rate(int device_id, sound_sample_rate_e rate)
1673 {
1674         int ret = MM_ERROR_NONE;
1675         GDBusConnection *conn = NULL;
1676         GError *err = NULL;
1677         unsigned int _rate;
1678
1679         if ((ret = __get_dbus_connection(&conn)))
1680                 return ret;
1681
1682         if ((ret = _convert_sample_rate_enum_to_uint(rate, &_rate)))
1683                 return ret;
1684
1685         g_dbus_connection_call_sync(conn,
1686                                                 PA_BUS_NAME,
1687                                                 PA_DEVICE_MANAGER_OBJECT_PATH,
1688                                                 PA_DEVICE_MANAGER_INTERFACE,
1689                                                 PA_DEVICE_MANAGER_METHOD_NAME_SET_SAMPLE_RATE,
1690                                                 g_variant_new("(iu)", device_id, _rate),
1691                                                 NULL,
1692                                                 G_DBUS_CALL_FLAGS_NONE,
1693                                                 2000,
1694                                                 NULL,
1695                                                 &err);
1696         if (err) {
1697                 LOGE("g_dbus_connection_call_sync() for SET_SAMPLE_RATE error (%s)", err->message);
1698                 ret = _convert_dbus_error(err->message);
1699                 g_error_free(err);
1700         }
1701
1702         g_object_unref(conn);
1703
1704         return ret;
1705 }
1706
1707 int _get_sample_rate(int device_id, sound_sample_rate_e *rate)
1708 {
1709         int ret = MM_ERROR_NONE;
1710         GVariant *result = NULL;
1711         GDBusConnection *conn = NULL;
1712         GError *err = NULL;
1713         unsigned int _rate;
1714         sound_sample_rate_e rate_e;
1715
1716         SM_NULL_ARG_CHECK_FOR_PRIV(rate);
1717
1718         if ((ret = __get_dbus_connection(&conn)))
1719                 return ret;
1720
1721         result = g_dbus_connection_call_sync(conn,
1722                                                         PA_BUS_NAME,
1723                                                         PA_DEVICE_MANAGER_OBJECT_PATH,
1724                                                         PA_DEVICE_MANAGER_INTERFACE,
1725                                                         PA_DEVICE_MANAGER_METHOD_NAME_GET_SAMPLE_RATE,
1726                                                         g_variant_new("(i)", device_id),
1727                                                         G_VARIANT_TYPE("(u)"),
1728                                                         G_DBUS_CALL_FLAGS_NONE,
1729                                                         2000,
1730                                                         NULL,
1731                                                         &err);
1732         if (!result || err) {
1733                 LOGE("g_dbus_connection_call_sync() for GET_SAMPLE_RATE error (%s)", err ? err->message : NULL);
1734                 ret = _convert_dbus_error(err ? err->message : NULL);
1735                 g_error_free(err);
1736                 goto LEAVE;
1737         }
1738         g_variant_get(result, "(u)", &_rate);
1739         if (_convert_sample_rate_to_enum(_rate, &rate_e))
1740                 ret = MM_ERROR_SOUND_INTERNAL;
1741         else
1742                 *rate = rate_e;
1743
1744         g_variant_unref(result);
1745
1746 LEAVE:
1747         g_object_unref(conn);
1748
1749         return ret;
1750 }
1751
1752 int _set_avoid_resampling(int device_id, bool enable)
1753 {
1754         int ret = MM_ERROR_NONE;
1755         GDBusConnection *conn = NULL;
1756         GError *err = NULL;
1757
1758         if ((ret = __get_dbus_connection(&conn)))
1759                 return ret;
1760
1761         g_dbus_connection_call_sync(conn,
1762                                                 PA_BUS_NAME,
1763                                                 PA_DEVICE_MANAGER_OBJECT_PATH,
1764                                                 PA_DEVICE_MANAGER_INTERFACE,
1765                                                 PA_DEVICE_MANAGER_METHOD_NAME_SET_AVOID_RESAMPLING,
1766                                                 g_variant_new("(ib)", device_id, enable),
1767                                                 NULL,
1768                                                 G_DBUS_CALL_FLAGS_NONE,
1769                                                 2000,
1770                                                 NULL,
1771                                                 &err);
1772         if (err) {
1773                 LOGE("g_dbus_connection_call_sync() for SET_AVOID_RESAMPLING error (%s)", err->message);
1774                 ret = _convert_dbus_error(err->message);
1775                 g_error_free(err);
1776         }
1777
1778         g_object_unref(conn);
1779
1780         return ret;
1781 }
1782
1783 int _get_avoid_resampling(int device_id, bool *enabled)
1784 {
1785         int ret = MM_ERROR_NONE;
1786         GVariant *result = NULL;
1787         GDBusConnection *conn = NULL;
1788         GError *err = NULL;
1789         gboolean _enabled;
1790
1791         SM_NULL_ARG_CHECK_FOR_PRIV(enabled);
1792
1793         if ((ret = __get_dbus_connection(&conn)))
1794                 return ret;
1795
1796         result = g_dbus_connection_call_sync(conn,
1797                                                         PA_BUS_NAME,
1798                                                         PA_DEVICE_MANAGER_OBJECT_PATH,
1799                                                         PA_DEVICE_MANAGER_INTERFACE,
1800                                                         PA_DEVICE_MANAGER_METHOD_NAME_GET_AVOID_RESAMPLING,
1801                                                         g_variant_new("(i)", device_id),
1802                                                         G_VARIANT_TYPE("(b)"),
1803                                                         G_DBUS_CALL_FLAGS_NONE,
1804                                                         2000,
1805                                                         NULL,
1806                                                         &err);
1807         if (!result || err) {
1808                 LOGE("g_dbus_connection_call_sync() for GET_AVOID_RESAMPLING error (%s)", err ? err->message : NULL);
1809                 ret = _convert_dbus_error(err ? err->message : NULL);
1810                 g_error_free(err);
1811                 goto LEAVE;
1812         }
1813
1814         g_variant_get(result, "(b)", &_enabled);
1815         *enabled = (bool)_enabled;
1816         g_variant_unref(result);
1817
1818 LEAVE:
1819         g_object_unref(conn);
1820
1821         return ret;
1822 }
1823
1824 int _set_media_stream_only(int device_id, bool enable)
1825 {
1826         int ret = MM_ERROR_NONE;
1827         GDBusConnection *conn = NULL;
1828         GError *err = NULL;
1829         const char *stream_type;
1830
1831         if ((ret = __get_dbus_connection(&conn)))
1832                 return ret;
1833
1834         if (enable)
1835                 stream_type = "media";
1836         else
1837                 stream_type = "none";
1838
1839         g_dbus_connection_call_sync(conn,
1840                                                 PA_BUS_NAME,
1841                                                 PA_DEVICE_MANAGER_OBJECT_PATH,
1842                                                 PA_DEVICE_MANAGER_INTERFACE,
1843                                                 PA_DEVICE_MANAGER_METHOD_NAME_SET_SPECIFIC_STREAM,
1844                                                 g_variant_new("(is)", device_id, stream_type),
1845                                                 NULL,
1846                                                 G_DBUS_CALL_FLAGS_NONE,
1847                                                 2000,
1848                                                 NULL,
1849                                                 &err);
1850         if (err) {
1851                 LOGE("g_dbus_connection_call_sync() for SET_SPECIFIC_STREAM error (%s)", err->message);
1852                 ret = _convert_dbus_error(err->message);
1853                 g_error_free(err);
1854         }
1855
1856         g_object_unref(conn);
1857
1858         return ret;
1859 }
1860
1861 int _get_media_stream_only(int device_id, bool *enabled)
1862 {
1863         int ret = MM_ERROR_NONE;
1864         GVariant *result = NULL;
1865         GDBusConnection *conn = NULL;
1866         GError *err = NULL;
1867         char *stream_type;
1868
1869         SM_NULL_ARG_CHECK_FOR_PRIV(enabled);
1870
1871         if ((ret = __get_dbus_connection(&conn)))
1872                 return ret;
1873
1874         result = g_dbus_connection_call_sync(conn,
1875                                                         PA_BUS_NAME,
1876                                                         PA_DEVICE_MANAGER_OBJECT_PATH,
1877                                                         PA_DEVICE_MANAGER_INTERFACE,
1878                                                         PA_DEVICE_MANAGER_METHOD_NAME_GET_SPECIFIED_STREAM,
1879                                                         g_variant_new("(i)", device_id),
1880                                                         G_VARIANT_TYPE("(s)"),
1881                                                         G_DBUS_CALL_FLAGS_NONE,
1882                                                         2000,
1883                                                         NULL,
1884                                                         &err);
1885         if (!result || err) {
1886                 LOGE("g_dbus_connection_call_sync() for GET_SPECIFIED_STREAM error (%s)", err ? err->message : NULL);
1887                 ret = _convert_dbus_error(err ? err->message : NULL);
1888                 g_error_free(err);
1889                 goto LEAVE;
1890         }
1891
1892         g_variant_get(result, "(&s)", &stream_type);
1893         if (!strncmp(stream_type, "media", SOUND_STREAM_TYPE_LEN))
1894                 *enabled = true;
1895         else
1896                 *enabled = false;
1897
1898         g_variant_unref(result);
1899
1900 LEAVE:
1901         g_object_unref(conn);
1902
1903         return ret;
1904 }
1905 //LCOV_EXCL_STOP
1906 int _make_pa_connection_and_register_focus(sound_stream_info_s *stream_h, sound_stream_focus_state_changed_cb callback, void *user_data)
1907 {
1908         int ret = MM_ERROR_NONE;
1909         int pa_ret = PA_OK;
1910         int i = 0;
1911         bool is_focus_cb_thread = false;
1912
1913         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
1914                 return ret;
1915
1916         if (is_focus_cb_thread)
1917                 return MM_ERROR_SOUND_INVALID_OPERATION;
1918
1919         /* get configuration information of this stream type */
1920         if ((ret = _get_stream_conf_info(stream_h->stream_type, &stream_h->stream_conf_info)))
1921                 return ret;
1922
1923         LOGI("stream_conf_info : stream type[%s], priority[%d], route type[%d]",
1924                 stream_h->stream_type, stream_h->stream_conf_info.priority, stream_h->stream_conf_info.route_type);
1925
1926         if (!(stream_h->pa_mainloop = pa_threaded_mainloop_new()))
1927                 goto PA_ERROR;
1928
1929         if (!(stream_h->pa_context = pa_context_new(pa_threaded_mainloop_get_api(stream_h->pa_mainloop), "SOUND_MANAGER_STREAM_INFO")))
1930                 goto PA_ERROR;
1931
1932         pa_context_set_state_callback(stream_h->pa_context, _pa_context_state_cb, stream_h);
1933
1934         if (pa_context_connect(stream_h->pa_context, NULL, 0, NULL) < 0) {
1935                 pa_ret = pa_context_errno(stream_h->pa_context);
1936                 goto PA_ERROR;
1937         }
1938
1939         pa_threaded_mainloop_lock(stream_h->pa_mainloop);
1940
1941         if (pa_threaded_mainloop_start(stream_h->pa_mainloop) < 0)
1942                 goto PA_ERROR_WITH_UNLOCK;
1943
1944         /* wait for ready state of the context */
1945         for (;;) {
1946                 pa_context_state_t state;
1947                 state = pa_context_get_state(stream_h->pa_context);
1948                 if (state == PA_CONTEXT_READY)
1949                         break;
1950                 if (!PA_CONTEXT_IS_GOOD(state)) {
1951                         pa_ret = pa_context_errno(stream_h->pa_context);
1952                         goto PA_ERROR_WITH_UNLOCK;
1953                 }
1954                 pa_threaded_mainloop_wait(stream_h->pa_mainloop);
1955         }
1956
1957         /* get index of this context */
1958         stream_h->pa_index = pa_context_get_index(stream_h->pa_context);
1959
1960         pa_threaded_mainloop_unlock(stream_h->pa_mainloop);
1961
1962         /* register focus */
1963         if (!stream_h->is_focus_unavailable) {
1964                 ret = mm_sound_register_focus(stream_h->stream_type, _focus_state_change_callback, stream_h, &stream_h->focus_id);
1965                 if (ret == MM_ERROR_NONE) {
1966                         stream_h->user_cb = callback;
1967                         stream_h->user_data = user_data;
1968                 } else {
1969                         LOGE("failed to register focus, ret(0x%x)", ret);
1970                         /* disconnect */
1971                         goto PA_ERROR;
1972                 }
1973         }
1974         goto SUCCESS;
1975 //LCOV_EXCL_START
1976 PA_ERROR_WITH_UNLOCK:
1977         pa_threaded_mainloop_unlock(stream_h->pa_mainloop);
1978
1979 PA_ERROR:
1980         for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
1981                 SM_SAFE_FREE(stream_h->stream_conf_info.avail_in_devices[i]);
1982                 SM_SAFE_FREE(stream_h->stream_conf_info.avail_out_devices[i]);
1983         }
1984         for (i = 0; i < AVAIL_FRAMEWORKS_MAX; i++)
1985                 SM_SAFE_FREE(stream_h->stream_conf_info.avail_frameworks[i]);
1986
1987         SM_SAFE_FREE(stream_h->stream_conf_info.volume_type);
1988
1989         if (stream_h->pa_context) {
1990                 pa_context_disconnect(stream_h->pa_context);
1991                 pa_context_unref(stream_h->pa_context);
1992                 stream_h->pa_context = NULL;
1993         }
1994         if (stream_h->pa_mainloop) {
1995                 pa_threaded_mainloop_free(stream_h->pa_mainloop);
1996                 stream_h->pa_mainloop = NULL;
1997         }
1998         ret = MM_ERROR_SOUND_INTERNAL;
1999         LOGE("pa_ret(%d), ret(0x%x)", pa_ret, ret);
2000 //LCOV_EXCL_STOP
2001 SUCCESS:
2002         return ret;
2003 }
2004
2005 int _destroy_pa_connection_and_unregister_focus(sound_stream_info_s *stream_h)
2006 {
2007         int i = 0;
2008         int ret = MM_ERROR_NONE;
2009         bool is_focus_cb_thread = false;
2010
2011         ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread);
2012         if (ret)
2013                 return ret;
2014
2015         if (is_focus_cb_thread)
2016                 return MM_ERROR_SOUND_INVALID_OPERATION;
2017
2018         if (stream_h->pa_mainloop)
2019                 pa_threaded_mainloop_stop(stream_h->pa_mainloop);
2020
2021         if (stream_h->pa_context) {
2022                 pa_context_disconnect(stream_h->pa_context);
2023                 pa_context_unref(stream_h->pa_context);
2024                 stream_h->pa_context = NULL;
2025         }
2026
2027         if (stream_h->pa_mainloop) {
2028                 pa_threaded_mainloop_free(stream_h->pa_mainloop);
2029                 stream_h->pa_mainloop = NULL;
2030         }
2031
2032         /* unregister focus */
2033         if (!stream_h->is_focus_unavailable) {
2034                 ret = mm_sound_unregister_focus(stream_h->focus_id);
2035                 if (ret)
2036                         LOGE("failed to unregister focus, ret(0x%x)", ret);
2037         }
2038
2039         for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
2040                 SM_SAFE_FREE(stream_h->stream_conf_info.avail_in_devices[i]);
2041                 SM_SAFE_FREE(stream_h->stream_conf_info.avail_out_devices[i]);
2042         }
2043         for (i = 0; i < AVAIL_FRAMEWORKS_MAX; i++)
2044                 SM_SAFE_FREE(stream_h->stream_conf_info.avail_frameworks[i]);
2045
2046         SM_SAFE_FREE(stream_h->stream_conf_info.volume_type);
2047
2048         return ret;
2049 }
2050
2051 static int __check_manual_route_type(sound_stream_info_s *stream_info)
2052 {
2053         SM_INSTANCE_CHECK_FOR_PRIV(stream_info);
2054
2055         if (stream_info->stream_conf_info.route_type != STREAM_ROUTE_TYPE_MANUAL &&
2056                 stream_info->stream_conf_info.route_type != STREAM_ROUTE_TYPE_MANUAL_EXT) {
2057                 LOGE("route type is not manual or manual-ext");
2058                 return MM_ERROR_POLICY_INTERNAL;
2059         }
2060
2061         return MM_ERROR_NONE;
2062 }
2063
2064 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)
2065 {
2066         int i, j;
2067         bool added_successfully = false;
2068
2069         SM_INSTANCE_CHECK_FOR_PRIV(stream_info);
2070         SM_NULL_ARG_CHECK_FOR_PRIV(device_type_str);
2071
2072         if (device_direction == MM_SOUND_DEVICE_IO_DIRECTION_IN || device_direction == MM_SOUND_DEVICE_IO_DIRECTION_BOTH) {
2073                 for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
2074                         if (!stream_info->stream_conf_info.avail_in_devices[i])
2075                                 break;
2076                         if (strncmp(stream_info->stream_conf_info.avail_in_devices[i], device_type_str, SOUND_DEVICE_TYPE_LEN))
2077                                 continue;
2078
2079                         for (j = 0; j < AVAIL_DEVICES_MAX; j++) {
2080                                 if (!stream_info->manual_route_info.route_in_devices[j]) {
2081                                         stream_info->manual_route_info.route_in_devices[j] = (unsigned int)device_id;
2082                                         added_successfully = true;
2083                                         break;
2084                                 }
2085                                 if (stream_info->manual_route_info.route_in_devices[j] == (unsigned int)device_id) {
2086                                         LOGE("failed to add device, this IN/BOTH-device[type:%s, id:%d] has been already set", device_type_str, device_id);
2087                                         return MM_ERROR_POLICY_DUPLICATED;
2088                                 }
2089                         }
2090                 }
2091         }
2092         if (device_direction == MM_SOUND_DEVICE_IO_DIRECTION_OUT || device_direction == MM_SOUND_DEVICE_IO_DIRECTION_BOTH) {
2093                 for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
2094                         if (!stream_info->stream_conf_info.avail_out_devices[i])
2095                                 break;
2096                         if (strncmp(stream_info->stream_conf_info.avail_out_devices[i], device_type_str, SOUND_DEVICE_TYPE_LEN))
2097                                 continue;
2098
2099                         for (j = 0; j < AVAIL_DEVICES_MAX; j++) {
2100                                 if (!stream_info->manual_route_info.route_out_devices[j]) {
2101                                         stream_info->manual_route_info.route_out_devices[j] = (unsigned int)device_id;
2102                                         added_successfully = true;
2103                                         break;
2104                                 }
2105                                 if (stream_info->manual_route_info.route_out_devices[j] == (unsigned int)device_id) {
2106                                         LOGE("failed to add device, this OUT/BOTH-device[type:%s, id:%d] has been already set", device_type_str, device_id);
2107                                         return MM_ERROR_POLICY_DUPLICATED;
2108                                 }
2109                         }
2110                 }
2111         }
2112
2113         if (!added_successfully) {
2114                 LOGE("failed to add device, not supported device[type:%s, id:%d]", device_type_str, device_id);
2115                 return MM_ERROR_POLICY_INTERNAL;
2116         }
2117
2118         return MM_ERROR_NONE;
2119 }
2120
2121 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)
2122 {
2123         int i, j;
2124         bool removed_successfully = false;
2125
2126         SM_INSTANCE_CHECK_FOR_PRIV(stream_info);
2127         SM_NULL_ARG_CHECK_FOR_PRIV(device_type_str);
2128
2129         if (device_direction == MM_SOUND_DEVICE_IO_DIRECTION_IN || device_direction == MM_SOUND_DEVICE_IO_DIRECTION_BOTH) {
2130                 for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
2131                         if (!stream_info->stream_conf_info.avail_in_devices[i])
2132                                 break;
2133                         if (strncmp(stream_info->stream_conf_info.avail_in_devices[i], device_type_str, SOUND_DEVICE_TYPE_LEN))
2134                                 continue;
2135
2136                         for (j = 0; j < AVAIL_DEVICES_MAX; j++) {
2137                                 if (stream_info->manual_route_info.route_in_devices[j] == (unsigned int)device_id) {
2138                                         removed_successfully = true;
2139                                         stream_info->manual_route_info.route_in_devices[j] = 0;
2140                                         break;
2141                                 }
2142                         }
2143                 }
2144         }
2145         if (device_direction == MM_SOUND_DEVICE_IO_DIRECTION_OUT || device_direction == MM_SOUND_DEVICE_IO_DIRECTION_BOTH) {
2146                 for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
2147                         if (!stream_info->stream_conf_info.avail_out_devices[i])
2148                                 break;
2149                         if (strncmp(stream_info->stream_conf_info.avail_out_devices[i], device_type_str, SOUND_DEVICE_TYPE_LEN))
2150                                 continue;
2151
2152                         for (j = 0; j < AVAIL_DEVICES_MAX; j++) {
2153                                 if (stream_info->manual_route_info.route_out_devices[j] == (unsigned int)device_id) {
2154                                         removed_successfully = true;
2155                                         stream_info->manual_route_info.route_out_devices[j] = 0;
2156                                         break;
2157                                 }
2158                         }
2159                 }
2160         }
2161
2162         if (!removed_successfully) {
2163                 LOGE("failed to remove device, could not find this device[type:%s, id:%d]", device_type_str, device_id);
2164                 return MM_ERROR_INVALID_ARGUMENT;
2165         }
2166
2167         return MM_ERROR_NONE;
2168 }
2169
2170 int _add_device_for_stream_routing(sound_stream_info_s *stream_info, sound_device_h device)
2171 {
2172         int ret = MM_ERROR_NONE;
2173         char *device_type_str = NULL;
2174         int device_id = 0;
2175         mm_sound_device_type_e mm_sound_device_type;
2176         mm_sound_device_io_direction_e device_direction;
2177         sound_device_type_e device_type;
2178
2179         SM_INSTANCE_CHECK_FOR_PRIV(stream_info);
2180         SM_NULL_ARG_CHECK_FOR_PRIV(device);
2181
2182         if ((ret = __check_manual_route_type(stream_info)))
2183                 return ret;
2184
2185         if ((ret = mm_sound_get_device_id(device, &device_id)))
2186                 return ret;
2187         if ((ret = mm_sound_get_device_type(device, &mm_sound_device_type)))
2188                 return ret;
2189         if ((ret = _convert_device_type(mm_sound_device_type, &device_type)))
2190                 return ret;
2191         if ((ret = _convert_device_type_enum_to_str(device_type, &device_type_str)))
2192                 return ret;
2193         if ((ret = mm_sound_get_device_io_direction(device, &device_direction)))
2194                 return ret;
2195
2196         if ((ret = __add_device_to_stream_info(stream_info, device_id, device_direction, device_type_str)))
2197                 return ret;
2198
2199         LOGI("*** added device[type:%s, id:%d]", device_type_str, device_id);
2200
2201         return MM_ERROR_NONE;
2202 }
2203
2204 int _remove_device_for_stream_routing(sound_stream_info_s *stream_info, sound_device_h device)
2205 {
2206         int ret = MM_ERROR_NONE;
2207         char *device_type_str = NULL;
2208         int device_id = 0;
2209         mm_sound_device_type_e mm_sound_device_type;
2210         mm_sound_device_io_direction_e device_direction;
2211         sound_device_type_e device_type;
2212
2213         SM_INSTANCE_CHECK_FOR_PRIV(stream_info);
2214         SM_NULL_ARG_CHECK_FOR_PRIV(device);
2215
2216         if ((ret = __check_manual_route_type(stream_info)))
2217                 return ret;
2218
2219         if ((ret = mm_sound_get_device_id(device, &device_id)))
2220                 return ret;
2221         if ((ret = mm_sound_get_device_type(device, &mm_sound_device_type)))
2222                 return ret;
2223         if ((ret = _convert_device_type(mm_sound_device_type, &device_type)))
2224                 return ret;
2225         if ((ret = _convert_device_type_enum_to_str(device_type, &device_type_str)))
2226                 return ret;
2227         if ((ret = mm_sound_get_device_io_direction(device, &device_direction)))
2228                 return ret;
2229
2230         if ((ret = __remove_device_from_stream_info(stream_info, device_id, device_direction, device_type_str)))
2231                 return ret;
2232
2233         LOGI("*** removed device[type:%s, id:%d]", device_type_str, device_id);
2234
2235         return MM_ERROR_NONE;
2236 }
2237
2238 int _remove_all_devices_for_stream_routing(sound_stream_info_s *stream_info)
2239 {
2240         int ret = MM_ERROR_NONE;
2241         int i;
2242
2243         SM_INSTANCE_CHECK_FOR_PRIV(stream_info);
2244
2245         if ((ret = __check_manual_route_type(stream_info)))
2246                 return ret;
2247
2248         for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
2249                 stream_info->manual_route_info.route_in_devices[i] = 0;
2250                 stream_info->manual_route_info.route_out_devices[i] = 0;
2251         }
2252
2253         stream_info->manual_route_info.is_set = false;
2254
2255         LOGI("*** removed all devices");
2256
2257         return MM_ERROR_NONE;
2258 }
2259
2260 int _add_device_id_for_stream_routing(sound_stream_info_s *stream_info, int device_id)
2261 {
2262         int ret = MM_ERROR_NONE;
2263         char *device_type_str = NULL;
2264         mm_sound_device_type_e mm_sound_device_type;
2265         mm_sound_device_io_direction_e device_direction;
2266         sound_device_type_e device_type;
2267         MMSoundDevice_t device = NULL;
2268
2269         SM_INSTANCE_CHECK_FOR_PRIV(stream_info);
2270
2271         if ((ret = __check_manual_route_type(stream_info)))
2272                 return ret;
2273
2274         if ((ret = mm_sound_get_device_by_id(device_id, &device)))
2275                 return ret;
2276         if ((ret = mm_sound_get_device_type(device, &mm_sound_device_type)))
2277                 goto LEAVE;
2278         if ((ret = _convert_device_type(mm_sound_device_type, &device_type)))
2279                 goto LEAVE;
2280         if ((ret = _convert_device_type_enum_to_str(device_type, &device_type_str)))
2281                 goto LEAVE;
2282         if ((ret = mm_sound_get_device_io_direction(device, &device_direction)))
2283                 goto LEAVE;
2284
2285         if ((ret = __add_device_to_stream_info(stream_info, device_id, device_direction, device_type_str)))
2286                 goto LEAVE;
2287
2288         LOGI("*** added device by id[type:%s, id:%d]", device_type_str, device_id);
2289
2290 LEAVE:
2291         if (device)
2292                 mm_sound_free_device(device);
2293         return ret;
2294 }
2295
2296 int _remove_device_id_for_stream_routing(sound_stream_info_s *stream_info, int device_id)
2297 {
2298         int ret = MM_ERROR_NONE;
2299         char *device_type_str = NULL;
2300         mm_sound_device_type_e mm_sound_device_type;
2301         mm_sound_device_io_direction_e device_direction;
2302         sound_device_type_e device_type;
2303         MMSoundDevice_t device = NULL;
2304
2305         SM_INSTANCE_CHECK_FOR_PRIV(stream_info);
2306
2307         if ((ret = __check_manual_route_type(stream_info)))
2308                 return ret;
2309
2310         if ((ret = mm_sound_get_device_by_id(device_id, &device)))
2311                 return ret;
2312         if ((ret = mm_sound_get_device_type(device, &mm_sound_device_type)))
2313                 goto LEAVE;
2314         if ((ret = _convert_device_type(mm_sound_device_type, &device_type)))
2315                 goto LEAVE;
2316         if ((ret = _convert_device_type_enum_to_str(device_type, &device_type_str)))
2317                 goto LEAVE;
2318         if ((ret = mm_sound_get_device_io_direction(device, &device_direction)))
2319                 goto LEAVE;
2320
2321         if ((ret = __remove_device_from_stream_info(stream_info, device_id, device_direction, device_type_str)))
2322                 goto LEAVE;
2323
2324         LOGI("*** removed device by id[type:%s, id:%d]", device_type_str, device_id);
2325
2326 LEAVE:
2327         if (device)
2328                 mm_sound_free_device(device);
2329         return ret;
2330 }
2331
2332 int _apply_stream_routing(sound_stream_info_s *stream_info)
2333 {
2334         int i = 0;
2335
2336         SM_INSTANCE_CHECK_FOR_PRIV(stream_info);
2337
2338         if (stream_info->stream_conf_info.route_type != STREAM_ROUTE_TYPE_MANUAL &&
2339                 stream_info->stream_conf_info.route_type != STREAM_ROUTE_TYPE_MANUAL_EXT) {
2340                 LOGE("route type is not manual or manual-ext");
2341                 /* Differ from others, it uses SOUND_INTERNAL error.
2342                  * ACR process is required prior to changing error value. */
2343                 return MM_ERROR_SOUND_INTERNAL;
2344         }
2345
2346         for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
2347                 if (stream_info->manual_route_info.route_in_devices[i] ||
2348                     stream_info->manual_route_info.route_out_devices[i])
2349                         return _set_manual_route_info(stream_info->pa_index, &stream_info->manual_route_info);
2350         }
2351
2352         return MM_ERROR_SOUND_INVALID_STATE;
2353 }
2354
2355 int _create_virtual_stream(sound_stream_info_s *stream_info, virtual_sound_stream_info_s **virtual_stream)
2356 {
2357         int ret = MM_ERROR_NONE;
2358         bool result = false;
2359         const char *name = NULL;
2360         int i = 0;
2361
2362         SM_INSTANCE_CHECK_FOR_PRIV(virtual_stream);
2363         SM_INSTANCE_CHECK_FOR_PRIV(stream_info);
2364
2365         /* check if this stream_info is available for virtual stream */
2366         name = _convert_api_name(NATIVE_API_SOUND_MANAGER);
2367         for (i = 0; i < AVAIL_FRAMEWORKS_MAX; i++) {
2368                 if (stream_info->stream_conf_info.avail_frameworks[i] && !strncmp(stream_info->stream_conf_info.avail_frameworks[i], name, strlen(name))) {
2369                         result = true;
2370                         break;
2371                 }
2372         }
2373         LOGI("stream_type[%s], native api[%s], is_available[%d]", stream_info->stream_type, name, result);
2374         if (result == false) {
2375                 ret = MM_ERROR_NOT_SUPPORT_API;
2376                 goto LEAVE;
2377         }
2378
2379         (*virtual_stream) = malloc(sizeof(virtual_sound_stream_info_s));
2380         if (!(*virtual_stream)) {
2381                 ret = MM_ERROR_OUT_OF_MEMORY;
2382                 goto LEAVE;
2383         }
2384
2385         memset((*virtual_stream), 0, sizeof(virtual_sound_stream_info_s));
2386         (*virtual_stream)->stream_type = stream_info->stream_type;
2387         (*virtual_stream)->pa_mainloop = stream_info->pa_mainloop;
2388         (*virtual_stream)->pa_context = stream_info->pa_context;
2389         (*virtual_stream)->pa_proplist = pa_proplist_new();
2390         pa_proplist_sets((*virtual_stream)->pa_proplist, PA_PROP_MEDIA_ROLE, (*virtual_stream)->stream_type);
2391         pa_proplist_setf((*virtual_stream)->pa_proplist, PA_PROP_MEDIA_PARENT_ID, "%u", stream_info->pa_index);
2392         (*virtual_stream)->state = _VSTREAM_STATE_READY;
2393         (*virtual_stream)->stream_info = stream_info;
2394
2395 LEAVE:
2396         return ret;
2397 }
2398
2399 int _destroy_virtual_stream(virtual_sound_stream_info_s *virtual_stream)
2400 {
2401         int ret = MM_ERROR_NONE;
2402
2403         SM_INSTANCE_CHECK_FOR_PRIV(virtual_stream);
2404         SM_STATE_CHECK_FOR_PRIV(virtual_stream, _VSTREAM_STATE_READY);
2405
2406         virtual_stream->pa_mainloop = NULL;
2407         virtual_stream->pa_context = NULL;
2408         if (virtual_stream->pa_proplist)
2409                 pa_proplist_free(virtual_stream->pa_proplist);
2410
2411         SM_SAFE_FREE(virtual_stream);
2412
2413         return ret;
2414 }
2415
2416 int _start_virtual_stream(virtual_sound_stream_info_s *virtual_stream)
2417 {
2418         int ret = MM_ERROR_NONE;
2419         int pa_ret = PA_OK;
2420         int i = 0;
2421         int io_direction = 0;
2422         pa_sample_spec ss;
2423         pa_channel_map maps;
2424
2425         SM_INSTANCE_CHECK_FOR_PRIV(virtual_stream);
2426         SM_STATE_CHECK_FOR_PRIV(virtual_stream, _VSTREAM_STATE_READY);
2427
2428         if (virtual_stream->stream_info->stream_conf_info.route_type == STREAM_ROUTE_TYPE_MANUAL ||
2429                         virtual_stream->stream_info->stream_conf_info.route_type == STREAM_ROUTE_TYPE_MANUAL_EXT) {
2430                 /* check if the manual route info. is set when it comes to the manual route type */
2431                 if (virtual_stream->stream_info->manual_route_info.is_set == false) {
2432                         ret = MM_ERROR_SOUND_INVALID_STATE;
2433                         goto ERROR;
2434                 }
2435         }
2436
2437         /* fill up with default value */
2438         ss.channels = 2;
2439         ss.rate = 44100;
2440         ss.format = PA_SAMPLE_S16LE;
2441         pa_channel_map_init_auto(&maps, ss.channels, PA_CHANNEL_MAP_ALSA);
2442
2443         /* check direction of this stream */
2444         if (virtual_stream->stream_info->stream_conf_info.avail_in_devices[0] != NULL)
2445                 io_direction |= SOUND_STREAM_DIRECTION_INPUT;
2446         if (virtual_stream->stream_info->stream_conf_info.avail_out_devices[0] != NULL)
2447                 io_direction |= SOUND_STREAM_DIRECTION_OUTPUT;
2448
2449         /* LOCK the pa_threaded_mainloop */
2450         pa_threaded_mainloop_lock(virtual_stream->pa_mainloop);
2451
2452         for (i = 0; i < SOUND_STREAM_DIRECTION_MAX; i++) {
2453                 if (io_direction & (i + 1)) {
2454                         virtual_stream->pa_stream[i] = pa_stream_new_with_proplist(virtual_stream->pa_context, "VIRTUAL_STREAM", &ss, &maps, virtual_stream->pa_proplist);
2455                         if (virtual_stream->pa_stream[i] == NULL) {
2456                                 LOGE("failed to pa_stream_new_with_proplist()");
2457                                 pa_ret = pa_context_errno(virtual_stream->pa_context);
2458                                 ret = MM_ERROR_SOUND_INTERNAL;
2459                                 goto ERROR_WITH_UNLOCK;
2460                         }
2461                         pa_stream_set_state_callback(virtual_stream->pa_stream[i], _pa_stream_state_cb, virtual_stream);
2462
2463                         if ((i + 1) == SOUND_STREAM_DIRECTION_OUTPUT) {
2464                                 pa_ret = pa_stream_connect_playback(virtual_stream->pa_stream[i], NULL, NULL, 0, NULL, NULL);
2465                                 if (pa_ret < 0) {
2466                                         LOGE("failed to pa_stream_connect_playback()");
2467                                         pa_ret = pa_context_errno(virtual_stream->pa_context);
2468                                         ret = MM_ERROR_SOUND_INTERNAL;
2469                                         goto ERROR_WITH_UNLOCK;
2470                                 }
2471                         } else if ((i + 1) == SOUND_STREAM_DIRECTION_INPUT) {
2472                                 pa_ret = pa_stream_connect_record(virtual_stream->pa_stream[i], NULL, NULL, 0);
2473                                 if (pa_ret < 0) {
2474                                         LOGE("failed to pa_stream_connect_record()");
2475                                         pa_ret = pa_context_errno(virtual_stream->pa_context);
2476                                         ret = MM_ERROR_SOUND_INTERNAL;
2477                                         goto ERROR_WITH_UNLOCK;
2478                                 }
2479                         }
2480
2481                         /* wait for ready state of the stream */
2482                         for (;;) {
2483                                 pa_stream_state_t state;
2484                                 state = pa_stream_get_state(virtual_stream->pa_stream[i]);
2485                                 if (state == PA_STREAM_READY)
2486                                         break;
2487                                 if (!PA_STREAM_IS_GOOD(state)) {
2488                                         LOGE("stream(%d) is not good, state : %d", i, state);
2489                                         pa_ret = pa_context_errno(virtual_stream->pa_context);
2490                                         ret = MM_ERROR_SOUND_INTERNAL;
2491                                         goto ERROR_WITH_UNLOCK;
2492                                 }
2493
2494                                 pa_threaded_mainloop_wait(virtual_stream->pa_mainloop);
2495                         }
2496                 }
2497         }
2498         virtual_stream->state = _VSTREAM_STATE_RUNNING;
2499
2500         /* UNLOCK the pa_threaded_mainloop */
2501         pa_threaded_mainloop_unlock(virtual_stream->pa_mainloop);
2502
2503         return ret;
2504 //LCOV_EXCL_START
2505 ERROR_WITH_UNLOCK:
2506         /* UNLOCK the pa_threaded_mainloop */
2507         pa_threaded_mainloop_unlock(virtual_stream->pa_mainloop);
2508
2509         for (i = 0; i < SOUND_STREAM_DIRECTION_MAX; i++) {
2510                 if (virtual_stream->pa_stream[i]) {
2511                         pa_stream_unref(virtual_stream->pa_stream[i]);
2512                         virtual_stream->pa_stream[i] = NULL;
2513                 }
2514         }
2515         LOGE("pa_ret(%d)", pa_ret);
2516 //LCOV_EXCL_STOP
2517 ERROR:
2518         return ret;
2519 }
2520
2521 int _stop_virtual_stream(virtual_sound_stream_info_s *virtual_stream)
2522 {
2523         int ret = MM_ERROR_NONE;
2524         int i = 0;
2525
2526         SM_INSTANCE_CHECK_FOR_PRIV(virtual_stream);
2527         SM_STATE_CHECK_FOR_PRIV(virtual_stream, _VSTREAM_STATE_RUNNING);
2528
2529         /* LOCK the pa_threaded_mainloop */
2530         pa_threaded_mainloop_lock(virtual_stream->pa_mainloop);
2531
2532         for (i = 0; i < SOUND_STREAM_DIRECTION_MAX; i++) {
2533                 if (virtual_stream->pa_stream[i]) {
2534                         pa_stream_disconnect(virtual_stream->pa_stream[i]);
2535
2536                         /* wait for terminated state of the stream */
2537                         for (;;) {
2538                                 pa_stream_state_t state;
2539                                 state = pa_stream_get_state(virtual_stream->pa_stream[i]);
2540                                 if (state == PA_STREAM_TERMINATED)
2541                                         break;
2542                                 pa_threaded_mainloop_wait(virtual_stream->pa_mainloop);
2543                         }
2544
2545                         pa_stream_unref(virtual_stream->pa_stream[i]);
2546                         virtual_stream->pa_stream[i] = NULL;
2547                 }
2548         }
2549
2550         /* UNLOCK the pa_threaded_mainloop */
2551         pa_threaded_mainloop_unlock(virtual_stream->pa_mainloop);
2552
2553         virtual_stream->state = _VSTREAM_STATE_READY;
2554
2555         return ret;
2556 }