OpenShot Library | libopenshot  0.2.7
AudioPlaybackThread.cpp
Go to the documentation of this file.
1 /**
2  * @file
3  * @brief Source file for AudioPlaybackThread class
4  * @author Duzy Chan <code@duzy.info>
5  * @author Jonathan Thomas <jonathan@openshot.org> *
6  *
7  * @ref License
8  */
9 
10 /* LICENSE
11  *
12  * Copyright (c) 2008-2019 OpenShot Studios, LLC
13  * <http://www.openshotstudios.com/>. This file is part of
14  * OpenShot Library (libopenshot), an open-source project dedicated to
15  * delivering high quality video editing and animation solutions to the
16  * world. For more information visit <http://www.openshot.org/>.
17  *
18  * OpenShot Library (libopenshot) is free software: you can redistribute it
19  * and/or modify it under the terms of the GNU Lesser General Public License
20  * as published by the Free Software Foundation, either version 3 of the
21  * License, or (at your option) any later version.
22  *
23  * OpenShot Library (libopenshot) is distributed in the hope that it will be
24  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26  * GNU Lesser General Public License for more details.
27  *
28  * You should have received a copy of the GNU Lesser General Public License
29  * along with OpenShot Library. If not, see <http://www.gnu.org/licenses/>.
30  */
31 
32 #include "AudioPlaybackThread.h"
33 
34 #include <thread> // for std::this_thread::sleep_for
35 #include <chrono> // for std::chrono::milliseconds
36 
37 namespace openshot
38 {
39 
40  // Global reference to device manager
41  AudioDeviceManagerSingleton *AudioDeviceManagerSingleton::m_pInstance = NULL;
42 
43  // Create or Get an instance of the device manager singleton
45  {
46  if (!m_pInstance) {
47  // Create the actual instance of device manager only once
48  m_pInstance = new AudioDeviceManagerSingleton;
49 
50  // Get preferred audio device name (if any)
51  juce::String preferred_audio_device = juce::String(Settings::Instance()->PLAYBACK_AUDIO_DEVICE_NAME.c_str());
52 
53  // Initialize audio device only 1 time
54  juce::String audio_error = m_pInstance->audioDeviceManager.initialise (
55  0, /* number of input channels */
56  2, /* number of output channels */
57  0, /* no XML settings.. */
58  true, /* select default device on failure */
59  preferred_audio_device /* preferredDefaultDeviceName */);
60 
61  // Persist any errors detected
62  if (audio_error.isNotEmpty()) {
63  m_pInstance->initialise_error = audio_error.toRawUTF8();
64  } else {
65  m_pInstance->initialise_error = "";
66  }
67 
68  // Get all audio device names
69  for (int i = 0; i < m_pInstance->audioDeviceManager.getAvailableDeviceTypes().size(); ++i)
70  {
71  const AudioIODeviceType* t = m_pInstance->audioDeviceManager.getAvailableDeviceTypes()[i];
72  const juce::StringArray deviceNames = t->getDeviceNames ();
73 
74  for (int j = 0; j < deviceNames.size (); ++j )
75  {
76  juce::String deviceName = deviceNames[j];
77  juce::String typeName = t->getTypeName();
78  openshot::AudioDeviceInfo deviceInfo = {deviceName.toRawUTF8(), typeName.toRawUTF8()};
79  m_pInstance->audio_device_names.push_back(deviceInfo);
80  }
81  }
82  }
83 
84  return m_pInstance;
85  }
86 
87  // Close audio device
89  {
90  // Close Audio Device
91  audioDeviceManager.closeAudioDevice();
92  audioDeviceManager.removeAllChangeListeners();
93  audioDeviceManager.dispatchPendingMessages();
94  }
95 
96  // Constructor
97  AudioPlaybackThread::AudioPlaybackThread()
98  : juce::Thread("audio-playback")
99  , player()
100  , transport()
101  , mixer()
102  , source(NULL)
103  , sampleRate(0.0)
104  , numChannels(0)
105  , buffer_size(12000)
106  , is_playing(false)
107  , time_thread("audio-buffer")
108  {
109  }
110 
111  // Destructor
112  AudioPlaybackThread::~AudioPlaybackThread()
113  {
114  }
115 
116  // Set the reader object
117  void AudioPlaybackThread::Reader(openshot::ReaderBase *reader) {
118  if (source)
119  source->Reader(reader);
120  else {
121  // Create new audio source reader
122  source = new AudioReaderSource(reader, 1, buffer_size);
123  source->setLooping(true); // prevent this source from terminating when it reaches the end
124  }
125 
126  // Set local vars
127  sampleRate = reader->info.sample_rate;
128  numChannels = reader->info.channels;
129 
130  // TODO: Update transport or audio source's sample rate, incase the sample rate
131  // is different than the original Reader
132 
133  // Mark as 'playing'
134  Play();
135  }
136 
137  // Get the current frame object (which is filling the buffer)
138  std::shared_ptr<openshot::Frame> AudioPlaybackThread::getFrame()
139  {
140  if (source) return source->getFrame();
141  return std::shared_ptr<openshot::Frame>();
142  }
143 
144  // Get the currently playing frame number
145  int64_t AudioPlaybackThread::getCurrentFramePosition()
146  {
147  return source ? source->getEstimatedFrame() : 0;
148  }
149 
150  // Seek the audio thread
151  void AudioPlaybackThread::Seek(int64_t new_position)
152  {
153  source->Seek(new_position);
154  }
155 
156  // Play the audio
157  void AudioPlaybackThread::Play() {
158  // Start playing
159  is_playing = true;
160  }
161 
162  // Stop the audio
163  void AudioPlaybackThread::Stop() {
164  // Stop playing
165  is_playing = false;
166  }
167 
168  // Start audio thread
169  void AudioPlaybackThread::run()
170  {
171  while (!threadShouldExit())
172  {
173  if (source && !transport.isPlaying() && is_playing) {
174 
175  // Start new audio device (or get existing one)
176  // Add callback
177  AudioDeviceManagerSingleton::Instance()->audioDeviceManager.addAudioCallback(&player);
178 
179  // Create TimeSliceThread for audio buffering
180  time_thread.startThread();
181 
182  // Connect source to transport
183  transport.setSource(
184  source,
185  buffer_size, // tells it to buffer this many samples ahead
186  &time_thread,
187  sampleRate,
188  numChannels);
189  transport.setPosition(0);
190  transport.setGain(1.0);
191 
192  // Connect transport to mixer and player
193  mixer.addInputSource(&transport, false);
194  player.setSource(&mixer);
195 
196  // Start the transport
197  transport.start();
198 
199  while (!threadShouldExit() && transport.isPlaying() && is_playing)
200  std::this_thread::sleep_for(std::chrono::milliseconds(2));
201 
202  // Stop audio and shutdown transport
203  Stop();
204  transport.stop();
205 
206  // Kill previous audio
207  transport.setSource(NULL);
208 
209  player.setSource(NULL);
210  AudioDeviceManagerSingleton::Instance()->audioDeviceManager.removeAudioCallback(&player);
211 
212  // Remove source
213  delete source;
214  source = NULL;
215 
216  // Stop time slice thread
217  time_thread.stopThread(-1);
218  }
219  }
220 
221  }
222 }
Source file for AudioPlaybackThread class.
Singleton wrapper for AudioDeviceManager (to prevent multiple instances).
void CloseAudioDevice()
Close audio device.
std::vector< openshot::AudioDeviceInfo > audio_device_names
List of valid audio device names.
static AudioDeviceManagerSingleton * Instance()
Override with no channels and no preferred audio device.
juce::AudioDeviceManager audioDeviceManager
Public device manager property.
std::string initialise_error
Error found during JUCE initialise method.
void Seek(int64_t new_position)
Seek to a specific frame.
int64_t getEstimatedFrame() const
Get the estimate frame that is playing at this moment.
void Reader(ReaderBase *audio_reader)
Set Reader.
std::shared_ptr< Frame > getFrame() const
Return the current frame object.
void setLooping(bool shouldLoop)
Set if this audio source should repeat when it reaches the end.
This abstract class is the base class, used by all readers in libopenshot.
Definition: ReaderBase.h:98
openshot::ReaderInfo info
Information about the current media file.
Definition: ReaderBase.h:111
static Settings * Instance()
Create or get an instance of this logger singleton (invoke the class with this method)
Definition: Settings.cpp:41
This namespace is the default namespace for all code in the openshot library.
Definition: Compressor.h:47
int channels
The number of audio channels used in the audio stream.
Definition: ReaderBase.h:83
int sample_rate
The number of audio samples per second (44100 is a common sample rate)
Definition: ReaderBase.h:82