diff --git a/src/common/interfaceproxy.cpp b/src/common/interfaceproxy.cpp index ea838e701..8390a6609 100644 --- a/src/common/interfaceproxy.cpp +++ b/src/common/interfaceproxy.cpp @@ -30,10 +30,10 @@ using util::cStr; namespace lumiera { namespace facade { - - + + LUMIERA_ERROR_DEFINE (FACADE_LIFECYCLE, "facade interface currently not accessible"); - + template class Holder; @@ -95,11 +95,11 @@ namespace lumiera { } // namespace facade } // namespace lumiera - - + + /* ==================== GuiNotification =================================== */ #include "include/guinotification-facade.h" @@ -115,7 +115,7 @@ namespace gui { namespace lumiera { namespace facade { - + typedef InstanceHandle< LUMIERA_INTERFACE_INAME(lumieraorg_GuiNotification, 0) , gui::GuiNotification > Handle_GuiNotification; @@ -132,7 +132,7 @@ namespace lumiera { public: - Proxy (IHandle const& iha) : THolder(iha) {} + Proxy (IHandle const& iha) : THolder(iha) {} }; @@ -142,12 +142,59 @@ namespace lumiera { } // namespace facade } // namespace lumiera - - - - + + + + + + /* ==================== gui::Display ====================================== */ +#include "include/display-facade.h" + +namespace lumiera { + /** storage for the facade proxy factory used by client code to invoke through the interface */ + lumiera::facade::Accessor Display::facade; + +} // namespace lumiera + + + +namespace lumiera { + namespace facade { + + typedef InstanceHandle< LUMIERA_INTERFACE_INAME(lumieraorg_Display, 0) + , lumiera::Display + > Handle_Display; + + + template<> + class Proxy + : public Holder + { + //----Proxy-Implementation-of-lumiera::Display-------- + + void displayInfo (string const& text) { _i_.displayInfo (cStr(text)); } + void triggerGuiShutdown (string const& cause) { _i_.triggerGuiShutdown (cStr(cause)); } + + + public: + Proxy (IHandle const& iha) : THolder(iha) {} + }; + + + template void openProxy (Handle_Display const&); + template void closeProxy (void); + + } // namespace facade + +} // namespace lumiera + + + + + + /* ==================== DummyPlayer ======================================= */ #include "proc/play/dummy-player-service.hpp" @@ -163,7 +210,7 @@ namespace proc { namespace lumiera { namespace facade { - + typedef lumiera::InstanceHandle< LUMIERA_INTERFACE_INAME(lumieraorg_DummyPlayer, 0) , proc::play::DummyPlayer > Handle_DummyPlayer; @@ -184,8 +231,8 @@ namespace lumiera { * and thus leaves us only with one level of indirection, * irrespective if using the C or C++ interface. */ - Process start() - { + Process start() + { ProcessImpl* pP = static_cast (_i_.startPlay()); if (!pP) @@ -197,7 +244,7 @@ namespace lumiera { public: - Proxy (IHandle const& iha) : THolder(iha) {} + Proxy (IHandle const& iha) : THolder(iha) {} }; diff --git a/src/gui/display-service.cpp b/src/gui/display-service.cpp new file mode 100644 index 000000000..68fe45b25 --- /dev/null +++ b/src/gui/display-service.cpp @@ -0,0 +1,310 @@ +/* + DisplayService - service providing access to a display for outputting frames + + Copyright (C) Lumiera.org + 2009, 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. + +* *****************************************************/ + + +#include "gui/display-service.hpp" +//#include "lib/singleton.hpp" + +extern "C" { +#include "common/interfacedescriptor.h" +} + +#include +//#include +//#include + + +namespace gui { + + using std::string; +// using boost::scoped_ptr; + + + namespace { // hidden local details of the service implementation.... + + + + /* ================== define an lumieraorg_GuiNotification instance ======================= */ + + LUMIERA_INTERFACE_INSTANCE (lumieraorg_interfacedescriptor, 0 + ,lumieraorg_DisplayFacade_descriptor + , NULL, NULL, NULL + , LUMIERA_INTERFACE_INLINE (name, LUIDGEN, + const char*, (LumieraInterface ifa), + { (void)ifa; return "Display"; } + ) + , LUMIERA_INTERFACE_INLINE (brief, LUIDGEN, + const char*, (LumieraInterface ifa), + { (void)ifa; return "UI Interface: service for outputting frames to a viewer or display"; } + ) + , LUMIERA_INTERFACE_INLINE (homepage, LUIDGEN, + const char*, (LumieraInterface ifa), + { (void)ifa; return "http://www.lumiera.org/develompent.html" ;} + ) + , LUMIERA_INTERFACE_INLINE (version, LUIDGEN, + const char*, (LumieraInterface ifa), + { (void)ifa; return "0.1~pre"; } + ) + , LUMIERA_INTERFACE_INLINE (author, LUIDGEN, + const char*, (LumieraInterface ifa), + { (void)ifa; return "Hermann Vosseler"; } + ) + , LUMIERA_INTERFACE_INLINE (email, LUIDGEN, + const char*, (LumieraInterface ifa), + { (void)ifa; return "Ichthyostega@web.de"; } + ) + , LUMIERA_INTERFACE_INLINE (copyright, LUIDGEN, + const char*, (LumieraInterface ifa), + { + (void)ifa; + return + "Copyright (C) Lumiera.org\n" + " 2009 Hermann Vosseler "; + } + ) + , LUMIERA_INTERFACE_INLINE (license, LUIDGEN, + const char*, (LumieraInterface ifa), + { + (void)ifa; + return + "This program is free software; you can redistribute it and/or modify\n" + "it under the terms of the GNU General Public License as published by\n" + "the Free Software Foundation; either version 2 of the License, or\n" + "(at your option) any later version.\n" + "\n" + "This program is distributed in the hope that it will be useful,\n" + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + "GNU General Public License for more details.\n" + "\n" + "You should have received a copy of the GNU General Public License\n" + "along with this program; if not, write to the Free Software\n" + "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA"; + } + ) + , LUMIERA_INTERFACE_INLINE (state, LUIDGEN, + int, (LumieraInterface ifa), + {(void)ifa; return LUMIERA_INTERFACE_EXPERIMENTAL; } + ) + , LUMIERA_INTERFACE_INLINE (versioncmp, LUIDGEN, + int, (const char* a, const char* b), + {return 0;} ////////////////////////////////////////////TODO define version ordering + ) + ); + + + + + + using lumiera::facade::LUMIERA_ERROR_FACADE_LIFECYCLE; + typedef lib::SingletonRef::Accessor InstanceRef; + + InstanceRef _instance; ///< a backdoor for the C Language impl to access the actual DummyPlayer implementation... + + typedef ProcessImpl* ProcP; ///////////////TODO + + + LUMIERA_INTERFACE_INSTANCE (lumieraorg_Display, 0 + ,lumieraorg_DisplayService + , LUMIERA_INTERFACE_REF(lumieraorg_interfacedescriptor, 0, lumieraorg_DisplayFacade_descriptor) + , NULL /* on open */ + , NULL /* on close */ + , LUMIERA_INTERFACE_INLINE (startPlay, LUIDGEN, + LumieraPlayProcess, (void), + { + if (!_instance) + { + lumiera_error_set(LUMIERA_ERROR_FACADE_LIFECYCLE, 0); + return 0; + } + + return static_cast (_instance->start()); + } + ) + , LUMIERA_INTERFACE_INLINE (togglePlay, LUIDGEN, + void, (LumieraPlayProcess handle, bool doPlay), + { + if (!_instance) + { + lumiera_error_set(LUMIERA_ERROR_FACADE_LIFECYCLE, 0); + return; + } + + REQUIRE (handle); + ProcP proc = static_cast (handle); + + proc->doPlay(doPlay); + } + ) + , LUMIERA_INTERFACE_INLINE (terminate, LUIDGEN, + void, (LumieraPlayProcess handle), + { + if (!_instance) + { + lumiera_error_set(LUMIERA_ERROR_FACADE_LIFECYCLE, 0); + return; + } + + REQUIRE (handle); + ProcP proc = static_cast (handle); + + ProcessImpl::terminate (proc); + } + ) + , LUMIERA_INTERFACE_INLINE (getFrame, LUIDGEN, + void *, (LumieraPlayProcess handle), + { + //skipping full checks for performance reasons + REQUIRE (_instance && !lumiera_error_peek()); + + REQUIRE (handle); + ProcP proc = static_cast (handle); + + return const_cast (proc->getFrame()); + } + ) + ); + + + + + } // (End) hidden service impl details + + + + + DisplayService::DisplayService() + : error_("") + , implInstance_(this,_instance) + , serviceInstance_( LUMIERA_INTERFACE_REF (lumieraorg_Display, 0, lumieraorg_DisplayService)) + { + INFO (progress, "Display Facade opened."); + } + + + + + /** @par implementation note + * A new process (implementation) is created, configured + * and started here. This may include spawning a thread or + * allocating a timer. The newly created process is self-contained + * and will be just handed out, without caring for its lifecycle. + * If client code accesses this function via the plain C interface, + * the client is responsible for terminating this process, whereas + * when using the C++ interface, you'll get a Handle object which + * manages the lifecycle automatically. + */ + ProcessImpl* + DisplayService::start() + { + auto_ptr newProcess (new ProcessImpl); + + REQUIRE (!newProcess->isActive()); + newProcess->setRate(25); + + return newProcess.release(); + } + + + /* === Forwarding functions on the Process handle === */ + + void DummyPlayer::Process::play(bool yes) { impl().doPlay(yes); } + void* const DummyPlayer::Process::getFrame() { return impl().getFrame(); } + + + + + + /* === Process Implementation === */ + + + ProcessImpl::ProcessImpl() + : fps_(0), play_(false), imageGen_(0) + { } + + + DummyPlayer::Process + ProcessImpl::createHandle() + { + DummyPlayer::Process handle; + handle.activate(this, &terminate); + return handle; + } + + + void + ProcessImpl::terminate (ProcessImpl* process) + { + if (process) + delete process; + } + + + + void + ProcessImpl::setRate (uint fps) + { + REQUIRE (fps==0 || fps_==0 ); + REQUIRE (fps==0 || !play_ ); + + fps_ = fps; + play_ = (fps != 0); + + if (play_) + imageGen_.reset(new DummyImageGenerator(fps)); + } + + + + void + ProcessImpl::doPlay(bool yes) + { + REQUIRE (isActive()); + play_ = yes; + } + + + + void* const + ProcessImpl::getFrame() + { + REQUIRE (isActive()); + ASSERT (imageGen_); + + if (play_) + return imageGen_->next(); + else + return imageGen_->current(); + } + + + + + + + + // emit the vtable here into this translation unit within liblumieraproc.so ... + DummyPlayer::~DummyPlayer() { } + + + +} // namespace proc diff --git a/src/gui/display-service.hpp b/src/gui/display-service.hpp new file mode 100644 index 000000000..4d11768cf --- /dev/null +++ b/src/gui/display-service.hpp @@ -0,0 +1,125 @@ +/* + DISPLAY-SERVICE.hpp - service providing access to a display for outputting frames + + Copyright (C) Lumiera.org + 2009, 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 display-service.hpp + ** A public service provided by the GUI, implementing the gui::GuiNotification facade interface. + ** The purpose of this service is to push state update and notification of events from the lower + ** layers into the Lumiera GUI. Typically, this happens asynchronously and triggered by events + ** within the lower layers. + ** + ** This service is the implementation of a layer separation facade interface. Clients should use + ** proc::play::DummyPlayer#facade to access this service. This header defines the interface used + ** to \em provide this service, not to access it. + ** + ** @see gui::GuiFacade + ** @see guifacade.cpp starting this service + */ + + +#ifndef GUI_DISPLAY_SERVICE_H +#define GUI_DISPLAY_SERVICE_H + + +#include "include/display-facade.h" +#include "common/instancehandle.hpp" +#include "lib/singleton-ref.hpp" + +#include +#include +#include + + +namespace gui { + + using std::string; + using lumiera::Display; + + +// class DummyImageGenerator; + + + /******************************************************************** + * 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. + */ + class DisplayerSlot + : public Display::Displayer, + boost::noncopyable + { + + public: + DisplayerSlot() ; + + /* Implementation-level API to be used by DisplayService */ + + }; + + + + /****************************************************** + * Actual implementation of the DisplayService. + * Creating an instance of this class automatically + * registers the interface lumieraorg_Display with + * the Lumiera Interface/Plugin system and creates + * a forwarding proxy within the application core to + * route calls through this interface. + * \par + * In addition to the Display interface, this class + * implements an additional service for the GUI, + * allowing actually to set up display slots, which + * then can be handed out to client code in the + * course of the play process for outputting frames. + */ + class DisplayService + : boost::noncopyable + { + + string error_; + + + /* === Interface Lifecycle === */ + + typedef lumiera::InstanceHandle< LUMIERA_INTERFACE_INAME(lumieraorg_Display, 0) + , lumiera::Display + > ServiceInstanceHandle; + + lib::SingletonRef implInstance_; + ServiceInstanceHandle serviceInstance_; + + public: + DisplayService(); + + ~DummyPlayerService() { } ///TODO + + + + /** allocate and lock the given display slot */ + Display::Displayer getHandle(LumieraDisplaySlot) =0; + + }; + + + + +} // namespace gui +#endif diff --git a/src/gui/notification-service.cpp b/src/gui/notification-service.cpp index 4138129ba..080d1461d 100644 --- a/src/gui/notification-service.cpp +++ b/src/gui/notification-service.cpp @@ -140,7 +140,7 @@ namespace gui { LUMIERA_INTERFACE_INSTANCE (lumieraorg_GuiNotification, 0 - ,lumieraorg_GuiNotificationFacade + ,lumieraorg_GuiNotificationService , LUMIERA_INTERFACE_REF(lumieraorg_interfacedescriptor, 0, lumieraorg_GuiNotificationFacade_descriptor) , NULL /* on open */ , NULL /* on close */ @@ -171,7 +171,7 @@ namespace gui { NotificationService::NotificationService () : implInstance_(this,_instance), - serviceInstance_( LUMIERA_INTERFACE_REF (lumieraorg_GuiNotification, 0,lumieraorg_GuiNotificationFacade)) + serviceInstance_( LUMIERA_INTERFACE_REF (lumieraorg_GuiNotification, 0,lumieraorg_GuiNotificationService)) { INFO (gui, "GuiNotification Facade opened."); } diff --git a/src/include/display-facade.h b/src/include/display-facade.h index 7375ffce2..2e2261a55 100644 --- a/src/include/display-facade.h +++ b/src/include/display-facade.h @@ -98,6 +98,8 @@ namespace lumiera { class Display { public: + /** get an implementation instance of this service */ + static lumiera::facade::Accessor facade; /** diff --git a/src/proc/play/dummy-player-service.cpp b/src/proc/play/dummy-player-service.cpp index 27f78559f..865aa18f4 100644 --- a/src/proc/play/dummy-player-service.cpp +++ b/src/proc/play/dummy-player-service.cpp @@ -177,7 +177,7 @@ namespace proc { LUMIERA_INTERFACE_INSTANCE (lumieraorg_DummyPlayer, 0 - ,lumieraorg_DummyPlayerFacade + ,lumieraorg_DummyPlayerService , LUMIERA_INTERFACE_REF(lumieraorg_interfacedescriptor, 0, lumieraorg_DummyPlayerFacade_descriptor) , NULL /* on open */ , NULL /* on close */ @@ -249,7 +249,7 @@ namespace proc { : error_("") , notifyTermination_(terminationHandle) , implInstance_(this,_instance) - , serviceInstance_( LUMIERA_INTERFACE_REF (lumieraorg_DummyPlayer, 0, lumieraorg_DummyPlayerFacade)) + , serviceInstance_( LUMIERA_INTERFACE_REF (lumieraorg_DummyPlayer, 0, lumieraorg_DummyPlayerService)) { INFO (progress, "DummyPlayer Facade opened."); }