Support external device playback and capture on sink2/source2 ref/for/tizen
authorJaechul Lee <jcsing.lee@samsung.com>
Fri, 3 Dec 2021 02:15:30 +0000 (11:15 +0900)
committerJaechul Lee <jcsing.lee@samsung.com>
Tue, 22 Mar 2022 06:04:02 +0000 (15:04 +0900)
module-alsa-card try to use 'device_id' that is from udev but
tizenaudio-sink2/source2 can't load device with device_id.

This patch makes devices load with device_id and device_string both.

[Version] 13.0.78
[Issue Type] New feature

Change-Id: I26645fc7b43b6289a3da9017b5643a0e65b8e026
Signed-off-by: Jaechul Lee <jcsing.lee@samsung.com>
Makefile.am
packaging/pulseaudio-modules-tizen.spec
src/module-tizenaudio-sink2.c
src/module-tizenaudio-source2.c
src/tizenaudio-sink2.c
src/tizenaudio-sink2.h
src/tizenaudio-source2.c
src/tizenaudio-source2.h
src/tizenaudio-util.c [new file with mode: 0644]
src/tizenaudio-util.h [new file with mode: 0644]

index 300d9a3d10d7f205e93ff0f1f9fa5b4b76ff815e..7fa049b2fbbce1c63822f1f51ac6125b4d0fb5d1 100644 (file)
@@ -38,7 +38,7 @@ pulsemodlibexec_LTLIBRARIES = \
                libhal-interface.la \
                libprocessor.la \
                libcommunicator.la \
-               libtizenaudio-utils.la \
+               libtizenaudio-util.la \
                module-tizenaudio-sink.la \
                module-tizenaudio-source.la \
                module-tizenaudio-sink2.la \
@@ -79,19 +79,26 @@ module_tizenaudio_source_la_LDFLAGS = $(MODULE_LDFLAGS)
 module_tizenaudio_source_la_LIBADD = $(MODULE_LIBADD) libhal-interface.la
 module_tizenaudio_source_la_CFLAGS = $(MODULE_CFLAGS) -DPA_MODULE_NAME=module_tizenaudio_source
 
-libtizenaudio_utils_la_SOURCES = src/tizenaudio-sink2.c src/tizenaudio-sink2.h src/tizenaudio-source2.c src/tizenaudio-source2.h src/echo-cancel/echo-cancel-def.h
-libtizenaudio_utils_la_LDFLAGS = $(MODULE_LDFLAGS)
-libtizenaudio_utils_la_LIBADD = $(MODULE_LIBADD) libhal-interface.la
-libtizenaudio_utils_la_CFLAGS = $(MODULE_CFLAGS)
+libtizenaudio_util_la_SOURCES = \
+                               src/tizenaudio-sink2.c \
+                               src/tizenaudio-sink2.h \
+                               src/tizenaudio-source2.c \
+                               src/tizenaudio-source2.h \
+                               src/tizenaudio-util.c \
+                               src/tizenaudio-util.h \
+                               src/echo-cancel/echo-cancel-def.h
+libtizenaudio_util_la_LDFLAGS = $(MODULE_LDFLAGS)
+libtizenaudio_util_la_LIBADD = $(MODULE_LIBADD) libhal-interface.la
+libtizenaudio_util_la_CFLAGS = $(MODULE_CFLAGS)
 
 module_tizenaudio_sink2_la_SOURCES = src/module-tizenaudio-sink2.c
 module_tizenaudio_sink2_la_LDFLAGS = $(MODULE_LDFLAGS)
-module_tizenaudio_sink2_la_LIBADD = $(MODULE_LIBADD) libtizenaudio-utils.la
+module_tizenaudio_sink2_la_LIBADD = $(MODULE_LIBADD) libtizenaudio-util.la
 module_tizenaudio_sink2_la_CFLAGS = $(MODULE_CFLAGS) -DPA_MODULE_NAME=module_tizenaudio_sink2
 
 module_tizenaudio_source2_la_SOURCES = src/module-tizenaudio-source2.c src/echo-cancel/echo-cancel-def.h
 module_tizenaudio_source2_la_LDFLAGS = $(MODULE_LDFLAGS)
