]> git.vomp.tv Git - vompclient.git/commitdiff
New timers method
authorChris Tallon <chris@vomp.tv>
Sun, 4 Mar 2007 01:26:31 +0000 (01:26 +0000)
committerChris Tallon <chris@vomp.tv>
Sun, 4 Mar 2007 01:26:31 +0000 (01:26 +0000)
16 files changed:
command.cc
message.h
threadp.cc
threadp.h
ticonfig.c
timers.cc
timers.h
vchannelselect.cc
viewman.cc
vlivebanner.cc
vmute.cc
vradiorec.cc
vtimerlist.cc
vvideorec.cc
vvolume.cc
vwelcome.cc

index 1ab1417793019019fdbad724954e618419ccba51..b6f0977673c9b48591c94260f7db85c568eba3b9 100644 (file)
@@ -214,9 +214,8 @@ void Command::postMessageNoLock(Message* m)
 
 bool Command::postMessageIfNotBusy(Message* m)
 {
-  // This is for the timers module
-  // If the masterlock is locked then the timers module wants to
-  // cancel delivery
+  // Used for Windows mouse events
+
   //logger->log("Command", Log::DEBUG, "TRY LOCK");
 #ifndef WIN32
   if (pthread_mutex_trylock(&masterLock) != EBUSY)
@@ -295,28 +294,14 @@ void Command::postMessageFromOuterSpace(Message* m)
 
 void Command::processMessage(Message* m)
 {
-  logger->log("Command", Log::DEBUG, "processing message %i", m->message);
-
-  // Timer handling is very weird at the mo. Take them out here and convert
-  if (m->message == Message::TIMER)
-  {
-    // 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
-
     // FIXME - a slight modification - how if messagereceivers were to register
     // themselves as receivers to avoid the calling-a-deleted-object problem
     // then only deliver/register/unregister would have to be protected
 
-    // deliver timer
+  logger->log("Command", Log::DEBUG, "processing message %i", m->message);
+
 
-    logger->log("Command", Log::DEBUG, "sending timer to %p with parameter %u", m->to, 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!
-//    break;
-  }
-  else if (m->to == this)
+  if (m->to == this)
   {
     switch(m->message)
     {
@@ -790,9 +775,9 @@ void Command::doJustConnected(VConnect* vconnect)
     viewman->updateView(vw);
 
     // Enter pre-keys here
-//    handleCommand(Remote::THREE);
-//    handleCommand(Remote::UP);
-//    handleCommand(Remote::PLAY);
+    handleCommand(Remote::THREE);
+    handleCommand(Remote::UP);
+    handleCommand(Remote::PLAY);
 //    handleCommand(Remote::DOWN);
 //    handleCommand(Remote::DOWN);
 //    handleCommand(Remote::DOWN);
index 146c89959202e4f9465ff4432ae9a8073f596836..0c7b70173a5969be3e32966089b5c1f30a8a9d8d 100644 (file)
--- a/message.h
+++ b/message.h
@@ -57,7 +57,7 @@ class Message
     const static ULONG ADD_VIEW = 12;
     const static ULONG STREAM_END = 13;
     const static ULONG REDRAW_LANG = 14;
-    const static ULONG TIMER = 15;
+    const static ULONG REDRAW = 15;
     const static ULONG EPG = 16;
     const static ULONG EPG_CLOSE = 17;
     const static ULONG CHANGED_OPTIONS = 18;
index 019c54df1f6b18a28b1c251ca2d14a200ba0b6d2..f97fb8f28f782bd89c8a80cf8e80b4b863e2c90c 100644 (file)
@@ -101,3 +101,18 @@ void ThreadP::threadSetKillable()
   pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
   pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
 }
+
+void ThreadP::threadSuicide()
+{
+  if(!pthread_detach(pthread_self()))
+  {
+    MILLISLEEP(1000);
+    if(!pthread_detach(pthread_self()))
+    {
+      MILLISLEEP(1000);
+      pthread_detach(pthread_self());
+    }
+  }
+
+  pthread_exit(NULL);
+}
index 5461f869af126da0ecaae7507349af3d461a3f24..419a93ee862dc4b13e9f49e61aabd54605776edf 100644 (file)
--- a/threadp.h
+++ b/threadp.h
@@ -24,6 +24,7 @@
 #include <pthread.h>
 #include <signal.h>
 
+#include "defines.h"
 #include "thread.h"
 
 class ThreadP : public Thread
@@ -54,6 +55,9 @@ class ThreadP : public Thread
     pthread_t pthread;
     pthread_cond_t threadCond;
     pthread_mutex_t threadCondMutex;
+
+  public:
+    static void threadSuicide();        // Self termination
 };
 
 #endif
index 8c9e0e2063b13f00ac4b43fafefab1b9d6efcbd8..deb8296e03ae84983f9c5be7d66d6001160cef2f 100644 (file)
@@ -1,4 +1,4 @@
-/* Adapted for vomp by Chris Tallon by changing "int main" to "int ticonfig_main"
+// Adapted for vomp by Chris Tallon by changing "int main" to "int ticonfig_main"
 
 /*
  *  Copyright (C) 2006, Jon Gettler
index b6674df3479585c50d6d0f78c20bcd13ea5f0f29..9c491ccb87f21e3dc5312af104358619fd25a57f 100755 (executable)
--- a/timers.cc
+++ b/timers.cc
@@ -1,5 +1,5 @@
 /*
-    Copyright 2004-2005 Chris Tallon
+    Copyright 2004-2007 Chris Tallon
 
     This file is part of VOMP.
 
@@ -46,7 +46,6 @@ int Timers::init()
   logger = Log::getInstance();
 
   threadLock(); // lock here, the thread loop will unlock and wait
-  //logger->log("Timers", Log::DEBUG, "LOCKED -TIMERS- MUTEX 1");
   if (!threadStart())
   {
     shutdown();
@@ -65,14 +64,19 @@ int Timers::shutdown()
 
   threadStop();
 
-  TimerList::iterator i;
-  UINT numTimers = timerList.size();
-  while(numTimers)
+  TimerEvent* timerEvent = NULL;
+  TimerReceiver* client = NULL;
+  int clientReference = 0;
+
+  while(timerList.size())
   {
-    i = timerList.begin();
-    delete *i;
-    timerList.pop_front();
-    --numTimers;
+    threadLock();
+    timerEvent = timerList.front();
+    client = timerEvent->client;
+    clientReference = timerEvent->clientReference;
+    threadUnlock();
+
+    cancelTimer(client, clientReference);
   }
 
   logger->log("Timers", Log::DEBUG, "Timers shutdown end");
@@ -80,7 +84,7 @@ int Timers::shutdown()
   return 1;
 }
 
-int Timers::setTimerT(TimerReceiver* client, int clientReference, long int requestedTime, long int requestedTimeNSEC)
+bool Timers::setTimerT(TimerReceiver* client, int clientReference, long int requestedTime, long int requestedTimeNSEC)
 {
   if (!initted) return 0;
 
@@ -91,25 +95,41 @@ int Timers::setTimerT(TimerReceiver* client, int clientReference, long int reque
 
   // Check that this timer is not already in the list
   TimerList::iterator i;
-  Timer* currentTimer = NULL;
+  TimerEvent* currentTimerEvent = NULL;
   for(i = timerList.begin(); i != timerList.end(); i++)
   {
-    currentTimer = *i;
-    if ((currentTimer->client == client) && (currentTimer->clientReference == clientReference))
+    currentTimerEvent = *i;
+
+    if ((currentTimerEvent->client == client) && (currentTimerEvent->clientReference == clientReference))
     {
-      // Overwrite an existing timer
-      currentTimer->requestedTime.tv_sec = requestedTime;
-      currentTimer->requestedTime.tv_nsec = requestedTimeNSEC;
-      resetThreadFlag = true;
-      threadSignalNoLock();
+      // Timer exists already, either waiting or running
+      // Update the clocks
+      currentTimerEvent->requestedTime.tv_sec = requestedTime;
+      currentTimerEvent->requestedTime.tv_nsec = requestedTimeNSEC;
 
-      //logger->log("Timers", Log::DEBUG, "about to un-LOCK -TIMERS- MUTEX 2 (b)");
-      threadUnlock();
-      return 0;
+      if (currentTimerEvent->running)
+      {
+        // If this timerEvent is currently running, update the clocks and set the restart flag.
+        // Instead of being deleted in timerEventFinished it will be restarted
+        currentTimerEvent->restartAfterFinish = true;
+        // Don't need to resetThreadFlag because this timer isn't re-live yet
+        threadUnlock();
+        return true;
+      }
+      else
+      {
+        // A waiting timer has been edited
+        resetThreadFlag = true;
+        threadSignalNoLock();
+        threadUnlock();
+        return true;
+      }
     }
   }
 
-  Timer* t = new Timer();
+  // Timer did not exist already
+
+  TimerEvent* t = new TimerEvent();
   t->client = client;
   t->clientReference = clientReference;
   t->requestedTime.tv_sec = requestedTime;
@@ -124,10 +144,10 @@ int Timers::setTimerT(TimerReceiver* client, int clientReference, long int reque
 
   logger->log("Timers", Log::DEBUG, "Timer set for %p ref %i", client, clientReference);
 
-  return 1;
+  return true;
 }
 
-int Timers::setTimerD(TimerReceiver* client, int clientReference, long int requestedSecs, long int requestedNSecs)
+bool Timers::setTimerD(TimerReceiver* client, int clientReference, long int requestedSecs, long int requestedNSecs)
 {
   struct timespec currentTime;
 
@@ -159,51 +179,125 @@ int Timers::setTimerD(TimerReceiver* client, int clientReference, long int reque
   return setTimerT(client, clientReference, requestedTime, requestedTimeNSEC);
 }
 
-int Timers::cancelTimer(TimerReceiver* client, int clientReference)
+bool Timers::cancelTimer(TimerReceiver* client, int clientReference)
 {
-  if (!initted) return 0;
+  /* This method locks the timers mutex
+     Then one of three things can happen:
+     1. The TimerEvent is found, running = false. This means it hasn't started yet.
+        Delete the timer normally, set resetFlag
+     2. The TimerEvent is found, running = true. This means the timer is currently firing,
+        timercall on the client is being called.
+        In this case, this thread calling cancelTimer needs to unlock and wait for the
+        timercall thread to get back. (sleeps or signalling)
+     3. The TimerEvent is not found. Client error or the thread returned to
+        the Timers module in between client calling cancelTimer and cancelTimer actually
+        running. Do nothing, return normally.
+
+  By making sure there is no waiting timerevent, and no running timerevent, this ensures
+  that the program cannot segfault because a timer fired on a just deleted object.
+
+  */
+
+  if (!initted) return false;
 
   logger->log("Timers", Log::DEBUG, "Starting cancel timer %p %i, list size = %i", client, clientReference, timerList.size());
 
-  //logger->log("Timers", Log::DEBUG, "Waiting for LOCK -TIMERS- MUTEX 4");
+  while(1)
+  {
+    threadLock();
+
+    TimerList::iterator i;
+    TimerEvent* currentTimerEvent = NULL;
+    for(i = timerList.begin(); i != timerList.end(); i++)
+    {
+      currentTimerEvent = *i;
+      if ((currentTimerEvent->client == client) && (currentTimerEvent->clientReference == clientReference))
+      {
+        break;
+      }
+    }
+
+    if (i == timerList.end())
+    {
+      // Case 3, no timer found
+      threadUnlock();
+      return true;
+    }
+    else
+    {
+      // Timer found, Case 1 or 2
+
+      if (currentTimerEvent->running == false)
+      {
+        // Case 1. Just delete the timer and reset the thread.
+        timerList.erase(i);
+        delete currentTimerEvent;
+        logger->log("Timers", Log::DEBUG, "Removed timer for %p ref %i", client, clientReference);
+        resetThreadFlag = true;
+        threadSignalNoLock();
+        threadUnlock();
+        return true;
+      }
+      else
+      {
+        // Case 2. For now, use polling with a 50ms delay.
+        // Don't delete a running timer.
+        // FIXME upgrade me to signalling
+
+        logger->log("Timers", Log::DEBUG, "%p ref %i cancelTimer WAITING", client, clientReference);
+
+        threadUnlock();
+        MILLISLEEP(50);
+      }
+    }
+  } // end of the big while loop
+}
+
+void Timers::timerEventFinished(TimerEvent* timerEvent)
+{
+  // This function takes out the already timercall'd TimerEvent from the list
+  // Or resets it if restart flag is true
+
+
+  if (!initted) return;
   threadLock();
-  //logger->log("Timers", Log::DEBUG, "LOCKED -TIMERS- MUTEX 4");
-  TimerList::iterator i;
-  Timer* currentTimer = NULL;
-  for(i = timerList.begin(); i != timerList.end(); i++)
+
+  logger->log("Timers", Log::DEBUG, "timerEventFinished for %p", timerEvent->client);
+
+  for(TimerList::iterator i = timerList.begin(); i != timerList.end(); i++)
   {
-    currentTimer = *i;
-    //logger->log("Timers", Log::DEBUG, "I: %p %i : %p %i", client, clientReference, currentTimer->client, currentTimer->clientReference);
-    if ((currentTimer->client == client) && (currentTimer->clientReference == clientReference))
+    if (timerEvent != *i) continue;
+
+    if (timerEvent->restartAfterFinish)
+    {
+      logger->log("Timers", Log::DEBUG, "timerEventFinished RESTART for %p", timerEvent->client);
+
+      timerEvent->restartAfterFinish = false;
+      timerEvent->running = false;
+      resetThreadFlag = true;
+      threadSignalNoLock();
+    }
+    else
     {
+      // The removal of a called and non-restart TimerEvent doesn't need the threadMethod to be reset
       timerList.erase(i);
-      logger->log("Timers", Log::DEBUG, "Removed timer for %p ref %i", client, clientReference);
-      break;
-      // At this point currentTimer is not in the list but might still be nextTimer in the thread
+      logger->log("Timers", Log::DEBUG, "timerEventFinished for %p %i - remove done", timerEvent->client, timerEvent->clientReference);
+      delete timerEvent;
     }
-  }
-  if (i == timerList.end())
-  {
-    // no timer found
-    logger->log("Timers", Log::DEBUG, "No timer found in cancelTimer %p ref %i", client, clientReference);
-    //logger->log("Timers", Log::DEBUG, "about to un-LOCK -TIMERS- MUTEX 4");
-    threadUnlock();
-    return 0;
-  }
 
-  resetThreadFlag = true;
-  threadSignalNoLock();
-  //logger->log("Timers", Log::DEBUG, "about to un-LOCK -TIMERS- MUTEX 4");
+    break;
+  }
+  // FIXME At this point, this should signal all threads waiting on cancelTimer
   threadUnlock();
 
-
-  return 1;
+  // Kill this thread, as it's the one started for the timer event
+  Thread_TYPE::threadSuicide();
 }
 
 void Timers::threadMethod()
 {
   struct timespec nextTime;
-  Timer* nextTimer = NULL;
+  TimerEvent* nextTimer = NULL;
   resetThreadFlag = true;
 
   // locked here
@@ -221,10 +315,12 @@ void Timers::threadMethod()
       nextTimer = NULL;
 
       TimerList::iterator i;
-      Timer* currentTimer = NULL;
+      TimerEvent* currentTimer = NULL;
       for(i = timerList.begin(); i != timerList.end(); i++)
       {
         currentTimer = *i;
+        if (currentTimer->running) continue; // has already been timercall'd
+
         if (!nextTimer)
         {
           nextTime.tv_sec = currentTimer->requestedTime.tv_sec;
@@ -271,6 +367,8 @@ void Timers::threadMethod()
       // unlocks in the wait
     }
 
+    // Mutex locked again here by exit of wait or timedwait above
+
     // ok. we have been signalled or the time has run out
     // This only gets signalled if it is to reset or die
 
@@ -285,77 +383,34 @@ void Timers::threadMethod()
 
     Log::getInstance()->log("Timers", Log::DEBUG, "Timer firing for client %p ref %i", nextTimer->client, nextTimer->clientReference);
 
-    // send this timer to the timer receiver, via the command message queue
-    // so that the gui mutex is locked when it happens
-
-    Message* m = new Message(); // Timer call, must be injected into master mutex (this is generated outside the mutex)
-    m->from = this;
-    m->to = nextTimer->client;
-    m->message = Message::TIMER;
-    m->parameter = nextTimer->clientReference;
-
-    if (!Command::getInstance()->postMessageIfNotBusy(m))
-    {
-      // GUI mutex was locked
-      // abort this timer delivery - it might be trying to be deleted!
-      delete m;
-
-      // now unlock the timers mutex for a fraction of a second
-      // in case the gui thread is waiting on the timers mutex
-      threadUnlock();
-      //logger->log("Timers", Log::DEBUG, "un-LOCKED -TIMERS- MUTEX (3)");
-      //printf("\n\n\n WOOOOO \n\n\n The anti deadlock code is working!!! \n\n\n");
-      MILLISLEEP(20); // 10ms - too long? too short?
-      //logger->log("Timers", Log::DEBUG, "Waiting for LOCK -TIMERS- MUTEX 7");
-      threadLock();
-      //logger->log("Timers", Log::DEBUG, "LOCKED -TIMERS- MUTEX 7");
-      resetThreadFlag = true;
-    }
-    else
-    {
-      // timer was delivered
-      timerList.remove(nextTimer);
-      delete nextTimer;
-      nextTimer = NULL;
-      resetThreadFlag = true;
-    }
+    nextTimer->run(); // sets timerevent to running and starts it
+    resetThreadFlag = true; // find a new timer to wait on
   }
 }
 
-/*
-
-Avoiding deadlock using the timer class...
-
-Situation:
 
-timer condwait finishes
-timers is about to fire a timer
-timers locks timers-mutex
 
-    user presses a button
-    command locks gui-mutex
+// Class TimerEvent
 
-timers tries to get gui-mutex
-
-    view receives button
-    view wants to delete itself
-    view tries to deletetimer
-    goes into delete timer
-    waits on timers mutex
-
-- deadlock
-
-
-Solution:
+TimerEvent::TimerEvent()
+{
+  running = false;
+  restartAfterFinish = false;
+  client = NULL;
+  clientReference = 0;
+  requestedTime.tv_sec = 0;
+  requestedTime.tv_nsec = 0;
+}
 
-timers tries to get gui mutex
-if mutex is locked already abort
-unlock timers mutex
-wait a fraction of time
-(allow other thread to lock timers mutex)
-lock timers mutex
-set reset flag to recalculate
-- if timer has been cancelled next timer will be calced
-- if timer has not been cancelled it will be called next
+void TimerEvent::threadMethod()
+{
+  Log::getInstance()->log("Timers", Log::DEBUG, "sending timer to %p with parameter %u", client, clientReference);
+  client->timercall(clientReference);
+  Timers::getInstance()->timerEventFinished(this); // does not return
+}
 
-*/
+void TimerEvent::run()
+{
+  running = true;
+  threadStart();
+}
index 09dddc07c7fcfbb8a9e19628639c13eb38e62c94..3c95e60c1b876f1ece007f11fe0e4c13b9657384 100755 (executable)
--- a/timers.h
+++ b/timers.h
@@ -57,19 +57,34 @@ You can reset a timer by calling setTimer again. This will not create 2 timers,
 You must not allow a timer to fire on an object that has been deleted already, unless you want
 segfaulty hell.
 
+??
+
+You must call cancelTimer before deleting object. cancelTimer guarantees that timercall
+will not be called again.
+
 */
 
-class Timer
+class TimerEvent : public Thread_TYPE
 {
   public:
+    TimerEvent();
+
+    virtual void run();
+    virtual void threadMethod();
+    virtual void threadPostStopCleanup() {};
+
     TimerReceiver* client;
     int clientReference;
     struct timespec requestedTime;
+
+    bool running;
+    bool restartAfterFinish;
 };
 
+
 using namespace std;
-//using namespace __gnu_cxx;
-typedef list<Timer*> TimerList;
+
+typedef list<TimerEvent*> TimerList;
 
 class Timers : public Thread_TYPE
 {
@@ -81,14 +96,16 @@ class Timers : public Thread_TYPE
     int init();
     int shutdown();
 
-    int setTimerT(TimerReceiver* client, int clientReference, long int requestedTime, long int requestedTimeNSEC=0);
-    int setTimerD(TimerReceiver* client, int clientReference, long int requestedSecs, long int requestedNSecs=0);
-    int cancelTimer(TimerReceiver* client, int clientReference);
+    bool setTimerT(TimerReceiver* client, int clientReference, long int requestedTime, long int requestedTimeNSEC=0);
+    bool setTimerD(TimerReceiver* client, int clientReference, long int requestedSecs, long int requestedNSecs=0);
+    bool cancelTimer(TimerReceiver* client, int clientReference);
 
     // Thread stuff
     virtual void threadMethod();
     virtual void threadPostStopCleanup() {};
 
+    void timerEventFinished(TimerEvent* timerEvent); // internal use only, does not return
+
   private:
     static Timers* instance;
     Log* logger;
index 880309fcf1d3fb256588edcbc6466a610a956b67..8df54f67528b34c6e619ffcda1bcfc48734ea456 100644 (file)
@@ -182,7 +182,7 @@ void VChannelSelect::timercall(int clientReference)
   m->from = this;
   m->to = ViewMan::getInstance();
   m->message = Message::CLOSE_ME;
-  Command::getInstance()->postMessageNoLock(m);
+  Command::getInstance()->postMessageFromOuterSpace(m);
 
   // Is there valid data?
   if ((first > 0) || (second > 0) || (third > 0))
@@ -205,6 +205,6 @@ void VChannelSelect::timercall(int clientReference)
     m->to = videoLive;
     m->message = Message::CHANNEL_CHANGE;
     m->parameter = newChannel;
-    Command::getInstance()->postMessageNoLock(m);
+    Command::getInstance()->postMessageFromOuterSpace(m);
   }
 }
