@@ -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 | |||
@@ -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 | |||
@@ -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 | |||
@@ -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); | |||
} | |||
//============================================================================== | |||
@@ -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; | |||
@@ -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... | |||
@@ -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__ |
@@ -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)); | |||
} | |||
} | |||
@@ -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); | |||
} | |||
} | |||
} | |||
@@ -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); | |||
} | |||
} | |||
@@ -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(); | |||
@@ -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 | |||
@@ -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 | |||
@@ -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; | |||
} | |||
@@ -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() | |||
{ | |||
@@ -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); | |||
@@ -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. | |||
} | |||
//============================================================================== | |||
@@ -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(); | |||
@@ -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); | |||