-module_tizenaudio_source2_la_LIBADD = $(MODULE_LIBADD) libtizenaudio-utils.la
+module_tizenaudio_source2_la_LIBADD = $(MODULE_LIBADD) libtizenaudio-util.la
 module_tizenaudio_source2_la_CFLAGS = $(MODULE_CFLAGS) -DPA_MODULE_NAME=module_tizenaudio_source2
 
 libprocessor_la_SOURCES = \
index 896f569f8ca7984818711ee94e7af3ba2ed46dbb..762292c722f8ab9904a57d247c066961c0a9015b 100644 (file)
@@ -91,7 +91,7 @@ install -m 0644 %SOURCE1 %{buildroot}%{_tmpfilesdir}/pulseaudio.conf
 %{_libdir}/pulse-%{module_ver}/modules/module-tizenaudio-publish.so
 %{_libdir}/pulse-%{module_ver}/modules/module-tizenaudio-echo-cancel.so
 %{_libdir}/pulse-%{module_ver}/modules/libprocessor.so
-%{_libdir}/pulse-%{module_ver}/modules/libtizenaudio-utils.so
+%{_libdir}/pulse-%{module_ver}/modules/libtizenaudio-util.so
 %{_libdir}/pulse-%{module_ver}/modules/libhal-interface.so
 %{_libdir}/pulse-%{module_ver}/modules/libcommunicator.so
 %{_tmpfilesdir}/pulseaudio.conf
index 9a22a63574b210838551ea53317d494d22469d78..0b107241556c7bb0c0d491ac0ce34197c80af268 100644 (file)
@@ -65,7 +65,7 @@ int pa__init(pa_module *m) {
         goto fail;
     }
 
-    if (!(m->userdata = pa_tizenaudio_sink2_new(m, ma, __FILE__, NULL)))
+    if (!(m->userdata = pa_tizenaudio_sink2_new(m, ma, __FILE__, NULL, NULL, NULL, NULL)))
         goto fail;
 
     pa_modargs_free(ma);
index 381362adae8c0fe27b7008f18375a5c1a0fc7446..c916b58b4adfb9b59483df56e340c781ab3489ec 100644 (file)
@@ -65,7 +65,7 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
-    if (!(m->userdata = pa_tizenaudio_source2_new(m, ma, __FILE__, NULL)))
+    if (!(m->userdata = pa_tizenaudio_source2_new(m, ma, __FILE__, NULL, NULL, NULL, NULL)))
         goto fail;
 
     pa_modargs_free(ma);
index 530f01aaa80f406dd3812fd2185d3e3eda1bb826..9e4c9708140546c0e99fb4e6356b8b22df0dbbed 100644 (file)
@@ -46,6 +46,7 @@
 #include <pulsecore/poll.h>
 
 #include "hal-interface.h"
+#include "tizenaudio-util.h"
 #include "echo-cancel/echo-cancel-def.h"
 
 #define DEFAULT_SINK_NAME "tizenaudio-sink2"
@@ -377,59 +378,39 @@ finish:
     pa_log_debug("Thread shutting down");
 }
 
