diff options
author | Tim Mayberry <mojofunk@gmail.com> | 2014-12-25 20:44:06 +0700 |
---|---|---|
committer | Tim Mayberry <mojofunk@gmail.com> | 2015-01-01 18:59:01 +0700 |
commit | b959b3fb87f4e3b740d3ad64024d1c8c3eb0aebc (patch) | |
tree | 17f9cdc4eea4a61a99bdd0499e64216cc7ee8850 /libs | |
parent | 770c190ccff8e6096e0bff9c78b42633020f72be (diff) |
Add PBD::Timer/StandardTimer/BlinkTimer classes for convenient timeouts
Diffstat (limited to 'libs')
-rw-r--r-- | libs/pbd/pbd/timer.h | 121 | ||||
-rw-r--r-- | libs/pbd/timer.cc | 156 | ||||
-rw-r--r-- | libs/pbd/wscript | 1 |
3 files changed, 278 insertions, 0 deletions
diff --git a/libs/pbd/pbd/timer.h b/libs/pbd/pbd/timer.h new file mode 100644 index 0000000000..4c80d9d088 --- /dev/null +++ b/libs/pbd/pbd/timer.h @@ -0,0 +1,121 @@ +/* + Copyright (C) 2014 Tim Mayberry + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __libpbd_timer_h__ +#define __libpbd_timer_h__ + +#include <sigc++/signal.h> + +#include <glibmm/main.h> + +#include "pbd/libpbd_visibility.h" + +namespace PBD { + +/** + * The Timer class is a wrapper around Glib TimeoutSources + * The Timer will start automatically when the first connection + * is made and stop when the last callback is disconnected. + */ +class LIBPBD_API Timer +{ +public: + + Timer (unsigned int interval, + const Glib::RefPtr<Glib::MainContext>& main_context); + + unsigned int get_interval () const; + + void set_interval (unsigned int new_interval); + + virtual unsigned int connection_count () const = 0; + +protected: + + virtual ~Timer() { } + + void start (); + + void stop (); + + virtual bool on_elapsed () = 0; + +private: + + Timer(const Timer&); + Timer& operator= (const Timer&); + +private: + + static gboolean _timeout_handler (void *data); + + bool timeout_handler (); + + GSource* m_timeout_source; + + unsigned int m_timeout_interval; + + const Glib::RefPtr<Glib::MainContext> m_main_context; + +}; + +class LIBPBD_API StandardTimer : public Timer +{ +public: + + StandardTimer (unsigned int interval, + const Glib::RefPtr<Glib::MainContext>& main_context = Glib::MainContext::get_default()); + + sigc::connection connect (const sigc::slot<void>& slot); + + virtual unsigned int connection_count () const + { return m_signal.size (); } + +protected: + + virtual bool on_elapsed (); + + sigc::signal<void> m_signal; + +}; + +class LIBPBD_API BlinkTimer : public Timer +{ +public: + + BlinkTimer (unsigned int interval, + const Glib::RefPtr<Glib::MainContext>& main_context = Glib::MainContext::get_default()); + + + sigc::connection connect (const sigc::slot<void, bool>& slot); + + virtual unsigned int connection_count () const + { return m_blink_signal.size (); } + +protected: + + virtual bool on_elapsed (); + + sigc::signal<void, bool> m_blink_signal; + +}; + +} // namespace PBD + +#endif // __libpbd_timer_h__ diff --git a/libs/pbd/timer.cc b/libs/pbd/timer.cc new file mode 100644 index 0000000000..662c7ddc38 --- /dev/null +++ b/libs/pbd/timer.cc @@ -0,0 +1,156 @@ +/* + Copyright (C) 2014 Tim Mayberry + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "pbd/timer.h" + +namespace PBD { + +Timer::Timer (unsigned int interval, + const Glib::RefPtr<Glib::MainContext>& main_context) + : m_timeout_source(NULL) + , m_timeout_interval(interval) + , m_main_context(main_context) +{ + +} + +gboolean +Timer::_timeout_handler (void *data) +{ + Timer *const timer = static_cast<Timer*>(data); + return timer->timeout_handler(); +} + +unsigned int +Timer::get_interval () const +{ + return m_timeout_interval; +} + +void +Timer::set_interval (unsigned int new_interval) +{ + if (new_interval == m_timeout_interval) return; + + stop (); + m_timeout_interval = new_interval; + start (); +} + +/** + * We don't use Glibmm::TimeoutSource::create() here as contrary + * to the documentation, SignalTimeout::connect and manually + * adding a TimeoutSource to a GMainContext are not equivalent. + * + * SignalTimeout::connect is the equivalent of g_timeout_add in + * terms off callback timing but TimeoutSource tries to adjust + * the timeout based on the time elapsed since the last timeout. + * + * On Windows with a high frequency timeout(40ms) this causes a + * small but noticable increase in CPU Usage. + */ +void +Timer::start() +{ + if (m_timeout_source) return; + + m_timeout_source = g_timeout_source_new (m_timeout_interval); + +#if 0 // support priorites? + if(priority != G_PRIORITY_DEFAULT) + g_source_set_priority(source, priority); +#endif + + g_source_set_callback (m_timeout_source, &Timer::_timeout_handler, this, NULL); + + g_source_attach (m_timeout_source, m_main_context->gobj()); + // GMainContext also holds a reference +} + +void +Timer::stop() +{ + if (m_timeout_source) { + g_source_destroy (m_timeout_source); + g_source_unref (m_timeout_source); + m_timeout_source = NULL; + } +} + +bool +Timer::timeout_handler() +{ + return on_elapsed(); +} + +StandardTimer::StandardTimer(unsigned int interval, + const Glib::RefPtr<Glib::MainContext>& main_context) + : Timer(interval, main_context) +{ } + +sigc::connection +StandardTimer::connect(const sigc::slot<void>& slot) +{ + if(m_signal.size() == 0) { start(); } + + return m_signal.connect(slot); +} + +bool +StandardTimer::on_elapsed() +{ + if(m_signal.size() == 0) + { + stop(); + return false; + } + + m_signal(); + return true; +} + +BlinkTimer::BlinkTimer(unsigned int interval, + const Glib::RefPtr<Glib::MainContext>& main_context) + : Timer(interval, main_context) +{ } + +sigc::connection +BlinkTimer::connect(const sigc::slot<void, bool>& slot) +{ + if(m_blink_signal.size() == 0) { start(); } + + return m_blink_signal.connect(slot); +} + +bool +BlinkTimer::on_elapsed() +{ + static bool blink_on = false; + + if(m_blink_signal.size() == 0) + { + stop(); + return false; + } + + m_blink_signal(blink_on = !blink_on); + return true; +} + +} // namespace PBD diff --git a/libs/pbd/wscript b/libs/pbd/wscript index 1535f6446e..0c8ad918f7 100644 --- a/libs/pbd/wscript +++ b/libs/pbd/wscript @@ -75,6 +75,7 @@ libpbd_sources = [ 'strsplit.cc', 'system_exec.cc', 'textreceiver.cc', + 'timer.cc', 'timing.cc', 'transmitter.cc', 'undo.cc', |