LadspaNetworkExporter.cxx

Go to the documentation of this file.
00001 #include "LadspaNetworkExporter.hxx"
00002 #include "ControlSource.hxx"
00003 #include "ControlSink.hxx"
00004 
00005 namespace CLAM
00006 {
00007 
00008 template<class T>
00009 class LADSPAInfo
00010 {
00011 public:
00012         std::string name;
00013         T* processing;
00014         LADSPA_Data *dataBuffer;
00015 };
00016 
00017 class NetworkLADSPAPlugin
00018 {
00019 private:
00020         typedef std::vector< LADSPAInfo<AudioSource> > LADSPAInPortList;
00021         typedef std::vector< LADSPAInfo<AudioSink> > LADSPAOutPortList;
00022         typedef std::vector< LADSPAInfo<ControlSource> > LADSPAInControlList;
00023         typedef std::vector< LADSPAInfo<ControlSink> > LADSPAOutControlList;
00024 
00025         Network _network;
00026         LADSPAInPortList mReceiverList;
00027         LADSPAOutPortList mSenderList;
00028         LADSPAInControlList mInControlList;
00029         LADSPAOutControlList mOutControlList;
00030         unsigned long mClamBufferSize, mExternBufferSize;
00031         
00032 public:
00033         NetworkLADSPAPlugin(const std::string & networkXmlContent);
00034         ~NetworkLADSPAPlugin();
00035         
00036         void Activate();
00037         void Deactivate();
00038         
00039         void LocateConnections();
00040         void UpdatePortFrameAndHopSize();
00041         void FillPortInfo( LADSPA_PortDescriptor* descriptors, char** names, LADSPA_PortRangeHint* rangehints );
00042         void ConnectTo(unsigned long port, LADSPA_Data * data);
00043         
00044         void Run( unsigned long nsamples );
00045         void CopyLadspaBuffersToGenerators(const unsigned long nframes);
00046         void CopySinksToLadspaBuffers(const unsigned long nframes);
00047         void ProcessInControlValues();
00048         void ProcessOutControlValues();
00049         static LADSPA_Descriptor * CreateLADSPADescriptor(
00050                 const std::string & networkXmlContent,
00051                 unsigned id,
00052                 const std::string & label,
00053                 const std::string & name,
00054                 const std::string & maker,
00055                 const std::string & copyright
00056         );
00057 };
00058 
00059 }
00060 
00061 // Ladspa Callbacks
00062 extern "C"
00063 {
00064         // Construct a new plugin instance.
00065         static LADSPA_Handle Instantiate(const LADSPA_Descriptor * descriptor, unsigned long sampleRate)
00066         {
00067 //              std::cerr << "Network2Ladspa: instantiate" << std::endl;
00068                 return new CLAM::NetworkLADSPAPlugin((const char*)descriptor->ImplementationData);
00069         }
00070         // Destruct plugin instance
00071         static void CleanUp(LADSPA_Handle handle)
00072         {
00073 //              std::cerr << "Network2Ladspa: cleanup " << handle << std::endl;
00074                 delete (CLAM::NetworkLADSPAPlugin*) handle;
00075         }
00076 
00077         // Run the plugin
00078         static void Run(LADSPA_Handle handle, unsigned long sampleCount)
00079         {
00080                 CLAM::NetworkLADSPAPlugin *p = (CLAM::NetworkLADSPAPlugin*) handle;
00081                 p->Run( sampleCount );
00082         }
00083         // Activate Plugin
00084         static void Activate(LADSPA_Handle handle)
00085         {
00086 //              std::cerr << "Network2Ladspa: activate " << handle << std::endl;
00087                 CLAM::NetworkLADSPAPlugin *p = (CLAM::NetworkLADSPAPlugin*) handle;
00088                 p->Activate();
00089         }
00090 
00091         static void Deactivate(LADSPA_Handle handle)
00092         {
00093 //              std::cerr << "Network2Ladspa: deactivate " << handle << std::endl;
00094                 CLAM::NetworkLADSPAPlugin *p = (CLAM::NetworkLADSPAPlugin*) handle;
00095                 p->Deactivate();
00096         }
00097 
00098         // Connect a port to a data location.
00099         static void ConnectTo(LADSPA_Handle handle, unsigned long port, LADSPA_Data * dataLocation)
00100         {
00101 //              std::cerr << "Network2Ladspa: connect " << port << std::endl;
00102                 CLAM::NetworkLADSPAPlugin *p = (CLAM::NetworkLADSPAPlugin*) handle;
00103                 p->ConnectTo( port, dataLocation );
00104         }
00105 }
00106 
00107 namespace CLAM
00108 {
00109 
00110 
00111 NetworkLADSPAPlugin::NetworkLADSPAPlugin(const std::string & networkXmlContent)
00112 {
00113         mClamBufferSize=512;
00114         mExternBufferSize=mClamBufferSize;
00115         _network.SetName("Testing name");
00116 
00117 //      std::cerr << "NetworkLADSPAPlugin: Constructed" << std::endl;
00118         std::istringstream xmlfile(networkXmlContent);
00119         try
00120         {
00121                 XmlStorage::Restore( _network, xmlfile);
00122         }
00123         catch ( XmlStorageErr err)
00124         {
00125                 std::cerr << "CLAM::NetworkLADSPAPlugin WARNING: error opening file <" << xmlfile << "> . Plugin not loaded" <<std::endl;
00126                 std::cerr << err.what() << std::endl;
00127                 return;
00128         }
00129 
00130         LocateConnections();
00131 }
00132 
00133 NetworkLADSPAPlugin::~NetworkLADSPAPlugin()
00134 {
00135 //      std::cerr << "NetworkLADSPAPlugin: DELETED" << std::endl;
00136 }
00137 
00138 void NetworkLADSPAPlugin::Activate()
00139 {
00140         _network.Start();
00141 }
00142 
00143 void NetworkLADSPAPlugin::Deactivate()
00144 {
00145         _network.Stop();
00146 }
00147 
00148 void NetworkLADSPAPlugin::LocateConnections()
00149 {
00150         CLAM_ASSERT( mReceiverList.empty(), "NetworkLADSPAPlugin::LocateConnections() : there are already registered input ports");
00151         CLAM_ASSERT( mSenderList.empty(), "NetworkLADSPAPlugin::LocateConnections() : there are already registered output ports");
00152         CLAM_ASSERT( mInControlList.empty(), "NetworkLADSPAPlugin::LocateConnections() : there are already registered controls");
00153         CLAM_ASSERT( mOutControlList.empty(), "NetworkLADSPAPlugin::LocateConnections() : there are already registered controls");
00154 
00155         //Get them from the Network and add it to local list            
00156         for (Network::ProcessingsMap::const_iterator it=_network.BeginProcessings(); it!=_network.EndProcessings(); it++)
00157         {
00158                 CLAM::Processing * processing = it->second;
00159                 const std::string & className = processing->GetClassName();
00160                 if (className == "AudioSource")
00161                 {
00162                         LADSPAInfo<AudioSource> info;
00163                         info.name=it->first;
00164                         info.processing=(AudioSource*)processing;
00165                         info.processing->SetFrameAndHopSize( mExternBufferSize );
00166                         mReceiverList.push_back(info);
00167                 }
00168                 if (className == "AudioSink")
00169                 {
00170                         LADSPAInfo<AudioSink> info;
00171                         info.name=it->first;
00172                         info.processing=(AudioSink*)it->second;
00173                         info.processing->SetFrameAndHopSize( mExternBufferSize );
00174                         mSenderList.push_back(info);
00175                 }
00176                 if (className == "ControlSource")
00177                 {
00178                         LADSPAInfo<ControlSource> info;
00179                         info.name=it->first;
00180                         info.processing=(ControlSource*)it->second;
00181                         mInControlList.push_back(info);
00182                 }
00183                 if (className == "ControlSink")
00184                 {
00185                         LADSPAInfo<ControlSink> info;
00186                         info.name=it->first;
00187                         info.processing=(ControlSink*)it->second;
00188                         mOutControlList.push_back(info);
00189                 }
00190         }
00191 }
00192 
00193 void NetworkLADSPAPlugin::UpdatePortFrameAndHopSize()
00194 {
00195         //AudioSources
00196         for (LADSPAInPortList::iterator it=mReceiverList.begin(); it!=mReceiverList.end(); it++)
00197                 it->processing->SetFrameAndHopSize( mExternBufferSize );
00198 
00199         //AudioSinks
00200         for (LADSPAOutPortList::iterator it=mSenderList.begin(); it!=mSenderList.end(); it++)
00201                 it->processing->SetFrameAndHopSize( mExternBufferSize );
00202 }
00203 
00204 void NetworkLADSPAPlugin::FillPortInfo( LADSPA_PortDescriptor* descriptors, char** names, LADSPA_PortRangeHint* rangehints )
00205 {
00206         int currentport=0;
00207 
00208         //Manage InPorts (AudioSources)
00209         for (LADSPAInPortList::iterator it=mReceiverList.begin(); it!=mReceiverList.end(); it++)
00210         {
00211                 descriptors[currentport] = (LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO);
00212                 names[currentport] = LadspaLibrary::dupstr( it->name.c_str() );
00213                 rangehints[currentport].HintDescriptor = 0;
00214                 currentport++;
00215         }
00216 
00217         //Manage OutPorts (AudioSinks)
00218         for (LADSPAOutPortList::iterator it=mSenderList.begin(); it!=mSenderList.end(); it++)
00219         {
00220                 descriptors[currentport] = (LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO);
00221                 names[currentport] = LadspaLibrary::dupstr( it->name.c_str() );
00222                 rangehints[currentport].HintDescriptor = 0;
00223                 currentport++;
00224         }
00225 
00226         //Manage InControls (ExternInControls)
00227         for (LADSPAInControlList::iterator it=mInControlList.begin(); it!=mInControlList.end(); it++)
00228         {
00229                 descriptors[currentport] = (LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL);
00230                 names[currentport] = LadspaLibrary::dupstr( it->name.c_str() );
00231 
00232                 //Obté processingConfig, i defineix cada param
00233                 ControlSourceConfig conf = dynamic_cast<const ControlSourceConfig&>(it->processing->GetConfig() );
00234                 
00235                 rangehints[currentport].LowerBound=(LADSPA_Data)conf.GetMinValue();
00236                 rangehints[currentport].UpperBound=(LADSPA_Data)conf.GetMaxValue();
00237                 rangehints[currentport].HintDescriptor = (LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MIDDLE);
00238                 currentport++;
00239         }
00240         
00241         //Manage OutControls (ExternOutControls)
00242         // (Please note that not all the LADSPA hosts make use of these kind of ports)
00243         for (LADSPAOutControlList::iterator it=mOutControlList.begin(); it!=mOutControlList.end(); it++)
00244         {
00245                 descriptors[currentport] = (LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL);
00246                 names[currentport] = LadspaLibrary::dupstr( it->name.c_str() );
00247                 rangehints[currentport].LowerBound=(LADSPA_Data)0;
00248                 rangehints[currentport].UpperBound=(LADSPA_Data)1000;
00249                 rangehints[currentport].HintDescriptor = (LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE);
00250                 currentport++;
00251         }
00252 }
00253 
00254 void NetworkLADSPAPlugin::Run( unsigned long nsamples )
00255 {
00256         //Check current buffer size of ports, to make sure everything fits!
00257         // if it isn't so, upgrade Frame and Hop sizes (vital)
00258         if (nsamples!=mExternBufferSize)
00259         {
00260                 mExternBufferSize=nsamples;
00261                 UpdatePortFrameAndHopSize();
00262         }               
00263         
00264         ProcessInControlValues();
00265         
00266         CopyLadspaBuffersToGenerators(nsamples);
00267 
00268         //Do() as much as it is needed
00269         for (int stepcount=0; stepcount < (int(mExternBufferSize)/int(mClamBufferSize)); stepcount++)
00270                 _network.Do();
00271 
00272         CopySinksToLadspaBuffers(nsamples);
00273         ProcessOutControlValues();
00274 }
00275 
00276 void NetworkLADSPAPlugin::ProcessInControlValues()
00277 {
00278         for (LADSPAInControlList::iterator it=mInControlList.begin(); it!=mInControlList.end(); it++)
00279                 it->processing->Do( (float) *(it->dataBuffer) );
00280 }
00281 
00282 void NetworkLADSPAPlugin::ProcessOutControlValues()
00283 {
00284         for (LADSPAOutControlList::iterator it=mOutControlList.begin(); it!=mOutControlList.end(); it++)
00285                 *(it->dataBuffer)=it->processing->GetControlValue();
00286 }
00287 
00288 void NetworkLADSPAPlugin::CopyLadspaBuffersToGenerators(const unsigned long nframes)
00289 {
00290         for (LADSPAInPortList::iterator it=mReceiverList.begin(); it!=mReceiverList.end(); it++)
00291                 it->processing->SetExternalBuffer(it->dataBuffer, nframes );
00292 }
00293 
00294 void NetworkLADSPAPlugin::CopySinksToLadspaBuffers(const unsigned long nframes)
00295 {
00296         for (LADSPAOutPortList::iterator it=mSenderList.begin(); it!=mSenderList.end(); it++)
00297                 it->processing->SetExternalBuffer(it->dataBuffer, nframes );
00298 }
00299 
00300 void NetworkLADSPAPlugin::ConnectTo(unsigned long port, LADSPA_Data * data)
00301 {
00302         if ( port <= mReceiverList.size()-1 ) //Input port
00303                 mReceiverList.at( port ).dataBuffer=data;
00304         else if ( port <= mReceiverList.size() + mSenderList.size() -1) //Output port
00305                 mSenderList.at( port-mReceiverList.size() ).dataBuffer=data;
00306         else if ( port <= mReceiverList.size() + mSenderList.size() + mInControlList.size() -1) //Input control
00307                 mInControlList.at( port-mReceiverList.size()-mSenderList.size() ).dataBuffer=data;
00308         else //Output control
00309                 mOutControlList.at( port-mReceiverList.size()-mSenderList.size()-mInControlList.size() ).dataBuffer=data;
00310 }
00311 
00312 
00313 
00314 LADSPA_Descriptor * NetworkLADSPAPlugin::CreateLADSPADescriptor(
00315         const std::string & networkXmlContent,
00316         unsigned id,
00317         const std::string & label,
00318         const std::string & name,
00319         const std::string & maker,
00320         const std::string & copyright
00321         )
00322 {
00323         CLAM::NetworkLADSPAPlugin plugin(networkXmlContent);
00324 
00325         unsigned numports =
00326                 plugin.mReceiverList.size() + plugin.mSenderList.size() +
00327                 plugin.mInControlList.size() + plugin.mOutControlList.size();
00328 
00329         if (numports == 0) return 0;
00330 
00331         LADSPA_Descriptor * descriptor = new LADSPA_Descriptor;
00332 
00333         descriptor->UniqueID = id;
00334         descriptor->Label = LadspaLibrary::dupstr(label.c_str());
00335         descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE; // LADSPA_PROPERTY_REALTIME;
00336         descriptor->Name = LadspaLibrary::dupstr(name.c_str());
00337         descriptor->Maker = LadspaLibrary::dupstr(maker.c_str());
00338         descriptor->Copyright = LadspaLibrary::dupstr(copyright.c_str());
00339         descriptor->ImplementationData = LadspaLibrary::dupstr(networkXmlContent.c_str());
00340         descriptor->PortCount = numports;
00341 
00342         LADSPA_PortDescriptor * piPortDescriptors = new LADSPA_PortDescriptor[ numports ];
00343         descriptor->PortDescriptors = (const LADSPA_PortDescriptor *)piPortDescriptors;
00344         
00345         char ** pcPortNames = new char*[ numports ];
00346         
00347         descriptor->PortNames = (const char **)pcPortNames;
00348 
00349         LADSPA_PortRangeHint * psPortRangeHints = new LADSPA_PortRangeHint[ numports ];
00350         descriptor->PortRangeHints = (const LADSPA_PortRangeHint *)psPortRangeHints;
00351 
00352         plugin.FillPortInfo( piPortDescriptors, pcPortNames, psPortRangeHints);
00353         
00354         descriptor->instantiate = ::Instantiate;
00355         descriptor->connect_port = ::ConnectTo;
00356         descriptor->activate = ::Activate;
00357         descriptor->run = ::Run;
00358         descriptor->deactivate = ::Deactivate;
00359         descriptor->cleanup = ::CleanUp;
00360 
00361         return descriptor;
00362 }
00363 
00364 LadspaNetworkExporter::LadspaNetworkExporter(
00365         LadspaLibrary & library, const std::string & networkXmlContent,
00366         unsigned id,
00367         const std::string & label,
00368         const std::string & name,
00369         const std::string & maker,
00370         const std::string & copyright
00371         )
00372 {
00373         LADSPA_Descriptor * descriptor = NetworkLADSPAPlugin::CreateLADSPADescriptor(
00374                 networkXmlContent, id, label, name,
00375                 maker, copyright);
00376         if (not descriptor) return;
00377         library.AddPluginType(descriptor);
00378 }
00379 
00380 } //end namespace CLAM
00381 

Generated on Tue Aug 12 22:33:43 2008 for CLAM by  doxygen 1.5.5