BEAST/BSE - Better Audio System and Sound Engine  0.8.2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
bsecxxmodule.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_MODULE_H__
00003 #define __BSE_CXX_MODULE_H__
00004 
00005 #include <bse/bsecxxbase.hh>
00006 #include <bse/bseieee754.hh>
00007 
00008 namespace Bse {
00009 
00010 /* enums/structures mirrored from bseengine.hh */
00011 enum ProcessCost {
00012   NORMAL,
00013   CHEAP,
00014   EXPENSIVE
00015 };
00016 struct JStream {
00017   const float **values;
00018   uint          n_connections;
00019   /* private: */
00020   uint          jcount; /* reserved */
00021 };
00022 struct IStream {
00023   const float  *values;
00024   gboolean      connected;
00025 };
00026 struct OStream {
00027   float        *values;
00028   gboolean      connected;
00029 };
00030 
00031 class Effect;
00032 
00033 class SynthesisModule {
00034   template<class T, typename P> class ClosureP1; /* 1-argument member function closure */
00035   BseModule     *intern_module;
00036 public:
00037   explicit                  SynthesisModule ();
00038   virtual                  ~SynthesisModule () = 0;
00039   virtual void              reset           () = 0;
00040   virtual void              process         (uint n_values) = 0;
00041   virtual const ProcessCost cost            ();
00042   inline const IStream&     istream         (uint istream_index) const;
00043   inline const JStream&     jstream         (uint jstream_index) const;
00044   inline const OStream&     ostream         (uint ostream_index) const;
00045   void                      ostream_set     (uint ostream_index,
00046                                              const float *values);
00047   const float*              const_values    (float  value);
00048   inline const uint         mix_freq        () const;
00049   inline const uint         block_size      () const;
00050   inline guint64            tick_stamp      ();
00051   inline BseModule*         engine_module   ();
00052   static inline int         dtoi            (double d) { return bse_dtoi (d); }
00053   static inline int         ftoi            (float  f) { return bse_ftoi (f); }
00054   /* member functions and closures */
00055   struct Closure {
00056     virtual void            operator()      (SynthesisModule*) = 0;
00057     virtual                ~Closure         ()         {}
00058   };
00059   /* create a 1-argument member function closure, where C must be derived from SynthesisModule */
00060   template<class D, class C>
00061   static Closure*           make_closure    (void    (C::*method) (D*),
00062                                              const D     &data);
00063   /* internal */
00064   void                      set_module      (BseModule *module);
00065   /* auto_update() trampoline */
00066 public:
00067   typedef void     (*AutoUpdate)            (BseModule*, gpointer);
00068   struct AutoUpdateData {
00069     guint       prop_id;
00070     double      prop_value;
00071     /* required by back propagation */
00072     guint64     tick_stamp;
00073     GParamSpec *pspec;
00074     Effect     *effect;
00075   };    
00076   struct NeedAutoUpdateTag {};
00077 protected:
00078   template<class M, class P, class C> struct Trampoline {
00079     static void auto_update_accessor (BseModule*, gpointer);
00080   };
00081   /* partial trampoline specializations */
00082   template<class M, class P> struct Trampoline<M,P,NeedAutoUpdateTag> {
00083     static void auto_update_accessor (BseModule*, gpointer);
00084   };
00085   template<class M, class P> struct Trampoline<M,P,void> {
00086     static void auto_update_accessor (BseModule*, gpointer);
00087   };
00088 };
00089 
00090 #define BSE_TYPE_EFFECT         (BSE_CXX_TYPE_GET_REGISTERED (Bse, Effect))
00091 class EffectBase : public CxxBase {};
00092 class Effect : public EffectBase {
00093 private:
00094   guint64                   last_module_update;
00095 public:
00096   /* BseObject functionality */
00097   explicit                  Effect               ();
00098   void                      set_property         (guint            prop_id,
00099                                                   const Value     &value,
00100                                                   GParamSpec      *pspec);
00101   void                      get_property         (guint            prop_id,
00102                                                   Value           &value,
00103                                                   GParamSpec      *pspec);
00104   /* BseSource accessors */
00105   bool          is_prepared()               const { return BSE_SOURCE_PREPARED (gobject()); }
00106   guint         n_ichannels()               const { return BSE_SOURCE_N_ICHANNELS (gobject()); }
00107   guint         n_joint_ichannels()         const { return BSE_SOURCE_N_JOINT_ICHANNELS (gobject()); }
00108   guint         n_ochannels()               const { return BSE_SOURCE_N_OCHANNELS (gobject()); }
00109   bool          is_joint_ichannel (guint i) const { return BSE_SOURCE_IS_JOINT_ICHANNEL (gobject(), i); }
00110   guint         ichannels_istream (guint i) const { return BSE_SOURCE_ICHANNEL_ISTREAM (gobject(), i); }
00111   guint         ichannels_jstream (guint i) const { return BSE_SOURCE_ICHANNEL_JSTREAM (gobject(), i); }
00112   guint         ochannels_ostream (guint i) const { return BSE_SOURCE_OCHANNEL_OSTREAM (gobject(), i); }
00113   const gchar*  ichannel_ident    (guint i) const { return BSE_SOURCE_ICHANNEL_IDENT (gobject(), i); }
00114   const gchar*  ichannel_label    (guint i) const { return BSE_SOURCE_ICHANNEL_LABEL (gobject(), i); }
00115   const gchar*  ichannel_blurb    (guint i) const { return BSE_SOURCE_ICHANNEL_BLURB (gobject(), i); }
00116   const gchar*  ochannel_ident    (guint i) const { return BSE_SOURCE_OCHANNEL_IDENT (gobject(), i); }
00117   const gchar*  ochannel_label    (guint i) const { return BSE_SOURCE_OCHANNEL_LABEL (gobject(), i); }
00118   const gchar*  ochannel_blurb    (guint i) const { return BSE_SOURCE_OCHANNEL_BLURB (gobject(), i); }
00119   virtual SynthesisModule*  create_module              (uint             context_handle,
00120                                                         BseTrans        *trans) = 0;
00121   virtual SynthesisModule::
00122   Closure*                  make_module_config_closure () = 0;
00123   virtual SynthesisModule::
00124   AutoUpdate                get_module_auto_update     () = 0;
00125   void                      update_modules             (BseTrans        *trans = NULL);
00126   guint64                   module_update_tick_stamp   () { return last_module_update; }
00127   /* prepare & dismiss pre and post invocation hooks */
00128   virtual void  prepare1()      { /* override this to do something before parent class prepare */ }
00129   virtual void  prepare2()      { /* override this to do something after parent class prepare */ }
00130   virtual void  reset1()        { /* override this to do something before parent class dismiss */ }
00131   virtual void  reset2()        { /* override this to do something after parent class dismiss */ }
00132 
00133   static void               class_init                 (CxxBaseClass    *klass);
00134 protected:
00135   const BseModuleClass*     create_engine_class        (SynthesisModule *sample_module,
00136                                                         int              cost = -1,
00137                                                         int              n_istreams = -1,
00138                                                         int              n_jstreams = -1,
00139                                                         int              n_ostreams = -1);
00140   virtual BseModule*        integrate_engine_module    (uint             context_handle,
00141                                                         BseTrans        *trans);
00142   virtual void              dismiss_engine_module      (BseModule       *engine_module,
00143                                                         guint            context_handle,
00144                                                         BseTrans        *trans);
00145   uint                      block_size                 () const;
00146   uint                      max_block_size             () const;
00147 public: /* FIXME: make this protected as soon as the modules have their own current_musical_tuning() accessor */
00148   BseMusicalTuningType      current_musical_tuning     () const;
00149 };
00150 /* implement Bse::Effect and Bse::SynthesisModule methods */
00151 #define BSE_EFFECT_INTEGRATE_MODULE(ObjectType,ModuleType,ParamType)            \
00152 Bse::SynthesisModule*                                                           \
00153 create_module (uint         context_handle,                                     \
00154                BseTrans    *trans)                                              \
00155 {                                                                               \
00156   /* check that 'this' is a ObjectType* */                                      \
00157   (void) const_cast<ObjectType*> (this);                                        \
00158   /* create a synthesis module */                                               \
00159   return new ModuleType();                                                      \
00160 }                                                                               \
00161 Bse::SynthesisModule::Closure*                                                  \
00162 make_module_config_closure()                                                    \
00163 {                                                                               \
00164   return SynthesisModule::make_closure (&ModuleType::config, ParamType (this)); \
00165 }                                                                               \
00166 Bse::SynthesisModule::AutoUpdate                                                \
00167 get_module_auto_update()                                                        \
00168 {                                                                               \
00169   return SynthesisModule::Trampoline<ModuleType,ParamType,                      \
00170                   ObjectType::AutoUpdateCategory>::auto_update_accessor;        \
00171 }
00172 template<class M, class P>
00173 void
00174 SynthesisModule::Trampoline<M,P,SynthesisModule::NeedAutoUpdateTag>::
00175 auto_update_accessor (BseModule *bmodule,      /* Engine Thread */
00176                       gpointer   data)
00177 {
00178   M *m = static_cast<M*> (BSE_MODULE_GET_USER_DATA (bmodule));
00179   AutoUpdateData *au = static_cast<AutoUpdateData*> (data);
00180   typename P::IDType prop_id = static_cast<typename P::IDType> (au->prop_id);
00181   if (0)        // check M::auto_update() member and prototype
00182     (void) static_cast<void (M::*) (typename P::IDType, double)> (&M::auto_update);
00183   m->auto_update (prop_id, au->prop_value);
00184 }
00185 template<class M, class P>
00186 void
00187 SynthesisModule::Trampoline<M,P,void>::
00188 auto_update_accessor (BseModule *bmodule,
00189                       gpointer   data)
00190 {
00191 }
00192 
00193 
00194 /* --- implementation details --- */
00195 namespace externC { extern "C" {
00196 extern guint bse_engine_exvar_sample_freq;
00197 extern guint bse_engine_exvar_block_size;
00198 extern guint64 bse_module_tick_stamp (BseModule*);
00199 } }
00200 inline BseModule*
00201 SynthesisModule::engine_module ()
00202 {
00203   return intern_module;
00204 }
00205 inline const uint
00206 SynthesisModule::mix_freq () const
00207 {
00208   return externC::bse_engine_exvar_sample_freq;
00209 }
00210 inline const uint
00211 SynthesisModule::block_size () const
00212 {
00213   return externC::bse_engine_exvar_block_size;
00214 }
00215 inline guint64
00216 SynthesisModule::tick_stamp ()
00217 {
00218   return externC::bse_module_tick_stamp (engine_module());
00219 }
00220 inline const IStream&
00221 SynthesisModule::istream (uint         istream_index) const
00222 {
00223   void *istreams = BSE_MODULE_GET_ISTREAMSP (intern_module);
00224   return reinterpret_cast<IStream*> (istreams)[istream_index];
00225 }
00226 inline const JStream&
00227 SynthesisModule::jstream (uint         jstream_index) const
00228 {
00229   void *jstreams = BSE_MODULE_GET_JSTREAMSP (intern_module);
00230   return reinterpret_cast<JStream*> (jstreams)[jstream_index];
00231 }
00232 inline const OStream&
00233 SynthesisModule::ostream (uint         ostream_index) const
00234 {
00235   void *ostreams = BSE_MODULE_GET_OSTREAMSP (intern_module);
00236   return reinterpret_cast<OStream*> (ostreams)[ostream_index];
00237 }
00238 template<class T, typename P>
00239 class SynthesisModule::ClosureP1 : public SynthesisModule::Closure {
00240   typedef void (T::*Member) (P*);
00241   Member    func;
00242   P        *data;
00243 public:
00244   ClosureP1 (void (T::*f) (P*), P *p)
00245     : func (f), data (p)
00246   {
00247     assert_derived_from<T,SynthesisModule>();
00248   }
00249   void operator() (SynthesisModule *p)
00250   {
00251     T *t = static_cast<T*> (p);
00252     (t->*func) (data);
00253   }
00254   ~ClosureP1 ()
00255   {
00256     delete data;
00257   }
00258 };
00259 template<class D, class C> SynthesisModule::Closure*
00260 SynthesisModule::make_closure (void   (C::*method) (D*),
00261                                const D    &data)
00262 {
00263   D *d = new D (data);
00264   ClosureP1<C,D> *ac = new ClosureP1<C,D> (method, d);
00265   return ac;
00266 }
00267 
00268 } // Bse
00269 
00270 #endif /* __BSE_CXX_MODULE_H__ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines