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);
316 const cEvent *Event = NULL;
326 Event ?
'(' :
' ', Event ? Event->
Title() :
"", Event ?
')' :
' ');
329 Event ?
'(' :
' ', Event ? Event->
Title() :
"", Event ?
')' :
' ');
338 #define CHANNELNUMBERTIMEOUT 1000 //ms
353 virtual void Move(
int From,
int To);
385 if (channel == currentChannel)
392 SetHelp(
tr(
"Button$Edit"),
tr(
"Button$New"),
tr(
"Button$Delete"),
tr(
"Button$Mark"));
424 if (!ci->Channel()->GroupSep() && ci->Channel()->Number() ==
number) {
469 int DeletedChannel = channel->
Number();
476 if (CurrentChannel && channel == CurrentChannel) {
481 CurrentChannelNr = 0;
487 isyslog(
"channel %d deleted", DeletedChannel);
488 if (CurrentChannel && CurrentChannel->
Number() != CurrentChannelNr) {
505 if (FromChannel && ToChannel) {
506 int FromNumber = FromChannel->
Number();
507 int ToNumber = ToChannel->
Number();
512 isyslog(
"channel %d moved to %d", FromNumber, ToNumber);
513 if (CurrentChannel && CurrentChannel->
Number() != CurrentChannelNr) {
573 text = Text ? strdup(Text) : NULL;
646 :
cOsdMenu(Folder ?
tr(
"Edit folder") :
tr(
"New folder"), 12)
679 if (strcmp(Folder->Text(),
name) == 0) {
684 char *p = strpbrk(
name,
"\\{}#~");
761 Add(FolderItem, CurrentFolder ? strcmp(Folder->Text(), CurrentFolder) == 0 :
false);
773 if (strncmp(Folder->Folder()->Text(), Path, p - Path) == 0) {
775 if (Folder->Folder()->SubItems())
947 memmove(
data.
file, p, strlen(p) + 1);
1014 virtual void Set(
void);
1042 localtime_r(&Day, &tm_r);
1044 strftime(buffer,
sizeof(buffer),
"%Y%m%d", &tm_r);
1053 char diskStatusString[2] = {
diskStatus, 0 };
1055 csc.
Convert(diskStatusString),
1059 *name && **name ?
" " :
"",
1147 timer->SetEventFromSchedule();
1165 return item ? item->
Timer() : NULL;
1170 int NewHelpKeys = 0;
1242 #define CHECK_2PTR_NULL(x_,y_) ((x_)? ((y_)? y_:""):"")
1250 char *parameter = NULL;
1256 pEvent = ti->
Event();
1266 iRecNumber=rc->
Index() + 1;
1270 asprintf(¶meter,
"%d '%s' %d %d '%s' '%s' '%s' %d", ti->
Index(),
1278 isyslog(
"timercmd: %s", parameter);
1294 if (ti && ti->
Event())
1305 int freeMB, freeMinutes, runshortMinutes;
1307 freeMinutes = int(
double(freeMB) * 1.1 / 25.75);
1308 runshortMinutes = freeMinutes / 5;
1318 for (entry = entries.
First(); entry; entry = entries.
Next(entry))
1322 for (entry = entries.
First(); entry; entry = entries.
Next(entry))
1332 for (entry = entries.
First(); entry; entry = entries.
Next(entry)) {
1336 status = freeMinutes > runshortMinutes ?
'+' : freeMinutes > 0 ? 177 :
'-';
1339 #ifdef DEBUG_TIMER_INFO
1340 dsyslog(
"timer-info: %c | %d | %s | %s | %3d | %+5d -> %+5d",
1343 entry->
active() ?
"aktiv " :
"n.akt.",
1344 entry->
repTimer() ? entry->
isDummy() ?
" dummy " :
"mehrmalig" :
"einmalig ",
1369 state =
OnOff();
break;
1407 SetHelp(TimerMatch ==
tmFull ?
tr(
"Button$Timer") :
tr(
"Button$Record"), NULL, NULL, CanSwitch ?
tr(
"Button$Switch") : NULL);
1468 bool Update(
bool Force =
false);
1497 bool result =
false;
1503 char v =
event->Vps() && (
event->Vps() -
event->StartTime()) ?
'V' :
' ';
1504 char r =
event->SeenWithin(30) &&
event->IsRunning() ?
'*' :
' ';
1506 cString eds =
event->GetDateString();
1508 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());
1552 if (!Channel->GroupSep()) {
1568 bool result =
false;
1581 int NewHelpKeys = 0;
1589 const char *Red[] = { NULL,
tr(
"Button$Record"),
tr(
"Button$Timer") };
1590 SetHelp(Red[NewHelpKeys],
now ?
tr(
"Button$Next") :
tr(
"Button$Now"),
tr(
"Button$Schedule"),
tr(
"Button$Switch"));
1675 if (HadSubMenu &&
Update())
1743 if (ev->EndTime() > now || ev == PresentEvent)
1760 if ((ev->EndTime() > now || ev == Event) && !strcmp(ev->Title(), Event->
Title()))
1778 if ((ev->EndTime() > now || ev == Event) && !strcmp(ev->Title(), Event->
Title()))
1797 if (ev->EndTime() > now || ev == Event)
1807 bool result =
false;
1820 int NewHelpKeys = 0;
1828 const char *Red[] = { NULL,
tr(
"Button$Record"),
tr(
"Button$Timer") };
1829 SetHelp(Red[NewHelpKeys],
tr(
"Button$Now"),
tr(
"Button$Next"));
1839 const cEvent *Event = NULL;
1841 Event = CurrentItem->
event;
1919 ChannelNr = channel->
Number();
1951 SetHelp(
Count() ?
tr(
"Button$Record") : NULL,
tr(
"Button$Now"),
tr(
"Button$Next"),
tr(
"Button$Switch"));
1956 else if (HadSubMenu &&
Update())
1975 const char *s = Command->Text();
1976 if (Command->SubItems())
1990 const char *p = strchr(s,
':');
1997 if (l > 1 && t[l - 1] ==
'?') {
2025 const char *cmd = *cmdbuf ? *cmdbuf : *
command;
2026 dsyslog(
"executing command '%s'", cmd);
2028 if (p.
Open(cmd,
"r")) {
2031 while ((c = fgetc(p)) != EOF) {
2033 if (
char *NewBuffer = (
char *)realloc(
result, l + 21))
2036 esyslog(
"ERROR: out of memory");
2047 esyslog(
"ERROR: can't open pipe for command '%s'", cmd);
2186 const char *p = strchr(s,
'\n');
2187 int l = p ? p - s : strlen(s);
2190 item->
SetText(strndup(s, l),
false);
2235 else if (state ==
osBack) {
2262 if (CamSlot->HasUserIO())
2360 if (*
Text() ==
'\t')
2361 name = strdup(
Text() + 2);
2423 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));
2432 isResume = (ResumeFile.Read() != -1);
2442 SetHelp(
tr(
"Button$Folder"),
tr(
"Button$Cut"),
tr(
"Button$Copy"),
tr(
"Button$Rename/Move"));
2458 memmove(
name, p, strlen(p) + 1);
2542 :
cOsdMenu(Base ? Base :
tr(
"Recordings"), 9, 6, 6)
2545 base = Base ? strdup(Base) : NULL;
2568 int NewHelpKeys = 0;
2575 if (recording && recording->
Info()->
Title())
2580 switch (NewHelpKeys) {
2582 case 1:
SetHelp(
tr(
"Button$Open"));
break;
2595 char *LastItemText = NULL;
2602 CurrentRecording = Recording->
FileName();
2615 LastItemText = strdup(LastItem->
Text());
2620 if (CurrentRecording && strcmp(CurrentRecording, recording->FileName()) == 0)
2655 const char *t = ri->
Name();
2739 if (!recording || recording->
Delete()) {
2764 if (recording && recording->
Info()->
Title())
2851 virtual void Store(
void);
2884 virtual void Set(
void);
2967 bool ModifiedAppearance =
false;
2976 ModifiedAppearance =
true;
2985 ModifiedAppearance =
true;
2987 ModifiedAppearance =
true;
2992 ModifiedAppearance =
true;
2994 ModifiedAppearance =
true;
2996 ModifiedAppearance =
true;
3003 if (ModifiedAppearance) {
3098 for (k = 0; k < oldnumLanguages; k++) {
3102 if (k >= oldnumLanguages) {
3157 SetHelp(NULL,
tr(
"Button$Audio"),
tr(
"Button$Subtitles"), NULL);
3194 int oldPrimaryDVB =
::Setup.PrimaryDVB;
3195 int oldVideoDisplayFormat =
::Setup.VideoDisplayFormat;
3196 bool oldVideoFormat =
::Setup.VideoFormat;
3198 bool oldDisplaySubtitles =
::Setup.DisplaySubtitles;
3220 for (k = 0; k < oldnumAudioLanguages; k++) {
3224 if (k >= oldnumAudioLanguages) {
3238 for (k = 0; k < oldnumSubtitleLanguages; k++) {
3242 if (k >= oldnumSubtitleLanguages) {
3257 if (::
Setup.PrimaryDVB != oldPrimaryDVB)
3259 if (::
Setup.VideoDisplayFormat != oldVideoDisplayFormat)
3261 if (::
Setup.VideoFormat != oldVideoFormat)
3263 if (::
Setup.DisplaySubtitles != oldDisplaySubtitles)
3302 int NumSatDevices = 0;
3307 if (NumSatDevices > 1) {
3308 for (
int i = 0; i < cDevice::NumDevices(); i++) {
3321 bool DeviceBondingsChanged =
false;
3331 else if (DeviceBondingsChanged)
3360 case msReset: CamName =
tr(
"CAM reset");
break;
3361 case msPresent: CamName =
tr(
"CAM present");
break;
3362 case msReady: CamName =
tr(
"CAM ready");
break;
3363 default: CamName =
"-";
break;
3367 if (strcmp(buffer,
Text()) != 0) {
3399 time_t t0 = time(NULL);
3494 virtual void Store(
void);
3568 for (
int i = 0; ; i++) {
3611 virtual void Set(
void);
3629 snprintf(buffer,
sizeof(buffer),
"%s - VDR %s",
tr(
"Setup"),
VDRVERSION);
3699 #define STOP_RECORDING trNOOP(" Stop recording ")
3766 for (
int i = 0; ; i++) {
3790 bool result =
false;
3793 if (Force || NewReplaying !=
replaying) {
3841 const char *s = NULL;
3928 default:
switch (Key) {
3930 case kRed:
if (!HadSubMenu)
3933 case kGreen:
if (!HadSubMenu) {
3938 case kYellow:
if (!HadSubMenu)
3941 case kBlue:
if (!HadSubMenu)
3995 int indexSubtitle = 0;
3999 case 2:
if (p->
type == 0x05)
4136 if (n <= ch->Number() && ch->
Number() < n + m) {
4171 int SaveGroup =
group;
4250 if ((Key & (k_Repeat |
k_Release)) == 0) {
4277 #define VOLUMETIMEOUT 1000 //ms
4278 #define MUTETIMEOUT 5000 //ms
4344 #define TRACKTIMEOUT 5000 //ms
4359 if (TrackId && TrackId->
id) {
4362 if (i == CurrentAudioTrack)
4411 int oldTrack =
track;
4428 static int ac[] = { 1, 0, 2 };
4455 if (
track != oldTrack) {
4480 if (TrackId && TrackId->
id) {
4483 if (i == CurrentSubtitleTrack)
4529 int oldTrack =
track;
4556 if (
track != oldTrack) {
4592 fileName = strdup(Recording.FileName());
4617 Recording.WriteInfo();
4623 char *Directory = strdup(
fileName);
4625 if (
char *p = strrchr(Directory,
'/')) {
4626 while (p > Directory && *--p !=
'/')
4630 dsyslog(
"setting %s to be sorted by time", Directory);
4655 #define INSTANT_REC_EPG_LOOKAHEAD 300 // seconds to look into the EPG data for an instant recording
4671 dsyslog(
"got EPG info after %d seconds", seconds);
4678 dsyslog(
"waiting for EPG info...");
4681 dsyslog(
"no EPG info available");
4692 if (ExecuteUserCommand)
4716 static time_t LastNoDiskSpaceMessage = 0;
4725 isyslog(
"not enough disk space to start recording%s%s", Timer ?
" timer " :
"", Timer ? *Timer->
ToDescr() :
"");
4727 LastNoDiskSpaceMessage = time(NULL);
4731 LastNoDiskSpaceMessage = 0;
4746 if (!Timer || Timer->
Matches()) {
4755 else if (!Timer || !Timer->
Pending()) {
4756 isyslog(
"no free DVB device to record channel %d!", ch);
4761 esyslog(
"ERROR: channel %d not defined!", ch);
4771 if (
id && strcmp(
id, InstantId) == 0) {
4789 if (
Start(NULL,
true)) {
4806 if (LastInstantId && LastInstantId ==
RecordControls[i]->InstantId())
4807 LastInstantId = NULL;
4851 isyslog(
"stopping recording due to modification of channel %d", Channel->
Number());
4880 int NewState =
state;
4881 bool Result = State != NewState;
4888 #define REPLAYCONTROLSKIPLIMIT 9 // s
4889 #define REPLAYCONTROLSKIPSECONDS 90 // s
4890 #define REPLAYCONTROLSKIPTIMEOUT 5000 // ms
4946 if (recording->
Delete()) {
5020 bool NormalPlay = (Play && Speed == -1);
5043 if (
GetIndex(Current, Total) && Total > 0) {
5061 Index = Current - Index;
5084 strcpy(buf,
tr(
"Jump: "));
5085 int len = strlen(buf);
5094 sprintf(buf + len,
"%c%c:%c%c", ch10, ch1, cm10, cm1);
5100 #define STAY_SECONDS_OFF_END 10
5169 if (
GetIndex(Current, Total,
true)) {
5179 Goto(Current,
true);
5193 bool Play2, Forward2;
5311 bool DoShowMode =
true;