@@ -145,27 +145,48 @@ QList<QString> SoundManager::getHostAPIList() const {
145145 return apiList;
146146}
147147
148- void SoundManager::closeDevices (bool sleepAfterClosing) {
149- // qDebug() << "SoundManager::closeDevices()";
148+ void SoundManager::closeDevices (
149+ [[maybe_unused]] bool sleepAfterClosing, [[maybe_unused]] bool async) {
150+ // sleepAfterClosing and async maybe unused depending on platform support
151+ // qDebug() << "SoundManager::closeDevices()";
150152
153+ #ifdef __LINUX__
151154 bool closed = false ;
155+ #endif
152156 for (const auto & pDevice : std::as_const (m_devices)) {
153157 if (pDevice->isOpen ()) {
154158 // NOTE(rryan): As of 2009 (?) it has been safe to close() a SoundDevice
155159 // while callbacks are active.
156160 pDevice->close ();
161+ #ifdef __LINUX__
157162 closed = true ;
163+ #endif
158164 }
159165 }
160166
161- if (closed && sleepAfterClosing) {
162167#ifdef __LINUX__
168+ if (closed && sleepAfterClosing) {
163169 // Sleep for 5 sec to allow asynchronously sound APIs like "pulse" to free
164170 // its resources as well
171+ if (async) {
172+ // Async mode - the caller will wait for `devicesClosed` before
173+ // trying to reconfigure or reopen audio devices
174+ QTimer::singleShot (
175+ std::chrono::seconds (kSleepSecondsAfterClosingDevice ),
176+ this ,
177+ &SoundManager::completeDevicesClosing);
178+ return ;
179+ }
180+ // Sync mode, legacy - we sleep the current thread for 5 seconds
165181 QThread::sleep (kSleepSecondsAfterClosingDevice );
182+ } else if (!closed)
166183#endif
184+ {
185+ completeDevicesClosing ();
167186 }
187+ }
168188
189+ void SoundManager::completeDevicesClosing () {
169190 // TODO(rryan): Should we do this before SoundDevice::close()? No! Because
170191 // then the callback may be running when we call
171192 // onInputDisconnected/onOutputDisconnected.
@@ -199,6 +220,7 @@ void SoundManager::closeDevices(bool sleepAfterClosing) {
199220
200221 // Indicate to the rest of Mixxx that sound is disconnected.
201222 m_pControlObjectSoundStatusCO->set (SOUNDMANAGER_DISCONNECTED );
223+ emit devicesClosed ();
202224}
203225
204226void SoundManager::clearDeviceList (bool sleepAfterClosing) {
@@ -553,12 +575,12 @@ SoundManagerConfig SoundManager::getConfig() const {
553575 return m_config;
554576}
555577
556- void SoundManager::closeActiveConfig () {
578+ void SoundManager::closeActiveConfig (bool async ) {
557579 // Close open devices. After this call we will not get any more
558580 // onDeviceOutputCallback() or pushBuffer() calls because all the
559581 // SoundDevices are closed. closeDevices() blocks and can take a while.
560582 const bool sleepAfterClosing = true ;
561- closeDevices (sleepAfterClosing);
583+ closeDevices (sleepAfterClosing, async );
562584}
563585
564586SoundDeviceStatus SoundManager::setConfig (const SoundManagerConfig& config) {
0 commit comments