Version 0.05

- Support for more than one DVB card.
- Simultaneous record and replay (with two DVB cards).
- 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.
- Displaying the recording DVB interface status in the decimal points of the
  RCU display.
- Reduced the number of remote control keys. Modified the key assignments for
  the PC keyboard to better resemble the "up-down-left-right-ok" layout on
  menu controlling remote control units.
This commit is contained in:
Klaus Schmidinger 2000-05-27 18:00:00 +02:00
parent 85b8e41e8b
commit 9599a8fd8a
21 changed files with 679 additions and 263 deletions

6
BUGS
View File

@ -1,7 +1,7 @@
Video Disk Recorder - Known Bugs
--------------------------------
* Sometimes picture and sound drift apart.
* Sometimes the picture "jumps" as if a frame is skipped.
Presumably this is a problem in the card driver or firmware?
* When the on-screen display is activated during recording,
@ -10,7 +10,3 @@ Video Disk Recorder - Known Bugs
I assume this is a problem in the driver of firmware.
There is no such problem in replay mode.
* After a replay session the screen may go blank.
Haven't figured out yet how to ensure that it switches back to
the current channel.

23
HISTORY
View File

@ -32,3 +32,26 @@ Video Disk Recorder Revision History
kick in too early).
- Channel selection is now blocked when recording or replaying.
- Improved process handling.
2000-05-27: Version 0.05
- Support for more than one DVB card.
- Simultaneous record and replay (with two DVB cards).
- 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.
- Displaying the recording DVB interface status in the decimal points of the
RCU display.
- Reduced the number of remote control keys. Modified the key assignments for
the PC keyboard to better resemble the "up-down-left-right-ok" layout on
menu controlling remote control units.

26
INSTALL
View File

@ -12,7 +12,7 @@ about that driver). For example, if the DVB driver was
extracted into the directory /home/kls/vdr/DVB, then this
package should be extracted into /home/kls/vdr/VDR.
This program requires the card driver version 0.04 or higher
This program requires the card driver version 0.05 or higher
to work properly.
After extracting the package, change into the VDR directory
@ -30,6 +30,10 @@ interface. These modes are useful when testing new menus if you
only have a remote connection to the VDR (which, in my case, is
located in the living room and has neither a monitor nor a keyboard).
When running, the 'vdr' program writes status information into the
system log file (/var/log/messages). You may want to watch these
messages (tail -f /var/log/mesages) to see if there are any problems.
The video data directory:
-------------------------
@ -69,7 +73,9 @@ key after the other so that it can learn the various key codes. You will
at least need to provide an "Up" and a "Down" key, so that you can switch
channels. The rest of the key definitions is optional, but the more keys
you define, the more you will be able to navigate through the menus and
control recording/replaying.
control recording/replaying. The program uses only a very small number
of keys which have multiple meanings in the various modes (see MANUAL
for a detailed description).
If the program has been built with "DEBUG_REMOTE=1", it will use the
key configuration file 'keys-pc.conf', so that you won't loose data
when switching between normal and debug mode.
@ -77,19 +83,11 @@ when switching between normal and debug mode.
The default PC key assignments are:
Up, Down, Left, Right Crsr keys in numeric block
Menu '5' in numeric block
Ok Enter
Back Backspace
0..9 '0'..'9' in top row
Menu 'Home' in numeric block
Ok '5' in numeric block
Back 'End' in numeric block
Red, Green, Yellow, Blue 'F1'..'F4'
Record 'r'
Pause 'p'
Stop 's'
Begin 'B'
SearchForward 'f'
SearchBack 'b'
SkipForward 'PgDn' in numeric block
SkipBack 'PgUp' in numeric block
0..9 '0'..'9' in top row
If you prefer different key assignments, simply delete the file
'keys-pc.conf' and restart 'vdr' to get into learning mode.

65
MANUAL
View File