-static int parse_to_get_card(const char *modarg_device, char *card) {
-    const char *name_p;
-    char *card_p;
-
-    if (!strchr(modarg_device, ',')) {
-        pa_log_error("Failed to parse device argument : no comma");
-        return -1;
-    }
-
-    name_p = modarg_device;
-    card_p = card;
-    while (*name_p != ',')
-        *(card_p++) = *(name_p++);
-    *card_p = '\0';
-
-    return 0;
-}
-
-static int parse_to_get_device(const char *modarg_device, char *device) {
-    const char *comma_p;
-    char *device_p;
-
-    if (!(comma_p = strchr(modarg_device, ','))) {
-        pa_log_error("Failed to parse device argument : no comma");
-        return -1;
-    }
-
-    comma_p++;
-    device_p = device;
-    while (*comma_p != '\0')
-        *(device_p++) = *(comma_p++);
-    *device_p = '\0';
-
-    return 0;
-}
-
-pa_sink *pa_tizenaudio_sink2_new(pa_module *m, pa_modargs *ma, const char *driver, pa_card *c/*mapping somthing */) {
+pa_sink *pa_tizenaudio_sink2_new(pa_module *m,
+                                    pa_modargs *ma,
+                                    const char *driver,
+                                    pa_card *c,
+                                    char **device_string,
+                                    pa_sample_spec *sample_spec,
+                                    pa_channel_map *channel_map) {
     struct userdata *u = NULL;
     pa_sample_spec ss;
     pa_channel_map map;
     pa_sink_new_data data;
     uint32_t alternate_sample_rate;
     const char *modarg_device;
-    char card[DEVICE_NAME_MAX];
-    char device[DEVICE_NAME_MAX];
+    const char *modarg_device_id;
     size_t frame_size, buffer_size, period_frames, buffer_frames;
+    pa_pcm_params param;
 
     pa_assert(m);
     pa_assert(ma);
 
+    /*
+     * TODO: It doesn't need to handle sample_spec, channels_map yet.
+     * Because it comes from UCM
+     */
     ss = m->core->default_sample_spec;
     map = m->core->default_channel_map;
-    if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
+
+    if (channel_map && channel_map->channels != ss.channels)
+        ss.channels = channel_map->channels;
+
+    pa_channel_map_init_extend(&map, ss.channels, PA_CHANNEL_MAP_ALSA);
+
+    if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_ALSA) < 0) {
         pa_log_error("Invalid sample format specification or channel map");
         goto fail;
     }
