Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

dssiplugin.hpp

Go to the documentation of this file.
00001 /****************************************************************************
00002     
00003     dssiplugin.hpp - a class and functions that should make it easier to
00004                      write DSSI plugins in C++
00005     
00006     Copyright (C) 2005  Lars Luthman <larsl@users.sourceforge.net>
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 2 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 
00027 #ifndef DSSIPLUGIN_HPP
00028 #define DSSIPLUGIN_HPP
00029 
00030 #include <unistd.h>
00031 
00032 #include <cstring>
00033 #include <string>
00034 #include <map>
00035 #include <vector>
00036 
00037 #include <dssi.h>
00038 
00039 
00040 extern "C" {
00041   /*This is the one function that needs to be in all DSSI plugin libraries.
00042     It is called by the host and returns descriptors for all plugins that
00043     the library contains. Only for use by the host, you should not touch this
00044     in your plugin. */
00045   /* Yes, this is intentionally not documented with Doxygen comments. */
00046   const DSSI_Descriptor* dssi_descriptor(unsigned long index);
00047 }
00048 
00049 
00050 /* A helper class that stores info about a DSSI port. You should not need
00051    to use this class, it's only for internal use. */
00052 /* Yes, this is intentionally not documented with Doxygen comments. */
00053 struct DSSIPort {
00054   DSSIPort(LADSPA_PortDescriptor descriptor, const std::string& name, 
00055            const LADSPA_PortRangeHint& hint)
00056     : m_descriptor(descriptor), m_name(name), m_hint(hint) { }
00057   DSSIPort(LADSPA_PortDescriptor descriptor, const std::string& name)
00058     : m_descriptor(descriptor), m_name(name) {
00059     memset(&m_hint, 0, sizeof(LADSPA_PortRangeHint));
00060   }
00061 
00062   LADSPA_PortDescriptor m_descriptor;
00063   std::string m_name;
00064   LADSPA_PortRangeHint m_hint;
00065 };
00066 
00067 
00072 enum DSSIFeatureMask {
00074   DSSI_NO_FEATURES = 0,
00077   DSSI_RECEIVES_MIDI = 1 << 0,
00080   DSSI_HAS_PROGRAMS = 1 << 1,
00085   DSSI_USES_SHM = 1 << 2
00086 };
00087 
00088 
00090 inline DSSIFeatureMask operator|(const DSSIFeatureMask& m1, 
00091                                  const DSSIFeatureMask& m2) {
00092   return DSSIFeatureMask(static_cast<unsigned>(m1) | static_cast<unsigned>(m2));
00093 }
00094 
00095 
00099 struct DSSIPortList : public std::vector<DSSIPort> {
00100   
00102   int add_port(LADSPA_PortDescriptor descriptor, const std::string& name,
00103                 const LADSPA_PortRangeHint& hint) {
00104     push_back(DSSIPort(descriptor, name, hint));
00105     return size() - 1;
00106   }
00107   
00109   int add_port(LADSPA_PortDescriptor descriptor, const std::string& name) {
00110     push_back(DSSIPort(descriptor, name));
00111     return size() - 1;
00112   }
00113   
00115   int add_port(LADSPA_PortDescriptor descriptor, const std::string name,
00116                LADSPA_PortRangeHintDescriptor rh_desc,
00117                LADSPA_Data lower_bound, LADSPA_Data upper_bound) {
00118     LADSPA_PortRangeHint prh = { rh_desc, lower_bound, upper_bound };
00119     push_back(DSSIPort(descriptor, name, prh));
00120     return size() - 1;
00121   }
00122 
00123 };
00124 
00125 
00126 
00145 template <class T>
00146 size_t register_dssi(const std::string& label, LADSPA_Properties properties, 
00147                      const std::string& name, const std::string& maker, 
00148                      const std::string& copyright, const DSSIPortList& ports,
00149                      DSSIFeatureMask features = DSSI_RECEIVES_MIDI | 
00150                      DSSI_HAS_PROGRAMS | DSSI_USES_SHM);
00151 
00152 
00153 
00216 class DSSIPlugin {
00217 public:
00218   
00220   // @{
00221   
00223   virtual ~DSSIPlugin();
00224   
00226   virtual void activate() { }
00227   
00229   virtual void deactivate() { }
00230 
00231   // @}
00232 
00233   
00235   // @{
00236   
00238   virtual char* configure(const char* key, const char* value) { return NULL; }
00239   
00243   virtual int get_midi_controller_for_port(unsigned long port) { 
00244     return DSSI_NONE;
00245   }
00246   
00251   virtual const DSSI_Program_Descriptor* get_program(unsigned long index) {
00252     return NULL;
00253   }
00254   
00263   virtual bool shm_attached(void* shm, size_t size) { 
00264     return false; 
00265   }
00266   
00277   virtual void shm_detach_request(void* shm) { shm_detach(shm); }
00278   
00279   // @}
00280   
00281 
00283   // @{
00284   
00290   virtual void run(unsigned long sample_count) {
00291     run_synth(sample_count, NULL, 0);
00292   }
00293 
00298   virtual void run_synth(unsigned long sample_count, snd_seq_event_t* events,
00299                          unsigned long event_count) { }
00300   
00304   virtual void select_program(unsigned long bank, unsigned long program) { }
00305   
00308   virtual void connect_port(unsigned long port, LADSPA_Data* data_location) {
00309     m_ports[port] = data_location;
00310   }
00311   
00313   
00314   
00315   friend const DSSI_Descriptor* dssi_descriptor(unsigned long index);
00316   template <class T> friend 
00317   size_t register_dssi(const std::string& label, LADSPA_Properties properties, 
00318                        const std::string& name, const std::string& maker, 
00319                        const std::string& copyright, const DSSIPortList& ports,
00320                        DSSIFeatureMask features);
00321 
00322   
00323 protected:
00324 
00328   void shm_detach(void* shm);
00329   
00332   std::vector<LADSPA_Data*> m_ports;
00333   
00334   
00335 private:
00336 
00337   /* This function returns the global vector of DSSI_Descriptors that is added 
00338      to by register_dssi(). It is used by the dssi_descriptor() function. */
00339   static std::vector<DSSI_Descriptor>& get_dssi_descriptors();
00340   
00341   /* Static callbacks */
00342   static void _activate(LADSPA_Handle instance);
00343   static void _deactivate(LADSPA_Handle instance);
00344   static void _cleanup(LADSPA_Handle instance);
00345 
00346   static char* _configure(LADSPA_Handle instance, 
00347                           const char* key, const char* value);
00348   static char* _configure_with_shm(LADSPA_Handle instance, 
00349                                    const char* key, const char* value);
00350   static int _get_midi_controller_for_port(LADSPA_Handle instance, 
00351                                            unsigned long port);
00352   static const DSSI_Program_Descriptor* _get_program(LADSPA_Handle instance,
00353                                                      unsigned long index);
00354   
00355   static void _run(LADSPA_Handle instance, unsigned long sample_count);
00356   static void _run_synth(LADSPA_Handle instance, unsigned long sample_count, 
00357                          snd_seq_event_t* events, unsigned long event_count);
00358   static void _select_program(LADSPA_Handle instance, 
00359                               unsigned long bank, unsigned long program);
00360   static void _connect_port(LADSPA_Handle instance, unsigned long port, 
00361                             LADSPA_Data* data_location);
00362   
00363   /*This template function is instantiated for each plugin class and used 
00364     as the instantiation function. */
00365   template <class T>
00366   static LADSPA_Handle create_plugin_instance(const LADSPA_Descriptor* 
00367                                               descriptor,
00368                                               unsigned long sample_rate) {
00369     T* t = new T(sample_rate);
00370     t->m_ports.resize(descriptor->PortCount, NULL);
00371     return reinterpret_cast<LADSPA_Handle>(t);
00372   }
00373 
00374   std::map<std::string, void*> m_segments;
00375   
00376 };
00377 
00378 
00379 
00380 template <class T>
00381 size_t register_dssi(const std::string& label, LADSPA_Properties properties, 
00382                      const std::string& name, const std::string& maker, 
00383                      const std::string& copyright, const DSSIPortList& ports,
00384                      DSSIFeatureMask features) {
00385   
00386   DSSI_Descriptor descriptor;
00387   memset(&descriptor, 0, sizeof(DSSI_Descriptor));
00388   descriptor.DSSI_API_Version = 1;
00389       
00390   LADSPA_Descriptor* l_descriptor = 
00391     (LADSPA_Descriptor*)calloc(1, sizeof(LADSPA_Descriptor));
00392   descriptor.LADSPA_Plugin = l_descriptor;
00393   
00394   l_descriptor->UniqueID = 666;
00395   l_descriptor->Label = strdup(label.c_str());
00396   l_descriptor->Properties = properties;
00397   l_descriptor->Name = strdup(name.c_str());
00398   l_descriptor->Maker = strdup(maker.c_str());
00399   l_descriptor->Copyright = strdup(copyright.c_str());
00400     
00401   l_descriptor->PortCount = ports.size();
00402   LADSPA_PortDescriptor* port_desc = 
00403     (LADSPA_PortDescriptor*)calloc(ports.size(), sizeof(LADSPA_PortDescriptor));
00404   char** port_name = (char**)calloc(ports.size(), sizeof(const char*));
00405   LADSPA_PortRangeHint* port_hint = 
00406     (LADSPA_PortRangeHint*)calloc(ports.size(), sizeof(LADSPA_PortRangeHint));
00407   for (unsigned i = 0; i < ports.size(); ++i) {
00408     port_desc[i] = ports[i].m_descriptor;
00409     port_name[i] = strdup(ports[i].m_name.c_str());
00410     port_hint[i] = ports[i].m_hint;
00411   }
00412   l_descriptor->PortDescriptors = port_desc;
00413   l_descriptor->PortNames = port_name;
00414   l_descriptor->PortRangeHints = port_hint;
00415     
00416   l_descriptor->instantiate = &DSSIPlugin::create_plugin_instance<T>;
00417   l_descriptor->cleanup = &DSSIPlugin::_cleanup;
00418   l_descriptor->connect_port = &DSSIPlugin::_connect_port;
00419   l_descriptor->activate = &DSSIPlugin::_activate;
00420   l_descriptor->run = &DSSIPlugin::_run;
00421   l_descriptor->deactivate = &DSSIPlugin::_deactivate;
00422   
00423   if (features & DSSI_USES_SHM)
00424     descriptor.configure = &DSSIPlugin::_configure_with_shm;
00425   else
00426     descriptor.configure = &DSSIPlugin::_configure;
00427   
00428   if (features & DSSI_RECEIVES_MIDI) {
00429     descriptor.run_synth = &DSSIPlugin::_run_synth;
00430     descriptor.get_midi_controller_for_port =
00431       &DSSIPlugin::_get_midi_controller_for_port;
00432   }
00433   else {
00434     descriptor.run_synth = 0;
00435     descriptor.get_midi_controller_for_port = 0;
00436   }
00437   
00438   if (features & DSSI_HAS_PROGRAMS) {
00439     descriptor.get_program = &DSSIPlugin::_get_program;
00440     descriptor.select_program = &DSSIPlugin::_select_program;
00441   }
00442   else {
00443     descriptor.get_program = 0;
00444     descriptor.select_program = 0;
00445   }
00446   
00447   DSSIPlugin::get_dssi_descriptors().push_back(descriptor);
00448   
00449   return DSSIPlugin::get_dssi_descriptors().size() - 1;
00450 }
00451 
00452 
00453 
00454 #endif
00455 
00456 

Generated on Wed Mar 1 17:12:44 2006 for DSSI support libraries by  doxygen 1.4.4