So, here are some suggested changes to juce_linux_JackAudio.cpp
[list]
[]Fix a SIGSEGV when jack server goes away[/]
[]Keep in sync with externally [dis]connected channels (ports), ie changed in qjackqtl or similar[/]
[]Only send active in/out channels to audioDeviceIOCallback[/][/list]
[code]diff --git a/modules/juce_audio_devices/native/juce_linux_JackAudio.cpp b/modules/juce_audio_devices/native/juce_linux_JackAudio.cpp
index 65d122b…4d3d5a5 100644
— a/modules/juce_audio_devices/native/juce_linux_JackAudio.cpp
+++ b/modules/juce_audio_devices/native/juce_linux_JackAudio.cpp
@@ -66,7 +66,7 @@ JUCE_DECL_JACK_FUNCTION (int, jack_set_process_callback, (jack_client_t* client,
JUCE_DECL_JACK_FUNCTION (const char**, jack_get_ports, (jack_client_t* client, const char* port_name_pattern, const char* type_name_pattern, unsigned long flags), (client, port_name_pattern, type_name_pattern, flags));
JUCE_DECL_JACK_FUNCTION (int, jack_connect, (jack_client_t* client, const char* source_port, const char* destination_port), (client, source_port, destination_port));
JUCE_DECL_JACK_FUNCTION (const char*, jack_port_name, (const jack_port_t* port), (port));
-JUCE_DECL_JACK_FUNCTION (int, jack_set_port_connect_callback, (jack_client_t* client, JackPortConnectCallback connect_callback, void* arg), (client, connect_callback, arg));
+JUCE_DECL_JACK_FUNCTION (void*, jack_set_port_connect_callback, (jack_client_t* client, JackPortConnectCallback port_connect_callback, void* arg), (client, port_connect_callback, arg));
JUCE_DECL_JACK_FUNCTION (jack_port_t* , jack_port_by_id, (jack_client_t* client, jack_port_id_t port_id), (client, port_id));
JUCE_DECL_JACK_FUNCTION (int, jack_port_connected, (const jack_port_t* port), (port));
JUCE_DECL_JACK_FUNCTION (int, jack_port_connected_to, (const jack_port_t* port, const char* port_name), (port, port_name));
@@ -106,6 +106,9 @@ namespace
static const char** getJackPorts (jack_client_t* const client, const bool forInput)
{
- if (client == nullptr)
-
return nullptr;
- return juce::jack_get_ports (client, nullptr, nullptr,
forInput ? JackPortIsOutput : JackPortIsInput);
// (NB: This looks like it’s the wrong way round, but it is correct!)
@@ -161,8 +164,8 @@ public:
JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0));
}
@@ -216,6 +219,7 @@ public:
close();
juce::jack_set_process_callback (client, processCallback, this);
-
juce::jack_set_port_connect_callback (client, portConnectCallback, this);
juce::jack_on_shutdown (client, shutdownCallback, this);
juce::jack_activate (client);
isOpen_ = true;
@@ -264,6 +268,8 @@ public:
}
}
-
updateActivePorts();
-
return lastError;
}
@@ -275,6 +281,7 @@ public:
{
juce::jack_deactivate (client);
juce::jack_set_process_callback (client, processCallback, nullptr);
-
juce::jack_set_port_connect_callback (client, portConnectCallback, nullptr);
juce::jack_on_shutdown (client, shutdownCallback, nullptr);
}
@@ -312,27 +319,8 @@ public:
int getCurrentBitDepth() { return 32; }
String getLastError() { return lastError; }
- BigInteger getActiveOutputChannels() const
- {
-
BigInteger outputBits;
-
-
for (int i = 0; i < outputPorts.size(); i++)
-
if (juce::jack_port_connected ((jack_port_t*) outputPorts [i]))
-
outputBits.setBit (i);
-
-
return outputBits;
- }
-
- BigInteger getActiveInputChannels() const
- {
-
BigInteger inputBits;
-
-
for (int i = 0; i < inputPorts.size(); i++)
-
if (juce::jack_port_connected ((jack_port_t*) inputPorts [i]))
-
inputBits.setBit (i);
-
-
return inputBits;
- }
-
BigInteger getActiveOutputChannels() const { return activeOutputChannels; }
-
BigInteger getActiveInputChannels() const { return activeInputChannels; }
int getOutputLatencyInSamples()
{
@@ -359,33 +347,37 @@ public:
private:
void process (const int numSamples)
{
-
if (activeInputChannels[i])
-
if (jack_default_audio_sample_t* in
= (jack_default_audio_sample_t*) juce::jack_port_get_buffer ((jack_port_t*) inputPorts.getUnchecked(i), numSamples))
-
if (activeOutputChannels[i])
-
if (jack_default_audio_sample_t* out
= (jack_default_audio_sample_t*) juce::jack_port_get_buffer ((jack_port_t*) outputPorts.getUnchecked(i), numSamples))
-
callback->audioDeviceIOCallback (const_cast <const float**> (inChans.getData()), numActiveInChans,
-
outChans, numActiveOutChans, numSamples);
-
/* check we have any active channels, else it will trigger assertion in juce_AudioSampleBuffer.cpp:72 */
-
if ((numActiveInputChannels + numActiveOutputChannels) > 0)
-
callback->audioDeviceIOCallback (const_cast <const float**> (inputChannelsBuffer.getData()), numActiveInputChannels,
-
outputChannelsBuffer, numActiveOutputChannels, numSamples);
}
else
{
-
for (int i = 0; i < numActiveOutputChannels; ++i)
-
zeromem (outputChannelsBuffer[i], sizeof (float) * numSamples);
}
}
@@ -397,6 +389,30 @@ private:
return 0;
}
-
void updateActivePorts()
-
{
-
/* This function is called on open(), and from jack as callback on external
-
* jack port changes. Jules, is there any risk that this can happen in a
-
* separate thread from the audio thread, meaning we need a critical section?
-
* the below two activeOut/InputChannels are used in process() */
-
activeOutputChannels.clear();
-
activeInputChannels.clear();
-
-
for (int i = 0; i < outputPorts.size(); i++)
-
if (juce::jack_port_connected ((jack_port_t*) outputPorts [i]))
-
activeOutputChannels.setBit (i);
-
for (int i = 0; i < inputPorts.size(); i++)
-
if (juce::jack_port_connected ((jack_port_t*) inputPorts [i]))
-
activeInputChannels.setBit (i);
-
}
-
-
static void portConnectCallback (jack_port_id_t /* a /, jack_port_id_t / b /, int / isConnect /, void callbackArgument)
-
{
-
if (callbackArgument != nullptr)
-
((JackAudioIODevice*) callbackArgument)->updateActivePorts();
-
}
-
static void threadInitCallback (void* /* callbackArgument /)
{
jack_Log (“JackAudioIODevice::initialise”);
@@ -424,10 +440,13 @@ private:
AudioIODeviceCallback callback;
CriticalSection callbackLock;
- HeapBlock <float*> inChans, outChans;
- HeapBlock <float*> inputChannelsBuffer, outputChannelsBuffer;
int totalNumberOfInputChannels;
int totalNumberOfOutputChannels;
Array<void*> inputPorts, outputPorts;
-
- BigInteger activeInputChannels;
- BigInteger activeOutputChannels;
};
[/code]