| @@ -109,6 +109,8 @@ OBJECTS := \ | |||
| $(OBJDIR)/juce_MidiMessageSequence.o \ | |||
| $(OBJDIR)/juce_AudioProcessor.o \ | |||
| $(OBJDIR)/juce_AudioProcessorEditor.o \ | |||
| $(OBJDIR)/juce_AudioProcessorGraph.o \ | |||
| $(OBJDIR)/juce_AudioProcessorPlayer.o \ | |||
| $(OBJDIR)/juce_GenericAudioProcessorEditor.o \ | |||
| $(OBJDIR)/juce_AiffAudioFormat.o \ | |||
| $(OBJDIR)/juce_AudioCDReader.o \ | |||
| @@ -120,6 +122,8 @@ OBJECTS := \ | |||
| $(OBJDIR)/juce_WavAudioFormat.o \ | |||
| $(OBJDIR)/bitbuffer.o \ | |||
| $(OBJDIR)/bitmath.o \ | |||
| $(OBJDIR)/bitreader.o \ | |||
| $(OBJDIR)/bitwriter.o \ | |||
| $(OBJDIR)/cpu.o \ | |||
| $(OBJDIR)/crc.o \ | |||
| $(OBJDIR)/fixed.o \ | |||
| @@ -801,6 +805,16 @@ $(OBJDIR)/juce_AudioProcessorEditor.o: ../../src/juce_appframework/audio/process | |||
| @echo $(notdir $<) | |||
| @$(CXX) $(CXXFLAGS) -o $@ -c $< | |||
| $(OBJDIR)/juce_AudioProcessorGraph.o: ../../src/juce_appframework/audio/processors/juce_AudioProcessorGraph.cpp | |||
| -@$(CMD_MKOBJDIR) | |||
| @echo $(notdir $<) | |||
| @$(CXX) $(CXXFLAGS) -o $@ -c $< | |||
| $(OBJDIR)/juce_AudioProcessorPlayer.o: ../../src/juce_appframework/audio/processors/juce_AudioProcessorPlayer.cpp | |||
| -@$(CMD_MKOBJDIR) | |||
| @echo $(notdir $<) | |||
| @$(CXX) $(CXXFLAGS) -o $@ -c $< | |||
| $(OBJDIR)/juce_GenericAudioProcessorEditor.o: ../../src/juce_appframework/audio/processors/juce_GenericAudioProcessorEditor.cpp | |||
| -@$(CMD_MKOBJDIR) | |||
| @echo $(notdir $<) | |||
| @@ -856,6 +870,16 @@ $(OBJDIR)/bitmath.o: ../../src/juce_appframework/audio/audio_file_formats/flac/l | |||
| @echo $(notdir $<) | |||
| @$(CC) $(CFLAGS) -o $@ -c $< | |||
| $(OBJDIR)/bitreader.o: ../../src/juce_appframework/audio/audio_file_formats/flac/libFLAC/bitreader.c | |||
| -@$(CMD_MKOBJDIR) | |||
| @echo $(notdir $<) | |||
| @$(CC) $(CFLAGS) -o $@ -c $< | |||
| $(OBJDIR)/bitwriter.o: ../../src/juce_appframework/audio/audio_file_formats/flac/libFLAC/bitwriter.c | |||
| -@$(CMD_MKOBJDIR) | |||
| @echo $(notdir $<) | |||
| @$(CC) $(CFLAGS) -o $@ -c $< | |||
| $(OBJDIR)/cpu.o: ../../src/juce_appframework/audio/audio_file_formats/flac/libFLAC/cpu.c | |||
| -@$(CMD_MKOBJDIR) | |||
| @echo $(notdir $<) | |||
| @@ -68,6 +68,10 @@ package.files = { matchfiles ( | |||
| "../../src/juce_appframework/audio/midi/*.h", | |||
| "../../src/juce_appframework/audio/processors/*.cpp", | |||
| "../../src/juce_appframework/audio/processors/*.h", | |||
| "../../src/juce_appframework/audio/plugins/*.cpp", | |||
| "../../src/juce_appframework/audio/plugins/*.h", | |||
| "../../src/juce_appframework/audio/plugins/formats/*.cpp", | |||
| "../../src/juce_appframework/audio/plugins/formats/*.h", | |||
| "../../src/juce_appframework/audio/audio_file_formats/*.cpp", | |||
| "../../src/juce_appframework/audio/audio_file_formats/*.h", | |||
| "../../src/juce_appframework/audio/audio_file_formats/flac/libFLAC/*.c", | |||
| @@ -20,6 +20,22 @@ | |||
| 84099CA10AE52BD000B2A05D /* juce_Synthesiser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84099C9D0AE52BD000B2A05D /* juce_Synthesiser.cpp */; }; | |||
| 84099CA20AE52BD000B2A05D /* juce_Synthesiser.h in Headers */ = {isa = PBXBuildFile; fileRef = 84099C9E0AE52BD000B2A05D /* juce_Synthesiser.h */; }; | |||
| 840F80BC092B399D005E7B4E /* juce.h in Headers */ = {isa = PBXBuildFile; fileRef = 840F80BB092B399D005E7B4E /* juce.h */; }; | |||
| 8416EB750D1999620094A433 /* bitbuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 8416EB650D1999610094A433 /* bitbuffer.c */; }; | |||
| 8416EB760D1999620094A433 /* bitmath.c in Sources */ = {isa = PBXBuildFile; fileRef = 8416EB660D1999610094A433 /* bitmath.c */; }; | |||
| 8416EB770D1999620094A433 /* bitreader.c in Sources */ = {isa = PBXBuildFile; fileRef = 8416EB670D1999610094A433 /* bitreader.c */; }; | |||
| 8416EB780D1999620094A433 /* bitwriter.c in Sources */ = {isa = PBXBuildFile; fileRef = 8416EB680D1999610094A433 /* bitwriter.c */; }; | |||
| 8416EB790D1999620094A433 /* cpu.c in Sources */ = {isa = PBXBuildFile; fileRef = 8416EB690D1999610094A433 /* cpu.c */; }; | |||
| 8416EB7A0D1999620094A433 /* crc.c in Sources */ = {isa = PBXBuildFile; fileRef = 8416EB6A0D1999610094A433 /* crc.c */; }; | |||
| 8416EB7B0D1999620094A433 /* fixed.c in Sources */ = {isa = PBXBuildFile; fileRef = 8416EB6B0D1999610094A433 /* fixed.c */; }; | |||
| 8416EB7C0D1999620094A433 /* float.c in Sources */ = {isa = PBXBuildFile; fileRef = 8416EB6C0D1999610094A433 /* float.c */; }; | |||
| 8416EB7D0D1999620094A433 /* format.c in Sources */ = {isa = PBXBuildFile; fileRef = 8416EB6D0D1999610094A433 /* format.c */; }; | |||
| 8416EB7E0D1999620094A433 /* lpc_flac.c in Sources */ = {isa = PBXBuildFile; fileRef = 8416EB6E0D1999610094A433 /* lpc_flac.c */; }; | |||
| 8416EB7F0D1999620094A433 /* md5.c in Sources */ = {isa = PBXBuildFile; fileRef = 8416EB6F0D1999620094A433 /* md5.c */; }; | |||
| 8416EB800D1999620094A433 /* memory.c in Sources */ = {isa = PBXBuildFile; fileRef = 8416EB700D1999620094A433 /* memory.c */; }; | |||
| 8416EB810D1999620094A433 /* stream_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 8416EB710D1999620094A433 /* stream_decoder.c */; }; | |||
| 8416EB820D1999620094A433 /* stream_encoder_framing.c in Sources */ = {isa = PBXBuildFile; fileRef = 8416EB720D1999620094A433 /* stream_encoder_framing.c */; }; | |||
| 8416EB830D1999620094A433 /* stream_encoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 8416EB730D1999620094A433 /* stream_encoder.c */; }; | |||
| 8416EB840D1999620094A433 /* window_flac.c in Sources */ = {isa = PBXBuildFile; fileRef = 8416EB740D1999620094A433 /* window_flac.c */; }; | |||
| 8417EE530A6E7A280058E04E /* juce_TableHeaderComponent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8417EE4F0A6E7A270058E04E /* juce_TableHeaderComponent.cpp */; }; | |||
| 8417EE540A6E7A280058E04E /* juce_TableHeaderComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 8417EE500A6E7A270058E04E /* juce_TableHeaderComponent.h */; }; | |||
| 8417EE550A6E7A280058E04E /* juce_TableListBox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8417EE510A6E7A280058E04E /* juce_TableListBox.cpp */; }; | |||
| @@ -571,20 +587,6 @@ | |||
| 84F593AE09855679008153BA /* juce_DocumentWindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84F593AC09855679008153BA /* juce_DocumentWindow.cpp */; }; | |||
| 84F593AF09855679008153BA /* juce_DocumentWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = 84F593AD09855679008153BA /* juce_DocumentWindow.h */; }; | |||
| 84F593B109855693008153BA /* juce_LassoComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 84F593B009855693008153BA /* juce_LassoComponent.h */; }; | |||
| 84F690EF0B3444E500ABAE1C /* bitbuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 84F690E10B3444E500ABAE1C /* bitbuffer.c */; }; | |||
| 84F690F00B3444E500ABAE1C /* bitmath.c in Sources */ = {isa = PBXBuildFile; fileRef = 84F690E20B3444E500ABAE1C /* bitmath.c */; }; | |||
| 84F690F10B3444E500ABAE1C /* cpu.c in Sources */ = {isa = PBXBuildFile; fileRef = 84F690E30B3444E500ABAE1C /* cpu.c */; }; | |||
| 84F690F20B3444E500ABAE1C /* crc.c in Sources */ = {isa = PBXBuildFile; fileRef = 84F690E40B3444E500ABAE1C /* crc.c */; }; | |||
| 84F690F30B3444E500ABAE1C /* fixed.c in Sources */ = {isa = PBXBuildFile; fileRef = 84F690E50B3444E500ABAE1C /* fixed.c */; }; | |||
| 84F690F40B3444E500ABAE1C /* float.c in Sources */ = {isa = PBXBuildFile; fileRef = 84F690E60B3444E500ABAE1C /* float.c */; }; | |||
| 84F690F50B3444E500ABAE1C /* format.c in Sources */ = {isa = PBXBuildFile; fileRef = 84F690E70B3444E500ABAE1C /* format.c */; }; | |||
| 84F690F60B3444E500ABAE1C /* lpc_flac.c in Sources */ = {isa = PBXBuildFile; fileRef = 84F690E80B3444E500ABAE1C /* lpc_flac.c */; }; | |||
| 84F690F70B3444E500ABAE1C /* md5.c in Sources */ = {isa = PBXBuildFile; fileRef = 84F690E90B3444E500ABAE1C /* md5.c */; }; | |||
| 84F690F80B3444E500ABAE1C /* memory.c in Sources */ = {isa = PBXBuildFile; fileRef = 84F690EA0B3444E500ABAE1C /* memory.c */; }; | |||
| 84F690F90B3444E500ABAE1C /* stream_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 84F690EB0B3444E500ABAE1C /* stream_decoder.c */; }; | |||
| 84F690FA0B3444E500ABAE1C /* stream_encoder_framing.c in Sources */ = {isa = PBXBuildFile; fileRef = 84F690EC0B3444E500ABAE1C /* stream_encoder_framing.c */; }; | |||
| 84F690FB0B3444E500ABAE1C /* stream_encoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 84F690ED0B3444E500ABAE1C /* stream_encoder.c */; }; | |||
| 84F690FC0B3444E500ABAE1C /* window_flac.c in Sources */ = {isa = PBXBuildFile; fileRef = 84F690EE0B3444E500ABAE1C /* window_flac.c */; }; | |||
| 84F690FF0B3444F800ABAE1C /* bitwise.c in Sources */ = {isa = PBXBuildFile; fileRef = 84F690FD0B3444F800ABAE1C /* bitwise.c */; }; | |||
| 84F691000B3444F800ABAE1C /* framing.c in Sources */ = {isa = PBXBuildFile; fileRef = 84F690FE0B3444F800ABAE1C /* framing.c */; }; | |||
| 84F691170B34453600ABAE1C /* analysis.c in Sources */ = {isa = PBXBuildFile; fileRef = 84F691010B34453600ABAE1C /* analysis.c */; }; | |||
| @@ -672,6 +674,22 @@ | |||
| 84099C9D0AE52BD000B2A05D /* juce_Synthesiser.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = juce_Synthesiser.cpp; sourceTree = "<group>"; }; | |||
| 84099C9E0AE52BD000B2A05D /* juce_Synthesiser.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = juce_Synthesiser.h; sourceTree = "<group>"; }; | |||
| 840F80BB092B399D005E7B4E /* juce.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = juce.h; path = ../../juce.h; sourceTree = SOURCE_ROOT; }; | |||
| 8416EB650D1999610094A433 /* bitbuffer.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = bitbuffer.c; path = flac/libFLAC/bitbuffer.c; sourceTree = "<group>"; }; | |||
| 8416EB660D1999610094A433 /* bitmath.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = bitmath.c; path = flac/libFLAC/bitmath.c; sourceTree = "<group>"; }; | |||
| 8416EB670D1999610094A433 /* bitreader.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = bitreader.c; path = flac/libFLAC/bitreader.c; sourceTree = "<group>"; }; | |||
| 8416EB680D1999610094A433 /* bitwriter.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = bitwriter.c; path = flac/libFLAC/bitwriter.c; sourceTree = "<group>"; }; | |||
| 8416EB690D1999610094A433 /* cpu.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = cpu.c; path = flac/libFLAC/cpu.c; sourceTree = "<group>"; }; | |||
| 8416EB6A0D1999610094A433 /* crc.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = crc.c; path = flac/libFLAC/crc.c; sourceTree = "<group>"; }; | |||
| 8416EB6B0D1999610094A433 /* fixed.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = fixed.c; path = flac/libFLAC/fixed.c; sourceTree = "<group>"; }; | |||
| 8416EB6C0D1999610094A433 /* float.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = float.c; path = flac/libFLAC/float.c; sourceTree = "<group>"; }; | |||
| 8416EB6D0D1999610094A433 /* format.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = format.c; path = flac/libFLAC/format.c; sourceTree = "<group>"; }; | |||
| 8416EB6E0D1999610094A433 /* lpc_flac.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = lpc_flac.c; path = flac/libFLAC/lpc_flac.c; sourceTree = "<group>"; }; | |||
| 8416EB6F0D1999620094A433 /* md5.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = md5.c; path = flac/libFLAC/md5.c; sourceTree = "<group>"; }; | |||
| 8416EB700D1999620094A433 /* memory.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = memory.c; path = flac/libFLAC/memory.c; sourceTree = "<group>"; }; | |||
| 8416EB710D1999620094A433 /* stream_decoder.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = stream_decoder.c; path = flac/libFLAC/stream_decoder.c; sourceTree = "<group>"; }; | |||
| 8416EB720D1999620094A433 /* stream_encoder_framing.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = stream_encoder_framing.c; path = flac/libFLAC/stream_encoder_framing.c; sourceTree = "<group>"; }; | |||
| 8416EB730D1999620094A433 /* stream_encoder.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = stream_encoder.c; path = flac/libFLAC/stream_encoder.c; sourceTree = "<group>"; }; | |||
| 8416EB740D1999620094A433 /* window_flac.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = window_flac.c; path = flac/libFLAC/window_flac.c; sourceTree = "<group>"; }; | |||
| 8417EE4F0A6E7A270058E04E /* juce_TableHeaderComponent.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = juce_TableHeaderComponent.cpp; sourceTree = "<group>"; }; | |||
| 8417EE500A6E7A270058E04E /* juce_TableHeaderComponent.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = juce_TableHeaderComponent.h; sourceTree = "<group>"; }; | |||
| 8417EE510A6E7A280058E04E /* juce_TableListBox.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = juce_TableListBox.cpp; sourceTree = "<group>"; }; | |||
| @@ -1226,20 +1244,6 @@ | |||
| 84F593AC09855679008153BA /* juce_DocumentWindow.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = juce_DocumentWindow.cpp; sourceTree = "<group>"; }; | |||
| 84F593AD09855679008153BA /* juce_DocumentWindow.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = juce_DocumentWindow.h; sourceTree = "<group>"; }; | |||
| 84F593B009855693008153BA /* juce_LassoComponent.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = juce_LassoComponent.h; sourceTree = "<group>"; }; | |||
| 84F690E10B3444E500ABAE1C /* bitbuffer.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = bitbuffer.c; path = flac/libFLAC/bitbuffer.c; sourceTree = "<group>"; }; | |||
| 84F690E20B3444E500ABAE1C /* bitmath.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = bitmath.c; path = flac/libFLAC/bitmath.c; sourceTree = "<group>"; }; | |||
| 84F690E30B3444E500ABAE1C /* cpu.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = cpu.c; path = flac/libFLAC/cpu.c; sourceTree = "<group>"; }; | |||
| 84F690E40B3444E500ABAE1C /* crc.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = crc.c; path = flac/libFLAC/crc.c; sourceTree = "<group>"; }; | |||
| 84F690E50B3444E500ABAE1C /* fixed.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = fixed.c; path = flac/libFLAC/fixed.c; sourceTree = "<group>"; }; | |||
| 84F690E60B3444E500ABAE1C /* float.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = float.c; path = flac/libFLAC/float.c; sourceTree = "<group>"; }; | |||
| 84F690E70B3444E500ABAE1C /* format.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = format.c; path = flac/libFLAC/format.c; sourceTree = "<group>"; }; | |||
| 84F690E80B3444E500ABAE1C /* lpc_flac.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = lpc_flac.c; path = flac/libFLAC/lpc_flac.c; sourceTree = "<group>"; }; | |||
| 84F690E90B3444E500ABAE1C /* md5.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = md5.c; path = flac/libFLAC/md5.c; sourceTree = "<group>"; }; | |||
| 84F690EA0B3444E500ABAE1C /* memory.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = memory.c; path = flac/libFLAC/memory.c; sourceTree = "<group>"; }; | |||
| 84F690EB0B3444E500ABAE1C /* stream_decoder.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = stream_decoder.c; path = flac/libFLAC/stream_decoder.c; sourceTree = "<group>"; }; | |||
| 84F690EC0B3444E500ABAE1C /* stream_encoder_framing.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = stream_encoder_framing.c; path = flac/libFLAC/stream_encoder_framing.c; sourceTree = "<group>"; }; | |||
| 84F690ED0B3444E500ABAE1C /* stream_encoder.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = stream_encoder.c; path = flac/libFLAC/stream_encoder.c; sourceTree = "<group>"; }; | |||
| 84F690EE0B3444E500ABAE1C /* window_flac.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = window_flac.c; path = flac/libFLAC/window_flac.c; sourceTree = "<group>"; }; | |||
| 84F690FD0B3444F800ABAE1C /* bitwise.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = bitwise.c; path = oggvorbis/bitwise.c; sourceTree = "<group>"; }; | |||
| 84F690FE0B3444F800ABAE1C /* framing.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = framing.c; path = oggvorbis/framing.c; sourceTree = "<group>"; }; | |||
| 84F691010B34453600ABAE1C /* analysis.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = analysis.c; path = "oggvorbis/libvorbis-1.1.2/lib/analysis.c"; sourceTree = "<group>"; }; | |||
| @@ -2364,20 +2368,22 @@ | |||
| 84F690DC0B3444A500ABAE1C /* flac */ = { | |||
| isa = PBXGroup; | |||
| children = ( | |||
| 84F690E10B3444E500ABAE1C /* bitbuffer.c */, | |||
| 84F690E20B3444E500ABAE1C /* bitmath.c */, | |||
| 84F690E30B3444E500ABAE1C /* cpu.c */, | |||
| 84F690E40B3444E500ABAE1C /* crc.c */, | |||
| 84F690E50B3444E500ABAE1C /* fixed.c */, | |||
| 84F690E60B3444E500ABAE1C /* float.c */, | |||
| 84F690E70B3444E500ABAE1C /* format.c */, | |||
| 84F690E80B3444E500ABAE1C /* lpc_flac.c */, | |||
| 84F690E90B3444E500ABAE1C /* md5.c */, | |||
| 84F690EA0B3444E500ABAE1C /* memory.c */, | |||
| 84F690EB0B3444E500ABAE1C /* stream_decoder.c */, | |||
| 84F690EC0B3444E500ABAE1C /* stream_encoder_framing.c */, | |||
| 84F690ED0B3444E500ABAE1C /* stream_encoder.c */, | |||
| 84F690EE0B3444E500ABAE1C /* window_flac.c */, | |||
| 8416EB650D1999610094A433 /* bitbuffer.c */, | |||
| 8416EB660D1999610094A433 /* bitmath.c */, | |||
| 8416EB670D1999610094A433 /* bitreader.c */, | |||
| 8416EB680D1999610094A433 /* bitwriter.c */, | |||
| 8416EB690D1999610094A433 /* cpu.c */, | |||
| 8416EB6A0D1999610094A433 /* crc.c */, | |||
| 8416EB6B0D1999610094A433 /* fixed.c */, | |||
| 8416EB6C0D1999610094A433 /* float.c */, | |||
| 8416EB6D0D1999610094A433 /* format.c */, | |||
| 8416EB6E0D1999610094A433 /* lpc_flac.c */, | |||
| 8416EB6F0D1999620094A433 /* md5.c */, | |||
| 8416EB700D1999620094A433 /* memory.c */, | |||
| 8416EB710D1999620094A433 /* stream_decoder.c */, | |||
| 8416EB720D1999620094A433 /* stream_encoder_framing.c */, | |||
| 8416EB730D1999620094A433 /* stream_encoder.c */, | |||
| 8416EB740D1999620094A433 /* window_flac.c */, | |||
| ); | |||
| name = flac; | |||
| sourceTree = "<group>"; | |||
| @@ -3119,20 +3125,6 @@ | |||
| 841E06370AF8CE75005E6FCC /* juce_AudioSampleBuffer.cpp in Sources */, | |||
| 841E06390AF8CE75005E6FCC /* juce_IIRFilter.cpp in Sources */, | |||
| 84F525000B32A8D500597B73 /* juce_ApplicationProperties.cpp in Sources */, | |||
| 84F690EF0B3444E500ABAE1C /* bitbuffer.c in Sources */, | |||
| 84F690F00B3444E500ABAE1C /* bitmath.c in Sources */, | |||
| 84F690F10B3444E500ABAE1C /* cpu.c in Sources */, | |||
| 84F690F20B3444E500ABAE1C /* crc.c in Sources */, | |||
| 84F690F30B3444E500ABAE1C /* fixed.c in Sources */, | |||
| 84F690F40B3444E500ABAE1C /* float.c in Sources */, | |||
| 84F690F50B3444E500ABAE1C /* format.c in Sources */, | |||
| 84F690F60B3444E500ABAE1C /* lpc_flac.c in Sources */, | |||
| 84F690F70B3444E500ABAE1C /* md5.c in Sources */, | |||
| 84F690F80B3444E500ABAE1C /* memory.c in Sources */, | |||
| 84F690F90B3444E500ABAE1C /* stream_decoder.c in Sources */, | |||
| 84F690FA0B3444E500ABAE1C /* stream_encoder_framing.c in Sources */, | |||
| 84F690FB0B3444E500ABAE1C /* stream_encoder.c in Sources */, | |||
| 84F690FC0B3444E500ABAE1C /* window_flac.c in Sources */, | |||
| 84F690FF0B3444F800ABAE1C /* bitwise.c in Sources */, | |||
| 84F691000B3444F800ABAE1C /* framing.c in Sources */, | |||
| 84F691170B34453600ABAE1C /* analysis.c in Sources */, | |||
| @@ -3166,6 +3158,22 @@ | |||
| 84BC4E2A0C8DD38C00FA249B /* juce_AudioProcessor.cpp in Sources */, | |||
| 84BC4E2C0C8DD38C00FA249B /* juce_AudioProcessorEditor.cpp in Sources */, | |||
| 84BC4E2F0C8DD38C00FA249B /* juce_GenericAudioProcessorEditor.cpp in Sources */, | |||
| 8416EB750D1999620094A433 /* bitbuffer.c in Sources */, | |||
| 8416EB760D1999620094A433 /* bitmath.c in Sources */, | |||
| 8416EB770D1999620094A433 /* bitreader.c in Sources */, | |||
| 8416EB780D1999620094A433 /* bitwriter.c in Sources */, | |||
| 8416EB790D1999620094A433 /* cpu.c in Sources */, | |||
| 8416EB7A0D1999620094A433 /* crc.c in Sources */, | |||
| 8416EB7B0D1999620094A433 /* fixed.c in Sources */, | |||
| 8416EB7C0D1999620094A433 /* float.c in Sources */, | |||
| 8416EB7D0D1999620094A433 /* format.c in Sources */, | |||
| 8416EB7E0D1999620094A433 /* lpc_flac.c in Sources */, | |||
| 8416EB7F0D1999620094A433 /* md5.c in Sources */, | |||
| 8416EB800D1999620094A433 /* memory.c in Sources */, | |||
| 8416EB810D1999620094A433 /* stream_decoder.c in Sources */, | |||
| 8416EB820D1999620094A433 /* stream_encoder_framing.c in Sources */, | |||
| 8416EB830D1999620094A433 /* stream_encoder.c in Sources */, | |||
| 8416EB840D1999620094A433 /* window_flac.c in Sources */, | |||
| ); | |||
| runOnlyForDeploymentPostprocessing = 0; | |||
| }; | |||
| @@ -1,13 +1,22 @@ | |||
| ARCHS = ppc i386 | |||
| // For 10.2 compatibility, use these values: | |||
| // For 10.2 (and later) compatibility, use these values: | |||
| GCC_VERSION_ppc = 3.3 | |||
| MACOSX_DEPLOYMENT_TARGET = 10.4 | |||
| MACOSX_DEPLOYMENT_TARGET_ppc = 10.2 | |||
| OTHER_LD_FLAGS_ppc = /Developer/SDKs/MacOSX10.2.8.sdk/usr/lib/gcc/darwin/3.3/libstdc++.a | |||
| SDKROOT_ppc = /Developer/SDKs/MacOSX10.2.8.sdk | |||
| OTHER_LD_FLAGS_ppc = $(DEVELOPER_SDK_DIR)/MacOSX10.2.8.sdk/usr/lib/gcc/darwin/3.3/libstdc++.a | |||
| SDKROOT_ppc = $(DEVELOPER_SDK_DIR)/MacOSX10.2.8.sdk | |||
| // For 10.3 compatibility, use these: | |||
| // For 10.3 (and later) compatibility, use these instead: | |||
| // MACOSX_DEPLOYMENT_TARGET = 10.4 | |||
| // MACOSX_DEPLOYMENT_TARGET_ppc = 10.3 | |||
| // SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk | |||
| // SDKROOT_ppc = /Developer/SDKs/MacOSX10.3.9.sdk | |||
| // SDKROOT = $(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk | |||
| // SDKROOT_ppc = $(DEVELOPER_SDK_DIR)/MacOSX10.3.9.sdk | |||
| // For 10.4 (and later) compatibility, use these instead: | |||
| // MACOSX_DEPLOYMENT_TARGET = 10.4 | |||
| // SDKROOT = $(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk | |||
| // For 10.5 (and later) compatibility, use these instead: | |||
| // MACOSX_DEPLOYMENT_TARGET = 10.5 | |||
| // SDKROOT = $(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk | |||
| @@ -705,11 +705,15 @@ | |||
| Name="flac" | |||
| > | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\audio_file_formats\flac\libFLAC\bitbuffer.c" | |||
| RelativePath="..\..\..\src\juce_appframework\audio\audio_file_formats\flac\libFLAC\bitmath.c" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\audio_file_formats\flac\libFLAC\bitmath.c" | |||
| RelativePath="..\..\..\src\juce_appframework\audio\audio_file_formats\flac\libFLAC\bitreader.c" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\audio_file_formats\flac\libFLAC\bitwriter.c" | |||
| > | |||
| </File> | |||
| <File | |||
| @@ -732,10 +736,6 @@ | |||
| RelativePath="..\..\..\src\juce_appframework\audio\audio_file_formats\flac\libFLAC\format.c" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\audio_file_formats\flac\libFLAC\juce_FlacHeader.h" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\audio_file_formats\flac\libFLAC\lpc_flac.c" | |||
| > | |||
| @@ -1189,10 +1189,26 @@ | |||
| RelativePath="..\..\..\src\juce_appframework\audio\processors\juce_AudioProcessorEditor.h" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\processors\juce_AudioProcessorGraph.cpp" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\processors\juce_AudioProcessorGraph.h" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\processors\juce_AudioProcessorListener.h" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\processors\juce_AudioProcessorPlayer.cpp" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\processors\juce_AudioProcessorPlayer.h" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\processors\juce_GenericAudioProcessorEditor.cpp" | |||
| > | |||
| @@ -1202,6 +1218,94 @@ | |||
| > | |||
| </File> | |||
| </Filter> | |||
| <Filter | |||
| Name="plugins" | |||
| > | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\plugins\juce_AudioPluginFormat.cpp" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\plugins\juce_AudioPluginFormat.h" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\plugins\juce_AudioPluginFormatManager.cpp" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\plugins\juce_AudioPluginFormatManager.h" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\plugins\juce_AudioPluginInstance.cpp" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\plugins\juce_AudioPluginInstance.h" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\plugins\juce_KnownPluginList.cpp" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\plugins\juce_KnownPluginList.h" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\plugins\juce_PluginDescription.cpp" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\plugins\juce_PluginDescription.h" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\plugins\juce_PluginDirectoryScanner.cpp" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\plugins\juce_PluginDirectoryScanner.h" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\plugins\juce_PluginListComponent.cpp" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\plugins\juce_PluginListComponent.h" | |||
| > | |||
| </File> | |||
| <Filter | |||
| Name="formats" | |||
| > | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\plugins\formats\juce_AudioUnitPluginFormat.cpp" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\plugins\formats\juce_AudioUnitPluginFormat.h" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\plugins\formats\juce_DirectXPluginFormat.h" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\plugins\formats\juce_LADSPAPluginFormat.h" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\plugins\formats\juce_VSTPluginFormat.cpp" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\..\src\juce_appframework\audio\plugins\formats\juce_VSTPluginFormat.h" | |||
| > | |||
| </File> | |||
| </Filter> | |||
| </Filter> | |||
| </Filter> | |||
| <Filter | |||
| Name="events" | |||
| @@ -6,12 +6,19 @@ | |||
| ============================================================================== | |||
| Changelist for version 1.46 | |||
| - new class: AudioProcessorGraph: This allows AudioProcessors to be efficiently wired together and run as a graph. I've converted the plugin host demo to now use this instead of its own graph rendering code. | |||
| - new class: AudioProcessorPlayer: This allows an audio i/o device to stream through an AudioProcessor (or an AudioProcessorGraph). | |||
| - AudioProcessor now has a few more pure virtual methods that you'll need to implement: acceptsMidi(), producesMidi() and getName() | |||
| - moved all the audio plugin hosting classes into the main juce tree | |||
| - Mac: the project now requires at least XCode V2.5 | |||
| - new class: ScopedTryLock | |||
| - added AudioUnit support to the audio hosting code | |||
| - any top-level components will now have their parentSizeChanged() method called when the screen res is changed (not on linux yet though..) | |||
| - jucer: added support for ImageButtons | |||
| - audio devices - a few tweaks to the various audio drivers to try to make the best possible guess at the input and output latencies that they introduce | |||
| - updated to include the latest version of Flac (1.2.1) | |||
| - added a parameter to DragAndDropTarget::isInterestedInDragSource(). This ma | |||
| - changed the parameters to AudioIODeviceCallback::audioDeviceAboutToStart(), so that it now just supplies a pointer to the device. If you need to, you can still find out the sample rate and block size by asking the device for them. | |||
| ============================================================================== | |||
| Changelist for version 1.45 | |||
| @@ -214,78 +214,6 @@ | |||
| > | |||
| </File> | |||
| </Filter> | |||
| <Filter | |||
| Name="plugins" | |||
| > | |||
| <File | |||
| RelativePath="..\..\src\plugins\juce_AudioPluginFormat.cpp" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\src\plugins\juce_AudioPluginFormat.h" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\src\plugins\juce_AudioPluginInstance.cpp" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\src\plugins\juce_AudioPluginInstance.h" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\src\plugins\juce_KnownPluginList.cpp" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\src\plugins\juce_KnownPluginList.h" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\src\plugins\juce_PluginDescription.cpp" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\src\plugins\juce_PluginDescription.h" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\src\plugins\juce_PluginDirectoryScanner.cpp" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\src\plugins\juce_PluginDirectoryScanner.h" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\src\plugins\juce_PluginListComponent.cpp" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\src\plugins\juce_PluginListComponent.h" | |||
| > | |||
| </File> | |||
| <Filter | |||
| Name="formats" | |||
| > | |||
| <File | |||
| RelativePath="..\..\src\plugins\formats\juce_AudioUnitPluginFormat.cpp" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\src\plugins\formats\juce_AudioUnitPluginFormat.h" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\src\plugins\formats\juce_VSTPluginFormat.cpp" | |||
| > | |||
| </File> | |||
| <File | |||
| RelativePath="..\..\src\plugins\formats\juce_VSTPluginFormat.h" | |||
| > | |||
| </File> | |||
| </Filter> | |||
| </Filter> | |||
| </Filter> | |||
| <Filter | |||
| Name="Resource Files" | |||
| @@ -67,6 +67,7 @@ public: | |||
| AudioPluginFormatManager::getInstance()->addFormat (new InternalPluginFormat()); | |||
| mainWindow = new MainHostWindow(); | |||
| //mainWindow->setUsingNativeTitleBar (true); | |||
| commandManager->registerAllCommandsForTarget (this); | |||
| commandManager->registerAllCommandsForTarget (mainWindow); | |||
| @@ -32,6 +32,7 @@ | |||
| #include "../../../../juce.h" | |||
| #include "FilterGraph.h" | |||
| #include "InternalFilters.h" | |||
| #include "GraphEditorPanel.h" | |||
| //============================================================================== | |||
| @@ -55,264 +56,185 @@ FilterConnection::~FilterConnection() | |||
| //============================================================================== | |||
| class PluginWindow : public DocumentWindow | |||
| { | |||
| public: | |||
| PluginWindow (Component* const uiComp, | |||
| FilterInGraph& owner_) | |||
| : DocumentWindow (uiComp->getName(), Colours::lightblue, | |||
| DocumentWindow::minimiseButton | DocumentWindow::closeButton), | |||
| owner (owner_) | |||
| { | |||
| setSize (400, 300); | |||
| setContentComponent (uiComp, true, true); | |||
| setTopLeftPosition (owner.lastX, owner.lastY); | |||
| setVisible (true); | |||
| } | |||
| ~PluginWindow() | |||
| { | |||
| if (owner.activeGenericUI == this) | |||
| owner.activeGenericUI = 0; | |||
| else | |||
| owner.activeUI = 0; | |||
| const int FilterGraph::midiChannelNumber = 0x1000; | |||
| setContentComponent (0); | |||
| } | |||
| FilterGraph::FilterGraph() | |||
| : FileBasedDocument (filenameSuffix, | |||
| filenameWildcard, | |||
| "Load a filter graph", | |||
| "Save a filter graph"), | |||
| lastUID (0) | |||
| { | |||
| InternalPluginFormat internalFormat; | |||
| void moved() | |||
| { | |||
| owner.lastX = getX(); | |||
| owner.lastY = getY(); | |||
| } | |||
| addFilter (internalFormat.getDescriptionFor (InternalPluginFormat::audioInputFilter), | |||
| 0.5f, 0.1f); | |||
| void closeButtonPressed() | |||
| { | |||
| delete this; | |||
| } | |||
| addFilter (internalFormat.getDescriptionFor (InternalPluginFormat::midiInputFilter), | |||
| 0.25f, 0.1f); | |||
| private: | |||
| FilterInGraph& owner; | |||
| }; | |||
| addFilter (internalFormat.getDescriptionFor (InternalPluginFormat::audioOutputFilter), | |||
| 0.5f, 0.9f); | |||
| setChangedFlag (false); | |||
| } | |||
| //============================================================================== | |||
| FilterInGraph::FilterInGraph (FilterGraph& owner_, AudioPluginInstance* const filter_) | |||
| : owner (owner_), | |||
| filter (filter_), | |||
| uid (0), | |||
| processedAudio (1, 1), | |||
| activeUI (0), | |||
| activeGenericUI (0) | |||
| FilterGraph::~FilterGraph() | |||
| { | |||
| lastX = 100 + Random::getSystemRandom().nextInt (400); | |||
| lastY = 100 + Random::getSystemRandom().nextInt (400); | |||
| graph.clear(); | |||
| } | |||
| FilterInGraph::~FilterInGraph() | |||
| uint32 FilterGraph::getNextUID() throw() | |||
| { | |||
| delete activeGenericUI; | |||
| delete activeUI; | |||
| delete filter; | |||
| return ++lastUID; | |||
| } | |||
| void FilterInGraph::setPosition (double newX, double newY) throw() | |||
| //============================================================================== | |||
| int FilterGraph::getNumFilters() const throw() | |||
| { | |||
| x = jlimit (0.0, 1.0, newX); | |||
| y = jlimit (0.0, 1.0, newY); | |||
| return graph.getNumNodes(); | |||
| } | |||
| void FilterInGraph::showUI (bool useGenericUI) | |||
| const AudioProcessorGraph::Node::Ptr FilterGraph::getNode (const int index) const throw() | |||
| { | |||
| if (! useGenericUI) | |||
| { | |||
| if (activeUI == 0) | |||
| { | |||
| Component* ui = filter->createEditorIfNeeded(); | |||
| if (ui == 0) | |||
| return showUI (true); | |||
| ui->setName (filter->getName()); | |||
| activeUI = new PluginWindow (ui, *this); | |||
| } | |||
| if (activeUI != 0) | |||
| activeUI->toFront (true); | |||
| } | |||
| else | |||
| { | |||
| if (activeGenericUI == 0) | |||
| { | |||
| Component* ui = new GenericAudioProcessorEditor (filter); | |||
| ui->setName (filter->getName()); | |||
| activeGenericUI = new PluginWindow (ui, *this); | |||
| } | |||
| if (activeGenericUI != 0) | |||
| activeGenericUI->toFront (true); | |||
| } | |||
| return graph.getNode (index); | |||
| } | |||
| void FilterInGraph::prepareBuffers (int blockSize) | |||
| const AudioProcessorGraph::Node::Ptr FilterGraph::getNodeForId (const uint32 uid) const throw() | |||
| { | |||
| processedAudio.setSize (jmax (1, filter->getNumInputChannels(), filter->getNumOutputChannels()), blockSize); | |||
| processedAudio.clear(); | |||
| processedMidi.clear(); | |||
| return graph.getNodeForId (uid); | |||
| } | |||
| void FilterInGraph::renderBlock (int numSamples, | |||
| const ReferenceCountedArray <FilterInGraph>& filters, | |||
| const OwnedArray <FilterConnection>& connections) | |||
| void FilterGraph::addFilter (const PluginDescription* desc, double x, double y) | |||
| { | |||
| processedAudio.setSize (jmax (1, filter->getNumInputChannels(), filter->getNumOutputChannels()), numSamples); | |||
| if (desc != 0) | |||
| { | |||
| String errorMessage; | |||
| // this isn't particularly efficient - could do with some optimising here | |||
| processedAudio.clear(); | |||
| processedMidi.clear(); | |||
| AudioPluginInstance* instance | |||
| = AudioPluginFormatManager::getInstance()->createPluginInstance (*desc, errorMessage); | |||
| for (int i = connections.size(); --i >= 0;) | |||
| { | |||
| const FilterConnection* const fc = connections.getUnchecked(i); | |||
| AudioProcessorGraph::Node* node = 0; | |||
| if (instance != 0) | |||
| node = graph.addNode (instance); | |||
| if (fc->destFilterID == uid) | |||
| if (node != 0) | |||
| { | |||
| node->properties.setValue ("x", x); | |||
| node->properties.setValue ("y", y); | |||
| changed(); | |||
| } | |||
| else | |||
| { | |||
| for (int j = filters.size(); --j >= 0;) | |||
| { | |||
| const FilterInGraph* const input = filters.getUnchecked(j); | |||
| if (filters.getUnchecked(j)->uid == fc->sourceFilterID) | |||
| { | |||
| if (fc->sourceChannel == FilterGraph::midiChannelNumber) | |||
| { | |||
| processedMidi.addEvents (input->processedMidi, 0, numSamples, 0); | |||
| } | |||
| else | |||
| { | |||
| if (fc->destChannel < filter->getNumInputChannels() | |||
| && fc->sourceChannel < input->filter->getNumOutputChannels()) | |||
| { | |||
| processedAudio.addFrom (fc->destChannel, 0, input->processedAudio, | |||
| fc->sourceChannel, 0, numSamples); | |||
| } | |||
| } | |||
| break; | |||
| } | |||
| } | |||
| AlertWindow::showMessageBox (AlertWindow::WarningIcon, | |||
| TRANS("Couldn't create filter"), | |||
| errorMessage); | |||
| } | |||
| } | |||
| filter->processBlock (processedAudio, processedMidi); | |||
| } | |||
| XmlElement* FilterInGraph::createXml() const | |||
| void FilterGraph::removeFilter (const uint32 id) | |||
| { | |||
| XmlElement* e = new XmlElement ("FILTER"); | |||
| e->setAttribute (T("uid"), (int) uid); | |||
| e->setAttribute (T("x"), x); | |||
| e->setAttribute (T("y"), y); | |||
| e->setAttribute (T("uiLastX"), lastX); | |||
| e->setAttribute (T("uiLastY"), lastY); | |||
| PluginDescription pd; | |||
| pd.fillInFromInstance (*filter); | |||
| e->addChildElement (pd.createXml()); | |||
| XmlElement* state = new XmlElement ("STATE"); | |||
| MemoryBlock m; | |||
| filter->getStateInformation (m); | |||
| state->addTextElement (m.toBase64Encoding()); | |||
| e->addChildElement (state); | |||
| PluginWindow::closeCurrentlyOpenWindowsFor (id); | |||
| return e; | |||
| if (graph.removeNode (id)) | |||
| changed(); | |||
| } | |||
| FilterInGraph* FilterInGraph::createForDescription (FilterGraph& owner, | |||
| const PluginDescription& desc, | |||
| String& errorMessage) | |||
| void FilterGraph::disconnectFilter (const uint32 id) | |||
| { | |||
| AudioPluginInstance* instance = desc.createInstance (errorMessage); | |||
| if (instance != 0) | |||
| return new FilterInGraph (owner, instance); | |||
| if (graph.disconnectNode (id)) | |||
| changed(); | |||
| } | |||
| return 0; | |||
| void FilterGraph::removeIllegalConnections() | |||
| { | |||
| if (graph.removeIllegalConnections()) | |||
| changed(); | |||
| } | |||
| FilterInGraph* FilterInGraph::createFromXml (FilterGraph& owner, const XmlElement& xml) | |||
| void FilterGraph::setNodePosition (const int nodeId, double x, double y) | |||
| { | |||
| PluginDescription pd; | |||
| const AudioProcessorGraph::Node::Ptr n (graph.getNodeForId (nodeId)); | |||
| forEachXmlChildElement (xml, e) | |||
| if (n != 0) | |||
| { | |||
| if (pd.loadFromXml (*e)) | |||
| break; | |||
| n->properties.setValue ("x", jlimit (0.0, 1.0, x)); | |||
| n->properties.setValue ("y", jlimit (0.0, 1.0, y)); | |||
| } | |||
| } | |||
| String errorMessage; | |||
| FilterInGraph* const c = createForDescription (owner, pd, errorMessage); | |||
| if (c == 0) | |||
| return 0; | |||
| void FilterGraph::getNodePosition (const int nodeId, double& x, double& y) const | |||
| { | |||
| x = y = 0; | |||
| const XmlElement* const state = xml.getChildByName (T("STATE")); | |||
| const AudioProcessorGraph::Node::Ptr n (graph.getNodeForId (nodeId)); | |||
| if (state != 0) | |||
| if (n != 0) | |||
| { | |||
| MemoryBlock m; | |||
| m.fromBase64Encoding (state->getAllSubText()); | |||
| c->filter->setStateInformation (m.getData(), m.getSize()); | |||
| x = n->properties.getDoubleValue ("x"); | |||
| y = n->properties.getDoubleValue ("y"); | |||
| } | |||
| } | |||
| c->uid = xml.getIntAttribute (T("uid")); | |||
| c->x = xml.getDoubleAttribute (T("x")); | |||
| c->y = xml.getDoubleAttribute (T("y")); | |||
| c->lastX = xml.getIntAttribute (T("uiLastX"), c->lastX); | |||
| c->lastY = xml.getIntAttribute (T("uiLastY"), c->lastY); | |||
| return c; | |||
| //============================================================================== | |||
| int FilterGraph::getNumConnections() const throw() | |||
| { | |||
| return graph.getNumConnections(); | |||
| } | |||
| const AudioProcessorGraph::Connection* FilterGraph::getConnection (const int index) const throw() | |||
| { | |||
| return graph.getConnection (index); | |||
| } | |||
| //============================================================================== | |||
| const int FilterGraph::midiChannelNumber = 0x1000; | |||
| const AudioProcessorGraph::Connection* FilterGraph::getConnectionBetween (uint32 sourceFilterUID, int sourceFilterChannel, | |||
| uint32 destFilterUID, int destFilterChannel) const throw() | |||
| { | |||
| return graph.getConnectionBetween (sourceFilterUID, sourceFilterChannel, | |||
| destFilterUID, destFilterChannel); | |||
| } | |||
| FilterGraph::FilterGraph() | |||
| : FileBasedDocument (filenameSuffix, | |||
| filenameWildcard, | |||
| "Load a filter graph", | |||
| "Save a filter graph"), | |||
| lastUID (0) | |||
| bool FilterGraph::canConnect (uint32 sourceFilterUID, int sourceFilterChannel, | |||
| uint32 destFilterUID, int destFilterChannel) const throw() | |||
| { | |||
| InternalPluginFormat internalFormat; | |||
| return graph.canConnect (sourceFilterUID, sourceFilterChannel, | |||
| destFilterUID, destFilterChannel); | |||
| } | |||
| addFilter (internalFormat.getDescriptionFor (InternalPluginFormat::audioInputFilter), | |||
| 0.5f, 0.1f); | |||
| bool FilterGraph::addConnection (uint32 sourceFilterUID, int sourceFilterChannel, | |||
| uint32 destFilterUID, int destFilterChannel) | |||
| { | |||
| const bool result = graph.addConnection (sourceFilterUID, sourceFilterChannel, | |||
| destFilterUID, destFilterChannel); | |||
| addFilter (internalFormat.getDescriptionFor (InternalPluginFormat::midiInputFilter), | |||
| 0.25f, 0.1f); | |||
| if (result) | |||
| changed(); | |||
| addFilter (internalFormat.getDescriptionFor (InternalPluginFormat::audioOutputFilter), | |||
| 0.5f, 0.9f); | |||
| return result; | |||
| } | |||
| setChangedFlag (false); | |||
| void FilterGraph::removeConnection (const int index) | |||
| { | |||
| graph.removeConnection (index); | |||
| changed(); | |||
| } | |||
| FilterGraph::~FilterGraph() | |||
| void FilterGraph::removeConnection (uint32 sourceFilterUID, int sourceFilterChannel, | |||
| uint32 destFilterUID, int destFilterChannel) | |||
| { | |||
| clear(); | |||
| if (graph.removeConnection (sourceFilterUID, sourceFilterChannel, | |||
| destFilterUID, destFilterChannel)) | |||
| changed(); | |||
| } | |||
| uint32 FilterGraph::getNextUID() throw() | |||
| void FilterGraph::clear() | |||
| { | |||
| return ++lastUID; | |||
| PluginWindow::closeAllCurrentlyOpenWindows(); | |||
| graph.clear(); | |||
| changed(); | |||
| } | |||
| //============================================================================== | |||
| @@ -376,224 +298,78 @@ void FilterGraph::setLastDocumentOpened (const File& file) | |||
| } | |||
| //============================================================================== | |||
| FilterInGraph* FilterGraph::getFilterForUID (const uint32 uid) const throw() | |||
| { | |||
| for (int i = filters.size(); --i >= 0;) | |||
| if (filters.getUnchecked(i)->uid == uid) | |||
| return filters.getUnchecked(i); | |||
| return 0; | |||
| } | |||
| void FilterGraph::addFilter (const FilterInGraph::Ptr& newFilter) | |||
| static XmlElement* createNodeXml (AudioProcessorGraph::Node* const node) throw() | |||
| { | |||
| if (newFilter->uid == 0) | |||
| newFilter->uid = getNextUID(); | |||
| else if (newFilter->uid > lastUID) | |||
| lastUID = newFilter->uid; | |||
| AudioPluginInstance* plugin = dynamic_cast <AudioPluginInstance*> (node->processor); | |||
| filters.add (newFilter); | |||
| changed(); | |||
| } | |||
| void FilterGraph::addFilter (const PluginDescription* desc, double x, double y) | |||
| { | |||
| if (desc != 0) | |||
| if (plugin == 0) | |||
| { | |||
| String errorMessage; | |||
| FilterInGraph* cf = FilterInGraph::createForDescription (*this, *desc, errorMessage); | |||
| if (cf != 0) | |||
| { | |||
| cf->setPosition (x, y); | |||
| addFilter (cf); | |||
| } | |||
| else | |||
| { | |||
| AlertWindow::showMessageBox (AlertWindow::WarningIcon, | |||
| TRANS("Couldn't create filter"), | |||
| errorMessage); | |||
| } | |||
| } | |||
| } | |||
| void FilterGraph::removeFilter (const uint32 uid) | |||
| { | |||
| disconnectFilter (uid); | |||
| for (int i = filters.size(); --i >= 0;) | |||
| { | |||
| if (filters.getUnchecked(i)->uid == uid) | |||
| { | |||
| filters.remove (i); | |||
| changed(); | |||
| } | |||
| jassertfalse | |||
| return 0; | |||
| } | |||
| } | |||
| void FilterGraph::disconnectFilter (const uint32 uid) | |||
| { | |||
| for (int i = connections.size(); --i >= 0;) | |||
| { | |||
| const FilterConnection* const fc = connections.getUnchecked(i); | |||
| if (fc->sourceFilterID == uid | |||
| || fc->destFilterID == uid) | |||
| { | |||
| removeConnection (i); | |||
| } | |||
| } | |||
| } | |||
| XmlElement* e = new XmlElement ("FILTER"); | |||
| e->setAttribute (T("uid"), (int) node->id); | |||
| e->setAttribute (T("x"), node->properties.getDoubleValue("x")); | |||
| e->setAttribute (T("y"), node->properties.getDoubleValue("y")); | |||
| e->setAttribute (T("uiLastX"), node->properties.getIntValue("uiLastX")); | |||
| e->setAttribute (T("uiLastY"), node->properties.getIntValue("uiLastY")); | |||
| bool FilterGraph::isAnInputTo (const uint32 possibleInput, const uint32 possibleDestination, int recursionCheck) const throw() | |||
| { | |||
| if (recursionCheck > 0) | |||
| { | |||
| for (int i = 0; i < connections.size(); ++i) | |||
| { | |||
| if (connections.getUnchecked(i)->destFilterID == possibleDestination | |||
| && (connections.getUnchecked(i)->sourceFilterID == possibleInput | |||
| || isAnInputTo (possibleInput, connections.getUnchecked(i)->sourceFilterID, recursionCheck - 1))) | |||
| return true; | |||
| } | |||
| } | |||
| PluginDescription pd; | |||
| return false; | |||
| } | |||
| plugin->fillInPluginDescription (pd); | |||
| bool FilterGraph::isAnInputTo (const uint32 possibleInput, const uint32 possibleDestination) const throw() | |||
| { | |||
| return isAnInputTo (possibleInput, possibleDestination, filters.size() + 1); | |||
| } | |||
| e->addChildElement (pd.createXml()); | |||
| const FilterConnection* FilterGraph::getConnectionBetween (uint32 sourceFilterUID, int sourceFilterChannel, | |||
| uint32 destFilterUID, int destFilterChannel) const throw() | |||
| { | |||
| for (int i = connections.size(); --i >= 0;) | |||
| { | |||
| FilterConnection* const fc = connections.getUnchecked(i); | |||
| XmlElement* state = new XmlElement ("STATE"); | |||
| if (fc->sourceFilterID == sourceFilterUID | |||
| && fc->sourceChannel == sourceFilterChannel | |||
| && fc->destFilterID == destFilterUID | |||
| && fc->destChannel == destFilterChannel) | |||
| { | |||
| return fc; | |||
| } | |||
| } | |||
| MemoryBlock m; | |||
| node->processor->getStateInformation (m); | |||
| state->addTextElement (m.toBase64Encoding()); | |||
| e->addChildElement (state); | |||
| return 0; | |||
| return e; | |||
| } | |||
| bool FilterGraph::canConnect (uint32 sourceFilterUID, int sourceFilterChannel, | |||
| uint32 destFilterUID, int destFilterChannel) const throw() | |||
| void FilterGraph::createNodeFromXml (const XmlElement& xml) | |||
| { | |||
| if (sourceFilterChannel < 0 | |||
| || destFilterChannel < 0 | |||
| || sourceFilterUID == destFilterUID | |||
| || (destFilterChannel == midiChannelNumber) != (sourceFilterChannel == midiChannelNumber)) | |||
| return false; | |||
| const FilterInGraph* const source = getFilterForUID (sourceFilterUID); | |||
| if (source == 0 | |||
| || (sourceFilterChannel != midiChannelNumber && (sourceFilterChannel < 0 || sourceFilterChannel >= source->filter->getNumOutputChannels())) | |||
| || (sourceFilterChannel == midiChannelNumber && ! source->filter->producesMidi())) | |||
| return false; | |||
| const FilterInGraph* const dest = getFilterForUID (destFilterUID); | |||
| if (dest == 0 | |||
| || (destFilterChannel != midiChannelNumber && (destFilterChannel < 0 || destFilterChannel >= dest->filter->getNumInputChannels())) | |||
| || (destFilterChannel == midiChannelNumber && ! dest->filter->acceptsMidi())) | |||
| return false; | |||
| if (getConnectionBetween (sourceFilterUID, sourceFilterChannel, destFilterUID, destFilterChannel) != 0) | |||
| return false; | |||
| return true; | |||
| } | |||
| PluginDescription pd; | |||
| bool FilterGraph::addConnection (uint32 sourceFilterUID, int sourceChannel, | |||
| uint32 destFilterUID, int destChannel) | |||
| { | |||
| if (canConnect (sourceFilterUID, sourceChannel, destFilterUID, destChannel)) | |||
| forEachXmlChildElement (xml, e) | |||
| { | |||
| FilterConnection* const conn = new FilterConnection (*this); | |||
| conn->sourceFilterID = sourceFilterUID; | |||
| conn->sourceChannel = sourceChannel; | |||
| conn->destFilterID = destFilterUID; | |||
| conn->destChannel = destChannel; | |||
| connections.add (conn); | |||
| changed(); | |||
| return true; | |||
| if (pd.loadFromXml (*e)) | |||
| break; | |||
| } | |||
| return false; | |||
| } | |||
| String errorMessage; | |||
| void FilterGraph::removeConnection (const int index) | |||
| { | |||
| if (connections [index] != 0) | |||
| { | |||
| connections.remove (index); | |||
| changed(); | |||
| } | |||
| } | |||
| AudioPluginInstance* instance | |||
| = AudioPluginFormatManager::getInstance()->createPluginInstance (pd, errorMessage); | |||
| void FilterGraph::removeIllegalConnections() | |||
| { | |||
| for (int i = connections.size(); --i >= 0;) | |||
| if (instance == 0) | |||
| { | |||
| const FilterConnection* const fc = connections.getUnchecked(i); | |||
| bool ok = true; | |||
| const FilterInGraph* const source = getFilterForUID (fc->sourceFilterID); | |||
| if (source == 0 | |||
| || (fc->sourceChannel != midiChannelNumber && (fc->sourceChannel < 0 || fc->sourceChannel >= source->filter->getNumOutputChannels())) | |||
| || (fc->sourceChannel == midiChannelNumber && ! source->filter->producesMidi())) | |||
| ok = false; | |||
| const FilterInGraph* const dest = getFilterForUID (fc->destFilterID); | |||
| // xxx handle ins + outs | |||
| } | |||
| if (dest == 0 | |||
| || (fc->destChannel != midiChannelNumber && (fc->destChannel < 0 || fc->destChannel >= dest->filter->getNumInputChannels())) | |||
| || (fc->destChannel == midiChannelNumber && ! dest->filter->acceptsMidi())) | |||
| ok = false; | |||
| if (instance == 0) | |||
| return; | |||
| AudioProcessorGraph::Node::Ptr node (graph.addNode (instance, xml.getIntAttribute (T("uid")))); | |||
| if (! ok) | |||
| removeConnection (i); | |||
| } | |||
| } | |||
| const XmlElement* const state = xml.getChildByName (T("STATE")); | |||
| void FilterGraph::removeConnection (uint32 sourceFilterUID, int sourceFilterChannel, | |||
| uint32 destFilterUID, int destFilterChannel) | |||
| { | |||
| for (int i = connections.size(); --i >= 0;) | |||
| if (state != 0) | |||
| { | |||
| const FilterConnection* const fc = connections.getUnchecked(i); | |||
| MemoryBlock m; | |||
| m.fromBase64Encoding (state->getAllSubText()); | |||
| if (fc->sourceFilterID == sourceFilterUID | |||
| && fc->sourceChannel == sourceFilterChannel | |||
| && fc->destFilterID == destFilterUID | |||
| && fc->destChannel == destFilterChannel) | |||
| { | |||
| removeConnection (i); | |||
| } | |||
| node->processor->setStateInformation (m.getData(), m.getSize()); | |||
| } | |||
| } | |||
| void FilterGraph::clear() | |||
| { | |||
| connections.clear(); | |||
| filters.clear(); | |||
| changed(); | |||
| node->properties.setValue ("x", xml.getDoubleAttribute (T("x"))); | |||
| node->properties.setValue ("y", xml.getDoubleAttribute (T("y"))); | |||
| node->properties.setValue ("uiLastX", xml.getIntAttribute (T("uiLastX"))); | |||
| node->properties.setValue ("uiLastY", xml.getIntAttribute (T("uiLastY"))); | |||
| } | |||
| XmlElement* FilterGraph::createXml() const | |||
| @@ -601,19 +377,21 @@ XmlElement* FilterGraph::createXml() const | |||
| XmlElement* xml = new XmlElement ("FILTERGRAPH"); | |||
| int i; | |||
| for (i = 0; i < filters.size(); ++i) | |||
| xml->addChildElement (filters.getUnchecked(i)->createXml()); | |||
| for (i = 0; i < graph.getNumNodes(); ++i) | |||
| { | |||
| xml->addChildElement (createNodeXml (graph.getNode (i))); | |||
| } | |||
| for (i = 0; i < connections.size(); ++i) | |||
| for (i = 0; i < graph.getNumConnections(); ++i) | |||
| { | |||
| const FilterConnection* const fc = connections.getUnchecked(i); | |||
| const AudioProcessorGraph::Connection* const fc = graph.getConnection(i); | |||
| XmlElement* e = new XmlElement ("CONNECTION"); | |||
| e->setAttribute (T("srcFilter"), (int) fc->sourceFilterID); | |||
| e->setAttribute (T("srcChannel"), fc->sourceChannel); | |||
| e->setAttribute (T("dstFilter"), (int) fc->destFilterID); | |||
| e->setAttribute (T("dstChannel"), fc->destChannel); | |||
| e->setAttribute (T("srcFilter"), (int) fc->sourceNodeId); | |||
| e->setAttribute (T("srcChannel"), fc->sourceChannelIndex); | |||
| e->setAttribute (T("dstFilter"), (int) fc->destNodeId); | |||
| e->setAttribute (T("dstChannel"), fc->destChannelIndex); | |||
| xml->addChildElement (e); | |||
| } | |||
| @@ -627,10 +405,8 @@ void FilterGraph::restoreFromXml (const XmlElement& xml) | |||
| forEachXmlChildElementWithTagName (xml, e, T("FILTER")) | |||
| { | |||
| FilterInGraph* f = FilterInGraph::createFromXml (*this, *e); | |||
| if (f != 0) | |||
| addFilter (f); | |||
| createNodeFromXml (*e); | |||
| changed(); | |||
| } | |||
| forEachXmlChildElementWithTagName (xml, e, T("CONNECTION")) | |||
| @@ -641,171 +417,5 @@ void FilterGraph::restoreFromXml (const XmlElement& xml) | |||
| e->getIntAttribute (T("dstChannel"))); | |||
| } | |||
| removeIllegalConnections(); | |||
| } | |||
| //============================================================================== | |||
| FilterGraphPlayer::FilterGraphPlayer (FilterGraph& graph_) | |||
| : graph (graph_), | |||
| sampleRate (44100.0), | |||
| blockSize (512), | |||
| deviceManager (0), | |||
| inputChannelData (0), | |||
| totalNumInputChannels (0), | |||
| outputChannelData (0), | |||
| totalNumOutputChannels (0) | |||
| { | |||
| setAudioDeviceManager (0); | |||
| keyState.addListener (&messageCollector); | |||
| graph.addChangeListener (this); | |||
| } | |||
| FilterGraphPlayer::~FilterGraphPlayer() | |||
| { | |||
| graph.removeChangeListener (this); | |||
| keyState.removeListener (&messageCollector); | |||
| } | |||
| void FilterGraphPlayer::setAudioDeviceManager (AudioDeviceManager* dm) | |||
| { | |||
| if (deviceManager != 0) | |||
| { | |||
| deviceManager->removeMidiInputCallback (this); | |||
| deviceManager->setAudioCallback (0); | |||
| } | |||
| deviceManager = dm; | |||
| if (dm != 0) | |||
| { | |||
| dm->addMidiInputCallback (String::empty, this); | |||
| dm->setAudioCallback (this); | |||
| } | |||
| } | |||
| int FilterGraphPlayer::compareElements (FilterInGraph* const first, FilterInGraph* const second) throw() | |||
| { | |||
| const bool firstIsInputToSecond = first->owner.isAnInputTo (first->uid, second->uid); | |||
| const bool secondInInputToFirst = first->owner.isAnInputTo (second->uid, first->uid); | |||
| if (firstIsInputToSecond == secondInInputToFirst) | |||
| return 0; | |||
| return firstIsInputToSecond ? -1 : 1; | |||
| } | |||
| void FilterGraphPlayer::update() | |||
| { | |||
| ReferenceCountedArray <FilterInGraph> filtersBeingRemoved (filters); | |||
| ReferenceCountedArray <FilterInGraph> newFilters (graph.filters); | |||
| int i; | |||
| for (i = newFilters.size(); --i >= 0;) | |||
| if (filters.contains (newFilters.getUnchecked(i))) | |||
| newFilters.remove (i); | |||
| for (i = filtersBeingRemoved.size(); --i >= 0;) | |||
| if (graph.filters.contains (filtersBeingRemoved.getUnchecked(i))) | |||
| filtersBeingRemoved.remove (i); | |||
| // prepare any new filters for use.. | |||
| for (i = 0; i < newFilters.size(); ++i) | |||
| newFilters.getUnchecked(i)->filter->prepareToPlay (sampleRate, blockSize); | |||
| ReferenceCountedArray <FilterInGraph> sortedFilters (graph.filters); | |||
| sortedFilters.sort (*this, true); | |||
| for (i = sortedFilters.size(); --i >= 0;) | |||
| { | |||
| PlayerAwareFilter* const specialFilter = dynamic_cast <PlayerAwareFilter*> (sortedFilters.getUnchecked(i)->filter); | |||
| if (specialFilter != 0) | |||
| specialFilter->setPlayer (this); | |||
| } | |||
| { | |||
| const ScopedLock sl (processLock); | |||
| filters = sortedFilters; | |||
| connections.clear(); | |||
| for (int i = 0; i < graph.connections.size(); ++i) | |||
| connections.add (new FilterConnection (*graph.connections.getUnchecked(i))); | |||
| } | |||
| // release any old ones.. | |||
| for (int i = 0; i < filtersBeingRemoved.size(); ++i) | |||
| { | |||
| filtersBeingRemoved.getUnchecked(i)->filter->releaseResources(); | |||
| PlayerAwareFilter* const specialFilter = dynamic_cast <PlayerAwareFilter*> (filtersBeingRemoved.getUnchecked(i)->filter); | |||
| if (specialFilter != 0) | |||
| specialFilter->setPlayer (0); | |||
| } | |||
| } | |||
| void FilterGraphPlayer::changeListenerCallback (void*) | |||
| { | |||
| update(); | |||
| } | |||
| void FilterGraphPlayer::audioDeviceIOCallback (const float** inputChannelData_, | |||
| int totalNumInputChannels_, | |||
| float** outputChannelData_, | |||
| int totalNumOutputChannels_, | |||
| int numSamples) | |||
| { | |||
| incomingMidi.clear(); | |||
| messageCollector.removeNextBlockOfMessages (incomingMidi, numSamples); | |||
| for (int i = 0; i < totalNumOutputChannels_; ++i) | |||
| if (outputChannelData_[i] != 0) | |||
| zeromem (outputChannelData_[i], sizeof (float) * numSamples); | |||
| const ScopedLock sl (processLock); | |||
| inputChannelData = inputChannelData_; | |||
| totalNumInputChannels = totalNumInputChannels_; | |||
| outputChannelData = outputChannelData_; | |||
| totalNumOutputChannels = totalNumOutputChannels_; | |||
| for (int i = 0; i < filters.size(); ++i) | |||
| { | |||
| FilterInGraph* const cf = filters.getUnchecked(i); | |||
| cf->renderBlock (numSamples, filters, connections); | |||
| } | |||
| } | |||
| void FilterGraphPlayer::audioDeviceAboutToStart (double sampleRate_, int numSamplesPerBlock) | |||
| { | |||
| const ScopedLock sl (processLock); | |||
| sampleRate = sampleRate_; | |||
| blockSize = numSamplesPerBlock; | |||
| messageCollector.reset (sampleRate_); | |||
| for (int i = 0; i < filters.size(); ++i) | |||
| { | |||
| filters.getUnchecked(i)->filter->prepareToPlay (sampleRate, blockSize); | |||
| filters.getUnchecked(i)->prepareBuffers (blockSize); | |||
| } | |||
| graph.sendChangeMessage (&graph); | |||
| } | |||
| void FilterGraphPlayer::audioDeviceStopped() | |||
| { | |||
| const ScopedLock sl (processLock); | |||
| for (int i = 0; i < filters.size(); ++i) | |||
| filters.getUnchecked(i)->filter->releaseResources(); | |||
| } | |||
| void FilterGraphPlayer::handleIncomingMidiMessage (MidiInput*, const MidiMessage& message) | |||
| { | |||
| // keyState.processNextMidiEvent (message); | |||
| messageCollector.addMessageToQueue (message); | |||
| graph.removeIllegalConnections(); | |||
| } | |||
| @@ -32,12 +32,8 @@ | |||
| #ifndef __JUCE_FILTERGRAPH_JUCEHEADER__ | |||
| #define __JUCE_FILTERGRAPH_JUCEHEADER__ | |||
| #include "../plugins/juce_AudioPluginInstance.h" | |||
| #include "../plugins/juce_PluginDescription.h" | |||
| class FilterInGraph; | |||
| class FilterGraph; | |||
| class FilterGraphPlayer; | |||
| const char* const filenameSuffix = ".filtergraph"; | |||
| const char* const filenameWildcard = "*.filtergraph"; | |||
| @@ -75,7 +71,7 @@ private: | |||
| /** | |||
| Represents one of the filters in a FilterGraph. | |||
| */ | |||
| class FilterInGraph : public ReferenceCountedObject | |||
| /*class FilterInGraph : public ReferenceCountedObject | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| @@ -129,7 +125,7 @@ private: | |||
| FilterInGraph (const FilterInGraph&); | |||
| const FilterInGraph& operator= (const FilterInGraph&); | |||
| }; | |||
| */ | |||
| //============================================================================== | |||
| /** | |||
| @@ -143,11 +139,12 @@ public: | |||
| ~FilterGraph(); | |||
| //============================================================================== | |||
| int getNumFilters() const throw() { return filters.size(); } | |||
| FilterInGraph* getFilter (const int index) const throw() { return filters [index]; } | |||
| FilterInGraph* getFilterForUID (const uint32 uid) const throw(); | |||
| AudioProcessorGraph& getGraph() throw() { return graph; } | |||
| int getNumFilters() const throw(); | |||
| const AudioProcessorGraph::Node::Ptr getNode (const int index) const throw(); | |||
| const AudioProcessorGraph::Node::Ptr getNodeForId (const uint32 uid) const throw(); | |||
| void addFilter (const FilterInGraph::Ptr& newFilter); | |||
| void addFilter (const PluginDescription* desc, double x, double y); | |||
| void removeFilter (const uint32 filterUID); | |||
| @@ -155,14 +152,15 @@ public: | |||
| void removeIllegalConnections(); | |||
| //============================================================================== | |||
| int getNumConnections() const throw() { return connections.size(); } | |||
| const FilterConnection* getConnection (const int index) const throw() { return connections [index]; } | |||
| void setNodePosition (const int nodeId, double x, double y); | |||
| void getNodePosition (const int nodeId, double& x, double& y) const; | |||
| const FilterConnection* getConnectionBetween (uint32 sourceFilterUID, int sourceFilterChannel, | |||
| uint32 destFilterUID, int destFilterChannel) const throw(); | |||
| //============================================================================== | |||
| int getNumConnections() const throw(); | |||
| const AudioProcessorGraph::Connection* getConnection (const int index) const throw(); | |||
| bool isAnInputTo (const uint32 possibleInput, const uint32 possibleDestination) const throw(); | |||
| const AudioProcessorGraph::Connection* getConnectionBetween (uint32 sourceFilterUID, int sourceFilterChannel, | |||
| uint32 destFilterUID, int destFilterChannel) const throw(); | |||
| bool canConnect (uint32 sourceFilterUID, int sourceFilterChannel, | |||
| uint32 destFilterUID, int destFilterChannel) const throw(); | |||
| @@ -177,6 +175,9 @@ public: | |||
| void clear(); | |||
| //============================================================================== | |||
| XmlElement* createXml() const; | |||
| void restoreFromXml (const XmlElement& xml); | |||
| @@ -195,14 +196,17 @@ public: | |||
| juce_UseDebuggingNewOperator | |||
| private: | |||
| friend class FilterGraphPlayer; | |||
| ReferenceCountedArray <FilterInGraph> filters; | |||
| OwnedArray <FilterConnection> connections; | |||
| //friend class FilterGraphPlayer; | |||
| //ReferenceCountedArray <FilterInGraph> filters; | |||
| //OwnedArray <FilterConnection> connections; | |||
| AudioProcessorGraph graph; | |||
| AudioProcessorPlayer player; | |||
| uint32 lastUID; | |||
| uint32 getNextUID() throw(); | |||
| bool isAnInputTo (const uint32 possibleInput, const uint32 possibleDestination, int recursionCheck) const throw(); | |||
| void createNodeFromXml (const XmlElement& xml); | |||
| FilterGraph (const FilterGraph&); | |||
| const FilterGraph& operator= (const FilterGraph&); | |||
| @@ -213,7 +217,7 @@ private: | |||
| /** | |||
| */ | |||
| class FilterGraphPlayer : public AudioIODeviceCallback, | |||
| /*class FilterGraphPlayer : public AudioIODeviceCallback, | |||
| public MidiInputCallback, | |||
| public ChangeListener | |||
| @@ -274,6 +278,6 @@ private: | |||
| FilterGraphPlayer (const FilterGraphPlayer&); | |||
| const FilterGraphPlayer& operator= (const FilterGraphPlayer&); | |||
| }; | |||
| */ | |||
| #endif | |||
| @@ -35,6 +35,95 @@ | |||
| #include "MainHostWindow.h" | |||
| //============================================================================== | |||
| class PluginWindow; | |||
| static Array <PluginWindow*> activePluginWindows; | |||
| PluginWindow::PluginWindow (Component* const uiComp, | |||
| AudioProcessorGraph::Node* owner_, | |||
| const bool isGeneric_) | |||
| : DocumentWindow (uiComp->getName(), Colours::lightblue, | |||
| DocumentWindow::minimiseButton | DocumentWindow::closeButton), | |||
| owner (owner_), | |||
| isGeneric (isGeneric_) | |||
| { | |||
| setSize (400, 300); | |||
| setContentComponent (uiComp, true, true); | |||
| setTopLeftPosition (owner->properties.getIntValue ("uiLastX", Random::getSystemRandom().nextInt (500)), | |||
| owner->properties.getIntValue ("uiLastY", Random::getSystemRandom().nextInt (500))); | |||
| setVisible (true); | |||
| activePluginWindows.add (this); | |||
| } | |||
| void PluginWindow::closeCurrentlyOpenWindowsFor (const uint32 nodeId) | |||
| { | |||
| for (int i = activePluginWindows.size(); --i >= 0;) | |||
| if (activePluginWindows.getUnchecked(i)->owner->id == nodeId) | |||
| delete activePluginWindows.getUnchecked(i); | |||
| } | |||
| void PluginWindow::closeAllCurrentlyOpenWindows() | |||
| { | |||
| for (int i = activePluginWindows.size(); --i >= 0;) | |||
| delete activePluginWindows.getUnchecked(i); | |||
| } | |||
| PluginWindow* PluginWindow::getWindowFor (AudioProcessorGraph::Node* node, | |||
| bool useGenericView) | |||
| { | |||
| for (int i = activePluginWindows.size(); --i >= 0;) | |||
| if (activePluginWindows.getUnchecked(i)->owner == node | |||
| && activePluginWindows.getUnchecked(i)->isGeneric == useGenericView) | |||
| return activePluginWindows.getUnchecked(i); | |||
| AudioProcessorEditor* ui = 0; | |||
| if (! useGenericView) | |||
| { | |||
| ui = node->processor->createEditorIfNeeded(); | |||
| if (ui == 0) | |||
| useGenericView = true; | |||
| } | |||
| if (useGenericView) | |||
| { | |||
| ui = new GenericAudioProcessorEditor (node->processor); | |||
| } | |||
| if (ui != 0) | |||
| { | |||
| AudioPluginInstance* const plugin = dynamic_cast <AudioPluginInstance*> (node->processor); | |||
| if (plugin != 0) | |||
| ui->setName (plugin->getName()); | |||
| return new PluginWindow (ui, node, useGenericView); | |||
| } | |||
| return 0; | |||
| } | |||
| PluginWindow::~PluginWindow() | |||
| { | |||
| activePluginWindows.removeValue (this); | |||
| setContentComponent (0); | |||
| } | |||
| void PluginWindow::moved() | |||
| { | |||
| owner->properties.setValue ("uiLastX", getX()); | |||
| owner->properties.setValue ("uiLastY", getY()); | |||
| } | |||
| void PluginWindow::closeButtonPressed() | |||
| { | |||
| delete this; | |||
| } | |||
| //============================================================================== | |||
| class PinComponent : public Component, | |||
| public SettableTooltipClient | |||
| @@ -47,16 +136,16 @@ public: | |||
| index (index_), | |||
| isInput (isInput_) | |||
| { | |||
| const FilterInGraph* const f = graph.getFilterForUID (filterID_); | |||
| const AudioProcessorGraph::Node::Ptr node (graph.getNodeForId (filterID_)); | |||
| if (f != 0) | |||
| if (node != 0) | |||
| { | |||
| String tip; | |||
| if (isInput) | |||
| tip = f->filter->getInputChannelName (index_); | |||
| tip = node->processor->getInputChannelName (index_); | |||
| else | |||
| tip = f->filter->getOutputChannelName (index_); | |||
| tip = node->processor->getOutputChannelName (index_); | |||
| if (tip.isEmpty()) | |||
| { | |||
| @@ -185,10 +274,15 @@ public: | |||
| } | |||
| else if (r == 3 || r == 4) | |||
| { | |||
| FilterInGraph* const f = graph.getFilterForUID (filterID); | |||
| AudioProcessorGraph::Node::Ptr f (graph.getNodeForId (filterID)); | |||
| if (f != 0) | |||
| f->showUI (r == 4); | |||
| { | |||
| PluginWindow* const w = PluginWindow::getWindowFor (f, r == 4); | |||
| if (w != 0) | |||
| w->toFront (true); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -203,15 +297,11 @@ public: | |||
| if (getParentComponent() != 0) | |||
| getParentComponent()->globalPositionToRelative (x, y); | |||
| const FilterInGraph::Ptr f (graph.getFilterForUID (filterID)); | |||
| if (f != 0) | |||
| { | |||
| f->setPosition ((x + getWidth() / 2) / (double) getParentWidth(), | |||
| (y + getHeight() / 2) / (double) getParentHeight()); | |||
| graph.setNodePosition (filterID, | |||
| (x + getWidth() / 2) / (double) getParentWidth(), | |||
| (y + getHeight() / 2) / (double) getParentHeight()); | |||
| getGraphPanel()->updateComponents(); | |||
| } | |||
| getGraphPanel()->updateComponents(); | |||
| } | |||
| } | |||
| @@ -219,10 +309,15 @@ public: | |||
| { | |||
| if (e.mouseWasClicked() && e.getNumberOfClicks() == 2) | |||
| { | |||
| const FilterInGraph::Ptr f (graph.getFilterForUID (filterID)); | |||
| const AudioProcessorGraph::Node::Ptr f (graph.getNodeForId (filterID)); | |||
| if (f != 0) | |||
| f->showUI (false); | |||
| { | |||
| PluginWindow* const w = PluginWindow::getWindowFor (f, false); | |||
| if (w != 0) | |||
| w->toFront (true); | |||
| } | |||
| } | |||
| else if (! e.mouseWasClicked()) | |||
| { | |||
| @@ -295,7 +390,7 @@ public: | |||
| void update() | |||
| { | |||
| const FilterInGraph* const f = graph.getFilterForUID (filterID); | |||
| const AudioProcessorGraph::Node::Ptr f (graph.getNodeForId (filterID)); | |||
| if (f == 0) | |||
| { | |||
| @@ -303,12 +398,12 @@ public: | |||
| return; | |||
| } | |||
| numIns = f->filter->getNumInputChannels(); | |||
| if (f->filter->acceptsMidi()) | |||
| numIns = f->processor->getNumInputChannels(); | |||
| if (f->processor->acceptsMidi()) | |||
| ++numIns; | |||
| numOuts = f->filter->getNumOutputChannels(); | |||
| if (f->filter->producesMidi()) | |||
| numOuts = f->processor->getNumOutputChannels(); | |||
| if (f->processor->producesMidi()) | |||
| ++numOuts; | |||
| int w = 100; | |||
| @@ -316,14 +411,20 @@ public: | |||
| w = jmax (w, (jmax (numIns, numOuts) + 1) * 20); | |||
| const int textWidth = font.getStringWidth (f->filter->getName()); | |||
| const int textWidth = font.getStringWidth (f->processor->getName()); | |||
| w = jmax (w, 16 + jmin (textWidth, 300)); | |||
| if (textWidth > 300) | |||
| h = 100; | |||
| setSize (w, h); | |||
| setCentreRelative ((float) f->getX(), (float) f->getY()); | |||
| setName (f->processor->getName()); | |||
| { | |||
| double x, y; | |||
| graph.getNodePosition (filterID, x, y); | |||
| setCentreRelative ((float) x, (float) y); | |||
| } | |||
| if (numIns != numInputs || numOuts != numOutputs) | |||
| { | |||
| @@ -333,20 +434,18 @@ public: | |||
| deleteAllChildren(); | |||
| int i; | |||
| for (i = 0; i < f->filter->getNumInputChannels(); ++i) | |||
| for (i = 0; i < f->processor->getNumInputChannels(); ++i) | |||
| addAndMakeVisible (new PinComponent (graph, filterID, i, true)); | |||
| if (f->filter->acceptsMidi()) | |||
| if (f->processor->acceptsMidi()) | |||
| addAndMakeVisible (new PinComponent (graph, filterID, FilterGraph::midiChannelNumber, true)); | |||
| for (i = 0; i < f->filter->getNumOutputChannels(); ++i) | |||
| for (i = 0; i < f->processor->getNumOutputChannels(); ++i) | |||
| addAndMakeVisible (new PinComponent (graph, filterID, i, false)); | |||
| if (f->filter->producesMidi()) | |||
| if (f->processor->producesMidi()) | |||
| addAndMakeVisible (new PinComponent (graph, filterID, FilterGraph::midiChannelNumber, false)); | |||
| setName (f->filter->getName()); | |||
| resized(); | |||
| } | |||
| } | |||
| @@ -679,17 +778,17 @@ FilterComponent* GraphEditorPanel::getComponentForFilter (const uint32 filterID) | |||
| return 0; | |||
| } | |||
| ConnectorComponent* GraphEditorPanel::getComponentForConnection (const FilterConnection& conn) const | |||
| ConnectorComponent* GraphEditorPanel::getComponentForConnection (const AudioProcessorGraph::Connection& conn) const | |||
| { | |||
| for (int i = getNumChildComponents(); --i >= 0;) | |||
| { | |||
| ConnectorComponent* const c = dynamic_cast <ConnectorComponent*> (getChildComponent (i)); | |||
| if (c != 0 | |||
| && c->sourceFilterID == conn.sourceFilterID | |||
| && c->destFilterID == conn.destFilterID | |||
| && c->sourceFilterChannel == conn.sourceChannel | |||
| && c->destFilterChannel == conn.destChannel) | |||
| && c->sourceFilterID == conn.sourceNodeId | |||
| && c->destFilterID == conn.destNodeId | |||
| && c->sourceFilterChannel == conn.sourceChannelIndex | |||
| && c->destFilterChannel == conn.destChannelIndex) | |||
| { | |||
| return c; | |||
| } | |||
| @@ -759,11 +858,11 @@ void GraphEditorPanel::updateComponents() | |||
| for (i = graph.getNumFilters(); --i >= 0;) | |||
| { | |||
| const FilterInGraph* const f = graph.getFilter (i); | |||
| const AudioProcessorGraph::Node::Ptr f (graph.getNode (i)); | |||
| if (getComponentForFilter (f->uid) == 0) | |||
| if (getComponentForFilter (f->id) == 0) | |||
| { | |||
| FilterComponent* const comp = new FilterComponent (graph, f->uid); | |||
| FilterComponent* const comp = new FilterComponent (graph, f->id); | |||
| addAndMakeVisible (comp); | |||
| comp->update(); | |||
| } | |||
| @@ -771,15 +870,15 @@ void GraphEditorPanel::updateComponents() | |||
| for (i = graph.getNumConnections(); --i >= 0;) | |||
| { | |||
| const FilterConnection* const c = graph.getConnection (i); | |||
| const AudioProcessorGraph::Connection* const c = graph.getConnection (i); | |||
| if (getComponentForConnection (*c) == 0) | |||
| { | |||
| ConnectorComponent* const comp = new ConnectorComponent (graph); | |||
| addAndMakeVisible (comp); | |||
| comp->setInput (c->sourceFilterID, c->sourceChannel); | |||
| comp->setOutput (c->destFilterID, c->destChannel); | |||
| comp->setInput (c->sourceNodeId, c->sourceChannelIndex); | |||
| comp->setOutput (c->destNodeId, c->destChannelIndex); | |||
| } | |||
| } | |||
| } | |||
| @@ -942,24 +1041,27 @@ GraphDocumentComponent::GraphDocumentComponent (AudioDeviceManager* deviceManage | |||
| { | |||
| addAndMakeVisible (graphPanel = new GraphEditorPanel (graph)); | |||
| graphPlayer = new FilterGraphPlayer (graph); | |||
| graphPlayer.setProcessor (&graph.getGraph()); | |||
| keyState.addListener (&graphPlayer.getMidiMessageCollector()); | |||
| addAndMakeVisible (keyboardComp = new MidiKeyboardComponent (graphPlayer->keyState, | |||
| addAndMakeVisible (keyboardComp = new MidiKeyboardComponent (keyState, | |||
| MidiKeyboardComponent::horizontalKeyboard)); | |||
| addAndMakeVisible (statusBar = new TooltipBar()); | |||
| graphPlayer->setAudioDeviceManager (deviceManager); | |||
| deviceManager->setAudioCallback (&graphPlayer); | |||
| graphPanel->updateComponents(); | |||
| } | |||
| GraphDocumentComponent::~GraphDocumentComponent() | |||
| { | |||
| deviceManager->setAudioCallback (0); | |||
| deleteAllChildren(); | |||
| graphPlayer->setAudioDeviceManager (0); | |||
| deleteAndZero (graphPlayer); | |||
| graphPlayer.setProcessor (0); | |||
| keyState.removeListener (&graphPlayer.getMidiMessageCollector()); | |||
| graph.clear(); | |||
| } | |||
| @@ -32,7 +32,6 @@ | |||
| #ifndef __JUCE_FILTERGRAPHEDITOR_JUCEHEADER__ | |||
| #define __JUCE_FILTERGRAPHEDITOR_JUCEHEADER__ | |||
| #include "../plugins/juce_KnownPluginList.h" | |||
| #include "FilterGraph.h" | |||
| class FilterComponent; | |||
| @@ -57,7 +56,7 @@ public: | |||
| void createNewPlugin (const PluginDescription* desc, int x, int y); | |||
| FilterComponent* getComponentForFilter (const uint32 filterID) const; | |||
| ConnectorComponent* getComponentForConnection (const FilterConnection& conn) const; | |||
| ConnectorComponent* getComponentForConnection (const AudioProcessorGraph::Connection& conn) const; | |||
| PinComponent* findPinAt (const int x, const int y) const; | |||
| void resized(); | |||
| @@ -110,12 +109,39 @@ public: | |||
| private: | |||
| AudioDeviceManager* deviceManager; | |||
| FilterGraphPlayer* graphPlayer; | |||
| AudioProcessorPlayer graphPlayer; | |||
| MidiKeyboardState keyState; | |||
| GraphEditorPanel* graphPanel; | |||
| Component* keyboardComp; | |||
| Component* statusBar; | |||
| }; | |||
| //============================================================================== | |||
| /** A desktop window containing a plugin's UI. | |||
| */ | |||
| class PluginWindow : public DocumentWindow | |||
| { | |||
| PluginWindow (Component* const uiComp, | |||
| AudioProcessorGraph::Node* owner_, | |||
| const bool isGeneric_); | |||
| public: | |||
| static PluginWindow* getWindowFor (AudioProcessorGraph::Node* node, | |||
| bool useGenericView); | |||
| static void closeCurrentlyOpenWindowsFor (const uint32 nodeId); | |||
| static void closeAllCurrentlyOpenWindows(); | |||
| ~PluginWindow(); | |||
| void moved(); | |||
| void closeButtonPressed(); | |||
| private: | |||
| AudioProcessorGraph::Node* owner; | |||
| bool isGeneric; | |||
| }; | |||
| #endif | |||
| @@ -33,319 +33,22 @@ | |||
| #include "InternalFilters.h" | |||
| #include "FilterGraph.h" | |||
| //============================================================================== | |||
| class InternalFilterBase : public AudioPluginInstance, | |||
| public FilterGraphPlayer::PlayerAwareFilter | |||
| { | |||
| public: | |||
| InternalFilterBase() | |||
| : player (0) | |||
| { | |||
| } | |||
| ~InternalFilterBase() | |||
| { | |||
| } | |||
| void setPlayer (FilterGraphPlayer* p) | |||
| { | |||
| player = p; | |||
| playerChanged(); | |||
| } | |||
| virtual void playerChanged() {} | |||
| const String getManufacturer() const { return "Raw Material Software"; } | |||
| const String getFormatName() const { return "Internal"; } | |||
| const File getFile() const { return File::nonexistent; } | |||
| int getUID() const { return getName().hashCode(); } | |||
| int getSamplesLatency() const { return 0; } | |||
| AudioProcessorEditor* createEditor() { return 0; } | |||
| int getNumParameters() { return 0; } | |||
| const String getParameterName (int) { return String::empty; } | |||
| float getParameter (int) { return 0; } | |||
| const String getParameterText (int) { return String::empty; } | |||
| void setParameter (int, float) {} | |||
| int getNumPrograms() { return 0; } | |||
| int getCurrentProgram() { return 0; } | |||
| void setCurrentProgram (int) {} | |||
| const String getProgramName (int) { return String::empty; } | |||
| void changeProgramName (int, const String&) {} | |||
| void getStateInformation (MemoryBlock&) {} | |||
| void setStateInformation (const void*, int) {} | |||
| protected: | |||
| FilterGraphPlayer* player; | |||
| AudioIODevice* getAudioDevice() const | |||
| { | |||
| if (player != 0) | |||
| { | |||
| AudioDeviceManager* const dm = player->getAudioDeviceManager(); | |||
| jassert (dm != 0); | |||
| if (dm != 0) | |||
| return dm->getCurrentAudioDevice(); | |||
| } | |||
| return 0; | |||
| } | |||
| }; | |||
| //============================================================================== | |||
| class AudioInputDeviceFilter : public InternalFilterBase | |||
| { | |||
| public: | |||
| AudioInputDeviceFilter (const int numChannels) | |||
| { | |||
| setPlayConfigDetails (0, numChannels, getSampleRate(), getBlockSize()); | |||
| } | |||
| ~AudioInputDeviceFilter() {} | |||
| const String getName() const { return "Audio Input"; } | |||
| const String getVersion() const { return "1.0"; } | |||
| bool isInstrument() const { return true; } | |||
| const String getCategory() const { return "I/O devices"; } | |||
| bool acceptsMidi() const { return false; } | |||
| bool producesMidi() const { return false; } | |||
| void playerChanged() | |||
| { | |||
| AudioIODevice* const dev = getAudioDevice(); | |||
| if (dev != 0) | |||
| setPlayConfigDetails (0, dev->getActiveInputChannels().countNumberOfSetBits(), getSampleRate(), getBlockSize()); | |||
| } | |||
| void prepareToPlay (double /*sampleRate*/, int /*estimatedSamplesPerBlock*/) | |||
| { | |||
| playerChanged(); | |||
| } | |||
| void releaseResources() | |||
| { | |||
| } | |||
| void processBlock (AudioSampleBuffer& buffer, MidiBuffer&) | |||
| { | |||
| int n = 0; | |||
| for (int i = 0; i < player->totalNumInputChannels; ++i) | |||
| { | |||
| if (n >= getNumOutputChannels()) | |||
| break; | |||
| if (player->inputChannelData [i] != 0) | |||
| { | |||
| buffer.copyFrom (n, 0, player->inputChannelData [i], buffer.getNumSamples()); | |||
| ++n; | |||
| } | |||
| } | |||
| } | |||
| const String getInputChannelName (const int channelIndex) const | |||
| { | |||
| return String (channelIndex + 1); | |||
| } | |||
| const String getOutputChannelName (const int channelIndex) const | |||
| { | |||
| AudioIODevice* const dev = getAudioDevice(); | |||
| if (dev != 0) | |||
| return dev->getInputChannelNames() [channelIndex]; | |||
| return "Input Channel " + String (channelIndex + 1); | |||
| } | |||
| bool isInputChannelStereoPair (int) const | |||
| { | |||
| return true; | |||
| } | |||
| bool isOutputChannelStereoPair (int) const | |||
| { | |||
| return true; | |||
| } | |||
| }; | |||
| //============================================================================== | |||
| class AudioOutputDeviceFilter : public InternalFilterBase | |||
| { | |||
| public: | |||
| AudioOutputDeviceFilter (const int numChannels) | |||
| { | |||
| setPlayConfigDetails (numChannels, 0, getSampleRate(), getBlockSize()); | |||
| } | |||
| ~AudioOutputDeviceFilter() {} | |||
| const String getName() const { return "Audio Output"; } | |||
| const String getVersion() const { return "1.0"; } | |||
| bool isInstrument() const { return false; } | |||
| const String getCategory() const { return "I/O devices"; } | |||
| bool acceptsMidi() const { return false; } | |||
| bool producesMidi() const { return false; } | |||
| void playerChanged() | |||
| { | |||
| AudioIODevice* const dev = getAudioDevice(); | |||
| if (dev != 0) | |||
| setPlayConfigDetails (dev->getActiveOutputChannels().countNumberOfSetBits(), 0, getSampleRate(), getBlockSize()); | |||
| } | |||
| void prepareToPlay (double /*sampleRate*/, int /*estimatedSamplesPerBlock*/) | |||
| { | |||
| playerChanged(); | |||
| } | |||
| void releaseResources() | |||
| { | |||
| } | |||
| void processBlock (AudioSampleBuffer& buffer, MidiBuffer&) | |||
| { | |||
| int n = 0; | |||
| for (int i = 0; i < player->totalNumOutputChannels; ++i) | |||
| { | |||
| float* const dst = player->outputChannelData [i]; | |||
| if (dst != 0) | |||
| { | |||
| if (n >= getNumInputChannels()) | |||
| { | |||
| zeromem (dst, sizeof (float) * buffer.getNumSamples()); | |||
| } | |||
| else | |||
| { | |||
| memcpy (dst, buffer.getSampleData (n), | |||
| sizeof (float) * buffer.getNumSamples()); | |||
| } | |||
| ++n; | |||
| } | |||
| } | |||
| } | |||
| const String getInputChannelName (const int channelIndex) const | |||
| { | |||
| AudioIODevice* const dev = getAudioDevice(); | |||
| if (dev != 0) | |||
| return dev->getOutputChannelNames() [channelIndex]; | |||
| return "Output Channel " + String (channelIndex + 1); | |||
| } | |||
| const String getOutputChannelName (const int channelIndex) const | |||
| { | |||
| return String (channelIndex + 1); | |||
| } | |||
| bool isInputChannelStereoPair (int) const | |||
| { | |||
| return true; | |||
| } | |||
| bool isOutputChannelStereoPair (int) const | |||
| { | |||
| return true; | |||
| } | |||
| }; | |||
| //============================================================================== | |||
| class MidiInputDeviceFilter : public InternalFilterBase | |||
| { | |||
| public: | |||
| MidiInputDeviceFilter() | |||
| { | |||
| } | |||
| ~MidiInputDeviceFilter() {} | |||
| const String getName() const { return "Midi Input"; } | |||
| const String getVersion() const { return "1.0"; } | |||
| bool isInstrument() const { return true; } | |||
| const String getCategory() const { return "I/O devices"; } | |||
| bool acceptsMidi() const { return false; } | |||
| bool producesMidi() const { return true; } | |||
| void playerChanged() | |||
| { | |||
| if (player != 0) | |||
| { | |||
| AudioDeviceManager* const dm = player->getAudioDeviceManager(); | |||
| (void) dm; | |||
| jassert (dm != 0); | |||
| } | |||
| } | |||
| void prepareToPlay (double /*sampleRate*/, int /*estimatedSamplesPerBlock*/) | |||
| { | |||
| playerChanged(); | |||
| } | |||
| void releaseResources() | |||
| { | |||
| } | |||
| void processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiBuffer) | |||
| { | |||
| midiBuffer.clear(); | |||
| midiBuffer.addEvents (player->incomingMidi, 0, buffer.getNumSamples(), 0); | |||
| } | |||
| const String getInputChannelName (const int channelIndex) const | |||
| { | |||
| return String (channelIndex + 1); | |||
| } | |||
| const String getOutputChannelName (const int channelIndex) const | |||
| { | |||
| AudioIODevice* const dev = getAudioDevice(); | |||
| if (dev != 0) | |||
| return dev->getInputChannelNames() [channelIndex]; | |||
| return "Midi Input"; | |||
| } | |||
| bool isInputChannelStereoPair (int) const | |||
| { | |||
| return true; | |||
| } | |||
| bool isOutputChannelStereoPair (int) const | |||
| { | |||
| return true; | |||
| } | |||
| }; | |||
| //============================================================================== | |||
| InternalPluginFormat::InternalPluginFormat() | |||
| { | |||
| { | |||
| AudioInputDeviceFilter f (2); | |||
| audioInDesc.fillInFromInstance (f); | |||
| AudioProcessorGraph::AudioGraphIOProcessor p (AudioProcessorGraph::AudioGraphIOProcessor::audioOutputNode); | |||
| p.fillInPluginDescription (audioOutDesc); | |||
| } | |||
| { | |||
| AudioOutputDeviceFilter f (2); | |||
| audioOutDesc.fillInFromInstance (f); | |||
| AudioProcessorGraph::AudioGraphIOProcessor p (AudioProcessorGraph::AudioGraphIOProcessor::audioInputNode); | |||
| p.fillInPluginDescription (audioInDesc); | |||
| } | |||
| { | |||
| MidiInputDeviceFilter f; | |||
| midiInDesc.fillInFromInstance (f); | |||
| AudioProcessorGraph::AudioGraphIOProcessor p (AudioProcessorGraph::AudioGraphIOProcessor::midiInputNode); | |||
| p.fillInPluginDescription (midiInDesc); | |||
| } | |||
| } | |||
| @@ -353,15 +56,15 @@ AudioPluginInstance* InternalPluginFormat::createInstanceFromDescription (const | |||
| { | |||
| if (desc.name == audioOutDesc.name) | |||
| { | |||
| return new AudioOutputDeviceFilter (desc.numInputChannels); | |||
| return new AudioProcessorGraph::AudioGraphIOProcessor (AudioProcessorGraph::AudioGraphIOProcessor::audioOutputNode); | |||
| } | |||
| else if (desc.name == audioInDesc.name) | |||
| { | |||
| return new AudioInputDeviceFilter (desc.numOutputChannels); | |||
| return new AudioProcessorGraph::AudioGraphIOProcessor (AudioProcessorGraph::AudioGraphIOProcessor::audioInputNode); | |||
| } | |||
| else if (desc.name == midiInDesc.name) | |||
| { | |||
| return new MidiInputDeviceFilter(); | |||
| return new AudioProcessorGraph::AudioGraphIOProcessor (AudioProcessorGraph::AudioGraphIOProcessor::midiInputNode); | |||
| } | |||
| return 0; | |||
| @@ -33,7 +33,7 @@ | |||
| #define __JUCE_MAINHOSTWINDOW_JUCEHEADER__xxxxx | |||
| #include "FilterGraph.h" | |||
| #include "../plugins/juce_AudioPluginFormat.h" | |||
| //============================================================================== | |||
| /** | |||
| @@ -32,7 +32,7 @@ | |||
| #include "../../../../juce.h" | |||
| #include "MainHostWindow.h" | |||
| #include "InternalFilters.h" | |||
| #include "../plugins/juce_PluginListComponent.h" | |||
| //============================================================================== | |||
| class PluginListWindow : public DocumentWindow | |||
| @@ -85,6 +85,13 @@ MainHostWindow::MainHostWindow() | |||
| : DocumentWindow (JUCEApplication::getInstance()->getApplicationName(), Colours::lightgrey, | |||
| DocumentWindow::allButtons) | |||
| { | |||
| XmlElement* const savedAudioState = ApplicationProperties::getInstance()->getUserSettings() | |||
| ->getXmlValue (T("audioDeviceState")); | |||
| deviceManager.initialise (256, 256, savedAudioState, true); | |||
| delete savedAudioState; | |||
| setResizable (true, false); | |||
| setResizeLimits (500, 400, 10000, 10000); | |||
| centreWithSize (800, 600); | |||
| @@ -104,13 +111,6 @@ MainHostWindow::MainHostWindow() | |||
| InternalPluginFormat internalFormat; | |||
| internalFormat.getAllTypes (internalTypes); | |||
| XmlElement* const savedAudioState = ApplicationProperties::getInstance()->getUserSettings() | |||
| ->getXmlValue (T("audioDeviceState")); | |||
| deviceManager.initialise (256, 256, savedAudioState, true); | |||
| delete savedAudioState; | |||
| XmlElement* const savedPluginList = ApplicationProperties::getInstance() | |||
| ->getUserSettings() | |||
| ->getXmlValue (T("pluginList")); | |||
| @@ -34,7 +34,6 @@ | |||
| #include "FilterGraph.h" | |||
| #include "GraphEditorPanel.h" | |||
| #include "../plugins/juce_KnownPluginList.h" | |||
| //============================================================================== | |||
| @@ -105,3 +105,27 @@ void AudioPluginFormatManager::addFormat (AudioPluginFormat* const format) throw | |||
| { | |||
| formats.add (format); | |||
| } | |||
| AudioPluginInstance* AudioPluginFormatManager::createInstance (const PluginDescription& description, | |||
| String& errorMessage) const | |||
| { | |||
| AudioPluginInstance* result = 0; | |||
| for (int i = 0; i < formats.size(); ++i) | |||
| { | |||
| result = formats.getUnchecked(i)->createInstanceFromDescription (*this); | |||
| if (result != 0) | |||
| break; | |||
| } | |||
| if (result == 0) | |||
| { | |||
| if (file != File::nonexistent && ! file.exists()) | |||
| errorMessage = TRANS ("This plug-in file no longer exists"); | |||
| else | |||
| errorMessage = TRANS ("This plug-in failed to load correctly"); | |||
| } | |||
| return result; | |||
| } | |||
| @@ -146,6 +146,19 @@ public: | |||
| */ | |||
| void addFormat (AudioPluginFormat* const format) throw(); | |||
| //============================================================================== | |||
| /** Tries to load the type for this description, by trying all the formats | |||
| that this manager knows about. | |||
| The caller is responsible for deleting the object that is returned. | |||
| If it can't load the plugin, it returns 0 and leaves a message in the | |||
| errorMessage string. | |||
| */ | |||
| AudioPluginInstance* createInstance (const PluginDescription& description, | |||
| String& errorMessage) const; | |||
| //============================================================================== | |||
| juce_UseDebuggingNewOperator | |||
| @@ -60,6 +60,15 @@ PluginDescription* KnownPluginList::getTypeForFile (const File& file) const thro | |||
| return 0; | |||
| } | |||
| PluginDescription* KnownPluginList::getTypeForIdentifierString (const String& identifierString) const throw() | |||
| { | |||
| for (int i = 0; i < types.size(); ++i) | |||
| if (types.getUnchecked(i)->createIdentifierString() == identifierString) | |||
| return types.getUnchecked(i); | |||
| return 0; | |||
| } | |||
| bool KnownPluginList::addType (const PluginDescription& type) | |||
| { | |||
| for (int i = types.size(); --i >= 0;) | |||
| @@ -341,7 +350,7 @@ public: | |||
| { | |||
| PluginDescription* const plugin = plugins.getUnchecked(i); | |||
| m.addItem (allPlugins.indexOf (plugin) + menuIdBase, | |||
| m.addItem (allPlugins.indexOf (plugin) + menuIdBase, | |||
| plugin->name, true, false); | |||
| } | |||
| } | |||
| @@ -74,6 +74,13 @@ public: | |||
| */ | |||
| PluginDescription* getTypeForFile (const File& file) const throw(); | |||
| /** Looks for a type in the list which matches a plugin type ID. | |||
| The identifierString parameter must have been created by | |||
| PluginDescription::createIdentifierString(). | |||
| */ | |||
| PluginDescription* getTypeForIdentifierString (const String& identifierString) const throw(); | |||
| /** Adds a type manually from its description. */ | |||
| bool addType (const PluginDescription& type); | |||
| @@ -85,44 +85,11 @@ bool PluginDescription::isDuplicateOf (const PluginDescription& other) const | |||
| && uid == other.uid; | |||
| } | |||
| void PluginDescription::fillInFromInstance (AudioPluginInstance& instance) throw() | |||
| const String PluginDescription::createIdentifierString() const throw() | |||
| { | |||
| name = instance.getName(); | |||
| file = instance.getFile(); | |||
| uid = instance.getUID(); | |||
| lastFileModTime = file.getLastModificationTime(); | |||
| pluginFormatName = instance.getFormatName(); | |||
| category = instance.getCategory(); | |||
| manufacturerName = instance.getManufacturer(); | |||
| version = instance.getVersion(); | |||
| numInputChannels = instance.getNumInputChannels(); | |||
| numOutputChannels = instance.getNumOutputChannels(); | |||
| isInstrument = instance.isInstrument(); | |||
| } | |||
| AudioPluginInstance* PluginDescription::createInstance (String& errorMessage) const | |||
| { | |||
| AudioPluginInstance* result = 0; | |||
| for (int i = 0; i < AudioPluginFormatManager::getInstance()->getNumFormats(); ++i) | |||
| { | |||
| AudioPluginFormat* const format = AudioPluginFormatManager::getInstance()->getFormat (i); | |||
| result = format->createInstanceFromDescription (*this); | |||
| if (result != 0) | |||
| break; | |||
| } | |||
| if (result == 0) | |||
| { | |||
| if (file != File::nonexistent && ! file.exists()) | |||
| errorMessage = TRANS ("This plug-in file no longer exists"); | |||
| else | |||
| errorMessage = TRANS ("This plug-in failed to load correctly"); | |||
| } | |||
| return result; | |||
| return pluginFormatName | |||
| + T("/") + pluginName | |||
| + T("/") + String::toHexString (file.getFileName().hashCode()); | |||
| } | |||
| XmlElement* PluginDescription::createXml() const | |||
| @@ -85,6 +85,8 @@ public: | |||
| Note that this might not be unique between formats, e.g. a VST and some | |||
| other format might actually have the same id. | |||
| @see createIdentifierString | |||
| */ | |||
| int uid; | |||
| @@ -111,17 +113,6 @@ public: | |||
| */ | |||
| void fillInFromInstance (AudioPluginInstance& instance) throw(); | |||
| //============================================================================== | |||
| /** Tries to load the type for this description, by trying all the formats | |||
| available in the AudioPluginFormat. | |||
| The caller is responsible for deleting the object that is returned. | |||
| If it can't load the plugin, it returns 0 and leaves a message in the | |||
| errorMessage string. | |||
| */ | |||
| AudioPluginInstance* createInstance (String& errorMessage) const; | |||
| //============================================================================== | |||
| /** Creates an XML object containing these details. | |||
| @@ -136,6 +127,16 @@ public: | |||
| */ | |||
| bool loadFromXml (const XmlElement& xml); | |||
| //============================================================================== | |||
| /** Returns a string that can be saved and used to uniquely identify the | |||
| plugin again. | |||
| This contains less info than the XML encoding, and is independent of the | |||
| plugin's file location, so can be used to store a plugin ID for use | |||
| across different machines. | |||
| */ | |||
| const String createIdentifierString() const throw(); | |||
| //============================================================================== | |||
| juce_UseDebuggingNewOperator | |||
| @@ -124,6 +124,16 @@ bool DemoJuceFilter::isOutputChannelStereoPair (int index) const | |||
| return false; | |||
| } | |||
| bool DemoJuceFilter::acceptsMidi() const | |||
| { | |||
| return true; | |||
| } | |||
| bool DemoJuceFilter::producesMidi() const | |||
| { | |||
| return true; | |||
| } | |||
| //============================================================================== | |||
| void DemoJuceFilter::prepareToPlay (double sampleRate, int samplesPerBlock) | |||
| { | |||
| @@ -71,6 +71,9 @@ public: | |||
| bool isInputChannelStereoPair (int index) const; | |||
| bool isOutputChannelStereoPair (int index) const; | |||
| bool acceptsMidi() const; | |||
| bool producesMidi() const; | |||
| //============================================================================== | |||
| int getNumPrograms() { return 0; } | |||
| int getCurrentProgram() { return 0; } | |||
| @@ -101,15 +101,14 @@ void AudioFilterStreamer::audioDeviceIOCallback (const float** inputChannelData, | |||
| zeromem (outChans[numOutsWanted++], sizeof (float) * numSamples); | |||
| } | |||
| void AudioFilterStreamer::audioDeviceAboutToStart (double sampleRate_, | |||
| int numSamplesPerBlock) | |||
| void AudioFilterStreamer::audioDeviceAboutToStart (AudioIODevice* device) | |||
| { | |||
| sampleRate = sampleRate_; | |||
| sampleRate = device->getCurrentSampleRate(); | |||
| isPlaying = true; | |||
| emptyBuffer.setSize (1 + filter.getNumOutputChannels(), | |||
| jmax (2048, numSamplesPerBlock * 2)); | |||
| jmax (2048, device->getCurrentBlockSizeSamples() * 2)); | |||
| emptyBuffer.clear(); | |||
| midiCollector.reset (sampleRate); | |||
| @@ -66,7 +66,7 @@ public: | |||
| int totalNumOutputChannels, | |||
| int numSamples); | |||
| void audioDeviceAboutToStart (double sampleRate, int numSamplesPerBlock); | |||
| void audioDeviceAboutToStart (AudioIODevice* device); | |||
| void audioDeviceStopped(); | |||
| void handleIncomingMidiMessage (MidiInput* source, const MidiMessage& message); | |||
| @@ -32,7 +32,7 @@ | |||
| 84EAE2F309DAAF0B00288D0A /* AGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84EAE2F109DAAF0B00288D0A /* AGL.framework */; }; | |||
| 84EAE2F409DAAF0B00288D0A /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84EAE2F209DAAF0B00288D0A /* OpenGL.framework */; }; | |||
| 84F8DB0B099CA8DD00E911ED /* QuickTimeDemo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84F8DB0A099CA8DD00E911ED /* QuickTimeDemo.cpp */; }; | |||
| 84FDB0950C15BDDD00CD0087 /* libjucedebug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 84FDB0940C15BDCE00CD0087 /* libjucedebug.a */; }; | |||
| 84FDB0950C15BDDD00CD0087 /* libjuce.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 84FDB0940C15BDCE00CD0087 /* libjuce.a */; }; | |||
| 8D0C4E8D0486CD37000505A6 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0867D6AAFE840B52C02AAC07 /* InfoPlist.strings */; }; | |||
| 8D0C4E920486CD37000505A6 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 20286C33FDCF999611CA2CEA /* Carbon.framework */; }; | |||
| /* End PBXBuildFile section */ | |||
| @@ -77,7 +77,7 @@ | |||
| 84EAE2F909DAAF2F00288D0A /* Juce.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Juce.xcodeproj; path = ../../../../build/macosx/Juce.xcodeproj; sourceTree = SOURCE_ROOT; }; | |||
| 84F8DB0A099CA8DD00E911ED /* QuickTimeDemo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = QuickTimeDemo.cpp; sourceTree = "<group>"; }; | |||
| 8D0C4E960486CD37000505A6 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; }; | |||
| 8D0C4E970486CD37000505A6 /* jucedemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = jucedemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; | |||
| 8D0C4E970486CD37000505A6 /* jucedemo.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = jucedemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; | |||
| /* End PBXFileReference section */ | |||
| /* Begin PBXFrameworksBuildPhase section */ | |||
| @@ -85,7 +85,7 @@ | |||
| isa = PBXFrameworksBuildPhase; | |||
| buildActionMask = 2147483647; | |||
| files = ( | |||
| 84FDB0950C15BDDD00CD0087 /* libjucedebug.a in Frameworks */, | |||
| 84FDB0950C15BDDD00CD0087 /* libjuce.a in Frameworks */, | |||
| 8D0C4E920486CD37000505A6 /* Carbon.framework in Frameworks */, | |||
| 84C49F2606C0F3200066071B /* CoreAudio.framework in Frameworks */, | |||
| 84C4A41106C0F9A00066071B /* IOKit.framework in Frameworks */, | |||
| @@ -181,7 +181,7 @@ | |||
| 84FDB0900C15BDCE00CD0087 /* Products */ = { | |||
| isa = PBXGroup; | |||
| children = ( | |||
| 84FDB0940C15BDCE00CD0087 /* libjucedebug.a */, | |||
| 84FDB0940C15BDCE00CD0087 /* libjuce.a */, | |||
| ); | |||
| name = Products; | |||
| sourceTree = "<group>"; | |||
| @@ -244,10 +244,10 @@ | |||
| /* End PBXProject section */ | |||
| /* Begin PBXReferenceProxy section */ | |||
| 84FDB0940C15BDCE00CD0087 /* libjucedebug.a */ = { | |||
| 84FDB0940C15BDCE00CD0087 /* libjuce.a */ = { | |||
| isa = PBXReferenceProxy; | |||
| fileType = archive.ar; | |||
| path = libjucedebug.a; | |||
| path = libjuce.a; | |||
| remoteRef = 84FDB0930C15BDCE00CD0087 /* PBXContainerItemProxy */; | |||
| sourceTree = BUILT_PRODUCTS_DIR; | |||
| }; | |||
| @@ -2022,68 +2022,70 @@ static const unsigned char temp4[] = {47,42,13,10,32,32,61,61,61,61,61,61,61,61, | |||
| 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, | |||
| 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,98, | |||
| 111,111,108,32,105,115,73,110,116,101,114,101,115,116,101,100,73,110,68,114,97,103,83,111,117,114,99,101,32,40,99,111,110,115,116,32,83,116,114,105, | |||
| 110,103,38,32,115,111,117,114,99,101,68,101,115,99,114,105,112,116,105,111,110,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,47, | |||
| 47,32,110,111,114,109,97,108,108,121,32,121,111,117,39,100,32,99,104,101,99,107,32,116,104,101,32,115,111,117,114,99,101,68,101,115,99,114,105,112, | |||
| 116,105,111,110,32,118,97,108,117,101,32,116,111,32,115,101,101,32,105,102,32,105,116,39,115,32,116,104,101,13,10,32,32,32,32,32,32,32,32,47, | |||
| 47,32,115,111,114,116,32,111,102,32,111,98,106,101,99,116,32,116,104,97,116,32,121,111,117,39,114,101,32,105,110,116,101,114,101,115,116,101,100,32, | |||
| 105,110,32,98,101,102,111,114,101,32,114,101,116,117,114,110,105,110,103,32,116,114,117,101,44,32,98,117,116,32,102,111,114,13,10,32,32,32,32,32, | |||
| 32,32,32,47,47,32,116,104,101,32,100,101,109,111,44,32,119,101,39,108,108,32,115,97,121,32,121,101,115,32,116,111,32,97,110,121,116,104,105,110, | |||
| 103,46,46,13,10,32,32,32,32,32,32,32,32,114,101,116,117,114,110,32,116,114,117,101,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32, | |||
| 118,111,105,100,32,105,116,101,109,68,114,97,103,69,110,116,101,114,32,40,99,111,110,115,116,32,83,116,114,105,110,103,38,32,115,111,117,114,99,101, | |||
| 68,101,115,99,114,105,112,116,105,111,110,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,67,111, | |||
| 109,112,111,110,101,110,116,42,32,115,111,117,114,99,101,67,111,109,112,111,110,101,110,116,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32, | |||
| 32,32,32,32,32,32,32,32,32,32,32,105,110,116,32,120,44,32,105,110,116,32,121,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32, | |||
| 32,115,111,109,101,116,104,105,110,103,73,115,66,101,105,110,103,68,114,97,103,103,101,100,79,118,101,114,32,61,32,116,114,117,101,59,13,10,32,32, | |||
| 32,32,32,32,32,32,114,101,112,97,105,110,116,40,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,105,116,101,109, | |||
| 68,114,97,103,77,111,118,101,32,40,99,111,110,115,116,32,83,116,114,105,110,103,38,32,115,111,117,114,99,101,68,101,115,99,114,105,112,116,105,111, | |||
| 110,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,67,111,109,112,111,110,101,110,116,42,32,115,111, | |||
| 117,114,99,101,67,111,109,112,111,110,101,110,116,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105, | |||
| 110,116,32,120,44,32,105,110,116,32,121,41,13,10,32,32,32,32,123,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,105, | |||
| 116,101,109,68,114,97,103,69,120,105,116,32,40,99,111,110,115,116,32,83,116,114,105,110,103,38,32,115,111,117,114,99,101,68,101,115,99,114,105,112, | |||
| 116,105,111,110,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,67,111,109,112,111,110,101,110,116,42, | |||
| 32,115,111,117,114,99,101,67,111,109,112,111,110,101,110,116,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,115,111,109,101,116,104, | |||
| 105,110,103,73,115,66,101,105,110,103,68,114,97,103,103,101,100,79,118,101,114,32,61,32,102,97,108,115,101,59,13,10,32,32,32,32,32,32,32,32, | |||
| 114,101,112,97,105,110,116,40,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,105,116,101,109,68,114,111,112,112,101, | |||
| 100,32,40,99,111,110,115,116,32,83,116,114,105,110,103,38,32,115,111,117,114,99,101,68,101,115,99,114,105,112,116,105,111,110,44,13,10,32,32,32, | |||
| 110,103,38,32,115,111,117,114,99,101,68,101,115,99,114,105,112,116,105,111,110,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, | |||
| 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,67,111,109,112,111,110,101,110,116,42,32,115,111,117,114,99,101,67,111,109,112, | |||
| 111,110,101,110,116,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,110,116,32,120,44,32,105,110,116, | |||
| 32,121,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,109,101,115,115,97,103,101,32,61,32,84,40,34,108,97,115,116,32,114,111, | |||
| 119,115,32,100,114,111,112,112,101,100,58,32,34,41,32,43,32,115,111,117,114,99,101,68,101,115,99,114,105,112,116,105,111,110,59,13,10,13,10,32, | |||
| 32,32,32,32,32,32,32,115,111,109,101,116,104,105,110,103,73,115,66,101,105,110,103,68,114,97,103,103,101,100,79,118,101,114,32,61,32,102,97,108, | |||
| 115,101,59,13,10,32,32,32,32,32,32,32,32,114,101,112,97,105,110,116,40,41,59,13,10,32,32,32,32,125,13,10,125,59,13,10,13,10,13,10, | |||
| 47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, | |||
| 111,110,101,110,116,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,47,47,32,110,111,114,109,97,108,108,121,32,121,111,117,39,100, | |||
| 32,99,104,101,99,107,32,116,104,101,32,115,111,117,114,99,101,68,101,115,99,114,105,112,116,105,111,110,32,118,97,108,117,101,32,116,111,32,115,101, | |||
| 101,32,105,102,32,105,116,39,115,32,116,104,101,13,10,32,32,32,32,32,32,32,32,47,47,32,115,111,114,116,32,111,102,32,111,98,106,101,99,116, | |||
| 32,116,104,97,116,32,121,111,117,39,114,101,32,105,110,116,101,114,101,115,116,101,100,32,105,110,32,98,101,102,111,114,101,32,114,101,116,117,114,110, | |||
| 105,110,103,32,116,114,117,101,44,32,98,117,116,32,102,111,114,13,10,32,32,32,32,32,32,32,32,47,47,32,116,104,101,32,100,101,109,111,44,32, | |||
| 119,101,39,108,108,32,115,97,121,32,121,101,115,32,116,111,32,97,110,121,116,104,105,110,103,46,46,13,10,32,32,32,32,32,32,32,32,114,101,116, | |||
| 117,114,110,32,116,114,117,101,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,105,116,101,109,68,114,97,103,69,110,116, | |||
| 101,114,32,40,99,111,110,115,116,32,83,116,114,105,110,103,38,32,115,111,117,114,99,101,68,101,115,99,114,105,112,116,105,111,110,44,13,10,32,32, | |||
| 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,67,111,109,112,111,110,101,110,116,42,32,115,111,117,114,99,101,67, | |||
| 111,109,112,111,110,101,110,116,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,110,116,32,120, | |||
| 44,32,105,110,116,32,121,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,115,111,109,101,116,104,105,110,103,73,115,66,101,105,110, | |||
| 103,68,114,97,103,103,101,100,79,118,101,114,32,61,32,116,114,117,101,59,13,10,32,32,32,32,32,32,32,32,114,101,112,97,105,110,116,40,41,59, | |||
| 13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,105,116,101,109,68,114,97,103,77,111,118,101,32,40,99,111,110,115,116,32, | |||
| 83,116,114,105,110,103,38,32,115,111,117,114,99,101,68,101,115,99,114,105,112,116,105,111,110,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32, | |||
| 32,32,32,32,32,32,32,32,32,32,32,67,111,109,112,111,110,101,110,116,42,32,115,111,117,114,99,101,67,111,109,112,111,110,101,110,116,44,13,10, | |||
| 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,110,116,32,120,44,32,105,110,116,32,121,41,13,10,32,32, | |||
| 32,32,123,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,105,116,101,109,68,114,97,103,69,120,105,116,32,40,99,111,110, | |||
| 115,116,32,83,116,114,105,110,103,38,32,115,111,117,114,99,101,68,101,115,99,114,105,112,116,105,111,110,44,13,10,32,32,32,32,32,32,32,32,32, | |||
| 32,32,32,32,32,32,32,32,32,32,32,32,32,32,67,111,109,112,111,110,101,110,116,42,32,115,111,117,114,99,101,67,111,109,112,111,110,101,110,116, | |||
| 41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,115,111,109,101,116,104,105,110,103,73,115,66,101,105,110,103,68,114,97,103,103,101, | |||
| 100,79,118,101,114,32,61,32,102,97,108,115,101,59,13,10,32,32,32,32,32,32,32,32,114,101,112,97,105,110,116,40,41,59,13,10,32,32,32,32, | |||
| 125,13,10,13,10,32,32,32,32,118,111,105,100,32,105,116,101,109,68,114,111,112,112,101,100,32,40,99,111,110,115,116,32,83,116,114,105,110,103,38, | |||
| 32,115,111,117,114,99,101,68,101,115,99,114,105,112,116,105,111,110,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32, | |||
| 32,32,32,67,111,109,112,111,110,101,110,116,42,32,115,111,117,114,99,101,67,111,109,112,111,110,101,110,116,44,13,10,32,32,32,32,32,32,32,32, | |||
| 32,32,32,32,32,32,32,32,32,32,32,32,32,32,105,110,116,32,120,44,32,105,110,116,32,121,41,13,10,32,32,32,32,123,13,10,32,32,32,32, | |||
| 32,32,32,32,109,101,115,115,97,103,101,32,61,32,84,40,34,108,97,115,116,32,114,111,119,115,32,100,114,111,112,112,101,100,58,32,34,41,32,43, | |||
| 32,115,111,117,114,99,101,68,101,115,99,114,105,112,116,105,111,110,59,13,10,13,10,32,32,32,32,32,32,32,32,115,111,109,101,116,104,105,110,103, | |||
| 73,115,66,101,105,110,103,68,114,97,103,103,101,100,79,118,101,114,32,61,32,102,97,108,115,101,59,13,10,32,32,32,32,32,32,32,32,114,101,112, | |||
| 97,105,110,116,40,41,59,13,10,32,32,32,32,125,13,10,125,59,13,10,13,10,13,10,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61, | |||
| 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, | |||
| 13,10,99,108,97,115,115,32,68,114,97,103,65,110,100,68,114,111,112,68,101,109,111,32,32,58,32,112,117,98,108,105,99,32,67,111,109,112,111,110, | |||
| 101,110,116,44,13,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,112,117,98,108,105,99,32,68,114, | |||
| 97,103,65,110,100,68,114,111,112,67,111,110,116,97,105,110,101,114,13,10,123,13,10,32,32,32,32,47,47,61,61,61,61,61,61,61,61,61,61,61, | |||
| 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,99,108,97,115,115,32,68,114,97,103,65,110,100,68, | |||
| 114,111,112,68,101,109,111,32,32,58,32,112,117,98,108,105,99,32,67,111,109,112,111,110,101,110,116,44,13,10,32,32,32,32,32,32,32,32,32,32, | |||
| 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,112,117,98,108,105,99,32,68,114,97,103,65,110,100,68,114,111,112,67,111,110,116,97,105,110, | |||
| 101,114,13,10,123,13,10,32,32,32,32,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, | |||
| 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, | |||
| 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,68,114,97,103,65,110,100, | |||
| 68,114,111,112,68,101,109,111,83,111,117,114,99,101,42,32,115,111,117,114,99,101,59,13,10,32,32,32,32,68,114,97,103,65,110,100,68,114,111,112, | |||
| 68,101,109,111,84,97,114,103,101,116,42,32,116,97,114,103,101,116,59,13,10,13,10,112,117,98,108,105,99,58,13,10,32,32,32,32,47,47,61,61, | |||
| 61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,68,114,97,103,65,110,100,68,114,111,112,68,101,109,111,83,111,117,114,99,101,42,32, | |||
| 115,111,117,114,99,101,59,13,10,32,32,32,32,68,114,97,103,65,110,100,68,114,111,112,68,101,109,111,84,97,114,103,101,116,42,32,116,97,114,103, | |||
| 101,116,59,13,10,13,10,112,117,98,108,105,99,58,13,10,32,32,32,32,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, | |||
| 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, | |||
| 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,32,32, | |||
| 32,32,68,114,97,103,65,110,100,68,114,111,112,68,101,109,111,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,115,101,116,78, | |||
| 97,109,101,32,40,84,40,34,68,114,97,103,45,97,110,100,45,68,114,111,112,34,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,115,111,117, | |||
| 114,99,101,32,61,32,110,101,119,32,68,114,97,103,65,110,100,68,114,111,112,68,101,109,111,83,111,117,114,99,101,40,41,59,13,10,32,32,32,32, | |||
| 32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,115,111,117,114,99,101,41,59,13,10,13,10,32,32,32,32,32, | |||
| 32,32,32,116,97,114,103,101,116,32,61,32,110,101,119,32,68,114,97,103,65,110,100,68,114,111,112,68,101,109,111,84,97,114,103,101,116,40,41,59, | |||
| 13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105,115,105,98,108,101,32,40,116,97,114,103,101,116,41,59,13,10,32, | |||
| 32,32,32,125,13,10,13,10,32,32,32,32,126,68,114,97,103,65,110,100,68,114,111,112,68,101,109,111,40,41,13,10,32,32,32,32,123,13,10,32, | |||
| 32,32,32,32,32,32,32,100,101,108,101,116,101,65,108,108,67,104,105,108,100,114,101,110,40,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32, | |||
| 32,32,118,111,105,100,32,114,101,115,105,122,101,100,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,115,111,117,114,99,101,45, | |||
| 62,115,101,116,66,111,117,110,100,115,32,40,49,48,44,32,49,48,44,32,50,53,48,44,32,49,53,48,41,59,13,10,32,32,32,32,32,32,32,32, | |||
| 116,97,114,103,101,116,45,62,115,101,116,66,111,117,110,100,115,32,40,103,101,116,87,105,100,116,104,40,41,32,45,32,50,54,48,44,32,103,101,116, | |||
| 72,101,105,103,104,116,40,41,32,45,32,49,54,48,44,32,50,53,48,44,32,49,53,48,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32, | |||
| 32,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, | |||
| 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,68,114,97,103,65,110,100,68,114,111,112,68,101,109, | |||
| 111,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,115,101,116,78,97,109,101,32,40,84,40,34,68,114,97,103,45,97,110,100, | |||
| 45,68,114,111,112,34,41,41,59,13,10,13,10,32,32,32,32,32,32,32,32,115,111,117,114,99,101,32,61,32,110,101,119,32,68,114,97,103,65,110, | |||
| 100,68,114,111,112,68,101,109,111,83,111,117,114,99,101,40,41,59,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100,77,97,107,101,86,105, | |||
| 115,105,98,108,101,32,40,115,111,117,114,99,101,41,59,13,10,13,10,32,32,32,32,32,32,32,32,116,97,114,103,101,116,32,61,32,110,101,119,32, | |||
| 68,114,97,103,65,110,100,68,114,111,112,68,101,109,111,84,97,114,103,101,116,40,41,59,13,10,32,32,32,32,32,32,32,32,97,100,100,65,110,100, | |||
| 77,97,107,101,86,105,115,105,98,108,101,32,40,116,97,114,103,101,116,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,126,68,114,97, | |||
| 103,65,110,100,68,114,111,112,68,101,109,111,40,41,13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,100,101,108,101,116,101,65,108,108, | |||
| 67,104,105,108,100,114,101,110,40,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,118,111,105,100,32,114,101,115,105,122,101,100,40,41, | |||
| 13,10,32,32,32,32,123,13,10,32,32,32,32,32,32,32,32,115,111,117,114,99,101,45,62,115,101,116,66,111,117,110,100,115,32,40,49,48,44,32, | |||
| 49,48,44,32,50,53,48,44,32,49,53,48,41,59,13,10,32,32,32,32,32,32,32,32,116,97,114,103,101,116,45,62,115,101,116,66,111,117,110,100, | |||
| 115,32,40,103,101,116,87,105,100,116,104,40,41,32,45,32,50,54,48,44,32,103,101,116,72,101,105,103,104,116,40,41,32,45,32,49,54,48,44,32, | |||
| 50,53,48,44,32,49,53,48,41,59,13,10,32,32,32,32,125,13,10,13,10,32,32,32,32,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61, | |||
| 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, | |||
| 61,13,10,32,32,32,32,47,47,32,40,110,101,101,100,32,116,111,32,112,117,116,32,116,104,105,115,32,105,110,32,116,111,32,100,105,115,97,109,98, | |||
| 105,103,117,97,116,101,32,116,104,101,32,110,101,119,47,100,101,108,101,116,101,32,111,112,101,114,97,116,111,114,115,32,117,115,101,100,32,105,110,32, | |||
| 116,104,101,13,10,32,32,32,32,47,47,32,116,119,111,32,98,97,115,101,32,99,108,97,115,115,101,115,41,46,13,10,32,32,32,32,106,117,99,101, | |||
| 95,85,115,101,68,101,98,117,103,103,105,110,103,78,101,119,79,112,101,114,97,116,111,114,13,10,125,59,13,10,13,10,13,10,47,47,61,61,61,61, | |||
| 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,32,32,32,32,47,47,32,40,110,101,101,100,32, | |||
| 116,111,32,112,117,116,32,116,104,105,115,32,105,110,32,116,111,32,100,105,115,97,109,98,105,103,117,97,116,101,32,116,104,101,32,110,101,119,47,100, | |||
| 101,108,101,116,101,32,111,112,101,114,97,116,111,114,115,32,117,115,101,100,32,105,110,32,116,104,101,13,10,32,32,32,32,47,47,32,116,119,111,32, | |||
| 98,97,115,101,32,99,108,97,115,115,101,115,41,46,13,10,32,32,32,32,106,117,99,101,95,85,115,101,68,101,98,117,103,103,105,110,103,78,101,119, | |||
| 79,112,101,114,97,116,111,114,13,10,125,59,13,10,13,10,13,10,47,47,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, | |||
| 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, | |||
| 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,67,111,109,112, | |||
| 111,110,101,110,116,42,32,99,114,101,97,116,101,68,114,97,103,65,110,100,68,114,111,112,68,101,109,111,40,41,13,10,123,13,10,32,32,32,32,114, | |||
| 101,116,117,114,110,32,110,101,119,32,68,114,97,103,65,110,100,68,114,111,112,68,101,109,111,40,41,59,13,10,125,13,10,0,0}; | |||
| 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,13,10,67,111,109,112,111,110,101,110,116,42,32,99,114,101,97,116,101,68,114,97, | |||
| 103,65,110,100,68,114,111,112,68,101,109,111,40,41,13,10,123,13,10,32,32,32,32,114,101,116,117,114,110,32,110,101,119,32,68,114,97,103,65,110, | |||
| 100,68,114,111,112,68,101,109,111,40,41,59,13,10,125,13,10,0,0}; | |||
| const char* BinaryData::draganddropdemo_cpp = (const char*) temp4; | |||
| static const unsigned char temp5[] = {47,42,13,10,32,32,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, | |||
| @@ -15,7 +15,7 @@ namespace BinaryData | |||
| const int demo_table_data_xmlSize = 5239; | |||
| extern const char* draganddropdemo_cpp; | |||
| const int draganddropdemo_cppSize = 7873; | |||
| const int draganddropdemo_cppSize = 7937; | |||
| extern const char* fontsandtextdemo_cpp; | |||
| const int fontsandtextdemo_cppSize = 9064; | |||
| @@ -342,7 +342,7 @@ public: | |||
| } | |||
| } | |||
| void audioDeviceAboutToStart (double sampleRate, int numSamplesPerBlock) | |||
| void audioDeviceAboutToStart (AudioIODevice*) | |||
| { | |||
| zeromem (circularBuffer, sizeof (float) * bufferSize); | |||
| } | |||
| @@ -504,10 +504,10 @@ public: | |||
| waveformComponent->audioDeviceIOCallback (inputChannelData, totalNumInputChannels, outputChannelData, totalNumOutputChannels, numSamples); | |||
| } | |||
| void audioDeviceAboutToStart (double sampleRate, int numSamplesPerBlock) | |||
| void audioDeviceAboutToStart (AudioIODevice* device) | |||
| { | |||
| audioSourcePlayer.audioDeviceAboutToStart (sampleRate, numSamplesPerBlock); | |||
| waveformComponent->audioDeviceAboutToStart (sampleRate, numSamplesPerBlock); | |||
| audioSourcePlayer.audioDeviceAboutToStart (device); | |||
| waveformComponent->audioDeviceAboutToStart (device); | |||
| } | |||
| void audioDeviceStopped() | |||
| @@ -152,7 +152,8 @@ public: | |||
| } | |||
| //============================================================================== | |||
| bool isInterestedInDragSource (const String& sourceDescription) | |||
| bool isInterestedInDragSource (const String& sourceDescription, | |||
| Component* sourceComponent) | |||
| { | |||
| // normally you'd check the sourceDescription value to see if it's the | |||
| // sort of object that you're interested in before returning true, but for | |||
| @@ -342,7 +342,7 @@ public: | |||
| } | |||
| } | |||
| void audioDeviceAboutToStart (double sampleRate, int numSamplesPerBlock) | |||
| void audioDeviceAboutToStart (AudioIODevice*) | |||
| { | |||
| zeromem (circularBuffer, sizeof (float) * bufferSize); | |||
| } | |||
| @@ -504,10 +504,10 @@ public: | |||
| waveformComponent->audioDeviceIOCallback (inputChannelData, totalNumInputChannels, outputChannelData, totalNumOutputChannels, numSamples); | |||
| } | |||
| void audioDeviceAboutToStart (double sampleRate, int numSamplesPerBlock) | |||
| void audioDeviceAboutToStart (AudioIODevice* device) | |||
| { | |||
| audioSourcePlayer.audioDeviceAboutToStart (sampleRate, numSamplesPerBlock); | |||
| waveformComponent->audioDeviceAboutToStart (sampleRate, numSamplesPerBlock); | |||
| audioSourcePlayer.audioDeviceAboutToStart (device); | |||
| waveformComponent->audioDeviceAboutToStart (device); | |||
| } | |||
| void audioDeviceStopped() | |||
| @@ -152,7 +152,8 @@ public: | |||
| } | |||
| //============================================================================== | |||
| bool isInterestedInDragSource (const String& sourceDescription) | |||
| bool isInterestedInDragSource (const String& sourceDescription, | |||
| Component* sourceComponent) | |||
| { | |||
| // normally you'd check the sourceDescription value to see if it's the | |||
| // sort of object that you're interested in before returning true, but for | |||
| @@ -169,6 +169,7 @@ END_JUCE_NAMESPACE | |||
| #pragma comment(lib, "ole32.lib") | |||
| #pragma comment(lib, "advapi32.lib") | |||
| #pragma comment(lib, "ws2_32.lib") | |||
| #pragma comment(lib, "SetupAPI.Lib") | |||
| //#pragma comment(lib, "gdiplus.lib") | |||
| #if JUCE_OPENGL | |||
| @@ -137,6 +137,16 @@ | |||
| #define JUCE_USE_XSHM 1 | |||
| #endif | |||
| //============================================================================= | |||
| /** Enabling this builds support for VST audio plugins. | |||
| @see VSTPluginFormat, AudioPluginFormat, AudioPluginFormatManager, JUCE_PLUGINHOST_AU | |||
| */ | |||
| #define JUCE_PLUGINHOST_VST 1 | |||
| /** Enabling this builds support for AudioUnit audio plugins. | |||
| @see AudioUnitPluginFormat, AudioPluginFormat, AudioPluginFormatManager, JUCE_PLUGINHOST_VST | |||
| */ | |||
| #define JUCE_PLUGINHOST_AU 1 | |||
| //============================================================================= | |||
| /** Disabling this will avoid linking to any UI code. This is handy for | |||
| @@ -95,9 +95,15 @@ | |||
| #ifndef __JUCE_AUDIOPROCESSOREDITOR_JUCEHEADER__ | |||
| #include "juce_appframework/audio/processors/juce_AudioProcessorEditor.h" | |||
| #endif | |||
| #ifndef __JUCE_AUDIOPROCESSORGRAPH_JUCEHEADER__ | |||
| #include "juce_appframework/audio/processors/juce_AudioProcessorGraph.h" | |||
| #endif | |||
| #ifndef __JUCE_AUDIOPROCESSORLISTENER_JUCEHEADER__ | |||
| #include "juce_appframework/audio/processors/juce_AudioProcessorListener.h" | |||
| #endif | |||
| #ifndef __JUCE_AUDIOPROCESSORPLAYER_JUCEHEADER__ | |||
| #include "juce_appframework/audio/processors/juce_AudioProcessorPlayer.h" | |||
| #endif | |||
| #ifndef __JUCE_GENERICAUDIOPROCESSOREDITOR_JUCEHEADER__ | |||
| #include "juce_appframework/audio/processors/juce_GenericAudioProcessorEditor.h" | |||
| #endif | |||
| @@ -155,6 +161,39 @@ | |||
| #ifndef __JUCE_SYNTHESISER_JUCEHEADER__ | |||
| #include "juce_appframework/audio/synthesisers/juce_Synthesiser.h" | |||
| #endif | |||
| #ifndef __JUCE_AUDIOUNITPLUGINFORMAT_JUCEHEADER__ | |||
| #include "juce_appframework/audio/plugins/formats/juce_AudioUnitPluginFormat.h" | |||
| #endif | |||
| #ifndef __JUCE_DIRECTXPLUGINFORMAT_JUCEHEADER__ | |||
| #include "juce_appframework/audio/plugins/formats/juce_DirectXPluginFormat.h" | |||
| #endif | |||
| #ifndef __JUCE_LADSPAPLUGINFORMAT_JUCEHEADER__ | |||
| #include "juce_appframework/audio/plugins/formats/juce_LADSPAPluginFormat.h" | |||
| #endif | |||
| #ifndef __JUCE_VSTPLUGINFORMAT_JUCEHEADER__ | |||
| #include "juce_appframework/audio/plugins/formats/juce_VSTPluginFormat.h" | |||
| #endif | |||
| #ifndef __JUCE_AUDIOPLUGINFORMAT_JUCEHEADER__ | |||
| #include "juce_appframework/audio/plugins/juce_AudioPluginFormat.h" | |||
| #endif | |||
| #ifndef __JUCE_AUDIOPLUGINFORMATMANAGER_JUCEHEADER__ | |||
| #include "juce_appframework/audio/plugins/juce_AudioPluginFormatManager.h" | |||
| #endif | |||
| #ifndef __JUCE_AUDIOPLUGININSTANCE_JUCEHEADER__ | |||
| #include "juce_appframework/audio/plugins/juce_AudioPluginInstance.h" | |||
| #endif | |||
| #ifndef __JUCE_KNOWNPLUGINLIST_JUCEHEADER__ | |||
| #include "juce_appframework/audio/plugins/juce_KnownPluginList.h" | |||
| #endif | |||
| #ifndef __JUCE_PLUGINDESCRIPTION_JUCEHEADER__ | |||
| #include "juce_appframework/audio/plugins/juce_PluginDescription.h" | |||
| #endif | |||
| #ifndef __JUCE_PLUGINDIRECTORYSCANNER_JUCEHEADER__ | |||
| #include "juce_appframework/audio/plugins/juce_PluginDirectoryScanner.h" | |||
| #endif | |||
| #ifndef __JUCE_PLUGINLISTCOMPONENT_JUCEHEADER__ | |||
| #include "juce_appframework/audio/plugins/juce_PluginListComponent.h" | |||
| #endif | |||
| #ifndef __JUCE_AIFFAUDIOFORMAT_JUCEHEADER__ | |||
| #include "juce_appframework/audio/audio_file_formats/juce_AiffAudioFormat.h" | |||
| #endif | |||
| @@ -0,0 +1,67 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-7 by Raw Material Software ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the | |||
| GNU General Public License, as published by the Free Software Foundation; | |||
| either version 2 of the License, or (at your option) any later version. | |||
| JUCE is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with JUCE; if not, visit www.gnu.org/licenses or write to the | |||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||
| Boston, MA 02111-1307 USA | |||
| ------------------------------------------------------------------------------ | |||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||
| more information. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef __JUCE_AUDIOUNITPLUGINFORMAT_JUCEHEADER__ | |||
| #define __JUCE_AUDIOUNITPLUGINFORMAT_JUCEHEADER__ | |||
| #include "../juce_AudioPluginFormat.h" | |||
| #if JUCE_PLUGINHOST_AU && JUCE_MAC | |||
| //============================================================================== | |||
| /** | |||
| Implements a plugin format manager for AudioUnits. | |||
| */ | |||
| class JUCE_API AudioUnitPluginFormat : public AudioPluginFormat | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| AudioUnitPluginFormat(); | |||
| ~AudioUnitPluginFormat(); | |||
| //============================================================================== | |||
| const String getName() const { return "AudioUnit"; } | |||
| void findAllTypesForFile (OwnedArray <PluginDescription>& results, const File& file); | |||
| AudioPluginInstance* createInstanceFromDescription (const PluginDescription& desc); | |||
| bool fileMightContainThisPluginType (const File& file); | |||
| const FileSearchPath getDefaultLocationsToSearch(); | |||
| //============================================================================== | |||
| juce_UseDebuggingNewOperator | |||
| private: | |||
| AudioUnitPluginFormat (const AudioUnitPluginFormat&); | |||
| const AudioUnitPluginFormat& operator= (const AudioUnitPluginFormat&); | |||
| }; | |||
| #endif | |||
| #endif // __JUCE_AUDIOUNITPLUGINFORMAT_JUCEHEADER__ | |||
| @@ -0,0 +1,71 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-7 by Raw Material Software ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the | |||
| GNU General Public License, as published by the Free Software Foundation; | |||
| either version 2 of the License, or (at your option) any later version. | |||
| JUCE is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with JUCE; if not, visit www.gnu.org/licenses or write to the | |||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||
| Boston, MA 02111-1307 USA | |||
| ------------------------------------------------------------------------------ | |||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||
| more information. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef __JUCE_DIRECTXPLUGINFORMAT_JUCEHEADER__ | |||
| #define __JUCE_DIRECTXPLUGINFORMAT_JUCEHEADER__ | |||
| #include "../juce_AudioPluginFormat.h" | |||
| #if JUCE_PLUGINHOST_DX && JUCE_WIN32 | |||
| // Sorry, this file is just a placeholder at the moment!... | |||
| //============================================================================== | |||
| /** | |||
| Implements a plugin format manager for DirectX plugins. | |||
| */ | |||
| class JUCE_API DirectXPluginFormat : public AudioPluginFormat | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| DirectXPluginFormat(); | |||
| ~DirectXPluginFormat(); | |||
| //============================================================================== | |||
| const String getName() const { return "DirectX"; } | |||
| void findAllTypesForFile (OwnedArray <PluginDescription>& results, const File& file); | |||
| AudioPluginInstance* createInstanceFromDescription (const PluginDescription& desc); | |||
| bool fileMightContainThisPluginType (const File& file); | |||
| const FileSearchPath getDefaultLocationsToSearch(); | |||
| //============================================================================== | |||
| juce_UseDebuggingNewOperator | |||
| private: | |||
| DirectXPluginFormat (const DirectXPluginFormat&); | |||
| const DirectXPluginFormat& operator= (const DirectXPluginFormat&); | |||
| }; | |||
| #endif | |||
| #endif // __JUCE_DIRECTXPLUGINFORMAT_JUCEHEADER__ | |||
| @@ -0,0 +1,71 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-7 by Raw Material Software ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the | |||
| GNU General Public License, as published by the Free Software Foundation; | |||
| either version 2 of the License, or (at your option) any later version. | |||
| JUCE is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with JUCE; if not, visit www.gnu.org/licenses or write to the | |||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||
| Boston, MA 02111-1307 USA | |||
| ------------------------------------------------------------------------------ | |||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||
| more information. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef __JUCE_LADSPAPLUGINFORMAT_JUCEHEADER__ | |||
| #define __JUCE_LADSPAPLUGINFORMAT_JUCEHEADER__ | |||
| #include "../juce_AudioPluginFormat.h" | |||
| #if JUCE_PLUGINHOST_LADSPA && JUCE_LINUX | |||
| // Sorry, this file is just a placeholder at the moment!... | |||
| //============================================================================== | |||
| /** | |||
| Implements a plugin format manager for DirectX plugins. | |||
| */ | |||
| class JUCE_API LADSPAPluginFormat : public AudioPluginFormat | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| LADSPAPluginFormat(); | |||
| ~LADSPAPluginFormat(); | |||
| //============================================================================== | |||
| const String getName() const { return "LADSPA"; } | |||
| void findAllTypesForFile (OwnedArray <PluginDescription>& results, const File& file); | |||
| AudioPluginInstance* createInstanceFromDescription (const PluginDescription& desc); | |||
| bool fileMightContainThisPluginType (const File& file); | |||
| const FileSearchPath getDefaultLocationsToSearch(); | |||
| //============================================================================== | |||
| juce_UseDebuggingNewOperator | |||
| private: | |||
| LADSPAPluginFormat (const LADSPAPluginFormat&); | |||
| const LADSPAPluginFormat& operator= (const LADSPAPluginFormat&); | |||
| }; | |||
| #endif | |||
| #endif // __JUCE_LADSPAPLUGINFORMAT_JUCEHEADER__ | |||
| @@ -0,0 +1,68 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-7 by Raw Material Software ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the | |||
| GNU General Public License, as published by the Free Software Foundation; | |||
| either version 2 of the License, or (at your option) any later version. | |||
| JUCE is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with JUCE; if not, visit www.gnu.org/licenses or write to the | |||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||
| Boston, MA 02111-1307 USA | |||
| ------------------------------------------------------------------------------ | |||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||
| more information. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef __JUCE_VSTPLUGINFORMAT_JUCEHEADER__ | |||
| #define __JUCE_VSTPLUGINFORMAT_JUCEHEADER__ | |||
| #include "../juce_AudioPluginFormat.h" | |||
| #if JUCE_PLUGINHOST_VST | |||
| //============================================================================== | |||
| /** | |||
| Implements a plugin format manager for VSTs. | |||
| */ | |||
| class JUCE_API VSTPluginFormat : public AudioPluginFormat | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| VSTPluginFormat(); | |||
| ~VSTPluginFormat(); | |||
| //============================================================================== | |||
| const String getName() const { return "VST"; } | |||
| void findAllTypesForFile (OwnedArray <PluginDescription>& results, const File& file); | |||
| AudioPluginInstance* createInstanceFromDescription (const PluginDescription& desc); | |||
| bool fileMightContainThisPluginType (const File& file); | |||
| const FileSearchPath getDefaultLocationsToSearch(); | |||
| //============================================================================== | |||
| juce_UseDebuggingNewOperator | |||
| private: | |||
| VSTPluginFormat (const VSTPluginFormat&); | |||
| const VSTPluginFormat& operator= (const VSTPluginFormat&); | |||
| }; | |||
| #endif | |||
| #endif // __JUCE_VSTPLUGINFORMAT_JUCEHEADER__ | |||
| @@ -0,0 +1,49 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-7 by Raw Material Software ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the | |||
| GNU General Public License, as published by the Free Software Foundation; | |||
| either version 2 of the License, or (at your option) any later version. | |||
| JUCE is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with JUCE; if not, visit www.gnu.org/licenses or write to the | |||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||
| Boston, MA 02111-1307 USA | |||
| ------------------------------------------------------------------------------ | |||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||
| more information. | |||
| ============================================================================== | |||
| */ | |||
| #include "../../../juce_core/basics/juce_StandardHeader.h" | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_AudioPluginFormat.h" | |||
| //============================================================================== | |||
| AudioPluginFormat::AudioPluginFormat() throw() | |||
| { | |||
| } | |||
| AudioPluginFormat::~AudioPluginFormat() throw() | |||
| { | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| @@ -0,0 +1,107 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-7 by Raw Material Software ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the | |||
| GNU General Public License, as published by the Free Software Foundation; | |||
| either version 2 of the License, or (at your option) any later version. | |||
| JUCE is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with JUCE; if not, visit www.gnu.org/licenses or write to the | |||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||
| Boston, MA 02111-1307 USA | |||
| ------------------------------------------------------------------------------ | |||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||
| more information. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef __JUCE_AUDIOPLUGINFORMAT_JUCEHEADER__ | |||
| #define __JUCE_AUDIOPLUGINFORMAT_JUCEHEADER__ | |||
| #include "juce_AudioPluginInstance.h" | |||
| #include "../../../juce_core/io/files/juce_FileSearchPath.h" | |||
| class PluginDescription; | |||
| //============================================================================== | |||
| /** | |||
| The base class for a type of plugin format, such as VST, AudioUnit, LADSPA, etc. | |||
| Use the static getNumFormats() and getFormat() calls to find the types | |||
| of format that are available. | |||
| */ | |||
| class JUCE_API AudioPluginFormat | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| /** Destructor. */ | |||
| virtual ~AudioPluginFormat(); | |||
| //============================================================================== | |||
| /** Returns the format name. | |||
| E.g. "VST", "AudioUnit", etc. | |||
| */ | |||
| virtual const String getName() const = 0; | |||
| /** This tries to create descriptions for all the plugin types available in | |||
| a binary module file. | |||
| The file will be some kind of DLL or bundle. | |||
| Normally there will only be one type returned, but some plugins | |||
| (e.g. VST shells) can use a single DLL to create a set of different plugin | |||
| subtypes, so in that case, each subtype is returned as a separate object. | |||
| */ | |||
| virtual void findAllTypesForFile (OwnedArray <PluginDescription>& results, | |||
| const File& file) = 0; | |||
| /** Tries to recreate a type from a previously generated PluginDescription. | |||
| @see PluginDescription::createInstance | |||
| */ | |||
| virtual AudioPluginInstance* createInstanceFromDescription (const PluginDescription& desc) = 0; | |||
| /** Should do a quick check to see if this file or directory might be a plugin of | |||
| this format. | |||
| This is for searching for potential files, so it shouldn't actually try to | |||
| load the plugin or do anything time-consuming. | |||
| */ | |||
| virtual bool fileMightContainThisPluginType (const File& file) = 0; | |||
| /** Returns the typical places to look for this kind of plugin. | |||
| Note that if this returns no paths, it means that the format can't be scanned-for | |||
| (i.e. it's an internal format that doesn't live in files) | |||
| */ | |||
| virtual const FileSearchPath getDefaultLocationsToSearch() = 0; | |||
| //============================================================================== | |||
| juce_UseDebuggingNewOperator | |||
| protected: | |||
| AudioPluginFormat() throw(); | |||
| AudioPluginFormat (const AudioPluginFormat&); | |||
| const AudioPluginFormat& operator= (const AudioPluginFormat&); | |||
| }; | |||
| #endif // __JUCE_AUDIOPLUGINFORMAT_JUCEHEADER__ | |||
| @@ -0,0 +1,138 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-7 by Raw Material Software ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the | |||
| GNU General Public License, as published by the Free Software Foundation; | |||
| either version 2 of the License, or (at your option) any later version. | |||
| JUCE is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with JUCE; if not, visit www.gnu.org/licenses or write to the | |||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||
| Boston, MA 02111-1307 USA | |||
| ------------------------------------------------------------------------------ | |||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||
| more information. | |||
| ============================================================================== | |||
| */ | |||
| #include "../../../juce_core/basics/juce_StandardHeader.h" | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_AudioPluginFormatManager.h" | |||
| #include "juce_PluginDescription.h" | |||
| #include "../../../juce_core/text/juce_LocalisedStrings.h" | |||
| #include "formats/juce_VSTPluginFormat.h" | |||
| #include "formats/juce_AudioUnitPluginFormat.h" | |||
| #include "formats/juce_DirectXPluginFormat.h" | |||
| #include "formats/juce_LADSPAPluginFormat.h" | |||
| //============================================================================== | |||
| AudioPluginFormatManager::AudioPluginFormatManager() throw() | |||
| { | |||
| } | |||
| AudioPluginFormatManager::~AudioPluginFormatManager() throw() | |||
| { | |||
| } | |||
| juce_ImplementSingleton_SingleThreaded (AudioPluginFormatManager); | |||
| //============================================================================== | |||
| void AudioPluginFormatManager::addDefaultFormats() | |||
| { | |||
| #ifdef JUCE_DEBUG | |||
| // you should only call this method once! | |||
| for (int i = formats.size(); --i >= 0;) | |||
| { | |||
| #if JUCE_PLUGINHOST_VST | |||
| jassert (dynamic_cast <VSTPluginFormat*> (formats[i]) == 0); | |||
| #endif | |||
| #if JUCE_PLUGINHOST_AU && JUCE_MAC | |||
| jassert (dynamic_cast <AudioUnitPluginFormat*> (formats[i]) == 0); | |||
| #endif | |||
| #if JUCE_PLUGINHOST_DX && JUCE_WIN32 | |||
| jassert (dynamic_cast <DirectXPluginFormat*> (formats[i]) == 0); | |||
| #endif | |||
| #if JUCE_PLUGINHOST_LADSPA && JUCE_LINUX | |||
| jassert (dynamic_cast <LADSPAPluginFormat*> (formats[i]) == 0); | |||
| #endif | |||
| } | |||
| #endif | |||
| #if JUCE_PLUGINHOST_VST | |||
| formats.add (new VSTPluginFormat()); | |||
| #endif | |||
| #if JUCE_PLUGINHOST_AU && JUCE_MAC | |||
| formats.add (new AudioUnitPluginFormat()); | |||
| #endif | |||
| #if JUCE_PLUGINHOST_DX && JUCE_WIN32 | |||
| formats.add (new DirectXPluginFormat()); | |||
| #endif | |||
| #if JUCE_PLUGINHOST_LADSPA && JUCE_LINUX | |||
| formats.add (new LADSPAPluginFormat()); | |||
| #endif | |||
| } | |||
| int AudioPluginFormatManager::getNumFormats() throw() | |||
| { | |||
| return formats.size(); | |||
| } | |||
| AudioPluginFormat* AudioPluginFormatManager::getFormat (const int index) throw() | |||
| { | |||
| return formats [index]; | |||
| } | |||
| void AudioPluginFormatManager::addFormat (AudioPluginFormat* const format) throw() | |||
| { | |||
| formats.add (format); | |||
| } | |||
| AudioPluginInstance* AudioPluginFormatManager::createPluginInstance (const PluginDescription& description, | |||
| String& errorMessage) const | |||
| { | |||
| AudioPluginInstance* result = 0; | |||
| for (int i = 0; i < formats.size(); ++i) | |||
| { | |||
| result = formats.getUnchecked(i)->createInstanceFromDescription (description); | |||
| if (result != 0) | |||
| break; | |||
| } | |||
| if (result == 0) | |||
| { | |||
| if (description.file != File::nonexistent && ! description.file.exists()) | |||
| errorMessage = TRANS ("This plug-in file no longer exists"); | |||
| else | |||
| errorMessage = TRANS ("This plug-in failed to load correctly"); | |||
| } | |||
| return result; | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| @@ -0,0 +1,107 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-7 by Raw Material Software ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the | |||
| GNU General Public License, as published by the Free Software Foundation; | |||
| either version 2 of the License, or (at your option) any later version. | |||
| JUCE is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with JUCE; if not, visit www.gnu.org/licenses or write to the | |||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||
| Boston, MA 02111-1307 USA | |||
| ------------------------------------------------------------------------------ | |||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||
| more information. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef __JUCE_AUDIOPLUGINFORMATMANAGER_JUCEHEADER__ | |||
| #define __JUCE_AUDIOPLUGINFORMATMANAGER_JUCEHEADER__ | |||
| #include "juce_AudioPluginFormat.h" | |||
| #include "../../application/juce_DeletedAtShutdown.h" | |||
| #include "../../../juce_core/basics/juce_Singleton.h" | |||
| //============================================================================== | |||
| /** | |||
| This maintains a list of known AudioPluginFormats. | |||
| @see AudioPluginFormat | |||
| */ | |||
| class JUCE_API AudioPluginFormatManager : public DeletedAtShutdown | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| AudioPluginFormatManager() throw(); | |||
| /** Destructor. */ | |||
| ~AudioPluginFormatManager() throw(); | |||
| juce_DeclareSingleton_SingleThreaded (AudioPluginFormatManager, false); | |||
| //============================================================================== | |||
| /** Adds any formats that it knows about, e.g. VST. | |||
| */ | |||
| void addDefaultFormats(); | |||
| //============================================================================== | |||
| /** Returns the number of types of format that are available. | |||
| Use getFormat() to get one of them. | |||
| */ | |||
| int getNumFormats() throw(); | |||
| /** Returns one of the available formats. | |||
| @see getNumFormats | |||
| */ | |||
| AudioPluginFormat* getFormat (const int index) throw(); | |||
| //============================================================================== | |||
| /** Adds a format to the list. | |||
| The object passed in will be owned and deleted by the manager. | |||
| */ | |||
| void addFormat (AudioPluginFormat* const format) throw(); | |||
| //============================================================================== | |||
| /** Tries to load the type for this description, by trying all the formats | |||
| that this manager knows about. | |||
| The caller is responsible for deleting the object that is returned. | |||
| If it can't load the plugin, it returns 0 and leaves a message in the | |||
| errorMessage string. | |||
| */ | |||
| AudioPluginInstance* createPluginInstance (const PluginDescription& description, | |||
| String& errorMessage) const; | |||
| //============================================================================== | |||
| juce_UseDebuggingNewOperator | |||
| private: | |||
| OwnedArray <AudioPluginFormat> formats; | |||
| AudioPluginFormatManager (const AudioPluginFormatManager&); | |||
| const AudioPluginFormatManager& operator= (const AudioPluginFormatManager&); | |||
| }; | |||
| #endif // __JUCE_AUDIOPLUGINFORMATMANAGER_JUCEHEADER__ | |||
| @@ -0,0 +1,51 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-7 by Raw Material Software ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the | |||
| GNU General Public License, as published by the Free Software Foundation; | |||
| either version 2 of the License, or (at your option) any later version. | |||
| JUCE is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with JUCE; if not, visit www.gnu.org/licenses or write to the | |||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||
| Boston, MA 02111-1307 USA | |||
| ------------------------------------------------------------------------------ | |||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||
| more information. | |||
| ============================================================================== | |||
| */ | |||
| #define JUCE_PLUGIN_HOST 1 | |||
| #include "../../../juce_core/basics/juce_StandardHeader.h" | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_AudioPluginInstance.h" | |||
| //============================================================================== | |||
| AudioPluginInstance::AudioPluginInstance() | |||
| { | |||
| } | |||
| AudioPluginInstance::~AudioPluginInstance() | |||
| { | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| @@ -0,0 +1,76 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-7 by Raw Material Software ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the | |||
| GNU General Public License, as published by the Free Software Foundation; | |||
| either version 2 of the License, or (at your option) any later version. | |||
| JUCE is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with JUCE; if not, visit www.gnu.org/licenses or write to the | |||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||
| Boston, MA 02111-1307 USA | |||
| ------------------------------------------------------------------------------ | |||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||
| more information. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef __JUCE_AUDIOPLUGININSTANCE_JUCEHEADER__ | |||
| #define __JUCE_AUDIOPLUGININSTANCE_JUCEHEADER__ | |||
| #include "../processors/juce_AudioProcessor.h" | |||
| #include "juce_PluginDescription.h" | |||
| //============================================================================== | |||
| /** | |||
| Base class for an active instance of a plugin. | |||
| This derives from the AudioProcessor class, and adds some extra functionality | |||
| that helps when wrapping dynamically loaded plugins. | |||
| @see AudioProcessor, AudioPluginFormat | |||
| */ | |||
| class JUCE_API AudioPluginInstance : public AudioProcessor | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| /** Destructor. | |||
| Make sure that you delete any UI components that belong to this plugin before | |||
| deleting the plugin. | |||
| */ | |||
| virtual ~AudioPluginInstance(); | |||
| //============================================================================== | |||
| /** Fills-in the appropriate parts of this plugin description object. | |||
| */ | |||
| virtual void fillInPluginDescription (PluginDescription& description) const = 0; | |||
| //============================================================================== | |||
| juce_UseDebuggingNewOperator | |||
| protected: | |||
| AudioPluginInstance(); | |||
| AudioPluginInstance (const AudioPluginInstance&); | |||
| const AudioPluginInstance& operator= (const AudioPluginInstance&); | |||
| }; | |||
| #endif // __JUCE_AUDIOPLUGININSTANCE_JUCEHEADER__ | |||
| @@ -0,0 +1,431 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-7 by Raw Material Software ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the | |||
| GNU General Public License, as published by the Free Software Foundation; | |||
| either version 2 of the License, or (at your option) any later version. | |||
| JUCE is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with JUCE; if not, visit www.gnu.org/licenses or write to the | |||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||
| Boston, MA 02111-1307 USA | |||
| ------------------------------------------------------------------------------ | |||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||
| more information. | |||
| ============================================================================== | |||
| */ | |||
| #include "../../../juce_core/basics/juce_StandardHeader.h" | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_KnownPluginList.h" | |||
| #include "juce_AudioPluginFormatManager.h" | |||
| //============================================================================== | |||
| KnownPluginList::KnownPluginList() | |||
| { | |||
| } | |||
| KnownPluginList::~KnownPluginList() | |||
| { | |||
| } | |||
| void KnownPluginList::clear() | |||
| { | |||
| if (types.size() > 0) | |||
| { | |||
| types.clear(); | |||
| sendChangeMessage (this); | |||
| } | |||
| } | |||
| PluginDescription* KnownPluginList::getTypeForFile (const File& file) const throw() | |||
| { | |||
| for (int i = 0; i < types.size(); ++i) | |||
| if (types.getUnchecked(i)->file == file) | |||
| return types.getUnchecked(i); | |||
| return 0; | |||
| } | |||
| PluginDescription* KnownPluginList::getTypeForIdentifierString (const String& identifierString) const throw() | |||
| { | |||
| for (int i = 0; i < types.size(); ++i) | |||
| if (types.getUnchecked(i)->createIdentifierString() == identifierString) | |||
| return types.getUnchecked(i); | |||
| return 0; | |||
| } | |||
| bool KnownPluginList::addType (const PluginDescription& type) | |||
| { | |||
| for (int i = types.size(); --i >= 0;) | |||
| { | |||
| if (types.getUnchecked(i)->isDuplicateOf (type)) | |||
| { | |||
| // strange - found a duplicate plugin with different info.. | |||
| jassert (types.getUnchecked(i)->name == type.name); | |||
| jassert (types.getUnchecked(i)->isInstrument == type.isInstrument); | |||
| *types.getUnchecked(i) = type; | |||
| return false; | |||
| } | |||
| } | |||
| types.add (new PluginDescription (type)); | |||
| sendChangeMessage (this); | |||
| return true; | |||
| } | |||
| void KnownPluginList::removeType (const int index) throw() | |||
| { | |||
| types.remove (index); | |||
| sendChangeMessage (this); | |||
| } | |||
| bool KnownPluginList::isListingUpToDate (const File& possiblePluginFile) const throw() | |||
| { | |||
| if (getTypeForFile (possiblePluginFile) == 0) | |||
| return false; | |||
| for (int i = types.size(); --i >= 0;) | |||
| { | |||
| const PluginDescription* const d = types.getUnchecked(i); | |||
| if (d->file == possiblePluginFile | |||
| && d->lastFileModTime != possiblePluginFile.getLastModificationTime()) | |||
| { | |||
| return false; | |||
| } | |||
| } | |||
| return true; | |||
| } | |||
| bool KnownPluginList::scanAndAddFile (const File& possiblePluginFile, | |||
| const bool dontRescanIfAlreadyInList, | |||
| OwnedArray <PluginDescription>& typesFound) | |||
| { | |||
| bool addedOne = false; | |||
| if (dontRescanIfAlreadyInList | |||
| && getTypeForFile (possiblePluginFile) != 0) | |||
| { | |||
| bool needsRescanning = false; | |||
| for (int i = types.size(); --i >= 0;) | |||
| { | |||
| const PluginDescription* const d = types.getUnchecked(i); | |||
| if (d->file == possiblePluginFile) | |||
| { | |||
| if (d->lastFileModTime != possiblePluginFile.getLastModificationTime()) | |||
| needsRescanning = true; | |||
| else | |||
| typesFound.add (new PluginDescription (*d)); | |||
| } | |||
| } | |||
| if (! needsRescanning) | |||
| return false; | |||
| } | |||
| for (int i = 0; i < AudioPluginFormatManager::getInstance()->getNumFormats(); ++i) | |||
| { | |||
| AudioPluginFormat* const format = AudioPluginFormatManager::getInstance()->getFormat (i); | |||
| OwnedArray <PluginDescription> found; | |||
| format->findAllTypesForFile (found, possiblePluginFile); | |||
| for (int i = 0; i < found.size(); ++i) | |||
| { | |||
| PluginDescription* const desc = found.getUnchecked(i); | |||
| jassert (desc != 0); | |||
| if (addType (*desc)) | |||
| addedOne = true; | |||
| typesFound.add (new PluginDescription (*desc)); | |||
| } | |||
| } | |||
| return addedOne; | |||
| } | |||
| void KnownPluginList::scanAndAddDragAndDroppedFiles (const StringArray& files, | |||
| OwnedArray <PluginDescription>& typesFound) | |||
| { | |||
| for (int i = 0; i < files.size(); ++i) | |||
| { | |||
| const File f (files [i]); | |||
| if (! scanAndAddFile (f, true, typesFound)) | |||
| { | |||
| if (f.isDirectory()) | |||
| { | |||
| StringArray s; | |||
| { | |||
| OwnedArray <File> subFiles; | |||
| f.findChildFiles (subFiles, File::findFilesAndDirectories, false); | |||
| for (int j = 0; j < subFiles.size(); ++j) | |||
| s.add (subFiles.getUnchecked (j)->getFullPathName()); | |||
| } | |||
| scanAndAddDragAndDroppedFiles (s, typesFound); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| //============================================================================== | |||
| class PluginSorter | |||
| { | |||
| public: | |||
| KnownPluginList::SortMethod method; | |||
| PluginSorter() throw() {} | |||
| int compareElements (const PluginDescription* const first, | |||
| const PluginDescription* const second) const throw() | |||
| { | |||
| int diff = 0; | |||
| if (method == KnownPluginList::sortByCategory) | |||
| diff = first->category.compareLexicographically (second->category); | |||
| else if (method == KnownPluginList::sortByManufacturer) | |||
| diff = first->manufacturerName.compareLexicographically (second->manufacturerName); | |||
| else if (method == KnownPluginList::sortByFileSystemLocation) | |||
| diff = first->file.getParentDirectory().getFullPathName().compare (second->file.getParentDirectory().getFullPathName()); | |||
| if (diff == 0) | |||
| diff = first->name.compareLexicographically (second->name); | |||
| return diff; | |||
| } | |||
| }; | |||
| void KnownPluginList::sort (const SortMethod method) | |||
| { | |||
| if (method != defaultOrder) | |||
| { | |||
| PluginSorter sorter; | |||
| sorter.method = method; | |||
| types.sort (sorter, true); | |||
| sendChangeMessage (this); | |||
| } | |||
| } | |||
| //============================================================================== | |||
| XmlElement* KnownPluginList::createXml() const | |||
| { | |||
| XmlElement* const e = new XmlElement (T("KNOWNPLUGINS")); | |||
| for (int i = 0; i < types.size(); ++i) | |||
| e->addChildElement (types.getUnchecked(i)->createXml()); | |||
| return e; | |||
| } | |||
| void KnownPluginList::recreateFromXml (const XmlElement& xml) | |||
| { | |||
| clear(); | |||
| if (xml.hasTagName (T("KNOWNPLUGINS"))) | |||
| { | |||
| forEachXmlChildElement (xml, e) | |||
| { | |||
| PluginDescription info; | |||
| if (info.loadFromXml (*e)) | |||
| addType (info); | |||
| } | |||
| } | |||
| } | |||
| //============================================================================== | |||
| const int menuIdBase = 0x324503f4; | |||
| // This is used to turn a bunch of paths into a nested menu structure. | |||
| struct PluginFilesystemTree | |||
| { | |||
| private: | |||
| String folder; | |||
| OwnedArray <PluginFilesystemTree> subFolders; | |||
| Array <PluginDescription*> plugins; | |||
| void addPlugin (PluginDescription* const pd, const String& path) | |||
| { | |||
| if (path.isEmpty()) | |||
| { | |||
| plugins.add (pd); | |||
| } | |||
| else | |||
| { | |||
| const String firstSubFolder (path.upToFirstOccurrenceOf (T("/"), false, false)); | |||
| const String remainingPath (path.fromFirstOccurrenceOf (T("/"), false, false)); | |||
| for (int i = subFolders.size(); --i >= 0;) | |||
| { | |||
| if (subFolders.getUnchecked(i)->folder.equalsIgnoreCase (firstSubFolder)) | |||
| { | |||
| subFolders.getUnchecked(i)->addPlugin (pd, remainingPath); | |||
| return; | |||
| } | |||
| } | |||
| PluginFilesystemTree* const newFolder = new PluginFilesystemTree(); | |||
| newFolder->folder = firstSubFolder; | |||
| subFolders.add (newFolder); | |||
| newFolder->addPlugin (pd, remainingPath); | |||
| } | |||
| } | |||
| // removes any deeply nested folders that don't contain any actual plugins | |||
| void optimise() | |||
| { | |||
| for (int i = subFolders.size(); --i >= 0;) | |||
| { | |||
| PluginFilesystemTree* const sub = subFolders.getUnchecked(i); | |||
| sub->optimise(); | |||
| if (sub->plugins.size() == 0) | |||
| { | |||
| for (int j = 0; j < sub->subFolders.size(); ++j) | |||
| subFolders.add (sub->subFolders.getUnchecked(j)); | |||
| sub->subFolders.clear (false); | |||
| subFolders.remove (i); | |||
| } | |||
| } | |||
| } | |||
| public: | |||
| void buildTree (const Array <PluginDescription*>& allPlugins) | |||
| { | |||
| for (int i = 0; i < allPlugins.size(); ++i) | |||
| { | |||
| String path (allPlugins.getUnchecked(i)->file.getParentDirectory().getFullPathName()); | |||
| if (path.substring (1, 2) == T(":")) | |||
| path = path.substring (2); | |||
| path = path.replaceCharacter (T('\\'), T('/')); | |||
| addPlugin (allPlugins.getUnchecked(i), path); | |||
| } | |||
| optimise(); | |||
| } | |||
| void addToMenu (PopupMenu& m, const OwnedArray <PluginDescription>& allPlugins) const | |||
| { | |||
| int i; | |||
| for (i = 0; i < subFolders.size(); ++i) | |||
| { | |||
| const PluginFilesystemTree* const sub = subFolders.getUnchecked(i); | |||
| PopupMenu subMenu; | |||
| sub->addToMenu (subMenu, allPlugins); | |||
| m.addSubMenu (sub->folder, subMenu); | |||
| } | |||
| for (i = 0; i < plugins.size(); ++i) | |||
| { | |||
| PluginDescription* const plugin = plugins.getUnchecked(i); | |||
| m.addItem (allPlugins.indexOf (plugin) + menuIdBase, | |||
| plugin->name, true, false); | |||
| } | |||
| } | |||
| }; | |||
| //============================================================================== | |||
| void KnownPluginList::addToMenu (PopupMenu& menu, const SortMethod sortMethod) const | |||
| { | |||
| Array <PluginDescription*> sorted; | |||
| { | |||
| PluginSorter sorter; | |||
| sorter.method = sortMethod; | |||
| for (int i = 0; i < types.size(); ++i) | |||
| sorted.addSorted (sorter, types.getUnchecked(i)); | |||
| } | |||
| if (sortMethod == sortByCategory | |||
| || sortMethod == sortByManufacturer) | |||
| { | |||
| String lastSubMenuName; | |||
| PopupMenu sub; | |||
| for (int i = 0; i < sorted.size(); ++i) | |||
| { | |||
| const PluginDescription* const pd = sorted.getUnchecked(i); | |||
| String thisSubMenuName (sortMethod == sortByCategory ? pd->category | |||
| : pd->manufacturerName); | |||
| if (thisSubMenuName.trim().isEmpty()) | |||
| thisSubMenuName = T("Other"); | |||
| if (thisSubMenuName != lastSubMenuName) | |||
| { | |||
| if (sub.getNumItems() > 0) | |||
| { | |||
| menu.addSubMenu (lastSubMenuName, sub); | |||
| sub.clear(); | |||
| } | |||
| lastSubMenuName = thisSubMenuName; | |||
| } | |||
| sub.addItem (types.indexOf (pd) + menuIdBase, pd->name, true, false); | |||
| } | |||
| if (sub.getNumItems() > 0) | |||
| menu.addSubMenu (lastSubMenuName, sub); | |||
| } | |||
| else if (sortMethod == sortByFileSystemLocation) | |||
| { | |||
| PluginFilesystemTree root; | |||
| root.buildTree (sorted); | |||
| root.addToMenu (menu, types); | |||
| } | |||
| else | |||
| { | |||
| for (int i = 0; i < sorted.size(); ++i) | |||
| { | |||
| const PluginDescription* const pd = sorted.getUnchecked(i); | |||
| menu.addItem (types.indexOf (pd) + menuIdBase, pd->name, true, false); | |||
| } | |||
| } | |||
| } | |||
| int KnownPluginList::getIndexChosenByMenu (const int menuResultCode) const | |||
| { | |||
| const int i = menuResultCode - menuIdBase; | |||
| return (((unsigned int) i) < (unsigned int) types.size()) ? i : -1; | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| @@ -0,0 +1,176 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-7 by Raw Material Software ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the | |||
| GNU General Public License, as published by the Free Software Foundation; | |||
| either version 2 of the License, or (at your option) any later version. | |||
| JUCE is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with JUCE; if not, visit www.gnu.org/licenses or write to the | |||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||
| Boston, MA 02111-1307 USA | |||
| ------------------------------------------------------------------------------ | |||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||
| more information. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef __JUCE_KNOWNPLUGINLIST_JUCEHEADER__ | |||
| #define __JUCE_KNOWNPLUGINLIST_JUCEHEADER__ | |||
| #include "juce_PluginDescription.h" | |||
| #include "juce_AudioPluginFormat.h" | |||
| #include "../../events/juce_ChangeBroadcaster.h" | |||
| #include "../../gui/components/menus/juce_PopupMenu.h" | |||
| //============================================================================== | |||
| /** | |||
| Manages a list of plugin types. | |||
| This can be easily edited, saved and loaded, and used to create instances of | |||
| the plugin types in it. | |||
| @see PluginListComponent | |||
| */ | |||
| class JUCE_API KnownPluginList : public ChangeBroadcaster | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| /** Creates an empty list. | |||
| */ | |||
| KnownPluginList(); | |||
| /** Destructor. */ | |||
| ~KnownPluginList(); | |||
| //============================================================================== | |||
| /** Clears the list. */ | |||
| void clear(); | |||
| /** Returns the number of types currently in the list. | |||
| @see getType | |||
| */ | |||
| int getNumTypes() const throw() { return types.size(); } | |||
| /** Returns one of the types. | |||
| @see getNumTypes | |||
| */ | |||
| PluginDescription* getType (const int index) const throw() { return types [index]; } | |||
| /** Looks for a type in the list which comes from this file. | |||
| */ | |||
| PluginDescription* getTypeForFile (const File& file) const throw(); | |||
| /** Looks for a type in the list which matches a plugin type ID. | |||
| The identifierString parameter must have been created by | |||
| PluginDescription::createIdentifierString(). | |||
| */ | |||
| PluginDescription* getTypeForIdentifierString (const String& identifierString) const throw(); | |||
| /** Adds a type manually from its description. */ | |||
| bool addType (const PluginDescription& type); | |||
| /** Removes a type. */ | |||
| void removeType (const int index) throw(); | |||
| /** Looks for all types that can be loaded from a given file, and adds them | |||
| to the list. | |||
| If dontRescanIfAlreadyInList is true, then the file will only be loaded and | |||
| re-tested if it's not already in the list, or if the file's modification | |||
| time has changed since the list was created. If dontRescanIfAlreadyInList is | |||
| false, the file will always be reloaded and tested. | |||
| Returns true if any new types were added, and all the types found in this | |||
| file (even if it was already known and hasn't been re-scanned) get returned | |||
| in the array. | |||
| */ | |||
| bool scanAndAddFile (const File& possiblePluginFile, | |||
| const bool dontRescanIfAlreadyInList, | |||
| OwnedArray <PluginDescription>& typesFound); | |||
| /** Returns true if the specified file is already known about and if it | |||
| hasn't been modified since our entry was created. | |||
| */ | |||
| bool isListingUpToDate (const File& possiblePluginFile) const throw(); | |||
| /** Scans and adds a bunch of files that might have been dragged-and-dropped. | |||
| If any types are found in the files, their descriptions are returned in the array. | |||
| */ | |||
| void scanAndAddDragAndDroppedFiles (const StringArray& filenames, | |||
| OwnedArray <PluginDescription>& typesFound); | |||
| //============================================================================== | |||
| /** Sort methods used to change the order of the plugins in the list. | |||
| */ | |||
| enum SortMethod | |||
| { | |||
| defaultOrder = 0, | |||
| sortAlphabetically, | |||
| sortByCategory, | |||
| sortByManufacturer, | |||
| sortByFileSystemLocation | |||
| }; | |||
| //============================================================================== | |||
| /** Adds all the plugin types to a popup menu so that the user can select one. | |||
| Depending on the sort method, it may add sub-menus for categories, | |||
| manufacturers, etc. | |||
| Use getIndexChosenByMenu() to find out the type that was chosen. | |||
| */ | |||
| void addToMenu (PopupMenu& menu, | |||
| const SortMethod sortMethod) const; | |||
| /** Converts a menu item index that has been chosen into its index in this list. | |||
| Returns -1 if it's not an ID that was used. | |||
| @see addToMenu | |||
| */ | |||
| int getIndexChosenByMenu (const int menuResultCode) const; | |||
| //============================================================================== | |||
| /** Sorts the list. */ | |||
| void sort (const SortMethod method); | |||
| //============================================================================== | |||
| /** Creates some XML that can be used to store the state of this list. | |||
| */ | |||
| XmlElement* createXml() const; | |||
| /** Recreates the state of this list from its stored XML format. | |||
| */ | |||
| void recreateFromXml (const XmlElement& xml); | |||
| //============================================================================== | |||
| juce_UseDebuggingNewOperator | |||
| private: | |||
| OwnedArray <PluginDescription> types; | |||
| KnownPluginList (const KnownPluginList&); | |||
| const KnownPluginList& operator= (const KnownPluginList&); | |||
| }; | |||
| #endif // __JUCE_KNOWNPLUGINLIST_JUCEHEADER__ | |||
| @@ -0,0 +1,139 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-7 by Raw Material Software ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the | |||
| GNU General Public License, as published by the Free Software Foundation; | |||
| either version 2 of the License, or (at your option) any later version. | |||
| JUCE is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with JUCE; if not, visit www.gnu.org/licenses or write to the | |||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||
| Boston, MA 02111-1307 USA | |||
| ------------------------------------------------------------------------------ | |||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||
| more information. | |||
| ============================================================================== | |||
| */ | |||
| #include "../../../juce_core/basics/juce_StandardHeader.h" | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_PluginDescription.h" | |||
| #include "juce_AudioPluginFormat.h" | |||
| //============================================================================== | |||
| PluginDescription::PluginDescription() throw() | |||
| : uid (0), | |||
| isInstrument (false), | |||
| numInputChannels (0), | |||
| numOutputChannels (0) | |||
| { | |||
| } | |||
| PluginDescription::~PluginDescription() throw() | |||
| { | |||
| } | |||
| PluginDescription::PluginDescription (const PluginDescription& other) throw() | |||
| : name (other.name), | |||
| pluginFormatName (other.pluginFormatName), | |||
| category (other.category), | |||
| manufacturerName (other.manufacturerName), | |||
| version (other.version), | |||
| file (other.file), | |||
| uid (other.uid), | |||
| isInstrument (other.isInstrument), | |||
| lastFileModTime (other.lastFileModTime), | |||
| numInputChannels (other.numInputChannels), | |||
| numOutputChannels (other.numOutputChannels) | |||
| { | |||
| } | |||
| const PluginDescription& PluginDescription::operator= (const PluginDescription& other) throw() | |||
| { | |||
| name = other.name; | |||
| pluginFormatName = other.pluginFormatName; | |||
| category = other.category; | |||
| manufacturerName = other.manufacturerName; | |||
| version = other.version; | |||
| file = other.file; | |||
| uid = other.uid; | |||
| isInstrument = other.isInstrument; | |||
| lastFileModTime = other.lastFileModTime; | |||
| numInputChannels = other.numInputChannels; | |||
| numOutputChannels = other.numOutputChannels; | |||
| return *this; | |||
| } | |||
| bool PluginDescription::isDuplicateOf (const PluginDescription& other) const | |||
| { | |||
| return file == other.file | |||
| && uid == other.uid; | |||
| } | |||
| const String PluginDescription::createIdentifierString() const throw() | |||
| { | |||
| return pluginFormatName | |||
| + T("-") + name | |||
| + T("-") + String::toHexString (file.getFileName().hashCode()) | |||
| + T("-") + String::toHexString (uid); | |||
| } | |||
| XmlElement* PluginDescription::createXml() const | |||
| { | |||
| XmlElement* const e = new XmlElement (T("PLUGIN")); | |||
| e->setAttribute (T("name"), name); | |||
| e->setAttribute (T("format"), pluginFormatName); | |||
| e->setAttribute (T("category"), category); | |||
| e->setAttribute (T("manufacturer"), manufacturerName); | |||
| e->setAttribute (T("version"), version); | |||
| e->setAttribute (T("file"), file.getFullPathName()); | |||
| e->setAttribute (T("uid"), String::toHexString (uid)); | |||
| e->setAttribute (T("isInstrument"), isInstrument); | |||
| e->setAttribute (T("fileTime"), String::toHexString (lastFileModTime.toMilliseconds())); | |||
| e->setAttribute (T("numInputs"), numInputChannels); | |||
| e->setAttribute (T("numOutputs"), numOutputChannels); | |||
| return e; | |||
| } | |||
| bool PluginDescription::loadFromXml (const XmlElement& xml) | |||
| { | |||
| if (xml.hasTagName (T("PLUGIN"))) | |||
| { | |||
| name = xml.getStringAttribute (T("name")); | |||
| pluginFormatName = xml.getStringAttribute (T("format")); | |||
| category = xml.getStringAttribute (T("category")); | |||
| manufacturerName = xml.getStringAttribute (T("manufacturer")); | |||
| version = xml.getStringAttribute (T("version")); | |||
| file = File (xml.getStringAttribute (T("file"))); | |||
| uid = xml.getStringAttribute (T("uid")).getHexValue32(); | |||
| isInstrument = xml.getBoolAttribute (T("isInstrument"), false); | |||
| lastFileModTime = Time (xml.getStringAttribute (T("fileTime")).getHexValue64()); | |||
| numInputChannels = xml.getIntAttribute (T("numInputs")); | |||
| numOutputChannels = xml.getIntAttribute (T("numOutputs")); | |||
| return true; | |||
| } | |||
| return false; | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| @@ -0,0 +1,140 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-7 by Raw Material Software ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the | |||
| GNU General Public License, as published by the Free Software Foundation; | |||
| either version 2 of the License, or (at your option) any later version. | |||
| JUCE is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with JUCE; if not, visit www.gnu.org/licenses or write to the | |||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||
| Boston, MA 02111-1307 USA | |||
| ------------------------------------------------------------------------------ | |||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||
| more information. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef __JUCE_PLUGINDESCRIPTION_JUCEHEADER__ | |||
| #define __JUCE_PLUGINDESCRIPTION_JUCEHEADER__ | |||
| #include "../../../juce_core/io/files/juce_File.h" | |||
| #include "../../../juce_core/text/juce_XmlElement.h" | |||
| //============================================================================== | |||
| /** | |||
| A small class to represent some facts about a particular type of plugin. | |||
| This class is for storing and managing the details about a plugin without | |||
| actually having to load an instance of it. | |||
| A KnownPluginList contains a list of PluginDescription objects. | |||
| @see KnownPluginList | |||
| */ | |||
| class JUCE_API PluginDescription | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| PluginDescription() throw(); | |||
| PluginDescription (const PluginDescription& other) throw(); | |||
| const PluginDescription& operator= (const PluginDescription& other) throw(); | |||
| ~PluginDescription() throw(); | |||
| //============================================================================== | |||
| /** The name of the plugin. */ | |||
| String name; | |||
| /** The plugin format, e.g. "VST", "AudioUnit", etc. | |||
| */ | |||
| String pluginFormatName; | |||
| /** A category, such as "Dynamics", "Reverbs", etc. | |||
| */ | |||
| String category; | |||
| /** The manufacturer. */ | |||
| String manufacturerName; | |||
| /** The version. This string doesn't have any particular format. */ | |||
| String version; | |||
| /** The binary module file containing the plugin. */ | |||
| File file; | |||
| /** The last time the plugin file was changed. | |||
| This is handy when scanning for new or changed plugins. | |||
| */ | |||
| Time lastFileModTime; | |||
| /** A unique ID for the plugin. | |||
| Note that this might not be unique between formats, e.g. a VST and some | |||
| other format might actually have the same id. | |||
| @see createIdentifierString | |||
| */ | |||
| int uid; | |||
| /** True if the plugin identifies itself as a synthesiser. */ | |||
| bool isInstrument; | |||
| /** The number of inputs. */ | |||
| int numInputChannels; | |||
| /** The number of outputs. */ | |||
| int numOutputChannels; | |||
| /** Returns true if the two descriptions refer the the same plugin. | |||
| This isn't quite as simple as them just having the same file (because of | |||
| shell plugins). | |||
| */ | |||
| bool isDuplicateOf (const PluginDescription& other) const; | |||
| //============================================================================== | |||
| /** Returns a string that can be saved and used to uniquely identify the | |||
| plugin again. | |||
| This contains less info than the XML encoding, and is independent of the | |||
| plugin's file location, so can be used to store a plugin ID for use | |||
| across different machines. | |||
| */ | |||
| const String createIdentifierString() const throw(); | |||
| //============================================================================== | |||
| /** Creates an XML object containing these details. | |||
| @see loadFromXml | |||
| */ | |||
| XmlElement* createXml() const; | |||
| /** Reloads the info in this structure from an XML record that was previously | |||
| saved with createXML(). | |||
| Returns true if the XML was a valid plugin description. | |||
| */ | |||
| bool loadFromXml (const XmlElement& xml); | |||
| //============================================================================== | |||
| juce_UseDebuggingNewOperator | |||
| }; | |||
| #endif // __JUCE_PLUGINDESCRIPTION_JUCEHEADER__ | |||
| @@ -0,0 +1,164 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-7 by Raw Material Software ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the | |||
| GNU General Public License, as published by the Free Software Foundation; | |||
| either version 2 of the License, or (at your option) any later version. | |||
| JUCE is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with JUCE; if not, visit www.gnu.org/licenses or write to the | |||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||
| Boston, MA 02111-1307 USA | |||
| ------------------------------------------------------------------------------ | |||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||
| more information. | |||
| ============================================================================== | |||
| */ | |||
| #include "../../../juce_core/basics/juce_StandardHeader.h" | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_PluginDirectoryScanner.h" | |||
| #include "juce_AudioPluginFormat.h" | |||
| #include "../../../juce_core/io/files/juce_DirectoryIterator.h" | |||
| //============================================================================== | |||
| PluginDirectoryScanner::PluginDirectoryScanner (KnownPluginList& listToAddTo, | |||
| AudioPluginFormat& formatToLookFor, | |||
| FileSearchPath directoriesToSearch, | |||
| const bool recursive, | |||
| const File& deadMansPedalFile_) | |||
| : list (listToAddTo), | |||
| format (formatToLookFor), | |||
| deadMansPedalFile (deadMansPedalFile_), | |||
| nextIndex (0), | |||
| progress (0) | |||
| { | |||
| directoriesToSearch.removeRedundantPaths(); | |||
| for (int j = 0; j < directoriesToSearch.getNumPaths(); ++j) | |||
| recursiveFileSearch (directoriesToSearch [j], recursive); | |||
| // If any plugins have crashed recently when being loaded, move them to the | |||
| // end of the list to give the others a chance to load correctly.. | |||
| const StringArray crashedPlugins (getDeadMansPedalFile()); | |||
| for (int i = 0; i < crashedPlugins.size(); ++i) | |||
| { | |||
| const File f (crashedPlugins[i]); | |||
| for (int j = filesToScan.size(); --j >= 0;) | |||
| if (f == *filesToScan.getUnchecked (j)) | |||
| filesToScan.move (j, -1); | |||
| } | |||
| } | |||
| void PluginDirectoryScanner::recursiveFileSearch (const File& dir, const bool recursive) | |||
| { | |||
| // avoid allowing the dir iterator to be recursive, because we want to avoid letting it delve inside | |||
| // .component or .vst directories. | |||
| DirectoryIterator iter (dir, false, "*", File::findFilesAndDirectories); | |||
| while (iter.next()) | |||
| { | |||
| const File f (iter.getFile()); | |||
| bool isPlugin = false; | |||
| if (format.fileMightContainThisPluginType (f)) | |||
| { | |||
| isPlugin = true; | |||
| filesToScan.add (new File (f)); | |||
| } | |||
| if (recursive && (! isPlugin) && f.isDirectory()) | |||
| recursiveFileSearch (f, true); | |||
| } | |||
| } | |||
| PluginDirectoryScanner::~PluginDirectoryScanner() | |||
| { | |||
| } | |||
| //============================================================================== | |||
| const File PluginDirectoryScanner::getNextPluginFileThatWillBeScanned() const throw() | |||
| { | |||
| File* const file = filesToScan [nextIndex]; | |||
| if (file != 0) | |||
| return *file; | |||
| return File::nonexistent; | |||
| } | |||
| bool PluginDirectoryScanner::scanNextFile (const bool dontRescanIfAlreadyInList) | |||
| { | |||
| File* const file = filesToScan [nextIndex]; | |||
| if (file != 0) | |||
| { | |||
| if (! list.isListingUpToDate (*file)) | |||
| { | |||
| OwnedArray <PluginDescription> typesFound; | |||
| // Add this plugin to the end of the dead-man's pedal list in case it crashes... | |||
| StringArray crashedPlugins (getDeadMansPedalFile()); | |||
| crashedPlugins.removeString (file->getFullPathName()); | |||
| crashedPlugins.add (file->getFullPathName()); | |||
| setDeadMansPedalFile (crashedPlugins); | |||
| list.scanAndAddFile (*file, | |||
| dontRescanIfAlreadyInList, | |||
| typesFound); | |||
| // Managed to load without crashing, so remove it from the dead-man's-pedal.. | |||
| crashedPlugins.removeString (file->getFullPathName()); | |||
| setDeadMansPedalFile (crashedPlugins); | |||
| if (typesFound.size() == 0) | |||
| failedFiles.add (file->getFullPathName()); | |||
| } | |||
| ++nextIndex; | |||
| progress = nextIndex / (float) filesToScan.size(); | |||
| } | |||
| return nextIndex < filesToScan.size(); | |||
| } | |||
| const StringArray PluginDirectoryScanner::getDeadMansPedalFile() throw() | |||
| { | |||
| StringArray lines; | |||
| if (deadMansPedalFile != File::nonexistent) | |||
| { | |||
| lines.addLines (deadMansPedalFile.loadFileAsString()); | |||
| lines.removeEmptyStrings(); | |||
| } | |||
| return lines; | |||
| } | |||
| void PluginDirectoryScanner::setDeadMansPedalFile (const StringArray& newContents) throw() | |||
| { | |||
| if (deadMansPedalFile != File::nonexistent) | |||
| deadMansPedalFile.replaceWithText (newContents.joinIntoString ("\n"), true, true); | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| @@ -0,0 +1,129 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-7 by Raw Material Software ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the | |||
| GNU General Public License, as published by the Free Software Foundation; | |||
| either version 2 of the License, or (at your option) any later version. | |||
| JUCE is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with JUCE; if not, visit www.gnu.org/licenses or write to the | |||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||
| Boston, MA 02111-1307 USA | |||
| ------------------------------------------------------------------------------ | |||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||
| more information. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef __JUCE_PLUGINDIRECTORYSCANNER_JUCEHEADER__ | |||
| #define __JUCE_PLUGINDIRECTORYSCANNER_JUCEHEADER__ | |||
| #include "juce_KnownPluginList.h" | |||
| #include "juce_AudioPluginFormatManager.h" | |||
| //============================================================================== | |||
| /** | |||
| Scans a directory for plugins, and adds them to a KnownPluginList. | |||
| To use one of these, create it and call scanNextFile() repeatedly, until | |||
| it returns false. | |||
| */ | |||
| class JUCE_API PluginDirectoryScanner | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| /** | |||
| Creates a scanner. | |||
| @param listToAddResultsTo this will get the new types added to it. | |||
| @param formatToLookFor this is the type of format that you want to look for | |||
| @param directoriesToSearch the path to search | |||
| @param searchRecursively true to search recursively | |||
| @param deadMansPedalFile if this isn't File::nonexistent, then it will | |||
| be used as a file to store the names of any plugins | |||
| that crash during initialisation. If there are | |||
| any plugins listed in it, then these will always | |||
| be scanned after all other possible files have | |||
| been tried - in this way, even if there's a few | |||
| dodgy plugins in your path, then a couple of rescans | |||
| will still manage to find all the proper plugins. | |||
| It's probably best to choose a file in the user's | |||
| application data directory (alongside your app's | |||
| settings file) for this. The file format it uses | |||
| is just a list of filenames of the modules that | |||
| failed. | |||
| */ | |||
| PluginDirectoryScanner (KnownPluginList& listToAddResultsTo, | |||
| AudioPluginFormat& formatToLookFor, | |||
| FileSearchPath directoriesToSearch, | |||
| const bool searchRecursively, | |||
| const File& deadMansPedalFile); | |||
| /** Destructor. */ | |||
| ~PluginDirectoryScanner(); | |||
| //============================================================================== | |||
| /** Tries the next likely-looking file. | |||
| If dontRescanIfAlreadyInList is true, then the file will only be loaded and | |||
| re-tested if it's not already in the list, or if the file's modification | |||
| time has changed since the list was created. If dontRescanIfAlreadyInList is | |||
| false, the file will always be reloaded and tested. | |||
| Returns false when there are no more files to try. | |||
| */ | |||
| bool scanNextFile (const bool dontRescanIfAlreadyInList); | |||
| /** Returns the file that will be scanned during the next call to scanNextFile(). | |||
| This is handy if you want to show the user which file is currently getting | |||
| scanned. | |||
| */ | |||
| const File getNextPluginFileThatWillBeScanned() const throw(); | |||
| /** Returns the estimated progress, between 0 and 1. | |||
| */ | |||
| float getProgress() const { return progress; } | |||
| /** This returns a list of all the filenames of things that looked like being | |||
| a plugin file, but which failed to open for some reason. | |||
| */ | |||
| const StringArray& getFailedFiles() const throw() { return failedFiles; } | |||
| //============================================================================== | |||
| juce_UseDebuggingNewOperator | |||
| private: | |||
| KnownPluginList& list; | |||
| AudioPluginFormat& format; | |||
| OwnedArray <File> filesToScan; | |||
| File deadMansPedalFile; | |||
| StringArray failedFiles; | |||
| int nextIndex; | |||
| float progress; | |||
| void recursiveFileSearch (const File& dir, const bool recursive); | |||
| const StringArray getDeadMansPedalFile() throw(); | |||
| void setDeadMansPedalFile (const StringArray& newContents) throw(); | |||
| PluginDirectoryScanner (const PluginDirectoryScanner&); | |||
| const PluginDirectoryScanner& operator= (const PluginDirectoryScanner&); | |||
| }; | |||
| #endif // __JUCE_PLUGINDIRECTORYSCANNER_JUCEHEADER__ | |||
| @@ -0,0 +1,308 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-7 by Raw Material Software ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the | |||
| GNU General Public License, as published by the Free Software Foundation; | |||
| either version 2 of the License, or (at your option) any later version. | |||
| JUCE is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with JUCE; if not, visit www.gnu.org/licenses or write to the | |||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||
| Boston, MA 02111-1307 USA | |||
| ------------------------------------------------------------------------------ | |||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||
| more information. | |||
| ============================================================================== | |||
| */ | |||
| #include "../../../juce_core/basics/juce_StandardHeader.h" | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_PluginListComponent.h" | |||
| #include "juce_PluginDirectoryScanner.h" | |||
| #include "../../gui/components/controls/juce_TextEditor.h" | |||
| #include "../../gui/components/windows/juce_AlertWindow.h" | |||
| #include "../../gui/graphics/fonts/juce_GlyphArrangement.h" | |||
| #include "../../gui/components/filebrowser/juce_FileSearchPathListComponent.h" | |||
| #include "../../../juce_core/text/juce_LocalisedStrings.h" | |||
| #include "../../events/juce_MessageManager.h" | |||
| //============================================================================== | |||
| PluginListComponent::PluginListComponent (KnownPluginList& listToEdit, | |||
| const File& deadMansPedalFile_, | |||
| PropertiesFile* const propertiesToUse_) | |||
| : list (listToEdit), | |||
| deadMansPedalFile (deadMansPedalFile_), | |||
| propertiesToUse (propertiesToUse_) | |||
| { | |||
| addAndMakeVisible (listBox = new ListBox (String::empty, this)); | |||
| addAndMakeVisible (optionsButton = new TextButton ("Options...")); | |||
| optionsButton->addButtonListener (this); | |||
| optionsButton->setTriggeredOnMouseDown (true); | |||
| setSize (400, 600); | |||
| list.addChangeListener (this); | |||
| } | |||
| PluginListComponent::~PluginListComponent() | |||
| { | |||
| list.removeChangeListener (this); | |||
| deleteAllChildren(); | |||
| } | |||
| void PluginListComponent::resized() | |||
| { | |||
| listBox->setBounds (0, 0, getWidth(), getHeight() - 30); | |||
| optionsButton->changeWidthToFitText (24); | |||
| optionsButton->setTopLeftPosition (8, getHeight() - 28); | |||
| } | |||
| void PluginListComponent::changeListenerCallback (void*) | |||
| { | |||
| listBox->updateContent(); | |||
| listBox->repaint(); | |||
| } | |||
| int PluginListComponent::getNumRows() | |||
| { | |||
| return list.getNumTypes(); | |||
| } | |||
| void PluginListComponent::paintListBoxItem (int row, | |||
| Graphics& g, | |||
| int width, int height, | |||
| bool rowIsSelected) | |||
| { | |||
| if (rowIsSelected) | |||
| g.fillAll (findColour (TextEditor::highlightColourId)); | |||
| const PluginDescription* const pd = list.getType (row); | |||
| if (pd != 0) | |||
| { | |||
| GlyphArrangement ga; | |||
| ga.addCurtailedLineOfText (Font (height * 0.7f, Font::bold), pd->name, 8.0f, height * 0.8f, width - 10.0f, true); | |||
| g.setColour (Colours::black); | |||
| ga.draw (g); | |||
| float x, y, r, b; | |||
| ga.getBoundingBox (0, -1, x, y, r, b, false); | |||
| String desc; | |||
| desc << pd->pluginFormatName | |||
| << (pd->isInstrument ? " instrument" : " effect") | |||
| << " - " | |||
| << pd->numInputChannels << (pd->numInputChannels == 1 ? " in" : " ins") | |||
| << " / " | |||
| << pd->numOutputChannels << (pd->numOutputChannels == 1 ? " out" : " outs"); | |||
| if (pd->manufacturerName.isNotEmpty()) | |||
| desc << " - " << pd->manufacturerName; | |||
| if (pd->version.isNotEmpty()) | |||
| desc << " - " << pd->version; | |||
| if (pd->category.isNotEmpty()) | |||
| desc << " - category: '" << pd->category << '\''; | |||
| g.setColour (Colours::grey); | |||
| ga.clear(); | |||
| ga.addCurtailedLineOfText (Font (height * 0.6f), desc, r + 10.0f, height * 0.8f, width - r - 12.0f, true); | |||
| ga.draw (g); | |||
| } | |||
| } | |||
| void PluginListComponent::deleteKeyPressed (int lastRowSelected) | |||
| { | |||
| list.removeType (lastRowSelected); | |||
| } | |||
| void PluginListComponent::buttonClicked (Button* b) | |||
| { | |||
| if (optionsButton == b) | |||
| { | |||
| PopupMenu menu; | |||
| menu.addItem (1, TRANS("Clear list")); | |||
| menu.addItem (5, TRANS("Remove selected plugin from list"), listBox->getNumSelectedRows() > 0); | |||
| menu.addItem (6, TRANS("Show folder containing selected plugin"), listBox->getNumSelectedRows() > 0); | |||
| menu.addItem (7, TRANS("Remove any plugins whose files no longer exist")); | |||
| menu.addSeparator(); | |||
| menu.addItem (2, TRANS("Sort alphabetically")); | |||
| menu.addItem (3, TRANS("Sort by category")); | |||
| menu.addItem (4, TRANS("Sort by manufacturer")); | |||
| menu.addSeparator(); | |||
| for (int i = 0; i < AudioPluginFormatManager::getInstance()->getNumFormats(); ++i) | |||
| { | |||
| AudioPluginFormat* const format = AudioPluginFormatManager::getInstance()->getFormat (i); | |||
| if (format->getDefaultLocationsToSearch().getNumPaths() > 0) | |||
| menu.addItem (10 + i, "Scan for new or updated " + format->getName() + " plugins..."); | |||
| } | |||
| const int r = menu.showAt (optionsButton); | |||
| if (r == 1) | |||
| { | |||
| list.clear(); | |||
| } | |||
| else if (r == 2) | |||
| { | |||
| list.sort (KnownPluginList::sortAlphabetically); | |||
| } | |||
| else if (r == 3) | |||
| { | |||
| list.sort (KnownPluginList::sortByCategory); | |||
| } | |||
| else if (r == 4) | |||
| { | |||
| list.sort (KnownPluginList::sortByManufacturer); | |||
| } | |||
| else if (r == 5) | |||
| { | |||
| const SparseSet <int> selected (listBox->getSelectedRows()); | |||
| for (int i = list.getNumTypes(); --i >= 0;) | |||
| if (selected.contains (i)) | |||
| list.removeType (i); | |||
| } | |||
| else if (r == 6) | |||
| { | |||
| const PluginDescription* const desc = list.getType (listBox->getSelectedRow()); | |||
| if (desc != 0) | |||
| desc->file.getParentDirectory().startAsProcess(); | |||
| } | |||
| else if (r == 7) | |||
| { | |||
| for (int i = list.getNumTypes(); --i >= 0;) | |||
| { | |||
| if (list.getType (i)->file != File::nonexistent | |||
| && ! list.getType (i)->file.exists()) | |||
| { | |||
| list.removeType (i); | |||
| } | |||
| } | |||
| } | |||
| else if (r != 0) | |||
| { | |||
| typeToScan = r - 10; | |||
| startTimer (1); | |||
| } | |||
| } | |||
| } | |||
| void PluginListComponent::timerCallback() | |||
| { | |||
| stopTimer(); | |||
| scanFor (AudioPluginFormatManager::getInstance()->getFormat (typeToScan)); | |||
| } | |||
| bool PluginListComponent::isInterestedInFileDrag (const StringArray& /*files*/) | |||
| { | |||
| return true; | |||
| } | |||
| void PluginListComponent::filesDropped (const StringArray& files, int, int) | |||
| { | |||
| OwnedArray <PluginDescription> typesFound; | |||
| list.scanAndAddDragAndDroppedFiles (files, typesFound); | |||
| } | |||
| void PluginListComponent::scanFor (AudioPluginFormat* format) | |||
| { | |||
| if (format == 0) | |||
| return; | |||
| FileSearchPath path (format->getDefaultLocationsToSearch()); | |||
| if (propertiesToUse != 0) | |||
| path = propertiesToUse->getValue ("lastPluginScanPath_" + format->getName(), path.toString()); | |||
| { | |||
| AlertWindow aw (TRANS("Select folders to scan..."), String::empty, AlertWindow::NoIcon); | |||
| FileSearchPathListComponent pathList; | |||
| pathList.setSize (500, 300); | |||
| pathList.setPath (path); | |||
| aw.addCustomComponent (&pathList); | |||
| aw.addButton (TRANS("Scan"), 1, KeyPress::returnKey); | |||
| aw.addButton (TRANS("Cancel"), 0, KeyPress (KeyPress::escapeKey)); | |||
| if (aw.runModalLoop() == 0) | |||
| return; | |||
| path = pathList.getPath(); | |||
| } | |||
| if (propertiesToUse != 0) | |||
| { | |||
| propertiesToUse->setValue ("lastPluginScanPath_" + format->getName(), path.toString()); | |||
| propertiesToUse->saveIfNeeded(); | |||
| } | |||
| double progress = 0.0; | |||
| AlertWindow aw (TRANS("Scanning for plugins..."), | |||
| TRANS("Searching for all possible plugin files..."), AlertWindow::NoIcon); | |||
| aw.addButton (TRANS("Cancel"), 0, KeyPress (KeyPress::escapeKey)); | |||
| aw.addProgressBarComponent (progress); | |||
| aw.enterModalState(); | |||
| MessageManager::getInstance()->dispatchPendingMessages(); | |||
| PluginDirectoryScanner scanner (list, *format, path, true, deadMansPedalFile); | |||
| for (;;) | |||
| { | |||
| aw.setMessage (TRANS("Testing:\n\n") | |||
| + scanner.getNextPluginFileThatWillBeScanned().getFileName()); | |||
| MessageManager::getInstance()->dispatchPendingMessages (500); | |||
| if (! scanner.scanNextFile (true)) | |||
| break; | |||
| if (! aw.isCurrentlyModal()) | |||
| break; | |||
| progress = scanner.getProgress(); | |||
| } | |||
| if (scanner.getFailedFiles().size() > 0) | |||
| { | |||
| StringArray shortNames; | |||
| for (int i = 0; i < scanner.getFailedFiles().size(); ++i) | |||
| shortNames.add (File (scanner.getFailedFiles()[i]).getFileName()); | |||
| AlertWindow::showMessageBox (AlertWindow::InfoIcon, | |||
| TRANS("Scan complete"), | |||
| TRANS("Note that the following files appeared to be plugin files, but failed to load correctly:\n\n") | |||
| + shortNames.joinIntoString (", ")); | |||
| } | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| @@ -0,0 +1,107 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-7 by Raw Material Software ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the | |||
| GNU General Public License, as published by the Free Software Foundation; | |||
| either version 2 of the License, or (at your option) any later version. | |||
| JUCE is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with JUCE; if not, visit www.gnu.org/licenses or write to the | |||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||
| Boston, MA 02111-1307 USA | |||
| ------------------------------------------------------------------------------ | |||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||
| more information. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef __JUCE_PLUGINLISTCOMPONENT_JUCEHEADER__ | |||
| #define __JUCE_PLUGINLISTCOMPONENT_JUCEHEADER__ | |||
| #include "juce_KnownPluginList.h" | |||
| #include "juce_AudioPluginFormat.h" | |||
| #include "../../gui/components/controls/juce_ListBox.h" | |||
| #include "../../gui/components/buttons/juce_TextButton.h" | |||
| #include "../../application/juce_PropertiesFile.h" | |||
| //============================================================================== | |||
| /** | |||
| A component displaying a list of plugins, with options to scan for them, | |||
| add, remove and sort them. | |||
| */ | |||
| class JUCE_API PluginListComponent : public Component, | |||
| public ListBoxModel, | |||
| public ChangeListener, | |||
| public ButtonListener, | |||
| public Timer | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| /** | |||
| Creates the list component. | |||
| For info about the deadMansPedalFile, see the PluginDirectoryScanner constructor. | |||
| The properties file, if supplied, is used to store the user's last search paths. | |||
| */ | |||
| PluginListComponent (KnownPluginList& listToRepresent, | |||
| const File& deadMansPedalFile, | |||
| PropertiesFile* const propertiesToUse); | |||
| /** Destructor. */ | |||
| ~PluginListComponent(); | |||
| //============================================================================== | |||
| /** @internal */ | |||
| void resized(); | |||
| /** @internal */ | |||
| bool isInterestedInFileDrag (const StringArray& files); | |||
| /** @internal */ | |||
| void filesDropped (const StringArray& files, int, int); | |||
| /** @internal */ | |||
| int getNumRows(); | |||
| /** @internal */ | |||
| void paintListBoxItem (int row, Graphics& g, int width, int height, bool rowIsSelected); | |||
| /** @internal */ | |||
| void deleteKeyPressed (int lastRowSelected); | |||
| /** @internal */ | |||
| void buttonClicked (Button* b); | |||
| /** @internal */ | |||
| void changeListenerCallback (void*); | |||
| /** @internal */ | |||
| void timerCallback(); | |||
| //============================================================================== | |||
| juce_UseDebuggingNewOperator | |||
| private: | |||
| KnownPluginList& list; | |||
| File deadMansPedalFile; | |||
| ListBox* listBox; | |||
| TextButton* optionsButton; | |||
| PropertiesFile* propertiesToUse; | |||
| int typeToScan; | |||
| void scanFor (AudioPluginFormat* format); | |||
| PluginListComponent (const PluginListComponent&); | |||
| const PluginListComponent& operator= (const PluginListComponent&); | |||
| }; | |||
| #endif // __JUCE_PLUGINLISTCOMPONENT_JUCEHEADER__ | |||
| @@ -69,6 +69,11 @@ public: | |||
| /** Destructor. */ | |||
| virtual ~AudioProcessor(); | |||
| //============================================================================== | |||
| /** Returns the name of this processor. | |||
| */ | |||
| virtual const String getName() const = 0; | |||
| //============================================================================== | |||
| /** Called before playback starts, to let the filter prepare itself. | |||
| @@ -229,6 +234,12 @@ public: | |||
| */ | |||
| void setLatencySamples (const int newLatency); | |||
| /** Returns true if the processor wants midi messages. */ | |||
| virtual bool acceptsMidi() const = 0; | |||
| /** Returns true if the processor produces midi messages. */ | |||
| virtual bool producesMidi() const = 0; | |||
| //============================================================================== | |||
| /** This returns a critical section that will automatically be locked while the host | |||
| is calling the processBlock() method. | |||
| @@ -535,6 +546,9 @@ private: | |||
| #ifdef JUCE_DEBUG | |||
| BitArray changingParams; | |||
| #endif | |||
| AudioProcessor (const AudioProcessor&); | |||
| const AudioProcessor& operator= (const AudioProcessor&); | |||
| }; | |||
| @@ -0,0 +1,440 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-7 by Raw Material Software ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the | |||
| GNU General Public License, as published by the Free Software Foundation; | |||
| either version 2 of the License, or (at your option) any later version. | |||
| JUCE is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with JUCE; if not, visit www.gnu.org/licenses or write to the | |||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||
| Boston, MA 02111-1307 USA | |||
| ------------------------------------------------------------------------------ | |||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||
| more information. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef __JUCE_AUDIOPROCESSORGRAPH_JUCEHEADER__ | |||
| #define __JUCE_AUDIOPROCESSORGRAPH_JUCEHEADER__ | |||
| #include "juce_AudioProcessor.h" | |||
| #include "../plugins/juce_AudioPluginFormatManager.h" | |||
| #include "../plugins/juce_KnownPluginList.h" | |||
| #include "../../../juce_core/containers/juce_ReferenceCountedArray.h" | |||
| //============================================================================== | |||
| /** | |||
| A type of AudioProcessor which plays back a graph of other AudioProcessors. | |||
| Use one of these objects if you want to wire-up a set of AudioProcessors | |||
| and play back the result. | |||
| Processors can be added to the graph as "nodes" using addNode(), and once | |||
| added, you can connect any of their input or output channels to other | |||
| nodes using addConnection(). | |||
| To play back a graph through an audio device, you might want to use an | |||
| AudioProcessorPlayer object. | |||
| */ | |||
| class JUCE_API AudioProcessorGraph : public AudioProcessor, | |||
| public AsyncUpdater | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| /** Creates an empty graph. | |||
| */ | |||
| AudioProcessorGraph(); | |||
| /** Destructor. | |||
| Any processor objects that have been added to the graph will also be deleted. | |||
| */ | |||
| ~AudioProcessorGraph(); | |||
| //============================================================================== | |||
| /** Represents one of the nodes, or processors, in an AudioProcessorGraph. | |||
| To create a node, call AudioProcessorGraph::addNode(). | |||
| */ | |||
| class Node : public ReferenceCountedObject | |||
| { | |||
| public: | |||
| /** Destructor. | |||
| */ | |||
| ~Node(); | |||
| //============================================================================== | |||
| /** The ID number assigned to this node. | |||
| This is assigned by the graph that owns it, and can't be changed. | |||
| */ | |||
| const uint32 id; | |||
| /** The actual processor object that this node represents. | |||
| */ | |||
| AudioProcessor* const processor; | |||
| /** A set of user-definable properties that are associated with this node. | |||
| This can be used to attach values to the node for whatever purpose seems | |||
| useful. For example, you might store an x and y position if your application | |||
| is displaying the nodes on-screen. | |||
| */ | |||
| PropertySet properties; | |||
| //============================================================================== | |||
| /** A convenient typedef for referring to a pointer to a node object. | |||
| */ | |||
| typedef ReferenceCountedObjectPtr <Node> Ptr; | |||
| //============================================================================== | |||
| juce_UseDebuggingNewOperator | |||
| private: | |||
| friend class AudioProcessorGraph; | |||
| bool isPrepared; | |||
| Node (const uint32 id, AudioProcessor* const processor) throw(); | |||
| void prepare (const double sampleRate, const int blockSize, AudioProcessorGraph* const graph); | |||
| void unprepare(); | |||
| Node (const Node&); | |||
| const Node& operator= (const Node&); | |||
| }; | |||
| //============================================================================== | |||
| /** Represents a connection between two channels of two nodes in an AudioProcessorGraph. | |||
| To create a connection, use AudioProcessorGraph::addConnection(). | |||
| */ | |||
| struct Connection | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| /** The ID number of the node which is the input source for this connection. | |||
| @see AudioProcessorGraph::getNodeForId | |||
| */ | |||
| uint32 sourceNodeId; | |||
| /** The index of the output channel of the source node from which this | |||
| connection takes its data. | |||
| If this value is the special number AudioProcessorGraph::midiChannelIndex, then | |||
| it is referring to the source node's midi output. Otherwise, it is the zero-based | |||
| index of an audio output channel in the source node. | |||
| */ | |||
| int sourceChannelIndex; | |||
| /** The ID number of the node which is the destination for this connection. | |||
| @see AudioProcessorGraph::getNodeForId | |||
| */ | |||
| uint32 destNodeId; | |||
| /** The index of the input channel of the destination node to which this | |||
| connection delivers its data. | |||
| If this value is the special number AudioProcessorGraph::midiChannelIndex, then | |||
| it is referring to the destination node's midi input. Otherwise, it is the zero-based | |||
| index of an audio input channel in the destination node. | |||
| */ | |||
| int destChannelIndex; | |||
| //============================================================================== | |||
| juce_UseDebuggingNewOperator | |||
| private: | |||
| }; | |||
| //============================================================================== | |||
| /** Deletes all nodes and connections from this graph. | |||
| Any processor objects in the graph will be deleted. | |||
| */ | |||
| void clear(); | |||
| /** Returns the number of nodes in the graph. */ | |||
| int getNumNodes() const throw() { return nodes.size(); } | |||
| /** Returns a pointer to one of the nodes in the graph. | |||
| This will return 0 if the index is out of range. | |||
| @see getNodeForId | |||
| */ | |||
| Node* getNode (const int index) const throw() { return nodes [index]; } | |||
| /** Searches the graph for a node with the given ID number and returns it. | |||
| If no such node was found, this returns 0. | |||
| @see getNode | |||
| */ | |||
| Node* getNodeForId (const uint32 nodeId) const throw(); | |||
| /** Adds a node to the graph. | |||
| This creates a new node in the graph, for the specified processor. Once you have | |||
| added a processor to the graph, the graph owns it and will delete it later when | |||
| it is no longer needed. | |||
| The optional nodeId parameter lets you specify an ID to use for the node, but | |||
| if the value is already in use, this new node will overwrite the old one. | |||
| If this succeeds, it returns a pointer to the newly-created node. | |||
| */ | |||
| Node* addNode (AudioProcessor* const newProcessor, | |||
| uint32 nodeId = 0); | |||
| /** Deletes a node within the graph which has the specified ID. | |||
| This will also delete any connections that are attached to this node. | |||
| */ | |||
| bool removeNode (const uint32 nodeId); | |||
| //============================================================================== | |||
| /** Returns the number of connections in the graph. */ | |||
| int getNumConnections() const throw() { return connections.size(); } | |||
| /** Returns a pointer to one of the connections in the graph. */ | |||
| const Connection* getConnection (const int index) const throw() { return connections [index]; } | |||
| /** Searches for a connection between some specified channels. | |||
| If no such connection is found, this returns 0. | |||
| */ | |||
| const Connection* getConnectionBetween (const uint32 sourceNodeId, | |||
| const int sourceChannelIndex, | |||
| const uint32 destNodeId, | |||
| const int destChannelIndex) const throw(); | |||
| /** Returns true if there is a connection between any of the channels of | |||
| two specified nodes. | |||
| */ | |||
| bool isConnected (const uint32 possibleSourceNodeId, | |||
| const uint32 possibleDestNodeId) const throw(); | |||
| /** Returns true if it would be legal to connect the specified points. | |||
| */ | |||
| bool canConnect (const uint32 sourceNodeId, const int sourceChannelIndex, | |||
| const uint32 destNodeId, const int destChannelIndex) const throw(); | |||
| /** Attempts to connect two specified channels of two nodes. | |||
| If this isn't allowed (e.g. because you're trying to connect a midi channel | |||
| to an audio one or other such nonsense), then it'll return 0. | |||
| */ | |||
| bool addConnection (const uint32 sourceNodeId, const int sourceChannelIndex, | |||
| const uint32 destNodeId, const int destChannelIndex); | |||
| /** Deletes the connection with the specified index. | |||
| Returns true if a connection was actually deleted. | |||
| */ | |||
| void removeConnection (const int index); | |||
| /** Deletes any connection between two specified points. | |||
| Returns true if a connection was actually deleted. | |||
| */ | |||
| bool removeConnection (const uint32 sourceNodeId, const int sourceChannelIndex, | |||
| const uint32 destNodeId, const int destChannelIndex); | |||
| /** Removes all connections from the specified node. | |||
| */ | |||
| bool disconnectNode (const uint32 nodeId); | |||
| /** Performs a sanity checks of all the connections. | |||
| This might be useful if some of the processors are doing things like changing | |||
| their channel counts, which could render some connections obsolete. | |||
| */ | |||
| bool removeIllegalConnections(); | |||
| //============================================================================== | |||
| /** A special number that represents the midi channel of a node. | |||
| This is used as a channel index value if you want to refer to the midi input | |||
| or output instead of an audio channel. | |||
| */ | |||
| static const int midiChannelIndex; | |||
| //============================================================================== | |||
| /** A special type of AudioProcessor that can live inside an AudioProcessorGraph | |||
| in order to use the audio that comes into and out of the graph itself. | |||
| If you create an AudioGraphIOProcessor in "input" mode, it will act as a | |||
| node in the graph which delivers the audio that is coming into the parent | |||
| graph. This allows you to stream the data to other nodes and process the | |||
| incoming audio. | |||
| Likewise, one of these in "output" mode can be sent data which it will add to | |||
| the sum of data being sent to the graph's output. | |||
| @see AudioProcessorGraph | |||
| */ | |||
| class AudioGraphIOProcessor : public AudioPluginInstance | |||
| { | |||
| public: | |||
| /** Specifies the mode in which this processor will operate. | |||
| */ | |||
| enum IODeviceType | |||
| { | |||
| audioInputNode, /**< In this mode, the processor has output channels | |||
| representing all the audio input channels that are | |||
| coming into its parent audio graph. */ | |||
| audioOutputNode, /**< In this mode, the processor has input channels | |||
| representing all the audio output channels that are | |||
| going out of its parent audio graph. */ | |||
| midiInputNode, /**< In this mode, the processor has a midi output which | |||
| delivers the same midi data that is arriving at its | |||
| parent graph. */ | |||
| midiOutputNode /**< In this mode, the processor has a midi input and | |||
| any data sent to it will be passed out of the parent | |||
| graph. */ | |||
| }; | |||
| //============================================================================== | |||
| /** Returns the mode of this processor. */ | |||
| IODeviceType getType() const throw() { return type; } | |||
| /** Returns the parent graph to which this processor belongs, or 0 if it | |||
| hasn't yet been added to one. */ | |||
| AudioProcessorGraph* getParentGraph() const throw() { return graph; } | |||
| /** True if this is an audio or midi input. */ | |||
| bool isInput() const throw(); | |||
| /** True if this is an audio or midi output. */ | |||
| bool isOutput() const throw(); | |||
| //============================================================================== | |||
| AudioGraphIOProcessor (const IODeviceType type); | |||
| ~AudioGraphIOProcessor(); | |||
| const String getName() const; | |||
| void fillInPluginDescription (PluginDescription& d) const; | |||
| void prepareToPlay (double sampleRate, int estimatedSamplesPerBlock); | |||
| void releaseResources(); | |||
| void processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages); | |||
| const String getInputChannelName (const int channelIndex) const; | |||
| const String getOutputChannelName (const int channelIndex) const; | |||
| bool isInputChannelStereoPair (int index) const; | |||
| bool isOutputChannelStereoPair (int index) const; | |||
| bool acceptsMidi() const; | |||
| bool producesMidi() const; | |||
| AudioProcessorEditor* createEditor(); | |||
| int getNumParameters(); | |||
| const String getParameterName (int); | |||
| float getParameter (int); | |||
| const String getParameterText (int); | |||
| void setParameter (int, float); | |||
| int getNumPrograms(); | |||
| int getCurrentProgram(); | |||
| void setCurrentProgram (int); | |||
| const String getProgramName (int); | |||
| void changeProgramName (int, const String&); | |||
| void getStateInformation (JUCE_NAMESPACE::MemoryBlock& destData); | |||
| void setStateInformation (const void* data, int sizeInBytes); | |||
| /** @internal */ | |||
| void setParentGraph (AudioProcessorGraph* const graph) throw(); | |||
| juce_UseDebuggingNewOperator | |||
| private: | |||
| const IODeviceType type; | |||
| AudioProcessorGraph* graph; | |||
| AudioGraphIOProcessor (const AudioGraphIOProcessor&); | |||
| const AudioGraphIOProcessor& operator= (const AudioGraphIOProcessor&); | |||
| }; | |||
| //============================================================================== | |||
| // AudioProcessor methods: | |||
| const String getName() const; | |||
| void prepareToPlay (double sampleRate, int estimatedSamplesPerBlock); | |||
| void releaseResources(); | |||
| void processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages); | |||
| const String getInputChannelName (const int channelIndex) const; | |||
| const String getOutputChannelName (const int channelIndex) const; | |||
| bool isInputChannelStereoPair (int index) const; | |||
| bool isOutputChannelStereoPair (int index) const; | |||
| bool acceptsMidi() const; | |||
| bool producesMidi() const; | |||
| AudioProcessorEditor* createEditor() { return 0; } | |||
| int getNumParameters() { return 0; } | |||
| const String getParameterName (int) { return String::empty; } | |||
| float getParameter (int) { return 0; } | |||
| const String getParameterText (int) { return String::empty; } | |||
| void setParameter (int, float) { } | |||
| int getNumPrograms() { return 0; } | |||
| int getCurrentProgram() { return 0; } | |||
| void setCurrentProgram (int) { } | |||
| const String getProgramName (int) { return String::empty; } | |||
| void changeProgramName (int, const String&) { } | |||
| void getStateInformation (JUCE_NAMESPACE::MemoryBlock& destData); | |||
| void setStateInformation (const void* data, int sizeInBytes); | |||
| /** @internal */ | |||
| void handleAsyncUpdate(); | |||
| //============================================================================== | |||
| juce_UseDebuggingNewOperator | |||
| private: | |||
| ReferenceCountedArray <Node> nodes; | |||
| OwnedArray <Connection> connections; | |||
| int lastNodeId; | |||
| AudioSampleBuffer renderingBuffers; | |||
| OwnedArray <MidiBuffer> midiBuffers; | |||
| CriticalSection renderLock; | |||
| VoidArray renderingOps; | |||
| friend class AudioGraphIOProcessor; | |||
| AudioSampleBuffer* currentAudioIOBuffer; | |||
| MidiBuffer* currentMidiIOBuffer; | |||
| void clearRenderingSequence(); | |||
| void buildRenderingSequence(); | |||
| bool isAnInputTo (const uint32 possibleInputId, | |||
| const uint32 possibleDestinationId, | |||
| const int recursionCheck) const throw(); | |||
| AudioProcessorGraph (const AudioProcessorGraph&); | |||
| const AudioProcessorGraph& operator= (const AudioProcessorGraph&); | |||
| }; | |||
| #endif // __JUCE_AUDIOPROCESSORGRAPH_JUCEHEADER__ | |||
| @@ -0,0 +1,207 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-7 by Raw Material Software ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the | |||
| GNU General Public License, as published by the Free Software Foundation; | |||
| either version 2 of the License, or (at your option) any later version. | |||
| JUCE is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with JUCE; if not, visit www.gnu.org/licenses or write to the | |||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||
| Boston, MA 02111-1307 USA | |||
| ------------------------------------------------------------------------------ | |||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||
| more information. | |||
| ============================================================================== | |||
| */ | |||
| #include "../../../juce_core/basics/juce_StandardHeader.h" | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_AudioProcessorPlayer.h" | |||
| #include "../../../juce_core/threads/juce_ScopedLock.h" | |||
| //============================================================================== | |||
| AudioProcessorPlayer::AudioProcessorPlayer() | |||
| : processor (0), | |||
| sampleRate (0), | |||
| blockSize (0), | |||
| isPrepared (false), | |||
| numInputChans (0), | |||
| numOutputChans (0), | |||
| tempBuffer (1, 1) | |||
| { | |||
| } | |||
| AudioProcessorPlayer::~AudioProcessorPlayer() | |||
| { | |||
| setProcessor (0); | |||
| } | |||
| //============================================================================== | |||
| void AudioProcessorPlayer::setProcessor (AudioProcessor* const processorToPlay) | |||
| { | |||
| if (processor != processorToPlay) | |||
| { | |||
| if (processorToPlay != 0 && sampleRate > 0 && blockSize > 0) | |||
| { | |||
| processorToPlay->setPlayConfigDetails (numInputChans, numOutputChans, | |||
| sampleRate, blockSize); | |||
| processorToPlay->prepareToPlay (sampleRate, blockSize); | |||
| } | |||
| lock.enter(); | |||
| AudioProcessor* const oldOne = isPrepared ? processor : 0; | |||
| processor = processorToPlay; | |||
| isPrepared = true; | |||
| lock.exit(); | |||
| if (oldOne != 0) | |||
| oldOne->releaseResources(); | |||
| } | |||
| } | |||
| //============================================================================== | |||
| void AudioProcessorPlayer::audioDeviceIOCallback (const float** inputChannelData, | |||
| int totalNumInputChannels, | |||
| float** outputChannelData, | |||
| int totalNumOutputChannels, | |||
| int numSamples) | |||
| { | |||
| // these should have been prepared by audioDeviceAboutToStart()... | |||
| jassert (sampleRate > 0 && blockSize > 0); | |||
| incomingMidi.clear(); | |||
| messageCollector.removeNextBlockOfMessages (incomingMidi, numSamples); | |||
| int i, numActiveChans = 0, numInputs = 0, numOutputs = 0; | |||
| // messy stuff needed to compact the channels down into an array | |||
| // of non-zero pointers.. | |||
| for (i = 0; i < totalNumInputChannels; ++i) | |||
| { | |||
| if (inputChannelData[i] != 0) | |||
| { | |||
| inputChans [numInputs++] = inputChannelData[i]; | |||
| if (numInputs >= numElementsInArray (inputChans)) | |||
| break; | |||
| } | |||
| } | |||
| for (i = 0; i < totalNumOutputChannels; ++i) | |||
| { | |||
| if (outputChannelData[i] != 0) | |||
| { | |||
| outputChans [numOutputs++] = outputChannelData[i]; | |||
| if (numOutputs >= numElementsInArray (outputChans)) | |||
| break; | |||
| } | |||
| } | |||
| if (numInputs > numOutputs) | |||
| { | |||
| // if there aren't enough output channels for the number of | |||
| // inputs, we need to create some temporary extra ones (can't | |||
| // use the input data in case it gets written to) | |||
| tempBuffer.setSize (numInputs - numOutputs, numSamples, | |||
| false, false, true); | |||
| for (i = 0; i < numOutputs; ++i) | |||
| { | |||
| channels[numActiveChans] = outputChans[i]; | |||
| memcpy (channels[numActiveChans], inputChans[i], sizeof (float) * numSamples); | |||
| ++numActiveChans; | |||
| } | |||
| for (i = numOutputs; i < numInputs; ++i) | |||
| { | |||
| channels[numActiveChans] = tempBuffer.getSampleData (i - numOutputs, 0); | |||
| memcpy (channels[numActiveChans], inputChans[i], sizeof (float) * numSamples); | |||
| ++numActiveChans; | |||
| } | |||
| } | |||
| else | |||
| { | |||
| for (i = 0; i < numInputs; ++i) | |||
| { | |||
| channels[numActiveChans] = outputChans[i]; | |||
| memcpy (channels[numActiveChans], inputChans[i], sizeof (float) * numSamples); | |||
| ++numActiveChans; | |||
| } | |||
| for (i = numInputs; i < numOutputs; ++i) | |||
| { | |||
| channels[numActiveChans] = outputChans[i]; | |||
| zeromem (channels[numActiveChans], sizeof (float) * numSamples); | |||
| ++numActiveChans; | |||
| } | |||
| } | |||
| AudioSampleBuffer buffer (channels, numActiveChans, numSamples); | |||
| const ScopedLock sl (lock); | |||
| if (processor != 0) | |||
| processor->processBlock (buffer, incomingMidi); | |||
| } | |||
| void AudioProcessorPlayer::audioDeviceAboutToStart (AudioIODevice* device) | |||
| { | |||
| const ScopedLock sl (lock); | |||
| sampleRate = device->getCurrentSampleRate(); | |||
| blockSize = device->getCurrentBufferSizeSamples(); | |||
| numInputChans = device->getActiveInputChannels().countNumberOfSetBits(); | |||
| numOutputChans = device->getActiveOutputChannels().countNumberOfSetBits(); | |||
| messageCollector.reset (sampleRate); | |||
| zeromem (channels, sizeof (channels)); | |||
| if (processor != 0) | |||
| { | |||
| if (isPrepared) | |||
| processor->releaseResources(); | |||
| AudioProcessor* const oldProcessor = processor; | |||
| setProcessor (0); | |||
| setProcessor (oldProcessor); | |||
| } | |||
| } | |||
| void AudioProcessorPlayer::audioDeviceStopped() | |||
| { | |||
| const ScopedLock sl (lock); | |||
| if (processor != 0 && isPrepared) | |||
| processor->releaseResources(); | |||
| sampleRate = 0.0; | |||
| blockSize = 0; | |||
| isPrepared = false; | |||
| tempBuffer.setSize (1, 1); | |||
| } | |||
| void AudioProcessorPlayer::handleIncomingMidiMessage (MidiInput*, const MidiMessage& message) | |||
| { | |||
| messageCollector.addMessageToQueue (message); | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| @@ -0,0 +1,121 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-7 by Raw Material Software ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the | |||
| GNU General Public License, as published by the Free Software Foundation; | |||
| either version 2 of the License, or (at your option) any later version. | |||
| JUCE is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with JUCE; if not, visit www.gnu.org/licenses or write to the | |||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||
| Boston, MA 02111-1307 USA | |||
| ------------------------------------------------------------------------------ | |||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||
| more information. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef __JUCE_AUDIOPROCESSORPLAYER_JUCEHEADER__ | |||
| #define __JUCE_AUDIOPROCESSORPLAYER_JUCEHEADER__ | |||
| #include "juce_AudioProcessor.h" | |||
| #include "../devices/juce_AudioIODevice.h" | |||
| #include "../devices/juce_MidiInput.h" | |||
| #include "../midi/juce_MidiMessageCollector.h" | |||
| //============================================================================== | |||
| /** | |||
| An AudioIODeviceCallback object which streams audio through an AudioProcessor. | |||
| To use one of these, just make it the callback used by your AudioIODevice, and | |||
| give it a processor to use by calling setProcessor(). | |||
| It's also a MidiInputCallback, so you can connect it to both an audio and midi | |||
| input to send both streams through the processor. | |||
| @see AudioProcessor, AudioProcessorGraph | |||
| */ | |||
| class JUCE_API AudioProcessorPlayer : public AudioIODeviceCallback, | |||
| public MidiInputCallback | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| /** | |||
| */ | |||
| AudioProcessorPlayer(); | |||
| /** Destructor. */ | |||
| virtual ~AudioProcessorPlayer(); | |||
| //============================================================================== | |||
| /** Sets the processor that should be played. | |||
| The processor that is passed in will not be deleted or owned by this object. | |||
| To stop anything playing, pass in 0 to this method. | |||
| */ | |||
| void setProcessor (AudioProcessor* const processorToPlay); | |||
| /** Returns the current audio processor that is being played. | |||
| */ | |||
| AudioProcessor* getCurrentProcessor() const throw() { return processor; } | |||
| /** Returns a midi message collector that you can pass midi messages to if you | |||
| want them to be injected into the midi stream that is being sent to the | |||
| processor. | |||
| */ | |||
| MidiMessageCollector& getMidiMessageCollector() throw() { return messageCollector; } | |||
| //============================================================================== | |||
| /** @internal */ | |||
| void audioDeviceIOCallback (const float** inputChannelData, | |||
| int totalNumInputChannels, | |||
| float** outputChannelData, | |||
| int totalNumOutputChannels, | |||
| int numSamples); | |||
| /** @internal */ | |||
| void audioDeviceAboutToStart (AudioIODevice* device); | |||
| /** @internal */ | |||
| void audioDeviceStopped(); | |||
| /** @internal */ | |||
| void handleIncomingMidiMessage (MidiInput* source, const MidiMessage& message); | |||
| //============================================================================== | |||
| juce_UseDebuggingNewOperator | |||
| private: | |||
| AudioProcessor* processor; | |||
| CriticalSection lock; | |||
| double sampleRate; | |||
| int blockSize; | |||
| bool isPrepared; | |||
| int numInputChans, numOutputChans; | |||
| float* channels [128]; | |||
| float* outputChans [128]; | |||
| const float* inputChans [128]; | |||
| AudioSampleBuffer tempBuffer; | |||
| MidiBuffer incomingMidi; | |||
| MidiMessageCollector messageCollector; | |||
| AudioProcessorPlayer (const AudioProcessorPlayer&); | |||
| const AudioProcessorPlayer& operator= (const AudioProcessorPlayer&); | |||
| }; | |||
| #endif // __JUCE_AUDIOPROCESSORPLAYER_JUCEHEADER__ | |||