Files
libopenshot/src/QtPlayer.cpp

236 lines
6.0 KiB
C++
Raw Normal View History

/**
* @file
* @brief Source file for QtPlayer class
2014-01-25 03:38:38 +08:00
* @author Duzy Chan <code@duzy.info>
* @author Jonathan Thomas <jonathan@openshot.org>
*
* @ref License
*/
// Copyright (c) 2008-2019 OpenShot Studios, LLC
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#include "QtPlayer.h"
#include "AudioDevices.h"
#include "Clip.h"
#include "FFmpegReader.h"
#include "Timeline.h"
#include "Qt/PlayerPrivate.h"
#include "Qt/VideoRenderer.h"
2011-10-11 08:44:27 -05:00
namespace openshot
{
using AudioDeviceList = std::vector<std::pair<std::string, std::string>>;
// Delegating constructor
QtPlayer::QtPlayer()
: QtPlayer::QtPlayer(new VideoRenderer())
{ }
// Constructor
QtPlayer::QtPlayer(openshot::RendererBase *rb)
: PlayerBase()
, p(new openshot::PlayerPrivate(rb))
, threads_started(false)
{
reader = NULL;
}
2011-10-11 08:44:27 -05:00
QtPlayer::~QtPlayer()
{
if (mode != PLAYBACK_STOPPED)
Stop();
2017-03-21 14:38:42 -05:00
delete p;
}
2011-10-11 08:44:27 -05:00
void QtPlayer::CloseAudioDevice()
{
// Close audio device (only do this once, when all audio playback is finished)
openshot::AudioDeviceManagerSingleton::Instance()->CloseAudioDevice();
}
// Return any error string during initialization
std::string QtPlayer::GetError() {
if (reader && threads_started) {
// Get error from audio thread (if any)
return p->audioPlayback->getError();
} else {
return "";
}
}
/// Get Audio Devices from JUCE
AudioDeviceList QtPlayer::GetAudioDeviceNames() {
AudioDevices devs;
return devs.getNames();
}
// Set the source JSON of an openshot::Timelime
void QtPlayer::SetTimelineSource(const std::string &json) {
// Create timeline instance (720p, since we have no re-scaling in this player yet)
reader = new Timeline(1280, 720, openshot::Fraction(30, 1), 44100, 2, openshot::LAYOUT_STEREO);
Timeline* tm = (Timeline*)reader;
tm->SetJson(json);
tm->DisplayInfo();
tm->Open();
// Set the reader
Reader(reader);
}
void QtPlayer::SetSource(const std::string &source)
{
FFmpegReader *ffreader = new FFmpegReader(source);
ffreader->DisplayInfo();
// Use default sample rate (or use the FFmpegReader's audio settings if any)
int sample_rate = 44100;
if (ffreader->info.sample_rate > 0)
sample_rate = ffreader->info.sample_rate;
// Use default channels (or use the FFmpegReader's audio settings if any)
int channels = 2;
if (ffreader->info.channels > 0)
channels = ffreader->info.channels;
// Use default channel layout (or use the FFmpegReader's audio settings if any)
openshot::ChannelLayout channel_layout = openshot::LAYOUT_STEREO;
if (channels != 2)
channel_layout = ffreader->info.channel_layout;
// Create timeline instance (720p, since we have no re-scaling in this player yet)
reader = new Timeline(1280, 720, ffreader->info.fps, sample_rate, channels, channel_layout);
Clip *c = new Clip(source);
Timeline* tm = (Timeline*)reader;
tm->AddClip(c);
tm->Open();
// Set the reader
Reader(reader);
}
2011-10-11 08:44:27 -05:00
void QtPlayer::Play()
{
// Set mode to playing, and speed to normal
mode = PLAYBACK_PLAY;
Speed(1);
if (reader && !threads_started) {
// Start thread only once
p->startPlayback();
threads_started = true;
}
}
2014-01-25 03:38:38 +08:00
void QtPlayer::Loading()
{
mode = PLAYBACK_LOADING;
}
2014-01-25 03:38:38 +08:00
/// Get the current mode
openshot::PlaybackMode QtPlayer::Mode()
{
return mode;
}
void QtPlayer::Pause()
{
mode = PLAYBACK_PAUSED;
Speed(0);
}
2014-01-25 03:38:38 +08:00
int64_t QtPlayer::Position()
{
return p->video_position;
}
2014-01-25 03:38:38 +08:00
void QtPlayer::Seek(int64_t new_frame)
{
// Check for seek
if (reader && threads_started && new_frame > 0) {
// Notify cache thread that seek has occurred
p->videoCache->Seek(new_frame, true);
// Notify audio thread that seek has occurred
p->audioPlayback->Seek(new_frame);
// Update current position
p->Seek(new_frame);
}
}
2014-01-25 03:38:38 +08:00
void QtPlayer::Stop()
{
// Change mode to stopped
mode = PLAYBACK_STOPPED;
// Notify threads of stopping
if (reader && threads_started) {
p->videoCache->Stop();
p->audioPlayback->Stop();
// Kill all threads
p->stopPlayback();
}
p->video_position = 0;
threads_started = false;
}
// Set the reader object
void QtPlayer::Reader(openshot::ReaderBase *new_reader)
{
// Set new reader. Note: Be sure to close and dispose of the old reader after calling this
reader = new_reader;
p->reader = new_reader;
p->videoCache->Reader(new_reader);
p->audioPlayback->Reader(new_reader);
}
// Get the current reader, such as a FFmpegReader
openshot::ReaderBase* QtPlayer::Reader() {
return reader;
}
// Set the QWidget pointer to display the video on (as a LONG pointer id)
void QtPlayer::SetQWidget(int64_t qwidget_address) {
// Update override QWidget address on the video renderer
p->renderer->OverrideWidget(qwidget_address);
}
// Get the Renderer pointer address (for Python to cast back into a QObject)
int64_t QtPlayer::GetRendererQObject() {
return (int64_t)(VideoRenderer*)p->renderer;
}
// 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;
p->videoCache->setSpeed(new_speed);
if (p->reader->info.has_audio)
p->audioPlayback->setSpeed(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;
}
}