Fix a segfault if JACK libs are missing (#8026)
Fix a segmentation fault that occurs if the JACK libraries are not installed. In that case `jack_client_open` which is called through `lib_weakjack` will return a `nullptr` for the client. Subsequent calls to `jack_client_open` do not check for `nullptr` in the library so we have to do this ourselves to prevent the segmentation fault. The check is added to `AudioJack::setupWidget::getAudioPortNames`. Extract the printing of the JACK status into the function `printJackStatus` as its functionality is needed several times. Print a warning and the status in `AudioJack::setupWidget::setupWidget`. ## Code review changes Use `std::printf` and `std::fprintf`and print to `stderr` whenever fitting. --------- Co-authored-by: Andrew Wiltshire <62200778+AW1534@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
dabfe6f95b
commit
88ed51edb9
@@ -40,6 +40,8 @@
|
||||
#include "MainWindow.h"
|
||||
#include "MidiJack.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -57,6 +59,21 @@ QString getInputKeyByChannel(size_t channel)
|
||||
return "input" + QString::number(channel + 1);
|
||||
}
|
||||
|
||||
void printJackStatus(jack_status_t status)
|
||||
{
|
||||
std::fprintf(stderr, "Status: 0x%2.0x\n", static_cast<unsigned int>(status));
|
||||
|
||||
if (status & JackFailure)
|
||||
{
|
||||
std::fprintf(stderr, "Overall operation failed. JACK dependencies might need to be installed.\n");
|
||||
}
|
||||
|
||||
if (status & JackServerFailed)
|
||||
{
|
||||
std::fprintf(stderr, "Could not connect to JACK server.\n");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace lmms
|
||||
@@ -172,15 +189,16 @@ bool AudioJack::initJackClient()
|
||||
m_client = jack_client_open(clientName.toLatin1().constData(), JackNullOption, &status, serverName);
|
||||
if (m_client == nullptr)
|
||||
{
|
||||
printf("jack_client_open() failed, status 0x%2.0x\n", status);
|
||||
if (status & JackServerFailed) { printf("Could not connect to JACK server.\n"); }
|
||||
std::fprintf(stderr, "jack_client_open() failed, ");
|
||||
printJackStatus(status);
|
||||
|
||||
return false;
|
||||
}
|
||||
if (status & JackNameNotUnique)
|
||||
{
|
||||
printf( "there's already a client with name '%s', so unique "
|
||||
"name '%s' was assigned\n",
|
||||
clientName.toLatin1().constData(), jack_get_client_name(m_client));
|
||||
std::printf("there's already a client with name '%s', so unique "
|
||||
"name '%s' was assigned\n",
|
||||
clientName.toLatin1().constData(), jack_get_client_name(m_client));
|
||||
}
|
||||
|
||||
resizeInputBuffer(jack_get_buffer_size(m_client));
|
||||
@@ -212,7 +230,7 @@ bool AudioJack::initJackClient()
|
||||
|
||||
if (m_outputPorts.back() == nullptr)
|
||||
{
|
||||
printf("no more JACK-ports available!\n");
|
||||
std::fprintf(stderr, "no more JACK-ports available!\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -230,14 +248,14 @@ void AudioJack::resizeInputBuffer(jack_nframes_t nframes)
|
||||
|
||||
void AudioJack::attemptToConnect(size_t index, const char *lmms_port_type, const char *source_port, const char *destination_port)
|
||||
{
|
||||
printf("Attempting to reconnect %s port %u: %s -> %s", lmms_port_type, static_cast<unsigned int>(index), source_port, destination_port);
|
||||
std::printf("Attempting to reconnect %s port %u: %s -> %s", lmms_port_type, static_cast<unsigned int>(index), source_port, destination_port);
|
||||
if (!jack_connect(m_client, source_port, destination_port))
|
||||
{
|
||||
printf(" - Success!\n");
|
||||
std::printf(" - Success!\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(" - Failure\n");
|
||||
std::printf(" - Failure\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,7 +265,7 @@ void AudioJack::attemptToReconnectOutput(size_t outputIndex, const QString& targ
|
||||
|
||||
if (targetPort == disconnectedRepresentation)
|
||||
{
|
||||
printf("Output port %u is not connected.\n", static_cast<unsigned int>(outputIndex));
|
||||
std::fprintf(stderr, "Output port %u is not connected.\n", static_cast<unsigned int>(outputIndex));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -263,7 +281,7 @@ void AudioJack::attemptToReconnectInput(size_t inputIndex, const QString& source
|
||||
|
||||
if (sourcePort == disconnectedRepresentation)
|
||||
{
|
||||
printf("Input port %u is not connected.\n", static_cast<unsigned int>(inputIndex));
|
||||
std::fprintf(stderr, "Input port %u is not connected.\n", static_cast<unsigned int>(inputIndex));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -284,7 +302,7 @@ void AudioJack::startProcessing()
|
||||
|
||||
if (jack_activate(m_client))
|
||||
{
|
||||
printf("cannot activate client\n");
|
||||
std::fprintf(stderr, "cannot activate client\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -483,6 +501,11 @@ AudioJack::setupWidget::setupWidget(QWidget* parent)
|
||||
const char* serverName = nullptr;
|
||||
jack_status_t status;
|
||||
m_client = jack_client_open("LMMS-Setup Dialog", JackNullOption, &status, serverName);
|
||||
if (!m_client)
|
||||
{
|
||||
std::fprintf(stderr, "jack_client_open() failed, ");
|
||||
printJackStatus(status);
|
||||
}
|
||||
|
||||
QFormLayout * form = new QFormLayout(this);
|
||||
|
||||
@@ -562,6 +585,14 @@ std::vector<std::string> AudioJack::setupWidget::getAudioPortNames(JackPortFlags
|
||||
{
|
||||
std::vector<std::string> audioPorts;
|
||||
|
||||
// We are using weak_libjack. If JACK is not installed this will result in the client being nullptr.
|
||||
// Because jack_get_ports in weak_libjack does not check for nullptr we have to do this here and fail gracefully,
|
||||
// i.e. with an empty list of audio ports.
|
||||
if (!m_client)
|
||||
{
|
||||
return audioPorts;
|
||||
}
|
||||
|
||||
const char **inputAudioPorts = jack_get_ports(m_client, nullptr, JACK_DEFAULT_AUDIO_TYPE, portFlags);
|
||||
if (inputAudioPorts)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user