Updated to JUCE 3.0.1

pull/1/head
asb2m10 11 years ago
parent 453bd181e5
commit 7bb4a809aa
  1. 14
      Builds/MacOSX/Dexed.xcodeproj/project.pbxproj
  2. BIN
      Builds/MacOSX/Dexed.xcodeproj/project.xcworkspace/xcuserdata/asb2m10.xcuserdatad/UserInterfaceState.xcuserstate
  3. 12
      Builds/VisualStudio2012/Dexed.vcxproj
  4. 18
      Builds/VisualStudio2012/Dexed.vcxproj.filters
  5. 12
      Builds/VisualStudio2013/Dexed.vcxproj
  6. 18
      Builds/VisualStudio2013/Dexed.vcxproj.filters
  7. 4
      JuceLibraryCode/AppConfig.h
  8. 338
      JuceLibraryCode/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp
  9. 7
      JuceLibraryCode/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h
  10. 5
      JuceLibraryCode/modules/juce_audio_basics/juce_audio_basics.cpp
  11. 2
      JuceLibraryCode/modules/juce_audio_basics/juce_module_info
  12. 138
      JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiMessage.cpp
  13. 20
      JuceLibraryCode/modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp
  14. 36
      JuceLibraryCode/modules/juce_audio_basics/synthesisers/juce_Synthesiser.h
  15. 28
      JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.cpp
  16. 2
      JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.h
  17. 46
      JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioIODevice.h
  18. 2
      JuceLibraryCode/modules/juce_audio_devices/juce_module_info
  19. 57
      JuceLibraryCode/modules/juce_audio_devices/native/juce_android_Audio.cpp
  20. 55
      JuceLibraryCode/modules/juce_audio_devices/native/juce_android_OpenSL.cpp
  21. 56
      JuceLibraryCode/modules/juce_audio_devices/native/juce_ios_Audio.cpp
  22. 71
      JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_ALSA.cpp
  23. 62
      JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_JackAudio.cpp
  24. 951
      JuceLibraryCode/modules/juce_audio_devices/native/juce_mac_CoreAudio.cpp
  25. 58
      JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_ASIO.cpp
  26. 55
      JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_DirectSound.cpp
  27. 52
      JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_WASAPI.cpp
  28. 3
      JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioSourcePlayer.h
  29. 32
      JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioTransportSource.cpp
  30. 10
      JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioTransportSource.h
  31. 14
      JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/stream_decoder.c
  32. 2
      JuceLibraryCode/modules/juce_audio_formats/codecs/juce_AiffAudioFormat.cpp
  33. 10
      JuceLibraryCode/modules/juce_audio_formats/codecs/juce_LAMEEncoderAudioFormat.cpp
  34. 9
      JuceLibraryCode/modules/juce_audio_formats/codecs/juce_MP3AudioFormat.cpp
  35. 2
      JuceLibraryCode/modules/juce_audio_formats/juce_module_info
  36. 11
      JuceLibraryCode/modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm
  37. 2
      JuceLibraryCode/modules/juce_audio_plugin_client/RTAS/juce_RTAS_Wrapper.cpp
  38. 2
      JuceLibraryCode/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h
  39. 32
      JuceLibraryCode/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp
  40. 2
      JuceLibraryCode/modules/juce_audio_plugin_client/juce_module_info
  41. 4
      JuceLibraryCode/modules/juce_audio_plugin_client/utility/juce_PluginUtilities.cpp
  42. 28
      JuceLibraryCode/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm
  43. 12
      JuceLibraryCode/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.cpp
  44. 266
      JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp
  45. 4
      JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VSTMidiEventList.h
  46. 15
      JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp
  47. 2
      JuceLibraryCode/modules/juce_audio_processors/juce_module_info
  48. 4
      JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp
  49. 12
      JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.cpp
  50. 6
      JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.h
  51. 4
      JuceLibraryCode/modules/juce_audio_processors/processors/juce_GenericAudioProcessorEditor.cpp
  52. 19
      JuceLibraryCode/modules/juce_audio_processors/scanning/juce_KnownPluginList.cpp
  53. 5
      JuceLibraryCode/modules/juce_audio_processors/scanning/juce_KnownPluginList.h
  54. 2
      JuceLibraryCode/modules/juce_audio_processors/scanning/juce_PluginDirectoryScanner.cpp
  55. 243
      JuceLibraryCode/modules/juce_audio_processors/scanning/juce_PluginListComponent.cpp
  56. 36
      JuceLibraryCode/modules/juce_audio_processors/scanning/juce_PluginListComponent.h
  57. 37
      JuceLibraryCode/modules/juce_audio_utils/gui/juce_AudioDeviceSelectorComponent.cpp
  58. 2
      JuceLibraryCode/modules/juce_audio_utils/juce_module_info
  59. 5
      JuceLibraryCode/modules/juce_core/containers/juce_OwnedArray.h
  60. 4
      JuceLibraryCode/modules/juce_core/containers/juce_PropertySet.cpp
  61. 6
      JuceLibraryCode/modules/juce_core/containers/juce_PropertySet.h
  62. 12
      JuceLibraryCode/modules/juce_core/files/juce_File.cpp
  63. 2
      JuceLibraryCode/modules/juce_core/files/juce_File.h
  64. 4
      JuceLibraryCode/modules/juce_core/files/juce_TemporaryFile.cpp
  65. 2
      JuceLibraryCode/modules/juce_core/files/juce_TemporaryFile.h
  66. 14
      JuceLibraryCode/modules/juce_core/javascript/juce_JSON.cpp
  67. 5
      JuceLibraryCode/modules/juce_core/javascript/juce_Javascript.cpp
  68. 1
      JuceLibraryCode/modules/juce_core/javascript/juce_Javascript.h
  69. 2
      JuceLibraryCode/modules/juce_core/juce_module_info
  70. 2
      JuceLibraryCode/modules/juce_core/maths/juce_BigInteger.cpp
  71. 4
      JuceLibraryCode/modules/juce_core/maths/juce_Expression.cpp
  72. 1
      JuceLibraryCode/modules/juce_core/misc/juce_Uuid.cpp
  73. 2
      JuceLibraryCode/modules/juce_core/native/juce_android_Files.cpp
  74. 6
      JuceLibraryCode/modules/juce_core/native/juce_linux_Files.cpp
  75. 6
      JuceLibraryCode/modules/juce_core/native/juce_linux_Network.cpp
  76. 8
      JuceLibraryCode/modules/juce_core/native/juce_linux_SystemStats.cpp
  77. 4
      JuceLibraryCode/modules/juce_core/native/juce_mac_Files.mm
  78. 2
      JuceLibraryCode/modules/juce_core/native/juce_mac_Strings.mm
  79. 8
      JuceLibraryCode/modules/juce_core/native/juce_mac_SystemStats.mm
  80. 2
      JuceLibraryCode/modules/juce_core/native/juce_posix_SharedCode.h
  81. 4
      JuceLibraryCode/modules/juce_core/native/juce_win32_Files.cpp
  82. 2
      JuceLibraryCode/modules/juce_core/network/juce_IPAddress.cpp
  83. 4
      JuceLibraryCode/modules/juce_core/network/juce_Socket.cpp
  84. 2
      JuceLibraryCode/modules/juce_core/network/juce_Socket.h
  85. 8
      JuceLibraryCode/modules/juce_core/network/juce_URL.cpp
  86. 2
      JuceLibraryCode/modules/juce_core/network/juce_URL.h
  87. 2
      JuceLibraryCode/modules/juce_core/system/juce_StandardHeader.h
  88. 17
      JuceLibraryCode/modules/juce_core/text/juce_LocalisedStrings.cpp
  89. 7
      JuceLibraryCode/modules/juce_core/text/juce_LocalisedStrings.h
  90. 9
      JuceLibraryCode/modules/juce_core/text/juce_String.cpp
  91. 3
      JuceLibraryCode/modules/juce_core/text/juce_String.h
  92. 2
      JuceLibraryCode/modules/juce_core/text/juce_StringArray.cpp
  93. 5
      JuceLibraryCode/modules/juce_core/text/juce_StringPairArray.cpp
  94. 2
      JuceLibraryCode/modules/juce_core/text/juce_StringPairArray.h
  95. 6
      JuceLibraryCode/modules/juce_core/text/juce_StringPool.cpp
  96. 2
      JuceLibraryCode/modules/juce_core/threads/juce_ThreadPool.h
  97. 2
      JuceLibraryCode/modules/juce_core/time/juce_PerformanceCounter.cpp
  98. 2
      JuceLibraryCode/modules/juce_core/time/juce_PerformanceCounter.h
  99. 2
      JuceLibraryCode/modules/juce_core/xml/juce_XmlDocument.cpp
  100. 2
      JuceLibraryCode/modules/juce_core/zip/juce_ZipFile.cpp
  101. Some files were not shown because too many files have changed in this diff Show More

@ -86,6 +86,7 @@
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"; };
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"; };
07CB27E064E2A82C2B1D3832 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_AbstractFifo.h"; path = "../../JuceLibraryCode/modules/juce_core/containers/juce_AbstractFifo.h"; sourceTree = "SOURCE_ROOT"; }; 07CB27E064E2A82C2B1D3832 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_AbstractFifo.h"; path = "../../JuceLibraryCode/modules/juce_core/containers/juce_AbstractFifo.h"; sourceTree = "SOURCE_ROOT"; };
0A3CCDBDD4238A7F9CB559BD = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_FilenameComponent.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FilenameComponent.h"; sourceTree = "SOURCE_ROOT"; }; 0A3CCDBDD4238A7F9CB559BD = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_FilenameComponent.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FilenameComponent.h"; sourceTree = "SOURCE_ROOT"; };
0A55490419140DC6D2FBB1DA = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ComboBox.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/widgets/juce_ComboBox.cpp"; sourceTree = "SOURCE_ROOT"; }; 0A55490419140DC6D2FBB1DA = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ComboBox.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/widgets/juce_ComboBox.cpp"; sourceTree = "SOURCE_ROOT"; };
@ -129,6 +130,7 @@
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"; };
18D52C793029AFCC92C77A75 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_LiveConstantEditor.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_extra/misc/juce_LiveConstantEditor.cpp"; sourceTree = "SOURCE_ROOT"; };
1914E45DEAEBD1592581F1FD = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_AudioPluginFormatManager.h"; path = "../../JuceLibraryCode/modules/juce_audio_processors/format/juce_AudioPluginFormatManager.h"; sourceTree = "SOURCE_ROOT"; }; 1914E45DEAEBD1592581F1FD = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_AudioPluginFormatManager.h"; path = "../../JuceLibraryCode/modules/juce_audio_processors/format/juce_AudioPluginFormatManager.h"; sourceTree = "SOURCE_ROOT"; };
195B617C1FF754108A97F645 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_KeyPressMappingSet.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/commands/juce_KeyPressMappingSet.h"; sourceTree = "SOURCE_ROOT"; }; 195B617C1FF754108A97F645 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_KeyPressMappingSet.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/commands/juce_KeyPressMappingSet.h"; sourceTree = "SOURCE_ROOT"; };
19B56FF22ED0090A8D7A3E04 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_gui_basics.mm"; path = "../../JuceLibraryCode/modules/juce_gui_basics/juce_gui_basics.mm"; sourceTree = "SOURCE_ROOT"; }; 19B56FF22ED0090A8D7A3E04 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_gui_basics.mm"; path = "../../JuceLibraryCode/modules/juce_gui_basics/juce_gui_basics.mm"; sourceTree = "SOURCE_ROOT"; };
@ -294,6 +296,7 @@
45F6575A7BDB9134EAEA7633 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ActiveXControlComponent.h"; path = "../../JuceLibraryCode/modules/juce_gui_extra/embedding/juce_ActiveXControlComponent.h"; sourceTree = "SOURCE_ROOT"; }; 45F6575A7BDB9134EAEA7633 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ActiveXControlComponent.h"; path = "../../JuceLibraryCode/modules/juce_gui_extra/embedding/juce_ActiveXControlComponent.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"; }; 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"; };
46B8FB88F2949700DD70A821 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_WildcardFileFilter.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_WildcardFileFilter.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"; };
@ -398,6 +401,7 @@
6D256DC39965C982ADAAFA81 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_FillType.h"; path = "../../JuceLibraryCode/modules/juce_graphics/colour/juce_FillType.h"; sourceTree = "SOURCE_ROOT"; }; 6D256DC39965C982ADAAFA81 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_FillType.h"; path = "../../JuceLibraryCode/modules/juce_graphics/colour/juce_FillType.h"; sourceTree = "SOURCE_ROOT"; };
6DC26B61BA1638AFAF142A6C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_gui_extra.mm"; path = "../../JuceLibraryCode/modules/juce_gui_extra/juce_gui_extra.mm"; sourceTree = "SOURCE_ROOT"; }; 6DC26B61BA1638AFAF142A6C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_gui_extra.mm"; path = "../../JuceLibraryCode/modules/juce_gui_extra/juce_gui_extra.mm"; sourceTree = "SOURCE_ROOT"; };
6DCB546B40A962FCA3C74DB9 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ColourGradient.h"; path = "../../JuceLibraryCode/modules/juce_graphics/colour/juce_ColourGradient.h"; sourceTree = "SOURCE_ROOT"; }; 6DCB546B40A962FCA3C74DB9 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ColourGradient.h"; path = "../../JuceLibraryCode/modules/juce_graphics/colour/juce_ColourGradient.h"; sourceTree = "SOURCE_ROOT"; };
6DEFC761C7F27A8ED88790B4 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_XMLCodeTokeniser.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_extra/code_editor/juce_XMLCodeTokeniser.cpp"; sourceTree = "SOURCE_ROOT"; };
6E2A781F28B3F735F4FAB2A2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_KeyMappingEditorComponent.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_extra/misc/juce_KeyMappingEditorComponent.cpp"; sourceTree = "SOURCE_ROOT"; }; 6E2A781F28B3F735F4FAB2A2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_KeyMappingEditorComponent.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_extra/misc/juce_KeyMappingEditorComponent.cpp"; sourceTree = "SOURCE_ROOT"; };
6E84E300D2ECD62ED1ED3478 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_FileInputSource.h"; path = "../../JuceLibraryCode/modules/juce_core/streams/juce_FileInputSource.h"; sourceTree = "SOURCE_ROOT"; }; 6E84E300D2ECD62ED1ED3478 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_FileInputSource.h"; path = "../../JuceLibraryCode/modules/juce_core/streams/juce_FileInputSource.h"; sourceTree = "SOURCE_ROOT"; };
6E8FC799E88893F8CD15BB71 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_LADSPAPluginFormat.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.cpp"; sourceTree = "SOURCE_ROOT"; }; 6E8FC799E88893F8CD15BB71 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_LADSPAPluginFormat.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.cpp"; sourceTree = "SOURCE_ROOT"; };
@ -838,6 +842,7 @@
F957420DFF4D2354671B4116 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_RectanglePlacement.cpp"; path = "../../JuceLibraryCode/modules/juce_graphics/placement/juce_RectanglePlacement.cpp"; sourceTree = "SOURCE_ROOT"; }; F957420DFF4D2354671B4116 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_RectanglePlacement.cpp"; path = "../../JuceLibraryCode/modules/juce_graphics/placement/juce_RectanglePlacement.cpp"; sourceTree = "SOURCE_ROOT"; };
F9B29C9F01195D5A979AB5C9 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_SVGParser.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/drawables/juce_SVGParser.cpp"; sourceTree = "SOURCE_ROOT"; }; F9B29C9F01195D5A979AB5C9 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_SVGParser.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/drawables/juce_SVGParser.cpp"; sourceTree = "SOURCE_ROOT"; };
F9FA29A5FF9C9921D785A1C0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_LookAndFeel_V1.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V1.cpp"; sourceTree = "SOURCE_ROOT"; }; F9FA29A5FF9C9921D785A1C0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_LookAndFeel_V1.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V1.cpp"; sourceTree = "SOURCE_ROOT"; };
FA0406B777C1CB9C71F86BC1 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_LuaCodeTokeniser.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_extra/code_editor/juce_LuaCodeTokeniser.cpp"; sourceTree = "SOURCE_ROOT"; };
FA726CE9275EF0E84BBEA666 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_LinkedListPointer.h"; path = "../../JuceLibraryCode/modules/juce_core/containers/juce_LinkedListPointer.h"; sourceTree = "SOURCE_ROOT"; }; FA726CE9275EF0E84BBEA666 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_LinkedListPointer.h"; path = "../../JuceLibraryCode/modules/juce_core/containers/juce_LinkedListPointer.h"; sourceTree = "SOURCE_ROOT"; };
FA98BC06299525310A31107B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Label.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/widgets/juce_Label.h"; sourceTree = "SOURCE_ROOT"; }; FA98BC06299525310A31107B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Label.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/widgets/juce_Label.h"; sourceTree = "SOURCE_ROOT"; };
FAC5045BEAA6C0B1AC904BED = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_TextDragAndDropTarget.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h"; sourceTree = "SOURCE_ROOT"; }; FAC5045BEAA6C0B1AC904BED = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_TextDragAndDropTarget.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h"; sourceTree = "SOURCE_ROOT"; };
@ -847,6 +852,7 @@
FC452B781AEE181BEF7F948E = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ComponentPeer.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/windows/juce_ComponentPeer.cpp"; sourceTree = "SOURCE_ROOT"; }; FC452B781AEE181BEF7F948E = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ComponentPeer.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/windows/juce_ComponentPeer.cpp"; sourceTree = "SOURCE_ROOT"; };
FC856709502EE15E8D3F448B = { isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; FC856709502EE15E8D3F448B = { isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; };
FCABD85F0480D4972896F379 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ReverbAudioSource.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_basics/sources/juce_ReverbAudioSource.cpp"; sourceTree = "SOURCE_ROOT"; }; FCABD85F0480D4972896F379 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ReverbAudioSource.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_basics/sources/juce_ReverbAudioSource.cpp"; sourceTree = "SOURCE_ROOT"; };
FCBA692E842A80D9618CA467 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_LiveConstantEditor.h"; path = "../../JuceLibraryCode/modules/juce_gui_extra/misc/juce_LiveConstantEditor.h"; sourceTree = "SOURCE_ROOT"; };
FD2285710D78FDBC856ADF13 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_AudioProcessorPlayer.h"; path = "../../JuceLibraryCode/modules/juce_audio_utils/players/juce_AudioProcessorPlayer.h"; sourceTree = "SOURCE_ROOT"; }; FD2285710D78FDBC856ADF13 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_AudioProcessorPlayer.h"; path = "../../JuceLibraryCode/modules/juce_audio_utils/players/juce_AudioProcessorPlayer.h"; sourceTree = "SOURCE_ROOT"; };
FD333147C1339A81B846EC52 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_RecentlyOpenedFilesList.h"; path = "../../JuceLibraryCode/modules/juce_gui_extra/misc/juce_RecentlyOpenedFilesList.h"; sourceTree = "SOURCE_ROOT"; }; FD333147C1339A81B846EC52 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_RecentlyOpenedFilesList.h"; path = "../../JuceLibraryCode/modules/juce_gui_extra/misc/juce_RecentlyOpenedFilesList.h"; sourceTree = "SOURCE_ROOT"; };
FD799268DEA0EC4CDFD4DA10 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_NewLine.h"; path = "../../JuceLibraryCode/modules/juce_core/text/juce_NewLine.h"; sourceTree = "SOURCE_ROOT"; }; FD799268DEA0EC4CDFD4DA10 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_NewLine.h"; path = "../../JuceLibraryCode/modules/juce_core/text/juce_NewLine.h"; sourceTree = "SOURCE_ROOT"; };
@ -1741,7 +1747,11 @@
5DE3DC6998A92F718C9683FA, 5DE3DC6998A92F718C9683FA,
71DFB6F3C44390C0FD109073, 71DFB6F3C44390C0FD109073,
7E68BB771E88E0A2A323D365, 7E68BB771E88E0A2A323D365,
588255FD68989F1A03FDF31C ); name = "code_editor"; sourceTree = "<group>"; }; 588255FD68989F1A03FDF31C,
FA0406B777C1CB9C71F86BC1,
076C4F22CCC47AFEAC2D0C68,
6DEFC761C7F27A8ED88790B4,
46969E6B78BC89383358DCDA ); name = "code_editor"; sourceTree = "<group>"; };
3BAE6D34CB0FFE32A18C6008 = { isa = PBXGroup; children = ( 3BAE6D34CB0FFE32A18C6008 = { isa = PBXGroup; children = (
BAA44451865610A98B3A69AE, BAA44451865610A98B3A69AE,
346937AF08405CC63D570161 ); name = documents; sourceTree = "<group>"; }; 346937AF08405CC63D570161 ); name = documents; sourceTree = "<group>"; };
@ -1757,6 +1767,8 @@
4F977F1C295B0D355391AAD3, 4F977F1C295B0D355391AAD3,
6E2A781F28B3F735F4FAB2A2, 6E2A781F28B3F735F4FAB2A2,
A00DC4E59356AF5F1D9C02D1, A00DC4E59356AF5F1D9C02D1,
18D52C793029AFCC92C77A75,
FCBA692E842A80D9618CA467,
5BFC8D75FFE4E8DEE50B3B1A, 5BFC8D75FFE4E8DEE50B3B1A,
A062855D9DD17397012BC224, A062855D9DD17397012BC224,
AE8321756C03700EB12FF98A, AE8321756C03700EB12FF98A,

@ -1036,6 +1036,12 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CPlusPlusCodeTokeniser.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CPlusPlusCodeTokeniser.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_LuaCodeTokeniser.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_XMLCodeTokeniser.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\documents\juce_FileBasedDocument.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\documents\juce_FileBasedDocument.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
@ -1048,6 +1054,9 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_KeyMappingEditorComponent.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_KeyMappingEditorComponent.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_LiveConstantEditor.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_PreferencesPanel.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_PreferencesPanel.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
@ -1502,6 +1511,8 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CodeTokeniser.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CodeTokeniser.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CPlusPlusCodeTokeniser.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CPlusPlusCodeTokeniser.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CPlusPlusCodeTokeniserFunctions.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CPlusPlusCodeTokeniserFunctions.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_LuaCodeTokeniser.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_XMLCodeTokeniser.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\documents\juce_FileBasedDocument.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\documents\juce_FileBasedDocument.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\embedding\juce_ActiveXControlComponent.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\embedding\juce_ActiveXControlComponent.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\embedding\juce_NSViewComponent.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\embedding\juce_NSViewComponent.h"/>
@ -1510,6 +1521,7 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_BubbleMessageComponent.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_BubbleMessageComponent.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_ColourSelector.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_ColourSelector.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_KeyMappingEditorComponent.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_KeyMappingEditorComponent.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_LiveConstantEditor.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_PreferencesPanel.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_PreferencesPanel.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_RecentlyOpenedFilesList.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_RecentlyOpenedFilesList.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_SplashScreen.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_SplashScreen.h"/>

@ -1270,6 +1270,12 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CPlusPlusCodeTokeniser.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CPlusPlusCodeTokeniser.cpp">
<Filter>Juce Modules\juce_gui_extra\code_editor</Filter> <Filter>Juce Modules\juce_gui_extra\code_editor</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_LuaCodeTokeniser.cpp">
<Filter>Juce Modules\juce_gui_extra\code_editor</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_XMLCodeTokeniser.cpp">
<Filter>Juce Modules\juce_gui_extra\code_editor</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\documents\juce_FileBasedDocument.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\documents\juce_FileBasedDocument.cpp">
<Filter>Juce Modules\juce_gui_extra\documents</Filter> <Filter>Juce Modules\juce_gui_extra\documents</Filter>
</ClCompile> </ClCompile>
@ -1282,6 +1288,9 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_KeyMappingEditorComponent.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_KeyMappingEditorComponent.cpp">
<Filter>Juce Modules\juce_gui_extra\misc</Filter> <Filter>Juce Modules\juce_gui_extra\misc</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_LiveConstantEditor.cpp">
<Filter>Juce Modules\juce_gui_extra\misc</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_PreferencesPanel.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_PreferencesPanel.cpp">
<Filter>Juce Modules\juce_gui_extra\misc</Filter> <Filter>Juce Modules\juce_gui_extra\misc</Filter>
</ClCompile> </ClCompile>
@ -2556,6 +2565,12 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CPlusPlusCodeTokeniserFunctions.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CPlusPlusCodeTokeniserFunctions.h">
<Filter>Juce Modules\juce_gui_extra\code_editor</Filter> <Filter>Juce Modules\juce_gui_extra\code_editor</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_LuaCodeTokeniser.h">
<Filter>Juce Modules\juce_gui_extra\code_editor</Filter>
</ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_XMLCodeTokeniser.h">
<Filter>Juce Modules\juce_gui_extra\code_editor</Filter>
</ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\documents\juce_FileBasedDocument.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\documents\juce_FileBasedDocument.h">
<Filter>Juce Modules\juce_gui_extra\documents</Filter> <Filter>Juce Modules\juce_gui_extra\documents</Filter>
</ClInclude> </ClInclude>
@ -2580,6 +2595,9 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_KeyMappingEditorComponent.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_KeyMappingEditorComponent.h">
<Filter>Juce Modules\juce_gui_extra\misc</Filter> <Filter>Juce Modules\juce_gui_extra\misc</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_LiveConstantEditor.h">
<Filter>Juce Modules\juce_gui_extra\misc</Filter>
</ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_PreferencesPanel.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_PreferencesPanel.h">
<Filter>Juce Modules\juce_gui_extra\misc</Filter> <Filter>Juce Modules\juce_gui_extra\misc</Filter>
</ClInclude> </ClInclude>

@ -1036,6 +1036,12 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CPlusPlusCodeTokeniser.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CPlusPlusCodeTokeniser.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_LuaCodeTokeniser.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_XMLCodeTokeniser.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\documents\juce_FileBasedDocument.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\documents\juce_FileBasedDocument.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
@ -1048,6 +1054,9 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_KeyMappingEditorComponent.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_KeyMappingEditorComponent.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_LiveConstantEditor.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_PreferencesPanel.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_PreferencesPanel.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild> <ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile> </ClCompile>
@ -1502,6 +1511,8 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CodeTokeniser.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CodeTokeniser.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CPlusPlusCodeTokeniser.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CPlusPlusCodeTokeniser.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CPlusPlusCodeTokeniserFunctions.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CPlusPlusCodeTokeniserFunctions.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_LuaCodeTokeniser.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_XMLCodeTokeniser.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\documents\juce_FileBasedDocument.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\documents\juce_FileBasedDocument.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\embedding\juce_ActiveXControlComponent.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\embedding\juce_ActiveXControlComponent.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\embedding\juce_NSViewComponent.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\embedding\juce_NSViewComponent.h"/>
@ -1510,6 +1521,7 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_BubbleMessageComponent.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_BubbleMessageComponent.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_ColourSelector.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_ColourSelector.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_KeyMappingEditorComponent.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_KeyMappingEditorComponent.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_LiveConstantEditor.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_PreferencesPanel.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_PreferencesPanel.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_RecentlyOpenedFilesList.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_RecentlyOpenedFilesList.h"/>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_SplashScreen.h"/> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_SplashScreen.h"/>

@ -1270,6 +1270,12 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CPlusPlusCodeTokeniser.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CPlusPlusCodeTokeniser.cpp">
<Filter>Juce Modules\juce_gui_extra\code_editor</Filter> <Filter>Juce Modules\juce_gui_extra\code_editor</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_LuaCodeTokeniser.cpp">
<Filter>Juce Modules\juce_gui_extra\code_editor</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_XMLCodeTokeniser.cpp">
<Filter>Juce Modules\juce_gui_extra\code_editor</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\documents\juce_FileBasedDocument.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\documents\juce_FileBasedDocument.cpp">
<Filter>Juce Modules\juce_gui_extra\documents</Filter> <Filter>Juce Modules\juce_gui_extra\documents</Filter>
</ClCompile> </ClCompile>
@ -1282,6 +1288,9 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_KeyMappingEditorComponent.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_KeyMappingEditorComponent.cpp">
<Filter>Juce Modules\juce_gui_extra\misc</Filter> <Filter>Juce Modules\juce_gui_extra\misc</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_LiveConstantEditor.cpp">
<Filter>Juce Modules\juce_gui_extra\misc</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_PreferencesPanel.cpp"> <ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_PreferencesPanel.cpp">
<Filter>Juce Modules\juce_gui_extra\misc</Filter> <Filter>Juce Modules\juce_gui_extra\misc</Filter>
</ClCompile> </ClCompile>
@ -2556,6 +2565,12 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CPlusPlusCodeTokeniserFunctions.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_CPlusPlusCodeTokeniserFunctions.h">
<Filter>Juce Modules\juce_gui_extra\code_editor</Filter> <Filter>Juce Modules\juce_gui_extra\code_editor</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_LuaCodeTokeniser.h">
<Filter>Juce Modules\juce_gui_extra\code_editor</Filter>
</ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\code_editor\juce_XMLCodeTokeniser.h">
<Filter>Juce Modules\juce_gui_extra\code_editor</Filter>
</ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\documents\juce_FileBasedDocument.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\documents\juce_FileBasedDocument.h">
<Filter>Juce Modules\juce_gui_extra\documents</Filter> <Filter>Juce Modules\juce_gui_extra\documents</Filter>
</ClInclude> </ClInclude>
@ -2580,6 +2595,9 @@
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_KeyMappingEditorComponent.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_KeyMappingEditorComponent.h">
<Filter>Juce Modules\juce_gui_extra\misc</Filter> <Filter>Juce Modules\juce_gui_extra\misc</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_LiveConstantEditor.h">
<Filter>Juce Modules\juce_gui_extra\misc</Filter>
</ClInclude>
<ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_PreferencesPanel.h"> <ClInclude Include="..\..\JuceLibraryCode\modules\juce_gui_extra\misc\juce_PreferencesPanel.h">
<Filter>Juce Modules\juce_gui_extra\misc</Filter> <Filter>Juce Modules\juce_gui_extra\misc</Filter>
</ClInclude> </ClInclude>

@ -168,6 +168,10 @@
//#define JUCE_WEB_BROWSER //#define JUCE_WEB_BROWSER
#endif #endif
#ifndef JUCE_ENABLE_LIVE_CONSTANT_EDITOR
//#define JUCE_ENABLE_LIVE_CONSTANT_EDITOR
#endif
//============================================================================== //==============================================================================
// Audio plugin settings.. // Audio plugin settings..

