1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

Move AudioPluginHost and NetworkGraphicsDemo projects from examples to extras

This commit is contained in:
ed 2018-03-13 09:18:44 +00:00
parent 66ee9d6d6d
commit 44f9a5c256
166 changed files with 0 additions and 0 deletions

View file

@ -0,0 +1,168 @@
<?xml version="1.0" encoding="UTF-8"?>
<JUCERPROJECT id="NTe0XB0ij" name="AudioPluginHost" projectType="guiapp" version="1.0.0"
juceFolder="../../../juce" vstFolderMac="~/SDKs/vstsdk2.4" vstFolderPC="c:\SDKs\vstsdk2.4"
bundleIdentifier="com.roli.pluginhost" jucerVersion="5.2.1" companyName="ROLI Ltd."
displaySplashScreen="0" reportAppUsage="0" companyCopyright="ROLI Ltd.">
<EXPORTFORMATS>
<XCODE_MAC targetFolder="Builds/MacOSX" vstFolder="" rtasFolder="~/SDKs/PT_80_SDK"
objCExtraSuffix="M73TRi" vst3Folder="" extraCompilerFlags="-Wall -Wshadow -Wstrict-aliasing -Wconversion -Wsign-compare -Woverloaded-virtual -Wextra-semi">
<CONFIGURATIONS>
<CONFIGURATION name="Debug" isDebug="1" targetName="AudioPluginHost"/>
<CONFIGURATION name="Release" isDebug="0" optimisation="2" targetName="AudioPluginHost"/>
</CONFIGURATIONS>
<MODULEPATHS>
<MODULEPATH id="juce_video" path="../../modules"/>
<MODULEPATH id="juce_opengl" path="../../modules"/>
<MODULEPATH id="juce_gui_extra" path="../../modules"/>
<MODULEPATH id="juce_gui_basics" path="../../modules"/>
<MODULEPATH id="juce_graphics" path="../../modules"/>
<MODULEPATH id="juce_events" path="../../modules"/>
<MODULEPATH id="juce_data_structures" path="../../modules"/>
<MODULEPATH id="juce_cryptography" path="../../modules"/>
<MODULEPATH id="juce_core" path="../../modules"/>
<MODULEPATH id="juce_audio_utils" path="../../modules"/>
<MODULEPATH id="juce_audio_processors" path="../../modules"/>
<MODULEPATH id="juce_audio_formats" path="../../modules"/>
<MODULEPATH id="juce_audio_devices" path="../../modules"/>
<MODULEPATH id="juce_audio_basics" path="../../modules"/>
</MODULEPATHS>
</XCODE_MAC>
<LINUX_MAKE targetFolder="Builds/LinuxMakefile" vstFolder="" vst3Folder="">
<CONFIGURATIONS>
<CONFIGURATION name="Debug" isDebug="1" targetName="AudioPluginHost" libraryPath="/usr/X11R6/lib/"/>
<CONFIGURATION name="Release" isDebug="0" optimisation="2" targetName="AudioPluginHost"
libraryPath="/usr/X11R6/lib/"/>
</CONFIGURATIONS>
<MODULEPATHS>
<MODULEPATH id="juce_video" path="../../modules"/>
<MODULEPATH id="juce_opengl" path="../../modules"/>
<MODULEPATH id="juce_gui_extra" path="../../modules"/>
<MODULEPATH id="juce_gui_basics" path="../../modules"/>
<MODULEPATH id="juce_graphics" path="../../modules"/>
<MODULEPATH id="juce_events" path="../../modules"/>
<MODULEPATH id="juce_data_structures" path="../../modules"/>
<MODULEPATH id="juce_cryptography" path="../../modules"/>
<MODULEPATH id="juce_core" path="../../modules"/>
<MODULEPATH id="juce_audio_utils" path="../../modules"/>
<MODULEPATH id="juce_audio_processors" path="../../modules"/>
<MODULEPATH id="juce_audio_formats" path="../../modules"/>
<MODULEPATH id="juce_audio_devices" path="../../modules"/>
<MODULEPATH id="juce_audio_basics" path="../../modules"/>
</MODULEPATHS>
</LINUX_MAKE>
<VS2013 targetFolder="Builds/VisualStudio2013" vstFolder="" vst3Folder="">
<CONFIGURATIONS>
<CONFIGURATION name="Debug" winArchitecture="32-bit" isDebug="1" optimisation="1"
targetName="AudioPluginHost"/>
<CONFIGURATION name="Release" winArchitecture="32-bit" isDebug="0" targetName="AudioPluginHost"
debugInformationFormat="ProgramDatabase"/>
</CONFIGURATIONS>
<MODULEPATHS>
<MODULEPATH id="juce_video" path="../../modules"/>
<MODULEPATH id="juce_opengl" path="../../modules"/>
<MODULEPATH id="juce_gui_extra" path="../../modules"/>
<MODULEPATH id="juce_gui_basics" path="../../modules"/>
<MODULEPATH id="juce_graphics" path="../../modules"/>
<MODULEPATH id="juce_events" path="../../modules"/>
<MODULEPATH id="juce_data_structures" path="../../modules"/>
<MODULEPATH id="juce_cryptography" path="../../modules"/>
<MODULEPATH id="juce_core" path="../../modules"/>
<MODULEPATH id="juce_audio_utils" path="../../modules"/>
<MODULEPATH id="juce_audio_processors" path="../../modules"/>
<MODULEPATH id="juce_audio_formats" path="../../modules"/>
<MODULEPATH id="juce_audio_devices" path="../../modules"/>
<MODULEPATH id="juce_audio_basics" path="../../modules"/>
</MODULEPATHS>
</VS2013>
<VS2015 targetFolder="Builds/VisualStudio2015" vstFolder="" vst3Folder="">
<CONFIGURATIONS>
<CONFIGURATION name="Debug" isDebug="1" targetName="AudioPluginHost"/>
<CONFIGURATION name="Release" isDebug="0" targetName="AudioPluginHost" debugInformationFormat="ProgramDatabase"/>
</CONFIGURATIONS>
<MODULEPATHS>
<MODULEPATH id="juce_video" path="../../modules"/>
<MODULEPATH id="juce_opengl" path="../../modules"/>
<MODULEPATH id="juce_gui_extra" path="../../modules"/>
<MODULEPATH id="juce_gui_basics" path="../../modules"/>
<MODULEPATH id="juce_graphics" path="../../modules"/>
<MODULEPATH id="juce_events" path="../../modules"/>
<MODULEPATH id="juce_data_structures" path="../../modules"/>
<MODULEPATH id="juce_cryptography" path="../../modules"/>
<MODULEPATH id="juce_core" path="../../modules"/>
<MODULEPATH id="juce_audio_utils" path="../../modules"/>
<MODULEPATH id="juce_audio_processors" path="../../modules"/>
<MODULEPATH id="juce_audio_formats" path="../../modules"/>
<MODULEPATH id="juce_audio_devices" path="../../modules"/>
<MODULEPATH id="juce_audio_basics" path="../../modules"/>
</MODULEPATHS>
</VS2015>
<VS2017 targetFolder="Builds/VisualStudio2017" vst3Folder="">
<CONFIGURATIONS>
<CONFIGURATION name="Debug" isDebug="1" targetName="AudioPluginHost"/>
<CONFIGURATION name="Release" isDebug="0" targetName="AudioPluginHost" debugInformationFormat="ProgramDatabase"/>
</CONFIGURATIONS>
<MODULEPATHS>
<MODULEPATH id="juce_video" path="../../modules"/>
<MODULEPATH id="juce_opengl" path="../../modules"/>
<MODULEPATH id="juce_gui_extra" path="../../modules"/>
<MODULEPATH id="juce_gui_basics" path="../../modules"/>
<MODULEPATH id="juce_graphics" path="../../modules"/>
<MODULEPATH id="juce_events" path="../../modules"/>
<MODULEPATH id="juce_data_structures" path="../../modules"/>
<MODULEPATH id="juce_cryptography" path="../../modules"/>
<MODULEPATH id="juce_core" path="../../modules"/>
<MODULEPATH id="juce_audio_utils" path="../../modules"/>
<MODULEPATH id="juce_audio_processors" path="../../modules"/>
<MODULEPATH id="juce_audio_formats" path="../../modules"/>
<MODULEPATH id="juce_audio_devices" path="../../modules"/>
<MODULEPATH id="juce_audio_basics" path="../../modules"/>
</MODULEPATHS>
</VS2017>
</EXPORTFORMATS>
<MAINGROUP id="YdWL7hi7p" name="AudioPluginHost">
<FILE id="8tLeuntR4" name="FilterGraph.cpp" compile="1" resource="0"
file="Source/FilterGraph.cpp"/>
<FILE id="auGSxnlTU" name="FilterGraph.h" compile="0" resource="0"
file="Source/FilterGraph.h"/>
<FILE id="cnfPX5" name="FilterIOConfiguration.cpp" compile="1" resource="0"
file="Source/FilterIOConfiguration.cpp"/>
<FILE id="ZVUq7Q" name="FilterIOConfiguration.h" compile="0" resource="0"
file="Source/FilterIOConfiguration.h"/>
<FILE id="2b09bSUt" name="GraphEditorPanel.cpp" compile="1" resource="0"
file="Source/GraphEditorPanel.cpp"/>
<FILE id="sj8Yug8cu" name="GraphEditorPanel.h" compile="0" resource="0"
file="Source/GraphEditorPanel.h"/>
<FILE id="nehnGjkrX" name="HostStartup.cpp" compile="1" resource="0"
file="Source/HostStartup.cpp"/>
<FILE id="J6HWWSQP1" name="InternalFilters.cpp" compile="1" resource="0"
file="Source/InternalFilters.cpp"/>
<FILE id="AplCcJ0La" name="InternalFilters.h" compile="0" resource="0"
file="Source/InternalFilters.h"/>
<FILE id="mFVSjbHfN" name="MainHostWindow.cpp" compile="1" resource="0"
file="Source/MainHostWindow.cpp"/>
<FILE id="h1kpxyzHi" name="MainHostWindow.h" compile="0" resource="0"
file="Source/MainHostWindow.h"/>
<FILE id="ZwQDmm" name="PluginWindow.h" compile="0" resource="0" file="Source/PluginWindow.h"/>
</MAINGROUP>
<JUCEOPTIONS JUCE_WASAPI="1" JUCE_DIRECTSOUND="1" JUCE_ALSA="1" JUCE_USE_FLAC="0"
JUCE_USE_OGGVORBIS="0" JUCE_USE_CDBURNER="0" JUCE_USE_CDREADER="0"
JUCE_USE_CAMERA="0" JUCE_PLUGINHOST_VST="1" JUCE_PLUGINHOST_AU="1"
JUCE_WEB_BROWSER="0" JUCE_PLUGINHOST_VST3="1"/>
<MODULES>
<MODULE id="juce_audio_basics" showAllCode="1"/>
<MODULE id="juce_audio_devices" showAllCode="1"/>
<MODULE id="juce_audio_formats" showAllCode="1"/>
<MODULE id="juce_audio_processors" showAllCode="1"/>
<MODULE id="juce_audio_utils" showAllCode="1"/>
<MODULE id="juce_core" showAllCode="1"/>
<MODULE id="juce_cryptography" showAllCode="1"/>
<MODULE id="juce_data_structures" showAllCode="1"/>
<MODULE id="juce_events" showAllCode="1"/>
<MODULE id="juce_graphics" showAllCode="1"/>
<MODULE id="juce_gui_basics" showAllCode="1"/>
<MODULE id="juce_gui_extra" showAllCode="1"/>
<MODULE id="juce_opengl" showAllCode="1"/>
<MODULE id="juce_video" showAllCode="1"/>
</MODULES>
</JUCERPROJECT>

View file

