Re: Feature request: program guide scroll

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Am 17.06.2010 19:29, schrieb Udo Richter:
> Am 17.06.2010 17:31, schrieb martinez:
>> Can any kind person write this patch? 
> 
> I'll see if I can come up with something on the weekend.


As always, the more close you look on it, the more complicated it gets.
In other words, it got a little more than 12 lines... ;)

The cMenuEvent can now switch through the list of events of the parent
menu with the green and yellow buttons. Depending on the parent menu,
the buttons either show channel names or event starting times. From
timer menu (blue button), the green and yellow buttons stay empty.

To gain access to the list of events, I've added an abstract
cEventSequence class that is implemented by cMenuWhatsOn and
cMenuSchedule. That way these two and the cMenuScheduleItem can continue
to be private to menu.c.

Since now the cMenuEvent can handle different events, a convenient
shortcut had to be removed: Previously, the red and blue buttons were
handled by the parent menu, not cMenuEvent itself. cMenuEvent now does
this on its own. Also the constructor parameters CanSwitch and Buttons
were dropped and replaced by dynamic code. By this change, the event
info on blue key in timers menu gains the red and blue button for free.

cMenuEvent had its ProcessKey re-arranged, as the original version could
not handle sub-menus. (the parent menu did.)

Timer menu got a bug fix to handle sub-sub-menus without overwriting the
button bar.



The attached patch is against vdr-1.6, but also cleanly applies and
compiles on vdr-1.7.15.

A little testing help and feedback is welcome. Check that the green and
yellow buttons work in program, whats now, whats next and timer info
menu, and keep an eye on button bar text in the event menu and the
parent menu after exiting. Also, the t and T markers on events should
change, and in the timer menu the '>' for active timers, if you change
that. Try adding timers from the event menu for running and future
events. Try whether the blue key switches to the right channel. And try
whatever else you can imagine.


Cheers,

Udo
diff -Naur vdr-1.6.0/menu.h vdr-1.6.0-MenuEventNext/menu.h
--- vdr-1.6.0/menu.h	2008-02-10 17:01:53.000000000 +0100
+++ vdr-1.6.0-MenuEventNext/menu.h	2010-06-19 15:33:20.000000000 +0200
@@ -45,12 +45,28 @@
   virtual eOSState ProcessKey(eKeys Key);
   };
 
+class cEventSequence {
+public:
+  virtual const cEvent* GetEvent(int Nr) const = 0;
+  virtual int GetEventCount() const = 0;
+};
+
 class cMenuEvent : public cOsdMenu {
 private:
   const cEvent *event;
-public:
-  cMenuEvent(const cEvent *Event, bool CanSwitch = false, bool Buttons = false);
+  const cEventSequence *eventSequence;
+  int eventNr;
+  int otherChannel;
+  char *green;
+  char *yellow;
+  void UpdateEvent();
+public:
+  cMenuEvent(const cEvent *Event);
+  cMenuEvent(const cEventSequence *Events, int EventNr);
+  virtual ~cMenuEvent();
   virtual void Display(void);
+  eOSState Record(void);
+  eOSState Switch(void);
   virtual eOSState ProcessKey(eKeys Key);
   };
 
diff -Naur vdr-1.6.0/menu.c vdr-1.6.0-MenuEventNext/menu.c
--- vdr-1.6.0/menu.c	2008-03-16 12:15:28.000000000 +0100
+++ vdr-1.6.0-MenuEventNext/menu.c	2010-06-19 16:38:35.000000000 +0200
@@ -974,27 +974,99 @@
      Add(new cMenuTimerItem(Timers.Get(TimerNumber)), true);
      Display();
      }
-  if (Key != kNone)
+  if (Key != kNone && !HasSubMenu())
      SetHelpKeys();
   return state;
 }
 
 // --- cMenuEvent ------------------------------------------------------------
 
