]> git.vomp.tv Git - vompclient.git/commitdiff
New timers system. New program structure for handling buttons/timers
authorChris Tallon <chris@vomp.tv>
Thu, 1 Dec 2005 19:46:43 +0000 (19:46 +0000)
committerChris Tallon <chris@vomp.tv>
Thu, 1 Dec 2005 19:46:43 +0000 (19:46 +0000)
21 files changed:
Makefile
command.cc
command.h
message.h
thread.cc
thread.h
timerreceiver.h [new file with mode: 0755]
timers.cc [new file with mode: 0755]
timers.h [new file with mode: 0755]
vconnect.cc
viewman.cc
viewman.h
vlivebanner.cc
vlivebanner.h
vmute.cc
vmute.h
vrecordingmenu.cc
vvideolive.cc
vvideolive.h
vvolume.cc
vvolume.h

index 0b7c21c23b4a758efe5a143f06e08c1e2eacde45..5757f5a9dd311722de6ddbce331b9168ddbebc76 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -17,7 +17,7 @@ OBJECTS = main.o command.o log.o remote.o led.o mtd.o video.o audio.o tcp.o dire
           view.o vinfo.o vwallpaper.o vvolume.o vrecordinglist.o vlivebanner.o vmute.o \
           vrecordingmenu.o vquestion.o vchannellist.o vwelcome.o vvideolive.o vvideorec.o vradiolive.o \
           vchannelselect.o vserverselect.o colour.o vconnect.o voptions.o vepg.o region.o \
-          widget.o wselectlist.o wjpeg.o wsymbol.o wbutton.o woptionbox.o wtextbox.o i18n.o \
+          widget.o wselectlist.o wjpeg.o wsymbol.o wbutton.o woptionbox.o wtextbox.o i18n.o timers.o \
           fonts/helvB24.o fonts/helvB18.o
 
 .PHONY: clean fresh all install strip
index c43e9127f9be42e3050b8b43a4d0ccd9b1fd40cc..ef4834801daebfaeaa588e65837b9afd07f98ed3 100644 (file)
@@ -56,6 +56,8 @@ int Command::init()
     return 0;
   }
 
+  pthread_mutex_init(&masterLock, NULL);
+
   return 1;
 }
 
@@ -114,6 +116,11 @@ void Command::run()
   wallpaper->show();
   viewman->add(wallpaper);
 
+  // End of startup. Lock the mutex and put the first view up
+
+  pthread_mutex_lock(&masterLock);
+
+
   VConnect* vconnect = new VConnect();
   viewman->add(vconnect);
   vconnect->run();
@@ -122,18 +129,34 @@ void Command::run()
   UCHAR button = 0;
   while(irun)
   {
+    // unlock and wait
+    pthread_mutex_unlock(&masterLock);
+
     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);
+
     if ((button == Remote::NA_NONE) || (button == Remote::NA_UNKNOWN)) continue;
 
     if (button != Remote::NA_SIGNAL) handleCommand(button);
     processMessageQueue();
   }
+
+  pthread_mutex_unlock(&masterLock);
 }
 
 void Command::postMessage(Message* m)
 {
+  // This is locked here in case the main loop is not waiting for an event, but is processing one
+  // it could be killed but then not react to it because the signal wouldn't cause
+  // remote->getButtonPress to break
+  // locking the mutex ensures that the master thread is waiting on getButtonPress
+
+  pthread_mutex_lock(&masterLock);
   MessageQueue::postMessage(m);
   kill(mainPid, SIGURG);
+  pthread_mutex_unlock(&masterLock);
 }
 
 void Command::processMessage(Message* m)
@@ -155,10 +178,10 @@ void Command::processMessage(Message* m)
     case Message::STREAM_END:
     {
       // post a message to ViewMan and then run the viewman message queue
-      Message* m = new Message();
-      m->message = Message::STREAM_END;
-      m->to = VVideoLive::getInstance();
-      viewman->postMessage(m);
+      Message* m2 = new Message();
+      m2->message = Message::STREAM_END;
+      m2->to = VVideoLive::getInstance();
+      viewman->postMessage(m2);
       handleCommand(Remote::NA_NONE);
       break;
     }
@@ -167,6 +190,26 @@ void Command::processMessage(Message* m)
       doJustConnected((VConnect*)m->from);
       break;
     }
+    case Message::TIMER:
+    {
+      // FIXME lock main mutex
+      // FIXME Reply - if messages are being processed then main loop is on processMessageQueue()
+      // -- this means the mutex is locked
+
+      // FIXME investigate whether timer can have fired, but waits on this mutex,
+      // a view is deleted, then the timer runs on a non-object
+
+      // FIXME - go to one message queue only - then instead of having
+      // objects deriving from messagequeues, make them derive from
+      // messagereceiver - then one messagequeue can deliver any message to anywhere
+
+
+      // deliver timer
+      ((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!
+      // FIXME unlock main mutex
+    }
   }
 }
 
