Mod Wheel action + envelope display bugfix

pull/1/head
asb2m10 11 years ago
parent ca889efb42
commit 945055e380
  1. 48
      Builds/MacOSX/Dexed.xcodeproj/project.pbxproj
  2. BIN
      Builds/MacOSX/Dexed.xcodeproj/project.xcworkspace/xcuserdata/asb2m10.xcuserdatad/UserInterfaceState.xcuserstate
  3. 26
      Builds/VisualStudio2012/Dexed.vcxproj
  4. 48
      Builds/VisualStudio2012/Dexed.vcxproj.filters
  5. 26
      Builds/VisualStudio2013/Dexed.vcxproj
  6. 48
      Builds/VisualStudio2013/Dexed.vcxproj.filters
  7. 2
      JuceLibraryCode/modules/juce_audio_basics/juce_module_info
  8. 37
      JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiMessage.cpp
  9. 53
      JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiMessage.h
  10. 2
      JuceLibraryCode/modules/juce_audio_devices/juce_module_info
  11. 3
      JuceLibraryCode/modules/juce_audio_devices/native/juce_ios_Audio.cpp
  12. 88
      JuceLibraryCode/modules/juce_audio_devices/native/juce_mac_CoreAudio.cpp
  13. 2
      JuceLibraryCode/modules/juce_audio_formats/juce_module_info
  14. 42
      JuceLibraryCode/modules/juce_audio_plugin_client/AAX/juce_AAX_Wrapper.cpp
  15. 6
      JuceLibraryCode/modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm
  16. 2
      JuceLibraryCode/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h
  17. 102
      JuceLibraryCode/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp
  18. 284
      JuceLibraryCode/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.mm
  19. 7
      JuceLibraryCode/modules/juce_audio_plugin_client/juce_module_info
  20. 10
      JuceLibraryCode/modules/juce_audio_plugin_client/utility/juce_CheckSettingMacros.h
  21. 25
      JuceLibraryCode/modules/juce_audio_plugin_client/utility/juce_IncludeModuleHeaders.h
  22. 73
      JuceLibraryCode/modules/juce_audio_plugin_client/utility/juce_PluginHostType.h
  23. 58
      JuceLibraryCode/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm
  24. 618
      JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp
  25. 111
      JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp
  26. 7
      JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.h
  27. 67
      JuceLibraryCode/modules/juce_audio_processors/juce_audio_processors.cpp
  28. 4
      JuceLibraryCode/modules/juce_audio_processors/juce_audio_processors.h
  29. 2
      JuceLibraryCode/modules/juce_audio_processors/juce_module_info
  30. 1
      JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessor.h
  31. 26
      JuceLibraryCode/modules/juce_audio_processors/scanning/juce_KnownPluginList.cpp
  32. 21
      JuceLibraryCode/modules/juce_audio_processors/scanning/juce_KnownPluginList.h
  33. 1
      JuceLibraryCode/modules/juce_audio_processors/scanning/juce_PluginDirectoryScanner.cpp
  34. 9
      JuceLibraryCode/modules/juce_audio_processors/scanning/juce_PluginListComponent.cpp
  35. 15
      JuceLibraryCode/modules/juce_audio_utils/gui/juce_AudioDeviceSelectorComponent.cpp
  36. 19
      JuceLibraryCode/modules/juce_audio_utils/gui/juce_AudioThumbnail.cpp
  37. 72
      JuceLibraryCode/modules/juce_audio_utils/gui/juce_MidiKeyboardComponent.cpp
  38. 12
      JuceLibraryCode/modules/juce_audio_utils/gui/juce_MidiKeyboardComponent.h
  39. 2
      JuceLibraryCode/modules/juce_audio_utils/juce_module_info
  40. 27
      JuceLibraryCode/modules/juce_audio_utils/players/juce_AudioProcessorPlayer.cpp
  41. 15
      JuceLibraryCode/modules/juce_audio_utils/players/juce_AudioProcessorPlayer.h
  42. 3
      JuceLibraryCode/modules/juce_core/containers/juce_Array.h
  43. 19
      JuceLibraryCode/modules/juce_core/containers/juce_DynamicObject.cpp
  44. 8
      JuceLibraryCode/modules/juce_core/containers/juce_DynamicObject.h
  45. 2
      JuceLibraryCode/modules/juce_core/containers/juce_HashMap.h
  46. 51
      JuceLibraryCode/modules/juce_core/containers/juce_NamedValueSet.cpp
  47. 37
      JuceLibraryCode/modules/juce_core/containers/juce_NamedValueSet.h
  48. 10
      JuceLibraryCode/modules/juce_core/files/juce_DirectoryIterator.h
  49. 2
      JuceLibraryCode/modules/juce_core/files/juce_FileSearchPath.h
  50. 59
      JuceLibraryCode/modules/juce_core/javascript/juce_JSON.cpp
  51. 17
      JuceLibraryCode/modules/juce_core/javascript/juce_JSON.h
  52. 4
      JuceLibraryCode/modules/juce_core/juce_core.cpp
  53. 2
      JuceLibraryCode/modules/juce_core/juce_core.h
  54. 2
      JuceLibraryCode/modules/juce_core/juce_module_info
  55. 61
      JuceLibraryCode/modules/juce_core/maths/juce_BigInteger.h
  56. 8
      JuceLibraryCode/modules/juce_core/maths/juce_Expression.cpp
  57. 18
      JuceLibraryCode/modules/juce_core/maths/juce_Expression.h
  58. 4
      JuceLibraryCode/modules/juce_core/native/juce_android_Network.cpp
  59. 7
      JuceLibraryCode/modules/juce_core/native/juce_posix_NamedPipe.cpp
  60. 35
      JuceLibraryCode/modules/juce_core/native/juce_posix_SharedCode.h
  61. 28
      JuceLibraryCode/modules/juce_core/native/juce_win32_Threads.cpp
  62. 8
      JuceLibraryCode/modules/juce_core/network/juce_MACAddress.h
  63. 4
      JuceLibraryCode/modules/juce_core/streams/juce_OutputStream.cpp
  64. 2
      JuceLibraryCode/modules/juce_core/system/juce_StandardHeader.h
  65. 13
      JuceLibraryCode/modules/juce_core/text/juce_CharPointer_UTF8.h
  66. 15
      JuceLibraryCode/modules/juce_core/text/juce_LocalisedStrings.cpp
  67. 12
      JuceLibraryCode/modules/juce_core/text/juce_LocalisedStrings.h
  68. 8
      JuceLibraryCode/modules/juce_core/text/juce_String.cpp
  69. 4
      JuceLibraryCode/modules/juce_core/text/juce_String.h
  70. 20
      JuceLibraryCode/modules/juce_core/threads/juce_ChildProcess.cpp
  71. 3
      JuceLibraryCode/modules/juce_core/threads/juce_ChildProcess.h
  72. 91
      JuceLibraryCode/modules/juce_core/threads/juce_CriticalSection.h
  73. 2
      JuceLibraryCode/modules/juce_core/threads/juce_Thread.cpp
  74. 118
      JuceLibraryCode/modules/juce_core/threads/juce_ThreadPool.cpp
  75. 9
      JuceLibraryCode/modules/juce_core/threads/juce_ThreadPool.h
  76. 2
      JuceLibraryCode/modules/juce_core/time/juce_Time.cpp
  77. 26
      JuceLibraryCode/modules/juce_core/xml/juce_XmlDocument.cpp
  78. 20
      JuceLibraryCode/modules/juce_core/xml/juce_XmlDocument.h
  79. 2
      JuceLibraryCode/modules/juce_core/xml/juce_XmlElement.cpp
  80. 19
      JuceLibraryCode/modules/juce_data_structures/app_properties/juce_PropertiesFile.cpp
  81. 2
      JuceLibraryCode/modules/juce_data_structures/app_properties/juce_PropertiesFile.h
  82. 2
      JuceLibraryCode/modules/juce_data_structures/juce_module_info
  83. 2
      JuceLibraryCode/modules/juce_events/broadcasters/juce_ActionBroadcaster.h
  84. 5
      JuceLibraryCode/modules/juce_events/broadcasters/juce_ActionListener.h
  85. 41
      JuceLibraryCode/modules/juce_events/interprocess/juce_InterprocessConnection.cpp
  86. 11
      JuceLibraryCode/modules/juce_events/interprocess/juce_InterprocessConnection.h
  87. 1
      JuceLibraryCode/modules/juce_events/juce_events.cpp
  88. 1
      JuceLibraryCode/modules/juce_events/juce_events.h
  89. 2
      JuceLibraryCode/modules/juce_events/juce_module_info
  90. 2
      JuceLibraryCode/modules/juce_graphics/colour/juce_Colour.cpp
  91. 10
      JuceLibraryCode/modules/juce_graphics/colour/juce_ColourGradient.h
  92. 12
      JuceLibraryCode/modules/juce_graphics/colour/juce_FillType.h
  93. 24
      JuceLibraryCode/modules/juce_graphics/contexts/juce_GraphicsContext.cpp
  94. 14
      JuceLibraryCode/modules/juce_graphics/contexts/juce_GraphicsContext.h
  95. 4
      JuceLibraryCode/modules/juce_graphics/fonts/juce_CustomTypeface.cpp
  96. 2
      JuceLibraryCode/modules/juce_graphics/fonts/juce_CustomTypeface.h
  97. 8
      JuceLibraryCode/modules/juce_graphics/fonts/juce_GlyphArrangement.h
  98. 138
      JuceLibraryCode/modules/juce_graphics/fonts/juce_Typeface.cpp
  99. 13
      JuceLibraryCode/modules/juce_graphics/fonts/juce_Typeface.h
  100. 6
      JuceLibraryCode/modules/juce_graphics/geometry/juce_EdgeTable.h
  101. Some files were not shown because too many files have changed in this diff Show More

@ -58,6 +58,8 @@
E293B9570C97E4BAD129D4A2 = { isa = PBXBuildFile; fileRef = FE39DD2B654DF778D919D554; }; E293B9570C97E4BAD129D4A2 = { isa = PBXBuildFile; fileRef = FE39DD2B654DF778D919D554; };
A6E2908774D7F669F21B1874 = { isa = PBXBuildFile; fileRef = C7C6039A52C3EE370CA9E73A; }; A6E2908774D7F669F21B1874 = { isa = PBXBuildFile; fileRef = C7C6039A52C3EE370CA9E73A; };
B82FDEB3E53C9455BC6A5DAE = { isa = PBXBuildFile; fileRef = EAA5D8078BCC042BDF94C77A; settings = {COMPILER_FLAGS = "-w"; }; }; B82FDEB3E53C9455BC6A5DAE = { isa = PBXBuildFile; fileRef = EAA5D8078BCC042BDF94C77A; settings = {COMPILER_FLAGS = "-w"; }; };
52C0C94470D90310AF2F8433 = { isa = PBXBuildFile; fileRef = D0178A36F6E46F92111E4883; };
13F8BF7C26D50908163425CF = { isa = PBXBuildFile; fileRef = 01EF232D8B427B8CE38127C2; };
00C044DBB8BA1AF35CBC42E6 = { isa = PBXBuildFile; fileRef = D6C6FCBA5ECA257959BFE674; }; 00C044DBB8BA1AF35CBC42E6 = { isa = PBXBuildFile; fileRef = D6C6FCBA5ECA257959BFE674; };
E8D9A2B640A87FE92D2DA887 = { isa = PBXBuildFile; fileRef = F6F950B6ABB40B62AE4C0B78; }; E8D9A2B640A87FE92D2DA887 = { isa = PBXBuildFile; fileRef = F6F950B6ABB40B62AE4C0B78; };
001A2BCC899370ADC99A8F3A = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_FileChooser.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileChooser.h"; sourceTree = "SOURCE_ROOT"; }; 001A2BCC899370ADC99A8F3A = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_FileChooser.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileChooser.h"; sourceTree = "SOURCE_ROOT"; };
@ -65,6 +67,7 @@
00FDFD1ABE59B4CEF74BF5A3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = env.cc; path = ../../Source/msfa/env.cc; sourceTree = "SOURCE_ROOT"; }; 00FDFD1ABE59B4CEF74BF5A3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = env.cc; path = ../../Source/msfa/env.cc; sourceTree = "SOURCE_ROOT"; };
015FE0A32C2B3FDA879FAB57 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_DragAndDropContainer.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.h"; sourceTree = "SOURCE_ROOT"; }; 015FE0A32C2B3FDA879FAB57 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_DragAndDropContainer.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.h"; sourceTree = "SOURCE_ROOT"; };
018D0FB9E97B68D2EB3E3F72 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = PluginEditor.cpp; path = ../../Source/PluginEditor.cpp; sourceTree = "SOURCE_ROOT"; }; 018D0FB9E97B68D2EB3E3F72 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = PluginEditor.cpp; path = ../../Source/PluginEditor.cpp; sourceTree = "SOURCE_ROOT"; };
01EF232D8B427B8CE38127C2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_VST3_Wrapper.mm"; path = "../../JuceLibraryCode/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.mm"; sourceTree = "SOURCE_ROOT"; };
02139A14E2732DE36631414F = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_TableHeaderComponent.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/widgets/juce_TableHeaderComponent.cpp"; sourceTree = "SOURCE_ROOT"; }; 02139A14E2732DE36631414F = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_TableHeaderComponent.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/widgets/juce_TableHeaderComponent.cpp"; sourceTree = "SOURCE_ROOT"; };
0236A082C107280C1505021A = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ImageConvolutionKernel.h"; path = "../../JuceLibraryCode/modules/juce_graphics/images/juce_ImageConvolutionKernel.h"; sourceTree = "SOURCE_ROOT"; }; 0236A082C107280C1505021A = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ImageConvolutionKernel.h"; path = "../../JuceLibraryCode/modules/juce_graphics/images/juce_ImageConvolutionKernel.h"; sourceTree = "SOURCE_ROOT"; };
02E962E65624D43B0906B0C6 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_PerformanceCounter.cpp"; path = "../../JuceLibraryCode/modules/juce_core/time/juce_PerformanceCounter.cpp"; sourceTree = "SOURCE_ROOT"; }; 02E962E65624D43B0906B0C6 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_PerformanceCounter.cpp"; path = "../../JuceLibraryCode/modules/juce_core/time/juce_PerformanceCounter.cpp"; sourceTree = "SOURCE_ROOT"; };
@ -84,6 +87,7 @@
06C4DD7797E7526DB1B47AE5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_IPAddress.cpp"; path = "../../JuceLibraryCode/modules/juce_core/network/juce_IPAddress.cpp"; sourceTree = "SOURCE_ROOT"; }; 06C4DD7797E7526DB1B47AE5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_IPAddress.cpp"; path = "../../JuceLibraryCode/modules/juce_core/network/juce_IPAddress.cpp"; sourceTree = "SOURCE_ROOT"; };
07037505B34930CDA76B04A5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_StretchableObjectResizer.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_StretchableObjectResizer.cpp"; sourceTree = "SOURCE_ROOT"; }; 07037505B34930CDA76B04A5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_StretchableObjectResizer.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_StretchableObjectResizer.cpp"; sourceTree = "SOURCE_ROOT"; };
0707C87B401DC983E3FF4263 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_MathsFunctions.h"; path = "../../JuceLibraryCode/modules/juce_core/maths/juce_MathsFunctions.h"; sourceTree = "SOURCE_ROOT"; }; 0707C87B401DC983E3FF4263 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_MathsFunctions.h"; path = "../../JuceLibraryCode/modules/juce_core/maths/juce_MathsFunctions.h"; sourceTree = "SOURCE_ROOT"; };
07333A7932C6B7538F4DF21F = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_VST3Headers.h"; path = "../../JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VST3Headers.h"; sourceTree = "SOURCE_ROOT"; };
0733471B6DA02299D2C9590A = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_StringArray.cpp"; path = "../../JuceLibraryCode/modules/juce_core/text/juce_StringArray.cpp"; sourceTree = "SOURCE_ROOT"; }; 0733471B6DA02299D2C9590A = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_StringArray.cpp"; path = "../../JuceLibraryCode/modules/juce_core/text/juce_StringArray.cpp"; sourceTree = "SOURCE_ROOT"; };
075BB641199B15A84856DE6E = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_SliderPropertyComponent.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/properties/juce_SliderPropertyComponent.cpp"; sourceTree = "SOURCE_ROOT"; }; 075BB641199B15A84856DE6E = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_SliderPropertyComponent.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/properties/juce_SliderPropertyComponent.cpp"; sourceTree = "SOURCE_ROOT"; };
076C4F22CCC47AFEAC2D0C68 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_LuaCodeTokeniser.h"; path = "../../JuceLibraryCode/modules/juce_gui_extra/code_editor/juce_LuaCodeTokeniser.h"; sourceTree = "SOURCE_ROOT"; }; 076C4F22CCC47AFEAC2D0C68 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_LuaCodeTokeniser.h"; path = "../../JuceLibraryCode/modules/juce_gui_extra/code_editor/juce_LuaCodeTokeniser.h"; sourceTree = "SOURCE_ROOT"; };
@ -127,6 +131,7 @@
170F06D00B2197E66300D558 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_TextPropertyComponent.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/properties/juce_TextPropertyComponent.h"; sourceTree = "SOURCE_ROOT"; }; 170F06D00B2197E66300D558 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_TextPropertyComponent.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/properties/juce_TextPropertyComponent.h"; sourceTree = "SOURCE_ROOT"; };
1754400A2E372510CB25043F = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_TopLevelWindow.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/windows/juce_TopLevelWindow.h"; sourceTree = "SOURCE_ROOT"; }; 1754400A2E372510CB25043F = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_TopLevelWindow.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/windows/juce_TopLevelWindow.h"; sourceTree = "SOURCE_ROOT"; };
1756BAFDC82F5E69704BEAFE = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ComponentMovementWatcher.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentMovementWatcher.cpp"; sourceTree = "SOURCE_ROOT"; }; 1756BAFDC82F5E69704BEAFE = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ComponentMovementWatcher.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentMovementWatcher.cpp"; sourceTree = "SOURCE_ROOT"; };
17A328AD02B5D7DA362E1D5D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ConnectedChildProcess.cpp"; path = "../../JuceLibraryCode/modules/juce_events/interprocess/juce_ConnectedChildProcess.cpp"; sourceTree = "SOURCE_ROOT"; };
17C3024C2A1EE03BC0ED9C96 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_mac_Windowing.mm"; path = "../../JuceLibraryCode/modules/juce_gui_basics/native/juce_mac_Windowing.mm"; sourceTree = "SOURCE_ROOT"; }; 17C3024C2A1EE03BC0ED9C96 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_mac_Windowing.mm"; path = "../../JuceLibraryCode/modules/juce_gui_basics/native/juce_mac_Windowing.mm"; sourceTree = "SOURCE_ROOT"; };
17ED00953353016B7E7492B0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ApplicationCommandInfo.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandInfo.cpp"; sourceTree = "SOURCE_ROOT"; }; 17ED00953353016B7E7492B0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ApplicationCommandInfo.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandInfo.cpp"; sourceTree = "SOURCE_ROOT"; };
18AD1662D33E576F96C30A6A = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_TopLevelWindow.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/windows/juce_TopLevelWindow.cpp"; sourceTree = "SOURCE_ROOT"; }; 18AD1662D33E576F96C30A6A = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_TopLevelWindow.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/windows/juce_TopLevelWindow.cpp"; sourceTree = "SOURCE_ROOT"; };
@ -197,6 +202,7 @@
2B455841042E415B99DEE263 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_SpinLock.h"; path = "../../JuceLibraryCode/modules/juce_core/threads/juce_SpinLock.h"; sourceTree = "SOURCE_ROOT"; }; 2B455841042E415B99DEE263 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_SpinLock.h"; path = "../../JuceLibraryCode/modules/juce_core/threads/juce_SpinLock.h"; sourceTree = "SOURCE_ROOT"; };
2BAC9F6B6869D1E85C51540B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Expression.h"; path = "../../JuceLibraryCode/modules/juce_core/maths/juce_Expression.h"; sourceTree = "SOURCE_ROOT"; }; 2BAC9F6B6869D1E85C51540B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Expression.h"; path = "../../JuceLibraryCode/modules/juce_core/maths/juce_Expression.h"; sourceTree = "SOURCE_ROOT"; };
2BEBDED2BACDEEEE975583F3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_StringPool.h"; path = "../../JuceLibraryCode/modules/juce_core/text/juce_StringPool.h"; sourceTree = "SOURCE_ROOT"; }; 2BEBDED2BACDEEEE975583F3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_StringPool.h"; path = "../../JuceLibraryCode/modules/juce_core/text/juce_StringPool.h"; sourceTree = "SOURCE_ROOT"; };
2C65FDA74486C92DF5EA5C87 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_FileFilter.h"; path = "../../JuceLibraryCode/modules/juce_core/files/juce_FileFilter.h"; sourceTree = "SOURCE_ROOT"; };
2CA19470CA427333F8CAC0A5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ImagePreviewComponent.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_ImagePreviewComponent.cpp"; sourceTree = "SOURCE_ROOT"; }; 2CA19470CA427333F8CAC0A5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ImagePreviewComponent.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_ImagePreviewComponent.cpp"; sourceTree = "SOURCE_ROOT"; };
2CB4C73C121FCDEF65CBAC79 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_mac_MainMenu.mm"; path = "../../JuceLibraryCode/modules/juce_gui_basics/native/juce_mac_MainMenu.mm"; sourceTree = "SOURCE_ROOT"; }; 2CB4C73C121FCDEF65CBAC79 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_mac_MainMenu.mm"; path = "../../JuceLibraryCode/modules/juce_gui_basics/native/juce_mac_MainMenu.mm"; sourceTree = "SOURCE_ROOT"; };
2D26E2304C0F6FC633936014 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = lfo.cc; path = ../../Source/msfa/lfo.cc; sourceTree = "SOURCE_ROOT"; }; 2D26E2304C0F6FC633936014 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = lfo.cc; path = ../../Source/msfa/lfo.cc; sourceTree = "SOURCE_ROOT"; };
@ -235,7 +241,6 @@
3444F7C54161FEB1F844619E = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_IPAddress.h"; path = "../../JuceLibraryCode/modules/juce_core/network/juce_IPAddress.h"; sourceTree = "SOURCE_ROOT"; }; 3444F7C54161FEB1F844619E = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_IPAddress.h"; path = "../../JuceLibraryCode/modules/juce_core/network/juce_IPAddress.h"; sourceTree = "SOURCE_ROOT"; };
346937AF08405CC63D570161 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_FileBasedDocument.h"; path = "../../JuceLibraryCode/modules/juce_gui_extra/documents/juce_FileBasedDocument.h"; sourceTree = "SOURCE_ROOT"; }; 346937AF08405CC63D570161 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_FileBasedDocument.h"; path = "../../JuceLibraryCode/modules/juce_gui_extra/documents/juce_FileBasedDocument.h"; sourceTree = "SOURCE_ROOT"; };
349B7AFA001B78E62A9AFABB = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_KeyListener.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyListener.cpp"; sourceTree = "SOURCE_ROOT"; }; 349B7AFA001B78E62A9AFABB = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_KeyListener.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyListener.cpp"; sourceTree = "SOURCE_ROOT"; };
35865817C4ED48DCD346B5D9 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_WildcardFileFilter.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_WildcardFileFilter.cpp"; sourceTree = "SOURCE_ROOT"; };
35892C1EF9CEA7C1F1C9109F = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_TabbedComponent.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_TabbedComponent.h"; sourceTree = "SOURCE_ROOT"; }; 35892C1EF9CEA7C1F1C9109F = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_TabbedComponent.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_TabbedComponent.h"; sourceTree = "SOURCE_ROOT"; };
3597896505C601CE1FFE1158 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ApplicationCommandManager.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandManager.h"; sourceTree = "SOURCE_ROOT"; }; 3597896505C601CE1FFE1158 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ApplicationCommandManager.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandManager.h"; sourceTree = "SOURCE_ROOT"; };
35F80132DF4DC3669B44BD4A = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_LowLevelGraphicsPostScriptRenderer.h"; path = "../../JuceLibraryCode/modules/juce_graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.h"; sourceTree = "SOURCE_ROOT"; }; 35F80132DF4DC3669B44BD4A = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_LowLevelGraphicsPostScriptRenderer.h"; path = "../../JuceLibraryCode/modules/juce_graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.h"; sourceTree = "SOURCE_ROOT"; };
@ -270,6 +275,7 @@
4051235A3DA7534A8E1286F0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ComponentDragger.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/mouse/juce_ComponentDragger.h"; sourceTree = "SOURCE_ROOT"; }; 4051235A3DA7534A8E1286F0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ComponentDragger.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/mouse/juce_ComponentDragger.h"; sourceTree = "SOURCE_ROOT"; };
40ACF762CE264F32184C4F7D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_HighResolutionTimer.cpp"; path = "../../JuceLibraryCode/modules/juce_core/threads/juce_HighResolutionTimer.cpp"; sourceTree = "SOURCE_ROOT"; }; 40ACF762CE264F32184C4F7D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_HighResolutionTimer.cpp"; path = "../../JuceLibraryCode/modules/juce_core/threads/juce_HighResolutionTimer.cpp"; sourceTree = "SOURCE_ROOT"; };
40D83B00A8BBE334104EB694 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_RectangleList.h"; path = "../../JuceLibraryCode/modules/juce_graphics/geometry/juce_RectangleList.h"; sourceTree = "SOURCE_ROOT"; }; 40D83B00A8BBE334104EB694 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_RectangleList.h"; path = "../../JuceLibraryCode/modules/juce_graphics/geometry/juce_RectangleList.h"; sourceTree = "SOURCE_ROOT"; };
40DCD07DB4B1D9FBB9D47BE5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ConnectedChildProcess.h"; path = "../../JuceLibraryCode/modules/juce_events/interprocess/juce_ConnectedChildProcess.h"; sourceTree = "SOURCE_ROOT"; };
413E92912A2C8CACB46AFD3B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_SliderPropertyComponent.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/properties/juce_SliderPropertyComponent.h"; sourceTree = "SOURCE_ROOT"; }; 413E92912A2C8CACB46AFD3B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_SliderPropertyComponent.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/properties/juce_SliderPropertyComponent.h"; sourceTree = "SOURCE_ROOT"; };
4166468539A5F6E92A7A153E = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ReferenceCountedArray.h"; path = "../../JuceLibraryCode/modules/juce_core/containers/juce_ReferenceCountedArray.h"; sourceTree = "SOURCE_ROOT"; }; 4166468539A5F6E92A7A153E = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ReferenceCountedArray.h"; path = "../../JuceLibraryCode/modules/juce_core/containers/juce_ReferenceCountedArray.h"; sourceTree = "SOURCE_ROOT"; };
41700CC92AEEF157D3B53BA2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Drawable.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/drawables/juce_Drawable.h"; sourceTree = "SOURCE_ROOT"; }; 41700CC92AEEF157D3B53BA2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Drawable.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/drawables/juce_Drawable.h"; sourceTree = "SOURCE_ROOT"; };
@ -297,7 +303,6 @@
462B768DFC2129F54233D51D = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_StretchableLayoutResizerBar.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_StretchableLayoutResizerBar.h"; sourceTree = "SOURCE_ROOT"; }; 462B768DFC2129F54233D51D = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_StretchableLayoutResizerBar.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_StretchableLayoutResizerBar.h"; sourceTree = "SOURCE_ROOT"; };
46908987EEFC3623A53A95C2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_LagrangeInterpolator.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_basics/effects/juce_LagrangeInterpolator.cpp"; sourceTree = "SOURCE_ROOT"; }; 46908987EEFC3623A53A95C2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_LagrangeInterpolator.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_basics/effects/juce_LagrangeInterpolator.cpp"; sourceTree = "SOURCE_ROOT"; };
46969E6B78BC89383358DCDA = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_XMLCodeTokeniser.h"; path = "../../JuceLibraryCode/modules/juce_gui_extra/code_editor/juce_XMLCodeTokeniser.h"; sourceTree = "SOURCE_ROOT"; }; 46969E6B78BC89383358DCDA = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_XMLCodeTokeniser.h"; path = "../../JuceLibraryCode/modules/juce_gui_extra/code_editor/juce_XMLCodeTokeniser.h"; sourceTree = "SOURCE_ROOT"; };
46B8FB88F2949700DD70A821 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_WildcardFileFilter.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_WildcardFileFilter.h"; sourceTree = "SOURCE_ROOT"; };
46C20298CCB469481F5C8D36 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_MouseInactivityDetector.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseInactivityDetector.h"; sourceTree = "SOURCE_ROOT"; }; 46C20298CCB469481F5C8D36 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_MouseInactivityDetector.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseInactivityDetector.h"; sourceTree = "SOURCE_ROOT"; };
4710CA869326390AF0CE2A0B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ResizableEdgeComponent.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableEdgeComponent.h"; sourceTree = "SOURCE_ROOT"; }; 4710CA869326390AF0CE2A0B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ResizableEdgeComponent.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableEdgeComponent.h"; sourceTree = "SOURCE_ROOT"; };
47168956BF1BAC3FCBD55BB8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_posix_NamedPipe.cpp"; path = "../../JuceLibraryCode/modules/juce_core/native/juce_posix_NamedPipe.cpp"; sourceTree = "SOURCE_ROOT"; }; 47168956BF1BAC3FCBD55BB8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_posix_NamedPipe.cpp"; path = "../../JuceLibraryCode/modules/juce_core/native/juce_posix_NamedPipe.cpp"; sourceTree = "SOURCE_ROOT"; };
@ -446,7 +451,6 @@
7936BBAA586387B2FAFB958B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = PluginData.cpp; path = ../../Source/PluginData.cpp; sourceTree = "SOURCE_ROOT"; }; 7936BBAA586387B2FAFB958B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = PluginData.cpp; path = ../../Source/PluginData.cpp; sourceTree = "SOURCE_ROOT"; };
7A0FB6545BA2E344A1F45EA5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Decibels.h"; path = "../../JuceLibraryCode/modules/juce_audio_basics/effects/juce_Decibels.h"; sourceTree = "SOURCE_ROOT"; }; 7A0FB6545BA2E344A1F45EA5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Decibels.h"; path = "../../JuceLibraryCode/modules/juce_audio_basics/effects/juce_Decibels.h"; sourceTree = "SOURCE_ROOT"; };
7A26D67672786E0663369D49 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_IIRFilterAudioSource.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_basics/sources/juce_IIRFilterAudioSource.cpp"; sourceTree = "SOURCE_ROOT"; }; 7A26D67672786E0663369D49 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_IIRFilterAudioSource.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_basics/sources/juce_IIRFilterAudioSource.cpp"; sourceTree = "SOURCE_ROOT"; };
7A38190CB0652B0EBA02100C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_FileFilter.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileFilter.cpp"; sourceTree = "SOURCE_ROOT"; };
7A739B1B4B833A4668904CA6 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ReferenceCountedObject.h"; path = "../../JuceLibraryCode/modules/juce_core/memory/juce_ReferenceCountedObject.h"; sourceTree = "SOURCE_ROOT"; }; 7A739B1B4B833A4668904CA6 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ReferenceCountedObject.h"; path = "../../JuceLibraryCode/modules/juce_core/memory/juce_ReferenceCountedObject.h"; sourceTree = "SOURCE_ROOT"; };
7A854175B4E6D35ABB7D4E45 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_URL.h"; path = "../../JuceLibraryCode/modules/juce_core/network/juce_URL.h"; sourceTree = "SOURCE_ROOT"; }; 7A854175B4E6D35ABB7D4E45 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_URL.h"; path = "../../JuceLibraryCode/modules/juce_core/network/juce_URL.h"; sourceTree = "SOURCE_ROOT"; };
7A905E3EE096DAA1D7BA7ABD = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_TabbedButtonBar.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_TabbedButtonBar.cpp"; sourceTree = "SOURCE_ROOT"; }; 7A905E3EE096DAA1D7BA7ABD = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_TabbedButtonBar.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_TabbedButtonBar.cpp"; sourceTree = "SOURCE_ROOT"; };
@ -456,8 +460,10 @@
7C2634F55C78A3822A661CE2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_XmlElement.cpp"; path = "../../JuceLibraryCode/modules/juce_core/xml/juce_XmlElement.cpp"; sourceTree = "SOURCE_ROOT"; }; 7C2634F55C78A3822A661CE2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_XmlElement.cpp"; path = "../../JuceLibraryCode/modules/juce_core/xml/juce_XmlElement.cpp"; sourceTree = "SOURCE_ROOT"; };
7CDDAFACA226D14742566EE3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_StringPairArray.cpp"; path = "../../JuceLibraryCode/modules/juce_core/text/juce_StringPairArray.cpp"; sourceTree = "SOURCE_ROOT"; }; 7CDDAFACA226D14742566EE3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_StringPairArray.cpp"; path = "../../JuceLibraryCode/modules/juce_core/text/juce_StringPairArray.cpp"; sourceTree = "SOURCE_ROOT"; };
7D5E3634F29C83FE1216E5EC = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_DragAndDropContainer.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp"; sourceTree = "SOURCE_ROOT"; }; 7D5E3634F29C83FE1216E5EC = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_DragAndDropContainer.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp"; sourceTree = "SOURCE_ROOT"; };
7DC83451FCA10947AC92EBBC = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_VST3Common.h"; path = "../../JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VST3Common.h"; sourceTree = "SOURCE_ROOT"; };
7E68BB771E88E0A2A323D365 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_CPlusPlusCodeTokeniser.h"; path = "../../JuceLibraryCode/modules/juce_gui_extra/code_editor/juce_CPlusPlusCodeTokeniser.h"; sourceTree = "SOURCE_ROOT"; }; 7E68BB771E88E0A2A323D365 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_CPlusPlusCodeTokeniser.h"; path = "../../JuceLibraryCode/modules/juce_gui_extra/code_editor/juce_CPlusPlusCodeTokeniser.h"; sourceTree = "SOURCE_ROOT"; };
7EC7AB8D0C164E19F70A4D8C = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ModifierKeys.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_ModifierKeys.h"; sourceTree = "SOURCE_ROOT"; }; 7EC7AB8D0C164E19F70A4D8C = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ModifierKeys.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_ModifierKeys.h"; sourceTree = "SOURCE_ROOT"; };
7ECA74A2FC82F26715446C70 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_FileFilter.cpp"; path = "../../JuceLibraryCode/modules/juce_core/files/juce_FileFilter.cpp"; sourceTree = "SOURCE_ROOT"; };
7F081876B753390FC305329F = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Thread.cpp"; path = "../../JuceLibraryCode/modules/juce_core/threads/juce_Thread.cpp"; sourceTree = "SOURCE_ROOT"; }; 7F081876B753390FC305329F = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Thread.cpp"; path = "../../JuceLibraryCode/modules/juce_core/threads/juce_Thread.cpp"; sourceTree = "SOURCE_ROOT"; };
7F0B06EA0B38D4555CFEBA61 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_MemoryBlock.h"; path = "../../JuceLibraryCode/modules/juce_core/memory/juce_MemoryBlock.h"; sourceTree = "SOURCE_ROOT"; }; 7F0B06EA0B38D4555CFEBA61 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_MemoryBlock.h"; path = "../../JuceLibraryCode/modules/juce_core/memory/juce_MemoryBlock.h"; sourceTree = "SOURCE_ROOT"; };
7F63546442D6681E7AA27CB8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_KeyPress.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyPress.h"; sourceTree = "SOURCE_ROOT"; }; 7F63546442D6681E7AA27CB8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_KeyPress.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyPress.h"; sourceTree = "SOURCE_ROOT"; };
@ -467,6 +473,7 @@
80153220EFB623D6F205FD1B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_MenuBarComponent.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/menus/juce_MenuBarComponent.cpp"; sourceTree = "SOURCE_ROOT"; }; 80153220EFB623D6F205FD1B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_MenuBarComponent.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/menus/juce_MenuBarComponent.cpp"; sourceTree = "SOURCE_ROOT"; };
8141C52E88E3E82A0A226FAD = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_KeyPress.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyPress.cpp"; sourceTree = "SOURCE_ROOT"; }; 8141C52E88E3E82A0A226FAD = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_KeyPress.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyPress.cpp"; sourceTree = "SOURCE_ROOT"; };
817CC81F50861DAEEFB2043A = { isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; }; 817CC81F50861DAEEFB2043A = { isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; };
829D2BFEB85DC3589FEBB868 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_WildcardFileFilter.cpp"; path = "../../JuceLibraryCode/modules/juce_core/files/juce_WildcardFileFilter.cpp"; sourceTree = "SOURCE_ROOT"; };
8312A52619B88D3763F6B493 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_LookAndFeel_V3.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V3.cpp"; sourceTree = "SOURCE_ROOT"; }; 8312A52619B88D3763F6B493 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_LookAndFeel_V3.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V3.cpp"; sourceTree = "SOURCE_ROOT"; };
834F3F9FC2FE9564FF95243D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_win32_Fonts.cpp"; path = "../../JuceLibraryCode/modules/juce_graphics/native/juce_win32_Fonts.cpp"; sourceTree = "SOURCE_ROOT"; }; 834F3F9FC2FE9564FF95243D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_win32_Fonts.cpp"; path = "../../JuceLibraryCode/modules/juce_graphics/native/juce_win32_Fonts.cpp"; sourceTree = "SOURCE_ROOT"; };
838E63F5800CA577B92EF6AE = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = OperatorEditor.cpp; path = ../../Source/OperatorEditor.cpp; sourceTree = "SOURCE_ROOT"; }; 838E63F5800CA577B92EF6AE = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = OperatorEditor.cpp; path = ../../Source/OperatorEditor.cpp; sourceTree = "SOURCE_ROOT"; };
@ -710,10 +717,10 @@
CF348935D8F88A548C0FB249 = { isa = PBXFileReference; lastKnownFileType = file; name = "juce_module_info"; path = "../../../JUCE/modules/juce_events/juce_module_info"; sourceTree = "SOURCE_ROOT"; }; CF348935D8F88A548C0FB249 = { isa = PBXFileReference; lastKnownFileType = file; name = "juce_module_info"; path = "../../../JUCE/modules/juce_events/juce_module_info"; sourceTree = "SOURCE_ROOT"; };
CFFA7532FAFF5655253878FE = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_Threads.cpp"; path = "../../JuceLibraryCode/modules/juce_core/native/juce_android_Threads.cpp"; sourceTree = "SOURCE_ROOT"; }; CFFA7532FAFF5655253878FE = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_Threads.cpp"; path = "../../JuceLibraryCode/modules/juce_core/native/juce_android_Threads.cpp"; sourceTree = "SOURCE_ROOT"; };
D0096F2804DF0875565D0051 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_AudioDataConverters.h"; path = "../../JuceLibraryCode/modules/juce_audio_basics/buffers/juce_AudioDataConverters.h"; sourceTree = "SOURCE_ROOT"; }; D0096F2804DF0875565D0051 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_AudioDataConverters.h"; path = "../../JuceLibraryCode/modules/juce_audio_basics/buffers/juce_AudioDataConverters.h"; sourceTree = "SOURCE_ROOT"; };
D0178A36F6E46F92111E4883 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_VST3_Wrapper.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp"; sourceTree = "SOURCE_ROOT"; };
D1353A684AD92A6A9FAFBB1B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_DynamicObject.cpp"; path = "../../JuceLibraryCode/modules/juce_core/containers/juce_DynamicObject.cpp"; sourceTree = "SOURCE_ROOT"; }; D1353A684AD92A6A9FAFBB1B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_DynamicObject.cpp"; path = "../../JuceLibraryCode/modules/juce_core/containers/juce_DynamicObject.cpp"; sourceTree = "SOURCE_ROOT"; };
D154251B66BF13E992D3D06A = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_SystemTrayIconComponent.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_extra/misc/juce_SystemTrayIconComponent.cpp"; sourceTree = "SOURCE_ROOT"; }; D154251B66BF13E992D3D06A = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_SystemTrayIconComponent.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_extra/misc/juce_SystemTrayIconComponent.cpp"; sourceTree = "SOURCE_ROOT"; };
D17049595AD1C1353337817D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ImageConvolutionKernel.cpp"; path = "../../JuceLibraryCode/modules/juce_graphics/images/juce_ImageConvolutionKernel.cpp"; sourceTree = "SOURCE_ROOT"; }; D17049595AD1C1353337817D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ImageConvolutionKernel.cpp"; path = "../../JuceLibraryCode/modules/juce_graphics/images/juce_ImageConvolutionKernel.cpp"; sourceTree = "SOURCE_ROOT"; };
D1BA8296F20CACB8F81B7316 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_FileFilter.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileFilter.h"; sourceTree = "SOURCE_ROOT"; };
D1BEED433BFC4AA10346BE1C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_FileSearchPath.cpp"; path = "../../JuceLibraryCode/modules/juce_core/files/juce_FileSearchPath.cpp"; sourceTree = "SOURCE_ROOT"; }; D1BEED433BFC4AA10346BE1C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_FileSearchPath.cpp"; path = "../../JuceLibraryCode/modules/juce_core/files/juce_FileSearchPath.cpp"; sourceTree = "SOURCE_ROOT"; };
D25566BCBFE5CCA4E425E6A7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Variant.h"; path = "../../JuceLibraryCode/modules/juce_core/containers/juce_Variant.h"; sourceTree = "SOURCE_ROOT"; }; D25566BCBFE5CCA4E425E6A7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Variant.h"; path = "../../JuceLibraryCode/modules/juce_core/containers/juce_Variant.h"; sourceTree = "SOURCE_ROOT"; };
D2E57CCA4E6F6DBE2953744C = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ComponentBoundsConstrainer.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentBoundsConstrainer.h"; sourceTree = "SOURCE_ROOT"; }; D2E57CCA4E6F6DBE2953744C = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ComponentBoundsConstrainer.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentBoundsConstrainer.h"; sourceTree = "SOURCE_ROOT"; };
@ -864,6 +871,7 @@
FF46344F53B1AE5119D163D5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_CarbonVisibility.h"; path = "../../JuceLibraryCode/modules/juce_audio_plugin_client/utility/juce_CarbonVisibility.h"; sourceTree = "SOURCE_ROOT"; }; FF46344F53B1AE5119D163D5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_CarbonVisibility.h"; path = "../../JuceLibraryCode/modules/juce_audio_plugin_client/utility/juce_CarbonVisibility.h"; sourceTree = "SOURCE_ROOT"; };
FF5B77AA3517B4637F862BD3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_RelativeCoordinatePositioner.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeCoordinatePositioner.cpp"; sourceTree = "SOURCE_ROOT"; }; FF5B77AA3517B4637F862BD3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_RelativeCoordinatePositioner.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeCoordinatePositioner.cpp"; sourceTree = "SOURCE_ROOT"; };
FF6607118B29435E76806DFA = { isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Dexed.component; sourceTree = "BUILT_PRODUCTS_DIR"; }; FF6607118B29435E76806DFA = { isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Dexed.component; sourceTree = "BUILT_PRODUCTS_DIR"; };
FF973BD60572C077A148D3AB = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_WildcardFileFilter.h"; path = "../../JuceLibraryCode/modules/juce_core/files/juce_WildcardFileFilter.h"; sourceTree = "SOURCE_ROOT"; };
F472964B0FFEE5615B72CE3D = { isa = PBXGroup; children = ( F472964B0FFEE5615B72CE3D = { isa = PBXGroup; children = (
15B75D829C40872D542A38B8 ); name = Resources; sourceTree = "<group>"; }; 15B75D829C40872D542A38B8 ); name = Resources; sourceTree = "<group>"; };
BDC5059F1563FD8DD69AD324 = { isa = PBXGroup; children = ( BDC5059F1563FD8DD69AD324 = { isa = PBXGroup; children = (
@ -978,10 +986,13 @@
B794B15ADD462305846C5903 = { isa = PBXGroup; children = ( B794B15ADD462305846C5903 = { isa = PBXGroup; children = (
D6C6FCBA5ECA257959BFE674, D6C6FCBA5ECA257959BFE674,
F6F950B6ABB40B62AE4C0B78 ); name = VST; sourceTree = "<group>"; }; F6F950B6ABB40B62AE4C0B78 ); name = VST; sourceTree = "<group>"; };
85A5C17AC07E3A6A3F2EDA18 = { isa = PBXGroup; children = ( FA8A91020A6EDA9A5DDF8D4A = { isa = PBXGroup; children = (
D0178A36F6E46F92111E4883,
01EF232D8B427B8CE38127C2 ); name = VST3; sourceTree = "<group>"; };
C6FD96042B8BCA45D8185D2F = { isa = PBXGroup; children = (
505852570B48EB3F18076B03, 505852570B48EB3F18076B03,
3254CAE4C282C4432214B016 ); name = AAX; sourceTree = "<group>"; }; 3254CAE4C282C4432214B016 ); name = AAX; sourceTree = "<group>"; };
87B177FB46D381DF5C97583E = { isa = PBXGroup; children = ( 0FB9E2767E5705CC99B13E68 = { isa = PBXGroup; children = (
FF46344F53B1AE5119D163D5, FF46344F53B1AE5119D163D5,
C33C134DA87CD13FAF7BC5A1, C33C134DA87CD13FAF7BC5A1,
477946525F6F1BE9135A3101, 477946525F6F1BE9135A3101,
@ -993,8 +1004,9 @@
D53856B782944C7AA8FC0B1E, D53856B782944C7AA8FC0B1E,
9302146DD804F9CBF819DE20, 9302146DD804F9CBF819DE20,
B794B15ADD462305846C5903, B794B15ADD462305846C5903,
85A5C17AC07E3A6A3F2EDA18, FA8A91020A6EDA9A5DDF8D4A,
87B177FB46D381DF5C97583E, C6FD96042B8BCA45D8185D2F,
0FB9E2767E5705CC99B13E68,
EF6B42F9461A962D9D91EFEA, EF6B42F9461A962D9D91EFEA,
4E1C775897B0A2C2F9E2CB44 ); name = "juce_audio_plugin_client"; sourceTree = "<group>"; }; 4E1C775897B0A2C2F9E2CB44 ); name = "juce_audio_plugin_client"; sourceTree = "<group>"; };
2BB71E1725728DD1B293B270 = { isa = PBXGroup; children = ( 2BB71E1725728DD1B293B270 = { isa = PBXGroup; children = (
@ -1021,6 +1033,8 @@
78934C6C88D2B35DEF15BAB8, 78934C6C88D2B35DEF15BAB8,
6E8FC799E88893F8CD15BB71, 6E8FC799E88893F8CD15BB71,
B4AA6DED570BD1D3E701BA49, B4AA6DED570BD1D3E701BA49,
7DC83451FCA10947AC92EBBC,
07333A7932C6B7538F4DF21F,
3F15C4289E956EA0447392BD, 3F15C4289E956EA0447392BD,
153D4DE95D01307F844AA15B, 153D4DE95D01307F844AA15B,
83DC5A4F730ECA567FADFC3E, 83DC5A4F730ECA567FADFC3E,
@ -1160,6 +1174,8 @@
4D488219CE9D736D69F6EF59, 4D488219CE9D736D69F6EF59,
39423D67EFB8E7CEEF5FFAA9, 39423D67EFB8E7CEEF5FFAA9,
95B7D6B36478C5A2977ADD4C, 95B7D6B36478C5A2977ADD4C,
7ECA74A2FC82F26715446C70,
2C65FDA74486C92DF5EA5C87,
D409BECBAD7CDC3DE48EFA2F, D409BECBAD7CDC3DE48EFA2F,
418C5A909668054B5140BDA9, 418C5A909668054B5140BDA9,
B446CB8C1ED8823EA2F33E30, B446CB8C1ED8823EA2F33E30,
@ -1168,7 +1184,9 @@
3BB7B60AE87F68C10DBEE118, 3BB7B60AE87F68C10DBEE118,
F5E56D366A88F772BE998AED, F5E56D366A88F772BE998AED,
4370F9713D43E71621F2AA2A, 4370F9713D43E71621F2AA2A,
F0E8BE4931D56987065FE1C1 ); name = files; sourceTree = "<group>"; }; F0E8BE4931D56987065FE1C1,
829D2BFEB85DC3589FEBB868,
FF973BD60572C077A148D3AB ); name = files; sourceTree = "<group>"; };
F71D9B3CC8688C2E11360EA4 = { isa = PBXGroup; children = ( F71D9B3CC8688C2E11360EA4 = { isa = PBXGroup; children = (
06C4DD7797E7526DB1B47AE5, 06C4DD7797E7526DB1B47AE5,
3444F7C54161FEB1F844619E, 3444F7C54161FEB1F844619E,
@ -1329,6 +1347,8 @@
29FCF15A6F116C0A823A186D, 29FCF15A6F116C0A823A186D,
ECB0C2120DE11AE690DB987B ); name = broadcasters; sourceTree = "<group>"; }; ECB0C2120DE11AE690DB987B ); name = broadcasters; sourceTree = "<group>"; };
9ACE3BB033DC986A0A577EE8 = { isa = PBXGroup; children = ( 9ACE3BB033DC986A0A577EE8 = { isa = PBXGroup; children = (
17A328AD02B5D7DA362E1D5D,
40DCD07DB4B1D9FBB9D47BE5,
88DEE0054A9328954E19EECA, 88DEE0054A9328954E19EECA,
F4EA09FAC67FDDA4D2E1D151, F4EA09FAC67FDDA4D2E1D151,
EACE6ED62F30C9222D91ACB2, EACE6ED62F30C9222D91ACB2,
@ -1669,8 +1689,6 @@
001A2BCC899370ADC99A8F3A, 001A2BCC899370ADC99A8F3A,
3223ECE0332620D3B03E301A, 3223ECE0332620D3B03E301A,
E44EB5B165F16ABE2DFB809D, E44EB5B165F16ABE2DFB809D,
7A38190CB0652B0EBA02100C,
D1BA8296F20CACB8F81B7316,
25F88A5C788D9CF7301569EB, 25F88A5C788D9CF7301569EB,
8C4A3CBB322357AF0CA3C2CD, 8C4A3CBB322357AF0CA3C2CD,
9E0A95AA535CE6ABE66D9A30, 9E0A95AA535CE6ABE66D9A30,
@ -1681,9 +1699,7 @@
BA9FFDC7BCC2D364014E1280, BA9FFDC7BCC2D364014E1280,
E8A7578ED10948AB49EE2997, E8A7578ED10948AB49EE2997,
2CA19470CA427333F8CAC0A5, 2CA19470CA427333F8CAC0A5,
27077B2F6AA5ED05FAF0B5D8, 27077B2F6AA5ED05FAF0B5D8 ); name = filebrowser; sourceTree = "<group>"; };
35865817C4ED48DCD346B5D9,
46B8FB88F2949700DD70A821 ); name = filebrowser; sourceTree = "<group>"; };
D20A63B1C4DF64E9DA6C9CE8 = { isa = PBXGroup; children = ( D20A63B1C4DF64E9DA6C9CE8 = { isa = PBXGroup; children = (
041EA7D542B0EBF7213B9BA2, 041EA7D542B0EBF7213B9BA2,
17ED00953353016B7E7492B0, 17ED00953353016B7E7492B0,
@ -1836,6 +1852,8 @@
FE39DD2B654DF778D919D554, FE39DD2B654DF778D919D554,
C7C6039A52C3EE370CA9E73A, C7C6039A52C3EE370CA9E73A,
EAA5D8078BCC042BDF94C77A, EAA5D8078BCC042BDF94C77A,
D0178A36F6E46F92111E4883,
01EF232D8B427B8CE38127C2,
D6C6FCBA5ECA257959BFE674, D6C6FCBA5ECA257959BFE674,
F6F950B6ABB40B62AE4C0B78, F6F950B6ABB40B62AE4C0B78,
8F32EF92B0A18751EC39A79B ); name = "Juce Library Code"; sourceTree = "<group>"; }; 8F32EF92B0A18751EC39A79B ); name = "Juce Library Code"; sourceTree = "<group>"; };
@ -1991,6 +2009,8 @@
DDD1E74DE1AC7E6493AF04CA, DDD1E74DE1AC7E6493AF04CA,
A6E2908774D7F669F21B1874, A6E2908774D7F669F21B1874,
B82FDEB3E53C9455BC6A5DAE, B82FDEB3E53C9455BC6A5DAE,
52C0C94470D90310AF2F8433,
13F8BF7C26D50908163425CF,
00C044DBB8BA1AF35CBC42E6, 00C044DBB8BA1AF35CBC42E6,
E8D9A2B640A87FE92D2DA887 ); runOnlyForDeploymentPostprocessing = 0; }; E8D9A2B640A87FE92D2DA887 ); runOnlyForDeploymentPostprocessing = 0; };
06D721A024B3596A28AB8EC1 = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 06D721A024B3596A28AB8EC1 = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = (

@ -223,6 +223,9 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST\juce_VST_Wrapper.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST\juce_VST_Wrapper.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST3\juce_VST3_Wrapper.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\AAX\juce_AAX_Wrapper.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\AAX\juce_AAX_Wrapper.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
@ -367,6 +370,9 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_File.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_File.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileFilter.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileInputStream.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileInputStream.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
@ -379,6 +385,9 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_TemporaryFile.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_TemporaryFile.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_WildcardFileFilter.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\network\juce_IPAddress.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\network\juce_IPAddress.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
@ -544,6 +553,9 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_events\broadcasters\juce_ChangeBroadcaster.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_events\broadcasters\juce_ChangeBroadcaster.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_events\interprocess\juce_ConnectedChildProcess.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_events\interprocess\juce_InterprocessConnection.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_events\interprocess\juce_InterprocessConnection.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
@ -961,9 +973,6 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileChooserDialogBox.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileChooserDialogBox.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileFilter.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileListComponent.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileListComponent.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
@ -979,9 +988,6 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_ImagePreviewComponent.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_ImagePreviewComponent.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_WildcardFileFilter.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\commands\juce_ApplicationCommandInfo.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\commands\juce_ApplicationCommandInfo.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
@ -1119,6 +1125,7 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\RTAS\juce_RTAS_Wrapper.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\RTAS\juce_RTAS_Wrapper.cpp">
<CallingConvention>StdCall</CallingConvention> <CallingConvention>StdCall</CallingConvention>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST3\juce_VST3_Wrapper.cpp"/>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST\juce_VST_Wrapper.cpp"/> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST\juce_VST_Wrapper.cpp"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -1187,6 +1194,8 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format\juce_AudioPluginFormatManager.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format\juce_AudioPluginFormatManager.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_AudioUnitPluginFormat.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_AudioUnitPluginFormat.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_LADSPAPluginFormat.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_LADSPAPluginFormat.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_VST3Common.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_VST3Headers.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_VST3PluginFormat.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_VST3PluginFormat.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_VSTMidiEventList.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_VSTMidiEventList.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_VSTPluginFormat.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_VSTPluginFormat.h"/>
@ -1268,11 +1277,13 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\time\juce_Time.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\time\juce_Time.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_DirectoryIterator.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_DirectoryIterator.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_File.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_File.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileFilter.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileInputStream.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileInputStream.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileOutputStream.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileOutputStream.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileSearchPath.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileSearchPath.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_MemoryMappedFile.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_MemoryMappedFile.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_TemporaryFile.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_TemporaryFile.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_WildcardFileFilter.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\network\juce_IPAddress.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\network\juce_IPAddress.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\network\juce_MACAddress.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\network\juce_MACAddress.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\network\juce_NamedPipe.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\network\juce_NamedPipe.h"/>
@ -1332,6 +1343,7 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\broadcasters\juce_ChangeBroadcaster.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\broadcasters\juce_ChangeBroadcaster.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\broadcasters\juce_ChangeListener.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\broadcasters\juce_ChangeListener.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\broadcasters\juce_ListenerList.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\broadcasters\juce_ListenerList.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\interprocess\juce_ConnectedChildProcess.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\interprocess\juce_InterprocessConnection.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\interprocess\juce_InterprocessConnection.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\interprocess\juce_InterprocessConnectionServer.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\interprocess\juce_InterprocessConnectionServer.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\native\juce_osx_MessageQueue.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\native\juce_osx_MessageQueue.h"/>
@ -1488,14 +1500,12 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileBrowserListener.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileBrowserListener.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileChooser.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileChooser.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileChooserDialogBox.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileChooserDialogBox.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileFilter.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileListComponent.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileListComponent.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FilenameComponent.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FilenameComponent.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FilePreviewComponent.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FilePreviewComponent.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileSearchPathListComponent.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileSearchPathListComponent.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileTreeComponent.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileTreeComponent.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_ImagePreviewComponent.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_ImagePreviewComponent.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_WildcardFileFilter.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\commands\juce_ApplicationCommandID.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\commands\juce_ApplicationCommandID.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\commands\juce_ApplicationCommandInfo.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\commands\juce_ApplicationCommandInfo.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\commands\juce_ApplicationCommandManager.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\commands\juce_ApplicationCommandManager.h"/>

@ -47,6 +47,9 @@
<Filter Include="Juce Modules\juce_audio_plugin_client\VST"> <Filter Include="Juce Modules\juce_audio_plugin_client\VST">
<UniqueIdentifier>{AF5F4789-D607-BFD8-D853-09473C27449C}</UniqueIdentifier> <UniqueIdentifier>{AF5F4789-D607-BFD8-D853-09473C27449C}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="Juce Modules\juce_audio_plugin_client\VST3">
<UniqueIdentifier>{22689F25-8C5C-52CF-09E4-4308D1521B9B}</UniqueIdentifier>
</Filter>
<Filter Include="Juce Modules\juce_audio_plugin_client\AAX"> <Filter Include="Juce Modules\juce_audio_plugin_client\AAX">
<UniqueIdentifier>{F0C10808-8C36-BCD0-D25F-523774B0ADA2}</UniqueIdentifier> <UniqueIdentifier>{F0C10808-8C36-BCD0-D25F-523774B0ADA2}</UniqueIdentifier>
</Filter> </Filter>
@ -403,6 +406,12 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST\juce_VST_Wrapper.mm"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST\juce_VST_Wrapper.mm">
<Filter>Juce Modules\juce_audio_plugin_client\VST</Filter> <Filter>Juce Modules\juce_audio_plugin_client\VST</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST3\juce_VST3_Wrapper.cpp">
<Filter>Juce Modules\juce_audio_plugin_client\VST3</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST3\juce_VST3_Wrapper.mm">
<Filter>Juce Modules\juce_audio_plugin_client\VST3</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\AAX\juce_AAX_Wrapper.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\AAX\juce_AAX_Wrapper.cpp">
<Filter>Juce Modules\juce_audio_plugin_client\AAX</Filter> <Filter>Juce Modules\juce_audio_plugin_client\AAX</Filter>
</ClCompile> </ClCompile>
@ -553,6 +562,9 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_File.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_File.cpp">
<Filter>Juce Modules\juce_core\files</Filter> <Filter>Juce Modules\juce_core\files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileFilter.cpp">
<Filter>Juce Modules\juce_core\files</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileInputStream.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileInputStream.cpp">
<Filter>Juce Modules\juce_core\files</Filter> <Filter>Juce Modules\juce_core\files</Filter>
</ClCompile> </ClCompile>
@ -565,6 +577,9 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_TemporaryFile.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_TemporaryFile.cpp">
<Filter>Juce Modules\juce_core\files</Filter> <Filter>Juce Modules\juce_core\files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_WildcardFileFilter.cpp">
<Filter>Juce Modules\juce_core\files</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\network\juce_IPAddress.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\network\juce_IPAddress.cpp">
<Filter>Juce Modules\juce_core\network</Filter> <Filter>Juce Modules\juce_core\network</Filter>
</ClCompile> </ClCompile>
@ -745,6 +760,9 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_events\broadcasters\juce_ChangeBroadcaster.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_events\broadcasters\juce_ChangeBroadcaster.cpp">
<Filter>Juce Modules\juce_events\broadcasters</Filter> <Filter>Juce Modules\juce_events\broadcasters</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_events\interprocess\juce_ConnectedChildProcess.cpp">
<Filter>Juce Modules\juce_events\interprocess</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_events\interprocess\juce_InterprocessConnection.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_events\interprocess\juce_InterprocessConnection.cpp">
<Filter>Juce Modules\juce_events\interprocess</Filter> <Filter>Juce Modules\juce_events\interprocess</Filter>
</ClCompile> </ClCompile>
@ -1174,9 +1192,6 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileChooserDialogBox.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileChooserDialogBox.cpp">
<Filter>Juce Modules\juce_gui_basics\filebrowser</Filter> <Filter>Juce Modules\juce_gui_basics\filebrowser</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileFilter.cpp">
<Filter>Juce Modules\juce_gui_basics\filebrowser</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileListComponent.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileListComponent.cpp">
<Filter>Juce Modules\juce_gui_basics\filebrowser</Filter> <Filter>Juce Modules\juce_gui_basics\filebrowser</Filter>
</ClCompile> </ClCompile>
@ -1192,9 +1207,6 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_ImagePreviewComponent.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_ImagePreviewComponent.cpp">
<Filter>Juce Modules\juce_gui_basics\filebrowser</Filter> <Filter>Juce Modules\juce_gui_basics\filebrowser</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_WildcardFileFilter.cpp">
<Filter>Juce Modules\juce_gui_basics\filebrowser</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\commands\juce_ApplicationCommandInfo.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\commands\juce_ApplicationCommandInfo.cpp">
<Filter>Juce Modules\juce_gui_basics\commands</Filter> <Filter>Juce Modules\juce_gui_basics\commands</Filter>
</ClCompile> </ClCompile>
@ -1393,6 +1405,9 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\RTAS\juce_RTAS_Wrapper.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\RTAS\juce_RTAS_Wrapper.cpp">
<Filter>Juce Library Code</Filter> <Filter>Juce Library Code</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST3\juce_VST3_Wrapper.cpp">
<Filter>Juce Library Code</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST\juce_VST_Wrapper.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST\juce_VST_Wrapper.cpp">
<Filter>Juce Library Code</Filter> <Filter>Juce Library Code</Filter>
</ClCompile> </ClCompile>
@ -1593,6 +1608,12 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_LADSPAPluginFormat.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_LADSPAPluginFormat.h">
<Filter>Juce Modules\juce_audio_processors\format_types</Filter> <Filter>Juce Modules\juce_audio_processors\format_types</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_VST3Common.h">
<Filter>Juce Modules\juce_audio_processors\format_types</Filter>
</ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_VST3Headers.h">
<Filter>Juce Modules\juce_audio_processors\format_types</Filter>
</ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_VST3PluginFormat.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_VST3PluginFormat.h">
<Filter>Juce Modules\juce_audio_processors\format_types</Filter> <Filter>Juce Modules\juce_audio_processors\format_types</Filter>
</ClInclude> </ClInclude>
@ -1836,6 +1857,9 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_File.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_File.h">
<Filter>Juce Modules\juce_core\files</Filter> <Filter>Juce Modules\juce_core\files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileFilter.h">
<Filter>Juce Modules\juce_core\files</Filter>
</ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileInputStream.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileInputStream.h">
<Filter>Juce Modules\juce_core\files</Filter> <Filter>Juce Modules\juce_core\files</Filter>
</ClInclude> </ClInclude>
@ -1851,6 +1875,9 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_TemporaryFile.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_TemporaryFile.h">
<Filter>Juce Modules\juce_core\files</Filter> <Filter>Juce Modules\juce_core\files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_WildcardFileFilter.h">
<Filter>Juce Modules\juce_core\files</Filter>
</ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\network\juce_IPAddress.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\network\juce_IPAddress.h">
<Filter>Juce Modules\juce_core\network</Filter> <Filter>Juce Modules\juce_core\network</Filter>
</ClInclude> </ClInclude>
@ -2028,6 +2055,9 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\broadcasters\juce_ListenerList.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\broadcasters\juce_ListenerList.h">
<Filter>Juce Modules\juce_events\broadcasters</Filter> <Filter>Juce Modules\juce_events\broadcasters</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\interprocess\juce_ConnectedChildProcess.h">
<Filter>Juce Modules\juce_events\interprocess</Filter>
</ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\interprocess\juce_InterprocessConnection.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\interprocess\juce_InterprocessConnection.h">
<Filter>Juce Modules\juce_events\interprocess</Filter> <Filter>Juce Modules\juce_events\interprocess</Filter>
</ClInclude> </ClInclude>
@ -2496,9 +2526,6 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileChooserDialogBox.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileChooserDialogBox.h">
<Filter>Juce Modules\juce_gui_basics\filebrowser</Filter> <Filter>Juce Modules\juce_gui_basics\filebrowser</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileFilter.h">
<Filter>Juce Modules\juce_gui_basics\filebrowser</Filter>
</ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileListComponent.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileListComponent.h">
<Filter>Juce Modules\juce_gui_basics\filebrowser</Filter> <Filter>Juce Modules\juce_gui_basics\filebrowser</Filter>
</ClInclude> </ClInclude>
@ -2517,9 +2544,6 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_ImagePreviewComponent.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_ImagePreviewComponent.h">
<Filter>Juce Modules\juce_gui_basics\filebrowser</Filter> <Filter>Juce Modules\juce_gui_basics\filebrowser</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_WildcardFileFilter.h">
<Filter>Juce Modules\juce_gui_basics\filebrowser</Filter>
</ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\commands\juce_ApplicationCommandID.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\commands\juce_ApplicationCommandID.h">
<Filter>Juce Modules\juce_gui_basics\commands</Filter> <Filter>Juce Modules\juce_gui_basics\commands</Filter>
</ClInclude> </ClInclude>

@ -223,6 +223,9 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST\juce_VST_Wrapper.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST\juce_VST_Wrapper.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST3\juce_VST3_Wrapper.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\AAX\juce_AAX_Wrapper.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\AAX\juce_AAX_Wrapper.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
@ -367,6 +370,9 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_File.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_File.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileFilter.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileInputStream.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileInputStream.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
@ -379,6 +385,9 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_TemporaryFile.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_TemporaryFile.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_WildcardFileFilter.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\network\juce_IPAddress.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\network\juce_IPAddress.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
@ -544,6 +553,9 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_events\broadcasters\juce_ChangeBroadcaster.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_events\broadcasters\juce_ChangeBroadcaster.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_events\interprocess\juce_ConnectedChildProcess.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_events\interprocess\juce_InterprocessConnection.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_events\interprocess\juce_InterprocessConnection.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
@ -961,9 +973,6 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileChooserDialogBox.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileChooserDialogBox.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileFilter.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileListComponent.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileListComponent.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
@ -979,9 +988,6 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_ImagePreviewComponent.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_ImagePreviewComponent.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_WildcardFileFilter.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\commands\juce_ApplicationCommandInfo.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\commands\juce_ApplicationCommandInfo.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
@ -1119,6 +1125,7 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\RTAS\juce_RTAS_Wrapper.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\RTAS\juce_RTAS_Wrapper.cpp">
<CallingConvention>StdCall</CallingConvention> <CallingConvention>StdCall</CallingConvention>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST3\juce_VST3_Wrapper.cpp"/>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST\juce_VST_Wrapper.cpp"/> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST\juce_VST_Wrapper.cpp"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -1187,6 +1194,8 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format\juce_AudioPluginFormatManager.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format\juce_AudioPluginFormatManager.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_AudioUnitPluginFormat.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_AudioUnitPluginFormat.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_LADSPAPluginFormat.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_LADSPAPluginFormat.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_VST3Common.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_VST3Headers.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_VST3PluginFormat.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_VST3PluginFormat.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_VSTMidiEventList.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_VSTMidiEventList.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_VSTPluginFormat.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_VSTPluginFormat.h"/>
@ -1268,11 +1277,13 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\time\juce_Time.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\time\juce_Time.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_DirectoryIterator.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_DirectoryIterator.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_File.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_File.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileFilter.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileInputStream.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileInputStream.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileOutputStream.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileOutputStream.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileSearchPath.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileSearchPath.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_MemoryMappedFile.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_MemoryMappedFile.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_TemporaryFile.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_TemporaryFile.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_WildcardFileFilter.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\network\juce_IPAddress.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\network\juce_IPAddress.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\network\juce_MACAddress.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\network\juce_MACAddress.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\network\juce_NamedPipe.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\network\juce_NamedPipe.h"/>
@ -1332,6 +1343,7 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\broadcasters\juce_ChangeBroadcaster.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\broadcasters\juce_ChangeBroadcaster.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\broadcasters\juce_ChangeListener.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\broadcasters\juce_ChangeListener.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\broadcasters\juce_ListenerList.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\broadcasters\juce_ListenerList.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\interprocess\juce_ConnectedChildProcess.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\interprocess\juce_InterprocessConnection.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\interprocess\juce_InterprocessConnection.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\interprocess\juce_InterprocessConnectionServer.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\interprocess\juce_InterprocessConnectionServer.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\native\juce_osx_MessageQueue.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\native\juce_osx_MessageQueue.h"/>
@ -1488,14 +1500,12 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileBrowserListener.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileBrowserListener.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileChooser.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileChooser.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileChooserDialogBox.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileChooserDialogBox.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileFilter.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileListComponent.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileListComponent.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FilenameComponent.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FilenameComponent.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FilePreviewComponent.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FilePreviewComponent.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileSearchPathListComponent.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileSearchPathListComponent.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileTreeComponent.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileTreeComponent.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_ImagePreviewComponent.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_ImagePreviewComponent.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_WildcardFileFilter.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\commands\juce_ApplicationCommandID.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\commands\juce_ApplicationCommandID.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\commands\juce_ApplicationCommandInfo.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\commands\juce_ApplicationCommandInfo.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\commands\juce_ApplicationCommandManager.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\commands\juce_ApplicationCommandManager.h"/>

@ -47,6 +47,9 @@
<Filter Include="Juce Modules\juce_audio_plugin_client\VST"> <Filter Include="Juce Modules\juce_audio_plugin_client\VST">
<UniqueIdentifier>{AF5F4789-D607-BFD8-D853-09473C27449C}</UniqueIdentifier> <UniqueIdentifier>{AF5F4789-D607-BFD8-D853-09473C27449C}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="Juce Modules\juce_audio_plugin_client\VST3">
<UniqueIdentifier>{22689F25-8C5C-52CF-09E4-4308D1521B9B}</UniqueIdentifier>
</Filter>
<Filter Include="Juce Modules\juce_audio_plugin_client\AAX"> <Filter Include="Juce Modules\juce_audio_plugin_client\AAX">
<UniqueIdentifier>{F0C10808-8C36-BCD0-D25F-523774B0ADA2}</UniqueIdentifier> <UniqueIdentifier>{F0C10808-8C36-BCD0-D25F-523774B0ADA2}</UniqueIdentifier>
</Filter> </Filter>
@ -403,6 +406,12 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST\juce_VST_Wrapper.mm"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST\juce_VST_Wrapper.mm">
<Filter>Juce Modules\juce_audio_plugin_client\VST</Filter> <Filter>Juce Modules\juce_audio_plugin_client\VST</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST3\juce_VST3_Wrapper.cpp">
<Filter>Juce Modules\juce_audio_plugin_client\VST3</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST3\juce_VST3_Wrapper.mm">
<Filter>Juce Modules\juce_audio_plugin_client\VST3</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\AAX\juce_AAX_Wrapper.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\AAX\juce_AAX_Wrapper.cpp">
<Filter>Juce Modules\juce_audio_plugin_client\AAX</Filter> <Filter>Juce Modules\juce_audio_plugin_client\AAX</Filter>
</ClCompile> </ClCompile>
@ -553,6 +562,9 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_File.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_File.cpp">
<Filter>Juce Modules\juce_core\files</Filter> <Filter>Juce Modules\juce_core\files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileFilter.cpp">
<Filter>Juce Modules\juce_core\files</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileInputStream.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileInputStream.cpp">
<Filter>Juce Modules\juce_core\files</Filter> <Filter>Juce Modules\juce_core\files</Filter>
</ClCompile> </ClCompile>
@ -565,6 +577,9 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_TemporaryFile.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_TemporaryFile.cpp">
<Filter>Juce Modules\juce_core\files</Filter> <Filter>Juce Modules\juce_core\files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_WildcardFileFilter.cpp">
<Filter>Juce Modules\juce_core\files</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\network\juce_IPAddress.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\network\juce_IPAddress.cpp">
<Filter>Juce Modules\juce_core\network</Filter> <Filter>Juce Modules\juce_core\network</Filter>
</ClCompile> </ClCompile>
@ -745,6 +760,9 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_events\broadcasters\juce_ChangeBroadcaster.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_events\broadcasters\juce_ChangeBroadcaster.cpp">
<Filter>Juce Modules\juce_events\broadcasters</Filter> <Filter>Juce Modules\juce_events\broadcasters</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_events\interprocess\juce_ConnectedChildProcess.cpp">
<Filter>Juce Modules\juce_events\interprocess</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_events\interprocess\juce_InterprocessConnection.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_events\interprocess\juce_InterprocessConnection.cpp">
<Filter>Juce Modules\juce_events\interprocess</Filter> <Filter>Juce Modules\juce_events\interprocess</Filter>
</ClCompile> </ClCompile>
@ -1174,9 +1192,6 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileChooserDialogBox.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileChooserDialogBox.cpp">
<Filter>Juce Modules\juce_gui_basics\filebrowser</Filter> <Filter>Juce Modules\juce_gui_basics\filebrowser</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileFilter.cpp">
<Filter>Juce Modules\juce_gui_basics\filebrowser</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileListComponent.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileListComponent.cpp">
<Filter>Juce Modules\juce_gui_basics\filebrowser</Filter> <Filter>Juce Modules\juce_gui_basics\filebrowser</Filter>
</ClCompile> </ClCompile>
@ -1192,9 +1207,6 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_ImagePreviewComponent.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_ImagePreviewComponent.cpp">
<Filter>Juce Modules\juce_gui_basics\filebrowser</Filter> <Filter>Juce Modules\juce_gui_basics\filebrowser</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_WildcardFileFilter.cpp">
<Filter>Juce Modules\juce_gui_basics\filebrowser</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\commands\juce_ApplicationCommandInfo.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\commands\juce_ApplicationCommandInfo.cpp">
<Filter>Juce Modules\juce_gui_basics\commands</Filter> <Filter>Juce Modules\juce_gui_basics\commands</Filter>
</ClCompile> </ClCompile>
@ -1393,6 +1405,9 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\RTAS\juce_RTAS_Wrapper.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\RTAS\juce_RTAS_Wrapper.cpp">
<Filter>Juce Library Code</Filter> <Filter>Juce Library Code</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST3\juce_VST3_Wrapper.cpp">
<Filter>Juce Library Code</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST\juce_VST_Wrapper.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST\juce_VST_Wrapper.cpp">
<Filter>Juce Library Code</Filter> <Filter>Juce Library Code</Filter>
</ClCompile> </ClCompile>
@ -1593,6 +1608,12 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_LADSPAPluginFormat.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_LADSPAPluginFormat.h">
<Filter>Juce Modules\juce_audio_processors\format_types</Filter> <Filter>Juce Modules\juce_audio_processors\format_types</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_VST3Common.h">
<Filter>Juce Modules\juce_audio_processors\format_types</Filter>
</ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_VST3Headers.h">
<Filter>Juce Modules\juce_audio_processors\format_types</Filter>
</ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_VST3PluginFormat.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_VST3PluginFormat.h">
<Filter>Juce Modules\juce_audio_processors\format_types</Filter> <Filter>Juce Modules\juce_audio_processors\format_types</Filter>
</ClInclude> </ClInclude>
@ -1836,6 +1857,9 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_File.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_File.h">
<Filter>Juce Modules\juce_core\files</Filter> <Filter>Juce Modules\juce_core\files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileFilter.h">
<Filter>Juce Modules\juce_core\files</Filter>
</ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileInputStream.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_FileInputStream.h">
<Filter>Juce Modules\juce_core\files</Filter> <Filter>Juce Modules\juce_core\files</Filter>
</ClInclude> </ClInclude>
@ -1851,6 +1875,9 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_TemporaryFile.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_TemporaryFile.h">
<Filter>Juce Modules\juce_core\files</Filter> <Filter>Juce Modules\juce_core\files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\files\juce_WildcardFileFilter.h">
<Filter>Juce Modules\juce_core\files</Filter>
</ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\network\juce_IPAddress.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_core\network\juce_IPAddress.h">
<Filter>Juce Modules\juce_core\network</Filter> <Filter>Juce Modules\juce_core\network</Filter>
</ClInclude> </ClInclude>
@ -2028,6 +2055,9 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\broadcasters\juce_ListenerList.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\broadcasters\juce_ListenerList.h">
<Filter>Juce Modules\juce_events\broadcasters</Filter> <Filter>Juce Modules\juce_events\broadcasters</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\interprocess\juce_ConnectedChildProcess.h">
<Filter>Juce Modules\juce_events\interprocess</Filter>
</ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\interprocess\juce_InterprocessConnection.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_events\interprocess\juce_InterprocessConnection.h">
<Filter>Juce Modules\juce_events\interprocess</Filter> <Filter>Juce Modules\juce_events\interprocess</Filter>
</ClInclude> </ClInclude>
@ -2496,9 +2526,6 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileChooserDialogBox.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileChooserDialogBox.h">
<Filter>Juce Modules\juce_gui_basics\filebrowser</Filter> <Filter>Juce Modules\juce_gui_basics\filebrowser</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileFilter.h">
<Filter>Juce Modules\juce_gui_basics\filebrowser</Filter>
</ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileListComponent.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_FileListComponent.h">
<Filter>Juce Modules\juce_gui_basics\filebrowser</Filter> <Filter>Juce Modules\juce_gui_basics\filebrowser</Filter>
</ClInclude> </ClInclude>
@ -2517,9 +2544,6 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_ImagePreviewComponent.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_ImagePreviewComponent.h">
<Filter>Juce Modules\juce_gui_basics\filebrowser</Filter> <Filter>Juce Modules\juce_gui_basics\filebrowser</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\filebrowser\juce_WildcardFileFilter.h">
<Filter>Juce Modules\juce_gui_basics\filebrowser</Filter>
</ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\commands\juce_ApplicationCommandID.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_basics\commands\juce_ApplicationCommandID.h">
<Filter>Juce Modules\juce_gui_basics\commands</Filter> <Filter>Juce Modules\juce_gui_basics\commands</Filter>
</ClInclude> </ClInclude>

@ -1,7 +1,7 @@
{ {
"id": "juce_audio_basics", "id": "juce_audio_basics",
"name": "JUCE audio and midi data classes", "name": "JUCE audio and midi data classes",
"version": "3.0.1", "version": "3.0.3",
"description": "Classes for audio buffer manipulation, midi message handling, synthesis, etc", "description": "Classes for audio buffer manipulation, midi message handling, synthesis, etc",
"website": "http://www.juce.com/juce", "website": "http://www.juce.com/juce",
"license": "GPL/Commercial", "license": "GPL/Commercial",

@ -155,7 +155,7 @@ MidiMessage::MidiMessage (const MidiMessage& other, const double newTimeStamp)
MidiMessage::MidiMessage (const void* srcData, int sz, int& numBytesUsed, const uint8 lastStatusByte, double t) MidiMessage::MidiMessage (const void* srcData, int sz, int& numBytesUsed, const uint8 lastStatusByte, double t)
: timeStamp (t) : timeStamp (t)
{ {
const uint8* src = static_cast <const uint8*> (srcData); const uint8* src = static_cast<const uint8*> (srcData);
unsigned int byte = (unsigned int) *src; unsigned int byte = (unsigned int) *src;
if (byte < 0x80) if (byte < 0x80)
@ -658,6 +658,36 @@ String MidiMessage::getTextFromTextMetaEvent() const
CharPointer_UTF8 (textData + getMetaEventLength())); CharPointer_UTF8 (textData + getMetaEventLength()));
} }
MidiMessage MidiMessage::textMetaEvent (int type, StringRef text)
{
jassert (type > 0 && type < 16)
MidiMessage result;
const size_t textSize = text.text.sizeInBytes() - 1;
uint8 header[8];
size_t n = sizeof (header);
header[--n] = (uint8) (textSize & 0x7f);
for (size_t i = textSize; (i >>= 7) != 0;)
header[--n] = (uint8) ((i & 0x7f) | 0x80);
header[--n] = (uint8) type;
header[--n] = 0xff;
const size_t headerLen = sizeof (header) - n;
uint8* const dest = result.allocateSpace ((int) (headerLen + textSize));
result.size = (int) (headerLen + textSize);
memcpy (dest, header + n, headerLen);
memcpy (dest + headerLen, text.text.getAddress(), textSize);
return result;
}
bool MidiMessage::isTrackNameEvent() const noexcept { const uint8* data = getRawData(); return (data[1] == 3) && (*data == 0xff); } bool MidiMessage::isTrackNameEvent() const noexcept { const uint8* data = getRawData(); return (data[1] == 3) && (*data == 0xff); }
bool MidiMessage::isTempoMetaEvent() const noexcept { const uint8* data = getRawData(); return (data[1] == 81) && (*data == 0xff); } bool MidiMessage::isTempoMetaEvent() const noexcept { const uint8* data = getRawData(); return (data[1] == 81) && (*data == 0xff); }
bool MidiMessage::isMidiChannelMetaEvent() const noexcept { const uint8* data = getRawData(); return (data[1] == 0x20) && (*data == 0xff) && (data[2] == 1); } bool MidiMessage::isMidiChannelMetaEvent() const noexcept { const uint8* data = getRawData(); return (data[1] == 0x20) && (*data == 0xff) && (data[2] == 1); }
@ -941,6 +971,11 @@ double MidiMessage::getMidiNoteInHertz (int noteNumber, const double frequencyOf
return frequencyOfA * pow (2.0, (noteNumber - 69) / 12.0); return frequencyOfA * pow (2.0, (noteNumber - 69) / 12.0);
} }
bool MidiMessage::isMidiNoteBlack (int noteNumber) noexcept
{
return ((1 << (noteNumber % 12)) & 0x054a) != 0;
}
const char* MidiMessage::getGMInstrumentName (const int n) const char* MidiMessage::getGMInstrumentName (const int n)
{ {
static const char* names[] = static const char* names[] =

@ -168,9 +168,7 @@ public:
bool isForChannel (int channelNumber) const noexcept; bool isForChannel (int channelNumber) const noexcept;
/** Changes the message's midi channel. /** Changes the message's midi channel.
This won't do anything for non-channel messages like sysexes. This won't do anything for non-channel messages like sysexes.
@param newChannelNumber the channel number to change it to, in the range 1 to 16 @param newChannelNumber the channel number to change it to, in the range 1 to 16
*/ */
void setChannel (int newChannelNumber) noexcept; void setChannel (int newChannelNumber) noexcept;
@ -181,17 +179,13 @@ public:
bool isSysEx() const noexcept; bool isSysEx() const noexcept;
/** Returns a pointer to the sysex data inside the message. /** Returns a pointer to the sysex data inside the message.
If this event isn't a sysex event, it'll return 0. If this event isn't a sysex event, it'll return 0.
@see getSysExDataSize @see getSysExDataSize
*/ */
const uint8* getSysExData() const noexcept; const uint8* getSysExData() const noexcept;
/** Returns the size of the sysex data. /** Returns the size of the sysex data.
This value excludes the 0xf0 header byte and the 0xf7 at the end. This value excludes the 0xf0 header byte and the 0xf7 at the end.
@see getSysExData @see getSysExData
*/ */
int getSysExDataSize() const noexcept; int getSysExDataSize() const noexcept;
@ -252,15 +246,12 @@ public:
bool isNoteOnOrOff() const noexcept; bool isNoteOnOrOff() const noexcept;
/** Returns the midi note number for note-on and note-off messages. /** Returns the midi note number for note-on and note-off messages.
If the message isn't a note-on or off, the value returned is undefined. If the message isn't a note-on or off, the value returned is undefined.
@see isNoteOff, getMidiNoteName, getMidiNoteInHertz, setNoteNumber @see isNoteOff, getMidiNoteName, getMidiNoteInHertz, setNoteNumber
*/ */
int getNoteNumber() const noexcept; int getNoteNumber() const noexcept;
/** Changes the midi note number of a note-on or note-off message. /** Changes the midi note number of a note-on or note-off message.
If the message isn't a note on or off, this will do nothing. If the message isn't a note on or off, this will do nothing.
*/ */
void setNoteNumber (int newNoteNumber) noexcept; void setNoteNumber (int newNoteNumber) noexcept;
@ -320,16 +311,12 @@ public:
//============================================================================== //==============================================================================
/** Returns true if the message is a program (patch) change message. /** Returns true if the message is a program (patch) change message.
@see getProgramChangeNumber, getGMInstrumentName @see getProgramChangeNumber, getGMInstrumentName
*/ */
bool isProgramChange() const noexcept; bool isProgramChange() const noexcept;
/** Returns the new program number of a program change message. /** Returns the new program number of a program change message.
If the message isn't a program change, the value returned is undefined.
If the message isn't a program change, the value returned will be
nonsense.
@see isProgramChange, getGMInstrumentName @see isProgramChange, getGMInstrumentName
*/ */
int getProgramChangeNumber() const noexcept; int getProgramChangeNumber() const noexcept;
@ -344,7 +331,6 @@ public:
//============================================================================== //==============================================================================
/** Returns true if the message is a pitch-wheel move. /** Returns true if the message is a pitch-wheel move.
@see getPitchWheelValue, pitchWheel @see getPitchWheelValue, pitchWheel
*/ */
bool isPitchWheel() const noexcept; bool isPitchWheel() const noexcept;
@ -433,7 +419,6 @@ public:
/** Returns the controller number of a controller message. /** Returns the controller number of a controller message.
The name of the controller can be looked up using the getControllerName() method. The name of the controller can be looked up using the getControllerName() method.
Note that the value returned is invalid for messages that aren't controller changes. Note that the value returned is invalid for messages that aren't controller changes.
@see isController, getControllerName, getControllerValue @see isController, getControllerName, getControllerValue
@ -443,7 +428,6 @@ public:
/** Returns the controller value from a controller message. /** Returns the controller value from a controller message.
A value 0 to 127 is returned to indicate the new controller position. A value 0 to 127 is returned to indicate the new controller position.
Note that the value returned is invalid for messages that aren't controller changes. Note that the value returned is invalid for messages that aren't controller changes.
@see isController, getControllerNumber @see isController, getControllerNumber
@ -467,13 +451,11 @@ public:
int value) noexcept; int value) noexcept;
/** Checks whether this message is an all-notes-off message. /** Checks whether this message is an all-notes-off message.
@see allNotesOff @see allNotesOff
*/ */
bool isAllNotesOff() const noexcept; bool isAllNotesOff() const noexcept;
/** Checks whether this message is an all-sound-off message. /** Checks whether this message is an all-sound-off message.
@see allSoundOff @see allSoundOff
*/ */
bool isAllSoundOff() const noexcept; bool isAllSoundOff() const noexcept;
@ -520,13 +502,11 @@ public:
int getMetaEventType() const noexcept; int getMetaEventType() const noexcept;
/** Returns a pointer to the data in a meta-event. /** Returns a pointer to the data in a meta-event.
@see isMetaEvent, getMetaEventLength @see isMetaEvent, getMetaEventLength
*/ */
const uint8* getMetaEventData() const noexcept; const uint8* getMetaEventData() const noexcept;
/** Returns the length of the data for a meta-event. /** Returns the length of the data for a meta-event.
@see isMetaEvent, getMetaEventData @see isMetaEvent, getMetaEventData
*/ */
int getMetaEventLength() const noexcept; int getMetaEventLength() const noexcept;
@ -539,29 +519,28 @@ public:
bool isEndOfTrackMetaEvent() const noexcept; bool isEndOfTrackMetaEvent() const noexcept;
/** Creates an end-of-track meta-event. /** Creates an end-of-track meta-event.
@see isEndOfTrackMetaEvent @see isEndOfTrackMetaEvent
*/ */
static MidiMessage endOfTrack() noexcept; static MidiMessage endOfTrack() noexcept;
/** Returns true if this is an 'track name' meta-event. /** Returns true if this is an 'track name' meta-event.
You can use the getTextFromTextMetaEvent() method to get the track's name. You can use the getTextFromTextMetaEvent() method to get the track's name.
*/ */
bool isTrackNameEvent() const noexcept; bool isTrackNameEvent() const noexcept;
/** Returns true if this is a 'text' meta-event. /** Returns true if this is a 'text' meta-event.
@see getTextFromTextMetaEvent @see getTextFromTextMetaEvent
*/ */
bool isTextMetaEvent() const noexcept; bool isTextMetaEvent() const noexcept;
/** Returns the text from a text meta-event. /** Returns the text from a text meta-event.
@see isTextMetaEvent @see isTextMetaEvent
*/ */
String getTextFromTextMetaEvent() const; String getTextFromTextMetaEvent() const;
/** Creates a text meta-event. */
static MidiMessage textMetaEvent (int type, StringRef text);
//============================================================================== //==============================================================================
/** Returns true if this is a 'tempo' meta-event. /** Returns true if this is a 'tempo' meta-event.
@see getTempoMetaEventTickLength, getTempoSecondsPerQuarterNote @see getTempoMetaEventTickLength, getTempoSecondsPerQuarterNote
@ -660,7 +639,6 @@ public:
//============================================================================== //==============================================================================
/** Returns true if this is a midi start event. /** Returns true if this is a midi start event.
@see midiStart @see midiStart
*/ */
bool isMidiStart() const noexcept; bool isMidiStart() const noexcept;
@ -669,7 +647,6 @@ public:
static MidiMessage midiStart() noexcept; static MidiMessage midiStart() noexcept;
/** Returns true if this is a midi continue event. /** Returns true if this is a midi continue event.
@see midiContinue @see midiContinue
*/ */
bool isMidiContinue() const noexcept; bool isMidiContinue() const noexcept;
@ -678,7 +655,6 @@ public:
static MidiMessage midiContinue() noexcept; static MidiMessage midiContinue() noexcept;
/** Returns true if this is a midi stop event. /** Returns true if this is a midi stop event.
@see midiStop @see midiStop
*/ */
bool isMidiStop() const noexcept; bool isMidiStop() const noexcept;
@ -687,7 +663,6 @@ public:
static MidiMessage midiStop() noexcept; static MidiMessage midiStop() noexcept;
/** Returns true if this is a midi clock event. /** Returns true if this is a midi clock event.
@see midiClock, songPositionPointer @see midiClock, songPositionPointer
*/ */
bool isMidiClock() const noexcept; bool isMidiClock() const noexcept;
@ -696,13 +671,11 @@ public:
static MidiMessage midiClock() noexcept; static MidiMessage midiClock() noexcept;
/** Returns true if this is a song-position-pointer message. /** Returns true if this is a song-position-pointer message.
@see getSongPositionPointerMidiBeat, songPositionPointer @see getSongPositionPointerMidiBeat, songPositionPointer
*/ */
bool isSongPositionPointer() const noexcept; bool isSongPositionPointer() const noexcept;
/** Returns the midi beat-number of a song-position-pointer message. /** Returns the midi beat-number of a song-position-pointer message.
@see isSongPositionPointer, songPositionPointer @see isSongPositionPointer, songPositionPointer
*/ */
int getSongPositionPointerMidiBeat() const noexcept; int getSongPositionPointerMidiBeat() const noexcept;
@ -719,23 +692,18 @@ public:
//============================================================================== //==============================================================================
/** Returns true if this is a quarter-frame midi timecode message. /** Returns true if this is a quarter-frame midi timecode message.
@see quarterFrame, getQuarterFrameSequenceNumber, getQuarterFrameValue @see quarterFrame, getQuarterFrameSequenceNumber, getQuarterFrameValue
*/ */
bool isQuarterFrame() const noexcept; bool isQuarterFrame() const noexcept;
/** Returns the sequence number of a quarter-frame midi timecode message. /** Returns the sequence number of a quarter-frame midi timecode message.
This will be a value between 0 and 7. This will be a value between 0 and 7.
@see isQuarterFrame, getQuarterFrameValue, quarterFrame @see isQuarterFrame, getQuarterFrameValue, quarterFrame
*/ */
int getQuarterFrameSequenceNumber() const noexcept; int getQuarterFrameSequenceNumber() const noexcept;
/** Returns the value from a quarter-frame message. /** Returns the value from a quarter-frame message.
This will be the lower nybble of the message's data-byte, a value between 0 and 15
This will be the lower nybble of the message's data-byte, a value
between 0 and 15
*/ */
int getQuarterFrameValue() const noexcept; int getQuarterFrameValue() const noexcept;
@ -747,7 +715,6 @@ public:
static MidiMessage quarterFrame (int sequenceNumber, int value) noexcept; static MidiMessage quarterFrame (int sequenceNumber, int value) noexcept;
/** SMPTE timecode types. /** SMPTE timecode types.
Used by the getFullFrameParameters() and fullFrame() methods. Used by the getFullFrameParameters() and fullFrame() methods.
*/ */
enum SmpteTimecodeType enum SmpteTimecodeType
@ -758,8 +725,7 @@ public:
fps30 = 3 fps30 = 3
}; };
/** Returns true if this is a full-frame midi timecode message. /** Returns true if this is a full-frame midi timecode message. */
*/
bool isFullFrame() const noexcept; bool isFullFrame() const noexcept;
/** Extracts the timecode information from a full-frame midi timecode message. /** Extracts the timecode information from a full-frame midi timecode message.
@ -773,8 +739,7 @@ public:
int& frames, int& frames,
SmpteTimecodeType& timecodeType) const noexcept; SmpteTimecodeType& timecodeType) const noexcept;
/** Creates a full-frame MTC message. /** Creates a full-frame MTC message. */
*/
static MidiMessage fullFrame (int hours, static MidiMessage fullFrame (int hours,
int minutes, int minutes,
int seconds, int seconds,
@ -799,7 +764,6 @@ public:
}; };
/** Checks whether this is an MMC message. /** Checks whether this is an MMC message.
If it is, you can use the getMidiMachineControlCommand() to find out its type. If it is, you can use the getMidiMachineControlCommand() to find out its type.
*/ */
bool isMidiMachineControlMessage() const noexcept; bool isMidiMachineControlMessage() const noexcept;
@ -889,6 +853,9 @@ public:
*/ */
static double getMidiNoteInHertz (int noteNumber, const double frequencyOfA = 440.0) noexcept; static double getMidiNoteInHertz (int noteNumber, const double frequencyOfA = 440.0) noexcept;
/** Returns true if the given midi note number is a black key. */
static bool isMidiNoteBlack (int noteNumber) noexcept;
/** Returns the standard name of a GM instrument, or nullptr if unknown for this index. /** Returns the standard name of a GM instrument, or nullptr if unknown for this index.
@param midiInstrumentNumber the program number 0 to 127 @param midiInstrumentNumber the program number 0 to 127

@ -1,7 +1,7 @@
{ {
"id": "juce_audio_devices", "id": "juce_audio_devices",
"name": "JUCE audio and midi I/O device classes", "name": "JUCE audio and midi I/O device classes",
"version": "3.0.1", "version": "3.0.3",
"description": "Classes to play and record from audio and midi i/o devices.", "description": "Classes to play and record from audio and midi i/o devices.",
"website": "http://www.juce.com/juce", "website": "http://www.juce.com/juce",
"license": "GPL/Commercial", "license": "GPL/Commercial",

@ -122,7 +122,7 @@ public:
setSessionFloat64Property (kAudioSessionProperty_PreferredHardwareSampleRate, targetSampleRate); setSessionFloat64Property (kAudioSessionProperty_PreferredHardwareSampleRate, targetSampleRate);
updateSampleRates(); updateSampleRates();
setSessionFloat64Property (kAudioSessionProperty_PreferredHardwareIOBufferDuration, preferredBufferSize / sampleRate); setSessionFloat32Property (kAudioSessionProperty_PreferredHardwareIOBufferDuration, preferredBufferSize / sampleRate);
updateCurrentBufferSize(); updateCurrentBufferSize();
prepareFloatBuffers (actualBufferSize); prepareFloatBuffers (actualBufferSize);
@ -553,6 +553,7 @@ private:
} }
static void setSessionUInt32Property (AudioSessionPropertyID propID, UInt32 v) noexcept { AudioSessionSetProperty (propID, sizeof (v), &v); } static void setSessionUInt32Property (AudioSessionPropertyID propID, UInt32 v) noexcept { AudioSessionSetProperty (propID, sizeof (v), &v); }
static void setSessionFloat32Property (AudioSessionPropertyID propID, Float32 v) noexcept { AudioSessionSetProperty (propID, sizeof (v), &v); }
static void setSessionFloat64Property (AudioSessionPropertyID propID, Float64 v) noexcept { AudioSessionSetProperty (propID, sizeof (v), &v); } static void setSessionFloat64Property (AudioSessionPropertyID propID, Float64 v) noexcept { AudioSessionSetProperty (propID, sizeof (v), &v); }
JUCE_DECLARE_NON_COPYABLE (iOSAudioIODevice) JUCE_DECLARE_NON_COPYABLE (iOSAudioIODevice)

@ -185,15 +185,12 @@ public:
const int tempBufSize = bufferSize + 4; const int tempBufSize = bufferSize + 4;
audioBuffer.calloc ((size_t) ((numInputChans + numOutputChans) * tempBufSize)); audioBuffer.calloc ((size_t) ((numInputChans + numOutputChans) * tempBufSize));
tempInputBuffers.calloc ((size_t) numInputChans + 2); tempInputBuffers.calloc ((size_t) numInputChans + 2);
tempOutputBuffers.calloc ((size_t) numOutputChans + 2); tempOutputBuffers.calloc ((size_t) numOutputChans + 2);
int count = 0; int count = 0;
for (int i = 0; i < numInputChans; ++i) for (int i = 0; i < numInputChans; ++i) tempInputBuffers[i] = audioBuffer + count++ * tempBufSize;
tempInputBuffers[i] = audioBuffer + count++ * tempBufSize; for (int i = 0; i < numOutputChans; ++i) tempOutputBuffers[i] = audioBuffer + count++ * tempBufSize;
for (int i = 0; i < numOutputChans; ++i)
tempOutputBuffers[i] = audioBuffer + count++ * tempBufSize;
} }
struct CallbackDetailsForChannel struct CallbackDetailsForChannel
@ -234,24 +231,15 @@ public:
NSString* nameNSString = nil; NSString* nameNSString = nil;
size = sizeof (nameNSString); size = sizeof (nameNSString);
#if JUCE_CLANG pa.mSelector = kAudioObjectPropertyElementName;
// Very irritating that AudioDeviceGetProperty is marked as deprecated, since pa.mElement = chanNum + 1;
// there seems to be no replacement way of getting the channel names.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#endif
if (AudioDeviceGetProperty (deviceID, chanNum + 1, input, kAudioDevicePropertyChannelNameCFString, if (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &nameNSString) == noErr)
&size, &nameNSString) == noErr)
{ {
name = nsStringToJuce (nameNSString); name = nsStringToJuce (nameNSString);
[nameNSString release]; [nameNSString release];
} }
#if JUCE_CLANG
#pragma clang diagnostic pop
#endif
if ((input ? activeInputChans : activeOutputChans) [chanNum]) if ((input ? activeInputChans : activeOutputChans) [chanNum])
{ {
CallbackDetailsForChannel info = { i, (int) j, (int) b.mNumberChannels }; CallbackDetailsForChannel info = { i, (int) j, (int) b.mNumberChannels };
@ -283,7 +271,7 @@ public:
if (OK (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, nullptr, &size))) if (OK (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, nullptr, &size)))
{ {
HeapBlock <AudioValueRange> ranges; HeapBlock<AudioValueRange> ranges;
ranges.calloc (size, 1); ranges.calloc (size, 1);
if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, ranges))) if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, ranges)))
@ -322,7 +310,7 @@ public:
if (OK (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, nullptr, &size))) if (OK (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, nullptr, &size)))
{ {
HeapBlock <AudioValueRange> ranges; HeapBlock<AudioValueRange> ranges;
ranges.calloc (size, 1); ranges.calloc (size, 1);
if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, ranges))) if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, ranges)))
@ -424,7 +412,7 @@ public:
StringArray getSources (bool input) StringArray getSources (bool input)
{ {
StringArray s; StringArray s;
HeapBlock <OSType> types; HeapBlock<OSType> types;
const int num = getAllDataSourcesForDevice (deviceID, types); const int num = getAllDataSourcesForDevice (deviceID, types);
for (int i = 0; i < num; ++i) for (int i = 0; i < num; ++i)
@ -466,7 +454,7 @@ public:
{ {
if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &currentSourceID))) if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &currentSourceID)))
{ {
HeapBlock <OSType> types; HeapBlock<OSType> types;
const int num = getAllDataSourcesForDevice (deviceID, types); const int num = getAllDataSourcesForDevice (deviceID, types);
for (int i = 0; i < num; ++i) for (int i = 0; i < num; ++i)
@ -487,7 +475,7 @@ public:
{ {
if (deviceID != 0) if (deviceID != 0)
{ {
HeapBlock <OSType> types; HeapBlock<OSType> types;
const int num = getAllDataSourcesForDevice (deviceID, types); const int num = getAllDataSourcesForDevice (deviceID, types);
if (isPositiveAndBelow (index, num)) if (isPositiveAndBelow (index, num))
@ -1049,12 +1037,12 @@ public:
devices.clear(); devices.clear();
} }
void addDevice (AudioIODevice* device) void addDevice (AudioIODevice* device, bool useInputs, bool useOutputs)
{ {
jassert (device != nullptr); jassert (device != nullptr);
jassert (! isOpen()); jassert (! isOpen());
jassert (! device->isOpen()); jassert (! device->isOpen());
devices.add (new DeviceWrapper (*this, device)); devices.add (new DeviceWrapper (*this, device, useInputs, useOutputs));
} }
Array<AudioIODevice*> getDevices() const Array<AudioIODevice*> getDevices() const
@ -1072,8 +1060,7 @@ public:
StringArray names; StringArray names;
for (int i = 0; i < devices.size(); ++i) for (int i = 0; i < devices.size(); ++i)
names.addArray (devices.getUnchecked(i)->device->getOutputChannelNames()); names.addArray (devices.getUnchecked(i)->getOutputChannelNames());
names.appendNumbersToDuplicates (false, true); names.appendNumbersToDuplicates (false, true);
return names; return names;
@ -1084,7 +1071,7 @@ public:
StringArray names; StringArray names;
for (int i = 0; i < devices.size(); ++i) for (int i = 0; i < devices.size(); ++i)
names.addArray (devices.getUnchecked(i)->device->getInputChannelNames()); names.addArray (devices.getUnchecked(i)->getInputChannelNames());
names.appendNumbersToDuplicates (false, true); names.appendNumbersToDuplicates (false, true);
return names; return names;
@ -1181,8 +1168,8 @@ public:
BigInteger ins (inputChannels >> totalInputChanIndex); BigInteger ins (inputChannels >> totalInputChanIndex);
BigInteger outs (outputChannels >> totalOutputChanIndex); BigInteger outs (outputChannels >> totalOutputChanIndex);
int numIns = d.device->getInputChannelNames().size(); int numIns = d.getInputChannelNames().size();
int numOuts = d.device->getOutputChannelNames().size(); int numOuts = d.getOutputChannelNames().size();
totalInputChanIndex += numIns; totalInputChanIndex += numIns;
totalOutputChanIndex += numOuts; totalOutputChanIndex += numOuts;
@ -1225,9 +1212,13 @@ public:
for (int i = 0; i < devices.size(); ++i) for (int i = 0; i < devices.size(); ++i)
{ {
const int numChans = devices.getUnchecked(i)->device->getOutputChannelNames().size(); const int numChans = devices.getUnchecked(i)->getOutputChannelNames().size();
chans |= (devices.getUnchecked(i)->device->getActiveOutputChannels() << start);
start += numChans; if (numChans > 0)
{
chans |= (devices.getUnchecked(i)->device->getActiveOutputChannels() << start);
start += numChans;
}
} }
return chans; return chans;
@ -1240,9 +1231,13 @@ public:
for (int i = 0; i < devices.size(); ++i) for (int i = 0; i < devices.size(); ++i)
{ {
const int numChans = devices.getUnchecked(i)->device->getInputChannelNames().size(); const int numChans = devices.getUnchecked(i)->getInputChannelNames().size();
chans |= (devices.getUnchecked(i)->device->getActiveInputChannels() << start);
start += numChans; if (numChans > 0)
{
chans |= (devices.getUnchecked(i)->device->getActiveInputChannels() << start);
start += numChans;
}
} }
return chans; return chans;
@ -1469,8 +1464,9 @@ private:
//============================================================================== //==============================================================================
struct DeviceWrapper : private AudioIODeviceCallback struct DeviceWrapper : private AudioIODeviceCallback
{ {
DeviceWrapper (AudioIODeviceCombiner& cd, AudioIODevice* d) DeviceWrapper (AudioIODeviceCombiner& cd, AudioIODevice* d, bool useIns, bool useOuts)
: owner (cd), device (d), inputIndex (0), outputIndex (0), : owner (cd), device (d), inputIndex (0), outputIndex (0),
useInputs (useIns), useOutputs (useOuts),
inputFifo (32), outputFifo (32), done (false) inputFifo (32), outputFifo (32), done (false)
{ {
} }
@ -1490,10 +1486,12 @@ private:
inputFifo.reset(); inputFifo.reset();
outputFifo.reset(); outputFifo.reset();
String err (device->open (inputChannels, outputChannels, sampleRate, bufferSize)); String err (device->open (useInputs ? inputChannels : BigInteger(),
useOutputs ? outputChannels : BigInteger(),
sampleRate, bufferSize));
numInputChans = device->getActiveInputChannels().countNumberOfSetBits(); numInputChans = useInputs ? device->getActiveInputChannels().countNumberOfSetBits() : 0;
numOutputChans = device->getActiveOutputChannels().countNumberOfSetBits(); numOutputChans = useOutputs ? device->getActiveOutputChannels().countNumberOfSetBits() : 0;
inputIndex = channelIndex; inputIndex = channelIndex;
outputIndex = channelIndex + numInputChans; outputIndex = channelIndex + numInputChans;
@ -1518,6 +1516,9 @@ private:
outputFifo.reset(); outputFifo.reset();
} }
StringArray getOutputChannelNames() const { return useOutputs ? device->getOutputChannelNames() : StringArray(); }
StringArray getInputChannelNames() const { return useInputs ? device->getInputChannelNames() : StringArray(); }
bool isInputReady (int numSamples) const noexcept bool isInputReady (int numSamples) const noexcept
{ {
return numInputChans == 0 || inputFifo.getNumReady() >= numSamples; return numInputChans == 0 || inputFifo.getNumReady() >= numSamples;
@ -1655,6 +1656,7 @@ private:
AudioIODeviceCombiner& owner; AudioIODeviceCombiner& owner;
ScopedPointer<AudioIODevice> device; ScopedPointer<AudioIODevice> device;
int inputIndex, numInputChans, outputIndex, numOutputChans; int inputIndex, numInputChans, outputIndex, numOutputChans;
bool useInputs, useOutputs;
AbstractFifo inputFifo, outputFifo; AbstractFifo inputFifo, outputFifo;
bool done; bool done;
@ -1850,8 +1852,8 @@ public:
if (out == nullptr) return in.release(); if (out == nullptr) return in.release();
ScopedPointer<AudioIODeviceCombiner> combo (new AudioIODeviceCombiner (combinedName)); ScopedPointer<AudioIODeviceCombiner> combo (new AudioIODeviceCombiner (combinedName));
combo->addDevice (in.release()); combo->addDevice (in.release(), true, false);
combo->addDevice (out.release()); combo->addDevice (out.release(), false, true);
return combo.release(); return combo.release();
} }
@ -1874,7 +1876,7 @@ private:
if (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, nullptr, &size) == noErr) if (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, nullptr, &size) == noErr)
{ {
HeapBlock <AudioBufferList> bufList; HeapBlock<AudioBufferList> bufList;
bufList.calloc (size, 1); bufList.calloc (size, 1);
if (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, bufList) == noErr) if (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, bufList) == noErr)

@ -1,7 +1,7 @@
{ {
"id": "juce_audio_formats", "id": "juce_audio_formats",
"name": "JUCE audio file format codecs", "name": "JUCE audio file format codecs",
"version": "3.0.1", "version": "3.0.3",
"description": "Classes for reading and writing various audio file formats.", "description": "Classes for reading and writing various audio file formats.",
"website": "http://www.juce.com/juce", "website": "http://www.juce.com/juce",
"license": "GPL/Commercial", "license": "GPL/Commercial",

@ -124,8 +124,7 @@ struct AAXClasses
case 6: return AAX_eStemFormat_5_1; case 6: return AAX_eStemFormat_5_1;
case 7: return AAX_eStemFormat_7_0_DTS; case 7: return AAX_eStemFormat_7_0_DTS;
case 8: return AAX_eStemFormat_7_1_DTS; case 8: return AAX_eStemFormat_7_1_DTS;
default: jassertfalse; break;
default: jassertfalse; break; // hmm - not a valid number of chans..
} }
return AAX_eStemFormat_None; return AAX_eStemFormat_None;
@ -139,17 +138,45 @@ struct AAXClasses
case AAX_eStemFormat_Mono: return 1; case AAX_eStemFormat_Mono: return 1;
case AAX_eStemFormat_Stereo: return 2; case AAX_eStemFormat_Stereo: return 2;
case AAX_eStemFormat_LCR: return 3; case AAX_eStemFormat_LCR: return 3;
case AAX_eStemFormat_LCRS:
case AAX_eStemFormat_Quad: return 4; case AAX_eStemFormat_Quad: return 4;
case AAX_eStemFormat_5_0: return 5; case AAX_eStemFormat_5_0: return 5;
case AAX_eStemFormat_5_1: return 6; case AAX_eStemFormat_5_1:
case AAX_eStemFormat_6_0: return 6;
case AAX_eStemFormat_6_1:
case AAX_eStemFormat_7_0_SDDS:
case AAX_eStemFormat_7_0_DTS: return 7; case AAX_eStemFormat_7_0_DTS: return 7;
case AAX_eStemFormat_7_1_SDDS:
case AAX_eStemFormat_7_1_DTS: return 8; case AAX_eStemFormat_7_1_DTS: return 8;
default: jassertfalse; break; // hmm - not a valid number of chans.. default: jassertfalse; break;
} }
return 0; return 0;
} }
static const char* getSpeakerArrangementString (AAX_EStemFormat format) noexcept
{
switch (format)
{
case AAX_eStemFormat_Mono: return "M";
case AAX_eStemFormat_Stereo: return "L R";
case AAX_eStemFormat_LCR: return "L C R";
case AAX_eStemFormat_LCRS: return "L C R S";
case AAX_eStemFormat_Quad: return "L R Ls Rs";
case AAX_eStemFormat_5_0: return "L C R Ls Rs";
case AAX_eStemFormat_5_1: return "L C R Ls Rs LFE";
case AAX_eStemFormat_6_0: return "L C R Ls Cs Rs";
case AAX_eStemFormat_6_1: return "L C R Ls Cs Rs LFE";
case AAX_eStemFormat_7_0_SDDS: return "L Lc C Rc R Ls Rs";
case AAX_eStemFormat_7_1_SDDS: return "L Lc C Rc R Ls Rs LFE";
case AAX_eStemFormat_7_0_DTS: return "L C R Lss Rss Lsr Rsr";
case AAX_eStemFormat_7_1_DTS: return "L C R Lss Rss Lsr Rsr LFE";
default: break;
}
return nullptr;
}
//============================================================================== //==============================================================================
struct JUCELibraryRefCount struct JUCELibraryRefCount
{ {
@ -743,6 +770,9 @@ struct AAXClasses
midiBuffer.clear(); midiBuffer.clear();
(void) midiNodeIn;
(void) midiNodesOut;
#if JucePlugin_WantsMidiInput #if JucePlugin_WantsMidiInput
{ {
AAX_CMidiStream* const midiStream = midiNodeIn->GetNodeBuffer(); AAX_CMidiStream* const midiStream = midiNodeIn->GetNodeBuffer();
@ -852,6 +882,9 @@ struct AAXClasses
AudioProcessor& audioProcessor = getPluginInstance(); AudioProcessor& audioProcessor = getPluginInstance();
audioProcessor.setSpeakerArrangement (getSpeakerArrangementString (inputStemFormat),
getSpeakerArrangementString (outputStemFormat));
audioProcessor.setPlayConfigDetails (numberOfInputChannels, numberOfOutputChannels, sampleRate, lastBufferSize); audioProcessor.setPlayConfigDetails (numberOfInputChannels, numberOfOutputChannels, sampleRate, lastBufferSize);
audioProcessor.prepareToPlay (sampleRate, lastBufferSize); audioProcessor.prepareToPlay (sampleRate, lastBufferSize);
@ -928,6 +961,7 @@ struct AAXClasses
// This value needs to match the RTAS wrapper's Type ID, so that // This value needs to match the RTAS wrapper's Type ID, so that
// the host knows that the RTAS/AAX plugins are equivalent. // the host knows that the RTAS/AAX plugins are equivalent.
properties->AddProperty (AAX_eProperty_PlugInID_Native, 'jcaa' + channelConfigIndex); properties->AddProperty (AAX_eProperty_PlugInID_Native, 'jcaa' + channelConfigIndex);
properties->AddProperty (AAX_eProperty_PlugInID_AudioSuite, 'jyaa' + channelConfigIndex);
check (desc.AddProcessProc_Native (algorithmProcessCallback, properties)); check (desc.AddProcessProc_Native (algorithmProcessCallback, properties));
} }

@ -535,7 +535,7 @@ public:
#if BUILD_AU_CARBON_UI #if BUILD_AU_CARBON_UI
int GetNumCustomUIComponents() override int GetNumCustomUIComponents() override
{ {
return PluginHostType().isDigitalPerformer() ? 0 : 1; return getHostType().isDigitalPerformer() ? 0 : 1;
} }
void GetUIComponentDescs (ComponentDescription* inDescArray) override void GetUIComponentDescs (ComponentDescription* inDescArray) override
@ -947,6 +947,7 @@ public:
incomingEvents.addEvent (data, 3, (int) inStartFrame); incomingEvents.addEvent (data, 3, (int) inStartFrame);
return noErr; return noErr;
#else #else
(void) nStatus; (void) inChannel; (void) inData1; (void) inData2; (void) inStartFrame;
return kAudioUnitErr_PropertyNotInUse; return kAudioUnitErr_PropertyNotInUse;
#endif #endif
} }
@ -958,6 +959,7 @@ public:
incomingEvents.addEvent (inData, (int) inLength, 0); incomingEvents.addEvent (inData, (int) inLength, 0);
return noErr; return noErr;
#else #else
(void) inData; (void) inLength;
return kAudioUnitErr_PropertyNotInUse; return kAudioUnitErr_PropertyNotInUse;
#endif #endif
} }
@ -1093,7 +1095,7 @@ public:
bool keyPressed (const KeyPress&) override bool keyPressed (const KeyPress&) override
{ {
if (PluginHostType().isAbletonLive()) if (getHostType().isAbletonLive())
{ {
static NSTimeInterval lastEventTime = 0; // check we're not recursively sending the same event static NSTimeInterval lastEventTime = 0; // check we're not recursively sending the same event
NSTimeInterval eventTime = [[NSApp currentEvent] timestamp]; NSTimeInterval eventTime = [[NSApp currentEvent] timestamp];

@ -105,7 +105,7 @@ public:
const int y = settings->getIntValue ("windowY", -100); const int y = settings->getIntValue ("windowY", -100);
if (x != -100 && y != -100) if (x != -100 && y != -100)
setBoundsConstrained (Rectangle<int> (x, y, getWidth(), getHeight())); setBoundsConstrained (juce::Rectangle<int> (x, y, getWidth(), getHeight()));
else else
centreWithSize (getWidth(), getHeight()); centreWithSize (getWidth(), getHeight());
} }

@ -111,11 +111,11 @@ namespace juce
{ {
#if JUCE_MAC #if JUCE_MAC
extern void initialiseMac(); extern void initialiseMac();
extern void* attachComponentToWindowRef (Component*, void* windowRef); extern void* attachComponentToWindowRef (Component*, void* parent, bool isNSView);
extern void detachComponentFromWindowRef (Component*, void* nsWindow); extern void detachComponentFromWindowRef (Component*, void* window, bool isNSView);
extern void setNativeHostWindowSize (void* nsWindow, Component*, int newWidth, int newHeight); extern void setNativeHostWindowSize (void* window, Component*, int newWidth, int newHeight, bool isNSView);
extern void checkWindowVisibility (void* nsWindow, Component*); extern void checkWindowVisibility (void* window, Component*, bool isNSView);
extern bool forwardCurrentKeyEventToHost (Component*); extern bool forwardCurrentKeyEventToHost (Component*, bool isNSView);
#if ! JUCE_64BIT #if ! JUCE_64BIT
extern void updateEditorCompBounds (Component*); extern void updateEditorCompBounds (Component*);
#endif #endif
@ -283,6 +283,11 @@ public:
hasShutdown (false), hasShutdown (false),
firstProcessCallback (true), firstProcessCallback (true),
shouldDeleteEditor (false), shouldDeleteEditor (false),
#if JUCE_64BIT
useNSView (true),
#else
useNSView (false),
#endif
processTempBuffer (1, 1), processTempBuffer (1, 1),
hostWindow (0) hostWindow (0)
{ {
@ -366,61 +371,70 @@ public:
} }
//============================================================================== //==============================================================================
bool getEffectName (char* name) bool getEffectName (char* name) override
{ {
String (JucePlugin_Name).copyToUTF8 (name, 64); String (JucePlugin_Name).copyToUTF8 (name, 64);
return true; return true;
} }
bool getVendorString (char* text) bool getVendorString (char* text) override
{ {
String (JucePlugin_Manufacturer).copyToUTF8 (text, 64); String (JucePlugin_Manufacturer).copyToUTF8 (text, 64);
return true; return true;
} }
bool getProductString (char* text) { return getEffectName (text); } bool getProductString (char* text) override { return getEffectName (text); }
VstInt32 getVendorVersion() { return convertHexVersionToDecimal (JucePlugin_VersionCode); } VstInt32 getVendorVersion() override { return convertHexVersionToDecimal (JucePlugin_VersionCode); }
VstPlugCategory getPlugCategory() { return JucePlugin_VSTCategory; } VstPlugCategory getPlugCategory() override { return JucePlugin_VSTCategory; }
bool keysRequired() { return (JucePlugin_EditorRequiresKeyboardFocus) != 0; } bool keysRequired() { return (JucePlugin_EditorRequiresKeyboardFocus) != 0; }
VstInt32 canDo (char* text) VstInt32 canDo (char* text) override
{ {
VstInt32 result = 0;
if (strcmp (text, "receiveVstEvents") == 0 if (strcmp (text, "receiveVstEvents") == 0
|| strcmp (text, "receiveVstMidiEvent") == 0 || strcmp (text, "receiveVstMidiEvent") == 0
|| strcmp (text, "receiveVstMidiEvents") == 0) || strcmp (text, "receiveVstMidiEvents") == 0)
{ {
#if JucePlugin_WantsMidiInput #if JucePlugin_WantsMidiInput
result = 1; return 1;
#else #else
result = -1; return -1;
#endif #endif
} }
else if (strcmp (text, "sendVstEvents") == 0
|| strcmp (text, "sendVstMidiEvent") == 0 if (strcmp (text, "sendVstEvents") == 0
|| strcmp (text, "sendVstMidiEvents") == 0) || strcmp (text, "sendVstMidiEvent") == 0
|| strcmp (text, "sendVstMidiEvents") == 0)
{ {
#if JucePlugin_ProducesMidiOutput #if JucePlugin_ProducesMidiOutput
result = 1; return 1;
#else #else
result = -1; return -1;
#endif #endif
} }
else if (strcmp (text, "receiveVstTimeInfo") == 0
|| strcmp (text, "conformsToWindowRules") == 0 if (strcmp (text, "receiveVstTimeInfo") == 0
|| strcmp (text, "bypass") == 0) || strcmp (text, "conformsToWindowRules") == 0
|| strcmp (text, "bypass") == 0)
{ {
result = 1; return 1;
} }
else if (strcmp (text, "openCloseAnyThread") == 0)
if (strcmp (text, "openCloseAnyThread") == 0)
{ {
// This tells Wavelab to use the UI thread to invoke open/close, // This tells Wavelab to use the UI thread to invoke open/close,
// like all other hosts do. // like all other hosts do.
result = -1; return -1;
}
#if JUCE_MAC
if (strcmp (text, "hasCockosViewAsConfig") == 0)
{
useNSView = true;
return 0xbeef0000;
} }
#endif
return result; return 0;
} }
bool getInputProperties (VstInt32 index, VstPinProperties* properties) bool getInputProperties (VstInt32 index, VstPinProperties* properties)
@ -485,6 +499,7 @@ public:
VSTMidiEventList::addEventsToMidiBuffer (events, midiEvents); VSTMidiEventList::addEventsToMidiBuffer (events, midiEvents);
return 1; return 1;
#else #else
(void) events;
return 0; return 0;
#endif #endif
} }
@ -1014,7 +1029,7 @@ public:
#if JUCE_MAC #if JUCE_MAC
if (hostWindow != 0) if (hostWindow != 0)
checkWindowVisibility (hostWindow, editorComp); checkWindowVisibility (hostWindow, editorComp, useNSView);
#endif #endif
tryMasterIdle(); tryMasterIdle();
@ -1107,7 +1122,7 @@ public:
#if JUCE_MAC #if JUCE_MAC
if (hostWindow != 0) if (hostWindow != 0)
{ {
detachComponentFromWindowRef (editorComp, hostWindow); detachComponentFromWindowRef (editorComp, hostWindow, useNSView);
hostWindow = 0; hostWindow = 0;
} }
#endif #endif
@ -1164,7 +1179,7 @@ public:
Window editorWnd = (Window) editorComp->getWindowHandle(); Window editorWnd = (Window) editorComp->getWindowHandle();
XReparentWindow (display, editorWnd, hostWindow, 0, 0); XReparentWindow (display, editorWnd, hostWindow, 0, 0);
#else #else
hostWindow = attachComponentToWindowRef (editorComp, ptr); hostWindow = attachComponentToWindowRef (editorComp, ptr, useNSView);
#endif #endif
editorComp->setVisible (true); editorComp->setVisible (true);
@ -1210,7 +1225,7 @@ public:
{ {
// some hosts don't support the sizeWindow call, so do it manually.. // some hosts don't support the sizeWindow call, so do it manually..
#if JUCE_MAC #if JUCE_MAC
setNativeHostWindowSize (hostWindow, editorComp, newWidth, newHeight); setNativeHostWindowSize (hostWindow, editorComp, newWidth, newHeight, useNSView);
#elif JUCE_LINUX #elif JUCE_LINUX
// (Currently, all linux hosts support sizeWindow, so this should never need to happen) // (Currently, all linux hosts support sizeWindow, so this should never need to happen)
@ -1266,12 +1281,6 @@ public:
} }
} }
static PluginHostType& getHostType()
{
static PluginHostType hostType;
return hostType;
}
//============================================================================== //==============================================================================
// A component to hold the AudioProcessorEditor, and cope with some housekeeping // A component to hold the AudioProcessorEditor, and cope with some housekeeping
// chores when it changes or repaints. // chores when it changes or repaints.
@ -1323,7 +1332,7 @@ public:
{ {
// If we have an unused keypress, move the key-focus to a host window // If we have an unused keypress, move the key-focus to a host window
// and re-inject the event.. // and re-inject the event..
return forwardCurrentKeyEventToHost (this); return forwardCurrentKeyEventToHost (this, wrapper.useNSView);
} }
#endif #endif
@ -1338,7 +1347,8 @@ public:
editor->setBounds (getLocalBounds()); editor->setBounds (getLocalBounds());
#if JUCE_MAC && ! JUCE_64BIT #if JUCE_MAC && ! JUCE_64BIT
updateEditorCompBounds (this); if (! wrapper.useNSView)
updateEditorCompBounds (this);
#endif #endif
} }
@ -1349,8 +1359,9 @@ public:
const int cw = child->getWidth(); const int cw = child->getWidth();
const int ch = child->getHeight(); const int ch = child->getHeight();
#if JUCE_MAC && JUCE_64BIT #if JUCE_MAC
setTopLeftPosition (0, getHeight() - ch); if (wrapper.useNSView)
setTopLeftPosition (0, getHeight() - ch);
#endif #endif
wrapper.resizeHostWindow (cw, ch); wrapper.resizeHostWindow (cw, ch);
@ -1405,7 +1416,8 @@ private:
VSTMidiEventList outgoingEvents; VSTMidiEventList outgoingEvents;
VstSpeakerArrangementType speakerIn, speakerOut; VstSpeakerArrangementType speakerIn, speakerOut;
int numInChans, numOutChans; int numInChans, numOutChans;
bool isProcessing, isBypassed, hasShutdown, firstProcessCallback, shouldDeleteEditor; bool isProcessing, isBypassed, hasShutdown, firstProcessCallback;
bool shouldDeleteEditor, useNSView;
HeapBlock<float*> channels; HeapBlock<float*> channels;
Array<float*> tempChannels; // see note in processReplacing() Array<float*> tempChannels; // see note in processReplacing()
AudioSampleBuffer processTempBuffer; AudioSampleBuffer processTempBuffer;

@ -28,7 +28,7 @@
#include "../utility/juce_CheckSettingMacros.h" #include "../utility/juce_CheckSettingMacros.h"
#if JucePlugin_Build_VST #if JucePlugin_Build_VST || JucePlugin_Build_VST3
#define JUCE_MAC_WINDOW_VISIBITY_BODGE 1 #define JUCE_MAC_WINDOW_VISIBITY_BODGE 1
@ -77,13 +77,82 @@ void initialiseMac()
#endif #endif
} }
void* attachComponentToWindowRef (Component* comp, void* windowRef); void* attachComponentToWindowRef (Component* comp, void* parentWindowOrView, bool isNSView);
void* attachComponentToWindowRef (Component* comp, void* windowRef) void* attachComponentToWindowRef (Component* comp, void* parentWindowOrView, bool isNSView)
{ {
JUCE_AUTORELEASEPOOL JUCE_AUTORELEASEPOOL
{ {
#if JUCE_64BIT #if ! JUCE_64BIT
NSView* parentView = (NSView*) windowRef; if (! isNSView)
{
NSWindow* hostWindow = [[NSWindow alloc] initWithWindowRef: parentWindowOrView];
[hostWindow retain];
[hostWindow setCanHide: YES];
[hostWindow setReleasedWhenClosed: YES];
HIViewRef parentView = 0;
WindowAttributes attributes;
GetWindowAttributes ((WindowRef) parentWindowOrView, &attributes);
if ((attributes & kWindowCompositingAttribute) != 0)
{
HIViewRef root = HIViewGetRoot ((WindowRef) parentWindowOrView);
HIViewFindByID (root, kHIViewWindowContentID, &parentView);
if (parentView == 0)
parentView = root;
}
else
{
GetRootControl ((WindowRef) parentWindowOrView, (ControlRef*) &parentView);
if (parentView == 0)
CreateRootControl ((WindowRef) parentWindowOrView, (ControlRef*) &parentView);
}
// It seems that the only way to successfully position our overlaid window is by putting a dummy
// HIView into the host's carbon window, and then catching events to see when it gets repositioned
HIViewRef dummyView = 0;
HIImageViewCreate (0, &dummyView);
HIRect r = { {0, 0}, { (float) comp->getWidth(), (float) comp->getHeight()} };
HIViewSetFrame (dummyView, &r);
HIViewAddSubview (parentView, dummyView);
comp->getProperties().set ("dummyViewRef", String::toHexString ((pointer_sized_int) (void*) dummyView));
EventHandlerRef ref;
const EventTypeSpec kControlBoundsChangedEvent = { kEventClassControl, kEventControlBoundsChanged };
InstallEventHandler (GetControlEventTarget (dummyView), NewEventHandlerUPP (viewBoundsChangedEvent), 1, &kControlBoundsChangedEvent, (void*) comp, &ref);
comp->getProperties().set ("boundsEventRef", String::toHexString ((pointer_sized_int) (void*) ref));
updateEditorCompBounds (comp);
#if ! JucePlugin_EditorRequiresKeyboardFocus
comp->addToDesktop (ComponentPeer::windowIsTemporary | ComponentPeer::windowIgnoresKeyPresses);
#else
comp->addToDesktop (ComponentPeer::windowIsTemporary);
#endif
comp->setVisible (true);
comp->toFront (false);
NSView* pluginView = (NSView*) comp->getWindowHandle();
NSWindow* pluginWindow = [pluginView window];
[pluginWindow setExcludedFromWindowsMenu: YES];
[pluginWindow setCanHide: YES];
[hostWindow addChildWindow: pluginWindow
ordered: NSWindowAbove];
[hostWindow orderFront: nil];
[pluginWindow orderFront: nil];
attachWindowHidingHooks (comp, (WindowRef) parentWindowOrView, hostWindow);
return hostWindow;
}
#endif
(void) isNSView;
NSView* parentView = (NSView*) parentWindowOrView;
#if JucePlugin_EditorRequiresKeyboardFocus #if JucePlugin_EditorRequiresKeyboardFocus
comp->addToDesktop (0, parentView); comp->addToDesktop (0, parentView);
@ -100,162 +169,125 @@ void* attachComponentToWindowRef (Component* comp, void* windowRef)
[[parentView window] setAcceptsMouseMovedEvents: YES]; [[parentView window] setAcceptsMouseMovedEvents: YES];
return parentView; return parentView;
#else
NSWindow* hostWindow = [[NSWindow alloc] initWithWindowRef: windowRef];
[hostWindow retain];
[hostWindow setCanHide: YES];
[hostWindow setReleasedWhenClosed: YES];
HIViewRef parentView = 0;
WindowAttributes attributes;
GetWindowAttributes ((WindowRef) windowRef, &attributes);
if ((attributes & kWindowCompositingAttribute) != 0)
{
HIViewRef root = HIViewGetRoot ((WindowRef) windowRef);
HIViewFindByID (root, kHIViewWindowContentID, &parentView);
if (parentView == 0)
parentView = root;
}
else
{
GetRootControl ((WindowRef) windowRef, (ControlRef*) &parentView);
if (parentView == 0)
CreateRootControl ((WindowRef) windowRef, (ControlRef*) &parentView);
}
// It seems that the only way to successfully position our overlaid window is by putting a dummy
// HIView into the host's carbon window, and then catching events to see when it gets repositioned
HIViewRef dummyView = 0;
HIImageViewCreate (0, &dummyView);
HIRect r = { {0, 0}, { (float) comp->getWidth(), (float) comp->getHeight()} };
HIViewSetFrame (dummyView, &r);
HIViewAddSubview (parentView, dummyView);
comp->getProperties().set ("dummyViewRef", String::toHexString ((pointer_sized_int) (void*) dummyView));
EventHandlerRef ref;
const EventTypeSpec kControlBoundsChangedEvent = { kEventClassControl, kEventControlBoundsChanged };
InstallEventHandler (GetControlEventTarget (dummyView), NewEventHandlerUPP (viewBoundsChangedEvent), 1, &kControlBoundsChangedEvent, (void*) comp, &ref);
comp->getProperties().set ("boundsEventRef", String::toHexString ((pointer_sized_int) (void*) ref));
updateEditorCompBounds (comp);
#if ! JucePlugin_EditorRequiresKeyboardFocus
comp->addToDesktop (ComponentPeer::windowIsTemporary | ComponentPeer::windowIgnoresKeyPresses);
#else
comp->addToDesktop (ComponentPeer::windowIsTemporary);
#endif
comp->setVisible (true);
comp->toFront (false);
NSView* pluginView = (NSView*) comp->getWindowHandle();
NSWindow* pluginWindow = [pluginView window];
[pluginWindow setExcludedFromWindowsMenu: YES];
[pluginWindow setCanHide: YES];
[hostWindow addChildWindow: pluginWindow
ordered: NSWindowAbove];
[hostWindow orderFront: nil];
[pluginWindow orderFront: nil];
attachWindowHidingHooks (comp, (WindowRef) windowRef, hostWindow);
return hostWindow;
#endif
} }
} }
void detachComponentFromWindowRef (Component* comp, void* nsWindow); void detachComponentFromWindowRef (Component* comp, void* window, bool isNSView);
void detachComponentFromWindowRef (Component* comp, void* nsWindow) void detachComponentFromWindowRef (Component* comp, void* window, bool isNSView)
{ {
JUCE_AUTORELEASEPOOL JUCE_AUTORELEASEPOOL
{ {
#if JUCE_64BIT #if ! JUCE_64BIT
comp->removeFromDesktop(); if (! isNSView)
#else {
EventHandlerRef ref = (EventHandlerRef) (void*) (pointer_sized_int) EventHandlerRef ref = (EventHandlerRef) (void*) (pointer_sized_int)
comp->getProperties() ["boundsEventRef"].toString().getHexValue64(); comp->getProperties() ["boundsEventRef"].toString().getHexValue64();
RemoveEventHandler (ref); RemoveEventHandler (ref);
removeWindowHidingHooks (comp); removeWindowHidingHooks (comp);
HIViewRef dummyView = (HIViewRef) (void*) (pointer_sized_int) HIViewRef dummyView = (HIViewRef) (void*) (pointer_sized_int)
comp->getProperties() ["dummyViewRef"].toString().getHexValue64(); comp->getProperties() ["dummyViewRef"].toString().getHexValue64();
if (HIViewIsValid (dummyView)) if (HIViewIsValid (dummyView))
CFRelease (dummyView); CFRelease (dummyView);
NSWindow* hostWindow = (NSWindow*) nsWindow; NSWindow* hostWindow = (NSWindow*) window;
NSView* pluginView = (NSView*) comp->getWindowHandle(); NSView* pluginView = (NSView*) comp->getWindowHandle();
NSWindow* pluginWindow = [pluginView window]; NSWindow* pluginWindow = [pluginView window];
[hostWindow removeChildWindow: pluginWindow]; [pluginView retain];
comp->removeFromDesktop(); [hostWindow removeChildWindow: pluginWindow];
[pluginWindow close];
comp->removeFromDesktop();
[pluginView release];
[hostWindow release]; [hostWindow release];
// The event loop needs to be run between closing the window and deleting the plugin, static bool needToRunMessageLoop = ! getHostType().isReaper();
// presumably to let the cocoa objects get tidied up. Leaving out this line causes crashes
// in Live and Reaper when you delete the plugin with its window open. // The event loop needs to be run between closing the window and deleting the plugin,
// (Doing it this way rather than using a single longer timout means that we can guarantee // presumably to let the cocoa objects get tidied up. Leaving out this line causes crashes
// how many messages will be dispatched, which seems to be vital in Reaper) // in Live when you delete the plugin with its window open.
for (int i = 20; --i >= 0;) // (Doing it this way rather than using a single longer timout means that we can guarantee
MessageManager::getInstance()->runDispatchLoopUntil (1); // how many messages will be dispatched, which seems to be vital in Reaper)
if (needToRunMessageLoop)
for (int i = 20; --i >= 0;)
MessageManager::getInstance()->runDispatchLoopUntil (1);
return;
}
#endif #endif
(void) isNSView;
comp->removeFromDesktop();
} }
} }
void setNativeHostWindowSize (void* nsWindow, Component* component, int newWidth, int newHeight); void setNativeHostWindowSize (void* window, Component* component, int newWidth, int newHeight, bool isNSView);
void setNativeHostWindowSize (void* nsWindow, Component* component, int newWidth, int newHeight) void setNativeHostWindowSize (void* window, Component* component, int newWidth, int newHeight, bool isNSView)
{ {
JUCE_AUTORELEASEPOOL JUCE_AUTORELEASEPOOL
{ {
#if JUCE_64BIT #if ! JUCE_64BIT
if (NSView* hostView = (NSView*) nsWindow) if (! isNSView)
{ {
// xxx is this necessary, or do the hosts detect a change in the child view and do this automatically? if (HIViewRef dummyView = (HIViewRef) (void*) (pointer_sized_int)
[hostView setFrameSize: NSMakeSize ([hostView frame].size.width + (newWidth - component->getWidth()), component->getProperties() ["dummyViewRef"].toString().getHexValue64())
[hostView frame].size.height + (newHeight - component->getHeight()))]; {
HIRect frameRect;
HIViewGetFrame (dummyView, &frameRect);
frameRect.size.width = newWidth;
frameRect.size.height = newHeight;
HIViewSetFrame (dummyView, &frameRect);
}
return;
} }
#else #endif
(void) nsWindow;
(void) isNSView;
if (HIViewRef dummyView = (HIViewRef) (void*) (pointer_sized_int) if (NSView* hostView = (NSView*) window)
component->getProperties() ["dummyViewRef"].toString().getHexValue64())
{ {
HIRect frameRect; const int dx = newWidth - component->getWidth();
HIViewGetFrame (dummyView, &frameRect); const int dy = newHeight - component->getHeight();
frameRect.size.width = newWidth;
frameRect.size.height = newHeight; NSRect r = [hostView frame];
HIViewSetFrame (dummyView, &frameRect); r.size.width += dx;
r.size.height += dy;
r.origin.y -= dy;
[hostView setFrame: r];
} }
#endif
} }
} }
void checkWindowVisibility (void* nsWindow, Component* comp); void checkWindowVisibility (void* window, Component* comp, bool isNSView);
void checkWindowVisibility (void* nsWindow, Component* comp) void checkWindowVisibility (void* window, Component* comp, bool isNSView)
{ {
(void) window; (void) comp; (void) isNSView;
#if ! JUCE_64BIT #if ! JUCE_64BIT
comp->setVisible ([((NSWindow*) nsWindow) isVisible]); if (! isNSView)
comp->setVisible ([((NSWindow*) window) isVisible]);
#endif #endif
} }
bool forwardCurrentKeyEventToHost (Component* comp); bool forwardCurrentKeyEventToHost (Component* comp, bool isNSView);
bool forwardCurrentKeyEventToHost (Component* comp) bool forwardCurrentKeyEventToHost (Component* comp, bool isNSView)
{ {
#if JUCE_64BIT #if ! JUCE_64BIT
(void) comp; if (! isNSView)
return false; {
#else NSWindow* win = [(NSView*) comp->getWindowHandle() window];
NSWindow* win = [(NSView*) comp->getWindowHandle() window]; [[win parentWindow] makeKeyWindow];
[[win parentWindow] makeKeyWindow]; repostCurrentNSEvent();
repostCurrentNSEvent(); return true;
return true; }
#endif #endif
(void) comp; (void) isNSView;
return false;
} }
} // (juce namespace) } // (juce namespace)

@ -1,8 +1,8 @@
{ {
"id": "juce_audio_plugin_client", "id": "juce_audio_plugin_client",
"name": "JUCE audio plugin wrapper classes", "name": "JUCE audio plugin wrapper classes",
"version": "3.0.1", "version": "3.0.3",
"description": "Classes for building VST, RTAS and AU plugins.", "description": "Classes for building VST, VST3, RTAS, AAX and AU plugins.",
"website": "http://www.juce.com/juce", "website": "http://www.juce.com/juce",
"license": "GPL/Commercial", "license": "GPL/Commercial",
@ -14,6 +14,8 @@
"compile": [ { "file": "VST/juce_VST_Wrapper.cpp" }, "compile": [ { "file": "VST/juce_VST_Wrapper.cpp" },
{ "file": "VST/juce_VST_Wrapper.mm", "target": "xcode" }, { "file": "VST/juce_VST_Wrapper.mm", "target": "xcode" },
{ "file": "VST3/juce_VST3_Wrapper.cpp" },
{ "file": "VST3/juce_VST3_Wrapper.mm", "target": "xcode" },
{ "file": "RTAS/juce_RTAS_DigiCode1.cpp", "warnings": "disabled", "stdcall": "1", "target": "xcode, msvc" }, { "file": "RTAS/juce_RTAS_DigiCode1.cpp", "warnings": "disabled", "stdcall": "1", "target": "xcode, msvc" },
{ "file": "RTAS/juce_RTAS_DigiCode2.cpp", "warnings": "disabled", "stdcall": "1", "target": "xcode, msvc" }, { "file": "RTAS/juce_RTAS_DigiCode2.cpp", "warnings": "disabled", "stdcall": "1", "target": "xcode, msvc" },
{ "file": "RTAS/juce_RTAS_DigiCode3.cpp", "warnings": "disabled", "stdcall": "1", "target": "xcode, msvc" }, { "file": "RTAS/juce_RTAS_DigiCode3.cpp", "warnings": "disabled", "stdcall": "1", "target": "xcode, msvc" },
@ -36,6 +38,7 @@
"RTAS/*.mm", "RTAS/*.mm",
"RTAS/*.h", "RTAS/*.h",
"VST/*", "VST/*",
"VST3/*",
"AAX/*", "AAX/*",
"utility/*" "utility/*"
] ]

@ -25,7 +25,8 @@
// The following checks should cause a compile error if you've forgotten to // The following checks should cause a compile error if you've forgotten to
// define all your plugin settings properly.. // define all your plugin settings properly..
#if ! (JucePlugin_Build_VST || JucePlugin_Build_AU || JucePlugin_Build_RTAS || JucePlugin_Build_AAX \ #if ! (JucePlugin_Build_VST || JucePlugin_Build_VST3 \
|| JucePlugin_Build_AU || JucePlugin_Build_RTAS || JucePlugin_Build_AAX \
|| JucePlugin_Build_Standalone || JucePlugin_Build_LV2) || JucePlugin_Build_Standalone || JucePlugin_Build_LV2)
#error "You need to enable at least one plugin format!" #error "You need to enable at least one plugin format!"
#endif #endif
@ -75,11 +76,16 @@
#endif #endif
//============================================================================== //==============================================================================
#if _WIN64 || (__LP64__ && (defined(__APPLE_CPP__) || defined(__APPLE_CC__))) #if _WIN64 || (__LP64__ && (defined (__APPLE_CPP__) || defined (__APPLE_CC__)))
#undef JucePlugin_Build_RTAS #undef JucePlugin_Build_RTAS
#define JucePlugin_Build_RTAS 0 #define JucePlugin_Build_RTAS 0
#endif #endif
#if ! (defined (_MSC_VER) || defined (__APPLE_CPP__) || defined (__APPLE_CC__))
#undef JucePlugin_Build_VST3
#define JucePlugin_Build_VST3 0
#endif
//============================================================================== //==============================================================================
#if JucePlugin_Build_RTAS && _MSC_VER && ! defined (JucePlugin_WinBag_path) #if JucePlugin_Build_RTAS && _MSC_VER && ! defined (JucePlugin_WinBag_path)
#error "You need to define the JucePlugin_WinBag_path value!" #error "You need to define the JucePlugin_WinBag_path value!"

@ -26,14 +26,21 @@
using namespace juce; using namespace juce;
#if JUCE_MAC && ! DOXYGEN namespace juce
#define Point juce::Point {
#define Component juce::Component #if JUCE_MAC && ! DOXYGEN
#define Point juce::Point
namespace juce #define Component juce::Component
{
void repostCurrentNSEvent(); void repostCurrentNSEvent();
} #endif
#endif
//==============================================================================
inline const PluginHostType& getHostType()
{
static PluginHostType hostType;
return hostType;
}
}
extern AudioProcessor* JUCE_CALLTYPE createPluginFilterOfType (AudioProcessor::WrapperType); extern AudioProcessor* JUCE_CALLTYPE createPluginFilterOfType (AudioProcessor::WrapperType);

@ -39,14 +39,19 @@ public:
AbletonLive7, AbletonLive7,
AbletonLive8, AbletonLive8,
AbletonLiveGeneric, AbletonLiveGeneric,
AdobeAudition,
AdobePremierePro, AdobePremierePro,
AppleLogic, AppleLogic,
Ardour,
CakewalkSonar8, CakewalkSonar8,
CakewalkSonarGeneric, CakewalkSonarGeneric,
DigidesignProTools, DigidesignProTools,
DigitalPerformer,
FruityLoops,
MagixSamplitude,
MergingPyramix,
MuseReceptorGeneric,
Reaper, Reaper,
Tracktion3,
TracktionGeneric,
SteinbergCubase4, SteinbergCubase4,
SteinbergCubase5, SteinbergCubase5,
SteinbergCubase5Bridged, SteinbergCubase5Bridged,
@ -62,13 +67,11 @@ public:
SteinbergWavelab7, SteinbergWavelab7,
SteinbergWavelab8, SteinbergWavelab8,
SteinbergWavelabGeneric, SteinbergWavelabGeneric,
MuseReceptorGeneric, SteinbergTestHost,
MagixSamplitude,
FruityLoops,
WaveBurner,
DigitalPerformer,
StudioOne, StudioOne,
MergingPyramix, Tracktion3,
TracktionGeneric,
WaveBurner,
VBVSTScanner VBVSTScanner
}; };
@ -76,25 +79,28 @@ public:
//============================================================================== //==============================================================================
bool isAbletonLive() const noexcept { return type == AbletonLive6 || type == AbletonLive7 || type == AbletonLive8 || type == AbletonLiveGeneric; } bool isAbletonLive() const noexcept { return type == AbletonLive6 || type == AbletonLive7 || type == AbletonLive8 || type == AbletonLiveGeneric; }
bool isNuendo() const noexcept { return type == SteinbergNuendo3 || type == SteinbergNuendo4 || type == SteinbergNuendo5 || type == SteinbergNuendoGeneric; } bool isAdobeAudition() const noexcept { return type == AdobeAudition; }
bool isArdour() const noexcept { return type == Ardour; }
bool isDigitalPerformer() const noexcept { return type == DigitalPerformer; }
bool isCubase() const noexcept { return type == SteinbergCubase4 || type == SteinbergCubase5 || type == SteinbergCubase5Bridged || type == SteinbergCubase6 || type == SteinbergCubase7 || type == SteinbergCubaseGeneric; } bool isCubase() const noexcept { return type == SteinbergCubase4 || type == SteinbergCubase5 || type == SteinbergCubase5Bridged || type == SteinbergCubase6 || type == SteinbergCubase7 || type == SteinbergCubaseGeneric; }
bool isCubaseBridged() const noexcept { return type == SteinbergCubase5Bridged; } bool isCubaseBridged() const noexcept { return type == SteinbergCubase5Bridged; }
bool isSteinberg() const noexcept { return isCubase() || isNuendo() || isWavelab(); }
bool isTracktion() const noexcept { return type == Tracktion3 || type == TracktionGeneric; }
bool isSonar() const noexcept { return type == CakewalkSonar8 || type == CakewalkSonarGeneric; }
bool isWavelab() const noexcept { return isWavelabLegacy() || type == SteinbergWavelab7 || type == SteinbergWavelab8 || type == SteinbergWavelabGeneric; }
bool isWavelabLegacy() const noexcept { return type == SteinbergWavelab5 || type == SteinbergWavelab6; }
bool isPremiere() const noexcept { return type == AdobePremierePro; }
bool isLogic() const noexcept { return type == AppleLogic; } bool isLogic() const noexcept { return type == AppleLogic; }
bool isReceptor() const noexcept { return type == MuseReceptorGeneric; }
bool isSamplitude() const noexcept { return type == MagixSamplitude; }
bool isFruityLoops() const noexcept { return type == FruityLoops; } bool isFruityLoops() const noexcept { return type == FruityLoops; }
bool isWaveBurner() const noexcept { return type == WaveBurner; } bool isNuendo() const noexcept { return type == SteinbergNuendo3 || type == SteinbergNuendo4 || type == SteinbergNuendo5 || type == SteinbergNuendoGeneric; }
bool isDigitalPerformer() const noexcept { return type == DigitalPerformer; } bool isPremiere() const noexcept { return type == AdobePremierePro; }
bool isPyramix() const noexcept { return type == MergingPyramix; }
bool isReceptor() const noexcept { return type == MuseReceptorGeneric; }
bool isReaper() const noexcept { return type == Reaper; } bool isReaper() const noexcept { return type == Reaper; }
bool isSamplitude() const noexcept { return type == MagixSamplitude; }
bool isSonar() const noexcept { return type == CakewalkSonar8 || type == CakewalkSonarGeneric; }
bool isSteinbergTestHost() const noexcept{ return type == SteinbergTestHost; }
bool isSteinberg() const noexcept { return isCubase() || isNuendo() || isWavelab() || isSteinbergTestHost(); }
bool isStudioOne() const noexcept { return type == StudioOne; } bool isStudioOne() const noexcept { return type == StudioOne; }
bool isPyramix() const noexcept { return type == MergingPyramix; } bool isTracktion() const noexcept { return type == Tracktion3 || type == TracktionGeneric; }
bool isVBVSTScanner() const noexcept { return type == VBVSTScanner; } bool isVBVSTScanner() const noexcept { return type == VBVSTScanner; }
bool isWaveBurner() const noexcept { return type == WaveBurner; }
bool isWavelab() const noexcept { return isWavelabLegacy() || type == SteinbergWavelab7 || type == SteinbergWavelab8 || type == SteinbergWavelabGeneric; }
bool isWavelabLegacy() const noexcept { return type == SteinbergWavelab5 || type == SteinbergWavelab6; }
//============================================================================== //==============================================================================
const char* getHostDescription() const noexcept const char* getHostDescription() const noexcept
@ -105,14 +111,18 @@ public:
case AbletonLive7: return "Ableton Live 7"; case AbletonLive7: return "Ableton Live 7";
case AbletonLive8: return "Ableton Live 8"; case AbletonLive8: return "Ableton Live 8";
case AbletonLiveGeneric: return "Ableton Live"; case AbletonLiveGeneric: return "Ableton Live";
case AdobeAudition: return "Adobe Audition";
case AdobePremierePro: return "Adobe Premiere"; case AdobePremierePro: return "Adobe Premiere";
case AppleLogic: return "Apple Logic"; case AppleLogic: return "Apple Logic";
case CakewalkSonar8: return "Cakewalk Sonar 8"; case CakewalkSonar8: return "Cakewalk Sonar 8";
case CakewalkSonarGeneric: return "Cakewalk Sonar"; case CakewalkSonarGeneric: return "Cakewalk Sonar";
case DigidesignProTools: return "ProTools"; case DigidesignProTools: return "ProTools";
case DigitalPerformer: return "DigitalPerformer";
case FruityLoops: return "FruityLoops";
case MagixSamplitude: return "Magix Samplitude";
case MergingPyramix: return "Pyramix";
case MuseReceptorGeneric: return "Muse Receptor";
case Reaper: return "Reaper"; case Reaper: return "Reaper";
case Tracktion3: return "Tracktion 3";
case TracktionGeneric: return "Tracktion";
case SteinbergCubase4: return "Steinberg Cubase 4"; case SteinbergCubase4: return "Steinberg Cubase 4";
case SteinbergCubase5: return "Steinberg Cubase 5"; case SteinbergCubase5: return "Steinberg Cubase 5";
case SteinbergCubase5Bridged: return "Steinberg Cubase 5 Bridged"; case SteinbergCubase5Bridged: return "Steinberg Cubase 5 Bridged";
@ -128,14 +138,12 @@ public:
case SteinbergWavelab7: return "Steinberg Wavelab 7"; case SteinbergWavelab7: return "Steinberg Wavelab 7";
case SteinbergWavelab8: return "Steinberg Wavelab 8"; case SteinbergWavelab8: return "Steinberg Wavelab 8";
case SteinbergWavelabGeneric: return "Steinberg Wavelab"; case SteinbergWavelabGeneric: return "Steinberg Wavelab";
case MuseReceptorGeneric: return "Muse Receptor"; case SteinbergTestHost: return "Steinberg TestHost";
case MagixSamplitude: return "Magix Samplitude";
case FruityLoops: return "FruityLoops";
case WaveBurner: return "WaveBurner";
case DigitalPerformer: return "DigitalPerformer";
case StudioOne: return "Studio One"; case StudioOne: return "Studio One";
case MergingPyramix: return "Pyramix"; case Tracktion3: return "Tracktion 3";
case TracktionGeneric: return "Tracktion";
case VBVSTScanner: return "VBVSTScanner"; case VBVSTScanner: return "VBVSTScanner";
case WaveBurner: return "WaveBurner";
default: break; default: break;
} }
@ -155,7 +163,7 @@ private:
const String hostPath (getHostPath()); const String hostPath (getHostPath());
const String hostFilename (File (hostPath).getFileName()); const String hostFilename (File (hostPath).getFileName());
#if JUCE_MAC #if JUCE_MAC
if (hostPath.containsIgnoreCase ("Live 6.")) return AbletonLive6; if (hostPath.containsIgnoreCase ("Live 6.")) return AbletonLive6;
if (hostPath.containsIgnoreCase ("Live 7.")) return AbletonLive7; if (hostPath.containsIgnoreCase ("Live 7.")) return AbletonLive7;
if (hostPath.containsIgnoreCase ("Live 8.")) return AbletonLive8; if (hostPath.containsIgnoreCase ("Live 8.")) return AbletonLive8;
@ -182,11 +190,12 @@ private:
if (hostPath.containsIgnoreCase ("Tracktion 3")) return Tracktion3; if (hostPath.containsIgnoreCase ("Tracktion 3")) return Tracktion3;
if (hostFilename.containsIgnoreCase ("Tracktion")) return TracktionGeneric; if (hostFilename.containsIgnoreCase ("Tracktion")) return TracktionGeneric;
#elif JUCE_WINDOWS #elif JUCE_WINDOWS
if (hostFilename.containsIgnoreCase ("Live 6.")) return AbletonLive6; if (hostFilename.containsIgnoreCase ("Live 6.")) return AbletonLive6;
if (hostFilename.containsIgnoreCase ("Live 7.")) return AbletonLive7; if (hostFilename.containsIgnoreCase ("Live 7.")) return AbletonLive7;
if (hostFilename.containsIgnoreCase ("Live 8.")) return AbletonLive8; if (hostFilename.containsIgnoreCase ("Live 8.")) return AbletonLive8;
if (hostFilename.containsIgnoreCase ("Live ")) return AbletonLiveGeneric; if (hostFilename.containsIgnoreCase ("Live ")) return AbletonLiveGeneric;
if (hostFilename.containsIgnoreCase ("Audition")) return AdobeAudition;
if (hostFilename.containsIgnoreCase ("Adobe Premiere")) return AdobePremierePro; if (hostFilename.containsIgnoreCase ("Adobe Premiere")) return AdobePremierePro;
if (hostFilename.containsIgnoreCase ("ProTools")) return DigidesignProTools; if (hostFilename.containsIgnoreCase ("ProTools")) return DigidesignProTools;
if (hostPath.containsIgnoreCase ("SONAR 8")) return CakewalkSonar8; if (hostPath.containsIgnoreCase ("SONAR 8")) return CakewalkSonar8;
@ -207,6 +216,7 @@ private:
if (hostPath.containsIgnoreCase ("Wavelab 8")) return SteinbergWavelab8; if (hostPath.containsIgnoreCase ("Wavelab 8")) return SteinbergWavelab8;
if (hostPath.containsIgnoreCase ("Nuendo")) return SteinbergNuendoGeneric; if (hostPath.containsIgnoreCase ("Nuendo")) return SteinbergNuendoGeneric;
if (hostFilename.containsIgnoreCase ("Wavelab")) return SteinbergWavelabGeneric; if (hostFilename.containsIgnoreCase ("Wavelab")) return SteinbergWavelabGeneric;
if (hostFilename.containsIgnoreCase ("TestHost")) return SteinbergTestHost;
if (hostFilename.containsIgnoreCase ("rm-host")) return MuseReceptorGeneric; if (hostFilename.containsIgnoreCase ("rm-host")) return MuseReceptorGeneric;
if (hostFilename.startsWith ("FL")) return FruityLoops; if (hostFilename.startsWith ("FL")) return FruityLoops;
if (hostPath.containsIgnoreCase ("Studio One")) return StudioOne; if (hostPath.containsIgnoreCase ("Studio One")) return StudioOne;
@ -216,7 +226,8 @@ private:
if (hostFilename.startsWithIgnoreCase ("Sam")) return MagixSamplitude; if (hostFilename.startsWithIgnoreCase ("Sam")) return MagixSamplitude;
#elif JUCE_LINUX #elif JUCE_LINUX
jassertfalse // not yet done! if (hostFilename.containsIgnoreCase ("Ardour")) return Ardour;
#else #else
#error #error
#endif #endif

@ -478,8 +478,8 @@ public:
resetBusses(); resetBusses();
prepared = (AudioUnitInitialize (audioUnit) == noErr); jassert (! prepared);
jassert (prepared); initialiseAudioUnit();
} }
} }
@ -499,6 +499,14 @@ public:
incomingMidi.clear(); incomingMidi.clear();
} }
bool initialiseAudioUnit()
{
if (! prepared)
prepared = (AudioUnitInitialize (audioUnit) == noErr);
return prepared;
}
void resetBusses() void resetBusses()
{ {
for (int i = 0; i < numInputBusses; ++i) AudioUnitReset (audioUnit, kAudioUnitScope_Input, i); for (int i = 0; i < numInputBusses; ++i) AudioUnitReset (audioUnit, kAudioUnitScope_Input, i);
@ -653,8 +661,13 @@ public:
void sendAllParametersChangedEvents() void sendAllParametersChangedEvents()
{ {
for (int i = 0; i < parameters.size(); ++i) jassert (audioUnit != nullptr);
sendParameterChangeEvent (i);
AudioUnitParameter param;
param.mAudioUnit = audioUnit;
param.mParameterID = kAUParameterListener_AnyParameter;
AUParameterListenerNotify (nullptr, nullptr, &param);
} }
const String getParameterName (int index) override const String getParameterName (int index) override
@ -799,10 +812,14 @@ public:
if (propertyList != 0) if (propertyList != 0)
{ {
initialiseAudioUnit();
AudioUnitSetProperty (audioUnit, kAudioUnitProperty_ClassInfo, kAudioUnitScope_Global, AudioUnitSetProperty (audioUnit, kAudioUnitProperty_ClassInfo, kAudioUnitScope_Global,
0, &propertyList, sizeof (propertyList)); 0, &propertyList, sizeof (propertyList));
sendAllParametersChangedEvents(); sendAllParametersChangedEvents();
CFRelease (propertyList);
} }
} }
@ -1295,8 +1312,7 @@ private:
}; };
//============================================================================== //==============================================================================
class AudioUnitPluginWindowCocoa : public AudioProcessorEditor, class AudioUnitPluginWindowCocoa : public AudioProcessorEditor
public Timer
{ {
public: public:
AudioUnitPluginWindowCocoa (AudioUnitPluginInstance& p, bool createGenericViewIfNeeded) AudioUnitPluginWindowCocoa (AudioUnitPluginInstance& p, bool createGenericViewIfNeeded)
@ -1335,30 +1351,25 @@ public:
wrapper.setSize (getWidth(), getHeight()); wrapper.setSize (getWidth(), getHeight());
} }
void timerCallback() override
{
wrapper.resizeToFitView();
startTimer (jmin (713, getTimerInterval() + 51));
}
void childBoundsChanged (Component*) override void childBoundsChanged (Component*) override
{ {
setSize (wrapper.getWidth(), wrapper.getHeight()); setSize (wrapper.getWidth(), wrapper.getHeight());
startTimer (70);
} }
private: private:
AudioUnitPluginInstance& plugin; AudioUnitPluginInstance& plugin;
NSViewComponent wrapper;
AutoResizingNSViewComponent wrapper;
bool createView (const bool createGenericViewIfNeeded) bool createView (const bool createGenericViewIfNeeded)
{ {
if (! plugin.initialiseAudioUnit())
return false;
NSView* pluginView = nil; NSView* pluginView = nil;
UInt32 dataSize = 0; UInt32 dataSize = 0;
Boolean isWritable = false; Boolean isWritable = false;
AudioUnitInitialize (plugin.audioUnit);
if (AudioUnitGetPropertyInfo (plugin.audioUnit, kAudioUnitProperty_CocoaUI, kAudioUnitScope_Global, if (AudioUnitGetPropertyInfo (plugin.audioUnit, kAudioUnitProperty_CocoaUI, kAudioUnitScope_Global,
0, &dataSize, &isWritable) == noErr 0, &dataSize, &isWritable) == noErr
&& dataSize != 0 && dataSize != 0
@ -1410,10 +1421,7 @@ private:
wrapper.setView (pluginView); wrapper.setView (pluginView);
if (pluginView != nil) if (pluginView != nil)
{ wrapper.resizeToFitView();
timerCallback();
startTimer (70);
}
return pluginView != nil; return pluginView != nil;
} }
@ -1528,16 +1536,10 @@ private:
Float32Point pos = { 0, 0 }; Float32Point pos = { 0, 0 };
Float32Point size = { 250, 200 }; Float32Point size = { 250, 200 };
HIViewRef pluginView = 0; HIViewRef pluginView = 0;
AudioUnitCarbonViewCreate (carbonView, AudioUnitCarbonViewCreate (carbonView, owner.getAudioUnit(), windowRef, rootView,
owner.getAudioUnit(), &pos, &size, (ControlRef*) &pluginView);
windowRef,
rootView,
&pos,
&size,
(ControlRef*) &pluginView);
return pluginView; return pluginView;
} }

@ -26,96 +26,20 @@
} // namespace juce } // namespace juce
// Wow, those VST guys really don't worry too much about compiler warnings. #if JucePlugin_Build_VST3
#if JUCE_MSVC #undef JUCE_VST3HEADERS_INCLUDE_HEADERS_ONLY
#pragma warning (disable: 4505) #define JUCE_VST3HEADERS_INCLUDE_HEADERS_ONLY 1
#pragma warning (push, 0)
#pragma warning (disable: 4702)
#elif JUCE_CLANG
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
#pragma clang diagnostic ignored "-Wreorder"
#pragma clang diagnostic ignored "-Wunsequenced"
#pragma clang diagnostic ignored "-Wint-to-pointer-cast"
#pragma clang diagnostic ignored "-Wunused-parameter"
#pragma clang diagnostic ignored "-Wconversion"
#pragma clang diagnostic ignored "-Woverloaded-virtual"
#pragma clang diagnostic ignored "-Wshadow"
#endif #endif
/* These files come with the Steinberg VST3 SDK - to get them, you'll need to #include "juce_VST3Headers.h"
visit the Steinberg website and agree to whatever is currently required to
get them.
Then, you'll need to make sure your include path contains your "VST SDK3" #undef JUCE_VST3HEADERS_INCLUDE_HEADERS_ONLY
directory (or whatever you've named it on your machine). The introjucer has
a special box for setting this path.
*/
#include <base/source/baseiids.cpp>
#include <base/source/fatomic.cpp>
#include <base/source/fbuffer.cpp>
#include <base/source/fdebug.cpp>
#include <base/source/fobject.cpp>
#include <base/source/frect.cpp>
#include <base/source/fstreamer.cpp>
#include <base/source/fstring.cpp>
#include <base/source/fthread.cpp>
#include <base/source/updatehandler.cpp>
#include <pluginterfaces/base/conststringtable.cpp>
#include <pluginterfaces/base/funknown.cpp>
#include <pluginterfaces/base/ustring.cpp>
#include <public.sdk/source/main/pluginfactoryvst3.cpp>
#include <public.sdk/source/common/memorystream.cpp>
#include <public.sdk/source/common/pluginview.cpp>
#include <public.sdk/source/vst/vstbus.cpp>
#include <public.sdk/source/vst/vstinitiids.cpp>
#include <public.sdk/source/vst/vstcomponent.cpp>
#include <public.sdk/source/vst/vstcomponentbase.cpp>
#include <public.sdk/source/vst/vstparameters.cpp>
#include <public.sdk/source/vst/vstsinglecomponenteffect.cpp>
#include <public.sdk/source/vst/hosting/hostclasses.cpp>
#if JUCE_MSVC
#pragma warning (pop)
#elif JUCE_CLANG
#pragma clang diagnostic pop
#endif
#undef ASSERT
#undef WARNING
#undef PRINTSYSERROR
#undef DEBUGSTR
#undef DBPRT0
#undef DBPRT1
#undef DBPRT2
#undef DBPRT3
#undef DBPRT4
#undef DBPRT5
#undef calloc
#undef free
#undef malloc
#undef realloc
#undef NEW
#undef NEWVEC
#undef VERIFY
#undef VERIFY_IS
#undef VERIFY_NOT
#undef META_CREATE_FUNC
#undef CLASS_CREATE_FUNC
#undef SINGLE_CREATE_FUNC
#undef _META_CLASS
#undef _META_CLASS_IFACE
#undef _META_CLASS_SINGLE
#undef META_CLASS
#undef META_CLASS_IFACE
#undef META_CLASS_SINGLE
#undef OBJ_METHODS
#undef SINGLETON
#undef QUERY_INTERFACE
namespace juce namespace juce
{ {
#include "juce_VST3Common.h"
using namespace Steinberg; using namespace Steinberg;
//============================================================================== //==============================================================================
@ -157,71 +81,6 @@ static int warnOnFailure (int result)
#define warnOnFailure(x) x #define warnOnFailure(x) x
#endif #endif
//==============================================================================
template <class ObjectType>
class ComSmartPtr
{
public:
ComSmartPtr() noexcept : source (nullptr) {}
ComSmartPtr (ObjectType* object) noexcept : source (object) { if (source != nullptr) source->addRef(); }
ComSmartPtr (const ComSmartPtr& other) noexcept : source (other.source) { if (source != nullptr) source->addRef(); }
~ComSmartPtr() { if (source != nullptr) source->release(); }
operator ObjectType*() const noexcept { return source; }
ObjectType* get() const noexcept { return source; }
ObjectType& operator*() const noexcept { return *source; }
ObjectType* operator->() const noexcept { return source; }
ComSmartPtr& operator= (const ComSmartPtr& other) { return operator= (other.source); }
ComSmartPtr& operator= (ObjectType* const newObjectToTakePossessionOf)
{
ComSmartPtr p (newObjectToTakePossessionOf);
std::swap (p.source, source);
return *this;
}
bool operator== (ObjectType* const other) noexcept { return source == other; }
bool operator!= (ObjectType* const other) noexcept { return source != other; }
bool loadFrom (FUnknown* o)
{
*this = nullptr;
return o != nullptr && o->queryInterface (ObjectType::iid, (void**) &source) == kResultOk;
}
bool loadFrom (IPluginFactory* factory, const TUID& uuid)
{
jassert (factory != nullptr);
*this = nullptr;
return factory->createInstance (uuid, ObjectType::iid, (void**) &source) == kResultOk;
}
private:
ObjectType* source;
};
//==============================================================================
#define JUCE_DECLARE_VST3_COM_REF_METHODS \
Steinberg::uint32 JUCE_CALLTYPE addRef() { return (Steinberg::uint32) ++refCount; } \
Steinberg::uint32 JUCE_CALLTYPE release() { const int r = --refCount; if (r == 0) delete this; return (Steinberg::uint32) r; }
#define JUCE_DECLARE_VST3_COM_QUERY_METHODS \
tresult PLUGIN_API JUCE_CALLTYPE queryInterface (const TUID, void** obj) \
{\
jassertfalse; \
*obj = nullptr; \
return kNotImplemented; \
}
//==============================================================================
static String toString (const char8* string) noexcept { return String (string); }
static String toString (const char16* string) noexcept { return String (CharPointer_UTF16 ((CharPointer_UTF16::CharType*) string)); }
// NB: The casts are handled by a Steinberg::UString operator
static String toString (const UString128& string) noexcept { return toString (static_cast<const char16*> (string)); }
static String toString (const UString256& string) noexcept { return toString (static_cast<const char16*> (string)); }
//============================================================================== //==============================================================================
static int getHashForTUID (const TUID& tuid) noexcept static int getHashForTUID (const TUID& tuid) noexcept
{ {
@ -299,9 +158,10 @@ static int getNumSingleDirectionChannelsFor (Vst::IComponent* component,
return numChannels; return numChannels;
} }
static void activateAllBussesOfType (Vst::IComponent* component, static void setStateForAllBussesOfType (Vst::IComponent* component,
bool activateInputs, bool state,
bool activateAudioChannels) bool activateInputs,
bool activateAudioChannels)
{ {
jassert (component != nullptr); jassert (component != nullptr);
@ -310,7 +170,7 @@ static void activateAllBussesOfType (Vst::IComponent* component,
const Steinberg::int32 numBuses = component->getBusCount (mediaType, direction); const Steinberg::int32 numBuses = component->getBusCount (mediaType, direction);
for (Steinberg::int32 i = numBuses; --i >= 0;) for (Steinberg::int32 i = numBuses; --i >= 0;)
warnOnFailure (component->activateBus (mediaType, direction, i, true)); warnOnFailure (component->activateBus (mediaType, direction, i, state));
} }
//============================================================================== //==============================================================================
@ -457,42 +317,6 @@ static Vst::SpeakerArrangement getSpeakerArrangementFrom (const String& string)
return Vst::SpeakerArr::getSpeakerArrangementFromString (string.toUTF8()); return Vst::SpeakerArr::getSpeakerArrangementFromString (string.toUTF8());
} }
/**
@note There can only be 1 arrangement per channel count. (i.e.: 4 channels == k31Cine OR k40Cine)
*/
static void fillWithCorrespondingSpeakerArrangements (Array<Vst::SpeakerArrangement>& destination,
int numChannels)
{
using namespace Vst::SpeakerArr;
destination.clearQuick();
if (numChannels <= 0)
{
destination.add (kEmpty);
return;
}
/*
The order of the arrangement checks must be descending, since most plugins test for
the first arrangement to match their number of specified channels.
*/
if (numChannels >= 14) destination.add (k131);
if (numChannels >= 13) destination.add (k130);
if (numChannels >= 12) destination.add (k111);
if (numChannels >= 11) destination.add (k101);
if (numChannels >= 10) destination.add (k91);
if (numChannels >= 9) destination.add (k90);
if (numChannels >= 8) destination.add (k71CineFullFront);
if (numChannels >= 7) destination.add (k61Cine);
if (numChannels >= 6) destination.add (k51);
if (numChannels >= 5) destination.add (k50);
if (numChannels >= 4) destination.add (k31Cine);
if (numChannels >= 3) destination.add (k30Cine);
if (numChannels >= 2) destination.add (kStereo);
if (numChannels >= 1) destination.add (kMono);
}
//============================================================================== //==============================================================================
static StringArray getPluginEffectCategories() static StringArray getPluginEffectCategories()
{ {
@ -528,170 +352,6 @@ static StringArray getPluginInstrumentCategories()
return StringArray (categories); return StringArray (categories);
} }
//==============================================================================
class MidiEventList : public Vst::IEventList
{
public:
MidiEventList() {}
virtual ~MidiEventList() {}
JUCE_DECLARE_VST3_COM_REF_METHODS
JUCE_DECLARE_VST3_COM_QUERY_METHODS
//==============================================================================
void clear()
{
events.clearQuick();
}
Steinberg::int32 PLUGIN_API getEventCount() override
{
return (Steinberg::int32) events.size();
}
// NB: This has to cope with out-of-range indexes from some plugins.
tresult PLUGIN_API getEvent (Steinberg::int32 index, Vst::Event& e) override
{
if (isPositiveAndBelow ((int) index, events.size()))
{
e = events.getReference ((int) index);
return kResultTrue;
}
return kResultFalse;
}
tresult PLUGIN_API addEvent (Vst::Event& e) override
{
events.add (e);
return kResultTrue;
}
//==============================================================================
static void toMidiBuffer (MidiBuffer& result, Vst::IEventList& eventList)
{
using namespace Vst;
for (Steinberg::int32 i = 0; i < eventList.getEventCount(); ++i)
{
Event e;
if (eventList.getEvent (i, e) == kResultOk)
{
switch (e.type)
{
case Event::kNoteOnEvent:
result.addEvent (MidiMessage::noteOn (createSafeChannel (e.noteOn.channel),
createSafeNote (e.noteOn.pitch),
(uint8) denormaliseToMidiValue (e.noteOn.velocity)),
e.sampleOffset);
break;
case Event::kNoteOffEvent:
result.addEvent (MidiMessage::noteOff (createSafeChannel (e.noteOff.channel),
createSafeNote (e.noteOff.pitch),
(uint8) denormaliseToMidiValue (e.noteOff.velocity)),
e.sampleOffset);
break;
case Event::kPolyPressureEvent:
result.addEvent (MidiMessage::aftertouchChange (createSafeChannel (e.polyPressure.channel),
createSafeNote (e.polyPressure.pitch),
denormaliseToMidiValue (e.polyPressure.pressure)),
e.sampleOffset);
break;
case Event::kDataEvent:
result.addEvent (MidiMessage::createSysExMessage (e.data.bytes, e.data.size),
e.sampleOffset);
break;
default:
break;
}
}
}
}
static void toEventList (Vst::IEventList& result, MidiBuffer& midiBuffer)
{
using namespace Vst;
MidiBuffer::Iterator iterator (midiBuffer);
MidiMessage msg;
int midiEventPosition = 0;
enum { maxNumEvents = 2048 }; // Steinberg's Host Checker states no more than 2048 events are allowed at once
int numEvents = 0;
while (iterator.getNextEvent (msg, midiEventPosition))
{
if (++numEvents > maxNumEvents)
break;
Event e = { 0 };
if (msg.isNoteOn())
{
e.type = Event::kNoteOnEvent;
e.noteOn.channel = createSafeChannel (msg.getChannel());
e.noteOn.pitch = createSafeNote (msg.getNoteNumber());
e.noteOn.velocity = normaliseMidiValue (msg.getVelocity());
e.noteOn.length = 0;
e.noteOn.tuning = 0.0f;
e.noteOn.noteId = -1;
}
else if (msg.isNoteOff())
{
e.type = Event::kNoteOffEvent;
e.noteOff.channel = createSafeChannel (msg.getChannel());
e.noteOff.pitch = createSafeNote (msg.getNoteNumber());
e.noteOff.velocity = normaliseMidiValue (msg.getVelocity());
e.noteOff.tuning = 0.0f;
e.noteOff.noteId = -1;
}
else if (msg.isSysEx())
{
e.type = Event::kDataEvent;
e.data.bytes = msg.getSysExData();
e.data.size = msg.getSysExDataSize();
e.data.type = DataEvent::kMidiSysEx;
}
else if (msg.isAftertouch())
{
e.type = Event::kPolyPressureEvent;
e.polyPressure.channel = createSafeChannel (msg.getChannel());
e.polyPressure.pitch = createSafeNote (msg.getNoteNumber());
e.polyPressure.pressure = normaliseMidiValue (msg.getAfterTouchValue());
}
else
{
continue;
}
e.busIndex = 0;
e.sampleOffset = midiEventPosition;
result.addEvent (e);
}
}
private:
Array<Vst::Event, CriticalSection> events;
Atomic<int32> refCount;
static Steinberg::int16 createSafeChannel (int channel) noexcept { return (Steinberg::int16) jlimit (0, 15, channel - 1); }
static int createSafeChannel (Steinberg::int16 channel) noexcept { return (int) jlimit (1, 16, channel + 1); }
static Steinberg::int16 createSafeNote (int note) noexcept { return (Steinberg::int16) jlimit (0, 127, note); }
static int createSafeNote (Steinberg::int16 note) noexcept { return jlimit (0, 127, (int) note); }
static float normaliseMidiValue (int value) noexcept { return jlimit (0.0f, 1.0f, (float) value / 127.0f); }
static int denormaliseToMidiValue (float value) noexcept { return roundToInt (jlimit (0.0f, 127.0f, value * 127.0f)); }
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MidiEventList)
};
//============================================================================== //==============================================================================
class VST3PluginInstance; class VST3PluginInstance;
@ -753,7 +413,6 @@ public:
//============================================================================== //==============================================================================
tresult PLUGIN_API setDirty (TBool) override tresult PLUGIN_API setDirty (TBool) override
{ {
jassertfalse;
return kResultFalse; return kResultFalse;
} }
@ -873,14 +532,6 @@ public:
return kResultOk; return kResultOk;
} }
#define TEST_FOR_AND_RETURN_IF_VALID(ClassType) \
if (doIdsMatch (iid, ClassType::iid)) \
{ \
addRef(); \
*obj = dynamic_cast<ClassType*> (this); \
return kResultOk; \
}
TEST_FOR_AND_RETURN_IF_VALID (Vst::IComponentHandler) TEST_FOR_AND_RETURN_IF_VALID (Vst::IComponentHandler)
TEST_FOR_AND_RETURN_IF_VALID (Vst::IComponentHandler2) TEST_FOR_AND_RETURN_IF_VALID (Vst::IComponentHandler2)
TEST_FOR_AND_RETURN_IF_VALID (Vst::IComponentHandler3) TEST_FOR_AND_RETURN_IF_VALID (Vst::IComponentHandler3)
@ -888,7 +539,6 @@ public:
TEST_FOR_AND_RETURN_IF_VALID (Vst::IHostApplication) TEST_FOR_AND_RETURN_IF_VALID (Vst::IHostApplication)
TEST_FOR_AND_RETURN_IF_VALID (Vst::IParamValueQueue) TEST_FOR_AND_RETURN_IF_VALID (Vst::IParamValueQueue)
TEST_FOR_AND_RETURN_IF_VALID (Vst::IUnitHandler) TEST_FOR_AND_RETURN_IF_VALID (Vst::IUnitHandler)
#undef TEST_FOR_AND_RETURN_IF_VALID
*obj = nullptr; *obj = nullptr;
return kNotImplemented; return kNotImplemented;
@ -1139,6 +789,7 @@ public:
Result result (Result::ok()); Result result (Result::ok());
const Steinberg::int32 numClasses = factory->countClasses(); const Steinberg::int32 numClasses = factory->countClasses();
for (Steinberg::int32 i = 0; i < numClasses; ++i) for (Steinberg::int32 i = 0; i < numClasses; ++i)
{ {
PClassInfo info; PClassInfo info;
@ -1174,7 +825,7 @@ public:
foundNames.add (name); foundNames.add (name);
int numInputs = 0, numOutputs = 0; PluginDescription desc;
{ {
ComSmartPtr<Vst::IComponent> component; ComSmartPtr<Vst::IComponent> component;
@ -1183,8 +834,11 @@ public:
{ {
if (component->initialize (vst3HostContext->getFUnknown()) == kResultOk) if (component->initialize (vst3HostContext->getFUnknown()) == kResultOk)
{ {
numInputs = getNumSingleDirectionChannelsFor (component, true, true); const int numInputs = getNumSingleDirectionChannelsFor (component, true, true);
numOutputs = getNumSingleDirectionChannelsFor (component, false, true); const int numOutputs = getNumSingleDirectionChannelsFor (component, false, true);
createPluginDescription (desc, file, companyName, name,
info, info2, infoW, numInputs, numOutputs);
component->terminate(); component->terminate();
} }
@ -1193,13 +847,12 @@ public:
jassertfalse; jassertfalse;
} }
} }
else
{
jassertfalse;
}
} }
PluginDescription desc;
createPluginDescription (desc, file, companyName, name,
info, info2, infoW, numInputs, numOutputs);
result = performOnDescription (desc); result = performOnDescription (desc);
if (result.failed()) if (result.failed())
@ -1265,6 +918,7 @@ private:
struct DLLHandle struct DLLHandle
{ {
DLLHandle (const String& modulePath) DLLHandle (const String& modulePath)
: factory (nullptr)
{ {
if (modulePath.trim().isNotEmpty()) if (modulePath.trim().isNotEmpty())
open (modulePath); open (modulePath);
@ -1278,6 +932,7 @@ struct DLLHandle
if (ExitModuleFn exitFn = (ExitModuleFn) getFunction ("ExitDll")) if (ExitModuleFn exitFn = (ExitModuleFn) getFunction ("ExitDll"))
exitFn(); exitFn();
releaseFactory();
library.close(); library.close();
#else #else
@ -1286,6 +941,8 @@ struct DLLHandle
if (ExitModuleFn exitFn = (ExitModuleFn) getFunction ("bundleExit")) if (ExitModuleFn exitFn = (ExitModuleFn) getFunction ("bundleExit"))
exitFn(); exitFn();
releaseFactory();
CFRelease (bundleRef); CFRelease (bundleRef);
bundleRef = nullptr; bundleRef = nullptr;
} }
@ -1303,12 +960,22 @@ struct DLLHandle
#endif #endif
} }
/** @note The factory should begin with a refCount of 1,
so don't increment the reference count
(ie: don't use a ComSmartPtr in here)!
Its lifetime will be handled by this DllHandle,
when such will be destroyed.
@see releaseFactory
*/
IPluginFactory* JUCE_CALLTYPE getPluginFactory() IPluginFactory* JUCE_CALLTYPE getPluginFactory()
{ {
if (GetFactoryProc proc = (GetFactoryProc) getFunction ("GetPluginFactory")) if (factory == nullptr)
return proc(); if (GetFactoryProc proc = (GetFactoryProc) getFunction ("GetPluginFactory"))
factory = proc();
return nullptr; jassert (factory != nullptr); // The plugin NEEDS to provide a factory to be able to be called a VST3!
return factory;
} }
void* getFunction (const char* functionName) void* getFunction (const char* functionName)
@ -1327,6 +994,14 @@ struct DLLHandle
} }
private: private:
IPluginFactory* factory;
void releaseFactory()
{
if (factory != nullptr)
factory->release();
}
#if JUCE_WINDOWS #if JUCE_WINDOWS
DynamicLibrary library; DynamicLibrary library;
@ -1364,9 +1039,9 @@ private:
bundleRef = CFBundleCreate (kCFAllocatorDefault, url); bundleRef = CFBundleCreate (kCFAllocatorDefault, url);
CFRelease (url); CFRelease (url);
if (bundleRef != 0) if (bundleRef != nullptr)
{ {
CFErrorRef error = 0; CFErrorRef error = nullptr;
if (CFBundleLoadExecutableAndReturnError (bundleRef, &error)) if (CFBundleLoadExecutableAndReturnError (bundleRef, &error))
{ {
@ -1383,7 +1058,7 @@ private:
} }
} }
if (error != 0) if (error != nullptr)
{ {
if (CFStringRef failureMessage = CFErrorCopyFailureReason (error)) if (CFStringRef failureMessage = CFErrorCopyFailureReason (error))
{ {
@ -1395,7 +1070,7 @@ private:
} }
CFRelease (bundleRef); CFRelease (bundleRef);
bundleRef = 0; bundleRef = nullptr;
} }
} }
@ -1443,6 +1118,7 @@ public:
return result.wasOk(); return result.wasOk();
} }
jassertfalse;
return false; return false;
} }
@ -1493,15 +1169,18 @@ private:
ComSmartPtr<IPluginFactory> pluginFactory (dllHandle->getPluginFactory()); ComSmartPtr<IPluginFactory> pluginFactory (dllHandle->getPluginFactory());
ComSmartPtr<VST3HostContext> host (new VST3HostContext (nullptr)); if (pluginFactory != nullptr)
MatchingDescriptionFinder finder (host, pluginFactory, description); {
ComSmartPtr<VST3HostContext> host (new VST3HostContext (nullptr));
MatchingDescriptionFinder finder (host, pluginFactory, description);
const Result result (finder.findDescriptionsAndPerform (f)); const Result result (finder.findDescriptionsAndPerform (f));
if (result.getErrorMessage() == MatchingDescriptionFinder::getSuccessString()) if (result.getErrorMessage() == MatchingDescriptionFinder::getSuccessString())
{ {
name = description.name; name = description.name;
return true; return true;
}
} }
return false; return false;
@ -1527,11 +1206,11 @@ public:
setOpaque (true); setOpaque (true);
setVisible (true); setVisible (true);
view->setFrame (this);
ViewRect rect; ViewRect rect;
warnOnFailure (view->getSize (&rect)); warnOnFailure (view->getSize (&rect));
resizeWithRect (*this, rect); resizeWithRect (*this, rect);
view->setFrame (this); // Done after to avoid recursive calls from plugins...
} }
~VST3PluginWindow() ~VST3PluginWindow()
@ -1541,8 +1220,9 @@ public:
#if JUCE_MAC #if JUCE_MAC
dummyComponent.setView (nullptr); dummyComponent.setView (nullptr);
[pluginHandle release];
#endif #endif
view = nullptr;
} }
JUCE_DECLARE_VST3_COM_REF_METHODS JUCE_DECLARE_VST3_COM_REF_METHODS
@ -1604,7 +1284,8 @@ public:
dummyComponent.setBounds (0, 0, (int) rect.getWidth(), (int) rect.getHeight()); dummyComponent.setBounds (0, 0, (int) rect.getWidth(), (int) rect.getHeight());
#endif #endif
Desktop::getInstance().getMainMouseSource().forceMouseCursorUpdate(); // Some plugins don't update their cursor correctly when mousing out the window // Some plugins don't update their cursor correctly when mousing out the window
Desktop::getInstance().getMainMouseSource().forceMouseCursorUpdate();
recursiveResize = false; recursiveResize = false;
} }
@ -1655,20 +1336,20 @@ private:
ScopedPointer<ComponentPeer> peer; ScopedPointer<ComponentPeer> peer;
typedef HWND HandleFormat; typedef HWND HandleFormat;
#elif JUCE_MAC #elif JUCE_MAC
NSViewComponent dummyComponent; AutoResizingNSViewComponentWithParent dummyComponent;
typedef NSView* HandleFormat; typedef NSView* HandleFormat;
#else #else
Component dummyComponent; Component dummyComponent;
typedef void* HandleFormat; typedef void* HandleFormat;
#endif #endif
HandleFormat pluginHandle; //< Don't delete this HandleFormat pluginHandle;
bool recursiveResize; bool recursiveResize;
//============================================================================== //==============================================================================
static void resizeWithRect (Component& comp, const ViewRect& rect) static void resizeWithRect (Component& comp, const ViewRect& rect)
{ {
comp.setBounds (rect.left, rect.top, comp.setBounds ((int) rect.left, (int) rect.top,
jmax (10, std::abs ((int) rect.getWidth())), jmax (10, std::abs ((int) rect.getWidth())),
jmax (10, std::abs ((int) rect.getHeight()))); jmax (10, std::abs ((int) rect.getHeight())));
} }
@ -1688,17 +1369,12 @@ private:
#elif JUCE_MAC #elif JUCE_MAC
dummyComponent.setBounds (getBounds().withZeroOrigin()); dummyComponent.setBounds (getBounds().withZeroOrigin());
addAndMakeVisible (dummyComponent); addAndMakeVisible (dummyComponent);
pluginHandle = [[NSView alloc] init]; pluginHandle = (NSView*) dummyComponent.getView();
dummyComponent.setView (pluginHandle); jassert (pluginHandle != nil);
#endif #endif
if (pluginHandle != nullptr) if (pluginHandle != nullptr)
view->attached (pluginHandle, warnOnFailure (view->attached (pluginHandle, defaultVST3WindowType));
#if JUCE_WINDOWS
kPlatformTypeHWND);
#else
kPlatformTypeNSView);
#endif
} }
} }
@ -1713,7 +1389,6 @@ public:
: module (handle), : module (handle),
numInputAudioBusses (0), numInputAudioBusses (0),
numOutputAudioBusses (0), numOutputAudioBusses (0),
resultBuffer (1, 1),
inputParameterChanges (new ParameterChangeList()), inputParameterChanges (new ParameterChangeList()),
outputParameterChanges (new ParameterChangeList()), outputParameterChanges (new ParameterChangeList()),
midiInputs (new MidiEventList()), midiInputs (new MidiEventList()),
@ -1741,6 +1416,16 @@ public:
if (isControllerInitialised) editController->terminate(); if (isControllerInitialised) editController->terminate();
if (isComponentInitialised) component->terminate(); if (isComponentInitialised) component->terminate();
//Deletion order appears to matter:
componentConnection = nullptr;
editControllerConnection = nullptr;
unitData = nullptr;
unitInfo = nullptr;
programListData = nullptr;
componentHandler2 = nullptr;
componentHandler = nullptr;
processor = nullptr;
editController2 = nullptr;
editController = nullptr; editController = nullptr;
component = nullptr; component = nullptr;
} }
@ -1763,8 +1448,8 @@ public:
if (! fetchComponentAndController (factory, factory->countClasses())) if (! fetchComponentAndController (factory, factory->countClasses()))
return false; return false;
if (warnOnFailure (editController->initialize (host->getFUnknown())) != kResultTrue) // (May return an error if the plugin combines the IComponent and IEditController implementations)
return false; editController->initialize (host->getFUnknown());
isControllerInitialised = true; isControllerInitialised = true;
editController->setComponentHandler (host); editController->setComponentHandler (host);
@ -1796,62 +1481,6 @@ public:
return module != nullptr ? module->name : String::empty; return module != nullptr ? module->name : String::empty;
} }
typedef Array<Array<float*> > BusMap;
/** Assigns a series of AudioSampleBuffer's channels to an AudioBusBuffers'
@warning For speed, does not check the channel count and offsets
according to the AudioSampleBuffer
*/
void associateBufferTo (Vst::AudioBusBuffers& vstBuffers,
BusMap& busMap,
const AudioSampleBuffer& buffer,
int numChannels, int channelStartOffset,
int sampleOffset = 0) noexcept
{
const int channelEnd = numChannels + channelStartOffset;
jassert (channelEnd >= 0 && channelEnd <= buffer.getNumChannels());
busMap.add (Array<float*>());
Array<float*>& chans = busMap.getReference (busMap.size() - 1);
for (int i = channelStartOffset; i < channelEnd; ++i)
chans.add (buffer.getSampleData (i, sampleOffset));
vstBuffers.channelBuffers32 = chans.getRawDataPointer();
vstBuffers.numChannels = numChannels;
vstBuffers.silenceFlags = 0;
}
void mapAudioSampleBufferToBusses (Array<Vst::AudioBusBuffers>& result,
AudioSampleBuffer& source,
int numBusses, bool isInput)
{
result.clearQuick();
BusMap& busMapToUse = isInput ? inputBusMap : outputBusMap;
busMapToUse.clearQuick();
int channelIndexOffset = 0;
for (int i = 0; i < numBusses; ++i)
{
Vst::SpeakerArrangement arrangement = 0;
processor->getBusArrangement (isInput ? Vst::kInput : Vst::kOutput,
(Steinberg::int32) i, arrangement);
const int numChansForBus = BigInteger ((int64) arrangement).countNumberOfSetBits();
result.add (Vst::AudioBusBuffers());
associateBufferTo (result.getReference (i), busMapToUse, source,
BigInteger ((int64) arrangement).countNumberOfSetBits(),
channelIndexOffset);
channelIndexOffset += numChansForBus;
}
}
void prepareToPlay (double sampleRate, int estimatedSamplesPerBlock) override void prepareToPlay (double sampleRate, int estimatedSamplesPerBlock) override
{ {
using namespace Vst; using namespace Vst;
@ -1868,8 +1497,6 @@ public:
setup.sampleRate = sampleRate; setup.sampleRate = sampleRate;
setup.processMode = isNonRealtime() ? kOffline : kRealtime; setup.processMode = isNonRealtime() ? kOffline : kRealtime;
resultBuffer.setSize (numOutputs, estimatedSamplesPerBlock, false, true, true);
warnOnFailure (processor->setupProcessing (setup)); warnOnFailure (processor->setupProcessing (setup));
if (! isComponentInitialised) if (! isComponentInitialised)
@ -1877,8 +1504,7 @@ public:
editController->setComponentHandler (host); editController->setComponentHandler (host);
warnOnFailure (component->setActive (true)); setStateForAllBusses (true);
warnOnFailure (processor->setProcessing (true));
Array<SpeakerArrangement> inArrangements, outArrangements; Array<SpeakerArrangement> inArrangements, outArrangements;
@ -1887,13 +1513,16 @@ public:
warnOnFailure (processor->setBusArrangements (inArrangements.getRawDataPointer(), numInputAudioBusses, warnOnFailure (processor->setBusArrangements (inArrangements.getRawDataPointer(), numInputAudioBusses,
outArrangements.getRawDataPointer(), numOutputAudioBusses)); outArrangements.getRawDataPointer(), numOutputAudioBusses));
warnOnFailure (component->setActive (true));
warnOnFailure (processor->setProcessing (true));
} }
void releaseResources() override void releaseResources() override
{ {
JUCE_TRY JUCE_TRY
{ {
resultBuffer.setSize (1, 1, false, true, true); setStateForAllBusses (false);
if (processor != nullptr) if (processor != nullptr)
processor->setProcessing (false); processor->setProcessing (false);
@ -1996,10 +1625,7 @@ public:
//============================================================================== //==============================================================================
AudioProcessorEditor* createEditor() override AudioProcessorEditor* createEditor() override
{ {
if (view == nullptr) if (IPlugView* view = tryCreatingView())
view = tryCreatingView();
if (view != nullptr)
return new VST3PluginWindow (this, view); return new VST3PluginWindow (this, view);
return nullptr; return nullptr;
@ -2007,9 +1633,7 @@ public:
bool hasEditor() const override bool hasEditor() const override
{ {
if (view == nullptr) ComSmartPtr<IPlugView> view (tryCreatingView()); //N.B.: Must use a ComSmartPtr to not delete the view from the plugin permanently!
view = tryCreatingView();
return view != nullptr; return view != nullptr;
} }
@ -2123,11 +1747,11 @@ public:
(void) sizeInBytes; (void) sizeInBytes;
} }
ComSmartPtr<Vst::IEditController> editController;
private: private:
//============================================================================== //==============================================================================
VST3ModuleHandle::Ptr module; VST3ModuleHandle::Ptr module;
friend VST3HostContext;
ComSmartPtr<VST3HostContext> host; ComSmartPtr<VST3HostContext> host;
// Information objects: // Information objects:
@ -2137,26 +1761,24 @@ private:
ScopedPointer<PClassInfoW> infoW; ScopedPointer<PClassInfoW> infoW;
// Rudimentary interfaces: // Rudimentary interfaces:
ComSmartPtr<Vst::IAudioProcessor> processor;
ComSmartPtr<Vst::IComponent> component; ComSmartPtr<Vst::IComponent> component;
ComSmartPtr<Vst::IEditController> editController;
ComSmartPtr<Vst::IEditController2> editController2;
ComSmartPtr<Vst::IAudioProcessor> processor;
ComSmartPtr<Vst::IComponentHandler> componentHandler; ComSmartPtr<Vst::IComponentHandler> componentHandler;
ComSmartPtr<Vst::IComponentHandler2> componentHandler2; ComSmartPtr<Vst::IComponentHandler2> componentHandler2;
ComSmartPtr<Vst::IEditController2> editController2;
ComSmartPtr<Vst::IUnitInfo> unitInfo; ComSmartPtr<Vst::IUnitInfo> unitInfo;
ComSmartPtr<Vst::IProgramListData> programListData;
ComSmartPtr<Vst::IUnitData> unitData; ComSmartPtr<Vst::IUnitData> unitData;
ComSmartPtr<Vst::IProgramListData> programListData;
ComSmartPtr<Vst::IConnectionPoint> componentConnection; ComSmartPtr<Vst::IConnectionPoint> componentConnection;
ComSmartPtr<Vst::IConnectionPoint> editControllerConnection; ComSmartPtr<Vst::IConnectionPoint> editControllerConnection;
mutable ComSmartPtr<IPlugView> view;
/** The number of IO busses MUST match that of the plugin, /** The number of IO busses MUST match that of the plugin,
even if there aren't enough channels to process, even if there aren't enough channels to process,
as very poorly specified by the Steinberg SDK as very poorly specified by the Steinberg SDK
*/ */
int numInputAudioBusses, numOutputAudioBusses; int numInputAudioBusses, numOutputAudioBusses;
AudioSampleBuffer resultBuffer; VST3BufferExchange::BusMap inputBusMap, outputBusMap;
BusMap inputBusMap, outputBusMap;
Array<Vst::AudioBusBuffers> inputBusses, outputBusses; Array<Vst::AudioBusBuffers> inputBusses, outputBusses;
//============================================================================== //==============================================================================
@ -2370,12 +1992,17 @@ private:
if (componentHandler2 == nullptr) componentHandler2.loadFrom (editController); if (componentHandler2 == nullptr) componentHandler2.loadFrom (editController);
} }
void setStateForAllBusses (bool newState)
{
setStateForAllBussesOfType (component, newState, true, true); // Activate/deactivate audio inputs
setStateForAllBussesOfType (component, newState, false, true); // Activate/deactivate audio outputs
setStateForAllBussesOfType (component, newState, true, false); // Activate/deactivate MIDI inputs
setStateForAllBussesOfType (component, newState, false, false); // Activate/deactivate MIDI outputs
}
void setupIO() void setupIO()
{ {
activateAllBussesOfType (component, true, true); // Activate audio inputs setStateForAllBusses (true);
activateAllBussesOfType (component, false, true); // Activate audio outputs
activateAllBussesOfType (component, true, false); // Activate MIDI inputs
activateAllBussesOfType (component, false, false); // Activate MIDI outputs
Vst::ProcessSetup setup; Vst::ProcessSetup setup;
setup.symbolicSampleSize = Vst::kSample32; setup.symbolicSampleSize = Vst::kSample32;
@ -2406,15 +2033,13 @@ private:
} }
//============================================================================== //==============================================================================
ComSmartPtr<IPlugView> tryCreatingView() const /** @note An IPlugView, when first created, should start with a ref-count of 1! */
IPlugView* tryCreatingView() const
{ {
ComSmartPtr<IPlugView> v (editController->createView (Vst::ViewType::kEditor)); IPlugView* v = editController->createView (Vst::ViewType::kEditor);
if (v == nullptr)
v = editController->createView (nullptr);
if (v == nullptr) if (v == nullptr) v = editController->createView (nullptr);
v.loadFrom (editController); if (v == nullptr) editController->queryInterface (IPlugView::iid, (void**) &v);
return v; return v;
} }
@ -2422,10 +2047,13 @@ private:
//============================================================================== //==============================================================================
void associateTo (Vst::ProcessData& destination, AudioSampleBuffer& buffer) void associateTo (Vst::ProcessData& destination, AudioSampleBuffer& buffer)
{ {
resultBuffer.clear(); using namespace VST3BufferExchange;
mapBufferToBusses (inputBusses, *processor, inputBusMap,
true, numInputAudioBusses, buffer);
mapAudioSampleBufferToBusses (inputBusses, buffer, numInputAudioBusses, true); mapBufferToBusses (outputBusses, *processor, outputBusMap,
mapAudioSampleBufferToBusses (outputBusses, resultBuffer, numOutputAudioBusses, false); false, numOutputAudioBusses, buffer);
destination.inputs = inputBusses.getRawDataPointer(); destination.inputs = inputBusses.getRawDataPointer();
destination.outputs = outputBusses.getRawDataPointer(); destination.outputs = outputBusses.getRawDataPointer();
@ -2512,7 +2140,7 @@ AudioPluginInstance* VST3PluginFormat::createInstanceFromDescription (const Plug
bool VST3PluginFormat::fileMightContainThisPluginType (const String& fileOrIdentifier) bool VST3PluginFormat::fileMightContainThisPluginType (const String& fileOrIdentifier)
{ {
const File f (fileOrIdentifier); const File f (File::createFileWithoutCheckingPath (fileOrIdentifier));
return f.hasFileExtension (".vst3") return f.hasFileExtension (".vst3")
#if JUCE_MAC #if JUCE_MAC
@ -2573,7 +2201,7 @@ FileSearchPath VST3PluginFormat::getDefaultLocationsToSearch()
const String programFiles (File::getSpecialLocation (File::globalApplicationsDirectory).getFullPathName()); const String programFiles (File::getSpecialLocation (File::globalApplicationsDirectory).getFullPathName());
return FileSearchPath (programFiles + "\\Common Files\\VST3"); return FileSearchPath (programFiles + "\\Common Files\\VST3");
#elif JUCE_MAC #elif JUCE_MAC
return FileSearchPath ("~/Library/Audio/Plug-Ins/VST3;/Library/Audio/Plug-Ins/VST3"); return FileSearchPath ("/Library/Audio/Plug-Ins/VST3;~/Library/Audio/Plug-Ins/VST3");
#else #else
return FileSearchPath(); return FileSearchPath();
#endif #endif

@ -718,6 +718,7 @@ public:
VSTPluginInstance (const ModuleHandle::Ptr& module_) VSTPluginInstance (const ModuleHandle::Ptr& module_)
: effect (nullptr), : effect (nullptr),
module (module_), module (module_),
usesCocoaNSView (false),
name (module_->pluginName), name (module_->pluginName),
wantsMidiMessages (false), wantsMidiMessages (false),
initialised (false), initialised (false),
@ -839,7 +840,7 @@ public:
jassert (MessageManager::getInstance()->isThisTheMessageThread()); jassert (MessageManager::getInstance()->isThisTheMessageThread());
#endif #endif
JUCE_VST_LOG ("Initialising VST: " + module->pluginName); JUCE_VST_LOG ("Initialising VST: " + module->pluginName + " (" + getVersion() + ")");
initialised = true; initialised = true;
setPlayConfigDetails (effect->numInputs, effect->numOutputs, setPlayConfigDetails (effect->numInputs, effect->numOutputs,
@ -871,6 +872,10 @@ public:
wantsMidiMessages = dispatch (effCanDo, 0, 0, (void*) "receiveVstMidiEvent", 0) > 0; wantsMidiMessages = dispatch (effCanDo, 0, 0, (void*) "receiveVstMidiEvent", 0) > 0;
#if JUCE_MAC && JUCE_SUPPORT_CARBON
usesCocoaNSView = (dispatch (effCanDo, 0, 0, (void*) "hasCockosViewAsConfig", 0) & 0xffff0000) == 0xbeef0000;
#endif
setLatencySamples (effect->initialDelay); setLatencySamples (effect->initialDelay);
} }
@ -1659,6 +1664,7 @@ public:
ModuleHandle::Ptr module; ModuleHandle::Ptr module;
ScopedPointer<VSTPluginFormat::ExtraFunctions> extraFunctions; ScopedPointer<VSTPluginFormat::ExtraFunctions> extraFunctions;
bool usesCocoaNSView;
private: private:
String name; String name;
@ -1898,7 +1904,6 @@ class VSTPluginWindow : public AudioProcessorEditor,
public Timer public Timer
{ {
public: public:
//==============================================================================
VSTPluginWindow (VSTPluginInstance& plug) VSTPluginWindow (VSTPluginInstance& plug)
: AudioProcessorEditor (&plug), : AudioProcessorEditor (&plug),
#if ! JUCE_MAC #if ! JUCE_MAC
@ -1912,18 +1917,20 @@ public:
alreadyInside (false) alreadyInside (false)
{ {
#if JUCE_WINDOWS #if JUCE_WINDOWS
sizeCheckCount = 0;
pluginHWND = 0; pluginHWND = 0;
sizeCheckCount = 0;
#elif JUCE_LINUX #elif JUCE_LINUX
pluginWindow = None; pluginWindow = None;
pluginProc = None; pluginProc = None;
#elif JUCE_MAC && JUCE_SUPPORT_CARBON
addAndMakeVisible (innerWrapper = new InnerWrapperComponent (*this));
#elif JUCE_MAC #elif JUCE_MAC
addAndMakeVisible (innerWrapper = new NSViewComponent()); #if JUCE_SUPPORT_CARBON
NSView* innerView = [[NSView alloc] init]; if (! plug.usesCocoaNSView)
innerWrapper->setView (innerView); addAndMakeVisible (carbonWrapper = new CarbonWrapperComponent (*this));
[innerView release]; else
#endif
addAndMakeVisible (cocoaWrapper = new AutoResizingNSViewComponentWithParent());
#endif #endif
activeVSTWindows.add (this); activeVSTWindows.add (this);
@ -1938,7 +1945,10 @@ public:
closePluginWindow(); closePluginWindow();
#if JUCE_MAC #if JUCE_MAC
innerWrapper = nullptr; #if JUCE_SUPPORT_CARBON
carbonWrapper = nullptr;
#endif
cocoaWrapper = nullptr;
#endif #endif
activeVSTWindows.removeFirstMatchingValue (this); activeVSTWindows.removeFirstMatchingValue (this);
@ -1993,20 +2003,28 @@ public:
} }
#endif #endif
#if JUCE_MAC && ! JUCE_SUPPORT_CARBON #if JUCE_MAC
void visibilityChanged() override void visibilityChanged() override
{ {
if (isVisible()) if (cocoaWrapper != nullptr)
openPluginWindow(); {
else if (isVisible())
closePluginWindow(); openPluginWindow ((NSView*) cocoaWrapper->getView());
else
closePluginWindow();
}
} }
void childBoundsChanged (Component*) override void childBoundsChanged (Component*) override
{ {
if (innerWrapper != nullptr) if (cocoaWrapper != nullptr)
setSize (innerWrapper->getWidth(), {
innerWrapper->getHeight()); int w = cocoaWrapper->getWidth();
int h = cocoaWrapper->getHeight();
if (w != getWidth() || h != getHeight())
setSize (w, h);
}
} }
#endif #endif
@ -2138,15 +2156,8 @@ private:
//============================================================================== //==============================================================================
#if JUCE_MAC #if JUCE_MAC
#if JUCE_SUPPORT_CARBON void openPluginWindow (void* parentWindow)
void openPluginWindow (WindowRef parentWindow)
{
#else
void openPluginWindow()
{ {
NSView* parentWindow = (NSView*) innerWrapper->getView();
#endif
if (isOpen || parentWindow == 0) if (isOpen || parentWindow == 0)
return; return;
@ -2358,9 +2369,9 @@ private:
{ {
for (int i = activeVSTWindows.size(); --i >= 0;) for (int i = activeVSTWindows.size(); --i >= 0;)
{ {
const VSTPluginWindow* const w = activeVSTWindows.getUnchecked (i); Component::SafePointer<VSTPluginWindow> w (activeVSTWindows[i]);
if (w->pluginHWND == hW) if (w != nullptr && w->pluginHWND == hW)
{ {
if (message == WM_CHAR if (message == WM_CHAR
|| message == WM_KEYDOWN || message == WM_KEYDOWN
@ -2373,9 +2384,10 @@ private:
message, wParam, lParam); message, wParam, lParam);
} }
return CallWindowProc ((WNDPROC) w->originalWndProc, if (w != nullptr) // (may have been deleted in SendMessage callback)
(HWND) w->pluginHWND, return CallWindowProc ((WNDPROC) w->originalWndProc,
message, wParam, lParam); (HWND) w->pluginHWND,
message, wParam, lParam);
} }
} }
@ -2500,17 +2512,17 @@ private:
//============================================================================== //==============================================================================
#if JUCE_MAC #if JUCE_MAC
#if JUCE_SUPPORT_CARBON #if JUCE_SUPPORT_CARBON
class InnerWrapperComponent : public CarbonViewWrapperComponent class CarbonWrapperComponent : public CarbonViewWrapperComponent
{ {
public: public:
InnerWrapperComponent (VSTPluginWindow& w) CarbonWrapperComponent (VSTPluginWindow& w)
: owner (w), alreadyInside (false) : owner (w), alreadyInside (false)
{ {
keepPluginWindowWhenHidden = w.shouldAvoidDeletingWindow(); keepPluginWindowWhenHidden = w.shouldAvoidDeletingWindow();
setRepaintsChildHIViewWhenCreated (w.shouldRepaintCarbonWindowWhenCreated()); setRepaintsChildHIViewWhenCreated (w.shouldRepaintCarbonWindowWhenCreated());
} }
~InnerWrapperComponent() ~CarbonWrapperComponent()
{ {
deleteWindow(); deleteWindow();
} }
@ -2574,20 +2586,24 @@ private:
VSTPluginWindow& owner; VSTPluginWindow& owner;
bool alreadyInside; bool alreadyInside;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (InnerWrapperComponent) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CarbonWrapperComponent)
}; };
friend class InnerWrapperComponent; friend class CarbonWrapperComponent;
ScopedPointer<InnerWrapperComponent> innerWrapper; ScopedPointer<CarbonWrapperComponent> carbonWrapper;
#else
ScopedPointer<NSViewComponent> innerWrapper;
#endif #endif
ScopedPointer<AutoResizingNSViewComponentWithParent> cocoaWrapper;
void resized() override void resized() override
{ {
if (innerWrapper != nullptr) #if JUCE_SUPPORT_CARBON
innerWrapper->setSize (getWidth(), getHeight()); if (carbonWrapper != nullptr)
carbonWrapper->setSize (getWidth(), getHeight());
#endif
if (cocoaWrapper != nullptr)
cocoaWrapper->setSize (getWidth(), getHeight());
} }
#endif #endif
@ -2637,7 +2653,7 @@ static VSTPluginInstance* createAndUpdateDesc (VSTPluginFormat& format, PluginDe
return nullptr; return nullptr;
} }
void VSTPluginFormat::findAllTypesForFile (OwnedArray <PluginDescription>& results, void VSTPluginFormat::findAllTypesForFile (OwnedArray<PluginDescription>& results,
const String& fileOrIdentifier) const String& fileOrIdentifier)
{ {
if (! fileMightContainThisPluginType (fileOrIdentifier)) if (! fileMightContainThisPluginType (fileOrIdentifier))
@ -2671,14 +2687,17 @@ void VSTPluginFormat::findAllTypesForFile (OwnedArray <PluginDescription>& resul
break; break;
desc.uid = uid; desc.uid = uid;
desc.name = shellEffectName;
aboutToScanVSTShellPlugin (desc);
ScopedPointer<VSTPluginInstance> shellInstance (createAndUpdateDesc (*this, desc)); ScopedPointer<VSTPluginInstance> shellInstance (createAndUpdateDesc (*this, desc));
if (shellInstance != nullptr) if (shellInstance != nullptr)
{ {
jassert (desc.uid == uid); jassert (desc.uid == uid);
desc.name = shellEffectName;
desc.hasSharedContainer = true; desc.hasSharedContainer = true;
desc.name = shellEffectName;
if (! arrayContainsPlugin (results, desc)) if (! arrayContainsPlugin (results, desc))
results.add (new PluginDescription (desc)); results.add (new PluginDescription (desc));
@ -2724,7 +2743,7 @@ AudioPluginInstance* VSTPluginFormat::createInstanceFromDescription (const Plugi
bool VSTPluginFormat::fileMightContainThisPluginType (const String& fileOrIdentifier) bool VSTPluginFormat::fileMightContainThisPluginType (const String& fileOrIdentifier)
{ {
const File f (fileOrIdentifier); const File f (File::createFileWithoutCheckingPath (fileOrIdentifier));
#if JUCE_MAC #if JUCE_MAC
if (f.isDirectory() && f.hasFileExtension (".vst")) if (f.isDirectory() && f.hasFileExtension (".vst"))
@ -2881,4 +2900,6 @@ VSTPluginFormat::VstIntPtr JUCE_CALLTYPE VSTPluginFormat::dispatcher (AudioPlugi
return 0; return 0;
} }
void VSTPluginFormat::aboutToScanVSTShellPlugin (const PluginDescription&) {}
#endif #endif

@ -96,6 +96,13 @@ public:
FileSearchPath getDefaultLocationsToSearch() override; FileSearchPath getDefaultLocationsToSearch() override;
bool canScanForPlugins() const override { return true; } bool canScanForPlugins() const override { return true; }
/** Can be overridden to receive a callback when each member of a shell plugin is about to be
tested during a call to findAllTypesForFile().
Only the name and uid members of the PluginDescription are guaranteed to be valid when
this is called.
*/
virtual void aboutToScanVSTShellPlugin (const PluginDescription&);
private: private:
void recursiveFileSearch (StringArray&, const File&, bool recursive); void recursiveFileSearch (StringArray&, const File&, bool recursive);

@ -57,6 +57,11 @@
#undef KeyPress #undef KeyPress
#endif #endif
#if ! JUCE_WINDOWS && ! JUCE_MAC
#undef JUCE_PLUGINHOST_VST3
#define JUCE_PLUGINHOST_VST3 0
#endif
//============================================================================== //==============================================================================
namespace juce namespace juce
{ {
@ -71,6 +76,68 @@ static inline bool arrayContainsPlugin (const OwnedArray<PluginDescription>& lis
return false; return false;
} }
#if JUCE_MAC
//==============================================================================
struct AutoResizingNSViewComponent : public NSViewComponent,
private AsyncUpdater
{
AutoResizingNSViewComponent() : recursive (false) {}
void childBoundsChanged (Component*) override
{
if (recursive)
{
triggerAsyncUpdate();
}
else
{
recursive = true;
resizeToFitView();
recursive = true;
}
}
void handleAsyncUpdate() override { resizeToFitView(); }
bool recursive;
};
//==============================================================================
struct AutoResizingNSViewComponentWithParent : public AutoResizingNSViewComponent,
private Timer
{
AutoResizingNSViewComponentWithParent()
{
NSView* v = [[NSView alloc] init];
setView (v);
[v release];
startTimer (100);
}
void timerCallback() override
{
if (NSView* parent = (NSView*) getView())
{
if ([[parent subviews] count] > 0)
{
if (NSView* child = [[parent subviews] objectAtIndex: 0])
{
NSRect f = [parent frame];
NSSize newSize = [child frame].size;
if (f.size.width != newSize.width || f.size.height != newSize.height)
{
f.size = newSize;
[parent setFrame: f];
}
}
}
}
}
};
#endif
#if JUCE_CLANG #if JUCE_CLANG
#pragma clang diagnostic ignored "-Wdeprecated-declarations" #pragma clang diagnostic ignored "-Wdeprecated-declarations"
#endif #endif

@ -44,7 +44,7 @@
Enables the VST3 audio plugin hosting classes. This requires the Steinberg VST3 SDK to be Enables the VST3 audio plugin hosting classes. This requires the Steinberg VST3 SDK to be
installed on your machine. installed on your machine.
@see VSTPluginFormat, VVST3PluginFormat, AudioPluginFormat, AudioPluginFormatManager, JUCE_PLUGINHOST_VST, JUCE_PLUGINHOST_AU @see VSTPluginFormat, VST3PluginFormat, AudioPluginFormat, AudioPluginFormatManager, JUCE_PLUGINHOST_VST, JUCE_PLUGINHOST_AU
*/ */
#ifndef JUCE_PLUGINHOST_VST3 #ifndef JUCE_PLUGINHOST_VST3
#define JUCE_PLUGINHOST_VST3 0 #define JUCE_PLUGINHOST_VST3 0
@ -60,7 +60,7 @@
#endif #endif
#if ! (JUCE_PLUGINHOST_AU || JUCE_PLUGINHOST_VST || JUCE_PLUGINHOST_VST3) #if ! (JUCE_PLUGINHOST_AU || JUCE_PLUGINHOST_VST || JUCE_PLUGINHOST_VST3)
// #error "You need to set either the JUCE_PLUGINHOST_AU anr/or JUCE_PLUGINHOST_VST flags if you're using this module!" // #error "You need to set either the JUCE_PLUGINHOST_AU and/or JUCE_PLUGINHOST_VST and/or JUCE_PLUGINHOST_VST3 flags if you're using this module!"
#endif #endif
#if ! (defined (JUCE_SUPPORT_CARBON) || JUCE_64BIT) #if ! (defined (JUCE_SUPPORT_CARBON) || JUCE_64BIT)

@ -1,7 +1,7 @@
{ {
"id": "juce_audio_processors", "id": "juce_audio_processors",
"name": "JUCE audio plugin hosting classes", "name": "JUCE audio plugin hosting classes",
"version": "3.0.1", "version": "3.0.3",
"description": "Classes for loading and playing VST, AU, or internally-generated audio processors.", "description": "Classes for loading and playing VST, AU, or internally-generated audio processors.",
"website": "http://www.juce.com/juce", "website": "http://www.juce.com/juce",
"license": "GPL/Commercial", "license": "GPL/Commercial",

@ -609,6 +609,7 @@ public:
{ {
wrapperType_Undefined = 0, wrapperType_Undefined = 0,
wrapperType_VST, wrapperType_VST,
wrapperType_VST3,
wrapperType_AudioUnit, wrapperType_AudioUnit,
wrapperType_RTAS, wrapperType_RTAS,
wrapperType_AAX, wrapperType_AAX,

@ -202,6 +202,14 @@ void KnownPluginList::scanAndAddDragAndDroppedFiles (AudioPluginFormatManager& f
} }
} }
} }
scanFinished();
}
void KnownPluginList::scanFinished()
{
if (scanner != nullptr)
scanner->scanFinished();
} }
const StringArray& KnownPluginList::getBlacklistedFiles() const const StringArray& KnownPluginList::getBlacklistedFiles() const
@ -280,10 +288,16 @@ void KnownPluginList::sort (const SortMethod method, bool forwards)
{ {
if (method != defaultOrder) if (method != defaultOrder)
{ {
Array<PluginDescription*> oldOrder, newOrder;
oldOrder.addArray (types);
PluginSorter sorter (method, forwards); PluginSorter sorter (method, forwards);
types.sort (sorter, true); types.sort (sorter, true);
sendChangeMessage(); newOrder.addArray (types);
if (oldOrder != newOrder)
sendChangeMessage();
} }
} }
@ -523,3 +537,13 @@ int KnownPluginList::getIndexChosenByMenu (const int menuResultCode) const
//============================================================================== //==============================================================================
KnownPluginList::CustomScanner::CustomScanner() {} KnownPluginList::CustomScanner::CustomScanner() {}
KnownPluginList::CustomScanner::~CustomScanner() {} KnownPluginList::CustomScanner::~CustomScanner() {}
void KnownPluginList::CustomScanner::scanFinished() {}
bool KnownPluginList::CustomScanner::shouldExit() const noexcept
{
if (ThreadPoolJob* job = ThreadPoolJob::getCurrentThreadPoolJob())
return job->shouldExit();
return false;
}

@ -97,6 +97,9 @@ public:
OwnedArray <PluginDescription>& typesFound, OwnedArray <PluginDescription>& typesFound,
AudioPluginFormat& formatToUse); AudioPluginFormat& formatToUse);
/** Tells a custom scanner that a scan has finished, and it can release any resources. */
void scanFinished();
/** Returns true if the specified file is already known about and if it /** Returns true if the specified file is already known about and if it
hasn't been modified since our entry was created. hasn't been modified since our entry was created.
*/ */
@ -170,8 +173,8 @@ public:
struct PluginTree struct PluginTree
{ {
String folder; /**< The name of this folder in the tree */ String folder; /**< The name of this folder in the tree */
OwnedArray <PluginTree> subFolders; OwnedArray<PluginTree> subFolders;
Array <const PluginDescription*> plugins; Array<const PluginDescription*> plugins;
}; };
/** Creates a PluginTree object containing all the known plugins. */ /** Creates a PluginTree object containing all the known plugins. */
@ -190,9 +193,21 @@ public:
virtual bool findPluginTypesFor (AudioPluginFormat& format, virtual bool findPluginTypesFor (AudioPluginFormat& format,
OwnedArray <PluginDescription>& result, OwnedArray <PluginDescription>& result,
const String& fileOrIdentifier) = 0; const String& fileOrIdentifier) = 0;
/** Called when a scan has finished, to allow clean-up of resources. */
virtual void scanFinished();
/** Returns true if the current scan should be abandoned.
Any blocking methods should check this value repeatedly and return if
if becomes true.
*/
bool shouldExit() const noexcept;
}; };
void setCustomScanner (CustomScanner* scanner); /** Supplies a custom scanner to be used in future scans.
The KnownPluginList will take ownership of the object passed in.
*/
void setCustomScanner (CustomScanner*);
private: private:
//============================================================================== //==============================================================================

@ -63,6 +63,7 @@ PluginDirectoryScanner::PluginDirectoryScanner (KnownPluginList& listToAddTo,
PluginDirectoryScanner::~PluginDirectoryScanner() PluginDirectoryScanner::~PluginDirectoryScanner()
{ {
list.scanFinished();
} }
//============================================================================== //==============================================================================

@ -83,9 +83,9 @@ public:
} }
} }
void deleteKeyPressed (int lastRowSelected) override void deleteKeyPressed (int) override
{ {
removePluginItem (list, lastRowSelected); owner.removeSelected();
} }
void sortOrderChanged (int newSortColumnId, bool isForwards) override void sortOrderChanged (int newSortColumnId, bool isForwards) override
@ -152,6 +152,7 @@ PluginListComponent::PluginListComponent (AudioPluginFormatManager& manager, Kno
table.setHeaderHeight (22); table.setHeaderHeight (22);
table.setRowHeight (20); table.setRowHeight (20);
table.setModel (tableModel); table.setModel (tableModel);
table.setMultipleSelectionEnabled (true);
addAndMakeVisible (table); addAndMakeVisible (table);
addAndMakeVisible (optionsButton); addAndMakeVisible (optionsButton);
@ -161,6 +162,7 @@ PluginListComponent::PluginListComponent (AudioPluginFormatManager& manager, Kno
setSize (400, 600); setSize (400, 600);
list.addChangeListener (this); list.addChangeListener (this);
updateList(); updateList();
table.getHeader().reSortTable();
PluginDirectoryScanner::applyBlacklistingsFromDeadMansPedal (list, deadMansPedalFile); PluginDirectoryScanner::applyBlacklistingsFromDeadMansPedal (list, deadMansPedalFile);
deadMansPedalFile.deleteFile(); deadMansPedalFile.deleteFile();
@ -195,6 +197,7 @@ void PluginListComponent::resized()
void PluginListComponent::changeListenerCallback (ChangeBroadcaster*) void PluginListComponent::changeListenerCallback (ChangeBroadcaster*)
{ {
table.getHeader().reSortTable();
updateList(); updateList();
} }
@ -208,7 +211,7 @@ void PluginListComponent::removeSelected()
{ {
const SparseSet<int> selected (table.getSelectedRows()); const SparseSet<int> selected (table.getSelectedRows());
for (int i = list.getNumTypes(); --i >= 0;) for (int i = table.getNumRows(); --i >= 0;)
if (selected.contains (i)) if (selected.contains (i))
TableModel::removePluginItem (list, i); TableModel::removePluginItem (list, i);
} }

@ -40,12 +40,19 @@ public:
void timerCallback() override void timerCallback() override
{ {
const float newLevel = (float) manager.getCurrentInputLevel(); if (isShowing())
{
const float newLevel = (float) manager.getCurrentInputLevel();
if (std::abs (level - newLevel) > 0.005f) if (std::abs (level - newLevel) > 0.005f)
{
level = newLevel;
repaint();
}
}
else
{ {
level = newLevel; level = 0;
repaint();
} }
} }

@ -461,15 +461,20 @@ private:
if (sample >= 0) if (sample >= 0)
{ {
if (sample >= levelData->lengthInSamples) if (sample >= levelData->lengthInSamples)
break; {
for (int chan = 0; chan < numChannelsCached; ++chan)
levelData->getLevels (sample, jmax (1, nextSample - sample), levels); *getData (chan, i) = MinMaxValue();
}
else
{
levelData->getLevels (sample, jmax (1, nextSample - sample), levels);
const int totalChans = jmin (levels.size() / 2, numChannelsCached); const int totalChans = jmin (levels.size() / 2, numChannelsCached);
for (int chan = 0; chan < totalChans; ++chan) for (int chan = 0; chan < totalChans; ++chan)
getData (chan, i)->setFloat (levels.getUnchecked (chan * 2), getData (chan, i)->setFloat (levels.getUnchecked (chan * 2),
levels.getUnchecked (chan * 2 + 1)); levels.getUnchecked (chan * 2 + 1));
}
} }
startTime += timePerPixel; startTime += timePerPixel;

@ -152,10 +152,9 @@ void MidiKeyboardComponent::setLowestVisibleKeyFloat (float noteNumber)
firstKey = noteNumber; firstKey = noteNumber;
if (hasMoved) if (hasMoved)
{
sendChangeMessage(); sendChangeMessage();
resized();
} resized();
} }
} }
@ -212,19 +211,11 @@ void MidiKeyboardComponent::getKeyPosition (int midiNoteNumber, const float keyW
5.0f, 6 - blackNoteWidth * 0.3f, 5.0f, 6 - blackNoteWidth * 0.3f,
6.0f }; 6.0f };
static const float widths[] = { 1.0f, blackNoteWidth,
1.0f, blackNoteWidth,
1.0f,
1.0f, blackNoteWidth,
1.0f, blackNoteWidth,
1.0f, blackNoteWidth,
1.0f };
const int octave = midiNoteNumber / 12; const int octave = midiNoteNumber / 12;
const int note = midiNoteNumber % 12; const int note = midiNoteNumber % 12;
x = roundToInt (octave * 7.0f * keyWidth_ + notePos [note] * keyWidth_); x = roundToInt (octave * 7.0f * keyWidth_ + notePos [note] * keyWidth_);
w = roundToInt (widths [note] * keyWidth_); w = roundToInt (MidiMessage::isMidiNoteBlack (note) ? blackNoteWidth * keyWidth_ : keyWidth_);
} }
void MidiKeyboardComponent::getKeyPos (int midiNoteNumber, int& x, int& w) const void MidiKeyboardComponent::getKeyPos (int midiNoteNumber, int& x, int& w) const
@ -261,6 +252,12 @@ int MidiKeyboardComponent::getKeyStartPosition (const int midiNoteNumber) const
return x; return x;
} }
int MidiKeyboardComponent::getNoteAtPosition (Point<int> p)
{
float v;
return xyToNote (p, v);
}
const uint8 MidiKeyboardComponent::whiteNotes[] = { 0, 2, 4, 5, 7, 9, 11 }; const uint8 MidiKeyboardComponent::whiteNotes[] = { 0, 2, 4, 5, 7, 9, 11 };
const uint8 MidiKeyboardComponent::blackNotes[] = { 1, 3, 6, 8, 10 }; const uint8 MidiKeyboardComponent::blackNotes[] = { 1, 3, 6, 8, 10 };
@ -383,13 +380,13 @@ void MidiKeyboardComponent::paint (Graphics& g)
else else
y2 = 5.0f; y2 = 5.0f;
g.setGradientFill (ColourGradient (Colours::black.withAlpha (0.3f), x1, y1,
Colours::transparentBlack, x2, y2, false));
int x, w; int x, w;
getKeyPos (rangeEnd, x, w); getKeyPos (rangeEnd, x, w);
x += w; x += w;
const Colour shadowCol (findColour (shadowColourId));
g.setGradientFill (ColourGradient (shadowCol, x1, y1, shadowCol.withAlpha (0.0f), x2, y2, false));
switch (orientation) switch (orientation)
{ {
case horizontalKeyboard: g.fillRect (0, 0, x, 5); break; case horizontalKeyboard: g.fillRect (0, 0, x, 5); break;
@ -458,14 +455,13 @@ void MidiKeyboardComponent::drawWhiteNote (int midiNoteNumber,
g.setColour (textColour); g.setColour (textColour);
g.setFont (Font (jmin (12.0f, keyWidth * 0.9f)).withHorizontalScale (0.8f)); g.setFont (Font (jmin (12.0f, keyWidth * 0.9f)).withHorizontalScale (0.8f));
Justification justification (Justification::centredBottom); switch (orientation)
{
if (orientation == verticalKeyboardFacingLeft) case horizontalKeyboard: g.drawFittedText (text, x + 1, y, w - 1, h - 2, Justification::centredBottom, 1); break;
justification = Justification::centredLeft; case verticalKeyboardFacingLeft: g.drawFittedText (text, x + 2, y + 2, w - 4, h - 4, Justification::centredLeft, 1); break;
else if (orientation == verticalKeyboardFacingRight) case verticalKeyboardFacingRight: g.drawFittedText (text, x + 2, y + 2, w - 4, h - 4, Justification::centredRight, 1); break;
justification = Justification::centredRight; default: break;
}
g.drawFittedText (text, x + 2, y + 2, w - 4, h - 4, justification, 1);
} }
g.setColour (lineColour); g.setColour (lineColour);
@ -531,7 +527,7 @@ void MidiKeyboardComponent::setOctaveForMiddleC (const int octaveNum)
String MidiKeyboardComponent::getWhiteNoteText (const int midiNoteNumber) String MidiKeyboardComponent::getWhiteNoteText (const int midiNoteNumber)
{ {
if (keyWidth > 14.0f && midiNoteNumber % 12 == 0) if (keyWidth > 11.0f && midiNoteNumber % 12 == 0)
return MidiMessage::getMidiNoteName (midiNoteNumber, true, true, octaveNumForMiddleC); return MidiMessage::getMidiNoteName (midiNoteNumber, true, true, octaveNumForMiddleC);
return String::empty; return String::empty;
@ -594,31 +590,29 @@ void MidiKeyboardComponent::resized()
} }
} }
const bool showScrollButtons = canScroll && (((int) firstKey) > rangeStart || kx2 > w + xOffset * 2); scrollDown->setVisible (canScroll && firstKey > (float) rangeStart);
scrollDown->setVisible (showScrollButtons);
scrollUp->setVisible (showScrollButtons);
xOffset = 0; xOffset = 0;
if (showScrollButtons) if (canScroll)
{ {
const int scrollButtonW = jmin (12, w / 2); const int scrollButtonW = jmin (12, w / 2);
Rectangle<int> r (getLocalBounds());
if (orientation == horizontalKeyboard) if (orientation == horizontalKeyboard)
{ {
scrollDown->setBounds (0, 0, scrollButtonW, getHeight()); scrollDown->setBounds (r.removeFromLeft (scrollButtonW));
scrollUp->setBounds (getWidth() - scrollButtonW, 0, scrollButtonW, getHeight()); scrollUp ->setBounds (r.removeFromRight (scrollButtonW));
} }
else if (orientation == verticalKeyboardFacingLeft) else if (orientation == verticalKeyboardFacingLeft)
{ {
scrollDown->setBounds (0, 0, getWidth(), scrollButtonW); scrollDown->setBounds (r.removeFromTop (scrollButtonW));
scrollUp->setBounds (0, getHeight() - scrollButtonW, getWidth(), scrollButtonW); scrollUp ->setBounds (r.removeFromBottom (scrollButtonW));
} }
else else
{ {
scrollDown->setBounds (0, getHeight() - scrollButtonW, getWidth(), scrollButtonW); scrollDown->setBounds (r.removeFromBottom (scrollButtonW));
scrollUp->setBounds (0, 0, getWidth(), scrollButtonW); scrollUp ->setBounds (r.removeFromTop (scrollButtonW));
} }
int endOfLastKey, kw; int endOfLastKey, kw;
@ -626,7 +620,7 @@ void MidiKeyboardComponent::resized()
endOfLastKey += kw; endOfLastKey += kw;
float mousePositionVelocity; float mousePositionVelocity;
const int spaceAvailable = w - scrollButtonW * 2; const int spaceAvailable = w;
const int lastStartKey = remappedXYToNote (Point<int> (endOfLastKey - spaceAvailable, 0), mousePositionVelocity) + 1; const int lastStartKey = remappedXYToNote (Point<int> (endOfLastKey - spaceAvailable, 0), mousePositionVelocity) + 1;
if (lastStartKey >= 0 && ((int) firstKey) > lastStartKey) if (lastStartKey >= 0 && ((int) firstKey) > lastStartKey)
@ -636,14 +630,16 @@ void MidiKeyboardComponent::resized()
} }
int newOffset = 0; int newOffset = 0;
getKeyPos (((int) firstKey), newOffset, kw); getKeyPos ((int) firstKey, newOffset, kw);
xOffset = newOffset - scrollButtonW; xOffset = newOffset;
} }
else else
{ {
firstKey = (float) rangeStart; firstKey = (float) rangeStart;
} }
getKeyPos (rangeEnd, kx2, kw2);
scrollUp->setVisible (canScroll && kx2 > w);
repaint(); repaint();
} }
} }

@ -52,7 +52,6 @@ class JUCE_API MidiKeyboardComponent : public Component,
public: public:
//============================================================================== //==============================================================================
/** The direction of the keyboard. /** The direction of the keyboard.
@see setOrientation @see setOrientation
*/ */
enum Orientation enum Orientation
@ -97,7 +96,6 @@ public:
void setMidiChannel (int midiChannelNumber); void setMidiChannel (int midiChannelNumber);
/** Returns the midi channel that the keyboard is using for midi messages. /** Returns the midi channel that the keyboard is using for midi messages.
@see setMidiChannel @see setMidiChannel
*/ */
int getMidiChannel() const noexcept { return midiChannel; } int getMidiChannel() const noexcept { return midiChannel; }
@ -117,7 +115,6 @@ public:
void setMidiChannelsToDisplay (int midiChannelMask); void setMidiChannelsToDisplay (int midiChannelMask);
/** Returns the current set of midi channels represented by the component. /** Returns the current set of midi channels represented by the component.
This is the value that was set with setMidiChannelsToDisplay(). This is the value that was set with setMidiChannelsToDisplay().
*/ */
int getMidiChannelsToDisplay() const noexcept { return midiInChannelMask; } int getMidiChannelsToDisplay() const noexcept { return midiInChannelMask; }
@ -169,7 +166,6 @@ public:
int getLowestVisibleKey() const noexcept { return (int) firstKey; } int getLowestVisibleKey() const noexcept { return (int) firstKey; }
/** Returns the length of the black notes. /** Returns the length of the black notes.
This will be their vertical or horizontal length, depending on the keyboard's orientation. This will be their vertical or horizontal length, depending on the keyboard's orientation.
*/ */
int getBlackNoteLength() const noexcept { return blackNoteLength; } int getBlackNoteLength() const noexcept { return blackNoteLength; }
@ -196,7 +192,8 @@ public:
keyDownOverlayColourId = 0x1005004, /**< This colour will be overlaid on the normal note colour. */ keyDownOverlayColourId = 0x1005004, /**< This colour will be overlaid on the normal note colour. */
textLabelColourId = 0x1005005, textLabelColourId = 0x1005005,
upDownButtonBackgroundColourId = 0x1005006, upDownButtonBackgroundColourId = 0x1005006,
upDownButtonArrowColourId = 0x1005007 upDownButtonArrowColourId = 0x1005007,
shadowColourId = 0x1005008
}; };
/** Returns the position within the component of the left-hand edge of a key. /** Returns the position within the component of the left-hand edge of a key.
@ -206,6 +203,9 @@ public:
*/ */
int getKeyStartPosition (int midiNoteNumber) const; int getKeyStartPosition (int midiNoteNumber) const;
/** Returns the key at a given coordinate. */
int getNoteAtPosition (Point<int> position);
//============================================================================== //==============================================================================
/** Deletes all key-mappings. /** Deletes all key-mappings.
@see setKeyPressForNote @see setKeyPressForNote
@ -319,9 +319,7 @@ protected:
const Colour& noteFillColour); const Colour& noteFillColour);
/** Allows text to be drawn on the white notes. /** Allows text to be drawn on the white notes.
By default this is used to label the C in each octave, but could be used for other things. By default this is used to label the C in each octave, but could be used for other things.
@see setOctaveForMiddleC @see setOctaveForMiddleC
*/ */
virtual String getWhiteNoteText (const int midiNoteNumber); virtual String getWhiteNoteText (const int midiNoteNumber);

@ -1,7 +1,7 @@
{ {
"id": "juce_audio_utils", "id": "juce_audio_utils",
"name": "JUCE extra audio utility classes", "name": "JUCE extra audio utility classes",
"version": "3.0.1", "version": "3.0.3",
"description": "Classes for audio-related GUI and miscellaneous tasks.", "description": "Classes for audio-related GUI and miscellaneous tasks.",
"website": "http://www.juce.com/juce", "website": "http://www.juce.com/juce",
"license": "GPL/Commercial", "license": "GPL/Commercial",

@ -45,9 +45,7 @@ void AudioProcessorPlayer::setProcessor (AudioProcessor* const processorToPlay)
{ {
if (processorToPlay != nullptr && sampleRate > 0 && blockSize > 0) if (processorToPlay != nullptr && sampleRate > 0 && blockSize > 0)
{ {
processorToPlay->setPlayConfigDetails (numInputChans, numOutputChans, processorToPlay->setPlayConfigDetails (numInputChans, numOutputChans, sampleRate, blockSize);
sampleRate, blockSize);
processorToPlay->prepareToPlay (sampleRate, blockSize); processorToPlay->prepareToPlay (sampleRate, blockSize);
} }
@ -120,22 +118,23 @@ void AudioProcessorPlayer::audioDeviceIOCallback (const float** const inputChann
AudioSampleBuffer buffer (channels, totalNumChans, numSamples); AudioSampleBuffer buffer (channels, totalNumChans, numSamples);
const ScopedLock sl (lock);
if (processor != nullptr)
{ {
const ScopedLock sl2 (processor->getCallbackLock()); const ScopedLock sl (lock);
if (processor->isSuspended()) if (processor != nullptr)
{ {
for (int i = 0; i < numOutputChannels; ++i) const ScopedLock sl2 (processor->getCallbackLock());
zeromem (outputChannelData[i], sizeof (float) * (size_t) numSamples);
} if (! processor->isSuspended())
else {
{ processor->processBlock (buffer, incomingMidi);
processor->processBlock (buffer, incomingMidi); return;
}
} }
} }
for (int i = 0; i < numOutputChannels; ++i)
FloatVectorOperations::clear (outputChannelData[i], numSamples);
} }
void AudioProcessorPlayer::audioDeviceAboutToStart (AudioIODevice* const device) void AudioProcessorPlayer::audioDeviceAboutToStart (AudioIODevice* const device)

@ -52,27 +52,22 @@ public:
/** Sets the processor that should be played. /** Sets the processor that should be played.
The processor that is passed in will not be deleted or owned by this object. 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. To stop anything playing, pass a nullptr to this method.
*/ */
void setProcessor (AudioProcessor* processorToPlay); void setProcessor (AudioProcessor* processorToPlay);
/** Returns the current audio processor that is being played. /** Returns the current audio processor that is being played. */
*/ AudioProcessor* getCurrentProcessor() const noexcept { return processor; }
AudioProcessor* getCurrentProcessor() const { return processor; }
/** Returns a midi message collector that you can pass midi messages to if you /** 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 want them to be injected into the midi stream that is being sent to the
processor. processor.
*/ */
MidiMessageCollector& getMidiMessageCollector() { return messageCollector; } MidiMessageCollector& getMidiMessageCollector() noexcept { return messageCollector; }
//============================================================================== //==============================================================================
/** @internal */ /** @internal */
void audioDeviceIOCallback (const float** inputChannelData, void audioDeviceIOCallback (const float**, int, float**, int, int) override;
int totalNumInputChannels,
float** outputChannelData,
int totalNumOutputChannels,
int numSamples) override;
/** @internal */ /** @internal */
void audioDeviceAboutToStart (AudioIODevice*) override; void audioDeviceAboutToStart (AudioIODevice*) override;
/** @internal */ /** @internal */

@ -40,7 +40,7 @@
do so, the class must fulfil these requirements: do so, the class must fulfil these requirements:
- it must have a copy constructor and assignment operator - it must have a copy constructor and assignment operator
- it must be able to be relocated in memory by a memcpy without this causing any problems - so - it must be able to be relocated in memory by a memcpy without this causing any problems - so
objects whose functionality relies on external pointers or references to themselves can be used. objects whose functionality relies on external pointers or references to themselves can not be used.
You can of course have an array of pointers to any kind of object, e.g. Array <MyClass*>, but if You can of course have an array of pointers to any kind of object, e.g. Array <MyClass*>, but if
you do this, the array doesn't take any ownership of the objects - see the OwnedArray class or the you do this, the array doesn't take any ownership of the objects - see the OwnedArray class or the
@ -143,6 +143,7 @@ public:
Array& operator= (Array&& other) noexcept Array& operator= (Array&& other) noexcept
{ {
const ScopedLockType lock (getLock()); const ScopedLockType lock (getLock());
deleteAllElements();
data = static_cast<ArrayAllocationBase<ElementType, TypeOfCriticalSectionToUse>&&> (other.data); data = static_cast<ArrayAllocationBase<ElementType, TypeOfCriticalSectionToUse>&&> (other.data);
numUsed = other.numUsed; numUsed = other.numUsed;
other.numUsed = 0; other.numUsed = 0;

@ -30,6 +30,11 @@ DynamicObject::DynamicObject()
{ {
} }
DynamicObject::DynamicObject (const DynamicObject& other)
: properties (other.properties)
{
}
DynamicObject::~DynamicObject() DynamicObject::~DynamicObject()
{ {
} }
@ -78,12 +83,9 @@ void DynamicObject::clear()
properties.clear(); properties.clear();
} }
DynamicObject::Ptr DynamicObject::clone() void DynamicObject::cloneAllProperties()
{ {
DynamicObject* newCopy = new DynamicObject(); for (LinkedListPointer<NamedValueSet::NamedValue>* i = &(properties.values);;)
newCopy->properties = properties;
for (LinkedListPointer<NamedValueSet::NamedValue>* i = &(newCopy->properties.values);;)
{ {
if (NamedValueSet::NamedValue* const v = i->get()) if (NamedValueSet::NamedValue* const v = i->get())
{ {
@ -93,8 +95,13 @@ DynamicObject::Ptr DynamicObject::clone()
else else
break; break;
} }
}
return newCopy; DynamicObject::Ptr DynamicObject::clone()
{
Ptr d (new DynamicObject (*this));
d->cloneAllProperties();
return d;
} }
void DynamicObject::writeAsJSON (OutputStream& out, const int indentLevel, const bool allOnOneLine) void DynamicObject::writeAsJSON (OutputStream& out, const int indentLevel, const bool allOnOneLine)

@ -46,9 +46,8 @@ class JUCE_API DynamicObject : public ReferenceCountedObject
public: public:
//============================================================================== //==============================================================================
DynamicObject(); DynamicObject();
DynamicObject (const DynamicObject&);
/** Destructor. */ ~DynamicObject();
virtual ~DynamicObject();
typedef ReferenceCountedObjectPtr<DynamicObject> Ptr; typedef ReferenceCountedObjectPtr<DynamicObject> Ptr;
@ -104,6 +103,9 @@ public:
/** Returns the NamedValueSet that holds the object's properties. */ /** Returns the NamedValueSet that holds the object's properties. */
NamedValueSet& getProperties() noexcept { return properties; } NamedValueSet& getProperties() noexcept { return properties; }
/** Calls var::clone() on all the properties that this object contains. */
void cloneAllProperties();
//============================================================================== //==============================================================================
/** Returns a clone of this object. /** Returns a clone of this object.
The default implementation of this method just returns a new DynamicObject The default implementation of this method just returns a new DynamicObject

@ -60,7 +60,7 @@ struct DefaultHashFunctions
@code @code
struct MyHashGenerator struct MyHashGenerator
{ {
int generateHash (MyKeyType key, int upperLimit) int generateHash (MyKeyType key, int upperLimit) const
{ {
// The function must return a value 0 <= x < upperLimit // The function must return a value 0 <= x < upperLimit
return someFunctionOfMyKeyType (key) % upperLimit; return someFunctionOfMyKeyType (key) % upperLimit;

@ -30,7 +30,7 @@ NamedValueSet::NamedValue::NamedValue() noexcept
{ {
} }
inline NamedValueSet::NamedValue::NamedValue (const Identifier n, const var& v) inline NamedValueSet::NamedValue::NamedValue (Identifier n, const var& v)
: name (n), value (v) : name (n), value (v)
{ {
} }
@ -49,22 +49,22 @@ NamedValueSet::NamedValue& NamedValueSet::NamedValue::operator= (const NamedValu
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
NamedValueSet::NamedValue::NamedValue (NamedValue&& other) noexcept NamedValueSet::NamedValue::NamedValue (NamedValue&& other) noexcept
: nextListItem (static_cast <LinkedListPointer<NamedValue>&&> (other.nextListItem)), : nextListItem (static_cast<LinkedListPointer<NamedValue>&&> (other.nextListItem)),
name (static_cast <Identifier&&> (other.name)), name (static_cast<Identifier&&> (other.name)),
value (static_cast <var&&> (other.value)) value (static_cast<var&&> (other.value))
{ {
} }
inline NamedValueSet::NamedValue::NamedValue (const Identifier n, var&& v) inline NamedValueSet::NamedValue::NamedValue (Identifier n, var&& v)
: name (n), value (static_cast <var&&> (v)) : name (n), value (static_cast<var&&> (v))
{ {
} }
NamedValueSet::NamedValue& NamedValueSet::NamedValue::operator= (NamedValue&& other) noexcept NamedValueSet::NamedValue& NamedValueSet::NamedValue::operator= (NamedValue&& other) noexcept
{ {
nextListItem = static_cast <LinkedListPointer<NamedValue>&&> (other.nextListItem); nextListItem = static_cast<LinkedListPointer<NamedValue>&&> (other.nextListItem);
name = static_cast <Identifier&&> (other.name); name = static_cast<Identifier&&> (other.name);
value = static_cast <var&&> (other.value); value = static_cast<var&&> (other.value);
return *this; return *this;
} }
#endif #endif
@ -141,7 +141,7 @@ int NamedValueSet::size() const noexcept
return values.size(); return values.size();
} }
const var& NamedValueSet::operator[] (const Identifier name) const const var& NamedValueSet::operator[] (Identifier name) const
{ {
for (NamedValue* i = values; i != nullptr; i = i->nextListItem) for (NamedValue* i = values; i != nullptr; i = i->nextListItem)
if (i->name == name) if (i->name == name)
@ -150,7 +150,7 @@ const var& NamedValueSet::operator[] (const Identifier name) const
return var::null; return var::null;
} }
var NamedValueSet::getWithDefault (const Identifier name, const var& defaultReturnValue) const var NamedValueSet::getWithDefault (Identifier name, const var& defaultReturnValue) const
{ {
if (const var* const v = getVarPointer (name)) if (const var* const v = getVarPointer (name))
return *v; return *v;
@ -158,7 +158,7 @@ var NamedValueSet::getWithDefault (const Identifier name, const var& defaultRetu
return defaultReturnValue; return defaultReturnValue;
} }
var* NamedValueSet::getVarPointer (const Identifier name) const noexcept var* NamedValueSet::getVarPointer (Identifier name) const noexcept
{ {
for (NamedValue* i = values; i != nullptr; i = i->nextListItem) for (NamedValue* i = values; i != nullptr; i = i->nextListItem)
if (i->name == name) if (i->name == name)
@ -168,7 +168,7 @@ var* NamedValueSet::getVarPointer (const Identifier name) const noexcept
} }
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
bool NamedValueSet::set (const Identifier name, var&& newValue) bool NamedValueSet::set (Identifier name, var&& newValue)
{ {
LinkedListPointer<NamedValue>* i = &values; LinkedListPointer<NamedValue>* i = &values;
@ -193,7 +193,7 @@ bool NamedValueSet::set (const Identifier name, var&& newValue)
} }
#endif #endif
bool NamedValueSet::set (const Identifier name, const var& newValue) bool NamedValueSet::set (Identifier name, const var& newValue)
{ {
LinkedListPointer<NamedValue>* i = &values; LinkedListPointer<NamedValue>* i = &values;
@ -217,12 +217,27 @@ bool NamedValueSet::set (const Identifier name, const var& newValue)
return true; return true;
} }
bool NamedValueSet::contains (const Identifier name) const bool NamedValueSet::contains (Identifier name) const
{ {
return getVarPointer (name) != nullptr; return getVarPointer (name) != nullptr;
} }
bool NamedValueSet::remove (const Identifier name) int NamedValueSet::indexOf (Identifier name) const noexcept
{
int index = 0;
for (NamedValue* i = values; i != nullptr; i = i->nextListItem)
{
if (i->name == name)
return index;
++index;
}
return -1;
}
bool NamedValueSet::remove (Identifier name)
{ {
LinkedListPointer<NamedValue>* i = &values; LinkedListPointer<NamedValue>* i = &values;
@ -245,7 +260,7 @@ bool NamedValueSet::remove (const Identifier name)
return false; return false;
} }
const Identifier NamedValueSet::getName (const int index) const Identifier NamedValueSet::getName (const int index) const
{ {
const NamedValue* const v = values[index]; const NamedValue* const v = values[index];
jassert (v != nullptr); jassert (v != nullptr);
@ -268,7 +283,7 @@ void NamedValueSet::setFromXmlAttributes (const XmlElement& xml)
for (int i = 0; i < numAtts; ++i) for (int i = 0; i < numAtts; ++i)
{ {
const String& name = xml.getAttributeName (i); const String& name = xml.getAttributeName (i);
const String& value = xml.getAttributeValue (i); const String& value = xml.getAttributeValue (i);
if (name.startsWith ("base64:")) if (name.startsWith ("base64:"))

@ -43,21 +43,21 @@ public:
NamedValueSet() noexcept; NamedValueSet() noexcept;
/** Creates a copy of another set. */ /** Creates a copy of another set. */
NamedValueSet (const NamedValueSet& other); NamedValueSet (const NamedValueSet&);
/** Replaces this set with a copy of another set. */ /** Replaces this set with a copy of another set. */
NamedValueSet& operator= (const NamedValueSet& other); NamedValueSet& operator= (const NamedValueSet&);
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
NamedValueSet (NamedValueSet&& other) noexcept; NamedValueSet (NamedValueSet&&) noexcept;
NamedValueSet& operator= (NamedValueSet&& other) noexcept; NamedValueSet& operator= (NamedValueSet&&) noexcept;
#endif #endif
/** Destructor. */ /** Destructor. */
~NamedValueSet(); ~NamedValueSet();
bool operator== (const NamedValueSet& other) const; bool operator== (const NamedValueSet&) const;
bool operator!= (const NamedValueSet& other) const; bool operator!= (const NamedValueSet&) const;
//============================================================================== //==============================================================================
/** Returns the total number of values that the set contains. */ /** Returns the total number of values that the set contains. */
@ -67,46 +67,49 @@ public:
If the name isn't found, this will return a void variant. If the name isn't found, this will return a void variant.
@see getProperty @see getProperty
*/ */
const var& operator[] (const Identifier name) const; const var& operator[] (Identifier name) const;
/** Tries to return the named value, but if no such value is found, this will /** Tries to return the named value, but if no such value is found, this will
instead return the supplied default value. instead return the supplied default value.
*/ */
var getWithDefault (const Identifier name, const var& defaultReturnValue) const; var getWithDefault (Identifier name, const var& defaultReturnValue) const;
/** Changes or adds a named value. /** Changes or adds a named value.
@returns true if a value was changed or added; false if the @returns true if a value was changed or added; false if the
value was already set the the value passed-in. value was already set the the value passed-in.
*/ */
bool set (const Identifier name, const var& newValue); bool set (Identifier name, const var& newValue);
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
/** Changes or adds a named value. /** Changes or adds a named value.
@returns true if a value was changed or added; false if the @returns true if a value was changed or added; false if the
value was already set the the value passed-in. value was already set the the value passed-in.
*/ */
bool set (const Identifier name, var&& newValue); bool set (Identifier name, var&& newValue);
#endif #endif
/** Returns true if the set contains an item with the specified name. */ /** Returns true if the set contains an item with the specified name. */
bool contains (const Identifier name) const; bool contains (Identifier name) const;
/** Removes a value from the set. /** Removes a value from the set.
@returns true if a value was removed; false if there was no value @returns true if a value was removed; false if there was no value
with the name that was given. with the name that was given.
*/ */
bool remove (const Identifier name); bool remove (Identifier name);
/** Returns the name of the value at a given index. /** Returns the name of the value at a given index.
The index must be between 0 and size() - 1. The index must be between 0 and size() - 1.
*/ */
const Identifier getName (int index) const; Identifier getName (int index) const;
/** Returns the value of the item at a given index. /** Returns the value of the item at a given index.
The index must be between 0 and size() - 1. The index must be between 0 and size() - 1.
*/ */
const var& getValueAt (int index) const; const var& getValueAt (int index) const;
/** Returns the index of the given name, or -1 if it's not found. */
int indexOf (Identifier name) const noexcept;
/** Removes all values. */ /** Removes all values. */
void clear(); void clear();
@ -117,7 +120,7 @@ public:
Do not use this method unless you really need access to the internal var object Do not use this method unless you really need access to the internal var object
for some reason - for normal reading and writing always prefer operator[]() and set(). for some reason - for normal reading and writing always prefer operator[]() and set().
*/ */
var* getVarPointer (const Identifier name) const noexcept; var* getVarPointer (Identifier name) const noexcept;
//============================================================================== //==============================================================================
/** Sets properties to the values of all of an XML element's attributes. */ /** Sets properties to the values of all of an XML element's attributes. */
@ -135,14 +138,14 @@ private:
public: public:
NamedValue() noexcept; NamedValue() noexcept;
NamedValue (const NamedValue&); NamedValue (const NamedValue&);
NamedValue (const Identifier name, const var& value); NamedValue (Identifier, const var&);
NamedValue& operator= (const NamedValue&); NamedValue& operator= (const NamedValue&);
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
NamedValue (NamedValue&&) noexcept; NamedValue (NamedValue&&) noexcept;
NamedValue (const Identifier name, var&& value); NamedValue (Identifier, var&&);
NamedValue& operator= (NamedValue&&) noexcept; NamedValue& operator= (NamedValue&&) noexcept;
#endif #endif
bool operator== (const NamedValue& other) const noexcept; bool operator== (const NamedValue&) const noexcept;
LinkedListPointer<NamedValue> nextListItem; LinkedListPointer<NamedValue> nextListItem;
Identifier name; Identifier name;

@ -32,16 +32,16 @@
//============================================================================== //==============================================================================
/** /**
Searches through a the files in a directory, returning each file that is found. Searches through the files in a directory, returning each file that is found.
A DirectoryIterator will search through a directory and its subdirectories using A DirectoryIterator will search through a directory and its subdirectories using
a wildcard filepattern match. a wildcard filepattern match.
If you may be finding a large number of files, this is better than If you may be scanning a large number of files, it's usually smarter to use this
using File::findChildFiles() because it doesn't block while it finds them class than File::findChildFiles() because it allows you to stop at any time, rather
all, and this is more memory-efficient. than having to wait for the entire scan to finish before getting the results.
It can also guess how far it's got using a wildly inaccurate algorithm. It also provides an estimate of its progress, using a (highly inaccurate!) algorithm.
*/ */
class JUCE_API DirectoryIterator class JUCE_API DirectoryIterator
{ {

@ -101,7 +101,7 @@ public:
/** Merges another search path into this one. /** Merges another search path into this one.
This will remove any duplicate directories. This will remove any duplicate directories.
*/ */
void addPath (const FileSearchPath& other); void addPath (const FileSearchPath&);
/** Removes any directories that are actually subdirectories of one of the other directories in the search path. /** Removes any directories that are actually subdirectories of one of the other directories in the search path.

@ -100,7 +100,6 @@ public:
return Result::ok(); return Result::ok();
} }
private:
static Result parseAny (String::CharPointerType& t, var& result) static Result parseAny (String::CharPointerType& t, var& result)
{ {
t = t.findEndOfWhitespace(); t = t.findEndOfWhitespace();
@ -160,6 +159,7 @@ private:
return createFail ("Syntax error", &t); return createFail ("Syntax error", &t);
} }
private:
static Result createFail (const char* const message, const String::CharPointerType* location = nullptr) static Result createFail (const char* const message, const String::CharPointerType* location = nullptr)
{ {
String m (message); String m (message);
@ -460,51 +460,6 @@ public:
out << ']'; out << ']';
} }
/* static void writeObject (OutputStream& out, DynamicObject& object,
const int indentLevel, const bool allOnOneLine)
{
NamedValueSet& props = object.getProperties();
out << '{';
if (! allOnOneLine)
out << newLine;
LinkedListPointer<NamedValueSet::NamedValue>* i = &(props.values);
for (;;)
{
NamedValueSet::NamedValue* const v = i->get();
if (v == nullptr)
break;
if (! allOnOneLine)
writeSpaces (out, indentLevel + indentSize);
out << '"';
writeString (out, v->name);
out << "\": ";
write (out, v->value, indentLevel + indentSize, allOnOneLine);
if (v->nextListItem.get() != nullptr)
{
if (allOnOneLine)
out << ", ";
else
out << ',' << newLine;
}
else if (! allOnOneLine)
out << newLine;
i = &(v->nextListItem);
}
if (! allOnOneLine)
writeSpaces (out, indentLevel);
out << '}';
}*/
enum { indentSize = 2 }; enum { indentSize = 2 };
}; };
@ -513,7 +468,17 @@ var JSON::parse (const String& text)
{ {
var result; var result;
if (! JSONParser::parseObjectOrArray (text.getCharPointer(), result)) if (! parse (text, result))
result = var();
return result;
}
var JSON::fromString (StringRef text)
{
var result;
if (! JSONParser::parseAny (text.text, result))
result = var(); result = var();
return result; return result;

@ -53,6 +53,10 @@ public:
If you're not interested in the error message, you can use one of the other If you're not interested in the error message, you can use one of the other
shortcut parse methods, which simply return a var::null if the parsing fails. shortcut parse methods, which simply return a var::null if the parsing fails.
Note that this will only parse valid JSON, which means that the item given must
be either an object or an array definition. If you want to also be able to parse
any kind of primitive JSON object, use the fromString() method.
*/ */
static Result parse (const String& text, var& parsedResult); static Result parse (const String& text, var& parsedResult);
@ -60,6 +64,10 @@ public:
If the parsing fails, this simply returns var::null - if you need to find out more If the parsing fails, this simply returns var::null - if you need to find out more
detail about the parse error, use the alternative parse() method which returns a Result. detail about the parse error, use the alternative parse() method which returns a Result.
Note that this will only parse valid JSON, which means that the item given must
be either an object or an array definition. If you want to also be able to parse
any kind of primitive JSON object, use the fromString() method.
*/ */
static var parse (const String& text); static var parse (const String& text);
@ -94,6 +102,13 @@ public:
static String toString (const var& objectToFormat, static String toString (const var& objectToFormat,
bool allOnOneLine = false); bool allOnOneLine = false);
/** Parses a string that was created with the toString() method.
This is slightly different to the parse() methods because they will reject primitive
values and only accept array or object definitions, whereas this method will handle
either.
*/
static var fromString (StringRef);
/** Writes a JSON-formatted representation of the var object to the given stream. /** Writes a JSON-formatted representation of the var object to the given stream.
If allOnOneLine is true, the result will be compacted into a single line of text If allOnOneLine is true, the result will be compacted into a single line of text
with no carriage-returns. If false, it will be laid-out in a more human-readable format. with no carriage-returns. If false, it will be laid-out in a more human-readable format.
@ -106,7 +121,7 @@ public:
/** Returns a version of a string with any extended characters escaped. */ /** Returns a version of a string with any extended characters escaped. */
static String escapeString (StringRef); static String escapeString (StringRef);
/** Parses a quoted string in JSON format, returning the un-escaped result in the /** Parses a quoted string-literal in JSON format, returning the un-escaped result in the
result parameter, and an error message in case the content was illegal. result parameter, and an error message in case the content was illegal.
This advances the text parameter, leaving it positioned after the closing quote. This advances the text parameter, leaving it positioned after the closing quote.
*/ */

@ -151,7 +151,6 @@ namespace juce
#include "text/juce_StringPairArray.cpp" #include "text/juce_StringPairArray.cpp"
#include "text/juce_StringPool.cpp" #include "text/juce_StringPool.cpp"
#include "text/juce_TextDiff.cpp" #include "text/juce_TextDiff.cpp"
#include "threads/juce_ChildProcess.cpp"
#include "threads/juce_ReadWriteLock.cpp" #include "threads/juce_ReadWriteLock.cpp"
#include "threads/juce_Thread.cpp" #include "threads/juce_Thread.cpp"
#include "threads/juce_ThreadPool.cpp" #include "threads/juce_ThreadPool.cpp"
@ -165,6 +164,8 @@ namespace juce
#include "zip/juce_GZIPDecompressorInputStream.cpp" #include "zip/juce_GZIPDecompressorInputStream.cpp"
#include "zip/juce_GZIPCompressorOutputStream.cpp" #include "zip/juce_GZIPCompressorOutputStream.cpp"
#include "zip/juce_ZipFile.cpp" #include "zip/juce_ZipFile.cpp"
#include "files/juce_FileFilter.cpp"
#include "files/juce_WildcardFileFilter.cpp"
//============================================================================== //==============================================================================
#if JUCE_MAC || JUCE_IOS #if JUCE_MAC || JUCE_IOS
@ -216,6 +217,7 @@ namespace juce
#endif #endif
#include "threads/juce_ChildProcess.cpp"
#include "threads/juce_HighResolutionTimer.cpp" #include "threads/juce_HighResolutionTimer.cpp"
} }

@ -232,6 +232,8 @@ extern JUCE_API void JUCE_CALLTYPE logAssertion (const char* file, int line) noe
#include "files/juce_FileSearchPath.h" #include "files/juce_FileSearchPath.h"
#include "files/juce_MemoryMappedFile.h" #include "files/juce_MemoryMappedFile.h"
#include "files/juce_TemporaryFile.h" #include "files/juce_TemporaryFile.h"
#include "files/juce_FileFilter.h"
#include "files/juce_WildcardFileFilter.h"
#include "streams/juce_FileInputSource.h" #include "streams/juce_FileInputSource.h"
#include "logging/juce_FileLogger.h" #include "logging/juce_FileLogger.h"
#include "javascript/juce_JSON.h" #include "javascript/juce_JSON.h"

@ -1,7 +1,7 @@
{ {
"id": "juce_core", "id": "juce_core",
"name": "JUCE core classes", "name": "JUCE core classes",
"version": "3.0.1", "version": "3.0.3",
"description": "The essential set of basic JUCE classes, as required by all the other JUCE modules. Includes text, container, memory, threading and i/o functionality.", "description": "The essential set of basic JUCE classes, as required by all the other JUCE modules. Includes text, container, memory, threading and i/o functionality.",
"website": "http://www.juce.com/juce", "website": "http://www.juce.com/juce",
"license": "ISC Permissive", "license": "ISC Permissive",

@ -65,11 +65,11 @@ public:
BigInteger (int64 value); BigInteger (int64 value);
/** Creates a copy of another BigInteger. */ /** Creates a copy of another BigInteger. */
BigInteger (const BigInteger& other); BigInteger (const BigInteger&);
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
BigInteger (BigInteger&& other) noexcept; BigInteger (BigInteger&&) noexcept;
BigInteger& operator= (BigInteger&& other) noexcept; BigInteger& operator= (BigInteger&&) noexcept;
#endif #endif
/** Destructor. */ /** Destructor. */
@ -77,10 +77,10 @@ public:
//============================================================================== //==============================================================================
/** Copies another BigInteger onto this one. */ /** Copies another BigInteger onto this one. */
BigInteger& operator= (const BigInteger& other); BigInteger& operator= (const BigInteger&);
/** Swaps the internal contents of this with another object. */ /** Swaps the internal contents of this with another object. */
void swapWith (BigInteger& other) noexcept; void swapWith (BigInteger&) noexcept;
//============================================================================== //==============================================================================
/** Returns the value of a specified bit in the number. /** Returns the value of a specified bit in the number.
@ -183,14 +183,14 @@ public:
//============================================================================== //==============================================================================
// All the standard arithmetic ops... // All the standard arithmetic ops...
BigInteger& operator+= (const BigInteger& other); BigInteger& operator+= (const BigInteger&);
BigInteger& operator-= (const BigInteger& other); BigInteger& operator-= (const BigInteger&);
BigInteger& operator*= (const BigInteger& other); BigInteger& operator*= (const BigInteger&);
BigInteger& operator/= (const BigInteger& other); BigInteger& operator/= (const BigInteger&);
BigInteger& operator|= (const BigInteger& other); BigInteger& operator|= (const BigInteger&);
BigInteger& operator&= (const BigInteger& other); BigInteger& operator&= (const BigInteger&);
BigInteger& operator^= (const BigInteger& other); BigInteger& operator^= (const BigInteger&);
BigInteger& operator%= (const BigInteger& other); BigInteger& operator%= (const BigInteger&);
BigInteger& operator<<= (int numBitsToShift); BigInteger& operator<<= (int numBitsToShift);
BigInteger& operator>>= (int numBitsToShift); BigInteger& operator>>= (int numBitsToShift);
BigInteger& operator++(); BigInteger& operator++();
@ -199,23 +199,23 @@ public:
BigInteger operator-- (int); BigInteger operator-- (int);
BigInteger operator-() const; BigInteger operator-() const;
BigInteger operator+ (const BigInteger& other) const; BigInteger operator+ (const BigInteger&) const;
BigInteger operator- (const BigInteger& other) const; BigInteger operator- (const BigInteger&) const;
BigInteger operator* (const BigInteger& other) const; BigInteger operator* (const BigInteger&) const;
BigInteger operator/ (const BigInteger& other) const; BigInteger operator/ (const BigInteger&) const;
BigInteger operator| (const BigInteger& other) const; BigInteger operator| (const BigInteger&) const;
BigInteger operator& (const BigInteger& other) const; BigInteger operator& (const BigInteger&) const;
BigInteger operator^ (const BigInteger& other) const; BigInteger operator^ (const BigInteger&) const;
BigInteger operator% (const BigInteger& other) const; BigInteger operator% (const BigInteger&) const;
BigInteger operator<< (int numBitsToShift) const; BigInteger operator<< (int numBitsToShift) const;
BigInteger operator>> (int numBitsToShift) const; BigInteger operator>> (int numBitsToShift) const;
bool operator== (const BigInteger& other) const noexcept; bool operator== (const BigInteger&) const noexcept;
bool operator!= (const BigInteger& other) const noexcept; bool operator!= (const BigInteger&) const noexcept;
bool operator< (const BigInteger& other) const noexcept; bool operator< (const BigInteger&) const noexcept;
bool operator<= (const BigInteger& other) const noexcept; bool operator<= (const BigInteger&) const noexcept;
bool operator> (const BigInteger& other) const noexcept; bool operator> (const BigInteger&) const noexcept;
bool operator>= (const BigInteger& other) const noexcept; bool operator>= (const BigInteger&) const noexcept;
//============================================================================== //==============================================================================
/** Does a signed comparison of two BigIntegers. /** Does a signed comparison of two BigIntegers.
@ -243,8 +243,7 @@ public:
*/ */
void divideBy (const BigInteger& divisor, BigInteger& remainder); void divideBy (const BigInteger& divisor, BigInteger& remainder);
/** Returns the largest value that will divide both this value and the one passed-in. /** Returns the largest value that will divide both this value and the one passed-in. */
*/
BigInteger findGreatestCommonDivisor (BigInteger other) const; BigInteger findGreatestCommonDivisor (BigInteger other) const;
/** Performs a combined exponent and modulo operation. /** Performs a combined exponent and modulo operation.
@ -310,12 +309,12 @@ public:
private: private:
//============================================================================== //==============================================================================
HeapBlock <uint32> values; HeapBlock<uint32> values;
size_t numValues; size_t numValues;
int highestBit; int highestBit;
bool negative; bool negative;
void ensureSize (size_t numVals); void ensureSize (size_t);
void shiftLeft (int bits, int startBit); void shiftLeft (int bits, int startBit);
void shiftRight (int bits, int startBit); void shiftRight (int bits, int startBit);

@ -188,12 +188,10 @@ struct Expression::Helpers
if (input != left && input != right) if (input != left && input != right)
return TermPtr(); return TermPtr();
const Term* const dest = findDestinationFor (topLevelTerm, this); if (const Term* const dest = findDestinationFor (topLevelTerm, this))
return dest->createTermToEvaluateInput (scope, this, overallTarget, topLevelTerm);
if (dest == nullptr)
return new Constant (overallTarget, false);
return dest->createTermToEvaluateInput (scope, this, overallTarget, topLevelTerm); return new Constant (overallTarget, false);
} }
}; };

@ -59,14 +59,14 @@ public:
explicit Expression (double constant); explicit Expression (double constant);
/** Creates a copy of an expression. */ /** Creates a copy of an expression. */
Expression (const Expression& other); Expression (const Expression&);
/** Copies another expression. */ /** Copies another expression. */
Expression& operator= (const Expression& other); Expression& operator= (const Expression&);
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
Expression (Expression&& other) noexcept; Expression (Expression&&) noexcept;
Expression& operator= (Expression&& other) noexcept; Expression& operator= (Expression&&) noexcept;
#endif #endif
/** Creates an expression by parsing a string. /** Creates an expression by parsing a string.
@ -78,14 +78,14 @@ public:
/** Returns a string version of the expression. */ /** Returns a string version of the expression. */
String toString() const; String toString() const;
/** Returns an expression which is an addtion operation of two existing expressions. */ /** Returns an expression which is an addition operation of two existing expressions. */
Expression operator+ (const Expression& other) const; Expression operator+ (const Expression&) const;
/** Returns an expression which is a subtraction operation of two existing expressions. */ /** Returns an expression which is a subtraction operation of two existing expressions. */
Expression operator- (const Expression& other) const; Expression operator- (const Expression&) const;
/** Returns an expression which is a multiplication operation of two existing expressions. */ /** Returns an expression which is a multiplication operation of two existing expressions. */
Expression operator* (const Expression& other) const; Expression operator* (const Expression&) const;
/** Returns an expression which is a division operation of two existing expressions. */ /** Returns an expression which is a division operation of two existing expressions. */
Expression operator/ (const Expression& other) const; Expression operator/ (const Expression&) const;
/** Returns an expression which performs a negation operation on an existing expression. */ /** Returns an expression which performs a negation operation on an existing expression. */
Expression operator-() const; Expression operator-() const;

@ -87,6 +87,10 @@ public:
LocalRef<jobject> responseHeaderBuffer (env->NewObject (StringBuffer, StringBuffer.constructor)); LocalRef<jobject> responseHeaderBuffer (env->NewObject (StringBuffer, StringBuffer.constructor));
// Annoyingly, the android HTTP functions will choke on this call if you try to do it on the message
// thread. You'll need to move your networking code to a background thread to keep it happy..
jassert (Thread::getCurrentThread() != nullptr);
stream = GlobalRef (env->CallStaticObjectMethod (JuceAppActivity, stream = GlobalRef (env->CallStaticObjectMethod (JuceAppActivity,
JuceAppActivity.createHTTPStream, JuceAppActivity.createHTTPStream,
javaString (address).get(), javaString (address).get(),

@ -194,7 +194,12 @@ bool NamedPipe::openInternal (const String& pipeName, const bool createPipe)
pimpl = new Pimpl (File::getSpecialLocation (File::tempDirectory) pimpl = new Pimpl (File::getSpecialLocation (File::tempDirectory)
.getChildFile (File::createLegalFileName (pipeName)).getFullPathName(), createPipe); .getChildFile (File::createLegalFileName (pipeName)).getFullPathName(), createPipe);
#else #else
pimpl = new Pimpl ("/tmp/" + File::createLegalFileName (pipeName), createPipe); String file (pipeName);
if (! File::isAbsolutePath (file))
file = "/tmp/" + File::createLegalFileName (file);
pimpl = new Pimpl (file, createPipe);
#endif #endif
if (createPipe && ! pimpl->createFifos()) if (createPipe && ! pimpl->createFifos())

@ -1053,7 +1053,7 @@ public:
close (pipeHandle); close (pipeHandle);
} }
bool isRunning() const bool isRunning() const noexcept
{ {
if (childPID != 0) if (childPID != 0)
{ {
@ -1065,7 +1065,7 @@ public:
return false; return false;
} }
int read (void* const dest, const int numBytes) int read (void* const dest, const int numBytes) noexcept
{ {
jassert (dest != nullptr); jassert (dest != nullptr);
@ -1082,11 +1082,25 @@ public:
return 0; return 0;
} }
bool killProcess() const bool killProcess() const noexcept
{ {
return ::kill (childPID, SIGKILL) == 0; return ::kill (childPID, SIGKILL) == 0;
} }
uint32 getExitCode() const noexcept
{
if (childPID != 0)
{
int childState = 0;
const int pid = waitpid (childPID, &childState, WNOHANG);
if (pid >= 0 && WIFEXITED (childState))
return WEXITSTATUS (childState);
}
return 0;
}
int childPID; int childPID;
private: private:
@ -1114,21 +1128,6 @@ bool ChildProcess::start (const StringArray& args, int streamFlags)
return activeProcess != nullptr; return activeProcess != nullptr;
} }
bool ChildProcess::isRunning() const
{
return activeProcess != nullptr && activeProcess->isRunning();
}
int ChildProcess::readProcessOutput (void* dest, int numBytes)
{
return activeProcess != nullptr ? activeProcess->read (dest, numBytes) : 0;
}
bool ChildProcess::kill()
{
return activeProcess == nullptr || activeProcess->killProcess();
}
//============================================================================== //==============================================================================
struct HighResolutionTimer::Pimpl struct HighResolutionTimer::Pimpl
{ {

@ -482,12 +482,12 @@ public:
CloseHandle (writePipe); CloseHandle (writePipe);
} }
bool isRunning() const bool isRunning() const noexcept
{ {
return WaitForSingleObject (processInfo.hProcess, 0) != WAIT_OBJECT_0; return WaitForSingleObject (processInfo.hProcess, 0) != WAIT_OBJECT_0;
} }
int read (void* dest, int numNeeded) const int read (void* dest, int numNeeded) const noexcept
{ {
int total = 0; int total = 0;
@ -522,11 +522,18 @@ public:
return total; return total;
} }
bool killProcess() const bool killProcess() const noexcept
{ {
return TerminateProcess (processInfo.hProcess, 0) != FALSE; return TerminateProcess (processInfo.hProcess, 0) != FALSE;
} }
uint32 getExitCode() const noexcept
{
DWORD exitCode = 0;
GetExitCodeProcess (processInfo.hProcess, &exitCode);
return (uint32) exitCode;
}
bool ok; bool ok;
private: private:
@ -551,21 +558,6 @@ bool ChildProcess::start (const StringArray& args, int streamFlags)
return start (args.joinIntoString (" "), streamFlags); return start (args.joinIntoString (" "), streamFlags);
} }
bool ChildProcess::isRunning() const
{
return activeProcess != nullptr && activeProcess->isRunning();
}
int ChildProcess::readProcessOutput (void* dest, int numBytes)
{
return activeProcess != nullptr ? activeProcess->read (dest, numBytes) : 0;
}
bool ChildProcess::kill()
{
return activeProcess == nullptr || activeProcess->killProcess();
}
//============================================================================== //==============================================================================
struct HighResolutionTimer::Pimpl struct HighResolutionTimer::Pimpl
{ {

@ -51,10 +51,10 @@ public:
MACAddress(); MACAddress();
/** Creates a copy of another address. */ /** Creates a copy of another address. */
MACAddress (const MACAddress& other); MACAddress (const MACAddress&);
/** Creates a copy of another address. */ /** Creates a copy of another address. */
MACAddress& operator= (const MACAddress& other); MACAddress& operator= (const MACAddress&);
/** Creates an address from 6 bytes. */ /** Creates an address from 6 bytes. */
explicit MACAddress (const uint8 bytes[6]); explicit MACAddress (const uint8 bytes[6]);
@ -75,8 +75,8 @@ public:
/** Returns true if this address is null (00-00-00-00-00-00). */ /** Returns true if this address is null (00-00-00-00-00-00). */
bool isNull() const noexcept; bool isNull() const noexcept;
bool operator== (const MACAddress& other) const noexcept; bool operator== (const MACAddress&) const noexcept;
bool operator!= (const MACAddress& other) const noexcept; bool operator!= (const MACAddress&) const noexcept;
//============================================================================== //==============================================================================
private: private:

@ -174,12 +174,16 @@ bool OutputStream::writeDoubleBigEndian (double value)
bool OutputStream::writeString (const String& text) bool OutputStream::writeString (const String& text)
{ {
#if (JUCE_STRING_UTF_TYPE == 8)
return write (text.toRawUTF8(), text.getNumBytesAsUTF8() + 1);
#else
// (This avoids using toUTF8() to prevent the memory bloat that it would leave behind // (This avoids using toUTF8() to prevent the memory bloat that it would leave behind
// if lots of large, persistent strings were to be written to streams). // if lots of large, persistent strings were to be written to streams).
const size_t numBytes = text.getNumBytesAsUTF8() + 1; const size_t numBytes = text.getNumBytesAsUTF8() + 1;
HeapBlock<char> temp (numBytes); HeapBlock<char> temp (numBytes);
text.copyToUTF8 (temp, numBytes); text.copyToUTF8 (temp, numBytes);
return write (temp, numBytes); return write (temp, numBytes);
#endif
} }
bool OutputStream::writeText (const String& text, const bool asUTF16, bool OutputStream::writeText (const String& text, const bool asUTF16,

@ -36,7 +36,7 @@
*/ */
#define JUCE_MAJOR_VERSION 3 #define JUCE_MAJOR_VERSION 3
#define JUCE_MINOR_VERSION 0 #define JUCE_MINOR_VERSION 0
#define JUCE_BUILDNUMBER 1 #define JUCE_BUILDNUMBER 3
/** Current Juce version number. /** Current Juce version number.

@ -171,11 +171,12 @@ public:
while (--numExtraValues >= 0) while (--numExtraValues >= 0)
{ {
const uint32 nextByte = (uint32) (uint8) *data++; const uint32 nextByte = (uint32) (uint8) *data;
if ((nextByte & 0xc0) != 0x80) if ((nextByte & 0xc0) != 0x80)
break; break;
++data;
n <<= 6; n <<= 6;
n |= (nextByte & 0x3f); n |= (nextByte & 0x3f);
} }
@ -248,16 +249,8 @@ public:
if ((n & 0x80) != 0) if ((n & 0x80) != 0)
{ {
uint32 bit = 0x40; while ((*d & 0xc0) == 0x80)
while ((n & bit) != 0)
{
++d; ++d;
bit >>= 1;
if (bit == 0)
break; // illegal utf-8 sequence
}
} }
else if (n == 0) else if (n == 0)
break; break;

@ -36,6 +36,21 @@ LocalisedStrings::LocalisedStrings (const File& fileToLoad, bool ignoreCase)
loadFromText (fileToLoad.loadFileAsString(), ignoreCase); loadFromText (fileToLoad.loadFileAsString(), ignoreCase);
} }
LocalisedStrings::LocalisedStrings (const LocalisedStrings& other)
: languageName (other.languageName), countryCodes (other.countryCodes),
translations (other.translations), fallback (createCopyIfNotNull (other.fallback.get()))
{
}
LocalisedStrings& LocalisedStrings::operator= (const LocalisedStrings& other)
{
languageName = other.languageName;
countryCodes = other.countryCodes;
translations = other.translations;
fallback = createCopyIfNotNull (other.fallback.get());
return *this;
}
LocalisedStrings::~LocalisedStrings() LocalisedStrings::~LocalisedStrings()
{ {
} }

@ -82,16 +82,17 @@ public:
When you create one of these, you can call setCurrentMappings() to make it When you create one of these, you can call setCurrentMappings() to make it
the set of mappings that the system's using. the set of mappings that the system's using.
*/ */
LocalisedStrings (const String& fileContents, LocalisedStrings (const String& fileContents, bool ignoreCaseOfKeys);
bool ignoreCaseOfKeys);
/** Creates a set of translations from a file. /** Creates a set of translations from a file.
When you create one of these, you can call setCurrentMappings() to make it When you create one of these, you can call setCurrentMappings() to make it
the set of mappings that the system's using. the set of mappings that the system's using.
*/ */
LocalisedStrings (const File& fileToLoad, LocalisedStrings (const File& fileToLoad, bool ignoreCaseOfKeys);
bool ignoreCaseOfKeys);
LocalisedStrings (const LocalisedStrings&);
LocalisedStrings& operator= (const LocalisedStrings&);
/** Destructor. */ /** Destructor. */
~LocalisedStrings(); ~LocalisedStrings();
@ -100,7 +101,7 @@ public:
/** Selects the current set of mappings to be used by the system. /** Selects the current set of mappings to be used by the system.
The object you pass in will be automatically deleted when no longer needed, so The object you pass in will be automatically deleted when no longer needed, so
don't keep a pointer to it. You can also pass in zero to remove the current don't keep a pointer to it. You can also pass in nullptr to remove the current
mappings. mappings.
See also the TRANS() macro, which uses the current set to do its translation. See also the TRANS() macro, which uses the current set to do its translation.
@ -195,6 +196,7 @@ private:
StringArray countryCodes; StringArray countryCodes;
StringPairArray translations; StringPairArray translations;
ScopedPointer<LocalisedStrings> fallback; ScopedPointer<LocalisedStrings> fallback;
friend struct ContainerDeletePolicy<LocalisedStrings>;
void loadFromText (const String&, bool ignoreCase); void loadFromText (const String&, bool ignoreCase);

@ -313,6 +313,10 @@ String::String (const char* const t)
you use UTF-8 with escape characters in your source code to represent extended characters, you use UTF-8 with escape characters in your source code to represent extended characters,
because there's no other way to represent these strings in a way that isn't dependent on because there's no other way to represent these strings in a way that isn't dependent on
the compiler, source code editor and platform. the compiler, source code editor and platform.
Note that the Introjucer has a handy string literal generator utility that will convert
any unicode string to a valid C++ string literal, creating ascii escape sequences that will
work in any compiler.
*/ */
jassert (t == nullptr || CharPointer_ASCII::isValidString (t, std::numeric_limits<int>::max())); jassert (t == nullptr || CharPointer_ASCII::isValidString (t, std::numeric_limits<int>::max()));
} }
@ -332,6 +336,10 @@ String::String (const char* const t, const size_t maxChars)
you use UTF-8 with escape characters in your source code to represent extended characters, you use UTF-8 with escape characters in your source code to represent extended characters,
because there's no other way to represent these strings in a way that isn't dependent on because there's no other way to represent these strings in a way that isn't dependent on
the compiler, source code editor and platform. the compiler, source code editor and platform.
Note that the Introjucer has a handy string literal generator utility that will convert
any unicode string to a valid C++ string literal, creating ascii escape sequences that will
work in any compiler.
*/ */
jassert (t == nullptr || CharPointer_ASCII::isValidString (t, (int) maxChars)); jassert (t == nullptr || CharPointer_ASCII::isValidString (t, (int) maxChars));
} }

@ -84,7 +84,7 @@ public:
because there's no other way to represent unicode strings in a way that isn't dependent because there's no other way to represent unicode strings in a way that isn't dependent
on the compiler, source code editor and platform. on the compiler, source code editor and platform.
This will use up the the first maxChars characters of the string (or less if the string This will use up to the first maxChars characters of the string (or less if the string
is actually shorter). is actually shorter).
*/ */
String (const char* text, size_t maxChars); String (const char* text, size_t maxChars);
@ -1294,6 +1294,8 @@ JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, long number);
/** Appends a decimal number at the end of a string. */ /** Appends a decimal number at the end of a string. */
JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, int64 number); JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, int64 number);
/** Appends a decimal number at the end of a string. */ /** Appends a decimal number at the end of a string. */
JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, uint64 number);
/** Appends a decimal number at the end of a string. */
JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, float number); JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, float number);
/** Appends a decimal number at the end of a string. */ /** Appends a decimal number at the end of a string. */
JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, double number); JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, double number);

@ -29,6 +29,26 @@
ChildProcess::ChildProcess() {} ChildProcess::ChildProcess() {}
ChildProcess::~ChildProcess() {} ChildProcess::~ChildProcess() {}
bool ChildProcess::isRunning() const
{
return activeProcess != nullptr && activeProcess->isRunning();
}
int ChildProcess::readProcessOutput (void* dest, int numBytes)
{
return activeProcess != nullptr ? activeProcess->read (dest, numBytes) : 0;
}
bool ChildProcess::kill()
{
return activeProcess == nullptr || activeProcess->killProcess();
}
uint32 ChildProcess::getExitCode() const
{
return activeProcess != nullptr ? activeProcess->getExitCode() : 0;
}
bool ChildProcess::waitForProcessToFinish (const int timeoutMs) const bool ChildProcess::waitForProcessToFinish (const int timeoutMs) const
{ {
const uint32 timeoutTime = Time::getMillisecondCounter() + (uint32) timeoutMs; const uint32 timeoutTime = Time::getMillisecondCounter() + (uint32) timeoutMs;

@ -97,6 +97,9 @@ public:
/** Blocks until the process is no longer running. */ /** Blocks until the process is no longer running. */
bool waitForProcessToFinish (int timeoutMs) const; bool waitForProcessToFinish (int timeoutMs) const;
/** If the process has finished, this returns its exit code. */
uint32 getExitCode() const;
/** Attempts to kill the child process. /** Attempts to kill the child process.
Returns true if it succeeded. Trying to read from the process after calling this may Returns true if it succeeded. Trying to read from the process after calling this may
result in undefined behaviour. result in undefined behaviour.

@ -38,6 +38,10 @@
one of these is by using RAII in the form of a local ScopedLock object - have a look one of these is by using RAII in the form of a local ScopedLock object - have a look
through the codebase for many examples of how to do this. through the codebase for many examples of how to do this.
In almost all cases you'll want to declare your CriticalSection as a member variable.
Occasionally you may want to declare one as a static variable, but in that case the usual
C++ static object order-of-construction warnings should be heeded.
@see ScopedLock, ScopedTryLock, ScopedUnlock, SpinLock, ReadWriteLock, Thread, InterProcessLock @see ScopedLock, ScopedTryLock, ScopedUnlock, SpinLock, ReadWriteLock, Thread, InterProcessLock
*/ */
class JUCE_API CriticalSection class JUCE_API CriticalSection
@ -157,21 +161,27 @@ private:
/** /**
Automatically locks and unlocks a CriticalSection object. Automatically locks and unlocks a CriticalSection object.
Use one of these as a local variable to provide RAII-based locking of a CriticalSection. You can use a ScopedLock as a local variable to provide RAII-based locking of a CriticalSection.
e.g. @code e.g. @code
CriticalSection myCriticalSection; struct MyObject
for (;;)
{ {
const ScopedLock myScopedLock (myCriticalSection); CriticalSection objectLock;
// myCriticalSection is now locked
// assuming that this example function will be called by multiple threads
void foo()
{
const ScopedLock myScopedLock (objectLock);
// objectLock is now locked..
...do some stuff... ...do some thread-safe work here...
// myCriticalSection gets unlocked here. // ..and objectLock gets unlocked here, as myScopedLock goes out of
} // scope at the end of the block
}
};
@endcode @endcode
@see CriticalSection, ScopedUnlock @see CriticalSection, ScopedUnlock
@ -189,29 +199,29 @@ typedef CriticalSection::ScopedLockType ScopedLock;
e.g. @code e.g. @code
CriticalSection myCriticalSection; struct MyObject
for (;;)
{ {
const ScopedLock myScopedLock (myCriticalSection); CriticalSection objectLock;
// myCriticalSection is now locked
... do some stuff with it locked ..
while (xyz) void foo()
{ {
... do some stuff with it locked .. {
const ScopedLock myScopedLock (objectLock);
const ScopedUnlock unlocker (myCriticalSection); // objectLock is now locked..
// myCriticalSection is now unlocked for the remainder of this block, {
// and re-locked at the end. ScopedUnlock myUnlocker (objectLock);
...do some stuff with it unlocked ... // ..and now unlocked..
} }
// ..and now locked again..
}
// myCriticalSection gets unlocked here. // ..and finally unlocked.
} }
};
@endcode @endcode
@see CriticalSection, ScopedLock @see CriticalSection, ScopedLock
@ -225,26 +235,27 @@ typedef CriticalSection::ScopedUnlockType ScopedUnlock;
Use one of these as a local variable to control access to a CriticalSection. Use one of these as a local variable to control access to a CriticalSection.
e.g. @code e.g. @code
CriticalSection myCriticalSection;
for (;;) struct MyObject
{ {
const ScopedTryLock myScopedTryLock (myCriticalSection); CriticalSection objectLock;
// Unlike using a ScopedLock, this may fail to actually get the lock, so you void foo()
// should test this with the isLocked() method before doing your thread-unsafe
// action..
if (myScopedTryLock.isLocked())
{ {
...do some stuff... const ScopedTryLock myScopedTryLock (objectLock);
// Unlike using a ScopedLock, this may fail to actually get the lock, so you
// must call the isLocked() method before making any assumptions..
if (myScopedTryLock.isLocked())
{
...safely do some work...
}
else
{
// If we get here, then our attempt at locking failed because another thread had already locked it..
}
} }
else };
{
..our attempt at locking failed because another thread had already locked it..
}
// myCriticalSection gets unlocked here (if it was locked)
}
@endcode @endcode
@see CriticalSection::tryEnter, ScopedLock, ScopedUnlock, ScopedReadLock @see CriticalSection::tryEnter, ScopedLock, ScopedUnlock, ScopedReadLock

@ -221,7 +221,7 @@ bool Thread::setPriority (const int newPriority)
const ScopedLock sl (startStopLock); const ScopedLock sl (startStopLock);
if (setThreadPriority (threadHandle, newPriority)) if ((! isThreadRunning()) || setThreadPriority (threadHandle, newPriority))
{ {
threadPriority = newPriority; threadPriority = newPriority;
return true; return true;

@ -26,12 +26,31 @@
============================================================================== ==============================================================================
*/ */
class ThreadPool::ThreadPoolThread : public Thread
{
public:
ThreadPoolThread (ThreadPool& p)
: Thread ("Pool"), currentJob (nullptr), pool (p)
{
}
void run() override
{
while (! threadShouldExit())
if (! pool.runNextJob (*this))
wait (500);
}
ThreadPoolJob* volatile currentJob;
ThreadPool& pool;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ThreadPoolThread)
};
//==============================================================================
ThreadPoolJob::ThreadPoolJob (const String& name) ThreadPoolJob::ThreadPoolJob (const String& name)
: jobName (name), : jobName (name), pool (nullptr),
pool (nullptr), shouldStop (false), isActive (false), shouldBeDeleted (false)
shouldStop (false),
isActive (false),
shouldBeDeleted (false)
{ {
} }
@ -57,30 +76,13 @@ void ThreadPoolJob::signalJobShouldExit()
shouldStop = true; shouldStop = true;
} }
//============================================================================== ThreadPoolJob* ThreadPoolJob::getCurrentThreadPoolJob()
class ThreadPool::ThreadPoolThread : public Thread
{ {
public: if (ThreadPool::ThreadPoolThread* t = dynamic_cast<ThreadPool::ThreadPoolThread*> (Thread::getCurrentThread()))
ThreadPoolThread (ThreadPool& pool_) return t->currentJob;
: Thread ("Pool"),
pool (pool_)
{
}
void run() override
{
while (! threadShouldExit())
{
if (! pool.runNextJob())
wait (500);
}
}
private: return nullptr;
ThreadPool& pool; }
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ThreadPoolThread)
};
//============================================================================== //==============================================================================
ThreadPool::ThreadPool (const int numThreads) ThreadPool::ThreadPool (const int numThreads)
@ -164,8 +166,7 @@ bool ThreadPool::isJobRunning (const ThreadPoolJob* const job) const
return jobs.contains (const_cast <ThreadPoolJob*> (job)) && job->isActive; return jobs.contains (const_cast <ThreadPoolJob*> (job)) && job->isActive;
} }
bool ThreadPool::waitForJobToFinish (const ThreadPoolJob* const job, bool ThreadPool::waitForJobToFinish (const ThreadPoolJob* const job, const int timeOutMs) const
const int timeOutMs) const
{ {
if (job != nullptr) if (job != nullptr)
{ {
@ -215,7 +216,7 @@ bool ThreadPool::removeJob (ThreadPoolJob* const job,
} }
bool ThreadPool::removeAllJobs (const bool interruptRunningJobs, const int timeOutMs, bool ThreadPool::removeAllJobs (const bool interruptRunningJobs, const int timeOutMs,
ThreadPool::JobSelector* selectedJobsToRemove) ThreadPool::JobSelector* const selectedJobsToRemove)
{ {
Array <ThreadPoolJob*> jobsToWaitFor; Array <ThreadPoolJob*> jobsToWaitFor;
@ -328,46 +329,49 @@ ThreadPoolJob* ThreadPool::pickNextJobToRun()
return nullptr; return nullptr;
} }
bool ThreadPool::runNextJob() bool ThreadPool::runNextJob (ThreadPoolThread& thread)
{ {
ThreadPoolJob* const job = pickNextJobToRun(); if (ThreadPoolJob* const job = pickNextJobToRun())
if (job == nullptr)
return false;
ThreadPoolJob::JobStatus result = ThreadPoolJob::jobHasFinished;
JUCE_TRY
{ {
result = job->runJob(); ThreadPoolJob::JobStatus result = ThreadPoolJob::jobHasFinished;
} thread.currentJob = job;
JUCE_CATCH_ALL_ASSERT
OwnedArray<ThreadPoolJob> deletionList; JUCE_TRY
{
result = job->runJob();
}
JUCE_CATCH_ALL_ASSERT
{ thread.currentJob = nullptr;
const ScopedLock sl (lock);
OwnedArray<ThreadPoolJob> deletionList;
if (jobs.contains (job))
{ {
job->isActive = false; const ScopedLock sl (lock);
if (result != ThreadPoolJob::jobNeedsRunningAgain || job->shouldStop) if (jobs.contains (job))
{ {
jobs.removeFirstMatchingValue (job); job->isActive = false;
addToDeleteList (deletionList, job);
jobFinishedSignal.signal(); if (result != ThreadPoolJob::jobNeedsRunningAgain || job->shouldStop)
} {
else jobs.removeFirstMatchingValue (job);
{ addToDeleteList (deletionList, job);
// move the job to the end of the queue if it wants another go
jobs.move (jobs.indexOf (job), -1); jobFinishedSignal.signal();
}
else
{
// move the job to the end of the queue if it wants another go
jobs.move (jobs.indexOf (job), -1);
}
} }
} }
return true;
} }
return true; return false;
} }
void ThreadPool::addToDeleteList (OwnedArray<ThreadPoolJob>& deletionList, ThreadPoolJob* const job) const void ThreadPool::addToDeleteList (OwnedArray<ThreadPoolJob>& deletionList, ThreadPoolJob* const job) const

@ -119,6 +119,12 @@ public:
*/ */
void signalJobShouldExit(); void signalJobShouldExit();
//==============================================================================
/** If the calling thread is being invoked inside a runJob() method, this will
return the ThreadPoolJob that it belongs to.
*/
static ThreadPoolJob* getCurrentThreadPoolJob();
//============================================================================== //==============================================================================
private: private:
friend class ThreadPool; friend class ThreadPool;
@ -290,6 +296,7 @@ private:
Array <ThreadPoolJob*> jobs; Array <ThreadPoolJob*> jobs;
class ThreadPoolThread; class ThreadPoolThread;
friend class ThreadPoolJob;
friend class ThreadPoolThread; friend class ThreadPoolThread;
friend struct ContainerDeletePolicy<ThreadPoolThread>; friend struct ContainerDeletePolicy<ThreadPoolThread>;
OwnedArray<ThreadPoolThread> threads; OwnedArray<ThreadPoolThread> threads;
@ -297,7 +304,7 @@ private:
CriticalSection lock; CriticalSection lock;
WaitableEvent jobFinishedSignal; WaitableEvent jobFinishedSignal;
bool runNextJob(); bool runNextJob (ThreadPoolThread&);
ThreadPoolJob* pickNextJobToRun(); ThreadPoolJob* pickNextJobToRun();
void addToDeleteList (OwnedArray<ThreadPoolJob>&, ThreadPoolJob*) const; void addToDeleteList (OwnedArray<ThreadPoolJob>&, ThreadPoolJob*) const;
void createThreads (int numThreads); void createThreads (int numThreads);

@ -110,7 +110,7 @@ namespace TimeHelpers
const size_t numChars = wcsftime (buffer, bufferSize - 1, format.toUTF32(), tm); const size_t numChars = wcsftime (buffer, bufferSize - 1, format.toUTF32(), tm);
#endif #endif
if (numChars > 0) if (numChars > 0 || format.isEmpty())
return String (StringType (buffer), return String (StringType (buffer),
StringType (buffer) + (int) numChars); StringType (buffer) + (int) numChars);
} }

@ -371,8 +371,8 @@ void XmlDocument::readQuotedString (String& result)
} }
else if (character == 0) else if (character == 0)
{ {
outOfData = true;
setLastError ("unmatched quotes", false); setLastError ("unmatched quotes", false);
outOfData = true;
break; break;
} }
@ -432,7 +432,7 @@ XmlElement* XmlDocument::readNextElement (const bool alsoParseSubElements)
++input; ++input;
if (alsoParseSubElements) if (alsoParseSubElements)
readChildElements (node); readChildElements (*node);
break; break;
} }
@ -487,9 +487,9 @@ XmlElement* XmlDocument::readNextElement (const bool alsoParseSubElements)
return node; return node;
} }
void XmlDocument::readChildElements (XmlElement* parent) void XmlDocument::readChildElements (XmlElement& parent)
{ {
LinkedListPointer<XmlElement>::Appender childAppender (parent->firstChildElement); LinkedListPointer<XmlElement>::Appender childAppender (parent.firstChildElement);
for (;;) for (;;)
{ {
@ -563,7 +563,25 @@ void XmlDocument::readChildElements (XmlElement* parent)
const juce_wchar c = *input; const juce_wchar c = *input;
if (c == '<') if (c == '<')
{
if (input[1] == '!' && input[2] == '-' && input[3] == '-')
{
input += 4;
const int closeComment = input.indexOf (CharPointer_ASCII ("-->"));
if (closeComment < 0)
{
setLastError ("unterminated comment", false);
outOfData = true;
return;
}
input += closeComment + 3;
continue;
}
break; break;
}
if (c == 0) if (c == 0)
{ {

@ -156,23 +156,23 @@ private:
String lastError, dtdText; String lastError, dtdText;
StringArray tokenisedDTD; StringArray tokenisedDTD;
bool needToLoadDTD, ignoreEmptyTextElements; bool needToLoadDTD, ignoreEmptyTextElements;
ScopedPointer <InputSource> inputSource; ScopedPointer<InputSource> inputSource;
XmlElement* parseDocumentElement (String::CharPointerType, bool outer); XmlElement* parseDocumentElement (String::CharPointerType, bool outer);
void setLastError (const String& desc, bool carryOn); void setLastError (const String&, bool carryOn);
bool parseHeader(); bool parseHeader();
bool parseDTD(); bool parseDTD();
void skipNextWhiteSpace(); void skipNextWhiteSpace();
juce_wchar readNextChar() noexcept; juce_wchar readNextChar() noexcept;
XmlElement* readNextElement (bool alsoParseSubElements); XmlElement* readNextElement (bool alsoParseSubElements);
void readChildElements (XmlElement* parent); void readChildElements (XmlElement&);
void readQuotedString (String& result); void readQuotedString (String&);
void readEntity (String& result); void readEntity (String&);
String getFileContents (const String& filename) const; String getFileContents (const String&) const;
String expandEntity (const String& entity); String expandEntity (const String&);
String expandExternalEntity (const String& entity); String expandExternalEntity (const String&);
String getParameterEntity (const String& entity); String getParameterEntity (const String&);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (XmlDocument) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (XmlDocument)
}; };

@ -55,7 +55,7 @@ XmlElement::XmlElement (const String& tag) noexcept
jassert (tag.containsNonWhitespaceChars()) jassert (tag.containsNonWhitespaceChars())
// The tag can't contain spaces or other characters that would create invalid XML! // The tag can't contain spaces or other characters that would create invalid XML!
jassert (! tag.containsAnyOf (" <>/&")); jassert (! tag.containsAnyOf (" <>/&(){}"));
} }
XmlElement::XmlElement (int /*dummy*/) noexcept XmlElement::XmlElement (int /*dummy*/) noexcept

@ -215,18 +215,18 @@ bool PropertiesFile::loadAsXml()
bool PropertiesFile::saveAsXml() bool PropertiesFile::saveAsXml()
{ {
XmlElement doc (PropertyFileConstants::fileTag); XmlElement doc (PropertyFileConstants::fileTag);
const StringPairArray& props = getAllProperties();
for (int i = 0; i < getAllProperties().size(); ++i) for (int i = 0; i < props.size(); ++i)
{ {
XmlElement* const e = doc.createNewChildElement (PropertyFileConstants::valueTag); XmlElement* const e = doc.createNewChildElement (PropertyFileConstants::valueTag);
e->setAttribute (PropertyFileConstants::nameAttribute, getAllProperties().getAllKeys() [i]); e->setAttribute (PropertyFileConstants::nameAttribute, props.getAllKeys() [i]);
// if the value seems to contain xml, store it as such.. // if the value seems to contain xml, store it as such..
if (XmlElement* const childElement = XmlDocument::parse (getAllProperties().getAllValues() [i])) if (XmlElement* const childElement = XmlDocument::parse (props.getAllValues() [i]))
e->addChildElement (childElement); e->addChildElement (childElement);
else else
e->setAttribute (PropertyFileConstants::valueAttribute, e->setAttribute (PropertyFileConstants::valueAttribute, props.getAllValues() [i]);
getAllProperties().getAllValues() [i]);
} }
ProcessScopedLock pl (createProcessLock()); ProcessScopedLock pl (createProcessLock());
@ -311,14 +311,17 @@ bool PropertiesFile::saveAsBinary()
out->writeInt (PropertyFileConstants::magicNumber); out->writeInt (PropertyFileConstants::magicNumber);
} }
const int numProperties = getAllProperties().size(); const StringPairArray& props = getAllProperties();
const int numProperties = props.size();
const StringArray& keys = props.getAllKeys();
const StringArray& values = props.getAllValues();
out->writeInt (numProperties); out->writeInt (numProperties);
for (int i = 0; i < numProperties; ++i) for (int i = 0; i < numProperties; ++i)
{ {
out->writeString (getAllProperties().getAllKeys() [i]); out->writeString (keys[i]);
out->writeString (getAllProperties().getAllValues() [i]); out->writeString (values[i]);
} }
out = nullptr; out = nullptr;

@ -57,7 +57,7 @@ public:
struct JUCE_API Options struct JUCE_API Options
{ {
/** Creates an empty Options structure. /** Creates an empty Options structure.
You'll need to fill-in the data memebers appropriately before using this structure. You'll need to fill-in the data members appropriately before using this structure.
*/ */
Options(); Options();

@ -1,7 +1,7 @@
{ {
"id": "juce_data_structures", "id": "juce_data_structures",
"name": "JUCE data model helper classes", "name": "JUCE data model helper classes",
"version": "3.0.1", "version": "3.0.3",
"description": "Classes for undo/redo management, and smart data structures.", "description": "Classes for undo/redo management, and smart data structures.",
"website": "http://www.juce.com/juce", "website": "http://www.juce.com/juce",
"license": "GPL/Commercial", "license": "GPL/Commercial",

@ -73,7 +73,7 @@ private:
class ActionMessage; class ActionMessage;
friend class ActionMessage; friend class ActionMessage;
SortedSet <ActionListener*> actionListeners; SortedSet<ActionListener*> actionListeners;
CriticalSection actionListenerLock; CriticalSection actionListenerLock;
JUCE_DECLARE_NON_COPYABLE (ActionBroadcaster) JUCE_DECLARE_NON_COPYABLE (ActionBroadcaster)

@ -28,10 +28,7 @@
//============================================================================== //==============================================================================
/** /**
Receives callbacks to indicate that some kind of event has occurred. Interface class for delivery of events that are sent by an ActionBroadcaster.
Used by various classes, e.g. buttons when they are pressed, to tell listeners
about something that's happened.
@see ActionBroadcaster, ChangeListener @see ActionBroadcaster, ChangeListener
*/ */

@ -22,14 +22,27 @@
============================================================================== ==============================================================================
*/ */
struct InterprocessConnection::ConnectionThread : public Thread
{
ConnectionThread (InterprocessConnection& c) : Thread ("JUCE IPC"), owner (c) {}
void run() override { owner.runThread(); }
private:
InterprocessConnection& owner;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ConnectionThread);
};
//==============================================================================
InterprocessConnection::InterprocessConnection (const bool callbacksOnMessageThread, InterprocessConnection::InterprocessConnection (const bool callbacksOnMessageThread,
const uint32 magicMessageHeaderNumber) const uint32 magicMessageHeaderNumber)
: Thread ("Juce IPC connection"), : callbackConnectionState (false),
callbackConnectionState (false),
useMessageThread (callbacksOnMessageThread), useMessageThread (callbacksOnMessageThread),
magicMessageHeader (magicMessageHeaderNumber), magicMessageHeader (magicMessageHeaderNumber),
pipeReceiveMessageTimeout (-1) pipeReceiveMessageTimeout (-1)
{ {
thread = new ConnectionThread (*this);
} }
InterprocessConnection::~InterprocessConnection() InterprocessConnection::~InterprocessConnection()
@ -37,9 +50,9 @@ InterprocessConnection::~InterprocessConnection()
callbackConnectionState = false; callbackConnectionState = false;
disconnect(); disconnect();
masterReference.clear(); masterReference.clear();
thread = nullptr;
} }
//============================================================================== //==============================================================================
bool InterprocessConnection::connectToSocket (const String& hostName, bool InterprocessConnection::connectToSocket (const String& hostName,
const int portNumber, const int portNumber,
@ -53,7 +66,7 @@ bool InterprocessConnection::connectToSocket (const String& hostName,
if (socket->connect (hostName, portNumber, timeOutMillisecs)) if (socket->connect (hostName, portNumber, timeOutMillisecs))
{ {
connectionMadeInt(); connectionMadeInt();
startThread(); thread->startThread();
return true; return true;
} }
else else
@ -99,7 +112,7 @@ bool InterprocessConnection::createPipe (const String& pipeName, const int timeo
void InterprocessConnection::disconnect() void InterprocessConnection::disconnect()
{ {
signalThreadShouldExit(); thread->signalThreadShouldExit();
{ {
const ScopedLock sl (pipeAndSocketLock); const ScopedLock sl (pipeAndSocketLock);
@ -107,7 +120,7 @@ void InterprocessConnection::disconnect()
if (pipe != nullptr) pipe->close(); if (pipe != nullptr) pipe->close();
} }
stopThread (4000); thread->stopThread (4000);
deletePipeAndSocket(); deletePipeAndSocket();
connectionLostInt(); connectionLostInt();
} }
@ -125,7 +138,7 @@ bool InterprocessConnection::isConnected() const
return ((socket != nullptr && socket->isConnected()) return ((socket != nullptr && socket->isConnected())
|| (pipe != nullptr && pipe->isOpen())) || (pipe != nullptr && pipe->isOpen()))
&& isThreadRunning(); && thread->isThreadRunning();
} }
String InterprocessConnection::getConnectedHostName() const String InterprocessConnection::getConnectedHostName() const
@ -173,7 +186,7 @@ void InterprocessConnection::initialiseWithSocket (StreamingSocket* newSocket)
jassert (socket == nullptr && pipe == nullptr); jassert (socket == nullptr && pipe == nullptr);
socket = newSocket; socket = newSocket;
connectionMadeInt(); connectionMadeInt();
startThread(); thread->startThread();
} }
void InterprocessConnection::initialiseWithPipe (NamedPipe* newPipe) void InterprocessConnection::initialiseWithPipe (NamedPipe* newPipe)
@ -181,7 +194,7 @@ void InterprocessConnection::initialiseWithPipe (NamedPipe* newPipe)
jassert (socket == nullptr && pipe == nullptr); jassert (socket == nullptr && pipe == nullptr);
pipe = newPipe; pipe = newPipe;
connectionMadeInt(); connectionMadeInt();
startThread(); thread->startThread();
} }
//============================================================================== //==============================================================================
@ -279,7 +292,7 @@ bool InterprocessConnection::readNextMessageInt()
while (bytesInMessage > 0) while (bytesInMessage > 0)
{ {
if (threadShouldExit()) if (thread->threadShouldExit())
return false; return false;
const int numThisTime = jmin (bytesInMessage, 65536); const int numThisTime = jmin (bytesInMessage, 65536);
@ -311,9 +324,9 @@ bool InterprocessConnection::readNextMessageInt()
return true; return true;
} }
void InterprocessConnection::run() void InterprocessConnection::runThread()
{ {
while (! threadShouldExit()) while (! thread->threadShouldExit())
{ {
if (socket != nullptr) if (socket != nullptr)
{ {
@ -328,7 +341,7 @@ void InterprocessConnection::run()
if (ready == 0) if (ready == 0)
{ {
wait (1); thread->wait (1);
continue; continue;
} }
} }
@ -346,7 +359,7 @@ void InterprocessConnection::run()
break; break;
} }
if (threadShouldExit() || ! readNextMessageInt()) if (thread->threadShouldExit() || ! readNextMessageInt())
break; break;
} }
} }

@ -47,7 +47,7 @@ class MemoryBlock;
@see InterprocessConnectionServer, Socket, NamedPipe @see InterprocessConnectionServer, Socket, NamedPipe
*/ */
class JUCE_API InterprocessConnection : private Thread class JUCE_API InterprocessConnection
{ {
public: public:
//============================================================================== //==============================================================================
@ -71,7 +71,7 @@ public:
uint32 magicMessageHeaderNumber = 0xf2b49e2c); uint32 magicMessageHeaderNumber = 0xf2b49e2c);
/** Destructor. */ /** Destructor. */
~InterprocessConnection(); virtual ~InterprocessConnection();
//============================================================================== //==============================================================================
/** Tries to connect this object to a socket. /** Tries to connect this object to a socket.
@ -195,7 +195,12 @@ private:
void connectionLostInt(); void connectionLostInt();
void deliverDataInt (const MemoryBlock&); void deliverDataInt (const MemoryBlock&);
bool readNextMessageInt(); bool readNextMessageInt();
void run() override;
struct ConnectionThread;
friend struct ConnectionThread;
friend struct ContainerDeletePolicy<ConnectionThread>;
ScopedPointer<ConnectionThread> thread;
void runThread();
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (InterprocessConnection) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (InterprocessConnection)
}; };

@ -73,6 +73,7 @@ namespace juce
#include "timers/juce_Timer.cpp" #include "timers/juce_Timer.cpp"
#include "interprocess/juce_InterprocessConnection.cpp" #include "interprocess/juce_InterprocessConnection.cpp"
#include "interprocess/juce_InterprocessConnectionServer.cpp" #include "interprocess/juce_InterprocessConnectionServer.cpp"
#include "interprocess/juce_ConnectedChildProcess.cpp"
//============================================================================== //==============================================================================
#if JUCE_MAC #if JUCE_MAC

@ -49,6 +49,7 @@ namespace juce
#include "timers/juce_MultiTimer.h" #include "timers/juce_MultiTimer.h"
#include "interprocess/juce_InterprocessConnection.h" #include "interprocess/juce_InterprocessConnection.h"
#include "interprocess/juce_InterprocessConnectionServer.h" #include "interprocess/juce_InterprocessConnectionServer.h"
#include "interprocess/juce_ConnectedChildProcess.h"
#include "native/juce_ScopedXLock.h" #include "native/juce_ScopedXLock.h"
} }

@ -1,7 +1,7 @@
{ {
"id": "juce_events", "id": "juce_events",
"name": "JUCE message and event handling classes", "name": "JUCE message and event handling classes",
"version": "3.0.1", "version": "3.0.3",
"description": "Classes for running an application's main event loop and sending/receiving messages, timers, etc.", "description": "Classes for running an application's main event loop and sending/receiving messages, timers, etc.",
"website": "http://www.juce.com/juce", "website": "http://www.juce.com/juce",
"license": "GPL/Commercial", "license": "GPL/Commercial",

@ -26,7 +26,7 @@ namespace ColourHelpers
{ {
static uint8 floatToUInt8 (const float n) noexcept static uint8 floatToUInt8 (const float n) noexcept
{ {
return n <= 0.0f ? 0 : (n >= 1.0f ? 255 : (uint8) (n * 255.0f)); return n <= 0.0f ? 0 : (n >= 1.0f ? 255 : static_cast<uint8> (n * 255.996f));
} }
// This is an adjusted brightness value, based on the way the human // This is an adjusted brightness value, based on the way the human

@ -151,8 +151,8 @@ public:
*/ */
bool isRadial; bool isRadial;
bool operator== (const ColourGradient& other) const noexcept; bool operator== (const ColourGradient&) const noexcept;
bool operator!= (const ColourGradient& other) const noexcept; bool operator!= (const ColourGradient&) const noexcept;
private: private:
@ -165,14 +165,14 @@ private:
: position (pos), colour (col) : position (pos), colour (col)
{} {}
bool operator== (const ColourPoint& other) const noexcept; bool operator== (const ColourPoint&) const noexcept;
bool operator!= (const ColourPoint& other) const noexcept; bool operator!= (const ColourPoint&) const noexcept;
double position; double position;
Colour colour; Colour colour;
}; };
Array <ColourPoint> colours; Array<ColourPoint> colours;
JUCE_LEAK_DETECTOR (ColourGradient) JUCE_LEAK_DETECTOR (ColourGradient)
}; };

@ -59,14 +59,14 @@ public:
FillType (const Image& image, const AffineTransform& transform) noexcept; FillType (const Image& image, const AffineTransform& transform) noexcept;
/** Creates a copy of another FillType. */ /** Creates a copy of another FillType. */
FillType (const FillType& other); FillType (const FillType&);
/** Makes a copy of another FillType. */ /** Makes a copy of another FillType. */
FillType& operator= (const FillType& other); FillType& operator= (const FillType&);
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
FillType (FillType&& other) noexcept; FillType (FillType&&) noexcept;
FillType& operator= (FillType&& other) noexcept; FillType& operator= (FillType&&) noexcept;
#endif #endif
/** Destructor. */ /** Destructor. */
@ -138,8 +138,8 @@ public:
AffineTransform transform; AffineTransform transform;
//============================================================================== //==============================================================================
bool operator== (const FillType& other) const; bool operator== (const FillType&) const;
bool operator!= (const FillType& other) const; bool operator!= (const FillType&) const;
private: private:
JUCE_LEAK_DETECTOR (FillType) JUCE_LEAK_DETECTOR (FillType)

@ -281,28 +281,30 @@ void Graphics::drawMultiLineText (const String& text, const int startX,
} }
} }
void Graphics::drawText (const String& text, const Rectangle<int>& area, void Graphics::drawText (const String& text, const Rectangle<float>& area,
Justification justificationType, Justification justificationType, bool useEllipsesIfTooBig) const
const bool useEllipsesIfTooBig) const
{ {
if (text.isNotEmpty() && context.clipRegionIntersects (area)) if (text.isNotEmpty() && context.clipRegionIntersects (area.getSmallestIntegerContainer()))
{ {
GlyphArrangement arr; GlyphArrangement arr;
arr.addCurtailedLineOfText (context.getFont(), text, arr.addCurtailedLineOfText (context.getFont(), text, 0.0f, 0.0f,
0.0f, 0.0f, (float) area.getWidth(), area.getWidth(), useEllipsesIfTooBig);
useEllipsesIfTooBig);
arr.justifyGlyphs (0, arr.getNumGlyphs(), arr.justifyGlyphs (0, arr.getNumGlyphs(),
(float) area.getX(), (float) area.getY(), area.getX(), area.getY(), area.getWidth(), area.getHeight(),
(float) area.getWidth(), (float) area.getHeight(),
justificationType); justificationType);
arr.draw (*this); arr.draw (*this);
} }
} }
void Graphics::drawText (const String& text, const Rectangle<int>& area,
Justification justificationType, bool useEllipsesIfTooBig) const
{
drawText (text, area.toFloat(), justificationType, useEllipsesIfTooBig);
}
void Graphics::drawText (const String& text, const int x, const int y, const int width, const int height, void Graphics::drawText (const String& text, const int x, const int y, const int width, const int height,
Justification justificationType, Justification justificationType, const bool useEllipsesIfTooBig) const
const bool useEllipsesIfTooBig) const
{ {
drawText (text, Rectangle<int> (x, y, width, height), justificationType, useEllipsesIfTooBig); drawText (text, Rectangle<int> (x, y, width, height), justificationType, useEllipsesIfTooBig);
} }

@ -174,6 +174,20 @@ public:
Justification justificationType, Justification justificationType,
bool useEllipsesIfTooBig) const; bool useEllipsesIfTooBig) const;
/** Draws a line of text within a specified rectangle.
The text will be positioned within the rectangle based on the justification
flags passed-in. If the string is too long to fit inside the rectangle, it will
either be truncated or will have ellipsis added to its end (if the useEllipsesIfTooBig
flag is true).
@see drawSingleLineText, drawFittedText, drawMultiLineText, GlyphArrangement::addJustifiedText
*/
void drawText (const String& text,
const Rectangle<float>& area,
Justification justificationType,
bool useEllipsesIfTooBig) const;
/** Tries to draw a text string inside a given space. /** Tries to draw a text string inside a given space.
This does its best to make the given text readable within the specified rectangle, This does its best to make the given text readable within the specified rectangle,

@ -385,7 +385,7 @@ bool CustomTypeface::getOutlineForGlyph (int glyphNumber, Path& path)
return false; return false;
} }
EdgeTable* CustomTypeface::getEdgeTableForGlyph (int glyphNumber, const AffineTransform& transform) EdgeTable* CustomTypeface::getEdgeTableForGlyph (int glyphNumber, const AffineTransform& transform, float fontHeight)
{ {
if (const GlyphInfo* const glyph = findGlyph ((juce_wchar) glyphNumber, true)) if (const GlyphInfo* const glyph = findGlyph ((juce_wchar) glyphNumber, true))
{ {
@ -399,7 +399,7 @@ EdgeTable* CustomTypeface::getEdgeTableForGlyph (int glyphNumber, const AffineTr
const Typeface::Ptr fallbackTypeface (getFallbackTypeface()); const Typeface::Ptr fallbackTypeface (getFallbackTypeface());
if (fallbackTypeface != nullptr && fallbackTypeface != this) if (fallbackTypeface != nullptr && fallbackTypeface != this)
return fallbackTypeface->getEdgeTableForGlyph (glyphNumber, transform); return fallbackTypeface->getEdgeTableForGlyph (glyphNumber, transform, fontHeight);
} }
return nullptr; return nullptr;

@ -119,7 +119,7 @@ public:
float getStringWidth (const String&) override; float getStringWidth (const String&) override;
void getGlyphPositions (const String&, Array <int>& glyphs, Array<float>& xOffsets) override; void getGlyphPositions (const String&, Array <int>& glyphs, Array<float>& xOffsets) override;
bool getOutlineForGlyph (int glyphNumber, Path&) override; bool getOutlineForGlyph (int glyphNumber, Path&) override;
EdgeTable* getEdgeTableForGlyph (int glyphNumber, const AffineTransform&) override; EdgeTable* getEdgeTableForGlyph (int glyphNumber, const AffineTransform&, float fontHeight) override;
protected: protected:
//============================================================================== //==============================================================================

@ -44,8 +44,8 @@ public:
PositionedGlyph (const Font& font, juce_wchar character, int glyphNumber, PositionedGlyph (const Font& font, juce_wchar character, int glyphNumber,
float anchorX, float baselineY, float width, bool isWhitespace); float anchorX, float baselineY, float width, bool isWhitespace);
PositionedGlyph (const PositionedGlyph& other); PositionedGlyph (const PositionedGlyph&);
PositionedGlyph& operator= (const PositionedGlyph& other); PositionedGlyph& operator= (const PositionedGlyph&);
~PositionedGlyph(); ~PositionedGlyph();
/** Returns the character the glyph represents. */ /** Returns the character the glyph represents. */
@ -209,10 +209,10 @@ public:
float minimumHorizontalScale = 0.7f); float minimumHorizontalScale = 0.7f);
/** Appends another glyph arrangement to this one. */ /** Appends another glyph arrangement to this one. */
void addGlyphArrangement (const GlyphArrangement& other); void addGlyphArrangement (const GlyphArrangement&);
/** Appends a custom glyph to the arrangement. */ /** Appends a custom glyph to the arrangement. */
void addGlyph (const PositionedGlyph& glyph); void addGlyph (const PositionedGlyph&);
//============================================================================== //==============================================================================
/** Draws this glyph arrangement to a graphics context. /** Draws this glyph arrangement to a graphics context.

@ -101,8 +101,8 @@ struct FontStyleHelpers
}; };
//============================================================================== //==============================================================================
Typeface::Typeface (const String& name_, const String& style_) noexcept Typeface::Typeface (const String& faceName, const String& styleName) noexcept
: name (name_), style (style_) : name (faceName), style (styleName)
{ {
} }
@ -116,13 +116,145 @@ Typeface::Ptr Typeface::getFallbackTypeface()
return fallbackFont.getTypeface(); return fallbackFont.getTypeface();
} }
EdgeTable* Typeface::getEdgeTableForGlyph (int glyphNumber, const AffineTransform& transform) EdgeTable* Typeface::getEdgeTableForGlyph (int glyphNumber, const AffineTransform& transform, float fontHeight)
{ {
Path path; Path path;
if (getOutlineForGlyph (glyphNumber, path) && ! path.isEmpty()) if (getOutlineForGlyph (glyphNumber, path) && ! path.isEmpty())
{
applyVerticalHintingTransform (fontHeight, path);
return new EdgeTable (path.getBoundsTransformed (transform).getSmallestIntegerContainer().expanded (1, 0), return new EdgeTable (path.getBoundsTransformed (transform).getSmallestIntegerContainer().expanded (1, 0),
path, transform); path, transform);
}
return nullptr; return nullptr;
} }
//==============================================================================
struct Typeface::HintingParams
{
HintingParams (Typeface& t)
: cachedSize (0), top (0), middle (0), bottom (0)
{
Font font (&t);
font = font.withHeight ((float) standardHeight);
top = getAverageY (font, "BDEFPRTZOQ", true);
middle = getAverageY (font, "acegmnopqrsuvwxy", true);
bottom = getAverageY (font, "BDELZOC", false);
}
void applyVerticalHintingTransform (float fontSize, Path& path)
{
if (cachedSize != fontSize)
{
cachedSize = fontSize;
cachedScale = Scaling (top, middle, bottom, fontSize);
}
if (bottom < top + 3.0f / fontSize)
return;
Path result;
for (Path::Iterator i (path); i.next();)
{
switch (i.elementType)
{
case Path::Iterator::startNewSubPath: result.startNewSubPath (i.x1, cachedScale.apply (i.y1)); break;
case Path::Iterator::lineTo: result.lineTo (i.x1, cachedScale.apply (i.y1)); break;
case Path::Iterator::quadraticTo: result.quadraticTo (i.x1, cachedScale.apply (i.y1),
i.x2, cachedScale.apply (i.y2)); break;
case Path::Iterator::cubicTo: result.cubicTo (i.x1, cachedScale.apply (i.y1),
i.x2, cachedScale.apply (i.y2),
i.x3, cachedScale.apply (i.y3)); break;
case Path::Iterator::closePath: result.closeSubPath(); break;
default: jassertfalse; break;
}
}
result.swapWithPath (path);
}
private:
struct Scaling
{
Scaling() noexcept : middle(), upperScale(), upperOffset(), lowerScale(), lowerOffset() {}
Scaling (float t, float m, float b, float fontSize) noexcept : middle (m)
{
const float newT = std::floor (fontSize * t + 0.5f) / fontSize;
const float newB = std::floor (fontSize * b + 0.5f) / fontSize;
const float newM = std::floor (fontSize * m + 0.3f) / fontSize; // this is slightly biased so that lower-case letters
// are more likely to become taller than shorter.
upperScale = jlimit (0.9f, 1.1f, (newM - newT) / (m - t));
lowerScale = jlimit (0.9f, 1.1f, (newB - newM) / (b - m));
upperOffset = newM - m * upperScale;
lowerOffset = newB - b * lowerScale;
}
float apply (float y) const noexcept
{
return y < middle ? (y * upperScale + upperOffset)
: (y * lowerScale + lowerOffset);
}
float middle, upperScale, upperOffset, lowerScale, lowerOffset;
};
float cachedSize;
Scaling cachedScale;
static float getAverageY (const Font& font, const char* chars, bool getTop)
{
GlyphArrangement ga;
ga.addLineOfText (font, chars, 0, 0);
Array<float> y;
DefaultElementComparator<float> sorter;
for (int i = 0; i < ga.getNumGlyphs(); ++i)
{
Path p;
ga.getGlyph (i).createPath (p);
Rectangle<float> bounds (p.getBounds());
if (! p.isEmpty())
y.addSorted (sorter, getTop ? bounds.getY() : bounds.getBottom());
}
float median = y[y.size() / 2];
float total = 0;
int num = 0;
for (int i = 0; i < y.size(); ++i)
{
if (std::abs (median - y.getUnchecked(i)) < 0.05f * (float) standardHeight)
{
total += y.getUnchecked(i);
++num;
}
}
return num < 4 ? 0.0f : total / (num * (float) standardHeight);
}
enum { standardHeight = 100 };
float top, middle, bottom;
};
void Typeface::applyVerticalHintingTransform (float fontSize, Path& path)
{
if (fontSize > 3.0f && fontSize < 25.0f)
{
ScopedLock sl (hintingLock);
if (hintingParams == nullptr)
hintingParams = new HintingParams (*this);
return hintingParams->applyVerticalHintingTransform (fontSize, path);
}
}

@ -117,7 +117,7 @@ public:
virtual bool getOutlineForGlyph (int glyphNumber, Path& path) = 0; virtual bool getOutlineForGlyph (int glyphNumber, Path& path) = 0;
/** Returns a new EdgeTable that contains the path for the givem glyph, with the specified transform applied. */ /** Returns a new EdgeTable that contains the path for the givem glyph, with the specified transform applied. */
virtual EdgeTable* getEdgeTableForGlyph (int glyphNumber, const AffineTransform& transform); virtual EdgeTable* getEdgeTableForGlyph (int glyphNumber, const AffineTransform& transform, float fontHeight);
/** Returns true if the typeface uses hinting. */ /** Returns true if the typeface uses hinting. */
virtual bool isHinted() const { return false; } virtual bool isHinted() const { return false; }
@ -134,6 +134,12 @@ public:
*/ */
static void scanFolderForFonts (const File& folder); static void scanFolderForFonts (const File& folder);
/** Makes an attempt at performing a good overall distortion that will scale a font of
the given size to align vertically with the pixel grid. The path should be an unscaled
(i.e. normalised to height of 1.0) path for a glyph.
*/
void applyVerticalHintingTransform (float fontHeight, Path& path);
protected: protected:
//============================================================================== //==============================================================================
String name, style; String name, style;
@ -143,6 +149,11 @@ protected:
static Ptr getFallbackTypeface(); static Ptr getFallbackTypeface();
private: private:
struct HintingParams;
friend struct ContainerDeletePolicy<HintingParams>;
ScopedPointer<HintingParams> hintingParams;
CriticalSection hintingLock;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Typeface) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Typeface)
}; };

@ -62,10 +62,10 @@ public:
explicit EdgeTable (const Rectangle<float>& rectangleToAdd); explicit EdgeTable (const Rectangle<float>& rectangleToAdd);
/** Creates a copy of another edge table. */ /** Creates a copy of another edge table. */
EdgeTable (const EdgeTable& other); EdgeTable (const EdgeTable&);
/** Copies from another edge table. */ /** Copies from another edge table. */
EdgeTable& operator= (const EdgeTable& other); EdgeTable& operator= (const EdgeTable&);
/** Destructor. */ /** Destructor. */
~EdgeTable(); ~EdgeTable();
@ -73,7 +73,7 @@ public:
//============================================================================== //==============================================================================
void clipToRectangle (const Rectangle<int>& r); void clipToRectangle (const Rectangle<int>& r);
void excludeRectangle (const Rectangle<int>& r); void excludeRectangle (const Rectangle<int>& r);
void clipToEdgeTable (const EdgeTable& other); void clipToEdgeTable (const EdgeTable&);
void clipLineToMask (int x, int y, const uint8* mask, int maskStride, int numPixels); void clipLineToMask (int x, int y, const uint8* mask, int maskStride, int numPixels);
bool isEmpty() noexcept; bool isEmpty() noexcept;
const Rectangle<int>& getMaximumBounds() const noexcept { return bounds; } const Rectangle<int>& getMaximumBounds() const noexcept { return bounds; }

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save