LadspaNetworkExporter.cxx

Go to the documentation of this file.
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 
Generated by  doxygen 1.6.3