diff options
Diffstat (limited to 'dvbapi.c')
-rw-r--r-- | dvbapi.c | 171 |
1 files changed, 127 insertions, 44 deletions
@@ -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; +} + |