@@ -188,7 +231,6 @@ void Command::handleCommand(int button)
       VVolume* v = new VVolume();
       v->handleCommand(button); // this will draw+show
       viewman->add(v);
-      viewman->timedDelete(v, 2, 1);
       return;
     }
     case Remote::MUTE:
@@ -197,7 +239,6 @@ void Command::handleCommand(int button)
       v->draw();
       v->show();
       viewman->add(v);
-      viewman->timedDelete(v, 2, 1);
       return;
     }
     case Remote::POWER:
index 2ce40149365f9dee7f5d00c1fa80d5eab8779893..91526f0af1b06876113f8515667b5ed4b6dac8ac 100644 (file)
--- a/command.h
+++ b/command.h
@@ -26,7 +26,7 @@
 #include <sys/reboot.h>
 
 #include <time.h>
-
+#include <pthread.h>
 #include <signal.h>
 
 #include "defines.h"
@@ -50,6 +50,8 @@
 #include "colour.h"
 #include "osd.h"
 #include "i18n.h"
+#include "timerreceiver.h"
+#include "timers.h"
 
 class VConnect;
 
@@ -74,6 +76,7 @@ class Command : public MessageQueue
 
     static Command* instance;
     pid_t mainPid;
+    pthread_mutex_t masterLock;
     UCHAR initted;
     UCHAR irun;
     UCHAR isStandby;
index 844b1f16be3bf8f447587f18e3787eee9a1b4ab1..873b4bc77cb405d3bb0ff47e3c62f48836f788b7 100644 (file)
--- a/message.h
+++ b/message.h
@@ -41,7 +41,6 @@ class Message
     const static ULONG CLOSE_ME = 2;
     const static ULONG PLAY_SELECTED_RECORDING = 3;
     const static ULONG DELETE_SELECTED_RECORDING = 4;
-    const static ULONG SWAP_ME_FOR = 5;
     const static ULONG CHANNEL_CHANGE = 6;
     const static ULONG RESUME_SELECTED_RECORDING = 7;
     const static ULONG STANDBY = 8;
@@ -55,6 +54,7 @@ class Message
     const static ULONG STREAM_END = 16;
     const static ULONG CHILD_CLOSE = 17;
     const static ULONG REDRAW_LANG = 18;
+    const static ULONG TIMER = 19;
 };
 
 #endif
index 9384858087fa531a7b91900bbc040bb03a6d59dd..d8bb647bef177311a98f96dedd03dafe97c5c2df 100644 (file)
--- a/thread.cc
+++ b/thread.cc
@@ -74,6 +74,16 @@ char Thread::threadIsActive()
   return threadActive;
 }
 
