mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
This commit is contained in:
parent
25448ad8b2
commit
1e5a9ad56e
54 changed files with 11665 additions and 2506 deletions
|
|
@ -321,6 +321,7 @@ OBJECTS := \
|
|||
$(OBJDIR)/juce_FileFilter.o \
|
||||
$(OBJDIR)/juce_FileListComponent.o \
|
||||
$(OBJDIR)/juce_FilenameComponent.o \
|
||||
$(OBJDIR)/juce_FileSearchPathListComponent.o \
|
||||
$(OBJDIR)/juce_FileTreeComponent.o \
|
||||
$(OBJDIR)/juce_ImagePreviewComponent.o \
|
||||
$(OBJDIR)/juce_WildcardFileFilter.o \
|
||||
|
|
@ -1859,6 +1860,11 @@ $(OBJDIR)/juce_FilenameComponent.o: ../../src/juce_appframework/gui/components/f
|
|||
@echo $(notdir $<)
|
||||
@$(CXX) $(CXXFLAGS) -o $@ -c $<
|
||||
|
||||
$(OBJDIR)/juce_FileSearchPathListComponent.o: ../../src/juce_appframework/gui/components/filebrowser/juce_FileSearchPathListComponent.cpp
|
||||
-@$(CMD_MKOBJDIR)
|
||||
@echo $(notdir $<)
|
||||
@$(CXX) $(CXXFLAGS) -o $@ -c $<
|
||||
|
||||
$(OBJDIR)/juce_FileTreeComponent.o: ../../src/juce_appframework/gui/components/filebrowser/juce_FileTreeComponent.cpp
|
||||
-@$(CMD_MKOBJDIR)
|
||||
@echo $(notdir $<)
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#include <X11/Xmd.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/cursorfont.h>
|
||||
#include <X11/extensions/scrnsaver.h>
|
||||
|
||||
#if JUCE_USE_XINERAMA
|
||||
/* If you're trying to use Xinerama, you'll need to install the "libxinerama-dev" package..
|
||||
|
|
@ -2564,14 +2565,20 @@ void Desktop::setMousePosition (int x, int y) throw()
|
|||
|
||||
|
||||
//==============================================================================
|
||||
static bool screenSaverAllowed = false;
|
||||
|
||||
void Desktop::setScreenSaverEnabled (const bool isEnabled) throw()
|
||||
{
|
||||
jassertfalse // anyone know how to do this??
|
||||
if (screenSaverAllowed != isEnabled)
|
||||
{
|
||||
screenSaverAllowed = isEnabled;
|
||||
XScreenSaverSuspend (display, ! isEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
bool Desktop::isScreenSaverEnabled() throw()
|
||||
{
|
||||
return true;
|
||||
return screenSaverAllowed;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -2897,6 +2904,14 @@ bool juce_makeOpenGLContextCurrent (void* context)
|
|||
return glXMakeCurrent (display, None, 0);
|
||||
}
|
||||
|
||||
bool juce_isActiveOpenGLContext (void* context) throw()
|
||||
{
|
||||
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;
|
||||
|
||||
jassert (oc != 0);
|
||||
return glXGetCurrentContext() == oc->renderContext;
|
||||
}
|
||||
|
||||
void juce_swapOpenGLBuffers (void* context)
|
||||
{
|
||||
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;
|
||||
|
|
|
|||
|
|
@ -646,6 +646,8 @@
|
|||
84FC31BB09B74A5C00B75141 /* juce_WildcardFileFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 84FC31A909B74A5C00B75141 /* juce_WildcardFileFilter.h */; };
|
||||
84FC31BE09B74A7700B75141 /* juce_BorderSize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84FC31BC09B74A7700B75141 /* juce_BorderSize.cpp */; };
|
||||
84FC31BF09B74A7700B75141 /* juce_BorderSize.h in Headers */ = {isa = PBXBuildFile; fileRef = 84FC31BD09B74A7700B75141 /* juce_BorderSize.h */; };
|
||||
84FFAF2B0C6C8F2B009F6E72 /* juce_FileSearchPathListComponent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84FFAF290C6C8F2B009F6E72 /* juce_FileSearchPathListComponent.cpp */; };
|
||||
84FFAF2C0C6C8F2B009F6E72 /* juce_FileSearchPathListComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 84FFAF2A0C6C8F2B009F6E72 /* juce_FileSearchPathListComponent.h */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
|
|
@ -1291,6 +1293,8 @@
|
|||
84FC31A909B74A5C00B75141 /* juce_WildcardFileFilter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_WildcardFileFilter.h; path = filebrowser/juce_WildcardFileFilter.h; sourceTree = "<group>"; };
|
||||
84FC31BC09B74A7700B75141 /* juce_BorderSize.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = juce_BorderSize.cpp; sourceTree = "<group>"; };
|
||||
84FC31BD09B74A7700B75141 /* juce_BorderSize.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = juce_BorderSize.h; sourceTree = "<group>"; };
|
||||
84FFAF290C6C8F2B009F6E72 /* juce_FileSearchPathListComponent.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_FileSearchPathListComponent.cpp; path = filebrowser/juce_FileSearchPathListComponent.cpp; sourceTree = "<group>"; };
|
||||
84FFAF2A0C6C8F2B009F6E72 /* juce_FileSearchPathListComponent.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_FileSearchPathListComponent.h; path = filebrowser/juce_FileSearchPathListComponent.h; sourceTree = "<group>"; };
|
||||
D2AAC046055464E500DB518D /* libjucedebug.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libjucedebug.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
|
|
@ -2416,6 +2420,8 @@
|
|||
84FC31A209B74A5C00B75141 /* juce_FileFilter.h */,
|
||||
84FC31A309B74A5C00B75141 /* juce_FileListComponent.cpp */,
|
||||
84FC31A409B74A5C00B75141 /* juce_FileListComponent.h */,
|
||||
84FFAF290C6C8F2B009F6E72 /* juce_FileSearchPathListComponent.cpp */,
|
||||
84FFAF2A0C6C8F2B009F6E72 /* juce_FileSearchPathListComponent.h */,
|
||||
847F72D90C2702A000CBECEC /* juce_FileTreeComponent.cpp */,
|
||||
847F72DA0C2702A000CBECEC /* juce_FileTreeComponent.h */,
|
||||
84F1F05B0A36CE96008CCC5E /* juce_FilenameComponent.cpp */,
|
||||
|
|
@ -2722,6 +2728,7 @@
|
|||
84F6B7550C06E29D00BB8791 /* juce_ChannelRemappingAudioSource.h in Headers */,
|
||||
847F72DC0C2702A000CBECEC /* juce_DirectoryContentsDisplayComponent.h in Headers */,
|
||||
847F72DE0C2702A000CBECEC /* juce_FileTreeComponent.h in Headers */,
|
||||
84FFAF2C0C6C8F2B009F6E72 /* juce_FileSearchPathListComponent.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
@ -3118,6 +3125,7 @@
|
|||
847F72DB0C2702A000CBECEC /* juce_DirectoryContentsDisplayComponent.cpp in Sources */,
|
||||
847F72DD0C2702A000CBECEC /* juce_FileTreeComponent.cpp in Sources */,
|
||||
8406AA5A0C4BDF90003A0D6A /* juce_MidiOutput.cpp in Sources */,
|
||||
84FFAF2B0C6C8F2B009F6E72 /* juce_FileSearchPathListComponent.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1937,6 +1937,15 @@ bool juce_isHIViewCreatedByJuce (HIViewRef view)
|
|||
&& HIObjectIsOfClass ((HIObjectRef) view, juceHiViewClassNameCFString);
|
||||
}
|
||||
|
||||
bool juce_isWindowCreatedByJuce (WindowRef window)
|
||||
{
|
||||
for (int i = ComponentPeer::getNumPeers(); --i >= 0;)
|
||||
if (ComponentPeer::getPeer(i)->getNativeHandle() == window)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void trackNextMouseEvent()
|
||||
{
|
||||
UInt32 mods;
|
||||
|
|
@ -3350,6 +3359,14 @@ bool juce_makeOpenGLContextCurrent (void* context)
|
|||
return aglSetCurrentContext ((oc != 0) ? oc->renderContext : 0);
|
||||
}
|
||||
|
||||
bool juce_isActiveOpenGLContext (void* context) throw()
|
||||
{
|
||||
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;
|
||||
|
||||
jassert (oc != 0);
|
||||
return aglGetCurrentContext() == oc->renderContext;
|
||||
}
|
||||
|
||||
void juce_swapOpenGLBuffers (void* context)
|
||||
{
|
||||
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;
|
||||
|
|
|
|||
|
|
@ -3141,6 +3141,14 @@ bool juce_makeOpenGLContextCurrent (void* context)
|
|||
return wglMakeCurrent (0, 0) != 0;
|
||||
}
|
||||
|
||||
bool juce_isActiveOpenGLContext (void* context) throw()
|
||||
{
|
||||
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;
|
||||
|
||||
jassert (oc != 0);
|
||||
return wglGetCurrentContext() == oc->renderContext;
|
||||
}
|
||||
|
||||
void juce_swapOpenGLBuffers (void* context)
|
||||
{
|
||||
OpenGLContextInfo* const oc = (OpenGLContextInfo*) context;
|
||||
|
|
|
|||
|
|
@ -4145,6 +4145,14 @@
|
|||
RelativePath="..\..\..\src\juce_appframework\gui\components\filebrowser\juce_FilePreviewComponent.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\juce_appframework\gui\components\filebrowser\juce_FileSearchPathListComponent.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\juce_appframework\gui\components\filebrowser\juce_FileSearchPathListComponent.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\juce_appframework\gui\components\filebrowser\juce_FileTreeComponent.cpp"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,10 @@
|
|||
==============================================================================
|
||||
Changelist for version 1.45
|
||||
|
||||
-
|
||||
- big new project in the "extras" folder - a basic audio plugin host! Currently it loads VSTs on PC/Mac, and lets you put them together in a filter graph, which it plays. Hosting functionality is very basic at the moment, but I'm laying down a good architecture to hopefully build out into cross-platform plugin loading.
|
||||
- audio plugins: AudioFilterBase now requires a few extra methods to be implemented by your plugin: getInputChannelName, getOutputChannelName, isInputChannelStereoPair, isOutputChannelStereoPair.
|
||||
- new class: FileSearchPathListComponent, for letting the user edit a FileSearchPath.
|
||||
|
||||
|
||||
==============================================================================
|
||||
Changelist for version 1.44
|
||||
|
|
|
|||
26
extras/audio plugin host/build/mac/Info.plist
Normal file
26
extras/audio plugin host/build/mac/Info.plist
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string></string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.yourcompany.PluginHost</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>CSResourcesFileMapped</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -0,0 +1,371 @@
|
|||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 42;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
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 */; };
|
||||
84FFAEAF0C6C8A6F009F6E72 /* MainHostWindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84FFAE980C6C8A6F009F6E72 /* MainHostWindow.cpp */; };
|
||||
84FFAEB00C6C8A6F009F6E72 /* HostStartup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84FFAE9A0C6C8A6F009F6E72 /* HostStartup.cpp */; };
|
||||
84FFAEB10C6C8A6F009F6E72 /* juce_AudioPluginFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84FFAE9C0C6C8A6F009F6E72 /* juce_AudioPluginFormat.cpp */; };
|
||||
84FFAEB20C6C8A6F009F6E72 /* juce_AudioPluginInstance.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84FFAE9E0C6C8A6F009F6E72 /* juce_AudioPluginInstance.cpp */; };
|
||||
84FFAEB30C6C8A6F009F6E72 /* juce_KnownPluginList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84FFAEA00C6C8A6F009F6E72 /* juce_KnownPluginList.cpp */; };
|
||||
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 */; };
|
||||
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 */; };
|
||||
84FFAF080C6C8ED5009F6E72 /* QuickTime.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84FFAF030C6C8ED5009F6E72 /* QuickTime.framework */; };
|
||||
84FFAF150C6C8EE8009F6E72 /* AGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84FFAF140C6C8EE8009F6E72 /* AGL.framework */; };
|
||||
8D0C4E920486CD37000505A6 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 20286C33FDCF999611CA2CEA /* Carbon.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
84FFAEFB0C6C8E76009F6E72 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 84FFAEF70C6C8E76009F6E72 /* Juce.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = D2AAC046055464E500DB518D;
|
||||
remoteInfo = Juce;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
20286C33FDCF999611CA2CEA /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = "<absolute>"; };
|
||||
4A9504C8FFE6A3BC11CA0CBA /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = /System/Library/Frameworks/ApplicationServices.framework; sourceTree = "<absolute>"; };
|
||||
4A9504CAFFE6A41611CA0CBA /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = /System/Library/Frameworks/CoreServices.framework; sourceTree = "<absolute>"; };
|
||||
508344B209E5C41E0093A071 /* Juce Plugin Host.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Juce Plugin Host.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
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; };
|
||||
84FFAE950C6C8A6F009F6E72 /* GraphEditorPanel.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = GraphEditorPanel.h; path = ../../src/host/GraphEditorPanel.h; sourceTree = SOURCE_ROOT; };
|
||||
84FFAE960C6C8A6F009F6E72 /* InternalFilters.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = InternalFilters.cpp; path = ../../src/host/InternalFilters.cpp; sourceTree = SOURCE_ROOT; };
|
||||
84FFAE970C6C8A6F009F6E72 /* InternalFilters.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = InternalFilters.h; path = ../../src/host/InternalFilters.h; sourceTree = SOURCE_ROOT; };
|
||||
84FFAE980C6C8A6F009F6E72 /* MainHostWindow.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = MainHostWindow.cpp; path = ../../src/host/MainHostWindow.cpp; sourceTree = SOURCE_ROOT; };
|
||||
84FFAE990C6C8A6F009F6E72 /* MainHostWindow.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = MainHostWindow.h; path = ../../src/host/MainHostWindow.h; sourceTree = SOURCE_ROOT; };
|
||||
84FFAE9A0C6C8A6F009F6E72 /* HostStartup.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = HostStartup.cpp; path = ../../src/HostStartup.cpp; sourceTree = SOURCE_ROOT; };
|
||||
84FFAE9C0C6C8A6F009F6E72 /* juce_AudioPluginFormat.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_AudioPluginFormat.cpp; path = ../../src/plugins/juce_AudioPluginFormat.cpp; sourceTree = SOURCE_ROOT; };
|
||||
84FFAE9D0C6C8A6F009F6E72 /* juce_AudioPluginFormat.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_AudioPluginFormat.h; path = ../../src/plugins/juce_AudioPluginFormat.h; sourceTree = SOURCE_ROOT; };
|
||||
84FFAE9E0C6C8A6F009F6E72 /* juce_AudioPluginInstance.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_AudioPluginInstance.cpp; path = ../../src/plugins/juce_AudioPluginInstance.cpp; sourceTree = SOURCE_ROOT; };
|
||||
84FFAE9F0C6C8A6F009F6E72 /* juce_AudioPluginInstance.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_AudioPluginInstance.h; path = ../../src/plugins/juce_AudioPluginInstance.h; sourceTree = SOURCE_ROOT; };
|
||||
84FFAEA00C6C8A6F009F6E72 /* juce_KnownPluginList.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_KnownPluginList.cpp; path = ../../src/plugins/juce_KnownPluginList.cpp; sourceTree = SOURCE_ROOT; };
|
||||
84FFAEA10C6C8A6F009F6E72 /* juce_KnownPluginList.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_KnownPluginList.h; path = ../../src/plugins/juce_KnownPluginList.h; sourceTree = SOURCE_ROOT; };
|
||||
84FFAEA20C6C8A6F009F6E72 /* juce_PluginDescription.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_PluginDescription.cpp; path = ../../src/plugins/juce_PluginDescription.cpp; sourceTree = SOURCE_ROOT; };
|
||||
84FFAEA30C6C8A6F009F6E72 /* juce_PluginDescription.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce_PluginDescription.h; path = ../../src/plugins/juce_PluginDescription.h; sourceTree = SOURCE_ROOT; };
|
||||
84FFAEA40C6C8A6F009F6E72 /* juce_PluginDirectoryScanner.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = juce_PluginDirectoryScanner.cpp; path = ../../src/plugins/juce_PluginDirectoryScanner.cpp; sourceTree = SOURCE_ROOT; };
|
||||
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 = "<absolute>"; };
|
||||
84FFAF000C6C8ED5009F6E72 /* CoreMIDI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMIDI.framework; path = /System/Library/Frameworks/CoreMIDI.framework; sourceTree = "<absolute>"; };
|
||||
84FFAF010C6C8ED5009F6E72 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = /System/Library/Frameworks/IOKit.framework; sourceTree = "<absolute>"; };
|
||||
84FFAF030C6C8ED5009F6E72 /* QuickTime.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickTime.framework; path = /System/Library/Frameworks/QuickTime.framework; sourceTree = "<absolute>"; };
|
||||
84FFAF140C6C8EE8009F6E72 /* AGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AGL.framework; path = /System/Library/Frameworks/AGL.framework; sourceTree = "<absolute>"; };
|
||||
8D0C4E960486CD37000505A6 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
8D0C4E910486CD37000505A6 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
84FFAEFE0C6C8E80009F6E72 /* libjucedebug.a in Frameworks */,
|
||||
8D0C4E920486CD37000505A6 /* Carbon.framework in Frameworks */,
|
||||
84FFAF040C6C8ED5009F6E72 /* CoreAudio.framework in Frameworks */,
|
||||
84FFAF050C6C8ED5009F6E72 /* CoreMIDI.framework in Frameworks */,
|
||||
84FFAF060C6C8ED5009F6E72 /* IOKit.framework in Frameworks */,
|
||||
84FFAF080C6C8ED5009F6E72 /* QuickTime.framework in Frameworks */,
|
||||
84FFAF150C6C8EE8009F6E72 /* AGL.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
195DF8CFFE9D517E11CA2CBB /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
508344B209E5C41E0093A071 /* Juce Plugin Host.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
20286C29FDCF999611CA2CEA /* PluginHost */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
20286C2AFDCF999611CA2CEA /* Sources */,
|
||||
20286C2CFDCF999611CA2CEA /* Resources */,
|
||||
20286C32FDCF999611CA2CEA /* External Frameworks and Libraries */,
|
||||
195DF8CFFE9D517E11CA2CBB /* Products */,
|
||||
);
|
||||
name = PluginHost;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
20286C2AFDCF999611CA2CEA /* Sources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
84FFAE900C6C8A6F009F6E72 /* src */,
|
||||
);
|
||||
name = Sources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
20286C2CFDCF999611CA2CEA /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8D0C4E960486CD37000505A6 /* Info.plist */,
|
||||
);
|
||||
name = Resources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
20286C32FDCF999611CA2CEA /* External Frameworks and Libraries */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
84FFAF140C6C8EE8009F6E72 /* AGL.framework */,
|
||||
84FFAEFF0C6C8ED5009F6E72 /* CoreAudio.framework */,
|
||||
84FFAF000C6C8ED5009F6E72 /* CoreMIDI.framework */,
|
||||
84FFAF010C6C8ED5009F6E72 /* IOKit.framework */,
|
||||
84FFAF030C6C8ED5009F6E72 /* QuickTime.framework */,
|
||||
84FFAEF70C6C8E76009F6E72 /* Juce.xcodeproj */,
|
||||
20286C33FDCF999611CA2CEA /* Carbon.framework */,
|
||||
4A9504CAFFE6A41611CA0CBA /* CoreServices.framework */,
|
||||
4A9504C8FFE6A3BC11CA0CBA /* ApplicationServices.framework */,
|
||||
);
|
||||
name = "External Frameworks and Libraries";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
84FFAE900C6C8A6F009F6E72 /* src */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
84FFAE910C6C8A6F009F6E72 /* host */,
|
||||
84FFAE9A0C6C8A6F009F6E72 /* HostStartup.cpp */,
|
||||
84FFAE9B0C6C8A6F009F6E72 /* plugins */,
|
||||
);
|
||||
name = src;
|
||||
path = ../../src;
|
||||
sourceTree = SOURCE_ROOT;
|
||||
};
|
||||
84FFAE910C6C8A6F009F6E72 /* host */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
84FFAE920C6C8A6F009F6E72 /* FilterGraph.cpp */,
|
||||
84FFAE930C6C8A6F009F6E72 /* FilterGraph.h */,
|
||||
84FFAE940C6C8A6F009F6E72 /* GraphEditorPanel.cpp */,
|
||||
84FFAE950C6C8A6F009F6E72 /* GraphEditorPanel.h */,
|
||||
84FFAE960C6C8A6F009F6E72 /* InternalFilters.cpp */,
|
||||
84FFAE970C6C8A6F009F6E72 /* InternalFilters.h */,
|
||||
84FFAE980C6C8A6F009F6E72 /* MainHostWindow.cpp */,
|
||||
84FFAE990C6C8A6F009F6E72 /* MainHostWindow.h */,
|
||||
);
|
||||
name = host;
|
||||
path = ../../src/host;
|
||||
sourceTree = SOURCE_ROOT;
|
||||
};
|
||||
84FFAE9B0C6C8A6F009F6E72 /* plugins */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
84FFAE9C0C6C8A6F009F6E72 /* juce_AudioPluginFormat.cpp */,
|
||||
84FFAE9D0C6C8A6F009F6E72 /* juce_AudioPluginFormat.h */,
|
||||
84FFAE9E0C6C8A6F009F6E72 /* juce_AudioPluginInstance.cpp */,
|
||||
84FFAE9F0C6C8A6F009F6E72 /* juce_AudioPluginInstance.h */,
|
||||
84FFAEA00C6C8A6F009F6E72 /* juce_KnownPluginList.cpp */,
|
||||
84FFAEA10C6C8A6F009F6E72 /* juce_KnownPluginList.h */,
|
||||
84FFAEA20C6C8A6F009F6E72 /* juce_PluginDescription.cpp */,
|
||||
84FFAEA30C6C8A6F009F6E72 /* juce_PluginDescription.h */,
|
||||
84FFAEA40C6C8A6F009F6E72 /* juce_PluginDirectoryScanner.cpp */,
|
||||
84FFAEA50C6C8A6F009F6E72 /* juce_PluginDirectoryScanner.h */,
|
||||
84FFAEA60C6C8A6F009F6E72 /* juce_PluginListComponent.cpp */,
|
||||
84FFAEA70C6C8A6F009F6E72 /* juce_PluginListComponent.h */,
|
||||
84FFAEA80C6C8A6F009F6E72 /* vst */,
|
||||
);
|
||||
name = plugins;
|
||||
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 */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
8D0C4E890486CD37000505A6 /* PluginHost */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = C0E91AC508A95435008D54AB /* Build configuration list for PBXNativeTarget "PluginHost" */;
|
||||
buildPhases = (
|
||||
8D0C4E8C0486CD37000505A6 /* Resources */,
|
||||
8D0C4E8F0486CD37000505A6 /* Sources */,
|
||||
8D0C4E910486CD37000505A6 /* Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = PluginHost;
|
||||
productInstallPath = "$(HOME)/Applications";
|
||||
productName = PluginHost;
|
||||
productReference = 508344B209E5C41E0093A071 /* Juce Plugin Host.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
20286C28FDCF999611CA2CEA /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
buildConfigurationList = C0E91AC908A95435008D54AB /* Build configuration list for PBXProject "PluginHost" */;
|
||||
hasScannedForEncodings = 1;
|
||||
mainGroup = 20286C29FDCF999611CA2CEA /* PluginHost */;
|
||||
projectDirPath = "";
|
||||
projectReferences = (
|
||||
{
|
||||
ProductGroup = 84FFAEF80C6C8E76009F6E72 /* Products */;
|
||||
ProjectRef = 84FFAEF70C6C8E76009F6E72 /* Juce.xcodeproj */;
|
||||
},
|
||||
);
|
||||
targets = (
|
||||
8D0C4E890486CD37000505A6 /* PluginHost */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXReferenceProxy section */
|
||||
84FFAEFC0C6C8E76009F6E72 /* libjucedebug.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libjucedebug.a;
|
||||
remoteRef = 84FFAEFB0C6C8E76009F6E72 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
/* End PBXReferenceProxy section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
8D0C4E8C0486CD37000505A6 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
8D0C4E8F0486CD37000505A6 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
84FFAEAC0C6C8A6F009F6E72 /* FilterGraph.cpp in Sources */,
|
||||
84FFAEAD0C6C8A6F009F6E72 /* GraphEditorPanel.cpp in Sources */,
|
||||
84FFAEAE0C6C8A6F009F6E72 /* InternalFilters.cpp in Sources */,
|
||||
84FFAEAF0C6C8A6F009F6E72 /* MainHostWindow.cpp in Sources */,
|
||||
84FFAEB00C6C8A6F009F6E72 /* HostStartup.cpp in Sources */,
|
||||
84FFAEB10C6C8A6F009F6E72 /* juce_AudioPluginFormat.cpp in Sources */,
|
||||
84FFAEB20C6C8A6F009F6E72 /* juce_AudioPluginInstance.cpp in Sources */,
|
||||
84FFAEB30C6C8A6F009F6E72 /* juce_KnownPluginList.cpp in Sources */,
|
||||
84FFAEB40C6C8A6F009F6E72 /* juce_PluginDescription.cpp in Sources */,
|
||||
84FFAEB50C6C8A6F009F6E72 /* juce_PluginDirectoryScanner.cpp in Sources */,
|
||||
84FFAEB60C6C8A6F009F6E72 /* juce_PluginListComponent.cpp in Sources */,
|
||||
84FFAEB70C6C8A6F009F6E72 /* juce_VSTPluginInstance.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
C0E91AC608A95435008D54AB /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = ppc;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
C0E91AC708A95435008D54AB /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = ppc;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
INSTALL_PATH = "$(HOME)/Applications";
|
||||
PRESERVE_DEAD_CODE_INITS_AND_TERMS = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
C0E91ACA08A95435008D54AB /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = (
|
||||
ppc,
|
||||
i386,
|
||||
);
|
||||
GCC_ENABLE_FIX_AND_CONTINUE = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
PRODUCT_NAME = "Juce Plugin Host";
|
||||
USER_HEADER_SEARCH_PATHS = "~/stuff/vstsdk2.4 $(inherited)";
|
||||
ZERO_LINK = NO;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
C0E91ACB08A95435008D54AB /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = (
|
||||
ppc,
|
||||
i386,
|
||||
);
|
||||
PRODUCT_NAME = "Juce Plugin Host";
|
||||
SEPARATE_STRIP = YES;
|
||||
USER_HEADER_SEARCH_PATHS = "~/stuff/vstsdk2.4 $(inherited)";
|
||||
ZERO_LINK = NO;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
C0E91AC508A95435008D54AB /* Build configuration list for PBXNativeTarget "PluginHost" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
C0E91AC608A95435008D54AB /* Debug */,
|
||||
C0E91AC708A95435008D54AB /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
C0E91AC908A95435008D54AB /* Build configuration list for PBXProject "PluginHost" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
C0E91ACA08A95435008D54AB /* Debug */,
|
||||
C0E91ACB08A95435008D54AB /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 20286C28FDCF999611CA2CEA /* Project object */;
|
||||
}
|
||||
39
extras/audio plugin host/build/win32/PluginHost.sln
Normal file
39
extras/audio plugin host/build/win32/PluginHost.sln
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 9.00
|
||||
# Visual Studio 2005
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginHost", "PluginHost.vcproj", "{A20203D2-E1C3-48E3-89DD-401D5731DCC0}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{AE232C11-D91C-4CA1-B24E-8B11A52EFF26} = {AE232C11-D91C-4CA1-B24E-8B11A52EFF26}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JUCE", "..\..\..\..\build\win32\vc8\JUCE.vcproj", "{AE232C11-D91C-4CA1-B24E-8B11A52EFF26}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
DLL Debug|Win32 = DLL Debug|Win32
|
||||
DLL Release|Win32 = DLL Release|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{A20203D2-E1C3-48E3-89DD-401D5731DCC0}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{A20203D2-E1C3-48E3-89DD-401D5731DCC0}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{A20203D2-E1C3-48E3-89DD-401D5731DCC0}.DLL Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{A20203D2-E1C3-48E3-89DD-401D5731DCC0}.DLL Debug|Win32.Build.0 = Debug|Win32
|
||||
{A20203D2-E1C3-48E3-89DD-401D5731DCC0}.DLL Release|Win32.ActiveCfg = Release|Win32
|
||||
{A20203D2-E1C3-48E3-89DD-401D5731DCC0}.DLL Release|Win32.Build.0 = Release|Win32
|
||||
{A20203D2-E1C3-48E3-89DD-401D5731DCC0}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{A20203D2-E1C3-48E3-89DD-401D5731DCC0}.Release|Win32.Build.0 = Release|Win32
|
||||
{AE232C11-D91C-4CA1-B24E-8B11A52EFF26}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{AE232C11-D91C-4CA1-B24E-8B11A52EFF26}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{AE232C11-D91C-4CA1-B24E-8B11A52EFF26}.DLL Debug|Win32.ActiveCfg = DLL Debug|Win32
|
||||
{AE232C11-D91C-4CA1-B24E-8B11A52EFF26}.DLL Debug|Win32.Build.0 = DLL Debug|Win32
|
||||
{AE232C11-D91C-4CA1-B24E-8B11A52EFF26}.DLL Release|Win32.ActiveCfg = DLL Release|Win32
|
||||
{AE232C11-D91C-4CA1-B24E-8B11A52EFF26}.DLL Release|Win32.Build.0 = DLL Release|Win32
|
||||
{AE232C11-D91C-4CA1-B24E-8B11A52EFF26}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{AE232C11-D91C-4CA1-B24E-8B11A52EFF26}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
BIN
extras/audio plugin host/build/win32/PluginHost.suo
Normal file
BIN
extras/audio plugin host/build/win32/PluginHost.suo
Normal file
Binary file not shown.
295
extras/audio plugin host/build/win32/PluginHost.vcproj
Normal file
295
extras/audio plugin host/build/win32/PluginHost.vcproj
Normal file
|
|
@ -0,0 +1,295 @@
|
|||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Name="PluginHost"
|
||||
ProjectGUID="{A20203D2-E1C3-48E3-89DD-401D5731DCC0}"
|
||||
RootNamespace="PluginHost"
|
||||
Keyword="Win32Proj"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
|
||||
RuntimeLibrary="0"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="4"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\src\HostStartup.cpp"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="host"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\src\host\FilterGraph.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\host\FilterGraph.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\host\GraphEditorPanel.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\host\GraphEditorPanel.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\host\InternalFilters.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\host\InternalFilters.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\host\MainHostWindow.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\host\MainHostWindow.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="plugins"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\src\plugins\juce_AudioPluginFormat.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\plugins\juce_AudioPluginFormat.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\plugins\juce_AudioPluginInstance.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\plugins\juce_AudioPluginInstance.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\plugins\juce_KnownPluginList.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\plugins\juce_KnownPluginList.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\plugins\juce_PluginDescription.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\plugins\juce_PluginDescription.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\plugins\juce_PluginDirectoryScanner.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\plugins\juce_PluginDirectoryScanner.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\plugins\juce_PluginListComponent.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\plugins\juce_PluginListComponent.h"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="vst"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\src\plugins\vst\juce_VSTPluginFormat.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\plugins\vst\juce_VSTPluginInstance.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\plugins\vst\juce_VSTPluginInstance.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
110
extras/audio plugin host/src/HostStartup.cpp
Normal file
110
extras/audio plugin host/src/HostStartup.cpp
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
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.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../../juce.h"
|
||||
#include "host/MainHostWindow.h"
|
||||
#include "host/InternalFilters.h"
|
||||
|
||||
|
||||
ApplicationCommandManager* commandManager = 0;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class PluginHostApp : public JUCEApplication
|
||||
{
|
||||
MainHostWindow* mainWindow;
|
||||
|
||||
public:
|
||||
//==============================================================================
|
||||
PluginHostApp()
|
||||
: mainWindow (0)
|
||||
{
|
||||
}
|
||||
|
||||
~PluginHostApp()
|
||||
{
|
||||
}
|
||||
|
||||
void initialise (const String& /*commandLine*/)
|
||||
{
|
||||
// initialise our settings file..
|
||||
ApplicationProperties::getInstance()
|
||||
->setStorageParameters (T("Juce Audio Plugin Host"),
|
||||
T("settings"), String::empty, 1000,
|
||||
PropertiesFile::storeAsXML);
|
||||
|
||||
commandManager = new ApplicationCommandManager();
|
||||
|
||||
AudioPluginFormatManager::getInstance()->addDefaultFormats();
|
||||
AudioPluginFormatManager::getInstance()->addFormat (new InternalPluginFormat());
|
||||
|
||||
mainWindow = new MainHostWindow();
|
||||
|
||||
commandManager->registerAllCommandsForTarget (this);
|
||||
commandManager->registerAllCommandsForTarget (mainWindow);
|
||||
}
|
||||
|
||||
void shutdown()
|
||||
{
|
||||
deleteAndZero (mainWindow);
|
||||
|
||||
ApplicationProperties::getInstance()->closeFiles();
|
||||
|
||||
deleteAndZero (commandManager);
|
||||
}
|
||||
|
||||
const String getApplicationName()
|
||||
{
|
||||
return T("Juce Plug-In Host");
|
||||
}
|
||||
|
||||
const String getApplicationVersion()
|
||||
{
|
||||
return T("0.9");
|
||||
}
|
||||
|
||||
void systemRequestedQuit()
|
||||
{
|
||||
if (mainWindow->isValidComponent())
|
||||
mainWindow->tryToQuitApplication();
|
||||
else
|
||||
JUCEApplication::quit();
|
||||
}
|
||||
|
||||
bool moreThanOneInstanceAllowed()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// This kicks the whole thing off..
|
||||
START_JUCE_APPLICATION (PluginHostApp)
|
||||
744
extras/audio plugin host/src/host/FilterGraph.cpp
Normal file
744
extras/audio plugin host/src/host/FilterGraph.cpp
Normal file
|
|
@ -0,0 +1,744 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
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.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "FilterGraph.h"
|
||||
#include "InternalFilters.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
FilterConnection::FilterConnection (FilterGraph& owner_)
|
||||
: owner (owner_)
|
||||
{
|
||||
}
|
||||
|
||||
FilterConnection::FilterConnection (const FilterConnection& other)
|
||||
: sourceFilterID (other.sourceFilterID),
|
||||
sourceChannel (other.sourceChannel),
|
||||
destFilterID (other.destFilterID),
|
||||
destChannel (other.destChannel),
|
||||
owner (other.owner)
|
||||
{
|
||||
}
|
||||
|
||||
FilterConnection::~FilterConnection()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class PluginWindow : public DocumentWindow
|
||||
{
|
||||
public:
|
||||
PluginWindow (Component* const uiComp,
|
||||
FilterInGraph& owner_)
|
||||
: DocumentWindow (uiComp->getName(), Colours::lightblue,
|
||||
DocumentWindow::minimiseButton | DocumentWindow::closeButton),
|
||||
owner (owner_)
|
||||
{
|
||||
setSize (400, 300);
|
||||
|
||||
setContentComponent (uiComp, true, true);
|
||||
|
||||
setTopLeftPosition (owner.lastX, owner.lastY);
|
||||
setVisible (true);
|
||||
}
|
||||
|
||||
~PluginWindow()
|
||||
{
|
||||
setContentComponent (0);
|
||||
}
|
||||
|
||||
void moved()
|
||||
{
|
||||
owner.lastX = getX();
|
||||
owner.lastY = getY();
|
||||
}
|
||||
|
||||
void closeButtonPressed()
|
||||
{
|
||||
owner.activeUI = 0;
|
||||
delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
FilterInGraph& owner;
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
FilterInGraph::FilterInGraph (FilterGraph& owner_, AudioPluginInstance* const filter_)
|
||||
: owner (owner_),
|
||||
filter (filter_),
|
||||
uid (0),
|
||||
processedAudio (1, 1),
|
||||
inputAudio (1, 1),
|
||||
activeUI (0)
|
||||
{
|
||||
lastX = 100 + Random::getSystemRandom().nextInt (400);
|
||||
lastY = 100 + Random::getSystemRandom().nextInt (400);
|
||||
}
|
||||
|
||||
FilterInGraph::~FilterInGraph()
|
||||
{
|
||||
delete activeUI;
|
||||
delete filter;
|
||||
}
|
||||
|
||||
void FilterInGraph::setPosition (double newX, double newY) throw()
|
||||
{
|
||||
x = jlimit (0.0, 1.0, newX);
|
||||
y = jlimit (0.0, 1.0, newY);
|
||||
}
|
||||
|
||||
void FilterInGraph::showUI()
|
||||
{
|
||||
if (activeUI == 0)
|
||||
{
|
||||
Component* ui = filter->createEditorIfNeeded();
|
||||
|
||||
if (ui != 0)
|
||||
{
|
||||
ui->setName (filter->getName());
|
||||
activeUI = new PluginWindow (ui, *this);
|
||||
}
|
||||
}
|
||||
|
||||
if (activeUI != 0)
|
||||
activeUI->toFront (true);
|
||||
}
|
||||
|
||||
void FilterInGraph::prepareBuffers (int blockSize)
|
||||
{
|
||||
processedAudio.setSize (jmax (1, filter->getNumOutputChannels()), blockSize);
|
||||
inputAudio.setSize (jmax (1, filter->getNumInputChannels()), blockSize);
|
||||
processedAudio.clear();
|
||||
|
||||
processedMidi.clear();
|
||||
}
|
||||
|
||||
void FilterInGraph::renderBlock (int numSamples,
|
||||
const ReferenceCountedArray <FilterInGraph>& filters,
|
||||
const OwnedArray <FilterConnection>& connections)
|
||||
{
|
||||
processedAudio.setSize (jmax (1, filter->getNumOutputChannels()), numSamples);
|
||||
inputAudio.setSize (jmax (1, filter->getNumInputChannels()), numSamples);
|
||||
|
||||
// this isn't particularly efficient - could do with some optimising here
|
||||
inputAudio.clear();
|
||||
processedAudio.clear();
|
||||
processedMidi.clear();
|
||||
|
||||
for (int i = connections.size(); --i >= 0;)
|
||||
{
|
||||
const FilterConnection* const fc = connections.getUnchecked(i);
|
||||
|
||||
if (fc->destFilterID == uid)
|
||||
{
|
||||
for (int j = filters.size(); --j >= 0;)
|
||||
{
|
||||
const FilterInGraph* const input = filters.getUnchecked(j);
|
||||
|
||||
if (filters.getUnchecked(j)->uid == fc->sourceFilterID)
|
||||
{
|
||||
if (fc->sourceChannel == FilterGraph::midiChannelNumber)
|
||||
{
|
||||
processedMidi.addEvents (input->processedMidi, 0, numSamples, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
inputAudio.addFrom (fc->destChannel, 0, input->processedAudio,
|
||||
fc->sourceChannel, 0, numSamples);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
filter->processBlock (inputAudio, processedAudio, true, processedMidi);
|
||||
}
|
||||
|
||||
XmlElement* FilterInGraph::createXml() const
|
||||
{
|
||||
XmlElement* e = new XmlElement ("FILTER");
|
||||
e->setAttribute (T("uid"), (int) uid);
|
||||
e->setAttribute (T("x"), x);
|
||||
e->setAttribute (T("y"), y);
|
||||
e->setAttribute (T("uiLastX"), lastX);
|
||||
e->setAttribute (T("uiLastY"), lastY);
|
||||
|
||||
PluginDescription pd;
|
||||
pd.fillInFromInstance (*filter);
|
||||
e->addChildElement (pd.createXml());
|
||||
|
||||
XmlElement* state = new XmlElement ("STATE");
|
||||
|
||||
juce::MemoryBlock m;
|
||||
filter->getStateInformation (m);
|
||||
state->addTextElement (m.toBase64Encoding());
|
||||
e->addChildElement (state);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
FilterInGraph* FilterInGraph::createForDescription (FilterGraph& owner, const PluginDescription& desc)
|
||||
{
|
||||
AudioPluginInstance* instance = desc.createInstance();
|
||||
|
||||
if (instance != 0)
|
||||
return new FilterInGraph (owner, instance);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FilterInGraph* FilterInGraph::createFromXml (FilterGraph& owner, const XmlElement& xml)
|
||||
{
|
||||
PluginDescription pd;
|
||||
|
||||
forEachXmlChildElement (xml, e)
|
||||
{
|
||||
if (pd.loadFromXml (*e))
|
||||
break;
|
||||
}
|
||||
|
||||
FilterInGraph* const c = createForDescription (owner, pd);
|
||||
|
||||
if (c == 0)
|
||||
return 0;
|
||||
|
||||
const XmlElement* const state = xml.getChildByName (T("STATE"));
|
||||
|
||||
if (state != 0)
|
||||
{
|
||||
juce::MemoryBlock m;
|
||||
m.fromBase64Encoding (state->getAllSubText());
|
||||
|
||||
c->filter->setStateInformation (m.getData(), m.getSize());
|
||||
}
|
||||
|
||||
c->uid = xml.getIntAttribute (T("uid"));
|
||||
c->x = xml.getDoubleAttribute (T("x"));
|
||||
c->y = xml.getDoubleAttribute (T("y"));
|
||||
c->lastX = xml.getIntAttribute (T("uiLastX"), c->lastX);
|
||||
c->lastY = xml.getIntAttribute (T("uiLastY"), c->lastY);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
const int FilterGraph::midiChannelNumber = 0x1000;
|
||||
|
||||
FilterGraph::FilterGraph()
|
||||
: FileBasedDocument (filenameSuffix,
|
||||
filenameWildcard,
|
||||
"Load a filter graph",
|
||||
"Save a filter graph"),
|
||||
lastUID (0)
|
||||
{
|
||||
InternalPluginFormat internalFormat;
|
||||
|
||||
addFilter (internalFormat.getDescriptionFor (InternalPluginFormat::audioInputFilter),
|
||||
0.5f, 0.1f);
|
||||
|
||||
addFilter (internalFormat.getDescriptionFor (InternalPluginFormat::midiInputFilter),
|
||||
0.25f, 0.1f);
|
||||
|
||||
addFilter (internalFormat.getDescriptionFor (InternalPluginFormat::audioOutputFilter),
|
||||
0.5f, 0.9f);
|
||||
|
||||
setChangedFlag (false);
|
||||
}
|
||||
|
||||
FilterGraph::~FilterGraph()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
uint32 FilterGraph::getNextUID() throw()
|
||||
{
|
||||
return ++lastUID;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
const String FilterGraph::getDocumentTitle()
|
||||
{
|
||||
if (! getFile().exists())
|
||||
return "Unnamed";
|
||||
|
||||
return getFile().getFileNameWithoutExtension();
|
||||
}
|
||||
|
||||
const String FilterGraph::loadDocument (const File& file)
|
||||
{
|
||||
XmlDocument doc (file);
|
||||
XmlElement* xml = doc.getDocumentElement();
|
||||
|
||||
if (xml == 0 || ! xml->hasTagName (T("FILTERGRAPH")))
|
||||
{
|
||||
delete xml;
|
||||
return "Not a valid filter graph file";
|
||||
}
|
||||
|
||||
restoreFromXml (*xml);
|
||||
delete xml;
|
||||
|
||||
return String::empty;
|
||||
}
|
||||
|
||||
const String FilterGraph::saveDocument (const File& file)
|
||||
{
|
||||
XmlElement* xml = createXml();
|
||||
|
||||
String error;
|
||||
|
||||
if (! xml->writeToFile (file, String::empty))
|
||||
error = "Couldn't write to the file";
|
||||
|
||||
delete xml;
|
||||
return error;
|
||||
}
|
||||
|
||||
const File FilterGraph::getLastDocumentOpened()
|
||||
{
|
||||
RecentlyOpenedFilesList recentFiles;
|
||||
recentFiles.restoreFromString (ApplicationProperties::getInstance()->getUserSettings()
|
||||
->getValue ("recentFilterGraphFiles"));
|
||||
|
||||
return recentFiles.getFile (0);
|
||||
}
|
||||
|
||||
void FilterGraph::setLastDocumentOpened (const File& file)
|
||||
{
|
||||
RecentlyOpenedFilesList recentFiles;
|
||||
recentFiles.restoreFromString (ApplicationProperties::getInstance()->getUserSettings()
|
||||
->getValue ("recentFilterGraphFiles"));
|
||||
|
||||
recentFiles.addFile (file);
|
||||
|
||||
ApplicationProperties::getInstance()->getUserSettings()
|
||||
->setValue ("recentFilterGraphFiles", recentFiles.toString());
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
FilterInGraph* FilterGraph::getFilterForUID (const uint32 uid) const throw()
|
||||
{
|
||||
for (int i = filters.size(); --i >= 0;)
|
||||
if (filters.getUnchecked(i)->uid == uid)
|
||||
return filters.getUnchecked(i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FilterGraph::addFilter (const FilterInGraph::Ptr& newFilter)
|
||||
{
|
||||
if (newFilter->uid == 0)
|
||||
newFilter->uid = getNextUID();
|
||||
else if (newFilter->uid > lastUID)
|
||||
lastUID = newFilter->uid;
|
||||
|
||||
filters.add (newFilter);
|
||||
|
||||
changed();
|
||||
}
|
||||
|
||||
void FilterGraph::addFilter (const PluginDescription* desc, double x, double y)
|
||||
{
|
||||
if (desc != 0)
|
||||
{
|
||||
FilterInGraph* cf = FilterInGraph::createForDescription (*this, *desc);
|
||||
|
||||
if (cf != 0)
|
||||
{
|
||||
cf->setPosition (x, y);
|
||||
addFilter (cf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FilterGraph::removeFilter (const uint32 uid)
|
||||
{
|
||||
FilterInGraph* const filter = getFilterForUID (uid);
|
||||
|
||||
if (filter != 0)
|
||||
{
|
||||
disconnectFilter (uid);
|
||||
|
||||
filters.removeObject (filter);
|
||||
changed();
|
||||
}
|
||||
}
|
||||
|
||||
void FilterGraph::disconnectFilter (const uint32 uid)
|
||||
{
|
||||
for (int i = connections.size(); --i >= 0;)
|
||||
{
|
||||
const FilterConnection* const fc = connections.getUnchecked(i);
|
||||
|
||||
if (fc->sourceFilterID == uid
|
||||
|| fc->destFilterID == uid)
|
||||
{
|
||||
removeConnection (i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool FilterGraph::isAnInputTo (const uint32 possibleInput, const uint32 possibleDestination, int recursionCheck) const throw()
|
||||
{
|
||||
if (recursionCheck > 0)
|
||||
{
|
||||
for (int i = 0; i < connections.size(); ++i)
|
||||
{
|
||||
if (connections.getUnchecked(i)->destFilterID == possibleDestination
|
||||
&& (connections.getUnchecked(i)->sourceFilterID == possibleInput
|
||||
|| isAnInputTo (possibleInput, connections.getUnchecked(i)->sourceFilterID, recursionCheck - 1)))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FilterGraph::isAnInputTo (const uint32 possibleInput, const uint32 possibleDestination) const throw()
|
||||
{
|
||||
return isAnInputTo (possibleInput, possibleDestination, filters.size() + 1);
|
||||
}
|
||||
|
||||
FilterConnection* FilterGraph::getConnectionBetween (uint32 sourceFilterUID, int sourceFilterChannel,
|
||||
uint32 destFilterUID, int destFilterChannel) const throw()
|
||||
{
|
||||
for (int i = connections.size(); --i >= 0;)
|
||||
{
|
||||
FilterConnection* const fc = connections.getUnchecked(i);
|
||||
|
||||
if (fc->sourceFilterID == sourceFilterUID
|
||||
&& fc->sourceChannel == sourceFilterChannel
|
||||
&& fc->destFilterID == destFilterUID
|
||||
&& fc->destChannel == destFilterChannel)
|
||||
{
|
||||
return fc;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool FilterGraph::canConnect (uint32 sourceFilterUID, int sourceFilterChannel,
|
||||
uint32 destFilterUID, int destFilterChannel) const throw()
|
||||
{
|
||||
if (sourceFilterChannel < 0
|
||||
|| destFilterChannel < 0
|
||||
|| sourceFilterUID == destFilterUID
|
||||
|| (destFilterChannel == midiChannelNumber) != (sourceFilterChannel == midiChannelNumber))
|
||||
return false;
|
||||
|
||||
const FilterInGraph* const source = getFilterForUID (sourceFilterUID);
|
||||
|
||||
if (source == 0
|
||||
|| (sourceFilterChannel != midiChannelNumber && (sourceFilterChannel < 0 || sourceFilterChannel >= source->filter->getNumOutputChannels()))
|
||||
|| (sourceFilterChannel == midiChannelNumber && ! source->filter->producesMidi()))
|
||||
return false;
|
||||
|
||||
const FilterInGraph* const dest = getFilterForUID (destFilterUID);
|
||||
|
||||
if (dest == 0
|
||||
|| (destFilterChannel != midiChannelNumber && (destFilterChannel < 0 || destFilterChannel >= dest->filter->getNumInputChannels()))
|
||||
|| (destFilterChannel == midiChannelNumber && ! dest->filter->acceptsMidi()))
|
||||
return false;
|
||||
|
||||
if (getConnectionBetween (sourceFilterUID, sourceFilterChannel, destFilterUID, destFilterChannel) != 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FilterGraph::addConnection (uint32 sourceFilterUID, int sourceChannel,
|
||||
uint32 destFilterUID, int destChannel)
|
||||
{
|
||||
if (canConnect (sourceFilterUID, sourceChannel, destFilterUID, destChannel))
|
||||
{
|
||||
FilterConnection* const conn = new FilterConnection (*this);
|
||||
|
||||
conn->sourceFilterID = sourceFilterUID;
|
||||
conn->sourceChannel = sourceChannel;
|
||||
conn->destFilterID = destFilterUID;
|
||||
conn->destChannel = destChannel;
|
||||
|
||||
connections.add (conn);
|
||||
changed();
|
||||
}
|
||||
}
|
||||
|
||||
void FilterGraph::removeConnection (const int index)
|
||||
{
|
||||
if (connections [index] != 0)
|
||||
{
|
||||
connections.remove (index);
|
||||
changed();
|
||||
}
|
||||
}
|
||||
|
||||
void FilterGraph::removeConnection (uint32 sourceFilterUID, int sourceFilterChannel,
|
||||
uint32 destFilterUID, int destFilterChannel)
|
||||
{
|
||||
for (int i = connections.size(); --i >= 0;)
|
||||
{
|
||||
const FilterConnection* const fc = connections.getUnchecked(i);
|
||||
|
||||
if (fc->sourceFilterID == sourceFilterUID
|
||||
&& fc->sourceChannel == sourceFilterChannel
|
||||
&& fc->destFilterID == destFilterUID
|
||||
&& fc->destChannel == destFilterChannel)
|
||||
{
|
||||
removeConnection (i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FilterGraph::clear()
|
||||
{
|
||||
connections.clear();
|
||||
filters.clear();
|
||||
changed();
|
||||
}
|
||||
|
||||
XmlElement* FilterGraph::createXml() const
|
||||
{
|
||||
XmlElement* xml = new XmlElement ("FILTERGRAPH");
|
||||
|
||||
int i;
|
||||
for (i = 0; i < filters.size(); ++i)
|
||||
xml->addChildElement (filters.getUnchecked(i)->createXml());
|
||||
|
||||
for (i = 0; i < connections.size(); ++i)
|
||||
{
|
||||
const FilterConnection* const fc = connections.getUnchecked(i);
|
||||
|
||||
XmlElement* e = new XmlElement ("CONNECTION");
|
||||
|
||||
e->setAttribute (T("srcFilter"), (int) fc->sourceFilterID);
|
||||
e->setAttribute (T("srcChannel"), fc->sourceChannel);
|
||||
e->setAttribute (T("dstFilter"), (int) fc->destFilterID);
|
||||
e->setAttribute (T("dstChannel"), fc->destChannel);
|
||||
|
||||
xml->addChildElement (e);
|
||||
}
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
||||
void FilterGraph::restoreFromXml (const XmlElement& xml)
|
||||
{
|
||||
clear();
|
||||
|
||||
forEachXmlChildElementWithTagName (xml, e, T("FILTER"))
|
||||
{
|
||||
FilterInGraph* f = FilterInGraph::createFromXml (*this, *e);
|
||||
|
||||
if (f != 0)
|
||||
addFilter (f);
|
||||
}
|
||||
|
||||
forEachXmlChildElementWithTagName (xml, e, T("CONNECTION"))
|
||||
{
|
||||
addConnection ((uint32) e->getIntAttribute (T("srcFilter")),
|
||||
e->getIntAttribute (T("srcChannel")),
|
||||
(uint32) e->getIntAttribute (T("dstFilter")),
|
||||
e->getIntAttribute (T("dstChannel")));
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
FilterGraphPlayer::FilterGraphPlayer()
|
||||
: sampleRate (44100.0),
|
||||
blockSize (512),
|
||||
deviceManager (0),
|
||||
inputChannelData (0),
|
||||
totalNumInputChannels (0),
|
||||
outputChannelData (0),
|
||||
totalNumOutputChannels (0)
|
||||
{
|
||||
setAudioDeviceManager (0);
|
||||
keyState.addListener (&messageCollector);
|
||||
}
|
||||
|
||||
FilterGraphPlayer::~FilterGraphPlayer()
|
||||
{
|
||||
keyState.removeListener (&messageCollector);
|
||||
}
|
||||
|
||||
void FilterGraphPlayer::setAudioDeviceManager (AudioDeviceManager* dm)
|
||||
{
|
||||
if (deviceManager != 0)
|
||||
{
|
||||
deviceManager->removeMidiInputCallback (this);
|
||||
deviceManager->setAudioCallback (0);
|
||||
}
|
||||
|
||||
deviceManager = dm;
|
||||
|
||||
if (dm != 0)
|
||||
{
|
||||
dm->addMidiInputCallback (String::empty, this);
|
||||
dm->setAudioCallback (this);
|
||||
}
|
||||
}
|
||||
|
||||
int FilterGraphPlayer::compareElements (FilterInGraph* const first, FilterInGraph* const second) throw()
|
||||
{
|
||||
const bool firstIsInputToSecond = first->owner.isAnInputTo (first->uid, second->uid);
|
||||
const bool secondInInputToFirst = first->owner.isAnInputTo (second->uid, first->uid);
|
||||
|
||||
if (firstIsInputToSecond == secondInInputToFirst)
|
||||
return 0;
|
||||
|
||||
return firstIsInputToSecond ? -1 : 1;
|
||||
}
|
||||
|
||||
void FilterGraphPlayer::updateFrom (FilterGraph* graphToUse)
|
||||
{
|
||||
ReferenceCountedArray <FilterInGraph> filtersBeingRemoved (filters);
|
||||
|
||||
if (graphToUse != 0)
|
||||
{
|
||||
ReferenceCountedArray <FilterInGraph> newFilters (graphToUse->filters);
|
||||
int i;
|
||||
for (i = newFilters.size(); --i >= 0;)
|
||||
if (filters.contains (newFilters.getUnchecked(i)))
|
||||
newFilters.remove (i);
|
||||
|
||||
for (i = filtersBeingRemoved.size(); --i >= 0;)
|
||||
if (graphToUse->filters.contains (filtersBeingRemoved.getUnchecked(i)))
|
||||
filtersBeingRemoved.remove (i);
|
||||
|
||||
// prepare any new filters for use..
|
||||
for (i = 0; i < newFilters.size(); ++i)
|
||||
newFilters.getUnchecked(i)->filter->prepareToPlay (sampleRate, blockSize);
|
||||
|
||||
ReferenceCountedArray <FilterInGraph> sortedFilters (graphToUse->filters);
|
||||
sortedFilters.sort (*this, true);
|
||||
|
||||
for (i = sortedFilters.size(); --i >= 0;)
|
||||
{
|
||||
PlayerAwareFilter* const specialFilter = dynamic_cast <PlayerAwareFilter*> (sortedFilters.getUnchecked(i)->filter);
|
||||
|
||||
if (specialFilter != 0)
|
||||
specialFilter->setPlayer (this);
|
||||
}
|
||||
|
||||
{
|
||||
const ScopedLock sl (processLock);
|
||||
|
||||
filters = sortedFilters;
|
||||
connections.clear();
|
||||
|
||||
for (int i = 0; i < graphToUse->connections.size(); ++i)
|
||||
connections.add (new FilterConnection (*graphToUse->connections.getUnchecked(i)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const ScopedLock sl (processLock);
|
||||
|
||||
filters.clear();
|
||||
connections.clear();
|
||||
}
|
||||
|
||||
// release any old ones..
|
||||
for (int i = 0; i < filtersBeingRemoved.size(); ++i)
|
||||
{
|
||||
filtersBeingRemoved.getUnchecked(i)->filter->releaseResources();
|
||||
|
||||
PlayerAwareFilter* const specialFilter = dynamic_cast <PlayerAwareFilter*> (filtersBeingRemoved.getUnchecked(i)->filter);
|
||||
|
||||
if (specialFilter != 0)
|
||||
specialFilter->setPlayer (0);
|
||||
}
|
||||
}
|
||||
|
||||
void FilterGraphPlayer::audioDeviceIOCallback (const float** inputChannelData_,
|
||||
int totalNumInputChannels_,
|
||||
float** outputChannelData_,
|
||||
int totalNumOutputChannels_,
|
||||
int numSamples)
|
||||
{
|
||||
incomingMidi.clear();
|
||||
messageCollector.removeNextBlockOfMessages (incomingMidi, numSamples);
|
||||
|
||||
for (int i = 0; i < totalNumOutputChannels_; ++i)
|
||||
if (outputChannelData_[i] != 0)
|
||||
zeromem (outputChannelData_[i], sizeof (float) * numSamples);
|
||||
|
||||
const ScopedLock sl (processLock);
|
||||
|
||||
inputChannelData = inputChannelData_;
|
||||
totalNumInputChannels = totalNumInputChannels_;
|
||||
outputChannelData = outputChannelData_;
|
||||
totalNumOutputChannels = totalNumOutputChannels_;
|
||||
|
||||
for (int i = 0; i < filters.size(); ++i)
|
||||
{
|
||||
FilterInGraph* const cf = filters.getUnchecked(i);
|
||||
|
||||
cf->renderBlock (numSamples, filters, connections);
|
||||
}
|
||||
}
|
||||
|
||||
void FilterGraphPlayer::audioDeviceAboutToStart (double sampleRate_, int numSamplesPerBlock)
|
||||
{
|
||||
const ScopedLock sl (processLock);
|
||||
|
||||
sampleRate = sampleRate_;
|
||||
blockSize = numSamplesPerBlock;
|
||||
|
||||
messageCollector.reset (sampleRate_);
|
||||
|
||||
for (int i = 0; i < filters.size(); ++i)
|
||||
{
|
||||
filters.getUnchecked(i)->prepareBuffers (blockSize);
|
||||
filters.getUnchecked(i)->filter->prepareToPlay (sampleRate, blockSize);
|
||||
}
|
||||
}
|
||||
|
||||
void FilterGraphPlayer::audioDeviceStopped()
|
||||
{
|
||||
const ScopedLock sl (processLock);
|
||||
|
||||
for (int i = 0; i < filters.size(); ++i)
|
||||
filters.getUnchecked(i)->filter->releaseResources();
|
||||
}
|
||||
|
||||
void FilterGraphPlayer::handleIncomingMidiMessage (MidiInput*, const MidiMessage& message)
|
||||
{
|
||||
// keyState.processNextMidiEvent (message);
|
||||
messageCollector.addMessageToQueue (message);
|
||||
}
|
||||
269
extras/audio plugin host/src/host/FilterGraph.h
Normal file
269
extras/audio plugin host/src/host/FilterGraph.h
Normal file
|
|
@ -0,0 +1,269 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
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_FILTERGRAPH_JUCEHEADER__
|
||||
#define __JUCE_FILTERGRAPH_JUCEHEADER__
|
||||
|
||||
#include "../plugins/juce_AudioPluginInstance.h"
|
||||
#include "../plugins/juce_PluginDescription.h"
|
||||
|
||||
class FilterInGraph;
|
||||
class FilterGraph;
|
||||
class FilterGraphPlayer;
|
||||
|
||||
const char* const filenameSuffix = ".filtergraph";
|
||||
const char* const filenameWildcard = "*.filtergraph";
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Represents a connection between two pins in a FilterGraph.
|
||||
*/
|
||||
class FilterConnection
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
FilterConnection (FilterGraph& owner);
|
||||
FilterConnection (const FilterConnection& other);
|
||||
~FilterConnection();
|
||||
|
||||
//==============================================================================
|
||||
uint32 sourceFilterID;
|
||||
int sourceChannel;
|
||||
uint32 destFilterID;
|
||||
int destChannel;
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
FilterGraph& owner;
|
||||
|
||||
const FilterConnection& operator= (const FilterConnection&);
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Represents one of the filters in a FilterGraph.
|
||||
*/
|
||||
class FilterInGraph : public ReferenceCountedObject
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
FilterInGraph (FilterGraph& owner, AudioPluginInstance* const plugin);
|
||||
~FilterInGraph();
|
||||
|
||||
//==============================================================================
|
||||
AudioPluginInstance* const filter;
|
||||
uint32 uid;
|
||||
|
||||
//==============================================================================
|
||||
void showUI();
|
||||
|
||||
double getX() const throw() { return x; }
|
||||
double getY() const throw() { return y; }
|
||||
void setPosition (double x, double y) throw();
|
||||
|
||||
XmlElement* createXml() const;
|
||||
|
||||
static FilterInGraph* createForDescription (FilterGraph& owner, const PluginDescription& desc);
|
||||
static FilterInGraph* createFromXml (FilterGraph& owner, const XmlElement& xml);
|
||||
|
||||
//==============================================================================
|
||||
typedef ReferenceCountedObjectPtr <FilterInGraph> Ptr;
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
friend class FilterGraphPlayer;
|
||||
FilterGraph& owner;
|
||||
double x, y;
|
||||
|
||||
friend class PluginWindow;
|
||||
Component* activeUI;
|
||||
int lastX, lastY;
|
||||
|
||||
MidiBuffer outputMidi;
|
||||
AudioSampleBuffer inputAudio, processedAudio;
|
||||
MidiBuffer processedMidi;
|
||||
|
||||
void prepareBuffers (int blockSize);
|
||||
void renderBlock (int numSamples,
|
||||
const ReferenceCountedArray <FilterInGraph>& filters,
|
||||
const OwnedArray <FilterConnection>& connections);
|
||||
|
||||
FilterInGraph (const FilterInGraph&);
|
||||
const FilterInGraph& operator= (const FilterInGraph&);
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A collection of filters and some connections between them.
|
||||
*/
|
||||
class FilterGraph : public FileBasedDocument
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
FilterGraph();
|
||||
~FilterGraph();
|
||||
|
||||
//==============================================================================
|
||||
int getNumFilters() const throw() { return filters.size(); }
|
||||
FilterInGraph* getFilter (const int index) const throw() { return filters [index]; }
|
||||
FilterInGraph* getFilterForUID (const uint32 uid) const throw();
|
||||
|
||||
void addFilter (const FilterInGraph::Ptr& newFilter);
|
||||
void addFilter (const PluginDescription* desc, double x, double y);
|
||||
|
||||
void removeFilter (const uint32 filterUID);
|
||||
void disconnectFilter (const uint32 filterUID);
|
||||
|
||||
//==============================================================================
|
||||
int getNumConnections() const throw() { return connections.size(); }
|
||||
FilterConnection* getConnection (const int index) const throw() { return connections [index]; }
|
||||
|
||||
FilterConnection* getConnectionBetween (uint32 sourceFilterUID, int sourceFilterChannel,
|
||||
uint32 destFilterUID, int destFilterChannel) const throw();
|
||||
|
||||
bool isAnInputTo (const uint32 possibleInput, const uint32 possibleDestination) const throw();
|
||||
|
||||
bool canConnect (uint32 sourceFilterUID, int sourceFilterChannel,
|
||||
uint32 destFilterUID, int destFilterChannel) const throw();
|
||||
|
||||
void addConnection (uint32 sourceFilterUID, int sourceFilterChannel,
|
||||
uint32 destFilterUID, int destFilterChannel);
|
||||
|
||||
void removeConnection (const int index);
|
||||
|
||||
void removeConnection (uint32 sourceFilterUID, int sourceFilterChannel,
|
||||
uint32 destFilterUID, int destFilterChannel);
|
||||
|
||||
void clear();
|
||||
|
||||
XmlElement* createXml() const;
|
||||
void restoreFromXml (const XmlElement& xml);
|
||||
|
||||
//==============================================================================
|
||||
const String getDocumentTitle();
|
||||
const String loadDocument (const File& file);
|
||||
const String saveDocument (const File& file);
|
||||
const File getLastDocumentOpened();
|
||||
void setLastDocumentOpened (const File& file);
|
||||
|
||||
/** The special channel index used to refer to a filter's midi channel.
|
||||
*/
|
||||
static const int midiChannelNumber;
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
friend class FilterGraphPlayer;
|
||||
ReferenceCountedArray <FilterInGraph> filters;
|
||||
OwnedArray <FilterConnection> connections;
|
||||
|
||||
uint32 lastUID;
|
||||
uint32 getNextUID() throw();
|
||||
|
||||
bool isAnInputTo (const uint32 possibleInput, const uint32 possibleDestination, int recursionCheck) const throw();
|
||||
|
||||
FilterGraph (const FilterGraph&);
|
||||
const FilterGraph& operator= (const FilterGraph&);
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
An object the
|
||||
*/
|
||||
class FilterGraphPlayer : public AudioIODeviceCallback,
|
||||
public MidiInputCallback
|
||||
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
FilterGraphPlayer();
|
||||
~FilterGraphPlayer();
|
||||
|
||||
//==============================================================================
|
||||
void updateFrom (FilterGraph* graphToUse);
|
||||
|
||||
void setAudioDeviceManager (AudioDeviceManager* dm);
|
||||
AudioDeviceManager* getAudioDeviceManager() const throw() { return deviceManager; }
|
||||
|
||||
//==============================================================================
|
||||
void audioDeviceIOCallback (const float** inputChannelData,
|
||||
int totalNumInputChannels,
|
||||
float** outputChannelData,
|
||||
int totalNumOutputChannels,
|
||||
int numSamples);
|
||||
void audioDeviceAboutToStart (double sampleRate, int numSamplesPerBlock);
|
||||
void audioDeviceStopped();
|
||||
|
||||
void handleIncomingMidiMessage (MidiInput* source, const MidiMessage& message);
|
||||
|
||||
//==============================================================================
|
||||
static int compareElements (FilterInGraph* const first, FilterInGraph* const second) throw();
|
||||
|
||||
const float** inputChannelData;
|
||||
int totalNumInputChannels;
|
||||
float** outputChannelData;
|
||||
int totalNumOutputChannels;
|
||||
MidiBuffer incomingMidi;
|
||||
|
||||
MidiKeyboardState keyState;
|
||||
MidiMessageCollector messageCollector;
|
||||
|
||||
//==============================================================================
|
||||
class PlayerAwareFilter
|
||||
{
|
||||
public:
|
||||
virtual void setPlayer (FilterGraphPlayer* newPlayer) = 0;
|
||||
};
|
||||
|
||||
private:
|
||||
CriticalSection processLock;
|
||||
double sampleRate;
|
||||
int blockSize;
|
||||
AudioDeviceManager* deviceManager;
|
||||
|
||||
ReferenceCountedArray <FilterInGraph> filters;
|
||||
OwnedArray <FilterConnection> connections;
|
||||
|
||||
FilterGraphPlayer (const FilterGraphPlayer&);
|
||||
const FilterGraphPlayer& operator= (const FilterGraphPlayer&);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
901
extras/audio plugin host/src/host/GraphEditorPanel.cpp
Normal file
901
extras/audio plugin host/src/host/GraphEditorPanel.cpp
Normal file
|
|
@ -0,0 +1,901 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
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.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../../../juce.h"
|
||||
#include "GraphEditorPanel.h"
|
||||
#include "InternalFilters.h"
|
||||
#include "MainHostWindow.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class PinComponent : public Component
|
||||
{
|
||||
public:
|
||||
PinComponent (FilterGraph& graph_,
|
||||
const uint32 filterID_, const int index_, const bool isInput_)
|
||||
: graph (graph_),
|
||||
filterID (filterID_),
|
||||
index (index_),
|
||||
isInput (isInput_)
|
||||
{
|
||||
setSize (16, 16);
|
||||
}
|
||||
|
||||
~PinComponent()
|
||||
{
|
||||
}
|
||||
|
||||
void paint (Graphics& g)
|
||||
{
|
||||
const float w = (float) getWidth();
|
||||
const float h = (float) getHeight();
|
||||
|
||||
Path p;
|
||||
p.addEllipse (w * 0.25f, h * 0.25f, w * 0.5f, h * 0.5f);
|
||||
|
||||
p.addRectangle (w * 0.4f, isInput ? (0.5f * h) : 0.0f, w * 0.2f, h * 0.5f);
|
||||
|
||||
g.setColour (index == FilterGraph::midiChannelNumber ? Colours::red : Colours::green);
|
||||
g.fillPath (p);
|
||||
}
|
||||
|
||||
void mouseDown (const MouseEvent& e)
|
||||
{
|
||||
getGraphPanel()->beginConnectorDrag (isInput ? 0 : filterID,
|
||||
index,
|
||||
isInput ? filterID : 0,
|
||||
index,
|
||||
e);
|
||||
}
|
||||
|
||||
void mouseDrag (const MouseEvent& e)
|
||||
{
|
||||
getGraphPanel()->dragConnector (e);
|
||||
}
|
||||
|
||||
void mouseUp (const MouseEvent& e)
|
||||
{
|
||||
getGraphPanel()->endDraggingConnector (e);
|
||||
}
|
||||
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
const uint32 filterID;
|
||||
const int index;
|
||||
const bool isInput;
|
||||
|
||||
private:
|
||||
FilterGraph& graph;
|
||||
|
||||
PinComponent (const PinComponent&);
|
||||
const PinComponent& operator= (const PinComponent&);
|
||||
|
||||
GraphEditorPanel* getGraphPanel() const throw()
|
||||
{
|
||||
return findParentComponentOfClass ((GraphEditorPanel*) 0);
|
||||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class FilterComponent : public Component
|
||||
{
|
||||
public:
|
||||
FilterComponent (FilterGraph& graph_,
|
||||
const uint32 filterID_)
|
||||
: graph (graph_),
|
||||
filterID (filterID_),
|
||||
numInputs (0),
|
||||
numOutputs (0),
|
||||
pinSize (16),
|
||||
originalX (0),
|
||||
originalY (0),
|
||||
font (13.0f, Font::bold),
|
||||
numIns (0),
|
||||
numOuts (0)
|
||||
{
|
||||
shadow.setShadowProperties (2.5f, 0.5f, -1, 0);
|
||||
setComponentEffect (&shadow);
|
||||
|
||||
setSize (150, 60);
|
||||
}
|
||||
|
||||
~FilterComponent()
|
||||
{
|
||||
deleteAllChildren();
|
||||
}
|
||||
|
||||
void mouseDown (const MouseEvent& e)
|
||||
{
|
||||
originalX = 0;
|
||||
originalY = 0;
|
||||
relativePositionToGlobal (originalX, originalY);
|
||||
|
||||
toFront (true);
|
||||
|
||||
if (e.mods.isPopupMenu())
|
||||
{
|
||||
PopupMenu m;
|
||||
m.addItem (1, "Delete this filter");
|
||||
m.addItem (2, "Disconnect all pins");
|
||||
|
||||
const int r = m.show();
|
||||
|
||||
if (r == 1)
|
||||
{
|
||||
graph.removeFilter (filterID);
|
||||
return;
|
||||
}
|
||||
else if (r == 2)
|
||||
{
|
||||
graph.disconnectFilter (filterID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mouseDrag (const MouseEvent& e)
|
||||
{
|
||||
if (! e.mods.isPopupMenu())
|
||||
{
|
||||
int x = originalX + e.getDistanceFromDragStartX();
|
||||
int y = originalY + e.getDistanceFromDragStartY();
|
||||
|
||||
if (getParentComponent() != 0)
|
||||
getParentComponent()->globalPositionToRelative (x, y);
|
||||
|
||||
const FilterInGraph::Ptr f (graph.getFilterForUID (filterID));
|
||||
|
||||
if (f != 0)
|
||||
{
|
||||
f->setPosition ((x + getWidth() / 2) / (double) getParentWidth(),
|
||||
(y + getHeight() / 2) / (double) getParentHeight());
|
||||
|
||||
getGraphPanel()->updateComponents();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mouseUp (const MouseEvent& e)
|
||||
{
|
||||
if (e.mouseWasClicked() && e.getNumberOfClicks() == 2)
|
||||
{
|
||||
const FilterInGraph::Ptr f (graph.getFilterForUID (filterID));
|
||||
|
||||
if (f != 0)
|
||||
f->showUI();
|
||||
}
|
||||
else if (! e.mouseWasClicked())
|
||||
{
|
||||
graph.setChangedFlag (true);
|
||||
}
|
||||
}
|
||||
|
||||
bool hitTest (int x, int y)
|
||||
{
|
||||
for (int i = getNumChildComponents(); --i >= 0;)
|
||||
if (getChildComponent(i)->getBounds().contains (x, y))
|
||||
return true;
|
||||
|
||||
return x >= 3 && x < getWidth() - 6 && y >= pinSize && y < getHeight() - pinSize;
|
||||
}
|
||||
|
||||
void paint (Graphics& g)
|
||||
{
|
||||
g.setColour (Colours::lightgrey);
|
||||
|
||||
const int x = 4;
|
||||
const int y = pinSize;
|
||||
const int w = getWidth() - x * 2;
|
||||
const int h = getHeight() - pinSize * 2;
|
||||
|
||||
g.fillRect (x, y, w, h);
|
||||
|
||||
g.setColour (Colours::black);
|
||||
g.setFont (font);
|
||||
g.drawFittedText (getName(),
|
||||
x + 4, y + 2, w - 8, h - 4,
|
||||
Justification::centred, 2);
|
||||
|
||||
g.setColour (Colours::grey);
|
||||
g.drawRect (x, y, w, h);
|
||||
}
|
||||
|
||||
void resized()
|
||||
{
|
||||
for (int i = 0; i < getNumChildComponents(); ++i)
|
||||
{
|
||||
PinComponent* const pc = dynamic_cast <PinComponent*> (getChildComponent(i));
|
||||
|
||||
if (pc != 0)
|
||||
{
|
||||
const int total = pc->isInput ? numIns : numOuts;
|
||||
const int index = pc->index == FilterGraph::midiChannelNumber ? (total - 1) : pc->index;
|
||||
|
||||
pc->setBounds (proportionOfWidth ((1 + index) / (total + 1.0f)) - pinSize / 2,
|
||||
pc->isInput ? 0 : (getHeight() - pinSize),
|
||||
pinSize, pinSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void getPinPos (const int index, const bool isInput, float& x, float& y)
|
||||
{
|
||||
for (int i = 0; i < getNumChildComponents(); ++i)
|
||||
{
|
||||
PinComponent* const pc = dynamic_cast <PinComponent*> (getChildComponent(i));
|
||||
|
||||
if (pc != 0 && pc->index == index && isInput == pc->isInput)
|
||||
{
|
||||
x = getX() + pc->getX() + pc->getWidth() * 0.5f;
|
||||
y = getY() + pc->getY() + pc->getHeight() * 0.5f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void update()
|
||||
{
|
||||
const FilterInGraph* const f = graph.getFilterForUID (filterID);
|
||||
|
||||
if (f == 0)
|
||||
{
|
||||
delete this;
|
||||
return;
|
||||
}
|
||||
|
||||
numIns = f->filter->getNumInputChannels();
|
||||
if (f->filter->acceptsMidi())
|
||||
++numIns;
|
||||
|
||||
numOuts = f->filter->getNumOutputChannels();
|
||||
if (f->filter->producesMidi())
|
||||
++numOuts;
|
||||
|
||||
int w = 100;
|
||||
int h = 60;
|
||||
|
||||
w = jmax (w, (jmax (numIns, numOuts) + 1) * 20);
|
||||
|
||||
const int textWidth = font.getStringWidth (f->filter->getName());
|
||||
w = jmax (w, 16 + jmin (textWidth, 300));
|
||||
if (textWidth > 300)
|
||||
h = 100;
|
||||
|
||||
setSize (w, h);
|
||||
|
||||
setCentreRelative ((float) f->getX(), (float) f->getY());
|
||||
|
||||
if (numIns != numInputs || numOuts != numOutputs)
|
||||
{
|
||||
numInputs = numIns;
|
||||
numOutputs = numOuts;
|
||||
|
||||
deleteAllChildren();
|
||||
|
||||
int i;
|
||||
for (i = 0; i < f->filter->getNumInputChannels(); ++i)
|
||||
addAndMakeVisible (new PinComponent (graph, filterID, i, true));
|
||||
|
||||
if (f->filter->acceptsMidi())
|
||||
addAndMakeVisible (new PinComponent (graph, filterID, FilterGraph::midiChannelNumber, true));
|
||||
|
||||
for (i = 0; i < f->filter->getNumOutputChannels(); ++i)
|
||||
addAndMakeVisible (new PinComponent (graph, filterID, i, false));
|
||||
|
||||
if (f->filter->producesMidi())
|
||||
addAndMakeVisible (new PinComponent (graph, filterID, FilterGraph::midiChannelNumber, false));
|
||||
|
||||
setName (f->filter->getName());
|
||||
|
||||
resized();
|
||||
}
|
||||
}
|
||||
|
||||
FilterGraph& graph;
|
||||
const uint32 filterID;
|
||||
int numInputs, numOutputs;
|
||||
|
||||
private:
|
||||
int pinSize;
|
||||
int originalX, originalY;
|
||||
int numIns, numOuts;
|
||||
DropShadowEffect shadow;
|
||||
Font font;
|
||||
|
||||
GraphEditorPanel* getGraphPanel() const throw()
|
||||
{
|
||||
return findParentComponentOfClass ((GraphEditorPanel*) 0);
|
||||
}
|
||||
|
||||
FilterComponent (const FilterComponent&);
|
||||
const FilterComponent& operator= (const FilterComponent&);
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class ConnectorComponent : public Component
|
||||
{
|
||||
public:
|
||||
ConnectorComponent (FilterGraph& graph_)
|
||||
: graph (graph_),
|
||||
sourceFilterID (0),
|
||||
destFilterID (0),
|
||||
sourceFilterChannel (0),
|
||||
destFilterChannel (0),
|
||||
lastInputX (0),
|
||||
lastInputY (0),
|
||||
lastOutputX (0),
|
||||
lastOutputY (0)
|
||||
{
|
||||
setAlwaysOnTop (true);
|
||||
}
|
||||
|
||||
~ConnectorComponent()
|
||||
{
|
||||
}
|
||||
|
||||
void setInput (const uint32 sourceFilterID_, const int sourceFilterChannel_)
|
||||
{
|
||||
if (sourceFilterID != sourceFilterID_ || sourceFilterChannel != sourceFilterChannel_)
|
||||
{
|
||||
sourceFilterID = sourceFilterID_;
|
||||
sourceFilterChannel = sourceFilterChannel_;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void setOutput (const uint32 destFilterID_, const int destFilterChannel_)
|
||||
{
|
||||
if (destFilterID != destFilterID_ || destFilterChannel != destFilterChannel_)
|
||||
{
|
||||
destFilterID = destFilterID_;
|
||||
destFilterChannel = destFilterChannel_;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void dragStart (int x, int y)
|
||||
{
|
||||
lastInputX = (float) x;
|
||||
lastInputY = (float) y;
|
||||
resizeToFit();
|
||||
}
|
||||
|
||||
void dragEnd (int x, int y)
|
||||
{
|
||||
lastOutputX = (float) x;
|
||||
lastOutputY = (float) y;
|
||||
resizeToFit();
|
||||
}
|
||||
|
||||
void update()
|
||||
{
|
||||
float x1, y1, x2, y2;
|
||||
getPoints (x1, y1, x2, y2);
|
||||
|
||||
if (lastInputX != x1
|
||||
|| lastInputY != y1
|
||||
|| lastOutputX != x2
|
||||
|| lastOutputY != y2)
|
||||
{
|
||||
resizeToFit();
|
||||
}
|
||||
}
|
||||
|
||||
void resizeToFit()
|
||||
{
|
||||
float x1, y1, x2, y2;
|
||||
getPoints (x1, y1, x2, y2);
|
||||
|
||||
const Rectangle newBounds ((int) jmin (x1, x2) - 4,
|
||||
(int) jmin (y1, y2) - 4,
|
||||
(int) abs (x1 - x2) + 8,
|
||||
(int) abs (y1 - y2) + 8);
|
||||
|
||||
if (newBounds != getBounds())
|
||||
setBounds (newBounds);
|
||||
else
|
||||
resized();
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
void getPoints (float& x1, float& y1, float& x2, float& y2) const
|
||||
{
|
||||
x1 = lastInputX;
|
||||
y1 = lastInputY;
|
||||
x2 = lastOutputX;
|
||||
y2 = lastOutputY;
|
||||
|
||||
GraphEditorPanel* const hostPanel = getGraphPanel();
|
||||
|
||||
if (hostPanel != 0)
|
||||
{
|
||||
FilterComponent* srcFilterComp = hostPanel->getComponentForFilter (sourceFilterID);
|
||||
|
||||
if (srcFilterComp != 0)
|
||||
srcFilterComp->getPinPos (sourceFilterChannel, false, x1, y1);
|
||||
|
||||
FilterComponent* dstFilterComp = hostPanel->getComponentForFilter (destFilterID);
|
||||
|
||||
if (dstFilterComp != 0)
|
||||
dstFilterComp->getPinPos (destFilterChannel, true, x2, y2);
|
||||
}
|
||||
}
|
||||
|
||||
void paint (Graphics& g)
|
||||
{
|
||||
if (sourceFilterChannel == FilterGraph::midiChannelNumber
|
||||
|| destFilterChannel == FilterGraph::midiChannelNumber)
|
||||
{
|
||||
g.setColour (Colours::red);
|
||||
}
|
||||
else
|
||||
{
|
||||
g.setColour (Colours::green);
|
||||
}
|
||||
|
||||
g.fillPath (linePath);
|
||||
}
|
||||
|
||||
bool hitTest (int x, int y)
|
||||
{
|
||||
if (hitPath.contains ((float) x, (float) y))
|
||||
{
|
||||
double distanceFromStart, distanceFromEnd;
|
||||
getDistancesFromEnds (x, y, distanceFromStart, distanceFromEnd);
|
||||
|
||||
// avoid clicking the connector when over a pin
|
||||
return distanceFromStart > 7.0 && distanceFromEnd > 7.0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void mouseDown (const MouseEvent&)
|
||||
{
|
||||
dragging = false;
|
||||
}
|
||||
|
||||
void mouseDrag (const MouseEvent& e)
|
||||
{
|
||||
if ((! dragging) && ! e.mouseWasClicked())
|
||||
{
|
||||
dragging = true;
|
||||
|
||||
graph.removeConnection (sourceFilterID, sourceFilterChannel, destFilterID, destFilterChannel);
|
||||
|
||||
double distanceFromStart, distanceFromEnd;
|
||||
getDistancesFromEnds (e.x, e.y, distanceFromStart, distanceFromEnd);
|
||||
const bool isNearerSource = (distanceFromStart < distanceFromEnd);
|
||||
|
||||
getGraphPanel()->beginConnectorDrag (isNearerSource ? 0 : sourceFilterID,
|
||||
sourceFilterChannel,
|
||||
isNearerSource ? destFilterID : 0,
|
||||
destFilterChannel,
|
||||
e);
|
||||
}
|
||||
else if (dragging)
|
||||
{
|
||||
getGraphPanel()->dragConnector (e);
|
||||
}
|
||||
}
|
||||
|
||||
void mouseUp (const MouseEvent& e)
|
||||
{
|
||||
if (dragging)
|
||||
getGraphPanel()->endDraggingConnector (e);
|
||||
}
|
||||
|
||||
void resized()
|
||||
{
|
||||
float x1, y1, x2, y2;
|
||||
getPoints (x1, y1, x2, y2);
|
||||
|
||||
lastInputX = x1;
|
||||
lastInputY = y1;
|
||||
lastOutputX = x2;
|
||||
lastOutputY = y2;
|
||||
|
||||
x1 -= getX();
|
||||
y1 -= getY();
|
||||
x2 -= getX();
|
||||
y2 -= getY();
|
||||
|
||||
linePath.clear();
|
||||
linePath.startNewSubPath (x1, y1);
|
||||
linePath.cubicTo (x1, y1 + (y2 - y1) * 0.33f,
|
||||
x2, y1 + (y2 - y1) * 0.66f,
|
||||
x2, y2);
|
||||
|
||||
PathStrokeType wideStroke (8.0f);
|
||||
wideStroke.createStrokedPath (hitPath, linePath);
|
||||
|
||||
PathStrokeType stroke (2.5f);
|
||||
stroke.createStrokedPath (linePath, linePath);
|
||||
|
||||
const float arrowW = 5.0f;
|
||||
const float arrowL = 4.0f;
|
||||
|
||||
Path arrow;
|
||||
arrow.addTriangle (-arrowL, arrowW,
|
||||
-arrowL, -arrowW,
|
||||
arrowL, 0.0f);
|
||||
|
||||
arrow.applyTransform (AffineTransform::identity
|
||||
.rotated (float_Pi * 0.5f - (float) atan2 (x2 - x1, y2 - y1))
|
||||
.translated ((x1 + x2) * 0.5f,
|
||||
(y1 + y2) * 0.5f));
|
||||
|
||||
linePath.addPath (arrow);
|
||||
linePath.setUsingNonZeroWinding (true);
|
||||
}
|
||||
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
uint32 sourceFilterID, destFilterID;
|
||||
int sourceFilterChannel, destFilterChannel;
|
||||
|
||||
private:
|
||||
FilterGraph& graph;
|
||||
float lastInputX, lastInputY, lastOutputX, lastOutputY;
|
||||
Path linePath, hitPath;
|
||||
bool dragging;
|
||||
|
||||
GraphEditorPanel* getGraphPanel() const throw()
|
||||
{
|
||||
return findParentComponentOfClass ((GraphEditorPanel*) 0);
|
||||
}
|
||||
|
||||
void getDistancesFromEnds (int x, int y, double& distanceFromStart, double& distanceFromEnd) const
|
||||
{
|
||||
float x1, y1, x2, y2;
|
||||
getPoints (x1, y1, x2, y2);
|
||||
|
||||
distanceFromStart = juce_hypot (x - (x1 - getX()), y - (y1 - getY()));
|
||||
distanceFromEnd = juce_hypot (x - (x2 - getX()), y - (y2 - getY()));
|
||||
}
|
||||
|
||||
ConnectorComponent (const ConnectorComponent&);
|
||||
const ConnectorComponent& operator= (const ConnectorComponent&);
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
GraphEditorPanel::GraphEditorPanel (FilterGraph& graph_)
|
||||
: graph (graph_),
|
||||
draggingConnector (0)
|
||||
{
|
||||
graph.addChangeListener (this);
|
||||
setOpaque (true);
|
||||
}
|
||||
|
||||
GraphEditorPanel::~GraphEditorPanel()
|
||||
{
|
||||
graph.removeChangeListener (this);
|
||||
deleteAndZero (draggingConnector);
|
||||
deleteAllChildren();
|
||||
}
|
||||
|
||||
void GraphEditorPanel::paint (Graphics& g)
|
||||
{
|
||||
g.fillAll (Colours::white);
|
||||
}
|
||||
|
||||
void GraphEditorPanel::mouseDown (const MouseEvent& e)
|
||||
{
|
||||
if (e.mods.isPopupMenu())
|
||||
{
|
||||
PopupMenu m;
|
||||
|
||||
MainHostWindow* const mainWindow = findParentComponentOfClass ((MainHostWindow*) 0);
|
||||
|
||||
if (mainWindow != 0)
|
||||
{
|
||||
mainWindow->addPluginsToMenu (m);
|
||||
|
||||
const int r = m.show();
|
||||
|
||||
createNewPlugin (mainWindow->getChosenType (r), e.x, e.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GraphEditorPanel::createNewPlugin (const PluginDescription* desc, int x, int y)
|
||||
{
|
||||
graph.addFilter (desc, x / (double) getWidth(), y / (double) getHeight());
|
||||
}
|
||||
|
||||
FilterComponent* GraphEditorPanel::getComponentForFilter (const uint32 filterID) const
|
||||
{
|
||||
for (int i = getNumChildComponents(); --i >= 0;)
|
||||
{
|
||||
FilterComponent* const fc = dynamic_cast <FilterComponent*> (getChildComponent (i));
|
||||
|
||||
if (fc != 0 && fc->filterID == filterID)
|
||||
return fc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ConnectorComponent* GraphEditorPanel::getComponentForConnection (const FilterConnection& conn) const
|
||||
{
|
||||
for (int i = getNumChildComponents(); --i >= 0;)
|
||||
{
|
||||
ConnectorComponent* const c = dynamic_cast <ConnectorComponent*> (getChildComponent (i));
|
||||
|
||||
if (c != 0
|
||||
&& c->sourceFilterID == conn.sourceFilterID
|
||||
&& c->destFilterID == conn.destFilterID
|
||||
&& c->sourceFilterChannel == conn.sourceChannel
|
||||
&& c->destFilterChannel == conn.destChannel)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
PinComponent* GraphEditorPanel::findPinAt (const int x, const int y) const
|
||||
{
|
||||
for (int i = getNumChildComponents(); --i >= 0;)
|
||||
{
|
||||
FilterComponent* const fc = dynamic_cast <FilterComponent*> (getChildComponent (i));
|
||||
|
||||
if (fc != 0)
|
||||
{
|
||||
PinComponent* const pin
|
||||
= dynamic_cast <PinComponent*> (fc->getComponentAt (x - fc->getX(),
|
||||
y - fc->getY()));
|
||||
|
||||
if (pin != 0)
|
||||
return pin;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GraphEditorPanel::resized()
|
||||
{
|
||||
updateComponents();
|
||||
}
|
||||
|
||||
void GraphEditorPanel::changeListenerCallback (void*)
|
||||
{
|
||||
updateComponents();
|
||||
}
|
||||
|
||||
void GraphEditorPanel::updateComponents()
|
||||
{
|
||||
int i;
|
||||
for (i = getNumChildComponents(); --i >= 0;)
|
||||
{
|
||||
FilterComponent* const fc = dynamic_cast <FilterComponent*> (getChildComponent (i));
|
||||
|
||||
if (fc != 0)
|
||||
fc->update();
|
||||
}
|
||||
|
||||
for (i = getNumChildComponents(); --i >= 0;)
|
||||
{
|
||||
ConnectorComponent* const cc = dynamic_cast <ConnectorComponent*> (getChildComponent (i));
|
||||
|
||||
if (cc != 0 && cc != draggingConnector)
|
||||
{
|
||||
if (graph.getConnectionBetween (cc->sourceFilterID, cc->sourceFilterChannel,
|
||||
cc->destFilterID, cc->destFilterChannel) == 0)
|
||||
{
|
||||
delete cc;
|
||||
}
|
||||
else
|
||||
{
|
||||
cc->update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = graph.getNumFilters(); --i >= 0;)
|
||||
{
|
||||
const FilterInGraph* const f = graph.getFilter (i);
|
||||
|
||||
if (getComponentForFilter (f->uid) == 0)
|
||||
{
|
||||
FilterComponent* const comp = new FilterComponent (graph, f->uid);
|
||||
addAndMakeVisible (comp);
|
||||
comp->update();
|
||||
}
|
||||
}
|
||||
|
||||
for (i = graph.getNumConnections(); --i >= 0;)
|
||||
{
|
||||
FilterConnection* const c = graph.getConnection (i);
|
||||
|
||||
if (getComponentForConnection (*c) == 0)
|
||||
{
|
||||
ConnectorComponent* const comp = new ConnectorComponent (graph);
|
||||
addAndMakeVisible (comp);
|
||||
|
||||
comp->setInput (c->sourceFilterID, c->sourceChannel);
|
||||
comp->setOutput (c->destFilterID, c->destChannel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GraphEditorPanel::beginConnectorDrag (const uint32 sourceFilterID, const int sourceFilterChannel,
|
||||
const uint32 destFilterID, const int destFilterChannel,
|
||||
const MouseEvent& e)
|
||||
{
|
||||
delete draggingConnector;
|
||||
draggingConnector = dynamic_cast <ConnectorComponent*> (e.originalComponent);
|
||||
|
||||
if (draggingConnector == 0)
|
||||
draggingConnector = new ConnectorComponent (graph);
|
||||
|
||||
draggingConnector->setInput (sourceFilterID, sourceFilterChannel);
|
||||
draggingConnector->setOutput (destFilterID, destFilterChannel);
|
||||
|
||||
addAndMakeVisible (draggingConnector);
|
||||
draggingConnector->toFront (false);
|
||||
|
||||
dragConnector (e);
|
||||
}
|
||||
|
||||
void GraphEditorPanel::dragConnector (const MouseEvent& e)
|
||||
{
|
||||
const MouseEvent e2 (e.getEventRelativeTo (this));
|
||||
|
||||
if (draggingConnector != 0)
|
||||
{
|
||||
int x = e2.x;
|
||||
int y = e2.y;
|
||||
|
||||
PinComponent* const pin = findPinAt (x, y);
|
||||
|
||||
if (pin != 0)
|
||||
{
|
||||
uint32 srcFilter = draggingConnector->sourceFilterID;
|
||||
int srcChannel = draggingConnector->sourceFilterChannel;
|
||||
uint32 dstFilter = draggingConnector->destFilterID;
|
||||
int dstChannel = draggingConnector->destFilterChannel;
|
||||
|
||||
if (srcFilter == 0 && ! pin->isInput)
|
||||
{
|
||||
srcFilter = pin->filterID;
|
||||
srcChannel = pin->index;
|
||||
}
|
||||
else if (dstFilter == 0 && pin->isInput)
|
||||
{
|
||||
dstFilter = pin->filterID;
|
||||
dstChannel = pin->index;
|
||||
}
|
||||
|
||||
if (graph.canConnect (srcFilter, srcChannel, dstFilter, dstChannel))
|
||||
{
|
||||
x = pin->getParentComponent()->getX() + pin->getX() + pin->getWidth() / 2;
|
||||
y = pin->getParentComponent()->getY() + pin->getY() + pin->getHeight() / 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (draggingConnector->sourceFilterID == 0)
|
||||
draggingConnector->dragStart (x, y);
|
||||
else
|
||||
draggingConnector->dragEnd (x, y);
|
||||
}
|
||||
}
|
||||
|
||||
void GraphEditorPanel::endDraggingConnector (const MouseEvent& e)
|
||||
{
|
||||
if (draggingConnector == 0)
|
||||
return;
|
||||
|
||||
const MouseEvent e2 (e.getEventRelativeTo (this));
|
||||
|
||||
uint32 srcFilter = draggingConnector->sourceFilterID;
|
||||
int srcChannel = draggingConnector->sourceFilterChannel;
|
||||
uint32 dstFilter = draggingConnector->destFilterID;
|
||||
int dstChannel = draggingConnector->destFilterChannel;
|
||||
|
||||
deleteAndZero (draggingConnector);
|
||||
|
||||
PinComponent* const pin = findPinAt (e2.x, e2.y);
|
||||
|
||||
if (pin != 0)
|
||||
{
|
||||
if (srcFilter == 0)
|
||||
{
|
||||
if (pin->isInput)
|
||||
return;
|
||||
|
||||
srcFilter = pin->filterID;
|
||||
srcChannel = pin->index;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (! pin->isInput)
|
||||
return;
|
||||
|
||||
dstFilter = pin->filterID;
|
||||
dstChannel = pin->index;
|
||||
}
|
||||
|
||||
graph.addConnection (srcFilter, srcChannel, dstFilter, dstChannel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
GraphDocumentComponent::GraphDocumentComponent (AudioDeviceManager* deviceManager_)
|
||||
: deviceManager (deviceManager_)
|
||||
{
|
||||
addAndMakeVisible (graphPanel = new GraphEditorPanel (graph));
|
||||
|
||||
addAndMakeVisible (keyboardComp = new MidiKeyboardComponent (graphRenderer.keyState,
|
||||
MidiKeyboardComponent::horizontalKeyboard));
|
||||
|
||||
graphRenderer.setAudioDeviceManager (deviceManager);
|
||||
graphRenderer.updateFrom (&graph);
|
||||
|
||||
graph.addChangeListener (this);
|
||||
deviceManager->addChangeListener (this);
|
||||
|
||||
graphPanel->updateComponents();
|
||||
}
|
||||
|
||||
GraphDocumentComponent::~GraphDocumentComponent()
|
||||
{
|
||||
graph.removeChangeListener (this);
|
||||
deviceManager->removeChangeListener (this);
|
||||
|
||||
deleteAllChildren();
|
||||
|
||||
graphRenderer.updateFrom (0);
|
||||
graphRenderer.setAudioDeviceManager (0);
|
||||
|
||||
graph.clear();
|
||||
}
|
||||
|
||||
void GraphDocumentComponent::resized()
|
||||
{
|
||||
const int keysHeight = 60;
|
||||
graphPanel->setBounds (0, 0, getWidth(), getHeight() - keysHeight);
|
||||
keyboardComp->setBounds (0, getHeight() - keysHeight, getWidth(), keysHeight);
|
||||
}
|
||||
|
||||
void GraphDocumentComponent::createNewPlugin (const PluginDescription* desc, int x, int y)
|
||||
{
|
||||
graphPanel->createNewPlugin (desc, x, y);
|
||||
}
|
||||
|
||||
void GraphDocumentComponent::changeListenerCallback (void*)
|
||||
{
|
||||
graphRenderer.updateFrom (&graph);
|
||||
}
|
||||
122
extras/audio plugin host/src/host/GraphEditorPanel.h
Normal file
122
extras/audio plugin host/src/host/GraphEditorPanel.h
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
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_FILTERGRAPHEDITOR_JUCEHEADER__
|
||||
#define __JUCE_FILTERGRAPHEDITOR_JUCEHEADER__
|
||||
|
||||
#include "../plugins/juce_KnownPluginList.h"
|
||||
#include "FilterGraph.h"
|
||||
|
||||
class FilterComponent;
|
||||
class ConnectorComponent;
|
||||
class PinComponent;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A panel that displays and edits a FilterGraph.
|
||||
*/
|
||||
class GraphEditorPanel : public Component,
|
||||
public ChangeListener
|
||||
{
|
||||
public:
|
||||
GraphEditorPanel (FilterGraph& graph);
|
||||
~GraphEditorPanel();
|
||||
|
||||
void paint (Graphics& g);
|
||||
void mouseDown (const MouseEvent& e);
|
||||
|
||||
void createNewPlugin (const PluginDescription* desc, int x, int y);
|
||||
|
||||
FilterComponent* getComponentForFilter (const uint32 filterID) const;
|
||||
ConnectorComponent* getComponentForConnection (const FilterConnection& conn) const;
|
||||
PinComponent* findPinAt (const int x, const int y) const;
|
||||
|
||||
void resized();
|
||||
void changeListenerCallback (void*);
|
||||
void updateComponents();
|
||||
|
||||
//==============================================================================
|
||||
void beginConnectorDrag (const uint32 sourceFilterID, const int sourceFilterChannel,
|
||||
const uint32 destFilterID, const int destFilterChannel,
|
||||
const MouseEvent& e);
|
||||
void dragConnector (const MouseEvent& e);
|
||||
void endDraggingConnector (const MouseEvent& e);
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
FilterGraph& graph;
|
||||
ConnectorComponent* draggingConnector;
|
||||
|
||||
GraphEditorPanel (const GraphEditorPanel&);
|
||||
const GraphEditorPanel& operator= (const GraphEditorPanel&);
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A panel that embeds a GraphEditorPanel with a midi keyboard at the bottom.
|
||||
|
||||
It also manages the graph itself, and plays it.
|
||||
*/
|
||||
class GraphDocumentComponent : public Component,
|
||||
public ChangeListener
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
GraphDocumentComponent (AudioDeviceManager* deviceManager);
|
||||
~GraphDocumentComponent();
|
||||
|
||||
//==============================================================================
|
||||
void createNewPlugin (const PluginDescription* desc, int x, int y);
|
||||
|
||||
//==============================================================================
|
||||
FilterGraph graph;
|
||||
|
||||
//==============================================================================
|
||||
void resized();
|
||||
void changeListenerCallback (void*);
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
AudioDeviceManager* deviceManager;
|
||||
FilterGraphPlayer graphRenderer;
|
||||
|
||||
GraphEditorPanel* graphPanel;
|
||||
Component* keyboardComp;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
406
extras/audio plugin host/src/host/InternalFilters.cpp
Normal file
406
extras/audio plugin host/src/host/InternalFilters.cpp
Normal file
|
|
@ -0,0 +1,406 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
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.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "InternalFilters.h"
|
||||
#include "FilterGraph.h"
|
||||
|
||||
//==============================================================================
|
||||
class InternalFilterBase : public AudioPluginInstance,
|
||||
public FilterGraphPlayer::PlayerAwareFilter
|
||||
{
|
||||
public:
|
||||
InternalFilterBase()
|
||||
: player (0)
|
||||
{
|
||||
}
|
||||
|
||||
~InternalFilterBase()
|
||||
{
|
||||
}
|
||||
|
||||
void setPlayer (FilterGraphPlayer* p)
|
||||
{
|
||||
player = p;
|
||||
rendererChanged();
|
||||
}
|
||||
|
||||
virtual void rendererChanged() {}
|
||||
|
||||
const String getManufacturer() const { return "Raw Material Software"; }
|
||||
const String getFormatName() const { return "Internal"; }
|
||||
const File getFile() const { return File::nonexistent; }
|
||||
int getUID() const { return getName().hashCode(); }
|
||||
int getSamplesLatency() const { return 0; }
|
||||
|
||||
AudioFilterEditor* JUCE_CALLTYPE createEditor() { return 0; }
|
||||
int JUCE_CALLTYPE getNumParameters() { return 0; }
|
||||
const String JUCE_CALLTYPE getParameterName (int) { return String::empty; }
|
||||
float JUCE_CALLTYPE getParameter (int) { return 0; }
|
||||
const String JUCE_CALLTYPE getParameterText (int) { return String::empty; }
|
||||
void JUCE_CALLTYPE setParameter (int, float) {}
|
||||
int JUCE_CALLTYPE getNumPrograms() { return 0; }
|
||||
int JUCE_CALLTYPE getCurrentProgram() { return 0; }
|
||||
void JUCE_CALLTYPE setCurrentProgram (int) {}
|
||||
const String JUCE_CALLTYPE getProgramName (int) { return String::empty; }
|
||||
void JUCE_CALLTYPE changeProgramName (int, const String&) {}
|
||||
void JUCE_CALLTYPE getStateInformation (JUCE_NAMESPACE::MemoryBlock&) {}
|
||||
void JUCE_CALLTYPE setStateInformation (const void*, int) {}
|
||||
|
||||
protected:
|
||||
FilterGraphPlayer* player;
|
||||
|
||||
AudioIODevice* getAudioDevice() const
|
||||
{
|
||||
if (player != 0)
|
||||
{
|
||||
AudioDeviceManager* const dm = player->getAudioDeviceManager();
|
||||
|
||||
jassert (dm != 0);
|
||||
if (dm != 0)
|
||||
return dm->getCurrentAudioDevice();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class AudioInputDeviceFilter : public InternalFilterBase
|
||||
{
|
||||
public:
|
||||
AudioInputDeviceFilter (const int numChannels)
|
||||
{
|
||||
numOutputChannels = numChannels;
|
||||
}
|
||||
|
||||
~AudioInputDeviceFilter() {}
|
||||
|
||||
const String getName() const { return "Audio Input"; }
|
||||
const String getVersion() const { return "1.0"; }
|
||||
bool isInstrument() const { return true; }
|
||||
const String getCategory() const { return "I/O devices"; }
|
||||
bool acceptsMidi() const { return false; }
|
||||
bool producesMidi() const { return false; }
|
||||
|
||||
void rendererChanged()
|
||||
{
|
||||
AudioIODevice* const dev = getAudioDevice();
|
||||
|
||||
if (dev != 0)
|
||||
numOutputChannels = dev->getInputChannelNames().size();
|
||||
}
|
||||
|
||||
void JUCE_CALLTYPE prepareToPlay (double /*sampleRate*/, int /*estimatedSamplesPerBlock*/)
|
||||
{
|
||||
rendererChanged();
|
||||
}
|
||||
|
||||
void JUCE_CALLTYPE releaseResources()
|
||||
{
|
||||
}
|
||||
|
||||
void JUCE_CALLTYPE processBlock (const AudioSampleBuffer& /*input*/,
|
||||
AudioSampleBuffer& output,
|
||||
const bool accumulateOutput,
|
||||
MidiBuffer&)
|
||||
{
|
||||
int n = 0;
|
||||
|
||||
for (int i = 0; i < player->totalNumInputChannels; ++i)
|
||||
{
|
||||
if (n >= output.getNumChannels())
|
||||
break;
|
||||
|
||||
if (player->inputChannelData [i] != 0)
|
||||
{
|
||||
if (accumulateOutput)
|
||||
output.addFrom (n, 0, player->inputChannelData [i], output.getNumSamples());
|
||||
else
|
||||
output.copyFrom (n, 0, player->inputChannelData [i], output.getNumSamples());
|
||||
|
||||
++n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const String JUCE_CALLTYPE getInputChannelName (const int channelIndex) const
|
||||
{
|
||||
return String (channelIndex + 1);
|
||||
}
|
||||
|
||||
const String JUCE_CALLTYPE getOutputChannelName (const int channelIndex) const
|
||||
{
|
||||
AudioIODevice* const dev = getAudioDevice();
|
||||
|
||||
if (dev != 0)
|
||||
return dev->getInputChannelNames() [channelIndex];
|
||||
|
||||
return String (channelIndex + 1);
|
||||
}
|
||||
|
||||
bool JUCE_CALLTYPE isInputChannelStereoPair (int) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JUCE_CALLTYPE isOutputChannelStereoPair (int) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class AudioOutputDeviceFilter : public InternalFilterBase
|
||||
{
|
||||
public:
|
||||
AudioOutputDeviceFilter (const int numChannels)
|
||||
{
|
||||
numInputChannels = numChannels;
|
||||
}
|
||||
|
||||
~AudioOutputDeviceFilter() {}
|
||||
|
||||
const String getName() const { return "Audio Output"; }
|
||||
const String getVersion() const { return "1.0"; }
|
||||
bool isInstrument() const { return false; }
|
||||
const String getCategory() const { return "I/O devices"; }
|
||||
bool acceptsMidi() const { return false; }
|
||||
bool producesMidi() const { return false; }
|
||||
|
||||
void rendererChanged()
|
||||
{
|
||||
AudioIODevice* const dev = getAudioDevice();
|
||||
|
||||
if (dev != 0)
|
||||
numInputChannels = dev->getOutputChannelNames().size();
|
||||
}
|
||||
|
||||
void JUCE_CALLTYPE prepareToPlay (double /*sampleRate*/, int /*estimatedSamplesPerBlock*/)
|
||||
{
|
||||
rendererChanged();
|
||||
}
|
||||
|
||||
void JUCE_CALLTYPE releaseResources()
|
||||
{
|
||||
}
|
||||
|
||||
void JUCE_CALLTYPE processBlock (const AudioSampleBuffer& input,
|
||||
AudioSampleBuffer&,
|
||||
const bool accumulateOutput,
|
||||
MidiBuffer&)
|
||||
{
|
||||
int n = 0;
|
||||
|
||||
for (int i = 0; i < player->totalNumOutputChannels; ++i)
|
||||
{
|
||||
if (n >= input.getNumChannels())
|
||||
break;
|
||||
|
||||
float* dst = player->outputChannelData [i];
|
||||
|
||||
if (dst != 0)
|
||||
{
|
||||
const float* src = input.getSampleData (n);
|
||||
|
||||
if (accumulateOutput)
|
||||
{
|
||||
for (int i = input.getNumSamples(); --i >= 0;)
|
||||
*dst++ += *src++;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (dst, src, sizeof (float) * input.getNumSamples());
|
||||
}
|
||||
|
||||
++n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const String JUCE_CALLTYPE getInputChannelName (const int channelIndex) const
|
||||
{
|
||||
AudioIODevice* const dev = getAudioDevice();
|
||||
|
||||
if (dev != 0)
|
||||
return dev->getOutputChannelNames() [channelIndex];
|
||||
|
||||
return String (channelIndex + 1);
|
||||
}
|
||||
|
||||
const String JUCE_CALLTYPE getOutputChannelName (const int channelIndex) const
|
||||
{
|
||||
return String (channelIndex + 1);
|
||||
}
|
||||
|
||||
bool JUCE_CALLTYPE isInputChannelStereoPair (int) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JUCE_CALLTYPE isOutputChannelStereoPair (int) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class MidiInputDeviceFilter : public InternalFilterBase
|
||||
{
|
||||
public:
|
||||
MidiInputDeviceFilter()
|
||||
{
|
||||
}
|
||||
|
||||
~MidiInputDeviceFilter() {}
|
||||
|
||||
const String getName() const { return "Midi Input"; }
|
||||
const String getVersion() const { return "1.0"; }
|
||||
bool isInstrument() const { return true; }
|
||||
const String getCategory() const { return "I/O devices"; }
|
||||
bool acceptsMidi() const { return false; }
|
||||
bool producesMidi() const { return true; }
|
||||
|
||||
void rendererChanged()
|
||||
{
|
||||
if (player != 0)
|
||||
{
|
||||
AudioDeviceManager* const dm = player->getAudioDeviceManager();
|
||||
|
||||
jassert (dm != 0);
|
||||
}
|
||||
}
|
||||
|
||||
void JUCE_CALLTYPE prepareToPlay (double /*sampleRate*/, int /*estimatedSamplesPerBlock*/)
|
||||
{
|
||||
rendererChanged();
|
||||
}
|
||||
|
||||
void JUCE_CALLTYPE releaseResources()
|
||||
{
|
||||
}
|
||||
|
||||
void JUCE_CALLTYPE processBlock (const AudioSampleBuffer& input,
|
||||
AudioSampleBuffer&,
|
||||
const bool accumulateOutput,
|
||||
MidiBuffer& midiBuffer)
|
||||
{
|
||||
if (! accumulateOutput)
|
||||
midiBuffer.clear();
|
||||
|
||||
midiBuffer.addEvents (player->incomingMidi, 0, input.getNumSamples(), 0);
|
||||
}
|
||||
|
||||
const String JUCE_CALLTYPE getInputChannelName (const int channelIndex) const
|
||||
{
|
||||
return String (channelIndex + 1);
|
||||
}
|
||||
|
||||
const String JUCE_CALLTYPE getOutputChannelName (const int channelIndex) const
|
||||
{
|
||||
AudioIODevice* const dev = getAudioDevice();
|
||||
|
||||
if (dev != 0)
|
||||
return dev->getInputChannelNames() [channelIndex];
|
||||
|
||||
return String (channelIndex + 1);
|
||||
}
|
||||
|
||||
bool JUCE_CALLTYPE isInputChannelStereoPair (int) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JUCE_CALLTYPE isOutputChannelStereoPair (int) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
InternalPluginFormat::InternalPluginFormat()
|
||||
{
|
||||
{
|
||||
AudioInputDeviceFilter f (2);
|
||||
audioInDesc.fillInFromInstance (f);
|
||||
}
|
||||
|
||||
{
|
||||
AudioOutputDeviceFilter f (2);
|
||||
audioOutDesc.fillInFromInstance (f);
|
||||
}
|
||||
|
||||
{
|
||||
MidiInputDeviceFilter f;
|
||||
midiInDesc.fillInFromInstance (f);
|
||||
}
|
||||
}
|
||||
|
||||
AudioPluginInstance* InternalPluginFormat::createInstanceFromDescription (const PluginDescription& desc)
|
||||
{
|
||||
if (desc.name == audioOutDesc.name)
|
||||
{
|
||||
return new AudioOutputDeviceFilter (desc.numInputChannels);
|
||||
}
|
||||
else if (desc.name == audioInDesc.name)
|
||||
{
|
||||
return new AudioInputDeviceFilter (desc.numOutputChannels);
|
||||
}
|
||||
else if (desc.name == midiInDesc.name)
|
||||
{
|
||||
return new MidiInputDeviceFilter();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const PluginDescription* InternalPluginFormat::getDescriptionFor (const InternalFilterType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case audioInputFilter:
|
||||
return &audioInDesc;
|
||||
case audioOutputFilter:
|
||||
return &audioOutDesc;
|
||||
case midiInputFilter:
|
||||
return &midiInDesc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void InternalPluginFormat::getAllTypes (OwnedArray <PluginDescription>& results)
|
||||
{
|
||||
for (int i = 0; i < (int) endOfFilterTypes; ++i)
|
||||
results.add (new PluginDescription (*getDescriptionFor ((InternalFilterType) i)));
|
||||
}
|
||||
80
extras/audio plugin host/src/host/InternalFilters.h
Normal file
80
extras/audio plugin host/src/host/InternalFilters.h
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
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_MAINHOSTWINDOW_JUCEHEADER__xxxxx
|
||||
#define __JUCE_MAINHOSTWINDOW_JUCEHEADER__xxxxx
|
||||
|
||||
#include "FilterGraph.h"
|
||||
#include "../plugins/juce_AudioPluginFormat.h"
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Manages the internal plugin types.
|
||||
*/
|
||||
class InternalPluginFormat : public AudioPluginFormat
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
InternalPluginFormat();
|
||||
~InternalPluginFormat() {}
|
||||
|
||||
//==============================================================================
|
||||
enum InternalFilterType
|
||||
{
|
||||
audioInputFilter = 0,
|
||||
audioOutputFilter,
|
||||
midiInputFilter,
|
||||
|
||||
endOfFilterTypes
|
||||
};
|
||||
|
||||
const PluginDescription* getDescriptionFor (const InternalFilterType type);
|
||||
|
||||
void getAllTypes (OwnedArray <PluginDescription>& results);
|
||||
|
||||
//==============================================================================
|
||||
const String getName() const { return "Internal"; }
|
||||
bool fileMightContainThisPluginType (const File&) { return false; }
|
||||
const FileSearchPath getDefaultLocationsToSearch() { return FileSearchPath(); }
|
||||
void findAllTypesForFile (OwnedArray <PluginDescription>&, const File&) {}
|
||||
AudioPluginInstance* createInstanceFromDescription (const PluginDescription& desc);
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
PluginDescription audioInDesc;
|
||||
PluginDescription audioOutDesc;
|
||||
PluginDescription midiInDesc;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
484
extras/audio plugin host/src/host/MainHostWindow.cpp
Normal file
484
extras/audio plugin host/src/host/MainHostWindow.cpp
Normal file
|
|
@ -0,0 +1,484 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
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.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../../../juce.h"
|
||||
#include "MainHostWindow.h"
|
||||
#include "InternalFilters.h"
|
||||
#include "../plugins/juce_PluginListComponent.h"
|
||||
|
||||
//==============================================================================
|
||||
class PluginListWindow : public DocumentWindow
|
||||
{
|
||||
public:
|
||||
PluginListWindow (KnownPluginList& knownPluginList)
|
||||
: DocumentWindow ("Available Plugins", Colours::white,
|
||||
DocumentWindow::minimiseButton | DocumentWindow::closeButton)
|
||||
{
|
||||
currentPluginListWindow = this;
|
||||
|
||||
const File deadMansPedalFile (ApplicationProperties::getInstance()->getUserSettings()
|
||||
->getFile().getSiblingFile ("RecentlyCrashedPluginsList"));
|
||||
|
||||
setContentComponent (new PluginListComponent (knownPluginList,
|
||||
deadMansPedalFile,
|
||||
ApplicationProperties::getInstance()->getUserSettings()), true, true);
|
||||
|
||||
setResizable (true, false);
|
||||
setVisible (true);
|
||||
setResizeLimits (300, 400, 800, 1500);
|
||||
setTopLeftPosition (60, 60);
|
||||
|
||||
restoreWindowStateFromString (ApplicationProperties::getInstance()->getUserSettings()->getValue ("listWindowPos"));
|
||||
}
|
||||
|
||||
~PluginListWindow()
|
||||
{
|
||||
ApplicationProperties::getInstance()->getUserSettings()->setValue ("listWindowPos", getWindowStateAsString());
|
||||
|
||||
setContentComponent (0);
|
||||
|
||||
jassert (currentPluginListWindow == this);
|
||||
currentPluginListWindow = 0;
|
||||
}
|
||||
|
||||
void closeButtonPressed()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
static PluginListWindow* currentPluginListWindow;
|
||||
};
|
||||
|
||||
PluginListWindow* PluginListWindow::currentPluginListWindow = 0;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
MainHostWindow::MainHostWindow()
|
||||
: DocumentWindow (JUCEApplication::getInstance()->getApplicationName(), Colours::lightgrey,
|
||||
DocumentWindow::allButtons)
|
||||
{
|
||||
setResizable (true, false);
|
||||
setResizeLimits (500, 400, 10000, 10000);
|
||||
centreWithSize (800, 600);
|
||||
|
||||
setContentComponent (new GraphDocumentComponent (&deviceManager));
|
||||
|
||||
restoreWindowStateFromString (ApplicationProperties::getInstance()->getUserSettings()->getValue ("mainWindowPos"));
|
||||
|
||||
#if JUCE_MAC
|
||||
setMacMainMenu (this);
|
||||
#else
|
||||
setMenuBar (this);
|
||||
#endif
|
||||
|
||||
setVisible (true);
|
||||
|
||||
InternalPluginFormat internalFormat;
|
||||
internalFormat.getAllTypes (internalTypes);
|
||||
|
||||
XmlElement* const savedAudioState = ApplicationProperties::getInstance()->getUserSettings()
|
||||
->getXmlValue (T("audioDeviceState"));
|
||||
|
||||
deviceManager.initialise (256, 256, savedAudioState, true);
|
||||
|
||||
delete savedAudioState;
|
||||
|
||||
XmlElement* const savedPluginList = ApplicationProperties::getInstance()
|
||||
->getUserSettings()
|
||||
->getXmlValue (T("pluginList"));
|
||||
|
||||
if (savedPluginList != 0)
|
||||
{
|
||||
knownPluginList.recreateFromXml (*savedPluginList);
|
||||
delete savedPluginList;
|
||||
}
|
||||
|
||||
pluginSortMethod = (KnownPluginList::SortMethod) ApplicationProperties::getInstance()->getUserSettings()
|
||||
->getIntValue (T("pluginSortMethod"), KnownPluginList::sortByManufacturer);
|
||||
|
||||
knownPluginList.addChangeListener (this);
|
||||
|
||||
addKeyListener (commandManager->getKeyMappings());
|
||||
}
|
||||
|
||||
MainHostWindow::~MainHostWindow()
|
||||
{
|
||||
delete PluginListWindow::currentPluginListWindow;
|
||||
|
||||
#if JUCE_MAC
|
||||
setMacMainMenu (0);
|
||||
#else
|
||||
setMenuBar (0);
|
||||
#endif
|
||||
|
||||
knownPluginList.removeChangeListener (this);
|
||||
|
||||
ApplicationProperties::getInstance()->getUserSettings()->setValue ("mainWindowPos", getWindowStateAsString());
|
||||
setContentComponent (0);
|
||||
}
|
||||
|
||||
void MainHostWindow::closeButtonPressed()
|
||||
{
|
||||
tryToQuitApplication();
|
||||
}
|
||||
|
||||
bool MainHostWindow::tryToQuitApplication()
|
||||
{
|
||||
if (getGraphEditor() != 0
|
||||
&& getGraphEditor()->graph.saveIfNeededAndUserAgrees() == FileBasedDocument::savedOk)
|
||||
{
|
||||
JUCEApplication::quit();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MainHostWindow::changeListenerCallback (void*)
|
||||
{
|
||||
menuItemsChanged();
|
||||
|
||||
// save the plugin list every time it gets chnaged, so that if we're scanning
|
||||
// and it crashes, we've still saved the previous ones
|
||||
XmlElement* const savedPluginList = knownPluginList.createXml();
|
||||
|
||||
if (savedPluginList != 0)
|
||||
{
|
||||
ApplicationProperties::getInstance()->getUserSettings()
|
||||
->setValue (T("pluginList"), savedPluginList);
|
||||
|
||||
delete savedPluginList;
|
||||
|
||||
ApplicationProperties::getInstance()->saveIfNeeded();
|
||||
}
|
||||
}
|
||||
|
||||
const StringArray MainHostWindow::getMenuBarNames()
|
||||
{
|
||||
const tchar* const names[] = { T("File"), T("Plugins"), T("Options"), 0 };
|
||||
|
||||
return StringArray ((const tchar**) names);
|
||||
}
|
||||
|
||||
const PopupMenu MainHostWindow::getMenuForIndex (int topLevelMenuIndex, const String& /*menuName*/)
|
||||
{
|
||||
PopupMenu menu;
|
||||
|
||||
if (topLevelMenuIndex == 0)
|
||||
{
|
||||
// "File" menu
|
||||
menu.addCommandItem (commandManager, CommandIDs::open);
|
||||
|
||||
RecentlyOpenedFilesList recentFiles;
|
||||
recentFiles.restoreFromString (ApplicationProperties::getInstance()->getUserSettings()
|
||||
->getValue ("recentFilterGraphFiles"));
|
||||
|
||||
PopupMenu recentFilesMenu;
|
||||
recentFiles.createPopupMenuItems (recentFilesMenu, 100, true, true);
|
||||
menu.addSubMenu (T("Open recent file"), recentFilesMenu);
|
||||
|
||||
menu.addCommandItem (commandManager, CommandIDs::save);
|
||||
menu.addCommandItem (commandManager, CommandIDs::saveAs);
|
||||
menu.addSeparator();
|
||||
menu.addCommandItem (commandManager, StandardApplicationCommandIDs::quit);
|
||||
}
|
||||
else if (topLevelMenuIndex == 1)
|
||||
{
|
||||
// "Plugins" menu
|
||||
PopupMenu pluginsMenu;
|
||||
addPluginsToMenu (pluginsMenu);
|
||||
menu.addSubMenu (T("Create plugin"), pluginsMenu);
|
||||
menu.addSeparator();
|
||||
menu.addItem (250, T("Delete all plugins"));
|
||||
|
||||
}
|
||||
else if (topLevelMenuIndex == 2)
|
||||
{
|
||||
// "Options" menu
|
||||
|
||||
menu.addCommandItem (commandManager, CommandIDs::showPluginListEditor);
|
||||
|
||||
PopupMenu sortTypeMenu;
|
||||
sortTypeMenu.addItem (200, "List plugins in default order", true, pluginSortMethod == KnownPluginList::defaultOrder);
|
||||
sortTypeMenu.addItem (201, "List plugins in alphabetical order", true, pluginSortMethod == KnownPluginList::sortAlphabetically);
|
||||
sortTypeMenu.addItem (202, "List plugins by category", true, pluginSortMethod == KnownPluginList::sortByCategory);
|
||||
sortTypeMenu.addItem (203, "List plugins by manufacturer", true, pluginSortMethod == KnownPluginList::sortByManufacturer);
|
||||
menu.addSubMenu ("Plugin menu type", sortTypeMenu);
|
||||
|
||||
menu.addSeparator();
|
||||
menu.addCommandItem (commandManager, CommandIDs::showAudioSettings);
|
||||
|
||||
menu.addSeparator();
|
||||
menu.addCommandItem (commandManager, CommandIDs::aboutBox);
|
||||
}
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
void MainHostWindow::menuItemSelected (int menuItemID, int /*topLevelMenuIndex*/)
|
||||
{
|
||||
GraphDocumentComponent* const graphEditor = getGraphEditor();
|
||||
|
||||
if (menuItemID == 250)
|
||||
{
|
||||
if (graphEditor != 0)
|
||||
graphEditor->graph.clear();
|
||||
}
|
||||
else if (menuItemID >= 100 && menuItemID < 200)
|
||||
{
|
||||
RecentlyOpenedFilesList recentFiles;
|
||||
recentFiles.restoreFromString (ApplicationProperties::getInstance()->getUserSettings()
|
||||
->getValue ("recentFilterGraphFiles"));
|
||||
|
||||
if (graphEditor != 0 && graphEditor->graph.saveIfNeededAndUserAgrees() == FileBasedDocument::savedOk)
|
||||
graphEditor->graph.loadFrom (recentFiles.getFile (menuItemID - 100), true);
|
||||
}
|
||||
else if (menuItemID >= 200 && menuItemID < 210)
|
||||
{
|
||||
if (menuItemID == 200)
|
||||
pluginSortMethod = KnownPluginList::defaultOrder;
|
||||
else if (menuItemID == 201)
|
||||
pluginSortMethod = KnownPluginList::sortAlphabetically;
|
||||
else if (menuItemID == 202)
|
||||
pluginSortMethod = KnownPluginList::sortByCategory;
|
||||
else if (menuItemID == 203)
|
||||
pluginSortMethod = KnownPluginList::sortByManufacturer;
|
||||
|
||||
ApplicationProperties::getInstance()->getUserSettings()
|
||||
->setValue (T("pluginSortMethod"), (int) pluginSortMethod);
|
||||
}
|
||||
else
|
||||
{
|
||||
createPlugin (getChosenType (menuItemID),
|
||||
proportionOfWidth (0.3f + Random::getSystemRandom().nextFloat() * 0.6f),
|
||||
proportionOfHeight (0.3f + Random::getSystemRandom().nextFloat() * 0.6f));
|
||||
}
|
||||
}
|
||||
|
||||
void MainHostWindow::createPlugin (const PluginDescription* desc, int x, int y)
|
||||
{
|
||||
GraphDocumentComponent* const graphEditor = getGraphEditor();
|
||||
|
||||
if (graphEditor != 0)
|
||||
graphEditor->createNewPlugin (desc, x, y);
|
||||
}
|
||||
|
||||
void MainHostWindow::addPluginsToMenu (PopupMenu& m) const
|
||||
{
|
||||
for (int i = 0; i < internalTypes.size(); ++i)
|
||||
m.addItem (i + 1, internalTypes.getUnchecked(i)->name);
|
||||
|
||||
m.addSeparator();
|
||||
|
||||
knownPluginList.addToMenu (m, pluginSortMethod);
|
||||
}
|
||||
|
||||
const PluginDescription* MainHostWindow::getChosenType (const int menuID) const
|
||||
{
|
||||
if (menuID >= 1 && menuID < 1 + internalTypes.size())
|
||||
{
|
||||
return internalTypes [menuID - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
return knownPluginList.getType (knownPluginList.getIndexChosenByMenu (menuID));
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
ApplicationCommandTarget* MainHostWindow::getNextCommandTarget()
|
||||
{
|
||||
return findFirstTargetParentComponent();
|
||||
}
|
||||
|
||||
void MainHostWindow::getAllCommands (Array <CommandID>& commands)
|
||||
{
|
||||
// this returns the set of all commands that this target can perform..
|
||||
const CommandID ids[] = { CommandIDs::open,
|
||||
CommandIDs::save,
|
||||
CommandIDs::saveAs,
|
||||
CommandIDs::showPluginListEditor,
|
||||
CommandIDs::showAudioSettings,
|
||||
CommandIDs::aboutBox
|
||||
};
|
||||
|
||||
commands.addArray (ids, numElementsInArray (ids));
|
||||
}
|
||||
|
||||
void MainHostWindow::getCommandInfo (const CommandID commandID, ApplicationCommandInfo& result)
|
||||
{
|
||||
const String category ("General");
|
||||
|
||||
switch (commandID)
|
||||
{
|
||||
case CommandIDs::open:
|
||||
result.setInfo (T("Open..."),
|
||||
T("Opens a filter graph file"),
|
||||
category, 0);
|
||||
result.defaultKeypresses.add (KeyPress (T('o'), ModifierKeys::commandModifier, 0));
|
||||
break;
|
||||
|
||||
case CommandIDs::save:
|
||||
result.setInfo (T("Save"),
|
||||
T("Saves the current graph to a file"),
|
||||
category, 0);
|
||||
result.defaultKeypresses.add (KeyPress (T('s'), ModifierKeys::commandModifier, 0));
|
||||
break;
|
||||
|
||||
case CommandIDs::saveAs:
|
||||
result.setInfo (T("Save As..."),
|
||||
T("Saves a copy of the current graph to a file"),
|
||||
category, 0);
|
||||
result.defaultKeypresses.add (KeyPress (T('s'), ModifierKeys::shiftModifier | ModifierKeys::commandModifier, 0));
|
||||
break;
|
||||
|
||||
case CommandIDs::showPluginListEditor:
|
||||
result.setInfo ("Edit the list of available plug-Ins...", String::empty, category, 0);
|
||||
result.addDefaultKeypress (T('p'), ModifierKeys::commandModifier);
|
||||
break;
|
||||
|
||||
case CommandIDs::showAudioSettings:
|
||||
result.setInfo ("Change the audio device settings", String::empty, category, 0);
|
||||
result.addDefaultKeypress (T('a'), ModifierKeys::commandModifier);
|
||||
break;
|
||||
|
||||
case CommandIDs::aboutBox:
|
||||
result.setInfo ("About...", String::empty, category, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool MainHostWindow::perform (const InvocationInfo& info)
|
||||
{
|
||||
GraphDocumentComponent* const graphEditor = getGraphEditor();
|
||||
|
||||
switch (info.commandID)
|
||||
{
|
||||
case CommandIDs::open:
|
||||
if (graphEditor != 0 && graphEditor->graph.saveIfNeededAndUserAgrees() == FileBasedDocument::savedOk)
|
||||
graphEditor->graph.loadFromUserSpecifiedFile (true);
|
||||
|
||||
break;
|
||||
|
||||
case CommandIDs::save:
|
||||
if (graphEditor != 0)
|
||||
graphEditor->graph.save (true, true);
|
||||
break;
|
||||
|
||||
case CommandIDs::saveAs:
|
||||
if (graphEditor != 0)
|
||||
graphEditor->graph.saveAs (File::nonexistent, true, true, true);
|
||||
break;
|
||||
|
||||
case CommandIDs::showPluginListEditor:
|
||||
if (PluginListWindow::currentPluginListWindow == 0)
|
||||
PluginListWindow::currentPluginListWindow = new PluginListWindow (knownPluginList);
|
||||
|
||||
PluginListWindow::currentPluginListWindow->toFront (true);
|
||||
break;
|
||||
|
||||
case CommandIDs::showAudioSettings:
|
||||
showAudioSettings();
|
||||
break;
|
||||
|
||||
case CommandIDs::aboutBox:
|
||||
{
|
||||
/* AboutBoxComponent aboutComp;
|
||||
|
||||
DialogWindow::showModalDialog (T("About"),
|
||||
&aboutComp,
|
||||
this, Colours::white,
|
||||
true, false, false);
|
||||
*/ }
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MainHostWindow::showAudioSettings()
|
||||
{
|
||||
AudioDeviceSelectorComponent audioSettingsComp (deviceManager,
|
||||
0, 2,
|
||||
0, 2,
|
||||
false);
|
||||
|
||||
audioSettingsComp.setSize (500, 300);
|
||||
|
||||
DialogWindow::showModalDialog (T("Audio Settings"),
|
||||
&audioSettingsComp,
|
||||
this,
|
||||
Colours::azure,
|
||||
true);
|
||||
|
||||
XmlElement* const audioState = deviceManager.createStateXml();
|
||||
|
||||
ApplicationProperties::getInstance()->getUserSettings()
|
||||
->setValue (T("audioSettings"), audioState);
|
||||
|
||||
ApplicationProperties::getInstance()->getUserSettings()->saveIfNeeded();
|
||||
|
||||
delete audioState;
|
||||
}
|
||||
|
||||
bool MainHostWindow::filesDropped (const StringArray& files, int x, int y)
|
||||
{
|
||||
if (files.size() == 1 && File (files[0]).hasFileExtension (filenameSuffix))
|
||||
{
|
||||
GraphDocumentComponent* const graphEditor = getGraphEditor();
|
||||
|
||||
if (graphEditor == 0)
|
||||
return false;
|
||||
|
||||
return graphEditor->graph.saveIfNeededAndUserAgrees() == FileBasedDocument::savedOk
|
||||
&& graphEditor->graph.loadFrom (File (files[0]), true);
|
||||
}
|
||||
|
||||
OwnedArray <PluginDescription> typesFound;
|
||||
knownPluginList.scanAndAddDragAndDroppedFiles (files, typesFound);
|
||||
|
||||
for (int i = 0; i < jmin (5, typesFound.size()); ++i)
|
||||
createPlugin (typesFound.getUnchecked(i), x, y);
|
||||
|
||||
return typesFound.size() > 0;
|
||||
}
|
||||
|
||||
GraphDocumentComponent* MainHostWindow::getGraphEditor() const
|
||||
{
|
||||
return dynamic_cast <GraphDocumentComponent*> (getContentComponent());
|
||||
}
|
||||
103
extras/audio plugin host/src/host/MainHostWindow.h
Normal file
103
extras/audio plugin host/src/host/MainHostWindow.h
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
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_MAINHOSTWINDOW_JUCEHEADER__
|
||||
#define __JUCE_MAINHOSTWINDOW_JUCEHEADER__
|
||||
|
||||
#include "FilterGraph.h"
|
||||
#include "GraphEditorPanel.h"
|
||||
#include "../plugins/juce_KnownPluginList.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
namespace CommandIDs
|
||||
{
|
||||
static const int open = 0x30000;
|
||||
static const int save = 0x30001;
|
||||
static const int saveAs = 0x30002;
|
||||
static const int showPluginListEditor = 0x30100;
|
||||
static const int showAudioSettings = 0x30200;
|
||||
static const int aboutBox = 0x30300;
|
||||
}
|
||||
|
||||
extern ApplicationCommandManager* commandManager;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
*/
|
||||
class MainHostWindow : public DocumentWindow,
|
||||
public MenuBarModel,
|
||||
public ApplicationCommandTarget,
|
||||
public ChangeListener
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
MainHostWindow();
|
||||
~MainHostWindow();
|
||||
|
||||
//==============================================================================
|
||||
void closeButtonPressed();
|
||||
void changeListenerCallback (void*);
|
||||
bool filesDropped (const StringArray& filenames, int x, int y);
|
||||
|
||||
const StringArray getMenuBarNames();
|
||||
const PopupMenu getMenuForIndex (int topLevelMenuIndex, const String& menuName);
|
||||
void menuItemSelected (int menuItemID, int topLevelMenuIndex);
|
||||
ApplicationCommandTarget* getNextCommandTarget();
|
||||
void getAllCommands (Array <CommandID>& commands);
|
||||
void getCommandInfo (const CommandID commandID, ApplicationCommandInfo& result);
|
||||
bool perform (const InvocationInfo& info);
|
||||
|
||||
bool tryToQuitApplication();
|
||||
|
||||
void createPlugin (const PluginDescription* desc, int x, int y);
|
||||
|
||||
void addPluginsToMenu (PopupMenu& m) const;
|
||||
const PluginDescription* getChosenType (const int menuID) const;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
AudioDeviceManager deviceManager;
|
||||
|
||||
OwnedArray <PluginDescription> internalTypes;
|
||||
KnownPluginList knownPluginList;
|
||||
KnownPluginList::SortMethod pluginSortMethod;
|
||||
|
||||
void showAudioSettings();
|
||||
GraphDocumentComponent* getGraphEditor() const;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
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.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../../../juce.h"
|
||||
#include "juce_AudioPluginFormat.h"
|
||||
#include "vst/juce_VSTPluginFormat.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
AudioPluginFormatManager::AudioPluginFormatManager() throw()
|
||||
{
|
||||
}
|
||||
|
||||
AudioPluginFormatManager::~AudioPluginFormatManager() throw()
|
||||
{
|
||||
}
|
||||
|
||||
juce_ImplementSingleton_SingleThreaded (AudioPluginFormatManager);
|
||||
|
||||
//==============================================================================
|
||||
void AudioPluginFormatManager::addDefaultFormats()
|
||||
{
|
||||
#ifdef JUCE_DEBUG
|
||||
// you should only call this method once!
|
||||
for (int i = formats.size(); --i >= 0;)
|
||||
jassert (dynamic_cast <VSTPluginFormat*> (formats[i]) == 0);
|
||||
#endif
|
||||
|
||||
formats.add (new VSTPluginFormat());
|
||||
}
|
||||
|
||||
int AudioPluginFormatManager::getNumFormats() throw()
|
||||
{
|
||||
return formats.size();
|
||||
}
|
||||
|
||||
AudioPluginFormat* AudioPluginFormatManager::getFormat (const int index) throw()
|
||||
{
|
||||
return formats [index];
|
||||
}
|
||||
|
||||
void AudioPluginFormatManager::addFormat (AudioPluginFormat* const format) throw()
|
||||
{
|
||||
formats.add (format);
|
||||
}
|
||||
154
extras/audio plugin host/src/plugins/juce_AudioPluginFormat.h
Normal file
154
extras/audio plugin host/src/plugins/juce_AudioPluginFormat.h
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
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_AUDIOPLUGINFORMAT_JUCEHEADER__
|
||||
#define __JUCE_AUDIOPLUGINFORMAT_JUCEHEADER__
|
||||
|
||||
#include "juce_AudioPluginInstance.h"
|
||||
class PluginDescription;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
The base class for a type of plugin format, such as VST, AudioUnit, LADSPA, etc.
|
||||
|
||||
Use the static getNumFormats() and getFormat() calls to find the types
|
||||
of format that are available.
|
||||
*/
|
||||
class AudioPluginFormat
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Destructor. */
|
||||
virtual ~AudioPluginFormat() {}
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the format name.
|
||||
|
||||
E.g. "VST", "AudioUnit", etc.
|
||||
*/
|
||||
virtual const String getName() const = 0;
|
||||
|
||||
/** This tries to create descriptions for all the plugin types available in
|
||||
a binary module file.
|
||||
|
||||
The file will be some kind of DLL or bundle.
|
||||
|
||||
Normally there will only be one type returned, but some plugins
|
||||
(e.g. VST shells) can use a single DLL to create a set of different plugin
|
||||
subtypes, so in that case, each subtype is returned as a separate object.
|
||||
*/
|
||||
virtual void findAllTypesForFile (OwnedArray <PluginDescription>& results,
|
||||
const File& file) = 0;
|
||||
|
||||
/** Tries to recreate a type from a previously generated PluginDescription.
|
||||
|
||||
@see PluginDescription::createInstance
|
||||
*/
|
||||
virtual AudioPluginInstance* createInstanceFromDescription (const PluginDescription& desc) = 0;
|
||||
|
||||
/** Should do a quick check to see if this file or directory might be a plugin of
|
||||
this format.
|
||||
|
||||
This is for searching for potential files, so it shouldn't actually try to
|
||||
load the plugin or do anything time-consuming.
|
||||
*/
|
||||
virtual bool fileMightContainThisPluginType (const File& file) = 0;
|
||||
|
||||
/** Returns the typical places to look for this kind of plugin.
|
||||
|
||||
Note that if this returns no paths, it means that the format can't be scanned-for
|
||||
(i.e. it's an internal format that doesn't live in files)
|
||||
*/
|
||||
virtual const FileSearchPath getDefaultLocationsToSearch() = 0;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
|
||||
protected:
|
||||
AudioPluginFormat() throw() {}
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
This simply maintains a list of known AudioPluginFormats.
|
||||
|
||||
@see AudioPluginFormat
|
||||
*/
|
||||
class AudioPluginFormatManager : public DeletedAtShutdown
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
AudioPluginFormatManager() throw();
|
||||
|
||||
/** Destructor. */
|
||||
~AudioPluginFormatManager() throw();
|
||||
|
||||
juce_DeclareSingleton_SingleThreaded (AudioPluginFormatManager, false);
|
||||
|
||||
//==============================================================================
|
||||
/** Adds any formats that it knows about, e.g. VST.
|
||||
*/
|
||||
void addDefaultFormats();
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the number of types of format that are available.
|
||||
|
||||
Use getFormat() to get one of them.
|
||||
*/
|
||||
int getNumFormats() throw();
|
||||
|
||||
/** Returns one of the available formats.
|
||||
|
||||
@see getNumFormats
|
||||
*/
|
||||
AudioPluginFormat* getFormat (const int index) throw();
|
||||
|
||||
//==============================================================================
|
||||
/** Adds a format to the list.
|
||||
|
||||
The object passed in will be owned and deleted by the manager.
|
||||
*/
|
||||
void addFormat (AudioPluginFormat* const format) throw();
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
OwnedArray <AudioPluginFormat> formats;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // __JUCE_AUDIOPLUGINFORMAT_JUCEHEADER__
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
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.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#define JUCE_PLUGIN_HOST 1
|
||||
|
||||
//==============================================================================
|
||||
// (Just a quick way of getting these files into the project)
|
||||
#include "../../../audio plugins/wrapper/juce_AudioFilterBase.cpp"
|
||||
#include "../../../audio plugins/wrapper/juce_AudioFilterEditor.cpp"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
#include "juce_AudioPluginInstance.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
bool JUCE_CALLTYPE AudioPluginInstance::getCurrentPositionInfo (AudioFilterBase::CurrentPositionInfo& info)
|
||||
{
|
||||
info.bpm = 120.0;
|
||||
info.timeSigNumerator = 4;
|
||||
info.timeSigDenominator = 4;
|
||||
|
||||
info.timeInSeconds = 0;
|
||||
|
||||
/** For timecode, the position of the start of the edit, in seconds from 00:00:00:00. */
|
||||
info.editOriginTime = 0;
|
||||
|
||||
/** The current play position in pulses-per-quarter-note.
|
||||
This is the number of quarter notes since the edit start.
|
||||
*/
|
||||
info.ppqPosition = 0;
|
||||
|
||||
/** The position of the start of the last bar, in pulses-per-quarter-note.
|
||||
|
||||
This is the number of quarter notes from the start of the edit to the
|
||||
start of the current bar.
|
||||
|
||||
Note - this value may be unavailable on some hosts, e.g. Pro-Tools. If
|
||||
it's not available, the value will be 0.
|
||||
*/
|
||||
info.ppqPositionOfLastBarStart = 0;
|
||||
|
||||
info.frameRate = AudioFilterBase::CurrentPositionInfo::fpsUnknown;
|
||||
|
||||
info.isPlaying = false;
|
||||
info.isRecording = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void JUCE_CALLTYPE AudioPluginInstance::informHostOfParameterChange (int /*index*/, float /*newValue*/)
|
||||
{
|
||||
|
||||
}
|
||||
123
extras/audio plugin host/src/plugins/juce_AudioPluginInstance.h
Normal file
123
extras/audio plugin host/src/plugins/juce_AudioPluginInstance.h
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
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_AUDIOPLUGININSTANCE_JUCEHEADER__
|
||||
#define __JUCE_AUDIOPLUGININSTANCE_JUCEHEADER__
|
||||
|
||||
#include "../../../audio plugins/wrapper/juce_AudioFilterBase.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Base class for an active instance of a plugin.
|
||||
|
||||
This derives from the same AudioFilterBase object that is used in the
|
||||
plugin wrapper code, and most of its functionality is exposed by that interface,
|
||||
with just a few extra methods here for using it from the host side.
|
||||
|
||||
@see AudioFilterBase, AudioPluginFormat
|
||||
*/
|
||||
class AudioPluginInstance : public AudioFilterBase,
|
||||
private AudioFilterBase::FilterNativeCallbacks
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Destructor.
|
||||
|
||||
Make sure that you delete any UI components that belong to this plugin before
|
||||
deleting the plugin.
|
||||
*/
|
||||
virtual ~AudioPluginInstance() {}
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the plugin's name. */
|
||||
virtual const String getName() const = 0;
|
||||
|
||||
/** Asks the plugin to supply a manufacturer name. */
|
||||
virtual const String getManufacturer() const = 0;
|
||||
|
||||
/** Asks the plugin for its version number. */
|
||||
virtual const String getVersion() const = 0;
|
||||
|
||||
/** Returns true if the plugin is an instrument rather than an effect. */
|
||||
virtual bool isInstrument() const = 0;
|
||||
|
||||
/** Returns a category description for the plugin.
|
||||
|
||||
E.g. "Dynamics", "Reverbs", etc.
|
||||
*/
|
||||
virtual const String getCategory() const = 0;
|
||||
|
||||
/** Returns the class of plugin to which this belongs.
|
||||
|
||||
E.g. "VST", "AU", etc
|
||||
*/
|
||||
virtual const String getFormatName() const = 0;
|
||||
|
||||
/** Returns the binary file containing the plugin.
|
||||
|
||||
This is normally the DLL or bundle file.
|
||||
*/
|
||||
virtual const File getFile() const = 0;
|
||||
|
||||
/** Returns a unique identifier for the plugin.
|
||||
|
||||
(Note that this may not be unique across different plugin formats).
|
||||
*/
|
||||
virtual int getUID() const = 0;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** Returns true if the plugin wants midi messages. */
|
||||
virtual bool acceptsMidi() const = 0;
|
||||
|
||||
/** Returns true if the plugin produces midi messages. */
|
||||
virtual bool producesMidi() const = 0;
|
||||
|
||||
/** Returns the plugin's latency.
|
||||
|
||||
This may not always be fixed, but should be correct just after the filter
|
||||
has been prepared for playback.
|
||||
*/
|
||||
virtual int getSamplesLatency() const = 0;
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
protected:
|
||||
AudioPluginInstance() {}
|
||||
|
||||
bool JUCE_CALLTYPE getCurrentPositionInfo (AudioFilterBase::CurrentPositionInfo& info);
|
||||
void JUCE_CALLTYPE informHostOfParameterChange (int index, float newValue);
|
||||
};
|
||||
|
||||
|
||||
#endif // __JUCE_AUDIOPLUGININSTANCE_JUCEHEADER__
|
||||
314
extras/audio plugin host/src/plugins/juce_KnownPluginList.cpp
Normal file
314
extras/audio plugin host/src/plugins/juce_KnownPluginList.cpp
Normal file
|
|
@ -0,0 +1,314 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
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.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../../../juce.h"
|
||||
#include "juce_KnownPluginList.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
KnownPluginList::KnownPluginList()
|
||||
{
|
||||
}
|
||||
|
||||
KnownPluginList::~KnownPluginList()
|
||||
{
|
||||
}
|
||||
|
||||
void KnownPluginList::clear()
|
||||
{
|
||||
if (types.size() > 0)
|
||||
{
|
||||
types.clear();
|
||||
sendChangeMessage (this);
|
||||
}
|
||||
}
|
||||
|
||||
PluginDescription* KnownPluginList::getTypeForFile (const File& file) const throw()
|
||||
{
|
||||
for (int i = 0; i < types.size(); ++i)
|
||||
if (types.getUnchecked(i)->file == file)
|
||||
return types.getUnchecked(i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool KnownPluginList::addType (const PluginDescription& type)
|
||||
{
|
||||
for (int i = types.size(); --i >= 0;)
|
||||
{
|
||||
if (types.getUnchecked(i)->isDuplicateOf (type))
|
||||
{
|
||||
// strange - found a duplicate plugin with different info..
|
||||
jassert (types.getUnchecked(i)->name == type.name);
|
||||
jassert (types.getUnchecked(i)->isInstrument == type.isInstrument);
|
||||
|
||||
*types.getUnchecked(i) = type;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
types.add (new PluginDescription (type));
|
||||
sendChangeMessage (this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void KnownPluginList::removeType (const int index) throw()
|
||||
{
|
||||
types.remove (index);
|
||||
sendChangeMessage (this);
|
||||
}
|
||||
|
||||
bool KnownPluginList::isListingUpToDate (const File& possiblePluginFile) const throw()
|
||||
{
|
||||
if (getTypeForFile (possiblePluginFile) == 0)
|
||||
return false;
|
||||
|
||||
for (int i = types.size(); --i >= 0;)
|
||||
{
|
||||
const PluginDescription* const d = types.getUnchecked(i);
|
||||
|
||||
if (d->file == possiblePluginFile
|
||||
&& d->lastFileModTime != possiblePluginFile.getLastModificationTime())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool KnownPluginList::scanAndAddFile (const File& possiblePluginFile,
|
||||
const bool dontRescanIfAlreadyInList,
|
||||
OwnedArray <PluginDescription>& typesFound)
|
||||
{
|
||||
bool addedOne = false;
|
||||
|
||||
if (dontRescanIfAlreadyInList
|
||||
&& getTypeForFile (possiblePluginFile) != 0)
|
||||
{
|
||||
bool needsRescanning = false;
|
||||
|
||||
for (int i = types.size(); --i >= 0;)
|
||||
{
|
||||
const PluginDescription* const d = types.getUnchecked(i);
|
||||
|
||||
if (d->file == possiblePluginFile
|
||||
&& d->lastFileModTime != possiblePluginFile.getLastModificationTime())
|
||||
{
|
||||
needsRescanning = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
typesFound.add (new PluginDescription (*d));
|
||||
}
|
||||
}
|
||||
|
||||
if (! needsRescanning)
|
||||
return false;
|
||||
}
|
||||
|
||||
OwnedArray <PluginDescription> found;
|
||||
|
||||
for (int i = 0; i < AudioPluginFormatManager::getInstance()->getNumFormats(); ++i)
|
||||
{
|
||||
AudioPluginFormat* const format = AudioPluginFormatManager::getInstance()->getFormat (i);
|
||||
|
||||
format->findAllTypesForFile (found, possiblePluginFile);
|
||||
|
||||
for (int i = 0; i < found.size(); ++i)
|
||||
{
|
||||
PluginDescription* const desc = found.getUnchecked(i);
|
||||
jassert (desc != 0);
|
||||
|
||||
if (addType (*desc))
|
||||
addedOne = true;
|
||||
|
||||
typesFound.add (new PluginDescription (*desc));
|
||||
}
|
||||
}
|
||||
|
||||
return addedOne;
|
||||
}
|
||||
|
||||
void KnownPluginList::scanAndAddDragAndDroppedFiles (const StringArray& files,
|
||||
OwnedArray <PluginDescription>& typesFound)
|
||||
{
|
||||
for (int i = 0; i < files.size(); ++i)
|
||||
{
|
||||
const File f (files [i]);
|
||||
|
||||
if (! scanAndAddFile (f, false, typesFound))
|
||||
{
|
||||
if (f.isDirectory())
|
||||
{
|
||||
StringArray s;
|
||||
|
||||
{
|
||||
OwnedArray <File> subFiles;
|
||||
f.findChildFiles (subFiles, File::findFilesAndDirectories, false);
|
||||
|
||||
for (int j = 0; j < subFiles.size(); ++j)
|
||||
s.add (subFiles.getUnchecked (j)->getFullPathName());
|
||||
}
|
||||
|
||||
scanAndAddDragAndDroppedFiles (s, typesFound);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
class PluginSorter
|
||||
{
|
||||
public:
|
||||
KnownPluginList::SortMethod method;
|
||||
|
||||
PluginSorter() throw() {}
|
||||
|
||||
int compareElements (const PluginDescription* const first,
|
||||
const PluginDescription* const second) const throw()
|
||||
{
|
||||
int diff = 0;
|
||||
|
||||
if (method == KnownPluginList::sortByCategory)
|
||||
diff = first->category.compareLexicographically (second->category);
|
||||
else if (method == KnownPluginList::sortByManufacturer)
|
||||
diff = first->manufacturerName.compareLexicographically (second->manufacturerName);
|
||||
|
||||
if (diff == 0)
|
||||
diff = first->name.compareLexicographically (second->name);
|
||||
|
||||
return diff;
|
||||
}
|
||||
};
|
||||
|
||||
void KnownPluginList::sort (const SortMethod method)
|
||||
{
|
||||
if (method != defaultOrder)
|
||||
{
|
||||
PluginSorter sorter;
|
||||
sorter.method = method;
|
||||
types.sort (sorter, true);
|
||||
|
||||
sendChangeMessage (this);
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
XmlElement* KnownPluginList::createXml() const
|
||||
{
|
||||
XmlElement* const e = new XmlElement (T("KNOWNPLUGINS"));
|
||||
|
||||
for (int i = 0; i < types.size(); ++i)
|
||||
e->addChildElement (types.getUnchecked(i)->createXml());
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
void KnownPluginList::recreateFromXml (const XmlElement& xml)
|
||||
{
|
||||
clear();
|
||||
|
||||
if (xml.hasTagName (T("KNOWNPLUGINS")))
|
||||
{
|
||||
forEachXmlChildElement (xml, e)
|
||||
{
|
||||
PluginDescription info;
|
||||
|
||||
if (info.loadFromXml (*e))
|
||||
addType (info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
const int menuIdBase = 0x324503f4;
|
||||
|
||||
void KnownPluginList::addToMenu (PopupMenu& menu, const SortMethod sortMethod) const
|
||||
{
|
||||
Array <PluginDescription*> sorted;
|
||||
|
||||
{
|
||||
PluginSorter sorter;
|
||||
sorter.method = sortMethod;
|
||||
|
||||
for (int i = 0; i < types.size(); ++i)
|
||||
sorted.addSorted (sorter, types.getUnchecked(i));
|
||||
}
|
||||
|
||||
if (sortMethod == sortByCategory
|
||||
|| sortMethod == KnownPluginList::sortByManufacturer)
|
||||
{
|
||||
String lastSubMenuName;
|
||||
PopupMenu sub;
|
||||
|
||||
for (int i = 0; i < sorted.size(); ++i)
|
||||
{
|
||||
const PluginDescription* const pd = sorted.getUnchecked(i);
|
||||
String thisSubMenuName (sortMethod == sortByCategory ? pd->category
|
||||
: pd->manufacturerName);
|
||||
|
||||
if (thisSubMenuName.trim().isEmpty())
|
||||
thisSubMenuName = T("Other");
|
||||
|
||||
if (thisSubMenuName != lastSubMenuName)
|
||||
{
|
||||
if (sub.getNumItems() > 0)
|
||||
{
|
||||
menu.addSubMenu (lastSubMenuName, sub);
|
||||
sub.clear();
|
||||
}
|
||||
|
||||
lastSubMenuName = thisSubMenuName;
|
||||
}
|
||||
|
||||
sub.addItem (types.indexOf (pd) + menuIdBase, pd->name, true, false);
|
||||
}
|
||||
|
||||
if (sub.getNumItems() > 0)
|
||||
menu.addSubMenu (lastSubMenuName, sub);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < sorted.size(); ++i)
|
||||
{
|
||||
const PluginDescription* const pd = sorted.getUnchecked(i);
|
||||
menu.addItem (types.indexOf (pd) + menuIdBase, pd->name, true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int KnownPluginList::getIndexChosenByMenu (const int menuResultCode) const
|
||||
{
|
||||
const int i = menuResultCode - menuIdBase;
|
||||
|
||||
return (i >= 0 && i < types.size()) ? i : -1;
|
||||
}
|
||||
163
extras/audio plugin host/src/plugins/juce_KnownPluginList.h
Normal file
163
extras/audio plugin host/src/plugins/juce_KnownPluginList.h
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
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_KNOWNPLUGINLIST_JUCEHEADER__
|
||||
#define __JUCE_KNOWNPLUGINLIST_JUCEHEADER__
|
||||
|
||||
#include "juce_PluginDescription.h"
|
||||
#include "juce_AudioPluginFormat.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Manages a list of plugin types.
|
||||
|
||||
This can be easily edited, saved and loaded, and used to create instances of
|
||||
the plugin types in it.
|
||||
|
||||
@see PluginListComponent
|
||||
*/
|
||||
class KnownPluginList : public ChangeBroadcaster
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates an empty list.
|
||||
*/
|
||||
KnownPluginList();
|
||||
|
||||
/** Destructor. */
|
||||
~KnownPluginList();
|
||||
|
||||
//==============================================================================
|
||||
/** Clears the list. */
|
||||
void clear();
|
||||
|
||||
/** Returns the number of types currently in the list.
|
||||
@see getType
|
||||
*/
|
||||
int getNumTypes() const throw() { return types.size(); }
|
||||
|
||||
/** Returns one of the types.
|
||||
@see getNumTypes
|
||||
*/
|
||||
PluginDescription* getType (const int index) const throw() { return types [index]; }
|
||||
|
||||
/** Looks for a type in the list which comes from this file.
|
||||
*/
|
||||
PluginDescription* getTypeForFile (const File& file) const throw();
|
||||
|
||||
/** Adds a type manually from its description. */
|
||||
bool addType (const PluginDescription& type);
|
||||
|
||||
/** Removes a type. */
|
||||
void removeType (const int index) throw();
|
||||
|
||||
/** Looks for all types that can be loaded from a given file, and adds them
|
||||
to the list.
|
||||
|
||||
If dontRescanIfAlreadyInList is true, then the file will only be loaded and
|
||||
re-tested if it's not already in the list, or if the file's modification
|
||||
time has changed since the list was created. If dontRescanIfAlreadyInList is
|
||||
false, the file will always be reloaded and tested.
|
||||
|
||||
Returns true if any new types were added, and all the types found in this
|
||||
file (even if it was already known and hasn't been re-scanned) get returned
|
||||
in the array.
|
||||
*/
|
||||
bool scanAndAddFile (const File& possiblePluginFile,
|
||||
const bool dontRescanIfAlreadyInList,
|
||||
OwnedArray <PluginDescription>& typesFound);
|
||||
|
||||
/** Returns true if the specified file is already known about and if it
|
||||
hasn't been modified since our entry was created.
|
||||
*/
|
||||
bool isListingUpToDate (const File& possiblePluginFile) const throw();
|
||||
|
||||
/** Scans and adds a bunch of files that might have been dragged-and-dropped.
|
||||
|
||||
If any types are found in the files, their descriptions are returned in the array.
|
||||
*/
|
||||
void scanAndAddDragAndDroppedFiles (const StringArray& filenames,
|
||||
OwnedArray <PluginDescription>& typesFound);
|
||||
|
||||
//==============================================================================
|
||||
/** Sort methods used to change the order of the plugins in the list.
|
||||
*/
|
||||
enum SortMethod
|
||||
{
|
||||
defaultOrder = 0,
|
||||
sortAlphabetically,
|
||||
sortByCategory,
|
||||
sortByManufacturer
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** Adds all the plugin types to a popup menu so that the user can select one.
|
||||
|
||||
Depending on the sort method, it may add sub-menus for categories,
|
||||
manufacturers, etc.
|
||||
|
||||
Use getIndexChosenByMenu() to find out the type that was chosen.
|
||||
*/
|
||||
void addToMenu (PopupMenu& menu,
|
||||
const SortMethod sortMethod) const;
|
||||
|
||||
/** Converts a menu item index that has been chosen into its index in this list.
|
||||
|
||||
Returns -1 if it's not an ID that was used.
|
||||
|
||||
@see addToMenu
|
||||
*/
|
||||
int getIndexChosenByMenu (const int menuResultCode) const;
|
||||
|
||||
//==============================================================================
|
||||
/** Sorts the list. */
|
||||
void sort (const SortMethod method);
|
||||
|
||||
//==============================================================================
|
||||
/** Creates some XML that can be used to store the state of this list.
|
||||
*/
|
||||
XmlElement* createXml() const;
|
||||
|
||||
/** Recreates the state of this list from its stored XML format.
|
||||
*/
|
||||
void recreateFromXml (const XmlElement& xml);
|
||||
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
OwnedArray <PluginDescription> types;
|
||||
};
|
||||
|
||||
|
||||
#endif // __JUCE_KNOWNPLUGINLIST_JUCEHEADER__
|
||||
158
extras/audio plugin host/src/plugins/juce_PluginDescription.cpp
Normal file
158
extras/audio plugin host/src/plugins/juce_PluginDescription.cpp
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
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.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../../../juce.h"
|
||||
#include "juce_PluginDescription.h"
|
||||
#include "juce_AudioPluginFormat.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
PluginDescription::PluginDescription() throw()
|
||||
: uid (0),
|
||||
isInstrument (false),
|
||||
numInputChannels (0),
|
||||
numOutputChannels (0)
|
||||
{
|
||||
}
|
||||
|
||||
PluginDescription::~PluginDescription() throw()
|
||||
{
|
||||
}
|
||||
|
||||
PluginDescription::PluginDescription (const PluginDescription& other) throw()
|
||||
: name (other.name),
|
||||
pluginFormatName (other.pluginFormatName),
|
||||
category (other.category),
|
||||
manufacturerName (other.manufacturerName),
|
||||
version (other.version),
|
||||
file (other.file),
|
||||
uid (other.uid),
|
||||
isInstrument (other.isInstrument),
|
||||
lastFileModTime (other.lastFileModTime),
|
||||
numInputChannels (other.numInputChannels),
|
||||
numOutputChannels (other.numOutputChannels)
|
||||
{
|
||||
}
|
||||
|
||||
const PluginDescription& PluginDescription::operator= (const PluginDescription& other) throw()
|
||||
{
|
||||
name = other.name;
|
||||
pluginFormatName = other.pluginFormatName;
|
||||
category = other.category;
|
||||
manufacturerName = other.manufacturerName;
|
||||
version = other.version;
|
||||
file = other.file;
|
||||
uid = other.uid;
|
||||
isInstrument = other.isInstrument;
|
||||
lastFileModTime = other.lastFileModTime;
|
||||
numInputChannels = other.numInputChannels;
|
||||
numOutputChannels = other.numOutputChannels;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool PluginDescription::isDuplicateOf (const PluginDescription& other) const
|
||||
{
|
||||
return file == other.file
|
||||
&& uid == other.uid;
|
||||
}
|
||||
|
||||
void PluginDescription::fillInFromInstance (AudioPluginInstance& instance) throw()
|
||||
{
|
||||
name = instance.getName();
|
||||
file = instance.getFile();
|
||||
uid = instance.getUID();
|
||||
lastFileModTime = file.getLastModificationTime();
|
||||
pluginFormatName = instance.getFormatName();
|
||||
category = instance.getCategory();
|
||||
manufacturerName = instance.getManufacturer();
|
||||
version = instance.getVersion();
|
||||
numInputChannels = instance.getNumInputChannels();
|
||||
numOutputChannels = instance.getNumOutputChannels();
|
||||
isInstrument = instance.isInstrument();
|
||||
}
|
||||
|
||||
AudioPluginInstance* PluginDescription::createInstance() const
|
||||
{
|
||||
AudioPluginInstance* result = 0;
|
||||
|
||||
for (int i = 0; i < AudioPluginFormatManager::getInstance()->getNumFormats(); ++i)
|
||||
{
|
||||
AudioPluginFormat* const format = AudioPluginFormatManager::getInstance()->getFormat (i);
|
||||
|
||||
result = format->createInstanceFromDescription (*this);
|
||||
|
||||
if (result != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
XmlElement* PluginDescription::createXml() const
|
||||
{
|
||||
XmlElement* const e = new XmlElement (T("PLUGIN"));
|
||||
e->setAttribute (T("name"), name);
|
||||
e->setAttribute (T("format"), pluginFormatName);
|
||||
e->setAttribute (T("category"), category);
|
||||
e->setAttribute (T("manufacturer"), manufacturerName);
|
||||
e->setAttribute (T("version"), version);
|
||||
e->setAttribute (T("file"), file.getFullPathName());
|
||||
e->setAttribute (T("uid"), String::toHexString (uid));
|
||||
e->setAttribute (T("isInstrument"), isInstrument);
|
||||
e->setAttribute (T("fileTime"), String::toHexString (lastFileModTime.toMilliseconds()));
|
||||
e->setAttribute (T("numInputs"), numInputChannels);
|
||||
e->setAttribute (T("numOutputs"), numOutputChannels);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
bool PluginDescription::loadFromXml (const XmlElement& xml)
|
||||
{
|
||||
if (xml.hasTagName (T("PLUGIN")))
|
||||
{
|
||||
name = xml.getStringAttribute (T("name"));
|
||||
pluginFormatName = xml.getStringAttribute (T("format"));
|
||||
category = xml.getStringAttribute (T("category"));
|
||||
manufacturerName = xml.getStringAttribute (T("manufacturer"));
|
||||
version = xml.getStringAttribute (T("version"));
|
||||
file = File (xml.getStringAttribute (T("file")));
|
||||
uid = xml.getStringAttribute (T("uid")).getHexValue32();
|
||||
isInstrument = xml.getBoolAttribute (T("isInstrument"), false);
|
||||
lastFileModTime = Time (xml.getStringAttribute (T("fileTime")).getHexValue64());
|
||||
numInputChannels = xml.getIntAttribute (T("numInputs"));
|
||||
numOutputChannels = xml.getIntAttribute (T("numOutputs"));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
144
extras/audio plugin host/src/plugins/juce_PluginDescription.h
Normal file
144
extras/audio plugin host/src/plugins/juce_PluginDescription.h
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
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_PLUGINDESCRIPTION_JUCEHEADER__
|
||||
#define __JUCE_PLUGINDESCRIPTION_JUCEHEADER__
|
||||
|
||||
#include "juce_AudioPluginInstance.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A small class to represent some facts about a particular type of plugin.
|
||||
|
||||
This class is for storing and managing the details about a plugin without
|
||||
actually having to load an instance of it.
|
||||
|
||||
A KnownPluginList contains a list of PluginDescription objects.
|
||||
|
||||
@see KnownPluginList
|
||||
*/
|
||||
class PluginDescription
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
PluginDescription() throw();
|
||||
PluginDescription (const PluginDescription& other) throw();
|
||||
const PluginDescription& operator= (const PluginDescription& other) throw();
|
||||
~PluginDescription() throw();
|
||||
|
||||
//==============================================================================
|
||||
/** The name of the plugin. */
|
||||
String name;
|
||||
|
||||
/** The plugin format, e.g. "VST", "AudioUnit", etc.
|
||||
*/
|
||||
String pluginFormatName;
|
||||
|
||||
/** A category, such as "Dynamics", "Reverbs", etc.
|
||||
*/
|
||||
String category;
|
||||
|
||||
/** The manufacturer. */
|
||||
String manufacturerName;
|
||||
|
||||
/** The version. This string doesn't have any particular format. */
|
||||
String version;
|
||||
|
||||
/** The binary module file containing the plugin. */
|
||||
File file;
|
||||
|
||||
/** The last time the plugin file was changed.
|
||||
This is handy when scanning for new or changed plugins.
|
||||
*/
|
||||
Time lastFileModTime;
|
||||
|
||||
/** A unique ID for the plugin.
|
||||
|
||||
Note that this might not be unique between formats, e.g. a VST and some
|
||||
other format might actually have the same id.
|
||||
*/
|
||||
int uid;
|
||||
|
||||
/** True if the plugin identifies itself as a synthesiser. */
|
||||
bool isInstrument;
|
||||
|
||||
/** The number of inputs. */
|
||||
int numInputChannels;
|
||||
|
||||
/** The number of outputs. */
|
||||
int numOutputChannels;
|
||||
|
||||
/** Returns true if the two descriptions refer the the same plugin.
|
||||
|
||||
This isn't quite as simple as them just having the same file (because of
|
||||
shell plugins).
|
||||
*/
|
||||
bool isDuplicateOf (const PluginDescription& other) const;
|
||||
|
||||
//==============================================================================
|
||||
/** Fills in this description based on the given plugin.
|
||||
|
||||
Returns true if it worked, false if it couldn't get the info.
|
||||
*/
|
||||
void fillInFromInstance (AudioPluginInstance& instance) throw();
|
||||
|
||||
//==============================================================================
|
||||
/** Tries to load the type for this description, by trying all the formats
|
||||
available in the AudioPluginFormat.
|
||||
|
||||
The caller is responsible for deleting the object that is returned.
|
||||
|
||||
Returns 0 if it can't load the plugin for some reason.
|
||||
*/
|
||||
AudioPluginInstance* createInstance() const;
|
||||
|
||||
//==============================================================================
|
||||
/** Creates an XML object containing these details.
|
||||
|
||||
@see loadFromXml
|
||||
*/
|
||||
XmlElement* createXml() const;
|
||||
|
||||
/** Reloads the info in this structure from an XML record that was previously
|
||||
saved with createXML().
|
||||
|
||||
Returns true if the XML was a valid plugin description.
|
||||
*/
|
||||
bool loadFromXml (const XmlElement& xml);
|
||||
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
};
|
||||
|
||||
|
||||
#endif // __JUCE_PLUGINDESCRIPTION_JUCEHEADER__
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
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.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../../../juce.h"
|
||||
#include "juce_PluginDirectoryScanner.h"
|
||||
#include "juce_AudioPluginFormat.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
PluginDirectoryScanner::PluginDirectoryScanner (KnownPluginList& listToAddTo,
|
||||
FileSearchPath directoriesToSearch,
|
||||
const bool recursive,
|
||||
const File& deadMansPedalFile_)
|
||||
: list (listToAddTo),
|
||||
deadMansPedalFile (deadMansPedalFile_),
|
||||
nextIndex (0),
|
||||
progress (0)
|
||||
{
|
||||
directoriesToSearch.removeRedundantPaths();
|
||||
|
||||
for (int j = 0; j < directoriesToSearch.getNumPaths(); ++j)
|
||||
{
|
||||
DirectoryIterator iter (directoriesToSearch[j], recursive, "*", File::findFilesAndDirectories);
|
||||
|
||||
while (iter.next())
|
||||
{
|
||||
const File f (iter.getFile());
|
||||
|
||||
for (int i = 0; i < AudioPluginFormatManager::getInstance()->getNumFormats(); ++i)
|
||||
{
|
||||
AudioPluginFormat* const format = AudioPluginFormatManager::getInstance()->getFormat (i);
|
||||
|
||||
if (format->fileMightContainThisPluginType (f))
|
||||
{
|
||||
filesToScan.add (new File (f));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If any plugins have crashed recently when being loaded, move them to the
|
||||
// end of the list to give the others a chance to load correctly..
|
||||
const StringArray crashedPlugins (getDeadMansPedalFile());
|
||||
|
||||
for (int i = 0; i < crashedPlugins.size(); ++i)
|
||||
{
|
||||
const File f (crashedPlugins[i]);
|
||||
|
||||
for (int j = filesToScan.size(); --j >= 0;)
|
||||
if (f == *filesToScan.getUnchecked (j))
|
||||
filesToScan.move (j, -1);
|
||||
}
|
||||
}
|
||||
|
||||
PluginDirectoryScanner::~PluginDirectoryScanner()
|
||||
{
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
const File PluginDirectoryScanner::getNextPluginFileThatWillBeScanned() const throw()
|
||||
{
|
||||
File* const file = filesToScan [nextIndex];
|
||||
|
||||
if (file != 0)
|
||||
return *file;
|
||||
|
||||
return File::nonexistent;
|
||||
}
|
||||
|
||||
bool PluginDirectoryScanner::scanNextFile (const bool dontRescanIfAlreadyInList)
|
||||
{
|
||||
File* const file = filesToScan [nextIndex];
|
||||
|
||||
if (file != 0)
|
||||
{
|
||||
if (! list.isListingUpToDate (*file))
|
||||
{
|
||||
OwnedArray <PluginDescription> typesFound;
|
||||
|
||||
// Add this plugin to the end of the dead-man's pedal list in case it crashes...
|
||||
StringArray crashedPlugins (getDeadMansPedalFile());
|
||||
crashedPlugins.removeString (file->getFullPathName());
|
||||
crashedPlugins.add (file->getFullPathName());
|
||||
setDeadMansPedalFile (crashedPlugins);
|
||||
|
||||
list.scanAndAddFile (*file,
|
||||
dontRescanIfAlreadyInList,
|
||||
typesFound);
|
||||
|
||||
// Managed to load without crashing, so remove it from the dead-man's-pedal..
|
||||
crashedPlugins.removeString (file->getFullPathName());
|
||||
setDeadMansPedalFile (crashedPlugins);
|
||||
}
|
||||
|
||||
++nextIndex;
|
||||
progress = nextIndex / (float) filesToScan.size();
|
||||
}
|
||||
|
||||
return nextIndex < filesToScan.size();
|
||||
}
|
||||
|
||||
const StringArray PluginDirectoryScanner::getDeadMansPedalFile() throw()
|
||||
{
|
||||
StringArray lines;
|
||||
|
||||
if (deadMansPedalFile != File::nonexistent)
|
||||
{
|
||||
lines.addLines (deadMansPedalFile.loadFileAsString());
|
||||
lines.removeEmptyStrings();
|
||||
}
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
void PluginDirectoryScanner::setDeadMansPedalFile (const StringArray& newContents) throw()
|
||||
{
|
||||
if (deadMansPedalFile != File::nonexistent)
|
||||
deadMansPedalFile.replaceWithText (newContents.joinIntoString ("\n"), true, true);
|
||||
}
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
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_PLUGINDIRECTORYSCANNER_JUCEHEADER__
|
||||
#define __JUCE_PLUGINDIRECTORYSCANNER_JUCEHEADER__
|
||||
|
||||
#include "juce_KnownPluginList.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Scans a directory for plugins, and adds them to a KnownPluginList.
|
||||
|
||||
To use one of these, create it and call scanNextFile() repeatedly, until
|
||||
it returns false.
|
||||
*/
|
||||
class PluginDirectoryScanner
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/**
|
||||
Creates a scanner.
|
||||
|
||||
@param listToAddResultsTo this will get the new types added to it.
|
||||
@param directoriesToSearch the path to search
|
||||
@param searchRecursively true to search recursively
|
||||
@param deadMansPedalFile if this isn't File::nonexistent, then it will
|
||||
be used as a file to store the names of any plugins
|
||||
that crash during initialisation. If there are
|
||||
any plugins listed in it, then these will always
|
||||
be scanned after all other possible files have
|
||||
been tried - in this way, even if there's a few
|
||||
dodgy plugins in your path, then a couple of rescans
|
||||
will still manage to find all the proper plugins.
|
||||
It's probably best to choose a file in the user's
|
||||
application data directory (alongside your app's
|
||||
settings file) for this. The file format it uses
|
||||
is just a list of filenames of the modules that
|
||||
failed.
|
||||
*/
|
||||
PluginDirectoryScanner (KnownPluginList& listToAddResultsTo,
|
||||
FileSearchPath directoriesToSearch,
|
||||
const bool searchRecursively,
|
||||
const File& deadMansPedalFile);
|
||||
|
||||
/** Destructor. */
|
||||
~PluginDirectoryScanner();
|
||||
|
||||
//==============================================================================
|
||||
/** Tries the next likely-looking file.
|
||||
|
||||
If dontRescanIfAlreadyInList is true, then the file will only be loaded and
|
||||
re-tested if it's not already in the list, or if the file's modification
|
||||
time has changed since the list was created. If dontRescanIfAlreadyInList is
|
||||
false, the file will always be reloaded and tested.
|
||||
|
||||
Returns false when there are no more files to try.
|
||||
*/
|
||||
bool scanNextFile (const bool dontRescanIfAlreadyInList);
|
||||
|
||||
/** Returns the file that will be scanned during the next call to scanNextFile().
|
||||
|
||||
This is handy if you want to show the user which file is currently getting
|
||||
scanned.
|
||||
*/
|
||||
const File getNextPluginFileThatWillBeScanned() const throw();
|
||||
|
||||
/** Returns the estimated progress, between 0 and 1.
|
||||
*/
|
||||
float getProgress() const { return progress; }
|
||||
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
KnownPluginList& list;
|
||||
OwnedArray <File> filesToScan;
|
||||
File deadMansPedalFile;
|
||||
int nextIndex;
|
||||
float progress;
|
||||
|
||||
const StringArray getDeadMansPedalFile() throw();
|
||||
void setDeadMansPedalFile (const StringArray& newContents) throw();
|
||||
};
|
||||
|
||||
|
||||
#endif // __JUCE_PLUGINDIRECTORYSCANNER_JUCEHEADER__
|
||||
|
|
@ -0,0 +1,261 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
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.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../../../juce.h"
|
||||
#include "juce_PluginListComponent.h"
|
||||
#include "juce_PluginDirectoryScanner.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
PluginListComponent::PluginListComponent (KnownPluginList& listToEdit,
|
||||
const File& deadMansPedalFile_,
|
||||
PropertiesFile* const propertiesToUse_)
|
||||
: list (listToEdit),
|
||||
deadMansPedalFile (deadMansPedalFile_),
|
||||
propertiesToUse (propertiesToUse_)
|
||||
{
|
||||
addAndMakeVisible (listBox = new ListBox (String::empty, this));
|
||||
|
||||
addAndMakeVisible (optionsButton = new TextButton ("Options..."));
|
||||
optionsButton->addButtonListener (this);
|
||||
optionsButton->setTriggeredOnMouseDown (true);
|
||||
|
||||
setSize (400, 600);
|
||||
list.addChangeListener (this);
|
||||
}
|
||||
|
||||
PluginListComponent::~PluginListComponent()
|
||||
{
|
||||
list.removeChangeListener (this);
|
||||
deleteAllChildren();
|
||||
}
|
||||
|
||||
void PluginListComponent::resized()
|
||||
{
|
||||
listBox->setBounds (0, 0, getWidth(), getHeight() - 30);
|
||||
optionsButton->changeWidthToFitText (24);
|
||||
optionsButton->setTopLeftPosition (8, getHeight() - 28);
|
||||
}
|
||||
|
||||
void PluginListComponent::changeListenerCallback (void*)
|
||||
{
|
||||
listBox->updateContent();
|
||||
listBox->repaint();
|
||||
}
|
||||
|
||||
int PluginListComponent::getNumRows()
|
||||
{
|
||||
return list.getNumTypes();
|
||||
}
|
||||
|
||||
void PluginListComponent::paintListBoxItem (int row,
|
||||
Graphics& g,
|
||||
int width, int height,
|
||||
bool rowIsSelected)
|
||||
{
|
||||
if (rowIsSelected)
|
||||
g.fillAll (findColour (TextEditor::highlightColourId));
|
||||
|
||||
const PluginDescription* const pd = list.getType (row);
|
||||
|
||||
if (pd != 0)
|
||||
{
|
||||
GlyphArrangement ga;
|
||||
ga.addCurtailedLineOfText (Font (height * 0.7f, Font::bold), pd->name, 8.0f, height * 0.8f, width - 10.0f, true);
|
||||
|
||||
g.setColour (Colours::black);
|
||||
ga.draw (g);
|
||||
|
||||
float x, y, r, b;
|
||||
ga.getBoundingBox (0, -1, x, y, r, b, false);
|
||||
|
||||
String desc;
|
||||
desc << pd->pluginFormatName
|
||||
<< (pd->isInstrument ? " instrument" : " effect")
|
||||
<< " - "
|
||||
<< pd->numInputChannels << (pd->numInputChannels == 1 ? " in" : " ins")
|
||||
<< " / "
|
||||
<< pd->numOutputChannels << (pd->numOutputChannels == 1 ? " out" : " outs");
|
||||
|
||||
if (pd->manufacturerName.isNotEmpty())
|
||||
desc << " - " << pd->manufacturerName;
|
||||
|
||||
if (pd->version.isNotEmpty())
|
||||
desc << " - " << pd->version;
|
||||
|
||||
if (pd->category.isNotEmpty())
|
||||
desc << " - category: '" << pd->category << '\'';
|
||||
|
||||
g.setColour (Colours::grey);
|
||||
|
||||
ga.clear();
|
||||
ga.addCurtailedLineOfText (Font (height * 0.6f), desc, r + 10.0f, height * 0.8f, width - r - 12.0f, true);
|
||||
ga.draw (g);
|
||||
}
|
||||
}
|
||||
|
||||
void PluginListComponent::deleteKeyPressed (int lastRowSelected)
|
||||
{
|
||||
list.removeType (lastRowSelected);
|
||||
}
|
||||
|
||||
void PluginListComponent::buttonClicked (Button* b)
|
||||
{
|
||||
if (optionsButton == b)
|
||||
{
|
||||
PopupMenu menu;
|
||||
menu.addItem (1, TRANS("Clear list"));
|
||||
menu.addItem (5, TRANS("Remove selected plugin from list"), listBox->getNumSelectedRows() > 0);
|
||||
menu.addItem (6, TRANS("Show folder containing selected plugin"), listBox->getNumSelectedRows() > 0);
|
||||
menu.addSeparator();
|
||||
menu.addItem (2, TRANS("Sort alphabetically"));
|
||||
menu.addItem (3, TRANS("Sort by category"));
|
||||
menu.addItem (4, TRANS("Sort by manufacturer"));
|
||||
menu.addSeparator();
|
||||
|
||||
for (int i = 0; i < AudioPluginFormatManager::getInstance()->getNumFormats(); ++i)
|
||||
{
|
||||
AudioPluginFormat* const format = AudioPluginFormatManager::getInstance()->getFormat (i);
|
||||
|
||||
if (format->getDefaultLocationsToSearch().getNumPaths() > 0)
|
||||
menu.addItem (10 + i, "Scan for new or updated " + format->getName() + " plugins...");
|
||||
}
|
||||
|
||||
const int r = menu.showAt (optionsButton);
|
||||
|
||||
if (r == 1)
|
||||
{
|
||||
list.clear();
|
||||
}
|
||||
else if (r == 2)
|
||||
{
|
||||
list.sort (KnownPluginList::sortAlphabetically);
|
||||
}
|
||||
else if (r == 3)
|
||||
{
|
||||
list.sort (KnownPluginList::sortByCategory);
|
||||
}
|
||||
else if (r == 4)
|
||||
{
|
||||
list.sort (KnownPluginList::sortByManufacturer);
|
||||
}
|
||||
else if (r == 5)
|
||||
{
|
||||
const SparseSet <int> selected (listBox->getSelectedRows());
|
||||
|
||||
for (int i = list.getNumTypes(); --i >= 0;)
|
||||
if (selected.contains (i))
|
||||
list.removeType (i);
|
||||
}
|
||||
else if (r == 6)
|
||||
{
|
||||
const PluginDescription* const desc = list.getType (listBox->getSelectedRow());
|
||||
|
||||
if (desc != 0)
|
||||
desc->file.getParentDirectory().startAsProcess();
|
||||
}
|
||||
else if (r != 0)
|
||||
{
|
||||
scanFor (AudioPluginFormatManager::getInstance()->getFormat (r - 10));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool PluginListComponent::filesDropped (const StringArray& files, int, int)
|
||||
{
|
||||
OwnedArray <PluginDescription> typesFound;
|
||||
list.scanAndAddDragAndDroppedFiles (files, typesFound);
|
||||
|
||||
return typesFound.size() > 0;
|
||||
}
|
||||
|
||||
void PluginListComponent::scanFor (AudioPluginFormat* format)
|
||||
{
|
||||
if (format == 0)
|
||||
return;
|
||||
|
||||
FileSearchPath path (format->getDefaultLocationsToSearch());
|
||||
|
||||
if (propertiesToUse != 0)
|
||||
path = propertiesToUse->getValue ("lastPluginScanPath_" + format->getName(), path.toString());
|
||||
|
||||
{
|
||||
AlertWindow aw (TRANS("Select folders to scan..."), String::empty, AlertWindow::NoIcon);
|
||||
FileSearchPathListComponent pathList;
|
||||
pathList.setSize (500, 300);
|
||||
pathList.setPath (path);
|
||||
|
||||
aw.addCustomComponent (&pathList);
|
||||
aw.addButton (TRANS("Scan"), 1, KeyPress::returnKey);
|
||||
aw.addButton (TRANS("Cancel"), 0, KeyPress (KeyPress::escapeKey));
|
||||
|
||||
if (aw.runModalLoop() == 0)
|
||||
return;
|
||||
|
||||
path = pathList.getPath();
|
||||
}
|
||||
|
||||
if (propertiesToUse != 0)
|
||||
{
|
||||
propertiesToUse->setValue ("lastPluginScanPath_" + format->getName(), path.toString());
|
||||
propertiesToUse->saveIfNeeded();
|
||||
}
|
||||
|
||||
double progress = 0.0;
|
||||
|
||||
AlertWindow aw (TRANS("Scanning for plugins..."),
|
||||
TRANS("Searching for all possible plugin files..."), AlertWindow::NoIcon);
|
||||
|
||||
aw.addButton (TRANS("Cancel"), 0, KeyPress (KeyPress::escapeKey));
|
||||
aw.addProgressBarComponent (progress);
|
||||
|
||||
aw.enterModalState();
|
||||
|
||||
MessageManager::getInstance()->dispatchPendingMessages();
|
||||
|
||||
PluginDirectoryScanner scanner (list, path, true, deadMansPedalFile);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
aw.setMessage (TRANS("Testing:\n\n")
|
||||
+ scanner.getNextPluginFileThatWillBeScanned().getFileName());
|
||||
|
||||
MessageManager::getInstance()->dispatchPendingMessages (500);
|
||||
|
||||
if (! scanner.scanNextFile (true))
|
||||
break;
|
||||
|
||||
if (! aw.isCurrentlyModal())
|
||||
break;
|
||||
|
||||
progress = scanner.getProgress();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
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_PLUGINLISTCOMPONENT_JUCEHEADER__
|
||||
#define __JUCE_PLUGINLISTCOMPONENT_JUCEHEADER__
|
||||
|
||||
#include "juce_KnownPluginList.h"
|
||||
#include "juce_AudioPluginFormat.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A component displaying a list of plugins, with options to scan for them,
|
||||
add, remove and sort them.
|
||||
*/
|
||||
class PluginListComponent : public Component,
|
||||
public ListBoxModel,
|
||||
public ChangeListener,
|
||||
public ButtonListener
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/**
|
||||
Creates the list component.
|
||||
|
||||
For info about the deadMansPedalFile, see the PluginDirectoryScanner constructor.
|
||||
|
||||
The properties file, if supplied is used to store the user's last search paths.
|
||||
*/
|
||||
PluginListComponent (KnownPluginList& listToRepresent,
|
||||
const File& deadMansPedalFile,
|
||||
PropertiesFile* const propertiesToUse);
|
||||
|
||||
/** Destructor. */
|
||||
~PluginListComponent();
|
||||
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
void resized();
|
||||
/** @internal */
|
||||
bool filesDropped (const StringArray& files, int x, int y);
|
||||
/** @internal */
|
||||
int getNumRows();
|
||||
/** @internal */
|
||||
void paintListBoxItem (int row, Graphics& g, int width, int height, bool rowIsSelected);
|
||||
/** @internal */
|
||||
void deleteKeyPressed (int lastRowSelected);
|
||||
/** @internal */
|
||||
void buttonClicked (Button* b);
|
||||
/** @internal */
|
||||
void changeListenerCallback (void*);
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
KnownPluginList& list;
|
||||
File deadMansPedalFile;
|
||||
ListBox* listBox;
|
||||
TextButton* optionsButton;
|
||||
PropertiesFile* propertiesToUse;
|
||||
|
||||
void scanFor (AudioPluginFormat* format);
|
||||
};
|
||||
|
||||
|
||||
#endif // __JUCE_PLUGINLISTCOMPONENT_JUCEHEADER__
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
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__
|
||||
#define __JUCE_VSTPLUGINFORMAT_JUCEHEADER__
|
||||
|
||||
#include "../juce_AudioPluginFormat.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Implements a plugin format manager for VSTs.
|
||||
*/
|
||||
class VSTPluginFormat : public AudioPluginFormat
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
VSTPluginFormat();
|
||||
~VSTPluginFormat();
|
||||
|
||||
//==============================================================================
|
||||
const String getName() const { return "VST"; }
|
||||
void findAllTypesForFile (OwnedArray <PluginDescription>& results, const File& file);
|
||||
AudioPluginInstance* createInstanceFromDescription (const PluginDescription& desc);
|
||||
bool fileMightContainThisPluginType (const File& file);
|
||||
const FileSearchPath getDefaultLocationsToSearch();
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
};
|
||||
|
||||
|
||||
#endif // __JUCE_VSTPLUGINFORMAT_JUCEHEADER__
|
||||
2540
extras/audio plugin host/src/plugins/vst/juce_VSTPluginInstance.cpp
Normal file
2540
extras/audio plugin host/src/plugins/vst/juce_VSTPluginInstance.cpp
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
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_VSTFORMAT_JUCEHEADER__
|
||||
#define __JUCE_VSTFORMAT_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 VSTPluginType.
|
||||
|
||||
*/
|
||||
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;
|
||||
int getSamplesLatency() const;
|
||||
|
||||
//==============================================================================
|
||||
// AudioFilterBase methods:
|
||||
|
||||
void JUCE_CALLTYPE prepareToPlay (double sampleRate, int estimatedSamplesPerBlock);
|
||||
void JUCE_CALLTYPE releaseResources();
|
||||
void JUCE_CALLTYPE processBlock (const AudioSampleBuffer& input,
|
||||
AudioSampleBuffer& output,
|
||||
const bool accumulateOutput,
|
||||
MidiBuffer& midiMessages);
|
||||
|
||||
AudioFilterEditor* JUCE_CALLTYPE createEditor();
|
||||
|
||||
const String JUCE_CALLTYPE getInputChannelName (const int index) const;
|
||||
bool JUCE_CALLTYPE isInputChannelStereoPair (int index) const;
|
||||
|
||||
const String JUCE_CALLTYPE getOutputChannelName (const int index) const;
|
||||
bool JUCE_CALLTYPE isOutputChannelStereoPair (int index) const;
|
||||
|
||||
//==============================================================================
|
||||
int JUCE_CALLTYPE getNumParameters();
|
||||
float JUCE_CALLTYPE getParameter (int index);
|
||||
void JUCE_CALLTYPE setParameter (int index, float newValue);
|
||||
const String JUCE_CALLTYPE getParameterName (int index);
|
||||
const String JUCE_CALLTYPE getParameterText (int index);
|
||||
bool isParameterAutomatable (int index) const;
|
||||
|
||||
//==============================================================================
|
||||
int JUCE_CALLTYPE getNumPrograms();
|
||||
int JUCE_CALLTYPE getCurrentProgram();
|
||||
void JUCE_CALLTYPE setCurrentProgram (int index);
|
||||
const String JUCE_CALLTYPE getProgramName (int index);
|
||||
void JUCE_CALLTYPE changeProgramName (int index, const String& newName);
|
||||
|
||||
//==============================================================================
|
||||
void JUCE_CALLTYPE getStateInformation (JUCE_NAMESPACE::MemoryBlock& destData);
|
||||
void JUCE_CALLTYPE getCurrentProgramStateInformation (JUCE_NAMESPACE::MemoryBlock& destData);
|
||||
void JUCE_CALLTYPE setStateInformation (const void* data, int sizeInBytes);
|
||||
void JUCE_CALLTYPE 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 VSTPluginType;
|
||||
friend class VSTPluginWindow;
|
||||
friend class VSTPluginFormat;
|
||||
|
||||
AEffect* effect;
|
||||
String name;
|
||||
CriticalSection lock;
|
||||
bool wantsMidiMessages, initialised, isPowerOn;
|
||||
mutable StringArray programNames;
|
||||
MidiMessageCollector midiCollector;
|
||||
AudioSampleBuffer tempBuffer;
|
||||
CriticalSection midiInLock;
|
||||
MidiBuffer incomingMidi;
|
||||
void* midiEventsToSend;
|
||||
int numAllocatedMidiEvents;
|
||||
VstTimeInfo vstHostTime;
|
||||
float** channelsIn;
|
||||
float** channelsOut;
|
||||
|
||||
ReferenceCountedObjectPtr <ModuleHandle> 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 (juce::MemoryBlock& dest);
|
||||
void restoreFromTempParameterStore (const juce::MemoryBlock& mb);
|
||||
const String getParameterLabel (int index) const;
|
||||
|
||||
bool usesChunks() const throw();
|
||||
void getChunkData (juce::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 (juce::MemoryBlock& dest, bool isFXB, int maxSizeMB);
|
||||
|
||||
int getVersionNumber() const throw();
|
||||
bool hasEditor() const throw();
|
||||
bool canMono() const throw();
|
||||
bool canReplace() const throw();
|
||||
bool isOffline() const throw();
|
||||
void setPower (const bool on);
|
||||
|
||||
VSTPluginInstance (const ReferenceCountedObjectPtr <ModuleHandle>& module);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // __JUCE_VSTFORMAT_JUCEHEADER__
|
||||
55
extras/audio plugins/demo/build/VST_Linux/premake.lua
Normal file
55
extras/audio plugins/demo/build/VST_Linux/premake.lua
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
|
||||
project.name = "JucePluginDemo"
|
||||
project.bindir = "build"
|
||||
project.libdir = "build"
|
||||
|
||||
project.configs = { "Debug", "Release" }
|
||||
|
||||
package = newpackage()
|
||||
package.name = "JucePluginDemo"
|
||||
package.kind = "dll"
|
||||
package.language = "c++"
|
||||
|
||||
package.objdir = "build/intermediate"
|
||||
package.config["Debug"].objdir = "build/intermediate/Debug"
|
||||
package.config["Release"].objdir = "build/intermediate/Release"
|
||||
|
||||
package.config["Debug"].defines = { "LINUX=1", "DEBUG=1", "_DEBUG=1" }
|
||||
package.config["Debug"].buildoptions = { "-O0 -ggdb -g3 -Wall" }
|
||||
|
||||
package.config["Release"].defines = { "LINUX=1", "NDEBUG=1" }
|
||||
package.config["Release"].buildoptions = { "-O2 -s" }
|
||||
|
||||
package.includepaths = {
|
||||
"/usr/include",
|
||||
"../../../../../",
|
||||
"/usr/include/vst/source/common",
|
||||
"/usr/include/vst",
|
||||
"../../src"
|
||||
}
|
||||
|
||||
package.libpaths = {
|
||||
"../../../../../bin",
|
||||
"/usr/X11R6/lib/",
|
||||
"/usr/lib"
|
||||
}
|
||||
|
||||
package.config["Debug"].links = {
|
||||
"freetype", "pthread", "rt", "X11", "GL", "GLU", "Xinerama", "asound", "juce_debug"
|
||||
}
|
||||
|
||||
package.config["Release"].links = {
|
||||
"freetype", "pthread", "rt", "X11", "GL", "GLU", "Xinerama", "asound", "juce"
|
||||
}
|
||||
|
||||
package.files = {
|
||||
matchfiles (
|
||||
"../../../wrapper/*.h",
|
||||
"../../../wrapper/*.cpp",
|
||||
"../../../wrapper/formats/VST/*.cpp"
|
||||
),
|
||||
matchrecursive (
|
||||
"../../src/*.h",
|
||||
"../../src/*.cpp"
|
||||
)
|
||||
}
|
||||
|
|
@ -811,6 +811,9 @@ protected:
|
|||
|
||||
void JUCE_CALLTYPE informHostOfParameterChange (int index, float newValue)
|
||||
{
|
||||
if (juceFilter != 0)
|
||||
juceFilter->setParameter (index, newValue);
|
||||
|
||||
SetControlValue (index + 2, floatToLong (newValue));
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -34,14 +34,14 @@
|
|||
|
||||
//==============================================================================
|
||||
AudioFilterBase::AudioFilterBase()
|
||||
: suspended (false),
|
||||
: sampleRate (0),
|
||||
blockSize (0),
|
||||
numInputChannels (0),
|
||||
numOutputChannels (0),
|
||||
suspended (false),
|
||||
callbacks (0),
|
||||
activeEditor (0)
|
||||
{
|
||||
sampleRate = 0.0;
|
||||
blockSize = 0;
|
||||
}
|
||||
|
||||
AudioFilterBase::~AudioFilterBase()
|
||||
|
|
@ -67,6 +67,11 @@ void AudioFilterBase::setParameterNotifyingHost (const int parameterIndex,
|
|||
setParameter (parameterIndex, newValue);
|
||||
}
|
||||
|
||||
bool AudioFilterBase::isParameterAutomatable (int /*index*/) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void AudioFilterBase::suspendProcessing (const bool shouldBeSuspended)
|
||||
{
|
||||
const ScopedLock sl (callbackLock);
|
||||
|
|
@ -80,18 +85,6 @@ bool AudioFilterBase::getCurrentPositionInfo (CurrentPositionInfo& info)
|
|||
&& callbacks->getCurrentPositionInfo (info);
|
||||
}
|
||||
|
||||
const String AudioFilterBase::getInputChannelName (const int channelIndex) const
|
||||
{
|
||||
String s (inputNames [channelIndex]);
|
||||
return s.isNotEmpty() ? s : String (channelIndex + 1);
|
||||
}
|
||||
|
||||
const String AudioFilterBase::getOutputChannelName (const int channelIndex) const
|
||||
{
|
||||
String s (outputNames [channelIndex]);
|
||||
return s.isNotEmpty() ? s : String (channelIndex + 1);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void AudioFilterBase::editorBeingDeleted (AudioFilterEditor* const editor)
|
||||
{
|
||||
|
|
@ -112,8 +105,10 @@ AudioFilterEditor* AudioFilterBase::createEditorIfNeeded()
|
|||
|
||||
if (ed != 0)
|
||||
{
|
||||
#if ! JUCE_PLUGIN_HOST
|
||||
// you must give your editor comp a size before returning it..
|
||||
jassert (ed->getWidth() > 0 && ed->getHeight() > 0);
|
||||
#endif
|
||||
|
||||
const ScopedLock sl (callbackLock);
|
||||
activeEditor = ed;
|
||||
|
|
|
|||
|
|
@ -207,6 +207,7 @@ public:
|
|||
*/
|
||||
bool JUCE_CALLTYPE getCurrentPositionInfo (CurrentPositionInfo& info);
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the current sample rate.
|
||||
|
||||
This can be called from your processBlock() method - it's not guaranteed
|
||||
|
|
@ -225,6 +226,7 @@ public:
|
|||
*/
|
||||
int JUCE_CALLTYPE getBlockSize() const throw() { return blockSize; }
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the number of input channels that the host will be sending the filter.
|
||||
|
||||
In your JucePluginCharacteristics.h file, you specify the number of channels
|
||||
|
|
@ -252,14 +254,20 @@ public:
|
|||
The host might not supply very useful names for channels, and this might be
|
||||
something like "1", "2", "left", "right", etc.
|
||||
*/
|
||||
const String getInputChannelName (const int channelIndex) const;
|
||||
virtual const String JUCE_CALLTYPE getInputChannelName (const int channelIndex) const = 0;
|
||||
|
||||
/** Returns the name of one of the output channels, as returned by the host.
|
||||
|
||||
The host might not supply very useful names for channels, and this might be
|
||||
something like "1", "2", "left", "right", etc.
|
||||
*/
|
||||
const String getOutputChannelName (const int channelIndex) const;
|
||||
virtual const String JUCE_CALLTYPE getOutputChannelName (const int channelIndex) const = 0;
|
||||
|
||||
/** Returns true if the specified channel is part of a stereo pair with its neighbour. */
|
||||
virtual bool JUCE_CALLTYPE isInputChannelStereoPair (int index) const = 0;
|
||||
|
||||
/** Returns true if the specified channel is part of a stereo pair with its neighbour. */
|
||||
virtual bool JUCE_CALLTYPE isOutputChannelStereoPair (int index) const = 0;
|
||||
|
||||
//==============================================================================
|
||||
/** This returns a critical section that will automatically be locked while the host
|
||||
|
|
@ -384,6 +392,12 @@ public:
|
|||
void JUCE_CALLTYPE setParameterNotifyingHost (int parameterIndex,
|
||||
float newValue);
|
||||
|
||||
/** Returns true if the host can automate this parameter.
|
||||
|
||||
By default, this returns true for all parameters.
|
||||
*/
|
||||
virtual bool isParameterAutomatable (int index) const;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the number of preset programs the plugin supports.
|
||||
|
||||
|
|
@ -507,6 +521,11 @@ protected:
|
|||
static XmlElement* JUCE_CALLTYPE getXmlFromBinary (const void* data,
|
||||
const int sizeInBytes);
|
||||
|
||||
/** @internal */
|
||||
double sampleRate;
|
||||
/** @internal */
|
||||
int numInputChannels, numOutputChannels, blockSize;
|
||||
|
||||
private:
|
||||
friend class JuceVSTWrapper;
|
||||
friend class JuceAU;
|
||||
|
|
@ -517,9 +536,6 @@ private:
|
|||
|
||||
CriticalSection callbackLock;
|
||||
bool suspended;
|
||||
double sampleRate;
|
||||
int blockSize, numInputChannels, numOutputChannels;
|
||||
StringArray outputNames, inputNames;
|
||||
|
||||
FilterNativeCallbacks* callbacks;
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -54,7 +54,7 @@ namespace BinaryData
|
|||
const int treeviewdemo_cppSize = 7534;
|
||||
|
||||
extern const char* widgetsdemo_cpp;
|
||||
const int widgetsdemo_cppSize = 52997;
|
||||
const int widgetsdemo_cppSize = 53000;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -175,8 +175,8 @@ class CustomMenuComponent : public PopupMenuCustomComponent,
|
|||
|
||||
public:
|
||||
CustomMenuComponent()
|
||||
blobX (0),
|
||||
blobY (0)
|
||||
: blobX (0),
|
||||
blobY (0)
|
||||
{
|
||||
// set off a timer to move a blob around on this component every
|
||||
// 300 milliseconds - see the timerCallback() method.
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ class CustomMenuComponent : public PopupMenuCustomComponent,
|
|||
|
||||
public:
|
||||
CustomMenuComponent()
|
||||
: blobX (0),
|
||||
: blobX (0),
|
||||
blobY (0)
|
||||
{
|
||||
// set off a timer to move a blob around on this component every
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ MainWindow::MainWindow()
|
|||
}
|
||||
|
||||
addKeyListener (commandManager->getKeyMappings());
|
||||
commandManager->addListener (this);
|
||||
|
||||
// don't want the window to take focus when the title-bar is clicked..
|
||||
setWantsKeyboardFocus (false);
|
||||
|
|
|
|||
|
|
@ -569,6 +569,9 @@
|
|||
#ifndef __JUCE_FILEPREVIEWCOMPONENT_JUCEHEADER__
|
||||
#include "juce_appframework/gui/components/filebrowser/juce_FilePreviewComponent.h"
|
||||
#endif
|
||||
#ifndef __JUCE_FILESEARCHPATHLISTCOMPONENT_JUCEHEADER__
|
||||
#include "juce_appframework/gui/components/filebrowser/juce_FileSearchPathListComponent.h"
|
||||
#endif
|
||||
#ifndef __JUCE_FILETREECOMPONENT_JUCEHEADER__
|
||||
#include "juce_appframework/gui/components/filebrowser/juce_FileTreeComponent.h"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -256,7 +256,7 @@ FileBasedDocument::SaveResult FileBasedDocument::saveAsInteractive (const bool w
|
|||
if (f.existsAsFile() || f.getParentDirectory().isDirectory())
|
||||
f = f.getSiblingFile (legalFilename);
|
||||
else
|
||||
f = File::getCurrentWorkingDirectory().getChildFile (legalFilename);
|
||||
f = File::getSpecialLocation (File::userDocumentsDirectory).getChildFile (legalFilename);
|
||||
|
||||
f = f.withFileExtension (fileExtension)
|
||||
.getNonexistentSibling (true);
|
||||
|
|
@ -267,8 +267,11 @@ FileBasedDocument::SaveResult FileBasedDocument::saveAsInteractive (const bool w
|
|||
{
|
||||
setLastDocumentOpened (fc.getResult());
|
||||
|
||||
return saveAs (fc.getResult(),
|
||||
false, false, true);
|
||||
File chosen (fc.getResult());
|
||||
if (chosen.getFileExtension().isEmpty())
|
||||
chosen = chosen.withFileExtension (fileExtension);
|
||||
|
||||
return saveAs (f, false, false, true);
|
||||
}
|
||||
|
||||
return userCancelledSave;
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@
|
|||
void loadMooseFile()
|
||||
{
|
||||
FileChooser myChooser ("Please select the moose you want to load...",
|
||||
File (SystemStats::getUserHomeDirectory()),
|
||||
File::getSpecialLocation (File::userHomeDirectory),
|
||||
"*.moose");
|
||||
|
||||
if (myChooser.browseForFileToOpen())
|
||||
|
|
|
|||
|
|
@ -0,0 +1,279 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
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.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../../../juce_core/basics/juce_StandardHeader.h"
|
||||
|
||||
BEGIN_JUCE_NAMESPACE
|
||||
|
||||
#include "juce_FileSearchPathListComponent.h"
|
||||
#include "../lookandfeel/juce_LookAndFeel.h"
|
||||
#include "../filebrowser/juce_FileChooser.h"
|
||||
#include "../../../../juce_core/text/juce_LocalisedStrings.h"
|
||||
#include "../buttons/juce_TextButton.h"
|
||||
#include "../buttons/juce_DrawableButton.h"
|
||||
#include "../../graphics/drawables/juce_DrawablePath.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
FileSearchPathListComponent::FileSearchPathListComponent()
|
||||
{
|
||||
addAndMakeVisible (listBox = new ListBox (String::empty, this));
|
||||
listBox->setColour (ListBox::backgroundColourId, Colours::black.withAlpha (0.02f));
|
||||
listBox->setColour (ListBox::outlineColourId, Colours::black.withAlpha (0.1f));
|
||||
listBox->setOutlineThickness (1);
|
||||
|
||||
addAndMakeVisible (addButton = new TextButton ("+"));
|
||||
addButton->addButtonListener (this);
|
||||
addButton->setConnectedEdges (Button::ConnectedOnLeft | Button::ConnectedOnRight | Button::ConnectedOnBottom | Button::ConnectedOnTop);
|
||||
|
||||
addAndMakeVisible (removeButton = new TextButton ("-"));
|
||||
removeButton->addButtonListener (this);
|
||||
removeButton->setConnectedEdges (Button::ConnectedOnLeft | Button::ConnectedOnRight | Button::ConnectedOnBottom | Button::ConnectedOnTop);
|
||||
|
||||
addAndMakeVisible (changeButton = new TextButton (TRANS("change...")));
|
||||
changeButton->addButtonListener (this);
|
||||
|
||||
addAndMakeVisible (upButton = new DrawableButton (String::empty, DrawableButton::ImageOnButtonBackground));
|
||||
upButton->addButtonListener (this);
|
||||
|
||||
{
|
||||
Path arrowPath;
|
||||
arrowPath.addArrow (50.0f, 100.0f, 50.0f, 0.0, 40.0f, 100.0f, 50.0f);
|
||||
DrawablePath arrowImage;
|
||||
arrowImage.setSolidFill (Colours::black.withAlpha (0.4f));
|
||||
arrowImage.setPath (arrowPath);
|
||||
|
||||
((DrawableButton*) upButton)->setImages (&arrowImage);
|
||||
}
|
||||
|
||||
addAndMakeVisible (downButton = new DrawableButton (String::empty, DrawableButton::ImageOnButtonBackground));
|
||||
downButton->addButtonListener (this);
|
||||
|
||||
{
|
||||
Path arrowPath;
|
||||
arrowPath.addArrow (50.0f, 0.0f, 50.0f, 100.0f, 40.0f, 100.0f, 50.0f);
|
||||
DrawablePath arrowImage;
|
||||
arrowImage.setSolidFill (Colours::black.withAlpha (0.4f));
|
||||
arrowImage.setPath (arrowPath);
|
||||
|
||||
((DrawableButton*) downButton)->setImages (&arrowImage);
|
||||
}
|
||||
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
FileSearchPathListComponent::~FileSearchPathListComponent()
|
||||
{
|
||||
deleteAllChildren();
|
||||
}
|
||||
|
||||
void FileSearchPathListComponent::updateButtons() throw()
|
||||
{
|
||||
const bool anythingSelected = listBox->getNumSelectedRows() > 0;
|
||||
|
||||
removeButton->setEnabled (anythingSelected);
|
||||
changeButton->setEnabled (anythingSelected);
|
||||
upButton->setEnabled (anythingSelected);
|
||||
downButton->setEnabled (anythingSelected);
|
||||
}
|
||||
|
||||
void FileSearchPathListComponent::changed() throw()
|
||||
{
|
||||
listBox->updateContent();
|
||||
listBox->repaint();
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void FileSearchPathListComponent::setPath (const FileSearchPath& newPath)
|
||||
{
|
||||
if (newPath.toString() != path.toString())
|
||||
{
|
||||
path = newPath;
|
||||
changed();
|
||||
}
|
||||
}
|
||||
|
||||
void FileSearchPathListComponent::setDefaultBrowseTarget (const File& newDefaultDirectory) throw()
|
||||
{
|
||||
defaultBrowseTarget = newDefaultDirectory;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
int FileSearchPathListComponent::getNumRows()
|
||||
{
|
||||
return path.getNumPaths();
|
||||
}
|
||||
|
||||
void FileSearchPathListComponent::paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool rowIsSelected)
|
||||
{
|
||||
if (rowIsSelected)
|
||||
g.fillAll (findColour (TextEditor::highlightColourId));
|
||||
|
||||
g.setColour (findColour (ListBox::textColourId));
|
||||
Font f (height * 0.7f);
|
||||
f.setHorizontalScale (0.9f);
|
||||
g.setFont (f);
|
||||
|
||||
g.drawText (path [rowNumber].getFullPathName(),
|
||||
4, 0, width - 6, height,
|
||||
Justification::centredLeft, true);
|
||||
}
|
||||
|
||||
void FileSearchPathListComponent::deleteKeyPressed (int row)
|
||||
{
|
||||
if (row >= 0 && row < path.getNumPaths())
|
||||
{
|
||||
path.remove (row);
|
||||
changed();
|
||||
}
|
||||
}
|
||||
|
||||
void FileSearchPathListComponent::returnKeyPressed (int row)
|
||||
{
|
||||
FileChooser chooser (TRANS("Change folder..."), path [row], T("*"));
|
||||
|
||||
if (chooser.browseForDirectory())
|
||||
{
|
||||
path.remove (row);
|
||||
path.add (chooser.getResult(), row);
|
||||
changed();
|
||||
}
|
||||
}
|
||||
|
||||
void FileSearchPathListComponent::listBoxItemDoubleClicked (int row, const MouseEvent&)
|
||||
{
|
||||
returnKeyPressed (row);
|
||||
}
|
||||
|
||||
void FileSearchPathListComponent::selectedRowsChanged (int)
|
||||
{
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
void FileSearchPathListComponent::paint (Graphics& g)
|
||||
{
|
||||
g.fillAll (findColour (backgroundColourId));
|
||||
}
|
||||
|
||||
void FileSearchPathListComponent::resized()
|
||||
{
|
||||
const int buttonH = 22;
|
||||
const int buttonY = getHeight() - buttonH - 4;
|
||||
listBox->setBounds (2, 2, getWidth() - 4, buttonY - 5);
|
||||
|
||||
addButton->setBounds (2, buttonY, buttonH, buttonH);
|
||||
removeButton->setBounds (addButton->getRight(), buttonY, buttonH, buttonH);
|
||||
|
||||
((TextButton*) changeButton)->changeWidthToFitText (buttonH);
|
||||
downButton->setSize (buttonH * 2, buttonH);
|
||||
upButton->setSize (buttonH * 2, buttonH);
|
||||
|
||||
downButton->setTopRightPosition (getWidth() - 2, buttonY);
|
||||
upButton->setTopRightPosition (downButton->getX() - 4, buttonY);
|
||||
changeButton->setTopRightPosition (upButton->getX() - 8, buttonY);
|
||||
}
|
||||
|
||||
bool FileSearchPathListComponent::filesDropped (const StringArray& filenames, int /*mouseX*/, int mouseY)
|
||||
{
|
||||
bool usedAny = false;
|
||||
|
||||
for (int i = filenames.size(); --i >= 0;)
|
||||
{
|
||||
const File f (filenames[i]);
|
||||
|
||||
if (f.isDirectory())
|
||||
{
|
||||
const int row = listBox->getRowContainingPosition (0, mouseY - listBox->getY());
|
||||
path.add (f, row);
|
||||
changed();
|
||||
usedAny = true;
|
||||
}
|
||||
}
|
||||
|
||||
return usedAny;
|
||||
}
|
||||
|
||||
void FileSearchPathListComponent::buttonClicked (Button* button)
|
||||
{
|
||||
const int currentRow = listBox->getSelectedRow();
|
||||
|
||||
if (button == removeButton)
|
||||
{
|
||||
deleteKeyPressed (currentRow);
|
||||
}
|
||||
else if (button == addButton)
|
||||
{
|
||||
File start (defaultBrowseTarget);
|
||||
|
||||
if (start == File::nonexistent)
|
||||
start = path [0];
|
||||
|
||||
if (start == File::nonexistent)
|
||||
start = File::getCurrentWorkingDirectory();
|
||||
|
||||
FileChooser chooser (TRANS("Add a folder..."), start, T("*"));
|
||||
|
||||
if (chooser.browseForDirectory())
|
||||
{
|
||||
path.add (chooser.getResult(), currentRow);
|
||||
}
|
||||
}
|
||||
else if (button == changeButton)
|
||||
{
|
||||
returnKeyPressed (currentRow);
|
||||
}
|
||||
else if (button == upButton)
|
||||
{
|
||||
if (currentRow > 0 && currentRow < path.getNumPaths())
|
||||
{
|
||||
const File f (path[currentRow]);
|
||||
path.remove (currentRow);
|
||||
path.add (f, currentRow - 1);
|
||||
listBox->selectRow (currentRow - 1);
|
||||
}
|
||||
}
|
||||
else if (button == downButton)
|
||||
{
|
||||
if (currentRow >= 0 && currentRow < path.getNumPaths()-1)
|
||||
{
|
||||
const File f (path[currentRow]);
|
||||
path.remove (currentRow);
|
||||
path.add (f, currentRow + 1);
|
||||
listBox->selectRow (currentRow + 1);
|
||||
}
|
||||
}
|
||||
|
||||
changed();
|
||||
}
|
||||
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
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_FILESEARCHPATHLISTCOMPONENT_JUCEHEADER__
|
||||
#define __JUCE_FILESEARCHPATHLISTCOMPONENT_JUCEHEADER__
|
||||
|
||||
#include "../controls/juce_ListBox.h"
|
||||
#include "../buttons/juce_Button.h"
|
||||
#include "../../../../juce_core/io/files/juce_FileSearchPath.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Shows a set of file paths in a list, allowing them to be added, removed or
|
||||
re-ordered.
|
||||
|
||||
@see FileSearchPath
|
||||
*/
|
||||
class JUCE_API FileSearchPathListComponent : public Component,
|
||||
public SettableTooltipClient,
|
||||
private ButtonListener,
|
||||
private ListBoxModel
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates an empty FileSearchPathListComponent.
|
||||
|
||||
*/
|
||||
FileSearchPathListComponent();
|
||||
|
||||
/** Destructor. */
|
||||
~FileSearchPathListComponent();
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the path as it is currently shown. */
|
||||
const FileSearchPath& getPath() const throw() { return path; }
|
||||
|
||||
/** Changes the current path. */
|
||||
void setPath (const FileSearchPath& newPath);
|
||||
|
||||
/** Sets a file or directory to be the default starting point for the browser to show.
|
||||
|
||||
This is only used if the current file hasn't been set.
|
||||
*/
|
||||
void setDefaultBrowseTarget (const File& newDefaultDirectory) throw();
|
||||
|
||||
/** A set of colour IDs to use to change the colour of various aspects of the label.
|
||||
|
||||
These constants can be used either via the Component::setColour(), or LookAndFeel::setColour()
|
||||
methods.
|
||||
|
||||
@see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
|
||||
*/
|
||||
enum ColourIds
|
||||
{
|
||||
backgroundColourId = 0x1004100, /**< The background colour to fill the component with.
|
||||
Make this transparent if you don't want the background to be filled. */
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
int getNumRows();
|
||||
/** @internal */
|
||||
void paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool rowIsSelected);
|
||||
/** @internal */
|
||||
void deleteKeyPressed (int lastRowSelected);
|
||||
/** @internal */
|
||||
void returnKeyPressed (int lastRowSelected);
|
||||
/** @internal */
|
||||
void listBoxItemDoubleClicked (int row, const MouseEvent&);
|
||||
/** @internal */
|
||||
void selectedRowsChanged (int lastRowSelected);
|
||||
/** @internal */
|
||||
void resized();
|
||||
/** @internal */
|
||||
void paint (Graphics& g);
|
||||
/** @internal */
|
||||
bool filesDropped (const StringArray& filenames, int mouseX, int mouseY);
|
||||
/** @internal */
|
||||
void buttonClicked (Button* button);
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
FileSearchPath path;
|
||||
File defaultBrowseTarget;
|
||||
|
||||
ListBox* listBox;
|
||||
Button* addButton;
|
||||
Button* removeButton;
|
||||
Button* changeButton;
|
||||
Button* upButton;
|
||||
Button* downButton;
|
||||
|
||||
void changed() throw();
|
||||
void updateButtons() throw();
|
||||
|
||||
FileSearchPathListComponent (const FileSearchPathListComponent&);
|
||||
const FileSearchPathListComponent& operator= (const FileSearchPathListComponent&);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // __JUCE_FILESEARCHPATHLISTCOMPONENT_JUCEHEADER__
|
||||
|
|
@ -56,6 +56,7 @@ BEGIN_JUCE_NAMESPACE
|
|||
#include "../controls/juce_TreeView.h"
|
||||
#include "../filebrowser/juce_FilenameComponent.h"
|
||||
#include "../filebrowser/juce_DirectoryContentsDisplayComponent.h"
|
||||
#include "../filebrowser/juce_FileSearchPathListComponent.h"
|
||||
#include "../layout/juce_GroupComponent.h"
|
||||
#include "../properties/juce_PropertyComponent.h"
|
||||
#include "../juce_Desktop.h"
|
||||
|
|
@ -193,7 +194,9 @@ LookAndFeel::LookAndFeel()
|
|||
MidiKeyboardComponent::upDownButtonArrowColourId, 0xff000000,
|
||||
|
||||
ColourSelector::backgroundColourId, 0xffe5e5e5,
|
||||
ColourSelector::labelTextColourId, 0xff000000
|
||||
ColourSelector::labelTextColourId, 0xff000000,
|
||||
|
||||
FileSearchPathListComponent::backgroundColourId, 0xffffffff,
|
||||
};
|
||||
|
||||
for (int i = 0; i < numElementsInArray (standardColours); i += 2)
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ extern bool juce_makeOpenGLContextCurrent (void* context);
|
|||
extern void juce_swapOpenGLBuffers (void* context);
|
||||
extern void juce_updateOpenGLWindowPos (void* context, Component* owner, Component* topComp);
|
||||
extern void juce_repaintOpenGLWindow (void* context);
|
||||
extern bool juce_isActiveOpenGLContext (void* context) throw();
|
||||
|
||||
static VoidArray activeGLWindows (2);
|
||||
|
||||
|
|
@ -139,6 +140,11 @@ public:
|
|||
return context != 0 && juce_makeOpenGLContextCurrent (context);
|
||||
}
|
||||
|
||||
bool isActive() const throw()
|
||||
{
|
||||
return context != 0 && juce_isActiveOpenGLContext (context);
|
||||
}
|
||||
|
||||
void swapBuffers() const
|
||||
{
|
||||
if (context != 0)
|
||||
|
|
@ -222,6 +228,26 @@ void OpenGLComponent::makeCurrentContextInactive()
|
|||
juce_makeOpenGLContextCurrent (0);
|
||||
}
|
||||
|
||||
bool OpenGLComponent::isActiveContext() const throw()
|
||||
{
|
||||
const InternalGLContextHolder* const context = (InternalGLContextHolder*) internalData;
|
||||
|
||||
return context != 0 && context->isActive();
|
||||
}
|
||||
|
||||
OpenGLComponent* OpenGLComponent::getCurrentlyActiveContextComponent() throw()
|
||||
{
|
||||
for (int i = activeGLWindows.size(); --i >= 0;)
|
||||
{
|
||||
OpenGLComponent* const component = (OpenGLComponent*) activeGLWindows.getUnchecked(i);
|
||||
|
||||
if (component->isActiveContext())
|
||||
return component;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void OpenGLComponent::swapBuffers()
|
||||
{
|
||||
InternalGLContextHolder* const context = (InternalGLContextHolder*) internalData;
|
||||
|
|
|
|||
|
|
@ -78,6 +78,17 @@ public:
|
|||
*/
|
||||
void makeCurrentContextInactive();
|
||||
|
||||
/** Returns true if this component is the active openGL context for the
|
||||
current thread.
|
||||
*/
|
||||
bool isActiveContext() const throw();
|
||||
|
||||
/** Returns the OpenGLComponent that is currently the active context for
|
||||
the current thread.
|
||||
*/
|
||||
static OpenGLComponent* getCurrentlyActiveContextComponent() throw();
|
||||
|
||||
//==============================================================================
|
||||
/** Flips the openGL buffers over. */
|
||||
void swapBuffers();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue