Q_LOGGING_CATEGORY(mpvBackend, "MPV")
Q_LOGGING_CATEGORY(mpvLog, "MPV Log")
-BackendMpv::BackendMpv() {
+BackendMpv::BackendMpv(QObject *parent) : QObject{parent} {
#ifdef Q_OS_UNIX
setlocale(LC_NUMERIC, "C");
#endif
}
-BackendMpv::~BackendMpv() {}
+BackendInstance *BackendMpv::createInstance(PlayerPluginInterface *player) {
+ return new MpvInstance{player};
+}
-bool BackendMpv::initialize(PlayerPluginInterface *playerInterface) {
+MpvInstance::MpvInstance(PlayerPluginInterface *playerInterface,
+ QObject *parent)
+ : QObject{parent}, m_player{playerInterface} {
qCDebug(mpvBackend) << "Initialize";
- m_player = playerInterface;
m_handle = mpv_create();
+ Q_CHECK_PTR(m_handle);
+
qCDebug(mpvBackend()).nospace()
<< "Client API version: " << (mpv_client_api_version() >> 16) << '.'
<< (mpv_client_api_version() & ~(~0u << 16));
- // mpv_set_option(handle, "wid", MPV_FORMAT_INT64, &wid);
mpv_set_option_string(m_handle, "vo", "opengl-cb");
int error = mpv_initialize(m_handle);
if (error) {
qCDebug(mpvBackend) << "Error initializing mpv" << mpv_error_string(error);
- return false;
+ return;
}
mpv_set_wakeup_callback(m_handle, mpvWakeupCb, this);
qCDebug(mpvBackend) << "request log messages"
<< mpv_request_log_messages(m_handle, "info");
- return !error;
}
-void BackendMpv::deinitialize() {
+MpvInstance::~MpvInstance() {
qCDebug(mpvBackend) << "Deinitialize";
mpv_terminate_destroy(m_handle);
}
-VideoRendererBase *BackendMpv::createRenderer(VideoUpdateInterface *vui) {
+VideoRendererBase *MpvInstance::createRenderer(VideoUpdateInterface *vui) {
qCDebug(mpvBackend, "BackendMpv::createRenderer");
return new VideoRendererMpv(m_handle, vui);
}
-bool BackendMpv::open(const QUrl &source) {
+bool MpvInstance::open(const QUrl &source) {
qCDebug(mpvBackend) << "Opening " << source;
const QByteArray tmp = source.toLocalFile().toUtf8();
- const char *args[] = {"loadfile", tmp.constData(), NULL};
+ const char *args[] = {"loadfile", tmp.constData(), nullptr};
mpv_command_async(m_handle, 1, args);
pause();
return true;
}
-void BackendMpv::play() {
+void MpvInstance::play() {
qCDebug(mpvBackend) << "Play";
int f = 0;
mpv_set_property(m_handle, "pause", MPV_FORMAT_FLAG, &f);
}
-void BackendMpv::pause() {
+void MpvInstance::pause() {
qCDebug(mpvBackend) << "Pause";
int f = 1;
mpv_set_property(m_handle, "pause", MPV_FORMAT_FLAG, &f);
}
-void BackendMpv::stop() { qCDebug(mpvBackend) << "Stop"; }
+void MpvInstance::stop() { qCDebug(mpvBackend) << "Stop"; }
-void BackendMpv::seek(TimeStamp pos) {
+void MpvInstance::seek(TimeStamp pos) {
mpv_set_property(m_handle, "playback-time", MPV_FORMAT_DOUBLE, &pos);
}
-void BackendMpv::setVolume(BackendPluginBase::Volume volume) {
+void MpvInstance::setVolume(Volume volume) {
double percantageVolume = volume * 100;
int error = mpv_set_property(m_handle, "ao-volume", MPV_FORMAT_DOUBLE,
&percantageVolume);
return MpvProperty<TYPE>::read(property);
}
-void BackendMpv::processMpvEvents() {
+void MpvInstance::processMpvEvents() {
struct mpv_event *event = nullptr;
do {
event = mpv_wait_event(m_handle, 0);
} while (event->event_id != MPV_EVENT_NONE);
}
-void BackendMpv::mpvWakeupCb(void *obj) {
+void MpvInstance::mpvWakeupCb(void *obj) {
auto self = static_cast<BackendMpv *>(obj);
QMetaObject::invokeMethod(self, "processMpvEvents", Qt::QueuedConnection);
}
Q_INTERFACES(BackendPluginBase)
public:
- BackendMpv();
- virtual ~BackendMpv();
- bool initialize(PlayerPluginInterface *) override;
- void deinitialize() override;
+ explicit BackendMpv(QObject *parent = nullptr);
+
+ BackendInstance *createInstance(PlayerPluginInterface *) override;
+};
+
+class BACKEND_MPVSHARED_EXPORT MpvInstance : public QObject,
+ public BackendInstance {
+ Q_OBJECT
+public:
+ MpvInstance(PlayerPluginInterface *, QObject *parent = nullptr);
+ virtual ~MpvInstance() override;
VideoRendererBase *createRenderer(VideoUpdateInterface *) override;
void setVolume(Volume) override;
private:
- mpv_handle *m_handle = nullptr;
PlayerPluginInterface *m_player = nullptr;
+ mpv_handle *m_handle = nullptr;
Volume m_volumeToSet = -1;
bool m_loadedFile = false;
#include "backendnull.h"
-#include <QTimer>
#include <QDebug>
+#include <QTimer>
-BackendNull::BackendNull()
-{
-}
-
-BackendNull::~BackendNull()
-{
-}
-
-bool BackendNull::initialize(PlayerPluginInterface *)
-{
- qDebug() << "Initialize";
- m_timer = new QTimer{this};
- m_timer->setInterval(1000);
- return true;
-}
-
-void BackendNull::deinitialize()
-{
- qDebug() << "Deinitialize";
- delete m_timer;
- m_timer = nullptr;
+BackendInstance *BackendNull::createInstance(PlayerPluginInterface *) {
+ return new NullInstance;
}
-bool BackendNull::open(const QUrl &source)
-{
- qDebug() << "Opening " << source;
- return true;
+NullInstance::NullInstance() {
+ qDebug() << "Initialize";
+ m_timer = new QTimer{this};
+ m_timer->setInterval(1000);
}
-void BackendNull::play()
-{
- qDebug() << "Play";
+bool NullInstance::open(const QUrl &source) {
+ qDebug() << "Opening " << source;
+ return true;
}
-void BackendNull::pause()
-{
- qDebug() << "Pause";
-}
+void NullInstance::play() { qDebug() << "Play"; }
-void BackendNull::stop()
-{
- qDebug() << "Stop";
-}
+void NullInstance::pause() { qDebug() << "Pause"; }
+void NullInstance::stop() { qDebug() << "Stop"; }
-VideoRendererBase *BackendNull::createRenderer(VideoUpdateInterface *)
-{
- return nullptr;
+VideoRendererBase *NullInstance::createRenderer(VideoUpdateInterface *) {
+ return nullptr;
}
+void NullInstance::seek(TimeStamp) {}
-void BackendNull::seek(TimeStamp)
-{
-}
-
-void BackendNull::setVolume(BackendPluginBase::Volume)
-{
-}
+void NullInstance::setVolume(Volume) {}
class QTimer;
-class BACKEND_NULLSHARED_EXPORT BackendNull : public QObject, public BackendPluginBase
-{
- Q_OBJECT
- Q_PLUGIN_METADATA(IID ANIPLAYER_BACKEND_DPLUGIN_INTERFACE_IID FILE "backend_null.json")
- Q_INTERFACES(BackendPluginBase)
+class BACKEND_NULLSHARED_EXPORT BackendNull : public QObject,
+ public BackendPluginBase {
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID ANIPLAYER_BACKEND_DPLUGIN_INTERFACE_IID FILE
+ "backend_null.json")
+ Q_INTERFACES(BackendPluginBase)
public:
- BackendNull();
- virtual ~BackendNull();
- bool initialize(PlayerPluginInterface *) override;
- void deinitialize() override;
+ using QObject::QObject;
+ virtual BackendInstance *createInstance(PlayerPluginInterface *) override;
+};
- bool open(const QUrl &source) override;
- void play() override;
- void pause() override;
- void stop() override;
+class BACKEND_NULLSHARED_EXPORT NullInstance : public QObject,
+ public BackendInstance {
+ Q_OBJECT
+public:
+ NullInstance();
+ bool open(const QUrl &source) override;
+ void play() override;
+ void pause() override;
+ void stop() override;
- void seek(TimeStamp) override;
+ void seek(TimeStamp) override;
- void setVolume(Volume) override;
+ void setVolume(Volume) override;
- VideoRendererBase *createRenderer(VideoUpdateInterface *) override;
+ VideoRendererBase *createRenderer(VideoUpdateInterface *) override;
private:
- QTimer *m_timer = nullptr;
-
+ QTimer *m_timer = nullptr;
};
#endif // BACKENDNULL_H
class QUrl;
-class BackendPluginBase {
+class BackendInstance {
public:
+ // In seconds
using TimeStamp = double;
// Volume valid range is 0.0-1.0
using Volume = double;
-
- virtual ~BackendPluginBase() = default;
-
- virtual bool initialize(PlayerPluginInterface *) = 0;
- virtual void deinitialize() = 0;
+ virtual ~BackendInstance() = default;
virtual VideoRendererBase *createRenderer(VideoUpdateInterface *) = 0;
virtual void setVolume(Volume) = 0;
};
+class BackendPluginBase {
+public:
+ virtual ~BackendPluginBase() = default;
+
+ virtual BackendInstance *createInstance(PlayerPluginInterface *) = 0;
+};
+
#define ANIPLAYER_BACKEND_DPLUGIN_INTERFACE_IID \
"org.aptx.aniplayer.BackendPluginInterface"
player = new Player{this};
Q_CHECK_PTR(player);
+ qCDebug(imCategory, "Player Created");
if (!positionalArgs.empty())
player->setNextSource(QUrl::fromUserInput(positionalArgs[0]));
- qCDebug(imCategory, "Player Created");
TimeFormatter timeFormatter;
engine.rootContext()->setContextProperty("player", player);
engine.rootContext()->setContextProperty("timeFormatter", &timeFormatter);
"Start playback specific position",
"position in seconds", "0"};
QCommandLineParser parser;
- Player *player;
+ Player *player = nullptr;
};
#endif // INSTANCEMANAGER_H
Q_LOGGING_CATEGORY(playerCategory, "Player")
-Player::Player(QObject *parent) : QObject(parent) { loadBackend(); }
+Player::Player(QObject *parent) : QObject(parent) {
+ qCDebug(playerCategory) << "Creating player" << this;
+ loadBackend();
+}
+
+Player::~Player()
+{
+ qCDebug(playerCategory) << "Destroying player" << this;
+}
-BackendPluginBase *Player::backend() const { return m_backend; }
+BackendInstance *Player::backend() const { return m_backend; }
bool Player::hasRenderer() const { return m_renderer != nullptr; }
}
void Player::backendReadyToPlay() {
- m_backendReady = true;
+ m_backendInstanceReady = true;
if (canLoadVideoNow())
loadNextFile();
}
#ifdef Q_OS_WIN
QStringList pluginPaths{"backendplugins"};
#else
- QStringList pluginPaths{"/usr/lib/aniplayer/backendplugins",
- "backendplugins"};
+ QStringList pluginPaths{"backendplugins",
+ "/usr/lib/aniplayer/backendplugins"};
#endif
m_pluginManager.setPluginDirectories(pluginPaths);
m_pluginManager.setPluginPrefix("backend");
m_pluginManager.loadDefaultPlugin();
- m_backend = m_pluginManager.instance<BackendPluginBase>();
- if (!m_backend)
+ m_plugin = m_pluginManager.instance<BackendPluginBase>();
+ if (!m_plugin)
throw std::runtime_error{std::string("Failed to load backend: ") +
qPrintable(m_pluginManager.errorString())};
- m_backend->initialize(this);
+ m_backend = m_plugin->createInstance(this);
+ Q_CHECK_PTR(m_backend);
qCDebug(playerCategory) << "Loaded backend" << m_backend;
}
bool Player::canLoadVideoNow() const {
- return m_backendReady && m_renderer && m_rendererReady;
+ return m_backendInstanceReady && m_renderer && m_rendererReady;
}
void Player::loadNextFile() {
static const constexpr Volume MAX_VOLUME = Volume{1.0};
explicit Player(QObject *parent = 0);
- // ~Player() /*override*/;
+ ~Player() override;
enum class PlayState {
Stopped = static_cast<int>(PlayerPluginInterface::PlayState::Stopped),
};
Q_ENUM(PlayState)
- BackendPluginBase *backend() const;
+ BackendInstance *backend() const;
bool hasRenderer() const;
QUrl currentSource() const;
void loadNextFile();
PluginManager m_pluginManager;
- BackendPluginBase *m_backend = nullptr;
+ BackendPluginBase *m_plugin = nullptr;
+ BackendInstance *m_backend = nullptr;
QUrl m_currentSource;
PlayState m_state = PlayState::Stopped;
Volume m_volume = MAX_VOLUME;
QUrl m_nextSource;
VideoUpdateInterface *m_renderer = nullptr;
bool m_muted = false;
- bool m_backendReady = false;
+ bool m_backendInstanceReady = false;
bool m_rendererReady = false;
};
#include "videoelement.h"
#include "player.h"
+#include <QLoggingCategory>
+
+Q_LOGGING_CATEGORY(videoElementCategory, "VideoElement")
+
VideoElement::VideoElement() : m_source{nullptr} {
connect(this, SIGNAL(updateRequested()), this, SLOT(update()),
Qt::QueuedConnection);
VideoElement::~VideoElement() {}
VideoElement::Renderer *VideoElement::createRenderer() const {
- qDebug("creating VideoElement::Renderer");
+ qDebug(videoElementCategory, "creating VideoElement::Renderer");
return new Renderer;
}
m_source = source;
emit sourceChanged(source);
- qDebug() << "source has been set!";
+ qDebug(videoElementCategory) << "source has been set!" << m_source;
rendererUpdateRequired = true;
return;
}
m_renderer = nullptr;
return;
}
- qDebug("creating backend renderer");
+ qDebug(videoElementCategory, "creating backend renderer");
m_renderer = ve->source()->backend()->createRenderer(ve);
// Call via base to ensure a public method.
PlayerRendererInterface *src = ve->m_source;
src->rendererReady();
- qDebug("backend renderer created");
+ qDebug(videoElementCategory, "backend renderer created");
}
void VideoElement::videoUpdated() { emit updateRequested(); }
void synchronize(QQuickFramebufferObject *object) override;
private:
- VideoRendererBase *m_renderer;
+ VideoRendererBase *m_renderer = nullptr;
};
- Player *m_source;
+ Player *m_source = nullptr;
public:
VideoElement();