pull/1/head
Pascal Gauthier 10 years ago
parent 6265606c6f
commit 5bdfae091f
  1. 2
      Builds/MacOSX/Dexed.xcodeproj/project.pbxproj
  2. BIN
      Builds/VisualStudio2012/Dexed.v11.suo
  3. 1
      Builds/VisualStudio2012/Dexed.vcxproj
  4. 3
      Builds/VisualStudio2012/Dexed.vcxproj.filters
  5. 1
      Builds/VisualStudio2013/Dexed.vcxproj
  6. 3
      Builds/VisualStudio2013/Dexed.vcxproj.filters
  7. 2
      Dexed.jucer
  8. 4006
      JuceLibraryCode/BinaryData.cpp
  9. 11
      JuceLibraryCode/BinaryData.h
  10. 129
      JuceLibraryCode/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp
  11. 30
      JuceLibraryCode/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h
  12. 3
      JuceLibraryCode/modules/juce_audio_basics/sources/juce_ResamplingAudioSource.cpp
  13. 97
      JuceLibraryCode/modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp
  14. 68
      JuceLibraryCode/modules/juce_audio_basics/synthesisers/juce_Synthesiser.h
  15. 2
      JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_ALSA.cpp
  16. 77
      JuceLibraryCode/modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp
  17. 10
      JuceLibraryCode/modules/juce_audio_formats/sampler/juce_Sampler.cpp
  18. 6
      JuceLibraryCode/modules/juce_audio_formats/sampler/juce_Sampler.h
  19. 8
      JuceLibraryCode/modules/juce_audio_plugin_client/AAX/juce_AAX_Wrapper.cpp
  20. 9
      JuceLibraryCode/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp
  21. 5
      JuceLibraryCode/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.mm
  22. 4
      JuceLibraryCode/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp
  23. 3
      JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp
  24. 8
      JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessor.h
  25. 2
      JuceLibraryCode/modules/juce_core/containers/juce_OwnedArray.h
  26. 19
      JuceLibraryCode/modules/juce_core/javascript/juce_Javascript.cpp
  27. 7
      JuceLibraryCode/modules/juce_core/native/juce_linux_Network.cpp
  28. 15
      JuceLibraryCode/modules/juce_core/native/juce_posix_SharedCode.h
  29. 2
      JuceLibraryCode/modules/juce_core/network/juce_Socket.cpp
  30. 2
      JuceLibraryCode/modules/juce_core/streams/juce_MemoryOutputStream.cpp
  31. 1
      JuceLibraryCode/modules/juce_core/system/juce_StandardHeader.h
  32. 2
      JuceLibraryCode/modules/juce_core/system/juce_TargetPlatform.h
  33. 5
      JuceLibraryCode/modules/juce_data_structures/values/juce_ValueTree.h
  34. 16
      JuceLibraryCode/modules/juce_events/messages/juce_MessageManager.cpp
  35. 5
      JuceLibraryCode/modules/juce_events/messages/juce_MessageManager.h
  36. 6
      JuceLibraryCode/modules/juce_graphics/contexts/juce_GraphicsContext.h
  37. 12
      JuceLibraryCode/modules/juce_gui_basics/buttons/juce_Button.cpp
  38. 7
      JuceLibraryCode/modules/juce_gui_basics/buttons/juce_Button.h
  39. 39
      JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandManager.cpp
  40. 1
      JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandManager.h
  41. 13
      JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.cpp
  42. 3
      JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.h
  43. 7
      JuceLibraryCode/modules/juce_gui_basics/menus/juce_PopupMenu.cpp
  44. 3
      JuceLibraryCode/modules/juce_gui_basics/menus/juce_PopupMenu.h
  45. 37
      JuceLibraryCode/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp
  46. 6
      JuceLibraryCode/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.h
  47. 123
      JuceLibraryCode/modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm
  48. 4
      JuceLibraryCode/modules/juce_gui_basics/native/juce_linux_Windowing.cpp
  49. 46
      JuceLibraryCode/modules/juce_gui_basics/native/juce_win32_Windowing.cpp
  50. 2
      JuceLibraryCode/modules/juce_gui_basics/properties/juce_BooleanPropertyComponent.cpp
  51. 14
      JuceLibraryCode/modules/juce_gui_basics/properties/juce_BooleanPropertyComponent.h
  52. 2
      JuceLibraryCode/modules/juce_gui_basics/widgets/juce_Label.cpp
  53. 2
      JuceLibraryCode/modules/juce_gui_basics/widgets/juce_Label.h
  54. 14
      JuceLibraryCode/modules/juce_gui_basics/widgets/juce_ListBox.cpp
  55. 18
      JuceLibraryCode/modules/juce_gui_basics/widgets/juce_ListBox.h
  56. 7
      JuceLibraryCode/modules/juce_gui_basics/widgets/juce_Slider.cpp
  57. 3
      JuceLibraryCode/modules/juce_gui_basics/widgets/juce_TableListBox.h
  58. 8
      JuceLibraryCode/modules/juce_gui_basics/widgets/juce_Toolbar.cpp
  59. 9
      JuceLibraryCode/modules/juce_gui_basics/widgets/juce_TreeView.cpp
  60. 2
      JuceLibraryCode/modules/juce_gui_basics/windows/juce_DialogWindow.h
  61. 2
      JuceLibraryCode/modules/juce_gui_basics/windows/juce_TopLevelWindow.h
  62. 6
      JuceLibraryCode/modules/juce_gui_extra/native/juce_win32_WebBrowserComponent.cpp
  63. 8
      README.md
  64. BIN
      Resources/ui/Knob_34x34.png
  65. BIN
      Resources/ui/LFO_36_26.png
  66. BIN
      Resources/ui/NotoSans-Bold.ttf
  67. BIN
      Resources/ui/Scaling_36_26.png
  68. BIN
      Resources/ui/source/Dexed-skinman.skin
  69. BIN
      Resources/ui/source/Knob_34x34.knob
  70. BIN
      Resources/ui/source/render_template.png
  71. 309
      Source/AlgoDisplay.cpp
  72. 25
      Source/AlgoDisplay.h
  73. 70
      Source/DXComponents.cpp
  74. 7
      Source/DXComponents.h
  75. 57
      Source/DXLookNFeel.cpp
  76. 14
      Source/DXLookNFeel.h
  77. 56
      Source/GlobalEditor.cpp
  78. 21
      Source/OperatorEditor.cpp
  79. 35
      Source/ParamDialog.cpp
  80. 5
      Source/ParamDialog.h
  81. 14
      Source/PluginData.cpp
  82. 17
      Source/PluginEditor.cpp
  83. 8
      Source/PluginParam.cpp
  84. 3
      Source/PluginProcessor.h
  85. 2
      Source/msfa/dx7note.cc

@ -381,6 +381,7 @@
588255FD68989F1A03FDF31C = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_CPlusPlusCodeTokeniserFunctions.h"; path = "../../JuceLibraryCode/modules/juce_gui_extra/code_editor/juce_CPlusPlusCodeTokeniserFunctions.h"; sourceTree = "SOURCE_ROOT"; }; 588255FD68989F1A03FDF31C = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_CPlusPlusCodeTokeniserFunctions.h"; path = "../../JuceLibraryCode/modules/juce_gui_extra/code_editor/juce_CPlusPlusCodeTokeniserFunctions.h"; sourceTree = "SOURCE_ROOT"; };
59D15F780D468B587F9C7E78 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = PluginParam.cpp; path = ../../Source/PluginParam.cpp; sourceTree = "SOURCE_ROOT"; }; 59D15F780D468B587F9C7E78 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = PluginParam.cpp; path = ../../Source/PluginParam.cpp; sourceTree = "SOURCE_ROOT"; };
5A1BD822F8CB7D42BB0EAF7A = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_PluginListComponent.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_processors/scanning/juce_PluginListComponent.cpp"; sourceTree = "SOURCE_ROOT"; }; 5A1BD822F8CB7D42BB0EAF7A = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_PluginListComponent.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_processors/scanning/juce_PluginListComponent.cpp"; sourceTree = "SOURCE_ROOT"; };
5A366F36F3B4E50587A30351 = {isa = PBXFileReference; lastKnownFileType = file.ttf; name = "NotoSans-Bold.ttf"; path = "../../Resources/ui/NotoSans-Bold.ttf"; sourceTree = "SOURCE_ROOT"; };
5B12686E2808FCCB8BBE0E24 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_GraphicsContext.cpp"; path = "../../JuceLibraryCode/modules/juce_graphics/native/juce_android_GraphicsContext.cpp"; sourceTree = "SOURCE_ROOT"; }; 5B12686E2808FCCB8BBE0E24 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_GraphicsContext.cpp"; path = "../../JuceLibraryCode/modules/juce_graphics/native/juce_android_GraphicsContext.cpp"; sourceTree = "SOURCE_ROOT"; };
5BA236D62129EFE13A9EAB1B = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_MixerAudioSource.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_basics/sources/juce_MixerAudioSource.cpp"; sourceTree = "SOURCE_ROOT"; }; 5BA236D62129EFE13A9EAB1B = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_MixerAudioSource.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_basics/sources/juce_MixerAudioSource.cpp"; sourceTree = "SOURCE_ROOT"; };
5BC311F801FE9D018A7B231C = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ComponentDragger.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/mouse/juce_ComponentDragger.cpp"; sourceTree = "SOURCE_ROOT"; }; 5BC311F801FE9D018A7B231C = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ComponentDragger.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/mouse/juce_ComponentDragger.cpp"; sourceTree = "SOURCE_ROOT"; };
@ -910,6 +911,7 @@
66E042C6FFE93F0E19B32F09, 66E042C6FFE93F0E19B32F09,
C7577AF98915C39EDCEC259A, C7577AF98915C39EDCEC259A,
1D72CD485011A4EA3E6B0FD5, 1D72CD485011A4EA3E6B0FD5,
5A366F36F3B4E50587A30351,
15B75D829C40872D542A38B8, 15B75D829C40872D542A38B8,
0E3FA3D7B11FC7D19CC634BE, ); name = Resources; sourceTree = "<group>"; }; 0E3FA3D7B11FC7D19CC634BE, ); name = Resources; sourceTree = "<group>"; };
0652CE27AE4971C99654E3BF = {isa = PBXGroup; children = ( 0652CE27AE4971C99654E3BF = {isa = PBXGroup; children = (

@ -1539,6 +1539,7 @@
<None Include="..\..\Resources\ui\Scaling_36_26.png"/> <None Include="..\..\Resources\ui\Scaling_36_26.png"/>
<None Include="..\..\Resources\ui\Slider_26x26.png"/> <None Include="..\..\Resources\ui\Slider_26x26.png"/>
<None Include="..\..\Resources\ui\NotoSans-Regular.ttf"/> <None Include="..\..\Resources\ui\NotoSans-Regular.ttf"/>
<None Include="..\..\Resources\ui\NotoSans-Bold.ttf"/>
<None Include="..\..\Resources\builtin_pgm.zip"/> <None Include="..\..\Resources\builtin_pgm.zip"/>
<None Include="..\..\Resources\about.png"/> <None Include="..\..\Resources\about.png"/>
<None Include="..\..\JuceLibraryCode\modules\juce_audio_basics\juce_module_info"/> <None Include="..\..\JuceLibraryCode\modules\juce_audio_basics\juce_module_info"/>

@ -2699,6 +2699,9 @@
<None Include="..\..\Resources\ui\NotoSans-Regular.ttf"> <None Include="..\..\Resources\ui\NotoSans-Regular.ttf">
<Filter>Dexed\Resources</Filter> <Filter>Dexed\Resources</Filter>
</None> </None>
<None Include="..\..\Resources\ui\NotoSans-Bold.ttf">
<Filter>Dexed\Resources</Filter>
</None>
<None Include="..\..\Resources\builtin_pgm.zip"> <None Include="..\..\Resources\builtin_pgm.zip">
<Filter>Dexed\Resources</Filter> <Filter>Dexed\Resources</Filter>
</None> </None>

@ -1538,6 +1538,7 @@
<None Include="..\..\Resources\ui\Scaling_36_26.png"/> <None Include="..\..\Resources\ui\Scaling_36_26.png"/>
<None Include="..\..\Resources\ui\Slider_26x26.png"/> <None Include="..\..\Resources\ui\Slider_26x26.png"/>
<None Include="..\..\Resources\ui\NotoSans-Regular.ttf"/> <None Include="..\..\Resources\ui\NotoSans-Regular.ttf"/>
<None Include="..\..\Resources\ui\NotoSans-Bold.ttf"/>
<None Include="..\..\Resources\builtin_pgm.zip"/> <None Include="..\..\Resources\builtin_pgm.zip"/>
<None Include="..\..\Resources\about.png"/> <None Include="..\..\Resources\about.png"/>
<None Include="..\..\JuceLibraryCode\modules\juce_audio_basics\juce_module_info"/> <None Include="..\..\JuceLibraryCode\modules\juce_audio_basics\juce_module_info"/>

@ -2699,6 +2699,9 @@
<None Include="..\..\Resources\ui\NotoSans-Regular.ttf"> <None Include="..\..\Resources\ui\NotoSans-Regular.ttf">
<Filter>Dexed\Resources</Filter> <Filter>Dexed\Resources</Filter>
</None> </None>
<None Include="..\..\Resources\ui\NotoSans-Bold.ttf">
<Filter>Dexed\Resources</Filter>
</None>
<None Include="..\..\Resources\builtin_pgm.zip"> <None Include="..\..\Resources\builtin_pgm.zip">
<Filter>Dexed\Resources</Filter> <Filter>Dexed\Resources</Filter>
</None> </None>

@ -26,6 +26,8 @@
file="Resources/ui/Slider_26x26.png"/> file="Resources/ui/Slider_26x26.png"/>
<FILE id="g1Wwz3" name="NotoSans-Regular.ttf" compile="0" resource="1" <FILE id="g1Wwz3" name="NotoSans-Regular.ttf" compile="0" resource="1"
file="Resources/ui/NotoSans-Regular.ttf"/> file="Resources/ui/NotoSans-Regular.ttf"/>
<FILE id="A3xTGc" name="NotoSans-Bold.ttf" compile="0" resource="1"
file="Resources/ui/NotoSans-Bold.ttf"/>
<FILE id="gfRTZ1" name="builtin_pgm.zip" compile="0" resource="1" file="Resources/builtin_pgm.zip"/> <FILE id="gfRTZ1" name="builtin_pgm.zip" compile="0" resource="1" file="Resources/builtin_pgm.zip"/>
<FILE id="xxGEA4" name="about.png" compile="0" resource="1" file="Resources/about.png"/> <FILE id="xxGEA4" name="about.png" compile="0" resource="1" file="Resources/about.png"/>
</GROUP> </GROUP>

File diff suppressed because it is too large Load Diff

@ -16,10 +16,10 @@ namespace BinaryData
const int ButtonUnlabeled_50x30_pngSize = 1850; const int ButtonUnlabeled_50x30_pngSize = 1850;
extern const char* Knob_34x34_png; extern const char* Knob_34x34_png;
const int Knob_34x34_pngSize = 3926; const int Knob_34x34_pngSize = 13011;
extern const char* LFO_36_26_png; extern const char* LFO_36_26_png;
const int LFO_36_26_pngSize = 1666; const int LFO_36_26_pngSize = 1702;
extern const char* Light_14x14_png; extern const char* Light_14x14_png;
const int Light_14x14_pngSize = 796; const int Light_14x14_pngSize = 796;
@ -28,7 +28,7 @@ namespace BinaryData
const int Meter_140x8_pngSize = 402; const int Meter_140x8_pngSize = 402;
extern const char* Scaling_36_26_png; extern const char* Scaling_36_26_png;
const int Scaling_36_26_pngSize = 1736; const int Scaling_36_26_pngSize = 1538;
extern const char* Slider_26x26_png; extern const char* Slider_26x26_png;
const int Slider_26x26_pngSize = 744; const int Slider_26x26_pngSize = 744;
@ -36,6 +36,9 @@ namespace BinaryData
extern const char* NotoSansRegular_ttf; extern const char* NotoSansRegular_ttf;
const int NotoSansRegular_ttfSize = 306788; const int NotoSansRegular_ttfSize = 306788;
extern const char* NotoSansBold_ttf;
const int NotoSansBold_ttfSize = 311508;
extern const char* builtin_pgm_zip; extern const char* builtin_pgm_zip;
const int builtin_pgm_zipSize = 88890; const int builtin_pgm_zipSize = 88890;
@ -46,7 +49,7 @@ namespace BinaryData
extern const char* namedResourceList[]; extern const char* namedResourceList[];
// Number of elements in the namedResourceList array. // Number of elements in the namedResourceList array.
const int namedResourceListSize = 11; const int namedResourceListSize = 12;
// If you provide the name of one of the binary resource variables above, this function will // If you provide the name of one of the binary resource variables above, this function will
// return the corresponding data and its size (or a null pointer if the name isn't found). // return the corresponding data and its size (or a null pointer if the name isn't found).

@ -24,8 +24,9 @@
namespace FloatVectorHelpers namespace FloatVectorHelpers
{ {
#define JUCE_INCREMENT_SRC_DEST dest += (16 / sizeof (*dest)); src += (16 / sizeof (*dest)); #define JUCE_INCREMENT_SRC_DEST dest += (16 / sizeof (*dest)); src += (16 / sizeof (*dest));
#define JUCE_INCREMENT_DEST dest += (16 / sizeof (*dest)); #define JUCE_INCREMENT_SRC1_SRC2_DEST dest += (16 / sizeof (*dest)); src1 += (16 / sizeof (*dest)); src2 += (16 / sizeof (*dest));
#define JUCE_INCREMENT_DEST dest += (16 / sizeof (*dest));
#if JUCE_USE_SSE_INTRINSICS #if JUCE_USE_SSE_INTRINSICS
static bool sse2Present = false; static bool sse2Present = false;
@ -122,6 +123,17 @@ namespace FloatVectorHelpers
} \ } \
JUCE_FINISH_VEC_OP (normalOp) JUCE_FINISH_VEC_OP (normalOp)
#define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST(normalOp, vecOp, locals, increment, setupOp) \
JUCE_BEGIN_VEC_OP \
setupOp \
{ \
Mode::ParallelType (&loadSrc1) (const Mode::Type* v) = FloatVectorHelpers::isAligned (src1) ? Mode::loadA : Mode::loadU; \
Mode::ParallelType (&loadSrc2) (const Mode::Type* v) = FloatVectorHelpers::isAligned (src2) ? Mode::loadA : Mode::loadU; \
void (&storeDst) (Mode::Type* dest, Mode::ParallelType a) = FloatVectorHelpers::isAligned (dest) ? Mode::storeA : Mode::storeU; \
JUCE_VEC_LOOP_TWO_SOURCES (vecOp, loadSrc1, loadSrc2, storeDst, locals, increment); \
} \
JUCE_FINISH_VEC_OP (normalOp)
//============================================================================== //==============================================================================
#elif JUCE_USE_ARM_NEON #elif JUCE_USE_ARM_NEON
@ -193,6 +205,12 @@ namespace FloatVectorHelpers
JUCE_VEC_LOOP (vecOp, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \ JUCE_VEC_LOOP (vecOp, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \
JUCE_FINISH_VEC_OP (normalOp) JUCE_FINISH_VEC_OP (normalOp)
#define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST(normalOp, vecOp, locals, increment, setupOp) \
JUCE_BEGIN_VEC_OP \
setupOp \
JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \
JUCE_FINISH_VEC_OP (normalOp)
//============================================================================== //==============================================================================
#else #else
#define JUCE_PERFORM_VEC_OP_DEST(normalOp, vecOp, locals, setupOp) \ #define JUCE_PERFORM_VEC_OP_DEST(normalOp, vecOp, locals, setupOp) \
@ -201,6 +219,8 @@ namespace FloatVectorHelpers
#define JUCE_PERFORM_VEC_OP_SRC_DEST(normalOp, vecOp, locals, increment, setupOp) \ #define JUCE_PERFORM_VEC_OP_SRC_DEST(normalOp, vecOp, locals, increment, setupOp) \
for (int i = 0; i < num; ++i) normalOp; for (int i = 0; i < num; ++i) normalOp;
#define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST(normalOp, vecOp, locals, increment, setupOp) \
for (int i = 0; i < num; ++i) normalOp;
#endif #endif
//============================================================================== //==============================================================================
@ -212,10 +232,19 @@ namespace FloatVectorHelpers
increment; \ increment; \
} }
#define JUCE_VEC_LOOP_TWO_SOURCES(vecOp, src1Load, src2Load, dstStore, locals, increment) \
for (int i = 0; i < numLongOps; ++i) \
{ \
locals (src1Load, src2Load); \
dstStore (dest, vecOp); \
increment; \
}
#define JUCE_LOAD_NONE(srcLoad, dstLoad) #define JUCE_LOAD_NONE(srcLoad, dstLoad)
#define JUCE_LOAD_DEST(srcLoad, dstLoad) const Mode::ParallelType d = dstLoad (dest); #define JUCE_LOAD_DEST(srcLoad, dstLoad) const Mode::ParallelType d = dstLoad (dest);
#define JUCE_LOAD_SRC(srcLoad, dstLoad) const Mode::ParallelType s = srcLoad (src); #define JUCE_LOAD_SRC(srcLoad, dstLoad) const Mode::ParallelType s = srcLoad (src);
#define JUCE_LOAD_SRC_DEST(srcLoad, dstLoad) const Mode::ParallelType d = dstLoad (dest), s = srcLoad (src); #define JUCE_LOAD_SRC1_SRC2(src1Load, src2Load) const Mode::ParallelType s1 = src1Load (src1), s2 = src2Load (src2);
#define JUCE_LOAD_SRC_DEST(srcLoad, dstLoad) const Mode::ParallelType d = dstLoad (dest), s = srcLoad (src);
#if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON #if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
template<int typeSize> struct ModeType { typedef BasicOps32 Mode; }; template<int typeSize> struct ModeType { typedef BasicOps32 Mode; };
@ -443,6 +472,28 @@ void JUCE_CALLTYPE FloatVectorOperations::add (double* dest, double amount, int
const Mode::ParallelType amountToAdd = Mode::load1 (amount);) const Mode::ParallelType amountToAdd = Mode::load1 (amount);)
} }
void JUCE_CALLTYPE FloatVectorOperations::add (float* dest, float* src, float amount, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vsadd (src, 1, &amount, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] + amount, Mode::add (am, s),
JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
const Mode::ParallelType am = Mode::load1 (amount);)
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::add (double* dest, double* src, double amount, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vsaddD (src, 1, &amount, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] + amount, Mode::add (am, s),
JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
const Mode::ParallelType am = Mode::load1 (amount);)
#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
@ -461,6 +512,24 @@ void JUCE_CALLTYPE FloatVectorOperations::add (double* dest, const double* src,
#endif #endif
} }
void JUCE_CALLTYPE FloatVectorOperations::add (float* dest, const float* src1, const float* src2, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vadd (src1, 1, src2, 1, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] + src2[i], Mode::add (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, )
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::add (double* dest, const double* src1, const double* src2, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vaddD (src1, 1, src2, 1, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] + src2[i], Mode::add (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, )
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::subtract (float* dest, const float* src, int num) noexcept void JUCE_CALLTYPE FloatVectorOperations::subtract (float* dest, const float* src, int num) noexcept
{ {
#if JUCE_USE_VDSP_FRAMEWORK #if JUCE_USE_VDSP_FRAMEWORK
@ -479,6 +548,24 @@ void JUCE_CALLTYPE FloatVectorOperations::subtract (double* dest, const double*
#endif #endif
} }
void JUCE_CALLTYPE FloatVectorOperations::subtract (float* dest, const float* src1, const float* src2, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vsub (src2, 1, src1, 1, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] - src2[i], Mode::sub (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, )
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::subtract (double* dest, const double* src1, const double* src2, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vsubD (src2, 1, src1, 1, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] - src2[i], Mode::sub (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, )
#endif
}
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
{ {
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] += src[i] * multiplier, Mode::add (d, Mode::mul (mult, s)), JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] += src[i] * multiplier, Mode::add (d, Mode::mul (mult, s)),
@ -511,6 +598,24 @@ void JUCE_CALLTYPE FloatVectorOperations::multiply (double* dest, const double*
#endif #endif
} }
void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, const float* src1, const float* src2, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vmul (src1, 1, src2, 1, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] * src2[i], Mode::mul (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, )
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::multiply (double* dest, const double* src1, const double* src2, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vmulD (src1, 1, src2, 1, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] * src2[i], Mode::mul (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, )
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, float multiplier, int num) noexcept void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, float multiplier, int num) noexcept
{ {
#if JUCE_USE_VDSP_FRAMEWORK #if JUCE_USE_VDSP_FRAMEWORK
@ -531,6 +636,20 @@ void JUCE_CALLTYPE FloatVectorOperations::multiply (double* dest, double multipl
#endif #endif
} }
void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, const float* src, float multiplier, int num) noexcept
{
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] * multiplier, Mode::mul (mult, s),
JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
const Mode::ParallelType mult = Mode::load1 (multiplier);)
}
void JUCE_CALLTYPE FloatVectorOperations::multiply (double* dest, const double* src, double multiplier, int num) noexcept
{
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] * multiplier, Mode::mul (mult, s),
JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
const Mode::ParallelType mult = Mode::load1 (multiplier);)
}
void FloatVectorOperations::negate (float* dest, const float* src, int num) noexcept void FloatVectorOperations::negate (float* dest, const float* src, int num) noexcept
{ {
#if JUCE_USE_VDSP_FRAMEWORK #if JUCE_USE_VDSP_FRAMEWORK

@ -65,18 +65,36 @@ public:
/** Adds a fixed value to the destination values. */ /** Adds a fixed value to the destination values. */
static void JUCE_CALLTYPE add (double* dest, double amountToAdd, int numValues) noexcept; static void JUCE_CALLTYPE add (double* dest, double amountToAdd, int numValues) noexcept;
/** Adds a fixed value to each source value and stores it in the destination array. */
static void JUCE_CALLTYPE add (float* dest, float* src, float amount, int numValues) noexcept;
/** Adds a fixed value to each source value and stores it in the destination array. */
static void JUCE_CALLTYPE add (double* dest, double* src, double 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 the source values to the destination values. */ /** Adds the source values to the destination values. */
static void JUCE_CALLTYPE add (double* dest, const double* src, int numValues) noexcept; static void JUCE_CALLTYPE add (double* dest, const double* src, int numValues) noexcept;
/** Adds each source1 value to the corresponding source2 value and stores the result in the destination array. */
static void JUCE_CALLTYPE add (float* dest, const float* src1, const float* src2, int num) noexcept;
/** Adds each source1 value to the corresponding source2 value and stores the result in the destination array. */
static void JUCE_CALLTYPE add (double* dest, const double* src1, const double* src2, int num) noexcept;
/** Subtracts the source values from the destination values. */ /** Subtracts the source values from the destination values. */
static void JUCE_CALLTYPE subtract (float* dest, const float* src, int numValues) noexcept; static void JUCE_CALLTYPE subtract (float* dest, const float* src, int numValues) noexcept;
/** Subtracts the source values from the destination values. */ /** Subtracts the source values from the destination values. */
static void JUCE_CALLTYPE subtract (double* dest, const double* src, int numValues) noexcept; static void JUCE_CALLTYPE subtract (double* dest, const double* src, int numValues) noexcept;
/** Subtracts each source2 value from the corresponding source1 value and stores the result in the destination array. */
static void JUCE_CALLTYPE subtract (float* dest, const float* src1, const float* src2, int num) noexcept;
/** Subtracts each source2 value from the corresponding source1 value and stores the result in the destination array. */
static void JUCE_CALLTYPE subtract (double* dest, const double* src1, const double* src2, int num) 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;
@ -89,12 +107,24 @@ public:
/** Multiplies the destination values by the source values. */ /** Multiplies the destination values by the source values. */
static void JUCE_CALLTYPE multiply (double* dest, const double* src, int numValues) noexcept; static void JUCE_CALLTYPE multiply (double* dest, const double* src, int numValues) noexcept;
/** Multiplies each source1 value by the correspinding source2 value, then stores it in the destination array. */
static void JUCE_CALLTYPE multiply (float* dest, const float* src1, const float* src2, int numValues) noexcept;
/** Multiplies each source1 value by the correspinding source2 value, then stores it in the destination array. */
static void JUCE_CALLTYPE multiply (double* dest, const double* src1, const double* src2, int numValues) noexcept;
/** Multiplies each of the destination values by a fixed multiplier. */ /** Multiplies each of the destination values by a fixed multiplier. */
static void JUCE_CALLTYPE multiply (float* dest, float multiplier, int numValues) noexcept; static void JUCE_CALLTYPE multiply (float* dest, float multiplier, int numValues) noexcept;
/** Multiplies each of the destination values by a fixed multiplier. */ /** Multiplies each of the destination values by a fixed multiplier. */
static void JUCE_CALLTYPE multiply (double* dest, double multiplier, int numValues) noexcept; static void JUCE_CALLTYPE multiply (double* dest, double multiplier, int numValues) noexcept;
/** Multiplies each of the source values by a fixed multiplier and stores the result in the destination array. */
static void JUCE_CALLTYPE multiply (float* dest, const float* src, float multiplier, int num) noexcept;
/** Multiplies each of the source values by a fixed multiplier and stores the result in the destination array. */
static void JUCE_CALLTYPE multiply (double* dest, const double* src, double multiplier, int num) noexcept;
/** Copies a source vector to a destination, negating each value. */ /** Copies a source vector to a destination, negating each value. */
static void JUCE_CALLTYPE negate (float* dest, const float* src, int numValues) noexcept; static void JUCE_CALLTYPE negate (float* dest, const float* src, int numValues) noexcept;

@ -230,7 +230,8 @@ void ResamplingAudioSource::setFilterCoefficients (double c1, double c2, double
void ResamplingAudioSource::resetFilters() void ResamplingAudioSource::resetFilters()
{ {
filterStates.clear ((size_t) numChannels); if (filterStates != nullptr)
filterStates.clear ((size_t) numChannels);
} }
void ResamplingAudioSource::applyFilter (float* samples, int num, FilterState& fs) void ResamplingAudioSource::applyFilter (float* samples, int num, FilterState& fs)

@ -163,10 +163,7 @@ void Synthesiser::renderNextBlock (AudioSampleBuffer& outputBuffer, const MidiBu
: numSamples; : numSamples;
if (numThisTime > 0) if (numThisTime > 0)
{ renderVoices (outputBuffer, startSample, numThisTime);
for (int i = voices.size(); --i >= 0;)
voices.getUnchecked (i)->renderNextBlock (outputBuffer, startSample, numThisTime);
}
if (useEvent) if (useEvent)
handleMidiEvent (m); handleMidiEvent (m);
@ -176,6 +173,12 @@ void Synthesiser::renderNextBlock (AudioSampleBuffer& outputBuffer, const MidiBu
} }
} }
void Synthesiser::renderVoices (AudioSampleBuffer& buffer, int startSample, int numSamples)
{
for (int i = voices.size(); --i >= 0;)
voices.getUnchecked (i)->renderNextBlock (buffer, startSample, numSamples);
}
void Synthesiser::handleMidiEvent (const MidiMessage& m) void Synthesiser::handleMidiEvent (const MidiMessage& m)
{ {
if (m.isNoteOn()) if (m.isNoteOn())
@ -184,7 +187,7 @@ void Synthesiser::handleMidiEvent (const MidiMessage& m)
} }
else if (m.isNoteOff()) else if (m.isNoteOff())
{ {
noteOff (m.getChannel(), m.getNoteNumber(), true); noteOff (m.getChannel(), m.getNoteNumber(), m.getFloatVelocity(), true);
} }
else if (m.isAllNotesOff() || m.isAllSoundOff()) else if (m.isAllNotesOff() || m.isAllSoundOff())
{ {
@ -230,10 +233,10 @@ void Synthesiser::noteOn (const int midiChannel,
if (voice->getCurrentlyPlayingNote() == midiNoteNumber if (voice->getCurrentlyPlayingNote() == midiNoteNumber
&& voice->isPlayingChannel (midiChannel)) && voice->isPlayingChannel (midiChannel))
stopVoice (voice, true); stopVoice (voice, 1.0f, true);
} }
startVoice (findFreeVoice (sound, shouldStealNotes), startVoice (findFreeVoice (sound, midiChannel, midiNoteNumber, shouldStealNotes),
sound, midiChannel, midiNoteNumber, velocity); sound, midiChannel, midiNoteNumber, velocity);
} }
} }
@ -248,7 +251,7 @@ void Synthesiser::startVoice (SynthesiserVoice* const voice,
if (voice != nullptr && sound != nullptr) if (voice != nullptr && sound != nullptr)
{ {
if (voice->currentlyPlayingSound != nullptr) if (voice->currentlyPlayingSound != nullptr)
voice->stopNote (false); voice->stopNote (0.0f, false);
voice->startNote (midiNoteNumber, velocity, sound, voice->startNote (midiNoteNumber, velocity, sound,
lastPitchWheelValues [midiChannel - 1]); lastPitchWheelValues [midiChannel - 1]);
@ -261,11 +264,11 @@ void Synthesiser::startVoice (SynthesiserVoice* const voice,
} }
} }
void Synthesiser::stopVoice (SynthesiserVoice* voice, const bool allowTailOff) void Synthesiser::stopVoice (SynthesiserVoice* voice, float velocity, const bool allowTailOff)
{ {
jassert (voice != nullptr); jassert (voice != nullptr);
voice->stopNote (allowTailOff); voice->stopNote (velocity, allowTailOff);
// the subclass MUST call clearCurrentNote() if it's not tailing off! RTFM for stopNote()! // the subclass MUST call clearCurrentNote() if it's not tailing off! RTFM for stopNote()!
jassert (allowTailOff || (voice->getCurrentlyPlayingNote() < 0 && voice->getCurrentlyPlayingSound() == 0)); jassert (allowTailOff || (voice->getCurrentlyPlayingNote() < 0 && voice->getCurrentlyPlayingSound() == 0));
@ -273,6 +276,7 @@ void Synthesiser::stopVoice (SynthesiserVoice* voice, const bool allowTailOff)
void Synthesiser::noteOff (const int midiChannel, void Synthesiser::noteOff (const int midiChannel,
const int midiNoteNumber, const int midiNoteNumber,
const float velocity,
const bool allowTailOff) const bool allowTailOff)
{ {
const ScopedLock sl (lock); const ScopedLock sl (lock);
@ -291,7 +295,7 @@ void Synthesiser::noteOff (const int midiChannel,
voice->keyIsDown = false; voice->keyIsDown = false;
if (! (sustainPedalsDown [midiChannel] || voice->sostenutoPedalDown)) if (! (sustainPedalsDown [midiChannel] || voice->sostenutoPedalDown))
stopVoice (voice, allowTailOff); stopVoice (voice, velocity, allowTailOff);
} }
} }
} }
@ -307,7 +311,7 @@ void Synthesiser::allNotesOff (const int midiChannel, const bool allowTailOff)
SynthesiserVoice* const voice = voices.getUnchecked (i); SynthesiserVoice* const voice = voices.getUnchecked (i);
if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel)) if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel))
voice->stopNote (allowTailOff); voice->stopNote (1.0f, allowTailOff);
} }
sustainPedalsDown.clear(); sustainPedalsDown.clear();
@ -379,7 +383,7 @@ void Synthesiser::handleSustainPedal (int midiChannel, bool isDown)
SynthesiserVoice* const voice = voices.getUnchecked (i); SynthesiserVoice* const voice = voices.getUnchecked (i);
if (voice->isPlayingChannel (midiChannel) && ! voice->keyIsDown) if (voice->isPlayingChannel (midiChannel) && ! voice->keyIsDown)
stopVoice (voice, true); stopVoice (voice, 1.0f, true);
} }
sustainPedalsDown.clearBit (midiChannel); sustainPedalsDown.clearBit (midiChannel);
@ -400,7 +404,7 @@ void Synthesiser::handleSostenutoPedal (int midiChannel, bool isDown)
if (isDown) if (isDown)
voice->sostenutoPedalDown = true; voice->sostenutoPedalDown = true;
else if (voice->sostenutoPedalDown) else if (voice->sostenutoPedalDown)
stopVoice (voice, true); stopVoice (voice, 1.0f, true);
} }
} }
} }
@ -412,7 +416,9 @@ void Synthesiser::handleSoftPedal (int midiChannel, bool /*isDown*/)
} }
//============================================================================== //==============================================================================
SynthesiserVoice* Synthesiser::findFreeVoice (SynthesiserSound* soundToPlay, const bool stealIfNoneAvailable) const SynthesiserVoice* Synthesiser::findFreeVoice (SynthesiserSound* soundToPlay,
int midiChannel, int midiNoteNumber,
const bool stealIfNoneAvailable) const
{ {
const ScopedLock sl (lock); const ScopedLock sl (lock);
@ -425,25 +431,68 @@ SynthesiserVoice* Synthesiser::findFreeVoice (SynthesiserSound* soundToPlay, con
} }
if (stealIfNoneAvailable) if (stealIfNoneAvailable)
return findVoiceToSteal (soundToPlay); return findVoiceToSteal (soundToPlay, midiChannel, midiNoteNumber);
return nullptr; return nullptr;
} }
SynthesiserVoice* Synthesiser::findVoiceToSteal (SynthesiserSound* soundToPlay) const struct VoiceAgeSorter
{
static int compareElements (SynthesiserVoice* v1, SynthesiserVoice* v2) noexcept
{
return v1->wasStartedBefore (*v2) ? 1 : (v2->wasStartedBefore (*v1) ? -1 : 0);
}
};
SynthesiserVoice* Synthesiser::findVoiceToSteal (SynthesiserSound* soundToPlay,
int /*midiChannel*/, int midiNoteNumber) const
{ {
// currently this just steals the one that's been playing the longest, but could be made a bit smarter.. SynthesiserVoice* bottom = nullptr;
SynthesiserVoice* oldest = nullptr; SynthesiserVoice* top = nullptr;
// this is a list of voices we can steal, sorted by how long they've been running
Array<SynthesiserVoice*> usableVoices;
usableVoices.ensureStorageAllocated (voices.size());
for (int i = 0; i < voices.size(); ++i) for (int i = 0; i < voices.size(); ++i)
{ {
SynthesiserVoice* const voice = voices.getUnchecked (i); SynthesiserVoice* const voice = voices.getUnchecked (i);
if (voice->canPlaySound (soundToPlay) if (voice->canPlaySound (soundToPlay))
&& (oldest == nullptr || voice->wasStartedBefore (*oldest))) {
oldest = voice; VoiceAgeSorter sorter;
usableVoices.addSorted (sorter, voice);
const int note = voice->getCurrentlyPlayingNote();
if (bottom == nullptr || note < bottom->getCurrentlyPlayingNote())
bottom = voice;
if (top == nullptr || note > top->getCurrentlyPlayingNote())
top = voice;
}
}
jassert (bottom != nullptr && top != nullptr);
// The oldest note that's playing with the target pitch playing is ideal..
for (int i = 0; i < usableVoices.size(); ++i)
{
SynthesiserVoice* const voice = usableVoices.getUnchecked (i);
if (voice->getCurrentlyPlayingNote() == midiNoteNumber)
return voice;
}
// ..otherwise, look for the oldest note that isn't the top or bottom note..
for (int i = 0; i < usableVoices.size(); ++i)
{
SynthesiserVoice* const voice = usableVoices.getUnchecked (i);
if (voice != bottom && voice != top)
return voice;
} }
jassert (oldest != nullptr); // ..otherwise, there's only one or two voices to choose from - we'll return the top one..
return oldest; return top;
} }