-cMenuEvent::cMenuEvent(const cEvent *Event, bool CanSwitch, bool Buttons)
+cMenuEvent::cMenuEvent(const cEvent *Event)
 :cOsdMenu(tr("Event"))
 {
   event = Event;
+  eventNr = 0;
+  eventSequence = NULL;
+  green = NULL;
+  yellow = NULL;
+  UpdateEvent();
+}
+
+cMenuEvent::cMenuEvent(const cEventSequence *Events, int EventNr)
+:cOsdMenu(tr("Event"))
+{
+  eventSequence = Events;
+  eventNr = EventNr;
+  green = NULL;
+  yellow = NULL;
+  UpdateEvent();
+}
+
+cMenuEvent::~cMenuEvent() {
+  if (green)
+     free(green);
+  if (yellow)
+     free(yellow);
+}
+
+void cMenuEvent::UpdateEvent()
+{
+  const cEvent *eventPrev = NULL;
+  const cEvent *eventNext = NULL;
+  int TimerMatch = tmNone;
+  otherChannel = 0;
+
+  if (eventSequence) {
+     event = eventSequence->GetEvent(eventNr);
+     eventPrev = eventSequence->GetEvent(eventNr-1);
+     eventNext = eventSequence->GetEvent(eventNr+1);
+     }
+
   if (event) {
      cChannel *channel = Channels.GetByChannelID(event->ChannelID(), true);
      if (channel) {
         SetTitle(channel->Name());
-        int TimerMatch = tmNone;
-        Timers.GetMatch(event, &TimerMatch);
-        if (Buttons)
-           SetHelp(TimerMatch == tmFull ? tr("Button$Timer") : tr("Button$Record"), NULL, NULL, CanSwitch ? tr("Button$Switch") : NULL);
+        if (channel->Number() != cDevice::CurrentChannel())
+           otherChannel = channel->Number();
         }
+     Timers.GetMatch(event, &TimerMatch);
      }
+
+  if (green) {
+     free(green);
+     green = NULL;
+     }
+  if (eventPrev) {
+     if (eventPrev->ChannelID() == event->ChannelID()) {
+        time_t tstart = eventPrev->StartTime();
+        struct tm tm_r;
+        struct tm *time = localtime_r(&tstart, &tm_r);
+        asprintf(&green, "%02d:%02d", time->tm_hour, time->tm_min);
+        }
+     else {
+        cChannel *channel = Channels.GetByChannelID(eventPrev->ChannelID(), true);
+        green = strdup(channel->Name());
+        }
+     }
+
+  if (yellow) {
+     free(yellow);
+     yellow = NULL;
+     }
+  if (eventNext) {
+     if (eventNext->ChannelID() == event->ChannelID()) {
+        time_t tstart = eventNext->StartTime();
+        struct tm tm_r;
+        struct tm *time = localtime_r(&tstart, &tm_r);
+        asprintf(&yellow, "%02d:%02d", time->tm_hour, time->tm_min);
+        }
+     else {
+        cChannel *channel = Channels.GetByChannelID(eventNext->ChannelID(), true);
+        yellow = strdup(channel->Name());
+        }
+     }
+
+  SetHelp(TimerMatch == tmFull ? tr("Button$Timer") : tr("Button$Record"), green, yellow, otherChannel ? tr("Button$Switch") : NULL);
 }
 
 void cMenuEvent::Display(void)
@@ -1005,34 +1077,87 @@
      cStatus::MsgOsdTextItem(event->Description());
 }
 
-eOSState cMenuEvent::ProcessKey(eKeys Key)
+eOSState cMenuEvent::Record(void)
 {
-  switch (Key) {
-    case kUp|k_Repeat:
-    case kUp:
-    case kDown|k_Repeat:
-    case kDown:
-    case kLeft|k_Repeat:
-    case kLeft:
-    case kRight|k_Repeat:
-    case kRight:
-                  DisplayMenu()->Scroll(NORMALKEY(Key) == kUp || NORMALKEY(Key) == kLeft, NORMALKEY(Key) == kLeft || NORMALKEY(Key) == kRight);
-                  cStatus::MsgOsdTextItem(NULL, NORMALKEY(Key) == kUp || NORMALKEY(Key) == kLeft);
-                  return osContinue;
-    case kInfo:   return osBack;
-    default: break;
-    }
+  if (event) {
+     int tm = tmNone;
+     cTimer *timer = Timers.GetMatch(event, &tm);
+     if (timer)
+        return AddSubMenu(new cMenuEditTimer(timer));
 
+     timer = new cTimer(event);
+     cTimer *t = Timers.GetTimer(timer);
+     if (t) {
+        delete timer;
+        timer = t;
+        return AddSubMenu(new cMenuEditTimer(timer));
+        }
+     else {
+        Timers.Add(timer);
+        Timers.SetModified();
+        isyslog("timer %s added (active)", *timer->ToDescr());
+        if (timer->Matches(0, false, NEWTIMERLIMIT))
+           return AddSubMenu(new cMenuEditTimer(timer));
+        UpdateEvent();
+        Display();
+        }
+     }
+  return osContinue;
+}
+
+eOSState cMenuEvent::Switch(void)
+{
+  if (otherChannel) {
+     if (Channels.SwitchTo(otherChannel))
+        return osEnd;
+     }
+  Skins.Message(mtError, tr("Can't switch channel!"));
+  return osContinue;
+}
+
+eOSState cMenuEvent::ProcessKey(eKeys Key)
+{
+  bool HadSubMenu = HasSubMenu();
   eOSState state = cOsdMenu::ProcessKey(Key);
 
   if (state == osUnknown) {
      switch (Key) {
-       case kGreen:
-       case kYellow: return osContinue;
+       case kUp|k_Repeat:
+       case kUp:
+       case kDown|k_Repeat:
+       case kDown:
+       case kLeft|k_Repeat:
+       case kLeft:
+       case kRight|k_Repeat:
+       case kRight:
+                     DisplayMenu()->Scroll(NORMALKEY(Key) == kUp || NORMALKEY(Key) == kLeft, NORMALKEY(Key) == kLeft || NORMALKEY(Key) == kRight);
+                     cStatus::MsgOsdTextItem(NULL, NORMALKEY(Key) == kUp || NORMALKEY(Key) == kLeft);
+                     return osContinue;
+       case kInfo:   return osBack;
+       case kRecord:
+       case kRed:    return Record();
+       case kGreen:  if (eventSequence && eventNr > 0) {
+                        eventNr--;
+                        UpdateEvent();
+                        Display();
+                        }
+                     return osContinue;
+       case kYellow: if (eventSequence && eventNr < eventSequence->GetEventCount()-1) {
+                        eventNr++;
+                        UpdateEvent();
+                        Display();
+                        }
+                     return osContinue;
+       case kBlue:   return Switch();
        case kOk:     return osBack;
        default: break;
        }
      }
+  else if (!HasSubMenu() && HadSubMenu) {
+     UpdateEvent();
+     Display();
+     }
+
   return state;
 }
 
