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)
5  2008, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 * *****************************************************************/
13 
14 
25 #include "stage/guifacade.hpp"
27 #include "lib/sync.hpp"
28 #include "lib/error.hpp"
29 #include "lib/depend.hpp"
31 #include "common/option.hpp"
32 
33 #include <memory>
34 #include <string>
35 
36 
37 namespace stage {
38 
39  using std::string;
40  using std::unique_ptr;
41  using lumiera::Subsys;
43  using lib::Sync;
44  using lib::RecursiveLock_NoWait;
45 
46 
47 
49  struct GuiRunner
51  {
53 
54  GuiHandle theGUI_;
55 
56 
57  GuiRunner (Subsys::SigTerm terminationHandle)
58  : theGUI_("lumieraorg_Gui", 1, 1, "lumieraorg_GuiStarterPlugin") // load GuiStarterPlugin
59  {
60  ASSERT (theGUI_);
61  bool res = this->launchUI (terminationHandle);
62 
63  if (!res || lumiera_error_peek())
64  throw lumiera::error::Fatal{"failed to bring up the GUI", lumiera_error()};
65  }
66 
67 
68  /* ===== control interface for the GuiStarterPlugin ======= */
69 
77  bool launchUI (Subsys::SigTerm& terminationHandle)
78  {
79  return theGUI_->launchUI (reinterpret_cast<void*> (&terminationHandle));
80  }
81  };
82 
83 
84 
85 
86  namespace { // implementation of GUI-"Subsystem" : start GUI through GuiStarterPlugin
87 
88  unique_ptr<GuiRunner> facade;
89 
90 
92  : public lumiera::Subsys,
93  public Sync<RecursiveLock_NoWait>
94  {
95  operator string() const { return "Lumiera GTK GUI"; }
96 
97  bool
98  shouldStart (lumiera::Option& opts) override
99  {
100  if (opts.isHeadless() or 0 < opts.getPort())
101  {
102  INFO (guifacade, "*not* starting the GUI...");
103  return false;
104  }
105  else
106  return true;
107  }
108 
109  bool
110  start (lumiera::Option&, Subsys::SigTerm termNotification) override
111  {
112  Lock guard{this};
113  if (facade)
114  return false; // already started
115 
116  facade.reset ( // trigger loading of the GuiStarterPlugin...
117  new GuiRunner (
118  [=] (string* problemMessage)
119  { // will be invoked when the UI thread exits
120  closeGuiModule();
121  termNotification(problemMessage);
122  }));
123 
124  return true;
125  }
126 
135  void
136  triggerShutdown () noexcept override
137  {
138  try { GuiNotification::facade().triggerGuiShutdown ("Application shutdown"); }
139 
140  ERROR_LOG_AND_IGNORE (guifacade, "trigger shutdown of the GUI");
141  }
142 
143  bool
144  checkRunningState () noexcept override
145  {
146  return bool(facade);
147  }
148 
149 
150  void
151  closeGuiModule ()
152  {
153  Lock guard{this};
154  if (!facade)
155  {
156  WARN (guifacade, "Termination signal invoked, but GUI is currently closed. "
157  "Probably this is due to some broken startup logic and should be fixed.");
158  }
159  else
160  facade.reset (nullptr);
161  }
162 
163 
164 
165  public:
166  GuiSubsysDescriptor() { }
167 
169  {
170  if (facade)
171  {
172  WARN (guifacade, "GUI subsystem terminates, but GuiFacade isn't properly closed. "
173  "Closing it forcedly; this indicates broken startup logic and should be fixed.");
174  try { facade.reset (0); }
175  ERROR_LOG_AND_IGNORE (guifacade, "forcibly closing the GUI");
176  ENSURE (not lumiera_error_peek());
177  }
178  }
179  };
180 
181  lib::Depend<GuiSubsysDescriptor> theDescriptor;
182 
183  } // (End) impl details
184 
185 
186 
187 
188 
189 
193  {
194  return theDescriptor();
195  }
196 
197 
198  bool
200  {
201  return bool(facade);
202  }
203 
204 
205 } // namespace stage
Facility for monitor object based locking.
Definition: sync.hpp:209
Dependencies and lifecycle of a partially independent Subsystem of the Application.
Definition: subsys.hpp:61
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:133
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:266
Any copy and copy construction prohibited.
Definition: nocopy.hpp:37
bool launchUI(Subsys::SigTerm &terminationHandle)
start the actual GUI thread(s), after successfully loading the GuiStarterPlugin, that is...
Definition: guifacade.cpp:77
scoped guard to control the actual locking.
Definition: sync.hpp:226
Frontend for handling the Lumiera application commandline arguments.
Definition: option.hpp:68
Access point to singletons and other kinds of dependencies designated by type.
Definition: depend.hpp:280
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:192
Object Monitor based synchronisation.
bool isHeadless()
Definition: option.cpp:132
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:190
Lumiera GTK UI implementation root.
Definition: guifacade.cpp:37
lumiera_err lumiera_error(void)
Get and clear current error state.
Definition: error-state.c:115
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:98
Singleton services and Dependency Injection.
static bool isUp()
weather the GUI has been started and all interfaces are opened
Definition: guifacade.cpp:199
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:144
load and start the GUI as a plugin
Definition: guifacade.cpp:49
bool start(lumiera::Option &, Subsys::SigTerm termNotification) override
attempt to bring up this subsystem up.
Definition: guifacade.cpp:110