MODULE_LIBADD = $(AM_LIBADD) $(PACORE_LIBS) $(PA_LIBS)
pulsemodlibexec_LTLIBRARIES = \
- libhal-interface.la \
- libprocessor.la \
- libcommunicator.la \
- libtizenaudio-util.la \
- module-tizenaudio-sink.la \
- module-tizenaudio-source.la \
- module-tizenaudio-sink2.la \
- module-tizenaudio-source2.la \
- module-tizenaudio-policy.la \
- module-tizenaudio-discover.la \
- module-tizenaudio-publish.la \
- module-tizenaudio-echo-cancel.la \
- module-sound-player.la \
- module-tone-player.la \
- module-poweroff.la
+ libhal-interface.la \
+ libprocessor.la \
+ libcommunicator.la \
+ libtizenaudio-util.la \
+ module-tizenaudio-sink.la \
+ module-tizenaudio-source.la \
+ module-tizenaudio-sink2.la \
+ module-tizenaudio-source2.la \
+ module-tizenaudio-policy.la \
+ module-tizenaudio-discover.la \
+ module-tizenaudio-publish.la \
+ module-tizenaudio-echo-cancel.la \
+ module-sound-player.la \
+ module-tone-player.la \
+ module-poweroff.la
if ENABLE_HALTC
pulsemodlibexec_LTLIBRARIES += module-tizenaudio-haltc.la
endif
module_tizenaudio_source_la_LIBADD = $(MODULE_LIBADD) libhal-interface.la
module_tizenaudio_source_la_CFLAGS = $(MODULE_CFLAGS) -DPA_MODULE_NAME=module_tizenaudio_source
-libtizenaudio_util_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_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 = $(AM_LDFLAGS) $(PA_LDFLAGS) -avoid-version
libtizenaudio_util_la_LIBADD = $(AM_LIBADD) $(PA_LIBS) libhal-interface.la
libtizenaudio_util_la_CFLAGS = $(MODULE_CFLAGS)
Name: pulseaudio-modules-tizen
Summary: Pulseaudio modules for Tizen
-Version: 15.0.19
+Version: 15.0.20
Release: 0
Group: Multimedia/Audio
License: LGPL-2.1+
}
int32_t pa_hal_interface_pcm_get_params(pa_hal_interface *h, pcm_handle pcm_h, uint32_t direction,
- void **sample_spec, uint32_t *period_size, uint32_t *periods) {
+ void *sample_spec, uint32_t *period_size, uint32_t *periods) {
audio_return_e hal_ret = AUDIO_RET_OK;
pa_assert(h);
- pa_assert(*sample_spec);
+ pa_assert(sample_spec);
pa_assert(period_size);
pa_assert(periods);
int32_t pa_hal_interface_pcm_read(pa_hal_interface *h, pcm_handle pcm_h, void *buffer, uint32_t frames);
int32_t pa_hal_interface_pcm_get_fd(pa_hal_interface *h, pcm_handle pcm_h, int *fd);
int32_t pa_hal_interface_pcm_recover(pa_hal_interface *h, pcm_handle pcm_h, int err);
-int32_t pa_hal_interface_pcm_get_params(pa_hal_interface *h, pcm_handle pcm_h, uint32_t direction, void **sample_spec, uint32_t *period_size, uint32_t *periods);
+int32_t pa_hal_interface_pcm_get_params(pa_hal_interface *h, pcm_handle pcm_h, uint32_t direction, void *sample_spec, uint32_t *period_size, uint32_t *periods);
int32_t pa_hal_interface_pcm_set_params(pa_hal_interface *h, pcm_handle pcm_h, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods);
int32_t pa_hal_interface_add_message_callback(pa_hal_interface *h, hal_message_callback callback, void *user_data);
int32_t pa_hal_interface_remove_message_callback(pa_hal_interface *h, hal_message_callback callback);
goto fail;
}
- if (!(m->userdata = pa_tizenaudio_sink2_new(m, ma, __FILE__)))
+ if (!(m->userdata = pa_tizenaudio_sink2_new(m, ma, __FILE__, NULL, NULL, NULL, NULL)))
goto fail;
pa_modargs_free(ma);
goto fail;
}
- if (!(m->userdata = pa_tizenaudio_source2_new(m, ma, __FILE__)))
+ if (!(m->userdata = pa_tizenaudio_source2_new(m, ma, __FILE__, NULL, NULL, NULL, NULL)))
goto fail;
pa_modargs_free(ma);
#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"
#define DEVICE_NAME_MAX 30
-#define DEFAULT_FRAGMENT_MSEC 20
+#define DEFAULT_FRAGMENT_MSEC 10
#define DEFAULT_FRAGMENTS 4
struct userdata {
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_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_t param;
+
+ uint32_t period_size;
+ uint32_t periods;
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;
}
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", NULL))) {
- pa_log_error("device is invalid");
+ 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;
}
- 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;
- }
-
- 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 ||
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 = (size_t)(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;
+
+ pa_log_info("Try to open device with rate(%d), channels(%d), format(%s), period_size(%u), periods(%u)",
+ ss.rate, ss.channels, pa_sample_format_to_string(ss.format), param.period_size, param.periods);
+
+ if (modarg_device_id && device_string) {
+ if (pa_tz_util_pcm_open_by_dev_id(
+ u->hal_interface,
+ modarg_device_id,
+ device_string,
+ ¶m,
+ (void **)&u->pcm_handle,
+ &u->card,
+ &u->device)) {
+ pa_log_error("Error opening PCM device");
+ goto fail;
+ }
+ } else if (modarg_device) {
+ if (pa_tz_util_pcm_open_by_device(
+ u->hal_interface,
+ modarg_device,
+ ¶m,
+ (void **)&u->pcm_handle,
+ &u->card,
+ &u->device)) {
+ pa_log_error("Error opening PCM device");
+ goto fail;
+ }
+ } else {
+ pa_log_error("Device name doesn't exist");
+ goto fail;
+ }
+
+ if (!pa_sample_spec_equal(&ss, ¶m.ss)) {
+ pa_sample_spec _ss;
+ char requested_spec[PA_SAMPLE_SPEC_SNPRINT_MAX];
+ char selected_spec[PA_SAMPLE_SPEC_SNPRINT_MAX];
+
+ if (pa_hal_interface_pcm_get_params(u->hal_interface, u->pcm_handle, 0, (void *)&_ss, &period_size, &periods) < 0) {
+ pa_log_error("Failed to get pcm params");
+ goto fail;
+ }
+
+ frame_size = pa_frame_size(¶m.ss);
+ u->frag_size = period_size * frame_size;
+ /* TODO: can't trust periods value from hal */
+ u->nfrags = param.periods;
+
+ buffer_size = (size_t)(u->frag_size * u->nfrags);
+ buffer_frames = buffer_size / frame_size;
+ period_frames = u->frag_size / frame_size;
+
+ pa_log_info("Device doesn't support sample_spec(%s). It was changed to (%s)",
+ pa_sample_spec_snprint(requested_spec, PA_SAMPLE_SPEC_SNPRINT_MAX, &ss),
+ pa_sample_spec_snprint(selected_spec, PA_SAMPLE_SPEC_SNPRINT_MAX, ¶m.ss));
+
+ ss = param.ss;
+ }
+
+ pa_log_info("Device opened. card(%s), device(%s) rate(%d), channels(%d), format(%s), "
+ "frag_size(%u), nfrags(%u), period_size(%u), periods(%u)",
+ u->card, u->device, ss.rate, ss.channels, pa_sample_format_to_string(ss.format),
+ u->frag_size, u->nfrags, param.period_size, param.periods);
pa_sink_new_data_init(&data);
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));
pa_sink_new_data_set_sample_spec(&data, &ss);
pa_sink_new_data_set_channel_map(&data, &map);
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");
-
- frame_size = pa_frame_size(&ss);
- buffer_size = (size_t)(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);
+ if (pa_modargs_get_value(ma, "device_id", NULL))
+ 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);
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);
return u->sink;
fail:
- userdata_free(u);
+ if (u)
+ userdata_free(u);
+
return NULL;
}
#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);
+#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);
#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"
#define DEVICE_NAME_MAX 30
-#define DEFAULT_FRAGMENT_MSEC 20
+#define DEFAULT_FRAGMENT_MSEC 10
#define DEFAULT_FRAGMENTS 4
struct userdata {
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_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_t param;
+
+ uint32_t period_size;
+ uint32_t periods;
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;
}
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", NULL))) {
- pa_log_error("device is invalid");
+ 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;
}
- 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;
- }
-
- 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 ||
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 = (size_t)(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;
+
+ pa_log_info("Try to open device with rate(%d), channels(%d), format(%s), period_size(%u), periods(%u)",
+ ss.rate, ss.channels, pa_sample_format_to_string(ss.format), param.period_size, param.periods);
+
+ if (modarg_device_id && device_string) {
+ if (pa_tz_util_pcm_open_by_dev_id(
+ u->hal_interface,
+ modarg_device_id,
+ device_string,
+ ¶m,
+ (void **)&u->pcm_handle,
+ &u->card,
+ &u->device)) {
+ pa_log_error("Error opening PCM device");
+ goto fail;
+ }
+ } else if (modarg_device) {
+ if (pa_tz_util_pcm_open_by_device(
+ u->hal_interface,
+ modarg_device,
+ ¶m,
+ (void **)&u->pcm_handle,
+ &u->card,
+ &u->device)) {
+ pa_log_error("Error opening PCM device");
+ goto fail;
+ }
+ } else {
+ pa_log_error("Device name doesn't exist");
+ goto fail;
+ }
+
+ if (!pa_sample_spec_equal(&ss, ¶m.ss)) {
+ pa_sample_spec _ss;
+ char requested_spec[PA_SAMPLE_SPEC_SNPRINT_MAX];
+ char selected_spec[PA_SAMPLE_SPEC_SNPRINT_MAX];
+
+ if (pa_hal_interface_pcm_get_params(u->hal_interface, u->pcm_handle, 0, (void *)&_ss, &period_size, &periods) < 0) {
+ pa_log_error("Failed to get pcm params");
+ goto fail;
+ }
+
+ frame_size = pa_frame_size(¶m.ss);
+ u->frag_size = period_size * frame_size;
+ /* TODO: can't trust periods value from hal */
+ u->nfrags = param.periods;
+
+ buffer_size = (size_t)(u->frag_size * u->nfrags);
+ buffer_frames = buffer_size / frame_size;
+ period_frames = u->frag_size / frame_size;
+
+ pa_log_info("Device doesn't support sample_spec(%s). It was changed to (%s)",
+ pa_sample_spec_snprint(requested_spec, PA_SAMPLE_SPEC_SNPRINT_MAX, &ss),
+ pa_sample_spec_snprint(selected_spec, PA_SAMPLE_SPEC_SNPRINT_MAX, ¶m.ss));
+
+ ss = param.ss;
+ }
+
+ pa_log_info("Device opened. card(%s), device(%s) rate(%d), channels(%d), format(%s), "
+ "frag_size(%u), nfrags(%u), period_size(%u), periods(%u)",
+ u->card, u->device, ss.rate, ss.channels, pa_sample_format_to_string(ss.format),
+ u->frag_size, u->nfrags, period_size, param.periods);
pa_source_new_data_init(&data);
data.driver = driver;
data.module = m;
+ data.card = c;
pa_source_new_data_set_name(&data, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME));
pa_source_new_data_set_sample_spec(&data, &ss);
pa_source_new_data_set_channel_map(&data, &map);
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");
-
- frame_size = pa_frame_size(&ss);
- buffer_size = (size_t)(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);
+ if (pa_modargs_get_value(ma, "device_id", NULL))
+ pa_proplist_sets(data.proplist, PA_PROP_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);
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);
return u->source;
fail:
- userdata_free(u);
+ if (u)
+ userdata_free(u);
+
return NULL;
}
#include <pulsecore/module.h>
#include <pulsecore/modargs.h>
#include <pulsecore/source.h>
-
-pa_sink *pa_tizenaudio_source2_new(pa_module *m, pa_modargs *ma, const char *driver);
+#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);
--- /dev/null
+/***
+ This file is part of PulseAudio.
+
+ Copyright (c) 2022 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 CARD_NAME_MAX 32
+#define DEVICE_NAME_MAX 32
+
+/*
+ * Extract card string from the device_string that contains device name like 'hw:1,2'
+ * card variable will have '1' after calling this function.
+ */
+static int parse_to_get_card(const char *device_string, char *card, int n, const char *def) {
+ char *name_p;
+ char *card_p;
+ char *sep;
+ int i;
+
+ /* device_string contains various device name such as 'ALSA,0', 'hw:0,0" and "hw:1,1,1" */
+ if (!(sep = strchr(device_string, ':'))) {
+
+ /* It doesn't have a prefix like 'hw:', 'hdmi:' */
+ if ((sep = strchr(device_string, ','))) {
+ size_t size = sep - device_string;
+
+ memcpy(card, device_string, size);
+ card[size] = '\0';
+
+ return 0;
+ }
+
+ /* Can't find card number. Use default */
+ if (!def)
+ return -1;
+
+ snprintf(card, n, "%s", def);
+ } else {
+ name_p = ++sep;
+ card_p = card;
+
+ for (i = 0; i < n; i++) {
+ if (*name_p == ',' || *name_p == '\0')
+ break;
+
+ *(card_p++) = *(name_p++);
+ }
+
+ *card_p = '\0';
+ }
+
+ return 0;
+}
+
+/*
+ * Extract card string from the device_string that contains device name like 'hw:1,2'
+ * card variable will have '2' after calling this function.
+ */
+static int parse_to_get_device(const char *device_string, char *device, int n, const char *def) {
+ char *device_p;
+ char *sep;
+
+ if (!(sep = strchr(device_string, ','))) {
+ if (!def)
+ return -1;
+
+ n = snprintf(device, n, "%s", def);
+ } else {
+ sep++;
+ device_p = device;
+
+ while (*sep != '\0')
+ *(device_p++) = *(sep++);
+
+ *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_t *param,
+ pcm_handle *pcm_h,
+ char **card,
+ char **device) {
+ 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(card);
+ pa_assert(device);
+
+ 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, DEVICE_NAME_MAX, "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, CARD_NAME_MAX, "0") < 0) {
+ pa_log_error("Failed to parse card");
+ pa_xfree(d);
+ continue;
+ }
+
+ if (pa_hal_interface_pcm_open(h,
+ _card,
+ _device,
+ param->direction,
+ ¶m->ss,
+ param->period_size,
+ param->periods,
+ (void **)pcm_h)) {
+ pa_log_error("Failed to open PCM device (%s)", d);
+ pa_xfree(d);
+ continue;
+ }
+
+ *card = pa_xstrdup(_card);
+ *device = pa_xstrdup(_device);
+
+ pa_log_debug("card(%s) device(%s) opened successfully", *card, *device);
+
+ 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_t *param,
+ pcm_handle *pcm_h,
+ char **card,
+ char **device) {
+ 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, DEVICE_NAME_MAX, NULL) < 0) {
+ pa_log_error("Failed to parse device. dev(%s)", dev);
+ return -1;
+ }
+
+ if (parse_to_get_card(dev, _card, CARD_NAME_MAX, 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,
+ ¶m->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;
+ }
+
+ *card = pa_xstrdup(_card);
+ *device = pa_xstrdup(_device);
+
+ pa_log_debug("card(%s) device(%s) opened successfully", *card, *device);
+
+ return 0;
+}
--- /dev/null
+#ifndef footizenaudioutilhfoo
+#define footizenaudioutilhfoo
+
+/***
+ This file is part of PulseAudio.
+
+ Copyright (c) 2022 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 {
+ io_direction_t direction;
+ pa_sample_spec ss;
+ uint32_t period_size;
+ uint32_t periods;
+} pa_pcm_params_t;
+
+
+int32_t pa_tz_util_pcm_open_by_dev_id(pa_hal_interface *h,
+ const char *dev_id,
+ char **device_string,
+ pa_pcm_params_t *param,
+ pcm_handle *pcm_h,
+ char **card,
+ char **device);
+
+int32_t pa_tz_util_pcm_open_by_device(pa_hal_interface *h,
+ const char* dev,
+ pa_pcm_params_t *param,
+ pcm_handle *pcm_h,
+ char **card,
+ char **device);
+#endif
+