Browse Source

Fix for multithreaded Mac OpenGL components; better responding to shutdown messages on Windows; a couple of small VST tweaks; fixed a typo in the AudioDeviceManager and made it close and reopen the audio device while the midi output is being changed; changed AlertWindow to give more control over the desktop window style; fixed a small bug in Graphics; changed SparseSet to avoid an overflow error; stopped BufferedInputStream locking up when its source stream fails; added a case-sensitivity option to StringPairArray and LocalisedStrings.

tags/2021-05-28
jules 16 years ago
parent
commit
bf501e1fda
16 changed files with 333 additions and 68 deletions
  1. +94
    -22
      build/macosx/platform_specific_code/juce_mac_OpenGLComponent.mm
  2. +10
    -1
      build/win32/platform_specific_code/juce_win32_Windowing.cpp
  3. +21
    -1
      extras/audio plugins/wrapper/VST/juce_VST_Wrapper.cpp
  4. +130
    -24
      juce_amalgamated.cpp
  5. +24
    -9
      juce_amalgamated.h
  6. +7
    -1
      src/juce_appframework/audio/devices/juce_AudioDeviceManager.cpp
  7. +5
    -0
      src/juce_appframework/gui/components/windows/juce_AlertWindow.cpp
  8. +2
    -0
      src/juce_appframework/gui/components/windows/juce_AlertWindow.h
  9. +1
    -1
      src/juce_appframework/gui/graphics/contexts/juce_Graphics.cpp
  10. +1
    -0
      src/juce_core/containers/juce_ArrayAllocationBase.h
  11. +12
    -9
      src/juce_core/containers/juce_SparseSet.h
  12. +4
    -0
      src/juce_core/io/streams/juce_BufferedInputStream.cpp
  13. +5
    -0
      src/juce_core/text/juce_LocalisedStrings.cpp
  14. +7
    -0
      src/juce_core/text/juce_LocalisedStrings.h
  15. +5
    -0
      src/juce_core/text/juce_StringPairArray.cpp
  16. +5
    -0
      src/juce_core/text/juce_StringPairArray.h

+ 94
- 22
build/macosx/platform_specific_code/juce_mac_OpenGLComponent.mm View File

