]> git.vomp.tv Git - vompclient-marten.git/commitdiff
New timers code
authorChris Tallon <chris@vomp.tv>
Fri, 2 Dec 2005 23:10:42 +0000 (23:10 +0000)
committerChris Tallon <chris@vomp.tv>
Fri, 2 Dec 2005 23:10:42 +0000 (23:10 +0000)
21 files changed:
command.cc
command.h
main.cc
playerradio.cc
playervideo.cc
thread.cc
timers.cc
timers.h
vchannellist.cc
vconnect.cc
vepg.cc
vepg.h
viewman.cc
viewman.h
vlivebanner.cc
vrecordinglist.cc
vrecordingmenu.cc
vvideolive.cc
vwelcome.cc
wtextbox.cc
wtextbox.h

index ef4834801daebfaeaa588e65837b9afd07f98ed3..abf770bd4e9ca31f88e2ea26e7fe0f4452b687ac 100644 (file)
@@ -131,11 +131,13 @@ void Command::run()
   {
     // unlock and wait
     pthread_mutex_unlock(&masterLock);
+    logger->log("Command", Log::DEBUG, "un-LOCKED MASTER MUTEX");
 
     button = remote->getButtonPress(2);  // FIXME why is this set to 2 and not 0? so it can quit
     // something happened, lock and process
 
     pthread_mutex_lock(&masterLock);
+    logger->log("Command", Log::DEBUG, "LOCKED MASTER MUTEX");
 
     if ((button == Remote::NA_NONE) || (button == Remote::NA_UNKNOWN)) continue;
 
@@ -154,9 +156,32 @@ void Command::postMessage(Message* m)
   // locking the mutex ensures that the master thread is waiting on getButtonPress
 
   pthread_mutex_lock(&masterLock);
+    logger->log("Command", Log::DEBUG, "LOCKED MASTER MUTEX");
   MessageQueue::postMessage(m);
   kill(mainPid, SIGURG);
   pthread_mutex_unlock(&masterLock);
+    logger->log("Command", Log::DEBUG, "un-LOCKED MASTER MUTEX");
+}
+
+bool Command::postMessageIfNotBusy(Message* m)
+{
+  // This is for the timers module
+  // If the masterlock is locked then the timers module wants to
+  // cancel delivery
+
+  if (pthread_mutex_trylock(&masterLock) != EBUSY)
+  {
+      logger->log("Command", Log::DEBUG, "LOCKED MASTER MUTEX");
+    MessageQueue::postMessage(m);
+    kill(mainPid, SIGURG);
+    pthread_mutex_unlock(&masterLock);
+      logger->log("Command", Log::DEBUG, "un-LOCKED MASTER MUTEX");
+    return true;
+  }
+  else
+  {
+    return false;
+  }
 }
 
 void Command::processMessage(Message* m)
@@ -205,6 +230,12 @@ void Command::processMessage(Message* m)
 
 
       // deliver timer
+
+      logger->log("Command", Log::DEBUG, "m = %p", m);
+      logger->log("Command", Log::DEBUG, "m->message = %i", m->message);
+      logger->log("Command", Log::DEBUG, "m->from = %p", m->from);
+      logger->log("Command", Log::DEBUG, "m->to = %p", m->to);
+      logger->log("Command", Log::DEBUG, "m->parameter = %p", m->parameter);
       ((TimerReceiver*)m->to)->timercall(m->parameter);
       handleCommand(Remote::NA_NONE); // in case any timer has posted messages to viewman,
                                       // run viewman message queue here. FIXME improve this!
@@ -294,7 +325,7 @@ void Command::doJustConnected(VConnect* vconnect)
 {
   I18n::initialize();
   Video* video = Video::getInstance();
-  viewman->removeView(vconnect, 0);
+  viewman->removeView(vconnect);
 
   VInfo* vi = new VInfo();
   vi->create(400, 200);
index 91526f0af1b06876113f8515667b5ed4b6dac8ac..ccd651ff73d1c0f863b1a33100710a8c4da4aa8d 100644 (file)
--- a/command.h
+++ b/command.h
@@ -68,6 +68,7 @@ class Command : public MessageQueue
     void stop();
     void doReboot();
     void postMessage(Message* m); // override of MessageQueue::postMessage
+    bool postMessageIfNotBusy(Message* m); // for timers, when masterMutex might be locked
 
   private:
     void handleCommand(int);
diff --git a/main.cc b/main.cc
index a4e1bfe969ce24aa87341b5f3d25c88b7d305ee6..4dfbbc2f51d67649ec69f1e629e38bb453cb9527 100644 (file)
--- a/main.cc
+++ b/main.cc
@@ -30,6 +30,7 @@
 #include "remote.h"
 #include "led.h"
 #include "mtd.h"
+#include "timers.h"
 #include "video.h"
 #include "audio.h"
 #include "vdr.h"
@@ -47,6 +48,7 @@ Remote* remote;
 Mtd* mtd;
 Led* led;
 Osd* osd;
+Timers* timers;
 ViewMan* viewman;
 Command* command;
 VDR* vdr;
@@ -64,6 +66,7 @@ int main(int argc, char** argv)
   remote     = new Remote();
   mtd        = new Mtd();
   led        = new Led();
+  timers     = new Timers();
   osd        = new Osd();
   vdr        = new VDR();
   video      = new Video();
@@ -188,6 +191,17 @@ int main(int argc, char** argv)
     shutdown(1);
   }
 
+  success = timers->init();
+  if (success)
+  {
+    logger->log("Core", Log::INFO, "Timers module initialised");
+  }
+  else
+  {
+    logger->log("Core", Log::EMERG, "Timers module failed to initialise");
+    shutdown(1);
+  }
+
   UCHAR videoFormat = (UCHAR)mtd->getPALorNTSC();
   if      (videoFormat == Video::PAL)  logger->log("Core", Log::INFO, "Read from MTD: PAL 720x576");
   else if (videoFormat == Video::NTSC) logger->log("Core", Log::INFO, "Read from MTD: NTSC 720x480");