@ -22,10 +22,13 @@
============================================================================== ==============================================================================
*/ */
#if JUCE_USE_SSE_INTRINSICS
namespace FloatVectorHelpers namespace FloatVectorHelpers
{ {
#define JUCE_INCREMENT_SRC_DEST dest += 4; src += 4;
#define JUCE_INCREMENT_DEST dest += 4;
#if JUCE_USE_SSE_INTRINSICS
static bool sse2Present = false; static bool sse2Present = false;
static bool isSSE2Available() noexcept static bool isSSE2Available() noexcept
@ -44,7 +47,6 @@ namespace FloatVectorHelpers
static inline float findMinimumOrMaximum (const float* src, int num, const bool isMinimum) noexcept static inline float findMinimumOrMaximum (const float* src, int num, const bool isMinimum) noexcept
{ {
#if JUCE_USE_SSE_INTRINSICS
const int numLongOps = num / 4; const int numLongOps = num / 4;
if (numLongOps > 1 && FloatVectorHelpers::isSSE2Available()) if (numLongOps > 1 && FloatVectorHelpers::isSSE2Available())
@ -90,12 +92,10 @@ namespace FloatVectorHelpers
return localVal; return localVal;
} }
#endif
return isMinimum ? juce::findMinimum (src, num) return isMinimum ? juce::findMinimum (src, num)
: juce::findMaximum (src, num); : juce::findMaximum (src, num);
} }
}
#define JUCE_BEGIN_SSE_OP \ #define JUCE_BEGIN_SSE_OP \
if (FloatVectorHelpers::isSSE2Available()) \ if (FloatVectorHelpers::isSSE2Available()) \
@ -116,9 +116,6 @@ namespace FloatVectorHelpers
increment; \ increment; \
} }
#define JUCE_INCREMENT_SRC_DEST dest += 4; src += 4;
#define JUCE_INCREMENT_DEST dest += 4;
#define JUCE_LOAD_NONE(srcLoad, dstLoad) #define JUCE_LOAD_NONE(srcLoad, dstLoad)
#define JUCE_LOAD_DEST(srcLoad, dstLoad) const __m128 d = dstLoad (dest); #define JUCE_LOAD_DEST(srcLoad, dstLoad) const __m128 d = dstLoad (dest);
#define JUCE_LOAD_SRC(srcLoad, dstLoad) const __m128 s = srcLoad (src); #define JUCE_LOAD_SRC(srcLoad, dstLoad) const __m128 s = srcLoad (src);
@ -145,11 +142,92 @@ namespace FloatVectorHelpers
JUCE_FINISH_SSE_OP (normalOp) JUCE_FINISH_SSE_OP (normalOp)
//==============================================================================
#elif JUCE_USE_ARM_NEON
static inline float findMinimumOrMaximum (const float* src, int num, const bool isMinimum) noexcept
{
const int numLongOps = num / 4;
if (numLongOps > 1)
{
float32x4_t val;
#define JUCE_MINIMUMMAXIMUM_NEON_LOOP(loadOp, minMaxOp) \
val = loadOp (src); \
src += 4; \
for (int i = 1; i < numLongOps; ++i) \
{ \
const float32x4_t s = loadOp (src); \
val = minMaxOp (val, s); \
src += 4; \
}
if (isMinimum) { JUCE_MINIMUMMAXIMUM_NEON_LOOP (vld1q_f32, vminq_f32) }
else { JUCE_MINIMUMMAXIMUM_NEON_LOOP (vld1q_f32, vmaxq_f32) }
float localVal;
{
float vals[4];
vst1q_f32 (vals, val);
localVal = isMinimum ? jmin (vals[0], vals[1], vals[2], vals[3])
: jmax (vals[0], vals[1], vals[2], vals[3]);
}
num &= 3;
for (int i = 0; i < num; ++i)
localVal = isMinimum ? jmin (localVal, src[i])
: jmax (localVal, src[i]);
return localVal;
}
return isMinimum ? juce::findMinimum (src, num)
: juce::findMaximum (src, num);
}
#define JUCE_BEGIN_NEON_OP \
const int numLongOps = num / 4;
#define JUCE_FINISH_NEON_OP(normalOp) \
num &= 3; \
if (num == 0) return; \
for (int i = 0; i < num; ++i) normalOp;
#define JUCE_NEON_LOOP(neonOp, srcLoad, dstLoad, dstStore, locals, increment) \
for (int i = 0; i < numLongOps; ++i) \
{ \
locals (srcLoad, dstLoad); \
dstStore (dest, neonOp); \
increment; \
}
#define JUCE_LOAD_NONE(srcLoad, dstLoad)
#define JUCE_LOAD_DEST(srcLoad, dstLoad) const float32x4_t d = dstLoad (dest);
#define JUCE_LOAD_SRC(srcLoad, dstLoad) const float32x4_t s = srcLoad (src);
#define JUCE_LOAD_SRC_DEST(srcLoad, dstLoad) const float32x4_t d = dstLoad (dest); const float32x4_t s = srcLoad (src);
#define JUCE_PERFORM_NEON_OP_DEST(normalOp, neonOp, locals) \
JUCE_BEGIN_NEON_OP \
JUCE_NEON_LOOP (neonOp, dummy, vld1q_f32, vst1q_f32, locals, JUCE_INCREMENT_DEST) \
JUCE_FINISH_NEON_OP (normalOp)
#define JUCE_PERFORM_NEON_OP_SRC_DEST(normalOp, neonOp, locals) \
JUCE_BEGIN_NEON_OP \
JUCE_NEON_LOOP (neonOp, vld1q_f32, vld1q_f32, vst1q_f32, locals, JUCE_INCREMENT_SRC_DEST) \
JUCE_FINISH_NEON_OP (normalOp)
//==============================================================================
#else #else
#define JUCE_PERFORM_SSE_OP_DEST(normalOp, unused1, unused2) for (int i = 0; i < num; ++i) normalOp; #define JUCE_PERFORM_SSE_OP_DEST(normalOp, unused1, unused2) for (int i = 0; i < num; ++i) normalOp;
#define JUCE_PERFORM_SSE_OP_SRC_DEST(normalOp, sseOp, locals, increment) for (int i = 0; i < num; ++i) normalOp; #define JUCE_PERFORM_SSE_OP_SRC_DEST(normalOp, sseOp, locals, increment) for (int i = 0; i < num; ++i) normalOp;
#endif #endif
}
//==============================================================================
void JUCE_CALLTYPE FloatVectorOperations::clear (float* dest, int num) noexcept void JUCE_CALLTYPE FloatVectorOperations::clear (float* dest, int num) noexcept
{ {
#if JUCE_USE_VDSP_FRAMEWORK #if JUCE_USE_VDSP_FRAMEWORK
@ -163,11 +241,13 @@ void JUCE_CALLTYPE FloatVectorOperations::fill (float* dest, float valueToFill,
{ {
#if JUCE_USE_VDSP_FRAMEWORK #if JUCE_USE_VDSP_FRAMEWORK
vDSP_vfill (&valueToFill, dest, 1, (size_t) num); vDSP_vfill (&valueToFill, dest, 1, (size_t) num);
#elif JUCE_USE_ARM_NEON
const float32x4_t val = vld1q_dup_f32 (&valueToFill);
JUCE_PERFORM_NEON_OP_DEST (dest[i] = valueToFill, val, JUCE_LOAD_NONE)
#else #else
#if JUCE_USE_SSE_INTRINSICS #if JUCE_USE_SSE_INTRINSICS
const __m128 val = _mm_load1_ps (&valueToFill); const __m128 val = _mm_load1_ps (&valueToFill);
#endif #endif
JUCE_PERFORM_SSE_OP_DEST (dest[i] = valueToFill, val, JUCE_LOAD_NONE) JUCE_PERFORM_SSE_OP_DEST (dest[i] = valueToFill, val, JUCE_LOAD_NONE)
#endif #endif
} }
@ -181,41 +261,59 @@ void JUCE_CALLTYPE FloatVectorOperations::copyWithMultiply (float* dest, const f
{ {
#if JUCE_USE_VDSP_FRAMEWORK #if JUCE_USE_VDSP_FRAMEWORK
vDSP_vsmul (src, 1, &multiplier, dest, 1, num); vDSP_vsmul (src, 1, &multiplier, dest, 1, num);
#elif JUCE_USE_ARM_NEON
JUCE_PERFORM_NEON_OP_SRC_DEST (dest[i] += src[i], vmulq_n_f32(s, multiplier), JUCE_LOAD_SRC)
#else #else
#if JUCE_USE_SSE_INTRINSICS #if JUCE_USE_SSE_INTRINSICS
const __m128 mult = _mm_load1_ps (&multiplier); const __m128 mult = _mm_load1_ps (&multiplier);
#endif #endif
JUCE_PERFORM_SSE_OP_SRC_DEST (dest[i] = src[i] * multiplier, _mm_mul_ps (mult, s),
JUCE_PERFORM_SSE_OP_SRC_DEST (dest[i] = src[i] * multiplier,
_mm_mul_ps (mult, s),
JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST) JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST)
#endif #endif
} }
void JUCE_CALLTYPE FloatVectorOperations::add (float* dest, float amount, int num) noexcept
{
#if JUCE_USE_ARM_NEON
const float32x4_t amountToAdd = vld1q_dup_f32(&amount);
JUCE_PERFORM_NEON_OP_DEST (dest[i] += amount, vaddq_f32 (d, amountToAdd), JUCE_LOAD_DEST)
#else
#if JUCE_USE_SSE_INTRINSICS
const __m128 amountToAdd = _mm_load1_ps (&amount);
#endif
JUCE_PERFORM_SSE_OP_DEST (dest[i] += amount, _mm_add_ps (d, amountToAdd), JUCE_LOAD_DEST)
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::add (float* dest, const float* src, int num) noexcept void JUCE_CALLTYPE FloatVectorOperations::add (float* dest, const float* src, int num) noexcept
{ {
#if JUCE_USE_VDSP_FRAMEWORK #if JUCE_USE_VDSP_FRAMEWORK
vDSP_vadd (src, 1, dest, 1, dest, 1, num); vDSP_vadd (src, 1, dest, 1, dest, 1, num);
#elif JUCE_USE_ARM_NEON
JUCE_PERFORM_NEON_OP_SRC_DEST (dest[i] += src[i], vaddq_f32 (d, s), JUCE_LOAD_SRC_DEST)
#else #else
JUCE_PERFORM_SSE_OP_SRC_DEST (dest[i] += src[i], JUCE_PERFORM_SSE_OP_SRC_DEST (dest[i] += src[i], _mm_add_ps (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST)
_mm_add_ps (d, s),
JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST)
#endif #endif
} }
void JUCE_CALLTYPE FloatVectorOperations::add (float* dest, float amount, int num) noexcept void JUCE_CALLTYPE FloatVectorOperations::subtract (float* dest, const float* src, int num) noexcept
{ {
#if JUCE_USE_SSE_INTRINSICS #if JUCE_USE_VDSP_FRAMEWORK
const __m128 amountToAdd = _mm_load1_ps (&amount); vDSP_vsub (src, 1, dest, 1, dest, 1, num);
#elif JUCE_USE_ARM_NEON
JUCE_PERFORM_NEON_OP_SRC_DEST (dest[i] -= src[i], vsubq_f32 (d, s), JUCE_LOAD_SRC_DEST)
#else
JUCE_PERFORM_SSE_OP_SRC_DEST (dest[i] -= src[i], _mm_sub_ps (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST)
#endif #endif
JUCE_PERFORM_SSE_OP_DEST (dest[i] += amount,
_mm_add_ps (d, amountToAdd),
JUCE_LOAD_DEST)
} }
void JUCE_CALLTYPE FloatVectorOperations::addWithMultiply (float* dest, const float* src, float multiplier, int num) noexcept void JUCE_CALLTYPE FloatVectorOperations::addWithMultiply (float* dest, const float* src, float multiplier, int num) noexcept
{ {
#if JUCE_USE_ARM_NEON
JUCE_PERFORM_NEON_OP_SRC_DEST (dest[i] += src[i] * multiplier,
vmlaq_n_f32 (d, s, multiplier),
JUCE_LOAD_SRC_DEST)
#else
#if JUCE_USE_SSE_INTRINSICS #if JUCE_USE_SSE_INTRINSICS
const __m128 mult = _mm_load1_ps (&multiplier); const __m128 mult = _mm_load1_ps (&multiplier);
#endif #endif
@ -223,16 +321,18 @@ void JUCE_CALLTYPE FloatVectorOperations::addWithMultiply (float* dest, const fl
JUCE_PERFORM_SSE_OP_SRC_DEST (dest[i] += src[i] * multiplier, JUCE_PERFORM_SSE_OP_SRC_DEST (dest[i] += src[i] * multiplier,
_mm_add_ps (d, _mm_mul_ps (mult, s)), _mm_add_ps (d, _mm_mul_ps (mult, s)),
JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST) JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST)
#endif
} }
void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, const float* src, int num) noexcept void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, const float* src, int num) noexcept
{ {
#if JUCE_USE_VDSP_FRAMEWORK #if JUCE_USE_VDSP_FRAMEWORK
vDSP_vmul (src, 1, dest, 1, dest, 1, num); vDSP_vmul (src, 1, dest, 1, dest, 1, num);
#elif JUCE_USE_ARM_NEON
JUCE_PERFORM_NEON_OP_SRC_DEST (dest[i] *= src[i], vmulq_f32 (d, s), JUCE_LOAD_SRC_DEST)
#else #else
JUCE_PERFORM_SSE_OP_SRC_DEST (dest[i] *= src[i], JUCE_PERFORM_SSE_OP_SRC_DEST (dest[i] *= src[i], _mm_mul_ps (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST)
_mm_mul_ps (d, s),
JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST)
#endif #endif
} }
@ -240,14 +340,13 @@ void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, float multiplie
{ {
#if JUCE_USE_VDSP_FRAMEWORK #if JUCE_USE_VDSP_FRAMEWORK
vDSP_vsmul (dest, 1, &multiplier, dest, 1, num); vDSP_vsmul (dest, 1, &multiplier, dest, 1, num);
#elif JUCE_USE_ARM_NEON
JUCE_PERFORM_NEON_OP_DEST (dest[i] *= multiplier, vmulq_n_f32 (d, multiplier), JUCE_LOAD_DEST)
#else #else
#if JUCE_USE_SSE_INTRINSICS #if JUCE_USE_SSE_INTRINSICS
const __m128 mult = _mm_load1_ps (&multiplier); const __m128 mult = _mm_load1_ps (&multiplier);
#endif #endif
JUCE_PERFORM_SSE_OP_DEST (dest[i] *= multiplier, _mm_mul_ps (d, mult), JUCE_LOAD_DEST)
JUCE_PERFORM_SSE_OP_DEST (dest[i] *= multiplier,
_mm_mul_ps (d, mult),
JUCE_LOAD_DEST)
#endif #endif
} }
@ -262,6 +361,11 @@ void FloatVectorOperations::negate (float* dest, const float* src, int num) noex
void JUCE_CALLTYPE FloatVectorOperations::convertFixedToFloat (float* dest, const int* src, float multiplier, int num) noexcept void JUCE_CALLTYPE FloatVectorOperations::convertFixedToFloat (float* dest, const int* src, float multiplier, int num) noexcept
{ {
#if JUCE_USE_ARM_NEON
JUCE_PERFORM_NEON_OP_SRC_DEST (dest[i] = src[i] * multiplier,
vmulq_n_f32 (vcvtq_f32_s32 (vld1q_s32 (src)), multiplier),
JUCE_LOAD_NONE)
#else
#if JUCE_USE_SSE_INTRINSICS #if JUCE_USE_SSE_INTRINSICS
const __m128 mult = _mm_load1_ps (&multiplier); const __m128 mult = _mm_load1_ps (&multiplier);
#endif #endif
@ -269,6 +373,7 @@ void JUCE_CALLTYPE FloatVectorOperations::convertFixedToFloat (float* dest, cons
JUCE_PERFORM_SSE_OP_SRC_DEST (dest[i] = src[i] * multiplier, JUCE_PERFORM_SSE_OP_SRC_DEST (dest[i] = src[i] * multiplier,
_mm_mul_ps (mult, _mm_cvtepi32_ps (_mm_loadu_si128 ((const __m128i*) src))), _mm_mul_ps (mult, _mm_cvtepi32_ps (_mm_loadu_si128 ((const __m128i*) src))),
JUCE_LOAD_NONE, JUCE_INCREMENT_SRC_DEST) JUCE_LOAD_NONE, JUCE_INCREMENT_SRC_DEST)
#endif
} }
void JUCE_CALLTYPE FloatVectorOperations::findMinAndMax (const float* src, int num, float& minResult, float& maxResult) noexcept void JUCE_CALLTYPE FloatVectorOperations::findMinAndMax (const float* src, int num, float& minResult, float& maxResult) noexcept
@ -315,6 +420,51 @@ void JUCE_CALLTYPE FloatVectorOperations::findMinAndMax (const float* src, int n
localMax = jmax (localMax, s); localMax = jmax (localMax, s);
} }
minResult = localMin;
maxResult = localMax;
return;
}
#elif JUCE_USE_ARM_NEON
const int numLongOps = num / 4;
if (numLongOps > 1)
{
float32x4_t mn, mx;
#define JUCE_MINMAX_NEON_LOOP(loadOp) \
mn = loadOp (src); \
mx = mn; \
src += 4; \
for (int i = 1; i < numLongOps; ++i) \
{ \
const float32x4_t s = loadOp (src); \
mn = vminq_f32 (mn, s); \
mx = vmaxq_f32 (mx, s); \
src += 4; \
}
JUCE_MINMAX_NEON_LOOP (vld1q_f32);
float localMin, localMax;
{
float mns[4], mxs[4];
vst1q_f32 (mns, mn);
vst1q_f32 (mxs, mx);
localMin = jmin (mns[0], mns[1], mns[2], mns[3]);
localMax = jmax (mxs[0], mxs[1], mxs[2], mxs[3]);
}
num &= 3;
for (int i = 0; i < num; ++i)
{
const float s = src[i];
localMin = jmin (localMin, s);
localMax = jmax (localMax, s);
}
minResult = localMin; minResult = localMin;
maxResult = localMax; maxResult = localMax;
return; return;
@ -326,7 +476,7 @@ void JUCE_CALLTYPE FloatVectorOperations::findMinAndMax (const float* src, int n
float JUCE_CALLTYPE FloatVectorOperations::findMinimum (const float* src, int num) noexcept float JUCE_CALLTYPE FloatVectorOperations::findMinimum (const float* src, int num) noexcept
{ {
#if JUCE_USE_SSE_INTRINSICS #if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
return FloatVectorHelpers::findMinimumOrMaximum (src, num, true); return FloatVectorHelpers::findMinimumOrMaximum (src, num, true);
#else #else
return juce::findMinimum (src, num); return juce::findMinimum (src, num);
@ -335,7 +485,7 @@ float JUCE_CALLTYPE FloatVectorOperations::findMinimum (const float* src, int nu
float JUCE_CALLTYPE FloatVectorOperations::findMaximum (const float* src, int num) noexcept float JUCE_CALLTYPE FloatVectorOperations::findMaximum (const float* src, int num) noexcept
{ {
#if JUCE_USE_SSE_INTRINSICS #if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
return FloatVectorHelpers::findMinimumOrMaximum (src, num, false); return FloatVectorHelpers::findMinimumOrMaximum (src, num, false);
#else #else
return juce::findMaximum (src, num); return juce::findMaximum (src, num);
@ -350,3 +500,129 @@ void JUCE_CALLTYPE FloatVectorOperations::enableFlushToZeroMode (bool shouldEnab
#endif #endif
(void) shouldEnable; (void) shouldEnable;
} }
//==============================================================================
//==============================================================================
#if JUCE_UNIT_TESTS
class FloatVectorOperationsTests : public UnitTest
{
public:
FloatVectorOperationsTests() : UnitTest ("FloatVectorOperations") {}
void runTest()
{
beginTest ("FloatVectorOperations");
for (int i = 100; --i >= 0;)
{
const int num = getRandom().nextInt (500) + 1;
HeapBlock<float> buffer1 (num + 16), buffer2 (num + 16);
HeapBlock<int> buffer3 (num + 16);
#if JUCE_ARM
float* const data1 = buffer1;
float* const data2 = buffer2;
int* const int1 = buffer3;
#else
float* const data1 = addBytesToPointer (buffer1.getData(), getRandom().nextInt (16));
float* const data2 = addBytesToPointer (buffer2.getData(), getRandom().nextInt (16));
int* const int1 = addBytesToPointer (buffer3.getData(), getRandom().nextInt (16));
#endif
fillRandomly (data1, num);
fillRandomly (data2, num);
float mn1, mx1, mn2, mx2;
FloatVectorOperations::findMinAndMax (data1, num, mn1, mx1);
juce::findMinAndMax (data1, num, mn2, mx2);
expect (mn1 == mn2);
expect (mx1 == mx2);
expect (FloatVectorOperations::findMinimum (data1, num) == juce::findMinimum (data1, num));
expect (FloatVectorOperations::findMaximum (data1, num) == juce::findMaximum (data1, num));
expect (FloatVectorOperations::findMinimum (data2, num) == juce::findMinimum (data2, num));
expect (FloatVectorOperations::findMaximum (data2, num) == juce::findMaximum (data2, num));
FloatVectorOperations::clear (data1, num);
expect (areAllValuesEqual (data1, num, 0));
FloatVectorOperations::fill (data1, 2.0f, num);
expect (areAllValuesEqual (data1, num, 2.0f));
FloatVectorOperations::add (data1, 2.0f, num);
expect (areAllValuesEqual (data1, num, 4.0f));
FloatVectorOperations::copy (data2, data1, num);
expect (areAllValuesEqual (data2, num, 4.0f));
FloatVectorOperations::add (data2, data1, num);
expect (areAllValuesEqual (data2, num, 8.0f));
FloatVectorOperations::copyWithMultiply (data2, data1, 4.0f, num);
expect (areAllValuesEqual (data2, num, 16.0f));
FloatVectorOperations::addWithMultiply (data2, data1, 4.0f, num);
expect (areAllValuesEqual (data2, num, 32.0f));
FloatVectorOperations::multiply (data1, 2.0f, num);
expect (areAllValuesEqual (data1, num, 8.0f));
FloatVectorOperations::multiply (data1, data2, num);
expect (areAllValuesEqual (data1, num, 256.0f));
FloatVectorOperations::negate (data2, data1, num);
expect (areAllValuesEqual (data2, num, -256.0f));
FloatVectorOperations::subtract (data1, data2, num);
expect (areAllValuesEqual (data1, num, 512.0f));
fillRandomly (int1, num);
FloatVectorOperations::convertFixedToFloat (data1, int1, 2.0f, num);
convertFixed (data2, int1, 2.0f, num);
expect (buffersMatch (data1, data2, num));
}
}
void fillRandomly (float* d, int num)
{
while (--num >= 0)
*d++ = getRandom().nextFloat() * 1000.0f;
}
void fillRandomly (int* d, int num)
{
while (--num >= 0)
*d++ = getRandom().nextInt();
}
static void convertFixed (float* d, const int* s, float multiplier, int num)
{
while (--num >= 0)
*d++ = *s++ * multiplier;
}
static bool areAllValuesEqual (const float* d, int num, float target)
{
while (--num >= 0)
if (*d++ != target)
return false;
return true;
}
static bool buffersMatch (const float* d1, const float* d2, int num)
{
while (--num >= 0)
if (std::abs (*d1++ - *d2++) > std::numeric_limits<float>::epsilon())
return false;
return true;
}
};
static FloatVectorOperationsTests vectorOpTests;
#endif

@ -47,11 +47,14 @@ public:
/** Copies a vector of floats, multiplying each value by a given multiplier */ /** Copies a vector of floats, multiplying each value by a given multiplier */
static void JUCE_CALLTYPE copyWithMultiply (float* dest, const float* src, float multiplier, int numValues) noexcept; static void JUCE_CALLTYPE copyWithMultiply (float* dest, const float* src, float multiplier, int numValues) noexcept;
/** Adds a fixed value to the destination values. */
static void JUCE_CALLTYPE add (float* dest, float amount, int numValues) noexcept;
/** Adds the source values to the destination values. */ /** Adds the source values to the destination values. */
static void JUCE_CALLTYPE add (float* dest, const float* src, int numValues) noexcept; static void JUCE_CALLTYPE add (float* dest, const float* src, int numValues) noexcept;
/** Adds a fixed value to the destination values. */ /** Subtracts the source values from the destination values. */
static void JUCE_CALLTYPE add (float* dest, float amount, int numValues) noexcept; static void JUCE_CALLTYPE subtract (float* dest, const float* src, int numValues) noexcept;
/** Multiplies each source value by the given multiplier, then adds it to the destination value. */ /** Multiplies each source value by the given multiplier, then adds it to the destination value. */
static void JUCE_CALLTYPE addWithMultiply (float* dest, const float* src, float multiplier, int numValues) noexcept; static void JUCE_CALLTYPE addWithMultiply (float* dest, const float* src, float multiplier, int numValues) noexcept;

@ -58,6 +58,11 @@
#undef JUCE_USE_VDSP_FRAMEWORK #undef JUCE_USE_VDSP_FRAMEWORK
#endif #endif
#if __ARM_NEON__ && ! (JUCE_USE_VDSP_FRAMEWORK || defined (JUCE_USE_ARM_NEON))
#define JUCE_USE_ARM_NEON 1
#include <arm_neon.h>
#endif
namespace juce namespace juce
{ {

@ -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.0", "version": "3.0.1",
"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",

@ -945,29 +945,38 @@ const char* MidiMessage::getGMInstrumentName (const int n)
{ {
static const char* names[] = static const char* names[] =
{ {
"Acoustic Grand Piano", "Bright Acoustic Piano", "Electric Grand Piano", "Honky-tonk Piano", NEEDS_TRANS("Acoustic Grand Piano"), NEEDS_TRANS("Bright Acoustic Piano"), NEEDS_TRANS("Electric Grand Piano"), NEEDS_TRANS("Honky-tonk Piano"),
"Electric Piano 1", "Electric Piano 2", "Harpsichord", "Clavinet", "Celesta", "Glockenspiel", NEEDS_TRANS("Electric Piano 1"), NEEDS_TRANS("Electric Piano 2"), NEEDS_TRANS("Harpsichord"), NEEDS_TRANS("Clavinet"),
"Music Box", "Vibraphone", "Marimba", "Xylophone", "Tubular Bells", "Dulcimer", "Drawbar Organ", NEEDS_TRANS("Celesta"), NEEDS_TRANS("Glockenspiel"), NEEDS_TRANS("Music Box"), NEEDS_TRANS("Vibraphone"),
"Percussive Organ", "Rock Organ", "Church Organ", "Reed Organ", "Accordion", "Harmonica", NEEDS_TRANS("Marimba"), NEEDS_TRANS("Xylophone"), NEEDS_TRANS("Tubular Bells"), NEEDS_TRANS("Dulcimer"),
"Tango Accordion", "Acoustic Guitar (nylon)", "Acoustic Guitar (steel)", "Electric Guitar (jazz)", NEEDS_TRANS("Drawbar Organ"), NEEDS_TRANS("Percussive Organ"), NEEDS_TRANS("Rock Organ"), NEEDS_TRANS("Church Organ"),
"Electric Guitar (clean)", "Electric Guitar (mute)", "Overdriven Guitar", "Distortion Guitar", NEEDS_TRANS("Reed Organ"), NEEDS_TRANS("Accordion"), NEEDS_TRANS("Harmonica"), NEEDS_TRANS("Tango Accordion"),
"Guitar Harmonics", "Acoustic Bass", "Electric Bass (finger)", "Electric Bass (pick)", NEEDS_TRANS("Acoustic Guitar (nylon)"), NEEDS_TRANS("Acoustic Guitar (steel)"), NEEDS_TRANS("Electric Guitar (jazz)"), NEEDS_TRANS("Electric Guitar (clean)"),
"Fretless Bass", "Slap Bass 1", "Slap Bass 2", "Synth Bass 1", "Synth Bass 2", "Violin", NEEDS_TRANS("Electric Guitar (mute)"), NEEDS_TRANS("Overdriven Guitar"), NEEDS_TRANS("Distortion Guitar"), NEEDS_TRANS("Guitar Harmonics"),
"Viola", "Cello", "Contrabass", "Tremolo Strings", "Pizzicato Strings", "Orchestral Harp", NEEDS_TRANS("Acoustic Bass"), NEEDS_TRANS("Electric Bass (finger)"), NEEDS_TRANS("Electric Bass (pick)"), NEEDS_TRANS("Fretless Bass"),
"Timpani", "String Ensemble 1", "String Ensemble 2", "SynthStrings 1", "SynthStrings 2", NEEDS_TRANS("Slap Bass 1"), NEEDS_TRANS("Slap Bass 2"), NEEDS_TRANS("Synth Bass 1"), NEEDS_TRANS("Synth Bass 2"),
"Choir Aahs", "Voice Oohs", "Synth Voice", "Orchestra Hit", "Trumpet", "Trombone", "Tuba", NEEDS_TRANS("Violin"), NEEDS_TRANS("Viola"), NEEDS_TRANS("Cello"), NEEDS_TRANS("Contrabass"),
"Muted Trumpet", "French Horn", "Brass Section", "SynthBrass 1", "SynthBrass 2", "Soprano Sax", NEEDS_TRANS("Tremolo Strings"), NEEDS_TRANS("Pizzicato Strings"), NEEDS_TRANS("Orchestral Harp"), NEEDS_TRANS("Timpani"),
"Alto Sax", "Tenor Sax", "Baritone Sax", "Oboe", "English Horn", "Bassoon", "Clarinet", NEEDS_TRANS("String Ensemble 1"), NEEDS_TRANS("String Ensemble 2"), NEEDS_TRANS("SynthStrings 1"), NEEDS_TRANS("SynthStrings 2"),
"Piccolo", "Flute", "Recorder", "Pan Flute", "Blown Bottle", "Shakuhachi", "Whistle", NEEDS_TRANS("Choir Aahs"), NEEDS_TRANS("Voice Oohs"), NEEDS_TRANS("Synth Voice"), NEEDS_TRANS("Orchestra Hit"),
"Ocarina", "Lead 1 (square)", "Lead 2 (sawtooth)", "Lead 3 (calliope)", "Lead 4 (chiff)", NEEDS_TRANS("Trumpet"), NEEDS_TRANS("Trombone"), NEEDS_TRANS("Tuba"), NEEDS_TRANS("Muted Trumpet"),
"Lead 5 (charang)", "Lead 6 (voice)", "Lead 7 (fifths)", "Lead 8 (bass+lead)", "Pad 1 (new age)", NEEDS_TRANS("French Horn"), NEEDS_TRANS("Brass Section"), NEEDS_TRANS("SynthBrass 1"), NEEDS_TRANS("SynthBrass 2"),
"Pad 2 (warm)", "Pad 3 (polysynth)", "Pad 4 (choir)", "Pad 5 (bowed)", "Pad 6 (metallic)", NEEDS_TRANS("Soprano Sax"), NEEDS_TRANS("Alto Sax"), NEEDS_TRANS("Tenor Sax"), NEEDS_TRANS("Baritone Sax"),
"Pad 7 (halo)", "Pad 8 (sweep)", "FX 1 (rain)", "FX 2 (soundtrack)", "FX 3 (crystal)", NEEDS_TRANS("Oboe"), NEEDS_TRANS("English Horn"), NEEDS_TRANS("Bassoon"), NEEDS_TRANS("Clarinet"),
"FX 4 (atmosphere)", "FX 5 (brightness)", "FX 6 (goblins)", "FX 7 (echoes)", "FX 8 (sci-fi)", NEEDS_TRANS("Piccolo"), NEEDS_TRANS("Flute"), NEEDS_TRANS("Recorder"), NEEDS_TRANS("Pan Flute"),
"Sitar", "Banjo", "Shamisen", "Koto", "Kalimba", "Bag pipe", "Fiddle", "Shanai", "Tinkle Bell", NEEDS_TRANS("Blown Bottle"), NEEDS_TRANS("Shakuhachi"), NEEDS_TRANS("Whistle"), NEEDS_TRANS("Ocarina"),
"Agogo", "Steel Drums", "Woodblock", "Taiko Drum", "Melodic Tom", "Synth Drum", "Reverse Cymbal", NEEDS_TRANS("Lead 1 (square)"), NEEDS_TRANS("Lead 2 (sawtooth)"), NEEDS_TRANS("Lead 3 (calliope)"), NEEDS_TRANS("Lead 4 (chiff)"),
"Guitar Fret Noise", "Breath Noise", "Seashore", "Bird Tweet", "Telephone Ring", "Helicopter", NEEDS_TRANS("Lead 5 (charang)"), NEEDS_TRANS("Lead 6 (voice)"), NEEDS_TRANS("Lead 7 (fifths)"), NEEDS_TRANS("Lead 8 (bass+lead)"),
"Applause", "Gunshot" NEEDS_TRANS("Pad 1 (new age)"), NEEDS_TRANS("Pad 2 (warm)"), NEEDS_TRANS("Pad 3 (polysynth)"), NEEDS_TRANS("Pad 4 (choir)"),
NEEDS_TRANS("Pad 5 (bowed)"), NEEDS_TRANS("Pad 6 (metallic)"), NEEDS_TRANS("Pad 7 (halo)"), NEEDS_TRANS("Pad 8 (sweep)"),
NEEDS_TRANS("FX 1 (rain)"), NEEDS_TRANS("FX 2 (soundtrack)"), NEEDS_TRANS("FX 3 (crystal)"), NEEDS_TRANS("FX 4 (atmosphere)"),
NEEDS_TRANS("FX 5 (brightness)"), NEEDS_TRANS("FX 6 (goblins)"), NEEDS_TRANS("FX 7 (echoes)"), NEEDS_TRANS("FX 8 (sci-fi)"),
NEEDS_TRANS("Sitar"), NEEDS_TRANS("Banjo"), NEEDS_TRANS("Shamisen"), NEEDS_TRANS("Koto"),
NEEDS_TRANS("Kalimba"), NEEDS_TRANS("Bag pipe"), NEEDS_TRANS("Fiddle"), NEEDS_TRANS("Shanai"),
NEEDS_TRANS("Tinkle Bell"), NEEDS_TRANS("Agogo"), NEEDS_TRANS("Steel Drums"), NEEDS_TRANS("Woodblock"),
NEEDS_TRANS("Taiko Drum"), NEEDS_TRANS("Melodic Tom"), NEEDS_TRANS("Synth Drum"), NEEDS_TRANS("Reverse Cymbal"),
NEEDS_TRANS("Guitar Fret Noise"), NEEDS_TRANS("Breath Noise"), NEEDS_TRANS("Seashore"), NEEDS_TRANS("Bird Tweet"),
NEEDS_TRANS("Telephone Ring"), NEEDS_TRANS("Helicopter"), NEEDS_TRANS("Applause"), NEEDS_TRANS("Gunshot")
}; };
return isPositiveAndBelow (n, numElementsInArray (names)) ? names[n] : nullptr; return isPositiveAndBelow (n, numElementsInArray (names)) ? names[n] : nullptr;
@ -977,10 +986,10 @@ const char* MidiMessage::getGMInstrumentBankName (const int n)
{ {
static const char* names[] = static const char* names[] =
{ {
"Piano", "Chromatic Percussion", "Organ", "Guitar", NEEDS_TRANS("Piano"), NEEDS_TRANS("Chromatic Percussion"), NEEDS_TRANS("Organ"), NEEDS_TRANS("Guitar"),
"Bass", "Strings", "Ensemble", "Brass", NEEDS_TRANS("Bass"), NEEDS_TRANS("Strings"), NEEDS_TRANS("Ensemble"), NEEDS_TRANS("Brass"),
"Reed", "Pipe", "Synth Lead", "Synth Pad", NEEDS_TRANS("Reed"), NEEDS_TRANS("Pipe"), NEEDS_TRANS("Synth Lead"), NEEDS_TRANS("Synth Pad"),
"Synth Effects", "Ethnic", "Percussive", "Sound Effects" NEEDS_TRANS("Synth Effects"), NEEDS_TRANS("Ethnic"), NEEDS_TRANS("Percussive"), NEEDS_TRANS("Sound Effects")
}; };
return isPositiveAndBelow (n, numElementsInArray (names)) ? names[n] : nullptr; return isPositiveAndBelow (n, numElementsInArray (names)) ? names[n] : nullptr;
@ -990,15 +999,18 @@ const char* MidiMessage::getRhythmInstrumentName (const int n)
{ {
static const char* names[] = static const char* names[] =
{ {
"Acoustic Bass Drum", "Bass Drum 1", "Side Stick", "Acoustic Snare", NEEDS_TRANS("Acoustic Bass Drum"), NEEDS_TRANS("Bass Drum 1"), NEEDS_TRANS("Side Stick"), NEEDS_TRANS("Acoustic Snare"),
"Hand Clap", "Electric Snare", "Low Floor Tom", "Closed Hi-Hat", "High Floor Tom", NEEDS_TRANS("Hand Clap"), NEEDS_TRANS("Electric Snare"), NEEDS_TRANS("Low Floor Tom"), NEEDS_TRANS("Closed Hi-Hat"),
"Pedal Hi-Hat", "Low Tom", "Open Hi-Hat", "Low-Mid Tom", "Hi-Mid Tom", "Crash Cymbal 1", NEEDS_TRANS("High Floor Tom"), NEEDS_TRANS("Pedal Hi-Hat"), NEEDS_TRANS("Low Tom"), NEEDS_TRANS("Open Hi-Hat"),
"High Tom", "Ride Cymbal 1", "Chinese Cymbal", "Ride Bell", "Tambourine", "Splash Cymbal", NEEDS_TRANS("Low-Mid Tom"), NEEDS_TRANS("Hi-Mid Tom"), NEEDS_TRANS("Crash Cymbal 1"), NEEDS_TRANS("High Tom"),
"Cowbell", "Crash Cymbal 2", "Vibraslap", "Ride Cymbal 2", "Hi Bongo", "Low Bongo", NEEDS_TRANS("Ride Cymbal 1"), NEEDS_TRANS("Chinese Cymbal"), NEEDS_TRANS("Ride Bell"), NEEDS_TRANS("Tambourine"),
"Mute Hi Conga", "Open Hi Conga", "Low Conga", "High Timbale", "Low Timbale", "High Agogo", NEEDS_TRANS("Splash Cymbal"), NEEDS_TRANS("Cowbell"), NEEDS_TRANS("Crash Cymbal 2"), NEEDS_TRANS("Vibraslap"),
"Low Agogo", "Cabasa", "Maracas", "Short Whistle", "Long Whistle", "Short Guiro", NEEDS_TRANS("Ride Cymbal 2"), NEEDS_TRANS("Hi Bongo"), NEEDS_TRANS("Low Bongo"), NEEDS_TRANS("Mute Hi Conga"),
"Long Guiro", "Claves", "Hi Wood Block", "Low Wood Block", "Mute Cuica", "Open Cuica", NEEDS_TRANS("Open Hi Conga"), NEEDS_TRANS("Low Conga"), NEEDS_TRANS("High Timbale"), NEEDS_TRANS("Low Timbale"),
"Mute Triangle", "Open Triangle" NEEDS_TRANS("High Agogo"), NEEDS_TRANS("Low Agogo"), NEEDS_TRANS("Cabasa"), NEEDS_TRANS("Maracas"),
NEEDS_TRANS("Short Whistle"), NEEDS_TRANS("Long Whistle"), NEEDS_TRANS("Short Guiro"), NEEDS_TRANS("Long Guiro"),
NEEDS_TRANS("Claves"), NEEDS_TRANS("Hi Wood Block"), NEEDS_TRANS("Low Wood Block"), NEEDS_TRANS("Mute Cuica"),
NEEDS_TRANS("Open Cuica"), NEEDS_TRANS("Mute Triangle"), NEEDS_TRANS("Open Triangle")
}; };
return (n >= 35 && n <= 81) ? names [n - 35] : nullptr; return (n >= 35 && n <= 81) ? names [n - 35] : nullptr;
@ -1008,28 +1020,38 @@ const char* MidiMessage::getControllerName (const int n)
{ {
static const char* names[] = static const char* names[] =
{ {
"Bank Select", "Modulation Wheel (coarse)", "Breath controller (coarse)", NEEDS_TRANS("Bank Select"), NEEDS_TRANS("Modulation Wheel (coarse)"), NEEDS_TRANS("Breath controller (coarse)"),
0, "Foot Pedal (coarse)", "Portamento Time (coarse)", nullptr,
"Data Entry (coarse)", "Volume (coarse)", "Balance (coarse)", NEEDS_TRANS("Foot Pedal (coarse)"), NEEDS_TRANS("Portamento Time (coarse)"), NEEDS_TRANS("Data Entry (coarse)"),
0, "Pan position (coarse)", "Expression (coarse)", "Effect Control 1 (coarse)", NEEDS_TRANS("Volume (coarse)"), NEEDS_TRANS("Balance (coarse)"),
"Effect Control 2 (coarse)", 0, 0, "General Purpose Slider 1", "General Purpose Slider 2", nullptr,
"General Purpose Slider 3", "General Purpose Slider 4", 0, 0, 0, 0, 0, 0, 0, 0, NEEDS_TRANS("Pan position (coarse)"), NEEDS_TRANS("Expression (coarse)"), NEEDS_TRANS("Effect Control 1 (coarse)"),
0, 0, 0, 0, "Bank Select (fine)", "Modulation Wheel (fine)", "Breath controller (fine)", NEEDS_TRANS("Effect Control 2 (coarse)"),
0, "Foot Pedal (fine)", "Portamento Time (fine)", "Data Entry (fine)", "Volume (fine)", nullptr, nullptr,
"Balance (fine)", 0, "Pan position (fine)", "Expression (fine)", "Effect Control 1 (fine)", NEEDS_TRANS("General Purpose Slider 1"), NEEDS_TRANS("General Purpose Slider 2"),
"Effect Control 2 (fine)", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NEEDS_TRANS("General Purpose Slider 3"), NEEDS_TRANS("General Purpose Slider 4"),
"Hold Pedal (on/off)", "Portamento (on/off)", "Sustenuto Pedal (on/off)", "Soft Pedal (on/off)", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
"Legato Pedal (on/off)", "Hold 2 Pedal (on/off)", "Sound Variation", "Sound Timbre", NEEDS_TRANS("Bank Select (fine)"), NEEDS_TRANS("Modulation Wheel (fine)"), NEEDS_TRANS("Breath controller (fine)"),
"Sound Release Time", "Sound Attack Time", "Sound Brightness", "Sound Control 6", nullptr,
"Sound Control 7", "Sound Control 8", "Sound Control 9", "Sound Control 10", NEEDS_TRANS("Foot Pedal (fine)"), NEEDS_TRANS("Portamento Time (fine)"), NEEDS_TRANS("Data Entry (fine)"), NEEDS_TRANS("Volume (fine)"),
"General Purpose Button 1 (on/off)", "General Purpose Button 2 (on/off)", NEEDS_TRANS("Balance (fine)"), nullptr, NEEDS_TRANS("Pan position (fine)"), NEEDS_TRANS("Expression (fine)"),
"General Purpose Button 3 (on/off)", "General Purpose Button 4 (on/off)", NEEDS_TRANS("Effect Control 1 (fine)"), NEEDS_TRANS("Effect Control 2 (fine)"),
0, 0, 0, 0, 0, 0, 0, "Reverb Level", "Tremolo Level", "Chorus Level", "Celeste Level", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
"Phaser Level", "Data Button increment", "Data Button decrement", "Non-registered Parameter (fine)", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
"Non-registered Parameter (coarse)", "Registered Parameter (fine)", "Registered Parameter (coarse)", NEEDS_TRANS("Hold Pedal (on/off)"), NEEDS_TRANS("Portamento (on/off)"), NEEDS_TRANS("Sustenuto Pedal (on/off)"), NEEDS_TRANS("Soft Pedal (on/off)"),
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "All Sound Off", "All Controllers Off", NEEDS_TRANS("Legato Pedal (on/off)"), NEEDS_TRANS("Hold 2 Pedal (on/off)"), NEEDS_TRANS("Sound Variation"), NEEDS_TRANS("Sound Timbre"),
"Local Keyboard (on/off)", "All Notes Off", "Omni Mode Off", "Omni Mode On", "Mono Operation", NEEDS_TRANS("Sound Release Time"), NEEDS_TRANS("Sound Attack Time"), NEEDS_TRANS("Sound Brightness"), NEEDS_TRANS("Sound Control 6"),
"Poly Operation" NEEDS_TRANS("Sound Control 7"), NEEDS_TRANS("Sound Control 8"), NEEDS_TRANS("Sound Control 9"), NEEDS_TRANS("Sound Control 10"),
NEEDS_TRANS("General Purpose Button 1 (on/off)"), NEEDS_TRANS("General Purpose Button 2 (on/off)"),
NEEDS_TRANS("General Purpose Button 3 (on/off)"), NEEDS_TRANS("General Purpose Button 4 (on/off)"),
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
NEEDS_TRANS("Reverb Level"), NEEDS_TRANS("Tremolo Level"), NEEDS_TRANS("Chorus Level"), NEEDS_TRANS("Celeste Level"),
NEEDS_TRANS("Phaser Level"), NEEDS_TRANS("Data Button increment"), NEEDS_TRANS("Data Button decrement"), NEEDS_TRANS("Non-registered Parameter (fine)"),
NEEDS_TRANS("Non-registered Parameter (coarse)"), NEEDS_TRANS("Registered Parameter (fine)"), NEEDS_TRANS("Registered Parameter (coarse)"),
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
NEEDS_TRANS("All Sound Off"), NEEDS_TRANS("All Controllers Off"), NEEDS_TRANS("Local Keyboard (on/off)"), NEEDS_TRANS("All Notes Off"),
NEEDS_TRANS("Omni Mode Off"), NEEDS_TRANS("Omni Mode On"), NEEDS_TRANS("Mono Operation"), NEEDS_TRANS("Poly Operation")
}; };
return isPositiveAndBelow (n, numElementsInArray (names)) ? names[n] : nullptr; return isPositiveAndBelow (n, numElementsInArray (names)) ? names[n] : nullptr;

@ -56,6 +56,8 @@ void SynthesiserVoice::clearCurrentNote()
currentlyPlayingSound = nullptr; currentlyPlayingSound = nullptr;
} }
void SynthesiserVoice::aftertouchChanged (int) {}
//============================================================================== //==============================================================================
Synthesiser::Synthesiser() Synthesiser::Synthesiser()
: sampleRate (0), : sampleRate (0),
@ -191,6 +193,10 @@ void Synthesiser::handleMidiEvent (const MidiMessage& m)
handlePitchWheel (channel, wheelPos); handlePitchWheel (channel, wheelPos);
} }
else if (m.isAftertouch())
{
handleAftertouch (m.getChannel(), m.getNoteNumber(), m.getAfterTouchValue());
}
else if (m.isController()) else if (m.isController())
{ {
handleController (m.getChannel(), m.getControllerNumber(), m.getControllerValue()); handleController (m.getChannel(), m.getControllerNumber(), m.getControllerValue());
@ -338,6 +344,20 @@ void Synthesiser::handleController (const int midiChannel,
} }
} }
void Synthesiser::handleAftertouch (int midiChannel, int midiNoteNumber, int aftertouchValue)
{
const ScopedLock sl (lock);
for (int i = voices.size(); --i >= 0;)
{
SynthesiserVoice* const voice = voices.getUnchecked (i);
if (voice->getCurrentlyPlayingNote() == midiNoteNumber
&& (midiChannel <= 0 || voice->isPlayingChannel (midiChannel)))
voice->aftertouchChanged (aftertouchValue);
}
}
void Synthesiser::handleSustainPedal (int midiChannel, bool isDown) void Synthesiser::handleSustainPedal (int midiChannel, bool isDown)
{ {
jassert (midiChannel > 0 && midiChannel <= 16); jassert (midiChannel > 0 && midiChannel <= 16);

@ -116,7 +116,6 @@ public:
virtual bool canPlaySound (SynthesiserSound*) = 0; virtual bool canPlaySound (SynthesiserSound*) = 0;
/** Called to start a new note. /** Called to start a new note.
This will be called during the rendering callback, so must be fast and thread-safe. This will be called during the rendering callback, so must be fast and thread-safe.
*/ */
virtual void startNote (int midiNoteNumber, virtual void startNote (int midiNoteNumber,
@ -142,12 +141,17 @@ public:
/** Called to let the voice know that the pitch wheel has been moved. /** Called to let the voice know that the pitch wheel has been moved.
This will be called during the rendering callback, so must be fast and thread-safe. This will be called during the rendering callback, so must be fast and thread-safe.
*/ */
virtual void pitchWheelMoved (int newValue) = 0; virtual void pitchWheelMoved (int newPitchWheelValue) = 0;
/** Called to let the voice know that a midi controller has been moved. /** Called to let the voice know that a midi controller has been moved.
This will be called during the rendering callback, so must be fast and thread-safe. This will be called during the rendering callback, so must be fast and thread-safe.
*/ */
virtual void controllerMoved (int controllerNumber, int newValue) = 0; virtual void controllerMoved (int controllerNumber, int newControllerValue) = 0;
/** Called to let the voice know that the aftertouch has changed.
This will be called during the rendering callback, so must be fast and thread-safe.
*/
virtual void aftertouchChanged (int newAftertouchValue);
//============================================================================== //==============================================================================
/** Renders the next block of data for this voice. /** Renders the next block of data for this voice.
@ -186,6 +190,14 @@ public:
*/ */
void setCurrentPlaybackSampleRate (double newRate); void setCurrentPlaybackSampleRate (double newRate);
/** Returns true if the key that triggered this voice is still held down.
Note that the voice may still be playing after the key was released (e.g because the
sostenuto pedal is down).
*/
bool isKeyDown() const noexcept { return keyIsDown; }
/** Returns true if the sostenuto pedal is currently active for this voice. */
bool isSostenutoPedalDown() const noexcept { return sostenutoPedalDown; }
protected: protected:
//============================================================================== //==============================================================================
@ -218,8 +230,7 @@ private:
int currentlyPlayingNote; int currentlyPlayingNote;
uint32 noteOnTime; uint32 noteOnTime;
SynthesiserSound::Ptr currentlyPlayingSound; SynthesiserSound::Ptr currentlyPlayingSound;
bool keyIsDown; // the voice may still be playing when the key is not down (i.e. sustain pedal) bool keyIsDown, sostenutoPedalDown;
bool sostenutoPedalDown;
JUCE_LEAK_DETECTOR (SynthesiserVoice) JUCE_LEAK_DETECTOR (SynthesiserVoice)
}; };
@ -400,6 +411,21 @@ public:
int controllerNumber, int controllerNumber,
int controllerValue); int controllerValue);
/** Sends an aftertouch message.
This will send an aftertouch message to any voices that are playing sounds on
the given midi channel and note number.
This method will be called automatically according to the midi data passed into
renderNextBlock(), but may be called explicitly too.
@param midiChannel the midi channel, from 1 to 16 inclusive
@param midiNoteNumber the midi note number, 0 to 127
@param aftertouchValue the aftertouch value, between 0 and 127,
as returned by MidiMessage::getAftertouchValue()
*/
virtual void handleAftertouch (int midiChannel, int midiNoteNumber, int aftertouchValue);
/** Handles a sustain pedal event. */ /** Handles a sustain pedal event. */
virtual void handleSustainPedal (int midiChannel, bool isDown); virtual void handleSustainPedal (int midiChannel, bool isDown);

@ -361,8 +361,8 @@ void AudioDeviceManager::getAudioDeviceSetup (AudioDeviceSetup& setup)
void AudioDeviceManager::deleteCurrentDevice() void AudioDeviceManager::deleteCurrentDevice()
{ {
currentAudioDevice = nullptr; currentAudioDevice = nullptr;
currentSetup.inputDeviceName = String::empty; currentSetup.inputDeviceName.clear();
currentSetup.outputDeviceName = String::empty; currentSetup.outputDeviceName.clear();
} }
void AudioDeviceManager::setCurrentAudioDeviceType (const String& type, void AudioDeviceManager::setCurrentAudioDeviceType (const String& type,
@ -408,15 +408,15 @@ String AudioDeviceManager::setAudioDeviceSetup (const AudioDeviceSetup& newSetup
jassert (&newSetup != &currentSetup); // this will have no effect jassert (&newSetup != &currentSetup); // this will have no effect
if (newSetup == currentSetup && currentAudioDevice != nullptr) if (newSetup == currentSetup && currentAudioDevice != nullptr)
return String::empty; return String();
if (! (newSetup == currentSetup)) if (! (newSetup == currentSetup))
sendChangeMessage(); sendChangeMessage();
stopDevice(); stopDevice();
const String newInputDeviceName (numInputChansNeeded == 0 ? String::empty : newSetup.inputDeviceName); const String newInputDeviceName (numInputChansNeeded == 0 ? String() : newSetup.inputDeviceName);
const String newOutputDeviceName (numOutputChansNeeded == 0 ? String::empty : newSetup.outputDeviceName); const String newOutputDeviceName (numOutputChansNeeded == 0 ? String() : newSetup.outputDeviceName);
String error; String error;
AudioIODeviceType* type = getCurrentDeviceTypeObject(); AudioIODeviceType* type = getCurrentDeviceTypeObject();
@ -428,7 +428,7 @@ String AudioDeviceManager::setAudioDeviceSetup (const AudioDeviceSetup& newSetup
if (treatAsChosenDevice) if (treatAsChosenDevice)
updateXml(); updateXml();
return String::empty; return String();
} }
if (currentSetup.inputDeviceName != newInputDeviceName if (currentSetup.inputDeviceName != newInputDeviceName
@ -524,16 +524,16 @@ double AudioDeviceManager::chooseBestSampleRate (double rate) const
{ {
jassert (currentAudioDevice != nullptr); jassert (currentAudioDevice != nullptr);
if (rate > 0) const Array<double> rates (currentAudioDevice->getAvailableSampleRates());
for (int i = currentAudioDevice->getNumSampleRates(); --i >= 0;)
if (currentAudioDevice->getSampleRate (i) == rate) if (rate > 0 && rates.contains (rate))
return rate; return rate;
double lowestAbove44 = 0.0; double lowestAbove44 = 0.0;
for (int i = currentAudioDevice->getNumSampleRates(); --i >= 0;) for (int i = rates.size(); --i >= 0;)
{ {
const double sr = currentAudioDevice->getSampleRate (i); const double sr = rates[i];
if (sr >= 44100.0 && (lowestAbove44 < 1.0 || sr < lowestAbove44)) if (sr >= 44100.0 && (lowestAbove44 < 1.0 || sr < lowestAbove44))
lowestAbove44 = sr; lowestAbove44 = sr;
@ -542,16 +542,14 @@ double AudioDeviceManager::chooseBestSampleRate (double rate) const
if (lowestAbove44 > 0.0) if (lowestAbove44 > 0.0)
return lowestAbove44; return lowestAbove44;
return currentAudioDevice->getSampleRate (0); return rates[0];
} }
int AudioDeviceManager::chooseBestBufferSize (int bufferSize) const int AudioDeviceManager::chooseBestBufferSize (int bufferSize) const
{ {
jassert (currentAudioDevice != nullptr); jassert (currentAudioDevice != nullptr);
if (bufferSize > 0) if (bufferSize > 0 && currentAudioDevice->getAvailableBufferSizes().contains (bufferSize))
for (int i = currentAudioDevice->getNumBufferSizesAvailable(); --i >= 0;)
if (currentAudioDevice->getBufferSizeSamples(i) == bufferSize)
return bufferSize; return bufferSize;
return currentAudioDevice->getDefaultBufferSize(); return currentAudioDevice->getDefaultBufferSize();

@ -190,7 +190,7 @@ public:
int numOutputChannelsNeeded, int numOutputChannelsNeeded,
const XmlElement* savedState, const XmlElement* savedState,
bool selectDefaultDeviceOnFailure, bool selectDefaultDeviceOnFailure,
const String& preferredDefaultDeviceName = String::empty, const String& preferredDefaultDeviceName = String(),
const AudioDeviceSetup* preferredSetupOptions = 0); const AudioDeviceSetup* preferredSetupOptions = 0);
/** Returns some XML representing the current state of the manager. /** Returns some XML representing the current state of the manager.

@ -157,47 +157,19 @@ public:
virtual StringArray getInputChannelNames() = 0; virtual StringArray getInputChannelNames() = 0;
//============================================================================== //==============================================================================
/** Returns the number of sample-rates this device supports. /** Returns the set of sample-rates this device supports.
@see getCurrentSampleRate
To find out which rates are available on this device, use this method to
find out how many there are, and getSampleRate() to get the rates.
@see getSampleRate
*/
virtual int getNumSampleRates() = 0;
/** Returns one of the sample-rates this device supports.
To find out which rates are available on this device, use getNumSampleRates() to
find out how many there are, and getSampleRate() to get the individual rates.
The sample rate is set by the open() method.
(Note that for DirectSound some rates might not work, depending on combinations
of i/o channels that are being opened).
@see getNumSampleRates
*/ */
virtual double getSampleRate (int index) = 0; virtual Array<double> getAvailableSampleRates() = 0;
/** Returns the number of sizes of buffer that are available.
@see getBufferSizeSamples, getDefaultBufferSize /** Returns the set of buffer sizes that are available.
@see getCurrentBufferSizeSamples, getDefaultBufferSize
*/ */
virtual int getNumBufferSizesAvailable() = 0; virtual Array<int> getAvailableBufferSizes() = 0;
/** Returns one of the possible buffer-sizes.
@param index the index of the buffer-size to use, from 0 to getNumBufferSizesAvailable() - 1
@returns a number of samples
@see getNumBufferSizesAvailable, getDefaultBufferSize
*/
virtual int getBufferSizeSamples (int index) = 0;
/** Returns the default buffer-size to use. /** Returns the default buffer-size to use.
@returns a number of samples @returns a number of samples
@see getNumBufferSizesAvailable, getBufferSizeSamples @see getAvailableBufferSizes
*/ */
virtual int getDefaultBufferSize() = 0; virtual int getDefaultBufferSize() = 0;
@ -209,9 +181,9 @@ public:
@param outputChannels a BigInteger in which a set bit indicates that the corresponding @param outputChannels a BigInteger in which a set bit indicates that the corresponding
output channel should be enabled output channel should be enabled
@param sampleRate the sample rate to try to use - to find out which rates are @param sampleRate the sample rate to try to use - to find out which rates are
available, see getNumSampleRates() and getSampleRate() available, see getAvailableSampleRates()
@param bufferSizeSamples the size of i/o buffer to use - to find out the available buffer @param bufferSizeSamples the size of i/o buffer to use - to find out the available buffer
sizes, see getNumBufferSizesAvailable() and getBufferSizeSamples() sizes, see getAvailableBufferSizes()
@returns an error description if there's a problem, or an empty string if it succeeds in @returns an error description if there's a problem, or an empty string if it succeeds in
opening the device opening the device
@see close @see close

@ -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.0", "version": "3.0.1",
"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",

@ -105,7 +105,7 @@ public:
close(); close();
} }
StringArray getOutputChannelNames() StringArray getOutputChannelNames() override
{ {
StringArray s; StringArray s;
s.add ("Left"); s.add ("Left");
@ -113,7 +113,7 @@ public:
return s; return s;
} }
StringArray getInputChannelNames() StringArray getInputChannelNames() override
{ {
StringArray s; StringArray s;
@ -130,36 +130,43 @@ public:
return s; return s;
} }
int getNumSampleRates() { return 1;} Array<double> getAvailableSampleRates() override
double getSampleRate (int index) { return sampleRate; } {
Array<double> r;
int getDefaultBufferSize() { return 2048; } r.add ((double) sampleRate);
int getNumBufferSizesAvailable() { return 50; } return r;
}
int getBufferSizeSamples (int index) Array<int> getAvailableBufferSizes() override
{ {
Array<int> b;
int n = 16; int n = 16;
for (int i = 0; i < index; ++i)
for (int i = 0; i < 50; ++i)
{
b.add (n);
n += n < 64 ? 16 n += n < 64 ? 16
: (n < 512 ? 32 : (n < 512 ? 32
: (n < 1024 ? 64 : (n < 1024 ? 64
: (n < 2048 ? 128 : 256))); : (n < 2048 ? 128 : 256)));
}
return n; return b;
} }
int getDefaultBufferSize() override { return 2048; }
String open (const BigInteger& inputChannels, String open (const BigInteger& inputChannels,
const BigInteger& outputChannels, const BigInteger& outputChannels,
double requestedSampleRate, double requestedSampleRate,
int bufferSize) int bufferSize) override
{ {
close(); close();
if (sampleRate != (int) requestedSampleRate) if (sampleRate != (int) requestedSampleRate)
return "Sample rate not allowed"; return "Sample rate not allowed";
lastError = String::empty; lastError.clear();
int preferredBufferSize = (bufferSize <= 0) ? getDefaultBufferSize() : bufferSize; int preferredBufferSize = (bufferSize <= 0) ? getDefaultBufferSize() : bufferSize;
numDeviceInputChannels = 0; numDeviceInputChannels = 0;
@ -227,7 +234,7 @@ public:
return lastError; return lastError;
} }
void close() void close() override
{ {
if (isRunning) if (isRunning)
{ {
@ -237,18 +244,18 @@ public:
} }
} }
int getOutputLatencyInSamples() { return (minBufferSizeOut * 3) / 4; } int getOutputLatencyInSamples() override { return (minBufferSizeOut * 3) / 4; }
int getInputLatencyInSamples() { return (minBufferSizeIn * 3) / 4; } int getInputLatencyInSamples() override { return (minBufferSizeIn * 3) / 4; }
bool isOpen() { return isRunning; } bool isOpen() override { return isRunning; }
int getCurrentBufferSizeSamples() { return actualBufferSize; } int getCurrentBufferSizeSamples() override { return actualBufferSize; }
int getCurrentBitDepth() { return 16; } int getCurrentBitDepth() override { return 16; }
double getCurrentSampleRate() { return sampleRate; } double getCurrentSampleRate() override { return sampleRate; }
BigInteger getActiveOutputChannels() const { return activeOutputChans; } BigInteger getActiveOutputChannels() const override { return activeOutputChans; }
BigInteger getActiveInputChannels() const { return activeInputChans; } BigInteger getActiveInputChannels() const override { return activeInputChans; }
String getLastError() { return lastError; } String getLastError() override { return lastError; }
bool isPlaying() { return isRunning && callback != 0; } bool isPlaying() override { return isRunning && callback != 0; }
void start (AudioIODeviceCallback* newCallback) void start (AudioIODeviceCallback* newCallback) override
{ {
if (isRunning && callback != newCallback) if (isRunning && callback != newCallback)
{ {
@ -260,7 +267,7 @@ public:
} }
} }
void stop() void stop() override
{ {
if (isRunning) if (isRunning)
{ {

@ -30,9 +30,6 @@ bool isOpenSLAvailable()
return library.open ("libOpenSLES.so"); return library.open ("libOpenSLES.so");
} }
const unsigned short openSLRates[] = { 8000, 16000, 32000, 44100, 48000 };
const unsigned short openSLBufferSizes[] = { 256, 512, 768, 1024, 1280, 1600 }; // must all be multiples of the block size
//============================================================================== //==============================================================================
class OpenSLAudioIODevice : public AudioIODevice, class OpenSLAudioIODevice : public AudioIODevice,
public Thread public Thread
@ -66,7 +63,7 @@ public:
bool openedOk() const { return engine.outputMixObject != nullptr; } bool openedOk() const { return engine.outputMixObject != nullptr; }
StringArray getOutputChannelNames() StringArray getOutputChannelNames() override
{ {
StringArray s; StringArray s;
s.add ("Left"); s.add ("Left");
@ -74,38 +71,33 @@ public:
return s; return s;
} }
StringArray getInputChannelNames() StringArray getInputChannelNames() override
{ {
StringArray s; StringArray s;
s.add ("Audio Input"); s.add ("Audio Input");
return s; return s;
} }
int getNumSampleRates() { return numElementsInArray (openSLRates); } Array<double> getAvailableSampleRates() override
double getSampleRate (int index)
{ {
jassert (index >= 0 && index < getNumSampleRates()); static const double rates[] = { 8000.0, 16000.0, 32000.0, 44100.0, 48000.0 };
return (int) openSLRates [index]; return Array<double> (rates, numElementsInArray (rates));
} }
int getDefaultBufferSize() { return 1024; } Array<int> getAvailableBufferSizes() override
int getNumBufferSizesAvailable() { return numElementsInArray (openSLBufferSizes); }
int getBufferSizeSamples (int index)
{ {
jassert (index >= 0 && index < getNumBufferSizesAvailable()); static const int sizes[] = { 256, 512, 768, 1024, 1280, 1600 }; // must all be multiples of the block size
return (int) openSLBufferSizes [index]; return Array<int> (sizes, numElementsInArray (sizes));
} }
String open (const BigInteger& inputChannels, String open (const BigInteger& inputChannels,
const BigInteger& outputChannels, const BigInteger& outputChannels,
double requestedSampleRate, double requestedSampleRate,
int bufferSize) int bufferSize) override
{ {
close(); close();
lastError = String::empty; lastError.clear();
sampleRate = (int) requestedSampleRate; sampleRate = (int) requestedSampleRate;
int preferredBufferSize = (bufferSize <= 0) ? getDefaultBufferSize() : bufferSize; int preferredBufferSize = (bufferSize <= 0) ? getDefaultBufferSize() : bufferSize;
@ -133,7 +125,7 @@ public:
return lastError; return lastError;
} }
void close() void close() override
{ {
stop(); stop();
stopThread (6000); stopThread (6000);
@ -142,18 +134,19 @@ public:
player = nullptr; player = nullptr;
} }
int getOutputLatencyInSamples() { return outputLatency; } int getDefaultBufferSize() override { return 1024; }
int getInputLatencyInSamples() { return inputLatency; } int getOutputLatencyInSamples() override { return outputLatency; }
bool isOpen() { return deviceOpen; } int getInputLatencyInSamples() override { return inputLatency; }
int getCurrentBufferSizeSamples() { return actualBufferSize; } bool isOpen() override { return deviceOpen; }
int getCurrentBitDepth() { return 16; } int getCurrentBufferSizeSamples() override { return actualBufferSize; }
double getCurrentSampleRate() { return sampleRate; } int getCurrentBitDepth() override { return 16; }
BigInteger getActiveOutputChannels() const { return activeOutputChans; } double getCurrentSampleRate() override { return sampleRate; }
BigInteger getActiveInputChannels() const { return activeInputChans; } BigInteger getActiveOutputChannels() const override { return activeOutputChans; }
String getLastError() { return lastError; } BigInteger getActiveInputChannels() const override { return activeInputChans; }
bool isPlaying() { return callback != nullptr; } String getLastError() override { return lastError; }
bool isPlaying() override { return callback != nullptr; }
void start (AudioIODeviceCallback* newCallback) void start (AudioIODeviceCallback* newCallback) override
{ {
stop(); stop();
@ -166,7 +159,7 @@ public:
} }
} }
void stop() void stop() override
{ {
if (AudioIODeviceCallback* const oldCallback = setCallback (nullptr)) if (AudioIODeviceCallback* const oldCallback = setCallback (nullptr))
oldCallback->audioDeviceStopped(); oldCallback->audioDeviceStopped();

@ -48,7 +48,7 @@ public:
close(); close();
} }
StringArray getOutputChannelNames() StringArray getOutputChannelNames() override
{ {
StringArray s; StringArray s;
s.add ("Left"); s.add ("Left");
@ -56,7 +56,7 @@ public:
return s; return s;
} }
StringArray getInputChannelNames() StringArray getInputChannelNames() override
{ {
StringArray s; StringArray s;
if (audioInputIsAvailable) if (audioInputIsAvailable)
@ -67,20 +67,27 @@ public:
return s; return s;
} }
int getNumSampleRates() { return jmax (1, sampleRates.size()); } Array<double> getAvailableSampleRates() override { return sampleRates; }
double getSampleRate (int index) { return sampleRates.size() > 0 ? sampleRates [index] : sampleRate; }
int getNumBufferSizesAvailable() { return 6; } Array<int> getAvailableBufferSizes() override
int getBufferSizeSamples (int index) { return 1 << (jlimit (0, 5, index) + 6); } {
int getDefaultBufferSize() { return 1024; } Array<int> r;
for (int i = 6; i < 12; ++i)
r.add (1 << i);
return r;
}
int getDefaultBufferSize() override { return 1024; }
String open (const BigInteger& inputChannelsWanted, String open (const BigInteger& inputChannelsWanted,
const BigInteger& outputChannelsWanted, const BigInteger& outputChannelsWanted,
double targetSampleRate, int bufferSize) double targetSampleRate, int bufferSize) override
{ {
close(); close();
lastError = String::empty; lastError.clear();
preferredBufferSize = (bufferSize <= 0) ? getDefaultBufferSize() : bufferSize; preferredBufferSize = (bufferSize <= 0) ? getDefaultBufferSize() : bufferSize;
// xxx set up channel mapping // xxx set up channel mapping
@ -127,7 +134,7 @@ public:
return lastError; return lastError;
} }
void close() void close() override
{ {
if (isRunning) if (isRunning)
{ {
@ -146,19 +153,19 @@ public:
} }
} }
bool isOpen() { return isRunning; } bool isOpen() override { return isRunning; }
int getCurrentBufferSizeSamples() { return actualBufferSize; } int getCurrentBufferSizeSamples() override { return actualBufferSize; }
double getCurrentSampleRate() { return sampleRate; } double getCurrentSampleRate() override { return sampleRate; }
int getCurrentBitDepth() { return 16; } int getCurrentBitDepth() override { return 16; }
BigInteger getActiveOutputChannels() const { return activeOutputChans; } BigInteger getActiveOutputChannels() const override { return activeOutputChans; }
BigInteger getActiveInputChannels() const { return activeInputChans; } BigInteger getActiveInputChannels() const override { return activeInputChans; }
int getOutputLatencyInSamples() { return 0; } //xxx int getOutputLatencyInSamples() override { return 0; } //xxx
int getInputLatencyInSamples() { return 0; } //xxx int getInputLatencyInSamples() override { return 0; } //xxx
void start (AudioIODeviceCallback* newCallback) void start (AudioIODeviceCallback* newCallback) override
{ {
if (isRunning && callback != newCallback) if (isRunning && callback != newCallback)
{ {
@ -170,7 +177,7 @@ public:
} }
} }
void stop() void stop() override
{ {
if (isRunning) if (isRunning)
{ {
@ -187,8 +194,8 @@ public:
} }
} }
bool isPlaying() { return isRunning && callback != nullptr; } bool isPlaying() override { return isRunning && callback != nullptr; }
String getLastError() { return lastError; } String getLastError() override { return lastError; }
private: private:
//================================================================================================== //==================================================================================================
@ -436,6 +443,11 @@ private:
isRunning = true; isRunning = true;
AudioSessionSetActive (true); AudioSessionSetActive (true);
AudioOutputUnitStart (audioUnit); AudioOutputUnitStart (audioUnit);
const ScopedLock sl (callbackLock);
if (callback != nullptr)
callback->audioDeviceError ("iOS audio session resumed");
} }
} }

@ -47,7 +47,7 @@ namespace
#define JUCE_ALSA_FAILED(x) failed (x) #define JUCE_ALSA_FAILED(x) failed (x)
static void getDeviceSampleRates (snd_pcm_t* handle, Array <int>& rates) static void getDeviceSampleRates (snd_pcm_t* handle, Array<double>& rates)
{ {
const int ratesToTry[] = { 22050, 32000, 44100, 48000, 88200, 96000, 176400, 192000, 0 }; const int ratesToTry[] = { 22050, 32000, 44100, 48000, 88200, 96000, 176400, 192000, 0 };
@ -59,7 +59,7 @@ static void getDeviceSampleRates (snd_pcm_t* handle, Array <int>& rates)
if (snd_pcm_hw_params_any (handle, hwParams) >= 0 if (snd_pcm_hw_params_any (handle, hwParams) >= 0
&& snd_pcm_hw_params_test_rate (handle, hwParams, ratesToTry[i], 0) == 0) && snd_pcm_hw_params_test_rate (handle, hwParams, ratesToTry[i], 0) == 0)
{ {
rates.addIfNotAlreadyThere (ratesToTry[i]); rates.addIfNotAlreadyThere ((double) ratesToTry[i]);
} }
} }
} }
@ -91,7 +91,7 @@ static void getDeviceProperties (const String& deviceID,
unsigned int& maxChansOut, unsigned int& maxChansOut,
unsigned int& minChansIn, unsigned int& minChansIn,
unsigned int& maxChansIn, unsigned int& maxChansIn,
Array <int>& rates, Array<double>& rates,
bool testOutput, bool testOutput,
bool testInput) bool testInput)
{ {
@ -482,7 +482,7 @@ public:
{ {
close(); close();
error = String::empty; error.clear();
sampleRate = newSampleRate; sampleRate = newSampleRate;
bufferSize = newBufferSize; bufferSize = newBufferSize;
@ -722,7 +722,7 @@ public:
int bufferSize, outputLatency, inputLatency; int bufferSize, outputLatency, inputLatency;
BigInteger currentInputChans, currentOutputChans; BigInteger currentInputChans, currentOutputChans;
Array <int> sampleRates; Array<double> sampleRates;
StringArray channelNamesOut, channelNamesIn; StringArray channelNamesOut, channelNamesIn;
AudioIODeviceCallback* callback; AudioIODeviceCallback* callback;
@ -798,31 +798,34 @@ public:
close(); close();
} }
StringArray getOutputChannelNames() { return internal.channelNamesOut; } StringArray getOutputChannelNames() override { return internal.channelNamesOut; }
StringArray getInputChannelNames() { return internal.channelNamesIn; } StringArray getInputChannelNames() override { return internal.channelNamesIn; }
int getNumSampleRates() { return internal.sampleRates.size(); } Array<double> getAvailableSampleRates() override { return internal.sampleRates; }
double getSampleRate (int index) { return internal.sampleRates [index]; }
int getDefaultBufferSize() { return 512; } Array<int> getAvailableBufferSizes() override
int getNumBufferSizesAvailable() { return 50; }
int getBufferSizeSamples (int index)
{ {
Array<int> r;
int n = 16; int n = 16;
for (int i = 0; i < index; ++i)
for (int i = 0; i < 50; ++i)
{
r.add (n);
n += n < 64 ? 16 n += n < 64 ? 16
: (n < 512 ? 32 : (n < 512 ? 32
: (n < 1024 ? 64 : (n < 1024 ? 64
: (n < 2048 ? 128 : 256))); : (n < 2048 ? 128 : 256)));
}
return n; return r;
} }
int getDefaultBufferSize() override { return 512; }
String open (const BigInteger& inputChannels, String open (const BigInteger& inputChannels,
const BigInteger& outputChannels, const BigInteger& outputChannels,
double sampleRate, double sampleRate,
int bufferSizeSamples) int bufferSizeSamples) override
{ {
close(); close();
@ -831,11 +834,13 @@ public:
if (sampleRate <= 0) if (sampleRate <= 0)
{ {
for (int i = 0; i < getNumSampleRates(); ++i) for (int i = 0; i < internal.sampleRates.size(); ++i)
{ {
if (getSampleRate (i) >= 44100) double rate = internal.sampleRates[i];
if (rate >= 44100)
{ {
sampleRate = getSampleRate (i); sampleRate = rate;
break; break;
} }
} }
@ -848,28 +853,28 @@ public:
return internal.error; return internal.error;
} }
void close() void close() override
{ {
stop(); stop();
internal.close(); internal.close();
isOpen_ = false; isOpen_ = false;
} }
bool isOpen() { return isOpen_; } bool isOpen() override { return isOpen_; }
bool isPlaying() { return isStarted && internal.error.isEmpty(); } bool isPlaying() override { return isStarted && internal.error.isEmpty(); }
String getLastError() { return internal.error; } String getLastError() override { return internal.error; }
int getCurrentBufferSizeSamples() { return internal.bufferSize; } int getCurrentBufferSizeSamples() override { return internal.bufferSize; }
double getCurrentSampleRate() { return internal.sampleRate; } double getCurrentSampleRate() override { return internal.sampleRate; }
int getCurrentBitDepth() { return internal.getBitDepth(); } int getCurrentBitDepth() override { return internal.getBitDepth(); }
BigInteger getActiveOutputChannels() const { return internal.currentOutputChans; } BigInteger getActiveOutputChannels() const override { return internal.currentOutputChans; }
BigInteger getActiveInputChannels() const { return internal.currentInputChans; } BigInteger getActiveInputChannels() const override { return internal.currentInputChans; }
int getOutputLatencyInSamples() { return internal.outputLatency; } int getOutputLatencyInSamples() override { return internal.outputLatency; }
int getInputLatencyInSamples() { return internal.inputLatency; } int getInputLatencyInSamples() override { return internal.inputLatency; }
void start (AudioIODeviceCallback* callback) void start (AudioIODeviceCallback* callback) override
{ {
if (! isOpen_) if (! isOpen_)
callback = nullptr; callback = nullptr;
@ -882,7 +887,7 @@ public:
isStarted = (callback != nullptr); isStarted = (callback != nullptr);
} }
void stop() void stop() override
{ {
AudioIODeviceCallback* const oldCallback = internal.callback; AudioIODeviceCallback* const oldCallback = internal.callback;
@ -1002,7 +1007,7 @@ private:
{ {
unsigned int minChansOut = 0, maxChansOut = 0; unsigned int minChansOut = 0, maxChansOut = 0;
unsigned int minChansIn = 0, maxChansIn = 0; unsigned int minChansIn = 0, maxChansIn = 0;
Array <int> rates; Array<double> rates;
bool isInput = inputName.isNotEmpty(), isOutput = outputName.isNotEmpty(); bool isInput = inputName.isNotEmpty(), isOutput = outputName.isNotEmpty();
getDeviceProperties (id, minChansOut, maxChansOut, minChansIn, maxChansIn, rates, isOutput, isInput); getDeviceProperties (id, minChansOut, maxChansOut, minChansIn, maxChansIn, rates, isOutput, isInput);

@ -218,16 +218,36 @@ public:
return names; return names;
} }
StringArray getOutputChannelNames() { return getChannelNames (false); } StringArray getOutputChannelNames() override { return getChannelNames (false); }
StringArray getInputChannelNames() { return getChannelNames (true); } StringArray getInputChannelNames() override { return getChannelNames (true); }
int getNumSampleRates() { return client != nullptr ? 1 : 0; }
double getSampleRate (int /*index*/) { return client != nullptr ? juce::jack_get_sample_rate (client) : 0; } Array<double> getAvailableSampleRates() override
int getNumBufferSizesAvailable() { return client != nullptr ? 1 : 0; } {
int getBufferSizeSamples (int /*index*/) { return getDefaultBufferSize(); } Array<double> rates;
int getDefaultBufferSize() { return client != nullptr ? juce::jack_get_buffer_size (client) : 0; }
if (client != nullptr)
rates.add (juce::jack_get_sample_rate (client));
return rates;
}
Array<int> getAvailableBufferSizes() override
{
Array<int> sizes;
if (client != nullptr)
sizes.add (juce::jack_get_buffer_size (client));
return sizes;
}
int getDefaultBufferSize() override { return getCurrentBufferSizeSamples(); }
int getCurrentBufferSizeSamples() override { return client != nullptr ? juce::jack_get_buffer_size (client) : 0; }
double getCurrentSampleRate() override { return client != nullptr ? juce::jack_get_sample_rate (client) : 0; }
String open (const BigInteger& inputChannels, const BigInteger& outputChannels, String open (const BigInteger& inputChannels, const BigInteger& outputChannels,
double /* sampleRate */, int /* bufferSizeSamples */) double /* sampleRate */, int /* bufferSizeSamples */) override
{ {
if (client == nullptr) if (client == nullptr)
{ {
@ -235,7 +255,7 @@ public:
return lastError; return lastError;
} }
lastError = String::empty; lastError.clear();
close(); close();
juce::jack_set_process_callback (client, processCallback, this); juce::jack_set_process_callback (client, processCallback, this);
@ -273,7 +293,7 @@ public:
return lastError; return lastError;
} }
void close() void close() override
{ {
stop(); stop();
@ -288,7 +308,7 @@ public:
deviceIsOpen = false; deviceIsOpen = false;
} }
void start (AudioIODeviceCallback* newCallback) void start (AudioIODeviceCallback* newCallback) override
{ {
if (deviceIsOpen && newCallback != callback) if (deviceIsOpen && newCallback != callback)
{ {
@ -307,22 +327,20 @@ public:
} }
} }
void stop() void stop() override
{ {
start (nullptr); start (nullptr);
} }
bool isOpen() { return deviceIsOpen; } bool isOpen() override { return deviceIsOpen; }
bool isPlaying() { return callback != nullptr; } bool isPlaying() override { return callback != nullptr; }
int getCurrentBufferSizeSamples() { return getBufferSizeSamples (0); } int getCurrentBitDepth() override { return 32; }
double getCurrentSampleRate() { return getSampleRate (0); } String getLastError() override { return lastError; }
int getCurrentBitDepth() { return 32; }
String getLastError() { return lastError; }
BigInteger getActiveOutputChannels() const { return activeOutputChannels; } BigInteger getActiveOutputChannels() const override { return activeOutputChannels; }
BigInteger getActiveInputChannels() const { return activeInputChannels; } BigInteger getActiveInputChannels() const override { return activeInputChannels; }
int getOutputLatencyInSamples() int getOutputLatencyInSamples() override
{ {
int latency = 0; int latency = 0;
@ -332,7 +350,7 @@ public:
return latency; return latency;
} }
int getInputLatencyInSamples() int getInputLatencyInSamples() override
{ {
int latency = 0; int latency = 0;

@ -366,13 +366,13 @@ public:
{ {
// find a list of sample rates.. // find a list of sample rates..
const int possibleSampleRates[] = { 44100, 48000, 88200, 96000, 176400, 192000 }; const int possibleSampleRates[] = { 44100, 48000, 88200, 96000, 176400, 192000 };
Array<int> newRates; Array<double> newRates;
if (asioObject != nullptr) if (asioObject != nullptr)
{ {
for (int index = 0; index < numElementsInArray (possibleSampleRates); ++index) for (int index = 0; index < numElementsInArray (possibleSampleRates); ++index)
if (asioObject->canSampleRate ((double) possibleSampleRates[index]) == 0) if (asioObject->canSampleRate ((double) possibleSampleRates[index]) == 0)
newRates.add (possibleSampleRates[index]); newRates.add ((double) possibleSampleRates[index]);
} }
if (newRates.size() == 0) if (newRates.size() == 0)
@ -398,19 +398,16 @@ public:
} }
} }
StringArray getOutputChannelNames() { return outputChannelNames; } StringArray getOutputChannelNames() override { return outputChannelNames; }
StringArray getInputChannelNames() { return inputChannelNames; } StringArray getInputChannelNames() override { return inputChannelNames; }
int getNumSampleRates() { return sampleRates.size(); } Array<double> getAvailableSampleRates() override { return sampleRates; }
double getSampleRate (int index) { return sampleRates [index]; } Array<int> getAvailableBufferSizes() override { return bufferSizes; }
int getDefaultBufferSize() override { return preferredSize; }
int getNumBufferSizesAvailable() { return bufferSizes.size(); }
int getBufferSizeSamples (int index) { return bufferSizes [index]; }
int getDefaultBufferSize() { return preferredSize; }
String open (const BigInteger& inputChannels, String open (const BigInteger& inputChannels,
const BigInteger& outputChannels, const BigInteger& outputChannels,
double sr, int bufferSizeSamples) double sr, int bufferSizeSamples) override
{ {
if (isOpen()) if (isOpen())
close(); close();
@ -436,7 +433,7 @@ public:
bufferSizeSamples = readBufferSizes (bufferSizeSamples); bufferSizeSamples = readBufferSizes (bufferSizeSamples);
int sampleRate = roundToInt (sr); double sampleRate = sr;
currentSampleRate = sampleRate; currentSampleRate = sampleRate;
currentBlockSizeSamples = bufferSizeSamples; currentBlockSizeSamples = bufferSizeSamples;
currentChansOut.clear(); currentChansOut.clear();
@ -451,12 +448,12 @@ public:
jassert (sampleRate != 0); jassert (sampleRate != 0);
if (sampleRate == 0) if (sampleRate == 0)
sampleRate = 44100; sampleRate = 44100.0;
updateClockSources(); updateClockSources();
currentSampleRate = getSampleRate(); currentSampleRate = getSampleRate();
error = String::empty; error.clear();
buffersCreated = false; buffersCreated = false;
setSampleRate (sampleRate); setSampleRate (sampleRate);
@ -615,9 +612,9 @@ public:
return error; return error;
} }
void close() void close() override
{ {
error = String::empty; error.clear();
stopTimer(); stopTimer();
stop(); stop();
@ -643,20 +640,20 @@ public:
} }
} }
bool isOpen() { return deviceIsOpen || insideControlPanelModalLoop; } bool isOpen() override { return deviceIsOpen || insideControlPanelModalLoop; }
bool isPlaying() { return asioObject != nullptr && currentCallback != nullptr; } bool isPlaying() override { return asioObject != nullptr && currentCallback != nullptr; }
int getCurrentBufferSizeSamples() { return currentBlockSizeSamples; } int getCurrentBufferSizeSamples() override { return currentBlockSizeSamples; }
double getCurrentSampleRate() { return currentSampleRate; } double getCurrentSampleRate() override { return currentSampleRate; }
int getCurrentBitDepth() { return currentBitDepth; } int getCurrentBitDepth() override { return currentBitDepth; }
BigInteger getActiveOutputChannels() const { return currentChansOut; } BigInteger getActiveOutputChannels() const override { return currentChansOut; }
BigInteger getActiveInputChannels() const { return currentChansIn; } BigInteger getActiveInputChannels() const override { return currentChansIn; }
int getOutputLatencyInSamples() { return outputLatency + currentBlockSizeSamples / 4; } int getOutputLatencyInSamples() override { return outputLatency + currentBlockSizeSamples / 4; }
int getInputLatencyInSamples() { return inputLatency + currentBlockSizeSamples / 4; } int getInputLatencyInSamples() override { return inputLatency + currentBlockSizeSamples / 4; }
void start (AudioIODeviceCallback* callback) void start (AudioIODeviceCallback* callback) override
{ {
if (callback != nullptr) if (callback != nullptr)
{ {
@ -667,7 +664,7 @@ public:
} }
} }
void stop() void stop() override
{ {
AudioIODeviceCallback* const lastCallback = currentCallback; AudioIODeviceCallback* const lastCallback = currentCallback;
@ -764,7 +761,8 @@ private:
long totalNumInputChans, totalNumOutputChans; long totalNumInputChans, totalNumOutputChans;
StringArray inputChannelNames, outputChannelNames; StringArray inputChannelNames, outputChannelNames;
Array<int> sampleRates, bufferSizes; Array<double> sampleRates;
Array<int> bufferSizes;
long inputLatency, outputLatency; long inputLatency, outputLatency;
long minSize, maxSize, preferredSize, granularity; long minSize, maxSize, preferredSize, granularity;
ASIOClockSource clocks[32]; ASIOClockSource clocks[32];
@ -951,7 +949,7 @@ private:
return cr; return cr;
} }
void setSampleRate (int newRate) void setSampleRate (double newRate)
{ {
if (currentSampleRate != newRate) if (currentSampleRate != newRate)
{ {
@ -1181,7 +1179,7 @@ private:
numActiveOutputChans = 0; numActiveOutputChans = 0;
currentCallback = nullptr; currentCallback = nullptr;
error = String::empty; error.clear();
if (getName().isEmpty()) if (getName().isEmpty())
return error; return error;

@ -755,7 +755,7 @@ public:
String open (const BigInteger& inputChannels, String open (const BigInteger& inputChannels,
const BigInteger& outputChannels, const BigInteger& outputChannels,
double sampleRate, int bufferSizeSamples) double sampleRate, int bufferSizeSamples) override
{ {
lastError = openDevice (inputChannels, outputChannels, sampleRate, bufferSizeSamples); lastError = openDevice (inputChannels, outputChannels, sampleRate, bufferSizeSamples);
isOpen_ = lastError.isEmpty(); isOpen_ = lastError.isEmpty();
@ -763,7 +763,7 @@ public:
return lastError; return lastError;
} }
void close() void close() override
{ {
stop(); stop();
@ -774,38 +774,41 @@ public:
} }
} }
bool isOpen() { return isOpen_ && isThreadRunning(); } bool isOpen() override { return isOpen_ && isThreadRunning(); }
int getCurrentBufferSizeSamples() { return bufferSizeSamples; } int getCurrentBufferSizeSamples() override { return bufferSizeSamples; }
double getCurrentSampleRate() { return sampleRate; } double getCurrentSampleRate() override { return sampleRate; }
BigInteger getActiveOutputChannels() const { return enabledOutputs; } BigInteger getActiveOutputChannels() const override { return enabledOutputs; }
BigInteger getActiveInputChannels() const { return enabledInputs; } BigInteger getActiveInputChannels() const override { return enabledInputs; }
int getOutputLatencyInSamples() { return (int) (getCurrentBufferSizeSamples() * 1.5); } int getOutputLatencyInSamples() override { return (int) (getCurrentBufferSizeSamples() * 1.5); }
int getInputLatencyInSamples() { return getOutputLatencyInSamples(); } int getInputLatencyInSamples() override { return getOutputLatencyInSamples(); }
StringArray getOutputChannelNames() { return outChannels; } StringArray getOutputChannelNames() override { return outChannels; }
StringArray getInputChannelNames() { return inChannels; } StringArray getInputChannelNames() override { return inChannels; }
int getNumSampleRates() { return 4; }
int getDefaultBufferSize() { return 2560; }
int getNumBufferSizesAvailable() { return 50; }
double getSampleRate (int index) Array<double> getAvailableSampleRates() override
{ {
const double samps[] = { 44100.0, 48000.0, 88200.0, 96000.0 }; static const double rates[] = { 44100.0, 48000.0, 88200.0, 96000.0 };
return samps [jlimit (0, 3, index)]; return Array<double> (rates, numElementsInArray (rates));
} }
int getBufferSizeSamples (int index) Array<int> getAvailableBufferSizes() override
{ {
Array<int> r;
int n = 64; int n = 64;
for (int i = 0; i < index; ++i)
for (int i = 0; i < 50; ++i)
{
r.add (n);
n += (n < 512) ? 32 n += (n < 512) ? 32
: ((n < 1024) ? 64 : ((n < 1024) ? 64
: ((n < 2048) ? 128 : 256)); : ((n < 2048) ? 128 : 256));
}
return n; return r;
} }
int getCurrentBitDepth() int getDefaultBufferSize() override { return 2560; }
int getCurrentBitDepth() override
{ {
int bits = 256; int bits = 256;
@ -821,7 +824,7 @@ public:
return bits; return bits;
} }
void start (AudioIODeviceCallback* call) void start (AudioIODeviceCallback* call) override
{ {
if (isOpen_ && call != nullptr && ! isStarted) if (isOpen_ && call != nullptr && ! isStarted)
{ {
@ -840,7 +843,7 @@ public:
} }
} }
void stop() void stop() override
{ {
if (isStarted) if (isStarted)
{ {
@ -856,8 +859,8 @@ public:
} }
} }
bool isPlaying() { return isStarted && isOpen_ && isThreadRunning(); } bool isPlaying() override { return isStarted && isOpen_ && isThreadRunning(); }
String getLastError() { return lastError; } String getLastError() override { return lastError; }
//============================================================================== //==============================================================================
StringArray inChannels, outChannels; StringArray inChannels, outChannels;

@ -882,7 +882,7 @@ public:
return false; return false;
} }
StringArray getOutputChannelNames() StringArray getOutputChannelNames() override
{ {
StringArray outChannels; StringArray outChannels;
@ -893,7 +893,7 @@ public:
return outChannels; return outChannels;
} }
StringArray getInputChannelNames() StringArray getInputChannelNames() override
{ {
StringArray inChannels; StringArray inChannels;
@ -904,31 +904,29 @@ public:
return inChannels; return inChannels;
} }
int getNumSampleRates() { return sampleRates.size(); } Array<double> getAvailableSampleRates() override { return sampleRates; }
double getSampleRate (int index) { return sampleRates [index]; } Array<int> getAvailableBufferSizes() override { return bufferSizes; }
int getNumBufferSizesAvailable() { return bufferSizes.size(); } int getDefaultBufferSize() override { return defaultBufferSize; }
int getBufferSizeSamples (int index) { return bufferSizes [index]; }
int getDefaultBufferSize() { return defaultBufferSize; }
int getCurrentBufferSizeSamples() { return currentBufferSizeSamples; } int getCurrentBufferSizeSamples() override { return currentBufferSizeSamples; }
double getCurrentSampleRate() { return currentSampleRate; } double getCurrentSampleRate() override { return currentSampleRate; }
int getCurrentBitDepth() { return 32; } int getCurrentBitDepth() override { return 32; }
int getOutputLatencyInSamples() { return latencyOut; } int getOutputLatencyInSamples() override { return latencyOut; }
int getInputLatencyInSamples() { return latencyIn; } int getInputLatencyInSamples() override { return latencyIn; }
BigInteger getActiveOutputChannels() const { return outputDevice != nullptr ? outputDevice->channels : BigInteger(); } BigInteger getActiveOutputChannels() const override { return outputDevice != nullptr ? outputDevice->channels : BigInteger(); }
BigInteger getActiveInputChannels() const { return inputDevice != nullptr ? inputDevice->channels : BigInteger(); } BigInteger getActiveInputChannels() const override { return inputDevice != nullptr ? inputDevice->channels : BigInteger(); }
String getLastError() { return lastError; } String getLastError() override { return lastError; }
String open (const BigInteger& inputChannels, const BigInteger& outputChannels, String open (const BigInteger& inputChannels, const BigInteger& outputChannels,
double sampleRate, int bufferSizeSamples) double sampleRate, int bufferSizeSamples) override
{ {
close(); close();
lastError = String::empty; lastError.clear();
if (sampleRates.size() == 0 && inputDevice != nullptr && outputDevice != nullptr) if (sampleRates.size() == 0 && inputDevice != nullptr && outputDevice != nullptr)
{ {
lastError = "The input and output devices don't share a common sample rate!"; lastError = TRANS("The input and output devices don't share a common sample rate!");
return lastError; return lastError;
} }
@ -939,14 +937,14 @@ public:
if (inputDevice != nullptr && ! inputDevice->open (currentSampleRate, inputChannels)) if (inputDevice != nullptr && ! inputDevice->open (currentSampleRate, inputChannels))
{ {
lastError = "Couldn't open the input device!"; lastError = TRANS("Couldn't open the input device!");
return lastError; return lastError;
} }
if (outputDevice != nullptr && ! outputDevice->open (currentSampleRate, outputChannels)) if (outputDevice != nullptr && ! outputDevice->open (currentSampleRate, outputChannels))
{ {
close(); close();
lastError = "Couldn't open the output device!"; lastError = TRANS("Couldn't open the output device!");
return lastError; return lastError;
} }
@ -963,7 +961,7 @@ public:
if (! check (inputDevice->client->Start())) if (! check (inputDevice->client->Start()))
{ {
close(); close();
lastError = "Couldn't start the input device!"; lastError = TRANS("Couldn't start the input device!");
return lastError; return lastError;
} }
} }
@ -975,7 +973,7 @@ public:
if (! check (outputDevice->client->Start())) if (! check (outputDevice->client->Start()))
{ {
close(); close();
lastError = "Couldn't start the output device!"; lastError = TRANS("Couldn't start the output device!");
return lastError; return lastError;
} }
} }
@ -984,7 +982,7 @@ public:
return lastError; return lastError;
} }
void close() void close() override
{ {
stop(); stop();
signalThreadShouldExit(); signalThreadShouldExit();
@ -1000,10 +998,10 @@ public:
isOpen_ = false; isOpen_ = false;
} }
bool isOpen() { return isOpen_ && isThreadRunning(); } bool isOpen() override { return isOpen_ && isThreadRunning(); }
bool isPlaying() { return isStarted && isOpen_ && isThreadRunning(); } bool isPlaying() override { return isStarted && isOpen_ && isThreadRunning(); }
void start (AudioIODeviceCallback* call) void start (AudioIODeviceCallback* call) override
{ {
if (isOpen_ && call != nullptr && ! isStarted) if (isOpen_ && call != nullptr && ! isStarted)
{ {
@ -1022,7 +1020,7 @@ public:
} }
} }
void stop() void stop() override
{ {
if (isStarted) if (isStarted)
{ {

@ -65,8 +65,7 @@ public:
void setSource (AudioSource* newSource); void setSource (AudioSource* newSource);
/** Returns the source that's playing. /** Returns the source that's playing.
May return nullptr if there's no source.
May return 0 if there's no source.
*/ */
AudioSource* getCurrentSource() const noexcept { return source; } AudioSource* getCurrentSource() const noexcept { return source; }

@ -44,15 +44,12 @@ AudioTransportSource::AudioTransportSource()
AudioTransportSource::~AudioTransportSource() AudioTransportSource::~AudioTransportSource()
{ {
setSource (nullptr); setSource (nullptr);
releaseMasterResources(); releaseMasterResources();
} }
void AudioTransportSource::setSource (PositionableAudioSource* const newSource, void AudioTransportSource::setSource (PositionableAudioSource* const newSource,
int readAheadBufferSize_, int readAheadSize, TimeSliceThread* readAheadThread,
TimeSliceThread* readAheadThread, double sourceSampleRateToCorrectFor, int maxNumChannels)
double sourceSampleRateToCorrectFor,
int maxNumChannels)
{ {
if (source == newSource) if (source == newSource)
{ {
@ -62,7 +59,7 @@ void AudioTransportSource::setSource (PositionableAudioSource* const newSource,
setSource (nullptr, 0, nullptr); // deselect and reselect to avoid releasing resources wrongly setSource (nullptr, 0, nullptr); // deselect and reselect to avoid releasing resources wrongly
} }
readAheadBufferSize = readAheadBufferSize_; readAheadBufferSize = readAheadSize;
sourceSampleRate = sourceSampleRateToCorrectFor; sourceSampleRate = sourceSampleRateToCorrectFor;
ResamplingAudioSource* newResamplerSource = nullptr; ResamplingAudioSource* newResamplerSource = nullptr;
@ -78,7 +75,7 @@ void AudioTransportSource::setSource (PositionableAudioSource* const newSource,
{ {
newPositionableSource = newSource; newPositionableSource = newSource;
if (readAheadBufferSize_ > 0) if (readAheadSize > 0)
{ {
// If you want to use a read-ahead buffer, you must also provide a TimeSliceThread // If you want to use a read-ahead buffer, you must also provide a TimeSliceThread
// for it to use! // for it to use!
@ -86,7 +83,7 @@ void AudioTransportSource::setSource (PositionableAudioSource* const newSource,
newPositionableSource = newBufferingSource newPositionableSource = newBufferingSource
= new BufferingAudioSource (newPositionableSource, *readAheadThread, = new BufferingAudioSource (newPositionableSource, *readAheadThread,
false, readAheadBufferSize_, maxNumChannels); false, readAheadSize, maxNumChannels);
} }
newPositionableSource->setNextReadPosition (0); newPositionableSource->setNextReadPosition (0);
@ -115,6 +112,7 @@ void AudioTransportSource::setSource (PositionableAudioSource* const newSource,
masterSource = newMasterSource; masterSource = newMasterSource;
positionableSource = newPositionableSource; positionableSource = newPositionableSource;
inputStreamEOF = false;
playing = false; playing = false;
} }
@ -170,7 +168,10 @@ double AudioTransportSource::getCurrentPosition() const
double AudioTransportSource::getLengthInSeconds() const double AudioTransportSource::getLengthInSeconds() const
{ {
if (sampleRate > 0.0)
return getTotalLength() / sampleRate; return getTotalLength() / sampleRate;
return 0.0;
} }
void AudioTransportSource::setNextReadPosition (int64 newPosition) void AudioTransportSource::setNextReadPosition (int64 newPosition)
@ -181,6 +182,7 @@ void AudioTransportSource::setNextReadPosition (int64 newPosition)
newPosition = (int64) (newPosition * sourceSampleRate / sampleRate); newPosition = (int64) (newPosition * sourceSampleRate / sampleRate);
positionableSource->setNextReadPosition (newPosition); positionableSource->setNextReadPosition (newPosition);
inputStreamEOF = false;
} }
} }
@ -189,7 +191,6 @@ int64 AudioTransportSource::getNextReadPosition() const
if (positionableSource != nullptr) if (positionableSource != nullptr)
{ {
const double ratio = (sampleRate > 0 && sourceSampleRate > 0) ? sampleRate / sourceSampleRate : 1.0; const double ratio = (sampleRate > 0 && sourceSampleRate > 0) ? sampleRate / sourceSampleRate : 1.0;
return (int64) (positionableSource->getNextReadPosition() * ratio); return (int64) (positionableSource->getNextReadPosition() * ratio);
} }
@ -203,7 +204,6 @@ int64 AudioTransportSource::getTotalLength() const
if (positionableSource != nullptr) if (positionableSource != nullptr)
{ {
const double ratio = (sampleRate > 0 && sourceSampleRate > 0) ? sampleRate / sourceSampleRate : 1.0; const double ratio = (sampleRate > 0 && sourceSampleRate > 0) ? sampleRate / sourceSampleRate : 1.0;
return (int64) (positionableSource->getTotalLength() * ratio); return (int64) (positionableSource->getTotalLength() * ratio);
} }
@ -213,9 +213,7 @@ int64 AudioTransportSource::getTotalLength() const
bool AudioTransportSource::isLooping() const bool AudioTransportSource::isLooping() const
{ {
const ScopedLock sl (callbackLock); const ScopedLock sl (callbackLock);
return positionableSource != nullptr && positionableSource->isLooping();
return positionableSource != nullptr
&& positionableSource->isLooping();
} }
void AudioTransportSource::setGain (const float newGain) noexcept void AudioTransportSource::setGain (const float newGain) noexcept
@ -236,6 +234,7 @@ void AudioTransportSource::prepareToPlay (int samplesPerBlockExpected, double ne
if (resamplerSource != nullptr && sourceSampleRate > 0) if (resamplerSource != nullptr && sourceSampleRate > 0)
resamplerSource->setResamplingRatio (sourceSampleRate / sampleRate); resamplerSource->setResamplingRatio (sourceSampleRate / sampleRate);
inputStreamEOF = false;
isPrepared = true; isPrepared = true;
} }
@ -258,8 +257,6 @@ void AudioTransportSource::getNextAudioBlock (const AudioSourceChannelInfo& info
{ {
const ScopedLock sl (callbackLock); const ScopedLock sl (callbackLock);
inputStreamEOF = false;
if (masterSource != nullptr && ! stopped) if (masterSource != nullptr && ! stopped)
{ {
masterSource->getNextAudioBlock (info); masterSource->getNextAudioBlock (info);
@ -285,10 +282,7 @@ void AudioTransportSource::getNextAudioBlock (const AudioSourceChannelInfo& info
stopped = ! playing; stopped = ! playing;
for (int i = info.buffer->getNumChannels(); --i >= 0;) for (int i = info.buffer->getNumChannels(); --i >= 0;)
{ info.buffer->applyGainRamp (i, info.startSample, info.numSamples, lastGain, gain);
info.buffer->applyGainRamp (i, info.startSample, info.numSamples,
lastGain, gain);
}
} }
else else
{ {

@ -45,7 +45,6 @@ class JUCE_API AudioTransportSource : public PositionableAudioSource,
public: public:
//============================================================================== //==============================================================================
/** Creates an AudioTransportSource. /** Creates an AudioTransportSource.
After creating one of these, use the setSource() method to select an input source. After creating one of these, use the setSource() method to select an input source.
*/ */
AudioTransportSource(); AudioTransportSource();
@ -94,7 +93,6 @@ public:
void setPosition (double newPosition); void setPosition (double newPosition);
/** Returns the position that the next data block will be read from /** Returns the position that the next data block will be read from
This is a time in seconds. This is a time in seconds.
*/ */
double getCurrentPosition() const; double getCurrentPosition() const;
@ -102,8 +100,7 @@ public:
/** Returns the stream's length in seconds. */ /** Returns the stream's length in seconds. */
double getLengthInSeconds() const; double getLengthInSeconds() const;
/** Returns true if the player has stopped because its input stream ran out of data. /** Returns true if the player has stopped because its input stream ran out of data. */
*/
bool hasStreamFinished() const noexcept { return inputStreamEOF; } bool hasStreamFinished() const noexcept { return inputStreamEOF; }
//============================================================================== //==============================================================================
@ -126,19 +123,16 @@ public:
//============================================================================== //==============================================================================
/** Changes the gain to apply to the output. /** Changes the gain to apply to the output.
@param newGain a factor by which to multiply the outgoing samples, @param newGain a factor by which to multiply the outgoing samples,
so 1.0 = 0dB, 0.5 = -6dB, 2.0 = 6dB, etc. so 1.0 = 0dB, 0.5 = -6dB, 2.0 = 6dB, etc.
*/ */
void setGain (float newGain) noexcept; void setGain (float newGain) noexcept;
/** Returns the current gain setting. /** Returns the current gain setting.
@see setGain @see setGain
*/ */
float getGain() const noexcept { return gain; } float getGain() const noexcept { return gain; }
//============================================================================== //==============================================================================
/** Implementation of the AudioSource method. */ /** Implementation of the AudioSource method. */
void prepareToPlay (int samplesPerBlockExpected, double sampleRate) override; void prepareToPlay (int samplesPerBlockExpected, double sampleRate) override;
@ -175,7 +169,7 @@ private:
bool volatile playing, stopped; bool volatile playing, stopped;
double sampleRate, sourceSampleRate; double sampleRate, sourceSampleRate;
int blockSize, readAheadBufferSize; int blockSize, readAheadBufferSize;
bool isPrepared, inputStreamEOF; bool volatile isPrepared, inputStreamEOF;
void releaseMasterResources(); void releaseMasterResources();

@ -1348,12 +1348,12 @@ FLAC__bool has_id_filtered_(FLAC__StreamDecoder *decoder, FLAC__byte *id)
FLAC__bool find_metadata_(FLAC__StreamDecoder *decoder) FLAC__bool find_metadata_(FLAC__StreamDecoder *decoder)
{ {
FLAC__uint32 x; FLAC__uint32 x;
unsigned i, id; unsigned i, id_;
FLAC__bool first = true; FLAC__bool first = true;
FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input)); FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input));
for(i = id = 0; i < 4; ) { for(i = id_ = 0; i < 4; ) {
if(decoder->private_->cached) { if(decoder->private_->cached) {
x = (FLAC__uint32)decoder->private_->lookahead; x = (FLAC__uint32)decoder->private_->lookahead;
decoder->private_->cached = false; decoder->private_->cached = false;
@ -1365,19 +1365,19 @@ FLAC__bool find_metadata_(FLAC__StreamDecoder *decoder)
if(x == FLAC__STREAM_SYNC_STRING[i]) { if(x == FLAC__STREAM_SYNC_STRING[i]) {
first = true; first = true;
i++; i++;
id = 0; id_ = 0;
continue; continue;
} }
if(x == ID3V2_TAG_[id]) { if(x == ID3V2_TAG_[id_]) {
id++; id_++;
i = 0; i = 0;
if(id == 3) { if(id_ == 3) {
if(!skip_id3v2_tag_(decoder)) if(!skip_id3v2_tag_(decoder))
return false; /* skip_id3v2_tag_ sets the state for us */ return false; /* skip_id3v2_tag_ sets the state for us */
} }
continue; continue;
} }
id = 0; id_ = 0;
if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */ if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */
decoder->private_->header_warmup[0] = (FLAC__byte)x; decoder->private_->header_warmup[0] = (FLAC__byte)x;
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 8)) if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 8))

@ -343,7 +343,7 @@ namespace AiffFileHelpers
out.writeIntBigEndian (values.getValue (prefix + "TimeStamp", "0").getIntValue()); out.writeIntBigEndian (values.getValue (prefix + "TimeStamp", "0").getIntValue());
out.writeShortBigEndian ((short) values.getValue (prefix + "Identifier", "0").getIntValue()); out.writeShortBigEndian ((short) values.getValue (prefix + "Identifier", "0").getIntValue());
const String comment (values.getValue (prefix + "Text", String::empty)); const String comment (values.getValue (prefix + "Text", String()));
const size_t commentLength = jmin (comment.getNumBytesAsUTF8(), (size_t) 65534); const size_t commentLength = jmin (comment.getNumBytesAsUTF8(), (size_t) 65534);
out.writeShortBigEndian ((short) commentLength + 1); out.writeShortBigEndian ((short) commentLength + 1);

@ -28,7 +28,7 @@ class LAMEEncoderAudioFormat::Writer : public AudioFormatWriter
{ {
public: public:
Writer (OutputStream* destStream, const String& formatName, Writer (OutputStream* destStream, const String& formatName,
const File& lameApp, int vbr, int cbr, const File& appFile, int vbr, int cbr,
double sampleRate, unsigned int numberOfChannels, double sampleRate, unsigned int numberOfChannels,
unsigned int bitsPerSample, const StringPairArray& metadata) unsigned int bitsPerSample, const StringPairArray& metadata)
: AudioFormatWriter (destStream, formatName, sampleRate, : AudioFormatWriter (destStream, formatName, sampleRate,
@ -43,7 +43,7 @@ public:
writer = wavFormat.createWriterFor (out, sampleRate, numChannels, writer = wavFormat.createWriterFor (out, sampleRate, numChannels,
bitsPerSample, metadata, 0); bitsPerSample, metadata, 0);
args.add (lameApp.getFullPathName()); args.add (appFile.getFullPathName());
args.add ("--quiet"); args.add ("--quiet");
@ -72,7 +72,7 @@ public:
void addMetadataArg (const StringPairArray& metadata, const char* key, const char* lameFlag) void addMetadataArg (const StringPairArray& metadata, const char* key, const char* lameFlag)
{ {
const String value (metadata.getValue (key, String::empty)); const String value (metadata.getValue (key, String()));
if (value.isNotEmpty()) if (value.isNotEmpty())
{ {
@ -103,11 +103,11 @@ private:
ScopedPointer<AudioFormatWriter> writer; ScopedPointer<AudioFormatWriter> writer;
StringArray args; StringArray args;
bool runLameChildProcess (const TemporaryFile& tempMP3, const StringArray& args) const bool runLameChildProcess (const TemporaryFile& tempMP3, const StringArray& processArgs) const
{ {
ChildProcess cp; ChildProcess cp;
if (cp.start (args)) if (cp.start (processArgs))
{ {
const String childOutput (cp.readAllProcessOutput()); const String childOutput (cp.readAllProcessOutput());
DBG (childOutput); (void) childOutput; DBG (childOutput); (void) childOutput;

@ -3095,7 +3095,14 @@ private:
const int64 streamSize = stream.stream.getTotalLength(); const int64 streamSize = stream.stream.getTotalLength();
if (streamSize > 0) if (streamSize > 0)
numFrames = (streamSize - streamStartPos) / (stream.frame.frameSize); {
const int bytesPerFrame = stream.frame.frameSize + 4;
if (bytesPerFrame == 417 || bytesPerFrame == 418)
numFrames = roundToInt ((streamSize - streamStartPos) / 417.95918); // more accurate for 128k
else
numFrames = (streamSize - streamStartPos) / bytesPerFrame;
}
} }
return numFrames * 1152; return numFrames * 1152;

@ -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.0", "version": "3.0.1",
"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",

@ -945,9 +945,10 @@ public:
(juce::uint8) inData2 }; (juce::uint8) inData2 };
incomingEvents.addEvent (data, 3, (int) inStartFrame); incomingEvents.addEvent (data, 3, (int) inStartFrame);
#endif
return noErr; return noErr;
#else
return kAudioUnitErr_PropertyNotInUse;
#endif
} }
OSStatus HandleSysEx (const UInt8* inData, UInt32 inLength) override OSStatus HandleSysEx (const UInt8* inData, UInt32 inLength) override
@ -955,8 +956,10 @@ public:
#if JucePlugin_WantsMidiInput #if JucePlugin_WantsMidiInput
const ScopedLock sl (incomingMidiLock); const ScopedLock sl (incomingMidiLock);
incomingEvents.addEvent (inData, (int) inLength, 0); incomingEvents.addEvent (inData, (int) inLength, 0);
#endif
return noErr; return noErr;
#else
return kAudioUnitErr_PropertyNotInUse;
#endif
} }
//============================================================================== //==============================================================================
@ -1369,7 +1372,7 @@ private:
JUCE_AUTORELEASEPOOL JUCE_AUTORELEASEPOOL
{ {
jassert (ed != nullptr); jassert (ed != nullptr);
addAndMakeVisible (&editor); addAndMakeVisible (editor);
setOpaque (true); setOpaque (true);
setVisible (true); setVisible (true);
setBroughtToFrontOnMouseClick (true); setBroughtToFrontOnMouseClick (true);

@ -861,7 +861,7 @@ private:
void GetNameOfLength (char* name, int maxLength, OSType inControllerType) const void GetNameOfLength (char* name, int maxLength, OSType inControllerType) const
{ {
// Pro-tools expects all your parameters to have valid names! // Pro-tools expects all your parameters to have valid names!
jassert (juceFilter->getParameterName (index).isNotEmpty()); jassert (juceFilter->getParameterName (index, maxLength).isNotEmpty());
juceFilter->getParameterName (index, maxLength).copyToUTF8 (name, (size_t) maxLength + 1); juceFilter->getParameterName (index, maxLength).copyToUTF8 (name, (size_t) maxLength + 1);
} }

@ -54,7 +54,7 @@ public:
{ {
setTitleBarButtonsRequired (DocumentWindow::minimiseButton | DocumentWindow::closeButton, false); setTitleBarButtonsRequired (DocumentWindow::minimiseButton | DocumentWindow::closeButton, false);
Component::addAndMakeVisible (&optionsButton); Component::addAndMakeVisible (optionsButton);
optionsButton.addListener (this); optionsButton.addListener (this);
optionsButton.setTriggeredOnMouseDown (true); optionsButton.setTriggeredOnMouseDown (true);

@ -40,13 +40,6 @@
#undef STRICT #undef STRICT
#define STRICT 1 #define STRICT 1
#include <windows.h> #include <windows.h>
#ifdef __MINGW32__
struct MOUSEHOOKSTRUCTEX : public MOUSEHOOKSTRUCT
{
DWORD mouseData;
};
#endif
#elif defined (LINUX) #elif defined (LINUX)
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xutil.h> #include <X11/Xutil.h>
@ -62,12 +55,6 @@
#endif #endif
//============================================================================== //==============================================================================
/* These files come with the Steinberg VST SDK - to get them, you'll need to
visit the Steinberg website and jump through some hoops to sign up as a
VST developer.
Then, you'll need to make sure your include path contains your "vstsdk2.4" directory.
*/
#ifndef _MSC_VER #ifndef _MSC_VER
#define __cdecl #define __cdecl
#endif #endif
@ -80,7 +67,15 @@
#pragma clang diagnostic ignored "-Wdeprecated-writable-strings" #pragma clang diagnostic ignored "-Wdeprecated-writable-strings"
#endif #endif
// VSTSDK V2.4 includes.. /* These files come with the Steinberg VST SDK - to get them, you'll need to
visit the Steinberg website and agree to whatever is currently required to
get them. The best version to get is the VST3 SDK, which also contains
the older VST2.4 files.
Then, you'll need to make sure your include path contains your "VST SDK3"
directory (or whatever you've named it on your machine). The introjucer has
a special box for setting this path.
*/
#include <public.sdk/source/vst2.x/audioeffectx.h> #include <public.sdk/source/vst2.x/audioeffectx.h>
#include <public.sdk/source/vst2.x/aeffeditor.h> #include <public.sdk/source/vst2.x/aeffeditor.h>
#include <public.sdk/source/vst2.x/audioeffectx.cpp> #include <public.sdk/source/vst2.x/audioeffectx.cpp>
@ -181,7 +176,10 @@ namespace
{ {
if (nCode >= 0 && wParam == WM_MOUSEWHEEL) if (nCode >= 0 && wParam == WM_MOUSEWHEEL)
{ {
const MOUSEHOOKSTRUCTEX& hs = *(MOUSEHOOKSTRUCTEX*) lParam; // using a local copy of this struct to support old mingw libraries
struct MOUSEHOOKSTRUCTEX_ : public MOUSEHOOKSTRUCT { DWORD mouseData; };
const MOUSEHOOKSTRUCTEX_& hs = *(MOUSEHOOKSTRUCTEX_*) lParam;
if (Component* const comp = Desktop::getInstance().findComponentAt (Point<int> (hs.pt.x, hs.pt.y))) if (Component* const comp = Desktop::getInstance().findComponentAt (Point<int> (hs.pt.x, hs.pt.y)))
if (comp->getWindowHandle() != 0) if (comp->getWindowHandle() != 0)
@ -835,7 +833,7 @@ public:
if (filter != nullptr) if (filter != nullptr)
{ {
jassert (isPositiveAndBelow (index, filter->getNumParameters())); jassert (isPositiveAndBelow (index, filter->getNumParameters()));
filter->getParameterText (index).copyToUTF8 (text, 24); // length should technically be kVstMaxParamStrLen, which is 8, but hosts will normally allow a bit more. filter->getParameterText (index, 24).copyToUTF8 (text, 24); // length should technically be kVstMaxParamStrLen, which is 8, but hosts will normally allow a bit more.
} }
} }
@ -844,7 +842,7 @@ public:
if (filter != nullptr) if (filter != nullptr)
{ {
jassert (isPositiveAndBelow (index, filter->getNumParameters())); jassert (isPositiveAndBelow (index, filter->getNumParameters()));
filter->getParameterName (index).copyToUTF8 (text, 16); // length should technically be kVstMaxParamStrLen, which is 8, but hosts will normally allow a bit more. filter->getParameterName (index, 16).copyToUTF8 (text, 16); // length should technically be kVstMaxParamStrLen, which is 8, but hosts will normally allow a bit more.
} }
} }

@ -1,7 +1,7 @@
{ {
"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.0", "version": "3.0.1",
"description": "Classes for building VST, RTAS and AU plugins.", "description": "Classes for building VST, RTAS and AU plugins.",
"website": "http://www.juce.com/juce", "website": "http://www.juce.com/juce",
"license": "GPL/Commercial", "license": "GPL/Commercial",

@ -22,7 +22,7 @@
============================================================================== ==============================================================================
*/ */
#if _MSC_VER #if _MSC_VER || JUCE_MINGW
#include <windows.h> #include <windows.h>
#endif #endif
@ -33,7 +33,7 @@
#include "../utility/juce_CheckSettingMacros.h" #include "../utility/juce_CheckSettingMacros.h"
#include "juce_IncludeModuleHeaders.h" #include "juce_IncludeModuleHeaders.h"
#if _MSC_VER #if _MSC_VER || JUCE_MINGW
#if JucePlugin_Build_RTAS #if JucePlugin_Build_RTAS
extern "C" BOOL WINAPI DllMainRTAS (HINSTANCE, DWORD, LPVOID); extern "C" BOOL WINAPI DllMainRTAS (HINSTANCE, DWORD, LPVOID);

@ -58,7 +58,9 @@ namespace juce
namespace AudioUnitFormatHelpers namespace AudioUnitFormatHelpers
{ {
static int insideCallback = 0; #if JUCE_DEBUG
static ThreadLocalValue<int> insideCallback;
#endif
String osTypeToString (OSType type) String osTypeToString (OSType type)
{ {
@ -136,7 +138,7 @@ namespace AudioUnitFormatHelpers
fileOrIdentifier.lastIndexOfChar ('/')) + 1)); fileOrIdentifier.lastIndexOfChar ('/')) + 1));
StringArray tokens; StringArray tokens;
tokens.addTokens (s, ",", String::empty); tokens.addTokens (s, ",", String());
tokens.removeEmptyStrings(); tokens.removeEmptyStrings();
if (tokens.size() == 3) if (tokens.size() == 3)
@ -290,7 +292,9 @@ public:
{ {
using namespace AudioUnitFormatHelpers; using namespace AudioUnitFormatHelpers;
++insideCallback; #if JUCE_DEBUG
++*insideCallback;
#endif
JUCE_AU_LOG ("Opening AU: " + fileOrIdentifier); JUCE_AU_LOG ("Opening AU: " + fileOrIdentifier);
@ -306,14 +310,20 @@ public:
} }
} }
--insideCallback; #if JUCE_DEBUG
--*insideCallback;
#endif
} }
~AudioUnitPluginInstance() ~AudioUnitPluginInstance()
{ {
const ScopedLock sl (lock); const ScopedLock sl (lock);
jassert (AudioUnitFormatHelpers::insideCallback == 0); #if JUCE_DEBUG
// this indicates that some kind of recursive call is getting triggered that's
// deleting this plugin while it's still under construction.
jassert (AudioUnitFormatHelpers::insideCallback.get() == 0);
#endif
if (eventListenerRef != 0) if (eventListenerRef != 0)
{ {
@ -570,7 +580,7 @@ public:
if (isPositiveAndBelow (index, getNumInputChannels())) if (isPositiveAndBelow (index, getNumInputChannels()))
return "Input " + String (index + 1); return "Input " + String (index + 1);
return String::empty; return String();
} }
const String getOutputChannelName (int index) const override const String getOutputChannelName (int index) const override
@ -578,7 +588,7 @@ public:
if (isPositiveAndBelow (index, getNumOutputChannels())) if (isPositiveAndBelow (index, getNumOutputChannels()))
return "Output " + String (index + 1); return "Output " + String (index + 1);
return String::empty; return String();
} }
bool isInputChannelStereoPair (int index) const override { return isPositiveAndBelow (index, getNumInputChannels()); } bool isInputChannelStereoPair (int index) const override { return isPositiveAndBelow (index, getNumInputChannels()); }
@ -652,7 +662,7 @@ public:
if (const ParamInfo* p = parameters[index]) if (const ParamInfo* p = parameters[index])
return p->name; return p->name;
return String::empty; return String();
} }
const String getParameterText (int index) override { return String (getParameter (index)); } const String getParameterText (int index) override { return String (getParameter (index)); }
@ -1293,7 +1303,7 @@ public:
: AudioProcessorEditor (&p), : AudioProcessorEditor (&p),
plugin (p) plugin (p)
{ {
addAndMakeVisible (&wrapper); addAndMakeVisible (wrapper);
setOpaque (true); setOpaque (true);
setVisible (true); setVisible (true);

@ -222,7 +222,7 @@ public:
desc.lastFileModTime = module->file.getLastModificationTime(); desc.lastFileModTime = module->file.getLastModificationTime();
desc.pluginFormatName = "LADSPA"; desc.pluginFormatName = "LADSPA";
desc.category = getCategory(); desc.category = getCategory();
desc.manufacturerName = plugin != nullptr ? String (plugin->Maker) : String::empty; desc.manufacturerName = plugin != nullptr ? String (plugin->Maker) : String();
desc.version = getVersion(); desc.version = getVersion();
desc.numInputChannels = getNumInputChannels(); desc.numInputChannels = getNumInputChannels();
desc.numOutputChannels = getNumOutputChannels(); desc.numOutputChannels = getNumOutputChannels();
@ -338,7 +338,7 @@ public:
if (isPositiveAndBelow (index, getNumInputChannels())) if (isPositiveAndBelow (index, getNumInputChannels()))
return String (plugin->PortNames [inputs [index]]).trim(); return String (plugin->PortNames [inputs [index]]).trim();
return String::empty; return String();
} }
const String getOutputChannelName (const int index) const const String getOutputChannelName (const int index) const
@ -346,7 +346,7 @@ public:
if (isPositiveAndBelow (index, getNumInputChannels())) if (isPositiveAndBelow (index, getNumInputChannels()))
return String (plugin->PortNames [outputs [index]]).trim(); return String (plugin->PortNames [outputs [index]]).trim();
return String::empty; return String();
} }
//============================================================================== //==============================================================================
@ -390,7 +390,7 @@ public:
return String (plugin->PortNames [parameters [index]]).trim(); return String (plugin->PortNames [parameters [index]]).trim();
} }
return String::empty; return String();
} }
const String getParameterText (int index) const String getParameterText (int index)
@ -407,7 +407,7 @@ public:
return String (parameterValues[index].scaled, 4); return String (parameterValues[index].scaled, 4);
} }
return String::empty; return String();
} }
//============================================================================== //==============================================================================
@ -424,7 +424,7 @@ public:
const String getProgramName (int index) const String getProgramName (int index)
{ {
// XXX // XXX
return String::empty; return String();
} }
void changeProgramName (int index, const String& newName) void changeProgramName (int index, const String& newName)

@ -40,11 +40,17 @@
#pragma clang diagnostic ignored "-Wunused-parameter" #pragma clang diagnostic ignored "-Wunused-parameter"
#pragma clang diagnostic ignored "-Wconversion" #pragma clang diagnostic ignored "-Wconversion"
#pragma clang diagnostic ignored "-Woverloaded-virtual" #pragma clang diagnostic ignored "-Woverloaded-virtual"
#pragma clang diagnostic ignored "-Wshadow"
#endif #endif
// Got an include error here? If so, you'll need to install the VST3 SDK somewhere, /* These files come with the Steinberg VST3 SDK - to get them, you'll need to
// and use the introjucer or your IDE to add it to your include path. The introjucer visit the Steinberg website and agree to whatever is currently required to
// has a special box for specifying this path for each export target. get them.
Then, you'll need to make sure your include path contains your "VST SDK3"
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/baseiids.cpp>
#include <base/source/fatomic.cpp> #include <base/source/fatomic.cpp>
#include <base/source/fbuffer.cpp> #include <base/source/fbuffer.cpp>
@ -85,11 +91,12 @@
#undef DBPRT3 #undef DBPRT3
#undef DBPRT4 #undef DBPRT4
#undef DBPRT5 #undef DBPRT5
#undef calloc
#undef free #undef free
#undef malloc #undef malloc
#undef realloc
#undef NEW #undef NEW
#undef NEWVEC #undef NEWVEC
#undef realloc
#undef VERIFY #undef VERIFY
#undef VERIFY_IS #undef VERIFY_IS
#undef VERIFY_NOT #undef VERIFY_NOT
@ -98,6 +105,7 @@
#undef SINGLE_CREATE_FUNC #undef SINGLE_CREATE_FUNC
#undef _META_CLASS #undef _META_CLASS
#undef _META_CLASS_IFACE #undef _META_CLASS_IFACE
#undef _META_CLASS_SINGLE
#undef META_CLASS #undef META_CLASS
#undef META_CLASS_IFACE #undef META_CLASS_IFACE
#undef META_CLASS_SINGLE #undef META_CLASS_SINGLE
@ -306,8 +314,8 @@ static void activateAllBussesOfType (Vst::IComponent* component,
} }
//============================================================================== //==============================================================================
/** Assigns an AudioSampleBuffer's channels to an AudioBusBuffers' */ /** Assigns a complete AudioSampleBuffer's channels to an AudioBusBuffers' */
static void associateBufferTo (Vst::AudioBusBuffers& vstBuffers, const AudioSampleBuffer& buffer) noexcept static void associateWholeBufferTo (Vst::AudioBusBuffers& vstBuffers, const AudioSampleBuffer& buffer) noexcept
{ {
vstBuffers.channelBuffers32 = buffer.getArrayOfChannels(); vstBuffers.channelBuffers32 = buffer.getArrayOfChannels();
vstBuffers.numChannels = buffer.getNumChannels(); vstBuffers.numChannels = buffer.getNumChannels();
@ -566,30 +574,36 @@ public:
for (Steinberg::int32 i = 0; i < eventList.getEventCount(); ++i) for (Steinberg::int32 i = 0; i < eventList.getEventCount(); ++i)
{ {
Event event; Event e;
if (eventList.getEvent (i, event) == kResultOk) if (eventList.getEvent (i, e) == kResultOk)
{ {
switch (event.type) switch (e.type)
{ {
case Event::kNoteOnEvent: case Event::kNoteOnEvent:
result.addEvent (MidiMessage::noteOn (event.noteOn.channel + 1, event.noteOn.pitch, (uint8) (event.noteOn.velocity * 127.0f)), result.addEvent (MidiMessage::noteOn (createSafeChannel (e.noteOn.channel),
event.sampleOffset); createSafeNote (e.noteOn.pitch),
(uint8) denormaliseToMidiValue (e.noteOn.velocity)),
e.sampleOffset);
break; break;
case Event::kNoteOffEvent: case Event::kNoteOffEvent:
result.addEvent (MidiMessage::noteOff (event.noteOff.channel + 1, event.noteOff.pitch, (uint8) (event.noteOff.velocity * 127.0f)), result.addEvent (MidiMessage::noteOff (createSafeChannel (e.noteOff.channel),
event.sampleOffset); createSafeNote (e.noteOff.pitch),
(uint8) denormaliseToMidiValue (e.noteOff.velocity)),
e.sampleOffset);
break; break;
case Event::kPolyPressureEvent: case Event::kPolyPressureEvent:
result.addEvent (MidiMessage::aftertouchChange (event.polyPressure.channel + 1, event.polyPressure.pitch, (int) (event.polyPressure.pressure * 127.0f)), result.addEvent (MidiMessage::aftertouchChange (createSafeChannel (e.polyPressure.channel),
event.sampleOffset); createSafeNote (e.polyPressure.pitch),
denormaliseToMidiValue (e.polyPressure.pressure)),
e.sampleOffset);
break; break;
case Event::kDataEvent: case Event::kDataEvent:
result.addEvent (MidiMessage::createSysExMessage (event.data.bytes, event.data.size), result.addEvent (MidiMessage::createSysExMessage (e.data.bytes, e.data.size),
event.sampleOffset); e.sampleOffset);
break; break;
default: default:
@ -607,42 +621,58 @@ public:
MidiMessage msg; MidiMessage msg;
int midiEventPosition = 0; 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)) while (iterator.getNextEvent (msg, midiEventPosition))
{ {
Event event = { 0 }; if (++numEvents > maxNumEvents)
break;
Event e = { 0 };
if (msg.isNoteOn()) if (msg.isNoteOn())
{ {
event.type = Event::kNoteOnEvent; e.type = Event::kNoteOnEvent;
event.noteOn.channel = (Steinberg::int16) msg.getChannel() - 1; e.noteOn.channel = createSafeChannel (msg.getChannel());
event.noteOn.pitch = (Steinberg::int16) msg.getNoteNumber(); e.noteOn.pitch = createSafeNote (msg.getNoteNumber());
event.noteOn.velocity = msg.getVelocity() / 127.0f; e.noteOn.velocity = normaliseMidiValue (msg.getVelocity());
e.noteOn.length = 0;
e.noteOn.tuning = 0.0f;
e.noteOn.noteId = -1;
} }
else if (msg.isNoteOff()) else if (msg.isNoteOff())
{ {
event.type = Event::kNoteOffEvent; e.type = Event::kNoteOffEvent;
event.noteOff.channel = (Steinberg::int16) msg.getChannel() - 1; e.noteOff.channel = createSafeChannel (msg.getChannel());
event.noteOff.pitch = (Steinberg::int16) msg.getNoteNumber(); e.noteOff.pitch = createSafeNote (msg.getNoteNumber());
event.noteOff.velocity = msg.getVelocity() / 127.0f; e.noteOff.velocity = normaliseMidiValue (msg.getVelocity());
e.noteOff.tuning = 0.0f;
e.noteOff.noteId = -1;
} }
else if (msg.isSysEx()) else if (msg.isSysEx())
{ {
event.type = Event::kDataEvent; e.type = Event::kDataEvent;
event.data.bytes = msg.getSysExData(); e.data.bytes = msg.getSysExData();
event.data.size = msg.getSysExDataSize(); e.data.size = msg.getSysExDataSize();
e.data.type = DataEvent::kMidiSysEx;
} }
else if (msg.isAftertouch()) else if (msg.isAftertouch())
{ {
event.type = Event::kPolyPressureEvent; e.type = Event::kPolyPressureEvent;
event.polyPressure.channel = (Steinberg::int16) msg.getChannel() - 1; e.polyPressure.channel = createSafeChannel (msg.getChannel());
event.polyPressure.pitch = (Steinberg::int16) msg.getNoteNumber(); e.polyPressure.pitch = createSafeNote (msg.getNoteNumber());
event.polyPressure.pressure = msg.getAfterTouchValue() / 127.0f; e.polyPressure.pressure = normaliseMidiValue (msg.getAfterTouchValue());
}
else
{
continue;
} }
event.busIndex = 0; e.busIndex = 0;
event.sampleOffset = midiEventPosition; e.sampleOffset = midiEventPosition;
result.addEvent (event); result.addEvent (e);
} }
} }
@ -650,6 +680,15 @@ private:
Array<Vst::Event, CriticalSection> events; Array<Vst::Event, CriticalSection> events;
Atomic<int32> refCount; 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) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MidiEventList)
}; };
@ -1448,16 +1487,16 @@ private:
} }
//============================================================================== //==============================================================================
bool open (const File& file, const PluginDescription& description) bool open (const File& f, const PluginDescription& description)
{ {
dllHandle = new DLLHandle (file.getFullPathName()); dllHandle = new DLLHandle (f.getFullPathName());
ComSmartPtr<IPluginFactory> pluginFactory (dllHandle->getPluginFactory()); ComSmartPtr<IPluginFactory> pluginFactory (dllHandle->getPluginFactory());
ComSmartPtr<VST3HostContext> host (new VST3HostContext (nullptr)); ComSmartPtr<VST3HostContext> host (new VST3HostContext (nullptr));
MatchingDescriptionFinder finder (host, pluginFactory, description); MatchingDescriptionFinder finder (host, pluginFactory, description);
const Result result (finder.findDescriptionsAndPerform (file)); const Result result (finder.findDescriptionsAndPerform (f));
if (result.getErrorMessage() == MatchingDescriptionFinder::getSuccessString()) if (result.getErrorMessage() == MatchingDescriptionFinder::getSuccessString())
{ {
@ -1506,14 +1545,8 @@ public:
#endif #endif
} }
Steinberg::uint32 PLUGIN_API addRef() override { return 1; } JUCE_DECLARE_VST3_COM_REF_METHODS
Steinberg::uint32 PLUGIN_API release() override { return 1; } JUCE_DECLARE_VST3_COM_QUERY_METHODS
tresult PLUGIN_API queryInterface (const TUID, void** obj) override
{
*obj = nullptr;
return kNotImplemented;
}
void paint (Graphics& g) override void paint (Graphics& g) override
{ {
@ -1602,13 +1635,15 @@ public:
private: private:
//============================================================================== //==============================================================================
Atomic<int> refCount;
ComSmartPtr<IPlugView> view; ComSmartPtr<IPlugView> view;
#if JUCE_WINDOWS #if JUCE_WINDOWS
struct ChildComponent : public Component class ChildComponent : public Component
{ {
public:
ChildComponent() {} ChildComponent() {}
void paint (Graphics& g) { g.fillAll (Colours::cornflowerblue); } void paint (Graphics& g) override { g.fillAll (Colours::cornflowerblue); }
using Component::createNewPeer; using Component::createNewPeer;
@ -1652,7 +1687,7 @@ private:
pluginHandle = (HandleFormat) peer->getNativeHandle(); pluginHandle = (HandleFormat) peer->getNativeHandle();
#elif JUCE_MAC #elif JUCE_MAC
dummyComponent.setBounds (getBounds().withZeroOrigin()); dummyComponent.setBounds (getBounds().withZeroOrigin());
addAndMakeVisible (&dummyComponent); addAndMakeVisible (dummyComponent);
pluginHandle = [[NSView alloc] init]; pluginHandle = [[NSView alloc] init];
dummyComponent.setView (pluginHandle); dummyComponent.setView (pluginHandle);
#endif #endif
@ -1676,9 +1711,9 @@ class VST3PluginInstance : public AudioPluginInstance
public: public:
VST3PluginInstance (const VST3ModuleHandle::Ptr& handle) VST3PluginInstance (const VST3ModuleHandle::Ptr& handle)
: module (handle), : module (handle),
result (1, 1),
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()),
@ -1761,6 +1796,62 @@ 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;
@ -1777,6 +1868,8 @@ 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)
@ -1787,22 +1880,20 @@ public:
warnOnFailure (component->setActive (true)); warnOnFailure (component->setActive (true));
warnOnFailure (processor->setProcessing (true)); warnOnFailure (processor->setProcessing (true));
result.setSize (numOutputs, estimatedSamplesPerBlock, false, true, true);
Array<SpeakerArrangement> inArrangements, outArrangements; Array<SpeakerArrangement> inArrangements, outArrangements;
fillWithCorrespondingSpeakerArrangements (inArrangements, numInputs); fillWithCorrespondingSpeakerArrangements (inArrangements, numInputs);
fillWithCorrespondingSpeakerArrangements (outArrangements, numOutputs); fillWithCorrespondingSpeakerArrangements (outArrangements, numOutputs);
warnOnFailure (processor->setBusArrangements (inArrangements.getRawDataPointer(), warnOnFailure (processor->setBusArrangements (inArrangements.getRawDataPointer(), numInputAudioBusses,
getNumSingleDirectionBussesFor (component, true, true), outArrangements.getRawDataPointer(), numOutputAudioBusses));
outArrangements.getRawDataPointer(),
getNumSingleDirectionBussesFor (component, false, true)));
} }
void releaseResources() override void releaseResources() override
{ {
result.setSize (1, 1, false, true, true); JUCE_TRY
{
resultBuffer.setSize (1, 1, false, true, true);
if (processor != nullptr) if (processor != nullptr)
processor->setProcessing (false); processor->setProcessing (false);
@ -1810,6 +1901,8 @@ public:
if (component != nullptr) if (component != nullptr)
component->setActive (false); component->setActive (false);
} }
JUCE_CATCH_ALL_ASSERT
}
void processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) override void processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) override
{ {
@ -1823,8 +1916,8 @@ public:
ProcessData data; ProcessData data;
data.processMode = isNonRealtime() ? kOffline : kRealtime; data.processMode = isNonRealtime() ? kOffline : kRealtime;
data.symbolicSampleSize = kSample32; data.symbolicSampleSize = kSample32;
data.numInputs = 1; // Number of busses, not channels! data.numInputs = numInputAudioBusses;
data.numOutputs = 1; // Number of busses, not channels! data.numOutputs = numOutputAudioBusses;
data.inputParameterChanges = inputParameterChanges; data.inputParameterChanges = inputParameterChanges;
data.outputParameterChanges = outputParameterChanges; data.outputParameterChanges = outputParameterChanges;
data.numSamples = (Steinberg::int32) numSamples; data.numSamples = (Steinberg::int32) numSamples;
@ -2057,14 +2150,17 @@ private:
mutable ComSmartPtr<IPlugView> view; mutable ComSmartPtr<IPlugView> view;
AudioSampleBuffer result; /** The number of IO busses MUST match that of the plugin,
Vst::AudioBusBuffers inputs, outputs; even if there aren't enough channels to process,
as very poorly specified by the Steinberg SDK
// The number of IO busses MUST match that of the plugin's, as very poorly specified by the Steinberg SDK */
int numInputAudioBusses, numOutputAudioBusses; int numInputAudioBusses, numOutputAudioBusses;
AudioSampleBuffer resultBuffer;
BusMap inputBusMap, outputBusMap;
Array<Vst::AudioBusBuffers> inputBusses, outputBusses;
//============================================================================== //==============================================================================
template<class Type> template <typename Type>
static void appendStateFrom (XmlElement& head, ComSmartPtr<Type>& object, const String& identifier) static void appendStateFrom (XmlElement& head, ComSmartPtr<Type>& object, const String& identifier)
{ {
if (object != nullptr) if (object != nullptr)
@ -2133,10 +2229,10 @@ private:
{ {
jassert (numClasses >= 0); // The plugin must provide at least an IComponent and IEditController! jassert (numClasses >= 0); // The plugin must provide at least an IComponent and IEditController!
for (Steinberg::int32 i = 0; i < numClasses; ++i) for (Steinberg::int32 j = 0; j < numClasses; ++j)
{ {
info = new PClassInfo(); info = new PClassInfo();
factory->getClassInfo (i, info); factory->getClassInfo (j, info);
if (std::strcmp (info->category, kVstAudioEffectClass) != 0) if (std::strcmp (info->category, kVstAudioEffectClass) != 0)
continue; continue;
@ -2153,7 +2249,7 @@ private:
if (pf2.loadFrom (factory)) if (pf2.loadFrom (factory))
{ {
info2 = new PClassInfo2(); info2 = new PClassInfo2();
pf2->getClassInfo2 (i, info2); pf2->getClassInfo2 (j, info2);
} }
else else
{ {
@ -2164,7 +2260,7 @@ private:
{ {
pf3->setHostContext (host->getFUnknown()); pf3->setHostContext (host->getFUnknown());
infoW = new PClassInfoW(); infoW = new PClassInfoW();
pf3->getClassInfoUnicode (i, infoW); pf3->getClassInfoUnicode (j, infoW);
} }
else else
{ {
@ -2251,6 +2347,7 @@ private:
Steinberg::MemoryStream stream; Steinberg::MemoryStream stream;
if (component->getState (&stream) == kResultTrue) if (component->getState (&stream) == kResultTrue)
if (stream.seek (0, Steinberg::IBStream::kIBSeekSet, nullptr) == kResultTrue)
warnOnFailure (editController->setComponentState (&stream)); warnOnFailure (editController->setComponentState (&stream));
} }
@ -2304,6 +2401,7 @@ private:
component->getBusInfo (forAudio ? Vst::kAudio : Vst::kEvent, component->getBusInfo (forAudio ? Vst::kAudio : Vst::kEvent,
forInput ? Vst::kInput : Vst::kOutput, forInput ? Vst::kInput : Vst::kOutput,
(Steinberg::int32) index, busInfo); (Steinberg::int32) index, busInfo);
return busInfo; return busInfo;
} }
@ -2322,23 +2420,15 @@ private:
} }
//============================================================================== //==============================================================================
struct AudioBusBuffersWrapper
{
AudioBusBuffersWrapper() {}
~AudioBusBuffersWrapper() {}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioBusBuffersWrapper)
};
void associateTo (Vst::ProcessData& destination, AudioSampleBuffer& buffer) void associateTo (Vst::ProcessData& destination, AudioSampleBuffer& buffer)
{ {
result.clear(); resultBuffer.clear();
associateBufferTo (inputs, buffer); mapAudioSampleBufferToBusses (inputBusses, buffer, numInputAudioBusses, true);
associateBufferTo (outputs, result); mapAudioSampleBufferToBusses (outputBusses, resultBuffer, numOutputAudioBusses, false);
destination.inputs = &inputs; destination.inputs = inputBusses.getRawDataPointer();
destination.outputs = &outputs; destination.outputs = outputBusses.getRawDataPointer();
} }
void associateTo (Vst::ProcessData& destination, MidiBuffer& midiBuffer) void associateTo (Vst::ProcessData& destination, MidiBuffer& midiBuffer)
@ -2360,22 +2450,22 @@ private:
Vst::ParameterInfo getParameterInfoForIndex (int index) const Vst::ParameterInfo getParameterInfoForIndex (int index) const
{ {
Vst::ParameterInfo info = { 0 }; Vst::ParameterInfo paramInfo = { 0 };
if (processor != nullptr) if (processor != nullptr)
editController->getParameterInfo (index, info); editController->getParameterInfo (index, paramInfo);
return info; return paramInfo;
} }
Vst::ProgramListInfo getProgramListInfo (int index) const Vst::ProgramListInfo getProgramListInfo (int index) const
{ {
Vst::ProgramListInfo info = { 0 }; Vst::ProgramListInfo paramInfo = { 0 };
if (unitInfo != nullptr) if (unitInfo != nullptr)
unitInfo->getProgramListInfo (index, info); unitInfo->getProgramListInfo (index, paramInfo);
return info; return paramInfo;
} }
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (VST3PluginInstance) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (VST3PluginInstance)

@ -22,12 +22,11 @@
============================================================================== ==============================================================================
*/ */
#ifdef __aeffect__ #ifdef __aeffect__ // NB: this must come first, *before* the header-guard.
#ifndef JUCE_VSTMIDIEVENTLIST_H_INCLUDED #ifndef JUCE_VSTMIDIEVENTLIST_H_INCLUDED
#define JUCE_VSTMIDIEVENTLIST_H_INCLUDED #define JUCE_VSTMIDIEVENTLIST_H_INCLUDED
//============================================================================== //==============================================================================
/** Holds a set of VSTMidiEvent objects and makes it easy to add /** Holds a set of VSTMidiEvent objects and makes it easy to add
events to the list. events to the list.
@ -184,6 +183,5 @@ private:
} }
}; };
#endif // JUCE_VSTMIDIEVENTLIST_H_INCLUDED #endif // JUCE_VSTMIDIEVENTLIST_H_INCLUDED
#endif #endif

@ -1831,17 +1831,22 @@ private:
int versionBits[32]; int versionBits[32];
int n = 0; int n = 0;
while (v != 0) for (int vv = v; vv != 0; vv /= 10)
versionBits [n++] = vv % 10;
if (n > 4) // if the number ends up silly, it's probably encoded as hex instead of decimal..
{ {
versionBits [n++] = v % 10; n = 0;
v /= 10;
}
s << 'V'; for (int vv = v; vv != 0; vv >>= 8)
versionBits [n++] = vv & 255;
}
while (n > 1 && versionBits [n - 1] == 0) while (n > 1 && versionBits [n - 1] == 0)
--n; --n;
s << 'V';
while (n > 0) while (n > 0)
{ {
s << versionBits [--n]; s << versionBits [--n];

@ -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.0", "version": "3.0.1",
"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",

@ -201,7 +201,7 @@ void AudioProcessor::updateHostDisplay()
l->audioProcessorChanged (this); l->audioProcessorChanged (this);
} }
String AudioProcessor::getParameterLabel (int) const { return String::empty; } String AudioProcessor::getParameterLabel (int) const { return String(); }
bool AudioProcessor::isParameterAutomatable (int) const { return true; } bool AudioProcessor::isParameterAutomatable (int) const { return true; }
bool AudioProcessor::isMetaParameter (int) const { return false; } bool AudioProcessor::isMetaParameter (int) const { return false; }
@ -266,7 +266,7 @@ void AudioProcessor::copyXmlToBinary (const XmlElement& xml, juce::MemoryBlock&
MemoryOutputStream out (destData, false); MemoryOutputStream out (destData, false);
out.writeInt (magicXmlNumber); out.writeInt (magicXmlNumber);
out.writeInt (0); out.writeInt (0);
xml.writeToStream (out, String::empty, true, false); xml.writeToStream (out, String(), true, false);
out.writeByte (0); out.writeByte (0);
} }

@ -1367,7 +1367,7 @@ const String AudioProcessorGraph::AudioGraphIOProcessor::getName() const
default: break; default: break;
} }
return String::empty; return String();
} }
void AudioProcessorGraph::AudioGraphIOProcessor::fillInPluginDescription (PluginDescription& d) const void AudioProcessorGraph::AudioGraphIOProcessor::fillInPluginDescription (PluginDescription& d) const
@ -1469,7 +1469,7 @@ const String AudioProcessorGraph::AudioGraphIOProcessor::getInputChannelName (in
default: break; default: break;
} }
return String::empty; return String();
} }
const String AudioProcessorGraph::AudioGraphIOProcessor::getOutputChannelName (int channelIndex) const const String AudioProcessorGraph::AudioGraphIOProcessor::getOutputChannelName (int channelIndex) const
@ -1481,7 +1481,7 @@ const String AudioProcessorGraph::AudioGraphIOProcessor::getOutputChannelName (i
default: break; default: break;
} }
return String::empty; return String();
} }
bool AudioProcessorGraph::AudioGraphIOProcessor::isInputChannelStereoPair (int /*index*/) const bool AudioProcessorGraph::AudioGraphIOProcessor::isInputChannelStereoPair (int /*index*/) const
@ -1501,17 +1501,17 @@ bool AudioProcessorGraph::AudioGraphIOProcessor::hasEditor() const
AudioProcessorEditor* AudioProcessorGraph::AudioGraphIOProcessor::createEditor() { return nullptr; } AudioProcessorEditor* AudioProcessorGraph::AudioGraphIOProcessor::createEditor() { return nullptr; }
int AudioProcessorGraph::AudioGraphIOProcessor::getNumParameters() { return 0; } int AudioProcessorGraph::AudioGraphIOProcessor::getNumParameters() { return 0; }
const String AudioProcessorGraph::AudioGraphIOProcessor::getParameterName (int) { return String::empty; } const String AudioProcessorGraph::AudioGraphIOProcessor::getParameterName (int) { return String(); }
float AudioProcessorGraph::AudioGraphIOProcessor::getParameter (int) { return 0.0f; } float AudioProcessorGraph::AudioGraphIOProcessor::getParameter (int) { return 0.0f; }
const String AudioProcessorGraph::AudioGraphIOProcessor::getParameterText (int) { return String::empty; } const String AudioProcessorGraph::AudioGraphIOProcessor::getParameterText (int) { return String(); }
void AudioProcessorGraph::AudioGraphIOProcessor::setParameter (int, float) { } void AudioProcessorGraph::AudioGraphIOProcessor::setParameter (int, float) { }
int AudioProcessorGraph::AudioGraphIOProcessor::getNumPrograms() { return 0; } int AudioProcessorGraph::AudioGraphIOProcessor::getNumPrograms() { return 0; }
int AudioProcessorGraph::AudioGraphIOProcessor::getCurrentProgram() { return 0; } int AudioProcessorGraph::AudioGraphIOProcessor::getCurrentProgram() { return 0; }
void AudioProcessorGraph::AudioGraphIOProcessor::setCurrentProgram (int) { } void AudioProcessorGraph::AudioGraphIOProcessor::setCurrentProgram (int) { }
const String AudioProcessorGraph::AudioGraphIOProcessor::getProgramName (int) { return String::empty; } const String AudioProcessorGraph::AudioGraphIOProcessor::getProgramName (int) { return String(); }
void AudioProcessorGraph::AudioGraphIOProcessor::changeProgramName (int, const String&) {} void AudioProcessorGraph::AudioGraphIOProcessor::changeProgramName (int, const String&) {}
void AudioProcessorGraph::AudioGraphIOProcessor::getStateInformation (juce::MemoryBlock&) {} void AudioProcessorGraph::AudioGraphIOProcessor::getStateInformation (juce::MemoryBlock&) {}

@ -372,15 +372,15 @@ public:
AudioProcessorEditor* createEditor() { return nullptr; } AudioProcessorEditor* createEditor() { return nullptr; }
int getNumParameters() { return 0; } int getNumParameters() { return 0; }
const String getParameterName (int) { return String::empty; } const String getParameterName (int) { return String(); }
float getParameter (int) { return 0; } float getParameter (int) { return 0; }
const String getParameterText (int) { return String::empty; } const String getParameterText (int) { return String(); }
void setParameter (int, float) { } void setParameter (int, float) { }
int getNumPrograms() { return 0; } int getNumPrograms() { return 0; }
int getCurrentProgram() { return 0; } int getCurrentProgram() { return 0; }
void setCurrentProgram (int) { } void setCurrentProgram (int) { }
const String getProgramName (int) { return String::empty; } const String getProgramName (int) { return String(); }
void changeProgramName (int, const String&) { } void changeProgramName (int, const String&) { }
void getStateInformation (juce::MemoryBlock&); void getStateInformation (juce::MemoryBlock&);

@ -35,7 +35,7 @@ public:
slider (p, index_) slider (p, index_)
{ {
startTimer (100); startTimer (100);
addAndMakeVisible (&slider); addAndMakeVisible (slider);
owner.addListener (this); owner.addListener (this);
} }
@ -123,7 +123,7 @@ GenericAudioProcessorEditor::GenericAudioProcessorEditor (AudioProcessor* const
jassert (p != nullptr); jassert (p != nullptr);
setOpaque (true); setOpaque (true);
addAndMakeVisible (&panel); addAndMakeVisible (panel);
Array <PropertyComponent*> params; Array <PropertyComponent*> params;

@ -241,7 +241,8 @@ void KnownPluginList::clearBlacklistedFiles()
//============================================================================== //==============================================================================
struct PluginSorter struct PluginSorter
{ {
PluginSorter (KnownPluginList::SortMethod sortMethod) noexcept : method (sortMethod) {} PluginSorter (KnownPluginList::SortMethod sortMethod, bool forwards) noexcept
: method (sortMethod), direction (forwards ? 1 : -1) {}
int compareElements (const PluginDescription* const first, int compareElements (const PluginDescription* const first,
const PluginDescription* const second) const const PluginDescription* const second) const
@ -252,6 +253,7 @@ struct PluginSorter
{ {
case KnownPluginList::sortByCategory: diff = first->category.compareLexicographically (second->category); break; case KnownPluginList::sortByCategory: diff = first->category.compareLexicographically (second->category); break;
case KnownPluginList::sortByManufacturer: diff = first->manufacturerName.compareLexicographically (second->manufacturerName); break; case KnownPluginList::sortByManufacturer: diff = first->manufacturerName.compareLexicographically (second->manufacturerName); break;
case KnownPluginList::sortByFormat: diff = first->pluginFormatName.compare (second->pluginFormatName); break;
case KnownPluginList::sortByFileSystemLocation: diff = lastPathPart (first->fileOrIdentifier).compare (lastPathPart (second->fileOrIdentifier)); break; case KnownPluginList::sortByFileSystemLocation: diff = lastPathPart (first->fileOrIdentifier).compare (lastPathPart (second->fileOrIdentifier)); break;
default: break; default: break;
} }
@ -259,7 +261,7 @@ struct PluginSorter
if (diff == 0) if (diff == 0)
diff = first->name.compareLexicographically (second->name); diff = first->name.compareLexicographically (second->name);
return diff; return diff * direction;
} }
private: private:
@ -268,14 +270,17 @@ private:
return path.replaceCharacter ('\\', '/').upToLastOccurrenceOf ("/", false, false); return path.replaceCharacter ('\\', '/').upToLastOccurrenceOf ("/", false, false);
} }
KnownPluginList::SortMethod method; const KnownPluginList::SortMethod method;
const int direction;
JUCE_DECLARE_NON_COPYABLE (PluginSorter)
}; };
void KnownPluginList::sort (const SortMethod method) void KnownPluginList::sort (const SortMethod method, bool forwards)
{ {
if (method != defaultOrder) if (method != defaultOrder)
{ {
PluginSorter sorter (method); PluginSorter sorter (method, forwards);
types.sort (sorter, true); types.sort (sorter, true);
sendChangeMessage(); sendChangeMessage();
@ -477,7 +482,7 @@ KnownPluginList::PluginTree* KnownPluginList::createTree (const SortMethod sortM
Array <PluginDescription*> sorted; Array <PluginDescription*> sorted;
{ {
PluginSorter sorter (sortMethod); PluginSorter sorter (sortMethod, true);
for (int i = 0; i < types.size(); ++i) for (int i = 0; i < types.size(); ++i)
sorted.addSorted (sorter, types.getUnchecked(i)); sorted.addSorted (sorter, types.getUnchecked(i));
@ -485,7 +490,7 @@ KnownPluginList::PluginTree* KnownPluginList::createTree (const SortMethod sortM
PluginTree* tree = new PluginTree(); PluginTree* tree = new PluginTree();
if (sortMethod == sortByCategory || sortMethod == sortByManufacturer) if (sortMethod == sortByCategory || sortMethod == sortByManufacturer || sortMethod == sortByFormat)
{ {
PluginTreeUtils::buildTreeByCategory (*tree, sorted, sortMethod); PluginTreeUtils::buildTreeByCategory (*tree, sorted, sortMethod);
} }

@ -132,6 +132,7 @@ public:
sortAlphabetically, sortAlphabetically,
sortByCategory, sortByCategory,
sortByManufacturer, sortByManufacturer,
sortByFormat,
sortByFileSystemLocation sortByFileSystemLocation
}; };
@ -143,7 +144,7 @@ public:
Use getIndexChosenByMenu() to find out the type that was chosen. Use getIndexChosenByMenu() to find out the type that was chosen.
*/ */
void addToMenu (PopupMenu& menu, const SortMethod sortMethod) const; void addToMenu (PopupMenu& menu, SortMethod sortMethod) const;
/** Converts a menu item index that has been chosen into its index in this list. /** Converts a menu item index that has been chosen into its index in this list.
Returns -1 if it's not an ID that was used. Returns -1 if it's not an ID that was used.
@ -153,7 +154,7 @@ public:
//============================================================================== //==============================================================================
/** Sorts the list. */ /** Sorts the list. */
void sort (const SortMethod method); void sort (SortMethod method, bool forwards);
//============================================================================== //==============================================================================
/** Creates some XML that can be used to store the state of this list. */ /** Creates some XML that can be used to store the state of this list. */

@ -120,7 +120,7 @@ bool PluginDirectoryScanner::skipNextFile()
void PluginDirectoryScanner::setDeadMansPedalFile (const StringArray& newContents) void PluginDirectoryScanner::setDeadMansPedalFile (const StringArray& newContents)
{ {
if (deadMansPedalFile != File::nonexistent) if (deadMansPedalFile.getFullPathName().isNotEmpty())
deadMansPedalFile.replaceWithText (newContents.joinIntoString ("\n"), true, true); deadMansPedalFile.replaceWithText (newContents.joinIntoString ("\n"), true, true);
} }

@ -22,10 +22,116 @@
============================================================================== ==============================================================================
*/ */
PluginListComponent::PluginListComponent (AudioPluginFormatManager& manager, class PluginListComponent::TableModel : public TableListBoxModel
KnownPluginList& listToEdit, {
const File& deadMansPedal, public:
PropertiesFile* const props) TableModel (PluginListComponent& c, KnownPluginList& l) : owner (c), list (l) {}
int getNumRows() override
{
return list.getNumTypes() + list.getBlacklistedFiles().size();
}
void paintRowBackground (Graphics& g, int /*rowNumber*/, int /*width*/, int /*height*/, bool rowIsSelected) override
{
if (rowIsSelected)
g.fillAll (owner.findColour (TextEditor::highlightColourId));
}
enum
{
nameCol = 1,
typeCol = 2,
categoryCol = 3,
manufacturerCol = 4,
descCol = 5
};
void paintCell (Graphics& g, int row, int columnId, int width, int height, bool /*rowIsSelected*/) override
{
String text;
bool isBlacklisted = row >= list.getNumTypes();
if (isBlacklisted)
{
if (columnId == nameCol)
text = list.getBlacklistedFiles() [row - list.getNumTypes()];
else if (columnId == descCol)
text = TRANS("Deactivated after failing to initialise correctly");
}
else if (const PluginDescription* const desc = list.getType (row))
{
switch (columnId)
{
case nameCol: text = desc->name; break;
case typeCol: text = desc->pluginFormatName; break;
case categoryCol: text = desc->category.isNotEmpty() ? desc->category : "-"; break;
case manufacturerCol: text = desc->manufacturerName; break;
case descCol: text = getPluginDescription (*desc); break;
default: jassertfalse; break;
}
}
if (text.isNotEmpty())
{
g.setColour (isBlacklisted ? Colours::red
: columnId == nameCol ? Colours::black
: Colours::grey);
g.setFont (Font (height * 0.7f, Font::bold));
g.drawFittedText (text, 4, 0, width - 6, height, Justification::centredLeft, 1, 0.9f);
}
}
void deleteKeyPressed (int lastRowSelected) override
{
removePluginItem (list, lastRowSelected);
}
void sortOrderChanged (int newSortColumnId, bool isForwards) override
{
switch (newSortColumnId)
{
case nameCol: list.sort (KnownPluginList::sortAlphabetically, isForwards); break;
case typeCol: list.sort (KnownPluginList::sortByFormat, isForwards); break;
case categoryCol: list.sort (KnownPluginList::sortByCategory, isForwards); break;
case manufacturerCol: list.sort (KnownPluginList::sortByManufacturer, isForwards); break;
case descCol: break;
default: jassertfalse; break;
}
}
static void removePluginItem (KnownPluginList& list, int index)
{
if (index < list.getNumTypes())
list.removeType (index);
else
list.removeFromBlacklist (list.getBlacklistedFiles() [index - list.getNumTypes()]);
}
static String getPluginDescription (const PluginDescription& desc)
{
StringArray items;
if (desc.descriptiveName != desc.name)
items.add (desc.descriptiveName);
items.add (desc.version);
items.removeEmptyStrings();
return items.joinIntoString (" - ");
}
PluginListComponent& owner;
KnownPluginList& list;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TableModel)
};
//==============================================================================
PluginListComponent::PluginListComponent (AudioPluginFormatManager& manager, KnownPluginList& listToEdit,
const File& deadMansPedal, PropertiesFile* const props)
: formatManager (manager), : formatManager (manager),
list (listToEdit), list (listToEdit),
deadMansPedalFile (deadMansPedal), deadMansPedalFile (deadMansPedal),
@ -33,10 +139,22 @@ PluginListComponent::PluginListComponent (AudioPluginFormatManager& manager,
propertiesToUse (props), propertiesToUse (props),
numThreads (0) numThreads (0)
{ {
listBox.setModel (this); tableModel = new TableModel (*this, listToEdit);
addAndMakeVisible (&listBox);
TableHeaderComponent& header = table.getHeader();
header.addColumn (TRANS("Name"), TableModel::nameCol, 200, 100, 700, TableHeaderComponent::defaultFlags | TableHeaderComponent::sortedForwards);
header.addColumn (TRANS("Format"), TableModel::typeCol, 80, 80, 80, TableHeaderComponent::notResizable);
header.addColumn (TRANS("Category"), TableModel::categoryCol, 100, 100, 200);
header.addColumn (TRANS("Manufacturer"), TableModel::manufacturerCol, 200, 100, 300);
header.addColumn (TRANS("Description"), TableModel::descCol, 300, 100, 500, TableHeaderComponent::notSortable);
addAndMakeVisible (&optionsButton); table.setHeaderHeight (22);
table.setRowHeight (20);
table.setModel (tableModel);
addAndMakeVisible (table);
addAndMakeVisible (optionsButton);
optionsButton.addListener (this); optionsButton.addListener (this);
optionsButton.setTriggeredOnMouseDown (true); optionsButton.setTriggeredOnMouseDown (true);
@ -66,9 +184,13 @@ void PluginListComponent::setNumberOfThreadsForScanning (int num)
void PluginListComponent::resized() void PluginListComponent::resized()
{ {
listBox.setBounds (0, 0, getWidth(), getHeight() - 30); Rectangle<int> r (getLocalBounds().reduced (2));
optionsButton.setBounds (r.removeFromBottom (24));
optionsButton.changeWidthToFitText (24); optionsButton.changeWidthToFitText (24);
optionsButton.setTopLeftPosition (0, getHeight() - 28);
r.removeFromBottom (3);
table.setBounds (r);
} }
void PluginListComponent::changeListenerCallback (ChangeBroadcaster*) void PluginListComponent::changeListenerCallback (ChangeBroadcaster*)
@ -78,89 +200,22 @@ void PluginListComponent::changeListenerCallback (ChangeBroadcaster*)
void PluginListComponent::updateList() void PluginListComponent::updateList()
{ {
listBox.updateContent(); table.updateContent();
listBox.repaint(); table.repaint();
}
int PluginListComponent::getNumRows()
{
return list.getNumTypes() + list.getBlacklistedFiles().size();
}
void PluginListComponent::paintListBoxItem (int row, Graphics& g, int width, int height, bool rowIsSelected)
{
if (rowIsSelected)
g.fillAll (findColour (TextEditor::highlightColourId));
String name, desc;
bool isBlacklisted = false;
if (row >= list.getNumTypes())
{
isBlacklisted = true;
name = list.getBlacklistedFiles() [row - list.getNumTypes()];
desc = TRANS("Deactivated after failing to initialise correctly");
}
else if (const PluginDescription* const pd = list.getType (row))
{
name = pd->name;
desc << pd->pluginFormatName
<< (pd->isInstrument ? " instrument" : " effect")
<< " - " << pd->numInputChannels << (pd->numInputChannels == 1 ? " in" : " ins")
<< " / " << pd->numOutputChannels << (pd->numOutputChannels == 1 ? " out" : " outs");
if (pd->manufacturerName.isNotEmpty()) desc << " - " << pd->manufacturerName;
if (pd->version.isNotEmpty()) desc << " - " << pd->version;
if (pd->category.isNotEmpty()) desc << " - category: '" << pd->category << '\'';
}
if (name.isNotEmpty())
{
GlyphArrangement ga;
ga.addCurtailedLineOfText (Font (height * 0.7f, Font::bold),
name, 8.0f, height * 0.8f, width - 10.0f, true);
g.setColour (isBlacklisted ? Colours::red : Colours::black);
ga.draw (g);
const Rectangle<float> bb (ga.getBoundingBox (0, -1, false));
ga.clear();
ga.addCurtailedLineOfText (Font (height * 0.6f), desc,
jmax (bb.getRight() + 10.0f, width / 3.0f), height * 0.8f,
width - bb.getRight() - 12.0f, true);
g.setColour (isBlacklisted ? Colours::red : Colours::grey);
ga.draw (g);
}
}
static void removePluginItem (KnownPluginList& list, int index)
{
if (index < list.getNumTypes())
list.removeType (index);
else
list.removeFromBlacklist (list.getBlacklistedFiles() [index - list.getNumTypes()]);
}
void PluginListComponent::deleteKeyPressed (int lastRowSelected)
{
removePluginItem (list, lastRowSelected);
} }
void PluginListComponent::removeSelected() void PluginListComponent::removeSelected()
{ {
const SparseSet <int> selected (listBox.getSelectedRows()); const SparseSet<int> selected (table.getSelectedRows());
for (int i = list.getNumTypes(); --i >= 0;) for (int i = list.getNumTypes(); --i >= 0;)
if (selected.contains (i)) if (selected.contains (i))
removePluginItem (list, i); TableModel::removePluginItem (list, i);
} }
bool PluginListComponent::canShowSelectedFolder() const bool PluginListComponent::canShowSelectedFolder() const
{ {
if (const PluginDescription* const desc = list.getType (listBox.getSelectedRow())) if (const PluginDescription* const desc = list.getType (table.getSelectedRow()))
return File::createFileWithoutCheckingPath (desc->fileOrIdentifier).exists(); return File::createFileWithoutCheckingPath (desc->fileOrIdentifier).exists();
return false; return false;
@ -169,7 +224,7 @@ bool PluginListComponent::canShowSelectedFolder() const
void PluginListComponent::showSelectedFolder() void PluginListComponent::showSelectedFolder()
{ {
if (canShowSelectedFolder()) if (canShowSelectedFolder())
if (const PluginDescription* const desc = list.getType (listBox.getSelectedRow())) if (const PluginDescription* const desc = list.getType (table.getSelectedRow()))
File (desc->fileOrIdentifier).getParentDirectory().startAsProcess(); File (desc->fileOrIdentifier).getParentDirectory().startAsProcess();
} }
@ -192,12 +247,9 @@ void PluginListComponent::optionsMenuCallback (int result)
{ {
case 0: break; case 0: break;
case 1: list.clear(); break; case 1: list.clear(); break;
case 2: list.sort (KnownPluginList::sortAlphabetically); break; case 2: removeSelected(); break;
case 3: list.sort (KnownPluginList::sortByCategory); break; case 3: showSelectedFolder(); break;
case 4: list.sort (KnownPluginList::sortByManufacturer); break; case 4: removeMissingPlugins(); break;
case 5: removeSelected(); break;
case 6: showSelectedFolder(); break;
case 7: removeMissingPlugins(); break;
default: default:
if (AudioPluginFormat* format = formatManager.getFormat (result - 10)) if (AudioPluginFormat* format = formatManager.getFormat (result - 10))
@ -213,13 +265,9 @@ void PluginListComponent::buttonClicked (Button* button)
{ {
PopupMenu menu; PopupMenu menu;
menu.addItem (1, TRANS("Clear list")); menu.addItem (1, TRANS("Clear list"));
menu.addItem (5, TRANS("Remove selected plug-in from list"), listBox.getNumSelectedRows() > 0); menu.addItem (2, TRANS("Remove selected plug-in from list"), table.getNumSelectedRows() > 0);
menu.addItem (6, TRANS("Show folder containing selected plug-in"), canShowSelectedFolder()); menu.addItem (3, TRANS("Show folder containing selected plug-in"), canShowSelectedFolder());
menu.addItem (7, TRANS("Remove any plug-ins whose files no longer exist")); menu.addItem (4, TRANS("Remove any plug-ins whose files no longer exist"));
menu.addSeparator();
menu.addItem (2, TRANS("Sort alphabetically"));
menu.addItem (3, TRANS("Sort by category"));
menu.addItem (4, TRANS("Sort by manufacturer"));
menu.addSeparator(); menu.addSeparator();
for (int i = 0; i < formatManager.getNumFormats(); ++i) for (int i = 0; i < formatManager.getNumFormats(); ++i)
@ -262,10 +310,7 @@ void PluginListComponent::setLastSearchPath (PropertiesFile& properties, AudioPl
class PluginListComponent::Scanner : private Timer class PluginListComponent::Scanner : private Timer
{ {
public: public:
Scanner (PluginListComponent& plc, Scanner (PluginListComponent& plc, AudioPluginFormat& format, PropertiesFile* properties, int threads)
AudioPluginFormat& format,
PropertiesFile* properties,
int threads)
: owner (plc), formatToScan (format), propertiesToUse (properties), : owner (plc), formatToScan (format), propertiesToUse (properties),
pathChooserWindow (TRANS("Select folders to scan..."), String::empty, AlertWindow::NoIcon), pathChooserWindow (TRANS("Select folders to scan..."), String::empty, AlertWindow::NoIcon),
progressWindow (TRANS("Scanning for plug-ins..."), progressWindow (TRANS("Scanning for plug-ins..."),

@ -33,7 +33,6 @@
*/ */
class JUCE_API PluginListComponent : public Component, class JUCE_API PluginListComponent : public Component,
public FileDragAndDropTarget, public FileDragAndDropTarget,
private ListBoxModel,
private ChangeListener, private ChangeListener,
private ButtonListener // (can't use Button::Listener due to idiotic VC2005 bug) private ButtonListener // (can't use Button::Listener due to idiotic VC2005 bug)
{ {
@ -53,7 +52,7 @@ public:
/** Destructor. */ /** Destructor. */
~PluginListComponent(); ~PluginListComponent();
/** Changes the text in the panel's button. */ /** Changes the text in the panel's options button. */
void setOptionsButtonText (const String& newText); void setOptionsButtonText (const String& newText);
/** Sets how many threads to simultaneously scan for plugins. /** Sets how many threads to simultaneously scan for plugins.
@ -62,42 +61,32 @@ public:
void setNumberOfThreadsForScanning (int numThreads); void setNumberOfThreadsForScanning (int numThreads);
/** Returns the last search path stored in a given properties file for the specified format. */ /** Returns the last search path stored in a given properties file for the specified format. */
static FileSearchPath getLastSearchPath (PropertiesFile& properties, AudioPluginFormat& format); static FileSearchPath getLastSearchPath (PropertiesFile&, AudioPluginFormat&);
/** Stores a search path in a properties file for the given format. */ /** Stores a search path in a properties file for the given format. */
static void setLastSearchPath (PropertiesFile& properties, AudioPluginFormat& format, static void setLastSearchPath (PropertiesFile&, AudioPluginFormat&, const FileSearchPath&);
const FileSearchPath& newPath);
/** Triggers an asynchronous scan for the given format. */ /** Triggers an asynchronous scan for the given format. */
void scanFor (AudioPluginFormat& format); void scanFor (AudioPluginFormat&);
/** Returns true if there's currently a scan in progress. */ /** Returns true if there's currently a scan in progress. */
bool isScanning() const noexcept; bool isScanning() const noexcept;
//==============================================================================
/** @internal */
void resized() override;
/** @internal */
bool isInterestedInFileDrag (const StringArray&) override;
/** @internal */
void filesDropped (const StringArray&, int, int) override;
/** @internal */
int getNumRows() override;
/** @internal */
void paintListBoxItem (int row, Graphics&, int width, int height, bool rowIsSelected) override;
/** @internal */
void deleteKeyPressed (int lastRowSelected) override;
private: private:
//============================================================================== //==============================================================================
AudioPluginFormatManager& formatManager; AudioPluginFormatManager& formatManager;
KnownPluginList& list; KnownPluginList& list;
File deadMansPedalFile; File deadMansPedalFile;
ListBox listBox; TableListBox table;
TextButton optionsButton; TextButton optionsButton;
PropertiesFile* propertiesToUse; PropertiesFile* propertiesToUse;
int numThreads; int numThreads;
class TableModel;
friend class TableModel;
friend struct ContainerDeletePolicy<TableModel>;
ScopedPointer<TableModel> tableModel;
class Scanner; class Scanner;
friend class Scanner; friend class Scanner;
friend struct ContainerDeletePolicy<Scanner>; friend struct ContainerDeletePolicy<Scanner>;
@ -107,11 +96,14 @@ private:
static void optionsMenuStaticCallback (int, PluginListComponent*); static void optionsMenuStaticCallback (int, PluginListComponent*);
void optionsMenuCallback (int); void optionsMenuCallback (int);
void updateList(); void updateList();
void removeSelected();
void showSelectedFolder(); void showSelectedFolder();
bool canShowSelectedFolder() const; bool canShowSelectedFolder() const;
void removeSelected();
void removeMissingPlugins(); void removeMissingPlugins();
void resized() override;
bool isInterestedInFileDrag (const StringArray&) override;
void filesDropped (const StringArray&, int, int) override;
void buttonClicked (Button*) override; void buttonClicked (Button*) override;
void changeListenerCallback (ChangeBroadcaster*) override; void changeListenerCallback (ChangeBroadcaster*) override;

@ -410,7 +410,7 @@ public:
addAndMakeVisible (outputChanList addAndMakeVisible (outputChanList
= new ChannelSelectorListBox (setup, ChannelSelectorListBox::audioOutputType, = new ChannelSelectorListBox (setup, ChannelSelectorListBox::audioOutputType,
TRANS ("(no audio output channels found)"))); TRANS ("(no audio output channels found)")));
outputChanLabel = new Label (String::empty, TRANS ("active output channels:")); outputChanLabel = new Label (String::empty, TRANS("Active output channels:"));
outputChanLabel->attachToComponent (outputChanList, true); outputChanLabel->attachToComponent (outputChanList, true);
} }
@ -430,7 +430,7 @@ public:
addAndMakeVisible (inputChanList addAndMakeVisible (inputChanList
= new ChannelSelectorListBox (setup, ChannelSelectorListBox::audioInputType, = new ChannelSelectorListBox (setup, ChannelSelectorListBox::audioInputType,
TRANS("(no audio input channels found)"))); TRANS("(no audio input channels found)")));
inputChanLabel = new Label (String::empty, TRANS ("active input channels:")); inputChanLabel = new Label (String::empty, TRANS("Active input channels:"));
inputChanLabel->attachToComponent (inputChanList, true); inputChanLabel->attachToComponent (inputChanList, true);
} }
@ -525,8 +525,8 @@ private:
if (currentDevice != nullptr && currentDevice->hasControlPanel()) if (currentDevice != nullptr && currentDevice->hasControlPanel())
{ {
addAndMakeVisible (showUIButton = new TextButton (TRANS ("show this device's control panel"), addAndMakeVisible (showUIButton = new TextButton (TRANS ("Show this device's control panel"),
TRANS ("opens the device's own control panel"))); TRANS ("Opens the device's own control panel")));
showUIButton->addListener (this); showUIButton->addListener (this);
} }
@ -544,8 +544,8 @@ private:
addAndMakeVisible (outputDeviceDropDown); addAndMakeVisible (outputDeviceDropDown);
outputDeviceLabel = new Label (String::empty, outputDeviceLabel = new Label (String::empty,
type.hasSeparateInputsAndOutputs() ? TRANS ("output:") type.hasSeparateInputsAndOutputs() ? TRANS("Output:")
: TRANS ("device:")); : TRANS("Device:"));
outputDeviceLabel->attachToComponent (outputDeviceDropDown, true); outputDeviceLabel->attachToComponent (outputDeviceDropDown, true);
if (setup.maxNumOutputChannels > 0) if (setup.maxNumOutputChannels > 0)
@ -571,7 +571,7 @@ private:
inputDeviceDropDown->addListener (this); inputDeviceDropDown->addListener (this);
addAndMakeVisible (inputDeviceDropDown); addAndMakeVisible (inputDeviceDropDown);
inputDeviceLabel = new Label (String::empty, TRANS ("input:")); inputDeviceLabel = new Label (String::empty, TRANS("Input:"));
inputDeviceLabel->attachToComponent (inputDeviceDropDown, true); inputDeviceLabel->attachToComponent (inputDeviceDropDown, true);
addAndMakeVisible (inputLevelMeter addAndMakeVisible (inputLevelMeter
@ -590,7 +590,7 @@ private:
{ {
addAndMakeVisible (sampleRateDropDown = new ComboBox (String::empty)); addAndMakeVisible (sampleRateDropDown = new ComboBox (String::empty));
sampleRateLabel = new Label (String::empty, TRANS ("sample rate:")); sampleRateLabel = new Label (String::empty, TRANS("Sample rate:"));
sampleRateLabel->attachToComponent (sampleRateDropDown, true); sampleRateLabel->attachToComponent (sampleRateDropDown, true);
} }
else else
@ -599,11 +599,11 @@ private:
sampleRateDropDown->removeListener (this); sampleRateDropDown->removeListener (this);
} }
const int numRates = currentDevice->getNumSampleRates(); const Array<double> rates (currentDevice->getAvailableSampleRates());
for (int i = 0; i < numRates; ++i) for (int i = 0; i < rates.size(); ++i)
{ {
const int rate = roundToInt (currentDevice->getSampleRate (i)); const int rate = roundToInt (rates[i]);
sampleRateDropDown->addItem (String (rate) + " Hz", rate); sampleRateDropDown->addItem (String (rate) + " Hz", rate);
} }
@ -617,7 +617,7 @@ private:
{ {
addAndMakeVisible (bufferSizeDropDown = new ComboBox (String::empty)); addAndMakeVisible (bufferSizeDropDown = new ComboBox (String::empty));
bufferSizeLabel = new Label (String::empty, TRANS ("audio buffer size:")); bufferSizeLabel = new Label (String::empty, TRANS("Audio buffer size:"));
bufferSizeLabel->attachToComponent (bufferSizeDropDown, true); bufferSizeLabel->attachToComponent (bufferSizeDropDown, true);
} }
else else
@ -626,19 +626,16 @@ private:
bufferSizeDropDown->removeListener (this); bufferSizeDropDown->removeListener (this);
} }
const int numBufferSizes = currentDevice->getNumBufferSizesAvailable(); const Array<int> bufferSizes (currentDevice->getAvailableBufferSizes());
double currentRate = currentDevice->getCurrentSampleRate(); double currentRate = currentDevice->getCurrentSampleRate();
if (currentRate == 0) if (currentRate == 0)
currentRate = 48000.0; currentRate = 48000.0;
for (int i = 0; i < numBufferSizes; ++i) for (int i = 0; i < bufferSizes.size(); ++i)
{ {
const int bs = currentDevice->getBufferSizeSamples (i); const int bs = bufferSizes[i];
bufferSizeDropDown->addItem (String (bs) bufferSizeDropDown->addItem (String (bs) + " samples (" + String (bs * 1000.0 / currentRate, 1) + " ms)", bs);
+ " samples ("
+ String (bs * 1000.0 / currentRate, 1)
+ " ms)",
bs);
} }
bufferSizeDropDown->setSelectedId (currentDevice->getCurrentBufferSizeSamples(), dontSendNotification); bufferSizeDropDown->setSelectedId (currentDevice->getCurrentBufferSizeSamples(), dontSendNotification);

@ -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.0", "version": "3.0.1",
"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",

@ -505,10 +505,7 @@ public:
jassert (numElementsToAdd <= 0 || data.elements != nullptr); jassert (numElementsToAdd <= 0 || data.elements != nullptr);
while (--numElementsToAdd >= 0) while (--numElementsToAdd >= 0)
{ data.elements [numUsed++] = createCopyIfNotNull (arrayToAddFrom.getUnchecked (startIndex++));
data.elements [numUsed] = new ObjectClass (*arrayToAddFrom.getUnchecked (startIndex++));
++numUsed;
}
} }
/** Inserts a new object into the array assuming that the array is sorted. /** Inserts a new object into the array assuming that the array is sorted.

@ -155,8 +155,8 @@ void PropertySet::removeValue (StringRef keyName)
void PropertySet::setValue (const String& keyName, const XmlElement* const xml) void PropertySet::setValue (const String& keyName, const XmlElement* const xml)
{ {
setValue (keyName, xml == nullptr ? var::null setValue (keyName, xml == nullptr ? var()
: var (xml->createDocument (String::empty, true))); : var (xml->createDocument ("", true)));
} }
bool PropertySet::containsKey (StringRef keyName) const noexcept bool PropertySet::containsKey (StringRef keyName) const noexcept

@ -69,7 +69,7 @@ public:
@param keyName the name of the property to retrieve @param keyName the name of the property to retrieve
@param defaultReturnValue a value to return if the named property doesn't actually exist @param defaultReturnValue a value to return if the named property doesn't actually exist
*/ */
String getValue (StringRef keyName, const String& defaultReturnValue = String::empty) const noexcept; String getValue (StringRef keyName, const String& defaultReturnValue = String()) const noexcept;
/** Returns one of the properties as an integer. /** Returns one of the properties as an integer.
@ -109,8 +109,8 @@ public:
/** Returns one of the properties as an XML element. /** Returns one of the properties as an XML element.
The result will a new XMLElement object that the caller must delete. If may return 0 if the The result will a new XMLElement object that the caller must delete. If may return nullptr
key isn't found, or if the entry contains an string that isn't valid XML. if the key isn't found, or if the entry contains an string that isn't valid XML.
If the value isn't found in this set, then this will look for it in a fallback If the value isn't found in this set, then this will look for it in a fallback
property set (if you've specified one with the setFallbackPropertySet() method), property set (if you've specified one with the setFallbackPropertySet() method),

@ -75,7 +75,7 @@ const File File::nonexistent;
String File::parseAbsolutePath (const String& p) String File::parseAbsolutePath (const String& p)
{ {
if (p.isEmpty()) if (p.isEmpty())
return String::empty; return String();
#if JUCE_WINDOWS #if JUCE_WINDOWS
// Windows.. // Windows..
@ -322,7 +322,7 @@ String File::getFileNameWithoutExtension() const
bool File::isAChildOf (const File& potentialParent) const bool File::isAChildOf (const File& potentialParent) const
{ {
if (potentialParent == File::nonexistent) if (potentialParent.fullPath.isEmpty())
return false; return false;
const String ourPath (getPathUpToLastSlash()); const String ourPath (getPathUpToLastSlash());
@ -482,11 +482,11 @@ bool File::loadFileAsData (MemoryBlock& destBlock) const
String File::loadFileAsString() const String File::loadFileAsString() const
{ {
if (! existsAsFile()) if (! existsAsFile())
return String::empty; return String();
FileInputStream in (*this); FileInputStream in (*this);
return in.openedOk() ? in.readEntireStreamAsString() return in.openedOk() ? in.readEntireStreamAsString()
: String::empty; : String();
} }
void File::readLines (StringArray& destLines) const void File::readLines (StringArray& destLines) const
@ -598,7 +598,7 @@ String File::getFileExtension() const
if (indexOfDot > fullPath.lastIndexOfChar (separator)) if (indexOfDot > fullPath.lastIndexOfChar (separator))
return fullPath.substring (indexOfDot); return fullPath.substring (indexOfDot);
return String::empty; return String();
} }
bool File::hasFileExtension (StringRef possibleSuffix) const bool File::hasFileExtension (StringRef possibleSuffix) const
@ -629,7 +629,7 @@ bool File::hasFileExtension (StringRef possibleSuffix) const
File File::withFileExtension (StringRef newExtension) const File File::withFileExtension (StringRef newExtension) const
{ {
if (fullPath.isEmpty()) if (fullPath.isEmpty())
return File::nonexistent; return File();
String filePart (getFileName()); String filePart (getFileName());

@ -741,7 +741,7 @@ public:
@see revealToUser @see revealToUser
*/ */
bool startAsProcess (const String& parameters = String::empty) const; bool startAsProcess (const String& parameters = String()) const;
/** Opens Finder, Explorer, or whatever the OS uses, to show the user this file's location. /** Opens Finder, Explorer, or whatever the OS uses, to show the user this file's location.
@see startAsProcess @see startAsProcess

@ -50,7 +50,7 @@ TemporaryFile::TemporaryFile (const File& target, const int optionFlags)
targetFile (target) targetFile (target)
{ {
// If you use this constructor, you need to give it a valid target file! // If you use this constructor, you need to give it a valid target file!
jassert (targetFile != File::nonexistent); jassert (targetFile != File());
} }
TemporaryFile::TemporaryFile (const File& target, const File& temporary) TemporaryFile::TemporaryFile (const File& target, const File& temporary)
@ -79,7 +79,7 @@ bool TemporaryFile::overwriteTargetFileWithTemporary() const
{ {
// This method only works if you created this object with the constructor // This method only works if you created this object with the constructor
// that takes a target file! // that takes a target file!
jassert (targetFile != File::nonexistent); jassert (targetFile != File());
if (temporaryFile.exists()) if (temporaryFile.exists())
{ {

@ -89,7 +89,7 @@ public:
The file will not be created until you write to it. And remember that when The file will not be created until you write to it. And remember that when
this object is deleted, the file will also be deleted! this object is deleted, the file will also be deleted!
*/ */
TemporaryFile (const String& suffix = String::empty, TemporaryFile (const String& suffix = String(),
int optionFlags = 0); int optionFlags = 0);
/** Creates a temporary file in the same directory as a specified file. /** Creates a temporary file in the same directory as a specified file.

@ -35,7 +35,7 @@ public:
switch (t.getAndAdvance()) switch (t.getAndAdvance())
{ {
case 0: result = var::null; return Result::ok(); case 0: result = var(); return Result::ok();
case '{': return parseObject (t, result); case '{': return parseObject (t, result);
case '[': return parseArray (t, result); case '[': return parseArray (t, result);
} }
@ -148,7 +148,7 @@ private:
if (t2.getAndAdvance() == 'u' && t2.getAndAdvance() == 'l' && t2.getAndAdvance() == 'l') if (t2.getAndAdvance() == 'u' && t2.getAndAdvance() == 'l' && t2.getAndAdvance() == 'l')
{ {
t = t2; t = t2;
result = var::null; result = var();
return Result::ok(); return Result::ok();
} }
break; break;
@ -254,7 +254,7 @@ private:
if (c2 != ':') if (c2 != ':')
return createFail ("Expected ':', but found", &oldT); return createFail ("Expected ':', but found", &oldT);
resultProperties.set (propertyName, var::null); resultProperties.set (propertyName, var());
var* propertyValue = resultProperties.getVarPointer (propertyName); var* propertyValue = resultProperties.getVarPointer (propertyName);
Result r2 (parseAny (t, *propertyValue)); Result r2 (parseAny (t, *propertyValue));
@ -300,7 +300,7 @@ private:
return createFail ("Unexpected end-of-input in array declaration"); return createFail ("Unexpected end-of-input in array declaration");
t = oldT; t = oldT;
destArray->add (var::null); destArray->add (var());
Result r (parseAny (t, destArray->getReference (destArray->size() - 1))); Result r (parseAny (t, destArray->getReference (destArray->size() - 1)));
if (r.failed()) if (r.failed())
@ -514,7 +514,7 @@ var JSON::parse (const String& text)
var result; var result;
if (! JSONParser::parseObjectOrArray (text.getCharPointer(), result)) if (! JSONParser::parseObjectOrArray (text.getCharPointer(), result))
result = var::null; result = var();
return result; return result;
} }
@ -610,7 +610,7 @@ public:
{ {
switch (r.nextInt (depth > 3 ? 6 : 8)) switch (r.nextInt (depth > 3 ? 6 : 8))
{ {
case 0: return var::null; case 0: return var();
case 1: return r.nextInt(); case 1: return r.nextInt();
case 2: return r.nextInt64(); case 2: return r.nextInt64();
case 3: return r.nextBool(); case 3: return r.nextBool();
@ -638,7 +638,7 @@ public:
} }
default: default:
return var::null; return var();
} }
} }

@ -298,11 +298,10 @@ struct JavascriptEngine::RootObject : public DynamicObject
if (r == returnWasHit) return r; if (r == returnWasHit) return r;
if (r == breakWasHit) break; if (r == breakWasHit) break;
if (r == continueWasHit) continue;
iterator->perform (s, nullptr); iterator->perform (s, nullptr);
if (isDoLoop && ! condition->getResult (s)) if (isDoLoop && r != continueWasHit && ! condition->getResult (s))
break; break;
} }
@ -1244,7 +1243,7 @@ struct JavascriptEngine::RootObject : public DynamicObject
if (matchIf (TokenTypes::openParen)) return parseSuffixes (matchCloseParen (parseExpression())); if (matchIf (TokenTypes::openParen)) return parseSuffixes (matchCloseParen (parseExpression()));
if (matchIf (TokenTypes::true_)) return parseSuffixes (new LiteralValue (location, (int) 1)); if (matchIf (TokenTypes::true_)) return parseSuffixes (new LiteralValue (location, (int) 1));
if (matchIf (TokenTypes::false_)) return parseSuffixes (new LiteralValue (location, (int) 0)); if (matchIf (TokenTypes::false_)) return parseSuffixes (new LiteralValue (location, (int) 0));
if (matchIf (TokenTypes::null_)) return parseSuffixes (new LiteralValue (location, var::null)); if (matchIf (TokenTypes::null_)) return parseSuffixes (new LiteralValue (location, var()));
if (matchIf (TokenTypes::undefined)) return parseSuffixes (new Expression (location)); if (matchIf (TokenTypes::undefined)) return parseSuffixes (new Expression (location));
if (currentType == TokenTypes::literal) if (currentType == TokenTypes::literal)

@ -26,7 +26,6 @@
============================================================================== ==============================================================================
*/ */
/** /**
A simple javascript interpreter! A simple javascript interpreter!

@ -1,7 +1,7 @@
{ {
"id": "juce_core", "id": "juce_core",
"name": "JUCE core classes", "name": "JUCE core classes",
"version": "3.0.0", "version": "3.0.1",
"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",

@ -951,7 +951,7 @@ String BigInteger::toString (const int base, const int minimumNumCharacters) con
else else
{ {
jassertfalse; // can't do the specified base! jassertfalse; // can't do the specified base!
return String::empty; return String();
} }
s = s.paddedLeft ('0', minimumNumCharacters); s = s.paddedLeft ('0', minimumNumCharacters);

@ -53,7 +53,7 @@ public:
virtual String getName() const virtual String getName() const
{ {
jassertfalse; // You shouldn't call this for an expression that's not actually a function! jassertfalse; // You shouldn't call this for an expression that's not actually a function!
return String::empty; return String();
} }
virtual void renameSymbol (const Symbol& oldSymbol, const String& newName, const Scope& scope, int recursionDepth) virtual void renameSymbol (const Symbol& oldSymbol, const String& newName, const Scope& scope, int recursionDepth)
@ -1181,5 +1181,5 @@ void Expression::Scope::visitRelativeScope (const String& scopeName, Visitor&) c
String Expression::Scope::getScopeUID() const String Expression::Scope::getScopeUID() const
{ {
return String::empty; return String();
} }

@ -26,7 +26,6 @@
============================================================================== ==============================================================================
*/ */
Uuid::Uuid() Uuid::Uuid()
{ {
Random r; Random r;

@ -80,7 +80,7 @@ File File::getSpecialLocation (const SpecialLocationType type)
break; break;
} }
return File::nonexistent; return File();
} }
bool File::moveToTrash() const bool File::moveToTrash() const

@ -72,7 +72,7 @@ bool File::isOnRemovableDrive() const
String File::getVersion() const String File::getVersion() const
{ {
return String::empty; // xxx not yet implemented return String(); // xxx not yet implemented
} }
//============================================================================== //==============================================================================
@ -115,7 +115,7 @@ File File::getSpecialLocation (const SpecialLocationType type)
if (struct passwd* const pw = getpwuid (getuid())) if (struct passwd* const pw = getpwuid (getuid()))
return File (CharPointer_UTF8 (pw->pw_dir)); return File (CharPointer_UTF8 (pw->pw_dir));
return File::nonexistent; return File();
} }
case userDocumentsDirectory: return resolveXDGFolder ("XDG_DOCUMENTS_DIR", "~"); case userDocumentsDirectory: return resolveXDGFolder ("XDG_DOCUMENTS_DIR", "~");
@ -163,7 +163,7 @@ File File::getSpecialLocation (const SpecialLocationType type)
break; break;
} }
return File::nonexistent; return File();
} }
//============================================================================== //==============================================================================

@ -309,7 +309,7 @@ private:
{ {
char c = 0; char c = 0;
if (read (&c, 1) != 1) if (read (&c, 1) != 1)
return String::empty; return String();
buffer.writeByte (c); buffer.writeByte (c);
@ -324,7 +324,7 @@ private:
if (header.startsWithIgnoreCase ("HTTP/")) if (header.startsWithIgnoreCase ("HTTP/"))
return header; return header;
return String::empty; return String();
} }
static void writeValueIfNotPresent (MemoryOutputStream& dest, const String& headers, const String& key, const String& value) static void writeValueIfNotPresent (MemoryOutputStream& dest, const String& headers, const String& key, const String& value)
@ -432,7 +432,7 @@ private:
if (lines[i].startsWithIgnoreCase (itemName)) if (lines[i].startsWithIgnoreCase (itemName))
return lines[i].substring (itemName.length()).trim(); return lines[i].substring (itemName.length()).trim();
return String::empty; return String();
} }
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebInputStream) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebInputStream)

@ -44,7 +44,7 @@ String SystemStats::getOperatingSystemName()
String SystemStats::getDeviceDescription() String SystemStats::getDeviceDescription()
{ {
return String::empty; return String();
} }
bool SystemStats::isOperatingSystem64Bit() bool SystemStats::isOperatingSystem64Bit()
@ -69,7 +69,7 @@ namespace LinuxStatsHelpers
if (lines[i].startsWithIgnoreCase (key)) if (lines[i].startsWithIgnoreCase (key))
return lines[i].fromFirstOccurrenceOf (":", false, false).trim(); return lines[i].fromFirstOccurrenceOf (":", false, false).trim();
return String::empty; return String();
} }
} }
@ -107,7 +107,7 @@ String SystemStats::getLogonName()
if (struct passwd* const pw = getpwuid (getuid())) if (struct passwd* const pw = getpwuid (getuid()))
return CharPointer_UTF8 (pw->pw_name); return CharPointer_UTF8 (pw->pw_name);
return String::empty; return String();
} }
String SystemStats::getFullUserName() String SystemStats::getFullUserName()
@ -121,7 +121,7 @@ String SystemStats::getComputerName()
if (gethostname (name, sizeof (name) - 1) == 0) if (gethostname (name, sizeof (name) - 1) == 0)
return name; return name;
return String::empty; return String();
} }
static String getLocaleValue (nl_item key) static String getLocaleValue (nl_item key)

@ -257,7 +257,7 @@ File File::getSpecialLocation (const SpecialLocationType type)
return File (resultPath.convertToPrecomposedUnicode()); return File (resultPath.convertToPrecomposedUnicode());
} }
return File::nonexistent; return File();
} }
//============================================================================== //==============================================================================
@ -271,7 +271,7 @@ String File::getVersion() const
return nsStringToJuce (name); return nsStringToJuce (name);
} }
return String::empty; return String();
} }
//============================================================================== //==============================================================================

