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