diff --git a/include/AudioReaderSource.h b/include/AudioReaderSource.h
index e5756afb..c788fab7 100644
--- a/include/AudioReaderSource.h
+++ b/include/AudioReaderSource.h
@@ -58,6 +58,7 @@ namespace openshot
bool repeat; /// Repeat the audio source when finished
int size; /// The size of the internal buffer
AudioSampleBuffer *buffer; /// The audio sample buffer
+ int speed; /// The speed and direction to playback a reader (1=normal, 2=fast, 3=faster, -1=rewind, etc...)
ReaderBase *reader; /// The reader to pull samples from
int64 original_frame_number; /// The current frame to read from
@@ -70,6 +71,9 @@ namespace openshot
/// Get more samples from the reader
void GetMoreSamplesFromReader();
+ /// Reverse an audio buffer (for backwards audio)
+ juce::AudioSampleBuffer* reverse_buffer(juce::AudioSampleBuffer* buffer);
+
public:
/// @brief Constructor that reads samples from a reader
@@ -111,9 +115,26 @@ namespace openshot
void setBuffer (AudioSampleBuffer *audio_buffer);
const ReaderInfo & getReaderInfo() const { return reader->info; }
+
+ /// Return the current frame object
tr1::shared_ptr getFrame() const { return frame; }
- int getFramePosition() const { return frame_position; }
+
+ /// Get the estimate frame that is playing at this moment
int getEstimatedFrame() const { return int(estimated_frame); }
+
+ /// Set Speed (The speed and direction to playback a reader (1=normal, 2=fast, 3=faster, -1=rewind, etc...)
+ void setSpeed(int new_speed) { speed = new_speed; }
+ /// Get Speed (The speed and direction to playback a reader (1=normal, 2=fast, 3=faster, -1=rewind, etc...)
+ int getSpeed() const { return speed; }
+
+ /// Set Reader
+ void Reader(ReaderBase *audio_reader) { reader = audio_reader; }
+ /// Get Reader
+ ReaderBase* Reader() const { return reader; }
+
+ /// Seek to a specific frame
+ int Seek(int64 new_position) { frame_number = new_position; }
+
};
}
diff --git a/include/PlayerBase.h b/include/PlayerBase.h
index c6d938f1..7c4cbd85 100644
--- a/include/PlayerBase.h
+++ b/include/PlayerBase.h
@@ -68,6 +68,9 @@ namespace openshot
/// Display a loading animation
virtual void Loading() = 0;
+ /// Get the current mode
+ virtual PlaybackMode Mode() = 0;
+
/// Play the video
virtual void Play() = 0;
@@ -81,25 +84,25 @@ namespace openshot
virtual void Seek(int new_frame) = 0;
/// Get the Playback speed
- float Speed();
+ virtual float Speed() = 0;
/// Set the Playback speed (1.0 = normal speed, <1.0 = slower, >1.0 faster)
- void Speed(float new_speed);
+ virtual void Speed(float new_speed) = 0;
/// Stop the video player and clear the cached frames
virtual void Stop() = 0;
/// Get the current reader, such as a FFmpegReader
- ReaderBase* Reader();
+ virtual ReaderBase* Reader() = 0;
/// Set the current reader, such as a FFmpegReader
- void Reader(ReaderBase *new_reader);
+ virtual void Reader(ReaderBase *new_reader) = 0;
/// Get the Volume
- float Volume();
+ virtual float Volume() = 0;
/// Set the Volume (1.0 = normal volume, <1.0 = quieter, >1.0 louder)
- void Volume(float new_volume);
+ virtual void Volume(float new_volume) = 0;
};
diff --git a/include/Qt/PlayerDemo.h b/include/Qt/PlayerDemo.h
index fa53972a..9f1a372a 100644
--- a/include/Qt/PlayerDemo.h
+++ b/include/Qt/PlayerDemo.h
@@ -9,6 +9,7 @@
#include
#include
#include
+#include
namespace openshot
{
@@ -26,6 +27,9 @@ public:
PlayerDemo(QWidget *parent = 0);
~PlayerDemo();
+protected:
+ void keyPressEvent(QKeyEvent *event);
+
private slots:
void open(bool checked);
diff --git a/include/QtPlayer.h b/include/QtPlayer.h
index a7f24215..65bc30e5 100644
--- a/include/QtPlayer.h
+++ b/include/QtPlayer.h
@@ -47,6 +47,7 @@ namespace openshot
class QtPlayer : public PlayerBase
{
PlayerPrivate *p;
+ bool threads_started;
public:
/// Default constructor
@@ -64,6 +65,9 @@ namespace openshot
/// Display a loading animation
void Loading();
+ /// Get the current mode
+ PlaybackMode Mode();
+
/// Pause the video
void Pause();
@@ -73,8 +77,26 @@ namespace openshot
/// Seek to a specific frame in the player
void Seek(int new_frame);
+ /// Get the Playback speed
+ float Speed();
+
+ /// Set the Playback speed (1.0 = normal speed, <1.0 = slower, >1.0 faster)
+ void Speed(float new_speed);
+
/// Stop the video player and clear the cached frames
void Stop();
+
+ /// Set the current reader
+ void Reader(ReaderBase *new_reader);
+
+ /// Get the current reader, such as a FFmpegReader
+ ReaderBase* Reader();
+
+ /// Get the Volume
+ float Volume();
+
+ /// Set the Volume (1.0 = normal volume, <1.0 = quieter, >1.0 louder)
+ void Volume(float new_volume);
};
}
diff --git a/src/AudioReaderSource.cpp b/src/AudioReaderSource.cpp
index 0569bf33..677ee308 100644
--- a/src/AudioReaderSource.cpp
+++ b/src/AudioReaderSource.cpp
@@ -33,7 +33,7 @@ using namespace openshot;
// Constructor that reads samples from a reader
AudioReaderSource::AudioReaderSource(ReaderBase *audio_reader, int64 starting_frame_number, int buffer_size)
: reader(audio_reader), frame_number(starting_frame_number), original_frame_number(starting_frame_number),
- size(buffer_size), position(0), frame_position(0), estimated_frame(0) {
+ size(buffer_size), position(0), frame_position(0), estimated_frame(0), speed(1) {
// Initialize an audio buffer (based on reader)
buffer = new juce::AudioSampleBuffer(reader->info.channels, size);
@@ -79,13 +79,14 @@ void AudioReaderSource::GetMoreSamplesFromReader() {
position = 0;
// Loop through frames until buffer filled
- while (amount_needed > 0) {
+ while (amount_needed > 0 && speed != 0) {
// Get the next frame (if position is zero)
if (frame_position == 0) {
try {
// Get frame object
- frame = reader->GetFrameSafe(frame_number++);
+ frame = reader->GetFrameSafe(frame_number);
+ frame_number = frame_number + speed;
} catch (const ReaderClosed & e) {
break;
@@ -110,7 +111,12 @@ void AudioReaderSource::GetMoreSamplesFromReader() {
// Load all of its samples into the buffer
for (int channel = 0; channel < new_buffer->getNumChannels(); channel++)
- new_buffer->addFrom(channel, position, *frame->GetAudioSampleBuffer(), channel, frame_position, amount_to_copy);
+ if (speed >= 0)
+ // playback normal
+ new_buffer->addFrom(channel, position, *frame->GetAudioSampleBuffer(), channel, frame_position, amount_to_copy);
+ else
+ // reverse playback
+ new_buffer->addFrom(channel, position, *reverse_buffer(frame->GetAudioSampleBuffer()), channel, frame_position, amount_to_copy);
// Adjust remaining samples
position += amount_to_copy;
@@ -131,6 +137,37 @@ void AudioReaderSource::GetMoreSamplesFromReader() {
position = 0;
}
+// Reverse an audio buffer
+juce::AudioSampleBuffer* AudioReaderSource::reverse_buffer(juce::AudioSampleBuffer* buffer)
+{
+ int number_of_samples = buffer->getNumSamples();
+ int channels = buffer->getNumChannels();
+
+ // Reverse array (create new buffer to hold the reversed version)
+ AudioSampleBuffer *reversed = new juce::AudioSampleBuffer(channels, number_of_samples);
+ reversed->clear();
+
+ for (int channel = 0; channel < channels; channel++)
+ {
+ int n=0;
+ for (int s = number_of_samples - 1; s >= 0; s--, n++)
+ reversed->getSampleData(channel)[n] = buffer->getSampleData(channel)[s];
+ }
+
+ // Copy the samples back to the original array
+ buffer->clear();
+ // Loop through channels, and get audio samples
+ for (int channel = 0; channel < channels; channel++)
+ // Get the audio samples for this channel
+ buffer->addFrom(channel, 0, reversed->getSampleData(channel), number_of_samples, 1.0f);
+
+ delete reversed;
+ reversed = NULL;
+
+ // return pointer or passed in object (so this method can be chained together)
+ return buffer;
+}
+
// Get the next block of audio samples
void AudioReaderSource::getNextAudioBlock (const AudioSourceChannelInfo& info)
{
@@ -182,7 +219,8 @@ void AudioReaderSource::getNextAudioBlock (const AudioSourceChannelInfo& info)
// Adjust estimate frame number (the estimated frame number that is being played)
estimated_samples_per_frame = Frame::GetSamplesPerFrame(estimated_frame, reader->info.fps, reader->info.sample_rate);
- estimated_frame += double(info.numSamples) / double(estimated_samples_per_frame);
+ if (speed != 0)
+ estimated_frame += double(info.numSamples) / double(estimated_samples_per_frame);
}
}
diff --git a/src/Qt/AudioPlaybackThread.cpp b/src/Qt/AudioPlaybackThread.cpp
index 2aff987d..10ba5d9b 100644
--- a/src/Qt/AudioPlaybackThread.cpp
+++ b/src/Qt/AudioPlaybackThread.cpp
@@ -2,6 +2,7 @@
* @file
* @brief Source file for AudioPlaybackThread class
* @author Duzy Chan
+ * @author Jonathan Thomas *
*
* @section LICENSE
*
@@ -44,6 +45,7 @@ namespace openshot
}
};
+ // Construtor
AudioPlaybackThread::AudioPlaybackThread()
: Thread("audio-playback")
, audioDeviceManager()
@@ -57,28 +59,41 @@ namespace openshot
{
}
+ // Destructor
AudioPlaybackThread::~AudioPlaybackThread()
{
}
- void AudioPlaybackThread::setReader(ReaderBase *reader)
+ // Set the reader object
+ void AudioPlaybackThread::Reader(ReaderBase *reader)
{
- sampleRate = reader->info.sample_rate;
- numChannels = reader->info.channels;
- source = new AudioReaderSource(reader, 1, buffer_size);
+ if (!source) {
+ sampleRate = reader->info.sample_rate;
+ numChannels = reader->info.channels;
+ source = new AudioReaderSource(reader, 1, buffer_size);
+ }
}
+ // Get the current frame object (which is filling the buffer)
tr1::shared_ptr AudioPlaybackThread::getFrame()
{
if (source) return source->getFrame();
return tr1::shared_ptr();
}
+ // Get the currently playing frame number
int AudioPlaybackThread::getCurrentFramePosition()
{
return source ? source->getEstimatedFrame() : 0;
}
+ // Seek the audio thread
+ void AudioPlaybackThread::Seek(int new_position)
+ {
+ source->Seek(new_position);
+ }
+
+ // Start audio thread
void AudioPlaybackThread::run()
{
// Init audio device
@@ -113,7 +128,7 @@ namespace openshot
transport.start();
while (!threadShouldExit() && transport.isPlaying()) {
- sleep(1);
+ sleep(100);
}
transport.stop();
@@ -124,5 +139,9 @@ namespace openshot
audioDeviceManager.closeAudioDevice();
audioDeviceManager.removeAllChangeListeners();
audioDeviceManager.dispatchPendingMessages();
+
+ // Remove source
+ delete source;
+ source = NULL;
}
}
diff --git a/src/Qt/AudioPlaybackThread.h b/src/Qt/AudioPlaybackThread.h
index bb8b848c..770f8edc 100644
--- a/src/Qt/AudioPlaybackThread.h
+++ b/src/Qt/AudioPlaybackThread.h
@@ -2,6 +2,7 @@
* @file
* @brief Source file for AudioPlaybackThread class
* @author Duzy Chan
+ * @author Jonathan Thomas
*
* @section LICENSE
*
@@ -31,7 +32,7 @@ namespace openshot
using juce::WaitableEvent;
/**
- * @brief The audio playback class.
+ * @brief The audio playback thread
*/
class AudioPlaybackThread : Thread
{
@@ -47,15 +48,32 @@ namespace openshot
WaitableEvent played;
int buffer_size;
+ /// Constructor
AudioPlaybackThread();
+ /// Destructor
~AudioPlaybackThread();
- void setReader(ReaderBase *reader);
+ /// Set the current thread's reader
+ void Reader(ReaderBase *reader);
+
+ /// Get the current frame object (which is filling the buffer)
tr1::shared_ptr getFrame();
+
+ /// Get the current frame number being played
int getCurrentFramePosition();
+ /// Seek the audio thread
+ void Seek(int new_position);
+
+ /// Start thread
void run();
+ /// Set Speed (The speed and direction to playback a reader (1=normal, 2=fast, 3=faster, -1=rewind, etc...)
+ void setSpeed(int new_speed) { if (source) source->setSpeed(new_speed); }
+
+ /// Get Speed (The speed and direction to playback a reader (1=normal, 2=fast, 3=faster, -1=rewind, etc...)
+ int getSpeed() const { if (source) return source->getSpeed(); else return 1; }
+
friend class PlayerPrivate;
};
diff --git a/src/Qt/PlayerDemo.cpp b/src/Qt/PlayerDemo.cpp
index 8185007c..5fbac427 100644
--- a/src/Qt/PlayerDemo.cpp
+++ b/src/Qt/PlayerDemo.cpp
@@ -2,6 +2,8 @@
* @file player.cpp
*/
+#include "stdio.h"
+#include "string.h"
#include "../../../include/QtPlayer.h"
#include "../../../include/Qt/PlayerDemo.h"
#include "../../../include/Qt/VideoRenderWidget.h"
@@ -30,6 +32,10 @@ PlayerDemo::PlayerDemo(QWidget *parent)
vbox->setMargin(0);
vbox->setSpacing(0);
resize(600, 480);
+
+ // Accept keyboard event
+ setFocusPolicy(Qt::StrongFocus);
+
}
PlayerDemo::~PlayerDemo()
@@ -37,6 +43,42 @@ PlayerDemo::~PlayerDemo()
delete player;
}
+void PlayerDemo::keyPressEvent(QKeyEvent *event)
+{
+ string key = event->text().toStdString();
+ if (key == " ") {
+ cout << "START / STOP: " << player->Mode() << endl;
+ if (player->Mode() == openshot::PLAYBACK_PLAY)
+ player->Pause();
+ else if (player->Mode() == openshot::PLAYBACK_PAUSED)
+ player->Play();
+
+ }
+ else if (key == "j") {
+ cout << "BACKWARD" << player->Speed() - 1 << endl;
+ int current_speed = player->Speed();
+ player->Speed(current_speed - 1); // backwards
+
+ }
+ else if (key == "k") {
+ cout << "PAUSE" << endl;
+ if (player->Mode() == openshot::PLAYBACK_PLAY)
+ player->Pause();
+ else if (player->Mode() == openshot::PLAYBACK_PAUSED)
+ player->Play();
+
+ }
+ else if (key == "l") {
+ cout << "FORWARD" << player->Speed() + 1 << endl;
+ int current_speed = player->Speed();
+ player->Speed(current_speed + 1); // backwards
+
+ }
+
+ event->accept();
+ QWidget::keyPressEvent(event);
+}
+
void PlayerDemo::open(bool checked)
{
const QString filename = QFileDialog::getOpenFileName(this, "Open Video File");
diff --git a/src/Qt/PlayerPrivate.cpp b/src/Qt/PlayerPrivate.cpp
index 00707089..dd8408c9 100644
--- a/src/Qt/PlayerPrivate.cpp
+++ b/src/Qt/PlayerPrivate.cpp
@@ -25,22 +25,20 @@
* You should have received a copy of the GNU General Public License
* along with OpenShot Library. If not, see .
*/
-#include "../include/ReaderBase.h"
-#include "../include/RendererBase.h"
-#include "../include/AudioReaderSource.h"
+
#include "PlayerPrivate.h"
-#include "AudioPlaybackThread.h"
-#include "VideoPlaybackThread.h"
namespace openshot
{
+ // Constructor
PlayerPrivate::PlayerPrivate(RendererBase *rb)
: Thread("player"), video_position(0), audio_position(0)
, audioPlayback(new AudioPlaybackThread())
, videoPlayback(new VideoPlaybackThread(rb))
- {
- }
+ , speed(1), reader(NULL)
+ { }
+ // Destructor
PlayerPrivate::~PlayerPrivate()
{
if (isThreadRunning()) stopThread(500);
@@ -50,13 +48,15 @@ namespace openshot
delete videoPlayback;
}
+ // Start thread
void PlayerPrivate::run()
{
+ // Kill audio and video threads (if they are currently running)
if (audioPlayback->isThreadRunning() && reader->info.has_audio) audioPlayback->stopThread(-1);
if (videoPlayback->isThreadRunning() && reader->info.has_video) videoPlayback->stopThread(-1);
// Set the reader for the Audio thread
- audioPlayback->setReader(reader);
+ audioPlayback->Reader(reader);
// Start the threads
if (reader->info.has_audio)
@@ -67,6 +67,15 @@ namespace openshot
tr1::shared_ptr frame;
while (!threadShouldExit()) {
+ // Calculate the milliseconds a single frame should stay on the screen
+ double frame_time = (1000.0 / reader->info.fps.ToDouble());
+
+ // Experimental Pausing Code
+ if (speed == 0) {
+ sleep(frame_time);
+ continue;
+ }
+
// Get the start time (to track how long a frame takes to render)
const Time t1 = Time::getCurrentTime();
@@ -88,9 +97,6 @@ namespace openshot
// Get the end time (to track how long a frame takes to render)
const Time t2 = Time::getCurrentTime();
- // Calculate the milliseconds a single frame should stay on the screen
- double frame_time = (1000.0 / reader->info.fps.ToDouble());
-
// Determine how many milliseconds it took to render the frame
int64 render_time = t2.toMilliseconds() - t1.toMilliseconds();
@@ -112,25 +118,24 @@ namespace openshot
// Debug output
std::cout << "video frame diff: " << video_frame_diff << std::endl;
- // Determine if the next frame will be the end of stream
- //if ((video_position + 1) > reader->info.video_length)
- //{
- // End threads at END OF STREAM
- //if (reader->info.has_audio)
- // audioPlayback->stopThread(1);
- //if (reader->info.has_video)
- // videoPlayback->stopThread(2);
- //}
}
+ std::cout << "stopped thread" << endl;
+
+ // Kill audio and video threads (if they are still running)
if (audioPlayback->isThreadRunning() && reader->info.has_audio) audioPlayback->stopThread(-1);
if (videoPlayback->isThreadRunning() && reader->info.has_video) videoPlayback->stopThread(-1);
}
+ // Get the next displayed frame (based on speed and direction)
tr1::shared_ptr PlayerPrivate::getFrame()
{
try {
- return reader->GetFrameSafe(video_position++);
+
+ // Get the next frame (based on speed)
+ video_position = video_position + speed;
+ return reader->GetFrameSafe(video_position);
+
} catch (const ReaderClosed & e) {
// ...
} catch (const TooManySeeks & e) {
@@ -141,6 +146,7 @@ namespace openshot
return tr1::shared_ptr();
}
+ // Start video/audio playback
bool PlayerPrivate::startPlayback()
{
if (video_position < 0) return false;
@@ -149,9 +155,39 @@ namespace openshot
return true;
}
+ // Stop video/audio playback
void PlayerPrivate::stopPlayback(int timeOutMilliseconds)
{
+ std::cout << "stop playback!!!" << std::endl;
if (isThreadRunning()) stopThread(timeOutMilliseconds);
}
+ // Seek to a frame
+ void PlayerPrivate::Seek(int new_position)
+ {
+ // Check for seek
+ if (new_position > 0) {
+ // Update current position
+ video_position = new_position;
+
+ // Notify audio thread that seek has occured
+ audioPlayback->Seek(video_position);
+ }
+ }
+
+ // Set Speed (The speed and direction to playback a reader (1=normal, 2=fast, 3=faster, -1=rewind, etc...)
+ void PlayerPrivate::Speed(int new_speed)
+ {
+ speed = new_speed;
+ if (reader->info.has_audio)
+ audioPlayback->setSpeed(new_speed);
+ }
+
+ // Set the reader object
+ void PlayerPrivate::Reader(ReaderBase *new_reader)
+ {
+ reader = new_reader;
+ audioPlayback->Reader(new_reader);
+ }
+
}
diff --git a/src/Qt/PlayerPrivate.h b/src/Qt/PlayerPrivate.h
index c1e40993..d054ad17 100644
--- a/src/Qt/PlayerPrivate.h
+++ b/src/Qt/PlayerPrivate.h
@@ -26,6 +26,12 @@
* along with OpenShot Library. If not, see .
*/
+#include "../include/ReaderBase.h"
+#include "../include/RendererBase.h"
+#include "../include/AudioReaderSource.h"
+#include "AudioPlaybackThread.h"
+#include "VideoPlaybackThread.h"
+
namespace openshot
{
class AudioPlaybackThread;
@@ -33,26 +39,47 @@ namespace openshot
using juce::Thread;
/**
- * @brief The private part of QtPlayer class.
+ * @brief The private part of QtPlayer class, which contains an audio thread and video thread,
+ * and controls the video timing and audio synchronization code.
*/
class PlayerPrivate : Thread
{
int video_position; /// The current frame position.
int audio_position; /// The current frame position.
- ReaderBase *reader;
- AudioPlaybackThread *audioPlayback;
- VideoPlaybackThread *videoPlayback;
+ ReaderBase *reader; /// The reader which powers this player
+ AudioPlaybackThread *audioPlayback; /// The audio thread
+ VideoPlaybackThread *videoPlayback; /// The video thread
+ int speed; /// The speed and direction to playback a reader (1=normal, 2=fast, 3=faster, -1=rewind, etc...)
+ /// Constructor
PlayerPrivate(RendererBase *rb);
+ /// Destructor
virtual ~PlayerPrivate();
+ /// Start thread
void run();
+ /// Seek to a frame
+ void Seek(int new_position);
+
+ /// Start the video/audio playback
bool startPlayback();
+
+ /// Stop the video/audio playback
void stopPlayback(int timeOutMilliseconds = -1);
+ /// Get the next frame (based on speed and direction)
tr1::shared_ptr getFrame();
+ /// Set Speed (The speed and direction to playback a reader (1=normal, 2=fast, 3=faster, -1=rewind, etc...)
+ void Speed(int new_speed);
+ /// Get Speed (The speed and direction to playback a reader (1=normal, 2=fast, 3=faster, -1=rewind, etc...)
+ int Speed() const { return speed; }
+
+ /// Set the current reader
+ void Reader(ReaderBase *new_reader);
+
+ /// The parent class of PlayerPrivate
friend class QtPlayer;
};
diff --git a/src/Qt/VideoPlaybackThread.cpp b/src/Qt/VideoPlaybackThread.cpp
index ca69fde5..d41295cc 100644
--- a/src/Qt/VideoPlaybackThread.cpp
+++ b/src/Qt/VideoPlaybackThread.cpp
@@ -31,16 +31,19 @@
namespace openshot
{
+ // Constructor
VideoPlaybackThread::VideoPlaybackThread(RendererBase *rb)
: Thread("video-playback"), renderer(rb)
, render(), reset(false)
{
}
+ // Destructor
VideoPlaybackThread::~VideoPlaybackThread()
{
}
+ // Get the currently playing frame number (if any)
int VideoPlaybackThread::getCurrentFramePosition()
{
if (frame)
@@ -49,11 +52,15 @@ namespace openshot
return 0;
}
+ // Start the thread
void VideoPlaybackThread::run()
{
while (!threadShouldExit()) {
- render.wait();
+ // Make other threads wait on the render event
+ render.wait();
+ // Render the frame to the screen
renderer->paint(frame);
+ // Signal to other threads that the rendered event has completed
rendered.signal();
}
}
diff --git a/src/Qt/VideoPlaybackThread.h b/src/Qt/VideoPlaybackThread.h
index 0a56e2e2..aa0837e1 100644
--- a/src/Qt/VideoPlaybackThread.h
+++ b/src/Qt/VideoPlaybackThread.h
@@ -42,12 +42,18 @@ namespace openshot
WaitableEvent rendered;
bool reset;
+ /// Constructor
VideoPlaybackThread(RendererBase *rb);
+ /// Destructor
~VideoPlaybackThread();
+
+ /// Get the currently playing frame number (if any)
int getCurrentFramePosition();
+ /// Start the thread
void run();
+ /// Parent class of VideoPlaybackThread
friend class PlayerPrivate;
};
diff --git a/src/QtPlayer.cpp b/src/QtPlayer.cpp
index 3da864ec..0b28cc1a 100644
--- a/src/QtPlayer.cpp
+++ b/src/QtPlayer.cpp
@@ -32,15 +32,15 @@
using namespace openshot;
-QtPlayer::QtPlayer(RendererBase *rb) : PlayerBase(), p(new PlayerPrivate(rb))
+QtPlayer::QtPlayer(RendererBase *rb) : PlayerBase(), p(new PlayerPrivate(rb)), threads_started(false)
{
- reader = NULL;
+ reader = NULL;
}
QtPlayer::~QtPlayer()
{
if (mode != PLAYBACK_STOPPED) {
- //p->stop();
+ Stop();
}
delete p;
}
@@ -49,15 +49,21 @@ void QtPlayer::SetSource(const std::string &source)
{
reader = new FFmpegReader(source);
reader->Open();
+ p->Reader(reader);
}
void QtPlayer::Play()
{
- mode = PLAYBACK_PLAY;
- p->stopPlayback();
- p->video_position = 0;
- p->reader = reader;
- p->startPlayback();
+ cout << "PLAY() on QTPlayer" << endl;
+ if (reader && !threads_started) {
+ mode = PLAYBACK_PLAY;
+ p->Reader(reader);
+ p->startPlayback();
+ threads_started = true;
+ } else {
+ mode = PLAYBACK_PLAY;
+ Speed(1);
+ }
}
void QtPlayer::Loading()
@@ -65,9 +71,16 @@ void QtPlayer::Loading()
mode = PLAYBACK_LOADING;
}
+/// Get the current mode
+PlaybackMode QtPlayer::Mode()
+{
+ return mode;
+}
+
void QtPlayer::Pause()
{
mode = PLAYBACK_PAUSED;
+ Speed(0);
}
int QtPlayer::Position()
@@ -78,10 +91,46 @@ int QtPlayer::Position()
void QtPlayer::Seek(int new_frame)
{
// Seek the reader to a new position
- p->video_position = new_frame;
+ p->Seek(new_frame);
}
void QtPlayer::Stop()
{
mode = PLAYBACK_STOPPED;
+ p->stopPlayback();
+ p->video_position = 0;
+ threads_started = false;
+}
+
+// Set the reader object
+void QtPlayer::Reader(ReaderBase *new_reader)
+{
+ reader = new_reader;
+ p->Reader(new_reader);
+}
+
+// Get the current reader, such as a FFmpegReader
+ReaderBase* QtPlayer::Reader() {
+ return reader;
+}
+
+// Get the Playback speed
+float QtPlayer::Speed() {
+ return speed;
+}
+
+// Set the Playback speed multiplier (1.0 = normal speed, <1.0 = slower, >1.0 faster)
+void QtPlayer::Speed(float new_speed) {
+ speed = new_speed;
+ p->Speed(new_speed);
+}
+
+// Get the Volume
+float QtPlayer::Volume() {
+ return volume;
+}
+
+// Set the Volume multiplier (1.0 = normal volume, <1.0 = quieter, >1.0 louder)
+void QtPlayer::Volume(float new_volume) {
+ volume = new_volume;
}