BEAST/BSE - Better Audio System and Sound Engine  0.8.2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
bsecxxplugin.hh
Go to the documentation of this file.
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__ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines