diff --git a/src/gui/controller/playback-controller.cpp b/src/gui/controller/playback-controller.cpp index 27832ec32..cc7881393 100644 --- a/src/gui/controller/playback-controller.cpp +++ b/src/gui/controller/playback-controller.cpp @@ -20,13 +20,18 @@ * *****************************************************/ + #include "gui/controller/playback-controller.hpp" +#include "gui/display-service.hpp" #include "lib/error.hpp" + #include namespace gui { namespace controller { + + PlaybackController::PlaybackController() : playing(false) { } @@ -75,45 +80,18 @@ PlaybackController::is_playing() return playing; } -//dispatcher.connect(sigc::mem_fun(this, &PlaybackController::on_frame)); void -PlaybackController::attach_viewer( - const sigc::slot& on_frame) +PlaybackController::attach_viewer (FrameDestination const& outputDestination) { - frame_signal.connect(on_frame); -} - - -/* -void -PlaybackController::pull_frame() -{ - REQUIRE (is_playing()); - REQUIRE (playHandle); + /////////////////////TODO: unsolved problem: how to access the display-service from /within/ the GUI?? + DisplayService& displayService = do_something_magic(); - unsigned char * newBuffer = reinterpret_cast (playHandle.getFrame()); - - if (newBuffer != currentBuffer) - { - currentBuffer = newBuffer; - dispatcher.emit(); - } - else - { - TRACE (render, "frame dropped?"); - } + viewerHandle_ = displayService.setUp (outputDestination); } -*/ -void -PlaybackController::on_frame() -{ - frame_signal.emit(currentBuffer); -} - } // namespace controller } // namespace gui diff --git a/src/gui/controller/playback-controller.hpp b/src/gui/controller/playback-controller.hpp index abe1340c5..5b3b598ae 100644 --- a/src/gui/controller/playback-controller.hpp +++ b/src/gui/controller/playback-controller.hpp @@ -27,8 +27,8 @@ #define PLAYBACK_CONTROLLER_HPP #include "include/dummy-player-facade.h" +#include "include/display-facade.h" -#include #include #include @@ -63,13 +63,10 @@ private: volatile bool playing; - Glib::Dispatcher dispatcher; - proc::play::DummyPlayer::Process playHandle; - unsigned char * currentBuffer; + LumieraDisplaySlot viewerHandle_; - sigc::signal frame_signal; }; } // namespace controller diff --git a/src/gui/display-service.cpp b/src/gui/display-service.cpp index 68fe45b25..07205fcb7 100644 --- a/src/gui/display-service.cpp +++ b/src/gui/display-service.cpp @@ -234,12 +234,22 @@ namespace gui { - /* === Process Implementation === */ + /* === DisplayerSlot Implementation === */ - ProcessImpl::ProcessImpl() - : fps_(0), play_(false), imageGen_(0) - { } + DisplayerSlot::DisplayerSlot (FrameDestination const& outputDestination) + : currBuffer_(0) + { + hasFrame_.connect (outputDestination); + dispatcher_.connect (sigc::mem_fun (this, &DisplayerSlot::displayCurrentFrame)); + } + + + void + DisplayerSlot::displayCurrentFrame() + { + hasFrame_.emit (currentBuffer_); + } DummyPlayer::Process diff --git a/src/gui/display-service.hpp b/src/gui/display-service.hpp index 4d11768cf..ce2027091 100644 --- a/src/gui/display-service.hpp +++ b/src/gui/display-service.hpp @@ -43,37 +43,60 @@ #include "common/instancehandle.hpp" #include "lib/singleton-ref.hpp" +#include #include #include #include +#include namespace gui { - + using std::string; + using std::vector; + using boost::scoped_ptr; using lumiera::Display; + using Glib::Dispatcher; -// class DummyImageGenerator; + typedef sigc::slot FrameDestination; + typedef sigc::signal FrameSignal; + /******************************************************************** * Actual implementation of a single displayer slot. Internally, - * it is connected* via the Glib::Dispatcher to output frames - * to a viewer widget executing within the GTK event thread. + * it is connected via the Glib::Dispatcher for outputting frames + * to a viewer widget, which executes within the GTK event thread. + * @note must be created from the GTK event thread. */ class DisplayerSlot - : public Display::Displayer, - boost::noncopyable + : boost::noncopyable { + Dispatcher dispatcher_; + FrameSignal hasFrame_; + + LumieraDisplayFrame currBuffer_; + public: - DisplayerSlot() ; + DisplayerSlot (FrameDestination const&) ; /* Implementation-level API to be used by DisplayService */ + /** receive a frame to be displayed */ + inline void put (LumieraDisplayFrame); + + + private: + /** internal: activated via Dispatcher + * and running in GTK main thread */ + void displayCurrentFrame(); + }; + typedef vector > DisplayerTab; + /****************************************************** @@ -95,6 +118,7 @@ namespace gui { { string error_; + DisplayerTab slots_; /* === Interface Lifecycle === */ @@ -106,20 +130,35 @@ namespace gui { lib::SingletonRef implInstance_; ServiceInstanceHandle serviceInstance_; + public: DisplayService(); ~DummyPlayerService() { } ///TODO - - /** allocate and lock the given display slot */ - Display::Displayer getHandle(LumieraDisplaySlot) =0; + LumieraDisplaySlot setUp (FrameDestination const&); }; + void + DisplayerSlot::put(LumieraDisplayFrame newFrame) + { + if (newFrame != currBuffer_) + { + currBuffer_ = newFrame; + dispatcher_.emit(); + } + else + { + TRACE (render, "frame dropped?"); + } + } + + + } // namespace gui #endif diff --git a/src/gui/guistart.cpp b/src/gui/guistart.cpp index bb6793ecc..1aa7d9782 100644 --- a/src/gui/guistart.cpp +++ b/src/gui/guistart.cpp @@ -48,7 +48,7 @@ #include // need to include this to prevent errors when libintl.h defines textdomain (because gtk-lumiera removes the def when ENABLE_NLS isn't defined) #include "gui/gtk-lumiera.hpp" // need to include this before nobugcfg.h, because types.h from GTK tries to shaddow the ERROR macro from windows, which kills nobug's ERROR macro -// TODO not needed? #include "include/logging.h" + #include "lib/error.hpp" #include "gui/guifacade.hpp" #include "gui/notification-service.hpp" @@ -110,7 +110,7 @@ namespace gui { gui::application().main(argc, argv); // execute the GTK Event Loop if (!lumiera_error_peek()) - return; + return; // all went well, normal shutdown } catch (lumiera::Error& problem) { @@ -149,7 +149,7 @@ namespace gui { if (!lumiera_error_peek()) LUMIERA_ERROR_SET (gui, STATE, "unexpected error when starting the GUI thread"); return false; - } + } // note: lumiera_error state remains set } } // namespace gui diff --git a/src/include/display-facade.h b/src/include/display-facade.h index 2e2261a55..eb7f37f09 100644 --- a/src/include/display-facade.h +++ b/src/include/display-facade.h @@ -47,11 +47,7 @@ struct lumiera_displaySlot_struct typedef struct lumiera_displaySlot_struct LumieraDisplaySlot; ///< value semantics -struct lumiera_displayFrame_struct - { - void* const buff_; - }; -typedef struct lumiera_displayFrame_struct LumieraDisplayFrame; +typedef unsigned char * LumieraDisplayFrame; @@ -105,15 +101,15 @@ namespace lumiera { /** * Functor for pushing frames to the display */ - typedef function Displayer; + typedef function Sink; /** allocate an already existing display/viewer for output * @return a functor representing the frame sink */ - virtual Displayer getHandle(LumieraDisplaySlot) =0; + virtual Sink getHandle(LumieraDisplaySlot) =0; - virtual ~DummyPlayer(); + virtual ~Display(); }; diff --git a/src/proc/play/dummy-player-service.cpp b/src/proc/play/dummy-player-service.cpp index 3fea947e3..c4bd9e92b 100644 --- a/src/proc/play/dummy-player-service.cpp +++ b/src/proc/play/dummy-player-service.cpp @@ -296,7 +296,10 @@ namespace proc { ProcessImpl::ProcessImpl() - : fps_(0), play_(false), imageGen_(0), tick_(new TickService (bind (ProcessImpl::doFrame, this))) + : fps_(0) + , play_(false) + , imageGen_(0) + , tick_(new TickService (bind (ProcessImpl::doFrame, this))) { }