+void Thread::threadLock()
+{
+  pthread_mutex_lock(&threadCondMutex);
+}
+
+void Thread::threadUnlock()
+{
+  pthread_mutex_unlock(&threadCondMutex);
+}
+
 void Thread::threadSignal()
 {
   pthread_mutex_lock(&threadCondMutex);
@@ -93,6 +103,13 @@ void Thread::threadWaitForSignal()
   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()
 {
   pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
index eddaf7141dbec51470ca3f9e727f9933cb5ddd96..965228e240d4e437b49f755300f8a09fcc0eea5f 100644 (file)
--- a/thread.h
+++ b/thread.h
@@ -45,6 +45,9 @@ class Thread
     void threadSetKillable();    // allows threadCancel() to work
     void threadCheckExit();      // terminates thread if threadStop() has been called
     void threadWaitForSignal();  // pauses thread until threadSignal() is called
+    void threadWaitForSignalTimed(struct timespec*);  // pauses thread until threadSignal() is called or timer expires
+    void threadLock();           // locks the mutex used for internal cond/signal stuff
+    void threadUnlock();         // unlocks.
 
     // Internal bits and pieces
 
diff --git a/timerreceiver.h b/timerreceiver.h
new file mode 100755 (executable)
index 0000000..db11b61
--- /dev/null
@@ -0,0 +1,30 @@
+/*\r
+    Copyright 2005 Chris Tallon\r
+\r
+    This file is part of VOMP.\r
+\r
+    VOMP is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    VOMP is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with VOMP; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+*/\r
+\r
+#ifndef TIMERRECEIVER_H\r
+#define TIMERRECEIVER_H\r
+\r
+class TimerReceiver\r
+{\r
+  public:\r
+    virtual void timercall(int clientReference)=0;\r
+};\r
+\r
+#endif\r
diff --git a/timers.cc b/timers.cc
new file mode 100755 (executable)
index 0000000..eea0f89
--- /dev/null
+++ b/timers.cc
@@ -0,0 +1,284 @@
+/*\r
+    Copyright 2004-2005 Chris Tallon\r
+\r
+    This file is part of VOMP.\r
+\r
+    VOMP is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    VOMP is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with VOMP; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+*/\r
+\r
+#include "timers.h"\r
+\r
+Timers* Timers::instance = NULL;\r
+\r
+Timers::Timers()\r
+{\r
+  if (instance) return;\r
+  instance = this;\r
+  initted = false;\r
+}\r
+\r
+Timers::~Timers()\r
+{\r
+  instance = NULL;\r
+}\r
+\r
+Timers* Timers::getInstance()\r
+{\r
+  return instance;\r
+}\r
+\r
+int Timers::init()\r
+{\r
+  if (initted) return 0;\r
+  initted = true;\r
+  logger = Log::getInstance();\r
+\r
+  logger->log("Timers", Log::DEBUG, "Timers init start");\r
+\r
+  threadLock();\r
+  if (!threadStart())\r
+  {\r
+    shutdown();\r
+    return 0;\r
+  }\r
+  threadUnlock();\r
+\r
+  logger->log("Timers", Log::DEBUG, "Timers init end");\r
+\r
+  return 1;\r
+}\r
+\r
+int Timers::shutdown()\r
+{\r
+  if (!initted) return 0;\r
+  initted = false;\r
+\r
+  logger->log("Timers", Log::DEBUG, "Timers shutdown start");\r
+\r
+  threadStop();\r
+\r
+  TimerList::iterator i;\r
+  UINT numTimers = timerList.size();\r
+  while(numTimers)\r
+  {\r
+    i = timerList.begin();\r
+    delete *i;\r
+    timerList.pop_front();\r
+    --numTimers;\r
+  }\r
+\r
+  logger->log("Timers", Log::DEBUG, "Timers shutdown end");\r
+\r
+  return 1;\r
+}\r
+\r
+int Timers::setTimer(TimerReceiver* client, int clientReference, time_t requestedTime)\r
+{\r
+  if (!initted) return 0;\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
+  threadLock();\r
+  timerList.push_back(t);\r
+  threadUnlock();\r
+  threadSignal();\r
+\r
+  logger->log("Timers", Log::DEBUG, "Have set timer for %p ref %i", client, clientReference);\r
+\r
+  return 1;\r
+}\r
+\r
+int Timers::setTimer(TimerReceiver* client, int clientReference, struct timespec duration)\r
+{\r
+  if (!initted) return 0;\r
+\r
+  Timer* t = new Timer();\r
+  t->client = client;\r
+  t->clientReference = clientReference;\r
+\r
+  struct timespec currentTime;\r
+  clock_gettime(CLOCK_REALTIME, &currentTime);\r
+\r
+  t->requestedTime.tv_sec = currentTime.tv_sec + duration.tv_sec;\r
+  t->requestedTime.tv_nsec = currentTime.tv_nsec + duration.tv_nsec;\r
+  if (t->requestedTime.tv_nsec > 999999999)\r
+  {\r
+    ++t->requestedTime.tv_sec;\r
+    t->requestedTime.tv_nsec -= 1000000000;\r
+    logger->log("Timers", Log::DEBUG, "Second rollover - CHECK FIXME");\r
+  }\r
+\r
+  threadLock();\r
+  timerList.push_back(t);\r
+  threadUnlock();\r
+  threadSignal();\r
+\r
+  logger->log("Timers", Log::DEBUG, "Have set timer for %p ref %i", client, clientReference);\r
+\r
+  return 1;\r
+}\r
+\r
+int Timers::cancelTimer(TimerReceiver* client, int clientReference)\r
+{\r
+  if (!initted) return 0;\r
+\r
+  threadLock();\r
+  TimerList::iterator i;\r
+  Timer* currentTimer = NULL;\r
+  for(i = timerList.begin(); i != timerList.end(); i++)\r
+  {\r
+    currentTimer = *i;\r
+    if ((currentTimer->client == client) && (currentTimer->clientReference == clientReference))\r
+    {\r
+      timerList.erase(i);\r
+      break;\r
+      // At this point currentTimer is not in the list but might still be nextTimer in the thread\r
+    }\r
+  }\r
+  if (i == timerList.end())\r
+  {\r
+    // no timer found\r
+    logger->log("Timers", Log::DEBUG, "No timer found in cancelTimer %p ref %i", client, clientReference);\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
+  threadUnlock();\r
+  threadSignal();\r
+\r
+  logger->log("Timers", Log::DEBUG, "Removed timer for %p ref %i", client, clientReference);\r
+\r
+  return 1;\r
+}\r
+\r
+void Timers::threadMethod()\r
+{\r
+  struct timespec nextTime;\r
+  Timer* nextTimer = NULL;\r
+  resetThreadFlag = true;\r
+\r
+  // locked here\r
+\r
+  while(1)\r
+  {\r
+    if (resetThreadFlag)\r
+    {\r
+      resetThreadFlag = false;\r
+\r
+      // Work out the next Timer\r
+\r
+      nextTime.tv_sec = 0;\r
+      nextTime.tv_nsec = 0;\r
+      nextTimer = NULL;\r
+\r
+      TimerList::iterator i;\r
+      Timer* currentTimer = NULL;\r
+      for(i = timerList.begin(); i != timerList.end(); i++)\r
+      {\r
+        currentTimer = *i;\r
+        if (!nextTimer)\r
+        {\r
+          nextTime.tv_sec = currentTimer->requestedTime.tv_sec;\r
+          nextTime.tv_nsec = currentTimer->requestedTime.tv_nsec;\r
+          nextTimer = currentTimer;\r
+        }\r
+        else\r
+        {\r
+          if (currentTimer->requestedTime.tv_sec < nextTime.tv_sec)\r
+          {\r
+            nextTime.tv_sec = currentTimer->requestedTime.tv_sec;\r
+            nextTime.tv_nsec = currentTimer->requestedTime.tv_nsec;\r
+            nextTimer = currentTimer;\r
+          }\r
+          else if (currentTimer->requestedTime.tv_sec == nextTime.tv_sec)\r
+          {\r
+            if (currentTimer->requestedTime.tv_nsec < nextTime.tv_nsec)\r
+            {\r
+              nextTime.tv_sec = currentTimer->requestedTime.tv_sec;\r
+              nextTime.tv_nsec = currentTimer->requestedTime.tv_nsec;\r
+              nextTimer = currentTimer;\r
+            }\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
+\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
+\r
+      // First check for die..\r
+      threadCheckExit(); // exiting thread with mutex locked\r
+\r
+      // Check for reset..\r
+      if (resetThreadFlag) continue;\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
+\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
+\r
+\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
+\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
+\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
diff --git a/timers.h b/timers.h
new file mode 100755 (executable)
index 0000000..4881e3a
--- /dev/null
+++ b/timers.h
@@ -0,0 +1,74 @@
+/*\r
+    Copyright 2004-2005 Chris Tallon\r
+\r
+    This file is part of VOMP.\r
+\r
+    VOMP is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    VOMP is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with VOMP; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+*/\r
+\r
+#ifndef TIMERS_H\r
+#define TIMERS_H\r
+\r
+#include <stdio.h>\r
+#include <pthread.h>\r
+#include <list>\r
+\r
+#include "defines.h"\r
+#include "log.h"\r
+#include "thread.h"\r
+#include "command.h"\r
+#include "timerreceiver.h"\r
+\r
+class Timer\r
+{\r
+  public:\r
+    TimerReceiver* client;\r
+    int clientReference;\r
+    struct timespec requestedTime;\r
+};\r
+\r
+using namespace std;\r
+//using namespace __gnu_cxx;\r
+typedef list<Timer*> TimerList;\r
+\r
+class Timers : public Thread\r
+{\r
+  public:\r
+    Timers();\r
+    virtual ~Timers();\r
+    static Timers* getInstance();\r
+\r
+    int init();\r
+    int shutdown();\r
+\r
+    // FIXME - ensure all objects that call settimer call cancel timer if they are being deleted\r
+\r
+    int setTimer(TimerReceiver* client, int clientReference, time_t requestedTime);\r
+    int setTimer(TimerReceiver* client, int clientReference, timespec duration);\r
+    int cancelTimer(TimerReceiver* client, int clientReference);\r
+\r
+    // Thread stuff\r
+    virtual void threadMethod();\r
+    virtual void threadPostStopCleanup();\r
+\r
+  private:\r
+    static Timers* instance;\r
+    Log* logger;\r
+    bool initted;\r
+    TimerList timerList;\r
+    bool resetThreadFlag;\r
+};\r
+\r
+#endif\r
index d4480bd67d701fa0a373adcd95ecaaf5b9bd3150..b487110602a3c51467ec0ac09ece48401cd6a58e 100644 (file)
@@ -95,7 +95,8 @@ void VConnect::threadMethod()
       vs->setParent(this);
       vs->draw();
       vs->show();
-      viewman->add(vs);
+      viewman->add(vs);  // FIXME - do this better - perhaps post message to Command
+                         // Otherwise it will be using ViewMan without the Command mutex locked
       threadWaitForSignal();
     }
 
index c10a8fdc4d57d9496635233f2927fcf92aca2daf..c3ccbc8db54afe218a938d6ace3ed912364a9c8f 100644 (file)
@@ -28,9 +28,6 @@ ViewMan::ViewMan()
   instance = this;
   initted = 0;
   numViews = 0;
-  resetThreadFlag = 0;
-  autoDeleteThreadRun = 0;
-  callFromThread = 0;
 }
 
 ViewMan::~ViewMan()
@@ -46,9 +43,6 @@ ViewMan* ViewMan::getInstance()
 int ViewMan::init()
 {
   if (initted) return 0;
-  pthread_mutex_init(&viewManLock, NULL);
-  pthread_cond_init(&autoDeleteThreadSignal, NULL);
-  if (!startAutoDeleteThread()) return 0;
   initted = 1;
   return 1;
 }
@@ -60,12 +54,6 @@ int ViewMan::shutdown()
   // FIXME don't think this can work properly, removeAll leaves the wallpaper there!
   removeAll();
 
-  // get the lock here to ensure that the thread is waiting on the cond
-  pthread_mutex_lock(&viewManLock);
-  autoDeleteThreadRun = 0;
-  pthread_cond_signal(&autoDeleteThreadSignal);
-  pthread_mutex_unlock(&viewManLock);
-  pthread_join(autoDeleteThread, NULL);
   initted = 0;
   return 1;
 }
@@ -73,40 +61,20 @@ int ViewMan::shutdown()
 int ViewMan::add(View* v)
 {
   if (!initted) return 0;
-  if (numViews == 20) return 0;
-
-  pthread_mutex_lock(&viewManLock);
+  if (numViews == 16) return 0;
 
   views[numViews++] = v;
 
-  resetThread();
-  pthread_mutex_unlock(&viewManLock);
-
-  return 1;
-}
-
-int ViewMan::addNoLock(View* v)
-{
-  if (!initted) return 0;
-  if (numViews == 20) return 0;
-
-  views[numViews++] = v;
-
-  resetThread();
-
   return 1;
 }
 
-
 // ---------------------------------------------------- REMOVE CODE
 
-int ViewMan::removeView(View* toDelete, int noLock)
+int ViewMan::removeView(View* toDelete)
 {
   if (!initted) return 0;
   if (numViews == 0) return 0;
 
-  if (!noLock) pthread_mutex_lock(&viewManLock);
-
   Log::getInstance()->log("ViewMan", Log::DEBUG, "entering remove, numViews=%i", numViews);
 
   int i;
@@ -128,7 +96,6 @@ int ViewMan::removeView(View* toDelete, int noLock)
     if (i == -1)
     {
       // not a View we have!
-      if (!noLock) pthread_mutex_unlock(&viewManLock);
       return 0;
     }
   }
@@ -144,9 +111,6 @@ int ViewMan::removeView(View* toDelete, int noLock)
   // Delete the view
   delete toDelete;
 
-  resetThread();
-  if (!noLock) pthread_mutex_unlock(&viewManLock);
-
   return 1;
 }
 
@@ -359,22 +323,15 @@ void ViewMan::drawBlack(Region& r)
 
 void ViewMan::removeAll()
 {
-  pthread_mutex_lock(&viewManLock);
-
   // 1.. Don't delete wallpaper. No point.
   for (; numViews > 1; --numViews)
   {
     delete views[numViews-1];
   }
-
-  resetThread();
-  pthread_mutex_unlock(&viewManLock);
 }
 
 int ViewMan::handleCommand(UCHAR command)
 {
-  pthread_mutex_lock(&viewManLock);
-
   int retVal;
   int retVal2 = 0;
   int i;
@@ -394,33 +351,19 @@ int ViewMan::handleCommand(UCHAR command)
       if (retVal == 1)
       {
         // not handled but don't give to any more views
-        pthread_mutex_unlock(&viewManLock);
         return 0;
       }
 
       if (retVal == 2)
       {
         // command handled
-        if (views[i]->seconds)
-        {
-          struct timespec currentTime;
-          clock_gettime(CLOCK_REALTIME, &currentTime);
-          views[i]->delSec = currentTime.tv_sec + views[i]->seconds;
-          views[i]->delNSec = currentTime.tv_nsec;
-          resetThread();
-        }
-        pthread_mutex_unlock(&viewManLock);
         retVal2 = 1;
         break;
       }
       else if (retVal == 4)
       {
-  //      removeNoLock(views[i]);
-  //      Box::showAll();
-  //      resetThread();
         Log::getInstance()->log("ViewMan", Log::DEBUG, "Return 4: i=%i, views[i]=%p", i, views[i]);
         removeView(views[i], 1);
-        pthread_mutex_unlock(&viewManLock);
         retVal2 = 1;
         break;
       }
@@ -436,7 +379,6 @@ int ViewMan::handleCommand(UCHAR command)
 
   processMessageQueue();
 
-  pthread_mutex_unlock(&viewManLock);
   return retVal2;
 }
 
@@ -465,182 +407,12 @@ void ViewMan::processMessage(Message* m)
       removeView((View*)m->from, 1);
       break;
     }
-    case Message::SWAP_ME_FOR:
-    {
-      View* toReplace = (View*) m->parameter;
-
-      removeView((View*)m->from, 1);
-
-      views[numViews] = toReplace;
-      ++numViews;
-      if (toReplace->seconds)
-      {
-        struct timespec currentTime;
-        clock_gettime(CLOCK_REALTIME, &currentTime);
-        toReplace->delSec = currentTime.tv_sec + toReplace->seconds;
-        toReplace->delNSec = currentTime.tv_nsec;
-      }
-      toReplace->draw();
-      toReplace->show();
-      resetThread();
-      break;
-    }
     case Message::ADD_VIEW:
     {
       View* toAdd = (View*)m->parameter;
-      addNoLock(toAdd);
+      add(toAdd);
       toAdd->draw();
       toAdd->show();
     }
   }
 }
-
-int ViewMan::timedDelete(View* v, int seconds, int lockMutex)
-{
-  int success;
-
-  if (lockMutex) pthread_mutex_lock(&viewManLock);
-
-  struct timespec currentTime;
-  clock_gettime(CLOCK_REALTIME, &currentTime);
-
-  if (v)
-  {
-    if (seconds)
-    {
-      v->seconds = seconds;
-      v->delSec = currentTime.tv_sec + seconds;
-      v->delNSec = currentTime.tv_nsec;
-    }
-    else
-    {
-      // for cancelling the delete
-      v->seconds = 0;
-      v->delSec = 0;
-      v->delNSec = 0;
-    }
-    success = 1;
-  }
-  else
-  {
-    success = 0;
-  }
-
-  resetThread();
-  if (lockMutex) pthread_mutex_unlock(&viewManLock);
-
-  return success;
-}
-
-
-// THE THREAD CODE STARTS HERE /////////////////////////////////////////////////////////////
-
-void ViewMan::resetThread()
-{
-  // must be called with mutex already locked
-  resetThreadFlag = 1;
-  pthread_cond_signal(&autoDeleteThreadSignal);
-}
-
-// undeclared function
-void startAutoDeleteThread2(void *arg)
-{
-  ViewMan *v = (ViewMan *)arg;
-  v->startAutoDeleteThread3();
-}
-int ViewMan::startAutoDeleteThread()
-{
-  pthread_mutex_lock(&viewManLock);
-  resetThreadFlag = 1;
-  autoDeleteThreadRun = 1;
-  if (pthread_create(&autoDeleteThread, NULL, (void*(*)(void*))startAutoDeleteThread2, (void *)this) == -1) return 0;
-  return 1;
-}
-
-void ViewMan::startAutoDeleteThread3()
-{
-  struct timespec nextTime;
-  View* nextToDelete = NULL;
-
-  // I don't want signals
-  sigset_t sigs;
-  sigfillset(&sigs);
-  pthread_sigmask(SIG_BLOCK, &sigs, NULL);
-
-  // locked here
-
-  while(1)
-  {
-    if (resetThreadFlag)
-    {
-      resetThreadFlag = 0;
-
-      // Work out the next View to be deleted
-
-      nextTime.tv_sec = 0;
-      nextTime.tv_nsec = 0;
-      nextToDelete = NULL;
-
-      for(int i = 0; i < numViews; i++)
-      {
-        if ((views[i]->delSec > 0) && (views[i]->delNSec > 0))
-        {
-          if ((nextTime.tv_sec == 0) && (nextTime.tv_nsec == 0))
-          {
-            nextTime.tv_sec = views[i]->delSec;
-            nextTime.tv_nsec = views[i]->delNSec;
-            nextToDelete = views[i];
-          }
-          else
-          {
-            if (views[i]->delSec < nextTime.tv_sec)
-            {
-              nextTime.tv_sec = views[i]->delSec;
-              nextTime.tv_nsec = views[i]->delNSec;
-              nextToDelete = views[i];
-            }
-            else if (views[i]->delSec == nextTime.tv_sec)
-            {
-              if (views[i]->delNSec < nextTime.tv_nsec)
-              {
-                nextTime.tv_sec = views[i]->delNSec;
-                nextTime.tv_nsec = views[i]->delNSec;
-                nextToDelete = views[i];
-              }
-            }
-          }
-        }
-        // no case
-      }
-      // end
-    }
-
-    if (nextTime.tv_sec == 0)
-    {
-      pthread_cond_wait(&autoDeleteThreadSignal, &viewManLock);
-    }
-    else
-    {
-      pthread_cond_timedwait(&autoDeleteThreadSignal, &viewManLock, &nextTime);
-    }
-
-    // ok. we have been signalled or the time has run out
-
-    // see if we have been signalled. we only get signalled if we
-    // are to reset the timer or if we are to die completely
-    if (!autoDeleteThreadRun)
-    {
-      pthread_exit(NULL);
-      // exiting thread with mutex locked
-    }
-
-    if (resetThreadFlag) continue;
-
-    // timer ran out
-    Log::getInstance()->log("ViewMan", Log::DEBUG, "AutoDel: About to remove %p", nextToDelete);
-    removeView(nextToDelete, 1);  // enter this method with mutex locked
-
-    resetThreadFlag = 1;
-  }
-}
-
index 83994457ea07eff8afb47068d1348f70578797f4..859dbceb01c6e3dd6cc1175e6695316c99d3ab19 100644 (file)
--- a/viewman.h
+++ b/viewman.h
@@ -24,8 +24,7 @@
 #include <stdio.h>
 #include <time.h>
 #include <signal.h>
-#include <pthread.h>
-#include <slist>
+#include <ext/slist>
 
 #include "defines.h"
 #include "view.h"
@@ -35,6 +34,9 @@
 #include "surface.h"
 #include "region.h"
 
+//using namespace std;
+using namespace __gnu_cxx;
+
 typedef slist<Region> RegionList;
 
 class ViewMan : public MessageQueue
@@ -47,17 +49,11 @@ class ViewMan : public MessageQueue
     int init();
     int shutdown();
 
-    // All these reset the thread
     int add(View* v);
-    int addNoLock(View* v);
-    int removeView(View* toRemove = NULL, int noLock = 0);
+    int removeView(View* toRemove = NULL);
     void removeAll();
 
     int handleCommand(UCHAR command);
-    int timedDelete(View* v, int seconds, int lock);
-
-    // not for external use
-    void startAutoDeleteThread3();
 
   private:
     static ViewMan* instance;
@@ -66,17 +62,6 @@ class ViewMan : public MessageQueue
     View* views[20];
     int numViews;
 
-    // Threading stuff
-
-    int startAutoDeleteThread();
-    pthread_mutex_t viewManLock;
-    pthread_t autoDeleteThread;
-    pthread_cond_t autoDeleteThreadSignal;
-    int resetThreadFlag;
-    int autoDeleteThreadRun;
-    int callFromThread;
-    void resetThread();
-
     void processMessage(Message* m);
 
     // New windowing stuff
index 3d3639e3272ba5ba8c6510e6af6b944c6cc6a1dd..2b85d468f89083154582305b3f6da28973b73d61 100644 (file)
@@ -47,6 +47,9 @@ 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()
@@ -108,7 +111,8 @@ void VLiveBanner::setChannel(Channel* tChannel)
     }
 
     // Reset the timer as it probably took 1-2 seconds to change the channel
-    ViewMan::getInstance()->timedDelete(this, 4, 0);
+    Timers::getInstance()->cancelTimer(this, 1); // if it exists
+    Timers::getInstance()->setTimer(this, 1, (struct timespec){4, 0});
   }
 }
 