@@ -322,6 +336,13 @@ void shutdown(int code)
     logger->log("Core", Log::NOTICE, "Video module shut down");
   }
 
+  if (timers)
+  {
+    timers->shutdown();
+    delete timers;
+    logger->log("Core", Log::NOTICE, "Timers module shut down");
+  }
+
   if (mtd)
   {
     mtd->shutdown();
index ec41b2bdcd59f9961abfdf3dc34ac168204a6864..419391e2fed09c031c6ffe563a3f80a287b152ea 100644 (file)
@@ -368,7 +368,9 @@ void PlayerRadio::threadMethod()
       {
         Log::getInstance()->log("PlayerRadio", Log::DEBUG, "RADIO OUTPUT STREAM FULL!!!");
         // stream is full and cant take anymore
+        threadLock();
         threadWaitForSignal();
+        threadUnlock();
         Log::getInstance()->log("PlayerRadio", Log::DEBUG, "BACK FROM WAIT");
       }
 
index 82ff84778ea84918aa56ced3b36db6cd4c006e22..0a326e8cbee7cda6ad1435850c33c91f7bded09b 100644 (file)
@@ -608,7 +608,9 @@ void PlayerVideo::threadMethod()
       {
 //        Log::getInstance()->log("Player", Log::DEBUG, "DEMUXER FULL!!!");
         // demuxer is full and cant take anymore
+        threadLock();
         threadWaitForSignal();
+        threadUnlock();
 //        Log::getInstance()->log("Player", Log::DEBUG, "BACK FROM WAIT");
       }
 
index d8bb647bef177311a98f96dedd03dafe97c5c2df..6e210a547dc48e51ad90c91743ea132db7aba6c6 100644 (file)
--- a/thread.cc
+++ b/thread.cc
@@ -98,16 +98,12 @@ void Thread::threadSignalNoLock()
 
 void Thread::threadWaitForSignal()
 {
-  pthread_mutex_lock(&threadCondMutex);
   pthread_cond_wait(&threadCond, &threadCondMutex);
-  pthread_mutex_unlock(&threadCondMutex);
 }
 
 void Thread::threadWaitForSignalTimed(struct timespec* ts)
 {
-  pthread_mutex_lock(&threadCondMutex);
   pthread_cond_timedwait(&threadCond, &threadCondMutex, ts);
-  pthread_mutex_unlock(&threadCondMutex);
 }
 
 void Thread::threadSetKillable()
index eea0f89fc1c91278fe8fe0304df05a0d8890b995..e734f5bce50abae24173fef0f1786e4f3e8e3285 100755 (executable)
--- a/timers.cc
+++ b/timers.cc
@@ -47,13 +47,13 @@ int Timers::init()
 \r
   logger->log("Timers", Log::DEBUG, "Timers init start");\r
 \r
-  threadLock();\r
+  threadLock(); // lock here, the thread loop will unlock and wait\r
+logger->log("Timers", Log::DEBUG, "LOCKED -TIMERS- MUTEX 1");\r
   if (!threadStart())\r
   {\r
     shutdown();\r
     return 0;\r
   }\r
-  threadUnlock();\r
 \r
   logger->log("Timers", Log::DEBUG, "Timers init end");\r
 \r
@@ -88,18 +88,24 @@ int Timers::setTimer(TimerReceiver* client, int clientReference, time_t requeste
 {\r
   if (!initted) return 0;\r
 \r
+  logger->log("Timers", Log::DEBUG, "Starting set timer 1");\r
+\r
   Timer* t = new Timer();\r
   t->client = client;\r
   t->clientReference = clientReference;\r
   t->requestedTime.tv_sec = requestedTime;\r
   t->requestedTime.tv_nsec = 0;\r
 \r
+logger->log("Timers", Log::DEBUG, "Waiting for LOCK -TIMERS- MUTEX 2");\r
   threadLock();\r
+logger->log("Timers", Log::DEBUG, "LOCKED -TIMERS- MUTEX 2");\r
   timerList.push_back(t);\r
+  resetThreadFlag = true;\r
+  threadSignalNoLock();\r
+logger->log("Timers", Log::DEBUG, "about to un-LOCK -TIMERS- MUTEX 2");\r
   threadUnlock();\r
-  threadSignal();\r
 \r
-  logger->log("Timers", Log::DEBUG, "Have set timer for %p ref %i", client, clientReference);\r
+  logger->log("Timers", Log::DEBUG, "Have set timer for %p ref %i", client, clientReference);\r
 \r
   return 1;\r
 }\r
@@ -108,6 +114,8 @@ int Timers::setTimer(TimerReceiver* client, int clientReference, struct timespec
 {\r
   if (!initted) return 0;\r
 \r
+  logger->log("Timers", Log::DEBUG, "Starting set timer 2");\r
+\r
   Timer* t = new Timer();\r
   t->client = client;\r
   t->clientReference = clientReference;\r
@@ -124,12 +132,16 @@ int Timers::setTimer(TimerReceiver* client, int clientReference, struct timespec
     logger->log("Timers", Log::DEBUG, "Second rollover - CHECK FIXME");\r
   }\r
 \r
+logger->log("Timers", Log::DEBUG, "Waiting for LOCK -TIMERS- MUTEX 3");\r
   threadLock();\r
+logger->log("Timers", Log::DEBUG, "LOCKED -TIMERS- MUTEX 3");\r
   timerList.push_back(t);\r
+  resetThreadFlag = true;\r
+  threadSignalNoLock();\r
+logger->log("Timers", Log::DEBUG, "about to un-LOCK -TIMERS- MUTEX 3");\r
   threadUnlock();\r
-  threadSignal();\r
 \r
-  logger->log("Timers", Log::DEBUG, "Have set timer for %p ref %i", client, clientReference);\r
+  logger->log("Timers", Log::DEBUG, "Have set timer for %p ref %i", client, clientReference);\r
 \r
   return 1;\r
 }\r
@@ -138,15 +150,21 @@ int Timers::cancelTimer(TimerReceiver* client, int clientReference)
 {\r
   if (!initted) return 0;\r
 \r
+  logger->log("Timers", Log::DEBUG, "Starting cancel timer %p %i, list size = %i", client, clientReference, timerList.size());\r
+\r
+logger->log("Timers", Log::DEBUG, "Waiting for LOCK -TIMERS- MUTEX 4");\r
   threadLock();\r
+logger->log("Timers", Log::DEBUG, "LOCKED -TIMERS- MUTEX 4");\r
   TimerList::iterator i;\r
   Timer* currentTimer = NULL;\r
   for(i = timerList.begin(); i != timerList.end(); i++)\r
   {\r
     currentTimer = *i;\r
+    logger->log("Timers", Log::DEBUG, "I: %p %i : %p %i", client, clientReference, currentTimer->client, currentTimer->clientReference);\r
     if ((currentTimer->client == client) && (currentTimer->clientReference == clientReference))\r
     {\r
       timerList.erase(i);\r
+      logger->log("Timers", Log::DEBUG, "Removed timer for %p ref %i", client, clientReference);\r
       break;\r
       // At this point currentTimer is not in the list but might still be nextTimer in the thread\r
     }\r
@@ -155,17 +173,16 @@ int Timers::cancelTimer(TimerReceiver* client, int clientReference)
   {\r
     // no timer found\r
     logger->log("Timers", Log::DEBUG, "No timer found in cancelTimer %p ref %i", client, clientReference);\r
+logger->log("Timers", Log::DEBUG, "about to un-LOCK -TIMERS- MUTEX 4");\r
     threadUnlock();\r
     return 0;\r
   }\r
 \r
-  // FIXME how to delete a cancelled timer?\r
-  // Just delete it, thread now checks to see if timer is still valid when it wakes up\r
-\r
+  resetThreadFlag = true;\r
+  threadSignalNoLock();\r
+logger->log("Timers", Log::DEBUG, "about to un-LOCK -TIMERS- MUTEX 4");\r
   threadUnlock();\r
-  threadSignal();\r
 \r
-  logger->log("Timers", Log::DEBUG, "Removed timer for %p ref %i", client, clientReference);\r
 \r
   return 1;\r
 }\r
@@ -220,65 +237,113 @@ void Timers::threadMethod()
           }\r
         }\r
       }\r
+    }\r
 \r
