From 22128db0415d9191dd7ab912e030f8cf9a1dbacb Mon Sep 17 00:00:00 2001 From: Larry Valkama Date: Fri, 1 Sep 2023 21:46:05 +0200 Subject: [PATCH] linuxaudiodriver runs jack+alsa --- src/framework/audio/CMakeLists.txt | 23 +- src/framework/audio/audiomodule.cpp | 10 - .../platform/alsa/alsaaudiodriver.cpp | 33 ++- .../internal/platform/alsa/alsaaudiodriver.h | 3 + .../platform/jack/jackaudiodriver.cpp | 224 +++++------------- .../internal/platform/jack/jackaudiodriver.h | 66 ++---- .../platform/lin/linuxaudiodriver.cpp | 64 +++-- .../internal/platform/lin/linuxaudiodriver.h | 3 +- 8 files changed, 167 insertions(+), 259 deletions(-) diff --git a/src/framework/audio/CMakeLists.txt b/src/framework/audio/CMakeLists.txt index c634352e65e45..c014c11fdd886 100644 --- a/src/framework/audio/CMakeLists.txt +++ b/src/framework/audio/CMakeLists.txt @@ -37,23 +37,22 @@ if (OS_IS_WIN) ${CMAKE_CURRENT_LIST_DIR}/internal/platform/win/audiodeviceslistener.h ) elseif(OS_IS_LIN OR OS_IS_FBSD) + set(JACK_SRC "") if (MUE_ENABLE_AUDIO_JACK) - set(DRIVER_SRC + set(JACK_SRC ${CMAKE_CURRENT_LIST_DIR}/internal/platform/jack/jackaudiodriver.cpp ${CMAKE_CURRENT_LIST_DIR}/internal/platform/jack/jackaudiodriver.h - ${CMAKE_CURRENT_LIST_DIR}/internal/platform/jack/audiodeviceslistener.cpp - ${CMAKE_CURRENT_LIST_DIR}/internal/platform/jack/audiodeviceslistener.h - ) - else (MUE_ENABLE_AUDIO_JACK) - set(DRIVER_SRC - ${CMAKE_CURRENT_LIST_DIR}/internal/platform/alsa/alsaaudiodriver.cpp - ${CMAKE_CURRENT_LIST_DIR}/internal/platform/alsa/alsaaudiodriver.h - ${CMAKE_CURRENT_LIST_DIR}/internal/platform/lin/linuxaudiodriver.cpp - ${CMAKE_CURRENT_LIST_DIR}/internal/platform/lin/linuxaudiodriver.h - ${CMAKE_CURRENT_LIST_DIR}/internal/platform/lin/audiodeviceslistener.cpp - ${CMAKE_CURRENT_LIST_DIR}/internal/platform/lin/audiodeviceslistener.h ) endif() + set(DRIVER_SRC + ${CMAKE_CURRENT_LIST_DIR}/internal/platform/lin/linuxaudiodriver.cpp + ${CMAKE_CURRENT_LIST_DIR}/internal/platform/lin/linuxaudiodriver.h + ${CMAKE_CURRENT_LIST_DIR}/internal/platform/lin/audiodeviceslistener.cpp + ${CMAKE_CURRENT_LIST_DIR}/internal/platform/lin/audiodeviceslistener.h + ${CMAKE_CURRENT_LIST_DIR}/internal/platform/alsa/alsaaudiodriver.cpp + ${CMAKE_CURRENT_LIST_DIR}/internal/platform/alsa/alsaaudiodriver.h + ${JACK_SRC} + ) elseif(OS_IS_MAC) set(DRIVER_SRC ${CMAKE_CURRENT_LIST_DIR}/internal/platform/osx/osxaudiodriver.mm diff --git a/src/framework/audio/audiomodule.cpp b/src/framework/audio/audiomodule.cpp index 2dea36f43503e..86647118c94cb 100644 --- a/src/framework/audio/audiomodule.cpp +++ b/src/framework/audio/audiomodule.cpp @@ -60,10 +60,6 @@ using namespace mu::audio; using namespace mu::audio::synth; using namespace mu::audio::fx; -#ifdef JACK_AUDIO -#include "internal/platform/jack/jackaudiodriver.h" -#endif - #ifdef Q_OS_LINUX #include "internal/platform/lin/linuxaudiodriver.h" #endif @@ -112,10 +108,6 @@ void AudioModule::registerExports() m_soundFontRepository = std::make_shared(); m_registerAudioPluginsScenario = std::make_shared(); -#if defined(JACK_AUDIO) - m_audioDriver = std::shared_ptr(new JackAudioDriver()); -#else - #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) m_audioDriver = std::shared_ptr(new LinuxAudioDriver()); #endif @@ -134,8 +126,6 @@ void AudioModule::registerExports() m_audioDriver = std::shared_ptr(new WebAudioDriver()); #endif -#endif // JACK_AUDIO - ioc()->registerExport(moduleName(), m_configuration); ioc()->registerExport(moduleName(), std::make_shared()); ioc()->registerExport(moduleName(), m_audioDriver); diff --git a/src/framework/audio/internal/platform/alsa/alsaaudiodriver.cpp b/src/framework/audio/internal/platform/alsa/alsaaudiodriver.cpp index 9d66a497bd04d..d8f09bb8cd9bb 100644 --- a/src/framework/audio/internal/platform/alsa/alsaaudiodriver.cpp +++ b/src/framework/audio/internal/platform/alsa/alsaaudiodriver.cpp @@ -64,6 +64,17 @@ static void* alsaThread(void* aParam) return nullptr; } +AlsaDriverState::AlsaDriverState() +{ + m_deviceId = "alsa"; + m_deviceName = "default"; +} + +AlsaDriverState::~AlsaDriverState() +{ + alsaCleanup(); +} + void AlsaDriverState::alsaCleanup() { m_audioProcessingDone = true; @@ -76,23 +87,25 @@ void AlsaDriverState::alsaCleanup() snd_pcm_close(aDevice); m_alsaDeviceHandle = nullptr; } - - delete[] m_buffer; + if (m_buffer) { + delete[] m_buffer; + } + m_buffer = nullptr; } -AlsaDriverState::AlsaDriverState() +std::string AlsaDriverState::name() const { - m_deviceId = "alsa"; + return "alsa"; } -AlsaDriverState::~AlsaDriverState() +std::string AlsaDriverState::deviceName() const { - alsaCleanup(); + return m_deviceName; } -std::string AlsaDriverState::name() const +void AlsaDriverState::deviceName(const std::string newDeviceName) { - return "MUAUDIO(ALSA)"; + m_deviceName = newDeviceName; } bool AlsaDriverState::open(const IAudioDriver::Spec& spec, IAudioDriver::Spec* activeSpec) @@ -104,7 +117,7 @@ bool AlsaDriverState::open(const IAudioDriver::Spec& spec, IAudioDriver::Spec* a int rc; snd_pcm_t* handle; - rc = snd_pcm_open(&handle, name().c_str(), SND_PCM_STREAM_PLAYBACK, 0); + rc = snd_pcm_open(&handle, m_deviceName.c_str(), SND_PCM_STREAM_PLAYBACK, 0); if (rc < 0) { return false; } @@ -138,10 +151,12 @@ bool AlsaDriverState::open(const IAudioDriver::Spec& spec, IAudioDriver::Spec* a snd_pcm_hw_params_get_rate(params, &val, &dir); aSamplerate = val; + m_spec.sampleRate = aSamplerate; if (m_buffer != nullptr) { LOGW() << "open before close"; delete[] m_buffer; + m_buffer = nullptr; } m_buffer = new float[m_spec.samples * m_spec.channels]; diff --git a/src/framework/audio/internal/platform/alsa/alsaaudiodriver.h b/src/framework/audio/internal/platform/alsa/alsaaudiodriver.h index d69c6da21c1f6..6d34d5e300357 100644 --- a/src/framework/audio/internal/platform/alsa/alsaaudiodriver.h +++ b/src/framework/audio/internal/platform/alsa/alsaaudiodriver.h @@ -36,6 +36,8 @@ class AlsaDriverState : public AudioDriverState bool open(const IAudioDriver::Spec& spec, IAudioDriver::Spec* activeSpec) override; void close() override; bool isOpened() const override; + std::string deviceName() const; + void deviceName(const std::string newDeviceName); void* m_alsaDeviceHandle = nullptr; @@ -43,6 +45,7 @@ class AlsaDriverState : public AudioDriverState bool m_audioProcessingDone = false; pthread_t m_threadHandle = 0; private: + std::string m_deviceName = "default"; void alsaCleanup(); }; } diff --git a/src/framework/audio/internal/platform/jack/jackaudiodriver.cpp b/src/framework/audio/internal/platform/jack/jackaudiodriver.cpp index 2e5badc0cd288..bdfca31c04478 100644 --- a/src/framework/audio/internal/platform/jack/jackaudiodriver.cpp +++ b/src/framework/audio/internal/platform/jack/jackaudiodriver.cpp @@ -5,7 +5,7 @@ * MuseScore * Music Composition & Notation * - * Copyright (C) 2021 MuseScore BVBA and others + * Copyright (C) 2022 MuseScore BVBA and others * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -33,20 +33,18 @@ #include "log.h" #include "runtime.h" -static constexpr char DEFAULT_DEVICE_ID[] = "default"; - using namespace mu::audio; -int mu::audio::jack_process_callback(jack_nframes_t nframes, void* args) +static int jack_process_callback(jack_nframes_t nframes, void* args) { JackDriverState* state = static_cast(args); - 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); + jack_default_audio_sample_t* l = (float*)jack_port_get_buffer(state->m_outputPorts[0], nframes); + jack_default_audio_sample_t* r = (float*)jack_port_get_buffer(state->m_outputPorts[1], nframes); - uint8_t* stream = (uint8_t*)state->buffer; - state->callback(state->userdata, stream, nframes * state->channels * sizeof(float)); - float* sp = state->buffer; + uint8_t* stream = (uint8_t*)state->m_buffer; + state->m_spec.callback(state->m_spec.userdata, stream, nframes * state->m_spec.channels * sizeof(float)); + float* sp = state->m_buffer; for (size_t i = 0; i < nframes; i++) { *l++ = *sp++; *r++ = *sp++; @@ -58,54 +56,58 @@ void mu::audio::jack_cleanup_callback(void*) { } -JackAudioDriver::JackAudioDriver() +JackDriverState::JackDriverState() { - m_jackDriverState = std::make_shared(); - m_deviceId = DEFAULT_DEVICE_ID; + m_deviceId = "jack"; + m_deviceName = "MuseScore"; } -JackAudioDriver::~JackAudioDriver() +JackDriverState::~JackDriverState() { - if (m_jackDriverState->jackDeviceHandle != nullptr) { - jack_client_close(static_cast(m_jackDriverState->jackDeviceHandle)); + if (m_jackDeviceHandle != nullptr) { + jack_client_close(static_cast(m_jackDeviceHandle)); } - delete[] m_jackDriverState->buffer; + delete[] m_buffer; } -void JackAudioDriver::init() +std::string JackDriverState::name() const { - m_devicesListener.startWithCallback([this]() { - return availableOutputDevices(); - }); + LOGE() << "----- name: " << m_deviceName; + return m_deviceId; +} - m_devicesListener.devicesChanged().onNotify(this, [this]() { - m_availableOutputDevicesChanged.notify(); - }); +std::string JackDriverState::deviceName() const +{ + return m_deviceName; } -std::string JackAudioDriver::name() const +void JackDriverState::deviceName(const std::string newDeviceName) { - return "MUAUDIO(JACK)"; + m_deviceName = newDeviceName; } -int jack_srate_callback(jack_nframes_t nframes, void* args) +int jack_srate_callback(jack_nframes_t newSampleRate, void* args) { IAudioDriver::Spec* spec = (IAudioDriver::Spec*)args; - LOGI() << "Jack reported sampleRate change. Pray to god, musescores samplerate: " << spec->sampleRate << ", is the same as jacks: " << - nframes; + if (newSampleRate != spec->sampleRate) { + LOGW() << "Jack reported system sampleRate change. new samplerate: " << newSampleRate << ", MuseScore: " << spec->sampleRate; + // FIX: notify Musescore audio-layer to adjust musescores samplerate + } + spec->sampleRate = newSampleRate; return 0; } -bool JackAudioDriver::open(const Spec& spec, Spec* activeSpec) +bool JackDriverState::open(const IAudioDriver::Spec& spec, IAudioDriver::Spec* activeSpec) { + LOGI() << "cb: " << std::addressof(spec.callback) << " acb: " << std::addressof(activeSpec->callback); if (isOpened()) { LOGW() << "Jack is already opened"; - return false; + return true; } - // m_jackDriverState->samples = spec.samples; // client doesn't set sample-rate - m_jackDriverState->channels = spec.channels; - m_jackDriverState->callback = spec.callback; - m_jackDriverState->userdata = spec.userdata; + // m_spec.samples = spec.samples; // client doesn't set sample-rate + m_spec.channels = spec.channels; + m_spec.callback = spec.callback; + m_spec.userdata = spec.userdata; // FIX: "default" is not a good name for jack-clients // const char *clientName = // outputDevice().c_str() == "default" ? "MuseScore" : @@ -115,24 +117,16 @@ bool JackAudioDriver::open(const Spec& spec, Spec* activeSpec) jack_status_t status; jack_client_t* handle; + LOGI() << "jcb: " << std::addressof(m_spec.callback); if (!(handle = jack_client_open(clientName, JackNullOption, &status))) { LOGE() << "jack_client_open() failed: " << status; return false; } - - jack_set_sample_rate_callback(handle, jack_srate_callback, (void*)&spec); - - m_jackDriverState->jackDeviceHandle = handle; - - jack_port_t* output_port_left = jack_port_register(handle, "audio_out_left", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); - 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); - m_jackDriverState->outputPorts.push_back(output_port_right); - - m_jackDriverState->samples = jack_get_buffer_size(handle); - LOGI() << "buffer size (in samples): " << m_jackDriverState->samples; + m_jackDeviceHandle = handle; unsigned int jackSamplerate = jack_get_sample_rate(handle); + m_spec.sampleRate = jackSamplerate; + LOGI() << "sampleRate used by MuseScore: " << spec.sampleRate; LOGI() << "sampleRate used by jack: " << jackSamplerate; if (spec.sampleRate != jackSamplerate) { LOGW() << "Musescores samplerate: " << spec.sampleRate << ", is NOT the same as jack's: " << jackSamplerate; @@ -141,17 +135,27 @@ bool JackAudioDriver::open(const Spec& spec, Spec* activeSpec) //return false; } - m_jackDriverState->buffer = new float[m_jackDriverState->samples * m_jackDriverState->channels]; + jack_set_sample_rate_callback(handle, jack_srate_callback, (void*)&m_spec); + + jack_port_t* output_port_left = jack_port_register(handle, "audio_out_left", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + m_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); + m_outputPorts.push_back(output_port_right); + + m_spec.samples = jack_get_buffer_size(handle); + LOGI() << "buffer size (in frames): " << m_spec.samples; + + m_buffer = new float[m_spec.samples * m_spec.channels]; if (activeSpec) { *activeSpec = spec; - activeSpec->format = Format::AudioF32; + activeSpec->format = IAudioDriver::Format::AudioF32; activeSpec->sampleRate = jackSamplerate; - m_jackDriverState->format = *activeSpec; + m_spec = *activeSpec; } - jack_on_shutdown(handle, jack_cleanup_callback, (void*)m_jackDriverState.get()); - jack_set_process_callback(handle, jack_process_callback, (void*)m_jackDriverState.get()); + jack_on_shutdown(handle, jack_cleanup_callback, (void*)this); + jack_set_process_callback(handle, jack_process_callback, (void*)this); if (jack_activate(handle)) { LOGE() << "cannot activate client"; @@ -161,119 +165,15 @@ bool JackAudioDriver::open(const Spec& spec, Spec* activeSpec) return true; } -void JackAudioDriver::close() -{ - jack_client_close(static_cast(m_jackDriverState->jackDeviceHandle)); - m_jackDriverState->jackDeviceHandle = nullptr; - delete[] m_jackDriverState->buffer; -} - -bool JackAudioDriver::isOpened() const -{ - return m_jackDriverState->jackDeviceHandle != nullptr; -} - -AudioDeviceID JackAudioDriver::outputDevice() const -{ - return m_deviceId; -} - -bool JackAudioDriver::selectOutputDevice(const AudioDeviceID& deviceId) -{ - if (m_deviceId == deviceId) { - return true; - } - - bool reopen = isOpened(); - close(); - m_deviceId = deviceId; - - bool ok = true; - if (reopen) { - ok = open(m_jackDriverState->format, &m_jackDriverState->format); - } - - if (ok) { - m_outputDeviceChanged.notify(); - } - - return ok; -} - -bool JackAudioDriver::resetToDefaultOutputDevice() -{ - return selectOutputDevice(DEFAULT_DEVICE_ID); -} - -mu::async::Notification JackAudioDriver::outputDeviceChanged() const -{ - return m_outputDeviceChanged; -} - -AudioDeviceList JackAudioDriver::availableOutputDevices() const -{ - AudioDeviceList devices; - devices.push_back({ DEFAULT_DEVICE_ID, trc("audio", "System default") }); - - return devices; -} - -mu::async::Notification JackAudioDriver::availableOutputDevicesChanged() const -{ - return m_availableOutputDevicesChanged; -} - -unsigned int JackAudioDriver::outputDeviceBufferSize() const -{ - return m_jackDriverState->format.samples; -} - -bool JackAudioDriver::setOutputDeviceBufferSize(unsigned int bufferSize) -{ - if (m_jackDriverState->format.samples == bufferSize) { - return true; - } - - bool reopen = isOpened(); - close(); - m_jackDriverState->format.samples = bufferSize; - - bool ok = true; - if (reopen) { - ok = open(m_jackDriverState->format, &m_jackDriverState->format); - } - - if (ok) { - m_bufferSizeChanged.notify(); - } - - return ok; -} - -mu::async::Notification JackAudioDriver::outputDeviceBufferSizeChanged() const -{ - return m_bufferSizeChanged; -} - -std::vector JackAudioDriver::availableOutputDeviceBufferSizes() const -{ - std::vector result; - - unsigned int n = 4096; - while (n >= MINIMUM_BUFFER_SIZE) { - result.push_back(n); - n /= 2; - } - - std::sort(result.begin(), result.end()); - - return result; -} - -void JackAudioDriver::resume() +void JackDriverState::close() { + jack_client_close(static_cast(m_jackDeviceHandle)); + m_jackDeviceHandle = nullptr; + delete[] m_buffer; + m_buffer = nullptr; } -void JackAudioDriver::suspend() +bool JackDriverState::isOpened() const { + return m_jackDeviceHandle != nullptr; } diff --git a/src/framework/audio/internal/platform/jack/jackaudiodriver.h b/src/framework/audio/internal/platform/jack/jackaudiodriver.h index 2245f6fd4fb56..be081bba50b0d 100644 --- a/src/framework/audio/internal/platform/jack/jackaudiodriver.h +++ b/src/framework/audio/internal/platform/jack/jackaudiodriver.h @@ -5,7 +5,7 @@ * MuseScore * Music Composition & Notation * - * Copyright (C) 2021 MuseScore BVBA and others + * Copyright (C) 2022 MuseScore BVBA and others * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -20,74 +20,40 @@ * along with this program. If not, see . */ -#ifndef MU_AUDIO_LINUXAUDIODRIVER_H -#define MU_AUDIO_LINUXAUDIODRIVER_H +#ifndef MU_AUDIO_JACKAUDIODRIVER_H +#define MU_AUDIO_JACKAUDIODRIVER_H #include -#include "async/asyncable.h" #include "iaudiodriver.h" -#include "audiodeviceslistener.h" namespace mu::audio { -int jack_process_callback(jack_nframes_t nframes, void* jackParam); +//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 +class JackDriverState : public AudioDriverState { public: - JackAudioDriver(); - ~JackAudioDriver(); - - void init() override; + JackDriverState(); + ~JackDriverState(); std::string name() const override; - bool open(const Spec& spec, Spec* activeSpec) override; + bool open(const IAudioDriver::Spec& spec, IAudioDriver::Spec* activeSpec) override; void close() override; bool isOpened() const override; + std::string deviceName() const; + void deviceName(const std::string newDeviceName); - AudioDeviceID outputDevice() const override; - bool selectOutputDevice(const AudioDeviceID& deviceId) override; - bool resetToDefaultOutputDevice() override; - async::Notification outputDeviceChanged() const override; - - AudioDeviceList availableOutputDevices() const override; - async::Notification availableOutputDevicesChanged() const override; - - unsigned int outputDeviceBufferSize() const override; - bool setOutputDeviceBufferSize(unsigned int bufferSize) override; - async::Notification outputDeviceBufferSizeChanged() const override; + void* m_jackDeviceHandle = nullptr; - std::vector availableOutputDeviceBufferSizes() const override; + float* m_buffer = nullptr; - void resume() override; - void suspend() override; + std::vector m_outputPorts; private: - async::Notification m_outputDeviceChanged; - - mutable std::mutex m_devicesMutex; - AudioDevicesListener m_devicesListener; - async::Notification m_availableOutputDevicesChanged; - - std::string m_deviceId; - - async::Notification m_bufferSizeChanged; - async::Notification m_sampleRateChanged; - - std::shared_ptr m_jackDriverState; + std::string m_deviceName = ""; // isn't used with jack + void jackCleanup(); }; } -#endif // MU_AUDIO_LINUXAUDIODRIVER_H +#endif // MU_AUDIO_JACKAUDIODRIVER_H diff --git a/src/framework/audio/internal/platform/lin/linuxaudiodriver.cpp b/src/framework/audio/internal/platform/lin/linuxaudiodriver.cpp index 73585f6a7a862..bb2a2f6c3a538 100644 --- a/src/framework/audio/internal/platform/lin/linuxaudiodriver.cpp +++ b/src/framework/audio/internal/platform/lin/linuxaudiodriver.cpp @@ -21,6 +21,9 @@ */ #include "linuxaudiodriver.h" #include "../alsa/alsaaudiodriver.h" //FIX: relative path, set path in CMakeLists +#if JACK_AUDIO +#include "../jack/jackaudiodriver.h" //FIX: relative path, set path in CMakeLists +#endif #define ALSA_PCM_NEW_HW_PARAMS_API #include @@ -39,7 +42,6 @@ using namespace mu::audio; LinuxAudioDriver::LinuxAudioDriver() { - m_current_audioDriverState = std::make_shared(); } LinuxAudioDriver::~LinuxAudioDriver() @@ -64,7 +66,11 @@ std::string LinuxAudioDriver::name() const bool LinuxAudioDriver::open(const Spec& spec, Spec* activeSpec) { - return m_current_audioDriverState->open(spec, activeSpec); + if (! m_current_audioDriverState->open(spec, activeSpec)) { + return false; + } + m_spec = *activeSpec; + return true; } void LinuxAudioDriver::close() @@ -79,31 +85,59 @@ bool LinuxAudioDriver::isOpened() const AudioDeviceID LinuxAudioDriver::outputDevice() const { - return m_current_audioDriverState->name(); // m_deviceId; + if (m_current_audioDriverState != nullptr) { + return m_current_audioDriverState->m_deviceId; + } else { + LOGE("device is not opened"); + return m_deviceId; // FIX: should return optional type + } +} + +bool LinuxAudioDriver::makeDevice(const AudioDeviceID& deviceId) +{ + if (deviceId == "alsa") { + m_current_audioDriverState = std::make_shared(); +#if JACK_AUDIO + } else if (deviceId == "jack") { + m_current_audioDriverState = std::make_shared(); +#endif + } else { + LOGE() << "Unknown device name: " << deviceId; + return false; + } + return true; } bool LinuxAudioDriver::selectOutputDevice(const AudioDeviceID& deviceId) { + // When starting, no previously device has been selected + if (m_current_audioDriverState == nullptr) { + LOGW() << "no previously opened device"; + return makeDevice(deviceId); + } + // If for some reason we select the same device, do nothing if (m_current_audioDriverState->name() == deviceId) { return true; } - //FIX: no, we need to create the new device conditioned on the deviceId bool reopen = m_current_audioDriverState->isOpened(); - IAudioDriver::Spec spec(m_current_audioDriverState->m_spec); - m_current_audioDriverState->close(); - - bool ok = true; + // close current device if opened if (reopen) { - ok = m_current_audioDriverState->open(spec, &spec); + m_current_audioDriverState->close(); } - m_current_audioDriverState->m_spec = spec; + m_current_audioDriverState = nullptr; // FIX: shouldn't be needed - if (ok) { - m_outputDeviceChanged.notify(); + // select the new device driver + if (! makeDevice(deviceId)) { + return false; } - return ok; + // open the device driver + if (! m_current_audioDriverState->open(m_spec, &m_spec)) { + return false; + } + m_outputDeviceChanged.notify(); + return true; } bool LinuxAudioDriver::resetToDefaultOutputDevice() @@ -147,7 +181,7 @@ bool LinuxAudioDriver::setOutputDeviceBufferSize(unsigned int bufferSize) bool ok = true; if (reopen) { - // FIX: + LOGW() << "reopen the device is not implemented"; // FIX: //ok = open(m_current_audioDriverState->m_spec, &m_current_audioDriverState->m_spec); } @@ -168,7 +202,7 @@ std::vector LinuxAudioDriver::availableOutputDeviceBufferSizes() c { std::vector result; - unsigned int n = 4096; + unsigned int n = 4096; // FIX: magic number while (n >= MINIMUM_BUFFER_SIZE) { result.push_back(n); n /= 2; diff --git a/src/framework/audio/internal/platform/lin/linuxaudiodriver.h b/src/framework/audio/internal/platform/lin/linuxaudiodriver.h index 0b9a69f425800..e1e00c522308f 100644 --- a/src/framework/audio/internal/platform/lin/linuxaudiodriver.h +++ b/src/framework/audio/internal/platform/lin/linuxaudiodriver.h @@ -62,6 +62,7 @@ class LinuxAudioDriver : public IAudioDriver, public async::Asyncable private: void alsaCleanup(); + bool makeDevice(const AudioDeviceID& deviceId); async::Notification m_outputDeviceChanged; mutable std::mutex m_devicesMutex; @@ -74,7 +75,7 @@ class LinuxAudioDriver : public IAudioDriver, public async::Asyncable async::Notification m_sampleRateChanged; struct IAudioDriver::Spec m_spec; - std::shared_ptr m_current_audioDriverState; + std::shared_ptr m_current_audioDriverState = nullptr; }; }