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"; };
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"; };
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"; };
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"; };
@ -910,6 +911,7 @@
66E042C6FFE93F0E19B32F09,
C7577AF98915C39EDCEC259A,
1D72CD485011A4EA3E6B0FD5,
5A366F36F3B4E50587A30351,
15B75D829C40872D542A38B8,
0E3FA3D7B11FC7D19CC634BE, ); name = Resources; sourceTree = "<group>"; };
0652CE27AE4971C99654E3BF = {isa = PBXGroup; children = (

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

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

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

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

@ -26,6 +26,8 @@
file="Resources/ui/Slider_26x26.png"/>
<FILE id="g1Wwz3" name="NotoSans-Regular.ttf" compile="0" resource="1"
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="xxGEA4" name="about.png" compile="0" resource="1" file="Resources/about.png"/>
</GROUP>

File diff suppressed because it is too large Load Diff

@ -16,10 +16,10 @@ namespace BinaryData
const int ButtonUnlabeled_50x30_pngSize = 1850;
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;
const int LFO_36_26_pngSize = 1666;
const int LFO_36_26_pngSize = 1702;
extern const char* Light_14x14_png;
const int Light_14x14_pngSize = 796;
@ -28,7 +28,7 @@ namespace BinaryData
const int Meter_140x8_pngSize = 402;
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;
const int Slider_26x26_pngSize = 744;
@ -36,6 +36,9 @@ namespace BinaryData
extern const char* NotoSansRegular_ttf;
const int NotoSansRegular_ttfSize = 306788;
extern const char* NotoSansBold_ttf;
const int NotoSansBold_ttfSize = 311508;
extern const char* builtin_pgm_zip;
const int builtin_pgm_zipSize = 88890;
@ -46,7 +49,7 @@ namespace BinaryData
extern const char* namedResourceList[];
// 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
// return the corresponding data and its size (or a null pointer if the name isn't found).

@ -24,8 +24,9 @@
namespace FloatVectorHelpers
{
#define JUCE_INCREMENT_SRC_DEST dest += (16 / sizeof (*dest)); src += (16 / sizeof (*dest));
#define JUCE_INCREMENT_DEST dest += (16 / sizeof (*dest));
#define JUCE_INCREMENT_SRC_DEST dest += (16 / sizeof (*dest)); src += (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
static bool sse2Present = false;
@ -122,6 +123,17 @@ namespace FloatVectorHelpers
} \
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
@ -193,6 +205,12 @@ namespace FloatVectorHelpers
JUCE_VEC_LOOP (vecOp, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \
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
#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) \
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
//==============================================================================
@ -212,10 +232,19 @@ namespace FloatVectorHelpers
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_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_DEST(srcLoad, dstLoad) const Mode::ParallelType d = dstLoad (dest), s = srcLoad (src);
#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_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
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);)
}
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
{
#if JUCE_USE_VDSP_FRAMEWORK
@ -461,6 +512,24 @@ void JUCE_CALLTYPE FloatVectorOperations::add (double* dest, const double* src,
#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
{
#if JUCE_USE_VDSP_FRAMEWORK
@ -479,6 +548,24 @@ void JUCE_CALLTYPE FloatVectorOperations::subtract (double* dest, const double*
#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
{
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
}
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
{
#if JUCE_USE_VDSP_FRAMEWORK
@ -531,6 +636,20 @@ void JUCE_CALLTYPE FloatVectorOperations::multiply (double* dest, double multipl
#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
{
#if JUCE_USE_VDSP_FRAMEWORK

@ -65,18 +65,36 @@ public:
/** Adds a fixed value to the destination values. */
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. */
static void JUCE_CALLTYPE add (float* dest, const float* src, int numValues) noexcept;
/** Adds the source values to the destination values. */
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. */
static void JUCE_CALLTYPE subtract (float* dest, const float* src, int numValues) noexcept;
/** Subtracts the source values from the destination values. */
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. */
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. */
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. */
static void JUCE_CALLTYPE multiply (float* dest, float multiplier, int numValues) noexcept;
/** Multiplies each of the destination values by a fixed multiplier. */
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. */
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()
{
filterStates.clear ((size_t) numChannels);
if (filterStates != nullptr)
filterStates.clear ((size_t) numChannels);
}
void ResamplingAudioSource::applyFilter (float* samples, int num, FilterState& fs)

@ -163,10 +163,7 @@ void Synthesiser::renderNextBlock (AudioSampleBuffer& outputBuffer, const MidiBu
: numSamples;
if (numThisTime > 0)
{
for (int i = voices.size(); --i >= 0;)
voices.getUnchecked (i)->renderNextBlock (outputBuffer, startSample, numThisTime);
}
renderVoices (outputBuffer, startSample, numThisTime);
if (useEvent)
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)
{
if (m.isNoteOn())
@ -184,7 +187,7 @@ void Synthesiser::handleMidiEvent (const MidiMessage& m)
}
else if (m.isNoteOff())
{
noteOff (m.getChannel(), m.getNoteNumber(), true);
noteOff (m.getChannel(), m.getNoteNumber(), m.getFloatVelocity(), true);
}
else if (m.isAllNotesOff() || m.isAllSoundOff())
{
@ -230,10 +233,10 @@ void Synthesiser::noteOn (const int midiChannel,
if (voice->getCurrentlyPlayingNote() == midiNoteNumber
&& 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);
}
}
@ -248,7 +251,7 @@ void Synthesiser::startVoice (SynthesiserVoice* const voice,
if (voice != nullptr && sound != nullptr)
{
if (voice->currentlyPlayingSound != nullptr)
voice->stopNote (false);
voice->stopNote (0.0f, false);
voice->startNote (midiNoteNumber, velocity, sound,
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);
voice->stopNote (allowTailOff);
voice->stopNote (velocity, allowTailOff);
// the subclass MUST call clearCurrentNote() if it's not tailing off! RTFM for stopNote()!
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,
const int midiNoteNumber,
const float velocity,
const bool allowTailOff)
{
const ScopedLock sl (lock);
@ -291,7 +295,7 @@ void Synthesiser::noteOff (const int midiChannel,
voice->keyIsDown = false;
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);
if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel))
voice->stopNote (allowTailOff);
voice->stopNote (1.0f, allowTailOff);
}
sustainPedalsDown.clear();
@ -379,7 +383,7 @@ void Synthesiser::handleSustainPedal (int midiChannel, bool isDown)
SynthesiserVoice* const voice = voices.getUnchecked (i);
if (voice->isPlayingChannel (midiChannel) && ! voice->keyIsDown)
stopVoice (voice, true);
stopVoice (voice, 1.0f, true);
}
sustainPedalsDown.clearBit (midiChannel);
@ -400,7 +404,7 @@ void Synthesiser::handleSostenutoPedal (int midiChannel, bool isDown)
if (isDown)
voice->sostenutoPedalDown = true;
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);
@ -425,25 +431,68 @@ SynthesiserVoice* Synthesiser::findFreeVoice (SynthesiserSound* soundToPlay, con
}
if (stealIfNoneAvailable)
return findVoiceToSteal (soundToPlay);
return findVoiceToSteal (soundToPlay, midiChannel, midiNoteNumber);
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* oldest = nullptr;
SynthesiserVoice* bottom = 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)
{
SynthesiserVoice* const voice = voices.getUnchecked (i);
if (voice->canPlaySound (soundToPlay)
&& (oldest == nullptr || voice->wasStartedBefore (*oldest)))
oldest = voice;
if (voice->canPlaySound (soundToPlay))
{
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);
return oldest;
// ..otherwise, there's only one or two voices to choose from - we'll return the top one..
return top;
}

@ -55,14 +55,14 @@ public:
The Synthesiser will use this information when deciding which sounds to trigger
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.
The Synthesiser will use this information when deciding which sounds to trigger
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. */
typedef ReferenceCountedObjectPtr<SynthesiserSound> Ptr;
@ -127,6 +127,8 @@ public:
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
sound immediately, and must call clearCurrentNote() to reset the state of this voice
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
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.
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);
/** 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
midi channel.
@ -203,13 +210,6 @@ public:
bool wasStartedBefore (const SynthesiserVoice& other) const noexcept;
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.
The subclass must call this when it finishes playing a note and becomes available
@ -235,6 +235,11 @@ private:
SynthesiserSound::Ptr currentlyPlayingSound;
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)
};
@ -268,8 +273,7 @@ class JUCE_API Synthesiser
public:
//==============================================================================
/** 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();
@ -365,6 +369,7 @@ public:
*/
virtual void noteOff (int midiChannel,
int midiNoteNumber,
float velocity,
bool allowTailOff);
/** Turns off all notes.
@ -463,6 +468,11 @@ public:
int startSample,
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:
//==============================================================================
/** 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. */
int lastPitchWheelValues [16];
/** Searches through the voices to find one that's not currently playing, and which
can play the given sound.
/** Renders the voices for the given range.
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.
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,
const bool stealIfNoneAvailable) const;
int midiChannel,
int midiNoteNumber,
bool stealIfNoneAvailable) const;
/** 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
you may want to override this and do something more cunning instead.
The default method will attempt to find the oldest voice that isn't the
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.
@ -511,11 +534,14 @@ private:
bool shouldStealNotes;
BigInteger sustainPedalsDown;
void stopVoice (SynthesiserVoice*, bool allowTailOff);
void stopVoice (SynthesiserVoice*, float velocity, bool allowTailOff);
#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 noteOff (int, int, int) { return 0; }
virtual int findFreeVoice (SynthesiserSound*, const bool) { return 0; }
virtual int findVoiceToSteal (SynthesiserSound*) const { return 0; }
#endif
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Synthesiser)

@ -41,7 +41,7 @@ namespace
return err;
}
#else
#define JUCE_ALSA_LOG(x)
#define JUCE_ALSA_LOG(x) {}
#define JUCE_CHECKED_RESULT(x) (x)
#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
{
@ -987,14 +1027,15 @@ public:
// key should be removed (or set to "WAV") once this has been done
jassert (metadataValues.getValue ("MetaDataSource", "None") != "AIFF");
bwavChunk = BWAVChunk::createFrom (metadataValues);
axmlChunk = AXMLChunk::createFrom (metadataValues);
smplChunk = SMPLChunk::createFrom (metadataValues);
instChunk = InstChunk::createFrom (metadataValues);
cueChunk = CueChunk ::createFrom (metadataValues);
listChunk = ListChunk::createFrom (metadataValues);
acidChunk = AcidChunk::createFrom (metadataValues);
trckChunk = TracktionChunk::createFrom (metadataValues);
bwavChunk = BWAVChunk::createFrom (metadataValues);
axmlChunk = AXMLChunk::createFrom (metadataValues);
smplChunk = SMPLChunk::createFrom (metadataValues);
instChunk = InstChunk::createFrom (metadataValues);
cueChunk = CueChunk ::createFrom (metadataValues);
listChunk = ListChunk::createFrom (metadataValues);
listInfoChunk = ListInfoChunk::createFrom (metadataValues);
acidChunk = AcidChunk::createFrom (metadataValues);
trckChunk = TracktionChunk::createFrom (metadataValues);
}
headerPosition = out->getPosition();
@ -1057,7 +1098,7 @@ public:
}
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;
int64 headerPosition;
bool writeFailed;
@ -1109,6 +1150,7 @@ private:
+ chunkSize (instChunk)
+ chunkSize (cueChunk)
+ chunkSize (listChunk)
+ chunkSize (listInfoChunk)
+ chunkSize (acidChunk)
+ chunkSize (trckChunk)
+ (8 + 28)); // (ds64 chunk)
@ -1184,14 +1226,15 @@ private:
output->write (subFormat.data4, sizeof (subFormat.data4));
}
writeChunk (bwavChunk, chunkName ("bext"));
writeChunk (axmlChunk, chunkName ("axml"));
writeChunk (smplChunk, chunkName ("smpl"));
writeChunk (instChunk, chunkName ("inst"), 7);
writeChunk (cueChunk, chunkName ("cue "));
writeChunk (listChunk, chunkName ("LIST"));
writeChunk (acidChunk, chunkName ("acid"));
writeChunk (trckChunk, chunkName ("Trkn"));
writeChunk (bwavChunk, chunkName ("bext"));
writeChunk (axmlChunk, chunkName ("axml"));
writeChunk (smplChunk, chunkName ("smpl"));
writeChunk (instChunk, chunkName ("inst"), 7);
writeChunk (cueChunk, chunkName ("cue "));
writeChunk (listChunk, chunkName ("LIST"));
writeChunk (listInfoChunk, chunkName ("LIST"));
writeChunk (acidChunk, chunkName ("acid"));
writeChunk (trckChunk, chunkName ("Trkn"));
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];
}
bool SamplerSound::appliesToChannel (const int /*midiChannel*/)
bool SamplerSound::appliesToChannel (int /*midiChannel*/)
{
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)
{
@ -197,7 +197,7 @@ void SamplerVoice::renderNextBlock (AudioSampleBuffer& outputBuffer, int startSa
if (attackReleaseLevel <= 0.0f)
{
stopNote (false);
stopNote (0.0f, false);
break;
}
}
@ -216,7 +216,7 @@ void SamplerVoice::renderNextBlock (AudioSampleBuffer& outputBuffer, int startSa
if (sourceSamplePosition > playingSound->length)
{
stopNote (false);
stopNote (0.0f, false);
break;
}
}

@ -82,8 +82,8 @@ public:
//==============================================================================
bool appliesToNote (const int midiNoteNumber) override;
bool appliesToChannel (const int midiChannel) override;
bool appliesToNote (int midiNoteNumber) override;
bool appliesToChannel (int midiChannel) override;
private:
@ -124,7 +124,7 @@ public:
bool canPlaySound (SynthesiserSound*) 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 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)
{
@ -792,6 +792,9 @@ struct AAXClasses
if (lastBufferSize != bufferSize)
{
lastBufferSize = bufferSize;
pluginInstance->setPlayConfigDetails (pluginInstance->getNumInputChannels(),
pluginInstance->getNumOutputChannels(),
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
// the host knows that the RTAS/AAX plugins are equivalent.
properties->AddProperty (AAX_eProperty_PlugInID_Native, 'jcaa' + channelConfigIndex);
#if ! JucePlugin_AAXDisableAudioSuite
properties->AddProperty (AAX_eProperty_PlugInID_AudioSuite, 'jyaa' + channelConfigIndex);
#endif
#if JucePlugin_AAXDisableMultiMono
properties->AddProperty (AAX_eProperty_Constraint_MultiMonoSupport, false);

@ -144,13 +144,16 @@ namespace juce
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);
while (w != 0)
{
HWND parent = GetParent (w);
HWND parent = getWindowParent (w);
if (parent == 0)
break;
@ -1244,7 +1247,7 @@ public:
while (w != 0)
{
HWND parent = GetParent (w);
HWND parent = getWindowParent (w);
if (parent == 0)
break;

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

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

@ -128,7 +128,8 @@ String AudioProcessor::getParameterText (int parameterIndex, int maximumStringLe
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; }
AudioProcessorListener* AudioProcessor::getListenerLocked (const int index) const noexcept

@ -414,12 +414,18 @@ public:
virtual String getParameterText (int parameterIndex, int maximumStringLength);
/** 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.
The value that is returned may or may not be used, depending on the host.
*/
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.
By default, this just returns 0.
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
passed must have a method of the form:
@code
int compareElements (ElementType first, ElementType second);
int compareElements (ElementType* first, ElementType* second);
@endcode
..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 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 var* getPropertyPointer (DynamicObject* o, Identifier i) { return o->getProperties().getVarPointer (i); }
//==============================================================================
struct CodeLocation
@ -139,13 +140,13 @@ struct JavascriptEngine::RootObject : public DynamicObject
{
if (DynamicObject* o = targetObject.getDynamicObject())
{
if (var* prop = o->getProperties().getVarPointer (functionName))
if (const var* prop = getPropertyPointer (o, functionName))
return *prop;
for (DynamicObject* p = o->getProperty (getPrototypeIdentifier()).getDynamicObject(); p != nullptr;
p = p->getProperty (getPrototypeIdentifier()).getDynamicObject())
{
if (var* prop = p->getProperties().getVarPointer (functionName))
if (const var* prop = getPropertyPointer (p, functionName))
return *prop;
}
}
@ -168,14 +169,14 @@ struct JavascriptEngine::RootObject : public DynamicObject
var* findRootClassProperty (Identifier className, Identifier propName) const
{
if (DynamicObject* cls = root->getProperty (className).getDynamicObject())
return cls->getProperties().getVarPointer (propName);
return getPropertyPointer (cls, propName);
return nullptr;
}
var findSymbolInParentScopes (Identifier name) const
{
if (var* v = scope->getProperties().getVarPointer (name))
if (const var* v = getPropertyPointer (scope, name))
return *v;
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
{
const NamedValueSet& props = scope->getProperties();
DynamicObject* target = args.thisObject.getDynamicObject();
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()))
{
@ -200,6 +199,8 @@ struct JavascriptEngine::RootObject : public DynamicObject
}
}
const NamedValueSet& props = scope->getProperties();
for (int i = 0; i < props.size(); ++i)
if (DynamicObject* o = props.getValueAt (i).getDynamicObject())
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
{
if (var* v = s.scope->getProperties().getVarPointer (name))
if (var* v = getPropertyPointer (s.scope, name))
*v = newValue;
else
s.root->setProperty (name, newValue);
@ -378,7 +379,7 @@ struct JavascriptEngine::RootObject : public DynamicObject
}
if (DynamicObject* o = p.getDynamicObject())
if (var* v = o->getProperties().getVarPointer (child))
if (const var* v = getPropertyPointer (o, child))
return *v;
return var::undefined();

@ -263,7 +263,7 @@ private:
}
}
String responseHeader (readResponse (socketHandle, timeOutTime));
String responseHeader (readResponse (timeOutTime));
position = 0;
if (responseHeader.isNotEmpty())
@ -302,7 +302,7 @@ private:
}
//==============================================================================
String readResponse (const int socketHandle, const uint32 timeOutTime)
String readResponse (const uint32 timeOutTime)
{
int numConsecutiveLFs = 0;
MemoryOutputStream buffer;
@ -338,7 +338,8 @@ private:
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;
}

@ -223,6 +223,12 @@ namespace
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,
Time* const modTime, Time* const creationTime, bool* const isReadOnly)
{
@ -232,9 +238,9 @@ namespace
const bool statOk = juce_stat (path, info);
if (isDir != nullptr) *isDir = statOk && ((info.st_mode & S_IFDIR) != 0);
if (fileSize != nullptr) *fileSize = statOk ? info.st_size : 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 (fileSize != nullptr) *fileSize = statOk ? (int64) info.st_size : 0;
if (modTime != nullptr) *modTime = Time (statOk ? (int64) info.st_mtime * 1000 : 0);
if (creationTime != nullptr) *creationTime = Time (statOk ? getCreationTime (info) * 1000 : 0);
}
if (isReadOnly != nullptr)
@ -664,6 +670,7 @@ int File::getVolumeSerialNumber() const
}
//==============================================================================
#if ! JUCE_IOS
void juce_runSystemCommand (const String&);
void juce_runSystemCommand (const String& command)
{
@ -684,7 +691,7 @@ String juce_getOutputFromCommand (const String& command)
tempFile.deleteFile();
return result;
}
#endif
//==============================================================================
#if JUCE_IOS

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

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

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

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

