Browse Source

Update juce

tags/2018-04-16
falkTX 11 years ago
parent
commit
3f05eae6f4
72 changed files with 896 additions and 674 deletions
  1. +1
    -1
      libs/juce/source/modules/juce_audio_basics/juce_module_info
  2. +31
    -1
      libs/juce/source/modules/juce_audio_basics/midi/juce_MidiMessage.cpp
  3. +7
    -43
      libs/juce/source/modules/juce_audio_basics/midi/juce_MidiMessage.h
  4. +1
    -1
      libs/juce/source/modules/juce_audio_basics/sources/juce_AudioSource.h
  5. +105
    -84
      libs/juce/source/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.cpp
  6. +19
    -12
      libs/juce/source/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.h
  7. +1
    -1
      libs/juce/source/modules/juce_audio_devices/audio_io/juce_AudioIODeviceType.h
  8. +1
    -1
      libs/juce/source/modules/juce_audio_devices/juce_module_info
  9. +17
    -5
      libs/juce/source/modules/juce_audio_devices/native/juce_MidiDataConcatenator.h
  10. +3
    -7
      libs/juce/source/modules/juce_audio_devices/native/juce_linux_JackAudio.cpp
  11. +7
    -1
      libs/juce/source/modules/juce_audio_devices/native/juce_win32_Midi.cpp
  12. +1
    -1
      libs/juce/source/modules/juce_audio_formats/format/juce_AudioSubsectionReader.h
  13. +1
    -1
      libs/juce/source/modules/juce_audio_formats/juce_module_info
  14. +42
    -4
      libs/juce/source/modules/juce_audio_plugin_client/AAX/juce_AAX_Wrapper.cpp
  15. +24
    -35
      libs/juce/source/modules/juce_audio_plugin_client/RTAS/juce_RTAS_Wrapper.cpp
  16. +1
    -1
      libs/juce/source/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h
  17. +53
    -57
      libs/juce/source/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp
  18. +1
    -1
      libs/juce/source/modules/juce_audio_plugin_client/juce_module_info
  19. +15
    -58
      libs/juce/source/modules/juce_audio_processors/format_types/juce_VST3Common.h
  20. +26
    -25
      libs/juce/source/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp
  21. +10
    -7
      libs/juce/source/modules/juce_audio_processors/juce_audio_processors.cpp
  22. +1
    -1
      libs/juce/source/modules/juce_audio_processors/juce_module_info
  23. +1
    -1
      libs/juce/source/modules/juce_audio_processors/processors/juce_PluginDescription.h
  24. +1
    -1
      libs/juce/source/modules/juce_audio_utils/juce_module_info
  25. +2
    -2
      libs/juce/source/modules/juce_core/containers/juce_NamedValueSet.h
  26. +1
    -1
      libs/juce/source/modules/juce_core/juce_core.cpp
  27. +1
    -1
      libs/juce/source/modules/juce_core/juce_core.h
  28. +1
    -1
      libs/juce/source/modules/juce_core/juce_module_info
  29. +39
    -15
      libs/juce/source/modules/juce_core/native/java/JuceAppActivity.java
  30. +45
    -37
      libs/juce/source/modules/juce_core/native/juce_android_JNIHelpers.h
  31. +13
    -11
      libs/juce/source/modules/juce_core/native/juce_android_Network.cpp
  32. +18
    -27
      libs/juce/source/modules/juce_core/native/juce_linux_Network.cpp
  33. +12
    -13
      libs/juce/source/modules/juce_core/native/juce_mac_Network.mm
  34. +5
    -0
      libs/juce/source/modules/juce_core/native/juce_posix_SharedCode.h
  35. +30
    -30
      libs/juce/source/modules/juce_core/native/juce_win32_Network.cpp
  36. +32
    -37
      libs/juce/source/modules/juce_core/native/juce_win32_SystemStats.cpp
  37. +18
    -4
      libs/juce/source/modules/juce_core/network/juce_URL.cpp
  38. +17
    -7
      libs/juce/source/modules/juce_core/network/juce_URL.h
  39. +1
    -1
      libs/juce/source/modules/juce_core/streams/juce_OutputStream.h
  40. +1
    -1
      libs/juce/source/modules/juce_core/system/juce_StandardHeader.h
  41. +51
    -40
      libs/juce/source/modules/juce_core/threads/juce_CriticalSection.h
  42. +1
    -1
      libs/juce/source/modules/juce_data_structures/app_properties/juce_PropertiesFile.h
  43. +1
    -1
      libs/juce/source/modules/juce_data_structures/juce_module_info
  44. +1
    -1
      libs/juce/source/modules/juce_events/broadcasters/juce_ActionBroadcaster.h
  45. +1
    -4
      libs/juce/source/modules/juce_events/broadcasters/juce_ActionListener.h
  46. +1
    -1
      libs/juce/source/modules/juce_events/juce_module_info
  47. +1
    -1
      libs/juce/source/modules/juce_events/messages/juce_NotificationType.h
  48. +9
    -8
      libs/juce/source/modules/juce_graphics/geometry/juce_Point.h
  49. +10
    -0
      libs/juce/source/modules/juce_graphics/geometry/juce_Rectangle.h
  50. +14
    -1
      libs/juce/source/modules/juce_graphics/images/juce_Image.cpp
  51. +13
    -0
      libs/juce/source/modules/juce_graphics/images/juce_Image.h
  52. +1
    -1
      libs/juce/source/modules/juce_graphics/juce_module_info
  53. +5
    -1
      libs/juce/source/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm
  54. +5
    -0
      libs/juce/source/modules/juce_graphics/native/juce_mac_Fonts.mm
  55. +1
    -1
      libs/juce/source/modules/juce_gui_basics/commands/juce_ApplicationCommandManager.h
  56. +1
    -1
      libs/juce/source/modules/juce_gui_basics/commands/juce_KeyPressMappingSet.h
  57. +2
    -2
      libs/juce/source/modules/juce_gui_basics/components/juce_Component.h
  58. +1
    -1
      libs/juce/source/modules/juce_gui_basics/juce_module_info
  59. +10
    -9
      libs/juce/source/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.cpp
  60. +5
    -1
      libs/juce/source/modules/juce_gui_basics/native/juce_linux_Windowing.cpp
  61. +30
    -14
      libs/juce/source/modules/juce_gui_basics/native/juce_win32_Windowing.cpp
  62. +16
    -0
      libs/juce/source/modules/juce_gui_basics/properties/juce_PropertyComponent.h
  63. +15
    -7
      libs/juce/source/modules/juce_gui_basics/widgets/juce_Slider.cpp
  64. +18
    -6
      libs/juce/source/modules/juce_gui_basics/widgets/juce_Slider.h
  65. +6
    -5
      libs/juce/source/modules/juce_gui_basics/widgets/juce_TreeView.cpp
  66. +1
    -1
      libs/juce/source/modules/juce_gui_basics/widgets/juce_TreeView.h
  67. +9
    -4
      libs/juce/source/modules/juce_gui_basics/windows/juce_CallOutBox.cpp
  68. +5
    -0
      libs/juce/source/modules/juce_gui_basics/windows/juce_CallOutBox.h
  69. +1
    -1
      libs/juce/source/modules/juce_gui_basics/windows/juce_ComponentPeer.h
  70. +33
    -21
      libs/juce/source/modules/juce_gui_basics/windows/juce_ThreadWithProgressWindow.cpp
  71. +21
    -1
      libs/juce/source/modules/juce_gui_basics/windows/juce_ThreadWithProgressWindow.h
  72. +1
    -1
      libs/juce/source/modules/juce_gui_extra/juce_module_info

+ 1
- 1
libs/juce/source/modules/juce_audio_basics/juce_module_info View File

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


+ 31
- 1
libs/juce/source/modules/juce_audio_basics/midi/juce_MidiMessage.cpp View File

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


+ 7
- 43
libs/juce/source/modules/juce_audio_basics/midi/juce_MidiMessage.h View File

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


+ 1
- 1
libs/juce/source/modules/juce_audio_basics/sources/juce_AudioSource.h View File

@@ -65,7 +65,7 @@ struct JUCE_API AudioSourceChannelInfo
Only the samples specified by the startSample and numSamples members of this structure
should be affected by the call.
The contents of the buffer when it is passed to the the AudioSource::getNextAudioBlock()
The contents of the buffer when it is passed to the AudioSource::getNextAudioBlock()
method can be treated as the input if the source is performing some kind of filter operation,
but should be cleared if this is not the case - the clearActiveBufferRegion() is
a handy way of doing this.


+ 105
- 84
libs/juce/source/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.cpp View File

