2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <sound_manager.h>
18 #include <sound_manager_private.h>
22 #define PA_BUS_NAME "org.pulseaudio.Server"
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"
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"
51 #define VCONF_PATH_PREFIX_VOLUME "file/private/sound/volume/"
52 #define VCONF_PATH_MAX 64
54 #define DBUS_ERR_MSG_MAX 24
56 int _convert_dbus_error(const char *error_msg)
58 int ret = MM_ERROR_NONE;
63 return MM_ERROR_SOUND_INTERNAL;
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;
71 ret_str = ret_str + 1;
72 if (ret_str[0] == '\0')
73 return MM_ERROR_SOUND_INTERNAL;
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;
82 ret = MM_ERROR_SOUND_INTERNAL;
84 LOGE("%s => 0x%x", ret_str, ret);
89 int _convert_sound_manager_error_code(const char *func, int code)
91 int ret = SOUND_MANAGER_ERROR_NONE;
92 char *errorstr = NULL;
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";
102 ret = SOUND_MANAGER_ERROR_NONE;
103 errorstr = "ERROR_NONE";
105 case MM_ERROR_INVALID_ARGUMENT:
106 case MM_ERROR_SOUND_INVALID_POINTER:
107 ret = SOUND_MANAGER_ERROR_INVALID_PARAMETER;
108 errorstr = "INVALID_PARAMETER";
110 case MM_ERROR_SOUND_PERMISSION_DENIED:
112 ret = SOUND_MANAGER_ERROR_PERMISSION_DENIED;
113 errorstr = "PERMISSION_DENIED";
116 case MM_ERROR_SOUND_NO_DATA:
117 ret = SOUND_MANAGER_ERROR_NO_DATA;
118 errorstr = "NO_DATA";
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";
126 case MM_ERROR_POLICY_DUPLICATED:
127 case MM_ERROR_POLICY_INTERNAL:
128 case MM_ERROR_POLICY_BLOCKED:
129 ret = SOUND_MANAGER_ERROR_POLICY;
132 case MM_ERROR_SOUND_VOLUME_NO_INSTANCE:
133 ret = SOUND_MANAGER_ERROR_NO_PLAYING_SOUND;
134 errorstr = "NO_PLAYING_SOUND";
136 case MM_ERROR_NOT_SUPPORT_API:
137 ret = SOUND_MANAGER_ERROR_NOT_SUPPORTED;
138 errorstr = "NOT_SUPPORTED";
140 case MM_ERROR_SOUND_INVALID_STATE:
141 ret = SOUND_MANAGER_ERROR_INVALID_STATE;
142 errorstr = "INVALID_STATE";
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";
153 LOGE("[%s] >> leave : %s(0x%08x), mm_error(0x%08x)", func, errorstr, ret, code);
155 LOGD("[%s] >> leave : %s(0x%08x)", func, errorstr, ret);
160 int _convert_stream_type(sound_stream_type_e stream_type_enum, char **stream_type)
162 int ret = MM_ERROR_NONE;
164 if (stream_type == NULL)
165 return MM_ERROR_INVALID_ARGUMENT;
167 switch (stream_type_enum) {
168 case SOUND_STREAM_TYPE_MEDIA:
169 *stream_type = "media";
171 case SOUND_STREAM_TYPE_SYSTEM:
172 *stream_type = "system";
174 case SOUND_STREAM_TYPE_ALARM:
175 *stream_type = "alarm";
177 case SOUND_STREAM_TYPE_NOTIFICATION:
178 *stream_type = "notification";
180 case SOUND_STREAM_TYPE_EMERGENCY:
181 *stream_type = "emergency";
183 case SOUND_STREAM_TYPE_VOICE_INFORMATION:
184 *stream_type = "voice-information";
186 case SOUND_STREAM_TYPE_VOICE_RECOGNITION:
187 *stream_type = "voice-recognition";
189 case SOUND_STREAM_TYPE_RINGTONE_VOIP:
190 *stream_type = "ringtone-voip";
192 case SOUND_STREAM_TYPE_VOIP:
193 *stream_type = "voip";
195 case SOUND_STREAM_TYPE_MEDIA_EXTERNAL_ONLY:
196 *stream_type = "ext-media";
199 LOGE("could not find the stream_type[%d] in this switch case statement", stream_type_enum);
200 ret = MM_ERROR_SOUND_INTERNAL;
203 LOGI("stream_type[%s]", *stream_type);
208 int _convert_stream_type_for_internal(sound_stream_type_internal_e stream_type_enum, char **stream_type)
210 int ret = MM_ERROR_NONE;
212 if (stream_type == NULL)
213 return MM_ERROR_INVALID_ARGUMENT;
215 switch (stream_type_enum) {
216 case SOUND_STREAM_TYPE_RINGTONE_CALL:
217 *stream_type = "ringtone-call";
219 case SOUND_STREAM_TYPE_RINGBACKTONE_CALL:
220 *stream_type = "ringbacktone-call";
222 case SOUND_STREAM_TYPE_VOICE_CALL:
223 *stream_type = "call-voice";
225 case SOUND_STREAM_TYPE_VIDEO_CALL:
226 *stream_type = "call-video";
228 case SOUND_STREAM_TYPE_RADIO:
229 *stream_type = "radio";
231 case SOUND_STREAM_TYPE_LOOPBACK:
232 *stream_type = "loopback";
234 case SOUND_STREAM_TYPE_LOOPBACK_MIRRORING:
235 *stream_type = "loopback-mirroring";
237 case SOUND_STREAM_TYPE_SOLO:
238 *stream_type = "solo";
240 case SOUND_STREAM_TYPE_VOICE_RECOGNITION_SERVICE:
241 *stream_type = "voice-recognition-service";
243 case SOUND_STREAM_TYPE_MEDIA_COMPRESSED:
244 *stream_type = "compressed-media";
247 LOGE("could not find the stream_type[%d] in this switch case statement", stream_type_enum);
248 ret = MM_ERROR_SOUND_INTERNAL;
251 LOGI("stream_type_for_internal[%s]", *stream_type);
256 void _set_focus_availability(sound_stream_info_s *stream_info)
258 if (stream_info == NULL || stream_info->stream_type == NULL) {
260 LOGE("invalid argument");
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);
274 int _convert_stream_type_to_change_reason(const char *stream_type, sound_stream_focus_change_reason_e *change_reason)
276 SM_NULL_ARG_CHECK_FOR_PRIV(stream_type);
277 SM_NULL_ARG_CHECK_FOR_PRIV(change_reason);
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;
285 } else if (!strncmp(stream_type, "system", SOUND_STREAM_TYPE_LEN)) {
286 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_SYSTEM;
288 } else if (!strncmp(stream_type, "alarm", SOUND_STREAM_TYPE_LEN)) {
289 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_ALARM;
291 } else if (!strncmp(stream_type, "notification", SOUND_STREAM_TYPE_LEN)) {
292 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_NOTIFICATION;
294 } else if (!strncmp(stream_type, "emergency", SOUND_STREAM_TYPE_LEN)) {
295 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_EMERGENCY;
297 } else if (!strncmp(stream_type, "voice-information", SOUND_STREAM_TYPE_LEN)) {
298 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_INFORMATION;
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;
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;
309 } else if (!strncmp(stream_type, "voip", SOUND_STREAM_TYPE_LEN)) {
310 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_VOIP;
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;
316 } else if (!strncmp(stream_type, "ext-media", SOUND_STREAM_TYPE_LEN)) {
317 *change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA_EXTERNAL_ONLY;
321 LOGE("not supported stream_type(%s)", stream_type);
322 return MM_ERROR_INVALID_ARGUMENT;
326 return MM_ERROR_NONE;
329 static int __get_dbus_connection(GDBusConnection **conn)
333 *conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
334 if (!(*conn) || err) {
337 LOGE("g_bus_get_sync() error (%s)", err->message);
339 LOGE("g_bus_get_sync() error");
341 return MM_ERROR_SOUND_INTERNAL;
345 return MM_ERROR_NONE;
348 int _convert_sound_type(sound_type_e sound_type, const char **volume_type)
350 SM_NULL_ARG_CHECK_FOR_PRIV(volume_type);
352 switch (sound_type) {
353 case SOUND_TYPE_SYSTEM:
354 *volume_type = "system";
356 case SOUND_TYPE_NOTIFICATION:
357 *volume_type = "notification";
359 case SOUND_TYPE_ALARM:
360 *volume_type = "alarm";
362 case SOUND_TYPE_RINGTONE:
363 *volume_type = "ringtone";
365 case SOUND_TYPE_MEDIA:
366 *volume_type = "media";
368 case SOUND_TYPE_CALL:
369 *volume_type = "call";
371 case SOUND_TYPE_VOIP:
372 *volume_type = "voip";
374 case SOUND_TYPE_VOICE:
375 *volume_type = "voice";
378 LOGI("volume_type[%s]", *volume_type);
380 return MM_ERROR_NONE;
383 int _convert_sound_type_to_enum(const char *sound_type, sound_type_e *sound_type_enum)
385 SM_NULL_ARG_CHECK_FOR_PRIV(sound_type);
386 SM_NULL_ARG_CHECK_FOR_PRIV(sound_type_enum);
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;
406 LOGE("not supported sound_type(%s)", sound_type);
407 return MM_ERROR_INVALID_ARGUMENT;
411 return MM_ERROR_NONE;
414 int _convert_device_type_enum_to_str(sound_device_type_e device_type, char **device_type_str)
416 SM_NULL_ARG_CHECK_FOR_PRIV(device_type_str);
418 switch (device_type) {
419 case SOUND_DEVICE_BUILTIN_SPEAKER:
420 *device_type_str = "builtin-speaker";
422 case SOUND_DEVICE_BUILTIN_RECEIVER:
423 *device_type_str = "builtin-receiver";
425 case SOUND_DEVICE_BUILTIN_MIC:
426 *device_type_str = "builtin-mic";
429 case SOUND_DEVICE_AUDIO_JACK:
430 *device_type_str = "audio-jack";
432 case SOUND_DEVICE_BLUETOOTH_MEDIA:
433 *device_type_str = "bt-a2dp";
435 case SOUND_DEVICE_BLUETOOTH_VOICE:
436 *device_type_str = "bt-sco";
438 case SOUND_DEVICE_HDMI:
439 *device_type_str = "hdmi";
441 case SOUND_DEVICE_USB_AUDIO:
442 *device_type_str = "usb-audio";
444 case SOUND_DEVICE_FORWARDING:
445 *device_type_str = "forwarding";
448 LOGE("could not find the device_type[%d] in this switch case statement", device_type);
449 return MM_ERROR_SOUND_INTERNAL;
453 LOGI("device_type[%s]", *device_type_str);
455 return MM_ERROR_NONE;
458 int _convert_device_type_str_to_enum(const char *device_type_str, sound_device_type_e *device_type)
460 SM_NULL_ARG_CHECK_FOR_PRIV(device_type_str);
461 SM_NULL_ARG_CHECK_FOR_PRIV(device_type);
463 if (!strncmp(device_type_str, "builtin-speaker", SOUND_DEVICE_TYPE_LEN)) {
464 *device_type = SOUND_DEVICE_BUILTIN_SPEAKER;
466 } else if (!strncmp(device_type_str, "builtin-receiver", SOUND_DEVICE_TYPE_LEN)) {
467 *device_type = SOUND_DEVICE_BUILTIN_RECEIVER;
469 } else if (!strncmp(device_type_str, "builtin-mic", SOUND_DEVICE_TYPE_LEN)) {
470 *device_type = SOUND_DEVICE_BUILTIN_MIC;
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;
477 } else if (!strncmp(device_type_str, "usb-audio", SOUND_DEVICE_TYPE_LEN)) {
478 *device_type = SOUND_DEVICE_USB_AUDIO;
480 } else if (!strncmp(device_type_str, "bt-a2dp", SOUND_DEVICE_TYPE_LEN)) {
481 *device_type = SOUND_DEVICE_BLUETOOTH_MEDIA;
483 } else if (!strncmp(device_type_str, "bt-sco", SOUND_DEVICE_TYPE_LEN)) {
484 *device_type = SOUND_DEVICE_BLUETOOTH_VOICE;
487 LOGE("not supported device_type(%s)", device_type_str);
488 return MM_ERROR_INVALID_ARGUMENT;
492 return MM_ERROR_NONE;
495 int _convert_device_type(mm_sound_device_type_e device_type, sound_device_type_e *sound_device_type)
497 switch (device_type) {
498 case MM_SOUND_DEVICE_TYPE_BUILTIN_SPEAKER:
499 *sound_device_type = SOUND_DEVICE_BUILTIN_SPEAKER;
501 case MM_SOUND_DEVICE_TYPE_BUILTIN_RECEIVER:
502 *sound_device_type = SOUND_DEVICE_BUILTIN_RECEIVER;
504 case MM_SOUND_DEVICE_TYPE_BUILTIN_MIC:
505 *sound_device_type = SOUND_DEVICE_BUILTIN_MIC;
508 case MM_SOUND_DEVICE_TYPE_AUDIOJACK:
509 *sound_device_type = SOUND_DEVICE_AUDIO_JACK;
511 case MM_SOUND_DEVICE_TYPE_BLUETOOTH_A2DP:
512 *sound_device_type = SOUND_DEVICE_BLUETOOTH_MEDIA;
514 case MM_SOUND_DEVICE_TYPE_BLUETOOTH_SCO:
515 *sound_device_type = SOUND_DEVICE_BLUETOOTH_VOICE;
517 case MM_SOUND_DEVICE_TYPE_HDMI:
518 *sound_device_type = SOUND_DEVICE_HDMI;
520 case MM_SOUND_DEVICE_TYPE_USB_AUDIO:
521 *sound_device_type = SOUND_DEVICE_USB_AUDIO;
523 case MM_SOUND_DEVICE_TYPE_MIRRORING:
524 *sound_device_type = SOUND_DEVICE_FORWARDING;
527 LOGE("not supported device_type(%d)", device_type);
528 return MM_ERROR_INVALID_ARGUMENT;
532 return MM_ERROR_NONE;
535 int _convert_device_io_direction(mm_sound_device_io_direction_e io_direction, sound_device_io_direction_e *sound_io_direction)
537 SM_NULL_ARG_CHECK(sound_io_direction);
539 switch (io_direction) {
540 case MM_SOUND_DEVICE_IO_DIRECTION_IN:
541 *sound_io_direction = SOUND_DEVICE_IO_DIRECTION_IN;
543 case MM_SOUND_DEVICE_IO_DIRECTION_OUT:
544 *sound_io_direction = SOUND_DEVICE_IO_DIRECTION_OUT;
546 case MM_SOUND_DEVICE_IO_DIRECTION_BOTH:
547 *sound_io_direction = SOUND_DEVICE_IO_DIRECTION_BOTH;
551 return MM_ERROR_NONE;
554 const char* _convert_api_name(native_api_e api_name)
556 const char* name = NULL;
559 case NATIVE_API_SOUND_MANAGER:
560 name = "sound-manager";
562 case NATIVE_API_PLAYER:
565 case NATIVE_API_WAV_PLAYER:
568 case NATIVE_API_TONE_PLAYER:
569 name = "tone-player";
571 case NATIVE_API_AUDIO_IO:
574 case NATIVE_API_RECORDER:
582 int _convert_sample_format_enum_to_str(sound_sample_format_e format, char **format_str)
584 SM_NULL_ARG_CHECK_FOR_PRIV(format_str);
587 case SOUND_SAMPLE_FORMAT_U8:
590 case SOUND_SAMPLE_FORMAT_S16_LE:
591 *format_str = "s16le";
593 case SOUND_SAMPLE_FORMAT_S24_LE:
594 *format_str = "s24le";
596 case SOUND_SAMPLE_FORMAT_S24_32_LE:
597 *format_str = "s24-32le";
600 LOGE("could not find format[%d] in this switch case statement", format);
601 return MM_ERROR_SOUND_INTERNAL;
604 return MM_ERROR_NONE;
607 int _convert_sample_format_str_to_enum(const char *format_str, sound_sample_format_e *format)
609 SM_NULL_ARG_CHECK_FOR_PRIV(format_str);
610 SM_NULL_ARG_CHECK_FOR_PRIV(format);
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;
621 LOGE("not supported sample format(%s)", format_str);
622 return MM_ERROR_INVALID_ARGUMENT;
625 return MM_ERROR_NONE;
628 int _convert_sample_rate_enum_to_uint(sound_sample_rate_e rate, unsigned int *sample_rate)
630 SM_NULL_ARG_CHECK_FOR_PRIV(sample_rate);
633 case SOUND_SAMPLE_RATE_8000:
636 case SOUND_SAMPLE_RATE_16000:
637 *sample_rate = 16000;
639 case SOUND_SAMPLE_RATE_22050:
640 *sample_rate = 22050;
642 case SOUND_SAMPLE_RATE_44100:
643 *sample_rate = 44100;
645 case SOUND_SAMPLE_RATE_48000:
646 *sample_rate = 48000;
648 case SOUND_SAMPLE_RATE_88200:
649 *sample_rate = 88200;
651 case SOUND_SAMPLE_RATE_96000:
652 *sample_rate = 96000;
654 case SOUND_SAMPLE_RATE_192000:
655 *sample_rate = 192000;
658 LOGE("not supported sample rate(%u)", rate);
659 return MM_ERROR_INVALID_ARGUMENT;
662 return MM_ERROR_NONE;
665 int _convert_sample_rate_to_enum(unsigned int rate, sound_sample_rate_e *rate_e)
667 SM_NULL_ARG_CHECK_FOR_PRIV(rate_e);
671 *rate_e = SOUND_SAMPLE_RATE_8000;
674 *rate_e = SOUND_SAMPLE_RATE_16000;
677 *rate_e = SOUND_SAMPLE_RATE_22050;
680 *rate_e = SOUND_SAMPLE_RATE_44100;
683 *rate_e = SOUND_SAMPLE_RATE_48000;
686 *rate_e = SOUND_SAMPLE_RATE_88200;
689 *rate_e = SOUND_SAMPLE_RATE_96000;
692 *rate_e = SOUND_SAMPLE_RATE_192000;
695 LOGE("not supported sample rate(%u)", rate);
696 return MM_ERROR_INVALID_ARGUMENT;
699 return MM_ERROR_NONE;
702 int _return_val_if_not_usb_device(sound_device_h device, int ret_val)
704 mm_sound_device_type_e type;
706 if (mm_sound_get_device_type(device, &type))
709 if (type != MM_SOUND_DEVICE_TYPE_USB_AUDIO) {
710 LOGE("device type is not USB AUDIO");
714 return MM_ERROR_NONE;
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)
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;
727 LOGE("user_data is null");
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);
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);
742 SM_ENTER_CRITICAL_SECTION(&stream_info->focus_cb_mutex);
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;
749 if (state == FOCUS_IS_ACQUIRED)
750 _update_focus_status(stream_info->pa_index, (unsigned int)stream_info->acquired_focus);
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);
757 if (state == FOCUS_IS_RELEASED)
758 _update_focus_status(stream_info->pa_index, (unsigned int)stream_info->acquired_focus);
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;
765 SM_LEAVE_CRITICAL_SECTION(&stream_info->focus_cb_mutex);
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)
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;
780 LOGE("user_data is null");
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);
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);
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);
805 void _pa_context_state_cb(pa_context *c, void *userdata)
807 pa_context_state_t state;
808 sound_stream_info_s *stream_info_h = (sound_stream_info_s*)userdata;
812 state = pa_context_get_state(c);
813 LOGI("[%p] context state = [%d]", stream_info_h, 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);
820 case PA_CONTEXT_UNCONNECTED:
821 case PA_CONTEXT_CONNECTING:
822 case PA_CONTEXT_AUTHORIZING:
823 case PA_CONTEXT_SETTING_NAME:
830 void _pa_stream_state_cb(pa_stream *s, void * userdata)
832 pa_stream_state_t state;
833 virtual_sound_stream_info_s *vstream_h = (virtual_sound_stream_info_s*)userdata;
837 state = pa_stream_get_state(s);
838 LOGI("[%p] stream [%d] state = [%d]", vstream_h, pa_stream_get_index(s), 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);
846 case PA_STREAM_UNCONNECTED:
847 case PA_STREAM_CREATING:
854 int _get_stream_conf_info(const char *stream_type, stream_conf_info_s *info)
856 int ret = MM_ERROR_NONE;
857 GVariant *result = NULL;
858 GVariant *child = NULL;
859 GDBusConnection *conn = NULL;
862 GVariant *item = NULL;
870 if ((ret = __get_dbus_connection(&conn)))
873 result = g_dbus_connection_call_sync(conn,
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,
884 if (!result || err) {
885 LOGE("g_dbus_connection_call_sync() for GET_STREAM_INFO error (%s)", err ? err->message : NULL);
887 ret = MM_ERROR_SOUND_INTERNAL;
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);
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);
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")))
914 /* we use volume type only for out direction */
916 LOGI(" volume-type : %s", name);
917 info->volume_type = strdup(name);
921 g_variant_unref(item);
922 g_variant_unref(child);
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);
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);
936 LOGI(" in-device name : %s", name);
937 info->avail_in_devices[i++] = strdup(name);
939 g_variant_unref(item);
940 g_variant_unref(child);
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);
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);
954 LOGI(" out-device name : %s", name);
955 info->avail_out_devices[i++] = strdup(name);
957 g_variant_unref(item);
958 g_variant_unref(child);
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);
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);
972 LOGI(" framework name : %s", name);
973 info->avail_frameworks[i++] = strdup(name);
975 g_variant_unref(item);
976 g_variant_unref(child);
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;
984 g_variant_unref(result);
985 g_object_unref(conn);
990 int _set_manual_route_info(unsigned int index, manual_route_info_s *info)
992 int ret = MM_ERROR_NONE;
994 GVariantBuilder *builder_for_in_devices;
995 GVariantBuilder *builder_for_out_devices;
996 GVariant *result = NULL;
997 GDBusConnection *conn = NULL;
999 const gchar *dbus_ret = NULL;
1003 if ((ret = __get_dbus_connection(&conn)))
1006 LOGI("stream info index(%u)", index);
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;
1016 for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
1017 if (!info->route_in_devices[i])
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]);
1022 for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
1023 if (!info->route_out_devices[i])
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]);
1029 result = g_dbus_connection_call_sync(conn,
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,
1040 if (!result || err) {
1041 LOGE("g_dbus_connection_call_sync() for SET_STREAM_ROUTE_DEVICES error (%s)", err ? err->message : NULL);
1043 ret = MM_ERROR_SOUND_INTERNAL;
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;
1052 info->is_set = true;
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);
1065 int _set_route_option(unsigned int index, const char *name, int value)
1067 int ret = MM_ERROR_NONE;
1068 GVariant *result = NULL;
1069 GDBusConnection *conn = NULL;
1071 const gchar *dbus_ret = NULL;
1075 if ((ret = __get_dbus_connection(&conn)))
1078 LOGI("[OPTION] %s(%d)", name, value);
1080 result = g_dbus_connection_call_sync(conn,
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,
1091 if (!result || err) {
1092 LOGE("g_dbus_connection_call_sync() for SET_STREAM_ROUTE_OPTION error (%s)", err ? err->message : NULL);
1094 ret = MM_ERROR_SOUND_INTERNAL;
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;
1106 g_variant_unref(result);
1107 g_object_unref(conn);
1112 int _get_volume_max_level(const char *direction, const char *volume_type, unsigned int *max_level)
1114 int ret = MM_ERROR_NONE;
1115 GVariant *result = NULL;
1116 GDBusConnection *conn = NULL;
1118 const gchar *dbus_ret = NULL;
1121 assert(volume_type);
1124 if ((ret = __get_dbus_connection(&conn)))
1127 result = g_dbus_connection_call_sync(conn,
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,
1138 if (!result || err) {
1139 LOGE("g_dbus_connection_call_sync() for GET_VOLUME_MAX_LEVEL error (%s)", err ? err->message : NULL);
1141 ret = MM_ERROR_SOUND_INTERNAL;
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;
1151 g_variant_unref(result);
1152 g_object_unref(conn);
1157 int _get_volume_level(const char *direction, const char *volume_type, unsigned int *level)
1159 int ret = MM_ERROR_NONE;
1160 GVariant *result = NULL;
1161 GDBusConnection *conn = NULL;
1163 const gchar *dbus_ret = NULL;
1166 assert(volume_type);
1169 if ((ret = __get_dbus_connection(&conn)))
1172 result = g_dbus_connection_call_sync(conn,
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,
1183 if (!result || err) {
1184 LOGE("g_dbus_connection_call_sync() for GET_VOLUME_LEVEL error (%s)", err ? err->message : NULL);
1186 ret = MM_ERROR_SOUND_INTERNAL;
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;
1196 g_variant_unref(result);
1197 g_object_unref(conn);
1202 int _set_volume_level(const char *direction, const char *volume_type, unsigned int level)
1204 int ret = MM_ERROR_NONE;
1205 GVariant *result = NULL;
1206 GDBusConnection *conn = NULL;
1208 const gchar *dbus_ret = NULL;
1210 char volume_path[VCONF_PATH_MAX] = {0,};
1213 assert(volume_type);
1215 if ((ret = __get_dbus_connection(&conn)))
1218 result = g_dbus_connection_call_sync(conn,
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,
1229 if (!result || err) {
1230 LOGE("g_dbus_connection_call_sync() for SET_VOLUME_LEVEL error (%s)", err ? err->message : NULL);
1232 ret = MM_ERROR_SOUND_INTERNAL;
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;
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);
1248 g_variant_unref(result);
1249 g_object_unref(conn);
1254 int _get_current_volume_type(const char *direction, char **volume_type)
1256 int ret = MM_ERROR_NONE;
1257 GVariant *result = NULL;
1258 GDBusConnection *conn = NULL;
1260 const gchar *dbus_volume_type = NULL;
1261 const gchar *dbus_ret = NULL;
1264 assert(volume_type);
1266 if ((ret = __get_dbus_connection(&conn)))
1269 result = g_dbus_connection_call_sync(conn,
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,
1280 if (!result || err) {
1281 LOGE("g_dbus_connection_call_sync() for GET_CURRENT_VOLUME_TYPE error (%s)", err ? err->message : NULL);
1283 ret = MM_ERROR_SOUND_INTERNAL;
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;
1295 ret = MM_ERROR_SOUND_INTERNAL;
1299 g_variant_unref(result);
1300 g_object_unref(conn);
1305 int _get_current_media_routing_path(const char *direction, sound_device_type_e *device_type)
1307 int ret = MM_ERROR_NONE;
1308 GVariant *result = NULL;
1309 GDBusConnection *conn = NULL;
1311 const gchar *dbus_device_type = NULL;
1312 const gchar *dbus_ret = NULL;
1315 assert(device_type);
1317 if ((ret = __get_dbus_connection(&conn)))
1320 result = g_dbus_connection_call_sync(conn,
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,
1331 if (!result || err) {
1332 LOGE("g_dbus_connection_call_sync() for GET_CURRENT_MEDIA_ROUTING_PATH error (%s)", err ? err->message : NULL);
1334 ret = MM_ERROR_SOUND_INTERNAL;
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;
1345 if (!strncmp("none", dbus_device_type, strlen(dbus_device_type)))
1346 ret = MM_ERROR_SOUND_NO_DATA;
1348 ret = MM_ERROR_SOUND_INTERNAL;
1352 g_variant_unref(result);
1353 g_object_unref(conn);
1358 void _update_focus_status(unsigned int index, unsigned int acquired_focus_status)
1360 GVariant *result = NULL;
1361 GDBusConnection *conn = NULL;
1363 const gchar *dbus_ret = NULL;
1365 if (__get_dbus_connection(&conn))
1368 result = g_dbus_connection_call_sync(conn,
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,
1379 if (!result || err) {
1380 LOGE("g_dbus_connection_call_sync() for UPDATE_FOCUS_STATUS error (%s)", err ? err->message : NULL);
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);
1390 g_variant_unref(result);
1391 g_object_unref(conn);
1396 int _is_device_running_by_id(int device_id, bool *is_running)
1398 int ret = MM_ERROR_NONE;
1399 GVariant *result = NULL;
1400 GDBusConnection *conn = NULL;
1402 gboolean _is_running;
1406 if ((ret = __get_dbus_connection(&conn)))
1409 result = g_dbus_connection_call_sync(conn,
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,
1421 LOGE("g_dbus_connection_call_sync() for IS_DEVICE_RUNNING_BY_ID error (%s)", err->message);
1422 ret = _convert_dbus_error(err->message);
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");
1432 g_variant_unref(result);
1433 g_object_unref(conn);
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)
1441 int ret = MM_ERROR_NONE;
1442 GVariant *result = NULL;
1443 GDBusConnection *conn = NULL;
1445 GVariantIter *iter = NULL;
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, };
1452 SM_NULL_ARG_CHECK_FOR_PRIV(formats);
1453 SM_NULL_ARG_CHECK_FOR_PRIV(num);
1455 if ((ret = __get_dbus_connection(&conn)))
1458 result = g_dbus_connection_call_sync(conn,
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,
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);
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;
1483 while (g_variant_iter_loop(iter, "&s", &format_str)) {
1484 if (_convert_sample_format_str_to_enum((const char *)format_str, &format))
1486 LOGI("%s(enum:%u) is supported", format_str, format);
1488 sm_formats[elem_num - 1] = format;
1491 if (elem_num == 0) {
1492 LOGE("could not find supported sample formats");
1493 ret = MM_ERROR_SOUND_INTERNAL;
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;
1502 memcpy(*formats, sm_formats, elem_num * sizeof(sound_sample_format_e));
1508 g_variant_iter_free(iter);
1509 g_variant_unref(result);
1510 g_object_unref(conn);
1515 int _set_sample_format(int device_id, sound_sample_format_e format)
1517 int ret = MM_ERROR_NONE;
1518 GDBusConnection *conn = NULL;
1520 char *format_str = NULL;
1522 if ((ret = __get_dbus_connection(&conn)))
1525 if ((ret = _convert_sample_format_enum_to_str(format, &format_str)))
1528 g_dbus_connection_call_sync(conn,
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),
1535 G_DBUS_CALL_FLAGS_NONE,
1540 LOGE("g_dbus_connection_call_sync() for SET_SAMPLE_FORMAT error (%s)", err->message);
1541 ret = _convert_dbus_error(err->message);
1545 g_object_unref(conn);
1550 int _get_sample_format(int device_id, sound_sample_format_e *format)
1552 int ret = MM_ERROR_NONE;
1553 GVariant *result = NULL;
1554 GDBusConnection *conn = NULL;
1557 sound_sample_format_e format_e;
1559 SM_NULL_ARG_CHECK_FOR_PRIV(format);
1561 if ((ret = __get_dbus_connection(&conn)))
1564 result = g_dbus_connection_call_sync(conn,
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,
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);
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;
1587 g_variant_unref(result);
1590 g_object_unref(conn);
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)
1598 int ret = MM_ERROR_NONE;
1599 GVariant *result = NULL;
1600 GDBusConnection *conn = NULL;
1602 GVariantIter *iter = NULL;
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, };
1609 SM_NULL_ARG_CHECK_FOR_PRIV(rates);
1610 SM_NULL_ARG_CHECK_FOR_PRIV(num);
1612 if ((ret = __get_dbus_connection(&conn)))
1615 result = g_dbus_connection_call_sync(conn,
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,
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);
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;
1640 while (g_variant_iter_loop(iter, "u", &rate)) {
1641 if (_convert_sample_rate_to_enum(rate, &rate_e))
1643 LOGI("%u(enum:%u) is supported", rate, rate_e);
1645 sm_rates[elem_num - 1] = rate_e;
1648 if (elem_num == 0) {
1649 LOGE("could not find supported sample rates");
1650 ret = MM_ERROR_SOUND_INTERNAL;
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;
1659 memcpy(*rates, sm_rates, elem_num * sizeof(sound_sample_rate_e));
1665 g_variant_iter_free(iter);
1666 g_variant_unref(result);
1667 g_object_unref(conn);
1672 int _set_sample_rate(int device_id, sound_sample_rate_e rate)
1674 int ret = MM_ERROR_NONE;
1675 GDBusConnection *conn = NULL;
1679 if ((ret = __get_dbus_connection(&conn)))
1682 if ((ret = _convert_sample_rate_enum_to_uint(rate, &_rate)))
1685 g_dbus_connection_call_sync(conn,
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),
1692 G_DBUS_CALL_FLAGS_NONE,
1697 LOGE("g_dbus_connection_call_sync() for SET_SAMPLE_RATE error (%s)", err->message);
1698 ret = _convert_dbus_error(err->message);
1702 g_object_unref(conn);
1707 int _get_sample_rate(int device_id, sound_sample_rate_e *rate)
1709 int ret = MM_ERROR_NONE;
1710 GVariant *result = NULL;
1711 GDBusConnection *conn = NULL;
1714 sound_sample_rate_e rate_e;
1716 SM_NULL_ARG_CHECK_FOR_PRIV(rate);
1718 if ((ret = __get_dbus_connection(&conn)))
1721 result = g_dbus_connection_call_sync(conn,
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,
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);
1738 g_variant_get(result, "(u)", &_rate);
1739 if (_convert_sample_rate_to_enum(_rate, &rate_e))
1740 ret = MM_ERROR_SOUND_INTERNAL;
1744 g_variant_unref(result);
1747 g_object_unref(conn);
1752 int _set_avoid_resampling(int device_id, bool enable)
1754 int ret = MM_ERROR_NONE;
1755 GDBusConnection *conn = NULL;
1758 if ((ret = __get_dbus_connection(&conn)))
1761 g_dbus_connection_call_sync(conn,
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),
1768 G_DBUS_CALL_FLAGS_NONE,
1773 LOGE("g_dbus_connection_call_sync() for SET_AVOID_RESAMPLING error (%s)", err->message);
1774 ret = _convert_dbus_error(err->message);
1778 g_object_unref(conn);
1783 int _get_avoid_resampling(int device_id, bool *enabled)
1785 int ret = MM_ERROR_NONE;
1786 GVariant *result = NULL;
1787 GDBusConnection *conn = NULL;
1791 SM_NULL_ARG_CHECK_FOR_PRIV(enabled);
1793 if ((ret = __get_dbus_connection(&conn)))
1796 result = g_dbus_connection_call_sync(conn,
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,
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);
1814 g_variant_get(result, "(b)", &_enabled);
1815 *enabled = (bool)_enabled;
1816 g_variant_unref(result);
1819 g_object_unref(conn);
1824 int _set_media_stream_only(int device_id, bool enable)
1826 int ret = MM_ERROR_NONE;
1827 GDBusConnection *conn = NULL;
1829 const char *stream_type;
1831 if ((ret = __get_dbus_connection(&conn)))
1835 stream_type = "media";
1837 stream_type = "none";
1839 g_dbus_connection_call_sync(conn,
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),
1846 G_DBUS_CALL_FLAGS_NONE,
1851 LOGE("g_dbus_connection_call_sync() for SET_SPECIFIC_STREAM error (%s)", err->message);
1852 ret = _convert_dbus_error(err->message);
1856 g_object_unref(conn);
1861 int _get_media_stream_only(int device_id, bool *enabled)
1863 int ret = MM_ERROR_NONE;
1864 GVariant *result = NULL;
1865 GDBusConnection *conn = NULL;
1869 SM_NULL_ARG_CHECK_FOR_PRIV(enabled);
1871 if ((ret = __get_dbus_connection(&conn)))
1874 result = g_dbus_connection_call_sync(conn,
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,
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);
1892 g_variant_get(result, "(&s)", &stream_type);
1893 if (!strncmp(stream_type, "media", SOUND_STREAM_TYPE_LEN))
1898 g_variant_unref(result);
1901 g_object_unref(conn);
1906 int _make_pa_connection_and_register_focus(sound_stream_info_s *stream_h, sound_stream_focus_state_changed_cb callback, void *user_data)
1908 int ret = MM_ERROR_NONE;
1911 bool is_focus_cb_thread = false;
1913 if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
1916 if (is_focus_cb_thread)
1917 return MM_ERROR_SOUND_INVALID_OPERATION;
1919 /* get configuration information of this stream type */
1920 if ((ret = _get_stream_conf_info(stream_h->stream_type, &stream_h->stream_conf_info)))
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);
1926 if (!(stream_h->pa_mainloop = pa_threaded_mainloop_new()))
1929 if (!(stream_h->pa_context = pa_context_new(pa_threaded_mainloop_get_api(stream_h->pa_mainloop), "SOUND_MANAGER_STREAM_INFO")))
1932 pa_context_set_state_callback(stream_h->pa_context, _pa_context_state_cb, stream_h);
1934 if (pa_context_connect(stream_h->pa_context, NULL, 0, NULL) < 0) {
1935 pa_ret = pa_context_errno(stream_h->pa_context);
1939 pa_threaded_mainloop_lock(stream_h->pa_mainloop);
1941 if (pa_threaded_mainloop_start(stream_h->pa_mainloop) < 0)
1942 goto PA_ERROR_WITH_UNLOCK;
1944 /* wait for ready state of the context */
1946 pa_context_state_t state;
1947 state = pa_context_get_state(stream_h->pa_context);
1948 if (state == PA_CONTEXT_READY)
1950 if (!PA_CONTEXT_IS_GOOD(state)) {
1951 pa_ret = pa_context_errno(stream_h->pa_context);
1952 goto PA_ERROR_WITH_UNLOCK;
1954 pa_threaded_mainloop_wait(stream_h->pa_mainloop);
1957 /* get index of this context */
1958 stream_h->pa_index = pa_context_get_index(stream_h->pa_context);
1960 pa_threaded_mainloop_unlock(stream_h->pa_mainloop);
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;
1969 LOGE("failed to register focus, ret(0x%x)", ret);
1976 PA_ERROR_WITH_UNLOCK:
1977 pa_threaded_mainloop_unlock(stream_h->pa_mainloop);
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]);
1984 for (i = 0; i < AVAIL_FRAMEWORKS_MAX; i++)
1985 SM_SAFE_FREE(stream_h->stream_conf_info.avail_frameworks[i]);
1987 SM_SAFE_FREE(stream_h->stream_conf_info.volume_type);
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;
1994 if (stream_h->pa_mainloop) {
1995 pa_threaded_mainloop_free(stream_h->pa_mainloop);
1996 stream_h->pa_mainloop = NULL;
1998 ret = MM_ERROR_SOUND_INTERNAL;
1999 LOGE("pa_ret(%d), ret(0x%x)", pa_ret, ret);
2005 int _destroy_pa_connection_and_unregister_focus(sound_stream_info_s *stream_h)
2008 int ret = MM_ERROR_NONE;
2009 bool is_focus_cb_thread = false;
2011 ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread);
2015 if (is_focus_cb_thread)
2016 return MM_ERROR_SOUND_INVALID_OPERATION;
2018 if (stream_h->pa_mainloop)
2019 pa_threaded_mainloop_stop(stream_h->pa_mainloop);
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;
2027 if (stream_h->pa_mainloop) {
2028 pa_threaded_mainloop_free(stream_h->pa_mainloop);
2029 stream_h->pa_mainloop = NULL;
2032 /* unregister focus */
2033 if (!stream_h->is_focus_unavailable) {
2034 ret = mm_sound_unregister_focus(stream_h->focus_id);
2036 LOGE("failed to unregister focus, ret(0x%x)", ret);
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]);
2043 for (i = 0; i < AVAIL_FRAMEWORKS_MAX; i++)
2044 SM_SAFE_FREE(stream_h->stream_conf_info.avail_frameworks[i]);
2046 SM_SAFE_FREE(stream_h->stream_conf_info.volume_type);
2051 static int __check_manual_route_type(sound_stream_info_s *stream_info)
2053 SM_INSTANCE_CHECK_FOR_PRIV(stream_info);
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;
2061 return MM_ERROR_NONE;
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)
2067 bool added_successfully = false;
2069 SM_INSTANCE_CHECK_FOR_PRIV(stream_info);
2070 SM_NULL_ARG_CHECK_FOR_PRIV(device_type_str);
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])
2076 if (strncmp(stream_info->stream_conf_info.avail_in_devices[i], device_type_str, SOUND_DEVICE_TYPE_LEN))
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;
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;
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])
2096 if (strncmp(stream_info->stream_conf_info.avail_out_devices[i], device_type_str, SOUND_DEVICE_TYPE_LEN))
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;
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;
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;
2118 return MM_ERROR_NONE;
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)
2124 bool removed_successfully = false;
2126 SM_INSTANCE_CHECK_FOR_PRIV(stream_info);
2127 SM_NULL_ARG_CHECK_FOR_PRIV(device_type_str);
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])
2133 if (strncmp(stream_info->stream_conf_info.avail_in_devices[i], device_type_str, SOUND_DEVICE_TYPE_LEN))
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;
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])
2149 if (strncmp(stream_info->stream_conf_info.avail_out_devices[i], device_type_str, SOUND_DEVICE_TYPE_LEN))
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;
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;
2167 return MM_ERROR_NONE;
2170 int _add_device_for_stream_routing(sound_stream_info_s *stream_info, sound_device_h device)
2172 int ret = MM_ERROR_NONE;
2173 char *device_type_str = NULL;
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;
2179 SM_INSTANCE_CHECK_FOR_PRIV(stream_info);
2180 SM_NULL_ARG_CHECK_FOR_PRIV(device);
2182 if ((ret = __check_manual_route_type(stream_info)))
2185 if ((ret = mm_sound_get_device_id(device, &device_id)))
2187 if ((ret = mm_sound_get_device_type(device, &mm_sound_device_type)))
2189 if ((ret = _convert_device_type(mm_sound_device_type, &device_type)))
2191 if ((ret = _convert_device_type_enum_to_str(device_type, &device_type_str)))
2193 if ((ret = mm_sound_get_device_io_direction(device, &device_direction)))
2196 if ((ret = __add_device_to_stream_info(stream_info, device_id, device_direction, device_type_str)))
2199 LOGI("*** added device[type:%s, id:%d]", device_type_str, device_id);
2201 return MM_ERROR_NONE;
2204 int _remove_device_for_stream_routing(sound_stream_info_s *stream_info, sound_device_h device)
2206 int ret = MM_ERROR_NONE;
2207 char *device_type_str = NULL;
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;
2213 SM_INSTANCE_CHECK_FOR_PRIV(stream_info);
2214 SM_NULL_ARG_CHECK_FOR_PRIV(device);
2216 if ((ret = __check_manual_route_type(stream_info)))
2219 if ((ret = mm_sound_get_device_id(device, &device_id)))
2221 if ((ret = mm_sound_get_device_type(device, &mm_sound_device_type)))
2223 if ((ret = _convert_device_type(mm_sound_device_type, &device_type)))
2225 if ((ret = _convert_device_type_enum_to_str(device_type, &device_type_str)))
2227 if ((ret = mm_sound_get_device_io_direction(device, &device_direction)))
2230 if ((ret = __remove_device_from_stream_info(stream_info, device_id, device_direction, device_type_str)))
2233 LOGI("*** removed device[type:%s, id:%d]", device_type_str, device_id);
2235 return MM_ERROR_NONE;
2238 int _remove_all_devices_for_stream_routing(sound_stream_info_s *stream_info)
2240 int ret = MM_ERROR_NONE;
2243 SM_INSTANCE_CHECK_FOR_PRIV(stream_info);
2245 if ((ret = __check_manual_route_type(stream_info)))
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;
2253 stream_info->manual_route_info.is_set = false;
2255 LOGI("*** removed all devices");
2257 return MM_ERROR_NONE;
2260 int _add_device_id_for_stream_routing(sound_stream_info_s *stream_info, int device_id)
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;
2269 SM_INSTANCE_CHECK_FOR_PRIV(stream_info);
2271 if ((ret = __check_manual_route_type(stream_info)))
2274 if ((ret = mm_sound_get_device_by_id(device_id, &device)))
2276 if ((ret = mm_sound_get_device_type(device, &mm_sound_device_type)))
2278 if ((ret = _convert_device_type(mm_sound_device_type, &device_type)))
2280 if ((ret = _convert_device_type_enum_to_str(device_type, &device_type_str)))
2282 if ((ret = mm_sound_get_device_io_direction(device, &device_direction)))
2285 if ((ret = __add_device_to_stream_info(stream_info, device_id, device_direction, device_type_str)))
2288 LOGI("*** added device by id[type:%s, id:%d]", device_type_str, device_id);
2292 mm_sound_free_device(device);
2296 int _remove_device_id_for_stream_routing(sound_stream_info_s *stream_info, int device_id)
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;
2305 SM_INSTANCE_CHECK_FOR_PRIV(stream_info);
2307 if ((ret = __check_manual_route_type(stream_info)))
2310 if ((ret = mm_sound_get_device_by_id(device_id, &device)))
2312 if ((ret = mm_sound_get_device_type(device, &mm_sound_device_type)))
2314 if ((ret = _convert_device_type(mm_sound_device_type, &device_type)))
2316 if ((ret = _convert_device_type_enum_to_str(device_type, &device_type_str)))
2318 if ((ret = mm_sound_get_device_io_direction(device, &device_direction)))
2321 if ((ret = __remove_device_from_stream_info(stream_info, device_id, device_direction, device_type_str)))
2324 LOGI("*** removed device by id[type:%s, id:%d]", device_type_str, device_id);
2328 mm_sound_free_device(device);
2332 int _apply_stream_routing(sound_stream_info_s *stream_info)
2336 SM_INSTANCE_CHECK_FOR_PRIV(stream_info);
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;
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);
2352 return MM_ERROR_SOUND_INVALID_STATE;
2355 int _create_virtual_stream(sound_stream_info_s *stream_info, virtual_sound_stream_info_s **virtual_stream)
2357 int ret = MM_ERROR_NONE;
2358 bool result = false;
2359 const char *name = NULL;
2362 SM_INSTANCE_CHECK_FOR_PRIV(virtual_stream);
2363 SM_INSTANCE_CHECK_FOR_PRIV(stream_info);
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))) {
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;
2379 (*virtual_stream) = malloc(sizeof(virtual_sound_stream_info_s));
2380 if (!(*virtual_stream)) {
2381 ret = MM_ERROR_OUT_OF_MEMORY;
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;
2399 int _destroy_virtual_stream(virtual_sound_stream_info_s *virtual_stream)
2401 int ret = MM_ERROR_NONE;
2403 SM_INSTANCE_CHECK_FOR_PRIV(virtual_stream);
2404 SM_STATE_CHECK_FOR_PRIV(virtual_stream, _VSTREAM_STATE_READY);
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);
2411 SM_SAFE_FREE(virtual_stream);
2416 int _start_virtual_stream(virtual_sound_stream_info_s *virtual_stream)
2418 int ret = MM_ERROR_NONE;
2421 int io_direction = 0;
2423 pa_channel_map maps;
2425 SM_INSTANCE_CHECK_FOR_PRIV(virtual_stream);
2426 SM_STATE_CHECK_FOR_PRIV(virtual_stream, _VSTREAM_STATE_READY);
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;
2437 /* fill up with default value */
2440 ss.format = PA_SAMPLE_S16LE;
2441 pa_channel_map_init_auto(&maps, ss.channels, PA_CHANNEL_MAP_ALSA);
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;
2449 /* LOCK the pa_threaded_mainloop */
2450 pa_threaded_mainloop_lock(virtual_stream->pa_mainloop);
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;
2461 pa_stream_set_state_callback(virtual_stream->pa_stream[i], _pa_stream_state_cb, virtual_stream);
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);
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;
2471 } else if ((i + 1) == SOUND_STREAM_DIRECTION_INPUT) {
2472 pa_ret = pa_stream_connect_record(virtual_stream->pa_stream[i], NULL, NULL, 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;
2481 /* wait for ready state of the stream */
2483 pa_stream_state_t state;
2484 state = pa_stream_get_state(virtual_stream->pa_stream[i]);
2485 if (state == PA_STREAM_READY)
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;
2494 pa_threaded_mainloop_wait(virtual_stream->pa_mainloop);
2498 virtual_stream->state = _VSTREAM_STATE_RUNNING;
2500 /* UNLOCK the pa_threaded_mainloop */
2501 pa_threaded_mainloop_unlock(virtual_stream->pa_mainloop);
2506 /* UNLOCK the pa_threaded_mainloop */
2507 pa_threaded_mainloop_unlock(virtual_stream->pa_mainloop);
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;
2515 LOGE("pa_ret(%d)", pa_ret);
2521 int _stop_virtual_stream(virtual_sound_stream_info_s *virtual_stream)
2523 int ret = MM_ERROR_NONE;
2526 SM_INSTANCE_CHECK_FOR_PRIV(virtual_stream);
2527 SM_STATE_CHECK_FOR_PRIV(virtual_stream, _VSTREAM_STATE_RUNNING);
2529 /* LOCK the pa_threaded_mainloop */
2530 pa_threaded_mainloop_lock(virtual_stream->pa_mainloop);
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]);
2536 /* wait for terminated state of the stream */
2538 pa_stream_state_t state;
2539 state = pa_stream_get_state(virtual_stream->pa_stream[i]);
2540 if (state == PA_STREAM_TERMINATED)
2542 pa_threaded_mainloop_wait(virtual_stream->pa_mainloop);
2545 pa_stream_unref(virtual_stream->pa_stream[i]);
2546 virtual_stream->pa_stream[i] = NULL;
2550 /* UNLOCK the pa_threaded_mainloop */
2551 pa_threaded_mainloop_unlock(virtual_stream->pa_mainloop);
2553 virtual_stream->state = _VSTREAM_STATE_READY;