@ -0,0 +1,215 @@
# Automatically generated makefile, created by the Projucer
# Don't edit this file! Your changes will be overwritten when you re-save the Projucer project!
# build with "V=1" for verbose builds
ifeq ($(V), 1)
V_AT =
else
V_AT = @
endif
# (this disables dependency generation if multiple architectures are set)
DEPFLAGS := $(if $(word 2, $(TARGET_ARCH)), , -MMD)
ifndef STRIP
STRIP=strip
endif
ifndef AR
AR=ar
endif
ifndef CONFIG
CONFIG=Debug
endif
JUCE_ARCH_LABEL := $(shell uname -m)
ifeq ($(CONFIG),Debug)
JUCE_BINDIR := build
JUCE_LIBDIR := build
JUCE_OBJDIR := build/intermediate/Debug
JUCE_OUTDIR := build
ifeq ($(TARGET_ARCH),)
TARGET_ARCH := -march=native
endif
JUCE_CPPFLAGS := $(DEPFLAGS) -DLINUX=1 -DDEBUG=1 -D_DEBUG=1 -DJUCER_LINUX_MAKE_6D53C8B4=1 -DJUCE_APP_VERSION=1.0.0 -DJUCE_APP_VERSION_HEX=0x10000 $(shell pkg-config --cflags alsa freetype2 libcurl x11 xext xinerama) -pthread -I$(HOME)/SDKs/VST_SDK/VST3_SDK -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
JUCE_CPPFLAGS_APP := -DJucePlugin_Build_VST=0 -DJucePlugin_Build_VST3=0 -DJucePlugin_Build_AU=0 -DJucePlugin_Build_AUv3=0 -DJucePlugin_Build_RTAS=0 -DJucePlugin_Build_AAX=0 -DJucePlugin_Build_Standalone=0
JUCE_TARGET_APP := AudioPluginHost
JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -g -ggdb -O0 $(CFLAGS)
JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++14 $(CXXFLAGS)
JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) -L/usr/X11R6/lib/ $(shell pkg-config --libs alsa freetype2 libcurl x11 xext xinerama) -lGL -ldl -lpthread -lrt $(LDFLAGS)
CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)
endif
ifeq ($(CONFIG),Release)
JUCE_BINDIR := build
JUCE_LIBDIR := build
JUCE_OBJDIR := build/intermediate/Release
JUCE_OUTDIR := build
ifeq ($(TARGET_ARCH),)
TARGET_ARCH := -march=native
endif
JUCE_CPPFLAGS := $(DEPFLAGS) -DLINUX=1 -DNDEBUG=1 -DJUCER_LINUX_MAKE_6D53C8B4=1 -DJUCE_APP_VERSION=1.0.0 -DJUCE_APP_VERSION_HEX=0x10000 $(shell pkg-config --cflags alsa freetype2 libcurl x11 xext xinerama) -pthread -I$(HOME)/SDKs/VST_SDK/VST3_SDK -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
JUCE_CPPFLAGS_APP := -DJucePlugin_Build_VST=0 -DJucePlugin_Build_VST3=0 -DJucePlugin_Build_AU=0 -DJucePlugin_Build_AUv3=0 -DJucePlugin_Build_RTAS=0 -DJucePlugin_Build_AAX=0 -DJucePlugin_Build_Standalone=0
JUCE_TARGET_APP := AudioPluginHost
JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -Os $(CFLAGS)
JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++14 $(CXXFLAGS)
JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) -L/usr/X11R6/lib/ $(shell pkg-config --libs alsa freetype2 libcurl x11 xext xinerama) -fvisibility=hidden -lGL -ldl -lpthread -lrt $(LDFLAGS)
CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)
endif
OBJECTS_APP := \
$(JUCE_OBJDIR)/FilterGraph_62e9c017.o \
$(JUCE_OBJDIR)/FilterIOConfiguration_1cc9b659.o \
$(JUCE_OBJDIR)/GraphEditorPanel_3dbd4872.o \
$(JUCE_OBJDIR)/HostStartup_5ce96f96.o \
$(JUCE_OBJDIR)/InternalFilters_beb54bdf.o \
$(JUCE_OBJDIR)/MainHostWindow_e920295a.o \
$(JUCE_OBJDIR)/include_juce_audio_basics_8a4e984a.o \
$(JUCE_OBJDIR)/include_juce_audio_devices_63111d02.o \
$(JUCE_OBJDIR)/include_juce_audio_formats_15f82001.o \
$(JUCE_OBJDIR)/include_juce_audio_processors_10c03666.o \
$(JUCE_OBJDIR)/include_juce_audio_utils_9f9fb2d6.o \
$(JUCE_OBJDIR)/include_juce_core_f26d17db.o \
$(JUCE_OBJDIR)/include_juce_cryptography_8cb807a8.o \
$(JUCE_OBJDIR)/include_juce_data_structures_7471b1e3.o \
$(JUCE_OBJDIR)/include_juce_events_fd7d695.o \
$(JUCE_OBJDIR)/include_juce_graphics_f817e147.o \
$(JUCE_OBJDIR)/include_juce_gui_basics_e3f79785.o \
$(JUCE_OBJDIR)/include_juce_gui_extra_6dee1c1a.o \
$(JUCE_OBJDIR)/include_juce_opengl_a8a032b.o \
$(JUCE_OBJDIR)/include_juce_video_be78589.o \
.PHONY: clean all
all : $(JUCE_OUTDIR)/$(JUCE_TARGET_APP)
$(JUCE_OUTDIR)/$(JUCE_TARGET_APP) : check-pkg-config $(OBJECTS_APP) $(RESOURCES)
@echo Linking "AudioPluginHost - App"
-$(V_AT)mkdir -p $(JUCE_BINDIR)
-$(V_AT)mkdir -p $(JUCE_LIBDIR)
-$(V_AT)mkdir -p $(JUCE_OUTDIR)
$(V_AT)$(CXX) -o $(JUCE_OUTDIR)/$(JUCE_TARGET_APP) $(OBJECTS_APP) $(JUCE_LDFLAGS) $(JUCE_LDFLAGS_APP) $(RESOURCES) $(TARGET_ARCH)
$(JUCE_OBJDIR)/FilterGraph_62e9c017.o: ../../Source/FilterGraph.cpp
-$(V_AT)mkdir -p $(JUCE_OBJDIR)
@echo "Compiling FilterGraph.cpp"
$(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<"
$(JUCE_OBJDIR)/FilterIOConfiguration_1cc9b659.o: ../../Source/FilterIOConfiguration.cpp
-$(V_AT)mkdir -p $(JUCE_OBJDIR)
@echo "Compiling FilterIOConfiguration.cpp"
$(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<"
$(JUCE_OBJDIR)/GraphEditorPanel_3dbd4872.o: ../../Source/GraphEditorPanel.cpp
-$(V_AT)mkdir -p $(JUCE_OBJDIR)
@echo "Compiling GraphEditorPanel.cpp"
$(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<"
$(JUCE_OBJDIR)/HostStartup_5ce96f96.o: ../../Source/HostStartup.cpp
-$(V_AT)mkdir -p $(JUCE_OBJDIR)
@echo "Compiling HostStartup.cpp"
$(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<"
$(JUCE_OBJDIR)/InternalFilters_beb54bdf.o: ../../Source/InternalFilters.cpp
-$(V_AT)mkdir -p $(JUCE_OBJDIR)
@echo "Compiling InternalFilters.cpp"
$(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<"
$(JUCE_OBJDIR)/MainHostWindow_e920295a.o: ../../Source/MainHostWindow.cpp
-$(V_AT)mkdir -p $(JUCE_OBJDIR)
@echo "Compiling MainHostWindow.cpp"
$(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<"
$(JUCE_OBJDIR)/include_juce_audio_basics_8a4e984a.o: ../../JuceLibraryCode/include_juce_audio_basics.cpp
-$(V_AT)mkdir -p $(JUCE_OBJDIR)
@echo "Compiling include_juce_audio_basics.cpp"
$(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<"
$(JUCE_OBJDIR)/include_juce_audio_devices_63111d02.o: ../../JuceLibraryCode/include_juce_audio_devices.cpp
-$(V_AT)mkdir -p $(JUCE_OBJDIR)
@echo "Compiling include_juce_audio_devices.cpp"
$(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<"
$(JUCE_OBJDIR)/include_juce_audio_formats_15f82001.o: ../../JuceLibraryCode/include_juce_audio_formats.cpp
-$(V_AT)mkdir -p $(JUCE_OBJDIR)
@echo "Compiling include_juce_audio_formats.cpp"
$(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<"
$(JUCE_OBJDIR)/include_juce_audio_processors_10c03666.o: ../../JuceLibraryCode/include_juce_audio_processors.cpp
-$(V_AT)mkdir -p $(JUCE_OBJDIR)
@echo "Compiling include_juce_audio_processors.cpp"
$(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<"
$(JUCE_OBJDIR)/include_juce_audio_utils_9f9fb2d6.o: ../../JuceLibraryCode/include_juce_audio_utils.cpp
-$(V_AT)mkdir -p $(JUCE_OBJDIR)
@echo "Compiling include_juce_audio_utils.cpp"
$(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<"
$(JUCE_OBJDIR)/include_juce_core_f26d17db.o: ../../JuceLibraryCode/include_juce_core.cpp
-$(V_AT)mkdir -p $(JUCE_OBJDIR)
@echo "Compiling include_juce_core.cpp"
$(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<"
$(JUCE_OBJDIR)/include_juce_cryptography_8cb807a8.o: ../../JuceLibraryCode/include_juce_cryptography.cpp
-$(V_AT)mkdir -p $(JUCE_OBJDIR)
@echo "Compiling include_juce_cryptography.cpp"
$(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<"
$(JUCE_OBJDIR)/include_juce_data_structures_7471b1e3.o: ../../JuceLibraryCode/include_juce_data_structures.cpp
-$(V_AT)mkdir -p $(JUCE_OBJDIR)
@echo "Compiling include_juce_data_structures.cpp"
$(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<"
$(JUCE_OBJDIR)/include_juce_events_fd7d695.o: ../../JuceLibraryCode/include_juce_events.cpp
-$(V_AT)mkdir -p $(JUCE_OBJDIR)
@echo "Compiling include_juce_events.cpp"
$(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<"
$(JUCE_OBJDIR)/include_juce_graphics_f817e147.o: ../../JuceLibraryCode/include_juce_graphics.cpp
-$(V_AT)mkdir -p $(JUCE_OBJDIR)
@echo "Compiling include_juce_graphics.cpp"
$(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<"
$(JUCE_OBJDIR)/include_juce_gui_basics_e3f79785.o: ../../JuceLibraryCode/include_juce_gui_basics.cpp
-$(V_AT)mkdir -p $(JUCE_OBJDIR)
@echo "Compiling include_juce_gui_basics.cpp"
$(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<"
$(JUCE_OBJDIR)/include_juce_gui_extra_6dee1c1a.o: ../../JuceLibraryCode/include_juce_gui_extra.cpp
-$(V_AT)mkdir -p $(JUCE_OBJDIR)
@echo "Compiling include_juce_gui_extra.cpp"
$(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<"
$(JUCE_OBJDIR)/include_juce_opengl_a8a032b.o: ../../JuceLibraryCode/include_juce_opengl.cpp
-$(V_AT)mkdir -p $(JUCE_OBJDIR)
@echo "Compiling include_juce_opengl.cpp"
$(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<"
$(JUCE_OBJDIR)/include_juce_video_be78589.o: ../../JuceLibraryCode/include_juce_video.cpp
-$(V_AT)mkdir -p $(JUCE_OBJDIR)
@echo "Compiling include_juce_video.cpp"
$(V_AT)$(CXX) $(JUCE_CXXFLAGS) $(JUCE_CPPFLAGS_APP) $(JUCE_CFLAGS_APP) -o "$@" -c "$<"
check-pkg-config:
@command -v pkg-config >/dev/null 2>&1 || { echo >&2 "pkg-config not installed. Please, install it."; exit 1; }
@pkg-config --print-errors alsa freetype2 libcurl x11 xext xinerama
clean:
@echo Cleaning AudioPluginHost
$(V_AT)$(CLEANCMD)
strip:
@echo Stripping AudioPluginHost
-$(V_AT)$(STRIP) --strip-unneeded $(JUCE_OUTDIR)/$(TARGET)
-include $(OBJECTS_APP:%.o=%.d)

View file

@ -0,0 +1,376 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
FCDB1F8A93F59E0F97821456 = {isa = PBXBuildFile; fileRef = 8D8BBC353637DA442C5575DA; };
73E371F1B912FCCAE0CD7E5D = {isa = PBXBuildFile; fileRef = 86CA337014D3F67E906FFD28; };
21D330A5B13178B12BEAFC3C = {isa = PBXBuildFile; fileRef = D4EBC17BDB7F88CCBC76730B; };
B288A89F96704F142ED8E939 = {isa = PBXBuildFile; fileRef = 5ACC21AA45BBF48C3C64D56D; };
851C1165C9E4ACDD19C56A96 = {isa = PBXBuildFile; fileRef = 942A0F04EFB8D0B2FF9780BA; };
AF42316D915057E930A5624E = {isa = PBXBuildFile; fileRef = A4B568E26157FC282214976F; };
2B4B9CF71F94BDD1E3AC89AE = {isa = PBXBuildFile; fileRef = B0935EBBA4F6E2B05F3D1C0A; };
AC3BED74AC7C6D9F5739F38B = {isa = PBXBuildFile; fileRef = 9794142D24966F93FFDE51A1; };
E3CB85BA817BC9E3942A8AB0 = {isa = PBXBuildFile; fileRef = 9F9B445E6755CAA19E4344ED; };
70580743C3D5695F065FF698 = {isa = PBXBuildFile; fileRef = E68018DE199135B7F738FB17; };
3470F40DA5D68EC217872906 = {isa = PBXBuildFile; fileRef = 31D55A751C790CB81F58DDB7; };
E092A70431B046BF1F50A482 = {isa = PBXBuildFile; fileRef = 5AF0CA7CDFCA90B4DE1F55C3; };
E2BAA7CFC729809530FD71EE = {isa = PBXBuildFile; fileRef = B8774D8AD307D798831C0DF7; };
68FBFDA1FE637B3EDA09A592 = {isa = PBXBuildFile; fileRef = 4DF6E6E41E10965AD169143B; };
BBA1733CF8B064A5FD0B4CF4 = {isa = PBXBuildFile; fileRef = D313CF37B25D7FD313C4F336; };
A02C9F4C4B840C27B6CAFEBD = {isa = PBXBuildFile; fileRef = 89309C0C5F3269BD06BE7F27; };
4DB15177DDC357F4503F88CF = {isa = PBXBuildFile; fileRef = B457EE687507BF1DEEA7581F; };
D92C7BF86C9CCF6B4D14F809 = {isa = PBXBuildFile; fileRef = 7DA35787B5F6F7440D667CC8; };
4C88899EB7993A76A97643FE = {isa = PBXBuildFile; fileRef = 9BA1DD697B98005D24F7EC3C; };
485A37478F7EAA352DD1A86A = {isa = PBXBuildFile; fileRef = 01FE7ED58992BC9683BA3C94; };
040EB574807E8A86F124D851 = {isa = PBXBuildFile; fileRef = B1C6B9E4B9FDC17AA298E541; };
A1B0416DA378BB0C3AD6F74B = {isa = PBXBuildFile; fileRef = A66EFAC64B1B67B536C73415; };
D493393499E0822C70009A63 = {isa = PBXBuildFile; fileRef = 362BB539489999164C3A3D5B; };
6CD3B433544911DA879170AE = {isa = PBXBuildFile; fileRef = 1EC0F33A3BABE58138317375; };
15CCE43D7DCFC649638919D4 = {isa = PBXBuildFile; fileRef = 4C7D82F9274A4F9DBF11235C; };
5C4D406B924230F83E3580AD = {isa = PBXBuildFile; fileRef = 65968EA1B476D71F14DE1D58; };
F4DD98B9310B679D50A2C8A6 = {isa = PBXBuildFile; fileRef = 5D250A57C7DEA80248F30EED; };
CAF0DE157C8F7D9F168AA3B6 = {isa = PBXBuildFile; fileRef = 5FBD6C402617272052BB4D81; };
0F20A4AE04736634F097F5A6 = {isa = PBXBuildFile; fileRef = B285CAB91AE928C476CA4F9C; };
76A80851698FC773D2479B4E = {isa = PBXBuildFile; fileRef = 683CEE986A2467C850FE99E6; };
E4A926EF695823F0F13268FF = {isa = PBXBuildFile; fileRef = B8E24A5CEE6B7055537725CF; };
A09E93F1B354E1FF8B3E9ABE = {isa = PBXBuildFile; fileRef = 5EF1D381F42AA8764597F189; };
7DE202DC1D876F49266D9E7D = {isa = PBXBuildFile; fileRef = 8290D7BAC160B3A56B66891A; };
075C54DDDBDEA5AAD2F60154 = {isa = PBXBuildFile; fileRef = 82800DBA287EF4BAB13B42FB; };
2C3D221D2AA87F07B3F1044D = {isa = PBXBuildFile; fileRef = 8FE7B37CDE0818DB27BDDEBD; };
C38D14DC58F1941DD5E4BF60 = {isa = PBXBuildFile; fileRef = 2BE6C2DFD6EBB9A89109AEB5; };
2727A191DB1BAAC9C04B9081 = {isa = PBXBuildFile; fileRef = 37E4D5C341406B7072120006; };
84BAFE82A102D9C350672689 = {isa = PBXBuildFile; fileRef = 29D746FC68F69751796671A2; };
01FE7ED58992BC9683BA3C94 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = FilterIOConfiguration.cpp; path = ../../Source/FilterIOConfiguration.cpp; sourceTree = "SOURCE_ROOT"; };
18DD15714443AFC3BAAE211C = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FilterIOConfiguration.h; path = ../../Source/FilterIOConfiguration.h; sourceTree = "SOURCE_ROOT"; };
1EC0F33A3BABE58138317375 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = MainHostWindow.cpp; path = ../../Source/MainHostWindow.cpp; sourceTree = "SOURCE_ROOT"; };
29D746FC68F69751796671A2 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_video.mm"; path = "../../JuceLibraryCode/include_juce_video.mm"; sourceTree = "SOURCE_ROOT"; };
2B143B5431318DDB2104B46E = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FilterGraph.h; path = ../../Source/FilterGraph.h; sourceTree = "SOURCE_ROOT"; };
2BE6C2DFD6EBB9A89109AEB5 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_gui_extra.mm"; path = "../../JuceLibraryCode/include_juce_gui_extra.mm"; sourceTree = "SOURCE_ROOT"; };
30F22843EFEBF7AA841EB4D6 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AppConfig.h; path = ../../JuceLibraryCode/AppConfig.h; sourceTree = "SOURCE_ROOT"; };
31D55A751C790CB81F58DDB7 = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; };
362BB539489999164C3A3D5B = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = InternalFilters.cpp; path = ../../Source/InternalFilters.cpp; sourceTree = "SOURCE_ROOT"; };
37E4D5C341406B7072120006 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_opengl.mm"; path = "../../JuceLibraryCode/include_juce_opengl.mm"; sourceTree = "SOURCE_ROOT"; };
3C070DD522CDD11FFC87425D = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_audio_utils"; path = "../../../../modules/juce_audio_utils"; sourceTree = "SOURCE_ROOT"; };
3D57FE2A8877F12A61054726 = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_core"; path = "../../../../modules/juce_core"; sourceTree = "SOURCE_ROOT"; };
4C7D82F9274A4F9DBF11235C = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_audio_basics.mm"; path = "../../JuceLibraryCode/include_juce_audio_basics.mm"; sourceTree = "SOURCE_ROOT"; };
4DF6E6E41E10965AD169143B = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; };
5313EB852E41EE58B199B9A2 = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_audio_devices"; path = "../../../../modules/juce_audio_devices"; sourceTree = "SOURCE_ROOT"; };
57DF618F1DE781556B7AFC32 = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "Info-App.plist"; path = "Info-App.plist"; sourceTree = "SOURCE_ROOT"; };
59842A98E5EBBC54B50C04CD = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_events"; path = "../../../../modules/juce_events"; sourceTree = "SOURCE_ROOT"; };
5ACC21AA45BBF48C3C64D56D = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioUnit.framework; path = System/Library/Frameworks/AudioUnit.framework; sourceTree = SDKROOT; };
5AF0CA7CDFCA90B4DE1F55C3 = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMIDI.framework; path = System/Library/Frameworks/CoreMIDI.framework; sourceTree = SDKROOT; };
5D250A57C7DEA80248F30EED = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_audio_formats.mm"; path = "../../JuceLibraryCode/include_juce_audio_formats.mm"; sourceTree = "SOURCE_ROOT"; };
5EF1D381F42AA8764597F189 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_data_structures.mm"; path = "../../JuceLibraryCode/include_juce_data_structures.mm"; sourceTree = "SOURCE_ROOT"; };
5FBD6C402617272052BB4D81 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_audio_processors.mm"; path = "../../JuceLibraryCode/include_juce_audio_processors.mm"; sourceTree = "SOURCE_ROOT"; };
65968EA1B476D71F14DE1D58 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_audio_devices.mm"; path = "../../JuceLibraryCode/include_juce_audio_devices.mm"; sourceTree = "SOURCE_ROOT"; };
6692043E22BB181F01767845 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MainHostWindow.h; path = ../../Source/MainHostWindow.h; sourceTree = "SOURCE_ROOT"; };
683CEE986A2467C850FE99E6 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_core.mm"; path = "../../JuceLibraryCode/include_juce_core.mm"; sourceTree = "SOURCE_ROOT"; };
6A71B2BCAC4239072BC2BD7E = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_audio_basics"; path = "../../../../modules/juce_audio_basics"; sourceTree = "SOURCE_ROOT"; };
714C53257417E615916687E5 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PluginWindow.h; path = ../../Source/PluginWindow.h; sourceTree = "SOURCE_ROOT"; };
7DA35787B5F6F7440D667CC8 = {isa = PBXFileReference; lastKnownFileType = file.nib; name = RecentFilesMenuTemplate.nib; path = RecentFilesMenuTemplate.nib; sourceTree = "SOURCE_ROOT"; };
81C1A7770E082F56FE5A90A7 = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_opengl"; path = "../../../../modules/juce_opengl"; sourceTree = "SOURCE_ROOT"; };
82800DBA287EF4BAB13B42FB = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_graphics.mm"; path = "../../JuceLibraryCode/include_juce_graphics.mm"; sourceTree = "SOURCE_ROOT"; };
8290D7BAC160B3A56B66891A = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_events.mm"; path = "../../JuceLibraryCode/include_juce_events.mm"; sourceTree = "SOURCE_ROOT"; };
86CA337014D3F67E906FFD28 = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; };
89309C0C5F3269BD06BE7F27 = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
8D8BBC353637DA442C5575DA = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AudioPluginHost.app; sourceTree = "BUILT_PRODUCTS_DIR"; };
8FE7B37CDE0818DB27BDDEBD = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_gui_basics.mm"; path = "../../JuceLibraryCode/include_juce_gui_basics.mm"; sourceTree = "SOURCE_ROOT"; };
938AE72315C6C93949F6220E = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_gui_basics"; path = "../../../../modules/juce_gui_basics"; sourceTree = "SOURCE_ROOT"; };
942A0F04EFB8D0B2FF9780BA = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
94CB96C8E4B51F52776C2638 = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_graphics"; path = "../../../../modules/juce_graphics"; sourceTree = "SOURCE_ROOT"; };
9794142D24966F93FFDE51A1 = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
9BA1DD697B98005D24F7EC3C = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = FilterGraph.cpp; path = ../../Source/FilterGraph.cpp; sourceTree = "SOURCE_ROOT"; };
9F9B445E6755CAA19E4344ED = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; };
A4B568E26157FC282214976F = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVKit.framework; path = System/Library/Frameworks/AVKit.framework; sourceTree = SDKROOT; };
A5E7CA8A71D049BE2BD33861 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = JuceHeader.h; path = ../../JuceLibraryCode/JuceHeader.h; sourceTree = "SOURCE_ROOT"; };
A66EFAC64B1B67B536C73415 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = HostStartup.cpp; path = ../../Source/HostStartup.cpp; sourceTree = "SOURCE_ROOT"; };
B0935EBBA4F6E2B05F3D1C0A = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; };
B1C6B9E4B9FDC17AA298E541 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = GraphEditorPanel.cpp; path = ../../Source/GraphEditorPanel.cpp; sourceTree = "SOURCE_ROOT"; };
B285CAB91AE928C476CA4F9C = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_audio_utils.mm"; path = "../../JuceLibraryCode/include_juce_audio_utils.mm"; sourceTree = "SOURCE_ROOT"; };
B457EE687507BF1DEEA7581F = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; };
B86B918291E1090C6A720971 = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_data_structures"; path = "../../../../modules/juce_data_structures"; sourceTree = "SOURCE_ROOT"; };
B8774D8AD307D798831C0DF7 = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DiscRecording.framework; path = System/Library/Frameworks/DiscRecording.framework; sourceTree = SDKROOT; };
B8E24A5CEE6B7055537725CF = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_cryptography.mm"; path = "../../JuceLibraryCode/include_juce_cryptography.mm"; sourceTree = "SOURCE_ROOT"; };
D313CF37B25D7FD313C4F336 = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; };
D4EBC17BDB7F88CCBC76730B = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
DD8E5D0C88FA2C287F824357 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GraphEditorPanel.h; path = ../../Source/GraphEditorPanel.h; sourceTree = "SOURCE_ROOT"; };
DDE115D3084ACA6DD6AA4471 = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_video"; path = "../../../../modules/juce_video"; sourceTree = "SOURCE_ROOT"; };
E68018DE199135B7F738FB17 = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudioKit.framework; path = System/Library/Frameworks/CoreAudioKit.framework; sourceTree = SDKROOT; };
EE1BEF4055936CD0C543687C = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = InternalFilters.h; path = ../../Source/InternalFilters.h; sourceTree = "SOURCE_ROOT"; };
F299BECFB2AEA6105F014848 = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_gui_extra"; path = "../../../../modules/juce_gui_extra"; sourceTree = "SOURCE_ROOT"; };
F9AC862E9A3583B6C1488EE0 = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_audio_formats"; path = "../../../../modules/juce_audio_formats"; sourceTree = "SOURCE_ROOT"; };
FA21631C5536EA3DF55C7FA6 = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_cryptography"; path = "../../../../modules/juce_cryptography"; sourceTree = "SOURCE_ROOT"; };
FAF867E9E731D0880D40511F = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_audio_processors"; path = "../../../../modules/juce_audio_processors"; sourceTree = "SOURCE_ROOT"; };
97790EAEA01CFA5C3CA9737A = {isa = PBXGroup; children = (
9BA1DD697B98005D24F7EC3C,
2B143B5431318DDB2104B46E,
01FE7ED58992BC9683BA3C94,
18DD15714443AFC3BAAE211C,
B1C6B9E4B9FDC17AA298E541,
DD8E5D0C88FA2C287F824357,
A66EFAC64B1B67B536C73415,
362BB539489999164C3A3D5B,
EE1BEF4055936CD0C543687C,
1EC0F33A3BABE58138317375,
6692043E22BB181F01767845,
714C53257417E615916687E5, ); name = AudioPluginHost; sourceTree = "<group>"; };
9D8FE1F65CAD416AA606C47A = {isa = PBXGroup; children = (
6A71B2BCAC4239072BC2BD7E,
5313EB852E41EE58B199B9A2,
F9AC862E9A3583B6C1488EE0,
FAF867E9E731D0880D40511F,
3C070DD522CDD11FFC87425D,
3D57FE2A8877F12A61054726,
FA21631C5536EA3DF55C7FA6,
B86B918291E1090C6A720971,
59842A98E5EBBC54B50C04CD,
94CB96C8E4B51F52776C2638,
938AE72315C6C93949F6220E,
F299BECFB2AEA6105F014848,
81C1A7770E082F56FE5A90A7,
DDE115D3084ACA6DD6AA4471, ); name = "JUCE Modules"; sourceTree = "<group>"; };
7E30376DDAD775FEFE64944C = {isa = PBXGroup; children = (
30F22843EFEBF7AA841EB4D6,
4C7D82F9274A4F9DBF11235C,
65968EA1B476D71F14DE1D58,
5D250A57C7DEA80248F30EED,
5FBD6C402617272052BB4D81,
B285CAB91AE928C476CA4F9C,
683CEE986A2467C850FE99E6,
B8E24A5CEE6B7055537725CF,
5EF1D381F42AA8764597F189,
8290D7BAC160B3A56B66891A,
82800DBA287EF4BAB13B42FB,
8FE7B37CDE0818DB27BDDEBD,
2BE6C2DFD6EBB9A89109AEB5,
37E4D5C341406B7072120006,
29D746FC68F69751796671A2,
A5E7CA8A71D049BE2BD33861, ); name = "JUCE Library Code"; sourceTree = "<group>"; };
A97EE73C79DA3F729D46AF48 = {isa = PBXGroup; children = (
57DF618F1DE781556B7AFC32,
7DA35787B5F6F7440D667CC8, ); name = Resources; sourceTree = "<group>"; };
D1C4804CD275CB57A5C89A2D = {isa = PBXGroup; children = (
86CA337014D3F67E906FFD28,
D4EBC17BDB7F88CCBC76730B,
5ACC21AA45BBF48C3C64D56D,
942A0F04EFB8D0B2FF9780BA,
A4B568E26157FC282214976F,
B0935EBBA4F6E2B05F3D1C0A,
9794142D24966F93FFDE51A1,
9F9B445E6755CAA19E4344ED,
E68018DE199135B7F738FB17,
31D55A751C790CB81F58DDB7,
5AF0CA7CDFCA90B4DE1F55C3,
B8774D8AD307D798831C0DF7,
4DF6E6E41E10965AD169143B,
D313CF37B25D7FD313C4F336,
89309C0C5F3269BD06BE7F27,
B457EE687507BF1DEEA7581F, ); name = Frameworks; sourceTree = "<group>"; };
D85C0D11EE4F6C73B9EB5BCD = {isa = PBXGroup; children = (
8D8BBC353637DA442C5575DA, ); name = Products; sourceTree = "<group>"; };
65BEFC705A89E5C8A9E35C97 = {isa = PBXGroup; children = (
97790EAEA01CFA5C3CA9737A,
9D8FE1F65CAD416AA606C47A,
7E30376DDAD775FEFE64944C,
A97EE73C79DA3F729D46AF48,
D1C4804CD275CB57A5C89A2D,
D85C0D11EE4F6C73B9EB5BCD, ); name = Source; sourceTree = "<group>"; };
C8B793AC1BEFBE7A99BE8352 = {isa = XCBuildConfiguration; buildSettings = {
CLANG_CXX_LANGUAGE_STANDARD = "c++14";
CLANG_LINK_OBJC_RUNTIME = NO;
COMBINE_HIDPI_IMAGES = YES;
CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
COPY_PHASE_STRIP = NO;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"_DEBUG=1",
"DEBUG=1",
"JUCER_XCODE_MAC_F6D2F4CF=1",
"JUCE_APP_VERSION=1.0.0",
"JUCE_APP_VERSION_HEX=0x10000",
"JucePlugin_Build_VST=0",
"JucePlugin_Build_VST3=0",
"JucePlugin_Build_AU=0",
"JucePlugin_Build_AUv3=0",
"JucePlugin_Build_RTAS=0",
"JucePlugin_Build_AAX=0",
"JucePlugin_Build_Standalone=0", );
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
HEADER_SEARCH_PATHS = ("~/SDKs/VST_SDK/VST3_SDK", "../../JuceLibraryCode", "../../../../modules", "$(inherited)");
INFOPLIST_FILE = Info-App.plist;
INFOPLIST_PREPROCESS = NO;
INSTALL_PATH = "$(HOME)/Applications";
MACOSX_DEPLOYMENT_TARGET = 10.11;
MACOSX_DEPLOYMENT_TARGET_ppc = 10.4;
OTHER_CPLUSPLUSFLAGS = "-Wall -Wshadow -Wstrict-aliasing -Wconversion -Wsign-compare -Woverloaded-virtual -Wextra-semi";
PRODUCT_BUNDLE_IDENTIFIER = com.roli.pluginhost;
SDKROOT_ppc = macosx10.5;
USE_HEADERMAP = NO; }; name = Debug; };
49453CC5AD9F08D2738464AC = {isa = XCBuildConfiguration; buildSettings = {
CLANG_CXX_LANGUAGE_STANDARD = "c++14";
CLANG_LINK_OBJC_RUNTIME = NO;
COMBINE_HIDPI_IMAGES = YES;
CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
DEAD_CODE_STRIPPING = YES;
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_OPTIMIZATION_LEVEL = s;
GCC_PREPROCESSOR_DEFINITIONS = (
"_NDEBUG=1",
"NDEBUG=1",
"JUCER_XCODE_MAC_F6D2F4CF=1",
"JUCE_APP_VERSION=1.0.0",
"JUCE_APP_VERSION_HEX=0x10000",
"JucePlugin_Build_VST=0",
"JucePlugin_Build_VST3=0",
"JucePlugin_Build_AU=0",
"JucePlugin_Build_AUv3=0",
"JucePlugin_Build_RTAS=0",
"JucePlugin_Build_AAX=0",
"JucePlugin_Build_Standalone=0", );
GCC_SYMBOLS_PRIVATE_EXTERN = YES;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
HEADER_SEARCH_PATHS = ("~/SDKs/VST_SDK/VST3_SDK", "../../JuceLibraryCode", "../../../../modules", "$(inherited)");
INFOPLIST_FILE = Info-App.plist;
INFOPLIST_PREPROCESS = NO;
INSTALL_PATH = "$(HOME)/Applications";
LLVM_LTO = YES;
MACOSX_DEPLOYMENT_TARGET = 10.11;
MACOSX_DEPLOYMENT_TARGET_ppc = 10.4;
OTHER_CPLUSPLUSFLAGS = "-Wall -Wshadow -Wstrict-aliasing -Wconversion -Wsign-compare -Woverloaded-virtual -Wextra-semi";
PRODUCT_BUNDLE_IDENTIFIER = com.roli.pluginhost;
SDKROOT_ppc = macosx10.5;
USE_HEADERMAP = NO; }; name = Release; };
8D1CA827F1EFD443BDCF198A = {isa = XCBuildConfiguration; buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
DEBUG_INFORMATION_FORMAT = "dwarf";
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = c11;
GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
GCC_MODEL_TUNING = G5;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_CHECK_SWITCH_STATEMENTS = YES;
GCC_WARN_MISSING_PARENTHESES = YES;
GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_NAME = "AudioPluginHost";
WARNING_CFLAGS = -Wreorder;
ZERO_LINK = NO; }; name = Debug; };
C9295196717FABE454A210B7 = {isa = XCBuildConfiguration; buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
DEBUG_INFORMATION_FORMAT = "dwarf";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = c11;
GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
GCC_MODEL_TUNING = G5;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_CHECK_SWITCH_STATEMENTS = YES;
GCC_WARN_MISSING_PARENTHESES = YES;
GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
PRODUCT_NAME = "AudioPluginHost";
WARNING_CFLAGS = -Wreorder;
ZERO_LINK = NO; }; name = Release; };
B9D79D85AC7DE5BED1B6547C = {isa = PBXTargetDependency; target = DE12B7643D374BFF7E4FEB1C; };
493C2C5E457692E5149C5525 = {isa = XCConfigurationList; buildConfigurations = (
8D1CA827F1EFD443BDCF198A,
C9295196717FABE454A210B7, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; };
E4ECAE24A646A7D1585F776C = {isa = XCConfigurationList; buildConfigurations = (
C8B793AC1BEFBE7A99BE8352,
49453CC5AD9F08D2738464AC, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; };
2429BB4D705CC57F49418CFB = {isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = (
D92C7BF86C9CCF6B4D14F809, ); runOnlyForDeploymentPostprocessing = 0; };
E8E94B3C187DA578BFCBDA98 = {isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = (
4C88899EB7993A76A97643FE,
485A37478F7EAA352DD1A86A,
040EB574807E8A86F124D851,
A1B0416DA378BB0C3AD6F74B,
D493393499E0822C70009A63,
6CD3B433544911DA879170AE,
15CCE43D7DCFC649638919D4,
5C4D406B924230F83E3580AD,
F4DD98B9310B679D50A2C8A6,
CAF0DE157C8F7D9F168AA3B6,
0F20A4AE04736634F097F5A6,
76A80851698FC773D2479B4E,
E4A926EF695823F0F13268FF,
A09E93F1B354E1FF8B3E9ABE,
7DE202DC1D876F49266D9E7D,
075C54DDDBDEA5AAD2F60154,
2C3D221D2AA87F07B3F1044D,
C38D14DC58F1941DD5E4BF60,
2727A191DB1BAAC9C04B9081,
84BAFE82A102D9C350672689, ); runOnlyForDeploymentPostprocessing = 0; };
C515A1FE1A53D3968C22FAEF = {isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = (
73E371F1B912FCCAE0CD7E5D,
21D330A5B13178B12BEAFC3C,
B288A89F96704F142ED8E939,
851C1165C9E4ACDD19C56A96,
AF42316D915057E930A5624E,
2B4B9CF71F94BDD1E3AC89AE,
AC3BED74AC7C6D9F5739F38B,
E3CB85BA817BC9E3942A8AB0,
70580743C3D5695F065FF698,
3470F40DA5D68EC217872906,
E092A70431B046BF1F50A482,
E2BAA7CFC729809530FD71EE,
68FBFDA1FE637B3EDA09A592,
BBA1733CF8B064A5FD0B4CF4,
A02C9F4C4B840C27B6CAFEBD,
4DB15177DDC357F4503F88CF, ); runOnlyForDeploymentPostprocessing = 0; };
DE12B7643D374BFF7E4FEB1C = {isa = PBXNativeTarget; buildConfigurationList = E4ECAE24A646A7D1585F776C; buildPhases = (
2429BB4D705CC57F49418CFB,
E8E94B3C187DA578BFCBDA98,
C515A1FE1A53D3968C22FAEF, ); buildRules = ( ); dependencies = ( ); name = "AudioPluginHost - App"; productName = AudioPluginHost; productReference = 8D8BBC353637DA442C5575DA; productType = "com.apple.product-type.application"; };
ADE6E539DB98A302483A82D0 = {isa = PBXProject; buildConfigurationList = 493C2C5E457692E5149C5525; attributes = { LastUpgradeCheck = 0830; ORGANIZATIONNAME = "ROLI Ltd."; TargetAttributes = { DE12B7643D374BFF7E4FEB1C = { SystemCapabilities = {com.apple.ApplicationGroups.iOS = { enabled = 0; }; com.apple.InAppPurchase = { enabled = 0; }; com.apple.InterAppAudio = { enabled = 0; }; com.apple.Push = { enabled = 0; }; com.apple.Sandbox = { enabled = 0; }; }; }; }; }; compatibilityVersion = "Xcode 3.2"; hasScannedForEncodings = 0; mainGroup = 65BEFC705A89E5C8A9E35C97; projectDirPath = ""; projectRoot = ""; targets = (DE12B7643D374BFF7E4FEB1C); };
};
rootObject = ADE6E539DB98A302483A82D0;
}

