00001 #include "LadspaNetworkExporter.hxx"
00002 #include "ControlSource.hxx"
00003 #include "ControlSink.hxx"
00004 #include "AudioBufferSource.hxx"
00005 #include "AudioBufferSink.hxx"
00006 #include "NetworkPlayer.hxx"
00007
00008 namespace CLAM
00009 {
00010
00011 class LadspaNetworkPlayer : public NetworkPlayer
00012 {
00013 template<class T>
00014 class LADSPAInfo
00015 {
00016 public:
00017 std::string name;
00018 T* processing;
00019 LADSPA_Data *dataBuffer;
00020 unsigned port;
00021 };
00022
00023 private:
00024 typedef std::vector< LADSPAInfo<ControlSource> > LADSPAInControlList;
00025 typedef std::vector< LADSPAInfo<ControlSink> > LADSPAOutControlList;
00026 typedef std::vector<LADSPA_Data * > Buffers;
00027
00028 Network _network;
00029 Buffers _sourceBuffers;
00030 Buffers _sinkBuffers;
00031 Buffers _inControlBuffers;
00032 Buffers _outControlBuffers;
00033 LADSPAInControlList mInControlList;
00034 LADSPAOutControlList mOutControlList;
00035 unsigned long mClamBufferSize;
00036 unsigned long mExternBufferSize;
00037 public:
00038 virtual bool IsWorking() { return true; }
00039 virtual std::string NonWorkingReason() { return ""; }
00040 virtual void Start() {}
00041 virtual void Stop() {}
00042
00043 virtual bool IsRealTime() const { return true; }
00044
00045
00046 public:
00047 LadspaNetworkPlayer(const std::string & label, const std::string & networkXmlContent);
00048 ~LadspaNetworkPlayer();
00049
00050 void Activate();
00051 void Deactivate();
00052
00053 void LocateConnections();
00054 void UpdatePortFrameAndHopSize();
00055 void FillPortInfo( LADSPA_PortDescriptor* descriptors, char** names, LADSPA_PortRangeHint* rangehints );
00056 void ConnectTo(unsigned long port, LADSPA_Data * data);
00057
00058 void Run( unsigned long nsamples );
00059 void EstablishLadspaBuffersToAudioSources(const unsigned long nframes);
00060 void EstablishLadspaBuffersToAudioSinks(const unsigned long nframes);
00061 void ProcessInControlValues();
00062 void ProcessOutControlValues();
00063 static LADSPA_Descriptor * CreateLADSPADescriptor(
00064 const std::string & networkXmlContent,
00065 unsigned id,
00066 const std::string & label,
00067 const std::string & name,
00068 const std::string & maker,
00069 const std::string & copyright
00070 );
00071 };
00072
00073 }
00074
00075
00076 extern "C"
00077 {
00078
00079 static LADSPA_Handle Instantiate(const LADSPA_Descriptor * descriptor, unsigned long sampleRate)
00080 {
00081
00082 return new CLAM::LadspaNetworkPlayer(descriptor->Label, (const char*)descriptor->ImplementationData);
00083 }
00084
00085 static void CleanUp(LADSPA_Handle handle)
00086 {
00087
00088 delete (CLAM::LadspaNetworkPlayer*) handle;
00089 }
00090
00091
00092 static void Run(LADSPA_Handle handle, unsigned long sampleCount)
00093 {
00094 CLAM::LadspaNetworkPlayer *p = (CLAM::LadspaNetworkPlayer*) handle;
00095 p->Run( sampleCount );
00096 }
00097
00098 static void Activate(LADSPA_Handle handle)
00099 {
00100
00101 CLAM::LadspaNetworkPlayer *p = (CLAM::LadspaNetworkPlayer*) handle;
00102 p->Activate();
00103 }
00104
00105 static void Deactivate(LADSPA_Handle handle)
00106 {
00107
00108 CLAM::LadspaNetworkPlayer *p = (CLAM::LadspaNetworkPlayer*) handle;
00109 p->Deactivate();
00110 }
00111
00112
00113 static void ConnectTo(LADSPA_Handle handle, unsigned long port, LADSPA_Data * dataLocation)
00114 {
00115
00116 CLAM::LadspaNetworkPlayer *p = (CLAM::LadspaNetworkPlayer*) handle;
00117 p->ConnectTo( port, dataLocation );
00118 }
00119 }
00120
00121 namespace CLAM
00122 {
00123
00124
00125 LadspaNetworkPlayer::LadspaNetworkPlayer(const std::string & name, const std::string & networkXmlContent)
00126 {
00127 mClamBufferSize=512;
00128 mExternBufferSize=mClamBufferSize;
00129
00130 std::istringstream xmlfile(networkXmlContent);
00131 try
00132 {
00133 XmlStorage::Restore( _network, xmlfile );
00134 }
00135 catch ( XmlStorageErr err)
00136 {
00137 std::cerr << "CLAM LADSPA: Error while loading CLAM network based plugin '" << name << "'." <<std::endl;
00138 std::cerr << err.what() << std::endl;
00139 std::cerr << "Plugin not loaded." << std::endl;
00140 return;
00141 }
00142 if (_network.HasMisconfiguredProcessings())
00143 {
00144 std::cerr << "CLAM LADSPA: Error while configuring CLAM network based plugin '" << name << "'." <<std::endl;
00145 std::cerr << _network.GetConfigurationErrors() << std::endl;
00146 std::cerr << "Plugin not loaded." << std::endl;
00147 return;
00148 }
00149 if (_network.HasUnconnectedInPorts())
00150 {
00151 std::cerr << "CLAM LADSPA: Error loading CLAM network based plugin '" << name << "'." <<std::endl;
00152 std::cerr << "Plugin not loaded because internal network inports were unconnected." <<std::endl;
00153 std::cerr << _network.GetUnconnectedInPorts() << std::flush;
00154 return;
00155 }
00156
00157
00158
00159
00160 SetNetworkBackLink(_network);
00161 LocateConnections();
00162 }
00163
00164 LadspaNetworkPlayer::~LadspaNetworkPlayer()
00165 {
00166 }
00167
00168 void LadspaNetworkPlayer::Activate()
00169 {
00170
00171 CLAM_WARNING(_network.SupportsVariableAudioSize(), "Network don't support variable audio size");
00172 _network.Start();
00173 }
00174
00175 void LadspaNetworkPlayer::Deactivate()
00176 {
00177 _network.Stop();
00178 }
00179
00180 void LadspaNetworkPlayer::LocateConnections()
00181 {
00182 CacheSourcesAndSinks();
00183
00184 CLAM_ASSERT( mInControlList.empty(), "LadspaNetworkPlayer::LocateConnections() : there are already registered controls");
00185 CLAM_ASSERT( mOutControlList.empty(), "LadspaNetworkPlayer::LocateConnections() : there are already registered controls");
00186
00187 Network::ControlSources controlSources = _network.getOrderedControlSources();
00188 Network::ControlSinks controlSinks = _network.getOrderedControlSinks();
00189
00190 _sourceBuffers.resize(GetNSources());
00191 _sinkBuffers.resize(GetNSinks());
00192
00193 for (Network::ControlSources::const_iterator it=controlSources.begin(); it!=controlSources.end(); it++)
00194 {
00195 LADSPAInfo<ControlSource> info;
00196 info.name = _network.GetNetworkId(*it).c_str();
00197 info.processing=*it;
00198 mInControlList.push_back(info);
00199 }
00200 _inControlBuffers.resize(mInControlList.size());
00201
00202 for (Network::ControlSinks::const_iterator it=controlSinks.begin(); it!=controlSinks.end(); it++)
00203 {
00204 LADSPAInfo<ControlSink> info;
00205 info.name = _network.GetNetworkId( *it ).c_str();
00206 info.processing =*it;
00207 mOutControlList.push_back(info);
00208 }
00209 _outControlBuffers.resize(mOutControlList.size());
00210
00211 UpdatePortFrameAndHopSize();
00212 }
00213
00214 void LadspaNetworkPlayer::UpdatePortFrameAndHopSize()
00215 {
00216
00217 for (unsigned i=0; i<GetNSources(); i++)
00218 {
00219 SetSourceFrameSize(i, mExternBufferSize);
00220 }
00221 for (unsigned i=0; i<GetNSinks(); i++)
00222 {
00223 SetSinkFrameSize(i, mExternBufferSize);
00224 }
00225 }
00226
00227 void LadspaNetworkPlayer::FillPortInfo( LADSPA_PortDescriptor* descriptors, char** names, LADSPA_PortRangeHint* rangehints )
00228 {
00229 int currentport=0;
00230
00231
00232 for (unsigned i=0; i<GetNSources(); i++)
00233 {
00234 descriptors[currentport] = (LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO);
00235 names[currentport] = LadspaLibrary::dupstr( SourceName(i).c_str() );
00236 rangehints[currentport].HintDescriptor = 0;
00237 currentport++;
00238 }
00239
00240
00241 for (unsigned i=0; i<GetNSinks(); i++)
00242 {
00243 descriptors[currentport] = (LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO);
00244 names[currentport] = LadspaLibrary::dupstr( SinkName(i).c_str() );
00245 rangehints[currentport].HintDescriptor = 0;
00246 currentport++;
00247 }
00248
00249
00250 for (LADSPAInControlList::iterator it=mInControlList.begin(); it!=mInControlList.end(); it++)
00251 {
00252 descriptors[currentport] = (LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL);
00253 names[currentport] = LadspaLibrary::dupstr( it->name.c_str() );
00254
00255
00256 ControlSourceConfig conf = dynamic_cast<const ControlSourceConfig&>(it->processing->GetConfig() );
00257
00258 rangehints[currentport].LowerBound=(LADSPA_Data)conf.GetMinValue();
00259 rangehints[currentport].UpperBound=(LADSPA_Data)conf.GetMaxValue();
00260
00261 unsigned defaultHintValue=LADSPA_HINT_DEFAULT_MIDDLE;
00262
00263 if (conf.GetDefaultValue() == conf.GetMinValue() ) defaultHintValue=LADSPA_HINT_DEFAULT_MINIMUM;
00264 else if (conf.GetDefaultValue() == conf.GetMaxValue() ) defaultHintValue=LADSPA_HINT_DEFAULT_MAXIMUM;
00265 else if (conf.GetDefaultValue() == 0) defaultHintValue = LADSPA_HINT_DEFAULT_0;
00266 else if (conf.GetDefaultValue() == 1) defaultHintValue = LADSPA_HINT_DEFAULT_1;
00267 else if (conf.GetDefaultValue() == 100) defaultHintValue = LADSPA_HINT_DEFAULT_100;
00268 else if (conf.GetDefaultValue() == 440) defaultHintValue = LADSPA_HINT_DEFAULT_440;
00269
00270 rangehints[currentport].HintDescriptor = (LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | defaultHintValue);
00271 currentport++;
00272 }
00273
00274
00275
00276 for (LADSPAOutControlList::iterator it=mOutControlList.begin(); it!=mOutControlList.end(); it++)
00277 {
00278 descriptors[currentport] = (LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL);
00279 names[currentport] = LadspaLibrary::dupstr( it->name.c_str() );
00280 rangehints[currentport].LowerBound=(LADSPA_Data)0;
00281 rangehints[currentport].UpperBound=(LADSPA_Data)1000;
00282 rangehints[currentport].HintDescriptor = (LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE);
00283 currentport++;
00284 }
00285 }
00286
00287 void LadspaNetworkPlayer::Run( unsigned long nsamples )
00288 {
00289
00290
00291 if (nsamples!=mExternBufferSize)
00292 {
00293 mExternBufferSize=nsamples;
00294 if (nsamples==0)
00295 return;
00296 UpdatePortFrameAndHopSize();
00297 }
00298
00299 ProcessInControlValues();
00300
00301 EstablishLadspaBuffersToAudioSources(nsamples);
00302 EstablishLadspaBuffersToAudioSinks(nsamples);
00303
00304
00305 {
00306 _network.Do();
00307
00308 }
00309
00310 ProcessOutControlValues();
00311 }
00312
00313 void LadspaNetworkPlayer::ProcessInControlValues()
00314 {
00315 for (LADSPAInControlList::iterator it=mInControlList.begin(); it!=mInControlList.end(); it++)
00316 it->processing->Do( (float) *(it->dataBuffer) );
00317 }
00318
00319 void LadspaNetworkPlayer::ProcessOutControlValues()
00320 {
00321 for (LADSPAOutControlList::iterator it=mOutControlList.begin(); it!=mOutControlList.end(); it++)
00322 *(it->dataBuffer)=it->processing->GetControlValue();
00323 }
00324
00325 void LadspaNetworkPlayer::EstablishLadspaBuffersToAudioSources(const unsigned long nframes)
00326 {
00327 for (unsigned i=0; i<GetNSources(); i++)
00328 SetSourceBuffer(i, _sourceBuffers[i], nframes);
00329 }
00330
00331 void LadspaNetworkPlayer::EstablishLadspaBuffersToAudioSinks(const unsigned long nframes)
00332 {
00333 for (unsigned i=0; i<GetNSinks(); i++)
00334 SetSinkBuffer(i, _sinkBuffers[i], nframes);
00335 }
00336
00337 void LadspaNetworkPlayer::ConnectTo(unsigned long port, LADSPA_Data * data)
00338 {
00339
00340 unsigned nSources = GetNSources();
00341 unsigned nSinks = GetNSinks();
00342 unsigned nInControls = mInControlList.size();
00343 unsigned nOutControls = mInControlList.size();
00344
00345 if ( port < nSources )
00346 {
00347 _sourceBuffers[port]=data;
00348 return;
00349 }
00350 port-=nSources;
00351 if (port < nSinks)
00352 {
00353 _sinkBuffers[port]=data;
00354 return;
00355 }
00356 port-=nSinks;
00357 if ( port < nInControls)
00358 {
00359 mInControlList.at( port ).dataBuffer=data;
00360 return;
00361 }
00362 port-=nInControls;
00363 if (port < nOutControls)
00364 {
00365 mOutControlList.at( port ).dataBuffer=data;
00366 return;
00367 }
00368 }
00369
00370
00371
00372 LADSPA_Descriptor * LadspaNetworkPlayer::CreateLADSPADescriptor(
00373 const std::string & networkXmlContent,
00374 unsigned id,
00375 const std::string & label,
00376 const std::string & name,
00377 const std::string & maker,
00378 const std::string & copyright
00379 )
00380 {
00381 CLAM::LadspaNetworkPlayer plugin(label, networkXmlContent);
00382
00383 unsigned numports = plugin.GetNSources() + plugin.GetNSinks() +
00384 plugin.mInControlList.size() + plugin.mOutControlList.size();
00385
00386 if (numports == 0) return 0;
00387
00388 LADSPA_Descriptor * descriptor = new LADSPA_Descriptor;
00389
00390 descriptor->UniqueID = id;
00391 descriptor->Label = LadspaLibrary::dupstr(label.c_str());
00392 descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
00393 descriptor->Name = LadspaLibrary::dupstr(name.c_str());
00394 descriptor->Maker = LadspaLibrary::dupstr(maker.c_str());
00395 descriptor->Copyright = LadspaLibrary::dupstr(copyright.c_str());
00396 descriptor->ImplementationData = LadspaLibrary::dupstr(networkXmlContent.c_str());
00397 descriptor->PortCount = numports;
00398
00399 LADSPA_PortDescriptor * piPortDescriptors = new LADSPA_PortDescriptor[ numports ];
00400 descriptor->PortDescriptors = (const LADSPA_PortDescriptor *)piPortDescriptors;
00401
00402 char ** pcPortNames = new char*[ numports ];
00403
00404 descriptor->PortNames = (const char **)pcPortNames;
00405
00406 LADSPA_PortRangeHint * psPortRangeHints = new LADSPA_PortRangeHint[ numports ];
00407 descriptor->PortRangeHints = (const LADSPA_PortRangeHint *)psPortRangeHints;
00408
00409 plugin.FillPortInfo( piPortDescriptors, pcPortNames, psPortRangeHints);
00410
00411 descriptor->instantiate = ::Instantiate;
00412 descriptor->connect_port = ::ConnectTo;
00413 descriptor->activate = ::Activate;
00414 descriptor->run = ::Run;
00415 descriptor->deactivate = ::Deactivate;
00416 descriptor->cleanup = ::CleanUp;
00417
00418 return descriptor;
00419 }
00420
00421 LadspaNetworkExporter::LadspaNetworkExporter(
00422 LadspaLibrary & library, const std::string & networkXmlContent,
00423 unsigned id,
00424 const std::string & label,
00425 const std::string & name,
00426 const std::string & maker,
00427 const std::string & copyright
00428 )
00429 {
00430 LADSPA_Descriptor * descriptor = LadspaNetworkPlayer::CreateLADSPADescriptor(
00431 networkXmlContent, id, label, name,
00432 maker, copyright);
00433 if (not descriptor) return;
00434 library.AddPluginType(descriptor);
00435 }
00436
00437 }
00438