@@ -33,6 +33,88 @@
// compiled on its own). // compiled on its own).
#if JUCE_INCLUDED_FILE && JUCE_OPENGL #if JUCE_INCLUDED_FILE && JUCE_OPENGL
END_JUCE_NAMESPACE
//==============================================================================
@interface ThreadSafeNSOpenGLView : NSOpenGLView
{
CriticalSection* contextLock;
bool needsUpdate;
}
- (id) initWithFrame: (NSRect) frameRect pixelFormat: (NSOpenGLPixelFormat*) format;
- (bool) makeActive;
- (void) makeInactive;
- (void) reshape;
@end
@implementation ThreadSafeNSOpenGLView
- (id) initWithFrame: (NSRect) frameRect
pixelFormat: (NSOpenGLPixelFormat*) format
{
contextLock = new CriticalSection();
self = [super initWithFrame: frameRect pixelFormat: format];
if (self != nil)
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector (_surfaceNeedsUpdate:)
name: NSViewGlobalFrameDidChangeNotification
object: self];
return self;
}
- (void) dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver: self];
delete contextLock;
[super dealloc];
}
- (bool) makeActive
{
const ScopedLock sl (*contextLock);
if ([self openGLContext] == 0)
return false;
[[self openGLContext] makeCurrentContext];
if (needsUpdate)
{
[super update];
needsUpdate = false;
}
return true;
}
- (void) makeInactive
{
const ScopedLock sl (*contextLock);
[NSOpenGLContext clearCurrentContext];
}
- (void) _surfaceNeedsUpdate: (NSNotification*) notification
{
const ScopedLock sl (*contextLock);
needsUpdate = true;
}
- (void) update
{
const ScopedLock sl (*contextLock);
needsUpdate = true;
}
- (void) reshape
{
const ScopedLock sl (*contextLock);
needsUpdate = true;
}
@end
BEGIN_JUCE_NAMESPACE
//============================================================================== //==============================================================================
class WindowedGLContext : public OpenGLContext class WindowedGLContext : public OpenGLContext
@@ -50,6 +132,7 @@ public:
int n = 0; int n = 0;
attribs[n++] = NSOpenGLPFADoubleBuffer; attribs[n++] = NSOpenGLPFADoubleBuffer;
attribs[n++] = NSOpenGLPFAAccelerated; attribs[n++] = NSOpenGLPFAAccelerated;
attribs[n++] = NSOpenGLPFAMPSafe; // NSOpenGLPFAAccelerated, NSOpenGLPFAMultiScreen, NSOpenGLPFASingleRenderer
attribs[n++] = NSOpenGLPFAColorSize; attribs[n++] = NSOpenGLPFAColorSize;
attribs[n++] = (NSOpenGLPixelFormatAttribute) jmax (pixelFormat.redBits, attribs[n++] = (NSOpenGLPixelFormatAttribute) jmax (pixelFormat.redBits,
pixelFormat.greenBits, pixelFormat.greenBits,
@@ -67,7 +150,6 @@ public:
pixelFormat.accumulationBufferAlphaBits); pixelFormat.accumulationBufferAlphaBits);
// xxx not sure how to do fullSceneAntiAliasingNumSamples.. // xxx not sure how to do fullSceneAntiAliasingNumSamples..
attribs[n++] = NSOpenGLPFASampleBuffers; attribs[n++] = NSOpenGLPFASampleBuffers;
attribs[n++] = (NSOpenGLPixelFormatAttribute) 1; attribs[n++] = (NSOpenGLPixelFormatAttribute) 1;
attribs[n++] = NSOpenGLPFAClosestPolicy; attribs[n++] = NSOpenGLPFAClosestPolicy;
@@ -77,21 +159,13 @@ public:
NSOpenGLPixelFormat* format NSOpenGLPixelFormat* format
= [[NSOpenGLPixelFormat alloc] initWithAttributes: attribs]; = [[NSOpenGLPixelFormat alloc] initWithAttributes: attribs];
NSOpenGLView* view
= [[NSOpenGLView alloc] initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f)
pixelFormat: format];
if (sharedContext != 0)
{
renderContext = [[NSOpenGLContext alloc] initWithFormat: format
shareContext: sharedContext];
[view setOpenGLContext: renderContext];
[renderContext setView: view];
}
else
{
renderContext = [view openGLContext];
}
view = [[ThreadSafeNSOpenGLView alloc] initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f)
pixelFormat: format];
renderContext = [[[NSOpenGLContext alloc] initWithFormat: format
shareContext: sharedContext] autorelease];
[view setOpenGLContext: renderContext];
[renderContext setView: view];
[format release]; [format release];
@@ -108,15 +182,13 @@ public:
bool makeActive() const throw() bool makeActive() const throw()
{ {
jassert (renderContext != 0); jassert (renderContext != 0);
[renderContext makeCurrentContext];
return renderContext != 0;
[view makeActive];
return isActive();
} }
bool makeInactive() const throw() bool makeInactive() const throw()
{ {
if (! isActive())
[NSOpenGLContext clearCurrentContext];
[view makeInactive];
return true; return true;
} }
@@ -134,7 +206,6 @@ public:
void swapBuffers() void swapBuffers()
{ {
glFlush();
[renderContext flushBuffer]; [renderContext flushBuffer];
} }
@@ -173,6 +244,7 @@ public:
juce_UseDebuggingNewOperator juce_UseDebuggingNewOperator
NSOpenGLContext* renderContext; NSOpenGLContext* renderContext;
ThreadSafeNSOpenGLView* view;
private: private:
OpenGLPixelFormat pixelFormat; OpenGLPixelFormat pixelFormat;


+ 10
- 1
build/win32/platform_specific_code/juce_win32_Windowing.cpp View File

