From bf5ab9de8a1466d69eb69235c0233ee4313a0ad3 Mon Sep 17 00:00:00 2001
From: Kubat <mael.martin31@gmail.com>
Date: Fri, 19 Nov 2021 11:43:00 +0100
Subject: [PATCH] MPV: Checkout a working implementation of the MPV viewer

---
 src/UI/DocumentViews/MpvContainer.cc | 38 +++++-----------------------
 src/UI/DocumentViews/MpvControls.cc  |  4 +++
 src/UI/DocumentViews/MpvControls.hh  |  1 +
 3 files changed, 11 insertions(+), 32 deletions(-)

diff --git a/src/UI/DocumentViews/MpvContainer.cc b/src/UI/DocumentViews/MpvContainer.cc
index 1f123238..fb094d4e 100644
--- a/src/UI/DocumentViews/MpvContainer.cc
+++ b/src/UI/DocumentViews/MpvContainer.cc
@@ -3,16 +3,6 @@
 using namespace Vivy;
 using namespace std::string_literals;
 
-#define RETURN_IF_NULLPTR(ptr) \
-    if ((ptr) == nullptr)      \
-    return
-
-#define TRY_CREATE_MPV(ptr)                                                         \
-    if ((ptr) == nullptr) {                                                         \
-        logInfo() << "Asked to play MPV but context not created, try to create it"; \
-        reCreateMpvContext();                                                       \
-    }
-
 void
 MpvContainer::mpvEventWakeUpCB(void *user) noexcept
 {
@@ -22,8 +12,11 @@ MpvContainer::mpvEventWakeUpCB(void *user) noexcept
 
 MpvContainer::MpvContainer(QWidget *parent)
     : QWidget(parent)
-    , mpv(nullptr)
+    , mpv(mpv_create())
 {
+    if (mpv == nullptr)
+        throw std::runtime_error("Failed to create the MPV context");
+
     setAttribute(Qt::WA_DontCreateNativeAncestors);
     setAttribute(Qt::WA_NativeWindow);
 
@@ -69,7 +62,6 @@ MpvContainer::reCreateMpvContext()
         throw std::runtime_error("Failed to create the MPV context");
     initializeMpv();
     loadFile(previousLoadedFile);
-    logInfo() << "Reloaded the MPV component";
 }
 
 void
@@ -99,9 +91,9 @@ MpvContainer::closeMpv() noexcept
         asyncCommand(AsyncCmdType::None, { "quit", nullptr });
         mpv_wait_async_requests(mpv);
         mpv_destroy(mpv);
-        mpv = nullptr; // Stop all other callbacks here
+        mpv                     = nullptr; // Stop all other callbacks here
+        isMpvAlreadyInitialized = false;   // De-init
     }
-    isMpvAlreadyInitialized = false; // De-init
 }
 
 MpvContainer::~MpvContainer() noexcept { closeMpv(); }
