Prepared for more than one DVB card

This commit is contained in:
Klaus Schmidinger 2000-05-01 16:29:46 +02:00
parent f7ac74ede4
commit eff7aa4a3d
12 changed files with 338 additions and 123 deletions

17
HISTORY
View File

@ -32,3 +32,20 @@ Video Disk Recorder Revision History
kick in too early).
- Channel selection is now blocked when recording or replaying.
- Improved process handling.
2000-05-01: Version 0.05
- Prepared for support of more than one DVB card.
- Instant recordings no longer get the name "instant". They now get the name
of the channel, with a prepended '@' character.
- Timers that are not given an explicit Name now use the channel name with
a prepended '@' character.
- If an instant recording is currently active, the Main menu now contains
an option to stop that recording.
- Timers are now only processed when the Menu is not active. So after editing
a timer the effect will take place only after the menu has been closed.
In order to avoid missing a timer event by inadvertently leaving the menu
open, the menu will be closed automatically after about two minutes of
inactivity.
- If a recording is currently being replayed, the Main menu now contains an
option to stop replaying.

6
MANUAL
View File

@ -49,7 +49,7 @@ Video Disk Recorder User's Manual
* Instant Recording
You can start recording the current channel by pressing the "Record"
button. This will create a timer event named "instant" that starts
button. This will create a timer event named "@channelname" that starts
at the current time and records for two hours.
If you want to modify the recording time you need to edit the timer.
Stop instant recording by pressing the "Menu" button and selecting
@ -60,6 +60,8 @@ Video Disk Recorder User's Manual
All recordings are listed in the "Recordings" menu. Browse through the
list with the "Up" and "Down" button and press "Ok" (or the "Red" button)
to start playback.
Playback can be stopped via the Main menu by selecting "Stop replaying",
or by pressing the "Stop" button outside the menu.
* Replay Control
@ -67,7 +69,7 @@ Video Disk Recorder User's Manual
- "Begin" Positions to beginning of the recording and starts playback
from there.
- "Pause" Halts playback at the current frame. Press again to continue
- "Pause" Halts playback at the current position. Press again to continue
playback.
- "Stop" Stops playback and stores the current position, so that
playback can be resumed later at that point.

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.5 2000/04/24 09:44:15 kls Exp $
* $Id: config.c 1.6 2000/05/01 16:29:31 kls Exp $
*/
#include "config.h"
@ -201,13 +201,15 @@ bool cChannel::Save(FILE *f)
return fprintf(f, "%s:%d:%c:%d:%d:%d:%d:%d:%d\n", name, frequency, polarization, diseqc, srate, vpid, apid, ca, pnr) > 0;
}
bool cChannel::Switch(void)
bool cChannel::Switch(cDvbApi *DvbApi)
{
if (!DvbApi.Recording()) {
if (!DvbApi)
DvbApi = cDvbApi::PrimaryDvbApi;
if (!DvbApi->Recording()) {
isyslog(LOG_INFO, "switching to channel %d", Index() + 1);
CurrentChannel = Index();
for (int i = 3; --i;) {
if (DvbApi.SetChannel(frequency, polarization, diseqc, srate, vpid, apid, ca, pnr))
if (DvbApi->SetChannel(frequency, polarization, diseqc, srate, vpid, apid, ca, pnr))
return true;
esyslog(LOG_ERR, "retrying");
}
@ -217,10 +219,16 @@ bool cChannel::Switch(void)
return false;
}
bool cChannel::SwitchTo(int i)
bool cChannel::SwitchTo(int i, cDvbApi *DvbApi)
{
cChannel *channel = Channels.Get(i);
return channel && channel->Switch();
return channel && channel->Switch(DvbApi);
}
const char *cChannel::GetChannelName(int i)
{
cChannel *channel = Channels.Get(i);
return channel ? channel->name : NULL;
}
// -- cTimer -----------------------------------------------------------------
@ -241,7 +249,9 @@ cTimer::cTimer(bool Instant)
//TODO VPS???
priority = 99;
lifetime = 99;
strcpy(file, Instant ? "instant" : "");
*file = 0;
if (Instant)
snprintf(file, sizeof(file), "@%s", cChannel::GetChannelName(CurrentChannel));
}
int cTimer::TimeToInt(int t)
@ -382,7 +392,7 @@ cTimer *cTimer::GetMatch(void)
{
cTimer *t = (cTimer *)Timers.First();
while (t) {
if (t->Matches())
if (!t->recording && t->Matches())
return t;
t = (cTimer *)t->Next();
}

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.4 2000/04/24 09:44:17 kls Exp $
* $Id: config.h 1.5 2000/05/01 10:45:17 kls Exp $
*/
#ifndef __CONFIG_H
@ -14,6 +14,7 @@
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "dvbapi.h"
#include "tools.h"
#define MaxBuffer 1000
@ -79,8 +80,9 @@ public:
cChannel(const cChannel *Channel);
bool Parse(char *s);
bool Save(FILE *f);
bool Switch(void);
static bool SwitchTo(int i);
bool Switch(cDvbApi *DvbApi = NULL);
static bool SwitchTo(int i, cDvbApi *DvbApi = NULL);
static const char *GetChannelName(int i);
};
class cTimer : public cListObject {

103
dvbapi.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: dvbapi.c 1.8 2000/04/24 15:30:35 kls Exp $
* $Id: dvbapi.c 1.9 2000/05/01 13:18:29 kls Exp $
*/
#include "dvbapi.h"
@ -987,13 +987,16 @@ int cReplayBuffer::Write(int Max)
// --- cDvbApi ---------------------------------------------------------------
cDvbApi::cDvbApi(void)
int cDvbApi::NumDvbApis = 0;
cDvbApi *cDvbApi::dvbApi[MAXDVBAPI] = { NULL };
cDvbApi *cDvbApi::PrimaryDvbApi = NULL;
cDvbApi::cDvbApi(const char *FileName)
{
isMainProcess = true;
pidRecord = pidReplay = 0;
fromRecord = toRecord = -1;
fromReplay = toReplay = -1;
videoDev = open(VIDEODEVICE, O_RDWR | O_NONBLOCK);
videoDev = open(FileName, O_RDWR | O_NONBLOCK);
if (videoDev < 0)
LOG_ERROR;
cols = rows = 0;
@ -1017,20 +1020,84 @@ cDvbApi::cDvbApi(void)
cDvbApi::~cDvbApi()
{
if (isMainProcess) {
if (videoDev >= 0) {
Close();
StopReplay();
StopRecord();
close(videoDev);
}
#if defined(DEBUG_REMOTE) || defined(DEBUG_OSD)
endwin();
#endif
if (videoDev >= 0) {
Close();
StopReplay();
StopRecord();
close(videoDev);
}
#if defined(DEBUG_REMOTE) || defined(DEBUG_OSD)
endwin();
#endif
delete replayTitle;
}
cDvbApi *cDvbApi::GetDvbApi(int Ca)
{
Ca--;
for (int i = MAXDVBAPI; --i >= 0; ) {
if (dvbApi[i]) {
if ((i == Ca || Ca < 0) && !dvbApi[i]->Recording())
return dvbApi[i];
}
}
return NULL;
}
int cDvbApi::Index(void)
{
for (int i = 0; i < MAXDVBAPI; i++) {
if (dvbApi[i] == this)
return i;
}
return -1;
}
bool cDvbApi::Init(void)
{
char fileName[strlen(VIDEODEVICE) + 10];
int i;
NumDvbApis = 0;
for (i = 0; i < MAXDVBAPI; i++) {
sprintf(fileName, "%s%d", VIDEODEVICE, i);
if (access(fileName, F_OK | R_OK | W_OK) == 0) {
dsyslog(LOG_INFO, "probing %s", fileName);
int f = open(fileName, O_RDWR);
if (f >= 0) {
close(f);
dvbApi[i] = new cDvbApi(fileName);
NumDvbApis++;
}
else {
if (errno != ENODEV)
LOG_ERROR_STR(fileName);
break;
}
}
else {
if (errno != ENOENT)
LOG_ERROR_STR(fileName);
break;
}
}
PrimaryDvbApi = dvbApi[0];
if (NumDvbApis > 0)
isyslog(LOG_INFO, "found %d video device%s", NumDvbApis, NumDvbApis > 1 ? "s" : "");
else
esyslog(LOG_ERR, "ERROR: no video device found, giving up!");
return NumDvbApis > 0;
}
void cDvbApi::Cleanup(void)
{
for (int i = 0; i < MAXDVBAPI; i++) {
delete dvbApi[i];
dvbApi[i] = NULL;
}
PrimaryDvbApi = NULL;
}
#ifdef DEBUG_OSD
void cDvbApi::SetColor(eDvbColor colorFg, eDvbColor colorBg)
{
@ -1100,7 +1167,9 @@ void cDvbApi::Open(int w, int h)
void cDvbApi::Close(void)
{
#ifndef DEBUG_OSD
#ifdef DEBUG_OSD
delwin(window);
#else
Cmd(OSD_Close);
#endif
lastProgress = -1;
@ -1247,6 +1316,8 @@ bool cDvbApi::StartRecord(const char *FileName)
}
if (videoDev >= 0) {
StopReplay(); // TODO: remove this if the driver is able to do record and replay at the same time
// Check FileName:
if (!FileName) {
@ -1285,7 +1356,6 @@ bool cDvbApi::StartRecord(const char *FileName)
// This is the actual recording process
dsyslog(LOG_INFO, "start recording process (pid=%d)", getpid());
isMainProcess = false;
bool DataStreamBroken = false;
int fromMain = toRecordPipe[0];
int toMain = fromRecordPipe[1];
@ -1411,7 +1481,6 @@ bool cDvbApi::StartReplay(const char *FileName, const char *Title)
// This is the actual replaying process
dsyslog(LOG_INFO, "start replaying process (pid=%d)", getpid());
isMainProcess = false;
int fromMain = toReplayPipe[0];
int toMain = fromReplayPipe[1];
cReplayBuffer *Buffer = new cReplayBuffer(&videoDev, FileName);

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.8 2000/04/24 15:31:07 kls Exp $
* $Id: dvbapi.h 1.9 2000/05/01 12:46:25 kls Exp $
*/
#ifndef __DVBAPI_H
@ -43,10 +43,29 @@ enum eDvbColor { clrBackground,
class cDvbApi {
private:
int videoDev;
cDvbApi(const char *FileName);
public:
cDvbApi(void);
~cDvbApi();
#define MAXDVBAPI 2
static int NumDvbApis;
private:
static cDvbApi *dvbApi[MAXDVBAPI];
public:
static cDvbApi *PrimaryDvbApi;
static cDvbApi *GetDvbApi(int Ca = 0);
// Selects a free DVB device, starting with the highest device number.
// If Ca is nor 0, the device with the given number will be returned
// if it is not currently recording.
int Index(void);
// Returns the index of this DvbApi.
static bool Init(void);
// Initializes the DVB API and probes for existing DVB devices.
// Must be called before accessing any DVB functions.
static void Cleanup(void);
// Closes down all DVB devices.
// Must be called at the end of the program.
// On Screen Display facilities
private:
@ -91,7 +110,6 @@ private:
dvbSkip,
dvbGetIndex,
};
bool isMainProcess;
pid_t pidRecord, pidReplay;
int fromRecord, toRecord;
int fromReplay, toReplay;
@ -133,5 +151,5 @@ public:
// beginning of the recording.
bool GetIndex(int *Current, int *Total = NULL);
};
#endif //__DVBAPI_H

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.6 2000/04/24 09:44:23 kls Exp $
* $Id: interface.c 1.7 2000/05/01 10:11:26 kls Exp $
*/
#include "interface.h"
@ -15,8 +15,6 @@
cRcIo RcIo("/dev/ttyS1");
#endif
cDvbApi DvbApi; //XXX member of cInterface???
cInterface Interface;
cInterface::cInterface(void)
@ -36,7 +34,7 @@ void cInterface::Init(void)
void cInterface::Open(int NumCols, int NumLines)
{
if (!open++)
DvbApi.Open(NumCols, NumLines);
cDvbApi::PrimaryDvbApi->Open(NumCols, NumLines);
}
void cInterface::Close(void)
@ -44,7 +42,7 @@ void cInterface::Close(void)
if (open == 1)
Clear();
if (!--open)
DvbApi.Close();
cDvbApi::PrimaryDvbApi->Close();
}
unsigned int cInterface::GetCh(bool Wait)
@ -91,13 +89,13 @@ eKeys cInterface::Wait(int Seconds, bool KeepChar)
void cInterface::Clear(void)
{
if (open)
DvbApi.Clear();
cDvbApi::PrimaryDvbApi->Clear();
}
void cInterface::ClearEol(int x, int y, eDvbColor Color)
{
if (open)
DvbApi.ClrEol(x, y, Color);
cDvbApi::PrimaryDvbApi->ClrEol(x, y, Color);
}
void cInterface::SetCols(int *c)
@ -112,7 +110,7 @@ void cInterface::SetCols(int *c)
void cInterface::Write(int x, int y, const char *s, eDvbColor FgColor, eDvbColor BgColor)
{
if (open)
DvbApi.Text(x, y, s, FgColor, BgColor);
cDvbApi::PrimaryDvbApi->Text(x, y, s, FgColor, BgColor);
}
void cInterface::WriteText(int x, int y, const char *s, bool Current)
@ -198,8 +196,8 @@ void cInterface::HelpButton(int Index, const char *Text, eDvbColor FgColor, eDvb
int l = (w - strlen(Text)) / 2;
if (l < 0)
l = 0;
DvbApi.Fill(Index * w, -1, w, 1, BgColor);
DvbApi.Text(Index * w + l, -1, Text, FgColor, BgColor);
cDvbApi::PrimaryDvbApi->Fill(Index * w, -1, w, 1, BgColor);
cDvbApi::PrimaryDvbApi->Text(Index * w + l, -1, Text, FgColor, BgColor);
}
}
@ -337,3 +335,9 @@ void cInterface::DisplayChannel(int Number, const char *Name)
Close();
}
}
bool cInterface::Recording(void)
{
// This is located here because the Interface has to do with the "PrimaryDvbApi" anyway
return cDvbApi::PrimaryDvbApi->Recording();
}

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: interface.h 1.7 2000/04/24 09:44:25 kls Exp $
* $Id: interface.h 1.8 2000/05/01 10:10:08 kls Exp $
*/
#ifndef __INTERFACE_H
@ -43,9 +43,9 @@ public:
void Help(const char *Red, const char *Green = NULL, const char *Yellow = NULL, const char *Blue = NULL);
void LearnKeys(void);
void DisplayChannel(int Number, const char *Name = NULL);
bool Recording(void);
};
extern cInterface Interface;
extern cDvbApi DvbApi; //XXX member of cInterface???
#endif //__INTERFACE_H

151
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.12 2000/04/30 11:10:49 kls Exp $
* $Id: menu.c 1.13 2000/05/01 16:29:46 kls Exp $
*/
#include "menu.h"
@ -12,9 +12,10 @@
#include <stdio.h>
#include <string.h>
#include "config.h"
#include "dvbapi.h"
#include "recording.h"
#define MENUTIMEOUT 120 // seconds
const char *FileNameChars = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789-.# ";
// --- cMenuEditItem ---------------------------------------------------------
@ -744,7 +745,7 @@ eOSState cMenuEditTimer::ProcessKey(eKeys Key)
if (state == osUnknown) {
if (Key == kOk) {
if (!*data.file)
strcpy(data.file, "unnamed");
strcpy(data.file, cChannel::GetChannelName(data.channel - 1));
if (timer && memcmp(timer, &data, sizeof(data)) != 0) {
*timer = data;
Timers.Save();
@ -991,15 +992,25 @@ eOSState cMenuRecordings::ProcessKey(eKeys Key)
// --- cMenuMain -------------------------------------------------------------
cMenuMain::cMenuMain(bool Recording)
#define STOP_RECORDING "Stop recording "
cMenuMain::cMenuMain(bool Replaying)
:cOsdMenu("Main")
{
Add(new cOsdItem("Channels", osChannels));
Add(new cOsdItem("Timer", osTimer));
Add(new cOsdItem("Recordings", osRecordings));
if (Recording)
Add(new cOsdItem("Stop Recording", osStopRecord));
if (Replaying)
Add(new cOsdItem("Stop replaying", osStopReplay));
const char *s = NULL;
while ((s = cRecordControls::GetInstantId(s)) != NULL) {
char *buffer = NULL;
asprintf(&buffer, "%s%s", STOP_RECORDING, s);
Add(new cOsdItem(buffer, osStopRecord));
delete buffer;
}
Display();
lastActivity = time(NULL);
}
eOSState cMenuMain::ProcessKey(eKeys Key)
@ -1010,42 +1021,55 @@ eOSState cMenuMain::ProcessKey(eKeys Key)
case osChannels: return AddSubMenu(new cMenuChannels);
case osTimer: return AddSubMenu(new cMenuTimers);
case osRecordings: return AddSubMenu(new cMenuRecordings);
case osStopRecord: if (!Interface.Confirm("Stop Recording?"))
return osContinue;
case osStopRecord: if (Interface.Confirm("Stop Recording?")) {
cOsdItem *item = Get(Current());
if (item) {
cRecordControls::Stop(item->Text() + strlen(STOP_RECORDING));
return osEnd;
}
}
default: if (Key == kMenu)
state = osEnd;
}
if (Key != kNone)
lastActivity = time(NULL);
else if (time(NULL) - lastActivity > MENUTIMEOUT)
state = osEnd;
return state;
}
// --- cRecordControl --------------------------------------------------------
cRecordControl::cRecordControl(cTimer *Timer)
cRecordControl::cRecordControl(cDvbApi *DvbApi, cTimer *Timer)
{
instantId = NULL;
dvbApi = DvbApi;
if (!dvbApi) dvbApi = cDvbApi::PrimaryDvbApi;//XXX
timer = Timer;
isInstant = !timer;
if (!timer) {
timer = new cTimer(true);
Timers.Add(timer);
Timers.Save();
asprintf(&instantId, cDvbApi::NumDvbApis > 1 ? "%s on %d" : "%s", cChannel::GetChannelName(timer->channel - 1), dvbApi->Index() + 1);
}
timer->SetRecording(true);
cChannel::SwitchTo(timer->channel - 1);
cChannel::SwitchTo(timer->channel - 1, dvbApi);
cRecording Recording(timer);
DvbApi.StartRecord(Recording.FileName());
dvbApi->StartRecord(Recording.FileName());
}
cRecordControl::~cRecordControl()
{
Stop(true);
delete instantId;
}
void cRecordControl::Stop(bool KeepInstant)
{
if (timer) {
DvbApi.StopRecord();
dvbApi->StopRecord();
timer->SetRecording(false);
if ((isInstant && !KeepInstant) || (timer->IsSingleEvent() && !timer->Matches())) {
if ((IsInstant() && !KeepInstant) || (timer->IsSingleEvent() && !timer->Matches())) {
// checking timer->Matches() to make sure we don't delete the timer
// if the program was cancelled before the timer's stop time!
isyslog(LOG_INFO, "deleting timer %d", timer->Index() + 1);
@ -1056,17 +1080,73 @@ void cRecordControl::Stop(bool KeepInstant)
}
}
eOSState cRecordControl::ProcessKey(eKeys Key)
bool cRecordControl::Process(void)
{
if (!timer->Matches())
return osEnd;
switch (Key) {
case kNone: break;
case kMenu: return osMenu; // allow switching to menu
default: return osUnknown; // anything else is blocked while recording
}
if (!timer || !timer->Matches())
return false;
AssertFreeDiskSpace();
return osContinue;
return true;
}
// --- cRecordControls -------------------------------------------------------
cRecordControl *cRecordControls::RecordControls[MAXDVBAPI] = { NULL };
bool cRecordControls::Start(cTimer *Timer)
{
int ch = Timer ? Timer->channel - 1 : CurrentChannel;
cChannel *channel = Channels.Get(ch);
if (channel) {
cDvbApi *dvbApi = cDvbApi::GetDvbApi(channel->ca);
if (dvbApi) {
for (int i = 0; i < MAXDVBAPI; i++) {
if (!RecordControls[i]) {
RecordControls[i] = new cRecordControl(dvbApi, Timer);
return true;
}
}
}
else
esyslog(LOG_ERR, "ERROR: no free DVB device to record channel %d!", ch);
}
else
esyslog(LOG_ERR, "ERROR: channel %d not defined!", ch + 1);
return false;
}
void cRecordControls::Stop(const char *InstantId)
{
for (int i = 0; i < MAXDVBAPI; i++) {
if (RecordControls[i]) {
const char *id = RecordControls[i]->InstantId();
if (id && strcmp(id, InstantId) == 0)
RecordControls[i]->Stop();
}
}
}
const char *cRecordControls::GetInstantId(const char *LastInstantId)
{
for (int i = 0; i < MAXDVBAPI; i++) {
if (RecordControls[i]) {
if (!LastInstantId && RecordControls[i]->InstantId())
return RecordControls[i]->InstantId();
if (LastInstantId && LastInstantId == RecordControls[i]->InstantId())
LastInstantId = NULL;
}
}
return NULL;
}
void cRecordControls::Process(void)
{
for (int i = 0; i < MAXDVBAPI; i++) {
if (RecordControls[i]) {
if (!RecordControls[i]->Process())
DELETENULL(RecordControls[i]);
}
}
}
// --- cReplayControl --------------------------------------------------------
@ -1076,15 +1156,16 @@ char *cReplayControl::title = NULL;
cReplayControl::cReplayControl(void)
{
dvbApi = cDvbApi::PrimaryDvbApi;//XXX
visible = shown = false;
if (fileName)
DvbApi.StartReplay(fileName, title);
dvbApi->StartReplay(fileName, title);
}
cReplayControl::~cReplayControl()
{
Hide();
DvbApi.StopReplay();
dvbApi->StopReplay();
}
void cReplayControl::SetRecording(const char *FileName, const char *Title)
@ -1100,7 +1181,7 @@ void cReplayControl::Show(void)
if (!visible) {
Interface.Open(MenuColumns, -3);
needsFastResponse = visible = true;
shown = DvbApi.ShowProgress(true);
shown = dvbApi->ShowProgress(true);
}
}
@ -1114,20 +1195,20 @@ void cReplayControl::Hide(void)
eOSState cReplayControl::ProcessKey(eKeys Key)
{
if (!DvbApi.Replaying())
if (!dvbApi->Replaying())
return osEnd;
if (visible)
shown = DvbApi.ShowProgress(!shown) || shown;
shown = dvbApi->ShowProgress(!shown) || shown;
switch (Key) {
case kBegin: DvbApi.Skip(-INT_MAX); break;
case kPause: DvbApi.PauseReplay(); break;
case kBegin: dvbApi->Skip(-INT_MAX); break;
case kPause: dvbApi->PauseReplay(); break;
case kStop: Hide();
DvbApi.StopReplay();
dvbApi->StopReplay();
return osEnd;
case kSearchBack: DvbApi.FastRewind(); break;
case kSearchForward: DvbApi.FastForward(); break;
case kSkipBack: DvbApi.Skip(-60); break;
case kSkipForward: DvbApi.Skip(60); break;
case kSearchBack: dvbApi->FastRewind(); break;
case kSearchForward: dvbApi->FastForward(); break;
case kSkipBack: dvbApi->Skip(-60); break;
case kSkipForward: dvbApi->Skip(60); break;
case kMenu: Hide(); return osMenu; // allow direct switching to menu
case kOk: visible ? Hide() : Show(); break;
default: return osUnknown;

32
menu.h
View File

@ -4,34 +4,52 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: menu.h 1.8 2000/04/30 10:58:49 kls Exp $
* $Id: menu.h 1.9 2000/05/01 15:16:23 kls Exp $
*/
#ifndef _MENU_H
#define _MENU_H
#define _GNU_SOURCE
#include "dvbapi.h"
#include "osd.h"
class cMenuMain : public cOsdMenu {
private:
time_t lastActivity;
public:
cMenuMain(bool Recording);
cMenuMain(bool Replaying);
virtual eOSState ProcessKey(eKeys Key);
};
class cRecordControl : public cOsdBase {
class cRecordControl {
private:
cDvbApi *dvbApi;
cTimer *timer;
bool isInstant;
char *instantId;
public:
cRecordControl(cTimer *Timer = NULL);
cRecordControl(cDvbApi *DvbApi, cTimer *Timer = NULL);
virtual ~cRecordControl();
virtual eOSState ProcessKey(eKeys Key);
bool Process(void);
void Stop(bool KeepInstant = false);
bool IsInstant(void) { return isInstant; }
bool IsInstant(void) { return instantId; }
const char *InstantId(void) { return instantId; }
};
class cRecordControls {
private:
static cRecordControl *RecordControls[MAXDVBAPI];
public:
static bool Start(cTimer *Timer = NULL);
static void Stop(const char *InstantId);
static const char *GetInstantId(const char *LastInstantId);
static void Process(void);
};
class cReplayControl : public cOsdBase {
private:
cDvbApi *dvbApi;
bool visible, shown;
void Show(void);
void Hide(void);

3
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.7 2000/04/30 10:37:15 kls Exp $
* $Id: osd.h 1.8 2000/05/01 15:16:00 kls Exp $
*/
#ifndef __OSD_H
@ -24,6 +24,7 @@ enum eOSState { osUnknown,
osRecordings,
osReplay,
osStopRecord,
osStopReplay,
osBack,
osEnd,
};

61
vdr.c
View File

@ -22,11 +22,12 @@
*
* The project's page is at http://www.cadsoft.de/people/kls/vdr
*
* $Id: vdr.c 1.16 2000/04/30 11:06:41 kls Exp $
* $Id: vdr.c 1.17 2000/05/01 15:24:56 kls Exp $
*/
#include <signal.h>
#include "config.h"
#include "dvbapi.h"
#include "interface.h"
#include "menu.h"
#include "recording.h"
@ -52,6 +53,9 @@ int main(int argc, char *argv[])
openlog("vdr", LOG_PID | LOG_CONS, LOG_USER);
isyslog(LOG_INFO, "started");
if (!cDvbApi::Init())
return 1;
Channels.Load("channels.conf");
Timers.Load("timers.conf");
if (!Keys.Load(KEYS_CONF))
@ -65,7 +69,6 @@ int main(int argc, char *argv[])
if (signal(SIGTERM, SignalHandler) == SIG_IGN) signal(SIGTERM, SIG_IGN);
cMenuMain *Menu = NULL;
cRecordControl *RecordControl = NULL;
cReplayControl *ReplayControl = NULL;
int dcTime = 0, dcNumber = 0;
int LastChannel = -1;
@ -73,7 +76,7 @@ int main(int argc, char *argv[])
while (!Interrupted) {
// Channel display:
if (CurrentChannel != LastChannel) {
if (!RecordControl) {
if (!Menu && !Interface.Recording()) {
cChannel *channel = Channels.Get(CurrentChannel);
if (channel)
Interface.DisplayChannel(CurrentChannel + 1, channel->name);
@ -86,43 +89,32 @@ int main(int argc, char *argv[])
dcNumber = 0;
LastChannel = -1; // in case an invalid channel number was entered!
}
// Timer Processing:
else if (!RecordControl) {
// Timers and Recordings:
if (!Menu) {
cTimer *Timer = cTimer::GetMatch();
if (Timer) {
DELETENULL(Menu);
DELETENULL(ReplayControl);
RecordControl = new cRecordControl(Timer);
if (!cRecordControls::Start(Timer)) {
//TODO need to do something to prevent the timer from hitting over and over again...
}
}
cRecordControls::Process();
}
// User Input:
cOsdBase **Interact = Menu ? (cOsdBase **)&Menu : (cOsdBase **)&ReplayControl;
eKeys key = Interface.GetKey(!*Interact || !(*Interact)->NeedsFastResponse());
if (RecordControl) {
switch (RecordControl->ProcessKey(key)) {
case osMenu: break;
case osEnd: DELETENULL(Menu); // must make sure no menu uses the timer
DELETENULL(RecordControl);
break;
default: if (!*Interact)
continue;
}
}
if (*Interact) {
switch ((*Interact)->ProcessKey(key)) {
case osMenu: DELETENULL(Menu);
Menu = new cMenuMain(RecordControl && RecordControl->IsInstant());
Menu = new cMenuMain(ReplayControl);
break;
case osReplay: DELETENULL(Menu);
DELETENULL(ReplayControl);
ReplayControl = new cReplayControl;
break;
case osStopRecord: if (RecordControl) {
RecordControl->Stop();
DELETENULL(Menu); // must make sure no menu uses the timer
DELETENULL(RecordControl);
}
break;
case osStopReplay:
DELETENULL(*Interact);
DELETENULL(ReplayControl);
break;
case osBack:
case osEnd: DELETENULL(*Interact);
break;
@ -134,28 +126,29 @@ int main(int argc, char *argv[])
// Direct Channel Select (input):
case k0: case k1: case k2: case k3: case k4: case k5: case k6: case k7: case k8: case k9:
{
if (!RecordControl) {
if (!Interface.Recording()) {
dcNumber = dcNumber * 10 + key - k0;
dcTime = time_ms();
Interface.DisplayChannel(dcNumber);
}
}
break;
// Instant Recording:
case kRecord: if (!RecordControl)
RecordControl = new cRecordControl;
break;
// Menu Control:
case kMenu: Menu = new cMenuMain(RecordControl && RecordControl->IsInstant()); break;
// Up/Down Channel Select:
case kUp:
case kDown: if (!RecordControl) {
case kDown: if (!Interface.Recording()) {
int n = CurrentChannel + (key == kUp ? 1 : -1);
cChannel *channel = Channels.Get(n);
if (channel)
channel->Switch();
}
break;
// Instant Recording:
case kRecord: DELETENULL(Menu);
if (!cRecordControls::Start())
Interface.Error("No free DVB device to record!");
break;
// Menu Control:
case kMenu: Menu = new cMenuMain(ReplayControl); break;
// Viewing Control:
case kOk: LastChannel = -1; break; // forces channel display
default: break;
@ -164,8 +157,8 @@ int main(int argc, char *argv[])
}
isyslog(LOG_INFO, "caught signal %d", Interrupted);
delete Menu;
delete RecordControl;
delete ReplayControl;
cDvbApi::Cleanup();
isyslog(LOG_INFO, "exiting");
closelog();
return 0;