| @@ -932,7 +932,9 @@ public: | |||
| return namesCopy; | |||
| } | |||
| const String getDefaultDeviceName (const bool /*preferInputNames*/) const | |||
| const String getDefaultDeviceName (const bool /*preferInputNames*/, | |||
| const int /*numInputChannelsNeeded*/, | |||
| const int /*numOutputChannelsNeeded*/) const | |||
| { | |||
| jassert (hasScanned); // need to call scanForDevices() before doing this | |||
| @@ -751,12 +751,12 @@ public: | |||
| int getOutputLatencyInSamples() | |||
| { | |||
| return outputLatency; | |||
| return outputLatency + currentBlockSizeSamples / 4; | |||
| } | |||
| int getInputLatencyInSamples() | |||
| { | |||
| return inputLatency; | |||
| return inputLatency + currentBlockSizeSamples / 4; | |||
| } | |||
| void start (AudioIODeviceCallback* callback) | |||
| @@ -1809,7 +1809,9 @@ public: | |||
| return deviceNames; | |||
| } | |||
| const String getDefaultDeviceName (const bool /*preferInputNames*/) const | |||
| const String getDefaultDeviceName (const bool /*preferInputNames*/, | |||
| const int /*numInputChannelsNeeded*/, | |||
| const int /*numOutputChannelsNeeded*/) const | |||
| { | |||
| jassert (hasScanned); // need to call scanForDevices() before doing this | |||
| @@ -1477,7 +1477,9 @@ public: | |||
| : outputDeviceNames; | |||
| } | |||
| const String getDefaultDeviceName (const bool preferInputNames) const | |||
| const String getDefaultDeviceName (const bool preferInputNames, | |||
| const int /*numInputChannelsNeeded*/, | |||
| const int /*numOutputChannelsNeeded*/) const | |||
| { | |||
| jassert (hasScanned); // need to call scanForDevices() before doing this | |||
| @@ -11,6 +11,7 @@ Changelist for version 1.46 | |||
| - added AudioUnit support to the audio hosting code | |||
| - any top-level components will now have their parentSizeChanged() method called when the screen res is changed (not on linux yet though..) | |||
| - jucer: added support for ImageButtons | |||
| - audio devices - a few tweaks to the various audio drivers to try to make the best possible guess at the input and output latencies that they introduce | |||
| ============================================================================== | |||
| Changelist for version 1.45 | |||
| @@ -118,7 +118,9 @@ const String AudioDeviceManager::initialise (const int numInputChannelsNeeded, | |||
| String defaultDevice; | |||
| if (availableDeviceTypes [0] != 0) | |||
| defaultDevice = availableDeviceTypes[0]->getDefaultDeviceName (numOutputChannelsNeeded == 0); | |||
| defaultDevice = availableDeviceTypes[0]->getDefaultDeviceName (numOutputChannelsNeeded == 0, | |||
| numInputChannelsNeeded, | |||
| numOutputChannelsNeeded); | |||
| return setAudioDevice (defaultDevice, 0, 0, 0, 0, false); | |||
| } | |||
| @@ -49,10 +49,15 @@ AudioIODeviceType::~AudioIODeviceType() | |||
| //============================================================================== | |||
| extern AudioIODeviceType* juce_createDefaultAudioIODeviceType(); | |||
| #if JUCE_ASIO && JUCE_WIN32 | |||
| #if JUCE_WIN32 && JUCE_ASIO | |||
| extern AudioIODeviceType* juce_createASIOAudioIODeviceType(); | |||
| #endif | |||
| #if JUCE_WIN32 && JUCE_WDM_AUDIO | |||
| extern AudioIODeviceType* juce_createWDMAudioIODeviceType(); | |||
| #endif | |||
| //============================================================================== | |||
| void AudioIODeviceType::createDeviceTypes (OwnedArray <AudioIODeviceType>& list) | |||
| { | |||
| AudioIODeviceType* const defaultDeviceType = juce_createDefaultAudioIODeviceType(); | |||
| @@ -60,9 +65,13 @@ void AudioIODeviceType::createDeviceTypes (OwnedArray <AudioIODeviceType>& list) | |||
| if (defaultDeviceType != 0) | |||
| list.add (defaultDeviceType); | |||
| #if JUCE_ASIO && JUCE_WIN32 | |||
| #if JUCE_WIN32 && JUCE_ASIO | |||
| list.add (juce_createASIOAudioIODeviceType()); | |||
| #endif | |||
| #if JUCE_WIN32 && JUCE_WDM_AUDIO | |||
| list.add (juce_createWDMAudioIODeviceType()); | |||
| #endif | |||
| } | |||
| @@ -117,8 +117,14 @@ public: | |||
| @param preferInputNames only really used by DirectSound where devices are split up | |||
| into inputs and outputs, this indicates whether to use | |||
| the input or output name to refer to a pair of devices. | |||
| @param numInputChannelsNeeded the number of input channels the user is expecting to need - this | |||
| may be used to help decide which device would be most suitable | |||
| @param numOutputChannelsNeeded the number of output channels the user is expecting to need - this | |||
| may be used to help decide which device would be most suitable | |||
| */ | |||
| virtual const String getDefaultDeviceName (const bool preferInputNames = false) const = 0; | |||
| virtual const String getDefaultDeviceName (const bool preferInputNames, | |||
| const int numInputChannelsNeeded, | |||
| const int numOutputChannelsNeeded) const = 0; | |||
| /** Creates one of the devices of this type. | |||
| @@ -37,25 +37,31 @@ BEGIN_JUCE_NAMESPACE | |||
| //============================================================================== | |||
| void AudioDataConverters::convertFloatToInt16LE (const float* source, void* dest, int numSamples) | |||
| void AudioDataConverters::convertFloatToInt16LE (const float* source, void* dest, int numSamples, const int destBytesPerSample) | |||
| { | |||
| const double maxVal = (double) 0x7fff; | |||
| uint16* const intData = (uint16*) dest; | |||
| char* intData = (char*) dest; | |||
| for (int i = 0; i < numSamples; ++i) | |||
| intData[i] = swapIfBigEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); | |||
| { | |||
| *(uint16*)intData = swapIfBigEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); | |||
| intData += destBytesPerSample; | |||
| } | |||
| } | |||
| void AudioDataConverters::convertFloatToInt16BE (const float* source, void* dest, int numSamples) | |||
| void AudioDataConverters::convertFloatToInt16BE (const float* source, void* dest, int numSamples, const int destBytesPerSample) | |||
| { | |||
| const double maxVal = (double) 0x7fff; | |||
| uint16* const intData = (uint16*) dest; | |||
| char* intData = (char*) dest; | |||
| for (int i = 0; i < numSamples; ++i) | |||
| intData[i] = swapIfLittleEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); | |||
| { | |||
| *(uint16*)intData = swapIfLittleEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); | |||
| intData += destBytesPerSample; | |||
| } | |||
| } | |||
| void AudioDataConverters::convertFloatToInt24LE (const float* source, void* dest, int numSamples) | |||
| void AudioDataConverters::convertFloatToInt24LE (const float* source, void* dest, int numSamples, const int destBytesPerSample) | |||
| { | |||
| const double maxVal = (double) 0x7fffff; | |||
| char* intData = (char*) dest; | |||
| @@ -63,11 +69,11 @@ void AudioDataConverters::convertFloatToInt24LE (const float* source, void* dest | |||
| for (int i = 0; i < numSamples; ++i) | |||
| { | |||
| littleEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData); | |||
| intData += 3; | |||
| intData += destBytesPerSample; | |||
| } | |||
| } | |||
| void AudioDataConverters::convertFloatToInt24BE (const float* source, void* dest, int numSamples) | |||
| void AudioDataConverters::convertFloatToInt24BE (const float* source, void* dest, int numSamples, const int destBytesPerSample) | |||
| { | |||
| const double maxVal = (double) 0x7fffff; | |||
| char* intData = (char*) dest; | |||
| @@ -75,119 +81,174 @@ void AudioDataConverters::convertFloatToInt24BE (const float* source, void* dest | |||
| for (int i = 0; i < numSamples; ++i) | |||
| { | |||
| bigEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData); | |||
| intData += 3; | |||
| intData += destBytesPerSample; | |||
| } | |||
| } | |||
| void AudioDataConverters::convertFloatToInt32LE (const float* source, void* dest, int numSamples) | |||
| void AudioDataConverters::convertFloatToInt32LE (const float* source, void* dest, int numSamples, const int destBytesPerSample) | |||
| { | |||
| const double maxVal = (double) 0x7fffffff; | |||
| uint32* const intData = (uint32*) dest; | |||
| char* intData = (char*) dest; | |||
| for (int i = 0; i < numSamples; ++i) | |||
| intData[i] = swapIfBigEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); | |||
| { | |||
| *(uint32*)intData = swapIfBigEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); | |||
| intData += destBytesPerSample; | |||
| } | |||
| } | |||
| void AudioDataConverters::convertFloatToInt32BE (const float* source, void* dest, int numSamples) | |||
| void AudioDataConverters::convertFloatToInt32BE (const float* source, void* dest, int numSamples, const int destBytesPerSample) | |||
| { | |||
| const double maxVal = (double) 0x7fffffff; | |||
| uint32* const intData = (uint32*) dest; | |||
| char* intData = (char*) dest; | |||
| for (int i = 0; i < numSamples; ++i) | |||
| intData[i] = swapIfLittleEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); | |||
| { | |||
| *(uint32*)intData = swapIfLittleEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); | |||
| intData += destBytesPerSample; | |||
| } | |||
| } | |||
| void AudioDataConverters::convertFloatToFloat32LE (const float* source, void* dest, int numSamples) | |||
| void AudioDataConverters::convertFloatToFloat32LE (const float* source, void* dest, int numSamples, const int destBytesPerSample) | |||
| { | |||
| if (source != (const float*) dest) | |||
| memcpy (dest, source, numSamples * sizeof (float)); | |||
| #if JUCE_BIG_ENDIAN | |||
| uint32* const data = (uint32*) dest; | |||
| char* d = (char*) dest; | |||
| for (int i = 0; i < numSamples; ++i) | |||
| data[i] = swapByteOrder (data [i]); | |||
| { | |||
| *(float*)d = source[i]; | |||
| #if JUCE_BIG_ENDIAN | |||
| *(uint32*)d = swapByteOrder (*(uint32*)d); | |||
| #endif | |||
| d += destBytesPerSample; | |||
| } | |||
| } | |||
| void AudioDataConverters::convertFloatToFloat32BE (const float* source, void* dest, int numSamples) | |||
| void AudioDataConverters::convertFloatToFloat32BE (const float* source, void* dest, int numSamples, const int destBytesPerSample) | |||
| { | |||
| if (source != (const float*) dest) | |||
| memcpy (dest, source, numSamples * sizeof (float)); | |||
| #if JUCE_LITTLE_ENDIAN | |||
| uint32* const data = (uint32*) dest; | |||
| char* d = (char*) dest; | |||
| for (int i = 0; i < numSamples; ++i) | |||
| data[i] = swapByteOrder (data [i]); | |||
| { | |||
| *(float*)d = source[i]; | |||
| #if JUCE_LITTLE_ENDIAN | |||
| *(uint32*)d = swapByteOrder (*(uint32*)d); | |||
| #endif | |||
| d += destBytesPerSample; | |||
| } | |||
| } | |||
| //============================================================================== | |||
| void AudioDataConverters::convertInt16LEToFloat (const void* const source, float* const dest, int numSamples) | |||
| void AudioDataConverters::convertInt16LEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) | |||
| { | |||
| const float scale = 1.0f / 0x7fff; | |||
| uint16* const intData = (uint16*) source; | |||
| const char* intData = (const char*) source; | |||
| while (--numSamples >= 0) | |||
| dest [numSamples] = scale * (short) swapIfBigEndian (intData [numSamples]); | |||
| for (int i = 0; i < numSamples; ++i) | |||
| { | |||
| dest[i] = scale * (short) swapIfBigEndian (*(uint16*)intData); | |||
| intData += srcBytesPerSample; | |||
| } | |||
| } | |||
| void AudioDataConverters::convertInt16BEToFloat (const void* const source, float* const dest, int numSamples) | |||
| void AudioDataConverters::convertInt16BEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) | |||
| { | |||
| const float scale = 1.0f / 0x7fff; | |||
| uint16* const intData = (uint16*) source; | |||
| const char* intData = (const char*) source; | |||
| while (--numSamples >= 0) | |||
| dest [numSamples] = scale * (short) swapIfLittleEndian (intData [numSamples]); | |||
| for (int i = 0; i < numSamples; ++i) | |||
| { | |||
| dest[i] = scale * (short) swapIfLittleEndian (*(uint16*)intData); | |||
| intData += srcBytesPerSample; | |||
| } | |||
| } | |||
| void AudioDataConverters::convertInt24LEToFloat (const void* const source, float* const dest, int numSamples) | |||
| void AudioDataConverters::convertInt24LEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) | |||
| { | |||
| const float scale = 1.0f / 0x7fffff; | |||
| char* const intData = (char*) source; | |||
| const char* intData = (const char*) source; | |||
| while (--numSamples >= 0) | |||
| dest [numSamples] = scale * littleEndian24Bit (intData + (numSamples + numSamples + numSamples)); | |||
| for (int i = 0; i < numSamples; ++i) | |||
| { | |||
| dest[i] = scale * (short) littleEndian24Bit (intData); | |||
| intData += srcBytesPerSample; | |||
| } | |||
| } | |||
| void AudioDataConverters::convertInt24BEToFloat (const void* const source, float* const dest, int numSamples) | |||
| void AudioDataConverters::convertInt24BEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) | |||
| { | |||
| const float scale = 1.0f / 0x7fffff; | |||
| char* const intData = (char*) source; | |||
| const char* intData = (const char*) source; | |||
| while (--numSamples >= 0) | |||
| dest [numSamples] = scale * bigEndian24Bit (intData + (numSamples + numSamples + numSamples)); | |||
| for (int i = 0; i < numSamples; ++i) | |||
| { | |||
| dest[i] = scale * (short) bigEndian24Bit (intData); | |||
| intData += srcBytesPerSample; | |||
| } | |||
| } | |||
| void AudioDataConverters::convertInt32LEToFloat (const void* const source, float* const dest, int numSamples) | |||
| void AudioDataConverters::convertInt32LEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) | |||
| { | |||
| const float scale = 1.0f / 0x7fffffff; | |||
| uint32* const intData = (uint32*) source; | |||
| const char* intData = (const char*) source; | |||
| for (int i = 0; i < numSamples; ++i) | |||
| dest [numSamples] = scale * (int) swapIfBigEndian (intData [numSamples]); | |||
| { | |||
| dest[i] = scale * (int) swapIfBigEndian (*(uint32*) intData); | |||
| intData += srcBytesPerSample; | |||
| } | |||
| } | |||
| void AudioDataConverters::convertInt32BEToFloat (const void* const source, float* const dest, int numSamples) | |||
| void AudioDataConverters::convertInt32BEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) | |||
| { | |||
| const float scale = 1.0f / 0x7fffffff; | |||
| uint32* const intData = (uint32*) source; | |||
| const char* intData = (const char*) source; | |||
| for (int i = 0; i < numSamples; ++i) | |||
| dest [numSamples] = scale * (int) swapIfLittleEndian (intData [numSamples]); | |||
| { | |||
| dest[i] = scale * (int) (swapIfLittleEndian (*(uint32*) intData)); | |||
| intData += srcBytesPerSample; | |||
| } | |||
| } | |||
| void AudioDataConverters::convertFloat32LEToFloat (const void* const source, float* const dest, int numSamples) | |||
| void AudioDataConverters::convertFloat32LEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) | |||
| { | |||
| convertFloatToFloat32LE ((float*) source, dest, numSamples); | |||
| const char* s = (const char*) source; | |||
| for (int i = 0; i < numSamples; ++i) | |||
| { | |||
| dest[i] = *(float*)s; | |||
| #if JUCE_BIG_ENDIAN | |||
| uint32* const d = (uint32*) (dest + i); | |||
| *d = swapByteOrder (*d); | |||
| #endif | |||
| s += srcBytesPerSample; | |||
| } | |||
| } | |||
| void AudioDataConverters::convertFloat32BEToFloat (const void* const source, float* const dest, int numSamples) | |||
| void AudioDataConverters::convertFloat32BEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) | |||
| { | |||
| convertFloatToFloat32BE ((float*) source, dest, numSamples); | |||
| const char* s = (const char*) source; | |||
| for (int i = 0; i < numSamples; ++i) | |||
| { | |||
| dest[i] = *(float*)s; | |||
| #if JUCE_LITTLE_ENDIAN | |||
| uint32* const d = (uint32*) (dest + i); | |||
| *d = swapByteOrder (*d); | |||
| #endif | |||
| s += srcBytesPerSample; | |||
| } | |||
| } | |||
| //============================================================================== | |||
| void AudioDataConverters::convertFloatToFormat (const DataFormat destFormat, | |||
| const float* const source, | |||
| @@ -43,30 +43,30 @@ class JUCE_API AudioDataConverters | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| static void convertFloatToInt16LE (const float* source, void* dest, int numSamples); | |||
| static void convertFloatToInt16BE (const float* source, void* dest, int numSamples); | |||
| static void convertFloatToInt16LE (const float* source, void* dest, int numSamples, const int destBytesPerSample = 2); | |||
| static void convertFloatToInt16BE (const float* source, void* dest, int numSamples, const int destBytesPerSample = 2); | |||
| static void convertFloatToInt24LE (const float* source, void* dest, int numSamples); | |||
| static void convertFloatToInt24BE (const float* source, void* dest, int numSamples); | |||
| static void convertFloatToInt24LE (const float* source, void* dest, int numSamples, const int destBytesPerSample = 3); | |||
| static void convertFloatToInt24BE (const float* source, void* dest, int numSamples, const int destBytesPerSample = 3); | |||
| static void convertFloatToInt32LE (const float* source, void* dest, int numSamples); | |||
| static void convertFloatToInt32BE (const float* source, void* dest, int numSamples); | |||
| static void convertFloatToInt32LE (const float* source, void* dest, int numSamples, const int destBytesPerSample = 4); | |||
| static void convertFloatToInt32BE (const float* source, void* dest, int numSamples, const int destBytesPerSample = 4); | |||
| static void convertFloatToFloat32LE (const float* source, void* dest, int numSamples); | |||
| static void convertFloatToFloat32BE (const float* source, void* dest, int numSamples); | |||
| static void convertFloatToFloat32LE (const float* source, void* dest, int numSamples, const int destBytesPerSample = 4); | |||
| static void convertFloatToFloat32BE (const float* source, void* dest, int numSamples, const int destBytesPerSample = 4); | |||
| //============================================================================== | |||
| static void convertInt16LEToFloat (const void* source, float* dest, int numSamples); | |||
| static void convertInt16BEToFloat (const void* source, float* dest, int numSamples); | |||
| static void convertInt16LEToFloat (const void* source, float* dest, int numSamples, const int srcBytesPerSample = 2); | |||
| static void convertInt16BEToFloat (const void* source, float* dest, int numSamples, const int srcBytesPerSample = 2); | |||
| static void convertInt24LEToFloat (const void* source, float* dest, int numSamples); | |||
| static void convertInt24BEToFloat (const void* source, float* dest, int numSamples); | |||
| static void convertInt24LEToFloat (const void* source, float* dest, int numSamples, const int srcBytesPerSample = 3); | |||
| static void convertInt24BEToFloat (const void* source, float* dest, int numSamples, const int srcBytesPerSample = 3); | |||
| static void convertInt32LEToFloat (const void* source, float* dest, int numSamples); | |||
| static void convertInt32BEToFloat (const void* source, float* dest, int numSamples); | |||
| static void convertInt32LEToFloat (const void* source, float* dest, int numSamples, const int srcBytesPerSample = 4); | |||
| static void convertInt32BEToFloat (const void* source, float* dest, int numSamples, const int srcBytesPerSample = 4); | |||
| static void convertFloat32LEToFloat (const void* source, float* dest, int numSamples); | |||
| static void convertFloat32BEToFloat (const void* source, float* dest, int numSamples); | |||
| static void convertFloat32LEToFloat (const void* source, float* dest, int numSamples, const int srcBytesPerSample = 4); | |||
| static void convertFloat32BEToFloat (const void* source, float* dest, int numSamples, const int srcBytesPerSample = 4); | |||
| //============================================================================== | |||
| enum DataFormat | |||
| @@ -132,14 +132,8 @@ FileBrowserComponent::FileBrowserComponent (FileChooserMode mode_, | |||
| addAndMakeVisible (label); | |||
| label->attachToComponent (filenameBox, true); | |||
| addAndMakeVisible (goUpButton = new DrawableButton ("up", DrawableButton::ImageOnButtonBackground)); | |||
| Path arrowPath; | |||
| arrowPath.addArrow (50.0f, 100.0f, 50.0f, 0.0, 40.0f, 100.0f, 50.0f); | |||
| DrawablePath arrowImage; | |||
| arrowImage.setSolidFill (Colours::black.withAlpha (0.4f)); | |||
| arrowImage.setPath (arrowPath); | |||
| goUpButton->setImages (&arrowImage); | |||
| addAndMakeVisible (goUpButton = getLookAndFeel().createFileBrowserGoUpButton()); | |||
| goUpButton->addButtonListener (this); | |||
| goUpButton->setTooltip (TRANS ("go up to parent directory")); | |||
| @@ -275,33 +269,10 @@ FilePreviewComponent* FileBrowserComponent::getPreviewComponent() const throw() | |||
| //============================================================================== | |||
| void FileBrowserComponent::resized() | |||
| { | |||
| const int x = 8; | |||
| int w = getWidth() - x - x; | |||
| if (previewComp != 0) | |||
| { | |||
| const int previewWidth = w / 3; | |||
| previewComp->setBounds (x + w - previewWidth, 0, previewWidth, getHeight()); | |||
| w -= previewWidth + 4; | |||
| } | |||
| int y = 4; | |||
| const int controlsHeight = 22; | |||
| const int bottomSectionHeight = controlsHeight + 8; | |||
| const int upButtonWidth = 50; | |||
| currentPathBox->setBounds (x, y, w - upButtonWidth - 6, controlsHeight); | |||
| goUpButton->setBounds (x + w - upButtonWidth, y, upButtonWidth, controlsHeight); | |||
| y += controlsHeight + 4; | |||
| Component* const listAsComp = dynamic_cast <Component*> (fileListComponent); | |||
| listAsComp->setBounds (x, y, w, getHeight() - y - bottomSectionHeight); | |||
| y = listAsComp->getBottom() + 4; | |||
| filenameBox->setBounds (x + 50, y, w - 50, controlsHeight); | |||
| getLookAndFeel() | |||
| .layoutFileBrowserComponent (*this, fileListComponent, | |||
| previewComp, currentPathBox, | |||
| filenameBox, goUpButton); | |||
| } | |||
| //============================================================================== | |||
| @@ -200,7 +200,7 @@ private: | |||
| FilePreviewComponent* previewComp; | |||
| ComboBox* currentPathBox; | |||
| TextEditor* filenameBox; | |||
| DrawableButton* goUpButton; | |||
| Button* goUpButton; | |||
| TimeSliceThread thread; | |||
| @@ -39,8 +39,6 @@ BEGIN_JUCE_NAMESPACE | |||
| //============================================================================== | |||
| const int spaceAroundImage = 4; | |||
| TabBarButton::TabBarButton (const String& name, | |||
| TabbedButtonBar* const owner_, | |||
| const int index) | |||
| @@ -128,6 +126,8 @@ void TabBarButton::getActiveArea (int& x, int& y, int& w, int& h) | |||
| int r = getWidth(); | |||
| int b = getHeight(); | |||
| const int spaceAroundImage = getLookAndFeel().getTabButtonSpaceAroundImage(); | |||
| if (owner->getOrientation() != TabbedButtonBar::TabsAtLeft) | |||
| r -= spaceAroundImage; | |||
| @@ -377,7 +377,8 @@ void TabbedButtonBar::resized() | |||
| if (orientation == TabsAtTop || orientation == TabsAtBottom) | |||
| swapVariables (depth, length); | |||
| const int overlap = getLookAndFeel().getTabButtonOverlap (depth) + spaceAroundImage * 2; | |||
| const int overlap = getLookAndFeel().getTabButtonOverlap (depth) | |||
| + getLookAndFeel().getTabButtonSpaceAroundImage() * 2; | |||
| int i, totalLength = overlap; | |||
| int numVisibleButtons = tabs.size(); | |||
| @@ -57,6 +57,7 @@ BEGIN_JUCE_NAMESPACE | |||
| #include "../filebrowser/juce_FilenameComponent.h" | |||
| #include "../filebrowser/juce_DirectoryContentsDisplayComponent.h" | |||
| #include "../filebrowser/juce_FileSearchPathListComponent.h" | |||
| #include "../filebrowser/juce_FileBrowserComponent.h" | |||
| #include "../layout/juce_GroupComponent.h" | |||
| #include "../properties/juce_PropertyComponent.h" | |||
| #include "../juce_Desktop.h" | |||
| @@ -1790,6 +1791,11 @@ int LookAndFeel::getTabButtonOverlap (int tabDepth) | |||
| return 1 + tabDepth / 3; | |||
| } | |||
| int LookAndFeel::getTabButtonSpaceAroundImage() | |||
| { | |||
| return 4; | |||
| } | |||
| void LookAndFeel::createTabButtonShape (Path& p, | |||
| int width, int height, | |||
| int /*tabIndex*/, | |||
| @@ -2323,6 +2329,58 @@ void LookAndFeel::drawFileBrowserRow (Graphics& g, int width, int height, | |||
| } | |||
| } | |||
| Button* LookAndFeel::createFileBrowserGoUpButton() | |||
| { | |||
| DrawableButton* goUpButton = new DrawableButton ("up", DrawableButton::ImageOnButtonBackground); | |||
| Path arrowPath; | |||
| arrowPath.addArrow (50.0f, 100.0f, 50.0f, 0.0, 40.0f, 100.0f, 50.0f); | |||
| DrawablePath arrowImage; | |||
| arrowImage.setSolidFill (Colours::black.withAlpha (0.4f)); | |||
| arrowImage.setPath (arrowPath); | |||
| goUpButton->setImages (&arrowImage); | |||
| return goUpButton; | |||
| } | |||
| void LookAndFeel::layoutFileBrowserComponent (FileBrowserComponent& browserComp, | |||
| DirectoryContentsDisplayComponent* fileListComponent, | |||
| FilePreviewComponent* previewComp, | |||
| ComboBox* currentPathBox, | |||
| TextEditor* filenameBox, | |||
| Button* goUpButton) | |||
| { | |||
| const int x = 8; | |||
| int w = browserComp.getWidth() - x - x; | |||
| if (previewComp != 0) | |||
| { | |||
| const int previewWidth = w / 3; | |||
| previewComp->setBounds (x + w - previewWidth, 0, previewWidth, browserComp.getHeight()); | |||
| w -= previewWidth + 4; | |||
| } | |||
| int y = 4; | |||
| const int controlsHeight = 22; | |||
| const int bottomSectionHeight = controlsHeight + 8; | |||
| const int upButtonWidth = 50; | |||
| currentPathBox->setBounds (x, y, w - upButtonWidth - 6, controlsHeight); | |||
| goUpButton->setBounds (x + w - upButtonWidth, y, upButtonWidth, controlsHeight); | |||
| y += controlsHeight + 4; | |||
| Component* const listAsComp = dynamic_cast <Component*> (fileListComponent); | |||
| listAsComp->setBounds (x, y, w, browserComp.getHeight() - y - bottomSectionHeight); | |||
| y = listAsComp->getBottom() + 4; | |||
| filenameBox->setBounds (x + 50, y, w - 50, controlsHeight); | |||
| } | |||
| Image* LookAndFeel::getDefaultFolderImage() | |||
| { | |||
| static const unsigned char foldericon_png[] = { 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,32,0,0,0,28,8,6,0,0,0,0,194,189,34,0,0,0,4,103,65,77,65,0,0,175,200,55,5, | |||
| @@ -58,6 +58,9 @@ class Toolbar; | |||
| class ToolbarItemComponent; | |||
| class PopupMenu; | |||
| class ProgressBar; | |||
| class FileBrowserComponent; | |||
| class DirectoryContentsDisplayComponent; | |||
| class FilePreviewComponent; | |||
| //============================================================================== | |||
| @@ -262,6 +265,15 @@ public: | |||
| const bool isDirectory, | |||
| const bool isItemSelected); | |||
| virtual Button* createFileBrowserGoUpButton(); | |||
| virtual void layoutFileBrowserComponent (FileBrowserComponent& browserComp, | |||
| DirectoryContentsDisplayComponent* fileListComponent, | |||
| FilePreviewComponent* previewComp, | |||
| ComboBox* currentPathBox, | |||
| TextEditor* filenameBox, | |||
| Button* goUpButton); | |||
| //============================================================================== | |||
| virtual void drawBubble (Graphics& g, | |||
| float tipX, float tipY, | |||
| @@ -449,6 +461,7 @@ public: | |||
| const bool isFrontTab); | |||
| virtual int getTabButtonOverlap (int tabDepth); | |||
| virtual int getTabButtonSpaceAroundImage(); | |||
| virtual int getTabButtonBestWidth (int tabIndex, | |||
| const String& text, | |||
| @@ -361,7 +361,6 @@ public: | |||
| if (menu.items.size() > 0) | |||
| { | |||
| int totalItems = 0; | |||
| bool lastItemWasSeparator = true; | |||
| PopupMenuWindow* const mw = new PopupMenuWindow(); | |||
| mw->setLookAndFeel (menu.lookAndFeel); | |||
| @@ -375,30 +374,8 @@ public: | |||
| { | |||
| MenuItemInfo* const item = (MenuItemInfo*) menu.items.getUnchecked(i); | |||
| if (item->isSeparator) | |||
| { | |||
| if (! lastItemWasSeparator) | |||
| { | |||
| // check it's not one of the last separators.. | |||
| for (int j = i + 1; j < menu.items.size(); ++j) | |||
| { | |||
| if (! ((MenuItemInfo*) menu.items.getUnchecked (j))->isSeparator) | |||
| { | |||
| mw->addItem (*item); | |||
| ++totalItems; | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| else | |||
| { | |||
| mw->addItem (*item); | |||
| ++totalItems; | |||
| } | |||
| lastItemWasSeparator = item->isSeparator; | |||
| mw->addItem (*item); | |||
| ++totalItems; | |||
| } | |||
| if (totalItems == 0) | |||
| @@ -1321,13 +1298,15 @@ private: | |||
| //============================================================================== | |||
| PopupMenu::PopupMenu() throw() | |||
| : items (8), | |||
| lookAndFeel (0) | |||
| lookAndFeel (0), | |||
| separatorPending (false) | |||
| { | |||
| } | |||
| PopupMenu::PopupMenu (const PopupMenu& other) throw() | |||
| : items (8), | |||
| lookAndFeel (other.lookAndFeel) | |||
| lookAndFeel (other.lookAndFeel), | |||
| separatorPending (false) | |||
| { | |||
| items.ensureStorageAllocated (other.items.size()); | |||
| @@ -1365,6 +1344,18 @@ void PopupMenu::clear() throw() | |||
| } | |||
| items.clear(); | |||
| separatorPending = false; | |||
| } | |||
| void PopupMenu::addSeparatorIfPending() | |||
| { | |||
| if (separatorPending) | |||
| { | |||
| separatorPending = false; | |||
| if (items.size() > 0) | |||
| items.add (new MenuItemInfo()); | |||
| } | |||
| } | |||
| void PopupMenu::addItem (const int itemResultId, | |||
| @@ -1377,6 +1368,8 @@ void PopupMenu::addItem (const int itemResultId, | |||
| // didn't pick anything, so you shouldn't use it as the id | |||
| // for an item.. | |||
| addSeparatorIfPending(); | |||
| items.add (new MenuItemInfo (itemResultId, | |||
| itemText, | |||
| isActive, | |||
| @@ -1400,6 +1393,8 @@ void PopupMenu::addCommandItem (ApplicationCommandManager* commandManager, | |||
| ApplicationCommandInfo info (*registeredInfo); | |||
| ApplicationCommandTarget* const target = commandManager->getTargetForCommand (commandID, info); | |||
| addSeparatorIfPending(); | |||
| items.add (new MenuItemInfo (commandID, | |||
| displayName.isNotEmpty() ? displayName | |||
| : info.shortName, | |||
| @@ -1424,6 +1419,8 @@ void PopupMenu::addColouredItem (const int itemResultId, | |||
| // didn't pick anything, so you shouldn't use it as the id | |||
| // for an item.. | |||
| addSeparatorIfPending(); | |||
| items.add (new MenuItemInfo (itemResultId, | |||
| itemText, | |||
| isActive, | |||
| @@ -1442,6 +1439,8 @@ void PopupMenu::addCustomItem (const int itemResultId, | |||
| // didn't pick anything, so you shouldn't use it as the id | |||
| // for an item.. | |||
| addSeparatorIfPending(); | |||
| items.add (new MenuItemInfo (itemResultId, | |||
| String::empty, | |||
| true, | |||
| @@ -1506,6 +1505,8 @@ void PopupMenu::addSubMenu (const String& subMenuName, | |||
| const bool isActive, | |||
| Image* const iconToUse) throw() | |||
| { | |||
| addSeparatorIfPending(); | |||
| items.add (new MenuItemInfo (0, | |||
| subMenuName, | |||
| isActive && (subMenu.getNumItems() > 0), | |||
| @@ -1520,7 +1521,7 @@ void PopupMenu::addSubMenu (const String& subMenuName, | |||
| void PopupMenu::addSeparator() throw() | |||
| { | |||
| items.add (new MenuItemInfo()); | |||
| separatorPending = true; | |||
| } | |||
| @@ -381,6 +381,9 @@ private: | |||
| friend class MenuItemIterator; | |||
| VoidArray items; | |||
| LookAndFeel* lookAndFeel; | |||
| bool separatorPending; | |||
| void addSeparatorIfPending(); | |||
| int showMenu (const int x, const int y, const int w, const int h, | |||
| const int itemIdThatMustBeVisible, | |||
| @@ -137,6 +137,13 @@ public: | |||
| /** Returns the current play position of the movie. */ | |||
| double getPosition() const; | |||
| /** Changes the movie playback rate. | |||
| A value of 1 is normal speed, greater values play it proportionately faster, | |||
| smaller values play it slower. | |||
| */ | |||
| void setSpeed (const float newSpeed); | |||
| /** Changes the movie's playback volume. | |||
| @param newVolume the volume in the range 0 (silent) to 1.0 (full) | |||