diff --git a/CMakeLists.txt b/CMakeLists.txt index 07cae5d..b9ac5a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS}) set(SOURCES src/main.cpp - src/mpvobject.cpp + src/MpvPlayerBackend.cpp src/filesavedialog.cpp src/fileopendialog.cpp ) diff --git a/KittehPlayer.pro b/KittehPlayer.pro index 45b5cf6..6b6810a 100644 --- a/KittehPlayer.pro +++ b/KittehPlayer.pro @@ -2,7 +2,7 @@ TARGET = KittehPlayer TEMPLATE = app QT += qml quickcontrols2 widgets core-private gui-private -SOURCES += src/main.cpp src/mpvobject.cpp src/filesavedialog.cpp src/fileopendialog.cpp +SOURCES += src/main.cpp src/MpvPlayerBackend.cpp src/filesavedialog.cpp src/fileopendialog.cpp CONFIG += release #CONFIG+=qtquickcompiler @@ -29,7 +29,7 @@ unix { INSTALLS += target -HEADERS += src/mpvobject.h src/filesavedialog.h src/fileopendialog.h +HEADERS += src/MpvPlayerBackend.h src/filesavedialog.h src/fileopendialog.h DISTFILES += KittehPlayer.desktop KittehPlayer.png README.md LICENSE.txt diff --git a/src/mpvobject.cpp b/src/MpvPlayerBackend.cpp similarity index 75% rename from src/mpvobject.cpp rename to src/MpvPlayerBackend.cpp index 9f27b17..1c0fe5d 100644 --- a/src/mpvobject.cpp +++ b/src/MpvPlayerBackend.cpp @@ -2,7 +2,7 @@ #include #include -#include "mpvobject.h" +#include "MpvPlayerBackend.h" #include #include @@ -15,12 +15,12 @@ namespace void wakeup(void *ctx) { - QMetaObject::invokeMethod((MpvObject*)ctx, "on_mpv_events", Qt::QueuedConnection); + QMetaObject::invokeMethod((MpvPlayerBackend*)ctx, "on_mpv_events", Qt::QueuedConnection); } void on_mpv_redraw(void *ctx) { - MpvObject::on_update(ctx); + MpvPlayerBackend::on_update(ctx); } static void *get_proc_address_mpv(void *ctx, const char *name) @@ -38,11 +38,11 @@ static void *get_proc_address_mpv(void *ctx, const char *name) class MpvRenderer : public QQuickFramebufferObject::Renderer { - MpvObject *obj; + MpvPlayerBackend *obj; public: - MpvRenderer(MpvObject *new_obj) + MpvRenderer(MpvPlayerBackend *new_obj) : obj{new_obj} { } @@ -99,7 +99,7 @@ public: } }; -MpvObject::MpvObject(QQuickItem * parent) +MpvPlayerBackend::MpvPlayerBackend(QQuickItem * parent) : QQuickFramebufferObject(parent), mpv{mpv_create()}, mpv_gl(nullptr) { @@ -140,12 +140,12 @@ MpvObject::MpvObject(QQuickItem * parent) if (mpv_initialize(mpv) < 0) throw std::runtime_error("could not initialize mpv context"); - connect(this, &MpvObject::onUpdate, this, &MpvObject::doUpdate, + connect(this, &MpvPlayerBackend::onUpdate, this, &MpvPlayerBackend::doUpdate, Qt::QueuedConnection); } -MpvObject::~MpvObject() +MpvPlayerBackend::~MpvPlayerBackend() { if (mpv_gl) { @@ -155,47 +155,101 @@ MpvObject::~MpvObject() mpv_terminate_destroy(mpv); } -void MpvObject::on_update(void *ctx) +void MpvPlayerBackend::on_update(void *ctx) { - MpvObject *self = (MpvObject *)ctx; + MpvPlayerBackend *self = (MpvPlayerBackend *)ctx; emit self->onUpdate(); } // connected to onUpdate(); signal makes sure it runs on the GUI thread -void MpvObject::doUpdate() +void MpvPlayerBackend::doUpdate() { update(); } -QVariant MpvObject::getProperty(const QString &name) const +QVariant MpvPlayerBackend::getProperty(const QString &name) const { return mpv::qt::get_property_variant(mpv, name); } -void MpvObject::command(const QVariant& params) +void MpvPlayerBackend::command(const QVariant& params) { mpv::qt::command_variant(mpv, params); } -void MpvObject::setProperty(const QString& name, const QVariant& value) +void MpvPlayerBackend::setProperty(const QString& name, const QVariant& value) { mpv::qt::set_property_variant(mpv, name, value); } -void MpvObject::setOption(const QString& name, const QVariant& value) +void MpvPlayerBackend::setOption(const QString& name, const QVariant& value) { mpv::qt::set_option_variant(mpv, name, value); } -void MpvObject::launchAboutQt() +void MpvPlayerBackend::launchAboutQt() { QApplication *qapp = qobject_cast(QCoreApplication::instance()); qapp->aboutQt(); } -void MpvObject::on_mpv_events() +void MpvPlayerBackend::togglePlayPause() +{ + mpv::qt::command_variant(mpv, QVariantList() << "cycle" << "pause"); +} + +void MpvPlayerBackend::toggleMute() +{ + mpv::qt::command_variant(mpv, QVariantList() << "cycle" << "mute"); +} + +void MpvPlayerBackend::nextAudioTrack() +{ + mpv::qt::command_variant(mpv, QVariantList() << "cycle" << "audio"); +} +void MpvPlayerBackend::nextSubtitleTrack() +{ + mpv::qt::command_variant(mpv, QVariantList() << "cycle" << "sub"); +} + +void MpvPlayerBackend::nextVideoTrack() +{ + mpv::qt::command_variant(mpv, QVariantList() << "cycle" << "video"); +} + +void MpvPlayerBackend::prevPlaylistItem() +{ + mpv::qt::command_variant(mpv, QVariantList() << "playlist-prev"); +} + +void MpvPlayerBackend::nextPlaylistItem() +{ + mpv::qt::command_variant(mpv, QVariantList() << "playlist-next" << "force"); +} + +void MpvPlayerBackend::loadFile(const QVariant &filename) +{ + mpv::qt::command_variant(mpv, QVariantList() << "loadfile" << filename); +} + +void MpvPlayerBackend::setVolume(const QVariant &volume) +{ + mpv::qt::command_variant(mpv, QVariantList() << "set" << "volume" << volume); +} + +void MpvPlayerBackend::addVolume(const QVariant &volume) +{ + mpv::qt::command_variant(mpv, QVariantList() << "add" << "volume" << volume); +} + +void MpvPlayerBackend::seek(const QVariant &seekTime) +{ + mpv::qt::command_variant(mpv, QVariantList() << "seek" << seekTime); +} + +void MpvPlayerBackend::on_mpv_events() { while (mpv) { mpv_event *event = mpv_wait_event(mpv, 0); @@ -208,7 +262,7 @@ void MpvObject::on_mpv_events() } -void MpvObject::handle_mpv_event(mpv_event *event) +void MpvPlayerBackend::handle_mpv_event(mpv_event *event) { switch (event->event_id) { case MPV_EVENT_PROPERTY_CHANGE: { @@ -268,10 +322,10 @@ void MpvObject::handle_mpv_event(mpv_event *event) } } -QQuickFramebufferObject::Renderer *MpvObject::createRenderer() const +QQuickFramebufferObject::Renderer *MpvPlayerBackend::createRenderer() const { window()->setPersistentOpenGLContext(true); window()->setPersistentSceneGraph(true); - return new MpvRenderer(const_cast(this)); + return new MpvRenderer(const_cast(this)); } diff --git a/src/mpvobject.h b/src/MpvPlayerBackend.h similarity index 60% rename from src/mpvobject.h rename to src/MpvPlayerBackend.h index b20bea4..dc1f874 100644 --- a/src/mpvobject.h +++ b/src/MpvPlayerBackend.h @@ -1,5 +1,5 @@ -#ifndef MPVOBJECT_H -#define MPVOBJECT_H +#ifndef MpvPlayerBackend_H +#define MpvPlayerBackend_H #include #include @@ -13,7 +13,7 @@ class MpvRenderer; -class MpvObject : public QQuickFramebufferObject +class MpvPlayerBackend : public QQuickFramebufferObject { Q_OBJECT mpv_handle *mpv; @@ -24,13 +24,24 @@ class MpvObject : public QQuickFramebufferObject public: static void on_update(void *ctx); - MpvObject(QQuickItem * parent = 0); - virtual ~MpvObject(); + MpvPlayerBackend(QQuickItem * parent = 0); + virtual ~MpvPlayerBackend(); virtual Renderer *createRenderer() const; public slots: void launchAboutQt(); + void togglePlayPause(); + void toggleMute(); + void nextAudioTrack(); + void nextVideoTrack(); + void nextSubtitleTrack(); + void prevPlaylistItem(); + void nextPlaylistItem(); + void setVolume(const QVariant& volume); + void addVolume(const QVariant& volume); + void loadFile(const QVariant& filename); + void seek(const QVariant& seekTime); void command(const QVariant& params); void setProperty(const QString& name, const QVariant& value); void setOption(const QString& name, const QVariant& value); diff --git a/src/main.cpp b/src/main.cpp index 9ef9cbb..9fc34ca 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,7 +10,7 @@ #include #include "fileopendialog.h" #include "filesavedialog.h" -#include "mpvobject.h" +#include "MpvPlayerBackend.h" #ifdef WIN32 #include "setenv_mingw.hpp" @@ -48,17 +48,12 @@ setenv("QT_QPA_PLATFORMTHEME", "gtk3", 0); setenv("PATH", newpath.toUtf8().constData(), 1); QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); - qmlRegisterType("player", 1, 0, "MpvObject"); + qmlRegisterType("player", 1, 0, "PlayerBackend"); qmlRegisterType("player", 1, 0, "FileOpenDialog"); qmlRegisterType("player", 1, 0, "FileSaveDialog"); std::setlocale(LC_NUMERIC, "C"); -/*QQuickView *view = new QQuickView(); -view->setResizeMode(QQuickView::SizeRootObjectToView); -view->setSource(QUrl("qrc:///player/main.qml")); -view->show();*/ - QQmlApplicationEngine engine; #ifdef QRC_SOURCE_PATH RuntimeQML *rt = new RuntimeQML(&engine, QRC_SOURCE_PATH"/qml.qrc"); diff --git a/src/qml/main.qml b/src/qml/main.qml index a34d1d4..4000d44 100644 --- a/src/qml/main.qml +++ b/src/qml/main.qml @@ -77,7 +77,7 @@ ApplicationWindow { } } - MpvObject { + PlayerBackend { id: player anchors.fill: parent width: parent.width @@ -157,7 +157,7 @@ ApplicationWindow { } } } else { - player.command(["loadfile", argument]) + player.loadFile(argument) } } } @@ -307,7 +307,7 @@ ApplicationWindow { title: translate.getTranslation("URL_FILE_PATH", i18n.language) standardButtons: StandardButton.Cancel | StandardButton.Open onAccepted: { - player.command(["loadfile", pathText.text]) + player.loadFile("loadfile") pathText.text = "" } TextField { @@ -348,7 +348,7 @@ ApplicationWindow { cursorShape: controlsBar.visible ? Qt.ArrowCursor : Qt.BlankCursor onClicked: { if (appearance.clickToPause) { - player.command(["cycle", "pause"]) + player.togglePlayPause() } } Timer { @@ -515,35 +515,35 @@ ApplicationWindow { Action { text: translate.getTranslation("PLAY_PAUSE", i18n.language) onTriggered: { - player.command(["cycle", "pause"]) + player.togglePlayPause() } shortcut: String(keybinds.playPause) } Action { text: translate.getTranslation("REWIND_10S", i18n.language) onTriggered: { - player.command(["seek", "-10"]) + player.seek("-10") } shortcut: keybinds.rewind10 } Action { text: translate.getTranslation("FORWARD_10S", i18n.language) onTriggered: { - player.command(["seek", "10"]) + player.seek("10") } shortcut: keybinds.forward10 } Action { text: translate.getTranslation("FORWARD_5S", i18n.language) onTriggered: { - player.command(["seek", "-5"]) + player.seek("-5") } shortcut: keybinds.rewind5 } Action { text: translate.getTranslation("FORWARD_5S", i18n.language) onTriggered: { - player.command(["seek", "5"]) + player.seek("5") } shortcut: keybinds.forward5 } @@ -613,7 +613,7 @@ ApplicationWindow { text: translate.getTranslation("CYCLE_AUDIO_TRACK", i18n.language) onTriggered: { - player.command(["cycle", "audio"]) + player.nextAudioTrack() } shortcut: keybinds.cycleAudio } @@ -621,7 +621,7 @@ ApplicationWindow { text: translate.getTranslation("INCREASE_VOLUME", i18n.language) onTriggered: { - player.command(["add", "volume", "2"]) + player.addVolume("2") } shortcut: keybinds.increaseVolume } @@ -629,14 +629,14 @@ ApplicationWindow { text: translate.getTranslation("DECREASE_VOLUME", i18n.language) onTriggered: { - player.command(["add", "volume", "-2"]) + player.addVolume("-2") } shortcut: keybinds.decreaseVolume } Action { text: translate.getTranslation("MUTE_VOLUME", i18n.language) onTriggered: { - player.command(["cycle", "mute"]) + player.toggleMute() } shortcut: keybinds.mute } @@ -658,7 +658,7 @@ ApplicationWindow { Action { text: translate.getTranslation("CYCLE_VIDEO", i18n.language) onTriggered: { - player.command(["cycle", "video"]) + player.nextVideoTrack() } shortcut: keybinds.cycleVideo } @@ -680,18 +680,10 @@ ApplicationWindow { text: translate.getTranslation("CYCLE_SUB_TRACK", i18n.language) onTriggered: { - player.command(["cycle", "sub"]) + player.nextSubtitleTrack() } shortcut: keybinds.cycleSub } - Action { - text: translate.getTranslation("CYCLE_SUB_TRACK_BACKWARDS", - i18n.language) - onTriggered: { - player.command(["cycle", "sub", "down"]) - } - shortcut: keybinds.cycleSubBackwards - } Action { text: translate.getTranslation("TOGGLE_MPV_SUBS", i18n.language) @@ -1147,7 +1139,7 @@ ApplicationWindow { visible: false width: 0 onClicked: { - player.command(["playlist-prev"]) + player.prevPlaylistItem() } background: Rectangle { color: "transparent" @@ -1164,7 +1156,7 @@ ApplicationWindow { anchors.bottom: parent.bottom anchors.left: playlistPrevButton.right onClicked: { - player.command(["cycle", "pause"]) + player.togglePlayPause() } background: Rectangle { color: "transparent" @@ -1181,7 +1173,7 @@ ApplicationWindow { anchors.bottom: parent.bottom anchors.left: playPauseButton.right onClicked: { - player.command(["playlist-next", "force"]) + player.prevPlaylistItem() } background: Rectangle { color: "transparent" @@ -1198,7 +1190,7 @@ ApplicationWindow { anchors.bottom: parent.bottom anchors.left: playlistNextButton.right onClicked: { - player.command(["cycle", "mute"]) + player.toggleMute() } background: Rectangle { color: "transparent" @@ -1223,8 +1215,8 @@ ApplicationWindow { anchors.top: parent.top anchors.bottom: parent.bottom onMoved: { - player.command(["set", "volume", Math.round( - volumeBar.value).toString()]) + player.setVolume(Math.round( + volumeBar.value).toString()) } handle: Rectangle { diff --git a/src/qml/translations.js b/src/qml/translations.js index 7d2d226..9159703 100644 --- a/src/qml/translations.js +++ b/src/qml/translations.js @@ -30,7 +30,6 @@ var translations = { CYCLE_VIDEO: "Cycle video", SUBTITLES: "Subtitles", CYCLE_SUB_TRACK: "Cycle Subtitle Track", - CYCLE_SUB_TRACK_BACKWARDS: "Cycle Subtitle Track Backwards", CYCLE_AUDIO_TRACK: "Cycle Audio Track", TOGGLE_MPV_SUBS: "Toggle MPV Subtitles", VIEW: "View", @@ -73,7 +72,6 @@ var translations = { CYCLE_VIDEO: "Siguiente vídeo", SUBTITLES: "Subtítulos", CYCLE_SUB_TRACK: "Siguientes subtítulos", - CYCLE_SUB_TRACK_BACKWARDS: "Subtítulos previos", CYCLE_AUDIO_TRACK: "Siguiente pista de audio", TOGGLE_MPV_SUBS: "Activar subtítulos MPV", VIEW: "Ver", @@ -116,7 +114,6 @@ var translations = { CYCLE_VIDEO: "Wechsle Video", SUBTITLES: "Untertitel", CYCLE_SUB_TRACK: "Wechsle Untertitel Spur", - CYCLE_SUB_TRACK_BACKWARDS: "Wechsle Untertitel Spur Rückwärts", CYCLE_AUDIO_TRACK: "Cycle Audio Track", TOGGLE_MPV_SUBS: "Schalte MPV Untertitel An/Aus", VIEW: "Ansicht", @@ -159,7 +156,6 @@ var translations = { CYCLE_VIDEO: "Changer de vidéo", SUBTITLES: "Sous-titres", CYCLE_SUB_TRACK: "Changer de piste de sous-titres", - CYCLE_SUB_TRACK_BACKWARDS: "Changer de piste de sous-titres pour la précédente", CYCLE_AUDIO_TRACK: "Basculer de piste audio", TOGGLE_MPV_SUBS: "Basculer les sous-titres MPV", VIEW: "Voir", @@ -202,7 +198,6 @@ var translations = { CYCLE_VIDEO: "Ripeti video", SUBTITLES: "Sottotitoli", CYCLE_SUB_TRACK: "Ripeti traccia sottotitoli", - CYCLE_SUB_TRACK_BACKWARDS: "Ripeti traccia sottotili al contrario", CYCLE_AUDIO_TRACK: "Ripeti traccia audio", TOGGLE_MPV_SUBS: "Attiva MPV Sottotitoli", VIEW: "Vedi", @@ -245,7 +240,6 @@ var translations = { CYCLE_VIDEO: "Зациклить воспроизведение видео", SUBTITLES: "Субтитры", CYCLE_SUB_TRACK: "Зациклить дорожку субтитров", - CYCLE_SUB_TRACK_BACKWARDS: "Зациклить дорожку субтитров в обратную сторону", CYCLE_AUDIO_TRACK: "Зациклить аудиодорожку", TOGGLE_MPV_SUBS: "Переключить MPV-субтитры", VIEW: "Вид", @@ -288,7 +282,6 @@ var translations = { CYCLE_VIDEO: "Sirkuler Gjennom Videospor", SUBTITLES: "Undertekster", CYCLE_SUB_TRACK: "Sirkuler Gjennom Undertekster", - CYCLE_SUB_TRACK_BACKWARDS: "Sirkuler Gjennom Undertekster (Baklengs)", CYCLE_AUDIO_TRACK: "Sirkuler Gjennom Lydspor", TOGGLE_MPV_SUBS: "Skru Av/På MPV Undertekster", VIEW: "Vis",