device-manager: Apply preferences which are saved via Dbus APIs 67/184167/1 accepted/tizen/unified/20180718.071606 submit/tizen/20180718.011600
authorSangchul Lee <sc11.lee@samsung.com>
Fri, 13 Jul 2018 07:10:16 +0000 (16:10 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Mon, 16 Jul 2018 03:56:38 +0000 (12:56 +0900)
If user set a sample rate, a format and an option of avoid-resampling
for a specific USB device, it will be saved to system and loaded/applied
when the device is connected again.

[Version] 11.1.19
[Issue Type] New feature

Change-Id: I50c62272428eeed1a01b0613f0e82a49b5be272f
Signed-off-by: Sangchul Lee <sc11.lee@samsung.com>
packaging/pulseaudio-modules-tizen.spec
src/device-manager.c

index 62b94d8..a3c31ab 100644 (file)
@@ -1,6 +1,6 @@
 Name:             pulseaudio-modules-tizen
 Summary:          Pulseaudio modules for Tizen
-Version:          11.1.18
+Version:          11.1.19
 Release:          0
 Group:            Multimedia/Audio
 License:          LGPL-2.1+
index 5491658..6428836 100644 (file)
@@ -59,6 +59,7 @@
 #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"
@@ -70,6 +71,7 @@
 
 #define DEVICE_TYPE_STR_MAX                 20
 
+
 /* Properties of sink/sources */
 #define DEVICE_API_BLUEZ                    "bluez"
 #define DEVICE_API_ALSA                     "alsa"
@@ -230,6 +232,13 @@ do { \
     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",
@@ -1574,13 +1583,84 @@ static pa_source* _device_manager_set_default_source(pa_device_manager *dm,  con
     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");
 
@@ -1595,7 +1675,7 @@ static void handle_usb_pulse_device(pa_object *pdevice, bool is_loaded, pa_devic
         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);
@@ -1605,28 +1685,30 @@ static void handle_usb_pulse_device(pa_object *pdevice, bool is_loaded, pa_devic
         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");
 
@@ -1639,8 +1721,8 @@ static void handle_bt_pulse_device(pa_object *pdevice, bool is_loaded, pa_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)
@@ -1652,27 +1734,27 @@ static void handle_bt_pulse_device(pa_object *pdevice, bool is_loaded, pa_device
         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 ;
     }
@@ -1682,7 +1764,7 @@ static void handle_internal_pulse_device(pa_object *pdevice, bool is_loaded, pa_
         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));
@@ -1697,7 +1779,7 @@ static void handle_internal_pulse_device(pa_object *pdevice, bool is_loaded, pa_
         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));
@@ -3426,6 +3508,8 @@ static void handle_set_sample_format(DBusConnection *conn, DBusMessage *msg, voi
         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);
@@ -3596,6 +3680,8 @@ static void handle_set_sample_rate(DBusConnection *conn, DBusMessage *msg, void
         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);
@@ -3768,6 +3854,8 @@ static void handle_set_avoid_resampling(DBusConnection *conn, DBusMessage *msg,
 
     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));
@@ -4332,6 +4420,8 @@ pa_device_manager* pa_device_manager_get(pa_core *c) {
     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);
@@ -4439,6 +4529,8 @@ void pa_device_manager_unref(pa_device_manager *dm) {
 
     deinit_dbus(dm);
 
+    deinit_database(dm);
+
     if (dm->core)
         pa_shared_remove(dm->core, SHARED_DEVICE_MANAGER);