@ -29,7 +29,7 @@
String String::fromCFString (CFStringRef cfString) String String::fromCFString (CFStringRef cfString)
{ {
if (cfString == 0) if (cfString == 0)
return String::empty; return String();
CFRange range = { 0, CFStringGetLength (cfString) }; CFRange range = { 0, CFStringGetLength (cfString) };
HeapBlock <UniChar> u ((size_t) range.length + 1); HeapBlock <UniChar> u ((size_t) range.length + 1);

@ -124,7 +124,7 @@ SystemStats::OperatingSystemType SystemStats::getOperatingSystemType()
return iOS; return iOS;
#else #else
StringArray parts; StringArray parts;
parts.addTokens (getOSXVersion(), ".", String::empty); parts.addTokens (getOSXVersion(), ".", String());
jassert (parts[0].getIntValue() == 10); jassert (parts[0].getIntValue() == 10);
const int major = parts[1].getIntValue(); const int major = parts[1].getIntValue();
@ -148,7 +148,7 @@ String SystemStats::getDeviceDescription()
#if JUCE_IOS #if JUCE_IOS
return nsStringToJuce ([[UIDevice currentDevice] model]); return nsStringToJuce ([[UIDevice currentDevice] model]);
#else #else
return String::empty; return String();
#endif #endif
} }
@ -182,7 +182,7 @@ String SystemStats::getCpuVendor()
return String (reinterpret_cast <const char*> (vendor), 12); return String (reinterpret_cast <const char*> (vendor), 12);
#else #else
return String::empty; return String();
#endif #endif
} }
@ -218,7 +218,7 @@ String SystemStats::getComputerName()
if (gethostname (name, sizeof (name) - 1) == 0) if (gethostname (name, sizeof (name) - 1) == 0)
return String (name).upToLastOccurrenceOf (".local", false, true); return String (name).upToLastOccurrenceOf (".local", false, true);
return String::empty; return String();
} }
static String getLocaleValue (CFStringRef key) static String getLocaleValue (CFStringRef key)

