diff options
author | Klaus Schmidinger <kls (at) cadsoft (dot) de> | 2000-05-27 18:00:00 +0200 |
---|---|---|
committer | Klaus Schmidinger <kls (at) cadsoft (dot) de> | 2000-05-27 18:00:00 +0200 |
commit | 9599a8fd8a6724e55ec4ad2ba2c975c0850073d9 (patch) | |
tree | a1bbeee86ba1066f1e15d8311714b895f4c7b9a2 /menu.c | |
parent | 85b8e41e8bb16e4e66561768026456ec5f0ee276 (diff) | |
download | vdr-patch-lnbsharing-9599a8fd8a6724e55ec4ad2ba2c975c0850073d9.tar.gz vdr-patch-lnbsharing-9599a8fd8a6724e55ec4ad2ba2c975c0850073d9.tar.bz2 |
Version 0.05vdr-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.
Diffstat (limited to 'menu.c')
-rw-r--r-- | menu.c | 238 |
1 files changed, 208 insertions, 30 deletions
@@ -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 -------------------------------------------------------- + +cRecordControl::cRecordControl(cDvbApi *DvbApi, cTimer *Timer) +{ + 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); +} + +cRecordControl::~cRecordControl() +{ + Stop(true); + delete instantId; + Interface.DisplayRecording(dvbApi->Index(), false); +} + +void cRecordControl::Stop(bool KeepInstant) +{ + 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(); + } + } +} -cReplayDisplay::cReplayDisplay(void) +const char *cRecordControls::GetInstantId(const char *LastInstantId) { - Interface.Open(MenuColumns, -3); - shown = DvbApi.ShowProgress(true); + 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; } -cReplayDisplay::~cReplayDisplay() +void cRecordControls::Process(void) { - Interface.Close(); + for (int i = 0; i < MAXDVBAPI; i++) { + if (RecordControls[i]) { + if (!RecordControls[i]->Process()) + DELETENULL(RecordControls[i]); + } + } } -eKeys cReplayDisplay::ProcessKey(eKeys Key) +// --- cReplayControl -------------------------------------------------------- + +char *cReplayControl::fileName = NULL; +char *cReplayControl::title = NULL; + +cReplayControl::cReplayControl(void) { - if (!DvbApi.Replaying()) - return kOk; // will turn off replay display - shown = DvbApi.ShowProgress(!shown); + 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; } |