index c3e03a657083d844ead66022db14c5c66728ce0c..58691d64712b49c0656c39021ede9e7d8c58823f 100644 (file)
@@ -445,5 +445,12 @@ void ViewMan::processMessage(Message* m)
       updateView(toAdd);
       break;
     }
+    case Message::REDRAW:
+    {
+      View* toRedraw = (View*)m->from;
+      Region* toRedrawRegion = (Region*)m->parameter;
+      updateView(toRedraw, toRedrawRegion);
+      break;
+    }
   }
 }
index 2dc9c3f72530c803a65dff9c16055b5e329053d1..ab790cd1ef621283378ed5869a9221f01210aba6 100644 (file)
@@ -262,13 +262,18 @@ void VLiveBanner::timercall(int clientReference)
     m->message = Message::CLOSE_ME;
     m->to = ViewMan::getInstance();
     m->from = this;
-    Command::getInstance()->postMessageNoLock(m);
+    Command::getInstance()->postMessageFromOuterSpace(m);
   }
   else if (clientReference == 2)
   {
     // redraw clock
     drawClock();
-    ViewMan::getInstance()->updateView(this, &clockRegion);
+    Message* m = new Message();
+    m->message = Message::REDRAW;
+    m->to = ViewMan::getInstance();
+    m->from = this;
+    m->parameter = (ULONG)&clockRegion;
+    Command::getInstance()->postMessageFromOuterSpace(m);
   }
 }
 