@ -636,7 +636,7 @@ String File::getVolumeLabel() const
} }
#endif #endif
return String::empty; return String();
} }
int File::getVolumeSerialNumber() const int File::getVolumeSerialNumber() const

@ -93,7 +93,7 @@ namespace WindowsFileHelpers
if (SHGetSpecialFolderPath (0, path, type, FALSE)) if (SHGetSpecialFolderPath (0, path, type, FALSE))
return File (String (path)); return File (String (path));
return File::nonexistent; return File();
} }
File getModuleFileName (HINSTANCE moduleHandle) File getModuleFileName (HINSTANCE moduleHandle)
@ -542,7 +542,7 @@ File JUCE_CALLTYPE File::getSpecialLocation (const SpecialLocationType type)
default: default:
jassertfalse; // unknown type? jassertfalse; // unknown type?
return File::nonexistent; return File();
} }
return WindowsFileHelpers::getSpecialFolderPath (csidlType); return WindowsFileHelpers::getSpecialFolderPath (csidlType);

@ -55,7 +55,7 @@ IPAddress::IPAddress (uint32 n) noexcept
IPAddress::IPAddress (const String& adr) IPAddress::IPAddress (const String& adr)
{ {
StringArray tokens; StringArray tokens;
tokens.addTokens (adr, ".", String::empty); tokens.addTokens (adr, ".", String());
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
address[i] = (uint8) tokens[i].getIntValue(); address[i] = (uint8) tokens[i].getIntValue();

@ -386,7 +386,7 @@ void StreamingSocket::close()
::close (handle); ::close (handle);
#endif #endif
hostName = String::empty; hostName.clear();
portNumber = 0; portNumber = 0;
handle = -1; handle = -1;
isListener = false; isListener = false;
@ -506,7 +506,7 @@ void DatagramSocket::close()
::close (handle); ::close (handle);
#endif #endif
hostName = String::empty; hostName.clear();
portNumber = 0; portNumber = 0;
handle = -1; handle = -1;
} }

