diff --git a/HISTORY b/HISTORY index 1ffc34c0..7d81ca11 100644 --- a/HISTORY +++ b/HISTORY @@ -221,3 +221,13 @@ Video Disk Recorder Revision History that would display only partially). - In normal viewing mode the '0' key now toggles between the current and the previous channel. + +2000-10-08: Version 0.66 + +- Remote control data is now received in a separate thread, which makes things + a lot smoother. +- Repeat and release of remote control keys is now explicitly distinguished. +- In replay mode the search forward/back and skip functions now have two modes: + Pressing the key shortly and releasing it starts the function, and pressing it + again stops it. Pressing and holding down the key starts the function and + releasing the key stops it. diff --git a/MANUAL b/MANUAL index 24ee3ff5..f8b2a1b8 100644 --- a/MANUAL +++ b/MANUAL @@ -118,8 +118,12 @@ Video Disk Recorder User's Manual Right Runs playback forward or backward at a higher speed; press again to resume normal speed. If in Pause mode, runs forward or backward at a slower speed; press again to return to pause mode. + Pressing and holding down the button performs the function until + the button is released again. - Green Yellow Skips about 60 seconds back or forward. + Pressing and holding down the button performs the function until + the button is released again. - 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. diff --git a/config.h b/config.h index 99a57eba..73fc8f5a 100644 --- a/config.h +++ b/config.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: config.h 1.23 2000/10/07 17:34:23 kls Exp $ + * $Id: config.h 1.24 2000/10/08 10:38:17 kls Exp $ */ #ifndef __CONFIG_H @@ -34,9 +34,16 @@ enum eKeys { // "Up" and "Down" must be the first two keys! kYellow, kBlue, k0, k1, k2, k3, k4, k5, k6, k7, k8, k9, - kNone + kNone, + // The following flags are OR'd with the above codes: + k_Repeat = 0x8000, + k_Release = 0x4000, + k_Flags = k_Repeat | k_Release, }; +#define ISNORMALKEY(k) ((k) != kNone && ((k) & k_Flags) == 0) +#define NORMALKEY(k) ((k) & ~k_Flags) + struct tKey { eKeys type; char *name; diff --git a/interface.c b/interface.c index 485a5dd0..84ee101c 100644 --- a/interface.c +++ b/interface.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: interface.c 1.22 2000/10/07 16:42:37 kls Exp $ + * $Id: interface.c 1.23 2000/10/08 11:17:11 kls Exp $ */ #include "interface.h" @@ -58,21 +58,29 @@ void cInterface::Close(void) cDvbApi::PrimaryDvbApi->Close(); } -unsigned int cInterface::GetCh(bool Wait) +unsigned int cInterface::GetCh(bool Wait, bool *Repeat, bool *Release) { if (open) cDvbApi::PrimaryDvbApi->Flush(); if (!RcIo.InputAvailable()) cFile::AnyFileReady(-1, Wait ? 1000 : 0); unsigned int Command; - return RcIo.GetCommand(&Command) ? Command : 0; + return RcIo.GetCommand(&Command, Repeat, Release) ? Command : 0; } eKeys cInterface::GetKey(bool Wait) { if (SVDRP) SVDRP->Process(); - eKeys Key = keyFromWait != kNone ? keyFromWait : Keys.Get(GetCh(Wait)); + eKeys Key = keyFromWait; + if (Key == kNone) { + bool Repeat = false, Release = false; + Key = Keys.Get(GetCh(Wait, &Repeat, &Release)); + if (Repeat) + Key = eKeys(Key | k_Repeat); + if (Release) + Key = eKeys(Key | k_Release); + } keyFromWait = kNone; return Key; } @@ -90,10 +98,10 @@ eKeys cInterface::Wait(int Seconds, bool KeepChar) time_t timeout = time(NULL) + Seconds; for (;;) { Key = GetKey(); - if (Key != kNone || time(NULL) > timeout) + if ((Key != kNone && (NORMALKEY(Key) != kOk || NORMALKEY(Key) == Key)) || time(NULL) > timeout) break; } - if (KeepChar) + if (KeepChar && ISNORMALKEY(Key)) keyFromWait = Key; return Key; } diff --git a/interface.h b/interface.h index c5592983..e3bce38c 100644 --- a/interface.h +++ b/interface.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: interface.h 1.14 2000/10/07 16:17:53 kls Exp $ + * $Id: interface.h 1.15 2000/10/08 09:51:42 kls Exp $ */ #ifndef __INTERFACE_H @@ -22,7 +22,7 @@ private: int cols[MaxCols]; eKeys keyFromWait; cSVDRP *SVDRP; - unsigned int GetCh(bool Wait = true); + unsigned int GetCh(bool Wait = true, bool *Repeat = NULL, bool *Release = NULL); void QueryKeys(void); void HelpButton(int Index, const char *Text, eDvbColor FgColor, eDvbColor BgColor); eKeys Wait(int Seconds = 1, bool KeepChar = false); diff --git a/menu.c b/menu.c index 1f5fd888..cc7618ba 100644 --- a/menu.c +++ b/menu.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: menu.c 1.30 2000/10/03 14:06:44 kls Exp $ + * $Id: menu.c 1.31 2000/10/08 10:47:17 kls Exp $ */ #include "menu.h" @@ -94,11 +94,11 @@ eOSState cMenuEditIntItem::ProcessKey(eKeys Key) } newValue = *value * 10 + (Key - k0); } - else if (Key == kLeft) { // TODO might want to increase the delta if repeated quickly? + else if (NORMALKEY(Key) == kLeft) { // TODO might want to increase the delta if repeated quickly? newValue = *value - 1; fresh = true; } - else if (Key == kRight) { + else if (NORMALKEY(Key) == kRight) { newValue = *value + 1; fresh = true; } @@ -211,6 +211,7 @@ void cMenuEditDayItem::Set(void) eOSState cMenuEditDayItem::ProcessKey(eKeys Key) { switch (Key) { + case kLeft|k_Repeat: case kLeft: if (d > 0) *value = days[--d]; else if (d == 0) { @@ -225,6 +226,7 @@ eOSState cMenuEditDayItem::ProcessKey(eKeys Key) return cMenuEditIntItem::ProcessKey(Key); Set(); break; + case kRight|k_Repeat: case kRight: if (d >= 0) { *value = days[++d]; if (*value == 0) { @@ -310,7 +312,7 @@ eOSState cMenuEditTimeItem::ProcessKey(eKeys Key) break; } } - else if (Key == kLeft) { // TODO might want to increase the delta if repeated quickly? + else if (NORMALKEY(Key) == kLeft) { // TODO might want to increase the delta if repeated quickly? if (--mm < 0) { mm = 59; if (--hh < 0) @@ -318,7 +320,7 @@ eOSState cMenuEditTimeItem::ProcessKey(eKeys Key) } fresh = true; } - else if (Key == kRight) { + else if (NORMALKEY(Key) == kRight) { if (++mm > 59) { mm = 0; if (++hh > 23) @@ -377,11 +379,11 @@ eOSState cMenuEditChrItem::ProcessKey(eKeys Key) eOSState state = cMenuEditItem::ProcessKey(Key); if (state == osUnknown) { - if (Key == kLeft) { + if (NORMALKEY(Key) == kLeft) { if (current > allowed) current--; } - else if (Key == kRight) { + else if (NORMALKEY(Key) == kRight) { if (*(current + 1)) current++; } @@ -455,12 +457,14 @@ char cMenuEditStrItem::Inc(char c, bool Up) eOSState cMenuEditStrItem::ProcessKey(eKeys Key) { switch (Key) { + case kLeft|k_Repeat: case kLeft: if (pos > 0) { if (value[pos] == '^') value[pos] = 0; pos--; } break; + case kRight|k_Repeat: case kRight: if (pos < length && value[pos] != '^' && (pos < int(strlen(value) - 1) || value[pos] != ' ')) { if (++pos >= int(strlen(value))) { value[pos] = ' '; @@ -468,9 +472,11 @@ eOSState cMenuEditStrItem::ProcessKey(eKeys Key) } } break; + case kUp|k_Repeat: case kUp: + case kDown|k_Repeat: case kDown: if (pos >= 0) - value[pos] = Inc(value[pos], Key == kUp); + value[pos] = Inc(value[pos], NORMALKEY(Key) == kUp); else return cMenuEditItem::ProcessKey(Key); break; @@ -1388,7 +1394,12 @@ eOSState cReplayControl::ProcessKey(eKeys Key) return osEnd; case kLeft: dvbApi->Backward(); break; case kRight: dvbApi->Forward(); break; + case kLeft|k_Release: + case kRight|k_Release: + dvbApi->Play(); break; + case kGreen|k_Repeat: case kGreen: dvbApi->Skip(-60); break; + case kYellow|k_Repeat: case kYellow: dvbApi->Skip(60); break; case kMenu: Hide(); return osMenu; // allow direct switching to menu case kOk: visible ? Hide() : Show(); break; diff --git a/osd.c b/osd.c index e1c99b44..6874ba9f 100644 --- a/osd.c +++ b/osd.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: osd.c 1.7 2000/09/10 08:24:50 kls Exp $ + * $Id: osd.c 1.8 2000/10/08 10:27:04 kls Exp $ */ #include "osd.h" @@ -274,7 +274,9 @@ eOSState cOsdMenu::ProcessKey(eKeys Key) return state; } switch (Key) { + case kUp|k_Repeat: case kUp: CursorUp(); break; + case kDown|k_Repeat: case kDown: CursorDown(); break; case kBack: return osBack; case kOk: if (marked >= 0) { diff --git a/remote.c b/remote.c index 968184a5..87c70923 100644 --- a/remote.c +++ b/remote.c @@ -6,7 +6,7 @@ * * Ported to LIRC by Carsten Koch 2000-06-16. * - * $Id: remote.c 1.16 2000/10/08 09:25:20 kls Exp $ + * $Id: remote.c 1.17 2000/10/08 11:39:11 kls Exp $ */ #include "remote.h" @@ -69,7 +69,7 @@ bool cRcIoKBD::InputAvailable(void) return f.Ready(false); } -bool cRcIoKBD::GetCommand(unsigned int *Command) +bool cRcIoKBD::GetCommand(unsigned int *Command, bool *Repeat, bool *Release) { if (Command) { *Command = getch(); @@ -93,7 +93,7 @@ cRcIoRCU::cRcIoRCU(char *DeviceName) address = 0xFFFF; receivedAddress = 0; receivedCommand = 0; - receivedData = receivedRepeat = false; + receivedData = receivedRepeat = receivedRelease = false; lastNumber = 0; if ((f = open(DeviceName, O_RDWR | O_NONBLOCK)) >= 0) { struct termios t; @@ -131,8 +131,8 @@ void cRcIoRCU::Action(void) dsyslog(LOG_INFO, "RCU remote control thread started (pid=%d)", getpid()); - unsigned int LastCommand = 0; int FirstTime = 0; + unsigned int LastCommand = 0; for (; f >= 0;) { @@ -151,20 +151,23 @@ void cRcIoRCU::Action(void) // This remote control sends the above command before and after // each keypress - let's just drop this: break; - int Now = time_ms(); - if (Command != LastCommand) { - receivedAddress = Address; - receivedCommand = Command; - receivedData = true; - FirstTime = Now; + if (!receivedData) { // only accept new data the previous data has been fetched + int Now = time_ms(); + if (Command != LastCommand) { + receivedAddress = Address; + receivedCommand = Command; + receivedData = true; + receivedRepeat = receivedRelease = false; + FirstTime = Now; + } + else { + if (Now - FirstTime < REPEATDELAY) + break; // repeat function kicks in after a short delay + receivedData = receivedRepeat = true; + } + LastCommand = Command; + WakeUp(); } - else { - if (Now - FirstTime < REPEATDELAY) - break; // repeat function kicks in after a short delay - receivedData = receivedRepeat = true; - } - LastCommand = Command; - WakeUp(); } } else @@ -172,16 +175,15 @@ void cRcIoRCU::Action(void) } } else if (receivedData) { // the last data before releasing the key hasn't been fetched yet - if (receivedRepeat) { // it was a repeat, so let's drop it - //XXX replace it with "released"??? - receivedData = receivedRepeat = false; + if (receivedRepeat) { // it was a repeat, so let's make it a release + receivedRepeat = false; + receivedRelease = true; LastCommand = 0; - //XXX WakeUp(); + WakeUp(); } } - else if (receivedRepeat) { // all data has already been fetched, but the last one was a repeat - //XXX replace it with "released"??? - //XXX receivedData = true; + else if (receivedRepeat) { // all data has already been fetched, but the last one was a repeat, so let's generate a release + receivedData = receivedRelease = true; receivedRepeat = false; LastCommand = 0; WakeUp(); @@ -266,7 +268,7 @@ void cRcIoRCU::Flush(int WaitMs) receivedData = receivedRepeat = false; } -bool cRcIoRCU::GetCommand(unsigned int *Command) +bool cRcIoRCU::GetCommand(unsigned int *Command, bool *Repeat, bool *Release) { if (receivedData) { // first we check the boolean flag without a lock, to avoid delays @@ -275,7 +277,10 @@ bool cRcIoRCU::GetCommand(unsigned int *Command) if (receivedData) { // need to check again, since the status might have changed while waiting for the lock if (Command) *Command = receivedCommand; - //XXX repeat!!! + if (Repeat) + *Repeat = receivedRepeat; + if (Release) + *Release = receivedRelease; receivedData = false; return true; } @@ -422,47 +427,47 @@ void cRcIoLIRC::Action(void) int FirstTime = 0; char buf[LIRC_BUFFER_SIZE]; + char LastKeyName[LIRC_KEY_BUF]; for (; f >= 0;) { LOCK_THREAD; if (cFile::FileReady(f, REPEATLIMIT) && read(f, buf, sizeof(buf)) > 21) { - int count; - sscanf(buf, "%*x %x %7s", &count, keyName); // '7' in '%7s' is LIRC_KEY_BUF-1! - int Now = time_ms(); - if (count == 0) { - receivedData = true; - FirstTime = Now; + if (!receivedData) { // only accept new data the previous data has been fetched + int count; + sscanf(buf, "%*x %x %7s", &count, LastKeyName); // '7' in '%7s' is LIRC_KEY_BUF-1! + int Now = time_ms(); + if (count == 0) { + strcpy(keyName, LastKeyName); + receivedData = true; + receivedRepeat = receivedRelease = false; + FirstTime = Now; + } + else { + if (Now - FirstTime < REPEATDELAY) + continue; // repeat function kicks in after a short delay + receivedData = receivedRepeat = true; + } + WakeUp(); } - else { - if (Now - FirstTime < REPEATDELAY) - continue; // repeat function kicks in after a short delay - receivedData = receivedRepeat = true; - } - WakeUp(); } else if (receivedData) { // the last data before releasing the key hasn't been fetched yet - if (receivedRepeat) { // it was a repeat, so let's drop it - //XXX replace it with "released"??? - receivedData = receivedRepeat = false; - *keyName = 0; - //XXX WakeUp(); + if (receivedRepeat) { // it was a repeat, so let's make it a release + receivedRepeat = false; + receivedRelease = true; + WakeUp(); } } - else if (receivedRepeat) { // all data has already been fetched, but the last one was a repeat - //XXX replace it with "released"??? - //XXX receivedData = true; + else if (receivedRepeat) { // all data has already been fetched, but the last one was a repeat, so let's generate a release + receivedData = receivedRelease = true; receivedRepeat = false; - *keyName = 0; WakeUp(); } - else - *keyName = 0; } } -bool cRcIoLIRC::GetCommand(unsigned int *Command) +bool cRcIoLIRC::GetCommand(unsigned int *Command, bool *Repeat, bool *Release) { if (receivedData) { // first we check the boolean flag without a lock, to avoid delays @@ -471,7 +476,10 @@ bool cRcIoLIRC::GetCommand(unsigned int *Command) if (receivedData) { // need to check again, since the status might have changed while waiting for the lock if (Command) *Command = Keys.Encode(keyName); - //XXX repeat!!! + if (Repeat) + *Repeat = receivedRepeat; + if (Release) + *Release = receivedRelease; receivedData = false; return true; } diff --git a/remote.h b/remote.h index b9e79b4d..1e779b0b 100644 --- a/remote.h +++ b/remote.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: remote.h 1.11 2000/10/07 18:50:51 kls Exp $ + * $Id: remote.h 1.12 2000/10/08 11:19:17 kls Exp $ */ #ifndef __REMOTE_H @@ -30,7 +30,7 @@ public: virtual bool DetectCode(unsigned char *Code, unsigned short *Address) { return true; } virtual void Flush(int WaitMs = 0) {} virtual bool InputAvailable(void) = 0; - virtual bool GetCommand(unsigned int *Command = NULL) = 0; + virtual bool GetCommand(unsigned int *Command = NULL, bool *Repeat = NULL, bool *Release = NULL) = 0; }; #if defined REMOTE_KBD @@ -43,7 +43,7 @@ public: virtual ~cRcIoKBD(); virtual void Flush(int WaitMs = 0); virtual bool InputAvailable(void); - virtual bool GetCommand(unsigned int *Command = NULL); + virtual bool GetCommand(unsigned int *Command = NULL, bool *Repeat = NULL, bool *Release = NULL); }; #elif defined REMOTE_RCU @@ -55,7 +55,7 @@ private: unsigned short address; unsigned short receivedAddress; unsigned int receivedCommand; - bool receivedData, receivedRepeat; + bool receivedData, receivedRepeat, receivedRelease; int lastNumber; bool SendCommand(unsigned char Cmd); int ReceiveByte(int TimeoutMs = 0); @@ -74,7 +74,7 @@ public: virtual bool DetectCode(unsigned char *Code, unsigned short *Address); virtual void Flush(int WaitMs = 0); virtual bool InputAvailable(void) { return receivedData; } - virtual bool GetCommand(unsigned int *Command = NULL); + virtual bool GetCommand(unsigned int *Command = NULL, bool *Repeat = NULL, bool *Release = NULL); }; #elif defined REMOTE_LIRC @@ -84,13 +84,13 @@ private: enum { LIRC_KEY_BUF = 8, LIRC_BUFFER_SIZE = 128 }; int f; char keyName[LIRC_KEY_BUF]; - bool receivedData, receivedRepeat; + bool receivedData, receivedRepeat, receivedRelease; virtual void Action(void); public: cRcIoLIRC(char *DeviceName); virtual ~cRcIoLIRC(); virtual bool InputAvailable(void) { return receivedData; } - virtual bool GetCommand(unsigned int *Command = NULL); + virtual bool GetCommand(unsigned int *Command = NULL, bool *Repeat = NULL, bool *Release = NULL); }; #else diff --git a/vdr.c b/vdr.c index 042b03ce..379b6b45 100644 --- a/vdr.c +++ b/vdr.c @@ -22,7 +22,7 @@ * * The project's page is at http://www.cadsoft.de/people/kls/vdr * - * $Id: vdr.c 1.36 2000/10/03 13:52:26 kls Exp $ + * $Id: vdr.c 1.37 2000/10/08 10:32:44 kls Exp $ */ #include @@ -257,10 +257,12 @@ int main(int argc, char *argv[]) Menu = new cDirectChannelSelect(key); break; // Left/Right rotates trough channel groups: + case kLeft|k_Repeat: case kLeft: + case kRight|k_Repeat: case kRight: if (!Interface.Recording()) { int SaveGroup = CurrentGroup; - if (key == kRight) + if (NORMALKEY(key) == kRight) CurrentGroup = Channels.GetNextGroup(CurrentGroup) ; else CurrentGroup = Channels.GetPrevGroup(CurrentGroup < 1 ? 1 : CurrentGroup); @@ -271,9 +273,11 @@ int main(int argc, char *argv[]) } break; // Up/Down Channel Select: + case kUp|k_Repeat: case kUp: + case kDown|k_Repeat: case kDown: if (!Interface.Recording()) { - int n = CurrentChannel + (key == kUp ? 1 : -1); + int n = CurrentChannel + (NORMALKEY(key) == kUp ? 1 : -1); cChannel *channel = Channels.GetByNumber(n); if (channel) channel->Switch();