index 921f15a5de48d8cfc7c8db9e9a6eba8eecdb0e42..1f139501de2e7c3c08942977e0d5a71220aff2b9 100644 (file)
--- a/vmute.cc
+++ b/vmute.cc
@@ -64,7 +64,7 @@ void VMute::timercall(int clientReference)
   m->message = Message::CLOSE_ME;
   m->to = ViewMan::getInstance();
   m->from = this;
-  Command::getInstance()->postMessageNoLock(m);
+  Command::getInstance()->postMessageFromOuterSpace(m);
 }
 
 int VMute::handleCommand(int command)
index 8febeb4ee717546eae584dbdc7074a6506cad381..abd68a31a3c4feae63e898e53eedb6fbc42d9cd7 100644 (file)
@@ -398,7 +398,12 @@ void VRadioRec::timercall(int clientReference)
       // Update clock
       if (!barShowing) break;
       drawBarClocks();
-      ViewMan::getInstance()->updateView(this, &barRegion);
+      Message* m = new Message();
+      m->message = Message::REDRAW;
+      m->to = ViewMan::getInstance();
+      m->from = this;
+      m->parameter = (ULONG)&barRegion;
+      Command::getInstance()->postMessageFromOuterSpace(m);
       timers->setTimerD(this, 2, 0, 200000000);
       break;
     }
