diff --git a/src/proc/play/dummy-player-service.cpp b/src/proc/play/dummy-player-service.cpp index 865aa18f4..3fea947e3 100644 --- a/src/proc/play/dummy-player-service.cpp +++ b/src/proc/play/dummy-player-service.cpp @@ -23,6 +23,7 @@ #include "proc/play/dummy-player-service.hpp" #include "proc/play/dummy-image-generator.hpp" +#include "proc/play/tick-service.hpp" #include "lib/singleton.hpp" extern "C" { @@ -31,9 +32,11 @@ extern "C" { #include #include +#include #include + namespace proc { namespace play{ @@ -41,6 +44,7 @@ namespace proc { using lumiera::Subsys; using std::auto_ptr; using boost::scoped_ptr; + using std::tr1::bind; namespace { // hidden local details of the service implementation.... @@ -292,7 +296,7 @@ namespace proc { ProcessImpl::ProcessImpl() - : fps_(0), play_(false), imageGen_(0) + : fps_(0), play_(false), imageGen_(0), tick_(new TickService (bind (ProcessImpl::doFrame, this))) { } @@ -319,12 +323,16 @@ namespace proc { { REQUIRE (fps==0 || fps_==0 ); REQUIRE (fps==0 || !play_ ); + REQUIRE (tick_) fps_ = fps; play_ = (fps != 0); if (play_) imageGen_.reset(new DummyImageGenerator(fps)); + + // callbacks with given frequency, starting now + tick_->activate(fps); } @@ -333,6 +341,7 @@ namespace proc { ProcessImpl::doPlay(bool yes) { REQUIRE (isActive()); + tick_->activate (yes? fps_:0); play_ = yes; } diff --git a/src/proc/play/dummy-player-service.hpp b/src/proc/play/dummy-player-service.hpp index 92c4d27ca..a1856c745 100644 --- a/src/proc/play/dummy-player-service.hpp +++ b/src/proc/play/dummy-player-service.hpp @@ -56,6 +56,7 @@ namespace proc { class DummyImageGenerator; + class TickService; /******************************************************************** @@ -74,6 +75,7 @@ namespace proc { bool play_; boost::scoped_ptr imageGen_; + boost::scoped_ptr tick_; public: diff --git a/src/proc/play/tick-service.hpp b/src/proc/play/tick-service.hpp new file mode 100644 index 000000000..84c85af7c --- /dev/null +++ b/src/proc/play/tick-service.hpp @@ -0,0 +1,115 @@ +/* + TICK-SERVICE.hpp - issuing timed callbacks + + Copyright (C) Lumiera.org + 2009, Joel Holdsworth , + Hermann Vosseler + + 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. + +*/ + +/** @file tick-service.hpp + ** A timer service invoking a given callback periodically. + ** This is a rough preliminary implementation as of 1/2009. We use it to + ** drive the frame "creation" of a player dummy (the render engine is not + ** ready yet). The intention is to make this a real service later on, which + ** might consolidate and sync various ongoing output processes to a common + ** beat, which it implements by precision posix timers. Probably then this + ** service will become part of the backend, or rely on a timing service. + ** + ** @see proc::play::DummyPlayerService + ** + */ + + +#ifndef PROC_PLAY_TICKSERVICE_H +#define PROC_PLAY_TICKSERVICE_H + + +#include "backend/thread-wrapper.hpp" + +#include + + +namespace proc { + namespace play { + + + /************************************************************ + * Tick generating service for a periodic callback, + * with adjustable frequency. Quick'n dirty implementation! + */ + class TickService + : backend::Thread + { + typedef function Tick; + volatile uint timespan_; + + /** poll interval for new settings in wait state */ + static const uint POLL_TIMEOUT = 1000; + + public: + TickService (Tick& callback) + : Thread("Tick generator (dummy)", + bind (&TickService::timerLoop, this, callback)) + { } + + ~TickService () + { + uint curr_tick = timespan_; + timespan_ = 0; + usleep (curr_tick); ////TODO actually should wait for timer thread termination + } + + + /** set the periodic timer to run with a given frequency, + * starting \em now. Well, not actually now, but at the next + * opportunity. It should be \em now, but this implementation + * is sloppy! setting fps==0 halts (pauses) the timer. + */ + void activate (uint fps) + { + REQUIRE ( 0==fps + || 1000000/fps < std::numeric_limits::max() + && 1000000/fps > POLL_TIMEOUT); + if (fps) + timespan_ = 1000000/fps; // microseconds per tick + else + timespan_ = POLL_TIMEOUT; + } + + + private: + void timerLoop(Tick periodicFun) + { + timespan_ = POLL_TIMEOUT; + while (0 < timespan_) + { + if (timespan_ > POLL_TIMEOUT) + periodicFun(); + + usleep (timespan_); + } } + }; + + + + + } // namespace play + +} // namespace proc +#endif // PROC_PLAY_TICKSERVICE_H +