Browse Source

tags/2021-05-28
jules 18 years ago
parent
commit
1e5a9ad56e
54 changed files with 11651 additions and 2492 deletions
  1. +6
    -0
      build/linux/JUCE.make
  2. +17
    -2
      build/linux/platform_specific_code/juce_linux_Windowing.cpp
  3. +8
    -0
      build/macosx/Juce.xcodeproj/project.pbxproj
  4. +17
    -0
      build/macosx/platform_specific_code/juce_mac_Windowing.cpp
  5. +8
    -0
      build/win32/platform_specific_code/juce_win32_Windowing.cpp
  6. +8
    -0
      build/win32/vc8/JUCE.vcproj
  7. +4
    -1
      docs/JUCE changelist.txt
  8. +26
    -0
      extras/audio plugin host/build/mac/Info.plist
  9. +371
    -0
      extras/audio plugin host/build/mac/PluginHost.xcodeproj/project.pbxproj
  10. +39
    -0
      extras/audio plugin host/build/win32/PluginHost.sln
  11. BIN
      extras/audio plugin host/build/win32/PluginHost.suo
  12. +295
    -0
      extras/audio plugin host/build/win32/PluginHost.vcproj
  13. +110
    -0
      extras/audio plugin host/src/HostStartup.cpp
  14. +744
    -0
      extras/audio plugin host/src/host/FilterGraph.cpp
  15. +269
    -0
      extras/audio plugin host/src/host/FilterGraph.h
  16. +901
    -0
      extras/audio plugin host/src/host/GraphEditorPanel.cpp
  17. +122
    -0
      extras/audio plugin host/src/host/GraphEditorPanel.h
  18. +406
    -0
      extras/audio plugin host/src/host/InternalFilters.cpp
  19. +80
    -0
      extras/audio plugin host/src/host/InternalFilters.h
  20. +484
    -0
      extras/audio plugin host/src/host/MainHostWindow.cpp
  21. +103
    -0
      extras/audio plugin host/src/host/MainHostWindow.h
  22. +73
    -0
      extras/audio plugin host/src/plugins/juce_AudioPluginFormat.cpp
  23. +154
    -0
      extras/audio plugin host/src/plugins/juce_AudioPluginFormat.h
  24. +82
    -0
      extras/audio plugin host/src/plugins/juce_AudioPluginInstance.cpp
  25. +123
    -0
      extras/audio plugin host/src/plugins/juce_AudioPluginInstance.h
  26. +314
    -0
      extras/audio plugin host/src/plugins/juce_KnownPluginList.cpp
  27. +163
    -0
      extras/audio plugin host/src/plugins/juce_KnownPluginList.h
  28. +158
    -0
      extras/audio plugin host/src/plugins/juce_PluginDescription.cpp
  29. +144
    -0
      extras/audio plugin host/src/plugins/juce_PluginDescription.h
  30. +148
    -0
      extras/audio plugin host/src/plugins/juce_PluginDirectoryScanner.cpp
  31. +116
    -0
      extras/audio plugin host/src/plugins/juce_PluginDirectoryScanner.h
  32. +261
    -0
      extras/audio plugin host/src/plugins/juce_PluginListComponent.cpp
  33. +95
    -0
      extras/audio plugin host/src/plugins/juce_PluginListComponent.h
  34. +61
    -0
      extras/audio plugin host/src/plugins/vst/juce_VSTPluginFormat.h
  35. +2540
    -0
      extras/audio plugin host/src/plugins/vst/juce_VSTPluginInstance.cpp
  36. +187
    -0
      extras/audio plugin host/src/plugins/vst/juce_VSTPluginInstance.h
  37. +55
    -0
      extras/audio plugins/demo/build/VST_Linux/premake.lua
  38. +3
    -0
      extras/audio plugins/wrapper/formats/RTAS/juce_RTASWrapper.cpp
  39. +1312
    -1316
      extras/audio plugins/wrapper/formats/VST/juce_VstWrapper.cpp
  40. +10
    -15
      extras/audio plugins/wrapper/juce_AudioFilterBase.cpp
  41. +21
    -5
      extras/audio plugins/wrapper/juce_AudioFilterBase.h
  42. +1144
    -1144
      extras/juce demo/src/BinaryData.cpp
  43. +1
    -1
      extras/juce demo/src/BinaryData.h
  44. +2
    -2
      extras/juce demo/src/binarydata/WidgetsDemo.cpp
  45. +1
    -1
      extras/juce demo/src/demos/WidgetsDemo.cpp
  46. +1
    -0
      extras/the jucer/src/ui/jucer_MainWindow.cpp
  47. +3
    -0
      src/juce_app_includes.h
  48. +6
    -3
      src/juce_appframework/documents/juce_FileBasedDocument.cpp
  49. +1
    -1
      src/juce_appframework/gui/components/filebrowser/juce_FileChooser.h
  50. +279
    -0
      src/juce_appframework/gui/components/filebrowser/juce_FileSearchPathListComponent.cpp
  51. +134
    -0
      src/juce_appframework/gui/components/filebrowser/juce_FileSearchPathListComponent.h
  52. +4
    -1
      src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.cpp
  53. +26
    -0
      src/juce_appframework/gui/components/special/juce_OpenGLComponent.cpp
  54. +11
    -0
      src/juce_appframework/gui/components/special/juce_OpenGLComponent.h

+ 6
- 0
build/linux/JUCE.make View File

@@ -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 $<)


+ 17
- 2
build/linux/platform_specific_code/juce_linux_Windowing.cpp View File