View file

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist>
<dict>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>com.roli.pluginhost</string>
<key>CFBundleName</key>
<string>AudioPluginHost</string>
<key>CFBundleDisplayName</key>
<string>AudioPluginHost</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleShortVersionString</key>
<string>1.0.0</string>
<key>CFBundleVersion</key>
<string>1.0.0</string>
<key>NSHumanReadableCopyright</key>
<string>ROLI Ltd.</string>
<key>NSHighResolutionCapable</key>
<true/>
</dict>
</plist>

Binary file not shown.

View file

@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2013
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AudioPluginHost - App", "AudioPluginHost_App.vcxproj", "{5666EAA2-C82B-D06A-5228-D0E810428536}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5666EAA2-C82B-D06A-5228-D0E810428536}.Debug|Win32.ActiveCfg = Debug|Win32
{5666EAA2-C82B-D06A-5228-D0E810428536}.Debug|Win32.Build.0 = Debug|Win32
{5666EAA2-C82B-D06A-5228-D0E810428536}.Release|Win32.ActiveCfg = Release|Win32
{5666EAA2-C82B-D06A-5228-D0E810428536}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,31 @@
#ifdef JUCE_USER_DEFINED_RC_FILE
#include JUCE_USER_DEFINED_RC_FILE
#else
#undef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,0
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
BEGIN
VALUE "CompanyName", "ROLI Ltd.\0"
VALUE "LegalCopyright", "ROLI Ltd.\0"
VALUE "FileDescription", "AudioPluginHost\0"
VALUE "FileVersion", "1.0.0\0"
VALUE "ProductName", "AudioPluginHost\0"
VALUE "ProductVersion", "1.0.0\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1252
END
END
#endif

View file

@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2015
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AudioPluginHost - App", "AudioPluginHost_App.vcxproj", "{5666EAA2-C82B-D06A-5228-D0E810428536}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5666EAA2-C82B-D06A-5228-D0E810428536}.Debug|x64.ActiveCfg = Debug|x64
{5666EAA2-C82B-D06A-5228-D0E810428536}.Debug|x64.Build.0 = Debug|x64
{5666EAA2-C82B-D06A-5228-D0E810428536}.Release|x64.ActiveCfg = Release|x64
{5666EAA2-C82B-D06A-5228-D0E810428536}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,31 @@
#ifdef JUCE_USER_DEFINED_RC_FILE
#include JUCE_USER_DEFINED_RC_FILE
#else
#undef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,0
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
BEGIN
VALUE "CompanyName", "ROLI Ltd.\0"
VALUE "LegalCopyright", "ROLI Ltd.\0"
VALUE "FileDescription", "AudioPluginHost\0"
VALUE "FileVersion", "1.0.0\0"
VALUE "ProductName", "AudioPluginHost\0"
VALUE "ProductVersion", "1.0.0\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1252
END
END
#endif

View file

@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2017
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AudioPluginHost - App", "AudioPluginHost_App.vcxproj", "{5666EAA2-C82B-D06A-5228-D0E810428536}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5666EAA2-C82B-D06A-5228-D0E810428536}.Debug|x64.ActiveCfg = Debug|x64
{5666EAA2-C82B-D06A-5228-D0E810428536}.Debug|x64.Build.0 = Debug|x64
{5666EAA2-C82B-D06A-5228-D0E810428536}.Release|x64.ActiveCfg = Release|x64
{5666EAA2-C82B-D06A-5228-D0E810428536}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,31 @@
#ifdef JUCE_USER_DEFINED_RC_FILE
#include JUCE_USER_DEFINED_RC_FILE
#else
#undef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,0
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
BEGIN
VALUE "CompanyName", "ROLI Ltd.\0"
VALUE "LegalCopyright", "ROLI Ltd.\0"
VALUE "FileDescription", "AudioPluginHost\0"
VALUE "FileVersion", "1.0.0\0"
VALUE "ProductName", "AudioPluginHost\0"
VALUE "ProductVersion", "1.0.0\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1252
END
END
#endif

View file

