forked from pool/alsa-utils
- backport GIT PATCHES:
* A few alsactl init fix patches: * amixer control-id parse fix * new aloop utility * robusitfy speaker-test * misc clean up, translation updates - Use systemd for openSUSE 11.4 - Put udev rules into this package instead of alsa.rpm OBS-URL: https://build.opensuse.org/package/show/multimedia:libs/alsa-utils?expand=0&rev=23
This commit is contained in:
parent
00b6532313
commit
3331bcfb82
@ -0,0 +1,35 @@
|
||||
From 52bd2f8acedaacce32ca8e89cb1f21683658648e Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Tue, 7 Sep 2010 17:07:12 +0200
|
||||
Subject: [PATCH 14/38] alsactl init: Handle "Capture Source" and "Mic Boost" in the default script
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
alsactl/init/default | 6 ++++++
|
||||
1 files changed, 6 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/alsactl/init/default b/alsactl/init/default
|
||||
index 35acfc3..9fd7972 100644
|
||||
--- a/alsactl/init/default
|
||||
+++ b/alsactl/init/default
|
||||
@@ -185,6 +185,11 @@ CTL{name}="Capture Volume",CTL{do_search}=="1", \
|
||||
CTL{name}="Capture Switch",CTL{do_search}=="1", \
|
||||
CTL{values}="on"
|
||||
|
||||
+CTL{name}="Capture Source",PROGRAM!="__ctl_search", GOTO=""
|
||||
+CTL{enums}=="*|Internal Mic|*",CTL{values}="Internal Mic", GOTO=""
|
||||
+CTL{enums}=="*|Mic|*",CTL{values}="Mic"
|
||||
+LABEL=""
|
||||
+
|
||||
CTL{name}="Input Source",PROGRAM!="__ctl_search", GOTO=""
|
||||
CTL{enums}=="*|Internal Mic|*",CTL{values}="Internal Mic", GOTO=""
|
||||
CTL{enums}=="*|Mic|*",CTL{values}="Mic"
|
||||
@@ -195,4 +200,5 @@ CTL{enums}=="*|Digital Mic 1|*",CTL{values}="Digital Mic 1", GOTO=""
|
||||
CTL{enums}=="*|Mic|*",CTL{values}="Mic"
|
||||
LABEL=""
|
||||
|
||||
+CTL{name}="Mic Boost",CTL{do_search}=="1", CTL{values}="on"
|
||||
CTL{name}="Internal Mic Boost",CTL{do_search}=="1", CTL{values}="on"
|
||||
--
|
||||
1.7.3.1
|
||||
|
@ -0,0 +1,31 @@
|
||||
From ef919a4724169f4c0dc14168dec32c168b2471e4 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Tue, 7 Sep 2010 17:33:14 +0200
|
||||
Subject: [PATCH 15/38] alsactl init: Initialize also "Master Front Playback Volume" & "Switch"
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
alsactl/init/default | 7 +++++++
|
||||
1 files changed, 7 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/alsactl/init/default b/alsactl/init/default
|
||||
index 9fd7972..7f8ec4c 100644
|
||||
--- a/alsactl/init/default
|
||||
+++ b/alsactl/init/default
|
||||
@@ -30,6 +30,13 @@ CTL{name}="Master Playback Switch",CTL{do_search}=="1", \
|
||||
CTL{values}="on"
|
||||
|
||||
CTL{reset}="mixer"
|
||||
+CTL{name}="Master Front Playback Volume",CTL{do_search}=="1", \
|
||||
+ ENV{has_pmaster_vol}:="true", \
|
||||
+ CTL{write}!="$env{pvolume}",CTL{values}="$env{ppercent}"
|
||||
+CTL{name}="Master Front Playback Switch",CTL{do_search}=="1", \
|
||||
+ CTL{values}="on"
|
||||
+
|
||||
+CTL{reset}="mixer"
|
||||
CTL{name}="Master Digital Playback Volume",CTL{do_search}=="1", \
|
||||
CTL{write}!="$env{pvolume}",CTL{values}="$env{ppercent}"
|
||||
CTL{name}="Master Digital Playback Switch",CTL{do_search}=="1", \
|
||||
--
|
||||
1.7.3.1
|
||||
|
27
0016-amixer-fix-parsing-of-control-ID-name.patch
Normal file
27
0016-amixer-fix-parsing-of-control-ID-name.patch
Normal file
@ -0,0 +1,27 @@
|
||||
From 87c58b59b5c443fe3244bd06417c451581d1f635 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Tue, 5 Oct 2010 10:02:45 +0200
|
||||
Subject: [PATCH 16/38] amixer: fix parsing of control ID name
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
amixer/amixer.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/amixer/amixer.c b/amixer/amixer.c
|
||||
index c9ea572..a177288 100644
|
||||
--- a/amixer/amixer.c
|
||||
+++ b/amixer/amixer.c
|
||||
@@ -1120,8 +1120,8 @@ static int parse_control_id(const char *str, snd_ctl_elem_id_t *id)
|
||||
}
|
||||
str++;
|
||||
}
|
||||
- *ptr = '\0';
|
||||
}
|
||||
+ *ptr = '\0';
|
||||
snd_ctl_elem_id_set_name(id, buf);
|
||||
} else if (!strncasecmp(str, "index=", 6)) {
|
||||
str += 6;
|
||||
--
|
||||
1.7.3.1
|
||||
|
3313
0017-Introduce-alsaloop-utility.patch
Normal file
3313
0017-Introduce-alsaloop-utility.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,45 @@
|
||||
From ad0e562373af1de5e911cf1d5def598a7b6523f2 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Wed, 6 Oct 2010 18:30:18 +0200
|
||||
Subject: [PATCH 18/38] alsaloop: Fix loopbacks pointer initialization and allocation, fix -T option
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
alsaloop/alsaloop.c | 7 ++++---
|
||||
1 files changed, 4 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/alsaloop/alsaloop.c b/alsaloop/alsaloop.c
|
||||
index 4ba5203..0001358 100644
|
||||
--- a/alsaloop/alsaloop.c
|
||||
+++ b/alsaloop/alsaloop.c
|
||||
@@ -45,7 +45,7 @@ struct loopback_thread {
|
||||
int verbose = 0;
|
||||
int daemonize = 0;
|
||||
int use_syslog = 0;
|
||||
-struct loopback **loopbacks;
|
||||
+struct loopback **loopbacks = NULL;
|
||||
int loopbacks_count = 0;
|
||||
|
||||
static void my_exit(struct loopback_thread *thread, int exitcode)
|
||||
@@ -199,7 +199,8 @@ static long timediff(struct timeval t1, struct timeval t2)
|
||||
|
||||
static void add_loop(struct loopback *loop)
|
||||
{
|
||||
- loopbacks = realloc(loopbacks, loopbacks_count * sizeof(struct loopback *));
|
||||
+ loopbacks = realloc(loopbacks, (loopbacks_count + 1) *
|
||||
+ sizeof(struct loopback *));
|
||||
if (loopbacks == NULL) {
|
||||
logit(LOG_CRIT, "No enough memory\n");
|
||||
exit(EXIT_FAILURE);
|
||||
@@ -321,7 +322,7 @@ static int parse_config(int argc, char *argv[], snd_output_t *output)
|
||||
morehelp = 0;
|
||||
while (1) {
|
||||
int c;
|
||||
- if ((c = getopt_long(argc, argv, "hdg:P:C:l:t:F:f:c:r:s:benvA:S:a:m:", long_option, NULL)) < 0)
|
||||
+ if ((c = getopt_long(argc, argv, "hdg:P:C:l:t:F:f:c:r:s:benvA:S:a:m:T:", long_option, NULL)) < 0)
|
||||
break;
|
||||
switch (c) {
|
||||
case 'h':
|
||||
--
|
||||
1.7.3.1
|
||||
|
80
0019-alsaloop-Fix-thread-handling.patch
Normal file
80
0019-alsaloop-Fix-thread-handling.patch
Normal file
@ -0,0 +1,80 @@
|
||||
From 4fe4d22b73dd205521348583f8105de1c155f4a6 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Wed, 6 Oct 2010 18:51:29 +0200
|
||||
Subject: [PATCH 19/38] alsaloop: Fix thread handling
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
alsaloop/alsaloop.c | 5 ++---
|
||||
alsaloop/test.sh | 19 +++++++++++++++++++
|
||||
2 files changed, 21 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/alsaloop/alsaloop.c b/alsaloop/alsaloop.c
|
||||
index 0001358..743e0ef 100644
|
||||
--- a/alsaloop/alsaloop.c
|
||||
+++ b/alsaloop/alsaloop.c
|
||||
@@ -687,7 +687,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
/* we must sort thread IDs */
|
||||
- j = 0;
|
||||
+ j = -1;
|
||||
do {
|
||||
k = 0x7fffffff;
|
||||
for (i = 0; i < loopbacks_count; i++) {
|
||||
@@ -695,11 +695,11 @@ int main(int argc, char *argv[])
|
||||
loopbacks[i]->thread > j)
|
||||
k = loopbacks[i]->thread;
|
||||
}
|
||||
+ j++;
|
||||
for (i = 0; i < loopbacks_count; i++) {
|
||||
if (loopbacks[i]->thread == k)
|
||||
loopbacks[i]->thread = j;
|
||||
}
|
||||
- j++;
|
||||
} while (k != 0x7fffffff);
|
||||
/* fix maximum thread id */
|
||||
for (i = 0, j = -1; i < loopbacks_count; i++) {
|
||||
@@ -729,7 +729,6 @@ int main(int argc, char *argv[])
|
||||
for (k = 0; k < j; k++)
|
||||
thread_job(&threads[k]);
|
||||
|
||||
- logit(LOG_CRIT, "threads = %i %i\n", j, loopbacks_count);
|
||||
if (j > 1) {
|
||||
for (k = 0; k < j; k++)
|
||||
pthread_join(threads[k].thread, NULL);
|
||||
diff --git a/alsaloop/test.sh b/alsaloop/test.sh
|
||||
index 2033add..bc42480 100755
|
||||
--- a/alsaloop/test.sh
|
||||
+++ b/alsaloop/test.sh
|
||||
@@ -27,8 +27,27 @@ EOF
|
||||
$DBG ./alsaloop -d --config $CFGFILE
|
||||
}
|
||||
|
||||
+test3() {
|
||||
+ echo "TEST2"
|
||||
+cat > $CFGFILE <<EOF
|
||||
+-C hw:1,0,0 -P dmix:0 --tlatency 50000 --thread 0 \
|
||||
+ --mixer "name='Master Playback Volume'@name='Master Playback Volume'" \
|
||||
+ --mixer "name='Master Playback Switch'@name='Master Playback Switch'" \
|
||||
+ --mixer "name='PCM Playback Volume'"
|
||||
+-C hw:1,0,1 -P dmix:0 --tlatency 50000 --thread 1
|
||||
+-C hw:1,0,2 -P dmix:0 --tlatency 50000 --thread 2
|
||||
+-C hw:1,0,3 -P dmix:0 --tlatency 50000 --thread 3
|
||||
+-C hw:1,0,4 -P dmix:0 --tlatency 50000 --thread 4
|
||||
+-C hw:1,0,5 -P dmix:0 --tlatency 50000 --thread 5
|
||||
+-C hw:1,0,6 -P dmix:0 --tlatency 50000 --thread 6
|
||||
+-C hw:1,0,7 -P dmix:0 --tlatency 50000 --thread 7
|
||||
+EOF
|
||||
+ $DBG ./alsaloop --config $CFGFILE
|
||||
+}
|
||||
+
|
||||
case "$1" in
|
||||
test1) test1 ;;
|
||||
test2) test2 ;;
|
||||
+test3) test3 ;;
|
||||
*) test1 ;;
|
||||
esac
|
||||
--
|
||||
1.7.3.1
|
||||
|
85
0020-alsaloop-fix-a-option-and-slave-mode-processing.patch
Normal file
85
0020-alsaloop-fix-a-option-and-slave-mode-processing.patch
Normal file
@ -0,0 +1,85 @@
|
||||
From 5ad13c4825085ac28ed12afb0daf73c315fe0ed6 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Wed, 6 Oct 2010 20:34:03 +0200
|
||||
Subject: [PATCH 20/38] alsaloop: fix -a option and slave mode processing
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
alsaloop/alsaloop.c | 4 ++--
|
||||
alsaloop/pcmjob.c | 3 +++
|
||||
alsaloop/test.sh | 18 +++++++++---------
|
||||
3 files changed, 14 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/alsaloop/alsaloop.c b/alsaloop/alsaloop.c
|
||||
index 743e0ef..48bd21a 100644
|
||||
--- a/alsaloop/alsaloop.c
|
||||
+++ b/alsaloop/alsaloop.c
|
||||
@@ -424,9 +424,9 @@ static int parse_config(int argc, char *argv[], snd_output_t *output)
|
||||
case 'a':
|
||||
if (optarg[0] == 'a')
|
||||
arg_slave = SLAVE_TYPE_AUTO;
|
||||
- else if (strcasecmp(optarg, "off"))
|
||||
+ else if (strcasecmp(optarg, "on") == 0)
|
||||
arg_slave = SLAVE_TYPE_ON;
|
||||
- else if (strcasecmp(optarg, "on"))
|
||||
+ else if (strcasecmp(optarg, "off") == 0)
|
||||
arg_slave = SLAVE_TYPE_OFF;
|
||||
else
|
||||
arg_slave = atoi(optarg);
|
||||
diff --git a/alsaloop/pcmjob.c b/alsaloop/pcmjob.c
|
||||
index 47256e0..51d9ea6 100644
|
||||
--- a/alsaloop/pcmjob.c
|
||||
+++ b/alsaloop/pcmjob.c
|
||||
@@ -1432,6 +1432,8 @@ int pcmjob_pollfds_handle(struct loopback *loop, struct pollfd *fds)
|
||||
}
|
||||
if (verbose > 9)
|
||||
snd_output_printf(loop->output, "%s: prevents = 0x%x, crevents = 0x%x\n", loop->id, prevents, crevents);
|
||||
+ if (prevents == 0 && crevents == 0)
|
||||
+ goto __pcm_end;
|
||||
do {
|
||||
ccount = readit(capt);
|
||||
buf_add(loop, ccount);
|
||||
@@ -1520,6 +1522,7 @@ int pcmjob_pollfds_handle(struct loopback *loop, struct pollfd *fds)
|
||||
else
|
||||
snd_output_printf(loop->output, "%s: end delay %li\n", capt->id, cdelay);
|
||||
}
|
||||
+ __pcm_end:
|
||||
if (verbose > 13) {
|
||||
getcurtimestamp(&loop->tstamp_end);
|
||||
snd_output_printf(loop->output, "%s: processing time %lius\n", capt->id, timediff(loop->tstamp_end, loop->tstamp_start));
|
||||
diff --git a/alsaloop/test.sh b/alsaloop/test.sh
|
||||
index bc42480..a1d4dbe 100755
|
||||
--- a/alsaloop/test.sh
|
||||
+++ b/alsaloop/test.sh
|
||||
@@ -28,19 +28,19 @@ EOF
|
||||
}
|
||||
|
||||
test3() {
|
||||
- echo "TEST2"
|
||||
+ echo "TEST3"
|
||||
cat > $CFGFILE <<EOF
|
||||
--C hw:1,0,0 -P dmix:0 --tlatency 50000 --thread 0 \
|
||||
+-C hw:1,0,0 -P plug:dmix:0 --tlatency 50000 --thread 0 \
|
||||
--mixer "name='Master Playback Volume'@name='Master Playback Volume'" \
|
||||
--mixer "name='Master Playback Switch'@name='Master Playback Switch'" \
|
||||
--mixer "name='PCM Playback Volume'"
|
||||
--C hw:1,0,1 -P dmix:0 --tlatency 50000 --thread 1
|
||||
--C hw:1,0,2 -P dmix:0 --tlatency 50000 --thread 2
|
||||
--C hw:1,0,3 -P dmix:0 --tlatency 50000 --thread 3
|
||||
--C hw:1,0,4 -P dmix:0 --tlatency 50000 --thread 4
|
||||
--C hw:1,0,5 -P dmix:0 --tlatency 50000 --thread 5
|
||||
--C hw:1,0,6 -P dmix:0 --tlatency 50000 --thread 6
|
||||
--C hw:1,0,7 -P dmix:0 --tlatency 50000 --thread 7
|
||||
+-C hw:1,0,1 -P plug:dmix:0 --tlatency 50000 --thread 1
|
||||
+-C hw:1,0,2 -P plug:dmix:0 --tlatency 50000 --thread 2
|
||||
+-C hw:1,0,3 -P plug:dmix:0 --tlatency 50000 --thread 3
|
||||
+-C hw:1,0,4 -P plug:dmix:0 --tlatency 50000 --thread 4
|
||||
+-C hw:1,0,5 -P plug:dmix:0 --tlatency 50000 --thread 5
|
||||
+-C hw:1,0,6 -P plug:dmix:0 --tlatency 50000 --thread 6
|
||||
+-C hw:1,0,7 -P plug:dmix:0 --tlatency 50000 --thread 7
|
||||
EOF
|
||||
$DBG ./alsaloop --config $CFGFILE
|
||||
}
|
||||
--
|
||||
1.7.3.1
|
||||
|
49
0021-alsaloop-fix-resample-argument-parsing.patch
Normal file
49
0021-alsaloop-fix-resample-argument-parsing.patch
Normal file
@ -0,0 +1,49 @@
|
||||
From f956c329aa1271c89cf13a01d1bcea8fae6b03f8 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Thu, 7 Oct 2010 00:12:38 +0200
|
||||
Subject: [PATCH 21/38] alsaloop: fix resample argument parsing
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
alsaloop/alsaloop.c | 4 ++--
|
||||
alsaloop/pcmjob.c | 2 +-
|
||||
2 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/alsaloop/alsaloop.c b/alsaloop/alsaloop.c
|
||||
index 48bd21a..6fb9c2a 100644
|
||||
--- a/alsaloop/alsaloop.c
|
||||
+++ b/alsaloop/alsaloop.c
|
||||
@@ -81,7 +81,7 @@ static int create_loopback_handle(struct loopback_handle **_handle,
|
||||
handle->format = SND_PCM_FORMAT_S16_LE;
|
||||
handle->rate = 48000;
|
||||
handle->channels = 2;
|
||||
- handle->resample = 1;
|
||||
+ handle->resample = 0;
|
||||
*_handle = handle;
|
||||
return 0;
|
||||
}
|
||||
@@ -384,7 +384,7 @@ static int parse_config(int argc, char *argv[], snd_output_t *output)
|
||||
arg_effect = 1;
|
||||
break;
|
||||
case 'n':
|
||||
- arg_resample = 0;
|
||||
+ arg_resample = 1;
|
||||
break;
|
||||
case 'A':
|
||||
if (strcasecmp(optarg, "sincbest") == 0)
|
||||
diff --git a/alsaloop/pcmjob.c b/alsaloop/pcmjob.c
|
||||
index 51d9ea6..4ad752d 100644
|
||||
--- a/alsaloop/pcmjob.c
|
||||
+++ b/alsaloop/pcmjob.c
|
||||
@@ -108,7 +108,7 @@ static int setparams_stream(struct loopback_handle *lhandle,
|
||||
rrate = 0;
|
||||
snd_pcm_hw_params_get_rate(params, &rrate, 0);
|
||||
if ((int)rrate != lhandle->rate) {
|
||||
- logit(LOG_CRIT, "Rate does not match (requested %iHz, get %iHz)\n", lhandle->rate, err);
|
||||
+ logit(LOG_CRIT, "Rate does not match (requested %iHz, got %iHz, resample %i)\n", lhandle->rate, rrate, lhandle->resample);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
--
|
||||
1.7.3.1
|
||||
|
618
0022-alsaloop-added-resampling-for-unsupported-soundcard-.patch
Normal file
618
0022-alsaloop-added-resampling-for-unsupported-soundcard-.patch
Normal file
@ -0,0 +1,618 @@
|
||||
From 058357f04239e1c61d60c29f40409f91d6a6e413 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Thu, 7 Oct 2010 20:38:36 +0200
|
||||
Subject: [PATCH 22/38] alsaloop: added resampling for unsupported soundcard rates
|
||||
|
||||
- improve also xrun synchronization
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
alsaloop/alsaloop.c | 6 +-
|
||||
alsaloop/alsaloop.h | 7 +-
|
||||
alsaloop/pcmjob.c | 279 +++++++++++++++++++++++++++++++++++++--------------
|
||||
alsaloop/test.sh | 12 ++-
|
||||
4 files changed, 223 insertions(+), 81 deletions(-)
|
||||
|
||||
diff --git a/alsaloop/alsaloop.c b/alsaloop/alsaloop.c
|
||||
index 6fb9c2a..bbf570e 100644
|
||||
--- a/alsaloop/alsaloop.c
|
||||
+++ b/alsaloop/alsaloop.c
|
||||
@@ -79,7 +79,7 @@ static int create_loopback_handle(struct loopback_handle **_handle,
|
||||
handle->id = strdup(idbuf);
|
||||
handle->access = SND_PCM_ACCESS_RW_INTERLEAVED;
|
||||
handle->format = SND_PCM_FORMAT_S16_LE;
|
||||
- handle->rate = 48000;
|
||||
+ handle->rate = handle->rate_req = 48000;
|
||||
handle->channels = 2;
|
||||
handle->resample = 0;
|
||||
*_handle = handle;
|
||||
@@ -311,7 +311,7 @@ static int parse_config(int argc, char *argv[], snd_output_t *output)
|
||||
int arg_nblock = 0;
|
||||
int arg_effect = 0;
|
||||
int arg_resample = 0;
|
||||
- int arg_samplerate = 0;
|
||||
+ int arg_samplerate = SRC_SINC_FASTEST + 1;
|
||||
int arg_sync = SYNC_TYPE_AUTO;
|
||||
int arg_slave = SLAVE_TYPE_AUTO;
|
||||
int arg_thread = 0;
|
||||
@@ -474,7 +474,7 @@ static int parse_config(int argc, char *argv[], snd_output_t *output)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
play->format = capt->format = arg_format;
|
||||
- play->rate = capt->rate = arg_rate;
|
||||
+ play->rate = play->rate_req = capt->rate = capt->rate_req = arg_rate;
|
||||
play->channels = capt->channels = arg_channels;
|
||||
play->buffer_size_req = capt->buffer_size_req = arg_buffer_size;
|
||||
play->period_size_req = capt->period_size_req = arg_period_size;
|
||||
diff --git a/alsaloop/alsaloop.h b/alsaloop/alsaloop.h
|
||||
index 4b357de..9753c41 100644
|
||||
--- a/alsaloop/alsaloop.h
|
||||
+++ b/alsaloop/alsaloop.h
|
||||
@@ -79,6 +79,7 @@ struct loopback_handle {
|
||||
snd_pcm_access_t access;
|
||||
snd_pcm_format_t format;
|
||||
unsigned int rate;
|
||||
+ unsigned int rate_req;
|
||||
unsigned int channels;
|
||||
unsigned int buffer_size;
|
||||
unsigned int period_size;
|
||||
@@ -100,6 +101,8 @@ struct loopback_handle {
|
||||
unsigned long long counter;
|
||||
unsigned long sync_point; /* in samples */
|
||||
snd_pcm_sframes_t last_delay;
|
||||
+ double pitch;
|
||||
+ snd_pcm_uframes_t total_queued;
|
||||
/* control */
|
||||
snd_ctl_t *ctl;
|
||||
unsigned int ctl_pollfd_count;
|
||||
@@ -135,15 +138,15 @@ struct loopback {
|
||||
snd_pcm_sframes_t pitch_diff;
|
||||
snd_pcm_sframes_t pitch_diff_min;
|
||||
snd_pcm_sframes_t pitch_diff_max;
|
||||
- snd_pcm_uframes_t total_queued;
|
||||
unsigned int total_queued_count;
|
||||
snd_timestamp_t tstamp_start;
|
||||
snd_timestamp_t tstamp_end;
|
||||
/* control mixer */
|
||||
struct loopback_mixer *controls;
|
||||
/* sample rate */
|
||||
+ unsigned int use_samplerate:1;
|
||||
#ifdef USE_SAMPLERATE
|
||||
- unsigned int src_enable: 1;
|
||||
+ unsigned int src_enable:1;
|
||||
int src_converter_type;
|
||||
SRC_STATE *src_state;
|
||||
SRC_DATA src_data;
|
||||
diff --git a/alsaloop/pcmjob.c b/alsaloop/pcmjob.c
|
||||
index 4ad752d..86917ef 100644
|
||||
--- a/alsaloop/pcmjob.c
|
||||
+++ b/alsaloop/pcmjob.c
|
||||
@@ -99,18 +99,20 @@ static int setparams_stream(struct loopback_handle *lhandle,
|
||||
logit(LOG_CRIT, "Channels count (%i) not available for %s: %s\n", lhandle->channels, lhandle->id, snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
- rrate = lhandle->rate;
|
||||
+ rrate = lhandle->rate_req;
|
||||
err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, 0);
|
||||
if (err < 0) {
|
||||
- logit(LOG_CRIT, "Rate %iHz not available for %s: %s\n", lhandle->rate, lhandle->id, snd_strerror(err));
|
||||
+ logit(LOG_CRIT, "Rate %iHz not available for %s: %s\n", lhandle->rate_req, lhandle->id, snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
rrate = 0;
|
||||
snd_pcm_hw_params_get_rate(params, &rrate, 0);
|
||||
- if ((int)rrate != lhandle->rate) {
|
||||
+ lhandle->rate = rrate;
|
||||
+ if (!lhandle->loopback->src_enable && (int)rrate != lhandle->rate) {
|
||||
logit(LOG_CRIT, "Rate does not match (requested %iHz, got %iHz, resample %i)\n", lhandle->rate, rrate, lhandle->resample);
|
||||
return -EINVAL;
|
||||
}
|
||||
+ lhandle->pitch = (double)lhandle->rate_req / (double)lhandle->rate;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -245,11 +247,11 @@ static int setparams(struct loopback *loop, snd_pcm_uframes_t bufsize)
|
||||
return err;
|
||||
}
|
||||
|
||||
- if ((err = setparams_bufsize(loop->play, p_params, pt_params, bufsize)) < 0) {
|
||||
+ if ((err = setparams_bufsize(loop->play, p_params, pt_params, bufsize / loop->play->pitch)) < 0) {
|
||||
logit(LOG_CRIT, "Unable to set buffer parameters for %s stream: %s\n", loop->play->id, snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
- if ((err = setparams_bufsize(loop->capt, c_params, ct_params, bufsize)) < 0) {
|
||||
+ if ((err = setparams_bufsize(loop->capt, c_params, ct_params, bufsize / loop->capt->pitch)) < 0) {
|
||||
logit(LOG_CRIT, "Unable to set buffer parameters for %s stream: %s\n", loop->capt->id, snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
@@ -618,6 +620,7 @@ static snd_pcm_sframes_t remove_samples(struct loopback *loop,
|
||||
} else {
|
||||
if (count > play->buf_count)
|
||||
count = play->buf_count;
|
||||
+ play->buf_count -= count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
@@ -627,7 +630,7 @@ static int xrun_sync(struct loopback *loop)
|
||||
struct loopback_handle *play = loop->play;
|
||||
struct loopback_handle *capt = loop->capt;
|
||||
snd_pcm_uframes_t fill = get_whole_latency(loop);
|
||||
- snd_pcm_sframes_t delay, delayi, pdelay, cdelay, diff;
|
||||
+ snd_pcm_sframes_t pdelay, cdelay, delay1, pdelay1, cdelay1, diff;
|
||||
int err;
|
||||
|
||||
__again:
|
||||
@@ -681,45 +684,82 @@ static int xrun_sync(struct loopback *loop)
|
||||
}
|
||||
capt->counter = cdelay;
|
||||
play->counter = pdelay;
|
||||
- loop->total_queued = 0;
|
||||
- loop->total_queued_count = 0;
|
||||
- loop->pitch_diff = loop->pitch_diff_min = loop->pitch_diff_max = 0;
|
||||
- delay = delayi = pdelay + cdelay;
|
||||
if (play->buf != capt->buf)
|
||||
- delay += capt->buf_count;
|
||||
- delay += play->buf_count;
|
||||
+ cdelay += capt->buf_count;
|
||||
+ pdelay += play->buf_count;
|
||||
#ifdef USE_SAMPLERATE
|
||||
- delay += loop->src_out_frames;
|
||||
- delayi += loop->src_out_frames;
|
||||
+ pdelay += loop->src_out_frames;
|
||||
#endif
|
||||
-#if 0
|
||||
- printf("s: cdelay = %li, pdelay = %li, delay = %li, delayi = %li, fill = %li, src_out = %li\n",
|
||||
- (long)cdelay, (long)pdelay, (long)delay,
|
||||
- (long)delayi, (long)fill, (long)loop->src_out_frames);
|
||||
- printf("s: cbufcount = %li, pbufcount = %li\n", (long)capt->buf_count, (long)play->buf_count);
|
||||
-#endif
|
||||
- if (delayi > fill) {
|
||||
+ cdelay1 = cdelay * capt->pitch;
|
||||
+ pdelay1 = pdelay * play->pitch;
|
||||
+ delay1 = cdelay1 + pdelay1;
|
||||
+ capt->total_queued = 0;
|
||||
+ play->total_queued = 0;
|
||||
+ loop->total_queued_count = 0;
|
||||
+ loop->pitch_diff = loop->pitch_diff_min = loop->pitch_diff_max = 0;
|
||||
+ if (verbose > 6) {
|
||||
+ snd_output_printf(loop->output,
|
||||
+ "sync: cdelay=%li(%li), pdelay=%li(%li), fill=%li (delay=%li), src_out=%li\n",
|
||||
+ (long)cdelay, (long)cdelay1, (long)pdelay, (long)pdelay1,
|
||||
+ (long)fill, (long)delay1, (long)loop->src_out_frames);
|
||||
+ snd_output_printf(loop->output,
|
||||
+ "sync: cbufcount=%li, pbufcount=%li\n",
|
||||
+ (long)capt->buf_count, (long)play->buf_count);
|
||||
+ }
|
||||
+ if (delay1 > fill && capt->counter > 0) {
|
||||
if ((err = snd_pcm_drop(capt->handle)) < 0)
|
||||
return err;
|
||||
if ((err = snd_pcm_prepare(capt->handle)) < 0)
|
||||
return err;
|
||||
if ((err = snd_pcm_start(capt->handle)) < 0)
|
||||
return err;
|
||||
- remove_samples(loop, 1, delayi - fill);
|
||||
+ diff = remove_samples(loop, 1, (delay1 - fill) / capt->pitch);
|
||||
+ if (verbose > 6)
|
||||
+ snd_output_printf(loop->output,
|
||||
+ "sync: capt stop removed %li samples\n", (long)diff);
|
||||
goto __again;
|
||||
}
|
||||
- if (delay > fill) {
|
||||
- diff = fill > delayi ? play->buf_count - (fill - delayi) : 0;
|
||||
- delay -= remove_samples(loop, 0, diff);
|
||||
+ if (delay1 > fill) {
|
||||
+ diff = (delay1 - fill) / play->pitch;
|
||||
+ if (diff > play->buf_count)
|
||||
+ diff = play->buf_count;
|
||||
+ if (verbose > 6)
|
||||
+ snd_output_printf(loop->output,
|
||||
+ "sync: removing %li playback samples, delay1=%li\n", (long)diff, (long)delay1);
|
||||
+ diff = remove_samples(loop, 0, diff);
|
||||
+ pdelay -= diff;
|
||||
+ pdelay1 = pdelay * play->pitch;
|
||||
+ delay1 = cdelay1 + pdelay1;
|
||||
+ if (verbose > 6)
|
||||
+ snd_output_printf(loop->output,
|
||||
+ "sync: removed %li playback samples, delay1=%li\n", (long)diff, (long)delay1);
|
||||
}
|
||||
- if (delay > fill) {
|
||||
- diff = fill > delayi ? capt->buf_count - (fill - delayi) : 0;
|
||||
- delay -= remove_samples(loop, 1, diff);
|
||||
+ if (delay1 > fill) {
|
||||
+ diff = (delay1 - fill) / capt->pitch;
|
||||
+ if (diff > capt->buf_count)
|
||||
+ diff = capt->buf_count;
|
||||
+ if (verbose > 6)
|
||||
+ snd_output_printf(loop->output,
|
||||
+ "sync: removing %li captured samples, delay1=%li\n", (long)diff, (long)delay1);
|
||||
+ diff -= remove_samples(loop, 1, diff);
|
||||
+ cdelay -= diff;
|
||||
+ cdelay1 = cdelay * capt->pitch;
|
||||
+ delay1 = cdelay1 + pdelay1;
|
||||
+ if (verbose > 6)
|
||||
+ snd_output_printf(loop->output,
|
||||
+ "sync: removed %li captured samples, delay1=%li\n", (long)diff, (long)delay1);
|
||||
}
|
||||
if (play->xrun_pending) {
|
||||
play->xrun_pending = 0;
|
||||
- if (fill > delay && play->buf_count < fill - delay) {
|
||||
- diff = fill - delay - play->buf_count;
|
||||
+ diff = (fill - delay1) / play->pitch;
|
||||
+ if (verbose > 6)
|
||||
+ snd_output_printf(loop->output,
|
||||
+ "sync: xrun_pending, silence filling %li / buf_count=%li\n", (long)diff, play->buf_count);
|
||||
+ if (fill > delay1 && play->buf_count < diff) {
|
||||
+ diff = diff - play->buf_count;
|
||||
+ if (verbose > 6)
|
||||
+ snd_output_printf(loop->output,
|
||||
+ "sync: playback silence added %li samples\n", (long)diff);
|
||||
play->buf_pos -= diff;
|
||||
play->buf_pos %= play->buf_size;
|
||||
if ((err = snd_pcm_format_set_silence(play->format, play->buf + play->buf_pos * play->channels, diff)) < 0)
|
||||
@@ -728,18 +768,43 @@ static int xrun_sync(struct loopback *loop)
|
||||
}
|
||||
if ((err = snd_pcm_prepare(play->handle)) < 0) {
|
||||
logit(LOG_CRIT, "%s prepare failed: %s\n", play->id, snd_strerror(err));
|
||||
+
|
||||
return err;
|
||||
}
|
||||
- delayi = writeit(play);
|
||||
- if (delayi > diff)
|
||||
- buf_remove(loop, delayi - diff);
|
||||
+ delay1 = writeit(play);
|
||||
+ if (verbose > 6)
|
||||
+ snd_output_printf(loop->output,
|
||||
+ "sync: playback wrote %li samples\n", (long)delay1);
|
||||
+ if (delay1 > diff) {
|
||||
+ buf_remove(loop, delay1 - diff);
|
||||
+ if (verbose > 6)
|
||||
+ snd_output_printf(loop->output,
|
||||
+ "sync: playback buf_remove %li samples\n", (long)(delay1 - diff));
|
||||
+ }
|
||||
if ((err = snd_pcm_start(play->handle)) < 0) {
|
||||
logit(LOG_CRIT, "%s start failed: %s\n", play->id, snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
- if (verbose > 5)
|
||||
+ if (verbose > 5) {
|
||||
snd_output_printf(loop->output, "%s: xrun sync ok\n", loop->id);
|
||||
+ if (verbose > 6) {
|
||||
+ if (snd_pcm_delay(capt->handle, &cdelay) < 0)
|
||||
+ cdelay = -1;
|
||||
+ if (snd_pcm_delay(play->handle, &pdelay) < 0)
|
||||
+ pdelay = -1;
|
||||
+ if (play->buf != capt->buf)
|
||||
+ cdelay += capt->buf_count;
|
||||
+ pdelay += play->buf_count;
|
||||
+#ifdef USE_SAMPLERATE
|
||||
+ pdelay += loop->src_out_frames;
|
||||
+#endif
|
||||
+ cdelay1 = cdelay * capt->pitch;
|
||||
+ pdelay1 = pdelay * play->pitch;
|
||||
+ delay1 = cdelay1 + pdelay1;
|
||||
+ snd_output_printf(loop->output, "%s: sync verify: %li\n", loop->id, delay1);
|
||||
+ }
|
||||
+ }
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -778,6 +843,46 @@ static int set_rate_shift(struct loopback_handle *lhandle, double pitch)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+void update_pitch(struct loopback *loop)
|
||||
+{
|
||||
+ double pitch = loop->pitch;
|
||||
+
|
||||
+#ifdef USE_SAMPLERATE
|
||||
+ if (loop->sync == SYNC_TYPE_SAMPLERATE) {
|
||||
+ loop->src_data.src_ratio = (double)1.0 / (pitch *
|
||||
+ loop->play->pitch * loop->capt->pitch);
|
||||
+ if (verbose > 2)
|
||||
+ snd_output_printf(loop->output, "%s: Samplerate src_ratio update1: %.8f\n", loop->id, loop->src_data.src_ratio);
|
||||
+ } else
|
||||
+#endif
|
||||
+ if (loop->sync == SYNC_TYPE_CAPTRATESHIFT) {
|
||||
+ set_rate_shift(loop->capt, pitch);
|
||||
+#ifdef USE_SAMPLERATE
|
||||
+ if (loop->use_samplerate) {
|
||||
+ loop->src_data.src_ratio =
|
||||
+ (double)1.0 /
|
||||
+ (loop->play->pitch * loop->capt->pitch);
|
||||
+ if (verbose > 2)
|
||||
+ snd_output_printf(loop->output, "%s: Samplerate src_ratio update2: %.8f\n", loop->id, loop->src_data.src_ratio);
|
||||
+ }
|
||||
+#endif
|
||||
+ }
|
||||
+ else if (loop->sync == SYNC_TYPE_PLAYRATESHIFT) {
|
||||
+ set_rate_shift(loop->play, pitch);
|
||||
+#ifdef USE_SAMPLERATE
|
||||
+ if (loop->use_samplerate) {
|
||||
+ loop->src_data.src_ratio =
|
||||
+ (double)1.0 /
|
||||
+ (loop->play->pitch * loop->capt->pitch);
|
||||
+ if (verbose > 2)
|
||||
+ snd_output_printf(loop->output, "%s: Samplerate src_ratio update3: %.8f\n", loop->id, loop->src_data.src_ratio);
|
||||
+ }
|
||||
+#endif
|
||||
+ }
|
||||
+ if (verbose)
|
||||
+ snd_output_printf(loop->output, "New pitch for %s: %.8f (min/max samples = %li/%li)\n", loop->id, pitch, loop->pitch_diff_min, loop->pitch_diff_max);
|
||||
+}
|
||||
+
|
||||
static int get_active(struct loopback_handle *lhandle)
|
||||
{
|
||||
int err;
|
||||
@@ -1002,6 +1107,8 @@ int pcmjob_init(struct loopback *loop)
|
||||
#ifdef USE_SAMPLERATE
|
||||
if (loop->sync == SYNC_TYPE_AUTO && loop->src_enable)
|
||||
loop->sync = SYNC_TYPE_SAMPLERATE;
|
||||
+#else
|
||||
+ loop->src_enable = 0;
|
||||
#endif
|
||||
if (loop->sync == SYNC_TYPE_AUTO)
|
||||
loop->sync = SYNC_TYPE_SIMPLE;
|
||||
@@ -1035,8 +1142,9 @@ int pcmjob_init(struct loopback *loop)
|
||||
static void freeloop(struct loopback *loop)
|
||||
{
|
||||
#ifdef USE_SAMPLERATE
|
||||
- if (loop->src_enable) {
|
||||
- src_delete(loop->src_state);
|
||||
+ if (loop->use_samplerate) {
|
||||
+ if (loop->src_state)
|
||||
+ src_delete(loop->src_state);
|
||||
loop->src_state = NULL;
|
||||
free(loop->src_data.data_in);
|
||||
loop->src_data.data_in = NULL;
|
||||
@@ -1078,6 +1186,7 @@ static void lhandle_start(struct loopback_handle *lhandle)
|
||||
lhandle->buf_pos = 0;
|
||||
lhandle->buf_count = 0;
|
||||
lhandle->counter = 0;
|
||||
+ lhandle->total_queued = 0;
|
||||
}
|
||||
|
||||
int pcmjob_start(struct loopback *loop)
|
||||
@@ -1098,7 +1207,7 @@ int pcmjob_start(struct loopback *loop)
|
||||
err = get_rate(loop->capt);
|
||||
if (err < 0)
|
||||
goto __error;
|
||||
- loop->play->rate = loop->capt->rate = err;
|
||||
+ loop->play->rate_req = loop->capt->rate_req = err;
|
||||
err = get_channels(loop->capt);
|
||||
if (err < 0)
|
||||
goto __error;
|
||||
@@ -1107,6 +1216,7 @@ int pcmjob_start(struct loopback *loop)
|
||||
loop->pollfd_count = loop->play->ctl_pollfd_count +
|
||||
loop->capt->ctl_pollfd_count;
|
||||
loop->reinit = 0;
|
||||
+ loop->use_samplerate = 0;
|
||||
loop->latency = loop->latency_req;
|
||||
if (loop->latency == 0)
|
||||
loop->latency = time_to_frames(loop->play,
|
||||
@@ -1114,7 +1224,7 @@ int pcmjob_start(struct loopback *loop)
|
||||
if ((err = setparams(loop, loop->latency/2)) < 0)
|
||||
goto __error;
|
||||
if (verbose)
|
||||
- showlatency(loop, loop->latency, loop->play->rate);
|
||||
+ showlatency(loop, loop->latency, loop->play->rate_req);
|
||||
if (loop->play->access == loop->capt->access &&
|
||||
loop->play->format == loop->capt->format &&
|
||||
loop->play->rate == loop->capt->rate &&
|
||||
@@ -1142,6 +1252,10 @@ int pcmjob_start(struct loopback *loop)
|
||||
goto __error;
|
||||
if ((err = init_handle(loop->capt, 1)) < 0)
|
||||
goto __error;
|
||||
+ if (loop->play->rate_req != loop->play->rate)
|
||||
+ loop->use_samplerate = 1;
|
||||
+ if (loop->capt->rate_req != loop->capt->rate)
|
||||
+ loop->use_samplerate = 1;
|
||||
}
|
||||
if ((err = snd_pcm_poll_descriptors_count(loop->play->handle)) < 0)
|
||||
goto __error;
|
||||
@@ -1152,7 +1266,22 @@ int pcmjob_start(struct loopback *loop)
|
||||
loop->capt->pollfd_count = err;
|
||||
loop->pollfd_count += err;
|
||||
#ifdef USE_SAMPLERATE
|
||||
- if (loop->sync == SYNC_TYPE_SAMPLERATE) {
|
||||
+ if (loop->sync == SYNC_TYPE_SAMPLERATE)
|
||||
+ loop->use_samplerate = 1;
|
||||
+ if (loop->use_samplerate && !loop->src_enable) {
|
||||
+ logit(LOG_CRIT, "samplerate conversion required but disabled\n");
|
||||
+ loop->use_samplerate = 0;
|
||||
+ err = -EIO;
|
||||
+ goto __error;
|
||||
+ }
|
||||
+ if (loop->use_samplerate) {
|
||||
+ if (loop->capt->format != SND_PCM_FORMAT_S16 ||
|
||||
+ loop->play->format != SND_PCM_FORMAT_S16) {
|
||||
+ logit(LOG_CRIT, "samplerate conversion supports only S16_LE format (%i, %i)\n", loop->play->format, loop->capt->format);
|
||||
+ loop->use_samplerate = 0;
|
||||
+ err = -EIO;
|
||||
+ goto __error;
|
||||
+ }
|
||||
loop->src_state = src_new(loop->src_converter_type,
|
||||
loop->play->channels, &err);
|
||||
loop->src_data.data_in = calloc(1, sizeof(float)*loop->capt->channels*loop->capt->buf_size);
|
||||
@@ -1173,7 +1302,7 @@ int pcmjob_start(struct loopback *loop)
|
||||
loop->src_state = NULL;
|
||||
}
|
||||
#else
|
||||
- if (loop->sync == SYNC_TYPE_SAMPLERATE) {
|
||||
+ if (loop->sync == SYNC_TYPE_SAMPLERATE || loop->use_samplerate) {
|
||||
logit(LOG_CRIT, "alsaloop is compiled without libsamplerate support\n");
|
||||
err = -EIO;
|
||||
goto __error;
|
||||
@@ -1195,12 +1324,12 @@ int pcmjob_start(struct loopback *loop)
|
||||
logit(LOG_CRIT, "%s: silence error\n", loop->id);
|
||||
goto __error;
|
||||
}
|
||||
- loop->pitch = 1;
|
||||
+ loop->pitch = 1.0;
|
||||
+ update_pitch(loop);
|
||||
loop->pitch_delta = 1.0 / ((double)loop->capt->rate * 4);
|
||||
- loop->total_queued = 0;
|
||||
loop->total_queued_count = 0;
|
||||
loop->pitch_diff = 0;
|
||||
- count = get_whole_latency(loop);
|
||||
+ count = get_whole_latency(loop) / loop->play->pitch;
|
||||
loop->play->buf_count = count;
|
||||
if (loop->play->buf == loop->capt->buf)
|
||||
loop->capt->buf_pos = count;
|
||||
@@ -1277,19 +1406,14 @@ int pcmjob_pollfds_init(struct loopback *loop, struct pollfd *fds)
|
||||
return idx;
|
||||
}
|
||||
|
||||
-static snd_pcm_sframes_t get_queued_samples(struct loopback *loop)
|
||||
+static snd_pcm_sframes_t get_queued_playback_samples(struct loopback *loop)
|
||||
{
|
||||
- snd_pcm_sframes_t pdelay, cdelay, delay;
|
||||
+ snd_pcm_sframes_t delay;
|
||||
int err;
|
||||
|
||||
- if ((err = snd_pcm_delay(loop->play->handle, &pdelay)) < 0)
|
||||
- return 0;
|
||||
- if ((err = snd_pcm_delay(loop->capt->handle, &cdelay)) < 0)
|
||||
+ if ((err = snd_pcm_delay(loop->play->handle, &delay)) < 0)
|
||||
return 0;
|
||||
- loop->play->last_delay = pdelay;
|
||||
- loop->capt->last_delay = cdelay;
|
||||
- delay = pdelay + cdelay;
|
||||
- delay += loop->capt->buf_count;
|
||||
+ loop->play->last_delay = delay;
|
||||
delay += loop->play->buf_count;
|
||||
#ifdef USE_SAMPLERATE
|
||||
delay += loop->src_out_frames;
|
||||
@@ -1297,6 +1421,18 @@ static snd_pcm_sframes_t get_queued_samples(struct loopback *loop)
|
||||
return delay;
|
||||
}
|
||||
|
||||
+static snd_pcm_sframes_t get_queued_capture_samples(struct loopback *loop)
|
||||
+{
|
||||
+ snd_pcm_sframes_t delay;
|
||||
+ int err;
|
||||
+
|
||||
+ if ((err = snd_pcm_delay(loop->capt->handle, &delay)) < 0)
|
||||
+ return 0;
|
||||
+ loop->capt->last_delay = delay;
|
||||
+ delay += loop->capt->buf_count;
|
||||
+ return delay;
|
||||
+}
|
||||
+
|
||||
static int ctl_event_check(snd_ctl_elem_value_t *val, snd_ctl_event_t *ev)
|
||||
{
|
||||
snd_ctl_elem_id_t *id1, *id2;
|
||||
@@ -1363,7 +1499,6 @@ int pcmjob_pollfds_handle(struct loopback *loop, struct pollfd *fds)
|
||||
struct loopback_handle *capt = loop->capt;
|
||||
unsigned short prevents, crevents, events;
|
||||
snd_pcm_uframes_t ccount, pcount;
|
||||
- snd_pcm_sframes_t queued;
|
||||
int err, loopcount = 10, idx;
|
||||
|
||||
if (verbose > 11)
|
||||
@@ -1463,8 +1598,8 @@ int pcmjob_pollfds_handle(struct loopback *loop, struct pollfd *fds)
|
||||
play->counter >= play->sync_point &&
|
||||
capt->counter >= play->sync_point) {
|
||||
snd_pcm_sframes_t diff, lat = get_whole_latency(loop);
|
||||
- double pitch;
|
||||
- diff = ((double)loop->total_queued /
|
||||
+ diff = ((double)(((double)play->total_queued * play->pitch) +
|
||||
+ ((double)capt->total_queued * capt->pitch)) /
|
||||
(double)loop->total_queued_count) - lat;
|
||||
/* FIXME: this algorithm may be slightly better */
|
||||
if (verbose > 3)
|
||||
@@ -1472,12 +1607,12 @@ int pcmjob_pollfds_handle(struct loopback *loop, struct pollfd *fds)
|
||||
if (diff > 0) {
|
||||
if (diff == loop->pitch_diff)
|
||||
loop->pitch += loop->pitch_delta;
|
||||
- if (diff > loop->pitch_diff)
|
||||
+ else if (diff > loop->pitch_diff)
|
||||
loop->pitch += loop->pitch_delta*2;
|
||||
} else if (diff < 0) {
|
||||
if (diff == loop->pitch_diff)
|
||||
loop->pitch -= loop->pitch_delta;
|
||||
- if (diff < loop->pitch_diff)
|
||||
+ else if (diff < loop->pitch_diff)
|
||||
loop->pitch -= loop->pitch_delta*2;
|
||||
}
|
||||
loop->pitch_diff = diff;
|
||||
@@ -1485,31 +1620,25 @@ int pcmjob_pollfds_handle(struct loopback *loop, struct pollfd *fds)
|
||||
loop->pitch_diff_min = diff;
|
||||
if (loop->pitch_diff_max < diff)
|
||||
loop->pitch_diff_max = diff;
|
||||
- pitch = loop->pitch;
|
||||
-#ifdef USE_SAMPLERATE
|
||||
- if (loop->sync == SYNC_TYPE_SAMPLERATE)
|
||||
- loop->src_data.src_ratio = (double)1.0 / pitch;
|
||||
- else
|
||||
-#endif
|
||||
- if (loop->sync == SYNC_TYPE_CAPTRATESHIFT)
|
||||
- set_rate_shift(capt, pitch);
|
||||
- if (loop->sync == SYNC_TYPE_PLAYRATESHIFT)
|
||||
- set_rate_shift(play, pitch);
|
||||
- if (verbose)
|
||||
- snd_output_printf(loop->output, "New pitch for %s: %.8f (min/max samples = %li/%li)\n", loop->id, pitch, loop->pitch_diff_min, loop->pitch_diff_max);
|
||||
+ update_pitch(loop);
|
||||
play->counter -= play->sync_point;
|
||||
capt->counter -= play->sync_point;
|
||||
- loop->total_queued = 0;
|
||||
+ play->total_queued = 0;
|
||||
+ capt->total_queued = 0;
|
||||
loop->total_queued_count = 0;
|
||||
}
|
||||
if (loop->sync != SYNC_TYPE_NONE) {
|
||||
- queued = get_queued_samples(loop);
|
||||
+ snd_pcm_sframes_t pqueued, cqueued;
|
||||
+ pqueued = get_queued_playback_samples(loop);
|
||||
+ cqueued = get_queued_capture_samples(loop);
|
||||
if (verbose > 4)
|
||||
- snd_output_printf(loop->output, "%s: queued %li samples\n", loop->id, queued);
|
||||
- if (queued > 0) {
|
||||
- loop->total_queued += queued;
|
||||
+ snd_output_printf(loop->output, "%s: queued %li/%li samples\n", loop->id, pqueued, cqueued);
|
||||
+ if (pqueued > 0)
|
||||
+ loop->play->total_queued += pqueued;
|
||||
+ if (cqueued > 0)
|
||||
+ loop->capt->total_queued += cqueued;
|
||||
+ if (pqueued > 0 || cqueued > 0)
|
||||
loop->total_queued_count += 1;
|
||||
- }
|
||||
}
|
||||
if (verbose > 12) {
|
||||
snd_pcm_sframes_t pdelay, cdelay;
|
||||
diff --git a/alsaloop/test.sh b/alsaloop/test.sh
|
||||
index a1d4dbe..fbd40c0 100755
|
||||
--- a/alsaloop/test.sh
|
||||
+++ b/alsaloop/test.sh
|
||||
@@ -6,7 +6,7 @@ CFGFILE="/tmp/alsaloop.test.cfg"
|
||||
|
||||
test1() {
|
||||
echo "TEST1"
|
||||
- $DBG ./alsaloop -C hw:1,0 -P hw:0,0 \
|
||||
+ $DBG ./alsaloop -C hw:1,0 -P plughw:0,0 \
|
||||
--tlatency 50000 \
|
||||
--mixer "name='Master Playback Volume'@name='Master Playback Volume'" \
|
||||
--mixer "name='Master Playback Switch'@name='Master Playback Switch'" \
|
||||
@@ -45,9 +45,19 @@ EOF
|
||||
$DBG ./alsaloop --config $CFGFILE
|
||||
}
|
||||
|
||||
+test4() {
|
||||
+ echo "TEST4"
|
||||
+ $DBG ./alsaloop -C hw:1,0 -P plughw:0,0 -a off -r 11025 \
|
||||
+ --tlatency 50000 \
|
||||
+ --mixer "name='Master Playback Volume'@name='Master Playback Volume'" \
|
||||
+ --mixer "name='Master Playback Switch'@name='Master Playback Switch'" \
|
||||
+ --mixer "name='PCM Playback Volume'"
|
||||
+}
|
||||
+
|
||||
case "$1" in
|
||||
test1) test1 ;;
|
||||
test2) test2 ;;
|
||||
test3) test3 ;;
|
||||
+test4) test4 ;;
|
||||
*) test1 ;;
|
||||
esac
|
||||
--
|
||||
1.7.3.1
|
||||
|
317
0023-alsaloop-Add-OSS-mixer-redirection-support.patch
Normal file
317
0023-alsaloop-Add-OSS-mixer-redirection-support.patch
Normal file
@ -0,0 +1,317 @@
|
||||
From 147a1cc75cf6002eb5ea2983a374d2e84eee8e1d Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Fri, 8 Oct 2010 15:10:23 +0200
|
||||
Subject: [PATCH 23/38] alsaloop: Add OSS mixer redirection support
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
alsaloop/alsaloop.1 | 16 +++++++++++++
|
||||
alsaloop/alsaloop.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++-
|
||||
alsaloop/alsaloop.h | 12 +++++++++-
|
||||
alsaloop/control.c | 48 +++++++++++++++++++++++++++++++++++++-
|
||||
alsaloop/pcmjob.c | 1 +
|
||||
alsaloop/test.sh | 4 ++-
|
||||
6 files changed, 138 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/alsaloop/alsaloop.1 b/alsaloop/alsaloop.1
|
||||
index 66be499..1554b6e 100644
|
||||
--- a/alsaloop/alsaloop.1
|
||||
+++ b/alsaloop/alsaloop.1
|
||||
@@ -153,6 +153,22 @@ Known attributes:
|
||||
numid - control ID numid
|
||||
|
||||
.TP
|
||||
+\fI\-O <ossmixid>\fP | \fI\-\-ossmixer=<midid>\fP
|
||||
+
|
||||
+Redirect mixer control from the OSS Mixer emulation layer (capture card)
|
||||
+to the ALSA layer (capture card). Format of \fIossmixid\fP is
|
||||
+ALSAID[,INDEX]@OSSID:
|
||||
+
|
||||
+ "Master@VOLUME"
|
||||
+ "PCM,1@ALTPCM"
|
||||
+
|
||||
+Known OSS attributes:
|
||||
+
|
||||
+ VOLUME, BASS, TREBLE, SYNTH, PCM, SPEAKER, LINE, MIC, CD, IMIX, ALTPCM,
|
||||
+ RECLEV, IGAIN, OGAIN, LINE1, LINE2, LINE3, DIGITAL1, DIGITAL2, DIGITAL3,
|
||||
+ PHONEIN, PHONEOUT, VIDEO, RADIO, MONITOR
|
||||
+
|
||||
+.TP
|
||||
\fI\-v\fP | \fI\-\-verbose\fP
|
||||
|
||||
Verbose mode. Use multiple times to increase verbosity.
|
||||
diff --git a/alsaloop/alsaloop.c b/alsaloop/alsaloop.c
|
||||
index bbf570e..effa073 100644
|
||||
--- a/alsaloop/alsaloop.c
|
||||
+++ b/alsaloop/alsaloop.c
|
||||
@@ -164,7 +164,9 @@ void help(void)
|
||||
"-a,--slave stream parameters slave mode (0=auto, 1=on, 2=off)\n"
|
||||
"-T,--thread thread number (-1 = create unique)\n"
|
||||
"-m,--mixer redirect mixer, argument is:\n"
|
||||
-" SRC_SLAVE_ID(PLAYBACK)@DST_SLAVE_ID(CAPTURE)\n"
|
||||
+" SRC_SLAVE_ID(PLAYBACK)[@DST_SLAVE_ID(CAPTURE)]\n"
|
||||
+"-O,--ossmixer rescan and redirect oss mixer, argument is:\n"
|
||||
+" ALSA_ID@OSS_ID (for example: \"Master@VOLUME\")\n"
|
||||
"-e,--effect apply an effect (bandpass filter sweep)\n"
|
||||
"-v,--verbose verbose mode (more -v means more verbose)\n"
|
||||
);
|
||||
@@ -266,6 +268,46 @@ static int add_mixers(struct loopback *loop,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int add_oss_mixers(struct loopback *loop,
|
||||
+ char **mixers,
|
||||
+ int mixers_count)
|
||||
+{
|
||||
+ struct loopback_ossmixer *mixer, *last = NULL;
|
||||
+ char *str1, *str2;
|
||||
+
|
||||
+ while (mixers_count > 0) {
|
||||
+ mixer = calloc(1, sizeof(*mixer));
|
||||
+ if (mixer == NULL)
|
||||
+ return -ENOMEM;
|
||||
+ if (last)
|
||||
+ last->next = mixer;
|
||||
+ else
|
||||
+ loop->oss_controls = mixer;
|
||||
+ last = mixer;
|
||||
+ str1 = strchr(*mixers, ',');
|
||||
+ if (str1)
|
||||
+ *str1 = '\0';
|
||||
+ str2 = strchr(str1 ? str1 + 1 : *mixers, '@');
|
||||
+ if (str2)
|
||||
+ *str2 = '\0';
|
||||
+ mixer->alsa_id = strdup(*mixers);
|
||||
+ if (str1)
|
||||
+ mixer->alsa_index = atoi(str1);
|
||||
+ mixer->oss_id = strdup(str2 ? str2 + 1 : *mixers);
|
||||
+ if (mixer->alsa_id == NULL || mixer->oss_id == NULL) {
|
||||
+ logit(LOG_CRIT, "Not enough memory");
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+ if (str1)
|
||||
+ *str1 = ',';
|
||||
+ if (str2)
|
||||
+ *str2 = ',';
|
||||
+ mixers++;
|
||||
+ mixers_count--;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int parse_config_file(const char *file, snd_output_t *output);
|
||||
|
||||
static int parse_config(int argc, char *argv[], snd_output_t *output)
|
||||
@@ -294,6 +336,7 @@ static int parse_config(int argc, char *argv[], snd_output_t *output)
|
||||
{"slave", 1, NULL, 'a'},
|
||||
{"thread", 1, NULL, 'T'},
|
||||
{"mixer", 1, NULL, 'm'},
|
||||
+ {"ossmixer", 1, NULL, 'O'},
|
||||
{NULL, 0, NULL, 0},
|
||||
};
|
||||
int err, morehelp;
|
||||
@@ -318,11 +361,15 @@ static int parse_config(int argc, char *argv[], snd_output_t *output)
|
||||
struct loopback *loop = NULL;
|
||||
char *arg_mixers[MAX_MIXERS];
|
||||
int arg_mixers_count = 0;
|
||||
+ char *arg_ossmixers[MAX_MIXERS];
|
||||
+ int arg_ossmixers_count = 0;
|
||||
|
||||
morehelp = 0;
|
||||
while (1) {
|
||||
int c;
|
||||
- if ((c = getopt_long(argc, argv, "hdg:P:C:l:t:F:f:c:r:s:benvA:S:a:m:T:", long_option, NULL)) < 0)
|
||||
+ if ((c = getopt_long(argc, argv,
|
||||
+ "hdg:P:C:l:t:F:f:c:r:s:benvA:S:a:m:T:O:",
|
||||
+ long_option, NULL)) < 0)
|
||||
break;
|
||||
switch (c) {
|
||||
case 'h':
|
||||
@@ -445,6 +492,13 @@ static int parse_config(int argc, char *argv[], snd_output_t *output)
|
||||
}
|
||||
arg_mixers[arg_mixers_count++] = optarg;
|
||||
break;
|
||||
+ case 'O':
|
||||
+ if (arg_ossmixers_count >= MAX_MIXERS) {
|
||||
+ logit(LOG_CRIT, "Maximum redirected mixer controls reached (max %i)\n", (int)MAX_MIXERS);
|
||||
+ exit(EXIT_FAILURE);
|
||||
+ }
|
||||
+ arg_ossmixers[arg_ossmixers_count++] = optarg;
|
||||
+ break;
|
||||
case 'v':
|
||||
verbose++;
|
||||
break;
|
||||
@@ -490,6 +544,11 @@ static int parse_config(int argc, char *argv[], snd_output_t *output)
|
||||
logit(LOG_CRIT, "Unable to add mixer controls.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
+ err = add_oss_mixers(loop, arg_ossmixers, arg_ossmixers_count);
|
||||
+ if (err < 0) {
|
||||
+ logit(LOG_CRIT, "Unable to add ossmixer controls.\n");
|
||||
+ exit(EXIT_FAILURE);
|
||||
+ }
|
||||
#ifdef USE_SAMPLERATE
|
||||
loop->src_enable = arg_samplerate > 0;
|
||||
if (loop->src_enable)
|
||||
diff --git a/alsaloop/alsaloop.h b/alsaloop/alsaloop.h
|
||||
index 9753c41..366a296 100644
|
||||
--- a/alsaloop/alsaloop.h
|
||||
+++ b/alsaloop/alsaloop.h
|
||||
@@ -65,16 +65,25 @@ struct loopback_control {
|
||||
};
|
||||
|
||||
struct loopback_mixer {
|
||||
- unsigned int skip: 1;
|
||||
+ unsigned int skip:1;
|
||||
struct loopback_control src;
|
||||
struct loopback_control dst;
|
||||
struct loopback_mixer *next;
|
||||
};
|
||||
|
||||
+struct loopback_ossmixer {
|
||||
+ unsigned int skip:1;
|
||||
+ const char *alsa_id;
|
||||
+ int alsa_index;
|
||||
+ const char *oss_id;
|
||||
+ struct loopback_ossmixer *next;
|
||||
+};
|
||||
+
|
||||
struct loopback_handle {
|
||||
struct loopback *loopback;
|
||||
char *device;
|
||||
char *id;
|
||||
+ int card_number;
|
||||
snd_pcm_t *handle;
|
||||
snd_pcm_access_t access;
|
||||
snd_pcm_format_t format;
|
||||
@@ -143,6 +152,7 @@ struct loopback {
|
||||
snd_timestamp_t tstamp_end;
|
||||
/* control mixer */
|
||||
struct loopback_mixer *controls;
|
||||
+ struct loopback_ossmixer *oss_controls;
|
||||
/* sample rate */
|
||||
unsigned int use_samplerate:1;
|
||||
#ifdef USE_SAMPLERATE
|
||||
diff --git a/alsaloop/control.c b/alsaloop/control.c
|
||||
index ade7733..967f1e9 100644
|
||||
--- a/alsaloop/control.c
|
||||
+++ b/alsaloop/control.c
|
||||
@@ -205,6 +205,34 @@ static int copy_value(struct loopback_control *dst,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int oss_set(struct loopback *loop,
|
||||
+ struct loopback_ossmixer *ossmix,
|
||||
+ int enable)
|
||||
+{
|
||||
+ char buf[128], file[128];
|
||||
+ int fd;
|
||||
+
|
||||
+ if (loop->capt->card_number < 0)
|
||||
+ return 0;
|
||||
+ if (!enable) {
|
||||
+ sprintf(buf, "%s \"\" 0\n", ossmix->oss_id);
|
||||
+ } else {
|
||||
+ sprintf(buf, "%s \"%s\" %i\n", ossmix->oss_id, ossmix->alsa_id, ossmix->alsa_index);
|
||||
+ }
|
||||
+ sprintf(file, "/proc/asound/card%i/oss_mixer", loop->capt->card_number);
|
||||
+ if (verbose)
|
||||
+ snd_output_printf(loop->output, "%s: Initialize OSS volume %s: %s", loop->id, file, buf);
|
||||
+ fd = open(file, O_WRONLY);
|
||||
+ if (fd >= 0 && write(fd, buf, strlen(buf)) == strlen(buf)) {
|
||||
+ close(fd);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ if (fd >= 0)
|
||||
+ close(fd);
|
||||
+ logit(LOG_INFO, "%s: Unable to initialize OSS Mixer ID '%s'\n", loop->id, ossmix->oss_id);
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
static int control_init2(struct loopback *loop,
|
||||
struct loopback_mixer *mix)
|
||||
{
|
||||
@@ -280,12 +308,15 @@ static int control_init2(struct loopback *loop,
|
||||
int control_init(struct loopback *loop)
|
||||
{
|
||||
struct loopback_mixer *mix;
|
||||
+ struct loopback_ossmixer *ossmix;
|
||||
int err;
|
||||
|
||||
+ for (ossmix = loop->oss_controls; ossmix; ossmix = ossmix->next)
|
||||
+ oss_set(loop, ossmix, 0);
|
||||
for (mix = loop->controls; mix; mix = mix->next) {
|
||||
err = control_init1(loop->play, &mix->src);
|
||||
if (err < 0) {
|
||||
- logit(LOG_WARNING, "Disabling playback control '%s'\n", id_str(mix->src.id));
|
||||
+ logit(LOG_WARNING, "%s: Disabling playback control '%s'\n", loop->id, id_str(mix->src.id));
|
||||
mix->skip = 1;
|
||||
continue;
|
||||
}
|
||||
@@ -293,22 +324,35 @@ int control_init(struct loopback *loop)
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
+ for (ossmix = loop->oss_controls; ossmix; ossmix = ossmix->next) {
|
||||
+ err = oss_set(loop, ossmix, 1);
|
||||
+ if (err < 0) {
|
||||
+ ossmix->skip = 1;
|
||||
+ logit(LOG_WARNING, "%s: Disabling OSS mixer ID '%s'\n", loop->id, ossmix->oss_id);
|
||||
+ }
|
||||
+ }
|
||||
return 0;
|
||||
}
|
||||
|
||||
int control_done(struct loopback *loop)
|
||||
{
|
||||
struct loopback_mixer *mix;
|
||||
+ struct loopback_ossmixer *ossmix;
|
||||
int err;
|
||||
|
||||
if (loop->capt->ctl == NULL)
|
||||
return 0;
|
||||
+ for (ossmix = loop->oss_controls; ossmix; ossmix = ossmix->next) {
|
||||
+ err = oss_set(loop, ossmix, 0);
|
||||
+ if (err < 0)
|
||||
+ logit(LOG_WARNING, "%s: Unable to remove OSS control '%s'\n", loop->id, ossmix->oss_id);
|
||||
+ }
|
||||
for (mix = loop->controls; mix; mix = mix->next) {
|
||||
if (mix->skip)
|
||||
continue;
|
||||
err = snd_ctl_elem_remove(loop->capt->ctl, mix->dst.id);
|
||||
if (err < 0)
|
||||
- logit(LOG_WARNING, "Unable to remove control '%s': %s\n", id_str(mix->dst.id), snd_strerror(err));
|
||||
+ logit(LOG_WARNING, "%s: Unable to remove control '%s': %s\n", loop->id, id_str(mix->dst.id), snd_strerror(err));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
diff --git a/alsaloop/pcmjob.c b/alsaloop/pcmjob.c
|
||||
index 86917ef..5c2fed0 100644
|
||||
--- a/alsaloop/pcmjob.c
|
||||
+++ b/alsaloop/pcmjob.c
|
||||
@@ -1022,6 +1022,7 @@ static int openit(struct loopback_handle *lhandle)
|
||||
device = snd_pcm_info_get_device(info);
|
||||
subdevice = snd_pcm_info_get_subdevice(info);
|
||||
snd_pcm_info_free(info);
|
||||
+ lhandle->card_number = card;
|
||||
lhandle->ctl = NULL;
|
||||
if (card >= 0) {
|
||||
char name[16];
|
||||
diff --git a/alsaloop/test.sh b/alsaloop/test.sh
|
||||
index fbd40c0..13a5ba7 100755
|
||||
--- a/alsaloop/test.sh
|
||||
+++ b/alsaloop/test.sh
|
||||
@@ -10,7 +10,9 @@ test1() {
|
||||
--tlatency 50000 \
|
||||
--mixer "name='Master Playback Volume'@name='Master Playback Volume'" \
|
||||
--mixer "name='Master Playback Switch'@name='Master Playback Switch'" \
|
||||
- --mixer "name='PCM Playback Volume'"
|
||||
+ --mixer "name='PCM Playback Volume'" \
|
||||
+ --ossmixer "Master@VOLUME" \
|
||||
+ --ossmixer "PCM@PCM"
|
||||
}
|
||||
|
||||
test2() {
|
||||
--
|
||||
1.7.3.1
|
||||
|
227
0024-alsaloop-Fix-command-line-parsing-and-pollfd-initial.patch
Normal file
227
0024-alsaloop-Fix-command-line-parsing-and-pollfd-initial.patch
Normal file
@ -0,0 +1,227 @@
|
||||
From e77983d3c55a7822e2151dfd60d9a20ec2023c9f Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Fri, 8 Oct 2010 22:23:05 +0200
|
||||
Subject: [PATCH 24/38] alsaloop: Fix command-line parsing and pollfd initialization
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
alsaloop/alsaloop.c | 28 ++++++++++++++++++++--------
|
||||
alsaloop/control.c | 4 ++++
|
||||
alsaloop/pcmjob.c | 24 +++++++++++++-----------
|
||||
alsaloop/test.sh | 18 +++++++++++++++++-
|
||||
4 files changed, 54 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/alsaloop/alsaloop.c b/alsaloop/alsaloop.c
|
||||
index effa073..97b00d5 100644
|
||||
--- a/alsaloop/alsaloop.c
|
||||
+++ b/alsaloop/alsaloop.c
|
||||
@@ -47,6 +47,8 @@ int daemonize = 0;
|
||||
int use_syslog = 0;
|
||||
struct loopback **loopbacks = NULL;
|
||||
int loopbacks_count = 0;
|
||||
+char **my_argv = NULL;
|
||||
+int my_argc = 0;
|
||||
|
||||
static void my_exit(struct loopback_thread *thread, int exitcode)
|
||||
{
|
||||
@@ -575,9 +577,6 @@ static int parse_config_file(const char *file, snd_output_t *output)
|
||||
int argc, c, err = 0;
|
||||
char **argv;
|
||||
|
||||
- argv = malloc(sizeof(char *) * MAX_ARGS);
|
||||
- if (argv == NULL)
|
||||
- return -ENOMEM;
|
||||
fp = fopen(file, "r");
|
||||
if (fp == NULL) {
|
||||
logit(LOG_CRIT, "Unable to open file '%s': %s\n", file, strerror(errno));
|
||||
@@ -587,8 +586,13 @@ static int parse_config_file(const char *file, snd_output_t *output)
|
||||
if (fgets(line, sizeof(line)-1, fp) == NULL)
|
||||
break;
|
||||
line[sizeof(line)-1] = '\0';
|
||||
+ my_argv = realloc(my_argv, my_argc + MAX_ARGS * sizeof(char *));
|
||||
+ if (my_argv == NULL)
|
||||
+ return -ENOMEM;
|
||||
+ argv = my_argv + my_argc;
|
||||
argc = 0;
|
||||
argv[argc++] = strdup("<prog>");
|
||||
+ my_argc++;
|
||||
str = line;
|
||||
while (*str) {
|
||||
ptr = word;
|
||||
@@ -607,25 +611,30 @@ static int parse_config_file(const char *file, snd_output_t *output)
|
||||
*ptr++ = *str++;
|
||||
}
|
||||
if (ptr != word) {
|
||||
+ if (*(ptr-1) == '\n')
|
||||
+ ptr--;
|
||||
*ptr = '\0';
|
||||
+ if (argc >= MAX_ARGS) {
|
||||
+ logit(LOG_CRIT, "Too many arguments.");
|
||||
+ goto __error;
|
||||
+ }
|
||||
argv[argc++] = strdup(word);
|
||||
+ my_argc++;
|
||||
}
|
||||
}
|
||||
/* erase runtime variables for getopt */
|
||||
optarg = NULL;
|
||||
optind = opterr = 1;
|
||||
- optopt = 63;
|
||||
+ optopt = '?';
|
||||
|
||||
err = parse_config(argc, argv, output);
|
||||
__next:
|
||||
- while (argc > 0)
|
||||
- free(argv[--argc]);
|
||||
if (err < 0)
|
||||
break;
|
||||
err = 0;
|
||||
}
|
||||
+ __error:
|
||||
fclose(fp);
|
||||
- free(argv);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -656,7 +665,7 @@ static void thread_job1(void *_data)
|
||||
pfds_count += thread->loopbacks[i]->pollfd_count;
|
||||
}
|
||||
pfds = calloc(pfds_count, sizeof(struct pollfd));
|
||||
- if (pfds == NULL) {
|
||||
+ if (pfds == NULL || pfds_count <= 0) {
|
||||
logit(LOG_CRIT, "Poll FDs allocation failed.\n");
|
||||
my_exit(thread, EXIT_FAILURE);
|
||||
}
|
||||
@@ -723,6 +732,9 @@ int main(int argc, char *argv[])
|
||||
logit(LOG_CRIT, "Unable to parse arguments or configuration...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
+ while (my_argc > 0)
|
||||
+ free(my_argv[--my_argc]);
|
||||
+ free(my_argv);
|
||||
|
||||
if (loopbacks_count <= 0) {
|
||||
logit(LOG_CRIT, "No loopback defined...\n");
|
||||
diff --git a/alsaloop/control.c b/alsaloop/control.c
|
||||
index 967f1e9..8383d79 100644
|
||||
--- a/alsaloop/control.c
|
||||
+++ b/alsaloop/control.c
|
||||
@@ -164,6 +164,10 @@ static int control_init1(struct loopback_handle *lhandle,
|
||||
|
||||
snd_ctl_elem_info_set_id(ctl->info, ctl->id);
|
||||
snd_ctl_elem_value_set_id(ctl->value, ctl->id);
|
||||
+ if (lhandle->ctl == NULL) {
|
||||
+ logit(LOG_WARNING, "Unable to read control info for '%s'\n", id_str(ctl->id));
|
||||
+ return -EIO;
|
||||
+ }
|
||||
err = snd_ctl_elem_info(lhandle->ctl, ctl->info);
|
||||
if (err < 0) {
|
||||
logit(LOG_WARNING, "Unable to read control info '%s': %s\n", id_str(ctl->id), snd_strerror(err));
|
||||
diff --git a/alsaloop/pcmjob.c b/alsaloop/pcmjob.c
|
||||
index 5c2fed0..df835f0 100644
|
||||
--- a/alsaloop/pcmjob.c
|
||||
+++ b/alsaloop/pcmjob.c
|
||||
@@ -1195,6 +1195,16 @@ int pcmjob_start(struct loopback *loop)
|
||||
snd_pcm_uframes_t count;
|
||||
int err;
|
||||
|
||||
+ loop->pollfd_count = loop->play->ctl_pollfd_count +
|
||||
+ loop->capt->ctl_pollfd_count;
|
||||
+ if ((err = snd_pcm_poll_descriptors_count(loop->play->handle)) < 0)
|
||||
+ goto __error;
|
||||
+ loop->play->pollfd_count = err;
|
||||
+ loop->pollfd_count += err;
|
||||
+ if ((err = snd_pcm_poll_descriptors_count(loop->capt->handle)) < 0)
|
||||
+ goto __error;
|
||||
+ loop->capt->pollfd_count = err;
|
||||
+ loop->pollfd_count += err;
|
||||
if (loop->slave == SLAVE_TYPE_ON) {
|
||||
err = get_active(loop->capt);
|
||||
if (err < 0)
|
||||
@@ -1214,8 +1224,6 @@ int pcmjob_start(struct loopback *loop)
|
||||
goto __error;
|
||||
loop->play->channels = loop->capt->channels = err;
|
||||
}
|
||||
- loop->pollfd_count = loop->play->ctl_pollfd_count +
|
||||
- loop->capt->ctl_pollfd_count;
|
||||
loop->reinit = 0;
|
||||
loop->use_samplerate = 0;
|
||||
loop->latency = loop->latency_req;
|
||||
@@ -1258,14 +1266,6 @@ int pcmjob_start(struct loopback *loop)
|
||||
if (loop->capt->rate_req != loop->capt->rate)
|
||||
loop->use_samplerate = 1;
|
||||
}
|
||||
- if ((err = snd_pcm_poll_descriptors_count(loop->play->handle)) < 0)
|
||||
- goto __error;
|
||||
- loop->play->pollfd_count = err;
|
||||
- loop->pollfd_count += err;
|
||||
- if ((err = snd_pcm_poll_descriptors_count(loop->capt->handle)) < 0)
|
||||
- goto __error;
|
||||
- loop->capt->pollfd_count = err;
|
||||
- loop->pollfd_count += err;
|
||||
#ifdef USE_SAMPLERATE
|
||||
if (loop->sync == SYNC_TYPE_SAMPLERATE)
|
||||
loop->use_samplerate = 1;
|
||||
@@ -1463,9 +1463,11 @@ static int handle_ctl_events(struct loopback_handle *lhandle,
|
||||
if (lhandle == lhandle->loopback->play)
|
||||
goto __ctl_check;
|
||||
if (verbose > 6)
|
||||
- snd_output_printf(lhandle->loopback->output, "ctl event!!!! %s\n", snd_ctl_event_elem_get_name(ev));
|
||||
+ snd_output_printf(lhandle->loopback->output, "%s: ctl event!!!! %s\n", lhandle->id, snd_ctl_event_elem_get_name(ev));
|
||||
if (ctl_event_check(lhandle->ctl_active, ev)) {
|
||||
err = get_active(lhandle);
|
||||
+ if (verbose > 7)
|
||||
+ snd_output_printf(lhandle->loopback->output, "%s: ctl event active %i\n", lhandle->id, err);
|
||||
if (err != lhandle->loopback->running)
|
||||
goto __restart;
|
||||
} else if (ctl_event_check(lhandle->ctl_format, ev)) {
|
||||
diff --git a/alsaloop/test.sh b/alsaloop/test.sh
|
||||
index 13a5ba7..91f4cbc 100755
|
||||
--- a/alsaloop/test.sh
|
||||
+++ b/alsaloop/test.sh
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#DBG="gdb --args "
|
||||
#DBG="strace"
|
||||
+#DBG="valgrind --leak-check=full"
|
||||
CFGFILE="/tmp/alsaloop.test.cfg"
|
||||
|
||||
test1() {
|
||||
@@ -35,7 +36,8 @@ cat > $CFGFILE <<EOF
|
||||
-C hw:1,0,0 -P plug:dmix:0 --tlatency 50000 --thread 0 \
|
||||
--mixer "name='Master Playback Volume'@name='Master Playback Volume'" \
|
||||
--mixer "name='Master Playback Switch'@name='Master Playback Switch'" \
|
||||
- --mixer "name='PCM Playback Volume'"
|
||||
+ --mixer "name='PCM Playback Volume'" \
|
||||
+ --ossmixer "name=Master@VOLUME"
|
||||
-C hw:1,0,1 -P plug:dmix:0 --tlatency 50000 --thread 1
|
||||
-C hw:1,0,2 -P plug:dmix:0 --tlatency 50000 --thread 2
|
||||
-C hw:1,0,3 -P plug:dmix:0 --tlatency 50000 --thread 3
|
||||
@@ -56,10 +58,24 @@ test4() {
|
||||
--mixer "name='PCM Playback Volume'"
|
||||
}
|
||||
|
||||
+test5() {
|
||||
+ echo "TEST5"
|
||||
+cat > $CFGFILE <<EOF
|
||||
+-C hw:1,0,0 -P plughw:0,0 --tlatency 50000 --thread 1 \
|
||||
+ --mixer "name='Master Playback Volume'@name='Master Playback Volume'" \
|
||||
+ --mixer "name='Master Playback Switch'@name='Master Playback Switch'" \
|
||||
+ --mixer "name='PCM Playback Volume'" \
|
||||
+ --ossmixer "name=Master@VOLUME"
|
||||
+-C hw:1,0,1 -P plughw:0,1 --tlatency 50000 --thread 2
|
||||
+EOF
|
||||
+ $DBG ./alsaloop --config $CFGFILE
|
||||
+}
|
||||
+
|
||||
case "$1" in
|
||||
test1) test1 ;;
|
||||
test2) test2 ;;
|
||||
test3) test3 ;;
|
||||
test4) test4 ;;
|
||||
+test5) test5 ;;
|
||||
*) test1 ;;
|
||||
esac
|
||||
--
|
||||
1.7.3.1
|
||||
|
449
0025-alsaloop-Fixes-and-added-workaround-option.patch
Normal file
449
0025-alsaloop-Fixes-and-added-workaround-option.patch
Normal file
@ -0,0 +1,449 @@
|
||||
From bee994f509e6829647aa68fd276f5e8821d15445 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Mon, 11 Oct 2010 10:24:14 +0200
|
||||
Subject: [PATCH 25/38] alsaloop: Fixes and added --workaround option
|
||||
|
||||
- added workaround for alsa-lib (pthread configuration parsing issue) -
|
||||
the workaround must be activated manually using ('--workaround serialopen')
|
||||
- fixed avail_min initialization (caused high CPU usage or xruns)
|
||||
- fixed shared buffer initialization (both capture and playback buffers
|
||||
must have equal number of samples in this config)
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
alsaloop/Makefile.am | 1 +
|
||||
alsaloop/alsaloop.c | 9 ++++-
|
||||
alsaloop/alsaloop.h | 3 +
|
||||
alsaloop/pcmjob.c | 111 ++++++++++++++++++++++++++++++++++++++------------
|
||||
alsaloop/test.sh | 26 +++++++-----
|
||||
5 files changed, 112 insertions(+), 38 deletions(-)
|
||||
|
||||
diff --git a/alsaloop/Makefile.am b/alsaloop/Makefile.am
|
||||
index 97d2e6f..f76eafd 100644
|
||||
--- a/alsaloop/Makefile.am
|
||||
+++ b/alsaloop/Makefile.am
|
||||
@@ -1,5 +1,6 @@
|
||||
INCLUDES = -I$(top_srcdir)/include
|
||||
LDADD = -lm
|
||||
+CFLAGS += -D_GNU_SOURCE
|
||||
if HAVE_SAMPLERATE
|
||||
LDADD += -lsamplerate
|
||||
endif
|
||||
diff --git a/alsaloop/alsaloop.c b/alsaloop/alsaloop.c
|
||||
index 97b00d5..3af3dd7 100644
|
||||
--- a/alsaloop/alsaloop.c
|
||||
+++ b/alsaloop/alsaloop.c
|
||||
@@ -43,6 +43,7 @@ struct loopback_thread {
|
||||
};
|
||||
|
||||
int verbose = 0;
|
||||
+int workarounds = 0;
|
||||
int daemonize = 0;
|
||||
int use_syslog = 0;
|
||||
struct loopback **loopbacks = NULL;
|
||||
@@ -171,6 +172,7 @@ void help(void)
|
||||
" ALSA_ID@OSS_ID (for example: \"Master@VOLUME\")\n"
|
||||
"-e,--effect apply an effect (bandpass filter sweep)\n"
|
||||
"-v,--verbose verbose mode (more -v means more verbose)\n"
|
||||
+"-w,--workaround use workaround (serialopen)\n"
|
||||
);
|
||||
printf("\nRecognized sample formats are:");
|
||||
for (k = 0; k < SND_PCM_FORMAT_LAST; ++k) {
|
||||
@@ -339,6 +341,7 @@ static int parse_config(int argc, char *argv[], snd_output_t *output)
|
||||
{"thread", 1, NULL, 'T'},
|
||||
{"mixer", 1, NULL, 'm'},
|
||||
{"ossmixer", 1, NULL, 'O'},
|
||||
+ {"workaround", 1, NULL, 'w'},
|
||||
{NULL, 0, NULL, 0},
|
||||
};
|
||||
int err, morehelp;
|
||||
@@ -370,7 +373,7 @@ static int parse_config(int argc, char *argv[], snd_output_t *output)
|
||||
while (1) {
|
||||
int c;
|
||||
if ((c = getopt_long(argc, argv,
|
||||
- "hdg:P:C:l:t:F:f:c:r:s:benvA:S:a:m:T:O:",
|
||||
+ "hdg:P:C:l:t:F:f:c:r:s:benvA:S:a:m:T:O:w:",
|
||||
long_option, NULL)) < 0)
|
||||
break;
|
||||
switch (c) {
|
||||
@@ -504,6 +507,10 @@ static int parse_config(int argc, char *argv[], snd_output_t *output)
|
||||
case 'v':
|
||||
verbose++;
|
||||
break;
|
||||
+ case 'w':
|
||||
+ if (strcasecmp(optarg, "serialopen") == 0)
|
||||
+ workarounds |= WORKAROUND_SERIALOPEN;
|
||||
+ break;
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/alsaloop/alsaloop.h b/alsaloop/alsaloop.h
|
||||
index 366a296..6c4f40a 100644
|
||||
--- a/alsaloop/alsaloop.h
|
||||
+++ b/alsaloop/alsaloop.h
|
||||
@@ -40,6 +40,8 @@ enum {
|
||||
#define FILE_CWRITE "/tmp/alsaloop.craw"
|
||||
#endif
|
||||
|
||||
+#define WORKAROUND_SERIALOPEN (1<<0)
|
||||
+
|
||||
typedef enum _sync_type {
|
||||
SYNC_TYPE_NONE = 0,
|
||||
SYNC_TYPE_SIMPLE, /* add or remove samples */
|
||||
@@ -171,6 +173,7 @@ struct loopback {
|
||||
};
|
||||
|
||||
extern int verbose;
|
||||
+extern int workarounds;
|
||||
extern int use_syslog;
|
||||
|
||||
#define logit(priority, fmt, args...) do { \
|
||||
diff --git a/alsaloop/pcmjob.c b/alsaloop/pcmjob.c
|
||||
index df835f0..8b3e568 100644
|
||||
--- a/alsaloop/pcmjob.c
|
||||
+++ b/alsaloop/pcmjob.c
|
||||
@@ -31,9 +31,11 @@
|
||||
#include <sys/time.h>
|
||||
#include <math.h>
|
||||
#include <syslog.h>
|
||||
+#include <pthread.h>
|
||||
#include "alsaloop.h"
|
||||
|
||||
static int set_rate_shift(struct loopback_handle *lhandle, double pitch);
|
||||
+static int get_rate(struct loopback_handle *lhandle);
|
||||
|
||||
#define SYNCTYPE(v) [SYNC_TYPE_##v] = #v
|
||||
|
||||
@@ -56,6 +58,21 @@ static const char *src_types[] = {
|
||||
SRCTYPE(LINEAR)
|
||||
};
|
||||
|
||||
+static pthread_mutex_t pcm_open_mutex =
|
||||
+ PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
|
||||
+
|
||||
+static inline void pcm_open_lock(void)
|
||||
+{
|
||||
+ if (workarounds & WORKAROUND_SERIALOPEN)
|
||||
+ pthread_mutex_lock(&pcm_open_mutex);
|
||||
+}
|
||||
+
|
||||
+static inline void pcm_open_unlock(void)
|
||||
+{
|
||||
+ if (workarounds & WORKAROUND_SERIALOPEN)
|
||||
+ pthread_mutex_unlock(&pcm_open_mutex);
|
||||
+}
|
||||
+
|
||||
static inline snd_pcm_uframes_t get_whole_latency(struct loopback *loop)
|
||||
{
|
||||
return loop->latency;
|
||||
@@ -76,7 +93,7 @@ static int setparams_stream(struct loopback_handle *lhandle,
|
||||
|
||||
err = snd_pcm_hw_params_any(handle, params);
|
||||
if (err < 0) {
|
||||
- logit(LOG_CRIT, "Broken configuration for %s PCM: no configurations available: %s\n", snd_strerror(err), lhandle->id);
|
||||
+ logit(LOG_CRIT, "Broken configuration for %s PCM: no configurations available: %s\n", lhandle->id, snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
err = snd_pcm_hw_params_set_rate_resample(handle, params, lhandle->resample);
|
||||
@@ -153,6 +170,8 @@ static int setparams_bufsize(struct loopback_handle *lhandle,
|
||||
goto __again;
|
||||
}
|
||||
snd_pcm_hw_params_get_buffer_size(params, &periodsize);
|
||||
+ if (verbose > 6)
|
||||
+ snd_output_printf(lhandle->loopback->output, "%s: buffer_size=%li\n", lhandle->id, periodsize);
|
||||
if (lhandle->period_size_req > 0)
|
||||
periodsize = lhandle->period_size_req;
|
||||
else
|
||||
@@ -163,6 +182,8 @@ static int setparams_bufsize(struct loopback_handle *lhandle,
|
||||
goto __again;
|
||||
}
|
||||
snd_pcm_hw_params_get_period_size(params, &periodsize, NULL);
|
||||
+ if (verbose > 6)
|
||||
+ snd_output_printf(lhandle->loopback->output, "%s: period_size=%li\n", lhandle->id, periodsize);
|
||||
if (periodsize != bufsize)
|
||||
bufsize = periodsize;
|
||||
snd_pcm_hw_params_get_buffer_size(params, &buffersize);
|
||||
@@ -175,11 +196,12 @@ static int setparams_bufsize(struct loopback_handle *lhandle,
|
||||
|
||||
static int setparams_set(struct loopback_handle *lhandle,
|
||||
snd_pcm_hw_params_t *params,
|
||||
- snd_pcm_sw_params_t *swparams)
|
||||
+ snd_pcm_sw_params_t *swparams,
|
||||
+ snd_pcm_uframes_t bufsize)
|
||||
{
|
||||
snd_pcm_t *handle = lhandle->handle;
|
||||
int err;
|
||||
- snd_pcm_uframes_t val, val1;
|
||||
+ snd_pcm_uframes_t val, period_size, buffer_size;
|
||||
|
||||
err = snd_pcm_hw_params(handle, params);
|
||||
if (err < 0) {
|
||||
@@ -196,21 +218,29 @@ static int setparams_set(struct loopback_handle *lhandle,
|
||||
logit(LOG_CRIT, "Unable to set start threshold mode for %s: %s\n", lhandle->id, snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
- snd_pcm_hw_params_get_period_size(params, &val, NULL);
|
||||
- snd_pcm_hw_params_get_buffer_size(params, &val1);
|
||||
+ snd_pcm_hw_params_get_period_size(params, &period_size, NULL);
|
||||
+ snd_pcm_hw_params_get_buffer_size(params, &buffer_size);
|
||||
if (lhandle->nblock) {
|
||||
if (lhandle == lhandle->loopback->play) {
|
||||
- val = val1 - (2 * val - 4);
|
||||
+ val = buffer_size - (2 * period_size - 4);
|
||||
} else {
|
||||
val = 4;
|
||||
}
|
||||
+ if (verbose > 6)
|
||||
+ snd_output_printf(lhandle->loopback->output, "%s: avail_min1=%li\n", lhandle->id, val);
|
||||
} else {
|
||||
if (lhandle == lhandle->loopback->play) {
|
||||
- snd_pcm_hw_params_get_buffer_size(params, &val1);
|
||||
- val = val1 - val - val / 2;
|
||||
+ val = bufsize / 2 + bufsize / 4 + bufsize / 8;
|
||||
+ if (val > buffer_size / 4)
|
||||
+ val = buffer_size / 4;
|
||||
+ val = buffer_size - val;
|
||||
} else {
|
||||
- val /= 2;
|
||||
+ val = bufsize / 2;
|
||||
+ if (val > buffer_size / 4)
|
||||
+ val = buffer_size / 4;
|
||||
}
|
||||
+ if (verbose > 6)
|
||||
+ snd_output_printf(lhandle->loopback->output, "%s: avail_min2=%li\n", lhandle->id, val);
|
||||
}
|
||||
err = snd_pcm_sw_params_set_avail_min(handle, swparams, val);
|
||||
if (err < 0) {
|
||||
@@ -256,11 +286,11 @@ static int setparams(struct loopback *loop, snd_pcm_uframes_t bufsize)
|
||||
return err;
|
||||
}
|
||||
|
||||
- if ((err = setparams_set(loop->play, p_params, p_swparams)) < 0) {
|
||||
+ if ((err = setparams_set(loop->play, p_params, p_swparams, bufsize / loop->play->pitch)) < 0) {
|
||||
logit(LOG_CRIT, "Unable to set sw parameters for %s stream: %s\n", loop->play->id, snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
- if ((err = setparams_set(loop->capt, c_params, c_swparams)) < 0) {
|
||||
+ if ((err = setparams_set(loop->capt, c_params, c_swparams, bufsize / loop->capt->pitch)) < 0) {
|
||||
logit(LOG_CRIT, "Unable to set sw parameters for %s stream: %s\n", loop->capt->id, snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
@@ -495,6 +525,12 @@ static int readit(struct loopback_handle *lhandle)
|
||||
int err;
|
||||
|
||||
avail = snd_pcm_avail_update(lhandle->handle);
|
||||
+ if (avail == -EPIPE) {
|
||||
+ return xrun(lhandle);
|
||||
+ } else if (avail == -ESTRPIPE) {
|
||||
+ if ((err = suspend(lhandle)) < 0)
|
||||
+ return err;
|
||||
+ }
|
||||
if (avail > buf_avail(lhandle)) {
|
||||
lhandle->buf_over += avail - buf_avail(lhandle);
|
||||
avail = buf_avail(lhandle);
|
||||
@@ -1008,7 +1044,10 @@ static int openit(struct loopback_handle *lhandle)
|
||||
SND_PCM_STREAM_PLAYBACK :
|
||||
SND_PCM_STREAM_CAPTURE;
|
||||
int err, card, device, subdevice;
|
||||
- if ((err = snd_pcm_open(&lhandle->handle, lhandle->device, stream, SND_PCM_NONBLOCK)) < 0) {
|
||||
+ pcm_open_lock();
|
||||
+ err = snd_pcm_open(&lhandle->handle, lhandle->device, stream, SND_PCM_NONBLOCK);
|
||||
+ pcm_open_unlock();
|
||||
+ if (err < 0) {
|
||||
logit(LOG_CRIT, "%s open error: %s\n", lhandle->id, snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
@@ -1027,7 +1066,9 @@ static int openit(struct loopback_handle *lhandle)
|
||||
if (card >= 0) {
|
||||
char name[16];
|
||||
sprintf(name, "hw:%i", card);
|
||||
+ pcm_open_lock();
|
||||
err = snd_ctl_open(&lhandle->ctl, name, SND_CTL_NONBLOCK);
|
||||
+ pcm_open_unlock();
|
||||
if (err < 0) {
|
||||
logit(LOG_CRIT, "%s [%s] ctl open error: %s\n", lhandle->id, name, snd_strerror(err));
|
||||
lhandle->ctl = NULL;
|
||||
@@ -1254,6 +1295,17 @@ int pcmjob_start(struct loopback *loop)
|
||||
goto __error;
|
||||
}
|
||||
loop->play->buf = nbuf;
|
||||
+ loop->play->buf_size = loop->capt->buf_size;
|
||||
+ } else if (loop->capt->buf_size < loop->play->buf_size) {
|
||||
+ char *nbuf = realloc(loop->capt->buf,
|
||||
+ loop->play->buf_size *
|
||||
+ loop->play->frame_size);
|
||||
+ if (nbuf == NULL) {
|
||||
+ err = -ENOMEM;
|
||||
+ goto __error;
|
||||
+ }
|
||||
+ loop->capt->buf = nbuf;
|
||||
+ loop->capt->buf_size = loop->play->buf_size;
|
||||
}
|
||||
loop->capt->buf = loop->play->buf;
|
||||
} else {
|
||||
@@ -1278,7 +1330,7 @@ int pcmjob_start(struct loopback *loop)
|
||||
if (loop->use_samplerate) {
|
||||
if (loop->capt->format != SND_PCM_FORMAT_S16 ||
|
||||
loop->play->format != SND_PCM_FORMAT_S16) {
|
||||
- logit(LOG_CRIT, "samplerate conversion supports only S16_LE format (%i, %i)\n", loop->play->format, loop->capt->format);
|
||||
+ logit(LOG_CRIT, "samplerate conversion supports only %s format (play=%s, capt=%s)\n", snd_pcm_format_name(SND_PCM_FORMAT_S16), snd_pcm_format_name(loop->play->format), snd_pcm_format_name(loop->capt->format));
|
||||
loop->use_samplerate = 0;
|
||||
err = -EIO;
|
||||
goto __error;
|
||||
@@ -1325,6 +1377,8 @@ int pcmjob_start(struct loopback *loop)
|
||||
logit(LOG_CRIT, "%s: silence error\n", loop->id);
|
||||
goto __error;
|
||||
}
|
||||
+ if (verbose > 4)
|
||||
+ snd_output_printf(loop->output, "%s: capt->buffer_size = %li, play->buffer_size = %li\n", loop->id, loop->capt->buf_size, loop->play->buf_size);
|
||||
loop->pitch = 1.0;
|
||||
update_pitch(loop);
|
||||
loop->pitch_delta = 1.0 / ((double)loop->capt->rate * 4);
|
||||
@@ -1334,8 +1388,13 @@ int pcmjob_start(struct loopback *loop)
|
||||
loop->play->buf_count = count;
|
||||
if (loop->play->buf == loop->capt->buf)
|
||||
loop->capt->buf_pos = count;
|
||||
- if (writeit(loop->play) != count) {
|
||||
- logit(LOG_CRIT, "%s: initial playback fill error\n", loop->id);
|
||||
+ err = writeit(loop->play);
|
||||
+ if (verbose > 4)
|
||||
+ snd_output_printf(loop->output, "%s: silence queued %i samples\n", loop->id, err);
|
||||
+ if (count > loop->play->buffer_size)
|
||||
+ count = loop->play->buffer_size;
|
||||
+ if (err != count) {
|
||||
+ logit(LOG_CRIT, "%s: initial playback fill error (%i/%i/%i)\n", loop->id, err, (int)count, loop->play->buffer_size);
|
||||
err = -EIO;
|
||||
goto __error;
|
||||
}
|
||||
@@ -1511,13 +1570,13 @@ int pcmjob_pollfds_handle(struct loopback *loop, struct pollfd *fds)
|
||||
if (verbose > 12) {
|
||||
snd_pcm_sframes_t pdelay, cdelay;
|
||||
if ((err = snd_pcm_delay(play->handle, &pdelay)) < 0)
|
||||
- snd_output_printf(loop->output, "%s: delay error: %s\n", play->id, snd_strerror(err));
|
||||
+ snd_output_printf(loop->output, "%s: delay error: %s / %li / %li\n", play->id, snd_strerror(err), play->buf_size, play->buf_count);
|
||||
else
|
||||
- snd_output_printf(loop->output, "%s: delay %li\n", play->id, pdelay);
|
||||
+ snd_output_printf(loop->output, "%s: delay %li / %li / %li\n", play->id, pdelay, play->buf_size, play->buf_count);
|
||||
if ((err = snd_pcm_delay(capt->handle, &cdelay)) < 0)
|
||||
- snd_output_printf(loop->output, "%s: delay error: %s\n", capt->id, snd_strerror(err));
|
||||
+ snd_output_printf(loop->output, "%s: delay error: %s / %li / %li\n", capt->id, snd_strerror(err), capt->buf_size, capt->buf_count);
|
||||
else
|
||||
- snd_output_printf(loop->output, "%s: delay %li\n", capt->id, cdelay);
|
||||
+ snd_output_printf(loop->output, "%s: delay %li / %li / %li\n", capt->id, cdelay, capt->buf_size, capt->buf_count);
|
||||
}
|
||||
idx = 0;
|
||||
if (loop->running) {
|
||||
@@ -1570,7 +1629,7 @@ int pcmjob_pollfds_handle(struct loopback *loop, struct pollfd *fds)
|
||||
}
|
||||
if (verbose > 9)
|
||||
snd_output_printf(loop->output, "%s: prevents = 0x%x, crevents = 0x%x\n", loop->id, prevents, crevents);
|
||||
- if (prevents == 0 && crevents == 0)
|
||||
+ if (!loop->running)
|
||||
goto __pcm_end;
|
||||
do {
|
||||
ccount = readit(capt);
|
||||
@@ -1637,22 +1696,22 @@ int pcmjob_pollfds_handle(struct loopback *loop, struct pollfd *fds)
|
||||
if (verbose > 4)
|
||||
snd_output_printf(loop->output, "%s: queued %li/%li samples\n", loop->id, pqueued, cqueued);
|
||||
if (pqueued > 0)
|
||||
- loop->play->total_queued += pqueued;
|
||||
+ play->total_queued += pqueued;
|
||||
if (cqueued > 0)
|
||||
- loop->capt->total_queued += cqueued;
|
||||
+ capt->total_queued += cqueued;
|
||||
if (pqueued > 0 || cqueued > 0)
|
||||
loop->total_queued_count += 1;
|
||||
}
|
||||
if (verbose > 12) {
|
||||
snd_pcm_sframes_t pdelay, cdelay;
|
||||
if ((err = snd_pcm_delay(play->handle, &pdelay)) < 0)
|
||||
- snd_output_printf(loop->output, "%s: end delay error: %s\n", play->id, snd_strerror(err));
|
||||
+ snd_output_printf(loop->output, "%s: end delay error: %s / %li / %li\n", play->id, snd_strerror(err), play->buf_size, play->buf_count);
|
||||
else
|
||||
- snd_output_printf(loop->output, "%s: end delay %li\n", play->id, pdelay);
|
||||
+ snd_output_printf(loop->output, "%s: end delay %li / %li / %li\n", play->id, pdelay, play->buf_size, play->buf_count);
|
||||
if ((err = snd_pcm_delay(capt->handle, &cdelay)) < 0)
|
||||
- snd_output_printf(loop->output, "%s: end delay error: %s\n", capt->id, snd_strerror(err));
|
||||
+ snd_output_printf(loop->output, "%s: end delay error: %s / %li / %li\n", capt->id, snd_strerror(err), capt->buf_size, capt->buf_count);
|
||||
else
|
||||
- snd_output_printf(loop->output, "%s: end delay %li\n", capt->id, cdelay);
|
||||
+ snd_output_printf(loop->output, "%s: end delay %li / %li / %li\n", capt->id, cdelay, capt->buf_size, capt->buf_count);
|
||||
}
|
||||
__pcm_end:
|
||||
if (verbose > 13) {
|
||||
diff --git a/alsaloop/test.sh b/alsaloop/test.sh
|
||||
index 91f4cbc..e3d81b1 100755
|
||||
--- a/alsaloop/test.sh
|
||||
+++ b/alsaloop/test.sh
|
||||
@@ -3,6 +3,7 @@
|
||||
#DBG="gdb --args "
|
||||
#DBG="strace"
|
||||
#DBG="valgrind --leak-check=full"
|
||||
+ARGS=
|
||||
CFGFILE="/tmp/alsaloop.test.cfg"
|
||||
|
||||
test1() {
|
||||
@@ -13,7 +14,8 @@ test1() {
|
||||
--mixer "name='Master Playback Switch'@name='Master Playback Switch'" \
|
||||
--mixer "name='PCM Playback Volume'" \
|
||||
--ossmixer "Master@VOLUME" \
|
||||
- --ossmixer "PCM@PCM"
|
||||
+ --ossmixer "PCM@PCM" \
|
||||
+ $ARGS
|
||||
}
|
||||
|
||||
test2() {
|
||||
@@ -27,7 +29,7 @@ cat > $CFGFILE <<EOF
|
||||
# next line - second job
|
||||
-C hw:1,0,1 -P hw:0,1,0 --tlatency 50000 --thread 2
|
||||
EOF
|
||||
- $DBG ./alsaloop -d --config $CFGFILE
|
||||
+ $DBG ./alsaloop -d --config $CFGFILE $ARGS
|
||||
}
|
||||
|
||||
test3() {
|
||||
@@ -46,7 +48,8 @@ cat > $CFGFILE <<EOF
|
||||
-C hw:1,0,6 -P plug:dmix:0 --tlatency 50000 --thread 6
|
||||
-C hw:1,0,7 -P plug:dmix:0 --tlatency 50000 --thread 7
|
||||
EOF
|
||||
- $DBG ./alsaloop --config $CFGFILE
|
||||
+ LD_PRELOAD="/home/perex/alsa/alsa-lib/src/.libs/libasound.so" \
|
||||
+ $DBG ./alsaloop --config $CFGFILE $ARGS
|
||||
}
|
||||
|
||||
test4() {
|
||||
@@ -55,7 +58,8 @@ test4() {
|
||||
--tlatency 50000 \
|
||||
--mixer "name='Master Playback Volume'@name='Master Playback Volume'" \
|
||||
--mixer "name='Master Playback Switch'@name='Master Playback Switch'" \
|
||||
- --mixer "name='PCM Playback Volume'"
|
||||
+ --mixer "name='PCM Playback Volume'" \
|
||||
+ $ARGS
|
||||
}
|
||||
|
||||
test5() {
|
||||
@@ -68,14 +72,14 @@ cat > $CFGFILE <<EOF
|
||||
--ossmixer "name=Master@VOLUME"
|
||||
-C hw:1,0,1 -P plughw:0,1 --tlatency 50000 --thread 2
|
||||
EOF
|
||||
- $DBG ./alsaloop --config $CFGFILE
|
||||
+ $DBG ./alsaloop --config $CFGFILE $ARGS
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
-test1) test1 ;;
|
||||
-test2) test2 ;;
|
||||
-test3) test3 ;;
|
||||
-test4) test4 ;;
|
||||
-test5) test5 ;;
|
||||
-*) test1 ;;
|
||||
+test1) shift; ARGS="$@"; test1 ;;
|
||||
+test2) shift; ARGS="$@"; test2 ;;
|
||||
+test3) shift; ARGS="$@"; test3 ;;
|
||||
+test4) shift; ARGS="$@"; test4 ;;
|
||||
+test5) shift; ARGS="$@"; test5 ;;
|
||||
+*) ARGS="$@"; test1 ;;
|
||||
esac
|
||||
--
|
||||
1.7.3.1
|
||||
|
149
0026-alsaloop-add-pctl-and-cctl-options.patch
Normal file
149
0026-alsaloop-add-pctl-and-cctl-options.patch
Normal file
@ -0,0 +1,149 @@
|
||||
From 38c2ef96b78d8733957f03b74799d953b83e045d Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Mon, 11 Oct 2010 11:53:50 +0200
|
||||
Subject: [PATCH 26/38] alsaloop: add --pctl and --cctl options
|
||||
|
||||
In some cases it might be usefull to specify another CTL device names.
|
||||
Add -X/--pctl and -Y/--cctl options.
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
alsaloop/alsaloop.c | 28 +++++++++++++++++++++++++---
|
||||
alsaloop/alsaloop.h | 1 +
|
||||
alsaloop/pcmjob.c | 13 ++++++++-----
|
||||
3 files changed, 34 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/alsaloop/alsaloop.c b/alsaloop/alsaloop.c
|
||||
index 3af3dd7..1b3505e 100644
|
||||
--- a/alsaloop/alsaloop.c
|
||||
+++ b/alsaloop/alsaloop.c
|
||||
@@ -66,6 +66,7 @@ static void my_exit(struct loopback_thread *thread, int exitcode)
|
||||
|
||||
static int create_loopback_handle(struct loopback_handle **_handle,
|
||||
const char *device,
|
||||
+ const char *ctldev,
|
||||
const char *id)
|
||||
{
|
||||
char idbuf[1024];
|
||||
@@ -77,6 +78,15 @@ static int create_loopback_handle(struct loopback_handle **_handle,
|
||||
if (device == NULL)
|
||||
device = "hw:0,0";
|
||||
handle->device = strdup(device);
|
||||
+ if (handle->device == NULL)
|
||||
+ return -ENOMEM;
|
||||
+ if (ctldev) {
|
||||
+ handle->ctldev = strdup(ctldev);
|
||||
+ if (handle->ctldev == NULL)
|
||||
+ return -ENOMEM;
|
||||
+ } else {
|
||||
+ handle->ctldev = NULL;
|
||||
+ }
|
||||
snprintf(idbuf, sizeof(idbuf)-1, "%s %s", id, device);
|
||||
idbuf[sizeof(idbuf)-1] = '\0';
|
||||
handle->id = strdup(idbuf);
|
||||
@@ -150,6 +160,8 @@ void help(void)
|
||||
"-d,--daemonize daemonize the main process and use syslog for errors\n"
|
||||
"-P,--pdevice playback device\n"
|
||||
"-C,--cdevice capture device\n"
|
||||
+"-X,--pctl playback ctl device\n"
|
||||
+"-Y,--cctl capture ctl device\n"
|
||||
"-l,--latency requested latency in frames\n"
|
||||
"-t,--tlatency requested latency in usec (1/1000000sec)\n"
|
||||
"-f,--format sample format\n"
|
||||
@@ -323,6 +335,8 @@ static int parse_config(int argc, char *argv[], snd_output_t *output)
|
||||
{"daemonize", 0, NULL, 'd'},
|
||||
{"pdevice", 1, NULL, 'P'},
|
||||
{"cdevice", 1, NULL, 'C'},
|
||||
+ {"pctl", 1, NULL, 'X'},
|
||||
+ {"cctl", 1, NULL, 'Y'},
|
||||
{"latency", 1, NULL, 'l'},
|
||||
{"tlatency", 1, NULL, 't'},
|
||||
{"format", 1, NULL, 'f'},
|
||||
@@ -348,6 +362,8 @@ static int parse_config(int argc, char *argv[], snd_output_t *output)
|
||||
char *arg_config = NULL;
|
||||
char *arg_pdevice = NULL;
|
||||
char *arg_cdevice = NULL;
|
||||
+ char *arg_pctl = NULL;
|
||||
+ char *arg_cctl = NULL;
|
||||
unsigned int arg_latency_req = 0;
|
||||
unsigned int arg_latency_reqtime = 10000;
|
||||
snd_pcm_format_t arg_format = SND_PCM_FORMAT_S16_LE;
|
||||
@@ -373,7 +389,7 @@ static int parse_config(int argc, char *argv[], snd_output_t *output)
|
||||
while (1) {
|
||||
int c;
|
||||
if ((c = getopt_long(argc, argv,
|
||||
- "hdg:P:C:l:t:F:f:c:r:s:benvA:S:a:m:T:O:w:",
|
||||
+ "hdg:P:C:X:Y:l:t:F:f:c:r:s:benvA:S:a:m:T:O:w:",
|
||||
long_option, NULL)) < 0)
|
||||
break;
|
||||
switch (c) {
|
||||
@@ -394,6 +410,12 @@ static int parse_config(int argc, char *argv[], snd_output_t *output)
|
||||
case 'C':
|
||||
arg_cdevice = strdup(optarg);
|
||||
break;
|
||||
+ case 'X':
|
||||
+ arg_pctl = strdup(optarg);
|
||||
+ break;
|
||||
+ case 'Y':
|
||||
+ arg_cctl = strdup(optarg);
|
||||
+ break;
|
||||
case 'l':
|
||||
err = atoi(optarg);
|
||||
arg_latency_req = err >= 4 ? err : 4;
|
||||
@@ -521,12 +543,12 @@ static int parse_config(int argc, char *argv[], snd_output_t *output)
|
||||
if (arg_config == NULL) {
|
||||
struct loopback_handle *play;
|
||||
struct loopback_handle *capt;
|
||||
- err = create_loopback_handle(&play, arg_pdevice, "playback");
|
||||
+ err = create_loopback_handle(&play, arg_pdevice, arg_pctl, "playback");
|
||||
if (err < 0) {
|
||||
logit(LOG_CRIT, "Unable to create playback handle.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
- err = create_loopback_handle(&capt, arg_cdevice, "capture");
|
||||
+ err = create_loopback_handle(&capt, arg_cdevice, arg_cctl, "capture");
|
||||
if (err < 0) {
|
||||
logit(LOG_CRIT, "Unable to create capture handle.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
diff --git a/alsaloop/alsaloop.h b/alsaloop/alsaloop.h
|
||||
index 6c4f40a..7516807 100644
|
||||
--- a/alsaloop/alsaloop.h
|
||||
+++ b/alsaloop/alsaloop.h
|
||||
@@ -84,6 +84,7 @@ struct loopback_ossmixer {
|
||||
struct loopback_handle {
|
||||
struct loopback *loopback;
|
||||
char *device;
|
||||
+ char *ctldev;
|
||||
char *id;
|
||||
int card_number;
|
||||
snd_pcm_t *handle;
|
||||
diff --git a/alsaloop/pcmjob.c b/alsaloop/pcmjob.c
|
||||
index 8b3e568..9d1bb01 100644
|
||||
--- a/alsaloop/pcmjob.c
|
||||
+++ b/alsaloop/pcmjob.c
|
||||
@@ -1063,14 +1063,17 @@ static int openit(struct loopback_handle *lhandle)
|
||||
snd_pcm_info_free(info);
|
||||
lhandle->card_number = card;
|
||||
lhandle->ctl = NULL;
|
||||
- if (card >= 0) {
|
||||
- char name[16];
|
||||
- sprintf(name, "hw:%i", card);
|
||||
+ if (card >= 0 || lhandle->ctldev) {
|
||||
+ char name[16], *dev = lhandle->ctldev;
|
||||
+ if (dev == NULL) {
|
||||
+ sprintf(name, "hw:%i", card);
|
||||
+ dev = name;
|
||||
+ }
|
||||
pcm_open_lock();
|
||||
- err = snd_ctl_open(&lhandle->ctl, name, SND_CTL_NONBLOCK);
|
||||
+ err = snd_ctl_open(&lhandle->ctl, dev, SND_CTL_NONBLOCK);
|
||||
pcm_open_unlock();
|
||||
if (err < 0) {
|
||||
- logit(LOG_CRIT, "%s [%s] ctl open error: %s\n", lhandle->id, name, snd_strerror(err));
|
||||
+ logit(LOG_CRIT, "%s [%s] ctl open error: %s\n", lhandle->id, dev, snd_strerror(err));
|
||||
lhandle->ctl = NULL;
|
||||
}
|
||||
if (lhandle->ctl)
|
||||
--
|
||||
1.7.3.1
|
||||
|
34
0027-alsaloop-add-pctl-and-cctl-options-to-man-page.patch
Normal file
34
0027-alsaloop-add-pctl-and-cctl-options-to-man-page.patch
Normal file
@ -0,0 +1,34 @@
|
||||
From af61ea60cfabb6b59b29a1e26769a7068a5742e1 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Mon, 11 Oct 2010 11:56:16 +0200
|
||||
Subject: [PATCH 27/38] alsaloop: add --pctl and --cctl options to man page
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz># Please enter the commit message for your changes. Lines starting
|
||||
---
|
||||
alsaloop/alsaloop.1 | 10 ++++++++++
|
||||
1 files changed, 10 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/alsaloop/alsaloop.1 b/alsaloop/alsaloop.1
|
||||
index 1554b6e..0b57b59 100644
|
||||
--- a/alsaloop/alsaloop.1
|
||||
+++ b/alsaloop/alsaloop.1
|
||||
@@ -48,6 +48,16 @@ Use given playback device.
|
||||
Use given capture device.
|
||||
|
||||
.TP
|
||||
+\fI\-X <device>\fP | \fI\-\-pctl=<device>\fP
|
||||
+
|
||||
+Use given CTL device for playback.
|
||||
+
|
||||
+.TP
|
||||
+\fI\-Y <device>\fP | \fI\-\-cctl=<device>\fP
|
||||
+
|
||||
+Use given CTL device for capture.
|
||||
+
|
||||
+.TP
|
||||
\fI\-l <latency>\fP | \fI\-\-latency=<frames>\fP
|
||||
|
||||
Requested latency in frames.
|
||||
--
|
||||
1.7.3.1
|
||||
|
677
0028-alsaloop-added-xrun-profiling-support-U-xrun-added-S.patch
Normal file
677
0028-alsaloop-added-xrun-profiling-support-U-xrun-added-S.patch
Normal file
@ -0,0 +1,677 @@
|
||||
From 1a35bdf7c6c3a4727662d093963141dddc376072 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Wed, 13 Oct 2010 23:39:36 +0200
|
||||
Subject: [PATCH 28/38] alsaloop: added xrun profiling support (-U,--xrun), added SIGUSR1 state dump
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
alsaloop/alsaloop.c | 89 ++++++++++++++++++++++---
|
||||
alsaloop/alsaloop.h | 20 +++++-
|
||||
alsaloop/pcmjob.c | 180 ++++++++++++++++++++++++++++++++++++++++++++-------
|
||||
alsaloop/test.sh | 26 +++++---
|
||||
4 files changed, 270 insertions(+), 45 deletions(-)
|
||||
|
||||
diff --git a/alsaloop/alsaloop.c b/alsaloop/alsaloop.c
|
||||
index 1b3505e..561fdd7 100644
|
||||
--- a/alsaloop/alsaloop.c
|
||||
+++ b/alsaloop/alsaloop.c
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <math.h>
|
||||
#include <pthread.h>
|
||||
#include <syslog.h>
|
||||
+#include <sys/signal.h>
|
||||
#include "alsaloop.h"
|
||||
|
||||
struct loopback_thread {
|
||||
@@ -42,6 +43,7 @@ struct loopback_thread {
|
||||
snd_output_t *output;
|
||||
};
|
||||
|
||||
+int quit = 0;
|
||||
int verbose = 0;
|
||||
int workarounds = 0;
|
||||
int daemonize = 0;
|
||||
@@ -50,6 +52,10 @@ struct loopback **loopbacks = NULL;
|
||||
int loopbacks_count = 0;
|
||||
char **my_argv = NULL;
|
||||
int my_argc = 0;
|
||||
+struct loopback_thread *threads;
|
||||
+int threads_count = 0;
|
||||
+pthread_t main_job;
|
||||
+int arg_default_xrun = 0;
|
||||
|
||||
static void my_exit(struct loopback_thread *thread, int exitcode)
|
||||
{
|
||||
@@ -118,6 +124,7 @@ static int create_loopback(struct loopback **_handle,
|
||||
handle->loop_time = ~0UL;
|
||||
handle->loop_limit = ~0ULL;
|
||||
handle->output = output;
|
||||
+ handle->state = output;
|
||||
#ifdef USE_SAMPLERATE
|
||||
handle->src_enable = 1;
|
||||
handle->src_converter_type = SRC_SINC_BEST_QUALITY;
|
||||
@@ -185,6 +192,7 @@ void help(void)
|
||||
"-e,--effect apply an effect (bandpass filter sweep)\n"
|
||||
"-v,--verbose verbose mode (more -v means more verbose)\n"
|
||||
"-w,--workaround use workaround (serialopen)\n"
|
||||
+"-U,--xrun xrun profiling\n"
|
||||
);
|
||||
printf("\nRecognized sample formats are:");
|
||||
for (k = 0; k < SND_PCM_FORMAT_LAST; ++k) {
|
||||
@@ -326,7 +334,8 @@ static int add_oss_mixers(struct loopback *loop,
|
||||
|
||||
static int parse_config_file(const char *file, snd_output_t *output);
|
||||
|
||||
-static int parse_config(int argc, char *argv[], snd_output_t *output)
|
||||
+static int parse_config(int argc, char *argv[], snd_output_t *output,
|
||||
+ int cmdline)
|
||||
{
|
||||
struct option long_option[] =
|
||||
{
|
||||
@@ -356,6 +365,7 @@ static int parse_config(int argc, char *argv[], snd_output_t *output)
|
||||
{"mixer", 1, NULL, 'm'},
|
||||
{"ossmixer", 1, NULL, 'O'},
|
||||
{"workaround", 1, NULL, 'w'},
|
||||
+ {"xrun", 0, NULL, 'U'},
|
||||
{NULL, 0, NULL, 0},
|
||||
};
|
||||
int err, morehelp;
|
||||
@@ -384,12 +394,13 @@ static int parse_config(int argc, char *argv[], snd_output_t *output)
|
||||
int arg_mixers_count = 0;
|
||||
char *arg_ossmixers[MAX_MIXERS];
|
||||
int arg_ossmixers_count = 0;
|
||||
+ int arg_xrun = arg_default_xrun;
|
||||
|
||||
morehelp = 0;
|
||||
while (1) {
|
||||
int c;
|
||||
if ((c = getopt_long(argc, argv,
|
||||
- "hdg:P:C:X:Y:l:t:F:f:c:r:s:benvA:S:a:m:T:O:w:",
|
||||
+ "hdg:P:C:X:Y:l:t:F:f:c:r:s:benvA:S:a:m:T:O:w:U",
|
||||
long_option, NULL)) < 0)
|
||||
break;
|
||||
switch (c) {
|
||||
@@ -533,6 +544,11 @@ static int parse_config(int argc, char *argv[], snd_output_t *output)
|
||||
if (strcasecmp(optarg, "serialopen") == 0)
|
||||
workarounds |= WORKAROUND_SERIALOPEN;
|
||||
break;
|
||||
+ case 'U':
|
||||
+ arg_xrun = 1;
|
||||
+ if (cmdline)
|
||||
+ arg_default_xrun = 1;
|
||||
+ break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -570,6 +586,7 @@ static int parse_config(int argc, char *argv[], snd_output_t *output)
|
||||
loop->sync = arg_sync;
|
||||
loop->slave = arg_slave;
|
||||
loop->thread = arg_thread;
|
||||
+ loop->xrun = arg_xrun;
|
||||
err = add_mixers(loop, arg_mixers, arg_mixers_count);
|
||||
if (err < 0) {
|
||||
logit(LOG_CRIT, "Unable to add mixer controls.\n");
|
||||
@@ -656,7 +673,7 @@ static int parse_config_file(const char *file, snd_output_t *output)
|
||||
optind = opterr = 1;
|
||||
optopt = '?';
|
||||
|
||||
- err = parse_config(argc, argv, output);
|
||||
+ err = parse_config(argc, argv, output, 0);
|
||||
__next:
|
||||
if (err < 0)
|
||||
break;
|
||||
@@ -698,7 +715,7 @@ static void thread_job1(void *_data)
|
||||
logit(LOG_CRIT, "Poll FDs allocation failed.\n");
|
||||
my_exit(thread, EXIT_FAILURE);
|
||||
}
|
||||
- while (1) {
|
||||
+ while (!quit) {
|
||||
struct timeval tv1, tv2;
|
||||
for (i = j = 0; i < thread->loopbacks_count; i++) {
|
||||
err = pcmjob_pollfds_init(thread->loopbacks[i], &pfds[j]);
|
||||
@@ -711,12 +728,16 @@ static void thread_job1(void *_data)
|
||||
if (verbose > 10)
|
||||
gettimeofday(&tv1, NULL);
|
||||
err = poll(pfds, j, -1);
|
||||
+ if (err < 0)
|
||||
+ err = -errno;
|
||||
if (verbose > 10) {
|
||||
gettimeofday(&tv2, NULL);
|
||||
snd_output_printf(output, "pool took %lius\n", timediff(tv2, tv1));
|
||||
}
|
||||
if (err < 0) {
|
||||
- logit(LOG_CRIT, "Poll failed.\n");
|
||||
+ if (err == -EINTR || err == -ERESTART)
|
||||
+ continue;
|
||||
+ logit(LOG_CRIT, "Poll failed: %s\n", strerror(-err));
|
||||
my_exit(thread, EXIT_FAILURE);
|
||||
}
|
||||
for (i = j = 0; i < thread->loopbacks_count; i++) {
|
||||
@@ -745,18 +766,58 @@ static void thread_job(struct loopback_thread *thread)
|
||||
(void *) thread);
|
||||
}
|
||||
|
||||
+static void send_to_all(int sig)
|
||||
+{
|
||||
+ struct loopback_thread *thread;
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < threads_count; i++) {
|
||||
+ thread = &threads[i];
|
||||
+ if (thread->threaded)
|
||||
+ pthread_kill(thread->thread, sig);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void signal_handler(int sig)
|
||||
+{
|
||||
+ quit = 1;
|
||||
+ send_to_all(SIGUSR2);
|
||||
+}
|
||||
+
|
||||
+static void signal_handler_state(int sig)
|
||||
+{
|
||||
+ pthread_t self = pthread_self();
|
||||
+ struct loopback_thread *thread;
|
||||
+ int i, j;
|
||||
+
|
||||
+ if (pthread_equal(main_job, self))
|
||||
+ send_to_all(SIGUSR1);
|
||||
+ for (i = 0; i < threads_count; i++) {
|
||||
+ thread = &threads[i];
|
||||
+ if (thread->thread == self) {
|
||||
+ for (j = 0; j < thread->loopbacks_count; j++)
|
||||
+ pcmjob_state(thread->loopbacks[j]);
|
||||
+ }
|
||||
+ }
|
||||
+ signal(sig, signal_handler_state);
|
||||
+}
|
||||
+
|
||||
+static void signal_handler_ignore(int sig)
|
||||
+{
|
||||
+ signal(sig, signal_handler_ignore);
|
||||
+}
|
||||
+
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
snd_output_t *output;
|
||||
int i, j, k, l, err;
|
||||
- struct loopback_thread *threads;
|
||||
|
||||
err = snd_output_stdio_attach(&output, stdout, 0);
|
||||
if (err < 0) {
|
||||
logit(LOG_CRIT, "Output failed: %s\n", snd_strerror(err));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
- err = parse_config(argc, argv, output);
|
||||
+ err = parse_config(argc, argv, output, 1);
|
||||
if (err < 0) {
|
||||
logit(LOG_CRIT, "Unable to parse arguments or configuration...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
@@ -825,12 +886,20 @@ int main(int argc, char *argv[])
|
||||
if (loopbacks[i]->thread == k)
|
||||
threads[k].loopbacks[l++] = loopbacks[i];
|
||||
}
|
||||
-
|
||||
- for (k = 0; k < j; k++)
|
||||
+ threads_count = j;
|
||||
+ main_job = pthread_self();
|
||||
+
|
||||
+ signal(SIGINT, signal_handler);
|
||||
+ signal(SIGTERM, signal_handler);
|
||||
+ signal(SIGABRT, signal_handler);
|
||||
+ signal(SIGUSR1, signal_handler_state);
|
||||
+ signal(SIGUSR2, signal_handler_ignore);
|
||||
+
|
||||
+ for (k = 0; k < threads_count; k++)
|
||||
thread_job(&threads[k]);
|
||||
|
||||
if (j > 1) {
|
||||
- for (k = 0; k < j; k++)
|
||||
+ for (k = 0; k < threads_count; k++)
|
||||
pthread_join(threads[k].thread, NULL);
|
||||
}
|
||||
|
||||
diff --git a/alsaloop/alsaloop.h b/alsaloop/alsaloop.h
|
||||
index 7516807..839fc6d 100644
|
||||
--- a/alsaloop/alsaloop.h
|
||||
+++ b/alsaloop/alsaloop.h
|
||||
@@ -95,6 +95,7 @@ struct loopback_handle {
|
||||
unsigned int channels;
|
||||
unsigned int buffer_size;
|
||||
unsigned int period_size;
|
||||
+ snd_pcm_uframes_t avail_min;
|
||||
unsigned int buffer_size_req;
|
||||
unsigned int period_size_req;
|
||||
unsigned int frame_size;
|
||||
@@ -130,12 +131,13 @@ struct loopback {
|
||||
char *id;
|
||||
struct loopback_handle *capt;
|
||||
struct loopback_handle *play;
|
||||
- snd_pcm_uframes_t latency; /* final latency */
|
||||
- unsigned int latency_req; /* in frames / 2 */
|
||||
- unsigned int latency_reqtime; /* in us / 2 */
|
||||
+ snd_pcm_uframes_t latency; /* final latency in frames */
|
||||
+ unsigned int latency_req; /* in frames */
|
||||
+ unsigned int latency_reqtime; /* in us */
|
||||
unsigned long loop_time; /* ~0 = unlimited (in seconds) */
|
||||
unsigned long long loop_limit; /* ~0 = unlimited (in frames) */
|
||||
snd_output_t *output;
|
||||
+ snd_output_t *state;
|
||||
int pollfd_count;
|
||||
int active_pollfd_count;
|
||||
unsigned int linked:1; /* linked streams */
|
||||
@@ -153,6 +155,17 @@ struct loopback {
|
||||
unsigned int total_queued_count;
|
||||
snd_timestamp_t tstamp_start;
|
||||
snd_timestamp_t tstamp_end;
|
||||
+ /* xrun profiling */
|
||||
+ unsigned int xrun:1; /* xrun profiling */
|
||||
+ snd_timestamp_t xrun_last_update;
|
||||
+ snd_timestamp_t xrun_last_wake0;
|
||||
+ snd_timestamp_t xrun_last_wake;
|
||||
+ snd_timestamp_t xrun_last_check0;
|
||||
+ snd_timestamp_t xrun_last_check;
|
||||
+ snd_pcm_sframes_t xrun_last_pdelay;
|
||||
+ snd_pcm_sframes_t xrun_last_cdelay;
|
||||
+ long xrun_max_proctime;
|
||||
+ double xrun_max_missing;
|
||||
/* control mixer */
|
||||
struct loopback_mixer *controls;
|
||||
struct loopback_ossmixer *oss_controls;
|
||||
@@ -190,6 +203,7 @@ int pcmjob_start(struct loopback *loop);
|
||||
int pcmjob_stop(struct loopback *loop);
|
||||
int pcmjob_pollfds_init(struct loopback *loop, struct pollfd *fds);
|
||||
int pcmjob_pollfds_handle(struct loopback *loop, struct pollfd *fds);
|
||||
+void pcmjob_state(struct loopback *loop);
|
||||
|
||||
int control_parse_id(const char *str, snd_ctl_elem_id_t *id);
|
||||
int control_id_match(snd_ctl_elem_id_t *id1, snd_ctl_elem_id_t *id2);
|
||||
diff --git a/alsaloop/pcmjob.c b/alsaloop/pcmjob.c
|
||||
index 9d1bb01..0f1a853 100644
|
||||
--- a/alsaloop/pcmjob.c
|
||||
+++ b/alsaloop/pcmjob.c
|
||||
@@ -34,6 +34,8 @@
|
||||
#include <pthread.h>
|
||||
#include "alsaloop.h"
|
||||
|
||||
+#define XRUN_PROFILE_UNKNOWN (-10000000)
|
||||
+
|
||||
static int set_rate_shift(struct loopback_handle *lhandle, double pitch);
|
||||
static int get_rate(struct loopback_handle *lhandle);
|
||||
|
||||
@@ -50,6 +52,7 @@ static const char *sync_types[] = {
|
||||
|
||||
#define SRCTYPE(v) [SRC_##v] = "SRC_" #v
|
||||
|
||||
+#ifdef USE_SAMPLERATE
|
||||
static const char *src_types[] = {
|
||||
SRCTYPE(SINC_BEST_QUALITY),
|
||||
SRCTYPE(SINC_MEDIUM_QUALITY),
|
||||
@@ -57,6 +60,7 @@ static const char *src_types[] = {
|
||||
SRCTYPE(ZERO_ORDER_HOLD),
|
||||
SRCTYPE(LINEAR)
|
||||
};
|
||||
+#endif
|
||||
|
||||
static pthread_mutex_t pcm_open_mutex =
|
||||
PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
|
||||
@@ -78,6 +82,13 @@ static inline snd_pcm_uframes_t get_whole_latency(struct loopback *loop)
|
||||
return loop->latency;
|
||||
}
|
||||
|
||||
+static inline unsigned long long
|
||||
+ frames_to_time(struct loopback_handle *lhandle,
|
||||
+ snd_pcm_uframes_t frames)
|
||||
+{
|
||||
+ return (frames * 1000000ULL) / lhandle->rate;
|
||||
+}
|
||||
+
|
||||
static inline snd_pcm_uframes_t time_to_frames(struct loopback_handle *lhandle,
|
||||
unsigned long long time)
|
||||
{
|
||||
@@ -125,7 +136,11 @@ static int setparams_stream(struct loopback_handle *lhandle,
|
||||
rrate = 0;
|
||||
snd_pcm_hw_params_get_rate(params, &rrate, 0);
|
||||
lhandle->rate = rrate;
|
||||
- if (!lhandle->loopback->src_enable && (int)rrate != lhandle->rate) {
|
||||
+ if (
|
||||
+#ifdef USE_SAMPLERATE
|
||||
+ !lhandle->loopback->src_enable &&
|
||||
+#endif
|
||||
+ (int)rrate != lhandle->rate) {
|
||||
logit(LOG_CRIT, "Rate does not match (requested %iHz, got %iHz, resample %i)\n", lhandle->rate, rrate, lhandle->resample);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -247,6 +262,7 @@ static int setparams_set(struct loopback_handle *lhandle,
|
||||
logit(LOG_CRIT, "Unable to set avail min for %s: %s\n", lhandle->id, snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
+ snd_pcm_sw_params_get_avail_min(swparams, &lhandle->avail_min);
|
||||
err = snd_pcm_sw_params(handle, swparams);
|
||||
if (err < 0) {
|
||||
logit(LOG_CRIT, "Unable to set sw params for %s: %s\n", lhandle->id, snd_strerror(err));
|
||||
@@ -316,11 +332,12 @@ static int setparams(struct loopback *loop, snd_pcm_uframes_t bufsize)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static void showlatency(struct loopback *loop, size_t latency, unsigned int rate)
|
||||
+static void showlatency(snd_output_t *out, size_t latency, unsigned int rate,
|
||||
+ char *prefix)
|
||||
{
|
||||
double d;
|
||||
d = (double)latency / (double)rate;
|
||||
- snd_output_printf(loop->output, "Latency %li frames, %.3fus, %.6fms (%.4fHz)\n", (long)latency, d * 1000000, d * 1000, (double)1 / d);
|
||||
+ snd_output_printf(out, "%s %li frames, %.3fus, %.6fms (%.4fHz)\n", prefix, (long)latency, d * 1000000, d * 1000, (double)1 / d);
|
||||
}
|
||||
|
||||
static long timediff(snd_timestamp_t t1, snd_timestamp_t t2)
|
||||
@@ -328,11 +345,11 @@ static long timediff(snd_timestamp_t t1, snd_timestamp_t t2)
|
||||
signed long l;
|
||||
|
||||
t1.tv_sec -= t2.tv_sec;
|
||||
- l = (signed long) t1.tv_usec - (signed long) t2.tv_usec;
|
||||
- if (l < 0) {
|
||||
+ if (t1.tv_usec < t2.tv_usec) {
|
||||
+ l = ((t1.tv_usec + 1000000) - t2.tv_usec) % 1000000;
|
||||
t1.tv_sec--;
|
||||
- l = -l;
|
||||
- l %= 1000000;
|
||||
+ } else {
|
||||
+ l = t1.tv_usec - t2.tv_usec;
|
||||
}
|
||||
return (t1.tv_sec * 1000000) + l;
|
||||
}
|
||||
@@ -346,6 +363,56 @@ static int getcurtimestamp(snd_timestamp_t *ts)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void xrun_profile0(struct loopback *loop)
|
||||
+{
|
||||
+ snd_pcm_sframes_t pdelay, cdelay;
|
||||
+
|
||||
+ if (snd_pcm_delay(loop->play->handle, &pdelay) >= 0 &&
|
||||
+ snd_pcm_delay(loop->capt->handle, &cdelay) >= 0) {
|
||||
+ getcurtimestamp(&loop->xrun_last_update);
|
||||
+ loop->xrun_last_pdelay = pdelay;
|
||||
+ loop->xrun_last_cdelay = cdelay;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static inline void xrun_profile(struct loopback *loop)
|
||||
+{
|
||||
+ if (loop->xrun)
|
||||
+ xrun_profile0(loop);
|
||||
+}
|
||||
+
|
||||
+static void xrun_stats0(struct loopback *loop)
|
||||
+{
|
||||
+ snd_timestamp_t t;
|
||||
+ double expected, last, wake, check, queued = -1, proc, missing;
|
||||
+
|
||||
+ expected = ((double)loop->latency /
|
||||
+ (double)loop->play->rate) * 1000;
|
||||
+ getcurtimestamp(&t);
|
||||
+ last = (double)timediff(t, loop->xrun_last_update) / 1000;
|
||||
+ wake = (double)timediff(t, loop->xrun_last_wake) / 1000;
|
||||
+ check = (double)timediff(t, loop->xrun_last_check) / 1000;
|
||||
+ if (loop->xrun_last_pdelay != XRUN_PROFILE_UNKNOWN)
|
||||
+ queued = (((double)loop->xrun_last_pdelay *
|
||||
+ loop->play->pitch) /
|
||||
+ (double)loop->play->rate) * 1000;
|
||||
+ proc = (double)loop->xrun_max_proctime / 1000;
|
||||
+ missing = last - queued;
|
||||
+ if (loop->xrun_max_missing < missing)
|
||||
+ loop->xrun_max_missing = missing;
|
||||
+ loop->xrun_max_proctime = 0;
|
||||
+ getcurtimestamp(&t);
|
||||
+ logit(LOG_INFO, " last write before %.4fms, queued %.4fms -> missing %.4fms\n", last, queued, missing);
|
||||
+ logit(LOG_INFO, " expected %.4fms, processing %.4fms, max missing %.4fms\n", expected, proc, loop->xrun_max_missing);
|
||||
+ logit(LOG_INFO, " last wake before %.4fms, last check before %.4fms\n", wake, check);
|
||||
+}
|
||||
+
|
||||
+static inline void xrun_stats(struct loopback *loop)
|
||||
+{
|
||||
+ if (loop->xrun)
|
||||
+ xrun_stats0(loop);
|
||||
+}
|
||||
+
|
||||
static inline snd_pcm_uframes_t buf_avail(struct loopback_handle *lhandle)
|
||||
{
|
||||
return lhandle->buf_size - lhandle->buf_count;
|
||||
@@ -495,11 +562,13 @@ static int xrun(struct loopback_handle *lhandle)
|
||||
|
||||
if (lhandle == lhandle->loopback->play) {
|
||||
logit(LOG_DEBUG, "underrun for %s\n", lhandle->id);
|
||||
+ xrun_stats(lhandle->loopback);
|
||||
if ((err = snd_pcm_prepare(lhandle->handle)) < 0)
|
||||
return err;
|
||||
lhandle->xrun_pending = 1;
|
||||
} else {
|
||||
logit(LOG_DEBUG, "overrun for %s\n", lhandle->id);
|
||||
+ xrun_stats(lhandle->loopback);
|
||||
if ((err = snd_pcm_prepare(lhandle->handle)) < 0)
|
||||
return err;
|
||||
lhandle->xrun_pending = 1;
|
||||
@@ -622,6 +691,7 @@ static int writeit(struct loopback_handle *lhandle)
|
||||
fwrite(lhandle->buf + lhandle->buf_pos * lhandle->frame_size,
|
||||
r, lhandle->frame_size, lhandle->loopback->pfile);
|
||||
#endif
|
||||
+ xrun_profile(lhandle->loopback);
|
||||
res += r;
|
||||
lhandle->counter += r;
|
||||
lhandle->buf_count -= r;
|
||||
@@ -735,9 +805,17 @@ static int xrun_sync(struct loopback *loop)
|
||||
loop->pitch_diff = loop->pitch_diff_min = loop->pitch_diff_max = 0;
|
||||
if (verbose > 6) {
|
||||
snd_output_printf(loop->output,
|
||||
- "sync: cdelay=%li(%li), pdelay=%li(%li), fill=%li (delay=%li), src_out=%li\n",
|
||||
+ "sync: cdelay=%li(%li), pdelay=%li(%li), fill=%li (delay=%li)"
|
||||
+#ifdef USE_SAMPLERATE
|
||||
+ ", src_out=%li"
|
||||
+#endif
|
||||
+ "\n",
|
||||
(long)cdelay, (long)cdelay1, (long)pdelay, (long)pdelay1,
|
||||
- (long)fill, (long)delay1, (long)loop->src_out_frames);
|
||||
+ (long)fill, (long)delay1
|
||||
+#ifdef USE_SAMPLERATE
|
||||
+ , (long)loop->src_out_frames
|
||||
+#endif
|
||||
+ );
|
||||
snd_output_printf(loop->output,
|
||||
"sync: cbufcount=%li, pbufcount=%li\n",
|
||||
(long)capt->buf_count, (long)play->buf_count);
|
||||
@@ -1112,10 +1190,7 @@ static int init_handle(struct loopback_handle *lhandle, int alloc)
|
||||
lhandle->frame_size = (snd_pcm_format_width(lhandle->format) / 8) *
|
||||
lhandle->channels;
|
||||
lhandle->sync_point = lhandle->rate * 15; /* every 15 seconds */
|
||||
- lat = lhandle->loopback->latency_req;
|
||||
- if (lat == 0)
|
||||
- lat = time_to_frames(lhandle,
|
||||
- lhandle->loopback->latency_reqtime);
|
||||
+ lat = lhandle->loopback->latency;
|
||||
if (lhandle->buffer_size > lat)
|
||||
lat = lhandle->buffer_size;
|
||||
lhandle->buf_size = lat * 2;
|
||||
@@ -1152,8 +1227,6 @@ int pcmjob_init(struct loopback *loop)
|
||||
#ifdef USE_SAMPLERATE
|
||||
if (loop->sync == SYNC_TYPE_AUTO && loop->src_enable)
|
||||
loop->sync = SYNC_TYPE_SAMPLERATE;
|
||||
-#else
|
||||
- loop->src_enable = 0;
|
||||
#endif
|
||||
if (loop->sync == SYNC_TYPE_AUTO)
|
||||
loop->sync = SYNC_TYPE_SIMPLE;
|
||||
@@ -1270,14 +1343,16 @@ int pcmjob_start(struct loopback *loop)
|
||||
}
|
||||
loop->reinit = 0;
|
||||
loop->use_samplerate = 0;
|
||||
- loop->latency = loop->latency_req;
|
||||
- if (loop->latency == 0)
|
||||
- loop->latency = time_to_frames(loop->play,
|
||||
- loop->latency_reqtime);
|
||||
+ if (loop->latency_req) {
|
||||
+ loop->latency_reqtime = frames_to_time(loop->play,
|
||||
+ loop->latency_req);
|
||||
+ loop->latency_req = 0;
|
||||
+ }
|
||||
+ loop->latency = time_to_frames(loop->play, loop->latency_reqtime);
|
||||
if ((err = setparams(loop, loop->latency/2)) < 0)
|
||||
goto __error;
|
||||
if (verbose)
|
||||
- showlatency(loop, loop->latency, loop->play->rate_req);
|
||||
+ showlatency(loop->output, loop->latency, loop->play->rate, "Latency");
|
||||
if (loop->play->access == loop->capt->access &&
|
||||
loop->play->format == loop->capt->format &&
|
||||
loop->play->rate == loop->capt->rate &&
|
||||
@@ -1402,6 +1477,12 @@ int pcmjob_start(struct loopback *loop)
|
||||
goto __error;
|
||||
}
|
||||
loop->running = 1;
|
||||
+ if (loop->xrun) {
|
||||
+ getcurtimestamp(&loop->xrun_last_update);
|
||||
+ loop->xrun_last_pdelay = XRUN_PROFILE_UNKNOWN;
|
||||
+ loop->xrun_last_cdelay = XRUN_PROFILE_UNKNOWN;
|
||||
+ loop->xrun_max_proctime = 0;
|
||||
+ }
|
||||
if ((err = snd_pcm_start(loop->capt->handle)) < 0) {
|
||||
logit(LOG_CRIT, "pcm start %s error: %s\n", loop->capt->id, snd_strerror(err));
|
||||
goto __error;
|
||||
@@ -1568,7 +1649,7 @@ int pcmjob_pollfds_handle(struct loopback *loop, struct pollfd *fds)
|
||||
|
||||
if (verbose > 11)
|
||||
snd_output_printf(loop->output, "%s: pollfds handle\n", loop->id);
|
||||
- if (verbose > 13)
|
||||
+ if (verbose > 13 || loop->xrun)
|
||||
getcurtimestamp(&loop->tstamp_start);
|
||||
if (verbose > 12) {
|
||||
snd_pcm_sframes_t pdelay, cdelay;
|
||||
@@ -1595,6 +1676,14 @@ int pcmjob_pollfds_handle(struct loopback *loop, struct pollfd *fds)
|
||||
if (err < 0)
|
||||
return err;
|
||||
idx += capt->pollfd_count;
|
||||
+ if (loop->xrun) {
|
||||
+ if (prevents || crevents) {
|
||||
+ loop->xrun_last_wake = loop->xrun_last_wake0;
|
||||
+ loop->xrun_last_wake0 = loop->tstamp_start;
|
||||
+ }
|
||||
+ loop->xrun_last_check = loop->xrun_last_check0;
|
||||
+ loop->xrun_last_check0 = loop->tstamp_start;
|
||||
+ }
|
||||
} else {
|
||||
prevents = crevents = 0;
|
||||
}
|
||||
@@ -1717,9 +1806,54 @@ int pcmjob_pollfds_handle(struct loopback *loop, struct pollfd *fds)
|
||||
snd_output_printf(loop->output, "%s: end delay %li / %li / %li\n", capt->id, cdelay, capt->buf_size, capt->buf_count);
|
||||
}
|
||||
__pcm_end:
|
||||
- if (verbose > 13) {
|
||||
+ if (verbose > 13 || loop->xrun) {
|
||||
+ long diff;
|
||||
getcurtimestamp(&loop->tstamp_end);
|
||||
- snd_output_printf(loop->output, "%s: processing time %lius\n", capt->id, timediff(loop->tstamp_end, loop->tstamp_start));
|
||||
+ diff = timediff(loop->tstamp_end, loop->tstamp_start);
|
||||
+ if (verbose > 13)
|
||||
+ snd_output_printf(loop->output, "%s: processing time %lius\n", loop->id, diff);
|
||||
+ if (loop->xrun && loop->xrun_max_proctime < diff)
|
||||
+ loop->xrun_max_proctime = diff;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+#define OUT(args...) \
|
||||
+ snd_output_printf(loop->state, ##args)
|
||||
+
|
||||
+static pthread_mutex_t state_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
+
|
||||
+static void show_handle(struct loopback_handle *lhandle, const char *id)
|
||||
+{
|
||||
+ struct loopback *loop = lhandle->loopback;
|
||||
+
|
||||
+ OUT(" %s: %s:\n", id, lhandle->id);
|
||||
+ OUT(" device = '%s', ctldev '%s'\n", lhandle->device, lhandle->ctldev);
|
||||
+ OUT(" card_number = %i\n", lhandle->card_number);
|
||||
+ if (!loop->running)
|
||||
+ return;
|
||||
+ OUT(" access = %s, format = %s, rate = %u, channels = %u\n", snd_pcm_access_name(lhandle->access), snd_pcm_format_name(lhandle->format), lhandle->rate, lhandle->channels);
|
||||
+ OUT(" buffer_size = %u, period_size = %u, avail_min = %li\n", lhandle->buffer_size, lhandle->period_size, lhandle->avail_min);
|
||||
+ OUT(" xrun_pending = %i\n", lhandle->xrun_pending);
|
||||
+ OUT(" buf_size = %li, buf_pos = %li, buf_count = %li, buf_over = %li\n", lhandle->buf_size, lhandle->buf_pos, lhandle->buf_count, lhandle->buf_over);
|
||||
+ OUT(" pitch = %.8f\n", lhandle->pitch);
|
||||
+}
|
||||
+
|
||||
+void pcmjob_state(struct loopback *loop)
|
||||
+{
|
||||
+ pthread_t self = pthread_self();
|
||||
+ pthread_mutex_lock(&state_mutex);
|
||||
+ OUT("State dump for thread %p job %i: %s:\n", (void *)self, loop->thread, loop->id);
|
||||
+ OUT(" running = %i\n", loop->running);
|
||||
+ OUT(" sync = %i\n", loop->sync);
|
||||
+ OUT(" slave = %i\n", loop->slave);
|
||||
+ if (!loop->running)
|
||||
+ goto __skip;
|
||||
+ OUT(" pollfd_count = %i\n", loop->pollfd_count);
|
||||
+ OUT(" pitch = %.8f, delta = %.8f, diff = %li, min = %li, max = %li\n", loop->pitch, loop->pitch_delta, loop->pitch_diff, loop->pitch_diff_min, loop->pitch_diff_max);
|
||||
+ OUT(" use_samplerate = %i\n", loop->use_samplerate);
|
||||
+ __skip:
|
||||
+ show_handle(loop->play, "playback");
|
||||
+ show_handle(loop->capt, "capture");
|
||||
+ pthread_mutex_unlock(&state_mutex);
|
||||
+}
|
||||
diff --git a/alsaloop/test.sh b/alsaloop/test.sh
|
||||
index e3d81b1..ff9aa4e 100755
|
||||
--- a/alsaloop/test.sh
|
||||
+++ b/alsaloop/test.sh
|
||||
@@ -35,20 +35,19 @@ EOF
|
||||
test3() {
|
||||
echo "TEST3"
|
||||
cat > $CFGFILE <<EOF
|
||||
--C hw:1,0,0 -P plug:dmix:0 --tlatency 50000 --thread 0 \
|
||||
+-C hw:1,0,0 -P plug:dmix:0 --tlatency 30000 --thread 0 \
|
||||
--mixer "name='Master Playback Volume'@name='Master Playback Volume'" \
|
||||
--mixer "name='Master Playback Switch'@name='Master Playback Switch'" \
|
||||
--mixer "name='PCM Playback Volume'" \
|
||||
--ossmixer "name=Master@VOLUME"
|
||||
--C hw:1,0,1 -P plug:dmix:0 --tlatency 50000 --thread 1
|
||||
--C hw:1,0,2 -P plug:dmix:0 --tlatency 50000 --thread 2
|
||||
--C hw:1,0,3 -P plug:dmix:0 --tlatency 50000 --thread 3
|
||||
--C hw:1,0,4 -P plug:dmix:0 --tlatency 50000 --thread 4
|
||||
--C hw:1,0,5 -P plug:dmix:0 --tlatency 50000 --thread 5
|
||||
--C hw:1,0,6 -P plug:dmix:0 --tlatency 50000 --thread 6
|
||||
--C hw:1,0,7 -P plug:dmix:0 --tlatency 50000 --thread 7
|
||||
+-C hw:1,0,1 -P plug:dmix:0 --tlatency 30000 --thread 1
|
||||
+-C hw:1,0,2 -P plug:dmix:0 --tlatency 30000 --thread 2
|
||||
+-C hw:1,0,3 -P plug:dmix:0 --tlatency 30000 --thread 3
|
||||
+-C hw:1,0,4 -P plug:dmix:0 --tlatency 30000 --thread 4
|
||||
+-C hw:1,0,5 -P plug:dmix:0 --tlatency 30000 --thread 5
|
||||
+-C hw:1,0,6 -P plug:dmix:0 --tlatency 30000 --thread 6
|
||||
+-C hw:1,0,7 -P plug:dmix:0 --tlatency 30000 --thread 7
|
||||
EOF
|
||||
- LD_PRELOAD="/home/perex/alsa/alsa-lib/src/.libs/libasound.so" \
|
||||
$DBG ./alsaloop --config $CFGFILE $ARGS
|
||||
}
|
||||
|
||||
@@ -75,11 +74,20 @@ EOF
|
||||
$DBG ./alsaloop --config $CFGFILE $ARGS
|
||||
}
|
||||
|
||||
+sigusr1() {
|
||||
+ pid=$(ps ax | grep alsaloop | grep -v grep | colrm 7 255)
|
||||
+ if test -n "$pid"; then
|
||||
+ echo "Killing alsaloop $pid..."
|
||||
+ kill -SIGUSR1 $pid
|
||||
+ fi
|
||||
+}
|
||||
+
|
||||
case "$1" in
|
||||
test1) shift; ARGS="$@"; test1 ;;
|
||||
test2) shift; ARGS="$@"; test2 ;;
|
||||
test3) shift; ARGS="$@"; test3 ;;
|
||||
test4) shift; ARGS="$@"; test4 ;;
|
||||
test5) shift; ARGS="$@"; test5 ;;
|
||||
+usr|sig*) sigusr1 ;;
|
||||
*) ARGS="$@"; test1 ;;
|
||||
esac
|
||||
--
|
||||
1.7.3.1
|
||||
|
30
0029-alsaloop-add-U-xrun-to-alsaloop.1-man-page.patch
Normal file
30
0029-alsaloop-add-U-xrun-to-alsaloop.1-man-page.patch
Normal file
@ -0,0 +1,30 @@
|
||||
From b68986fb4a946ef736295d3b2f24f1e6fab1e77d Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Wed, 13 Oct 2010 23:41:29 +0200
|
||||
Subject: [PATCH 29/38] alsaloop: add -U/--xrun to alsaloop.1 man page
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
alsaloop/alsaloop.1 | 6 ++++++
|
||||
1 files changed, 6 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/alsaloop/alsaloop.1 b/alsaloop/alsaloop.1
|
||||
index 0b57b59..65edba1 100644
|
||||
--- a/alsaloop/alsaloop.1
|
||||
+++ b/alsaloop/alsaloop.1
|
||||
@@ -184,6 +184,12 @@ Known OSS attributes:
|
||||
Verbose mode. Use multiple times to increase verbosity.
|
||||
|
||||
|
||||
+.TP
|
||||
+\fI\-U\fP | \fI\-\-xrun\fP
|
||||
+
|
||||
+Verbose xrun profiling.
|
||||
+
|
||||
+
|
||||
.SH EXAMPLES
|
||||
|
||||
.TP
|
||||
--
|
||||
1.7.3.1
|
||||
|
371
0030-alsaloop-fixes-added-W-wake-option.patch
Normal file
371
0030-alsaloop-fixes-added-W-wake-option.patch
Normal file
@ -0,0 +1,371 @@
|
||||
From 513a9c7ad179e9786a7d2ff0aa651d42f9674697 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Thu, 14 Oct 2010 11:17:25 +0200
|
||||
Subject: [PATCH 30/38] alsaloop: fixes, added -W/--wake option
|
||||
|
||||
- added -W/--wake option to reduce poll time
|
||||
- another try to fix the avail_min parameter for playback
|
||||
- fixed initial silence fill
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
alsaloop/alsaloop.1 | 4 ++
|
||||
alsaloop/alsaloop.c | 20 +++++++++--
|
||||
alsaloop/alsaloop.h | 4 ++
|
||||
alsaloop/pcmjob.c | 90 ++++++++++++++++++++++++++++++++++++++-------------
|
||||
alsaloop/test.sh | 17 +++++----
|
||||
5 files changed, 101 insertions(+), 34 deletions(-)
|
||||
|
||||
diff --git a/alsaloop/alsaloop.1 b/alsaloop/alsaloop.1
|
||||
index 65edba1..048d1e0 100644
|
||||
--- a/alsaloop/alsaloop.1
|
||||
+++ b/alsaloop/alsaloop.1
|
||||
@@ -189,6 +189,10 @@ Verbose mode. Use multiple times to increase verbosity.
|
||||
|
||||
Verbose xrun profiling.
|
||||
|
||||
+.TP
|
||||
+\fI\-W <timeout>\fP | \fI\-\-wake=<timeout>\fP
|
||||
+
|
||||
+Set process wake timeout.
|
||||
|
||||
.SH EXAMPLES
|
||||
|
||||
diff --git a/alsaloop/alsaloop.c b/alsaloop/alsaloop.c
|
||||
index 561fdd7..8710dd1 100644
|
||||
--- a/alsaloop/alsaloop.c
|
||||
+++ b/alsaloop/alsaloop.c
|
||||
@@ -56,6 +56,7 @@ struct loopback_thread *threads;
|
||||
int threads_count = 0;
|
||||
pthread_t main_job;
|
||||
int arg_default_xrun = 0;
|
||||
+int arg_default_wake = 0;
|
||||
|
||||
static void my_exit(struct loopback_thread *thread, int exitcode)
|
||||
{
|
||||
@@ -193,6 +194,7 @@ void help(void)
|
||||
"-v,--verbose verbose mode (more -v means more verbose)\n"
|
||||
"-w,--workaround use workaround (serialopen)\n"
|
||||
"-U,--xrun xrun profiling\n"
|
||||
+"-W,--wake process wake timeout in ms\n"
|
||||
);
|
||||
printf("\nRecognized sample formats are:");
|
||||
for (k = 0; k < SND_PCM_FORMAT_LAST; ++k) {
|
||||
@@ -395,12 +397,13 @@ static int parse_config(int argc, char *argv[], snd_output_t *output,
|
||||
char *arg_ossmixers[MAX_MIXERS];
|
||||
int arg_ossmixers_count = 0;
|
||||
int arg_xrun = arg_default_xrun;
|
||||
+ int arg_wake = arg_default_wake;
|
||||
|
||||
morehelp = 0;
|
||||
while (1) {
|
||||
int c;
|
||||
if ((c = getopt_long(argc, argv,
|
||||
- "hdg:P:C:X:Y:l:t:F:f:c:r:s:benvA:S:a:m:T:O:w:U",
|
||||
+ "hdg:P:C:X:Y:l:t:F:f:c:r:s:benvA:S:a:m:T:O:w:UW:",
|
||||
long_option, NULL)) < 0)
|
||||
break;
|
||||
switch (c) {
|
||||
@@ -549,6 +552,11 @@ static int parse_config(int argc, char *argv[], snd_output_t *output,
|
||||
if (cmdline)
|
||||
arg_default_xrun = 1;
|
||||
break;
|
||||
+ case 'W':
|
||||
+ arg_wake = atoi(optarg);
|
||||
+ if (cmdline)
|
||||
+ arg_default_wake = arg_wake;
|
||||
+ break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -587,6 +595,7 @@ static int parse_config(int argc, char *argv[], snd_output_t *output,
|
||||
loop->slave = arg_slave;
|
||||
loop->thread = arg_thread;
|
||||
loop->xrun = arg_xrun;
|
||||
+ loop->wake = arg_wake;
|
||||
err = add_mixers(loop, arg_mixers, arg_mixers_count);
|
||||
if (err < 0) {
|
||||
logit(LOG_CRIT, "Unable to add mixer controls.\n");
|
||||
@@ -691,7 +700,7 @@ static void thread_job1(void *_data)
|
||||
snd_output_t *output = thread->output;
|
||||
struct pollfd *pfds = NULL;
|
||||
int pfds_count = 0;
|
||||
- int i, j, err;
|
||||
+ int i, j, err, wake = 1000000;
|
||||
|
||||
setscheduler();
|
||||
|
||||
@@ -709,7 +718,12 @@ static void thread_job1(void *_data)
|
||||
my_exit(thread, EXIT_FAILURE);
|
||||
}
|
||||
pfds_count += thread->loopbacks[i]->pollfd_count;
|
||||
+ j = thread->loopbacks[i]->wake;
|
||||
+ if (j > 0 && j < wake)
|
||||
+ wake = j;
|
||||
}
|
||||
+ if (wake >= 1000000)
|
||||
+ wake = -1;
|
||||
pfds = calloc(pfds_count, sizeof(struct pollfd));
|
||||
if (pfds == NULL || pfds_count <= 0) {
|
||||
logit(LOG_CRIT, "Poll FDs allocation failed.\n");
|
||||
@@ -727,7 +741,7 @@ static void thread_job1(void *_data)
|
||||
}
|
||||
if (verbose > 10)
|
||||
gettimeofday(&tv1, NULL);
|
||||
- err = poll(pfds, j, -1);
|
||||
+ err = poll(pfds, j, wake);
|
||||
if (err < 0)
|
||||
err = -errno;
|
||||
if (verbose > 10) {
|
||||
diff --git a/alsaloop/alsaloop.h b/alsaloop/alsaloop.h
|
||||
index 839fc6d..e506427 100644
|
||||
--- a/alsaloop/alsaloop.h
|
||||
+++ b/alsaloop/alsaloop.h
|
||||
@@ -146,6 +146,7 @@ struct loopback {
|
||||
sync_type_t sync; /* type of sync */
|
||||
slave_type_t slave;
|
||||
int thread; /* thread number */
|
||||
+ unsigned int wake;
|
||||
/* statistics */
|
||||
double pitch;
|
||||
double pitch_delta;
|
||||
@@ -164,6 +165,9 @@ struct loopback {
|
||||
snd_timestamp_t xrun_last_check;
|
||||
snd_pcm_sframes_t xrun_last_pdelay;
|
||||
snd_pcm_sframes_t xrun_last_cdelay;
|
||||
+ snd_pcm_uframes_t xrun_buf_pcount;
|
||||
+ snd_pcm_uframes_t xrun_buf_ccount;
|
||||
+ unsigned int xrun_out_frames;
|
||||
long xrun_max_proctime;
|
||||
double xrun_max_missing;
|
||||
/* control mixer */
|
||||
diff --git a/alsaloop/pcmjob.c b/alsaloop/pcmjob.c
|
||||
index 0f1a853..6aa8bfe 100644
|
||||
--- a/alsaloop/pcmjob.c
|
||||
+++ b/alsaloop/pcmjob.c
|
||||
@@ -83,16 +83,16 @@ static inline snd_pcm_uframes_t get_whole_latency(struct loopback *loop)
|
||||
}
|
||||
|
||||
static inline unsigned long long
|
||||
- frames_to_time(struct loopback_handle *lhandle,
|
||||
+ frames_to_time(unsigned int rate,
|
||||
snd_pcm_uframes_t frames)
|
||||
{
|
||||
- return (frames * 1000000ULL) / lhandle->rate;
|
||||
+ return (frames * 1000000ULL) / rate;
|
||||
}
|
||||
|
||||
-static inline snd_pcm_uframes_t time_to_frames(struct loopback_handle *lhandle,
|
||||
+static inline snd_pcm_uframes_t time_to_frames(unsigned int rate,
|
||||
unsigned long long time)
|
||||
{
|
||||
- return (time * lhandle->rate) / 1000000ULL;
|
||||
+ return (time * rate) / 1000000ULL;
|
||||
}
|
||||
|
||||
static int setparams_stream(struct loopback_handle *lhandle,
|
||||
@@ -245,12 +245,16 @@ static int setparams_set(struct loopback_handle *lhandle,
|
||||
snd_output_printf(lhandle->loopback->output, "%s: avail_min1=%li\n", lhandle->id, val);
|
||||
} else {
|
||||
if (lhandle == lhandle->loopback->play) {
|
||||
- val = bufsize / 2 + bufsize / 4 + bufsize / 8;
|
||||
- if (val > buffer_size / 4)
|
||||
- val = buffer_size / 4;
|
||||
+ val = bufsize + bufsize / 2;
|
||||
+ if (val < (period_size * 3) / 4)
|
||||
+ val = (period_size * 3) / 4;
|
||||
+ if (val > (buffer_size * 3) / 4)
|
||||
+ val = (buffer_size * 3) / 4;
|
||||
val = buffer_size - val;
|
||||
} else {
|
||||
val = bufsize / 2;
|
||||
+ if (val < period_size / 2)
|
||||
+ val = period_size / 2;
|
||||
if (val > buffer_size / 4)
|
||||
val = buffer_size / 4;
|
||||
}
|
||||
@@ -372,6 +376,11 @@ static void xrun_profile0(struct loopback *loop)
|
||||
getcurtimestamp(&loop->xrun_last_update);
|
||||
loop->xrun_last_pdelay = pdelay;
|
||||
loop->xrun_last_cdelay = cdelay;
|
||||
+ loop->xrun_buf_pcount = loop->play->buf_count;
|
||||
+ loop->xrun_buf_ccount = loop->capt->buf_count;
|
||||
+#ifdef USE_SAMPLERATE
|
||||
+ loop->xrun_out_frames = loop->src_out_frames;
|
||||
+#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,27 +393,45 @@ static inline void xrun_profile(struct loopback *loop)
|
||||
static void xrun_stats0(struct loopback *loop)
|
||||
{
|
||||
snd_timestamp_t t;
|
||||
- double expected, last, wake, check, queued = -1, proc, missing;
|
||||
+ double expected, last, wake, check, queued = -1, proc, missing = -1;
|
||||
+ double maxbuf, pfilled, cfilled, cqueued = -1, avail_min;
|
||||
+ double sincejob;
|
||||
|
||||
expected = ((double)loop->latency /
|
||||
- (double)loop->play->rate) * 1000;
|
||||
+ (double)loop->play->rate_req) * 1000;
|
||||
getcurtimestamp(&t);
|
||||
last = (double)timediff(t, loop->xrun_last_update) / 1000;
|
||||
wake = (double)timediff(t, loop->xrun_last_wake) / 1000;
|
||||
check = (double)timediff(t, loop->xrun_last_check) / 1000;
|
||||
+ sincejob = (double)timediff(t, loop->tstamp_start) / 1000;
|
||||
if (loop->xrun_last_pdelay != XRUN_PROFILE_UNKNOWN)
|
||||
- queued = (((double)loop->xrun_last_pdelay *
|
||||
- loop->play->pitch) /
|
||||
+ queued = ((double)loop->xrun_last_pdelay /
|
||||
+ (double)loop->play->rate) * 1000;
|
||||
+ if (loop->xrun_last_cdelay != XRUN_PROFILE_UNKNOWN)
|
||||
+ cqueued = ((double)loop->xrun_last_cdelay /
|
||||
+ (double)loop->capt->rate) * 1000;
|
||||
+ maxbuf = ((double)loop->play->buffer_size /
|
||||
(double)loop->play->rate) * 1000;
|
||||
proc = (double)loop->xrun_max_proctime / 1000;
|
||||
- missing = last - queued;
|
||||
- if (loop->xrun_max_missing < missing)
|
||||
+ pfilled = ((double)(loop->xrun_buf_pcount + loop->xrun_out_frames) /
|
||||
+ (double)loop->play->rate) * 1000;
|
||||
+ cfilled = ((double)loop->xrun_buf_ccount /
|
||||
+ (double)loop->capt->rate) * 1000;
|
||||
+ avail_min = (((double)loop->play->buffer_size -
|
||||
+ (double)loop->play->avail_min ) /
|
||||
+ (double)loop->play->rate) * 1000;
|
||||
+ avail_min = expected - avail_min;
|
||||
+ if (queued >= 0)
|
||||
+ missing = last - queued;
|
||||
+ if (missing >= 0 && loop->xrun_max_missing < missing)
|
||||
loop->xrun_max_missing = missing;
|
||||
loop->xrun_max_proctime = 0;
|
||||
getcurtimestamp(&t);
|
||||
- logit(LOG_INFO, " last write before %.4fms, queued %.4fms -> missing %.4fms\n", last, queued, missing);
|
||||
+ logit(LOG_INFO, " last write before %.4fms, queued %.4fms/%.4fms -> missing %.4fms\n", last, queued, cqueued, missing);
|
||||
logit(LOG_INFO, " expected %.4fms, processing %.4fms, max missing %.4fms\n", expected, proc, loop->xrun_max_missing);
|
||||
- logit(LOG_INFO, " last wake before %.4fms, last check before %.4fms\n", wake, check);
|
||||
+ logit(LOG_INFO, " last wake %.4fms, last check %.4fms, avail_min %.4fms\n", wake, check, avail_min);
|
||||
+ logit(LOG_INFO, " max buf %.4fms, pfilled %.4fms, cfilled %.4fms\n", maxbuf, pfilled, cfilled);
|
||||
+ logit(LOG_INFO, " job started before %.4fms\n", sincejob);
|
||||
}
|
||||
|
||||
static inline void xrun_stats(struct loopback *loop)
|
||||
@@ -483,7 +510,14 @@ static void buf_add_src(struct loopback *loop)
|
||||
count1 = count;
|
||||
if (count1 + pos1 > capt->buf_size)
|
||||
count1 = capt->buf_size - pos1;
|
||||
- src_short_to_float_array((short *)(capt->buf +
|
||||
+ if (capt->format == SND_PCM_FORMAT_S32)
|
||||
+ src_int_to_float_array((int *)(capt->buf +
|
||||
+ pos1 * capt->frame_size),
|
||||
+ loop->src_data.data_in +
|
||||
+ pos * capt->channels,
|
||||
+ count1 * capt->channels);
|
||||
+ else
|
||||
+ src_short_to_float_array((short *)(capt->buf +
|
||||
pos1 * capt->frame_size),
|
||||
loop->src_data.data_in +
|
||||
pos * capt->channels,
|
||||
@@ -514,7 +548,14 @@ static void buf_add_src(struct loopback *loop)
|
||||
count1 = buf_avail(play);
|
||||
if (count1 == 0)
|
||||
break;
|
||||
- src_float_to_short_array(loop->src_data.data_out +
|
||||
+ if (capt->format == SND_PCM_FORMAT_S32)
|
||||
+ src_float_to_int_array(loop->src_data.data_out +
|
||||
+ pos * play->channels,
|
||||
+ (int *)(play->buf +
|
||||
+ pos1 * play->frame_size),
|
||||
+ count1 * play->channels);
|
||||
+ else
|
||||
+ src_float_to_short_array(loop->src_data.data_out +
|
||||
pos * play->channels,
|
||||
(short *)(play->buf +
|
||||
pos1 * play->frame_size),
|
||||
@@ -691,12 +732,12 @@ static int writeit(struct loopback_handle *lhandle)
|
||||
fwrite(lhandle->buf + lhandle->buf_pos * lhandle->frame_size,
|
||||
r, lhandle->frame_size, lhandle->loopback->pfile);
|
||||
#endif
|
||||
- xrun_profile(lhandle->loopback);
|
||||
res += r;
|
||||
lhandle->counter += r;
|
||||
lhandle->buf_count -= r;
|
||||
lhandle->buf_pos += r;
|
||||
lhandle->buf_pos %= lhandle->buf_size;
|
||||
+ xrun_profile(lhandle->loopback);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -919,6 +960,7 @@ static int xrun_sync(struct loopback *loop)
|
||||
snd_output_printf(loop->output, "%s: sync verify: %li\n", loop->id, delay1);
|
||||
}
|
||||
}
|
||||
+ loop->xrun_max_proctime = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1344,11 +1386,11 @@ int pcmjob_start(struct loopback *loop)
|
||||
loop->reinit = 0;
|
||||
loop->use_samplerate = 0;
|
||||
if (loop->latency_req) {
|
||||
- loop->latency_reqtime = frames_to_time(loop->play,
|
||||
+ loop->latency_reqtime = frames_to_time(loop->play->rate_req,
|
||||
loop->latency_req);
|
||||
loop->latency_req = 0;
|
||||
}
|
||||
- loop->latency = time_to_frames(loop->play, loop->latency_reqtime);
|
||||
+ loop->latency = time_to_frames(loop->play->rate_req, loop->latency_reqtime);
|
||||
if ((err = setparams(loop, loop->latency/2)) < 0)
|
||||
goto __error;
|
||||
if (verbose)
|
||||
@@ -1406,9 +1448,11 @@ int pcmjob_start(struct loopback *loop)
|
||||
goto __error;
|
||||
}
|
||||
if (loop->use_samplerate) {
|
||||
- if (loop->capt->format != SND_PCM_FORMAT_S16 ||
|
||||
- loop->play->format != SND_PCM_FORMAT_S16) {
|
||||
- logit(LOG_CRIT, "samplerate conversion supports only %s format (play=%s, capt=%s)\n", snd_pcm_format_name(SND_PCM_FORMAT_S16), snd_pcm_format_name(loop->play->format), snd_pcm_format_name(loop->capt->format));
|
||||
+ if ((loop->capt->format != SND_PCM_FORMAT_S16 ||
|
||||
+ loop->play->format != SND_PCM_FORMAT_S16) &&
|
||||
+ (loop->capt->format != SND_PCM_FORMAT_S32 ||
|
||||
+ loop->play->format != SND_PCM_FORMAT_S32)) {
|
||||
+ logit(LOG_CRIT, "samplerate conversion supports only %s or %s formats (play=%s, capt=%s)\n", snd_pcm_format_name(SND_PCM_FORMAT_S16), snd_pcm_format_name(SND_PCM_FORMAT_S32), snd_pcm_format_name(loop->play->format), snd_pcm_format_name(loop->capt->format));
|
||||
loop->use_samplerate = 0;
|
||||
err = -EIO;
|
||||
goto __error;
|
||||
diff --git a/alsaloop/test.sh b/alsaloop/test.sh
|
||||
index ff9aa4e..fac72b9 100755
|
||||
--- a/alsaloop/test.sh
|
||||
+++ b/alsaloop/test.sh
|
||||
@@ -34,19 +34,20 @@ EOF
|
||||
|
||||
test3() {
|
||||
echo "TEST3"
|
||||
+ LATENCY=180000
|
||||
cat > $CFGFILE <<EOF
|
||||
--C hw:1,0,0 -P plug:dmix:0 --tlatency 30000 --thread 0 \
|
||||
+-C hw:1,0,0 -P plug:dmix:0 --tlatency $LATENCY --thread 0 \
|
||||
--mixer "name='Master Playback Volume'@name='Master Playback Volume'" \
|
||||
--mixer "name='Master Playback Switch'@name='Master Playback Switch'" \
|
||||
--mixer "name='PCM Playback Volume'" \
|
||||
--ossmixer "name=Master@VOLUME"
|
||||
--C hw:1,0,1 -P plug:dmix:0 --tlatency 30000 --thread 1
|
||||
--C hw:1,0,2 -P plug:dmix:0 --tlatency 30000 --thread 2
|
||||
--C hw:1,0,3 -P plug:dmix:0 --tlatency 30000 --thread 3
|
||||
--C hw:1,0,4 -P plug:dmix:0 --tlatency 30000 --thread 4
|
||||
--C hw:1,0,5 -P plug:dmix:0 --tlatency 30000 --thread 5
|
||||
--C hw:1,0,6 -P plug:dmix:0 --tlatency 30000 --thread 6
|
||||
--C hw:1,0,7 -P plug:dmix:0 --tlatency 30000 --thread 7
|
||||
+-C hw:1,0,1 -P plug:dmix:0 --tlatency $LATENCY --thread 1
|
||||
+-C hw:1,0,2 -P plug:dmix:0 --tlatency $LATENCY --thread 2
|
||||
+-C hw:1,0,3 -P plug:dmix:0 --tlatency $LATENCY --thread 3
|
||||
+-C hw:1,0,4 -P plug:dmix:0 --tlatency $LATENCY --thread 4
|
||||
+-C hw:1,0,5 -P plug:dmix:0 --tlatency $LATENCY --thread 5
|
||||
+-C hw:1,0,6 -P plug:dmix:0 --tlatency $LATENCY --thread 6
|
||||
+-C hw:1,0,7 -P plug:dmix:0 --tlatency $LATENCY --thread 7
|
||||
EOF
|
||||
$DBG ./alsaloop --config $CFGFILE $ARGS
|
||||
}
|
||||
--
|
||||
1.7.3.1
|
||||
|
26
0031-alsaloop-Fix-latency-print.patch
Normal file
26
0031-alsaloop-Fix-latency-print.patch
Normal file
@ -0,0 +1,26 @@
|
||||
From 1ae28cae89a12ed39532bc2a3596e4efa0189e4c Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Thu, 14 Oct 2010 15:39:28 +0200
|
||||
Subject: [PATCH 31/38] alsaloop: Fix latency print
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
alsaloop/pcmjob.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/alsaloop/pcmjob.c b/alsaloop/pcmjob.c
|
||||
index 6aa8bfe..925380c 100644
|
||||
--- a/alsaloop/pcmjob.c
|
||||
+++ b/alsaloop/pcmjob.c
|
||||
@@ -1394,7 +1394,7 @@ int pcmjob_start(struct loopback *loop)
|
||||
if ((err = setparams(loop, loop->latency/2)) < 0)
|
||||
goto __error;
|
||||
if (verbose)
|
||||
- showlatency(loop->output, loop->latency, loop->play->rate, "Latency");
|
||||
+ showlatency(loop->output, loop->latency, loop->play->rate_req, "Latency");
|
||||
if (loop->play->access == loop->capt->access &&
|
||||
loop->play->format == loop->capt->format &&
|
||||
loop->play->rate == loop->capt->rate &&
|
||||
--
|
||||
1.7.3.1
|
||||
|
32
0032-speaker-test-Don-t-retry-after-fatal-errors.patch
Normal file
32
0032-speaker-test-Don-t-retry-after-fatal-errors.patch
Normal file
@ -0,0 +1,32 @@
|
||||
From b67d215d20bcf546617de962dec60cc29b238e4e Mon Sep 17 00:00:00 2001
|
||||
From: David Henningsson <david.henningsson@canonical.com>
|
||||
Date: Fri, 15 Oct 2010 12:30:44 +0200
|
||||
Subject: [PATCH 32/38] speaker-test: Don't retry after fatal errors
|
||||
|
||||
Fixup commit 9b1a2566: Remove error loop
|
||||
|
||||
Signed-off-by: David Henningsson <david.henningsson@canonical.com>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
speaker-test/speaker-test.c | 4 ++--
|
||||
1 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/speaker-test/speaker-test.c b/speaker-test/speaker-test.c
|
||||
index 458a8d7..3029110 100644
|
||||
--- a/speaker-test/speaker-test.c
|
||||
+++ b/speaker-test/speaker-test.c
|
||||
@@ -993,9 +993,9 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
}
|
||||
|
||||
- while ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
|
||||
+ if ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
|
||||
printf(_("Playback open error: %d,%s\n"), err,snd_strerror(err));
|
||||
- sleep(1);
|
||||
+ exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if ((err = set_hwparams(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
|
||||
--
|
||||
1.7.3.1
|
||||
|
104
0033-alsaloop-Delay-the-restart-a-bit-to-handle-snd-aloop.patch
Normal file
104
0033-alsaloop-Delay-the-restart-a-bit-to-handle-snd-aloop.patch
Normal file
@ -0,0 +1,104 @@
|
||||
From d53eb0309df34f058b33c18210c8949c8a2d8b8e Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Wed, 20 Oct 2010 09:26:24 +0200
|
||||
Subject: [PATCH 33/38] alsaloop: Delay the restart a bit (to handle snd-aloop playback xruns better)
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
alsaloop/alsaloop.h | 2 ++
|
||||
alsaloop/pcmjob.c | 33 ++++++++++++++++++++++++++-------
|
||||
2 files changed, 28 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/alsaloop/alsaloop.h b/alsaloop/alsaloop.h
|
||||
index e506427..8dc445a 100644
|
||||
--- a/alsaloop/alsaloop.h
|
||||
+++ b/alsaloop/alsaloop.h
|
||||
@@ -143,6 +143,8 @@ struct loopback {
|
||||
unsigned int linked:1; /* linked streams */
|
||||
unsigned int reinit:1;
|
||||
unsigned int running:1;
|
||||
+ unsigned int stop_pending:1;
|
||||
+ snd_pcm_uframes_t stop_count;
|
||||
sync_type_t sync; /* type of sync */
|
||||
slave_type_t slave;
|
||||
int thread; /* thread number */
|
||||
diff --git a/alsaloop/pcmjob.c b/alsaloop/pcmjob.c
|
||||
index 925380c..23270a0 100644
|
||||
--- a/alsaloop/pcmjob.c
|
||||
+++ b/alsaloop/pcmjob.c
|
||||
@@ -738,6 +738,15 @@ static int writeit(struct loopback_handle *lhandle)
|
||||
lhandle->buf_pos += r;
|
||||
lhandle->buf_pos %= lhandle->buf_size;
|
||||
xrun_profile(lhandle->loopback);
|
||||
+ if (lhandle->loopback->stop_pending) {
|
||||
+ lhandle->loopback->stop_count += r;
|
||||
+ if (lhandle->loopback->stop_count * lhandle->pitch >
|
||||
+ lhandle->loopback->latency * 3) {
|
||||
+ lhandle->loopback->stop_pending = 0;
|
||||
+ lhandle->loopback->reinit = 1;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -1521,6 +1530,7 @@ int pcmjob_start(struct loopback *loop)
|
||||
goto __error;
|
||||
}
|
||||
loop->running = 1;
|
||||
+ loop->stop_pending = 0;
|
||||
if (loop->xrun) {
|
||||
getcurtimestamp(&loop->xrun_last_update);
|
||||
loop->xrun_last_pdelay = XRUN_PROFILE_UNKNOWN;
|
||||
@@ -1638,6 +1648,7 @@ static int ctl_event_check(snd_ctl_elem_value_t *val, snd_ctl_event_t *ev)
|
||||
static int handle_ctl_events(struct loopback_handle *lhandle,
|
||||
unsigned short events)
|
||||
{
|
||||
+ struct loopback *loop = lhandle->loopback;
|
||||
snd_ctl_event_t *ev;
|
||||
int err;
|
||||
|
||||
@@ -1647,16 +1658,24 @@ static int handle_ctl_events(struct loopback_handle *lhandle,
|
||||
break;
|
||||
if (snd_ctl_event_get_type(ev) != SND_CTL_EVENT_ELEM)
|
||||
continue;
|
||||
- if (lhandle == lhandle->loopback->play)
|
||||
+ if (lhandle == loop->play)
|
||||
goto __ctl_check;
|
||||
if (verbose > 6)
|
||||
- snd_output_printf(lhandle->loopback->output, "%s: ctl event!!!! %s\n", lhandle->id, snd_ctl_event_elem_get_name(ev));
|
||||
+ snd_output_printf(loop->output, "%s: ctl event!!!! %s\n", lhandle->id, snd_ctl_event_elem_get_name(ev));
|
||||
if (ctl_event_check(lhandle->ctl_active, ev)) {
|
||||
err = get_active(lhandle);
|
||||
if (verbose > 7)
|
||||
- snd_output_printf(lhandle->loopback->output, "%s: ctl event active %i\n", lhandle->id, err);
|
||||
- if (err != lhandle->loopback->running)
|
||||
- goto __restart;
|
||||
+ snd_output_printf(loop->output, "%s: ctl event active %i\n", lhandle->id, err);
|
||||
+ if (!err) {
|
||||
+ if (lhandle->loopback->running) {
|
||||
+ loop->stop_pending = 1;
|
||||
+ loop->stop_count = 0;
|
||||
+ }
|
||||
+ } else {
|
||||
+ loop->stop_pending = 0;
|
||||
+ if (loop->running == 0)
|
||||
+ goto __restart;
|
||||
+ }
|
||||
} else if (ctl_event_check(lhandle->ctl_format, ev)) {
|
||||
err = get_format(lhandle);
|
||||
if (lhandle->format != err)
|
||||
@@ -1676,8 +1695,8 @@ static int handle_ctl_events(struct loopback_handle *lhandle,
|
||||
return 0;
|
||||
|
||||
__restart:
|
||||
- pcmjob_stop(lhandle->loopback);
|
||||
- err = pcmjob_start(lhandle->loopback);
|
||||
+ pcmjob_stop(loop);
|
||||
+ err = pcmjob_start(loop);
|
||||
if (err < 0)
|
||||
return err;
|
||||
return 1;
|
||||
--
|
||||
1.7.3.1
|
||||
|
95
0034-alsaloop-rework-the-ctl-event-handling-routine.patch
Normal file
95
0034-alsaloop-rework-the-ctl-event-handling-routine.patch
Normal file
@ -0,0 +1,95 @@
|
||||
From 7a11a2b5464e86573f01af6cf4637ffdc0351478 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Thu, 21 Oct 2010 20:38:06 +0200
|
||||
Subject: [PATCH 34/38] alsaloop: rework the ctl event handling routine
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
alsaloop/pcmjob.c | 51 +++++++++++++++++++++++++++------------------------
|
||||
1 files changed, 27 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/alsaloop/pcmjob.c b/alsaloop/pcmjob.c
|
||||
index 23270a0..0b84803 100644
|
||||
--- a/alsaloop/pcmjob.c
|
||||
+++ b/alsaloop/pcmjob.c
|
||||
@@ -1650,7 +1650,7 @@ static int handle_ctl_events(struct loopback_handle *lhandle,
|
||||
{
|
||||
struct loopback *loop = lhandle->loopback;
|
||||
snd_ctl_event_t *ev;
|
||||
- int err;
|
||||
+ int err, restart = 0;
|
||||
|
||||
snd_ctl_event_alloca(&ev);
|
||||
while ((err = snd_ctl_read(lhandle->ctl, ev)) != 0 && err != -EAGAIN) {
|
||||
@@ -1663,42 +1663,45 @@ static int handle_ctl_events(struct loopback_handle *lhandle,
|
||||
if (verbose > 6)
|
||||
snd_output_printf(loop->output, "%s: ctl event!!!! %s\n", lhandle->id, snd_ctl_event_elem_get_name(ev));
|
||||
if (ctl_event_check(lhandle->ctl_active, ev)) {
|
||||
- err = get_active(lhandle);
|
||||
- if (verbose > 7)
|
||||
- snd_output_printf(loop->output, "%s: ctl event active %i\n", lhandle->id, err);
|
||||
- if (!err) {
|
||||
- if (lhandle->loopback->running) {
|
||||
- loop->stop_pending = 1;
|
||||
- loop->stop_count = 0;
|
||||
- }
|
||||
- } else {
|
||||
- loop->stop_pending = 0;
|
||||
- if (loop->running == 0)
|
||||
- goto __restart;
|
||||
- }
|
||||
+ continue;
|
||||
} else if (ctl_event_check(lhandle->ctl_format, ev)) {
|
||||
err = get_format(lhandle);
|
||||
if (lhandle->format != err)
|
||||
- goto __restart;
|
||||
+ restart = 1;
|
||||
+ continue;
|
||||
} else if (ctl_event_check(lhandle->ctl_rate, ev)) {
|
||||
err = get_rate(lhandle);
|
||||
if (lhandle->rate != err)
|
||||
- goto __restart;
|
||||
+ restart = 1;
|
||||
+ continue;
|
||||
} else if (ctl_event_check(lhandle->ctl_channels, ev)) {
|
||||
err = get_channels(lhandle);
|
||||
if (lhandle->channels != err)
|
||||
- goto __restart;
|
||||
+ restart = 1;
|
||||
+ continue;
|
||||
}
|
||||
__ctl_check:
|
||||
control_event(lhandle, ev);
|
||||
}
|
||||
- return 0;
|
||||
-
|
||||
- __restart:
|
||||
- pcmjob_stop(loop);
|
||||
- err = pcmjob_start(loop);
|
||||
- if (err < 0)
|
||||
- return err;
|
||||
+ err = get_active(lhandle);
|
||||
+ if (verbose > 7)
|
||||
+ snd_output_printf(loop->output, "%s: ctl event active %i\n", lhandle->id, err);
|
||||
+ if (!err) {
|
||||
+ if (lhandle->loopback->running) {
|
||||
+ loop->stop_pending = 1;
|
||||
+ loop->stop_count = 0;
|
||||
+ }
|
||||
+ } else {
|
||||
+ loop->stop_pending = 0;
|
||||
+ if (loop->running == 0)
|
||||
+ restart = 1;
|
||||
+ }
|
||||
+ if (restart) {
|
||||
+ pcmjob_stop(loop);
|
||||
+ err = pcmjob_start(loop);
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
+ }
|
||||
return 1;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.3.1
|
||||
|
88
0035-alsamixer-remove-obsolete-e-mail.patch
Normal file
88
0035-alsamixer-remove-obsolete-e-mail.patch
Normal file
@ -0,0 +1,88 @@
|
||||
From f2e9e9a5b017a3834941256da52e1d608f9c4c7b Mon Sep 17 00:00:00 2001
|
||||
From: Clemens Ladisch <clemens@ladisch.de>
|
||||
Date: Wed, 10 Nov 2010 10:14:53 +0100
|
||||
Subject: [PATCH 35/38] alsamixer: remove obsolete e-mail
|
||||
|
||||
Tim Janik's e-mail address is no longer valid.
|
||||
|
||||
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
|
||||
---
|
||||
alsamixer/cli.c | 2 +-
|
||||
alsamixer/colors.c | 2 +-
|
||||
alsamixer/mixer_controls.c | 2 +-
|
||||
alsamixer/mixer_widget.c | 4 ++--
|
||||
alsamixer/textbox.c | 2 +-
|
||||
5 files changed, 6 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/alsamixer/cli.c b/alsamixer/cli.c
|
||||
index ab6255f..3898196 100644
|
||||
--- a/alsamixer/cli.c
|
||||
+++ b/alsamixer/cli.c
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* alsamixer - curses mixer for the ALSA project
|
||||
- * Copyright (c) 1998,1999 Tim Janik <timj@gtk.org>
|
||||
+ * Copyright (c) 1998,1999 Tim Janik
|
||||
* Jaroslav Kysela <perex@perex.cz>
|
||||
* Copyright (c) 2009 Clemens Ladisch <clemens@ladisch.de>
|
||||
*
|
||||
diff --git a/alsamixer/colors.c b/alsamixer/colors.c
|
||||
index fcceb16..b4b98e5 100644
|
||||
--- a/alsamixer/colors.c
|
||||
+++ b/alsamixer/colors.c
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* colors.c - color and attribute definitions
|
||||
- * Copyright (c) 1998,1999 Tim Janik <timj@gtk.org>
|
||||
+ * Copyright (c) 1998,1999 Tim Janik
|
||||
* Jaroslav Kysela <perex@perex.cz>
|
||||
* Copyright (c) 2009 Clemens Ladisch <clemens@ladisch.de>
|
||||
*
|
||||
diff --git a/alsamixer/mixer_controls.c b/alsamixer/mixer_controls.c
|
||||
index 796df7b..cc98b64 100644
|
||||
--- a/alsamixer/mixer_controls.c
|
||||
+++ b/alsamixer/mixer_controls.c
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* mixer_controls.c - handles mixer controls and mapping from selems
|
||||
- * Copyright (c) 1998,1999 Tim Janik <timj@gtk.org>
|
||||
+ * Copyright (c) 1998,1999 Tim Janik
|
||||
* Jaroslav Kysela <perex@perex.cz>
|
||||
* Copyright (c) 2009 Clemens Ladisch <clemens@ladisch.de>
|
||||
*
|
||||
diff --git a/alsamixer/mixer_widget.c b/alsamixer/mixer_widget.c
|
||||
index 796ea1d..c8ca156 100644
|
||||
--- a/alsamixer/mixer_widget.c
|
||||
+++ b/alsamixer/mixer_widget.c
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* mixer_widget.c - mixer widget and keys handling
|
||||
- * Copyright (c) 1998,1999 Tim Janik <timj@gtk.org>
|
||||
+ * Copyright (c) 1998,1999 Tim Janik
|
||||
* Jaroslav Kysela <perex@perex.cz>
|
||||
* Copyright (c) 2009 Clemens Ladisch <clemens@ladisch.de>
|
||||
*
|
||||
@@ -211,7 +211,7 @@ static void show_help(void)
|
||||
_("; ' Toggle left/right capture"),
|
||||
"",
|
||||
_("Authors:"),
|
||||
- _(" Tim Janik <timj@gtk.org>"),
|
||||
+ _(" Tim Janik"),
|
||||
_(" Jaroslav Kysela <perex@perex.cz>"),
|
||||
_(" Clemens Ladisch <clemens@ladisch.de>"),
|
||||
};
|
||||
diff --git a/alsamixer/textbox.c b/alsamixer/textbox.c
|
||||
index d743a14..a979d3c 100644
|
||||
--- a/alsamixer/textbox.c
|
||||
+++ b/alsamixer/textbox.c
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* textbox.c - show a text box for messages, files or help
|
||||
- * Copyright (c) 1998,1999 Tim Janik <timj@gtk.org>
|
||||
+ * Copyright (c) 1998,1999 Tim Janik
|
||||
* Jaroslav Kysela <perex@perex.cz>
|
||||
* Copyright (c) 2009 Clemens Ladisch <clemens@ladisch.de>
|
||||
*
|
||||
--
|
||||
1.7.3.1
|
||||
|
1170
0036-update-German-translations.patch
Normal file
1170
0036-update-German-translations.patch
Normal file
File diff suppressed because it is too large
Load Diff
211
0037-alsactl-systemd-and-udev-hookup.patch
Normal file
211
0037-alsactl-systemd-and-udev-hookup.patch
Normal file
@ -0,0 +1,211 @@
|
||||
From de7c3eff0e371ce155403bbcdcf81ee79266fa0f Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Tue, 23 Nov 2010 01:45:08 +0100
|
||||
Subject: [PATCH 37/38] alsactl: systemd and udev hookup
|
||||
|
||||
Add minimal systemd and udev support to alsactl so that mixer settings
|
||||
are restored at boot, when sound cards are plugged in and saved on
|
||||
shutdown.
|
||||
|
||||
This is similar to existing udev/init script solutions in various
|
||||
distributions.
|
||||
|
||||
Note that alsactl is called both synchronously from the udev rules as
|
||||
well as asynchronously at boot. This is intended, and to ensure two
|
||||
things:
|
||||
|
||||
- At boot the asound.state file might not be readable, since it resides
|
||||
on a different file system. That means exclusively restoring sound card
|
||||
settings from udev rules will no suffice, since if the rule is
|
||||
executed at early boot (for example within udev settle) then the file
|
||||
will no be readable and cannot be restored.
|
||||
|
||||
- We need to ensure that applications monitoring sound cards coming and
|
||||
going (such as PA) must not get these events before the mixer settings
|
||||
have been restored. That means the mixer settings must be restored
|
||||
synchronously withing the udev rules, before the events are passed on
|
||||
to the apps.
|
||||
|
||||
That basically means we need to restore the settings once in udev, to
|
||||
deal with sound cards becoming available during runtime. And once in
|
||||
early boot to deal with coldplugged soundcards whose data files might
|
||||
not have been available at time of plugging. Hence we call alsactl
|
||||
twice: one from the udev rule, and once from he systemd unit file.
|
||||
|
||||
Signed-off-by: Lennart Poettering <mznyfn@0pointer.de>
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
Makefile.am | 3 ++
|
||||
alsactl/90-alsa-restore.rules.in | 2 +
|
||||
alsactl/Makefile.am | 46 ++++++++++++++++++++++++++++++++++++++
|
||||
alsactl/alsa-restore.service.in | 11 +++++++++
|
||||
alsactl/alsa-store.service.in | 9 +++++++
|
||||
configure.in | 17 +++++++++++--
|
||||
7 files changed, 88 insertions(+), 3 deletions(-)
|
||||
create mode 100644 alsactl/90-alsa-restore.rules.in
|
||||
create mode 100644 alsactl/alsa-restore.service.in
|
||||
create mode 100644 alsactl/alsa-store.service.in
|
||||
|
||||
diff --git a/Makefile.am b/Makefile.am
|
||||
index 9951c46..62e1ba6 100644
|
||||
--- a/Makefile.am
|
||||
+++ b/Makefile.am
|
||||
@@ -37,3 +37,6 @@ dist-hook:
|
||||
else \
|
||||
$(TAR) --create --verbose --file=- $(distdir) | bzip2 -c -9 > $(distdir).tar.bz2 ; \
|
||||
fi
|
||||
+
|
||||
+DISTCHECK_CONFIGURE_FLAGS = \
|
||||
+ --with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
|
||||
diff --git a/alsactl/90-alsa-restore.rules.in b/alsactl/90-alsa-restore.rules.in
|
||||
new file mode 100644
|
||||
index 0000000..0bcee5b
|
||||
--- /dev/null
|
||||
+++ b/alsactl/90-alsa-restore.rules.in
|
||||
@@ -0,0 +1,2 @@
|
||||
+ACTION=="add", SUBSYSTEM=="sound", KERNEL=="controlC*", KERNELS=="card*", \
|
||||
+ RUN+="@sbindir@/alsactl restore $attr{number}"
|
||||
diff --git a/alsactl/Makefile.am b/alsactl/Makefile.am
|
||||
index 359f73a..9a2d30e 100644
|
||||
--- a/alsactl/Makefile.am
|
||||
+++ b/alsactl/Makefile.am
|
||||
@@ -10,5 +10,51 @@ EXTRA_DIST=alsactl.1 alsactl_init.xml
|
||||
alsactl_SOURCES=alsactl.c state.c utils.c init_parse.c
|
||||
noinst_HEADERS=alsactl.h list.h init_sysdeps.c init_utils_string.c init_utils_run.c init_sysfs.c
|
||||
|
||||
+udevrulesdir=/lib/udev/rules.d
|
||||
+
|
||||
+dist_udevrules_DATA = \
|
||||
+ 90-alsa-restore.rules
|
||||
+
|
||||
+if HAVE_SYSTEMD
|
||||
+
|
||||
+systemdsystemunit_DATA = \
|
||||
+ alsa-store.service \
|
||||
+ alsa-restore.service
|
||||
+
|
||||
+install-data-hook:
|
||||
+ $(MKDIR_P) -m 0755 \
|
||||
+ $(DESTDIR)$(systemdsystemunitdir)/basic.target.wants \
|
||||
+ $(DESTDIR)$(systemdsystemunitdir)/shutdown.target.wants
|
||||
+ ( cd $(DESTDIR)$(systemdsystemunitdir)/basic.target.wants && \
|
||||
+ rm -f alsa-restore.service && \
|
||||
+ $(LN_S) ../alsa-restore.service alsa-restore.service )
|
||||
+ ( cd $(DESTDIR)$(systemdsystemunitdir)/shutdown.target.wants && \
|
||||
+ rm -f alsa-store.service && \
|
||||
+ $(LN_S) ../alsa-store.service alsa-store.service )
|
||||
+
|
||||
+endif
|
||||
+
|
||||
+edit = \
|
||||
+ sed $(SED) -r 's,@sbindir\@,$(sbindir),g' < $< > $@ || rm $@
|
||||
+
|
||||
+alsa-store.service: alsa-store.service.in
|
||||
+ $(edit)
|
||||
+
|
||||
+alsa-restore.service: alsa-restore.service.in
|
||||
+ $(edit)
|
||||
+
|
||||
+90-alsa-restore.rules: 90-alsa-restore.rules.in
|
||||
+ $(edit)
|
||||
+
|
||||
+EXTRA_DIST += \
|
||||
+ alsa-store.service.in \
|
||||
+ alsa-restore.service.in \
|
||||
+ 90-alsa-restore.rules.in
|
||||
+
|
||||
+CLEANFILES = \
|
||||
+ alsa-store.service \
|
||||
+ alsa-restore.service \
|
||||
+ 90-alsa-restore.rules
|
||||
+
|
||||
%.7: %.xml
|
||||
xmlto man $?
|
||||
diff --git a/alsactl/alsa-restore.service.in b/alsactl/alsa-restore.service.in
|
||||
new file mode 100644
|
||||
index 0000000..e97d196
|
||||
--- /dev/null
|
||||
+++ b/alsactl/alsa-restore.service.in
|
||||
@@ -0,0 +1,11 @@
|
||||
+[Unit]
|
||||
+Description=Restore Sound Card State
|
||||
+DefaultDependencies=no
|
||||
+After=sysinit.target
|
||||
+Before=shutdown.target
|
||||
+Conflicts=shutdown.target
|
||||
+
|
||||
+[Service]
|
||||
+Type=oneshot
|
||||
+ExecStart=-@sbindir@/alsactl restore
|
||||
+StandardOutput=syslog
|
||||
diff --git a/alsactl/alsa-store.service.in b/alsactl/alsa-store.service.in
|
||||
new file mode 100644
|
||||
index 0000000..0e2823c
|
||||
--- /dev/null
|
||||
+++ b/alsactl/alsa-store.service.in
|
||||
@@ -0,0 +1,9 @@
|
||||
+[Unit]
|
||||
+Description=Store Sound Card State
|
||||
+DefaultDependencies=no
|
||||
+Before=shutdown.target
|
||||
+
|
||||
+[Service]
|
||||
+Type=oneshot
|
||||
+ExecStart=@sbindir@/alsactl store
|
||||
+StandardOutput=syslog
|
||||
diff --git a/configure.in b/configure.in
|
||||
index 31fd581..54ea74c 100644
|
||||
--- a/configure.in
|
||||
+++ b/configure.in
|
||||
@@ -26,6 +26,7 @@ fi
|
||||
AC_PROG_CC
|
||||
dnl AC_PROG_CXX
|
||||
AC_PROG_INSTALL
|
||||
+AC_PROG_MKDIR_P
|
||||
AC_PROG_LN_S
|
||||
AM_PATH_ALSA(1.0.16)
|
||||
|
||||
@@ -130,7 +131,7 @@ if test x$alsamixer = xtrue; then
|
||||
CURSES_CFLAGS=`ncursesw5-config --cflags`
|
||||
curseslib="ncursesw"
|
||||
else
|
||||
- AC_CHECK_LIB(ncursesw, initscr,
|
||||
+ AC_CHECK_LIB(ncursesw, initscr,
|
||||
[ CURSESINC='<ncurses.h>'; CURSESLIB='-lncursesw'; curseslib="ncursesw"])
|
||||
fi
|
||||
if test -n "$CURSESINC"; then
|
||||
@@ -147,12 +148,12 @@ if test x$alsamixer = xtrue; then
|
||||
CURSES_CFLAGS=`ncurses5-config --cflags`
|
||||
curseslib="ncurses"
|
||||
else
|
||||
- AC_CHECK_LIB(ncurses, initscr,
|
||||
+ AC_CHECK_LIB(ncurses, initscr,
|
||||
[ CURSESINC='<ncurses.h>'; CURSESLIB='-lncurses'; curseslib="ncurses"])
|
||||
fi
|
||||
fi
|
||||
if test "$curseslib" = "curses" -o "$curseslib" = "auto"; then
|
||||
- AC_CHECK_LIB(curses, initscr,
|
||||
+ AC_CHECK_LIB(curses, initscr,
|
||||
[ CURSESINC='<curses.h>'; CURSESLIB='-lcurses'; curseslib="curses"])
|
||||
fi
|
||||
if test -z "$CURSESINC"; then
|
||||
@@ -278,6 +279,16 @@ SAVE_UTIL_VERSION
|
||||
|
||||
AC_SUBST(LIBRT)
|
||||
|
||||
+dnl Check for systemd
|
||||
+PKG_PROG_PKG_CONFIG
|
||||
+AC_ARG_WITH([systemdsystemunitdir],
|
||||
+ AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]),
|
||||
+ [], [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)])
|
||||
+if test "x$with_systemdsystemunitdir" != xno; then
|
||||
+ AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])
|
||||
+fi
|
||||
+AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno ])
|
||||
+
|
||||
AC_OUTPUT(Makefile alsactl/Makefile alsactl/init/Makefile \
|
||||
alsamixer/Makefile amidi/Makefile amixer/Makefile \
|
||||
m4/Makefile po/Makefile.in \
|
||||
--
|
||||
1.7.3.1
|
||||
|
123
0038-alsactl-Move-asound.state-location-to-var-lib-alsa.patch
Normal file
123
0038-alsactl-Move-asound.state-location-to-var-lib-alsa.patch
Normal file
@ -0,0 +1,123 @@
|
||||
From 81f015f5abdd8e6cfa75e37bd97eb22781019eec Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Tue, 23 Nov 2010 02:59:18 +0100
|
||||
Subject: [PATCH 38/38] alsactl: Move asound.state location to /var/lib/alsa
|
||||
|
||||
.... and add configure switch for it.
|
||||
|
||||
/etc might be on a read-only partition which is not suitable for dynamic
|
||||
data such as the mixer settings. Hence move the location of asound.state
|
||||
to /var/lib.
|
||||
|
||||
This is based on a patch from Ubuntu/Debian which hardcoded the pah in
|
||||
/var/lib.
|
||||
|
||||
Signed-off-by: Lennart Poettering <mznyfn@0pointer.de>
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
---
|
||||
Makefile.am | 3 +++
|
||||
alsaconf/alsaconf.in | 5 +++--
|
||||
alsactl/Makefile.am | 1 +
|
||||
alsactl/alsactl.1 | 4 ++--
|
||||
alsactl/alsactl.c | 4 +++-
|
||||
configure.in | 6 ++++++
|
||||
6 files changed, 18 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/Makefile.am b/Makefile.am
|
||||
index 62e1ba6..48a4780 100644
|
||||
--- a/Makefile.am
|
||||
+++ b/Makefile.am
|
||||
@@ -38,5 +38,8 @@ dist-hook:
|
||||
$(TAR) --create --verbose --file=- $(distdir) | bzip2 -c -9 > $(distdir).tar.bz2 ; \
|
||||
fi
|
||||
|
||||
+install-data-hook:
|
||||
+ $(MKDIR_P) -m 0755 $(DESTDIR)$(ASOUND_STATE_DIR)
|
||||
+
|
||||
DISTCHECK_CONFIGURE_FLAGS = \
|
||||
--with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
|
||||
diff --git a/alsaconf/alsaconf.in b/alsaconf/alsaconf.in
|
||||
index ccc1b37..5c23787 100644
|
||||
--- a/alsaconf/alsaconf.in
|
||||
+++ b/alsaconf/alsaconf.in
|
||||
@@ -956,8 +956,9 @@ If you have a big amplifier, lower your volumes or say no.
|
||||
aplay -N $TESTSOUND
|
||||
fi
|
||||
fi
|
||||
- if [ ! -r /etc/asound.state ]; then
|
||||
- xecho "Saving the mixer setup used for this in /etc/asound.state."
|
||||
+ mkdir -p -m 0755 @ASOUND_STATE_DIR@
|
||||
+ if [ ! -r @ASOUND_STATE_DIR@/asound.state ]; then
|
||||
+ xecho "Saving the mixer setup used for this in @ASOUND_STATE_DIR@/asound.state."
|
||||
$sbindir/alsactl store
|
||||
fi
|
||||
clear
|
||||
diff --git a/alsactl/Makefile.am b/alsactl/Makefile.am
|
||||
index 9a2d30e..721b619 100644
|
||||
--- a/alsactl/Makefile.am
|
||||
+++ b/alsactl/Makefile.am
|
||||
@@ -8,6 +8,7 @@ endif
|
||||
EXTRA_DIST=alsactl.1 alsactl_init.xml
|
||||
|
||||
alsactl_SOURCES=alsactl.c state.c utils.c init_parse.c
|
||||
+alsactl_CFLAGS=$(AM_CFLAGS) -DSYS_ASOUNDRC=\"$(ASOUND_STATE_DIR)/asound.state\"
|
||||
noinst_HEADERS=alsactl.h list.h init_sysdeps.c init_utils_string.c init_utils_run.c init_sysfs.c
|
||||
|
||||
udevrulesdir=/lib/udev/rules.d
|
||||
diff --git a/alsactl/alsactl.1 b/alsactl/alsactl.1
|
||||
index eb3cbd1..eb5968c 100644
|
||||
--- a/alsactl/alsactl.1
|
||||
+++ b/alsactl/alsactl.1
|
||||
@@ -43,7 +43,7 @@ Print alsactl version number.
|
||||
|
||||
.TP
|
||||
\fI\-f, \-\-file\fP
|
||||
-Select the configuration file to use. The default is /etc/asound.state.
|
||||
+Select the configuration file to use. The default is /var/lib/alsa/asound.state.
|
||||
|
||||
.TP
|
||||
\fI\-F, \-\-force\fP
|
||||
@@ -90,7 +90,7 @@ The configuration file for init. By default, PREFIX/share/alsa/init/00main
|
||||
is used.
|
||||
|
||||
.SH FILES
|
||||
-\fI/etc/asound.state\fP (or whatever file you specify with the
|
||||
+\fI/var/lib/alsa/asound.state\fP (or whatever file you specify with the
|
||||
\fB\-f\fP flag) is used to store current settings for your
|
||||
soundcards. The settings include all the usual soundcard mixer
|
||||
settings. More importantly, alsactl is
|
||||
diff --git a/alsactl/alsactl.c b/alsactl/alsactl.c
|
||||
index 3b5dfda..c2120bd 100644
|
||||
--- a/alsactl/alsactl.c
|
||||
+++ b/alsactl/alsactl.c
|
||||
@@ -30,7 +30,9 @@
|
||||
#include <alsa/asoundlib.h>
|
||||
#include "alsactl.h"
|
||||
|
||||
-#define SYS_ASOUNDRC "/etc/asound.state"
|
||||
+#ifndef SYS_ASOUNDRC
|
||||
+#define SYS_ASOUNDRC "/var/lib/alsa/asound.state"
|
||||
+#endif
|
||||
|
||||
int debugflag = 0;
|
||||
int force_restore = 1;
|
||||
diff --git a/configure.in b/configure.in
|
||||
index 54ea74c..94a2b17 100644
|
||||
--- a/configure.in
|
||||
+++ b/configure.in
|
||||
@@ -289,6 +289,12 @@ if test "x$with_systemdsystemunitdir" != xno; then
|
||||
fi
|
||||
AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno ])
|
||||
|
||||
+AC_ARG_WITH(ASOUND_STATE_DIR,
|
||||
+ AS_HELP_STRING([--with-asound-state-dir=DIR], [Directory to place asound.state file in]),
|
||||
+ [ASOUND_STATE_DIR="$withval"],
|
||||
+ [ASOUND_STATE_DIR="/var/lib/alsa"])
|
||||
+AC_SUBST(ASOUND_STATE_DIR)
|
||||
+
|
||||
AC_OUTPUT(Makefile alsactl/Makefile alsactl/init/Makefile \
|
||||
alsamixer/Makefile amidi/Makefile amixer/Makefile \
|
||||
m4/Makefile po/Makefile.in \
|
||||
--
|
||||
1.7.3.1
|
||||
|
34
0039-configure.in-Fix-variable-name.patch
Normal file
34
0039-configure.in-Fix-variable-name.patch
Normal file
@ -0,0 +1,34 @@
|
||||
From 53b08bfc1451937bb19a86e4b116d28cd15c81ac Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Ozan=20=C3=87a=C4=9Flayan?= <ozan@pardus.org.tr>
|
||||
Date: Thu, 25 Nov 2010 09:36:37 +0200
|
||||
Subject: [PATCH] configure.in: Fix variable name
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Fix variable name for --with-asound-state-dir as currently we have
|
||||
to pass --with-ASOUND_STATE_DIR= which is wrong and inconsistent with
|
||||
the other switches.
|
||||
|
||||
Signed-off-by: Ozan Çağlayan <ozan@pardus.org.tr>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
---
|
||||
configure.in | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/configure.in b/configure.in
|
||||
index 94a2b17..77778da 100644
|
||||
--- a/configure.in
|
||||
+++ b/configure.in
|
||||
@@ -289,7 +289,7 @@ if test "x$with_systemdsystemunitdir" != xno; then
|
||||
fi
|
||||
AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno ])
|
||||
|
||||
-AC_ARG_WITH(ASOUND_STATE_DIR,
|
||||
+AC_ARG_WITH([asound-state-dir],
|
||||
AS_HELP_STRING([--with-asound-state-dir=DIR], [Directory to place asound.state file in]),
|
||||
[ASOUND_STATE_DIR="$withval"],
|
||||
[ASOUND_STATE_DIR="/var/lib/alsa"])
|
||||
--
|
||||
1.7.3.1
|
||||
|
2200
alsa-utils-po-pre-patch.diff
Normal file
2200
alsa-utils-po-pre-patch.diff
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,42 @@
|
||||
-------------------------------------------------------------------
|
||||
Fri Nov 26 09:05:03 CET 2010 - tiwai@suse.de
|
||||
|
||||
- backport GIT PATCHES:
|
||||
* A few alsactl init fix patches:
|
||||
0014-alsactl-init-Handle-Capture-Source-and-Mic-Boost-in-.patch
|
||||
0015-alsactl-init-Initialize-also-Master-Front-Playback-V.patch
|
||||
* amixer control-id parse fix
|
||||
0016-amixer-fix-parsing-of-control-ID-name.patch
|
||||
* new aloop utility
|
||||
0017-Introduce-alsaloop-utility.patch
|
||||
0018-alsaloop-Fix-loopbacks-pointer-initialization-and-al.patch
|
||||
0019-alsaloop-Fix-thread-handling.patch
|
||||
0020-alsaloop-fix-a-option-and-slave-mode-processing.patch
|
||||
0021-alsaloop-fix-resample-argument-parsing.patch
|
||||
0022-alsaloop-added-resampling-for-unsupported-soundcard-.patch
|
||||
0023-alsaloop-Add-OSS-mixer-redirection-support.patch
|
||||
0024-alsaloop-Fix-command-line-parsing-and-pollfd-initial.patch
|
||||
0025-alsaloop-Fixes-and-added-workaround-option.patch
|
||||
0026-alsaloop-add-pctl-and-cctl-options.patch
|
||||
0027-alsaloop-add-pctl-and-cctl-options-to-man-page.patch
|
||||
0028-alsaloop-added-xrun-profiling-support-U-xrun-added-S.patch
|
||||
0029-alsaloop-add-U-xrun-to-alsaloop.1-man-page.patch
|
||||
0030-alsaloop-fixes-added-W-wake-option.patch
|
||||
0031-alsaloop-Fix-latency-print.patch
|
||||
0033-alsaloop-Delay-the-restart-a-bit-to-handle-snd-aloop.patch
|
||||
0034-alsaloop-rework-the-ctl-event-handling-routine.patch
|
||||
* robusitfy speaker-test
|
||||
0032-speaker-test-Don-t-retry-after-fatal-errors.patch
|
||||
* misc clean up, translation updates
|
||||
0035-alsamixer-remove-obsolete-e-mail.patch
|
||||
0036-update-German-translations.patch
|
||||
* systemd integration
|
||||
0037-alsactl-systemd-and-udev-hookup.patch
|
||||
0038-alsactl-Move-asound.state-location-to-var-lib-alsa.patch
|
||||
0039-configure.in-Fix-variable-name.patch
|
||||
- Use systemd for openSUSE 11.4
|
||||
- Put udev rules into this package instead of alsa.rpm
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Thu Sep 2 16:06:17 CEST 2010 - tiwai@suse.de
|
||||
|
||||
|
@ -17,9 +17,17 @@
|
||||
|
||||
# norootforbuild
|
||||
|
||||
%if %suse_version > 1130
|
||||
%define use_systemd 1
|
||||
%else
|
||||
%define use_systemd 0
|
||||
%endif
|
||||
|
||||
Name: alsa-utils
|
||||
BuildRequires: alsa-devel ncurses-devel xmlto
|
||||
BuildRequires: alsa-devel ncurses-devel xmlto pkgconfig
|
||||
%if %use_systemd
|
||||
BuildRequires: systemd
|
||||
%endif
|
||||
%define package_version 1.0.23
|
||||
License: GPLv2+
|
||||
Group: Productivity/Multimedia/Sound/Players
|
||||
@ -44,8 +52,34 @@ Patch10: 0010-aplay-arecord-term_c_lflag-variable-might-be-unitial.patch
|
||||
Patch11: 0011-alsactl-init-Use-Found-hardware-instead-Unknown-hard.patch
|
||||
Patch12: 0012-alsactl-init-use-generic-method-instead-guess-method.patch
|
||||
Patch13: 0013-alsactl-Change-handling-of-inactive-controls.patch
|
||||
Patch14: 0014-alsactl-init-Handle-Capture-Source-and-Mic-Boost-in-.patch
|
||||
Patch15: 0015-alsactl-init-Initialize-also-Master-Front-Playback-V.patch
|
||||
Patch16: 0016-amixer-fix-parsing-of-control-ID-name.patch
|
||||
Patch17: 0017-Introduce-alsaloop-utility.patch
|
||||
Patch18: 0018-alsaloop-Fix-loopbacks-pointer-initialization-and-al.patch
|
||||
Patch19: 0019-alsaloop-Fix-thread-handling.patch
|
||||
Patch20: 0020-alsaloop-fix-a-option-and-slave-mode-processing.patch
|
||||
Patch21: 0021-alsaloop-fix-resample-argument-parsing.patch
|
||||
Patch22: 0022-alsaloop-added-resampling-for-unsupported-soundcard-.patch
|
||||
Patch23: 0023-alsaloop-Add-OSS-mixer-redirection-support.patch
|
||||
Patch24: 0024-alsaloop-Fix-command-line-parsing-and-pollfd-initial.patch
|
||||
Patch25: 0025-alsaloop-Fixes-and-added-workaround-option.patch
|
||||
Patch26: 0026-alsaloop-add-pctl-and-cctl-options.patch
|
||||
Patch27: 0027-alsaloop-add-pctl-and-cctl-options-to-man-page.patch
|
||||
Patch28: 0028-alsaloop-added-xrun-profiling-support-U-xrun-added-S.patch
|
||||
Patch29: 0029-alsaloop-add-U-xrun-to-alsaloop.1-man-page.patch
|
||||
Patch30: 0030-alsaloop-fixes-added-W-wake-option.patch
|
||||
Patch31: 0031-alsaloop-Fix-latency-print.patch
|
||||
Patch32: 0032-speaker-test-Don-t-retry-after-fatal-errors.patch
|
||||
Patch33: 0033-alsaloop-Delay-the-restart-a-bit-to-handle-snd-aloop.patch
|
||||
Patch34: 0034-alsaloop-rework-the-ctl-event-handling-routine.patch
|
||||
Patch35: 0035-alsamixer-remove-obsolete-e-mail.patch
|
||||
Patch36: 0036-update-German-translations.patch
|
||||
Patch37: 0037-alsactl-systemd-and-udev-hookup.patch
|
||||
Patch38: 0038-alsactl-Move-asound.state-location-to-var-lib-alsa.patch
|
||||
Patch39: 0039-configure.in-Fix-variable-name.patch
|
||||
Patch99: alsa-utils-gettext-version-removal.diff
|
||||
# Patch100: alsa-utils-po-pre-patch.diff
|
||||
Patch100: alsa-utils-po-pre-patch.diff
|
||||
Url: http://www.alsa-project.org/
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
|
||||
@ -65,9 +99,9 @@ Authors:
|
||||
# fix stupid automake's automatic action
|
||||
sed -i -e's/EXTRA_DIST= config.rpath /EXTRA_DIST=/' Makefile.am
|
||||
# fix po changes in tarball first
|
||||
# %patch100 -p1
|
||||
%patch100 -p1
|
||||
# rm -f po/Makefile* po/*.gmo po/*.pot po/*.header po/stamp-*
|
||||
# %patch -p1
|
||||
# %%patch -p1
|
||||
%patch1 -p1
|
||||
%patch2 -p1
|
||||
%patch3 -p1
|
||||
@ -81,6 +115,32 @@ sed -i -e's/EXTRA_DIST= config.rpath /EXTRA_DIST=/' Makefile.am
|
||||
%patch11 -p1
|
||||
%patch12 -p1
|
||||
%patch13 -p1
|
||||
%patch14 -p1
|
||||
%patch15 -p1
|
||||
%patch16 -p1
|
||||
%patch17 -p1
|
||||
%patch18 -p1
|
||||
%patch19 -p1
|
||||
%patch20 -p1
|
||||
%patch21 -p1
|
||||
%patch22 -p1
|
||||
%patch23 -p1
|
||||
%patch24 -p1
|
||||
%patch25 -p1
|
||||
%patch26 -p1
|
||||
%patch27 -p1
|
||||
%patch28 -p1
|
||||
%patch29 -p1
|
||||
%patch30 -p1
|
||||
%patch31 -p1
|
||||
%patch32 -p1
|
||||
%patch33 -p1
|
||||
%patch34 -p1
|
||||
%patch35 -p1
|
||||
%patch36 -p1
|
||||
%patch37 -p1
|
||||
%patch38 -p1
|
||||
%patch39 -p1
|
||||
%if %suse_version < 1020
|
||||
%patch99 -p1
|
||||
%endif
|
||||
@ -91,12 +151,14 @@ export AUTOMAKE_JOBS=%{?jobs:%jobs}
|
||||
gettextize -f
|
||||
%endif
|
||||
autoreconf -fi
|
||||
%if %suse_version < 1030
|
||||
%define moreopts --disable-xmlto
|
||||
%else
|
||||
%define moreopts
|
||||
opts=""
|
||||
%if %suse_version < 1140
|
||||
opts="$opts --with-asound-state-dir=/etc"
|
||||
%endif
|
||||
%configure --with-curses=ncursesw %moreopts
|
||||
%if %suse_version < 1030
|
||||
opts="$opts --disable-xmlto"
|
||||
%endif
|
||||
%configure --with-curses=ncursesw $opts
|
||||
make %{?jobs:-j %jobs}
|
||||
|
||||
%install
|
||||
@ -117,5 +179,10 @@ make %{?jobs:-j %jobs}
|
||||
%{_sbindir}/*
|
||||
%{_datadir}/sounds/alsa
|
||||
%{_datadir}/alsa
|
||||
/lib/udev/rules.d/*.rules
|
||||
%if %use_systemd
|
||||
/lib/systemd/system/*.service
|
||||
/lib/systemd/system/*/*.service
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
|
Loading…
Reference in New Issue
Block a user