@@ -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;


+ 8
- 0
build/macosx/Juce.xcodeproj/project.pbxproj View File

@@ -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;
};


+ 17
- 0
build/macosx/platform_specific_code/juce_mac_Windowing.cpp View File

@@ -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;


+ 8
- 0
build/win32/platform_specific_code/juce_win32_Windowing.cpp View File

@@ -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;


+ 8
- 0
build/win32/vc8/JUCE.vcproj View File

@@ -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"
>


+ 4
- 1
docs/JUCE changelist.txt View File

@@ -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
- 0
extras/audio plugin host/build/mac/Info.plist View 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>

+ 371
- 0
extras/audio plugin host/build/mac/PluginHost.xcodeproj/project.pbxproj View File

@@ -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
- 0
extras/audio plugin host/build/win32/PluginHost.sln View 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 View File


+ 295
- 0
extras/audio plugin host/build/win32/PluginHost.vcproj View 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
- 0
extras/audio plugin host/src/HostStartup.cpp View 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
- 0
extras/audio plugin host/src/host/FilterGraph.cpp View 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
- 0
extras/audio plugin host/src/host/FilterGraph.h View 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
- 0
extras/audio plugin host/src/host/GraphEditorPanel.cpp View 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
- 0
extras/audio plugin host/src/host/GraphEditorPanel.h View 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
- 0
extras/audio plugin host/src/host/InternalFilters.cpp View 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
- 0
extras/audio plugin host/src/host/InternalFilters.h View 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
- 0
extras/audio plugin host/src/host/MainHostWindow.cpp View 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
- 0
extras/audio plugin host/src/host/MainHostWindow.h View 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

+ 73
- 0
extras/audio plugin host/src/plugins/juce_AudioPluginFormat.cpp View File

@@ -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
- 0
extras/audio plugin host/src/plugins/juce_AudioPluginFormat.h View 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__

+ 82
- 0
extras/audio plugin host/src/plugins/juce_AudioPluginInstance.cpp View File

@@ -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
- 0
extras/audio plugin host/src/plugins/juce_AudioPluginInstance.h View 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
- 0
extras/audio plugin host/src/plugins/juce_KnownPluginList.cpp View 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
- 0
extras/audio plugin host/src/plugins/juce_KnownPluginList.h View 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
- 0
extras/audio plugin host/src/plugins/juce_PluginDescription.cpp View 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
- 0
extras/audio plugin host/src/plugins/juce_PluginDescription.h View 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__

+ 148
- 0
extras/audio plugin host/src/plugins/juce_PluginDirectoryScanner.cpp View File

@@ -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);
}

+ 116
- 0
extras/audio plugin host/src/plugins/juce_PluginDirectoryScanner.h View File

@@ -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__

+ 261
- 0
extras/audio plugin host/src/plugins/juce_PluginListComponent.cpp View File

@@ -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();
}
}

+ 95
- 0
extras/audio plugin host/src/plugins/juce_PluginListComponent.h View File

@@ -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__

+ 61
- 0
extras/audio plugin host/src/plugins/vst/juce_VSTPluginFormat.h View File

@@ -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
- 0
extras/audio plugin host/src/plugins/vst/juce_VSTPluginInstance.cpp
File diff suppressed because it is too large
View File


+ 187
- 0
extras/audio plugin host/src/plugins/vst/juce_VSTPluginInstance.h View File

@@ -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
- 0
extras/audio plugins/demo/build/VST_Linux/premake.lua View 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"
)
}

+ 3
- 0
extras/audio plugins/wrapper/formats/RTAS/juce_RTASWrapper.cpp View File

@@ -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));
}


+ 1312
- 1316
extras/audio plugins/wrapper/formats/VST/juce_VstWrapper.cpp
File diff suppressed because it is too large
View File


+ 10
- 15
extras/audio plugins/wrapper/juce_AudioFilterBase.cpp View File

@@ -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;


+ 21
- 5
extras/audio plugins/wrapper/juce_AudioFilterBase.h View File

@@ -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;


+ 1144
- 1144
extras/juce demo/src/BinaryData.cpp
File diff suppressed because it is too large
View File


+ 1
- 1
extras/juce demo/src/BinaryData.h View File

@@ -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;
};


+ 2
- 2
extras/juce demo/src/binarydata/WidgetsDemo.cpp View File

@@ -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.


+ 1
- 1
extras/juce demo/src/demos/WidgetsDemo.cpp View File

@@ -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


+ 1
- 0
extras/the jucer/src/ui/jucer_MainWindow.cpp View File

@@ -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);


+ 3
- 0
src/juce_app_includes.h View File

@@ -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


+ 6
- 3
src/juce_appframework/documents/juce_FileBasedDocument.cpp View File

@@ -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;


+ 1
- 1
src/juce_appframework/gui/components/filebrowser/juce_FileChooser.h View File

@@ -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())


+ 279
- 0
src/juce_appframework/gui/components/filebrowser/juce_FileSearchPathListComponent.cpp View File

@@ -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

+ 134
- 0
src/juce_appframework/gui/components/filebrowser/juce_FileSearchPathListComponent.h View File

@@ -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__

+ 4
- 1
src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.cpp View File

@@ -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)


+ 26
- 0
src/juce_appframework/gui/components/special/juce_OpenGLComponent.cpp View File

@@ -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;


+ 11
- 0
src/juce_appframework/gui/components/special/juce_OpenGLComponent.h View File

@@ -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…
Cancel
Save