@ -0,0 +1,264 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
There's a section below where you can add your own custom code safely, and the
Projucer will preserve the contents of that block, but the best way to change
any of these definitions is by using the Projucer's project settings.
Any commented-out settings will assume their default values.
*/
#pragma once
//==============================================================================
// [BEGIN_USER_CODE_SECTION]
// (You can add your own code in this section, and the Projucer will not overwrite it)
// [END_USER_CODE_SECTION]
/*
==============================================================================
In accordance with the terms of the JUCE 5 End-Use License Agreement, the
JUCE Code in SECTION A cannot be removed, changed or otherwise rendered
ineffective unless you have a JUCE Indie or Pro license, or are using JUCE
under the GPL v3 license.
End User License Agreement: www.juce.com/juce-5-licence
==============================================================================
*/
// BEGIN SECTION A
#ifndef JUCE_DISPLAY_SPLASH_SCREEN
#define JUCE_DISPLAY_SPLASH_SCREEN 0
#endif
#ifndef JUCE_REPORT_APP_USAGE
#define JUCE_REPORT_APP_USAGE 0
#endif
// END SECTION A
#define JUCE_USE_DARK_SPLASH_SCREEN 1
//==============================================================================
#define JUCE_MODULE_AVAILABLE_juce_audio_basics 1
#define JUCE_MODULE_AVAILABLE_juce_audio_devices 1
#define JUCE_MODULE_AVAILABLE_juce_audio_formats 1
#define JUCE_MODULE_AVAILABLE_juce_audio_processors 1
#define JUCE_MODULE_AVAILABLE_juce_audio_utils 1
#define JUCE_MODULE_AVAILABLE_juce_core 1
#define JUCE_MODULE_AVAILABLE_juce_cryptography 1
#define JUCE_MODULE_AVAILABLE_juce_data_structures 1
#define JUCE_MODULE_AVAILABLE_juce_events 1
#define JUCE_MODULE_AVAILABLE_juce_graphics 1
#define JUCE_MODULE_AVAILABLE_juce_gui_basics 1
#define JUCE_MODULE_AVAILABLE_juce_gui_extra 1
#define JUCE_MODULE_AVAILABLE_juce_opengl 1
#define JUCE_MODULE_AVAILABLE_juce_video 1
#define JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED 1
//==============================================================================
// juce_audio_devices flags:
#ifndef JUCE_ASIO
//#define JUCE_ASIO 0
#endif
#ifndef JUCE_WASAPI
#define JUCE_WASAPI 1
#endif
#ifndef JUCE_WASAPI_EXCLUSIVE
//#define JUCE_WASAPI_EXCLUSIVE 0
#endif
#ifndef JUCE_DIRECTSOUND
#define JUCE_DIRECTSOUND 1
#endif
#ifndef JUCE_ALSA
#define JUCE_ALSA 1
#endif
#ifndef JUCE_JACK
//#define JUCE_JACK 0
#endif
#ifndef JUCE_USE_ANDROID_OBOE
//#define JUCE_USE_ANDROID_OBOE 0
#endif
#ifndef JUCE_USE_ANDROID_OPENSLES
//#define JUCE_USE_ANDROID_OPENSLES 0
#endif
#ifndef JUCE_USE_WINRT_MIDI
//#define JUCE_USE_WINRT_MIDI 0
#endif
#ifndef JUCE_DISABLE_AUDIO_MIXING_WITH_OTHER_APPS
//#define JUCE_DISABLE_AUDIO_MIXING_WITH_OTHER_APPS 0
#endif
//==============================================================================
// juce_audio_formats flags:
#ifndef JUCE_USE_FLAC
#define JUCE_USE_FLAC 0
#endif
#ifndef JUCE_USE_OGGVORBIS
#define JUCE_USE_OGGVORBIS 0
#endif
#ifndef JUCE_USE_MP3AUDIOFORMAT
//#define JUCE_USE_MP3AUDIOFORMAT 0
#endif
#ifndef JUCE_USE_LAME_AUDIO_FORMAT
//#define JUCE_USE_LAME_AUDIO_FORMAT 0
#endif
#ifndef JUCE_USE_WINDOWS_MEDIA_FORMAT
//#define JUCE_USE_WINDOWS_MEDIA_FORMAT 1
#endif
//==============================================================================
// juce_audio_processors flags:
#ifndef JUCE_PLUGINHOST_VST
#define JUCE_PLUGINHOST_VST 1
#endif
#ifndef JUCE_PLUGINHOST_VST3
#define JUCE_PLUGINHOST_VST3 1
#endif
#ifndef JUCE_PLUGINHOST_AU
#define JUCE_PLUGINHOST_AU 1
#endif
//==============================================================================
// juce_audio_utils flags:
#ifndef JUCE_USE_CDREADER
#define JUCE_USE_CDREADER 0
#endif
#ifndef JUCE_USE_CDBURNER
#define JUCE_USE_CDBURNER 0
#endif
//==============================================================================
// juce_core flags:
#ifndef JUCE_FORCE_DEBUG
//#define JUCE_FORCE_DEBUG 0
#endif
#ifndef JUCE_LOG_ASSERTIONS
//#define JUCE_LOG_ASSERTIONS 0
#endif
#ifndef JUCE_CHECK_MEMORY_LEAKS
//#define JUCE_CHECK_MEMORY_LEAKS 1
#endif
#ifndef JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES
//#define JUCE_DONT_AUTOLINK_TO_WIN32_LIBRARIES 0
#endif
#ifndef JUCE_INCLUDE_ZLIB_CODE
//#define JUCE_INCLUDE_ZLIB_CODE 1
#endif
#ifndef JUCE_USE_CURL
//#define JUCE_USE_CURL 0
#endif
#ifndef JUCE_CATCH_UNHANDLED_EXCEPTIONS
//#define JUCE_CATCH_UNHANDLED_EXCEPTIONS 1
#endif
#ifndef JUCE_ALLOW_STATIC_NULL_VARIABLES
//#define JUCE_ALLOW_STATIC_NULL_VARIABLES 1
#endif
//==============================================================================
// juce_events flags:
#ifndef JUCE_EXECUTE_APP_SUSPEND_ON_IOS_BACKGROUND_TASK
//#define JUCE_EXECUTE_APP_SUSPEND_ON_IOS_BACKGROUND_TASK 0
#endif
//==============================================================================
// juce_graphics flags:
#ifndef JUCE_USE_COREIMAGE_LOADER
//#define JUCE_USE_COREIMAGE_LOADER 1
#endif
#ifndef JUCE_USE_DIRECTWRITE
//#define JUCE_USE_DIRECTWRITE 1
#endif
//==============================================================================
// juce_gui_basics flags:
#ifndef JUCE_ENABLE_REPAINT_DEBUGGING
//#define JUCE_ENABLE_REPAINT_DEBUGGING 0
#endif
#ifndef JUCE_USE_XRANDR
//#define JUCE_USE_XRANDR 1
#endif
#ifndef JUCE_USE_XINERAMA
//#define JUCE_USE_XINERAMA 1
#endif
#ifndef JUCE_USE_XSHM
//#define JUCE_USE_XSHM 1
#endif
#ifndef JUCE_USE_XRENDER
//#define JUCE_USE_XRENDER 0
#endif
#ifndef JUCE_USE_XCURSOR
//#define JUCE_USE_XCURSOR 1
#endif
//==============================================================================
// juce_gui_extra flags:
#ifndef JUCE_WEB_BROWSER
#define JUCE_WEB_BROWSER 0
#endif
#ifndef JUCE_ENABLE_LIVE_CONSTANT_EDITOR
//#define JUCE_ENABLE_LIVE_CONSTANT_EDITOR 0
#endif
//==============================================================================
// juce_video flags:
#ifndef JUCE_USE_CAMERA
#define JUCE_USE_CAMERA 0
#endif
//==============================================================================
#ifndef JUCE_STANDALONE_APPLICATION
#if defined(JucePlugin_Name) && defined(JucePlugin_Build_Standalone)
#define JUCE_STANDALONE_APPLICATION JucePlugin_Build_Standalone
#else
#define JUCE_STANDALONE_APPLICATION 1
#endif
#endif

View file

@ -0,0 +1,46 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
This is the header file that your files should include in order to get all the
JUCE library headers. You should avoid including the JUCE headers directly in
your own source files, because that wouldn't pick up the correct configuration
options for your app.
*/
#pragma once
#include "AppConfig.h"
#include <juce_audio_basics/juce_audio_basics.h>
#include <juce_audio_devices/juce_audio_devices.h>
#include <juce_audio_formats/juce_audio_formats.h>
#include <juce_audio_processors/juce_audio_processors.h>
#include <juce_audio_utils/juce_audio_utils.h>
#include <juce_core/juce_core.h>
#include <juce_cryptography/juce_cryptography.h>
#include <juce_data_structures/juce_data_structures.h>
#include <juce_events/juce_events.h>
#include <juce_graphics/juce_graphics.h>
#include <juce_gui_basics/juce_gui_basics.h>
#include <juce_gui_extra/juce_gui_extra.h>
#include <juce_opengl/juce_opengl.h>
#include <juce_video/juce_video.h>
#if ! DONT_SET_USING_JUCE_NAMESPACE
// If your code uses a lot of JUCE classes, then this will obviously save you
// a lot of typing, but can be disabled by setting DONT_SET_USING_JUCE_NAMESPACE.
using namespace juce;
#endif
#if ! JUCE_DONT_DECLARE_PROJECTINFO
namespace ProjectInfo
{
const char* const projectName = "AudioPluginHost";
const char* const versionString = "1.0.0";
const int versionNumber = 0x10000;
}
#endif

View file

@ -0,0 +1,12 @@
Important Note!!
================
The purpose of this folder is to contain files that are auto-generated by the Projucer,
and ALL files in this folder will be mercilessly DELETED and completely re-written whenever
the Projucer saves your project.
Therefore, it's a bad idea to make any manual changes to the files in here, or to
put any of your own files in here if you don't want to lose them. (Of course you may choose
to add the folder's contents to your version-control system so that you can re-merge your own
modifications after the Projucer has saved its changes).

View file

@ -0,0 +1,9 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include "AppConfig.h"
#include <juce_audio_basics/juce_audio_basics.cpp>

View file

@ -0,0 +1,9 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include "AppConfig.h"
#include <juce_audio_basics/juce_audio_basics.mm>

View file

@ -0,0 +1,9 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include "AppConfig.h"
#include <juce_audio_devices/juce_audio_devices.cpp>

View file

@ -0,0 +1,9 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include "AppConfig.h"
#include <juce_audio_devices/juce_audio_devices.mm>

View file

@ -0,0 +1,9 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include "AppConfig.h"
#include <juce_audio_formats/juce_audio_formats.cpp>

View file

@ -0,0 +1,9 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include "AppConfig.h"
#include <juce_audio_formats/juce_audio_formats.mm>

View file

@ -0,0 +1,9 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include "AppConfig.h"
#include <juce_audio_processors/juce_audio_processors.cpp>

View file

@ -0,0 +1,9 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include "AppConfig.h"
#include <juce_audio_processors/juce_audio_processors.mm>

View file

@ -0,0 +1,9 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include "AppConfig.h"
#include <juce_audio_utils/juce_audio_utils.cpp>

View file

@ -0,0 +1,9 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include "AppConfig.h"
#include <juce_audio_utils/juce_audio_utils.mm>

View file

@ -0,0 +1,9 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include "AppConfig.h"
#include <juce_core/juce_core.cpp>

View file

@ -0,0 +1,9 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include "AppConfig.h"
#include <juce_core/juce_core.mm>

View file

@ -0,0 +1,9 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include "AppConfig.h"
#include <juce_cryptography/juce_cryptography.cpp>

View file

@ -0,0 +1,9 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include "AppConfig.h"
#include <juce_cryptography/juce_cryptography.mm>

View file

@ -0,0 +1,9 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include "AppConfig.h"
#include <juce_data_structures/juce_data_structures.cpp>

View file

@ -0,0 +1,9 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include "AppConfig.h"
#include <juce_data_structures/juce_data_structures.mm>

View file

@ -0,0 +1,9 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include "AppConfig.h"
#include <juce_events/juce_events.cpp>

View file

@ -0,0 +1,9 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include "AppConfig.h"
#include <juce_events/juce_events.mm>

View file

@ -0,0 +1,9 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include "AppConfig.h"
#include <juce_graphics/juce_graphics.cpp>

View file

@ -0,0 +1,9 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include "AppConfig.h"
#include <juce_graphics/juce_graphics.mm>

View file

@ -0,0 +1,9 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include "AppConfig.h"
#include <juce_gui_basics/juce_gui_basics.cpp>

View file

@ -0,0 +1,9 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include "AppConfig.h"
#include <juce_gui_basics/juce_gui_basics.mm>

View file

@ -0,0 +1,9 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include "AppConfig.h"
#include <juce_gui_extra/juce_gui_extra.cpp>

View file

@ -0,0 +1,9 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include "AppConfig.h"
#include <juce_gui_extra/juce_gui_extra.mm>

View file

@ -0,0 +1,9 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include "AppConfig.h"
#include <juce_opengl/juce_opengl.cpp>

View file

@ -0,0 +1,9 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include "AppConfig.h"
#include <juce_opengl/juce_opengl.mm>

View file

@ -0,0 +1,9 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include "AppConfig.h"
#include <juce_video/juce_video.cpp>

View file

@ -0,0 +1,9 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include "AppConfig.h"
#include <juce_video/juce_video.mm>

View file

@ -0,0 +1,456 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#include "../JuceLibraryCode/JuceHeader.h"
#include "MainHostWindow.h"
#include "FilterGraph.h"
#include "InternalFilters.h"
#include "GraphEditorPanel.h"
//==============================================================================
FilterGraph::FilterGraph (AudioPluginFormatManager& fm)
: FileBasedDocument (getFilenameSuffix(),
getFilenameWildcard(),
"Load a filter graph",
"Save a filter graph"),
formatManager (fm)
{
newDocument();
graph.addListener (this);
graph.addChangeListener (this);
setChangedFlag (false);
}
FilterGraph::~FilterGraph()
{
graph.addListener (this);
graph.removeChangeListener (this);
graph.clear();
}
FilterGraph::NodeID FilterGraph::getNextUID() noexcept
{
return ++lastUID;
}
//==============================================================================
void FilterGraph::changeListenerCallback (ChangeBroadcaster*)
{
changed();
for (int i = activePluginWindows.size(); --i >= 0;)
if (! graph.getNodes().contains (activePluginWindows.getUnchecked(i)->node))
activePluginWindows.remove (i);
}
AudioProcessorGraph::Node::Ptr FilterGraph::getNodeForName (const String& name) const
{
for (auto* node : graph.getNodes())
if (auto p = node->getProcessor())
if (p->getName().equalsIgnoreCase (name))
return node;
return nullptr;
}
void FilterGraph::addPlugin (const PluginDescription& desc, Point<double> p)
{
struct AsyncCallback : public AudioPluginFormat::InstantiationCompletionCallback
{
AsyncCallback (FilterGraph& g, Point<double> pos) : owner (g), position (pos)
{}
void completionCallback (AudioPluginInstance* instance, const String& error) override
{
owner.addFilterCallback (instance, error, position);
}
FilterGraph& owner;
Point<double> position;
};
formatManager.createPluginInstanceAsync (desc,
graph.getSampleRate(),
graph.getBlockSize(),
new AsyncCallback (*this, p));
}
void FilterGraph::addFilterCallback (AudioPluginInstance* instance, const String& error, Point<double> pos)
{
if (instance == nullptr)
{
AlertWindow::showMessageBox (AlertWindow::WarningIcon,
TRANS("Couldn't create filter"),
error);
}
else
{
instance->enableAllBuses();
if (auto node = graph.addNode (instance))
{
node->properties.set ("x", pos.x);
node->properties.set ("y", pos.y);
changed();
}
}
}
void FilterGraph::setNodePosition (NodeID nodeID, Point<double> pos)
{
if (auto* n = graph.getNodeForId (nodeID))
{
n->properties.set ("x", jlimit (0.0, 1.0, pos.x));
n->properties.set ("y", jlimit (0.0, 1.0, pos.y));
}
}
Point<double> FilterGraph::getNodePosition (NodeID nodeID) const
{
if (auto* n = graph.getNodeForId (nodeID))
return { static_cast<double> (n->properties ["x"]),
static_cast<double> (n->properties ["y"]) };
return {};
}
//==============================================================================
void FilterGraph::clear()
{
closeAnyOpenPluginWindows();
graph.clear();
changed();
}
PluginWindow* FilterGraph::getOrCreateWindowFor (AudioProcessorGraph::Node* node, PluginWindow::Type type)
{
jassert (node != nullptr);
for (auto* w : activePluginWindows)
if (w->node == node && w->type == type)
return w;
if (auto* processor = node->getProcessor())
{
if (auto* plugin = dynamic_cast<AudioPluginInstance*> (processor))
{
auto description = plugin->getPluginDescription();
if (description.pluginFormatName == "Internal")
{
getCommandManager().invokeDirectly (CommandIDs::showAudioSettings, false);
return nullptr;
}
}
return activePluginWindows.add (new PluginWindow (node, type, activePluginWindows));
}
return nullptr;
}
bool FilterGraph::closeAnyOpenPluginWindows()
{
bool wasEmpty = activePluginWindows.isEmpty();
activePluginWindows.clear();
return ! wasEmpty;
}
//==============================================================================
String FilterGraph::getDocumentTitle()
{
if (! getFile().exists())
return "Unnamed";
return getFile().getFileNameWithoutExtension();
}
void FilterGraph::newDocument()
{
clear();
setFile ({});
InternalPluginFormat internalFormat;
addPlugin (internalFormat.audioInDesc, { 0.5, 0.1 });
addPlugin (internalFormat.midiInDesc, { 0.25, 0.1 });
addPlugin (internalFormat.audioOutDesc, { 0.5, 0.9 });
setChangedFlag (false);
}
Result FilterGraph::loadDocument (const File& file)
{
XmlDocument doc (file);
ScopedPointer<XmlElement> xml (doc.getDocumentElement());
if (xml == nullptr || ! xml->hasTagName ("FILTERGRAPH"))
return Result::fail ("Not a valid filter graph file");
restoreFromXml (*xml);
return Result::ok();
}
Result FilterGraph::saveDocument (const File& file)
{
ScopedPointer<XmlElement> xml (createXml());
if (! xml->writeToFile (file, {}))
return Result::fail ("Couldn't write to the file");
return Result::ok();
}
File FilterGraph::getLastDocumentOpened()
{
RecentlyOpenedFilesList recentFiles;
recentFiles.restoreFromString (getAppProperties().getUserSettings()
->getValue ("recentFilterGraphFiles"));
return recentFiles.getFile (0);
}
void FilterGraph::setLastDocumentOpened (const File& file)
{
RecentlyOpenedFilesList recentFiles;
recentFiles.restoreFromString (getAppProperties().getUserSettings()
->getValue ("recentFilterGraphFiles"));
recentFiles.addFile (file);
getAppProperties().getUserSettings()
->setValue ("recentFilterGraphFiles", recentFiles.toString());
}
//==============================================================================
static void readBusLayoutFromXml (AudioProcessor::BusesLayout& busesLayout, AudioProcessor* plugin,
const XmlElement& xml, const bool isInput)
{
auto& targetBuses = (isInput ? busesLayout.inputBuses
: busesLayout.outputBuses);
int maxNumBuses = 0;
if (auto* buses = xml.getChildByName (isInput ? "INPUTS" : "OUTPUTS"))
{
forEachXmlChildElementWithTagName (*buses, e, "BUS")
{
const int busIdx = e->getIntAttribute ("index");
maxNumBuses = jmax (maxNumBuses, busIdx + 1);
// the number of buses on busesLayout may not be in sync with the plugin after adding buses
// because adding an input bus could also add an output bus
for (int actualIdx = plugin->getBusCount (isInput) - 1; actualIdx < busIdx; ++actualIdx)
if (! plugin->addBus (isInput))
return;
for (int actualIdx = targetBuses.size() - 1; actualIdx < busIdx; ++actualIdx)
targetBuses.add (plugin->getChannelLayoutOfBus (isInput, busIdx));
auto layout = e->getStringAttribute ("layout");
if (layout.isNotEmpty())
targetBuses.getReference (busIdx) = AudioChannelSet::fromAbbreviatedString (layout);
}
}
// if the plugin has more buses than specified in the xml, then try to remove them!
while (maxNumBuses < targetBuses.size())
{
if (! plugin->removeBus (isInput))
return;
targetBuses.removeLast();
}
}
//==============================================================================
static XmlElement* createBusLayoutXml (const AudioProcessor::BusesLayout& layout, const bool isInput)
{
auto& buses = isInput ? layout.inputBuses
: layout.outputBuses;
auto* xml = new XmlElement (isInput ? "INPUTS" : "OUTPUTS");
for (int busIdx = 0; busIdx < buses.size(); ++busIdx)
{
auto& set = buses.getReference (busIdx);
auto* bus = xml->createNewChildElement ("BUS");
bus->setAttribute ("index", busIdx);
bus->setAttribute ("layout", set.isDisabled() ? "disabled" : set.getSpeakerArrangementAsString());
}
return xml;
}
static XmlElement* createNodeXml (AudioProcessorGraph::Node* const node) noexcept
{
if (auto* plugin = dynamic_cast<AudioPluginInstance*> (node->getProcessor()))
{
auto e = new XmlElement ("FILTER");
e->setAttribute ("uid", (int) node->nodeID);
e->setAttribute ("x", node->properties ["x"].toString());
e->setAttribute ("y", node->properties ["y"].toString());
for (int i = 0; i < (int) PluginWindow::Type::numTypes; ++i)
{
auto type = (PluginWindow::Type) i;
if (node->properties.contains (PluginWindow::getOpenProp (type)))
{
e->setAttribute (PluginWindow::getLastXProp (type), node->properties[PluginWindow::getLastXProp (type)].toString());
e->setAttribute (PluginWindow::getLastYProp (type), node->properties[PluginWindow::getLastYProp (type)].toString());
e->setAttribute (PluginWindow::getOpenProp (type), node->properties[PluginWindow::getOpenProp (type)].toString());
}
}
{
PluginDescription pd;
plugin->fillInPluginDescription (pd);
e->addChildElement (pd.createXml());
}
{
MemoryBlock m;
node->getProcessor()->getStateInformation (m);
e->createNewChildElement ("STATE")->addTextElement (m.toBase64Encoding());
}
auto layout = plugin->getBusesLayout();
auto layouts = e->createNewChildElement ("LAYOUT");
layouts->addChildElement (createBusLayoutXml (layout, true));
layouts->addChildElement (createBusLayoutXml (layout, false));
return e;
}
jassertfalse;
return nullptr;
}
void FilterGraph::createNodeFromXml (const XmlElement& xml)
{
PluginDescription pd;
forEachXmlChildElement (xml, e)
{
if (pd.loadFromXml (*e))
break;
}
String errorMessage;
if (auto* instance = formatManager.createPluginInstance (pd, graph.getSampleRate(),
graph.getBlockSize(), errorMessage))
{
if (auto* layoutEntity = xml.getChildByName ("LAYOUT"))
{
auto layout = instance->getBusesLayout();
readBusLayoutFromXml (layout, instance, *layoutEntity, true);
readBusLayoutFromXml (layout, instance, *layoutEntity, false);
instance->setBusesLayout (layout);
}
if (auto node = graph.addNode (instance, (NodeID) xml.getIntAttribute ("uid")))
{
if (auto* state = xml.getChildByName ("STATE"))
{
MemoryBlock m;
m.fromBase64Encoding (state->getAllSubText());
node->getProcessor()->setStateInformation (m.getData(), (int) m.getSize());
}
node->properties.set ("x", xml.getDoubleAttribute ("x"));
node->properties.set ("y", xml.getDoubleAttribute ("y"));
for (int i = 0; i < (int) PluginWindow::Type::numTypes; ++i)
{
auto type = (PluginWindow::Type) i;
if (xml.hasAttribute (PluginWindow::getOpenProp (type)))
{
node->properties.set (PluginWindow::getLastXProp (type), xml.getIntAttribute (PluginWindow::getLastXProp (type)));
node->properties.set (PluginWindow::getLastYProp (type), xml.getIntAttribute (PluginWindow::getLastYProp (type)));
node->properties.set (PluginWindow::getOpenProp (type), xml.getIntAttribute (PluginWindow::getOpenProp (type)));
if (node->properties[PluginWindow::getOpenProp (type)])
{
jassert (node->getProcessor() != nullptr);
if (auto w = getOrCreateWindowFor (node, type))
w->toFront (true);
}
}
}
}
}
}
XmlElement* FilterGraph::createXml() const
{
auto* xml = new XmlElement ("FILTERGRAPH");
for (auto* node : graph.getNodes())
xml->addChildElement (createNodeXml (node));
for (auto& connection : graph.getConnections())
{
auto e = xml->createNewChildElement ("CONNECTION");
e->setAttribute ("srcFilter", (int) connection.source.nodeID);
e->setAttribute ("srcChannel", connection.source.channelIndex);
e->setAttribute ("dstFilter", (int) connection.destination.nodeID);
e->setAttribute ("dstChannel", connection.destination.channelIndex);
}
return xml;
}
void FilterGraph::restoreFromXml (const XmlElement& xml)
{
clear();
forEachXmlChildElementWithTagName (xml, e, "FILTER")
{
createNodeFromXml (*e);
changed();
}
forEachXmlChildElementWithTagName (xml, e, "CONNECTION")
{
graph.addConnection ({ { (NodeID) e->getIntAttribute ("srcFilter"), e->getIntAttribute ("srcChannel") },
{ (NodeID) e->getIntAttribute ("dstFilter"), e->getIntAttribute ("dstChannel") } });
}
graph.removeIllegalConnections();
}

