Use new HAL pcm open interface which has card and device parameters 57/182557/6 accepted/tizen/unified/20180726.064848 submit/tizen/20180724.034640
authorJungsup Lee <jungsup4.lee@samsung.com>
Tue, 26 Jun 2018 05:16:41 +0000 (14:16 +0900)
committerJungsup Lee <jungsup4.lee@samsung.com>
Thu, 19 Jul 2018 05:42:31 +0000 (14:42 +0900)
[Version] 11.1.20
[Profile] Common
[Issue Type] Interface

Change-Id: I1da405ee91bb3abfaff62d1277b3c0def35c2e86

packaging/pulseaudio-modules-tizen.spec
src/device-manager.c
src/hal-interface.c
src/hal-interface.h
src/module-tizenaudio-haltc.c
src/module-tizenaudio-sink.c
src/module-tizenaudio-source.c

index a3c31ab..761c24e 100644 (file)
@@ -1,6 +1,6 @@
 Name:             pulseaudio-modules-tizen
 Summary:          Pulseaudio modules for Tizen
-Version:          11.1.19
+Version:          11.1.20
 Release:          0
 Group:            Multimedia/Audio
 License:          LGPL-2.1+
index 6428836..373c80a 100644 (file)
@@ -50,7 +50,7 @@
 #define SHARED_DEVICE_MANAGER "tizen-device-manager"
 
 #define DEVICE_MAP_FILE                    "/etc/pulse/device-map.json"
-#define DEVICE_STR_MAX                      30
+#define DEVICE_STR_MAX                      40
 #define DEVICE_DIRECTION_MAX                3
 #define DEVICE_PARAM_STRING_MAX             150
 #define DEVICE_AVAIL_COND_NUM_MAX           2
@@ -70,6 +70,7 @@
 #define DEVICE_TYPE_PROP_ROLE               "role"
 
 #define DEVICE_TYPE_STR_MAX                 20
+#define DEVICE_NAME_MAX                     30
 
 
 /* Properties of sink/sources */
@@ -632,25 +633,66 @@ static dm_device_class_t device_string_get_class(const char *device_string) {
     }
 }
 
