mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Switched from 'summary.vdr' to 'info.vdr'
This commit is contained in:
parent
6e274dfeef
commit
b0583e5373
20
HISTORY
20
HISTORY
@ -3513,7 +3513,7 @@ Video Disk Recorder Revision History
|
||||
- Fixed a wrong inheritance in libsi's SubtitlingDescriptor::Subtitling (thanks to
|
||||
Marco Schlüßler).
|
||||
|
||||
2005-05-14: Version 1.3.25
|
||||
2005-05-16: Version 1.3.25
|
||||
|
||||
- Updated the Estonian OSD texts (thanks to Arthur Konovalov).
|
||||
- Some cable providers don't mark short channel names according to the standard,
|
||||
@ -3526,3 +3526,21 @@ Video Disk Recorder Revision History
|
||||
- Made cOsd::isOpen an integer counter to avoid problems with messages when a
|
||||
cOsdObject uses the raw OSD (thanks to Andreas Regel for reporting this one).
|
||||
- Updated the Danish OSD texts (thanks to Mogens Elneff).
|
||||
- The file 'summary.vdr' has been replaced with 'info.vdr' and now contains the
|
||||
information about a recording, in the same format as the events are stored in
|
||||
'epg.data' (see man vdr(5) for details). Existing summary files can be converted
|
||||
to the new format by running the Perl script 'summary2info.pl', as in
|
||||
|
||||
summary2info.pl /video
|
||||
|
||||
(the parameter given has to be the video directory).
|
||||
- The "Summary" button in the "Recordings" menu has been renamed to "Info", and
|
||||
the page it brings up now shows the recording's information, much like the EPG
|
||||
event page. Therefore it now no longer uses the skin's SetText() function, but
|
||||
rather the SetRecording() function. Skin plugins may need to adjust that function
|
||||
accordingly (see skinsttng.c, for instance).
|
||||
- The SVDRP command LSTR now lists the recording information in the same tagged
|
||||
format as the LSTE command lists the EPG data.
|
||||
- The audio track menu now contains track descriptions when replaying (provided
|
||||
such descriptions were available in the EPG data when the recording was made,
|
||||
and are stored in the info.vdr file).
|
||||
|
2
MANUAL
2
MANUAL
@ -23,7 +23,7 @@ Version 1.2
|
||||
Red - Record Edit Edit ABC/abc Play/Commands(2) Jump -
|
||||
Green - Audio New New Ins/Ovr Rewind Skip -60s -
|
||||
Yellow - Pause live Delete Delete Delete Delete Skip +60s -
|
||||
Blue - Stop/Resume Mark On/Off(1) - Summary Stop -
|
||||
Blue - Stop/Resume Mark On/Off(1) - Info Stop -
|
||||
0..9 Ch select - Sort(3) Day(4) Numeric inp. Exec cmd(2) Editing -
|
||||
|
||||
In a numerical input field (like the response to a CAM enquiry) the keys 0..9
|
||||
|
@ -13,3 +13,7 @@ VDR Plugin 'skincurses' Revision History
|
||||
|
||||
- Made several functions threadsafe.
|
||||
- New audio track display.
|
||||
|
||||
2005-05-16: Version 0.0.4
|
||||
|
||||
- New "recording info" display.
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* See the README file for copyright information and how to reach the author.
|
||||
*
|
||||
* $Id: skincurses.c 1.5 2005/01/09 11:56:26 kls Exp $
|
||||
* $Id: skincurses.c 1.6 2005/05/16 10:45:12 kls Exp $
|
||||
*/
|
||||
|
||||
#include <ncurses.h>
|
||||
@ -11,7 +11,7 @@
|
||||
#include <vdr/plugin.h>
|
||||
#include <vdr/skins.h>
|
||||
|
||||
static const char *VERSION = "0.0.3";
|
||||
static const char *VERSION = "0.0.4";
|
||||
static const char *DESCRIPTION = "A text only skin";
|
||||
static const char *MAINMENUENTRY = NULL;
|
||||
|
||||
@ -407,7 +407,30 @@ void cSkinCursesDisplayMenu::SetEvent(const cEvent *Event)
|
||||
|
||||
void cSkinCursesDisplayMenu::SetRecording(const cRecording *Recording)
|
||||
{
|
||||
SetText(Recording->Summary(), false); //TODO
|
||||
if (!Recording)
|
||||
return;
|
||||
const cRecordingInfo *Info = Recording->Info();
|
||||
int y = 2;
|
||||
cTextScroller ts;
|
||||
char t[32];
|
||||
snprintf(t, sizeof(t), "%s %s", *DateString(Recording->start), *TimeString(Recording->start));
|
||||
ts.Set(osd, 0, y, OsdWidth, OsdHeight - y - 2, t, &Font, clrYellow, clrBackground);
|
||||
y += ts.Height();
|
||||
y += 1;
|
||||
const char *Title = Info->Title();
|
||||
if (isempty(Title))
|
||||
Title = Recording->Name();
|
||||
ts.Set(osd, 0, y, OsdWidth, OsdHeight - y - 2, Title, &Font, clrCyan, clrBackground);
|
||||
y += ts.Height();
|
||||
if (!isempty(Info->ShortText())) {
|
||||
ts.Set(osd, 0, y, OsdWidth, OsdHeight - y - 2, Info->ShortText(), &Font, clrYellow, clrBackground);
|
||||
y += ts.Height();
|
||||
}
|
||||
y += 1;
|
||||
if (!isempty(Info->Description())) {
|
||||
textScroller.Set(osd, 0, y, OsdWidth - 2, OsdHeight - y - 2, Info->Description(), &Font, clrCyan, clrBackground);
|
||||
SetScrollbar();
|
||||
}
|
||||
}
|
||||
|
||||
void cSkinCursesDisplayMenu::SetText(const char *Text, bool FixedFont)
|
||||
|
4
cutter.c
4
cutter.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: cutter.c 1.7 2004/06/13 16:04:08 kls Exp $
|
||||
* $Id: cutter.c 1.8 2005/05/15 14:21:08 kls Exp $
|
||||
*/
|
||||
|
||||
#include "cutter.h"
|
||||
@ -204,7 +204,7 @@ bool cCutter::Start(const char *FileName)
|
||||
free(s);
|
||||
// XXX
|
||||
editedVersionName = strdup(evn);
|
||||
Recording.WriteSummary();
|
||||
Recording.WriteInfo();
|
||||
Recordings.AddByName(editedVersionName);
|
||||
cuttingThread = new cCuttingThread(FileName, editedVersionName);
|
||||
return true;
|
||||
|
28
eit.c
28
eit.c
@ -8,7 +8,7 @@
|
||||
* Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
|
||||
* Adapted to 'libsi' for VDR 1.3.0 by Marcel Wiesweg <marcel.wiesweg@gmx.de>.
|
||||
*
|
||||
* $Id: eit.c 1.103 2005/03/20 12:33:51 kls Exp $
|
||||
* $Id: eit.c 1.104 2005/05/15 10:36:04 kls Exp $
|
||||
*/
|
||||
|
||||
#include "eit.h"
|
||||
@ -91,8 +91,7 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data)
|
||||
SI::ExtendedEventDescriptors *ExtendedEventDescriptors = NULL;
|
||||
SI::ShortEventDescriptor *ShortEventDescriptor = NULL;
|
||||
cLinkChannels *LinkChannels = NULL;
|
||||
int NumComponents = 0;
|
||||
SI::ComponentDescriptor *ComponentDescriptors[MAXCOMPONENTS];
|
||||
cComponents *Components = NULL;
|
||||
for (SI::Loop::Iterator it2; (d = SiEitEvent.eventDescriptors.getNext(it2)); ) {
|
||||
switch (d->getDescriptorTag()) {
|
||||
case SI::ExtendedEventDescriptorTag: {
|
||||
@ -193,12 +192,10 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data)
|
||||
uchar Stream = cd->getStreamContent();
|
||||
uchar Type = cd->getComponentType();
|
||||
if (1 <= Stream && Stream <= 2 && Type != 0) {
|
||||
if (NumComponents < MAXCOMPONENTS) {
|
||||
ComponentDescriptors[NumComponents++] = cd;
|
||||
d = NULL; // so that it is not deleted
|
||||
}
|
||||
else
|
||||
dsyslog("more than %d component descriptors!", MAXCOMPONENTS);
|
||||
if (!Components)
|
||||
Components = new cComponents;
|
||||
char buffer[256];
|
||||
Components->SetComponent(Components->NumComponents(), cd->getStreamContent(), cd->getComponentType(), I18nNormalizeLanguageCode(cd->languageCode), cd->description.getText(buffer, sizeof(buffer)));
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -221,18 +218,7 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data)
|
||||
delete ExtendedEventDescriptors;
|
||||
delete ShortEventDescriptor;
|
||||
|
||||
if (NumComponents > 0) {
|
||||
cComponents *Components = new cComponents(NumComponents);
|
||||
for (int i = 0; i < NumComponents; i++) {
|
||||
char buffer[256];
|
||||
SI::ComponentDescriptor *cd = ComponentDescriptors[i];
|
||||
Components->SetComponent(i, cd->getStreamContent(), cd->getComponentType(), I18nNormalizeLanguageCode(cd->languageCode), cd->description.getText(buffer, sizeof(buffer)));
|
||||
delete cd;
|
||||
}
|
||||
pEvent->SetComponents(Components);
|
||||
}
|
||||
else
|
||||
pEvent->SetComponents(NULL);
|
||||
pEvent->SetComponents(Components);
|
||||
|
||||
pEvent->FixEpgBugs();
|
||||
if (LinkChannels)
|
||||
|
141
epg.c
141
epg.c
@ -7,7 +7,7 @@
|
||||
* Original version (as used in VDR before 1.3.0) written by
|
||||
* Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
|
||||
*
|
||||
* $Id: epg.c 1.29 2005/05/05 13:53:19 kls Exp $
|
||||
* $Id: epg.c 1.30 2005/05/16 14:12:00 kls Exp $
|
||||
*/
|
||||
|
||||
#include "epg.h"
|
||||
@ -40,11 +40,10 @@ bool tComponent::FromString(const char *s)
|
||||
|
||||
// --- cComponents -----------------------------------------------------------
|
||||
|
||||
cComponents::cComponents(int NumComponents)
|
||||
cComponents::cComponents(void)
|
||||
{
|
||||
numComponents = NumComponents;
|
||||
components = MALLOC(tComponent, numComponents);
|
||||
memset(components, 0, sizeof(tComponent) * numComponents);
|
||||
numComponents = 0;
|
||||
components = NULL;
|
||||
}
|
||||
|
||||
cComponents::~cComponents(void)
|
||||
@ -54,24 +53,30 @@ cComponents::~cComponents(void)
|
||||
free(components);
|
||||
}
|
||||
|
||||
bool cComponents::SetComponent(int Index, const char *s)
|
||||
void cComponents::Realloc(int Index)
|
||||
{
|
||||
if (Index < numComponents)
|
||||
return components[Index].FromString(s);
|
||||
return false;
|
||||
if (Index >= numComponents) {
|
||||
int n = numComponents;
|
||||
numComponents = Index + 1;
|
||||
components = (tComponent *)realloc(components, numComponents * sizeof(tComponent));
|
||||
memset(&components[n], 0, sizeof(tComponent) * (numComponents - n));
|
||||
}
|
||||
}
|
||||
|
||||
bool cComponents::SetComponent(int Index, uchar Stream, uchar Type, const char *Language, const char *Description)
|
||||
void cComponents::SetComponent(int Index, const char *s)
|
||||
{
|
||||
if (Index < numComponents) {
|
||||
tComponent *p = &components[Index];
|
||||
p->stream = Stream;
|
||||
p->type = Type;
|
||||
strn0cpy(p->language, Language, sizeof(p->language));
|
||||
p->description = strcpyrealloc(p->description, !isempty(Description) ? Description : NULL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
Realloc(Index);
|
||||
components[Index].FromString(s);
|
||||
}
|
||||
|
||||
void cComponents::SetComponent(int Index, uchar Stream, uchar Type, const char *Language, const char *Description)
|
||||
{
|
||||
Realloc(Index);
|
||||
tComponent *p = &components[Index];
|
||||
p->stream = Stream;
|
||||
p->type = Type;
|
||||
strn0cpy(p->language, Language, sizeof(p->language));
|
||||
p->description = strcpyrealloc(p->description, !isempty(Description) ? Description : NULL);
|
||||
}
|
||||
|
||||
// --- cEvent ----------------------------------------------------------------
|
||||
@ -107,6 +112,11 @@ int cEvent::Compare(const cListObject &ListObject) const
|
||||
return startTime - e->startTime;
|
||||
}
|
||||
|
||||
void cEvent::SetChannelID(tChannelID ChannelID)
|
||||
{
|
||||
channelID = ChannelID;
|
||||
}
|
||||
|
||||
void cEvent::SetEventID(u_int16_t EventID)
|
||||
{
|
||||
eventID = EventID;
|
||||
@ -187,30 +197,17 @@ bool cEvent::IsRunning(bool OrAboutToStart) const
|
||||
|
||||
cString cEvent::GetDateString(void) const
|
||||
{
|
||||
char buf[32];
|
||||
struct tm tm_r;
|
||||
tm *tm = localtime_r(&startTime, &tm_r);
|
||||
char *p = stpcpy(buf, WeekDayName(tm->tm_wday));
|
||||
*p++ = ' ';
|
||||
strftime(p, sizeof(buf) - (p - buf), "%d.%m.%Y", tm);
|
||||
return buf;
|
||||
return DateString(startTime);
|
||||
}
|
||||
|
||||
cString cEvent::GetTimeString(void) const
|
||||
{
|
||||
char buf[25];
|
||||
struct tm tm_r;
|
||||
strftime(buf, sizeof(buf), "%R", localtime_r(&startTime, &tm_r));
|
||||
return buf;
|
||||
return TimeString(startTime);
|
||||
}
|
||||
|
||||
cString cEvent::GetEndTimeString(void) const
|
||||
{
|
||||
char buf[25];
|
||||
time_t EndTime = startTime + duration;
|
||||
struct tm tm_r;
|
||||
strftime(buf, sizeof(buf), "%R", localtime_r(&EndTime, &tm_r));
|
||||
return buf;
|
||||
return TimeString(startTime + duration);
|
||||
}
|
||||
|
||||
cString cEvent::GetVpsString(void) const
|
||||
@ -221,10 +218,11 @@ cString cEvent::GetVpsString(void) const
|
||||
return buf;
|
||||
}
|
||||
|
||||
void cEvent::Dump(FILE *f, const char *Prefix) const
|
||||
void cEvent::Dump(FILE *f, const char *Prefix, bool InfoOnly) const
|
||||
{
|
||||
if (startTime + duration + Setup.EPGLinger * 60 >= time(NULL)) {
|
||||
fprintf(f, "%sE %u %ld %d %X\n", Prefix, eventID, startTime, duration, tableID);
|
||||
if (InfoOnly || startTime + duration + Setup.EPGLinger * 60 >= time(NULL)) {
|
||||
if (!InfoOnly)
|
||||
fprintf(f, "%sE %u %ld %d %X\n", Prefix, eventID, startTime, duration, tableID);
|
||||
if (!isempty(title))
|
||||
fprintf(f, "%sT %s\n", Prefix, title);
|
||||
if (!isempty(shortText))
|
||||
@ -240,18 +238,40 @@ void cEvent::Dump(FILE *f, const char *Prefix) const
|
||||
fprintf(f, "%sX %s\n", Prefix, *p->ToString());
|
||||
}
|
||||
}
|
||||
if (vps)
|
||||
if (!InfoOnly && vps)
|
||||
fprintf(f, "%sV %ld\n", Prefix, vps);
|
||||
fprintf(f, "%se\n", Prefix);
|
||||
if (!InfoOnly)
|
||||
fprintf(f, "%se\n", Prefix);
|
||||
}
|
||||
}
|
||||
|
||||
bool cEvent::Parse(char *s)
|
||||
{
|
||||
char *t = skipspace(s + 1);
|
||||
switch (*s) {
|
||||
case 'T': SetTitle(t);
|
||||
break;
|
||||
case 'S': SetShortText(t);
|
||||
break;
|
||||
case 'D': strreplace(t, '|', '\n');
|
||||
SetDescription(t);
|
||||
break;
|
||||
case 'X': if (!components)
|
||||
components = new cComponents;
|
||||
components->SetComponent(components->NumComponents(), t);
|
||||
break;
|
||||
case 'V': SetVps(atoi(t));
|
||||
break;
|
||||
default: esyslog("ERROR: unexpected tag while reading EPG data: %s", s);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cEvent::Read(FILE *f, cSchedule *Schedule)
|
||||
{
|
||||
if (Schedule) {
|
||||
cEvent *Event = NULL;
|
||||
int NumComponents = 0;
|
||||
char *ComponentStrings[MAXCOMPONENTS];
|
||||
char *s;
|
||||
cReadLine ReadLine;
|
||||
while ((s = ReadLine.Read(f)) != NULL) {
|
||||
@ -273,45 +293,14 @@ bool cEvent::Read(FILE *f, cSchedule *Schedule)
|
||||
Event->SetDuration(Duration);
|
||||
}
|
||||
}
|
||||
NumComponents = 0;
|
||||
}
|
||||
break;
|
||||
case 'T': if (Event)
|
||||
Event->SetTitle(t);
|
||||
break;
|
||||
case 'S': if (Event)
|
||||
Event->SetShortText(t);
|
||||
break;
|
||||
case 'D': if (Event) {
|
||||
strreplace(t, '|', '\n');
|
||||
Event->SetDescription(t);
|
||||
}
|
||||
break;
|
||||
case 'X': if (Event) {
|
||||
if (NumComponents < MAXCOMPONENTS)
|
||||
ComponentStrings[NumComponents++] = strdup(t);
|
||||
else
|
||||
dsyslog("more than %d component descriptors!", MAXCOMPONENTS);
|
||||
}
|
||||
break;
|
||||
case 'V': if (Event)
|
||||
Event->SetVps(atoi(t));
|
||||
break;
|
||||
case 'e': if (Event && NumComponents > 0) {
|
||||
cComponents *Components = new cComponents(NumComponents);
|
||||
for (int i = 0; i < NumComponents; i++) {
|
||||
if (!Components->SetComponent(i, ComponentStrings[i]))
|
||||
esyslog("ERROR: faulty component string in EPG data: '%s'", ComponentStrings[i]);
|
||||
free(ComponentStrings[i]);
|
||||
}
|
||||
Event->SetComponents(Components);
|
||||
}
|
||||
Event = NULL;
|
||||
case 'e': Event = NULL;
|
||||
break;
|
||||
case 'c': // to keep things simple we react on 'c' here
|
||||
return true;
|
||||
default: esyslog("ERROR: unexpected tag while reading EPG data: %s", s);
|
||||
return false;
|
||||
default: if (Event && !Event->Parse(s))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
esyslog("ERROR: unexpected end of file while reading EPG data");
|
||||
|
16
epg.h
16
epg.h
@ -7,7 +7,7 @@
|
||||
* Original version (as used in VDR before 1.3.0) written by
|
||||
* Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
|
||||
*
|
||||
* $Id: epg.h 1.21 2005/03/20 12:32:36 kls Exp $
|
||||
* $Id: epg.h 1.22 2005/05/16 14:11:28 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __EPG_H
|
||||
@ -18,7 +18,6 @@
|
||||
#include "tools.h"
|
||||
|
||||
#define MAXEPGBUGFIXLEVEL 3
|
||||
#define MAXCOMPONENTS 32
|
||||
|
||||
enum eDumpMode { dmAll, dmPresent, dmFollowing, dmAtTime };
|
||||
|
||||
@ -35,12 +34,13 @@ class cComponents {
|
||||
private:
|
||||
int numComponents;
|
||||
tComponent *components;
|
||||
void Realloc(int Index);
|
||||
public:
|
||||
cComponents(int NumComponents);
|
||||
cComponents(void);
|
||||
~cComponents(void);
|
||||
int NumComponents(void) const { return numComponents; }
|
||||
bool SetComponent(int Index, const char *s);
|
||||
bool SetComponent(int Index, uchar Stream, uchar Type, const char *Language, const char *Description);
|
||||
void SetComponent(int Index, const char *s);
|
||||
void SetComponent(int Index, uchar Stream, uchar Type, const char *Language, const char *Description);
|
||||
tComponent *Component(int Index) const { return (Index < numComponents) ? &components[Index] : NULL; }
|
||||
};
|
||||
|
||||
@ -56,7 +56,7 @@ private:
|
||||
char *title; // Title of this event
|
||||
char *shortText; // Short description of this event (typically the episode name in case of a series)
|
||||
char *description; // Description of this event
|
||||
cComponents *components; // The stream components of this event (separated by '\n')
|
||||
cComponents *components; // The stream components of this event
|
||||
time_t startTime; // Start time of this event
|
||||
int duration; // Duration of this event in seconds
|
||||
time_t vps; // Video Programming Service timestamp (VPS, aka "Programme Identification Label", PIL)
|
||||
@ -86,6 +86,7 @@ public:
|
||||
cString GetTimeString(void) const;
|
||||
cString GetEndTimeString(void) const;
|
||||
cString GetVpsString(void) const;
|
||||
void SetChannelID(tChannelID ChannelID);
|
||||
void SetEventID(u_int16_t EventID);
|
||||
void SetTableID(uchar TableID);
|
||||
void SetVersion(uchar Version);
|
||||
@ -98,7 +99,8 @@ public:
|
||||
void SetDuration(int Duration);
|
||||
void SetVps(time_t Vps);
|
||||
void SetSeen(void);
|
||||
void Dump(FILE *f, const char *Prefix = "") const;
|
||||
void Dump(FILE *f, const char *Prefix = "", bool InfoOnly = false) const;
|
||||
bool Parse(char *s);
|
||||
static bool Read(FILE *f, cSchedule *Schedule);
|
||||
void FixEpgBugs(void);
|
||||
};
|
||||
|
23
i18n.c
23
i18n.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: i18n.c 1.190 2005/05/15 09:22:07 kls Exp $
|
||||
* $Id: i18n.c 1.191 2005/05/15 14:37:59 kls Exp $
|
||||
*
|
||||
* Translations provided by:
|
||||
*
|
||||
@ -399,6 +399,27 @@ const tI18nPhrase Phrases[] = {
|
||||
"Kokkuvõte",
|
||||
"Omtale",
|
||||
},
|
||||
{ "Info",
|
||||
"Info",
|
||||
"",//TODO
|
||||
"",//TODO
|
||||
"",//TODO
|
||||
"",//TODO
|
||||
"",//TODO
|
||||
"",//TODO
|
||||
"",//TODO
|
||||
"",//TODO
|
||||
"",//TODO
|
||||
"",//TODO
|
||||
"",//TODO
|
||||
"",//TODO
|
||||
"",//TODO
|
||||
"",//TODO
|
||||
"",//TODO
|
||||
"",//TODO
|
||||
"",//TODO
|
||||
"",//TODO
|
||||
},
|
||||
{ "Schedule - %s",
|
||||
"Programm - %s",
|
||||
"Program - %s",
|
||||
|
161
menu.c
161
menu.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: menu.c 1.348 2005/03/20 15:14:51 kls Exp $
|
||||
* $Id: menu.c 1.349 2005/05/16 13:59:03 kls Exp $
|
||||
*/
|
||||
|
||||
#include "menu.h"
|
||||
@ -872,7 +872,6 @@ eOSState cMenuTimers::Summary(void)
|
||||
cTimer *ti = CurrentTimer();
|
||||
if (ti && !isempty(ti->Summary()))
|
||||
return AddSubMenu(new cMenuText(tr("Summary"), ti->Summary()));
|
||||
//XXX cSkin::SetRecording()???
|
||||
return Edit(); // convenience for people not using the Summary feature ;-)
|
||||
}
|
||||
|
||||
@ -1297,8 +1296,12 @@ eOSState cMenuCommands::ProcessKey(eKeys Key)
|
||||
|
||||
if (state == osUnknown) {
|
||||
switch (Key) {
|
||||
case kOk: return Execute();
|
||||
default: break;
|
||||
case kRed:
|
||||
case kGreen:
|
||||
case kYellow:
|
||||
case kBlue: return osContinue;
|
||||
case kOk: return Execute();
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
return state;
|
||||
@ -1430,6 +1433,63 @@ cOsdObject *CamControl(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// --- cMenuRecording --------------------------------------------------------
|
||||
|
||||
class cMenuRecording : public cOsdMenu {
|
||||
private:
|
||||
const cRecording *recording;
|
||||
public:
|
||||
cMenuRecording(const cRecording *Recording);
|
||||
virtual void Display(void);
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
cMenuRecording::cMenuRecording(const cRecording *Recording)
|
||||
:cOsdMenu(tr("Recording"))
|
||||
{
|
||||
recording = Recording;
|
||||
if (recording)
|
||||
SetHelp(tr("Play"), tr("Rewind"));
|
||||
}
|
||||
|
||||
void cMenuRecording::Display(void)
|
||||
{
|
||||
cOsdMenu::Display();
|
||||
DisplayMenu()->SetRecording(recording);
|
||||
cStatus::MsgOsdTextItem(recording->Info()->Description());
|
||||
}
|
||||
|
||||
eOSState cMenuRecording::ProcessKey(eKeys Key)
|
||||
{
|
||||
switch (Key) {
|
||||
case kUp|k_Repeat:
|
||||
case kUp:
|
||||
case kDown|k_Repeat:
|
||||
case kDown:
|
||||
case kLeft|k_Repeat:
|
||||
case kLeft:
|
||||
case kRight|k_Repeat:
|
||||
case kRight:
|
||||
DisplayMenu()->Scroll(NORMALKEY(Key) == kUp || NORMALKEY(Key) == kLeft, NORMALKEY(Key) == kLeft || NORMALKEY(Key) == kRight);
|
||||
cStatus::MsgOsdTextItem(NULL, NORMALKEY(Key) == kUp);
|
||||
return osContinue;
|
||||
default: break;
|
||||
}
|
||||
|
||||
eOSState state = cOsdMenu::ProcessKey(Key);
|
||||
|
||||
if (state == osUnknown) {
|
||||
switch (Key) {
|
||||
case kRed: Key = kOk; // will play the recording, even if recording commands are defined
|
||||
case kGreen: cRemote::Put(Key, true);
|
||||
// continue with osBack to close the info menu and process the key
|
||||
case kOk: return osBack;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
// --- cMenuRecordingItem ----------------------------------------------------
|
||||
|
||||
class cMenuRecordingItem : public cOsdItem {
|
||||
@ -1530,7 +1590,7 @@ void cMenuRecordings::SetHelpKeys(void)
|
||||
else {
|
||||
NewHelpKeys = 2;
|
||||
cRecording *recording = GetRecording(ri);
|
||||
if (recording && recording->Summary())
|
||||
if (recording && recording->Info()->Title())
|
||||
NewHelpKeys = 3;
|
||||
}
|
||||
}
|
||||
@ -1539,7 +1599,7 @@ void cMenuRecordings::SetHelpKeys(void)
|
||||
case 0: SetHelp(NULL); break;
|
||||
case 1: SetHelp(tr("Open")); break;
|
||||
case 2:
|
||||
case 3: SetHelp(RecordingCommands.Count() ? tr("Commands") : tr("Play"), tr("Rewind"), tr("Delete"), NewHelpKeys == 3 ? tr("Summary") : NULL);
|
||||
case 3: SetHelp(RecordingCommands.Count() ? tr("Commands") : tr("Play"), tr("Rewind"), tr("Delete"), NewHelpKeys == 3 ? tr("Info") : NULL);
|
||||
}
|
||||
helpKeys = NewHelpKeys;
|
||||
}
|
||||
@ -1644,15 +1704,15 @@ eOSState cMenuRecordings::Delete(void)
|
||||
return osContinue;
|
||||
}
|
||||
|
||||
eOSState cMenuRecordings::Summary(void)
|
||||
eOSState cMenuRecordings::Info(void)
|
||||
{
|
||||
if (HasSubMenu() || Count() == 0)
|
||||
return osContinue;
|
||||
cMenuRecordingItem *ri = (cMenuRecordingItem *)Get(Current());
|
||||
if (ri && !ri->IsDirectory()) {
|
||||
cRecording *recording = GetRecording(ri);
|
||||
if (recording && recording->Summary() && *recording->Summary())
|
||||
return AddSubMenu(new cMenuText(tr("Summary"), recording->Summary()));
|
||||
if (recording && recording->Info()->Title())
|
||||
return AddSubMenu(new cMenuRecording(recording));
|
||||
}
|
||||
return osContinue;
|
||||
}
|
||||
@ -1689,7 +1749,7 @@ eOSState cMenuRecordings::ProcessKey(eKeys Key)
|
||||
case kRed: return (helpKeys > 1 && RecordingCommands.Count()) ? Commands() : Play();
|
||||
case kGreen: return Rewind();
|
||||
case kYellow: return Delete();
|
||||
case kBlue: return Summary();
|
||||
case kBlue: return Info();
|
||||
case k1...k9: return Commands(Key);
|
||||
default: break;
|
||||
}
|
||||
@ -2568,36 +2628,43 @@ eOSState cMenuMain::ProcessKey(eKeys Key)
|
||||
|
||||
// --- SetTrackDescriptions --------------------------------------------------
|
||||
|
||||
static void SetTrackDescriptions(void)
|
||||
static void SetTrackDescriptions(bool Live)
|
||||
{
|
||||
cDevice::PrimaryDevice()->ClrAvailableTracks(true);
|
||||
cChannel *Channel = Channels.GetByNumber(cDevice::CurrentChannel());
|
||||
if (Channel) {
|
||||
cSchedulesLock SchedulesLock;
|
||||
const cSchedules *Schedules = cSchedules::Schedules(SchedulesLock);
|
||||
if (Schedules) {
|
||||
const cSchedule *Schedule = Schedules->GetSchedule(Channel->GetChannelID());
|
||||
if (Schedule) {
|
||||
const cEvent *Present = Schedule->GetPresentEvent(true);
|
||||
if (Present) {
|
||||
const cComponents *Components = Present->Components();
|
||||
if (Components) {
|
||||
int indexAudio = 0;
|
||||
int indexDolby = 0;
|
||||
for (int i = 0; i < Components->NumComponents(); i++) {
|
||||
const tComponent *p = Components->Component(i);
|
||||
if (p->stream == 2) {
|
||||
if (p->type == 0x05)
|
||||
cDevice::PrimaryDevice()->SetAvailableTrack(ttDolby, indexDolby++, 0, NULL, p->description);
|
||||
else
|
||||
cDevice::PrimaryDevice()->SetAvailableTrack(ttAudio, indexAudio++, 0, NULL, p->description);
|
||||
}
|
||||
}
|
||||
}
|
||||
const cComponents *Components = NULL;
|
||||
cSchedulesLock SchedulesLock;
|
||||
if (Live) {
|
||||
cChannel *Channel = Channels.GetByNumber(cDevice::CurrentChannel());
|
||||
if (Channel) {
|
||||
const cSchedules *Schedules = cSchedules::Schedules(SchedulesLock);
|
||||
if (Schedules) {
|
||||
const cSchedule *Schedule = Schedules->GetSchedule(Channel->GetChannelID());
|
||||
if (Schedule) {
|
||||
const cEvent *Present = Schedule->GetPresentEvent(true);
|
||||
if (Present)
|
||||
Components = Present->Components();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (cReplayControl::LastReplayed()) {
|
||||
cRecording *Recording = Recordings.GetByName(cReplayControl::LastReplayed());
|
||||
if (Recording)
|
||||
Components = Recording->Info()->Components();
|
||||
}
|
||||
if (Components) {
|
||||
int indexAudio = 0;
|
||||
int indexDolby = 0;
|
||||
for (int i = 0; i < Components->NumComponents(); i++) {
|
||||
const tComponent *p = Components->Component(i);
|
||||
if (p->stream == 2) {
|
||||
if (p->type == 0x05)
|
||||
cDevice::PrimaryDevice()->SetAvailableTrack(ttDolby, indexDolby++, 0, NULL, p->description);
|
||||
else
|
||||
cDevice::PrimaryDevice()->SetAvailableTrack(ttAudio, indexAudio++, 0, NULL, p->description);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- cDisplayChannel -------------------------------------------------------
|
||||
@ -2657,7 +2724,7 @@ void cDisplayChannel::DisplayInfo(void)
|
||||
const cEvent *Present = Schedule->GetPresentEvent(true);
|
||||
const cEvent *Following = Schedule->GetFollowingEvent(true);
|
||||
if (Present != lastPresent || Following != lastFollowing) {
|
||||
SetTrackDescriptions();
|
||||
SetTrackDescriptions(true);
|
||||
displayChannel->SetEvents(Present, Following);
|
||||
cStatus::MsgOsdProgramme(Present ? Present->StartTime() : 0, Present ? Present->Title() : NULL, Present ? Present->ShortText() : NULL, Following ? Following->StartTime() : 0, Following ? Following->Title() : NULL, Following ? Following->ShortText() : NULL);
|
||||
lastPresent = Present;
|
||||
@ -2877,9 +2944,7 @@ cDisplayTracks::cDisplayTracks(void)
|
||||
:cOsdObject(true)
|
||||
{
|
||||
cDevice::PrimaryDevice()->EnsureAudioTrack();
|
||||
// Get the actual audio track descriptions from the EPG if we're not replaying:
|
||||
if (!cDevice::PrimaryDevice()->Replaying() || cTransferControl::ReceiverDevice())
|
||||
SetTrackDescriptions();
|
||||
SetTrackDescriptions(!cDevice::PrimaryDevice()->Replaying() || cTransferControl::ReceiverDevice());
|
||||
currentDisplayTracks = this;
|
||||
numTracks = track = 0;
|
||||
audioChannel = cDevice::PrimaryDevice()->GetAudioChannel();
|
||||
@ -2994,6 +3059,11 @@ eOSState cDisplayTracks::ProcessKey(eKeys Key)
|
||||
|
||||
cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer, bool Pause)
|
||||
{
|
||||
// We're going to manipulate an event here, so we need to prevent
|
||||
// others from modifying any EPG data:
|
||||
cSchedulesLock SchedulesLock;
|
||||
cSchedules::Schedules(SchedulesLock);
|
||||
|
||||
event = NULL;
|
||||
instantId = NULL;
|
||||
fileName = NULL;
|
||||
@ -3011,16 +3081,9 @@ cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer, bool Pause)
|
||||
timer->SetRecording(true);
|
||||
event = timer->Event();
|
||||
|
||||
const char *Title = NULL;
|
||||
const char *Subtitle = NULL;
|
||||
const char *Summary = NULL;
|
||||
if (event || GetEvent()) {
|
||||
Title = event->Title();
|
||||
Subtitle = event->ShortText();
|
||||
Summary = event->Description();
|
||||
dsyslog("Title: '%s' Subtitle: '%s'", Title, Subtitle);
|
||||
}
|
||||
cRecording Recording(timer, Title, Subtitle, Summary);
|
||||
if (event || GetEvent())
|
||||
dsyslog("Title: '%s' Subtitle: '%s'", event->Title(), event->ShortText());
|
||||
cRecording Recording(timer, event);
|
||||
fileName = strdup(Recording.FileName());
|
||||
|
||||
// crude attempt to avoid duplicate recordings:
|
||||
@ -3047,7 +3110,7 @@ cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer, bool Pause)
|
||||
const cChannel *ch = timer->Channel();
|
||||
recorder = new cRecorder(fileName, ch->Ca(), timer->Priority(), ch->Vpid(), ch->Apids(), ch->Dpids(), ch->Spids());
|
||||
if (device->AttachReceiver(recorder)) {
|
||||
Recording.WriteSummary();
|
||||
Recording.WriteInfo();
|
||||
cStatus::MsgRecording(device, Recording.Name());
|
||||
if (!Timer && !cReplayControl::LastReplayed()) // an instant recording, maybe from cRecordControls::PauseLiveVideo()
|
||||
cReplayControl::SetRecording(fileName, Recording.Name());
|
||||
|
4
menu.h
4
menu.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: menu.h 1.69 2005/03/20 10:57:29 kls Exp $
|
||||
* $Id: menu.h 1.70 2005/05/15 14:34:54 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __MENU_H
|
||||
@ -133,7 +133,7 @@ private:
|
||||
eOSState Play(void);
|
||||
eOSState Rewind(void);
|
||||
eOSState Delete(void);
|
||||
eOSState Summary(void);
|
||||
eOSState Info(void);
|
||||
eOSState Commands(eKeys Key = kNone);
|
||||
public:
|
||||
cMenuRecordings(const char *Base = NULL, int Level = 0, bool OpenSubMenus = false);
|
||||
|
146
recording.c
146
recording.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: recording.c 1.98 2005/05/07 15:25:15 kls Exp $
|
||||
* $Id: recording.c 1.99 2005/05/16 14:19:38 kls Exp $
|
||||
*/
|
||||
|
||||
#include "recording.h"
|
||||
@ -45,7 +45,7 @@
|
||||
// end of implementation for brain dead systems
|
||||
|
||||
#define RESUMEFILESUFFIX "/resume%s%s.vdr"
|
||||
#define SUMMARYFILESUFFIX "/summary.vdr"
|
||||
#define INFOFILESUFFIX "/info.vdr"
|
||||
#define MARKSFILESUFFIX "/marks.vdr"
|
||||
|
||||
#define MINDISKSPACE 1024 // MB
|
||||
@ -213,6 +213,58 @@ void cResumeFile::Delete(void)
|
||||
}
|
||||
}
|
||||
|
||||
// --- cRecordingInfo --------------------------------------------------------
|
||||
|
||||
cRecordingInfo::cRecordingInfo(const cEvent *Event)
|
||||
{
|
||||
if (Event) {
|
||||
event = Event;
|
||||
ownEvent = NULL;
|
||||
}
|
||||
else
|
||||
event = ownEvent = new cEvent(tChannelID(), 0);
|
||||
}
|
||||
|
||||
cRecordingInfo::~cRecordingInfo()
|
||||
{
|
||||
delete ownEvent;
|
||||
}
|
||||
|
||||
bool cRecordingInfo::Read(FILE *f)
|
||||
{
|
||||
if (ownEvent) {
|
||||
cReadLine ReadLine;
|
||||
char *s;
|
||||
while ((s = ReadLine.Read(f)) != NULL) {
|
||||
char *t = skipspace(s + 1);
|
||||
switch (*s) {
|
||||
case 'C': {
|
||||
char *p = strchr(t, ' ');
|
||||
if (p)
|
||||
*p = 0; // strips optional channel name
|
||||
if (*t)
|
||||
ownEvent->SetChannelID(tChannelID::FromString(t));
|
||||
}
|
||||
break;
|
||||
default: if (!ownEvent->Parse(s))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cRecordingInfo::Write(FILE *f, const char *Prefix) const
|
||||
{
|
||||
cChannel *channel = Channels.GetByChannelID(event->ChannelID(), true);
|
||||
if (channel)
|
||||
fprintf(f, "%sC %s %s\n", Prefix, *channel->GetChannelID().ToString(), channel->Name());
|
||||
event->Dump(f, Prefix, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
// --- cRecording ------------------------------------------------------------
|
||||
|
||||
#define RESUME_NOT_INITIALIZED (-2)
|
||||
@ -308,7 +360,7 @@ static char *ExchangeChars(char *s, bool ToFileSystem)
|
||||
return s;
|
||||
}
|
||||
|
||||
cRecording::cRecording(cTimer *Timer, const char *Title, const char *Subtitle, const char *Summary)
|
||||
cRecording::cRecording(cTimer *Timer, const cEvent *Event)
|
||||
{
|
||||
resume = RESUME_NOT_INITIALIZED;
|
||||
titleBuffer = NULL;
|
||||
@ -316,7 +368,8 @@ cRecording::cRecording(cTimer *Timer, const char *Title, const char *Subtitle, c
|
||||
fileName = NULL;
|
||||
name = NULL;
|
||||
// set up the actual name:
|
||||
const char *OriginalSubtitle = Subtitle;
|
||||
const char *Title = Event ? Event->Title() : NULL;
|
||||
const char *Subtitle = Event ? Event->ShortText() : NULL;
|
||||
char SubtitleBuffer[MAX_SUBTITLE_LENGTH];
|
||||
if (isempty(Title))
|
||||
Title = Timer->Channel()->Name();
|
||||
@ -347,17 +400,13 @@ cRecording::cRecording(cTimer *Timer, const char *Title, const char *Subtitle, c
|
||||
start = Timer->StartTime();
|
||||
priority = Timer->Priority();
|
||||
lifetime = Timer->Lifetime();
|
||||
// handle summary:
|
||||
summary = !isempty(Timer->Summary()) ? strdup(Timer->Summary()) : NULL;
|
||||
if (!summary) {
|
||||
Subtitle = OriginalSubtitle;
|
||||
if (isempty(Subtitle))
|
||||
Subtitle = "";
|
||||
if (isempty(Summary))
|
||||
Summary = "";
|
||||
if (*Subtitle || *Summary)
|
||||
asprintf(&summary, "%s\n\n%s%s%s", Title, Subtitle, (*Subtitle && *Summary) ? "\n\n" : "", Summary);
|
||||
}
|
||||
// handle info:
|
||||
info = new cRecordingInfo(Event);
|
||||
// this is a somewhat ugly hack to get the 'summary' information from the
|
||||
// timer into the recording info, but it saves us from having to actually
|
||||
// copy the entire event data:
|
||||
if (!isempty(Timer->Summary()))
|
||||
((cEvent *)Event)->SetDescription(Timer->Summary());
|
||||
}
|
||||
|
||||
cRecording::cRecording(const char *FileName)
|
||||
@ -370,7 +419,7 @@ cRecording::cRecording(const char *FileName)
|
||||
char *p = strrchr(FileName, '/');
|
||||
|
||||
name = NULL;
|
||||
summary = NULL;
|
||||
info = new cRecordingInfo;
|
||||
if (p) {
|
||||
time_t now = time(NULL);
|
||||
struct tm tm_r;
|
||||
@ -386,39 +435,17 @@ cRecording::cRecording(const char *FileName)
|
||||
name[p - FileName] = 0;
|
||||
name = ExchangeChars(name, false);
|
||||
}
|
||||
// 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 = MALLOC(char, size + 1); // +1 for terminating 0
|
||||
if (summary) {
|
||||
int rbytes = safe_read(f, summary, size);
|
||||
if (rbytes >= 0) {
|
||||
summary[rbytes] = 0;
|
||||
if (rbytes != size)
|
||||
esyslog("%s: expected %d bytes but read %d", SummaryFileName, size, rbytes);
|
||||
}
|
||||
else {
|
||||
LOG_ERROR_STR(SummaryFileName);
|
||||
free(summary);
|
||||
summary = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
esyslog("can't allocate %d byte of memory for summary file '%s'", size + 1, SummaryFileName);
|
||||
close(f);
|
||||
}
|
||||
else
|
||||
LOG_ERROR_STR(SummaryFileName);
|
||||
// read an optional info file:
|
||||
char *InfoFileName = NULL;
|
||||
asprintf(&InfoFileName, "%s%s", fileName, INFOFILESUFFIX);
|
||||
FILE *f = fopen(InfoFileName, "r");
|
||||
if (f) {
|
||||
info->Read(f);
|
||||
fclose(f);
|
||||
}
|
||||
else if (errno != ENOENT)
|
||||
LOG_ERROR_STR(SummaryFileName);
|
||||
free(SummaryFileName);
|
||||
LOG_ERROR_STR(InfoFileName);
|
||||
free(InfoFileName);
|
||||
}
|
||||
}
|
||||
|
||||
@ -428,7 +455,7 @@ cRecording::~cRecording()
|
||||
free(sortBuffer);
|
||||
free(fileName);
|
||||
free(name);
|
||||
free(summary);
|
||||
delete info;
|
||||
}
|
||||
|
||||
char *cRecording::StripEpisodeName(char *s)
|
||||
@ -568,21 +595,18 @@ bool cRecording::IsEdited(void) const
|
||||
return *s == '%';
|
||||
}
|
||||
|
||||
bool cRecording::WriteSummary(void)
|
||||
bool cRecording::WriteInfo(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);
|
||||
free(SummaryFileName);
|
||||
char *InfoFileName = NULL;
|
||||
asprintf(&InfoFileName, "%s%s", fileName, INFOFILESUFFIX);
|
||||
FILE *f = fopen(InfoFileName, "w");
|
||||
if (f) {
|
||||
info->Write(f);
|
||||
fclose(f);
|
||||
}
|
||||
else
|
||||
LOG_ERROR_STR(InfoFileName);
|
||||
free(InfoFileName);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
26
recording.h
26
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.34 2005/01/16 15:11:31 kls Exp $
|
||||
* $Id: recording.h 1.35 2005/05/16 14:18:43 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __RECORDING_H
|
||||
@ -12,6 +12,7 @@
|
||||
|
||||
#include <time.h>
|
||||
#include "config.h"
|
||||
#include "epg.h"
|
||||
#include "thread.h"
|
||||
#include "timers.h"
|
||||
#include "tools.h"
|
||||
@ -32,6 +33,21 @@ public:
|
||||
void Delete(void);
|
||||
};
|
||||
|
||||
class cRecordingInfo {
|
||||
private:
|
||||
const cEvent *event;
|
||||
cEvent *ownEvent;
|
||||
public:
|
||||
cRecordingInfo(const cEvent *Event = NULL);
|
||||
~cRecordingInfo();
|
||||
const char *Title(void) const { return event->Title(); }
|
||||
const char *ShortText(void) const { return event->ShortText(); }
|
||||
const char *Description(void) const { return event->Description(); }
|
||||
const cComponents *Components(void) const { return event->Components(); }
|
||||
bool Read(FILE *f);
|
||||
bool Write(FILE *f, const char *Prefix = "") const;
|
||||
};
|
||||
|
||||
class cRecording : public cListObject {
|
||||
private:
|
||||
mutable int resume;
|
||||
@ -39,7 +55,7 @@ private:
|
||||
mutable char *sortBuffer;
|
||||
mutable char *fileName;
|
||||
mutable char *name;
|
||||
char *summary;
|
||||
cRecordingInfo *info;
|
||||
static char *StripEpisodeName(char *s);
|
||||
char *SortName(void) const;
|
||||
int GetResume(void) const;
|
||||
@ -47,19 +63,19 @@ public:
|
||||
time_t start;
|
||||
int priority;
|
||||
int lifetime;
|
||||
cRecording(cTimer *Timer, const char *Title, const char *Subtitle, const char *Summary);
|
||||
cRecording(cTimer *Timer, const cEvent *Event);
|
||||
cRecording(const char *FileName);
|
||||
~cRecording();
|
||||
virtual int Compare(const cListObject &ListObject) const;
|
||||
const char *Name(void) const { return name; }
|
||||
const char *FileName(void) const;
|
||||
const char *Title(char Delimiter = ' ', bool NewIndicator = false, int Level = -1) const;
|
||||
const char *Summary(void) const { return summary; }
|
||||
const cRecordingInfo *Info(void) const { return info; }
|
||||
const char *PrefixFileName(char Prefix);
|
||||
int HierarchyLevels(void) const;
|
||||
bool IsNew(void) const { return GetResume() <= 0; }
|
||||
bool IsEdited(void) const;
|
||||
bool WriteSummary(void);
|
||||
bool WriteInfo(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
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: skinclassic.c 1.11 2005/01/09 11:56:29 kls Exp $
|
||||
* $Id: skinclassic.c 1.12 2005/05/16 10:45:07 kls Exp $
|
||||
*/
|
||||
|
||||
#include "skinclassic.h"
|
||||
@ -326,7 +326,33 @@ void cSkinClassicDisplayMenu::SetEvent(const cEvent *Event)
|
||||
|
||||
void cSkinClassicDisplayMenu::SetRecording(const cRecording *Recording)
|
||||
{
|
||||
SetText(Recording->Summary(), false); //TODO
|
||||
if (!Recording)
|
||||
return;
|
||||
const cRecordingInfo *Info = Recording->Info();
|
||||
const cFont *font = cFont::GetFont(fontOsd);
|
||||
int xl = x0 + 10;
|
||||
int y = y2;
|
||||
cTextScroller ts;
|
||||
char t[32];
|
||||
snprintf(t, sizeof(t), "%s %s", *DateString(Recording->start), *TimeString(Recording->start));
|
||||
ts.Set(osd, xl, y, x1 - xl, y3 - y, t, font, Theme.Color(clrMenuEventTime), Theme.Color(clrBackground));
|
||||
y += ts.Height();
|
||||
y += font->Height();
|
||||
const char *Title = Info->Title();
|
||||
if (isempty(Title))
|
||||
Title = Recording->Name();
|
||||
ts.Set(osd, xl, y, x1 - xl, y3 - y, Title, font, Theme.Color(clrMenuEventTitle), Theme.Color(clrBackground));
|
||||
y += ts.Height();
|
||||
if (!isempty(Info->ShortText())) {
|
||||
const cFont *font = cFont::GetFont(fontSml);
|
||||
ts.Set(osd, xl, y, x1 - xl, y3 - y, Info->ShortText(), font, Theme.Color(clrMenuEventShortText), Theme.Color(clrBackground));
|
||||
y += ts.Height();
|
||||
}
|
||||
y += font->Height();
|
||||
if (!isempty(Info->Description())) {
|
||||
textScroller.Set(osd, xl, y, x1 - xl - 2 * ScrollWidth, y3 - y, Info->Description(), font, Theme.Color(clrMenuEventDescription), Theme.Color(clrBackground));
|
||||
SetScrollbar();
|
||||
}
|
||||
}
|
||||
|
||||
void cSkinClassicDisplayMenu::SetText(const char *Text, bool FixedFont)
|
||||
|
4
skins.h
4
skins.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: skins.h 1.7 2005/02/27 14:37:37 kls Exp $
|
||||
* $Id: skins.h 1.8 2005/05/15 14:41:41 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __SKINS_H
|
||||
@ -150,7 +150,7 @@ public:
|
||||
///< that text if necessary.
|
||||
virtual void SetRecording(const cRecording *Recording) = 0;
|
||||
///< Sets the Recording that shall be displayed, using the entire central area
|
||||
///< of the menu. The Recording's 'summary' shall be displayed using a
|
||||
///< of the menu. The Recording's 'description' shall be displayed using a
|
||||
///< cTextScroller, and the Scroll() function will be called to drive scrolling
|
||||
///< that text if necessary.
|
||||
virtual void SetText(const char *Text, bool FixedFont) = 0;
|
||||
|
36
skinsttng.c
36
skinsttng.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: skinsttng.c 1.13 2005/02/27 14:45:19 kls Exp $
|
||||
* $Id: skinsttng.c 1.14 2005/05/16 10:44:58 kls Exp $
|
||||
*/
|
||||
|
||||
// Star Trek: The Next Generation® is a registered trademark of Paramount Pictures
|
||||
@ -576,7 +576,39 @@ void cSkinSTTNGDisplayMenu::SetEvent(const cEvent *Event)
|
||||
|
||||
void cSkinSTTNGDisplayMenu::SetRecording(const cRecording *Recording)
|
||||
{
|
||||
SetText(Recording->Summary(), false); //XXX
|
||||
if (!Recording)
|
||||
return;
|
||||
const cRecordingInfo *Info = Recording->Info();
|
||||
const cFont *font = cFont::GetFont(fontOsd);
|
||||
int xl = x3 + 5;
|
||||
int y = y3;
|
||||
cTextScroller ts;
|
||||
char t[32];
|
||||
snprintf(t, sizeof(t), "%s %s", *DateString(Recording->start), *TimeString(Recording->start));
|
||||
ts.Set(osd, xl, y, x4 - xl, y4 - y, t, font, Theme.Color(clrMenuEventTime), Theme.Color(clrBackground));
|
||||
y += ts.Height();
|
||||
y += font->Height();
|
||||
const char *Title = Info->Title();
|
||||
if (isempty(Title))
|
||||
Title = Recording->Name();
|
||||
ts.Set(osd, xl, y, x4 - xl, y4 - y, Title, font, Theme.Color(clrMenuEventTitle), Theme.Color(clrBackground));
|
||||
y += ts.Height();
|
||||
if (!isempty(Info->ShortText())) {
|
||||
const cFont *font = cFont::GetFont(fontSml);
|
||||
ts.Set(osd, xl, y, x4 - xl, y4 - y, Info->ShortText(), font, Theme.Color(clrMenuEventShortText), Theme.Color(clrBackground));
|
||||
y += ts.Height();
|
||||
}
|
||||
y += font->Height();
|
||||
if (!isempty(Info->Description())) {
|
||||
int yt = y;
|
||||
int yb = y4 - Roundness;
|
||||
textScroller.Set(osd, xl, yt, x4 - xl, yb - yt, Info->Description(), font, Theme.Color(clrMenuEventDescription), Theme.Color(clrBackground));
|
||||
yb = yt + textScroller.Height();
|
||||
osd->DrawEllipse (x1, yt - Roundness, x2, yt, frameColor, -3);
|
||||
osd->DrawRectangle(x1, yt, x2, yb, frameColor);
|
||||
osd->DrawEllipse (x1, yb, x2, yb + Roundness, frameColor, -2);
|
||||
SetScrollbar();
|
||||
}
|
||||
}
|
||||
|
||||
void cSkinSTTNGDisplayMenu::SetText(const char *Text, bool FixedFont)
|
||||
|
47
summary2info.pl
Executable file
47
summary2info.pl
Executable file
@ -0,0 +1,47 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# Convert 'summary.vdr' files to 'info.vdr'
|
||||
#
|
||||
# Converts all 'summary.vdr' files in the video directory to the
|
||||
# 'info.vdr' format as used from VDR version 1.3.25 upward.
|
||||
#
|
||||
# Usage: summary2info.pl /video
|
||||
#
|
||||
# See the main source file 'vdr.c' for copyright information and
|
||||
# how to reach the author.
|
||||
#
|
||||
# $Id: summary2info.pl 1.1 2005/05/15 16:03:10 kls Exp $
|
||||
|
||||
$VideoDir = $ARGV[0] || die "please provide the name of the video directory\n";
|
||||
|
||||
@SummaryFiles = `find "$VideoDir" -name summary.vdr`;
|
||||
|
||||
for $SummaryFile (@SummaryFiles) {
|
||||
chomp($SummaryFile);
|
||||
print STDERR "converting $SummaryFile...";
|
||||
open(F, $SummaryFile) || die "$SummaryFile: $!\n";
|
||||
$line = 0;
|
||||
@data = ();
|
||||
while (<F>) {
|
||||
chomp;
|
||||
if ($_) {
|
||||
$data[$line] .= '|' if ($data[$line]);
|
||||
$data[$line] .= $_;
|
||||
}
|
||||
else {
|
||||
$line++ unless ($_);
|
||||
}
|
||||
}
|
||||
close(F);
|
||||
if ($line == 1) {
|
||||
$data[2] = $data[1];
|
||||
$data[1] = "";
|
||||
}
|
||||
($InfoFile = $SummaryFile) =~ s/summary\.vdr$/info.vdr/;
|
||||
open(F, ">$InfoFile") || die "$InfoFile: $!\n";
|
||||
print F "T $data[0]\n" if ($data[0]);
|
||||
print F "S $data[1]\n" if ($data[1]);
|
||||
print F "D $data[2]\n" if ($data[2]);
|
||||
close(F);
|
||||
print STDERR "done.\n";
|
||||
}
|
18
svdrp.c
18
svdrp.c
@ -10,7 +10,7 @@
|
||||
* and interact with the Video Disk Recorder - or write a full featured
|
||||
* graphical interface that sits on top of an SVDRP connection.
|
||||
*
|
||||
* $Id: svdrp.c 1.70 2005/05/06 13:47:39 kls Exp $
|
||||
* $Id: svdrp.c 1.71 2005/05/16 14:20:25 kls Exp $
|
||||
*/
|
||||
|
||||
#include "svdrp.h"
|
||||
@ -214,7 +214,7 @@ const char *HelpPages[] = {
|
||||
" events at the given time (which must be in time_t form).",
|
||||
"LSTR [ <number> ]\n"
|
||||
" List recordings. Without option, all recordings are listed. Otherwise\n"
|
||||
" the summary for the given recording is listed.",
|
||||
" the information for the given recording is listed.",
|
||||
"LSTT [ <number> ]\n"
|
||||
" List timers. Without option, all timers are listed. Otherwise\n"
|
||||
" only the given timer is listed.",
|
||||
@ -281,7 +281,7 @@ const char *HelpPages[] = {
|
||||
/* SVDRP Reply Codes:
|
||||
|
||||
214 Help message
|
||||
215 EPG data record
|
||||
215 EPG or recording data record
|
||||
220 VDR service ready
|
||||
221 VDR service closing transmission channel
|
||||
250 Requested VDR action okay, completed
|
||||
@ -800,13 +800,15 @@ void cSVDRP::CmdLSTR(const char *Option)
|
||||
if (isnumber(Option)) {
|
||||
cRecording *recording = Recordings.Get(strtol(Option, NULL, 10) - 1);
|
||||
if (recording) {
|
||||
if (recording->Summary()) {
|
||||
char *summary = strdup(recording->Summary());
|
||||
Reply(250, "%s", strreplace(summary,'\n','|'));
|
||||
free(summary);
|
||||
FILE *f = fdopen(file, "w");
|
||||
if (f) {
|
||||
recording->Info()->Write(f, "215-");
|
||||
fflush(f);
|
||||
Reply(215, "End of recording information");
|
||||
// don't 'fclose(f)' here!
|
||||
}
|
||||
else
|
||||
Reply(550, "No summary available");
|
||||
Reply(451, "Can't open file connection");
|
||||
}
|
||||
else
|
||||
Reply(550, "Recording \"%s\" not found", Option);
|
||||
|
21
tools.c
21
tools.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: tools.c 1.91 2005/03/20 14:44:33 kls Exp $
|
||||
* $Id: tools.c 1.92 2005/05/16 09:55:26 kls Exp $
|
||||
*/
|
||||
|
||||
#include "tools.h"
|
||||
@ -571,6 +571,25 @@ cString TimeToString(time_t t)
|
||||
return "???";
|
||||
}
|
||||
|
||||
cString DateString(time_t t)
|
||||
{
|
||||
char buf[32];
|
||||
struct tm tm_r;
|
||||
tm *tm = localtime_r(&t, &tm_r);
|
||||
char *p = stpcpy(buf, WeekDayName(tm->tm_wday));
|
||||
*p++ = ' ';
|
||||
strftime(p, sizeof(buf) - (p - buf), "%d.%m.%Y", tm);
|
||||
return buf;
|
||||
}
|
||||
|
||||
cString TimeString(time_t t)
|
||||
{
|
||||
char buf[25];
|
||||
struct tm tm_r;
|
||||
strftime(buf, sizeof(buf), "%R", localtime_r(&t, &tm_r));
|
||||
return buf;
|
||||
}
|
||||
|
||||
// --- cReadLine -------------------------------------------------------------
|
||||
|
||||
char *cReadLine::Read(FILE *f)
|
||||
|
4
tools.h
4
tools.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: tools.h 1.68 2005/03/20 14:44:24 kls Exp $
|
||||
* $Id: tools.h 1.69 2005/05/16 09:55:19 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __TOOLS_H
|
||||
@ -102,6 +102,8 @@ cString WeekDayName(int WeekDay);
|
||||
cString WeekDayName(time_t t);
|
||||
cString DayDateTime(time_t t = 0);
|
||||
cString TimeToString(time_t t);
|
||||
cString DateString(time_t t);
|
||||
cString TimeString(time_t t);
|
||||
|
||||
class cTimeMs {
|
||||
private:
|
||||
|
10
vdr.5
10
vdr.5
@ -8,7 +8,7 @@
|
||||
.\" License as specified in the file COPYING that comes with the
|
||||
.\" vdr distribution.
|
||||
.\"
|
||||
.\" $Id: vdr.5 1.36 2005/05/07 10:40:23 kls Exp $
|
||||
.\" $Id: vdr.5 1.37 2005/05/16 14:16:48 kls Exp $
|
||||
.\"
|
||||
.TH vdr 5 "19 Mar 2005" "1.3.23" "Video Disk Recorder Files"
|
||||
.SH NAME
|
||||
@ -578,11 +578,13 @@ the current position within the recording, and to implement skipping
|
||||
and fast forward/back functions.
|
||||
See the definition of the \fBcIndexFile\fR class for details about the
|
||||
actual contents of this file.
|
||||
.SS SUMMARY
|
||||
The file \fIsummary.vdr\fR (if present in a recording directory) contains
|
||||
.SS INFO
|
||||
The file \fIinfo.vdr\fR (if present in a recording directory) contains
|
||||
a description of the recording, derived from the EPG data at recording time
|
||||
(if such data was available) or the \fBSummary\fR field of the corresponding
|
||||
timer. This is a plain ASCII file and can contain arbitrary text.
|
||||
timer. This is a plain ASCII file and contains tagged lines like the \fBEPG DATA\fR
|
||||
file (see the description of the \fIepg.data\fR file). Note that the tags
|
||||
c, E, e and V will not appear in an \fIinfo.vdr\fR file.
|
||||
.SS RESUME
|
||||
The file \fIresume.vdr\fR (if present in a recording directory) contains
|
||||
the position within the recording where the last replay session left off.
|
||||
|
Loading…
Reference in New Issue
Block a user