View file

@ -0,0 +1,97 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#pragma once
#include "PluginWindow.h"
//==============================================================================
/**
A collection of filters and some connections between them.
*/
class FilterGraph : public FileBasedDocument,
public AudioProcessorListener,
private ChangeListener
{
public:
//==============================================================================
FilterGraph (AudioPluginFormatManager&);
~FilterGraph();
//==============================================================================
typedef AudioProcessorGraph::NodeID NodeID;
void addPlugin (const PluginDescription&, Point<double>);
AudioProcessorGraph::Node::Ptr getNodeForName (const String& name) const;
void setNodePosition (NodeID, Point<double>);
Point<double> getNodePosition (NodeID) const;
//==============================================================================
void clear();
PluginWindow* getOrCreateWindowFor (AudioProcessorGraph::Node*, PluginWindow::Type);
void closeCurrentlyOpenWindowsFor (AudioProcessorGraph::NodeID);
bool closeAnyOpenPluginWindows();
//==============================================================================
void audioProcessorParameterChanged (AudioProcessor*, int, float) override {}
void audioProcessorChanged (AudioProcessor*) override { changed(); }
//==============================================================================
XmlElement* createXml() const;
void restoreFromXml (const XmlElement& xml);
static const char* getFilenameSuffix() { return ".filtergraph"; }
static const char* getFilenameWildcard() { return "*.filtergraph"; }
//==============================================================================
void newDocument();
String getDocumentTitle() override;
Result loadDocument (const File& file) override;
Result saveDocument (const File& file) override;
File getLastDocumentOpened() override;
void setLastDocumentOpened (const File& file) override;
//==============================================================================
AudioProcessorGraph graph;
private:
//==============================================================================
AudioPluginFormatManager& formatManager;
OwnedArray<PluginWindow> activePluginWindows;
NodeID lastUID = 0;
NodeID getNextUID() noexcept;
void createNodeFromXml (const XmlElement& xml);
void addFilterCallback (AudioPluginInstance*, const String& error, Point<double>);
void changeListenerCallback (ChangeBroadcaster*) override;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FilterGraph)
};

View file

@ -0,0 +1,548 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#include "../JuceLibraryCode/JuceHeader.h"
#include "GraphEditorPanel.h"
#include "InternalFilters.h"
#include "MainHostWindow.h"
#include "FilterIOConfiguration.h"
//==============================================================================
struct NumberedBoxes : public TableListBox,
private TableListBoxModel,
private Button::Listener
{
struct Listener
{
virtual ~Listener() {}
virtual void addColumn() = 0;
virtual void removeColumn() = 0;
virtual void columnSelected (int columnId) = 0;
};
enum
{
plusButtonColumnId = 128,
minusButtonColumnId = 129
};
//==============================================================================
NumberedBoxes (Listener& listenerToUse, bool canCurrentlyAddColumn, bool canCurrentlyRemoveColumn)
: TableListBox ("NumberedBoxes", this),
listener (listenerToUse),
canAddColumn (canCurrentlyAddColumn),
canRemoveColumn (canCurrentlyRemoveColumn)
{
auto& tableHeader = getHeader();
for (int i = 0; i < 16; ++i)
tableHeader.addColumn (String (i + 1), i + 1, 40);
setHeaderHeight (0);
setRowHeight (40);
getHorizontalScrollBar().setAutoHide (false);
}
void setSelected (int columnId)
{
if (auto* button = dynamic_cast<TextButton*> (getCellComponent (columnId, 0)))
button->setToggleState (true, NotificationType::dontSendNotification);
}
void setCanAddColumn (bool canCurrentlyAdd)
{
if (canCurrentlyAdd != canAddColumn)
{
canAddColumn = canCurrentlyAdd;
if (auto* button = dynamic_cast<TextButton*> (getCellComponent (plusButtonColumnId, 0)))
button->setEnabled (true);
}
}
void setCanRemoveColumn (bool canCurrentlyRemove)
{
if (canCurrentlyRemove != canRemoveColumn)
{
canRemoveColumn = canCurrentlyRemove;
if (auto* button = dynamic_cast<TextButton*> (getCellComponent (minusButtonColumnId, 0)))
button->setEnabled (true);
}
}
private:
//==============================================================================
Listener& listener;
bool canAddColumn, canRemoveColumn;
//==============================================================================
int getNumRows() override { return 1; }
void paintCell (Graphics&, int, int, int, int, bool) override {}
void paintRowBackground (Graphics& g, int, int, int, bool) override { g.fillAll (Colours::grey); }
Component* refreshComponentForCell (int, int columnId, bool,
Component* existingComponentToUpdate) override
{
auto* textButton = dynamic_cast<TextButton*> (existingComponentToUpdate);
if (textButton == nullptr)
textButton = new TextButton();
textButton->setButtonText (getButtonName (columnId));
textButton->setConnectedEdges (Button::ConnectedOnLeft | Button::ConnectedOnRight |
Button::ConnectedOnTop | Button::ConnectedOnBottom);
const bool isPlusMinusButton = (columnId == plusButtonColumnId || columnId == minusButtonColumnId);
if (isPlusMinusButton)
{
textButton->setEnabled (columnId == plusButtonColumnId ? canAddColumn : canRemoveColumn);
}
else
{
textButton->setRadioGroupId (1, NotificationType::dontSendNotification);
textButton->setClickingTogglesState (true);
auto busColour = Colours::green.withRotatedHue (static_cast<float> (columnId) / 5.0f);
textButton->setColour (TextButton::buttonColourId, busColour);
textButton->setColour (TextButton::buttonOnColourId, busColour.withMultipliedBrightness (2.0f));
}
textButton->addListener (this);
return textButton;
}
//==============================================================================
String getButtonName (int columnId)
{
if (columnId == plusButtonColumnId) return "+";
if (columnId == minusButtonColumnId) return "-";
return String (columnId);
}
void buttonClicked (Button* btn) override
{
auto text = btn->getButtonText();
if (text == "+") listener.addColumn();
if (text == "-") listener.removeColumn();
}
void buttonStateChanged (Button* btn) override
{
auto text = btn->getButtonText();
if (text == "+" || text == "-")
return;
if (btn->getToggleState())
listener.columnSelected (text.getIntValue());
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NumberedBoxes)
};
//==============================================================================
class FilterIOConfigurationWindow::InputOutputConfig : public Component,
private ComboBox::Listener,
private Button::Listener,
private NumberedBoxes::Listener
{
public:
InputOutputConfig (FilterIOConfigurationWindow& parent, bool direction)
: owner (parent),
ioTitle ("ioLabel", direction ? "Input Configuration" : "Output Configuration"),
ioBuses (*this, false, false),
isInput (direction)
{
ioTitle.setFont (ioTitle.getFont().withStyle (Font::bold));
nameLabel.setFont (nameLabel.getFont().withStyle (Font::bold));
layoutLabel.setFont (layoutLabel.getFont().withStyle (Font::bold));
enabledToggle.setClickingTogglesState (true);
layouts.addListener (this);
enabledToggle.addListener (this);
addAndMakeVisible (layoutLabel);
addAndMakeVisible (layouts);
addAndMakeVisible (enabledToggle);
addAndMakeVisible (ioTitle);
addAndMakeVisible (nameLabel);
addAndMakeVisible (name);
addAndMakeVisible (ioBuses);
updateBusButtons();
updateBusLayout();
}
void paint (Graphics& g) override
{
g.fillAll (getLookAndFeel().findColour (ResizableWindow::backgroundColourId));
}
void resized() override
{
auto r = getLocalBounds().reduced (10);
ioTitle.setBounds (r.removeFromTop (14));
r.reduce (10, 0);
r.removeFromTop (16);
ioBuses.setBounds (r.removeFromTop (60));
{
auto label = r.removeFromTop (24);
nameLabel.setBounds (label.removeFromLeft (100));
enabledToggle.setBounds (label.removeFromRight (80));
name.setBounds (label);
}
{
auto label = r.removeFromTop (24);
layoutLabel.setBounds (label.removeFromLeft (100));
layouts.setBounds (label);
}
}
private:
void updateBusButtons()
{
if (auto* filter = owner.getAudioProcessor())
{
auto& header = ioBuses.getHeader();
header.removeAllColumns();
const int n = filter->getBusCount (isInput);
for (int i = 0; i < n; ++i)
header.addColumn ("", i + 1, 40);
header.addColumn ("+", NumberedBoxes::plusButtonColumnId, 20);
header.addColumn ("-", NumberedBoxes::minusButtonColumnId, 20);
ioBuses.setCanAddColumn (filter->canAddBus (isInput));
ioBuses.setCanRemoveColumn (filter->canRemoveBus (isInput));
}
ioBuses.setSelected (currentBus + 1);
}
void updateBusLayout()
{
if (auto* filter = owner.getAudioProcessor())
{
if (auto* bus = filter->getBus (isInput, currentBus))
{
name.setText (bus->getName(), NotificationType::dontSendNotification);
int i;
for (i = 1; i < AudioChannelSet::maxChannelsOfNamedLayout; ++i)
if ((layouts.indexOfItemId(i) == -1) != bus->supportedLayoutWithChannels (i).isDisabled())
break;
// supported layouts have changed
if (i < AudioChannelSet::maxChannelsOfNamedLayout)
{
layouts.clear();
for (i = 1; i < AudioChannelSet::maxChannelsOfNamedLayout; ++i)
{
auto set = bus->supportedLayoutWithChannels (i);
if (! set.isDisabled())
layouts.addItem (set.getDescription(), i);
}
}
layouts.setSelectedId (bus->getLastEnabledLayout().size());
const bool canBeDisabled = bus->isNumberOfChannelsSupported (0);
if (canBeDisabled != enabledToggle.isEnabled())
enabledToggle.setEnabled (canBeDisabled);
enabledToggle.setToggleState (bus->isEnabled(), NotificationType::dontSendNotification);
}
}
}
//==============================================================================
void comboBoxChanged (ComboBox* combo) override
{
if (combo == &layouts)
{
if (auto* p = owner.getAudioProcessor())
{
if (auto* bus = p->getBus (isInput, currentBus))
{
auto selectedNumChannels = layouts.getSelectedId();
if (selectedNumChannels != bus->getLastEnabledLayout().size())
{
if (isPositiveAndBelow (selectedNumChannels, AudioChannelSet::maxChannelsOfNamedLayout)
&& bus->setCurrentLayoutWithoutEnabling (bus->supportedLayoutWithChannels (selectedNumChannels)))
{
if (auto* config = owner.getConfig (! isInput))
config->updateBusLayout();
owner.update();
}
}
}
}
}
}
void buttonClicked (Button*) override {}
void buttonStateChanged (Button* btn) override
{
if (btn == &enabledToggle && enabledToggle.isEnabled())
{
if (auto* p = owner.getAudioProcessor())
{
if (auto* bus = p->getBus (isInput, currentBus))
{
if (bus->isEnabled() != enabledToggle.getToggleState())
{
bool success = enabledToggle.getToggleState() ? bus->enable()
: bus->setCurrentLayout (AudioChannelSet::disabled());
if (success)
{
updateBusLayout();
if (auto* config = owner.getConfig (! isInput))
config->updateBusLayout();
owner.update();
}
else
{
enabledToggle.setToggleState (! enabledToggle.getToggleState(),
NotificationType::dontSendNotification);
}
}
}
}
}
}
//==============================================================================
void addColumn() override
{
if (auto* p = owner.getAudioProcessor())
{
if (p->canAddBus (isInput))
{
if (p->addBus (isInput))
{
updateBusButtons();
updateBusLayout();
if (auto* config = owner.getConfig (! isInput))
{
config->updateBusButtons();
config->updateBusLayout();
}
}
owner.update();
}
}
}
void removeColumn() override
{
if (auto* p = owner.getAudioProcessor())
{
if (p->getBusCount (isInput) > 1 && p->canRemoveBus (isInput))
{
if (p->removeBus (isInput))
{
currentBus = jmin (p->getBusCount (isInput) - 1, currentBus);
updateBusButtons();
updateBusLayout();
if (auto* config = owner.getConfig (! isInput))
{
config->updateBusButtons();
config->updateBusLayout();
}
owner.update();
}
}
}
}
void columnSelected (int columnId) override
{
const int newBus = columnId - 1;
if (currentBus != newBus)
{
currentBus = newBus;
ioBuses.setSelected (currentBus + 1);
updateBusLayout();
}
}
//==============================================================================
FilterIOConfigurationWindow& owner;
Label ioTitle, name;
Label nameLabel { "nameLabel", "Bus Name:" };
Label layoutLabel { "layoutLabel", "Channel Layout:" };
ToggleButton enabledToggle { "Enabled" };
ComboBox layouts;
NumberedBoxes ioBuses;
bool isInput;
int currentBus = 0;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (InputOutputConfig)
};
FilterIOConfigurationWindow::FilterIOConfigurationWindow (AudioProcessor& p)
: AudioProcessorEditor (&p),
title ("title", p.getName())
{
setOpaque (true);
title.setFont (title.getFont().withStyle (Font::bold));
addAndMakeVisible (title);
{
ScopedLock renderLock (p.getCallbackLock());
p.suspendProcessing (true);
p.releaseResources();
}
if (p.getBusCount (true) > 0 || p.canAddBus (true))
addAndMakeVisible (inConfig = new InputOutputConfig (*this, true));
if (p.getBusCount (false) > 0 || p.canAddBus (false))
addAndMakeVisible (outConfig = new InputOutputConfig (*this, false));
currentLayout = p.getBusesLayout();
setSize (400, (inConfig != nullptr && outConfig != nullptr ? 160 : 0) + 200);
}
FilterIOConfigurationWindow::~FilterIOConfigurationWindow()
{
if (auto* graph = getGraph())
{
if (auto* p = getAudioProcessor())
{
ScopedLock renderLock (graph->getCallbackLock());
graph->suspendProcessing (true);
graph->releaseResources();
p->prepareToPlay (graph->getSampleRate(), graph->getBlockSize());
p->suspendProcessing (false);
graph->prepareToPlay (graph->getSampleRate(), graph->getBlockSize());
graph->suspendProcessing (false);
}
}
}
void FilterIOConfigurationWindow::paint (Graphics& g)
{
g.fillAll (getLookAndFeel().findColour (ResizableWindow::backgroundColourId));
}
void FilterIOConfigurationWindow::resized()
{
auto r = getLocalBounds().reduced (10);
title.setBounds (r.removeFromTop (14));
r.reduce (10, 0);
if (inConfig != nullptr)
inConfig->setBounds (r.removeFromTop (160));
if (outConfig != nullptr)
outConfig->setBounds (r.removeFromTop (160));
}
void FilterIOConfigurationWindow::update()
{
auto nodeID = getNodeID();
if (auto* graph = getGraph())
if (nodeID != 0)
graph->disconnectNode (nodeID);
if (auto* graphEditor = getGraphEditor())
if (auto* panel = graphEditor->graphPanel.get())
panel->updateComponents();
}
AudioProcessorGraph::NodeID FilterIOConfigurationWindow::getNodeID() const
{
if (auto* graph = getGraph())
for (auto* node : graph->getNodes())
if (node->getProcessor() == getAudioProcessor())
return node->nodeID;
return 0;
}
MainHostWindow* FilterIOConfigurationWindow::getMainWindow() const
{
auto& desktop = Desktop::getInstance();
for (int i = desktop.getNumComponents(); --i >= 0;)
if (auto* mainWindow = dynamic_cast<MainHostWindow*> (desktop.getComponent(i)))
return mainWindow;
return nullptr;
}
GraphDocumentComponent* FilterIOConfigurationWindow::getGraphEditor() const
{
if (auto* mainWindow = getMainWindow())
return mainWindow->graphHolder.get();
return nullptr;
}
AudioProcessorGraph* FilterIOConfigurationWindow::getGraph() const
{
if (auto* graphEditor = getGraphEditor())
if (auto* panel = graphEditor->graph.get())
return &panel->graph;
return nullptr;
}

