mirror of
https://projects.vdr-developer.org/git/vdr-plugin-skindesigner.git
synced 2023-10-19 17:58:31 +02:00
50879fa931
This fix prevents a segfault when using the mpv plugin because there are no cutmarks.
428 lines
15 KiB
C
428 lines
15 KiB
C
#include "viewdisplayreplay.h"
|
|
|
|
/************************************************************************************
|
|
* cViewReplay
|
|
************************************************************************************/
|
|
|
|
cViewReplay::cViewReplay(void) {
|
|
veCustomTokens = NULL;
|
|
veTimeshiftTimes = NULL;
|
|
veEndTime = NULL;
|
|
veMessage = NULL;
|
|
veScraperContent = NULL;
|
|
veRecTitle = NULL;
|
|
veRecInfo = NULL;
|
|
veCurrentTime = NULL;
|
|
veTotalTime = NULL;
|
|
veProgressbar = NULL;
|
|
veCutMarks = NULL;
|
|
veProgressModeOnly = NULL;
|
|
veControlIcons = NULL;
|
|
veControlIconsModeOnly = NULL;
|
|
veJump = NULL;
|
|
veOnPause = NULL;
|
|
veOnPauseModeOnly = NULL;
|
|
ClearVariables();
|
|
viewId = eViewType::DisplayReplay;
|
|
viewName = strdup("displayreplay");
|
|
numViewElements = (int)eVeDisplayReplay::count;
|
|
viewElements = new cViewElement*[numViewElements];
|
|
for (int i=0; i < numViewElements; i++) {
|
|
viewElements[i] = NULL;
|
|
}
|
|
SetViewElements();
|
|
}
|
|
|
|
cViewReplay::~cViewReplay() {
|
|
}
|
|
|
|
void cViewReplay::SetViewElements(void) {
|
|
viewElementNames.insert(pair<string, int>("background", (int)eVeDisplayReplay::background));
|
|
viewElementNames.insert(pair<string, int>("backgroundmodeonly", (int)eVeDisplayReplay::backgroundmodeonly));
|
|
viewElementNames.insert(pair<string, int>("datetime", (int)eVeDisplayReplay::datetime));
|
|
viewElementNames.insert(pair<string, int>("time", (int)eVeDisplayReplay::time));
|
|
viewElementNames.insert(pair<string, int>("scrapercontent", (int)eVeDisplayReplay::scrapercontent));
|
|
viewElementNames.insert(pair<string, int>("currentweather", (int)eVeDisplayReplay::currentweather));
|
|
viewElementNames.insert(pair<string, int>("rectitle", (int)eVeDisplayReplay::rectitle));
|
|
viewElementNames.insert(pair<string, int>("recinfo", (int)eVeDisplayReplay::recinfo));
|
|
viewElementNames.insert(pair<string, int>("currenttime", (int)eVeDisplayReplay::currenttime));
|
|
viewElementNames.insert(pair<string, int>("timeshifttimes", (int)eVeDisplayReplay::timeshifttimes));
|
|
viewElementNames.insert(pair<string, int>("endtime", (int)eVeDisplayReplay::endtime));
|
|
viewElementNames.insert(pair<string, int>("totaltime", (int)eVeDisplayReplay::totaltime));
|
|
viewElementNames.insert(pair<string, int>("progressbar", (int)eVeDisplayReplay::progressbar));
|
|
viewElementNames.insert(pair<string, int>("cutmarks", (int)eVeDisplayReplay::cutmarks));
|
|
viewElementNames.insert(pair<string, int>("cutmarks", (int)eVeDisplayReplay::cutmarks));
|
|
viewElementNames.insert(pair<string, int>("controlicons", (int)eVeDisplayReplay::controlicons));
|
|
viewElementNames.insert(pair<string, int>("controliconsmodeonly", (int)eVeDisplayReplay::controliconsmodeonly));
|
|
viewElementNames.insert(pair<string, int>("progressmodeonly", (int)eVeDisplayReplay::progressmodeonly));
|
|
viewElementNames.insert(pair<string, int>("jump", (int)eVeDisplayReplay::jump));
|
|
viewElementNames.insert(pair<string, int>("message", (int)eVeDisplayReplay::message));
|
|
viewElementNames.insert(pair<string, int>("onpause", (int)eVeDisplayReplay::onpause));
|
|
viewElementNames.insert(pair<string, int>("onpausemodeonly", (int)eVeDisplayReplay::onpausemodeonly));
|
|
viewElementNames.insert(pair<string, int>("customtokens", (int)eVeDisplayReplay::customtokens));
|
|
}
|
|
|
|
void cViewReplay::SetViewElementObjects(void) {
|
|
for (int i = 0; i < numViewElements; i++) {
|
|
if (!viewElements[i])
|
|
continue;
|
|
if (dynamic_cast<cVeMessage*>(viewElements[i]))
|
|
{
|
|
veMessage = dynamic_cast<cVeMessage*>(viewElements[i]);
|
|
}
|
|
else if (dynamic_cast<cVeDrScraperContent*>(viewElements[i]))
|
|
{
|
|
veScraperContent = dynamic_cast<cVeDrScraperContent*>(viewElements[i]);
|
|
}
|
|
else if (dynamic_cast<cVeCustomTokens*>(viewElements[i]))
|
|
{
|
|
veCustomTokens = dynamic_cast<cVeCustomTokens*>(viewElements[i]);
|
|
}
|
|
else if (dynamic_cast<cVeDrRecTitle*>(viewElements[i]))
|
|
{
|
|
veRecTitle = dynamic_cast<cVeDrRecTitle*>(viewElements[i]);
|
|
}
|
|
else if (dynamic_cast<cVeDrRecInfo*>(viewElements[i]))
|
|
{
|
|
veRecInfo = dynamic_cast<cVeDrRecInfo*>(viewElements[i]);
|
|
}
|
|
else if (dynamic_cast<cVeDrCurrentTime*>(viewElements[i]))
|
|
{
|
|
veCurrentTime = dynamic_cast<cVeDrCurrentTime*>(viewElements[i]);
|
|
}
|
|
else if (dynamic_cast<cVeDrTotalTime*>(viewElements[i]))
|
|
{
|
|
veTotalTime = dynamic_cast<cVeDrTotalTime*>(viewElements[i]);
|
|
}
|
|
else if (dynamic_cast<cVeDrTimeshiftTimes*>(viewElements[i]))
|
|
{
|
|
veTimeshiftTimes = dynamic_cast<cVeDrTimeshiftTimes*>(viewElements[i]);
|
|
}
|
|
else if (dynamic_cast<cVeDrEndTime*>(viewElements[i]))
|
|
{
|
|
veEndTime = dynamic_cast<cVeDrEndTime*>(viewElements[i]);
|
|
}
|
|
else if (dynamic_cast<cVeDrProgressBar*>(viewElements[i]))
|
|
{
|
|
veProgressbar = dynamic_cast<cVeDrProgressBar*>(viewElements[i]);
|
|
}
|
|
else if (dynamic_cast<cVeDrCutMarks*>(viewElements[i]))
|
|
{
|
|
veCutMarks = dynamic_cast<cVeDrCutMarks*>(viewElements[i]);
|
|
}
|
|
else if (dynamic_cast<cVeDrProgressModeonly*>(viewElements[i]))
|
|
{
|
|
veProgressModeOnly = dynamic_cast<cVeDrProgressModeonly*>(viewElements[i]);
|
|
}
|
|
else if (dynamic_cast<cVeDrControlIcons*>(viewElements[i]) && (i == (int)eVeDisplayReplay::controlicons))
|
|
{
|
|
veControlIcons = dynamic_cast<cVeDrControlIcons*>(viewElements[i]);
|
|
}
|
|
else if (dynamic_cast<cVeDrControlIcons*>(viewElements[i]) && i == (int)eVeDisplayReplay::controliconsmodeonly)
|
|
{
|
|
veControlIconsModeOnly = dynamic_cast<cVeDrControlIcons*>(viewElements[i]);
|
|
}
|
|
else if (dynamic_cast<cVeDrJump*>(viewElements[i]))
|
|
{
|
|
veJump = dynamic_cast<cVeDrJump*>(viewElements[i]);
|
|
}
|
|
else if (dynamic_cast<cVeDrOnPause*>(viewElements[i]) && i == (int)eVeDisplayReplay::onpause)
|
|
{
|
|
veOnPause = dynamic_cast<cVeDrOnPause*>(viewElements[i]);
|
|
veOnPause->SetDetached();
|
|
veOnPause->UnsetWaitOnWakeup();
|
|
}
|
|
else if (dynamic_cast<cVeDrOnPause*>(viewElements[i]) && i == (int)eVeDisplayReplay::onpausemodeonly)
|
|
{
|
|
veOnPauseModeOnly = dynamic_cast<cVeDrOnPause*>(viewElements[i]);
|
|
veOnPauseModeOnly->SetDetached();
|
|
veOnPauseModeOnly->UnsetWaitOnWakeup();
|
|
}
|
|
}
|
|
}
|
|
|
|
void cViewReplay::PreCache(void) {
|
|
cView::PreCache();
|
|
SetViewelementsAnimOut();
|
|
}
|
|
|
|
void cViewReplay::ClearVariables(void) {
|
|
cView::ClearVariables();
|
|
recording = NULL;
|
|
lastEvent = NULL;
|
|
modeOnly = false;
|
|
lastFlush = 0;
|
|
lastFlushModeOnly = 0;
|
|
message = false;
|
|
timeShiftActive = NoRec;
|
|
timeShiftFramesTotal = -1;
|
|
timeShiftLength = -1;
|
|
timeShiftDuration = "";
|
|
timeshiftrest = "";
|
|
if (veCustomTokens)
|
|
veCustomTokens->Reset();
|
|
if (veTimeshiftTimes)
|
|
veTimeshiftTimes->Set(cString(""), cString(""), cString(""));
|
|
if (veEndTime)
|
|
veEndTime->Set(cString(""));
|
|
timersLoaded = false;
|
|
globalTimers.ClearTimers();
|
|
}
|
|
|
|
void cViewReplay::GetGlobalTimers(void) {
|
|
if (!timersLoaded) {
|
|
timersLoaded = true;
|
|
globalTimers.LoadTimers();
|
|
}
|
|
}
|
|
|
|
void cViewReplay::SetTimeShiftValues(int current, int total) {
|
|
if (!recording)
|
|
return;
|
|
timeShiftActive = NoRec;
|
|
#if APIVERSNUM >= 20101
|
|
int usage = recording->IsInUse();
|
|
if (usage & ruTimer)
|
|
timeShiftActive = NormalRec;
|
|
else {
|
|
GetGlobalTimers();
|
|
if (globalTimers.IsRecording(recording))
|
|
timeShiftActive = NormalRec;
|
|
}
|
|
#endif
|
|
if (!timeShiftActive)
|
|
return;
|
|
const char *recName = recording->Name();
|
|
if (recName && *recName == '@')
|
|
timeShiftActive = TimeshiftRec;
|
|
const cRecordingInfo *recInfo = recording->Info();
|
|
if (!recInfo)
|
|
return;
|
|
const cSchedule *Schedule = NULL;
|
|
if (timeShiftActive == TimeshiftRec) {
|
|
{
|
|
LOCK_SCHEDULES_READ;
|
|
Schedule = Schedules->GetSchedule(recInfo->ChannelID());
|
|
}
|
|
if (!Schedule)
|
|
return;
|
|
}
|
|
// Get event at actual recording position
|
|
const cEvent *event = (timeShiftActive == TimeshiftRec) ? Schedule->GetEventAround(time(0))
|
|
: recInfo->GetEvent();
|
|
if (!event)
|
|
return;
|
|
// End of live program
|
|
time_t liveEventStop = event->EndTime();
|
|
// Begin of timeshift recording
|
|
time_t recordingStart = time(0) - recording->LengthInSeconds();
|
|
// actual timeshiftlength in sec
|
|
timeShiftLength = liveEventStop - recordingStart;
|
|
// timeshiftlength until end of live program
|
|
timeShiftFramesTotal = total * ((double)timeShiftLength / (double)recording->LengthInSeconds());
|
|
// Get event at actual replay position (add 30sec for a better match)
|
|
int timeShiftSecondsAfter = (int)(recording->LengthInSeconds() * (1.0 - (double)current / (double)total)) + 30;
|
|
if (timeShiftActive == TimeshiftRec) {
|
|
const cEvent *eventReplay = Schedule->GetEventAround(time(0) - timeShiftSecondsAfter);
|
|
// Display title at replay position
|
|
if (veRecTitle && eventReplay != lastEvent) {
|
|
veRecTitle->Set(recording, eventReplay, timeShiftActive);
|
|
veRecTitle->Parse();
|
|
lastEvent = eventReplay;
|
|
}
|
|
}
|
|
int mins = (timeShiftLength / 60) % 60;
|
|
int hours = (timeShiftLength / 3600) % 24;
|
|
timeShiftDuration = cString::sprintf("%d:%02d", hours, mins);
|
|
mins = (timeShiftSecondsAfter / 60) % 60;
|
|
hours = (timeShiftSecondsAfter / 3600) % 24;
|
|
timeshiftrest = cString::sprintf("%d:%02d", hours, mins);
|
|
}
|
|
|
|
void cViewReplay::SetRecording(const cRecording *recording) {
|
|
this->recording = recording;
|
|
if (veRecTitle) {
|
|
veRecTitle->Set(recording);
|
|
}
|
|
if (veRecInfo) {
|
|
veRecInfo->Set(recording);
|
|
}
|
|
if (veScraperContent) {
|
|
veScraperContent->Set(recording);
|
|
}
|
|
}
|
|
|
|
void cViewReplay::SetTitle(const char *title) {
|
|
if (veRecTitle) {
|
|
veRecTitle->Set(title);
|
|
}
|
|
if (veRecInfo) {
|
|
veRecInfo->Set(NULL);
|
|
}
|
|
if (veScraperContent) {
|
|
veScraperContent->Set(NULL);
|
|
}
|
|
}
|
|
|
|
void cViewReplay::SetCurrent(const char *current) {
|
|
if (veCurrentTime)
|
|
veCurrentTime->Set(current, timeShiftActive);
|
|
Render((int)eVeDisplayReplay::currenttime);
|
|
}
|
|
|
|
void cViewReplay::SetTotal(const char *total) {
|
|
if (veTotalTime)
|
|
veTotalTime->Set(total, *timeShiftDuration, timeShiftActive);
|
|
Render((int)eVeDisplayReplay::totaltime);
|
|
}
|
|
|
|
void cViewReplay::SetTimeshiftTimes(int current, int total) {
|
|
if (!veTimeshiftTimes || !recording)
|
|
return;
|
|
time_t recordingStart = 0;
|
|
time_t playbackTime = 0;
|
|
if (timeShiftActive) {
|
|
recordingStart = time(0) - recording->LengthInSeconds();
|
|
playbackTime = time(0) - (int)(recording->LengthInSeconds() * (1.0 - (double)current / (double)total));
|
|
} else
|
|
recordingStart = recording->Start();
|
|
veTimeshiftTimes->Set(TimeString(recordingStart), TimeString(playbackTime), timeshiftrest, timeShiftActive);
|
|
Render((int)eVeDisplayReplay::timeshifttimes);
|
|
}
|
|
|
|
void cViewReplay::SetEndTime(int current, int total) {
|
|
if (!veEndTime || !recording)
|
|
return;
|
|
int totalLength = total;
|
|
int recordingLength = recording->LengthInSeconds();
|
|
if (timeShiftActive && timeShiftFramesTotal > 0) {
|
|
totalLength = timeShiftFramesTotal;
|
|
recordingLength = timeShiftLength;
|
|
}
|
|
double rest = (double)(totalLength - current) / (double)totalLength;
|
|
time_t end = time(0) + rest * recordingLength;
|
|
veEndTime->Set(TimeString(end), timeShiftActive);
|
|
Render((int)eVeDisplayReplay::endtime);
|
|
}
|
|
|
|
void cViewReplay::SetProgressbar(int current, int total) {
|
|
SetTimeShiftValues(current, total);
|
|
if (veProgressbar)
|
|
veProgressbar->Set(current, total, timeShiftActive, timeShiftFramesTotal);
|
|
Render((int)eVeDisplayReplay::progressbar);
|
|
}
|
|
|
|
void cViewReplay::SetMarks(const cMarks *marks, int current, int total) {
|
|
if (!veCutMarks)
|
|
return;
|
|
veCutMarks->Set(marks, current, total, timeShiftActive, timeShiftFramesTotal);
|
|
Render((int)eVeDisplayReplay::cutmarks);
|
|
}
|
|
|
|
void cViewReplay::SetControlIcons(bool play, bool forward, int speed) {
|
|
if (!modeOnly) {
|
|
if (veControlIcons)
|
|
veControlIcons->Set(play, forward, speed);
|
|
Render((int)eVeDisplayReplay::controlicons);
|
|
} else {
|
|
if (veControlIconsModeOnly)
|
|
veControlIconsModeOnly->Set(play, forward, speed);
|
|
Render((int)eVeDisplayReplay::controliconsmodeonly);
|
|
}
|
|
|
|
}
|
|
|
|
void cViewReplay::SetJump(const char *jump) {
|
|
if (veJump) {
|
|
if (!jump)
|
|
veJump->Clear();
|
|
else
|
|
veJump->Set(jump);
|
|
}
|
|
Render((int)eVeDisplayReplay::jump);
|
|
}
|
|
|
|
void cViewReplay::SetMessage(eMessageType type, const char *text) {
|
|
if (veMessage) {
|
|
if (text)
|
|
veMessage->Set(type, text);
|
|
else
|
|
veMessage->Clear();
|
|
}
|
|
Render((int)eVeDisplayReplay::message);
|
|
}
|
|
|
|
void cViewReplay::StartOnPause(const char *recfilename) {
|
|
cVeDrOnPause *onPause = (!modeOnly) ? veOnPause : veOnPauseModeOnly;
|
|
if (!onPause)
|
|
return;
|
|
onPause->Set(recfilename);
|
|
onPause->Parse(true);
|
|
}
|
|
|
|
void cViewReplay::ClearOnPause(void) {
|
|
cVeDrOnPause *onPause = (!modeOnly) ? veOnPause : veOnPauseModeOnly;
|
|
if (!onPause)
|
|
return;
|
|
onPause->Close();
|
|
}
|
|
|
|
void cViewReplay::DelayOnPause(void) {
|
|
if (!veOnPause)
|
|
return;
|
|
if (!veOnPause->Started())
|
|
return;
|
|
veOnPause->ResetSleep();
|
|
}
|
|
|
|
void cViewReplay::Flush(void) {
|
|
if (init) {
|
|
if (!modeOnly) {
|
|
Render((int)eVeDisplayReplay::background);
|
|
Render((int)eVeDisplayReplay::rectitle);
|
|
Render((int)eVeDisplayReplay::recinfo);
|
|
Render((int)eVeDisplayReplay::scrapercontent);
|
|
Render((int)eVeDisplayReplay::currentweather);
|
|
Render((int)eVeDisplayReplay::customtokens);
|
|
} else {
|
|
Render((int)eVeDisplayReplay::backgroundmodeonly);
|
|
}
|
|
}
|
|
|
|
time_t now = time(0);
|
|
if (!modeOnly && (now != lastFlush)) {
|
|
Render((int)eVeDisplayReplay::datetime);
|
|
Render((int)eVeDisplayReplay::time);
|
|
Render((int)eVeDisplayChannel::customtokens);
|
|
lastFlush = now;
|
|
}
|
|
|
|
if (modeOnly) {
|
|
SetProgressModeOnly();
|
|
}
|
|
|
|
cView::Flush();
|
|
}
|
|
|
|
void cViewReplay::SetProgressModeOnly(void) {
|
|
if (!veProgressModeOnly)
|
|
return;
|
|
time_t now = time(0);
|
|
if (now == lastFlushModeOnly) {
|
|
return;
|
|
}
|
|
lastFlushModeOnly = now;
|
|
|
|
cControl *control = cControl::Control();
|
|
if (!control)
|
|
return;
|
|
double fps = control->FramesPerSecond();
|
|
int current = 0;
|
|
int total = 0;
|
|
if (!control->GetIndex(current, total))
|
|
return;
|
|
veProgressModeOnly->Set(fps, current, total);
|
|
if (veProgressModeOnly->Parse())
|
|
veProgressModeOnly->Render();
|
|
}
|