Add active recordings to timeshift mode

If the current program is paused (timeshift mode), a recording
is created with an "@" at the beginning. A skin can display
this mode differently than the normal playback of a recording.
This change also enables a different display mode for currently
active timer recordings.
This commit is contained in:
kamel5 2021-03-04 16:30:10 +01:00
parent e7ea88c253
commit fdc8195174
6 changed files with 111 additions and 88 deletions

View File

@ -154,7 +154,7 @@ void cViewReplay::ClearVariables(void) {
lastFlush = 0;
lastFlushModeOnly = 0;
message = false;
timeShiftActive = false;
timeShiftActive = NoRec;
timeShiftFramesTotal = -1;
timeShiftLength = -1;
timeShiftDuration = "";
@ -181,35 +181,41 @@ void cViewReplay::GetGlobalTimers(void) {
void cViewReplay::SetTimeShiftValues(int current, int total) {
if (!recording)
return;
timeShiftActive = false;
timeShiftActive = NoRec;
#if APIVERSNUM >= 20101
int usage = recording->IsInUse();
if (usage & ruTimer)
timeShiftActive = true;
timeShiftActive = NormalRec;
else {
GetGlobalTimers();
if (globalTimers.IsRecording(recording))
timeShiftActive = true;
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;
{
LOCK_SCHEDULES_READ;
Schedule = Schedules->GetSchedule(recInfo->ChannelID());
if (timeShiftActive == TimeshiftRec) {
{
LOCK_SCHEDULES_READ;
Schedule = Schedules->GetSchedule(recInfo->ChannelID());
}
if (!Schedule)
return;
}
if (!Schedule)
return;
// Get event at actual recording position
const cEvent *eventEnde = Schedule->GetEventAround(time(0));
if (!eventEnde)
const cEvent *event = (timeShiftActive == TimeshiftRec) ? Schedule->GetEventAround(time(0))
: recInfo->GetEvent();
if (!event)
return;
// End of live program
time_t liveEventStop = eventEnde->EndTime();
time_t liveEventStop = event->EndTime();
// Begin of timeshift recording
time_t recordingStart = time(0) - recording->LengthInSeconds();
// actual timeshiftlength in sec
@ -218,12 +224,14 @@ void cViewReplay::SetTimeShiftValues(int current, int total) {
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;
const cEvent *eventReplay = Schedule->GetEventAround(time(0) - timeShiftSecondsAfter);
// Display title at replay position
if (eventReplay && eventReplay != lastEvent && veRecTitle) {
veRecTitle->Set(recording, eventReplay, true);
veRecTitle->Parse();
lastEvent = eventReplay;
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;

View File

@ -29,7 +29,7 @@ private:
time_t lastFlushModeOnly;
bool message;
int reclength;
bool timeShiftActive;
eRecType_t timeShiftActive;
int timeShiftFramesTotal;
int timeShiftLength;
cString timeshiftrest;

View File

@ -10,7 +10,7 @@ cVeDrRecTitle::cVeDrRecTitle(void) {
recording = NULL;
event = NULL;
title = NULL;
timeshiftActive = false;
timeShiftActive = NoRec;
}
cVeDrRecTitle::~cVeDrRecTitle(void) {
@ -29,8 +29,8 @@ void cVeDrRecTitle::SetTokenContainer(void) {
InheritTokenContainer();
}
void cVeDrRecTitle::Set(const cRecording *recording, const cEvent *event, bool timeshiftActive) {
this->timeshiftActive = timeshiftActive;
void cVeDrRecTitle::Set(const cRecording *recording, const cEvent *event, eRecType_t timeShiftActive) {
this->timeShiftActive = timeShiftActive;
if (this->title) {
free(this->title);
this->title = NULL;
@ -88,7 +88,7 @@ bool cVeDrRecTitle::Parse(bool force) {
tokenContainer->AddStringToken((int)eDRRecTitleST::recsubtitle, recShortText);
tokenContainer->AddStringToken((int)eDRRecTitleST::recdate, *ShortDateString(recording->Start()));
tokenContainer->AddStringToken((int)eDRRecTitleST::rectime, *TimeString(recording->Start()));
tokenContainer->AddIntToken((int)eDRRecTitleIT::timeshift, timeshiftActive);
tokenContainer->AddIntToken((int)eDRRecTitleIT::timeshift, timeShiftActive);
if (event) {
tokenContainer->AddStringToken((int)eDRRecTitleST::eventstart, *TimeString(event->StartTime()));
tokenContainer->AddStringToken((int)eDRRecTitleST::eventstop, *TimeString(event->EndTime()));
@ -164,7 +164,7 @@ bool cVeDrRecInfo::Parse(bool force) {
cVeDrCurrentTime::cVeDrCurrentTime(void) {
changed = true;
current = NULL;
timeshiftActive = false;
timeShiftActive = NoRec;
}
cVeDrCurrentTime::~cVeDrCurrentTime(void) {
@ -178,12 +178,12 @@ void cVeDrCurrentTime::SetTokenContainer(void) {
InheritTokenContainer();
}
void cVeDrCurrentTime::Set(const char *current, bool timeshiftActive) {
void cVeDrCurrentTime::Set(const char *current, eRecType_t timeShiftActive) {
if (!current)
return;
free(this->current);
this->current = strdup(current);
this->timeshiftActive = timeshiftActive;
this->timeShiftActive = timeShiftActive;
changed = true;
}
@ -192,7 +192,7 @@ bool cVeDrCurrentTime::Parse(bool force) {
return false;
tokenContainer->Clear();
tokenContainer->AddStringToken((int)eDRCurrentTimeST::reccurrent, current);
tokenContainer->AddIntToken((int)eDRCurrentTimeIT::timeshift, timeshiftActive);
tokenContainer->AddIntToken((int)eDRCurrentTimeIT::timeshift, timeShiftActive);
SetDirty();
changed = false;
return true;
@ -205,7 +205,7 @@ cVeDrTotalTime::cVeDrTotalTime(void) {
changed = true;
total = NULL;
timeshiftDuration = NULL;
timeshiftActive = false;
timeShiftActive = NoRec;
}
cVeDrTotalTime::~cVeDrTotalTime(void) {
@ -221,12 +221,12 @@ void cVeDrTotalTime::SetTokenContainer(void) {
InheritTokenContainer();
}
void cVeDrTotalTime::Set(const char *total, const char *timeshiftDuration, bool timeshiftActive) {
void cVeDrTotalTime::Set(const char *total, const char *timeshiftDuration, eRecType_t timeShiftActive) {
if (!total)
return;
free(this->total);
this->total = strdup(total);
this->timeshiftActive = timeshiftActive;
this->timeShiftActive = timeShiftActive;
free(this->timeshiftDuration);
this->timeshiftDuration = NULL;
if (timeshiftDuration)
@ -240,7 +240,7 @@ bool cVeDrTotalTime::Parse(bool force) {
tokenContainer->Clear();
tokenContainer->AddStringToken((int)eDRTotalTimeST::rectotal, total);
tokenContainer->AddStringToken((int)eDRTotalTimeST::timeshifttotal, timeshiftDuration);
tokenContainer->AddIntToken((int)eDRTotalTimeIT::timeshift, timeshiftActive);
tokenContainer->AddIntToken((int)eDRTotalTimeIT::timeshift, timeShiftActive);
SetDirty();
changed = false;
return true;
@ -254,7 +254,7 @@ cVeDrTimeshiftTimes::cVeDrTimeshiftTimes(void) {
start = "";
playbacktime = "";
timeshiftrest = "";
timeshiftActive = false;
timeShiftActive = NoRec;
}
cVeDrTimeshiftTimes::~cVeDrTimeshiftTimes(void) {
@ -269,8 +269,8 @@ void cVeDrTimeshiftTimes::SetTokenContainer(void) {
InheritTokenContainer();
}
void cVeDrTimeshiftTimes::Set(cString start, cString playbacktime, cString timeshiftrest, bool timeshiftActive) {
this->timeshiftActive = timeshiftActive;
void cVeDrTimeshiftTimes::Set(cString start, cString playbacktime, cString timeshiftrest, eRecType_t timeShiftActive) {
this->timeShiftActive = timeShiftActive;
if (strcmp(*this->start, *start) || strcmp(*this->playbacktime, *playbacktime) || strcmp(*this->timeshiftrest, *timeshiftrest)) {
this->start = start;
this->playbacktime = playbacktime;
@ -286,7 +286,7 @@ bool cVeDrTimeshiftTimes::Parse(bool force) {
tokenContainer->AddStringToken((int)eDRTimeshiftTimesST::recstart, *start);
tokenContainer->AddStringToken((int)eDRTimeshiftTimesST::playbacktime, *playbacktime);
tokenContainer->AddStringToken((int)eDRTimeshiftTimesST::timeshiftrest, *timeshiftrest);
tokenContainer->AddIntToken((int)eDRTimeshiftTimesIT::timeshift, timeshiftActive);
tokenContainer->AddIntToken((int)eDRTimeshiftTimesIT::timeshift, timeShiftActive);
SetDirty();
changed = false;
return true;
@ -298,7 +298,7 @@ bool cVeDrTimeshiftTimes::Parse(bool force) {
cVeDrEndTime::cVeDrEndTime(void) {
changed = true;
end = "";
timeshiftActive = false;
timeShiftActive = NoRec;
}
cVeDrEndTime::~cVeDrEndTime(void) {
@ -311,8 +311,8 @@ void cVeDrEndTime::SetTokenContainer(void) {
InheritTokenContainer();
}
void cVeDrEndTime::Set(cString end, bool timeshiftActive) {
this->timeshiftActive = timeshiftActive;
void cVeDrEndTime::Set(cString end, eRecType_t timeShiftActive) {
this->timeShiftActive = timeShiftActive;
if (strcmp(*this->end, *end)) {
this->end = end;
changed = true;
@ -324,7 +324,7 @@ bool cVeDrEndTime::Parse(bool force) {
return false;
tokenContainer->Clear();
tokenContainer->AddStringToken((int)eDREndTimeST::recend, *end);
tokenContainer->AddIntToken((int)eDREndTimeIT::timeshift, timeshiftActive);
tokenContainer->AddIntToken((int)eDREndTimeIT::timeshift, timeShiftActive);
SetDirty();
changed = false;
return true;
@ -337,7 +337,7 @@ cVeDrProgressBar::cVeDrProgressBar(void) {
current = -1;
total = -1;
timeshiftTotal = -1;
timeshiftActive = false;
timeShiftActive = NoRec;
changed = true;
}
@ -353,12 +353,12 @@ void cVeDrProgressBar::SetTokenContainer(void) {
InheritTokenContainer();
}
void cVeDrProgressBar::Set(int current, int total, bool timeshiftActive, int timeshiftTotal) {
void cVeDrProgressBar::Set(int current, int total, eRecType_t timeShiftActive, int timeshiftTotal) {
if (!(this->current != current || this->total != total))
return;
this->current = current;
this->total = total;
this->timeshiftActive = timeshiftActive;
this->timeShiftActive = timeShiftActive;
this->timeshiftTotal = timeshiftTotal;
changed = true;
@ -371,7 +371,7 @@ bool cVeDrProgressBar::Parse(bool force) {
tokenContainer->Clear();
tokenContainer->AddIntToken((int)eDRProgressbarIT::current, current);
tokenContainer->AddIntToken((int)eDRProgressbarIT::total, total);
tokenContainer->AddIntToken((int)eDRProgressbarIT::timeshift, timeshiftActive);
tokenContainer->AddIntToken((int)eDRProgressbarIT::timeshift, timeShiftActive);
tokenContainer->AddIntToken((int)eDRProgressbarIT::timeshifttotal, timeshiftTotal);
SetDirty();
@ -384,7 +384,7 @@ bool cVeDrProgressBar::Parse(bool force) {
cVeDrCutMarks::cVeDrCutMarks(void) {
cutmarksIndex = -1;
lastMarks = NULL;
timeshiftActive = false;
timeShiftActive = NoRec;
Reset();
}
@ -405,11 +405,11 @@ void cVeDrCutMarks::SetTokenContainer(void) {
InheritTokenContainer();
}
void cVeDrCutMarks::Set(const cMarks *marks, int current, int total, bool timeshiftActive, int timeshiftTotal) {
void cVeDrCutMarks::Set(const cMarks *marks, int current, int total, eRecType_t timeShiftActive, int timeshiftTotal) {
this->marks = marks;
this->current = current;
this->total = total;
this->timeshiftActive = timeshiftActive;
this->timeShiftActive = timeShiftActive;
this->timeshiftTotal = timeshiftTotal;
}
@ -421,7 +421,7 @@ void cVeDrCutMarks::Reset(void) {
delete[] lastMarks;
lastMarks = NULL;
markActive = -1;
timeshiftActive = false;
timeShiftActive = NoRec;
timeshiftTotal = -1;
}
@ -432,7 +432,7 @@ bool cVeDrCutMarks::Parse(bool force) {
return false;
}
tokenContainer->Clear();
tokenContainer->AddIntToken((int)eDRCutmarksIT::timeshift, timeshiftActive);
tokenContainer->AddIntToken((int)eDRCutmarksIT::timeshift, timeShiftActive);
int numMarks = marks->Count();
vector<int> cutmarksInfo;
cutmarksInfo.push_back(numMarks);
@ -444,7 +444,7 @@ bool cVeDrCutMarks::Parse(bool force) {
for (const cMark *m = marks->First(); m; m = marks->Next(m)) {
tokenContainer->AddLoopToken(cutmarksIndex, i, (int)eDRCutmarksLT::position, *cString::sprintf("%d", m->Position()));
tokenContainer->AddLoopToken(cutmarksIndex, i, (int)eDRCutmarksLT::total, *tot);
if (timeshiftActive) {
if (timeShiftActive) {
tokenContainer->AddLoopToken(cutmarksIndex, i, (int)eDRCutmarksLT::timeshifttotal, *timeshifttot);
}
tokenContainer->AddLoopToken(cutmarksIndex, i, (int)eDRCutmarksLT::startmark, isStartMark ? "1" : "0");

View File

@ -4,6 +4,13 @@
#include "viewelement.h"
#include "../extensions/scrapmanager.h"
// define recordingtypes
enum eRecType_t {
NoRec = 0,
NormalRec,
TimeshiftRec
};
/******************************************************************
* cVeDrRecTitle
******************************************************************/
@ -12,12 +19,12 @@ private:
const cRecording *recording;
const cEvent *event;
char *title;
bool timeshiftActive;
eRecType_t timeShiftActive;
public:
cVeDrRecTitle(void);
virtual ~cVeDrRecTitle(void);
void SetTokenContainer(void);
void Set(const cRecording *recording = NULL, const cEvent *event = NULL, bool timeshiftActive = false);
void Set(const cRecording *recording = NULL, const cEvent *event = NULL, eRecType_t timeShiftActive = NoRec);
void Set(const char *title = NULL);
bool Parse(bool forced = false);
};
@ -43,12 +50,12 @@ class cVeDrCurrentTime : public cViewElement {
private:
bool changed;
char *current;
bool timeshiftActive;
eRecType_t timeShiftActive;
public:
cVeDrCurrentTime(void);
virtual ~cVeDrCurrentTime(void);
void SetTokenContainer(void);
void Set(const char *current, bool timeshiftActive = false);
void Set(const char *current, eRecType_t timeShiftActive = NoRec);
bool Parse(bool forced = false);
};
@ -59,13 +66,13 @@ class cVeDrTotalTime : public cViewElement {
private:
bool changed;
char *total;
bool timeshiftActive;
eRecType_t timeShiftActive;
char *timeshiftDuration;
public:
cVeDrTotalTime(void);
virtual ~cVeDrTotalTime(void);
void SetTokenContainer(void);
void Set(const char *total, const char *timeshiftDuration = NULL, bool timeshiftActive = false);
void Set(const char *total, const char *timeshiftDuration = NULL, eRecType_t timeShiftActive = NoRec);
bool Parse(bool forced = false);
};
@ -78,12 +85,12 @@ private:
cString playbacktime;
cString timeshiftrest;
bool changed;
bool timeshiftActive;
eRecType_t timeShiftActive;
public:
cVeDrTimeshiftTimes(void);
virtual ~cVeDrTimeshiftTimes(void);
void SetTokenContainer(void);
void Set(cString start, cString playbacktime, cString timeshiftrest, bool timeshiftActive = false);
void Set(cString start, cString playbacktime, cString timeshiftrest, eRecType_t timeShiftActive = NoRec);
bool Parse(bool forced = false);
};
@ -93,13 +100,13 @@ public:
class cVeDrEndTime : public cViewElement {
private:
cString end;
bool timeshiftActive;
eRecType_t timeShiftActive;
bool changed;
public:
cVeDrEndTime(void);
virtual ~cVeDrEndTime(void);
void SetTokenContainer(void);
void Set(cString end, bool timeshiftActive = false);
void Set(cString end, eRecType_t timeShiftActive = NoRec);
bool Parse(bool forced = false);
};
@ -110,14 +117,14 @@ class cVeDrProgressBar : public cViewElement {
private:
int current;
int total;
bool timeshiftActive;
eRecType_t timeShiftActive;
int timeshiftTotal;
bool changed;
public:
cVeDrProgressBar(void);
virtual ~cVeDrProgressBar(void);
void SetTokenContainer(void);
void Set(int current, int total, bool timeshiftActive = false, int timeshiftTotal = 0);
void Set(int current, int total, eRecType_t timeShiftActive = NoRec, int timeshiftTotal = 0);
bool Parse(bool forced = false);
};
@ -130,7 +137,7 @@ private:
const cMarks *marks;
int current;
int total;
bool timeshiftActive;
eRecType_t timeShiftActive;
int timeshiftTotal;
int numMarksLast;
int *lastMarks;
@ -141,7 +148,7 @@ public:
cVeDrCutMarks(void);
virtual ~cVeDrCutMarks(void);
void SetTokenContainer(void);
void Set(const cMarks *marks, int current, int total, bool timeshiftActive = false, int timeshiftTotal = 0);
void Set(const cMarks *marks, int current, int total, eRecType_t timeShiftActive = NoRec, int timeshiftTotal = 0);
void Reset(void);
bool Parse(bool forced = false);
};

View File

@ -95,7 +95,8 @@
<drawtext align="left" y="0" fontsize="{areaheight}*{replayendtimesize}/100" font="{regular}" color="{fontdefault}" text="{tr(start)}: {recstart}" />
</area>
<area condition="{timeshift}" x="40%" y="81%" width="20%" height="5%" layer="2">
<drawtext name="rest" align="center" y="0" fontsize="{areaheight}*{replayendtimesize}/100" font="{regular}" color="{fontdefault}" text="TS {tr(rest)}: -{timeshiftrest}" />
<drawtext condition="eq({timeshift}, 1)" align="center" y="0" fontsize="{areaheight}*{replayendtimesize}/100" font="{regular}" color="{fontdefault}" text="{tr(rest)}: -{timeshiftrest}" />
<drawtext condition="gt({timeshift}, 1)" align="center" y="0" fontsize="{areaheight}*{replayendtimesize}/100" font="{regular}" color="{fontdefault}" text="Timeshift Mode {tr(rest)}: -{timeshiftrest}" />
</area>
<area condition="{timeshift}" x="12%" y="87%" width="19%" height="5%" layer="2">
<drawtext align="left" y="0" fontsize="{areaheight}*{replayendtimesize}/100" font="{regular}" color="{fontdefault}" text="{tr(playback)}: {playbacktime}" />

View File

@ -58,7 +58,8 @@
{rectime} Time of Recording in hh:mm
{eventstart} Starttime of coresponding event in timeshiftmode in hh:mm
{eventstop} Endtime of coresponding event in timeshiftmode in hh:mm
{timeshift} true if a timeshifted recording is displayed
{timeshift} 1 if a active recording is displayed
2 if a timeshift recording is displayed
-->
<rectitle>
</rectitle>
@ -76,54 +77,60 @@
</recinfo>
<!-- Available Variables currenttime:
{reccurrent} Current Time in hh:mm:ss
{timeshift} true if a timeshifted recording is displayed
{reccurrent} Current Time in hh:mm:ss
{timeshift} 1 if a active recording is displayed
2 if a timeshift recording is displayed
-->
<currenttime>
</currenttime>
<!-- Available Variables totaltime:
{rectotal} Total Time in hh:mm:ss
{timeshift} true if a timeshifted recording is displayed
{timeshifttotal} Total Time of timeshift event in hh:mm
{rectotal} Total Time in hh:mm:ss
{timeshift} 1 if a active recording is displayed
2 if a timeshift recording is displayed
{timeshifttotal} Total Time of timeshift event in hh:mm
-->
<totaltime>
</totaltime>
<!-- Available Variables timeshifttimes:
{recstart} Start Time in hh:mm
{playbacktime} actual replaying time in timeshift mode in hh:mm
{timeshiftrest} Rest of unseen timeshift buffer in hh:mm
{timeshift} true if a timeshifted recording is displayed
{recstart} Start Time in hh:mm
{playbacktime} actual replaying time in timeshift mode in hh:mm
{timeshiftrest} Rest of unseen timeshift buffer in hh:mm
{timeshift} 1 if a active recording is displayed
2 if a timeshift recording is displayed
-->
<timeshifttimes>
</timeshifttimes>
<!-- Available Variables endtime:
{recend} End Time in hh:mm
{timeshift} true if a timeshifted recording is displayed
{recend} End Time in hh:mm
{timeshift} 1 if a active recording is displayed
2 if a timeshift recording is displayed
-->
<endtime>
</endtime>
<!-- Available Variables progressbar:
{current} current frame of recording
{total} total frames of recording
{timeshift} true if a timeshifted recording is displayed
{timeshifttotal} total number of frames of timeshift event
{current} current frame of recording
{total} total frames of recording
{timeshift} 1 if a active recording is displayed
2 if a timeshift recording is displayed
{timeshifttotal} total number of frames of timeshift event
-->
<progressbar>
</progressbar>
<!-- Available Variables cutmarks:
{timeshift} true if a timeshifted recording is displayed
{marks[]} array of available marks
{marks[position]} frame of current mark
{marks[endposition]} frame where startmark ends
{marks[total]} total number of frames
{marks[timeshifttotal]} total number of frames of timeshift event
{marks[active]} true if current replay position hits exactly the mark
{marks[startmark]} true if mark is start mark
{timeshift} 1 if a active recording is displayed
2 if a timeshift recording is displayed
{marks[]} array of available marks
{marks[position]} frame of current mark
{marks[endposition]} frame where startmark ends
{marks[total]} total number of frames
{marks[timeshifttotal]} total number of frames of timeshift event
{marks[active]} true if current replay position hits exactly the mark
{marks[startmark]} true if mark is start mark
-->
<cutmarks>
</cutmarks>