Skip to content

Commit

Permalink
Add some patches from upstream master git
Browse files Browse the repository at this point in the history
  • Loading branch information
berolinux committed Feb 4, 2022
1 parent aabd7c8 commit 8c5da25
Show file tree
Hide file tree
Showing 9 changed files with 709 additions and 1 deletion.
120 changes: 120 additions & 0 deletions 7480d095899cd683d028c405b98076127b60a552.patch
@@ -0,0 +1,120 @@
From 7480d095899cd683d028c405b98076127b60a552 Mon Sep 17 00:00:00 2001
From: Wim Taymans <wtaymans@redhat.com>
Date: Thu, 3 Feb 2022 16:17:38 +0100
Subject: [PATCH] alsa: update test-timer

Remove the bandwidth reduce, we don't do that.
Clamp large errors.
Add htimestamp mode, which seems more stable.
---
spa/plugins/alsa/test-timer.c | 51 ++++++++++++++++++++++++++++-------
1 file changed, 41 insertions(+), 10 deletions(-)

diff --git a/spa/plugins/alsa/test-timer.c b/spa/plugins/alsa/test-timer.c
index caa6b25e2..16d7df105 100644
--- a/spa/plugins/alsa/test-timer.c
+++ b/spa/plugins/alsa/test-timer.c
@@ -45,10 +45,12 @@ struct state {
unsigned int rate;
unsigned int channels;
snd_pcm_uframes_t period;
+ snd_pcm_uframes_t buffer_frames;

snd_pcm_t *hndl;
int timerfd;

+ double max_error;
float accumulator;

uint64_t next_time;
@@ -103,15 +105,36 @@ static int write_period(struct state *state)

static int on_timer_wakeup(struct state *state)
{
- snd_pcm_sframes_t avail, delay;
+ snd_pcm_sframes_t delay;
double error, corr;
-
- /* check the delay in the device */
- CHECK(snd_pcm_avail_delay(state->hndl, &avail, &delay), "delay");
+#if 1
+ snd_pcm_sframes_t avail;
+ CHECK(snd_pcm_avail_delay(state->hndl, &avail, &delay), "delay");
+#else
+ snd_pcm_uframes_t avail;
+ snd_htimestamp_t tstamp;
+ uint64_t then;
+
+ CHECK(snd_pcm_htimestamp(state->hndl, &avail, &tstamp), "htimestamp");
+ delay = state->buffer_frames - avail;
+
+ then = TIMESPEC_TO_NSEC(&tstamp);
+ if (then != 0) {
+ if (then < state->next_time) {
+ delay -= (state->next_time - then) * state->rate / NSEC_PER_SEC;
+ } else {
+ delay += (then - state->next_time) * state->rate / NSEC_PER_SEC;
+ }
+ }
+#endif

/* calculate the error, we want to have exactly 1 period of
* samples remaining in the device when we wakeup. */
error = (double)delay - (double)state->period;
+ if (error > state->max_error)
+ error = state->max_error;
+ else if (error < -state->max_error)
+ error = -state->max_error;

/* update the dll with the error, this gives a rate correction */
corr = spa_dll_update(&state->dll, error);
@@ -124,12 +147,6 @@ static int on_timer_wakeup(struct state *state)

if (state->next_time - state->prev_time > BW_PERIOD) {
state->prev_time = state->next_time;
-
- /* reduce bandwidth and show some stats */
- if (state->dll.bw > SPA_DLL_BW_MIN)
- spa_dll_set_bw(&state->dll, state->dll.bw / 2.0,
- state->period, state->rate);
-
fprintf(stdout, "corr:%f error:%f bw:%f\n",
corr, error, state->dll.bw);
}
@@ -144,6 +161,7 @@ int main(int argc, char *argv[])
struct state state = { 0, };
const char *device = DEFAULT_DEVICE;
snd_pcm_hw_params_t *hparams;
+ snd_pcm_sw_params_t *sparams;
struct timespec now;

CHECK(snd_pcm_open(&state.hndl, device, SND_PCM_STREAM_PLAYBACK, 0), "open %s failed", device);
@@ -165,12 +183,25 @@ int main(int argc, char *argv[])
&state.rate, 0), "set rate");
CHECK(snd_pcm_hw_params(state.hndl, hparams), "hw_params");

