36 #define MAXWAIT4EPGINFO 3 // seconds
37 #define MODETIMEOUT 3 // seconds
38 #define NEWTIMERLIMIT 120 // seconds until the start time of a new timer created from the Schedule menu,
41 #define DEFERTIMER 60 // seconds by which a timer is deferred in case of problems
43 #define MAXRECORDCONTROLS (MAXDEVICES * MAXRECEIVERS)
44 #define MAXINSTANTRECTIME (24 * 60 - 1) // 23:59 hours
45 #define MAXWAITFORCAMMENU 10 // seconds to wait for the CAM menu to open
46 #define CAMMENURETYTIMEOUT 3 // seconds after which opening the CAM menu is retried
47 #define CAMRESPONSETIMEOUT 5 // seconds to wait for a response from a CAM
48 #define MINFREEDISK 300 // minimum free disk space (in MB) required to start recording
49 #define NODISKSPACEDELTA 300 // seconds between "Not enough disk space to start recording!" messages
50 #define MAXCHNAMWIDTH 16 // maximum number of characters of channels' short names shown in schedules menus
52 #define CHNUMWIDTH (numdigits(Channels.MaxNumber()) + 1)
53 #define CHNAMWIDTH (min(MAXCHNAMWIDTH, Channels.MaxShortChannelNameLength() + 1))
59 virtual void Set(
void);
102 virtual void Set(
void);
286 virtual void Set(
void);
317 const cEvent *Event = NULL;
327 Event ?
'(' :
' ', Event ? Event->
Title() :
"", Event ?
')' :
' ');
330 Event ?
'(' :
' ', Event ? Event->
Title() :
"", Event ?
')' :
' ');
340 DisplayMenu->
SetItem(
Text(), Index, Current, Selectable);
345 #define CHANNELNUMBERTIMEOUT 1000 //ms
360 virtual void Move(
int From,
int To);
392 if (channel == currentChannel)
399 SetHelp(
tr(
"Button$Edit"),
tr(
"Button$New"),
tr(
"Button$Delete"),
tr(
"Button$Mark"));
431 if (!ci->Channel()->GroupSep() && ci->Channel()->Number() ==
number) {
476 int DeletedChannel = channel->
Number();
483 if (CurrentChannel && channel == CurrentChannel) {
488 CurrentChannelNr = 0;
494 isyslog(
"channel %d deleted", DeletedChannel);
495 if (CurrentChannel && CurrentChannel->
Number() != CurrentChannelNr) {
512 if (FromChannel && ToChannel) {
513 int FromNumber = FromChannel->
Number();
514 int ToNumber = ToChannel->
Number();
519 isyslog(
"channel %d moved to %d", FromNumber, ToNumber);
520 if (CurrentChannel && CurrentChannel->
Number() != CurrentChannelNr) {
580 text = Text ? strdup(Text) : NULL;
653 :
cOsdMenu(Folder ?
tr(
"Edit folder") :
tr(
"New folder"), 12)
686 if (strcmp(Folder->Text(),
name) == 0) {
691 char *p = strpbrk(
name,
"\\{}#~");
768 Add(FolderItem, CurrentFolder ? strcmp(Folder->Text(), CurrentFolder) == 0 :
false);
780 if (strncmp(Folder->Folder()->Text(), Path, p - Path) == 0) {
782 if (Folder->Folder()->SubItems())
954 memmove(
data.
file, p, strlen(p) + 1);
1021 virtual void Set(
void);
1050 localtime_r(&Day, &tm_r);
1052 strftime(buffer,
sizeof(buffer),
"%Y%m%d", &tm_r);
1061 char diskStatusString[2] = {
diskStatus, 0 };
1063 csc.
Convert(diskStatusString),
1067 *name && **name ?
" " :
"",
1079 DisplayMenu->
SetItem(
Text(), Index, Current, Selectable);
1161 timer->SetEventFromSchedule();
1179 return item ? item->
Timer() : NULL;
1184 int NewHelpKeys = 0;
1256 #define CHECK_2PTR_NULL(x_,y_) ((x_)? ((y_)? y_:""):"")
1264 char *parameter = NULL;
1270 pEvent = ti->
Event();
1280 iRecNumber=rc->
Index() + 1;
1284 asprintf(¶meter,
"%d '%s' %d %d '%s' '%s' '%s' %d", ti->
Index(),
1292 isyslog(
"timercmd: %s", parameter);
1308 if (ti && ti->
Event())
1319 int freeMB, freeMinutes, runshortMinutes;
1321 freeMinutes = int(
double(freeMB) * 1.1 / 25.75);
1322 runshortMinutes = freeMinutes / 5;
1332 for (entry = entries.
First(); entry; entry = entries.
Next(entry))
1336 for (entry = entries.
First(); entry; entry = entries.
Next(entry))
1346 for (entry = entries.
First(); entry; entry = entries.
Next(entry)) {
1350 status = freeMinutes > runshortMinutes ?
'+' : freeMinutes > 0 ? 177 :
'-';
1353 #ifdef DEBUG_TIMER_INFO
1354 dsyslog(
"timer-info: %c | %d | %s | %s | %3d | %+5d -> %+5d",
1357 entry->
active() ?
"aktiv " :
"n.akt.",
1358 entry->
repTimer() ? entry->
isDummy() ?
" dummy " :
"mehrmalig" :
"einmalig ",
1383 state =
OnOff();
break;
1421 SetHelp(TimerMatch ==
tmFull ?
tr(
"Button$Timer") :
tr(
"Button$Record"), NULL, NULL, CanSwitch ?
tr(
"Button$Switch") : NULL);
1482 bool Update(
bool Force =
false);
1512 bool result =
false;
1518 char v =
event->Vps() && (
event->Vps() -
event->StartTime()) ?
'V' :
' ';
1519 char r =
event->SeenWithin(30) &&
event->IsRunning() ?
'*' :
' ';
1521 cString eds =
event->GetDateString();
1523 buffer =
cString::sprintf(
"%d\t%.*s\t%.*s\t%s\t%c%c%c\t%s",
channel->
Number(),
Utf8SymChars(csn, 999), csn,
Utf8SymChars(eds, 6), *eds, *
event->GetTimeString(), t, v, r,
event->Title());
1537 DisplayMenu->
SetItem(
Text(), Index, Current, Selectable);
1573 if (!Channel->GroupSep()) {
1589 bool result =
false;
1602 int NewHelpKeys = 0;
1610 const char *Red[] = { NULL,
tr(
"Button$Record"),
tr(
"Button$Timer") };
1611 SetHelp(Red[NewHelpKeys],
now ?
tr(
"Button$Next") :
tr(
"Button$Now"),
tr(
"Button$Schedule"),
tr(
"Button$Switch"));
1696 if (HadSubMenu &&
Update())
1764 if (ev->EndTime() > now || ev == PresentEvent)
1781 if ((ev->EndTime() > now || ev == Event) && !strcmp(ev->Title(), Event->
Title()))
1799 if ((ev->EndTime() > now || ev == Event) && !strcmp(ev->Title(), Event->
Title()))
1818 if (ev->EndTime() > now || ev == Event)
1828 bool result =
false;
1841 int NewHelpKeys = 0;
1849 const char *Red[] = { NULL,
tr(
"Button$Record"),
tr(
"Button$Timer") };
1850 SetHelp(Red[NewHelpKeys],
tr(
"Button$Now"),
tr(
"Button$Next"));
1860 const cEvent *Event = NULL;
1862 Event = CurrentItem->
event;
1940 ChannelNr = channel->
Number();
1972 SetHelp(
Count() ?
tr(
"Button$Record") : NULL,
tr(
"Button$Now"),
tr(
"Button$Next"),
tr(
"Button$Switch"));
1977 else if (HadSubMenu &&
Update())
1996 const char *s = Command->Text();
1997 if (Command->SubItems())
2011 const char *p = strchr(s,
':');
2018 if (l > 1 && t[l - 1] ==
'?') {
2046 const char *cmd = *cmdbuf ? *cmdbuf : *
command;
2047 dsyslog(
"executing command '%s'", cmd);
2049 if (p.
Open(cmd,
"r")) {
2052 while ((c = fgetc(p)) != EOF) {
2054 if (
char *NewBuffer = (
char *)realloc(
result, l + 21))
2057 esyslog(
"ERROR: out of memory");
2068 esyslog(
"ERROR: can't open pipe for command '%s'", cmd);
2207 const char *p = strchr(s,
'\n');
2208 int l = p ? p - s : strlen(s);
2211 item->
SetText(strndup(s, l),
false);
2256 else if (state ==
osBack) {
2283 if (CamSlot->HasUserIO())
2384 if (*
Text() ==
'\t')
2404 DisplayMenu->
SetItem(
Text(), Index, Current, Selectable);
2452 Add(
new cOsdItem((dirSize > 9999) ? cString::sprintf(
"%s:\t%.2f GB%s",
tr(
"Size"), dirSize / 1024.0, *bitRate) : cString::sprintf(
"%s:\t%d MB%s",
tr(
"Size"), dirSize, *bitRate),
osUnknown,
false));
2461 isResume = (ResumeFile.Read() != -1);
2471 SetHelp(
tr(
"Button$Folder"),
tr(
"Button$Cut"),
tr(
"Button$Copy"),
tr(
"Button$Rename/Move"));
2487 memmove(
name, p, strlen(p) + 1);
2571 :
cOsdMenu(Base ? Base :
tr(
"Recordings"), 9, 6, 6)
2574 base = Base ? strdup(Base) : NULL;
2597 int NewHelpKeys = 0;
2608 switch (NewHelpKeys) {
2610 case 1:
SetHelp(
tr(
"Button$Open"));
break;
2626 CurrentRecording = ri->Recording()->FileName();
2638 if (p->Name() && strcmp(p->Name(), Item->
Name()) == 0) {
2644 if (*Item->
Text() && !LastDir) {
2652 if (LastItem || LastDir) {
2653 if (CurrentRecording && strcmp(CurrentRecording, recording->FileName()) == 0)
2679 const char *t = ri->
Name();
2757 if (!recording || recording->
Delete()) {
2860 virtual void Store(
void);
2893 virtual void Set(
void);
2978 bool ModifiedAppearance =
false;
2987 ModifiedAppearance =
true;
2996 ModifiedAppearance =
true;
2998 ModifiedAppearance =
true;
3003 ModifiedAppearance =
true;
3005 ModifiedAppearance =
true;
3007 ModifiedAppearance =
true;
3016 if (ModifiedAppearance) {
3112 for (k = 0; k < oldnumLanguages; k++) {
3116 if (k >= oldnumLanguages) {
3172 SetHelp(NULL,
tr(
"Button$Audio"),
tr(
"Button$Subtitles"), NULL);
3209 int oldPrimaryDVB =
::Setup.PrimaryDVB;
3210 int oldVideoDisplayFormat =
::Setup.VideoDisplayFormat;
3211 bool oldVideoFormat =
::Setup.VideoFormat;
3213 bool oldDisplaySubtitles =
::Setup.DisplaySubtitles;
3235 for (k = 0; k < oldnumAudioLanguages; k++) {
3239 if (k >= oldnumAudioLanguages) {
3253 for (k = 0; k < oldnumSubtitleLanguages; k++) {
3257 if (k >= oldnumSubtitleLanguages) {
3272 if (::
Setup.PrimaryDVB != oldPrimaryDVB)
3274 if (::
Setup.VideoDisplayFormat != oldVideoDisplayFormat)
3276 if (::
Setup.VideoFormat != oldVideoFormat)
3278 if (::
Setup.DisplaySubtitles != oldDisplaySubtitles)
3318 int NumSatDevices = 0;
3323 if (NumSatDevices > 1) {
3339 bool DeviceBondingsChanged =
false;
3349 else if (DeviceBondingsChanged)
3378 case msReset: CamName =
tr(
"CAM reset");
break;
3379 case msPresent: CamName =
tr(
"CAM present");
break;
3380 case msReady: CamName =
tr(
"CAM ready");
break;
3381 default: CamName =
"-";
break;
3385 if (strcmp(buffer,
Text()) != 0) {
3418 time_t t0 = time(NULL);
3513 virtual void Store(
void);
3591 for (
int i = 0; ; i++) {
3634 virtual void Set(
void);
3652 snprintf(buffer,
sizeof(buffer),
"%s - VDR %s",
tr(
"Setup"),
VDRVERSION);
3722 #define STOP_RECORDING trNOOP(" Stop recording ")
3789 for (
int i = 0; ; i++) {
3813 bool result =
false;
3816 if (Force || NewReplaying !=
replaying) {
3864 const char *s = NULL;
3951 default:
switch (Key) {
3953 case kRed:
if (!HadSubMenu)
3956 case kGreen:
if (!HadSubMenu) {
3961 case kYellow:
if (!HadSubMenu)
3964 case kBlue:
if (!HadSubMenu)
4018 int indexSubtitle = 0;
4022 case 2:
if (p->
type == 0x05)
4159 if (n <= ch->Number() && ch->
Number() < n + m) {
4194 int SaveGroup =
group;
4273 if ((Key & (k_Repeat |
k_Release)) == 0) {
4300 #define VOLUMETIMEOUT 1000 //ms
4301 #define MUTETIMEOUT 5000 //ms
4367 #define TRACKTIMEOUT 5000 //ms
4382 if (TrackId && TrackId->
id) {
4385 if (i == CurrentAudioTrack)
4434 int oldTrack =
track;
4451 static int ac[] = { 1, 0, 2 };
4478 if (
track != oldTrack) {
4503 if (TrackId && TrackId->
id) {
4506 if (i == CurrentSubtitleTrack)
4552 int oldTrack =
track;
4579 if (
track != oldTrack) {
4615 fileName = strdup(Recording.FileName());
4640 Recording.WriteInfo();
4646 char *Directory = strdup(
fileName);
4648 if (
char *p = strrchr(Directory,
'/')) {
4649 while (p > Directory && *--p !=
'/')
4653 dsyslog(
"setting %s to be sorted by time", Directory);
4678 #define INSTANT_REC_EPG_LOOKAHEAD 300 // seconds to look into the EPG data for an instant recording
4694 dsyslog(
"got EPG info after %d seconds", seconds);
4701 dsyslog(
"waiting for EPG info...");
4704 dsyslog(
"no EPG info available");
4715 if (ExecuteUserCommand)
4739 static time_t LastNoDiskSpaceMessage = 0;
4748 isyslog(
"not enough disk space to start recording%s%s", Timer ?
" timer " :
"", Timer ? *Timer->
ToDescr() :
"");
4750 LastNoDiskSpaceMessage = time(NULL);
4754 LastNoDiskSpaceMessage = 0;
4769 if (!Timer || Timer->
Matches()) {
4778 else if (!Timer || !Timer->
Pending()) {
4779 isyslog(
"no free DVB device to record channel %d!", ch);
4784 esyslog(
"ERROR: channel %d not defined!", ch);
4794 if (
id && strcmp(
id, InstantId) == 0) {
4812 if (
Start(NULL,
true)) {
4829 if (LastInstantId && LastInstantId ==
RecordControls[i]->InstantId())
4830 LastInstantId = NULL;
4874 isyslog(
"stopping recording due to modification of channel %d", Channel->
Number());
4903 int NewState =
state;
4904 bool Result = State != NewState;
4911 #define REPLAYCONTROLSKIPLIMIT 9 // s
4912 #define REPLAYCONTROLSKIPSECONDS 90 // s
4913 #define REPLAYCONTROLSKIPTIMEOUT 5000 // ms
4969 if (recording->
Delete()) {
5049 bool NormalPlay = (Play && Speed == -1);
5072 if (
GetIndex(Current, Total) && Total > 0) {
5090 Index = Current - Index;
5113 strcpy(buf,
tr(
"Jump: "));
5114 int len = strlen(buf);
5123 sprintf(buf + len,
"%c%c:%c%c", ch10, ch1, cm10, cm1);
5129 #define STAY_SECONDS_OFF_END 10
5201 if (
GetIndex(Current, Total,
true)) {
5210 Goto(Current,
true);
5225 Goto(m->Position(),
true);
5232 Goto(Forward ? Total : 0,
true);
5253 Goto(m->Position(),
true);
5287 if ((m->
Index() & 0x01) != 0)
5344 bool DoShowMode =
true;