diff --git a/src/gui/components/cc_draw.cpp b/src/gui/components/cc_draw.cpp index 9c015ec94..674e64aa3 100644 --- a/src/gui/components/cc_draw.cpp +++ b/src/gui/components/cc_draw.cpp @@ -841,11 +841,12 @@ bool CCDraw::paintBlink(CComponentsTimer* Timer) return false; } -bool CCDraw::paintBlink(const int& interval, bool is_nano) +bool CCDraw::paintBlink(const int64_t& interval) { if (cc_draw_timer == NULL){ - cc_draw_timer = new CComponentsTimer(interval, is_nano); + cc_draw_timer = new CComponentsTimer(interval); cc_draw_timer->setThreadName(__func__); + cc_draw_timer->startTimer(); } return paintBlink(cc_draw_timer); diff --git a/src/gui/components/cc_draw.h b/src/gui/components/cc_draw.h index a0f458741..95ddad29d 100644 --- a/src/gui/components/cc_draw.h +++ b/src/gui/components/cc_draw.h @@ -328,8 +328,7 @@ class CCDraw : public COSDFader, public CComponentsSignals, public CCTypes * * @return bool returns true if effect is successful started * - * @param[in] interval optional, interval time as int, default = 1 - * @param[in] is_nano optional, time mode as bool, default = false means as seconds, true means nano seconds. + * @param[in] interval optional, interval time as int64_t in miliseconds, default = 1000 (1 sec) * * @see take a look into test menu class for examples. * cancelBlink() @@ -340,7 +339,7 @@ class CCDraw : public COSDFader, public CComponentsSignals, public CCTypes * and it's possible you must remove from screen before e.g.: * item->kill(); */ - bool paintBlink(const int& interval = 1, bool is_nano = false); + bool paintBlink(const int64_t& interval = 1000); /**Cancel blink effect * diff --git a/src/gui/components/cc_frm_clock.cpp b/src/gui/components/cc_frm_clock.cpp index dc80add69..72aa7c54f 100644 --- a/src/gui/components/cc_frm_clock.cpp +++ b/src/gui/components/cc_frm_clock.cpp @@ -3,7 +3,7 @@ Copyright (C) 2001 by Steffen Hehn 'McClean' Generic GUI-related component. - Copyright (C) 2013-2015 Thilo Graf 'dbt' + Copyright (C) 2013-2019 Thilo Graf 'dbt' License: GPL @@ -47,7 +47,7 @@ CComponentsFrmClock::CComponentsFrmClock( const int& x_pos, const char* prformat_str, const char* secformat_str, bool activ, - const int& interval_seconds, + const int64_t& interval_seconds, CComponentsForm* parent, int shadow_mode, fb_pixel_t color_frame, @@ -86,15 +86,14 @@ CComponentsFrmClock::CComponentsFrmClock( const int& x_pos, //init general clock dimensions height = height_old= cl_font->getHeight(); - width = width_old = cl_font->getRenderWidth(cl_format_str); + width = width_old = 0;//cl_font->getRenderWidth(cl_format_str); //set default text background behavior cc_txt_save_screen = false; //set default running clock properties - cl_interval = interval_seconds; + cl_interval = interval_seconds * 1000; cl_timer = NULL; - cl_blocked = true; #if 0 may_blit = true; #endif @@ -216,7 +215,7 @@ void CComponentsFrmClock::initCCLockItems() minSepWidth = max(cl_font->getRenderWidth(sep[i]), minSepWidth); //get minimal required dimensions for segements from current format string - int w_text_min = max(cl_font->getRenderWidth(s_time), width); + cl_width = 0; //summary of all segments (labels) int h_text_min = max(cl_font->getHeight(), height); //init some temporary variables @@ -224,18 +223,19 @@ void CComponentsFrmClock::initCCLockItems() int h_tmp = h_text_min; int y_tmp = y; - //summary of all segments (labels) - int w_segments = 0; - const bool force_repaint = cl_force_repaint; - +// dprintf(DEBUG_NORMAL, "\033[33m[CComponentsFrmClock][%s - %d], clock width width %d \033[0m\n", __func__, __LINE__, width); /* modify available label items with current segment chars * we are using segments with only one char per segment, * these chars are predefined via format string */ for (size_t i = 0; i < v_cc_items.size(); i++) { + std::lock_guard g(cc_frm_mutex); + //v_cc_items are only available as CComponent-items here, so we must cast them before + if (!v_cc_items[i]) + continue; CComponentsLabel *lbl = static_cast (v_cc_items[i]); //add rounded corners only to 1st and last segment @@ -261,6 +261,7 @@ void CComponentsFrmClock::initCCLockItems() //set size, text, color of current item lbl->setDimensionsAll(x_tmp, y_tmp, w_tmp, h_tmp); + lbl->setFrameThickness(0); lbl->setColorAll(col_frame, col_body, col_shadow); lbl->forceTextPaint(force_repaint); lbl->setText(stmp, CTextBox::CENTER, cl_font, cl_col_text, cl_font_style); @@ -278,33 +279,43 @@ void CComponentsFrmClock::initCCLockItems() ctb->setFontUseDigitHeight(); //ensure paint of text and label bg on changed text or painted form background - bool force_txt_and_bg = (lbl->textChanged() || this->paint_bg); + bool force_txt_and_bg = (lbl->textChanged() || paint_bg); lbl->forceTextPaint(force_txt_and_bg); #endif //set xpos and width of item (segment) lbl->setWidth(w_tmp); - x_tmp += w_tmp; + x_tmp += lbl->getWidth();//w_tmp; //sum required width for clock (this) - w_segments += w_tmp; + cl_width += lbl->getWidth();//w_tmp; h_text_min = max(lbl->getHeight(), height); height = max(lbl->getHeight(), height); +// dprintf(DEBUG_NORMAL, "\033[33m[CComponentsFrmClock][%s - %d], clock width width %d cl_width = %d\033[0m\n", __func__, __LINE__, width, cl_width); } //set required width for clock (this) - width = max(w_text_min, w_segments); + int w_std = width; + if (cl_width > width){ + width = cl_width; + } +// dprintf(DEBUG_NORMAL, "\033[33m[CComponentsFrmClock][%s - %d], clock width width %d w_std %d cl_width = %d\033[0m\n", __func__, __LINE__, width, w_std, cl_width); //use first item as reference and set x and y position to the 1st segement item with definied alignment - int x_lbl = width/2-w_segments/2; - v_cc_items[0]->setXPos(x_lbl); + //ensure unsigned position values + int x_lbl = max(0, width/2-cl_width/2); + int y_lbl = max(0, height/2-h_text_min/2); - int y_lbl = height/2-h_text_min/2; - v_cc_items[0]->setYPos(y_lbl); + if (v_cc_items.front()) + v_cc_items.front()->setPos(x_lbl, y_lbl); //set all evaluated position values to all other segement items for (size_t i = 1; i < v_cc_items.size(); i++){ - x_lbl += v_cc_items[i-1]->getWidth(); - v_cc_items[i]->setPos(x_lbl, y_lbl); + if (v_cc_items.at(i)){ + if (v_cc_items.at(i-1)){ + x_lbl += v_cc_items.at(i-1)->getWidth(); + v_cc_items.at(i)->setPos(x_lbl, y_lbl); + } + } } } @@ -312,60 +323,57 @@ void CComponentsFrmClock::initCCLockItems() //this member is provided for slot with timer event "OnTimer" void CComponentsFrmClock::ShowTime() { - if (!cl_blocked) { - //paint segements, but wihtout saved backgrounds - paint(CC_SAVE_SCREEN_NO); - } + //paint segements, but wihtout saved backgrounds + this->CComponentsFrmClock::paint(CC_SAVE_SCREEN_NO); } //start up ticking clock controled by timer with signal/slot, return true on succses bool CComponentsFrmClock::startClock() { - if (cl_interval <= 0){ - dprintf(DEBUG_NORMAL, "[CComponentsFrmClock] [%s] clock is set to active, but interval is initialized with value %d ...\n", __func__, cl_interval); - return false; + if (stopClock()){ + if (cl_interval <= 0){ + dprintf(DEBUG_NORMAL, "[CComponentsFrmClock] [%s] clock is set to active, but interval is initialized with value %l ...\n", __func__, cl_interval); + return false; + } + + if (!cl_timer){ + cl_timer = new CComponentsTimer(0); + cl_timer->setThreadName(getItemName()); + cl_timer->OnTimer.connect(cl_sl_show); + force_paint_bg = true; + cl_timer->setTimerInterval(cl_interval); + cl_timer->startTimer(); + } } - if (cl_timer == NULL) - cl_timer = new CComponentsTimer(0); - - cl_timer->setThreadName(getItemName()); - - if (cl_timer->OnTimer.empty()){ - dprintf(DEBUG_INFO,"\033[33m[CComponentsFrmClock]\t[%s] init slot...\033[0m\n", __func__); - cl_timer->OnTimer.connect(cl_sl_show); - force_paint_bg = true; - } - - cl_timer->setTimerInterval(cl_interval); - - if (cl_timer->startTimer()) - return true; - - return false; + return isRun(); } //stop ticking clock and internal timer, return true on succses bool CComponentsFrmClock::stopClock() { - if (cl_timer){ - if (cl_timer->stopTimer()){ - dprintf(DEBUG_INFO, "[CComponentsFrmClock] [%s] stopping clock...\n", __func__); - clear(); - delete cl_timer; - cl_timer = NULL; - return true; - } - else - dprintf(DEBUG_NORMAL, "[CComponentsFrmClock] [%s] stopping timer failed...\n", __func__); + if (!cl_timer){ + return true; + }else{ + delete cl_timer; + cl_timer = NULL; + clear(); + cc_allow_paint = true; + return true; } - return false; + + return isRun(); } bool CComponentsFrmClock::Start() { if (startClock()) { - cl_blocked = !cc_allow_paint; + if (cl_timer){ + if (!cc_allow_paint) + cl_timer->OnTimer.block(); + else + cl_timer->OnTimer.unblock(); + } return true; } return false; @@ -373,10 +381,8 @@ bool CComponentsFrmClock::Start() bool CComponentsFrmClock::Stop() { - if (stopClock()){ - cl_blocked = true; + if (stopClock()) return true; - } return false; } @@ -391,7 +397,6 @@ void CComponentsFrmClock::paint(const bool &do_save_bg) //paint form contents CComponentsForm::paint(do_save_bg); - } void CComponentsFrmClock::setClockFont(Font *font, const int& style) @@ -420,6 +425,9 @@ void CComponentsFrmClock::enableTboxSaveScreen(bool mode) { if (cc_txt_save_screen == mode || v_cc_items.empty()) return; + + std::lock_guard g(cl_mutex); + cc_txt_save_screen = mode; for (size_t i = 0; i < v_cc_items.size(); i++){ CComponentsLabel *seg = static_cast (v_cc_items[i]); @@ -429,6 +437,8 @@ void CComponentsFrmClock::enableTboxSaveScreen(bool mode) void CComponentsFrmClock::setHeight(const int& h) { + std::lock_guard g(cl_mutex); + if (h == height) return; @@ -443,18 +453,31 @@ void CComponentsFrmClock::setHeight(const int& h) void CComponentsFrmClock::setWidth(const int& w) { + std::lock_guard g(cl_mutex); + if (w == width) return; - + else + CComponentsItem::setWidth(w); +#if 0 int f_width = cl_font->getRenderWidth(cl_format_str); if (w != f_width){ dprintf(DEBUG_NORMAL, "\033[33m[CComponentsFrmClock]\t[%s - %d], font width is different than current width [%d], using [%d] ...\033[0m\n", __func__, __LINE__, w, f_width); CComponentsItem::setWidth(f_width); }else CComponentsItem::setWidth(w); +#endif initCCLockItems(); } +int CComponentsFrmClock::getWidth() const +{ + if (width > cl_width) + return width; + + return cl_width; +} + bool CComponentsFrmClock::enableColBodyGradient(const int& enable_mode, const fb_pixel_t& sec_color) { if (CCDraw::enableColBodyGradient(enable_mode, sec_color)){ diff --git a/src/gui/components/cc_frm_clock.h b/src/gui/components/cc_frm_clock.h index 441a8172b..288b49992 100644 --- a/src/gui/components/cc_frm_clock.h +++ b/src/gui/components/cc_frm_clock.h @@ -3,7 +3,7 @@ Copyright (C) 2001 by Steffen Hehn 'McClean' Classes for generic GUI-related components. - Copyright (C) 2012-2015, Thilo Graf 'dbt' + Copyright (C) 2012-2019, Thilo Graf 'dbt' License: GPL @@ -36,6 +36,7 @@ #include "cc_frm.h" #include "cc_text_screen.h" #include "cc_timer.h" + //! Sub class of CComponents. Show clock with digits on screen. /*! Usable as simple fixed display or as ticking clock. @@ -49,22 +50,17 @@ class CComponentsFrmClock : public CComponentsForm, public CCTextScreen #if 0 bool may_blit; #endif - protected: CComponentsTimer *cl_timer; - ///slot for timer event, reserved for ShowTime() - sigc::slot0 cl_sl_show; + std::mutex cl_mutex; ///refresh interval in seconds - int cl_interval; + int64_t cl_interval; ///raw time chars char cl_timestr[32]; - ///handle paint clock within thread and is not similar to cc_allow_paint - bool cl_blocked; - ///object: font render object Font *cl_font; int cl_font_style; @@ -82,10 +78,12 @@ class CComponentsFrmClock : public CComponentsForm, public CCTextScreen ///secondary time format for blink std::string cl_blink_str; + int cl_width; + ///initialize clock contents void initCCLockItems(); ///initialize timestring, called in initCCLockItems() - virtual void initTimeString(); + void initTimeString(); ///start ticking clock, returns true on success, if false causes log output bool startClock(); @@ -103,7 +101,7 @@ class CComponentsFrmClock : public CComponentsForm, public CCTextScreen const char* format_str = "%H:%M", const char* secformat_str = NULL, bool activ=false, - const int& interval_seconds = 1, + const int64_t& interval_seconds = 1, CComponentsForm *parent = NULL, int shadow_mode = CC_SHADOW_OFF, fb_pixel_t color_frame = COL_FRAME_PLUS_0, @@ -128,6 +126,9 @@ class CComponentsFrmClock : public CComponentsForm, public CCTextScreen ///return pointer of font object Font* getClockFont(); + ///return pointer of timer object + CComponentsTimer* getTimer(){return cl_timer;} + ///set text color void setTextColor(fb_pixel_t color_text){ cl_col_text = color_text;} @@ -135,6 +136,8 @@ class CComponentsFrmClock : public CComponentsForm, public CCTextScreen void setHeight(const int& h); ///set width of clock on screen void setWidth(const int& w); + + int getWidth() const; ///use string expession: "%H:%M" = 12:22, "%H:%M:%S" = 12:22:12 ///set current time format string, 1st parameter set the default format, 2nd parameter sets an alternatively format for use as blink effect @@ -145,18 +148,18 @@ class CComponentsFrmClock : public CComponentsForm, public CCTextScreen ///start and paint ticking clock bool Start(); ///same like Start() but for usage as simple call without return value - void unblock(){Start();} + void unblock(){if (cl_timer) cl_timer->OnTimer.unblock();} ///stop ticking clock, but don't hide, use kill() or hide() to remove from screen bool Stop(); ///same like Stop() but for usage as simple call without return value - void block(){Stop();} + void block(){if (cl_timer) cl_timer->OnTimer.block();} ///return true on blocked status, blocked means clock can be initalized but would be not paint, to unblock use unblock() - bool isBlocked(void) {return cl_blocked;} + bool isBlocked(void) const {return cl_timer ? cl_timer->OnTimer.blocked() : true;} ///returns true, if clock is running bool isRun() const {return cl_timer ? cl_timer->isRun() : false;} ///set refresh interval in seconds, default value=1 (=1 sec) - void setClockInterval(const int& seconds){cl_interval = seconds;} + void setClockInterval(const int64_t& seconds){cl_interval = seconds*1000;} ///show clock on screen void paint(const bool &do_save_bg = CC_SAVE_SCREEN_YES); @@ -187,6 +190,9 @@ class CComponentsFrmClock : public CComponentsForm, public CCTextScreen ///set color gradient on/off, returns true if gradient mode was changed bool enableColBodyGradient(const int& enable_mode, const fb_pixel_t& sec_color = 255 /*=COL_BACKGROUND*/); + + ///slot for timer event, reserved for ShowTime() + sigc::slot0 cl_sl_show; #if 0 ///enable/disable automatic blitting void setBlit(bool _may_blit = true) { may_blit = _may_blit; } diff --git a/src/gui/components/cc_timer.cpp b/src/gui/components/cc_timer.cpp index e57c7465d..34980e71d 100644 --- a/src/gui/components/cc_timer.cpp +++ b/src/gui/components/cc_timer.cpp @@ -3,7 +3,7 @@ Copyright (C) 2001 by Steffen Hehn 'McClean' Generic Timer. - Copyright (C) 2013-2016, Thilo Graf 'dbt' + Copyright (C) 2013-2019, Thilo Graf 'dbt' License: GPL @@ -29,154 +29,127 @@ #include #include "cc_timer.h" -#include +#include "cc_types.h" #include #include #include #include +#include +#include using namespace std; -CComponentsTimer::CComponentsTimer(const int& interval, bool is_nano) -{ - name = "unnamed"; - tm_thread = 0; - tm_interval = interval; - tm_enable_nano = is_nano; - tm_enable = false; - sl_stop_timer = sigc::mem_fun(*this, &CComponentsTimer::stopTimer); - if (interval > 0) - tm_enable = startTimer(); +CComponentsTimer::CComponentsTimer(const int64_t& interval) +{ + tm_thread_name = string(); + tm_interval = interval; + tm_enable = false; + sl_cleanup_timer = sigc::mem_fun(*this, &CComponentsTimer::stopThread); + CNeutrinoApp::getInstance()->OnBeforeRestart.connect(sl_cleanup_timer); + CNeutrinoApp::getInstance()->OnShutDown.connect(sl_cleanup_timer); + + tm_thread = NULL; } CComponentsTimer::~CComponentsTimer() { - stopTimer(); + stopThread(); } -int CComponentsTimer::getSleep(long miliseconds) +void CComponentsTimer::threadCallback(CComponentsTimer *tm) { - struct timespec req, rem; + if (!tm) + return; - if(miliseconds > 999){ - req.tv_sec = (time_t)(miliseconds / 1000); - req.tv_nsec = (miliseconds - ((long)req.tv_sec * 1000)) * 1000000; - }else{ - req.tv_sec = 0; - req.tv_nsec = miliseconds * 1000000; - } + if (tm->OnTimer.empty()) + dprintf(DEBUG_NORMAL," \033[36m[CComponentsTimer] [%s - %d] Signal OnTimer is empty, no callback defined \033[0m\n", __func__, __LINE__); - return nanosleep(&req , &rem); -} + tm->tn = "cc.timer:" + tm->tm_thread_name; + set_threadname(tm->tn.c_str()); -void CComponentsTimer::runSharedTimerAction() -{ - //start loop - tn = "cc:"+name; - set_threadname(tn.c_str()); - while(tm_enable && tm_interval > 0 && !OnTimer.empty()) { - tm_mutex.lock(); - OnTimer(); - if (!tm_enable_nano){ - sleep(tm_interval); - }else{ - //behavior is different on cst hardware - long corr_factor = 1; -#if ! HAVE_COOL_HARDWARE - corr_factor = 10; + dprintf(DEBUG_DEBUG,"\033[32m[CComponentsTimer] thread [%p] [%s] [%s - %d] loop start \033[0m\n", tm->tm_thread, tm->tn.c_str(), __func__, __LINE__); + +#if HAVE_COOL_HARDWARE //time offset + const int64_t MAX_COUNT = tm->tm_interval / 10; +#else + const int64_t MAX_COUNT = tm->tm_interval; #endif - int res = getSleep(tm_interval * corr_factor); - if (res != 0) - dprintf(DEBUG_NORMAL,"\033[33m[CComponentsTimer] [%s - %d] ERROR: returns [%d] \033[0m\n", __func__, __LINE__, res); + int64_t i = 0; + + TIMER_START(); + while(tm->tm_enable) //exit loop handled in destructor + { + if (tm->tm_interval > 0) + { + for (i = 0; i < MAX_COUNT; i++) + i += tm->tm_interval; + i = 0; + + if (!tm->OnTimer.blocked()) + { + tm->OnTimer(); + while (i < MAX_COUNT) + { + if (tm->tm_enable) + this_thread::sleep_for(std::chrono::milliseconds(1)); + i++; + } + } } - tm_mutex.unlock(); } - - if (tm_thread) - stopThread(); + dprintf(DEBUG_DEBUG,"\033[32m[CComponentsTimer] thread [%p] [%s] [%s - %d] loop/callback finished\033[0m\n ", tm->tm_thread, tm->tn.c_str(), __func__, __LINE__); } -//thread handle -void* CComponentsTimer::initThreadAction(void *arg) -{ - CComponentsTimer *timer = static_cast(arg); - timer->runSharedTimerAction(); - - return 0; -} - -//start up running timer with own thread, return true on succses +//start up running timer with own thread void CComponentsTimer::initThread() { - if(!tm_thread) { - void *ptr = static_cast(this); - - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,0); - pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS,0); - - int res = pthread_create (&tm_thread, NULL, initThreadAction, ptr); - - if (res != 0){ - dprintf(DEBUG_NORMAL,"\033[33m[CComponentsTimer] [%s - %d] ERROR! pthread_create\033[0m\n", __func__, __LINE__); - return; - }else - dprintf(DEBUG_DEBUG,"\033[33m[CComponentsTimer] [%s - %d] started thread ID:%ld \033[0m\n", __func__, __LINE__, pthread_self()); - - if (res == 0) - CNeutrinoApp::getInstance()->OnBeforeRestart.connect(sigc::retype_return(sl_stop_timer)); + if (!tm_thread) + { + tm_enable = true; + tm_thread = new std::thread (threadCallback, this); + tm_mutex.lock(); } } void CComponentsTimer::stopThread() { - //ensure disconnecting possible slots - while (!sl_stop_timer.empty()) - sl_stop_timer.disconnect(); + if (tm_thread) { + tm_enable = false; + tm_mutex.unlock(); + tm_thread->join(); + dprintf(DEBUG_DEBUG,"\033[32m[CComponentsTimer] thread [%p] [%s] [%s - %d] joined\033[0m\n", tm_thread, tn.c_str(), __func__, __LINE__); - while(tm_thread) { - int thres = pthread_cancel(tm_thread); - if (thres != 0) - dprintf(DEBUG_NORMAL,"\033[33m[CComponentsTimer] [%s - %d] ERROR! pthread_cancel, error [%d] %s\033[0m\n", __func__, __LINE__, thres, strerror(thres)); - - void* res; - thres = pthread_join(tm_thread, &res); - - if (res != PTHREAD_CANCELED) - dprintf(DEBUG_NORMAL, "\033[33m[CComponentsTimer] [%s - %d] ERROR! pthread_join, thread ID:%ld, error [%d] %s\033[0m\n", __func__, __LINE__, pthread_self(), thres, strerror(thres)); - else - tm_thread = 0; + delete tm_thread; + tm_thread = NULL; + tn.clear(); + dprintf(DEBUG_DEBUG,"\033[32m[CComponentsTimer] thread [%p] [%s] [%s - %d] thread object terminated\033[0m\n", tm_thread, tn.c_str(), __func__, __LINE__); } } -bool CComponentsTimer::startTimer() +void CComponentsTimer::startTimer() { initThread(); - if(tm_thread) - tm_enable = true; - - return tm_enable; } -bool CComponentsTimer::stopTimer() +void CComponentsTimer::stopTimer() { - tm_enable = false; stopThread(); - if(tm_thread == 0){ - if (!OnTimer.empty()) - OnTimer.clear(); - return true; - } - - return false; } -void CComponentsTimer::setTimerInterval(const int& interval, bool is_nano) +bool CComponentsTimer::isRun() const { - if (tm_interval == interval && tm_enable_nano == is_nano) + bool ret = tm_enable && tm_thread; + return ret; +} + +void CComponentsTimer::setTimerInterval(const int64_t& interval) +{ + if (tm_interval == interval) return; - tm_enable_nano = is_nano; + stopTimer(); tm_interval = interval; + startTimer(); } diff --git a/src/gui/components/cc_timer.h b/src/gui/components/cc_timer.h index 08e9895c8..ec7016313 100644 --- a/src/gui/components/cc_timer.h +++ b/src/gui/components/cc_timer.h @@ -3,7 +3,7 @@ Copyright (C) 2001 by Steffen Hehn 'McClean' Classes for generic GUI-related components. - Copyright (C) 2013-2015, Thilo Graf 'dbt' + Copyright (C) 2013-2019, Thilo Graf 'dbt' License: GPL @@ -31,9 +31,8 @@ #include #include -#include -#include -#include +#include +#include /**CComponentsTimer * Member of CComponents. Provides a generic timer class @@ -44,95 +43,83 @@ class CComponentsTimer : public sigc::trackable { private: ///thread - pthread_t tm_thread; + std::thread *tm_thread; + std::mutex tm_mutex; + ///flag to control thread state + bool tm_enable; ///refresh interval in seconds - int tm_interval; - - bool tm_enable_nano; - - ///init function to init shared timer action - static void* initThreadAction(void *arg); + int64_t tm_interval; ///init function to start/stop timer in own thread void initThread(); void stopThread(); ///runs shared timer action provided inside OnTimer() signal - void runSharedTimerAction(); + static void threadCallback(CComponentsTimer *tm); - ///flag to control thread state - bool tm_enable; + sigc::slot sl_cleanup_timer; ///name for the thread - std::string name; + std::string tm_thread_name; std::string tn; - ///mutex for timer - OpenThreads::Mutex tm_mutex; - ///slot for restart signals - sigc::slot0 sl_stop_timer; - ///sleep generated with nanosleep - int getSleep(long miliseconds); public: /**Constructor for timer class * * @param[in] interval - * @li int interval in seconds, default value=1 (1 sec) - * If init value for interval > 0, timer starts immediately - * @li bool default = false as seconds mode, true = nano seconds mode + * @li int64_t interval in miliseconds, default value=1000 ms (1 sec) * @see * setTimerInterval(); */ - CComponentsTimer(const int& interval = 1, bool is_nano = false); + CComponentsTimer(const int64_t& interval = 1000); ~CComponentsTimer(); - /**Starts timer thread - * @return - * bool - * returns true, if timer is running in thread + /**Acivate timer * @see * stopTimer() */ - bool startTimer(); + void startTimer(); - /**Stops timer thread - * @return - * bool - * returns true, if timer thread stopped + /**Disable timer * @see * startTimer() */ - bool stopTimer(); + void stopTimer(); + + /**Cancel timer thread + * @see + * stopTimer() + */ + void cancelTimerThread(){stopThread();} /**get current timer status * @return * bool - * returns true, if timer is running in thread + * returns true, if timer is active * @see * startTimer() * stopTimer() */ - bool isRun() const {return tm_thread;}; + bool isRun() const; /**set timer interval * @param[in] interval - * @li int default interval in seconds, if second parameter = true interval is used as nano seconds - * @li bool default = false as seconds mode, true = nano seconds mode + * @li int64_t default interval in miliseconds * @return * void * @see * tm_interval */ - void setTimerInterval(const int& interval, bool is_nano = false); + void setTimerInterval(const int64_t& interval); /**set thread name * @param[in] thread name * @return * void */ - void setThreadName(const std::string& n) { name = tn = n; } + void setThreadName(const std::string& n) { tm_thread_name = tn = n; } /**Provides a signal handler to receive any function or methode. * Use this in your class where ever you need time controled actions. diff --git a/src/gui/infoclock.cpp b/src/gui/infoclock.cpp index 42ed4a816..323f2e0c5 100644 --- a/src/gui/infoclock.cpp +++ b/src/gui/infoclock.cpp @@ -90,8 +90,8 @@ void CInfoClock::ClearDisplay() { bool run = isRun(); this->kill(); - clearSavedScreen(); - initCCLockItems(); + if (clearSavedScreen()) + initCCLockItems(); //provokes full repaint for next activation, otherwise clock segments only repaints on changed content clear(); if (run) @@ -104,9 +104,12 @@ bool CInfoClock::StartInfoClock() return Start(); } -bool CInfoClock::StopInfoClock() +bool CInfoClock::StopInfoClock(bool exit_thread) { bool ret = Stop(); + if (exit_thread) + if (cl_timer) + cl_timer->cancelTimerThread(); kill(); clear(); @@ -115,6 +118,8 @@ bool CInfoClock::StopInfoClock() bool CInfoClock::enableInfoClock(bool enable) { + std::lock_guard g(cl_mutex); + bool ret = false; if (g_settings.mode_clock) { if (enable) { diff --git a/src/gui/infoclock.h b/src/gui/infoclock.h index e8d48c5fe..ccba2a806 100644 --- a/src/gui/infoclock.h +++ b/src/gui/infoclock.h @@ -38,11 +38,11 @@ class CInfoClock : public CComponentsFrmClock void initCCLockItems(); public: CInfoClock(); - // ~CInfoClock(); // inherited from CComponentsFrmClock + virtual ~CInfoClock(){}; // inherited from CComponentsFrmClock static CInfoClock* getInstance(); bool StartInfoClock(); - bool StopInfoClock(); + bool StopInfoClock(bool exit_thread = false); bool enableInfoClock(bool enable = true); bool disableInfoClock() {return enableInfoClock(false);} void ClearDisplay(); diff --git a/src/gui/test_menu.cpp b/src/gui/test_menu.cpp index 1087f0ac4..08aaedd21 100644 --- a/src/gui/test_menu.cpp +++ b/src/gui/test_menu.cpp @@ -438,7 +438,7 @@ int CTestMenu::exec(CMenuTarget* parent, const std::string &actionKey) if (sq == NULL) sq = new CComponentsShapeSquare (0, 0, 100, 100, NULL, CC_SHADOW_ON, COL_OLIVE, COL_LIGHT_GRAY, COL_RED); - sq->paintBlink(50, true); + sq->paintBlink(500); sleep(10); if (sq->cancelBlink()) @@ -450,7 +450,7 @@ int CTestMenu::exec(CMenuTarget* parent, const std::string &actionKey) if (pic == NULL) pic = new CComponentsPicture (50, 50, 50, 50, ICONSDIR "/btn_pause.png"); - pic->paintBlink(50, true); + pic->paintBlink(500); sleep(10); if (pic->cancelBlink()) @@ -529,7 +529,7 @@ int CTestMenu::exec(CMenuTarget* parent, const std::string &actionKey) ptmp->kill(); } - if (static_cast(form->getCCItem(0))-> paintBlink(50, true)){ + if (static_cast(form->getCCItem(0))-> paintBlink(500)){ ShowHint("Testmenu: Blink","Testmenu: Blinking embedded image ...", 700, 10); } if (form->getCCItem(0)->cancelBlink()){ @@ -560,7 +560,7 @@ int CTestMenu::exec(CMenuTarget* parent, const std::string &actionKey) txt->setText("This is a text for testing textbox", CTextBox::NO_AUTO_LINEBREAK); } - if (txt->paintBlink(50, true)){ + if (txt->paintBlink(50)){ ShowHint("Testmenu: Blink","Testmenu: Blinking text is running ...", 700, 10); } if (txt->cancelBlink()){ @@ -591,7 +591,7 @@ int CTestMenu::exec(CMenuTarget* parent, const std::string &actionKey) text_ext->setFrameThickness(2); } - if (text_ext->paintBlink(50, true)){ + if (text_ext->paintBlink(500)){ ShowHint("Testmenu: Blink","Testmenu: Blinking extended text is running ...", 700, 10); } if (text_ext->cancelBlink()){ @@ -738,7 +738,7 @@ int CTestMenu::exec(CMenuTarget* parent, const std::string &actionKey) CComponentsPicture* img = static_cast(iconform->getCCItem(2)); img->kill(); - if (img->paintBlink(50, true)){ + if (img->paintBlink(500)){ ShowHint("Testmenu: Blink","Testmenu: Blinking image is running ...", 700, 10); } if (img->cancelBlink(true)){ diff --git a/src/gui/widget/hintbox.cpp b/src/gui/widget/hintbox.cpp index 8175bbf06..a434ec7e8 100644 --- a/src/gui/widget/hintbox.cpp +++ b/src/gui/widget/hintbox.cpp @@ -218,14 +218,14 @@ void CHintBox::enableTimeOutBar(bool enable) if(timeout_pb){ timeout_pb->paint0(); - timeout_pb->setValues(timeout_pb->getValue()+1, 100*timeout); + timeout_pb->setValues(timeout_pb->getValue()+1, 10*timeout); }else{ timeout_pb = new CProgressBar(); timeout_pb->setType(CProgressBar::PB_TIMESCALE); timeout_pb->setDimensionsAll(ccw_body->getRealXPos(), ccw_body->getRealYPos(), ccw_body->getWidth(), TIMEOUT_BAR_HEIGHT); - timeout_pb->setValues(0, 100*timeout); + timeout_pb->setValues(0, timeout); if (!timeout_pb_timer) { - timeout_pb_timer = new CComponentsTimer(1, true); + timeout_pb_timer = new CComponentsTimer(100); const string tn = cc_item_type.name + ":timeout_bar:"; timeout_pb_timer->setThreadName(tn); }