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
return 0;
}
+ pthread_mutex_init(&masterLock, NULL);
+
return 1;
}
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();
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)
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;
}
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
+ }
}
}
VVolume* v = new VVolume();
v->handleCommand(button); // this will draw+show
viewman->add(v);
- viewman->timedDelete(v, 2, 1);
return;
}
case Remote::MUTE:
v->draw();
v->show();
viewman->add(v);
- viewman->timedDelete(v, 2, 1);
return;
}
case Remote::POWER:
#include <sys/reboot.h>
#include <time.h>
-
+#include <pthread.h>
#include <signal.h>
#include "defines.h"
#include "colour.h"
#include "osd.h"
#include "i18n.h"
+#include "timerreceiver.h"
+#include "timers.h"
class VConnect;
static Command* instance;
pid_t mainPid;
+ pthread_mutex_t masterLock;
UCHAR initted;
UCHAR irun;
UCHAR isStandby;
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;
const static ULONG STREAM_END = 16;
const static ULONG CHILD_CLOSE = 17;
const static ULONG REDRAW_LANG = 18;
+ const static ULONG TIMER = 19;
};
#endif
return threadActive;
}
+void Thread::threadLock()
+{
+ pthread_mutex_lock(&threadCondMutex);
+}
+
+void Thread::threadUnlock()
+{
+ pthread_mutex_unlock(&threadCondMutex);
+}
+
void Thread::threadSignal()
{
pthread_mutex_lock(&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()
{
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
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
--- /dev/null
+/*\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
--- /dev/null
+/*\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, ¤tTime);\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
--- /dev/null
+/*\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
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();
}
instance = this;
initted = 0;
numViews = 0;
- resetThreadFlag = 0;
- autoDeleteThreadRun = 0;
- callFromThread = 0;
}
ViewMan::~ViewMan()
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;
}
// 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;
}
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;
if (i == -1)
{
// not a View we have!
- if (!noLock) pthread_mutex_unlock(&viewManLock);
return 0;
}
}
// Delete the view
delete toDelete;
- resetThread();
- if (!noLock) pthread_mutex_unlock(&viewManLock);
-
return 1;
}
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;
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, ¤tTime);
- 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;
}
processMessageQueue();
- pthread_mutex_unlock(&viewManLock);
return retVal2;
}
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, ¤tTime);
- 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, ¤tTime);
-
- 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;
- }
-}
-
#include <stdio.h>
#include <time.h>
#include <signal.h>
-#include <pthread.h>
-#include <slist>
+#include <ext/slist>
#include "defines.h"
#include "view.h"
#include "surface.h"
#include "region.h"
+//using namespace std;
+using namespace __gnu_cxx;
+
typedef slist<Region> RegionList;
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;
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
sl.setNoLoop();
setChannel(channel);
+
+ // set a timer for deleting view
+ Timers::getInstance()->setTimer(this, 1, (struct timespec){4, 0});
}
VLiveBanner::~VLiveBanner()
}
// 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});
}
}
{
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);
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);
+}
#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);
int handleCommand(int command);
void draw();
+ void timercall(int clientReference);
private:
View* parent;
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)
#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;
{
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);
}
}
}
{
VChannelSelect* v = new VChannelSelect(this, command);
viewman->addNoLock(v);
-// ViewMan::getInstance()->timedDelete(v, 4, 0);
v->draw();
v->show();
}
if(epgmode)
return;
vlb = new VLiveBanner(this, (*chanList)[currentChannel], bannerTakesCommands);
- viewman->timedDelete(vlb, 4, 0);
Message* m = new Message();
m->from = this;
class VEpg;
+class VLiveBanner;
+
class VVideoLive : public View
{
public:
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)
#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;