@ -318,7 +318,10 @@ public:
/** 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
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
*/
XmlElement* createXml() const;

@ -131,6 +131,22 @@ void MessageManager::stopDispatchLoop()
#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
{
public:

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

@ -125,11 +125,12 @@ void Button::setTooltip (const String& newTooltip)
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));
@ -145,10 +146,8 @@ String Button::getTooltip()
tt << key << ']';
}
return tt;
SettableTooltipClient::setTooltip (tt);
}
return SettableTooltipClient::getTooltip();
}
void Button::setConnectedEdges (const int newFlags)
@ -542,6 +541,7 @@ void Button::applicationCommandListChangeCallback()
if (commandManagerToUse->getTargetForCommand (commandID, info) != nullptr)
{
updateAutomaticTooltip (info);
setEnabled ((info.flags & ApplicationCommandInfo::isDisabled) == 0);
setToggleState ((info.flags & ApplicationCommandInfo::isTicked) != 0, dontSendNotification);
}

@ -277,12 +277,6 @@ public:
*/
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(). */
enum ConnectedEdgeFlags
@ -495,6 +489,7 @@ private:
void repeatTimerCallback();
bool keyStateChangedCallback();
void applicationCommandListChangeCallback();
void updateAutomaticTooltip (const ApplicationCommandInfo&);
ButtonState updateState();
ButtonState updateState (bool isOver, bool isDown);

