diff --git a/src/framework/audio/internal/platform/jack/jackaudiodriver.cpp b/src/framework/audio/internal/platform/jack/jackaudiodriver.cpp index 07d985e885872..0280903e6c51b 100644 --- a/src/framework/audio/internal/platform/jack/jackaudiodriver.cpp +++ b/src/framework/audio/internal/platform/jack/jackaudiodriver.cpp @@ -37,31 +37,16 @@ static constexpr char DEFAULT_DEVICE_ID[] = "default"; using namespace mu::audio; -//namespace { -struct JackData +int mu::audio::jack_process_callback(jack_nframes_t nframes, void* args) { - float* buffer = nullptr; - jack_client_t* jackDeviceHandle = nullptr; - unsigned long samples = 0; - int channels = 0; - std::vector outputPorts; - IAudioDriver::Callback callback; - void* userdata = nullptr; -}; - -static JackData* s_jackData{ nullptr }; -IAudioDriver::Spec s_format; - -int mu::audio::jack_process_callback(jack_nframes_t nframes, void*) -{ - JackData* data = s_jackData; + JackDriverState* state = static_cast(args); - jack_default_audio_sample_t* l = (float*)jack_port_get_buffer(data->outputPorts[0], nframes); - jack_default_audio_sample_t* r = (float*)jack_port_get_buffer(data->outputPorts[1], nframes); + jack_default_audio_sample_t* l = (float*)jack_port_get_buffer(state->outputPorts[0], nframes); + jack_default_audio_sample_t* r = (float*)jack_port_get_buffer(state->outputPorts[1], nframes); - uint8_t* stream = (uint8_t*)data->buffer; - data->callback(data->userdata, stream, nframes * data->channels * sizeof(float)); - float* sp = data->buffer; + uint8_t* stream = (uint8_t*)state->buffer; + state->callback(state->userdata, stream, nframes * state->channels * sizeof(float)); + float* sp = state->buffer; for (size_t i = 0; i < nframes; i++) { *l++ = *sp++; *r++ = *sp++; @@ -73,28 +58,15 @@ void mu::audio::jack_cleanup_callback(void*) { } -void jackCleanup() -{ - if (!s_jackData) { - return; - } - - if (nullptr != s_jackData->buffer) { - delete[] s_jackData->buffer; - } - - delete s_jackData; - s_jackData = nullptr; -} - JackAudioDriver::JackAudioDriver() { + m_jackDriverState = std::make_shared(); m_deviceId = DEFAULT_DEVICE_ID; } JackAudioDriver::~JackAudioDriver() { - jackCleanup(); + delete[] m_jackDriverState->buffer; } void JackAudioDriver::init() @@ -123,11 +95,14 @@ int jack_srate_callback(jack_nframes_t nframes, void* args) bool JackAudioDriver::open(const Spec& spec, Spec* activeSpec) { - s_jackData = new JackData(); + if (isOpened()) { + LOGW() << "Jack is already opened"; + return false; + } // s_jackData->samples = spec.samples; // client doesn't set sample-rate - s_jackData->channels = spec.channels; - s_jackData->callback = spec.callback; - s_jackData->userdata = spec.userdata; + m_jackDriverState->channels = spec.channels; + m_jackDriverState->callback = spec.callback; + m_jackDriverState->userdata = spec.userdata; // FIX: "default" is not a good name for jack-clients // const char *clientName = // outputDevice().c_str() == "default" ? "MuseScore" : @@ -144,15 +119,15 @@ bool JackAudioDriver::open(const Spec& spec, Spec* activeSpec) jack_set_sample_rate_callback(handle, jack_srate_callback, (void*)&spec); - s_jackData->jackDeviceHandle = handle; + m_jackDriverState->jackDeviceHandle = handle; jack_port_t* output_port_left = jack_port_register(handle, "audio_out_left", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); - s_jackData->outputPorts.push_back(output_port_left); + m_jackDriverState->outputPorts.push_back(output_port_left); jack_port_t* output_port_right = jack_port_register(handle, "audio_out_right", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); - s_jackData->outputPorts.push_back(output_port_right); + m_jackDriverState->outputPorts.push_back(output_port_right); - s_jackData->samples = jack_get_buffer_size(handle); - LOGI() << "buffer size (in samples): " << s_jackData->samples; + m_jackDriverState->samples = jack_get_buffer_size(handle); + LOGI() << "buffer size (in samples): " << m_jackDriverState->samples; unsigned int jackSamplerate = jack_get_sample_rate(handle); LOGI() << "sampleRate used by jack: " << jackSamplerate; @@ -163,17 +138,17 @@ bool JackAudioDriver::open(const Spec& spec, Spec* activeSpec) //return false; } - s_jackData->buffer = new float[s_jackData->samples * s_jackData->channels]; + m_jackDriverState->buffer = new float[m_jackDriverState->samples * m_jackDriverState->channels]; if (activeSpec) { *activeSpec = spec; activeSpec->format = Format::AudioF32; activeSpec->sampleRate = jackSamplerate; - s_format = *activeSpec; + m_jackDriverState->format = *activeSpec; } - jack_on_shutdown(handle, jack_cleanup_callback, 0); - jack_set_process_callback(handle, jack_process_callback, (void*)&s_jackData); + jack_on_shutdown(handle, jack_cleanup_callback, (void*)m_jackDriverState.get()); + jack_set_process_callback(handle, jack_process_callback, (void*)m_jackDriverState.get()); if (jack_activate(handle)) { LOGE() << "cannot activate client"; @@ -185,12 +160,14 @@ bool JackAudioDriver::open(const Spec& spec, Spec* activeSpec) void JackAudioDriver::close() { - jackCleanup(); + jack_client_t* jackDeviceHandle = static_cast(m_jackDriverState->jackDeviceHandle); + jack_client_close(jackDeviceHandle); + delete[] m_jackDriverState->buffer; } bool JackAudioDriver::isOpened() const { - return s_jackData != nullptr; + return m_jackDriverState->jackDeviceHandle != nullptr; } AudioDeviceID JackAudioDriver::outputDevice() const @@ -210,7 +187,7 @@ bool JackAudioDriver::selectOutputDevice(const AudioDeviceID& deviceId) bool ok = true; if (reopen) { - ok = open(s_format, &s_format); + ok = open(m_jackDriverState->format, &m_jackDriverState->format); } if (ok) { @@ -245,22 +222,22 @@ mu::async::Notification JackAudioDriver::availableOutputDevicesChanged() const unsigned int JackAudioDriver::outputDeviceBufferSize() const { - return s_format.samples; + return m_jackDriverState->format.samples; } bool JackAudioDriver::setOutputDeviceBufferSize(unsigned int bufferSize) { - if (s_format.samples == bufferSize) { + if (m_jackDriverState->format.samples == bufferSize) { return true; } bool reopen = isOpened(); close(); - s_format.samples = bufferSize; + m_jackDriverState->format.samples = bufferSize; bool ok = true; if (reopen) { - ok = open(s_format, &s_format); + ok = open(m_jackDriverState->format, &m_jackDriverState->format); } if (ok) { diff --git a/src/framework/audio/internal/platform/jack/jackaudiodriver.h b/src/framework/audio/internal/platform/jack/jackaudiodriver.h index 24887d59666ac..2245f6fd4fb56 100644 --- a/src/framework/audio/internal/platform/jack/jackaudiodriver.h +++ b/src/framework/audio/internal/platform/jack/jackaudiodriver.h @@ -33,6 +33,17 @@ namespace mu::audio { int jack_process_callback(jack_nframes_t nframes, void* jackParam); void jack_cleanup_callback(void* args); +struct JackDriverState { + float* buffer = nullptr; + void* jackDeviceHandle = nullptr; + unsigned long samples = 0; + int channels = 0; + std::vector outputPorts; + IAudioDriver::Callback callback; + void* userdata = nullptr; + IAudioDriver::Spec format; +}; + class JackAudioDriver : public IAudioDriver, public async::Asyncable { public: @@ -74,6 +85,8 @@ class JackAudioDriver : public IAudioDriver, public async::Asyncable async::Notification m_bufferSizeChanged; async::Notification m_sampleRateChanged; + + std::shared_ptr m_jackDriverState; }; } diff --git a/src/framework/audio/internal/platform/osx/osxaudiodriver.h b/src/framework/audio/internal/platform/osx/osxaudiodriver.h index d007a31480c29..5b6bf9f22c3e0 100644 --- a/src/framework/audio/internal/platform/osx/osxaudiodriver.h +++ b/src/framework/audio/internal/platform/osx/osxaudiodriver.h @@ -82,7 +82,7 @@ class OSXAudioDriver : public IAudioDriver struct Data; - std::shared_ptr m_data = nullptr; + std::shared_ptr m_data; std::map m_outputDevices = {}, m_inputDevices = {}; mutable std::mutex m_devicesMutex; async::Notification m_outputDeviceChanged; diff --git a/src/framework/audio/internal/platform/osx/osxaudiodriver.mm b/src/framework/audio/internal/platform/osx/osxaudiodriver.mm index e505ee0c3fcff..1c6e59e5e01b8 100644 --- a/src/framework/audio/internal/platform/osx/osxaudiodriver.mm +++ b/src/framework/audio/internal/platform/osx/osxaudiodriver.mm @@ -44,7 +44,6 @@ }; OSXAudioDriver::OSXAudioDriver() - : m_data(nullptr) { m_data = std::make_shared(); m_data->audioQueue = nullptr;