diff --git a/build/macosx/Juce.xcodeproj/project.pbxproj b/build/macosx/Juce.xcodeproj/project.pbxproj index e28fcfd084..238d856062 100644 --- a/build/macosx/Juce.xcodeproj/project.pbxproj +++ b/build/macosx/Juce.xcodeproj/project.pbxproj @@ -141,7 +141,6 @@ 84677D080917AB5F0086D5D9 /* jdpostct.c in Sources */ = {isa = PBXBuildFile; fileRef = 84677CD40917AB5F0086D5D9 /* jdpostct.c */; }; 84677D090917AB5F0086D5D9 /* jdsample.c in Sources */ = {isa = PBXBuildFile; fileRef = 84677CD50917AB5F0086D5D9 /* jdsample.c */; }; 84677D0A0917AB5F0086D5D9 /* jdtrans.c in Sources */ = {isa = PBXBuildFile; fileRef = 84677CD60917AB5F0086D5D9 /* jdtrans.c */; }; - 84677D0B0917AB5F0086D5D9 /* jerror.c in Sources */ = {isa = PBXBuildFile; fileRef = 84677CD70917AB5F0086D5D9 /* jerror.c */; }; 84677D0C0917AB5F0086D5D9 /* jfdctflt.c in Sources */ = {isa = PBXBuildFile; fileRef = 84677CD80917AB5F0086D5D9 /* jfdctflt.c */; }; 84677D0D0917AB5F0086D5D9 /* jfdctfst.c in Sources */ = {isa = PBXBuildFile; fileRef = 84677CD90917AB5F0086D5D9 /* jfdctfst.c */; }; 84677D0E0917AB5F0086D5D9 /* jfdctint.c in Sources */ = {isa = PBXBuildFile; fileRef = 84677CDA0917AB5F0086D5D9 /* jfdctint.c */; }; @@ -797,7 +796,6 @@ 84677CD40917AB5F0086D5D9 /* jdpostct.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = jdpostct.c; sourceTree = ""; }; 84677CD50917AB5F0086D5D9 /* jdsample.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = jdsample.c; sourceTree = ""; }; 84677CD60917AB5F0086D5D9 /* jdtrans.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = jdtrans.c; sourceTree = ""; }; - 84677CD70917AB5F0086D5D9 /* jerror.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = jerror.c; sourceTree = ""; }; 84677CD80917AB5F0086D5D9 /* jfdctflt.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = jfdctflt.c; sourceTree = ""; }; 84677CD90917AB5F0086D5D9 /* jfdctfst.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = jfdctfst.c; sourceTree = ""; }; 84677CDA0917AB5F0086D5D9 /* jfdctint.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = jfdctint.c; sourceTree = ""; }; @@ -1313,7 +1311,7 @@ 84FED3C80CAA96DA00003997 /* juce_FileDragAndDropTarget.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = juce_FileDragAndDropTarget.h; sourceTree = ""; }; 84FFAF290C6C8F2B009F6E72 /* juce_FileSearchPathListComponent.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_FileSearchPathListComponent.cpp; path = filebrowser/juce_FileSearchPathListComponent.cpp; sourceTree = ""; }; 84FFAF2A0C6C8F2B009F6E72 /* juce_FileSearchPathListComponent.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_FileSearchPathListComponent.h; path = filebrowser/juce_FileSearchPathListComponent.h; sourceTree = ""; }; - D2AAC046055464E500DB518D /* libjucedebug.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libjucedebug.a; sourceTree = BUILT_PRODUCTS_DIR; }; + D2AAC046055464E500DB518D /* libjuce.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libjuce.a; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -1353,7 +1351,7 @@ 1AB674ADFE9D54B511CA2CBB /* Products */ = { isa = PBXGroup; children = ( - D2AAC046055464E500DB518D /* libjucedebug.a */, + D2AAC046055464E500DB518D /* libjuce.a */, ); name = Products; sourceTree = ""; @@ -2069,7 +2067,6 @@ 84677CD40917AB5F0086D5D9 /* jdpostct.c */, 84677CD50917AB5F0086D5D9 /* jdsample.c */, 84677CD60917AB5F0086D5D9 /* jdtrans.c */, - 84677CD70917AB5F0086D5D9 /* jerror.c */, 84677CD80917AB5F0086D5D9 /* jfdctflt.c */, 84677CD90917AB5F0086D5D9 /* jfdctfst.c */, 84677CDA0917AB5F0086D5D9 /* jfdctint.c */, @@ -2790,7 +2787,7 @@ ); name = Juce; productName = Juce; - productReference = D2AAC046055464E500DB518D /* libjucedebug.a */; + productReference = D2AAC046055464E500DB518D /* libjuce.a */; productType = "com.apple.product-type.library.static"; }; /* End PBXNativeTarget section */ @@ -3037,7 +3034,6 @@ 84677D080917AB5F0086D5D9 /* jdpostct.c in Sources */, 84677D090917AB5F0086D5D9 /* jdsample.c in Sources */, 84677D0A0917AB5F0086D5D9 /* jdtrans.c in Sources */, - 84677D0B0917AB5F0086D5D9 /* jerror.c in Sources */, 84677D0C0917AB5F0086D5D9 /* jfdctflt.c in Sources */, 84677D0D0917AB5F0086D5D9 /* jfdctfst.c in Sources */, 84677D0E0917AB5F0086D5D9 /* jfdctint.c in Sources */, diff --git a/extras/audio plugin host/build/mac/PluginHost.xcodeproj/project.pbxproj b/extras/audio plugin host/build/mac/PluginHost.xcodeproj/project.pbxproj index 5fbeda612f..a317d4e77b 100644 --- a/extras/audio plugin host/build/mac/PluginHost.xcodeproj/project.pbxproj +++ b/extras/audio plugin host/build/mac/PluginHost.xcodeproj/project.pbxproj @@ -7,7 +7,10 @@ objects = { /* Begin PBXBuildFile section */ + 840A4D4A0CD774A000445927 /* juce_AudioUnitPluginFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840A4D460CD774A000445927 /* juce_AudioUnitPluginFormat.cpp */; }; + 840A4D4B0CD774A000445927 /* juce_VSTPluginFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840A4D480CD774A000445927 /* juce_VSTPluginFormat.cpp */; }; 8411682E0CBBEE0500232E45 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8411682D0CBBEE0500232E45 /* OpenGL.framework */; }; + 84CF14390CD6367800A8D756 /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84CF14380CD6367800A8D756 /* AudioUnit.framework */; }; 84FFAEAC0C6C8A6F009F6E72 /* FilterGraph.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84FFAE920C6C8A6F009F6E72 /* FilterGraph.cpp */; }; 84FFAEAD0C6C8A6F009F6E72 /* GraphEditorPanel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84FFAE940C6C8A6F009F6E72 /* GraphEditorPanel.cpp */; }; 84FFAEAE0C6C8A6F009F6E72 /* InternalFilters.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84FFAE960C6C8A6F009F6E72 /* InternalFilters.cpp */; }; @@ -19,8 +22,7 @@ 84FFAEB40C6C8A6F009F6E72 /* juce_PluginDescription.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84FFAEA20C6C8A6F009F6E72 /* juce_PluginDescription.cpp */; }; 84FFAEB50C6C8A6F009F6E72 /* juce_PluginDirectoryScanner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84FFAEA40C6C8A6F009F6E72 /* juce_PluginDirectoryScanner.cpp */; }; 84FFAEB60C6C8A6F009F6E72 /* juce_PluginListComponent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84FFAEA60C6C8A6F009F6E72 /* juce_PluginListComponent.cpp */; }; - 84FFAEB70C6C8A6F009F6E72 /* juce_VSTPluginInstance.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84FFAEAA0C6C8A6F009F6E72 /* juce_VSTPluginInstance.cpp */; }; - 84FFAEFE0C6C8E80009F6E72 /* libjucedebug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 84FFAEFC0C6C8E76009F6E72 /* libjucedebug.a */; }; + 84FFAEFE0C6C8E80009F6E72 /* libjuce.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 84FFAEFC0C6C8E76009F6E72 /* libjuce.a */; }; 84FFAF040C6C8ED5009F6E72 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84FFAEFF0C6C8ED5009F6E72 /* CoreAudio.framework */; }; 84FFAF050C6C8ED5009F6E72 /* CoreMIDI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84FFAF000C6C8ED5009F6E72 /* CoreMIDI.framework */; }; 84FFAF060C6C8ED5009F6E72 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84FFAF010C6C8ED5009F6E72 /* IOKit.framework */; }; @@ -44,7 +46,12 @@ 4A9504C8FFE6A3BC11CA0CBA /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = /System/Library/Frameworks/ApplicationServices.framework; sourceTree = ""; }; 4A9504CAFFE6A41611CA0CBA /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = /System/Library/Frameworks/CoreServices.framework; sourceTree = ""; }; 508344B209E5C41E0093A071 /* Juce Plugin Host.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Juce Plugin Host.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 840A4D460CD774A000445927 /* juce_AudioUnitPluginFormat.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_AudioUnitPluginFormat.cpp; path = formats/juce_AudioUnitPluginFormat.cpp; sourceTree = ""; }; + 840A4D470CD774A000445927 /* juce_AudioUnitPluginFormat.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_AudioUnitPluginFormat.h; path = formats/juce_AudioUnitPluginFormat.h; sourceTree = ""; }; + 840A4D480CD774A000445927 /* juce_VSTPluginFormat.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_VSTPluginFormat.cpp; path = formats/juce_VSTPluginFormat.cpp; sourceTree = ""; }; + 840A4D490CD774A000445927 /* juce_VSTPluginFormat.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_VSTPluginFormat.h; path = formats/juce_VSTPluginFormat.h; sourceTree = ""; }; 8411682D0CBBEE0500232E45 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = /System/Library/Frameworks/OpenGL.framework; sourceTree = ""; }; + 84CF14380CD6367800A8D756 /* AudioUnit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioUnit.framework; path = /System/Library/Frameworks/AudioUnit.framework; sourceTree = ""; }; 84FFAE920C6C8A6F009F6E72 /* FilterGraph.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = FilterGraph.cpp; path = ../../src/host/FilterGraph.cpp; sourceTree = SOURCE_ROOT; }; 84FFAE930C6C8A6F009F6E72 /* FilterGraph.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = FilterGraph.h; path = ../../src/host/FilterGraph.h; sourceTree = SOURCE_ROOT; }; 84FFAE940C6C8A6F009F6E72 /* GraphEditorPanel.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = GraphEditorPanel.cpp; path = ../../src/host/GraphEditorPanel.cpp; sourceTree = SOURCE_ROOT; }; @@ -66,9 +73,6 @@ 84FFAEA50C6C8A6F009F6E72 /* juce_PluginDirectoryScanner.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_PluginDirectoryScanner.h; path = ../../src/plugins/juce_PluginDirectoryScanner.h; sourceTree = SOURCE_ROOT; }; 84FFAEA60C6C8A6F009F6E72 /* juce_PluginListComponent.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_PluginListComponent.cpp; path = ../../src/plugins/juce_PluginListComponent.cpp; sourceTree = SOURCE_ROOT; }; 84FFAEA70C6C8A6F009F6E72 /* juce_PluginListComponent.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_PluginListComponent.h; path = ../../src/plugins/juce_PluginListComponent.h; sourceTree = SOURCE_ROOT; }; - 84FFAEA90C6C8A6F009F6E72 /* juce_VSTPluginFormat.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_VSTPluginFormat.h; path = ../../src/plugins/vst/juce_VSTPluginFormat.h; sourceTree = SOURCE_ROOT; }; - 84FFAEAA0C6C8A6F009F6E72 /* juce_VSTPluginInstance.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_VSTPluginInstance.cpp; path = ../../src/plugins/vst/juce_VSTPluginInstance.cpp; sourceTree = SOURCE_ROOT; }; - 84FFAEAB0C6C8A6F009F6E72 /* juce_VSTPluginInstance.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_VSTPluginInstance.h; path = ../../src/plugins/vst/juce_VSTPluginInstance.h; sourceTree = SOURCE_ROOT; }; 84FFAEF70C6C8E76009F6E72 /* Juce.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Juce.xcodeproj; path = ../../../../build/macosx/Juce.xcodeproj; sourceTree = SOURCE_ROOT; }; 84FFAEFF0C6C8ED5009F6E72 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = /System/Library/Frameworks/CoreAudio.framework; sourceTree = ""; }; 84FFAF000C6C8ED5009F6E72 /* CoreMIDI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMIDI.framework; path = /System/Library/Frameworks/CoreMIDI.framework; sourceTree = ""; }; @@ -83,7 +87,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 84FFAEFE0C6C8E80009F6E72 /* libjucedebug.a in Frameworks */, + 84FFAEFE0C6C8E80009F6E72 /* libjuce.a in Frameworks */, 8D0C4E920486CD37000505A6 /* Carbon.framework in Frameworks */, 84FFAF040C6C8ED5009F6E72 /* CoreAudio.framework in Frameworks */, 84FFAF050C6C8ED5009F6E72 /* CoreMIDI.framework in Frameworks */, @@ -91,6 +95,7 @@ 84FFAF080C6C8ED5009F6E72 /* QuickTime.framework in Frameworks */, 84FFAF150C6C8EE8009F6E72 /* AGL.framework in Frameworks */, 8411682E0CBBEE0500232E45 /* OpenGL.framework in Frameworks */, + 84CF14390CD6367800A8D756 /* AudioUnit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -137,6 +142,7 @@ 20286C32FDCF999611CA2CEA /* External Frameworks and Libraries */ = { isa = PBXGroup; children = ( + 84CF14380CD6367800A8D756 /* AudioUnit.framework */, 8411682D0CBBEE0500232E45 /* OpenGL.framework */, 84FFAF140C6C8EE8009F6E72 /* AGL.framework */, 84FFAEFF0C6C8ED5009F6E72 /* CoreAudio.framework */, @@ -151,6 +157,17 @@ name = "External Frameworks and Libraries"; sourceTree = ""; }; + 840A4D420CD7747400445927 /* formats */ = { + isa = PBXGroup; + children = ( + 840A4D460CD774A000445927 /* juce_AudioUnitPluginFormat.cpp */, + 840A4D470CD774A000445927 /* juce_AudioUnitPluginFormat.h */, + 840A4D480CD774A000445927 /* juce_VSTPluginFormat.cpp */, + 840A4D490CD774A000445927 /* juce_VSTPluginFormat.h */, + ); + name = formats; + sourceTree = ""; + }; 84FFAE910C6C8A6F009F6E72 /* host */ = { isa = PBXGroup; children = ( @@ -170,7 +187,7 @@ 84FFAE9B0C6C8A6F009F6E72 /* plugins */ = { isa = PBXGroup; children = ( - 84FFAEA80C6C8A6F009F6E72 /* vst */, + 840A4D420CD7747400445927 /* formats */, 84FFAE9C0C6C8A6F009F6E72 /* juce_AudioPluginFormat.cpp */, 84FFAE9D0C6C8A6F009F6E72 /* juce_AudioPluginFormat.h */, 84FFAE9E0C6C8A6F009F6E72 /* juce_AudioPluginInstance.cpp */, @@ -188,21 +205,10 @@ path = ../../src/plugins; sourceTree = SOURCE_ROOT; }; - 84FFAEA80C6C8A6F009F6E72 /* vst */ = { - isa = PBXGroup; - children = ( - 84FFAEA90C6C8A6F009F6E72 /* juce_VSTPluginFormat.h */, - 84FFAEAA0C6C8A6F009F6E72 /* juce_VSTPluginInstance.cpp */, - 84FFAEAB0C6C8A6F009F6E72 /* juce_VSTPluginInstance.h */, - ); - name = vst; - path = ../../src/plugins/vst; - sourceTree = SOURCE_ROOT; - }; 84FFAEF80C6C8E76009F6E72 /* Products */ = { isa = PBXGroup; children = ( - 84FFAEFC0C6C8E76009F6E72 /* libjucedebug.a */, + 84FFAEFC0C6C8E76009F6E72 /* libjuce.a */, ); name = Products; sourceTree = ""; @@ -250,10 +256,10 @@ /* End PBXProject section */ /* Begin PBXReferenceProxy section */ - 84FFAEFC0C6C8E76009F6E72 /* libjucedebug.a */ = { + 84FFAEFC0C6C8E76009F6E72 /* libjuce.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = libjucedebug.a; + path = libjuce.a; remoteRef = 84FFAEFB0C6C8E76009F6E72 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -285,7 +291,8 @@ 84FFAEB40C6C8A6F009F6E72 /* juce_PluginDescription.cpp in Sources */, 84FFAEB50C6C8A6F009F6E72 /* juce_PluginDirectoryScanner.cpp in Sources */, 84FFAEB60C6C8A6F009F6E72 /* juce_PluginListComponent.cpp in Sources */, - 84FFAEB70C6C8A6F009F6E72 /* juce_VSTPluginInstance.cpp in Sources */, + 840A4D4A0CD774A000445927 /* juce_AudioUnitPluginFormat.cpp in Sources */, + 840A4D4B0CD774A000445927 /* juce_VSTPluginFormat.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/extras/audio plugin host/build/win32/PluginHost.vcproj b/extras/audio plugin host/build/win32/PluginHost.vcproj index a3081568d1..49422cecb1 100644 --- a/extras/audio plugin host/build/win32/PluginHost.vcproj +++ b/extras/audio plugin host/build/win32/PluginHost.vcproj @@ -266,18 +266,22 @@ > + + diff --git a/extras/audio plugin host/src/host/FilterGraph.cpp b/extras/audio plugin host/src/host/FilterGraph.cpp index a7081d6e17..d40ec41486 100644 --- a/extras/audio plugin host/src/host/FilterGraph.cpp +++ b/extras/audio plugin host/src/host/FilterGraph.cpp @@ -420,14 +420,15 @@ void FilterGraph::addFilter (const PluginDescription* desc, double x, double y) void FilterGraph::removeFilter (const uint32 uid) { - FilterInGraph* const filter = getFilterForUID (uid); + disconnectFilter (uid); - if (filter != 0) + for (int i = filters.size(); --i >= 0;) { - disconnectFilter (uid); - - filters.removeObject (filter); - changed(); + if (filters.getUnchecked(i)->uid == uid) + { + filters.remove (i); + changed(); + } } } @@ -466,8 +467,8 @@ bool FilterGraph::isAnInputTo (const uint32 possibleInput, const uint32 possible return isAnInputTo (possibleInput, possibleDestination, filters.size() + 1); } -FilterConnection* FilterGraph::getConnectionBetween (uint32 sourceFilterUID, int sourceFilterChannel, - uint32 destFilterUID, int destFilterChannel) const throw() +const FilterConnection* FilterGraph::getConnectionBetween (uint32 sourceFilterUID, int sourceFilterChannel, + uint32 destFilterUID, int destFilterChannel) const throw() { for (int i = connections.size(); --i >= 0;) { diff --git a/extras/audio plugin host/src/host/FilterGraph.h b/extras/audio plugin host/src/host/FilterGraph.h index 63d116bd84..58c45f7b18 100644 --- a/extras/audio plugin host/src/host/FilterGraph.h +++ b/extras/audio plugin host/src/host/FilterGraph.h @@ -157,10 +157,10 @@ public: //============================================================================== int getNumConnections() const throw() { return connections.size(); } - FilterConnection* getConnection (const int index) const throw() { return connections [index]; } + const FilterConnection* getConnection (const int index) const throw() { return connections [index]; } - FilterConnection* getConnectionBetween (uint32 sourceFilterUID, int sourceFilterChannel, - uint32 destFilterUID, int destFilterChannel) const throw(); + const FilterConnection* getConnectionBetween (uint32 sourceFilterUID, int sourceFilterChannel, + uint32 destFilterUID, int destFilterChannel) const throw(); bool isAnInputTo (const uint32 possibleInput, const uint32 possibleDestination) const throw(); @@ -211,7 +211,7 @@ private: //============================================================================== /** - An object the + */ class FilterGraphPlayer : public AudioIODeviceCallback, public MidiInputCallback, diff --git a/extras/audio plugin host/src/host/GraphEditorPanel.cpp b/extras/audio plugin host/src/host/GraphEditorPanel.cpp index e39eeb14d9..bd18de39ee 100644 --- a/extras/audio plugin host/src/host/GraphEditorPanel.cpp +++ b/extras/audio plugin host/src/host/GraphEditorPanel.cpp @@ -47,7 +47,7 @@ public: index (index_), isInput (isInput_) { - FilterInGraph* const f = graph.getFilterForUID (filterID_); + const FilterInGraph* const f = graph.getFilterForUID (filterID_); if (f != 0) { @@ -185,7 +185,7 @@ public: } else if (r == 3 || r == 4) { - const FilterInGraph::Ptr f (graph.getFilterForUID (filterID)); + FilterInGraph* const f = graph.getFilterForUID (filterID); if (f != 0) f->showUI (r == 4); @@ -771,7 +771,7 @@ void GraphEditorPanel::updateComponents() for (i = graph.getNumConnections(); --i >= 0;) { - FilterConnection* const c = graph.getConnection (i); + const FilterConnection* const c = graph.getConnection (i); if (getComponentForConnection (*c) == 0) { diff --git a/extras/audio plugin host/src/plugins/formats/juce_AudioUnitPluginFormat.cpp b/extras/audio plugin host/src/plugins/formats/juce_AudioUnitPluginFormat.cpp new file mode 100644 index 0000000000..20859d9292 --- /dev/null +++ b/extras/audio plugin host/src/plugins/formats/juce_AudioUnitPluginFormat.cpp @@ -0,0 +1,1264 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#if ! (defined (LINUX) || defined (_WIN32)) + +#include +#include + +#include "../../../../../juce.h" +#include "juce_AudioUnitPluginFormat.h" +#include "../juce_PluginDescription.h" + +#if JUCE_PLUGINHOST_AU && JUCE_MAC + +BEGIN_JUCE_NAMESPACE + extern void juce_callAnyTimersSynchronously(); + extern bool juce_isHIViewCreatedByJuce (HIViewRef view); + extern bool juce_isWindowCreatedByJuce (WindowRef window); +END_JUCE_NAMESPACE + +// Change this to disable logging of various activities +#ifndef AU_LOGGING + #define AU_LOGGING 1 +#endif + +#if AU_LOGGING + #define log(a) Logger::writeToLog(a); +#else + #define log(a) +#endif + +static int insideCallback = 0; + +//============================================================================== +class AudioUnitPluginWindow; + +//============================================================================== +class AudioUnitPluginInstance : public AudioPluginInstance +{ +public: + //============================================================================== + ~AudioUnitPluginInstance(); + + //============================================================================== + // AudioPluginInstance methods: + + const String getName() const { return pluginName; } + const String getManufacturer() const { return manufacturer; } + const String getVersion() const { return version; } + bool isInstrument() const { return componentDesc.componentType == kAudioUnitType_MusicDevice; } + const String getCategory() const; + const String getFormatName() const { return "AudioUnit"; } + const File getFile() const { return file; } + int getUID() const { return file.hashCode(); } + bool acceptsMidi() const { return wantsMidiMessages; } + bool producesMidi() const { return false; } + + //============================================================================== + // AudioProcessor methods: + + void prepareToPlay (double sampleRate, int estimatedSamplesPerBlock); + void releaseResources(); + void processBlock (AudioSampleBuffer& buffer, + MidiBuffer& midiMessages); + + AudioProcessorEditor* createEditor(); + + const String getInputChannelName (const int index) const; + bool isInputChannelStereoPair (int index) const; + + const String getOutputChannelName (const int index) const; + bool isOutputChannelStereoPair (int index) const; + + //============================================================================== + int getNumParameters(); + float getParameter (int index); + void setParameter (int index, float newValue); + const String getParameterName (int index); + const String getParameterText (int index); + bool isParameterAutomatable (int index) const; + + //============================================================================== + int getNumPrograms(); + int getCurrentProgram(); + void setCurrentProgram (int index); + const String getProgramName (int index); + void changeProgramName (int index, const String& newName); + + //============================================================================== + void getStateInformation (MemoryBlock& destData); + void getCurrentProgramStateInformation (MemoryBlock& destData); + void setStateInformation (const void* data, int sizeInBytes); + void setCurrentProgramStateInformation (const void* data, int sizeInBytes); + + //============================================================================== + juce_UseDebuggingNewOperator + +private: + friend class AudioUnitPluginWindow; + friend class AudioUnitPluginFormat; + + ComponentDescription componentDesc; + String pluginName, manufacturer, version; + File file; + CriticalSection lock; + bool initialised, wantsMidiMessages, wasPlaying; + + AudioBufferList* outputBufferList; + AudioTimeStamp timeStamp; + AudioSampleBuffer* currentBuffer; + + AudioUnit audioUnit; + Array parameterIds; + + //============================================================================== + bool getComponentDescFromFile (const File& file); + void initialise(); + + //============================================================================== + OSStatus renderGetInput (AudioUnitRenderActionFlags* ioActionFlags, + const AudioTimeStamp* inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList* ioData) const; + + static OSStatus renderGetInputCallback (void* inRefCon, + AudioUnitRenderActionFlags* ioActionFlags, + const AudioTimeStamp* inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList* ioData) + { + return ((AudioUnitPluginInstance*) inRefCon) + ->renderGetInput (ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData); + } + + OSStatus getBeatAndTempo (Float64* outCurrentBeat, Float64* outCurrentTempo) const; + OSStatus getMusicalTimeLocation (UInt32* outDeltaSampleOffsetToNextBeat, Float32* outTimeSig_Numerator, + UInt32* outTimeSig_Denominator, Float64* outCurrentMeasureDownBeat) const; + OSStatus getTransportState (Boolean* outIsPlaying, Boolean* outTransportStateChanged, + Float64* outCurrentSampleInTimeLine, Boolean* outIsCycling, + Float64* outCycleStartBeat, Float64* outCycleEndBeat); + + static OSStatus getBeatAndTempoCallback (void* inHostUserData, Float64* outCurrentBeat, Float64* outCurrentTempo) + { + return ((AudioUnitPluginInstance*) inHostUserData)->getBeatAndTempo (outCurrentBeat, outCurrentTempo); + } + + static OSStatus getMusicalTimeLocationCallback (void* inHostUserData, UInt32* outDeltaSampleOffsetToNextBeat, + Float32* outTimeSig_Numerator, UInt32* outTimeSig_Denominator, + Float64* outCurrentMeasureDownBeat) + { + return ((AudioUnitPluginInstance*) inHostUserData) + ->getMusicalTimeLocation (outDeltaSampleOffsetToNextBeat, outTimeSig_Numerator, + outTimeSig_Denominator, outCurrentMeasureDownBeat); + } + + static OSStatus getTransportStateCallback (void* inHostUserData, Boolean* outIsPlaying, Boolean* outTransportStateChanged, + Float64* outCurrentSampleInTimeLine, Boolean* outIsCycling, + Float64* outCycleStartBeat, Float64* outCycleEndBeat) + { + return ((AudioUnitPluginInstance*) inHostUserData) + ->getTransportState (outIsPlaying, outTransportStateChanged, + outCurrentSampleInTimeLine, outIsCycling, + outCycleStartBeat, outCycleEndBeat); + } + + //============================================================================== + void getNumChannels (int& numIns, int& numOuts) + { + numIns = 0; + numOuts = 0; + + AUChannelInfo supportedChannels [128]; + UInt32 supportedChannelsSize = sizeof (supportedChannels); + + if (AudioUnitGetProperty (audioUnit, kAudioUnitProperty_SupportedNumChannels, kAudioUnitScope_Global, + 0, supportedChannels, &supportedChannelsSize) == noErr + && supportedChannelsSize > 0) + { + for (int i = 0; i < supportedChannelsSize / sizeof (AUChannelInfo); ++i) + { + numIns = jmax (numIns, supportedChannels[i].inChannels); + numOuts = jmax (numOuts, supportedChannels[i].outChannels); + } + } + else + { + // (this really means the plugin will take any number of ins/outs as long + // as they are the same) + numIns = numOuts = 2; + } + } + + //============================================================================== + AudioUnitPluginInstance (const File& file); +}; + +//============================================================================== +AudioUnitPluginInstance::AudioUnitPluginInstance (const File& file_) + : file (file_), + initialised (false), + wantsMidiMessages (false), + audioUnit (0), + outputBufferList (0), + currentBuffer (0) +{ + try + { + ++insideCallback; + + log (T("Opening AU: ") + file.getFullPathName()); + + if (getComponentDescFromFile (file)) + { + ComponentRecord* const comp = FindNextComponent (0, &componentDesc); + + if (comp != 0) + { + audioUnit = (AudioUnit) OpenComponent (comp); + + wantsMidiMessages = componentDesc.componentType == kAudioUnitType_MusicDevice + || componentDesc.componentType == kAudioUnitType_MusicEffect; + } + } + + --insideCallback; + } + catch (...) + { + --insideCallback; + } +} + +AudioUnitPluginInstance::~AudioUnitPluginInstance() +{ + { + const ScopedLock sl (lock); + + jassert (insideCallback == 0); + + if (audioUnit != 0) + { + AudioUnitUninitialize (audioUnit); + CloseComponent (audioUnit); + audioUnit = 0; + } + } + + juce_free (outputBufferList); +} + +bool AudioUnitPluginInstance::getComponentDescFromFile (const File& file) +{ + zerostruct (componentDesc); + + if (! file.hasFileExtension (T(".component"))) + return false; + + const String filename (file.getFullPathName()); + const char* const utf8 = filename.toUTF8(); + CFURLRef url = CFURLCreateFromFileSystemRepresentation (0, (const UInt8*) utf8, + strlen (utf8), file.isDirectory()); + if (url != 0) + { + CFBundleRef bundleRef = CFBundleCreate (kCFAllocatorDefault, url); + CFRelease (url); + + if (bundleRef != 0) + { + CFTypeRef name = CFBundleGetValueForInfoDictionaryKey (bundleRef, CFSTR("CFBundleName")); + + if (name != 0 && CFGetTypeID (name) == CFStringGetTypeID()) + pluginName = PlatformUtilities::cfStringToJuceString ((CFStringRef) name); + + if (pluginName.isEmpty()) + pluginName = file.getFileNameWithoutExtension(); + + CFTypeRef versionString = CFBundleGetValueForInfoDictionaryKey (bundleRef, CFSTR("CFBundleVersion")); + + if (versionString != 0 && CFGetTypeID (versionString) == CFStringGetTypeID()) + version = PlatformUtilities::cfStringToJuceString ((CFStringRef) versionString); + + CFTypeRef manuString = CFBundleGetValueForInfoDictionaryKey (bundleRef, CFSTR("CFBundleGetInfoString")); + + if (manuString != 0 && CFGetTypeID (manuString) == CFStringGetTypeID()) + manufacturer = PlatformUtilities::cfStringToJuceString ((CFStringRef) manuString); + + short resFileId = CFBundleOpenBundleResourceMap (bundleRef); + UseResFile (resFileId); + + for (int i = 1; i <= Count1Resources ('thng'); ++i) + { + Handle h = Get1IndResource ('thng', i); + + if (h != 0) + { + HLock (h); + const uint32* const types = (const uint32*) *h; + + if (types[0] == kAudioUnitType_MusicDevice + || types[0] == kAudioUnitType_MusicEffect + || types[0] == kAudioUnitType_Effect + || types[0] == kAudioUnitType_Generator + || types[0] == kAudioUnitType_Panner) + { + componentDesc.componentType = types[0]; + componentDesc.componentSubType = types[1]; + componentDesc.componentManufacturer = types[2]; + break; + } + + HUnlock (h); + ReleaseResource (h); + } + } + + CFBundleCloseBundleResourceMap (bundleRef, resFileId); + CFRelease (bundleRef); + } + } + + return componentDesc.componentType != 0 && componentDesc.componentSubType != 0; +} + +//============================================================================== +void AudioUnitPluginInstance::initialise() +{ + if (initialised || audioUnit == 0) + return; + + log (T("Initialising AU: ") + pluginName); + + parameterIds.clear(); + + { + UInt32 paramListSize = 0; + AudioUnitGetProperty (audioUnit, kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, + 0, 0, ¶mListSize); + + if (paramListSize > 0) + { + parameterIds.insertMultiple (0, 0, paramListSize / sizeof (int)); + + AudioUnitGetProperty (audioUnit, kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, + 0, ¶meterIds.getReference(0), ¶mListSize); + } + } + + { + AURenderCallbackStruct info; + zerostruct (info); + info.inputProcRefCon = this; + info.inputProc = renderGetInputCallback; + + AudioUnitSetProperty (audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, + 0, &info, sizeof (info)); + } + + { + HostCallbackInfo info; + zerostruct (info); + info.hostUserData = this; + info.beatAndTempoProc = getBeatAndTempoCallback; + info.musicalTimeLocationProc = getMusicalTimeLocationCallback; + info.transportStateProc = getTransportStateCallback; + + AudioUnitSetProperty (audioUnit, kAudioUnitProperty_HostCallbacks, kAudioUnitScope_Global, + 0, &info, sizeof (info)); + } + + int numIns, numOuts; + getNumChannels (numIns, numOuts); + setPlayConfigDetails (numIns, numOuts, 0, 0); + + initialised = AudioUnitInitialize (audioUnit) == noErr; + + setLatencySamples (0); +} + + +//============================================================================== +void AudioUnitPluginInstance::prepareToPlay (double sampleRate_, + int samplesPerBlockExpected) +{ + initialise(); + + if (initialised) + { + int numIns, numOuts; + getNumChannels (numIns, numOuts); + + setPlayConfigDetails (numIns, numOuts, sampleRate_, samplesPerBlockExpected); + + Float64 latencySecs = 0.0; + UInt32 latencySize = sizeof (latencySecs); + AudioUnitGetProperty (audioUnit, kAudioUnitProperty_Latency, kAudioUnitScope_Global, + 0, &latencySecs, &latencySize); + + setLatencySamples (roundDoubleToInt (latencySecs * sampleRate_)); + + AudioUnitReset (audioUnit, kAudioUnitScope_Input, 0); + AudioUnitReset (audioUnit, kAudioUnitScope_Output, 0); + AudioUnitReset (audioUnit, kAudioUnitScope_Global, 0); + + AudioStreamBasicDescription stream; + zerostruct (stream); + stream.mSampleRate = sampleRate_; + stream.mFormatID = kAudioFormatLinearPCM; + stream.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved; + stream.mFramesPerPacket = 1; + stream.mBytesPerPacket = 4; + stream.mBytesPerFrame = 4; + stream.mBitsPerChannel = 32; + stream.mChannelsPerFrame = numIns; + + OSStatus err = AudioUnitSetProperty (audioUnit, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Input, + 0, &stream, sizeof (stream)); + + stream.mChannelsPerFrame = numOuts; + + err = AudioUnitSetProperty (audioUnit, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Output, + 0, &stream, sizeof (stream)); + + juce_free (outputBufferList); + outputBufferList = (AudioBufferList*) juce_calloc (sizeof (AudioBufferList) + sizeof (AudioBuffer) * (numOuts + 1)); + outputBufferList->mNumberBuffers = numOuts; + + for (int i = numOuts; --i >= 0;) + outputBufferList->mBuffers[i].mNumberChannels = 1; + + zerostruct (timeStamp); + timeStamp.mSampleTime = 0; + timeStamp.mHostTime = AudioGetCurrentHostTime(); + timeStamp.mFlags = kAudioTimeStampSampleTimeValid | kAudioTimeStampHostTimeValid; + + currentBuffer = 0; + wasPlaying = false; + } +} + +void AudioUnitPluginInstance::releaseResources() +{ + if (initialised) + { + AudioUnitReset (audioUnit, kAudioUnitScope_Input, 0); + AudioUnitReset (audioUnit, kAudioUnitScope_Output, 0); + AudioUnitReset (audioUnit, kAudioUnitScope_Global, 0); + + juce_free (outputBufferList); + outputBufferList = 0; + currentBuffer = 0; + } +} + +OSStatus AudioUnitPluginInstance::renderGetInput (AudioUnitRenderActionFlags* ioActionFlags, + const AudioTimeStamp* inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList* ioData) const +{ + if (inBusNumber == 0 + && currentBuffer != 0) + { + jassert (inNumberFrames == currentBuffer->getNumSamples()); // if this ever happens, might need to add extra handling + + for (int i = 0; i < ioData->mNumberBuffers; ++i) + { + if (i < currentBuffer->getNumChannels()) + { + memcpy (ioData->mBuffers[i].mData, + currentBuffer->getSampleData (i, 0), + sizeof (float) * inNumberFrames); + } + else + { + zeromem (ioData->mBuffers[i].mData, sizeof (float) * inNumberFrames); + } + } + } + + return noErr; +} + +void AudioUnitPluginInstance::processBlock (AudioSampleBuffer& buffer, + MidiBuffer& midiMessages) +{ + const int numSamples = buffer.getNumSamples(); + + if (initialised) + { + AudioUnitRenderActionFlags flags = 0; + + timeStamp.mHostTime = AudioGetCurrentHostTime(); + + for (int i = getNumOutputChannels(); --i >= 0;) + { + outputBufferList->mBuffers[i].mDataByteSize = sizeof (float) * numSamples; + outputBufferList->mBuffers[i].mData = buffer.getSampleData (i, 0); + } + + currentBuffer = &buffer; + + if (wantsMidiMessages) + { + const uint8* midiEventData; + int midiEventSize, midiEventPosition; + MidiBuffer::Iterator i (midiMessages); + + while (i.getNextEvent (midiEventData, midiEventSize, midiEventPosition)) + { + if (midiEventSize <= 3) + MusicDeviceMIDIEvent (audioUnit, + midiEventData[0], midiEventData[1], midiEventData[2], + midiEventPosition); + else + MusicDeviceSysEx (audioUnit, midiEventData, midiEventSize); + } + + midiMessages.clear(); + } + + AudioUnitRender (audioUnit, &flags, &timeStamp, + 0, numSamples, outputBufferList); + + timeStamp.mSampleTime += numSamples; + } + else + { + // Not initialised, so just bypass.. + for (int i = getNumInputChannels(); i < getNumOutputChannels(); ++i) + buffer.clear (i, 0, buffer.getNumSamples()); + } +} + +//============================================================================== +OSStatus AudioUnitPluginInstance::getBeatAndTempo (Float64* outCurrentBeat, Float64* outCurrentTempo) const +{ + AudioPlayHead* const ph = getPlayHead(); + AudioPlayHead::CurrentPositionInfo result; + + if (ph != 0 && ph->getCurrentPosition (result)) + { + *outCurrentBeat = result.ppqPosition; + *outCurrentTempo = result.bpm; + } + else + { + *outCurrentBeat = 0; + *outCurrentTempo = 120.0; + } + + return noErr; +} + +OSStatus AudioUnitPluginInstance::getMusicalTimeLocation (UInt32* outDeltaSampleOffsetToNextBeat, + Float32* outTimeSig_Numerator, + UInt32* outTimeSig_Denominator, + Float64* outCurrentMeasureDownBeat) const +{ + AudioPlayHead* const ph = getPlayHead(); + AudioPlayHead::CurrentPositionInfo result; + + if (ph != 0 && ph->getCurrentPosition (result)) + { + *outTimeSig_Numerator = result.timeSigNumerator; + *outTimeSig_Denominator = result.timeSigDenominator; + + *outDeltaSampleOffsetToNextBeat = 0; //xxx + *outCurrentMeasureDownBeat = result.ppqPositionOfLastBarStart; //xxx wrong + } + else + { + *outDeltaSampleOffsetToNextBeat = 0; + *outTimeSig_Numerator = 4; + *outTimeSig_Denominator = 4; + *outCurrentMeasureDownBeat = 0; + } + + return noErr; +} + +OSStatus AudioUnitPluginInstance::getTransportState (Boolean* outIsPlaying, + Boolean* outTransportStateChanged, + Float64* outCurrentSampleInTimeLine, + Boolean* outIsCycling, + Float64* outCycleStartBeat, + Float64* outCycleEndBeat) +{ + AudioPlayHead* const ph = getPlayHead(); + AudioPlayHead::CurrentPositionInfo result; + + if (ph != 0 && ph->getCurrentPosition (result)) + { + *outIsPlaying = result.isPlaying; + *outTransportStateChanged = result.isPlaying != wasPlaying; + wasPlaying = result.isPlaying; + *outCurrentSampleInTimeLine = roundDoubleToInt (result.timeInSeconds * getSampleRate()); + *outIsCycling = false; + *outCycleStartBeat = 0; + *outCycleEndBeat = 0; + } + else + { + *outIsPlaying = false; + *outTransportStateChanged = false; + *outCurrentSampleInTimeLine = 0; + *outIsCycling = false; + *outCycleStartBeat = 0; + *outCycleEndBeat = 0; + } + + return noErr; +} + + +//============================================================================== +static VoidArray activeWindows; + +//============================================================================== +class AudioUnitPluginWindow : public AudioProcessorEditor, + public Timer +{ +public: + //============================================================================== + AudioUnitPluginWindow (AudioUnitPluginInstance& plugin_) + : AudioProcessorEditor (&plugin_), + plugin (plugin_), + isOpen (false), + pluginWantsKeys (false), + wasShowing (false), + recursiveResize (false), + viewComponent (0), + pluginViewRef (0) + { + movementWatcher = new CompMovementWatcher (this); + + activeWindows.add (this); + + setOpaque (true); + setVisible (true); + setSize (1, 1); + + ComponentDescription viewList [16]; + UInt32 viewListSize = sizeof (viewList); + AudioUnitGetProperty (plugin.audioUnit, kAudioUnitProperty_GetUIComponentList, kAudioUnitScope_Global, + 0, &viewList, &viewListSize); + + componentRecord = FindNextComponent (0, &viewList[0]); + } + + ~AudioUnitPluginWindow() + { + deleteAndZero (movementWatcher); + + closePluginWindow(); + + activeWindows.removeValue (this); + plugin.editorBeingDeleted (this); + } + + bool isValid() const throw() { return componentRecord != 0; } + + //============================================================================== + void componentMovedOrResized() + { + if (recursiveResize) + return; + + Component* const topComp = getTopLevelComponent(); + + if (topComp->getPeer() != 0) + { + int x = 0, y = 0; + relativePositionToOtherComponent (topComp, x, y); + + recursiveResize = true; + + if (pluginViewRef != 0) + { + HIRect r; + r.origin.x = (float) x; + r.origin.y = (float) y; + r.size.width = (float) getWidth(); + r.size.height = (float) getHeight(); + HIViewSetFrame (pluginViewRef, &r); + } + + recursiveResize = false; + } + } + + void componentVisibilityChanged() + { + const bool isShowingNow = isShowing(); + + if (wasShowing != isShowingNow) + { + wasShowing = isShowingNow; + + if (isShowingNow) + openPluginWindow(); + else + closePluginWindow(); + } + + componentMovedOrResized(); + } + + void componentPeerChanged() + { + closePluginWindow(); + openPluginWindow(); + } + + void timerCallback() + { + if (pluginViewRef != 0) + { + HIRect bounds; + HIViewGetBounds (pluginViewRef, &bounds); + const int w = jmax (32, (int) bounds.size.width); + const int h = jmax (32, (int) bounds.size.height); + + if (w != getWidth() || h != getHeight()) + { + setSize (w, h); + startTimer (50); + } + else + { + startTimer (jlimit (50, 500, getTimerInterval() + 20)); + } + } + } + + //============================================================================== + bool keyStateChanged() + { + return pluginWantsKeys; + } + + bool keyPressed (const KeyPress&) + { + return pluginWantsKeys; + } + + //============================================================================== + void paint (Graphics& g) + { + if (isOpen) + { + ComponentPeer* const peer = getPeer(); + + if (peer != 0) + { + peer->addMaskedRegion (getScreenX() - peer->getScreenX(), + getScreenY() - peer->getScreenY(), + getWidth(), getHeight()); + } + } + else + { + g.fillAll (Colours::black); + } + } + + //============================================================================== + void broughtToFront() + { + activeWindows.removeValue (this); + activeWindows.add (this); + } + + //============================================================================== + juce_UseDebuggingNewOperator + +private: + AudioUnitPluginInstance& plugin; + bool isOpen, wasShowing, recursiveResize; + bool pluginWantsKeys; + + ComponentRecord* componentRecord; + AudioUnitCarbonView viewComponent; + HIViewRef pluginViewRef; + + //============================================================================== + void openPluginWindow() + { + if (isOpen || getWindowHandle() == 0 || componentRecord == 0) + return; + + log (T("Opening AU GUI: ") + plugin.getName()); + isOpen = true; + + pluginWantsKeys = true; //xxx any way to find this out? Does it matter? + + viewComponent = (AudioUnitCarbonView) OpenComponent (componentRecord); + + if (viewComponent != 0) + { + Float32Point pos = { getScreenX() - getTopLevelComponent()->getScreenX(), + getScreenY() - getTopLevelComponent()->getScreenY() }; + Float32Point size = { 250, 200 }; + + AudioUnitCarbonViewCreate (viewComponent, + plugin.audioUnit, + (WindowRef) getWindowHandle(), + HIViewGetRoot ((WindowRef) getWindowHandle()), + &pos, &size, + (ControlRef*) &pluginViewRef); + } + + timerCallback(); // to set our comp to the right size + repaint(); + } + + //============================================================================== + void closePluginWindow() + { + stopTimer(); + + if (isOpen) + { + log (T("Closing AU GUI: ") + plugin.getName()); + isOpen = false; + + if (viewComponent != 0) + CloseComponent (viewComponent); + + pluginViewRef = 0; + } + } + + //============================================================================== + class CompMovementWatcher : public ComponentMovementWatcher + { + public: + CompMovementWatcher (AudioUnitPluginWindow* const owner_) + : ComponentMovementWatcher (owner_), + owner (owner_) + { + } + + //============================================================================== + void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/) + { + owner->componentMovedOrResized(); + } + + void componentPeerChanged() + { + owner->componentPeerChanged(); + } + + void componentVisibilityChanged (Component&) + { + owner->componentVisibilityChanged(); + } + + private: + AudioUnitPluginWindow* const owner; + }; + + CompMovementWatcher* movementWatcher; +}; + +//============================================================================== +AudioProcessorEditor* AudioUnitPluginInstance::createEditor() +{ + AudioUnitPluginWindow* w = new AudioUnitPluginWindow (*this); + + if (! w->isValid()) + deleteAndZero (w); + + return w; +} + + +//============================================================================== +const String AudioUnitPluginInstance::getCategory() const +{ + const char* result = 0; + + switch (componentDesc.componentType) + { + case kAudioUnitType_Effect: + case kAudioUnitType_MusicEffect: + result = "Effect"; + break; + case kAudioUnitType_MusicDevice: + result = "Synth"; + break; + case kAudioUnitType_Generator: + result = "Generator"; + break; + case kAudioUnitType_Panner: + result = "Panner"; + break; + default: + break; + } + + return result; +} + +//============================================================================== +int AudioUnitPluginInstance::getNumParameters() +{ + return parameterIds.size(); +} + +float AudioUnitPluginInstance::getParameter (int index) +{ + const ScopedLock sl (lock); + + Float32 value = 0.0f; + + if (audioUnit != 0 && ((unsigned int) index) < (unsigned int) parameterIds.size()) + { + AudioUnitGetParameter (audioUnit, + (UInt32) parameterIds.getUnchecked (index), + kAudioUnitScope_Global, 0, + &value); + } + + return value; +} + +void AudioUnitPluginInstance::setParameter (int index, float newValue) +{ + const ScopedLock sl (lock); + + if (audioUnit != 0 && ((unsigned int) index) < (unsigned int) parameterIds.size()) + { + AudioUnitSetParameter (audioUnit, + (UInt32) parameterIds.getUnchecked (index), + kAudioUnitScope_Global, 0, + newValue, 0); + } +} + +const String AudioUnitPluginInstance::getParameterName (int index) +{ + AudioUnitParameterInfo info; + zerostruct (info); + UInt32 sz = sizeof (info); + + String name; + + if (AudioUnitGetProperty (audioUnit, + kAudioUnitProperty_ParameterInfo, + kAudioUnitScope_Global, + parameterIds [index], &info, &sz) == noErr) + { + if ((info.flags & kAudioUnitParameterFlag_HasCFNameString) != 0) + name = PlatformUtilities::cfStringToJuceString (info.cfNameString); + else + name = String (info.name, sizeof (info.name)); + } + + return name; +} + +const String AudioUnitPluginInstance::getParameterText (int index) +{ + return String (getParameter (index)); +} + +bool AudioUnitPluginInstance::isParameterAutomatable (int index) const +{ + AudioUnitParameterInfo info; + UInt32 sz = sizeof (info); + + if (AudioUnitGetProperty (audioUnit, + kAudioUnitProperty_ParameterInfo, + kAudioUnitScope_Global, + parameterIds [index], &info, &sz) == noErr) + { + return (info.flags & kAudioUnitParameterFlag_NonRealTime) == 0; + } + + return true; +} + +//============================================================================== +int AudioUnitPluginInstance::getNumPrograms() +{ + CFArrayRef presets; + UInt32 sz = sizeof (CFArrayRef); + int num = 0; + + if (AudioUnitGetProperty (audioUnit, + kAudioUnitProperty_FactoryPresets, + kAudioUnitScope_Global, + 0, &presets, &sz) == noErr) + { + num = (int) CFArrayGetCount (presets); + CFRelease (presets); + } + + return num; +} + +int AudioUnitPluginInstance::getCurrentProgram() +{ + AUPreset current; + current.presetNumber = 0; + UInt32 sz = sizeof (AUPreset); + + AudioUnitGetProperty (audioUnit, + kAudioUnitProperty_FactoryPresets, + kAudioUnitScope_Global, + 0, ¤t, &sz); + + return current.presetNumber; +} + +void AudioUnitPluginInstance::setCurrentProgram (int newIndex) +{ + AUPreset current; + current.presetNumber = newIndex; + current.presetName = 0; + + AudioUnitSetProperty (audioUnit, + kAudioUnitProperty_FactoryPresets, + kAudioUnitScope_Global, + 0, ¤t, sizeof (AUPreset)); +} + +const String AudioUnitPluginInstance::getProgramName (int index) +{ + String s; + CFArrayRef presets; + UInt32 sz = sizeof (CFArrayRef); + + if (AudioUnitGetProperty (audioUnit, + kAudioUnitProperty_FactoryPresets, + kAudioUnitScope_Global, + 0, &presets, &sz) == noErr) + { + for (CFIndex i = 0; i < CFArrayGetCount (presets); ++i) + { + const AUPreset* p = (const AUPreset*) CFArrayGetValueAtIndex (presets, i); + + if (p != 0 && p->presetNumber == index) + { + s = PlatformUtilities::cfStringToJuceString (p->presetName); + break; + } + } + + CFRelease (presets); + } + + return s; +} + +void AudioUnitPluginInstance::changeProgramName (int index, const String& newName) +{ + jassertfalse // xxx not implemented! +} + +//============================================================================== +const String AudioUnitPluginInstance::getInputChannelName (const int index) const +{ + if (((unsigned int) index) < (unsigned int) getNumInputChannels()) + return T("Input ") + String (index + 1); + + return String::empty; +} + +bool AudioUnitPluginInstance::isInputChannelStereoPair (int index) const +{ + if (((unsigned int) index) >= (unsigned int) getNumInputChannels()) + return false; + + + return true; +} + +const String AudioUnitPluginInstance::getOutputChannelName (const int index) const +{ + if (((unsigned int) index) < (unsigned int) getNumOutputChannels()) + return T("Output ") + String (index + 1); + + return String::empty; +} + +bool AudioUnitPluginInstance::isOutputChannelStereoPair (int index) const +{ + if (((unsigned int) index) >= (unsigned int) getNumOutputChannels()) + return false; + + return true; +} + +//============================================================================== +void AudioUnitPluginInstance::getStateInformation (MemoryBlock& destData) +{ + getCurrentProgramStateInformation (destData); +} + +void AudioUnitPluginInstance::getCurrentProgramStateInformation (MemoryBlock& destData) +{ + CFPropertyListRef propertyList = 0; + UInt32 sz = sizeof (CFPropertyListRef); + + if (AudioUnitGetProperty (audioUnit, + kAudioUnitProperty_ClassInfo, + kAudioUnitScope_Global, + 0, &propertyList, &sz) == noErr) + { + CFWriteStreamRef stream = CFWriteStreamCreateWithAllocatedBuffers (kCFAllocatorDefault, kCFAllocatorDefault); + CFWriteStreamOpen (stream); + + CFIndex bytesWritten = CFPropertyListWriteToStream (propertyList, stream, kCFPropertyListBinaryFormat_v1_0, 0); + CFWriteStreamClose (stream); + + CFDataRef data = (CFDataRef) CFWriteStreamCopyProperty (stream, kCFStreamPropertyDataWritten); + + destData.setSize (bytesWritten); + destData.copyFrom (CFDataGetBytePtr (data), 0, destData.getSize()); + CFRelease (data); + + CFRelease (stream); + CFRelease (propertyList); + } +} + +void AudioUnitPluginInstance::setStateInformation (const void* data, int sizeInBytes) +{ + setCurrentProgramStateInformation (data, sizeInBytes); +} + +void AudioUnitPluginInstance::setCurrentProgramStateInformation (const void* data, int sizeInBytes) +{ + CFReadStreamRef stream = CFReadStreamCreateWithBytesNoCopy (kCFAllocatorDefault, + (const UInt8*) data, + sizeInBytes, + kCFAllocatorNull); + CFReadStreamOpen (stream); + + CFPropertyListFormat format = kCFPropertyListBinaryFormat_v1_0; + CFPropertyListRef propertyList = CFPropertyListCreateFromStream (kCFAllocatorDefault, + stream, + 0, + kCFPropertyListImmutable, + &format, + 0); + CFRelease (stream); + + if (propertyList != 0) + AudioUnitSetProperty (audioUnit, + kAudioUnitProperty_ClassInfo, + kAudioUnitScope_Global, + 0, &propertyList, sizeof (propertyList)); +} + +//============================================================================== +//============================================================================== +AudioUnitPluginFormat::AudioUnitPluginFormat() +{ +} + +AudioUnitPluginFormat::~AudioUnitPluginFormat() +{ +} + +void AudioUnitPluginFormat::findAllTypesForFile (OwnedArray & results, + const File& file) +{ + if (! fileMightContainThisPluginType (file)) + return; + + PluginDescription desc; + desc.file = file; + desc.uid = 0; + + AudioUnitPluginInstance* instance = dynamic_cast (createInstanceFromDescription (desc)); + + if (instance == 0) + return; + + try + { + desc.fillInFromInstance (*instance); + + results.add (new PluginDescription (desc)); + } + catch (...) + { + // crashed while loading... + } + + deleteAndZero (instance); +} + +AudioPluginInstance* AudioUnitPluginFormat::createInstanceFromDescription (const PluginDescription& desc) +{ + AudioUnitPluginInstance* result = 0; + + if (fileMightContainThisPluginType (desc.file)) + { + result = new AudioUnitPluginInstance (desc.file); + + if (result->audioUnit != 0) + { + result->initialise(); + } + else + { + deleteAndZero (result); + } + } + + return result; +} + +bool AudioUnitPluginFormat::fileMightContainThisPluginType (const File& f) +{ + return f.hasFileExtension (T(".component")) + && f.isDirectory(); +} + +const FileSearchPath AudioUnitPluginFormat::getDefaultLocationsToSearch() +{ + return FileSearchPath ("~/Library/Audio/Plug-Ins/Components;/Library/Audio/Plug-Ins/Components"); +} + +#endif +#endif \ No newline at end of file diff --git a/extras/audio plugin host/src/plugins/formats/juce_AudioUnitPluginFormat.h b/extras/audio plugin host/src/plugins/formats/juce_AudioUnitPluginFormat.h new file mode 100644 index 0000000000..c3f8817892 --- /dev/null +++ b/extras/audio plugin host/src/plugins/formats/juce_AudioUnitPluginFormat.h @@ -0,0 +1,63 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#ifndef __JUCE_VSTPLUGINFORMAT_JUCEHEADER__x +#define __JUCE_VSTPLUGINFORMAT_JUCEHEADER__x + +#include "../juce_AudioPluginFormat.h" + +#if JUCE_PLUGINHOST_AU && JUCE_MAC + +//============================================================================== +/** + Implements a plugin format manager for AudioUnits. +*/ +class AudioUnitPluginFormat : public AudioPluginFormat +{ +public: + //============================================================================== + AudioUnitPluginFormat(); + ~AudioUnitPluginFormat(); + + //============================================================================== + const String getName() const { return "AudioUnit"; } + void findAllTypesForFile (OwnedArray & results, const File& file); + AudioPluginInstance* createInstanceFromDescription (const PluginDescription& desc); + bool fileMightContainThisPluginType (const File& file); + const FileSearchPath getDefaultLocationsToSearch(); + + //============================================================================== + juce_UseDebuggingNewOperator +}; + +#endif + +#endif // __JUCE_VSTPLUGINFORMAT_JUCEHEADER__ diff --git a/extras/audio plugin host/src/plugins/formats/juce_DirectXPluginFormat.h b/extras/audio plugin host/src/plugins/formats/juce_DirectXPluginFormat.h new file mode 100644 index 0000000000..0a73e76f8a --- /dev/null +++ b/extras/audio plugin host/src/plugins/formats/juce_DirectXPluginFormat.h @@ -0,0 +1,67 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#ifndef __JUCE_VSTPLUGINFORMAT_JUCEHEADER__xy +#define __JUCE_VSTPLUGINFORMAT_JUCEHEADER__xy + +#include "../juce_AudioPluginFormat.h" + +#if JUCE_PLUGINHOST_DX && JUCE_WIN32 + + +// Sorry, this file is just a placeholder at the moment!... + + +//============================================================================== +/** + Implements a plugin format manager for DirectX plugins. +*/ +class DirectXPluginFormat : public AudioPluginFormat +{ +public: + //============================================================================== + DirectXPluginFormat(); + ~DirectXPluginFormat(); + + //============================================================================== + const String getName() const { return "DirectX"; } + void findAllTypesForFile (OwnedArray & results, const File& file); + AudioPluginInstance* createInstanceFromDescription (const PluginDescription& desc); + bool fileMightContainThisPluginType (const File& file); + const FileSearchPath getDefaultLocationsToSearch(); + + //============================================================================== + juce_UseDebuggingNewOperator +}; + +#endif + +#endif // __JUCE_VSTPLUGINFORMAT_JUCEHEADER__ diff --git a/extras/audio plugin host/src/plugins/formats/juce_LADSPAPluginFormat.h b/extras/audio plugin host/src/plugins/formats/juce_LADSPAPluginFormat.h new file mode 100644 index 0000000000..a5f1ad9389 --- /dev/null +++ b/extras/audio plugin host/src/plugins/formats/juce_LADSPAPluginFormat.h @@ -0,0 +1,67 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#ifndef __JUCE_VSTPLUGINFORMAT_JUCEHEADER__xyz +#define __JUCE_VSTPLUGINFORMAT_JUCEHEADER__xyz + +#include "../juce_AudioPluginFormat.h" + +#if JUCE_PLUGINHOST_LADSPA && JUCE_LINUX + + +// Sorry, this file is just a placeholder at the moment!... + + +//============================================================================== +/** + Implements a plugin format manager for DirectX plugins. +*/ +class LADSPAPluginFormat : public AudioPluginFormat +{ +public: + //============================================================================== + LADSPAPluginFormat(); + ~LADSPAPluginFormat(); + + //============================================================================== + const String getName() const { return "LADSPA"; } + void findAllTypesForFile (OwnedArray & results, const File& file); + AudioPluginInstance* createInstanceFromDescription (const PluginDescription& desc); + bool fileMightContainThisPluginType (const File& file); + const FileSearchPath getDefaultLocationsToSearch(); + + //============================================================================== + juce_UseDebuggingNewOperator +}; + +#endif + +#endif // __JUCE_VSTPLUGINFORMAT_JUCEHEADER__ diff --git a/extras/audio plugin host/src/plugins/vst/juce_VSTPluginInstance.cpp b/extras/audio plugin host/src/plugins/formats/juce_VSTPluginFormat.cpp similarity index 89% rename from extras/audio plugin host/src/plugins/vst/juce_VSTPluginInstance.cpp rename to extras/audio plugin host/src/plugins/formats/juce_VSTPluginFormat.cpp index 2a10501d57..4e7bd23b29 100644 --- a/extras/audio plugin host/src/plugins/vst/juce_VSTPluginInstance.cpp +++ b/extras/audio plugin host/src/plugins/formats/juce_VSTPluginFormat.cpp @@ -29,13 +29,19 @@ ============================================================================== */ +#ifndef JUCE_PLUGINHOST_VST // xxx temporary.. + #define JUCE_PLUGINHOST_VST 1 +#endif + +#if JUCE_PLUGINHOST_VST + #ifdef _WIN32 #define _WIN32_WINNT 0x500 #define STRICT #include #include #pragma warning (disable : 4312) -#elif defined LINUX +#elif defined (LINUX) #include #include #include @@ -45,19 +51,38 @@ #undef KeyPress #undef Drawable #undef Time - class VSTPluginWindow; #else #include #endif +//============================================================================== #include "../../../../../juce.h" -#include "juce_VSTPluginInstance.h" +#include "juce_VSTPluginFormat.h" +//============================================================================== +#undef PRAGMA_ALIGN_SUPPORTED +#define VST_FORCE_DEPRECATED 0 + +#ifdef _MSC_VER + #pragma warning (push) + #pragma warning (disable: 4996) +#endif + +/* Obviously you're going to need the Steinberg vstsdk2.4 folder in + your include path if you want to add VST support... +*/ +#include "pluginterfaces/vst2.x/aeffectx.h" + +#ifdef _MSC_VER + #pragma warning (pop) +#endif + +//============================================================================== #if JUCE_LINUX - #define Font JUCE_NAMESPACE::Font - #define KeyPress JUCE_NAMESPACE::KeyPress - #define Drawable JUCE_NAMESPACE::Drawable - #define Time JUCE_NAMESPACE::Time + #define Font JUCE_NAMESPACE::Font + #define KeyPress JUCE_NAMESPACE::KeyPress + #define Drawable JUCE_NAMESPACE::Drawable + #define Time JUCE_NAMESPACE::Time #endif #include "../juce_PluginDescription.h" @@ -71,10 +96,10 @@ BEGIN_JUCE_NAMESPACE extern void juce_callAnyTimersSynchronously(); END_JUCE_NAMESPACE + //============================================================================== const int fxbVersionNum = 1; -//============================================================================== struct fxProgram { long chunkMagic; // 'CcnK' @@ -157,7 +182,7 @@ static VstIntPtr VSTCALLBACK audioMaster (AEffect* effect, VstInt32 opcode, VstI static int shellUIDToCreate = 0; static int insideVSTCallback = 0; -static Array activeWindows; +class VSTPluginWindow; //============================================================================== // Change this to disable logging of various VST activities @@ -429,8 +454,9 @@ public: if (file.hasFileExtension (T(".vst"))) { - CFURLRef url = CFURLCreateFromFileSystemRepresentation (0, (const UInt8*) (const char*) filename, - filename.length(), file.isDirectory()); + const char* const utf8 = filename.toUTF8(); + CFURLRef url = CFURLCreateFromFileSystemRepresentation (0, (const UInt8*) utf8, + strlen (utf8), file.isDirectory()); if (url != 0) { @@ -630,6 +656,124 @@ public: }; +//============================================================================== +/** + An instance of a plugin, created by a VSTPluginFormat. + +*/ +class VSTPluginInstance : public AudioPluginInstance, + private Timer, + private AsyncUpdater +{ +public: + //============================================================================== + ~VSTPluginInstance(); + + //============================================================================== + // AudioPluginInstance methods: + + const String getName() const { return name; } + const String getManufacturer() const; + const String getVersion() const; + bool isInstrument() const { return effect != 0 && (effect->flags & effFlagsIsSynth) != 0; } + const String getCategory() const; + const String getFormatName() const { return "VST"; } + const File getFile() const { return module->file; } + int getUID() const; + bool acceptsMidi() const { return wantsMidiMessages; } + bool producesMidi() const { return dispatch (effCanDo, 0, 0, (void*) "sendVstMidiEvent", 0) > 0; } + + //============================================================================== + // AudioProcessor methods: + + void prepareToPlay (double sampleRate, int estimatedSamplesPerBlock); + void releaseResources(); + void processBlock (AudioSampleBuffer& buffer, + MidiBuffer& midiMessages); + + AudioProcessorEditor* createEditor(); + + const String getInputChannelName (const int index) const; + bool isInputChannelStereoPair (int index) const; + + const String getOutputChannelName (const int index) const; + bool isOutputChannelStereoPair (int index) const; + + //============================================================================== + int getNumParameters() { return effect != 0 ? effect->numParams : 0; } + float getParameter (int index); + void setParameter (int index, float newValue); + const String getParameterName (int index); + const String getParameterText (int index); + bool isParameterAutomatable (int index) const; + + //============================================================================== + int getNumPrograms() { return effect != 0 ? effect->numPrograms : 0; } + int getCurrentProgram() { return dispatch (effGetProgram, 0, 0, 0, 0); } + void setCurrentProgram (int index); + const String getProgramName (int index); + void changeProgramName (int index, const String& newName); + + //============================================================================== + void getStateInformation (MemoryBlock& destData); + void getCurrentProgramStateInformation (MemoryBlock& destData); + void setStateInformation (const void* data, int sizeInBytes); + void setCurrentProgramStateInformation (const void* data, int sizeInBytes); + + //============================================================================== + void timerCallback(); + void handleAsyncUpdate(); + VstIntPtr handleCallback (VstInt32 opcode, VstInt32 index, VstInt32 value, void *ptr, float opt); + + //============================================================================== + juce_UseDebuggingNewOperator + +private: + friend class VSTPluginWindow; + friend class VSTPluginFormat; + + AEffect* effect; + String name; + CriticalSection lock; + bool wantsMidiMessages, initialised, isPowerOn; + mutable StringArray programNames; + AudioSampleBuffer tempBuffer; + CriticalSection midiInLock; + MidiBuffer incomingMidi; + void* midiEventsToSend; + int numAllocatedMidiEvents; + VstTimeInfo vstHostTime; + float** channels; + + ReferenceCountedObjectPtr module; + + //============================================================================== + int dispatch (const int opcode, const int index, const int value, void* const ptr, float opt) const; + bool restoreProgramSettings (const fxProgram* const prog); + const String getCurrentProgramName(); + void setParamsInProgramBlock (fxProgram* const prog) throw(); + void updateStoredProgramNames(); + void initialise(); + void ensureMidiEventSize (int numEventsNeeded); + void freeMidiEvents(); + void handleMidiFromPlugin (const VstEvents* const events); + void createTempParameterStore (MemoryBlock& dest); + void restoreFromTempParameterStore (const MemoryBlock& mb); + const String getParameterLabel (int index) const; + + bool usesChunks() const throw() { return effect != 0 && (effect->flags & effFlagsProgramChunks) != 0; } + void getChunkData (MemoryBlock& mb, bool isPreset, int maxSizeMB) const; + void setChunkData (const char* data, int size, bool isPreset); + bool loadFromFXBFile (const void* data, int numBytes); + bool saveToFXBFile (MemoryBlock& dest, bool isFXB, int maxSizeMB); + + int getVersionNumber() const throw() { return effect != 0 ? effect->version : 0; } + bool hasEditor() const throw() { return effect != 0 && (effect->flags & effFlagsHasEditor) != 0; } + void setPower (const bool on); + + VSTPluginInstance (const ReferenceCountedObjectPtr & module); +}; + //============================================================================== VSTPluginInstance::VSTPluginInstance (const ReferenceCountedObjectPtr & module_) : effect (0), @@ -1030,6 +1174,9 @@ void VSTPluginInstance::handleMidiFromPlugin (const VstEvents* const events) } } +//============================================================================== +static Array activeWindows; + //============================================================================== class VSTPluginWindow : public AudioProcessorEditor, public Timer @@ -2281,11 +2428,6 @@ static VstIntPtr VSTCALLBACK audioMaster (AEffect* effect, VstInt32 opcode, VstI } //============================================================================== -const String VSTPluginInstance::getName() const -{ - return name; -} - const String VSTPluginInstance::getManufacturer() const { char buffer [kVstMaxVendorStrLen + 8]; @@ -2325,21 +2467,6 @@ const String VSTPluginInstance::getVersion() const return s; } -int VSTPluginInstance::getVersionNumber() const throw() -{ - return effect != 0 ? effect->version : 0; -} - -const String VSTPluginInstance::getFormatName() const -{ - return "VST"; -} - -const File VSTPluginInstance::getFile() const -{ - return module->file; -} - int VSTPluginInstance::getUID() const { int uid = effect != 0 ? effect->uniqueID : 0; @@ -2400,11 +2527,6 @@ const String VSTPluginInstance::getCategory() const } //============================================================================== -int VSTPluginInstance::getNumParameters() -{ - return effect != 0 ? effect->numParams : 0; -} - float VSTPluginInstance::getParameter (int index) { if (effect != 0 && ((unsigned int) index) < (unsigned int) effect->numParams) @@ -2517,16 +2639,6 @@ void VSTPluginInstance::restoreFromTempParameterStore (const MemoryBlock& m) } //============================================================================== -int VSTPluginInstance::getNumPrograms() -{ - return effect != 0 ? effect->numPrograms : 0; -} - -int VSTPluginInstance::getCurrentProgram() -{ - return dispatch (effGetProgram, 0, 0, 0, 0); -} - void VSTPluginInstance::setCurrentProgram (int newIndex) { if (getNumPrograms() > 0 && newIndex != getCurrentProgram()) @@ -2667,48 +2779,12 @@ bool VSTPluginInstance::isOutputChannelStereoPair (int index) const } //============================================================================== -bool VSTPluginInstance::acceptsMidi() const -{ - return wantsMidiMessages; -} - -bool VSTPluginInstance::producesMidi() const -{ - return dispatch (effCanDo, 0, 0, (void*) "sendVstMidiEvent", 0) > 0; -} - void VSTPluginInstance::setPower (const bool on) { dispatch (effMainsChanged, 0, on ? 1 : 0, 0, 0); isPowerOn = on; } -bool VSTPluginInstance::hasEditor() const throw() -{ - return effect != 0 && (effect->flags & effFlagsHasEditor) != 0; -} - -bool VSTPluginInstance::canMono() const throw() -{ - return effect != 0 && (effect->flags & effFlagsCanMono) != 0; -} - -bool VSTPluginInstance::isOffline() const throw() -{ - return dispatch (effCanDo, 0, 0, (void*) "offline", 0) > 0; -} - -bool VSTPluginInstance::isInstrument() const -{ - return effect != 0 && (effect->flags & effFlagsIsSynth) != 0; -} - -bool VSTPluginInstance::usesChunks() const throw() -{ - return effect != 0 && (effect->flags & effFlagsProgramChunks) != 0; -} - - //============================================================================== const int defaultMaxSizeMB = 64; @@ -2902,3 +2978,5 @@ const FileSearchPath VSTPluginFormat::getDefaultLocationsToSearch() return FileSearchPath ("/usr/lib/vst"); #endif } + +#endif diff --git a/extras/audio plugin host/src/plugins/vst/juce_VSTPluginFormat.h b/extras/audio plugin host/src/plugins/formats/juce_VSTPluginFormat.h similarity index 96% rename from extras/audio plugin host/src/plugins/vst/juce_VSTPluginFormat.h rename to extras/audio plugin host/src/plugins/formats/juce_VSTPluginFormat.h index 3a1692cb4b..42bb21d103 100644 --- a/extras/audio plugin host/src/plugins/vst/juce_VSTPluginFormat.h +++ b/extras/audio plugin host/src/plugins/formats/juce_VSTPluginFormat.h @@ -34,6 +34,8 @@ #include "../juce_AudioPluginFormat.h" +#if JUCE_PLUGINHOST_VST + //============================================================================== /** @@ -58,4 +60,5 @@ public: }; +#endif #endif // __JUCE_VSTPLUGINFORMAT_JUCEHEADER__ diff --git a/extras/audio plugin host/src/plugins/juce_AudioPluginFormat.cpp b/extras/audio plugin host/src/plugins/juce_AudioPluginFormat.cpp index f2001aeca6..e2dd538495 100644 --- a/extras/audio plugin host/src/plugins/juce_AudioPluginFormat.cpp +++ b/extras/audio plugin host/src/plugins/juce_AudioPluginFormat.cpp @@ -31,7 +31,11 @@ #include "../../../../juce.h" #include "juce_AudioPluginFormat.h" -#include "vst/juce_VSTPluginFormat.h" + +#include "formats/juce_VSTPluginFormat.h" +#include "formats/juce_AudioUnitPluginFormat.h" +#include "formats/juce_DirectXPluginFormat.h" +#include "formats/juce_LADSPAPluginFormat.h" //============================================================================== @@ -51,10 +55,40 @@ void AudioPluginFormatManager::addDefaultFormats() #ifdef JUCE_DEBUG // you should only call this method once! for (int i = formats.size(); --i >= 0;) + { + #if JUCE_PLUGINHOST_VST jassert (dynamic_cast (formats[i]) == 0); + #endif + + #if JUCE_PLUGINHOST_AU && JUCE_MAC + jassert (dynamic_cast (formats[i]) == 0); + #endif + + #if JUCE_PLUGINHOST_DX && JUCE_WIN32 + jassert (dynamic_cast (formats[i]) == 0); + #endif + + #if JUCE_PLUGINHOST_LADSPA && JUCE_LINUX + jassert (dynamic_cast (formats[i]) == 0); + #endif + } #endif +#if JUCE_PLUGINHOST_VST formats.add (new VSTPluginFormat()); +#endif + +#if JUCE_PLUGINHOST_AU && JUCE_MAC + formats.add (new AudioUnitPluginFormat()); +#endif + +#if JUCE_PLUGINHOST_DX && JUCE_WIN32 + formats.add (new DirectXPluginFormat()); +#endif + +#if JUCE_PLUGINHOST_LADSPA && JUCE_LINUX + formats.add (new LADSPAPluginFormat()); +#endif } int AudioPluginFormatManager::getNumFormats() throw() diff --git a/extras/audio plugin host/src/plugins/juce_AudioPluginFormat.h b/extras/audio plugin host/src/plugins/juce_AudioPluginFormat.h index b63292acf5..094eb1aada 100644 --- a/extras/audio plugin host/src/plugins/juce_AudioPluginFormat.h +++ b/extras/audio plugin host/src/plugins/juce_AudioPluginFormat.h @@ -35,6 +35,10 @@ #include "juce_AudioPluginInstance.h" class PluginDescription; +// XXX temporary place for these flags... +#define JUCE_PLUGINHOST_VST 1 +#define JUCE_PLUGINHOST_AU 1 + //============================================================================== /** diff --git a/extras/audio plugin host/src/plugins/vst/juce_VSTPluginInstance.h b/extras/audio plugin host/src/plugins/vst/juce_VSTPluginInstance.h deleted file mode 100644 index 19d32ea98b..0000000000 --- a/extras/audio plugin host/src/plugins/vst/juce_VSTPluginInstance.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - ============================================================================== - - This file is part of the JUCE library - "Jules' Utility Class Extensions" - Copyright 2004-7 by Raw Material Software ltd. - - ------------------------------------------------------------------------------ - - JUCE can be redistributed and/or modified under the terms of the - GNU General Public License, as published by the Free Software Foundation; - either version 2 of the License, or (at your option) any later version. - - JUCE is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with JUCE; if not, visit www.gnu.org/licenses or write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - ------------------------------------------------------------------------------ - - If you'd like to release a closed-source product which uses JUCE, commercial - licenses are also available: visit www.rawmaterialsoftware.com/juce for - more information. - - ============================================================================== -*/ - -#ifndef __JUCE_VSTPLUGININSTANCE_JUCEHEADER__ -#define __JUCE_VSTPLUGININSTANCE_JUCEHEADER__ - -#include "juce_VSTPluginFormat.h" - -#undef PRAGMA_ALIGN_SUPPORTED -#define VST_FORCE_DEPRECATED 0 - -#ifdef _MSC_VER - #pragma warning (push) - #pragma warning (disable: 4996) -#endif - -/* Obviously you're going to need the Steinberg vstsdk2.4 folder in - your include path. -*/ -#include "pluginterfaces/vst2.x/aeffectx.h" - -#ifdef _MSC_VER - #pragma warning (pop) -#endif - -class ModuleHandle; -struct fxProgram; - - -//============================================================================== -/** - An instance of a plugin, created by a VSTPluginFormat. - -*/ -class VSTPluginInstance : public AudioPluginInstance, - private Timer, - private AsyncUpdater -{ -public: - //============================================================================== - ~VSTPluginInstance(); - - //============================================================================== - // AudioPluginInstance methods: - - const String getName() const; - const String getManufacturer() const; - const String getVersion() const; - bool isInstrument() const; - const String getCategory() const; - const String getFormatName() const; - const File getFile() const; - int getUID() const; - bool acceptsMidi() const; - bool producesMidi() const; - - //============================================================================== - // AudioProcessor methods: - - void prepareToPlay (double sampleRate, int estimatedSamplesPerBlock); - void releaseResources(); - void processBlock (AudioSampleBuffer& buffer, - MidiBuffer& midiMessages); - - AudioProcessorEditor* createEditor(); - - const String getInputChannelName (const int index) const; - bool isInputChannelStereoPair (int index) const; - - const String getOutputChannelName (const int index) const; - bool isOutputChannelStereoPair (int index) const; - - //============================================================================== - int getNumParameters(); - float getParameter (int index); - void setParameter (int index, float newValue); - const String getParameterName (int index); - const String getParameterText (int index); - bool isParameterAutomatable (int index) const; - - //============================================================================== - int getNumPrograms(); - int getCurrentProgram(); - void setCurrentProgram (int index); - const String getProgramName (int index); - void changeProgramName (int index, const String& newName); - - //============================================================================== - void getStateInformation (MemoryBlock& destData); - void getCurrentProgramStateInformation (MemoryBlock& destData); - void setStateInformation (const void* data, int sizeInBytes); - void setCurrentProgramStateInformation (const void* data, int sizeInBytes); - - //============================================================================== - void timerCallback(); - void handleAsyncUpdate(); - VstIntPtr handleCallback (VstInt32 opcode, VstInt32 index, VstInt32 value, void *ptr, float opt); - - //============================================================================== - juce_UseDebuggingNewOperator - -private: - friend class VSTPluginWindow; - friend class VSTPluginFormat; - - AEffect* effect; - String name; - CriticalSection lock; - bool wantsMidiMessages, initialised, isPowerOn; - mutable StringArray programNames; - AudioSampleBuffer tempBuffer; - CriticalSection midiInLock; - MidiBuffer incomingMidi; - void* midiEventsToSend; - int numAllocatedMidiEvents; - VstTimeInfo vstHostTime; - float** channels; - - ReferenceCountedObjectPtr module; - - //============================================================================== - int dispatch (const int opcode, const int index, const int value, void* const ptr, float opt) const; - bool restoreProgramSettings (const fxProgram* const prog); - const String getCurrentProgramName(); - void setParamsInProgramBlock (fxProgram* const prog) throw(); - void updateStoredProgramNames(); - void initialise(); - void ensureMidiEventSize (int numEventsNeeded); - void freeMidiEvents(); - void handleMidiFromPlugin (const VstEvents* const events); - void createTempParameterStore (MemoryBlock& dest); - void restoreFromTempParameterStore (const MemoryBlock& mb); - const String getParameterLabel (int index) const; - - bool usesChunks() const throw(); - void getChunkData (MemoryBlock& mb, bool isPreset, int maxSizeMB) const; - void setChunkData (const char* data, int size, bool isPreset); - bool loadFromFXBFile (const void* data, int numBytes); - bool saveToFXBFile (MemoryBlock& dest, bool isFXB, int maxSizeMB); - - int getVersionNumber() const throw(); - bool hasEditor() const throw(); - bool canMono() const throw(); - bool isOffline() const throw(); - void setPower (const bool on); - - VSTPluginInstance (const ReferenceCountedObjectPtr & module); -}; - - - -#endif // __JUCE_VSTPLUGININSTANCE_JUCEHEADER__