@@ -114,7 +114,7 @@ void AudioDeviceManager::createDeviceTypesIfNeeded()
{
if (availableDeviceTypes.size() == 0)
{
OwnedArray <AudioIODeviceType> types;
OwnedArray<AudioIODeviceType> types;
createAudioDeviceTypes (types);
for (int i = 0; i < types.size(); ++i)
@@ -127,7 +127,7 @@ void AudioDeviceManager::createDeviceTypesIfNeeded()
}
}
const OwnedArray <AudioIODeviceType>& AudioDeviceManager::getAvailableDeviceTypes()
const OwnedArray<AudioIODeviceType>& AudioDeviceManager::getAvailableDeviceTypes()
{
scanDevicesIfNeeded();
return availableDeviceTypes;
@@ -147,13 +147,13 @@ void AudioDeviceManager::audioDeviceListChanged()
}
//==============================================================================
static void addIfNotNull (OwnedArray <AudioIODeviceType>& list, AudioIODeviceType* const device)
static void addIfNotNull (OwnedArray<AudioIODeviceType>& list, AudioIODeviceType* const device)
{
if (device != nullptr)
list.add (device);
}
void AudioDeviceManager::createAudioDeviceTypes (OwnedArray <AudioIODeviceType>& list)
void AudioDeviceManager::createAudioDeviceTypes (OwnedArray<AudioIODeviceType>& list)
{
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_WASAPI());
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_DirectSound());
@@ -181,7 +181,7 @@ void AudioDeviceManager::addAudioDeviceType (AudioIODeviceType* newDeviceType)
//==============================================================================
String AudioDeviceManager::initialise (const int numInputChannelsNeeded,
const int numOutputChannelsNeeded,
const XmlElement* const e,
const XmlElement* const xml,
const bool selectDefaultDeviceOnFailure,
const String& preferredDefaultDeviceName,
const AudioDeviceSetup* preferredSetupOptions)
@@ -191,106 +191,127 @@ String AudioDeviceManager::initialise (const int numInputChannelsNeeded,
numInputChansNeeded = numInputChannelsNeeded;
numOutputChansNeeded = numOutputChannelsNeeded;
if (e != nullptr && e->hasTagName ("DEVICESETUP"))
{
lastExplicitSettings = new XmlElement (*e);
if (xml != nullptr && xml->hasTagName ("DEVICESETUP"))
return initialiseFromXML (*xml, selectDefaultDeviceOnFailure,
preferredDefaultDeviceName, preferredSetupOptions);
String error;
AudioDeviceSetup setup;
return initialiseDefault (preferredDefaultDeviceName, preferredSetupOptions);
}
if (preferredSetupOptions != nullptr)
setup = *preferredSetupOptions;
String AudioDeviceManager::initialiseDefault (const String& preferredDefaultDeviceName,
const AudioDeviceSetup* preferredSetupOptions)
{
AudioDeviceSetup setup;
if (e->getStringAttribute ("audioDeviceName").isNotEmpty())
{
setup.inputDeviceName = setup.outputDeviceName
= e->getStringAttribute ("audioDeviceName");
}
else
if (preferredSetupOptions != nullptr)
{
setup = *preferredSetupOptions;
}
else if (preferredDefaultDeviceName.isNotEmpty())
{
for (int j = availableDeviceTypes.size(); --j >= 0;)
{
setup.inputDeviceName = e->getStringAttribute ("audioInputDeviceName");
setup.outputDeviceName = e->getStringAttribute ("audioOutputDeviceName");
}
AudioIODeviceType* const type = availableDeviceTypes.getUnchecked(j);
currentDeviceType = e->getStringAttribute ("deviceType");
const StringArray outs (type->getDeviceNames (false));
if (findType (currentDeviceType) == nullptr)
{
if (AudioIODeviceType* const type = findType (setup.inputDeviceName, setup.outputDeviceName))
currentDeviceType = type->getTypeName();
else if (availableDeviceTypes.size() > 0)
currentDeviceType = availableDeviceTypes.getUnchecked(0)->getTypeName();
for (int i = 0; i < outs.size(); ++i)
{
if (outs[i].matchesWildcard (preferredDefaultDeviceName, true))
{
setup.outputDeviceName = outs[i];
break;
}
}
const StringArray ins (type->getDeviceNames (true));
for (int i = 0; i < ins.size(); ++i)
{
if (ins[i].matchesWildcard (preferredDefaultDeviceName, true))
{
setup.inputDeviceName = ins[i];
break;
}
}
}
}
setup.bufferSize = e->getIntAttribute ("audioDeviceBufferSize");
setup.sampleRate = e->getDoubleAttribute ("audioDeviceRate");
insertDefaultDeviceNames (setup);
return setAudioDeviceSetup (setup, false);
}
setup.inputChannels .parseString (e->getStringAttribute ("audioDeviceInChans", "11"), 2);
setup.outputChannels.parseString (e->getStringAttribute ("audioDeviceOutChans", "11"), 2);
String AudioDeviceManager::initialiseFromXML (const XmlElement& xml,
const bool selectDefaultDeviceOnFailure,
const String& preferredDefaultDeviceName,
const AudioDeviceSetup* preferredSetupOptions)
{
lastExplicitSettings = new XmlElement (xml);
setup.useDefaultInputChannels = ! e->hasAttribute ("audioDeviceInChans");
setup.useDefaultOutputChannels = ! e->hasAttribute ("audioDeviceOutChans");
String error;
AudioDeviceSetup setup;
error = setAudioDeviceSetup (setup, true);
if (preferredSetupOptions != nullptr)
setup = *preferredSetupOptions;
midiInsFromXml.clear();
forEachXmlChildElementWithTagName (*e, c, "MIDIINPUT")
midiInsFromXml.add (c->getStringAttribute ("name"));
if (xml.getStringAttribute ("audioDeviceName").isNotEmpty())
{
setup.inputDeviceName = setup.outputDeviceName
= xml.getStringAttribute ("audioDeviceName");
}
else
{
setup.inputDeviceName = xml.getStringAttribute ("audioInputDeviceName");
setup.outputDeviceName = xml.getStringAttribute ("audioOutputDeviceName");
}
const StringArray allMidiIns (MidiInput::getDevices());
currentDeviceType = xml.getStringAttribute ("deviceType");
for (int i = allMidiIns.size(); --i >= 0;)
setMidiInputEnabled (allMidiIns[i], midiInsFromXml.contains (allMidiIns[i]));
if (findType (currentDeviceType) == nullptr)
{
if (AudioIODeviceType* const type = findType (setup.inputDeviceName, setup.outputDeviceName))
currentDeviceType = type->getTypeName();
else if (availableDeviceTypes.size() > 0)
currentDeviceType = availableDeviceTypes.getUnchecked(0)->getTypeName();
}
if (error.isNotEmpty() && selectDefaultDeviceOnFailure)
error = initialise (numInputChannelsNeeded, numOutputChannelsNeeded, 0,
false, preferredDefaultDeviceName);
setup.bufferSize = xml.getIntAttribute ("audioDeviceBufferSize");
setup.sampleRate = xml.getDoubleAttribute ("audioDeviceRate");
setDefaultMidiOutput (e->getStringAttribute ("defaultMidiOutput"));
setup.inputChannels .parseString (xml.getStringAttribute ("audioDeviceInChans", "11"), 2);
setup.outputChannels.parseString (xml.getStringAttribute ("audioDeviceOutChans", "11"), 2);
return error;
}
else
{
AudioDeviceSetup setup;
setup.useDefaultInputChannels = ! xml.hasAttribute ("audioDeviceInChans");
setup.useDefaultOutputChannels = ! xml.hasAttribute ("audioDeviceOutChans");
if (preferredSetupOptions != nullptr)
{
setup = *preferredSetupOptions;
}
else if (preferredDefaultDeviceName.isNotEmpty())
{
for (int j = availableDeviceTypes.size(); --j >= 0;)
{
AudioIODeviceType* const type = availableDeviceTypes.getUnchecked(j);
error = setAudioDeviceSetup (setup, true);
const StringArray outs (type->getDeviceNames (false));
midiInsFromXml.clear();
for (int i = 0; i < outs.size(); ++i)
{
if (outs[i].matchesWildcard (preferredDefaultDeviceName, true))
{
setup.outputDeviceName = outs[i];
break;
}
}
forEachXmlChildElementWithTagName (xml, c, "MIDIINPUT")
midiInsFromXml.add (c->getStringAttribute ("name"));
const StringArray ins (type->getDeviceNames (true));
const StringArray allMidiIns (MidiInput::getDevices());
for (int i = 0; i < ins.size(); ++i)
{
if (ins[i].matchesWildcard (preferredDefaultDeviceName, true))
{
setup.inputDeviceName = ins[i];
break;
}
}
}
}
for (int i = allMidiIns.size(); --i >= 0;)
setMidiInputEnabled (allMidiIns[i], midiInsFromXml.contains (allMidiIns[i]));
insertDefaultDeviceNames (setup);
return setAudioDeviceSetup (setup, false);
}
if (error.isNotEmpty() && selectDefaultDeviceOnFailure)
error = initialise (numInputChansNeeded, numOutputChansNeeded,
nullptr, false, preferredDefaultDeviceName);
setDefaultMidiOutput (xml.getStringAttribute ("defaultMidiOutput"));
return error;
}
String AudioDeviceManager::initialiseWithDefaultDevices (int numInputChannelsNeeded,
int numOutputChannelsNeeded)
{
lastExplicitSettings = nullptr;
return initialise (numInputChannelsNeeded, numOutputChannelsNeeded,
nullptr, false, String(), nullptr);
}
void AudioDeviceManager::insertDefaultDeviceNames (AudioDeviceSetup& setup) const
@@ -880,7 +901,7 @@ void AudioDeviceManager::setDefaultMidiOutput (const String& deviceName)
{
if (defaultMidiOutputName != deviceName)
{
Array <AudioIODeviceCallback*> oldCallbacks;
Array<AudioIODeviceCallback*> oldCallbacks;
{
const ScopedLock sl (audioCallbackLock);
@@ -915,7 +936,7 @@ void AudioDeviceManager::setDefaultMidiOutput (const String& deviceName)
void AudioDeviceManager::playTestSound()
{
{ // cunningly nested to swap, unlock and delete in that order.
ScopedPointer <AudioSampleBuffer> oldSound;
ScopedPointer<AudioSampleBuffer> oldSound;
{
const ScopedLock sl (audioCallbackLock);


+ 19
- 12
libs/juce/source/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.h View File

@@ -191,7 +191,11 @@ public:
const XmlElement* savedState,
bool selectDefaultDeviceOnFailure,
const String& preferredDefaultDeviceName = String(),
const AudioDeviceSetup* preferredSetupOptions = 0);
const AudioDeviceSetup* preferredSetupOptions = nullptr);
/** Resets everything to a default device setup, clearing any stored settings. */
String initialiseWithDefaultDevices (int numInputChannelsNeeded,
int numOutputChannelsNeeded);
/** Returns some XML representing the current state of the manager.
@@ -383,7 +387,7 @@ public:
/** Returns a list of the types of device supported.
*/
const OwnedArray <AudioIODeviceType>& getAvailableDeviceTypes();
const OwnedArray<AudioIODeviceType>& getAvailableDeviceTypes();
//==============================================================================
/** Creates a list of available types.
@@ -394,7 +398,7 @@ public:
You can override this if your app needs to do something specific, like avoid
using DirectSound devices, etc.
*/
virtual void createAudioDeviceTypes (OwnedArray <AudioIODeviceType>& types);
virtual void createAudioDeviceTypes (OwnedArray<AudioIODeviceType>& types);
/** Adds a new device type to the list of types.
The manager will take ownership of the object that is passed-in.
@@ -446,30 +450,30 @@ public:
private:
//==============================================================================
OwnedArray <AudioIODeviceType> availableDeviceTypes;
OwnedArray <AudioDeviceSetup> lastDeviceTypeConfigs;
OwnedArray<AudioIODeviceType> availableDeviceTypes;
OwnedArray<AudioDeviceSetup> lastDeviceTypeConfigs;
AudioDeviceSetup currentSetup;
ScopedPointer <AudioIODevice> currentAudioDevice;
Array <AudioIODeviceCallback*> callbacks;
ScopedPointer<AudioIODevice> currentAudioDevice;
Array<AudioIODeviceCallback*> callbacks;
int numInputChansNeeded, numOutputChansNeeded;
String currentDeviceType;
BigInteger inputChannels, outputChannels;
ScopedPointer <XmlElement> lastExplicitSettings;
ScopedPointer<XmlElement> lastExplicitSettings;
mutable bool listNeedsScanning;
bool useInputNames;
Atomic<int> inputLevelMeasurementEnabledCount;
double inputLevel;
ScopedPointer <AudioSampleBuffer> testSound;
ScopedPointer<AudioSampleBuffer> testSound;
int testSoundPosition;
AudioSampleBuffer tempBuffer;
StringArray midiInsFromXml;
OwnedArray <MidiInput> enabledMidiInputs;
Array <MidiInputCallback*> midiCallbacks;
OwnedArray<MidiInput> enabledMidiInputs;
Array<MidiInputCallback*> midiCallbacks;
StringArray midiCallbackDevices;
String defaultMidiOutputName;
ScopedPointer <MidiOutput> defaultMidiOutput;
ScopedPointer<MidiOutput> defaultMidiOutput;
CriticalSection audioCallbackLock, midiCallbackLock;
double cpuUsageMs, timeToCpuScale;
@@ -500,6 +504,9 @@ private:
double chooseBestSampleRate (double preferred) const;
int chooseBestBufferSize (int preferred) const;
void insertDefaultDeviceNames (AudioDeviceSetup&) const;
String initialiseDefault (const String& preferredDefaultDeviceName, const AudioDeviceSetup*);
String initialiseFromXML (const XmlElement&, bool selectDefaultDeviceOnFailure,
const String& preferredDefaultDeviceName, const AudioDeviceSetup*);
AudioIODeviceType* findType (const String& inputName, const String& outputName);
AudioIODeviceType* findType (const String& typeName);


+ 1
- 1
libs/juce/source/modules/juce_audio_devices/audio_io/juce_AudioIODeviceType.h View File

@@ -118,7 +118,7 @@ public:
/**
A class for receiving events when audio devices are inserted or removed.
You can register a AudioIODeviceType::Listener with an~AudioIODeviceType object
You can register an AudioIODeviceType::Listener with an~AudioIODeviceType object
using the AudioIODeviceType::addListener() method, and it will be called when
devices of that type are added or removed.


+ 1
- 1
libs/juce/source/modules/juce_audio_devices/juce_module_info View File

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


+ 17
- 5
libs/juce/source/modules/juce_audio_devices/native/juce_MidiDataConcatenator.h View File

@@ -123,6 +123,14 @@ private:
{
if (pendingBytes > 0 && *d >= 0x80)
{
if (*d == 0xf7)
{
*dest++ = *d++;
++pendingBytes;
--numBytes;
break;
}
if (*d >= 0xfa || *d == 0xf8)
{
callback.handleIncomingMidiMessage (input, MidiMessage (*d, time));
@@ -131,11 +139,15 @@ private:
}
else
{
if (*d == 0xf7)
pendingBytes = 0;
int used = 0;
const MidiMessage m (d, numBytes, used, 0, time);
if (used > 0)
{
*dest++ = *d++;
pendingBytes++;
--numBytes;
callback.handleIncomingMidiMessage (input, m);
numBytes -= used;
d += used;
}
break;
@@ -144,7 +156,7 @@ private:
else
{
*dest++ = *d++;
pendingBytes++;
++pendingBytes;
--numBytes;
}
}


+ 3
- 7
libs/juce/source/modules/juce_audio_devices/native/juce_linux_JackAudio.cpp View File

@@ -502,13 +502,9 @@ public:
outputNames.clear();
outputIds.clear();
if (juce_libjackHandle == nullptr)
{
juce_libjackHandle = dlopen ("libjack.so", RTLD_LAZY);
if (juce_libjackHandle == nullptr)
return;
}
if (juce_libjackHandle == nullptr) juce_libjackHandle = dlopen ("libjack.so.0", RTLD_LAZY);
if (juce_libjackHandle == nullptr) juce_libjackHandle = dlopen ("libjack.so", RTLD_LAZY);
if (juce_libjackHandle == nullptr) return;
jack_status_t status;


+ 7
- 1
libs/juce/source/modules/juce_audio_devices/native/juce_win32_Midi.cpp View File

@@ -478,6 +478,12 @@ void MidiOutput::sendMessageNow (const MidiMessage& message)
}
else
{
midiOutShortMsg (handle->handle, *(unsigned int*) message.getRawData());
for (int i = 0; i < 50; ++i)
{
if (midiOutShortMsg (handle->handle, *(unsigned int*) message.getRawData()) != MIDIERR_NOTREADY)
break;
Sleep (1);
}
}
}

+ 1
- 1
libs/juce/source/modules/juce_audio_formats/format/juce_AudioSubsectionReader.h View File

@@ -43,7 +43,7 @@ class JUCE_API AudioSubsectionReader : public AudioFormatReader
{
public:
//==============================================================================
/** Creates a AudioSubsectionReader for a given data source.
/** Creates an AudioSubsectionReader for a given data source.
@param sourceReader the source reader from which we'll be taking data
@param subsectionStartSample the sample within the source reader which will be


+ 1
- 1
libs/juce/source/modules/juce_audio_formats/juce_module_info View File

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


+ 42
- 4
libs/juce/source/modules/juce_audio_plugin_client/AAX/juce_AAX_Wrapper.cpp View File

@@ -124,8 +124,7 @@ struct AAXClasses
case 6: return AAX_eStemFormat_5_1;
case 7: return AAX_eStemFormat_7_0_DTS;
case 8: return AAX_eStemFormat_7_1_DTS;
default: jassertfalse; break; // hmm - not a valid number of chans..
default: jassertfalse; break;
}
return AAX_eStemFormat_None;
@@ -139,17 +138,45 @@ struct AAXClasses
case AAX_eStemFormat_Mono: return 1;
case AAX_eStemFormat_Stereo: return 2;
case AAX_eStemFormat_LCR: return 3;
case AAX_eStemFormat_LCRS:
case AAX_eStemFormat_Quad: return 4;
case AAX_eStemFormat_5_0: return 5;
case AAX_eStemFormat_5_1: return 6;
case AAX_eStemFormat_5_1:
case AAX_eStemFormat_6_0: return 6;
case AAX_eStemFormat_6_1:
case AAX_eStemFormat_7_0_SDDS:
case AAX_eStemFormat_7_0_DTS: return 7;
case AAX_eStemFormat_7_1_SDDS:
case AAX_eStemFormat_7_1_DTS: return 8;
default: jassertfalse; break; // hmm - not a valid number of chans..
default: jassertfalse; break;
}
return 0;
}
static const char* getSpeakerArrangementString (AAX_EStemFormat format) noexcept
{
switch (format)
{
case AAX_eStemFormat_Mono: return "M";
case AAX_eStemFormat_Stereo: return "L R";
case AAX_eStemFormat_LCR: return "L C R";
case AAX_eStemFormat_LCRS: return "L C R S";
case AAX_eStemFormat_Quad: return "L R Ls Rs";
case AAX_eStemFormat_5_0: return "L C R Ls Rs";
case AAX_eStemFormat_5_1: return "L C R Ls Rs LFE";
case AAX_eStemFormat_6_0: return "L C R Ls Cs Rs";
case AAX_eStemFormat_6_1: return "L C R Ls Cs Rs LFE";
case AAX_eStemFormat_7_0_SDDS: return "L Lc C Rc R Ls Rs";
case AAX_eStemFormat_7_1_SDDS: return "L Lc C Rc R Ls Rs LFE";
case AAX_eStemFormat_7_0_DTS: return "L C R Lss Rss Lsr Rsr";
case AAX_eStemFormat_7_1_DTS: return "L C R Lss Rss Lsr Rsr LFE";
default: break;
}
return nullptr;
}
//==============================================================================
struct JUCELibraryRefCount
{
@@ -652,6 +679,7 @@ struct AAXClasses
void audioProcessorChanged (AudioProcessor* processor) override
{
++mNumPlugInChanges;
check (Controller()->SetSignalLatency (processor->getLatencySamples()));
}
@@ -855,6 +883,9 @@ struct AAXClasses
AudioProcessor& audioProcessor = getPluginInstance();
audioProcessor.setSpeakerArrangement (getSpeakerArrangementString (inputStemFormat),
getSpeakerArrangementString (outputStemFormat));
audioProcessor.setPlayConfigDetails (numberOfInputChannels, numberOfOutputChannels, sampleRate, lastBufferSize);
audioProcessor.prepareToPlay (sampleRate, lastBufferSize);
@@ -931,6 +962,13 @@ 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);
properties->AddProperty (AAX_eProperty_PlugInID_AudioSuite, 'jyaa' + channelConfigIndex);
#if JucePlugin_AAXDisableMultiMono
properties->AddProperty (AAX_eProperty_Constraint_MultiMonoSupport, false);
#else
properties->AddProperty (AAX_eProperty_Constraint_MultiMonoSupport, true);
#endif
check (desc.AddProcessProc_Native (algorithmProcessCallback, properties));
}


+ 24
- 35
libs/juce/source/modules/juce_audio_plugin_client/RTAS/juce_RTAS_Wrapper.cpp View File

@@ -203,10 +203,8 @@ public:
{
public:
//==============================================================================
JuceCustomUIView (AudioProcessor* const filter_,
JucePlugInProcess* const process_)
: filter (filter_),
process (process_)
JuceCustomUIView (AudioProcessor* ap, JucePlugInProcess* p)
: filter (ap), process (p)
{
// setting the size in here crashes PT for some reason, so keep it simple..
}
@@ -237,7 +235,7 @@ public:
r.bottom = editorComp->getHeight();
SetRect (&r);
if ((oldRect.right != r.right) || (oldRect.bottom != r.bottom))
if (oldRect.right != r.right || oldRect.bottom != r.bottom)
startTimer (50);
}
}
@@ -269,8 +267,6 @@ public:
#endif
wrapper = nullptr;
wrapper = new EditorCompWrapper (hostWindow, editorComp, this);
process->touchAllParameters();
}
}
else
@@ -774,23 +770,13 @@ protected:
// xxx is there an RTAS equivalent?
}
void touchAllParameters()
{
for (int i = 0; i < juceFilter->getNumParameters(); ++i)
{
audioProcessorParameterChangeGestureBegin (0, i);
audioProcessorParameterChanged (0, i, juceFilter->getParameter (i));
audioProcessorParameterChangeGestureEnd (0, i);
}
}
public:
// Need to use an intermediate class here rather than inheriting from AsyncUpdater, so that it can
// be deleted before shutting down juce in our destructor.
class InternalAsyncUpdater : public AsyncUpdater
{
public:
InternalAsyncUpdater (JucePlugInProcess& owner_) : owner (owner_) {}
InternalAsyncUpdater (JucePlugInProcess& p) : owner (p) {}
void handleAsyncUpdate() { owner.handleAsyncUpdate(); }
private:
@@ -927,29 +913,32 @@ public:
for (int i = 0; i < numConfigs; ++i)
{
CEffectType* const type
= new CEffectTypeRTAS ('jcaa' + i,
JucePlugin_RTASProductId,
JucePlugin_RTASCategory);
if (channelConfigs[i][0] <= 8 && channelConfigs[i][1] <= 8)
{
CEffectType* const type
= new CEffectTypeRTAS ('jcaa' + i,
JucePlugin_RTASProductId,
JucePlugin_RTASCategory);
type->DefineTypeNames (createRTASName().toRawUTF8());
type->DefineSampleRateSupport (eSupports48kAnd96kAnd192k);
type->DefineTypeNames (createRTASName().toRawUTF8());
type->DefineSampleRateSupport (eSupports48kAnd96kAnd192k);
type->DefineStemFormats (getFormatForChans (channelConfigs [i][0] != 0 ? channelConfigs [i][0] : channelConfigs [i][1]),
getFormatForChans (channelConfigs [i][1] != 0 ? channelConfigs [i][1] : channelConfigs [i][0]));
type->DefineStemFormats (getFormatForChans (channelConfigs [i][0] != 0 ? channelConfigs [i][0] : channelConfigs [i][1]),
getFormatForChans (channelConfigs [i][1] != 0 ? channelConfigs [i][1] : channelConfigs [i][0]));
#if ! JucePlugin_RTASDisableBypass
type->AddGestalt (pluginGestalt_CanBypass);
#endif
#if ! JucePlugin_RTASDisableBypass
type->AddGestalt (pluginGestalt_CanBypass);
#endif
#if JucePlugin_RTASDisableMultiMono
type->AddGestalt (pluginGestalt_DoesntSupportMultiMono);
#endif
#if JucePlugin_RTASDisableMultiMono
type->AddGestalt (pluginGestalt_DoesntSupportMultiMono);
#endif
type->AddGestalt (pluginGestalt_SupportsVariableQuanta);
type->AttachEffectProcessCreator (createNewProcess);
type->AddGestalt (pluginGestalt_SupportsVariableQuanta);
type->AttachEffectProcessCreator (createNewProcess);
AddEffectType (type);
AddEffectType (type);
}
}
}


+ 1
- 1
libs/juce/source/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h View File

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


+ 53
- 57
libs/juce/source/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp View File

@@ -176,7 +176,9 @@ public:
toString128 (info.title, p.getParameterName (index));
toString128 (info.shortTitle, p.getParameterName (index, 8));
toString128 (info.units, p.getParameterLabel (index));
info.stepCount = (Steinberg::int32) p.getParameterNumSteps (index);
const int numSteps = p.getParameterNumSteps (index);
info.stepCount = (Steinberg::int32) (numSteps > 0 && numSteps < 0x7fffffff ? numSteps - 1 : 0);
info.defaultNormalizedValue = p.getParameterDefaultValue (index);
info.unitId = Vst::kRootUnitId;
info.flags = p.isParameterAutomatable (index) ? Vst::ParameterInfo::kCanAutomate : 0;
@@ -752,78 +754,72 @@ public:
tresult PLUGIN_API setIoMode (Vst::IoMode) override { return kNotImplemented; }
tresult PLUGIN_API getRoutingInfo (Vst::RoutingInfo&, Vst::RoutingInfo&) override { return kNotImplemented; }
tresult PLUGIN_API setState (IBStream* state) override
bool readFromMemoryStream (IBStream* state) const
{
if (state != nullptr)
FUnknownPtr<MemoryStream> s (state);
if (s != nullptr
&& s->getData() != nullptr
&& s->getSize() > 0
&& s->getSize() < 1024 * 1024 * 100) // (some hosts seem to return junk for the size)
{
// Reset to the beginning of the stream:
if (state->seek (0, IBStream::kIBSeekSet, nullptr) != kResultTrue)
return kResultFalse;
// Adobe Audition CS6 hack to avoid trying to use corrupted streams:
if (getHostType().isAdobeAudition())
if (s->getSize() >= 5 && memcmp (s->getData(), "VC2!E", 5) == 0)
return kResultFalse;
Steinberg::int64 end = -1;
pluginInstance->setStateInformation (s->getData(), (int) s->getSize());
return true;
}
if (end < 0)
{
FUnknownPtr<ISizeableStream> s (state);
return false;
}
if (s != nullptr)
s->getStreamSize (end);
}
bool readFromUnknownStream (IBStream* state) const
{
MemoryOutputStream allData;
{
const size_t bytesPerBlock = 4096;
HeapBlock<char> buffer (bytesPerBlock);
if (end < 0)
for (;;)
{
FUnknownPtr<MemoryStream> s (state);
int32 bytesRead = 0;
if (s != nullptr)
if (state->read (buffer, (int32) bytesPerBlock, &bytesRead) == kResultTrue && bytesRead > 0)
{
if (getHostType().isAdobeAudition())
{
// Adobe Audition CS6 hack to avoid trying to use corrupted streams:
bool failed = true;
if (const char* const data = s->getData())
{
if (s->getSize() >= 5 && data[0] != 'V' && data[1] != 'C'
&& data[2] != '2' && data[3] != '!' && data[4] != 'E')
{
failed = false;
}
}
else
{
jassertfalse;
}
if (failed)
return kResultFalse;
}
end = (Steinberg::int64) s->getSize();
allData.write (buffer, bytesRead);
continue;
}
break;
}
}
if (end <= 0)
return kResultFalse;
const size_t dataSize = allData.getDataSize();
// Try reading the data, and setting the plugin state:
Steinberg::int32 numBytes = (Steinberg::int32) jmin ((Steinberg::int64) std::numeric_limits<Steinberg::int32>::max(), end);
if (dataSize > 0 && dataSize < 0x7fffffff)
{
pluginInstance->setStateInformation (allData.getData(), (int) dataSize);
return true;
}
Array<char> buff;
buff.ensureStorageAllocated ((int) numBytes);
void* buffer = buff.getRawDataPointer();
return false;
}
if (state->read (buffer, numBytes, &numBytes) == kResultTrue
&& buffer != nullptr
&& numBytes > 0)
{
pluginInstance->setStateInformation (buffer, (int) numBytes);
return kResultTrue;
}
tresult PLUGIN_API setState (IBStream* state) override
{
if (state == nullptr)
return kInvalidArgument;
return kResultFalse;
}
FUnknownPtr<IBStream> stateRefHolder (state); // just in case the caller hasn't properly ref-counted the stream object
return kInvalidArgument;
if (state->seek (0, IBStream::kIBSeekSet, nullptr) == kResultTrue)
if (readFromMemoryStream (state) || readFromUnknownStream (state))
return kResultTrue;
return kResultFalse;
}
tresult PLUGIN_API getState (IBStream* state) override
@@ -1084,7 +1080,7 @@ public:
tresult PLUGIN_API process (Vst::ProcessData& data) override
{
if (pluginInstance == nullptr || processContext.sampleRate <= 0.0)
if (pluginInstance == nullptr)
return kResultFalse;
if (data.processContext != nullptr)


+ 1
- 1
libs/juce/source/modules/juce_audio_plugin_client/juce_module_info View File

@@ -1,7 +1,7 @@
{
"id": "juce_audio_plugin_client",
"name": "JUCE audio plugin wrapper classes",
"version": "3.0.2",
"version": "3.0.4",
"description": "Classes for building VST, VST3, RTAS, AAX and AU plugins.",
"website": "http://www.juce.com/juce",
"license": "GPL/Commercial",


+ 15
- 58
libs/juce/source/modules/juce_audio_processors/format_types/juce_VST3Common.h View File

@@ -27,11 +27,11 @@
//==============================================================================
#define JUCE_DECLARE_VST3_COM_REF_METHODS \
Steinberg::uint32 JUCE_CALLTYPE addRef() override { return (Steinberg::uint32) ++refCount; } \
Steinberg::uint32 JUCE_CALLTYPE release() override { const int r = --refCount; if (r == 0) delete this; return (Steinberg::uint32) r; }
Steinberg::uint32 PLUGIN_API addRef() override { return (Steinberg::uint32) ++refCount; } \
Steinberg::uint32 PLUGIN_API release() override { const int r = --refCount; if (r == 0) delete this; return (Steinberg::uint32) r; }
#define JUCE_DECLARE_VST3_COM_QUERY_METHODS \
Steinberg::tresult PLUGIN_API JUCE_CALLTYPE queryInterface (const Steinberg::TUID, void** obj) override \
Steinberg::tresult PLUGIN_API queryInterface (const Steinberg::TUID, void** obj) override \
{ \
jassertfalse; \
*obj = nullptr; \
@@ -51,6 +51,14 @@ static bool doUIDsMatch (const Steinberg::TUID a, const Steinberg::TUID b) noexc
return Steinberg::kResultOk; \
}
#define TEST_FOR_COMMON_BASE_AND_RETURN_IF_VALID(CommonClassType, SourceClassType) \
if (doUIDsMatch (iid, CommonClassType::iid)) \
{ \
addRef(); \
*obj = (CommonClassType*) static_cast<SourceClassType*> (this); \
return Steinberg::kResultOk; \
}
//==============================================================================
static juce::String toString (const Steinberg::char8* string) noexcept { return juce::String (string); }
static juce::String toString (const Steinberg::char16* string) noexcept { return juce::String (juce::CharPointer_UTF16 ((juce::CharPointer_UTF16::CharType*) string)); }
@@ -70,19 +78,15 @@ static Steinberg::Vst::TChar* toString (const juce::String& source) noexcept
}
#if JUCE_WINDOWS
static const Steinberg::FIDString defaultVST3WindowType = Steinberg::kPlatformTypeHWND;
static const Steinberg::FIDString defaultVST3WindowType = Steinberg::kPlatformTypeHWND;
#else
static const Steinberg::FIDString defaultVST3WindowType = Steinberg::kPlatformTypeNSView;
static const Steinberg::FIDString defaultVST3WindowType = Steinberg::kPlatformTypeNSView;
#endif
//==============================================================================
/** The equivalent numChannels and speaker arrangements should always
match between this function and fillWithCorrespondingSpeakerArrangements().
There can only be 1 arrangement per channel count. (i.e.: 4 channels == k31Cine OR k40Cine)
@see fillWithCorrespondingSpeakerArrangements
/** For the sake of simplicity, there can only be 1 arrangement type per channel count.
i.e.: 4 channels == k31Cine OR k40Cine
*/
static Steinberg::Vst::SpeakerArrangement getArrangementForNumChannels (int numChannels) noexcept
{
@@ -116,53 +120,6 @@ static Steinberg::Vst::SpeakerArrangement getArrangementForNumChannels (int numC
return (Steinberg::Vst::SpeakerArrangement) bi.toInt64();
}
/** The equivalent numChannels and speaker arrangements should always
match between this function and getArrangementForNumChannels().
There can only be 1 arrangement per channel count. (i.e.: 4 channels == k31Cine OR k40Cine)
@see getArrangementForNumChannels
*/
static void fillWithCorrespondingSpeakerArrangements (Array<Steinberg::Vst::SpeakerArrangement>& destination,
int numChannels)
{
using namespace Steinberg::Vst::SpeakerArr;
destination.clearQuick();
if (numChannels <= 0)
{
destination.add (kEmpty);
return;
}
// The order of the arrangement checks must be descending, since most plugins test for
/// the first arrangement to match their number of specified channels.
if (numChannels > 24)
{
juce::BigInteger bi;
bi.setRange (0, jmin (numChannels, (int) (sizeof (Steinberg::Vst::SpeakerArrangement) * 8)), true);
destination.add ((Steinberg::Vst::SpeakerArrangement) bi.toInt64());
}
if (numChannels >= 24) destination.add ((Steinberg::Vst::SpeakerArrangement) 1929904127); // k222
if (numChannels >= 14) destination.add (k131);
if (numChannels >= 13) destination.add (k130);
if (numChannels >= 12) destination.add (k111);
if (numChannels >= 11) destination.add (k101);
if (numChannels >= 10) destination.add (k91);
if (numChannels >= 9) destination.add (k90);
if (numChannels >= 8) destination.add (k71CineFullFront);
if (numChannels >= 7) destination.add (k61Cine);
if (numChannels >= 6) destination.add (k51);
if (numChannels >= 5) destination.add (k50);
if (numChannels >= 4) destination.add (k31Cine);
if (numChannels >= 3) destination.add (k30Cine);
if (numChannels >= 2) destination.add (kStereo);
if (numChannels >= 1) destination.add (kMono);
}
//==============================================================================
template <class ObjectType>
class ComSmartPtr


+ 26
- 25
libs/juce/source/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp View File

@@ -98,7 +98,7 @@ static void fillDescriptionWith (PluginDescription& description, ObjectType& obj
description.version = toString (object.version).trim();
description.category = toString (object.subCategories).trim();
if (description.manufacturerName.isEmpty())
if (description.manufacturerName.trim().isEmpty())
description.manufacturerName = toString (object.vendor).trim();
}
@@ -459,13 +459,13 @@ public:
{
*obj = nullptr;
if (! doIdsMatch (cid, iid))
if (! doUIDsMatch (cid, iid))
{
jassertfalse;
return kInvalidArgument;
}
if (doIdsMatch (cid, Vst::IMessage::iid) && doIdsMatch (iid, Vst::IMessage::iid))
if (doUIDsMatch (cid, Vst::IMessage::iid) && doUIDsMatch (iid, Vst::IMessage::iid))
{
ComSmartPtr<Message> m (new Message (*this, attributeList));
messageQueue.add (m);
@@ -473,7 +473,7 @@ public:
*obj = m;
return kResultOk;
}
else if (doIdsMatch (cid, Vst::IAttributeList::iid) && doIdsMatch (iid, Vst::IAttributeList::iid))
else if (doUIDsMatch (cid, Vst::IAttributeList::iid) && doUIDsMatch (iid, Vst::IAttributeList::iid))
{
ComSmartPtr<AttributeList> l (new AttributeList (this));
l->addRef();
@@ -526,7 +526,7 @@ public:
//==============================================================================
tresult PLUGIN_API queryInterface (const TUID iid, void** obj) override
{
if (doIdsMatch (iid, Vst::IAttributeList::iid))
if (doUIDsMatch (iid, Vst::IAttributeList::iid))
{
*obj = attributeList.get();
return kResultOk;
@@ -539,6 +539,7 @@ public:
TEST_FOR_AND_RETURN_IF_VALID (Vst::IHostApplication)
TEST_FOR_AND_RETURN_IF_VALID (Vst::IParamValueQueue)
TEST_FOR_AND_RETURN_IF_VALID (Vst::IUnitHandler)
TEST_FOR_COMMON_BASE_AND_RETURN_IF_VALID (FUnknown, Vst::IComponentHandler)
*obj = nullptr;
return kNotImplemented;
@@ -550,12 +551,6 @@ private:
String appName;
VST3PluginInstance* owner;
//==============================================================================
static bool doIdsMatch (const TUID a, const TUID b) noexcept
{
return std::memcmp (a, b, sizeof (TUID)) == 0;
}
//==============================================================================
class Message : public Vst::IMessage
{
@@ -1206,7 +1201,7 @@ public:
setOpaque (true);
setVisible (true);
view->setFrame (this);
warnOnFailure (view->setFrame (this));
ViewRect rect;
warnOnFailure (view->getSize (&rect));
@@ -1215,7 +1210,7 @@ public:
~VST3PluginWindow()
{
view->removed();
warnOnFailure (view->removed());
getAudioProcessor()->editorBeingDeleted (this);
#if JUCE_MAC
@@ -1273,7 +1268,7 @@ public:
}
else
{
view->getSize (&rect);
warnOnFailure (view->getSize (&rect));
}
#if JUCE_WINDOWS
@@ -1485,12 +1480,6 @@ public:
{
using namespace Vst;
const int numInputs = getNumInputChannels();
const int numOutputs = getNumOutputChannels();
// Needed for having the same sample rate in processBlock(); some plugins need this!
setPlayConfigDetails (numInputs, numOutputs, sampleRate, estimatedSamplesPerBlock);
ProcessSetup setup;
setup.symbolicSampleSize = kSample32;
setup.maxSamplesPerBlock = estimatedSamplesPerBlock;
@@ -1504,16 +1493,28 @@ public:
editController->setComponentHandler (host);
setStateForAllBusses (true);
Array<SpeakerArrangement> inArrangements, outArrangements;
fillWithCorrespondingSpeakerArrangements (inArrangements, numInputs);
fillWithCorrespondingSpeakerArrangements (outArrangements, numOutputs);
for (int i = 0; i < numInputAudioBusses; ++i)
inArrangements.add (getArrangementForNumChannels (jmax (0, (int) getBusInfo (true, true, i).channelCount)));
for (int i = 0; i < numOutputAudioBusses; ++i)
outArrangements.add (getArrangementForNumChannels (jmax (0, (int) getBusInfo (false, true, i).channelCount)));
warnOnFailure (processor->setBusArrangements (inArrangements.getRawDataPointer(), numInputAudioBusses,
outArrangements.getRawDataPointer(), numOutputAudioBusses));
// Update the num. busses in case the configuration has been modified by the plugin. (May affect number of channels!):
numInputAudioBusses = getNumSingleDirectionBussesFor (component, true, true);
numOutputAudioBusses = getNumSingleDirectionBussesFor (component, false, true);
// Needed for having the same sample rate in processBlock(); some plugins need this!
setPlayConfigDetails (getNumSingleDirectionChannelsFor (component, true, true),
getNumSingleDirectionChannelsFor (component, false, true),
sampleRate, estimatedSamplesPerBlock);
setStateForAllBusses (true);
warnOnFailure (component->setActive (true));
warnOnFailure (processor->setProcessing (true));
}
@@ -1716,7 +1717,7 @@ public:
if (head != nullptr)
{
ScopedPointer<Steinberg::MemoryStream> s (createMemoryStreamForState (*head, "IComponent"));
ComSmartPtr<Steinberg::MemoryStream> s (createMemoryStreamForState (*head, "IComponent"));
if (s != nullptr && component != nullptr)
component->setState (s);


+ 10
- 7
libs/juce/source/modules/juce_audio_processors/juce_audio_processors.cpp View File

@@ -119,15 +119,18 @@ struct AutoResizingNSViewComponentWithParent : public AutoResizingNSViewCompone
{
if (NSView* parent = (NSView*) getView())
{
if (NSView* child = [[parent subviews] firstObject])
if ([[parent subviews] count] > 0)
{
NSRect f = [parent frame];
NSSize newSize = [child frame].size;
if (f.size.width != newSize.width || f.size.height != newSize.height)
if (NSView* child = [[parent subviews] objectAtIndex: 0])
{
f.size = newSize;
[parent setFrame: f];
NSRect f = [parent frame];
NSSize newSize = [child frame].size;
if (f.size.width != newSize.width || f.size.height != newSize.height)
{
f.size = newSize;
[parent setFrame: f];
}
}
}
}


+ 1
- 1
libs/juce/source/modules/juce_audio_processors/juce_module_info View File

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


+ 1
- 1
libs/juce/source/modules/juce_audio_processors/processors/juce_PluginDescription.h View File

@@ -102,7 +102,7 @@ public:
/** True if the plug-in is part of a multi-type container, e.g. a VST Shell. */
bool hasSharedContainer;
/** Returns true if the two descriptions refer the the same plug-in.
/** Returns true if the two descriptions refer to the same plug-in.
This isn't quite as simple as them just having the same file (because of
shell plug-ins).


+ 1
- 1
libs/juce/source/modules/juce_audio_utils/juce_module_info View File

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


+ 2
- 2
libs/juce/source/modules/juce_core/containers/juce_NamedValueSet.h View File

@@ -76,14 +76,14 @@ public:
/** Changes or adds a named value.
@returns true if a value was changed or added; false if the
value was already set the the value passed-in.
value was already set the value passed-in.
*/
bool set (Identifier name, const var& newValue);
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
/** Changes or adds a named value.
@returns true if a value was changed or added; false if the
value was already set the the value passed-in.
value was already set the value passed-in.
*/
bool set (Identifier name, var&& newValue);
#endif


+ 1
- 1
libs/juce/source/modules/juce_core/juce_core.cpp View File

@@ -133,7 +133,6 @@ namespace juce
#include "network/juce_MACAddress.cpp"
#include "network/juce_NamedPipe.cpp"
#include "network/juce_Socket.cpp"
#include "network/juce_URL.cpp"
#include "network/juce_IPAddress.cpp"
#include "streams/juce_BufferedInputStream.cpp"
#include "streams/juce_FileInputSource.cpp"
@@ -219,5 +218,6 @@ namespace juce
#include "threads/juce_ChildProcess.cpp"
#include "threads/juce_HighResolutionTimer.cpp"
#include "network/juce_URL.cpp"
}

+ 1
- 1
libs/juce/source/modules/juce_core/juce_core.h View File

@@ -64,7 +64,7 @@
//=============================================================================
/** Config: JUCE_LOG_ASSERTIONS
If this flag is enabled, the the jassert and jassertfalse macros will always use Logger::writeToLog()
If this flag is enabled, the jassert and jassertfalse macros will always use Logger::writeToLog()
to write a message when an assertion happens.
Enabling it will also leave this turned on in release builds. When it's disabled,


+ 1
- 1
libs/juce/source/modules/juce_core/juce_module_info View File

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


+ 39
- 15
libs/juce/source/modules/juce_core/native/java/JuceAppActivity.java View File

@@ -589,10 +589,34 @@ public final class JuceAppActivity extends Activity
//==============================================================================
public static class HTTPStream
{
public HTTPStream (HttpURLConnection connection_) throws IOException
public HTTPStream (HttpURLConnection connection_,
int[] statusCode, StringBuffer responseHeaders) throws IOException
{
connection = connection_;
inputStream = new BufferedInputStream (connection.getInputStream());
try
{
inputStream = new BufferedInputStream (connection.getInputStream());
}
catch (IOException e)
{
if (connection.getResponseCode() < org.apache.http.HttpStatus.SC_BAD_REQUEST)
throw e;
}
finally
{
statusCode[0] = connection.getResponseCode();
}
if (statusCode[0] >= org.apache.http.HttpStatus.SC_BAD_REQUEST)
inputStream = connection.getErrorStream();
else
inputStream = connection.getInputStream();
for (java.util.Map.Entry<String, java.util.List<String>> entry : connection.getHeaderFields().entrySet())
if (entry.getKey() != null && entry.getValue() != null)
responseHeaders.append (entry.getKey() + ": "
+ android.text.TextUtils.join (",", entry.getValue()) + "\n");
}
public final void release()
@@ -634,30 +658,31 @@ public final class JuceAppActivity extends Activity
private long position;
}
public static final HTTPStream createHTTPStream (String address, boolean isPost, byte[] postData,
String headers, int timeOutMs,
java.lang.StringBuffer responseHeaders)
public static final HTTPStream createHTTPStream (String address,
boolean isPost, byte[] postData, String headers,
int timeOutMs, int[] statusCode,
StringBuffer responseHeaders)
{
try
{
HttpURLConnection connection = (HttpURLConnection) (new URL (address).openConnection());
HttpURLConnection connection = (HttpURLConnection) (new URL(address)
.openConnection());
if (connection != null)
{
try
{
if (isPost)
{
connection.setConnectTimeout (timeOutMs);
connection.setDoOutput (true);
connection.setChunkedStreamingMode (0);
connection.setRequestMethod("POST");
connection.setConnectTimeout(timeOutMs);
connection.setDoOutput(true);
connection.setChunkedStreamingMode(0);
OutputStream out = connection.getOutputStream();
out.write (postData);
out.write(postData);
out.flush();
}
return new HTTPStream (connection);
return new HTTPStream (connection, statusCode, responseHeaders);
}
catch (Throwable e)
{
@@ -665,8 +690,7 @@ public final class JuceAppActivity extends Activity
}
}
}
catch (Throwable e)
{}
catch (Throwable e) {}
return null;
}


+ 45
- 37
libs/juce/source/modules/juce_core/native/juce_android_JNIHelpers.h View File

@@ -251,7 +251,7 @@ extern AndroidSystem android;
class ThreadLocalJNIEnvHolder
{
public:
ThreadLocalJNIEnvHolder()
ThreadLocalJNIEnvHolder() noexcept
: jvm (nullptr)
{
zeromem (threads, sizeof (threads));
@@ -269,18 +269,19 @@ public:
addEnv (env);
}
JNIEnv* attach()
JNIEnv* attach() noexcept
{
JNIEnv* env = nullptr;
jvm->AttachCurrentThread (&env, nullptr);
if (env != nullptr)
addEnv (env);
if (JNIEnv* env = attachToCurrentThread())
{
SpinLock::ScopedLockType sl (addRemoveLock);
return addEnv (env);
}
return env;
jassertfalse;
return nullptr;
}
void detach()
void detach() noexcept
{
jvm->DetachCurrentThread();
@@ -294,54 +295,61 @@ public:
JNIEnv* getOrAttach() noexcept
{
JNIEnv* env = get();
if (JNIEnv* env = get())
return env;
if (env == nullptr)
env = attach();
SpinLock::ScopedLockType sl (addRemoveLock);
jassert (env != nullptr);
return env;
}
if (JNIEnv* env = get())
return env;
JNIEnv* get() const noexcept
{
const pthread_t thisThread = pthread_self();
for (int i = 0; i < maxThreads; ++i)
if (threads[i] == thisThread)
return envs[i];
if (JNIEnv* env = attachToCurrentThread())
return addEnv (env);
return nullptr;
}
enum { maxThreads = 32 };
private:
JavaVM* jvm;
enum { maxThreads = 32 };
pthread_t threads [maxThreads];
JNIEnv* envs [maxThreads];
SpinLock addRemoveLock;
void addEnv (JNIEnv* env)
JNIEnv* addEnv (JNIEnv* env) noexcept
{
SpinLock::ScopedLockType sl (addRemoveLock);
const pthread_t thisThread = pthread_self();
if (get() == nullptr)
for (int i = 0; i < maxThreads; ++i)
{
const pthread_t thisThread = pthread_self();
for (int i = 0; i < maxThreads; ++i)
if (threads[i] == 0)
{
if (threads[i] == 0)
{
envs[i] = env;
threads[i] = thisThread;
return;
}
envs[i] = env;
threads[i] = thisThread;
return env;
}
}
jassertfalse; // too many threads!
return nullptr;
}
JNIEnv* get() const noexcept
{
const pthread_t thisThread = pthread_self();
for (int i = 0; i < maxThreads; ++i)
if (threads[i] == thisThread)
return envs[i];
return nullptr;
}
JNIEnv* attachToCurrentThread()
{
JNIEnv* env = nullptr;
jvm->AttachCurrentThread (&env, nullptr);
return env;
}
};
@@ -357,7 +365,7 @@ extern ThreadLocalJNIEnvHolder threadLocalJNIEnvHolder;
METHOD (setClipboardContent, "setClipboardContent", "(Ljava/lang/String;)V") \
METHOD (excludeClipRegion, "excludeClipRegion", "(Landroid/graphics/Canvas;FFFF)V") \
METHOD (renderGlyph, "renderGlyph", "(CLandroid/graphics/Paint;Landroid/graphics/Matrix;Landroid/graphics/Rect;)[I") \
STATICMETHOD (createHTTPStream, "createHTTPStream", "(Ljava/lang/String;Z[BLjava/lang/String;ILjava/lang/StringBuffer;)L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$HTTPStream;") \
STATICMETHOD (createHTTPStream, "createHTTPStream", "(Ljava/lang/String;Z[BLjava/lang/String;I[ILjava/lang/StringBuffer;)L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$HTTPStream;") \
METHOD (launchURL, "launchURL", "(Ljava/lang/String;)V") \
METHOD (showMessageBox, "showMessageBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \
METHOD (showOkCancelBox, "showOkCancelBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \


+ 13
- 11
libs/juce/source/modules/juce_core/native/juce_android_Network.cpp View File

@@ -71,6 +71,7 @@ public:
WebInputStream (String address, bool isPost, const MemoryBlock& postData,
URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
const String& headers, int timeOutMs, StringPairArray* responseHeaders)
: statusCode (0)
{
if (! address.contains ("://"))
address = "http://" + address;
@@ -91,6 +92,9 @@ public:
// thread. You'll need to move your networking code to a background thread to keep it happy..
jassert (Thread::getCurrentThread() != nullptr);
jintArray statusCodeArray = env->NewIntArray (1);
jassert (statusCodeArray != 0);
stream = GlobalRef (env->CallStaticObjectMethod (JuceAppActivity,
JuceAppActivity.createHTTPStream,
javaString (address).get(),
@@ -98,8 +102,14 @@ public:
postDataArray,
javaString (headers).get(),
(jint) timeOutMs,
statusCodeArray,
responseHeaderBuffer.get()));
jint* const statusCodeElements = env->GetIntArrayElements (statusCodeArray, 0);
statusCode = statusCodeElements[0];
env->ReleaseIntArrayElements (statusCodeArray, statusCodeElements, 0);
env->DeleteLocalRef (statusCodeArray);
if (postDataArray != 0)
env->DeleteLocalRef (postDataArray);
@@ -135,6 +145,8 @@ public:
}
//==============================================================================
bool isError() const { return stream == nullptr; }
bool isExhausted() override { return stream != nullptr && stream.callBooleanMethod (HTTPStream.isExhausted); }
int64 getTotalLength() override { return stream != nullptr ? stream.callLongMethod (HTTPStream.getTotalLength) : 0; }
int64 getPosition() override { return stream != nullptr ? stream.callLongMethod (HTTPStream.getPosition) : 0; }
@@ -162,18 +174,8 @@ public:
//==============================================================================
GlobalRef stream;
int statusCode;
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebInputStream)
};
InputStream* URL::createNativeStream (const String& address, bool isPost, const MemoryBlock& postData,
OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
const String& headers, const int timeOutMs, StringPairArray* responseHeaders)
{
ScopedPointer <WebInputStream> wi (new WebInputStream (address, isPost, postData,
progressCallback, progressCallbackContext,
headers, timeOutMs, responseHeaders));
return wi->stream != 0 ? wi.release() : nullptr;
}

+ 18
- 27
libs/juce/source/modules/juce_core/native/juce_linux_Network.cpp View File

@@ -72,11 +72,11 @@ public:
WebInputStream (const String& address_, bool isPost_, const MemoryBlock& postData_,
URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
const String& headers_, int timeOutMs_, StringPairArray* responseHeaders)
: socketHandle (-1), levelsOfRedirection (0),
: statusCode (0), socketHandle (-1), levelsOfRedirection (0),
address (address_), headers (headers_), postData (postData_), position (0),
finished (false), isPost (isPost_), timeOutMs (timeOutMs_)
{
createConnection (progressCallback, progressCallbackContext);
statusCode = createConnection (progressCallback, progressCallbackContext);
if (responseHeaders != nullptr && ! isError())
{
@@ -144,7 +144,7 @@ public:
{
closeSocket();
position = 0;
createConnection (0, 0);
statusCode = createConnection (0, 0);
}
skipNextBytes (wantedPos - position);
@@ -154,6 +154,8 @@ public:
}
//==============================================================================
int statusCode;
private:
int socketHandle, levelsOfRedirection;
StringArray headerLines;
@@ -173,7 +175,7 @@ private:
levelsOfRedirection = 0;
}
void createConnection (URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext)
int createConnection (URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext)
{
closeSocket();
@@ -189,7 +191,7 @@ private:
String hostName, hostPath;
int hostPort;
if (! decomposeURL (address, hostName, hostPath, hostPort))
return;
return 0;
String serverName, proxyName, proxyPath;
int proxyPort = 0;
@@ -199,7 +201,7 @@ private:
if (proxyURL.startsWithIgnoreCase ("http://"))
{
if (! decomposeURL (proxyURL, proxyName, proxyPath, proxyPort))
return;
return 0;
serverName = proxyName;
port = proxyPort;
@@ -219,14 +221,14 @@ private:
struct addrinfo* result = nullptr;
if (getaddrinfo (serverName.toUTF8(), String (port).toUTF8(), &hints, &result) != 0 || result == 0)
return;
return 0;
socketHandle = socket (result->ai_family, result->ai_socktype, 0);
if (socketHandle == -1)
{
freeaddrinfo (result);
return;
return 0;
}
int receiveBufferSize = 16384;
@@ -241,7 +243,7 @@ private:
{
closeSocket();
freeaddrinfo (result);
return;
return 0;
}
freeaddrinfo (result);
@@ -254,7 +256,7 @@ private:
progressCallback, progressCallbackContext))
{
closeSocket();
return;
return 0;
}
}
@@ -265,15 +267,15 @@ private:
{
headerLines = StringArray::fromLines (responseHeader);
const int statusCode = responseHeader.fromFirstOccurrenceOf (" ", false, false)
.substring (0, 3).getIntValue();
const int status = responseHeader.fromFirstOccurrenceOf (" ", false, false)
.substring (0, 3).getIntValue();
//int contentLength = findHeaderItem (lines, "Content-Length:").getIntValue();
//bool isChunked = findHeaderItem (lines, "Transfer-Encoding:").equalsIgnoreCase ("chunked");
String location (findHeaderItem (headerLines, "Location:"));
if (statusCode >= 300 && statusCode < 400
if (status >= 300 && status < 400
&& location.isNotEmpty() && location != address)
{
if (! location.startsWithIgnoreCase ("http://"))
@@ -282,18 +284,18 @@ private:
if (++levelsOfRedirection <= 3)
{
address = location;
createConnection (progressCallback, progressCallbackContext);
return;
return createConnection (progressCallback, progressCallbackContext);
}
}
else
{
levelsOfRedirection = 0;
return;
return status;
}
}
closeSocket();
return 0;
}
//==============================================================================
@@ -437,14 +439,3 @@ private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebInputStream)
};
InputStream* URL::createNativeStream (const String& address, bool isPost, const MemoryBlock& postData,
OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
const String& headers, const int timeOutMs, StringPairArray* responseHeaders)
{
ScopedPointer<WebInputStream> wi (new WebInputStream (address, isPost, postData,
progressCallback, progressCallbackContext,
headers, timeOutMs, responseHeaders));
return wi->isError() ? nullptr : wi.release();
}

+ 12
- 13
libs/juce/source/modules/juce_core/native/juce_mac_Network.mm View File

@@ -118,6 +118,7 @@ public:
connection (nil),
data ([[NSMutableData data] retain]),
headers (nil),
statusCode (0),
initialised (false),
hasFailed (false),
hasFinished (false)
@@ -202,7 +203,11 @@ public:
headers = nil;
if ([response isKindOfClass: [NSHTTPURLResponse class]])
headers = [[((NSHTTPURLResponse*) response) allHeaderFields] retain];
{
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*) response;
headers = [[httpResponse allHeaderFields] retain];
statusCode = (int) [httpResponse statusCode];
}
}
void didFailWithError (NSError* error)
@@ -251,6 +256,7 @@ public:
NSURLConnection* connection;
NSMutableData* data;
NSDictionary* headers;
int statusCode;
bool initialised, hasFailed, hasFinished;
private:
@@ -318,7 +324,7 @@ public:
WebInputStream (const String& address_, bool isPost_, const MemoryBlock& postData_,
URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
const String& headers_, int timeOutMs_, StringPairArray* responseHeaders)
: address (address_), headers (headers_), postData (postData_), position (0),
: statusCode (0), address (address_), headers (headers_), postData (postData_), position (0),
finished (false), isPost (isPost_), timeOutMs (timeOutMs_)
{
JUCE_AUTORELEASEPOOL
@@ -327,6 +333,8 @@ public:
if (responseHeaders != nullptr && connection != nullptr && connection->headers != nil)
{
statusCode = connection->statusCode;
NSEnumerator* enumerator = [connection->headers keyEnumerator];
while (NSString* key = [enumerator nextObject])
@@ -380,6 +388,8 @@ public:
return true;
}
int statusCode;
private:
ScopedPointer<URLConnectionState> connection;
String address, headers;
@@ -428,14 +438,3 @@ private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebInputStream)
};
InputStream* URL::createNativeStream (const String& address, bool isPost, const MemoryBlock& postData,
OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
const String& headers, const int timeOutMs, StringPairArray* responseHeaders)
{
ScopedPointer<WebInputStream> wi (new WebInputStream (address, isPost, postData,
progressCallback, progressCallbackContext,
headers, timeOutMs, responseHeaders));
return wi->isError() ? nullptr : wi.release();
}

+ 5
- 0
libs/juce/source/modules/juce_core/native/juce_posix_SharedCode.h View File

@@ -996,6 +996,11 @@ public:
ActiveProcess (const StringArray& arguments, int streamFlags)
: childPID (0), pipeHandle (0), readHandle (0)
{
// Looks like you're trying to launch a non-existent exe or a folder (perhaps on OSX
// you're trying to launch the .app folder rather than the actual binary inside it?)
jassert ((! arguments[0].containsChar ('/'))
|| File::getCurrentWorkingDirectory().getChildFile (arguments[0]).existsAsFile());
int pipeHandles[2] = { 0 };
if (pipe (pipeHandles) == 0)


+ 30
- 30
libs/juce/source/modules/juce_core/native/juce_win32_Network.cpp View File

@@ -41,41 +41,50 @@ public:
WebInputStream (const String& address_, bool isPost_, const MemoryBlock& postData_,
URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
const String& headers_, int timeOutMs_, StringPairArray* responseHeaders)
: connection (0), request (0),
: statusCode (0), connection (0), request (0),
address (address_), headers (headers_), postData (postData_), position (0),
finished (false), isPost (isPost_), timeOutMs (timeOutMs_)
{
createConnection (progressCallback, progressCallbackContext);
if (responseHeaders != nullptr && ! isError())
if (! isError())
{
DWORD bufferSizeBytes = 4096;
for (;;)
if (responseHeaders != nullptr)
{
HeapBlock<char> buffer ((size_t) bufferSizeBytes);
DWORD bufferSizeBytes = 4096;
if (HttpQueryInfo (request, HTTP_QUERY_RAW_HEADERS_CRLF, buffer.getData(), &bufferSizeBytes, 0))
for (;;)
{
StringArray headersArray;
headersArray.addLines (String (reinterpret_cast<const WCHAR*> (buffer.getData())));
HeapBlock<char> buffer ((size_t) bufferSizeBytes);
for (int i = 0; i < headersArray.size(); ++i)
if (HttpQueryInfo (request, HTTP_QUERY_RAW_HEADERS_CRLF, buffer.getData(), &bufferSizeBytes, 0))
{
const String& header = headersArray[i];
const String key (header.upToFirstOccurrenceOf (": ", false, false));
const String value (header.fromFirstOccurrenceOf (": ", false, false));
const String previousValue ((*responseHeaders) [key]);
StringArray headersArray;
headersArray.addLines (String (reinterpret_cast<const WCHAR*> (buffer.getData())));
for (int i = 0; i < headersArray.size(); ++i)
{
const String& header = headersArray[i];
const String key (header.upToFirstOccurrenceOf (": ", false, false));
const String value (header.fromFirstOccurrenceOf (": ", false, false));
const String previousValue ((*responseHeaders) [key]);
responseHeaders->set (key, previousValue.isEmpty() ? value : (previousValue + "," + value));
responseHeaders->set (key, previousValue.isEmpty() ? value : (previousValue + "," + value));
}
break;
}
break;
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
break;
}
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
break;
}
DWORD status = 0;
DWORD statusSize = sizeof (status);
if (HttpQueryInfo (request, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &status, &statusSize, 0))
statusCode = (int) status;
}
}
@@ -145,6 +154,8 @@ public:
return true;
}
int statusCode;
private:
//==============================================================================
HINTERNET connection, request;
@@ -305,17 +316,6 @@ private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebInputStream)
};
InputStream* URL::createNativeStream (const String& address, bool isPost, const MemoryBlock& postData,
OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
const String& headers, const int timeOutMs, StringPairArray* responseHeaders)
{
ScopedPointer <WebInputStream> wi (new WebInputStream (address, isPost, postData,
progressCallback, progressCallbackContext,
headers, timeOutMs, responseHeaders));
return wi->isError() ? nullptr : wi.release();
}
//==============================================================================
struct GetAdaptersInfoHelper


+ 32
- 37
libs/juce/source/modules/juce_core/native/juce_win32_SystemStats.cpp View File

@@ -45,72 +45,67 @@ void Logger::outputDebugString (const String& text)
#pragma intrinsic (__cpuid)
#pragma intrinsic (__rdtsc)
String SystemStats::getCpuVendor()
static void callCPUID (int result[4], int infoType)
{
int info [4];
__cpuid (info, 0);
char v [12];
memcpy (v, info + 1, 4);
memcpy (v + 4, info + 3, 4);
memcpy (v + 8, info + 2, 4);
return String (v, 12);
__cpuid (result, infoType);
}
#else
//==============================================================================
// CPU info functions using old fashioned inline asm...
static void juce_getCpuVendor (char* const v)
static void callCPUID (int result[4], int infoType)
{
int vendor[4] = { 0 };
#if ! JUCE_MINGW
__try
#endif
{
#if JUCE_GCC
unsigned int dummy = 0;
__asm__ ("cpuid" : "=a" (dummy), "=b" (vendor[0]), "=c" (vendor[2]),"=d" (vendor[1]) : "a" (0));
__asm__ __volatile__ ("cpuid" : "=a" (result[0]), "=b" (result[1]), "=c" (result[2]),"=d" (result[3]) : "a" (infoType));
#else
__asm
{
mov eax, 0
mov esi, result
mov eax, infoType
xor ecx, ecx
cpuid
mov [vendor], ebx
mov [vendor + 4], edx
mov [vendor + 8], ecx
mov dword ptr [esi + 0], eax
mov dword ptr [esi + 4], ebx
mov dword ptr [esi + 8], ecx
mov dword ptr [esi + 12], edx
}
#endif
}
#if ! JUCE_MINGW
__except (EXCEPTION_EXECUTE_HANDLER)
{
}
__except (EXCEPTION_EXECUTE_HANDLER) {}
#endif
memcpy (v, vendor, 16);
}
#endif
String SystemStats::getCpuVendor()
{
char v [16];
juce_getCpuVendor (v);
return String (v, 16);
}
#endif
int info[4] = { 0 };
callCPUID (info, 0);
char v [12];
memcpy (v, info + 1, 4);
memcpy (v + 4, info + 3, 4);
memcpy (v + 8, info + 2, 4);
return String (v, 12);
}
//==============================================================================
void CPUInformation::initialise() noexcept
{
hasMMX = IsProcessorFeaturePresent (PF_MMX_INSTRUCTIONS_AVAILABLE) != 0;
hasSSE = IsProcessorFeaturePresent (PF_XMMI_INSTRUCTIONS_AVAILABLE) != 0;
hasSSE2 = IsProcessorFeaturePresent (PF_XMMI64_INSTRUCTIONS_AVAILABLE) != 0;
hasSSE3 = IsProcessorFeaturePresent (13 /*PF_SSE3_INSTRUCTIONS_AVAILABLE*/) != 0;
has3DNow = IsProcessorFeaturePresent (7 /*PF_AMD3D_INSTRUCTIONS_AVAILABLE*/) != 0;
int info[4] = { 0 };
callCPUID (info, 1);
// NB: IsProcessorFeaturePresent doesn't work on XP
hasMMX = (info[3] & (1 << 23)) != 0;
hasSSE = (info[3] & (1 << 25)) != 0;
hasSSE2 = (info[3] & (1 << 26)) != 0;
hasSSE3 = (info[2] & (1 << 0)) != 0;
has3DNow = (info[1] & (1 << 31)) != 0;
SYSTEM_INFO systemInfo;
GetNativeSystemInfo (&systemInfo);


+ 18
- 4
libs/juce/source/modules/juce_core/network/juce_URL.cpp View File

@@ -63,6 +63,13 @@ URL::URL (const String& u) : url (u)
}
}
URL::URL (const String& u, int) : url (u) {}
URL URL::createWithoutParsing (const String& u)
{
return URL (u, 0);
}
URL::URL (const URL& other)
: url (other.url),
postData (other.postData),
@@ -323,7 +330,8 @@ InputStream* URL::createInputStream (const bool usePostCommand,
void* const progressCallbackContext,
String headers,
const int timeOutMs,
StringPairArray* const responseHeaders) const
StringPairArray* const responseHeaders,
int* statusCode) const
{
MemoryBlock headersAndPostData;
@@ -336,9 +344,15 @@ InputStream* URL::createInputStream (const bool usePostCommand,
if (! headers.endsWithChar ('\n'))
headers << "\r\n";
return createNativeStream (toString (! usePostCommand), usePostCommand, headersAndPostData,
progressCallback, progressCallbackContext,
headers, timeOutMs, responseHeaders);
ScopedPointer<WebInputStream> wi (new WebInputStream (toString (! usePostCommand),
usePostCommand, headersAndPostData,
progressCallback, progressCallbackContext,
headers, timeOutMs, responseHeaders));
if (statusCode != nullptr)
*statusCode = wi->statusCode;
return wi->isError() ? nullptr : wi.release();
}
//==============================================================================


+ 17
- 7
libs/juce/source/modules/juce_core/network/juce_URL.h View File

@@ -44,7 +44,11 @@ public:
/** Creates an empty URL. */
URL();
/** Creates a URL from a string. */
/** Creates a URL from a string.
This will parse any embedded parameters after a '?' character and store them
in the list (see getParameterNames etc). If you don't want this to happen, you
can use createWithoutParsing().
*/
URL (const String& url);
/** Creates a copy of another URL. */
@@ -243,8 +247,10 @@ public:
@param connectionTimeOutMs if 0, this will use whatever default setting the OS chooses. If
a negative number, it will be infinite. Otherwise it specifies a
time in milliseconds.
@param responseHeaders if this is non-zero, all the (key, value) pairs received as headers
@param responseHeaders if this is non-null, all the (key, value) pairs received as headers
in the response will be stored in this array
@param statusCode if this is non-null, it will get set to the http status code, if one
is known, or 0 if a code isn't available
@returns an input stream that the caller must delete, or a null pointer if there was an
error trying to open it.
*/
@@ -253,7 +259,8 @@ public:
void* progressCallbackContext = nullptr,
String extraHeaders = String(),
int connectionTimeOutMs = 0,
StringPairArray* responseHeaders = nullptr) const;
StringPairArray* responseHeaders = nullptr,
int* statusCode = nullptr) const;
//==============================================================================
@@ -326,18 +333,21 @@ public:
*/
static String removeEscapeChars (const String& stringToRemoveEscapeCharsFrom);
/** Returns a URL without attempting to remove any embedded parameters from the string.
This may be necessary if you need to create a request that involves both POST
parameters and parameters which are embedded in the URL address itself.
*/
static URL createWithoutParsing (const String& url);
private:
//==============================================================================
String url, postData;
StringArray parameterNames, parameterValues;
StringPairArray filesToUpload, mimeTypes;
URL (const String&, int);
void addParameter (const String&, const String&);
static InputStream* createNativeStream (const String& address, bool isPost, const MemoryBlock& postData,
OpenStreamProgressCallback* progressCallback,
void* progressCallbackContext, const String& headers,
const int timeOutMs, StringPairArray* responseHeaders);
JUCE_LEAK_DETECTOR (URL)
};


+ 1
- 1
libs/juce/source/modules/juce_core/streams/juce_OutputStream.h View File

@@ -226,7 +226,7 @@ public:
//==============================================================================
/** Sets the string that will be written to the stream when the writeNewLine()
method is called.
By default this will be set the the value of NewLine::getDefault().
By default this will be set the value of NewLine::getDefault().
*/
void setNewLineString (const String& newLineString);


+ 1
- 1
libs/juce/source/modules/juce_core/system/juce_StandardHeader.h View File

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


+ 51
- 40
libs/juce/source/modules/juce_core/threads/juce_CriticalSection.h View File

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


+ 1
- 1
libs/juce/source/modules/juce_data_structures/app_properties/juce_PropertiesFile.h View File

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


+ 1
- 1
libs/juce/source/modules/juce_data_structures/juce_module_info View File

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


+ 1
- 1
libs/juce/source/modules/juce_events/broadcasters/juce_ActionBroadcaster.h View File

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


+ 1
- 4
libs/juce/source/modules/juce_events/broadcasters/juce_ActionListener.h View File

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


+ 1
- 1
libs/juce/source/modules/juce_events/juce_module_info View File

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


+ 1
- 1
libs/juce/source/modules/juce_events/messages/juce_NotificationType.h View File

@@ -35,7 +35,7 @@ enum NotificationType
dontSendNotification = 0, /**< No notification message should be sent. */
sendNotification = 1, /**< Requests a notification message, either synchronous or not. */
sendNotificationSync, /**< Requests a synchronous notification. */
sendNotificationAsync, /**< Requests a asynchronous notification. */
sendNotificationAsync, /**< Requests an asynchronous notification. */
};


+ 9
- 8
libs/juce/source/modules/juce_graphics/geometry/juce_Point.h View File

@@ -151,7 +151,8 @@ public:
*/
FloatType getAngleToPoint (Point other) const noexcept
{
return static_cast<FloatType> (std::atan2 (other.x - x, y - other.y));
return static_cast<FloatType> (std::atan2 (static_cast<FloatType> (other.x - x),
static_cast<FloatType> (y - other.y)));
}
/** Returns the point that would be reached by rotating this point clockwise
@@ -169,8 +170,8 @@ public:
*/
Point<FloatType> getPointOnCircumference (float radius, float angle) const noexcept
{
return Point<FloatType> (static_cast <FloatType> (x + radius * std::sin (angle)),
static_cast <FloatType> (y - radius * std::cos (angle)));
return Point<FloatType> (static_cast<FloatType> (x + radius * std::sin (angle)),
static_cast<FloatType> (y - radius * std::cos (angle)));
}
/** Taking this point to be the centre of an ellipse, this returns a point on its circumference.
@@ -180,8 +181,8 @@ public:
*/
Point<FloatType> getPointOnCircumference (float radiusX, float radiusY, float angle) const noexcept
{
return Point<FloatType> (static_cast <FloatType> (x + radiusX * std::sin (angle)),
static_cast <FloatType> (y - radiusY * std::cos (angle)));
return Point<FloatType> (static_cast<FloatType> (x + radiusX * std::sin (angle)),
static_cast<FloatType> (y - radiusY * std::cos (angle)));
}
/** Returns the dot-product of two points (x1 * x2 + y1 * y2). */
@@ -204,13 +205,13 @@ public:
//==============================================================================
/** Casts this point to a Point<int> object. */
Point<int> toInt() const noexcept { return Point<int> (static_cast <int> (x), static_cast<int> (y)); }
Point<int> toInt() const noexcept { return Point<int> (static_cast<int> (x), static_cast<int> (y)); }
/** Casts this point to a Point<float> object. */
Point<float> toFloat() const noexcept { return Point<float> (static_cast <float> (x), static_cast<float> (y)); }
Point<float> toFloat() const noexcept { return Point<float> (static_cast<float> (x), static_cast<float> (y)); }
/** Casts this point to a Point<double> object. */
Point<double> toDouble() const noexcept { return Point<double> (static_cast <double> (x), static_cast<double> (y)); }
Point<double> toDouble() const noexcept { return Point<double> (static_cast<double> (x), static_cast<double> (y)); }
/** Returns the point as a string in the form "x, y". */
String toString() const { return String (x) + ", " + String (y); }


+ 10
- 0
libs/juce/source/modules/juce_graphics/geometry/juce_Rectangle.h View File

@@ -174,6 +174,12 @@ public:
/** Changes the rectangle's height */
inline void setHeight (const ValueType newHeight) noexcept { h = newHeight; }
/** Changes the position of the rectangle's centre (leaving its size unchanged). */
inline void setCentre (const ValueType newCentreX, const ValueType newCentreY) noexcept { pos.x = newCentreX - w / (ValueType) 2; pos.y = newCentreY - h / (ValueType) 2; }
/** Changes the position of the rectangle's centre (leaving its size unchanged). */
inline void setCentre (const Point<ValueType> newCentre) noexcept { setCentre (newCentre.x, newCentre.y); }
/** Returns a rectangle which has the same size and y-position as this one, but with a different x-position. */
Rectangle withX (const ValueType newX) const noexcept { return Rectangle (newX, pos.y, w, h); }
@@ -189,6 +195,10 @@ public:
/** Returns a rectangle whose size is the same as this one, but whose top-left position is (0, 0). */
Rectangle withZeroOrigin() const noexcept { return Rectangle (w, h); }
/** Returns a rectangle with the same size as this one, but a new centre position. */
Rectangle withCentre (const Point<ValueType> newCentre) const noexcept { return Rectangle (newCentre.x - w / (ValueType) 2,
newCentre.y - h / (ValueType) 2, w, h); }
/** Returns a rectangle which has the same position and height as this one, but with a different width. */
Rectangle withWidth (ValueType newWidth) const noexcept { return Rectangle (pos.x, pos.y, newWidth, h); }


+ 14
- 1
libs/juce/source/modules/juce_graphics/images/juce_Image.cpp View File

@@ -31,6 +31,12 @@ ImagePixelData::ImagePixelData (const Image::PixelFormat format, const int w, co
ImagePixelData::~ImagePixelData()
{
listeners.call (&Listener::imageDataBeingDeleted, this);
}
void ImagePixelData::sendDataChangeMessage()
{
listeners.call (&Listener::imageDataChanged, this);
}
//==============================================================================
@@ -69,15 +75,19 @@ public:
LowLevelGraphicsContext* createLowLevelContext() override
{
sendDataChangeMessage();
return new LowLevelGraphicsSoftwareRenderer (Image (this));
}
void initialiseBitmapData (Image::BitmapData& bitmap, int x, int y, Image::BitmapData::ReadWriteMode) override
void initialiseBitmapData (Image::BitmapData& bitmap, int x, int y, Image::BitmapData::ReadWriteMode mode) override
{
bitmap.data = imageData + x * pixelStride + y * lineStride;
bitmap.pixelFormat = pixelFormat;
bitmap.lineStride = lineStride;
bitmap.pixelStride = pixelStride;
if (mode != Image::BitmapData::readOnly)
sendDataChangeMessage();
}
ImagePixelData* clone() override
@@ -146,6 +156,9 @@ public:
void initialiseBitmapData (Image::BitmapData& bitmap, int x, int y, Image::BitmapData::ReadWriteMode mode) override
{
image->initialiseBitmapData (bitmap, x + area.getX(), y + area.getY(), mode);
if (mode != Image::BitmapData::readOnly)
sendDataChangeMessage();
}
ImagePixelData* clone() override


+ 13
- 0
libs/juce/source/modules/juce_graphics/images/juce_Image.h View File

@@ -455,6 +455,19 @@ public:
typedef ReferenceCountedObjectPtr<ImagePixelData> Ptr;
//==============================================================================
struct Listener
{
virtual ~Listener() {}
virtual void imageDataChanged (ImagePixelData*) = 0;
virtual void imageDataBeingDeleted (ImagePixelData*) = 0;
};
ListenerList<Listener> listeners;
void sendDataChangeMessage();
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ImagePixelData)
};


+ 1
- 1
libs/juce/source/modules/juce_graphics/juce_module_info View File

@@ -1,7 +1,7 @@
{
"id": "juce_graphics",
"name": "JUCE graphics classes",
"version": "3.0.2",
"version": "3.0.4",
"description": "Classes for 2D vector graphics, image loading/saving, font handling, etc.",
"website": "http://www.juce.com/juce",
"license": "GPL/Commercial",


+ 5
- 1
libs/juce/source/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm View File

@@ -52,15 +52,19 @@ public:
LowLevelGraphicsContext* createLowLevelContext() override
{
sendDataChangeMessage();
return new CoreGraphicsContext (context, height, 1.0f);
}
void initialiseBitmapData (Image::BitmapData& bitmap, int x, int y, Image::BitmapData::ReadWriteMode) override
void initialiseBitmapData (Image::BitmapData& bitmap, int x, int y, Image::BitmapData::ReadWriteMode mode) override
{
bitmap.data = imageData + x * pixelStride + y * lineStride;
bitmap.pixelFormat = pixelFormat;
bitmap.lineStride = lineStride;
bitmap.pixelStride = pixelStride;
if (mode != Image::BitmapData::readOnly)
sendDataChangeMessage();
}
ImagePixelData* clone() override


+ 5
- 0
libs/juce/source/modules/juce_graphics/native/juce_mac_Fonts.mm View File

@@ -1230,7 +1230,12 @@ Typeface::Ptr Typeface::createSystemTypefaceFor (const Font& font)
Typeface::Ptr Typeface::createSystemTypefaceFor (const void* data, size_t dataSize)
{
#if JUCE_CORETEXT_AVAILABLE
return new OSXTypeface (data, dataSize);
#else
jassertfalse; // You need CoreText enabled to use this feature!
return nullptr;
#endif
}
void Typeface::scanFolderForFonts (const File&)


+ 1
- 1
libs/juce/source/modules/juce_gui_basics/commands/juce_ApplicationCommandManager.h View File

@@ -290,7 +290,7 @@ public:
static ApplicationCommandTarget* findDefaultComponentTarget();
/** Examines this component and all its parents in turn, looking for the first one
which is a ApplicationCommandTarget.
which is an ApplicationCommandTarget.
Returns the first ApplicationCommandTarget that it finds, or nullptr if none of them
implement that class.


+ 1
- 1
libs/juce/source/modules/juce_gui_basics/commands/juce_KeyPressMappingSet.h View File

@@ -29,7 +29,7 @@
//==============================================================================
/**
Manages and edits a list of keypresses, which it uses to invoke the appropriate
command in a ApplicationCommandManager.
command in an ApplicationCommandManager.
Normally, you won't actually create a KeyPressMappingSet directly, because
each ApplicationCommandManager contains its own KeyPressMappingSet, so typically


+ 2
- 2
libs/juce/source/modules/juce_gui_basics/components/juce_Component.h View File

@@ -326,12 +326,12 @@ public:
void getVisibleArea (RectangleList<int>& result, bool includeSiblings) const;
//==============================================================================
/** Returns this component's x coordinate relative the the screen's top-left origin.
/** Returns this component's x coordinate relative the screen's top-left origin.
@see getX, localPointToGlobal
*/
int getScreenX() const;
/** Returns this component's y coordinate relative the the screen's top-left origin.
/** Returns this component's y coordinate relative the screen's top-left origin.
@see getY, localPointToGlobal
*/
int getScreenY() const;


+ 1
- 1
libs/juce/source/modules/juce_gui_basics/juce_module_info View File

@@ -1,7 +1,7 @@
{
"id": "juce_gui_basics",
"name": "JUCE GUI core classes",
"version": "3.0.2",
"version": "3.0.4",
"description": "Basic user-interface components and related classes.",
"website": "http://www.juce.com/juce",
"license": "GPL/Commercial",


+ 10
- 9
libs/juce/source/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.cpp View File

@@ -104,6 +104,9 @@ LookAndFeel_V2::LookAndFeel_V2()
ComboBox::backgroundColourId, 0xffffffff,
ComboBox::arrowColourId, 0x99000000,
PropertyComponent::backgroundColourId, 0x66ffffff,
PropertyComponent::labelTextColourId, 0xff000000,
TextPropertyComponent::backgroundColourId, 0xffffffff,
TextPropertyComponent::textColourId, 0xff000000,
TextPropertyComponent::outlineColourId, standardOutlineColour,
@@ -1456,6 +1459,8 @@ Label* LookAndFeel_V2::createSliderTextBox (Slider& slider)
l->setColour (TextEditor::outlineColourId, slider.findColour (Slider::textBoxOutlineColourId));
l->setColour (TextEditor::highlightColourId, slider.findColour (Slider::textBoxHighlightColourId));
return l;
}
@@ -2302,20 +2307,16 @@ void LookAndFeel_V2::drawPropertyPanelSectionHeader (Graphics& g, const String&
g.drawText (name, textX, 0, width - textX - 4, height, Justification::centredLeft, true);
}
void LookAndFeel_V2::drawPropertyComponentBackground (Graphics& g, int width, int height,
PropertyComponent&)
void LookAndFeel_V2::drawPropertyComponentBackground (Graphics& g, int width, int height, PropertyComponent& component)
{
g.setColour (Colour (0x66ffffff));
g.setColour (component.findColour (PropertyComponent::backgroundColourId));
g.fillRect (0, 0, width, height - 1);
}
void LookAndFeel_V2::drawPropertyComponentLabel (Graphics& g, int, int height,
PropertyComponent& component)
void LookAndFeel_V2::drawPropertyComponentLabel (Graphics& g, int, int height, PropertyComponent& component)
{
g.setColour (Colours::black);
if (! component.isEnabled())
g.setOpacity (0.6f);
g.setColour (component.findColour (PropertyComponent::labelTextColourId)
.withMultipliedAlpha (component.isEnabled() ? 1.0f : 0.6f));
g.setFont (jmin (height, 24) * 0.65f);


+ 5
- 1
libs/juce/source/modules/juce_gui_basics/native/juce_linux_Windowing.cpp View File

@@ -617,15 +617,19 @@ public:
LowLevelGraphicsContext* createLowLevelContext() override
{
sendDataChangeMessage();
return new LowLevelGraphicsSoftwareRenderer (Image (this));
}
void initialiseBitmapData (Image::BitmapData& bitmap, int x, int y, Image::BitmapData::ReadWriteMode) override
void initialiseBitmapData (Image::BitmapData& bitmap, int x, int y, Image::BitmapData::ReadWriteMode mode) override
{
bitmap.data = imageData + x * pixelStride + y * lineStride;
bitmap.pixelFormat = pixelFormat;
bitmap.lineStride = lineStride;
bitmap.pixelStride = pixelStride;
if (mode != Image::BitmapData::readOnly)
sendDataChangeMessage();
}
ImagePixelData* clone() override


+ 30
- 14
libs/juce/source/modules/juce_gui_basics/native/juce_win32_Windowing.cpp View File

@@ -328,15 +328,19 @@ public:
LowLevelGraphicsContext* createLowLevelContext() override
{
sendDataChangeMessage();
return new LowLevelGraphicsSoftwareRenderer (Image (this));
}
void initialiseBitmapData (Image::BitmapData& bitmap, int x, int y, Image::BitmapData::ReadWriteMode) override
void initialiseBitmapData (Image::BitmapData& bitmap, int x, int y, Image::BitmapData::ReadWriteMode mode) override
{
bitmap.data = imageData + x * pixelStride + y * lineStride;
bitmap.pixelFormat = pixelFormat;
bitmap.lineStride = lineStride;
bitmap.pixelStride = pixelStride;
if (mode != Image::BitmapData::readOnly)
sendDataChangeMessage();
}
ImagePixelData* clone() override
@@ -3177,10 +3181,22 @@ void Desktop::setKioskComponent (Component* kioskModeComponent, bool enableOrDis
}
//==============================================================================
static BOOL CALLBACK enumMonitorsProc (HMONITOR, HDC, LPRECT r, LPARAM userInfo)
struct MonitorInfo
{
MonitorInfo (Rectangle<int> rect, bool main) noexcept : isMain (main), bounds (rect) {}
Rectangle<int> bounds;
bool isMain;
};
static BOOL CALLBACK enumMonitorsProc (HMONITOR hm, HDC, LPRECT r, LPARAM userInfo)
{
Array <Rectangle<int> >* const monitorCoords = (Array <Rectangle<int> >*) userInfo;
monitorCoords->add (rectangleFromRECT (*r));
MONITORINFO info = { 0 };
info.cbSize = sizeof (info);
GetMonitorInfo (hm, &info);
const bool isMain = (info.dwFlags & 1 /* MONITORINFOF_PRIMARY */) != 0;
((Array<MonitorInfo>*) userInfo)->add (MonitorInfo (rectangleFromRECT (*r), isMain));
return TRUE;
}
@@ -3188,17 +3204,17 @@ void Desktop::Displays::findDisplays (float masterScale)
{
setDPIAwareness();
Array <Rectangle<int> > monitors;
Array<MonitorInfo> monitors;
EnumDisplayMonitors (0, 0, &enumMonitorsProc, (LPARAM) &monitors);
if (monitors.size() == 0)
monitors.add (MonitorInfo (rectangleFromRECT (getWindowRect (GetDesktopWindow())), true));
// make sure the first in the list is the main monitor
for (int i = 1; i < monitors.size(); ++i)
if (monitors.getReference(i).getPosition().isOrigin())
if (monitors.getReference(i).isMain)
monitors.swap (i, 0);
if (monitors.size() == 0)
monitors.add (rectangleFromRECT (getWindowRect (GetDesktopWindow())));
RECT workArea;
SystemParametersInfo (SPI_GETWORKAREA, 0, &workArea, 0);
@@ -3207,12 +3223,12 @@ void Desktop::Displays::findDisplays (float masterScale)
for (int i = 0; i < monitors.size(); ++i)
{
Display d;
d.userArea = d.totalArea = monitors.getReference(i) / masterScale;
d.isMain = (i == 0);
d.scale = masterScale;
d.dpi = dpi;
d.userArea = d.totalArea = monitors.getReference(i).bounds / masterScale;
d.isMain = monitors.getReference(i).isMain;
d.scale = masterScale;
d.dpi = dpi;
if (i == 0)
if (d.isMain)
d.userArea = d.userArea.getIntersection (rectangleFromRECT (workArea) / masterScale);
displays.add (d);


+ 16
- 0
libs/juce/source/modules/juce_gui_basics/properties/juce_PropertyComponent.h View File

@@ -102,6 +102,22 @@ public:
/** By default, this just repaints the component. */
void enablementChanged() override;
//==============================================================================
/** A set of colour IDs to use to change the colour of various aspects of the combo box.
These constants can be used either via the Component::setColour(), or LookAndFeel::setColour()
methods.
To change the colours of the menu that pops up
@see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
*/
enum ColourIds
{
backgroundColourId = 0x1008300, /**< The background colour to fill the component with. */
labelTextColourId = 0x1008301, /**< The colour for the property's label text. */
};
//==============================================================================
/** This abstract base class is implemented by LookAndFeel classes. */
struct JUCE_API LookAndFeelMethods


+ 15
- 7
libs/juce/source/modules/juce_gui_basics/widgets/juce_Slider.cpp View File

@@ -375,7 +375,7 @@ public:
const double delta = (button == incButton) ? interval : -interval;
DragInProgress drag (*this);
setValue (owner.snapValue (getValue() + delta, false), sendNotificationSync);
setValue (owner.snapValue (getValue() + delta, notDragging), sendNotificationSync);
}
}
@@ -394,7 +394,7 @@ public:
void labelTextChanged (Label* label) override
{
const double newValue = owner.snapValue (owner.getValueFromText (label->getText()), false);
const double newValue = owner.snapValue (owner.getValueFromText (label->getText()), notDragging);
if (newValue != (double) currentValue.getValue())
{
@@ -873,6 +873,8 @@ public:
&& ! ((style == LinearBar || style == LinearBarVertical)
&& e.mouseWasClicked() && valueBox != nullptr && valueBox->isEditable()))
{
DragMode dragMode = notDragging;
if (style == Rotary)
{
handleRotaryDrag (e);
@@ -889,21 +891,27 @@ public:
}
if (isAbsoluteDragMode (e.mods) || (maximum - minimum) / sliderRegionSize < interval)
{
dragMode = notDragging;
handleAbsoluteDrag (e);
}
else
{
dragMode = velocityDrag;
handleVelocityDrag (e);
}
}
valueWhenLastDragged = jlimit (minimum, maximum, valueWhenLastDragged);
if (sliderBeingDragged == 0)
{
setValue (owner.snapValue (valueWhenLastDragged, true),
setValue (owner.snapValue (valueWhenLastDragged, dragMode),
sendChangeOnlyOnRelease ? dontSendNotification : sendNotificationSync);
}
else if (sliderBeingDragged == 1)
{
setMinValue (owner.snapValue (valueWhenLastDragged, true),
setMinValue (owner.snapValue (valueWhenLastDragged, dragMode),
sendChangeOnlyOnRelease ? dontSendNotification : sendNotificationAsync, true);
if (e.mods.isShiftDown())
@@ -913,7 +921,7 @@ public:
}
else if (sliderBeingDragged == 2)
{
setMaxValue (owner.snapValue (valueWhenLastDragged, true),
setMaxValue (owner.snapValue (valueWhenLastDragged, dragMode),
sendChangeOnlyOnRelease ? dontSendNotification : sendNotificationAsync, true);
if (e.mods.isShiftDown())
@@ -994,7 +1002,7 @@ public:
delta = -delta;
DragInProgress drag (*this);
setValue (owner.snapValue (value + delta, false), sendNotificationSync);
setValue (owner.snapValue (value + delta, notDragging), sendNotificationSync);
}
return true;
@@ -1534,7 +1542,7 @@ double Slider::valueToProportionOfLength (double value)
return skew == 1.0 ? n : pow (n, skew);
}
double Slider::snapValue (double attemptedValue, const bool)
double Slider::snapValue (double attemptedValue, DragMode)
{
return attemptedValue;
}


+ 18
- 6
libs/juce/source/modules/juce_gui_basics/widgets/juce_Slider.h View File

@@ -97,6 +97,16 @@ public:
TextBoxBelow /**< Puts the text box below the slider, horizontally centred. */
};
/** Describes the type of mouse-dragging that is happening when a value is being changed.
@see snapValue
*/
enum DragMode
{
notDragging, /**< Dragging is not active. */
absoluteDrag, /**< The dragging corresponds directly to the value that is displayed. */
velocityDrag /**< The dragging value change is relative to the velocity of the mouse mouvement. */
};
//==============================================================================
/** Creates a slider.
When created, you can set up the slider's style and range with setSliderStyle(), setRange(), etc.
@@ -157,7 +167,7 @@ public:
int getMouseDragSensitivity() const noexcept;
//==============================================================================
/** Changes the way the the mouse is used when dragging the slider.
/** Changes the way the mouse is used when dragging the slider.
If true, this will turn on velocity-sensitive dragging, so that
the faster the mouse moves, the bigger the movement to the slider. This
@@ -720,12 +730,13 @@ public:
a given position, and allows a subclass to sanity-check this value, possibly
returning a different value to use instead.
@param attemptedValue the value the user is trying to enter
@param userIsDragging true if the user is dragging with the mouse; false if
they are entering the value using the text box
@returns the value to use instead
@param attemptedValue the value the user is trying to enter
@param dragMode indicates whether the user is dragging with
the mouse; notDragging if they are entering the value
using the text box or other non-dragging interaction
@returns the value to use instead
*/
virtual double snapValue (double attemptedValue, bool userIsDragging);
virtual double snapValue (double attemptedValue, DragMode dragMode);
//==============================================================================
@@ -874,6 +885,7 @@ private:
JUCE_DEPRECATED (void setMaxValue (double, bool));
JUCE_DEPRECATED (void setMinAndMaxValues (double, double, bool, bool));
JUCE_DEPRECATED (void setMinAndMaxValues (double, double, bool));
virtual void snapValue (double, bool) {}
#endif
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Slider)


+ 6
- 5
libs/juce/source/modules/juce_gui_basics/widgets/juce_TreeView.cpp View File

@@ -560,7 +560,7 @@ Viewport* TreeView::getViewport() const noexcept
void TreeView::clearSelectedItems()
{
if (rootItem != nullptr)
rootItem->deselectAllRecursively();
rootItem->deselectAllRecursively (nullptr);
}
int TreeView::getNumSelectedItems (int maximumDepthToSearchTo) const noexcept
@@ -1299,12 +1299,13 @@ bool TreeViewItem::isSelected() const noexcept
return selected;
}
void TreeViewItem::deselectAllRecursively()
void TreeViewItem::deselectAllRecursively (TreeViewItem* itemToIgnore)
{
setSelected (false, false);
if (this != itemToIgnore)
setSelected (false, false);
for (int i = 0; i < subItems.size(); ++i)
subItems.getUnchecked(i)->deselectAllRecursively();
subItems.getUnchecked(i)->deselectAllRecursively (itemToIgnore);
}
void TreeViewItem::setSelected (const bool shouldBeSelected,
@@ -1315,7 +1316,7 @@ void TreeViewItem::setSelected (const bool shouldBeSelected,
return;
if (deselectOtherItemsFirst)
getTopLevelItem()->deselectAllRecursively();
getTopLevelItem()->deselectAllRecursively (this);
if (shouldBeSelected != selected)
{


+ 1
- 1
libs/juce/source/modules/juce_gui_basics/widgets/juce_TreeView.h View File

@@ -557,7 +557,7 @@ private:
TreeViewItem* getDeepestOpenParentItem() noexcept;
int getNumRows() const noexcept;
TreeViewItem* getItemOnRow (int index) noexcept;
void deselectAllRecursively();
void deselectAllRecursively (TreeViewItem* itemToIgnore);
int countSelectedItemsRecursively (int depth) const noexcept;
TreeViewItem* getSelectedItemWithIndex (int index) noexcept;
TreeViewItem* getNextVisibleItem (bool recurse) const noexcept;


+ 9
- 4
libs/juce/source/modules/juce_gui_basics/windows/juce_CallOutBox.cpp View File

@@ -48,8 +48,6 @@ CallOutBox::~CallOutBox()
{
}
enum { callOutBoxDismissCommandId = 0x4f83a04b };
//==============================================================================
class CallOutBoxCallback : public ModalComponentManager::Callback,
private Timer
@@ -68,7 +66,7 @@ public:
void timerCallback() override
{
if (! Process::isForegroundProcess())
callout.postCommandMessage (callOutBoxDismissCommandId);
callout.dismiss();
}
ScopedPointer<Component> content;
@@ -127,7 +125,7 @@ void CallOutBox::inputAttemptWhenModal()
// if you click on the area that originally popped-up the callout, you expect it
// to get rid of the box, but deleting the box here allows the click to pass through and
// probably re-trigger it, so we need to dismiss the box asynchronously to consume the click..
postCommandMessage (callOutBoxDismissCommandId);
dismiss();
}
else
{
@@ -136,6 +134,8 @@ void CallOutBox::inputAttemptWhenModal()
}
}
enum { callOutBoxDismissCommandId = 0x4f83a04b };
void CallOutBox::handleCommandMessage (int commandId)
{
Component::handleCommandMessage (commandId);
@@ -147,6 +147,11 @@ void CallOutBox::handleCommandMessage (int commandId)
}
}
void CallOutBox::dismiss()
{
postCommandMessage (callOutBoxDismissCommandId);
}
bool CallOutBox::keyPressed (const KeyPress& key)
{
if (key.isKeyCode (KeyPress::escapeKey))


+ 5
- 0
libs/juce/source/modules/juce_gui_basics/windows/juce_CallOutBox.h View File

@@ -118,6 +118,11 @@ public:
const Rectangle<int>& areaToPointTo,
Component* parentComponent);
/** Posts a message which will dismiss the callout box asynchronously.
NB: it's safe to call this method from any thread.
*/
void dismiss();
//==============================================================================
/** This abstract base class is implemented by LookAndFeel classes. */
struct JUCE_API LookAndFeelMethods


+ 1
- 1
libs/juce/source/modules/juce_gui_basics/windows/juce_ComponentPeer.h View File

@@ -102,7 +102,7 @@ public:
/** Returns the raw handle to whatever kind of window is being used.
On windows, this is probably a HWND, on the mac, it's likely to be a WindowRef,
but rememeber there's no guarantees what you'll get back.
but remember there's no guarantees what you'll get back.
*/
virtual void* getNativeHandle() const = 0;


+ 33
- 21
libs/juce/source/modules/juce_gui_basics/windows/juce_ThreadWithProgressWindow.cpp View File

@@ -25,12 +25,13 @@
ThreadWithProgressWindow::ThreadWithProgressWindow (const String& title,
const bool hasProgressBar,
const bool hasCancelButton,
const int timeOutMsWhenCancelling_,
const int cancellingTimeOutMs,
const String& cancelButtonText,
Component* componentToCentreAround)
: Thread ("Juce Progress Window"),
progress (0.0),
timeOutMsWhenCancelling (timeOutMsWhenCancelling_)
: Thread ("ThreadWithProgressWindow"),
progress (0.0),
timeOutMsWhenCancelling (cancellingTimeOutMs),
wasCancelledByUser (false)
{
alertWindow = LookAndFeel::getDefaultLookAndFeel()
.createAlertWindow (title, String(),
@@ -52,8 +53,7 @@ ThreadWithProgressWindow::~ThreadWithProgressWindow()
stopThread (timeOutMsWhenCancelling);
}
#if JUCE_MODAL_LOOPS_PERMITTED
bool ThreadWithProgressWindow::runThread (const int priority)
void ThreadWithProgressWindow::launchThread (int priority)
{
jassert (MessageManager::getInstance()->isThisTheMessageThread());
@@ -65,15 +65,8 @@ bool ThreadWithProgressWindow::runThread (const int priority)
alertWindow->setMessage (message);
}
const bool finishedNaturally = alertWindow->runModalLoop() != 0;
stopThread (timeOutMsWhenCancelling);
alertWindow->setVisible (false);
return finishedNaturally;
alertWindow->enterModalState();
}
#endif
void ThreadWithProgressWindow::setProgress (const double newProgress)
{
@@ -88,15 +81,34 @@ void ThreadWithProgressWindow::setStatusMessage (const String& newStatusMessage)
void ThreadWithProgressWindow::timerCallback()
{
if (! isThreadRunning())
bool threadStillRunning = isThreadRunning();
if (! (threadStillRunning && alertWindow->isCurrentlyModal()))
{
// thread has finished normally..
stopTimer();
stopThread (timeOutMsWhenCancelling);
alertWindow->exitModalState (1);
alertWindow->setVisible (false);
wasCancelledByUser = threadStillRunning;
threadComplete (threadStillRunning);
return; // (this may be deleted now)
}
else
{
const ScopedLock sl (messageLock);
alertWindow->setMessage (message);
}
const ScopedLock sl (messageLock);
alertWindow->setMessage (message);
}
void ThreadWithProgressWindow::threadComplete (bool) {}
#if JUCE_MODAL_LOOPS_PERMITTED
bool ThreadWithProgressWindow::runThread (const int priority)
{
launchThread (priority);
while (isTimerRunning())
MessageManager::getInstance()->runDispatchLoopUntil (5);
return ! wasCancelledByUser;
}
#endif

+ 21
- 1
libs/juce/source/modules/juce_gui_basics/windows/juce_ThreadWithProgressWindow.h View File

@@ -111,6 +111,7 @@ public:
~ThreadWithProgressWindow();
//==============================================================================
#if JUCE_MODAL_LOOPS_PERMITTED
/** Starts the thread and waits for it to finish.
This will start the thread, make the dialog box appear, and wait until either
@@ -123,6 +124,18 @@ public:
@returns true if the thread finished normally; false if the user pressed cancel
*/
bool runThread (int threadPriority = 5);
#endif
/** Starts the thread and returns.
This will start the thread and make the dialog box appear in a modal state. When
the thread finishes normally, or the cancel button is pressed, the window will be
hidden and the threadComplete() method will be called.
@param threadPriority the priority to use when starting the thread - see
Thread::startThread() for values
*/
void launchThread (int threadPriority = 5);
/** The thread should call this periodically to update the position of the progress bar.
@@ -137,15 +150,22 @@ public:
/** Returns the AlertWindow that is being used. */
AlertWindow* getAlertWindow() const noexcept { return alertWindow; }
//==============================================================================
/** This method is called (on the message thread) when the operation has finished.
You may choose to use this callback to delete the ThreadWithProgressWindow object.
*/
virtual void threadComplete (bool userPressedCancel);
private:
//==============================================================================
void timerCallback() override;
double progress;
ScopedPointer <AlertWindow> alertWindow;
ScopedPointer<AlertWindow> alertWindow;
String message;
CriticalSection messageLock;
const int timeOutMsWhenCancelling;
bool wasCancelledByUser;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ThreadWithProgressWindow)
};


+ 1
- 1
libs/juce/source/modules/juce_gui_extra/juce_module_info View File

@@ -1,7 +1,7 @@
{
"id": "juce_gui_extra",
"name": "JUCE extended GUI classes",
"version": "3.0.2",
"version": "3.0.4",
"description": "Miscellaneous GUI classes for specialised tasks.",
"website": "http://www.juce.com/juce",
"license": "GPL/Commercial",


Loading…
Cancel
Save