-      if (nextTimer)\r
-      {\r
-        threadWaitForSignalTimed(&nextTime); // FIXME does this work if the time is in the past?\r
-        logger->log("Timers", Log::DEBUG, "FIXME CHECK does waitforsignaltimed work for time < now?");\r
+    if (nextTimer)\r
+    {\r
+      logger->log("Timers", Log::DEBUG, "List size: %i. nextTimer: %p. nextTime.tv_sec: %li. nextTime.tv_nsec: %li", timerList.size(), nextTimer, nextTime.tv_sec, nextTime.tv_nsec);\r
 \r
-        // unlocks in the wait\r
-      }\r
-      else\r
-      {\r
-        threadWaitForSignal();\r
-        // unlocks in the wait\r
-      }\r
 \r
-      // ok. we have been signalled or the time has run out\r
-      // This only gets signalled if it is to reset or die\r
+logger->log("Timers", Log::DEBUG, "about to un-LOCK -TIMERS- MUTEX (1)");\r
+      threadWaitForSignalTimed(&nextTime); // FIXME does this work if the time is in the past?\r
+logger->log("Timers", Log::DEBUG, "LOCKED -TIMERS- MUTEX 5");\r
+      logger->log("Timers", Log::DEBUG, "FIXME CHECK does waitforsignaltimed work for time < now?");\r
 \r
-      // First check for die..\r
-      threadCheckExit(); // exiting thread with mutex locked\r
+      // unlocks in the wait\r
+    }\r
+    else\r
+    {\r
+logger->log("Timers", Log::DEBUG, "about to un-LOCK -TIMERS- MUTEX (2)");\r
+      threadWaitForSignal();\r
+logger->log("Timers", Log::DEBUG, "LOCKED -TIMERS- MUTEX 6");\r
+      // unlocks in the wait\r
+    }\r
 \r
-      // Check for reset..\r
-      if (resetThreadFlag) continue;\r
+    // ok. we have been signalled or the time has run out\r
+    // This only gets signalled if it is to reset or die\r
 \r
-      // timer ran out\r
-      // we have the lock, but we didn't in the wait. in case a timer was deleted during the wait,\r
-      // check to see if object nextTimer is still in the list\r
-      // FIXME - actually imlement the above\r
+    // First check for die..\r
+    threadCheckExit(); // exiting thread with mutex locked\r
 \r
-      // Ok. Get the main lock.\r
-      // If we get the main lock, the view can't be deleted before the timer gets there.\r
-      //   (But will need to call Command->postMessageNoLock) to keep the lock\r
-      //   How to run message queue then?\r
-      //   Ah, no need to worry, if it is locked then main thread is waiting on getButtonPress and will\r
-      //   run the queue afterwards anyway\r
-      // If we don't get the lock, lets say the view is deleted while we wait.\r
-      //   As part of its delete process, it will cancel its timer AND CAUSE DEADLOCK. DAMN.\r
+    // Check for reset..\r
+    // This can be caused by an addition or deletion to the list\r
+    if (resetThreadFlag) continue;\r
 \r
+    // timer ran out\r
 \r
-      Log::getInstance()->log("Timers", Log::DEBUG, "Timer firing for client %p ref %i", nextTimer->client, nextTimer->clientReference);\r
+    Log::getInstance()->log("Timers", Log::DEBUG, "Timer firing for client %p ref %i", nextTimer->client, nextTimer->clientReference);\r
 \r
-      // send this timer to the timer receiver somehow\r
-      // possibly give to command message queue\r
+    // send this timer to the timer receiver, via the command message queue\r
+    // so that the gui mutex is locked when it happens\r
 \r
-      Message* m = new Message();\r
-      m->from = this;\r
-      m->to = nextTimer->client;\r
-      m->message = Message::TIMER;\r
-      m->parameter = nextTimer->clientReference;\r
-      Command::getInstance()->postMessage(m);\r
+    Message* m = new Message();\r
+    m->from = this;\r
+    m->to = nextTimer->client;\r
+    m->message = Message::TIMER;\r
+    m->parameter = nextTimer->clientReference;\r
 \r
+    if (!Command::getInstance()->postMessageIfNotBusy(m))\r
+    {\r
+      // GUI mutex was locked\r
+      // abort this timer delivery - it might be trying to be deleted!\r
+      delete m;\r
+\r
+      // now unlock the timers mutex for a fraction of a second\r
+      // in case the gui thread is waiting on the timers mutex\r
+      threadUnlock();\r
+logger->log("Timers", Log::DEBUG, "un-LOCKED -TIMERS- MUTEX (3)");\r
+      printf("\n\n\n WOOOOO \n\n\n The anti deadlock code is working!!! \n\n\n");\r
+      usleep(10000); // 5ms - too long?\r
+logger->log("Timers", Log::DEBUG, "Waiting for LOCK -TIMERS- MUTEX 7");\r
+      threadLock();\r
+logger->log("Timers", Log::DEBUG, "LOCKED -TIMERS- MUTEX 7");\r
+      resetThreadFlag = true;\r
+    }\r
+    else\r
+    {\r
+      // timer was delivered\r
       timerList.remove(nextTimer);\r
       delete nextTimer;\r
       nextTimer = NULL;\r
-\r
       resetThreadFlag = true;\r
     }\r
   }\r
 }\r
 \r
-void Timers::threadPostStopCleanup()\r
-{\r
-}\r
+/*\r
+\r
+Avoiding deadlock using the timer class...\r
+\r
+Situation:\r
+\r
+timer condwait finishes\r
+timers is about to fire a timer\r
+timers locks timers-mutex\r
+\r
+    user presses a button\r
+    command locks gui-mutex\r
+\r
+timers tries to get gui-mutex\r
+\r
+    view receives button\r
+    view wants to delete itself\r
+    view tries to deletetimer\r
+    goes into delete timer\r
+    waits on timers mutex\r
+\r
+- deadlock\r
+\r
+\r
+Solution:\r
+\r
+timers tries to get gui mutex\r
+if mutex is locked already abort\r
+unlock timers mutex\r
+wait a fraction of time\r
+(allow other thread to lock timers mutex)\r
+lock timers mutex\r
+set reset flag to recalculate\r
+- if timer has been cancelled next timer will be calced\r
+- if timer has not been cancelled it will be called next\r
+\r
+*/\r
index 4881e3adb7d48e1a50f896e441e5195ba0ddabfb..3a88b069af00232e994e419b0de929689dd68c83 100755 (executable)
--- a/timers.h
+++ b/timers.h
@@ -61,7 +61,7 @@ class Timers : public Thread
 \r
     // Thread stuff\r
     virtual void threadMethod();\r
-    virtual void threadPostStopCleanup();\r
+    virtual void threadPostStopCleanup() {};\r
 \r
   private:\r
     static Timers* instance;\r
index 83ae18b98aceb6545593fed76a02f8272eae8746..69d2ce009f47c3bb476946be53c18bc8e0862481 100644 (file)
@@ -203,7 +203,7 @@ int VChannelList::handleCommand(int command)
       VVideoLive* v = new VVideoLive(chanList, chan->type);
       v->channelChange(VVideoLive::NUMBER, chan->number);
 
-      ViewMan::getInstance()->addNoLock(v);
+      ViewMan::getInstance()->add(v);
       v->draw();
       v->show();
 
index b487110602a3c51467ec0ac09ece48401cd6a58e..dbcbb4bf9c3b549c3fdb7e6a137178b45cd344a4 100644 (file)
@@ -97,7 +97,9 @@ void VConnect::threadMethod()
       vs->show();
       viewman->add(vs);  // FIXME - do this better - perhaps post message to Command
                          // Otherwise it will be using ViewMan without the Command mutex locked
+      threadLock();
       threadWaitForSignal();
+      threadUnlock();
     }
 
     if (!irun)
diff --git a/vepg.cc b/vepg.cc
index 4bb9fa79fd529c6d6ab691dc0305e1dcb7517698..190a401883f38ced6fae745dae65bcffb4ffbda4 100644 (file)
--- a/vepg.cc
+++ b/vepg.cc
@@ -1,5 +1,5 @@
 /*\r
-    Copyright 2004-2005 Brian Walton\r
+    Copyright 2005 Brian Walton\r
 \r
     This file is part of VOMP.\r
 \r
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
 */\r
 /*\r
-    vepg presents a 2 dimensional electronic programme guide with channels down \r
+    vepg presents a 2 dimensional electronic programme guide with channels down\r
     the y axis and time along the x axis.\r
-    Programmes are layed on the x axis as alterate coloured blocks with as much \r
+    Programmes are layed on the x axis as alterate coloured blocks with as much\r
     of the programme title as will fit inside the block shown as text.\r
-    Up and down commands step through the channels whilst left and right commands \r
+    Up and down commands step through the channels whilst left and right commands\r
     move through the programmes of the currently selected channel.\r
-    When a programme is selected, it highlights in the grid and full programe details \r
+    When a programme is selected, it highlights in the grid and full programe details\r
     (start time, title and description) are displayed in an area at te top left of the screen.\r
     Any currently programmed timers will display in the grid and in the orogramme detail window as red\r
     It is possible to select a programme to be recorded by pressing the record button.\r
     The video stream currently being viewed is shown as quarter screen in the top right.\r
 */\r
