@@ -13,32 +13,38 @@ | |||||
//============================================================================== | //============================================================================== | ||||
JuceDemoPluginAudioProcessorEditor::JuceDemoPluginAudioProcessorEditor (JuceDemoPluginAudioProcessor* ownerFilter) | JuceDemoPluginAudioProcessorEditor::JuceDemoPluginAudioProcessorEditor (JuceDemoPluginAudioProcessor* ownerFilter) | ||||
: AudioProcessorEditor (ownerFilter) | |||||
: AudioProcessorEditor (ownerFilter), | |||||
midiKeyboard (ownerFilter->keyboardState, MidiKeyboardComponent::horizontalKeyboard), | |||||
infoLabel (String::empty), | |||||
gainLabel ("", "Throughput level:"), | |||||
delayLabel ("", "Delay:"), | |||||
gainSlider ("gain"), | |||||
delaySlider ("delay") | |||||
{ | { | ||||
addAndMakeVisible (gainSlider = new Slider ("gain")); | |||||
gainSlider->setSliderStyle (Slider::Rotary); | |||||
gainSlider->addListener (this); | |||||
gainSlider->setRange (0.0, 1.0, 0.01); | |||||
Label* l = new Label ("", "Throughput level:"); | |||||
l->attachToComponent (gainSlider, false); | |||||
l->setFont (Font (11.0f)); | |||||
addAndMakeVisible (delaySlider = new Slider ("delay")); | |||||
delaySlider->setSliderStyle (Slider::Rotary); | |||||
delaySlider->addListener (this); | |||||
delaySlider->setRange (0.0, 1.0, 0.01); | |||||
l = new Label ("", "Delay:"); | |||||
l->attachToComponent (delaySlider, false); | |||||
l->setFont (Font (11.0f)); | |||||
// create and add the midi keyboard component.. | |||||
addAndMakeVisible (midiKeyboard | |||||
= new MidiKeyboardComponent (ownerFilter->keyboardState, | |||||
MidiKeyboardComponent::horizontalKeyboard)); | |||||
// add some sliders.. | |||||
addAndMakeVisible (&gainSlider); | |||||
gainSlider.setSliderStyle (Slider::Rotary); | |||||
gainSlider.addListener (this); | |||||
gainSlider.setRange (0.0, 1.0, 0.01); | |||||
addAndMakeVisible (&delaySlider); | |||||
delaySlider.setSliderStyle (Slider::Rotary); | |||||
delaySlider.addListener (this); | |||||
delaySlider.setRange (0.0, 1.0, 0.01); | |||||
// add some labels for the sliders.. | |||||
gainLabel.attachToComponent (&gainSlider, false); | |||||
gainLabel.setFont (Font (11.0f)); | |||||
delayLabel.attachToComponent (&delaySlider, false); | |||||
delayLabel.setFont (Font (11.0f)); | |||||
// add the midi keyboard component.. | |||||
addAndMakeVisible (&midiKeyboard); | |||||
// add a label that will display the current timecode and status.. | // add a label that will display the current timecode and status.. | ||||
addAndMakeVisible (infoLabel = new Label (String::empty, String::empty)); | |||||
infoLabel->setColour (Label::textColourId, Colours::blue); | |||||
addAndMakeVisible (&infoLabel); | |||||
infoLabel.setColour (Label::textColourId, Colours::blue); | |||||
// add the triangular resizer component for the bottom-right of the UI | // add the triangular resizer component for the bottom-right of the UI | ||||
addAndMakeVisible (resizer = new ResizableCornerComponent (this, &resizeLimits)); | addAndMakeVisible (resizer = new ResizableCornerComponent (this, &resizeLimits)); | ||||
@@ -53,7 +59,6 @@ JuceDemoPluginAudioProcessorEditor::JuceDemoPluginAudioProcessorEditor (JuceDemo | |||||
JuceDemoPluginAudioProcessorEditor::~JuceDemoPluginAudioProcessorEditor() | JuceDemoPluginAudioProcessorEditor::~JuceDemoPluginAudioProcessorEditor() | ||||
{ | { | ||||
deleteAllChildren(); | |||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
@@ -65,12 +70,12 @@ void JuceDemoPluginAudioProcessorEditor::paint (Graphics& g) | |||||
void JuceDemoPluginAudioProcessorEditor::resized() | void JuceDemoPluginAudioProcessorEditor::resized() | ||||
{ | { | ||||
infoLabel->setBounds (10, 4, 400, 25); | |||||
gainSlider->setBounds (20, 60, 150, 40); | |||||
delaySlider->setBounds (200, 60, 150, 40); | |||||
infoLabel.setBounds (10, 4, 400, 25); | |||||
gainSlider.setBounds (20, 60, 150, 40); | |||||
delaySlider.setBounds (200, 60, 150, 40); | |||||
const int keyboardHeight = 70; | const int keyboardHeight = 70; | ||||
midiKeyboard->setBounds (4, getHeight() - keyboardHeight - 4, getWidth() - 8, keyboardHeight); | |||||
midiKeyboard.setBounds (4, getHeight() - keyboardHeight - 4, getWidth() - 8, keyboardHeight); | |||||
resizer->setBounds (getWidth() - 16, getHeight() - 16, 16, 16); | resizer->setBounds (getWidth() - 16, getHeight() - 16, 16, 16); | ||||
@@ -89,25 +94,25 @@ void JuceDemoPluginAudioProcessorEditor::timerCallback() | |||||
if (lastDisplayedPosition != newPos) | if (lastDisplayedPosition != newPos) | ||||
displayPositionInfo (newPos); | displayPositionInfo (newPos); | ||||
gainSlider->setValue (ourProcessor->gain, false); | |||||
delaySlider->setValue (ourProcessor->delay, false); | |||||
gainSlider.setValue (ourProcessor->gain, false); | |||||
delaySlider.setValue (ourProcessor->delay, false); | |||||
} | } | ||||
// This is our Slider::Listener callback, when the user drags a slider. | // This is our Slider::Listener callback, when the user drags a slider. | ||||
void JuceDemoPluginAudioProcessorEditor::sliderValueChanged (Slider* slider) | void JuceDemoPluginAudioProcessorEditor::sliderValueChanged (Slider* slider) | ||||
{ | { | ||||
if (slider == gainSlider) | |||||
if (slider == &gainSlider) | |||||
{ | { | ||||
// It's vital to use setParameterNotifyingHost to change any parameters that are automatable | // It's vital to use setParameterNotifyingHost to change any parameters that are automatable | ||||
// by the host, rather than just modifying them directly, otherwise the host won't know | // by the host, rather than just modifying them directly, otherwise the host won't know | ||||
// that they've changed. | // that they've changed. | ||||
getProcessor()->setParameterNotifyingHost (JuceDemoPluginAudioProcessor::gainParam, | getProcessor()->setParameterNotifyingHost (JuceDemoPluginAudioProcessor::gainParam, | ||||
(float) gainSlider->getValue()); | |||||
(float) gainSlider.getValue()); | |||||
} | } | ||||
else if (slider == delaySlider) | |||||
else if (slider == &delaySlider) | |||||
{ | { | ||||
getProcessor()->setParameterNotifyingHost (JuceDemoPluginAudioProcessor::delayParam, | getProcessor()->setParameterNotifyingHost (JuceDemoPluginAudioProcessor::delayParam, | ||||
(float) delaySlider->getValue()); | |||||
(float) delaySlider.getValue()); | |||||
} | } | ||||
} | } | ||||
@@ -169,5 +174,5 @@ void JuceDemoPluginAudioProcessorEditor::displayPositionInfo (const AudioPlayHea | |||||
else if (pos.isPlaying) | else if (pos.isPlaying) | ||||
displayText << " (playing)"; | displayText << " (playing)"; | ||||
infoLabel->setText (displayText, false); | |||||
infoLabel.setText (displayText, false); | |||||
} | } |
@@ -34,11 +34,11 @@ public: | |||||
void sliderValueChanged (Slider*); | void sliderValueChanged (Slider*); | ||||
private: | private: | ||||
MidiKeyboardComponent* midiKeyboard; | |||||
Label* infoLabel; | |||||
Slider* gainSlider; | |||||
Slider* delaySlider; | |||||
ResizableCornerComponent* resizer; | |||||
MidiKeyboardComponent midiKeyboard; | |||||
Label infoLabel, gainLabel, delayLabel; | |||||
Slider gainSlider; | |||||
Slider delaySlider; | |||||
ScopedPointer<ResizableCornerComponent> resizer; | |||||
ComponentBoundsConstrainer resizeLimits; | ComponentBoundsConstrainer resizeLimits; | ||||
AudioPlayHead::CurrentPositionInfo lastDisplayedPosition; | AudioPlayHead::CurrentPositionInfo lastDisplayedPosition; | ||||
@@ -21988,6 +21988,12 @@ struct AudioThumbnail::MinMaxValue | |||||
return maxValue > minValue; | return maxValue > minValue; | ||||
} | } | ||||
inline int getPeak() const throw() | |||||
{ | |||||
return jmax (std::abs ((int) minValue), | |||||
std::abs ((int) maxValue)); | |||||
} | |||||
inline void read (InputStream& input) | inline void read (InputStream& input) | ||||
{ | { | ||||
minValue = input.readByte(); | minValue = input.readByte(); | ||||
@@ -22186,6 +22192,7 @@ class AudioThumbnail::ThumbData | |||||
{ | { | ||||
public: | public: | ||||
ThumbData (const int numThumbSamples) | ThumbData (const int numThumbSamples) | ||||
: peakLevel (-1) | |||||
{ | { | ||||
ensureSize (numThumbSamples); | ensureSize (numThumbSamples); | ||||
} | } | ||||
@@ -22232,6 +22239,8 @@ public: | |||||
void write (const MinMaxValue* const source, const int startIndex, const int numValues) | void write (const MinMaxValue* const source, const int startIndex, const int numValues) | ||||
{ | { | ||||
resetPeak(); | |||||
if (startIndex + numValues > data.size()) | if (startIndex + numValues > data.size()) | ||||
ensureSize (startIndex + numValues); | ensureSize (startIndex + numValues); | ||||
@@ -22241,8 +22250,29 @@ public: | |||||
dest[i] = source[i]; | dest[i] = source[i]; | ||||
} | } | ||||
void resetPeak() | |||||
{ | |||||
peakLevel = -1; | |||||
} | |||||
int getPeak() | |||||
{ | |||||
if (peakLevel < 0) | |||||
{ | |||||
for (int i = 0; i < data.size(); ++i) | |||||
{ | |||||
const int peak = data[i].getPeak(); | |||||
if (peak > peakLevel) | |||||
peakLevel = peak; | |||||
} | |||||
} | |||||
return peakLevel; | |||||
} | |||||
private: | private: | ||||
Array <MinMaxValue> data; | Array <MinMaxValue> data; | ||||
int peakLevel; | |||||
void ensureSize (const int thumbSamples) | void ensureSize (const int thumbSamples) | ||||
{ | { | ||||
@@ -22619,6 +22649,16 @@ bool AudioThumbnail::isFullyLoaded() const throw() | |||||
return numSamplesFinished >= totalSamples - samplesPerThumbSample; | return numSamplesFinished >= totalSamples - samplesPerThumbSample; | ||||
} | } | ||||
float AudioThumbnail::getApproximatePeak() const | |||||
{ | |||||
int peak = 0; | |||||
for (int i = channels.size(); --i >= 0;) | |||||
peak = jmax (peak, channels.getUnchecked(i)->getPeak()); | |||||
return jlimit (0, 127, peak) / 127.0f; | |||||
} | |||||
void AudioThumbnail::drawChannel (Graphics& g, const Rectangle<int>& area, double startTime, | void AudioThumbnail::drawChannel (Graphics& g, const Rectangle<int>& area, double startTime, | ||||
double endTime, int channelNum, float verticalZoomFactor) | double endTime, int channelNum, float verticalZoomFactor) | ||||
{ | { | ||||
@@ -36682,10 +36722,10 @@ public: | |||||
: graph (graph_), | : graph (graph_), | ||||
orderedNodes (orderedNodes_) | orderedNodes (orderedNodes_) | ||||
{ | { | ||||
nodeIds.add (zeroNodeID); // first buffer is read-only zeros | |||||
nodeIds.add ((uint32) zeroNodeID); // first buffer is read-only zeros | |||||
channels.add (0); | channels.add (0); | ||||
midiNodeIds.add (zeroNodeID); | |||||
midiNodeIds.add ((uint32) zeroNodeID); | |||||
for (int i = 0; i < orderedNodes.size(); ++i) | for (int i = 0; i < orderedNodes.size(); ++i) | ||||
{ | { | ||||
@@ -36969,7 +37009,7 @@ private: | |||||
if (midiNodeIds.getUnchecked(i) == freeNodeID) | if (midiNodeIds.getUnchecked(i) == freeNodeID) | ||||
return i; | return i; | ||||
midiNodeIds.add (freeNodeID); | |||||
midiNodeIds.add ((uint32) freeNodeID); | |||||
return midiNodeIds.size() - 1; | return midiNodeIds.size() - 1; | ||||
} | } | ||||
else | else | ||||
@@ -36978,7 +37018,7 @@ private: | |||||
if (nodeIds.getUnchecked(i) == freeNodeID) | if (nodeIds.getUnchecked(i) == freeNodeID) | ||||
return i; | return i; | ||||
nodeIds.add (freeNodeID); | |||||
nodeIds.add ((uint32) freeNodeID); | |||||
channels.add (0); | channels.add (0); | ||||
return nodeIds.size() - 1; | return nodeIds.size() - 1; | ||||
} | } | ||||
@@ -37018,7 +37058,7 @@ private: | |||||
nodeIds.getUnchecked(i), | nodeIds.getUnchecked(i), | ||||
channels.getUnchecked(i))) | channels.getUnchecked(i))) | ||||
{ | { | ||||
nodeIds.set (i, freeNodeID); | |||||
nodeIds.set (i, (uint32) freeNodeID); | |||||
} | } | ||||
} | } | ||||
@@ -37029,7 +37069,7 @@ private: | |||||
midiNodeIds.getUnchecked(i), | midiNodeIds.getUnchecked(i), | ||||
AudioProcessorGraph::midiChannelIndex)) | AudioProcessorGraph::midiChannelIndex)) | ||||
{ | { | ||||
midiNodeIds.set (i, freeNodeID); | |||||
midiNodeIds.set (i, (uint32) freeNodeID); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -40198,8 +40238,7 @@ void Component::setVisible (bool shouldBeVisible) | |||||
if (! shouldBeVisible) | if (! shouldBeVisible) | ||||
{ | { | ||||
if (currentlyFocusedComponent == this | |||||
|| isParentOf (currentlyFocusedComponent)) | |||||
if (currentlyFocusedComponent == this || isParentOf (currentlyFocusedComponent)) | |||||
{ | { | ||||
if (parentComponent_ != 0) | if (parentComponent_ != 0) | ||||
parentComponent_->grabKeyboardFocus(); | parentComponent_->grabKeyboardFocus(); | ||||
@@ -41074,32 +41113,18 @@ Component* Component::removeChildComponent (const int index) | |||||
childComponentList_.remove (index); | childComponentList_.remove (index); | ||||
child->parentComponent_ = 0; | child->parentComponent_ = 0; | ||||
if (childShowing) | |||||
// (NB: there are obscure situations where a childShowing = false, but it still has the focus) | |||||
if (currentlyFocusedComponent == child || child->isParentOf (currentlyFocusedComponent)) | |||||
{ | { | ||||
JUCE_TRY | |||||
{ | |||||
if ((currentlyFocusedComponent == child) | |||||
|| child->isParentOf (currentlyFocusedComponent)) | |||||
{ | |||||
// get rid first to force the grabKeyboardFocus to change to us. | |||||
giveAwayFocus(); | |||||
grabKeyboardFocus(); | |||||
} | |||||
} | |||||
#if JUCE_CATCH_UNHANDLED_EXCEPTIONS | |||||
catch (const std::exception& e) | |||||
{ | |||||
currentlyFocusedComponent = 0; | |||||
Desktop::getInstance().triggerFocusCallback(); | |||||
JUCEApplication::sendUnhandledException (&e, __FILE__, __LINE__); | |||||
} | |||||
catch (...) | |||||
{ | |||||
currentlyFocusedComponent = 0; | |||||
Desktop::getInstance().triggerFocusCallback(); | |||||
JUCEApplication::sendUnhandledException (0, __FILE__, __LINE__); | |||||
} | |||||
#endif | |||||
SafePointer<Component> thisPointer (this); | |||||
giveAwayFocus(); | |||||
if (thisPointer == 0) | |||||
return child; | |||||
if (childShowing) | |||||
grabKeyboardFocus(); | |||||
} | } | ||||
child->internalHierarchyChanged(); | child->internalHierarchyChanged(); | ||||
@@ -42545,14 +42570,13 @@ Component* JUCE_CALLTYPE Component::getCurrentlyFocusedComponent() throw() | |||||
void Component::giveAwayFocus() | void Component::giveAwayFocus() | ||||
{ | { | ||||
// use a copy so we can clear the value before the call | |||||
SafePointer<Component> componentLosingFocus (currentlyFocusedComponent); | |||||
Component* const componentLosingFocus = currentlyFocusedComponent; | |||||
currentlyFocusedComponent = 0; | currentlyFocusedComponent = 0; | ||||
Desktop::getInstance().triggerFocusCallback(); | |||||
if (componentLosingFocus != 0) | if (componentLosingFocus != 0) | ||||
componentLosingFocus->internalFocusLoss (focusChangedDirectly); | componentLosingFocus->internalFocusLoss (focusChangedDirectly); | ||||
Desktop::getInstance().triggerFocusCallback(); | |||||
} | } | ||||
bool Component::isMouseOver (const bool includeChildren) const | bool Component::isMouseOver (const bool includeChildren) const | ||||
@@ -64,7 +64,7 @@ | |||||
*/ | */ | ||||
#define JUCE_MAJOR_VERSION 1 | #define JUCE_MAJOR_VERSION 1 | ||||
#define JUCE_MINOR_VERSION 52 | #define JUCE_MINOR_VERSION 52 | ||||
#define JUCE_BUILDNUMBER 105 | |||||
#define JUCE_BUILDNUMBER 106 | |||||
/** Current Juce version number. | /** Current Juce version number. | ||||
@@ -28178,9 +28178,9 @@ private: | |||||
bool isDisabledFlag : 1; | bool isDisabledFlag : 1; | ||||
bool childCompFocusedFlag : 1; | bool childCompFocusedFlag : 1; | ||||
bool dontClipGraphicsFlag : 1; | bool dontClipGraphicsFlag : 1; | ||||
#if JUCE_DEBUG | |||||
#if JUCE_DEBUG | |||||
bool isInsidePaintCall : 1; | bool isInsidePaintCall : 1; | ||||
#endif | |||||
#endif | |||||
}; | }; | ||||
union | union | ||||
@@ -29126,18 +29126,19 @@ private: | |||||
class InternalTimerThread; | class InternalTimerThread; | ||||
/** | /** | ||||
Repeatedly calls a user-defined method at a specified time interval. | |||||
Makes repeated callbacks to a virtual method at a specified time interval. | |||||
A Timer's timerCallback() method will be repeatedly called at a given | A Timer's timerCallback() method will be repeatedly called at a given | ||||
interval. Initially when a Timer object is created, they will do nothing | |||||
until the startTimer() method is called, then the message thread will | |||||
start calling it back until stopTimer() is called. | |||||
interval. When you create a Timer object, it will do nothing until the | |||||
startTimer() method is called, which will cause the message thread to | |||||
start making callbacks at the specified interval, until stopTimer() is called | |||||
or the object is deleted. | |||||
The time interval isn't guaranteed to be precise to any more than maybe | The time interval isn't guaranteed to be precise to any more than maybe | ||||
10-20ms, and the intervals may end up being much longer than requested if the | 10-20ms, and the intervals may end up being much longer than requested if the | ||||
system is busy. Because it's the message thread that is doing the callbacks, | |||||
any messages that take a significant amount of time to process will block | |||||
all the timers for that period. | |||||
system is busy. Because the callbacks are made by the main message thread, | |||||
anything that blocks the message queue for a period of time will also prevent | |||||
any timers from running until it can carry on. | |||||
If you need to have a single callback that is shared by multiple timers with | If you need to have a single callback that is shared by multiple timers with | ||||
different frequencies, then the MultiTimer class allows you to do that - its | different frequencies, then the MultiTimer class allows you to do that - its | ||||
@@ -32741,6 +32742,12 @@ public: | |||||
/** Returns true if the low res preview is fully generated. */ | /** Returns true if the low res preview is fully generated. */ | ||||
bool isFullyLoaded() const throw(); | bool isFullyLoaded() const throw(); | ||||
/** Returns the highest level in the thumbnail. | |||||
Note that because the thumb only stores low-resolution data, this isn't | |||||
an accurate representation of the highest value, it's only a rough approximation. | |||||
*/ | |||||
float getApproximatePeak() const; | |||||
/** Returns the hash code that was set by setSource() or setReader(). */ | /** Returns the hash code that was set by setSource() or setReader(). */ | ||||
int64 getHashCode() const; | int64 getHashCode() const; | ||||
@@ -62,6 +62,12 @@ struct AudioThumbnail::MinMaxValue | |||||
return maxValue > minValue; | return maxValue > minValue; | ||||
} | } | ||||
inline int getPeak() const throw() | |||||
{ | |||||
return jmax (std::abs ((int) minValue), | |||||
std::abs ((int) maxValue)); | |||||
} | |||||
inline void read (InputStream& input) | inline void read (InputStream& input) | ||||
{ | { | ||||
minValue = input.readByte(); | minValue = input.readByte(); | ||||
@@ -262,6 +268,7 @@ class AudioThumbnail::ThumbData | |||||
{ | { | ||||
public: | public: | ||||
ThumbData (const int numThumbSamples) | ThumbData (const int numThumbSamples) | ||||
: peakLevel (-1) | |||||
{ | { | ||||
ensureSize (numThumbSamples); | ensureSize (numThumbSamples); | ||||
} | } | ||||
@@ -308,6 +315,8 @@ public: | |||||
void write (const MinMaxValue* const source, const int startIndex, const int numValues) | void write (const MinMaxValue* const source, const int startIndex, const int numValues) | ||||
{ | { | ||||
resetPeak(); | |||||
if (startIndex + numValues > data.size()) | if (startIndex + numValues > data.size()) | ||||
ensureSize (startIndex + numValues); | ensureSize (startIndex + numValues); | ||||
@@ -317,8 +326,29 @@ public: | |||||
dest[i] = source[i]; | dest[i] = source[i]; | ||||
} | } | ||||
void resetPeak() | |||||
{ | |||||
peakLevel = -1; | |||||
} | |||||
int getPeak() | |||||
{ | |||||
if (peakLevel < 0) | |||||
{ | |||||
for (int i = 0; i < data.size(); ++i) | |||||
{ | |||||
const int peak = data[i].getPeak(); | |||||
if (peak > peakLevel) | |||||
peakLevel = peak; | |||||
} | |||||
} | |||||
return peakLevel; | |||||
} | |||||
private: | private: | ||||
Array <MinMaxValue> data; | Array <MinMaxValue> data; | ||||
int peakLevel; | |||||
void ensureSize (const int thumbSamples) | void ensureSize (const int thumbSamples) | ||||
{ | { | ||||
@@ -700,6 +730,16 @@ bool AudioThumbnail::isFullyLoaded() const throw() | |||||
return numSamplesFinished >= totalSamples - samplesPerThumbSample; | return numSamplesFinished >= totalSamples - samplesPerThumbSample; | ||||
} | } | ||||
float AudioThumbnail::getApproximatePeak() const | |||||
{ | |||||
int peak = 0; | |||||
for (int i = channels.size(); --i >= 0;) | |||||
peak = jmax (peak, channels.getUnchecked(i)->getPeak()); | |||||
return jlimit (0, 127, peak) / 127.0f; | |||||
} | |||||
void AudioThumbnail::drawChannel (Graphics& g, const Rectangle<int>& area, double startTime, | void AudioThumbnail::drawChannel (Graphics& g, const Rectangle<int>& area, double startTime, | ||||
double endTime, int channelNum, float verticalZoomFactor) | double endTime, int channelNum, float verticalZoomFactor) | ||||
{ | { | ||||
@@ -177,6 +177,12 @@ public: | |||||
/** Returns true if the low res preview is fully generated. */ | /** Returns true if the low res preview is fully generated. */ | ||||
bool isFullyLoaded() const throw(); | bool isFullyLoaded() const throw(); | ||||
/** Returns the highest level in the thumbnail. | |||||
Note that because the thumb only stores low-resolution data, this isn't | |||||
an accurate representation of the highest value, it's only a rough approximation. | |||||
*/ | |||||
float getApproximatePeak() const; | |||||
/** Returns the hash code that was set by setSource() or setReader(). */ | /** Returns the hash code that was set by setSource() or setReader(). */ | ||||
int64 getHashCode() const; | int64 getHashCode() const; | ||||
@@ -546,10 +546,10 @@ public: | |||||
: graph (graph_), | : graph (graph_), | ||||
orderedNodes (orderedNodes_) | orderedNodes (orderedNodes_) | ||||
{ | { | ||||
nodeIds.add (zeroNodeID); // first buffer is read-only zeros | |||||
nodeIds.add ((uint32) zeroNodeID); // first buffer is read-only zeros | |||||
channels.add (0); | channels.add (0); | ||||
midiNodeIds.add (zeroNodeID); | |||||
midiNodeIds.add ((uint32) zeroNodeID); | |||||
for (int i = 0; i < orderedNodes.size(); ++i) | for (int i = 0; i < orderedNodes.size(); ++i) | ||||
{ | { | ||||
@@ -835,7 +835,7 @@ private: | |||||
if (midiNodeIds.getUnchecked(i) == freeNodeID) | if (midiNodeIds.getUnchecked(i) == freeNodeID) | ||||
return i; | return i; | ||||
midiNodeIds.add (freeNodeID); | |||||
midiNodeIds.add ((uint32) freeNodeID); | |||||
return midiNodeIds.size() - 1; | return midiNodeIds.size() - 1; | ||||
} | } | ||||
else | else | ||||
@@ -844,7 +844,7 @@ private: | |||||
if (nodeIds.getUnchecked(i) == freeNodeID) | if (nodeIds.getUnchecked(i) == freeNodeID) | ||||
return i; | return i; | ||||
nodeIds.add (freeNodeID); | |||||
nodeIds.add ((uint32) freeNodeID); | |||||
channels.add (0); | channels.add (0); | ||||
return nodeIds.size() - 1; | return nodeIds.size() - 1; | ||||
} | } | ||||
@@ -884,7 +884,7 @@ private: | |||||
nodeIds.getUnchecked(i), | nodeIds.getUnchecked(i), | ||||
channels.getUnchecked(i))) | channels.getUnchecked(i))) | ||||
{ | { | ||||
nodeIds.set (i, freeNodeID); | |||||
nodeIds.set (i, (uint32) freeNodeID); | |||||
} | } | ||||
} | } | ||||
@@ -895,7 +895,7 @@ private: | |||||
midiNodeIds.getUnchecked(i), | midiNodeIds.getUnchecked(i), | ||||
AudioProcessorGraph::midiChannelIndex)) | AudioProcessorGraph::midiChannelIndex)) | ||||
{ | { | ||||
midiNodeIds.set (i, freeNodeID); | |||||
midiNodeIds.set (i, (uint32) freeNodeID); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -33,7 +33,7 @@ | |||||
*/ | */ | ||||
#define JUCE_MAJOR_VERSION 1 | #define JUCE_MAJOR_VERSION 1 | ||||
#define JUCE_MINOR_VERSION 52 | #define JUCE_MINOR_VERSION 52 | ||||
#define JUCE_BUILDNUMBER 105 | |||||
#define JUCE_BUILDNUMBER 106 | |||||
/** Current Juce version number. | /** Current Juce version number. | ||||
@@ -31,18 +31,19 @@ class InternalTimerThread; | |||||
//============================================================================== | //============================================================================== | ||||
/** | /** | ||||
Repeatedly calls a user-defined method at a specified time interval. | |||||
Makes repeated callbacks to a virtual method at a specified time interval. | |||||
A Timer's timerCallback() method will be repeatedly called at a given | A Timer's timerCallback() method will be repeatedly called at a given | ||||
interval. Initially when a Timer object is created, they will do nothing | |||||
until the startTimer() method is called, then the message thread will | |||||
start calling it back until stopTimer() is called. | |||||
interval. When you create a Timer object, it will do nothing until the | |||||
startTimer() method is called, which will cause the message thread to | |||||
start making callbacks at the specified interval, until stopTimer() is called | |||||
or the object is deleted. | |||||
The time interval isn't guaranteed to be precise to any more than maybe | The time interval isn't guaranteed to be precise to any more than maybe | ||||
10-20ms, and the intervals may end up being much longer than requested if the | 10-20ms, and the intervals may end up being much longer than requested if the | ||||
system is busy. Because it's the message thread that is doing the callbacks, | |||||
any messages that take a significant amount of time to process will block | |||||
all the timers for that period. | |||||
system is busy. Because the callbacks are made by the main message thread, | |||||
anything that blocks the message queue for a period of time will also prevent | |||||
any timers from running until it can carry on. | |||||
If you need to have a single callback that is shared by multiple timers with | If you need to have a single callback that is shared by multiple timers with | ||||
different frequencies, then the MultiTimer class allows you to do that - its | different frequencies, then the MultiTimer class allows you to do that - its | ||||
@@ -470,8 +470,7 @@ void Component::setVisible (bool shouldBeVisible) | |||||
if (! shouldBeVisible) | if (! shouldBeVisible) | ||||
{ | { | ||||
if (currentlyFocusedComponent == this | |||||
|| isParentOf (currentlyFocusedComponent)) | |||||
if (currentlyFocusedComponent == this || isParentOf (currentlyFocusedComponent)) | |||||
{ | { | ||||
if (parentComponent_ != 0) | if (parentComponent_ != 0) | ||||
parentComponent_->grabKeyboardFocus(); | parentComponent_->grabKeyboardFocus(); | ||||
@@ -1358,32 +1357,18 @@ Component* Component::removeChildComponent (const int index) | |||||
childComponentList_.remove (index); | childComponentList_.remove (index); | ||||
child->parentComponent_ = 0; | child->parentComponent_ = 0; | ||||
if (childShowing) | |||||
// (NB: there are obscure situations where a childShowing = false, but it still has the focus) | |||||
if (currentlyFocusedComponent == child || child->isParentOf (currentlyFocusedComponent)) | |||||
{ | { | ||||
JUCE_TRY | |||||
{ | |||||
if ((currentlyFocusedComponent == child) | |||||
|| child->isParentOf (currentlyFocusedComponent)) | |||||
{ | |||||
// get rid first to force the grabKeyboardFocus to change to us. | |||||
giveAwayFocus(); | |||||
grabKeyboardFocus(); | |||||
} | |||||
} | |||||
#if JUCE_CATCH_UNHANDLED_EXCEPTIONS | |||||
catch (const std::exception& e) | |||||
{ | |||||
currentlyFocusedComponent = 0; | |||||
Desktop::getInstance().triggerFocusCallback(); | |||||
JUCEApplication::sendUnhandledException (&e, __FILE__, __LINE__); | |||||
} | |||||
catch (...) | |||||
{ | |||||
currentlyFocusedComponent = 0; | |||||
Desktop::getInstance().triggerFocusCallback(); | |||||
JUCEApplication::sendUnhandledException (0, __FILE__, __LINE__); | |||||
} | |||||
#endif | |||||
SafePointer<Component> thisPointer (this); | |||||
giveAwayFocus(); | |||||
if (thisPointer == 0) | |||||
return child; | |||||
if (childShowing) | |||||
grabKeyboardFocus(); | |||||
} | } | ||||
child->internalHierarchyChanged(); | child->internalHierarchyChanged(); | ||||
@@ -2854,14 +2839,13 @@ Component* JUCE_CALLTYPE Component::getCurrentlyFocusedComponent() throw() | |||||
void Component::giveAwayFocus() | void Component::giveAwayFocus() | ||||
{ | { | ||||
// use a copy so we can clear the value before the call | |||||
SafePointer<Component> componentLosingFocus (currentlyFocusedComponent); | |||||
Component* const componentLosingFocus = currentlyFocusedComponent; | |||||
currentlyFocusedComponent = 0; | currentlyFocusedComponent = 0; | ||||
Desktop::getInstance().triggerFocusCallback(); | |||||
if (componentLosingFocus != 0) | if (componentLosingFocus != 0) | ||||
componentLosingFocus->internalFocusLoss (focusChangedDirectly); | componentLosingFocus->internalFocusLoss (focusChangedDirectly); | ||||
Desktop::getInstance().triggerFocusCallback(); | |||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
@@ -2171,9 +2171,9 @@ private: | |||||
bool isDisabledFlag : 1; | bool isDisabledFlag : 1; | ||||
bool childCompFocusedFlag : 1; | bool childCompFocusedFlag : 1; | ||||
bool dontClipGraphicsFlag : 1; | bool dontClipGraphicsFlag : 1; | ||||
#if JUCE_DEBUG | |||||
#if JUCE_DEBUG | |||||
bool isInsidePaintCall : 1; | bool isInsidePaintCall : 1; | ||||
#endif | |||||
#endif | |||||
}; | }; | ||||
union | union | ||||