@ -146,7 +146,7 @@ public:
@see waitForNextConnection @see waitForNextConnection
*/ */
bool createListener (int portNumber, const String& localHostName = String::empty); bool createListener (int portNumber, const String& localHostName = String());
/** When in "listener" mode, this waits for a connection and spawns it as a new /** When in "listener" mode, this waits for a connection and spawns it as a new
socket. socket.

@ -181,7 +181,7 @@ namespace URLHelpers
<< "\"; filename=\"" << file.getFileName() << "\"\r\n"; << "\"; filename=\"" << file.getFileName() << "\"\r\n";
const String mimeType (url.getMimeTypesOfUploadFiles() const String mimeType (url.getMimeTypesOfUploadFiles()
.getValue (paramName, String::empty)); .getValue (paramName, String()));
if (mimeType.isNotEmpty()) if (mimeType.isNotEmpty())
data << "Content-Type: " << mimeType << "\r\n"; data << "Content-Type: " << mimeType << "\r\n";
@ -253,7 +253,7 @@ String URL::getSubPath() const
{ {
const int startOfPath = URLHelpers::findStartOfPath (url); const int startOfPath = URLHelpers::findStartOfPath (url);
return startOfPath <= 0 ? String::empty return startOfPath <= 0 ? String()
: url.substring (startOfPath); : url.substring (startOfPath);
} }
@ -363,7 +363,7 @@ String URL::readEntireTextStream (const bool usePostCommand) const
if (in != nullptr) if (in != nullptr)
return in->readEntireStreamAsString(); return in->readEntireStreamAsString();
return String::empty; return String();
} }
XmlElement* URL::readEntireXmlStream (const bool usePostCommand) const XmlElement* URL::readEntireXmlStream (const bool usePostCommand) const
@ -470,5 +470,5 @@ bool URL::launchInDefaultBrowser() const
if (u.containsChar ('@') && ! u.containsChar (':')) if (u.containsChar ('@') && ! u.containsChar (':'))
u = "mailto:" + u; u = "mailto:" + u;
return Process::openDocument (u, String::empty); return Process::openDocument (u, String());
} }

@ -251,7 +251,7 @@ public:
InputStream* createInputStream (bool usePostCommand, InputStream* createInputStream (bool usePostCommand,
OpenStreamProgressCallback* progressCallback = nullptr, OpenStreamProgressCallback* progressCallback = nullptr,
void* progressCallbackContext = nullptr, void* progressCallbackContext = nullptr,
String extraHeaders = String::empty, String extraHeaders = String(),
int connectionTimeOutMs = 0, int connectionTimeOutMs = 0,
StringPairArray* responseHeaders = nullptr) const; StringPairArray* responseHeaders = nullptr) const;

@ -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 0 #define JUCE_BUILDNUMBER 1
/** Current Juce version number. /** Current Juce version number.

@ -43,11 +43,17 @@ LocalisedStrings::~LocalisedStrings()
//============================================================================== //==============================================================================
String LocalisedStrings::translate (const String& text) const String LocalisedStrings::translate (const String& text) const
{ {
if (fallback != nullptr && ! translations.containsKey (text))
return fallback->translate (text);
return translations.getValue (text, text); return translations.getValue (text, text);
} }
String LocalisedStrings::translate (const String& text, const String& resultIfNotFound) const String LocalisedStrings::translate (const String& text, const String& resultIfNotFound) const
{ {
if (fallback != nullptr && ! translations.containsKey (text))
return fallback->translate (text, resultIfNotFound);
return translations.getValue (text, resultIfNotFound); return translations.getValue (text, resultIfNotFound);
} }
@ -73,7 +79,7 @@ namespace
SpinLock currentMappingsLock; SpinLock currentMappingsLock;
ScopedPointer<LocalisedStrings> currentMappings; ScopedPointer<LocalisedStrings> currentMappings;
int findCloseQuote (const String& text, int startPos) static int findCloseQuote (const String& text, int startPos)
{ {
juce_wchar lastChar = 0; juce_wchar lastChar = 0;
String::CharPointerType t (text.getCharPointer() + startPos); String::CharPointerType t (text.getCharPointer() + startPos);
@ -92,7 +98,7 @@ namespace
return startPos; return startPos;
} }
String unescapeString (const String& s) static String unescapeString (const String& s)
{ {
return s.replace ("\\\"", "\"") return s.replace ("\\\"", "\"")
.replace ("\\\'", "\'") .replace ("\\\'", "\'")
@ -141,6 +147,8 @@ void LocalisedStrings::loadFromText (const String& fileContents, bool ignoreCase
countryCodes.removeEmptyStrings(); countryCodes.removeEmptyStrings();
} }
} }
translations.minimiseStorageOverheads();
} }
void LocalisedStrings::addStrings (const LocalisedStrings& other) void LocalisedStrings::addStrings (const LocalisedStrings& other)
@ -151,6 +159,11 @@ void LocalisedStrings::addStrings (const LocalisedStrings& other)
translations.addArray (other.translations); translations.addArray (other.translations);
} }
void LocalisedStrings::setFallback (LocalisedStrings* f)
{
fallback = f;
}
//============================================================================== //==============================================================================
void LocalisedStrings::setCurrentMappings (LocalisedStrings* newTranslations) void LocalisedStrings::setCurrentMappings (LocalisedStrings* newTranslations)
{ {

@ -183,11 +183,18 @@ public:
*/ */
void addStrings (const LocalisedStrings&); void addStrings (const LocalisedStrings&);
/** Gives this object a set of strings to use as a fallback if a string isn't found.
The object that is passed-in will be owned and deleted by this object
when no longer needed. It can be nullptr to clear the existing fallback object.
*/
void setFallback (LocalisedStrings* fallbackStrings);
private: private:
//============================================================================== //==============================================================================
String languageName; String languageName;
StringArray countryCodes; StringArray countryCodes;
StringPairArray translations; StringPairArray translations;
ScopedPointer<LocalisedStrings> fallback;
void loadFromText (const String&, bool ignoreCase); void loadFromText (const String&, bool ignoreCase);