-    \r
+\r
 #include "vepg.h"\r
 \r
 VEpg::VEpg(VVideoLive* v, UINT currentChannel)\r
@@ -40,7 +40,7 @@ VEpg::VEpg(VVideoLive* v, UINT currentChannel)
     // initialise array of pointers to eventlist structures\r
     eventLista[listIndex] = NULL;\r
   }\r
-  \r
+\r
 \r
 // Create pallet on which to paint our epg view and position it in centre of screen.\r
 // Need to reduce size to deal with overscanning TVs.\r
@@ -58,7 +58,7 @@ VEpg::VEpg(VVideoLive* v, UINT currentChannel)
     create(512, 384);\r
     setScreenPos(64, 51);\r
   }\r
-  \r
+\r
 // beautify\r
   Colour transparent = Colour(0, 0, 0, 0);\r
   setBackgroundColour(transparent);\r
@@ -155,14 +155,14 @@ void VEpg::draw()
   int keyx = chanListbox.getOffsetX();\r
   int keyy = chanListbox.getOffsetY() + chanListbox.getHeight() + 2;\r
   surface->fillblt(keyx, keyy, 610, Surface::getFontHeight() * 2 + 14, surface->rgba(100, 100, 100, 255));\r
-  \r
+\r
   WSymbol w;\r
   w.setSurface(surface);\r
-  \r
+\r
   w.nextSymbol = WSymbol::LEFTARROW;\r
   w.setSurfaceOffset(keyx + 1, keyy + 20);\r
   w.draw();\r
-  \r
+\r
   w.nextSymbol = WSymbol::UP;\r
   w.setSurfaceOffset(keyx + 26, keyy + 3);\r
   w.draw();\r
@@ -170,38 +170,38 @@ void VEpg::draw()
   w.nextSymbol = WSymbol::DOWN;\r
   w.setSurfaceOffset(keyx + 26, keyy + 36);\r
   w.draw();\r
-  \r
+\r
   w.nextSymbol = WSymbol::RIGHTARROW;\r
   w.setSurfaceOffset(keyx + 50, keyy + 20);\r
   w.draw();\r
-  \r
+\r
   drawText("OK", keyx + 18, keyy + 20, Colour::LIGHTTEXT);\r
-  \r
+\r
   surface->fillblt(keyx + 72, keyy + 4, 104, Surface::getFontHeight() + 2, surface->rgba(200, 0, 0, 255));\r
   drawText("Page up", keyx + 74, keyy + 5, Colour::LIGHTTEXT);\r
-  \r
+\r
   surface->fillblt(keyx + 72, keyy + Surface::getFontHeight() + 8, 104, Surface::getFontHeight() + 2, surface->rgba(0, 200, 0, 255));\r
   drawText("Page down", keyx + 74, keyy + Surface::getFontHeight() + 9, Colour::LIGHTTEXT);\r
-  \r
+\r
   surface->fillblt(keyx + 180, keyy + 4, 104, Surface::getFontHeight() + 2, surface->rgba(200, 200, 0, 255));\r
   drawText("-24 hours", keyx + 182, keyy + 5, Colour::LIGHTTEXT);\r
-  \r
+\r
   surface->fillblt(keyx + 180, keyy + Surface::getFontHeight() + 8, 104, Surface::getFontHeight() + 2, surface->rgba( 0, 0, 200, 255));\r
   drawText("+24 hours", keyx + 182, keyy + Surface::getFontHeight() + 9, Colour::LIGHTTEXT);\r
-  \r
+\r
   surface->fillblt(keyx + 290, keyy + 4, 180, Surface::getFontHeight() + 2, surface->rgba( 180, 180, 180, 255));\r
   drawText("Guide / Back: Close", keyx + 292 , keyy + 5, Colour::LIGHTTEXT);\r
-  \r
+\r
   surface->fillblt(keyx + 290, keyy + Surface::getFontHeight() + 8, 180, Surface::getFontHeight() + 2, surface->rgba( 180, 180, 180, 255));\r
   Colour red = Colour(130, 0, 0);\r
   drawText("Rec: Set timer", keyx + 292, keyy + Surface::getFontHeight() + 9, red);\r
-  \r
+\r
   surface->fillblt(keyx + 474, keyy + 4, 128, Surface::getFontHeight() + 2, surface->rgba( 180, 180, 180, 255));\r
   w.nextSymbol = WSymbol::PLAY;\r
   w.setSurfaceOffset(keyx + 476, keyy + 5);\r
   w.draw();\r
   drawText("Sel channel", keyx + 496, keyy + 5, Colour::LIGHTTEXT);\r
-  \r
+\r
   surface->fillblt(keyx + 474, keyy + Surface::getFontHeight() + 8, 128, Surface::getFontHeight() + 2, surface->rgba( 180, 180, 180, 255));\r
   drawText("Go: Preview", keyx + 476, keyy + Surface::getFontHeight() + 9, Colour::LIGHTTEXT);\r
 }\r
@@ -236,7 +236,7 @@ int VEpg::handleCommand(int command)
     }\r
     case Remote::DF_RIGHT:\r
     case Remote::RIGHT:\r
