--- /dev/null
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2018 Sangchul Lee <sc11.lee@samsung.com>
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_DBUS
+
+#include <string.h>
+#include <stdbool.h>
+#include <pulse/proplist.h>
+#include <pulse/util.h>
+#include <pulsecore/log.h>
+
+#include "stream-manager.h"
+#include "device-manager.h"
+#include "device-manager-priv.h"
+#include "device-manager-db-priv.h"
+
+/* Dbus defines */
+#define DBUS_INTERFACE_DEVICE_MANAGER "org.pulseaudio.DeviceManager"
+#define DBUS_OBJECT_DEVICE_MANAGER "/org/pulseaudio/DeviceManager"
+
+#define DBUS_INTERFACE_DEVICED_SYSNOTI "org.tizen.system.deviced.SysNoti"
+#define DBUS_OBJECT_DEVICED_SYSNOTI "/Org/Tizen/System/DeviceD/SysNoti"
+
+#define DBUS_INTERFACE_SOUND_SERVER "org.tizen.SoundServer1"
+#define DBUS_OBJECT_SOUND_SERVER "/org/tizen/SoundServer1"
+
+#define DBUS_SERVICE_BLUEZ "org.bluez"
+#define DBUS_INTERFACE_BLUEZ_HEADSET "org.bluez.Headset"
+#define DBUS_INTERFACE_BLUEZ_DEVICE "org.bluez.Device1"
+#define DBUS_OBJECT_BLUEZ "/org/bluez"
+
+#define DBUS_INTERFACE_MIRRORING_SERVER "org.tizen.scmirroring.server"
+#define DBUS_OBJECT_MIRRORING_SERVER "/org/tizen/scmirroring/server"
+
+#define DBUS_SERVICE_HFP_AGENT "org.bluez.ag_agent"
+#define DBUS_OBJECT_HFP_AGENT "/org/bluez/hfp_agent"
+#define DBUS_INTERFACE_HFP_AGENT "Org.Hfp.App.Interface"
+
+#define DEVICE_MANAGER_INTROSPECT_XML \
+ DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
+ "<node>\n" \
+ " <interface name=\"" DBUS_INTERFACE_DEVICE_MANAGER "\">\n" \
+ " <method name=\"GetConnectedDeviceList\">\n" \
+ " <arg name=\"mask_flags\" direction=\"in\" type=\"i\"/>\n" \
+ " <arg name=\"ConnectedDeviceList\" direction=\"out\" type=\"a(isiisii)\"/>\n" \
+ " </method>\n" \
+ " <method name=\"GetDeviceById\">\n" \
+ " <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n" \
+ " <arg name=\"device\" direction=\"out\" type=\"(isiisii)\"/>\n" \
+ " </method>\n" \
+ " <method name=\"IsStreamOnDevice\">\n" \
+ " <arg name=\"stream_id\" direction=\"in\" type=\"i\"/>\n" \
+ " <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n" \
+ " <arg name=\"is_on\" direction=\"out\" type=\"b\"/>\n" \
+ " </method>\n" \
+ " <method name='GetBTA2DPStatus'>" \
+ " <arg type='b' name='is_bt_on' direction='out'/>" \
+ " <arg type='s' name='bt_name' direction='out'/>" \
+ " </method>" \
+ " <method name=\"LoadSink\">\n" \
+ " <arg name=\"device_type\" direction=\"in\" type=\"s\"/>\n" \
+ " <arg name=\"role\" direction=\"in\" type=\"s\"/>\n" \
+ " </method>\n" \
+ " <method name=\"UnloadSink\">\n" \
+ " <arg name=\"device_type\" direction=\"in\" type=\"s\"/>\n" \
+ " <arg name=\"role\" direction=\"in\" type=\"s\"/>\n" \
+ " </method>\n" \
+ " <method name=\"GetSupportedSampleFormats\">\n" \
+ " <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n" \
+ " <arg name=\"sample_formats\" direction=\"out\" type=\"a(s)\"/>\n" \
+ " </method>\n" \
+ " <method name=\"SetSampleFormat\">\n" \
+ " <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n" \
+ " <arg name=\"sample_format\" direction=\"in\" type=\"s\"/>\n" \
+ " </method>\n" \
+ " <method name=\"GetSampleFormat\">\n" \
+ " <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n" \
+ " <arg name=\"sample_format\" direction=\"out\" type=\"s\"/>\n" \
+ " </method>\n" \
+ " <method name=\"GetSupportedSampleRates\">\n" \
+ " <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n" \
+ " <arg name=\"sample_rates\" direction=\"out\" type=\"a(u)\"/>\n" \
+ " </method>\n" \
+ " <method name=\"SetSampleRate\">\n" \
+ " <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n" \
+ " <arg name=\"sample_rate\" direction=\"in\" type=\"u\"/>\n" \
+ " </method>\n" \
+ " <method name=\"GetSampleRate\">\n" \
+ " <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n" \
+ " <arg name=\"sample_rate\" direction=\"out\" type=\"u\"/>\n" \
+ " </method>\n" \
+ " <method name=\"SetSpecificStreamOnly\">\n" \
+ " <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n" \
+ " <arg name=\"stream_role\" direction=\"in\" type=\"s\"/>\n" \
+ " </method>\n" \
+ " <method name=\"GetSpecifiedStream\">\n" \
+ " <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n" \
+ " <arg name=\"stream_role\" direction=\"out\" type=\"s\"/>\n" \
+ " </method>\n" \
+ " <method name=\"SetAvoidResampling\">\n" \
+ " <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n" \
+ " <arg name=\"avoid_resampling\" direction=\"in\" type=\"b\"/>\n" \
+ " </method>\n" \
+ " <method name=\"GetAvoidResampling\">\n" \
+ " <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n" \
+ " <arg name=\"avoid_resampling\" direction=\"out\" type=\"b\"/>\n" \
+ " </method>\n" \
+ " <method name=\"DumpDeviceList\">\n" \
+ " </method>\n" \
+ " <method name=\"TestStatusChange\">\n" \
+ " <arg name=\"device_type\" direction=\"in\" type=\"s\"/>\n" \
+ " <arg name=\"status\" direction=\"in\" type=\"i\"/>\n" \
+ " </method>\n" \
+ " <property name=\"PropertyTest1\" type=\"i\" access=\"readwrite\"/>\n" \
+ " <property name=\"PropertyTest2\" type=\"s\" access=\"read\"/>\n" \
+ " <signal name=\"DeviceConnected\">\n" \
+ " <arg name=\"arg1\" type=\"i\"/>\n" \
+ " </signal>\n" \
+ " <signal name=\"DeviceInfoChanged\">\n" \
+ " <arg name=\"arg1\" type=\"s\"/>\n" \
+ " </signal>\n" \
+ " </interface>\n" \
+ " <interface name=\"" DBUS_INTERFACE_INTROSPECTABLE "\">\n" \
+ " <method name=\"Introspect\">\n" \
+ " <arg name=\"data\" type=\"s\" direction=\"out\"/>\n" \
+ " </method>\n" \
+ " </interface>\n" \
+ " <interface name=\"" DBUS_INTERFACE_PROPERTIES "\">\n" \
+ " <method name=\"Get\">\n" \
+ " <arg name=\"interface_name\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"property_name\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"value\" type=\"v\" direction=\"out\"/>\n" \
+ " </method>\n" \
+ " <method name=\"Set\">\n" \
+ " <arg name=\"interface_name\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"property_name\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"value\" type=\"v\" direction=\"in\"/>\n" \
+ " </method>\n" \
+ " <method name=\"GetAll\">\n" \
+ " <arg name=\"interface_name\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"props\" type=\"a{sv}\" direction=\"out\"/>\n" \
+ " </method>\n" \
+ " </interface>\n" \
+ "</node>\n"
+
+#define FILTER_DEVICED_SYSNOTI \
+ "type='signal'," \
+ " interface='" DBUS_INTERFACE_DEVICED_SYSNOTI "'"
+
+#define FILTER_SOUND_SERVER \
+ "type='signal'," \
+ " interface='" DBUS_INTERFACE_SOUND_SERVER "'"
+
+#define FILTER_MIRRORING \
+ "type='signal'," \
+ " interface='" DBUS_INTERFACE_MIRRORING_SERVER "', member='miracast_wfd_source_status_changed'"
+
+#define FILTER_BLUEZ \
+ "type='signal'," \
+ " interface='" DBUS_INTERFACE_BLUEZ_HEADSET "', member='PropertyChanged'"
+
+#define FILL_SAMPLE_SPEC_WITH_SELECTED(x_spec, x_sink) \
+do { \
+ x_spec.format = x_sink->selected_sample_format; \
+ x_spec.rate = x_sink->selected_sample_rate; \
+ x_spec.channels = 2; \
+} while(0)
+
+/*** Defines for method handle ***/
+static void handle_get_connected_device_list(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_get_device_by_id(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_is_stream_on_device(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_get_bt_a2dp_status(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_get_supported_sample_formats(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_set_sample_format(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_get_sample_format(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_get_supported_sample_rates(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_set_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_set_specific_stream_only(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_get_specified_stream(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_set_avoid_resampling(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_get_avoid_resampling(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_load_sink(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_unload_sink(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_unload_sink_with_device_string(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_get_device_string(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_dump_device_list(DBusConnection *conn, DBusMessage *msg, void *userdata);
+static void handle_test_device_status_change(DBusConnection *conn, DBusMessage *msg, void *userdata);
+
+static int method_call_bt_get_name(DBusConnection *conn, const char *device_path, char **name);
+
+enum method_handler_index {
+ METHOD_HANDLER_GET_CONNECTED_DEVICE_LIST,
+ METHOD_HANDLER_GET_DEVICE_BY_ID,
+ METHOD_HANDLER_IS_STREAM_ON_DEVICE,
+ METHOD_HANDLER_GET_BT_A2DP_STATUS,
+ METHOD_HANDLER_LOAD_SINK,
+ METHOD_HANDLER_UNLOAD_SINK,
+ METHOD_HANDLER_UNLOAD_SINK_WITH_DEVICE_STRING,
+ METHOD_HANDLER_GET_DEVICE_STRING,
+ METHOD_HANDLER_GET_SUPPORTED_SAMPLE_FORMATS,
+ METHOD_HANDLER_SET_SAMPLE_FORMAT,
+ METHOD_HANDLER_GET_SAMPLE_FORMAT,
+ METHOD_HANDLER_GET_SUPPORTED_SAMPLE_RATES,
+ METHOD_HANDLER_SET_SAMPLE_RATE,
+ METHOD_HANDLER_GET_SAMPLE_RATE,
+ METHOD_HANDLER_SET_SPECIFIC_STREAM_ONLY,
+ METHOD_HANDLER_GET_SPECIFIED_STREAM,
+ METHOD_HANDLER_SET_AVOID_RESAMPLING,
+ METHOD_HANDLER_GET_AVOID_RESAMPLING,
+ METHOD_HANDLER_DUMP_DEVICE_LIST,
+ METHOD_HANDLER_STATUS_TEST,
+ METHOD_HANDLER_MAX
+};
+
+static pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = {
+ [METHOD_HANDLER_GET_CONNECTED_DEVICE_LIST] = {
+ .method_name = "GetConnectedDeviceList",
+ .receive_cb = handle_get_connected_device_list },
+ [METHOD_HANDLER_GET_DEVICE_BY_ID] = {
+ .method_name = "GetDeviceById",
+ .receive_cb = handle_get_device_by_id },
+ [METHOD_HANDLER_IS_STREAM_ON_DEVICE] = {
+ .method_name = "IsStreamOnDevice",
+ .receive_cb = handle_is_stream_on_device },
+ [METHOD_HANDLER_GET_BT_A2DP_STATUS] = {
+ .method_name = "GetBTA2DPStatus",
+ .receive_cb = handle_get_bt_a2dp_status },
+ [METHOD_HANDLER_LOAD_SINK] = {
+ .method_name = "LoadSink",
+ .receive_cb = handle_load_sink },
+ [METHOD_HANDLER_UNLOAD_SINK] = {
+ .method_name = "UnloadSink",
+ .receive_cb = handle_unload_sink },
+ [METHOD_HANDLER_UNLOAD_SINK_WITH_DEVICE_STRING] = {
+ .method_name = "UnloadSinkWithDeviceString",
+ .receive_cb = handle_unload_sink_with_device_string },
+ [METHOD_HANDLER_GET_DEVICE_STRING] = {
+ .method_name = "GetDeviceString",
+ .receive_cb = handle_get_device_string },
+ [METHOD_HANDLER_GET_SUPPORTED_SAMPLE_FORMATS] = {
+ .method_name = "GetSupportedSampleFormats",
+ .receive_cb = handle_get_supported_sample_formats },
+ [METHOD_HANDLER_SET_SAMPLE_FORMAT] = {
+ .method_name = "SetSampleFormat",
+ .receive_cb = handle_set_sample_format },
+ [METHOD_HANDLER_GET_SAMPLE_FORMAT] = {
+ .method_name = "GetSampleFormat",
+ .receive_cb = handle_get_sample_format },
+ [METHOD_HANDLER_GET_SUPPORTED_SAMPLE_RATES] = {
+ .method_name = "GetSupportedSampleRates",
+ .receive_cb = handle_get_supported_sample_rates },
+ [METHOD_HANDLER_SET_SAMPLE_RATE] = {
+ .method_name = "SetSampleRate",
+ .receive_cb = handle_set_sample_rate },
+ [METHOD_HANDLER_GET_SAMPLE_RATE] = {
+ .method_name = "GetSampleRate",
+ .receive_cb = handle_get_sample_rate },
+ [METHOD_HANDLER_SET_SPECIFIC_STREAM_ONLY] = {
+ .method_name = "SetSpecificStreamOnly",
+ .receive_cb = handle_set_specific_stream_only },
+ [METHOD_HANDLER_GET_SPECIFIED_STREAM] = {
+ .method_name = "GetSpecifiedStream",
+ .receive_cb = handle_get_specified_stream },
+ [METHOD_HANDLER_SET_AVOID_RESAMPLING] = {
+ .method_name = "SetAvoidResampling",
+ .receive_cb = handle_set_avoid_resampling },
+ [METHOD_HANDLER_GET_AVOID_RESAMPLING] = {
+ .method_name = "GetAvoidResampling",
+ .receive_cb = handle_get_avoid_resampling },
+ [METHOD_HANDLER_DUMP_DEVICE_LIST] = {
+ .method_name = "DumpDeviceList",
+ .receive_cb = handle_dump_device_list },
+ [METHOD_HANDLER_STATUS_TEST] = {
+ .method_name = "TestStatusChange",
+ .receive_cb = handle_test_device_status_change },
+};
+
+static void save_preference(pa_device_manager *dm, pa_sink *sink) {
+ const char *key;
+ prefer_entry e;
+
+ pa_assert(dm);
+ pa_assert(sink);
+
+ e.avoid_resampling = sink->avoid_resampling;
+ e.format = sink->selected_sample_format;
+ e.rate = sink->selected_sample_rate;
+ if ((key = build_key_from_proplist(sink->proplist)))
+ write_prefer_entry(dm, key, &e);
+}
+
+/*
+ Handle device disconnection detected through dbus.
+ First, update device-status hashmap.
+ And if there is device which has the device_type, remove it.
+*/
+static int handle_device_disconnected(pa_device_manager *dm, const char *type, const char *system_id) {
+ pa_tz_device *device;
+
+ pa_assert(dm);
+ pa_assert(dm->device_status);
+
+ pa_log_info("Device type(%s) system_id(%s) disconnected",
+ type, pa_strempty(system_id));
+
+ device = device_list_get_device(dm, type, system_id);
+ if (!device) {
+ pa_log_error("Disconnection detected but no device for that");
+ return -1;
+ }
+
+ pa_tz_device_free(device);
+
+ return 0;
+}
+
+/*
+ look detected status which is external value, make conversion to internal consistent value, and handle it
+ device_type, which type of device is detected
+ system_id : system_id among same device types for support multi-device
+*/
+static int handle_device_status_changed(pa_device_manager *dm, const char *type,
+ const char *name, const char *system_id, device_detected_type_t detected) {
+ pa_assert(dm);
+
+ pa_log_info("Device Status Changed, type(%s) system_id(%s), detected_type(%d)",
+ type, pa_strempty(system_id), detected);
+
+ if (!device_type_is_valid(type)) {
+ pa_log_error("Invalid device type %s", type);
+ return -1;
+ } else if (device_type_is_equal(type, DEVICE_TYPE_BT_SCO)) {
+ device_set_detected(dm, type, name, system_id, detected);
+ if (detected == DEVICE_DISCONNECTED)
+ handle_device_disconnected(dm, type, system_id);
+ else
+ handle_device_connected(dm, type, name, system_id, detected);
+ } else if (device_type_is_need_detect(type)) {
+ device_set_detected(dm, type, name, system_id, detected);
+ if (detected == DEVICE_DISCONNECTED)
+ handle_device_disconnected(dm, type, system_id);
+ else
+ handle_device_connected(dm, type, name, system_id, detected);
+ } else {
+ pa_log_debug("No need to detect type %s", type);
+ }
+
+ return 0;
+}
+
+static int _translate_external_value(const char *type, int value, device_detected_type_t *detected) {
+
+ if (!type || !detected) {
+ pa_log_error("Invalid Parameter for translate");
+ return -1;
+ }
+
+ if (device_type_is_equal(DEVICE_TYPE_AUDIO_JACK, type)) {
+ if (value == EARJACK_DISCONNECTED)
+ *detected = DEVICE_DISCONNECTED;
+ else if (value == EARJACK_TYPE_SPK_ONLY)
+ *detected = DEVICE_CONNECTED_AUDIO_JACK_3P;
+ else if (value == EARJACK_TYPE_SPK_WITH_MIC)
+ *detected = DEVICE_CONNECTED_AUDIO_JACK_4P;
+ else
+ return -1;
+ } else if (device_type_is_equal(DEVICE_TYPE_HDMI, type)) {
+ if (value == HDMI_AUDIO_DISCONNECTED)
+ *detected = DEVICE_DISCONNECTED;
+ else if (value == HDMI_AUDIO_AVAILABLE)
+ *detected = DEVICE_CONNECTED;
+ else
+ return -1;
+ } else if (device_type_is_equal(DEVICE_TYPE_FORWARDING, type)) {
+ if (value == FORWARDING_DISCONNECTED)
+ *detected = DEVICE_DISCONNECTED;
+ else if (value == FORWARDING_CONNECTED)
+ *detected = DEVICE_CONNECTED;
+ else
+ return -1;
+ } else if (device_type_is_equal(DEVICE_TYPE_BT_SCO, type)) {
+ if (value == BT_SCO_DISCONNECTED)
+ *detected = DEVICE_DISCONNECTED;
+ else if (value == BT_SCO_CONNECTED)
+ *detected = DEVICE_CONNECTED_SCO;
+ else
+ return -1;
+ }
+
+ return 0;
+}
+
+static DBusHandlerResult dbus_filter_device_detect_handler(DBusConnection *c, DBusMessage *s, void *userdata) {
+ DBusError error;
+ int status = 0;
+ pa_device_manager *dm = (pa_device_manager *) userdata;
+ device_detected_type_t detected;
+
+ pa_assert(userdata);
+
+ if (dbus_message_get_type(s) != DBUS_MESSAGE_TYPE_SIGNAL)
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ pa_log_info("Device detect handler : Path(%s) Intf(%s) Member(%s) Signature(%s)",
+ dbus_message_get_path(s), dbus_message_get_interface(s), dbus_message_get_member(s), dbus_message_get_signature(s));
+
+ dbus_error_init(&error);
+
+ if (dbus_message_is_signal(s, DBUS_INTERFACE_DEVICED_SYSNOTI, "ChangedEarjack")) {
+ if (!dbus_message_get_args(s, NULL, DBUS_TYPE_INT32, &status, DBUS_TYPE_INVALID)) {
+ goto fail;
+ } else {
+ if (_translate_external_value(DEVICE_TYPE_AUDIO_JACK, status, &detected) < 0) {
+ pa_log_warn("failed to translate audio-jack detected value");
+ goto fail;
+ }
+ handle_device_status_changed(dm, DEVICE_TYPE_AUDIO_JACK, NULL, NULL, detected);
+ }
+ } else if (dbus_message_is_signal(s, DBUS_INTERFACE_DEVICED_SYSNOTI, "ChangedHDMIAudio")) {
+ if (!dbus_message_get_args(s, NULL, DBUS_TYPE_INT32, &status, DBUS_TYPE_INVALID)) {
+ goto fail;
+ } else {
+ if (_translate_external_value(DEVICE_TYPE_HDMI, status, &detected) < 0) {
+ pa_log_warn("failed to translate HDMI detected value");
+ goto fail;
+ }
+ handle_device_status_changed(dm, DEVICE_TYPE_HDMI, NULL, NULL, detected);
+ }
+ } else if (dbus_message_is_signal(s, DBUS_INTERFACE_MIRRORING_SERVER, "miracast_wfd_source_status_changed")) {
+ if (!dbus_message_get_args(s, NULL, DBUS_TYPE_INT32, &status, DBUS_TYPE_INVALID)) {
+ goto fail;
+ } else {
+ if (_translate_external_value(DEVICE_TYPE_FORWARDING, status, &detected) < 0) {
+ pa_log_warn("failed to translate forwarding detected value");
+ goto fail;
+ }
+ handle_device_status_changed(dm, DEVICE_TYPE_FORWARDING, NULL, NULL, detected);
+ }
+ } else if (dbus_message_is_signal(s, DBUS_INTERFACE_BLUEZ_HEADSET, "PropertyChanged")) {
+ DBusMessageIter msg_iter, variant_iter;
+ char *property_name;
+
+ pa_log_debug("Got %s PropertyChanged signal", DBUS_INTERFACE_BLUEZ_HEADSET);
+ dbus_message_iter_init(s, &msg_iter);
+ if (dbus_message_iter_get_arg_type(&msg_iter) != DBUS_TYPE_STRING) {
+ pa_log_error("Property name not string");
+ goto fail;
+ }
+ dbus_message_iter_get_basic(&msg_iter, &property_name);
+ pa_log_info("Changed Property name : %s", property_name);
+
+ if (!dbus_message_iter_next(&msg_iter)) {
+ pa_log_debug("Property value missing");
+ goto fail;
+ }
+
+ if (dbus_message_iter_get_arg_type(&msg_iter) != DBUS_TYPE_VARIANT) {
+ pa_log_debug("Property value not a variant.");
+ goto fail;
+ }
+
+ dbus_message_iter_recurse(&msg_iter, &variant_iter);
+
+ if (DBUS_TYPE_BOOLEAN == dbus_message_iter_get_arg_type(&variant_iter)) {
+ dbus_bool_t value;
+ char *name = NULL;
+ dbus_message_iter_get_basic(&variant_iter, &value);
+ if (pa_streq(property_name, "Connected")) {
+ pa_log_info("HFP Connection : %d", value);
+ if (value) {
+ method_call_bt_get_name(c, dbus_message_get_path(s), &name);
+ status = BT_SCO_CONNECTED;
+ } else {
+ status = BT_SCO_DISCONNECTED;
+ }
+ if (_translate_external_value(DEVICE_TYPE_BT_SCO, status, &detected) < 0) {
+ pa_log_warn("failed to translate bt-sco detected value");
+ goto fail;
+ }
+ handle_device_status_changed(dm, DEVICE_TYPE_BT_SCO,
+ name, dbus_message_get_path(s), detected);
+ } else if (pa_streq(property_name, "Playing")) {
+ pa_tz_device *device;
+ pa_log_info("SCO Playing : %d", value);
+ if ((device = device_list_get_device(dm, DEVICE_TYPE_BT_SCO, NULL)) != NULL) {
+ device->sco_opened = value;
+ if (value) {
+ /* update BT band/nrec information */
+ bool is_wide_band = false;
+ bool nrec = false;
+ pa_tz_device_sco_get_property(device, &is_wide_band, &nrec);
+ pa_log_info("got new wideband:%d, nrec:%d", is_wide_band, nrec);
+
+ UPDATE_HAL_ROUTE_OPTION(dm->hal_interface, NULL, "bt-wideband", is_wide_band);
+ UPDATE_HAL_ROUTE_OPTION(dm->hal_interface, NULL, "bt-nrec", nrec);
+ }
+ }
+ UPDATE_HAL_ROUTE_OPTION(dm->hal_interface, NULL, "bt-sco-ready", value);
+ }
+ }
+ } else {
+ pa_log_debug("Unknown message, not handle it");
+ dbus_error_free(&error);
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ pa_log_debug("Dbus Message handled");
+
+ dbus_error_free(&error);
+ return DBUS_HANDLER_RESULT_HANDLED;
+
+fail:
+ pa_log_error("Fail to handle dbus signal");
+ dbus_error_free(&error);
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static bool device_is_match_direction(pa_tz_device *device, int direction_mask) {
+ dm_device_direction_t direction;
+
+ if (direction_mask == DEVICE_IO_DIRECTION_FLAGS || direction_mask == 0)
+ return true;
+
+ direction = pa_tz_device_get_direction(device);
+
+ if ((direction_mask & DEVICE_IO_DIRECTION_IN_FLAG) && (direction & DM_DEVICE_DIRECTION_IN))
+ return true;
+ if ((direction_mask & DEVICE_IO_DIRECTION_OUT_FLAG) && (direction & DM_DEVICE_DIRECTION_OUT))
+ return true;
+ if ((direction_mask & DEVICE_IO_DIRECTION_BOTH_FLAG) && (direction == DM_DEVICE_DIRECTION_BOTH))
+ return true;
+
+ return false;
+}
+
+static bool device_is_match_state(pa_tz_device *device, int state_mask) {
+ dm_device_state_t state;
+
+ if (state_mask == DEVICE_STATE_FLAGS || state_mask == 0)
+ return true;
+
+ state = pa_tz_device_get_state(device);
+
+ if ((state_mask & DEVICE_STATE_DEACTIVATED_FLAG) && (state == DM_DEVICE_STATE_DEACTIVATED))
+ return true;
+ if ((state_mask & DEVICE_STATE_ACTIVATED_FLAG) && (state == DM_DEVICE_STATE_ACTIVATED))
+ return true;
+
+ return false;
+}
+
+static bool device_is_match_type(pa_tz_device *device, int type_mask) {
+ char *type;
+ bool is_builtin;
+
+ if (type_mask == DEVICE_TYPE_FLAGS || type_mask == 0)
+ return true;
+
+ type = pa_tz_device_get_type(device);
+ is_builtin = device_type_is_builtin(type);
+
+ if ((type_mask & DEVICE_TYPE_INTERNAL_FLAG) && is_builtin)
+ return true;
+ if ((type_mask & DEVICE_TYPE_EXTERNAL_FLAG) && !is_builtin)
+ return true;
+
+ return false;
+}
+
+static bool device_is_match_with_mask(pa_tz_device *device, int mask) {
+ pa_assert(device);
+
+ if (mask == DEVICE_ALL_FLAG)
+ return true;
+
+ return (device_is_match_direction(device, mask & DEVICE_IO_DIRECTION_FLAGS) &&
+ device_is_match_state(device, mask & DEVICE_STATE_FLAGS) &&
+ device_is_match_type(device, mask & DEVICE_TYPE_FLAGS));
+}
+
+static int method_call_bt_get_name(DBusConnection *conn, const char *device_path, char **name) {
+ const char *intf = DBUS_INTERFACE_BLUEZ_DEVICE, *prop = "Alias";
+ DBusMessage *msg, *reply;
+ DBusMessageIter reply_iter, variant_iter;
+ DBusError err;
+
+ pa_assert(conn);
+ pa_assert(device_path);
+ pa_assert(name);
+
+ if (!(msg = dbus_message_new_method_call(DBUS_SERVICE_BLUEZ, device_path, "org.freedesktop.DBus.Properties", "Get"))) {
+ pa_log_error("dbus method call failed");
+ return -1;
+ }
+
+ dbus_message_append_args(msg,
+ DBUS_TYPE_STRING, &intf,
+ DBUS_TYPE_STRING, &prop,
+ DBUS_TYPE_INVALID);
+
+ dbus_error_init(&err);
+ if (!(reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err))) {
+ pa_log_error("Failed to method call %s.%s, %s", DBUS_INTERFACE_BLUEZ_DEVICE, "Get", err.message);
+ dbus_error_free(&err);
+ return -1;
+ }
+
+ dbus_message_iter_init(reply, &reply_iter);
+
+ if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_VARIANT) {
+ pa_log_error("Cannot get reply argument");
+ return -1;
+ }
+
+ dbus_message_iter_recurse(&reply_iter, &variant_iter);
+
+ if (dbus_message_iter_get_arg_type(&variant_iter) == DBUS_TYPE_STRING) {
+ dbus_message_iter_get_basic(&variant_iter, name);
+ }
+
+ dbus_message_unref(reply);
+ return 0;
+}
+
+static void handle_get_connected_device_list(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ pa_device_manager *dm;
+ DBusMessage *reply = NULL;
+ DBusMessageIter msg_iter, array_iter, device_iter;
+ pa_tz_device *device;
+ dm_device_state_t state;
+ uint32_t device_idx;
+ dbus_int32_t device_id, direction;
+ int mask;
+ char *type, *name;
+ dbus_int32_t vendor_id, product_id;
+ dbus_bool_t is_running;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(userdata);
+
+
+ dm = (pa_device_manager*) userdata;
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_INT32, &mask,
+ DBUS_TYPE_INVALID));
+
+ pa_log_info("Get connected device list (mask : %d)", mask);
+
+ dbus_message_iter_init_append(reply, &msg_iter);
+ pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "(isiisiib)", &array_iter));
+
+ PA_IDXSET_FOREACH(device, dm->device_list, device_idx) {
+ device_id = (dbus_int32_t)pa_tz_device_get_id(device);
+ state = pa_tz_device_get_state(device);
+ direction = pa_tz_device_get_direction(device);
+ type = pa_tz_device_get_type(device);
+ name = pa_tz_device_get_name(device);
+ vendor_id = (dbus_int32_t) pa_tz_device_get_vendor_id(device);
+ product_id = (dbus_int32_t) pa_tz_device_get_product_id(device);
+ product_id = (dbus_int32_t) pa_tz_device_get_product_id(device);
+ is_running = (dbus_bool_t) pa_tz_device_is_running(device);
+ if (device_is_match_with_mask(device, mask)) {
+ simple_device_dump(PA_LOG_INFO, "[MATCH]", device_id, type, name, direction, state);
+ pa_assert_se(dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &device_iter));
+ dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &device_id);
+ dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_STRING, &type);
+ dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &direction);
+ dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &state);
+ dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_STRING, &name);
+ dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &vendor_id);
+ dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &product_id);
+ dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_BOOLEAN, &is_running);
+ pa_assert_se(dbus_message_iter_close_container(&array_iter, &device_iter));
+ } else {
+ simple_device_dump(PA_LOG_INFO, "[UNMATCH]", device_id, type, name, direction, state);
+ }
+ }
+
+ pa_assert_se(dbus_message_iter_close_container(&msg_iter, &array_iter));
+
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static void handle_get_device_by_id(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ pa_device_manager *manager;
+ DBusMessage *reply;
+ DBusMessageIter msg_iter;
+ pa_tz_device *device;
+ dbus_int32_t device_id;
+ dbus_int32_t id, direction, state;
+ dbus_int32_t vendor_id, product_id;
+ char *type, *name;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(userdata);
+
+ manager = (pa_device_manager*) userdata;
+
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_INT32, &device_id,
+ DBUS_TYPE_INVALID));
+
+ pa_log_info("Get device by id(%d)", device_id);
+
+ if ((device = device_list_get_device_by_id(manager, device_id))) {
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+ dbus_message_iter_init_append(reply, &msg_iter);
+
+ id = (dbus_int32_t)pa_tz_device_get_id(device);
+ state = pa_tz_device_get_state(device);
+ direction = pa_tz_device_get_direction(device);
+ type = pa_tz_device_get_type(device);
+ name = pa_tz_device_get_name(device);
+ vendor_id = (dbus_int32_t) pa_tz_device_get_vendor_id(device);
+ product_id = (dbus_int32_t) pa_tz_device_get_product_id(device);
+
+ simple_device_dump(PA_LOG_INFO, "[GET_BY_ID]", device_id, type, name, direction, state);
+
+ dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_INT32, &id);
+ dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &type);
+ dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_INT32, &direction);
+ dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_INT32, &state);
+ dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &name);
+ dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_INT32, &vendor_id);
+ dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_INT32, &product_id);
+
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+ } else {
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "%s", "org.tizen.multimedia.audio.Internal");
+ }
+}
+
+static void handle_is_stream_on_device(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ pa_device_manager *manager;
+ DBusMessage *reply;
+ pa_tz_device *device;
+ dbus_bool_t is_on = false;
+ dbus_int32_t stream_id, device_id;
+ pa_intset *stream_id_set;
+ int32_t stream_id_val;
+ int ret;
+ dm_device_state_t state;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(userdata);
+
+ pa_log_info("Is stream on device");
+
+ manager = (pa_device_manager*) userdata;
+
+
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_INT32, &stream_id,
+ DBUS_TYPE_INT32, &device_id,
+ DBUS_TYPE_INVALID));
+
+ if ((device = device_list_get_device_by_id(manager, device_id))) {
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+
+ state = pa_tz_device_get_state(device);
+ if (state == DM_DEVICE_STATE_ACTIVATED) {
+ stream_id_set = pa_tz_device_get_stream_list(device);
+ PA_INTSET_FOREACH(stream_id_val, stream_id_set, ret) {
+ if (stream_id_val == stream_id) {
+ is_on = true;
+ pa_log_info("stream(%d) is on device(%d)", stream_id, device_id);
+ break;
+ }
+ }
+ pa_intset_free(stream_id_set);
+ } else {
+ pa_log_info("device(%d) is not activated, regard as no stream on it", device_id);
+ is_on = false;
+ }
+
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &is_on,
+ DBUS_TYPE_INVALID));
+
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+ } else {
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.Internal");
+ }
+}
+
+static void handle_get_bt_a2dp_status(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ pa_device_manager *dm;
+ DBusMessage *reply = NULL;
+ pa_tz_device *device;
+ dbus_bool_t is_bt_on = false;
+ const char *bt_name = "none";
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(userdata);
+
+ pa_log_info("Get BT A2DP list");
+
+ dm = (pa_device_manager*) userdata;
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+
+ /* FIXME : Give system_id for multi device */
+ if ((device = device_list_get_device(dm, DEVICE_TYPE_BT_A2DP, NULL)) != NULL) {
+ is_bt_on = true;
+ bt_name = pa_tz_device_get_name(device);
+ }
+
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &is_bt_on,
+ DBUS_TYPE_STRING, &bt_name,
+ DBUS_TYPE_INVALID));
+
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static void handle_load_sink(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ pa_device_manager *dm;
+ char *type, *role;
+ DBusMessage *reply = NULL;
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+ dm = (pa_device_manager *) userdata;
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_STRING, &type,
+ DBUS_TYPE_STRING, &role,
+ DBUS_TYPE_INVALID));
+
+ pa_device_manager_load_sink(dm, type, role);
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static void handle_unload_sink(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ pa_device_manager *dm;
+ char *type, *role;
+ DBusMessage *reply = NULL;
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+ dm = (pa_device_manager *) userdata;
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_STRING, &type,
+ DBUS_TYPE_STRING, &role,
+ DBUS_TYPE_INVALID));
+
+ pa_device_manager_unload_sink(dm, type, role);
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static void handle_unload_sink_with_device_string(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ pa_device_manager *dm;
+ char *device_string;
+ DBusMessage *reply = NULL;
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+ dm = (pa_device_manager *) userdata;
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_STRING, &device_string,
+ DBUS_TYPE_INVALID));
+
+ pa_device_manager_unload_sink_with_device_string(dm, device_string);
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static void handle_get_device_string(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ pa_device_manager *dm;
+ char *type, *role;
+ const char *device_string;
+ dbus_bool_t is_playback;
+ DBusMessage *reply;
+
+ dm = (pa_device_manager *) userdata;
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_BOOLEAN, &is_playback,
+ DBUS_TYPE_STRING, &type,
+ DBUS_TYPE_STRING, &role,
+ DBUS_TYPE_INVALID));
+
+ device_string = pa_device_manager_get_device_string(dm, is_playback, type, role);
+ if (device_string == NULL) {
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "%s", "org.tizen.multimedia.audio.Internal");
+ return;
+ }
+
+ pa_log_info("device string : %s", device_string);
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &device_string,
+ DBUS_TYPE_INVALID));
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static void handle_dump_device_list(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ pa_device_manager *dm;
+ pa_tz_device *device;
+ uint32_t device_idx;
+ DBusMessage *reply = NULL;
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+ dm = (pa_device_manager *) userdata;
+
+ PA_IDXSET_FOREACH(device, dm->device_list, device_idx) {
+ pa_tz_device_dump_info(device, PA_LOG_INFO);
+ }
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static bool is_usb_output_device(pa_tz_device *device) {
+ char *type;
+ dm_device_direction_t direction;
+ pa_sink *sink;
+
+ pa_assert(device);
+
+ type = pa_tz_device_get_type(device);
+ if (!pa_streq(type, DEVICE_TYPE_USB_AUDIO)) {
+ pa_log_error("device(id:%d, %s) is not USB AUDIO type", pa_tz_device_get_id(device), type);
+ return false;
+ }
+ direction = pa_tz_device_get_direction(device);
+ if (direction & DM_DEVICE_DIRECTION_OUT) {
+ if (!(sink = pa_tz_device_get_sink(device, DEVICE_ROLE_NORMAL))) {
+ pa_log_error("sink is null");
+ return false;
+ }
+ } else {
+ pa_log_error("this device is not for output");
+ return false;
+ }
+
+ return true;
+}
+
+
+static bool is_supported_sample_format(pa_sample_format_t *supported_sample_formats, pa_sample_format_t sample_format) {
+ int i;
+
+ pa_assert(supported_sample_formats);
+ pa_assert(sample_format != PA_SAMPLE_INVALID);
+
+ for (i = 0; supported_sample_formats[i] != PA_SAMPLE_MAX; i++) {
+ if (supported_sample_formats[i] == sample_format) {
+ pa_log_info("%s is supported", pa_sample_format_to_string(sample_format));
+ return true;
+ }
+ }
+ pa_log_error("%s is not supported", pa_sample_format_to_string(sample_format));
+ return false;
+}
+
+static void handle_get_supported_sample_formats(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ pa_device_manager *dm;
+ DBusMessage *reply = NULL;
+ DBusMessageIter msg_iter, array_iter, item_iter;
+ dbus_int32_t device_id;
+ pa_tz_device *device;
+ pa_sink *sink;
+ const char *format;
+ int i;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(userdata);
+
+ dm = (pa_device_manager *)userdata;
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_INT32, &device_id,
+ DBUS_TYPE_INVALID));
+
+ pa_log_info("Get supported sample formats of the device(id:%d)", device_id);
+
+ if (!(device = device_list_get_device_by_id(dm, device_id))) {
+ pa_log_error("could not find any device with id:%d", device_id);
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
+ return;
+ }
+ if (!is_usb_output_device(device)) {
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_NOT_SUPPORTED, "%s", "org.tizen.multimedia.audio.PolicyInternal");
+ return;
+ }
+ if (!(sink = pa_tz_device_get_sink(device, DEVICE_ROLE_NORMAL))) {
+ pa_log_error("could not get sink for normal role");
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
+ return;
+ }
+
+ dbus_message_iter_init_append(reply, &msg_iter);
+ pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "(s)", &array_iter));
+ for (i = 0; sink->supported_sample_formats[i] != PA_SAMPLE_MAX; i++) {
+ format = pa_sample_format_to_string(sink->supported_sample_formats[i]);
+ pa_log_info("%s is supported", format);
+ pa_assert_se(dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &item_iter));
+ dbus_message_iter_append_basic(&item_iter, DBUS_TYPE_STRING, &format);
+ pa_assert_se(dbus_message_iter_close_container(&array_iter, &item_iter));
+ }
+ pa_assert_se(dbus_message_iter_close_container(&msg_iter, &array_iter));
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static void handle_set_sample_format(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ pa_device_manager *dm;
+ DBusMessage *reply = NULL;
+ dbus_int32_t device_id;
+ char *sample_format;
+ pa_sample_format_t prev_selected_sample_format;
+ pa_tz_device *device;
+ pa_sink *sink;
+ pa_sample_spec spec;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(userdata);
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+ dm = (pa_device_manager *)userdata;
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_INT32, &device_id,
+ DBUS_TYPE_STRING, &sample_format,
+ DBUS_TYPE_INVALID));
+
+ pa_log_info("Set sample format(%s) of the device(id:%d)", sample_format, device_id);
+
+ if (!(device = device_list_get_device_by_id(dm, device_id))) {
+ pa_log_error("could not find any device with id:%d", device_id);
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
+ return;
+ }
+ if (!is_usb_output_device(device)) {
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_NOT_SUPPORTED, "%s", "org.tizen.multimedia.audio.PolicyInternal");
+ return;
+ }
+ if (!(sink = pa_tz_device_get_sink(device, DEVICE_ROLE_NORMAL))) {
+ pa_log_error("could not get sink for normal role");
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
+ return;
+ }
+
+ /* use a supported sample format selected by user */
+ if (!is_supported_sample_format(sink->supported_sample_formats, pa_parse_sample_format(sample_format))) {
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
+ return;
+ }
+ prev_selected_sample_format = sink->selected_sample_format;
+ sink->selected_sample_format = pa_parse_sample_format(sample_format);
+
+ FILL_SAMPLE_SPEC_WITH_SELECTED(spec, sink);
+ if (pa_sink_reconfigure(sink, &spec, false) == -1) {
+ pa_log_error("failed to reconfigure");
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "%s", "org.tizen.multimedia.audio.Internal");
+ sink->selected_sample_format = prev_selected_sample_format;
+ return;
+ }
+
+ save_preference(dm, sink);
+
+ pa_log_info("Set sample format(%s) of the device(id:%d) successfully", sample_format, device_id);
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static void handle_get_sample_format(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ pa_device_manager *dm;
+ DBusMessage *reply = NULL;
+ dbus_int32_t device_id;
+ pa_tz_device *device;
+ pa_sink *sink;
+ const char *format;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(userdata);
+
+ dm = (pa_device_manager *)userdata;
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_INT32, &device_id,
+ DBUS_TYPE_INVALID));
+
+ pa_log_info("Get sample format of the device(id:%d)", device_id);
+
+ if (!(device = device_list_get_device_by_id(dm, device_id))) {
+ pa_log_error("could not find any device with id:%d", device_id);
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
+ return;
+ }
+ if (!is_usb_output_device(device)) {
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_NOT_SUPPORTED, "%s", "org.tizen.multimedia.audio.PolicyInternal");
+ return;
+ }
+ if (!(sink = pa_tz_device_get_sink(device, DEVICE_ROLE_NORMAL))) {
+ pa_log_error("could not get sink for normal role");
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
+ return;
+ }
+
+ format = pa_sample_format_to_string(sink->selected_sample_format);
+ pa_log_info("Get sample format(%s) of the device(id:%d) successfully", format, device_id);
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &format, DBUS_TYPE_INVALID));
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static bool is_supported_sample_rate(uint32_t *supported_sample_rates, uint32_t sample_rate) {
+ int i;
+
+ pa_assert(supported_sample_rates);
+
+ for (i = 0; supported_sample_rates[i]; i++) {
+ if (supported_sample_rates[i] == sample_rate) {
+ pa_log_info("%u is supported", sample_rate);
+ return true;
+ }
+ }
+ pa_log_error("%u is not supported", sample_rate);
+ return false;
+}
+
+static void handle_get_supported_sample_rates(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ pa_device_manager *dm;
+ DBusMessage *reply = NULL;
+ DBusMessageIter msg_iter, array_iter, item_iter;
+ dbus_int32_t device_id;
+ pa_tz_device *device;
+ pa_sink *sink;
+ int i;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(userdata);
+
+ dm = (pa_device_manager *)userdata;
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_INT32, &device_id,
+ DBUS_TYPE_INVALID));
+
+ pa_log_info("Get supported sample rates of the device(id:%d)", device_id);
+
+ if (!(device = device_list_get_device_by_id(dm, device_id))) {
+ pa_log_error("could not find any device with id:%d", device_id);
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
+ return;
+ }
+ if (!is_usb_output_device(device)) {
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_NOT_SUPPORTED, "%s", "org.tizen.multimedia.audio.PolicyInternal");
+ return;
+ }
+ if (!(sink = pa_tz_device_get_sink(device, DEVICE_ROLE_NORMAL))) {
+ pa_log_error("could not get sink for normal role");
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
+ return;
+ }
+
+ dbus_message_iter_init_append(reply, &msg_iter);
+ pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "(u)", &array_iter));
+ for (i = 0; sink->supported_sample_rates[i]; i++) {
+ pa_log_info("%u is supported", sink->supported_sample_rates[i]);
+ pa_assert_se(dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &item_iter));
+ dbus_message_iter_append_basic(&item_iter, DBUS_TYPE_UINT32, &sink->supported_sample_rates[i]);
+ pa_assert_se(dbus_message_iter_close_container(&array_iter, &item_iter));
+ }
+ pa_assert_se(dbus_message_iter_close_container(&msg_iter, &array_iter));
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static void handle_set_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ pa_device_manager *dm;
+ DBusMessage *reply = NULL;
+ dbus_int32_t device_id;
+ dbus_uint32_t sample_rate;
+ uint32_t prev_selected_sample_rate;
+ pa_tz_device *device;
+ pa_sink *sink;
+ pa_sample_spec spec;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(userdata);
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+ dm = (pa_device_manager *)userdata;
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_INT32, &device_id,
+ DBUS_TYPE_UINT32, &sample_rate,
+ DBUS_TYPE_INVALID));
+
+ pa_log_info("Set sample rate(%u) of the device(id:%d)", sample_rate, device_id);
+
+ if (!(device = device_list_get_device_by_id(dm, device_id))) {
+ pa_log_error("could not find any device with id:%d", device_id);
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
+ return;
+ }
+ if (!is_usb_output_device(device)) {
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_NOT_SUPPORTED, "%s", "org.tizen.multimedia.audio.PolicyInternal");
+ return;
+ }
+ if (!(sink = pa_tz_device_get_sink(device, DEVICE_ROLE_NORMAL))) {
+ pa_log_error("could not get sink for normal role");
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
+ return;
+ }
+
+ /* use a supported sample rate selected by user */
+ if (!is_supported_sample_rate(sink->supported_sample_rates, sample_rate)) {
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
+ return;
+ }
+ prev_selected_sample_rate = sink->selected_sample_rate;
+ sink->selected_sample_rate = sample_rate;
+
+ FILL_SAMPLE_SPEC_WITH_SELECTED(spec, sink);
+ if (pa_sink_reconfigure(sink, &spec, false) == -1) {
+ pa_log_error("failed to reconfigure");
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "%s", "org.tizen.multimedia.audio.Internal");
+ sink->selected_sample_rate = prev_selected_sample_rate;
+ return;
+ }
+
+ save_preference(dm, sink);
+
+ pa_log_info("Set sample rate(%u) of the device(id:%d) successfully", sample_rate, device_id);
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static void handle_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ pa_device_manager *dm;
+ DBusMessage *reply = NULL;
+ dbus_int32_t device_id;
+ pa_tz_device *device;
+ pa_sink *sink;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(userdata);
+
+ dm = (pa_device_manager *)userdata;
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_INT32, &device_id,
+ DBUS_TYPE_INVALID));
+
+ pa_log_info("Get sample rate of the device(id:%d)", device_id);
+
+ if (!(device = device_list_get_device_by_id(dm, device_id))) {
+ pa_log_error("could not find any device with id:%d", device_id);
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
+ return;
+ }
+ if (!is_usb_output_device(device)) {
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_NOT_SUPPORTED, "%s", "org.tizen.multimedia.audio.PolicyInternal");
+ return;
+ }
+ if (!(sink = pa_tz_device_get_sink(device, DEVICE_ROLE_NORMAL))) {
+ pa_log_error("could not get sink for normal role");
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
+ return;
+ }
+
+ pa_log_info("Get sample rate(%u) of the device(id:%d) successfully", sink->selected_sample_rate, device_id);
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_UINT32, &sink->selected_sample_rate, DBUS_TYPE_INVALID));
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static void handle_set_specific_stream_only(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ pa_device_manager *dm;
+ DBusMessage *reply = NULL;
+ dbus_int32_t device_id;
+ char *stream_role;
+ pa_tz_device *device;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(userdata);
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+ dm = (pa_device_manager *)userdata;
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_INT32, &device_id,
+ DBUS_TYPE_STRING, &stream_role,
+ DBUS_TYPE_INVALID));
+
+ pa_log_info("Set the device(id:%d) only for the stream role(%s)", device_id, stream_role);
+
+ if (!(device = device_list_get_device_by_id(dm, device_id))) {
+ pa_log_error("could not find any device with id:%d", device_id);
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
+ return;
+ }
+ if (!is_usb_output_device(device)) {
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_NOT_SUPPORTED, "%s", "org.tizen.multimedia.audio.PolicyInternal");
+ return;
+ }
+ if (!pa_stream_manager_is_valid_stream_role(dm->core, stream_role)) {
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_NOT_SUPPORTED, "%s", "org.tizen.multimedia.audio.InvalidArgument");
+ return;
+ }
+
+ device->specified_stream_role = stream_role;
+
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static void handle_get_specified_stream(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ pa_device_manager *dm;
+ DBusMessage *reply = NULL;
+ dbus_int32_t device_id;
+ char *specified_stream_role;
+ pa_tz_device *device;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(userdata);
+
+ dm = (pa_device_manager *)userdata;
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_INT32, &device_id,
+ DBUS_TYPE_INVALID));
+
+ pa_log_info("Get specified stream role for the device(id:%d)", device_id);
+
+ if (!(device = device_list_get_device_by_id(dm, device_id))) {
+ pa_log_error("could not find any device with id:%d", device_id);
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
+ return;
+ }
+ if (!is_usb_output_device(device)) {
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_NOT_SUPPORTED, "%s", "org.tizen.multimedia.audio.PolicyInternal");
+ return;
+ }
+
+ specified_stream_role = device->specified_stream_role;
+
+ pa_log_info("stream role(%s) is specified for the device(id:%d)", device->specified_stream_role, device_id);
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &specified_stream_role, DBUS_TYPE_INVALID));
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static void handle_set_avoid_resampling(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ pa_device_manager *dm;
+ DBusMessage *reply = NULL;
+ dbus_int32_t device_id;
+ dbus_bool_t avoid_resampling;
+ pa_tz_device *device;
+ pa_sink *sink;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(userdata);
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+ dm = (pa_device_manager *)userdata;
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_INT32, &device_id,
+ DBUS_TYPE_BOOLEAN, &avoid_resampling,
+ DBUS_TYPE_INVALID));
+
+ pa_log_info("Set the device(id:%d) avoid-resampling(%d)", device_id, avoid_resampling);
+
+ if (!(device = device_list_get_device_by_id(dm, device_id))) {
+ pa_log_error("could not find any device with id:%d", device_id);
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
+ return;
+ }
+ if (!is_usb_output_device(device)) {
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_NOT_SUPPORTED, "%s", "org.tizen.multimedia.audio.PolicyInternal");
+ return;
+ }
+ if (!(sink = pa_tz_device_get_sink(device, DEVICE_ROLE_NORMAL))) {
+ pa_log_error("could not get sink for normal role");
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
+ return;
+ }
+ if (sink->avoid_resampling == avoid_resampling) {
+ pa_log_info("already set to %d", avoid_resampling);
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+ return;
+ }
+
+ sink->avoid_resampling = avoid_resampling;
+
+ save_preference(dm, sink);
+
+ pa_log_info("Set avoid-resampling(%d) to the device(id:%d)", avoid_resampling, device_id);
+
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static void handle_get_avoid_resampling(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ pa_device_manager *dm;
+ DBusMessage *reply = NULL;
+ dbus_int32_t device_id;
+ dbus_bool_t avoid_resampling;
+ pa_tz_device *device;
+ pa_sink *sink;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(userdata);
+
+ dm = (pa_device_manager *)userdata;
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+
+ pa_assert_se(dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_INT32, &device_id,
+ DBUS_TYPE_INVALID));
+
+ pa_log_info("Get avoid-resampling of the device(id:%d)", device_id);
+
+ if (!(device = device_list_get_device_by_id(dm, device_id))) {
+ pa_log_error("could not find any device with id:%d", device_id);
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
+ return;
+ }
+ if (!is_usb_output_device(device)) {
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_NOT_SUPPORTED, "%s", "org.tizen.multimedia.audio.PolicyInternal");
+ return;
+ }
+ if (!(sink = pa_tz_device_get_sink(device, DEVICE_ROLE_NORMAL))) {
+ pa_log_error("could not get sink for normal role");
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
+ return;
+ }
+
+ avoid_resampling = sink->avoid_resampling;
+ pa_log_info("got avoid-resampling(%d) of the device(id:%d)", avoid_resampling, device_id);
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+ pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &avoid_resampling, DBUS_TYPE_INVALID));
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static void handle_test_device_status_change(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ pa_device_manager *dm = (pa_device_manager *)userdata;
+ char *type;
+ dbus_int32_t status;
+ DBusMessage *reply = NULL;
+ DBusError error;
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+
+ dbus_error_init(&error);
+ if (!dbus_message_get_args(msg, NULL,
+ DBUS_TYPE_STRING, &type,
+ DBUS_TYPE_INT32, &status,
+ DBUS_TYPE_INVALID)) {
+ pa_log_error("failed to get dbus args : %s", error.message);
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
+ dbus_error_free(&error);
+ }
+
+ pa_log_debug("handle_test_device_status_change, type:%s, status:%d", type, status);
+
+ handle_device_status_changed(dm, type, NULL, NULL, status);
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+}
+
+static DBusHandlerResult handle_introspect(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ const char *xml = DEVICE_MANAGER_INTROSPECT_XML;
+ DBusMessage *r = NULL;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(userdata);
+
+ pa_assert_se(r = dbus_message_new_method_return(msg));
+ pa_assert_se(dbus_message_append_args(r, DBUS_TYPE_STRING, &xml, DBUS_TYPE_INVALID));
+
+ if (r) {
+ pa_assert_se(dbus_connection_send((conn), r, NULL));
+ dbus_message_unref(r);
+ }
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult handle_device_manager_methods(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+ int method_idx = 0;
+
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(userdata);
+
+ for (method_idx = 0; method_idx < METHOD_HANDLER_MAX; method_idx++) {
+ if (dbus_message_is_method_call(msg, DBUS_INTERFACE_DEVICE_MANAGER, method_handlers[method_idx].method_name)) {
+ method_handlers[method_idx].receive_cb(conn, msg, userdata);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static DBusHandlerResult method_call_handler(DBusConnection *c, DBusMessage *m, void *userdata) {
+ struct userdata *u = userdata;
+ const char *path, *interface, *member;
+
+ pa_assert(c);
+ pa_assert(m);
+ pa_assert(u);
+
+ path = dbus_message_get_path(m);
+ interface = dbus_message_get_interface(m);
+ member = dbus_message_get_member(m);
+
+ pa_log_info("DeviceManager Method Call Handler : path=%s, interface=%s, member=%s", path, interface, member);
+
+ if (!pa_streq(path, DBUS_OBJECT_DEVICE_MANAGER))
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ if (dbus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
+ return handle_introspect(c, m, u);
+ /*
+ } else if (dbus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "Get")) {
+ return handle_get_property(c, m, u);
+ } else if (dbus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "Set")) {
+ return handle_set_property(c, m, u);
+ } else if (dbus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "GetAll")) {
+ return handle_get_all_property(c, m, u);
+ */
+ } else {
+ return handle_device_manager_methods(c, m, u);
+ }
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static void fill_signal_msg_with_device(const char *description, DBusMessageIter *msg_iter, uint32_t event_id, pa_tz_device *device) {
+ DBusMessageIter array_iter, device_iter;
+ char *type, *name;
+ dbus_int32_t device_id, direction, state, stream_id;
+ dbus_int32_t vendor_id, product_id;
+ dbus_bool_t is_running;
+ pa_intset *stream_id_set = NULL;
+ int32_t stream_id_val;
+ int ret;
+
+ pa_assert(msg_iter);
+ pa_assert(device);
+
+ dbus_message_iter_append_basic(msg_iter, DBUS_TYPE_UINT32, &event_id);
+ pa_assert_se(dbus_message_iter_open_container(msg_iter, DBUS_TYPE_STRUCT, NULL, &device_iter));
+
+ direction = (dbus_int32_t)pa_tz_device_get_direction(device);
+ type = pa_tz_device_get_type(device);
+ name = pa_tz_device_get_name(device);
+ device_id = (dbus_int32_t)pa_tz_device_get_id(device);
+ state = pa_tz_device_get_state(device);
+ vendor_id = (dbus_int32_t)pa_tz_device_get_vendor_id(device);
+ product_id = (dbus_int32_t)pa_tz_device_get_product_id(device);
+ is_running = (dbus_bool_t)pa_tz_device_is_running(device);
+
+ simple_device_dump(PA_LOG_INFO, description, device_id, type, name, direction, state);
+
+ dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &device_id);
+ dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_STRING, &type);
+ dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &direction);
+ dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &state);
+ dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_STRING, &name);
+ dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &vendor_id);
+ dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &product_id);
+ dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_BOOLEAN, &is_running);
+ if (state == DM_DEVICE_STATE_ACTIVATED)
+ stream_id_set = pa_tz_device_get_stream_list(device);
+ pa_assert_se(dbus_message_iter_open_container(&device_iter, DBUS_TYPE_ARRAY, "i", &array_iter));
+ if (state == DM_DEVICE_STATE_ACTIVATED) {
+ PA_INTSET_FOREACH(stream_id_val, stream_id_set, ret) {
+ stream_id = stream_id_val;
+ dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_INT32, &stream_id);
+ }
+ }
+ pa_assert_se(dbus_message_iter_close_container(&device_iter, &array_iter));
+ if (stream_id_set)
+ pa_intset_free(stream_id_set);
+ pa_assert_se(dbus_message_iter_close_container(msg_iter, &device_iter));
+ pa_log_info("end of fill signal msg");
+}
+
+void send_device_connection_changed_signal(uint32_t event_id, pa_tz_device *device, bool connected, pa_device_manager *dm) {
+ DBusMessage *signal_msg;
+ DBusMessageIter msg_iter;
+ dbus_bool_t _connected = connected;
+
+ pa_assert(device);
+ pa_assert(dm);
+
+ pa_log_info("Send device connection changed signal, event_id(%u)", event_id);
+
+ pa_assert_se(signal_msg = dbus_message_new_signal(DBUS_OBJECT_DEVICE_MANAGER, DBUS_INTERFACE_DEVICE_MANAGER, "DeviceConnected"));
+ dbus_message_iter_init_append(signal_msg, &msg_iter);
+ fill_signal_msg_with_device(connected ? "[Connected]" : "[Disconnected]", &msg_iter, event_id, device);
+
+ dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_BOOLEAN, &_connected);
+
+ pa_assert_se(dbus_connection_send(pa_dbus_connection_get(dm->dbus_conn), signal_msg, NULL));
+
+ dbus_message_unref(signal_msg);
+ pa_log_info("end of send device connection changed signal");
+}
+
+void send_device_info_changed_signal(uint32_t event_id, pa_tz_device *device, int changed_type, pa_device_manager *dm) {
+ DBusMessage *signal_msg;
+ DBusMessageIter msg_iter;
+ const char *changed_prefix[] = {"[State Changed]", "[Direction Changed]", "[Avail-Mode Changed]"};
+
+ pa_assert(device);
+ pa_assert(dm);
+
+ pa_log_debug("Send device info changed signal, event_id(%u)", event_id);
+
+ pa_assert_se(signal_msg = dbus_message_new_signal(DBUS_OBJECT_DEVICE_MANAGER, DBUS_INTERFACE_DEVICE_MANAGER, "DeviceInfoChanged"));
+ dbus_message_iter_init_append(signal_msg, &msg_iter);
+ fill_signal_msg_with_device(changed_prefix[changed_type], &msg_iter, event_id, device);
+ dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_INT32, &changed_type);
+
+ pa_assert_se(dbus_connection_send(pa_dbus_connection_get(dm->dbus_conn), signal_msg, NULL));
+
+ dbus_message_unref(signal_msg);
+}
+
+void send_device_state_changed_signal(uint32_t event_id, pa_tz_device *device, bool activated, pa_device_manager *dm) {
+ DBusMessage *signal_msg;
+ DBusMessageIter msg_iter;
+
+ pa_assert(device);
+ pa_assert(dm);
+
+ pa_log_debug("Send device state changed signal, event_id(%u)", event_id);
+
+ pa_assert_se(signal_msg = dbus_message_new_signal(DBUS_OBJECT_DEVICE_MANAGER, DBUS_INTERFACE_DEVICE_MANAGER, "DeviceStateChanged"));
+ dbus_message_iter_init_append(signal_msg, &msg_iter);
+ fill_signal_msg_with_device(activated ? "[Activated]" : "[Deactivated]", &msg_iter, event_id, device);
+
+ pa_assert_se(dbus_connection_send(pa_dbus_connection_get(dm->dbus_conn), signal_msg, NULL));
+
+ dbus_message_unref(signal_msg);
+}
+
+void send_device_running_changed_signal(uint32_t event_id, pa_tz_device *device, bool is_running, pa_device_manager *dm) {
+ DBusMessage *signal_msg;
+ DBusMessageIter msg_iter;
+
+ pa_assert(device);
+ pa_assert(dm);
+
+ pa_log_debug("Send device running changed signal, event_id(%u)", event_id);
+
+ pa_assert_se(signal_msg = dbus_message_new_signal(DBUS_OBJECT_DEVICE_MANAGER, DBUS_INTERFACE_DEVICE_MANAGER, "DeviceRunningChanged"));
+ dbus_message_iter_init_append(signal_msg, &msg_iter);
+ fill_signal_msg_with_device(is_running ? "[Running]" : "[NotRunning]", &msg_iter, event_id, device);
+
+ pa_assert_se(dbus_connection_send(pa_dbus_connection_get(dm->dbus_conn), signal_msg, NULL));
+
+ dbus_message_unref(signal_msg);
+}
+
+static void endpoint_init(pa_device_manager *dm) {
+ static const DBusObjectPathVTable vtable_endpoint = {
+ .message_function = method_call_handler,
+ };
+
+ pa_log_info("Device manager dbus endpoint init");
+
+ if (dm && dm->dbus_conn) {
+ if (!dbus_connection_register_object_path(pa_dbus_connection_get(dm->dbus_conn), DBUS_OBJECT_DEVICE_MANAGER, &vtable_endpoint, dm))
+ pa_log_error("Failed to register object path");
+ } else {
+ pa_log_error("Cannot get dbus connection to register object path");
+ }
+}
+
+static void endpoint_done(pa_device_manager *dm) {
+ pa_log_info("Device manager dbus endpoint done");
+ if (dm && dm->dbus_conn) {
+ if (!dbus_connection_unregister_object_path(pa_dbus_connection_get(dm->dbus_conn), DBUS_OBJECT_DEVICE_MANAGER))
+ pa_log_error("Failed to unregister object path");
+ } else {
+ pa_log_error("Cannot get dbus connection to unregister object path");
+ }
+}
+
+static int watch_signals(pa_device_manager *dm) {
+ DBusError error;
+
+ pa_assert(dm);
+ pa_assert(dm->dbus_conn);
+
+ dbus_error_init(&error);
+
+ pa_log_info("Watch Dbus signals");
+
+ if (!dbus_connection_add_filter(pa_dbus_connection_get(dm->dbus_conn), dbus_filter_device_detect_handler, dm, NULL)) {
+ pa_log_error("Unable to add D-Bus filter : %s: %s", error.name, error.message);
+ goto fail;
+ }
+
+ if (pa_dbus_add_matches(pa_dbus_connection_get(dm->dbus_conn), &error, FILTER_DEVICED_SYSNOTI, FILTER_SOUND_SERVER, FILTER_BLUEZ, FILTER_MIRRORING, NULL) < 0) {
+ pa_log_error("Unable to subscribe to signals: %s: %s", error.name, error.message);
+ goto fail;
+ }
+ return 0;
+
+fail:
+ dbus_error_free(&error);
+ return -1;
+}
+
+static void unwatch_signals(pa_device_manager *dm) {
+ pa_log_info("Unwatch Dbus signals");
+
+ pa_assert(dm);
+ pa_assert(dm->dbus_conn);
+
+ pa_dbus_remove_matches(pa_dbus_connection_get(dm->dbus_conn), FILTER_DEVICED_SYSNOTI, FILTER_SOUND_SERVER, FILTER_BLUEZ, FILTER_MIRRORING, NULL);
+ dbus_connection_remove_filter(pa_dbus_connection_get(dm->dbus_conn), dbus_filter_device_detect_handler, dm);
+}
+
+void init_dm_dbus(pa_device_manager *dm) {
+ DBusError error;
+ pa_dbus_connection *connection = NULL;
+
+ pa_assert(dm);
+ pa_log_info("init Dbus");
+ dbus_error_init(&error);
+
+ if (!(connection = pa_dbus_bus_get(dm->core, DBUS_BUS_SYSTEM, &error)) || dbus_error_is_set(&error)) {
+ if (connection) {
+ pa_dbus_connection_unref(connection);
+ }
+ pa_log_error("Unable to contact D-Bus system bus: %s: %s", error.name, error.message);
+ goto fail;
+ } else {
+ pa_log_info("Got dbus connection");
+ }
+
+ dm->dbus_conn = connection;
+
+ if (watch_signals(dm) < 0)
+ pa_log_error("dbus watch signals failed");
+ else
+ pa_log_debug("dbus ready to get signals");
+
+ endpoint_init(dm);
+
+fail:
+ dbus_error_free(&error);
+}
+
+void deinit_dm_dbus(pa_device_manager *dm) {
+ pa_assert(dm);
+
+ pa_log_info("deinit Dbus");
+
+ endpoint_done(dm);
+ unwatch_signals(dm);
+
+ if (dm->dbus_conn) {
+ pa_dbus_connection_unref(dm->dbus_conn);
+ dm->dbus_conn = NULL;
+ }
+}
+#endif
\ No newline at end of file
#include "stream-manager.h"
#include "device-manager.h"
#include "device-manager-priv.h"
+#include "device-manager-dbus-priv.h"
#include "device-manager-db-priv.h"
#define SHARED_DEVICE_MANAGER "tizen-device-manager"
#define DEVICE_CLASS_SOUND "sound"
#define DEVICE_CLASS_MONITOR "monitor"
-/* Dbus defines */
-#define DBUS_INTERFACE_DEVICE_MANAGER "org.pulseaudio.DeviceManager"
-#define DBUS_OBJECT_DEVICE_MANAGER "/org/pulseaudio/DeviceManager"
-
-#define DBUS_INTERFACE_DEVICED_SYSNOTI "org.tizen.system.deviced.SysNoti"
-#define DBUS_OBJECT_DEVICED_SYSNOTI "/Org/Tizen/System/DeviceD/SysNoti"
-
-#define DBUS_INTERFACE_SOUND_SERVER "org.tizen.SoundServer1"
-#define DBUS_OBJECT_SOUND_SERVER "/org/tizen/SoundServer1"
-
-#define DBUS_SERVICE_BLUEZ "org.bluez"
-#define DBUS_INTERFACE_BLUEZ_HEADSET "org.bluez.Headset"
-#define DBUS_INTERFACE_BLUEZ_DEVICE "org.bluez.Device1"
-#define DBUS_OBJECT_BLUEZ "/org/bluez"
-
-#define DBUS_INTERFACE_MIRRORING_SERVER "org.tizen.scmirroring.server"
-#define DBUS_OBJECT_MIRRORING_SERVER "/org/tizen/scmirroring/server"
-
-#define DBUS_SERVICE_HFP_AGENT "org.bluez.ag_agent"
-#define DBUS_OBJECT_HFP_AGENT "/org/bluez/hfp_agent"
-#define DBUS_INTERFACE_HFP_AGENT "Org.Hfp.App.Interface"
-
-#define DEVICE_MANAGER_INTROSPECT_XML \
- DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
- "<node>\n" \
- " <interface name=\"" DBUS_INTERFACE_DEVICE_MANAGER "\">\n" \
- " <method name=\"GetConnectedDeviceList\">\n" \
- " <arg name=\"mask_flags\" direction=\"in\" type=\"i\"/>\n" \
- " <arg name=\"ConnectedDeviceList\" direction=\"out\" type=\"a(isiisii)\"/>\n" \
- " </method>\n" \
- " <method name=\"GetDeviceById\">\n" \
- " <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n" \
- " <arg name=\"device\" direction=\"out\" type=\"(isiisii)\"/>\n" \
- " </method>\n" \
- " <method name=\"IsStreamOnDevice\">\n" \
- " <arg name=\"stream_id\" direction=\"in\" type=\"i\"/>\n" \
- " <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n" \
- " <arg name=\"is_on\" direction=\"out\" type=\"b\"/>\n" \
- " </method>\n" \
- " <method name='GetBTA2DPStatus'>" \
- " <arg type='b' name='is_bt_on' direction='out'/>" \
- " <arg type='s' name='bt_name' direction='out'/>" \
- " </method>" \
- " <method name=\"LoadSink\">\n" \
- " <arg name=\"device_type\" direction=\"in\" type=\"s\"/>\n" \
- " <arg name=\"role\" direction=\"in\" type=\"s\"/>\n" \
- " </method>\n" \
- " <method name=\"UnloadSink\">\n" \
- " <arg name=\"device_type\" direction=\"in\" type=\"s\"/>\n" \
- " <arg name=\"role\" direction=\"in\" type=\"s\"/>\n" \
- " </method>\n" \
- " <method name=\"GetSupportedSampleFormats\">\n" \
- " <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n" \
- " <arg name=\"sample_formats\" direction=\"out\" type=\"a(s)\"/>\n" \
- " </method>\n" \
- " <method name=\"SetSampleFormat\">\n" \
- " <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n" \
- " <arg name=\"sample_format\" direction=\"in\" type=\"s\"/>\n" \
- " </method>\n" \
- " <method name=\"GetSampleFormat\">\n" \
- " <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n" \
- " <arg name=\"sample_format\" direction=\"out\" type=\"s\"/>\n" \
- " </method>\n" \
- " <method name=\"GetSupportedSampleRates\">\n" \
- " <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n" \
- " <arg name=\"sample_rates\" direction=\"out\" type=\"a(u)\"/>\n" \
- " </method>\n" \
- " <method name=\"SetSampleRate\">\n" \
- " <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n" \
- " <arg name=\"sample_rate\" direction=\"in\" type=\"u\"/>\n" \
- " </method>\n" \
- " <method name=\"GetSampleRate\">\n" \
- " <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n" \
- " <arg name=\"sample_rate\" direction=\"out\" type=\"u\"/>\n" \
- " </method>\n" \
- " <method name=\"SetSpecificStreamOnly\">\n" \
- " <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n" \
- " <arg name=\"stream_role\" direction=\"in\" type=\"s\"/>\n" \
- " </method>\n" \
- " <method name=\"GetSpecifiedStream\">\n" \
- " <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n" \
- " <arg name=\"stream_role\" direction=\"out\" type=\"s\"/>\n" \
- " </method>\n" \
- " <method name=\"SetAvoidResampling\">\n" \
- " <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n" \
- " <arg name=\"avoid_resampling\" direction=\"in\" type=\"b\"/>\n" \
- " </method>\n" \
- " <method name=\"GetAvoidResampling\">\n" \
- " <arg name=\"device_id\" direction=\"in\" type=\"i\"/>\n" \
- " <arg name=\"avoid_resampling\" direction=\"out\" type=\"b\"/>\n" \
- " </method>\n" \
- " <method name=\"DumpDeviceList\">\n" \
- " </method>\n" \
- " <method name=\"TestStatusChange\">\n" \
- " <arg name=\"device_type\" direction=\"in\" type=\"s\"/>\n" \
- " <arg name=\"status\" direction=\"in\" type=\"i\"/>\n" \
- " </method>\n" \
- " <property name=\"PropertyTest1\" type=\"i\" access=\"readwrite\"/>\n" \
- " <property name=\"PropertyTest2\" type=\"s\" access=\"read\"/>\n" \
- " <signal name=\"DeviceConnected\">\n" \
- " <arg name=\"arg1\" type=\"i\"/>\n" \
- " </signal>\n" \
- " <signal name=\"DeviceInfoChanged\">\n" \
- " <arg name=\"arg1\" type=\"s\"/>\n" \
- " </signal>\n" \
- " </interface>\n" \
- " <interface name=\"" DBUS_INTERFACE_INTROSPECTABLE "\">\n" \
- " <method name=\"Introspect\">\n" \
- " <arg name=\"data\" type=\"s\" direction=\"out\"/>\n" \
- " </method>\n" \
- " </interface>\n" \
- " <interface name=\"" DBUS_INTERFACE_PROPERTIES "\">\n" \
- " <method name=\"Get\">\n" \
- " <arg name=\"interface_name\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"property_name\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"value\" type=\"v\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <method name=\"Set\">\n" \
- " <arg name=\"interface_name\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"property_name\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"value\" type=\"v\" direction=\"in\"/>\n" \
- " </method>\n" \
- " <method name=\"GetAll\">\n" \
- " <arg name=\"interface_name\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"props\" type=\"a{sv}\" direction=\"out\"/>\n" \
- " </method>\n" \
- " </interface>\n" \
- "</node>\n"
-
-#define FILTER_DEVICED_SYSNOTI \
- "type='signal'," \
- " interface='" DBUS_INTERFACE_DEVICED_SYSNOTI "'"
-
-#define FILTER_SOUND_SERVER \
- "type='signal'," \
- " interface='" DBUS_INTERFACE_SOUND_SERVER "'"
-
-#define FILTER_MIRRORING \
- "type='signal'," \
- " interface='" DBUS_INTERFACE_MIRRORING_SERVER "', member='miracast_wfd_source_status_changed'"
-
-#define FILTER_BLUEZ \
- "type='signal'," \
- " interface='" DBUS_INTERFACE_BLUEZ_HEADSET "', member='PropertyChanged'"
-
-#define FILL_SAMPLE_SPEC_WITH_SELECTED(x_sink, x_spec) \
-do { \
- x_spec.format = x_sink->selected_sample_format; \
- x_spec.rate = x_sink->selected_sample_rate; \
- x_spec.channels = 2; \
-} while(0)
-
-#define FILL_SAMPLE_SPEC_WITH_PREFER_ENTRY(x_entry, x_spec) \
-do { \
- x_spec.format = x_entry->format; \
- x_spec.rate = x_entry->rate; \
- x_spec.channels = 2; \
-} while(0)
-
static const char* const valid_alsa_device_modargs[] = {
"name",
"sink_name",
#define BT_CVSD_CODEC_ID 1 // narrow-band
#define BT_MSBC_CODEC_ID 2 // wide-band
-/*
- Enums for represent values which is defined on other module.
- This is needed to identify values which are sent by dbus or vconf.
-*/
-typedef enum external_value_earjack_type {
- EARJACK_DISCONNECTED = 0,
- EARJACK_TYPE_SPK_ONLY = 1,
- EARJACK_TYPE_SPK_WITH_MIC = 3,
-} external_value_earjack_t;
-
-typedef enum external_value_bt_sco_type {
- BT_SCO_DISCONNECTED = 0,
- BT_SCO_CONNECTED = 1,
-} external_value_bt_sco_t;
-
-typedef enum external_value_forwarding_type {
- FORWARDING_DISCONNECTED = 0,
- FORWARDING_CONNECTED = 1,
-} external_value_mirroring_t;
-
-typedef enum external_value_hdmi_type {
- HDMI_AUDIO_DISCONNECTED = -1,
- HDMI_AUDIO_NOT_AVAILABLE = 0,
- HDMI_AUDIO_AVAILABLE = 1,
-} external_value_hdmi_t;
-
-
-/*
- Enums for represent device detected status (through dbus)
- When some device is detected, one of these values should be saved in device_status hashmap.
- device_detected_type_t is needed to distinguish detected device-types ( ex. earjack which can be out or both way)
- So If you just want to know whether detected or not, can device_detected_t as mask.
-*/
-
-typedef enum device_detected_type {
- DEVICE_DISCONNECTED = 0x0,
- DEVICE_CONNECTED = 0x1,
- DEVICE_CONNECTED_AUDIO_JACK_4P = DEVICE_CONNECTED | 0x2,
- DEVICE_CONNECTED_AUDIO_JACK_3P = DEVICE_CONNECTED | 0x4,
- DEVICE_CONNECTED_SCO = DEVICE_CONNECTED | 0x8,
- DEVICE_OPENED_SCO = DEVICE_CONNECTED | 0xF,
-} device_detected_type_t;
typedef enum dm_device_class_type {
DM_DEVICE_CLASS_NONE,
DM_DEVICE_CLASS_MAX,
} dm_device_class_t;
-typedef enum {
- DEVICE_IO_DIRECTION_IN_FLAG = 0x0001, /**< Flag for input devices */
- DEVICE_IO_DIRECTION_OUT_FLAG = 0x0002, /**< Flag for output devices */
- DEVICE_IO_DIRECTION_BOTH_FLAG = 0x0004, /**< Flag for input/output devices (both directions are available) */
- DEVICE_TYPE_INTERNAL_FLAG = 0x0010, /**< Flag for built-in devices */
- DEVICE_TYPE_EXTERNAL_FLAG = 0x0020, /**< Flag for external devices */
- DEVICE_STATE_DEACTIVATED_FLAG = 0x1000, /**< Flag for deactivated devices */
- DEVICE_STATE_ACTIVATED_FLAG = 0x2000, /**< Flag for activated devices */
- DEVICE_ALL_FLAG = 0xFFFF, /**< Flag for all devices */
-} device_flag_t;
-
-typedef enum {
- DEVICE_IO_DIRECTION_FLAGS = 0x000F, /**< Flag for io direction */
- DEVICE_TYPE_FLAGS = 0x00F0, /**< Flag for device type */
- DEVICE_STATE_FLAGS = 0xF000, /**< Flag for device state */
-} device_flags_type_t;
-
typedef enum dm_device_bt_mode_type {
DM_DEVICE_BT_MODE_MEDIA = 0x1,
DM_DEVICE_BT_MODE_VOICE = 0x2
const char *role;
};
-#ifdef HAVE_DBUS
-
-/*** Defines for method handle ***/
-/* method handlers */
-static void handle_get_connected_device_list(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_get_device_by_id(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_is_stream_on_device(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_get_bt_a2dp_status(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_get_supported_sample_formats(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_set_sample_format(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_get_sample_format(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_get_supported_sample_rates(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_set_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_set_specific_stream_only(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_get_specified_stream(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_set_avoid_resampling(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_get_avoid_resampling(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_load_sink(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_unload_sink(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_unload_sink_with_device_string(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_get_device_string(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_dump_device_list(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_test_device_status_change(DBusConnection *conn, DBusMessage *msg, void *userdata);
-
-static int method_call_bt_get_name(DBusConnection *conn, const char *device_path, char **name);
-
-enum method_handler_index {
- METHOD_HANDLER_GET_CONNECTED_DEVICE_LIST,
- METHOD_HANDLER_GET_DEVICE_BY_ID,
- METHOD_HANDLER_IS_STREAM_ON_DEVICE,
- METHOD_HANDLER_GET_BT_A2DP_STATUS,
- METHOD_HANDLER_LOAD_SINK,
- METHOD_HANDLER_UNLOAD_SINK,
- METHOD_HANDLER_UNLOAD_SINK_WITH_DEVICE_STRING,
- METHOD_HANDLER_GET_DEVICE_STRING,
- METHOD_HANDLER_GET_SUPPORTED_SAMPLE_FORMATS,
- METHOD_HANDLER_SET_SAMPLE_FORMAT,
- METHOD_HANDLER_GET_SAMPLE_FORMAT,
- METHOD_HANDLER_GET_SUPPORTED_SAMPLE_RATES,
- METHOD_HANDLER_SET_SAMPLE_RATE,
- METHOD_HANDLER_GET_SAMPLE_RATE,
- METHOD_HANDLER_SET_SPECIFIC_STREAM_ONLY,
- METHOD_HANDLER_GET_SPECIFIED_STREAM,
- METHOD_HANDLER_SET_AVOID_RESAMPLING,
- METHOD_HANDLER_GET_AVOID_RESAMPLING,
- METHOD_HANDLER_DUMP_DEVICE_LIST,
- METHOD_HANDLER_STATUS_TEST,
- METHOD_HANDLER_MAX
-};
-
-static pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = {
- [METHOD_HANDLER_GET_CONNECTED_DEVICE_LIST] = {
- .method_name = "GetConnectedDeviceList",
- .receive_cb = handle_get_connected_device_list },
- [METHOD_HANDLER_GET_DEVICE_BY_ID] = {
- .method_name = "GetDeviceById",
- .receive_cb = handle_get_device_by_id },
- [METHOD_HANDLER_IS_STREAM_ON_DEVICE] = {
- .method_name = "IsStreamOnDevice",
- .receive_cb = handle_is_stream_on_device },
- [METHOD_HANDLER_GET_BT_A2DP_STATUS] = {
- .method_name = "GetBTA2DPStatus",
- .receive_cb = handle_get_bt_a2dp_status },
- [METHOD_HANDLER_LOAD_SINK] = {
- .method_name = "LoadSink",
- .receive_cb = handle_load_sink },
- [METHOD_HANDLER_UNLOAD_SINK] = {
- .method_name = "UnloadSink",
- .receive_cb = handle_unload_sink },
- [METHOD_HANDLER_UNLOAD_SINK_WITH_DEVICE_STRING] = {
- .method_name = "UnloadSinkWithDeviceString",
- .receive_cb = handle_unload_sink_with_device_string },
- [METHOD_HANDLER_GET_DEVICE_STRING] = {
- .method_name = "GetDeviceString",
- .receive_cb = handle_get_device_string },
- [METHOD_HANDLER_GET_SUPPORTED_SAMPLE_FORMATS] = {
- .method_name = "GetSupportedSampleFormats",
- .receive_cb = handle_get_supported_sample_formats },
- [METHOD_HANDLER_SET_SAMPLE_FORMAT] = {
- .method_name = "SetSampleFormat",
- .receive_cb = handle_set_sample_format },
- [METHOD_HANDLER_GET_SAMPLE_FORMAT] = {
- .method_name = "GetSampleFormat",
- .receive_cb = handle_get_sample_format },
- [METHOD_HANDLER_GET_SUPPORTED_SAMPLE_RATES] = {
- .method_name = "GetSupportedSampleRates",
- .receive_cb = handle_get_supported_sample_rates },
- [METHOD_HANDLER_SET_SAMPLE_RATE] = {
- .method_name = "SetSampleRate",
- .receive_cb = handle_set_sample_rate },
- [METHOD_HANDLER_GET_SAMPLE_RATE] = {
- .method_name = "GetSampleRate",
- .receive_cb = handle_get_sample_rate },
- [METHOD_HANDLER_SET_SPECIFIC_STREAM_ONLY] = {
- .method_name = "SetSpecificStreamOnly",
- .receive_cb = handle_set_specific_stream_only },
- [METHOD_HANDLER_GET_SPECIFIED_STREAM] = {
- .method_name = "GetSpecifiedStream",
- .receive_cb = handle_get_specified_stream },
- [METHOD_HANDLER_SET_AVOID_RESAMPLING] = {
- .method_name = "SetAvoidResampling",
- .receive_cb = handle_set_avoid_resampling },
- [METHOD_HANDLER_GET_AVOID_RESAMPLING] = {
- .method_name = "GetAvoidResampling",
- .receive_cb = handle_get_avoid_resampling },
- [METHOD_HANDLER_DUMP_DEVICE_LIST] = {
- .method_name = "DumpDeviceList",
- .receive_cb = handle_dump_device_list },
- [METHOD_HANDLER_STATUS_TEST] = {
- .method_name = "TestStatusChange",
- .receive_cb = handle_test_device_status_change },
-};
-
-#endif
-
enum internal_codec_device_index {
DEVICE_INDEX_BUILTIN_SPEAKER,
DEVICE_INDEX_BUILTIN_RECEIVER,
.is_running[1] = false },
};
+void simple_device_dump(pa_log_level_t level, const char *prefix, int id, const char *type, const char *name, int direction, int state) {
+ pa_logl(level, "%s device id(%d) type(%s) name (%s) direction(%d) state(%d)",
+ pa_strempty(prefix), id, pa_strnull(type), pa_strnull(name), direction, state);
+}
+
+const char* build_key_from_proplist(pa_proplist *p) {
+ const char *vendor_id;
+ const char *product_id;
+ static char key[DEVICE_KEY_STR_MAX] = {0,};
+
+ pa_assert(p);
+
+ vendor_id = pa_proplist_gets(p, PA_PROP_DEVICE_VENDOR_ID);
+ product_id = pa_proplist_gets(p, PA_PROP_DEVICE_PRODUCT_ID);
+ if (!vendor_id || !product_id) {
+ pa_log_error("could not get vendor id(%s) or product id(%s)", vendor_id, product_id);
+ return NULL;
+ }
+
+ snprintf(key, DEVICE_KEY_STR_MAX, "%s.%s", vendor_id, product_id);
+
+ return key;
+}
+
static inline void internal_codec_devices_dump() {
uint32_t i;
pa_log_info("========== devices using internal codec ==========");
pa_log_info("==================================================");
}
-static inline void simple_device_dump(pa_log_level_t level, const char *prefix, int id, const char *type, const char *name, int direction, int state) {
- pa_logl(level, "%s device id(%d) type(%s) name (%s) direction(%d) state(%d)",
- pa_strempty(prefix), id, pa_strnull(type), pa_strnull(name), direction, state);
-}
-
static void find_device_and_set_running(pa_device_manager *dm, const char *type, bool is_running) {
pa_tz_device* device;
return status_info->detected;
}
-static void _device_set_detected(pa_device_manager *manager, const char *type,
+void device_set_detected(pa_device_manager *manager, const char *type,
const char *name, const char *system_id, device_detected_type_t detected_type) {
struct device_status_info *status_info;
}
}
-static pa_tz_device* _device_list_get_device(pa_device_manager *manager, const char *type, const char *system_id) {
+pa_tz_device* device_list_get_device(pa_device_manager *manager, const char *type, const char *system_id) {
pa_tz_device *device;
uint32_t idx;
char *_type, *_system_id;
return NULL;
}
-
-static pa_tz_device* _device_list_get_device_by_id(pa_device_manager *manager, uint32_t id) {
+pa_tz_device* device_list_get_device_by_id(pa_device_manager *manager, uint32_t id) {
pa_tz_device *device;
uint32_t idx;
return NULL;
}
- if (!(device = _device_list_get_device(dm, type, NULL))) {
+ if (!(device = device_list_get_device(dm, type, NULL))) {
pa_log_warn("cannot get device item for %s", type);
return NULL;
}
return NULL;
}
- if (!(device = _device_list_get_device(dm, type, NULL))) {
+ if (!(device = device_list_get_device(dm, type, NULL))) {
pa_log_warn("cannot get device item for %s", type);
return NULL;
}
return source;
}
-static const char* build_key_from_proplist(pa_proplist *p) {
- const char *vendor_id;
- const char *product_id;
- static char key[DEVICE_KEY_STR_MAX] = {0,};
-
- pa_assert(p);
-
- vendor_id = pa_proplist_gets(p, PA_PROP_DEVICE_VENDOR_ID);
- product_id = pa_proplist_gets(p, PA_PROP_DEVICE_PRODUCT_ID);
- if (!vendor_id || !product_id) {
- pa_log_error("could not get vendor id(%s) or product id(%s)", vendor_id, product_id);
- return NULL;
- }
-
- snprintf(key, DEVICE_KEY_STR_MAX, "%s.%s", vendor_id, product_id);
-
- return key;
-}
-
static void apply_preference(pa_device_manager *dm, pa_sink *sink) {
const char *key;
prefer_entry *e;
if (do_reconfigure) {
pa_sample_spec spec;
- FILL_SAMPLE_SPEC_WITH_PREFER_ENTRY(e, spec);
+ FILL_SAMPLE_SPEC_WITH_PREFER_ENTRY(spec, e);
pa_log_info("reconfigure this sink to avoid-resampling(%d), format(%s), rate(%d)",
sink->avoid_resampling, pa_sample_format_to_string(e->format), e->rate);
pa_sink_reconfigure(sink, &spec, false);
pa_xfree(e);
}
-static void save_preference(pa_device_manager *dm, pa_sink *sink) {
- const char *key;
- prefer_entry e;
-
- pa_assert(dm);
- pa_assert(sink);
-
- e.avoid_resampling = sink->avoid_resampling;
- e.format = sink->selected_sample_format;
- e.rate = sink->selected_sample_rate;
- if ((key = build_key_from_proplist(sink->proplist)))
- write_prefer_entry(dm, key, &e);
-}
-
static void handle_usb_pulse_device(pa_object *pdevice, bool is_loaded, pa_device_manager *dm) {
const char *name, *system_id;
dm_device_direction_t direction;
pa_tz_device_new(&data);
pa_tz_device_new_data_done(&data);
} else {
- if (!(device = _device_list_get_device(dm, DEVICE_TYPE_USB_AUDIO, system_id)))
+ if (!(device = device_list_get_device(dm, DEVICE_TYPE_USB_AUDIO, system_id)))
pa_log_warn("Can't get usb device for %s", system_id);
else
pa_tz_device_free(device);
pa_tz_device_new_data_done(&data);
} else {
- if (!(device = _device_list_get_device(dm, DEVICE_TYPE_BT_A2DP, system_id)))
+ if (!(device = device_list_get_device(dm, DEVICE_TYPE_BT_A2DP, system_id)))
pa_log_warn("Can't get bt device for %s", system_id);
else
pa_tz_device_free(device);
for (int i = 0; i < pa_dynarray_size(ctypes); i++) {
ctype = pa_dynarray_get(ctypes, i);
pa_log_info("Found belongs type %s %s", ctype->type, ctype->role);
- if ((device = _device_list_get_device(dm, ctype->type, NULL))) {
+ if ((device = device_list_get_device(dm, ctype->type, NULL))) {
pa_log_info("Add this pulse_device to device(%u)", pa_tz_device_get_id(device));
if (direction == DM_DEVICE_DIRECTION_OUT)
pa_tz_device_add_sink(device, ctype->role, PA_SINK(pdevice));
for (int i = 0; i < pa_dynarray_size(ctypes); i++) {
ctype = pa_dynarray_get(ctypes, i);
pa_log_info("Found belongs type %s %s", ctype->type, ctype->role);
- if ((device = _device_list_get_device(dm, ctype->type, NULL))) {
+ if ((device = device_list_get_device(dm, ctype->type, NULL))) {
pa_log_info("Remove this pulse_device from device(%u)", pa_tz_device_get_id(device));
if (direction == DM_DEVICE_DIRECTION_OUT)
pa_tz_device_remove_sink(device, PA_SINK(pdevice));
pa_log_info("Load forwarding device");
- if ((forwarding_device = _device_list_get_device(dm, DEVICE_TYPE_FORWARDING, NULL))) {
+ if ((forwarding_device = device_list_get_device(dm, DEVICE_TYPE_FORWARDING, NULL))) {
pa_log_info("Forwarding device already exists");
return forwarding_device;
}
- if ((spk_device = _device_list_get_device(dm, DEVICE_TYPE_SPEAKER, NULL)) == NULL) {
+ if ((spk_device = device_list_get_device(dm, DEVICE_TYPE_SPEAKER, NULL)) == NULL) {
pa_log_error("Get speaker device failed");
return NULL;
}
And if correnspondent sink/sources for device_type exist, should make device and notify it.
Use [device_type->roles] mappings in sink/source for find proper sink/source.
*/
-static void handle_device_connected(pa_device_manager *dm, const char *type,
+void handle_device_connected(pa_device_manager *dm, const char *type,
const char *name, const char *system_id, device_detected_type_t detected_type) {
struct device_type_info *type_info;
pa_tz_device_new_data data;
return ;
}
-/*
- Handle device disconnection detected through dbus.
- First, update device-status hashmap.
- And if there is device which has the device_type, remove it.
-*/
-static int handle_device_disconnected(pa_device_manager *dm, const char *type, const char *system_id) {
- pa_tz_device *device;
-
- pa_assert(dm);
- pa_assert(dm->device_status);
-
- pa_log_info("Device type(%s) system_id(%s) disconnected",
- type, pa_strempty(system_id));
-
- device = _device_list_get_device(dm, type, system_id);
- if (!device) {
- pa_log_error("Disconnection detected but no device for that");
- return -1;
- }
-
- pa_tz_device_free(device);
-
- return 0;
-}
-
static int load_builtin_devices(pa_device_manager *dm) {
struct device_type_info *type_info;
uint32_t type_idx;
return file_map;
}
-
static pa_hashmap* parse_device_role_map(json_object *device_role_map_o) {
pa_hashmap *roles = NULL;
const char *device_string, *device_role;
return NULL;
}
-
-
static pa_idxset* parse_device_type_infos() {
json_object *o, *device_array_o = NULL;
int device_type_num = 0;
}
/*
- look detected status which is external value, make conversion to internal consistent value, and handle it
- device_type, which type of device is detected
- system_id : system_id among same device types for support multi-device
-*/
-static int handle_device_status_changed(pa_device_manager *dm, const char *type,
- const char *name, const char *system_id, device_detected_type_t detected) {
- pa_assert(dm);
-
- pa_log_info("Device Status Changed, type(%s) system_id(%s), detected_type(%d)",
- type, pa_strempty(system_id), detected);
-
- if (!device_type_is_valid(type)) {
- pa_log_error("Invalid device type %s", type);
- return -1;
- } else if (device_type_is_equal(type, DEVICE_TYPE_BT_SCO)) {
- _device_set_detected(dm, type, name, system_id, detected);
- if (detected == DEVICE_DISCONNECTED)
- handle_device_disconnected(dm, type, system_id);
- else
- handle_device_connected(dm, type, name, system_id, detected);
- } else if (device_type_is_need_detect(type)) {
- _device_set_detected(dm, type, name, system_id, detected);
- if (detected == DEVICE_DISCONNECTED)
- handle_device_disconnected(dm, type, system_id);
- else
- handle_device_connected(dm, type, name, system_id, detected);
- } else {
- pa_log_debug("No need to detect type %s", type);
- }
-
- return 0;
-}
-
-/*
Initialize device-status idxset.
This is for device-status detected through dbus.
So, if device_type is not detected through dbus, let's initialize them to detected. (ex. spk, rcv,...)
continue;
}
if (earjack_status == EARJACK_TYPE_SPK_ONLY)
- _device_set_detected(manager, type, NULL, NULL, DEVICE_CONNECTED_AUDIO_JACK_3P);
+ device_set_detected(manager, type, NULL, NULL, DEVICE_CONNECTED_AUDIO_JACK_3P);
else if (earjack_status == EARJACK_TYPE_SPK_WITH_MIC)
- _device_set_detected(manager, type, NULL, NULL, DEVICE_CONNECTED_AUDIO_JACK_4P);
+ device_set_detected(manager, type, NULL, NULL, DEVICE_CONNECTED_AUDIO_JACK_4P);
else if (earjack_status == EARJACK_DISCONNECTED)
- _device_set_detected(manager, type, NULL, NULL, DEVICE_DISCONNECTED);
+ device_set_detected(manager, type, NULL, NULL, DEVICE_DISCONNECTED);
else
pa_log_warn("Unknown earjack status : %d", earjack_status);
} else if (device_type_is_equal(type, DEVICE_TYPE_BT_SCO)) {
- _device_set_detected(manager, type, NULL, NULL, DEVICE_DISCONNECTED);
+ device_set_detected(manager, type, NULL, NULL, DEVICE_DISCONNECTED);
} else if (device_type_is_equal(type, DEVICE_TYPE_HDMI)) {
- _device_set_detected(manager, type, NULL, NULL, DEVICE_DISCONNECTED);
+ device_set_detected(manager, type, NULL, NULL, DEVICE_DISCONNECTED);
} else if (device_type_is_equal(type, DEVICE_TYPE_FORWARDING)) {
int miracast_wfd_status = 0;
if (vconf_get_bool(VCONFKEY_MIRACAST_WFD_SOURCE_STATUS, &miracast_wfd_status) < 0) {
continue;
}
if (miracast_wfd_status == FORWARDING_CONNECTED)
- _device_set_detected(manager, type, NULL, NULL, DEVICE_CONNECTED);
+ device_set_detected(manager, type, NULL, NULL, DEVICE_CONNECTED);
} else {
- _device_set_detected(manager, type, NULL, NULL, DEVICE_CONNECTED);
+ device_set_detected(manager, type, NULL, NULL, DEVICE_CONNECTED);
}
}
return ;
}
-#ifdef HAVE_DBUS
-
-static int _translate_external_value(const char *type, int value, device_detected_type_t *detected) {
-
- if (!type || !detected) {
- pa_log_error("Invalid Parameter for translate");
- return -1;
- }
-
- if (device_type_is_equal(DEVICE_TYPE_AUDIO_JACK, type)) {
- if (value == EARJACK_DISCONNECTED)
- *detected = DEVICE_DISCONNECTED;
- else if (value == EARJACK_TYPE_SPK_ONLY)
- *detected = DEVICE_CONNECTED_AUDIO_JACK_3P;
- else if (value == EARJACK_TYPE_SPK_WITH_MIC)
- *detected = DEVICE_CONNECTED_AUDIO_JACK_4P;
- else
- return -1;
- } else if (device_type_is_equal(DEVICE_TYPE_HDMI, type)) {
- if (value == HDMI_AUDIO_DISCONNECTED)
- *detected = DEVICE_DISCONNECTED;
- else if (value == HDMI_AUDIO_AVAILABLE)
- *detected = DEVICE_CONNECTED;
- else
- return -1;
- } else if (device_type_is_equal(DEVICE_TYPE_FORWARDING, type)) {
- if (value == FORWARDING_DISCONNECTED)
- *detected = DEVICE_DISCONNECTED;
- else if (value == FORWARDING_CONNECTED)
- *detected = DEVICE_CONNECTED;
- else
- return -1;
- } else if (device_type_is_equal(DEVICE_TYPE_BT_SCO, type)) {
- if (value == BT_SCO_DISCONNECTED)
- *detected = DEVICE_DISCONNECTED;
- else if (value == BT_SCO_CONNECTED)
- *detected = DEVICE_CONNECTED_SCO;
- else
- return -1;
- }
-
- return 0;
-}
-
-static DBusHandlerResult dbus_filter_device_detect_handler(DBusConnection *c, DBusMessage *s, void *userdata) {
- DBusError error;
- int status = 0;
- pa_device_manager *dm = (pa_device_manager *) userdata;
- device_detected_type_t detected;
-
- pa_assert(userdata);
-
- if (dbus_message_get_type(s) != DBUS_MESSAGE_TYPE_SIGNAL)
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
- pa_log_info("Device detect handler : Path(%s) Intf(%s) Member(%s) Signature(%s)",
- dbus_message_get_path(s), dbus_message_get_interface(s), dbus_message_get_member(s), dbus_message_get_signature(s));
-
- dbus_error_init(&error);
-
- if (dbus_message_is_signal(s, DBUS_INTERFACE_DEVICED_SYSNOTI, "ChangedEarjack")) {
- if (!dbus_message_get_args(s, NULL, DBUS_TYPE_INT32, &status, DBUS_TYPE_INVALID)) {
- goto fail;
- } else {
- if (_translate_external_value(DEVICE_TYPE_AUDIO_JACK, status, &detected) < 0) {
- pa_log_warn("failed to translate audio-jack detected value");
- goto fail;
- }
- handle_device_status_changed(dm, DEVICE_TYPE_AUDIO_JACK, NULL, NULL, detected);
- }
- } else if (dbus_message_is_signal(s, DBUS_INTERFACE_DEVICED_SYSNOTI, "ChangedHDMIAudio")) {
- if (!dbus_message_get_args(s, NULL, DBUS_TYPE_INT32, &status, DBUS_TYPE_INVALID)) {
- goto fail;
- } else {
- if (_translate_external_value(DEVICE_TYPE_HDMI, status, &detected) < 0) {
- pa_log_warn("failed to translate HDMI detected value");
- goto fail;
- }
- handle_device_status_changed(dm, DEVICE_TYPE_HDMI, NULL, NULL, detected);
- }
- } else if (dbus_message_is_signal(s, DBUS_INTERFACE_MIRRORING_SERVER, "miracast_wfd_source_status_changed")) {
- if (!dbus_message_get_args(s, NULL, DBUS_TYPE_INT32, &status, DBUS_TYPE_INVALID)) {
- goto fail;
- } else {
- if (_translate_external_value(DEVICE_TYPE_FORWARDING, status, &detected) < 0) {
- pa_log_warn("failed to translate forwarding detected value");
- goto fail;
- }
- handle_device_status_changed(dm, DEVICE_TYPE_FORWARDING, NULL, NULL, detected);
- }
- } else if (dbus_message_is_signal(s, DBUS_INTERFACE_BLUEZ_HEADSET, "PropertyChanged")) {
- DBusMessageIter msg_iter, variant_iter;
- char *property_name;
-
- pa_log_debug("Got %s PropertyChanged signal", DBUS_INTERFACE_BLUEZ_HEADSET);
- dbus_message_iter_init(s, &msg_iter);
- if (dbus_message_iter_get_arg_type(&msg_iter) != DBUS_TYPE_STRING) {
- pa_log_error("Property name not string");
- goto fail;
- }
- dbus_message_iter_get_basic(&msg_iter, &property_name);
- pa_log_info("Changed Property name : %s", property_name);
-
- if (!dbus_message_iter_next(&msg_iter)) {
- pa_log_debug("Property value missing");
- goto fail;
- }
-
- if (dbus_message_iter_get_arg_type(&msg_iter) != DBUS_TYPE_VARIANT) {
- pa_log_debug("Property value not a variant.");
- goto fail;
- }
-
- dbus_message_iter_recurse(&msg_iter, &variant_iter);
-
- if (DBUS_TYPE_BOOLEAN == dbus_message_iter_get_arg_type(&variant_iter)) {
- dbus_bool_t value;
- char *name = NULL;
- dbus_message_iter_get_basic(&variant_iter, &value);
- if (pa_streq(property_name, "Connected")) {
- pa_log_info("HFP Connection : %d", value);
- if (value) {
- method_call_bt_get_name(c, dbus_message_get_path(s), &name);
- status = BT_SCO_CONNECTED;
- } else {
- status = BT_SCO_DISCONNECTED;
- }
- if (_translate_external_value(DEVICE_TYPE_BT_SCO, status, &detected) < 0) {
- pa_log_warn("failed to translate bt-sco detected value");
- goto fail;
- }
- handle_device_status_changed(dm, DEVICE_TYPE_BT_SCO,
- name, dbus_message_get_path(s), detected);
- } else if (pa_streq(property_name, "Playing")) {
- pa_tz_device *device;
- pa_log_info("SCO Playing : %d", value);
- if ((device = _device_list_get_device(dm, DEVICE_TYPE_BT_SCO, NULL)) != NULL) {
- device->sco_opened = value;
- if (value) {
- /* update BT band/nrec information */
- bool is_wide_band = false;
- bool nrec = false;
- pa_tz_device_sco_get_property(device, &is_wide_band, &nrec);
- pa_log_info("got new wideband:%d, nrec:%d", is_wide_band, nrec);
-
- UPDATE_HAL_ROUTE_OPTION(dm->hal_interface, NULL, "bt-wideband", is_wide_band);
- UPDATE_HAL_ROUTE_OPTION(dm->hal_interface, NULL, "bt-nrec", nrec);
- }
- }
- UPDATE_HAL_ROUTE_OPTION(dm->hal_interface, NULL, "bt-sco-ready", value);
- }
- }
- } else {
- pa_log_debug("Unknown message, not handle it");
- dbus_error_free(&error);
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- }
-
- pa_log_debug("Dbus Message handled");
-
- dbus_error_free(&error);
- return DBUS_HANDLER_RESULT_HANDLED;
-
-fail:
- pa_log_error("Fail to handle dbus signal");
- dbus_error_free(&error);
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
-
-static int watch_signals(pa_device_manager *dm) {
- DBusError error;
-
- pa_assert(dm);
- pa_assert(dm->dbus_conn);
-
- dbus_error_init(&error);
-
- pa_log_info("Watch Dbus signals");
-
- if (!dbus_connection_add_filter(pa_dbus_connection_get(dm->dbus_conn), dbus_filter_device_detect_handler, dm, NULL)) {
- pa_log_error("Unable to add D-Bus filter : %s: %s", error.name, error.message);
- goto fail;
- }
-
- if (pa_dbus_add_matches(pa_dbus_connection_get(dm->dbus_conn), &error, FILTER_DEVICED_SYSNOTI, FILTER_SOUND_SERVER, FILTER_BLUEZ, FILTER_MIRRORING, NULL) < 0) {
- pa_log_error("Unable to subscribe to signals: %s: %s", error.name, error.message);
- goto fail;
- }
- return 0;
-
-fail:
- dbus_error_free(&error);
- return -1;
-}
-
-static void unwatch_signals(pa_device_manager *dm) {
- pa_log_info("Unwatch Dbus signals");
-
- pa_assert(dm);
- pa_assert(dm->dbus_conn);
-
- pa_dbus_remove_matches(pa_dbus_connection_get(dm->dbus_conn), FILTER_DEVICED_SYSNOTI, FILTER_SOUND_SERVER, FILTER_BLUEZ, FILTER_MIRRORING, NULL);
- dbus_connection_remove_filter(pa_dbus_connection_get(dm->dbus_conn), dbus_filter_device_detect_handler, dm);
-}
-
-static void fill_signal_msg_with_device(const char *description, DBusMessageIter *msg_iter, uint32_t event_id, pa_tz_device *device) {
- DBusMessageIter array_iter, device_iter;
- char *type, *name;
- dbus_int32_t device_id, direction, state, stream_id;
- dbus_int32_t vendor_id, product_id;
- dbus_bool_t is_running;
- pa_intset *stream_id_set = NULL;
- int32_t stream_id_val;
- int ret;
-
- pa_assert(msg_iter);
- pa_assert(device);
-
- dbus_message_iter_append_basic(msg_iter, DBUS_TYPE_UINT32, &event_id);
- pa_assert_se(dbus_message_iter_open_container(msg_iter, DBUS_TYPE_STRUCT, NULL, &device_iter));
-
- direction = (dbus_int32_t) pa_tz_device_get_direction(device);
- type = pa_tz_device_get_type(device);
- name = pa_tz_device_get_name(device);
- device_id = (dbus_int32_t) pa_tz_device_get_id(device);
- state = pa_tz_device_get_state(device);
- vendor_id = (dbus_int32_t) pa_tz_device_get_vendor_id(device);
- product_id = (dbus_int32_t) pa_tz_device_get_product_id(device);
- is_running = (dbus_bool_t) pa_tz_device_is_running(device);
-
- simple_device_dump(PA_LOG_INFO, description, device_id, type, name, direction, state);
-
- dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &device_id);
- dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_STRING, &type);
- dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &direction);
- dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &state);
- dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_STRING, &name);
- dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &vendor_id);
- dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &product_id);
- dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_BOOLEAN, &is_running);
- if (state == DM_DEVICE_STATE_ACTIVATED)
- stream_id_set = pa_tz_device_get_stream_list(device);
- pa_assert_se(dbus_message_iter_open_container(&device_iter, DBUS_TYPE_ARRAY, "i", &array_iter));
- if (state == DM_DEVICE_STATE_ACTIVATED) {
- PA_INTSET_FOREACH(stream_id_val, stream_id_set, ret) {
- stream_id = stream_id_val;
- dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_INT32, &stream_id);
- }
- }
- pa_assert_se(dbus_message_iter_close_container(&device_iter, &array_iter));
- if (stream_id_set)
- pa_intset_free(stream_id_set);
- pa_assert_se(dbus_message_iter_close_container(msg_iter, &device_iter));
- pa_log_info("end of fill signal msg");
-}
-
-static void send_device_connection_changed_signal(uint32_t event_id, pa_tz_device *device, bool connected, pa_device_manager *dm) {
- DBusMessage *signal_msg;
- DBusMessageIter msg_iter;
- dbus_bool_t _connected = connected;
-
- pa_assert(device);
- pa_assert(dm);
-
- pa_log_info("Send device connection changed signal, event_id(%u)", event_id);
-
- pa_assert_se(signal_msg = dbus_message_new_signal(DBUS_OBJECT_DEVICE_MANAGER, DBUS_INTERFACE_DEVICE_MANAGER, "DeviceConnected"));
- dbus_message_iter_init_append(signal_msg, &msg_iter);
- fill_signal_msg_with_device(connected ? "[Connected]" : "[Disconnected]", &msg_iter, event_id, device);
-
- dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_BOOLEAN, &_connected);
-
- pa_assert_se(dbus_connection_send(pa_dbus_connection_get(dm->dbus_conn), signal_msg, NULL));
-
- dbus_message_unref(signal_msg);
- pa_log_info("end of send device connection changed signal");
-}
-
-static void send_device_info_changed_signal(uint32_t event_id, pa_tz_device *device, int changed_type, pa_device_manager *dm) {
- DBusMessage *signal_msg;
- DBusMessageIter msg_iter;
- const char *changed_prefix[] = {"[State Changed]", "[Direction Changed]", "[Avail-Mode Changed]"};
-
- pa_assert(device);
- pa_assert(dm);
-
- pa_log_debug("Send device info changed signal, event_id(%u)", event_id);
-
- pa_assert_se(signal_msg = dbus_message_new_signal(DBUS_OBJECT_DEVICE_MANAGER, DBUS_INTERFACE_DEVICE_MANAGER, "DeviceInfoChanged"));
- dbus_message_iter_init_append(signal_msg, &msg_iter);
- fill_signal_msg_with_device(changed_prefix[changed_type], &msg_iter, event_id, device);
- dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_INT32, &changed_type);
-
- pa_assert_se(dbus_connection_send(pa_dbus_connection_get(dm->dbus_conn), signal_msg, NULL));
-
- dbus_message_unref(signal_msg);
-}
-
-static void send_device_state_changed_signal(uint32_t event_id, pa_tz_device *device, bool activated, pa_device_manager *dm) {
- DBusMessage *signal_msg;
- DBusMessageIter msg_iter;
-
- pa_assert(device);
- pa_assert(dm);
-
- pa_log_debug("Send device state changed signal, event_id(%u)", event_id);
-
- pa_assert_se(signal_msg = dbus_message_new_signal(DBUS_OBJECT_DEVICE_MANAGER, DBUS_INTERFACE_DEVICE_MANAGER, "DeviceStateChanged"));
- dbus_message_iter_init_append(signal_msg, &msg_iter);
- fill_signal_msg_with_device(activated ? "[Activated]" : "[Deactivated]", &msg_iter, event_id, device);
-
- pa_assert_se(dbus_connection_send(pa_dbus_connection_get(dm->dbus_conn), signal_msg, NULL));
-
- dbus_message_unref(signal_msg);
-}
-
-static void send_device_running_changed_signal(uint32_t event_id, pa_tz_device *device, bool is_running, pa_device_manager *dm) {
- DBusMessage *signal_msg;
- DBusMessageIter msg_iter;
-
- pa_assert(device);
- pa_assert(dm);
-
- pa_log_debug("Send device running changed signal, event_id(%u)", event_id);
-
- pa_assert_se(signal_msg = dbus_message_new_signal(DBUS_OBJECT_DEVICE_MANAGER, DBUS_INTERFACE_DEVICE_MANAGER, "DeviceRunningChanged"));
- dbus_message_iter_init_append(signal_msg, &msg_iter);
- fill_signal_msg_with_device(is_running ? "[Running]" : "[NotRunning]", &msg_iter, event_id, device);
-
- pa_assert_se(dbus_connection_send(pa_dbus_connection_get(dm->dbus_conn), signal_msg, NULL));
-
- dbus_message_unref(signal_msg);
-}
-
-static bool device_is_match_direction(pa_tz_device *device, int direction_mask) {
- dm_device_direction_t direction;
-
- if (direction_mask == DEVICE_IO_DIRECTION_FLAGS || direction_mask == 0)
- return true;
-
- direction = pa_tz_device_get_direction(device);
-
- if ((direction_mask & DEVICE_IO_DIRECTION_IN_FLAG) && (direction & DM_DEVICE_DIRECTION_IN))
- return true;
- if ((direction_mask & DEVICE_IO_DIRECTION_OUT_FLAG) && (direction & DM_DEVICE_DIRECTION_OUT))
- return true;
- if ((direction_mask & DEVICE_IO_DIRECTION_BOTH_FLAG) && (direction == DM_DEVICE_DIRECTION_BOTH))
- return true;
-
- return false;
-}
-
-static bool device_is_match_state(pa_tz_device *device, int state_mask) {
- dm_device_state_t state;
-
- if (state_mask == DEVICE_STATE_FLAGS || state_mask == 0)
- return true;
-
- state = pa_tz_device_get_state(device);
-
- if ((state_mask & DEVICE_STATE_DEACTIVATED_FLAG) && (state == DM_DEVICE_STATE_DEACTIVATED))
- return true;
- if ((state_mask & DEVICE_STATE_ACTIVATED_FLAG) && (state == DM_DEVICE_STATE_ACTIVATED))
- return true;
-
- return false;
-}
-
-static bool device_is_match_type(pa_tz_device *device, int type_mask) {
- char *type;
- bool is_builtin;
-
- if (type_mask == DEVICE_TYPE_FLAGS || type_mask == 0)
- return true;
-
- type = pa_tz_device_get_type(device);
- is_builtin = device_type_is_builtin(type);
-
- if ((type_mask & DEVICE_TYPE_INTERNAL_FLAG) && is_builtin)
- return true;
- if ((type_mask & DEVICE_TYPE_EXTERNAL_FLAG) && !is_builtin)
- return true;
-
- return false;
-}
-
-static bool device_is_match_with_mask(pa_tz_device *device, int mask) {
- pa_assert(device);
-
- if (mask == DEVICE_ALL_FLAG)
- return true;
-
- return (device_is_match_direction(device, mask & DEVICE_IO_DIRECTION_FLAGS) &&
- device_is_match_state(device, mask & DEVICE_STATE_FLAGS) &&
- device_is_match_type(device, mask & DEVICE_TYPE_FLAGS));
-}
-
-static int method_call_bt_get_name(DBusConnection *conn, const char *device_path, char **name) {
- const char *intf = DBUS_INTERFACE_BLUEZ_DEVICE, *prop = "Alias";
- DBusMessage *msg, *reply;
- DBusMessageIter reply_iter, variant_iter;
- DBusError err;
-
- pa_assert(conn);
- pa_assert(device_path);
- pa_assert(name);
-
- if (!(msg = dbus_message_new_method_call(DBUS_SERVICE_BLUEZ, device_path, "org.freedesktop.DBus.Properties", "Get"))) {
- pa_log_error("dbus method call failed");
- return -1;
- }
-
- dbus_message_append_args(msg,
- DBUS_TYPE_STRING, &intf,
- DBUS_TYPE_STRING, &prop,
- DBUS_TYPE_INVALID);
-
- dbus_error_init(&err);
- if (!(reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err))) {
- pa_log_error("Failed to method call %s.%s, %s", DBUS_INTERFACE_BLUEZ_DEVICE, "Get", err.message);
- dbus_error_free(&err);
- return -1;
- }
-
- dbus_message_iter_init(reply, &reply_iter);
-
- if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_VARIANT) {
- pa_log_error("Cannot get reply argument");
- return -1;
- }
-
- dbus_message_iter_recurse(&reply_iter, &variant_iter);
-
- if (dbus_message_iter_get_arg_type(&variant_iter) == DBUS_TYPE_STRING) {
- dbus_message_iter_get_basic(&variant_iter, name);
- }
-
- dbus_message_unref(reply);
- return 0;
-}
-
-static void handle_get_connected_device_list(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- pa_device_manager *dm;
- DBusMessage *reply = NULL;
- DBusMessageIter msg_iter, array_iter, device_iter;
- pa_tz_device *device;
- dm_device_state_t state;
- uint32_t device_idx;
- dbus_int32_t device_id, direction;
- int mask;
- char *type, *name;
- dbus_int32_t vendor_id, product_id;
- dbus_bool_t is_running;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(userdata);
-
-
- dm = (pa_device_manager*) userdata;
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
-
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_INT32, &mask,
- DBUS_TYPE_INVALID));
-
- pa_log_info("Get connected device list (mask : %d)", mask);
-
- dbus_message_iter_init_append(reply, &msg_iter);
- pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "(isiisiib)", &array_iter));
-
- PA_IDXSET_FOREACH(device, dm->device_list, device_idx) {
- device_id = (dbus_int32_t)pa_tz_device_get_id(device);
- state = pa_tz_device_get_state(device);
- direction = pa_tz_device_get_direction(device);
- type = pa_tz_device_get_type(device);
- name = pa_tz_device_get_name(device);
- vendor_id = (dbus_int32_t) pa_tz_device_get_vendor_id(device);
- product_id = (dbus_int32_t) pa_tz_device_get_product_id(device);
- product_id = (dbus_int32_t) pa_tz_device_get_product_id(device);
- is_running = (dbus_bool_t) pa_tz_device_is_running(device);
- if (device_is_match_with_mask(device, mask)) {
- simple_device_dump(PA_LOG_INFO, "[MATCH]", device_id, type, name, direction, state);
- pa_assert_se(dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &device_iter));
- dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &device_id);
- dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_STRING, &type);
- dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &direction);
- dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &state);
- dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_STRING, &name);
- dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &vendor_id);
- dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &product_id);
- dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_BOOLEAN, &is_running);
- pa_assert_se(dbus_message_iter_close_container(&array_iter, &device_iter));
- } else {
- simple_device_dump(PA_LOG_INFO, "[UNMATCH]", device_id, type, name, direction, state);
- }
- }
-
- pa_assert_se(dbus_message_iter_close_container(&msg_iter, &array_iter));
-
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static void handle_get_device_by_id(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- pa_device_manager *manager;
- DBusMessage *reply;
- DBusMessageIter msg_iter;
- pa_tz_device *device;
- dbus_int32_t device_id;
- dbus_int32_t id, direction, state;
- dbus_int32_t vendor_id, product_id;
- char *type, *name;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(userdata);
-
- manager = (pa_device_manager*) userdata;
-
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_INT32, &device_id,
- DBUS_TYPE_INVALID));
-
- pa_log_info("Get device by id(%d)", device_id);
-
- if ((device = _device_list_get_device_by_id(manager, device_id))) {
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
- dbus_message_iter_init_append(reply, &msg_iter);
-
- id = (dbus_int32_t)pa_tz_device_get_id(device);
- state = pa_tz_device_get_state(device);
- direction = pa_tz_device_get_direction(device);
- type = pa_tz_device_get_type(device);
- name = pa_tz_device_get_name(device);
- vendor_id = (dbus_int32_t) pa_tz_device_get_vendor_id(device);
- product_id = (dbus_int32_t) pa_tz_device_get_product_id(device);
-
- simple_device_dump(PA_LOG_INFO, "[GET_BY_ID]", device_id, type, name, direction, state);
-
- dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_INT32, &id);
- dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &type);
- dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_INT32, &direction);
- dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_INT32, &state);
- dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &name);
- dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_INT32, &vendor_id);
- dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_INT32, &product_id);
-
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
- } else {
- pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "%s", "org.tizen.multimedia.audio.Internal");
- }
-}
-
-static void handle_is_stream_on_device(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- pa_device_manager *manager;
- DBusMessage *reply;
- pa_tz_device *device;
- dbus_bool_t is_on = false;
- dbus_int32_t stream_id, device_id;
- pa_intset *stream_id_set;
- int32_t stream_id_val;
- int ret;
- dm_device_state_t state;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(userdata);
-
- pa_log_info("Is stream on device");
-
- manager = (pa_device_manager*) userdata;
-
-
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_INT32, &stream_id,
- DBUS_TYPE_INT32, &device_id,
- DBUS_TYPE_INVALID));
-
- if ((device = _device_list_get_device_by_id(manager, device_id))) {
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
-
- state = pa_tz_device_get_state(device);
- if (state == DM_DEVICE_STATE_ACTIVATED) {
- stream_id_set = pa_tz_device_get_stream_list(device);
- PA_INTSET_FOREACH(stream_id_val, stream_id_set, ret) {
- if (stream_id_val == stream_id) {
- is_on = true;
- pa_log_info("stream(%d) is on device(%d)", stream_id, device_id);
- break;
- }
- }
- pa_intset_free(stream_id_set);
- } else {
- pa_log_info("device(%d) is not activated, regard as no stream on it", device_id);
- is_on = false;
- }
-
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &is_on,
- DBUS_TYPE_INVALID));
-
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
- } else {
- pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.Internal");
- }
-}
-
-static void handle_get_bt_a2dp_status(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- pa_device_manager *dm;
- DBusMessage *reply = NULL;
- pa_tz_device *device;
- dbus_bool_t is_bt_on = false;
- const char *bt_name = "none";
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(userdata);
-
- pa_log_info("Get BT A2DP list");
-
- dm = (pa_device_manager*) userdata;
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
-
- /* FIXME : Give system_id for multi device */
- if ((device = _device_list_get_device(dm, DEVICE_TYPE_BT_A2DP, NULL)) != NULL) {
- is_bt_on = true;
- bt_name = pa_tz_device_get_name(device);
- }
-
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &is_bt_on,
- DBUS_TYPE_STRING, &bt_name,
- DBUS_TYPE_INVALID));
-
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-
-
-static void handle_load_sink(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- pa_device_manager *dm;
- char *type, *role;
- DBusMessage *reply = NULL;
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
- dm = (pa_device_manager *) userdata;
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_STRING, &type,
- DBUS_TYPE_STRING, &role,
- DBUS_TYPE_INVALID));
-
- pa_device_manager_load_sink(dm, type, role);
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static void handle_unload_sink(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- pa_device_manager *dm;
- char *type, *role;
- DBusMessage *reply = NULL;
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
- dm = (pa_device_manager *) userdata;
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_STRING, &type,
- DBUS_TYPE_STRING, &role,
- DBUS_TYPE_INVALID));
-
- pa_device_manager_unload_sink(dm, type, role);
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static void handle_unload_sink_with_device_string(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- pa_device_manager *dm;
- char *device_string;
- DBusMessage *reply = NULL;
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
- dm = (pa_device_manager *) userdata;
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_STRING, &device_string,
- DBUS_TYPE_INVALID));
-
- pa_device_manager_unload_sink_with_device_string(dm, device_string);
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static void handle_get_device_string(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- pa_device_manager *dm;
- char *type, *role;
- const char *device_string;
- dbus_bool_t is_playback;
- DBusMessage *reply;
-
- dm = (pa_device_manager *) userdata;
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_BOOLEAN, &is_playback,
- DBUS_TYPE_STRING, &type,
- DBUS_TYPE_STRING, &role,
- DBUS_TYPE_INVALID));
-
- device_string = pa_device_manager_get_device_string(dm, is_playback, type, role);
- if (device_string == NULL) {
- pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "%s", "org.tizen.multimedia.audio.Internal");
- return;
- }
-
- pa_log_info("device string : %s", device_string);
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &device_string,
- DBUS_TYPE_INVALID));
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static void handle_dump_device_list(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- pa_device_manager *dm;
- pa_tz_device *device;
- uint32_t device_idx;
- DBusMessage *reply = NULL;
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
- dm = (pa_device_manager *) userdata;
-
- PA_IDXSET_FOREACH(device, dm->device_list, device_idx) {
- pa_tz_device_dump_info(device, PA_LOG_INFO);
- }
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static bool is_usb_output_device(pa_tz_device *device) {
- char *type;
- dm_device_direction_t direction;
- pa_sink *sink;
-
- pa_assert(device);
-
- type = pa_tz_device_get_type(device);
- if (!pa_streq(type, DEVICE_TYPE_USB_AUDIO)) {
- pa_log_error("device(id:%d, %s) is not USB AUDIO type", pa_tz_device_get_id(device), type);
- return false;
- }
- direction = pa_tz_device_get_direction(device);
- if (direction & DM_DEVICE_DIRECTION_OUT) {
- if (!(sink = pa_tz_device_get_sink(device, DEVICE_ROLE_NORMAL))) {
- pa_log_error("sink is null");
- return false;
- }
- } else {
- pa_log_error("this device is not for output");
- return false;
- }
-
- return true;
-}
-
-
-static bool is_supported_sample_format(pa_sample_format_t *supported_sample_formats, pa_sample_format_t sample_format) {
- int i;
-
- pa_assert(supported_sample_formats);
- pa_assert(sample_format != PA_SAMPLE_INVALID);
-
- for (i = 0; supported_sample_formats[i] != PA_SAMPLE_MAX; i++) {
- if (supported_sample_formats[i] == sample_format) {
- pa_log_info("%s is supported", pa_sample_format_to_string(sample_format));
- return true;
- }
- }
- pa_log_error("%s is not supported", pa_sample_format_to_string(sample_format));
- return false;
-}
-
-static void handle_get_supported_sample_formats(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- pa_device_manager *dm;
- DBusMessage *reply = NULL;
- DBusMessageIter msg_iter, array_iter, item_iter;
- dbus_int32_t device_id;
- pa_tz_device *device;
- pa_sink *sink;
- const char *format;
- int i;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(userdata);
-
- dm = (pa_device_manager *)userdata;
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
-
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_INT32, &device_id,
- DBUS_TYPE_INVALID));
-
- pa_log_info("Get supported sample formats of the device(id:%d)", device_id);
-
- if (!(device = _device_list_get_device_by_id(dm, device_id))) {
- pa_log_error("could not find any device with id:%d", device_id);
- pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
- return;
- }
- if (!is_usb_output_device(device)) {
- pa_dbus_send_error(conn, msg, DBUS_ERROR_NOT_SUPPORTED, "%s", "org.tizen.multimedia.audio.PolicyInternal");
- return;
- }
- if (!(sink = pa_tz_device_get_sink(device, DEVICE_ROLE_NORMAL))) {
- pa_log_error("could not get sink for normal role");
- pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
- return;
- }
-
- dbus_message_iter_init_append(reply, &msg_iter);
- pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "(s)", &array_iter));
- for (i = 0; sink->supported_sample_formats[i] != PA_SAMPLE_MAX; i++) {
- format = pa_sample_format_to_string(sink->supported_sample_formats[i]);
- pa_log_info("%s is supported", format);
- pa_assert_se(dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &item_iter));
- dbus_message_iter_append_basic(&item_iter, DBUS_TYPE_STRING, &format);
- pa_assert_se(dbus_message_iter_close_container(&array_iter, &item_iter));
- }
- pa_assert_se(dbus_message_iter_close_container(&msg_iter, &array_iter));
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static void handle_set_sample_format(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- pa_device_manager *dm;
- DBusMessage *reply = NULL;
- dbus_int32_t device_id;
- char *sample_format;
- pa_sample_format_t prev_selected_sample_format;
- pa_tz_device *device;
- pa_sink *sink;
- pa_sample_spec spec;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(userdata);
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
- dm = (pa_device_manager *)userdata;
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_INT32, &device_id,
- DBUS_TYPE_STRING, &sample_format,
- DBUS_TYPE_INVALID));
-
- pa_log_info("Set sample format(%s) of the device(id:%d)", sample_format, device_id);
-
- if (!(device = _device_list_get_device_by_id(dm, device_id))) {
- pa_log_error("could not find any device with id:%d", device_id);
- pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
- return;
- }
- if (!is_usb_output_device(device)) {
- pa_dbus_send_error(conn, msg, DBUS_ERROR_NOT_SUPPORTED, "%s", "org.tizen.multimedia.audio.PolicyInternal");
- return;
- }
- if (!(sink = pa_tz_device_get_sink(device, DEVICE_ROLE_NORMAL))) {
- pa_log_error("could not get sink for normal role");
- pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
- return;
- }
-
- /* use a supported sample format selected by user */
- if (!is_supported_sample_format(sink->supported_sample_formats, pa_parse_sample_format(sample_format))) {
- pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
- return;
- }
- prev_selected_sample_format = sink->selected_sample_format;
- sink->selected_sample_format = pa_parse_sample_format(sample_format);
-
- FILL_SAMPLE_SPEC_WITH_SELECTED(sink, spec);
- if (pa_sink_reconfigure(sink, &spec, false) == -1) {
- pa_log_error("failed to reconfigure");
- pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "%s", "org.tizen.multimedia.audio.Internal");
- sink->selected_sample_format = prev_selected_sample_format;
- return;
- }
-
- save_preference(dm, sink);
-
- pa_log_info("Set sample format(%s) of the device(id:%d) successfully", sample_format, device_id);
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static void handle_get_sample_format(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- pa_device_manager *dm;
- DBusMessage *reply = NULL;
- dbus_int32_t device_id;
- pa_tz_device *device;
- pa_sink *sink;
- const char *format;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(userdata);
-
- dm = (pa_device_manager *)userdata;
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
-
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_INT32, &device_id,
- DBUS_TYPE_INVALID));
-
- pa_log_info("Get sample format of the device(id:%d)", device_id);
-
- if (!(device = _device_list_get_device_by_id(dm, device_id))) {
- pa_log_error("could not find any device with id:%d", device_id);
- pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
- return;
- }
- if (!is_usb_output_device(device)) {
- pa_dbus_send_error(conn, msg, DBUS_ERROR_NOT_SUPPORTED, "%s", "org.tizen.multimedia.audio.PolicyInternal");
- return;
- }
- if (!(sink = pa_tz_device_get_sink(device, DEVICE_ROLE_NORMAL))) {
- pa_log_error("could not get sink for normal role");
- pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
- return;
- }
-
- format = pa_sample_format_to_string(sink->selected_sample_format);
- pa_log_info("Get sample format(%s) of the device(id:%d) successfully", format, device_id);
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &format, DBUS_TYPE_INVALID));
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static bool is_supported_sample_rate(uint32_t *supported_sample_rates, uint32_t sample_rate) {
- int i;
-
- pa_assert(supported_sample_rates);
-
- for (i = 0; supported_sample_rates[i]; i++) {
- if (supported_sample_rates[i] == sample_rate) {
- pa_log_info("%u is supported", sample_rate);
- return true;
- }
- }
- pa_log_error("%u is not supported", sample_rate);
- return false;
-}
-
-static void handle_get_supported_sample_rates(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- pa_device_manager *dm;
- DBusMessage *reply = NULL;
- DBusMessageIter msg_iter, array_iter, item_iter;
- dbus_int32_t device_id;
- pa_tz_device *device;
- pa_sink *sink;
- int i;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(userdata);
-
- dm = (pa_device_manager *)userdata;
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
-
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_INT32, &device_id,
- DBUS_TYPE_INVALID));
-
- pa_log_info("Get supported sample rates of the device(id:%d)", device_id);
-
- if (!(device = _device_list_get_device_by_id(dm, device_id))) {
- pa_log_error("could not find any device with id:%d", device_id);
- pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
- return;
- }
- if (!is_usb_output_device(device)) {
- pa_dbus_send_error(conn, msg, DBUS_ERROR_NOT_SUPPORTED, "%s", "org.tizen.multimedia.audio.PolicyInternal");
- return;
- }
- if (!(sink = pa_tz_device_get_sink(device, DEVICE_ROLE_NORMAL))) {
- pa_log_error("could not get sink for normal role");
- pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
- return;
- }
-
- dbus_message_iter_init_append(reply, &msg_iter);
- pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "(u)", &array_iter));
- for (i = 0; sink->supported_sample_rates[i]; i++) {
- pa_log_info("%u is supported", sink->supported_sample_rates[i]);
- pa_assert_se(dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &item_iter));
- dbus_message_iter_append_basic(&item_iter, DBUS_TYPE_UINT32, &sink->supported_sample_rates[i]);
- pa_assert_se(dbus_message_iter_close_container(&array_iter, &item_iter));
- }
- pa_assert_se(dbus_message_iter_close_container(&msg_iter, &array_iter));
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static void handle_set_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- pa_device_manager *dm;
- DBusMessage *reply = NULL;
- dbus_int32_t device_id;
- dbus_uint32_t sample_rate;
- uint32_t prev_selected_sample_rate;
- pa_tz_device *device;
- pa_sink *sink;
- pa_sample_spec spec;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(userdata);
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
- dm = (pa_device_manager *)userdata;
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_INT32, &device_id,
- DBUS_TYPE_UINT32, &sample_rate,
- DBUS_TYPE_INVALID));
-
- pa_log_info("Set sample rate(%u) of the device(id:%d)", sample_rate, device_id);
-
- if (!(device = _device_list_get_device_by_id(dm, device_id))) {
- pa_log_error("could not find any device with id:%d", device_id);
- pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
- return;
- }
- if (!is_usb_output_device(device)) {
- pa_dbus_send_error(conn, msg, DBUS_ERROR_NOT_SUPPORTED, "%s", "org.tizen.multimedia.audio.PolicyInternal");
- return;
- }
- if (!(sink = pa_tz_device_get_sink(device, DEVICE_ROLE_NORMAL))) {
- pa_log_error("could not get sink for normal role");
- pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
- return;
- }
-
- /* use a supported sample rate selected by user */
- if (!is_supported_sample_rate(sink->supported_sample_rates, sample_rate)) {
- pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
- return;
- }
- prev_selected_sample_rate = sink->selected_sample_rate;
- sink->selected_sample_rate = sample_rate;
-
- FILL_SAMPLE_SPEC_WITH_SELECTED(sink, spec);
- if (pa_sink_reconfigure(sink, &spec, false) == -1) {
- pa_log_error("failed to reconfigure");
- pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "%s", "org.tizen.multimedia.audio.Internal");
- sink->selected_sample_rate = prev_selected_sample_rate;
- return;
- }
-
- save_preference(dm, sink);
-
- pa_log_info("Set sample rate(%u) of the device(id:%d) successfully", sample_rate, device_id);
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static void handle_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- pa_device_manager *dm;
- DBusMessage *reply = NULL;
- dbus_int32_t device_id;
- pa_tz_device *device;
- pa_sink *sink;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(userdata);
-
- dm = (pa_device_manager *)userdata;
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
-
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_INT32, &device_id,
- DBUS_TYPE_INVALID));
-
- pa_log_info("Get sample rate of the device(id:%d)", device_id);
-
- if (!(device = _device_list_get_device_by_id(dm, device_id))) {
- pa_log_error("could not find any device with id:%d", device_id);
- pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
- return;
- }
- if (!is_usb_output_device(device)) {
- pa_dbus_send_error(conn, msg, DBUS_ERROR_NOT_SUPPORTED, "%s", "org.tizen.multimedia.audio.PolicyInternal");
- return;
- }
- if (!(sink = pa_tz_device_get_sink(device, DEVICE_ROLE_NORMAL))) {
- pa_log_error("could not get sink for normal role");
- pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
- return;
- }
-
- pa_log_info("Get sample rate(%u) of the device(id:%d) successfully", sink->selected_sample_rate, device_id);
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_UINT32, &sink->selected_sample_rate, DBUS_TYPE_INVALID));
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static void handle_set_specific_stream_only(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- pa_device_manager *dm;
- DBusMessage *reply = NULL;
- dbus_int32_t device_id;
- char *stream_role;
- pa_tz_device *device;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(userdata);
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
- dm = (pa_device_manager *)userdata;
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_INT32, &device_id,
- DBUS_TYPE_STRING, &stream_role,
- DBUS_TYPE_INVALID));
-
- pa_log_info("Set the device(id:%d) only for the stream role(%s)", device_id, stream_role);
-
- if (!(device = _device_list_get_device_by_id(dm, device_id))) {
- pa_log_error("could not find any device with id:%d", device_id);
- pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
- return;
- }
- if (!is_usb_output_device(device)) {
- pa_dbus_send_error(conn, msg, DBUS_ERROR_NOT_SUPPORTED, "%s", "org.tizen.multimedia.audio.PolicyInternal");
- return;
- }
- if (!pa_stream_manager_is_valid_stream_role(dm->core, stream_role)) {
- pa_dbus_send_error(conn, msg, DBUS_ERROR_NOT_SUPPORTED, "%s", "org.tizen.multimedia.audio.InvalidArgument");
- return;
- }
-
- device->specified_stream_role = stream_role;
-
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static void handle_get_specified_stream(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- pa_device_manager *dm;
- DBusMessage *reply = NULL;
- dbus_int32_t device_id;
- char *specified_stream_role;
- pa_tz_device *device;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(userdata);
-
- dm = (pa_device_manager *)userdata;
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
-
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_INT32, &device_id,
- DBUS_TYPE_INVALID));
-
- pa_log_info("Get specified stream role for the device(id:%d)", device_id);
-
- if (!(device = _device_list_get_device_by_id(dm, device_id))) {
- pa_log_error("could not find any device with id:%d", device_id);
- pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
- return;
- }
- if (!is_usb_output_device(device)) {
- pa_dbus_send_error(conn, msg, DBUS_ERROR_NOT_SUPPORTED, "%s", "org.tizen.multimedia.audio.PolicyInternal");
- return;
- }
-
- specified_stream_role = device->specified_stream_role;
-
- pa_log_info("stream role(%s) is specified for the device(id:%d)", device->specified_stream_role, device_id);
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &specified_stream_role, DBUS_TYPE_INVALID));
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static void handle_set_avoid_resampling(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- pa_device_manager *dm;
- DBusMessage *reply = NULL;
- dbus_int32_t device_id;
- dbus_bool_t avoid_resampling;
- pa_tz_device *device;
- pa_sink *sink;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(userdata);
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
- dm = (pa_device_manager *)userdata;
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_INT32, &device_id,
- DBUS_TYPE_BOOLEAN, &avoid_resampling,
- DBUS_TYPE_INVALID));
-
- pa_log_info("Set the device(id:%d) avoid-resampling(%d)", device_id, avoid_resampling);
-
- if (!(device = _device_list_get_device_by_id(dm, device_id))) {
- pa_log_error("could not find any device with id:%d", device_id);
- pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
- return;
- }
- if (!is_usb_output_device(device)) {
- pa_dbus_send_error(conn, msg, DBUS_ERROR_NOT_SUPPORTED, "%s", "org.tizen.multimedia.audio.PolicyInternal");
- return;
- }
- if (!(sink = pa_tz_device_get_sink(device, DEVICE_ROLE_NORMAL))) {
- pa_log_error("could not get sink for normal role");
- pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
- return;
- }
- if (sink->avoid_resampling == avoid_resampling) {
- pa_log_info("already set to %d", avoid_resampling);
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
- return;
- }
-
- sink->avoid_resampling = avoid_resampling;
-
- save_preference(dm, sink);
-
- pa_log_info("Set avoid-resampling(%d) to the device(id:%d)", avoid_resampling, device_id);
-
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static void handle_get_avoid_resampling(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- pa_device_manager *dm;
- DBusMessage *reply = NULL;
- dbus_int32_t device_id;
- dbus_bool_t avoid_resampling;
- pa_tz_device *device;
- pa_sink *sink;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(userdata);
-
- dm = (pa_device_manager *)userdata;
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
-
- pa_assert_se(dbus_message_get_args(msg, NULL,
- DBUS_TYPE_INT32, &device_id,
- DBUS_TYPE_INVALID));
-
- pa_log_info("Get avoid-resampling of the device(id:%d)", device_id);
-
- if (!(device = _device_list_get_device_by_id(dm, device_id))) {
- pa_log_error("could not find any device with id:%d", device_id);
- pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
- return;
- }
- if (!is_usb_output_device(device)) {
- pa_dbus_send_error(conn, msg, DBUS_ERROR_NOT_SUPPORTED, "%s", "org.tizen.multimedia.audio.PolicyInternal");
- return;
- }
- if (!(sink = pa_tz_device_get_sink(device, DEVICE_ROLE_NORMAL))) {
- pa_log_error("could not get sink for normal role");
- pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", "org.tizen.multimedia.audio.InvalidArgument");
- return;
- }
-
- avoid_resampling = sink->avoid_resampling;
- pa_log_info("got avoid-resampling(%d) of the device(id:%d)", avoid_resampling, device_id);
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
- pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &avoid_resampling, DBUS_TYPE_INVALID));
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static void handle_test_device_status_change(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- pa_device_manager *dm = (pa_device_manager *)userdata;
- char *type;
- dbus_int32_t status;
- DBusMessage *reply = NULL;
- DBusError error;
-
- pa_assert_se((reply = dbus_message_new_method_return(msg)));
-
- dbus_error_init(&error);
- if (!dbus_message_get_args(msg, NULL,
- DBUS_TYPE_STRING, &type,
- DBUS_TYPE_INT32, &status,
- DBUS_TYPE_INVALID)) {
- pa_log_error("failed to get dbus args : %s", error.message);
- pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
- dbus_error_free(&error);
- }
-
- pa_log_debug("handle_test_device_status_change, type:%s, status:%d", type, status);
-
- handle_device_status_changed(dm, type, NULL, NULL, status);
- pa_assert_se(dbus_connection_send(conn, reply, NULL));
- dbus_message_unref(reply);
-}
-
-static DBusHandlerResult handle_introspect(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- const char *xml = DEVICE_MANAGER_INTROSPECT_XML;
- DBusMessage *r = NULL;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(userdata);
-
- pa_assert_se(r = dbus_message_new_method_return(msg));
- pa_assert_se(dbus_message_append_args(r, DBUS_TYPE_STRING, &xml, DBUS_TYPE_INVALID));
-
- if (r) {
- pa_assert_se(dbus_connection_send((conn), r, NULL));
- dbus_message_unref(r);
- }
-
- return DBUS_HANDLER_RESULT_HANDLED;
-}
-
-static DBusHandlerResult handle_device_manager_methods(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- int method_idx = 0;
-
- pa_assert(conn);
- pa_assert(msg);
- pa_assert(userdata);
-
- for (method_idx = 0; method_idx < METHOD_HANDLER_MAX; method_idx++) {
- if (dbus_message_is_method_call(msg, DBUS_INTERFACE_DEVICE_MANAGER, method_handlers[method_idx].method_name)) {
- method_handlers[method_idx].receive_cb(conn, msg, userdata);
- return DBUS_HANDLER_RESULT_HANDLED;
- }
- }
-
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
-
-static DBusHandlerResult method_call_handler(DBusConnection *c, DBusMessage *m, void *userdata) {
- struct userdata *u = userdata;
- const char *path, *interface, *member;
-
- pa_assert(c);
- pa_assert(m);
- pa_assert(u);
-
- path = dbus_message_get_path(m);
- interface = dbus_message_get_interface(m);
- member = dbus_message_get_member(m);
-
- pa_log_info("DeviceManager Method Call Handler : path=%s, interface=%s, member=%s", path, interface, member);
-
- if (!pa_streq(path, DBUS_OBJECT_DEVICE_MANAGER))
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
- if (dbus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
- return handle_introspect(c, m, u);
- /*
- } else if (dbus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "Get")) {
- return handle_get_property(c, m, u);
- } else if (dbus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "Set")) {
- return handle_set_property(c, m, u);
- } else if (dbus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "GetAll")) {
- return handle_get_all_property(c, m, u);
- */
- } else {
- return handle_device_manager_methods(c, m, u);
- }
-
- return DBUS_HANDLER_RESULT_HANDLED;
-}
-
-static void endpoint_init(pa_device_manager *dm) {
- static const DBusObjectPathVTable vtable_endpoint = {
- .message_function = method_call_handler,
- };
-
- pa_log_info("Device manager dbus endpoint init");
-
- if (dm && dm->dbus_conn) {
- if (!dbus_connection_register_object_path(pa_dbus_connection_get(dm->dbus_conn), DBUS_OBJECT_DEVICE_MANAGER, &vtable_endpoint, dm))
- pa_log_error("Failed to register object path");
- } else {
- pa_log_error("Cannot get dbus connection to register object path");
- }
-}
-
-static void endpoint_done(pa_device_manager *dm) {
- pa_log_info("Device manager dbus endpoint done");
- if (dm && dm->dbus_conn) {
- if (!dbus_connection_unregister_object_path(pa_dbus_connection_get(dm->dbus_conn), DBUS_OBJECT_DEVICE_MANAGER))
- pa_log_error("Failed to unregister object path");
- } else {
- pa_log_error("Cannot get dbus connection to unregister object path");
- }
-}
-
-static void init_dbus(pa_device_manager *dm) {
- DBusError error;
- pa_dbus_connection *connection = NULL;
-
- pa_assert(dm);
- pa_log_info("init Dbus");
- dbus_error_init(&error);
-
- if (!(connection = pa_dbus_bus_get(dm->core, DBUS_BUS_SYSTEM, &error)) || dbus_error_is_set(&error)) {
- if (connection) {
- pa_dbus_connection_unref(connection);
- }
- pa_log_error("Unable to contact D-Bus system bus: %s: %s", error.name, error.message);
- goto fail;
- } else {
- pa_log_info("Got dbus connection");
- }
-
- dm->dbus_conn = connection;
-
- if (watch_signals(dm) < 0)
- pa_log_error("dbus watch signals failed");
- else
- pa_log_debug("dbus ready to get signals");
-
- endpoint_init(dm);
-
-fail:
- dbus_error_free(&error);
-}
-
-static void deinit_dbus(pa_device_manager *dm) {
- pa_assert(dm);
-
- pa_log_info("deinit Dbus");
-
- endpoint_done(dm);
- unwatch_signals(dm);
-
- if (dm->dbus_conn) {
- pa_dbus_connection_unref(dm->dbus_conn);
- dm->dbus_conn = NULL;
- }
-}
-#endif
-
pa_idxset* pa_device_manager_get_device_list(pa_device_manager *dm) {
pa_assert(dm);
pa_assert(dm->device_list);
pa_tz_device* pa_device_manager_get_device(pa_device_manager *dm, const char *type) {
pa_assert(dm);
- return _device_list_get_device(dm, type, NULL);
+ return device_list_get_device(dm, type, NULL);
}
pa_tz_device* pa_device_manager_get_device_by_id(pa_device_manager *dm, uint32_t id) {
pa_assert(dm);
- return _device_list_get_device_by_id(dm, id);
+ return device_list_get_device_by_id(dm, id);
}
pa_tz_device* pa_device_manager_get_device_with_sink(pa_sink *sink) {
void pa_device_manager_unload_forwarding(pa_device_manager *dm) {
pa_tz_device *forwarding_device;
- forwarding_device = _device_list_get_device(dm, DEVICE_TYPE_FORWARDING, NULL);
+ forwarding_device = device_list_get_device(dm, DEVICE_TYPE_FORWARDING, NULL);
if (forwarding_device)
pa_tz_device_free(forwarding_device);
else
init_database(dm);
- init_dbus(dm);
+ init_dm_dbus(dm);
dm->sink_put_hook_slot = pa_hook_connect(&dm->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_LATE+10, (pa_hook_cb_t) sink_put_hook_callback, dm);
dm->sink_unlink_hook_slot = pa_hook_connect(&dm->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_EARLY, (pa_hook_cb_t) sink_unlink_hook_callback, dm);
if (dm->device_status)
pa_idxset_free(dm->device_status, NULL);
- deinit_dbus(dm);
+ deinit_dm_dbus(dm);
deinit_database(dm);