From feebc502e50002cb02c739131eb25f3b7b163785 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 7 Dec 2008 08:46:44 +0100 Subject: [PATCH] implementation of GuiStarterPlugin --- SConstruct | 6 +- src/common/error.cpp | 4 +- src/gui/guifacade.hpp | 33 ++++- src/gui/guinotificationfacade.cpp | 4 +- src/include/guinotificationfacade.h | 4 +- src/lumiera/guifacade.cpp | 54 ++++---- src/lumiera/instancehandle.hpp | 4 +- src/plugin/guistarterplugin.cpp | 191 ++++++++++++++++++++++++++++ src/plugin/helloplugin.c | 12 -- tests/plugin/example_plugin.c | 23 ++++ 10 files changed, 275 insertions(+), 60 deletions(-) create mode 100644 src/plugin/guistarterplugin.cpp delete mode 100644 src/plugin/helloplugin.c diff --git a/SConstruct b/SConstruct index 03c0723a6..96b09bc1b 100644 --- a/SConstruct +++ b/SConstruct @@ -141,8 +141,8 @@ def defineCmdlineOptions(): ('ARCHFLAGS', 'Set architecture-specific compilation flags (passed literally to gcc)','') ,EnumOption('BUILDLEVEL', 'NoBug build level for debugging', 'ALPHA', allowed_values=('ALPHA', 'BETA', 'RELEASE')) - ,BoolOption('DEBUG', 'Build with debugging information and no optimizations', False) - ,BoolOption('OPTIMIZE', 'Build with strong optimization (-O3)', False) + ,BoolOption('DEBUG', 'Build with debugging information and no optimisations', False) + ,BoolOption('OPTIMIZE', 'Build with strong optimisation (-O3)', False) ,BoolOption('VALGRIND', 'Run Testsuite under valgrind control', True) ,BoolOption('VERBOSE', 'Print full build commands', False) ,('TESTSUITES', 'Run only Testsuites matching the given pattern', '') @@ -153,7 +153,7 @@ def defineCmdlineOptions(): ,PathOption('PKGLIBDIR', 'Installation dir for plugins, defaults to DESTDIR/lib/lumiera', '',PathOption.PathAccept) ,PathOption('PKGDATADIR', 'Installation dir for default config, usually DESTDIR/share/lumiera', '',PathOption.PathAccept) ,PathOption('SRCTAR', 'Create source tarball prior to compiling', '..', PathOption.PathAccept) - ,PathOption('DOCTAR', 'Create tarball with dev documentaionl', '..', PathOption.PathAccept) + ,PathOption('DOCTAR', 'Create tarball with developer documentation', '..', PathOption.PathAccept) ) return opts diff --git a/src/common/error.cpp b/src/common/error.cpp index 90e2e6f6d..e069fef5a 100644 --- a/src/common/error.cpp +++ b/src/common/error.cpp @@ -74,7 +74,7 @@ namespace lumiera { /** @note we set the C-style errorstate as a side effect */ Error::Error (string description, const char* id) throw() : std::exception (), - id_ (default_or_given (id)), + id_ (error::default_or_given (id)), msg_ (error::default_usermsg (this)), desc_ (description), cause_ ("") @@ -86,7 +86,7 @@ namespace lumiera { Error::Error (std::exception& cause, string description, const char* id) throw() : std::exception (), - id_ (default_or_given (id)), + id_ (error::default_or_given (id)), msg_ (error::default_usermsg (this)), desc_ (description), cause_ (extractCauseMsg(cause)) diff --git a/src/gui/guifacade.hpp b/src/gui/guifacade.hpp index c623c8b4c..3b1775e79 100644 --- a/src/gui/guifacade.hpp +++ b/src/gui/guifacade.hpp @@ -40,6 +40,10 @@ #include "lumiera/subsys.hpp" +extern "C" { +#include "lumiera/interface.h" +} + namespace gui { @@ -60,25 +64,44 @@ namespace gui { * access via interface handles for communication with Backend and * Proc-Layer. * + * @note this facade is intended to be used by Lumiera main solely. + * client code should always use the "business" interface(s). + * */ - struct GuiFacade + class GuiFacade { + public: + /** provide a descriptor for lumiera::AppState, * wired accordingly to allow main to load, * start and stop the Lumiera GTK GUI. */ static lumiera::Subsys& getDescriptor(); - /** weather the GUI has been started and all intfaces are opened */ + /** weather the GUI has been started and all interfaces are opened */ static bool isUp(); - //////////////////TODO: define the global access interface for the GUI - //////////////////TODO: provide a function for accessing this interface - //////////////////TODO: register similar proxy/facade interfaces for Proc/Backend + /* ===== control interface for the GuiStarterPlugin ======= */ + /** start the actual GUI thread(s), after successfully loading + * the GuiStarterPlugin, that is. The implementation of this function + * must ensure to invoke the given termination signal reliably after + * shutting down the GUI, otherwise the application will hang on exit. + * @internal this function is invoked automatically during the GUI + * loading and startup process. Don't call it manually. + */ + virtual bool kickOff (lumiera::Subsys::SigTerm&) =0; + + + protected: + virtual ~GuiFacade() {} }; + /** interface of the GuiStarterPlugin */ + LUMIERA_INTERFACE_DECLARE (lumieraorg_Gui, 1, + LUMIERA_INTERFACE_SLOT (bool, kickOff, (void*)) + ); } // namespace gui diff --git a/src/gui/guinotificationfacade.cpp b/src/gui/guinotificationfacade.cpp index beed5b0a7..181006de7 100644 --- a/src/gui/guinotificationfacade.cpp +++ b/src/gui/guinotificationfacade.cpp @@ -62,7 +62,7 @@ namespace gui { - /* ================== define an lumieraorg_guinotification instance ======================= */ + /* ================== define an lumieraorg_GuiNotification instance ======================= */ LUMIERA_INTERFACE_INSTANCE (lumieraorg_interfacedescriptor, 0 ,lumieraorg_GuiNotificationFacade_descriptor @@ -124,7 +124,7 @@ namespace gui { ) , LUMIERA_INTERFACE_INLINE (versioncmp, "\253\066\335\233\025\161\135\347\377\156\121\135\347\313\130\014", int, (const char* a, const char* b), - {return 0;} ////////////////////////////////////////////TODO + {return 0;} ////////////////////////////////////////////TODO define version ordering ) ); diff --git a/src/include/guinotificationfacade.h b/src/include/guinotificationfacade.h index f401f2e1e..5d3ec28fc 100644 --- a/src/include/guinotificationfacade.h +++ b/src/include/guinotificationfacade.h @@ -34,8 +34,8 @@ */ -#ifndef GUI_FACADE_H -#define GUI_FACADE_H +#ifndef GUI_GUINOTIFICATION_H +#define GUI_GUINOTIFICATION_H #include "common/singletonsubclass.hpp" diff --git a/src/lumiera/guifacade.cpp b/src/lumiera/guifacade.cpp index fb5f4fc7d..d4ef02da1 100644 --- a/src/lumiera/guifacade.cpp +++ b/src/lumiera/guifacade.cpp @@ -22,13 +22,11 @@ #include "gui/guifacade.hpp" +#include "include/guinotificationfacade.h" +#include "include/error.hpp" #include "common/singleton.hpp" #include "lumiera/instancehandle.hpp" -extern "C" { -#include "lumiera/interface.h" -} - #include #include @@ -40,18 +38,7 @@ namespace gui { using lumiera::Subsys; using lumiera::InstanceHandle; - /** interface of the GuiStarterPlugin */ - LUMIERA_INTERFACE_DECLARE (lumieraorg_Gui, 1 - ); - ///////////////////////////////////////////////////TODO: Placeholder - LumieraInterface* - getGuiStarterPlugin_InstanceDescriptor() - { - UNIMPLEMENTED ("implement the GuiStarterPlugin"); - return 0; - } - ///////////////////////////////////////////////////TODO: Placeholder struct GuiRunner @@ -59,33 +46,33 @@ namespace gui { { typedef InstanceHandle GuiHandle; - Subsys& guiSubsysHandle_; - Subsys::SigTerm terminate_; - GuiHandle theGUI_; - GuiRunner (Subsys& handle, Subsys::SigTerm terminationSignal) - : guiSubsysHandle_(handle), - terminate_(terminationSignal), - theGUI_(getGuiStarterPlugin_InstanceDescriptor()) + GuiRunner (Subsys::SigTerm terminationHandle) + : theGUI_("lumieraorg_Gui", 1, 1, "lumieraorg_GuiStarterPlugin") // load GuiStarterPlugin { ASSERT (theGUI_); - TODO ("start gui thread, passing the terminationSignal"); + if (!kickOff (terminationHandle)) + throw lumiera::error::Fatal("failed to bring up GUI",lumiera_error()); } - ~GuiRunner () - { - ////TODO any cleanup here? + ~GuiRunner () { } + + + bool kickOff (Subsys::SigTerm& terminationHandle) + { + return theGUI_->kickOff (reinterpret_cast (&terminationHandle)) + && !lumiera_error_peek(); } }; - namespace { // implementation details + namespace { // implementation details : start GUI through GuiStarterPlugin - scoped_ptr facade (0); + scoped_ptr facade (0); class GuiSubsysDescriptor : public lumiera::Subsys @@ -102,15 +89,16 @@ namespace gui { bool start (lumiera::Option&, Subsys::SigTerm termination) { - UNIMPLEMENTED ("load and start the GUI and register shutdown hook"); - facade.reset (new GuiRunner (*this, termination)); /////////////////////TODO: actually decorate the termSignal, in order to delete the facade - return false; + facade.reset (new GuiRunner (termination)); /////////////////////TODO: actually decorate the termSignal, in order to delete the facade + return true; } void triggerShutdown () throw() { - UNIMPLEMENTED ("initiate closing the GUI"); + try { GuiNotification::facade().triggerGuiShutdown ("Application shutdown"); } + + catch (...){} } }; @@ -122,6 +110,8 @@ namespace gui { + + /** @internal intended for use by main(). */ lumiera::Subsys& GuiFacade::getDescriptor() diff --git a/src/lumiera/instancehandle.hpp b/src/lumiera/instancehandle.hpp index 368a8ee4c..753c1fbab 100644 --- a/src/lumiera/instancehandle.hpp +++ b/src/lumiera/instancehandle.hpp @@ -120,7 +120,7 @@ namespace lumiera { */ InstanceHandle (string const& iName, uint version, size_t minminor, string const& impName) : desc_(0), - instance_(static_cast + instance_(reinterpret_cast (lumiera_interface_open (iName.c_str(), version, minminor, impName.c_str()))) { } @@ -165,7 +165,7 @@ namespace lumiera { private: FA * - accessFacade() + accessFacade() const { ENSURE (instance_); return static_cast (instance_); /////////////////TODO: actually handle the case when the facade differs from the interface by using the proxy diff --git a/src/plugin/guistarterplugin.cpp b/src/plugin/guistarterplugin.cpp new file mode 100644 index 000000000..4d0a66630 --- /dev/null +++ b/src/plugin/guistarterplugin.cpp @@ -0,0 +1,191 @@ +/* + GuiStarterPlugin - entry point for the lumiera GUI loaded as shared module + + Copyright (C) Lumiera.org + 2007-2008, Joel Holdsworth + Christian Thaeter + 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 guistarterplugin.hpp + ** Start up the Lumiera GTK GUI when loading it as dynamic module. + ** This plugin is linked together with the Lumiera GUI code; when loaded as + ** Lumiera plugin, it allows to kick off the main GUI thread and thus to bring up + ** the GUI. The loading and shutdown process is carried out by gui::GuiFacade and + ** controlled by lumiera::AppState, which in turn is activated by Lumiera main(). + ** + ** After successfully loading this module, a call to #kickOff is expected to be + ** issued, passing a termination signal (callback) to be executed when the GUI + ** terminates. This call returns immediately, after spawning off the main thread + ** and setting up the termination callback accordingly. Additionally, it cares + ** for opening the primary "business" interface of the GUI, i.e. the interface + ** gui::GuiNotification. + ** + ** @see lumiera::AppState + ** @see gui::GuiFacade + ** @see guifacade.cpp + ** @see ///////////////////////////////////TODO: add link to the gui main routine here! + */ + + +#include "gui/guifacade.hpp" +#include "lumiera/subsys.hpp" +#include "common/singleton.hpp" + +extern "C" { +#include "lumiera/interface.h" +#include "lumiera/interfacedescriptor.h" +} + +//#include +#include + +#include /////////////TODO + + +using std::string; +// using boost::scoped_ptr; +using lumiera::Subsys; +using std::cout; //////////////TODO + +using gui::LUMIERA_INTERFACE_INAME(lumieraorg_Gui, 1); + + +namespace gui { + + namespace { // implementation details + + /** + * Implement the necessary steps for starting up the GUI main thread + */ + struct GuiFacadeImpl + : public GuiFacade + { + + bool kickOff (Subsys::SigTerm& terminationHandle) + { + cout << " *** Ha Ha Ha\n" + << " this is the GuiStarterPlugin speaking!\n" + << " now, the Lumiera GUI should be spawned....\n" + << " but actually nothing happens!!!!!!!!!!!!!!\n\n"; + + terminationHandle(0); // signal immediate shutdown without error + return true; + } + }; + + + lumiera::Singleton facade_; + + } // (End) impl details + +} // namespace gui + + + + + + +extern "C" { /* ================== define an lumieraorg_Gui instance ======================= */ + + + LUMIERA_INTERFACE_INSTANCE (lumieraorg_interfacedescriptor, 0 + ,lumieraorg_GuiStarterPlugin_descriptor + , NULL, NULL, NULL + , LUMIERA_INTERFACE_INLINE (name, "\126\247\365\337\126\254\173\037\130\310\337\345\200\347\323\136", + const char*, (LumieraInterface iface), + { return "GuiStarterPlugin"; } + ) + , LUMIERA_INTERFACE_INLINE (brief, "\056\346\322\365\344\104\232\232\355\213\367\056\301\144\051\021", + const char*, (LumieraInterface iface), + { return "entry point to star up the Lumiera GTK GUI contained in this dynamic module"; } + ) + , LUMIERA_INTERFACE_INLINE (homepage, "\357\056\117\165\320\066\273\130\113\100\367\022\221\350\236\256", + const char*, (LumieraInterface iface), + { return "http://www.lumiera.org/develompent.html" ;} + ) + , LUMIERA_INTERFACE_INLINE (version, "\013\117\366\210\070\320\274\076\253\230\032\116\271\161\027\354", + const char*, (LumieraInterface iface), + { return "0.1~pre"; } + ) + , LUMIERA_INTERFACE_INLINE (author, "\371\262\024\273\170\105\163\261\351\240\051\003\153\040\256\155", + const char*, (LumieraInterface iface), + { return "Joel Holdsworth, Christian Thaeter, Hermann Vosseler"; } + ) + , LUMIERA_INTERFACE_INLINE (email, "\353\242\247\130\056\242\314\145\053\162\003\060\200\357\303\214", + const char*, (LumieraInterface iface), + { return "Lumiera@lists.lumiera.org"; } + ) + , LUMIERA_INTERFACE_INLINE (copyright, "\172\325\335\304\015\222\377\372\343\151\255\020\030\103\320\101", + const char*, (LumieraInterface iface), + { + return + "Copyright (C) Lumiera.org\n" + "2007-2008, Joel Holdsworth \n" + " Christian Thaeter \n" + " Hermann Vosseler "; + } + ) + , LUMIERA_INTERFACE_INLINE (license, "\016\264\202\005\160\305\033\227\037\077\143\363\263\011\167\257", + const char*, (LumieraInterface iface), + { + 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, "\006\070\035\065\267\073\016\107\376\027\355\035\135\176\107\064", + int, (LumieraInterface iface), + {return LUMIERA_INTERFACE_EXPERIMENTAL; } + ) + , LUMIERA_INTERFACE_INLINE (versioncmp, "\224\077\275\040\357\244\311\244\112\030\042\163\061\166\245\325", + int, (const char* a, const char* b), + {return 0;} ////////////////////////////////////////////TODO define version ordering + ) + ); + + + LUMIERA_EXPORT( /* ===================== PLUGIN EXPORTS ================================== */ + + LUMIERA_INTERFACE_DEFINE (lumieraorg_Gui, 1 + ,lumieraorg_GuiStarterPlugin + , LUMIERA_INTERFACE_REF(lumieraorg_interfacedescriptor, 0, lumieraorg_GuiStarterPlugin_descriptor) + , NULL /* on open */ + , NULL /* on close */ + , LUMIERA_INTERFACE_INLINE (kickOff, "\255\142\006\244\057\170\152\312\301\372\220\323\230\026\200\065", + bool, (void* termSig), + { + return gui::facade_().kickOff ( + *reinterpret_cast (termSig)); + } + ) + ) + ); + +} // extern "C" diff --git a/src/plugin/helloplugin.c b/src/plugin/helloplugin.c deleted file mode 100644 index d75f55f94..000000000 --- a/src/plugin/helloplugin.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * hello.c - demonstrates how to build a standalone tool (C source) - * integrated into the SCons based build system of Lumiera - */ - -#include - -int main(int argc, char* argv[]) - { - printf("hello lumiera world"); - return 0; - } diff --git a/tests/plugin/example_plugin.c b/tests/plugin/example_plugin.c index 13d704634..ee48fc828 100644 --- a/tests/plugin/example_plugin.c +++ b/tests/plugin/example_plugin.c @@ -1,3 +1,26 @@ +/* + example_plugin - example plugin for testing the interface/plugin system + + Copyright (C) Lumiera.org + 2008, Christian Thaeter + + 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 #include "lumiera/interfacedescriptor.h"