-
-
Notifications
You must be signed in to change notification settings - Fork 313
/
module.h
275 lines (231 loc) · 10.4 KB
/
module.h
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
/* === S Y N F I G ========================================================= */
/*! \file synfig/module.h
** \brief Base class for all libraries modules
**
** \legal
** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
** Copyright (c) 2007, 2008 Chris Moore
**
** This file is part of Synfig.
**
** Synfig 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.
**
** Synfig 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 Synfig. If not, see <https://www.gnu.org/licenses/>.
** \endlegal
*/
/* ========================================================================= */
/* === S T A R T =========================================================== */
#ifndef __SYNFIG_MODULE_H
#define __SYNFIG_MODULE_H
/* === H E A D E R S ======================================================= */
#include <ETL/handle>
#include <map>
#include "string.h"
#include "releases.h"
#include "layer.h"
#include "version.h"
/* === M A C R O S ========================================================= */
//! Marks the start of a module description
#define MODULE_DESC_BEGIN(x) struct x##_modclass : public synfig::Module { explicit x##_modclass(synfig::ProgressCallback *callback=nullptr);
//! Sets the localized name of the module
#define MODULE_NAME(x) virtual const char * Name() const { return x; }
//! Sets a localized description of the module
#define MODULE_DESCRIPTION(x) virtual const char * Desc() const { return x; }
//! Sets the name of the module's author
#define MODULE_AUTHOR(x) virtual const char * Author() const { return x; }
//! Sets the version string for the module
#define MODULE_VERSION(x) virtual const char * Version() const { return x; }
//! Sets the copyright string for the module
#define MODULE_COPYRIGHT(x) virtual const char * Copyright() const { return x; }
//! Describes the module's construction function
#define MODULE_CONSTRUCTOR(x) virtual bool constructor_(synfig::ProgressCallback *cb) { return x(cb); }
//! Describes the module's destruction function
#define MODULE_DESTRUCTOR(x) virtual void destructor_() { return x(); }
//! Marks the end of a module description
#define MODULE_DESC_END };
#ifdef _MSC_VER
#define SYNFIG_API_EXPORT __declspec(dllexport)
#else
#define SYNFIG_API_EXPORT
#endif
#ifdef __APPLE__
//! Marks the start of a module's inventory
#define MODULE_INVENTORY_BEGIN(x) extern "C" { \
synfig::Module* _##x##_LTX_new_instance(synfig::ProgressCallback *cb) \
{ if(SYNFIG_CHECK_VERSION()) { x##_modclass *mod=new x##_modclass(cb); mod->constructor_(cb); return mod; }\
if(cb) { cb->error(#x": Unable to load module due to version mismatch."); } \
return nullptr; \
}; x##_modclass::x##_modclass(synfig::ProgressCallback */*cb*/) {
#else
//! Marks the start of a module's inventory
#define MODULE_INVENTORY_BEGIN(x) extern "C" { \
SYNFIG_API_EXPORT synfig::Module* x##_LTX_new_instance(synfig::ProgressCallback *cb) \
{ if(SYNFIG_CHECK_VERSION()) { x##_modclass *mod=new x##_modclass(cb); mod->constructor_(cb); return mod; }\
if(cb) { cb->error(#x": Unable to load module due to version mismatch."); } \
return nullptr; \
}; x##_modclass::x##_modclass(synfig::ProgressCallback */*cb*/) {
#endif
//! Marks the start of the layers in the module's inventory
#define BEGIN_LAYERS {
//! Register a Layer class in the book of layers
#define LAYER(class) \
synfig::Layer::register_in_book( \
synfig::Layer::BookEntry(class::create, \
class::get_register_name(), \
synfigcore_localize(class::get_register_local_name()), \
class::get_register_category(), \
class::get_register_version()));
//! Register a Layer class in the book of layers with an alias
#define LAYER_ALIAS(class,alias) \
synfig::Layer::register_in_book( \
synfig::Layer::BookEntry(class::create, \
alias, \
alias, \
CATEGORY_DO_NOT_USE, \
class::get_register_version()));
//! Marks the end of the layers in the module's inventory
#define END_LAYERS }
//! Marks the start of the targets in the module's inventory
#define BEGIN_TARGETS {
//! Register a Target class in the book of targets and its default file extension
#define TARGET(x) \
synfig::Target::book()[synfig::String(x::name__)].factory = \
reinterpret_cast<synfig::Target::Factory> (x::create); \
synfig::Target::book()[synfig::String(x::name__)].filename = \
synfig::String(x::ext__); \
synfig::Target::book()[synfig::String(x::name__)].target_param = \
synfig::TargetParam(); \
synfig::Target::ext_book()[synfig::String(x::ext__)]=x::name__;
//! Register an additional file extension y for Target class x
#define TARGET_EXT(x,y) synfig::Target::ext_book()[synfig::String(y)]=x::name__;
//! Marks the end of the targets in the module's inventory
#define END_TARGETS }
//! Marks the start of the importers in the module's inventory
#define BEGIN_IMPORTERS {
//! Register an Importer class in the book of importers by one file extension string
#define IMPORTER_EXT(x,y) \
synfig::Importer::book()[synfig::String(y)]=synfig::Importer::BookEntry(x::create, x::supports_file_system_wrapper__);
//! Register an Importer class in the book of importers by the default extension
#define IMPORTER(x) IMPORTER_EXT(x,x::ext__)
//! Marks the end of the importers in the module's inventory
#define END_IMPORTERS }
//! Marks the end of a module's inventory
#define MODULE_INVENTORY_END } }
/* === T Y P E D E F S ===================================================== */
/* === C L A S S E S & S T R U C T S ======================================= */
namespace synfig {
class ProgressCallback;
/*! \class Module
* Module is a dynamic library working as an add-on able to provide
* new layer types (Layer), new animation renderers/exporters (Target) and
* new image and video importers (Importer).
*
* Anyone creating a Module MUST declare its metadata. It SHOULD be done inside
* a block of macros starting with MODULE_DESC_BEGIN(module_name) and ending
* with MODULE_DESC_END. The module_name MUST match library file name.
* The meta data SHOULD be filled with the macros MODULE_NAME(localized_name),
* MODULE_DESCRIPTION(localized_description), MODULE_AUTHOR(author), MODULE_VERSION(version),
* MODULE_COPYRIGHT(copyright).
* If the module requires some sort of initialization or proper memory release on exit,
* it COULD set them via macros MODULE_CONSTRUCTOR(function_name) and MODULE_DESTRUCTOR(function_name).
*
* Module creator can register provided layers with helper macros like in this example:
*
* MODULE_INVENTORY_BEGIN(libmod_geometry)
* BEGIN_LAYERS
* LAYER(CheckerBoard)
* LAYER(Circle)
* END_LAYERS
* MODULE_INVENTORY_END
*
* In a similar way, module authors can register its Target and Importer classes:
*
* MODULE_INVENTORY_BEGIN(mod_ffmpeg)
* BEGIN_TARGETS
* TARGET(ffmpeg_trgt)
* TARGET_EXT(ffmpeg_trgt,"avi")
* TARGET_EXT(ffmpeg_trgt,"flv")
* END_TARGETS
* BEGIN_IMPORTERS
* IMPORTER_EXT(ffmpeg_mptr,"avi")
* IMPORTER_EXT(ffmpeg_mptr,"mp4")
* END_IMPORTERS
* MODULE_INVENTORY_END
*
* As can be noticed, a single module MAY provide multiple layers, multiple targets
* and multiple importers, and they aren't restricted to provide a single type of
* Synfig content.
*
* Modules can provide other Synfig content types (like Type and ValueNode), but
* currently it doesn't provide helper macros to those registrations.
*
* One remainder: those mentioned macros SHOULD NOT be used in a C++ header file.
* If this header is #include'd multiple times, there would be multiple variable/class
* declarations.
*
* As Layer class does, Module class provide a static list of all registered Modules,
* indexed by its module_name. Registered modules are already properly initialized.
* Modules are not auto-registered. Instead, Synfig register those listed in a
* plain-text file called "synfig_modules.cfg" or that defined by envvar SYNFIG_MODULE_LIST.
* See synfig::Main for further details.
*/
class Module : public etl::shared_object
{
public:
//! The initializer of the module. Default implementation does nothing
virtual bool constructor_(synfig::ProgressCallback */*cb*/) { return true; }
//! The module cleanup function
virtual void destructor_() { }
typedef etl::handle<Module> Handle;
typedef etl::loose_handle<Module> LooseHandle;
typedef etl::handle<const Module> ConstHandle;
//! Type that represents a pointer to a Module's constructor by name.
//! As a pointer to the member, it represents a constructor of the module.
typedef Module* (*constructor_type)(ProgressCallback *);
//! Type of registered modules: maps Module name to Module handle
typedef std::map<String, Handle> Book;
private:
//! Registered modules
static Book* book_;
public:
//! The registered modules
static Book& book();
//! Inits the book of modules and add the paths to search for them
static bool subsys_init(const String &prefix);
//! Cleans up this subsystem
static bool subsys_stop();
//! Register not optional modules
static void register_default_modules(ProgressCallback *cb=nullptr);
//! Register Module by handle
static void Register(Handle mod);
//! Register Module by name
static bool Register(const String &module_name, ProgressCallback *cb=nullptr);
//!Register Module by instance pointer
static inline void Register(Module *mod) { Register(Handle(mod)); }
// Virtual Modules properties wrappers.
// They MUST be defined in the module implementation classes.
// They SHOULD be defined via MODULE_* macros inside MODULE_DESC_BEGIN/END block.
//! Localized module name
virtual const char * Name() const = 0;
//! Localized module description
virtual const char * Desc() const = 0;
//! Module author(s)'s name
virtual const char * Author() const = 0;
//! Module version string
virtual const char * Version() const = 0;
//! Module copyright text
virtual const char * Copyright() const = 0;
virtual ~Module();
};
}; // END of namespace synfig
/* === E N D =============================================================== */
#endif