@@ -190,7 +194,7 @@ int VLiveBanner::handleCommand(int command)
         {
           Log::getInstance()->log("VLiveBanner", Log::DEBUG, "Found the option you pointed at. %s", event->title);
           // First, cancel my delete timer
-          ViewMan::getInstance()->timedDelete(this, 0, 0);
+          Timers::getInstance()->cancelTimer(this, 1); // if it exists
 
           VInfo* vi = new VInfo();
           vi->setTitleText(event->title);
@@ -222,3 +226,13 @@ int VLiveBanner::handleCommand(int command)
 
   return 1;
 }
+
+void VLiveBanner::timercall(int clientReference)
+{
+  // delete me!
+  Message* m = new Message();
+  m->message = Message::CLOSE_ME;
+  m->to = ViewMan::getInstance();
+  m->from = this;
+  ViewMan::getInstance()->postMessage(m);
+}
index d719f26de61f2395c532b3f03fa700d7885cab53..fe3620709d8dc6d272c472e183f8d68e255ac0a5 100644 (file)
 #include "vinfo.h"
 #include "viewman.h"
 #include "i18n.h"
+#include "timerreceiver.h"
+#include "timers.h"
 
-class VLiveBanner : public View
+class VLiveBanner : public View, public TimerReceiver
 {
   public:
     VLiveBanner(View* parent, Channel* channel, bool bannerTakesCommands);
@@ -48,6 +50,7 @@ class VLiveBanner : public View
 
     int handleCommand(int command);
     void draw();
+    void timercall(int clientReference);
 
   private:
     View* parent;
index f7eb1a36452b8ba66b494d1057868f0bf5b3c5e8..c7fee0c81ea3dc7054609da2a9482c1387730e35 100644 (file)
--- a/vmute.cc
+++ b/vmute.cc
@@ -47,6 +47,19 @@ void VMute::draw()
   else w.nextSymbol = WSymbol::UNMUTE;
   w.setSurfaceOffset(5, 5);
   w.draw();
+
+  Timers::getInstance()->cancelTimer(this, 1); // if it exists
+  Timers::getInstance()->setTimer(this, 1, (struct timespec){2, 0});
+}
+
+void VMute::timercall(int clientReference)
+{
+  // delete me!
+  Message* m = new Message();
+  m->message = Message::CLOSE_ME;
+  m->to = ViewMan::getInstance();
+  m->from = this;
+  ViewMan::getInstance()->postMessage(m);
 }
 
 int VMute::handleCommand(int command)
