" <arg name=\"device_type\" direction=\"in\" type=\"s\"/>\n" \
" <arg name=\"role\" direction=\"in\" 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=\"DumpDeviceList\">\n" \
" </method>\n" \
" <method name=\"TestStatusChange\">\n" \
" </interface>\n" \
"</node>\n"
-
#define FILTER_DEVICED_SYSNOTI \
"type='signal'," \
" interface='" DBUS_INTERFACE_DEVICED_SYSNOTI "'"
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_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_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);
METHOD_HANDLER_UNLOAD_SINK,
METHOD_HANDLER_UNLOAD_SINK_WITH_DEVICE_STRING,
METHOD_HANDLER_GET_DEVICE_STRING,
+ METHOD_HANDLER_GET_SUPPORTED_SAMPLE_RATES,
+ METHOD_HANDLER_SET_SAMPLE_RATE,
+ METHOD_HANDLER_GET_SAMPLE_RATE,
METHOD_HANDLER_DUMP_DEVICE_LIST,
METHOD_HANDLER_STATUS_TEST,
METHOD_HANDLER_MAX
[METHOD_HANDLER_GET_DEVICE_STRING] = {
.method_name = "GetDeviceString",
.receive_cb = handle_get_device_string },
+ [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_DUMP_DEVICE_LIST] = {
.method_name = "DumpDeviceList",
.receive_cb = handle_dump_device_list },
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_rate(uint32_t *supported_sample_rates, uint32_t sample_rate) {
+ int i;
+
+ pa_assert(supported_sample_rates);
+
+ /* use a supported sample rate selected by user */
+ 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;
+ }
+ sink = pa_tz_device_get_sink(device, DEVICE_ROLE_NORMAL);
+
+ 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_sink_input *si;
+ uint32_t idx;
+
+ 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;
+ }
+ sink = pa_tz_device_get_sink(device, DEVICE_ROLE_NORMAL);
+
+ /* use stream original sample rate if possible */
+ if (sample_rate == 0) {
+ sink->avoid_resampling = true;
+ PA_IDXSET_FOREACH(si, sink->inputs, idx) {
+ if (pa_sink_reconfigure(sink, &si->sample_spec, pa_sink_input_is_passthrough(si)) == -1) {
+ pa_log_error("failed to reconfigure");
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "%s", "org.tizen.multimedia.audio.Internal");
+ sink->avoid_resampling = sink->origin_avoid_resampling;
+ return;
+ }
+ }
+ sink->selected_sample_rate = 0;
+
+ pa_log_info("Set sample rate to avoid resampling for the device(%u) successfully", device_id);
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+ 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;
+
+ PA_IDXSET_FOREACH(si, sink->inputs, idx) {
+ if (pa_sink_reconfigure(sink, &si->sample_spec, pa_sink_input_is_passthrough(si)) == -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;
+ }
+ break;
+ }
+ sink->avoid_resampling = sink->origin_avoid_resampling;
+
+ 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;
+ }
+ sink = pa_tz_device_get_sink(device, DEVICE_ROLE_NORMAL);
+
+ 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_test_device_status_change(DBusConnection *conn, DBusMessage *msg, void *userdata) {
pa_device_manager *dm = (pa_device_manager *)userdata;
char *type;