index cccf503bf90a2412328a3684b783695b577adab8..3d280513e7b1ef9a97a23a2ac62cd92d1700871a 100644 (file)
@@ -211,11 +211,23 @@ void VTimerList::drawIndicators()
 void VTimerList::timercall(int clientReference)
 {
   drawClock();
-  ViewMan::getInstance()->updateView(this, &clockRegion);
+
+  Message* m = new Message();
+  m->message = Message::REDRAW;
+  m->to = ViewMan::getInstance();
+  m->from = this;
+  m->parameter = (ULONG)&clockRegion;
+  Command::getInstance()->postMessageFromOuterSpace(m);
 
   flipflop = !flipflop;
   drawIndicators();
-  ViewMan::getInstance()->updateView(this, &indicatorsRegion);
+
+  m = new Message();
+  m->message = Message::REDRAW;
+  m->to = ViewMan::getInstance();
+  m->from = this;
+  m->parameter = (ULONG)&indicatorsRegion;
+  Command::getInstance()->postMessageFromOuterSpace(m);
 }
 
 int VTimerList::handleCommand(int command)
index 9ce4ca7387e2a2903e8ccb98219c409e7dda5f6c..1f6fb334d1311accee70bb25d3eaf2e03882c6ca 100644 (file)
@@ -206,6 +206,7 @@ int VVideoRec::handleCommand(int command)
     case Remote::MENU:
     {
       if (playing) stopPlay();
+
       return 4;
     }
     case Remote::PAUSE:
@@ -651,7 +652,12 @@ void VVideoRec::timercall(int clientReference)
       // Update clock
       if (!barShowing) break;
       drawBarClocks();
-      viewman->updateView(this, &barRegion);
+      Message* m = new Message();
+      m->message = Message::REDRAW;
+      m->to = ViewMan::getInstance();
+      m->from = this;
+      m->parameter = (ULONG)&barRegion;
+      Command::getInstance()->postMessageFromOuterSpace(m);
       timers->setTimerD(this, 2, 0, 200000000);
       break;
     }
index fd7cbf6ff15cfd2aacf8a5d196fef972373c5520..d7e684db62948d13eb6dbab5004da900e7f4a94a 100644 (file)
@@ -79,7 +79,7 @@ void VVolume::timercall(int clientReference)
   m->message = Message::CLOSE_ME;
   m->to = ViewMan::getInstance();
   m->from = this;
-  Command::getInstance()->postMessageNoLock(m);
+  Command::getInstance()->postMessageFromOuterSpace(m);
 }
 
 int VVolume::handleCommand(int command)
index 8ba5d7489b7b081ea95eb40e9c7c290e5d727fbc..dd4d334f65afcf09e6c4772054a1fd2cee8c48af 100644 (file)
@@ -96,7 +96,13 @@ void VWelcome::drawClock()
 void VWelcome::timercall(int clientReference)
 {
   drawClock();
-  viewman->updateView(this, &clockRegion);
+  // Put updateView through master mutex since viewman is not mutex protected
+  Message* m = new Message();
+  m->message = Message::REDRAW;
+  m->to = ViewMan::getInstance();
+  m->from = this;
+  m->parameter = (ULONG)&clockRegion;
+  Command::getInstance()->postMessageFromOuterSpace(m);
 }
 
 int VWelcome::handleCommand(int command)