diff --git a/rsc/VivyRessources.qrc b/rsc/VivyRessources.qrc index 62d7ef146db8b572734d0347b3325016bdea862d..cf4b9dc75c8f74c8f4a33ee6adf4e5a8b1a541b6 100644 --- a/rsc/VivyRessources.qrc +++ b/rsc/VivyRessources.qrc @@ -49,6 +49,7 @@ <file alias="media-pause.svg">icons/breeze-dark/media-playback-pause.svg</file> <file alias="media-play.svg">icons/breeze-dark/media-playback-start.svg</file> <file alias="media-stop.svg">icons/breeze-dark/media-playback-stop.svg</file> + <file alias="run.svg">icons/breeze-dark/run-build-file.svg</file> </qresource> <qresource prefix="icons/light"> <file alias="document-new.svg">icons/breeze-light/document-new.svg</file> @@ -62,6 +63,7 @@ <file alias="media-pause.svg">icons/breeze-light/media-playback-pause.svg</file> <file alias="media-play.svg">icons/breeze-light/media-playback-start.svg</file> <file alias="media-stop.svg">icons/breeze-light/media-playback-stop.svg</file> + <file alias="run.svg">icons/breeze-light/run-build-file.svg</file> </qresource> <!-- QDarkStyle style sheet, MIT Licence --> diff --git a/src/UI/DocumentViews/MpvContainer.cc b/src/UI/DocumentViews/MpvContainer.cc index b6f30f4ce8a2cd34985dc44847e251baa0b02373..31e0dc58060fdfb46d75bb6c837774438752dfca 100644 --- a/src/UI/DocumentViews/MpvContainer.cc +++ b/src/UI/DocumentViews/MpvContainer.cc @@ -19,10 +19,12 @@ MpvContainer::MpvContainer(QWidget *parent) setAttribute(Qt::WA_DontCreateNativeAncestors); setAttribute(Qt::WA_NativeWindow); + + initializeMpv(); } void -MpvContainer::intializeMpv() +MpvContainer::initializeMpv() { if (isMpvAlreadyInitialized) throw std::logic_error("MPV is already initialized!"); @@ -42,13 +44,24 @@ MpvContainer::intializeMpv() mpv_observe_property(mpv, 0, "duration", MPV_FORMAT_DOUBLE); mpv_observe_property(mpv, 0, "time-pos", MPV_FORMAT_DOUBLE); + connect(this, &MpvContainer::mpvEvent, this, &MpvContainer::onMpvEvent, Qt::QueuedConnection); + mpv_set_wakeup_callback(mpv, &MpvContainer::mpvEventWakeUpCB, this); + if (int rc = mpv_initialize(mpv); rc < 0) { printMpvError(rc); throw std::runtime_error("Failed to initialize the mpv context"); } +} - connect(this, &MpvContainer::mpvEvent, this, &MpvContainer::onMpvEvent, Qt::QueuedConnection); - mpv_set_wakeup_callback(mpv, &MpvContainer::mpvEventWakeUpCB, this); +void +MpvContainer::reCreateMpvContext() +{ + closeMpv(); + mpv = mpv_create(); + if (mpv == nullptr) + throw std::runtime_error("Failed to create the MPV context"); + initializeMpv(); + loadFile(previousLoadedFile); } void @@ -75,11 +88,10 @@ MpvContainer::closeMpv() noexcept asyncCommand(AsyncCmdType::None, { "quit", nullptr }); registerMpvTimeCallback(nullptr); registerMpvDurationCallback(nullptr); - mpv_handle *tmp_mpv = mpv; - mpv = nullptr; // Stop all other callbacks here - mpv_destroy(tmp_mpv); - // mpv_wait_async_requests(tmp_mpv); - // mpv_terminate_destroy(tmp_mpv); + mpv_wait_async_requests(mpv); + mpv_terminate_destroy(mpv); + mpv = nullptr; // Stop all other callbacks here + isMpvAlreadyInitialized = false; // De-init } } @@ -232,10 +244,12 @@ MpvContainer::onMpvEvent() noexcept void MpvContainer::loadFile(const QString &filename) noexcept { - logDebug() << "Loading file" << filename; if (filename.size() == 0) return; + qDebug() << "Loading file" << filename; + if (previousLoadedFile != filename) + previousLoadedFile = filename; const QByteArray cFileName = filename.toUtf8(); asyncCommand(AsyncCmdType::LoadFile, { "loadfile", cFileName.data(), nullptr }); } diff --git a/src/UI/DocumentViews/MpvContainer.hh b/src/UI/DocumentViews/MpvContainer.hh index 677d945cf834a8dc2f80f1f4133d0c4566c9f3e6..37729f04dfa9ee9ee5ed2a04d6169645005ff90c 100644 --- a/src/UI/DocumentViews/MpvContainer.hh +++ b/src/UI/DocumentViews/MpvContainer.hh @@ -30,17 +30,8 @@ class MpvContainer final : public QWidget { TogglePlayback }; -private: - bool isPlaybackPaused{ true }; - bool isMpvAlreadyInitialized{ false }; - mpv_handle *volatile mpv{ nullptr }; - qint64 sid{ -1 }; - std::function<void(double)> mpvTimeCallback{ nullptr }; - std::function<void(double)> mpvDurationCallback{ nullptr }; - public: explicit MpvContainer(QWidget *parent); - void intializeMpv(); ~MpvContainer() noexcept override; void loadFile(const QString &) noexcept; @@ -55,6 +46,7 @@ public: void registerMpvDurationCallback(std::function<void(double)>) noexcept; private: + void initializeMpv(); void handleMpvEvent(const mpv_event *const) noexcept; void closeMpv() noexcept; void printMpvError(int) const noexcept; @@ -66,10 +58,19 @@ private: // Must be static to be passed as a function ptr static void mpvEventWakeUpCB(void *) noexcept; + bool isPlaybackPaused{ true }; + bool isMpvAlreadyInitialized{ false }; + mpv_handle *volatile mpv{ nullptr }; + qint64 sid{ -1 }; + QString previousLoadedFile{}; + std::function<void(double)> mpvTimeCallback{ nullptr }; + std::function<void(double)> mpvDurationCallback{ nullptr }; + public slots: void mpvPlay() noexcept; void mpvPause() noexcept; void mpvTogglePlayback() noexcept; + void reCreateMpvContext(); private slots: void onMpvEvent() noexcept; diff --git a/src/UI/DocumentViews/MpvControls.cc b/src/UI/DocumentViews/MpvControls.cc index 453c87c5ff116415c0ee121c1bbd2329bfe93ca7..a9d63a8f2e9c0a55cc4c555c864cd1573a2d6128 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 5c792dc72af07ec2866f5bc07e7bd6eaec077a7a..84cd143aaa76c30f6fb293124b73b245729ec93e 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; diff --git a/src/UI/DocumentViews/VideoView.cc b/src/UI/DocumentViews/VideoView.cc index 2e45fcfdb9c6d354cef88da731a80c19d971122c..30eee0e0863deaac58c2187232336f20395939a0 100644 --- a/src/UI/DocumentViews/VideoView.cc +++ b/src/UI/DocumentViews/VideoView.cc @@ -14,8 +14,6 @@ VideoView::VideoView(QWidget *parent) noexcept centralLayout->addWidget(new MpvControls(mpv, this)); setLayout(centralLayout); - - mpv->intializeMpv(); } void diff --git a/src/VivyApplication.hh b/src/VivyApplication.hh index 1546392992bb3ab29383f3c76fdf7ab79b8503e6..c802a011f505188c8dba07815c80a4c15e80f0d7 100644 --- a/src/VivyApplication.hh +++ b/src/VivyApplication.hh @@ -33,6 +33,7 @@ #define VIVY_ICON_PLAY ":icons/dark/media-play.svg" #define VIVY_ICON_PAUSE ":icons/dark/media-pause.svg" #define VIVY_ICON_STOP ":icons/dark/media-stop.svg" +#define VIVY_ICON_RUN ":icons/dark/run.svg" // Detect MacOS #if defined(Q_OS_DARWIN) || defined(Q_OS_MACOS)