• Main Page
  • Modules
  • Classes
  • Files
  • File List

libraries/lv2plugin/lv2plugin.hpp

00001 /****************************************************************************
00002     
00003     lv2plugin.hpp - support file for writing LV2 plugins in C++
00004     
00005     Copyright (C) 2006-2007 Lars Luthman <lars.luthman@gmail.com>
00006     Modified by Dave Robillard, 2008
00007 
00008     This program is free software; you can redistribute it and/or modify
00009     it under the terms of the GNU General Public License as published by
00010     the Free Software Foundation; either version 3 of the License, or
00011     (at your option) any later version.
00012     
00013     This program is distributed in the hope that it will be useful,
00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016     GNU General Public License for more details.
00017     
00018     You should have received a copy of the GNU General Public License
00019     along with this program; if not, write to the Free Software
00020     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 01222-1307  USA
00021 
00022 ****************************************************************************/
00023 
00024 #ifndef LV2PLUGIN_HPP
00025 #define LV2PLUGIN_HPP
00026 
00027 #include <cstdarg>
00028 
00029 #include <cstring>
00030 #include <string>
00031 #include <vector>
00032 
00033 #include <lv2.h>
00034 #include <lv2_uri_map.h>
00035 #include <lv2_saverestore.h>
00036 #include <lv2_event.h>
00037 #include <lv2_contexts.h>
00038 #include <lv2types.hpp>
00039 
00040 
00073 namespace LV2 {
00074   
00075 
00079   class DescList : public std::vector<LV2_Descriptor> {
00080   public:
00081     ~DescList();
00082   };
00083 
00084 
00088   DescList& get_lv2_descriptors();
00089 
00090   
00131   template <class Derived, 
00132             class Ext1 = End, class Ext2 = End, class Ext3 = End,
00133             class Ext4 = End, class Ext5 = End, class Ext6 = End, 
00134             class Ext7 = End, class Ext8 = End, class Ext9 = End>
00135   class Plugin : public MixinTree<Derived, 
00136                                   Ext1, Ext2, Ext3, Ext4, Ext5, 
00137                                   Ext6, Ext7, Ext8, Ext9> {
00138   public:
00139     
00146     Plugin(uint32_t ports) 
00147       : m_ports(ports, 0),
00148         m_ok(true) {
00149       m_features = s_features;
00150       m_bundle_path = s_bundle_path;
00151       s_features = 0;
00152       s_bundle_path = 0;
00153       if (m_features) {
00154         FeatureHandlerMap hmap;
00155         Derived::map_feature_handlers(hmap);
00156         for (const Feature* const* iter = m_features; *iter != 0; ++iter) {
00157           FeatureHandlerMap::iterator miter;
00158           miter = hmap.find((*iter)->URI);
00159           if (miter != hmap.end())
00160             miter->second(static_cast<Derived*>(this), (*iter)->data);
00161         }
00162       }
00163     }
00164     
00174     void connect_port(uint32_t port, void* data_location) {
00175       m_ports[port] = data_location;
00176     }
00177     
00181     void activate() { }
00182   
00193     void run(uint32_t sample_count) { }
00194   
00199     void deactivate() { }
00200     
00213     static unsigned register_class(const std::string& uri) {
00214       LV2_Descriptor desc;
00215       std::memset(&desc, 0, sizeof(LV2_Descriptor));
00216       char* c_uri = new char[uri.size() + 1];
00217       std::memcpy(c_uri, uri.c_str(), uri.size() + 1);
00218       desc.URI = c_uri;
00219       desc.instantiate = &Derived::_create_plugin_instance;
00220       desc.connect_port = &Derived::_connect_port;
00221       desc.activate = &Derived::_activate;
00222       desc.run = &Derived::_run;
00223       desc.deactivate = &Derived::_deactivate;
00224       desc.cleanup = &Derived::_delete_plugin_instance;
00225       desc.extension_data = &Derived::extension_data;
00226       get_lv2_descriptors().push_back(desc);
00227       return get_lv2_descriptors().size() - 1;
00228     }
00229     
00238     bool check_ok() {
00239       return m_ok && MixinTree<Derived, 
00240                                Ext1, Ext2, Ext3, Ext4, Ext5, 
00241                                Ext6, Ext7, Ext8, Ext9>::check_ok();
00242     }
00243 
00244   protected:
00245   
00257     template <typename T> T*& p(uint32_t port) {
00258       return reinterpret_cast<T*&>(m_ports[port]);
00259     }
00260   
00264     float*& p(uint32_t port) {
00265       return reinterpret_cast<float*&>(m_ports[port]);
00266     }
00267     
00271     const char* bundle_path() const {
00272       return m_bundle_path;
00273     }
00274     
00283     void set_ok(bool ok) {
00284       m_ok = ok;
00285     }
00286     
00290     std::vector<void*> m_ports;
00291 
00292   private:
00293     
00297     static void _connect_port(LV2_Handle instance, uint32_t port, 
00298                              void* data_location) {
00299       reinterpret_cast<Derived*>(instance)->connect_port(port, data_location);
00300     }
00301   
00305     static void _activate(LV2_Handle instance) {
00306       reinterpret_cast<Derived*>(instance)->activate();
00307     }
00308   
00312     static void _run(LV2_Handle instance, uint32_t sample_count) {
00313       reinterpret_cast<Derived*>(instance)->run(sample_count);
00314     }
00315   
00319     static void _deactivate(LV2_Handle instance) {
00320       reinterpret_cast<Derived*>(instance)->deactivate();
00321     }
00322   
00327     static LV2_Handle _create_plugin_instance(const LV2_Descriptor* descriptor,
00328                                               double sample_rate,
00329                                               const char* bundle_path,
00330                                               const Feature* const* 
00331                                               features) {
00332 
00333       // copy some data to static variables so the subclasses don't have to
00334       // bother with it
00335       s_features = features;
00336       s_bundle_path = bundle_path;
00337 
00338       Derived* t = new Derived(sample_rate);
00339       if (t->check_ok())
00340         return reinterpret_cast<LV2_Handle>(t);
00341       delete t;
00342       return 0;
00343     }
00344             
00349     static void _delete_plugin_instance(LV2_Handle instance) {
00350       delete reinterpret_cast<Derived*>(instance);
00351     }
00352 
00353 
00354   private:
00355     
00360     LV2::Feature const* const* m_features;
00361     
00366     char const* m_bundle_path;
00367     
00372     static LV2::Feature const* const* s_features;
00373 
00378     static char const* s_bundle_path;
00379     
00385     bool m_ok;
00386 
00387   };
00388 
00389   
00390   // The static variables need to be initialised. 
00391   template<class Derived, class Ext1, class Ext2, class Ext3, class Ext4,
00392            class Ext5, class Ext6, class Ext7, class Ext8, class Ext9>
00393   LV2::Feature const* const* 
00394   Plugin<Derived, Ext1, Ext2, Ext3, Ext4, 
00395          Ext5, Ext6, Ext7, Ext8, Ext9>::s_features = 0;
00396   
00397   template<class Derived, class Ext1, class Ext2, class Ext3, class Ext4,
00398            class Ext5, class Ext6, class Ext7, class Ext8, class Ext9>
00399   char const* 
00400   Plugin<Derived, Ext1, Ext2, Ext3, Ext4, 
00401          Ext5, Ext6, Ext7, Ext8, Ext9>::s_bundle_path = 0;
00402 
00403   
00429   template <bool Required = true>
00430   struct FixedBufSize {
00431     
00436     template <class Derived> struct I : Extension<Required> {
00437       
00439       I() : m_buffer_size(0) { }
00440       
00442       static void map_feature_handlers(FeatureHandlerMap& hmap) {
00443         hmap["http://tapas.affenbande.org/lv2/ext/fixed-buffersize"] = 
00444           &I<Derived>::handle_feature;
00445       }
00446       
00448       static void handle_feature(void* instance, void* data) { 
00449         Derived* d = reinterpret_cast<Derived*>(instance);
00450         I<Derived>* fe = static_cast<I<Derived>*>(d);
00451         fe->m_buffer_size = *reinterpret_cast<uint32_t*>(data);
00452         fe->m_ok = true;
00453       }
00454       
00455     protected:
00456       
00460       uint32_t get_buffer_size() const { return m_buffer_size; }
00461       
00462       uint32_t m_buffer_size;
00463       
00464     };
00465     
00466   };
00467   
00476   template <bool Required = true>
00477   struct FixedP2BufSize {
00478     
00483     template <class Derived> struct I : Extension<Required> {
00484       
00486       I() : m_buffer_size(0) { }
00487       
00489       static void map_feature_handlers(FeatureHandlerMap& hmap) {
00490         hmap["http://tapas.affenbande.org/lv2/ext/power-of-two-buffersize"] = 
00491           &I<Derived>::handle_feature;
00492       }
00493       
00495       static void handle_feature(void* instance, void* data) { 
00496         Derived* d = reinterpret_cast<Derived*>(instance);
00497         I<Derived>* fe = static_cast<I<Derived>*>(d);
00498         fe->m_buffer_size = *reinterpret_cast<uint32_t*>(data);
00499         fe->m_ok = true;
00500       }
00501       
00502     protected:
00503       
00507       uint32_t get_buffer_size() const { return m_buffer_size; }
00508       
00509       uint32_t m_buffer_size;
00510       
00511     };
00512   
00513   };
00514 
00515 
00522   template <bool Required = true>
00523   struct SaveRestore {
00524     
00529     template <class Derived> struct I : Extension<Required> {
00530       
00532       I() { }
00533       
00535       static void map_feature_handlers(FeatureHandlerMap& hmap) {
00536         hmap[LV2_SAVERESTORE_URI] = &I<Derived>::handle_feature;
00537       }
00538       
00540       static void handle_feature(void* instance, void* data) { 
00541         Derived* d = reinterpret_cast<Derived*>(instance);
00542         I<Derived>* fe = static_cast<I<Derived>*>(d);
00543         fe->m_ok = true;
00544       }
00545       
00547       static const void* extension_data(const char* uri) { 
00548         if (!std::strcmp(uri, LV2_SAVERESTORE_URI)) {
00549           static LV2SR_Descriptor srdesc = { &I<Derived>::_save,
00550                                              &I<Derived>::_restore };
00551           return &srdesc;
00552         }
00553         return 0;
00554       }
00555       
00568       char* save(const char* directory, LV2SR_File*** files) { return 0; }
00569       
00576       char* restore(const LV2SR_File** files) { return 0; }
00577       
00578     protected:
00579       
00582       static char* _save(LV2_Handle h, 
00583                          const char* directory, LV2SR_File*** files) {
00584         return reinterpret_cast<Derived*>(h)->save(directory, files);
00585       }
00586       
00589       static char* _restore(LV2_Handle h, const LV2SR_File** files) {
00590         return reinterpret_cast<Derived*>(h)->restore(files);
00591       }
00592       
00593     };
00594   };
00595   
00596   
00603   template <bool Required = true>
00604   struct EventRef {
00605     
00610     template <class Derived> struct I : Extension<Required> {
00611       
00613       I() : m_callback_data(0), m_ref_func(0), m_unref_func(0) { }
00614       
00616       static void map_feature_handlers(FeatureHandlerMap& hmap) {
00617         hmap[LV2_EVENT_URI] = &I<Derived>::handle_feature;
00618       }
00619       
00621       static void handle_feature(void* instance, void* data) { 
00622         Derived* d = reinterpret_cast<Derived*>(instance);
00623         I<Derived>* fe = static_cast<I<Derived>*>(d);
00624         LV2_Event_Feature* ef = reinterpret_cast<LV2_Event_Feature*>(data);
00625         fe->m_callback_data = ef->callback_data;
00626         fe->m_ref_func = ef->lv2_event_ref;
00627         fe->m_unref_func = ef->lv2_event_unref;
00628         fe->m_ok = true;
00629       }
00630       
00631     protected:
00632       
00642       uint32_t event_ref(LV2_Event* event) {
00643         return m_ref_func(m_callback_data, event);
00644       }
00645     
00650       uint32_t event_unref(LV2_Event* event) {
00651         return m_unref_func(m_callback_data, event);
00652       }
00653     
00654       LV2_Event_Callback_Data m_callback_data;
00655       uint32_t (*m_ref_func)(LV2_Event_Callback_Data, LV2_Event*);
00656       uint32_t (*m_unref_func)(LV2_Event_Callback_Data, LV2_Event*);
00657       
00658     };
00659     
00660   };
00661 
00662 
00670   template <bool Required = true>
00671   struct MsgContext {
00672     
00677     template <class Derived> struct I : Extension<Required> {
00678       
00680       I() { }
00681       
00683       static void map_feature_handlers(FeatureHandlerMap& hmap) {
00684         hmap[LV2_CONTEXT_MESSAGE] = &I<Derived>::handle_feature;
00685       }
00686       
00688       static void handle_feature(void* instance, void* data) { 
00689         Derived* d = reinterpret_cast<Derived*>(instance);
00690         I<Derived>* fe = static_cast<I<Derived>*>(d);
00691         fe->m_ok = true;
00692       }
00693       
00695       static const void* extension_data(const char* uri) { 
00696         if (!std::strcmp(uri, LV2_CONTEXT_MESSAGE)) {
00697           static LV2_Blocking_Context desc = { &I<Derived>::_blocking_run,
00698                                                &I<Derived>::_connect_port };
00699           return &desc;
00700         }
00701         return 0;
00702       }
00703       
00708       bool blocking_run(uint8_t* outputs_written) { return false; }
00709       
00710     protected:
00711       
00714       static bool _blocking_run(LV2_Handle h, uint8_t* outputs_written) {
00715         return reinterpret_cast<Derived*>(h)->blocking_run(outputs_written);
00716       }
00717       
00720       static void _connect_port(LV2_Handle h, uint32_t port, void* buffer) {
00721         reinterpret_cast<Derived*>(h)->connect_port(port, buffer);
00722       }
00723       
00724     };
00725   };
00726 
00727 
00728 }
00729 
00730 
00731 #endif

Generated on Sun Feb 27 2011 13:41:49 by  doxygen 1.7.1