Browse Source

Fix for String copying thread-safety, and some minor compile issues.

tags/2021-05-28
Julian Storer 15 years ago
parent
commit
0d278483e4
19 changed files with 287 additions and 266 deletions
  1. +1
    -1
      juce.h
  2. +97
    -133
      juce_amalgamated.cpp
  3. +31
    -2
      juce_amalgamated.h
  4. +13
    -17
      src/audio/devices/juce_AudioDeviceManager.cpp
  5. +1
    -4
      src/containers/juce_PropertySet.cpp
  6. +15
    -0
      src/core/juce_Atomic.h
  7. +50
    -0
      src/core/juce_Initialisation.h
  8. +13
    -15
      src/gui/components/controls/juce_TableHeaderComponent.cpp
  9. +2
    -6
      src/gui/components/keyboard/juce_KeyPressMappingSet.cpp
  10. +3
    -4
      src/gui/components/properties/juce_PropertyPanel.cpp
  11. +1
    -1
      src/native/mac/juce_iphone_MiscUtilities.mm
  12. +3
    -3
      src/native/mac/juce_mac_FileChooser.mm
  13. +1
    -1
      src/native/mac/juce_mac_Fonts.mm
  14. +1
    -1
      src/native/windows/juce_win32_PlatformUtils.cpp
  15. +2
    -0
      src/native/windows/juce_win32_Threads.cpp
  16. +35
    -17
      src/native/windows/juce_win32_WASAPI.cpp
  17. +17
    -57
      src/text/juce_String.cpp
  18. +0
    -1
      src/text/juce_String.h
  19. +1
    -3
      src/utilities/juce_PropertiesFile.cpp

+ 1
- 1
juce.h View File

@@ -80,7 +80,7 @@ END_JUCE_NAMESPACE
of 3rd party header files, you may need to use the juce_WithoutMacros.h file - see
the comments in that file for more information.
*/
#if JUCE_MAC && ! JUCE_DONT_DEFINE_MACROS
#if (JUCE_MAC || JUCE_IPHONE) && ! JUCE_DONT_DEFINE_MACROS
#define Component JUCE_NAMESPACE::Component
#define MemoryBlock JUCE_NAMESPACE::MemoryBlock
#define Point JUCE_NAMESPACE::Point


+ 97
- 133
juce_amalgamated.cpp View File

@@ -3459,12 +3459,9 @@ XmlElement* PropertySet::createXml (const String& nodeName) const throw()

for (int i = 0; i < properties.getAllKeys().size(); ++i)
{
XmlElement* const e = new XmlElement (T("VALUE"));

XmlElement* const e = xml->createNewChildElement ("VALUE");
e->setAttribute (T("name"), properties.getAllKeys()[i]);
e->setAttribute (T("val"), properties.getAllValues()[i]);

xml->addChildElement (e);
}

return xml;
@@ -10414,12 +10411,6 @@ void juce_initialiseStrings()
decimalPoint = String::fromUTF8 ((const uint8*) localeconv()->decimal_point) [0];
}

void String::deleteInternal() throw()
{
if (Atomic::decrementAndReturn (text->refCount) == 0)
juce_free (text);
}

void String::createInternal (const int numChars) throw()
{
jassert (numChars > 0);
@@ -10943,32 +10934,7 @@ int64 String::hashCode64() const throw()

const String& String::operator= (const tchar* const otherText) throw()
{
if (otherText != 0 && *otherText != 0)
{
const int otherLen = CharacterFunctions::length (otherText);

if (otherLen > 0)
{
// avoid resizing the memory block if the string is
// shrinking..
if (text->refCount > 1
|| otherLen > text->allocatedNumChars
|| otherLen <= (text->allocatedNumChars >> 1))
{
deleteInternal();
createInternal (otherLen);
}

memcpy (text->text, otherText, (otherLen + 1) * sizeof (tchar));

return *this;
}
}

deleteInternal();
text = &emptyString;
emptyString.refCount = safeEmptyStringRefCount;

operator= (String (otherText));
return *this;
}

@@ -10976,12 +10942,14 @@ const String& String::operator= (const String& other) throw()
{
if (this != &other)
{
Atomic::increment (other.text->refCount);
InternalRefCountedStringHolder* newText = other.text;
Atomic::increment (newText->refCount);

if (Atomic::decrementAndReturn (text->refCount) == 0)
juce_free (text);
InternalRefCountedStringHolder* oldText
= (InternalRefCountedStringHolder*) Atomic::swapPointers ((void* volatile*) &text, newText);

text = other.text;
if (Atomic::decrementAndReturn (oldText->refCount) == 0)
juce_free (oldText);
}

return *this;
@@ -11625,47 +11593,36 @@ const String String::formatted (const tchar* const pf, ...) throw()

void String::vprintf (const tchar* const pf, va_list& args) throw()
{
tchar stackBuf [256];
unsigned int bufSize = 256;
tchar* buf = stackBuf;

deleteInternal();
int bufferSize = 256;
String result (bufferSize, 0);

do
{
#if JUCE_LINUX && JUCE_64BIT
va_list tempArgs;
va_copy (tempArgs, args);
const int num = CharacterFunctions::vprintf (buf, bufSize - 1, pf, tempArgs);
const int num = CharacterFunctions::vprintf (result.text->text, bufferSize - 1, pf, tempArgs);
va_end (tempArgs);
#else
const int num = CharacterFunctions::vprintf (buf, bufSize - 1, pf, args);
const int num = CharacterFunctions::vprintf (result.text->text, bufferSize - 1, pf, args);
#endif

if (num > 0)
{
createInternal (num);
memcpy (text->text, buf, (num + 1) * sizeof (tchar));
*this = result;
break;
}
else if (num == 0)
{
text = &emptyString;
emptyString.refCount = safeEmptyStringRefCount;
*this = String::empty;
break;
}

if (buf != stackBuf)
juce_free (buf);

bufSize += 256;
buf = (tchar*) juce_malloc (bufSize * sizeof (tchar));
bufferSize += 256;
result.preallocateStorage (bufferSize);
}
while (bufSize < 65536); // this is a sanity check to avoid situations where vprintf repeatedly
// returns -1 because of an error rather than because it needs more space.

if (buf != stackBuf)
juce_free (buf);
while (bufferSize < 65536); // this is a sanity check to avoid situations where vprintf repeatedly
// returns -1 because of an error rather than because it needs more space.
}

const String String::repeatedString (const tchar* const stringToRepeat,
@@ -18196,7 +18153,7 @@ bool PropertiesFile::save()

for (int i = 0; i < getAllProperties().size(); ++i)
{
XmlElement* const e = new XmlElement (propertyTagName);
XmlElement* const e = doc.createNewChildElement (propertyTagName);
e->setAttribute (T("name"), getAllProperties().getAllKeys() [i]);

// if the value seems to contain xml, store it as such..
@@ -18207,8 +18164,6 @@ bool PropertiesFile::save()
e->addChildElement (childElement);
else
e->setAttribute (T("val"), getAllProperties().getAllValues() [i]);

doc.addChildElement (e);
}

return doc.writeToFile (file, String::empty);
@@ -24556,32 +24511,30 @@ void AudioDeviceManager::restartLastAudioDevice()

void AudioDeviceManager::updateXml()
{
lastExplicitSettings = new XmlElement (T("DEVICESETUP"));
lastExplicitSettings = new XmlElement ("DEVICESETUP");

lastExplicitSettings->setAttribute (T("deviceType"), currentDeviceType);
lastExplicitSettings->setAttribute (T("audioOutputDeviceName"), currentSetup.outputDeviceName);
lastExplicitSettings->setAttribute (T("audioInputDeviceName"), currentSetup.inputDeviceName);
lastExplicitSettings->setAttribute ("deviceType", currentDeviceType);
lastExplicitSettings->setAttribute ("audioOutputDeviceName", currentSetup.outputDeviceName);
lastExplicitSettings->setAttribute ("audioInputDeviceName", currentSetup.inputDeviceName);

if (currentAudioDevice != 0)
{
lastExplicitSettings->setAttribute (T("audioDeviceRate"), currentAudioDevice->getCurrentSampleRate());
lastExplicitSettings->setAttribute ("audioDeviceRate", currentAudioDevice->getCurrentSampleRate());

if (currentAudioDevice->getDefaultBufferSize() != currentAudioDevice->getCurrentBufferSizeSamples())
lastExplicitSettings->setAttribute (T("audioDeviceBufferSize"), currentAudioDevice->getCurrentBufferSizeSamples());
lastExplicitSettings->setAttribute ("audioDeviceBufferSize", currentAudioDevice->getCurrentBufferSizeSamples());

if (! currentSetup.useDefaultInputChannels)
lastExplicitSettings->setAttribute (T("audioDeviceInChans"), currentSetup.inputChannels.toString (2));
lastExplicitSettings->setAttribute ("audioDeviceInChans", currentSetup.inputChannels.toString (2));

if (! currentSetup.useDefaultOutputChannels)
lastExplicitSettings->setAttribute (T("audioDeviceOutChans"), currentSetup.outputChannels.toString (2));
lastExplicitSettings->setAttribute ("audioDeviceOutChans", currentSetup.outputChannels.toString (2));
}

for (int i = 0; i < enabledMidiInputs.size(); ++i)
{
XmlElement* const m = new XmlElement (T("MIDIINPUT"));
m->setAttribute (T("name"), enabledMidiInputs[i]->getName());

lastExplicitSettings->addChildElement (m);
XmlElement* const m = lastExplicitSettings->createNewChildElement ("MIDIINPUT");
m->setAttribute ("name", enabledMidiInputs[i]->getName());
}

if (midiInsFromXml.size() > 0)
@@ -24594,16 +24547,14 @@ void AudioDeviceManager::updateXml()
{
if (! availableMidiDevices.contains (midiInsFromXml[i], true))
{
XmlElement* const m = new XmlElement (T("MIDIINPUT"));
m->setAttribute (T("name"), midiInsFromXml[i]);

lastExplicitSettings->addChildElement (m);
XmlElement* const m = lastExplicitSettings->createNewChildElement ("MIDIINPUT");
m->setAttribute ("name", midiInsFromXml[i]);
}
}
}

if (defaultMidiOutputName.isNotEmpty())
lastExplicitSettings->setAttribute (T("defaultMidiOutput"), defaultMidiOutputName);
lastExplicitSettings->setAttribute ("defaultMidiOutput", defaultMidiOutputName);
}

void AudioDeviceManager::addAudioCallback (AudioIODeviceCallback* newCallback)
@@ -50375,21 +50326,19 @@ const String TableHeaderComponent::toString() const
{
String s;

XmlElement doc (T("TABLELAYOUT"));
XmlElement doc ("TABLELAYOUT");

doc.setAttribute (T("sortedCol"), getSortColumnId());
doc.setAttribute (T("sortForwards"), isSortedForwards());
doc.setAttribute ("sortedCol", getSortColumnId());
doc.setAttribute ("sortForwards", isSortedForwards());

for (int i = 0; i < columns.size(); ++i)
{
const ColumnInfo* const ci = columns.getUnchecked (i);

XmlElement* const e = new XmlElement (T("COLUMN"));
doc.addChildElement (e);

e->setAttribute (T("id"), ci->id);
e->setAttribute (T("visible"), ci->isVisible());
e->setAttribute (T("width"), ci->width);
XmlElement* const e = doc.createNewChildElement ("COLUMN");
e->setAttribute ("id", ci->id);
e->setAttribute ("visible", ci->isVisible());
e->setAttribute ("width", ci->width);
}

return doc.createDocument (String::empty, true, false);
@@ -50402,19 +50351,19 @@ void TableHeaderComponent::restoreFromString (const String& storedVersion)

int index = 0;

if (storedXml != 0 && storedXml->hasTagName (T("TABLELAYOUT")))
if (storedXml != 0 && storedXml->hasTagName ("TABLELAYOUT"))
{
forEachXmlChildElement (*storedXml, col)
{
const int tabId = col->getIntAttribute (T("id"));
const int tabId = col->getIntAttribute ("id");

ColumnInfo* const ci = getInfoForId (tabId);

if (ci != 0)
{
columns.move (columns.indexOf (ci), index);
ci->width = col->getIntAttribute (T("width"));
setColumnVisible (tabId, col->getBoolAttribute (T("visible")));
ci->width = col->getIntAttribute ("width");
setColumnVisible (tabId, col->getBoolAttribute ("visible"));
}

++index;
@@ -50423,8 +50372,8 @@ void TableHeaderComponent::restoreFromString (const String& storedVersion)
columnsResized = true;
sendColumnsChanged();

setSortColumnId (storedXml->getIntAttribute (T("sortedCol")),
storedXml->getBoolAttribute (T("sortForwards"), true));
setSortColumnId (storedXml->getIntAttribute ("sortedCol"),
storedXml->getBoolAttribute ("sortForwards", true));
}
}

@@ -60336,13 +60285,11 @@ XmlElement* KeyPressMappingSet::createXml (const bool saveDifferencesFromDefault
if (defaultSet == 0
|| ! defaultSet->containsMapping (cm->commandID, cm->keypresses.getReference (j)))
{
XmlElement* const map = new XmlElement (T("MAPPING"));
XmlElement* const map = doc->createNewChildElement ("MAPPING");

map->setAttribute (T("commandId"), String::toHexString ((int) cm->commandID));
map->setAttribute (T("description"), commandManager->getDescriptionOfCommand (cm->commandID));
map->setAttribute (T("key"), cm->keypresses.getReference (j).getTextDescription());

doc->addChildElement (map);
}
}
}
@@ -60357,13 +60304,11 @@ XmlElement* KeyPressMappingSet::createXml (const bool saveDifferencesFromDefault
{
if (! containsMapping (cm->commandID, cm->keypresses.getReference (j)))
{
XmlElement* const map = new XmlElement (T("UNMAPPING"));
XmlElement* const map = doc->createNewChildElement ("UNMAPPING");

map->setAttribute (T("commandId"), String::toHexString ((int) cm->commandID));
map->setAttribute (T("description"), commandManager->getDescriptionOfCommand (cm->commandID));
map->setAttribute (T("key"), cm->keypresses.getReference (j).getTextDescription());

doc->addChildElement (map);
}
}
}
@@ -71423,10 +71368,9 @@ XmlElement* PropertyPanel::getOpennessState() const
{
if (sections[i].isNotEmpty())
{
XmlElement* const e = new XmlElement (T("SECTION"));
e->setAttribute (T("name"), sections[i]);
e->setAttribute (T("open"), isSectionOpen (i) ? 1 : 0);
xml->addChildElement (e);
XmlElement* const e = xml->createNewChildElement ("SECTION");
e->setAttribute ("name", sections[i]);
e->setAttribute ("open", isSectionOpen (i) ? 1 : 0);
}
}

@@ -212236,6 +212180,8 @@ int32 Atomic::compareAndExchange (int32& destination, int32 newValue, int32 oldV
{ return InterlockedCompareExchange (reinterpret_cast <volatile long*> (&destination), newValue, oldValue); }
#endif

void* Atomic::swapPointers (void* volatile* value1, void* volatile value2) { return InterlockedExchangePointer (value1, value2); }

CriticalSection::CriticalSection() throw()
{
// (just to check the MS haven't changed this structure and broken things...)
@@ -213949,7 +213895,7 @@ static HKEY findKeyForPath (String name,

if (createForWriting)
{
if (RegCreateKeyEx (rootKey, name, 0, L"", REG_OPTION_NON_VOLATILE,
if (RegCreateKeyEx (rootKey, name, 0, 0, REG_OPTION_NON_VOLATILE,
(KEY_WRITE | KEY_QUERY_VALUE), 0, &key, &result) == ERROR_SUCCESS)
return key;
}
@@ -226510,7 +226456,7 @@ static void wasapi_copyWavFormat (WAVEFORMATEXTENSIBLE& dest, const WAVEFORMATEX
class WASAPIDeviceBase
{
public:
WASAPIDeviceBase (const ComSmartPtr <IMMDevice>& device_)
WASAPIDeviceBase (const ComSmartPtr <IMMDevice>& device_, const bool useExclusiveMode_)
: device (device_),
sampleRate (0),
numChannels (0),
@@ -226518,7 +226464,8 @@ public:
defaultSampleRate (0),
minBufferSize (0),
defaultBufferSize (0),
latencySamples (0)
latencySamples (0),
useExclusiveMode (useExclusiveMode_)
{
clientEvent = CreateEvent (0, false, false, _T("JuceWASAPI"));

@@ -226555,7 +226502,8 @@ public:

format.Format.nSamplesPerSec = roundDoubleToInt (ratesToTest[i]);

if (SUCCEEDED (tempClient->IsFormatSupported (AUDCLNT_SHAREMODE_SHARED, (WAVEFORMATEX*) &format, 0)))
if (SUCCEEDED (tempClient->IsFormatSupported (useExclusiveMode ? AUDCLNT_SHAREMODE_EXCLUSIVE : AUDCLNT_SHAREMODE_SHARED,
(WAVEFORMATEX*) &format, 0)))
if (! rates.contains (ratesToTest[i]))
rates.addSorted (comparator, ratesToTest[i]);
}
@@ -226616,6 +226564,7 @@ public:
double sampleRate, defaultSampleRate;
int numChannels, actualNumChannels;
int minBufferSize, defaultBufferSize, latencySamples;
const bool useExclusiveMode;
Array <double> rates;
HANDLE clientEvent;
BitArray channels;
@@ -226673,7 +226622,8 @@ private:

WAVEFORMATEXTENSIBLE* nearestFormat = 0;

HRESULT hr = client->IsFormatSupported (AUDCLNT_SHAREMODE_SHARED, (WAVEFORMATEX*) &format, (WAVEFORMATEX**) &nearestFormat);
HRESULT hr = client->IsFormatSupported (useExclusiveMode ? AUDCLNT_SHAREMODE_EXCLUSIVE : AUDCLNT_SHAREMODE_SHARED,
(WAVEFORMATEX*) &format, useExclusiveMode ? 0 : (WAVEFORMATEX**) &nearestFormat);
logFailure (hr);

if (hr == S_FALSE && format.Format.nSamplesPerSec == nearestFormat->Format.nSamplesPerSec)
@@ -226684,10 +226634,15 @@ private:

CoTaskMemFree (nearestFormat);

REFERENCE_TIME defaultPeriod = 0, minPeriod = 0;
if (useExclusiveMode)
OK (client->GetDevicePeriod (&defaultPeriod, &minPeriod));

GUID session;
if (hr == S_OK
&& OK (client->Initialize (AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
0, 0, (WAVEFORMATEX*) &format, &session)))
&& OK (client->Initialize (useExclusiveMode ? AUDCLNT_SHAREMODE_EXCLUSIVE : AUDCLNT_SHAREMODE_SHARED,
AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
defaultPeriod, defaultPeriod, (WAVEFORMATEX*) &format, &session)))
{
actualNumChannels = format.Format.nChannels;
const bool isFloat = format.Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && format.SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
@@ -226706,8 +226661,8 @@ private:
class WASAPIInputDevice : public WASAPIDeviceBase
{
public:
WASAPIInputDevice (const ComSmartPtr <IMMDevice>& device_)
: WASAPIDeviceBase (device_),
WASAPIInputDevice (const ComSmartPtr <IMMDevice>& device_, const bool useExclusiveMode_)
: WASAPIDeviceBase (device_, useExclusiveMode_),
reservoir (1, 1)
{
}
@@ -226851,8 +226806,8 @@ public:
class WASAPIOutputDevice : public WASAPIDeviceBase
{
public:
WASAPIOutputDevice (const ComSmartPtr <IMMDevice>& device_)
: WASAPIDeviceBase (device_)
WASAPIOutputDevice (const ComSmartPtr <IMMDevice>& device_, const bool useExclusiveMode_)
: WASAPIDeviceBase (device_, useExclusiveMode_)
{
}

@@ -226886,7 +226841,8 @@ public:
if (! OK (client->GetCurrentPadding (&padding)))
return;

const int samplesToDo = jmin ((int) (actualBufferSize - padding), bufferSize);
int samplesToDo = useExclusiveMode ? bufferSize
: jmin ((int) (actualBufferSize - padding), bufferSize);

if (samplesToDo <= 0)
{
@@ -226944,7 +226900,8 @@ class WASAPIAudioIODevice : public AudioIODevice,
public:
WASAPIAudioIODevice (const String& deviceName,
const String& outputDeviceId_,
const String& inputDeviceId_)
const String& inputDeviceId_,
const bool useExclusiveMode_)
: AudioIODevice (deviceName, "Windows Audio"),
Thread ("Juce WASAPI"),
isOpen_ (false),
@@ -226953,6 +226910,7 @@ public:
outputDeviceId (outputDeviceId_),
inputDevice (0),
inputDeviceId (inputDeviceId_),
useExclusiveMode (useExclusiveMode_),
currentBufferSizeSamples (0),
currentSampleRate (0),
callback (0)
@@ -227205,8 +227163,8 @@ public:

while (! threadShouldExit())
{
const DWORD result = WaitForMultipleObjects (numEvents, events, true, 1000);
const DWORD result = useExclusiveMode ? WaitForSingleObject (inputDevice->clientEvent, 1000)
: WaitForMultipleObjects (numEvents, events, true, 1000);
if (result == WAIT_TIMEOUT)
continue;

@@ -227238,6 +227196,9 @@ public:
}
}

if (useExclusiveMode && WaitForSingleObject (outputDevice->clientEvent, 1000) == WAIT_TIMEOUT)
continue;

if (outputDevice != 0)
outputDevice->copyBuffers ((const float**) outputBuffers, numOutputBuffers, bufferSize, *this);
}
@@ -227252,6 +227213,7 @@ private:
// Device stats...
WASAPIInputDevice* inputDevice;
WASAPIOutputDevice* outputDevice;
const bool useExclusiveMode;
double defaultSampleRate;
int minBufferSize, defaultBufferSize;
int latencyIn, latencyOut;
@@ -227293,9 +227255,9 @@ private:
const EDataFlow flow = wasapi_getDataFlow (device);

if (deviceId == inputDeviceId && flow == eCapture)
inputDevice = new WASAPIInputDevice (device);
inputDevice = new WASAPIInputDevice (device, useExclusiveMode);
else if (deviceId == outputDeviceId && flow == eRender)
outputDevice = new WASAPIOutputDevice (device);
outputDevice = new WASAPIOutputDevice (device, useExclusiveMode);
}

return (outputDeviceId.isEmpty() || (outputDevice != 0 && outputDevice->isOk()))
@@ -227421,6 +227383,7 @@ public:
{
jassert (hasScanned); // need to call scanForDevices() before doing this

const bool useExclusiveMode = false;
WASAPIAudioIODevice* d = 0;

const int outputIndex = outputDeviceNames.indexOf (outputDeviceName);
@@ -227431,7 +227394,8 @@ public:
d = new WASAPIAudioIODevice (outputDeviceName.isNotEmpty() ? outputDeviceName
: inputDeviceName,
outputDeviceIds [outputIndex],
inputDeviceIds [inputIndex]);
inputDeviceIds [inputIndex],
useExclusiveMode);

if (! d->initialise())
deleteAndZero (d);
@@ -239295,7 +239259,7 @@ bool Desktop::isScreenSaverEnabled() throw()
return ! [[UIApplication sharedApplication] isIdleTimerDisabled];
}

void juce_updateMultiMonitorInfo (Array <Rectangle>& monitorCoords, const bool clipToWorkArea)
void juce_updateMultiMonitorInfo (Array <Rectangle <int> >& monitorCoords, const bool clipToWorkArea)
{
const ScopedAutoReleasePool pool;
monitorCoords.clear();
@@ -239611,7 +239575,7 @@ bool JUCE_CALLTYPE Process::isRunningUnderDebugger()
#define SUPPORT_10_4_FONTS 1
#define NEW_CGFONT_FUNCTIONS_UNAVAILABLE (CGFontCreateWithFontName == 0)

#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
#if (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5) || JUCE_PPC
#define SUPPORT_ONLY_10_4_FONTS 1
#endif

@@ -241952,13 +241916,13 @@ using namespace JUCE_NAMESPACE;

- (BOOL) panel: (id) sender shouldShowFilename: (NSString*) filename
{
const String fname (nsStringToJuce (filename));
const File f (nsStringToJuce (filename));

for (int i = filters->size(); --i >= 0;)
if (fname.matchesWildcard ((*filters)[i], true))
if (f.getFileName().matchesWildcard ((*filters)[i], true))
return true;

return File (fname).isDirectory();
return f.isDirectory();
}
@end

@@ -244046,7 +244010,7 @@ MidiInput* MidiInput::openDevice (int index, MidiInputCallback* callback)
#define SUPPORT_10_4_FONTS 1
#define NEW_CGFONT_FUNCTIONS_UNAVAILABLE (CGFontCreateWithFontName == 0)

#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
#if (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5) || JUCE_PPC
#define SUPPORT_ONLY_10_4_FONTS 1
#endif

@@ -248173,13 +248137,13 @@ using namespace JUCE_NAMESPACE;

- (BOOL) panel: (id) sender shouldShowFilename: (NSString*) filename
{
const String fname (nsStringToJuce (filename));
const File f (nsStringToJuce (filename));

for (int i = filters->size(); --i >= 0;)
if (fname.matchesWildcard ((*filters)[i], true))
if (f.getFileName().matchesWildcard ((*filters)[i], true))
return true;

return File (fname).isDirectory();
return f.isDirectory();
}
@end



+ 31
- 2
juce_amalgamated.h View File

@@ -1424,7 +1424,6 @@ private:
// internal constructor that preallocates a certain amount of memory
String (const int numChars, const int dummyVariable) throw();

void deleteInternal() throw();
void createInternal (const int numChars) throw();
void createInternal (const tchar* const text, const tchar* const textEnd) throw();
void appendInternal (const tchar* const text, const int numExtraChars) throw();
@@ -3144,6 +3143,8 @@ public:
static int32 decrementAndReturn (int32& variable);

static int32 compareAndExchange (int32& destination, int32 newValue, int32 requiredCurrentValue);

static void* swapPointers (void* volatile* value1, void* value2);
};

#if (JUCE_MAC || JUCE_IPHONE) // Mac and iPhone...
@@ -3154,6 +3155,12 @@ inline void Atomic::decrement (int32& variable) { OSAtomicDecrement32 ((int32_
inline int32 Atomic::decrementAndReturn (int32& variable) { return OSAtomicDecrement32 ((int32_t*) &variable); }
inline int32 Atomic::compareAndExchange (int32& destination, int32 newValue, int32 oldValue)
{ return OSAtomicCompareAndSwap32Barrier (oldValue, newValue, (int32_t*) &destination); }
inline void* Atomic::swapPointers (void* volatile* value1, void* volatile value2)
{
void* currentVal = *value1;
while (! OSAtomicCompareAndSwapPtr (currentVal, value2, value1)) { currentVal = *value1; }
return currentVal;
}

#elif JUCE_LINUX // Linux...

@@ -3163,6 +3170,12 @@ inline void Atomic::decrement (int32& variable) { __sync_add_and_fetch (&varia
inline int32 Atomic::decrementAndReturn (int32& variable) { return __sync_add_and_fetch (&variable, -1); }
inline int32 Atomic::compareAndExchange (int32& destination, int32 newValue, int32 oldValue)
{ return __sync_val_compare_and_swap (&destination, oldValue, newValue); }
inline void* Atomic::swapPointers (void* volatile* value1, void* volatile value2)
{
void* currentVal = *value1;
while (! __sync_bool_compare_and_swap (&value1, currentVal, value2)) { currentVal = *value1; }
return currentVal;
}

#elif JUCE_USE_INTRINSICS // Windows...

@@ -6692,6 +6705,22 @@ void JUCE_PUBLIC_FUNCTION initialiseJuce_NonGUI();

void JUCE_PUBLIC_FUNCTION shutdownJuce_NonGUI();

class ScopedJuceInitialiser_NonGUI
{
public:
ScopedJuceInitialiser_NonGUI() { initialiseJuce_NonGUI(); }

~ScopedJuceInitialiser_NonGUI() { shutdownJuce_NonGUI(); }
};

class ScopedJuceInitialiser_GUI
{
public:
ScopedJuceInitialiser_GUI() { initialiseJuce_GUI(); }

~ScopedJuceInitialiser_GUI() { shutdownJuce_GUI(); }
};

#endif // __JUCE_INITIALISATION_JUCEHEADER__
/*** End of inlined file: juce_Initialisation.h ***/

@@ -28181,7 +28210,7 @@ END_JUCE_NAMESPACE
// defining DONT_SET_USING_JUCE_NAMESPACE, in case there are conflicts.
using namespace JUCE_NAMESPACE;

#if JUCE_MAC && ! JUCE_DONT_DEFINE_MACROS
#if (JUCE_MAC || JUCE_IPHONE) && ! JUCE_DONT_DEFINE_MACROS
#define Component JUCE_NAMESPACE::Component
#define MemoryBlock JUCE_NAMESPACE::MemoryBlock
#define Point JUCE_NAMESPACE::Point


+ 13
- 17
src/audio/devices/juce_AudioDeviceManager.cpp View File

@@ -548,32 +548,30 @@ void AudioDeviceManager::restartLastAudioDevice()
void AudioDeviceManager::updateXml()
{
lastExplicitSettings = new XmlElement (T("DEVICESETUP"));
lastExplicitSettings = new XmlElement ("DEVICESETUP");
lastExplicitSettings->setAttribute (T("deviceType"), currentDeviceType);
lastExplicitSettings->setAttribute (T("audioOutputDeviceName"), currentSetup.outputDeviceName);
lastExplicitSettings->setAttribute (T("audioInputDeviceName"), currentSetup.inputDeviceName);
lastExplicitSettings->setAttribute ("deviceType", currentDeviceType);
lastExplicitSettings->setAttribute ("audioOutputDeviceName", currentSetup.outputDeviceName);
lastExplicitSettings->setAttribute ("audioInputDeviceName", currentSetup.inputDeviceName);
if (currentAudioDevice != 0)
{
lastExplicitSettings->setAttribute (T("audioDeviceRate"), currentAudioDevice->getCurrentSampleRate());
lastExplicitSettings->setAttribute ("audioDeviceRate", currentAudioDevice->getCurrentSampleRate());
if (currentAudioDevice->getDefaultBufferSize() != currentAudioDevice->getCurrentBufferSizeSamples())
lastExplicitSettings->setAttribute (T("audioDeviceBufferSize"), currentAudioDevice->getCurrentBufferSizeSamples());
lastExplicitSettings->setAttribute ("audioDeviceBufferSize", currentAudioDevice->getCurrentBufferSizeSamples());
if (! currentSetup.useDefaultInputChannels)
lastExplicitSettings->setAttribute (T("audioDeviceInChans"), currentSetup.inputChannels.toString (2));
lastExplicitSettings->setAttribute ("audioDeviceInChans", currentSetup.inputChannels.toString (2));
if (! currentSetup.useDefaultOutputChannels)
lastExplicitSettings->setAttribute (T("audioDeviceOutChans"), currentSetup.outputChannels.toString (2));
lastExplicitSettings->setAttribute ("audioDeviceOutChans", currentSetup.outputChannels.toString (2));
}
for (int i = 0; i < enabledMidiInputs.size(); ++i)
{
XmlElement* const m = new XmlElement (T("MIDIINPUT"));
m->setAttribute (T("name"), enabledMidiInputs[i]->getName());
lastExplicitSettings->addChildElement (m);
XmlElement* const m = lastExplicitSettings->createNewChildElement ("MIDIINPUT");
m->setAttribute ("name", enabledMidiInputs[i]->getName());
}
if (midiInsFromXml.size() > 0)
@@ -586,16 +584,14 @@ void AudioDeviceManager::updateXml()
{
if (! availableMidiDevices.contains (midiInsFromXml[i], true))
{
XmlElement* const m = new XmlElement (T("MIDIINPUT"));
m->setAttribute (T("name"), midiInsFromXml[i]);
lastExplicitSettings->addChildElement (m);
XmlElement* const m = lastExplicitSettings->createNewChildElement ("MIDIINPUT");
m->setAttribute ("name", midiInsFromXml[i]);
}
}
}
if (defaultMidiOutputName.isNotEmpty())
lastExplicitSettings->setAttribute (T("defaultMidiOutput"), defaultMidiOutputName);
lastExplicitSettings->setAttribute ("defaultMidiOutput", defaultMidiOutputName);
}
//==============================================================================


+ 1
- 4
src/containers/juce_PropertySet.cpp View File

@@ -212,12 +212,9 @@ XmlElement* PropertySet::createXml (const String& nodeName) const throw()
for (int i = 0; i < properties.getAllKeys().size(); ++i)
{
XmlElement* const e = new XmlElement (T("VALUE"));
XmlElement* const e = xml->createNewChildElement ("VALUE");
e->setAttribute (T("name"), properties.getAllKeys()[i]);
e->setAttribute (T("val"), properties.getAllValues()[i]);
xml->addChildElement (e);
}
return xml;


+ 15
- 0
src/core/juce_Atomic.h View File

@@ -50,6 +50,9 @@ public:
@returns the new value of destination
*/
static int32 compareAndExchange (int32& destination, int32 newValue, int32 requiredCurrentValue);
/** This atomically sets *value1 to be value2, and returns the previous value of *value1. */
static void* swapPointers (void* volatile* value1, void* value2);
};
@@ -62,6 +65,12 @@ inline void Atomic::decrement (int32& variable) { OSAtomicDecrem
inline int32 Atomic::decrementAndReturn (int32& variable) { return OSAtomicDecrement32 ((int32_t*) &variable); }
inline int32 Atomic::compareAndExchange (int32& destination, int32 newValue, int32 oldValue)
{ return OSAtomicCompareAndSwap32Barrier (oldValue, newValue, (int32_t*) &destination); }
inline void* Atomic::swapPointers (void* volatile* value1, void* volatile value2)
{
void* currentVal = *value1;
while (! OSAtomicCompareAndSwapPtr (currentVal, value2, value1)) { currentVal = *value1; }
return currentVal;
}
#elif JUCE_LINUX // Linux...
@@ -72,6 +81,12 @@ inline void Atomic::decrement (int32& variable) { __sync_add_and
inline int32 Atomic::decrementAndReturn (int32& variable) { return __sync_add_and_fetch (&variable, -1); }
inline int32 Atomic::compareAndExchange (int32& destination, int32 newValue, int32 oldValue)
{ return __sync_val_compare_and_swap (&destination, oldValue, newValue); }
inline void* Atomic::swapPointers (void* volatile* value1, void* volatile value2)
{
void* currentVal = *value1;
while (! __sync_bool_compare_and_swap (&value1, currentVal, value2)) { currentVal = *value1; }
return currentVal;
}
//==============================================================================
#elif JUCE_USE_INTRINSICS // Windows...


+ 50
- 0
src/core/juce_Initialisation.h View File

@@ -76,5 +76,55 @@ void JUCE_PUBLIC_FUNCTION initialiseJuce_NonGUI();
void JUCE_PUBLIC_FUNCTION shutdownJuce_NonGUI();
//==============================================================================
/** A utility object that helps you initialise and shutdown Juce correctly
using an RAII pattern.
When an instance of this class is created, it calls initialiseJuce_NonGUI(),
and when it's deleted, it calls shutdownJuce_NonGUI(), which lets you easily
make sure that these functions are matched correctly.
This class is particularly handy to use at the beginning of a console app's
main() function, because it'll take care of shutting down whenever you return
from the main() call.
@see ScopedJuceInitialiser_GUI
*/
class ScopedJuceInitialiser_NonGUI
{
public:
/** The constructor simply calls initialiseJuce_NonGUI(). */
ScopedJuceInitialiser_NonGUI() { initialiseJuce_NonGUI(); }
/** The destructor simply calls shutdownJuce_NonGUI(). */
~ScopedJuceInitialiser_NonGUI() { shutdownJuce_NonGUI(); }
};
//==============================================================================
/** A utility object that helps you initialise and shutdown Juce correctly
using an RAII pattern.
When an instance of this class is created, it calls initialiseJuce_GUI(),
and when it's deleted, it calls shutdownJuce_GUI(), which lets you easily
make sure that these functions are matched correctly.
This class is particularly handy to use at the beginning of a console app's
main() function, because it'll take care of shutting down whenever you return
from the main() call.
@see ScopedJuceInitialiser_NonGUI
*/
class ScopedJuceInitialiser_GUI
{
public:
/** The constructor simply calls initialiseJuce_GUI(). */
ScopedJuceInitialiser_GUI() { initialiseJuce_GUI(); }
/** The destructor simply calls shutdownJuce_GUI(). */
~ScopedJuceInitialiser_GUI() { shutdownJuce_GUI(); }
};
#endif // __JUCE_INITIALISATION_JUCEHEADER__

+ 13
- 15
src/gui/components/controls/juce_TableHeaderComponent.cpp View File

@@ -439,21 +439,19 @@ const String TableHeaderComponent::toString() const
{
String s;
XmlElement doc (T("TABLELAYOUT"));
XmlElement doc ("TABLELAYOUT");
doc.setAttribute (T("sortedCol"), getSortColumnId());
doc.setAttribute (T("sortForwards"), isSortedForwards());
doc.setAttribute ("sortedCol", getSortColumnId());
doc.setAttribute ("sortForwards", isSortedForwards());
for (int i = 0; i < columns.size(); ++i)
{
const ColumnInfo* const ci = columns.getUnchecked (i);
XmlElement* const e = new XmlElement (T("COLUMN"));
doc.addChildElement (e);
e->setAttribute (T("id"), ci->id);
e->setAttribute (T("visible"), ci->isVisible());
e->setAttribute (T("width"), ci->width);
XmlElement* const e = doc.createNewChildElement ("COLUMN");
e->setAttribute ("id", ci->id);
e->setAttribute ("visible", ci->isVisible());
e->setAttribute ("width", ci->width);
}
return doc.createDocument (String::empty, true, false);
@@ -466,19 +464,19 @@ void TableHeaderComponent::restoreFromString (const String& storedVersion)
int index = 0;
if (storedXml != 0 && storedXml->hasTagName (T("TABLELAYOUT")))
if (storedXml != 0 && storedXml->hasTagName ("TABLELAYOUT"))
{
forEachXmlChildElement (*storedXml, col)
{
const int tabId = col->getIntAttribute (T("id"));
const int tabId = col->getIntAttribute ("id");
ColumnInfo* const ci = getInfoForId (tabId);
if (ci != 0)
{
columns.move (columns.indexOf (ci), index);
ci->width = col->getIntAttribute (T("width"));
setColumnVisible (tabId, col->getBoolAttribute (T("visible")));
ci->width = col->getIntAttribute ("width");
setColumnVisible (tabId, col->getBoolAttribute ("visible"));
}
++index;
@@ -487,8 +485,8 @@ void TableHeaderComponent::restoreFromString (const String& storedVersion)
columnsResized = true;
sendColumnsChanged();
setSortColumnId (storedXml->getIntAttribute (T("sortedCol")),
storedXml->getBoolAttribute (T("sortForwards"), true));
setSortColumnId (storedXml->getIntAttribute ("sortedCol"),
storedXml->getBoolAttribute ("sortForwards", true));
}
}


+ 2
- 6
src/gui/components/keyboard/juce_KeyPressMappingSet.cpp View File

@@ -298,13 +298,11 @@ XmlElement* KeyPressMappingSet::createXml (const bool saveDifferencesFromDefault
if (defaultSet == 0
|| ! defaultSet->containsMapping (cm->commandID, cm->keypresses.getReference (j)))
{
XmlElement* const map = new XmlElement (T("MAPPING"));
XmlElement* const map = doc->createNewChildElement ("MAPPING");
map->setAttribute (T("commandId"), String::toHexString ((int) cm->commandID));
map->setAttribute (T("description"), commandManager->getDescriptionOfCommand (cm->commandID));
map->setAttribute (T("key"), cm->keypresses.getReference (j).getTextDescription());
doc->addChildElement (map);
}
}
}
@@ -319,13 +317,11 @@ XmlElement* KeyPressMappingSet::createXml (const bool saveDifferencesFromDefault
{
if (! containsMapping (cm->commandID, cm->keypresses.getReference (j)))
{
XmlElement* const map = new XmlElement (T("UNMAPPING"));
XmlElement* const map = doc->createNewChildElement ("UNMAPPING");
map->setAttribute (T("commandId"), String::toHexString ((int) cm->commandID));
map->setAttribute (T("description"), commandManager->getDescriptionOfCommand (cm->commandID));
map->setAttribute (T("key"), cm->keypresses.getReference (j).getTextDescription());
doc->addChildElement (map);
}
}
}


+ 3
- 4
src/gui/components/properties/juce_PropertyPanel.cpp View File

@@ -395,10 +395,9 @@ XmlElement* PropertyPanel::getOpennessState() const
{
if (sections[i].isNotEmpty())
{
XmlElement* const e = new XmlElement (T("SECTION"));
e->setAttribute (T("name"), sections[i]);
e->setAttribute (T("open"), isSectionOpen (i) ? 1 : 0);
xml->addChildElement (e);
XmlElement* const e = xml->createNewChildElement ("SECTION");
e->setAttribute ("name", sections[i]);
e->setAttribute ("open", isSectionOpen (i) ? 1 : 0);
}
}


+ 1
- 1
src/native/mac/juce_iphone_MiscUtilities.mm View File

@@ -181,7 +181,7 @@ bool Desktop::isScreenSaverEnabled() throw()
//==============================================================================
void juce_updateMultiMonitorInfo (Array <Rectangle>& monitorCoords, const bool clipToWorkArea)
void juce_updateMultiMonitorInfo (Array <Rectangle <int> >& monitorCoords, const bool clipToWorkArea)
{
const ScopedAutoReleasePool pool;
monitorCoords.clear();


+ 3
- 3
src/native/mac/juce_mac_FileChooser.mm View File

@@ -66,13 +66,13 @@ using namespace JUCE_NAMESPACE;
- (BOOL) panel: (id) sender shouldShowFilename: (NSString*) filename
{
const String fname (nsStringToJuce (filename));
const File f (nsStringToJuce (filename));
for (int i = filters->size(); --i >= 0;)
if (fname.matchesWildcard ((*filters)[i], true))
if (f.getFileName().matchesWildcard ((*filters)[i], true))
return true;
return File (fname).isDirectory();
return f.isDirectory();
}
@end


+ 1
- 1
src/native/mac/juce_mac_Fonts.mm View File

@@ -31,7 +31,7 @@
#define SUPPORT_10_4_FONTS 1
#define NEW_CGFONT_FUNCTIONS_UNAVAILABLE (CGFontCreateWithFontName == 0)
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
#if (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5) || JUCE_PPC
#define SUPPORT_ONLY_10_4_FONTS 1
#endif


+ 1
- 1
src/native/windows/juce_win32_PlatformUtils.cpp View File

@@ -55,7 +55,7 @@ static HKEY findKeyForPath (String name,
if (createForWriting)
{
if (RegCreateKeyEx (rootKey, name, 0, L"", REG_OPTION_NON_VOLATILE,
if (RegCreateKeyEx (rootKey, name, 0, 0, REG_OPTION_NON_VOLATILE,
(KEY_WRITE | KEY_QUERY_VALUE), 0, &key, &result) == ERROR_SUCCESS)
return key;
}


+ 2
- 0
src/native/windows/juce_win32_Threads.cpp View File

@@ -43,6 +43,8 @@ int32 Atomic::compareAndExchange (int32& destination, int32 newValue, int32 oldV
{ return InterlockedCompareExchange (reinterpret_cast <volatile long*> (&destination), newValue, oldValue); }
#endif
void* Atomic::swapPointers (void* volatile* value1, void* volatile value2) { return InterlockedExchangePointer (value1, value2); }
//==============================================================================
CriticalSection::CriticalSection() throw()
{


+ 35
- 17
src/native/windows/juce_win32_WASAPI.cpp View File

@@ -121,7 +121,7 @@ static void wasapi_copyWavFormat (WAVEFORMATEXTENSIBLE& dest, const WAVEFORMATEX
class WASAPIDeviceBase
{
public:
WASAPIDeviceBase (const ComSmartPtr <IMMDevice>& device_)
WASAPIDeviceBase (const ComSmartPtr <IMMDevice>& device_, const bool useExclusiveMode_)
: device (device_),
sampleRate (0),
numChannels (0),
@@ -129,7 +129,8 @@ public:
defaultSampleRate (0),
minBufferSize (0),
defaultBufferSize (0),
latencySamples (0)
latencySamples (0),
useExclusiveMode (useExclusiveMode_)
{
clientEvent = CreateEvent (0, false, false, _T("JuceWASAPI"));
@@ -166,7 +167,8 @@ public:
format.Format.nSamplesPerSec = roundDoubleToInt (ratesToTest[i]);
if (SUCCEEDED (tempClient->IsFormatSupported (AUDCLNT_SHAREMODE_SHARED, (WAVEFORMATEX*) &format, 0)))
if (SUCCEEDED (tempClient->IsFormatSupported (useExclusiveMode ? AUDCLNT_SHAREMODE_EXCLUSIVE : AUDCLNT_SHAREMODE_SHARED,
(WAVEFORMATEX*) &format, 0)))
if (! rates.contains (ratesToTest[i]))
rates.addSorted (comparator, ratesToTest[i]);
}
@@ -227,6 +229,7 @@ public:
double sampleRate, defaultSampleRate;
int numChannels, actualNumChannels;
int minBufferSize, defaultBufferSize, latencySamples;
const bool useExclusiveMode;
Array <double> rates;
HANDLE clientEvent;
BitArray channels;
@@ -284,7 +287,8 @@ private:
WAVEFORMATEXTENSIBLE* nearestFormat = 0;
HRESULT hr = client->IsFormatSupported (AUDCLNT_SHAREMODE_SHARED, (WAVEFORMATEX*) &format, (WAVEFORMATEX**) &nearestFormat);
HRESULT hr = client->IsFormatSupported (useExclusiveMode ? AUDCLNT_SHAREMODE_EXCLUSIVE : AUDCLNT_SHAREMODE_SHARED,
(WAVEFORMATEX*) &format, useExclusiveMode ? 0 : (WAVEFORMATEX**) &nearestFormat);
logFailure (hr);
if (hr == S_FALSE && format.Format.nSamplesPerSec == nearestFormat->Format.nSamplesPerSec)
@@ -295,10 +299,15 @@ private:
CoTaskMemFree (nearestFormat);
REFERENCE_TIME defaultPeriod = 0, minPeriod = 0;
if (useExclusiveMode)
OK (client->GetDevicePeriod (&defaultPeriod, &minPeriod));
GUID session;
if (hr == S_OK
&& OK (client->Initialize (AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
0, 0, (WAVEFORMATEX*) &format, &session)))
&& OK (client->Initialize (useExclusiveMode ? AUDCLNT_SHAREMODE_EXCLUSIVE : AUDCLNT_SHAREMODE_SHARED,
AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
defaultPeriod, defaultPeriod, (WAVEFORMATEX*) &format, &session)))
{
actualNumChannels = format.Format.nChannels;
const bool isFloat = format.Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && format.SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
@@ -318,8 +327,8 @@ private:
class WASAPIInputDevice : public WASAPIDeviceBase
{
public:
WASAPIInputDevice (const ComSmartPtr <IMMDevice>& device_)
: WASAPIDeviceBase (device_),
WASAPIInputDevice (const ComSmartPtr <IMMDevice>& device_, const bool useExclusiveMode_)
: WASAPIDeviceBase (device_, useExclusiveMode_),
reservoir (1, 1)
{
}
@@ -464,8 +473,8 @@ public:
class WASAPIOutputDevice : public WASAPIDeviceBase
{
public:
WASAPIOutputDevice (const ComSmartPtr <IMMDevice>& device_)
: WASAPIDeviceBase (device_)
WASAPIOutputDevice (const ComSmartPtr <IMMDevice>& device_, const bool useExclusiveMode_)
: WASAPIDeviceBase (device_, useExclusiveMode_)
{
}
@@ -499,7 +508,8 @@ public:
if (! OK (client->GetCurrentPadding (&padding)))
return;
const int samplesToDo = jmin ((int) (actualBufferSize - padding), bufferSize);
int samplesToDo = useExclusiveMode ? bufferSize
: jmin ((int) (actualBufferSize - padding), bufferSize);
if (samplesToDo <= 0)
{
@@ -558,7 +568,8 @@ class WASAPIAudioIODevice : public AudioIODevice,
public:
WASAPIAudioIODevice (const String& deviceName,
const String& outputDeviceId_,
const String& inputDeviceId_)
const String& inputDeviceId_,
const bool useExclusiveMode_)
: AudioIODevice (deviceName, "Windows Audio"),
Thread ("Juce WASAPI"),
isOpen_ (false),
@@ -567,6 +578,7 @@ public:
outputDeviceId (outputDeviceId_),
inputDevice (0),
inputDeviceId (inputDeviceId_),
useExclusiveMode (useExclusiveMode_),
currentBufferSizeSamples (0),
currentSampleRate (0),
callback (0)
@@ -820,8 +832,8 @@ public:
while (! threadShouldExit())
{
const DWORD result = WaitForMultipleObjects (numEvents, events, true, 1000);
const DWORD result = useExclusiveMode ? WaitForSingleObject (inputDevice->clientEvent, 1000)
: WaitForMultipleObjects (numEvents, events, true, 1000);
if (result == WAIT_TIMEOUT)
continue;
@@ -853,6 +865,9 @@ public:
}
}
if (useExclusiveMode && WaitForSingleObject (outputDevice->clientEvent, 1000) == WAIT_TIMEOUT)
continue;
if (outputDevice != 0)
outputDevice->copyBuffers ((const float**) outputBuffers, numOutputBuffers, bufferSize, *this);
}
@@ -869,6 +884,7 @@ private:
// Device stats...
WASAPIInputDevice* inputDevice;
WASAPIOutputDevice* outputDevice;
const bool useExclusiveMode;
double defaultSampleRate;
int minBufferSize, defaultBufferSize;
int latencyIn, latencyOut;
@@ -911,9 +927,9 @@ private:
const EDataFlow flow = wasapi_getDataFlow (device);
if (deviceId == inputDeviceId && flow == eCapture)
inputDevice = new WASAPIInputDevice (device);
inputDevice = new WASAPIInputDevice (device, useExclusiveMode);
else if (deviceId == outputDeviceId && flow == eRender)
outputDevice = new WASAPIOutputDevice (device);
outputDevice = new WASAPIOutputDevice (device, useExclusiveMode);
}
return (outputDeviceId.isEmpty() || (outputDevice != 0 && outputDevice->isOk()))
@@ -1043,6 +1059,7 @@ public:
{
jassert (hasScanned); // need to call scanForDevices() before doing this
const bool useExclusiveMode = false;
WASAPIAudioIODevice* d = 0;
const int outputIndex = outputDeviceNames.indexOf (outputDeviceName);
@@ -1053,7 +1070,8 @@ public:
d = new WASAPIAudioIODevice (outputDeviceName.isNotEmpty() ? outputDeviceName
: inputDeviceName,
outputDeviceIds [outputIndex],
inputDeviceIds [inputIndex]);
inputDeviceIds [inputIndex],
useExclusiveMode);
if (! d->initialise())
deleteAndZero (d);


+ 17
- 57
src/text/juce_String.cpp View File

@@ -56,12 +56,6 @@ void juce_initialiseStrings()
}
//==============================================================================
void String::deleteInternal() throw()
{
if (Atomic::decrementAndReturn (text->refCount) == 0)
juce_free (text);
}
void String::createInternal (const int numChars) throw()
{
jassert (numChars > 0);
@@ -592,32 +586,7 @@ int64 String::hashCode64() const throw()
//==============================================================================
const String& String::operator= (const tchar* const otherText) throw()
{
if (otherText != 0 && *otherText != 0)
{
const int otherLen = CharacterFunctions::length (otherText);
if (otherLen > 0)
{
// avoid resizing the memory block if the string is
// shrinking..
if (text->refCount > 1
|| otherLen > text->allocatedNumChars
|| otherLen <= (text->allocatedNumChars >> 1))
{
deleteInternal();
createInternal (otherLen);
}
memcpy (text->text, otherText, (otherLen + 1) * sizeof (tchar));
return *this;
}
}
deleteInternal();
text = &emptyString;
emptyString.refCount = safeEmptyStringRefCount;
operator= (String (otherText));
return *this;
}
@@ -625,12 +594,14 @@ const String& String::operator= (const String& other) throw()
{
if (this != &other)
{
Atomic::increment (other.text->refCount);
InternalRefCountedStringHolder* newText = other.text;
Atomic::increment (newText->refCount);
if (Atomic::decrementAndReturn (text->refCount) == 0)
juce_free (text);
InternalRefCountedStringHolder* oldText
= (InternalRefCountedStringHolder*) Atomic::swapPointers ((void* volatile*) &text, newText);
text = other.text;
if (Atomic::decrementAndReturn (oldText->refCount) == 0)
juce_free (oldText);
}
return *this;
@@ -1282,47 +1253,36 @@ const String String::formatted (const tchar* const pf, ...) throw()
//==============================================================================
void String::vprintf (const tchar* const pf, va_list& args) throw()
{
tchar stackBuf [256];
unsigned int bufSize = 256;
tchar* buf = stackBuf;
deleteInternal();
int bufferSize = 256;
String result (bufferSize, 0);
do
{
#if JUCE_LINUX && JUCE_64BIT
va_list tempArgs;
va_copy (tempArgs, args);
const int num = CharacterFunctions::vprintf (buf, bufSize - 1, pf, tempArgs);
const int num = CharacterFunctions::vprintf (result.text->text, bufferSize - 1, pf, tempArgs);
va_end (tempArgs);
#else
const int num = CharacterFunctions::vprintf (buf, bufSize - 1, pf, args);
const int num = CharacterFunctions::vprintf (result.text->text, bufferSize - 1, pf, args);
#endif
if (num > 0)
{
createInternal (num);
memcpy (text->text, buf, (num + 1) * sizeof (tchar));
*this = result;
break;
}
else if (num == 0)
{
text = &emptyString;
emptyString.refCount = safeEmptyStringRefCount;
*this = String::empty;
break;
}
if (buf != stackBuf)
juce_free (buf);
bufSize += 256;
buf = (tchar*) juce_malloc (bufSize * sizeof (tchar));
bufferSize += 256;
result.preallocateStorage (bufferSize);
}
while (bufSize < 65536); // this is a sanity check to avoid situations where vprintf repeatedly
// returns -1 because of an error rather than because it needs more space.
if (buf != stackBuf)
juce_free (buf);
while (bufferSize < 65536); // this is a sanity check to avoid situations where vprintf repeatedly
// returns -1 because of an error rather than because it needs more space.
}
//==============================================================================


+ 0
- 1
src/text/juce_String.h View File

@@ -1117,7 +1117,6 @@ private:
// internal constructor that preallocates a certain amount of memory
String (const int numChars, const int dummyVariable) throw();
void deleteInternal() throw();
void createInternal (const int numChars) throw();
void createInternal (const tchar* const text, const tchar* const textEnd) throw();
void appendInternal (const tchar* const text, const int numExtraChars) throw();


+ 1
- 3
src/utilities/juce_PropertiesFile.cpp View File

@@ -164,7 +164,7 @@ bool PropertiesFile::save()
for (int i = 0; i < getAllProperties().size(); ++i)
{
XmlElement* const e = new XmlElement (propertyTagName);
XmlElement* const e = doc.createNewChildElement (propertyTagName);
e->setAttribute (T("name"), getAllProperties().getAllKeys() [i]);
// if the value seems to contain xml, store it as such..
@@ -175,8 +175,6 @@ bool PropertiesFile::save()
e->addChildElement (childElement);
else
e->setAttribute (T("val"), getAllProperties().getAllValues() [i]);
doc.addChildElement (e);
}
return doc.writeToFile (file, String::empty);


Loading…
Cancel
Save