@@ -449,22 +430,13 @@ pa_sink *pa_tizenaudio_sink2_new(pa_module *m, pa_modargs *ma, const char *drive
     u->rtpoll = pa_rtpoll_new();
     pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
 
-    if ((modarg_device = pa_modargs_get_value(ma, "device_id", NULL))) {
-        strcpy(card, modarg_device);
-        strcpy(device, "0");
-    } else if ((modarg_device = pa_modargs_get_value(ma, "device", NULL))) {
-        if (parse_to_get_card(modarg_device, card) || parse_to_get_device(modarg_device, device)) {
-            pa_log_error("failed to parse device module argument, %s", modarg_device);
-            goto fail;
-        }
-    } else {
-        pa_log_error("Unknown device");
+    modarg_device_id = pa_modargs_get_value(ma, "device_id", NULL);
+    modarg_device = pa_modargs_get_value(ma, "device", NULL);
+    if (!modarg_device_id && !modarg_device) {
+        pa_log_error("Failed to get device id or device string");
         goto fail;
     }
 
-    u->card = pa_xstrdup(card);
-    u->device = pa_xstrdup(device);
-
     u->frag_size = (uint32_t) pa_usec_to_bytes(DEFAULT_FRAGMENT_MSEC * PA_USEC_PER_MSEC, &ss);
     u->nfrags = DEFAULT_FRAGMENTS;
     if (pa_modargs_get_value_u32(ma, "fragment_size", &u->frag_size) < 0 ||
@@ -472,10 +444,44 @@ pa_sink *pa_tizenaudio_sink2_new(pa_module *m, pa_modargs *ma, const char *drive
         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);
+
+    frame_size = pa_frame_size(&ss);
+    buffer_size = u->frag_size * u->nfrags;
+    buffer_frames = buffer_size / frame_size;
+    period_frames = u->frag_size / frame_size;
+
+    param.direction = DIRECTION_OUT;
+    param.ss = &ss;
+    param.period_size = u->frag_size / pa_frame_size(&ss);
+    param.periods = u->nfrags;
+
+    if (modarg_device_id && device_string) {
+        if (pa_hal_interface_pcm_open_by_dev_id(
+                  u->hal_interface,
+                  modarg_device_id,
+                  device_string,
+                  &param,
+                  (void **)&u->pcm_handle,
+                  &u->card,
+                  &u->device)) {
+            pa_log_error("Error opening PCM device");
+            goto fail;
+        }
+    } else {
+        if (pa_hal_interface_pcm_open_by_device(
+                  u->hal_interface,
+                  modarg_device,
+                  &param,
+                  (void **)&u->pcm_handle,
+                  &u->card,
+                  &u->device)) {
+            pa_log_error("Error opening PCM device");
+            goto fail;
+        }
+    }
 
     pa_sink_new_data_init(&data);
-    data.driver = __FILE__;
+    data.driver = driver;
     data.module = m;
     data.card = c;
     pa_sink_new_data_set_name(&data, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME));
@@ -487,19 +493,15 @@ pa_sink *pa_tizenaudio_sink2_new(pa_module *m, pa_modargs *ma, const char *drive
     pa_proplist_sets(data.proplist, "tizen.device", u->device);
     pa_proplist_sets(data.proplist, "tizen.version", "2");
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "tizen");
-
-    // TODO: Need to check usb.
-    if (pa_modargs_get_value(ma, "device_id", NULL)) {
-        pa_proplist_sets(data.proplist, "device.bus", "usb");
-    }
-
-    frame_size = pa_frame_size(&ss);
-    buffer_size = u->frag_size * u->nfrags;
-    buffer_frames = buffer_size / frame_size;
-    period_frames = u->frag_size / frame_size;
     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%zu", buffer_frames * frame_size);
     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE, "%zu", period_frames * frame_size);
 
+    /*
+     * TODO: tricky code for tizen
+     */
+    if (modarg_device_id)
+        pa_proplist_sets(data.proplist, PA_PROP_DEVICE_BUS, "usb");
+
     if (pa_modargs_get_proplist(ma, "sink_properties", data.proplist, PA_UPDATE_REPLACE) < 0) {
         pa_log_error("Invalid properties.");
         pa_sink_new_data_done(&data);
@@ -518,17 +520,7 @@ pa_sink *pa_tizenaudio_sink2_new(pa_module *m, pa_modargs *ma, const char *drive
     u->sink->set_state_in_io_thread = sink_set_state_in_io_thread_cb;
     u->sink->userdata = u;
 
-    if (pa_hal_interface_pcm_open(u->hal_interface,
-              u->card,
-              u->device,
-              DIRECTION_OUT,
-              &u->sink->sample_spec,
-              u->frag_size / pa_frame_size(&u->sink->sample_spec),
-              u->nfrags,
-              (void **)&u->pcm_handle)) {
-        pa_log_error("Error opening PCM device");
-        goto fail;
-    }
+    pa_log_info("card(%s) device(%s) fragment_size(%u), fragments(%u)", u->card, u->device, u->frag_size, u->nfrags);
 
     pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
     pa_sink_set_rtpoll(u->sink, u->rtpoll);
@@ -546,7 +538,9 @@ pa_sink *pa_tizenaudio_sink2_new(pa_module *m, pa_modargs *ma, const char *drive
     return u->sink;
 
 fail:
-    userdata_free(u);
+    if (u)
+        userdata_free(u);
+
     return NULL;
 }
 
@@ -586,5 +580,7 @@ void pa_tizenaudio_sink2_free(pa_sink *s) {
     pa_sink_assert_ref(s);
     pa_assert_se((u = s->userdata));
 
+    pa_hal_interface_unref(u->hal_interface);
+
     userdata_free(u);
 }
index 4891f3937be1c970bf24fad23710db22df3f48b7..f74777e91da499f63ec425d5dbf8604100f8d888 100644 (file)
 #include <pulsecore/module.h>
 #include <pulsecore/modargs.h>
 #include <pulsecore/sink.h>
-
-pa_sink *pa_tizenaudio_sink2_new(pa_module *m, pa_modargs *ma, const char *driver, pa_card *card/*mapping somthing */);
+#include <pulse/channelmap.h>
+#include <pulse/sample.h>
+
+pa_sink *pa_tizenaudio_sink2_new(pa_module *m,
+                                    pa_modargs *ma,
+                                    const char *driver,
+                                    pa_card *c,
+                                    char **device_string,
+                                    pa_sample_spec *sample_spec,
+                                    pa_channel_map *channel_map);
 
 void pa_tizenaudio_sink2_free(pa_sink *s);
 
index dd5f8a32d1bf13750d1901229ca2170d87df7289..c856d01503fa75a54bbbbad8aefd28ecf88341a3 100644 (file)
@@ -46,6 +46,7 @@
 #include <pulsecore/poll.h>
 
 #include "hal-interface.h"
+#include "tizenaudio-util.h"
 #include "echo-cancel/echo-cancel-def.h"
 
 #define DEFAULT_SOURCE_NAME "tizenaudio-source2"
@@ -395,58 +396,39 @@ finish:
     pa_log_debug("Thread shutting down");
 }
 
-static int parse_to_get_card(const char *modarg_device, char *card) {
-    const char *name_p;
-    char *card_p;
-
-    if (!strchr(modarg_device, ',')) {
-        pa_log_error("Failed to parse device argument : no comma");
-        return -1;
-    }
-
-    name_p = modarg_device;
-    card_p = card;
-    while (*name_p != ',')
-        *(card_p++) = *(name_p++);
-    *card_p = '\0';
-
-    return 0;
-}
-
-static int parse_to_get_device(const char *modarg_device, char *device) {
-    const char *comma_p;
-    char *device_p;
-
-    if (!(comma_p = strchr(modarg_device, ','))) {
-        pa_log_error("Failed to parse device argument : no comma");
-        return -1;
-    }
-
-    comma_p++;
-    device_p = device;
-    while (*comma_p != '\0')
-        *(device_p++) = *(comma_p++);
-    *device_p = '\0';
-
-    return 0;
-}
-
-pa_source *pa_tizenaudio_source2_new(pa_module *m, pa_modargs *ma, const char *driver, pa_card *c/*mapping somthing */) {
+pa_source *pa_tizenaudio_source2_new(pa_module *m,
+                                        pa_modargs *ma,
+                                        const char *driver,
+                                        pa_card *c,
+                                        char **device_string,
+                                        pa_sample_spec *sample_spec,
+                                        pa_channel_map *channel_map) {
     struct userdata *u = NULL;
     pa_sample_spec ss;
     pa_channel_map map;
     pa_source_new_data data;
     uint32_t alternate_sample_rate;
     const char *modarg_device;
-    char card[DEVICE_NAME_MAX];
-    char device[DEVICE_NAME_MAX];
+    const char *modarg_device_id;
     size_t frame_size, buffer_size, period_frames, buffer_frames;
+    pa_pcm_params param;
 
     pa_assert(m);
+    pa_assert(ma);
 
+    /*
+     * TODO: It doesn't need to handle sample_spec, channels_map yet.
+     * Because it comes from UCM
+     */
     ss = m->core->default_sample_spec;
     map = m->core->default_channel_map;
-    if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
+
+    if (channel_map && channel_map->channels != ss.channels)
+        ss.channels = channel_map->channels;
+
+    pa_channel_map_init_extend(&map, ss.channels, PA_CHANNEL_MAP_ALSA);
+
+    if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_ALSA) < 0) {
         pa_log_error("Invalid sample format specification or channel map");
         goto fail;
     }
@@ -465,22 +447,13 @@ pa_source *pa_tizenaudio_source2_new(pa_module *m, pa_modargs *ma, const char *d
     u->rtpoll = pa_rtpoll_new();
     pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
 
-    if ((modarg_device = pa_modargs_get_value(ma, "device_id", NULL))) {
-        strcpy(card, modarg_device);
-        strcpy(device, "0"); //TODO temp
-    } else if ((modarg_device = pa_modargs_get_value(ma, "device", NULL))) {
-        if (parse_to_get_card(modarg_device, card) || parse_to_get_device(modarg_device, device)) {
-            pa_log_error("failed to parse device module argument, %s", modarg_device);
-            goto fail;
-        }
-    } else {
-        pa_log_error("Unknown device");
+    modarg_device_id = pa_modargs_get_value(ma, "device_id", NULL);
+    modarg_device = pa_modargs_get_value(ma, "device", NULL);
+    if (!modarg_device_id && !modarg_device) {
+        pa_log_error("Failed to get device id or device string");
         goto fail;
     }
 
-    u->card = pa_xstrdup(card);
-    u->device = pa_xstrdup(device);
-
     u->frag_size = (uint32_t) pa_usec_to_bytes(DEFAULT_FRAGMENT_MSEC * PA_USEC_PER_MSEC, &ss);
     u->nfrags = DEFAULT_FRAGMENTS;
     if (pa_modargs_get_value_u32(ma, "fragment_size", &u->frag_size) < 0 ||
@@ -488,7 +461,41 @@ pa_source *pa_tizenaudio_source2_new(pa_module *m, pa_modargs *ma, const char *d
         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);
+
+    frame_size = pa_frame_size(&ss);
+    buffer_size = u->frag_size * u->nfrags;
+    buffer_frames = buffer_size / frame_size;
+    period_frames = u->frag_size / frame_size;
+
+    param.direction = DIRECTION_IN;
+    param.ss = &ss;
+    param.period_size = u->frag_size / pa_frame_size(&ss);
+    param.periods = u->nfrags;
+
+    if (modarg_device_id && device_string) {
+        if (pa_hal_interface_pcm_open_by_dev_id(
+                  u->hal_interface,
+                  modarg_device_id,
+                  device_string,
+                  &param,
+                  (void **)&u->pcm_handle,
+                  &u->card,
+                  &u->device)) {
+            pa_log_error("Error opening PCM device");
+            goto fail;
+        }
+    } else {
+        if (pa_hal_interface_pcm_open_by_device(
+                  u->hal_interface,
+                  modarg_device,
+                  &param,
+                  (void **)&u->pcm_handle,
+                  &u->card,
+                  &u->device)) {
+            pa_log_error("Error opening PCM device");
+            goto fail;
+        }
+    }
 
     pa_source_new_data_init(&data);
     data.driver = __FILE__;
@@ -503,19 +510,15 @@ pa_source *pa_tizenaudio_source2_new(pa_module *m, pa_modargs *ma, const char *d
     pa_proplist_sets(data.proplist, "tizen.device", u->device);
     pa_proplist_sets(data.proplist, "tizen.version", "2");
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "tizen");
-
-    // TODO: Need to check usb.
-    if (pa_modargs_get_value(ma, "device_id", NULL)) {
-        pa_proplist_sets(data.proplist, "device.bus", "usb");
-    }
-
-    frame_size = pa_frame_size(&ss);
-    buffer_size = u->frag_size * u->nfrags;
-    buffer_frames = buffer_size / frame_size;
-    period_frames = u->frag_size / frame_size;
     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%zu", buffer_frames * frame_size);
     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE, "%zu", period_frames * frame_size);
 
+    /*
+     * TODO: tricky code for tizen
+     */
+    if (pa_modargs_get_value(ma, "device_id", NULL))
+        pa_proplist_sets(data.proplist, "device.bus", "usb");
+
     if (pa_modargs_get_proplist(ma, "source_properties", data.proplist, PA_UPDATE_REPLACE) < 0) {
         pa_log_error("Invalid properties.");
         pa_source_new_data_done(&data);
@@ -534,17 +537,8 @@ pa_source *pa_tizenaudio_source2_new(pa_module *m, pa_modargs *ma, const char *d
     u->source->set_state_in_io_thread = source_set_state_in_io_thread_cb;
     u->source->userdata = u;
 
-    if (pa_hal_interface_pcm_open(u->hal_interface,
-              u->card,
-              u->device,
-              DIRECTION_IN,
-              &u->source->sample_spec,
-              u->frag_size / pa_frame_size(&u->source->sample_spec),
-              u->nfrags,
-              (void **)&u->pcm_handle)) {
-        pa_log_error("Error opening PCM device");
-        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_set_asyncmsgq(u->source, u->thread_mq.inq);
     pa_source_set_rtpoll(u->source, u->rtpoll);
@@ -555,13 +549,16 @@ pa_source *pa_tizenaudio_source2_new(pa_module *m, pa_modargs *ma, const char *d
         pa_log_error("Failed to create thread.");
         goto fail;
     }
+
     pa_source_set_fixed_latency(u->source, pa_bytes_to_usec(buffer_size, &ss));
     pa_source_put(u->source);
 
     return u->source;
 
 fail:
-    userdata_free(u);
+    if (u)
+        userdata_free(u);
+
     return NULL;
 }
 
@@ -601,5 +598,7 @@ void pa_tizenaudio_source2_free(pa_source *s) {
     pa_source_assert_ref(s);
     pa_assert_se((u = s->userdata));
 
+    pa_hal_interface_unref(u->hal_interface);
+
     userdata_free(u);
 }
index 53c0523bc367d1bf820423831a0a7875715087dd..fa3406a0373fb5801b30ffbec77ce7968432b456 100644 (file)
 
 #include <pulsecore/module.h>
 #include <pulsecore/modargs.h>
-#include <pulsecore/sink.h>
-
-pa_sink *pa_tizenaudio_source2_new(pa_module *m, pa_modargs *ma, const char *driver, pa_card *card/*mapping somthing */);
+#include <pulsecore/source.h>
+#include <pulse/channelmap.h>
+#include <pulse/sample.h>
+
+pa_source *pa_tizenaudio_source2_new(pa_module *m,
+                                        pa_modargs *ma,
+                                        const char *driver,
+                                        pa_card *c,
+                                        char **device_string,
+                                        pa_sample_spec *sample_spec,
+                                        pa_channel_map *channel_map);
 
 void pa_tizenaudio_source2_free(pa_source *s);
 
diff --git a/src/tizenaudio-util.c b/src/tizenaudio-util.c
new file mode 100644 (file)
index 0000000..3446c44
--- /dev/null
@@ -0,0 +1,199 @@
+/***
+  This file is part of PulseAudio.
+
+  Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
+
+  PulseAudio is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as published
+  by the Free Software Foundation; either version 2.1 of the License,
+  or (at your option) any later version.
+
+  PulseAudio is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with PulseAudio; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include <pulsecore/core-util.h>
+#include <pulsecore/log.h>
+
+#include "hal-interface.h"
+#include "tizenaudio-util.h"
+
+#define DEVICE_NAME_MAX                     32
+
+static int parse_to_get_card(const char *device_string, char *card, const char *def) {
+    const char *name_p;
+    char *card_p;
+
+    if (!strchr(device_string, ',')) {
+        int n;
+
+        if (!def)
+            return -1;
+
+        n = snprintf(card, DEVICE_NAME_MAX, "%s", (!strncmp(def, "hw:", 3)) ? def+3 : def);
+        card[n] = '\0';
+
+        return 0;
+    }
+
+    name_p = device_string;
+    card_p = card;
+
+    if (!strncmp(name_p, "hw:", 3))
+        name_p += 3;
+
+    while (*name_p != ',')
+        *(card_p++) = *(name_p++);
+    *card_p = '\0';
+
+    return 0;
+}
+
+static int parse_to_get_device(const char *device_string, char *device, const char *def) {
+    const char *comma_p;
+    char *device_p;
+
+    if (!(comma_p = strchr(device_string, ','))) {
+        int n;
+
+        if (!def)
+            return -1;
+
+        n = snprintf(device, DEVICE_NAME_MAX, "%s", def);
+        device[n] = '\0';
+
+        return 0;
+    }
+
+    comma_p++;
+    device_p = device;
+    while (*comma_p != '\0')
+        *(device_p++) = *(comma_p++);
+    *device_p = '\0';
+
+    return 0;
+}
+
+int32_t pa_hal_interface_pcm_open_by_dev_id(pa_hal_interface *h,
+                                            const char *dev_id,
+                                            char **device_string,
+                                            pa_pcm_params *param,
+                                            pcm_handle *pcm_h,
+                                            char **rcard,
+                                            char **rdevice) {
+    char **i;
+    char card[DEVICE_NAME_MAX];
+    char device[DEVICE_NAME_MAX];
+
+    pa_assert(dev_id);
+    pa_assert(device_string);
+    pa_assert(device_string[0]);
+
+    pa_assert(rcard);
+    pa_assert(rdevice);
+
+    for (i=device_string; *i; i++) {
+        char *d;
+
+        pa_log_debug("Try to open device(%s), id(%s)", *i, dev_id);
+
+        if (!(d = pa_replace(*i, "%f", dev_id))) {
+            pa_log_error("Error parsing i(%s) dev_id(%s)", *i, dev_id);
+            continue;
+        }
+
+        if (parse_to_get_device(d, device, "0") < 0) {
+            pa_log_error("Failed to parse device_string. It doesn't contain device");
+            pa_xfree(d);
+            continue;
+        }
+
+        if (parse_to_get_card(d, card, (const char *)d) < 0) {
+            pa_log_error("Failed to parse card");
+            pa_xfree(d);
+            continue;
+        }
+
+        if (pa_hal_interface_pcm_open(h,
+                    card,
+                    device,
+                    param->direction,
+                    param->ss,
+                    param->period_size,
+                    param->periods,
+                    (void **)pcm_h)) {
+            pa_log_error("Failed to open PCM device (%s)", d);
+            pa_xfree(d);
+            continue;
+        }
+
+        *rcard = pa_xstrdup(card);
+        *rdevice = pa_xstrdup(device);
+
+        pa_log_debug("card(%s) device(%s) opened successfully", *rcard, *rdevice);
+
+        pa_xfree(d);
+
+        return 0;
+    }
+
+    pa_log_error("Error opening PCM device");
+
+    return -1;
+}
+
+int32_t pa_hal_interface_pcm_open_by_device(pa_hal_interface *h,
+                                            const char* dev,
+                                            pa_pcm_params *param,
+                                            pcm_handle *pcm_h,
+                                            char **rcard,
+                                            char **rdevice) {
+    char card[DEVICE_NAME_MAX];
+    char device[DEVICE_NAME_MAX];
+
+    pa_assert(dev);
+
+    pa_log_debug("Try to open device(%s)", dev);
+
+    if (parse_to_get_device(dev, device, NULL) < 0) {
+        pa_log_error("Failed to parse device. dev(%s)", dev);
+        return -1;
+    }
+
+    if (parse_to_get_card(dev, card, NULL) < 0) {
+        pa_log_error("Failed to parse card. dev(%s)", dev);
+        return -1;
+    }
+
+    if (pa_hal_interface_pcm_open(h,
+                card,
+                device,
+                param->direction,
+                param->ss,
+                param->period_size,
+                param->periods,
+                (void **)pcm_h)) {
+        pa_log_error("Failed to open PCM device (%s) card(%s), device(%s)", dev, card, device);
+        return -1;
+    }
+
+    *rcard = pa_xstrdup(card);
+    *rdevice = pa_xstrdup(device);
+
+    pa_log_debug("card(%s) device(%s) opened successfully", *rcard, *rdevice);
+
+    return 0;
+}
diff --git a/src/tizenaudio-util.h b/src/tizenaudio-util.h
new file mode 100644 (file)
index 0000000..aa6d29e
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef footizenaudioutilhfoo
+#define footizenaudioutilhfoo
+
+/***
+  This file is part of PulseAudio.
+
+  Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
+
+  PulseAudio is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as published
+  by the Free Software Foundation; either version 2.1 of the License,
+  or (at your option) any later version.
+
+  PulseAudio is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with PulseAudio; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pulse/sample.h>
+
+typedef struct pa_pcm_params pa_pcm_params;
+struct pa_pcm_params {
+       io_direction_t direction;
+       pa_sample_spec *ss;
+       uint32_t period_size;
+       uint32_t periods;
+};
+
+
+int32_t pa_hal_interface_pcm_open_by_dev_id(pa_hal_interface *h,
+                                            const char *dev_id,
+                                            char **device_string,
+                                            pa_pcm_params *param,
+                                            pcm_handle *pcm_h,
+                                            char **rcard,
+                                            char **rdevice);
+
+int32_t pa_hal_interface_pcm_open_by_device(pa_hal_interface *h,
+                                            const char* dev,
+                                            pa_pcm_params *param,
+                                            pcm_handle *pcm_h,
+                                            char **rcard,
+                                            char **rdevice);
+#endif
+