View file

@ -0,0 +1,60 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#pragma once
class MainHostWindow;
class GraphDocumentComponent;
//==============================================================================
class FilterIOConfigurationWindow : public AudioProcessorEditor
{
public:
FilterIOConfigurationWindow (AudioProcessor&);
~FilterIOConfigurationWindow();
//==============================================================================
void paint (Graphics& g) override;
void resized() override;
private:
class InputOutputConfig;
AudioProcessor::BusesLayout currentLayout;
Label title;
ScopedPointer<InputOutputConfig> inConfig, outConfig;
InputOutputConfig* getConfig (bool isInput) noexcept { return isInput ? inConfig : outConfig; }
void update();
MainHostWindow* getMainWindow() const;
GraphDocumentComponent* getGraphEditor() const;
AudioProcessorGraph* getGraph() const;
AudioProcessorGraph::NodeID getNodeID() const;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FilterIOConfigurationWindow)
};

View file

@ -0,0 +1,866 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#include "../JuceLibraryCode/JuceHeader.h"
#include "GraphEditorPanel.h"
#include "InternalFilters.h"
#include "MainHostWindow.h"
//==============================================================================
struct GraphEditorPanel::PinComponent : public Component,
public SettableTooltipClient
{
PinComponent (GraphEditorPanel& p, AudioProcessorGraph::NodeAndChannel pinToUse, bool isIn)
: panel (p), graph (p.graph), pin (pinToUse), isInput (isIn)
{
if (auto node = graph.graph.getNodeForId (pin.nodeID))
{
String tip;
if (pin.isMIDI())
{
tip = isInput ? "MIDI Input"
: "MIDI Output";
}
else
{
auto& processor = *node->getProcessor();
auto channel = processor.getOffsetInBusBufferForAbsoluteChannelIndex (isInput, pin.channelIndex, busIdx);
if (auto* bus = processor.getBus (isInput, busIdx))
tip = bus->getName() + ": " + AudioChannelSet::getAbbreviatedChannelTypeName (bus->getCurrentLayout().getTypeOfChannel (channel));
else
tip = (isInput ? "Main Input: "
: "Main Output: ") + String (pin.channelIndex + 1);
}
setTooltip (tip);
}
setSize (16, 16);
}
void paint (Graphics& g) override
{
auto w = (float) getWidth();
auto 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);
auto colour = (pin.isMIDI() ? Colours::red : Colours::green);
g.setColour (colour.withRotatedHue (busIdx / 5.0f));
g.fillPath (p);
}
void mouseDown (const MouseEvent& e) override
{
AudioProcessorGraph::NodeAndChannel dummy { 0, 0 };
panel.beginConnectorDrag (isInput ? dummy : pin,
isInput ? pin : dummy,
e);
}
void mouseDrag (const MouseEvent& e) override
{
panel.dragConnector (e);
}
void mouseUp (const MouseEvent& e) override
{
panel.endDraggingConnector (e);
}
GraphEditorPanel& panel;
FilterGraph& graph;
AudioProcessorGraph::NodeAndChannel pin;
const bool isInput;
int busIdx = 0;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PinComponent)
};
//==============================================================================
struct GraphEditorPanel::FilterComponent : public Component
{
FilterComponent (GraphEditorPanel& p, uint32 id) : panel (p), graph (p.graph), pluginID (id)
{
shadow.setShadowProperties (DropShadow (Colours::black.withAlpha (0.5f), 3, { 0, 1 }));
setComponentEffect (&shadow);
setSize (150, 60);
}
FilterComponent (const FilterComponent&) = delete;
FilterComponent& operator= (const FilterComponent&) = delete;
void mouseDown (const MouseEvent& e) override
{
originalPos = localPointToGlobal (Point<int>());
toFront (true);
if (e.mods.isPopupMenu())
showPopupMenu();
}
void mouseDrag (const MouseEvent& e) override
{
if (! e.mods.isPopupMenu())
{
auto pos = originalPos + e.getOffsetFromDragStart();
if (getParentComponent() != nullptr)
pos = getParentComponent()->getLocalPoint (nullptr, pos);
pos += getLocalBounds().getCentre();
graph.setNodePosition (pluginID,
{ pos.x / (double) getParentWidth(),
pos.y / (double) getParentHeight() });
panel.updateComponents();
}
}
void mouseUp (const MouseEvent& e) override
{
if (e.mouseWasDraggedSinceMouseDown())
{
graph.setChangedFlag (true);
}
else if (e.getNumberOfClicks() == 2)
{
if (auto f = graph.graph.getNodeForId (pluginID))
if (auto* w = graph.getOrCreateWindowFor (f, PluginWindow::Type::normal))
w->toFront (true);
}
}
bool hitTest (int x, int y) override
{
for (auto* child : getChildren())
if (child->getBounds().contains (x, y))
return true;
return x >= 3 && x < getWidth() - 6 && y >= pinSize && y < getHeight() - pinSize;
}
void paint (Graphics& g) override
{
auto boxArea = getLocalBounds().reduced (4, pinSize);
g.setColour (findColour (TextEditor::backgroundColourId));
g.fillRect (boxArea.toFloat());
g.setColour (findColour (TextEditor::textColourId));
g.setFont (font);
g.drawFittedText (getName(), boxArea, Justification::centred, 2);
}
void resized() override
{
if (auto f = graph.graph.getNodeForId (pluginID))
{
if (auto* processor = f->getProcessor())
{
for (auto* pin : pins)
{
const bool isInput = pin->isInput;
auto channelIndex = pin->pin.channelIndex;
int busIdx = 0;
processor->getOffsetInBusBufferForAbsoluteChannelIndex (isInput, channelIndex, busIdx);
const int total = isInput ? numIns : numOuts;
const int index = pin->pin.isMIDI() ? (total - 1) : channelIndex;
auto totalSpaces = static_cast<float> (total) + (static_cast<float> (jmax (0, processor->getBusCount (isInput) - 1)) * 0.5f);
auto indexPos = static_cast<float> (index) + (static_cast<float> (busIdx) * 0.5f);
pin->setBounds (proportionOfWidth ((1.0f + indexPos) / (totalSpaces + 1.0f)) - pinSize / 2,
pin->isInput ? 0 : (getHeight() - pinSize),
pinSize, pinSize);
}
}
}
}
Point<float> getPinPos (int index, bool isInput) const
{
for (auto* pin : pins)
if (pin->pin.channelIndex == index && isInput == pin->isInput)
return getPosition().toFloat() + pin->getBounds().getCentre().toFloat();
return {};
}
void update()
{
const AudioProcessorGraph::Node::Ptr f (graph.graph.getNodeForId (pluginID));
jassert (f != nullptr);
numIns = f->getProcessor()->getTotalNumInputChannels();
if (f->getProcessor()->acceptsMidi())
++numIns;
numOuts = f->getProcessor()->getTotalNumOutputChannels();
if (f->getProcessor()->producesMidi())
++numOuts;
int w = 100;
int h = 60;
w = jmax (w, (jmax (numIns, numOuts) + 1) * 20);
const int textWidth = font.getStringWidth (f->getProcessor()->getName());
w = jmax (w, 16 + jmin (textWidth, 300));
if (textWidth > 300)
h = 100;
setSize (w, h);
setName (f->getProcessor()->getName());
{
auto p = graph.getNodePosition (pluginID);
setCentreRelative ((float) p.x, (float) p.y);
}
if (numIns != numInputs || numOuts != numOutputs)
{
numInputs = numIns;
numOutputs = numOuts;
pins.clear();
for (int i = 0; i < f->getProcessor()->getTotalNumInputChannels(); ++i)
addAndMakeVisible (pins.add (new PinComponent (panel, { pluginID, i }, true)));
if (f->getProcessor()->acceptsMidi())
addAndMakeVisible (pins.add (new PinComponent (panel, { pluginID, AudioProcessorGraph::midiChannelIndex }, true)));
for (int i = 0; i < f->getProcessor()->getTotalNumOutputChannels(); ++i)
addAndMakeVisible (pins.add (new PinComponent (panel, { pluginID, i }, false)));
if (f->getProcessor()->producesMidi())
addAndMakeVisible (pins.add (new PinComponent (panel, { pluginID, AudioProcessorGraph::midiChannelIndex }, false)));
resized();
}
}
AudioProcessor* getProcessor() const
{
if (auto node = graph.graph.getNodeForId (pluginID))
return node->getProcessor();
return {};
}
void showPopupMenu()
{
PopupMenu m;
m.addItem (1, "Delete this filter");
m.addItem (2, "Disconnect all pins");
m.addSeparator();
m.addItem (10, "Show plugin GUI");
m.addItem (11, "Show all programs");
m.addItem (12, "Show all parameters");
m.addSeparator();
m.addItem (20, "Configure Audio I/O");
m.addItem (21, "Test state save/load");
switch (m.show())
{
case 1: graph.graph.removeNode (pluginID); break;
case 2: graph.graph.disconnectNode (pluginID); break;
case 10: showWindow (PluginWindow::Type::normal); break;
case 11: showWindow (PluginWindow::Type::programs); break;
case 12: showWindow (PluginWindow::Type::generic); break;
case 20: showWindow (PluginWindow::Type::audioIO); break;
case 21: testStateSaveLoad(); break;
default: break;
}
}
void testStateSaveLoad()
{
if (auto* processor = getProcessor())
{
MemoryBlock state;
processor->getStateInformation (state);
processor->setStateInformation (state.getData(), (int) state.getSize());
}
}
void showWindow (PluginWindow::Type type)
{
if (auto node = graph.graph.getNodeForId (pluginID))
if (auto* w = graph.getOrCreateWindowFor (node, type))
w->toFront (true);
}
GraphEditorPanel& panel;
FilterGraph& graph;
const AudioProcessorGraph::NodeID pluginID;
OwnedArray<PinComponent> pins;
int numInputs = 0, numOutputs = 0;
int pinSize = 16;
Point<int> originalPos;
Font font { 13.0f, Font::bold };
int numIns = 0, numOuts = 0;
DropShadowEffect shadow;
};
//==============================================================================
struct GraphEditorPanel::ConnectorComponent : public Component,
public SettableTooltipClient
{
ConnectorComponent (GraphEditorPanel& p) : panel (p), graph (p.graph)
{
setAlwaysOnTop (true);
}
void setInput (AudioProcessorGraph::NodeAndChannel newSource)
{
if (connection.source != newSource)
{
connection.source = newSource;
update();
}
}
void setOutput (AudioProcessorGraph::NodeAndChannel newDest)
{
if (connection.destination != newDest)
{
connection.destination = newDest;
update();
}
}
void dragStart (Point<float> pos)
{
lastInputPos = pos;
resizeToFit();
}
void dragEnd (Point<float> pos)
{
lastOutputPos = pos;
resizeToFit();
}
void update()
{
Point<float> p1, p2;
getPoints (p1, p2);
if (lastInputPos != p1 || lastOutputPos != p2)
resizeToFit();
}
void resizeToFit()
{
Point<float> p1, p2;
getPoints (p1, p2);
auto newBounds = Rectangle<float> (p1, p2).expanded (4.0f).getSmallestIntegerContainer();
if (newBounds != getBounds())
setBounds (newBounds);
else
resized();
repaint();
}
void getPoints (Point<float>& p1, Point<float>& p2) const
{
p1 = lastInputPos;
p2 = lastOutputPos;
if (auto* src = panel.getComponentForFilter (connection.source.nodeID))
p1 = src->getPinPos (connection.source.channelIndex, false);
if (auto* dest = panel.getComponentForFilter (connection.destination.nodeID))
p2 = dest->getPinPos (connection.destination.channelIndex, true);
}
void paint (Graphics& g) override
{
if (connection.source.isMIDI() || connection.destination.isMIDI())
g.setColour (Colours::red);
else
g.setColour (Colours::green);
g.fillPath (linePath);
}
bool hitTest (int x, int y) override
{
auto pos = Point<int> (x, y).toFloat();
if (hitPath.contains (pos))
{
double distanceFromStart, distanceFromEnd;
getDistancesFromEnds (pos, distanceFromStart, distanceFromEnd);
// avoid clicking the connector when over a pin
return distanceFromStart > 7.0 && distanceFromEnd > 7.0;
}
return false;
}
void mouseDown (const MouseEvent&) override
{
dragging = false;
}
void mouseDrag (const MouseEvent& e) override
{
if (dragging)
{
panel.dragConnector (e);
}
else if (e.mouseWasDraggedSinceMouseDown())
{
dragging = true;
graph.graph.removeConnection (connection);
double distanceFromStart, distanceFromEnd;
getDistancesFromEnds (getPosition().toFloat() + e.position, distanceFromStart, distanceFromEnd);
const bool isNearerSource = (distanceFromStart < distanceFromEnd);
AudioProcessorGraph::NodeAndChannel dummy { 0, 0 };
panel.beginConnectorDrag (isNearerSource ? dummy : connection.source,
isNearerSource ? connection.destination : dummy,
e);
}
}
void mouseUp (const MouseEvent& e) override
{
if (dragging)
panel.endDraggingConnector (e);
}
void resized() override
{
Point<float> p1, p2;
getPoints (p1, p2);
lastInputPos = p1;
lastOutputPos = p2;
p1 -= getPosition().toFloat();
p2 -= getPosition().toFloat();
linePath.clear();
linePath.startNewSubPath (p1);
linePath.cubicTo (p1.x, p1.y + (p2.y - p1.y) * 0.33f,
p2.x, p1.y + (p2.y - p1.y) * 0.66f,
p2.x, p2.y);
PathStrokeType wideStroke (8.0f);
wideStroke.createStrokedPath (hitPath, linePath);
PathStrokeType stroke (2.5f);
stroke.createStrokedPath (linePath, linePath);
auto arrowW = 5.0f;
auto arrowL = 4.0f;
Path arrow;
arrow.addTriangle (-arrowL, arrowW,
-arrowL, -arrowW,
arrowL, 0.0f);
arrow.applyTransform (AffineTransform()
.rotated (MathConstants<float>::halfPi - (float) atan2 (p2.x - p1.x, p2.y - p1.y))
.translated ((p1 + p2) * 0.5f));
linePath.addPath (arrow);
linePath.setUsingNonZeroWinding (true);
}
void getDistancesFromEnds (Point<float> p, double& distanceFromStart, double& distanceFromEnd) const
{
Point<float> p1, p2;
getPoints (p1, p2);
distanceFromStart = p1.getDistanceFrom (p);
distanceFromEnd = p2.getDistanceFrom (p);
}
GraphEditorPanel& panel;
FilterGraph& graph;
AudioProcessorGraph::Connection connection { { 0, 0 }, { 0, 0 } };
Point<float> lastInputPos, lastOutputPos;
Path linePath, hitPath;
bool dragging = false;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ConnectorComponent)
};
//==============================================================================
GraphEditorPanel::GraphEditorPanel (FilterGraph& g) : graph (g)
{
graph.addChangeListener (this);
setOpaque (true);
}
GraphEditorPanel::~GraphEditorPanel()
{
graph.removeChangeListener (this);
draggingConnector = nullptr;
nodes.clear();
connectors.clear();
}
void GraphEditorPanel::paint (Graphics& g)
{
g.fillAll (getLookAndFeel().findColour (ResizableWindow::backgroundColourId));
}
void GraphEditorPanel::mouseDown (const MouseEvent& e)
{
if (e.mods.isPopupMenu())
{
PopupMenu m;
if (auto* mainWindow = findParentComponentOfClass<MainHostWindow>())
{
mainWindow->addPluginsToMenu (m);
auto r = m.show();
if (auto* desc = mainWindow->getChosenType (r))
createNewPlugin (*desc, e.position.toInt());
}
}
}
void GraphEditorPanel::createNewPlugin (const PluginDescription& desc, Point<int> position)
{
graph.addPlugin (desc, position.toDouble() / Point<double> ((double) getWidth(), (double) getHeight()));
}
GraphEditorPanel::FilterComponent* GraphEditorPanel::getComponentForFilter (const uint32 filterID) const
{
for (auto* fc : nodes)
if (fc->pluginID == filterID)
return fc;
return nullptr;
}
GraphEditorPanel::ConnectorComponent* GraphEditorPanel::getComponentForConnection (const AudioProcessorGraph::Connection& conn) const
{
for (auto* cc : connectors)
if (cc->connection == conn)
return cc;
return nullptr;
}
GraphEditorPanel::PinComponent* GraphEditorPanel::findPinAt (Point<float> pos) const
{
for (auto* fc : nodes)
{
// NB: A Visual Studio optimiser error means we have to put this Component* in a local
// variable before trying to cast it, or it gets mysteriously optimised away..
auto* comp = fc->getComponentAt (pos.toInt() - fc->getPosition());
if (auto* pin = dynamic_cast<PinComponent*> (comp))
return pin;
}
return nullptr;
}
void GraphEditorPanel::resized()
{
updateComponents();
}
void GraphEditorPanel::changeListenerCallback (ChangeBroadcaster*)
{
updateComponents();
}
void GraphEditorPanel::updateComponents()
{
for (int i = nodes.size(); --i >= 0;)
if (graph.graph.getNodeForId (nodes.getUnchecked(i)->pluginID) == nullptr)
nodes.remove (i);
for (int i = connectors.size(); --i >= 0;)
if (! graph.graph.isConnected (connectors.getUnchecked(i)->connection))
connectors.remove (i);
for (auto* fc : nodes)
fc->update();
for (auto* cc : connectors)
cc->update();
for (auto* f : graph.graph.getNodes())
{
if (getComponentForFilter (f->nodeID) == 0)
{
auto* comp = nodes.add (new FilterComponent (*this, f->nodeID));
addAndMakeVisible (comp);
comp->update();
}
}
for (auto& c : graph.graph.getConnections())
{
if (getComponentForConnection (c) == 0)
{
auto* comp = connectors.add (new ConnectorComponent (*this));
addAndMakeVisible (comp);
comp->setInput (c.source);
comp->setOutput (c.destination);
}
}
}
void GraphEditorPanel::beginConnectorDrag (AudioProcessorGraph::NodeAndChannel source,
AudioProcessorGraph::NodeAndChannel dest,
const MouseEvent& e)
{
auto* c = dynamic_cast<ConnectorComponent*> (e.originalComponent);
connectors.removeObject (c, false);
draggingConnector = c;
if (draggingConnector == nullptr)
draggingConnector = new ConnectorComponent (*this);
draggingConnector->setInput (source);
draggingConnector->setOutput (dest);
addAndMakeVisible (draggingConnector);
draggingConnector->toFront (false);
dragConnector (e);
}
void GraphEditorPanel::dragConnector (const MouseEvent& e)
{
auto e2 = e.getEventRelativeTo (this);
if (draggingConnector != nullptr)
{
draggingConnector->setTooltip ({});
auto pos = e2.position;
if (auto* pin = findPinAt (pos))
{
auto connection = draggingConnector->connection;
if (connection.source.nodeID == 0 && ! pin->isInput)
{
connection.source = pin->pin;
}
else if (connection.destination.nodeID == 0 && pin->isInput)
{
connection.destination = pin->pin;
}
if (graph.graph.canConnect (connection))
{
pos = (pin->getParentComponent()->getPosition() + pin->getBounds().getCentre()).toFloat();
draggingConnector->setTooltip (pin->getTooltip());
}
}
if (draggingConnector->connection.source.nodeID == 0)
draggingConnector->dragStart (pos);
else
draggingConnector->dragEnd (pos);
}
}
void GraphEditorPanel::endDraggingConnector (const MouseEvent& e)
{
if (draggingConnector == nullptr)
return;
draggingConnector->setTooltip ({});
auto e2 = e.getEventRelativeTo (this);
auto connection = draggingConnector->connection;
draggingConnector = nullptr;
if (auto* pin = findPinAt (e2.position))
{
if (connection.source.nodeID == 0)
{
if (pin->isInput)
return;
connection.source = pin->pin;
}
else
{
if (! pin->isInput)
return;
connection.destination = pin->pin;
}
graph.graph.addConnection (connection);
}
}
//==============================================================================
struct GraphDocumentComponent::TooltipBar : public Component,
private Timer
{
TooltipBar()
{
startTimer (100);
}
void paint (Graphics& g) override
{
g.setFont (Font (getHeight() * 0.7f, Font::bold));
g.setColour (Colours::black);
g.drawFittedText (tip, 10, 0, getWidth() - 12, getHeight(), Justification::centredLeft, 1);
}
void timerCallback() override
{
String newTip;
if (auto* underMouse = Desktop::getInstance().getMainMouseSource().getComponentUnderMouse())
if (auto* ttc = dynamic_cast<TooltipClient*> (underMouse))
if (! (underMouse->isMouseButtonDown() || underMouse->isCurrentlyBlockedByAnotherModalComponent()))
newTip = ttc->getTooltip();
if (newTip != tip)
{
tip = newTip;
repaint();
}
}
String tip;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TooltipBar)
};
//==============================================================================
GraphDocumentComponent::GraphDocumentComponent (AudioPluginFormatManager& fm, AudioDeviceManager& dm)
: graph (new FilterGraph (fm)), deviceManager (dm),
graphPlayer (getAppProperties().getUserSettings()->getBoolValue ("doublePrecisionProcessing", false))
{
addAndMakeVisible (graphPanel = new GraphEditorPanel (*graph));
deviceManager.addChangeListener (graphPanel);
graphPlayer.setProcessor (&graph->graph);
keyState.addListener (&graphPlayer.getMidiMessageCollector());
addAndMakeVisible (keyboardComp = new MidiKeyboardComponent (keyState, MidiKeyboardComponent::horizontalKeyboard));
addAndMakeVisible (statusBar = new TooltipBar());
deviceManager.addAudioCallback (&graphPlayer);
deviceManager.addMidiInputCallback (String(), &graphPlayer.getMidiMessageCollector());
graphPanel->updateComponents();
}
GraphDocumentComponent::~GraphDocumentComponent()
{
releaseGraph();
keyState.removeListener (&graphPlayer.getMidiMessageCollector());
}
void GraphDocumentComponent::resized()
{
const int keysHeight = 60;
const int statusHeight = 20;
graphPanel->setBounds (0, 0, getWidth(), getHeight() - keysHeight);
statusBar->setBounds (0, getHeight() - keysHeight - statusHeight, getWidth(), statusHeight);
keyboardComp->setBounds (0, getHeight() - keysHeight, getWidth(), keysHeight);
}
void GraphDocumentComponent::createNewPlugin (const PluginDescription& desc, Point<int> pos)
{
graphPanel->createNewPlugin (desc, pos);
}
void GraphDocumentComponent::unfocusKeyboardComponent()
{
keyboardComp->unfocusAllComponents();
}
void GraphDocumentComponent::releaseGraph()
{
deviceManager.removeAudioCallback (&graphPlayer);
deviceManager.removeMidiInputCallback (String(), &graphPlayer.getMidiMessageCollector());
if (graphPanel != nullptr)
{
deviceManager.removeChangeListener (graphPanel);
graphPanel = nullptr;
}
keyboardComp = nullptr;
statusBar = nullptr;
graphPlayer.setProcessor (nullptr);
graph = nullptr;
}
void GraphDocumentComponent::setDoublePrecision (bool doublePrecision)
{
graphPlayer.setDoublePrecisionProcessing (doublePrecision);
}
bool GraphDocumentComponent::closeAnyOpenPluginWindows()
{
return graphPanel->graph.closeAnyOpenPluginWindows();
}