@ -55,14 +55,14 @@ public:
The Synthesiser will use this information when deciding which sounds to trigger The Synthesiser will use this information when deciding which sounds to trigger
for a given note. for a given note.
*/ */
virtual bool appliesToNote (const int midiNoteNumber) = 0; virtual bool appliesToNote (int midiNoteNumber) = 0;
/** Returns true if the sound should be triggered by midi events on a given channel. /** Returns true if the sound should be triggered by midi events on a given channel.
The Synthesiser will use this information when deciding which sounds to trigger The Synthesiser will use this information when deciding which sounds to trigger
for a given note. for a given note.
*/ */
virtual bool appliesToChannel (const int midiChannel) = 0; virtual bool appliesToChannel (int midiChannel) = 0;
/** The class is reference-counted, so this is a handy pointer class for it. */ /** The class is reference-counted, so this is a handy pointer class for it. */
typedef ReferenceCountedObjectPtr<SynthesiserSound> Ptr; typedef ReferenceCountedObjectPtr<SynthesiserSound> Ptr;
@ -127,6 +127,8 @@ public:
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.
The velocity indicates how quickly the note was released - 0 is slowly, 1 is quickly.
If allowTailOff is false or the voice doesn't want to tail-off, then it must stop all If allowTailOff is false or the voice doesn't want to tail-off, then it must stop all
sound immediately, and must call clearCurrentNote() to reset the state of this voice sound immediately, and must call clearCurrentNote() to reset the state of this voice
and allow the synth to reassign it another sound. and allow the synth to reassign it another sound.
@ -136,7 +138,7 @@ public:
finishes playing (during the rendering callback), it must make sure that it calls finishes playing (during the rendering callback), it must make sure that it calls
clearCurrentNote(). clearCurrentNote().
*/ */
virtual void stopNote (bool allowTailOff) = 0; virtual void stopNote (float velocity, bool allowTailOff) = 0;
/** 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.
@ -183,6 +185,11 @@ public:
*/ */
virtual void setCurrentPlaybackSampleRate (double newRate); virtual void setCurrentPlaybackSampleRate (double newRate);
/** Returns the current target sample rate at which rendering is being done.
Subclasses may need to know this so that they can pitch things correctly.
*/
double getSampleRate() const noexcept { return currentSampleRate; }
/** Returns true if the voice is currently playing a sound which is mapped to the given /** Returns true if the voice is currently playing a sound which is mapped to the given
midi channel. midi channel.
@ -203,13 +210,6 @@ public:
bool wasStartedBefore (const SynthesiserVoice& other) const noexcept; bool wasStartedBefore (const SynthesiserVoice& other) const noexcept;
protected: protected:
//==============================================================================
/** Returns the current target sample rate at which rendering is being done.
This is available for subclasses so they can pitch things correctly.
*/
double getSampleRate() const { return currentSampleRate; }
/** Resets the state of this voice after a sound has finished playing. /** Resets the state of this voice after a sound has finished playing.
The subclass must call this when it finishes playing a note and becomes available The subclass must call this when it finishes playing a note and becomes available
@ -235,6 +235,11 @@ private:
SynthesiserSound::Ptr currentlyPlayingSound; SynthesiserSound::Ptr currentlyPlayingSound;
bool keyIsDown, sostenutoPedalDown; bool keyIsDown, sostenutoPedalDown;
#if JUCE_CATCH_DEPRECATED_CODE_MISUSE
// Note the new parameters for this method.
virtual int stopNote (bool) { return 0; }
#endif
JUCE_LEAK_DETECTOR (SynthesiserVoice) JUCE_LEAK_DETECTOR (SynthesiserVoice)
}; };
@ -268,8 +273,7 @@ class JUCE_API Synthesiser
public: public:
//============================================================================== //==============================================================================
/** Creates a new synthesiser. /** Creates a new synthesiser.
You'll need to add some sounds and voices before it'll make any sound.
You'll need to add some sounds and voices before it'll make any sound..
*/ */
Synthesiser(); Synthesiser();
@ -365,6 +369,7 @@ public:
*/ */
virtual void noteOff (int midiChannel, virtual void noteOff (int midiChannel,
int midiNoteNumber, int midiNoteNumber,
float velocity,
bool allowTailOff); bool allowTailOff);
/** Turns off all notes. /** Turns off all notes.
@ -463,6 +468,11 @@ public:
int startSample, int startSample,
int numSamples); int numSamples);
/** Returns the current target sample rate at which rendering is being done.
Subclasses may need to know this so that they can pitch things correctly.
*/
double getSampleRate() const noexcept { return sampleRate; }
protected: protected:
//============================================================================== //==============================================================================
/** This is used to control access to the rendering callback and the note trigger methods. */ /** This is used to control access to the rendering callback and the note trigger methods. */
@ -474,21 +484,34 @@ protected:
/** The last pitch-wheel values for each midi channel. */ /** The last pitch-wheel values for each midi channel. */
int lastPitchWheelValues [16]; int lastPitchWheelValues [16];
/** Searches through the voices to find one that's not currently playing, and which /** Renders the voices for the given range.
can play the given sound. By default this just calls renderNextBlock() on each voice, but you may need
to override it to handle custom cases.
*/
virtual void renderVoices (AudioSampleBuffer& outputAudio,
int startSample, int numSamples);
/** Searches through the voices to find one that's not currently playing, and
which can play the given sound.
Returns nullptr if all voices are busy and stealing isn't enabled. Returns nullptr if all voices are busy and stealing isn't enabled.
This can be overridden to implement custom voice-stealing algorithms. To implement a custom note-stealing algorithm, you can either override this
method, or (preferably) override findVoiceToSteal().
*/ */
virtual SynthesiserVoice* findFreeVoice (SynthesiserSound* soundToPlay, virtual SynthesiserVoice* findFreeVoice (SynthesiserSound* soundToPlay,
const bool stealIfNoneAvailable) const; int midiChannel,
int midiNoteNumber,
bool stealIfNoneAvailable) const;
/** Chooses a voice that is most suitable for being re-used. /** Chooses a voice that is most suitable for being re-used.
The default method returns the one that has been playing for the longest, but The default method will attempt to find the oldest voice that isn't the
you may want to override this and do something more cunning instead. bottom or top note being played. If that's not suitable for your synth,
you can override this method and do something more cunning instead.
*/ */
virtual SynthesiserVoice* findVoiceToSteal (SynthesiserSound* soundToPlay) const; virtual SynthesiserVoice* findVoiceToSteal (SynthesiserSound* soundToPlay,
int midiChannel,
int midiNoteNumber) const;
/** Starts a specified voice playing a particular sound. /** Starts a specified voice playing a particular sound.
@ -511,11 +534,14 @@ private:
bool shouldStealNotes; bool shouldStealNotes;
BigInteger sustainPedalsDown; BigInteger sustainPedalsDown;
void stopVoice (SynthesiserVoice*, bool allowTailOff); void stopVoice (SynthesiserVoice*, float velocity, bool allowTailOff);
#if JUCE_CATCH_DEPRECATED_CODE_MISUSE #if JUCE_CATCH_DEPRECATED_CODE_MISUSE
// Note the new parameters for this method. // Note the new parameters for these methods.
virtual int findFreeVoice (const bool) const { return 0; } virtual int findFreeVoice (const bool) const { return 0; }
virtual int noteOff (int, int, int) { return 0; }
virtual int findFreeVoice (SynthesiserSound*, const bool) { return 0; }
virtual int findVoiceToSteal (SynthesiserSound*) const { return 0; }
#endif #endif
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Synthesiser) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Synthesiser)

@ -41,7 +41,7 @@ namespace
return err; return err;
} }
#else #else
#define JUCE_ALSA_LOG(x) #define JUCE_ALSA_LOG(x) {}
#define JUCE_CHECKED_RESULT(x) (x) #define JUCE_CHECKED_RESULT(x) (x)
#endif #endif

@ -472,6 +472,46 @@ namespace WavFileHelpers
} }
} }
//==============================================================================
namespace ListInfoChunk
{
static bool writeValue (const StringPairArray& values, MemoryOutputStream& out, const char* paramName)
{
const String value (values.getValue (paramName, String()));
if (value.isEmpty())
return false;
const int valueLength = (int) value.getNumBytesAsUTF8() + 1;
const int chunkLength = valueLength + (valueLength & 1);
out.writeInt (chunkName (paramName));
out.writeInt (chunkLength);
out.write (value.toUTF8(), (size_t) valueLength);
if ((out.getDataSize() & 1) != 0)
out.writeByte (0);
return true;
}
static MemoryBlock createFrom (const StringPairArray& values)
{
static const char* params[] = { "INAM", "IART", "IPRD", "IPRT", "ISFT",
"ISRC", "IGNR", "ICMT", "ICOP", "ICRD" };
MemoryOutputStream out;
out.writeInt (chunkName ("INFO"));
bool anyParamsDefined = false;
for (int i = 0; i < numElementsInArray (params); ++i)
if (writeValue (values, out, params[i]))
anyParamsDefined = true;
return anyParamsDefined ? out.getMemoryBlock() : MemoryBlock();
}
}
//============================================================================== //==============================================================================
struct AcidChunk struct AcidChunk
{ {
@ -987,14 +1027,15 @@ public:
// key should be removed (or set to "WAV") once this has been done // key should be removed (or set to "WAV") once this has been done
jassert (metadataValues.getValue ("MetaDataSource", "None") != "AIFF"); jassert (metadataValues.getValue ("MetaDataSource", "None") != "AIFF");
bwavChunk = BWAVChunk::createFrom (metadataValues); bwavChunk = BWAVChunk::createFrom (metadataValues);
axmlChunk = AXMLChunk::createFrom (metadataValues); axmlChunk = AXMLChunk::createFrom (metadataValues);
smplChunk = SMPLChunk::createFrom (metadataValues); smplChunk = SMPLChunk::createFrom (metadataValues);
instChunk = InstChunk::createFrom (metadataValues); instChunk = InstChunk::createFrom (metadataValues);
cueChunk = CueChunk ::createFrom (metadataValues); cueChunk = CueChunk ::createFrom (metadataValues);
listChunk = ListChunk::createFrom (metadataValues); listChunk = ListChunk::createFrom (metadataValues);
acidChunk = AcidChunk::createFrom (metadataValues); listInfoChunk = ListInfoChunk::createFrom (metadataValues);
trckChunk = TracktionChunk::createFrom (metadataValues); acidChunk = AcidChunk::createFrom (metadataValues);
trckChunk = TracktionChunk::createFrom (metadataValues);
} }
headerPosition = out->getPosition(); headerPosition = out->getPosition();
@ -1057,7 +1098,7 @@ public:
} }
private: private:
MemoryBlock tempBlock, bwavChunk, axmlChunk, smplChunk, instChunk, cueChunk, listChunk, acidChunk, trckChunk; MemoryBlock tempBlock, bwavChunk, axmlChunk, smplChunk, instChunk, cueChunk, listChunk, listInfoChunk, acidChunk, trckChunk;
uint64 lengthInSamples, bytesWritten; uint64 lengthInSamples, bytesWritten;
int64 headerPosition; int64 headerPosition;
bool writeFailed; bool writeFailed;
@ -1109,6 +1150,7 @@ private:
+ chunkSize (instChunk) + chunkSize (instChunk)
+ chunkSize (cueChunk) + chunkSize (cueChunk)
+ chunkSize (listChunk) + chunkSize (listChunk)
+ chunkSize (listInfoChunk)
+ chunkSize (acidChunk) + chunkSize (acidChunk)
+ chunkSize (trckChunk) + chunkSize (trckChunk)
+ (8 + 28)); // (ds64 chunk) + (8 + 28)); // (ds64 chunk)
@ -1184,14 +1226,15 @@ private:
output->write (subFormat.data4, sizeof (subFormat.data4)); output->write (subFormat.data4, sizeof (subFormat.data4));
} }
writeChunk (bwavChunk, chunkName ("bext")); writeChunk (bwavChunk, chunkName ("bext"));
writeChunk (axmlChunk, chunkName ("axml")); writeChunk (axmlChunk, chunkName ("axml"));
writeChunk (smplChunk, chunkName ("smpl")); writeChunk (smplChunk, chunkName ("smpl"));
writeChunk (instChunk, chunkName ("inst"), 7); writeChunk (instChunk, chunkName ("inst"), 7);
writeChunk (cueChunk, chunkName ("cue ")); writeChunk (cueChunk, chunkName ("cue "));
writeChunk (listChunk, chunkName ("LIST")); writeChunk (listChunk, chunkName ("LIST"));
writeChunk (acidChunk, chunkName ("acid")); writeChunk (listInfoChunk, chunkName ("LIST"));
writeChunk (trckChunk, chunkName ("Trkn")); writeChunk (acidChunk, chunkName ("acid"));
writeChunk (trckChunk, chunkName ("Trkn"));
writeChunkHeader (chunkName ("data"), isRF64 ? -1 : (int) (lengthInSamples * bytesPerFrame)); writeChunkHeader (chunkName ("data"), isRF64 ? -1 : (int) (lengthInSamples * bytesPerFrame));

@ -59,12 +59,12 @@ SamplerSound::~SamplerSound()
{ {
} }
bool SamplerSound::appliesToNote (const int midiNoteNumber) bool SamplerSound::appliesToNote (int midiNoteNumber)
{ {
return midiNotes [midiNoteNumber]; return midiNotes [midiNoteNumber];
} }
bool SamplerSound::appliesToChannel (const int /*midiChannel*/) bool SamplerSound::appliesToChannel (int /*midiChannel*/)
{ {
return true; return true;
} }
@ -127,7 +127,7 @@ void SamplerVoice::startNote (const int midiNoteNumber,
} }
} }
void SamplerVoice::stopNote (const bool allowTailOff) void SamplerVoice::stopNote (float /*velocity*/, bool allowTailOff)
{ {
if (allowTailOff) if (allowTailOff)
{ {
@ -197,7 +197,7 @@ void SamplerVoice::renderNextBlock (AudioSampleBuffer& outputBuffer, int startSa
if (attackReleaseLevel <= 0.0f) if (attackReleaseLevel <= 0.0f)
{ {
stopNote (false); stopNote (0.0f, false);
break; break;
} }
} }
@ -216,7 +216,7 @@ void SamplerVoice::renderNextBlock (AudioSampleBuffer& outputBuffer, int startSa
if (sourceSamplePosition > playingSound->length) if (sourceSamplePosition > playingSound->length)
{ {
stopNote (false); stopNote (0.0f, false);
break; break;
} }
} }

@ -82,8 +82,8 @@ public:
//============================================================================== //==============================================================================
bool appliesToNote (const int midiNoteNumber) override; bool appliesToNote (int midiNoteNumber) override;
bool appliesToChannel (const int midiChannel) override; bool appliesToChannel (int midiChannel) override;
private: private:
@ -124,7 +124,7 @@ public:
bool canPlaySound (SynthesiserSound*) override; bool canPlaySound (SynthesiserSound*) override;
void startNote (int midiNoteNumber, float velocity, SynthesiserSound*, int pitchWheel) override; void startNote (int midiNoteNumber, float velocity, SynthesiserSound*, int pitchWheel) override;
void stopNote (bool allowTailOff) override; void stopNote (float velocity, bool allowTailOff) override;
void pitchWheelMoved (int newValue); void pitchWheelMoved (int newValue);
void controllerMoved (int controllerNumber, int newValue) override; void controllerMoved (int controllerNumber, int newValue) override;

@ -308,7 +308,7 @@ struct AAXClasses
} }
} }
virtual AAX_Result GetViewSize (AAX_Point* viewSize) const override AAX_Result GetViewSize (AAX_Point* viewSize) const override
{ {
if (component != nullptr) if (component != nullptr)
{ {
@ -792,6 +792,9 @@ struct AAXClasses
if (lastBufferSize != bufferSize) if (lastBufferSize != bufferSize)
{ {
lastBufferSize = bufferSize; lastBufferSize = bufferSize;
pluginInstance->setPlayConfigDetails (pluginInstance->getNumInputChannels(),
pluginInstance->getNumOutputChannels(),
sampleRate, bufferSize);
pluginInstance->prepareToPlay (sampleRate, bufferSize); pluginInstance->prepareToPlay (sampleRate, bufferSize);
} }
@ -998,7 +1001,10 @@ struct AAXClasses
// This value needs to match the RTAS wrapper's Type ID, so that // This value needs to match the RTAS wrapper's Type ID, so that
// the host knows that the RTAS/AAX plugins are equivalent. // the host knows that the RTAS/AAX plugins are equivalent.
properties->AddProperty (AAX_eProperty_PlugInID_Native, 'jcaa' + channelConfigIndex); properties->AddProperty (AAX_eProperty_PlugInID_Native, 'jcaa' + channelConfigIndex);
#if ! JucePlugin_AAXDisableAudioSuite
properties->AddProperty (AAX_eProperty_PlugInID_AudioSuite, 'jyaa' + channelConfigIndex); properties->AddProperty (AAX_eProperty_PlugInID_AudioSuite, 'jyaa' + channelConfigIndex);
#endif
#if JucePlugin_AAXDisableMultiMono #if JucePlugin_AAXDisableMultiMono
properties->AddProperty (AAX_eProperty_Constraint_MultiMonoSupport, false); properties->AddProperty (AAX_eProperty_Constraint_MultiMonoSupport, false);

@ -144,13 +144,16 @@ namespace juce
namespace namespace
{ {
HWND findMDIParentOf (HWND w) // Returns the actual container window, unlike GetParent, which can also return a separate owner window.
static HWND getWindowParent (HWND w) noexcept { return GetAncestor (w, GA_PARENT); }
static HWND findMDIParentOf (HWND w)
{ {
const int frameThickness = GetSystemMetrics (SM_CYFIXEDFRAME); const int frameThickness = GetSystemMetrics (SM_CYFIXEDFRAME);
while (w != 0) while (w != 0)
{ {
HWND parent = GetParent (w); HWND parent = getWindowParent (w);
if (parent == 0) if (parent == 0)
break; break;
@ -1244,7 +1247,7 @@ public:
while (w != 0) while (w != 0)
{ {
HWND parent = GetParent (w); HWND parent = getWindowParent (w);
if (parent == 0) if (parent == 0)
break; break;

@ -152,7 +152,7 @@ void* attachComponentToWindowRef (Component* comp, void* parentWindowOrView, boo
#endif #endif
(void) isNSView; (void) isNSView;
NSView* parentView = (NSView*) parentWindowOrView; NSView* parentView = [(NSView*) parentWindowOrView retain];
#if JucePlugin_EditorRequiresKeyboardFocus #if JucePlugin_EditorRequiresKeyboardFocus
comp->addToDesktop (0, parentView); comp->addToDesktop (0, parentView);
@ -219,8 +219,9 @@ void detachComponentFromWindowRef (Component* comp, void* window, bool isNSView)
} }
#endif #endif
(void) isNSView; (void) window; (void) isNSView;
comp->removeFromDesktop(); comp->removeFromDesktop();
[(id) window release];
} }
} }

@ -729,7 +729,7 @@ public:
tresult PLUGIN_API setActive (TBool state) override tresult PLUGIN_API setActive (TBool state) override
{ {
if (state == kResultFalse) if (! state)
{ {
getPluginInstance().releaseResources(); getPluginInstance().releaseResources();
} }
@ -1172,7 +1172,7 @@ public:
tresult PLUGIN_API setProcessing (TBool state) override tresult PLUGIN_API setProcessing (TBool state) override
{ {
if (state == kResultFalse) if (! state)
getPluginInstance().reset(); getPluginInstance().reset();
return kResultTrue; return kResultTrue;

@ -128,7 +128,8 @@ String AudioProcessor::getParameterText (int parameterIndex, int maximumStringLe
return getParameterText (parameterIndex).substring (0, maximumStringLength); return getParameterText (parameterIndex).substring (0, maximumStringLength);
} }
int AudioProcessor::getParameterNumSteps (int /*parameterIndex*/) { return 0x7fffffff; } int AudioProcessor::getDefaultNumParameterSteps() noexcept { return 0x7fffffff; }
int AudioProcessor::getParameterNumSteps (int /*parameterIndex*/) { return getDefaultNumParameterSteps(); }
float AudioProcessor::getParameterDefaultValue (int /*parameterIndex*/) { return 0.0f; } float AudioProcessor::getParameterDefaultValue (int /*parameterIndex*/) { return 0.0f; }
AudioProcessorListener* AudioProcessor::getListenerLocked (const int index) const noexcept AudioProcessorListener* AudioProcessor::getListenerLocked (const int index) const noexcept

@ -414,12 +414,18 @@ public:
virtual String getParameterText (int parameterIndex, int maximumStringLength); virtual String getParameterText (int parameterIndex, int maximumStringLength);
/** Returns the number of discrete steps that this parameter can represent. /** Returns the number of discrete steps that this parameter can represent.
The default return value if you don't implement this method is 0x7fffffff. The default return value if you don't implement this method is
AudioProcessor::getDefaultNumParameterSteps().
If your parameter is boolean, then you may want to make this return 2. If your parameter is boolean, then you may want to make this return 2.
The value that is returned may or may not be used, depending on the host. The value that is returned may or may not be used, depending on the host.
*/ */
virtual int getParameterNumSteps (int parameterIndex); virtual int getParameterNumSteps (int parameterIndex);
/** Returns the default number of steps for a parameter.
@see getParameterNumSteps
*/
static int getDefaultNumParameterSteps() noexcept;
/** Returns the default value for the parameter. /** Returns the default value for the parameter.
By default, this just returns 0. By default, this just returns 0.
The value that is returned may or may not be used, depending on the host. The value that is returned may or may not be used, depending on the host.

@ -830,7 +830,7 @@ public:
This will use a comparator object to sort the elements into order. The object This will use a comparator object to sort the elements into order. The object
passed must have a method of the form: passed must have a method of the form:
@code @code
int compareElements (ElementType first, ElementType second); int compareElements (ElementType* first, ElementType* second);
@endcode @endcode
..and this method must return: ..and this method must return:

@ -102,6 +102,7 @@ struct JavascriptEngine::RootObject : public DynamicObject
static bool isNumericOrUndefined (const var& v) { return v.isInt() || v.isDouble() || v.isInt64() || v.isBool() || v.isUndefined(); } static bool isNumericOrUndefined (const var& v) { return v.isInt() || v.isDouble() || v.isInt64() || v.isBool() || v.isUndefined(); }
static int64 getOctalValue (const String& s) { BigInteger b; b.parseString (s, 8); return b.toInt64(); } static int64 getOctalValue (const String& s) { BigInteger b; b.parseString (s, 8); return b.toInt64(); }
static Identifier getPrototypeIdentifier() { static const Identifier i ("prototype"); return i; } static Identifier getPrototypeIdentifier() { static const Identifier i ("prototype"); return i; }
static var* getPropertyPointer (DynamicObject* o, Identifier i) { return o->getProperties().getVarPointer (i); }
//============================================================================== //==============================================================================
struct CodeLocation struct CodeLocation
@ -139,13 +140,13 @@ struct JavascriptEngine::RootObject : public DynamicObject
{ {
if (DynamicObject* o = targetObject.getDynamicObject()) if (DynamicObject* o = targetObject.getDynamicObject())
{ {
if (var* prop = o->getProperties().getVarPointer (functionName)) if (const var* prop = getPropertyPointer (o, functionName))
return *prop; return *prop;
for (DynamicObject* p = o->getProperty (getPrototypeIdentifier()).getDynamicObject(); p != nullptr; for (DynamicObject* p = o->getProperty (getPrototypeIdentifier()).getDynamicObject(); p != nullptr;
p = p->getProperty (getPrototypeIdentifier()).getDynamicObject()) p = p->getProperty (getPrototypeIdentifier()).getDynamicObject())
{ {
if (var* prop = p->getProperties().getVarPointer (functionName)) if (const var* prop = getPropertyPointer (p, functionName))
return *prop; return *prop;
} }
} }
@ -168,14 +169,14 @@ struct JavascriptEngine::RootObject : public DynamicObject
var* findRootClassProperty (Identifier className, Identifier propName) const var* findRootClassProperty (Identifier className, Identifier propName) const
{ {
if (DynamicObject* cls = root->getProperty (className).getDynamicObject()) if (DynamicObject* cls = root->getProperty (className).getDynamicObject())
return cls->getProperties().getVarPointer (propName); return getPropertyPointer (cls, propName);
return nullptr; return nullptr;
} }
var findSymbolInParentScopes (Identifier name) const var findSymbolInParentScopes (Identifier name) const
{ {
if (var* v = scope->getProperties().getVarPointer (name)) if (const var* v = getPropertyPointer (scope, name))
return *v; return *v;
return parent != nullptr ? parent->findSymbolInParentScopes (name) return parent != nullptr ? parent->findSymbolInParentScopes (name)
@ -184,13 +185,11 @@ struct JavascriptEngine::RootObject : public DynamicObject
bool findAndInvokeMethod (Identifier function, const var::NativeFunctionArgs& args, var& result) const bool findAndInvokeMethod (Identifier function, const var::NativeFunctionArgs& args, var& result) const
{ {
const NamedValueSet& props = scope->getProperties();
DynamicObject* target = args.thisObject.getDynamicObject(); DynamicObject* target = args.thisObject.getDynamicObject();
if (target == nullptr || target == scope) if (target == nullptr || target == scope)
{ {
if (const var* m = props.getVarPointer (function)) if (const var* m = getPropertyPointer (scope, function))
{ {
if (FunctionObject* fo = dynamic_cast<FunctionObject*> (m->getObject())) if (FunctionObject* fo = dynamic_cast<FunctionObject*> (m->getObject()))
{ {
@ -200,6 +199,8 @@ struct JavascriptEngine::RootObject : public DynamicObject
} }
} }
const NamedValueSet& props = scope->getProperties();
for (int i = 0; i < props.size(); ++i) for (int i = 0; i < props.size(); ++i)
if (DynamicObject* o = props.getValueAt (i).getDynamicObject()) if (DynamicObject* o = props.getValueAt (i).getDynamicObject())
if (Scope (this, root, o).findAndInvokeMethod (function, args, result)) if (Scope (this, root, o).findAndInvokeMethod (function, args, result))
@ -353,7 +354,7 @@ struct JavascriptEngine::RootObject : public DynamicObject
void assign (const Scope& s, const var& newValue) const override void assign (const Scope& s, const var& newValue) const override
{ {
if (var* v = s.scope->getProperties().getVarPointer (name)) if (var* v = getPropertyPointer (s.scope, name))
*v = newValue; *v = newValue;
else else
s.root->setProperty (name, newValue); s.root->setProperty (name, newValue);
@ -378,7 +379,7 @@ struct JavascriptEngine::RootObject : public DynamicObject
} }
if (DynamicObject* o = p.getDynamicObject()) if (DynamicObject* o = p.getDynamicObject())
if (var* v = o->getProperties().getVarPointer (child)) if (const var* v = getPropertyPointer (o, child))
return *v; return *v;
return var::undefined(); return var::undefined();

@ -263,7 +263,7 @@ private:
} }
} }
String responseHeader (readResponse (socketHandle, timeOutTime)); String responseHeader (readResponse (timeOutTime));
position = 0; position = 0;
if (responseHeader.isNotEmpty()) if (responseHeader.isNotEmpty())
@ -302,7 +302,7 @@ private:
} }
//============================================================================== //==============================================================================
String readResponse (const int socketHandle, const uint32 timeOutTime) String readResponse (const uint32 timeOutTime)
{ {
int numConsecutiveLFs = 0; int numConsecutiveLFs = 0;
MemoryOutputStream buffer; MemoryOutputStream buffer;
@ -338,7 +338,8 @@ private:
dest << "\r\n" << key << ' ' << value; dest << "\r\n" << key << ' ' << value;
} }
static void writeHost (MemoryOutputStream& dest, const bool isPost, const String& path, const String& host, const int port) static void writeHost (MemoryOutputStream& dest, const bool isPost,
const String& path, const String& host, int /*port*/)
{ {
dest << (isPost ? "POST " : "GET ") << path << " HTTP/1.0\r\nHost: " << host; dest << (isPost ? "POST " : "GET ") << path << " HTTP/1.0\r\nHost: " << host;
} }

@ -223,6 +223,12 @@ namespace
return statfs (f.getFullPathName().toUTF8(), &result) == 0; return statfs (f.getFullPathName().toUTF8(), &result) == 0;
} }
#if (JUCE_MAC && MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5) || JUCE_IOS
static int64 getCreationTime (const juce_statStruct& s) noexcept { return (int64) s.st_birthtime; }
#else
static int64 getCreationTime (const juce_statStruct& s) noexcept { return (int64) s.st_ctime; }
#endif
void updateStatInfoForFile (const String& path, bool* const isDir, int64* const fileSize, void updateStatInfoForFile (const String& path, bool* const isDir, int64* const fileSize,
Time* const modTime, Time* const creationTime, bool* const isReadOnly) Time* const modTime, Time* const creationTime, bool* const isReadOnly)
{ {
@ -232,9 +238,9 @@ namespace
const bool statOk = juce_stat (path, info); const bool statOk = juce_stat (path, info);
if (isDir != nullptr) *isDir = statOk && ((info.st_mode & S_IFDIR) != 0); if (isDir != nullptr) *isDir = statOk && ((info.st_mode & S_IFDIR) != 0);
if (fileSize != nullptr) *fileSize = statOk ? info.st_size : 0; if (fileSize != nullptr) *fileSize = statOk ? (int64) info.st_size : 0;
if (modTime != nullptr) *modTime = Time (statOk ? (int64) info.st_mtime * 1000 : 0); if (modTime != nullptr) *modTime = Time (statOk ? (int64) info.st_mtime * 1000 : 0);
if (creationTime != nullptr) *creationTime = Time (statOk ? (int64) info.st_ctime * 1000 : 0); if (creationTime != nullptr) *creationTime = Time (statOk ? getCreationTime (info) * 1000 : 0);
} }
if (isReadOnly != nullptr) if (isReadOnly != nullptr)
@ -664,6 +670,7 @@ int File::getVolumeSerialNumber() const
} }
//============================================================================== //==============================================================================
#if ! JUCE_IOS
void juce_runSystemCommand (const String&); void juce_runSystemCommand (const String&);
void juce_runSystemCommand (const String& command) void juce_runSystemCommand (const String& command)
{ {
@ -684,7 +691,7 @@ String juce_getOutputFromCommand (const String& command)
tempFile.deleteFile(); tempFile.deleteFile();
return result; return result;
} }
#endif
//============================================================================== //==============================================================================
#if JUCE_IOS #if JUCE_IOS

@ -418,8 +418,10 @@ bool StreamingSocket::createListener (const int newPortNumber, const String& loc
if (handle < 0) if (handle < 0)
return false; return false;
#if ! JUCE_WINDOWS // on windows, adding this option produces behaviour different to posix
const int reuse = 1; const int reuse = 1;
setsockopt (handle, SOL_SOCKET, SO_REUSEADDR, (const char*) &reuse, sizeof (reuse)); setsockopt (handle, SOL_SOCKET, SO_REUSEADDR, (const char*) &reuse, sizeof (reuse));
#endif
if (bind (handle, (struct sockaddr*) &servTmpAddr, sizeof (struct sockaddr_in)) < 0 if (bind (handle, (struct sockaddr*) &servTmpAddr, sizeof (struct sockaddr_in)) < 0
|| listen (handle, SOMAXCONN) < 0) || listen (handle, SOMAXCONN) < 0)

@ -182,7 +182,7 @@ int64 MemoryOutputStream::writeFromInputStream (InputStream& source, int64 maxNu
if (availableData > 0) if (availableData > 0)
{ {
if (maxNumBytesToWrite > availableData) if (maxNumBytesToWrite > availableData || maxNumBytesToWrite < 0)
maxNumBytesToWrite = availableData; maxNumBytesToWrite = availableData;
if (blockToUse != nullptr) if (blockToUse != nullptr)

@ -72,6 +72,7 @@
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
#include <functional>
#if JUCE_USE_MSVC_INTRINSICS #if JUCE_USE_MSVC_INTRINSICS
#include <intrin.h> #include <intrin.h>

@ -155,7 +155,7 @@
#define JUCE_BIG_ENDIAN 1 #define JUCE_BIG_ENDIAN 1
#endif #endif
#if defined (__LP64__) || defined (_LP64) #if defined (__LP64__) || defined (_LP64) || defined (__arm64__)
#define JUCE_64BIT 1 #define JUCE_64BIT 1
#else #else
#define JUCE_32BIT 1 #define JUCE_32BIT 1

@ -318,7 +318,10 @@ public:
/** Creates an XmlElement that holds a complete image of this node and all its children. /** Creates an XmlElement that holds a complete image of this node and all its children.
If this node is invalid, this may return nullptr. Otherwise, the XML that is produced can If this node is invalid, this may return nullptr. Otherwise, the XML that is produced can
be used to recreate a similar node by calling fromXml() be used to recreate a similar node by calling fromXml().
The caller must delete the object that is returned.
@see fromXml @see fromXml
*/ */
XmlElement* createXml() const; XmlElement* createXml() const;

@ -131,6 +131,22 @@ void MessageManager::stopDispatchLoop()
#endif #endif
//============================================================================== //==============================================================================
struct AsyncFunction : private MessageManager::MessageBase
{
AsyncFunction (std::function<void(void)> f) : fn (f) { post(); }
private:
std::function<void(void)> fn;
void messageCallback() override { fn(); }
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AsyncFunction)
};
void MessageManager::callAsync (std::function<void(void)> f)
{
new AsyncFunction (f);
}
class AsyncFunctionCallback : public MessageManager::MessageBase class AsyncFunctionCallback : public MessageManager::MessageBase
{ {
public: public:

@ -91,6 +91,11 @@ public:
#endif #endif
//============================================================================== //==============================================================================
/** Asynchronously invokes a function or C++11 lambda on the message thread.
Internally this uses the CallbackMessage class to invoke the callback.
*/
static void callAsync (std::function<void(void)>);
/** Calls a function using the message-thread. /** Calls a function using the message-thread.
This can be used by any thread to cause this function to be called-back This can be used by any thread to cause this function to be called-back

@ -158,7 +158,7 @@ public:
void drawText (const String& text, void drawText (const String& text,
int x, int y, int width, int height, int x, int y, int width, int height,
Justification justificationType, Justification justificationType,
bool useEllipsesIfTooBig) const; bool useEllipsesIfTooBig = true) const;
/** Draws a line of text within a specified rectangle. /** Draws a line of text within a specified rectangle.
@ -172,7 +172,7 @@ public:
void drawText (const String& text, void drawText (const String& text,
const Rectangle<int>& area, const Rectangle<int>& area,
Justification justificationType, Justification justificationType,
bool useEllipsesIfTooBig) const; bool useEllipsesIfTooBig = true) const;
/** Draws a line of text within a specified rectangle. /** Draws a line of text within a specified rectangle.
@ -186,7 +186,7 @@ public:
void drawText (const String& text, void drawText (const String& text,
const Rectangle<float>& area, const Rectangle<float>& area,
Justification justificationType, Justification justificationType,
bool useEllipsesIfTooBig) const; bool useEllipsesIfTooBig = true) const;
/** Tries to draw a text string inside a given space. /** Tries to draw a text string inside a given space.

@ -125,11 +125,12 @@ void Button::setTooltip (const String& newTooltip)
generateTooltip = false; generateTooltip = false;
} }
String Button::getTooltip() void Button::updateAutomaticTooltip (const ApplicationCommandInfo& info)
{ {
if (generateTooltip && commandManagerToUse != nullptr && commandID != 0) if (generateTooltip && commandManagerToUse != nullptr)
{ {
String tt (commandManagerToUse->getDescriptionOfCommand (commandID)); String tt (info.description.isNotEmpty() ? info.description
: info.shortName);
Array<KeyPress> keyPresses (commandManagerToUse->getKeyMappings()->getKeyPressesAssignedToCommand (commandID)); Array<KeyPress> keyPresses (commandManagerToUse->getKeyMappings()->getKeyPressesAssignedToCommand (commandID));
@ -145,10 +146,8 @@ String Button::getTooltip()
tt << key << ']'; tt << key << ']';
} }
return tt; SettableTooltipClient::setTooltip (tt);
} }
return SettableTooltipClient::getTooltip();
} }
void Button::setConnectedEdges (const int newFlags) void Button::setConnectedEdges (const int newFlags)
@ -542,6 +541,7 @@ void Button::applicationCommandListChangeCallback()
if (commandManagerToUse->getTargetForCommand (commandID, info) != nullptr) if (commandManagerToUse->getTargetForCommand (commandID, info) != nullptr)
{ {
updateAutomaticTooltip (info);
setEnabled ((info.flags & ApplicationCommandInfo::isDisabled) == 0); setEnabled ((info.flags & ApplicationCommandInfo::isDisabled) == 0);
setToggleState ((info.flags & ApplicationCommandInfo::isTicked) != 0, dontSendNotification); setToggleState ((info.flags & ApplicationCommandInfo::isTicked) != 0, dontSendNotification);
} }

@ -277,12 +277,6 @@ public:
*/ */
void setTooltip (const String& newTooltip) override; void setTooltip (const String& newTooltip) override;
/** Returns the tooltip set by setTooltip(), or the description corresponding to
the currently mapped command if one is enabled (see setCommandToTrigger).
*/
String getTooltip() override;
//============================================================================== //==============================================================================
/** A combination of these flags are used by setConnectedEdges(). */ /** A combination of these flags are used by setConnectedEdges(). */
enum ConnectedEdgeFlags enum ConnectedEdgeFlags
@ -495,6 +489,7 @@ private:
void repeatTimerCallback(); void repeatTimerCallback();
bool keyStateChangedCallback(); bool keyStateChangedCallback();
void applicationCommandListChangeCallback(); void applicationCommandListChangeCallback();
void updateAutomaticTooltip (const ApplicationCommandInfo&);
ButtonState updateState(); ButtonState updateState();
ButtonState updateState (bool isOver, bool isDown); ButtonState updateState (bool isOver, bool isDown);

@ -51,7 +51,20 @@ void ApplicationCommandManager::registerCommand (const ApplicationCommandInfo& n
// the name isn't optional! // the name isn't optional!
jassert (newCommand.shortName.isNotEmpty()); jassert (newCommand.shortName.isNotEmpty());
if (getCommandForID (newCommand.commandID) == 0) if (ApplicationCommandInfo* command = getMutableCommandForID (newCommand.commandID))
{
// Trying to re-register the same command ID with different parameters can often indicate a typo.
// This assertion is here because I've found it useful catching some mistakes, but it may also cause
// false alarms if you're deliberately updating some flags for a command.
jassert (newCommand.shortName == getCommandForID (newCommand.commandID)->shortName
&& newCommand.categoryName == getCommandForID (newCommand.commandID)->categoryName
&& newCommand.defaultKeypresses == getCommandForID (newCommand.commandID)->defaultKeypresses
&& (newCommand.flags & (ApplicationCommandInfo::wantsKeyUpDownCallbacks | ApplicationCommandInfo::hiddenFromKeyEditor | ApplicationCommandInfo::readOnlyInKeyEditor))
== (getCommandForID (newCommand.commandID)->flags & (ApplicationCommandInfo::wantsKeyUpDownCallbacks | ApplicationCommandInfo::hiddenFromKeyEditor | ApplicationCommandInfo::readOnlyInKeyEditor)));
*command = newCommand;
}
else
{ {
ApplicationCommandInfo* const newInfo = new ApplicationCommandInfo (newCommand); ApplicationCommandInfo* const newInfo = new ApplicationCommandInfo (newCommand);
newInfo->flags &= ~ApplicationCommandInfo::isTicked; newInfo->flags &= ~ApplicationCommandInfo::isTicked;
@ -61,16 +74,6 @@ void ApplicationCommandManager::registerCommand (const ApplicationCommandInfo& n
triggerAsyncUpdate(); triggerAsyncUpdate();
} }
else
{
// trying to re-register the same command ID with different parameters?
jassert (newCommand.shortName == getCommandForID (newCommand.commandID)->shortName
&& (newCommand.description == getCommandForID (newCommand.commandID)->description || newCommand.description.isEmpty())
&& newCommand.categoryName == getCommandForID (newCommand.commandID)->categoryName
&& newCommand.defaultKeypresses == getCommandForID (newCommand.commandID)->defaultKeypresses
&& (newCommand.flags & (ApplicationCommandInfo::wantsKeyUpDownCallbacks | ApplicationCommandInfo::hiddenFromKeyEditor | ApplicationCommandInfo::readOnlyInKeyEditor))
== (getCommandForID (newCommand.commandID)->flags & (ApplicationCommandInfo::wantsKeyUpDownCallbacks | ApplicationCommandInfo::hiddenFromKeyEditor | ApplicationCommandInfo::readOnlyInKeyEditor)));
}
} }
void ApplicationCommandManager::registerAllCommandsForTarget (ApplicationCommandTarget* target) void ApplicationCommandManager::registerAllCommandsForTarget (ApplicationCommandTarget* target)
@ -113,7 +116,7 @@ void ApplicationCommandManager::commandStatusChanged()
} }
//============================================================================== //==============================================================================
const ApplicationCommandInfo* ApplicationCommandManager::getCommandForID (const CommandID commandID) const noexcept ApplicationCommandInfo* ApplicationCommandManager::getMutableCommandForID (CommandID commandID) const noexcept
{ {
for (int i = commands.size(); --i >= 0;) for (int i = commands.size(); --i >= 0;)
if (commands.getUnchecked(i)->commandID == commandID) if (commands.getUnchecked(i)->commandID == commandID)
@ -122,6 +125,11 @@ const ApplicationCommandInfo* ApplicationCommandManager::getCommandForID (const
return nullptr; return nullptr;
} }
const ApplicationCommandInfo* ApplicationCommandManager::getCommandForID (const CommandID commandID) const noexcept
{
return getMutableCommandForID (commandID);
}
String ApplicationCommandManager::getNameOfCommand (const CommandID commandID) const noexcept String ApplicationCommandManager::getNameOfCommand (const CommandID commandID) const noexcept
{ {
if (const ApplicationCommandInfo* const ci = getCommandForID (commandID)) if (const ApplicationCommandInfo* const ci = getCommandForID (commandID))
@ -215,7 +223,10 @@ ApplicationCommandTarget* ApplicationCommandManager::getTargetForCommand (const
target = target->getTargetForCommand (commandID); target = target->getTargetForCommand (commandID);
if (target != nullptr) if (target != nullptr)
{
upToDateInfo.commandID = commandID;
target->getCommandInfo (commandID, upToDateInfo); target->getCommandInfo (commandID, upToDateInfo);
}
return target; return target;
} }
@ -223,7 +234,7 @@ ApplicationCommandTarget* ApplicationCommandManager::getTargetForCommand (const
//============================================================================== //==============================================================================
ApplicationCommandTarget* ApplicationCommandManager::findTargetForComponent (Component* c) ApplicationCommandTarget* ApplicationCommandManager::findTargetForComponent (Component* c)
{ {
ApplicationCommandTarget* target = dynamic_cast <ApplicationCommandTarget*> (c); ApplicationCommandTarget* target = dynamic_cast<ApplicationCommandTarget*> (c);
if (target == nullptr && c != nullptr) if (target == nullptr && c != nullptr)
target = c->findParentComponentOfClass<ApplicationCommandTarget>(); target = c->findParentComponentOfClass<ApplicationCommandTarget>();
@ -263,7 +274,7 @@ ApplicationCommandTarget* ApplicationCommandManager::findDefaultComponentTarget(
// component that really should get the event. And if not, the event will // component that really should get the event. And if not, the event will
// still be passed up to the top level window anyway, so let's send it to the // still be passed up to the top level window anyway, so let's send it to the
// content comp. // content comp.
if (ResizableWindow* const resizableWindow = dynamic_cast <ResizableWindow*> (c)) if (ResizableWindow* const resizableWindow = dynamic_cast<ResizableWindow*> (c))
if (Component* const content = resizableWindow->getContentComponent()) if (Component* const content = resizableWindow->getContentComponent())
c = content; c = content;

@ -308,6 +308,7 @@ private:
void sendListenerInvokeCallback (const ApplicationCommandTarget::InvocationInfo&); void sendListenerInvokeCallback (const ApplicationCommandTarget::InvocationInfo&);
void handleAsyncUpdate() override; void handleAsyncUpdate() override;
void globalFocusChanged (Component*) override; void globalFocusChanged (Component*) override;
ApplicationCommandInfo* getMutableCommandForID (CommandID) const noexcept;
#if JUCE_CATCH_DEPRECATED_CODE_MISUSE #if JUCE_CATCH_DEPRECATED_CODE_MISUSE
// This is just here to cause a compile error in old code that hasn't been changed to use the new // This is just here to cause a compile error in old code that hasn't been changed to use the new

@ -111,6 +111,9 @@ LookAndFeel_V2::LookAndFeel_V2()
TextPropertyComponent::textColourId, 0xff000000, TextPropertyComponent::textColourId, 0xff000000,
TextPropertyComponent::outlineColourId, standardOutlineColour, TextPropertyComponent::outlineColourId, standardOutlineColour,
BooleanPropertyComponent::backgroundColourId, 0xffffffff,
BooleanPropertyComponent::outlineColourId, standardOutlineColour,
ListBox::backgroundColourId, 0xffffffff, ListBox::backgroundColourId, 0xffffffff,
ListBox::outlineColourId, standardOutlineColour, ListBox::outlineColourId, standardOutlineColour,
ListBox::textColourId, 0xff000000, ListBox::textColourId, 0xff000000,
@ -1001,6 +1004,16 @@ void LookAndFeel_V2::drawPopupMenuItem (Graphics& g, const Rectangle<int>& area,
} }
} }
void LookAndFeel_V2::drawPopupMenuSectionHeader (Graphics& g, const Rectangle<int>& area, const String& sectionName)
{
g.setFont (getPopupMenuFont().boldened());
g.setColour (findColour (PopupMenu::headerTextColourId));
g.drawFittedText (sectionName,
area.getX() + 12, area.getY(), area.getWidth() - 16, (int) (area.getHeight() * 0.8f),
Justification::bottomLeft, 1);
}
//============================================================================== //==============================================================================
int LookAndFeel_V2::getMenuWindowFlags() int LookAndFeel_V2::getMenuWindowFlags()
{ {

@ -137,6 +137,9 @@ public:
const String& text, const String& shortcutKeyText, const String& text, const String& shortcutKeyText,
const Drawable* icon, const Colour* textColour) override; const Drawable* icon, const Colour* textColour) override;
void drawPopupMenuSectionHeader (Graphics&, const Rectangle<int>& area,
const String& sectionName) override;
Font getPopupMenuFont() override; Font getPopupMenuFont() override;
void drawPopupMenuUpDownArrow (Graphics&, int width, int height, bool isScrollUpArrow) override; void drawPopupMenuUpDownArrow (Graphics&, int width, int height, bool isScrollUpArrow) override;

@ -1216,12 +1216,7 @@ public:
void paint (Graphics& g) override void paint (Graphics& g) override
{ {
g.setFont (getLookAndFeel().getPopupMenuFont().boldened()); getLookAndFeel().drawPopupMenuSectionHeader (g, getLocalBounds(), getName());
g.setColour (findColour (PopupMenu::headerTextColourId));
g.drawFittedText (getName(),
12, 0, getWidth() - 16, proportionOfHeight (0.8f),
Justification::bottomLeft, 1);
} }
void getIdealSize (int& idealWidth, int& idealHeight) void getIdealSize (int& idealWidth, int& idealHeight)

@ -562,6 +562,9 @@ public:
const Drawable* icon, const Drawable* icon,
const Colour* textColour) = 0; const Colour* textColour) = 0;
virtual void drawPopupMenuSectionHeader (Graphics&, const Rectangle<int>& area,
const String& sectionName) = 0;
/** Returns the size and style of font to use in popup menus. */ /** Returns the size and style of font to use in popup menus. */
virtual Font getPopupMenuFont() = 0; virtual Font getPopupMenuFont() = 0;

@ -69,6 +69,8 @@ public:
if (current->isInterestedInDragSource (sourceDetails)) if (current->isInterestedInDragSource (sourceDetails))
current->itemDragExit (sourceDetails); current->itemDragExit (sourceDetails);
} }
owner.dragOperationEnded();
} }
void paint (Graphics& g) override void paint (Graphics& g) override
@ -164,14 +166,14 @@ public:
if (sourceDetails.sourceComponent == nullptr) if (sourceDetails.sourceComponent == nullptr)
{ {
delete this; deleteSelf();
} }
else if (! isMouseButtonDownAnywhere()) else if (! isMouseButtonDownAnywhere())
{ {
if (mouseDragSource != nullptr) if (mouseDragSource != nullptr)
mouseDragSource->removeMouseListener (this); mouseDragSource->removeMouseListener (this);
delete this; deleteSelf();
} }
} }
@ -180,7 +182,7 @@ public:
if (key == KeyPress::escapeKey) if (key == KeyPress::escapeKey)
{ {
dismissWithAnimation (true); dismissWithAnimation (true);
delete this; deleteSelf();
return true; return true;
} }
@ -215,13 +217,28 @@ private:
return dynamic_cast<DragAndDropTarget*> (currentlyOverComp.get()); return dynamic_cast<DragAndDropTarget*> (currentlyOverComp.get());
} }
static Component* findDesktopComponentBelow (Point<int> screenPos)
{
Desktop& desktop = Desktop::getInstance();
for (int i = desktop.getNumComponents(); --i >= 0;)
{
Component* c = desktop.getComponent(i);
if (Component* hit = c->getComponentAt (c->getLocalPoint (nullptr, screenPos)))
return hit;
}
return nullptr;
}
DragAndDropTarget* findTarget (Point<int> screenPos, Point<int>& relativePos, DragAndDropTarget* findTarget (Point<int> screenPos, Point<int>& relativePos,
Component*& resultComponent) const Component*& resultComponent) const
{ {
Component* hit = getParentComponent(); Component* hit = getParentComponent();
if (hit == nullptr) if (hit == nullptr)
hit = Desktop::getInstance().findComponentAt (screenPos); hit = findDesktopComponentBelow (screenPos);
else else
hit = hit->getComponentAt (hit->getLocalPoint (nullptr, screenPos)); hit = hit->getComponentAt (hit->getLocalPoint (nullptr, screenPos));
@ -296,12 +313,17 @@ private:
&& ModifierKeys::getCurrentModifiersRealtime().isAnyMouseButtonDown()) && ModifierKeys::getCurrentModifiersRealtime().isAnyMouseButtonDown())
{ {
(new ExternalDragAndDropMessage (files, canMoveFiles))->post(); (new ExternalDragAndDropMessage (files, canMoveFiles))->post();
delete this; deleteSelf();
} }
} }
} }
} }
void deleteSelf()
{
delete this;
}
void dismissWithAnimation (const bool shouldSnapBack) void dismissWithAnimation (const bool shouldSnapBack)
{ {
setVisible (true); setVisible (true);
@ -434,6 +456,8 @@ void DragAndDropContainer::startDragging (const var& sourceDescription,
if (ComponentPeer* const peer = dragImageComponent->getPeer()) if (ComponentPeer* const peer = dragImageComponent->getPeer())
peer->performAnyPendingRepaintsNow(); peer->performAnyPendingRepaintsNow();
#endif #endif
dragOperationStarted();
} }
} }
@ -458,6 +482,9 @@ bool DragAndDropContainer::shouldDropFilesWhenDraggedExternally (const DragAndDr
return false; return false;
} }
void DragAndDropContainer::dragOperationStarted() {}
void DragAndDropContainer::dragOperationEnded() {}
//============================================================================== //==============================================================================
DragAndDropTarget::SourceDetails::SourceDetails (const var& desc, Component* comp, Point<int> pos) noexcept DragAndDropTarget::SourceDetails::SourceDetails (const var& desc, Component* comp, Point<int> pos) noexcept
: description (desc), : description (desc),