@@ -2033,9 +2033,18 @@ private:
return 0; return 0;
case WM_QUIT: case WM_QUIT:
JUCEApplication::quit();
if (JUCEApplication::getInstance() != 0)
JUCEApplication::getInstance()->systemRequestedQuit();
return 0; return 0;
case WM_QUERYENDSESSION:
if (JUCEApplication::getInstance() != 0)
{
JUCEApplication::getInstance()->systemRequestedQuit();
return MessageManager::getInstance()->hasStopMessageBeenSent();
}
return TRUE;
//============================================================================== //==============================================================================
case WM_TRAYNOTIFY: case WM_TRAYNOTIFY:
if (component->isCurrentlyBlockedByAnotherModalComponent()) if (component->isCurrentlyBlockedByAnotherModalComponent())


+ 21
- 1
extras/audio plugins/wrapper/VST/juce_VST_Wrapper.cpp View File

@@ -69,12 +69,26 @@
#include "public.sdk/source/vst2.x/aeffeditor.h" #include "public.sdk/source/vst2.x/aeffeditor.h"
#include "public.sdk/source/vst2.x/audioeffectx.cpp" #include "public.sdk/source/vst2.x/audioeffectx.cpp"
#include "public.sdk/source/vst2.x/audioeffect.cpp" #include "public.sdk/source/vst2.x/audioeffect.cpp"
#if JUCE_LINUX
#define __cdecl
#endif
#if ! VST_2_4_EXTENSIONS
#error // You're probably trying to include the wrong VSTSDK version - make sure your include path matches the JUCE_USE_VSTSDK_2_4 flag
#endif
#else #else
// VSTSDK V2.3 includes.. // VSTSDK V2.3 includes..
#include "source/common/audioeffectx.h" #include "source/common/audioeffectx.h"
#include "source/common/AEffEditor.hpp" #include "source/common/AEffEditor.hpp"
#include "source/common/audioeffectx.cpp" #include "source/common/audioeffectx.cpp"
#include "source/common/AudioEffect.cpp" #include "source/common/AudioEffect.cpp"
#if (! VST_2_3_EXTENSIONS) || VST_2_4_EXTENSIONS
#error // You're probably trying to include the wrong VSTSDK version - make sure your include path matches the JUCE_USE_VSTSDK_2_4 flag
#endif
typedef long VstInt32; typedef long VstInt32;
typedef long VstIntPtr; typedef long VstIntPtr;
enum Vst2StringConstants enum Vst2StringConstants
@@ -966,7 +980,13 @@ public:
bool setSpeakerArrangement (VstSpeakerArrangement* pluginInput, bool setSpeakerArrangement (VstSpeakerArrangement* pluginInput,
VstSpeakerArrangement* pluginOutput) VstSpeakerArrangement* pluginOutput)
{ {
// if this method isn't implemented, nuendo4 + cubase4 crash when you've got multiple channels..
if (numInChans != pluginInput->numChannels
|| numOutChans != pluginOutput->numChannels)
{
setNumInputs (pluginInput->numChannels);
setNumOutputs (pluginOutput->numChannels);
ioChanged();
}
numInChans = pluginInput->numChannels; numInChans = pluginInput->numChannels;
numOutChans = pluginOutput->numChannels; numOutChans = pluginOutput->numChannels;


+ 130
- 24
juce_amalgamated.cpp View File

@@ -8029,8 +8029,12 @@ int BufferedInputStream::read (void* destBuffer, int maxBytesToRead)
destBuffer = (void*) (((char*) destBuffer) + bytesAvailable); destBuffer = (void*) (((char*) destBuffer) + bytesAvailable);
} }


const int64 oldLastReadPos = lastReadPos;
ensureBuffered(); ensureBuffered();


if (oldLastReadPos == lastReadPos)
break; // if ensureBuffered() failed to read any more data, bail out

if (isExhausted()) if (isExhausted())
break; break;
} }
@@ -9749,6 +9753,11 @@ void LocalisedStrings::loadFromText (const String& fileContents) throw()
} }
} }


void LocalisedStrings::setIgnoresCase (const bool shouldIgnoreCase) throw()
{
translations.setIgnoresCase (shouldIgnoreCase);
}

static CriticalSection currentMappingsLock; static CriticalSection currentMappingsLock;
static LocalisedStrings* currentMappings = 0; static LocalisedStrings* currentMappings = 0;