+ CHECK(snd_pcm_hw_params_get_buffer_size(hparams, &state.buffer_frames), "get_buffer_size_max");
+
fprintf(stdout, "opened format:%s rate:%u channels:%u\n",
snd_pcm_format_name(SND_PCM_FORMAT_S32_LE),
state.rate, state.channels);

+ snd_pcm_sw_params_alloca(&sparams);
+#if 0
+ CHECK(snd_pcm_sw_params_current(state.hndl, sparams), "sw_params_current");
+ CHECK(snd_pcm_sw_params_set_tstamp_mode(state.hndl, sparams, SND_PCM_TSTAMP_ENABLE),
+ "sw_params_set_tstamp_type");
+ CHECK(snd_pcm_sw_params_set_tstamp_type(state.hndl, sparams, SND_PCM_TSTAMP_TYPE_MONOTONIC),
+ "sw_params_set_tstamp_type");
+ CHECK(snd_pcm_sw_params(state.hndl, sparams), "sw_params");
+#endif
+
spa_dll_init(&state.dll);
spa_dll_set_bw(&state.dll, SPA_DLL_BW_MAX, state.period, state.rate);
+ state.max_error = 256.0;

if ((state.timerfd = timerfd_create(CLOCK_MONOTONIC, 0)) < 0)
perror("timerfd");
--
GitLab

29 changes: 29 additions & 0 deletions 76417fd2a6c10a319ab8eb4cc3edde0034f9300a.patch
@@ -0,0 +1,29 @@
From 76417fd2a6c10a319ab8eb4cc3edde0034f9300a Mon Sep 17 00:00:00 2001
From: Wim Taymans <wtaymans@redhat.com>
Date: Thu, 3 Feb 2022 16:21:41 +0100
Subject: [PATCH] alsa: use MONOTONIC clock for tstamp

---
spa/plugins/alsa/alsa-pcm.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/spa/plugins/alsa/alsa-pcm.c b/spa/plugins/alsa/alsa-pcm.c
index 99be668c5..05af22512 100644
--- a/spa/plugins/alsa/alsa-pcm.c
+++ b/spa/plugins/alsa/alsa-pcm.c
@@ -1516,8 +1516,10 @@ static int set_swparams(struct state *state)
/* get the current params */
CHECK(snd_pcm_sw_params_current(hndl, params), "sw_params_current");

- CHECK(snd_pcm_sw_params_set_tstamp_mode(hndl, params, SND_PCM_TSTAMP_ENABLE), "sw_params_set_tstamp_mode");
-
+ CHECK(snd_pcm_sw_params_set_tstamp_mode(hndl, params, SND_PCM_TSTAMP_ENABLE),
+ "sw_params_set_tstamp_mode");
+ CHECK(snd_pcm_sw_params_set_tstamp_type(hndl, params, SND_PCM_TSTAMP_TYPE_MONOTONIC),
+ "sw_params_set_tstamp_type");
#if 0
snd_pcm_uframes_t boundary;
CHECK(snd_pcm_sw_params_get_boundary(params, &boundary), "get_boundary");
--
GitLab

56 changes: 56 additions & 0 deletions 7ac809618ee4e5aea398d1cbbd8679db465f93f9.patch
@@ -0,0 +1,56 @@
From 7ac809618ee4e5aea398d1cbbd8679db465f93f9 Mon Sep 17 00:00:00 2001
From: Wim Taymans <wtaymans@redhat.com>
Date: Thu, 3 Feb 2022 16:39:52 +0100
Subject: [PATCH] pw-link: improve help and error messages

See #2089
---
src/tools/pw-link.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/src/tools/pw-link.c b/src/tools/pw-link.c
index 80dcb2f28..d05c54040 100644
--- a/src/tools/pw-link.c
+++ b/src/tools/pw-link.c
@@ -563,7 +563,7 @@ static void show_help(struct data *data, const char *name)
" -o, --output List output ports\n"
" -i, --input List input ports\n"
" -l, --links List links\n"
- " -m, --monitor Monitor links\n"
+ " -m, --monitor Monitor links and ports\n"
" -I, --id List IDs\n"
" -v, --verbose Verbose port properties\n"
"Connect: %1$s [options] output input\n"
@@ -662,6 +662,11 @@ int main(int argc, char *argv[])
if (argc == 1)
show_help(&data, argv[0]);