@ -1,6 +1,28 @@
Video Disk Recorder User's Manual
---------------------------------
* Remote Control Keys
The following remote control keys are used to control the VDR
operation. To keep the number of different keys as small as
possible, several keys have different meanings in the various
modes:
Key Normal Main Channels Timer Edit/New Recordings Replay
Up Ch up Crsr up Crsr up Crsr up Crsr up Crsr up Begin
Down Ch down Crsr down Crsr down Crsr down Crsr down Crsr down Pause
Left - - - Disable Decrement - Search back
Right - - - Enable Increment - Search forward
Ok Ch display Select Switch Edit Accept Play Progress disp.
Menu Menu on Menu off Menu off Menu off Menu off Menu off Menu on
Back - Menu off Main menu Main menu Discard Main menu -
Red - Record Edit Edit - Play -
Green - - New New - - Skip -60s
Yellow - - Delete Delete - Delete Skip +60s
Blue - - Mark Mark - - Stop
0..9 Ch select - - - Numeric inp. - -
* Navigating through the On Screen Menus
The "Main" menu can be called up with the "Menu" key of your remote
@ -22,10 +44,10 @@ Video Disk Recorder User's Manual
keys. "Ok" then confirms the changes.
The "Red", "Green", "Yellow" and "Blue" buttons have special meanings
in the various menus and are listed at the bottom of the on-screen-display.
in various menus and are listed at the bottom of the on-screen-display.
At any point in the menu system, pressing the "Menu" key again will
immediately leave the menu system.
immediately leave the menu system (discarding any pending changes).
* Selecting a Channel
@ -48,35 +70,40 @@ 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
at the current time and records for two hours.
You can start recording the current channel by pressing the "Red" button
in the Main menu. 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 disabling or deleting the timer.
Stop instant recording by pressing the "Menu" button and selecting
"Stop Recording", or by disabling the timer.
* Replaying a Recording
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 "Blue" button outside the menu.
* Replay Control
The following keys have the listed meaning in Replay mode:
- "Begin" Positions to beginning of the recording and starts playback
from there.
- "Pause" Halts playback at the current frame. Press again to continue
playback.
- "Stop" Stops playback and stores the current position, so that
playback can be resumed later at that point.
- "Search" Runs playback forward or backward at a higher speed. Press
again to resume normal speed.
- "Skip" Skips about 60 seconds forward or backward.
- "Ok" Brings up the replay progress display, which shows the date,
time and title of the recording, a progress bar and the
current and total time of the recording.
Press "Ok" again to turn off the progress display.
- Up Positions to beginning of the recording and starts playback
from there.
- Down Halts playback at the current position. Press again to continue
playback.
- Blue Stops playback and stores the current position, so that
playback can be resumed later at that point.
- Left
Right Runs playback forward or backward at a higher speed. Press
again to resume normal speed.
- Green
Yellow Skips about 60 seconds back or forward.
- Ok Brings up the replay progress display, which shows the date,
time and title of the recording, a progress bar and the
current and total time of the recording.
Press "Ok" again to turn off the progress display.
* Programming the Timer

7
TODO
View File

@ -1,11 +1,8 @@
TODO list for the Video Disk Recorder project
---------------------------------------------
* Make it work with two DVB-S PCI cards to allow simultaneous
recording of one programme, while replaying another programme
(or maybe the same one, but time delayed).
Maybe we can do this with only a single card, if the card
driver/firmware allows simultaneuos record/playback?
* Implement simultaneous record/replay with a single DVB card once
the card driver/firmware allows this.
* Implement "on-disk editing" to allow "cutting out" of certain
scenes in order to archive them (or, reversely, cut out
commercial breaks).

View File