@@ -12592,6 +12601,11 @@ void StringPairArray::remove (const int index) throw()
values.remove (index); values.remove (index);
} }


void StringPairArray::setIgnoresCase (const bool shouldIgnoreCase) throw()
{
ignoreCase = shouldIgnoreCase;
}

void StringPairArray::minimiseStorageOverheads() throw() void StringPairArray::minimiseStorageOverheads() throw()
{ {
keys.minimiseStorageOverheads(); keys.minimiseStorageOverheads();
@@ -22363,7 +22377,7 @@ const String AudioDeviceManager::setAudioDeviceSetup (const AudioDeviceSetup& ne
const String newOutputDeviceName (numOutputChansNeeded == 0 ? String::empty : newSetup.outputDeviceName); const String newOutputDeviceName (numOutputChansNeeded == 0 ? String::empty : newSetup.outputDeviceName);


if (currentSetup.inputDeviceName != newInputDeviceName if (currentSetup.inputDeviceName != newInputDeviceName
|| currentSetup.inputDeviceName != newOutputDeviceName
|| currentSetup.outputDeviceName != newOutputDeviceName
|| currentAudioDevice == 0) || currentAudioDevice == 0)
{ {
deleteCurrentDevice(); deleteCurrentDevice();
@@ -22813,12 +22827,18 @@ void AudioDeviceManager::setDefaultMidiOutput (const String& deviceName)
{ {
if (defaultMidiOutputName != deviceName) if (defaultMidiOutputName != deviceName)
{ {
if (currentCallback != 0 && currentAudioDevice != 0)
currentCallback->audioDeviceStopped();

deleteAndZero (defaultMidiOutput); deleteAndZero (defaultMidiOutput);
defaultMidiOutputName = deviceName; defaultMidiOutputName = deviceName;


if (deviceName.isNotEmpty()) if (deviceName.isNotEmpty())
defaultMidiOutput = MidiOutput::openDevice (MidiOutput::getDevices().indexOf (deviceName)); defaultMidiOutput = MidiOutput::openDevice (MidiOutput::getDevices().indexOf (deviceName));


if (currentCallback != 0 && currentAudioDevice != 0)
currentCallback->audioDeviceAboutToStart (currentAudioDevice);

updateXml(); updateXml();
sendChangeMessage (this); sendChangeMessage (this);
} }
@@ -71675,6 +71695,11 @@ void AlertWindow::lookAndFeelChanged()
setDropShadowEnabled ((flags & ComponentPeer::windowHasDropShadow) != 0); setDropShadowEnabled ((flags & ComponentPeer::windowHasDropShadow) != 0);
} }


int AlertWindow::getDesktopWindowStyleFlags() const
{
return getLookAndFeel().getAlertBoxWindowFlags();
}

struct AlertWindowInfo struct AlertWindowInfo
{ {
String title, message, button1, button2, button3; String title, message, button1, button2, button3;
@@ -76036,7 +76061,7 @@ void Graphics::strokePath (const Path& path,
const PathStrokeType& strokeType, const PathStrokeType& strokeType,
const AffineTransform& transform) const throw() const AffineTransform& transform) const throw()
{ {
if (! state->colour.isTransparent())
if ((! state->colour.isTransparent()) || state->brush != 0)
{ {
Path stroke; Path stroke;
strokeType.createStrokedPath (stroke, path, transform); strokeType.createStrokedPath (stroke, path, transform);
@@ -244183,9 +244208,18 @@ private:
return 0; return 0;


case WM_QUIT: case WM_QUIT:
JUCEApplication::quit();
if (JUCEApplication::getInstance() != 0)
JUCEApplication::getInstance()->systemRequestedQuit();
return 0; return 0;


case WM_QUERYENDSESSION:
if (JUCEApplication::getInstance() != 0)
{
JUCEApplication::getInstance()->systemRequestedQuit();
return MessageManager::getInstance()->hasStopMessageBeenSent();
}
return TRUE;

case WM_TRAYNOTIFY: case WM_TRAYNOTIFY:
if (component->isCurrentlyBlockedByAnotherModalComponent()) if (component->isCurrentlyBlockedByAnotherModalComponent())
{ {
@@ -267842,6 +267876,88 @@ void AppleRemoteDevice::handleCallbackInternal()
// compiled on its own). // compiled on its own).
#if JUCE_INCLUDED_FILE && JUCE_OPENGL #if JUCE_INCLUDED_FILE && JUCE_OPENGL


END_JUCE_NAMESPACE

@interface ThreadSafeNSOpenGLView : NSOpenGLView
{
CriticalSection* contextLock;
bool needsUpdate;
}

- (id) initWithFrame: (NSRect) frameRect pixelFormat: (NSOpenGLPixelFormat*) format;
- (bool) makeActive;
- (void) makeInactive;
- (void) reshape;
@end

@implementation ThreadSafeNSOpenGLView

- (id) initWithFrame: (NSRect) frameRect
pixelFormat: (NSOpenGLPixelFormat*) format
{
contextLock = new CriticalSection();
self = [super initWithFrame: frameRect pixelFormat: format];

if (self != nil)
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector (_surfaceNeedsUpdate:)
name: NSViewGlobalFrameDidChangeNotification
object: self];
return self;
}

- (void) dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver: self];
delete contextLock;
[super dealloc];
}

- (bool) makeActive
{
const ScopedLock sl (*contextLock);

if ([self openGLContext] == 0)
return false;

[[self openGLContext] makeCurrentContext];

if (needsUpdate)
{
[super update];
needsUpdate = false;
}

return true;
}

- (void) makeInactive
{
const ScopedLock sl (*contextLock);
[NSOpenGLContext clearCurrentContext];
}

- (void) _surfaceNeedsUpdate: (NSNotification*) notification
{
const ScopedLock sl (*contextLock);
needsUpdate = true;
}

- (void) update
{
const ScopedLock sl (*contextLock);
needsUpdate = true;
}

- (void) reshape
{
const ScopedLock sl (*contextLock);
needsUpdate = true;
}

@end
BEGIN_JUCE_NAMESPACE

class WindowedGLContext : public OpenGLContext class WindowedGLContext : public OpenGLContext
{ {
public: public:
@@ -267857,6 +267973,7 @@ public:
int n = 0; int n = 0;
attribs[n++] = NSOpenGLPFADoubleBuffer; attribs[n++] = NSOpenGLPFADoubleBuffer;
attribs[n++] = NSOpenGLPFAAccelerated; attribs[n++] = NSOpenGLPFAAccelerated;
attribs[n++] = NSOpenGLPFAMPSafe; // NSOpenGLPFAAccelerated, NSOpenGLPFAMultiScreen, NSOpenGLPFASingleRenderer
attribs[n++] = NSOpenGLPFAColorSize; attribs[n++] = NSOpenGLPFAColorSize;
attribs[n++] = (NSOpenGLPixelFormatAttribute) jmax (pixelFormat.redBits, attribs[n++] = (NSOpenGLPixelFormatAttribute) jmax (pixelFormat.redBits,
pixelFormat.greenBits, pixelFormat.greenBits,
@@ -267874,7 +267991,6 @@ public:
pixelFormat.accumulationBufferAlphaBits); pixelFormat.accumulationBufferAlphaBits);


// xxx not sure how to do fullSceneAntiAliasingNumSamples.. // xxx not sure how to do fullSceneAntiAliasingNumSamples..

attribs[n++] = NSOpenGLPFASampleBuffers; attribs[n++] = NSOpenGLPFASampleBuffers;
attribs[n++] = (NSOpenGLPixelFormatAttribute) 1; attribs[n++] = (NSOpenGLPixelFormatAttribute) 1;
attribs[n++] = NSOpenGLPFAClosestPolicy; attribs[n++] = NSOpenGLPFAClosestPolicy;
@@ -267884,21 +268000,13 @@ public:
NSOpenGLPixelFormat* format NSOpenGLPixelFormat* format
= [[NSOpenGLPixelFormat alloc] initWithAttributes: attribs]; = [[NSOpenGLPixelFormat alloc] initWithAttributes: attribs];


NSOpenGLView* view
= [[NSOpenGLView alloc] initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f)
pixelFormat: format];
view = [[ThreadSafeNSOpenGLView alloc] initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f)
pixelFormat: format];


if (sharedContext != 0)
{
renderContext = [[NSOpenGLContext alloc] initWithFormat: format
shareContext: sharedContext];
[view setOpenGLContext: renderContext];
[renderContext setView: view];
}
else
{
renderContext = [view openGLContext];
}
renderContext = [[[NSOpenGLContext alloc] initWithFormat: format
shareContext: sharedContext] autorelease];
[view setOpenGLContext: renderContext];
[renderContext setView: view];


[format release]; [format release];


@@ -267915,15 +268023,13 @@ public:
bool makeActive() const throw() bool makeActive() const throw()
{ {
jassert (renderContext != 0); jassert (renderContext != 0);
[renderContext makeCurrentContext];
return renderContext != 0;
[view makeActive];
return isActive();
} }


bool makeInactive() const throw() bool makeInactive() const throw()
{ {
if (! isActive())
[NSOpenGLContext clearCurrentContext];

[view makeInactive];
return true; return true;
} }


@@ -267941,7 +268047,6 @@ public:


void swapBuffers() void swapBuffers()
{ {
glFlush();
[renderContext flushBuffer]; [renderContext flushBuffer];
} }


@@ -267979,6 +268084,7 @@ public:
juce_UseDebuggingNewOperator juce_UseDebuggingNewOperator


NSOpenGLContext* renderContext; NSOpenGLContext* renderContext;
ThreadSafeNSOpenGLView* view;


private: private:
OpenGLPixelFormat pixelFormat; OpenGLPixelFormat pixelFormat;


+ 24
- 9
juce_amalgamated.h View File

@@ -2783,6 +2783,7 @@ protected:
numAllocated (0), numAllocated (0),
granularity (granularity_) granularity (granularity_)
{ {
jassert (granularity > 0);
} }


/** Destructor. */ /** Destructor. */
@@ -8102,6 +8103,10 @@ public:
*/ */
void remove (const int index) throw(); void remove (const int index) throw();


/** Indicates whether to use a case-insensitive search when looking up a key string.
*/
void setIgnoresCase (const bool shouldIgnoreCase) throw();

/** Reduces the amount of storage being used by the array. /** Reduces the amount of storage being used by the array.


Arrays typically allocate slightly more storage than they need, and after Arrays typically allocate slightly more storage than they need, and after
@@ -11214,23 +11219,26 @@ public:
{ {
jassert (numValuesToRemove >= 0); jassert (numValuesToRemove >= 0);


if (numValuesToRemove != 0
if (numValuesToRemove >= 0
&& firstValue < values.getLast()) && firstValue < values.getLast())
{ {
const bool onAtStart = contains (firstValue - 1); const bool onAtStart = contains (firstValue - 1);
Type lastValue = firstValue + numValuesToRemove;

if (lastValue < firstValue) // possible if the signed arithmetic wraps around
lastValue = values.getLast();

const Type lastValue = firstValue + jmin (numValuesToRemove, values.getLast() - firstValue);
const bool onAtEnd = contains (lastValue); const bool onAtEnd = contains (lastValue);


for (int i = values.size(); --i >= 0;) for (int i = values.size(); --i >= 0;)
{ {
if (values.getUnchecked(i) >= firstValue
&& values.getUnchecked(i) <= lastValue)
if (values.getUnchecked(i) <= lastValue)
{ {
values.remove (i);
while (values.getUnchecked(i) >= firstValue)
{
values.remove (i);

if (--i < 0)
break;
}

break;
} }
} }


@@ -13693,6 +13701,11 @@ public:
*/ */
const StringArray getCountryCodes() const throw() { return countryCodes; } const StringArray getCountryCodes() const throw() { return countryCodes; }


/** Indicates whether to use a case-insensitive search when looking up a string.
This defaults to true.
*/
void setIgnoresCase (const bool shouldIgnoreCase) throw();

juce_UseDebuggingNewOperator juce_UseDebuggingNewOperator


private: private:
@@ -50713,6 +50726,8 @@ protected:
void lookAndFeelChanged(); void lookAndFeelChanged();
/** @internal */ /** @internal */
void userTriedToCloseWindow(); void userTriedToCloseWindow();
/** @internal */
int getDesktopWindowStyleFlags() const;


private: private:
String text; String text;


+ 7
- 1
src/juce_appframework/audio/devices/juce_AudioDeviceManager.cpp View File

@@ -379,7 +379,7 @@ const String AudioDeviceManager::setAudioDeviceSetup (const AudioDeviceSetup& ne
const String newOutputDeviceName (numOutputChansNeeded == 0 ? String::empty : newSetup.outputDeviceName); const String newOutputDeviceName (numOutputChansNeeded == 0 ? String::empty : newSetup.outputDeviceName);
if (currentSetup.inputDeviceName != newInputDeviceName if (currentSetup.inputDeviceName != newInputDeviceName
|| currentSetup.inputDeviceName != newOutputDeviceName
|| currentSetup.outputDeviceName != newOutputDeviceName
|| currentAudioDevice == 0) || currentAudioDevice == 0)
{ {
deleteCurrentDevice(); deleteCurrentDevice();
@@ -832,12 +832,18 @@ void AudioDeviceManager::setDefaultMidiOutput (const String& deviceName)
{ {
if (defaultMidiOutputName != deviceName) if (defaultMidiOutputName != deviceName)
{ {
if (currentCallback != 0 && currentAudioDevice != 0)
currentCallback->audioDeviceStopped();
deleteAndZero (defaultMidiOutput); deleteAndZero (defaultMidiOutput);
defaultMidiOutputName = deviceName; defaultMidiOutputName = deviceName;
if (deviceName.isNotEmpty()) if (deviceName.isNotEmpty())
defaultMidiOutput = MidiOutput::openDevice (MidiOutput::getDevices().indexOf (deviceName)); defaultMidiOutput = MidiOutput::openDevice (MidiOutput::getDevices().indexOf (deviceName));
if (currentCallback != 0 && currentAudioDevice != 0)
currentCallback->audioDeviceAboutToStart (currentAudioDevice);
updateXml(); updateXml();
sendChangeMessage (this); sendChangeMessage (this);
} }


+ 5
- 0
src/juce_appframework/gui/components/windows/juce_AlertWindow.cpp View File

@@ -591,6 +591,11 @@ void AlertWindow::lookAndFeelChanged()
setDropShadowEnabled ((flags & ComponentPeer::windowHasDropShadow) != 0); setDropShadowEnabled ((flags & ComponentPeer::windowHasDropShadow) != 0);
} }
int AlertWindow::getDesktopWindowStyleFlags() const
{
return getLookAndFeel().getAlertBoxWindowFlags();
}
//============================================================================== //==============================================================================
struct AlertWindowInfo struct AlertWindowInfo
{ {


+ 2
- 0
src/juce_appframework/gui/components/windows/juce_AlertWindow.h View File

@@ -339,6 +339,8 @@ protected:
void lookAndFeelChanged(); void lookAndFeelChanged();
/** @internal */ /** @internal */
void userTriedToCloseWindow(); void userTriedToCloseWindow();
/** @internal */
int getDesktopWindowStyleFlags() const;
private: private:
String text; String text;


+ 1
- 1
src/juce_appframework/gui/graphics/contexts/juce_Graphics.cpp View File

@@ -429,7 +429,7 @@ void Graphics::strokePath (const Path& path,
const PathStrokeType& strokeType, const PathStrokeType& strokeType,
const AffineTransform& transform) const throw() const AffineTransform& transform) const throw()
{ {
if (! state->colour.isTransparent())
if ((! state->colour.isTransparent()) || state->brush != 0)
{ {
Path stroke; Path stroke;
strokeType.createStrokedPath (stroke, path, transform); strokeType.createStrokedPath (stroke, path, transform);


+ 1
- 0
src/juce_core/containers/juce_ArrayAllocationBase.h View File

@@ -65,6 +65,7 @@ protected:
numAllocated (0), numAllocated (0),
granularity (granularity_) granularity (granularity_)
{ {
jassert (granularity > 0);
} }
/** Destructor. */ /** Destructor. */


+ 12
- 9
src/juce_core/containers/juce_SparseSet.h View File

@@ -225,23 +225,26 @@ public:
{ {
jassert (numValuesToRemove >= 0); jassert (numValuesToRemove >= 0);
if (numValuesToRemove != 0
if (numValuesToRemove >= 0
&& firstValue < values.getLast()) && firstValue < values.getLast())
{ {
const bool onAtStart = contains (firstValue - 1); const bool onAtStart = contains (firstValue - 1);
Type lastValue = firstValue + numValuesToRemove;
if (lastValue < firstValue) // possible if the signed arithmetic wraps around
lastValue = values.getLast();
const Type lastValue = firstValue + jmin (numValuesToRemove, values.getLast() - firstValue);
const bool onAtEnd = contains (lastValue); const bool onAtEnd = contains (lastValue);
for (int i = values.size(); --i >= 0;) for (int i = values.size(); --i >= 0;)
{ {
if (values.getUnchecked(i) >= firstValue
&& values.getUnchecked(i) <= lastValue)
if (values.getUnchecked(i) <= lastValue)
{ {
values.remove (i);
while (values.getUnchecked(i) >= firstValue)
{
values.remove (i);
if (--i < 0)
break;
}
break;
} }
} }


+ 4
- 0
src/juce_core/io/streams/juce_BufferedInputStream.cpp View File

@@ -153,8 +153,12 @@ int BufferedInputStream::read (void* destBuffer, int maxBytesToRead)
destBuffer = (void*) (((char*) destBuffer) + bytesAvailable); destBuffer = (void*) (((char*) destBuffer) + bytesAvailable);
} }
const int64 oldLastReadPos = lastReadPos;
ensureBuffered(); ensureBuffered();
if (oldLastReadPos == lastReadPos)
break; // if ensureBuffered() failed to read any more data, bail out
if (isExhausted()) if (isExhausted())
break; break;
} }


+ 5
- 0
src/juce_core/text/juce_LocalisedStrings.cpp View File

@@ -124,6 +124,11 @@ void LocalisedStrings::loadFromText (const String& fileContents) throw()
} }
} }
void LocalisedStrings::setIgnoresCase (const bool shouldIgnoreCase) throw()
{
translations.setIgnoresCase (shouldIgnoreCase);
}
//============================================================================== //==============================================================================
static CriticalSection currentMappingsLock; static CriticalSection currentMappingsLock;
static LocalisedStrings* currentMappings = 0; static LocalisedStrings* currentMappings = 0;


+ 7
- 0
src/juce_core/text/juce_LocalisedStrings.h View File

@@ -181,6 +181,13 @@ public:
*/ */
const StringArray getCountryCodes() const throw() { return countryCodes; } const StringArray getCountryCodes() const throw() { return countryCodes; }
//==============================================================================
/** Indicates whether to use a case-insensitive search when looking up a string.
This defaults to true.
*/
void setIgnoresCase (const bool shouldIgnoreCase) throw();
//============================================================================== //==============================================================================
juce_UseDebuggingNewOperator juce_UseDebuggingNewOperator


+ 5
- 0
src/juce_core/text/juce_StringPairArray.cpp View File

@@ -130,6 +130,11 @@ void StringPairArray::remove (const int index) throw()
values.remove (index); values.remove (index);
} }
void StringPairArray::setIgnoresCase (const bool shouldIgnoreCase) throw()
{
ignoreCase = shouldIgnoreCase;
}
void StringPairArray::minimiseStorageOverheads() throw() void StringPairArray::minimiseStorageOverheads() throw()
{ {
keys.minimiseStorageOverheads(); keys.minimiseStorageOverheads();


+ 5
- 0
src/juce_core/text/juce_StringPairArray.h View File

@@ -138,6 +138,11 @@ public:
*/ */
void remove (const int index) throw(); void remove (const int index) throw();
//==============================================================================
/** Indicates whether to use a case-insensitive search when looking up a key string.
*/
void setIgnoresCase (const bool shouldIgnoreCase) throw();
//============================================================================== //==============================================================================
/** Reduces the amount of storage being used by the array. /** Reduces the amount of storage being used by the array.


Loading…
Cancel
Save