Lumiera  0.pre.03
»edit your freedom«
guifacade.cpp
Go to the documentation of this file.
1 /*
2  GuiFacade - access point for communicating with the Lumiera GTK GUI
3 
4  Copyright (C) Lumiera.org
5  2008, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 * *****************************************************/
22 
23 
34 #include "stage/guifacade.hpp"
36 #include "lib/sync.hpp"
37 #include "lib/error.hpp"
38 #include "lib/depend.hpp"
40 #include "common/option.hpp"
41 
42 #include <memory>
43 #include <string>
44 
45 
46 namespace stage {
47 
48  using std::string;
49  using std::unique_ptr;
50  using lumiera::Subsys;
52  using lib::Sync;
53  using lib::RecursiveLock_NoWait;
54 
55 
56 
58  struct GuiRunner
60  {
62 
63  GuiHandle theGUI_;
64 
65 
66  GuiRunner (Subsys::SigTerm terminationHandle)
67  : theGUI_("lumieraorg_Gui", 1, 1, "lumieraorg_GuiStarterPlugin") // load GuiStarterPlugin
68  {
69  ASSERT (theGUI_);
70  bool res = this->launchUI (terminationHandle);
71 
72  if (!res || lumiera_error_peek())
73  throw lumiera::error::Fatal{"failed to bring up the GUI", lumiera_error()};
74  }
75 
76 
77  /* ===== control interface for the GuiStarterPlugin ======= */
78 
86  bool launchUI (Subsys::SigTerm& terminationHandle)
87  {
88  return theGUI_->launchUI (reinterpret_cast<void*> (&terminationHandle));
89  }
90  };
91 
92 
93 
94 
95  namespace { // implementation of GUI-"Subsystem" : start GUI through GuiStarterPlugin
96 
97  unique_ptr<GuiRunner> facade;
98 
99 
101  : public lumiera::Subsys,
102  public Sync<RecursiveLock_NoWait>
103  {
104  operator string() const { return "Lumiera GTK GUI"; }
105 
106  bool
107  shouldStart (lumiera::Option& opts) override
108  {
109  if (opts.isHeadless() or 0 < opts.getPort())
110  {
111  INFO (guifacade, "*not* starting the GUI...");
112  return false;
113  }
114  else
115  return true;
116  }
117 
118  bool
119  start (lumiera::Option&, Subsys::SigTerm termNotification) override
120  {
121  Lock guard{this};
122  if (facade)
123  return false; // already started
124 
125  facade.reset ( // trigger loading of the GuiStarterPlugin...
126  new GuiRunner (
127  [=] (string* problemMessage)
128  { // will be invoked when the UI thread exits
129  closeGuiModule();
130  termNotification(problemMessage);
131  }));
132 
133  return true;
134  }
135 
144  void
145  triggerShutdown () noexcept override
146  {
147  try { GuiNotification::facade().triggerGuiShutdown ("Application shutdown"); }
148 
149  ERROR_LOG_AND_IGNORE (guifacade, "trigger shutdown of the GUI");
150  }
151 
152  bool
153  checkRunningState () noexcept override
154  {
155  return bool(facade);
156  }
157 
158 
159  void
160  closeGuiModule ()
161  {
162  Lock guard{this};
163  if (!facade)
164  {
165  WARN (guifacade, "Termination signal invoked, but GUI is currently closed. "
166  "Probably this is due to some broken startup logic and should be fixed.");
167  }
168  else
169  facade.reset (nullptr);
170  }
171 
172 
173 
174  public:
175  GuiSubsysDescriptor() { }
176 
178  {
179  if (facade)
180  {
181  WARN (guifacade, "GUI subsystem terminates, but GuiFacade isn't properly closed. "
182  "Closing it forcedly; this indicates broken startup logic and should be fixed.");
183  try { facade.reset (0); }
184  ERROR_LOG_AND_IGNORE (guifacade, "forcibly closing the GUI");
185  ENSURE (not lumiera_error_peek());
186  }
187  }
188  };
189 
190  lib::Depend<GuiSubsysDescriptor> theDescriptor;
191 
192  } // (End) impl details
193 
194 
195 
196 
197 
198 
202  {
203  return theDescriptor();
204  }
205 
206 
207  bool
209  {
210  return bool(facade);
211  }
212 
213 
214 } // namespace stage
Facility for monitor object based locking.
Definition: sync.hpp:217
Dependencies and lifecycle of a partially independent Subsystem of the Application.
Definition: subsys.hpp:70
lumiera_err lumiera_error_peek(void)
Check current error state without clearing it Please avoid this function and use lumiera_error() if p...
Definition: error-state.c:142
Major public Interface of the Lumiera GUI.
#define ERROR_LOG_AND_IGNORE(_FLAG_, _OP_DESCR_)
convenience shortcut for a sequence of catch blocks just logging and consuming an error...
Definition: error.hpp:275
Any copy and copy construction prohibited.
Definition: nocopy.hpp:46
bool launchUI(Subsys::SigTerm &terminationHandle)
start the actual GUI thread(s), after successfully loading the GuiStarterPlugin, that is...
Definition: guifacade.cpp:86
scoped guard to control the actual locking.
Definition: sync.hpp:234
Frontend for handling the Lumiera application commandline arguments.
Definition: option.hpp:77
Access point to singletons and other kinds of dependencies designated by type.
Definition: depend.hpp:289
static lumiera::Subsys & getDescriptor()
provide a descriptor for lumiera::AppState, wired accordingly to allow main to load, start and stop the Lumiera GTK GUI.
Definition: guifacade.cpp:201
Object Monitor based synchronisation.
bool isHeadless()
Definition: option.cpp:141
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:199
Lumiera GTK UI implementation root.
Definition: guifacade.cpp:46
lumiera_err lumiera_error(void)
Get and clear current error state.
Definition: error-state.c:124
front-end for handling the commandline arguments.
bool shouldStart(lumiera::Option &opts) override
query application option state to determine if this subsystem should be activated.
Definition: guifacade.cpp:107
Singleton services and Dependency Injection.
static bool isUp()
weather the GUI has been started and all interfaces are opened
Definition: guifacade.cpp:208
Lumiera error handling (C++ interface).
Handle tracking the registration of an interface, deregistering it on deletion.
Interface for the GUI loader and for accessing the GUI interface from the lower layers of Lumiera...
A handle template for automatically dealing with interface and plugin registration and deregistration...
static lib::Depend< GuiNotification > facade
static storage for the facade access front-end
bool checkRunningState() noexcept override
whether this subsystem is actually operational.
Definition: guifacade.cpp:153
load and start the GUI as a plugin
Definition: guifacade.cpp:58
bool start(lumiera::Option &, Subsys::SigTerm termNotification) override
attempt to bring up this subsystem up.
Definition: guifacade.cpp:119