From 126152a7562980fc3dbdc24dab8fbc5b6a95778e Mon Sep 17 00:00:00 2001 From: "lllucius@gmail.com" Date: Wed, 5 Nov 2014 07:06:38 +0000 Subject: [PATCH] Converts the ladspa effects to the new format and adds realtime support This also (hopefully) corrects some additional problems in general realtime support. Particular focus should be given to the handling of various combinations of stereo, left channel mono, right channel mono, and true mono as this has been a particularly troublesome area. --- mac/Audacity.xcodeproj/project.pbxproj | 10 - src/Makefile.am | 2 - src/Makefile.in | 24 +- src/effects/Effect.cpp | 8 +- src/effects/EffectManager.cpp | 11 +- src/effects/EffectManager.h | 1 + src/effects/LoadEffects.cpp | 14 - src/effects/VST/VSTEffect.cpp | 78 +- src/effects/ladspa/LadspaEffect.cpp | 1144 +++++++++++++---- src/effects/ladspa/LadspaEffect.h | 185 ++- src/effects/ladspa/LoadLadspa.cpp | 327 ----- src/effects/ladspa/LoadLadspa.h | 13 - src/widgets/AButton.cpp | 2 +- win/Projects/Audacity/Audacity.vcxproj | 2 - .../Audacity/Audacity.vcxproj.filters | 6 - 15 files changed, 1066 insertions(+), 761 deletions(-) delete mode 100644 src/effects/ladspa/LoadLadspa.cpp delete mode 100644 src/effects/ladspa/LoadLadspa.h diff --git a/mac/Audacity.xcodeproj/project.pbxproj b/mac/Audacity.xcodeproj/project.pbxproj index d0a6957d7..e99b52533 100644 --- a/mac/Audacity.xcodeproj/project.pbxproj +++ b/mac/Audacity.xcodeproj/project.pbxproj @@ -336,7 +336,6 @@ 1790B13C09883BFD008A330A /* Fade.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1790B01D09883BFD008A330A /* Fade.cpp */; }; 1790B13E09883BFD008A330A /* Invert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1790B02109883BFD008A330A /* Invert.cpp */; }; 1790B13F09883BFD008A330A /* LadspaEffect.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1790B02609883BFD008A330A /* LadspaEffect.cpp */; }; - 1790B14009883BFD008A330A /* LoadLadspa.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1790B02809883BFD008A330A /* LoadLadspa.cpp */; }; 1790B14109883BFD008A330A /* Leveller.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1790B02A09883BFD008A330A /* Leveller.cpp */; }; 1790B14209883BFD008A330A /* LoadEffects.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1790B02C09883BFD008A330A /* LoadEffects.cpp */; }; 1790B14309883BFD008A330A /* Noise.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1790B02E09883BFD008A330A /* Noise.cpp */; }; @@ -1314,7 +1313,6 @@ ED663BA816543647007F53A5 /* Fade.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1790B01D09883BFD008A330A /* Fade.cpp */; }; ED663BA916543647007F53A5 /* Invert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1790B02109883BFD008A330A /* Invert.cpp */; }; ED663BAA16543647007F53A5 /* LadspaEffect.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1790B02609883BFD008A330A /* LadspaEffect.cpp */; }; - ED663BAB16543647007F53A5 /* LoadLadspa.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1790B02809883BFD008A330A /* LoadLadspa.cpp */; }; ED663BAC16543647007F53A5 /* Leveller.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1790B02A09883BFD008A330A /* Leveller.cpp */; }; ED663BAD16543647007F53A5 /* LoadEffects.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1790B02C09883BFD008A330A /* LoadEffects.cpp */; }; ED663BAE16543647007F53A5 /* Noise.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1790B02E09883BFD008A330A /* Noise.cpp */; }; @@ -1641,7 +1639,6 @@ ED85B48016A47353006DA21D /* Fade.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1790B01D09883BFD008A330A /* Fade.cpp */; }; ED85B48116A47353006DA21D /* Invert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1790B02109883BFD008A330A /* Invert.cpp */; }; ED85B48216A47353006DA21D /* LadspaEffect.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1790B02609883BFD008A330A /* LadspaEffect.cpp */; }; - ED85B48316A47353006DA21D /* LoadLadspa.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1790B02809883BFD008A330A /* LoadLadspa.cpp */; }; ED85B48416A47353006DA21D /* Leveller.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1790B02A09883BFD008A330A /* Leveller.cpp */; }; ED85B48516A47353006DA21D /* LoadEffects.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1790B02C09883BFD008A330A /* LoadEffects.cpp */; }; ED85B48616A47353006DA21D /* Noise.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1790B02E09883BFD008A330A /* Noise.cpp */; }; @@ -2865,8 +2862,6 @@ 1790B02509883BFD008A330A /* ladspa.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 3; lastKnownFileType = sourcecode.c.h; path = ladspa.h; sourceTree = ""; tabWidth = 3; }; 1790B02609883BFD008A330A /* LadspaEffect.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 3; lastKnownFileType = sourcecode.cpp.cpp; path = LadspaEffect.cpp; sourceTree = ""; tabWidth = 3; }; 1790B02709883BFD008A330A /* LadspaEffect.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 3; lastKnownFileType = sourcecode.c.h; path = LadspaEffect.h; sourceTree = ""; tabWidth = 3; }; - 1790B02809883BFD008A330A /* LoadLadspa.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 3; lastKnownFileType = sourcecode.cpp.cpp; path = LoadLadspa.cpp; sourceTree = ""; tabWidth = 3; }; - 1790B02909883BFD008A330A /* LoadLadspa.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 3; lastKnownFileType = sourcecode.c.h; path = LoadLadspa.h; sourceTree = ""; tabWidth = 3; }; 1790B02A09883BFD008A330A /* Leveller.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 3; lastKnownFileType = sourcecode.cpp.cpp; path = Leveller.cpp; sourceTree = ""; tabWidth = 3; }; 1790B02B09883BFD008A330A /* Leveller.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 3; lastKnownFileType = sourcecode.c.h; path = Leveller.h; sourceTree = ""; tabWidth = 3; }; 1790B02C09883BFD008A330A /* LoadEffects.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 3; lastKnownFileType = sourcecode.cpp.cpp; path = LoadEffects.cpp; sourceTree = ""; tabWidth = 3; }; @@ -5270,8 +5265,6 @@ 1790B02509883BFD008A330A /* ladspa.h */, 1790B02609883BFD008A330A /* LadspaEffect.cpp */, 1790B02709883BFD008A330A /* LadspaEffect.h */, - 1790B02809883BFD008A330A /* LoadLadspa.cpp */, - 1790B02909883BFD008A330A /* LoadLadspa.h */, ); path = ladspa; sourceTree = ""; @@ -8833,7 +8826,6 @@ 1790B13C09883BFD008A330A /* Fade.cpp in Sources */, 1790B13E09883BFD008A330A /* Invert.cpp in Sources */, 1790B13F09883BFD008A330A /* LadspaEffect.cpp in Sources */, - 1790B14009883BFD008A330A /* LoadLadspa.cpp in Sources */, 1790B14109883BFD008A330A /* Leveller.cpp in Sources */, 1790B14209883BFD008A330A /* LoadEffects.cpp in Sources */, 1790B14309883BFD008A330A /* Noise.cpp in Sources */, @@ -9345,7 +9337,6 @@ ED663BA816543647007F53A5 /* Fade.cpp in Sources */, ED663BA916543647007F53A5 /* Invert.cpp in Sources */, ED663BAA16543647007F53A5 /* LadspaEffect.cpp in Sources */, - ED663BAB16543647007F53A5 /* LoadLadspa.cpp in Sources */, ED663BAC16543647007F53A5 /* Leveller.cpp in Sources */, ED663BAD16543647007F53A5 /* LoadEffects.cpp in Sources */, ED663BAE16543647007F53A5 /* Noise.cpp in Sources */, @@ -9655,7 +9646,6 @@ ED85B48016A47353006DA21D /* Fade.cpp in Sources */, ED85B48116A47353006DA21D /* Invert.cpp in Sources */, ED85B48216A47353006DA21D /* LadspaEffect.cpp in Sources */, - ED85B48316A47353006DA21D /* LoadLadspa.cpp in Sources */, ED85B48416A47353006DA21D /* Leveller.cpp in Sources */, ED85B48516A47353006DA21D /* LoadEffects.cpp in Sources */, ED85B48616A47353006DA21D /* Noise.cpp in Sources */, diff --git a/src/Makefile.am b/src/Makefile.am index bc28b6e39..e611ce19e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -585,8 +585,6 @@ audacity_SOURCES += \ effects/ladspa/ladspa.h \ effects/ladspa/LadspaEffect.cpp \ effects/ladspa/LadspaEffect.h \ - effects/ladspa/LoadLadspa.cpp \ - effects/ladspa/LoadLadspa.h \ $(NULL) endif diff --git a/src/Makefile.in b/src/Makefile.in index ad29a9078..d334b0e9f 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -113,8 +113,6 @@ bin_PROGRAMS = audacity$(EXEEXT) @USE_LADSPA_TRUE@ effects/ladspa/ladspa.h \ @USE_LADSPA_TRUE@ effects/ladspa/LadspaEffect.cpp \ @USE_LADSPA_TRUE@ effects/ladspa/LadspaEffect.h \ -@USE_LADSPA_TRUE@ effects/ladspa/LoadLadspa.cpp \ -@USE_LADSPA_TRUE@ effects/ladspa/LoadLadspa.h \ @USE_LADSPA_TRUE@ $(NULL) @USE_LAME_TRUE@am__append_13 = $(LAME_CFLAGS) @@ -469,7 +467,6 @@ am__audacity_SOURCES_DIST = BlockFile.cpp BlockFile.h DirManager.cpp \ import/ImportFFmpeg.h import/ImportGStreamer.cpp \ import/ImportGStreamer.h effects/ladspa/ladspa.h \ effects/ladspa/LadspaEffect.cpp effects/ladspa/LadspaEffect.h \ - effects/ladspa/LoadLadspa.cpp effects/ladspa/LoadLadspa.h \ ondemand/ODDecodeFlacTask.cpp ondemand/ODDecodeFlacTask.h \ effects/nyquist/LoadNyquist.cpp effects/nyquist/LoadNyquist.h \ effects/nyquist/Nyquist.cpp effects/nyquist/Nyquist.h \ @@ -504,8 +501,7 @@ am__objects_1 = audacity-BlockFile.$(OBJEXT) \ @USE_FFMPEG_TRUE@ import/audacity-ImportFFmpeg.$(OBJEXT) @USE_GSTREAMER_TRUE@am__objects_4 = \ @USE_GSTREAMER_TRUE@ import/audacity-ImportGStreamer.$(OBJEXT) -@USE_LADSPA_TRUE@am__objects_5 = effects/ladspa/audacity-LadspaEffect.$(OBJEXT) \ -@USE_LADSPA_TRUE@ effects/ladspa/audacity-LoadLadspa.$(OBJEXT) +@USE_LADSPA_TRUE@am__objects_5 = effects/ladspa/audacity-LadspaEffect.$(OBJEXT) @USE_LIBFLAC_TRUE@am__objects_6 = ondemand/audacity-ODDecodeFlacTask.$(OBJEXT) @USE_LIBNYQUIST_TRUE@am__objects_7 = effects/nyquist/audacity-LoadNyquist.$(OBJEXT) \ @USE_LIBNYQUIST_TRUE@ effects/nyquist/audacity-Nyquist.$(OBJEXT) @@ -1889,9 +1885,6 @@ effects/ladspa/$(DEPDIR)/$(am__dirstamp): effects/ladspa/audacity-LadspaEffect.$(OBJEXT): \ effects/ladspa/$(am__dirstamp) \ effects/ladspa/$(DEPDIR)/$(am__dirstamp) -effects/ladspa/audacity-LoadLadspa.$(OBJEXT): \ - effects/ladspa/$(am__dirstamp) \ - effects/ladspa/$(DEPDIR)/$(am__dirstamp) ondemand/audacity-ODDecodeFlacTask.$(OBJEXT): \ ondemand/$(am__dirstamp) ondemand/$(DEPDIR)/$(am__dirstamp) effects/nyquist/$(am__dirstamp): @@ -2146,7 +2139,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@effects/audiounits/$(DEPDIR)/audacity-AudioUnitEffect.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@effects/audiounits/$(DEPDIR)/audacity-LoadAudioUnits.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@effects/ladspa/$(DEPDIR)/audacity-LadspaEffect.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@effects/ladspa/$(DEPDIR)/audacity-LoadLadspa.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@effects/lv2/$(DEPDIR)/audacity-LV2Effect.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@effects/lv2/$(DEPDIR)/audacity-LV2PortGroup.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@effects/lv2/$(DEPDIR)/audacity-LoadLV2.Po@am__quote@ @@ -5783,20 +5775,6 @@ effects/ladspa/audacity-LadspaEffect.obj: effects/ladspa/LadspaEffect.cpp @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -c -o effects/ladspa/audacity-LadspaEffect.obj `if test -f 'effects/ladspa/LadspaEffect.cpp'; then $(CYGPATH_W) 'effects/ladspa/LadspaEffect.cpp'; else $(CYGPATH_W) '$(srcdir)/effects/ladspa/LadspaEffect.cpp'; fi` -effects/ladspa/audacity-LoadLadspa.o: effects/ladspa/LoadLadspa.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -MT effects/ladspa/audacity-LoadLadspa.o -MD -MP -MF effects/ladspa/$(DEPDIR)/audacity-LoadLadspa.Tpo -c -o effects/ladspa/audacity-LoadLadspa.o `test -f 'effects/ladspa/LoadLadspa.cpp' || echo '$(srcdir)/'`effects/ladspa/LoadLadspa.cpp -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) effects/ladspa/$(DEPDIR)/audacity-LoadLadspa.Tpo effects/ladspa/$(DEPDIR)/audacity-LoadLadspa.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='effects/ladspa/LoadLadspa.cpp' object='effects/ladspa/audacity-LoadLadspa.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -c -o effects/ladspa/audacity-LoadLadspa.o `test -f 'effects/ladspa/LoadLadspa.cpp' || echo '$(srcdir)/'`effects/ladspa/LoadLadspa.cpp - -effects/ladspa/audacity-LoadLadspa.obj: effects/ladspa/LoadLadspa.cpp -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -MT effects/ladspa/audacity-LoadLadspa.obj -MD -MP -MF effects/ladspa/$(DEPDIR)/audacity-LoadLadspa.Tpo -c -o effects/ladspa/audacity-LoadLadspa.obj `if test -f 'effects/ladspa/LoadLadspa.cpp'; then $(CYGPATH_W) 'effects/ladspa/LoadLadspa.cpp'; else $(CYGPATH_W) '$(srcdir)/effects/ladspa/LoadLadspa.cpp'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) effects/ladspa/$(DEPDIR)/audacity-LoadLadspa.Tpo effects/ladspa/$(DEPDIR)/audacity-LoadLadspa.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='effects/ladspa/LoadLadspa.cpp' object='effects/ladspa/audacity-LoadLadspa.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -c -o effects/ladspa/audacity-LoadLadspa.obj `if test -f 'effects/ladspa/LoadLadspa.cpp'; then $(CYGPATH_W) 'effects/ladspa/LoadLadspa.cpp'; else $(CYGPATH_W) '$(srcdir)/effects/ladspa/LoadLadspa.cpp'; fi` - ondemand/audacity-ODDecodeFlacTask.o: ondemand/ODDecodeFlacTask.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -MT ondemand/audacity-ODDecodeFlacTask.o -MD -MP -MF ondemand/$(DEPDIR)/audacity-ODDecodeFlacTask.Tpo -c -o ondemand/audacity-ODDecodeFlacTask.o `test -f 'ondemand/ODDecodeFlacTask.cpp' || echo '$(srcdir)/'`ondemand/ODDecodeFlacTask.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ondemand/$(DEPDIR)/audacity-ODDecodeFlacTask.Tpo ondemand/$(DEPDIR)/audacity-ODDecodeFlacTask.Po diff --git a/src/effects/Effect.cpp b/src/effects/Effect.cpp index 4c206b641..3ae2ac471 100644 --- a/src/effects/Effect.cpp +++ b/src/effects/Effect.cpp @@ -1009,10 +1009,6 @@ bool Effect::ProcessTrack(int count, void Effect::End() { - if (mClient) - { - mClient->Shutdown(); - } } bool Effect::TotalProgress(double frac) @@ -1432,10 +1428,10 @@ sampleCount Effect::RealtimeProcess(int group, // If the current group hasn't yet been seen, then we must // add a new processor to handle this channel (sub)group - if (group > mHighGroup) + if (mCurrentGroup > mHighGroup) { mClient->RealtimeAddProcessor(gchans, rate); - mHighGroup = group; + mHighGroup = mCurrentGroup; } // Finally call the plugin to process the block diff --git a/src/effects/EffectManager.cpp b/src/effects/EffectManager.cpp index a44052308..8027efccf 100644 --- a/src/effects/EffectManager.cpp +++ b/src/effects/EffectManager.cpp @@ -178,6 +178,7 @@ EffectManager::EffectManager() mRealtimeLock.Enter(); mRealtimeEffects = NULL; mRealtimeCount = 0; + mRealtimeActive = false; mRealtimeSuspended = true; mRealtimeLatency = 0; mRealtimeLock.Leave(); @@ -420,7 +421,7 @@ void EffectManager::RealtimeSetEffects(const EffectArray & effects) } // Must not have been in the new chain, so tell it to cleanup - if (e) + if (e && mRealtimeActive) { e->RealtimeFinalize(); } @@ -442,7 +443,7 @@ void EffectManager::RealtimeSetEffects(const EffectArray & effects) } // Must not have been in the old chain, so tell it to initialize - if (e) + if (e && mRealtimeActive) { e->RealtimeInitialize(); } @@ -474,6 +475,10 @@ void EffectManager::RealtimeInitialize() // The audio thread should not be running yet, but protect anyway RealtimeSuspend(); + // RealtimeSetEffects() needs to know when we're active so it can + // initialize newly added effects + mRealtimeActive = true; + // Tell each effect to get ready for action for (int i = 0; i < mRealtimeCount; i++) { @@ -497,6 +502,8 @@ void EffectManager::RealtimeFinalize() { mRealtimeEffects[i]->RealtimeFinalize(); } + + mRealtimeActive = false; } void EffectManager::RealtimeSuspend() diff --git a/src/effects/EffectManager.h b/src/effects/EffectManager.h index 00c700bb0..d5b407e43 100644 --- a/src/effects/EffectManager.h +++ b/src/effects/EffectManager.h @@ -162,6 +162,7 @@ private: int mRealtimeCount; int mRealtimeLatency; bool mRealtimeSuspended; + bool mRealtimeActive; #endif #ifdef EFFECT_CATEGORIES diff --git a/src/effects/LoadEffects.cpp b/src/effects/LoadEffects.cpp index db5d4ac64..418c1c969 100644 --- a/src/effects/LoadEffects.cpp +++ b/src/effects/LoadEffects.cpp @@ -62,10 +62,6 @@ #include "audiounits/LoadAudioUnits.h" #endif -#ifdef USE_LADSPA -#include "ladspa/LoadLadspa.h" -#endif - #ifdef USE_LV2 #include "lv2/LoadLV2.h" #endif @@ -279,12 +275,6 @@ void LoadEffects() } #endif -#ifdef USE_LADSPA - if (gPrefs->Read(wxT("/Ladspa/Enable"), true)) { - LoadLadspaPlugins(); - } -#endif - #ifdef USE_LV2 if (gPrefs->Read(wxT("/LV2/Enable"), true)) { LoadLV2Plugins(); @@ -309,10 +299,6 @@ void UnloadEffects() { EffectManager::Get().UnregisterEffects(); -#ifdef USE_LADSPA - UnloadLadspaPlugins(); -#endif - #ifdef USE_LV2 UnloadLV2Plugins(); #endif diff --git a/src/effects/VST/VSTEffect.cpp b/src/effects/VST/VSTEffect.cpp index 691ed1819..a1d86a668 100644 --- a/src/effects/VST/VSTEffect.cpp +++ b/src/effects/VST/VSTEffect.cpp @@ -3216,7 +3216,7 @@ wxString VSTEffect::GetDescription() // description, but most do not or they just return the name again. So, // try to provide some sort of useful information. mDescription = _("Audio In: ") + - wxString::Format(wxT("%d"), mAudioIns), + wxString::Format(wxT("%d"), mAudioIns) + _(", Audio Out: ") + wxString::Format(wxT("%d"), mAudioOuts); @@ -3290,7 +3290,13 @@ bool VSTEffect::Startup() return false; } - // mHost will be null when running in the subprocess + // If we have a master then there's no need to load settings since the master will feed + // us everything we need. + if (mMaster) + { + return true; + } + if (mHost) { mHost->GetSharedConfig(wxT("Settings"), wxT("BufferSize"), mUserBlockSize, 8192); @@ -3314,6 +3320,12 @@ bool VSTEffect::Startup() bool VSTEffect::Shutdown() { + // The master will save the settings. + if (mMaster) + { + return true; + } + SaveParameters(wxT("Current")); return true; @@ -3450,37 +3462,6 @@ bool VSTEffect::RealtimeInitialize() return ProcessInitialize(); } -bool VSTEffect::RealtimeAddProcessor(int numChannels, float sampleRate) -{ - VSTEffect *slave = new VSTEffect(mPath, this); - mSlaves.Add(slave); - - slave->SetChannelCount(numChannels); - slave->SetSampleRate(sampleRate); - - int clen = 0; - if (mAEffect->flags & effFlagsProgramChunks) - { - void *chunk = NULL; - - clen = (int) callDispatcher(effGetChunk, 1, 0, &chunk, 0.0); - if (clen != 0) - { - slave->callDispatcher(effSetChunk, 1, clen, chunk, 0.0); - } - } - - if (clen == 0) - { - for (int i = 0; i < mAEffect->numParams; i++) - { - slave->callSetParameter(i, callGetParameter(i)); - } - } - - return slave->RealtimeInitialize(); -} - bool VSTEffect::RealtimeFinalize() { for (size_t i = 0, cnt = mSlaves.GetCount(); i < cnt; i++) @@ -3598,6 +3579,37 @@ sampleCount VSTEffect::RealtimeProcess(int group, float **inbuf, float **outbuf, return mSlaves[group]->ProcessBlock(inbuf, outbuf, size); } +bool VSTEffect::RealtimeAddProcessor(int numChannels, float sampleRate) +{ + VSTEffect *slave = new VSTEffect(mPath, this); + mSlaves.Add(slave); + + slave->SetChannelCount(numChannels); + slave->SetSampleRate(sampleRate); + + int clen = 0; + if (mAEffect->flags & effFlagsProgramChunks) + { + void *chunk = NULL; + + clen = (int) callDispatcher(effGetChunk, 1, 0, &chunk, 0.0); + if (clen != 0) + { + slave->callDispatcher(effSetChunk, 1, clen, chunk, 0.0); + } + } + + if (clen == 0) + { + for (int i = 0; i < mAEffect->numParams; i++) + { + slave->callSetParameter(i, callGetParameter(i)); + } + } + + return slave->RealtimeInitialize(); +} + // // Some history... // diff --git a/src/effects/ladspa/LadspaEffect.cpp b/src/effects/ladspa/LadspaEffect.cpp index 150713335..cb0eee0ea 100644 --- a/src/effects/ladspa/LadspaEffect.cpp +++ b/src/effects/ladspa/LadspaEffect.cpp @@ -29,6 +29,9 @@ effects from this one class. #include #include #include +#include +#include +#include #include #include #include @@ -43,349 +46,901 @@ effects from this one class. #include "LadspaEffect.h" // This class's header file #include "../../Internat.h" -LadspaEffect::LadspaEffect(const LADSPA_Descriptor *data, - const std::set& categories) - : mCategories(categories) { +// ============================================================================ +// +// Module registration entry point +// +// This is the symbol that Audacity looks for when the module is built as a +// dynamic library. +// +// When the module is builtin to Audacity, we use the same function, but it is +// declared static so as not to clash with other builtin modules. +// +// ============================================================================ +DECLARE_MODULE_ENTRY(AudacityModule) +{ + // Create and register the importer + return new LadspaEffectsModule(moduleManager, path); +} - mData = data; - pluginName = LAT1CTOWX(mData->Name); +// ============================================================================ +// +// Register this as a builtin module +// +// ============================================================================ +DECLARE_BUILTIN_MODULE(LadspaBuiltin); - fInBuffer = NULL; - fOutBuffer = NULL; +// ============================================================================ +// +// LadspaEffectsModule +// +// ============================================================================ +LadspaEffectsModule::LadspaEffectsModule(ModuleManagerInterface *moduleManager, + const wxString *path) +{ + mModMan = moduleManager; + if (path) + { + mPath = *path; + } +} - inputs = 0; - outputs = 0; - numInputControls = 0; - mLength = 0; +LadspaEffectsModule::~LadspaEffectsModule() +{ +} - unsigned long p; +// ============================================================================ +// IdentInterface implementation +// ============================================================================ - inputPorts = new unsigned long [mData->PortCount]; - outputPorts = new unsigned long [mData->PortCount]; - inputControls = new float [mData->PortCount]; - outputControls = new float [mData->PortCount]; +wxString LadspaEffectsModule::GetID() +{ + // Can be anything, but this is a v4 UUID + return L"3ebd9fb9-c020-4c0d-a786-d6a914e55e31"; +} - for(p=0; pPortCount; p++) { - LADSPA_PortDescriptor d = mData->PortDescriptors[p]; - if (LADSPA_IS_PORT_AUDIO(d)) { - if (LADSPA_IS_PORT_INPUT(d)) { - inputPorts[inputs] = p; - inputs++; - } - else if (LADSPA_IS_PORT_OUTPUT(d)) { - outputPorts[outputs] = p; - outputs++; +wxString LadspaEffectsModule::GetPath() +{ + return mPath; +} + +wxString LadspaEffectsModule::GetName() +{ + return _("Ladspa Effect Module"); +} + +wxString LadspaEffectsModule::GetVendor() +{ + return _("The Audacity Team"); +} + +wxString LadspaEffectsModule::GetVersion() +{ + // This "may" be different if this were to be maintained as a separate DLL + return LADSPAEFFECTS_VERSION; +} + +wxString LadspaEffectsModule::GetDescription() +{ + return _("Provides Ladspa Effects"); +} + +// ============================================================================ +// ModuleInterface implementation +// ============================================================================ + +bool LadspaEffectsModule::Initialize() +{ + // Nothing to do here + return true; +} + +void LadspaEffectsModule::Terminate() +{ + // Nothing to do here + return; +} + +bool LadspaEffectsModule::AutoRegisterPlugins(PluginManagerInterface & pm) +{ + return false; +} + +wxArrayString LadspaEffectsModule::FindPlugins(PluginManagerInterface & pm) +{ +#if defined(USE_LIBLRDF) && defined(EFFECT_CATEGORIES) + + EffectManager& em = EffectManager::Get(); + wxArrayString rdfPathList; + wxString rdfPathVar; + wxArrayString rdfFiles; + + InitCategoryMap(); + lrdf_init(); + + rdfPathVar = wxGetenv(wxT("LADSPA_RDF_PATH")); + if (rdfPathVar != wxT("")) + wxGetApp().AddMultiPathsToPathList(rdfPathVar, rdfPathList); + +#ifdef __WXGTK__ + wxGetApp().AddUniquePathToPathList(wxT("/usr/share/ladspa/rdf"), + rdfPathList); + wxGetApp().AddUniquePathToPathList(wxT("/usr/local/share/ladspa/rdf"), + rdfPathList); +#endif + +#ifdef __WXMAC__ + wxGetApp().AddUniquePathToPathList(wxT("/usr/share/ladspa/rdf"), + rdfPathList); + // XXX Maybe other Mac paths here? +#endif + +#ifdef __WXMSW__ + //wxGetApp().AddUniquePathToPathList(wxT("WINDOWS LRDF PATH"), + // rdfPathList); + // XXX Other Windows paths here. +#endif + + // Add the Audacity paths so we get ladspa.rdfs if we are using a local + // liblrdf + for(i=0; icount; ++i) { + char* label = lrdf_get_label(cats->items[i]); + if (!label) + continue; + wxString uri = MapCategoryUri(wxString::FromAscii(cats->items[i])); + em.AddCategory(uri, wxString::FromUTF8(label)); + std::free(label); + + lrdf_uris* plugs = lrdf_get_instances(cats->items[i]); + if (plugs) { + for (size_t j = 0; j < plugs->count; ++j) { + unsigned long uid = lrdf_get_uid(plugs->items[j]); + gPluginCategories.insert(std::make_pair(uid, uri)); + } + lrdf_free_uris(plugs); } } - if (LADSPA_IS_PORT_CONTROL(d) && - LADSPA_IS_PORT_INPUT(d)) { - numInputControls++; - float val = float(1.0); - LADSPA_PortRangeHint hint = mData->PortRangeHints[p]; + // And their relationships + for (size_t i = 0; i < cats->count; ++i) { + EffectCategory* p = + em.LookupCategory(MapCategoryUri(wxString::FromAscii(cats-> + items[i]))); + if (!p) + continue; + lrdf_uris* subs = lrdf_get_subclasses(cats->items[i]); + if (subs) { + for (size_t j = 0; j < subs->count; ++j) { + EffectCategory* c = + em.LookupCategory(MapCategoryUri(wxString::FromAscii(subs->items[j]))); + if (c) + em.AddCategoryParent(c, p); + } + lrdf_free_uris(subs); + } + } - if (LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor) && - val < hint.LowerBound) - val = hint.LowerBound; + lrdf_free_uris(cats); - if (LADSPA_IS_HINT_BOUNDED_ABOVE(hint.HintDescriptor) && - val > hint.UpperBound) - val = hint.UpperBound; + } - if (LADSPA_IS_HINT_DEFAULT_MINIMUM(hint.HintDescriptor)) - val = hint.LowerBound; +#endif - if (LADSPA_IS_HINT_DEFAULT_LOW(hint.HintDescriptor)) - val = hint.LowerBound * 0.75f + hint.UpperBound * 0.25f; + wxArrayString pathList; + wxArrayString files; + wxString pathVar; - if (LADSPA_IS_HINT_DEFAULT_MIDDLE(hint.HintDescriptor)) - val = hint.LowerBound * 0.5f + hint.UpperBound * 0.5f; - - if (LADSPA_IS_HINT_DEFAULT_HIGH(hint.HintDescriptor)) - val = hint.LowerBound * 0.25f + hint.UpperBound * 0.75f; - - if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(hint.HintDescriptor)) - val = hint.UpperBound; - - if (LADSPA_IS_HINT_SAMPLE_RATE(hint.HintDescriptor)) - val *= mProjectRate; - - if (LADSPA_IS_HINT_DEFAULT_0(hint.HintDescriptor)) - val = 0.0f; - - if (LADSPA_IS_HINT_DEFAULT_1(hint.HintDescriptor)) - val = 1.0f; - - if (LADSPA_IS_HINT_DEFAULT_100(hint.HintDescriptor)) - val = 100.0f; - - if (LADSPA_IS_HINT_DEFAULT_440(hint.HintDescriptor)) - val = 440.0f; - - inputControls[p] = val; + // Check for the LADSPA_PATH environment variable + pathVar = wxString::FromUTF8(getenv("LADSPA_PATH")); + if (!pathVar.empty()) + { + wxStringTokenizer tok(pathVar); + while (tok.HasMoreTokens()) + { + pathList.Add(tok.GetNextToken()); } } - int flags = PLUGIN_EFFECT; - if (inputs == 0) - flags |= INSERT_EFFECT; - else if (outputs == 0) - flags |= ANALYZE_EFFECT; - else - flags |= PROCESS_EFFECT; +#if defined(__WXMAC__) - SetEffectFlags(flags); + pathList.Add(wxT("~/Library/Audio/Plug-Ins/LADSPA")); + pathList.Add(wxT("/Library/Audio/Plug-Ins/LADSPA")); + + // Recursively scan for all shared objects + pm.FindFilesInPathList(wxT("*.so"), pathList, files); + +#elif defined(__WXMSW__) + + // Recursively scan for all DLLs + pm.FindFilesInPathList(wxT("*.dll"), pathList, files); + +#else + + pathList.Add(wxT("~/.ladspa")); + pathList.Add(wxT("/usr/local/lib/ladspa")); + pathList.Add(wxT("/usr/lib/ladspa")); + pathList.Add(wxT(LIBDIR) wxT("/ladspa")); + + // Recursively scan for all shared objects + pm.FindFilesInPathList(wxT("*.so"), pathList, files); + +#endif + + return files; +} + +bool LadspaEffectsModule::RegisterPlugin(PluginManagerInterface & pm, const wxString & path) +{ + // Since we now have builtin VST support, ignore the VST bridge as it + // causes duplicate menu entries to appear. + wxFileName f(path); + if (f.GetName().CmpNoCase(wxT("vst-bridge")) == 0) { + return false; + } + + // As a courtesy to some plug-ins that might be bridges to + // open other plug-ins, we set the current working + // directory to be the plug-in's directory. + + wxString saveOldCWD = ::wxGetCwd(); + wxString prefix = ::wxPathOnly(path); + ::wxSetWorkingDirectory(prefix); + + int index = 0; + LADSPA_Descriptor_Function mainFn = NULL; + wxDynamicLibrary lib; + if (lib.Load(path, wxDL_LAZY)) { + wxLogNull logNo; + + mainFn = (LADSPA_Descriptor_Function) lib.GetSymbol(wxT("ladspa_descriptor")); + + if (mainFn) { + const LADSPA_Descriptor *data; + + for (data = mainFn(index); data; data = mainFn(++index)) { +#if defined(USE_LIBLRDF) && defined(EFFECT_CATEGORIES) + std::set categories; + std::multimap::const_iterator iter; + iter = gPluginCategories.lower_bound(data->UniqueID); + for ( ; (iter != gPluginCategories.end() && + iter->first == data->UniqueID); ++iter) + categories.insert(iter->second); +#endif + LadspaEffect effect(path, index); + if (effect.Startup()) { + pm.RegisterEffectPlugin(this, &effect); + effect.Shutdown(); + } + } + } + } + + if (lib.IsLoaded()) { + lib.Unload(); + } + + ::wxSetWorkingDirectory(saveOldCWD); + + return index > 0; +} + +void *LadspaEffectsModule::CreateInstance(const PluginID & ID, const wxString & path) +{ + // For us, the ID is two words. + // 1) The Ladspa descriptor index + // 2) The library's path + long index; + ID.BeforeFirst(wxT(' ')).ToLong(&index); + + return new LadspaEffect(path, (int) index); +} + +LadspaEffect::LadspaEffect(const wxString & path, int index) +{ + mPath = path; + mIndex = index; + mData = NULL; + + mHost = NULL; + mMaster = NULL; + mReady = false; + + mAudioIns = 0; + mAudioOuts = 0; + mNumInputControls = 0; + + mInputPorts = NULL; + mOutputPorts = NULL; + mInputControls = NULL; + mOutputControls = NULL; + + mDlg = NULL; } LadspaEffect::~LadspaEffect() { - delete[] inputPorts; - delete[] outputPorts; - delete[] inputControls; - delete[] outputControls; -} - -wxString LadspaEffect::GetEffectName() -{ - if (numInputControls > 0) - return pluginName + wxT("..."); - else - return pluginName; -} - -std::set LadspaEffect::GetEffectCategories() -{ - return mCategories; -} - -wxString LadspaEffect::GetEffectIdentifier() -{ - wxStringTokenizer st(pluginName, wxT(" ")); - wxString id; - - // CamelCase the name - while (st.HasMoreTokens()) { - wxString tok = st.GetNextToken(); - - id += tok.Left(1).MakeUpper() + tok.Mid(1); + if (mInputPorts) + { + delete [] mInputPorts; } - return id; + if (mOutputPorts) + { + delete [] mOutputPorts; + } + + if (mInputControls) + { + delete [] mInputControls; + } + + if (mOutputControls) + { + delete [] mOutputControls; + } } -wxString LadspaEffect::GetEffectAction() +// +// IdentInterface implementation +// +wxString LadspaEffect::GetID() { - return wxString::Format(_("Performing Effect: %s"), - pluginName.c_str()); + return wxString::Format(wxT("%d %s"), mIndex, mPath.c_str()); } -bool LadspaEffect::Init() +wxString LadspaEffect::GetPath() { - mBlockSize = 0; - mainRate = 0; + return mPath; +} - TrackListOfKindIterator iter(Track::Wave, mTracks); - Track *left = iter.First(); - while(left) { - if (mainRate == 0) - mainRate = (int)(((WaveTrack *)left)->GetRate() + 0.5); +wxString LadspaEffect::GetName() +{ + return LAT1CTOWX(mData->Name); +} - if (left->GetLinked()) { - Track *right = iter.Next(); +wxString LadspaEffect::GetVendor() +{ + return LAT1CTOWX(mData->Maker); +} - if (((WaveTrack *)left)->GetRate() != - ((WaveTrack *)right)->GetRate()) { - wxMessageBox(_("Sorry, Plug-in Effects cannot be performed on stereo tracks where the individual channels of the track do not match.")); - return false; +wxString LadspaEffect::GetVersion() +{ + return _("N/A"); +} + +wxString LadspaEffect::GetDescription() +{ + return _("Audio In: ") + + wxString::Format(wxT("%d"), mAudioIns) + + _(", Audio Out: ") + + wxString::Format(wxT("%d"), mAudioOuts); +} + +// +// EffectIdentInterface implementation +// +EffectType LadspaEffect::GetType() +{ + if (mAudioIns == 0) + { + return EffectTypeGenerate; + } + + if (mAudioOuts == 0) + { + return EffectTypeAnalyze; + } + + return EffectTypeProcess; +} + +wxString LadspaEffect::GetFamily() +{ + return LADSPAEFFECTS_FAMILY; +} + +bool LadspaEffect::IsInteractive() +{ + return mInteractive; +} + +bool LadspaEffect::IsDefault() +{ + return false; +} + +bool LadspaEffect::IsLegacy() +{ + return false; +} + +bool LadspaEffect::IsRealtimeCapable() +{ + return true; +} + +// +// EffectClientInterface Implementation +// +void LadspaEffect::SetHost(EffectHostInterface *host) +{ + mHost = host; +} + +bool LadspaEffect::Startup() +{ + if (!Load()) + { + return false; + } + + mInputPorts = new unsigned long [mData->PortCount]; + mOutputPorts = new unsigned long [mData->PortCount]; + mInputControls = new float [mData->PortCount]; + mOutputControls = new float [mData->PortCount]; + + for (unsigned long p = 0; p < mData->PortCount; p++) + { + LADSPA_PortDescriptor d = mData->PortDescriptors[p]; + if (LADSPA_IS_PORT_AUDIO(d)) + { + if (LADSPA_IS_PORT_INPUT(d)) + { + mInputPorts[mAudioIns++] = p; + } + else if (LADSPA_IS_PORT_OUTPUT(d)) + { + mOutputPorts[mAudioOuts++] = p; } } - left = iter.Next(); + if (LADSPA_IS_PORT_CONTROL(d) && LADSPA_IS_PORT_INPUT(d)) + { + mInteractive = true; + + float val = float(1.0); + LADSPA_PortRangeHint hint = mData->PortRangeHints[p]; + + if (LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor) && val < hint.LowerBound) + { + val = hint.LowerBound; + } + + if (LADSPA_IS_HINT_BOUNDED_ABOVE(hint.HintDescriptor) && val > hint.UpperBound) + { + val = hint.UpperBound; + } + + if (LADSPA_IS_HINT_DEFAULT_MINIMUM(hint.HintDescriptor)) + { + val = hint.LowerBound; + } + + if (LADSPA_IS_HINT_DEFAULT_LOW(hint.HintDescriptor)) + { + val = hint.LowerBound * 0.75f + hint.UpperBound * 0.25f; + } + + if (LADSPA_IS_HINT_DEFAULT_MIDDLE(hint.HintDescriptor)) + { + val = hint.LowerBound * 0.5f + hint.UpperBound * 0.5f; + } + + if (LADSPA_IS_HINT_DEFAULT_HIGH(hint.HintDescriptor)) + { + val = hint.LowerBound * 0.25f + hint.UpperBound * 0.75f; + } + + if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(hint.HintDescriptor)) + { + val = hint.UpperBound; + } + + if (LADSPA_IS_HINT_SAMPLE_RATE(hint.HintDescriptor)) + { + val *= mSampleRate; + } + + if (LADSPA_IS_HINT_DEFAULT_0(hint.HintDescriptor)) + { + val = 0.0f; + } + + if (LADSPA_IS_HINT_DEFAULT_1(hint.HintDescriptor)) + { + val = 1.0f; + } + + if (LADSPA_IS_HINT_DEFAULT_100(hint.HintDescriptor)) + { + val = 100.0f; + } + + if (LADSPA_IS_HINT_DEFAULT_440(hint.HintDescriptor)) + { + val = 440.0f; + } + + mNumInputControls++; + mInputControls[p] = val; + } } - if (mainRate<=0) - mainRate = (int)(mProjectRate + 0.5); + // mHost will be null during registration + if (mHost) + { + mHost->GetSharedConfig(wxT("Settings"), wxT("BufferSize"), mUserBlockSize, 8192); + mBlockSize = mUserBlockSize; + + bool haveDefaults; + mHost->GetPrivateConfig(wxT("Default"), wxT("Initialized"), haveDefaults, false); + if (!haveDefaults) + { + SaveParameters(wxT("Default")); + mHost->SetPrivateConfig(wxT("Default"), wxT("Initialized"), true); + } + + LoadParameters(wxT("Current")); + } return true; } -bool LadspaEffect::PromptUser() +bool LadspaEffect::Shutdown() { - if (numInputControls > 0) { - double length = mT1 > mT0 ? mT1 - mT0 : sDefaultGenerateLen; - - LadspaEffectDialog dlog(this, mParent, mData, inputControls, mainRate, length); - dlog.CentreOnParent(); - dlog.ShowModal(); - - if (!dlog.GetReturnCode()) - return false; - - mLength = dlog.GetLength(); + // mHost will be null during registration + if (mHost) + { + SaveParameters(wxT("Current")); } + + if (mInputPorts) + { + delete [] mInputPorts; + mInputPorts = NULL; + } + + if (mOutputPorts) + { + delete [] mOutputPorts; + mOutputPorts = NULL; + } + + if (mInputControls) + { + delete [] mInputControls; + mInputControls = NULL; + } + + if (mOutputControls) + { + delete [] mOutputControls; + mOutputControls = NULL; + } + return true; } -bool LadspaEffect::Process() +int LadspaEffect::GetAudioInCount() { - this->CopyInputTracks(); // Set up mOutputTracks. - bool bGoodResult = true; - - TrackListIterator iter(mOutputTracks); - int count = 0; - Track *left = iter.First(); - Track *right; - while(left) { - sampleCount lstart = 0, rstart = 0; - sampleCount len; - GetSamples((WaveTrack *)left, &lstart, &len); - - right = NULL; - if (left->GetLinked() && inputs>1) { - right = iter.Next(); - GetSamples((WaveTrack *)right, &rstart, &len); - } - - if (inputs < 2 && right) { - // If the effect is mono, apply to each channel separately - - bGoodResult = ProcessStereo(count, (WaveTrack *)left, NULL, - lstart, 0, len) && - ProcessStereo(count, (WaveTrack *)right, NULL, - rstart, 0, len); - } - else bGoodResult = ProcessStereo(count, - (WaveTrack *)left, (WaveTrack *)right, - lstart, rstart, len); - if (!bGoodResult) - break; - - left = iter.Next(); - count++; - } - - this->ReplaceProcessedTracks(bGoodResult); - return bGoodResult; + return mAudioIns; } -bool LadspaEffect::ProcessStereo(int count, WaveTrack *left, WaveTrack *right, - sampleCount lstart, - sampleCount rstart, - sampleCount len) +int LadspaEffect::GetAudioOutCount() { - /* Allocate buffers */ - if (mBlockSize == 0) { - mBlockSize = left->GetMaxBlockSize() * 2; + return mAudioOuts; +} - fInBuffer = new float *[inputs]; - unsigned long i; - for (i = 0; i < inputs; i++) - fInBuffer[i] = new float[mBlockSize]; - fOutBuffer = new float *[outputs]; - for (i = 0; i < outputs; i++) - fOutBuffer[i] = new float[mBlockSize]; +int LadspaEffect::GetMidiInCount() +{ + return 0; +} + +int LadspaEffect::GetMidiOutCount() +{ + return 0; +} + +void LadspaEffect::SetSampleRate(sampleCount rate) +{ + mSampleRate = rate; +} + +sampleCount LadspaEffect::GetBlockSize(sampleCount maxBlockSize) +{ +#if 0 + // TODO: Allow user to specify the max blocksize + if (mUserBlockSize > maxBlockSize) + { + mBlockSize = maxBlockSize; } + else + { + mBlockSize = mUserBlockSize; + } +#endif + return mBlockSize; +} + +sampleCount LadspaEffect::GetLatency() +{ + // Ladspa effects have a convention of providing latency on an output + // control port name "latency". + return 0; +} + +sampleCount LadspaEffect::GetTailSize() +{ + return 0; +} + +bool LadspaEffect::IsReady() +{ + return mReady; +} + +bool LadspaEffect::ProcessInitialize() +{ /* Instantiate the plugin */ - - unsigned long rate = (unsigned long)(left->GetRate() + 0.5); - LADSPA_Handle handle = mData->instantiate(mData, rate); - - unsigned long p; - for(p=0; pconnect_port(handle, inputPorts[p], fInBuffer[p]); - } - for(p=0; pconnect_port(handle, outputPorts[p], fOutBuffer[p]); + if (!mReady) + { + mMaster = InitInstance(mSampleRate); + mReady = true; } - for(p=0; pPortCount; p++) { + return true; +} + +bool LadspaEffect::ProcessFinalize() +{ + if (mReady) + { + mReady = false; + + FreeInstance(mMaster); + mMaster = NULL; + } + + return true; +} + +sampleCount LadspaEffect::ProcessBlock(float **inbuf, float **outbuf, sampleCount size) +{ + for (int i = 0; i < mAudioIns; i++) + { + mData->connect_port(mMaster, mInputPorts[i], inbuf[i]); + } + + for (int i = 0; i < mAudioOuts; i++) + { + mData->connect_port(mMaster, mOutputPorts[i], outbuf[i]); + } + + mData->run(mMaster, size); + + return size; +} + +bool LadspaEffect::RealtimeInitialize() +{ + return true; +} + +bool LadspaEffect::RealtimeFinalize() +{ + for (size_t i = 0, cnt = mSlaves.GetCount(); i < cnt; i++) + { + FreeInstance(mSlaves[i]); + } + mSlaves.Clear(); + + return true; +} + +bool LadspaEffect::RealtimeSuspend() +{ + return true; +} + +bool LadspaEffect::RealtimeResume() +{ + return true; +} + +sampleCount LadspaEffect::RealtimeProcess(int group, + float **inbuf, + float **outbuf, + sampleCount numSamples) +{ + if (group < 0 || group >= (int) mSlaves.GetCount()) + { + return 0; + } + + for (int i = 0; i < mAudioIns; i++) + { + mData->connect_port(mSlaves[group], mInputPorts[i], inbuf[i]); + } + + for (int i = 0; i < mAudioOuts; i++) + { + mData->connect_port(mSlaves[group], mOutputPorts[i], outbuf[i]); + } + + mData->run(mSlaves[group], numSamples); + + return numSamples; +} + +bool LadspaEffect::RealtimeAddProcessor(int numChannels, float sampleRate) +{ + LADSPA_Handle slave = InitInstance(sampleRate); + mSlaves.Add(slave); + mSlaveChannels.Add(numChannels); + + return true; +} + +bool LadspaEffect::ShowInterface(void *parent) +{ + if (mNumInputControls == 0) { + return false; + } + + double length = 0; //mT1 > mT0 ? mT1 - mT0 : sDefaultGenerateLen; + + if (!mDlg) + { + mDlg = new LadspaEffectDialog(this, (wxWindow *) parent, mData, mInputControls, mSampleRate, length); + mDlg->CentreOnParent(); + } + +#if defined(EXPERIMENTAL_REALTIME_EFFECTS) + mDlg->Show(!mDlg->IsShown()); + + return true; +#else + mDlg->ShowModal(); + bool ret = mDlg->GetReturnCode() != 0; + mDlg->Destroy(); + mDlg = NULL; + + return ret; +#endif +} + +// +// LadspaEffect Implementation +// +bool LadspaEffect::Load() +{ + if (mLib.IsLoaded()) + { + return true; + } + + LADSPA_Descriptor_Function mainFn = NULL; + if (mLib.Load(mPath, wxDL_LAZY)) + { + wxLogNull logNo; + + mainFn = (LADSPA_Descriptor_Function) mLib.GetSymbol(wxT("ladspa_descriptor")); + if (mainFn) + { + mData = mainFn(mIndex); + return true; + } + } + + if (mLib.IsLoaded()) + { + mLib.Unload(); + } + + return false; +} + +void LadspaEffect::Unload() +{ + if (mLib.IsLoaded()) + { + mLib.Unload(); + } +} + +void LadspaEffect::LoadParameters(const wxString & group) +{ + wxString value; + + if (mHost->GetPrivateConfig(group, wxT("Value"), value, wxEmptyString)) + { + wxStringTokenizer st(value, wxT(',')); + if (st.CountTokens() == mData->PortCount) + { + for (unsigned long p = 0; st.HasMoreTokens(); p++) + { + double val = 0.0; + st.GetNextToken().ToDouble(&val); + + if (val >= -1.0 && val <= 1.0) + { + mInputControls[p] = val; + } + } + } + } +} + +void LadspaEffect::SaveParameters(const wxString & group) +{ + wxString parms; + for (unsigned long p = 0; p < mData->PortCount; p++) + { + parms += wxString::Format(wxT(",%f"), mInputControls[p]); + } + + mHost->SetPrivateConfig(group, wxT("Value"), parms.Mid(1)); +} + +LADSPA_Handle LadspaEffect::InitInstance(float sampleRate) +{ + /* Instantiate the plugin */ + LADSPA_Handle handle = mData->instantiate(mData, sampleRate); + + for (unsigned long p = 0; p < mData->PortCount; p++) + { LADSPA_PortDescriptor d = mData->PortDescriptors[p]; - if (LADSPA_IS_PORT_CONTROL(d)) { - if (LADSPA_IS_PORT_INPUT(d)) { - mData->connect_port(handle, p, &inputControls[p]); + if (LADSPA_IS_PORT_CONTROL(d)) + { + if (LADSPA_IS_PORT_INPUT(d)) + { + mData->connect_port(handle, p, &mInputControls[p]); } else - mData->connect_port(handle, p, &outputControls[p]); + { + mData->connect_port(handle, p, &mOutputControls[p]); + } } } if (mData->activate) + { mData->activate(handle); - - // Actually perform the effect here - - sampleCount originalLen = len; - sampleCount ls = lstart; - sampleCount rs = rstart; - while (len) { - int block = mBlockSize; - if (block > len) - block = len; - - if (left && inputs > 0) { - left->Get((samplePtr)fInBuffer[0], floatSample, ls, block); - } - if (right && inputs > 1) { - right->Get((samplePtr)fInBuffer[1], floatSample, rs, block); - } - - mData->run(handle, block); - - if (left && outputs > 0) { - left->Set((samplePtr)fOutBuffer[0], floatSample, ls, block); - } - - if (right && outputs > 1) { - right->Set((samplePtr)fOutBuffer[1], floatSample, rs, block); - } - - len -= block; - ls += block; - rs += block; - - if (inputs > 1) { - if (TrackGroupProgress(count, (ls-lstart)/(double)originalLen)) - return false; - } - else { - if (TrackProgress(count, (ls-lstart)/(double)originalLen)) - return false; - } } - if (mData->deactivate) - mData->deactivate(handle); - - if (mData->cleanup) - mData->cleanup(handle); - - return true; + return handle; } -void LadspaEffect::End() +void LadspaEffect::FreeInstance(LADSPA_Handle handle) { - unsigned long i; - - if (fInBuffer) { - for (i = 0; i < inputs; i++) { - if (fInBuffer[i]) { - delete [] fInBuffer[i]; - } - } - delete [] fInBuffer; - fInBuffer = NULL; + if (mData->deactivate) + { + mData->deactivate(handle); } - if (fOutBuffer) { - for (i = 0; i < outputs; i++) { - if (fOutBuffer[i]) { - delete [] fOutBuffer[i]; - } - } - delete [] fOutBuffer; - fOutBuffer = NULL; - } + mData->cleanup(handle); } class Slider:public wxSlider @@ -492,9 +1047,13 @@ END_EVENT_TABLE() const int LADSPA_SECONDS_ID = 13101; BEGIN_EVENT_TABLE(LadspaEffectDialog, wxDialog) +#if defined(EXPERIMENTAL_REALTIME_EFFECTS) + EVT_BUTTON(wxID_APPLY, LadspaEffectDialog::OnApply) +#else EVT_BUTTON(wxID_OK, LadspaEffectDialog::OnOK) EVT_BUTTON(wxID_CANCEL, LadspaEffectDialog::OnCancel) EVT_BUTTON(ID_EFFECT_PREVIEW, LadspaEffectDialog::OnPreview) +#endif EVT_SLIDER(wxID_ANY, LadspaEffectDialog::OnSlider) EVT_TEXT(wxID_ANY, LadspaEffectDialog::OnTextCtrl) EVT_CHECKBOX(wxID_ANY, LadspaEffectDialog::OnCheckBox) @@ -506,7 +1065,7 @@ LadspaEffectDialog::LadspaEffectDialog(LadspaEffect *eff, wxWindow * parent, const LADSPA_Descriptor *data, float *inputControls, - int sampleRate, + sampleCount sampleRate, double length) :wxDialog(parent, -1, LAT1CTOWX(data->Name), wxDefaultPosition, wxDefaultSize, @@ -515,9 +1074,9 @@ LadspaEffectDialog::LadspaEffectDialog(LadspaEffect *eff, { mLength = length; numParams = 0; - this->mData = data; - this->inputControls = inputControls; - this->sampleRate = sampleRate; + mData = data; + mInputControls = inputControls; + sampleRate = sampleRate; #ifdef __WXMSW__ // On Windows, for some reason, wxWidgets calls OnTextCtrl during creation // of the text control, and LadspaEffectDialog::OnTextCtrl calls HandleText, @@ -582,7 +1141,11 @@ LadspaEffectDialog::LadspaEffectDialog(LadspaEffect *eff, vSizer->Add(w, 1, wxEXPAND|wxALL, 5); // Preview, OK, & Cancel buttons - vSizer->Add(CreateStdButtonSizer(this, ePreviewButton|eCancelButton|eOkButton), 0, wxEXPAND); +#if defined(EXPERIMENTAL_REALTIME_EFFECTS) + vSizer->Add(CreateStdButtonSizer(this, eApplyButton | eDefaultsButton), 0, wxEXPAND); +#else + vSizer->Add(CreateStdButtonSizer(this, ePreviewButton | eDefaultsButton |eCancelButton | eOkButton), 0, wxEXPAND); +#endif SetSizer(vSizer); @@ -604,7 +1167,7 @@ LadspaEffectDialog::LadspaEffectDialog(LadspaEffect *eff, if (LADSPA_IS_HINT_TOGGLED(hint.HintDescriptor)) { toggles[p] = new wxCheckBox(w, p, wxT("")); toggles[p]->SetName(labelText); - toggles[p]->SetValue(inputControls[ports[p]] > 0); + toggles[p]->SetValue(mInputControls[ports[p]] > 0); gridSizer->Add(toggles[p], 0, wxALL, 5); ConnectFocus(toggles[p]); @@ -614,9 +1177,9 @@ LadspaEffectDialog::LadspaEffectDialog(LadspaEffect *eff, } else { if (LADSPA_IS_HINT_INTEGER(hint.HintDescriptor)) - fieldText.Printf(wxT("%d"), (int)(inputControls[ports[p]] + 0.5)); + fieldText.Printf(wxT("%d"), (int)(mInputControls[ports[p]] + 0.5)); else - fieldText = Internat::ToDisplayString(inputControls[ports[p]]); + fieldText = Internat::ToDisplayString(mInputControls[ports[p]]); fields[p] = new wxTextCtrl(w, p, fieldText); fields[p]->SetName(labelText); @@ -681,7 +1244,7 @@ LadspaEffectDialog::LadspaEffectDialog(LadspaEffect *eff, } // Now add the length control - if (effect->GetEffectFlags() & INSERT_EFFECT) { + if (effect->GetType() == EffectTypeGenerate) { item = new wxStaticText(w, 0, _("Length (seconds)")); gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); mSeconds = new wxTextCtrl(w, LADSPA_SECONDS_ID, Internat::ToDisplayString(length)); @@ -719,7 +1282,7 @@ void LadspaEffectDialog::OnCheckBox(wxCommandEvent &event) { int p = event.GetId(); - inputControls[ports[p]] = toggles[p]->GetValue(); + mInputControls[ports[p]] = toggles[p]->GetValue(); } void LadspaEffectDialog::OnSlider(wxCommandEvent &event) @@ -763,7 +1326,7 @@ void LadspaEffectDialog::OnSlider(wxCommandEvent &event) fields[p]->SetValue(str); - inputControls[ports[p]] = val; + mInputControls[ports[p]] = val; inSlider = false; } @@ -813,7 +1376,7 @@ void LadspaEffectDialog::HandleText() if (val > upper) val = upper; - inputControls[ports[p]] = val; + mInputControls[ports[p]] = val; sliders[p]->SetValue((int)(((val-lower)/range) * 1000.0 + 0.5)); } @@ -821,6 +1384,18 @@ void LadspaEffectDialog::HandleText() inText = false; } +#if defined(EXPERIMENTAL_REALTIME_EFFECTS) +void LadspaEffectDialog::OnApply(wxCommandEvent & WXUNUSED(evt)) +{ +#if defined(__WXMAC__) + Close(); +#else + Show(false); +#endif + + effect->mHost->Apply(); +} +#else void LadspaEffectDialog::OnOK(wxCommandEvent & WXUNUSED(event)) { EndModal(TRUE); @@ -835,6 +1410,7 @@ void LadspaEffectDialog::OnPreview(wxCommandEvent & WXUNUSED(event)) { effect->Preview(); } +#endif void LadspaEffectDialog::ConnectFocus(wxControl *c) { @@ -880,7 +1456,7 @@ void LadspaEffectDialog::ControlSetFocus(wxFocusEvent &event) double LadspaEffectDialog::GetLength() { - if (effect->GetEffectFlags() & INSERT_EFFECT) { + if (effect->GetType() == EffectTypeGenerate) { mLength = Internat::CompatibleToDouble(mSeconds->GetValue()); } diff --git a/src/effects/ladspa/LadspaEffect.h b/src/effects/ladspa/LadspaEffect.h index 7c4cb1b34..c2a5cfd83 100644 --- a/src/effects/ladspa/LadspaEffect.h +++ b/src/effects/ladspa/LadspaEffect.h @@ -15,59 +15,164 @@ class wxCheckBox; #include -#include "../Effect.h" +#include "audacity/EffectInterface.h" +#include "audacity/ModuleInterface.h" +#include "audacity/PluginInterface.h" + #include "ladspa.h" -void LoadLadspaPlugins(); +#define LADSPAEFFECTS_VERSION wxT("1.0.0.0"); +#define LADSPAEFFECTS_FAMILY L"Ladspa" -class LadspaEffect:public Effect { +WX_DEFINE_ARRAY_PTR(LADSPA_Handle, LadspaSlaveArray); - public: +class LadspaEffectDialog; - LadspaEffect(const LADSPA_Descriptor *data, - const std::set& categories = std::set()); +class LadspaEffect : public EffectClientInterface +{ +public: + LadspaEffect(const wxString & path, int index); virtual ~LadspaEffect(); - virtual wxString GetEffectName(); + // IdentInterface implementation + virtual PluginID GetID(); + virtual wxString GetPath(); + virtual wxString GetName(); + virtual wxString GetVendor(); + virtual wxString GetVersion(); + virtual wxString GetDescription(); - virtual std::set GetEffectCategories(); + // EffectIdentInterface implementation + virtual EffectType GetType(); + virtual wxString GetFamily(); + virtual bool IsInteractive(); + virtual bool IsDefault(); + virtual bool IsLegacy(); + virtual bool IsRealtimeCapable(); - virtual wxString GetEffectIdentifier(); + // EffectClientInterface implementation + virtual void SetHost(EffectHostInterface *host); + virtual bool Startup(); + virtual bool Shutdown(); - virtual wxString GetEffectAction(); + virtual int GetAudioInCount(); + virtual int GetAudioOutCount(); - virtual bool Init(); + virtual int GetMidiInCount(); + virtual int GetMidiOutCount(); - virtual bool PromptUser(); + virtual void SetSampleRate(sampleCount rate); + virtual sampleCount GetBlockSize(sampleCount maxBlockSize); - virtual bool Process(); + virtual sampleCount GetLatency(); + virtual sampleCount GetTailSize(); - virtual void End(); + virtual bool IsReady(); + virtual bool ProcessInitialize(); + virtual bool ProcessFinalize(); + virtual sampleCount ProcessBlock(float **inbuf, float **outbuf, sampleCount size); - private: - bool ProcessStereo(int count, WaveTrack * left, WaveTrack *right, - sampleCount lstart, sampleCount rstart, - sampleCount len); + virtual bool RealtimeInitialize(); + virtual bool RealtimeAddProcessor(int numChannels, float sampleRate); + virtual bool RealtimeFinalize(); + virtual bool RealtimeSuspend(); + virtual bool RealtimeResume(); + virtual sampleCount RealtimeProcess(int group, + float **inbuf, + float **outbuf, + sampleCount numSamples); + + virtual bool ShowInterface(void *parent); + +private: + // LadspaEffect implementation + bool Load(); + void Unload(); + + void LoadParameters(const wxString & group); + void SaveParameters(const wxString & group); + + LADSPA_Handle InitInstance(float sampleRate); + void FreeInstance(LADSPA_Handle handle); + +private: + + wxString mPath; + int mIndex; + EffectHostInterface *mHost; + + wxDynamicLibrary mLib; + const LADSPA_Descriptor *mData; wxString pluginName; - const LADSPA_Descriptor *mData; - sampleCount mBlockSize; - float **fInBuffer; - float **fOutBuffer; - unsigned long inputs; - unsigned long outputs; - unsigned long numInputControls; - unsigned long *inputPorts; - unsigned long *outputPorts; - float *inputControls; - float *outputControls; - int mainRate; + bool mReady; - std::set mCategories; + LADSPA_Handle mMaster; + + sampleCount mSampleRate; + sampleCount mBlockSize; + sampleCount mUserBlockSize; + + bool mInteractive; + + int mAudioIns; + unsigned long *mInputPorts; + + int mAudioOuts; + unsigned long *mOutputPorts; + + int mNumInputControls; + float *mInputControls; + float *mOutputControls; + + // Realtime processing + LadspaSlaveArray mSlaves; + wxArrayInt mSlaveChannels; + + LadspaEffectDialog *mDlg; + + friend class LadspaEffectDialog; + friend class LadspaEffectsModule; }; -class LadspaEffectDialog:public wxDialog { +class LadspaEffectsModule : public ModuleInterface +{ +public: + LadspaEffectsModule(ModuleManagerInterface *moduleManager, const wxString *path); + virtual ~LadspaEffectsModule(); + + // IdentInterface implementatino + + virtual wxString GetID(); + virtual wxString GetPath(); + virtual wxString GetName(); + virtual wxString GetVendor(); + virtual wxString GetVersion(); + virtual wxString GetDescription(); + + // ModuleInterface implementation + + virtual bool Initialize(); + virtual void Terminate(); + + virtual bool AutoRegisterPlugins(PluginManagerInterface & pm); + virtual wxArrayString FindPlugins(PluginManagerInterface & pm); + virtual bool RegisterPlugin(PluginManagerInterface & pm, const wxString & path); + + virtual void *CreateInstance(const PluginID & ID, const wxString & path); + + // LadspaEffectModule implementation + + static void Check(const wchar_t *path); + +private: + ModuleManagerInterface *mModMan; + wxString mPath; +}; + +class LadspaEffectDialog : public wxDialog +{ DECLARE_DYNAMIC_CLASS(LadspaEffectDialog) public: @@ -75,7 +180,7 @@ class LadspaEffectDialog:public wxDialog { wxWindow * parent, const LADSPA_Descriptor *data, float *inputControls, - int sampleRate, + sampleCount sampleRate, double length); ~LadspaEffectDialog(); @@ -83,16 +188,20 @@ class LadspaEffectDialog:public wxDialog { void OnCheckBox(wxCommandEvent & event); void OnSlider(wxCommandEvent & event); void OnTextCtrl(wxCommandEvent & event); - void OnOK(wxCommandEvent & event); - void OnCancel(wxCommandEvent & event); - void OnPreview(wxCommandEvent & event); +#if defined(EXPERIMENTAL_REALTIME_EFFECTS) + void OnApply(wxCommandEvent & evt); +#else + void OnOk(wxCommandEvent & evt); + void OnCancel(wxCommandEvent & evt); + void OnPreview(wxCommandEvent & evt); +#endif void ControlSetFocus(wxFocusEvent & event); double GetLength(); DECLARE_EVENT_TABLE() - private: +private: void HandleText(); void ConnectFocus(wxControl *c); void DisconnectFocus(wxControl *c); @@ -108,7 +217,7 @@ class LadspaEffectDialog:public wxDialog { wxCheckBox **toggles; unsigned long *ports; unsigned long numParams; - float *inputControls; + float *mInputControls; LadspaEffect *effect; wxTextCtrl *mSeconds; }; diff --git a/src/effects/ladspa/LoadLadspa.cpp b/src/effects/ladspa/LoadLadspa.cpp deleted file mode 100644 index fdec3dc79..000000000 --- a/src/effects/ladspa/LoadLadspa.cpp +++ /dev/null @@ -1,327 +0,0 @@ -/********************************************************************** - - Audacity: A Digital Audio Editor - - LoadLadspa.cpp - - Dominic Mazzoni - - From the ladspa docs: - "To allow multiple hosts to - share plugin types, hosts may wish to check for environment - variable LADSPA_PATH. If present, this should contain a - colon-separated path indicating directories that should be searched - (in order) when loading plugin types." - -**********************************************************************/ - -#define descriptorFnName "ladspa_descriptor" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "ladspa.h" - -#include "../../Audacity.h" -#include "../../AudacityApp.h" -#include "../../Experimental.h" -#include "../../Internat.h" -#include "../EffectManager.h" -#include "LadspaEffect.h" -#include "LoadLadspa.h" - -#if defined(USE_LIBLRDF) && defined(EFFECT_CATEGORIES) -#include -#endif - -WX_DEFINE_ARRAY(wxDynamicLibrary*, DL_Array); - -static DL_Array ladspa_dls; - -#if defined(USE_LIBLRDF) && defined(EFFECT_CATEGORIES) - -#define LADSPA(S) wxT("http://ladspa.org/ontology#") wxT(S) -#define LV2(S) wxT("http://lv2plug.in/ns/lv2core#") wxT(S) - -static std::map gCategoryMap; -static std::multimap gPluginCategories; - -/** This function initialises the data structure that maps common LRDF - category URIs to LV2 or internal Audacity category URIs. */ -static void InitCategoryMap() -{ - gCategoryMap[LADSPA("UtilityPlugin")] = LV2("UtilityPlugin"); - gCategoryMap[LADSPA("GeneratorPlugin")] = LV2("GeneratorPlugin"); - gCategoryMap[LADSPA("SimulatorPlugin")] = LV2("SimulatorPlugin"); - gCategoryMap[LADSPA("OscillatorPlugin")] = LV2("OscillatorPlugin"); - gCategoryMap[LADSPA("TimePlugin")] = LV2("DelayPlugin"); - gCategoryMap[LADSPA("DelayPlugin")] = LV2("DelayPlugin"); - gCategoryMap[LADSPA("PhaserPlugin")] = LV2("PhaserPlugin"); - gCategoryMap[LADSPA("FlangerPlugin")] = LV2("FlangerPlugin"); - gCategoryMap[LADSPA("ChorusPlugin")] = LV2("ChorusPlugin"); - gCategoryMap[LADSPA("ReverbPlugin")] = LV2("ReverbPlugin"); - gCategoryMap[LADSPA("FrequencyPlugin")] = LV2("SpectralPlugin"); - gCategoryMap[LADSPA("FrequencyMeterPlugin")] = LV2("AnalyserPlugin"); - gCategoryMap[LADSPA("FilterPlugin")] = LV2("FilterPlugin"); - gCategoryMap[LADSPA("LowpassPlugin")] = LV2("LowpassPlugin"); - gCategoryMap[LADSPA("HighpassPlugin")] = LV2("HighpassPlugin"); - gCategoryMap[LADSPA("BandpassPlugin")] = LV2("BandpassPlugin"); - gCategoryMap[LADSPA("CombPlugin")] = LV2("CombPlugin"); - gCategoryMap[LADSPA("AllpassPlugin")] = LV2("AllpassPlugin"); - gCategoryMap[LADSPA("EQPlugin")] = LV2("EQPlugin"); - gCategoryMap[LADSPA("ParaEQPlugin")] = LV2("ParaEQPlugin"); - gCategoryMap[LADSPA("MultiEQPlugin")] = LV2("MultiEQPlugin"); - gCategoryMap[LADSPA("AmplitudePlugin")] = LV2("AmplifierPlugin"); - gCategoryMap[LADSPA("PitchPlugin")] = LV2("PitchPlugin"); - gCategoryMap[LADSPA("AmplifierPlugin")] = LV2("AmplifierPlugin"); - gCategoryMap[LADSPA("WaveshaperPlugin")] = LV2("WaveshaperPlugin"); - gCategoryMap[LADSPA("ModulatorPlugin")] = LV2("ModulatorPlugin"); - gCategoryMap[LADSPA("DistortionPlugin")] = LV2("DistortionPlugin"); - gCategoryMap[LADSPA("DynamicsPlugin")] = LV2("DynamicsPlugin"); - gCategoryMap[LADSPA("CompressorPlugin")] = LV2("CompressorPlugin"); - gCategoryMap[LADSPA("ExpanderPlugin")] = LV2("ExpanderPlugin"); - gCategoryMap[LADSPA("LimiterPlugin")] = LV2("LimiterPlugin"); - gCategoryMap[LADSPA("GatePlugin")] = LV2("GatePlugin"); - - // This isn't in ladspa.rdfs, it's added by the swh-plugins - - // we add it here to avoid having multiple "Spectral" categories - gCategoryMap[LADSPA("SpectralPlugin")] = LV2("SpectralPlugin"); - -} - -/** This function maps a LADSPA category URI to the category URIs used - by Audacity (LV2 ones). If there is no known mapping for the - given LADSPA category URI it is returned unchanged. */ -static wxString MapCategoryUri(const wxString& ladspaCategory) -{ - std::map::const_iterator iter; - iter = gCategoryMap.find(ladspaCategory); - if (iter != gCategoryMap.end()) - return iter->second; - return ladspaCategory; -} - -#endif - -static void LoadLadspaEffect(wxSortedArrayString &uniq, wxString fname, - DL_Array &dls) -{ - wxLogNull logNo; - LADSPA_Descriptor_Function mainFn = NULL; - - // Since we now have builtin VST support, ignore the VST bridge as it - // causes duplicate menu entries to appear. - wxFileName f(fname); - if (f.GetName().CmpNoCase(wxT("vst-bridge")) == 0) { - return; - } - - // As a courtesy to some plug-ins that might be bridges to - // open other plug-ins, we set the current working - // directory to be the plug-in's directory. - - wxString saveOldCWD = ::wxGetCwd(); - wxString prefix = ::wxPathOnly(fname); - ::wxSetWorkingDirectory(prefix); - - wxDynamicLibrary* pDLL = new wxDynamicLibrary(); - dls.push_back(pDLL); - if (pDLL && pDLL->Load(fname, wxDL_LAZY)) { - mainFn = (LADSPA_Descriptor_Function)(pDLL->GetSymbol(wxT(descriptorFnName))); - } - - if (mainFn) { - int index = 0; - const LADSPA_Descriptor *data; - - data = mainFn(index); - while(data) { - - wxString uniqid = wxString::Format(wxT("%08x-%s"), (int)data->UniqueID, LAT1CTOWX(data->Label).c_str()); - if (uniq.Index(uniqid) == wxNOT_FOUND) { - uniq.Add(uniqid); - std::set categories; - -#if defined(USE_LIBLRDF) && defined(EFFECT_CATEGORIES) - std::multimap::const_iterator iter; - iter = gPluginCategories.lower_bound(data->UniqueID); - for ( ; (iter != gPluginCategories.end() && - iter->first == data->UniqueID); ++iter) - categories.insert(iter->second); -#endif - - LadspaEffect *effect = new LadspaEffect(data, categories); - EffectManager::Get().RegisterEffect(effect); - } - - // Get next plugin - index++; - data = mainFn(index); - } - } - - ::wxSetWorkingDirectory(saveOldCWD); -} - -void LoadLadspaPlugins() -{ - wxArrayString audacityPathList = wxGetApp().audacityPathList; - wxArrayString pathList; - wxArrayString files; - wxSortedArrayString uniq; - wxString pathVar; - unsigned int i; - -#if defined(USE_LIBLRDF) && defined(EFFECT_CATEGORIES) - - EffectManager& em = EffectManager::Get(); - wxArrayString rdfPathList; - wxString rdfPathVar; - wxArrayString rdfFiles; - - InitCategoryMap(); - lrdf_init(); - - rdfPathVar = wxGetenv(wxT("LADSPA_RDF_PATH")); - if (rdfPathVar != wxT("")) - wxGetApp().AddMultiPathsToPathList(rdfPathVar, rdfPathList); - -#ifdef __WXGTK__ - wxGetApp().AddUniquePathToPathList(wxT("/usr/share/ladspa/rdf"), - rdfPathList); - wxGetApp().AddUniquePathToPathList(wxT("/usr/local/share/ladspa/rdf"), - rdfPathList); -#endif - -#ifdef __WXMAC__ - wxGetApp().AddUniquePathToPathList(wxT("/usr/share/ladspa/rdf"), - rdfPathList); - // XXX Maybe other Mac paths here? -#endif - -#ifdef __WXMSW__ - //wxGetApp().AddUniquePathToPathList(wxT("WINDOWS LRDF PATH"), - // rdfPathList); - // XXX Other Windows paths here. -#endif - - // Add the Audacity paths so we get ladspa.rdfs if we are using a local - // liblrdf - for(i=0; icount; ++i) { - char* label = lrdf_get_label(cats->items[i]); - if (!label) - continue; - wxString uri = MapCategoryUri(wxString::FromAscii(cats->items[i])); - em.AddCategory(uri, wxString::FromUTF8(label)); - std::free(label); - - lrdf_uris* plugs = lrdf_get_instances(cats->items[i]); - if (plugs) { - for (size_t j = 0; j < plugs->count; ++j) { - unsigned long uid = lrdf_get_uid(plugs->items[j]); - gPluginCategories.insert(std::make_pair(uid, uri)); - } - lrdf_free_uris(plugs); - } - } - - // And their relationships - for (size_t i = 0; i < cats->count; ++i) { - EffectCategory* p = - em.LookupCategory(MapCategoryUri(wxString::FromAscii(cats-> - items[i]))); - if (!p) - continue; - lrdf_uris* subs = lrdf_get_subclasses(cats->items[i]); - if (subs) { - for (size_t j = 0; j < subs->count; ++j) { - EffectCategory* c = - em.LookupCategory(MapCategoryUri(wxString::FromAscii(subs->items[j]))); - if (c) - em.AddCategoryParent(c, p); - } - lrdf_free_uris(subs); - } - } - - lrdf_free_uris(cats); - - } - -#endif - - pathVar = wxGetenv(wxT("LADSPA_PATH")); - if (pathVar != wxT("")) - wxGetApp().AddMultiPathsToPathList(pathVar, pathList); - - #ifdef __WXGTK__ - wxGetApp().AddUniquePathToPathList(wxT("~/.ladspa"), pathList); - wxGetApp().AddUniquePathToPathList(wxT("/usr/local/lib/ladspa"), pathList); - wxGetApp().AddUniquePathToPathList(wxT("/usr/lib/ladspa"), pathList); - wxGetApp().AddUniquePathToPathList(wxT(LIBDIR) wxT("/ladspa"), pathList); - #endif - - #ifdef __WXMAC__ - wxGetApp().AddUniquePathToPathList(wxT("~/Library/Audio/Plug-Ins/LADSPA"), pathList); - wxGetApp().AddUniquePathToPathList(wxT("/Library/Audio/Plug-Ins/LADSPA"), pathList); - #endif - - for(i=0; iAddPendingEvent(event); + GetEventHandler()->ProcessEvent(event); } void AButton::SetShift(bool shift) diff --git a/win/Projects/Audacity/Audacity.vcxproj b/win/Projects/Audacity/Audacity.vcxproj index 674fb937a..8b898d0c0 100755 --- a/win/Projects/Audacity/Audacity.vcxproj +++ b/win/Projects/Audacity/Audacity.vcxproj @@ -467,7 +467,6 @@ - @@ -741,7 +740,6 @@ - diff --git a/win/Projects/Audacity/Audacity.vcxproj.filters b/win/Projects/Audacity/Audacity.vcxproj.filters index d0a3c9642..75f4e13ef 100755 --- a/win/Projects/Audacity/Audacity.vcxproj.filters +++ b/win/Projects/Audacity/Audacity.vcxproj.filters @@ -729,9 +729,6 @@ src/effects/ladspa - - src/effects/ladspa - src/toolbars @@ -1526,9 +1523,6 @@ src/effects/ladspa - - src/effects/ladspa - src/toolbars