@ -1,14 +1,14 @@
RTL:12188:h:1:27500:163:104:0:0
Sat.1:12552:v:1:22000:163:104:0:0
Pro 7:12480:v:1:27500:255:256:0:0
Pro-7:12480:v:1:27500:255:256:0:0
RTL2:12188:h:1:27500:166:128:0:0
ARD:11837:h:1:27500:101:102:0:0
BR3:11837:h:1:27500:201:202:0:0
Hessen 3:11837:h:1:27500:301:302:0:0
Hessen-3:11837:h:1:27500:301:302:0:0
N3:11837:h:1:27500:401:402:0:0
SR3:11837:h:1:27500:501:502:0:0
WDR:11837:h:1:27500:601:602:0:0
BR alpha:11837:h:1:27500:701:702:0:0
BR-alpha:11837:h:1:27500:701:702:0:0
SWR BW:11837:h:1:27500:801:802:0:0
Phoenix:11837:h:1:27500:901:902:0:0
ZDF:11954:h:1:27500:110:120:0:0
@ -41,8 +41,14 @@ ORB:12722:h:1:22000:501:502:0:0
B1:12722:h:1:22000:601:602:0:0
ARD Online-Kanal:12722:h:1:22000:8191:701:0:0
Premiere World Promo:11798:h:1:27500:255:256:0:0
Premiere:11798:h:1:27500:511:512:1:10
Star Kino:11798:h:1:27500:767:768:1:9
Cine Action:11798:h:1:27500:1023:1024:1:20
Cine Comedy:11798:h:1:27500:1279:1280:1:29
Sci Fantasy:11798:h:1:27500:1535:1536:1:41
Romantic Movies:11798:h:1:27500:1791:1792:1:11
Studio Universal:11798:h:1:27500:2047:2048:1:21
TV Niepokalanow:11876:h:1:27500:305:321:0:0
Premiere:11798:h:1:27500:1023:1024:1:10
Mosaico:11934:v:1:27500:165:100:0:0
Andalucia TV:11934:v:1:27500:166:104:0:0
TVC Internacional:11934:v:1:27500:167:108:0:0

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.7 2000/05/27 14:44:15 kls Exp $
*/
#include "config.h"
@ -23,6 +23,10 @@ tKey keyTable[] = { // "Up" and "Down" must be the first two keys!
{ kBack, "Back", 0 },
{ kLeft, "Left", 0 },
{ kRight, "Right", 0 },
{ kRed, "Red", 0 },
{ kGreen, "Green", 0 },
{ kYellow, "Yellow", 0 },
{ kBlue, "Blue", 0 },
{ k0, "0", 0 },
{ k1, "1", 0 },
{ k2, "2", 0 },
@ -33,18 +37,6 @@ tKey keyTable[] = { // "Up" and "Down" must be the first two keys!
{ k7, "7", 0 },
{ k8, "8", 0 },
{ k9, "9", 0 },
{ kRed, "Red", 0 },
{ kGreen, "Green", 0 },
{ kYellow, "Yellow", 0 },
{ kBlue, "Blue", 0 },
{ kRecord, "Record", 0 },
{ kPause, "Pause", 0 },
{ kStop, "Stop", 0 },
{ kBegin, "Begin", 0 },
{ kSearchForward, "SearchForward", 0 },
{ kSearchBack, "SearchBack", 0 },
{ kSkipForward, "SkipForward", 0 },
{ kSkipBack, "SkipBack", 0 },
{ kNone, "", 0 },
};
@ -201,13 +193,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 +211,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 +241,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 +384,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.6 2000/05/27 14:43:46 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
@ -26,19 +27,11 @@ enum eKeys { // "Up" and "Down" must be the first two keys!
kBack,
kLeft,
kRight,
k0, k1, k2, k3, k4, k5, k6, k7, k8, k9,
kRed,
kGreen,
kYellow,
kBlue,
kRecord,
kPause,
kStop,
kBegin,
kSearchForward,
kSearchBack,
kSkipForward,
kSkipBack,
k0, k1, k2, k3, k4, k5, k6, k7, k8, k9,
kNone
};
@ -79,8 +72,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 {

195
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.10 2000/05/27 14:07:17 kls Exp $
*/
#include "dvbapi.h"
@ -70,8 +70,9 @@ private:
struct tIndex { int offset; uchar type; uchar number; short reserved; };
int f;
char *fileName, *pFileExt;
int last, resume;
int size, last, resume;
tIndex *index;
bool CatchUp(void);
public:
cIndexFile(const char *FileName, bool Record = false);
~cIndexFile();
@ -89,6 +90,7 @@ cIndexFile::cIndexFile(const char *FileName, bool Record)
{
f = -1;
fileName = pFileExt = NULL;
size = 0;
last = resume = -1;
index = NULL;
if (FileName) {
@ -108,18 +110,25 @@ cIndexFile::cIndexFile(const char *FileName, bool Record)
}
last = (buf.st_size + delta) / sizeof(tIndex) - 1;
if (!Record && last >= 0) {
index = new tIndex[last + 1];
int fi = open(fileName, O_RDONLY);
if (fi >= 0) {
if ((int)read(fi, index, buf.st_size) != buf.st_size) {
esyslog(LOG_ERR, "ERROR: can't read from file '%s'", fileName);
delete index;
index = NULL;
size = last + 1;
index = new tIndex[size];
if (index) {
f = open(fileName, O_RDONLY);
if (f >= 0) {
if ((int)read(f, index, buf.st_size) != buf.st_size) {
esyslog(LOG_ERR, "ERROR: can't read from file '%s'", fileName);
delete index;
index = NULL;
close(f);
f = -1;
}
// we don't close f here, see CatchUp()!
}
close(fi);
else
LOG_ERROR_STR(fileName);
}
else
LOG_ERROR_STR(fileName);
esyslog(LOG_ERR, "ERROR: can't allocate %d bytes for index '%s'", size * sizeof(tIndex), fileName);
}
}
else
@ -164,6 +173,46 @@ cIndexFile::~cIndexFile()
delete fileName;
}
bool cIndexFile::CatchUp(void)
{
if (index && f >= 0) {
struct stat buf;
if (fstat(f, &buf) == 0) {
int newLast = buf.st_size / sizeof(tIndex) - 1;
if (newLast > last) {
if (size <= newLast) {
size *= 2;
if (size <= newLast)
size = newLast + 1;
}
index = (tIndex *)realloc(index, size * sizeof(tIndex));
if (index) {
int offset = (last + 1) * sizeof(tIndex);
int delta = (newLast - last) * sizeof(tIndex);
if (lseek(f, offset, SEEK_SET) == offset) {
if (read(f, &index[last + 1], delta) != delta) {
esyslog(LOG_ERR, "ERROR: can't read from index");
delete index;
index = NULL;
close(f);
f = -1;
}
last = newLast;
return true;
}
else
LOG_ERROR;
}
else
esyslog(LOG_ERR, "ERROR: can't realloc() index");
}
}
else
LOG_ERROR;
}
return false;
}
void cIndexFile::Write(uchar PictureType, uchar FileNumber, int FileOffset)
{
if (f >= 0) {
@ -181,6 +230,7 @@ void cIndexFile::Write(uchar PictureType, uchar FileNumber, int FileOffset)
bool cIndexFile::Get(int Index, uchar *FileNumber, int *FileOffset, uchar *PictureType)
{
if (index) {
CatchUp();
if (Index >= 0 && Index <= last) {
*FileNumber = index[Index].number;
*FileOffset = index[Index].offset;
@ -195,10 +245,12 @@ bool cIndexFile::Get(int Index, uchar *FileNumber, int *FileOffset, uchar *Pictu
int cIndexFile::GetNextIFrame(int Index, bool Forward, uchar *FileNumber, int *FileOffset, int *Length)
{
if (index) {
if (Forward)
CatchUp();
int d = Forward ? 1 : -1;
for (;;) {
Index += d;
if (Index >= 0 && Index <= last) {
if (Index >= 0 && Index <= last - 100) { // '- 100': need to stay off the end!
if (index[Index].type == I_FRAME) {
*FileNumber = index[Index].number;
*FileOffset = index[Index].offset;
@ -226,6 +278,7 @@ int cIndexFile::GetNextIFrame(int Index, bool Forward, uchar *FileNumber, int *F
int cIndexFile::Get(uchar FileNumber, int FileOffset)
{
if (index) {
CatchUp();
//TODO implement binary search!
int i;
for (i = 0; i < last; i++) {
@ -842,6 +895,7 @@ void cReplayBuffer::SkipSeconds(int Seconds)
uchar FileNumber;
int FileOffset;
if (index->GetNextIFrame(Index, false, &FileNumber, &FileOffset) >= 0)
if ((Index = index->GetNextIFrame(Index, false, &FileNumber, &FileOffset)) >= 0)
NextFile(FileNumber, FileOffset);
}
}
@ -987,13 +1041,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;
@ -1011,26 +1068,90 @@ cDvbApi::cDvbApi(void)
leaveok(stdscr, TRUE);
window = NULL;
#endif
lastProgress = -1;
lastProgress = lastTotal = -1;
replayTitle = NULL;
}
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)
{
@ -1095,15 +1216,17 @@ void cDvbApi::Open(int w, int h)
SETCOLOR(clrMagenta, 0xB0, 0x00, 0xFC, 255);
SETCOLOR(clrWhite, 0xFC, 0xFC, 0xFC, 255);
lastProgress = -1;
lastProgress = lastTotal = -1;
}
void cDvbApi::Close(void)
{
#ifndef DEBUG_OSD
#ifdef DEBUG_OSD
delwin(window);
#else
Cmd(OSD_Close);
#endif
lastProgress = -1;
lastProgress = lastTotal = -1;
}
void cDvbApi::Clear(void)
@ -1158,8 +1281,9 @@ bool cDvbApi::ShowProgress(bool Initial)
if (Initial) {
if (replayTitle)
Text(0, 0, replayTitle);
Text(-7, 2, cIndexFile::Str(Total));
}
if (Total != lastTotal)
Text(-7, 2, cIndexFile::Str(Total));
#ifdef DEBUG_OSD
int p = cols * Current / Total;
Fill(0, 1, p, 1, clrGreen);
@ -1191,6 +1315,7 @@ bool cDvbApi::ShowProgress(bool Initial)
}
#endif
Text(0, 2, cIndexFile::Str(Current));
lastTotal = Total;
return true;
}
return false;
@ -1247,6 +1372,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 +1412,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];
@ -1371,7 +1497,7 @@ bool cDvbApi::StartReplay(const char *FileName, const char *Title)
StopReplay();
if (videoDev >= 0) {
lastProgress = -1;
lastProgress = lastTotal = -1;
delete replayTitle;
if (Title) {
if ((replayTitle = strdup(Title)) == NULL)
@ -1411,7 +1537,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);
@ -1440,7 +1565,8 @@ bool cDvbApi::StartReplay(const char *FileName, const char *Title)
}
if (FD_ISSET(fromMain, &setIn)) {
switch (readchar(fromMain)) {
case dvbStop: Buffer->Stop(); break;
case dvbStop: SetReplayMode(VID_PLAY_CLEAR_BUFFER);
Buffer->Stop(); break;
case dvbPauseReplay: SetReplayMode(Paused ? VID_PLAY_NORMAL : VID_PLAY_PAUSE);
Paused = !Paused;
FastForward = FastRewind = false;
@ -1459,6 +1585,7 @@ bool cDvbApi::StartReplay(const char *FileName, const char *Title)
case dvbSkip: {
int Seconds;
if (readint(fromMain, Seconds)) {
SetReplayMode(VID_PLAY_CLEAR_BUFFER);
SetReplayMode(VID_PLAY_NORMAL);
FastForward = FastRewind = Paused = false;
Buffer->SetMode(rmPlay);

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.10 2000/05/20 14:50:43 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:
@ -72,7 +91,7 @@ public:
// Progress Display facilities
private:
int lastProgress;
int lastProgress, lastTotal;
char *replayTitle;
public:
bool ShowProgress(bool Initial = false);
@ -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.9 2000/05/07 09:28:39 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);
}
}
@ -323,7 +321,7 @@ void cInterface::DisplayChannel(int Number, const char *Name)
#ifndef DEBUG_REMOTE
RcIo.Number(Number);
#endif
if (Name) {
if (Name && !Recording()) {
Open(MenuColumns, 1);
char buffer[MenuColumns + 1];
snprintf(buffer, sizeof(buffer), "%d %s", Number, Name ? Name : "");
@ -337,3 +335,16 @@ void cInterface::DisplayChannel(int Number, const char *Name)
Close();
}
}
void cInterface::DisplayRecording(int Index, bool On)
{
#ifndef DEBUG_REMOTE
RcIo.SetPoints(1 << Index, On);
#endif
}
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.9 2000/05/06 15:39:23 kls Exp $
*/
#ifndef __INTERFACE_H
@ -43,9 +43,10 @@ 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);
void DisplayRecording(int Index, bool On);
bool Recording(void);
};
extern cInterface Interface;
extern cDvbApi DvbApi; //XXX member of cInterface???
#endif //__INTERFACE_H

Binary file not shown.

238
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.8 2000/04/24 15:32:11 kls Exp $
* $Id: menu.c 1.16 2000/05/27 16:13:39 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 ---------------------------------------------------------
@ -509,7 +510,7 @@ cMenuEditChannel::cMenuEditChannel(int Index)
Add(new cMenuEditIntItem( "Srate", &data.srate, 22000, 27500)); //TODO exact limits - toggle???
Add(new cMenuEditIntItem( "Vpid", &data.vpid, 0, 10000)); //TODO exact limits???
Add(new cMenuEditIntItem( "Apid", &data.apid, 0, 10000)); //TODO exact limits???
Add(new cMenuEditBoolItem("CA", &data.ca));
Add(new cMenuEditIntItem( "CA", &data.ca, 0, cDvbApi::NumDvbApis));
Add(new cMenuEditIntItem( "Pnr", &data.pnr, 0, 10000)); //TODO exact limits???
}
}
@ -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();
@ -947,9 +948,8 @@ eOSState cMenuRecordings::Play(void)
{
cMenuRecordingItem *ri = (cMenuRecordingItem *)Get(Current());
if (ri) {
//XXX what if this recording's file is currently in use???
if (DvbApi.StartReplay(ri->recording->FileName(), ri->recording->Title()))
return osEnd;
cReplayControl::SetRecording(ri->recording->FileName(), ri->recording->Title());
return osReplay;
}
return osContinue;
}
@ -992,12 +992,26 @@ eOSState cMenuRecordings::ProcessKey(eKeys Key)
// --- cMenuMain -------------------------------------------------------------
cMenuMain::cMenuMain(void)
#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 (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;
}
SetHelp("Record");
Display();
lastActivity = time(NULL);
}
eOSState cMenuMain::ProcessKey(eKeys Key)
@ -1008,41 +1022,205 @@ eOSState cMenuMain::ProcessKey(eKeys Key)
case osChannels: return AddSubMenu(new cMenuChannels);
case osTimer: return AddSubMenu(new cMenuTimers);
case osRecordings: return AddSubMenu(new cMenuRecordings);
default: break;
case osStopRecord: if (Interface.Confirm("Stop Recording?")) {
cOsdItem *item = Get(Current());
if (item) {
cRecordControls::Stop(item->Text() + strlen(STOP_RECORDING));
return osEnd;
}
}
default: switch (Key) {
case kMenu: state = osEnd; break;
case kRed: if (!HasSubMenu())
state = osRecord;
break;
default: break;
}
}
if (Key != kNone)
lastActivity = time(NULL);
else if (time(NULL) - lastActivity > MENUTIMEOUT)
state = osEnd;
return state;
}
// --- cReplayDisplay --------------------------------------------------------
// --- cRecordControl --------------------------------------------------------
cReplayDisplay::cReplayDisplay(void)
cRecordControl::cRecordControl(cDvbApi *DvbApi, cTimer *Timer)
{
Interface.Open(MenuColumns, -3);
shown = DvbApi.ShowProgress(true);
instantId = NULL;
dvbApi = DvbApi;
if (!dvbApi) dvbApi = cDvbApi::PrimaryDvbApi;//XXX
timer = 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, dvbApi);
cRecording Recording(timer);
dvbApi->StartRecord(Recording.FileName());
Interface.DisplayRecording(dvbApi->Index(), true);
}
cReplayDisplay::~cReplayDisplay()
cRecordControl::~cRecordControl()
{
Interface.Close();
Stop(true);
delete instantId;
Interface.DisplayRecording(dvbApi->Index(), false);
}
eKeys cReplayDisplay::ProcessKey(eKeys Key)
void cRecordControl::Stop(bool KeepInstant)
{
if (!DvbApi.Replaying())
return kOk; // will turn off replay display
shown = DvbApi.ShowProgress(!shown);
if (timer) {
dvbApi->StopRecord();
timer->SetRecording(false);
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);
Timers.Del(timer);
Timers.Save();
}
timer = NULL;
}
}
bool cRecordControl::Process(void)
{
if (!timer || !timer->Matches())
return false;
AssertFreeDiskSpace();
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 --------------------------------------------------------
char *cReplayControl::fileName = NULL;
char *cReplayControl::title = NULL;
cReplayControl::cReplayControl(void)
{
dvbApi = cDvbApi::PrimaryDvbApi;//XXX
visible = shown = false;
if (fileName)
dvbApi->StartReplay(fileName, title);
}
cReplayControl::~cReplayControl()
{
Hide();
dvbApi->StopReplay();
}
void cReplayControl::SetRecording(const char *FileName, const char *Title)
{
delete fileName;
delete title;
fileName = FileName ? strdup(FileName) : NULL;
title = Title ? strdup(Title) : NULL;
}
void cReplayControl::Show(void)
{
if (!visible) {
Interface.Open(MenuColumns, -3);
needsFastResponse = visible = true;
shown = dvbApi->ShowProgress(true);
}
}
void cReplayControl::Hide(void)
{
if (visible) {
Interface.Close();
needsFastResponse = visible = false;
}
}
eOSState cReplayControl::ProcessKey(eKeys Key)
{
if (!dvbApi->Replaying())
return osEnd;
if (visible)
shown = dvbApi->ShowProgress(!shown) || shown;
switch (Key) {
case kBegin:
case kPause:
case kStop:
case kSearchBack:
case kSearchForward:
case kSkipBack:
case kSkipForward: break; // will be done in main loop
case kMenu: break; // allow direct switching to menu
case kOk: break; // switches off replay display
default: Key = kNone; // ignore anything not explicitly known here
case kUp: dvbApi->Skip(-INT_MAX); break;
case kDown: dvbApi->PauseReplay(); break;
case kBlue: Hide();
dvbApi->StopReplay();
return osEnd;
case kLeft: dvbApi->FastRewind(); break;
case kRight: dvbApi->FastForward(); break;
case kGreen: dvbApi->Skip(-60); break;
case kYellow: dvbApi->Skip(60); break;
case kMenu: Hide(); return osMenu; // allow direct switching to menu
case kOk: visible ? Hide() : Show(); break;
default: return osUnknown;
}
return Key;
return osContinue;
}

50
menu.h
View File

@ -4,27 +4,63 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: menu.h 1.5 2000/04/24 15:31:53 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(void);
cMenuMain(bool Replaying);
virtual eOSState ProcessKey(eKeys Key);
};
class cReplayDisplay {
class cRecordControl {
private:
bool shown;
cDvbApi *dvbApi;
cTimer *timer;
char *instantId;
public:
cReplayDisplay(void);
~cReplayDisplay();
eKeys ProcessKey(eKeys Key);
cRecordControl(cDvbApi *DvbApi, cTimer *Timer = NULL);
virtual ~cRecordControl();
bool Process(void);
void Stop(bool KeepInstant = false);
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);
static char *fileName;
static char *title;
public:
cReplayControl(void);
virtual ~cReplayControl();
virtual eOSState ProcessKey(eKeys Key);
bool Visible(void) { return visible; }
static void SetRecording(const char *FileName, const char *Title);
};
#endif //_MENU_H

20
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.4 2000/04/24 09:44:32 kls Exp $
* $Id: osd.h 1.9 2000/05/27 15:35:41 kls Exp $
*/
#ifndef __OSD_H
@ -17,11 +17,15 @@
#define MAXOSDITEMS 9
enum eOSState { osUnknown,
osMenu,
osContinue,
osProcessed,
osChannels,
osTimer,
osRecordings,
osRecord,
osReplay,
osStopRecord,
osStopReplay,
osBack,
osEnd,
};
@ -44,7 +48,17 @@ public:
virtual eOSState ProcessKey(eKeys Key);
};
class cOsdMenu : public cList<cOsdItem> {
class cOsdBase {
protected:
bool needsFastResponse;
public:
cOsdBase(bool FastResponse = false) { needsFastResponse = FastResponse; }
virtual ~cOsdBase() {}
virtual eOSState ProcessKey(eKeys Key) = 0;
bool NeedsFastResponse(void) { return needsFastResponse; }
};
class cOsdMenu : public cOsdBase, public cList<cOsdItem> {
private:
char *title;
int cols[cInterface::MaxCols];

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: recording.c 1.6 2000/04/24 09:45:13 kls Exp $
* $Id: recording.c 1.8 2000/05/13 16:16:56 kls Exp $
*/
#define _GNU_SOURCE
@ -61,8 +61,7 @@ void AssertFreeDiskSpace(void)
// it will get removed during the next call.
static time_t LastFreeDiskCheck = 0;
if (time(NULL) - LastFreeDiskCheck > DISKCHECKDELTA) {
LastFreeDiskCheck = time(NULL);
if (DvbApi.Recording() && LowDiskSpace()) {
if (LowDiskSpace()) {
// Remove the oldest file that has been "deleted":
cRecordings Recordings;
if (Recordings.Load(true)) {
@ -97,6 +96,7 @@ void AssertFreeDiskSpace(void)
// Unable to free disk space, but there's nothing we can do about that...
esyslog(LOG_ERR, "low disk space, but no recordings to delete");
}
LastFreeDiskCheck = time(NULL);
}
}

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: remote.c 1.6 2000/04/24 09:45:56 kls Exp $
* $Id: remote.c 1.7 2000/05/07 09:28:18 kls Exp $
*/
#include "remote.h"
@ -29,6 +29,7 @@ cRcIo::cRcIo(char *DeviceName)
t = 0;
firstTime = lastTime = 0;
lastCommand = 0;
lastNumber = 0;
if ((f = open(DeviceName, O_RDWR | O_NONBLOCK)) >= 0) {
struct termios t;
if (tcgetattr(f, &t) == 0) {
@ -206,6 +207,7 @@ bool cRcIo::Number(int n, bool Hex)
n = (n << 4) | ((*d - '0') & 0x0F);
}
}
lastNumber = n;
for (int i = 0; i < 4; i++) {
if (!Digit(i, n))
return false;
@ -231,6 +233,15 @@ bool cRcIo::String(char *s)
return Number(n, true);
}
void cRcIo::SetPoints(unsigned char Dp, bool On)
{
if (On)
dp |= Dp;
else
dp &= ~Dp;
Number(lastNumber, true);
}
bool cRcIo::DetectCode(unsigned char *Code, unsigned short *Address)
{
// Caller should initialize 'Code' to 0 and call DetectCode()

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: remote.h 1.4 2000/04/24 09:46:00 kls Exp $
* $Id: remote.h 1.5 2000/05/07 09:27:54 kls Exp $
*/
#ifndef __REMOTE_H
@ -21,10 +21,12 @@ private:
time_t t;
int firstTime, lastTime;
unsigned int lastCommand;
int lastNumber;
bool SendCommand(unsigned char Cmd);
int ReceiveByte(bool Wait = true);
bool SendByteHandshake(unsigned char c);
bool SendByte(unsigned char c);
bool Digit(int n, int v);
public:
enum { modeH = 'h', modeB = 'b', modeS = 's' };
cRcIo(char *DeviceName);
@ -34,9 +36,8 @@ public:
bool SetCode(unsigned char Code, unsigned short Address);
bool SetMode(unsigned char Mode);
bool GetCommand(unsigned int *Command, unsigned short *Address = NULL);
bool Digit(int n, int v);
bool Number(int n, bool Hex = false);
void Points(unsigned char Dp) { dp = Dp; }
void SetPoints(unsigned char Dp, bool On);
bool String(char *s);
bool DetectCode(unsigned char *Code, unsigned short *Address);
};

View File

@ -1,9 +1,10 @@
0:15:MTWTF--:1828:1901:10:5:nano
0:3:M------:2110:2230:99:10:SevenDays
1:10:-T-----:2058:2150:99:10:Quarks
1:15:MTWTF--:1828:1901:10:5:nano
1:3:M------:2110:2230:99:10:SevenDays
1:10:-T-----:2058:2202:99:10:Quarks
1:3:---T---:2158:2300:99:10:Switch
1:2:----F--:2110:2155:99:10:Anke
1:1:----F--:2210:2325:99:10:7Tage7Koepfe
1:15:-----S-:1358:1435:99:7:Neues
1:1:-----S-:1445:1600:99:10:Hammerman
1:2:-----S-:2205:2320:99:10:Wochenshow
1:2:-----S-:2150:2320:99:10:Wochenshow
1:14:------S:2155:2245:99:10:AprilHailer
1:2:--W----:2110:2325:99:99:BulleVonToelz

135
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.12 2000/04/24 13:36:39 kls Exp $
* $Id: vdr.c 1.19 2000/05/27 15:38:35 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,15 +69,14 @@ int main(int argc, char *argv[])
if (signal(SIGTERM, SignalHandler) == SIG_IGN) signal(SIGTERM, SIG_IGN);
cMenuMain *Menu = NULL;
cReplayDisplay *ReplayDisplay = NULL;
cTimer *Timer = NULL;
cReplayControl *ReplayControl = NULL;
int dcTime = 0, dcNumber = 0;
int LastChannel = -1;
while (!Interrupted) {
// Channel display:
if (CurrentChannel != LastChannel) {
if (!Menu && !ReplayDisplay) {
if (!Menu) {
cChannel *channel = Channels.Get(CurrentChannel);
if (channel)
Interface.DisplayChannel(CurrentChannel + 1, channel->name);
@ -81,108 +84,80 @@ int main(int argc, char *argv[])
LastChannel = CurrentChannel;
}
// Direct Channel Select (action):
if (dcNumber) {
Interface.DisplayChannel(dcNumber);
if (time_ms() - dcTime > DIRECTCHANNELTIMEOUT) {
cChannel::SwitchTo(dcNumber - 1);
dcNumber = 0;
LastChannel = -1; // in case an invalid channel number was entered!
}
if (dcNumber && time_ms() - dcTime > DIRECTCHANNELTIMEOUT) {
cChannel::SwitchTo(dcNumber - 1);
dcNumber = 0;
LastChannel = -1; // in case an invalid channel number was entered!
}
// Timer Processing:
else {
AssertFreeDiskSpace();
if (!Timer && (Timer = cTimer::GetMatch()) != NULL) {
DELETENULL(Menu);
DELETENULL(ReplayDisplay);
// make sure the timer won't be deleted:
Timer->SetRecording(true);
// switch to channel:
cChannel::SwitchTo(Timer->channel - 1);
// start recording:
cRecording Recording(Timer);
DvbApi.StartRecord(Recording.FileName());
}
if (Timer && !Timer->Matches()) {
// stop recording:
DvbApi.StopRecord();
// release timer:
Timer->SetRecording(false);
// clear single event timer:
if (Timer->IsSingleEvent()) {
DELETENULL(Menu); // must make sure no menu uses it
isyslog(LOG_INFO, "deleting timer %d", Timer->Index() + 1);
Timers.Del(Timer);
Timers.Save();
// Timers and Recordings:
if (!Menu) {
cTimer *Timer = cTimer::GetMatch();
if (Timer) {
if (!cRecordControls::Start(Timer)) {
//TODO need to do something to prevent the timer from hitting over and over again...
}
Timer = NULL;
}
cRecordControls::Process();
}
// User Input:
eKeys key = Interface.GetKey(!ReplayDisplay);
if (Menu) {
switch (Menu->ProcessKey(key)) {
default: if (key != kMenu)
break;
cOsdBase **Interact = Menu ? (cOsdBase **)&Menu : (cOsdBase **)&ReplayControl;
eKeys key = Interface.GetKey(!*Interact || !(*Interact)->NeedsFastResponse());
if (*Interact) {
switch ((*Interact)->ProcessKey(key)) {
case osMenu: DELETENULL(Menu);
Menu = new cMenuMain(ReplayControl);
break;
case osRecord: DELETENULL(Menu);
if (!cRecordControls::Start())
Interface.Error("No free DVB device to record!");
break;
case osReplay: DELETENULL(Menu);
DELETENULL(ReplayControl);
ReplayControl = new cReplayControl;
break;
case osStopReplay:
DELETENULL(*Interact);
DELETENULL(ReplayControl);
break;
case osBack:
case osEnd: DELETENULL(Menu);
break;
case osEnd: DELETENULL(*Interact);
break;
default: ;
}
}
else if (!ReplayDisplay || (key = ReplayDisplay->ProcessKey(key)) != kNone) {
else {
switch (key) {
// 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 (!(DvbApi.Recording() || DvbApi.Replaying())) {
dcNumber = dcNumber * 10 + key - k0;
dcTime = time_ms();
{
if (!Interface.Recording()) {
dcNumber = dcNumber * 10 + key - k0;
dcTime = time_ms();
Interface.DisplayChannel(dcNumber);
}
}
}
// Record/Replay Control:
case kBegin: DvbApi.Skip(-INT_MAX); break;
case kRecord: if (!(DvbApi.Recording() || DvbApi.Replaying())) {
cTimer *timer = new cTimer(true);
Timers.Add(timer);
Timers.Save();
}
break;
case kPause: DvbApi.PauseReplay(); break;
case kStop: DELETENULL(ReplayDisplay);
DvbApi.StopReplay();
break;
case kSearchBack: DvbApi.FastRewind(); break;
case kSearchForward: DvbApi.FastForward(); break;
case kSkipBack: DvbApi.Skip(-60); break;
case kSkipForward: DvbApi.Skip(60); break;
// Menu Control:
case kMenu: DELETENULL(ReplayDisplay);
Menu = new cMenuMain;
Menu->Display();
break;
break;
// Up/Down Channel Select:
case kUp:
case kDown: if (!(DvbApi.Recording() || DvbApi.Replaying())) {
case kDown: if (!Interface.Recording()) {
int n = CurrentChannel + (key == kUp ? 1 : -1);
cChannel *channel = Channels.Get(n);
if (channel)
channel->Switch();
}
break;
// Menu Control:
case kMenu: Menu = new cMenuMain(ReplayControl); break;
// Viewing Control:
case kOk: if (ReplayDisplay)
DELETENULL(ReplayDisplay);
else if (DvbApi.Replaying())
ReplayDisplay = new cReplayDisplay;
else
LastChannel = -1; break; // forces channel display
case kOk: LastChannel = -1; break; // forces channel display
default: break;
}
}
}
isyslog(LOG_INFO, "caught signal %d", Interrupted);
DvbApi.StopRecord();
DvbApi.StopReplay();
delete Menu;
delete ReplayControl;
cDvbApi::Cleanup();
isyslog(LOG_INFO, "exiting");
closelog();
return 0;