-    { \r
+    {\r
     // cursor right through time\r
       selTime = thisEvent.time + thisEvent.duration;\r
       draw();\r
@@ -244,7 +244,7 @@ int VEpg::handleCommand(int command)
       return 2;\r
     }\r
     case Remote::RED:\r
-    { \r
+    {\r
     // cursor up one page\r
       chanListbox.pageUp();\r
       draw();\r
@@ -252,7 +252,7 @@ int VEpg::handleCommand(int command)
       return 2;\r
     }\r
     case Remote::GREEN:\r
-    { \r
+    {\r
     // cursor down one page\r
       chanListbox.pageDown();\r
       draw();\r
@@ -260,7 +260,7 @@ int VEpg::handleCommand(int command)
       return 2;\r
     }\r
     case Remote::BLUE:\r
-    { \r
+    {\r
     // step forward 24 hours\r
       selTime += 24 * 60 * 60;\r
       draw();\r
@@ -268,7 +268,7 @@ int VEpg::handleCommand(int command)
       return 2;\r
     }\r
     case Remote::YELLOW:\r
-    { \r
+    {\r
     // step forward 24 hours\r
       selTime -= 24 * 60 * 60;\r
       draw();\r
@@ -370,7 +370,7 @@ void VEpg::drawgrid() // redraws grid and select programme
   surface->fillblt(515, timey + Surface::getFontHeight(), 2, 7, surface->rgba(255, 255, 255, 255));\r
   // pointer to selTime\r
   surface->fillblt(155 + (selTime - ltime) / 20, timey + Surface::getFontHeight(), 2, 7, surface->rgba(255, 50, 50, 255));\r
-  \r
+\r
   // TODO should the above two comditional statements be combined to avoid calling updateEventList() twice?\r
   Event* event;\r
   Event noevent; // an event to use if there are gaps in the epg\r
@@ -406,43 +406,43 @@ void VEpg::drawgrid() // redraws grid and select programme
       sort(eventLista[listIndex]->begin(), eventLista[listIndex]->end(), EventSorter());\r
       for(e = 0; e < (eventLista[listIndex])->size(); e++) // step through events for this channel\r
       {\r
-       fg = Colour::LIGHTTEXT;\r
+  fg = Colour::LIGHTTEXT;\r
         event = (*eventLista[listIndex])[e];\r
-       if (event)\r
-       {\r
-         UINT end = event->time + event->duration; // programme end time\r
-         if(event->time >= UINT(ltime) + (WINDOW_WIDTH * 60)) // programme starts after RHS of window\r
-           continue; // that's enough of this channel's events\r
-         if(end <= UINT(ltime)) // programme ends before LHS of window\r
-           continue; // this event is before the window - let's try the next event\r
-         // this event is one we are interested in\r
-         bg = (swapColour)?Colour::PROGRAMMEA:Colour::PROGRAMMEB; // alternate cell colour\r
-         swapColour = !swapColour; // it wil be the other colour next time\r
-         if(event->time <= UINT(selTime) && end > UINT(selTime) && currentRow)\r
-         {\r
-         // this is the selected programme\r
-           thisEvent.setdescription(event->description);\r
-           thisEvent.duration = event->duration;\r
-           thisEvent.time = event->time;\r
-           thisEvent.settitle(event->title);\r
-           thisEvent.id = event->id;\r
-           if(thisEvent.id == 0)\r
-             thisEvent.id = 1;\r
-           bg = Colour::SELECTHIGHLIGHT; // highlight cell\r
-           fg = Colour::DARKTEXT;\r
-         }\r
-         else\r
-         {\r
-           if (currentRow && thisEvent.id == 0)\r
-           {\r
-             if (end <= UINT(selTime) && end > UINT(thisEvent.time))\r
-               thisEvent.time = end;\r
-             if (event->time > UINT(selTime) && event->time < thisEvent.time + thisEvent.duration)\r
-               thisEvent.duration = event->time - thisEvent.time;\r
-           } \r
-         }\r
-         paintCell(event, y, bg, fg);\r
-       }\r
+  if (event)\r
+  {\r
+    UINT end = event->time + event->duration; // programme end time\r
+    if(event->time >= UINT(ltime) + (WINDOW_WIDTH * 60)) // programme starts after RHS of window\r
+      continue; // that's enough of this channel's events\r
+    if(end <= UINT(ltime)) // programme ends before LHS of window\r
+      continue; // this event is before the window - let's try the next event\r
+    // this event is one we are interested in\r
+    bg = (swapColour)?Colour::PROGRAMMEA:Colour::PROGRAMMEB; // alternate cell colour\r
+    swapColour = !swapColour; // it wil be the other colour next time\r
+    if(event->time <= UINT(selTime) && end > UINT(selTime) && currentRow)\r
+    {\r
+    // this is the selected programme\r
+      thisEvent.setdescription(event->description);\r
+      thisEvent.duration = event->duration;\r
+      thisEvent.time = event->time;\r
+      thisEvent.settitle(event->title);\r
+      thisEvent.id = event->id;\r
+      if(thisEvent.id == 0)\r
+        thisEvent.id = 1;\r
+      bg = Colour::SELECTHIGHLIGHT; // highlight cell\r
+      fg = Colour::DARKTEXT;\r
+    }\r
+    else\r
+    {\r
+      if (currentRow && thisEvent.id == 0)\r
+      {\r
+        if (end <= UINT(selTime) && end > UINT(thisEvent.time))\r
+          thisEvent.time = end;\r
+        if (event->time > UINT(selTime) && event->time < thisEvent.time + thisEvent.duration)\r
+          thisEvent.duration = event->time - thisEvent.time;\r
+      }\r
+    }\r
+    paintCell(event, y, bg, fg);\r
+  }\r
       }\r
     }\r
     else\r
@@ -457,9 +457,9 @@ void VEpg::drawgrid() // redraws grid and select programme
       else\r
       {\r
         bg = Colour::NOPROGRAMME;\r
-       fg = Colour::LIGHTTEXT;\r
+  fg = Colour::LIGHTTEXT;\r
         noevent.settitle("No programme details");\r
-       paintCell(&noevent, y, bg, fg);\r
+  paintCell(&noevent, y, bg, fg);\r
       }\r
     }\r
     y += Surface::getFontHeight() + 1;\r
@@ -467,7 +467,7 @@ void VEpg::drawgrid() // redraws grid and select programme
   setInfo(&thisEvent);\r
 }\r
 \r
-void VEpg::updateEventList() \r
+void VEpg::updateEventList()\r
 {\r
   Channel* chan;\r
   for(UINT listIndex = 0; listIndex < 7; listIndex++)\r
@@ -536,7 +536,7 @@ void VEpg::paintCell(Event* event, int yOffset, Colour bg, Colour fg)
     surface->drawText(tT, x+2, y, fg.red, fg.green, fg.blue);\r
   }\r
   delete tT;\r
-  \r
+\r
 }\r
 \r
 time_t VEpg::prevHour(time_t* t)\r
diff --git a/vepg.h b/vepg.h
index b4e5a0b476378d4b195d2d17a632307341b8d772..d0170150026189d8f7769c82f3c370b5cc921b66 100644 (file)
--- a/vepg.h
+++ b/vepg.h
@@ -1,5 +1,5 @@
 /*\r
-    Copyright 2004-2005 Chris Tallon\r
+    Copyright 2005 Brian Walton\r
 \r
     This file is part of VOMP.\r
 \r
@@ -55,13 +55,13 @@ class VEpg : public View
   private:\r
     void setInfo(Event* event); // display details of selected programme\r
     void drawgrid(); // redraws grid and select programme\r
-    \r
+\r
     WSelectList chanListbox; // listbox to display available channels\r
     WTextbox progTitle; // area to display time and title of selected programme\r
     WTextbox progInfo; // area to display details of selected programme\r
     EventList* eventList; // list of events (programmes) for a channel\r
     Event thisEvent; // the selected event\r
-    time_t selTime; // current selection time \r
+    time_t selTime; // current selection time\r
     UINT e; // temp used to point to an event\r
     ChannelList* chanList; // list of available channels\r
     tm* epgtime; // selected time within epg\r
index c3ccbc8db54afe218a938d6ace3ed912364a9c8f..633a574739f006f343f2893ea96ce4e3e95e7d7e 100644 (file)
@@ -363,7 +363,7 @@ int ViewMan::handleCommand(UCHAR command)
       else if (retVal == 4)
       {
         Log::getInstance()->log("ViewMan", Log::DEBUG, "Return 4: i=%i, views[i]=%p", i, views[i]);
-        removeView(views[i], 1);
+        removeView(views[i]);
         retVal2 = 1;
         break;
       }
@@ -404,7 +404,7 @@ void ViewMan::processMessage(Message* m)
   {
     case Message::CLOSE_ME:
     {
-      removeView((View*)m->from, 1);
+      removeView((View*)m->from);
       break;
     }
     case Message::ADD_VIEW:
index 859dbceb01c6e3dd6cc1175e6695316c99d3ab19..fcef28131233cc3064b05e611391633c07769be9 100644 (file)
--- a/viewman.h
+++ b/viewman.h
@@ -24,7 +24,9 @@
 #include <stdio.h>
 #include <time.h>
 #include <signal.h>
-#include <ext/slist>
+
+// might need <ext/slist> for newer compilers?
+#include <slist>
 
 #include "defines.h"
 #include "view.h"
@@ -35,7 +37,8 @@
 #include "region.h"
 
 //using namespace std;
-using namespace __gnu_cxx;
+
+//using namespace __gnu_cxx; // needed for newer compilers?
 
 typedef slist<Region> RegionList;
 
@@ -50,7 +53,7 @@ class ViewMan : public MessageQueue
     int shutdown();
 
     int add(View* v);
-    int removeView(View* toRemove = NULL);
+    int removeView(View* toRemove);
     void removeAll();
 
     int handleCommand(UCHAR command);
index 2b85d468f89083154582305b3f6da28973b73d61..539b2ada2473f5c8984ff61e9340449191eb6985 100644 (file)
@@ -47,9 +47,6 @@ VLiveBanner::VLiveBanner(View* tparent, Channel* channel, bool bannerTakesComman
   sl.setNoLoop();
 
   setChannel(channel);
-
-  // set a timer for deleting view
-  Timers::getInstance()->setTimer(this, 1, (struct timespec){4, 0});
 }
 
 VLiveBanner::~VLiveBanner()
@@ -133,6 +130,7 @@ int VLiveBanner::handleCommand(int command)
     case Remote::OK:
     case Remote::BACK:
     {
+      Timers::getInstance()->cancelTimer(this, 1); // if it exists
       return 4;
     }
     case Remote::DF_UP:
@@ -161,7 +159,8 @@ int VLiveBanner::handleCommand(int command)
     }
     case Remote::CHANNELUP:
     {
-      ViewMan::getInstance()->timedDelete(this, 0, 0); // cancel timer so this view is still here later
+      // cancel timer so this view is still here later
+      Timers::getInstance()->cancelTimer(this, 1); // if it exists
 
       Message* m = new Message();
       m->from = this;
@@ -172,7 +171,8 @@ int VLiveBanner::handleCommand(int command)
     }
     case Remote::CHANNELDOWN:
     {
-      ViewMan::getInstance()->timedDelete(this, 0, 0);
+      // cancel timer so this view is still here later
+      Timers::getInstance()->cancelTimer(this, 1); // if it exists
 
       Message* m = new Message();
       m->from = this;
@@ -212,7 +212,7 @@ int VLiveBanner::handleCommand(int command)
           }
           vi->create(510, 270);
 
-          ViewMan::getInstance()->addNoLock(vi);
+          ViewMan::getInstance()->add(vi);
           vi->draw();
           vi->show();
 
index c7f2b7bcf3a4e52e708297dd92c08df148e6ffcf..8b5ba14a73f40218d602f564e0459c4e314b8878 100644 (file)
@@ -292,7 +292,7 @@ int VRecordingList::doPlay()
   if (toPlay)
   {
     VVideoRec* vidrec = new VVideoRec(toPlay);
-    ViewMan::getInstance()->addNoLock(vidrec);
+    ViewMan::getInstance()->add(vidrec);
     vidrec->draw();
     vidrec->show();
     vidrec->go(0);
@@ -310,7 +310,7 @@ int VRecordingList::doResume()
     ULLONG position = VDR::getInstance()->getResumePoint(toResume->fileName);
 
     VVideoRec* vidrec = new VVideoRec(toResume);
-    ViewMan::getInstance()->addNoLock(vidrec);
+    ViewMan::getInstance()->add(vidrec);
     vidrec->draw();
     vidrec->show();
     vidrec->go(position);
@@ -386,7 +386,7 @@ int VRecordingList::handleCommand(int command)
         {
           VRecordingList* sub = new VRecordingList(this);
           sub->setDir(curDir);
-          ViewMan::getInstance()->addNoLock(sub);
+          ViewMan::getInstance()->add(sub);
 
           sub->draw();
           sub->show();
@@ -404,7 +404,7 @@ int VRecordingList::handleCommand(int command)
         VRecordingMenu* v = new VRecordingMenu();
         v->setParent(this);
         v->setRecording(current);
-        ViewMan::getInstance()->addNoLock(v);
+        ViewMan::getInstance()->add(v);
         v->draw();
         v->show();
         return 2;
index d7f95d03cbb0203215d42592fba67811e05a0005..3335ac97a63c0530fab9dfb8a407fa37101ed9ea 100644 (file)
@@ -132,7 +132,7 @@ int VRecordingMenu::handleCommand(int command)
         }
         vi->create(490, 300);
 
-        ViewMan::getInstance()->addNoLock(vi);
+        ViewMan::getInstance()->add(vi);
         vi->draw();
         vi->show();
 
@@ -161,7 +161,7 @@ int VRecordingMenu::handleCommand(int command)
           v->setScreenPos(220, 140);
         }
 
-        ViewMan::getInstance()->addNoLock(v);
+        ViewMan::getInstance()->add(v);
         v->draw();
         v->show();
         return 2;
index 3beb8506192d5707ac8cf2cf98702a3a522e4b1f..f96b5bccf07f17edf06ba7492191bf7344c26dbe 100644 (file)
@@ -116,7 +116,7 @@ int VVideoLive::handleCommand(int command)
     case Remote::ZERO ... Remote::NINE:
     {
       VChannelSelect* v = new VChannelSelect(this, command);
-      viewman->addNoLock(v);
+      viewman->add(v);
       v->draw();
       v->show();
     }
@@ -246,7 +246,7 @@ void VVideoLive::showUnavailable(int active)
   else
   {
     unavailable = 0;
-    ViewMan::getInstance()->removeView(unavailableView, 1);
+    ViewMan::getInstance()->removeView(unavailableView);
     unavailableView = NULL;
   }
 }
@@ -274,7 +274,7 @@ void VVideoLive::stop(int noRemoveVLB)
 printf("1\n");
   if (unavailable) return;
 printf("2\n");
-  if (!noRemoveVLB) viewman->removeView(vlb, 1); // if live banner is present, remove it. won't cause damage if its not present
+  if (!noRemoveVLB) viewman->removeView(vlb); // if live banner is present, remove it. won't cause damage if its not present
 printf("3\n");
 
   player->stop();
@@ -317,7 +317,7 @@ void VVideoLive::showEPG()
 {
   if (unavailable) showUnavailable(0);
   vepg = new VEpg(this, currentChannel);
-  ViewMan::getInstance()->addNoLock(vepg);
+  ViewMan::getInstance()->add(vepg);
   Video::getInstance()->setMode(Video::QUARTER);
   Video::getInstance()->setPosition(170, 5); //TODO need to deal with 4:3 switching
   vepg->draw();
index ade1c41e90800a6869582c6c2effaa1e11eb540d..0dd982744bd03dca3815f6229ed7d814c21cfe69 100644 (file)
@@ -192,7 +192,7 @@ void VWelcome::doChannelsList()
     VChannelList* vchan = new VChannelList(VDR::VIDEO);
     vchan->setList(chanList);
 
-    ViewMan::getInstance()->addNoLock(vchan);
+    ViewMan::getInstance()->add(vchan);
     vchan->draw();
     vchan->show();
 
@@ -215,7 +215,7 @@ void VWelcome::doRadioList()
     VChannelList* vchan = new VChannelList(VDR::RADIO);
     vchan->setList(chanList);
 
-    ViewMan::getInstance()->addNoLock(vchan);
+    ViewMan::getInstance()->add(vchan);
     vchan->draw();
     vchan->show();
   }
@@ -238,7 +238,7 @@ void VWelcome::doRecordingsList()
   viewWait->setOneLiner(tr("Downloading recordings list"));
   viewWait->draw();
   viewWait->show();
-  viewman->addNoLock(viewWait);
+  viewman->add(viewWait);
 
 
   VDR* vdr = VDR::getInstance();
@@ -249,21 +249,21 @@ void VWelcome::doRecordingsList()
     VRecordingList* vrec = new VRecordingList(NULL);
     vrec->setDir(recDir);
 
-    ViewMan::getInstance()->addNoLock(vrec);
+    ViewMan::getInstance()->add(vrec);
 
     vrec->draw();
     vrec->show();
   }
 
   Log::getInstance()->log("VWelcome", Log::DEBUG, "possible delay start");
-  viewman->removeView(viewWait, 1);
+  viewman->removeView(viewWait);
   Log::getInstance()->log("VWelcome", Log::DEBUG, "possible delay end");
 }
 
 void VWelcome::doOptions()
 {
   VOptions* voptions = new VOptions();
-  ViewMan::getInstance()->addNoLock(voptions);
+  ViewMan::getInstance()->add(voptions);
   voptions->draw();
   voptions->show();
 }
index d64f5e944c05e3282dee6ba79ad335500ba42002..33fb99dad5ddb41c4aae2519e91dd9d028e2b7a8 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
-    Copyright 2004-2005 Chris Tallon\r
+    Copyright 2005 Brian Walton\r
 \r
     This file is part of VOMP.\r
 \r
index bfbf865577ea3b45a5be9d930077f5df2941ad94..1037d3e5d30a0537065b7ebf4d610223d28091c0 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
-    Copyright 2004-2005 Chris Tallon\r
+    Copyright 2005 Brian Walton\r
 \r
     This file is part of VOMP.\r
 \r