Version 0.93

- The menus and the channel display now show the current date and time.
- The new Setup parameter MaxVideoFileSize can be used to customize the
  maximum size of the recorded video files.
- Fixed a bug in handling repeating timers that record over midnight (the
  calculation of matching timers has been completely rewritten).
- Timers that are currently recording are now marked with '#' in the "Timers"
  menu.
- Timers are now sorted in the "Timers" menu, showing the sequence in which
  they will be recording. This can be disabled in the "Setup" menu. Note
  that the "Mark" button doesn't work if timers are displayed sorted.
This commit is contained in:
Klaus Schmidinger 2001-08-26 18:00:00 +02:00
parent 371bf0665e
commit ae8fe25312
16 changed files with 342 additions and 115 deletions

13
HISTORY
View File

@ -663,3 +663,16 @@ Video Disk Recorder Revision History
- Fixed broken recordings after a driver buffer overflow.
- Fixed the chirping sound after Pause/Play of a DVD (thanks to Andreas
Schultz).
2001-08-26: Version 0.93
- The menus and the channel display now show the current date and time.
- The new Setup parameter MaxVideoFileSize can be used to customize the
maximum size of the recorded video files.
- Fixed a bug in handling repeating timers that record over midnight (the
calculation of matching timers has been completely rewritten).
- Timers that are currently recording are now marked with '#' in the "Timers"
menu.
- Timers are now sorted in the "Timers" menu, showing the sequence in which
they will be recording. This can be disabled in the "Setup" menu. Note
that the "Mark" button doesn't work if timers are displayed sorted.

25
MANUAL
View File