View file

@ -0,0 +1,116 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#pragma once
#include "FilterGraph.h"
//==============================================================================
/**
A panel that displays and edits a FilterGraph.
*/
class GraphEditorPanel : public Component,
public ChangeListener
{
public:
GraphEditorPanel (FilterGraph& graph);
~GraphEditorPanel();
void createNewPlugin (const PluginDescription&, Point<int> position);
void paint (Graphics&) override;
void mouseDown (const MouseEvent&) override;
void resized() override;
void changeListenerCallback (ChangeBroadcaster*) override;
void updateComponents();
//==============================================================================
void beginConnectorDrag (AudioProcessorGraph::NodeAndChannel source,
AudioProcessorGraph::NodeAndChannel dest,
const MouseEvent&);
void dragConnector (const MouseEvent&);
void endDraggingConnector (const MouseEvent&);
//==============================================================================
FilterGraph& graph;
private:
struct FilterComponent;
struct ConnectorComponent;
struct PinComponent;
OwnedArray<FilterComponent> nodes;
OwnedArray<ConnectorComponent> connectors;
ScopedPointer<ConnectorComponent> draggingConnector;
FilterComponent* getComponentForFilter (AudioProcessorGraph::NodeID) const;
ConnectorComponent* getComponentForConnection (const AudioProcessorGraph::Connection&) const;
PinComponent* findPinAt (Point<float>) const;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (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:
GraphDocumentComponent (AudioPluginFormatManager& formatManager,
AudioDeviceManager& deviceManager);
~GraphDocumentComponent();
//==============================================================================
void createNewPlugin (const PluginDescription&, Point<int> position);
void setDoublePrecision (bool doublePrecision);
bool closeAnyOpenPluginWindows();
//==============================================================================
ScopedPointer<FilterGraph> graph;
void resized();
void unfocusKeyboardComponent();
void releaseGraph();
ScopedPointer<GraphEditorPanel> graphPanel;
ScopedPointer<MidiKeyboardComponent> keyboardComp;
private:
//==============================================================================
AudioDeviceManager& deviceManager;
AudioProcessorPlayer graphPlayer;
MidiKeyboardState keyState;
struct TooltipBar;
ScopedPointer<TooltipBar> statusBar;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GraphDocumentComponent)
};

View file

@ -0,0 +1,133 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#include "../JuceLibraryCode/JuceHeader.h"
#include "MainHostWindow.h"
#include "InternalFilters.h"
#if ! (JUCE_PLUGINHOST_VST || JUCE_PLUGINHOST_VST3 || JUCE_PLUGINHOST_AU)
#error "If you're building the audio plugin host, you probably want to enable VST and/or AU support"
#endif
//==============================================================================
class PluginHostApp : public JUCEApplication,
private AsyncUpdater
{
public:
PluginHostApp() {}
void initialise (const String&) override
{
// initialise our settings file..
PropertiesFile::Options options;
options.applicationName = "Juce Audio Plugin Host";
options.filenameSuffix = "settings";
options.osxLibrarySubFolder = "Preferences";
appProperties = new ApplicationProperties();
appProperties->setStorageParameters (options);
mainWindow = new MainHostWindow();
mainWindow->setUsingNativeTitleBar (true);
commandManager.registerAllCommandsForTarget (this);
commandManager.registerAllCommandsForTarget (mainWindow);
mainWindow->menuItemsChanged();
// Important note! We're going to use an async update here so that if we need
// to re-open a file and instantiate some plugins, it will happen AFTER this
// initialisation method has returned.
// On Windows this probably won't make a difference, but on OSX there's a subtle event loop
// issue that can happen if a plugin runs one of those irritating modal dialogs while it's
// being loaded. If that happens inside this method, the OSX event loop seems to be in some
// kind of special "initialisation" mode and things get confused. But if we load the plugin
// later when the normal event loop is running, everything's fine.
triggerAsyncUpdate();
}
void handleAsyncUpdate() override
{
File fileToOpen;
for (int i = 0; i < getCommandLineParameterArray().size(); ++i)
{
fileToOpen = File::getCurrentWorkingDirectory().getChildFile (getCommandLineParameterArray()[i]);
if (fileToOpen.existsAsFile())
break;
}
if (! fileToOpen.existsAsFile())
{
RecentlyOpenedFilesList recentFiles;
recentFiles.restoreFromString (getAppProperties().getUserSettings()->getValue ("recentFilterGraphFiles"));
if (recentFiles.getNumFiles() > 0)
fileToOpen = recentFiles.getFile (0);
}
if (fileToOpen.existsAsFile())
if (auto* graph = mainWindow->graphHolder.get())
if (auto* ioGraph = graph->graph.get())
ioGraph->loadFrom (fileToOpen, true);
}
void shutdown() override
{
mainWindow = nullptr;
appProperties = nullptr;
LookAndFeel::setDefaultLookAndFeel (nullptr);
}
void systemRequestedQuit() override
{
if (mainWindow != nullptr)
mainWindow->tryToQuitApplication();
else
JUCEApplicationBase::quit();
}
const String getApplicationName() override { return "Juce Plug-In Host"; }
const String getApplicationVersion() override { return ProjectInfo::versionString; }
bool moreThanOneInstanceAllowed() override { return true; }
ApplicationCommandManager commandManager;
ScopedPointer<ApplicationProperties> appProperties;
private:
ScopedPointer<MainHostWindow> mainWindow;
};
static PluginHostApp& getApp() { return *dynamic_cast<PluginHostApp*>(JUCEApplication::getInstance()); }
ApplicationCommandManager& getCommandManager() { return getApp().commandManager; }
ApplicationProperties& getAppProperties() { return *getApp().appProperties; }
// This kicks the whole thing off..
START_JUCE_APPLICATION (PluginHostApp)

View file

@ -0,0 +1,81 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#include "../JuceLibraryCode/JuceHeader.h"
#include "InternalFilters.h"
#include "FilterGraph.h"
//==============================================================================
InternalPluginFormat::InternalPluginFormat()
{
{
AudioProcessorGraph::AudioGraphIOProcessor p (AudioProcessorGraph::AudioGraphIOProcessor::audioOutputNode);
p.fillInPluginDescription (audioOutDesc);
}
{
AudioProcessorGraph::AudioGraphIOProcessor p (AudioProcessorGraph::AudioGraphIOProcessor::audioInputNode);
p.fillInPluginDescription (audioInDesc);
}
{
AudioProcessorGraph::AudioGraphIOProcessor p (AudioProcessorGraph::AudioGraphIOProcessor::midiInputNode);
p.fillInPluginDescription (midiInDesc);
}
}
AudioPluginInstance* InternalPluginFormat::createInstance (const String& name)
{
if (name == audioOutDesc.name) return new AudioProcessorGraph::AudioGraphIOProcessor (AudioProcessorGraph::AudioGraphIOProcessor::audioOutputNode);
if (name == audioInDesc.name) return new AudioProcessorGraph::AudioGraphIOProcessor (AudioProcessorGraph::AudioGraphIOProcessor::audioInputNode);
if (name == midiInDesc.name) return new AudioProcessorGraph::AudioGraphIOProcessor (AudioProcessorGraph::AudioGraphIOProcessor::midiInputNode);
return nullptr;
}
void InternalPluginFormat::createPluginInstance (const PluginDescription& desc,
double /*initialSampleRate*/,
int /*initialBufferSize*/,
void* userData,
void (*callback) (void*, AudioPluginInstance*, const String&))
{
auto* p = createInstance (desc.name);
callback (userData, p, p == nullptr ? NEEDS_TRANS ("Invalid internal filter name") : String());
}
bool InternalPluginFormat::requiresUnblockedMessageThreadDuringCreation (const PluginDescription&) const noexcept
{
return false;
}
void InternalPluginFormat::getAllTypes (OwnedArray<PluginDescription>& results)
{
results.add (new PluginDescription (audioInDesc));
results.add (new PluginDescription (audioOutDesc));
results.add (new PluginDescription (midiInDesc));
}

View file

@ -0,0 +1,66 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#pragma once
#include "FilterGraph.h"
//==============================================================================
/**
Manages the internal plugin types.
*/
class InternalPluginFormat : public AudioPluginFormat
{
public:
//==============================================================================
InternalPluginFormat();
~InternalPluginFormat() {}
//==============================================================================
PluginDescription audioInDesc, audioOutDesc, midiInDesc;
void getAllTypes (OwnedArray<PluginDescription>&);
//==============================================================================
String getName() const override { return "Internal"; }
bool fileMightContainThisPluginType (const String&) override { return true; }
FileSearchPath getDefaultLocationsToSearch() override { return {}; }
bool canScanForPlugins() const override { return false; }
void findAllTypesForFile (OwnedArray <PluginDescription>&, const String&) override {}
bool doesPluginStillExist (const PluginDescription&) override { return true; }
String getNameOfPluginFromIdentifier (const String& fileOrIdentifier) override { return fileOrIdentifier; }
bool pluginNeedsRescanning (const PluginDescription&) override { return false; }
StringArray searchPathsForPlugins (const FileSearchPath&, bool, bool) override { return {}; }
private:
//==============================================================================
void createPluginInstance (const PluginDescription&, double initialSampleRate, int initialBufferSize,
void* userData, void (*callback) (void*, AudioPluginInstance*, const String&)) override;
AudioPluginInstance* createInstance (const String& name);
bool requiresUnblockedMessageThreadDuringCreation (const PluginDescription&) const noexcept override;
};

View file

