|
CLAM-Development
1.3
|
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 // virtual void Pause() {} 00043 virtual bool IsRealTime() const { return true; } 00044 // virtual unsigned BackendBufferSize(); 00045 // virtual unsigned BackendSampleRate(); 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 // Ladspa Callbacks 00076 extern "C" 00077 { 00078 // Construct a new plugin instance. 00079 static LADSPA_Handle Instantiate(const LADSPA_Descriptor * descriptor, unsigned long sampleRate) 00080 { 00081 // std::cerr << "Network2Ladspa: instantiate" << std::endl; 00082 return new CLAM::LadspaNetworkPlayer(descriptor->Label, (const char*)descriptor->ImplementationData); 00083 } 00084 // Destruct plugin instance 00085 static void CleanUp(LADSPA_Handle handle) 00086 { 00087 // std::cerr << "Network2Ladspa: cleanup " << handle << std::endl; 00088 delete (CLAM::LadspaNetworkPlayer*) handle; 00089 } 00090 00091 // Run the plugin 00092 static void Run(LADSPA_Handle handle, unsigned long sampleCount) 00093 { 00094 CLAM::LadspaNetworkPlayer *p = (CLAM::LadspaNetworkPlayer*) handle; 00095 p->Run( sampleCount ); 00096 } 00097 // Activate Plugin 00098 static void Activate(LADSPA_Handle handle) 00099 { 00100 // std::cerr << "Network2Ladspa: activate " << handle << std::endl; 00101 CLAM::LadspaNetworkPlayer *p = (CLAM::LadspaNetworkPlayer*) handle; 00102 p->Activate(); 00103 } 00104 00105 static void Deactivate(LADSPA_Handle handle) 00106 { 00107 // std::cerr << "Network2Ladspa: deactivate " << handle << std::endl; 00108 CLAM::LadspaNetworkPlayer *p = (CLAM::LadspaNetworkPlayer*) handle; 00109 p->Deactivate(); 00110 } 00111 00112 // Connect a port to a data location. 00113 static void ConnectTo(LADSPA_Handle handle, unsigned long port, LADSPA_Data * dataLocation) 00114 { 00115 // std::cerr << "Network2Ladspa: connect " << port << std::endl; 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 // TOFIX: Should be a full link for the network to obtain parameters 00158 // but the network adquires the ownership of the player and, in this case, 00159 // the player owns the network. 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 //AudioSources and AudioBufferSource 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 //Manage InPorts (AudioSource and AudioBufferSources) 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 //Manage OutPorts (AudioSink and AudioSinksBuffer) 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 //Manage InControls (ExternInControls) 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 //Obté processingConfig, i defineix cada param 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 // specific cases when the default value is equal to some of defined LADSPA hints (ugly!): 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 //Manage OutControls (ExternOutControls) 00275 // (Please note that not all the LADSPA hosts make use of these kind of ports) 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 //Check current buffer size of ports, to make sure everything fits! 00290 // if it isn't so, upgrade Frame and Hop sizes (vital) 00291 if (nsamples!=mExternBufferSize) 00292 { 00293 mExternBufferSize=nsamples; 00294 if (nsamples==0) 00295 return; // Seems that in Ardour2.8 it does never runs plugins with 0 samples 00296 UpdatePortFrameAndHopSize(); 00297 } 00298 00299 ProcessInControlValues(); 00300 00301 EstablishLadspaBuffersToAudioSources(nsamples); 00302 EstablishLadspaBuffersToAudioSinks(nsamples); 00303 //Do() as much as it is needed 00304 // for (int stepcount=0; stepcount < (int(mExternBufferSize)/int(mClamBufferSize)); stepcount++) 00305 { 00306 _network.Do(); 00307 // if (stepcount>0) std::cout << "ieeps!" << std::flush; 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 ) //Input port 00346 { 00347 _sourceBuffers[port]=data; 00348 return; 00349 } 00350 port-=nSources; 00351 if (port < nSinks) //Output port 00352 { 00353 _sinkBuffers[port]=data; 00354 return; 00355 } 00356 port-=nSinks; 00357 if ( port < nInControls) //Input control 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; // LADSPA_PROPERTY_REALTIME; 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 } //end namespace CLAM 00438
1.7.6.1