From: Felix Domke Date: Fri, 25 May 2007 00:51:08 +0000 (+0000) Subject: add 'spinner' (non-idle detection) X-Git-Tag: 2.6.0~2222 X-Git-Url: https://git.cweiske.de/enigma2.git/commitdiff_plain/2bc51a33ae4089d88a3a8a3e5fb56afafac69d35 add 'spinner' (non-idle detection) --- diff --git a/lib/base/ebase.cpp b/lib/base/ebase.cpp index 93bfd342..08c15610 100644 --- a/lib/base/ebase.cpp +++ b/lib/base/ebase.cpp @@ -197,12 +197,17 @@ int eMainloop::processOneEvent(unsigned int twisted_timeout, PyObject **res, ePy } } + m_is_idle = 1; + if (this == eApp) + { Py_BEGIN_ALLOW_THREADS ret = ::poll(pfd, fdcount, poll_timeout); Py_END_ALLOW_THREADS - else + } else ret = ::poll(pfd, fdcount, poll_timeout); + + m_is_idle = 0; /* ret > 0 means that there are some active poll entries. */ if (ret > 0) diff --git a/lib/base/ebase.h b/lib/base/ebase.h index f14d07ac..27e4ec84 100644 --- a/lib/base/ebase.h +++ b/lib/base/ebase.h @@ -191,6 +191,7 @@ class eMainloop int processOneEvent(unsigned int user_timeout, PyObject **res=0, ePyObject additional=ePyObject()); int retval; int time_offset; + int m_is_idle; pthread_mutex_t recalcLock; int m_interrupt_requested; @@ -211,7 +212,7 @@ public: #endif eMainloop() - :app_quit_now(0),loop_level(0),retval(0), m_interrupt_requested(0) + :app_quit_now(0),loop_level(0),retval(0), m_is_idle(0), m_interrupt_requested(0) { existing_loops.push_back(this); pthread_mutex_init(&recalcLock, 0); @@ -242,6 +243,9 @@ public: PyObject *poll(SWIG_PYOBJECT(ePyObject) dict, SWIG_PYOBJECT(ePyObject) timeout); void interruptPoll(); void reset(); + + /* m_is_idle needs to be atomic, but it doesn't really matter much, as it's read-only from outside */ + int isIdle() { return m_is_idle; } }; /** diff --git a/lib/gdi/grc.cpp b/lib/gdi/grc.cpp index 736630a8..b3ad2ccc 100644 --- a/lib/gdi/grc.cpp +++ b/lib/gdi/grc.cpp @@ -32,6 +32,7 @@ gRC::gRC(): rp(0), wp(0) else eDebug("RC thread created successfully"); #endif + m_spinner_enabled = 0; } DEFINE_REF(gRC); @@ -131,8 +132,46 @@ void *gRC::thread() } #ifndef SYNC_PAINT while(rp == wp) - pthread_cond_wait(&cond, &mutex); - pthread_mutex_unlock(&mutex); + { + + /* when the main thread is non-idle for a too long time without any display output, + we want to display a spinner. */ + + struct timeval time; + struct timespec timeout; + gettimeofday(&time, NULL); + timeout.tv_sec = time.tv_sec; + timeout.tv_nsec = time.tv_usec * 1000; + + if (m_spinner_enabled) + timeout.tv_nsec += 100*1000*1000; + else + timeout.tv_nsec += 500*1000*1000; + + /* yes, this is required. */ + if (timeout.tv_nsec > 1000*1000*1000) + { + timeout.tv_nsec -= 1000*1000*1000; + timeout.tv_sec++; + } + + int idle = 1; + + if (pthread_cond_timedwait(&cond, &mutex, &timeout) == ETIMEDOUT) + { + if (eApp && !eApp->isIdle()) + idle = 0; + } + + pthread_mutex_unlock(&mutex); + + if (!idle) + { + enableSpinner(); + eDebug("main thread is non-idle! display spinner!"); + } else + disableSpinner(); + } #endif } } @@ -152,6 +191,39 @@ gRC *gRC::getInstance() return instance; } +void gRC::enableSpinner() +{ + if (!m_spinner_dc) + { + eDebug("no spinner DC!"); + return; + } + + m_spinner_enabled = 1; + + gOpcode o; + o.opcode = m_spinner_enabled ? gOpcode::incrementSpinner : gOpcode::enableSpinner; + m_spinner_dc->exec(&o); +} + +void gRC::disableSpinner() +{ + if (!m_spinner_enabled) + return; + + if (!m_spinner_dc) + { + eDebug("no spinner DC!"); + return; + } + + m_spinner_enabled = 0; + + gOpcode o; + o.opcode = gOpcode::disableSpinner; + m_spinner_dc->exec(&o); +} + static int gPainter_instances; gPainter::gPainter(gDC *dc, eRect rect): m_dc(dc), m_rc(gRC::getInstance()) @@ -678,6 +750,12 @@ void gDC::exec(gOpcode *o) break; case gOpcode::flush: break; + case gOpcode::enableSpinner: + break; + case gOpcode::disableSpinner: + break; + case gOpcode::incrementSpinner: + break; default: eFatal("illegal opcode %d. expect memory leak!", o->opcode); } diff --git a/lib/gdi/grc.h b/lib/gdi/grc.h index fb9e2ea1..9f32e911 100644 --- a/lib/gdi/grc.h +++ b/lib/gdi/grc.h @@ -58,6 +58,8 @@ struct gOpcode flip, notify, + enableSpinner, disableSpinner, incrementSpinner, + shutdown } opcode; @@ -161,6 +163,13 @@ private: eFixedMessagePump m_notify_pump; void recv_notify(const int &i); + + ePtr m_spinner_dc; + int m_spinner_enabled; + + void enableSpinner(); + void disableSpinner(); + public: gRC(); virtual ~gRC(); @@ -168,7 +177,9 @@ public: void submit(const gOpcode &o); Signal0 notify; - + + void setSpinnerDC(gDC *dc) { m_spinner_dc = dc; } + static gRC *getInstance(); }; diff --git a/main/enigma.cpp b/main/enigma.cpp index cc9781cc..4af7ca03 100644 --- a/main/enigma.cpp +++ b/main/enigma.cpp @@ -189,6 +189,8 @@ int main(int argc, char **argv) /* redrawing is done in an idle-timer, so we have to set the context */ dsk.setRedrawTask(main); dsk_lcd.setRedrawTask(main); + + gRC::getInstance()->setSpinnerDC(my_dc); eRCInput::getInstance()->keyEvent.connect(slot(keyEvent));