[go: up one dir, main page]

Menu

[r10]: / gizmod3 / gizmod / Gizmod.cpp  Maximize  Restore  History

Download this file

316 lines (265 with data), 9.3 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
/**
*********************************************************************
*************************************************************************
***
*** \file Gizmod.cpp
*** \brief Gizmod class body
***
*****************************************
*****************************************
**/
/*
Copyright (c) 2007, Tim Burrell
All rights reserved.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "Gizmod.hpp"
#include "../libH/Debug.hpp"
#include "../libH/Exception.hpp"
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <boost/program_options.hpp>
#include <boost/format.hpp>
#include <boost/python.hpp>
using namespace std;
using namespace boost;
using namespace boost::program_options;
using namespace boost::python;
using namespace H;
////////////////////////////////////////////////////////////////////////////
// C++ -> Python Exposures
///////////////////////////////////////
/**
* \struct GizmodEventHandlerInterfaceWrap
* \brief Wrapper for GizmodEventHandlerInterface so Python can inherit the abstract class
*/
struct GizmodEventHandlerInterfaceWrap : public GizmodEventHandlerInterface {
/// Default Constructor
GizmodEventHandlerInterfaceWrap(PyObject * self_) : self(self_) {}
void __construct__() { return python::call_method<void>(self, "__construct__"); }
bool getInitialized() { return python::call_method<bool>(self, "getInitialized"); }
void initialize() { return python::call_method<void>(self, "initialize"); }
PyObject * self; ///< Pointer to self
};
/**
* Python module definition
*/
BOOST_PYTHON_MODULE(GizmoDaemon) {
class_<Gizmod>("PyGizmod")
.def("getVersion", & Gizmod::getVersion)
;
class_<GizmodEventHandlerInterface, GizmodEventHandlerInterfaceWrap, boost::noncopyable>("GizmodEventHandler")
;
}
////////////////////////////////////////////////////////////////////////////
// Type Defs / defines
///////////////////////////////////////
/**
* \def CONFIG_FILE
* The default path of the config file
*/
#define CONFIG_FILE PACKAGE_NAME ".conf"
/**
* \def SCRIPT_DIR
* The default path of the config file
*/
#define SCRIPT_DIR PACKAGE_PREFIX "/share/gizmo/scripts/"
/**
* \def SCRIPT_GIZMOD
* The path of the initial config script
*/
#define SCRIPT_GIZMOD "Gizmod.py"
/**
* \def SCRIPT_USER
* The path of the user config script that gets run after SCRIPT_GIZMOD
*/
#define SCRIPT_USER "User.py"
////////////////////////////////////////////////////////////////////////////
// Construction
///////////////////////////////////////
/**
* \brief Default Constructor
*/
Gizmod::Gizmod() {
cout << getProps();
mConfigDir = SCRIPT_DIR;
mpPyDispatcher = NULL;
}
/**
* \brief Default Destructor
*/
Gizmod::~Gizmod() {
cdbg << "Gizmod Shutting Down..." << endl << endl;
}
////////////////////////////////////////////////////////////////////////////
// Class Body
///////////////////////////////////////
/**
* \brief Enter the main run loop
*/
void Gizmod::enterLoop() {
}
/**
* \brief Get the program's propers
*/
string Gizmod::getProps() {
return "\nGizmod v" + getVersion() + " -- (c) 2007, Tim Burrell <tim.burrell@gmail.com>\n";
}
/**
* \brief Get the program's version information
*/
string Gizmod::getVersion() {
return string(PACKAGE_VERSION);
}
/**
* \brief Setup Gizmod
*
* Initialize Gizmod
*/
void Gizmod::initGizmod() {
// TODO init gizmod
// init python
try {
initPython();
} catch (H::Exception & e) {
throw e;
} catch (exception & e) {
throw H::Exception("Failed to Initialize Python!", __FILE__, __FUNCTION__, __LINE__);
}
}
/**
* \brief Initialize the Python interpreter
*/
void Gizmod::initPython() {
try {
cdbg1 << "Embedding Python Interpreter..." << endl;
PyImport_AppendInittab("GizmoDaemon", &initGizmoDaemon);
Py_Initialize();
cdbg1 << "Initializing Python Environment..." << endl;
object MainModule((handle<>(borrowed(PyImport_AddModule("__main__")))));
object MainNamespace = MainModule.attr("__dict__");
// add Gizmo Daemon module automatically to the namespace
object GizmoDaemonModule( (handle<>(PyImport_ImportModule("GizmoDaemon"))) );
MainNamespace["GizmoDaemon"] = GizmoDaemonModule;
// create a new object so the script can access this object
scope(GizmoDaemonModule).attr("Gizmod") = ptr(this);
// execute the main script code
string ScriptFile = mConfigDir + SCRIPT_GIZMOD;
cdbg << "Executing Main Python Script [" << ScriptFile << "]..." << endl;
FILE * ifScript = fopen(ScriptFile.c_str(), "r");
if (!ifScript)
throw H::Exception("Failed to Open Python Script [" + ScriptFile + "] for Reading", __FILE__, __FUNCTION__, __LINE__);
PyRun_SimpleFile(ifScript, ScriptFile.c_str());
fclose(ifScript);
// Create the event dispatcher object so we can interact with it
cdbg1 << "Creating Dispatcher Object" << endl;
handle<> ignored((PyRun_String(
"Dispatcher = GizmodDispatcher()\n",
Py_file_input, MainNamespace.ptr(), MainNamespace.ptr())));
// Grab the event dispatcher object so we can interact with it
mpPyDispatcher = extract<GizmodEventHandlerInterface*>(MainNamespace["Dispatcher"]);
// Initialize the dispatcher object
mpPyDispatcher->__construct__();
mpPyDispatcher->initialize();
// execute the user script code
ScriptFile = mConfigDir + SCRIPT_USER;
cdbg << "Executing User Python Script [" << ScriptFile << "]..." << endl;
ifScript = fopen(ScriptFile.c_str(), "r");
if (!ifScript)
throw H::Exception("Failed to Open Python Script [" + ScriptFile + "] for Reading", __FILE__, __FUNCTION__, __LINE__);
PyRun_SimpleFile(ifScript, ScriptFile.c_str());
fclose(ifScript);
} catch (error_already_set) {
PyErr_Print();
throw H::Exception("Failed to Execute Python Script!", __FILE__, __FUNCTION__, __LINE__);
}
}
/**
* \brief generic Init stuff
* \param argc number of command line arguments
* \param argv command line arguments
* \return true if the program should continue, false otherwise
*
* load the config file, process command line options, etc
*/
bool Gizmod::initialize(int argc, char ** argv) {
// generic options
options_description GenericOptions("Generic Options");
GenericOptions.add_options()
("debug,g", "Enable debug mode")
("help,h", "Display informative help message")
("verbosity,V", value<int>(), "Set debug vebosity level (0-5) [Default = 0]")
("version,v", "Print version information")
;
// config file options that can be loaded via command line as well
options_description ConfigurationOptions("Configuration Options");
ConfigurationOptions.add_options()
("configdir,c", value<string>(), "Set config scripts directory")
;
// hiGizmodn options
options_description HiddenOptions("Hidden Options");
HiddenOptions.add_options();
// create command line options group
options_description CommandLineOptions;
CommandLineOptions.add(GenericOptions).add(ConfigurationOptions).add(HiddenOptions);
// create config file options group
options_description ConfigFileOptions;
ConfigFileOptions.add(ConfigurationOptions).add(HiddenOptions);
// create a visible options group for help display
options_description VisibleOptions("");
VisibleOptions.add(GenericOptions).add(ConfigurationOptions);
// create the variables map
variables_map VarMap;
// try parsing the command line
try {
store(parse_command_line(argc, argv, CommandLineOptions), VarMap);
} catch (exception e) {
cout << VisibleOptions;
throw H::Exception("Invalid Command Line Argument(s)");
}
// try parsing the config file
try {
ifstream ifs(CONFIG_FILE);
store(parse_config_file(ifs, ConfigFileOptions), VarMap);
} catch (exception e) {
cout << VisibleOptions;
throw H::Exception("Invalid Configuration File");
}
// build the option map
notify(VarMap);
// check for options
if (VarMap.count("help")) {
cout << VisibleOptions << endl;
return false;
}
if (VarMap.count("version")) {
return false;
}
if (VarMap.count("debug")) {
Debug::setDebugEnabled(true);
cdbg << "Debug Mode Enabled" << endl;
}
if (VarMap.count("verbosity")) {
Debug::setDebugVerbosity(VarMap["verbosity"].as<int>());
cdbg << "Debug Verbosity set to [" << VarMap["verbosity"].as<int>() << "]" << endl;
}
if (VarMap.count("configdir")) {
mConfigDir = VarMap["configdir"].as<string>();
if (mConfigDir[mConfigDir.length() - 1] != '/')
mConfigDir += "/";
cdbg << "Config Scripts Directory set to [" << VarMap["configdir"].as<string>() << "]" << endl;
}
cout << endl;
return true;
}