@ -8,7 +8,7 @@ Video Disk Recorder User's Manual
possible, several keys have different meanings in the various
modes:
Key Normal Main Channels Timer Edit/New Recordings Replay
Key Normal Main Channels Timers Edit/New Recordings Replay
Up Ch up Crsr up Crsr up Crsr up Crsr up Crsr up Play
Down Ch down Crsr down Crsr down Crsr down Crsr down Crsr down Pause
@ -20,9 +20,12 @@ Video Disk Recorder User's Manual
Red - Record Edit Edit - Play Jump
Green - Language New New - Rewind Skip -60s
Yellow - Eject DVD Delete Delete - Delete Skip +60s
Blue - Resume Mark Mark - Summary Stop
Blue - Resume Mark Mark(1) - Summary Stop
0..9 Ch select - - - Numeric inp. - Editing
(1) The "Mark" button in the "Timers" menu only works if sorting the timers
has been disabled in the "Setup" menu.
* Navigating through the On Screen Menus
The "Main" menu can be called up with the "Menu" key of your remote
@ -34,7 +37,8 @@ Video Disk Recorder User's Manual
any changes that might have been made in the current menu.
In the "Timers" menu, the current timer can be enabled or disabled with
the "Right" or "Left" key, respectively (enabled timers are marked with ">").
the "Right" or "Left" key, respectively (enabled timers are marked with '>',
timers that are currently recording are marked with '#').
"Ok" here opens the "Edit timer" menu.
Textual options, like channel names or recording file names, can be edited
@ -296,6 +300,12 @@ Video Disk Recorder User's Manual
OSDLanguage = 0 Defines the language used to display the OSD texts.
0 = Englisch
1 = Deutsch
2 = Slovenian
3 = Italian
4 = Dutch
5 = Portugese
6 = French
7 = Norwegian
PrimaryDVB = 1 Defines the primary DVB interface (i.e. the one that
will display the menus and will react on input through
@ -373,6 +383,10 @@ Video Disk Recorder User's Manual
connection after which the connection is automatically
closed. Default is 300, a value of 0 means no timeout.
SortTimers = 1 Turns sorting the timers in the "Timers" menu on/off.
Timers are sorted by ascending start times, with the
first one being the next timer that will start.
PrimaryLimit = 0 The minimum priority a timer must have to be allowed to
use the primary DVB interface, or to force another timer
with higher priority to use the primary DVB interface.
@ -398,6 +412,11 @@ Video Disk Recorder User's Manual
OSDwidth = 52 The width and height of the OSD .
OSDheight = 18 The valid ranges are width=40...56, height=12...21.
MaxVideoFileSize=2000 The maximum size of a single recorded video file in MB.
The valid range is 100...2000. Default is 2000, but
you may want to use smaller values if you are planning
on archiving a recording to CD.
* Executing system commands
The "Main" menu option "Commands" allows you to execute any system commands

View File

@ -192,4 +192,6 @@ Video Italia:12610:v:0:22000:121:122:0:0:12220
AC 3 promo:12670:v:0:22000:308:256:0:0:0
ORF/ZDF:12699:h:0:22000:506:507:0:0:13012
VIVA:12670:v:0:22000:309:310:0:0:12732
VIVA2:12552:v:0:22000:171:172:0:0:12120
MTV Central Europe:12699:v:0:22000:3031:3032:0:0:28643
IFA-TV:10832:h:0:22000:132:133:32:0:7251

155
config.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: config.c 1.55 2001/08/17 13:02:01 kls Exp $
* $Id: config.c 1.59 2001/08/26 14:46:43 kls Exp $
*/
#include "config.h"
@ -394,6 +394,13 @@ cTimer& cTimer::operator= (const cTimer &Timer)
return *this;
}
bool cTimer::operator< (const cTimer &Timer)
{
time_t t1 = StartTime();
time_t t2 = (*(cTimer *)&Timer).StartTime();
return t1 < t2 || (t1 == t2 && priority > Timer.priority);
}
const char *cTimer::ToText(cTimer *Timer)
{
delete buffer;
@ -415,13 +422,6 @@ int cTimer::TimeToInt(int t)
return (t / 100 * 60 + t % 100) * 60;
}
time_t cTimer::Day(time_t t)
{
struct tm d = *localtime(&t);
d.tm_hour = d.tm_min = d.tm_sec = 0;
return mktime(&d);
}
int cTimer::ParseDay(const char *s)
{
char *tail;
@ -511,43 +511,66 @@ bool cTimer::IsSingleEvent(void)
return (day & 0x80000000) == 0;
}
int cTimer::GetMDay(time_t t)
{
return localtime(&t)->tm_mday;
}
int cTimer::GetWDay(time_t t)
{
int weekday = localtime(&t)->tm_wday;
return weekday == 0 ? 6 : weekday - 1; // we start with monday==0!
}
bool cTimer::DayMatches(time_t t)
{
return IsSingleEvent() ? GetMDay(t) == day : (day & (1 << GetWDay(t))) != 0;
}
time_t cTimer::IncDay(time_t t, int Days)
{
tm tm = *localtime(&t);
tm.tm_mday += Days; // now tm_mday may be out of its valid range
int h = tm.tm_hour; // save original hour to compensate for DST change
t = mktime(&tm); // normalize all values
tm.tm_hour = h; // compensate for DST change
return mktime(&tm); // calculate final result
}
time_t cTimer::SetTime(time_t t, int SecondsFromMidnight)
{
tm tm = *localtime(&t);
tm.tm_hour = SecondsFromMidnight / 3600;
tm.tm_min = (SecondsFromMidnight % 3600) / 60;
tm.tm_sec = SecondsFromMidnight % 60;
return mktime(&tm);
}
bool cTimer::Matches(time_t t)
{
if (active) {
if (t == 0)
t = time(NULL);
struct tm now = *localtime(&t);
int weekday = now.tm_wday == 0 ? 6 : now.tm_wday - 1; // we start with monday==0!
int begin = TimeToInt(start);
int end = TimeToInt(stop);
bool twoDays = (end < begin);
startTime = stopTime = 0;
if (t == 0)
t = time(NULL);
bool todayMatches = false, yesterdayMatches = false;
if ((day & 0x80000000) != 0) {
if ((day & (1 << weekday)) != 0)
todayMatches = true;
else if (twoDays) {
int yesterday = weekday == 0 ? 6 : weekday - 1;
if ((day & (1 << yesterday)) != 0)
yesterdayMatches = true;
}
}
else if (day == now.tm_mday)
todayMatches = true;
else if (twoDays) {
time_t ty = t - SECSINDAY;
if (day == localtime(&ty)->tm_mday)
yesterdayMatches = true;
}
if (todayMatches || (twoDays && yesterdayMatches)) {
startTime = Day(t - (yesterdayMatches ? SECSINDAY : 0)) + begin;
stopTime = startTime + (twoDays ? SECSINDAY - begin + end : end - begin);
}
else
startTime = stopTime = 0;
return startTime <= t && t <= stopTime;
}
return false;
int begin = TimeToInt(start); // seconds from midnight
int length = TimeToInt(stop) - begin;
if (length < 0)
length += SECSINDAY;
int DaysToCheck = IsSingleEvent() ? 31 : 7;
for (int i = -1; i <= DaysToCheck; i++) {
time_t t0 = IncDay(t, i);
if (DayMatches(t0)) {
time_t a = SetTime(t0, begin);
time_t b = a + length;
if (t <= b) {
startTime = a;
stopTime = b;
break;
}
}
}
return active && startTime <= t && t <= stopTime;
}
time_t cTimer::StartTime(void)
@ -575,21 +598,6 @@ void cTimer::SetPending(bool Pending)
pending = Pending;
}
cTimer *cTimer::GetMatch(void)
{
time_t t = time(NULL); // all timers must be checked against the exact same time to correctly handle Priority!
cTimer *t0 = NULL;
cTimer *ti = (cTimer *)Timers.First();
while (ti) {
if (!ti->recording && ti->Matches(t)) {
if (!t0 || ti->priority > t0->priority)
t0 = ti;
}
ti = (cTimer *)ti->Next();
}
return t0;
}
// --- cCommand -------------------------------------------------------------
char *cCommand::result = NULL;
@ -753,6 +761,33 @@ cTimer *cTimers::GetTimer(cTimer *Timer)
return NULL;
}
cTimer *cTimers::GetMatch(void)
{
time_t t = time(NULL); // all timers must be checked against the exact same time to correctly handle Priority!
cTimer *t0 = NULL;
cTimer *ti = First();
while (ti) {
if (!ti->recording && ti->Matches(t)) {
if (!t0 || ti->priority > t0->priority)
t0 = ti;
}
ti = (cTimer *)ti->Next();
}
return t0;
}
cTimer *cTimers::GetNextActiveTimer(void)
{
cTimer *t0 = NULL;
cTimer *ti = First();
while (ti) {
if (ti->active && (!t0 || *ti < *t0))
t0 = ti;
ti = (cTimer *)ti->Next();
}
return t0;
}
// -- cSetup -----------------------------------------------------------------
cSetup Setup;
@ -776,6 +811,7 @@ cSetup::cSetup(void)
EPGScanTimeout = 5;
EPGBugfixLevel = 2;
SVDRPTimeout = 300;
SortTimers = 1;
PrimaryLimit = 0;
DefaultPriority = 50;
DefaultLifetime = 50;
@ -783,6 +819,7 @@ cSetup::cSetup(void)
ChannelInfoPos = 0;
OSDwidth = 52;
OSDheight = 18;
MaxVideoFileSize = MAXVIDEOFILESIZE;
CurrentChannel = -1;
}
@ -807,6 +844,7 @@ bool cSetup::Parse(char *s)
else if (!strcasecmp(Name, "EPGScanTimeout")) EPGScanTimeout = atoi(Value);
else if (!strcasecmp(Name, "EPGBugfixLevel")) EPGBugfixLevel = atoi(Value);
else if (!strcasecmp(Name, "SVDRPTimeout")) SVDRPTimeout = atoi(Value);
else if (!strcasecmp(Name, "SortTimers")) SortTimers = atoi(Value);
else if (!strcasecmp(Name, "PrimaryLimit")) PrimaryLimit = atoi(Value);
else if (!strcasecmp(Name, "DefaultPriority")) DefaultPriority = atoi(Value);
else if (!strcasecmp(Name, "DefaultLifetime")) DefaultLifetime = atoi(Value);
@ -814,6 +852,7 @@ bool cSetup::Parse(char *s)
else if (!strcasecmp(Name, "ChannelInfoPos")) ChannelInfoPos = atoi(Value);
else if (!strcasecmp(Name, "OSDwidth")) OSDwidth = atoi(Value);
else if (!strcasecmp(Name, "OSDheight")) OSDheight = atoi(Value);
else if (!strcasecmp(Name, "MaxVideoFileSize")) MaxVideoFileSize = atoi(Value);
else if (!strcasecmp(Name, "CurrentChannel")) CurrentChannel = atoi(Value);
else
return false;
@ -873,6 +912,7 @@ bool cSetup::Save(const char *FileName)
fprintf(f, "EPGScanTimeout = %d\n", EPGScanTimeout);
fprintf(f, "EPGBugfixLevel = %d\n", EPGBugfixLevel);
fprintf(f, "SVDRPTimeout = %d\n", SVDRPTimeout);
fprintf(f, "SortTimers = %d\n", SortTimers);
fprintf(f, "PrimaryLimit = %d\n", PrimaryLimit);
fprintf(f, "DefaultPriority = %d\n", DefaultPriority);
fprintf(f, "DefaultLifetime = %d\n", DefaultLifetime);
@ -880,6 +920,7 @@ bool cSetup::Save(const char *FileName)
fprintf(f, "ChannelInfoPos = %d\n", ChannelInfoPos);
fprintf(f, "OSDwidth = %d\n", OSDwidth);
fprintf(f, "OSDheight = %d\n", OSDheight);
fprintf(f, "MaxVideoFileSize = %d\n", MaxVideoFileSize);
fprintf(f, "CurrentChannel = %d\n", CurrentChannel);
f.Close();
isyslog(LOG_INFO, "saved setup to %s", FileName);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: config.h 1.61 2001/08/17 13:00:48 kls Exp $
* $Id: config.h 1.66 2001/08/26 14:46:53 kls Exp $
*/
#ifndef __CONFIG_H
@ -19,7 +19,7 @@
#include "eit.h"
#include "tools.h"
#define VDRVERSION "0.92"
#define VDRVERSION "0.93"
#define MaxBuffer 10000
@ -137,18 +137,22 @@ public:
cTimer(const cEventInfo *EventInfo);
virtual ~cTimer();
cTimer& operator= (const cTimer &Timer);
bool operator< (const cTimer &Timer);
const char *ToText(void);
bool Parse(const char *s);
bool Save(FILE *f);
bool IsSingleEvent(void);
int GetMDay(time_t t);
int GetWDay(time_t t);
bool DayMatches(time_t t);
time_t IncDay(time_t t, int Days);
time_t SetTime(time_t t, int SecondsFromMidnight);
bool Matches(time_t t = 0);
time_t StartTime(void);
time_t StopTime(void);
void SetRecording(bool Recording);
void SetPending(bool Pending);
static cTimer *GetMatch(void);
static int TimeToInt(int t);
static time_t Day(time_t t);
static int ParseDay(const char *s);
static const char *PrintDay(int d);
};
@ -251,6 +255,8 @@ public:
class cTimers : public cConfig<cTimer> {
public:
cTimer *GetTimer(cTimer *Timer);
cTimer *GetMatch(void);
cTimer *GetNextActiveTimer(void);
};
class cCommands : public cConfig<cCommand> {};
@ -282,11 +288,13 @@ public:
int EPGScanTimeout;
int EPGBugfixLevel;
int SVDRPTimeout;
int SortTimers;
int PrimaryLimit;
int DefaultPriority, DefaultLifetime;
int VideoFormat;
int ChannelInfoPos;
int OSDwidth, OSDheight;
int MaxVideoFileSize;
int CurrentChannel;
cSetup(void);
bool Load(const char *FileName);

