- Upgraded the source package - Rebuilt the audacity patch based on the upgraded source package - Deleted obsolete portaudio-pipewire-jacknames.patch - Fixed a minor bug in the audacity patch that mixed up the alsa and oss build options (didn't matter, because we enable both of them) - Update sources file and replace MD5 with SHA512 hashepel9
parent
71dc5b5710
commit
5c1adf2a43
@ -1,194 +0,0 @@
|
||||
From eec7bb739771381ab698a6a611d933bdd72cbd8f Mon Sep 17 00:00:00 2001
|
||||
From: Be <be@mixxx.org>
|
||||
Date: Fri, 19 Mar 2021 12:51:31 -0500
|
||||
Subject: [PATCH] JACK PipeWire fixes (escape regex chars) (#504)
|
||||
|
||||
This patch fixes a problem caused by special regex characters
|
||||
appearing in the device names when using the Jack interface to PipeWire.
|
||||
|
||||
It is uncommon for JACK ports to have any characters that need to
|
||||
be escaped in a regex. jackd simply calls the audio interface
|
||||
"system". However PipeWire uses the device name from ALSA for the
|
||||
JACK port names. If this contains any special regex characters,
|
||||
BuildDeviceList would find the device but determine it has 0
|
||||
input channels and 0 output channels. In my case, I have an RME
|
||||
Babyface Pro which puts its serial number in parentheses:
|
||||
|
||||
$ aplay -l
|
||||
card 0: Pro70785713 [Babyface Pro (70785713)], device 0: USB Audio [USB Audio]
|
||||
Subdevices: 1/1
|
||||
Subdevice #0: subdevice #0
|
||||
---
|
||||
src/hostapi/jack/pa_jack.c | 83 +++++++++++++++++++++++++++++++++-----
|
||||
1 file changed, 73 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/src/hostapi/jack/pa_jack.c b/src/hostapi/jack/pa_jack.c
|
||||
index 0dad24fb..88926f47 100644
|
||||
--- a/src/hostapi/jack/pa_jack.c
|
||||
+++ b/src/hostapi/jack/pa_jack.c
|
||||
@@ -76,6 +76,7 @@
|
||||
static pthread_t mainThread_;
|
||||
static char *jackErr_ = NULL;
|
||||
static const char* clientName_ = "PortAudio";
|
||||
+static const char* port_regex_suffix = ":.*";
|
||||
|
||||
#define STRINGIZE_HELPER(expr) #expr
|
||||
#define STRINGIZE(expr) STRINGIZE_HELPER(expr)
|
||||
@@ -451,6 +452,38 @@ BlockingWaitEmpty( PaStream *s )
|
||||
|
||||
/* ---- jack driver ---- */
|
||||
|
||||
+/* copy null terminated string source to destination, escaping regex characters with '\\' in the process */
|
||||
+static void copy_string_and_escape_regex_chars( char *destination, const char *source, size_t destbuffersize )
|
||||
+{
|
||||
+ assert( destination != source );
|
||||
+ assert( destbuffersize > 0 );
|
||||
+
|
||||
+ char *dest = destination;
|
||||
+ /* dest_stop is the last location that we can null-terminate the string */
|
||||
+ char *dest_stop = destination + (destbuffersize - 1);
|
||||
+
|
||||
+ const char *src = source;
|
||||
+
|
||||
+ while ( *src != '\0' && dest != dest_stop )
|
||||
+ {
|
||||
+ const char c = *src;
|
||||
+ if ( strchr( "\\()[]{}*+?|$^.", c ) != NULL )
|
||||
+ {
|
||||
+ if( (dest + 1) == dest_stop )
|
||||
+ break; /* only proceed if we can write both c and the escape */
|
||||
+
|
||||
+ *dest = '\\';
|
||||
+ dest++;
|
||||
+ }
|
||||
+ *dest = c;
|
||||
+ dest++;
|
||||
+
|
||||
+ src++;
|
||||
+ }
|
||||
+
|
||||
+ *dest = '\0';
|
||||
+}
|
||||
+
|
||||
/* BuildDeviceList():
|
||||
*
|
||||
* The process of determining a list of PortAudio "devices" from
|
||||
@@ -472,7 +505,12 @@ static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi )
|
||||
|
||||
const char **jack_ports = NULL;
|
||||
char **client_names = NULL;
|
||||
- char *regex_pattern = NULL;
|
||||
+ char *port_regex_string = NULL;
|
||||
+ char *device_name_regex_escaped = NULL;
|
||||
+ // In the worst case scenario, every character would be escaped, doubling the string size.
|
||||
+ // Add 1 for null terminator.
|
||||
+ size_t device_name_regex_escaped_size = jack_client_name_size() * 2 + 1;
|
||||
+ size_t port_regex_size = device_name_regex_escaped_size + strlen(port_regex_suffix);
|
||||
int port_index, client_index, i;
|
||||
double globalSampleRate;
|
||||
regex_t port_regex;
|
||||
@@ -490,7 +528,9 @@ static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi )
|
||||
* associated with the previous list */
|
||||
PaUtil_FreeAllAllocations( jackApi->deviceInfoMemory );
|
||||
|
||||
- regex_pattern = PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory, jack_client_name_size() + 3 );
|
||||
+ port_regex_string = PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory, port_regex_size );
|
||||
+ device_name_regex_escaped = PaUtil_GroupAllocateMemory(
|
||||
+ jackApi->deviceInfoMemory, device_name_regex_escaped_size );
|
||||
tmp_client_name = PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory, jack_client_name_size() );
|
||||
|
||||
/* We can only retrieve the list of clients indirectly, by first
|
||||
@@ -512,6 +552,7 @@ static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi )
|
||||
int client_seen = FALSE;
|
||||
regmatch_t match_info;
|
||||
const char *port = jack_ports[port_index];
|
||||
+ PA_DEBUG(( "JACK port found: %s\n", port ));
|
||||
|
||||
/* extract the client name from the port name, using a regex
|
||||
* that parses the clientname:portname syntax */
|
||||
@@ -584,11 +625,14 @@ static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi )
|
||||
|
||||
/* To determine how many input and output channels are available,
|
||||
* we re-query jackd with more specific parameters. */
|
||||
-
|
||||
- sprintf( regex_pattern, "%s:.*", client_names[client_index] );
|
||||
+ copy_string_and_escape_regex_chars( device_name_regex_escaped,
|
||||
+ client_names[client_index],
|
||||
+ device_name_regex_escaped_size );
|
||||
+ strncpy( port_regex_string, device_name_regex_escaped, port_regex_size );
|
||||
+ strncat( port_regex_string, port_regex_suffix, port_regex_size );
|
||||
|
||||
/* ... what are your output ports (that we could input from)? */
|
||||
- clientPorts = jack_get_ports( jackApi->jack_client, regex_pattern,
|
||||
+ clientPorts = jack_get_ports( jackApi->jack_client, port_regex_string,
|
||||
JACK_PORT_TYPE_FILTER, JackPortIsOutput);
|
||||
curDevInfo->maxInputChannels = 0;
|
||||
curDevInfo->defaultLowInputLatency = 0.;
|
||||
@@ -609,7 +653,7 @@ static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi )
|
||||
}
|
||||
|
||||
/* ... what are your input ports (that we could output to)? */
|
||||
- clientPorts = jack_get_ports( jackApi->jack_client, regex_pattern,
|
||||
+ clientPorts = jack_get_ports( jackApi->jack_client, port_regex_string,
|
||||
JACK_PORT_TYPE_FILTER, JackPortIsInput);
|
||||
curDevInfo->maxOutputChannels = 0;
|
||||
curDevInfo->defaultLowOutputLatency = 0.;
|
||||
@@ -629,6 +673,11 @@ static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi )
|
||||
free(clientPorts);
|
||||
}
|
||||
|
||||
+ PA_DEBUG(( "Adding JACK device %s with %d input channels and %d output channels\n",
|
||||
+ client_names[client_index],
|
||||
+ curDevInfo->maxInputChannels,
|
||||
+ curDevInfo->maxOutputChannels ));
|
||||
+
|
||||
/* Add this client to the list of devices */
|
||||
commonApi->deviceInfos[client_index] = curDevInfo;
|
||||
++commonApi->info.deviceCount;
|
||||
@@ -1080,8 +1129,13 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
|
||||
PaJackHostApiRepresentation *jackHostApi = (PaJackHostApiRepresentation*)hostApi;
|
||||
PaJackStream *stream = NULL;
|
||||
char *port_string = PaUtil_GroupAllocateMemory( jackHostApi->deviceInfoMemory, jack_port_name_size() );
|
||||
- unsigned long regexSz = jack_client_name_size() + 3;
|
||||
- char *regex_pattern = PaUtil_GroupAllocateMemory( jackHostApi->deviceInfoMemory, regexSz );
|
||||
+ // In the worst case every character would be escaped which would double the string length.
|
||||
+ // Add 1 for null terminator
|
||||
+ size_t regex_escaped_client_name_length = jack_client_name_size() * 2 + 1;
|
||||
+ char *regex_escaped_client_name = PaUtil_GroupAllocateMemory(
|
||||
+ jackHostApi->deviceInfoMemory, regex_escaped_client_name_length );
|
||||
+ unsigned long regex_size = jack_client_name_size() * 2 + 1 + strlen(port_regex_suffix);
|
||||
+ char *regex_pattern = PaUtil_GroupAllocateMemory( jackHostApi->deviceInfoMemory, regex_size );
|
||||
const char **jack_ports = NULL;
|
||||
/* int jack_max_buffer_size = jack_get_buffer_size( jackHostApi->jack_client ); */
|
||||
int i;
|
||||
@@ -1239,7 +1293,11 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
|
||||
int err = 0;
|
||||
|
||||
/* Get output ports of our capture device */
|
||||
- snprintf( regex_pattern, regexSz, "%s:.*", hostApi->deviceInfos[ inputParameters->device ]->name );
|
||||
+ copy_string_and_escape_regex_chars( regex_escaped_client_name,
|
||||
+ hostApi->deviceInfos[ inputParameters->device ]->name,
|
||||
+ regex_escaped_client_name_length );
|
||||
+ strncpy( regex_pattern, regex_escaped_client_name, regex_size );
|
||||
+ strncat( regex_pattern, port_regex_suffix, regex_size );
|
||||
UNLESS( jack_ports = jack_get_ports( jackHostApi->jack_client, regex_pattern,
|
||||
JACK_PORT_TYPE_FILTER, JackPortIsOutput ), paUnanticipatedHostError );
|
||||
for( i = 0; i < inputChannelCount && jack_ports[i]; i++ )
|
||||
@@ -1263,7 +1321,11 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
|
||||
int err = 0;
|
||||
|
||||
/* Get input ports of our playback device */
|
||||
- snprintf( regex_pattern, regexSz, "%s:.*", hostApi->deviceInfos[ outputParameters->device ]->name );
|
||||
+ copy_string_and_escape_regex_chars( regex_escaped_client_name,
|
||||
+ hostApi->deviceInfos[ outputParameters->device ]->name,
|
||||
+ regex_escaped_client_name_length );
|
||||
+ strncpy( regex_pattern, regex_escaped_client_name, regex_size );
|
||||
+ strncat( regex_pattern, port_regex_suffix, regex_size );
|
||||
UNLESS( jack_ports = jack_get_ports( jackHostApi->jack_client, regex_pattern,
|
||||
JACK_PORT_TYPE_FILTER, JackPortIsInput ), paUnanticipatedHostError );
|
||||
for( i = 0; i < outputChannelCount && jack_ports[i]; i++ )
|
||||
@@ -1769,3 +1831,4 @@ PaError PaJack_GetClientName(const char** clientName)
|
||||
error:
|
||||
return result;
|
||||
}
|
||||
+
|
Loading…
Reference in new issue