@ -165,6 +165,12 @@ protected:
virtual bool shouldDropFilesWhenDraggedExternally (const DragAndDropTarget::SourceDetails& sourceDetails, virtual bool shouldDropFilesWhenDraggedExternally (const DragAndDropTarget::SourceDetails& sourceDetails,
StringArray& files, bool& canMoveFiles); StringArray& files, bool& canMoveFiles);
/** Subclasses can override this to be told when a drag starts. */
virtual void dragOperationStarted();
/** Subclasses can override this to be told when a drag finishes. */
virtual void dragOperationEnded();
private: private:
//============================================================================== //==============================================================================
class DragImageComponent; class DragImageComponent;

@ -24,6 +24,14 @@
class UIViewComponentPeer; class UIViewComponentPeer;
// The way rotation works changed in iOS8..
static bool isUsingOldRotationMethod() noexcept
{
static bool isPreV8 = ([[[UIDevice currentDevice] systemVersion] compare: @"8.0"
options: NSNumericSearch] == NSOrderedAscending);
return isPreV8;
}
namespace Orientations namespace Orientations
{ {
static Desktop::DisplayOrientation convertToJuce (UIInterfaceOrientation orientation) static Desktop::DisplayOrientation convertToJuce (UIInterfaceOrientation orientation)
@ -42,12 +50,15 @@ namespace Orientations
static CGAffineTransform getCGTransformFor (const Desktop::DisplayOrientation orientation) noexcept static CGAffineTransform getCGTransformFor (const Desktop::DisplayOrientation orientation) noexcept
{ {
switch (orientation) if (isUsingOldRotationMethod())
{ {
case Desktop::upsideDown: return CGAffineTransformMake (-1, 0, 0, -1, 0, 0); switch (orientation)
case Desktop::rotatedClockwise: return CGAffineTransformMake (0, -1, 1, 0, 0, 0); {
case Desktop::rotatedAntiClockwise: return CGAffineTransformMake (0, 1, -1, 0, 0, 0); case Desktop::upsideDown: return CGAffineTransformMake (-1, 0, 0, -1, 0, 0);
default: break; case Desktop::rotatedClockwise: return CGAffineTransformMake (0, -1, 1, 0, 0, 0);
case Desktop::rotatedAntiClockwise: return CGAffineTransformMake (0, 1, -1, 0, 0, 0);
default: break;
}
} }
return CGAffineTransformIdentity; return CGAffineTransformIdentity;
@ -85,10 +96,10 @@ using namespace juce;
- (void) drawRect: (CGRect) r; - (void) drawRect: (CGRect) r;
- (void) touchesBegan: (NSSet*) touches withEvent: (UIEvent*) event; - (void) touchesBegan: (NSSet*) touches withEvent: (UIEvent*) event;
- (void) touchesMoved: (NSSet*) touches withEvent: (UIEvent*) event; - (void) touchesMoved: (NSSet*) touches withEvent: (UIEvent*) event;
- (void) touchesEnded: (NSSet*) touches withEvent: (UIEvent*) event; - (void) touchesEnded: (NSSet*) touches withEvent: (UIEvent*) event;
- (void) touchesCancelled: (NSSet*) touches withEvent: (UIEvent*) event; - (void) touchesCancelled: (NSSet*) touches withEvent: (UIEvent*) event;
- (BOOL) becomeFirstResponder; - (BOOL) becomeFirstResponder;
- (BOOL) resignFirstResponder; - (BOOL) resignFirstResponder;
@ -106,6 +117,7 @@ using namespace juce;
- (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) interfaceOrientation; - (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) interfaceOrientation;
- (void) willRotateToInterfaceOrientation: (UIInterfaceOrientation) toInterfaceOrientation duration: (NSTimeInterval) duration; - (void) willRotateToInterfaceOrientation: (UIInterfaceOrientation) toInterfaceOrientation duration: (NSTimeInterval) duration;
- (void) didRotateFromInterfaceOrientation: (UIInterfaceOrientation) fromInterfaceOrientation; - (void) didRotateFromInterfaceOrientation: (UIInterfaceOrientation) fromInterfaceOrientation;
- (void) viewWillTransitionToSize: (CGSize) size withTransitionCoordinator: (id<UIViewControllerTransitionCoordinator>) coordinator;
- (void) viewDidLoad; - (void) viewDidLoad;
- (void) viewWillAppear: (BOOL) animated; - (void) viewWillAppear: (BOOL) animated;
@ -189,7 +201,7 @@ public:
bool isSharedWindow, fullScreen, insideDrawRect; bool isSharedWindow, fullScreen, insideDrawRect;
static ModifierKeys currentModifiers; static ModifierKeys currentModifiers;
static int64 getMouseTime (UIEvent* e) static int64 getMouseTime (UIEvent* e) noexcept
{ {
return (Time::currentTimeMillis() - Time::getMillisecondCounter()) return (Time::currentTimeMillis() - Time::getMillisecondCounter())
+ (int64) ([e timestamp] * 1000.0); + (int64) ([e timestamp] * 1000.0);
@ -197,26 +209,29 @@ public:
static Rectangle<int> rotatedScreenPosToReal (const Rectangle<int>& r) static Rectangle<int> rotatedScreenPosToReal (const Rectangle<int>& r)
{ {
const Rectangle<int> screen (convertToRectInt ([UIScreen mainScreen].bounds)); if (isUsingOldRotationMethod())
switch ([[UIApplication sharedApplication] statusBarOrientation])
{ {
case UIInterfaceOrientationPortrait: const Rectangle<int> screen (convertToRectInt ([UIScreen mainScreen].bounds));
return r;
switch ([[UIApplication sharedApplication] statusBarOrientation])
{
case UIInterfaceOrientationPortrait:
return r;
case UIInterfaceOrientationPortraitUpsideDown: case UIInterfaceOrientationPortraitUpsideDown:
return Rectangle<int> (screen.getWidth() - r.getRight(), screen.getHeight() - r.getBottom(), return Rectangle<int> (screen.getWidth() - r.getRight(), screen.getHeight() - r.getBottom(),
r.getWidth(), r.getHeight()); r.getWidth(), r.getHeight());
case UIInterfaceOrientationLandscapeLeft: case UIInterfaceOrientationLandscapeLeft:
return Rectangle<int> (r.getY(), screen.getHeight() - r.getRight(), return Rectangle<int> (r.getY(), screen.getHeight() - r.getRight(),
r.getHeight(), r.getWidth()); r.getHeight(), r.getWidth());
case UIInterfaceOrientationLandscapeRight: case UIInterfaceOrientationLandscapeRight:
return Rectangle<int> (screen.getWidth() - r.getBottom(), r.getX(), return Rectangle<int> (screen.getWidth() - r.getBottom(), r.getX(),
r.getHeight(), r.getWidth()); r.getHeight(), r.getWidth());
default: jassertfalse; // unknown orientation! default: jassertfalse; // unknown orientation!
}
} }
return r; return r;
@ -224,26 +239,29 @@ public:
static Rectangle<int> realScreenPosToRotated (const Rectangle<int>& r) static Rectangle<int> realScreenPosToRotated (const Rectangle<int>& r)
{ {
const Rectangle<int> screen (convertToRectInt ([UIScreen mainScreen].bounds)); if (isUsingOldRotationMethod())
switch ([[UIApplication sharedApplication] statusBarOrientation])
{ {
case UIInterfaceOrientationPortrait: const Rectangle<int> screen (convertToRectInt ([UIScreen mainScreen].bounds));
return r;
switch ([[UIApplication sharedApplication] statusBarOrientation])
{
case UIInterfaceOrientationPortrait:
return r;
case UIInterfaceOrientationPortraitUpsideDown: case UIInterfaceOrientationPortraitUpsideDown:
return Rectangle<int> (screen.getWidth() - r.getRight(), screen.getHeight() - r.getBottom(), return Rectangle<int> (screen.getWidth() - r.getRight(), screen.getHeight() - r.getBottom(),
r.getWidth(), r.getHeight()); r.getWidth(), r.getHeight());
case UIInterfaceOrientationLandscapeLeft: case UIInterfaceOrientationLandscapeLeft:
return Rectangle<int> (screen.getHeight() - r.getBottom(), r.getX(), return Rectangle<int> (screen.getHeight() - r.getBottom(), r.getX(),
r.getHeight(), r.getWidth()); r.getHeight(), r.getWidth());
case UIInterfaceOrientationLandscapeRight: case UIInterfaceOrientationLandscapeRight:
return Rectangle<int> (r.getY(), screen.getWidth() - r.getRight(), return Rectangle<int> (r.getY(), screen.getWidth() - r.getRight(),
r.getHeight(), r.getWidth()); r.getHeight(), r.getWidth());
default: jassertfalse; // unknown orientation! default: jassertfalse; // unknown orientation!
}
} }
return r; return r;
@ -273,6 +291,13 @@ private:
}; };
}; };
static void sendScreenBoundsUpdate (JuceUIViewController* c)
{
JuceUIView* juceView = (JuceUIView*) [c view];
jassert (juceView != nil && juceView->owner != nullptr);
juceView->owner->updateTransformAndScreenBounds();
}
} // (juce namespace) } // (juce namespace)
//============================================================================== //==============================================================================
@ -301,19 +326,23 @@ private:
- (void) didRotateFromInterfaceOrientation: (UIInterfaceOrientation) fromInterfaceOrientation - (void) didRotateFromInterfaceOrientation: (UIInterfaceOrientation) fromInterfaceOrientation
{ {
(void) fromInterfaceOrientation; (void) fromInterfaceOrientation;
sendScreenBoundsUpdate (self);
[UIView setAnimationsEnabled: YES];
}
JuceUIView* juceView = (JuceUIView*) [self view]; - (void) viewWillTransitionToSize: (CGSize) size withTransitionCoordinator: (id<UIViewControllerTransitionCoordinator>) coordinator
jassert (juceView != nil && juceView->owner != nullptr); {
juceView->owner->updateTransformAndScreenBounds(); [super viewWillTransitionToSize: size withTransitionCoordinator: coordinator];
sendScreenBoundsUpdate (self);
[UIView setAnimationsEnabled: YES]; // On some devices the screen-size isn't yet updated at this point, so also trigger another
// async update to double-check..
MessageManager::callAsync ([=]() { sendScreenBoundsUpdate (self); });
} }
- (void) viewDidLoad - (void) viewDidLoad
{ {
JuceUIView* juceView = (JuceUIView*) [self view]; sendScreenBoundsUpdate (self);
jassert (juceView != nil && juceView->owner != nullptr);
juceView->owner->updateTransformAndScreenBounds();
} }
- (void) viewWillAppear: (BOOL) animated - (void) viewWillAppear: (BOOL) animated

@ -1087,9 +1087,7 @@ public:
{ {
for (int i = windowListSize; --i >= 0;) for (int i = windowListSize; --i >= 0;)
{ {
LinuxComponentPeer* const peer = LinuxComponentPeer::getPeerFor (windowList[i]); if (LinuxComponentPeer* const peer = LinuxComponentPeer::getPeerFor (windowList[i]))
if (peer != 0)
{ {
result = (peer == this); result = (peer == this);
break; break;

@ -845,7 +845,7 @@ public:
void toBehind (ComponentPeer* other) override void toBehind (ComponentPeer* other) override
{ {
if (HWNDComponentPeer* const otherPeer = dynamic_cast <HWNDComponentPeer*> (other)) if (HWNDComponentPeer* const otherPeer = dynamic_cast<HWNDComponentPeer*> (other))
{ {
setMinimised (false); setMinimised (false);
@ -960,7 +960,7 @@ public:
static ModifierKeys modifiersAtLastCallback; static ModifierKeys modifiersAtLastCallback;
//============================================================================== //==============================================================================
class JuceDropTarget : public ComBaseClassHelper <IDropTarget> class JuceDropTarget : public ComBaseClassHelper<IDropTarget>
{ {
public: public:
JuceDropTarget (HWNDComponentPeer& p) : ownerInfo (new OwnerInfo (p)) {} JuceDropTarget (HWNDComponentPeer& p) : ownerInfo (new OwnerInfo (p)) {}
@ -1099,13 +1099,13 @@ public:
if (SUCCEEDED (fileData.error)) if (SUCCEEDED (fileData.error))
{ {
const LPDROPFILES dropFiles = static_cast <const LPDROPFILES> (fileData.data); const LPDROPFILES dropFiles = static_cast<const LPDROPFILES> (fileData.data);
const void* const names = addBytesToPointer (dropFiles, sizeof (DROPFILES)); const void* const names = addBytesToPointer (dropFiles, sizeof (DROPFILES));
if (dropFiles->fWide) if (dropFiles->fWide)
ownerInfo->parseFileList (static_cast <const WCHAR*> (names), fileData.dataSize); ownerInfo->parseFileList (static_cast<const WCHAR*> (names), fileData.dataSize);
else else
ownerInfo->parseFileList (static_cast <const char*> (names), fileData.dataSize); ownerInfo->parseFileList (static_cast<const char*> (names), fileData.dataSize);
} }
else else
{ {
@ -1300,7 +1300,7 @@ private:
//============================================================================== //==============================================================================
static void* createWindowCallback (void* userData) static void* createWindowCallback (void* userData)
{ {
static_cast <HWNDComponentPeer*> (userData)->createWindow(); static_cast<HWNDComponentPeer*> (userData)->createWindow();
return nullptr; return nullptr;
} }
@ -1643,7 +1643,7 @@ private:
handlePaint (*context); handlePaint (*context);
} }
static_cast <WindowsBitmapImage*> (offscreenImage.getPixelData()) static_cast<WindowsBitmapImage*> (offscreenImage.getPixelData())
->blitToWindow (hwnd, dc, transparent, x, y, updateLayeredWindowAlpha); ->blitToWindow (hwnd, dc, transparent, x, y, updateLayeredWindowAlpha);
} }
@ -2261,6 +2261,24 @@ private:
} }
} }
void handlePowerBroadcast (WPARAM wParam)
{
if (JUCEApplicationBase* const app = JUCEApplicationBase::getInstance())
{
switch (wParam)
{
case PBT_APMSUSPEND: app->suspended(); break;
case PBT_APMQUERYSUSPENDFAILED:
case PBT_APMRESUMECRITICAL:
case PBT_APMRESUMESUSPEND:
case PBT_APMRESUMEAUTOMATIC: app->resumed(); break;
default: break;
}
}
}
void handleLeftClickInNCArea (WPARAM wParam) void handleLeftClickInNCArea (WPARAM wParam)
{ {
if (! sendInputAttemptWhenModalMessage()) if (! sendInputAttemptWhenModalMessage())
@ -2309,7 +2327,7 @@ private:
{ {
Desktop& desktop = Desktop::getInstance(); Desktop& desktop = Desktop::getInstance();
const_cast <Desktop::Displays&> (desktop.getDisplays()).refresh(); const_cast<Desktop::Displays&> (desktop.getDisplays()).refresh();
if (fullScreen && ! isMinimised()) if (fullScreen && ! isMinimised())
{ {
@ -2550,6 +2568,10 @@ private:
} }
return TRUE; return TRUE;
case WM_POWERBROADCAST:
handlePowerBroadcast (wParam);
break;
case WM_SYNCPAINT: case WM_SYNCPAINT:
return 0; return 0;
@ -2879,7 +2901,7 @@ private:
void moveCandidateWindowToLeftAlignWithSelection (HIMC hImc, ComponentPeer& peer, TextInputTarget* target) const void moveCandidateWindowToLeftAlignWithSelection (HIMC hImc, ComponentPeer& peer, TextInputTarget* target) const
{ {
if (Component* const targetComp = dynamic_cast <Component*> (target)) if (Component* const targetComp = dynamic_cast<Component*> (target))
{ {
const Rectangle<int> area (peer.getComponent().getLocalArea (targetComp, target->getCaretRectangle())); const Rectangle<int> area (peer.getComponent().getLocalArea (targetComp, target->getCaretRectangle()));
@ -2981,7 +3003,7 @@ bool JUCE_CALLTYPE Process::isForegroundProcess()
fg = GetAncestor (fg, GA_ROOT); fg = GetAncestor (fg, GA_ROOT);
for (int i = ComponentPeer::getNumPeers(); --i >= 0;) for (int i = ComponentPeer::getNumPeers(); --i >= 0;)
if (HWNDComponentPeer* const wp = dynamic_cast <HWNDComponentPeer*> (ComponentPeer::getPeer (i))) if (HWNDComponentPeer* const wp = dynamic_cast<HWNDComponentPeer*> (ComponentPeer::getPeer (i)))
if (wp->isInside (fg)) if (wp->isInside (fg))
return true; return true;
@ -3007,7 +3029,7 @@ static BOOL CALLBACK enumAlwaysOnTopWindows (HWND hwnd, LPARAM lParam)
if (GetWindowInfo (hwnd, &info) if (GetWindowInfo (hwnd, &info)
&& (info.dwExStyle & WS_EX_TOPMOST) != 0) && (info.dwExStyle & WS_EX_TOPMOST) != 0)
{ {
*reinterpret_cast <bool*> (lParam) = true; *reinterpret_cast<bool*> (lParam) = true;
return FALSE; return FALSE;
} }
} }
@ -3212,7 +3234,7 @@ void SystemClipboard::copyTextToClipboard (const String& text)
{ {
if (HGLOBAL bufH = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT, bytesNeeded + sizeof (WCHAR))) if (HGLOBAL bufH = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT, bytesNeeded + sizeof (WCHAR)))
{ {
if (WCHAR* const data = static_cast <WCHAR*> (GlobalLock (bufH))) if (WCHAR* const data = static_cast<WCHAR*> (GlobalLock (bufH)))
{ {
text.copyToUTF16 (data, bytesNeeded); text.copyToUTF16 (data, bytesNeeded);
GlobalUnlock (bufH); GlobalUnlock (bufH);

@ -66,7 +66,7 @@ void BooleanPropertyComponent::paint (Graphics& g)
{ {
PropertyComponent::paint (g); PropertyComponent::paint (g);
g.setColour (Colours::white); g.setColour (findColour (backgroundColourId));
g.fillRect (button.getBounds()); g.fillRect (button.getBounds());
g.setColour (findColour (ComboBox::outlineColourId)); g.setColour (findColour (ComboBox::outlineColourId));

@ -78,6 +78,20 @@ public:
/** Must return the current value of the property. */ /** Must return the current value of the property. */
virtual bool getState() const; virtual bool getState() const;
//==============================================================================
/** A set of colour IDs to use to change the colour of various aspects of the component.
These constants can be used either via the Component::setColour(), or LookAndFeel::setColour()
methods.
@see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
*/
enum ColourIds
{
backgroundColourId = 0x100e801, /**< The colour to fill the background of the button area. */
outlineColourId = 0x100e803, /**< The colour to use to draw an outline around the text area. */
};
//============================================================================== //==============================================================================
/** @internal */ /** @internal */
void paint (Graphics&) override; void paint (Graphics&) override;

@ -460,5 +460,3 @@ void Label::textEditorFocusLost (TextEditor& ed)
{ {
textEditorTextChanged (ed); textEditorTextChanged (ed);
} }
void Label::Listener::editorShown (Label*, TextEditor&) {}

@ -184,7 +184,7 @@ public:
virtual void labelTextChanged (Label* labelThatHasChanged) = 0; virtual void labelTextChanged (Label* labelThatHasChanged) = 0;
/** Called when a Label goes into editing mode and displays a TextEditor. */ /** Called when a Label goes into editing mode and displays a TextEditor. */
virtual void editorShown (Label*, TextEditor& textEditorShown); virtual void editorShown (Label*, TextEditor&) {}
}; };
/** Registers a listener that will be called when the label's text changes. */ /** Registers a listener that will be called when the label's text changes. */

@ -367,6 +367,7 @@ ListBox::ListBox (const String& name, ListBoxModel* const m)
outlineThickness (0), outlineThickness (0),
lastRowSelected (-1), lastRowSelected (-1),
multipleSelection (false), multipleSelection (false),
alwaysFlipSelection (false),
hasDoneInitialUpdate (false) hasDoneInitialUpdate (false)
{ {
addAndMakeVisible (viewport = new ListViewport (*this)); addAndMakeVisible (viewport = new ListViewport (*this));
@ -391,11 +392,16 @@ void ListBox::setModel (ListBoxModel* const newModel)
} }
} }
void ListBox::setMultipleSelectionEnabled (bool b) void ListBox::setMultipleSelectionEnabled (bool b) noexcept
{ {
multipleSelection = b; multipleSelection = b;
} }
void ListBox::setClickingTogglesRowSelection (bool b) noexcept
{
alwaysFlipSelection = b;
}
void ListBox::setMouseMoveSelectsRows (bool b) void ListBox::setMouseMoveSelectsRows (bool b)
{ {
if (b) if (b)
@ -470,9 +476,7 @@ void ListBox::updateContent()
} }
//============================================================================== //==============================================================================
void ListBox::selectRow (const int row, void ListBox::selectRow (int row, bool dontScroll, bool deselectOthersFirst)
bool dontScroll,
bool deselectOthersFirst)
{ {
selectRowInternal (row, dontScroll, deselectOthersFirst, false); selectRowInternal (row, dontScroll, deselectOthersFirst, false);
} }
@ -589,7 +593,7 @@ void ListBox::selectRowsBasedOnModifierKeys (const int row,
ModifierKeys mods, ModifierKeys mods,
const bool isMouseUpEvent) const bool isMouseUpEvent)
{ {
if (multipleSelection && mods.isCommandDown()) if (multipleSelection && (mods.isCommandDown() || alwaysFlipSelection))
{ {
flipRowSelection (row); flipRowSelection (row);
} }

@ -45,7 +45,10 @@ public:
*/ */
virtual int getNumRows() = 0; virtual int getNumRows() = 0;
/** This method must be implemented to draw a row of the list. */ /** This method must be implemented to draw a row of the list.
Note that the rowNumber value may be greater than the number of rows in your
list, so be careful that you don't assume it's less than getNumRows().
*/
virtual void paintListBoxItem (int rowNumber, virtual void paintListBoxItem (int rowNumber,
Graphics& g, Graphics& g,
int width, int height, int width, int height,
@ -216,7 +219,16 @@ public:
clicked and to get it to do the appropriate selection based on whether clicked and to get it to do the appropriate selection based on whether
the ctrl/shift keys are held down. the ctrl/shift keys are held down.
*/ */
void setMultipleSelectionEnabled (bool shouldBeEnabled); void setMultipleSelectionEnabled (bool shouldBeEnabled) noexcept;
/** If enabled, this makes the listbox flip the selection status of
each row that the user clicks, without affecting other selected rows.
(This only has an effect if multiple selection is also enabled).
If not enabled, you can still get the same row-flipping behaviour by holding
down CMD or CTRL when clicking.
*/
void setClickingTogglesRowSelection (bool flipRowSelection) noexcept;
/** Makes the list react to mouse moves by selecting the row that the mouse if over. /** Makes the list react to mouse moves by selecting the row that the mouse if over.
@ -557,7 +569,7 @@ private:
int totalItems, rowHeight, minimumRowWidth; int totalItems, rowHeight, minimumRowWidth;
int outlineThickness; int outlineThickness;
int lastRowSelected; int lastRowSelected;
bool multipleSelection, hasDoneInitialUpdate; bool multipleSelection, alwaysFlipSelection, hasDoneInitialUpdate;
SparseSet<int> selected; SparseSet<int> selected;
void selectRowInternal (int rowNumber, bool dontScrollToShowThisRow, void selectRowInternal (int rowNumber, bool dontScrollToShowThisRow,

@ -1006,9 +1006,9 @@ public:
valueBox->hideEditor (false); valueBox->hideEditor (false);
const double value = (double) currentValue.getValue(); const double value = (double) currentValue.getValue();
const double delta = getMouseWheelDelta (value, (wheel.deltaX != 0 ? -wheel.deltaX : wheel.deltaY) const double delta = getMouseWheelDelta (value, (std::abs (wheel.deltaX) > std::abs (wheel.deltaY)
* (wheel.isReversed ? -1.0f : 1.0f)); ? -wheel.deltaX : wheel.deltaY)
* (wheel.isReversed ? -1.0f : 1.0f));
if (delta != 0) if (delta != 0)
{ {
const double newValue = value + jmax (interval, std::abs (delta)) * (delta < 0 ? -1.0 : 1.0); const double newValue = value + jmax (interval, std::abs (delta)) * (delta < 0 ? -1.0 : 1.0);
@ -1287,6 +1287,7 @@ public:
{ {
setAlwaysOnTop (true); setAlwaysOnTop (true);
setAllowedPlacement (owner.getLookAndFeel().getSliderPopupPlacement (s)); setAllowedPlacement (owner.getLookAndFeel().getSliderPopupPlacement (s));
setLookAndFeel (&s.getLookAndFeel());
} }
void paintContent (Graphics& g, int w, int h) void paintContent (Graphics& g, int w, int h)

@ -66,6 +66,9 @@ public:
The graphics context's origin will already be set to the top-left of the cell, The graphics context's origin will already be set to the top-left of the cell,
whose size is specified by (width, height). whose size is specified by (width, height).
Note that the rowNumber value may be greater than the number of rows in your
list, so be careful that you don't assume it's less than getNumRows().
*/ */
virtual void paintCell (Graphics&, virtual void paintCell (Graphics&,
int rowNumber, int rowNumber,

@ -591,8 +591,8 @@ void Toolbar::itemDragMove (const SourceDetails& dragSourceDetails)
{ {
const Rectangle<int> previousPos (animator.getComponentDestination (prev)); const Rectangle<int> previousPos (animator.getComponentDestination (prev));
if (abs (dragObjectLeft - (vertical ? previousPos.getY() : previousPos.getX()) if (std::abs (dragObjectLeft - (vertical ? previousPos.getY() : previousPos.getX()))
< abs (dragObjectRight - (vertical ? current.getBottom() : current.getRight())))) < std::abs (dragObjectRight - (vertical ? current.getBottom() : current.getRight())))
{ {
newIndex = getIndexOfChildComponent (prev); newIndex = getIndexOfChildComponent (prev);
} }
@ -602,8 +602,8 @@ void Toolbar::itemDragMove (const SourceDetails& dragSourceDetails)
{ {
const Rectangle<int> nextPos (animator.getComponentDestination (next)); const Rectangle<int> nextPos (animator.getComponentDestination (next));
if (abs (dragObjectLeft - (vertical ? current.getY() : current.getX()) if (std::abs (dragObjectLeft - (vertical ? current.getY() : current.getX()))
> abs (dragObjectRight - (vertical ? nextPos.getBottom() : nextPos.getRight())))) > std::abs (dragObjectRight - (vertical ? nextPos.getBottom() : nextPos.getRight())))
{ {
newIndex = getIndexOfChildComponent (next) + 1; newIndex = getIndexOfChildComponent (next) + 1;
} }

@ -1773,6 +1773,11 @@ TreeViewItem* TreeViewItem::getNextVisibleItem (const bool recurse) const noexce
return nullptr; return nullptr;
} }
static String escapeSlashesInTreeViewItemName (const String& s)
{
return s.replaceCharacter ('/', '\\');
}
String TreeViewItem::getItemIdentifierString() const String TreeViewItem::getItemIdentifierString() const
{ {
String s; String s;
@ -1780,12 +1785,12 @@ String TreeViewItem::getItemIdentifierString() const
if (parentItem != nullptr) if (parentItem != nullptr)
s = parentItem->getItemIdentifierString(); s = parentItem->getItemIdentifierString();
return s + "/" + getUniqueName().replaceCharacter ('/', '\\'); return s + "/" + escapeSlashesInTreeViewItemName (getUniqueName());
} }
TreeViewItem* TreeViewItem::findItemFromIdentifierString (const String& identifierString) TreeViewItem* TreeViewItem::findItemFromIdentifierString (const String& identifierString)
{ {
const String thisId ("/" + getUniqueName()); const String thisId ("/" + escapeSlashesInTreeViewItemName (getUniqueName()));
if (thisId == identifierString) if (thisId == identifierString)
return this; return this;

@ -78,7 +78,7 @@ public:
initialise its fields with the appropriate details, and then call its launchAsync() initialise its fields with the appropriate details, and then call its launchAsync()
method to launch the dialog. method to launch the dialog.
*/ */
struct LaunchOptions struct JUCE_API LaunchOptions
{ {
LaunchOptions() noexcept; LaunchOptions() noexcept;

@ -127,7 +127,7 @@ public:
//============================================================================== //==============================================================================
/** @internal */ /** @internal */
virtual void addToDesktop (int windowStyleFlags, void* nativeWindowToAttachTo = nullptr) override; void addToDesktop (int windowStyleFlags, void* nativeWindowToAttachTo = nullptr) override;
protected: protected:
//============================================================================== //==============================================================================

@ -226,6 +226,9 @@ void WebBrowserComponent::goToURL (const String& url,
blankPageShown = false; blankPageShown = false;
if (browser->browser == nullptr)
checkWindowAssociation();
browser->goToURL (url, headers, postData); browser->goToURL (url, headers, postData);
} }
@ -262,7 +265,10 @@ void WebBrowserComponent::refresh()
void WebBrowserComponent::paint (Graphics& g) void WebBrowserComponent::paint (Graphics& g)
{ {
if (browser->browser == nullptr) if (browser->browser == nullptr)
{
g.fillAll (Colours::white); g.fillAll (Colours::white);
checkWindowAssociation();
}
} }
void WebBrowserComponent::checkWindowAssociation() void WebBrowserComponent::checkWindowAssociation()

@ -34,6 +34,11 @@ new version here but you see it in the change log, it's because this version is
Changelog Changelog
--------- ---------
#### Version 0.8.0
* New UI
* Fixed mono mode ticks on lower frequencies
* SynprezFM preset are now in a submenu
#### Version 0.7.0 #### Version 0.7.0
* Preliminary Algo 4 & 6 feedback support * Preliminary Algo 4 & 6 feedback support
* DX Engine 'Dirty DX' emulation, including one based on OPL chips * DX Engine 'Dirty DX' emulation, including one based on OPL chips
@ -126,6 +131,7 @@ FAQ (possibly)
Credits & thanks Credits & thanks
---------------- ----------------
* DX Synth engine : Raph Levien and the [msfa](https://code.google.com/p/music-synthesizer-for-android) team * DX Synth engine : Raph Levien and the [msfa](https://code.google.com/p/music-synthesizer-for-android) team
* AZur Studio - Graphical design
* LP Filter : Filatov Vadim (2DaT); taken from the excellent [Obxd](https://obxd.wordpress.com) project * LP Filter : Filatov Vadim (2DaT); taken from the excellent [Obxd](https://obxd.wordpress.com) project
* PPPlay : Great [OPL3](http://sourceforge.net/projects/peepeeplayer) implementation, with documented code :D * PPPlay : Great [OPL3](http://sourceforge.net/projects/peepeeplayer) implementation, with documented code :D
* DX7 program compilation : Jean-Marc Desprez (author of [SynprezFM](http://www.synprez.com/SynprezFM)) * DX7 program compilation : Jean-Marc Desprez (author of [SynprezFM](http://www.synprez.com/SynprezFM))
@ -134,9 +140,9 @@ Credits & thanks
Planned milestones Planned milestones
------------------ ------------------
* 0.6 DX7 editor + user cartridges
* 0.7 msfa engine tuning * 0.7 msfa engine tuning
* 0.8 UI redesign * 0.8 UI redesign
* 0.8.1 Cartridge browser/editor
TODO - Dexed TODO - Dexed
------------ ------------

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 60 KiB

@ -1,116 +1,225 @@
/*
==============================================================================
ProgramSelector.cpp
Created: 29 Sep 2014 4:45:42pm
Author: Pascal Gauthier
==============================================================================
*/
#include "AlgoDisplay.h"
/** /**
* Algorithm arrangements, based on the DX1 display. *
* Copyright (c) 2014 Pascal Gauthier.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/ */
static const char algoArr[][13] = {
// 1 2 3 4 5 6 7 8 9 A B C D #include "AlgoDisplay.h"
{ 0, 0, 1, 3, 0, 0, 0, 2, 4, 0, 0, 5, -6 }, // 1 #include "DXLookNFeel.h"
{ 0, 0, 1, 3, 0, 0, 0, -2, 4, 0, 0, 5, 6 }, // 2
{ 0, 0, 1, 4, 0, 0, 0, 2, 5, 0, 3, -6, 0 }, // 3
{ 0, 0, 1, -4, 0, 0, 0, 2, -5, 0, 3, -6, 0 }, // 4
{ 0, 1, 3, 5, 0, 0, 2, 4, -6, 0, 0, 0, 0 }, // 5
{ 0, 1, 3, -5, 0, 0, 2, 4, -6, 0, 0, 0, 0 }, // 6
{ 0, 1, 3, 0, 0, 0, 2, 4, 5, 0, 0, -6, 0 }, // 7
{ 0, 1, 3, 0, 0, 0, 2, -4, 5, 0, 0, 6, 0 }, // 8
{ 0, 1, 3, 0, 0, 0, -2, 4, 5, 0, 0, 6, 0 }, // 9
{ 0, 0, 4, 1, 0, 0, 5, 6, 2, 0, 0, -3, 0 }, // 10
{ 0, 0, 4, 1, 0, 0, 5, -6, 2, 0, 0, 3, 0 }, // 11
{ 0, 0, 3, 0, 1, 0, 4, 5, 6, -2, 0, 0, 0 }, // 12
{ 0, 0, 3, 0, 1, 0, 4, 5, -6, 2, 0, 0, 0 }, // 13
// 1 2 3 4 5 6 7 8 9 A B C D
{ 0, 0, 1, 3, 0, 0, 0, 2, 4, 0, 5, -6, 0 }, // 14
{ 0, 0, 1, 3, 0, 0, 0, -2, 4, 0, 5, 6, 0 }, // 15
{ 0, 0, 1, 0, 0, 0, 2, 3, 5, 0, 4, -6, 0 }, // 16
{ 0, 0, 1, 0, 0, 0, -2, 3, 5, 0, 4, 6, 0 }, // 17
{ 0, 0, 1, 0, 0, 0, 2, -3, 4, 0, 0, 5, 6 }, // 18
{ 0, 0, 1, 4, 5, 0, 0, 2, -6, 0, 3, 0, 0 }, // 19
{ 0, 1, 2, 0, 4, 0, -3, 0, 5, 6, 0, 0, 0 }, // 20
{ 0, 1, 2, 4, 5, 0, -3, 0, 6, 0, 0, 0, 0 }, // 21
{ 0, 1, 3, 4, 5, 0, 2, 0, -6, 0, 0, 0, 0 }, // 22
{ 0, 1, 2, 4, 5, 0, 0, 3, -6, 0, 0, 0, 0 }, // 23
{ 1, 2, 3, 4, 5, 0, 0, 0, -6, 0, 0, 0, 0 }, // 24
{ 1, 2, 3, 4, 5, 0, 0, 0, -6, 0, 0, 0, 0 }, // 25
{ 0, 1, 2, 0, 4, 0, 0, 3, 5, -6, 0, 0, 0 }, // 26
// 1 2 3 4 5 6 7 8 9 A B C D
{ 0, 1, 2, 0, 4, 0, 0, -3, 5, 6, 0, 0, 0 }, // 27
{ 0, 1, 3, 6, 0, 0, 2, 4, 0, 0, -5, 0, 0 }, // 28
{ 0, 1, 2, 3, 5, 0, 0, 0, 4, -6, 0, 0, 0 }, // 29
{ 0, 1, 2, 3, 6, 0, 0, 0, 4, 0, 0, -5, 0 }, // 30
{ 1, 2, 3, 4, 5, 0, 0, 0, 0, -6, 0, 0, 0 }, // 31
{ 1, 2, 3, 4, 5, -6, 0, 0, 0, 0, 0, 0, 0 } // 32
};
AlgoDisplay::AlgoDisplay() { AlgoDisplay::AlgoDisplay() {
static char tmpAlgo = 0; static char tmpAlgo = 0;
algo = &tmpAlgo; algo = &tmpAlgo;
} }
void AlgoDisplay::paint(Graphics &g) { inline void displayOp(Graphics &g, char id, char x, char y, char link, char fb) {
int alg; const int LINE_SZ = 3;
String t(id);
if ( *algo <= 31 ) {
alg = *algo; x *= 25;
} else { y *= 21;
alg = 31; y += 5;
g.setColour(Colours::white);
g.drawText(t, x, y, 16, 12, Justification::centred, true);
g.setColour(DXLookNFeel::fillColour);
switch(link) {
case 0 : // LINE DOWN
g.drawLine(x+8, y+12, x+8, y+21, LINE_SZ);
break;
case 1: // ARROW TO RIGHT
g.drawLine(x+8, y+12, x+8, y+18, LINE_SZ);
g.drawLine(x+7, y+18, x+32, y+18, LINE_SZ);
break;
case 2: // ARROW TO LEFT
g.drawLine(x+8, y+12, x+8, y+18, LINE_SZ);
g.drawLine(x-16, y+18, x+10, y+18, LINE_SZ);
break;
case 3: // LINE
g.drawLine(x+8, y+12, x+8, y+18, LINE_SZ);
g.drawLine(x, y+18, x+26, y+18, LINE_SZ);
break;
case 4: // LEFT * 2
g.drawLine(x+8, y+12, x+8, y+18, LINE_SZ);
g.drawLine(x-16, y+18, x+25, y+18, LINE_SZ);
default :
break;
} }
const char *arr = algoArr[alg];
g.setColour (Colours::black.withAlpha(0.1f)); if ( fb ) {
g.fillRoundedRectangle (0.0f, 0.0f, (float) getWidth(), (float) getHeight(), 1.0f); g.drawLine(x+7, y, x+8, y-4, LINE_SZ);
g.drawLine(x+8, y-4, x+20, y-4, LINE_SZ);
for(int i=0;i<13;i++) { g.drawLine(x+19, y-4, x+19, y+15, LINE_SZ);
int target = arr[i]; g.drawLine(x+18, y+15, x+19, y+15, LINE_SZ);
if ( target == 0 ) g.drawLine(x+8, y+15, x+19, y+15, LINE_SZ);
continue;
if ( i < 6 ) {
drawOp(g, i, 3, target);
continue;
}
if ( i < 10 ){
drawOp(g, (i-6)+1, 2, target);
continue;
}
if ( i < 12 ) {
drawOp(g, (i-10)+2, 1, target);
continue;
}
// last one
drawOp(g, (i-12)+3, 0, target);
} }
String algoTxt;
algoTxt << (alg+1);
g.drawText(algoTxt, 5, 1, 21, 14, Justification::left, true);
} }
void AlgoDisplay::drawOp(Graphics &g, int x, int y, int num) { void AlgoDisplay::paint(Graphics &g) {
String txt;
txt << abs(num); switch(*algo) {
case 0:
int offx = 24; displayOp(g, 6, 3, 0, 0, 1);
int offy = 17; displayOp(g, 5, 3, 1, 0, 0);
displayOp(g, 4, 3, 2, 0, 0);
g.setColour(Colour(0xFF0FC00F)); displayOp(g, 3, 3, 3, 2, 0);
g.fillRect(x*offx+4, y*offy+3, offx-2, offy-1); displayOp(g, 2, 2, 2, 0, 0);
g.setColour(Colour(0xFFFFFFFF)); displayOp(g, 1, 2, 3, 1, 0);
g.drawText(txt, x*offx+3, y*offy+2, offx+2, offy+2, Justification::centred, true); break;
if ( num < 0 ) { case 1:
g.setColour(Colour(0xFFFFFFFF)); displayOp(g, 6, 3, 0, 0, 0);
int x1 = (x*offx) + 24; displayOp(g, 5, 3, 1, 0, 0);
g.drawLine(x1+1, y*offy+3, x1+1, y*offy+offy+2, 3); displayOp(g, 4, 3, 2, 0, 0);
displayOp(g, 3, 3, 3, 2, 0);
displayOp(g, 2, 2, 2, 0, 1);
displayOp(g, 1, 2, 3, 1, 0);
break;
case 2:
displayOp(g, 6, 3, 1, 0, 1);
displayOp(g, 5, 3, 2, 0, 0);
displayOp(g, 4, 3, 3, 2, 0);
displayOp(g, 3, 2, 1, 0, 0);
displayOp(g, 2, 2, 2, 0, 0);
displayOp(g, 1, 2, 3, 1, 0);
break;
case 3: //
displayOp(g, 6, 3, 1, 0, 0);
displayOp(g, 5, 3, 2, 0, 0);
displayOp(g, 4, 3, 3, 2, 0);
displayOp(g, 3, 2, 1, 0, 0);
displayOp(g, 2, 2, 2, 0, 0);
displayOp(g, 1, 2, 3, 1, 0);
break;
case 4:
displayOp(g, 6, 3, 2, 0, 1);
displayOp(g, 5, 3, 3, 2, 0);
displayOp(g, 4, 2, 2, 0, 0);
displayOp(g, 3, 2, 3, 3, 0);
displayOp(g, 2, 1, 2, 0, 0);
displayOp(g, 1, 1, 3, 1, 0);
break;
case 5: //
displayOp(g, 6, 3, 2, 0, 0);
displayOp(g, 5, 3, 3, 2, 0);
displayOp(g, 4, 2, 2, 0, 0);
displayOp(g, 3, 2, 3, 3, 0);
displayOp(g, 2, 1, 2, 0, 0);
displayOp(g, 1, 1, 3, 1, 0);
break;
case 6:
displayOp(g, 6, 3, 1, 0, 1);
displayOp(g, 5, 3, 2, 2, 0);
displayOp(g, 4, 2, 2, 0, 0);
displayOp(g, 3, 2, 3, 2, 0);
displayOp(g, 2, 1, 2, 0, 0);
displayOp(g, 1, 1, 3, 1, 0);
break;
case 7:
displayOp(g, 6, 3, 1, 0, 0);
displayOp(g, 5, 3, 2, 2, 0);
displayOp(g, 4, 2, 2, 0, 1);
displayOp(g, 3, 2, 3, 2, 0);
displayOp(g, 2, 1, 2, 0, 0);
displayOp(g, 1, 1, 3, 1, 0);
break;
case 8:
displayOp(g, 6, 3, 1, 0, 0);
displayOp(g, 5, 3, 2, 2, 0);
displayOp(g, 4, 2, 2, 0, 0);
displayOp(g, 3, 2, 3, 2, 0);
displayOp(g, 2, 1, 2, 0, 1);
displayOp(g, 1, 1, 3, 1, 0);
break;
case 9:
displayOp(g, 6, 2, 2, 0, 0);
displayOp(g, 5, 1, 2, 1, 0);
displayOp(g, 4, 2, 3, 1, 0);
displayOp(g, 3, 3, 1, 0, 1);
displayOp(g, 2, 3, 2, 2, 0);
displayOp(g, 1, 3, 3, 2, 0);
break;
case 10:
displayOp(g, 6, 2, 2, 0, 1);
displayOp(g, 5, 1, 2, 1, 0);
displayOp(g, 4, 2, 3, 1, 0);
displayOp(g, 3, 3, 1, 0, 0);
displayOp(g, 2, 3, 2, 2, 0);
displayOp(g, 1, 3, 3, 2, 0);
break;
case 11:
displayOp(g, 6, 2, 2, 0, 1);
displayOp(g, 5, 1, 2, 1, 0);
displayOp(g, 4, 0, 2, 1, 0);
displayOp(g, 3, 1, 3, 1, 0);
displayOp(g, 2, 3, 2, 0, 0);
displayOp(g, 1, 3, 3, 2, 0);
break;
case 12:
displayOp(g, 6, 2, 2, 0, 0);
displayOp(g, 5, 1, 2, 1, 0);
displayOp(g, 4, 0, 2, 1, 0);
displayOp(g, 3, 1, 3, 1, 0);
displayOp(g, 2, 3, 2, 0, 0);
displayOp(g, 1, 3, 3, 2, 0);
break;
case 13:
displayOp(g, 6, 3, 1, 0, 1);
displayOp(g, 5, 3, 2, 1, 0);
displayOp(g, 4, 3, 3, 2, 0);
displayOp(g, 3, 2, 1, 0, 0);
displayOp(g, 2, 2, 2, 0, 0);
displayOp(g, 1, 2, 3, 1, 0);
break;
case 14:
displayOp(g, 6, 3, 1, 0, 0);
displayOp(g, 5, 3, 2, 1, 0);
displayOp(g, 4, 3, 3, 2, 0);
displayOp(g, 3, 2, 1, 0, 0);
displayOp(g, 2, 2, 2, 0, 0);
displayOp(g, 1, 2, 3, 1, 0);
break;
case 30:
displayOp(g, 6, 4, 2, 0, 1);
displayOp(g, 5, 4, 3, 2, 0);
displayOp(g, 4, 3, 3, 3, 0);
displayOp(g, 3, 2, 3, 3, 0);
displayOp(g, 2, 1, 3, 3, 0);
displayOp(g, 1, 0, 3, 1, 0);
break;
case 31:
displayOp(g, 6, 5, 3, 2, 1);
displayOp(g, 5, 4, 3, 3, 0);
displayOp(g, 4, 3, 3, 3, 0);
displayOp(g, 3, 2, 3, 3, 0);
displayOp(g, 2, 1, 3, 3, 0);
displayOp(g, 1, 0, 3, 1, 0);
break;
default:
break;
} }
} }

@ -1,16 +1,29 @@
/* /**
============================================================================== *
============================================================================== * Copyright (c) 2014 Pascal Gauthier.
*/ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef ALGODISPLAY_H_INCLUDED #ifndef ALGODISPLAY_H_INCLUDED
#define ALGODISPLAY_H_INCLUDED #define ALGODISPLAY_H_INCLUDED
#include "../JuceLibraryCode/JuceHeader.h" #include "../JuceLibraryCode/JuceHeader.h"
class AlgoDisplay : public Component { class AlgoDisplay : public Component {
void drawOp(Graphics &g, int x, int y, int num);
public: public:
AlgoDisplay(); AlgoDisplay();
char *algo; char *algo;

@ -243,7 +243,6 @@ void EnvDisplay::paint(Graphics &g) {
p.lineTo(0, 32); p.lineTo(0, 32);
g.setColour(DXLookNFeel::fillColour); g.setColour(DXLookNFeel::fillColour);
//g.setColour(Colour(0xFF0FC00F).withAlpha(0.3f));
g.fillPath(p); g.fillPath(p);
g.setColour(Colour(0xFFFFFFFF)); g.setColour(Colour(0xFFFFFFFF));
@ -258,8 +257,6 @@ PitchEnvDisplay::PitchEnvDisplay() {
} }
void PitchEnvDisplay::paint(Graphics &g) { void PitchEnvDisplay::paint(Graphics &g) {
g.setColour(Colours::black.withAlpha(0.1f));
g.fillRoundedRectangle (0.0f, 0.0f, (float) getWidth(), (float) getHeight(), 1.0f);
g.setColour(Colours::white); g.setColour(Colours::white);
char *levels = pvalues + 4; char *levels = pvalues + 4;
@ -269,8 +266,8 @@ void PitchEnvDisplay::paint(Graphics &g) {
float total = 0; float total = 0;
int old = pitchenv_tab[levels[3]] + 128; int old = pitchenv_tab[levels[3]] + 128;
// find the scale
// find the scale
for(int i=0;i<4;i++) { for(int i=0;i<4;i++) {
int nw = pitchenv_tab[levels[i]] + 128; int nw = pitchenv_tab[levels[i]] + 128;
dist[i] = ((float)abs(nw - old)) / pitchenv_rate[rates[i]]; dist[i] = ((float)abs(nw - old)) / pitchenv_rate[rates[i]];
@ -283,30 +280,42 @@ void PitchEnvDisplay::paint(Graphics &g) {
total = 4; total = 4;
} }
// TODO : this is WIP
float ratio = 96 / total; float ratio = 96 / total;
int oldx = 0; Path p;
int oldy = 25 - (pitchenv_tab[levels[3]] + 128) / 10; p.startNewSubPath(0, 32);
int i; int x = 0;
for(i=0;i<4;i++) { int y = 25 - (pitchenv_tab[levels[3]] + 128) / 10;
int newx = dist[i] * ratio + oldx; p.lineTo(0,y);
int newy = 25 - (pitchenv_tab[levels[i]] + 128) / 10;
g.drawLine(oldx, oldy, newx, newy, 2); int dx = x;
int dy = y;
int i;
for(i=0;i<4;i++) {
if ( vPos == i ) { if ( vPos == i ) {
g.fillEllipse(oldx-2, oldy-2, 4, 4); dx = x;
dy = y;
} }
oldx = newx; x = dist[i] * ratio + x;
oldy = newy; y = 25 - (pitchenv_tab[levels[i]] + 128) / 10;
p.lineTo(x, y);
} }
if ( vPos == i ) { if ( vPos == i ) {
g.fillEllipse(oldx-2, oldy-2, 4, 4); dx = x;
dy = y;
} }
p.lineTo(96,32);
p.lineTo(0, 32);
g.setColour(DXLookNFeel::fillColour);
g.fillPath(p);
g.setColour(Colours::white);
g.fillEllipse(dx-2, dy-2, 4, 4);
} }
void VuMeter::paint(Graphics &g) { void VuMeter::paint(Graphics &g) {
@ -373,11 +382,20 @@ void ComboBoxImage::paint(Graphics &g) {
g.drawImage(items, 0, 0, items.getWidth(), itemHeight, 0, idx * itemHeight, items.getWidth(), itemHeight); g.drawImage(items, 0, 0, items.getWidth(), itemHeight, 0, idx * itemHeight, items.getWidth(), itemHeight);
} }
ComboBoxImage::ComboBoxImage() {
onPopup = false;
}
void ComboBoxImage::showPopup() { void ComboBoxImage::showPopup() {
int idx = popup.show() - 1; if ( !onPopup ) {
if ( idx < 0 ) onPopup = true;
return; int idx = popup.show() - 1;
setSelectedItemIndex(idx); onPopup = false;
if ( idx < 0 )
return;
setSelectedItemIndex(idx);
}
} }
void ComboBoxImage::setImage(Image image) { void ComboBoxImage::setImage(Image image) {
@ -392,6 +410,18 @@ void ComboBoxImage::setImage(Image image) {
} }
} }
void ComboBoxImage::setImage(Image image, int pos[]) {
items = image;
int numItems = getNumItems();
itemHeight = 26;
for(int i=0;i<numItems;i++) {
Image tmp = image.getClippedImage(Rectangle<int>(0,itemHeight*pos[i], image.getWidth(), itemHeight));
popup.addItem(i+1, getItemText(i), true, false, tmp);
}
}
void ProgramSelector::setInit() { void ProgramSelector::setInit() {
isInInit = true; isInInit = true;
} }

@ -61,15 +61,20 @@ class ComboBoxImage : public ComboBox {
Image items; Image items;
int itemHeight; int itemHeight;
PopupMenu popup; PopupMenu popup;
bool onPopup;
int itemPos[4];
public: public:
ComboBoxImage();
virtual void paint(Graphics &g); virtual void paint(Graphics &g);
virtual void showPopup() override; virtual void showPopup() override;
void setImage(Image image); void setImage(Image image);
void setImage(Image image, int pos[]);
}; };
class ProgramSelector : public ComboBox { class ProgramSelector : public ComboBox {
bool isInInit; bool isInInit;
public: public:
void setInit(); void setInit();
virtual void paint(Graphics &g) override; virtual void paint(Graphics &g) override;

@ -19,22 +19,35 @@
*/ */
#include "DXLookNFeel.h" #include "DXLookNFeel.h"
#include "DXComponents.h"
#include "Dexed.h" #include "Dexed.h"
Colour DXLookNFeel::dxDarkBrown = Colour(0xFF47260D);
Colour DXLookNFeel::dxLightBrown = Colour(0xFFA87B67);
Colour DXLookNFeel::background = Colour(60,50,47); Colour DXLookNFeel::background = Colour(60,50,47);
Colour DXLookNFeel::fillColour = Colour(77,159,151); Colour DXLookNFeel::fillColour = Colour(77,159,151);
Colour DXLookNFeel::lightBackground = Colour(78,72,63);
Colour DXLookNFeel::comboBoxBackground = Colour(20, 18, 18); Colour DXLookNFeel::ctrlBackground = Colour(20,18,18);
Colour DXLookNFeel::comboBoxBackground = Colour(20,18,18);
DXLookNFeel::DXLookNFeel() { DXLookNFeel::DXLookNFeel() {
setColour(TextButton::buttonColourId,Colour(0xFF0FC00F)); setColour(TextButton::buttonColourId,Colour(0xFF0FC00F));
setColour(Slider::rotarySliderOutlineColourId,Colour(0xFF0FC00F)); setColour(Slider::rotarySliderOutlineColourId,Colour(0xFF0FC00F));
setColour(Slider::rotarySliderFillColourId,Colour(0xFFFFFFFF)); setColour(Slider::rotarySliderFillColourId,Colour(0xFFFFFFFF));
setColour(AlertWindow::backgroundColourId,lightBackground);
setColour(TextEditor::backgroundColourId,ctrlBackground);
setColour(TextEditor::textColourId, Colours::white);
setColour(TextEditor::outlineColourId, Colours::transparentBlack);
setColour(ComboBox::backgroundColourId,ctrlBackground);
setColour(ComboBox::textColourId, Colours::white);
setColour(ComboBox::buttonColourId, Colours::white);
setColour(TextButton::textColourOnId, Colours::white);
setColour(TextButton::textColourOffId, Colours::white);
setColour(PopupMenu::backgroundColourId, background);
setColour(PopupMenu::textColourId, Colours::white);
setColour(PopupMenu::highlightedTextColourId, Colours::white);
setColour(PopupMenu::highlightedBackgroundColourId, fillColour);
defaultFont = Typeface::createSystemTypefaceFor(BinaryData::NotoSansRegular_ttf, BinaryData::NotoSansRegular_ttfSize); defaultFont = Typeface::createSystemTypefaceFor(BinaryData::NotoSansRegular_ttf, BinaryData::NotoSansRegular_ttfSize);
defaultFontBold = Typeface::createSystemTypefaceFor(BinaryData::NotoSansBold_ttf, BinaryData::NotoSansBold_ttfSize);
} }
Typeface::Ptr DXLookNFeel::getTypefaceForFont(const Font &) { Typeface::Ptr DXLookNFeel::getTypefaceForFont(const Font &) {
@ -58,46 +71,48 @@ void DXLookNFeel::drawRotarySlider( Graphics &g, int x, int y, int width, int he
g.drawImage(myStrip, (int)rx, (int)ry, 2*(int)radius, 2*(int)radius, 0, frameIdx*myStrip.getWidth(), myStrip.getWidth(), myStrip.getWidth()); g.drawImage(myStrip, (int)rx, (int)ry, 2*(int)radius, 2*(int)radius, 0, frameIdx*myStrip.getWidth(), myStrip.getWidth(), myStrip.getWidth());
}; };
void DXLookNFeel::drawToggleButton(Graphics& g, ToggleButton& button, bool isMouseOverButton, bool isButtonDown) { void DXLookNFeel::drawToggleButton(Graphics& g, ToggleButton& button, bool isMouseOverButton, bool isButtonDown) {
Image myStrip = ImageCache::getFromMemory(BinaryData::Switch_48x26_png, BinaryData::Switch_48x26_pngSize); Image myStrip = ImageCache::getFromMemory(BinaryData::Switch_48x26_png, BinaryData::Switch_48x26_pngSize);
g.drawImage(myStrip, 0, 0, 48, 26, 0, button.getToggleState() ? 0 : 26, 48, 26); g.drawImage(myStrip, 0, 0, 48, 26, 0, button.getToggleState() ? 0 : 26, 48, 26);
} }
void DXLookNFeel::drawButtonBackground(Graphics &g, Button &button, const Colour& backgroundColour, bool isMouseOverButton, bool isButtonDown) { void DXLookNFeel::drawButtonBackground(Graphics &g, Button &button, const Colour& backgroundColour, bool isMouseOverButton, bool isButtonDown) {
Image myStrip = ImageCache::getFromMemory(BinaryData::ButtonUnlabeled_50x30_png, BinaryData::ButtonUnlabeled_50x30_pngSize); Image myStrip = ImageCache::getFromMemory(BinaryData::ButtonUnlabeled_50x30_png, BinaryData::ButtonUnlabeled_50x30_pngSize);
// g.drawImage(myStrip, 0, 0, button.getWidth(), button.getHeight(), 0, isButtonDown ? 30 : 0, 50, 30);
int w = button.getWidth(); int w = button.getWidth();
// dx, dy, dw, dl, sx, sy, sw, sl // dx, dy, dw, dl, sx, sy, sw, sl
g.drawImage(myStrip, 0, 0, 3, 30, 0, button.getToggleState() ? 0 : 26, 3, 30); g.drawImage(myStrip, 0, 0, 3, 30, 0, isButtonDown ? 30 : 0, 3, 30);
g.drawImage(myStrip, 3, 0, w-3, 30, 3, button.getToggleState() ? 0 : 26, 44, 30); g.drawImage(myStrip, 3, 0, w-6, 30, 3, isButtonDown ? 30 : 0, 44, 30);
g.drawImage(myStrip, w-3, 0, w, 30, 47, button.getToggleState() ? 0 : 26, 47, 30); g.drawImage(myStrip, w-3, 0, 3, 30, 47, isButtonDown ? 30 : 0, 47, 30);
} }
void DXLookNFeel::drawLinearSliderBackground (Graphics&, int x, int y, int width, int height, void DXLookNFeel::drawLinearSliderBackground (Graphics&, int x, int y, int width, int height,
float sliderPos, float minSliderPos, float maxSliderPos, float sliderPos, float minSliderPos, float maxSliderPos,
const Slider::SliderStyle, Slider&) { const Slider::SliderStyle, Slider&) {
// NOP
} }
void DXLookNFeel::drawLinearSliderThumb (Graphics& g, int x, int y, int width, int height, void DXLookNFeel::drawLinearSliderThumb (Graphics& g, int x, int y, int width, int height,
float sliderPos, float minSliderPos, float maxSliderPos, float sliderPos, float minSliderPos, float maxSliderPos,
const Slider::SliderStyle, Slider&) { const Slider::SliderStyle, Slider&) {
Image myStrip = ImageCache::getFromMemory(BinaryData::Slider_26x26_png, BinaryData::Slider_26x26_pngSize); Image myStrip = ImageCache::getFromMemory(BinaryData::Slider_26x26_png, BinaryData::Slider_26x26_pngSize);
TRACE("%g %g", sliderPos, minSliderPos);
int p = sliderPos - minSliderPos; int p = sliderPos - minSliderPos;
p -= 6;
p -= 7;
g.drawImage(myStrip, p, 0, 26, 26, 0, 0, 26, 26); g.drawImage(myStrip, p, 0, 26, 26, 0, 0, 26, 26);
} }
Font DXLookNFeel::getTextButtonFont(TextButton& button, int buttonHeight) {
return Font(defaultFontBold);
}
void DXLookNFeel::positionComboBoxText(ComboBox& box, Label& label) {
ComboBox *src = &box;
ComboBoxImage* img = dynamic_cast<ComboBoxImage*>(src);
if(img != 0) {
return;
}
LookAndFeel_V3::positionComboBoxText(box, label);
}

@ -24,18 +24,22 @@
#include "../JuceLibraryCode/JuceHeader.h" #include "../JuceLibraryCode/JuceHeader.h"
class DXLookNFeel : public LookAndFeel_V3 { class DXLookNFeel : public LookAndFeel_V3 {
Typeface::Ptr defaultFont;
public: public:
Typeface::Ptr defaultFont;
Typeface::Ptr defaultFontBold;
static Colour comboBoxBackground; static Colour comboBoxBackground;
static Colour background; static Colour background;
static Colour lightBackground;
static Colour fillColour; static Colour fillColour;
static Colour ctrlBackground;
DXLookNFeel(); DXLookNFeel();
virtual void drawRotarySlider(Graphics &g, int x, int y, int width, int height, float sliderPosProportional, float rotaryStartAngle, float rotaryEndAngle, Slider &slider ); virtual void drawRotarySlider(Graphics &g, int x, int y, int width, int height, float sliderPosProportional, float rotaryStartAngle, float rotaryEndAngle, Slider &slider );
virtual void drawToggleButton(Graphics& g, ToggleButton& button, bool isMouseOverButton, bool isButtonDown); virtual void drawToggleButton(Graphics& g, ToggleButton& button, bool isMouseOverButton, bool isButtonDown);
static Colour dxDarkBrown;
static Colour dxLightBrown;
virtual void drawLinearSliderBackground (Graphics&, int x, int y, int width, int height, virtual void drawLinearSliderBackground (Graphics&, int x, int y, int width, int height,
float sliderPos, float minSliderPos, float maxSliderPos, float sliderPos, float minSliderPos, float maxSliderPos,
@ -48,7 +52,11 @@ public:
virtual void drawButtonBackground (Graphics&, Button&, const Colour& backgroundColour, virtual void drawButtonBackground (Graphics&, Button&, const Colour& backgroundColour,
bool isMouseOverButton, bool isButtonDown) override; bool isMouseOverButton, bool isButtonDown) override;
virtual Font getTextButtonFont(TextButton&, int buttonHeight) override;
virtual Typeface::Ptr getTypefaceForFont(const Font &); virtual Typeface::Ptr getTypefaceForFont(const Font &);
virtual void positionComboBoxText (ComboBox& box, Label& label);
}; };
#endif // DXLOOKNFEEL_H_INCLUDED #endif // DXLOOKNFEEL_H_INCLUDED

@ -116,7 +116,7 @@ GlobalEditor::GlobalEditor ()
addAndMakeVisible (transpose = new Slider ("transpose")); addAndMakeVisible (transpose = new Slider ("transpose"));
transpose->setRange (0, 48, 0); transpose->setRange (0, 48, 0);
transpose->setSliderStyle (Slider::Rotary); transpose->setSliderStyle (Slider::RotaryVerticalDrag);
transpose->setTextBoxStyle (Slider::NoTextBox, false, 80, 20); transpose->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
transpose->addListener (this); transpose->addListener (this);
@ -273,31 +273,14 @@ void GlobalEditor::paint (Graphics& g)
//[UserPrePaint] Add your own custom painting code here.. //[UserPrePaint] Add your own custom painting code here..
//[/UserPrePaint] //[/UserPrePaint]
g.setColour (Colours::black);
g.setFont (Font (10.00f, Font::plain));
g.drawText (TRANS("Volume"),
27, 73, 45, 15,
Justification::centred, true);
g.setColour (Colours::black);
g.setFont (Font (10.00f, Font::plain));
g.drawText (TRANS("Cutoff"),
75, 73, 45, 15,
Justification::centred, true);
g.setColour (Colours::black);
g.setFont (Font (10.00f, Font::plain));
g.drawText (TRANS("Resonance"),
123, 73, 45, 15,
Justification::centred, true);
g.setColour (Colours::black); g.setColour (Colours::black);
g.drawImage (cachedImage_globalEditor_864x144_png, g.drawImage (cachedImage_globalEditor_864x144_png,
0, 0, 864, 144, 0, 0, 864, 144,
0, 0, cachedImage_globalEditor_864x144_png.getWidth(), cachedImage_globalEditor_864x144_png.getHeight()); 0, 0, cachedImage_globalEditor_864x144_png.getWidth(), cachedImage_globalEditor_864x144_png.getHeight());
//[UserPaint] Add your own custom painting code here.. //[UserPaint] Add your own custom painting code here..
Image myStrip = ImageCache::getFromMemory(BinaryData::Light_14x14_png, BinaryData::Light_14x14_pngSize);
g.drawImage(myStrip, 300, 70, 14, 14, 0, monoMode->getToggleState() ? 14 : 0, 14, 14);
//[/UserPaint] //[/UserPaint]
} }
@ -318,13 +301,13 @@ void GlobalEditor::resized()
pitchLevel4->setBounds (823, 56, 34, 34); pitchLevel4->setBounds (823, 56, 34, 34);
pitchLevel1->setBounds (739, 57, 34, 34); pitchLevel1->setBounds (739, 57, 34, 34);
transpose->setBounds (202, 60, 34, 34); transpose->setBounds (202, 60, 34, 34);
oscSync->setBounds (662, 96, 48, 26); oscSync->setBounds (652, 95, 48, 26);
pitchModSens->setBounds (666, 5, 34, 34); pitchModSens->setBounds (666, 5, 34, 34);
lfoSync->setBounds (575, 96, 48, 26); lfoSync->setBounds (571, 96, 48, 26);
pitchEnvDisplay->setBounds (751, 10, 93, 30); pitchEnvDisplay->setBounds (751, 10, 93, 30);
algoDisplay->setBounds (331, 24, 153, 98); algoDisplay->setBounds (338, 30, 146, 91);
feedback->setBounds (500, 76, 34, 34); feedback->setBounds (501, 80, 34, 34);
algo->setBounds (500, 16, 34, 34); algo->setBounds (501, 22, 34, 34);
lcdDisplay->setBounds (6, 87, 140, 13); lcdDisplay->setBounds (6, 87, 140, 13);
output->setBounds (157, 60, 34, 34); output->setBounds (157, 60, 34, 34);
vuOutput->setBounds (6, 103, 140, 8); vuOutput->setBounds (6, 103, 140, 8);
@ -506,6 +489,7 @@ void GlobalEditor::buttonClicked (Button* buttonThatWasClicked)
{ {
//[UserButtonCode_monoMode] -- add your button handler code here.. //[UserButtonCode_monoMode] -- add your button handler code here..
editor->processor->setMonoMode(monoMode->getToggleState()); editor->processor->setMonoMode(monoMode->getToggleState());
repaint();
//[/UserButtonCode_monoMode] //[/UserButtonCode_monoMode]
} }
@ -551,7 +535,7 @@ void GlobalEditor::setSystemMessage(String msg) {
} }
void GlobalEditor::setParamMessage(String msg) { void GlobalEditor::setParamMessage(String msg) {
//lcdDisplay->paramMsg = msg; lcdDisplay->paramMsg = msg;
} }
void GlobalEditor::updateDisplay() { void GlobalEditor::updateDisplay() {
@ -590,12 +574,6 @@ BEGIN_JUCER_METADATA
snapPixels="8" snapActive="0" snapShown="1" overlayOpacity="0.330" snapPixels="8" snapActive="0" snapShown="1" overlayOpacity="0.330"
fixedSize="1" initialWidth="864" initialHeight="144"> fixedSize="1" initialWidth="864" initialHeight="144">
<BACKGROUND backgroundColour="ffffff"> <BACKGROUND backgroundColour="ffffff">
<TEXT pos="27 73 45 15" fill="solid: ff000000" hasStroke="0" text="Volume"
fontname="Default font" fontsize="10" bold="0" italic="0" justification="36"/>
<TEXT pos="75 73 45 15" fill="solid: ff000000" hasStroke="0" text="Cutoff"
fontname="Default font" fontsize="10" bold="0" italic="0" justification="36"/>
<TEXT pos="123 73 45 15" fill="solid: ff000000" hasStroke="0" text="Resonance"
fontname="Default font" fontsize="10" bold="0" italic="0" justification="36"/>
<IMAGE pos="0 0 864 144" resource="globalEditor_864x144_png" opacity="1" <IMAGE pos="0 0 864 144" resource="globalEditor_864x144_png" opacity="1"
mode="0"/> mode="0"/>
</BACKGROUND> </BACKGROUND>
@ -657,30 +635,30 @@ BEGIN_JUCER_METADATA
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="transpose" id="7d1266b1c1534947" memberName="transpose" <SLIDER name="transpose" id="7d1266b1c1534947" memberName="transpose"
virtualName="" explicitFocusOrder="0" pos="202 60 34 34" min="0" virtualName="" explicitFocusOrder="0" pos="202 60 34 34" min="0"
max="48" int="0" style="Rotary" textBoxPos="NoTextBox" textBoxEditable="1" max="48" int="0" style="RotaryVerticalDrag" textBoxPos="NoTextBox"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<TOGGLEBUTTON name="oscSync" id="8f3fe641537cd00" memberName="oscSync" virtualName="" <TOGGLEBUTTON name="oscSync" id="8f3fe641537cd00" memberName="oscSync" virtualName=""
explicitFocusOrder="0" pos="662 96 48 26" buttonText="" connectedEdges="0" explicitFocusOrder="0" pos="652 95 48 26" buttonText="" connectedEdges="0"
needsCallback="0" radioGroupId="0" state="0"/> needsCallback="0" radioGroupId="0" state="0"/>
<SLIDER name="pitchModSens" id="904f73df85a9f886" memberName="pitchModSens" <SLIDER name="pitchModSens" id="904f73df85a9f886" memberName="pitchModSens"
virtualName="" explicitFocusOrder="0" pos="666 5 34 34" min="0" virtualName="" explicitFocusOrder="0" pos="666 5 34 34" min="0"
max="7" int="0" style="RotaryVerticalDrag" textBoxPos="NoTextBox" max="7" int="0" style="RotaryVerticalDrag" textBoxPos="NoTextBox"
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<TOGGLEBUTTON name="lfoSync" id="ff92bb0a5a4f7187" memberName="lfoSync" virtualName="" <TOGGLEBUTTON name="lfoSync" id="ff92bb0a5a4f7187" memberName="lfoSync" virtualName=""
explicitFocusOrder="0" pos="575 96 48 26" buttonText="" connectedEdges="0" explicitFocusOrder="0" pos="571 96 48 26" buttonText="" connectedEdges="0"
needsCallback="0" radioGroupId="0" state="0"/> needsCallback="0" radioGroupId="0" state="0"/>
<GENERICCOMPONENT name="pitchEnvDisplay" id="9ddaae8ef924a038" memberName="pitchEnvDisplay" <GENERICCOMPONENT name="pitchEnvDisplay" id="9ddaae8ef924a038" memberName="pitchEnvDisplay"
virtualName="" explicitFocusOrder="0" pos="751 10 93 30" class="PitchEnvDisplay" virtualName="" explicitFocusOrder="0" pos="751 10 93 30" class="PitchEnvDisplay"
params=""/> params=""/>
<GENERICCOMPONENT name="algoDisplay" id="b26fb9e3b5f0bc37" memberName="algoDisplay" <GENERICCOMPONENT name="algoDisplay" id="b26fb9e3b5f0bc37" memberName="algoDisplay"
virtualName="" explicitFocusOrder="0" pos="331 24 153 98" class="AlgoDisplay" virtualName="" explicitFocusOrder="0" pos="338 30 146 91" class="AlgoDisplay"
params=""/> params=""/>
<SLIDER name="feedback" id="4fac1940c29ab8c" memberName="feedback" virtualName="" <SLIDER name="feedback" id="4fac1940c29ab8c" memberName="feedback" virtualName=""
explicitFocusOrder="0" pos="500 76 34 34" min="0" max="7" int="1" explicitFocusOrder="0" pos="501 80 34 34" min="0" max="7" int="1"
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="1"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="algo" id="8a226ddf9bbff752" memberName="algo" virtualName="" <SLIDER name="algo" id="8a226ddf9bbff752" memberName="algo" virtualName=""
explicitFocusOrder="0" pos="500 16 34 34" min="1" max="32" int="1" explicitFocusOrder="0" pos="501 22 34 34" min="1" max="32" int="1"
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="0" style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="0"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/> textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<GENERICCOMPONENT name="lcdDisplay" id="30c7bb8f114cbbe3" memberName="lcdDisplay" <GENERICCOMPONENT name="lcdDisplay" id="30c7bb8f114cbbe3" memberName="lcdDisplay"

@ -108,7 +108,7 @@ OperatorEditor::OperatorEditor ()
addAndMakeVisible (detune = new Slider ("detune")); addAndMakeVisible (detune = new Slider ("detune"));
detune->setRange (-7, 7, 1); detune->setRange (-7, 7, 1);
detune->setSliderStyle (Slider::Rotary); detune->setSliderStyle (Slider::RotaryVerticalDrag);
detune->setTextBoxStyle (Slider::NoTextBox, true, 80, 20); detune->setTextBoxStyle (Slider::NoTextBox, true, 80, 20);
detune->addListener (this); detune->addListener (this);
@ -183,13 +183,15 @@ OperatorEditor::OperatorEditor ()
kbdLeftCurve->addItem("-EX", 2); kbdLeftCurve->addItem("-EX", 2);
kbdLeftCurve->addItem("+EX", 3); kbdLeftCurve->addItem("+EX", 3);
kbdLeftCurve->addItem("+LN", 4); kbdLeftCurve->addItem("+LN", 4);
kbdLeftCurve->setImage(tmp); int posLeft[] = {0,5,4,3};
kbdLeftCurve->setImage(tmp, posLeft);
kbdRightCurve->addItem("-LN", 1); kbdRightCurve->addItem("-LN", 1);
kbdRightCurve->addItem("-EX", 2); kbdRightCurve->addItem("-EX", 2);
kbdRightCurve->addItem("+EX", 3); kbdRightCurve->addItem("+EX", 3);
kbdRightCurve->addItem("+LN", 4); kbdRightCurve->addItem("+LN", 4);
kbdRightCurve->setImage(tmp); int posRight[] = {3,2,1,0};
kbdRightCurve->setImage(tmp, posRight);
//[/Constructor] //[/Constructor]
} }
@ -250,7 +252,7 @@ void OperatorEditor::paint (Graphics& g)
// 129 x 24 // 129 x 24
g.drawImage(myStrip, 128, 24, 14, 14, 0, state ? 0 : 14, 14, 14); g.drawImage(myStrip, 128, 24, 14, 14, 0, state ? 0 : 14, 14, 14);
// 198 x 24 // 199 x 24
g.drawImage(myStrip, 199, 24, 14, 14, 0, !state ? 0 : 14, 14, 14); g.drawImage(myStrip, 199, 24, 14, 14, 0, !state ? 0 : 14, 14, 14);
//[/UserPaint] //[/UserPaint]
@ -271,7 +273,7 @@ void OperatorEditor::resized()
opCoarse->setBounds (41, 24, 34, 34); opCoarse->setBounds (41, 24, 34, 34);
khzDisplay->setBounds (15, 10, 95, 10); khzDisplay->setBounds (15, 10, 95, 10);
detune->setBounds (6, 24, 34, 34); detune->setBounds (6, 24, 34, 34);
envDisplay->setBounds (16, 82, 94, 30); envDisplay->setBounds (16, 83, 94, 30);
sclLeftLevel->setBounds (131, 115, 34, 34); sclLeftLevel->setBounds (131, 115, 34, 34);
sclRightLevel->setBounds (241, 115, 34, 34); sclRightLevel->setBounds (241, 115, 34, 34);
sclLvlBrkPt->setBounds (178, 130, 54, 24); sclLvlBrkPt->setBounds (178, 130, 54, 24);
@ -549,14 +551,13 @@ BEGIN_JUCER_METADATA
explicitFocusOrder="0" pos="15 10 95 10" bkgCol="6a000000" textCol="ffffffff" explicitFocusOrder="0" pos="15 10 95 10" bkgCol="6a000000" textCol="ffffffff"
outlineCol="0" edTextCol="ff000000" edBkgCol="0" labelText="1,000 kHz" outlineCol="0" edTextCol="ff000000" edBkgCol="0" labelText="1,000 kHz"
editableSingleClick="0" editableDoubleClick="0" focusDiscardsChanges="0" editableSingleClick="0" editableDoubleClick="0" focusDiscardsChanges="0"
fontname="Default font" fontsize="12.599999999999999645" bold="0" fontname="Default font" fontsize="12.6" bold="0" italic="0" justification="36"/>
italic="0" justification="36"/>
<SLIDER name="detune" id="f093ec8defca2fc2" memberName="detune" virtualName="" <SLIDER name="detune" id="f093ec8defca2fc2" memberName="detune" virtualName=""
explicitFocusOrder="0" pos="6 24 34 34" min="-7" max="7" int="1" explicitFocusOrder="0" pos="6 24 34 34" min="-7" max="7" int="1"
style="Rotary" textBoxPos="NoTextBox" textBoxEditable="0" textBoxWidth="80" style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="0"
textBoxHeight="20" skewFactor="1"/> textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<GENERICCOMPONENT name="envDisplay" id="b18856de924c6340" memberName="envDisplay" <GENERICCOMPONENT name="envDisplay" id="b18856de924c6340" memberName="envDisplay"
virtualName="" explicitFocusOrder="0" pos="16 82 94 30" class="EnvDisplay" virtualName="" explicitFocusOrder="0" pos="16 83 94 30" class="EnvDisplay"
params=""/> params=""/>
<SLIDER name="sclLeftLevel" id="bd6f338ae68e454f" memberName="sclLeftLevel" <SLIDER name="sclLeftLevel" id="bd6f338ae68e454f" memberName="sclLeftLevel"
virtualName="" explicitFocusOrder="0" pos="131 115 34 34" tooltip="Keyboard Scale Level Left Depth " virtualName="" explicitFocusOrder="0" pos="131 115 34 34" tooltip="Keyboard Scale Level Left Depth "

@ -72,6 +72,9 @@ ParamDialog::ParamDialog ()
engineReso->addItem (TRANS("OPL Series"), 3); engineReso->addItem (TRANS("OPL Series"), 3);
engineReso->addListener (this); engineReso->addListener (this);
addAndMakeVisible (showKeyboard = new ToggleButton ("showKeyboard"));
showKeyboard->setButtonText (String::empty);
//[UserPreSize] //[UserPreSize]
//[/UserPreSize] //[/UserPreSize]
@ -106,6 +109,7 @@ ParamDialog::~ParamDialog()
sysexOut = nullptr; sysexOut = nullptr;
sysexChl = nullptr; sysexChl = nullptr;
engineReso = nullptr; engineReso = nullptr;
showKeyboard = nullptr;
//[Destructor]. You can add your own custom destruction code here.. //[Destructor]. You can add your own custom destruction code here..
@ -118,7 +122,7 @@ void ParamDialog::paint (Graphics& g)
//[UserPrePaint] Add your own custom painting code here.. //[UserPrePaint] Add your own custom painting code here..
//[/UserPrePaint] //[/UserPrePaint]
g.fillAll (Colour (0xff4e270d)); g.fillAll (Colour (0xff3c322f));
g.setColour (Colours::white); g.setColour (Colours::white);
g.setFont (Font (15.00f, Font::plain)); g.setFont (Font (15.00f, Font::plain));
@ -135,13 +139,13 @@ void ParamDialog::paint (Graphics& g)
g.setColour (Colours::white); g.setColour (Colours::white);
g.setFont (Font (15.00f, Font::plain)); g.setFont (Font (15.00f, Font::plain));
g.drawText (TRANS("DX7 In"), g.drawText (TRANS("DX7 In"),
28, 226, 131, 23, 27, 221, 131, 23,
Justification::centredLeft, true); Justification::centredLeft, true);
g.setColour (Colours::white); g.setColour (Colours::white);
g.setFont (Font (15.00f, Font::plain)); g.setFont (Font (15.00f, Font::plain));
g.drawText (TRANS("DX7 Out"), g.drawText (TRANS("DX7 Out"),
30, 267, 131, 23, 27, 261, 131, 23,
Justification::centredLeft, true); Justification::centredLeft, true);
g.setColour (Colours::white); g.setColour (Colours::white);
@ -162,6 +166,12 @@ void ParamDialog::paint (Graphics& g)
g.setColour (Colours::black); g.setColour (Colours::black);
g.fillRect (22, 194, 306, 1); g.fillRect (22, 194, 306, 1);
g.setColour (Colours::white);
g.setFont (Font (15.00f, Font::plain));
g.drawText (TRANS("Show Keyboard"),
19, 101, 276, 23,
Justification::centredLeft, true);
//[UserPaint] Add your own custom painting code here.. //[UserPaint] Add your own custom painting code here..
//[/UserPaint] //[/UserPaint]
} }
@ -174,6 +184,7 @@ void ParamDialog::resized()
sysexOut->setBounds (104, 264, 224, 24); sysexOut->setBounds (104, 264, 224, 24);
sysexChl->setBounds (264, 304, 72, 24); sysexChl->setBounds (264, 304, 72, 24);
engineReso->setBounds (160, 152, 168, 24); engineReso->setBounds (160, 152, 168, 24);
showKeyboard->setBounds (264, 96, 56, 24);
//[UserResized] Add your own custom resize handling here.. //[UserResized] Add your own custom resize handling here..
//[/UserResized] //[/UserResized]
} }
@ -233,7 +244,7 @@ void ParamDialog::comboBoxChanged (ComboBox* comboBoxThatHasChanged)
//[MiscUserCode] You can add your own definitions of your custom methods or any other code here... //[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
void ParamDialog::setDialogValues(Controllers &c, SysexComm &mgr, int reso) { void ParamDialog::setDialogValues(Controllers &c, SysexComm &mgr, int reso, bool showKey) {
pitchRange->setValue(c.values_[kControllerPitchRange]); pitchRange->setValue(c.values_[kControllerPitchRange]);
pitchStep->setValue(c.values_[kControllerPitchStep]); pitchStep->setValue(c.values_[kControllerPitchStep]);
sysexChl->setValue(mgr.getChl() + 1); sysexChl->setValue(mgr.getChl() + 1);
@ -249,9 +260,10 @@ void ParamDialog::setDialogValues(Controllers &c, SysexComm &mgr, int reso) {
sysexOut->setSelectedItemIndex(idx); sysexOut->setSelectedItemIndex(idx);
engineReso->setSelectedItemIndex(reso); engineReso->setSelectedItemIndex(reso);
showKeyboard->setToggleState(showKey, false);
} }
bool ParamDialog::getDialogValues(Controllers &c, SysexComm &mgr, int *reso) { bool ParamDialog::getDialogValues(Controllers &c, SysexComm &mgr, int *reso, bool *showKey) {
bool ret = true; bool ret = true;
c.values_[kControllerPitchRange] = pitchRange->getValue(); c.values_[kControllerPitchRange] = pitchRange->getValue();
@ -261,7 +273,7 @@ bool ParamDialog::getDialogValues(Controllers &c, SysexComm &mgr, int *reso) {
mgr.setChl(sysexChl->getValue() - 1); mgr.setChl(sysexChl->getValue() - 1);
*reso = engineReso->getSelectedItemIndex(); *reso = engineReso->getSelectedItemIndex();
*showKey = showKeyboard->getToggleState();
return ret; return ret;
} }
@ -281,14 +293,14 @@ BEGIN_JUCER_METADATA
parentClasses="public Component" constructorParams="" variableInitialisers="" parentClasses="public Component" constructorParams="" variableInitialisers=""
snapPixels="8" snapActive="1" snapShown="1" overlayOpacity="0.330" snapPixels="8" snapActive="1" snapShown="1" overlayOpacity="0.330"
fixedSize="1" initialWidth="350" initialHeight="350"> fixedSize="1" initialWidth="350" initialHeight="350">
<BACKGROUND backgroundColour="ff4e270d"> <BACKGROUND backgroundColour="ff3c322f">
<TEXT pos="20 18 276 23" fill="solid: ffffffff" hasStroke="0" text="Pitch Bend Range" <TEXT pos="20 18 276 23" fill="solid: ffffffff" hasStroke="0" text="Pitch Bend Range"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/> fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
<TEXT pos="20 58 276 23" fill="solid: ffffffff" hasStroke="0" text="Pitch Bend Step" <TEXT pos="20 58 276 23" fill="solid: ffffffff" hasStroke="0" text="Pitch Bend Step"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/> fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
<TEXT pos="28 226 131 23" fill="solid: ffffffff" hasStroke="0" text="DX7 In" <TEXT pos="27 221 131 23" fill="solid: ffffffff" hasStroke="0" text="DX7 In"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/> fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
<TEXT pos="30 267 131 23" fill="solid: ffffffff" hasStroke="0" text="DX7 Out" <TEXT pos="27 261 131 23" fill="solid: ffffffff" hasStroke="0" text="DX7 Out"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/> fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
<TEXT pos="27 306 245 23" fill="solid: ffffffff" hasStroke="0" text="DX7 Channel" <TEXT pos="27 306 245 23" fill="solid: ffffffff" hasStroke="0" text="DX7 Channel"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/> fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
@ -296,6 +308,8 @@ BEGIN_JUCER_METADATA
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/> fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
<RECT pos="22 138 306 1" fill="solid: ff000000" hasStroke="0"/> <RECT pos="22 138 306 1" fill="solid: ff000000" hasStroke="0"/>
<RECT pos="22 194 306 1" fill="solid: ff000000" hasStroke="0"/> <RECT pos="22 194 306 1" fill="solid: ff000000" hasStroke="0"/>
<TEXT pos="19 101 276 23" fill="solid: ffffffff" hasStroke="0" text="Show Keyboard"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
</BACKGROUND> </BACKGROUND>
<SLIDER name="pitchRange" id="7409be5a8dfaa91" memberName="pitchRange" <SLIDER name="pitchRange" id="7409be5a8dfaa91" memberName="pitchRange"
virtualName="" explicitFocusOrder="0" pos="264 16 72 24" min="0" virtualName="" explicitFocusOrder="0" pos="264 16 72 24" min="0"
@ -319,6 +333,9 @@ BEGIN_JUCER_METADATA
virtualName="" explicitFocusOrder="0" pos="160 152 168 24" editable="0" virtualName="" explicitFocusOrder="0" pos="160 152 168 24" editable="0"
layout="33" items="Modern (Direct)&#10;Mark I&#10;OPL Series" layout="33" items="Modern (Direct)&#10;Mark I&#10;OPL Series"
textWhenNonSelected="" textWhenNoItems="(no choices)"/> textWhenNonSelected="" textWhenNoItems="(no choices)"/>
<TOGGLEBUTTON name="showKeyboard" id="c963d2cb8e49ffd7" memberName="showKeyboard"
virtualName="" explicitFocusOrder="0" pos="264 96 56 24" buttonText=""
connectedEdges="0" needsCallback="0" radioGroupId="0" state="0"/>
</JUCER_COMPONENT> </JUCER_COMPONENT>
END_JUCER_METADATA END_JUCER_METADATA

@ -47,8 +47,8 @@ public:
//============================================================================== //==============================================================================
//[UserMethods] -- You can add your own custom methods in this section. //[UserMethods] -- You can add your own custom methods in this section.
void setDialogValues(Controllers &c, SysexComm &mgr, int reso); void setDialogValues(Controllers &c, SysexComm &mgr, int reso, bool showKeyboard);
bool getDialogValues(Controllers &c, SysexComm &mgr, int *reso); bool getDialogValues(Controllers &c, SysexComm &mgr, int *reso, bool *showKeyboard);
//[/UserMethods] //[/UserMethods]
void paint (Graphics& g); void paint (Graphics& g);
@ -69,6 +69,7 @@ private:
ScopedPointer<ComboBox> sysexOut; ScopedPointer<ComboBox> sysexOut;
ScopedPointer<Slider> sysexChl; ScopedPointer<Slider> sysexChl;
ScopedPointer<ComboBox> engineReso; ScopedPointer<ComboBox> engineReso;
ScopedPointer<ToggleButton> showKeyboard;
//============================================================================== //==============================================================================

@ -390,6 +390,13 @@ void CartridgeManager::rebuildMenu() {
completeCarts.clear(); completeCarts.clear();
completeCarts.addItem(1, cartNames[0]);
PopupMenu synprez;
for(int i=1;i<cartNames.size();i++) {
synprez.addItem(i+1, cartNames[i]);
}
completeCarts.addSubMenu("SynprezFM", synprez, true);
if ( userCartFile.exists() ) { if ( userCartFile.exists() ) {
zipIdx = 0; zipIdx = 0;
ZipFile userZip(userCartFile); ZipFile userZip(userCartFile);
@ -404,18 +411,11 @@ void CartridgeManager::rebuildMenu() {
} else { } else {
lastModifiedUserCartFile = Time(0); lastModifiedUserCartFile = Time(0);
} }
for(int i=0;i<cartNames.size();i++) {
completeCarts.addItem(i+1, cartNames[i]);
}
} }
PopupMenu *CartridgeManager::getCarts() { PopupMenu *CartridgeManager::getCarts() {
Time t = userCartFile.getLastModificationTime(); Time t = userCartFile.getLastModificationTime();
TRACE("Usercart file %s exists: %d", userCartFile.getFullPathName().toRawUTF8(), userCartFile.exists());
TRACE("DIFF TM: %s %s", t.toString(true, true).toRawUTF8(), lastModifiedUserCartFile.toString(true, true).toRawUTF8());
if ( t != lastModifiedUserCartFile || completeCarts.getNumItems() == 0 ) { if ( t != lastModifiedUserCartFile || completeCarts.getNumItems() == 0 ) {
rebuildMenu(); rebuildMenu();
} }

@ -72,7 +72,7 @@ public:
if ( ! (midi->isInputActive() || midi->isOutputActive() ) ) if ( ! (midi->isInputActive() || midi->isOutputActive() ) )
return; return;
g.setColour(DXLookNFeel::dxDarkBrown); //g.setColour(DXLookNFeel::dxDarkBrown);
g.fillRect(0, 0, getWidth(), getHeight()); g.fillRect(0, 0, getWidth(), getHeight());
g.setColour(Colours::black); g.setColour(Colours::black);
g.drawSingleLineText("DX7 ", 0, 13); g.drawSingleLineText("DX7 ", 0, 13);
@ -115,13 +115,6 @@ DexedAudioProcessorEditor::DexedAudioProcessorEditor (DexedAudioProcessor* owner
processor = ownerFilter; processor = ownerFilter;
//addAndMakeVisible (&programs);
//programs.setEditableText(false);
//programs.setJustificationType (Justification::centredLeft);
//programs.setTextWhenNothingSelected (String::empty);
// programs.setBounds(167, 6, 160, 18);
addAndMakeVisible(midiMonitor = new MidiMonitor(&processor->sysexComm)); addAndMakeVisible(midiMonitor = new MidiMonitor(&processor->sysexComm));
midiMonitor->setBounds(645, 6, 110, 18); midiMonitor->setBounds(645, 6, 110, 18);
@ -278,7 +271,7 @@ void DexedAudioProcessorEditor::parmShow() {
AlertWindow window("","", AlertWindow::NoIcon, this); AlertWindow window("","", AlertWindow::NoIcon, this);
ParamDialog param; ParamDialog param;
param.setColour(AlertWindow::backgroundColourId, Colour(0x32FFFFFF)); param.setColour(AlertWindow::backgroundColourId, Colour(0x32FFFFFF));
param.setDialogValues(processor->controllers, processor->sysexComm, tp); param.setDialogValues(processor->controllers, processor->sysexComm, tp, processor->showKeyboard);
window.addCustomComponent(&param); window.addCustomComponent(&param);
window.addButton("OK", 0); window.addButton("OK", 0);
@ -286,7 +279,7 @@ void DexedAudioProcessorEditor::parmShow() {
if ( window.runModalLoop() != 0 ) if ( window.runModalLoop() != 0 )
return; return;
bool ret = param.getDialogValues(processor->controllers, processor->sysexComm, &tp); bool ret = param.getDialogValues(processor->controllers, processor->sysexComm, &tp, &processor->showKeyboard);
processor->setEngineType(tp); processor->setEngineType(tp);
processor->savePreference(); processor->savePreference();
@ -385,8 +378,8 @@ void DexedAudioProcessorEditor::storeProgram() {
dialog.addComboBox(String("Dest"), programs); dialog.addComboBox(String("Dest"), programs);
dialog.addButton("OK", 0, KeyPress(KeyPress::returnKey)); dialog.addButton("OK", 0, KeyPress(KeyPress::returnKey));
dialog.addButton("Cancel", 1, KeyPress(KeyPress::escapeKey)); dialog.addButton("CANCEL", 1, KeyPress(KeyPress::escapeKey));
dialog.addButton("External File", 2, KeyPress()); dialog.addButton("EXTERNAL FILE", 2, KeyPress());
int response = dialog.runModalLoop(); int response = dialog.runModalLoop();
if ( response == 2 ) { if ( response == 2 ) {

@ -179,7 +179,7 @@ void CtrlDX::updateDisplayName() {
} }
String msg; String msg;
msg << label << " = " << getValueDisplay(); msg << label << " = " << getValueDisplay();
//editor->global.setParamMessage(msg); editor->global.setParamMessage(msg);
editor->global.repaint(); editor->global.repaint();
} }
@ -516,6 +516,10 @@ void DexedAudioProcessor::loadPreference() {
if ( prop.containsKey( String("engineType" ) ) ) { if ( prop.containsKey( String("engineType" ) ) ) {
engineType = prop.getIntValue( String("engineType") ); engineType = prop.getIntValue( String("engineType") );
} }
if ( prop.containsKey( String("showKeyboard") ) ) {
showKeyboard = prop.getIntValue( String("showKeyboard") );
}
} }
void DexedAudioProcessor::savePreference() { void DexedAudioProcessor::savePreference() {
@ -529,6 +533,8 @@ void DexedAudioProcessor::savePreference() {
prop.setValue(String("sysexOut"), sysexComm.getOutput()); prop.setValue(String("sysexOut"), sysexComm.getOutput());
prop.setValue(String("sysexChl"), sysexComm.getChl()); prop.setValue(String("sysexChl"), sysexComm.getChl());
prop.setValue(String("showKeyboard"), showKeyboard);
//prop.setValue(String("engineResolution"), engineResolution); //prop.setValue(String("engineResolution"), engineResolution);
prop.save(); prop.save();

@ -115,6 +115,7 @@ class DexedAudioProcessor : public AudioProcessor, public AsyncUpdater, public
EngineOpl engineOpl; EngineOpl engineOpl;
public : public :
// in MIDI units (0x4000 is neutral) // in MIDI units (0x4000 is neutral)
Controllers controllers; Controllers controllers;
StringArray programNames; StringArray programNames;
@ -130,6 +131,8 @@ public :
float vuSignal; float vuSignal;
bool showKeyboard;
int getEngineType(); int getEngineType();
void setEngineType(int rs); void setEngineType(int rs);

@ -127,7 +127,6 @@ static const uint8_t pitchmodsenstab[] = {
0, 10, 20, 33, 55, 92, 153, 255 0, 10, 20, 33, 55, 92, 153, 255
}; };
// 0, 66, 109, 255 // 0, 66, 109, 255
static const uint32_t ampmodsenstab[] = { static const uint32_t ampmodsenstab[] = {
0, 4342338, 7171437, 16777216 0, 4342338, 7171437, 16777216
@ -271,6 +270,7 @@ void Dx7Note::transferState(Dx7Note &src) {
for (int i=0;i<6;i++) { for (int i=0;i<6;i++) {
env_[i].transfer(src.env_[i]); env_[i].transfer(src.env_[i]);
params_[i].gain_out = src.params_[i].gain_out; params_[i].gain_out = src.params_[i].gain_out;
params_[i].phase = src.params_[i].phase;
} }
} }

Loading…
Cancel
Save