diff --git a/vmute.h b/vmute.h
index fb393b467da726ed5f3fa43d1a36f0158fc040ff..263729dc517fec349ee6284bf24647159ec2c81d 100644 (file)
--- a/vmute.h
+++ b/vmute.h
 #include "wsymbol.h"
 #include "colour.h"
 #include "video.h"
+#include "timerreceiver.h"
+#include "timers.h"
+#include "viewman.h"
 
-class VMute : public View
+class VMute : public View, public TimerReceiver
 {
   public:
     VMute();
     void draw();
     int handleCommand(int command);
+    void timercall(int clientReference);
 
   private:
     int isMuted;
index 6f6460241e09457cb88ad44dc8a1c04c2425b614..d7f95d03cbb0203215d42592fba67811e05a0005 100644 (file)
@@ -182,17 +182,17 @@ void VRecordingMenu::processMessage(Message* m)
   {
     if (sl.getCurrentOption() == 3)
     {
-      Message* m = new Message();
-      m->from = this;
-      m->to = ViewMan::getInstance();
-      m->message = Message::CLOSE_ME;
-      ViewMan::getInstance()->postMessage(m);
-
-      m = new Message();
-      m->from = this;
-      m->to = vRecList;
-      m->message = Message::DELETE_SELECTED_RECORDING;
-      ViewMan::getInstance()->postMessage(m);
+      Message* m2 = new Message();
+      m2->from = this;
+      m2->to = ViewMan::getInstance();
+      m2->message = Message::CLOSE_ME;
+      ViewMan::getInstance()->postMessage(m2);
+
+      m2 = new Message();
+      m2->from = this;
+      m2->to = vRecList;
+      m2->message = Message::DELETE_SELECTED_RECORDING;
+      ViewMan::getInstance()->postMessage(m2);
     }
   }
 }
