BEAST/BSE - Better Audio System and Sound Engine
0.8.2
|
00001 // Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html 00002 #ifndef __BSE_CXX_PLUGIN_H__ 00003 #define __BSE_CXX_PLUGIN_H__ 00004 00005 #include <bse/bsecxxmodule.hh> 00006 #include <bse/bseexports.hh> 00007 #include <bse/bseparam.hh> 00008 #include <bse/bsecategories.hh> 00009 #include <bse/bseplugin.hh> 00010 #include <sfi/sficxx.hh> 00011 00012 namespace Bse { 00013 00014 /* --- frequently used constants --- */ 00015 const SfiInt KAMMER_NOTE = SFI_KAMMER_NOTE; 00016 const SfiInt KAMMER_OCTAVE = SFI_KAMMER_OCTAVE; 00017 const SfiReal KAMMER_FREQ = BSE_KAMMER_FREQUENCY; 00018 const SfiInt MIN_FINE_TUNE = BSE_MIN_FINE_TUNE; 00019 const SfiInt MAX_FINE_TUNE = BSE_MAX_FINE_TUNE; 00020 00021 00022 /* -- export identity --- */ 00023 /* provide plugin export identity, preceeding all type exports */ 00024 #ifndef BSE_COMPILATION 00025 #define BSE_CXX_DEFINE_EXPORTS() \ 00026 static ::BseExportIdentity __staticbse_export_identity = BSE_EXPORT_IDENTITY (*(::BseExportNode*) 0); 00027 #define BSE_CXX_EXPORT_IDENTITY &__staticbse_export_identity 00028 #else /* BSE internal "Plugins" */ 00029 #define BSE_CXX_DEFINE_EXPORTS() 00030 #define BSE_CXX_EXPORT_IDENTITY &bse_builtin_export_identity 00031 extern "C" { 00032 extern ::BseExportIdentity bse_builtin_export_identity; /* sync with bseplugin.hh */ 00033 }; 00034 #endif 00035 00036 // == Resident Type Plugin Registration == 00037 #define BSE_RESIDENT_TYPE_DEF(Object, func, anc, category, blurb, icon) \ 00038 static GType func##_get_type () { \ 00039 static const GTypeInfo type_info = { \ 00040 sizeof (Object##Class), \ 00041 (GBaseInitFunc) NULL, \ 00042 (GBaseFinalizeFunc) NULL, \ 00043 (GClassInitFunc) func##_class_init, \ 00044 (GClassFinalizeFunc) NULL, \ 00045 NULL /* class_data */, \ 00046 sizeof (Object), \ 00047 0 /* n_preallocs */, \ 00048 (GInstanceInitFunc) func##_init, \ 00049 }; \ 00050 static GType type_id = 0; \ 00051 if (!type_id) \ 00052 { \ 00053 type_id = bse_type_register_static (anc, # Object , blurb, __FILE__, __LINE__, &type_info); \ 00054 if (category) \ 00055 bse_categories_register_stock_module (category, type_id, icon); \ 00056 } \ 00057 return type_id; \ 00058 } \ 00059 static void func##__onload () { \ 00060 bse_plugin_make_resident(); \ 00061 (void) (volatile GType) func##_get_type(); \ 00062 } static Sfi::Init func##__onload_ (func##__onload); 00063 #define BSE_RESIDENT_SOURCE_DEF(Object, func, category, blurb, icon) \ 00064 BSE_RESIDENT_TYPE_DEF(Object, func, BSE_TYPE_SOURCE, category, blurb, icon) 00065 00066 /* --- hook registration --- */ 00067 /* hook registration is based on a static ExportTypeKeeper 00068 * object, which provides the hook's get_type() implementation and 00069 * auto-registers the hook's export node with the export_identity. 00070 */ 00071 #define BSE_CXX_REGISTER_HOOK(HookType) BSE_CXX_REGISTER_HOOK_NODE (HookType, 0) 00072 #define BSE_CXX_REGISTER_STATIC_HOOK(HookType) BSE_CXX_REGISTER_HOOK_NODE (HookType, 1) 00073 #define BSE_CXX_REGISTER_HOOK_NODE(HookType, __static) \ 00074 template<class E> static BseExportNode* bse_export_node (); \ 00075 template<> inline BseExportNode* \ 00076 bse_export_node<HookType> () \ 00077 { \ 00078 static BseExportNodeHook hnode = { \ 00079 { NULL, BSE_EXPORT_NODE_HOOK, "", }, \ 00080 }; \ 00081 static HookType hook_instance; \ 00082 struct Sub { \ 00083 static void \ 00084 hook_trampoline (void *data) \ 00085 { \ 00086 hook_instance.run(); \ 00087 } \ 00088 }; \ 00089 if (!hnode.hook) \ 00090 { \ 00091 hnode.hook = Sub::hook_trampoline; \ 00092 hnode.make_static = __static != 0; \ 00093 } \ 00094 return &hnode.node; \ 00095 } \ 00096 extern ::Bse::ExportTypeKeeper bse_type_keeper__7##HookType; \ 00097 ::Bse::ExportTypeKeeper \ 00098 bse_type_keeper__7##HookType (bse_export_node<HookType>, \ 00099 BSE_CXX_EXPORT_IDENTITY); 00100 00101 /* --- enum registration --- */ 00102 /* enum registration is based on a static ExportTypeKeeper 00103 * object, which provides the enum's get_type() implementation and 00104 * auto-registers the enum's export node with the export_identity. 00105 */ 00106 #define BSE_CXX_DECLARED_ENUM_TYPE(NameSpace,EnumType) \ 00107 (::NameSpace::bse_type_keeper__3##EnumType.get_type ()) 00108 #define BSE_CXX_DECLARE_ENUM(EnumType,EnumName,N,ICode) \ 00109 template<class E> static BseExportNode* bse_export_node (); \ 00110 template<> BseExportNode* \ 00111 bse_export_node<EnumType> () \ 00112 { \ 00113 static BseExportNodeEnum enode = { \ 00114 { NULL, BSE_EXPORT_NODE_ENUM, EnumName, }, \ 00115 }; \ 00116 struct Sub { \ 00117 static GEnumValue* \ 00118 get_enum_values (void) \ 00119 { \ 00120 static GEnumValue values[N + 1]; \ 00121 if (!values[0].value_name) { \ 00122 GEnumValue *v = values; \ 00123 ICode; /* initializes values via *v++ = ...; */ \ 00124 g_assert (v == values + N); \ 00125 *v++ = ::Bse::EnumValue (0, 0, 0); /* NULL termination */ \ 00126 } \ 00127 return values; \ 00128 } \ 00129 }; \ 00130 if (!enode.get_enum_values) \ 00131 { \ 00132 enode.get_enum_values = Sub::get_enum_values; \ 00133 enode.get_choice_values = EnumType ## _choice_values; \ 00134 } \ 00135 return &enode.node; \ 00136 } \ 00137 extern ::Bse::ExportTypeKeeper bse_type_keeper__3##EnumType; 00138 #define BSE_CXX_REGISTER_ENUM(EnumType) \ 00139 ::Bse::ExportTypeKeeper \ 00140 bse_type_keeper__3##EnumType (bse_export_node<EnumType>, \ 00141 BSE_CXX_EXPORT_IDENTITY); 00142 /* convenience creator to allow easy assignments of GEnumValue structs */ 00143 inline const GEnumValue 00144 EnumValue (int int_value, 00145 const char *value_name, 00146 const char *value_nick) 00147 { 00148 GEnumValue value; 00149 value.value = int_value; 00150 value.value_name = const_cast<char*> (value_name); 00151 value.value_nick = const_cast<char*> (value_nick); 00152 return value; 00153 } 00154 00155 /* --- record registration --- */ 00156 /* record registration is based on a static ExportTypeKeeper 00157 * object, which provides the record's get_type() implementation and 00158 * auto-registers the record's export node with the export_identity. 00159 */ 00160 #define BSE_CXX_DECLARED_RECORD_TYPE(NameSpace,RecordType) \ 00161 (::NameSpace::bse_type_keeper__1##RecordType.get_type ()) 00162 #define BSE_CXX_DECLARE_RECORD(RecordType) \ 00163 template<class E> static BseExportNode* bse_export_node (); \ 00164 template<> BseExportNode* \ 00165 bse_export_node<RecordType> () \ 00166 { \ 00167 static BseExportNodeBoxed bnode = { \ 00168 { NULL, BSE_EXPORT_NODE_RECORD, NULL, }, \ 00169 }; \ 00170 if (!bnode.node.name) { \ 00171 struct Sub { static void fill_strings (BseExportStrings *es) { \ 00172 es->blurb = RecordType::blurb(); \ 00173 es->authors = RecordType::authors(); \ 00174 es->license = RecordType::license(); \ 00175 } }; \ 00176 bnode.node.name = RecordType::type_name(); \ 00177 bnode.node.options = RecordType::options(); \ 00178 bnode.node.fill_strings = Sub::fill_strings; \ 00179 bnode.copy = Sfi::RecordHandle< RecordType >::boxed_copy; \ 00180 bnode.free = Sfi::RecordHandle< RecordType >::boxed_free; \ 00181 bnode.seqrec2boxed = ::Sfi::cxx_boxed_from_rec<RecordType>; \ 00182 bnode.boxed2recseq = ::Sfi::cxx_boxed_to_rec<RecordType>; \ 00183 bnode.func.get_fields = RecordType::get_fields; \ 00184 } \ 00185 return &bnode.node; \ 00186 } \ 00187 extern ::Bse::ExportTypeKeeper bse_type_keeper__1##RecordType; 00188 #define BSE_CXX_REGISTER_RECORD(RecordType) \ 00189 ::Bse::ExportTypeKeeper \ 00190 bse_type_keeper__1##RecordType (bse_export_node<RecordType>, \ 00191 BSE_CXX_EXPORT_IDENTITY); 00192 00193 00194 /* --- sequence registration --- */ 00195 /* sequence registration works similar to record registration */ 00196 #define BSE_CXX_DECLARED_SEQUENCE_TYPE(NameSpace,SequenceType) \ 00197 (::NameSpace::bse_type_keeper__2##SequenceType.get_type ()) 00198 #define BSE_CXX_DECLARE_SEQUENCE(SequenceType) \ 00199 template<class E> static BseExportNode* bse_export_node (); \ 00200 template<> BseExportNode* \ 00201 bse_export_node<SequenceType> () \ 00202 { \ 00203 static BseExportNodeBoxed bnode = { \ 00204 { NULL, BSE_EXPORT_NODE_SEQUENCE, NULL, }, \ 00205 }; \ 00206 if (!bnode.node.name) { \ 00207 struct Sub { static void fill_strings (BseExportStrings *es) { \ 00208 es->blurb = SequenceType::blurb(); \ 00209 es->authors = SequenceType::authors(); \ 00210 es->license = SequenceType::license(); \ 00211 } }; \ 00212 bnode.node.name = SequenceType::type_name(); \ 00213 bnode.node.options = SequenceType::options(); \ 00214 bnode.node.fill_strings = Sub::fill_strings; \ 00215 bnode.copy = SequenceType::boxed_copy; \ 00216 bnode.free = SequenceType::boxed_free; \ 00217 bnode.seqrec2boxed = ::Sfi::cxx_boxed_from_seq<SequenceType>; \ 00218 bnode.boxed2recseq = ::Sfi::cxx_boxed_to_seq<SequenceType>; \ 00219 bnode.func.get_element = SequenceType::get_element; \ 00220 } \ 00221 return &bnode.node; \ 00222 } \ 00223 extern ::Bse::ExportTypeKeeper bse_type_keeper__2##SequenceType; 00224 #define BSE_CXX_REGISTER_SEQUENCE(SequenceType) \ 00225 ::Bse::ExportTypeKeeper \ 00226 bse_type_keeper__2##SequenceType (bse_export_node<SequenceType>, \ 00227 BSE_CXX_EXPORT_IDENTITY); 00228 00229 00230 /* --- procedure registration --- */ 00231 /* procedure registration works similar to enum registration. */ 00232 #define BSE_CXX_DECLARED_PROC_TYPE(NameSpace,ProcType) \ 00233 (::NameSpace::bse_type_keeper__9##ProcType.get_type ()) 00234 #define BSE_CXX_DECLARE_PROC(ProcType) \ 00235 extern ::Bse::ExportTypeKeeper bse_type_keeper__9##ProcType; 00236 #define BSE_CXX_REGISTER_PROCEDURE(ProcType) \ 00237 template<class C> static ::BseExportNode* bse_export_node (); \ 00238 template<> ::BseExportNode* \ 00239 bse_export_node<Procedure::ProcType> () \ 00240 { \ 00241 static ::BseExportNodeProc pnode = { \ 00242 { NULL, ::BSE_EXPORT_NODE_PROC, NULL, }, \ 00243 0, Procedure::ProcType::init, Procedure::ProcType::marshal, \ 00244 }; \ 00245 if (!pnode.node.name) { \ 00246 struct Sub { static void fill_strings (BseExportStrings *es) { \ 00247 es->blurb = Procedure::ProcType::blurb(); \ 00248 es->authors = Procedure::ProcType::authors(); \ 00249 es->license = Procedure::ProcType::license(); \ 00250 es->i18n_category = Procedure::ProcType::i18n_category(); \ 00251 } }; \ 00252 pnode.node.name = Procedure::ProcType::type_name(); \ 00253 pnode.node.options = Procedure::ProcType::options(); \ 00254 pnode.node.category = Procedure::ProcType::category(); \ 00255 pnode.node.pixstream = Procedure::ProcType::pixstream(); \ 00256 pnode.node.fill_strings = Sub::fill_strings; \ 00257 } \ 00258 return &pnode.node; \ 00259 } \ 00260 ::Bse::ExportTypeKeeper \ 00261 bse_type_keeper__9##ProcType (bse_export_node<Procedure::ProcType>, \ 00262 BSE_CXX_EXPORT_IDENTITY); 00263 00264 00265 /* --- class registration --- */ 00266 /* class registration works similar to enum registration. 00267 * in addition, we need to define a couple trampoline functions to make 00268 * C++ methods callable, and for effects, we're providing some basic 00269 * method implementations to interface with the synmthesis Module. 00270 */ 00271 #define BSE_CXX_DECLARED_CLASS_TYPE(NameSpace,ClassType) \ 00272 (::NameSpace::bse_type_keeper__0##ClassType.get_type ()) 00273 #define BSE_CXX_DECLARE_CLASS(ClassType) \ 00274 extern ::Bse::ExportTypeKeeper bse_type_keeper__0##ClassType; 00275 #define BSE_CXX_REGISTER_EFFECT(Effect) \ 00276 BSE_CXX_DEFINE_STATIC_DATA (Effect##Base); \ 00277 template<class C> static ::BseExportNode* bse_export_node (); \ 00278 template<> ::BseExportNode* \ 00279 bse_export_node<Effect> () \ 00280 { \ 00281 static ::BseExportNodeClass cnode = { \ 00282 { NULL, ::BSE_EXPORT_NODE_CLASS, NULL, }, \ 00283 "BseEffect", BSE_CXX_COMMON_CLASS_SIZE, \ 00284 (GClassInitFunc) static_cast <void (*) (::Bse::CxxBaseClass*)> \ 00285 (::Bse::cxx_class_init_trampoline<Effect>), \ 00286 NULL, \ 00287 BSE_CXX_INSTANCE_OFFSET + sizeof (Effect), \ 00288 ::Bse::cxx_instance_init_trampoline<Effect>, \ 00289 }; \ 00290 if (!cnode.node.name) { \ 00291 struct Sub { static void fill_strings (BseExportStrings *es) { \ 00292 es->blurb = Effect::blurb(); \ 00293 es->authors = Effect::authors(); \ 00294 es->license = Effect::license(); \ 00295 es->i18n_category = Effect::i18n_category(); \ 00296 } }; \ 00297 cnode.node.name = Effect::type_name(); \ 00298 cnode.node.options = Effect::options(); \ 00299 cnode.node.category = Effect::category(); \ 00300 cnode.node.pixstream = Effect::pixstream(); \ 00301 cnode.node.fill_strings = Sub::fill_strings; \ 00302 } \ 00303 return &cnode.node; \ 00304 } \ 00305 ::Bse::ExportTypeKeeper \ 00306 bse_type_keeper__0##Effect (bse_export_node<Effect>, \ 00307 BSE_CXX_EXPORT_IDENTITY); 00308 /* implement static_data portions used by auto-generated classes */ 00309 #define BSE_CXX_DEFINE_STATIC_DATA(ObjectType) \ 00310 ObjectType::StaticData ObjectType::static_data; 00311 00312 00313 /* --- type keeper for export nodes --- */ 00314 class ExportTypeKeeper 00315 { 00316 BseExportNode *enode; 00317 BsePlugin *plugin; 00318 static BsePlugin* plugin_export_node (const ::BseExportIdentity *plugin_identity, 00319 ::BseExportNode *enode); 00320 static void plugin_cleanup (BsePlugin *plugin, 00321 ::BseExportNode *enode); 00322 RAPICORN_CLASS_NON_COPYABLE (ExportTypeKeeper); 00323 public: 00324 ExportTypeKeeper (::BseExportNode* (*export_node) (), 00325 ::BseExportIdentity *export_identity) 00326 { 00327 enode = export_node(); 00328 plugin = plugin_export_node (export_identity, enode); 00329 } 00330 ~ExportTypeKeeper() 00331 { 00332 if (plugin) 00333 plugin_cleanup (plugin, enode); 00334 } 00335 const GType get_type() { return enode->type; } 00336 }; 00337 } // Bse 00338 /* include generated C++ core types */ 00339 #include <bse/bsebasics.genidl.hh> /* includes bsecxxplugin.hh itself */ 00340 /* define types dependant on bsebasics.idl */ 00341 namespace Bse { 00342 /* --- trampoline templates --- */ 00343 template<class ObjectType, typename PropertyID> static void 00344 cxx_get_candidates_trampoline (BseItem *item, 00345 guint prop_id, 00346 BsePropertyCandidates *pc, 00347 GParamSpec *pspec) 00348 { 00349 CxxBase *cbase = cast (item); 00350 ObjectType *instance = static_cast<ObjectType*> (cbase); 00351 if (0) // check ObjectType::get_candidates() member and prototype 00352 (void) static_cast<void (ObjectType::*) (PropertyID, ::Bse::PropertyCandidatesHandle&, GParamSpec*)> (&ObjectType::get_candidates); 00353 ::Bse::PropertyCandidatesHandle pch (::Sfi::INIT_NULL); 00354 ::Bse::PropertyCandidates *cxxpc = (::Bse::PropertyCandidates*) pc; 00355 if (cxxpc) 00356 pch.take (cxxpc); /* take as pointer, not via CopyConstructor */ 00357 instance->get_candidates (static_cast<PropertyID> (prop_id), pch, pspec); 00358 if (cxxpc) 00359 pch.steal(); /* steal to avoid destruction */ 00360 } 00361 00362 } // Bse 00363 00364 #endif /* __BSE_CXX_PLUGIN_H__ */