@ -0,0 +1,604 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#include "../JuceLibraryCode/JuceHeader.h"
#include "MainHostWindow.h"
#include "InternalFilters.h"
//==============================================================================
class MainHostWindow::PluginListWindow : public DocumentWindow
{
public:
PluginListWindow (MainHostWindow& mw, AudioPluginFormatManager& pluginFormatManager)
: DocumentWindow ("Available Plugins",
LookAndFeel::getDefaultLookAndFeel().findColour (ResizableWindow::backgroundColourId),
DocumentWindow::minimiseButton | DocumentWindow::closeButton),
owner (mw)
{
auto deadMansPedalFile = getAppProperties().getUserSettings()
->getFile().getSiblingFile ("RecentlyCrashedPluginsList");
setContentOwned (new PluginListComponent (pluginFormatManager,
owner.knownPluginList,
deadMansPedalFile,
getAppProperties().getUserSettings(), true), true);
setResizable (true, false);
setResizeLimits (300, 400, 800, 1500);
setTopLeftPosition (60, 60);
restoreWindowStateFromString (getAppProperties().getUserSettings()->getValue ("listWindowPos"));
setVisible (true);
}
~PluginListWindow()
{
getAppProperties().getUserSettings()->setValue ("listWindowPos", getWindowStateAsString());
clearContentComponent();
}
void closeButtonPressed() override
{
owner.pluginListWindow = nullptr;
}
private:
MainHostWindow& owner;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PluginListWindow)
};
//==============================================================================
MainHostWindow::MainHostWindow()
: DocumentWindow (JUCEApplication::getInstance()->getApplicationName(),
LookAndFeel::getDefaultLookAndFeel().findColour (ResizableWindow::backgroundColourId),
DocumentWindow::allButtons)
{
formatManager.addDefaultFormats();
formatManager.addFormat (new InternalPluginFormat());
ScopedPointer<XmlElement> savedAudioState (getAppProperties().getUserSettings()
->getXmlValue ("audioDeviceState"));
deviceManager.initialise (256, 256, savedAudioState, true);
setResizable (true, false);
setResizeLimits (500, 400, 10000, 10000);
centreWithSize (800, 600);
graphHolder = new GraphDocumentComponent (formatManager, deviceManager);
setContentNonOwned (graphHolder, false);
restoreWindowStateFromString (getAppProperties().getUserSettings()->getValue ("mainWindowPos"));
setVisible (true);
InternalPluginFormat internalFormat;
internalFormat.getAllTypes (internalTypes);
ScopedPointer<XmlElement> savedPluginList (getAppProperties().getUserSettings()->getXmlValue ("pluginList"));
if (savedPluginList != nullptr)
knownPluginList.recreateFromXml (*savedPluginList);
pluginSortMethod = (KnownPluginList::SortMethod) getAppProperties().getUserSettings()
->getIntValue ("pluginSortMethod", KnownPluginList::sortByManufacturer);
knownPluginList.addChangeListener (this);
if (auto* filterGraph = graphHolder->graph.get())
filterGraph->addChangeListener (this);
addKeyListener (getCommandManager().getKeyMappings());
Process::setPriority (Process::HighPriority);
#if JUCE_MAC
setMacMainMenu (this);
#else
setMenuBar (this);
#endif
getCommandManager().setFirstCommandTarget (this);
}
MainHostWindow::~MainHostWindow()
{
pluginListWindow = nullptr;
knownPluginList.removeChangeListener (this);
if (auto* filterGraph = graphHolder->graph.get())
filterGraph->removeChangeListener (this);
getAppProperties().getUserSettings()->setValue ("mainWindowPos", getWindowStateAsString());
clearContentComponent();
#if JUCE_MAC
setMacMainMenu (nullptr);
#else
setMenuBar (nullptr);
#endif
graphHolder = nullptr;
}
void MainHostWindow::closeButtonPressed()
{
tryToQuitApplication();
}
struct AsyncQuitRetrier : private Timer
{
AsyncQuitRetrier() { startTimer (500); }
void timerCallback() override
{
stopTimer();
delete this;
if (auto app = JUCEApplicationBase::getInstance())
app->systemRequestedQuit();
}
};
void MainHostWindow::tryToQuitApplication()
{
if (graphHolder->closeAnyOpenPluginWindows())
{
// Really important thing to note here: if the last call just deleted any plugin windows,
// we won't exit immediately - instead we'll use our AsyncQuitRetrier to let the message
// loop run for another brief moment, then try again. This will give any plugins a chance
// to flush any GUI events that may have been in transit before the app forces them to
// be unloaded
new AsyncQuitRetrier();
}
else if (ModalComponentManager::getInstance()->cancelAllModalComponents())
{
new AsyncQuitRetrier();
}
else if (graphHolder == nullptr || graphHolder->graph->saveIfNeededAndUserAgrees() == FileBasedDocument::savedOk)
{
// Some plug-ins do not want [NSApp stop] to be called
// before the plug-ins are not deallocated.
graphHolder->releaseGraph();
JUCEApplication::quit();
}
}
void MainHostWindow::changeListenerCallback (ChangeBroadcaster* changed)
{
if (changed == &knownPluginList)
{
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
ScopedPointer<XmlElement> savedPluginList (knownPluginList.createXml());
if (savedPluginList != nullptr)
{
getAppProperties().getUserSettings()->setValue ("pluginList", savedPluginList);
getAppProperties().saveIfNeeded();
}
}
else if (graphHolder != nullptr && changed == graphHolder->graph)
{
auto title = JUCEApplication::getInstance()->getApplicationName();
auto f = graphHolder->graph->getFile();
if (f.existsAsFile())
title = f.getFileName() + " - " + title;
setName (title);
}
}
StringArray MainHostWindow::getMenuBarNames()
{
StringArray names;
names.add ("File");
names.add ("Plugins");
names.add ("Options");
names.add ("Windows");
return names;
}
PopupMenu MainHostWindow::getMenuForIndex (int topLevelMenuIndex, const String& /*menuName*/)
{
PopupMenu menu;
if (topLevelMenuIndex == 0)
{
// "File" menu
menu.addCommandItem (&getCommandManager(), CommandIDs::newFile);
menu.addCommandItem (&getCommandManager(), CommandIDs::open);
RecentlyOpenedFilesList recentFiles;
recentFiles.restoreFromString (getAppProperties().getUserSettings()
->getValue ("recentFilterGraphFiles"));
PopupMenu recentFilesMenu;
recentFiles.createPopupMenuItems (recentFilesMenu, 100, true, true);
menu.addSubMenu ("Open recent file", recentFilesMenu);
menu.addCommandItem (&getCommandManager(), CommandIDs::save);
menu.addCommandItem (&getCommandManager(), CommandIDs::saveAs);
menu.addSeparator();
menu.addCommandItem (&getCommandManager(), StandardApplicationCommandIDs::quit);
}
else if (topLevelMenuIndex == 1)
{
// "Plugins" menu
PopupMenu pluginsMenu;
addPluginsToMenu (pluginsMenu);
menu.addSubMenu ("Create plugin", pluginsMenu);
menu.addSeparator();
menu.addItem (250, "Delete all plugins");
}
else if (topLevelMenuIndex == 2)
{
// "Options" menu
menu.addCommandItem (&getCommandManager(), 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);
sortTypeMenu.addItem (204, "List plugins based on the directory structure", true, pluginSortMethod == KnownPluginList::sortByFileSystemLocation);
menu.addSubMenu ("Plugin menu type", sortTypeMenu);
menu.addSeparator();
menu.addCommandItem (&getCommandManager(), CommandIDs::showAudioSettings);
menu.addCommandItem (&getCommandManager(), CommandIDs::toggleDoublePrecision);
menu.addSeparator();
menu.addCommandItem (&getCommandManager(), CommandIDs::aboutBox);
}
else if (topLevelMenuIndex == 3)
{
menu.addCommandItem (&getCommandManager(), CommandIDs::allWindowsForward);
}
return menu;
}
void MainHostWindow::menuItemSelected (int menuItemID, int /*topLevelMenuIndex*/)
{
if (menuItemID == 250)
{
if (graphHolder != nullptr)
if (auto* graph = graphHolder->graph.get())
graph->clear();
}
else if (menuItemID >= 100 && menuItemID < 200)
{
RecentlyOpenedFilesList recentFiles;
recentFiles.restoreFromString (getAppProperties().getUserSettings()
->getValue ("recentFilterGraphFiles"));
if (graphHolder != nullptr)
if (auto* graph = graphHolder->graph.get())
if (graph != nullptr && graph->saveIfNeededAndUserAgrees() == FileBasedDocument::savedOk)
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;
else if (menuItemID == 204) pluginSortMethod = KnownPluginList::sortByFileSystemLocation;
getAppProperties().getUserSettings()->setValue ("pluginSortMethod", (int) pluginSortMethod);
menuItemsChanged();
}
else
{
if (auto* desc = getChosenType (menuItemID))
createPlugin (*desc,
{ proportionOfWidth (0.3f + Random::getSystemRandom().nextFloat() * 0.6f),
proportionOfHeight (0.3f + Random::getSystemRandom().nextFloat() * 0.6f) });
}
}
void MainHostWindow::menuBarActivated (bool isActivated)
{
if (isActivated && graphHolder != nullptr)
graphHolder->unfocusKeyboardComponent();
}
void MainHostWindow::createPlugin (const PluginDescription& desc, Point<int> pos)
{
if (graphHolder != nullptr)
graphHolder->createNewPlugin (desc, pos);
}
void MainHostWindow::addPluginsToMenu (PopupMenu& m) const
{
if (graphHolder != nullptr)
{
int i = 0;
for (auto* t : internalTypes)
m.addItem (++i, t->name + " (" + t->pluginFormatName + ")",
graphHolder->graph->getNodeForName (t->name) == nullptr);
}
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];
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::newFile,
CommandIDs::open,
CommandIDs::save,
CommandIDs::saveAs,
CommandIDs::showPluginListEditor,
CommandIDs::showAudioSettings,
CommandIDs::toggleDoublePrecision,
CommandIDs::aboutBox,
CommandIDs::allWindowsForward
};
commands.addArray (ids, numElementsInArray (ids));
}
void MainHostWindow::getCommandInfo (const CommandID commandID, ApplicationCommandInfo& result)
{
const String category ("General");
switch (commandID)
{
case CommandIDs::newFile:
result.setInfo ("New", "Creates a new filter graph file", category, 0);
result.defaultKeypresses.add(KeyPress('n', ModifierKeys::commandModifier, 0));
break;
case CommandIDs::open:
result.setInfo ("Open...", "Opens a filter graph file", category, 0);
result.defaultKeypresses.add (KeyPress ('o', ModifierKeys::commandModifier, 0));
break;
case CommandIDs::save:
result.setInfo ("Save", "Saves the current graph to a file", category, 0);
result.defaultKeypresses.add (KeyPress ('s', ModifierKeys::commandModifier, 0));
break;
case CommandIDs::saveAs:
result.setInfo ("Save As...",
"Saves a copy of the current graph to a file",
category, 0);
result.defaultKeypresses.add (KeyPress ('s', ModifierKeys::shiftModifier | ModifierKeys::commandModifier, 0));
break;
case CommandIDs::showPluginListEditor:
result.setInfo ("Edit the list of available plug-Ins...", String(), category, 0);
result.addDefaultKeypress ('p', ModifierKeys::commandModifier);
break;
case CommandIDs::showAudioSettings:
result.setInfo ("Change the audio device settings", String(), category, 0);
result.addDefaultKeypress ('a', ModifierKeys::commandModifier);
break;
case CommandIDs::toggleDoublePrecision:
updatePrecisionMenuItem (result);
break;
case CommandIDs::aboutBox:
result.setInfo ("About...", String(), category, 0);
break;
case CommandIDs::allWindowsForward:
result.setInfo ("All Windows Forward", "Bring all plug-in windows forward", category, 0);
result.addDefaultKeypress ('w', ModifierKeys::commandModifier);
break;
default:
break;
}
}
bool MainHostWindow::perform (const InvocationInfo& info)
{
switch (info.commandID)
{
case CommandIDs::newFile:
if (graphHolder != nullptr && graphHolder->graph != nullptr && graphHolder->graph->saveIfNeededAndUserAgrees() == FileBasedDocument::savedOk)
graphHolder->graph->newDocument();
break;
case CommandIDs::open:
if (graphHolder != nullptr && graphHolder->graph != nullptr && graphHolder->graph->saveIfNeededAndUserAgrees() == FileBasedDocument::savedOk)
graphHolder->graph->loadFromUserSpecifiedFile (true);
break;
case CommandIDs::save:
if (graphHolder != nullptr && graphHolder->graph != nullptr)
graphHolder->graph->save (true, true);
break;
case CommandIDs::saveAs:
if (graphHolder != nullptr && graphHolder->graph != nullptr)
graphHolder->graph->saveAs (File(), true, true, true);
break;
case CommandIDs::showPluginListEditor:
if (pluginListWindow == nullptr)
pluginListWindow = new PluginListWindow (*this, formatManager);
pluginListWindow->toFront (true);
break;
case CommandIDs::showAudioSettings:
showAudioSettings();
break;
case CommandIDs::toggleDoublePrecision:
if (auto* props = getAppProperties().getUserSettings())
{
bool newIsDoublePrecision = ! isDoublePrecisionProcessing();
props->setValue ("doublePrecisionProcessing", var (newIsDoublePrecision));
{
ApplicationCommandInfo cmdInfo (info.commandID);
updatePrecisionMenuItem (cmdInfo);
menuItemsChanged();
}
if (graphHolder != nullptr)
graphHolder->setDoublePrecision (newIsDoublePrecision);
}
break;
case CommandIDs::aboutBox:
// TODO
break;
case CommandIDs::allWindowsForward:
{
auto& desktop = Desktop::getInstance();
for (int i = 0; i < desktop.getNumComponents(); ++i)
desktop.getComponent (i)->toBehind (this);
break;
}
default:
return false;
}
return true;
}
void MainHostWindow::showAudioSettings()
{
AudioDeviceSelectorComponent audioSettingsComp (deviceManager,
0, 256,
0, 256,
true, true, true, false);
audioSettingsComp.setSize (500, 450);
DialogWindow::LaunchOptions o;
o.content.setNonOwned (&audioSettingsComp);
o.dialogTitle = "Audio Settings";
o.componentToCentreAround = this;
o.dialogBackgroundColour = getLookAndFeel().findColour (ResizableWindow::backgroundColourId);
o.escapeKeyTriggersCloseButton = true;
o.useNativeTitleBar = false;
o.resizable = false;
o.runModal();
ScopedPointer<XmlElement> audioState (deviceManager.createStateXml());
getAppProperties().getUserSettings()->setValue ("audioDeviceState", audioState);
getAppProperties().getUserSettings()->saveIfNeeded();
if (graphHolder != nullptr)
if (graphHolder->graph != nullptr)
graphHolder->graph->graph.removeIllegalConnections();
}
bool MainHostWindow::isInterestedInFileDrag (const StringArray&)
{
return true;
}
void MainHostWindow::fileDragEnter (const StringArray&, int, int)
{
}
void MainHostWindow::fileDragMove (const StringArray&, int, int)
{
}
void MainHostWindow::fileDragExit (const StringArray&)
{
}
void MainHostWindow::filesDropped (const StringArray& files, int x, int y)
{
if (graphHolder != nullptr)
{
if (files.size() == 1 && File (files[0]).hasFileExtension (FilterGraph::getFilenameSuffix()))
{
if (auto* filterGraph = graphHolder->graph.get())
if (filterGraph->saveIfNeededAndUserAgrees() == FileBasedDocument::savedOk)
filterGraph->loadFrom (File (files[0]), true);
}
else
{
OwnedArray<PluginDescription> typesFound;
knownPluginList.scanAndAddDragAndDroppedFiles (formatManager, files, typesFound);
auto pos = graphHolder->getLocalPoint (this, Point<int> (x, y));
for (int i = 0; i < jmin (5, typesFound.size()); ++i)
if (auto* desc = typesFound.getUnchecked(i))
createPlugin (*desc, pos);
}
}
}
bool MainHostWindow::isDoublePrecisionProcessing()
{
if (auto* props = getAppProperties().getUserSettings())
return props->getBoolValue ("doublePrecisionProcessing", false);
return false;
}
void MainHostWindow::updatePrecisionMenuItem (ApplicationCommandInfo& info)
{
info.setInfo ("Double floating point precision rendering", String(), "General", 0);
info.setTicked (isDoublePrecisionProcessing());
}

View file

@ -0,0 +1,109 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#pragma once
#include "FilterGraph.h"
#include "GraphEditorPanel.h"
//==============================================================================
namespace CommandIDs
{
static const int open = 0x30000;
static const int save = 0x30001;
static const int saveAs = 0x30002;
static const int newFile = 0x30003;
static const int showPluginListEditor = 0x30100;
static const int showAudioSettings = 0x30200;
static const int aboutBox = 0x30300;
static const int allWindowsForward = 0x30400;
static const int toggleDoublePrecision = 0x30500;
}
ApplicationCommandManager& getCommandManager();
ApplicationProperties& getAppProperties();
//==============================================================================
class MainHostWindow : public DocumentWindow,
public MenuBarModel,
public ApplicationCommandTarget,
public ChangeListener,
public FileDragAndDropTarget
{
public:
//==============================================================================
MainHostWindow();
~MainHostWindow();
//==============================================================================
void closeButtonPressed() override;
void changeListenerCallback (ChangeBroadcaster*) override;
bool isInterestedInFileDrag (const StringArray& files) override;
void fileDragEnter (const StringArray& files, int, int) override;
void fileDragMove (const StringArray& files, int, int) override;
void fileDragExit (const StringArray& files) override;
void filesDropped (const StringArray& files, int, int) override;
void menuBarActivated (bool isActive) override;
StringArray getMenuBarNames() override;
PopupMenu getMenuForIndex (int topLevelMenuIndex, const String& menuName) override;
void menuItemSelected (int menuItemID, int topLevelMenuIndex) override;
ApplicationCommandTarget* getNextCommandTarget() override;
void getAllCommands (Array<CommandID>&) override;
void getCommandInfo (CommandID, ApplicationCommandInfo&) override;
bool perform (const InvocationInfo&) override;
void tryToQuitApplication();
void createPlugin (const PluginDescription&, Point<int> pos);
void addPluginsToMenu (PopupMenu&) const;
const PluginDescription* getChosenType (int menuID) const;
bool isDoublePrecisionProcessing();
void updatePrecisionMenuItem (ApplicationCommandInfo& info);
ScopedPointer<GraphDocumentComponent> graphHolder;
private:
//==============================================================================
AudioDeviceManager deviceManager;
AudioPluginFormatManager formatManager;
OwnedArray<PluginDescription> internalTypes;
KnownPluginList knownPluginList;
KnownPluginList::SortMethod pluginSortMethod;
class PluginListWindow;
ScopedPointer<PluginListWindow> pluginListWindow;
void showAudioSettings();
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainHostWindow)
};

View file

@ -0,0 +1,201 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#pragma once
#include "FilterIOConfiguration.h"
class FilterGraph;
//==============================================================================
/**
A desktop window containing a plugin's GUI.
*/
class PluginWindow : public DocumentWindow
{
public:
enum class Type
{
normal = 0,
generic,
programs,
audioIO,
numTypes
};
PluginWindow (AudioProcessorGraph::Node* n, Type t, OwnedArray<PluginWindow>& windowList)
: DocumentWindow (n->getProcessor()->getName(),
LookAndFeel::getDefaultLookAndFeel().findColour (ResizableWindow::backgroundColourId),
DocumentWindow::minimiseButton | DocumentWindow::closeButton),
activeWindowList (windowList),
node (n), type (t)
{
setSize (400, 300);
if (auto* ui = createProcessorEditor (*node->getProcessor(), type))
setContentOwned (ui, true);
setTopLeftPosition (node->properties.getWithDefault (getLastXProp (type), Random::getSystemRandom().nextInt (500)),
node->properties.getWithDefault (getLastYProp (type), Random::getSystemRandom().nextInt (500)));
node->properties.set (getOpenProp (type), true);
setVisible (true);
}
~PluginWindow()
{
clearContentComponent();
}
void moved() override
{
node->properties.set (getLastXProp (type), getX());
node->properties.set (getLastYProp (type), getY());
}
void closeButtonPressed() override
{
node->properties.set (getOpenProp (type), false);
activeWindowList.removeObject (this);
}
static String getLastXProp (Type type) { return "uiLastX_" + getTypeName (type); }
static String getLastYProp (Type type) { return "uiLastY_" + getTypeName (type); }
static String getOpenProp (Type type) { return "uiopen_" + getTypeName (type); }
OwnedArray<PluginWindow>& activeWindowList;
const AudioProcessorGraph::Node::Ptr node;
const Type type;
private:
float getDesktopScaleFactor() const override { return 1.0f; }
static AudioProcessorEditor* createProcessorEditor (AudioProcessor& processor, PluginWindow::Type type)
{
if (type == PluginWindow::Type::normal)
{
if (auto* ui = processor.createEditorIfNeeded())
return ui;
type = PluginWindow::Type::generic;
}
if (type == PluginWindow::Type::generic)
return new GenericAudioProcessorEditor (&processor);
if (type == PluginWindow::Type::programs)
return new ProgramAudioProcessorEditor (processor);
if (type == PluginWindow::Type::audioIO)
return new FilterIOConfigurationWindow (processor);
jassertfalse;
return {};
}
static String getTypeName (Type type)
{
switch (type)
{
case Type::normal: return "Normal";
case Type::generic: return "Generic";
case Type::programs: return "Programs";
case Type::audioIO: return "IO";
default: return {};
}
}
//==============================================================================
struct ProgramAudioProcessorEditor : public AudioProcessorEditor
{
ProgramAudioProcessorEditor (AudioProcessor& p) : AudioProcessorEditor (p)
{
setOpaque (true);
addAndMakeVisible (panel);
Array<PropertyComponent*> programs;
auto numPrograms = p.getNumPrograms();
int totalHeight = 0;
for (int i = 0; i < numPrograms; ++i)
{
auto name = p.getProgramName (i).trim();
if (name.isEmpty())
name = "Unnamed";
auto pc = new PropertyComp (name, p);
programs.add (pc);
totalHeight += pc->getPreferredHeight();
}
panel.addProperties (programs);
setSize (400, jlimit (25, 400, totalHeight));
}
void paint (Graphics& g) override
{
g.fillAll (Colours::grey);
}
void resized() override
{
panel.setBounds (getLocalBounds());
}
private:
struct PropertyComp : public PropertyComponent,
private AudioProcessorListener
{
PropertyComp (const String& name, AudioProcessor& p) : PropertyComponent (name), owner (p)
{
owner.addListener (this);
}
~PropertyComp()
{
owner.removeListener (this);
}
void refresh() override {}
void audioProcessorChanged (AudioProcessor*) override {}
void audioProcessorParameterChanged (AudioProcessor*, int, float) override {}
AudioProcessor& owner;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PropertyComp)
};
PropertyPanel panel;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProgramAudioProcessorEditor)
};
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PluginWindow)
};