@@ -197,9 +189,6 @@ MpvContainer::handleMpvEvent(const mpv_event *const event) noexcept
 int
 MpvContainer::getAssSid() const noexcept
 {
-    // TODO: Do something about that!
-    RETURN_IF_NULLPTR(mpv) 0;
-
     bool conversionOk  = false;
     const char *result = mpv_get_property_string(mpv, "sid");
     const int ret      = QString::fromUtf8(result).toInt(&conversionOk);
@@ -256,8 +245,6 @@ MpvContainer::onMpvEvent() noexcept
 void
 MpvContainer::loadFile(const QString &filename) noexcept
 {
-    RETURN_IF_NULLPTR(mpv);
-
     if (filename.size() == 0)
         return;
 
@@ -271,8 +258,6 @@ MpvContainer::loadFile(const QString &filename) noexcept
 void
 MpvContainer::loadAssFile(const QString &ass) noexcept
 {
-    RETURN_IF_NULLPTR(mpv);
-
     if (ass.isEmpty())
         return;
 
@@ -283,14 +268,12 @@ MpvContainer::loadAssFile(const QString &ass) noexcept
 void
 MpvContainer::reloadAssFile() noexcept
 {
-    RETURN_IF_NULLPTR(mpv);
     asyncCommand(AsyncCmdType::ReloadAss, { "sub-reload", nullptr });
 }
 
 void
 MpvContainer::printMpvError(int rc) const noexcept
 {
-    RETURN_IF_NULLPTR(mpv);
     if (rc == MPV_ERROR_SUCCESS)
         return;
 
@@ -300,8 +283,6 @@ MpvContainer::printMpvError(int rc) const noexcept
 void
 MpvContainer::mpvPlay() noexcept
 {
-    TRY_CREATE_MPV(mpv);
-    RETURN_IF_NULLPTR(mpv);
     if (isPlaybackPaused)
         mpvTogglePlayback();
 }
@@ -309,7 +290,6 @@ MpvContainer::mpvPlay() noexcept
 void
 MpvContainer::mpvPause() noexcept
 {
-    RETURN_IF_NULLPTR(mpv);
     if (!isPlaybackPaused)
         mpvTogglePlayback();
 }
@@ -317,8 +297,6 @@ MpvContainer::mpvPause() noexcept
 void
 MpvContainer::mpvTogglePlayback() noexcept
 {
-    TRY_CREATE_MPV(mpv);
-    RETURN_IF_NULLPTR(mpv);
     logDebug() << "MPV: Toggling the playback";
     asyncCommand(AsyncCmdType::TogglePlayback, { "cycle", "pause", "up", nullptr });
 }
@@ -327,8 +305,6 @@ void
 MpvContainer::asyncCommand(const AsyncCmdType cmd,
                            std::initializer_list<const char *> args) noexcept
 {
-    RETURN_IF_NULLPTR(mpv);
-
     // NOTE: const_cast here, we have faith in MPV to not change the value of
     // the temporary pointers here. Should be OK anyway because the `args` init
     // list is a temporary and should be discarded afer the method call.
@@ -338,14 +314,12 @@ MpvContainer::asyncCommand(const AsyncCmdType cmd,
 void
 MpvContainer::unloadAssFile() noexcept
 {
-    RETURN_IF_NULLPTR(mpv);
     asyncCommand(AsyncCmdType::UnloadAss, { "sub-remove", nullptr });
 }
 
 void
 MpvContainer::seekInFile(const chrono::seconds time) noexcept
 {
-    RETURN_IF_NULLPTR(mpv);
     QByteArray seconds = QString::number(time.count()).toUtf8();
     asyncCommand(AsyncCmdType::SeekTime, { "seek", seconds.data(), "absolute", nullptr });
 }
diff --git a/src/UI/DocumentViews/MpvControls.cc b/src/UI/DocumentViews/MpvControls.cc
index 453c87c5..a9d63a8f 100644
--- a/src/UI/DocumentViews/MpvControls.cc
+++ b/src/UI/DocumentViews/MpvControls.cc
@@ -9,6 +9,8 @@ MpvControls::MpvControls(MpvContainer *passedContainer, QWidget *parent) noexcep
 {
     auto *progressBar          = new QSlider(this);
     auto *togglePlaybackButton = new QPushButton(playIcon, "", this); // Be default MPV is paused
+    auto *reCreateMpvButton    = new QPushButton(
+        reCreateMpvIcon, "", this); // Recreate the MPV context if something went wrong
 
     progressBar->setTracking(false);
     progressBar->setOrientation(Qt::Horizontal);
@@ -54,6 +56,7 @@ MpvControls::MpvControls(MpvContainer *passedContainer, QWidget *parent) noexcep
     });
 
     connect(togglePlaybackButton, &QAbstractButton::clicked, mpv, &MpvContainer::mpvTogglePlayback);
+    connect(reCreateMpvButton, &QAbstractButton::clicked, mpv, &MpvContainer::reCreateMpvContext);
     connect(mpv, &MpvContainer::mpvPlaybackToggled, this,
             [this, togglePlaybackButton](bool isPlay) noexcept -> void {
                 togglePlaybackButton->setIcon(isPlay ? pauseIcon : playIcon);
@@ -61,6 +64,7 @@ MpvControls::MpvControls(MpvContainer *passedContainer, QWidget *parent) noexcep
 
     auto *centralLayout = new QHBoxLayout(this);
     centralLayout->addWidget(togglePlaybackButton);
+    centralLayout->addWidget(reCreateMpvButton);
     centralLayout->addWidget(progressBar, 1);
     setLayout(centralLayout);
 }
diff --git a/src/UI/DocumentViews/MpvControls.hh b/src/UI/DocumentViews/MpvControls.hh
index 5c792dc7..84cd143a 100644
--- a/src/UI/DocumentViews/MpvControls.hh
+++ b/src/UI/DocumentViews/MpvControls.hh
@@ -23,6 +23,7 @@ private:
 
     const QIcon playIcon{ VIVY_ICON_PLAY };
     const QIcon pauseIcon{ VIVY_ICON_PAUSE };
+    const QIcon reCreateMpvIcon{ VIVY_ICON_RUN };
 
 public:
     explicit MpvControls(MpvContainer *mpv, QWidget *parent) noexcept;
-- 
GitLab