summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTORS1
-rw-r--r--HISTORY12
-rw-r--r--config.c22
-rw-r--r--config.h7
-rw-r--r--menu.c78
-rw-r--r--recording.c72
-rw-r--r--recording.h6
7 files changed, 175 insertions, 23 deletions
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index de4cae20..44980137 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -3,6 +3,7 @@ Thanks go to the following people for patches and contributions:
Carsten Koch <Carsten.Koch@icem.de>
for adding LIRC support
for making the 'Recordings' menu be listed alphabetically
+ for implementing the 'Summary' feature
Plamen Ganev <pganev@com-it.net>
for fixing the frequency offset for Hotbird channels
diff --git a/HISTORY b/HISTORY
index 10154cfe..41f8697f 100644
--- a/HISTORY
+++ b/HISTORY
@@ -56,7 +56,7 @@ Video Disk Recorder Revision History
the PC keyboard to better resemble the "up-down-left-right-ok" layout on
menu controlling remote control units.
-2000-07-23: Version 0.06
+2000-07-24: Version 0.6
- Added support for LIRC remote control (thanks to Carsten Koch!).
There are now three different remote control modes: KBD (PC-Keyboard), RCU
@@ -87,3 +87,13 @@ Video Disk Recorder Revision History
the VDR over a network connection.
- Implemented command line option handling.
- The program can now run in full background mode by using the --daemon option.
+- Added a "summary" field to the timers (thanks to Carsten Koch!).
+ This field can contain a descriptive text of the programme and will be
+ displayed when the "Blue" key is pressed on a recording that was created by
+ this timer. If the text contains the special character '|', a newline will
+ be inserted at that place. When pressing "Ok" on a timer that contains a
+ summary field, the summary will be displayed. To edit such a timer the "Red"
+ key must be pressed. Timers without a summary still go into Edit mode when
+ pressing "Ok". The summary field can only be filled in directly by editing
+ the 'timers.conf' file with a text editor, or by defining/modifying the timer
+ via the SVDRP interface.
diff --git a/config.c b/config.c
index 72043c13..d77d07e7 100644
--- a/config.c
+++ b/config.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: config.c 1.13 2000/07/23 11:56:06 kls Exp $
+ * $Id: config.c 1.14 2000/07/23 17:22:08 kls Exp $
*/
#include "config.h"
@@ -274,13 +274,27 @@ cTimer::cTimer(bool Instant)
priority = 99;
lifetime = 99;
*file = 0;
+ summary = NULL;
if (Instant)
snprintf(file, sizeof(file), "@%s", cChannel::GetChannelName(CurrentChannel));
}
+cTimer::~cTimer()
+{
+ delete summary;
+}
+
+cTimer& cTimer::operator= (const cTimer &Timer)
+{
+ memcpy(this, &Timer, sizeof(*this));
+ if (summary)
+ summary = strdup(summary);
+ return *this;
+}
+
const char *cTimer::ToText(cTimer *Timer)
{
- asprintf(&buffer, "%d:%d:%s:%d:%d:%d:%d:%s\n", Timer->active, Timer->channel, PrintDay(Timer->day), Timer->start, Timer->stop, Timer->priority, Timer->lifetime, Timer->file);
+ asprintf(&buffer, "%d:%d:%s:%d:%d:%d:%d:%s:%s\n", Timer->active, Timer->channel, PrintDay(Timer->day), Timer->start, Timer->stop, Timer->priority, Timer->lifetime, Timer->file, Timer->summary ? Timer->summary : "");
return buffer;
}
@@ -344,7 +358,9 @@ bool cTimer::Parse(const char *s)
{
char *buffer1 = NULL;
char *buffer2 = NULL;
- if (8 == sscanf(s, "%d:%d:%a[^:]:%d:%d:%d:%d:%a[^:\n]", &active, &channel, &buffer1, &start, &stop, &priority, &lifetime, &buffer2)) {
+ delete summary;
+ summary = NULL;
+ if (8 <= sscanf(s, "%d:%d:%a[^:]:%d:%d:%d:%d:%a[^:\n]:%a[^\n]", &active, &channel, &buffer1, &start, &stop, &priority, &lifetime, &buffer2, &summary)) {
//TODO add more plausibility checks
day = ParseDay(buffer1);
strncpy(file, buffer2, MaxFileName - 1);
diff --git a/config.h b/config.h
index 28d07edf..be1c7ec7 100644
--- a/config.h
+++ b/config.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: config.h 1.10 2000/07/23 11:54:53 kls Exp $
+ * $Id: config.h 1.11 2000/07/23 17:17:10 kls Exp $
*/
#ifndef __CONFIG_H
@@ -17,7 +17,7 @@
#include "dvbapi.h"
#include "tools.h"
-#define MaxBuffer 1000
+#define MaxBuffer 10000
enum eKeys { // "Up" and "Down" must be the first two keys!
kUp,
@@ -100,7 +100,10 @@ public:
int priority;
int lifetime;
char file[MaxFileName];
+ char *summary;
cTimer(bool Instant = false);
+ ~cTimer();
+ cTimer& operator= (const cTimer &Timer);
const char *ToText(void);
bool Parse(const char *s);
bool Save(FILE *f);
diff --git a/menu.c b/menu.c
index 1a8103ce..17a9b0b5 100644
--- a/menu.c
+++ b/menu.c
@@ -4,10 +4,11 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: menu.c 1.19 2000/07/16 14:52:48 kls Exp $
+ * $Id: menu.c 1.20 2000/07/24 16:25:53 kls Exp $
*/
#include "menu.h"
+#include <ctype.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
@@ -707,6 +708,51 @@ eOSState cMenuChannels::ProcessKey(eKeys Key)
return state;
}
+// --- cMenuSummary --------------------------------------------------------
+
+class cMenuSummary : public cOsdMenu {
+public:
+ cMenuSummary(const char *Text);
+ virtual eOSState ProcessKey(eKeys Key);
+ };
+
+cMenuSummary::cMenuSummary(const char *Text)
+:cOsdMenu("Summary")
+{
+ while (*Text) {
+ char line[MenuColumns + 1];
+ char *p = line;
+ const char *b = NULL;
+ *p++ = ' ';
+ while (*Text && p - line < MenuColumns - 2) {
+ if (isspace(*Text))
+ b = Text; // remember the blank
+ if (*Text == '\n')
+ break;
+ *p++ = *Text++;
+ }
+ if (*Text) {
+ if (b && Text - b > 0) {
+ p -= Text - b;
+ Text = b + 1;
+ }
+ else
+ Text++;
+ }
+ *p = 0;
+ Add(new cOsdItem(line, osBack));
+ }
+}
+
+eOSState cMenuSummary::ProcessKey(eKeys Key)
+{
+ eOSState state = cOsdMenu::ProcessKey(Key);
+
+ if (state == osUnknown)
+ state = osContinue;
+ return state;
+}
+
// --- cMenuEditTimer --------------------------------------------------------
class cMenuEditTimer : public cOsdMenu {
@@ -799,6 +845,7 @@ private:
eOSState New(void);
eOSState Del(void);
virtual void Move(int From, int To);
+ eOSState Summary(void);
public:
cMenuTimers(void);
virtual eOSState ProcessKey(eKeys Key);
@@ -880,6 +927,16 @@ void cMenuTimers::Move(int From, int To)
isyslog(LOG_INFO, "timer %d moved to %d", From + 1, To + 1);
}
+eOSState cMenuTimers::Summary(void)
+{
+ if (HasSubMenu() || Count() == 0)
+ return osContinue;
+ cTimer *ti = Timers.Get(Current());
+ if (ti && ti->summary && *ti->summary)
+ return AddSubMenu(new cMenuSummary(ti->summary));
+ return Edit(); // convenience for people not using the Summary feature ;-)
+}
+
eOSState cMenuTimers::ProcessKey(eKeys Key)
{
eOSState state = cOsdMenu::ProcessKey(Key);
@@ -888,7 +945,7 @@ eOSState cMenuTimers::ProcessKey(eKeys Key)
switch (Key) {
case kLeft:
case kRight: return Activate(Key == kRight);
- case kOk:
+ case kOk: return Summary();
case kRed: return Edit();
case kGreen: return New();
case kYellow: return Del();
@@ -926,6 +983,7 @@ private:
cRecordings Recordings;
eOSState Play(void);
eOSState Del(void);
+ eOSState Summary(void);
public:
cMenuRecordings(void);
virtual eOSState ProcessKey(eKeys Key);
@@ -941,7 +999,7 @@ cMenuRecordings::cMenuRecordings(void)
recording = Recordings.Next(recording);
}
}
- SetHelp("Play", NULL/*XXX"Resume"*/, "Delete");
+ SetHelp("Play", NULL/*XXX"Resume"*/, "Delete", "Summary");
}
eOSState cMenuRecordings::Play(void)
@@ -975,6 +1033,16 @@ eOSState cMenuRecordings::Del(void)
return osContinue;
}
+eOSState cMenuRecordings::Summary(void)
+{
+ if (HasSubMenu() || Count() == 0)
+ return osContinue;
+ cMenuRecordingItem *ri = (cMenuRecordingItem *)Get(Current());
+ if (ri && ri->recording->Summary() && *ri->recording->Summary())
+ return AddSubMenu(new cMenuSummary(ri->recording->Summary()));
+ return osContinue;
+}
+
eOSState cMenuRecordings::ProcessKey(eKeys Key)
{
eOSState state = cOsdMenu::ProcessKey(Key);
@@ -984,6 +1052,7 @@ eOSState cMenuRecordings::ProcessKey(eKeys Key)
case kOk:
case kRed: return Play();
case kYellow: return Del();
+ case kBlue: return Summary();
default: break;
}
}
@@ -1061,7 +1130,8 @@ cRecordControl::cRecordControl(cDvbApi *DvbApi, cTimer *Timer)
timer->SetRecording(true);
cChannel::SwitchTo(timer->channel - 1, dvbApi);
cRecording Recording(timer);
- dvbApi->StartRecord(Recording.FileName());
+ if (dvbApi->StartRecord(Recording.FileName()))
+ Recording.WriteSummary();
Interface.DisplayRecording(dvbApi->Index(), true);
}
diff --git a/recording.c b/recording.c
index 3e9df374..e37ccd85 100644
--- a/recording.c
+++ b/recording.c
@@ -4,14 +4,16 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: recording.c 1.11 2000/07/16 14:21:37 kls Exp $
+ * $Id: recording.c 1.12 2000/07/24 16:31:07 kls Exp $
*/
#define _GNU_SOURCE
#include "recording.h"
#include <errno.h>
+#include <fcntl.h>
#include <stdio.h>
#include <string.h>
+#include <unistd.h>
#include "interface.h"
#include "tools.h"
@@ -20,6 +22,8 @@
#define DATAFORMAT "%4d-%02d-%02d.%02d:%02d.%02d.%02d" RECEXT
#define NAMEFORMAT "%s/%s/" DATAFORMAT
+#define SUMMARYFILESUFFIX "/summary.vdr"
+
#define FINDCMD "find %s -type d -name '%s' | sort -df"
#define DFCMD "df -m %s"
@@ -102,21 +106,14 @@ void AssertFreeDiskSpace(void)
// --- cRecording ------------------------------------------------------------
-cRecording::cRecording(const char *Name, time_t Start, int Priority, int LifeTime)
-{
- titleBuffer = NULL;
- fileName = NULL;
- name = strdup(Name);
- start = Start;
- priority = Priority;
- lifetime = LifeTime;
-}
-
cRecording::cRecording(cTimer *Timer)
{
titleBuffer = NULL;
fileName = NULL;
name = strdup(Timer->file);
+ summary = Timer->summary ? strdup(Timer->summary) : NULL;
+ if (summary)
+ strreplace(summary, '|', '\n');
start = Timer->StartTime();
priority = Timer->priority;
lifetime = Timer->lifetime;
@@ -130,6 +127,7 @@ cRecording::cRecording(const char *FileName)
char *p = strrchr(FileName, '/');
name = NULL;
+ summary = NULL;
if (p) {
time_t now = time(NULL);
struct tm t = *localtime(&now); // this initializes the time zone in 't'
@@ -143,6 +141,39 @@ cRecording::cRecording(const char *FileName)
name[p - FileName] = 0;
strreplace(name, '_', ' ');
}
+ // read an optional summary file:
+ char *SummaryFileName = NULL;
+ asprintf(&SummaryFileName, "%s%s", fileName, SUMMARYFILESUFFIX);
+ int f = open(SummaryFileName, O_RDONLY);
+ if (f >= 0) {
+ struct stat buf;
+ if (fstat(f, &buf) == 0) {
+ int size = buf.st_size;
+ summary = new char[size + 1]; // +1 for terminating 0
+ if (summary) {
+ int rbytes = read(f, summary, size);
+ if (rbytes >= 0) {
+ summary[rbytes] = 0;
+ if (rbytes != size)
+ esyslog(LOG_ERR, "%s: expected %d bytes but read %d", SummaryFileName, size, rbytes);
+ }
+ else {
+ LOG_ERROR_STR(SummaryFileName);
+ delete summary;
+ summary = NULL;
+ }
+
+ }
+ else
+ esyslog(LOG_ERR, "can't allocate %d byte of memory for summary file '%s'", size + 1, SummaryFileName);
+ close(f);
+ }
+ else
+ LOG_ERROR_STR(SummaryFileName);
+ }
+ else if (errno != ENOENT)
+ LOG_ERROR_STR(SummaryFileName);
+ delete SummaryFileName;
}
}
@@ -151,6 +182,7 @@ cRecording::~cRecording()
delete titleBuffer;
delete fileName;
delete name;
+ delete summary;
}
const char *cRecording::FileName(void)
@@ -181,6 +213,24 @@ const char *cRecording::Title(char Delimiter)
return titleBuffer;
}
+bool cRecording::WriteSummary(void)
+{
+ if (summary) {
+ char *SummaryFileName = NULL;
+ asprintf(&SummaryFileName, "%s%s", fileName, SUMMARYFILESUFFIX);
+ FILE *f = fopen(SummaryFileName, "w");
+ if (f) {
+ if (fputs(summary, f) < 0)
+ LOG_ERROR_STR(SummaryFileName);
+ fclose(f);
+ }
+ else
+ LOG_ERROR_STR(SummaryFileName);
+ delete SummaryFileName;
+ }
+ return true;
+}
+
bool cRecording::Delete(void)
{
bool result = true;
diff --git a/recording.h b/recording.h
index eeea5609..e501af82 100644
--- a/recording.h
+++ b/recording.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: recording.h 1.6 2000/04/24 09:45:49 kls Exp $
+ * $Id: recording.h 1.7 2000/07/23 19:06:14 kls Exp $
*/
#ifndef __RECORDING_H
@@ -22,16 +22,18 @@ private:
char *titleBuffer;
char *fileName;
char *name;
+ char *summary;
public:
time_t start;
int priority;
int lifetime;
- cRecording(const char *Name, time_t Start, int Priority, int LifeTime);
cRecording(cTimer *Timer);
cRecording(const char *FileName);
~cRecording();
const char *FileName(void);
const char *Title(char Delimiter = ' ');
+ const char *Summary(void) { return summary; }
+ bool WriteSummary(void);
bool Delete(void);
// Changes the file name so that it will no longer be visible in the "Recordings" menu
// Returns false in case of error