summaryrefslogtreecommitdiff
path: root/control.c
diff options
context:
space:
mode:
Diffstat (limited to 'control.c')
-rw-r--r--control.c377
1 files changed, 377 insertions, 0 deletions
diff --git a/control.c b/control.c
new file mode 100644
index 0000000..e6061cb
--- /dev/null
+++ b/control.c
@@ -0,0 +1,377 @@
+//////////////////////////////////////////////////////////////////////////////
+/// ///
+/// This file is part of the VDR mpv plugin and licensed under AGPLv3 ///
+/// ///
+/// See the README file for copyright information ///
+/// ///
+//////////////////////////////////////////////////////////////////////////////
+
+#include "control.h"
+#include "config.h"
+#include <vdr/interface.h>
+
+cMpvControl::cMpvControl(string Filename, bool Shuffle)
+:cControl(Player = new cMpvPlayer(Filename.c_str(), Shuffle))
+{
+ dsyslog("[mpv] %s\n", __FUNCTION__);
+ DisplayReplay = NULL;
+ VolumeStatus = NULL;
+ if (!MpvPluginConfig->UsePassthrough)
+ VolumeStatus = new cMpvStatus(Player);
+ infoVisible = false;
+ timeSearchActive = false;
+ cStatus::MsgReplaying(this, Filename.c_str(), Filename.c_str(), true);
+}
+
+cMpvControl::~cMpvControl()
+{
+ dsyslog("[mpv]%s\n", __FUNCTION__);
+ if (VolumeStatus)
+ delete VolumeStatus;
+ Hide();
+ Player->OsdClose();
+ // Osd Workaround
+ // osd is open, first send menu key, this will close the menu, if any other
+ // osd was open this opens the menu, so send kBack afterwards, to close it again
+ if (cOsd::IsOpen())
+ {
+ eKeys key = kMenu;
+ dsyslog ("[mpv] osd is open sending menu key followed by back key\n");
+ cRemote::Put(key);
+ key = kBack;
+ cRemote::Put(key);
+}
+ Player->Shutdown();
+ delete Player;
+ cDevice::SetPrimaryDevice(cDevice::PrimaryDevice()->DeviceNumber() + 1);
+ cStatus::MsgReplaying(this, NULL, NULL, false);
+}
+
+void cMpvControl::ShowProgress(void)
+{
+ if (!Player->IsPaused() && LastPlayerCurrent == Player->CurrentPlayTime())
+ return;
+ LastPlayerCurrent = Player->CurrentPlayTime();
+
+ if (!DisplayReplay)
+ DisplayReplay = Skins.Current()->DisplayReplay(false);
+
+ if (!infoVisible)
+ {
+ UpdateMarks();
+ infoVisible = true;
+ timeoutShow = Setup.ProgressDisplayTime ? (time(0) + Setup.ProgressDisplayTime) : 0;
+ }
+
+ string TitleDisplay = Player->CurrentFile();
+ if (MpvPluginConfig->TitleOverride != "")
+ TitleDisplay = MpvPluginConfig->TitleOverride;
+ else if (MpvPluginConfig->ShowMediaTitle && Player->MediaTitle() != "")
+ TitleDisplay = Player->MediaTitle();
+
+ if (Player->NumChapters() > 0)
+ {
+ if (Player->ChapterTitle(Player->CurrentChapter()) != "")
+ TitleDisplay += " - " + Player->ChapterTitle(Player->CurrentChapter());
+
+ char buffer[10];
+ snprintf (buffer, sizeof(buffer), " (%d/%d)", Player->CurrentChapter(), Player->NumChapters());
+ TitleDisplay += buffer;
+ DisplayReplay->SetMarks(Marks());
+ }
+
+ DisplayReplay->SetTitle(TitleDisplay.c_str());
+ DisplayReplay->SetProgress(Player->CurrentPlayTime(), Player->TotalPlayTime());
+ int Speed = Player->CurrentPlaybackSpeed();
+ if (Speed == 1)
+ Speed = -1;
+ DisplayReplay->SetMode(!Player->IsPaused(), true, Speed);
+ DisplayReplay->SetCurrent(IndexToHMSF(Player->CurrentPlayTime(), false, 1));
+ DisplayReplay->SetTotal(IndexToHMSF(Player->TotalPlayTime(), false, 1));
+
+ SetNeedsFastResponse(true);
+ Skins.Flush();
+}
+
+void cMpvControl::Hide()
+{
+ if (DisplayReplay)
+ {
+ delete DisplayReplay;
+ DisplayReplay = NULL;
+ SetNeedsFastResponse(false);
+ }
+}
+
+eOSState cMpvControl::ProcessKey(eKeys key)
+{
+ eOSState state;
+
+ if (key != kNone)
+ {
+ dsyslog("[mpv]%s: key=%d\n", __FUNCTION__, key);
+ }
+
+ if (!Player->PlayerIsRunning()) // check if player is still alive
+ {
+ cControl::Shutdown();
+ return osEnd;
+ }
+
+ if (timeSearchActive && key != kNone)
+ {
+ TimeSearchProcess(key);
+ return osContinue;
+ }
+
+ if (timeoutShow && time(0) > timeoutShow)
+ {
+ timeoutShow = 0;
+ infoVisible = false;
+ Hide();
+ }
+ else if (infoVisible) // if RecordingInfo visible then update
+ ShowProgress();
+
+ state = osContinue;
+ switch ((int)key) // cast to shutup g++ warnings
+ {
+ case kUp:
+ if (Player->DiscNavActive())
+ {
+ Player->DiscNavUp();
+ break;
+ }
+ case kPlay:
+ Hide();
+ if (Player->CurrentPlaybackSpeed() != 1)
+ {
+ Player->SetSpeed(1);
+ }
+ if (Player->IsPaused())
+ {
+ Player->TogglePause();
+ }
+ ShowProgress();
+ break;
+
+ case kDown:
+ if (Player->DiscNavActive())
+ {
+ Player->DiscNavDown();
+ break;
+ }
+ case kPause:
+ Player->TogglePause();
+ ShowProgress();
+ break;
+
+ case kLeft:
+ if (Player->DiscNavActive())
+ {
+ Player->DiscNavLeft();
+ break;
+ }
+ case kFastRew:
+ // reset to normal playback speed (if fastfwd is active currently) and then just go back 10 seconds since there is no fastrew in mpv
+ Player->SetSpeed(1);
+ Player->Seek(-10);
+ ShowProgress();
+ break;
+ case kRight:
+ if (Player->DiscNavActive())
+ {
+ Player->DiscNavRight();
+ break;
+ }
+ case kFastFwd:
+ if (Player->CurrentPlaybackSpeed() < 32)
+ {
+ Player->SetSpeed(Player->CurrentPlaybackSpeed() * 2);
+ }
+ ShowProgress();
+ break;
+
+ case kRed:
+ TimeSearch();
+ break;
+ case kGreen | k_Repeat:
+ case kGreen:
+ Player->Seek(-60);
+ break;
+ case kYellow | k_Repeat:
+ case kYellow:
+ Player->Seek(+60);
+ break;
+
+ case kBack:
+ if (Player->DiscNavActive())
+ {
+ Player->DiscNavPrev();
+ break;
+ }
+ case kStop:
+ case kBlue:
+ Hide();
+ Player->QuitPlayer();
+ return osEnd;
+ break;
+
+ case kOk:
+ if (Player->DiscNavActive())
+ {
+ Player->DiscNavSelect();
+ break;
+ }
+ if (infoVisible)
+ {
+ Hide();
+ infoVisible = false;
+ }
+ else
+ ShowProgress();
+ break;
+
+ case k5:
+ Player->DiscNavMenu();
+ break;
+
+ case kNext:
+ if (MpvPluginConfig->PlaylistOnNextKey || (MpvPluginConfig->PlaylistIfNoChapters && !Player->NumChapters()))
+ Player->NextPlaylistItem();
+ else
+ Player->NextChapter();
+ break;
+
+ case kPrev:
+ if (MpvPluginConfig->PlaylistOnNextKey || (MpvPluginConfig->PlaylistIfNoChapters && !Player->NumChapters()))
+ Player->PreviousPlaylistItem();
+ else
+ Player->PreviousChapter();
+ break;
+
+ case k7:
+ if (MpvPluginConfig->PlaylistOnNextKey)
+ Player->PreviousChapter();
+ else
+ Player->PreviousPlaylistItem();
+ break;
+
+ case k9:
+ if (MpvPluginConfig->PlaylistOnNextKey)
+ Player->NextChapter();
+ else
+ Player->NextPlaylistItem();
+ break;
+
+ default:
+ break;
+ }
+ return state;
+}
+
+void cMpvControl::UpdateMarks()
+{
+ ((cList<cMark> *)&ChapterMarks)->Clear();
+
+ if (Player->NumChapters() > 1)
+ {
+ ChapterMarks.Add(0);
+ for (int i=1; i <= Player->NumChapters(); i++)
+ {
+ ChapterMarks.Add(Player->ChapterStartTime(i) - 1);
+ ChapterMarks.Add(Player->ChapterStartTime(i));
+ }
+ }
+}
+
+// TimeSearch code is copied from vdr menu.c and slightly adjusted to fit with our class
+void cMpvControl::TimeSearch()
+{
+ timeSearchTime = timeSearchPos = 0;
+ timeSearchHide = false;
+ if (!infoVisible) {
+ ShowProgress();
+ if (infoVisible)
+ timeSearchHide = true;
+ else
+ return;
+ }
+ timeoutShow = 0;
+ TimeSearchDisplay();
+ timeSearchActive = true;
+}
+
+void cMpvControl::TimeSearchDisplay()
+{
+ char buf[64];
+ // TRANSLATORS: note the trailing blank!
+ strcpy(buf, tr("Jump: "));
+ int len = strlen(buf);
+ char h10 = '0' + (timeSearchTime >> 24);
+ char h1 = '0' + ((timeSearchTime & 0x00FF0000) >> 16);
+ char m10 = '0' + ((timeSearchTime & 0x0000FF00) >> 8);
+ char m1 = '0' + (timeSearchTime & 0x000000FF);
+ char ch10 = timeSearchPos > 3 ? h10 : '-';
+ char ch1 = timeSearchPos > 2 ? h1 : '-';
+ char cm10 = timeSearchPos > 1 ? m10 : '-';
+ char cm1 = timeSearchPos > 0 ? m1 : '-';
+ sprintf(buf + len, "%c%c:%c%c", ch10, ch1, cm10, cm1);
+ DisplayReplay->SetJump(buf);
+}
+
+void cMpvControl::TimeSearchProcess(eKeys Key)
+{
+#define STAY_SECONDS_OFF_END 10
+ int Seconds = (timeSearchTime >> 24) * 36000 + ((timeSearchTime & 0x00FF0000) >> 16) * 3600 + ((timeSearchTime & 0x0000FF00) >> 8) * 600 + (timeSearchTime & 0x000000FF) * 60;
+ int Current = Player->CurrentPlayTime();
+ int Total = Player->TotalPlayTime();
+ switch (Key) {
+ case k0 ... k9:
+ if (timeSearchPos < 4) {
+ timeSearchTime <<= 8;
+ timeSearchTime |= Key - k0;
+ timeSearchPos++;
+ TimeSearchDisplay();
+ }
+ break;
+ case kFastRew:
+ case kLeft:
+ case kFastFwd:
+ case kRight: {
+ int dir = ((Key == kRight || Key == kFastFwd) ? 1 : -1);
+ if (dir > 0)
+ Seconds = min(Total - Current - STAY_SECONDS_OFF_END, Seconds);
+ else
+ Seconds = 0-Seconds;
+ Player->Seek(Seconds);
+ timeSearchActive = false;
+ }
+ break;
+ case kPlayPause:
+ case kPlay:
+ case kUp:
+ case kPause:
+ case kDown:
+ case kOk:
+ if (timeSearchPos > 0) {
+ Seconds = min(Total - STAY_SECONDS_OFF_END, Seconds);
+ Player->SetTimePos(Seconds);
+ }
+ timeSearchActive = false;
+ break;
+ default:
+ if (!(Key & k_Flags)) // ignore repeat/release keys
+ timeSearchActive = false;
+ break;
+ }
+
+ if (!timeSearchActive) {
+ if (timeSearchHide)
+ Hide();
+ else
+ DisplayReplay->SetJump(NULL);
+// ShowProgress();
+ }
+}
+