-static const char* device_string_get_value(const char *device_string) {
-    int len;
-    const char *end_p, *value_p;
+/* device_string looks like "alsa:0,0"
+ * in this case name is "0,0" */
+static int device_string_get_name(const char *device_string, char *name) {
+    char *colon_p;
 
-    if (!device_string) {
-        return NULL;
+    if (!(colon_p = strchr(device_string, ':'))) {
+        pa_log_error("No Colon in device string");
+        return -1;
     }
 
-    len = strlen(device_string);
-    end_p = device_string + len -1;
+    colon_p++;
+    if (*colon_p == '\0' || !strchr(colon_p, ',')) {
+        pa_log_error("No Comma or empty device name");
+        return -1;
+    }
 
-    if (!(value_p = strchr(device_string, ':'))) {
-        return NULL;
+    if (strlen(colon_p) >= DEVICE_NAME_MAX) {
+        pa_log_error("device name too long : %s", colon_p);
+        return -1;
     }
-    if (value_p < end_p) {
-        return value_p + 1;
-    } else {
-        return NULL;
+
+    strncpy(name, colon_p, DEVICE_NAME_MAX);
+
+    return 0;
+}
+
+static int device_name_get_card(const char *device_name, char *card) {
+    const char *name_p;
+    char *card_p;
+
+    if (!strchr(device_name, ',')) {
+        pa_log_error("Failed to parse name : no comma");
+        return -1;
     }
+
+    name_p = device_name;
+    card_p = card;
+    while (*name_p != ',')
+        *(card_p++) = *(name_p++);
+    *card_p = '\0';
+
+    return 0;
+}
+
+static int device_name_get_device(const char *device_name, char *device) {
+    const char *comma_p;
+    char *device_p;
+
+    if (!(comma_p = strchr(device_name, ','))) {
+        pa_log_error("Failed to parse name : no comma");
+        return -1;
+    }
+
+    comma_p++;
+    device_p = device;
+    while (*comma_p != '\0')
+        *(device_p++) = *(comma_p++);
+    *device_p = '\0';
+
+    return 0;
 }
 
 static pa_proplist* pulse_device_get_proplist(pa_object *pdevice) {
@@ -837,26 +879,40 @@ static bool pulse_device_is_monitor(pa_object *pdevice) {
     }
 }
 
-static int pulse_device_get_alsa_device_string(pa_proplist *prop, char **device_string) {
-    const char *device_string_prop = NULL;
-    char *device_string_tmp;
+/* Actually this device_name is not exactly same with alsa's form (ex. "hw:0,1")
+ * this is part of that. (ex. "0,1") */
+static int pulse_device_get_device_name(pa_object *pdevice, char *device_name) {
+    pa_proplist *prop;
 
-    if (!prop || !device_string) {
-        pa_log_error("Invalid Parameter");
-        return -1;
-    }
+    prop = pulse_device_get_proplist(pdevice);
 
-    if (!(device_string_prop = pa_proplist_gets(prop, "device.string"))) {
-        pa_log_error("failed to get property 'device.string'");
-        return -1;
-    }
-    if (!(device_string_tmp = strchr(device_string_prop, ':'))) {
-        pa_log_error("failed to parse device string");
+    if (pulse_device_is_alsa(pdevice)) {
+        const char *device_string_prop;
+        char *name_p;
+
+        if (!(device_string_prop = pa_proplist_gets(prop, PA_PROP_DEVICE_STRING))) {
+            pa_log_error("failed to get property 'device.string'");
+            return -1;
+        }
+        if (!(name_p = strchr(device_string_prop, ':'))) {
+            pa_log_error("failed to parse device string");
+            return -1;
+        }
+        strncpy(device_name, name_p + 1, DEVICE_NAME_MAX);
+    } else if (pulse_device_is_tizenaudio(pdevice)) {
+        const char *card, *device;
+        if (!(card = pa_proplist_gets(prop, "tizen.card"))) {
+            pa_log_error("failed to get property 'tizen.card'");
+            return -1;
+        }
+        if (!(device = pa_proplist_gets(prop, "tizen.device"))) {
+            pa_log_error("failed to get property 'tizen.device'");
+            return -1;
+        }
+        snprintf(device_name, DEVICE_NAME_MAX, "%s,%s", card, device);
+    } else {
         return -1;
     }
-
-    *device_string = device_string_tmp + 1;
-
     return 0;
 }
 
@@ -866,7 +922,7 @@ static const char* device_class_get_module_name(dm_device_class_t device_class,
     } else if (device_class == DM_DEVICE_CLASS_ALSA) {
         return is_sink ? "module-alsa-sink" : "module-alsa-source";
     } else if (device_class == DM_DEVICE_CLASS_TIZEN) {
-        return is_sink ? "module-tizenaudio-sink" : NULL;
+        return is_sink ? "module-tizenaudio-sink" : "module-tizenaudio-source";
     } else if (device_class == DM_DEVICE_CLASS_BT) {
         return is_sink ? "module-bluez5-device" : NULL;
     } else if (device_class == DM_DEVICE_CLASS_NULL) {
@@ -1076,34 +1132,36 @@ static pa_tz_device* _device_list_get_device_by_id(pa_device_manager *manager, u
     return NULL;
 }
 
-static const char* build_params_to_load_device(const char *device_string, const char *params, dm_device_class_t device_class) {
-    pa_strbuf *args_buf;
-    static char args[DEVICE_PARAM_STRING_MAX] = {0,};
+static int build_params_to_load_device(const char *device_string, const char *params, dm_device_class_t device_class, char *target) {
+    char device_name[DEVICE_NAME_MAX];
 
-    if (!device_string) {
-        pa_log_error("device string null");
-        return NULL;
+    pa_assert(device_string);
+    pa_assert(target);
+
+    if ((device_class != DM_DEVICE_CLASS_ALSA) && (device_class != DM_DEVICE_CLASS_TIZEN))
+        return -1;
+
+    if (device_string_get_name(device_string, device_name) < 0) {
+        pa_log_error("Invalid device string '%s'", device_string);
+        return -1;
     }
 
-    if (device_class == DM_DEVICE_CLASS_NULL) {
-        return params;
-    } else if (device_class == DM_DEVICE_CLASS_ALSA) {
-        const char *alsa_device_name;
-        if (!(alsa_device_name = device_string_get_value(device_string))) {
-            pa_log_error("Invalid device string for alsa-device, '%s'", device_string);
-            return NULL;
-        }
-        args_buf = pa_strbuf_new();
-        pa_strbuf_printf(args_buf, "device=hw:%s ", alsa_device_name);
-        if (params) {
-            pa_strbuf_printf(args_buf, "%s", params);
-        }
-        pa_strlcpy(args, pa_strbuf_to_string_free(args_buf), DEVICE_PARAM_STRING_MAX);
-    } else {
-        return params;
+    if (device_class == DM_DEVICE_CLASS_ALSA) {
+        snprintf(target, DEVICE_PARAM_STRING_MAX, "device=hw:%s ", device_name);
+    } else if (device_class == DM_DEVICE_CLASS_TIZEN) {
+        char card[DEVICE_NAME_MAX];
+        char device[DEVICE_NAME_MAX];
+
+        device_name_get_card(device_name, card);
+        device_name_get_device(device_name, device);
+
+        snprintf(target, DEVICE_PARAM_STRING_MAX, "card=%s device=%s ", card, device);
     }
 
-    return (const char*) args;
+    if (params)
+        strncat(target, params, DEVICE_PARAM_STRING_MAX - strlen(target));
+
+    return 0;
 }
 
 static bool device_params_is_equal(const char *params1, const char *params2) {
@@ -1180,41 +1238,44 @@ static bool pulse_device_params_is_equal(pa_object *pdevice, const char *params)
     return device_params_is_equal(params, removed_module_args);
 }
 
-static const char* pulse_device_get_device_string(pa_object *pdevice) {
+static int pulse_device_get_device_string(pa_object *pdevice, char *device_string) {
     dm_device_class_t device_class;
-    static char device_string[DEVICE_STR_MAX] = {0,};
-    char *device_string_val = NULL;
-    pa_proplist *prop;
+    char device_name[DEVICE_NAME_MAX];
 
     pa_assert(pdevice);
+    pa_assert(device_string);
 
     device_class = pulse_device_get_class(pdevice);
-    prop = pulse_device_get_proplist(pdevice);
 
     if (device_class == DM_DEVICE_CLASS_ALSA) {
-        if (pulse_device_get_alsa_device_string(prop, &device_string_val) < 0)
-            return NULL;
-        snprintf(device_string, DEVICE_STR_MAX, "alsa:%s", device_string_val);
-        return device_string;
+        if (pulse_device_get_device_name(pdevice, device_name) < 0)
+            return -1;
+        snprintf(device_string, DEVICE_STR_MAX, "alsa:%s", device_name);
+        return 0;
     } else if (device_class == DM_DEVICE_CLASS_NULL) {
-        return "null";
+        snprintf(device_string, DEVICE_STR_MAX, "null");
+        return 0;
     } else if (device_class == DM_DEVICE_CLASS_TIZEN) {
-        return "tizen";
+        if (pulse_device_get_device_name(pdevice, device_name) < 0)
+            return -1;
+        snprintf(device_string, DEVICE_STR_MAX, "tizen:%s", device_name);
+        return 0;
     } else if (device_class == DM_DEVICE_CLASS_BT) {
-        return "bt";
+        snprintf(device_string, DEVICE_STR_MAX, "bt");
+        return 0;
     } else {
-        return device_string;
+        return -1;
     }
 }
 
 /*  pdevice is sink or source */
 static bool pulse_device_same_device_string(pa_object *pdevice, const char *device_string) {
-    const char *_device_string;
+    char _device_string[DEVICE_STR_MAX];
 
     pa_assert(pdevice);
     pa_assert(device_string);
 
-    if (!(_device_string = pulse_device_get_device_string(pdevice)))
+    if (pulse_device_get_device_string(pdevice, _device_string) < 0)
         return false;
 
     return pa_streq(_device_string, device_string);
@@ -1303,22 +1364,6 @@ pa_dynarray* pulse_device_get_belongs_type(pa_object *pdevice, pa_device_manager
     return ctypes;
 }
 
-static const char* pulse_device_get_device_name(pa_object *pdevice, const char *type) {
-    pa_proplist *prop;
-
-    pa_assert(pdevice);
-    pa_assert(device_type_is_valid(type));
-
-    prop = pulse_device_get_proplist(pdevice);
-
-    if (pa_streq(type, DEVICE_TYPE_USB_AUDIO))
-        return pa_proplist_gets(prop, "udev.id");
-    else if (pa_streq(type, DEVICE_TYPE_BT_A2DP))
-        return pa_proplist_gets(prop, "bluez.alias");
-    else
-        return NULL;
-}
-
 /* If fails return -1 */
 static int atoi_base16(const char *s) {
     char *x = NULL;
@@ -1670,8 +1715,11 @@ static void handle_usb_pulse_device(pa_object *pdevice, bool is_loaded, pa_devic
     if (is_loaded) {
         pa_tz_device_new_data data;
         int product_id, vendor_id;
+        pa_proplist *prop;
+
+        prop = pulse_device_get_proplist(pdevice);
+        name = pa_proplist_gets(prop, "udev.id");
 
-        name = pulse_device_get_device_name(pdevice, DEVICE_TYPE_USB_AUDIO);
         vendor_id = pulse_device_get_vendor_id(pdevice);
         product_id = pulse_device_get_product_id(pdevice);
 
@@ -1719,7 +1767,10 @@ static void handle_bt_pulse_device(pa_object *pdevice, bool is_loaded, pa_device
         pa_tz_device_new_data data;
 
         const char *name;
-        name = pulse_device_get_device_name(pdevice, DEVICE_TYPE_BT_A2DP);
+        pa_proplist *prop;
+
+        prop = pulse_device_get_proplist(pdevice);
+        name = pa_proplist_gets(prop, "bluez.alias");
 
         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);
@@ -1938,13 +1989,13 @@ static pa_hook_result_t sink_source_state_changed_hook_cb(pa_core *c, pa_object
 */
 
 static void* load_device(pa_core *c, bool is_sink, const char *device_string, const char *device_params) {
-    const char *args = NULL;
     const char *module_name;
     pa_module *module;
     pa_sink *sink;
     pa_source *source;
     uint32_t device_idx;
     dm_device_class_t device_class;
+    char full_params[DEVICE_PARAM_STRING_MAX];
 
     pa_assert(c);
     pa_assert(device_string);
@@ -1957,35 +2008,44 @@ static void* load_device(pa_core *c, bool is_sink, const char *device_string, co
         pa_log_warn("Invalid device_string '%s'", device_string);
         return NULL;
     }
+    pa_log_info("device class : %d", device_class);
 
     if (!(module_name = device_class_get_module_name(device_class, is_sink))) {
         pa_log_error("Get proper module name to load failed");
         return NULL;
     }
-    if (!(args = build_params_to_load_device(device_string, device_params, device_class))) {
-        pa_log_error("Get proper module name to load failed");
+    pa_log_info("module name : %s", module_name);
+
+    if (build_params_to_load_device(device_string, device_params, device_class, full_params) < 0) {
+        pa_log_error("build param to load module failed");
         return NULL;
     }
-    if (!(module = pa_module_load(c, module_name, args))) {
-        pa_log_error("Load module with name '%s' argu '%s' failed", module_name, args);
+    pa_log_info("argument : %s", full_params);
+
+    if (!(module = pa_module_load(c, module_name, full_params))) {
+        pa_log_error("Load module with name '%s' argu '%s' failed", module_name, full_params);
         return NULL;
     }
-
+    pa_log_info("module loaded : %s %u with '%s'", module->name, module->index, module->argument);
 
     if (is_sink) {
         PA_IDXSET_FOREACH(sink, c->sinks, device_idx) {
             if (sink->module == module) {
+                pa_log_info("sink loaded : %s %u", sink->name, sink->index);
                 return sink;
             }
         }
     } else {
         PA_IDXSET_FOREACH(source, c->sources, device_idx) {
             if (source->module == module) {
+                pa_log_info("source loaded : %s %u", source->name, source->index);
                 return source;
             }
         }
     }
 
+    pa_log_warn("Failed to find matching %s after load module", is_sink ? "sink" : "source");
+
     return NULL;
 }
 
index 847bcf9..1692a80 100644 (file)
@@ -293,15 +293,18 @@ int32_t pa_hal_interface_notify_stream_connection_changed(pa_hal_interface *h, h
     return ret;
 }
 
-int32_t pa_hal_interface_pcm_open(pa_hal_interface *h, pcm_handle *pcm_h, io_direction_t direction, pa_sample_spec *sample_spec, uint32_t period_size, uint32_t periods) {
+int32_t pa_hal_interface_pcm_open(pa_hal_interface *h, const char *card, const char *device, io_direction_t direction,
+                                  pa_sample_spec *sample_spec, uint32_t period_size, uint32_t periods, pcm_handle *pcm_h) {
     int32_t ret = 0;
     audio_return_t hal_ret = AUDIO_RET_OK;
 
     pa_assert(h);
     pa_assert(pcm_h);
+    pa_assert(card);
+    pa_assert(device);
     pa_assert(sample_spec);
 
-    if (AUDIO_RET_OK != (hal_ret = h->intf.pcm_open(h->ah_handle, pcm_h, direction, sample_spec, period_size, periods))) {
+    if (AUDIO_RET_OK != (hal_ret = h->intf.pcm_open(h->ah_handle, card, device, direction, sample_spec, period_size, periods, pcm_h))) {
         pa_log_error("pcm_open returns error:0x%x", hal_ret);
         ret = -1;
     }
index c44b7d6..20c14f8 100644 (file)
@@ -93,7 +93,7 @@ int32_t pa_hal_interface_set_volume_mute(pa_hal_interface *h, const char *volume
 int32_t pa_hal_interface_update_route(pa_hal_interface *h, hal_route_info *info);
 int32_t pa_hal_interface_update_route_option(pa_hal_interface *h, hal_route_option *option);
 int32_t pa_hal_interface_notify_stream_connection_changed(pa_hal_interface *h, hal_stream_connection_info *info);
-int32_t pa_hal_interface_pcm_open(pa_hal_interface *h, pcm_handle *pcm_h, io_direction_t direction, pa_sample_spec *sample_spec, uint32_t period_size, uint32_t periods);
+int32_t pa_hal_interface_pcm_open(pa_hal_interface *h, const char *card, const char *device, io_direction_t direction, pa_sample_spec *sample_spec, uint32_t period_size, uint32_t periods, pcm_handle *pcm_h);
 int32_t pa_hal_interface_pcm_start(pa_hal_interface *h, pcm_handle pcm_h);
 int32_t pa_hal_interface_pcm_stop(pa_hal_interface *h, pcm_handle pcm_h);
 int32_t pa_hal_interface_pcm_close(pa_hal_interface *h, pcm_handle pcm_h);
index 7b0d016..1515005 100644 (file)
@@ -27,6 +27,9 @@
 #include "module-tizenaudio-haltc-symdef.h"
 #include "hal-interface.h"
 
+#define DEFAULT_CARD   "0"
+#define DEFAULT_DEVICE "0"
+
 PA_MODULE_AUTHOR("Sangchul Lee");
 PA_MODULE_DESCRIPTION("Tizen Audio HAL TC module");
 PA_MODULE_VERSION(PACKAGE_VERSION);
@@ -160,7 +163,7 @@ static int32_t pcm_open_close_p(pa_hal_interface *h)
     periods = 5;
     period_size = 6400 / pa_frame_size(&sample_spec);
 
-    if ((ret = pa_hal_interface_pcm_open(h, &pcm_h, DIRECTION_OUT, &sample_spec, period_size, periods)))
+    if ((ret = pa_hal_interface_pcm_open(h, DEFAULT_CARD, DEFAULT_DEVICE, DIRECTION_OUT, &sample_spec, period_size, periods, &pcm_h)))
         return ret;
     if ((ret = pa_hal_interface_pcm_close(h, pcm_h)))
         return ret;
@@ -176,7 +179,7 @@ static int32_t pcm_open_close_n(pa_hal_interface *h)
     uint32_t period_size = 0;
     uint32_t periods = 0;
 
-    if ((ret = pa_hal_interface_pcm_open(h, &pcm_h, DIRECTION_OUT, &sample_spec, period_size, periods)))
+    if ((ret = pa_hal_interface_pcm_open(h, DEFAULT_CARD, DEFAULT_DEVICE, DIRECTION_OUT, &sample_spec, period_size, periods, &pcm_h)))
         return !ret;
     if ((ret = pa_hal_interface_pcm_close(h, pcm_h)))
         return !ret;
index a898a5e..3d81cbb 100644 (file)
@@ -55,6 +55,8 @@ PA_MODULE_LOAD_ONCE(false);
 PA_MODULE_USAGE(
         "sink_name=<name of sink> "
         "sink_properties=<properties for the sink> "
+        "card=<card to use> "
+        "device=<device to use> "
         "format=<sample format> "
         "rate=<sample rate> "
         "channels=<number of channels> "
@@ -90,6 +92,8 @@ struct userdata {
     pa_usec_t timestamp;
     pa_usec_t timestamp_written;
 
+    char* card;
+    char* device;
     bool first;
 
     pa_rtpoll_item *rtpoll_item;
@@ -101,6 +105,8 @@ struct userdata {
 static const char* const valid_modargs[] = {
     "sink_name",
     "sink_properties",
+    "card",
+    "device",
     "format",
     "rate",
     "channels",
@@ -154,7 +160,7 @@ static int suspend(struct userdata *u) {
         u->rtpoll_item = NULL;
     }
 
-    pa_log_info("Device suspended...");
+    pa_log_info("Device suspended...[%s,%s]", u->card, u->device);
 
     return 0;
 }
@@ -178,11 +184,13 @@ static int unsuspend(struct userdata *u) {
     }
 
     ret = pa_hal_interface_pcm_open(u->hal_interface,
-              (void **)&u->pcm_handle,
+              u->card,
+              u->device,
               DIRECTION_OUT,
               &sample_spec,
               u->frag_size / frame_size,
-              u->nfrags);
+              u->nfrags,
+              (void **)&u->pcm_handle);
     if (ret) {
         pa_log_error("Error opening PCM device %x", ret);
         goto fail;
@@ -460,6 +468,7 @@ int pa__init(pa_module*m) {
     uint32_t alternate_sample_rate;
     uint32_t block_msec;
     uint32_t max_request_msec;
+    const char *card, *device;
 
     pa_assert(m);
 
@@ -489,15 +498,23 @@ int pa__init(pa_module*m) {
     u->rtpoll = pa_rtpoll_new();
     pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
 
-    u->frag_size = 0;
-    u->nfrags = 0;
-    pa_modargs_get_value_u32(ma, "fragment_size", &u->frag_size);
-    pa_modargs_get_value_u32(ma, "fragments", &u->nfrags);
-    if (u->frag_size == 0 || u->nfrags == 0) {
+    if (!(card = pa_modargs_get_value(ma, "card", NULL)) ||
+        !(device = pa_modargs_get_value(ma, "device", NULL))) {
+        pa_log_error("card or device are invalid");
+        goto fail;
+    }
+
+    u->card = pa_xstrdup(card);
+    u->device = pa_xstrdup(device);
+
+    u->frag_size = (uint32_t) pa_usec_to_bytes(m->core->default_fragment_size_msec*PA_USEC_PER_MSEC, &ss);
+    u->nfrags = m->core->default_n_fragments;
+    if (pa_modargs_get_value_u32(ma, "fragment_size", &u->frag_size) < 0 ||
+        pa_modargs_get_value_u32(ma, "fragments", &u->nfrags) < 0) {
         pa_log_error("fragment_size or fragments are invalid.");
         goto fail;
     }
-    pa_log_info("fragment_size(%u), fragments(%u)", u->frag_size, u->nfrags);
+    pa_log_info("card(%s) device(%s) fragment_size(%u), fragments(%u)", u->card, u->device, u->frag_size, u->nfrags);
 
     /* Optional */
     block_msec = DEFAULT_BLOCK_USEC / PA_USEC_PER_MSEC;
@@ -520,7 +537,8 @@ int pa__init(pa_module*m) {
     pa_sink_new_data_set_channel_map(&data, &map);
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, _("Tizen audio sink"));
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_CLASS, "abstract");
-    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, "tizen");
+    pa_proplist_sets(data.proplist, "tizen.card", u->card);
+    pa_proplist_sets(data.proplist, "tizen.device", u->device);
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "tizen");
 
     if (pa_modargs_get_proplist(ma, "sink_properties", data.proplist, PA_UPDATE_REPLACE) < 0) {
@@ -542,11 +560,13 @@ int pa__init(pa_module*m) {
     u->sink->userdata = u;
 
     if (pa_hal_interface_pcm_open(u->hal_interface,
-              (void **)&u->pcm_handle,
+              u->card,
+              u->device,
               DIRECTION_OUT,
               &u->sink->sample_spec,
               u->frag_size / pa_frame_size(&u->sink->sample_spec),
-              u->nfrags)) {
+              u->nfrags,
+              (void **)&u->pcm_handle)) {
         pa_log_error("Error opening PCM device");
         goto fail;
     }
@@ -605,6 +625,9 @@ void pa__done(pa_module*m) {
     if (u->sink)
         pa_sink_unref(u->sink);
 
+    pa_xfree(u->card);
+    pa_xfree(u->device);
+
     if (u->rtpoll)
         pa_rtpoll_free(u->rtpoll);
 
index f72ec87..f4c12ab 100644 (file)
@@ -55,6 +55,8 @@ PA_MODULE_LOAD_ONCE(false);
 PA_MODULE_USAGE(
         "source_name=<name of source> "
         "source_properties=<properties for the source> "
+        "card=<card to use> "
+        "device=<device to use> "
         "format=<sample format> "
         "rate=<sample rate> "
         "channels=<number of channels> "
@@ -84,6 +86,8 @@ struct userdata {
     pa_usec_t block_usec;
     pa_usec_t timestamp;
 
+    char* card;
+    char* device;
     bool first;
 
     pa_rtpoll_item *rtpoll_item;
@@ -96,6 +100,8 @@ struct userdata {
 static const char* const valid_modargs[] = {
     "source_name",
     "source_properties",
+    "card",
+    "device",
     "format",
     "rate",
     "channels",
@@ -147,7 +153,7 @@ static int suspend(struct userdata *u) {
         u->rtpoll_item = NULL;
     }
 
-    pa_log_info("Device suspended...");
+    pa_log_info("Device suspended...[%s,%s]", u->card, u->device);
 
     return 0;
 }
@@ -171,11 +177,13 @@ static int unsuspend(struct userdata *u) {
     }
 
     ret = pa_hal_interface_pcm_open(u->hal_interface,
-              (void **)&u->pcm_handle,
+              u->card,
+              u->device,
               DIRECTION_IN,
               &sample_spec,
               u->frag_size / frame_size,
-              u->nfrags);
+              u->nfrags,
+              (void **)&u->pcm_handle);
     if (ret) {
         pa_log_error("Error opening PCM device %x", ret);
         goto fail;
@@ -404,6 +412,7 @@ int pa__init(pa_module*m) {
     pa_modargs *ma = NULL;
     pa_source_new_data data;
     uint32_t alternate_sample_rate;
+    const char *card, *device;
 
     pa_assert(m);
 
@@ -433,14 +442,23 @@ int pa__init(pa_module*m) {
     u->rtpoll = pa_rtpoll_new();
     pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
 
-    u->frag_size = 0;
-    u->nfrags = 0;
-    pa_modargs_get_value_u32(ma, "fragment_size", &u->frag_size);
-    pa_modargs_get_value_u32(ma, "fragments", &u->nfrags);
-    if (u->frag_size == 0 || u->nfrags == 0) {
+    if (!(card = pa_modargs_get_value(ma, "card", NULL)) ||
+        !(device = pa_modargs_get_value(ma, "device", NULL))) {
+        pa_log_error("card or device are invalid");
+        goto fail;
+    }
+
+    u->card = pa_xstrdup(card);
+    u->device = pa_xstrdup(device);
+
+    u->frag_size = (uint32_t) pa_usec_to_bytes(m->core->default_fragment_size_msec*PA_USEC_PER_MSEC, &ss);
+    u->nfrags = m->core->default_n_fragments;
+    if (pa_modargs_get_value_u32(ma, "fragment_size", &u->frag_size) < 0 ||
+        pa_modargs_get_value_u32(ma, "fragments", &u->nfrags) < 0) {
         pa_log_error("fragment_size or fragments are invalid.");
         goto fail;
     }
+    pa_log_info("card(%s) device(%s) fragment_size(%u), fragments(%u)", u->card, u->device, u->frag_size, u->nfrags);
 
     pa_source_new_data_init(&data);
     data.driver = __FILE__;
@@ -450,7 +468,8 @@ int pa__init(pa_module*m) {
     pa_source_new_data_set_channel_map(&data, &map);
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, _("Tizen audio source"));
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_CLASS, "abstract");
-    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, "tizen");
+    pa_proplist_sets(data.proplist, "tizen.card", u->card);
+    pa_proplist_sets(data.proplist, "tizen.device", u->device);
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "tizen");
 
     if (pa_modargs_get_proplist(ma, "source_properties", data.proplist, PA_UPDATE_REPLACE) < 0) {
@@ -472,11 +491,13 @@ int pa__init(pa_module*m) {
     u->source->userdata = u;
 
     if (pa_hal_interface_pcm_open(u->hal_interface,
-              (void **)&u->pcm_handle,
+              u->card,
+              u->device,
               DIRECTION_IN,
               &u->source->sample_spec,
               u->frag_size / pa_frame_size(&u->source->sample_spec),
-              u->nfrags)) {
+              u->nfrags,
+              (void **)&u->pcm_handle)) {
         pa_log_error("Error opening PCM device");
         goto fail;
     }
@@ -538,6 +559,9 @@ void pa__done(pa_module*m) {
     if (u->source)
         pa_source_unref(u->source);
 
+    pa_xfree(u->card);
+    pa_xfree(u->device);
+
     if (u->rtpoll)
         pa_rtpoll_free(u->rtpoll);