BEAST/BSE - Better Audio System and Sound Engine  0.9.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
bsecxxplugin.hh
Go to the documentation of this file.
1  // Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
2 #ifndef __BSE_CXX_PLUGIN_H__
3 #define __BSE_CXX_PLUGIN_H__
4 
5 #include <bse/bsecxxmodule.hh>
6 #include <bse/bseexports.hh>
7 #include <bse/bseparam.hh>
8 #include <bse/bsecategories.hh>
9 #include <bse/bseplugin.hh>
10 #include <sfi/sficxx.hh>
11 
12 namespace Bse {
13 
14 /* --- frequently used constants --- */
15 const SfiInt KAMMER_NOTE = SFI_KAMMER_NOTE;
16 const SfiInt KAMMER_OCTAVE = SFI_KAMMER_OCTAVE;
17 const SfiReal KAMMER_FREQ = BSE_KAMMER_FREQUENCY;
18 const SfiInt MIN_FINE_TUNE = BSE_MIN_FINE_TUNE;
19 const SfiInt MAX_FINE_TUNE = BSE_MAX_FINE_TUNE;
20 
21 
22 /* -- export identity --- */
23 /* provide plugin export identity, preceeding all type exports */
24 #ifndef BSE_COMPILATION
25 #define BSE_CXX_DEFINE_EXPORTS() \
26  static ::BseExportIdentity __staticbse_export_identity = BSE_EXPORT_IDENTITY (*(::BseExportNode*) 0);
27 #define BSE_CXX_EXPORT_IDENTITY &__staticbse_export_identity
28 #else /* BSE internal "Plugins" */
29 #define BSE_CXX_DEFINE_EXPORTS()
30 #define BSE_CXX_EXPORT_IDENTITY &bse_builtin_export_identity
31 extern "C" {
32 extern ::BseExportIdentity bse_builtin_export_identity; /* sync with bseplugin.hh */
33 };
34 #endif
35 
36 // == Resident Type Plugin Registration ==
37 #define BSE_RESIDENT_TYPE_DEF(Object, func, anc, category, blurb, icon) \
38  static GType func##_get_type () { \
39  static const GTypeInfo type_info = { \
40  sizeof (Object##Class), \
41  (GBaseInitFunc) NULL, \
42  (GBaseFinalizeFunc) NULL, \
43  (GClassInitFunc) func##_class_init, \
44  (GClassFinalizeFunc) NULL, \
45  NULL /* class_data */, \
46  sizeof (Object), \
47  0 /* n_preallocs */, \
48  (GInstanceInitFunc) func##_init, \
49  }; \
50  static GType type_id = 0; \
51  if (!type_id) \
52  { \
53  type_id = bse_type_register_static (anc, # Object , blurb, __FILE__, __LINE__, &type_info); \
54  if (category) \
55  bse_categories_register_stock_module (category, type_id, icon); \
56  } \
57  return type_id; \
58  } \
59  static void func##__onload () { \
60  bse_plugin_make_resident(); \
61  (void) (volatile GType) func##_get_type(); \
62  } static Sfi::Init func##__onload_ (func##__onload);
63 #define BSE_RESIDENT_SOURCE_DEF(Object, func, category, blurb, icon) \
64  BSE_RESIDENT_TYPE_DEF(Object, func, BSE_TYPE_SOURCE, category, blurb, icon)
65 
66 /* --- hook registration --- */
67 /* hook registration is based on a static ExportTypeKeeper
68  * object, which provides the hook's get_type() implementation and
69  * auto-registers the hook's export node with the export_identity.
70  */
71 #define BSE_CXX_REGISTER_HOOK(HookType) BSE_CXX_REGISTER_HOOK_NODE (HookType, 0)
72 #define BSE_CXX_REGISTER_STATIC_HOOK(HookType) BSE_CXX_REGISTER_HOOK_NODE (HookType, 1)
73 #define BSE_CXX_REGISTER_HOOK_NODE(HookType, __static) \
74  template<class E> static BseExportNode* bse_export_node (); \
75  template<> inline BseExportNode* \
76  bse_export_node<HookType> () \
77  { \
78  static BseExportNodeHook hnode = { \
79  { NULL, BSE_EXPORT_NODE_HOOK, "", }, \
80  }; \
81  static HookType hook_instance; \
82  struct Sub { \
83  static void \
84  hook_trampoline (void *data) \
85  { \
86  hook_instance.run(); \
87  } \
88  }; \
89  if (!hnode.hook) \
90  { \
91  hnode.hook = Sub::hook_trampoline; \
92  hnode.make_static = __static != 0; \
93  } \
94  return &hnode.node; \
95  } \
96  extern ::Bse::ExportTypeKeeper bse_type_keeper__7##HookType; \
97  ::Bse::ExportTypeKeeper \
98  bse_type_keeper__7##HookType (bse_export_node<HookType>, \
99  BSE_CXX_EXPORT_IDENTITY);
100 
101 /* --- enum registration --- */
102 /* enum registration is based on a static ExportTypeKeeper
103  * object, which provides the enum's get_type() implementation and
104  * auto-registers the enum's export node with the export_identity.
105  */
106 #define BSE_CXX_DECLARED_ENUM_TYPE(NameSpace,EnumType) \
107  (::NameSpace::bse_type_keeper__3##EnumType.get_type ())
108 #define BSE_CXX_DECLARE_ENUM(EnumType,EnumName,N,ICode) \
109  template<class E> static BseExportNode* bse_export_node (); \
110  template<> BseExportNode* \
111  bse_export_node<EnumType> () \
112  { \
113  static BseExportNodeEnum enode = { \
114  { NULL, BSE_EXPORT_NODE_ENUM, EnumName, }, \
115  }; \
116  struct Sub { \
117  static GEnumValue* \
118  get_enum_values (void) \
119  { \
120  static GEnumValue values[N + 1]; \
121  if (!values[0].value_name) { \
122  GEnumValue *v = values; \
123  ICode; /* initializes values via *v++ = ...; */ \
124  g_assert (v == values + N); \
125  *v++ = ::Bse::EnumValue (0, 0, 0); /* NULL termination */ \
126  } \
127  return values; \
128  } \
129  }; \
130  if (!enode.get_enum_values) \
131  { \
132  enode.get_enum_values = Sub::get_enum_values; \
133  enode.get_choice_values = EnumType ## _choice_values; \
134  } \
135  return &enode.node; \
136  } \
137  extern ::Bse::ExportTypeKeeper bse_type_keeper__3##EnumType;
138 #define BSE_CXX_REGISTER_ENUM(EnumType) \
139  ::Bse::ExportTypeKeeper \
140  bse_type_keeper__3##EnumType (bse_export_node<EnumType>, \
141  BSE_CXX_EXPORT_IDENTITY);
142 /* convenience creator to allow easy assignments of GEnumValue structs */
143 inline const GEnumValue
144 EnumValue (int int_value,
145  const char *value_name,
146  const char *value_nick)
147 {
148  GEnumValue value;
149  value.value = int_value;
150  value.value_name = const_cast<char*> (value_name);
151  value.value_nick = const_cast<char*> (value_nick);
152  return value;
153 }
154 
155 /* --- record registration --- */
156 /* record registration is based on a static ExportTypeKeeper
157  * object, which provides the record's get_type() implementation and
158  * auto-registers the record's export node with the export_identity.
159  */
160 #define BSE_CXX_DECLARED_RECORD_TYPE(NameSpace,RecordType) \
161  (::NameSpace::bse_type_keeper__1##RecordType.get_type ())
162 #define BSE_CXX_DECLARE_RECORD(RecordType) \
163  template<class E> static BseExportNode* bse_export_node (); \
164  template<> BseExportNode* \
165  bse_export_node<RecordType> () \
166  { \
167  static BseExportNodeBoxed bnode = { \
168  { NULL, BSE_EXPORT_NODE_RECORD, NULL, }, \
169  }; \
170  if (!bnode.node.name) { \
171  struct Sub { static void fill_strings (BseExportStrings *es) { \
172  es->blurb = RecordType::blurb(); \
173  es->authors = RecordType::authors(); \
174  es->license = RecordType::license(); \
175  } }; \
176  bnode.node.name = RecordType::type_name(); \
177  bnode.node.options = RecordType::options(); \
178  bnode.node.fill_strings = Sub::fill_strings; \
179  bnode.copy = Sfi::RecordHandle< RecordType >::boxed_copy; \
180  bnode.free = Sfi::RecordHandle< RecordType >::boxed_free; \
181  bnode.seqrec2boxed = ::Sfi::cxx_boxed_from_rec<RecordType>; \
182  bnode.boxed2recseq = ::Sfi::cxx_boxed_to_rec<RecordType>; \
183  bnode.func.get_fields = RecordType::get_fields; \
184  } \
185  return &bnode.node; \
186  } \
187  extern ::Bse::ExportTypeKeeper bse_type_keeper__1##RecordType;
188 #define BSE_CXX_REGISTER_RECORD(RecordType) \
189  ::Bse::ExportTypeKeeper \
190  bse_type_keeper__1##RecordType (bse_export_node<RecordType>, \
191  BSE_CXX_EXPORT_IDENTITY);
192 
193 
194 /* --- sequence registration --- */
195 /* sequence registration works similar to record registration */
196 #define BSE_CXX_DECLARED_SEQUENCE_TYPE(NameSpace,SequenceType) \
197  (::NameSpace::bse_type_keeper__2##SequenceType.get_type ())
198 #define BSE_CXX_DECLARE_SEQUENCE(SequenceType) \
199  template<class E> static BseExportNode* bse_export_node (); \
200  template<> BseExportNode* \
201  bse_export_node<SequenceType> () \
202  { \
203  static BseExportNodeBoxed bnode = { \
204  { NULL, BSE_EXPORT_NODE_SEQUENCE, NULL, }, \
205  }; \
206  if (!bnode.node.name) { \
207  struct Sub { static void fill_strings (BseExportStrings *es) { \
208  es->blurb = SequenceType::blurb(); \
209  es->authors = SequenceType::authors(); \
210  es->license = SequenceType::license(); \
211  } }; \
212  bnode.node.name = SequenceType::type_name(); \
213  bnode.node.options = SequenceType::options(); \
214  bnode.node.fill_strings = Sub::fill_strings; \
215  bnode.copy = SequenceType::boxed_copy; \
216  bnode.free = SequenceType::boxed_free; \
217  bnode.seqrec2boxed = ::Sfi::cxx_boxed_from_seq<SequenceType>; \
218  bnode.boxed2recseq = ::Sfi::cxx_boxed_to_seq<SequenceType>; \
219  bnode.func.get_element = SequenceType::get_element; \
220  } \
221  return &bnode.node; \
222  } \
223  extern ::Bse::ExportTypeKeeper bse_type_keeper__2##SequenceType;
224 #define BSE_CXX_REGISTER_SEQUENCE(SequenceType) \
225  ::Bse::ExportTypeKeeper \
226  bse_type_keeper__2##SequenceType (bse_export_node<SequenceType>, \
227  BSE_CXX_EXPORT_IDENTITY);
228 
229 
230 /* --- procedure registration --- */
231 /* procedure registration works similar to enum registration. */
232 #define BSE_CXX_DECLARED_PROC_TYPE(NameSpace,ProcType) \
233  (::NameSpace::bse_type_keeper__9##ProcType.get_type ())
234 #define BSE_CXX_DECLARE_PROC(ProcType) \
235  extern ::Bse::ExportTypeKeeper bse_type_keeper__9##ProcType;
236 #define BSE_CXX_REGISTER_PROCEDURE(ProcType) \
237  template<class C> static ::BseExportNode* bse_export_node (); \
238  template<> ::BseExportNode* \
239  bse_export_node<Procedure::ProcType> () \
240  { \
241  static ::BseExportNodeProc pnode = { \
242  { NULL, ::BSE_EXPORT_NODE_PROC, NULL, }, \
243  0, Procedure::ProcType::init, Procedure::ProcType::marshal, \
244  }; \
245  if (!pnode.node.name) { \
246  struct Sub { static void fill_strings (BseExportStrings *es) { \
247  es->blurb = Procedure::ProcType::blurb(); \
248  es->authors = Procedure::ProcType::authors(); \
249  es->license = Procedure::ProcType::license(); \
250  es->i18n_category = Procedure::ProcType::i18n_category(); \
251  } }; \
252  pnode.node.name = Procedure::ProcType::type_name(); \
253  pnode.node.options = Procedure::ProcType::options(); \
254  pnode.node.category = Procedure::ProcType::category(); \
255  pnode.node.pixstream = Procedure::ProcType::pixstream(); \
256  pnode.node.fill_strings = Sub::fill_strings; \
257  } \
258  return &pnode.node; \
259  } \
260  ::Bse::ExportTypeKeeper \
261  bse_type_keeper__9##ProcType (bse_export_node<Procedure::ProcType>, \
262  BSE_CXX_EXPORT_IDENTITY);
263 
264 
265 /* --- class registration --- */
266 /* class registration works similar to enum registration.
267  * in addition, we need to define a couple trampoline functions to make
268  * C++ methods callable, and for effects, we're providing some basic
269  * method implementations to interface with the synmthesis Module.
270  */
271 #define BSE_CXX_DECLARED_CLASS_TYPE(NameSpace,ClassType) \
272  (::NameSpace::bse_type_keeper__0##ClassType.get_type ())
273 #define BSE_CXX_DECLARE_CLASS(ClassType) \
274  extern ::Bse::ExportTypeKeeper bse_type_keeper__0##ClassType;
275 #define BSE_CXX_REGISTER_EFFECT(Effect) \
276  BSE_CXX_DEFINE_STATIC_DATA (Effect##Base); \
277  template<class C> static ::BseExportNode* bse_export_node (); \
278  template<> ::BseExportNode* \
279  bse_export_node<Effect> () \
280  { \
281  static ::BseExportNodeClass cnode = { \
282  { NULL, ::BSE_EXPORT_NODE_CLASS, NULL, }, \
283  "BseEffect", BSE_CXX_COMMON_CLASS_SIZE, \
284  (GClassInitFunc) static_cast <void (*) (::Bse::CxxBaseClass*)> \
285  (::Bse::cxx_class_init_trampoline<Effect>), \
286  NULL, \
287  BSE_CXX_INSTANCE_OFFSET + sizeof (Effect), \
288  ::Bse::cxx_instance_init_trampoline<Effect>, \
289  }; \
290  if (!cnode.node.name) { \
291  struct Sub { static void fill_strings (BseExportStrings *es) { \
292  es->blurb = Effect::blurb(); \
293  es->authors = Effect::authors(); \
294  es->license = Effect::license(); \
295  es->i18n_category = Effect::i18n_category(); \
296  } }; \
297  cnode.node.name = Effect::type_name(); \
298  cnode.node.options = Effect::options(); \
299  cnode.node.category = Effect::category(); \
300  cnode.node.pixstream = Effect::pixstream(); \
301  cnode.node.fill_strings = Sub::fill_strings; \
302  } \
303  return &cnode.node; \
304  } \
305  ::Bse::ExportTypeKeeper \
306  bse_type_keeper__0##Effect (bse_export_node<Effect>, \
307  BSE_CXX_EXPORT_IDENTITY);
308 /* implement static_data portions used by auto-generated classes */
309 #define BSE_CXX_DEFINE_STATIC_DATA(ObjectType) \
310  ObjectType::StaticData ObjectType::static_data;
311 
312 
313 /* --- type keeper for export nodes --- */
315 {
316  BseExportNode *enode;
317  BsePlugin *plugin;
318  static BsePlugin* plugin_export_node (const ::BseExportIdentity *plugin_identity,
319  ::BseExportNode *enode);
320  static void plugin_cleanup (BsePlugin *plugin,
321  ::BseExportNode *enode);
322  RAPICORN_CLASS_NON_COPYABLE (ExportTypeKeeper);
323 public:
324  ExportTypeKeeper (::BseExportNode* (*export_node) (),
325  ::BseExportIdentity *export_identity)
326  {
327  enode = export_node();
328  plugin = plugin_export_node (export_identity, enode);
329  }
331  {
332  if (plugin)
333  plugin_cleanup (plugin, enode);
334  }
335  const GType get_type() { return enode->type; }
336 };
337 } // Bse
338 /* include generated C++ core types */
339 #include <bse/bsebasics.genidl.hh> /* includes bsecxxplugin.hh itself */
340 /* define types dependant on bsebasics.idl */
341 namespace Bse {
342 /* --- trampoline templates --- */
343 template<class ObjectType, typename PropertyID> static void
344 cxx_get_candidates_trampoline (BseItem *item,
345  guint prop_id,
346  BsePropertyCandidates *pc,
347  GParamSpec *pspec)
348 {
349  CxxBase *cbase = cast (item);
350  ObjectType *instance = static_cast<ObjectType*> (cbase);
351  if (0) // check ObjectType::get_candidates() member and prototype
352  (void) static_cast<void (ObjectType::*) (PropertyID, ::Bse::PropertyCandidatesHandle&, GParamSpec*)> (&ObjectType::get_candidates);
353  ::Bse::PropertyCandidatesHandle pch (::Sfi::INIT_NULL);
355  if (cxxpc)
356  pch.take (cxxpc); /* take as pointer, not via CopyConstructor */
357  instance->get_candidates (static_cast<PropertyID> (prop_id), pch, pspec);
358  if (cxxpc)
359  pch.steal(); /* steal to avoid destruction */
360 }
361 
362 } // Bse
363 
364 #endif /* __BSE_CXX_PLUGIN_H__ */
Definition: bsecxxplugin.hh:314
Definition: bseplugin.hh:19
Definition: bseexports.hh:105
Definition: sficxx.hh:168
Definition: bseitem.hh:33
Definition: bsebasics.genidl.hh:705