From 1677d8a0ef35572e10cb8e8ebd4f7a5814c845de Mon Sep 17 00:00:00 2001 From: Jaechul Lee Date: Fri, 3 Dec 2021 11:15:30 +0900 Subject: [PATCH 01/16] Support external device playback and capture on sink2/source2 module-alsa-card tries to use 'device_id' that is from udev but tizenaudio-sink2/source2 can't load devices with device_id. This patch makes devices load with device_id and device_string both. [Version] 15.0.20 [Issue Type] New feature Change-Id: I2dcd7b4abdc88abacec5ba997050217c0c8bfc48 Signed-off-by: Jaechul Lee --- Makefile.am | 39 +++--- packaging/pulseaudio-modules-tizen.spec | 2 +- src/hal-interface.c | 4 +- src/hal-interface.h | 2 +- src/module-tizenaudio-sink2.c | 2 +- src/module-tizenaudio-source2.c | 2 +- src/tizenaudio-sink2.c | 175 ++++++++++++++++---------- src/tizenaudio-sink2.h | 12 +- src/tizenaudio-source2.c | 177 ++++++++++++++++---------- src/tizenaudio-source2.h | 12 +- src/tizenaudio-util.c | 217 ++++++++++++++++++++++++++++++++ src/tizenaudio-util.h | 54 ++++++++ 12 files changed, 534 insertions(+), 164 deletions(-) create mode 100644 src/tizenaudio-util.c create mode 100644 src/tizenaudio-util.h diff --git a/Makefile.am b/Makefile.am index 12098ed..b3d0913 100644 --- a/Makefile.am +++ b/Makefile.am @@ -31,21 +31,21 @@ MODULE_LDFLAGS = $(AM_LDFLAGS) $(PACORE_LDFLAGS) $(PA_LDFLAGS) -module -disable- 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 @@ -75,7 +75,14 @@ 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_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) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index 5a5282f..cd1cfef 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -2,7 +2,7 @@ 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+ diff --git a/src/hal-interface.c b/src/hal-interface.c index e108f38..6837508 100644 --- a/src/hal-interface.c +++ b/src/hal-interface.c @@ -433,11 +433,11 @@ int32_t pa_hal_interface_pcm_recover(pa_hal_interface *h, pcm_handle pcm_h, int } 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); diff --git a/src/hal-interface.h b/src/hal-interface.h index ebfca2f..800ff6c 100644 --- a/src/hal-interface.h +++ b/src/hal-interface.h @@ -111,7 +111,7 @@ int32_t pa_hal_interface_pcm_write(pa_hal_interface *h, pcm_handle pcm_h, const 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); diff --git a/src/module-tizenaudio-sink2.c b/src/module-tizenaudio-sink2.c index 0861262..49410e0 100644 --- a/src/module-tizenaudio-sink2.c +++ b/src/module-tizenaudio-sink2.c @@ -65,7 +65,7 @@ int pa__init(pa_module *m) { 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); diff --git a/src/module-tizenaudio-source2.c b/src/module-tizenaudio-source2.c index 1df595e..cb821fb 100644 --- a/src/module-tizenaudio-source2.c +++ b/src/module-tizenaudio-source2.c @@ -65,7 +65,7 @@ int pa__init(pa_module *m) { 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); diff --git a/src/tizenaudio-sink2.c b/src/tizenaudio-sink2.c index a7ffd93..ff0dbc7 100644 --- a/src/tizenaudio-sink2.c +++ b/src/tizenaudio-sink2.c @@ -46,12 +46,13 @@ #include #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 { @@ -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_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; } @@ -449,19 +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", 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 || @@ -469,11 +444,83 @@ 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 = (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); @@ -483,14 +530,12 @@ 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"); - - 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); @@ -509,17 +554,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); @@ -538,7 +573,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; } diff --git a/src/tizenaudio-sink2.h b/src/tizenaudio-sink2.h index dd9e9e2..854ea9a 100644 --- a/src/tizenaudio-sink2.h +++ b/src/tizenaudio-sink2.h @@ -29,8 +29,16 @@ #include #include #include - -pa_sink *pa_tizenaudio_sink2_new(pa_module *m, pa_modargs *ma, const char *driver); +#include +#include + +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); diff --git a/src/tizenaudio-source2.c b/src/tizenaudio-source2.c index 8ddfa2f..846b086 100644 --- a/src/tizenaudio-source2.c +++ b/src/tizenaudio-source2.c @@ -46,12 +46,13 @@ #include #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 { @@ -382,58 +383,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_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; } @@ -452,19 +434,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", 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 || @@ -472,11 +448,83 @@ 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 = (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); @@ -486,14 +534,12 @@ 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"); - - 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); @@ -512,17 +558,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); @@ -540,7 +577,9 @@ pa_source *pa_tizenaudio_source2_new(pa_module *m, pa_modargs *ma, const char *d return u->source; fail: - userdata_free(u); + if (u) + userdata_free(u); + return NULL; } diff --git a/src/tizenaudio-source2.h b/src/tizenaudio-source2.h index a8e67c0..c1cdcae 100644 --- a/src/tizenaudio-source2.h +++ b/src/tizenaudio-source2.h @@ -29,8 +29,16 @@ #include #include #include - -pa_sink *pa_tizenaudio_source2_new(pa_module *m, pa_modargs *ma, const char *driver); +#include +#include + +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 index 0000000..17be479 --- /dev/null +++ b/src/tizenaudio-util.c @@ -0,0 +1,217 @@ +/*** + 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 +#endif + +#include + +#include +#include + +#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; +} diff --git a/src/tizenaudio-util.h b/src/tizenaudio-util.h new file mode 100644 index 0000000..ea74fb9 --- /dev/null +++ b/src/tizenaudio-util.h @@ -0,0 +1,54 @@ +#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 +#endif + +#include + +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 + -- 2.7.4 From 524ffee0ef91c855368f0be0a70d335114d37c7c Mon Sep 17 00:00:00 2001 From: Jaechul Lee Date: Thu, 2 Jun 2022 11:20:43 +0900 Subject: [PATCH 02/16] Improve latency difference between reference and capture source * Not allow negative latency * Added mchstreamer specific code * Fixed build warning on aarch64 [Version] 15.0.21 [Issue Type] Improvement Change-Id: Idd6c4337ec6567e52dd86bbca5c194a897804b43 Signed-off-by: Jaechul Lee --- packaging/pulseaudio-modules-tizen.spec | 2 +- src/echo-cancel/algo_reference_copy.c | 11 ++++++++++- src/echo-cancel/module-tizenaudio-echo-cancel.c | 2 +- src/echo-cancel/processor.c | 16 ++++++++++++++-- src/tizenaudio-sink2.c | 13 ++++++++++--- src/tizenaudio-source2.c | 9 +++++++-- 6 files changed, 43 insertions(+), 10 deletions(-) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index cd1cfef..1b6d631 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -2,7 +2,7 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 15.0.20 +Version: 15.0.21 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/echo-cancel/algo_reference_copy.c b/src/echo-cancel/algo_reference_copy.c index 2d9cf0b..7b397ec 100644 --- a/src/echo-cancel/algo_reference_copy.c +++ b/src/echo-cancel/algo_reference_copy.c @@ -94,13 +94,22 @@ int32_t reference_copy_change_reference_spec(void *priv, pa_sample_spec *source_ pa_assert(map); channels = rc->ss.channels - source_ss->channels; - if (channels <= 0) + if (channels <= 0) { + pa_log_error("No empty channels. reference copy will be disabled"); return -1; + } + + /* TODO: temporary code for supporting mchstreamer. reference copy uses the last 2ch of its channels */ + if (rc->ss.channels == 16) + channels = 2; *sample_spec = rc->ss; sample_spec->channels = rc->reference_channels = channels; pa_channel_map_init_auto(map, channels, PA_CHANNEL_MAP_AIFF); + pa_log_info("reference will be copied to empty channels(%d). source-output ch(%d), source ch(%d)", + channels, rc->ss.channels, source_ss->channels); + return 0; } diff --git a/src/echo-cancel/module-tizenaudio-echo-cancel.c b/src/echo-cancel/module-tizenaudio-echo-cancel.c index f9e13c0..7697368 100644 --- a/src/echo-cancel/module-tizenaudio-echo-cancel.c +++ b/src/echo-cancel/module-tizenaudio-echo-cancel.c @@ -298,7 +298,7 @@ static int process_msg( /* trigger resolves a race condition related to post_process between source and render thread */ if (u->triggered) { - if (code == PA_ECHO_CANCEL_MESSAGE_PUSH_DATA || code == PA_ECHO_CANCEL_MESSAGE_PUSH_ECHO) { + if (code == PA_ECHO_CANCEL_MESSAGE_PUSH_ECHO) { pa_source_output *o = NULL; pa_usec_t latency; diff --git a/src/echo-cancel/processor.c b/src/echo-cancel/processor.c index 0052ab8..dbce5fa 100644 --- a/src/echo-cancel/processor.c +++ b/src/echo-cancel/processor.c @@ -43,6 +43,7 @@ #endif #define MEMBLOCKQ_MAXLENGTH (16 * 1024 * 1024) +#define MEMBLOCKQ_PUSH_REFERENCE_BLOCK_ALIGN typedef struct pa_processor_method_interface pa_processor_method_interface; struct pa_processor { @@ -298,14 +299,24 @@ int pa_processor_setup_reference_memblockq_padding(pa_processor *processor, pa_u pa_assert(processor); bytes = pa_usec_to_bytes(latency, &processor->reference_memblockq_ss); - n = (bytes + (processor->reference_process_bytes - 1)) / processor->reference_process_bytes; +#ifdef MEMBLOCKQ_PUSH_REFERENCE_BLOCK_ALIGN + n = (bytes + (processor->reference_process_bytes - 1)) / processor->reference_process_bytes; pa_silence_memchunk_get( &processor->core->silence_cache, processor->core->mempool, &silence, &processor->reference_memblockq_ss, processor->reference_process_bytes); +#else + n = 1; + pa_silence_memchunk_get( + &processor->core->silence_cache, + processor->core->mempool, + &silence, + &processor->reference_memblockq_ss, + bytes); +#endif write_index = pa_memblockq_get_write_index(processor->reference_memblockq); read_index = pa_memblockq_get_read_index(processor->reference_memblockq); @@ -315,9 +326,10 @@ int pa_processor_setup_reference_memblockq_padding(pa_processor *processor, pa_u pa_memblock_unref(silence.memblock); - pa_log_info("push n(%u) silence blocks. ref_process_bytes(%zu) " + pa_log_info("push n(%u) silence blocks. latency(%" PRId64 "), ref_process_bytes(%zu) " "write_index(%" PRId64 "->%" PRId64 "), read_index(%" PRId64 "->%" PRId64 ")", pa_memblockq_get_nblocks(processor->reference_memblockq), + latency, processor->reference_process_bytes, write_index, pa_memblockq_get_write_index(processor->reference_memblockq), read_index, pa_memblockq_get_read_index(processor->reference_memblockq)); diff --git a/src/tizenaudio-sink2.c b/src/tizenaudio-sink2.c index ff0dbc7..f8601ac 100644 --- a/src/tizenaudio-sink2.c +++ b/src/tizenaudio-sink2.c @@ -169,7 +169,6 @@ static int unsuspend(struct userdata *u) { u->write_count = 0; u->first = true; - u->timestamp = pa_rtclock_now(); pa_log_info("Resumed successfully..."); @@ -245,8 +244,13 @@ static int sink_process_msg( case PA_SINK_MESSAGE_GET_LATENCY: { int64_t r = 0; - if (u->pcm_handle) - r = u->timestamp + pa_bytes_to_usec(u->write_count, &u->sink->sample_spec) - pa_rtclock_now(); + if (u->pcm_handle) { + pa_usec_t now = pa_rtclock_now(); + pa_usec_t write_latency = u->timestamp + pa_bytes_to_usec(u->write_count, &u->sink->sample_spec); + + if (now < write_latency) + r = write_latency - now; + } *((int64_t *) data) = r; @@ -297,6 +301,9 @@ static int process_render(struct userdata *u) { pa_sink_render_full(u->sink, u->frag_size, &chunk); p = pa_memblock_acquire(chunk.memblock); + if (u->first) + u->timestamp = pa_rtclock_now(); + if (pa_hal_interface_pcm_write(u->hal_interface, u->pcm_handle, (const char*)p + chunk.index, (uint32_t)frames_to_write)) { pa_log_error("failed to write pcm. p(%p), size(%zu)", p, frames_to_write); return -1; diff --git a/src/tizenaudio-source2.c b/src/tizenaudio-source2.c index 846b086..948e8f0 100644 --- a/src/tizenaudio-source2.c +++ b/src/tizenaudio-source2.c @@ -248,8 +248,13 @@ static int source_process_msg( case PA_SOURCE_MESSAGE_GET_LATENCY: { uint64_t r = 0; - if (u->pcm_handle) - r = pa_rtclock_now() - (u->timestamp + pa_bytes_to_usec(u->read_count, &u->source->sample_spec)); + if (u->pcm_handle) { + pa_usec_t now = pa_rtclock_now(); + pa_usec_t read_latency = u->timestamp + pa_bytes_to_usec(u->read_count, &u->source->sample_spec); + + if (now > read_latency) + r = now - read_latency; + } *((int64_t *) data) = r; -- 2.7.4 From 6947e28faa9126474a03a5d7924e75bfa288a96f Mon Sep 17 00:00:00 2001 From: Jaechul Lee Date: Tue, 28 Jun 2022 16:42:58 +0900 Subject: [PATCH 03/16] tizenaudio-util: Fix loading errors This patch fixes undefined symbol: pa_tz_util_pcm_open_by_* [Version] 15.0.22 [Issue Type] Runtime error Change-Id: I7c172938d4480348445458a56e1ba9a8ddf14de2 Signed-off-by: Jaechul Lee --- packaging/pulseaudio-modules-tizen.spec | 2 +- src/tizenaudio-util.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index 1b6d631..2eae259 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -2,7 +2,7 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 15.0.21 +Version: 15.0.22 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/tizenaudio-util.c b/src/tizenaudio-util.c index 17be479..c4fbc49 100644 --- a/src/tizenaudio-util.c +++ b/src/tizenaudio-util.c @@ -105,7 +105,7 @@ static int parse_to_get_device(const char *device_string, char *device, int n, c return 0; } -int32_t pa_hal_interface_pcm_open_by_dev_id(pa_hal_interface *h, +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, @@ -173,7 +173,7 @@ int32_t pa_hal_interface_pcm_open_by_dev_id(pa_hal_interface *h, return -1; } -int32_t pa_hal_interface_pcm_open_by_device(pa_hal_interface *h, +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, -- 2.7.4 From ae4ac2a78f77f549956f504f2bc13f003ba2bc4f Mon Sep 17 00:00:00 2001 From: Jaechul Lee Date: Thu, 30 Jun 2022 13:10:12 +0900 Subject: [PATCH 04/16] echo-cancel: Replace 'algo' prefix with 'method' [Version] 15.0.23 [Issue Type] Rename Change-Id: I8eee586036ef0f107f94413285b22a5736284318 Signed-off-by: Jaechul Lee --- Makefile.am | 8 ++++---- src/echo-cancel/{algo_adrian.c => method_adrian.c} | 10 +++++----- .../{algo_reference_copy.c => method_reference_copy.c} | 0 src/echo-cancel/{algo_speex.c => method_speex.c} | 10 +++++----- src/echo-cancel/{algo_webrtc.cpp => method_webrtc.cpp} | 18 +++++++++--------- 5 files changed, 23 insertions(+), 23 deletions(-) rename src/echo-cancel/{algo_adrian.c => method_adrian.c} (91%) rename src/echo-cancel/{algo_reference_copy.c => method_reference_copy.c} (100%) rename src/echo-cancel/{algo_speex.c => method_speex.c} (95%) rename src/echo-cancel/{algo_webrtc.cpp => method_webrtc.cpp} (93%) diff --git a/Makefile.am b/Makefile.am index b3d0913..cd71bb1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -98,9 +98,9 @@ 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 = \ - src/echo-cancel/algo_speex.c \ - src/echo-cancel/algo_reference_copy.c \ - src/echo-cancel/algo_adrian.c \ + src/echo-cancel/method_speex.c \ + src/echo-cancel/method_reference_copy.c \ + src/echo-cancel/method_adrian.c \ src/echo-cancel/adrian-aec.c \ src/echo-cancel/processor.c \ src/echo-cancel/processor.h \ @@ -110,7 +110,7 @@ libprocessor_la_LIBADD = $(AM_LIBADD) $(LIBSPEEX_LIBS) libprocessor_la_CFLAGS = $(AM_CFLAGS) $(PA_CFLAGS) $(LIBSPEEX_CFLAGS) if ENABLE_WEBRTC -libprocessor_la_SOURCES += src/echo-cancel/algo_webrtc.cpp +libprocessor_la_SOURCES += src/echo-cancel/method_webrtc.cpp libprocessor_la_LIBADD += $(WEBRTC_LIBS) libprocessor_la_CPPFLAGS = $(WEBRTC_CFLAGS) $(PA_CFLAGS) -DSUPPORT_METHOD_WEBRTC -std=c++17 endif diff --git a/src/echo-cancel/algo_adrian.c b/src/echo-cancel/method_adrian.c similarity index 91% rename from src/echo-cancel/algo_adrian.c rename to src/echo-cancel/method_adrian.c index a5d2e72..d673dcd 100644 --- a/src/echo-cancel/algo_adrian.c +++ b/src/echo-cancel/method_adrian.c @@ -32,13 +32,13 @@ #include "adrian-aec.h" -struct ec_adrian { +struct method_adrian { int blocksize; AEC *aec; }; void *adrian_create(size_t nframes, pa_sample_spec *ss) { - struct ec_adrian *adrian = NULL; + struct method_adrian *adrian = NULL; pa_assert(ss); @@ -47,7 +47,7 @@ void *adrian_create(size_t nframes, pa_sample_spec *ss) { return NULL; } - adrian = pa_xnew0(struct ec_adrian, 1); + adrian = pa_xnew0(struct method_adrian, 1); if (!(adrian->aec = AEC_init(ss->rate, 0))) { pa_log_error("Failed to init AEC"); @@ -64,7 +64,7 @@ fail: } int32_t adrian_process(void *priv, int8_t *rec, int8_t *ref, int8_t *out) { - struct ec_adrian *adrian = priv; + struct method_adrian *adrian = priv; int i; assert(rec); @@ -81,7 +81,7 @@ int32_t adrian_process(void *priv, int8_t *rec, int8_t *ref, int8_t *out) { } int32_t adrian_destroy(void *priv) { - struct ec_adrian *adrian = priv; + struct method_adrian *adrian = priv; pa_assert(adrian); diff --git a/src/echo-cancel/algo_reference_copy.c b/src/echo-cancel/method_reference_copy.c similarity index 100% rename from src/echo-cancel/algo_reference_copy.c rename to src/echo-cancel/method_reference_copy.c diff --git a/src/echo-cancel/algo_speex.c b/src/echo-cancel/method_speex.c similarity index 95% rename from src/echo-cancel/algo_speex.c rename to src/echo-cancel/method_speex.c index 161812a..5dd0b5f 100644 --- a/src/echo-cancel/algo_speex.c +++ b/src/echo-cancel/method_speex.c @@ -35,13 +35,13 @@ #include -struct algo_speex { +struct method_speex { SpeexEchoState *echo_state; SpeexPreprocessState *preprocess; }; void *speex_create(size_t nframes, pa_sample_spec *ss) { - struct algo_speex *speex = NULL; + struct method_speex *speex = NULL; spx_int32_t value = 1; int rate; @@ -52,7 +52,7 @@ void *speex_create(size_t nframes, pa_sample_spec *ss) { return NULL; } - speex = pa_xnew0(struct algo_speex, 1); + speex = pa_xnew0(struct method_speex, 1); /* TODO: need to check. weird behavior */ if (ss->channels == 2) @@ -108,7 +108,7 @@ fail: } int32_t speex_process(void *priv, int8_t *rec, int8_t *ref, int8_t *out) { - struct algo_speex *speex = priv; + struct method_speex *speex = priv; assert(rec); assert(ref); @@ -125,7 +125,7 @@ int32_t speex_process(void *priv, int8_t *rec, int8_t *ref, int8_t *out) { } int32_t speex_destroy(void *priv) { - struct algo_speex *speex = priv; + struct method_speex *speex = priv; if (speex->echo_state) speex_echo_state_destroy(speex->echo_state); diff --git a/src/echo-cancel/algo_webrtc.cpp b/src/echo-cancel/method_webrtc.cpp similarity index 93% rename from src/echo-cancel/algo_webrtc.cpp rename to src/echo-cancel/method_webrtc.cpp index 8253820..4b7721c 100644 --- a/src/echo-cancel/algo_webrtc.cpp +++ b/src/echo-cancel/method_webrtc.cpp @@ -41,8 +41,8 @@ PA_C_DECL_BEGIN #include #include -static void allocate_stream_buffer(struct algo_webrtc *webrtc, size_t nframes); -static void deallocate_stream_buffer(struct algo_webrtc *webrtc); +static void allocate_stream_buffer(struct method_webrtc *webrtc, size_t nframes); +static void deallocate_stream_buffer(struct method_webrtc *webrtc); static void convert_s16_to_float(float *dst, int16_t *src, size_t n); static void convert_float_to_s16(int16_t *dst, float *src, size_t n); @@ -51,7 +51,7 @@ int32_t webrtc_audio_process(void *priv, int8_t *rec, int8_t *ref, int8_t *out); int32_t webrtc_audio_destroy(void *priv); PA_C_DECL_END -struct algo_webrtc { +struct method_webrtc { AudioProcessing *ap; Config config; StreamConfig *sconfig; @@ -75,7 +75,7 @@ struct algo_webrtc { }; void *webrtc_audio_create(size_t nframes, pa_sample_spec *ss) { - struct algo_webrtc *webrtc = NULL; + struct method_webrtc *webrtc = NULL; size_t fixed_bytes, request_bytes; Config config; @@ -101,7 +101,7 @@ void *webrtc_audio_create(size_t nframes, pa_sample_spec *ss) { return NULL; } - webrtc = pa_xnew0(struct algo_webrtc, 1); + webrtc = pa_xnew0(struct method_webrtc, 1); webrtc->ss = *ss; webrtc->fixed_bytes = fixed_bytes; webrtc->fixed_frames = fixed_bytes / pa_frame_size(ss); @@ -164,7 +164,7 @@ fail: } int32_t webrtc_audio_process(void *priv, int8_t *rec, int8_t *ref, int8_t *out) { - struct algo_webrtc *webrtc = (struct algo_webrtc *)priv; + struct method_webrtc *webrtc = (struct method_webrtc *)priv; pa_sample_spec ss; size_t frames; @@ -225,7 +225,7 @@ int32_t webrtc_audio_process(void *priv, int8_t *rec, int8_t *ref, int8_t *out) } int32_t webrtc_audio_destroy(void *priv) { - struct algo_webrtc *webrtc = (struct algo_webrtc *)priv; + struct method_webrtc *webrtc = (struct method_webrtc *)priv; pa_assert(webrtc); @@ -238,7 +238,7 @@ int32_t webrtc_audio_destroy(void *priv) { return 0; } -static void deallocate_stream_buffer(struct algo_webrtc *webrtc) { +static void deallocate_stream_buffer(struct method_webrtc *webrtc) { pa_assert(webrtc); for (int i = 0; i < webrtc->ss.channels; i++) { @@ -252,7 +252,7 @@ static void deallocate_stream_buffer(struct algo_webrtc *webrtc) { pa_xfree(webrtc->out_fbuf); } -static void allocate_stream_buffer(struct algo_webrtc *webrtc, size_t nframes) { +static void allocate_stream_buffer(struct method_webrtc *webrtc, size_t nframes) { int channels; pa_assert(webrtc); -- 2.7.4 From 296538390258ece146df572170404b1c35a1095c Mon Sep 17 00:00:00 2001 From: Jaechul Lee Date: Mon, 4 Jul 2022 11:30:59 +0900 Subject: [PATCH 05/16] echo-cancel: Fix coverity issues (PARAMETER_HIDDEN) [Version] 15.0.24 [Issue Type] Coverity Change-Id: Ia5f389a408b7bb97ab379215939d9b910aebb8ee Signed-off-by: Jaechul Lee --- packaging/pulseaudio-modules-tizen.spec | 2 +- src/echo-cancel/module-tizenaudio-echo-cancel.c | 26 ++++++++++++------------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index 2eae259..ad23656 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -2,7 +2,7 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 15.0.22 +Version: 15.0.24 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/echo-cancel/module-tizenaudio-echo-cancel.c b/src/echo-cancel/module-tizenaudio-echo-cancel.c index 7697368..4b6939b 100644 --- a/src/echo-cancel/module-tizenaudio-echo-cancel.c +++ b/src/echo-cancel/module-tizenaudio-echo-cancel.c @@ -295,29 +295,29 @@ static int process_msg( pa_memchunk *chunk) { struct userdata *u = PA_ECHO_CANCEL(o)->u; + pa_source_output *so = NULL; /* trigger resolves a race condition related to post_process between source and render thread */ if (u->triggered) { if (code == PA_ECHO_CANCEL_MESSAGE_PUSH_ECHO) { - pa_source_output *o = NULL; pa_usec_t latency; - o = find_source_output_by_flags(u->source); - if (!o) { + so = find_source_output_by_flags(u->source); + if (!so) { u->triggered = false; return 0; } - o->post_process = post_process; + so->post_process = post_process; latency = get_round_trip_latency(u); - if (pa_processor_setup_reference_memblockq_padding(o->thread_info.processor, latency) < 0) + if (pa_processor_setup_reference_memblockq_padding(so->thread_info.processor, latency) < 0) pa_log_warn("Failed to setup reference memblockq padding"); u->triggered = false; - pa_log_info("Triggered Echo-Cancellation. index(%d), latency(%" PRIu64 ") usec", o->index, latency); + pa_log_info("Triggered Echo-Cancellation. index(%d), latency(%" PRIu64 ") usec", so->index, latency); } } @@ -330,15 +330,13 @@ static int process_msg( break; case PA_ECHO_CANCEL_MESSAGE_PUSH_ECHO: if (u->enable_in_thread) { - pa_source_output *o = NULL; - pa_assert(u->source); - o = find_source_output_by_flags(u->source); - if (!o) + so = find_source_output_by_flags(u->source); + if (!so) break; - if (pa_processor_push_reference(o->thread_info.processor, chunk) < 0) + if (pa_processor_push_reference(so->thread_info.processor, chunk) < 0) pa_log_error("Failed to push reference data"); } @@ -346,15 +344,15 @@ static int process_msg( case PA_ECHO_CANCEL_MESSAGE_SET_AEC_STATE: { void **v = (void **)data; bool enable = (bool)v[0]; - pa_source_output *o = (pa_source_output *)v[1]; + so = (pa_source_output *)v[1]; u->enable_in_thread = enable; if (enable) { u->triggered = true; } else { - pa_processor_flush(o->thread_info.processor); - o->post_process = NULL; + pa_processor_flush(so->thread_info.processor); + so->post_process = NULL; } break; -- 2.7.4 From 64c9859c2af892966f741a6ff24e39bd261fda68 Mon Sep 17 00:00:00 2001 From: Jaechul Lee Date: Mon, 27 Jun 2022 17:41:30 +0900 Subject: [PATCH 06/16] Enable webrtc-audio-processing by default [Version] 15.0.25 [Issue Type] Improvement Change-Id: Icb43727592ce90077ed6badf8481680dccc57ef1 Signed-off-by: Jaechul Lee --- Makefile.am | 3 ++ packaging/pulseaudio-modules-tizen.spec | 8 ++++- src/echo-cancel/module-tizenaudio-echo-cancel.c | 29 +++++++++++------- src/echo-cancel/processor.c | 39 ++++++++++++------------- src/echo-cancel/processor.h | 7 ++++- 5 files changed, 53 insertions(+), 33 deletions(-) diff --git a/Makefile.am b/Makefile.am index cd71bb1..3723d0a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -119,6 +119,9 @@ module_tizenaudio_echo_cancel_la_SOURCES = src/echo-cancel/module-tizenaudio-ech module_tizenaudio_echo_cancel_la_LDFLAGS = $(MODULE_LDFLAGS) module_tizenaudio_echo_cancel_la_LIBADD = $(MODULE_LIBADD) libprocessor.la module_tizenaudio_echo_cancel_la_CFLAGS = $(MODULE_CFLAGS) -DPA_MODULE_NAME=module_tizenaudio_echo_cancel +if ENABLE_WEBRTC +module_tizenaudio_echo_cancel_la_CFLAGS += -DSUPPORT_METHOD_WEBRTC +endif module_sound_player_la_SOURCES = src/module-sound-player.c module_sound_player_la_LDFLAGS = $(MODULE_LDFLAGS) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index ad23656..48a97c9 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -2,7 +2,7 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 15.0.24 +Version: 15.0.25 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ @@ -24,6 +24,9 @@ BuildRequires: pkgconfig(libsystemd) BuildRequires: pkgconfig(dns_sd) BuildRequires: pkgconfig(hal-api-audio) BuildRequires: pkgconfig(speexdsp) +%if "%{tizen_profile_name}" != "tv" +BuildRequires: pkgconfig(webrtc-audio-processing) +%endif BuildRequires: pulseaudio BuildRequires: m4 Requires(post): /sbin/ldconfig @@ -52,6 +55,9 @@ export LD_AS_NEEDED=0 %reconfigure --prefix=%{_prefix} \ --disable-static \ --enable-acm \ +%if "%{tizen_profile_name}" != "tv" + --enable-webrtc \ +%endif %if "%{tizen_profile_name}" == "tv" --enable-vconf-helper %endif diff --git a/src/echo-cancel/module-tizenaudio-echo-cancel.c b/src/echo-cancel/module-tizenaudio-echo-cancel.c index 4b6939b..3442009 100644 --- a/src/echo-cancel/module-tizenaudio-echo-cancel.c +++ b/src/echo-cancel/module-tizenaudio-echo-cancel.c @@ -46,7 +46,7 @@ PA_MODULE_DESCRIPTION("Tizen Audio Echo Cancel"); PA_MODULE_VERSION(PACKAGE_VERSION); PA_MODULE_LOAD_ONCE(true); PA_MODULE_USAGE( - "method= "); + "method= "); #define DEFAULT_PROCESS_MSEC 10 @@ -69,7 +69,7 @@ struct userdata { bool enable; uint32_t n_source_output; - char *default_method; + char *force_method; pa_thread *thread; pa_thread_mq thread_mq; @@ -93,7 +93,6 @@ PA_DEFINE_PRIVATE_CLASS(pa_echo_cancel, pa_msgobject); #define PA_ECHO_CANCEL(o) (pa_echo_cancel_cast(o)) #define MEMBLOCKQ_MAXLENGTH (16 * 1024 * 1024) -#define DEFAULT_AEC_METHOD "speex" static const char* const valid_modargs[] = { "method", @@ -119,7 +118,7 @@ static int proplist_get_fragment_size_usec(pa_proplist *p, pa_sample_spec *sampl return 0; } -static int proplist_get_method(pa_proplist *p, const char *default_method, pa_processor_method_t *method) { +static int proplist_get_method(pa_proplist *p, pa_processor_method_t *method) { const char *m; pa_assert(p); @@ -128,7 +127,7 @@ static int proplist_get_method(pa_proplist *p, const char *default_method, pa_pr if (!(m = pa_proplist_gets(p, PA_PROP_MEDIA_ECHO_CANCEL_METHOD))) return -1; - *method = pa_processor_get_method(m, default_method); + *method = pa_processor_get_method(m); return 0; } @@ -367,14 +366,17 @@ static int process_msg( static pa_hook_result_t source_output_new_cb(pa_core *c, pa_source_output_new_data *data, void *userdata) { struct userdata *u = (struct userdata *)userdata; pa_processor_method_t method; + const char *m; pa_assert(c); pa_assert(u); pa_assert(data); - if (proplist_get_method(data->proplist, u->default_method, &method) < 0) + if (!(m = pa_proplist_gets(data->proplist, PA_PROP_MEDIA_ECHO_CANCEL_METHOD))) return PA_HOOK_OK; + method = pa_processor_get_method(m); + /* TODO: source-output can be moved */ data->flags |= PA_SOURCE_OUTPUT_DONT_MOVE; data->flags |= PA_SOURCE_OUTPUT_ECHO_CANCEL; @@ -432,9 +434,13 @@ static pa_hook_result_t source_output_put_cb(pa_core *c, pa_source_output *o, vo goto fail; } - if (proplist_get_method(o->proplist, u->default_method, &method) < 0) { - pa_log_error("Failed to get method"); - goto fail; + if (u->force_method) { + method = pa_processor_get_method(u->force_method); + } else { + if (proplist_get_method(o->proplist, &method) < 0) { + pa_log_error("Failed to get method"); + goto fail; + } } u->source = o->source; @@ -624,7 +630,7 @@ int pa__init(pa_module *m) { m->userdata = u = pa_xnew0(struct userdata, 1); u->core = m->core; u->m = m; - u->default_method = pa_xstrdup(pa_modargs_get_value(ma, "method", DEFAULT_AEC_METHOD)); + u->force_method = pa_xstrdup(pa_modargs_get_value(ma, "method", NULL)); u->echo_cancel = pa_msgobject_new(pa_echo_cancel); u->echo_cancel->parent.process_msg = process_msg; @@ -741,7 +747,8 @@ void pa__done(pa_module *m) { pa_thread_mq_done(&u->thread_mq); - pa_xfree(u->default_method); + pa_xfree(u->force_method); + pa_xfree(u); } diff --git a/src/echo-cancel/processor.c b/src/echo-cancel/processor.c index dbce5fa..c77f088 100644 --- a/src/echo-cancel/processor.c +++ b/src/echo-cancel/processor.c @@ -471,33 +471,32 @@ int pa_processor_free(pa_processor *processor) { return 0; } -pa_processor_method_t pa_processor_get_method(const char *request_method, const char *default_method) { - const char *selected; +const char *pa_processor_method_to_string(pa_processor_method_t method) { + if (method >= PA_PROCESSOR_METHOD_MAX) + return NULL; - if (!request_method || !default_method) - return PA_PROCESSOR_SPEEX; + return method_table[method].name; +} - selected = pa_streq(request_method, "default") ? default_method : request_method; +pa_processor_method_t pa_processor_get_method(const char *request_method) { + pa_processor_method_t method; - if (pa_streq(selected, "speex")) - return PA_PROCESSOR_SPEEX; - else if (pa_streq(selected, "adrian")) - return PA_PROCESSOR_ADRIAN; + if (pa_streq(request_method, "speex")) + method = PA_PROCESSOR_SPEEX; + else if (pa_streq(request_method, "adrian")) + method = PA_PROCESSOR_ADRIAN; #ifdef SUPPORT_METHOD_WEBRTC - else if (pa_streq(selected, "webrtc")) - return PA_PROCESSOR_WEBRTC; + else if (pa_streq(request_method, "webrtc")) + method = PA_PROCESSOR_WEBRTC; #endif - else if (pa_streq(selected, "reference_copy")) - return PA_PROCESSOR_REFERENCE_COPY; + else if (pa_streq(request_method, "reference_copy")) + method = PA_PROCESSOR_REFERENCE_COPY; else - return PA_PROCESSOR_SPEEX; -} - -const char *pa_processor_method_to_string(pa_processor_method_t method) { - if (method >= PA_PROCESSOR_METHOD_MAX) - return NULL; + /* request_method could be had 'default' */ + method = PA_PROCESSOR_METHOD_DEFAULT; - return method_table[method].name; + pa_log_info("processing method is selected. request_method(%s), method_to_string(%s)", + request_method, pa_processor_method_to_string(method)); } #ifdef __DEBUG__ diff --git a/src/echo-cancel/processor.h b/src/echo-cancel/processor.h index ea07143..ea14a69 100644 --- a/src/echo-cancel/processor.h +++ b/src/echo-cancel/processor.h @@ -38,6 +38,11 @@ typedef enum { PA_PROCESSOR_WEBRTC, #endif PA_PROCESSOR_REFERENCE_COPY, +#ifdef SUPPORT_METHOD_WEBRTC + PA_PROCESSOR_METHOD_DEFAULT = PA_PROCESSOR_WEBRTC, +#else + PA_PROCESSOR_METHOD_DEFAULT = PA_PROCESSOR_SPEEX, +#endif PA_PROCESSOR_METHOD_MAX, } pa_processor_method_t; @@ -58,7 +63,7 @@ int pa_processor_process(pa_processor *processor, pa_memchunk *rec, pa_memchunk int pa_processor_push_reference(pa_processor *processor, pa_memchunk *chunk); void pa_processor_flush(pa_processor *processor); int pa_processor_free(pa_processor *processor); -pa_processor_method_t pa_processor_get_method(const char *requset_method, const char *default_method); +pa_processor_method_t pa_processor_get_method(const char *requset_method); const char *pa_processor_method_to_string(pa_processor_method_t method); #endif -- 2.7.4 From 9f6d318c9732681b3c98d03fb523872dc4928c73 Mon Sep 17 00:00:00 2001 From: Jaechul Lee Date: Mon, 18 Jul 2022 13:46:15 +0900 Subject: [PATCH 07/16] fixup! Enable webrtc-audio-processing by default [Version] 15.0.26 [Issue Type] Bug Change-Id: I683f8ca264196f01107f4713129e21ab233650ca --- packaging/pulseaudio-modules-tizen.spec | 2 +- src/echo-cancel/processor.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index 48a97c9..71b55b2 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -2,7 +2,7 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 15.0.25 +Version: 15.0.26 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/echo-cancel/processor.c b/src/echo-cancel/processor.c index c77f088..8dc6c2d 100644 --- a/src/echo-cancel/processor.c +++ b/src/echo-cancel/processor.c @@ -497,6 +497,8 @@ pa_processor_method_t pa_processor_get_method(const char *request_method) { pa_log_info("processing method is selected. request_method(%s), method_to_string(%s)", request_method, pa_processor_method_to_string(method)); + + return method; } #ifdef __DEBUG__ -- 2.7.4 From 83cceff1a8e745080a28d0b5de31ac436e45086b Mon Sep 17 00:00:00 2001 From: Seungbae Shin Date: Mon, 8 Aug 2022 17:27:01 +0900 Subject: [PATCH 08/16] fixup! fixup! Enable webrtc-audio-processing by default Fix the following crash error due to invalid enumeration value. processor.c: pa_processor_get_method(498) > processing method is selected. request_method(reference_copy), method_to_string((null)) processor.c: pa_processor_new(169) > Assertion 'method < PA_PROCESSOR_METHOD_MAX' failed at src/echo-cancel/processor.c:169, function pa_processor_new(). Aborting. [Version] 15.0.27 [Issue Type] Bug Change-Id: I331fbea04be4a2d0471b916082f3da298c31a851 --- packaging/pulseaudio-modules-tizen.spec | 2 +- src/echo-cancel/processor.h | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index 71b55b2..48aacf5 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -2,7 +2,7 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 15.0.26 +Version: 15.0.27 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/echo-cancel/processor.h b/src/echo-cancel/processor.h index ea14a69..625bb25 100644 --- a/src/echo-cancel/processor.h +++ b/src/echo-cancel/processor.h @@ -32,13 +32,11 @@ #include typedef enum { - PA_PROCESSOR_SPEEX, PA_PROCESSOR_ADRIAN, -#ifdef SUPPORT_METHOD_WEBRTC - PA_PROCESSOR_WEBRTC, -#endif PA_PROCESSOR_REFERENCE_COPY, + PA_PROCESSOR_SPEEX, #ifdef SUPPORT_METHOD_WEBRTC + PA_PROCESSOR_WEBRTC, PA_PROCESSOR_METHOD_DEFAULT = PA_PROCESSOR_WEBRTC, #else PA_PROCESSOR_METHOD_DEFAULT = PA_PROCESSOR_SPEEX, -- 2.7.4 From fd5c3fa79d103624c2d8c241e1ed72e0dda4267e Mon Sep 17 00:00:00 2001 From: Jaechul Lee Date: Tue, 16 Aug 2022 16:45:25 +0900 Subject: [PATCH 09/16] Fix mismatching between enum and method_table enums should be matched to method_table because the enum is used as an index. [Version] 15.0.28 [Issue Type] Bug Change-Id: I55b3e001ff035ca1983b96efcea3c8e4728f513a Signed-off-by: Jaechul Lee --- packaging/pulseaudio-modules-tizen.spec | 2 +- src/echo-cancel/processor.c | 11 +++++++---- src/echo-cancel/processor.h | 8 +++----- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index 48aacf5..b8c2e8a 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -2,7 +2,7 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 15.0.27 +Version: 15.0.28 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/echo-cancel/processor.c b/src/echo-cancel/processor.c index 8dc6c2d..6670955 100644 --- a/src/echo-cancel/processor.c +++ b/src/echo-cancel/processor.c @@ -492,11 +492,14 @@ pa_processor_method_t pa_processor_get_method(const char *request_method) { else if (pa_streq(request_method, "reference_copy")) method = PA_PROCESSOR_REFERENCE_COPY; else - /* request_method could be had 'default' */ - method = PA_PROCESSOR_METHOD_DEFAULT; +#ifdef SUPPORT_METHOD_WEBRTC + method = PA_PROCESSOR_WEBRTC; +#else + method = PA_PROCESSOR_SPEEX; +#endif - pa_log_info("processing method is selected. request_method(%s), method_to_string(%s)", - request_method, pa_processor_method_to_string(method)); + pa_log_info("processing method is selected. method(%d), request_method(%s), method_to_string(%s)", + method, request_method, pa_processor_method_to_string(method)); return method; } diff --git a/src/echo-cancel/processor.h b/src/echo-cancel/processor.h index 625bb25..3e81c22 100644 --- a/src/echo-cancel/processor.h +++ b/src/echo-cancel/processor.h @@ -31,16 +31,14 @@ #include #include +/* These are used as an index to choose a method in method_table. Keep this order */ typedef enum { - PA_PROCESSOR_ADRIAN, - PA_PROCESSOR_REFERENCE_COPY, PA_PROCESSOR_SPEEX, + PA_PROCESSOR_ADRIAN, #ifdef SUPPORT_METHOD_WEBRTC PA_PROCESSOR_WEBRTC, - PA_PROCESSOR_METHOD_DEFAULT = PA_PROCESSOR_WEBRTC, -#else - PA_PROCESSOR_METHOD_DEFAULT = PA_PROCESSOR_SPEEX, #endif + PA_PROCESSOR_REFERENCE_COPY, PA_PROCESSOR_METHOD_MAX, } pa_processor_method_t; -- 2.7.4 From 7152c5ee3556866a2f3b644b5c9a0531742174f2 Mon Sep 17 00:00:00 2001 From: Seungbae Shin Date: Wed, 28 Sep 2022 13:35:46 +0900 Subject: [PATCH 10/16] sound-player: stop all other existence sound playbacks if requested [Version] 15.0.29 [Issue Type] Feature Change-Id: Ife2480f0afc993165186e6f7b1cd04dbe16539fe --- packaging/pulseaudio-modules-tizen.spec | 2 +- src/module-sound-player.c | 35 +++++++++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index b8c2e8a..e29fb34 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -2,7 +2,7 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 15.0.28 +Version: 15.0.29 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/module-sound-player.c b/src/module-sound-player.c index cf55d04..229501d 100644 --- a/src/module-sound-player.c +++ b/src/module-sound-player.c @@ -103,9 +103,10 @@ static pa_dbus_arg_info sound_play_args[] = { { "filename", "s", "in" }, { "repeat", "i", "in" }, { "client_pid", "i", "in" }, { "role", "s", "in" }, - { "parent_id", "i", "in" } }; + { "parent_id", "i", "in" }, + { "stop_others", "b", "in" } }; static pa_dbus_arg_info sound_stop_args[] = { { "stream_idx", "i", "in" } }; -static const char* signature_args_for_in[] = { "sss", "s", NULL, "sss", "siisi", "i" }; +static const char* signature_args_for_in[] = { "sss", "s", NULL, "sss", "siisib", "i" }; static pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = { [METHOD_HANDLER_SIMPLE_PLAY] = { @@ -179,6 +180,7 @@ static pa_dbus_interface_info sound_player_interface_info = { " " \ " " \ " " \ + " " \ " " \ " " \ " " \ @@ -316,6 +318,27 @@ static void _simple_stop_all(struct userdata *u) { } } +static void _sound_stop_all(struct userdata *u) { + pa_sink_input *si; + uint32_t idx; + int32_t *stream_idx; + + pa_assert(u); + + PA_IDXSET_FOREACH(stream_idx, u->stream_idxs, idx) { + pa_assert(stream_idx); + + si = pa_idxset_get_by_index(u->module->core->sink_inputs, *stream_idx); + if (!si) { + pa_log_warn("null sink input for stream idx(%d)", *stream_idx); + continue; + } + + pa_log_info("killing sink-input(%d), stream_idx(%d)", si->index, *stream_idx); + pa_sink_input_kill(si); + } +} + static int _sample_play(struct userdata *u, const char *sample_name, const char *role, const char *vol_gain_type) { int ret = 0; pa_sink *sink = NULL; @@ -474,6 +497,7 @@ static void handle_sound_play(DBusConnection *conn, DBusMessage *msg, void *user const char *role; uint32_t parent_id; uint32_t stream_idx; + dbus_bool_t stop_others = false; pa_proplist *p; pa_assert_se(dbus_message_get_args(msg, NULL, @@ -482,8 +506,15 @@ static void handle_sound_play(DBusConnection *conn, DBusMessage *msg, void *user DBUS_TYPE_INT32, &client_pid, DBUS_TYPE_STRING, &role, DBUS_TYPE_INT32, &parent_id, + DBUS_TYPE_BOOLEAN, &stop_others, DBUS_TYPE_INVALID)); + if (stop_others) { + pa_log_info("stop_others enabled, stop all other sounds"); + _sound_stop_all(u); + pa_log_info("stop done, ready to play the requested one"); + } + p = pa_proplist_new(); pa_proplist_sets(p, PA_PROP_MEDIA_ROLE, role); pa_proplist_setf(p, PA_PROP_APPLICATION_PROCESS_ID_ORIGIN, "%d", client_pid); -- 2.7.4 From 50300148eeb4274d3f99dd9ed8f06a53d53b7f1d Mon Sep 17 00:00:00 2001 From: Seungbae Shin Date: Thu, 6 Oct 2022 20:38:53 +0900 Subject: [PATCH 11/16] tizen-device: add sample spec and return it for connected device list [Version] 15.0.30 [Issue Type] Feature Change-Id: I6a541a0d71f2924e778989c999a67b7b7310bf0f --- packaging/pulseaudio-modules-tizen.spec | 2 +- src/device-manager-dbus.c | 24 +++++++++++++++++------ src/tizen-device.c | 34 ++++++++++++++++++++++----------- src/tizen-device.h | 4 ++++ 4 files changed, 46 insertions(+), 18 deletions(-) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index e29fb34..aad852b 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -2,7 +2,7 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 15.0.29 +Version: 15.0.30 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/device-manager-dbus.c b/src/device-manager-dbus.c index 7752ce6..c5ae84c 100644 --- a/src/device-manager-dbus.c +++ b/src/device-manager-dbus.c @@ -64,7 +64,7 @@ " \n" \ " \n" \ " \n" \ - " \n" \ + " \n" \ " \n" \ " \n" \ " \n" \ @@ -698,6 +698,8 @@ static void array_iter_append(DBusMessageIter *array_iter, pa_idxset *device_lis dbus_bool_t is_running; pa_tz_device *device; DBusMessageIter device_iter; + const pa_sample_spec *spec = NULL; + dbus_int32_t format, samplerate, channels; pa_assert(array_iter); @@ -710,10 +712,16 @@ static void array_iter_append(DBusMessageIter *array_iter, pa_idxset *device_lis direction = pa_tz_device_get_direction(device); type = pa_tz_device_get_type(device); name = pa_tz_device_get_name(device); - vendor_id = (dbus_int32_t) pa_tz_device_get_vendor_id(device); - product_id = (dbus_int32_t) pa_tz_device_get_product_id(device); - product_id = (dbus_int32_t) pa_tz_device_get_product_id(device); - is_running = (dbus_bool_t) pa_tz_device_is_running(device); + vendor_id = (dbus_int32_t)pa_tz_device_get_vendor_id(device); + product_id = (dbus_int32_t)pa_tz_device_get_product_id(device); + product_id = (dbus_int32_t)pa_tz_device_get_product_id(device); + is_running = (dbus_bool_t)pa_tz_device_is_running(device); + + spec = pa_tz_device_get_sample_spec(device); + format = (dbus_int32_t)spec->format; + samplerate = (dbus_int32_t)spec->rate; + channels = (dbus_int32_t)spec->channels; + if (device_is_match_with_mask(device, mask)) { simple_device_dump(PA_LOG_INFO, "[MATCH]", device_id, type, name, direction, state); pa_assert_se(dbus_message_iter_open_container(array_iter, DBUS_TYPE_STRUCT, NULL, &device_iter)); @@ -725,6 +733,10 @@ static void array_iter_append(DBusMessageIter *array_iter, pa_idxset *device_lis dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &vendor_id); dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &product_id); dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_BOOLEAN, &is_running); + dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &format); + dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &samplerate); + dbus_message_iter_append_basic(&device_iter, DBUS_TYPE_INT32, &channels); + pa_assert_se(dbus_message_iter_close_container(array_iter, &device_iter)); } else { simple_device_dump(PA_LOG_INFO, "[UNMATCH]", device_id, type, name, direction, state); @@ -774,7 +786,7 @@ static void handle_get_connected_device_list(DBusConnection *conn, DBusMessage * pa_log_info("Get connected device list (mask : %d)", mask); dbus_message_iter_init_append(reply, &msg_iter); - pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "(isiisiib)", &array_iter)); + pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "(isiisiibiii)", &array_iter)); #ifndef __TIZEN_TV_EXTERNAL_BT_SCO__ array_iter_append(&array_iter, dm->device_list, mask); diff --git a/src/tizen-device.c b/src/tizen-device.c index 0f8a481..b40503a 100644 --- a/src/tizen-device.c +++ b/src/tizen-device.c @@ -462,6 +462,8 @@ pa_tz_device* pa_tz_device_new(pa_tz_device_new_data *data) { pa_sink *sink; pa_source *source; + char spec_str[PA_SAMPLE_SPEC_SNPRINT_MAX] = { 0, }; + pa_assert(data); if (_check_valid_device_new_data(data) < 0) { @@ -469,25 +471,19 @@ pa_tz_device* pa_tz_device_new(pa_tz_device_new_data *data) { return NULL; } - device = pa_xmalloc(sizeof(pa_tz_device)); + device = pa_xmalloc0(sizeof(pa_tz_device)); + device->list = data->list; device->comm = data->comm; device->dbus_conn = data->dbus_conn; device->id = device_id_max_g++; device->type = pa_xstrdup(data->type); - if (data->name) - device->name = pa_xstrdup(data->name); - else - device->name = pa_xstrdup(data->type); + device->name = pa_xstrdup(data->name ? data->name : data->type); device->system_id = pa_xstrdup(data->system_id); device->vendor_id = data->vendor_id; device->product_id = data->product_id; - pa_log_info("New device type(%s) id(%u) name(%s) system_id(%s) vendor_id(%04x) product_id(%04x)", - device->type, device->id, device->name, pa_strempty(device->system_id), - device->vendor_id, device->product_id); - device->playback_devices = data->playback_pcms; device->capture_devices = data->capture_pcms; device->direction = data->direction; @@ -500,12 +496,22 @@ pa_tz_device* pa_tz_device_new(pa_tz_device_new_data *data) { device->is_running = false; device->specified_stream_role = pa_xstrdup("none"); - if ((sink = device_get_sink(device, NULL))) + if ((sink = device_get_sink(device, NULL))) { sink->device_item = device; - if ((source = device_get_source(device, NULL))) + device->sample_spec = &sink->sample_spec; + } + if ((source = device_get_source(device, NULL))) { source->device_item = device; + device->sample_spec = &source->sample_spec; + } + pa_sample_spec_snprint(spec_str, sizeof(spec_str), device->sample_spec); + + pa_log_info("New device: type(%s) spec(%s) id(%u) name(%s) system_id(%s) vendor_id(%04x) product_id(%04x)", + device->type, spec_str, device->id, device->name, + pa_strempty(device->system_id), device->vendor_id, device->product_id); pa_idxset_put(device->list, device, NULL); + notify_device_connection_changed(device, true); pa_tz_device_dump_info(device, PA_LOG_INFO); @@ -780,6 +786,12 @@ bool pa_tz_device_is_use_internal_codec(pa_tz_device *device) { return device->use_internal_codec; } +const pa_sample_spec* pa_tz_device_get_sample_spec(pa_tz_device *device) { + pa_assert(device); + + return device->sample_spec; +} + bool pa_tz_device_is_all_suspended(pa_tz_device *device) { pa_sink *sink; pa_source *source; diff --git a/src/tizen-device.h b/src/tizen-device.h index a809eed..1d22ea0 100644 --- a/src/tizen-device.h +++ b/src/tizen-device.h @@ -64,6 +64,9 @@ struct pa_tz_device { bool sco_opened; #endif + /* mirrors to the corresponding sink/source sample spec */ + const pa_sample_spec *sample_spec; + /* Devices are contained in this list */ pa_idxset *list; @@ -152,6 +155,7 @@ char* pa_tz_device_get_system_id(pa_tz_device *device); dm_device_direction_t pa_tz_device_get_direction(pa_tz_device *device); pa_usec_t pa_tz_device_get_creation_time(pa_tz_device *device); bool pa_tz_device_is_use_internal_codec(pa_tz_device *device); +const pa_sample_spec* pa_tz_device_get_sample_spec(pa_tz_device *device); bool pa_tz_device_is_all_suspended(pa_tz_device *device); pa_intset* pa_tz_device_get_stream_list(pa_tz_device *device); -- 2.7.4 From 976df3474893103e0243e2029af8abaf1e29fcd5 Mon Sep 17 00:00:00 2001 From: Seungbae Shin Date: Thu, 20 Oct 2022 19:42:36 +0900 Subject: [PATCH 12/16] ladspa/acm: fix svace defects Checker: SEC_DO_NOT_USE_INT_IN_FOR_LOOP SEC_DO_NOT_ASSIGN_SIZE_OF_INT [Version] 15.0.31 [Issue Type] Svace Change-Id: Idfe703452c983f3cd5f49c3a6c7a6ad6ae8a6720 --- packaging/pulseaudio-modules-tizen.spec | 2 +- src/acm.c | 5 ++--- src/ladspa/delay.c | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index aad852b..89d8757 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -2,7 +2,7 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 15.0.30 +Version: 15.0.31 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/acm.c b/src/acm.c index 7f697c2..57deaf2 100644 --- a/src/acm.c +++ b/src/acm.c @@ -226,7 +226,7 @@ typedef enum { static int ipc_get_client_fd(struct userdata *u, ipc_channel_t channel) { struct sockaddr_un address; - int len, ret = IPC_ERR; + int ret = IPC_ERR; int sockfd; int n_opt_val; unsigned int n_opt_len = sizeof (n_opt_val); @@ -281,9 +281,8 @@ static int ipc_get_client_fd(struct userdata *u, ipc_channel_t channel) memset(&address, 0, sizeof(address)); address.sun_family = AF_UNIX; strncpy(address.sun_path, socket_path, sizeof(address.sun_path) - 1); - len = sizeof(address); - if ((ret = connect(sockfd, (struct sockaddr *)&address, len)) < 0) { + if ((ret = connect(sockfd, (struct sockaddr *)&address, (socklen_t)sizeof(address))) < 0) { pa_log_error("connect failure: %s, path: %s", pa_cstrerror(errno), socket_path); close(sockfd); return -1; diff --git a/src/ladspa/delay.c b/src/ladspa/delay.c index 76eb832..365fb1b 100644 --- a/src/ladspa/delay.c +++ b/src/ladspa/delay.c @@ -336,7 +336,7 @@ _init() { /* _fini() is called automatically when the library is unloaded. */ void _fini() { - long lIndex; + unsigned long lIndex; if (g_psDescriptor) { free((char *)g_psDescriptor->Label); free((char *)g_psDescriptor->Name); -- 2.7.4 From 1d4fd118c0eddbe7a1da1831f7190a94b9b81608 Mon Sep 17 00:00:00 2001 From: Jaechul Lee Date: Fri, 21 Oct 2022 11:55:55 +0900 Subject: [PATCH 13/16] tizen-sink/source: fix svace defects This commit fixes warnings as follows NO_CAST.INTEGER_OVERFLOW SEC_INVALID_ASSIGNMENT_WITH_UNSIGNED_VALUES [Version] 15.0.32 [Issue Type] Svace Change-Id: I901662abb6efdc5171d58d4042e5e4140a69c1d0 Signed-off-by: Jaechul Lee --- packaging/pulseaudio-modules-tizen.spec | 2 +- src/module-tizenaudio-sink.c | 2 +- src/module-tizenaudio-source.c | 2 +- src/tizenaudio-sink2.c | 4 ++-- src/tizenaudio-source2.c | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index 89d8757..d24a56e 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -2,7 +2,7 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 15.0.31 +Version: 15.0.32 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/module-tizenaudio-sink.c b/src/module-tizenaudio-sink.c index bb86007..187ebf1 100644 --- a/src/module-tizenaudio-sink.c +++ b/src/module-tizenaudio-sink.c @@ -635,7 +635,7 @@ int pa__init(pa_module*m) { pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "tizen"); frame_size = pa_frame_size(&ss); - buffer_size = u->frag_size * u->nfrags; + 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); diff --git a/src/module-tizenaudio-source.c b/src/module-tizenaudio-source.c index 746eb74..618c803 100644 --- a/src/module-tizenaudio-source.c +++ b/src/module-tizenaudio-source.c @@ -536,7 +536,7 @@ int pa__init(pa_module*m) { pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "tizen"); frame_size = pa_frame_size(&ss); - buffer_size = u->frag_size * u->nfrags; + 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); diff --git a/src/tizenaudio-sink2.c b/src/tizenaudio-sink2.c index f8601ac..9741901 100644 --- a/src/tizenaudio-sink2.c +++ b/src/tizenaudio-sink2.c @@ -459,7 +459,7 @@ pa_sink *pa_tizenaudio_sink2_new(pa_module *m, param.direction = DIRECTION_OUT; param.ss = ss; - param.period_size = u->frag_size / pa_frame_size(&ss); + param.period_size = (uint32_t)(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)", @@ -504,7 +504,7 @@ pa_sink *pa_tizenaudio_sink2_new(pa_module *m, } frame_size = pa_frame_size(¶m.ss); - u->frag_size = period_size * frame_size; + u->frag_size = (uint32_t)(period_size * frame_size); /* TODO: can't trust periods value from hal */ u->nfrags = param.periods; diff --git a/src/tizenaudio-source2.c b/src/tizenaudio-source2.c index 948e8f0..41bc90e 100644 --- a/src/tizenaudio-source2.c +++ b/src/tizenaudio-source2.c @@ -461,7 +461,7 @@ pa_source *pa_tizenaudio_source2_new(pa_module *m, param.direction = DIRECTION_IN; param.ss = ss; - param.period_size = u->frag_size / pa_frame_size(&ss); + param.period_size = (uint32_t)(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)", @@ -506,7 +506,7 @@ pa_source *pa_tizenaudio_source2_new(pa_module *m, } frame_size = pa_frame_size(¶m.ss); - u->frag_size = period_size * frame_size; + u->frag_size = (uint32_t)(period_size * frame_size); /* TODO: can't trust periods value from hal */ u->nfrags = param.periods; -- 2.7.4 From 41ce36150a27aa5bae9fb6844229bd5f50b2d13a Mon Sep 17 00:00:00 2001 From: Seungbae Shin Date: Tue, 25 Oct 2022 21:29:40 +0900 Subject: [PATCH 14/16] sound-player: support fd-passing for supporting container playback [Version] 15.0.33 [Issue Type] Feature Change-Id: I34f8c474a9ac9e5d882d4616bd9de9d1e49ab5a8 --- packaging/pulseaudio-modules-tizen.spec | 2 +- src/module-sound-player.c | 13 ++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index d24a56e..74c31ae 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -2,7 +2,7 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 15.0.32 +Version: 15.0.33 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/module-sound-player.c b/src/module-sound-player.c index 229501d..5773c47 100644 --- a/src/module-sound-player.c +++ b/src/module-sound-player.c @@ -104,9 +104,10 @@ static pa_dbus_arg_info sound_play_args[] = { { "filename", "s", "in" }, { "client_pid", "i", "in" }, { "role", "s", "in" }, { "parent_id", "i", "in" }, - { "stop_others", "b", "in" } }; + { "stop_others", "b", "in" }, + { "fd", "h", "in" }}; static pa_dbus_arg_info sound_stop_args[] = { { "stream_idx", "i", "in" } }; -static const char* signature_args_for_in[] = { "sss", "s", NULL, "sss", "siisib", "i" }; +static const char* signature_args_for_in[] = { "sss", "s", NULL, "sss", "siisibh", "i" }; static pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = { [METHOD_HANDLER_SIMPLE_PLAY] = { @@ -181,6 +182,7 @@ static pa_dbus_interface_info sound_player_interface_info = { " " \ " " \ " " \ + " " \ " " \ " " \ " " \ @@ -499,6 +501,7 @@ static void handle_sound_play(DBusConnection *conn, DBusMessage *msg, void *user uint32_t stream_idx; dbus_bool_t stop_others = false; pa_proplist *p; + int fd = -1; pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &filename, @@ -507,6 +510,7 @@ static void handle_sound_play(DBusConnection *conn, DBusMessage *msg, void *user DBUS_TYPE_STRING, &role, DBUS_TYPE_INT32, &parent_id, DBUS_TYPE_BOOLEAN, &stop_others, + DBUS_TYPE_UNIX_FD, &fd, DBUS_TYPE_INVALID)); if (stop_others) { @@ -515,13 +519,16 @@ static void handle_sound_play(DBusConnection *conn, DBusMessage *msg, void *user pa_log_info("stop done, ready to play the requested one"); } + pa_log_info("message contains unix fds(%s), received fd(%d)", + pa_yes_no(dbus_message_contains_unix_fds(msg)), fd); + p = pa_proplist_new(); pa_proplist_sets(p, PA_PROP_MEDIA_ROLE, role); pa_proplist_setf(p, PA_PROP_APPLICATION_PROCESS_ID_ORIGIN, "%d", client_pid); pa_proplist_setf(p, PA_PROP_MEDIA_PARENT_ID, "%d", parent_id); ret = pa_play_file_repeat(pa_namereg_get(u->module->core, NULL, PA_NAMEREG_SINK), - filename, NULL, p, repeat, &stream_idx); + filename, NULL, p, repeat, fd, &stream_idx); if (ret != 0) { pa_dbus_send_error(conn, msg, DBUS_ERROR_NOT_SUPPORTED, "%s", "org.tizen.multimedia.audio.UnsupportedMediaType"); -- 2.7.4 From 5815465df9ee4782c009b2dbfd7bee9df56fe3f9 Mon Sep 17 00:00:00 2001 From: Seungbae Shin Date: Tue, 13 Dec 2022 17:59:44 +0900 Subject: [PATCH 15/16] device-manager: update hdmi device management mechanism This update is based on the latest RPI kernel, the related obsolete hdmi handling code is now removed. [Version] 15.0.34 [Issue Type] Update Change-Id: I994fb43982c394cfa600219f51cd259a9b14e27f --- packaging/pulseaudio-modules-tizen.spec | 2 +- src/device-manager-dbus.c | 17 -------- src/device-manager-priv.h | 6 --- src/device-manager.c | 70 ++++++++++++++++++++++++++++++++- 4 files changed, 69 insertions(+), 26 deletions(-) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index 74c31ae..be642d8 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -2,7 +2,7 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 15.0.33 +Version: 15.0.34 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/device-manager-dbus.c b/src/device-manager-dbus.c index c5ae84c..6b52c1b 100644 --- a/src/device-manager-dbus.c +++ b/src/device-manager-dbus.c @@ -407,13 +407,6 @@ static int _translate_external_value(const char *type, int value, device_detecte *detected = DEVICE_CONNECTED_AUDIO_JACK_4P; else return -1; - } else if (device_type_is_equal(DEVICE_TYPE_HDMI, type)) { - if (value == HDMI_AUDIO_DISCONNECTED) - *detected = DEVICE_DISCONNECTED; - else if (value == HDMI_AUDIO_AVAILABLE) - *detected = DEVICE_CONNECTED; - else - return -1; } else if (device_type_is_equal(DEVICE_TYPE_FORWARDING, type)) { if (value == FORWARDING_DISCONNECTED) *detected = DEVICE_DISCONNECTED; @@ -535,16 +528,6 @@ static DBusHandlerResult dbus_filter_device_detect_handler(DBusConnection *c, DB } handle_device_status_changed(dm, DEVICE_TYPE_AUDIO_JACK, NULL, NULL, detected); - } else if (dbus_message_is_signal(s, DBUS_INTERFACE_DEVICED_SYSNOTI, "ChangedHDMIAudio")) { - if (!dbus_message_get_args(s, NULL, DBUS_TYPE_INT32, &status, DBUS_TYPE_INVALID)) - goto fail; - - if (_translate_external_value(DEVICE_TYPE_HDMI, status, &detected) < 0) { - pa_log_warn("failed to translate HDMI detected value"); - goto fail; - } - handle_device_status_changed(dm, DEVICE_TYPE_HDMI, NULL, NULL, detected); - } else if (dbus_message_is_signal(s, DBUS_INTERFACE_MIRRORING_SERVER, "miracast_wfd_source_status_changed")) { if (!dbus_message_get_args(s, NULL, DBUS_TYPE_INT32, &status, DBUS_TYPE_INVALID)) goto fail; diff --git a/src/device-manager-priv.h b/src/device-manager-priv.h index 5e17f2c..9244640 100644 --- a/src/device-manager-priv.h +++ b/src/device-manager-priv.h @@ -105,12 +105,6 @@ typedef enum external_value_forwarding_type { FORWARDING_CONNECTED = 1, } external_value_mirroring_t; -typedef enum external_value_hdmi_type { - HDMI_AUDIO_DISCONNECTED = -1, - HDMI_AUDIO_NOT_AVAILABLE = 0, - HDMI_AUDIO_AVAILABLE = 1, -} external_value_hdmi_t; - typedef enum external_value_bt_sco_type { BT_SCO_DISCONNECTED = 0, BT_SCO_CONNECTED = 1, diff --git a/src/device-manager.c b/src/device-manager.c index f541685..1e05eba 100644 --- a/src/device-manager.c +++ b/src/device-manager.c @@ -89,6 +89,7 @@ #define DEVICE_API_BTSCO "btsco" #endif #define DEVICE_BUS_USB "usb" +#define DEVICE_BUS_PATH_HDMI "hdmi" #define DEVICE_CLASS_SOUND "sound" #define DEVICE_CLASS_MONITOR "monitor" @@ -498,6 +499,20 @@ static bool pulse_device_is_btsco(pa_object *pdevice) { } #endif +static bool pulse_device_is_hdmi(pa_object *pdevice) { + const char *bus_path_name = NULL; + pa_proplist *prop = pulse_device_get_proplist(pdevice); + + if (!prop) + return false; + + if ((bus_path_name = pa_proplist_gets(prop, PA_PROP_DEVICE_BUS_PATH))) + return (bool)strstr(bus_path_name, DEVICE_BUS_PATH_HDMI); + + pa_log_debug("This device doesn't have property '%s'", PA_PROP_DEVICE_BUS_PATH); + return false; +} + static const char* pulse_device_get_device_string_removed_argument(pa_object *pdevice) { static char removed_param[DEVICE_PARAM_STRING_MAX] = {0,}; char *device_string_p = NULL; @@ -1052,6 +1067,8 @@ pa_dynarray* pulse_device_get_belongs_type(pa_object *pdevice, pa_device_manager return NULL; if (pulse_device_is_usb(pdevice)) return NULL; + if (pulse_device_is_hdmi(pdevice)) + return NULL; if (pulse_device_is_bluez(pdevice)) return NULL; @@ -1188,7 +1205,7 @@ static const char* pulse_device_get_system_id(pa_object *pdevice) { prop = pulse_device_get_proplist(pdevice); - if (pulse_device_is_usb(pdevice)) + if (pulse_device_is_usb(pdevice) || pulse_device_is_hdmi(pdevice)) return pa_proplist_gets(prop, "sysfs.path"); else if (pulse_device_is_bluez(pdevice)) return pa_proplist_gets(prop, "bluez.path"); @@ -1419,7 +1436,6 @@ static void handle_usb_pulse_device(pa_object *pdevice, bool is_loaded, pa_devic 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"); @@ -1453,6 +1469,49 @@ static void handle_usb_pulse_device(pa_object *pdevice, bool is_loaded, pa_devic } } +static void handle_hdmi_pulse_device(pa_object *pdevice, bool is_loaded, pa_device_manager *dm) { + const char *name, *system_id; + dm_device_direction_t direction; + pa_tz_device *device; + + pa_assert(pdevice); + pa_assert(dm); + + pa_log_info("Handle hdmi pulse device"); + + system_id = pulse_device_get_system_id(pdevice); + direction = pulse_device_get_direction(pdevice); + + if (is_loaded) { + pa_tz_device_new_data data; + pa_proplist *prop; + + prop = pulse_device_get_proplist(pdevice); + name = pa_proplist_gets(prop, "alsa.card_name"); + + pa_tz_device_new_data_init(&data, dm->device_list, dm->comm, NULL); + pa_tz_device_new_data_set_type(&data, DEVICE_TYPE_HDMI); + pa_tz_device_new_data_set_name(&data, name); + pa_tz_device_new_data_set_direction(&data, direction); + pa_tz_device_new_data_set_system_id(&data, system_id); + pa_tz_device_new_data_set_use_internal_codec(&data, false); + if (direction == DM_DEVICE_DIRECTION_OUT) { + apply_preference(dm, PA_SINK(pdevice)); + pa_tz_device_new_data_add_sink(&data, DEVICE_ROLE_NORMAL, PA_SINK(pdevice)); + } else { + pa_tz_device_new_data_add_source(&data, DEVICE_ROLE_NORMAL, PA_SOURCE(pdevice)); + } + + pa_tz_device_new(&data); + pa_tz_device_new_data_done(&data); + } else { + if (!(device = device_list_get_device(dm, DEVICE_TYPE_HDMI, NULL, system_id))) + pa_log_warn("Can't get hdmi device for %s", system_id); + else + pa_tz_device_free(device); + } +} + static void handle_bt_pulse_device(pa_object *pdevice, bool is_loaded, pa_device_manager *dm) { dm_device_direction_t direction; pa_tz_device *device; @@ -1721,6 +1780,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_usb_pulse_device(PA_OBJECT(sink), true, dm); return PA_HOOK_OK; + } else if (pulse_device_is_hdmi(PA_OBJECT(sink))) { + pulse_device_set_use_internal_codec(PA_OBJECT(sink), false); + handle_hdmi_pulse_device(PA_OBJECT(sink), true, dm); + return PA_HOOK_OK; } else if (pulse_device_is_bluez(PA_OBJECT(sink))) { pulse_device_set_use_internal_codec(PA_OBJECT(sink), false); handle_bt_pulse_device(PA_OBJECT(sink), true, dm); @@ -1763,6 +1826,9 @@ static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, pa_ if (pulse_device_is_usb(PA_OBJECT(sink))) { handle_usb_pulse_device(PA_OBJECT(sink), false, dm); return PA_HOOK_OK; + } else if (pulse_device_is_hdmi(PA_OBJECT(sink))) { + handle_hdmi_pulse_device(PA_OBJECT(sink), false, dm); + return PA_HOOK_OK; } else if (pulse_device_is_bluez(PA_OBJECT(sink))) { handle_bt_pulse_device(PA_OBJECT(sink), false, dm); return PA_HOOK_OK; -- 2.7.4 From 337a16875a734d99e78ddeb624df923cec6af844 Mon Sep 17 00:00:00 2001 From: Seungbae Shin Date: Wed, 28 Dec 2022 17:05:15 +0900 Subject: [PATCH 16/16] stream-manager-dbus: return device id also for get_current_media_routing_path method API related: sound_manager_get_current_media_playback_device_id() [Version] 15.0.35 [Issue Type] Update Change-Id: I27cbad83700c20262cf5ed5e88987755ff5d7523 --- packaging/pulseaudio-modules-tizen.spec | 2 +- src/stream-manager-dbus.c | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index be642d8..73c495b 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -2,7 +2,7 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 15.0.34 +Version: 15.0.35 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/stream-manager-dbus.c b/src/stream-manager-dbus.c index 096ff5c..fb0c17e 100644 --- a/src/stream-manager-dbus.c +++ b/src/stream-manager-dbus.c @@ -142,6 +142,7 @@ static pa_dbus_arg_info get_current_volume_type_args[] = { { "io_direction", "s { "type", "s", "out" }, { "ret_msg", "s", "out" } }; static pa_dbus_arg_info get_current_media_routing_path_args[] = { { "io_direction", "s", "in" }, + { "device_id", "u", "out" }, { "device_type", "s", "out" }, { "ret_msg", "s", "out" } }; static pa_dbus_arg_info update_focus_status_args[] = { { "parent_id", "u", "in" }, @@ -1560,6 +1561,7 @@ finish: static void handle_get_current_media_routing_path(DBusConnection *conn, DBusMessage *msg, void *userdata) { pa_stream_manager *m = (pa_stream_manager *)userdata; const char *direction = NULL; + dbus_uint32_t device_id; const char *device_type = dbus_str_none; dm_device_direction_t dm_device_direction = DM_DEVICE_DIRECTION_NONE; stream_info *s = NULL; @@ -1603,13 +1605,15 @@ static void handle_get_current_media_routing_path(DBusConnection *conn, DBusMess if (device) { device_type = pa_tz_device_get_type(device); + device_id = (dbus_uint32_t)pa_tz_device_get_id(device); ret = RET_MSG_OK; } else { pa_log_error("could not found matched device"); } finish: - pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &device_type, + pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_UINT32, &device_id, + DBUS_TYPE_STRING, &device_type, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[ret], DBUS_TYPE_INVALID)); pa_assert_se(dbus_connection_send(conn, reply, NULL)); -- 2.7.4