index 95694dc385a2889d2e033e8722b89dfa6604b417..3beb8506192d5707ac8cf2cf98702a3a522e4b1f 100644 (file)
@@ -117,7 +117,6 @@ int VVideoLive::handleCommand(int command)
     {
       VChannelSelect* v = new VChannelSelect(this, command);
       viewman->addNoLock(v);
-//      ViewMan::getInstance()->timedDelete(v, 4, 0);
       v->draw();
       v->show();
     }
@@ -204,7 +203,6 @@ void VVideoLive::doBanner(bool bannerTakesCommands)
   if(epgmode)
     return;
   vlb = new VLiveBanner(this, (*chanList)[currentChannel], bannerTakesCommands);
-  viewman->timedDelete(vlb, 4, 0);
 
   Message* m = new Message();
   m->from = this;
index 60e7e738ef238f08e132ab71777bb08d095b2292..ae6e51efdcddf8733ddd75e059ccd02350ed06b3 100644 (file)
@@ -42,6 +42,8 @@
 
 class VEpg;
 
+class VLiveBanner;
+
 class VVideoLive : public View
 {
   public:
index 4f8af9fbac5c99167fd81d39669f5b77c27a7071..b9de8cbcc01ed519ece030e0357644459e4d2617 100644 (file)
@@ -62,6 +62,19 @@ void VVolume::draw()
     w.setSurfaceOffset(40 + (i * 9), 13);
     w.draw();
   }
+
+  Timers::getInstance()->cancelTimer(this, 1); // if it exists
+  Timers::getInstance()->setTimer(this, 1, (struct timespec){2, 0});
+}
+
+void VVolume::timercall(int clientReference)
+{
+  // delete me!
+  Message* m = new Message();
+  m->message = Message::CLOSE_ME;
+  m->to = ViewMan::getInstance();
+  m->from = this;
+  ViewMan::getInstance()->postMessage(m);
 }
 
 int VVolume::handleCommand(int command)
index 893b0d0050285752474a5e11f241cd2274524820..a7915b9d22310b7df06aaa850caedb990d6f043a 100644 (file)
--- a/vvolume.h
+++ b/vvolume.h
 #include "wsymbol.h"
 #include "colour.h"
 #include "video.h"
+#include "timerreceiver.h"
+#include "timers.h"
+#include "viewman.h"
 
-class VVolume : public View
+class VVolume : public View, public TimerReceiver
 {
   public:
     VVolume();
     void draw();
     int handleCommand(int command);
+    void timercall(int clientReference);
 
   private:
     int displayCommand;