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
00062 extern "C"
00063 {
00064
00065 static LADSPA_Handle Instantiate(const LADSPA_Descriptor * descriptor, unsigned long sampleRate)
00066 {
00067
00068 return new CLAM::NetworkLADSPAPlugin((const char*)descriptor->ImplementationData);
00069 }
00070
00071 static void CleanUp(LADSPA_Handle handle)
00072 {
00073
00074 delete (CLAM::NetworkLADSPAPlugin*) handle;
00075 }
00076
00077
00078 static void Run(LADSPA_Handle handle, unsigned long sampleCount)
00079 {
00080 CLAM::NetworkLADSPAPlugin *p = (CLAM::NetworkLADSPAPlugin*) handle;
00081 p->Run( sampleCount );
00082 }
00083
00084 static void Activate(LADSPA_Handle handle)
00085 {
00086
00087 CLAM::NetworkLADSPAPlugin *p = (CLAM::NetworkLADSPAPlugin*) handle;
00088 p->Activate();
00089 }
00090
00091 static void Deactivate(LADSPA_Handle handle)
00092 {
00093
00094 CLAM::NetworkLADSPAPlugin *p = (CLAM::NetworkLADSPAPlugin*) handle;
00095 p->Deactivate();
00096 }
00097
00098
00099 static void ConnectTo(LADSPA_Handle handle, unsigned long port, LADSPA_Data * dataLocation)
00100 {
00101
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
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
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
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
00196 for (LADSPAInPortList::iterator it=mReceiverList.begin(); it!=mReceiverList.end(); it++)
00197 it->processing->SetFrameAndHopSize( mExternBufferSize );
00198
00199
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
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
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
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
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
00242
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
00257
00258 if (nsamples!=mExternBufferSize)
00259 {
00260 mExternBufferSize=nsamples;
00261 UpdatePortFrameAndHopSize();
00262 }
00263
00264 ProcessInControlValues();
00265
00266 CopyLadspaBuffersToGenerators(nsamples);
00267
00268
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 )
00303 mReceiverList.at( port ).dataBuffer=data;
00304 else if ( port <= mReceiverList.size() + mSenderList.size() -1)
00305 mSenderList.at( port-mReceiverList.size() ).dataBuffer=data;
00306 else if ( port <= mReceiverList.size() + mSenderList.size() + mInControlList.size() -1)
00307 mInControlList.at( port-mReceiverList.size()-mSenderList.size() ).dataBuffer=data;
00308 else
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;
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 }
00381