#define DEVICE_FILE_STRING_MAX 4
#define DEVICE_TYPE_STR_MAX 20
#define DEVICE_ROLE_STR_MAX 15
+#define DEVICE_KEY_STR_MAX 12
#define DEVICE_TYPE_OBJECT "device-types"
#define DEVICE_FILE_OBJECT "device-files"
#define DEVICE_TYPE_STR_MAX 20
+
/* Properties of sink/sources */
#define DEVICE_API_BLUEZ "bluez"
#define DEVICE_API_ALSA "alsa"
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",
return source;
}
-static void handle_usb_pulse_device(pa_object *pdevice, bool is_loaded, pa_device_manager *manager) {
+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;
+ bool do_reconfigure = false;
+
+ pa_assert(dm);
+ pa_assert(sink);
+
+ if (!(key = build_key_from_proplist(sink->proplist)))
+ return;
+
+ if (!(e = read_prefer_entry(dm, key)))
+ return;
+
+ if (sink->avoid_resampling != e->avoid_resampling) {
+ sink->avoid_resampling = e->avoid_resampling;
+ do_reconfigure = true;
+ }
+ if (sink->selected_sample_format != e->format) {
+ sink->selected_sample_format = e->format;
+ do_reconfigure = true;
+ }
+ if (sink->selected_sample_rate != e->rate) {
+ sink->selected_sample_rate = e->rate;
+ do_reconfigure = true;
+ }
+
+ if (do_reconfigure) {
+ pa_sample_spec spec;
+ FILL_SAMPLE_SPEC_WITH_PREFER_ENTRY(e, spec);
+ 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 *device;
pa_assert(pdevice);
- pa_assert(manager);
+ pa_assert(dm);
pa_log_info("Handle usb pulse device");
vendor_id = pulse_device_get_vendor_id(pdevice);
product_id = pulse_device_get_product_id(pdevice);
- pa_tz_device_new_data_init(&data, manager->device_list, manager->comm, NULL);
+ pa_tz_device_new_data_init(&data, dm->device_list, dm->comm, NULL);
pa_tz_device_new_data_set_type(&data, DEVICE_TYPE_USB_AUDIO);
pa_tz_device_new_data_set_name(&data, name);
pa_tz_device_new_data_set_direction(&data, direction);
if (product_id > 0)
pa_tz_device_new_data_set_product_id(&data, product_id);
pa_tz_device_new_data_set_use_internal_codec(&data, false);
- if (direction == DM_DEVICE_DIRECTION_OUT)
+ if (direction == DM_DEVICE_DIRECTION_OUT) {
+ apply_preference(dm, PA_SINK(pdevice));
pa_tz_device_new_data_add_sink(&data, DEVICE_ROLE_NORMAL, PA_SINK(pdevice));
- else
+ } else {
pa_tz_device_new_data_add_source(&data, DEVICE_ROLE_NORMAL, PA_SOURCE(pdevice));
+ }
pa_tz_device_new(&data);
pa_tz_device_new_data_done(&data);
} else {
- if (!(device = _device_list_get_device(manager, 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);
}
}
-static void handle_bt_pulse_device(pa_object *pdevice, bool is_loaded, pa_device_manager *manager) {
+static void handle_bt_pulse_device(pa_object *pdevice, bool is_loaded, pa_device_manager *dm) {
dm_device_direction_t direction;
pa_tz_device *device;
const char *system_id;
pa_assert(pdevice);
- pa_assert(manager);
+ pa_assert(dm);
pa_log_info("Handle bt pulse device");
const char *name;
name = pulse_device_get_device_name(pdevice, DEVICE_TYPE_BT_A2DP);
- pa_tz_device_new_data_init(&data, manager->device_list, manager->comm, manager->dbus_conn);
- _fill_new_data_basic(&data, DEVICE_TYPE_BT_A2DP, direction, false, manager);
+ pa_tz_device_new_data_init(&data, dm->device_list, dm->comm, dm->dbus_conn);
+ _fill_new_data_basic(&data, DEVICE_TYPE_BT_A2DP, direction, false, dm);
pa_tz_device_new_data_set_name(&data, name);
pa_tz_device_new_data_set_system_id(&data, system_id);
if (direction == DM_DEVICE_DIRECTION_OUT)
pa_tz_device_new_data_done(&data);
} else {
- if (!(device = _device_list_get_device(manager, 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);
}
}
-static void handle_internal_pulse_device(pa_object *pdevice, bool is_loaded, pa_device_manager *manager) {
+static void handle_internal_pulse_device(pa_object *pdevice, bool is_loaded, pa_device_manager *dm) {
pa_tz_device *device;
struct composite_type *ctype;
pa_dynarray *ctypes;
dm_device_direction_t direction;
pa_assert(pdevice);
- pa_assert(manager);
+ pa_assert(dm);
pa_log_info("Handle internal pulse device");
direction = pulse_device_get_direction(pdevice);
/* Get types which this pulse_device belongs to */
- if ((ctypes = pulse_device_get_belongs_type(pdevice, manager)) == NULL) {
+ if ((ctypes = pulse_device_get_belongs_type(pdevice, dm)) == NULL) {
pa_log_debug("Failed to get device type. Skip this");
return ;
}
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(manager, 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(manager, 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));
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);
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);
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));
dm->device_list = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
dm->device_status = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
+ init_database(dm);
+
init_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);
deinit_dbus(dm);
+ deinit_database(dm);
+
if (dm->core)
pa_shared_remove(dm->core, SHARED_DEVICE_MANAGER);