View File

@ -7,7 +7,7 @@
* DVD support initially written by Andreas Schultz <aschultz@warp10.net>
* based on dvdplayer-0.5 by Matjaz Thaler <matjaz.thaler@guest.arnes.si>
*
* $Id: dvbapi.c 1.109 2001/08/19 15:09:48 kls Exp $
* $Id: dvbapi.c 1.110 2001/08/25 13:52:38 kls Exp $
*/
//#define DVDDEBUG 1
@ -50,20 +50,16 @@ extern "C" {
#define DEV_OST_VIDEO "/dev/ost/video"
#define DEV_OST_AUDIO "/dev/ost/audio"
#define KILOBYTE(n) ((n) * 1024)
#define MEGABYTE(n) ((n) * 1024 * 1024)
// The size of the array used to buffer video data:
// (must be larger than MINVIDEODATA - see remux.h)
#define VIDEOBUFSIZE (1024*1024)
#define VIDEOBUFSIZE MEGABYTE(1)
// The maximum size of a single frame:
#define MAXFRAMESIZE (192*1024)
#define MAXFRAMESIZE KILOBYTE(192)
// The maximum file size is limited by the range that can be covered
// with 'int'. 4GB might be possible (if the range is considered
// 'unsigned'), 2GB should be possible (even if the range is considered
// 'signed'), so let's use 1GB for absolute safety (the actual file size
// may be slightly higher because we stop recording only before the next
// 'I' frame, to have a complete Group Of Pictures):
#define MAXVIDEOFILESIZE (1024*1024*1024) // Byte
#define MAXFILESPERRECORDING 255
#define MINFREEDISKSPACE (512) // MB
@ -517,7 +513,7 @@ bool cRecordBuffer::RunningLowOnDiskSpace(void)
bool cRecordBuffer::NextFile(void)
{
if (recordFile >= 0 && pictureType == I_FRAME) { // every file shall start with an I_FRAME
if (fileSize > MAXVIDEOFILESIZE || RunningLowOnDiskSpace()) {
if (fileSize > MEGABYTE(Setup.MaxVideoFileSize) || RunningLowOnDiskSpace()) {
recordFile = fileName.NextFile();
fileSize = 0;
}
@ -2217,7 +2213,7 @@ void cCuttingBuffer::Action(void)
// Write one frame:
if (PictureType == I_FRAME) { // every file shall start with an I_FRAME
if (FileSize > MAXVIDEOFILESIZE) {
if (FileSize > MEGABYTE(Setup.MaxVideoFileSize)) {
toFile = toFileName->NextFile();
if (toFile < 0)
break;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: dvbapi.h 1.46 2001/08/11 12:22:01 kls Exp $
* $Id: dvbapi.h 1.47 2001/08/25 13:37:00 kls Exp $
*/
#ifndef __DVBAPI_H
@ -42,6 +42,15 @@ typedef struct CRect {
#define FRAMESPERSEC 25
// The maximum file size is limited by the range that can be covered
// with 'int'. 4GB might be possible (if the range is considered
// 'unsigned'), 2GB should be possible (even if the range is considered
// 'signed'), so let's use 2000MB for absolute safety (the actual file size
// may be slightly higher because we stop recording only before the next
// 'I' frame, to have a complete Group Of Pictures):
#define MAXVIDEOFILESIZE 2000 // MB
#define MINVIDEOFILESIZE 100 // MB
const char *IndexToHMSF(int Index, bool WithFrame = false);
// Converts the given index to a string, optionally containing the frame number.
int HMSFToIndex(const char *HMSF);

29
i18n.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: i18n.c 1.32 2001/08/17 13:03:15 kls Exp $
* $Id: i18n.c 1.35 2001/08/26 13:45:10 kls Exp $
*
* Slovenian translations provided by Miha Setina <mihasetina@softhome.net>
* Italian translations provided by Alberto Carraro <bertocar@tin.it>
@ -794,6 +794,15 @@ const tPhrase Phrases[] = {
"Temps maxi SVDRP",
"Ubrukt SVDRP-levetid",
},
{ "SortTimers",
"Timer sortieren",
"", // TODO
"", // TODO
"", // TODO
"", // TODO
"", // TODO
"", // TODO
},
{ "PrimaryLimit",
"Primär-Limit",
"", // TODO
@ -857,6 +866,15 @@ const tPhrase Phrases[] = {
"Hauteur affichage",
"", // TODO
},
{ "MaxVideoFileSize",
"Max. Video Dateigröße",
"", // TODO
"", // TODO
"", // TODO
"", // TODO
"", // TODO
"", // TODO
},
// The days of the week:
{ "MTWTFSS",
"MDMDFSS",
@ -867,6 +885,15 @@ const tPhrase Phrases[] = {
"LMMJVSD",
"MTOTFLS",
},
{ "MonTueWedThuFriSatSun", // must all be 3 letters!
"MonDieMitDonFreSamSon",
"", // TODO
"", // TODO
"", // TODO
"", // TODO
"", // TODO
"", // TODO
},
// Learning keys:
{ "Learning Remote Control Keys",
"Fernbedienungs-Codes lernen",

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: interface.c 1.40 2001/08/07 16:23:28 kls Exp $
* $Id: interface.c 1.41 2001/08/25 13:15:00 kls Exp $
*/
#include "interface.h"
@ -271,7 +271,7 @@ void cInterface::Title(const char *s)
unsigned int n = t - s;
if (n >= sizeof(buffer))
n = sizeof(buffer) - 1;
strn0cpy(buffer, s, n);
strn0cpy(buffer, s, n + 1);
Write(1, 0, buffer, clrBlack, clrCyan);
t++;
Write(-(cDvbApi::PrimaryDvbApi->WidthInCells(t) + 1), 0, t, clrBlack, clrCyan);

55
libdtv/x.txt Normal file
View File

@ -0,0 +1,55 @@
Hallo ZDF-EPG-Redaktion!
Es würde mich interessieren, warum im digitalen EPG des
ZDF (über Astra) die Beschreibung der Sendungen oftmals
Trennungsstriche und zusätzliche Leerzeichen enthält.
So zum Beispiel bei folgendem Eintrag:
----------------------------------------------------
ZDF 23.08 10:50 - 11:35
Mit Leib und Seele
Der einzige Mensch
Stehlin hat die Frühmesse abge- sagt und sein
Kommen im Pfarr- haus angekündigt. August, erbost
über die Heimlichkeiten und Re- dereien von
Stutz, erzwingt eine Aussprache mit Stehlin.
----------------------------------------------------
der ohne Trennungsstriche so aussehen könnte:
----------------------------------------------------
ZDF 23.08 10:50 - 11:35
Mit Leib und Seele
Der einzige Mensch
Stehlin hat die Frühmesse abgesagt und sein
Kommen im Pfarrhaus angekündigt. August, erbost
über die Heimlichkeiten und Redereien von Stutz,
erzwingt eine Aussprache mit Stehlin.
----------------------------------------------------
Ich kann mir das nur so erklären, daß Sie konkrete Annahmen
darüber machen, mit welcher Zeilenlänge die Set-Top-Box diese
Texte darstellt - aber das ist in meinen Augen eine ziemlich
verwegene Annahme, denn es sollte ja wohl der STB überlassen bleiben,
wie groß das Fenster für die Darstellung des EPG ist.
Pro-7 zum Beispiel macht sowas nicht, wodurch der Text deultich
besser dargestellt wird.
Wenn Sie wenigstens nach dem (bzw. statt des) Bindestrich(s) ein deutlich
erkennbares Sonderzeichen einfügen würden, dann könnte man das zuverlässig
herausfiltern, aber so macht der ZDF-EPG immer wieder einen
schlechten Eindruck.
Über eine Antwort von Ihnen würde ich mich sehr freuen.
MfG
Klaus Schmidinger

66
menu.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: menu.c 1.105 2001/08/19 14:45:31 kls Exp $
* $Id: menu.c 1.109 2001/08/26 14:03:27 kls Exp $
*/
#include "menu.h"
@ -957,25 +957,30 @@ eOSState cMenuEditTimer::ProcessKey(eKeys Key)
class cMenuTimerItem : public cOsdItem {
private:
int index;
cTimer *timer;
public:
cMenuTimerItem(int Index, cTimer *Timer);
cMenuTimerItem(cTimer *Timer);
virtual bool operator< (const cListObject &ListObject);
virtual void Set(void);
cTimer *Timer(void) { return timer; }
};
cMenuTimerItem::cMenuTimerItem(int Index, cTimer *Timer)
cMenuTimerItem::cMenuTimerItem(cTimer *Timer)
{
index = Index;
timer = Timer;
Set();
}
bool cMenuTimerItem::operator< (const cListObject &ListObject)
{
return *timer < *((cMenuTimerItem *)&ListObject)->timer;
}
void cMenuTimerItem::Set(void)
{
char *buffer = NULL;
asprintf(&buffer, "%c\t%d\t%s\t%02d:%02d\t%02d:%02d\t%s",
timer->active ? '>' : ' ',
timer->active ? timer->recording ? '#' : '>' : ' ',
timer->channel,
timer->PrintDay(timer->day),
timer->start / 100,
@ -996,6 +1001,7 @@ private:
eOSState Del(void);
virtual void Move(int From, int To);
eOSState Summary(void);
cTimer *CurrentTimer(void);
public:
cMenuTimers(void);
virtual eOSState ProcessKey(eKeys Key);
@ -1008,15 +1014,23 @@ cMenuTimers::cMenuTimers(void)
cTimer *timer;
while ((timer = Timers.Get(i)) != NULL) {
Add(new cMenuTimerItem(i, timer));
Add(new cMenuTimerItem(timer));
i++;
}
SetHelp(tr("Edit"), tr("New"), tr("Delete"), tr("Mark"));
if (Setup.SortTimers)
Sort();
SetHelp(tr("Edit"), tr("New"), tr("Delete"), Setup.SortTimers ? NULL : tr("Mark"));
}
cTimer *cMenuTimers::CurrentTimer(void)
{
cMenuTimerItem *item = (cMenuTimerItem *)Get(Current());
return item ? item->Timer() : NULL;
}
eOSState cMenuTimers::Activate(bool On)
{
cTimer *timer = Timers.Get(Current());
cTimer *timer = CurrentTimer();
if (timer && timer->active != On) {
timer->active = On;
RefreshCurrent();
@ -1031,8 +1045,8 @@ eOSState cMenuTimers::Edit(void)
{
if (HasSubMenu() || Count() == 0)
return osContinue;
isyslog(LOG_INFO, "editing timer %d", Current() + 1);
return AddSubMenu(new cMenuEditTimer(Current()));
isyslog(LOG_INFO, "editing timer %d", CurrentTimer()->Index() + 1);
return AddSubMenu(new cMenuEditTimer(CurrentTimer()->Index()));
}
eOSState cMenuTimers::New(void)
@ -1041,22 +1055,22 @@ eOSState cMenuTimers::New(void)
return osContinue;
cTimer *timer = new cTimer;
Timers.Add(timer);
Add(new cMenuTimerItem(timer->Index()/*XXX*/, timer), true);
Add(new cMenuTimerItem(timer), true);
Timers.Save();
isyslog(LOG_INFO, "timer %d added", timer->Index() + 1);
return AddSubMenu(new cMenuEditTimer(Current(), true));
return AddSubMenu(new cMenuEditTimer(timer->Index(), true));
}
eOSState cMenuTimers::Del(void)
{
// Check if this timer is active:
int Index = Current();
cTimer *ti = Timers.Get(Index);
cTimer *ti = CurrentTimer();
if (ti) {
if (!ti->recording) {
if (Interface->Confirm(tr("Delete timer?"))) {
Timers.Del(Timers.Get(Index));
cOsdMenu::Del(Index);
int Index = ti->Index();
Timers.Del(ti);
cOsdMenu::Del(Current());
Timers.Save();
Display();
isyslog(LOG_INFO, "timer %d deleted", Index + 1);
@ -1081,7 +1095,7 @@ eOSState cMenuTimers::Summary(void)
{
if (HasSubMenu() || Count() == 0)
return osContinue;
cTimer *ti = Timers.Get(Current());
cTimer *ti = CurrentTimer();
if (ti && ti->summary && *ti->summary)
return AddSubMenu(new cMenuText(tr("Summary"), ti->summary));
return Edit(); // convenience for people not using the Summary feature ;-)
@ -1109,7 +1123,9 @@ eOSState cMenuTimers::ProcessKey(eKeys Key)
case kRed: return Edit();
case kGreen: return New();
case kYellow: return Del();
case kBlue: Mark(); break;
case kBlue: if (!Setup.SortTimers)
Mark();
break;
default: break;
}
}
@ -1137,6 +1153,7 @@ cMenuEvent::cMenuEvent(const cEventInfo *EventInfo, bool CanSwitch)
char *buffer;
asprintf(&buffer, "%-17.*s\t%.*s %s - %s", 17, channel->name, 5, eventInfo->GetDate(), eventInfo->GetTimeString(), eventInfo->GetEndTimeString());
SetTitle(buffer, false);
delete buffer;
int Line = 2;
cMenuTextItem *item;
const char *Title = eventInfo->GetTitle();
@ -1377,7 +1394,8 @@ void cMenuSchedule::PrepareSchedule(cChannel *Channel)
Clear();
char *buffer = NULL;
asprintf(&buffer, tr("Schedule - %s"), Channel->name);
SetTitle(buffer, false);
SetTitle(buffer);
delete buffer;
if (schedules) {
const cSchedule *Schedule = Channel->pnr ? schedules->GetSchedule(Channel->pnr) : schedules->GetSchedule();
int num = Schedule->NumEvents();
@ -1704,6 +1722,7 @@ void cMenuSetup::Set(void)
Add(new cMenuEditIntItem( tr("EPGScanTimeout"), &data.EPGScanTimeout));
Add(new cMenuEditIntItem( tr("EPGBugfixLevel"), &data.EPGBugfixLevel, 0, 3));
Add(new cMenuEditIntItem( tr("SVDRPTimeout"), &data.SVDRPTimeout));
Add(new cMenuEditBoolItem(tr("SortTimers"), &data.SortTimers));
Add(new cMenuEditIntItem( tr("PrimaryLimit"), &data.PrimaryLimit, 0, MAXPRIORITY));
Add(new cMenuEditIntItem( tr("DefaultPriority"), &data.DefaultPriority, 0, MAXPRIORITY));
Add(new cMenuEditIntItem( tr("DefaultLifetime"), &data.DefaultLifetime, 0, MAXLIFETIME));
@ -1711,6 +1730,7 @@ void cMenuSetup::Set(void)
Add(new cMenuEditBoolItem(tr("ChannelInfoPos"), &data.ChannelInfoPos, tr("bottom"), tr("top")));
Add(new cMenuEditIntItem( tr("OSDwidth"), &data.OSDwidth, MINOSDWIDTH, MAXOSDWIDTH));
Add(new cMenuEditIntItem( tr("OSDheight"), &data.OSDheight, MINOSDHEIGHT, MAXOSDHEIGHT));
Add(new cMenuEditIntItem( tr("MaxVideoFileSize"), &data.MaxVideoFileSize, MINVIDEOFILESIZE, MAXVIDEOFILESIZE));
}
eOSState cMenuSetup::ProcessKey(eKeys Key)
@ -1951,10 +1971,8 @@ void cDisplayChannel::DisplayChannel(const cChannel *Channel)
snprintf(buffer, BufSize, "%s", Channel ? Channel->name : tr("*** Invalid Channel ***"));
Interface->Fill(0, 0, Setup.OSDwidth, 1, clrBackground);
Interface->Write(0, 0, buffer);
time_t t = time(NULL);
struct tm *now = localtime(&t);
snprintf(buffer, BufSize, "%02d:%02d", now->tm_hour, now->tm_min);
Interface->Write(-5, 0, buffer);
const char *date = DayDateTime();
Interface->Write(-strlen(date), 0, date);
}
void cDisplayChannel::DisplayInfo(void)

12
osd.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: osd.c 1.17 2001/08/02 14:18:17 kls Exp $
* $Id: osd.c 1.18 2001/08/25 13:15:16 kls Exp $
*/
#include "osd.h"
@ -78,7 +78,8 @@ cOsdMenu::cOsdMenu(const char *Title, int c0, int c1, int c2, int c3, int c4)
{
hasHotkeys = false;
visible = false;
title = strdup(Title);
title = NULL;
SetTitle(Title);
cols[0] = c0;
cols[1] = c1;
cols[2] = c2;
@ -109,10 +110,13 @@ void cOsdMenu::SetStatus(const char *s)
Interface->Status(status);
}
void cOsdMenu::SetTitle(const char *Title, bool Copy)
void cOsdMenu::SetTitle(const char *Title, bool ShowDate)
{
delete title;
title = Copy ? strdup(Title) : Title;
if (ShowDate)
asprintf(&title, "%s\t%s", Title, DayDateTime(time(NULL)));
else
title = strdup(Title);
}
void cOsdMenu::SetHelp(const char *Red, const char *Green, const char *Yellow, const char *Blue)

6
osd.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: osd.h 1.23 2001/08/02 13:48:34 kls Exp $
* $Id: osd.h 1.24 2001/08/25 12:56:46 kls Exp $
*/
#ifndef __OSD_H
@ -72,7 +72,7 @@ public:
class cOsdMenu : public cOsdBase, public cList<cOsdItem> {
private:
const char *title;
char *title;
int cols[cInterface::MaxCols];
int first, current, marked;
cOsdMenu *subMenu;
@ -94,7 +94,7 @@ protected:
eOSState AddSubMenu(cOsdMenu *SubMenu);
bool HasSubMenu(void) { return subMenu; }
void SetStatus(const char *s);
void SetTitle(const char *Title, bool Copy = true);
void SetTitle(const char *Title, bool ShowDate = true);
void SetHelp(const char *Red, const char *Green = NULL, const char *Yellow = NULL, const char *Blue = NULL);
virtual void Del(int Index);
public:

34
tools.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: tools.c 1.40 2001/08/17 12:45:42 kls Exp $
* $Id: tools.c 1.43 2001/08/26 15:45:41 kls Exp $
*/
#define _GNU_SOURCE
@ -17,7 +17,9 @@
#endif
#include <stdlib.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include "i18n.h"
#define MaxBuffer 1000
@ -395,6 +397,20 @@ bool SpinUpDisk(const char *FileName)
return false;
}
const char *DayDateTime(time_t t)
{
static char buffer[32];
if (t == 0)
time(&t);
tm *tm = localtime(&t);
int weekday = tm->tm_wday == 0 ? 6 : tm->tm_wday - 1; // we start with monday==0!
const char *day = tr("MonTueWedThuFriSatSun");
day += weekday * 3;
strncpy(buffer, day, 3);
snprintf(buffer + 3, sizeof(buffer) - 3, " %2d.%02d %02d:%02d", tm->tm_mday, tm->tm_mon + 1, tm->tm_hour, tm->tm_min);
return buffer;
}
// --- cFile -----------------------------------------------------------------
bool cFile::files[FD_SETSIZE] = { false };
@ -677,3 +693,19 @@ int cListBase::Count(void) const
return n;
}
void cListBase::Sort(void)
{
bool swapped;
do {
swapped = false;
cListObject *object = objects;
while (object) {
if (object->Next() && *object->Next() < *object) {
Move(object->Next(), object);
swapped = true;
}
object = object->Next();
}
} while (swapped);
}

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: tools.h 1.29 2001/08/17 12:44:39 kls Exp $
* $Id: tools.h 1.31 2001/08/26 12:52:49 kls Exp $
*/
#ifndef __TOOLS_H
@ -55,6 +55,7 @@ bool RemoveFileOrDir(const char *FileName, bool FollowSymlinks = false);
bool RemoveEmptyDirectories(const char *DirName, bool RemoveThis = false);
char *ReadLink(const char *FileName);
bool SpinUpDisk(const char *FileName);
const char *DayDateTime(time_t t = 0);
class cFile {
private:
@ -94,6 +95,7 @@ private:
public:
cListObject(void);
virtual ~cListObject();
virtual bool operator< (const cListObject &ListObject) { return false; }
void Append(cListObject *Object);
void Unlink(void);
int Index(void);
@ -114,6 +116,7 @@ public:
virtual void Clear(void);
cListObject *Get(int Index) const;
int Count(void) const;
void Sort(void);
};
template<class T> class cList : public cListBase {

4
vdr.c
View File

@ -22,7 +22,7 @@
*
* The project's page is at http://www.cadsoft.de/people/kls/vdr
*
* $Id: vdr.c 1.63 2001/08/11 15:33:30 kls Exp $
* $Id: vdr.c 1.64 2001/08/26 15:02:00 kls Exp $
*/
#include <getopt.h>
@ -323,7 +323,7 @@ int main(int argc, char *argv[])
}
// Timers and Recordings:
if (!Menu) {
cTimer *Timer = cTimer::GetMatch();
cTimer *Timer = Timers.GetMatch();
if (Timer) {
if (!cRecordControls::Start(Timer))
Timer->SetPending(true);