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