summaryrefslogtreecommitdiff
path: root/dvbapi.c
diff options
context:
space:
mode:
authorKlaus Schmidinger <kls (at) cadsoft (dot) de>2000-04-24 18:00:00 +0200
committerKlaus Schmidinger <kls (at) cadsoft (dot) de>2000-04-24 18:00:00 +0200
commit85b8e41e8bb16e4e66561768026456ec5f0ee276 (patch)
treedd52f93f8db69b395ed2170d641a3e9d574ed039 /dvbapi.c
parent37250a0568d5b1d689d5c59f983e9be228ed49c2 (diff)
downloadvdr-patch-lnbsharing-85b8e41e8bb16e4e66561768026456ec5f0ee276.tar.gz
vdr-patch-lnbsharing-85b8e41e8bb16e4e66561768026456ec5f0ee276.tar.bz2
Version 0.04vdr-0.04
- Changed name from 'osm' to 'vdr' to avoid mixups with the 'oms' program that appears to be in use with DVD replay. - Implemented a channel display in the top menu line. - Implemented replay progress display (press "Ok" when replaying to bring it up). - Implemented direct channel selecting by pressing the numeric keys. - Added several 'const' keywords to please stricter compilers. - The repeat function for the remote control no longer adapts dynamically to the timing of the RCU (this sometimes caused the repeat function to kick in too early). - Channel selection is now blocked when recording or replaying. - Improved process handling.
Diffstat (limited to 'dvbapi.c')
-rw-r--r--dvbapi.c171
1 files changed, 127 insertions, 44 deletions
diff --git a/dvbapi.c b/dvbapi.c
index ef2f808..719437d 100644
--- a/dvbapi.c
+++ b/dvbapi.c
@@ -1,21 +1,19 @@
/*
* dvbapi.c: Interface to the DVB driver
*
- * See the main source file 'osm.c' for copyright information and
+ * See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: dvbapi.c 1.3 2000/04/15 14:45:04 kls Exp $
+ * $Id: dvbapi.c 1.8 2000/04/24 15:30:35 kls Exp $
*/
#include "dvbapi.h"
#include <errno.h>
#include <fcntl.h>
-#include <signal.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/time.h>
-#include <sys/wait.h>
#include <unistd.h>
#include "interface.h"
#include "tools.h"
@@ -59,7 +57,6 @@
#define RESUMEFILESUFFIX "/resume.vdr"
#define RECORDFILESUFFIX "/%03d.vdr"
#define RECORDFILESUFFIXLEN 20 // some additional bytes for safety...
-#define MAXPROCESSTIMEOUT 3 // seconds
// The number of frames to back up when resuming an interrupted replay session:
#define RESUMEBACKUP (10 * FRAMESPERSEC)
@@ -85,7 +82,7 @@ public:
int Last(void) { return last; }
int GetResume(void) { return resume; }
bool StoreResume(int Index);
- static char *Str(int Index);
+ static char *Str(int Index, bool WithFrame = false);
};
cIndexFile::cIndexFile(const char *FileName, bool Record)
@@ -256,7 +253,7 @@ bool cIndexFile::StoreResume(int Index)
return false;
}
-char *cIndexFile::Str(int Index)
+char *cIndexFile::Str(int Index, bool WithFrame)
{
static char buffer[16];
int f = (Index % FRAMESPERSEC) + 1;
@@ -264,7 +261,7 @@ char *cIndexFile::Str(int Index)
int m = s / 60 % 60;
int h = s / 3600;
s %= 60;
- snprintf(buffer, sizeof(buffer), "%d:%02d:%02d.%02d", h, m, s, f);
+ snprintf(buffer, sizeof(buffer), WithFrame ? "%d:%02d:%02d.%02d" : "%d:%02d:%02d", h, m, s, f);
return buffer;
}
@@ -554,7 +551,7 @@ private:
public:
cRecordBuffer(int *InFile, const char *FileName);
virtual ~cRecordBuffer();
- int WriteWithTimeout(void);
+ int WriteWithTimeout(bool EndIfEmpty = false);
};
cRecordBuffer::cRecordBuffer(int *InFile, const char *FileName)
@@ -720,13 +717,13 @@ int cRecordBuffer::Write(int Max)
return 0;
}
-int cRecordBuffer::WriteWithTimeout(void)
+int cRecordBuffer::WriteWithTimeout(bool EndIfEmpty)
{
int w, written = 0;
int t0 = time_ms();
while ((w = Write()) > 0 && time_ms() - t0 < MAXRECORDWRITETIME)
written += w;
- return w < 0 ? w : written;
+ return w < 0 ? w : (written == 0 && EndIfEmpty ? -1 : written);
}
// --- cReplayBuffer ---------------------------------------------------------
@@ -752,6 +749,7 @@ public:
int Resume(void);
bool Save(void);
void SkipSeconds(int Seconds);
+ void GetIndex(int &Current, int &Total);
};
cReplayBuffer::cReplayBuffer(int *OutFile, const char *FileName)
@@ -840,7 +838,7 @@ void cReplayBuffer::SkipSeconds(int Seconds)
}
Index += Seconds * FRAMESPERSEC;
if (Index < 0)
- Index = 1;
+ Index = 1; // not '0', to allow GetNextIFrame() below to work!
uchar FileNumber;
int FileOffset;
if (index->GetNextIFrame(Index, false, &FileNumber, &FileOffset) >= 0)
@@ -849,6 +847,16 @@ void cReplayBuffer::SkipSeconds(int Seconds)
}
}
+void cReplayBuffer::GetIndex(int &Current, int &Total)
+{
+ if (index) {
+ Current = index->Get(fileNumber, fileOffset);
+ Total = index->Last();
+ }
+ else
+ Current = Total = -1;
+}
+
void cReplayBuffer::SkipAudioBlocks(void)
{
int Length;
@@ -1001,8 +1009,10 @@ cDvbApi::cDvbApi(void)
memset(&colorPairs, 0, sizeof(colorPairs));
start_color();
leaveok(stdscr, TRUE);
- window = stdscr;
+ window = NULL;
#endif
+ lastProgress = -1;
+ replayTitle = NULL;
}
cDvbApi::~cDvbApi()
@@ -1018,6 +1028,7 @@ cDvbApi::~cDvbApi()
endwin();
#endif
}
+ delete replayTitle;
}
#ifdef DEBUG_OSD
@@ -1056,17 +1067,21 @@ void cDvbApi::Cmd(OSD_Command cmd, int color, int x0, int y0, int x1, int y1, co
void cDvbApi::Open(int w, int h)
{
+ int d = (h < 0) ? MenuLines + h : 0;
+ h = abs(h);
cols = w;
rows = h;
#ifdef DEBUG_OSD
- //XXX size...
+ window = subwin(stdscr, h, w, d, 0);
+ syncok(window, TRUE);
#define B2C(b) (((b) * 1000) / 255)
#define SETCOLOR(n, r, g, b, o) init_color(n, B2C(r), B2C(g), B2C(b))
#else
w *= charWidth;
h *= lineHeight;
- int x = (720 - w) / 2; //TODO PAL vs. NTSC???
- int y = (576 - h) / 2;
+ d *= lineHeight;
+ int x = (720 - MenuColumns * charWidth) / 2; //TODO PAL vs. NTSC???
+ int y = (576 - MenuLines * lineHeight) / 2 + d;
Cmd(OSD_Open, 4, x, y, x + w - 1, y + h - 1);
#define SETCOLOR(n, r, g, b, o) Cmd(OSD_SetColor, n, r, g, b, o)
#endif
@@ -1079,6 +1094,8 @@ void cDvbApi::Open(int w, int h)
SETCOLOR(clrCyan, 0x00, 0xFC, 0xFC, 255);
SETCOLOR(clrMagenta, 0xB0, 0x00, 0xFC, 255);
SETCOLOR(clrWhite, 0xFC, 0xFC, 0xFC, 255);
+
+ lastProgress = -1;
}
void cDvbApi::Close(void)
@@ -1086,6 +1103,7 @@ void cDvbApi::Close(void)
#ifndef DEBUG_OSD
Cmd(OSD_Close);
#endif
+ lastProgress = -1;
}
void cDvbApi::Clear(void)
@@ -1108,6 +1126,7 @@ void cDvbApi::Fill(int x, int y, int w, int h, eDvbColor color)
wmove(window, y + r, x); // ncurses wants 'y' before 'x'!
whline(window, ' ', w);
}
+ wsyncup(window); // shouldn't be necessary because of 'syncok()', but w/o it doesn't work
#else
Cmd(OSD_FillBlock, color, x * charWidth, y * lineHeight, (x + w) * charWidth - 1, (y + h) * lineHeight - 1);
#endif
@@ -1131,6 +1150,52 @@ void cDvbApi::Text(int x, int y, const char *s, eDvbColor colorFg, eDvbColor col
#endif
}
+bool cDvbApi::ShowProgress(bool Initial)
+{
+ int Current, Total;
+
+ if (GetIndex(&Current, &Total)) {
+ if (Initial) {
+ if (replayTitle)
+ Text(0, 0, replayTitle);
+ Text(-7, 2, cIndexFile::Str(Total));
+ }
+#ifdef DEBUG_OSD
+ int p = cols * Current / Total;
+ Fill(0, 1, p, 1, clrGreen);
+ Fill(p, 1, cols - p, 1, clrWhite);
+#else
+ int w = cols * charWidth;
+ int p = w * Current / Total;
+ if (p != lastProgress) {
+ int y1 = 1 * lineHeight;
+ int y2 = 2 * lineHeight - 1;
+ int x1, x2;
+ eDvbColor color;
+ if (lastProgress < p) {
+ x1 = lastProgress + 1;
+ x2 = p;
+ if (p >= w)
+ p = w - 1;
+ color = clrGreen;
+ }
+ else {
+ x1 = p + 1;
+ x2 = lastProgress;
+ color = clrWhite;
+ }
+ if (lastProgress < 0)
+ Cmd(OSD_FillBlock, clrWhite, 0, y1, w - 1, y2);
+ Cmd(OSD_FillBlock, color, x1, y1, x2, y2);
+ lastProgress = p;
+ }
+#endif
+ Text(0, 2, cIndexFile::Str(Current));
+ return true;
+ }
+ return false;
+}
+
bool cDvbApi::SetChannel(int FrequencyMHz, char Polarization, int Diseqc, int Srate, int Vpid, int Apid, int Ca, int Pnr)
{
if (videoDev >= 0) {
@@ -1160,35 +1225,17 @@ bool cDvbApi::SetChannel(int FrequencyMHz, char Polarization, int Diseqc, int Sr
return false;
}
-void cDvbApi::KillProcess(pid_t pid)
-{
- pid_t Pid2Wait4 = pid;
- for (time_t t0 = time(NULL); time(NULL) - t0 < MAXPROCESSTIMEOUT; ) {
- int status;
- pid_t pid = waitpid(Pid2Wait4, &status, WNOHANG);
- if (pid < 0) {
- if (errno != ECHILD)
- LOG_ERROR;
- return;
- }
- if (pid == Pid2Wait4)
- return;
- }
- esyslog(LOG_ERR, "ERROR: process %d won't end (waited %d seconds) - terminating it...", Pid2Wait4, MAXPROCESSTIMEOUT);
- if (kill(Pid2Wait4, SIGTERM) < 0) {
- esyslog(LOG_ERR, "ERROR: process %d won't terminate (%s) - killing it...", Pid2Wait4, strerror(errno));
- if (kill(Pid2Wait4, SIGKILL) < 0)
- esyslog(LOG_ERR, "ERROR: process %d won't die (%s) - giving up", Pid2Wait4, strerror(errno));
- }
-}
-
bool cDvbApi::Recording(void)
{
+ if (pidRecord && !CheckProcess(pidRecord))
+ pidRecord = 0;
return pidRecord;
}
bool cDvbApi::Replaying(void)
{
+ if (pidReplay && !CheckProcess(pidReplay))
+ pidReplay = 0;
return pidReplay;
}
@@ -1239,6 +1286,7 @@ bool cDvbApi::StartRecord(const char *FileName)
dsyslog(LOG_INFO, "start recording process (pid=%d)", getpid());
isMainProcess = false;
+ bool DataStreamBroken = false;
int fromMain = toRecordPipe[0];
int toMain = fromRecordPipe[1];
cRecordBuffer *Buffer = new cRecordBuffer(&videoDev, FileName);
@@ -1251,21 +1299,26 @@ bool cDvbApi::StartRecord(const char *FileName)
struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
+ bool ForceEnd = false;
if (select(FD_SETSIZE, &set, NULL, NULL, &timeout) > 0) {
if (FD_ISSET(videoDev, &set)) {
if (Buffer->Read() < 0)
break;
+ DataStreamBroken = false;
}
if (FD_ISSET(fromMain, &set)) {
switch (readchar(fromMain)) {
- case dvbStop: Buffer->Stop(); break;
- break;
+ case dvbStop: Buffer->Stop();
+ ForceEnd = DataStreamBroken;
+ break;
}
}
}
- else
+ else {
+ DataStreamBroken = true;
esyslog(LOG_ERR, "ERROR: video data stream broken");
- if (Buffer->WriteWithTimeout() < 0)
+ }
+ if (Buffer->WriteWithTimeout(ForceEnd) < 0)
break;
}
delete Buffer;
@@ -1309,7 +1362,7 @@ void cDvbApi::SetReplayMode(int Mode)
}
}
-bool cDvbApi::StartReplay(const char *FileName)
+bool cDvbApi::StartReplay(const char *FileName, const char *Title)
{
if (Recording()) {
esyslog(LOG_ERR, "ERROR: StartReplay() called while recording - ignored!");
@@ -1318,6 +1371,13 @@ bool cDvbApi::StartReplay(const char *FileName)
StopReplay();
if (videoDev >= 0) {
+ lastProgress = -1;
+ delete replayTitle;
+ if (Title) {
+ if ((replayTitle = strdup(Title)) == NULL)
+ esyslog(LOG_ERR, "ERROR: StartReplay: can't copy title '%s'", Title);
+ }
+
// Check FileName:
if (!FileName) {
@@ -1361,7 +1421,7 @@ bool cDvbApi::StartReplay(const char *FileName)
bool FastRewind = false;
int ResumeIndex = Buffer->Resume();
if (ResumeIndex >= 0)
- isyslog(LOG_INFO, "resuming replay at index %d (%s)", ResumeIndex, cIndexFile::Str(ResumeIndex));
+ isyslog(LOG_INFO, "resuming replay at index %d (%s)", ResumeIndex, cIndexFile::Str(ResumeIndex, true));
for (;;) {
if (Buffer->Read() < 0)
break;
@@ -1405,6 +1465,12 @@ bool cDvbApi::StartReplay(const char *FileName)
Buffer->SkipSeconds(Seconds);
}
}
+ case dvbGetIndex: {
+ int Current, Total;
+ Buffer->GetIndex(Current, Total);
+ writeint(toMain, Current);
+ writeint(toMain, Total);
+ }
break;
}
}
@@ -1470,3 +1536,20 @@ void cDvbApi::Skip(int Seconds)
}
}
+bool cDvbApi::GetIndex(int *Current, int *Total)
+{
+ if (pidReplay) {
+ int total;
+ purge(fromReplay);
+ writechar(toReplay, dvbGetIndex);
+ if (readint(fromReplay, *Current) && readint(fromReplay, total)) {
+ if (Total)
+ *Total = total;
+ }
+ else
+ *Current = -1;
+ return *Current >= 0;
+ }
+ return false;
+}
+