+ if (data.opt_id && (data.opt_mode & MODE_LIST) == 0) {
+ fprintf(stderr, "-I option needs one or more of -l, -i or -o\n");
+ return -1;
+ }
+
if ((data.opt_mode & MODE_MONITOR) == 0)
pw_properties_set(data.props, PW_KEY_OBJECT_LINGER, "true");

@@ -729,7 +734,7 @@ int main(int argc, char *argv[])
do_list(&data);
} else if (data.opt_mode & MODE_DISCONNECT) {
if (data.opt_output == NULL) {
- fprintf(stderr, "missing link-id or output and input port names\n");
+ fprintf(stderr, "missing link-id or output and input port names to disconnect\n");
return -1;
}
if ((res = do_unlink_ports(&data)) < 0) {
@@ -739,7 +744,7 @@ int main(int argc, char *argv[])
} else {
if (data.opt_output == NULL ||
data.opt_input == NULL) {
- fprintf(stderr, "missing output and input port names\n");
+ fprintf(stderr, "missing output and input port names to connect\n");
return -1;
}
if ((res = do_link_ports(&data)) < 0) {
--
GitLab

161 changes: 161 additions & 0 deletions 97a5fe80c1d0fb0d8173a61a87051053cff7a5c2.patch
@@ -0,0 +1,161 @@
From 97a5fe80c1d0fb0d8173a61a87051053cff7a5c2 Mon Sep 17 00:00:00 2001
From: Pauli Virtanen <pav@iki.fi>
Date: Thu, 3 Feb 2022 19:23:23 +0200
Subject: [PATCH] spa/alsa-udev: fix /proc/asound handling without
CONFIG_SND_VERBOSE_PROCFS

For kernels compiled with CONFIG_SND_VERBOSE_PROCFS=n, the pcmXX
/proc/asound entries do not exist. In that case, the "device busy"
check cannot be done, but we should still check existence of PCM devices
correctly.

Count the number of PCM devices from /dev/snd, which should work also
without /proc/asound or /sysfs/class/sound.
---
spa/plugins/alsa/alsa-udev.c | 88 ++++++++++++++++++++++++++++++------
1 file changed, 73 insertions(+), 15 deletions(-)

diff --git a/spa/plugins/alsa/alsa-udev.c b/spa/plugins/alsa/alsa-udev.c
index 572bb8a32..08373239d 100644
--- a/spa/plugins/alsa/alsa-udev.c
+++ b/spa/plugins/alsa/alsa-udev.c
@@ -246,6 +246,60 @@ static void unescape(const char *src, char *dst)
*d = 0;
}

+static int check_device_pcm_class(const char *devname)
+{
+ FILE *f;
+ char path[PATH_MAX];
+ char buf[16];
+ size_t sz;
+
+ /* Check device class */
+ spa_scnprintf(path, sizeof(path), "/sys/class/sound/%s/pcm_class",
+ devname);
+ f = fopen(path, "r");
+ if (f == NULL)
+ return -errno;
+ sz = fread(buf, 1, sizeof(buf) - 1, f);
+ buf[sz] = '\0';
+ fclose(f);
+ return spa_strstartswith(buf, "modem") ? -ENXIO : 0;
+}
+
+static int get_num_pcm_devices(unsigned int card_id)
+{
+ char prefix[32];
+ DIR *snd = NULL;
+ struct dirent *entry;
+ int num_dev = 0;
+ int res;
+
+ /* Check if card has PCM devices, without opening them */
+
+ spa_scnprintf(prefix, sizeof(prefix), "pcmC%uD", card_id);
+
+ if ((snd = opendir("/dev/snd")) == NULL)
+ return -errno;
+
+ while ((errno = 0, entry = readdir(snd)) != NULL) {
+ if (!(entry->d_type == DT_CHR &&
+ spa_strstartswith(entry->d_name, prefix)))
+ continue;
+
+ res = check_device_pcm_class(entry->d_name);
+ if (res == 0 || res == -ENOENT) {
+ /* count device also if sysfs status file not there */
+ ++num_dev;
+ }
+ }
+ if (errno != 0)
+ res = -errno;
+ else
+ res = num_dev;
+
+ closedir(snd);
+ return res;
+}
+
static int check_device_available(struct impl *this, struct device *device, int *num_pcm)
{
char path[PATH_MAX];
@@ -256,14 +310,26 @@ static int check_device_available(struct impl *this, struct device *device, int
struct dirent *entry, *entry_pcm;
int res;

+ res = get_num_pcm_devices(device->id);
+ if (res < 0) {
+ spa_log_error(this->log, "Error finding PCM devices for ALSA card %u: %s",
+ (unsigned int)device->id, spa_strerror(res));
+ return res;
+ }
+ *num_pcm = res;
+
+ spa_log_debug(this->log, "card %u has %d pcm device(s)", (unsigned int)device->id, *num_pcm);
+
/*
* Check if some pcm devices of the card are busy. Check it via /proc, as we
* don't want to actually open any devices using alsa-lib (generates uncontrolled
* number of inotify events), or replicate its subdevice logic.
+ *
+ * The pcmXX directories do not exist if kernel is compiled with
+ * CONFIG_SND_VERBOSE_PROCFS=n. In that case, the busy check always
+ * succeeds.
*/

- *num_pcm = 0;
-
spa_scnprintf(path, sizeof(path), "/proc/asound/card%u", (unsigned int)device->id);

if ((card = opendir(path)) == NULL)
@@ -274,16 +340,9 @@ static int check_device_available(struct impl *this, struct device *device, int
spa_strstartswith(entry->d_name, "pcm")))
continue;

- /* Check device class */
- spa_scnprintf(path, sizeof(path), "/sys/class/sound/pcmC%uD%s/pcm_class",
+ spa_scnprintf(path, sizeof(path), "pcmC%uD%s",
(unsigned int)device->id, entry->d_name+3);
- f = fopen(path, "r");
- if (f == NULL)
- goto done;
- sz = fread(buf, 1, sizeof(buf) - 1, f);
- buf[sz] = '\0';
- fclose(f);
- if (spa_strstartswith(buf, "modem"))
+ if (check_device_pcm_class(path) < 0)
continue;

/* Check busy status */
@@ -319,8 +378,6 @@ static int check_device_available(struct impl *this, struct device *device, int
if (errno != 0)
goto done;

- ++*num_pcm;
-
closedir(pcm);
pcm = NULL;
}
@@ -352,15 +409,16 @@ static int emit_object_info(struct impl *this, struct device *device)
* device->emitted to true. alsalib functions can be used after that.
*/

+ snprintf(path, sizeof(path), "hw:%u", id);
+
if ((res = check_device_available(this, device, &pcm)) < 0)
return res;
if (pcm == 0) {
spa_log_debug(this->log, "no pcm devices for %s", path);
device->ignored = true;
- return 0;
+ return -ENODEV;
}

- snprintf(path, sizeof(path), "hw:%u", id);
spa_log_debug(this->log, "emitting card %s", path);
device->emitted = true;

--
GitLab

26 changes: 26 additions & 0 deletions a947faeaa0a9d69398d7fb6510d0ba9d28707701.patch
@@ -0,0 +1,26 @@
From a947faeaa0a9d69398d7fb6510d0ba9d28707701 Mon Sep 17 00:00:00 2001
From: Wim Taymans <wtaymans@redhat.com>
Date: Thu, 3 Feb 2022 16:30:06 +0100
Subject: [PATCH] pw-link: clarify -L option

-L is enabled by default, unless -m is specified.
---
src/tools/pw-link.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/tools/pw-link.c b/src/tools/pw-link.c
index 88b7e0732..80dcb2f28 100644
--- a/src/tools/pw-link.c
+++ b/src/tools/pw-link.c
@@ -567,7 +567,7 @@ static void show_help(struct data *data, const char *name)
" -I, --id List IDs\n"
" -v, --verbose Verbose port properties\n"
"Connect: %1$s [options] output input\n"
- " -L, --linger Linger (for use without -m)\n"
+ " -L, --linger Linger (default, unless -m is used)\n"
" -P, --passive Passive link\n"
" -p, --props=PROPS Properties as JSON object\n"
"Disconnect: %1$s -d [options] output input\n"
--
GitLab

0 comments on commit 8c5da25

Please sign in to comment.