@ -51,7 +51,20 @@ void ApplicationCommandManager::registerCommand (const ApplicationCommandInfo& n
// the name isn't optional!
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);
newInfo->flags &= ~ApplicationCommandInfo::isTicked;
@ -61,16 +74,6 @@ void ApplicationCommandManager::registerCommand (const ApplicationCommandInfo& n
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)
@ -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;)
if (commands.getUnchecked(i)->commandID == commandID)
@ -122,6 +125,11 @@ const ApplicationCommandInfo* ApplicationCommandManager::getCommandForID (const
return nullptr;
}
const ApplicationCommandInfo* ApplicationCommandManager::getCommandForID (const CommandID commandID) const noexcept
{
return getMutableCommandForID (commandID);
}
String ApplicationCommandManager::getNameOfCommand (const CommandID commandID) const noexcept
{
if (const ApplicationCommandInfo* const ci = getCommandForID (commandID))
@ -215,7 +223,10 @@ ApplicationCommandTarget* ApplicationCommandManager::getTargetForCommand (const
target = target->getTargetForCommand (commandID);
if (target != nullptr)
{
upToDateInfo.commandID = commandID;
target->getCommandInfo (commandID, upToDateInfo);
}
return target;
}
@ -223,7 +234,7 @@ ApplicationCommandTarget* ApplicationCommandManager::getTargetForCommand (const
//==============================================================================
ApplicationCommandTarget* ApplicationCommandManager::findTargetForComponent (Component* c)
{
ApplicationCommandTarget* target = dynamic_cast <ApplicationCommandTarget*> (c);
ApplicationCommandTarget* target = dynamic_cast<ApplicationCommandTarget*> (c);
if (target == nullptr && c != nullptr)
target = c->findParentComponentOfClass<ApplicationCommandTarget>();
@ -263,7 +274,7 @@ ApplicationCommandTarget* ApplicationCommandManager::findDefaultComponentTarget(
// 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
// content comp.
if (ResizableWindow* const resizableWindow = dynamic_cast <ResizableWindow*> (c))
if (ResizableWindow* const resizableWindow = dynamic_cast<ResizableWindow*> (c))
if (Component* const content = resizableWindow->getContentComponent())
c = content;

@ -308,6 +308,7 @@ private:
void sendListenerInvokeCallback (const ApplicationCommandTarget::InvocationInfo&);
void handleAsyncUpdate() override;
void globalFocusChanged (Component*) override;
ApplicationCommandInfo* getMutableCommandForID (CommandID) const noexcept;
#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

@ -111,6 +111,9 @@ LookAndFeel_V2::LookAndFeel_V2()
TextPropertyComponent::textColourId, 0xff000000,
TextPropertyComponent::outlineColourId, standardOutlineColour,
BooleanPropertyComponent::backgroundColourId, 0xffffffff,
BooleanPropertyComponent::outlineColourId, standardOutlineColour,
ListBox::backgroundColourId, 0xffffffff,
ListBox::outlineColourId, standardOutlineColour,
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()
{

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

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

@ -562,6 +562,9 @@ public:
const Drawable* icon,
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. */
virtual Font getPopupMenuFont() = 0;

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

@ -165,6 +165,12 @@ protected:
virtual bool shouldDropFilesWhenDraggedExternally (const DragAndDropTarget::SourceDetails& sourceDetails,
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:
//==============================================================================
class DragImageComponent;

@ -24,6 +24,14 @@
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
{
static Desktop::DisplayOrientation convertToJuce (UIInterfaceOrientation orientation)
@ -42,12 +50,15 @@ namespace Orientations
static CGAffineTransform getCGTransformFor (const Desktop::DisplayOrientation orientation) noexcept
{
switch (orientation)
if (isUsingOldRotationMethod())
{
case Desktop::upsideDown: return CGAffineTransformMake (-1, 0, 0, -1, 0, 0);
case Desktop::rotatedClockwise: return CGAffineTransformMake (0, -1, 1, 0, 0, 0);
case Desktop::rotatedAntiClockwise: return CGAffineTransformMake (0, 1, -1, 0, 0, 0);
default: break;
switch (orientation)
{
case Desktop::upsideDown: return CGAffineTransformMake (-1, 0, 0, -1, 0, 0);
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;
@ -85,10 +96,10 @@ using namespace juce;
- (void) drawRect: (CGRect) r;
- (void) touchesBegan: (NSSet*) touches withEvent: (UIEvent*) event;
- (void) touchesMoved: (NSSet*) touches withEvent: (UIEvent*) event;
- (void) touchesEnded: (NSSet*) touches withEvent: (UIEvent*) event;
- (void) touchesCancelled: (NSSet*) touches withEvent: (UIEvent*) event;
- (void) touchesBegan: (NSSet*) touches withEvent: (UIEvent*) event;
- (void) touchesMoved: (NSSet*) touches withEvent: (UIEvent*) event;
- (void) touchesEnded: (NSSet*) touches withEvent: (UIEvent*) event;
- (void) touchesCancelled: (NSSet*) touches withEvent: (UIEvent*) event;
- (BOOL) becomeFirstResponder;
- (BOOL) resignFirstResponder;
@ -106,6 +117,7 @@ using namespace juce;
- (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) interfaceOrientation;
- (void) willRotateToInterfaceOrientation: (UIInterfaceOrientation) toInterfaceOrientation duration: (NSTimeInterval) duration;
- (void) didRotateFromInterfaceOrientation: (UIInterfaceOrientation) fromInterfaceOrientation;
- (void) viewWillTransitionToSize: (CGSize) size withTransitionCoordinator: (id<UIViewControllerTransitionCoordinator>) coordinator;
- (void) viewDidLoad;
- (void) viewWillAppear: (BOOL) animated;
@ -189,7 +201,7 @@ public:
bool isSharedWindow, fullScreen, insideDrawRect;
static ModifierKeys currentModifiers;
static int64 getMouseTime (UIEvent* e)
static int64 getMouseTime (UIEvent* e) noexcept
{
return (Time::currentTimeMillis() - Time::getMillisecondCounter())
+ (int64) ([e timestamp] * 1000.0);
@ -197,26 +209,29 @@ public:
static Rectangle<int> rotatedScreenPosToReal (const Rectangle<int>& r)
{
const Rectangle<int> screen (convertToRectInt ([UIScreen mainScreen].bounds));
switch ([[UIApplication sharedApplication] statusBarOrientation])
if (isUsingOldRotationMethod())
{
case UIInterfaceOrientationPortrait:
return r;
const Rectangle<int> screen (convertToRectInt ([UIScreen mainScreen].bounds));
switch ([[UIApplication sharedApplication] statusBarOrientation])
{
case UIInterfaceOrientationPortrait:
return r;
case UIInterfaceOrientationPortraitUpsideDown:
return Rectangle<int> (screen.getWidth() - r.getRight(), screen.getHeight() - r.getBottom(),
r.getWidth(), r.getHeight());
case UIInterfaceOrientationPortraitUpsideDown:
return Rectangle<int> (screen.getWidth() - r.getRight(), screen.getHeight() - r.getBottom(),
r.getWidth(), r.getHeight());
case UIInterfaceOrientationLandscapeLeft:
return Rectangle<int> (r.getY(), screen.getHeight() - r.getRight(),
r.getHeight(), r.getWidth());
case UIInterfaceOrientationLandscapeLeft:
return Rectangle<int> (r.getY(), screen.getHeight() - r.getRight(),
r.getHeight(), r.getWidth());
case UIInterfaceOrientationLandscapeRight:
return Rectangle<int> (screen.getWidth() - r.getBottom(), r.getX(),
r.getHeight(), r.getWidth());
case UIInterfaceOrientationLandscapeRight:
return Rectangle<int> (screen.getWidth() - r.getBottom(), r.getX(),
r.getHeight(), r.getWidth());
default: jassertfalse; // unknown orientation!
default: jassertfalse; // unknown orientation!
}
}
return r;
@ -224,26 +239,29 @@ public:
static Rectangle<int> realScreenPosToRotated (const Rectangle<int>& r)
{
const Rectangle<int> screen (convertToRectInt ([UIScreen mainScreen].bounds));
switch ([[UIApplication sharedApplication] statusBarOrientation])
if (isUsingOldRotationMethod())
{
case UIInterfaceOrientationPortrait:
return r;
const Rectangle<int> screen (convertToRectInt ([UIScreen mainScreen].bounds));
switch ([[UIApplication sharedApplication] statusBarOrientation])
{
case UIInterfaceOrientationPortrait:
return r;
case UIInterfaceOrientationPortraitUpsideDown:
return Rectangle<int> (screen.getWidth() - r.getRight(), screen.getHeight() - r.getBottom(),
r.getWidth(), r.getHeight());
case UIInterfaceOrientationPortraitUpsideDown:
return Rectangle<int> (screen.getWidth() - r.getRight(), screen.getHeight() - r.getBottom(),
r.getWidth(), r.getHeight());
case UIInterfaceOrientationLandscapeLeft:
return Rectangle<int> (screen.getHeight() - r.getBottom(), r.getX(),
r.getHeight(), r.getWidth());
case UIInterfaceOrientationLandscapeLeft:
return Rectangle<int> (screen.getHeight() - r.getBottom(), r.getX(),
r.getHeight(), r.getWidth());
case UIInterfaceOrientationLandscapeRight:
return Rectangle<int> (r.getY(), screen.getWidth() - r.getRight(),
r.getHeight(), r.getWidth());
case UIInterfaceOrientationLandscapeRight:
return Rectangle<int> (r.getY(), screen.getWidth() - r.getRight(),
r.getHeight(), r.getWidth());
default: jassertfalse; // unknown orientation!
default: jassertfalse; // unknown orientation!
}
}
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)
//==============================================================================
@ -301,19 +326,23 @@ private:
- (void) didRotateFromInterfaceOrientation: (UIInterfaceOrientation) fromInterfaceOrientation
{
(void) fromInterfaceOrientation;
sendScreenBoundsUpdate (self);
[UIView setAnimationsEnabled: YES];
}
JuceUIView* juceView = (JuceUIView*) [self view];
jassert (juceView != nil && juceView->owner != nullptr);
juceView->owner->updateTransformAndScreenBounds();
- (void) viewWillTransitionToSize: (CGSize) size withTransitionCoordinator: (id<UIViewControllerTransitionCoordinator>) coordinator
{
[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
{
JuceUIView* juceView = (JuceUIView*) [self view];
jassert (juceView != nil && juceView->owner != nullptr);
juceView->owner->updateTransformAndScreenBounds();
sendScreenBoundsUpdate (self);
}
- (void) viewWillAppear: (BOOL) animated

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

@ -845,7 +845,7 @@ public:
void toBehind (ComponentPeer* other) override
{
if (HWNDComponentPeer* const otherPeer = dynamic_cast <HWNDComponentPeer*> (other))
if (HWNDComponentPeer* const otherPeer = dynamic_cast<HWNDComponentPeer*> (other))
{
setMinimised (false);
@ -960,7 +960,7 @@ public:
static ModifierKeys modifiersAtLastCallback;
//==============================================================================
class JuceDropTarget : public ComBaseClassHelper <IDropTarget>
class JuceDropTarget : public ComBaseClassHelper<IDropTarget>
{
public:
JuceDropTarget (HWNDComponentPeer& p) : ownerInfo (new OwnerInfo (p)) {}
@ -1099,13 +1099,13 @@ public:
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));
if (dropFiles->fWide)
ownerInfo->parseFileList (static_cast <const WCHAR*> (names), fileData.dataSize);
ownerInfo->parseFileList (static_cast<const WCHAR*> (names), fileData.dataSize);
else
ownerInfo->parseFileList (static_cast <const char*> (names), fileData.dataSize);
ownerInfo->parseFileList (static_cast<const char*> (names), fileData.dataSize);
}
else
{
@ -1300,7 +1300,7 @@ private:
//==============================================================================
static void* createWindowCallback (void* userData)
{
static_cast <HWNDComponentPeer*> (userData)->createWindow();
static_cast<HWNDComponentPeer*> (userData)->createWindow();
return nullptr;
}
@ -1643,7 +1643,7 @@ private:
handlePaint (*context);
}
static_cast <WindowsBitmapImage*> (offscreenImage.getPixelData())
static_cast<WindowsBitmapImage*> (offscreenImage.getPixelData())
->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)
{
if (! sendInputAttemptWhenModalMessage())
@ -2309,7 +2327,7 @@ private:
{
Desktop& desktop = Desktop::getInstance();
const_cast <Desktop::Displays&> (desktop.getDisplays()).refresh();
const_cast<Desktop::Displays&> (desktop.getDisplays()).refresh();
if (fullScreen && ! isMinimised())
{
@ -2550,6 +2568,10 @@ private:
}
return TRUE;
case WM_POWERBROADCAST:
handlePowerBroadcast (wParam);
break;
case WM_SYNCPAINT:
return 0;
@ -2879,7 +2901,7 @@ private:
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()));
@ -2981,7 +3003,7 @@ bool JUCE_CALLTYPE Process::isForegroundProcess()
fg = GetAncestor (fg, GA_ROOT);
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))
return true;
@ -3007,7 +3029,7 @@ static BOOL CALLBACK enumAlwaysOnTopWindows (HWND hwnd, LPARAM lParam)
if (GetWindowInfo (hwnd, &info)
&& (info.dwExStyle & WS_EX_TOPMOST) != 0)
{
*reinterpret_cast <bool*> (lParam) = true;
*reinterpret_cast<bool*> (lParam) = true;
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 (WCHAR* const data = static_cast <WCHAR*> (GlobalLock (bufH)))
if (WCHAR* const data = static_cast<WCHAR*> (GlobalLock (bufH)))
{
text.copyToUTF16 (data, bytesNeeded);
GlobalUnlock (bufH);

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

@ -78,6 +78,20 @@ public:
/** Must return the current value of the property. */
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 */
void paint (Graphics&) override;

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

@ -184,7 +184,7 @@ public:
virtual void labelTextChanged (Label* labelThatHasChanged) = 0;
/** 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. */

@ -367,6 +367,7 @@ ListBox::ListBox (const String& name, ListBoxModel* const m)
outlineThickness (0),
lastRowSelected (-1),
multipleSelection (false),
alwaysFlipSelection (false),
hasDoneInitialUpdate (false)
{
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;
}
void ListBox::setClickingTogglesRowSelection (bool b) noexcept
{
alwaysFlipSelection = b;
}
void ListBox::setMouseMoveSelectsRows (bool b)
{
if (b)
@ -470,9 +476,7 @@ void ListBox::updateContent()
}
//==============================================================================
void ListBox::selectRow (const int row,
bool dontScroll,
bool deselectOthersFirst)
void ListBox::selectRow (int row, bool dontScroll, bool deselectOthersFirst)
{
selectRowInternal (row, dontScroll, deselectOthersFirst, false);
}
@ -589,7 +593,7 @@ void ListBox::selectRowsBasedOnModifierKeys (const int row,
ModifierKeys mods,
const bool isMouseUpEvent)
{
if (multipleSelection && mods.isCommandDown())
if (multipleSelection && (mods.isCommandDown() || alwaysFlipSelection))
{
flipRowSelection (row);
}

@ -45,7 +45,10 @@ public:
*/
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,
Graphics& g,
int width, int height,
@ -216,7 +219,16 @@ public:
clicked and to get it to do the appropriate selection based on whether
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.
@ -557,7 +569,7 @@ private:
int totalItems, rowHeight, minimumRowWidth;
int outlineThickness;
int lastRowSelected;
bool multipleSelection, hasDoneInitialUpdate;
bool multipleSelection, alwaysFlipSelection, hasDoneInitialUpdate;
SparseSet<int> selected;
void selectRowInternal (int rowNumber, bool dontScrollToShowThisRow,

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

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

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

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

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

@ -226,6 +226,9 @@ void WebBrowserComponent::goToURL (const String& url,
blankPageShown = false;
if (browser->browser == nullptr)
checkWindowAssociation();
browser->goToURL (url, headers, postData);
}
@ -262,7 +265,10 @@ void WebBrowserComponent::refresh()
void WebBrowserComponent::paint (Graphics& g)
{
if (browser->browser == nullptr)
{
g.fillAll (Colours::white);
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
---------
#### Version 0.8.0
* New UI
* Fixed mono mode ticks on lower frequencies
* SynprezFM preset are now in a submenu
#### Version 0.7.0
* Preliminary Algo 4 & 6 feedback support
* DX Engine 'Dirty DX' emulation, including one based on OPL chips
@ -126,6 +131,7 @@ FAQ (possibly)
Credits & thanks
----------------
* 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
* 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))
@ -134,9 +140,9 @@ Credits & thanks
Planned milestones
------------------
* 0.6 DX7 editor + user cartridges
* 0.7 msfa engine tuning
* 0.8 UI redesign
* 0.8.1 Cartridge browser/editor
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
{ 0, 0, 1, 3, 0, 0, 0, 2, 4, 0, 0, 5, -6 }, // 1
{ 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
};
#include "AlgoDisplay.h"
#include "DXLookNFeel.h"
AlgoDisplay::AlgoDisplay() {
static char tmpAlgo = 0;
algo = &tmpAlgo;
}
void AlgoDisplay::paint(Graphics &g) {
int alg;
if ( *algo <= 31 ) {
alg = *algo;
} else {
alg = 31;
inline void displayOp(Graphics &g, char id, char x, char y, char link, char fb) {
const int LINE_SZ = 3;
String t(id);
x *= 25;
y *= 21;
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));
g.fillRoundedRectangle (0.0f, 0.0f, (float) getWidth(), (float) getHeight(), 1.0f);
for(int i=0;i<13;i++) {
int target = arr[i];
if ( target == 0 )
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);
if ( fb ) {
g.drawLine(x+7, y, x+8, y-4, LINE_SZ);
g.drawLine(x+8, y-4, x+20, y-4, LINE_SZ);
g.drawLine(x+19, y-4, x+19, y+15, LINE_SZ);
g.drawLine(x+18, y+15, x+19, y+15, LINE_SZ);
g.drawLine(x+8, y+15, x+19, y+15, LINE_SZ);
}
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) {
String txt;
txt << abs(num);
int offx = 24;
int offy = 17;
g.setColour(Colour(0xFF0FC00F));
g.fillRect(x*offx+4, y*offy+3, offx-2, offy-1);
g.setColour(Colour(0xFFFFFFFF));
g.drawText(txt, x*offx+3, y*offy+2, offx+2, offy+2, Justification::centred, true);
if ( num < 0 ) {
g.setColour(Colour(0xFFFFFFFF));
int x1 = (x*offx) + 24;
g.drawLine(x1+1, y*offy+3, x1+1, y*offy+offy+2, 3);
void AlgoDisplay::paint(Graphics &g) {
switch(*algo) {
case 0:
displayOp(g, 6, 3, 0, 0, 1);
displayOp(g, 5, 3, 1, 0, 0);
displayOp(g, 4, 3, 2, 0, 0);
displayOp(g, 3, 3, 3, 2, 0);
displayOp(g, 2, 2, 2, 0, 0);
displayOp(g, 1, 2, 3, 1, 0);
break;
case 1:
displayOp(g, 6, 3, 0, 0, 0);
displayOp(g, 5, 3, 1, 0, 0);
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
#define ALGODISPLAY_H_INCLUDED
#include "../JuceLibraryCode/JuceHeader.h"
class AlgoDisplay : public Component {
void drawOp(Graphics &g, int x, int y, int num);
public:
AlgoDisplay();
char *algo;

@ -243,7 +243,6 @@ void EnvDisplay::paint(Graphics &g) {
p.lineTo(0, 32);
g.setColour(DXLookNFeel::fillColour);
//g.setColour(Colour(0xFF0FC00F).withAlpha(0.3f));
g.fillPath(p);
g.setColour(Colour(0xFFFFFFFF));
@ -258,8 +257,6 @@ PitchEnvDisplay::PitchEnvDisplay() {
}
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);
char *levels = pvalues + 4;
@ -269,8 +266,8 @@ void PitchEnvDisplay::paint(Graphics &g) {
float total = 0;
int old = pitchenv_tab[levels[3]] + 128;
// find the scale
// find the scale
for(int i=0;i<4;i++) {
int nw = pitchenv_tab[levels[i]] + 128;
dist[i] = ((float)abs(nw - old)) / pitchenv_rate[rates[i]];
@ -283,30 +280,42 @@ void PitchEnvDisplay::paint(Graphics &g) {
total = 4;
}
// TODO : this is WIP
float ratio = 96 / total;
int oldx = 0;
int oldy = 25 - (pitchenv_tab[levels[3]] + 128) / 10;
Path p;
p.startNewSubPath(0, 32);
int i;
for(i=0;i<4;i++) {
int newx = dist[i] * ratio + oldx;
int newy = 25 - (pitchenv_tab[levels[i]] + 128) / 10;
int x = 0;
int y = 25 - (pitchenv_tab[levels[3]] + 128) / 10;
p.lineTo(0,y);
g.drawLine(oldx, oldy, newx, newy, 2);
int dx = x;
int dy = y;
int i;
for(i=0;i<4;i++) {
if ( vPos == i ) {
g.fillEllipse(oldx-2, oldy-2, 4, 4);
dx = x;
dy = y;
}
oldx = newx;
oldy = newy;
x = dist[i] * ratio + x;
y = 25 - (pitchenv_tab[levels[i]] + 128) / 10;
p.lineTo(x, y);
}
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) {
@ -373,11 +382,20 @@ void ComboBoxImage::paint(Graphics &g) {
g.drawImage(items, 0, 0, items.getWidth(), itemHeight, 0, idx * itemHeight, items.getWidth(), itemHeight);
}
ComboBoxImage::ComboBoxImage() {
onPopup = false;
}
void ComboBoxImage::showPopup() {
int idx = popup.show() - 1;
if ( idx < 0 )
return;
setSelectedItemIndex(idx);
if ( !onPopup ) {
onPopup = true;
int idx = popup.show() - 1;
onPopup = false;
if ( idx < 0 )
return;
setSelectedItemIndex(idx);
}
}
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() {
isInInit = true;
}

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

@ -19,22 +19,35 @@
*/
#include "DXLookNFeel.h"
#include "DXComponents.h"
#include "Dexed.h"
Colour DXLookNFeel::dxDarkBrown = Colour(0xFF47260D);
Colour DXLookNFeel::dxLightBrown = Colour(0xFFA87B67);
Colour DXLookNFeel::background = Colour(60,50,47);
Colour DXLookNFeel::fillColour = Colour(77,159,151);
Colour DXLookNFeel::comboBoxBackground = Colour(20, 18, 18);
Colour DXLookNFeel::lightBackground = Colour(78,72,63);
Colour DXLookNFeel::ctrlBackground = Colour(20,18,18);
Colour DXLookNFeel::comboBoxBackground = Colour(20,18,18);
DXLookNFeel::DXLookNFeel() {
setColour(TextButton::buttonColourId,Colour(0xFF0FC00F));
setColour(Slider::rotarySliderOutlineColourId,Colour(0xFF0FC00F));
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);
defaultFontBold = Typeface::createSystemTypefaceFor(BinaryData::NotoSansBold_ttf, BinaryData::NotoSansBold_ttfSize);
}
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());
};
void DXLookNFeel::drawToggleButton(Graphics& g, ToggleButton& button, bool isMouseOverButton, bool isButtonDown) {
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);
}
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);
// g.drawImage(myStrip, 0, 0, button.getWidth(), button.getHeight(), 0, isButtonDown ? 30 : 0, 50, 30);
int w = button.getWidth();
// 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, 3, 0, w-3, 30, 3, button.getToggleState() ? 0 : 26, 44, 30);
g.drawImage(myStrip, w-3, 0, w, 30, 47, button.getToggleState() ? 0 : 26, 47, 30);
// dx, dy, dw, dl, sx, sy, sw, sl
g.drawImage(myStrip, 0, 0, 3, 30, 0, isButtonDown ? 30 : 0, 3, 30);
g.drawImage(myStrip, 3, 0, w-6, 30, 3, isButtonDown ? 30 : 0, 44, 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,
float sliderPos, float minSliderPos, float maxSliderPos,
const Slider::SliderStyle, Slider&) {
// NOP
}
void DXLookNFeel::drawLinearSliderThumb (Graphics& g, int x, int y, int width, int height,
float sliderPos, float minSliderPos, float maxSliderPos,
const Slider::SliderStyle, Slider&) {
Image myStrip = ImageCache::getFromMemory(BinaryData::Slider_26x26_png, BinaryData::Slider_26x26_pngSize);
TRACE("%g %g", sliderPos, minSliderPos);
int p = sliderPos - minSliderPos;
p -= 7;
p -= 6;
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"
class DXLookNFeel : public LookAndFeel_V3 {
Typeface::Ptr defaultFont;
public:
Typeface::Ptr defaultFont;
Typeface::Ptr defaultFontBold;
static Colour comboBoxBackground;
static Colour background;
static Colour lightBackground;
static Colour fillColour;
static Colour ctrlBackground;
DXLookNFeel();
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);
static Colour dxDarkBrown;
static Colour dxLightBrown;
virtual void drawLinearSliderBackground (Graphics&, int x, int y, int width, int height,
float sliderPos, float minSliderPos, float maxSliderPos,
@ -48,7 +52,11 @@ public:
virtual void drawButtonBackground (Graphics&, Button&, const Colour& backgroundColour,
bool isMouseOverButton, bool isButtonDown) override;
virtual Font getTextButtonFont(TextButton&, int buttonHeight) override;
virtual Typeface::Ptr getTypefaceForFont(const Font &);
virtual void positionComboBoxText (ComboBox& box, Label& label);
};
#endif // DXLOOKNFEEL_H_INCLUDED

@ -116,7 +116,7 @@ GlobalEditor::GlobalEditor ()
addAndMakeVisible (transpose = new Slider ("transpose"));
transpose->setRange (0, 48, 0);
transpose->setSliderStyle (Slider::Rotary);
transpose->setSliderStyle (Slider::RotaryVerticalDrag);
transpose->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
transpose->addListener (this);
@ -273,31 +273,14 @@ void GlobalEditor::paint (Graphics& g)
//[UserPrePaint] Add your own custom painting code here..
//[/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.drawImage (cachedImage_globalEditor_864x144_png,
0, 0, 864, 144,
0, 0, cachedImage_globalEditor_864x144_png.getWidth(), cachedImage_globalEditor_864x144_png.getHeight());
//[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]
}
@ -318,13 +301,13 @@ void GlobalEditor::resized()
pitchLevel4->setBounds (823, 56, 34, 34);
pitchLevel1->setBounds (739, 57, 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);
lfoSync->setBounds (575, 96, 48, 26);
lfoSync->setBounds (571, 96, 48, 26);
pitchEnvDisplay->setBounds (751, 10, 93, 30);
algoDisplay->setBounds (331, 24, 153, 98);
feedback->setBounds (500, 76, 34, 34);
algo->setBounds (500, 16, 34, 34);
algoDisplay->setBounds (338, 30, 146, 91);
feedback->setBounds (501, 80, 34, 34);
algo->setBounds (501, 22, 34, 34);
lcdDisplay->setBounds (6, 87, 140, 13);
output->setBounds (157, 60, 34, 34);
vuOutput->setBounds (6, 103, 140, 8);
@ -506,6 +489,7 @@ void GlobalEditor::buttonClicked (Button* buttonThatWasClicked)
{
//[UserButtonCode_monoMode] -- add your button handler code here..
editor->processor->setMonoMode(monoMode->getToggleState());
repaint();
//[/UserButtonCode_monoMode]
}
@ -551,7 +535,7 @@ void GlobalEditor::setSystemMessage(String msg) {
}
void GlobalEditor::setParamMessage(String msg) {
//lcdDisplay->paramMsg = msg;
lcdDisplay->paramMsg = msg;
}
void GlobalEditor::updateDisplay() {
@ -590,12 +574,6 @@ BEGIN_JUCER_METADATA
snapPixels="8" snapActive="0" snapShown="1" overlayOpacity="0.330"
fixedSize="1" initialWidth="864" initialHeight="144">
<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"
mode="0"/>
</BACKGROUND>
@ -657,30 +635,30 @@ BEGIN_JUCER_METADATA
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="transpose" id="7d1266b1c1534947" memberName="transpose"
virtualName="" explicitFocusOrder="0" pos="202 60 34 34" min="0"
max="48" int="0" style="Rotary" textBoxPos="NoTextBox" textBoxEditable="1"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
max="48" int="0" style="RotaryVerticalDrag" textBoxPos="NoTextBox"
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<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"/>
<SLIDER name="pitchModSens" id="904f73df85a9f886" memberName="pitchModSens"
virtualName="" explicitFocusOrder="0" pos="666 5 34 34" min="0"
max="7" int="0" style="RotaryVerticalDrag" textBoxPos="NoTextBox"
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<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"/>
<GENERICCOMPONENT name="pitchEnvDisplay" id="9ddaae8ef924a038" memberName="pitchEnvDisplay"
virtualName="" explicitFocusOrder="0" pos="751 10 93 30" class="PitchEnvDisplay"
params=""/>
<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=""/>
<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"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<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"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<GENERICCOMPONENT name="lcdDisplay" id="30c7bb8f114cbbe3" memberName="lcdDisplay"

@ -108,7 +108,7 @@ OperatorEditor::OperatorEditor ()
addAndMakeVisible (detune = new Slider ("detune"));
detune->setRange (-7, 7, 1);
detune->setSliderStyle (Slider::Rotary);
detune->setSliderStyle (Slider::RotaryVerticalDrag);
detune->setTextBoxStyle (Slider::NoTextBox, true, 80, 20);
detune->addListener (this);
@ -183,13 +183,15 @@ OperatorEditor::OperatorEditor ()
kbdLeftCurve->addItem("-EX", 2);
kbdLeftCurve->addItem("+EX", 3);
kbdLeftCurve->addItem("+LN", 4);
kbdLeftCurve->setImage(tmp);
int posLeft[] = {0,5,4,3};
kbdLeftCurve->setImage(tmp, posLeft);
kbdRightCurve->addItem("-LN", 1);
kbdRightCurve->addItem("-EX", 2);
kbdRightCurve->addItem("+EX", 3);
kbdRightCurve->addItem("+LN", 4);
kbdRightCurve->setImage(tmp);
int posRight[] = {3,2,1,0};
kbdRightCurve->setImage(tmp, posRight);
//[/Constructor]
}
@ -250,7 +252,7 @@ void OperatorEditor::paint (Graphics& g)
// 129 x 24
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);
//[/UserPaint]
@ -271,7 +273,7 @@ void OperatorEditor::resized()
opCoarse->setBounds (41, 24, 34, 34);
khzDisplay->setBounds (15, 10, 95, 10);
detune->setBounds (6, 24, 34, 34);
envDisplay->setBounds (16, 82, 94, 30);
envDisplay->setBounds (16, 83, 94, 30);
sclLeftLevel->setBounds (131, 115, 34, 34);
sclRightLevel->setBounds (241, 115, 34, 34);
sclLvlBrkPt->setBounds (178, 130, 54, 24);
@ -549,14 +551,13 @@ BEGIN_JUCER_METADATA
explicitFocusOrder="0" pos="15 10 95 10" bkgCol="6a000000" textCol="ffffffff"
outlineCol="0" edTextCol="ff000000" edBkgCol="0" labelText="1,000 kHz"
editableSingleClick="0" editableDoubleClick="0" focusDiscardsChanges="0"
fontname="Default font" fontsize="12.599999999999999645" bold="0"
italic="0" justification="36"/>
fontname="Default font" fontsize="12.6" bold="0" italic="0" justification="36"/>
<SLIDER name="detune" id="f093ec8defca2fc2" memberName="detune" virtualName=""
explicitFocusOrder="0" pos="6 24 34 34" min="-7" max="7" int="1"
style="Rotary" textBoxPos="NoTextBox" textBoxEditable="0" textBoxWidth="80"
textBoxHeight="20" skewFactor="1"/>
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="0"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<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=""/>
<SLIDER name="sclLeftLevel" id="bd6f338ae68e454f" memberName="sclLeftLevel"
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->addListener (this);
addAndMakeVisible (showKeyboard = new ToggleButton ("showKeyboard"));
showKeyboard->setButtonText (String::empty);
//[UserPreSize]
//[/UserPreSize]
@ -106,6 +109,7 @@ ParamDialog::~ParamDialog()
sysexOut = nullptr;
sysexChl = nullptr;
engineReso = nullptr;
showKeyboard = nullptr;
//[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]
g.fillAll (Colour (0xff4e270d));
g.fillAll (Colour (0xff3c322f));
g.setColour (Colours::white);
g.setFont (Font (15.00f, Font::plain));
@ -135,13 +139,13 @@ void ParamDialog::paint (Graphics& g)
g.setColour (Colours::white);
g.setFont (Font (15.00f, Font::plain));
g.drawText (TRANS("DX7 In"),
28, 226, 131, 23,
27, 221, 131, 23,
Justification::centredLeft, true);
g.setColour (Colours::white);
g.setFont (Font (15.00f, Font::plain));
g.drawText (TRANS("DX7 Out"),
30, 267, 131, 23,
27, 261, 131, 23,
Justification::centredLeft, true);
g.setColour (Colours::white);
@ -162,6 +166,12 @@ void ParamDialog::paint (Graphics& g)
g.setColour (Colours::black);
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]
}
@ -174,6 +184,7 @@ void ParamDialog::resized()
sysexOut->setBounds (104, 264, 224, 24);
sysexChl->setBounds (264, 304, 72, 24);
engineReso->setBounds (160, 152, 168, 24);
showKeyboard->setBounds (264, 96, 56, 24);
//[UserResized] Add your own custom resize handling here..
//[/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...
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]);
pitchStep->setValue(c.values_[kControllerPitchStep]);
sysexChl->setValue(mgr.getChl() + 1);
@ -249,9 +260,10 @@ void ParamDialog::setDialogValues(Controllers &c, SysexComm &mgr, int reso) {
sysexOut->setSelectedItemIndex(idx);
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;
c.values_[kControllerPitchRange] = pitchRange->getValue();
@ -261,7 +273,7 @@ bool ParamDialog::getDialogValues(Controllers &c, SysexComm &mgr, int *reso) {
mgr.setChl(sysexChl->getValue() - 1);
*reso = engineReso->getSelectedItemIndex();
*showKey = showKeyboard->getToggleState();
return ret;
}
@ -281,14 +293,14 @@ BEGIN_JUCER_METADATA
parentClasses="public Component" constructorParams="" variableInitialisers=""
snapPixels="8" snapActive="1" snapShown="1" overlayOpacity="0.330"
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"
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"
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"/>
<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"/>
<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"/>
@ -296,6 +308,8 @@ BEGIN_JUCER_METADATA
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 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>
<SLIDER name="pitchRange" id="7409be5a8dfaa91" memberName="pitchRange"
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"
layout="33" items="Modern (Direct)&#10;Mark I&#10;OPL Series"
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>
END_JUCER_METADATA

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

@ -390,6 +390,13 @@ void CartridgeManager::rebuildMenu() {
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() ) {
zipIdx = 0;
ZipFile userZip(userCartFile);
@ -404,18 +411,11 @@ void CartridgeManager::rebuildMenu() {
} else {
lastModifiedUserCartFile = Time(0);
}
for(int i=0;i<cartNames.size();i++) {
completeCarts.addItem(i+1, cartNames[i]);
}
}
PopupMenu *CartridgeManager::getCarts() {
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 ) {
rebuildMenu();
}

@ -72,7 +72,7 @@ public:
if ( ! (midi->isInputActive() || midi->isOutputActive() ) )
return;
g.setColour(DXLookNFeel::dxDarkBrown);
//g.setColour(DXLookNFeel::dxDarkBrown);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColour(Colours::black);
g.drawSingleLineText("DX7 ", 0, 13);
@ -115,13 +115,6 @@ DexedAudioProcessorEditor::DexedAudioProcessorEditor (DexedAudioProcessor* owner
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));
midiMonitor->setBounds(645, 6, 110, 18);
@ -278,7 +271,7 @@ void DexedAudioProcessorEditor::parmShow() {
AlertWindow window("","", AlertWindow::NoIcon, this);
ParamDialog param;
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.addButton("OK", 0);
@ -286,7 +279,7 @@ void DexedAudioProcessorEditor::parmShow() {
if ( window.runModalLoop() != 0 )
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->savePreference();
@ -385,8 +378,8 @@ void DexedAudioProcessorEditor::storeProgram() {
dialog.addComboBox(String("Dest"), programs);
dialog.addButton("OK", 0, KeyPress(KeyPress::returnKey));
dialog.addButton("Cancel", 1, KeyPress(KeyPress::escapeKey));
dialog.addButton("External File", 2, KeyPress());
dialog.addButton("CANCEL", 1, KeyPress(KeyPress::escapeKey));
dialog.addButton("EXTERNAL FILE", 2, KeyPress());
int response = dialog.runModalLoop();
if ( response == 2 ) {

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

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

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

Loading…
Cancel
Save