@ -259,6 +259,12 @@ void String::swapWith (String& other) noexcept
std::swap (text, other.text); std::swap (text, other.text);
} }
void String::clear() noexcept
{
StringHolder::release (text);
text = &(emptyString.text);
}
String& String::operator= (const String& other) noexcept String& String::operator= (const String& other) noexcept
{ {
StringHolder::retain (other.text); StringHolder::retain (other.text);
@ -419,7 +425,8 @@ namespace NumberToStringConverters
{ {
explicit StackArrayStream (char* d) explicit StackArrayStream (char* d)
{ {
imbue (std::locale::classic()); static const std::locale classicLocale (std::locale::classic());
imbue (classicLocale);
setp (d, d + charsNeededForDouble); setp (d, d + charsNeededForDouble);
} }

@ -307,6 +307,9 @@ public:
*/ */
inline bool isNotEmpty() const noexcept { return text[0] != 0; } inline bool isNotEmpty() const noexcept { return text[0] != 0; }
/** Resets this string to be empty. */
void clear() noexcept;
/** Case-insensitive comparison with another string. */ /** Case-insensitive comparison with another string. */
bool equalsIgnoreCase (const String& other) const noexcept; bool equalsIgnoreCase (const String& other) const noexcept;

@ -293,7 +293,7 @@ String StringArray::joinIntoString (StringRef separator, int start, int numberTo
start = 0; start = 0;
if (start >= last) if (start >= last)
return String::empty; return String();
if (start == last - 1) if (start == last - 1)
return strings.getReference (start); return strings.getReference (start);

@ -78,6 +78,11 @@ String StringPairArray::getValue (StringRef key, const String& defaultReturnValu
return defaultReturnValue; return defaultReturnValue;
} }
bool StringPairArray::containsKey (StringRef key) const noexcept
{
return keys.contains (key);
}
void StringPairArray::set (const String& key, const String& value) void StringPairArray::set (const String& key, const String& value)
{ {
const int i = keys.indexOf (key, ignoreCase); const int i = keys.indexOf (key, ignoreCase);

@ -85,6 +85,8 @@ public:
*/ */
String getValue (StringRef, const String& defaultReturnValue) const; String getValue (StringRef, const String& defaultReturnValue) const;
/** Returns true if the given key exists. */
bool containsKey (StringRef key) const noexcept;
/** Returns a list of all keys in the array. */ /** Returns a list of all keys in the array. */
const StringArray& getAllKeys() const noexcept { return keys; } const StringArray& getAllKeys() const noexcept { return keys; }

@ -81,7 +81,7 @@ namespace StringPoolHelpers
String::CharPointerType StringPool::getPooledString (const String& s) String::CharPointerType StringPool::getPooledString (const String& s)
{ {
if (s.isEmpty()) if (s.isEmpty())
return String::empty.getCharPointer(); return String().getCharPointer();
return StringPoolHelpers::getPooledStringFromArray (strings, s, lock); return StringPoolHelpers::getPooledStringFromArray (strings, s, lock);
} }
@ -89,7 +89,7 @@ String::CharPointerType StringPool::getPooledString (const String& s)
String::CharPointerType StringPool::getPooledString (const char* const s) String::CharPointerType StringPool::getPooledString (const char* const s)
{ {
if (s == nullptr || *s == 0) if (s == nullptr || *s == 0)
return String::empty.getCharPointer(); return String().getCharPointer();
return StringPoolHelpers::getPooledStringFromArray (strings, s, lock); return StringPoolHelpers::getPooledStringFromArray (strings, s, lock);
} }
@ -97,7 +97,7 @@ String::CharPointerType StringPool::getPooledString (const char* const s)
String::CharPointerType StringPool::getPooledString (const wchar_t* const s) String::CharPointerType StringPool::getPooledString (const wchar_t* const s)
{ {
if (s == nullptr || *s == 0) if (s == nullptr || *s == 0)
return String::empty.getCharPointer(); return String().getCharPointer();
return StringPoolHelpers::getPooledStringFromArray (strings, s, lock); return StringPoolHelpers::getPooledStringFromArray (strings, s, lock);
} }

@ -247,7 +247,7 @@ public:
/** Returns one of the jobs in the queue. /** Returns one of the jobs in the queue.
Note that this can be a very volatile list as jobs might be continuously getting shifted Note that this can be a very volatile list as jobs might be continuously getting shifted
around in the list, and this method may return 0 if the index is currently out-of-range. around in the list, and this method may return nullptr if the index is currently out-of-range.
*/ */
ThreadPoolJob* getJob (int index) const; ThreadPoolJob* getJob (int index) const;

@ -28,7 +28,7 @@
static void appendToFile (const File& f, const String& s) static void appendToFile (const File& f, const String& s)
{ {
if (f != File::nonexistent) if (f.getFullPathName().isNotEmpty())
{ {
FileOutputStream out (f); FileOutputStream out (f);

@ -65,7 +65,7 @@ public:
*/ */
PerformanceCounter (const String& counterName, PerformanceCounter (const String& counterName,
int runsPerPrintout = 100, int runsPerPrintout = 100,
const File& loggingFile = File::nonexistent); const File& loggingFile = File());
/** Destructor. */ /** Destructor. */
~PerformanceCounter(); ~PerformanceCounter();

@ -210,7 +210,7 @@ XmlElement* XmlDocument::parseDocumentElement (String::CharPointerType textToPar
} }
else else
{ {
lastError = String::empty; lastError.clear();
ScopedPointer<XmlElement> result (readNextElement (! onlyReadOuterDocumentElement)); ScopedPointer<XmlElement> result (readNextElement (! onlyReadOuterDocumentElement));

@ -541,7 +541,7 @@ private:
void writeFlagsAndSizes (OutputStream& target) const void writeFlagsAndSizes (OutputStream& target) const
{ {
target.writeShort (10); // version needed target.writeShort (10); // version needed
target.writeShort (0); // flags target.writeShort ((short) (1 << 11)); // this flag indicates UTF-8 filename encoding
target.writeShort (compressionLevel > 0 ? (short) 8 : (short) 0); target.writeShort (compressionLevel > 0 ? (short) 8 : (short) 0);
writeTimeAndDate (target, fileTime); writeTimeAndDate (target, fileTime);
target.writeInt ((int) checksum); target.writeInt ((int) checksum);

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

Loading…
Cancel
Save