17 #include "../ReaderBase.h" 
   18 #include "../RendererBase.h" 
   19 #include "../AudioReaderSource.h" 
   20 #include "../AudioDevices.h" 
   21 #include "../Settings.h" 
   22 #include "../ZmqLogger.h" 
   28 #include <condition_variable> 
   36     AudioDeviceManagerSingleton *AudioDeviceManagerSingleton::m_pInstance = NULL;
 
   41         return AudioDeviceManagerSingleton::Instance(44100, 2);
 
   47         static std::mutex mutex;
 
   48         std::lock_guard<std::mutex> lock(mutex);
 
   54             AudioIODevice *foundAudioIODevice = NULL;
 
   55             m_pInstance->initialise_error = 
"";
 
   56             m_pInstance->currentAudioDevice.name = 
"";
 
   57             m_pInstance->currentAudioDevice.type = 
"";
 
   58             m_pInstance->defaultSampleRate = 0.0;
 
   60             std::stringstream constructor_title;
 
   61             constructor_title << 
"AudioDeviceManagerSingleton::Instance (default audio device type: " <<
 
   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);
 
   68                                                           Settings::Instance()->PLAYBACK_AUDIO_DEVICE_NAME};
 
   71             if (requested_device.
type.isEmpty() && !requested_device.
name.isEmpty()) {
 
   72                 for (
const auto t : mgr->getAvailableDeviceTypes()) {
 
   74                     for (
const auto n : t->getDeviceNames()) {
 
   75                         if (requested_device.
name.trim().equalsIgnoreCase(n.trim())) {
 
   76                             requested_device.
type = t->getTypeName();
 
   84             std::vector<openshot::AudioDeviceInfo> devices{ { requested_device } };
 
   85             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);
 
   91                 for (
const auto n : t->getDeviceNames()) {
 
   93                     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);
 
  101             for (
auto attempt_device : devices) {
 
  102                 m_pInstance->currentAudioDevice = attempt_device;
 
  105                 m_pInstance->audioDeviceManager.initialiseWithDefaultDevices(0, channels);
 
  108                 if (!attempt_device.type.isEmpty()) {
 
  109                     m_pInstance->audioDeviceManager.setCurrentAudioDeviceType(attempt_device.type, 
true);
 
  113                 AudioDeviceManager::AudioDeviceSetup deviceSetup = AudioDeviceManager::AudioDeviceSetup();
 
  114                 deviceSetup.inputChannels = 0;
 
  115                 deviceSetup.outputChannels = channels;
 
  116                 deviceSetup.bufferSize = Settings::Instance()->PLAYBACK_AUDIO_BUFFER_SIZE;
 
  121                 int possible_rates[] { rate, 48000, 44100, 22050 };
 
  122                 for(
int attempt_rate : possible_rates) {
 
  123                     std::stringstream title_rate;
 
  124                     title_rate << 
"AudioDeviceManagerSingleton::Instance (attempt audio device name: " <<  attempt_device.name << 
")";
 
  125                     ZmqLogger::Instance()->AppendDebugMethod(title_rate.str(), 
"rate", attempt_rate, 
"channels", channels);
 
  128                     m_pInstance->defaultSampleRate = attempt_rate;
 
  129                     deviceSetup.sampleRate = attempt_rate;
 
  130                     m_pInstance->audioDeviceManager.setAudioDeviceSetup(deviceSetup, 
true);
 
  134                     juce::String audio_error = m_pInstance->audioDeviceManager.initialise(
 
  144                     m_pInstance->initialise_error = audio_error.toStdString();
 
  146                     if (!m_pInstance->initialise_error.empty()) {
 
  147                         std::stringstream title_error;
 
  148                         title_error << 
"AudioDeviceManagerSingleton::Instance (audio device error: " <<
 
  149                         m_pInstance->initialise_error << 
")";
 
  150                         ZmqLogger::Instance()->AppendDebugMethod(title_error.str(), 
"rate", attempt_rate, 
"channels", channels);
 
  155                     foundAudioIODevice = m_pInstance->audioDeviceManager.getCurrentAudioDevice();
 
  156                     if (foundAudioIODevice && foundAudioIODevice->getCurrentSampleRate() == attempt_rate) {
 
  158                         std::stringstream title_found;
 
  159                         title_found << 
"AudioDeviceManagerSingleton::Instance (successful audio device found: " <<
 
  160                         foundAudioIODevice->getTypeName() << 
", name: " << foundAudioIODevice->getName() << 
")";
 
  161                         ZmqLogger::Instance()->AppendDebugMethod(title_found.str(), 
"rate", attempt_rate, 
"channels", channels);
 
  166                 if (foundAudioIODevice) {
 
  172             ZmqLogger::Instance()->AppendDebugMethod(
"AudioDeviceManagerSingleton::Instance (audio device initialization completed)");
 
  178     void AudioDeviceManagerSingleton::CloseAudioDevice()
 
  181         audioDeviceManager.closeAudioDevice();
 
  182         audioDeviceManager.removeAllChangeListeners();
 
  183         audioDeviceManager.dispatchPendingMessages();
 
  191     : 
juce::Thread(
"audio-playback")
 
  199     , time_thread(
"audio-buffer")
 
  205     AudioPlaybackThread::~AudioPlaybackThread()
 
  215             auto starting_frame = 1;
 
  216             source = 
new AudioReaderSource(reader, starting_frame);
 
  233     std::shared_ptr<openshot::Frame> AudioPlaybackThread::getFrame()
 
  235     if (source) 
return source->
getFrame();
 
  236         return std::shared_ptr<openshot::Frame>();
 
  240     void AudioPlaybackThread::Seek(int64_t new_position)
 
  243             source->
Seek(new_position);
 
  248     void AudioPlaybackThread::Play() {
 
  250         NotifyTransportStateChanged();
 
  253     void AudioPlaybackThread::Stop() {
 
  255         NotifyTransportStateChanged();
 
  258     void AudioPlaybackThread::NotifyTransportStateChanged()
 
  260         std::lock_guard<std::mutex> lock(transportMutex);
 
  261         transportCondition.notify_all();
 
  265     void AudioPlaybackThread::run()
 
  267         while (!threadShouldExit())
 
  269             if (source && !transport.isPlaying() && is_playing) {
 
  271                 AudioDeviceManagerSingleton *audioInstance = 
 
  275                 audioInstance->audioDeviceManager.addAudioCallback(&player);
 
  278                 time_thread.startThread(Priority::high);
 
  287                 transport.setPosition(0);
 
  288                 transport.setGain(1.0);
 
  291                 mixer.addInputSource(&transport, 
false);
 
  292                 player.setSource(&mixer);
 
  297                     while (!threadShouldExit() && transport.isPlaying() && is_playing) {
 
  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;
 
  310                 transport.setSource(NULL);
 
  312                 player.setSource(NULL);
 
  313                 audioInstance->audioDeviceManager.removeAudioCallback(&player);
 
  320                 time_thread.stopThread(-1);