2525#include < thread> // for std::this_thread::sleep_for
2626#include < chrono> // for std::chrono::milliseconds
2727#include < sstream>
28+ #include < condition_variable>
29+ #include < mutex>
2830
2931using namespace juce ;
3032
@@ -57,9 +59,9 @@ namespace openshot
5759
5860 std::stringstream constructor_title;
5961 constructor_title << " AudioDeviceManagerSingleton::Instance (default audio device type: " <<
60- Settings::Instance ()->PLAYBACK_AUDIO_DEVICE_TYPE << " , default audio device name: " <<
61- Settings::Instance ()->PLAYBACK_AUDIO_DEVICE_NAME << " )" ;
62- ZmqLogger::Instance ()->AppendDebugMethod (constructor_title.str (), " channels" , channels);
62+ Settings::Instance ()->PLAYBACK_AUDIO_DEVICE_TYPE << " , default audio device name: " <<
63+ Settings::Instance ()->PLAYBACK_AUDIO_DEVICE_NAME << " )" ;
64+ ZmqLogger::Instance ()->AppendDebugMethod (constructor_title.str (), " channels" , channels, " buffer " , Settings::Instance ()-> PLAYBACK_AUDIO_BUFFER_SIZE );
6365
6466 // Get preferred audio device type and name (if any - these can be blank)
6567 openshot::AudioDeviceInfo requested_device = {Settings::Instance ()->PLAYBACK_AUDIO_DEVICE_TYPE ,
@@ -81,10 +83,17 @@ namespace openshot
8183 // Populate all possible device types and device names (starting with the user's requested settings)
8284 std::vector<openshot::AudioDeviceInfo> devices{ { requested_device } };
8385 for (const auto t : mgr->getAvailableDeviceTypes ()) {
86+ std::stringstream type_debug;
87+ type_debug << " AudioDeviceManagerSingleton::Instance (iterate audio device type: " << t->getTypeName () << " )" ;
88+ ZmqLogger::Instance ()->AppendDebugMethod (type_debug.str (), " rate" , rate, " channels" , channels);
89+
8490 t->scanForDevices ();
8591 for (const auto n : t->getDeviceNames ()) {
8692 AudioDeviceInfo device = { t->getTypeName (), n.trim () };
8793 devices.push_back (device);
94+ std::stringstream device_debug;
95+ device_debug << " AudioDeviceManagerSingleton::Instance (iterate audio device name: " << device.name << " , type: " << t->getTypeName () << " )" ;
96+ ZmqLogger::Instance ()->AppendDebugMethod (device_debug.str (), " rate" , rate, " channels" , channels);
8897 }
8998 }
9099
@@ -104,6 +113,7 @@ namespace openshot
104113 AudioDeviceManager::AudioDeviceSetup deviceSetup = AudioDeviceManager::AudioDeviceSetup ();
105114 deviceSetup.inputChannels = 0 ;
106115 deviceSetup.outputChannels = channels;
116+ deviceSetup.bufferSize = Settings::Instance ()->PLAYBACK_AUDIO_BUFFER_SIZE ;
107117
108118 // Loop through common sample rates, starting with the user's requested rate
109119 // Not all sample rates are supported by audio devices, for example, many VMs
@@ -234,16 +244,21 @@ namespace openshot
234244 }
235245 }
236246
237- // Play the audio
247+ // Override Play and Stop to notify of state changes
238248 void AudioPlaybackThread::Play () {
239- // Start playing
240249 is_playing = true ;
250+ NotifyTransportStateChanged ();
241251 }
242252
243- // Stop the audio
244253 void AudioPlaybackThread::Stop () {
245- // Stop playing
246254 is_playing = false ;
255+ NotifyTransportStateChanged ();
256+ }
257+
258+ void AudioPlaybackThread::NotifyTransportStateChanged ()
259+ {
260+ std::lock_guard<std::mutex> lock (transportMutex);
261+ transportCondition.notify_all ();
247262 }
248263
249264 // Start audio thread
@@ -260,7 +275,7 @@ namespace openshot
260275 audioInstance->audioDeviceManager .addAudioCallback (&player);
261276
262277 // Create TimeSliceThread for audio buffering
263- time_thread.startThread ();
278+ time_thread.startThread (Priority::high );
264279
265280 // Connect source to transport
266281 transport.setSource (
@@ -279,8 +294,13 @@ namespace openshot
279294 // Start the transport
280295 transport.start ();
281296
282- while (!threadShouldExit () && transport.isPlaying () && is_playing)
283- std::this_thread::sleep_for (std::chrono::milliseconds (2 ));
297+ while (!threadShouldExit () && transport.isPlaying () && is_playing) {
298+ // Wait until transport state changes or thread should exit
299+ std::unique_lock<std::mutex> lock (transportMutex);
300+ transportCondition.wait_for (lock, std::chrono::milliseconds (10 ), [this ]() {
301+ return threadShouldExit () || !transport.isPlaying () || !is_playing;
302+ });
303+ }
284304
285305 // Stop audio and shutdown transport
286306 Stop ();
0 commit comments