diff --git a/src/audio/audio_file_formats/juce_AudioFormatWriter.cpp b/src/audio/audio_file_formats/juce_AudioFormatWriter.cpp index 8949e63c78..5e55e86daf 100644 --- a/src/audio/audio_file_formats/juce_AudioFormatWriter.cpp +++ b/src/audio/audio_file_formats/juce_AudioFormatWriter.cpp @@ -200,7 +200,7 @@ public: isRunning = false; timeSliceThread.removeTimeSliceClient (this); - while (useTimeSlice() == 0) + while (writePendingData() == 0) {} } @@ -229,6 +229,11 @@ public: } int useTimeSlice() + { + return writePendingData(); + } + + int writePendingData() { const int numToDo = getTotalSize() / 4; diff --git a/src/audio/audio_file_formats/juce_OggVorbisAudioFormat.cpp b/src/audio/audio_file_formats/juce_OggVorbisAudioFormat.cpp index d967fcc943..39892bc684 100644 --- a/src/audio/audio_file_formats/juce_OggVorbisAudioFormat.cpp +++ b/src/audio/audio_file_formats/juce_OggVorbisAudioFormat.cpp @@ -90,11 +90,6 @@ static const char* const oggExtensions[] = { ".ogg", 0 }; //============================================================================== class OggReader : public AudioFormatReader { - OggVorbisNamespace::OggVorbis_File ovFile; - OggVorbisNamespace::ov_callbacks callbacks; - AudioSampleBuffer reservoir; - int reservoirStart, samplesInReservoir; - public: //============================================================================== OggReader (InputStream* const inp) @@ -242,33 +237,28 @@ public: } private: + OggVorbisNamespace::OggVorbis_File ovFile; + OggVorbisNamespace::ov_callbacks callbacks; + AudioSampleBuffer reservoir; + int reservoirStart, samplesInReservoir; + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OggReader); }; //============================================================================== class OggWriter : public AudioFormatWriter { - OggVorbisNamespace::ogg_stream_state os; - OggVorbisNamespace::ogg_page og; - OggVorbisNamespace::ogg_packet op; - OggVorbisNamespace::vorbis_info vi; - OggVorbisNamespace::vorbis_comment vc; - OggVorbisNamespace::vorbis_dsp_state vd; - OggVorbisNamespace::vorbis_block vb; - public: - bool ok; - //============================================================================== OggWriter (OutputStream* const out, const double sampleRate, const int numChannels, const int bitsPerSample, const int qualityIndex) - : AudioFormatWriter (out, TRANS (oggFormatName), sampleRate, numChannels, bitsPerSample) + : AudioFormatWriter (out, TRANS (oggFormatName), sampleRate, numChannels, bitsPerSample), + ok (false) { using namespace OggVorbisNamespace; - ok = false; vorbis_info_init (&vi); @@ -314,7 +304,7 @@ public: if (ok) { // write a zero-length packet to show ogg that we're finished.. - write (0, 0); + writeSamples (0); ogg_stream_clear (&os); vorbis_block_clear (&vb); @@ -335,28 +325,38 @@ public: //============================================================================== bool write (const int** samplesToWrite, int numSamples) { - using namespace OggVorbisNamespace; - if (! ok) - return false; - - if (numSamples > 0) + if (ok) { - const double gain = 1.0 / 0x80000000u; - float** const vorbisBuffer = vorbis_analysis_buffer (&vd, numSamples); + using namespace OggVorbisNamespace; - for (int i = numChannels; --i >= 0;) + if (numSamples > 0) { - float* const dst = vorbisBuffer[i]; - const int* const src = samplesToWrite [i]; + const double gain = 1.0 / 0x80000000u; + float** const vorbisBuffer = vorbis_analysis_buffer (&vd, numSamples); - if (src != nullptr && dst != nullptr) + for (int i = numChannels; --i >= 0;) { - for (int j = 0; j < numSamples; ++j) - dst[j] = (float) (src[j] * gain); + float* const dst = vorbisBuffer[i]; + const int* const src = samplesToWrite [i]; + + if (src != nullptr && dst != nullptr) + { + for (int j = 0; j < numSamples; ++j) + dst[j] = (float) (src[j] * gain); + } } } + + writeSamples (numSamples); } + return ok; + } + + void writeSamples (int numSamples) + { + using namespace OggVorbisNamespace; + vorbis_analysis_wrote (&vd, numSamples); while (vorbis_analysis_blockout (&vd, &vb) == 1) @@ -381,11 +381,19 @@ public: } } } - - return true; } + bool ok; + private: + OggVorbisNamespace::ogg_stream_state os; + OggVorbisNamespace::ogg_page og; + OggVorbisNamespace::ogg_packet op; + OggVorbisNamespace::vorbis_info vi; + OggVorbisNamespace::vorbis_comment vc; + OggVorbisNamespace::vorbis_dsp_state vd; + OggVorbisNamespace::vorbis_block vb; + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OggWriter); }; diff --git a/src/audio/audio_sources/juce_AudioFormatReaderSource.cpp b/src/audio/audio_sources/juce_AudioFormatReaderSource.cpp index a0692da240..7169e1c15d 100644 --- a/src/audio/audio_sources/juce_AudioFormatReaderSource.cpp +++ b/src/audio/audio_sources/juce_AudioFormatReaderSource.cpp @@ -43,8 +43,6 @@ AudioFormatReaderSource::AudioFormatReaderSource (AudioFormatReader* const reade AudioFormatReaderSource::~AudioFormatReaderSource() { - releaseResources(); - if (deleteReader) delete reader; } diff --git a/src/audio/audio_sources/juce_AudioTransportSource.cpp b/src/audio/audio_sources/juce_AudioTransportSource.cpp index 526802a2a7..25fe30887d 100644 --- a/src/audio/audio_sources/juce_AudioTransportSource.cpp +++ b/src/audio/audio_sources/juce_AudioTransportSource.cpp @@ -55,7 +55,7 @@ AudioTransportSource::~AudioTransportSource() { setSource (nullptr); - releaseResources(); + releaseMasterResources(); } void AudioTransportSource::setSource (PositionableAudioSource* const newSource, @@ -242,7 +242,7 @@ void AudioTransportSource::prepareToPlay (int samplesPerBlockExpected, isPrepared = true; } -void AudioTransportSource::releaseResources() +void AudioTransportSource::releaseMasterResources() { const ScopedLock sl (callbackLock); @@ -252,6 +252,11 @@ void AudioTransportSource::releaseResources() isPrepared = false; } +void AudioTransportSource::releaseResources() +{ + releaseMasterResources(); +} + void AudioTransportSource::getNextAudioBlock (const AudioSourceChannelInfo& info) { const ScopedLock sl (callbackLock); diff --git a/src/audio/audio_sources/juce_AudioTransportSource.h b/src/audio/audio_sources/juce_AudioTransportSource.h index 7e4488a5e7..9e9d91b71c 100644 --- a/src/audio/audio_sources/juce_AudioTransportSource.h +++ b/src/audio/audio_sources/juce_AudioTransportSource.h @@ -176,6 +176,8 @@ private: int blockSize, readAheadBufferSize; bool isPrepared, inputStreamEOF; + void releaseMasterResources(); + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioTransportSource); }; diff --git a/src/audio/midi/juce_MidiMessage.cpp b/src/audio/midi/juce_MidiMessage.cpp index 48a33f8f4b..9ffac45214 100644 --- a/src/audio/midi/juce_MidiMessage.cpp +++ b/src/audio/midi/juce_MidiMessage.cpp @@ -301,8 +301,8 @@ int MidiMessage::getChannel() const noexcept { if ((data[0] & 0xf0) != 0xf0) return (data[0] & 0xf) + 1; - else - return 0; + + return 0; } bool MidiMessage::isForChannel (const int channel) const noexcept @@ -355,8 +355,8 @@ uint8 MidiMessage::getVelocity() const noexcept { if (isNoteOnOrOff()) return data[2]; - else - return 0; + + return 0; } float MidiMessage::getFloatVelocity() const noexcept @@ -383,6 +383,7 @@ bool MidiMessage::isAftertouch() const noexcept int MidiMessage::getAfterTouchValue() const noexcept { + jassert (isAftertouch()); return data[2]; } @@ -407,7 +408,6 @@ bool MidiMessage::isChannelPressure() const noexcept int MidiMessage::getChannelPressureValue() const noexcept { jassert (isChannelPressure()); - return data[1]; } @@ -427,6 +427,7 @@ bool MidiMessage::isProgramChange() const noexcept int MidiMessage::getProgramChangeNumber() const noexcept { + jassert (isProgramChange()); return data[1]; } @@ -445,6 +446,7 @@ bool MidiMessage::isPitchWheel() const noexcept int MidiMessage::getPitchWheelValue() const noexcept { + jassert (isPitchWheel()); return data[1] | (data[2] << 7); } @@ -454,7 +456,8 @@ const MidiMessage MidiMessage::pitchWheel (const int channel, jassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16 jassert (isPositiveAndBelow (position, (int) 0x4000)); - return MidiMessage (MidiHelpers::initialByte (0xe0, channel), position & 127, (position >> 7) & 127); + return MidiMessage (MidiHelpers::initialByte (0xe0, channel), + position & 127, (position >> 7) & 127); } bool MidiMessage::isController() const noexcept @@ -465,14 +468,12 @@ bool MidiMessage::isController() const noexcept int MidiMessage::getControllerNumber() const noexcept { jassert (isController()); - return data[1]; } int MidiMessage::getControllerValue() const noexcept { jassert (isController()); - return data[2]; } @@ -481,12 +482,13 @@ const MidiMessage MidiMessage::controllerEvent (const int channel, const int con // the channel must be between 1 and 16 inclusive jassert (channel > 0 && channel <= 16); - return MidiMessage (MidiHelpers::initialByte (0xb0, channel), controllerType & 127, value & 127); + return MidiMessage (MidiHelpers::initialByte (0xb0, channel), + controllerType & 127, value & 127); } const MidiMessage MidiMessage::noteOn (const int channel, const int noteNumber, const float velocity) noexcept { - return noteOn (channel, noteNumber, (uint8)(velocity * 127.0f)); + return noteOn (channel, noteNumber, (uint8) (velocity * 127.0f)); } const MidiMessage MidiMessage::noteOn (const int channel, const int noteNumber, const uint8 velocity) noexcept @@ -494,7 +496,8 @@ const MidiMessage MidiMessage::noteOn (const int channel, const int noteNumber, jassert (channel > 0 && channel <= 16); jassert (isPositiveAndBelow (noteNumber, (int) 128)); - return MidiMessage (MidiHelpers::initialByte (0x90, channel), noteNumber & 127, MidiHelpers::validVelocity (velocity)); + return MidiMessage (MidiHelpers::initialByte (0x90, channel), + noteNumber & 127, MidiHelpers::validVelocity (velocity)); } const MidiMessage MidiMessage::noteOff (const int channel, const int noteNumber, uint8 velocity) noexcept @@ -502,7 +505,8 @@ const MidiMessage MidiMessage::noteOff (const int channel, const int noteNumber, jassert (channel > 0 && channel <= 16); jassert (isPositiveAndBelow (noteNumber, (int) 128)); - return MidiMessage (MidiHelpers::initialByte (0x80, channel), noteNumber & 127, MidiHelpers::validVelocity (velocity)); + return MidiMessage (MidiHelpers::initialByte (0x80, channel), + noteNumber & 127, MidiHelpers::validVelocity (velocity)); } const MidiMessage MidiMessage::allNotesOff (const int channel) noexcept @@ -534,15 +538,10 @@ const MidiMessage MidiMessage::masterVolume (const float volume) { const int vol = jlimit (0, 0x3fff, roundToInt (volume * 0x4000)); - uint8 buf[8]; - buf[0] = 0xf0; - buf[1] = 0x7f; - buf[2] = 0x7f; - buf[3] = 0x04; - buf[4] = 0x01; - buf[5] = (uint8) (vol & 0x7f); - buf[6] = (uint8) (vol >> 7); - buf[7] = 0xf7; + const uint8 buf[] = { 0xf0, 0x7f, 0x7f, 0x04, 0x01, + (uint8) (vol & 0x7f), + (uint8) (vol >> 7), + 0xf7 }; return MidiMessage (buf, 8); } @@ -574,17 +573,10 @@ int MidiMessage::getSysExDataSize() const noexcept return isSysEx() ? size - 2 : 0; } -bool MidiMessage::isMetaEvent() const noexcept -{ - return *data == 0xff; -} - -bool MidiMessage::isActiveSense() const noexcept -{ - return *data == 0xfe; -} - //============================================================================== +bool MidiMessage::isMetaEvent() const noexcept { return *data == 0xff; } +bool MidiMessage::isActiveSense() const noexcept { return *data == 0xfe; } + int MidiMessage::getMetaEventType() const noexcept { return *data != 0xff ? -1 : data[1]; @@ -603,26 +595,20 @@ int MidiMessage::getMetaEventLength() const noexcept const uint8* MidiMessage::getMetaEventData() const noexcept { + jassert (isMetaEvent()); + int n; const uint8* d = data + 2; readVariableLengthVal (d, n); return d + n; } -bool MidiMessage::isTrackMetaEvent() const noexcept -{ - return getMetaEventType() == 0; -} - -bool MidiMessage::isEndOfTrackMetaEvent() const noexcept -{ - return getMetaEventType() == 47; -} +bool MidiMessage::isTrackMetaEvent() const noexcept { return getMetaEventType() == 0; } +bool MidiMessage::isEndOfTrackMetaEvent() const noexcept { return getMetaEventType() == 47; } bool MidiMessage::isTextMetaEvent() const noexcept { const int t = getMetaEventType(); - return t > 0 && t < 16; } @@ -631,23 +617,13 @@ const String MidiMessage::getTextFromTextMetaEvent() const return String (reinterpret_cast (getMetaEventData()), getMetaEventLength()); } -bool MidiMessage::isTrackNameEvent() const noexcept -{ - return (data[1] == 3) && (*data == 0xff); -} - -bool MidiMessage::isTempoMetaEvent() const noexcept -{ - return (data[1] == 81) && (*data == 0xff); -} - -bool MidiMessage::isMidiChannelMetaEvent() const noexcept -{ - return (data[1] == 0x20) && (*data == 0xff) && (data[2] == 1); -} +bool MidiMessage::isTrackNameEvent() const noexcept { return (data[1] == 3) && (*data == 0xff); } +bool MidiMessage::isTempoMetaEvent() const noexcept { return (data[1] == 81) && (*data == 0xff); } +bool MidiMessage::isMidiChannelMetaEvent() const noexcept { return (data[1] == 0x20) && (*data == 0xff) && (data[2] == 1); } int MidiMessage::getMidiChannelMetaEventChannel() const noexcept { + jassert (isMidiChannelMetaEvent()); return data[3] + 1; } @@ -693,13 +669,10 @@ double MidiMessage::getTempoMetaEventTickLength (const short timeFormat) const n const MidiMessage MidiMessage::tempoMetaEvent (int microsecondsPerQuarterNote) noexcept { - uint8 d[8]; - d[0] = 0xff; - d[1] = 81; - d[2] = 3; - d[3] = (uint8) (microsecondsPerQuarterNote >> 16); - d[4] = (uint8) ((microsecondsPerQuarterNote >> 8) & 0xff); - d[5] = (uint8) (microsecondsPerQuarterNote & 0xff); + const uint8 d[] = { 0xff, 81, 3, + (uint8) (microsecondsPerQuarterNote >> 16), + (uint8) (microsecondsPerQuarterNote >> 8), + (uint8) microsecondsPerQuarterNote }; return MidiMessage (d, 6, 0.0); } @@ -726,12 +699,6 @@ void MidiMessage::getTimeSignatureInfo (int& numerator, int& denominator) const const MidiMessage MidiMessage::timeSignatureMetaEvent (const int numerator, const int denominator) { - uint8 d[8]; - d[0] = 0xff; - d[1] = 0x58; - d[2] = 0x04; - d[3] = (uint8) numerator; - int n = 1; int powerOfTwo = 0; @@ -741,20 +708,15 @@ const MidiMessage MidiMessage::timeSignatureMetaEvent (const int numerator, cons ++powerOfTwo; } - d[4] = (uint8) powerOfTwo; - d[5] = 0x01; - d[6] = 96; + const uint8 d[] = { 0xff, 0x58, 0x04, (uint8) numerator, + (uint8) powerOfTwo, 1, 96 }; return MidiMessage (d, 7, 0.0); } const MidiMessage MidiMessage::midiChannelMetaEvent (const int channel) noexcept { - uint8 d[8]; - d[0] = 0xff; - d[1] = 0x20; - d[2] = 0x01; - d[3] = (uint8) jlimit (0, 0xff, channel - 1); + const uint8 d[] = { 0xff, 0x20, 0x01, (uint8) jlimit (0, 0xff, channel - 1) }; return MidiMessage (d, 4, 0.0); } @@ -775,15 +737,8 @@ const MidiMessage MidiMessage::endOfTrack() noexcept } //============================================================================== -bool MidiMessage::isSongPositionPointer() const noexcept -{ - return *data == 0xf2; -} - -int MidiMessage::getSongPositionPointerMidiBeat() const noexcept -{ - return data[1] | (data[2] << 7); -} +bool MidiMessage::isSongPositionPointer() const noexcept { return *data == 0xf2; } +int MidiMessage::getSongPositionPointerMidiBeat() const noexcept { return data[1] | (data[2] << 7); } const MidiMessage MidiMessage::songPositionPointer (const int positionInMidiBeats) noexcept { @@ -792,63 +747,23 @@ const MidiMessage MidiMessage::songPositionPointer (const int positionInMidiBeat (positionInMidiBeats >> 7) & 127); } -bool MidiMessage::isMidiStart() const noexcept -{ - return *data == 0xfa; -} +bool MidiMessage::isMidiStart() const noexcept { return *data == 0xfa; } +const MidiMessage MidiMessage::midiStart() noexcept { return MidiMessage (0xfa); } -const MidiMessage MidiMessage::midiStart() noexcept -{ - return MidiMessage (0xfa); -} +bool MidiMessage::isMidiContinue() const noexcept { return *data == 0xfb; } +const MidiMessage MidiMessage::midiContinue() noexcept { return MidiMessage (0xfb); } -bool MidiMessage::isMidiContinue() const noexcept -{ - return *data == 0xfb; -} - -const MidiMessage MidiMessage::midiContinue() noexcept -{ - return MidiMessage (0xfb); -} +bool MidiMessage::isMidiStop() const noexcept { return *data == 0xfc; } +const MidiMessage MidiMessage::midiStop() noexcept { return MidiMessage (0xfc); } -bool MidiMessage::isMidiStop() const noexcept -{ - return *data == 0xfc; -} +bool MidiMessage::isMidiClock() const noexcept { return *data == 0xf8; } +const MidiMessage MidiMessage::midiClock() noexcept { return MidiMessage (0xf8); } -const MidiMessage MidiMessage::midiStop() noexcept -{ - return MidiMessage (0xfc); -} +bool MidiMessage::isQuarterFrame() const noexcept { return *data == 0xf1; } +int MidiMessage::getQuarterFrameSequenceNumber() const noexcept { return ((int) data[1]) >> 4; } +int MidiMessage::getQuarterFrameValue() const noexcept { return ((int) data[1]) & 0x0f; } -bool MidiMessage::isMidiClock() const noexcept -{ - return *data == 0xf8; -} - -const MidiMessage MidiMessage::midiClock() noexcept -{ - return MidiMessage (0xf8); -} - -bool MidiMessage::isQuarterFrame() const noexcept -{ - return *data == 0xf1; -} - -int MidiMessage::getQuarterFrameSequenceNumber() const noexcept -{ - return ((int) data[1]) >> 4; -} - -int MidiMessage::getQuarterFrameValue() const noexcept -{ - return ((int) data[1]) & 0x0f; -} - -const MidiMessage MidiMessage::quarterFrame (const int sequenceNumber, - const int value) noexcept +const MidiMessage MidiMessage::quarterFrame (const int sequenceNumber, const int value) noexcept { return MidiMessage (0xf1, (sequenceNumber << 4) | value); } @@ -862,10 +777,7 @@ bool MidiMessage::isFullFrame() const noexcept && data[4] == 0x01; } -void MidiMessage::getFullFrameParameters (int& hours, - int& minutes, - int& seconds, - int& frames, +void MidiMessage::getFullFrameParameters (int& hours, int& minutes, int& seconds, int& frames, MidiMessage::SmpteTimecodeType& timecodeType) const noexcept { jassert (isFullFrame()); @@ -877,23 +789,16 @@ void MidiMessage::getFullFrameParameters (int& hours, frames = data[8]; } -const MidiMessage MidiMessage::fullFrame (const int hours, - const int minutes, - const int seconds, - const int frames, +const MidiMessage MidiMessage::fullFrame (const int hours, const int minutes, + const int seconds, const int frames, MidiMessage::SmpteTimecodeType timecodeType) { - uint8 d[10]; - d[0] = 0xf0; - d[1] = 0x7f; - d[2] = 0x7f; - d[3] = 0x01; - d[4] = 0x01; - d[5] = (uint8) ((hours & 0x01f) | (timecodeType << 5)); - d[6] = (uint8) minutes; - d[7] = (uint8) seconds; - d[8] = (uint8) frames; - d[9] = 0xf7; + const uint8 d[] = { 0xf0, 0x7f, 0x7f, 0x01, 0x01, + (uint8) ((hours & 0x01f) | (timecodeType << 5)), + (uint8) minutes, + (uint8) seconds, + (uint8) frames, + 0xf7 }; return MidiMessage (d, 10, 0.0); } @@ -915,22 +820,13 @@ MidiMessage::MidiMachineControlCommand MidiMessage::getMidiMachineControlCommand const MidiMessage MidiMessage::midiMachineControlCommand (MidiMessage::MidiMachineControlCommand command) { - uint8 d[6]; - d[0] = 0xf0; - d[1] = 0x7f; - d[2] = 0x00; - d[3] = 0x06; - d[4] = (uint8) command; - d[5] = 0xf7; + const uint8 d[] = { 0xf0, 0x7f, 0, 6, (uint8) command, 0xf7 }; return MidiMessage (d, 6, 0.0); } //============================================================================== -bool MidiMessage::isMidiMachineControlGoto (int& hours, - int& minutes, - int& seconds, - int& frames) const noexcept +bool MidiMessage::isMidiMachineControlGoto (int& hours, int& minutes, int& seconds, int& frames) const noexcept { if (size >= 12 && data[0] == 0xf0 @@ -951,24 +847,14 @@ bool MidiMessage::isMidiMachineControlGoto (int& hours, return false; } -const MidiMessage MidiMessage::midiMachineControlGoto (int hours, - int minutes, - int seconds, - int frames) -{ - uint8 d[12]; - d[0] = 0xf0; - d[1] = 0x7f; - d[2] = 0x00; - d[3] = 0x06; - d[4] = 0x44; - d[5] = 0x06; - d[6] = 0x01; - d[7] = (uint8) hours; - d[8] = (uint8) minutes; - d[9] = (uint8) seconds; - d[10] = (uint8) frames; - d[11] = 0xf7; +const MidiMessage MidiMessage::midiMachineControlGoto (int hours, int minutes, int seconds, int frames) +{ + const uint8 d[] = { 0xf0, 0x7f, 0, 6, 0x44, 6, 1, + (uint8) hours, + (uint8) minutes, + (uint8) seconds, + (uint8) frames, + 0xf7 }; return MidiMessage (d, 12, 0.0); } diff --git a/src/audio/plugin_host/juce_PluginListComponent.cpp b/src/audio/plugin_host/juce_PluginListComponent.cpp index eedbc8d3b5..45e897ce28 100644 --- a/src/audio/plugin_host/juce_PluginListComponent.cpp +++ b/src/audio/plugin_host/juce_PluginListComponent.cpp @@ -55,7 +55,7 @@ PluginListComponent::PluginListComponent (KnownPluginList& listToEdit, setSize (400, 600); list.addChangeListener (this); - changeListenerCallback (nullptr); + updateList(); } PluginListComponent::~PluginListComponent() @@ -71,6 +71,11 @@ void PluginListComponent::resized() } void PluginListComponent::changeListenerCallback (ChangeBroadcaster*) +{ + updateList(); +} + +void PluginListComponent::updateList() { listBox.updateContent(); listBox.repaint(); diff --git a/src/audio/plugin_host/juce_PluginListComponent.h b/src/audio/plugin_host/juce_PluginListComponent.h index eccc6e8b28..21265f4399 100644 --- a/src/audio/plugin_host/juce_PluginListComponent.h +++ b/src/audio/plugin_host/juce_PluginListComponent.h @@ -92,6 +92,7 @@ private: void scanFor (AudioPluginFormat* format); static void optionsMenuStaticCallback (int result, PluginListComponent*); void optionsMenuCallback (int result); + void updateList(); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PluginListComponent); }; diff --git a/src/containers/juce_Variant.cpp b/src/containers/juce_Variant.cpp index b9335c3afa..4b98d5fd69 100644 --- a/src/containers/juce_Variant.cpp +++ b/src/containers/juce_Variant.cpp @@ -378,16 +378,16 @@ void var::swapWith (var& other) noexcept std::swap (value, other.value); } -var& var::operator= (const var& newValue) { type->cleanUp (value); type = newValue.type; type->createCopy (value, newValue.value); return *this; } -var& var::operator= (const int newValue) { type->cleanUp (value); type = &VariantType_Int::instance; value.intValue = newValue; return *this; } -var& var::operator= (const int64 newValue) { type->cleanUp (value); type = &VariantType_Int64::instance; value.int64Value = newValue; return *this; } -var& var::operator= (const bool newValue) { type->cleanUp (value); type = &VariantType_Bool::instance; value.boolValue = newValue; return *this; } -var& var::operator= (const double newValue) { type->cleanUp (value); type = &VariantType_Double::instance; value.doubleValue = newValue; return *this; } -var& var::operator= (const char* const newValue) { var v (newValue); swapWith (v); return *this; } -var& var::operator= (const wchar_t* const newValue) { var v (newValue); swapWith (v); return *this; } -var& var::operator= (const String& newValue) { var v (newValue); swapWith (v); return *this; } -var& var::operator= (ReferenceCountedObject* newValue) { var v (newValue); swapWith (v); return *this; } -var& var::operator= (MethodFunction newValue) { var v (newValue); swapWith (v); return *this; } +const var& var::operator= (const var& newValue) { type->cleanUp (value); type = newValue.type; type->createCopy (value, newValue.value); return *this; } +const var& var::operator= (const int newValue) { type->cleanUp (value); type = &VariantType_Int::instance; value.intValue = newValue; return *this; } +const var& var::operator= (const int64 newValue) { type->cleanUp (value); type = &VariantType_Int64::instance; value.int64Value = newValue; return *this; } +const var& var::operator= (const bool newValue) { type->cleanUp (value); type = &VariantType_Bool::instance; value.boolValue = newValue; return *this; } +const var& var::operator= (const double newValue) { type->cleanUp (value); type = &VariantType_Double::instance; value.doubleValue = newValue; return *this; } +const var& var::operator= (const char* const newValue) { var v (newValue); swapWith (v); return *this; } +const var& var::operator= (const wchar_t* const newValue) { var v (newValue); swapWith (v); return *this; } +const var& var::operator= (const String& newValue) { var v (newValue); swapWith (v); return *this; } +const var& var::operator= (ReferenceCountedObject* newValue) { var v (newValue); swapWith (v); return *this; } +const var& var::operator= (MethodFunction newValue) { var v (newValue); swapWith (v); return *this; } //============================================================================== bool var::equals (const var& other) const noexcept diff --git a/src/containers/juce_Variant.h b/src/containers/juce_Variant.h index f7296b8db9..444b136006 100644 --- a/src/containers/juce_Variant.h +++ b/src/containers/juce_Variant.h @@ -73,16 +73,16 @@ public: var (ReferenceCountedObject* object); var (MethodFunction method) noexcept; - var& operator= (const var& valueToCopy); - var& operator= (int value); - var& operator= (int64 value); - var& operator= (bool value); - var& operator= (double value); - var& operator= (const char* value); - var& operator= (const wchar_t* value); - var& operator= (const String& value); - var& operator= (ReferenceCountedObject* object); - var& operator= (MethodFunction method); + const var& operator= (const var& valueToCopy); + const var& operator= (int value); + const var& operator= (int64 value); + const var& operator= (bool value); + const var& operator= (double value); + const var& operator= (const char* value); + const var& operator= (const wchar_t* value); + const var& operator= (const String& value); + const var& operator= (ReferenceCountedObject* object); + const var& operator= (MethodFunction method); void swapWith (var& other) noexcept; diff --git a/src/core/juce_FileLogger.cpp b/src/core/juce_FileLogger.cpp index 49a7b0ee65..0625c29636 100644 --- a/src/core/juce_FileLogger.cpp +++ b/src/core/juce_FileLogger.cpp @@ -55,7 +55,7 @@ FileLogger::FileLogger (const File& logFile_, << welcomeMessage << newLine << "Log started: " << Time::getCurrentTime().toString (true, true) << newLine; - logMessage (welcome); + FileLogger::logMessage (welcome); } FileLogger::~FileLogger() diff --git a/src/gui/components/buttons/juce_ArrowButton.cpp b/src/gui/components/buttons/juce_ArrowButton.cpp index 759677b089..68ad50265d 100644 --- a/src/gui/components/buttons/juce_ArrowButton.cpp +++ b/src/gui/components/buttons/juce_ArrowButton.cpp @@ -45,7 +45,7 @@ ArrowButton::ArrowButton (const String& name, 0.5f, 0.5f)); setComponentEffect (&shadow); - buttonStateChanged(); + updateShadowAndOffset(); } ArrowButton::~ArrowButton() @@ -66,6 +66,11 @@ void ArrowButton::paintButton (Graphics& g, } void ArrowButton::buttonStateChanged() +{ + updateShadowAndOffset(); +} + +void ArrowButton::updateShadowAndOffset() { offset = (isDown()) ? 1 : 0; diff --git a/src/gui/components/buttons/juce_ArrowButton.h b/src/gui/components/buttons/juce_ArrowButton.h index 64a07cf1f3..55628fde1a 100644 --- a/src/gui/components/buttons/juce_ArrowButton.h +++ b/src/gui/components/buttons/juce_ArrowButton.h @@ -72,6 +72,8 @@ private: Path path; int offset; + void updateShadowAndOffset(); + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ArrowButton); }; diff --git a/src/gui/components/controls/juce_ComboBox.cpp b/src/gui/components/controls/juce_ComboBox.cpp index 2455ef7ada..9dab881348 100644 --- a/src/gui/components/controls/juce_ComboBox.cpp +++ b/src/gui/components/controls/juce_ComboBox.cpp @@ -59,7 +59,7 @@ ComboBox::ComboBox (const String& name) noChoicesMessage (TRANS("(no choices)")) { setRepaintsOnMouseActivity (true); - lookAndFeelChanged(); + ComboBox::lookAndFeelChanged(); currentId.addListener (this); } diff --git a/src/gui/components/controls/juce_ListBox.cpp b/src/gui/components/controls/juce_ListBox.cpp index f0fc67a3cf..49c19ce4d1 100644 --- a/src/gui/components/controls/juce_ListBox.cpp +++ b/src/gui/components/controls/juce_ListBox.cpp @@ -355,8 +355,8 @@ ListBox::ListBox (const String& name, ListBoxModel* const model_) { addAndMakeVisible (viewport = new ListViewport (*this)); - setWantsKeyboardFocus (true); - colourChanged(); + ListBox::setWantsKeyboardFocus (true); + ListBox::colourChanged(); } ListBox::~ListBox() diff --git a/src/gui/components/controls/juce_Slider.cpp b/src/gui/components/controls/juce_Slider.cpp index 2b520214b3..24699e0023 100644 --- a/src/gui/components/controls/juce_Slider.cpp +++ b/src/gui/components/controls/juce_Slider.cpp @@ -52,8 +52,7 @@ public: void paintContent (Graphics& g, int w, int h) { g.setFont (font); - g.setColour (Colours::black); - + g.setColour (findColour (TooltipWindow::textColourId, true)); g.drawFittedText (text, 0, 0, w, h, Justification::centred, 1); } @@ -130,7 +129,7 @@ Slider::Slider (const String& name) setWantsKeyboardFocus (false); setRepaintsOnMouseActivity (true); - lookAndFeelChanged(); + Slider::lookAndFeelChanged(); updateText(); currentValue.addListener (this); @@ -1029,8 +1028,7 @@ void Slider::mouseDown (const MouseEvent& e) { mouseWasHidden = false; incDecDragged = false; - mouseXWhenLastDragged = e.x; - mouseYWhenLastDragged = e.y; + mousePosWhenLastDragged = e.getPosition(); mouseDragStartX = e.getMouseDownX(); mouseDragStartY = e.getMouseDownY(); @@ -1223,8 +1221,8 @@ void Slider::mouseDrag (const MouseEvent& e) { if (style == Rotary) { - int dx = e.x - sliderRect.getCentreX(); - int dy = e.y - sliderRect.getCentreY(); + const int dx = e.x - sliderRect.getCentreX(); + const int dy = e.y - sliderRect.getCentreY(); if (dx * dx + dy * dy > 25) { @@ -1329,8 +1327,8 @@ void Slider::mouseDrag (const MouseEvent& e) { const int mouseDiff = (isHorizontal() || style == RotaryHorizontalDrag || (style == IncDecButtons && incDecDragDirectionIsHorizontal())) - ? e.x - mouseXWhenLastDragged - : e.y - mouseYWhenLastDragged; + ? e.x - mousePosWhenLastDragged.getX() + : e.y - mousePosWhenLastDragged.getY(); const double maxSpeed = jmax (200, sliderRegionSize); double speed = jlimit (0.0, maxSpeed, (double) abs (mouseDiff)); @@ -1389,8 +1387,7 @@ void Slider::mouseDrag (const MouseEvent& e) minMaxDiff = (double) valueMax.getValue() - (double) valueMin.getValue(); } - mouseXWhenLastDragged = e.x; - mouseYWhenLastDragged = e.y; + mousePosWhenLastDragged = e.getPosition(); } } diff --git a/src/gui/components/controls/juce_Slider.h b/src/gui/components/controls/juce_Slider.h index b258433d2a..5ab50aaca1 100644 --- a/src/gui/components/controls/juce_Slider.h +++ b/src/gui/components/controls/juce_Slider.h @@ -825,7 +825,8 @@ private: double velocityModeSensitivity, velocityModeOffset, minMaxDiff; int velocityModeThreshold; float rotaryStart, rotaryEnd; - int numDecimalPlaces, mouseXWhenLastDragged, mouseYWhenLastDragged; + int numDecimalPlaces; + Point mousePosWhenLastDragged; int mouseDragStartX, mouseDragStartY; int sliderRegionStart, sliderRegionSize; int sliderBeingDragged; diff --git a/src/gui/components/filebrowser/juce_FileBrowserComponent.cpp b/src/gui/components/filebrowser/juce_FileBrowserComponent.cpp index fd413218bc..a50ff81a39 100644 --- a/src/gui/components/filebrowser/juce_FileBrowserComponent.cpp +++ b/src/gui/components/filebrowser/juce_FileBrowserComponent.cpp @@ -101,19 +101,7 @@ FileBrowserComponent::FileBrowserComponent (int flags_, addAndMakeVisible (¤tPathBox); currentPathBox.setEditableText (true); - - StringArray rootNames, rootPaths; - getRoots (rootNames, rootPaths); - - for (int i = 0; i < rootNames.size(); ++i) - { - if (rootNames[i].isEmpty()) - currentPathBox.addSeparator(); - else - currentPathBox.addItem (rootNames[i], i + 1); - } - - currentPathBox.addSeparator(); + resetRecentPaths(); currentPathBox.addListener (this); addAndMakeVisible (&filenameBox); @@ -271,6 +259,24 @@ void FileBrowserComponent::setRoot (const File& newRootDirectory) && currentRoot.getParentDirectory() != currentRoot); } +void FileBrowserComponent::resetRecentPaths() +{ + currentPathBox.clear(); + + StringArray rootNames, rootPaths; + getRoots (rootNames, rootPaths); + + for (int i = 0; i < rootNames.size(); ++i) + { + if (rootNames[i].isEmpty()) + currentPathBox.addSeparator(); + else + currentPathBox.addItem (rootNames[i], i + 1); + } + + currentPathBox.addSeparator(); +} + void FileBrowserComponent::goUp() { setRoot (getRoot().getParentDirectory()); @@ -475,7 +481,7 @@ void FileBrowserComponent::comboBoxChanged (ComboBox*) void FileBrowserComponent::getRoots (StringArray& rootNames, StringArray& rootPaths) { -#if JUCE_WINDOWS + #if JUCE_WINDOWS Array roots; File::findFileSystemRoots (roots); rootPaths.clear(); @@ -511,9 +517,8 @@ void FileBrowserComponent::getRoots (StringArray& rootNames, StringArray& rootPa rootNames.add ("Documents"); rootPaths.add (File::getSpecialLocation (File::userDesktopDirectory).getFullPathName()); rootNames.add ("Desktop"); -#endif -#if JUCE_MAC + #elif JUCE_MAC rootPaths.add (File::getSpecialLocation (File::userHomeDirectory).getFullPathName()); rootNames.add ("Home folder"); rootPaths.add (File::getSpecialLocation (File::userDocumentsDirectory).getFullPathName()); @@ -538,16 +543,15 @@ void FileBrowserComponent::getRoots (StringArray& rootNames, StringArray& rootPa rootNames.add (volume.getFileName()); } } -#endif -#if JUCE_LINUX + #else rootPaths.add ("/"); rootNames.add ("/"); rootPaths.add (File::getSpecialLocation (File::userHomeDirectory).getFullPathName()); rootNames.add ("Home folder"); rootPaths.add (File::getSpecialLocation (File::userDesktopDirectory).getFullPathName()); rootNames.add ("Desktop"); -#endif + #endif } diff --git a/src/gui/components/filebrowser/juce_FileBrowserComponent.h b/src/gui/components/filebrowser/juce_FileBrowserComponent.h index 18eb47ca52..72d91315e6 100644 --- a/src/gui/components/filebrowser/juce_FileBrowserComponent.h +++ b/src/gui/components/filebrowser/juce_FileBrowserComponent.h @@ -212,6 +212,9 @@ protected: */ virtual void getRoots (StringArray& rootNames, StringArray& rootPaths); + /** Updates the items in the dropdown list of recent paths with the values from getRoots(). */ + void resetRecentPaths(); + private: //============================================================================== ScopedPointer fileList; diff --git a/src/gui/components/filebrowser/juce_FileChooserDialogBox.cpp b/src/gui/components/filebrowser/juce_FileChooserDialogBox.cpp index 9736959cbc..759f0e2817 100644 --- a/src/gui/components/filebrowser/juce_FileChooserDialogBox.cpp +++ b/src/gui/components/filebrowser/juce_FileChooserDialogBox.cpp @@ -117,7 +117,7 @@ FileChooserDialogBox::FileChooserDialogBox (const String& name, content->newFolderButton.addListener (this); content->chooserComponent.addListener (this); - selectionChanged(); + FileChooserDialogBox::selectionChanged(); } FileChooserDialogBox::~FileChooserDialogBox() diff --git a/src/gui/components/keyboard/juce_KeyPress.cpp b/src/gui/components/keyboard/juce_KeyPress.cpp index 3070d6ff46..a246542a56 100644 --- a/src/gui/components/keyboard/juce_KeyPress.cpp +++ b/src/gui/components/keyboard/juce_KeyPress.cpp @@ -127,7 +127,55 @@ namespace KeyPressHelpers { "rewind", KeyPress::rewindKey } }; - const String numberPadPrefix() { return "numpad "; } + struct ModifierDescription + { + const char* name; + int flag; + }; + + static const ModifierDescription modifierNames[] = + { + { "ctrl", ModifierKeys::ctrlModifier }, + { "control", ModifierKeys::ctrlModifier }, + { "ctl", ModifierKeys::ctrlModifier }, + { "shift", ModifierKeys::shiftModifier }, + { "shft", ModifierKeys::shiftModifier }, + { "alt", ModifierKeys::altModifier }, + { "option", ModifierKeys::altModifier }, + { "command", ModifierKeys::commandModifier }, + { "cmd", ModifierKeys::commandModifier } + }; + + const char* numberPadPrefix() noexcept { return "numpad "; } + + int getNumpadKeyCode (const String& desc) + { + if (desc.containsIgnoreCase (numberPadPrefix())) + { + const juce_wchar lastChar = desc.trimEnd().getLastCharacter(); + + switch (lastChar) + { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + return KeyPress::numberPad0 + lastChar - '0'; + + case '+': return KeyPress::numberPadAdd; + case '-': return KeyPress::numberPadSubtract; + case '*': return KeyPress::numberPadMultiply; + case '/': return KeyPress::numberPadDivide; + case '.': return KeyPress::numberPadDecimalPoint; + case '=': return KeyPress::numberPadEquals; + + default: break; + } + + if (desc.endsWith ("separator")) return KeyPress::numberPadSeparator; + if (desc.endsWith ("delete")) return KeyPress::numberPadDelete; + } + + return 0; + } } //============================================================================== @@ -135,22 +183,9 @@ const KeyPress KeyPress::createFromDescription (const String& desc) { int modifiers = 0; - if (desc.containsWholeWordIgnoreCase ("ctrl") - || desc.containsWholeWordIgnoreCase ("control") - || desc.containsWholeWordIgnoreCase ("ctl")) - modifiers |= ModifierKeys::ctrlModifier; - - if (desc.containsWholeWordIgnoreCase ("shift") - || desc.containsWholeWordIgnoreCase ("shft")) - modifiers |= ModifierKeys::shiftModifier; - - if (desc.containsWholeWordIgnoreCase ("alt") - || desc.containsWholeWordIgnoreCase ("option")) - modifiers |= ModifierKeys::altModifier; - - if (desc.containsWholeWordIgnoreCase ("command") - || desc.containsWholeWordIgnoreCase ("cmd")) - modifiers |= ModifierKeys::commandModifier; + for (int i = 0; i < numElementsInArray (KeyPressHelpers::modifierNames); ++i) + if (desc.containsWholeWordIgnoreCase (KeyPressHelpers::modifierNames[i].name)) + modifiers |= KeyPressHelpers::modifierNames[i].flag; int key = 0; @@ -164,44 +199,28 @@ const KeyPress KeyPress::createFromDescription (const String& desc) } if (key == 0) - { - // see if it's a numpad key.. - if (desc.containsIgnoreCase (KeyPressHelpers::numberPadPrefix())) - { - const juce_wchar lastChar = desc.trimEnd().getLastCharacter(); + key = KeyPressHelpers::getNumpadKeyCode (desc); - if (lastChar >= '0' && lastChar <= '9') key = numberPad0 + lastChar - '0'; - else if (lastChar == '+') key = numberPadAdd; - else if (lastChar == '-') key = numberPadSubtract; - else if (lastChar == '*') key = numberPadMultiply; - else if (lastChar == '/') key = numberPadDivide; - else if (lastChar == '.') key = numberPadDecimalPoint; - else if (lastChar == '=') key = numberPadEquals; - else if (desc.endsWith ("separator")) key = numberPadSeparator; - else if (desc.endsWith ("delete")) key = numberPadDelete; - } + if (key == 0) + { + // see if it's a function key.. + if (! desc.containsChar ('#')) // avoid mistaking hex-codes like "#f1" + for (int i = 1; i <= 12; ++i) + if (desc.containsWholeWordIgnoreCase ("f" + String (i))) + key = F1Key + i - 1; if (key == 0) { - // see if it's a function key.. - if (! desc.containsChar ('#')) // avoid mistaking hex-codes like "#f1" - for (int i = 1; i <= 12; ++i) - if (desc.containsWholeWordIgnoreCase ("f" + String (i))) - key = F1Key + i - 1; - - if (key == 0) - { - // give up and use the hex code.. - const int hexCode = desc.fromFirstOccurrenceOf ("#", false, false) - .toLowerCase() - .retainCharacters ("0123456789abcdef") - .getHexValue32(); - - if (hexCode > 0) - key = hexCode; - else - key = CharacterFunctions::toUpperCase (desc.getLastCharacter()); - } + // give up and use the hex code.. + const int hexCode = desc.fromFirstOccurrenceOf ("#", false, false) + .toLowerCase() + .retainCharacters ("0123456789abcdef") + .getHexValue32(); + + if (hexCode > 0) + key = hexCode; + else + key = CharacterFunctions::toUpperCase (desc.getLastCharacter()); } } diff --git a/src/gui/components/special/juce_AudioDeviceSelectorComponent.cpp b/src/gui/components/special/juce_AudioDeviceSelectorComponent.cpp index 04ebc87a38..6421b262fa 100644 --- a/src/gui/components/special/juce_AudioDeviceSelectorComponent.cpp +++ b/src/gui/components/special/juce_AudioDeviceSelectorComponent.cpp @@ -100,10 +100,6 @@ public: setOutlineThickness (1); } - ~MidiInputSelectorComponentListBox() - { - } - int getNumRows() { return items.size(); @@ -223,7 +219,7 @@ public: type->scanForDevices(); setup.manager->addChangeListener (this); - changeListenerCallback (nullptr); + updateAllControls(); } ~AudioDeviceSettingsPanel() @@ -398,71 +394,15 @@ public: } } - void updateControlPanelButton() + void updateAllControls() { - AudioIODevice* const currentDevice = setup.manager->getCurrentAudioDevice(); - - showUIButton = nullptr; + updateOutputsComboBox(); + updateInputsComboBox(); - if (currentDevice != nullptr && currentDevice->hasControlPanel()) - { - addAndMakeVisible (showUIButton = new TextButton (TRANS ("show this device's control panel"), - TRANS ("opens the device's own control panel"))); - showUIButton->addListener (this); - } - - resized(); - } + updateControlPanelButton(); - void changeListenerCallback (ChangeBroadcaster*) - { AudioIODevice* const currentDevice = setup.manager->getCurrentAudioDevice(); - if (setup.maxNumOutputChannels > 0 || ! type->hasSeparateInputsAndOutputs()) - { - if (outputDeviceDropDown == nullptr) - { - outputDeviceDropDown = new ComboBox (String::empty); - outputDeviceDropDown->addListener (this); - addAndMakeVisible (outputDeviceDropDown); - - outputDeviceLabel = new Label (String::empty, - type->hasSeparateInputsAndOutputs() ? TRANS ("output:") - : TRANS ("device:")); - outputDeviceLabel->attachToComponent (outputDeviceDropDown, true); - - if (setup.maxNumOutputChannels > 0) - { - addAndMakeVisible (testButton = new TextButton (TRANS ("Test"))); - testButton->addListener (this); - } - } - - addNamesToDeviceBox (*outputDeviceDropDown, false); - } - - if (setup.maxNumInputChannels > 0 && type->hasSeparateInputsAndOutputs()) - { - if (inputDeviceDropDown == nullptr) - { - inputDeviceDropDown = new ComboBox (String::empty); - inputDeviceDropDown->addListener (this); - addAndMakeVisible (inputDeviceDropDown); - - inputDeviceLabel = new Label (String::empty, TRANS ("input:")); - inputDeviceLabel->attachToComponent (inputDeviceDropDown, true); - - addAndMakeVisible (inputLevelMeter - = new SimpleDeviceManagerInputLevelMeter (setup.manager)); - } - - addNamesToDeviceBox (*inputDeviceDropDown, true); - } - - updateControlPanelButton(); - showCorrectDeviceName (inputDeviceDropDown, true); - showCorrectDeviceName (outputDeviceDropDown, false); - if (currentDevice != nullptr) { if (setup.maxNumOutputChannels > 0 @@ -505,66 +445,8 @@ public: inputChanList = nullptr; } - // sample rate.. - { - if (sampleRateDropDown == nullptr) - { - addAndMakeVisible (sampleRateDropDown = new ComboBox (String::empty)); - - sampleRateLabel = new Label (String::empty, TRANS ("sample rate:")); - sampleRateLabel->attachToComponent (sampleRateDropDown, true); - } - else - { - sampleRateDropDown->clear(); - sampleRateDropDown->removeListener (this); - } - - const int numRates = currentDevice->getNumSampleRates(); - - for (int i = 0; i < numRates; ++i) - { - const int rate = roundToInt (currentDevice->getSampleRate (i)); - sampleRateDropDown->addItem (String (rate) + " Hz", rate); - } - - sampleRateDropDown->setSelectedId (roundToInt (currentDevice->getCurrentSampleRate()), true); - sampleRateDropDown->addListener (this); - } - - // buffer size - { - if (bufferSizeDropDown == nullptr) - { - addAndMakeVisible (bufferSizeDropDown = new ComboBox (String::empty)); - - bufferSizeLabel = new Label (String::empty, TRANS ("audio buffer size:")); - bufferSizeLabel->attachToComponent (bufferSizeDropDown, true); - } - else - { - bufferSizeDropDown->clear(); - bufferSizeDropDown->removeListener (this); - } - - const int numBufferSizes = currentDevice->getNumBufferSizesAvailable(); - double currentRate = currentDevice->getCurrentSampleRate(); - if (currentRate == 0) - currentRate = 48000.0; - - for (int i = 0; i < numBufferSizes; ++i) - { - const int bs = currentDevice->getBufferSizeSamples (i); - bufferSizeDropDown->addItem (String (bs) - + " samples (" - + String (bs * 1000.0 / currentRate, 1) - + " ms)", - bs); - } - - bufferSizeDropDown->setSelectedId (currentDevice->getCurrentBufferSizeSamples(), true); - bufferSizeDropDown->addListener (this); - } + updateSampleRateComboBox (currentDevice); + updateBufferSizeComboBox (currentDevice); } else { @@ -586,6 +468,11 @@ public: setSize (getWidth(), getLowestY() + 4); } + void changeListenerCallback (ChangeBroadcaster*) + { + updateAllControls(); + } + private: AudioIODeviceType* const type; const AudioIODeviceType::DeviceSetupDetails setup; @@ -634,6 +521,133 @@ private: return y; } + void updateControlPanelButton() + { + AudioIODevice* const currentDevice = setup.manager->getCurrentAudioDevice(); + showUIButton = nullptr; + + if (currentDevice != nullptr && currentDevice->hasControlPanel()) + { + addAndMakeVisible (showUIButton = new TextButton (TRANS ("show this device's control panel"), + TRANS ("opens the device's own control panel"))); + showUIButton->addListener (this); + } + + resized(); + } + + void updateOutputsComboBox() + { + if (setup.maxNumOutputChannels > 0 || ! type->hasSeparateInputsAndOutputs()) + { + if (outputDeviceDropDown == nullptr) + { + outputDeviceDropDown = new ComboBox (String::empty); + outputDeviceDropDown->addListener (this); + addAndMakeVisible (outputDeviceDropDown); + + outputDeviceLabel = new Label (String::empty, + type->hasSeparateInputsAndOutputs() ? TRANS ("output:") + : TRANS ("device:")); + outputDeviceLabel->attachToComponent (outputDeviceDropDown, true); + + if (setup.maxNumOutputChannels > 0) + { + addAndMakeVisible (testButton = new TextButton (TRANS ("Test"))); + testButton->addListener (this); + } + } + + addNamesToDeviceBox (*outputDeviceDropDown, false); + } + + showCorrectDeviceName (outputDeviceDropDown, false); + } + + void updateInputsComboBox() + { + if (setup.maxNumInputChannels > 0 && type->hasSeparateInputsAndOutputs()) + { + if (inputDeviceDropDown == nullptr) + { + inputDeviceDropDown = new ComboBox (String::empty); + inputDeviceDropDown->addListener (this); + addAndMakeVisible (inputDeviceDropDown); + + inputDeviceLabel = new Label (String::empty, TRANS ("input:")); + inputDeviceLabel->attachToComponent (inputDeviceDropDown, true); + + addAndMakeVisible (inputLevelMeter + = new SimpleDeviceManagerInputLevelMeter (setup.manager)); + } + + addNamesToDeviceBox (*inputDeviceDropDown, true); + } + + showCorrectDeviceName (inputDeviceDropDown, true); + } + + void updateSampleRateComboBox (AudioIODevice* currentDevice) + { + if (sampleRateDropDown == nullptr) + { + addAndMakeVisible (sampleRateDropDown = new ComboBox (String::empty)); + + sampleRateLabel = new Label (String::empty, TRANS ("sample rate:")); + sampleRateLabel->attachToComponent (sampleRateDropDown, true); + } + else + { + sampleRateDropDown->clear(); + sampleRateDropDown->removeListener (this); + } + + const int numRates = currentDevice->getNumSampleRates(); + + for (int i = 0; i < numRates; ++i) + { + const int rate = roundToInt (currentDevice->getSampleRate (i)); + sampleRateDropDown->addItem (String (rate) + " Hz", rate); + } + + sampleRateDropDown->setSelectedId (roundToInt (currentDevice->getCurrentSampleRate()), true); + sampleRateDropDown->addListener (this); + } + + void updateBufferSizeComboBox (AudioIODevice* currentDevice) + { + if (bufferSizeDropDown == nullptr) + { + addAndMakeVisible (bufferSizeDropDown = new ComboBox (String::empty)); + + bufferSizeLabel = new Label (String::empty, TRANS ("audio buffer size:")); + bufferSizeLabel->attachToComponent (bufferSizeDropDown, true); + } + else + { + bufferSizeDropDown->clear(); + bufferSizeDropDown->removeListener (this); + } + + const int numBufferSizes = currentDevice->getNumBufferSizesAvailable(); + double currentRate = currentDevice->getCurrentSampleRate(); + if (currentRate == 0) + currentRate = 48000.0; + + for (int i = 0; i < numBufferSizes; ++i) + { + const int bs = currentDevice->getBufferSizeSamples (i); + bufferSizeDropDown->addItem (String (bs) + + " samples (" + + String (bs * 1000.0 / currentRate, 1) + + " ms)", + bs); + } + + bufferSizeDropDown->setSelectedId (currentDevice->getCurrentBufferSizeSamples(), true); + bufferSizeDropDown->addListener (this); + } + public: //============================================================================== class ChannelSelectorListBox : public ListBox, @@ -660,10 +674,6 @@ public: setOutlineThickness (1); } - ~ChannelSelectorListBox() - { - } - void refresh() { items.clear(); @@ -712,10 +722,7 @@ public: return items.size(); } - void paintListBoxItem (int row, - Graphics& g, - int width, int height, - bool rowIsSelected) + void paintListBoxItem (int row, Graphics& g, int width, int height, bool rowIsSelected) { if (isPositiveAndBelow (row, items.size())) { @@ -969,7 +976,7 @@ AudioDeviceSelectorComponent::AudioDeviceSelectorComponent (AudioDeviceManager& } deviceManager_.addChangeListener (this); - changeListenerCallback (nullptr); + updateAllControls(); } AudioDeviceSelectorComponent::~AudioDeviceSelectorComponent() @@ -1040,7 +1047,7 @@ void AudioDeviceSelectorComponent::comboBoxChanged (ComboBox* comboBoxThatHasCha deviceManager.setCurrentAudioDeviceType (type->getTypeName(), true); - changeListenerCallback (nullptr); // needed in case the type hasn't actally changed + updateAllControls(); // needed in case the type hasn't actally changed } } else if (comboBoxThatHasChanged == midiOutputSelector) @@ -1050,11 +1057,14 @@ void AudioDeviceSelectorComponent::comboBoxChanged (ComboBox* comboBoxThatHasCha } void AudioDeviceSelectorComponent::changeListenerCallback (ChangeBroadcaster*) +{ + updateAllControls(); +} + +void AudioDeviceSelectorComponent::updateAllControls() { if (deviceTypeDropDown != nullptr) - { deviceTypeDropDown->setText (deviceManager.getCurrentAudioDeviceType(), false); - } if (audioDeviceSettingsComp == nullptr || audioDeviceSettingsCompType != deviceManager.getCurrentAudioDeviceType()) diff --git a/src/gui/components/special/juce_AudioDeviceSelectorComponent.h b/src/gui/components/special/juce_AudioDeviceSelectorComponent.h index 14b0b7dbff..955e37d53a 100644 --- a/src/gui/components/special/juce_AudioDeviceSelectorComponent.h +++ b/src/gui/components/special/juce_AudioDeviceSelectorComponent.h @@ -107,6 +107,8 @@ private: ScopedPointer midiOutputSelector; ScopedPointer