device-manager: Add support for ACM device 60/207560/5 submit/tizen/20190619.053430
authorSangchul Lee <sc11.lee@samsung.com>
Fri, 7 Jun 2019 06:49:48 +0000 (15:49 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Tue, 18 Jun 2019 02:45:22 +0000 (11:45 +0900)
A new ACM role that will be used with the network type is added.
A DBus method to set ACM mode triggering loading/unloading ACM
sink is added.

  server          : org.pulseaudio.Server
  object path     : /org/pulseaudio/DeviceManager
  interface       : org.pulseaudio.DeviceManager
  method name     : SetAcmMode
  method argument : unsigned int for mode (0:off)

[Version] 11.1.53
[Issue type] New feature

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

index e8d631f..cb28959 100644 (file)
@@ -1,6 +1,6 @@
 Name:             pulseaudio-modules-tizen
 Summary:          Pulseaudio modules for Tizen
-Version:          11.1.52
+Version:          11.1.53
 Release:          0
 Group:            Multimedia/Audio
 License:          LGPL-2.1+
index 6682567..18d0c0c 100644 (file)
     "   <arg name=\"device_type\" direction=\"in\" type=\"s\"/>\n"                          \
     "   <arg name=\"status\" direction=\"in\" type=\"i\"/>\n"                               \
     "  </method>\n"                                                                         \
+    "  <method name=\"SetAcmMode\">\n"                                                      \
+    "   <arg name=\"mode\" direction=\"in\" type=\"u\"/>\n"                                 \
+    "  </method>\n"                                                                         \
     "  <property name=\"PropertyTest1\" type=\"i\" access=\"readwrite\"/>\n"                \
     "  <property name=\"PropertyTest2\" type=\"s\" access=\"read\"/>\n"                     \
     "  <signal name=\"DeviceConnected\">\n"                                                 \
@@ -214,6 +217,7 @@ static void handle_unload_sink_with_device_string(DBusConnection *conn, DBusMess
 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 void handle_set_acm_mode(DBusConnection *conn, DBusMessage *msg, void *userdata);
 
 static int method_call_bt_get_name(DBusConnection *conn, const char *device_path, char **name);
 
@@ -239,6 +243,7 @@ enum method_handler_index {
     METHOD_HANDLER_GET_AVOID_RESAMPLING,
     METHOD_HANDLER_DUMP_DEVICE_LIST,
     METHOD_HANDLER_STATUS_TEST,
+    METHOD_HANDLER_SET_ACM_MODE,
     METHOD_HANDLER_MAX
 };
 
@@ -306,6 +311,9 @@ static pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = {
     [METHOD_HANDLER_STATUS_TEST] = {
         .method_name = "TestStatusChange",
         .receive_cb = handle_test_device_status_change },
+    [METHOD_HANDLER_SET_ACM_MODE] = {
+        .method_name = "SetAcmMode",
+        .receive_cb = handle_set_acm_mode },
 };
 
 static void save_preference(pa_device_manager *dm, pa_sink *sink) {
@@ -1568,6 +1576,38 @@ static void handle_test_device_status_change(DBusConnection *conn, DBusMessage *
     dbus_message_unref(reply);
 }
 
+static void handle_set_acm_mode(DBusConnection *conn, DBusMessage *msg, void *userdata) {
+    pa_device_manager *dm;
+    DBusMessage *reply = NULL;
+    uint32_t mode = 0;
+
+    pa_assert(conn);
+    pa_assert(msg);
+    pa_assert(userdata);
+
+    dm = (pa_device_manager *)userdata;
+    pa_assert_se(dbus_message_get_args(msg, NULL,
+                                       DBUS_TYPE_UINT32, &mode,
+                                       DBUS_TYPE_INVALID));
+
+    pa_log_info("Set ACM mode to (%d)", mode);
+
+    if (mode == 0) {
+        unload_acm_sink(dm);
+    } else {
+        /* For now, value of not 0 is just loading ACM sink. */
+        if (!load_acm_sink(dm)) {
+            pa_log_error("could not load acm sink");
+            pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "%s", "org.tizen.multimedia.audio.Internal");
+            return;
+        }
+    }
+
+    pa_assert_se((reply = dbus_message_new_method_return(msg)));
+    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;
index 4d491a1..b54a208 100644 (file)
@@ -141,5 +141,7 @@ void device_set_detected(pa_device_manager *dm, const char *type, const char *na
 pa_tz_device *device_list_get_device(pa_device_manager *dm, const char *type, const char *role, const char *system_id);
 pa_tz_device *device_list_get_device_by_id(pa_device_manager *dm, uint32_t id);
 void handle_device_connected(pa_device_manager *dm, const char *type, const char *name, const char *system_id, device_detected_type_t detected_type);
+pa_sink* load_acm_sink(pa_device_manager *dm);
+void unload_acm_sink(pa_device_manager *dm);
 
 #endif
index f1aa002..dbe965d 100644 (file)
@@ -78,6 +78,7 @@
 #define DEVICE_API_BLUEZ                    "bluez"
 #define DEVICE_API_ALSA                     "alsa"
 #define DEVICE_API_NULL                     "null"
+#define DEVICE_API_ACM                      "acm"
 #define DEVICE_API_RAOP                     "raop"
 #define DEVICE_BUS_USB                      "usb"
 #define DEVICE_CLASS_SOUND                  "sound"
@@ -121,6 +122,7 @@ typedef enum dm_device_class_type {
     DM_DEVICE_CLASS_TIZEN,
     DM_DEVICE_CLASS_BT,
     DM_DEVICE_CLASS_NULL,
+    DM_DEVICE_CLASS_ACM,
     DM_DEVICE_CLASS_MAX,
 } dm_device_class_t;
 
@@ -312,6 +314,8 @@ static dm_device_class_t device_string_get_class(const char *device_string) {
         return DM_DEVICE_CLASS_NULL;
     } else if (device_string == strstr(device_string, "tizen")) {
         return DM_DEVICE_CLASS_TIZEN;
+    } else if (device_string == strstr(device_string, "acm")) {
+        return DM_DEVICE_CLASS_ACM;
     } else {
         return DM_DEVICE_CLASS_NONE;
     }
@@ -386,6 +390,15 @@ static bool pulse_device_is_bluez(pa_object *pdevice) {
     }
 }
 
+static bool pulse_device_is_acm(pa_object *pdevice) {
+    pa_proplist *prop = pulse_device_get_proplist(pdevice);
+
+    if (!prop)
+        return false;
+
+    return pa_safe_streq(pa_proplist_gets(prop, PA_PROP_DEVICE_API), DEVICE_API_ACM);
+}
+
 static bool pulse_device_is_raop(pa_object *pdevice) {
     pa_proplist *prop = pulse_device_get_proplist(pdevice);
 
@@ -508,6 +521,8 @@ static dm_device_class_t pulse_device_get_class(pa_object *pdevice) {
         return DM_DEVICE_CLASS_TIZEN;
     } else if (pulse_device_is_bluez(pdevice)) {
         return DM_DEVICE_CLASS_BT;
+    } else if (pulse_device_is_acm(pdevice)) {
+        return DM_DEVICE_CLASS_ACM;
     } else {
         return DM_DEVICE_CLASS_NONE;
     }
@@ -585,6 +600,8 @@ static const char* device_class_get_module_name(dm_device_class_t device_class,
         return is_sink ? "module-bluez5-device" : NULL;
     } else if (device_class == DM_DEVICE_CLASS_NULL) {
         return is_sink ? "module-null-sink" : "module-null-source";
+    } else if (device_class == DM_DEVICE_CLASS_ACM) {
+        return is_sink ? "module-acm-sink" : NULL;
     } else {
         return NULL;
     }
@@ -803,11 +820,19 @@ static int build_params_to_load_module(const char *device_string, const char *pa
     char device_name[DEVICE_NAME_MAX];
 
     pa_assert(device_string);
+    pa_assert(params);
     pa_assert(target);
 
-    if ((device_class != DM_DEVICE_CLASS_ALSA) && (device_class != DM_DEVICE_CLASS_TIZEN))
+    if ((device_class != DM_DEVICE_CLASS_ALSA) &&
+        (device_class != DM_DEVICE_CLASS_TIZEN) &&
+        (device_class != DM_DEVICE_CLASS_ACM))
         return -1;
 
+    if (device_class == DM_DEVICE_CLASS_ACM) {
+        snprintf(target, DEVICE_PARAM_STRING_MAX, "%s ", params);
+        return 0;
+    }
+
     if (device_string_get_name(device_string, device_name) < 0) {
         pa_log_error("Invalid device string '%s'", device_string);
         return -1;
@@ -818,8 +843,7 @@ static int build_params_to_load_module(const char *device_string, const char *pa
     else if (device_class == DM_DEVICE_CLASS_TIZEN)
         snprintf(target, DEVICE_PARAM_STRING_MAX, "device=%s ", device_name);
 
-    if (params)
-        strncat(target, params, DEVICE_PARAM_STRING_MAX - strlen(target));
+    strncat(target, params, DEVICE_PARAM_STRING_MAX - strlen(target));
 
     return 0;
 }
@@ -923,6 +947,9 @@ static int pulse_device_get_device_string(pa_object *pdevice, char *device_strin
     } else if (device_class == DM_DEVICE_CLASS_BT) {
         snprintf(device_string, DEVICE_STR_MAX, "bt");
         return 0;
+    }  else if (device_class == DM_DEVICE_CLASS_ACM) {
+        snprintf(device_string, DEVICE_STR_MAX, "acm");
+        return 0;
     } else {
         return -1;
     }
@@ -1453,6 +1480,30 @@ static void handle_raop_pulse_device(pa_object *pdevice, bool is_loaded, pa_devi
     }
 }
 
+static void handle_acm_pulse_device(pa_object *pdevice, bool is_loaded, pa_device_manager *dm) {
+    pa_tz_device *device;
+
+    pa_assert(pdevice);
+    pa_assert(dm);
+
+    pa_log_info("Handle ACM pulse device");
+
+    if (is_loaded) {
+        pa_tz_device_new_data data;
+
+        pa_tz_device_new_data_init(&data, dm->device_list, dm->comm, NULL);
+        _fill_new_data_basic(&data, DEVICE_TYPE_NETWORK, DM_DEVICE_DIRECTION_OUT, false, dm);
+        pa_tz_device_new_data_add_sink(&data, DEVICE_ROLE_ACM, PA_SINK(pdevice));
+        pa_tz_device_new(&data);
+        pa_tz_device_new_data_done(&data);
+    } else {
+        if (!(device = device_list_get_device(dm, DEVICE_TYPE_NETWORK, DEVICE_ROLE_ACM, NULL)))
+            pa_log_warn("Can't get ACM device");
+        else
+            pa_tz_device_free(device);
+    }
+}
+
 static void handle_internal_pulse_device(pa_object *pdevice, bool is_loaded, pa_device_manager *dm) {
     pa_tz_device *device;
     struct composite_type *ctype;
@@ -1528,6 +1579,10 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, pa_dev
         pulse_device_set_use_internal_codec(PA_OBJECT(sink), false);
         handle_raop_pulse_device(PA_OBJECT(sink), true, dm);
         return PA_HOOK_OK;
+    } else if (pulse_device_is_acm(PA_OBJECT(sink))) {
+        pulse_device_set_use_internal_codec(PA_OBJECT(sink), false);
+        handle_acm_pulse_device(PA_OBJECT(sink), true, dm);
+        return PA_HOOK_OK;
     } else if (pulse_device_is_alsa(PA_OBJECT(sink)) || pulse_device_is_tizenaudio(PA_OBJECT(sink))) {
         pulse_device_set_use_internal_codec(PA_OBJECT(sink), true);
         handle_internal_pulse_device(PA_OBJECT(sink), true, dm);
@@ -1558,6 +1613,9 @@ static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, pa_
     } else if (pulse_device_is_raop(PA_OBJECT(sink))) {
         handle_raop_pulse_device(PA_OBJECT(sink), false, dm);
         return PA_HOOK_OK;
+    } else if (pulse_device_is_acm(PA_OBJECT(sink))) {
+        handle_acm_pulse_device(PA_OBJECT(sink), false, dm);
+        return PA_HOOK_OK;
     } else if (pulse_device_is_alsa(PA_OBJECT(sink)) || pulse_device_is_tizenaudio(PA_OBJECT(sink))) {
         handle_internal_pulse_device(PA_OBJECT(sink), false, dm);
         return PA_HOOK_OK;
@@ -2472,6 +2530,36 @@ static void unload_source(pa_device_manager *dm, const char *type, const char *r
     unload_module(dm->core, false, device_string);
 }
 
+pa_sink* load_acm_sink(pa_device_manager *dm) {
+    pa_tz_device *acm_device;
+
+    pa_assert(dm);
+
+    pa_log_info("Load ACM sink");
+
+    if ((acm_device = device_list_get_device(dm, DEVICE_TYPE_NETWORK, DEVICE_ROLE_ACM, NULL))) {
+        pa_log_info("ACM device already exists");
+        return pa_tz_device_get_sink(acm_device, DEVICE_ROLE_ACM);
+    }
+
+    return load_sink(dm, DEVICE_TYPE_NETWORK, DEVICE_ROLE_ACM);
+}
+
+void unload_acm_sink(pa_device_manager *dm) {
+    pa_assert(dm);
+
+    pa_log_info("Unload ACM sink");
+
+    if (!device_list_get_device(dm, DEVICE_TYPE_NETWORK, DEVICE_ROLE_ACM, NULL)) {
+        pa_log_info("ACM device does not exist");
+        return;
+    }
+
+    unload_sink(dm, DEVICE_TYPE_NETWORK, DEVICE_ROLE_ACM);
+
+    return;
+}
+
 pa_idxset* pa_device_manager_get_device_list(pa_device_manager *dm) {
     pa_assert(dm);
     pa_assert(dm->device_list);
index eff1e5e..5e58c27 100644 (file)
@@ -173,6 +173,8 @@ bool device_role_is_valid(const char *device_role) {
         return true;
     else if (pa_safe_streq(device_role, DEVICE_ROLE_RAOP))
         return true;
+    else if (pa_safe_streq(device_role, DEVICE_ROLE_ACM))
+        return true;
     else
         return false;
 }
index 55b2a49..df0e297 100644 (file)
@@ -24,6 +24,7 @@
 #define DEVICE_ROLE_HIGH_LATENCY            "high-latency"
 #define DEVICE_ROLE_UHQA                    "uhqa"
 #define DEVICE_ROLE_RAOP                    "raop"
+#define DEVICE_ROLE_ACM                     "acm"
 
 typedef enum dm_device_direction_type {
     DM_DEVICE_DIRECTION_NONE,