@@ -1106,7 +1231,7 @@
 
 // --- cMenuWhatsOn ----------------------------------------------------------
 
-class cMenuWhatsOn : public cOsdMenu {
+class cMenuWhatsOn : public cOsdMenu, public cEventSequence {
 private:
   bool now;
   int helpKeys;
@@ -1123,6 +1248,8 @@
   static void SetCurrentChannel(int ChannelNr) { currentChannel = ChannelNr; }
   static const cEvent *ScheduleEvent(void);
   virtual eOSState ProcessKey(eKeys Key);
+  virtual const cEvent* GetEvent(int Nr) const;
+  virtual int GetEventCount() const;
   };
 
 int cMenuWhatsOn::currentChannel = 0;
@@ -1253,7 +1380,7 @@
        case kBlue:   return Switch();
        case kInfo:
        case kOk:     if (Count())
-                        return AddSubMenu(new cMenuEvent(((cMenuScheduleItem *)Get(Current()))->event, true, true));
+                        return AddSubMenu(new cMenuEvent(this, Current()));
                      break;
        default:      break;
        }
@@ -1267,9 +1394,19 @@
   return state;
 }
 
+const cEvent* cMenuWhatsOn::GetEvent(int Nr) const {
+  if (Nr >= 0 && Nr < Count())
+     return ((cMenuScheduleItem *)Get(Nr))->event;
+  return NULL;
+  }
+
+int cMenuWhatsOn::GetEventCount() const {
+  return Count();
+  }
+
 // --- cMenuSchedule ---------------------------------------------------------
 
-class cMenuSchedule : public cOsdMenu {
+class cMenuSchedule : public cOsdMenu, public cEventSequence {
 private:
   cSchedulesLock schedulesLock;
   const cSchedules *schedules;
@@ -1290,6 +1427,8 @@
   cMenuSchedule(void);
   virtual ~cMenuSchedule();
   virtual eOSState ProcessKey(eKeys Key);
+  virtual const cEvent* GetEvent(int Nr) const;
+  virtual int GetEventCount() const;
   };
 
 cMenuSchedule::cMenuSchedule(void)
@@ -1518,7 +1657,7 @@
                      break;
        case kInfo:
        case kOk:     if (Count())
-                        return AddSubMenu(new cMenuEvent(((cMenuScheduleItem *)Get(Current()))->event, otherChannel, true));
+                        return AddSubMenu(new cMenuEvent(this, Current()));
                      break;
        default:      break;
        }
@@ -1546,6 +1685,16 @@
   return state;
 }
 
+const cEvent* cMenuSchedule::GetEvent(int Nr) const {
+  if (Nr >= 0 && Nr < Count())
+     return ((cMenuScheduleItem *)Get(Nr))->event;
+  return NULL;
+  }
+
+int cMenuSchedule::GetEventCount() const {
+  return Count();
+  }
+
 // --- cMenuCommands ---------------------------------------------------------
 
 class cMenuCommands : public cOsdMenu {

_______________________________________________
vdr mailing list
vdr@xxxxxxxxxxx
http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr

[Index of Archives]     [Linux Media]     [Asterisk]     [DCCP]     [Netdev]     [Xorg]     [Util Linux NG]     [Xfree86]     [Big List of Linux Books]     [Fedora Users]     [Fedora Women]     [ALSA Devel]     [Linux USB]

  Powered by Linux