| @@ -646,6 +646,10 @@ | |||
| #include <dwrite.h> | |||
| #endif | |||
| #ifndef WM_APPCOMMAND | |||
| #define WM_APPCOMMAND 0x0319 | |||
| #endif | |||
| /** A simple COM smart pointer. | |||
| Avoids having to include ATL just to get one of these. | |||
| */ | |||
| @@ -1716,20 +1720,6 @@ const String SystemStats::getJUCEVersion() | |||
| static JuceVersionPrinter juceVersionPrinter; | |||
| #endif | |||
| #ifdef JUCE_DLL | |||
| void* juce_Malloc (int size) { return malloc (size); } | |||
| void* juce_Calloc (int size) { return calloc (1, size); } | |||
| void* juce_Realloc (void* block, int size) { return realloc (block, size); } | |||
| void juce_Free (void* block) { free (block); } | |||
| #if JUCE_MSVC && JUCE_CHECK_MEMORY_LEAKS | |||
| void* juce_DebugMalloc (int size, const char* file, int line) { return _malloc_dbg (size, _NORMAL_BLOCK, file, line); } | |||
| void* juce_DebugCalloc (int size, const char* file, int line) { return _calloc_dbg (1, size, _NORMAL_BLOCK, file, line); } | |||
| void* juce_DebugRealloc (void* block, int size, const char* file, int line) { return _realloc_dbg (block, size, _NORMAL_BLOCK, file, line); } | |||
| void juce_DebugFree (void* block) { _free_dbg (block, _NORMAL_BLOCK); } | |||
| #endif | |||
| #endif | |||
| END_JUCE_NAMESPACE | |||
| /*** End of inlined file: juce_SystemStats.cpp ***/ | |||
| @@ -2032,7 +2022,9 @@ uint32 Time::getMillisecondCounter() noexcept | |||
| uint32 Time::getApproximateMillisecondCounter() noexcept | |||
| { | |||
| jassert (TimeHelpers::lastMSCounterValue != 0); | |||
| if (TimeHelpers::lastMSCounterValue == 0) | |||
| getMillisecondCounter(); | |||
| return TimeHelpers::lastMSCounterValue; | |||
| } | |||
| @@ -4164,7 +4156,7 @@ Identifier::Identifier (const String& name_) | |||
| { | |||
| /* An Identifier string must be suitable for use as a script variable or XML | |||
| attribute, so it can only contain this limited set of characters.. */ | |||
| jassert (name_.containsOnly ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_") && name_.isNotEmpty()); | |||
| jassert (isValidIdentifier (name_)); | |||
| } | |||
| Identifier::Identifier (const char* const name_) | |||
| @@ -4172,13 +4164,19 @@ Identifier::Identifier (const char* const name_) | |||
| { | |||
| /* An Identifier string must be suitable for use as a script variable or XML | |||
| attribute, so it can only contain this limited set of characters.. */ | |||
| jassert (toString().containsOnly ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_") && toString().isNotEmpty()); | |||
| jassert (isValidIdentifier (toString())); | |||
| } | |||
| Identifier::~Identifier() | |||
| { | |||
| } | |||
| bool Identifier::isValidIdentifier (const String& possibleIdentifier) noexcept | |||
| { | |||
| return possibleIdentifier.isNotEmpty() | |||
| && possibleIdentifier.containsOnly ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"); | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| /*** End of inlined file: juce_Identifier.cpp ***/ | |||
| @@ -4740,7 +4738,7 @@ const var NamedValueSet::getWithDefault (const Identifier& name, const var& defa | |||
| return v != nullptr ? *v : defaultReturnValue; | |||
| } | |||
| var* NamedValueSet::getVarPointer (const Identifier& name) const | |||
| var* NamedValueSet::getVarPointer (const Identifier& name) const noexcept | |||
| { | |||
| for (NamedValue* i = values; i != nullptr; i = i->nextListItem) | |||
| if (i->name == name) | |||
| @@ -13550,7 +13548,7 @@ struct StringCopier | |||
| jassert (maxBufferSizeBytes >= 0); // keep this value positive, or no characters will be copied! | |||
| if (buffer == nullptr) | |||
| return (int) CharPointerType_Dest::getBytesRequiredFor (source); | |||
| return (int) (CharPointerType_Dest::getBytesRequiredFor (source) + sizeof (typename CharPointerType_Dest::CharType)); | |||
| return CharPointerType_Dest (buffer).writeWithDestByteLimit (source, maxBufferSizeBytes); | |||
| } | |||
| @@ -24596,7 +24594,7 @@ void AudioTransportSource::setSource (PositionableAudioSource* const newSource, | |||
| if (readAheadBufferSize_ > 0) | |||
| newPositionableSource = newBufferingSource | |||
| = new BufferingAudioSource (newPositionableSource, false, readAheadBufferSize_); | |||
| = new BufferingAudioSource (newPositionableSource, false, readAheadBufferSize_, maxNumChannels); | |||
| newPositionableSource->setNextReadPosition (0); | |||
| @@ -24897,11 +24895,13 @@ juce_ImplementSingleton (SharedBufferingAudioSourceThread) | |||
| BufferingAudioSource::BufferingAudioSource (PositionableAudioSource* source_, | |||
| const bool deleteSourceWhenDeleted_, | |||
| int numberOfSamplesToBuffer_) | |||
| const int numberOfSamplesToBuffer_, | |||
| const int numberOfChannels_) | |||
| : source (source_), | |||
| deleteSourceWhenDeleted (deleteSourceWhenDeleted_), | |||
| numberOfSamplesToBuffer (jmax (1024, numberOfSamplesToBuffer_)), | |||
| buffer (2, 0), | |||
| numberOfChannels (numberOfChannels_), | |||
| buffer (numberOfChannels_, 0), | |||
| bufferValidStart (0), | |||
| bufferValidEnd (0), | |||
| nextPlayPos (0), | |||
| @@ -24930,7 +24930,7 @@ void BufferingAudioSource::prepareToPlay (int samplesPerBlockExpected, double sa | |||
| sampleRate = sampleRate_; | |||
| buffer.setSize (2, jmax (samplesPerBlockExpected * 2, numberOfSamplesToBuffer)); | |||
| buffer.setSize (numberOfChannels, jmax (samplesPerBlockExpected * 2, numberOfSamplesToBuffer)); | |||
| buffer.clear(); | |||
| bufferValidStart = 0; | |||
| @@ -24953,7 +24953,7 @@ void BufferingAudioSource::releaseResources() | |||
| if (thread != nullptr) | |||
| thread->removeSource (this); | |||
| buffer.setSize (2, 0); | |||
| buffer.setSize (numberOfChannels, 0); | |||
| source->releaseResources(); | |||
| } | |||
| @@ -24980,7 +24980,7 @@ void BufferingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& info | |||
| if (validStart < validEnd) | |||
| { | |||
| for (int chan = jmin (2, info.buffer->getNumChannels()); --chan >= 0;) | |||
| for (int chan = jmin (numberOfChannels, info.buffer->getNumChannels()); --chan >= 0;) | |||
| { | |||
| const int startBufferIndex = (validStart + nextPlayPos) % buffer.getNumSamples(); | |||
| const int endBufferIndex = (validEnd + nextPlayPos) % buffer.getNumSamples(); | |||
| @@ -40070,13 +40070,14 @@ public: | |||
| { | |||
| const uint32 now = Time::getMillisecondCounter(); | |||
| if (now <= lastTime) | |||
| if (now == lastTime) | |||
| { | |||
| wait (2); | |||
| wait (1); | |||
| continue; | |||
| } | |||
| const int elapsed = now - lastTime; | |||
| const int elapsed = now >= lastTime ? (now - lastTime) | |||
| : (std::numeric_limits<uint32>::max() - (lastTime - now)); | |||
| lastTime = now; | |||
| const int timeUntilFirstTimer = getTimeUntilFirstTimer (elapsed); | |||
| @@ -70513,20 +70514,22 @@ public: | |||
| { | |||
| if (isVisible()) | |||
| { | |||
| WeakReference<Component> deletionChecker (this); | |||
| activeSubMenu = nullptr; | |||
| currentChild = nullptr; | |||
| exitModalState (item != nullptr ? item->itemId : 0); | |||
| if (makeInvisible) | |||
| setVisible (false); | |||
| if (item != nullptr | |||
| && item->commandManager != nullptr | |||
| && item->itemId != 0) | |||
| { | |||
| *managerOfChosenCommand = item->commandManager; | |||
| } | |||
| exitModalState (item != nullptr ? item->itemId : 0); | |||
| if (makeInvisible && (deletionChecker != nullptr)) | |||
| setVisible (false); | |||
| } | |||
| } | |||
| @@ -79046,9 +79049,7 @@ void ComponentPeer::addMaskedRegion (int x, int y, int w, int h) | |||
| const StringArray ComponentPeer::getAvailableRenderingEngines() | |||
| { | |||
| StringArray s; | |||
| s.add ("Software Renderer"); | |||
| return s; | |||
| return StringArray ("Software Renderer"); | |||
| } | |||
| int ComponentPeer::getCurrentRenderingEngine() const | |||
| @@ -79701,12 +79702,12 @@ void ResizableWindow::resized() | |||
| { | |||
| if (resizableBorder != nullptr) | |||
| { | |||
| #if JUCE_WINDOWS || JUCE_LINUX | |||
| #if JUCE_WINDOWS || JUCE_LINUX | |||
| // hide the resizable border if the OS already provides one.. | |||
| resizableBorder->setVisible (! (isFullScreen() || isUsingNativeTitleBar())); | |||
| #else | |||
| #else | |||
| resizableBorder->setVisible (! isFullScreen()); | |||
| #endif | |||
| #endif | |||
| resizableBorder->setBorderThickness (getBorderThickness()); | |||
| resizableBorder->setSize (getWidth(), getHeight()); | |||
| @@ -79715,12 +79716,12 @@ void ResizableWindow::resized() | |||
| if (resizableCorner != nullptr) | |||
| { | |||
| #if JUCE_MAC | |||
| #if JUCE_MAC | |||
| // hide the resizable border if the OS already provides one.. | |||
| resizableCorner->setVisible (! (isFullScreen() || isUsingNativeTitleBar())); | |||
| #else | |||
| #else | |||
| resizableCorner->setVisible (! isFullScreen()); | |||
| #endif | |||
| #endif | |||
| const int resizerSize = 18; | |||
| resizableCorner->setBounds (getWidth() - resizerSize, | |||
| @@ -79733,9 +79734,9 @@ void ResizableWindow::resized() | |||
| updateLastPos(); | |||
| #if JUCE_DEBUG | |||
| #if JUCE_DEBUG | |||
| hasBeenResized = true; | |||
| #endif | |||
| #endif | |||
| } | |||
| void ResizableWindow::childBoundsChanged (Component* child) | |||
| @@ -79862,7 +79863,7 @@ void ResizableWindow::paint (Graphics& g) | |||
| getBorderThickness(), *this); | |||
| } | |||
| #if JUCE_DEBUG | |||
| #if JUCE_DEBUG | |||
| /* If this fails, then you've probably written a subclass with a resized() | |||
| callback but forgotten to make it call its parent class's resized() method. | |||
| @@ -79875,7 +79876,7 @@ void ResizableWindow::paint (Graphics& g) | |||
| layout. | |||
| */ | |||
| jassert (hasBeenResized || (getWidth() == 0 && getHeight() == 0)); | |||
| #endif | |||
| #endif | |||
| } | |||
| void ResizableWindow::lookAndFeelChanged() | |||
| @@ -243769,6 +243770,11 @@ void Logger::outputDebugString (const String& text) | |||
| OutputDebugString ((text + "\n").toWideCharPointer()); | |||
| } | |||
| #ifdef JUCE_DLL | |||
| JUCE_API void* juceDLL_malloc (size_t sz) { return ::malloc (sz); } | |||
| JUCE_API void juceDLL_free (void* block) { ::free (block); } | |||
| #endif | |||
| #if JUCE_USE_INTRINSICS || JUCE_64BIT | |||
| // CPU info functions using intrinsics... | |||
| @@ -244191,10 +244197,10 @@ void JUCE_API juce_threadEntryPoint (void*); | |||
| static unsigned int __stdcall threadEntryProc (void* userData) | |||
| { | |||
| #if ! JUCE_ONLY_BUILD_CORE_LIBRARY | |||
| #if ! JUCE_ONLY_BUILD_CORE_LIBRARY | |||
| AttachThreadInput (GetWindowThreadProcessId (juce_messageWindowHandle, 0), | |||
| GetCurrentThreadId(), TRUE); | |||
| #endif | |||
| #endif | |||
| juce_threadEntryPoint (userData); | |||
| @@ -244220,16 +244226,16 @@ void Thread::killThread() | |||
| { | |||
| if (threadHandle_ != 0) | |||
| { | |||
| #if JUCE_DEBUG | |||
| #if JUCE_DEBUG | |||
| OutputDebugString (_T("** Warning - Forced thread termination **\n")); | |||
| #endif | |||
| #endif | |||
| TerminateThread (threadHandle_, 0); | |||
| } | |||
| } | |||
| void Thread::setCurrentThreadName (const String& name) | |||
| { | |||
| #if JUCE_DEBUG && JUCE_MSVC | |||
| #if JUCE_DEBUG && JUCE_MSVC | |||
| struct | |||
| { | |||
| DWORD dwType; | |||
| @@ -244249,9 +244255,9 @@ void Thread::setCurrentThreadName (const String& name) | |||
| } | |||
| __except (EXCEPTION_CONTINUE_EXECUTION) | |||
| {} | |||
| #else | |||
| #else | |||
| (void) name; | |||
| #endif | |||
| #endif | |||
| } | |||
| Thread::ThreadID Thread::getCurrentThreadId() | |||
| @@ -244397,7 +244403,7 @@ void PlatformUtilities::freeDynamicLibrary (void* h) | |||
| { | |||
| JUCE_TRY | |||
| { | |||
| if (h != 0) | |||
| if (h != nullptr) | |||
| FreeLibrary ((HMODULE) h); | |||
| } | |||
| JUCE_CATCH_ALL | |||
| @@ -244405,7 +244411,7 @@ void PlatformUtilities::freeDynamicLibrary (void* h) | |||
| void* PlatformUtilities::getProcedureEntryPoint (void* h, const String& name) | |||
| { | |||
| return (h != 0) ? (void*) GetProcAddress ((HMODULE) h, name.toUTF8()) : nullptr; // (void* cast is required for mingw) | |||
| return (h != nullptr) ? (void*) GetProcAddress ((HMODULE) h, name.toUTF8()) : nullptr; // (void* cast is required for mingw) | |||
| } | |||
| class InterProcessLock::Pimpl | |||
| @@ -245366,11 +245372,11 @@ void NamedPipe::cancelPendingReads() | |||
| #if JUCE_INCLUDED_FILE | |||
| #ifndef INTERNET_FLAG_NEED_FILE | |||
| #define INTERNET_FLAG_NEED_FILE 0x00000010 | |||
| #define INTERNET_FLAG_NEED_FILE 0x00000010 | |||
| #endif | |||
| #ifndef INTERNET_OPTION_DISABLE_AUTODIAL | |||
| #define INTERNET_OPTION_DISABLE_AUTODIAL 70 | |||
| #define INTERNET_OPTION_DISABLE_AUTODIAL 70 | |||
| #endif | |||
| #ifndef WORKAROUND_TIMEOUT_BUG | |||
| @@ -246040,10 +246046,6 @@ HWND juce_messageWindowHandle = 0; | |||
| extern long improbableWindowNumber; // defined in windowing.cpp | |||
| #ifndef WM_APPCOMMAND | |||
| #define WM_APPCOMMAND 0x0319 | |||
| #endif | |||
| static LRESULT CALLBACK juce_MessageWndProc (HWND h, | |||
| const UINT message, | |||
| const WPARAM wParam, | |||
| @@ -247570,7 +247572,6 @@ private: | |||
| #define APPCOMMAND_MEDIA_PREVIOUSTRACK 12 | |||
| #define APPCOMMAND_MEDIA_STOP 13 | |||
| #define APPCOMMAND_MEDIA_PLAY_PAUSE 14 | |||
| #define WM_APPCOMMAND 0x0319 | |||
| #endif | |||
| extern void juce_repeatLastProcessPriority(); // in juce_win32_Threads.cpp | |||
| @@ -252279,29 +252280,32 @@ typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int* piAt | |||
| typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval); | |||
| typedef int (WINAPI * PFNWGLGETSWAPINTERVALEXTPROC) (void); | |||
| #define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 | |||
| #define WGL_DRAW_TO_WINDOW_ARB 0x2001 | |||
| #define WGL_ACCELERATION_ARB 0x2003 | |||
| #define WGL_SWAP_METHOD_ARB 0x2007 | |||
| #define WGL_SUPPORT_OPENGL_ARB 0x2010 | |||
| #define WGL_PIXEL_TYPE_ARB 0x2013 | |||
| #define WGL_DOUBLE_BUFFER_ARB 0x2011 | |||
| #define WGL_COLOR_BITS_ARB 0x2014 | |||
| #define WGL_RED_BITS_ARB 0x2015 | |||
| #define WGL_GREEN_BITS_ARB 0x2017 | |||
| #define WGL_BLUE_BITS_ARB 0x2019 | |||
| #define WGL_ALPHA_BITS_ARB 0x201B | |||
| #define WGL_DEPTH_BITS_ARB 0x2022 | |||
| #define WGL_STENCIL_BITS_ARB 0x2023 | |||
| #define WGL_FULL_ACCELERATION_ARB 0x2027 | |||
| #define WGL_ACCUM_RED_BITS_ARB 0x201E | |||
| #define WGL_ACCUM_GREEN_BITS_ARB 0x201F | |||
| #define WGL_ACCUM_BLUE_BITS_ARB 0x2020 | |||
| #define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 | |||
| #define WGL_STEREO_ARB 0x2012 | |||
| #define WGL_SAMPLE_BUFFERS_ARB 0x2041 | |||
| #define WGL_SAMPLES_ARB 0x2042 | |||
| #define WGL_TYPE_RGBA_ARB 0x202B | |||
| enum | |||
| { | |||
| WGL_NUMBER_PIXEL_FORMATS_ARB = 0x2000, | |||
| WGL_DRAW_TO_WINDOW_ARB = 0x2001, | |||
| WGL_ACCELERATION_ARB = 0x2003, | |||
| WGL_SWAP_METHOD_ARB = 0x2007, | |||
| WGL_SUPPORT_OPENGL_ARB = 0x2010, | |||
| WGL_PIXEL_TYPE_ARB = 0x2013, | |||
| WGL_DOUBLE_BUFFER_ARB = 0x2011, | |||
| WGL_COLOR_BITS_ARB = 0x2014, | |||
| WGL_RED_BITS_ARB = 0x2015, | |||
| WGL_GREEN_BITS_ARB = 0x2017, | |||
| WGL_BLUE_BITS_ARB = 0x2019, | |||
| WGL_ALPHA_BITS_ARB = 0x201B, | |||
| WGL_DEPTH_BITS_ARB = 0x2022, | |||
| WGL_STENCIL_BITS_ARB = 0x2023, | |||
| WGL_FULL_ACCELERATION_ARB = 0x2027, | |||
| WGL_ACCUM_RED_BITS_ARB = 0x201E, | |||
| WGL_ACCUM_GREEN_BITS_ARB = 0x201F, | |||
| WGL_ACCUM_BLUE_BITS_ARB = 0x2020, | |||
| WGL_ACCUM_ALPHA_BITS_ARB = 0x2021, | |||
| WGL_STEREO_ARB = 0x2012, | |||
| WGL_SAMPLE_BUFFERS_ARB = 0x2041, | |||
| WGL_SAMPLES_ARB = 0x2042, | |||
| WGL_TYPE_RGBA_ARB = 0x202B | |||
| }; | |||
| static void getWglExtensions (HDC dc, StringArray& result) noexcept | |||
| { | |||
| @@ -261987,7 +261991,7 @@ int64 Time::getHighResolutionTicks() noexcept | |||
| timespec t; | |||
| clock_gettime (CLOCK_MONOTONIC, &t); | |||
| return (t.tv_sec * (int64) 1000000) + (t.tv_nsec / (int64) 1000); | |||
| return (t.tv_sec * (int64) 1000000) + (t.tv_nsec / 1000); | |||
| } | |||
| int64 Time::getHighResolutionTicksPerSecond() noexcept | |||
| @@ -269340,13 +269344,15 @@ public: | |||
| { | |||
| mach_timebase_info_data_t timebase; | |||
| (void) mach_timebase_info (&timebase); | |||
| highResTimerFrequency = (int64) (1.0e9 * timebase.denom / timebase.numer); | |||
| highResTimerToMillisecRatio = timebase.numer / (1.0e6 * timebase.denom); | |||
| highResTimerFrequency = (timebase.denom * (int64) 1000000000) / timebase.numer; | |||
| numerator = timebase.numer; | |||
| denominator = timebase.denom * (int64) 1000000; | |||
| highResTimerToMillisecRatio = numerator / (double) denominator; | |||
| } | |||
| inline uint32 millisecondsSinceStartup() const noexcept | |||
| { | |||
| return (uint32) (mach_absolute_time() * highResTimerToMillisecRatio); | |||
| return (uint32) ((mach_absolute_time() * numerator) / denominator); | |||
| } | |||
| inline double getMillisecondCounterHiRes() const noexcept | |||
| @@ -269355,6 +269361,9 @@ public: | |||
| } | |||
| int64 highResTimerFrequency; | |||
| private: | |||
| int64 numerator, denominator; | |||
| double highResTimerToMillisecRatio; | |||
| }; | |||
| @@ -271813,8 +271822,6 @@ public: | |||
| timerCallback(); | |||
| } | |||
| ~ScreenSaverDefeater() {} | |||
| void timerCallback() | |||
| { | |||
| if (Process::isForegroundProcess()) | |||
| @@ -286929,7 +286936,7 @@ int64 Time::getHighResolutionTicks() noexcept | |||
| timespec t; | |||
| clock_gettime (CLOCK_MONOTONIC, &t); | |||
| return (t.tv_sec * (int64) 1000000) + (t.tv_nsec / (int64) 1000); | |||
| return (t.tv_sec * (int64) 1000000) + (t.tv_nsec / 1000); | |||
| } | |||
| int64 Time::getHighResolutionTicksPerSecond() noexcept | |||
| @@ -73,7 +73,7 @@ namespace JuceDummyNamespace {} | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 53 | |||
| #define JUCE_BUILDNUMBER 85 | |||
| #define JUCE_BUILDNUMBER 86 | |||
| /** Current Juce version number. | |||
| @@ -895,102 +895,6 @@ extern JUCE_API bool JUCE_CALLTYPE juce_isRunningUnderDebugger(); | |||
| #ifndef __JUCE_MEMORY_JUCEHEADER__ | |||
| #define __JUCE_MEMORY_JUCEHEADER__ | |||
| /* | |||
| This file defines the various juce_malloc(), juce_free() macros that can be used in | |||
| preference to the standard calls. | |||
| None of this stuff is actually used in the library itself, and will probably be | |||
| deprecated at some point in the future, to force everyone to use HeapBlock and other | |||
| safer allocation methods. | |||
| */ | |||
| #if JUCE_MSVC && JUCE_CHECK_MEMORY_LEAKS && ! DOXYGEN | |||
| #ifndef JUCE_DLL | |||
| // Win32 debug non-DLL versions.. | |||
| #define juce_malloc(numBytes) _malloc_dbg (numBytes, _NORMAL_BLOCK, __FILE__, __LINE__) | |||
| #define juce_calloc(numBytes) _calloc_dbg (1, numBytes, _NORMAL_BLOCK, __FILE__, __LINE__) | |||
| #define juce_realloc(location, numBytes) _realloc_dbg (location, numBytes, _NORMAL_BLOCK, __FILE__, __LINE__) | |||
| #define juce_free(location) _free_dbg (location, _NORMAL_BLOCK) | |||
| #else | |||
| // Win32 debug DLL versions.. | |||
| // For the DLL, we'll define some functions in the DLL that will be used for allocation - that | |||
| // way all juce calls in the DLL and in the host API will all use the same allocator. | |||
| extern JUCE_API void* juce_DebugMalloc (int size, const char* file, int line); | |||
| extern JUCE_API void* juce_DebugCalloc (int size, const char* file, int line); | |||
| extern JUCE_API void* juce_DebugRealloc (void* block, int size, const char* file, int line); | |||
| extern JUCE_API void juce_DebugFree (void* block); | |||
| #define juce_malloc(numBytes) JUCE_NAMESPACE::juce_DebugMalloc (numBytes, __FILE__, __LINE__) | |||
| #define juce_calloc(numBytes) JUCE_NAMESPACE::juce_DebugCalloc (numBytes, __FILE__, __LINE__) | |||
| #define juce_realloc(location, numBytes) JUCE_NAMESPACE::juce_DebugRealloc (location, numBytes, __FILE__, __LINE__) | |||
| #define juce_free(location) JUCE_NAMESPACE::juce_DebugFree (location) | |||
| #define JUCE_LEAK_DETECTOR(OwnerClass) public:\ | |||
| static void* operator new (size_t sz) { void* const p = juce_malloc ((int) sz); return (p != 0) ? p : ::operator new (sz); } \ | |||
| static void* operator new (size_t, void* p) { return p; } \ | |||
| static void operator delete (void* p) { juce_free (p); } \ | |||
| static void operator delete (void*, void*) {} | |||
| #endif | |||
| #elif defined (JUCE_DLL) && ! DOXYGEN | |||
| // Win32 DLL (release) versions.. | |||
| // For the DLL, we'll define some functions in the DLL that will be used for allocation - that | |||
| // way all juce calls in the DLL and in the host API will all use the same allocator. | |||
| extern JUCE_API void* juce_Malloc (int size); | |||
| extern JUCE_API void* juce_Calloc (int size); | |||
| extern JUCE_API void* juce_Realloc (void* block, int size); | |||
| extern JUCE_API void juce_Free (void* block); | |||
| #define juce_malloc(numBytes) JUCE_NAMESPACE::juce_Malloc (numBytes) | |||
| #define juce_calloc(numBytes) JUCE_NAMESPACE::juce_Calloc (numBytes) | |||
| #define juce_realloc(location, numBytes) JUCE_NAMESPACE::juce_Realloc (location, numBytes) | |||
| #define juce_free(location) JUCE_NAMESPACE::juce_Free (location) | |||
| #define JUCE_LEAK_DETECTOR(OwnerClass) public:\ | |||
| static void* operator new (size_t sz) { void* const p = juce_malloc ((int) sz); return (p != 0) ? p : ::operator new (sz); } \ | |||
| static void* operator new (size_t, void* p) { return p; } \ | |||
| static void operator delete (void* p) { juce_free (p); } \ | |||
| static void operator delete (void*, void*) {} | |||
| #else | |||
| // Mac, Linux and Win32 (release) versions.. | |||
| /** This can be used instead of calling malloc directly. | |||
| Only use direct memory allocation if there's really no way to use a HeapBlock object instead! | |||
| */ | |||
| #define juce_malloc(numBytes) malloc (numBytes) | |||
| /** This can be used instead of calling calloc directly. | |||
| Only use direct memory allocation if there's really no way to use a HeapBlock object instead! | |||
| */ | |||
| #define juce_calloc(numBytes) calloc (1, numBytes) | |||
| /** This can be used instead of calling realloc directly. | |||
| Only use direct memory allocation if there's really no way to use a HeapBlock object instead! | |||
| */ | |||
| #define juce_realloc(location, numBytes) realloc (location, numBytes) | |||
| /** This can be used instead of calling free directly. | |||
| Only use direct memory allocation if there's really no way to use a HeapBlock object instead! | |||
| */ | |||
| #define juce_free(location) free (location) | |||
| #endif | |||
| /** (Deprecated) This was a win32-specific way of checking for object leaks - now please | |||
| use the JUCE_LEAK_DETECTOR instead. | |||
| */ | |||
| #ifndef juce_UseDebuggingNewOperator | |||
| #define juce_UseDebuggingNewOperator | |||
| #endif | |||
| #if JUCE_MSVC || DOXYGEN | |||
| /** This is a compiler-independent way of declaring a variable as being thread-local. | |||
| @@ -1031,6 +935,35 @@ inline void deleteAndZero (Type& pointer) { delete pointer; pointer = nullp | |||
| template <typename Type> | |||
| inline Type* addBytesToPointer (Type* pointer, int bytes) noexcept { return (Type*) (((char*) pointer) + bytes); } | |||
| /** A handy function which returns the difference between any two pointers, in bytes. | |||
| The address of the second pointer is subtracted from the first, and the difference in bytes is returned. | |||
| */ | |||
| template <typename Type1, typename Type2> | |||
| inline int getAddressDifference (Type1* pointer1, Type2* pointer2) noexcept { return (int) (((const char*) pointer1) - (const char*) pointer2); } | |||
| /* In a win32 DLL build, we'll expose some malloc/free functions that live inside the DLL, and use these for | |||
| allocating all the objects - that way all juce objects in the DLL and in the host will live in the same heap, | |||
| avoiding problems when an object is created in one module and passed across to another where it is deleted. | |||
| By piggy-backing on the JUCE_LEAK_DETECTOR macro, these allocators can be injected into most juce classes. | |||
| */ | |||
| #if JUCE_MSVC && defined (JUCE_DLL) && ! DOXYGEN | |||
| extern JUCE_API void* juceDLL_malloc (size_t); | |||
| extern JUCE_API void juceDLL_free (void*); | |||
| #define JUCE_LEAK_DETECTOR(OwnerClass) public:\ | |||
| static void* operator new (size_t sz) { return JUCE_NAMESPACE::juceDLL_malloc ((int) sz); } \ | |||
| static void* operator new (size_t, void* p) { return p; } \ | |||
| static void operator delete (void* p) { JUCE_NAMESPACE::juceDLL_free (p); } \ | |||
| static void operator delete (void*, void*) {} | |||
| #endif | |||
| /** (Deprecated) This was a win32-specific way of checking for object leaks - now please | |||
| use the JUCE_LEAK_DETECTOR instead. | |||
| */ | |||
| #ifndef juce_UseDebuggingNewOperator | |||
| #define juce_UseDebuggingNewOperator | |||
| #endif | |||
| #endif // __JUCE_MEMORY_JUCEHEADER__ | |||
| /*** End of inlined file: juce_Memory.h ***/ | |||
| @@ -1912,7 +1845,7 @@ public: | |||
| template <typename DestCharPointerType, typename SrcCharPointerType> | |||
| static int copyWithDestByteLimit (DestCharPointerType& dest, SrcCharPointerType src, int maxBytes) noexcept | |||
| { | |||
| int numBytesDone = 0; | |||
| typename DestCharPointerType::CharType const* const startAddress = dest.getAddress(); | |||
| maxBytes -= sizeof (typename DestCharPointerType::CharType); // (allow for a terminating null) | |||
| for (;;) | |||
| @@ -1924,12 +1857,12 @@ public: | |||
| if (c == 0 || maxBytes < 0) | |||
| break; | |||
| numBytesDone += bytesNeeded; | |||
| dest.write (c); | |||
| } | |||
| dest.writeNull(); | |||
| return numBytesDone; | |||
| return getAddressDifference (dest.getAddress(), startAddress); | |||
| } | |||
| template <typename DestCharPointerType, typename SrcCharPointerType> | |||
| @@ -8008,6 +7941,12 @@ public: | |||
| /** Returns this identifier's raw string pointer. */ | |||
| operator const String::CharPointerType() const noexcept { return name; } | |||
| /** Checks a given string for characters that might not be valid in an Identifier. | |||
| Since Identifiers are used as a script variables and XML attributes, they should only contain | |||
| alphanumeric characters and underscores. | |||
| */ | |||
| static bool isValidIdentifier (const String& possibleIdentifier) noexcept; | |||
| private: | |||
| String::CharPointerType name; | |||
| @@ -8053,7 +7992,7 @@ public: | |||
| operator const String() const { return getDefault(); } | |||
| }; | |||
| /** An predefined object representing a new-line, which can be written to a string or stream. | |||
| /** A predefined object representing a new-line, which can be written to a string or stream. | |||
| To write a new-line to a stream, you can use the predefined 'newLine' variable like this: | |||
| @code | |||
| @@ -9317,7 +9256,7 @@ public: | |||
| Do not use this method unless you really need access to the internal var object | |||
| for some reason - for normal reading and writing always prefer operator[]() and set(). | |||
| */ | |||
| var* getVarPointer (const Identifier& name) const; | |||
| var* getVarPointer (const Identifier& name) const noexcept; | |||
| /** Sets properties to the values of all of an XML element's attributes. */ | |||
| void setFromXmlAttributes (const XmlElement& xml); | |||
| @@ -10791,7 +10730,7 @@ public: | |||
| { | |||
| const ScopedLockType sl (getLock()); | |||
| for (const HashEntry* entry = slots [generateHashFor (keyToLookFor)]; entry != nullptr; entry = entry->nextEntry) | |||
| for (const HashEntry* entry = slots.getUnchecked (generateHashFor (keyToLookFor)); entry != nullptr; entry = entry->nextEntry) | |||
| if (entry->key == keyToLookFor) | |||
| return entry->value; | |||
| @@ -10803,7 +10742,7 @@ public: | |||
| { | |||
| const ScopedLockType sl (getLock()); | |||
| for (const HashEntry* entry = slots [generateHashFor (keyToLookFor)]; entry != nullptr; entry = entry->nextEntry) | |||
| for (const HashEntry* entry = slots.getUnchecked (generateHashFor (keyToLookFor)); entry != nullptr; entry = entry->nextEntry) | |||
| if (entry->key == keyToLookFor) | |||
| return true; | |||
| @@ -10832,25 +10771,22 @@ public: | |||
| const ScopedLockType sl (getLock()); | |||
| const int hashIndex = generateHashFor (newKey); | |||
| if (isPositiveAndBelow (hashIndex, getNumSlots())) | |||
| { | |||
| HashEntry* const firstEntry = slots.getUnchecked (hashIndex); | |||
| HashEntry* const firstEntry = slots.getUnchecked (hashIndex); | |||
| for (HashEntry* entry = firstEntry; entry != nullptr; entry = entry->nextEntry) | |||
| for (HashEntry* entry = firstEntry; entry != nullptr; entry = entry->nextEntry) | |||
| { | |||
| if (entry->key == newKey) | |||
| { | |||
| if (entry->key == newKey) | |||
| { | |||
| entry->value = newValue; | |||
| return; | |||
| } | |||
| entry->value = newValue; | |||
| return; | |||
| } | |||
| } | |||
| slots.set (hashIndex, new HashEntry (newKey, newValue, firstEntry)); | |||
| ++totalNumItems; | |||
| slots.set (hashIndex, new HashEntry (newKey, newValue, firstEntry)); | |||
| ++totalNumItems; | |||
| if (totalNumItems > (getNumSlots() * 3) / 2) | |||
| remapTable (getNumSlots() * 2); | |||
| } | |||
| if (totalNumItems > (getNumSlots() * 3) / 2) | |||
| remapTable (getNumSlots() * 2); | |||
| } | |||
| /** Removes an item with the given key. */ | |||
| @@ -10858,7 +10794,7 @@ public: | |||
| { | |||
| const ScopedLockType sl (getLock()); | |||
| const int hashIndex = generateHashFor (keyToRemove); | |||
| HashEntry* entry = slots [hashIndex]; | |||
| HashEntry* entry = slots.getUnchecked (hashIndex); | |||
| HashEntry* previous = nullptr; | |||
| while (entry != nullptr) | |||
| @@ -11953,6 +11889,10 @@ public: | |||
| system clock. It should be accurate to within a few millisecs, depending on platform, | |||
| hardware, etc. | |||
| Being a 32-bit return value, it will of course wrap back to 0 after 2^32 seconds of | |||
| uptime, so be careful to take that into account. If you need a 64-bit time, you can | |||
| use currentTimeMillis() instead. | |||
| @see getApproximateMillisecondCounter | |||
| */ | |||
| static uint32 getMillisecondCounter() noexcept; | |||
| @@ -38449,10 +38389,12 @@ public: | |||
| @param deleteSourceWhenDeleted if true, then the input source object will | |||
| be deleted when this object is deleted | |||
| @param numberOfSamplesToBuffer the size of buffer to use for reading ahead | |||
| @param numberOfChannels the number of channels that will be played | |||
| */ | |||
| BufferingAudioSource (PositionableAudioSource* source, | |||
| bool deleteSourceWhenDeleted, | |||
| int numberOfSamplesToBuffer); | |||
| int numberOfSamplesToBuffer, | |||
| int numberOfChannels = 2); | |||
| /** Destructor. | |||
| @@ -38486,7 +38428,7 @@ private: | |||
| PositionableAudioSource* source; | |||
| bool deleteSourceWhenDeleted; | |||
| int numberOfSamplesToBuffer; | |||
| int numberOfSamplesToBuffer, numberOfChannels; | |||
| AudioSampleBuffer buffer; | |||
| CriticalSection bufferStartPosLock; | |||
| int64 volatile bufferValidStart, bufferValidEnd, nextPlayPos; | |||
| @@ -43908,6 +43850,9 @@ public: | |||
| This stores the current device, its samplerate, block size, etc, and | |||
| can be restored later with initialise(). | |||
| Note that this can return a null pointer if no settings have been explicitly changed | |||
| (i.e. if the device manager has just been left in its default state). | |||
| */ | |||
| XmlElement* createStateXml() const; | |||
| @@ -47730,7 +47675,7 @@ private: | |||
| ReferenceCountedArray <Node> nodes; | |||
| OwnedArray <Connection> connections; | |||
| int lastNodeId; | |||
| uint32 lastNodeId; | |||
| AudioSampleBuffer renderingBuffers; | |||
| OwnedArray <MidiBuffer> midiBuffers; | |||
| @@ -57819,22 +57764,24 @@ private: | |||
| @code | |||
| { | |||
| WildcardFileFilter wildcardFilter ("*.foo", "Foo files"); | |||
| WildcardFileFilter wildcardFilter ("*.foo", String::empty, "Foo files"); | |||
| FileBrowserComponent browser (FileBrowserComponent::loadFileMode, | |||
| FileBrowserComponent browser (FileBrowserComponent::canSelectFiles, | |||
| File::nonexistent, | |||
| &wildcardFilter, | |||
| 0); | |||
| nullptr); | |||
| FileChooserDialogBox dialogBox ("Open some kind of file", | |||
| "Please choose some kind of file that you want to open...", | |||
| browser, | |||
| getLookAndFeel().alertWindowBackground); | |||
| false, | |||
| Colours::lightgrey); | |||
| if (dialogBox.show()) | |||
| { | |||
| File selectedFile = browser.getCurrentFile(); | |||
| ... | |||
| File selectedFile = browser.getSelectedFile (0); | |||
| ...etc.. | |||
| } | |||
| } | |||
| @endcode | |||
| @@ -58447,6 +58394,10 @@ public: | |||
| patterns, e.g. "*.wav;*.aiff" would look for files ending in either .wav | |||
| or .aiff. | |||
| Passing an empty string as a pattern will fail to match anything, so by leaving | |||
| either the file or directory pattern parameter empty means you can control | |||
| whether files or directories are found. | |||
| The description is a name to show the user in a list of possible patterns, so | |||
| for the wav/aiff example, your description might be "audio files". | |||
| */ | |||
| @@ -89,7 +89,7 @@ void AudioTransportSource::setSource (PositionableAudioSource* const newSource, | |||
| if (readAheadBufferSize_ > 0) | |||
| newPositionableSource = newBufferingSource | |||
| = new BufferingAudioSource (newPositionableSource, false, readAheadBufferSize_); | |||
| = new BufferingAudioSource (newPositionableSource, false, readAheadBufferSize_, maxNumChannels); | |||
| newPositionableSource->setNextReadPosition (0); | |||
| @@ -121,11 +121,13 @@ juce_ImplementSingleton (SharedBufferingAudioSourceThread) | |||
| //============================================================================== | |||
| BufferingAudioSource::BufferingAudioSource (PositionableAudioSource* source_, | |||
| const bool deleteSourceWhenDeleted_, | |||
| int numberOfSamplesToBuffer_) | |||
| const int numberOfSamplesToBuffer_, | |||
| const int numberOfChannels_) | |||
| : source (source_), | |||
| deleteSourceWhenDeleted (deleteSourceWhenDeleted_), | |||
| numberOfSamplesToBuffer (jmax (1024, numberOfSamplesToBuffer_)), | |||
| buffer (2, 0), | |||
| numberOfChannels (numberOfChannels_), | |||
| buffer (numberOfChannels_, 0), | |||
| bufferValidStart (0), | |||
| bufferValidEnd (0), | |||
| nextPlayPos (0), | |||
| @@ -155,7 +157,7 @@ void BufferingAudioSource::prepareToPlay (int samplesPerBlockExpected, double sa | |||
| sampleRate = sampleRate_; | |||
| buffer.setSize (2, jmax (samplesPerBlockExpected * 2, numberOfSamplesToBuffer)); | |||
| buffer.setSize (numberOfChannels, jmax (samplesPerBlockExpected * 2, numberOfSamplesToBuffer)); | |||
| buffer.clear(); | |||
| bufferValidStart = 0; | |||
| @@ -178,7 +180,7 @@ void BufferingAudioSource::releaseResources() | |||
| if (thread != nullptr) | |||
| thread->removeSource (this); | |||
| buffer.setSize (2, 0); | |||
| buffer.setSize (numberOfChannels, 0); | |||
| source->releaseResources(); | |||
| } | |||
| @@ -205,7 +207,7 @@ void BufferingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& info | |||
| if (validStart < validEnd) | |||
| { | |||
| for (int chan = jmin (2, info.buffer->getNumChannels()); --chan >= 0;) | |||
| for (int chan = jmin (numberOfChannels, info.buffer->getNumChannels()); --chan >= 0;) | |||
| { | |||
| const int startBufferIndex = (validStart + nextPlayPos) % buffer.getNumSamples(); | |||
| const int endBufferIndex = (validEnd + nextPlayPos) % buffer.getNumSamples(); | |||
| @@ -51,10 +51,12 @@ public: | |||
| @param deleteSourceWhenDeleted if true, then the input source object will | |||
| be deleted when this object is deleted | |||
| @param numberOfSamplesToBuffer the size of buffer to use for reading ahead | |||
| @param numberOfChannels the number of channels that will be played | |||
| */ | |||
| BufferingAudioSource (PositionableAudioSource* source, | |||
| bool deleteSourceWhenDeleted, | |||
| int numberOfSamplesToBuffer); | |||
| int numberOfSamplesToBuffer, | |||
| int numberOfChannels = 2); | |||
| /** Destructor. | |||
| @@ -90,7 +92,7 @@ private: | |||
| //============================================================================== | |||
| PositionableAudioSource* source; | |||
| bool deleteSourceWhenDeleted; | |||
| int numberOfSamplesToBuffer; | |||
| int numberOfSamplesToBuffer, numberOfChannels; | |||
| AudioSampleBuffer buffer; | |||
| CriticalSection bufferStartPosLock; | |||
| int64 volatile bufferValidStart, bufferValidEnd, nextPlayPos; | |||
| @@ -201,6 +201,9 @@ public: | |||
| This stores the current device, its samplerate, block size, etc, and | |||
| can be restored later with initialise(). | |||
| Note that this can return a null pointer if no settings have been explicitly changed | |||
| (i.e. if the device manager has just been left in its default state). | |||
| */ | |||
| XmlElement* createStateXml() const; | |||
| @@ -160,7 +160,7 @@ public: | |||
| { | |||
| const ScopedLockType sl (getLock()); | |||
| for (const HashEntry* entry = slots [generateHashFor (keyToLookFor)]; entry != nullptr; entry = entry->nextEntry) | |||
| for (const HashEntry* entry = slots.getUnchecked (generateHashFor (keyToLookFor)); entry != nullptr; entry = entry->nextEntry) | |||
| if (entry->key == keyToLookFor) | |||
| return entry->value; | |||
| @@ -173,7 +173,7 @@ public: | |||
| { | |||
| const ScopedLockType sl (getLock()); | |||
| for (const HashEntry* entry = slots [generateHashFor (keyToLookFor)]; entry != nullptr; entry = entry->nextEntry) | |||
| for (const HashEntry* entry = slots.getUnchecked (generateHashFor (keyToLookFor)); entry != nullptr; entry = entry->nextEntry) | |||
| if (entry->key == keyToLookFor) | |||
| return true; | |||
| @@ -203,25 +203,22 @@ public: | |||
| const ScopedLockType sl (getLock()); | |||
| const int hashIndex = generateHashFor (newKey); | |||
| if (isPositiveAndBelow (hashIndex, getNumSlots())) | |||
| { | |||
| HashEntry* const firstEntry = slots.getUnchecked (hashIndex); | |||
| HashEntry* const firstEntry = slots.getUnchecked (hashIndex); | |||
| for (HashEntry* entry = firstEntry; entry != nullptr; entry = entry->nextEntry) | |||
| for (HashEntry* entry = firstEntry; entry != nullptr; entry = entry->nextEntry) | |||
| { | |||
| if (entry->key == newKey) | |||
| { | |||
| if (entry->key == newKey) | |||
| { | |||
| entry->value = newValue; | |||
| return; | |||
| } | |||
| entry->value = newValue; | |||
| return; | |||
| } | |||
| } | |||
| slots.set (hashIndex, new HashEntry (newKey, newValue, firstEntry)); | |||
| ++totalNumItems; | |||
| slots.set (hashIndex, new HashEntry (newKey, newValue, firstEntry)); | |||
| ++totalNumItems; | |||
| if (totalNumItems > (getNumSlots() * 3) / 2) | |||
| remapTable (getNumSlots() * 2); | |||
| } | |||
| if (totalNumItems > (getNumSlots() * 3) / 2) | |||
| remapTable (getNumSlots() * 2); | |||
| } | |||
| /** Removes an item with the given key. */ | |||
| @@ -229,7 +226,7 @@ public: | |||
| { | |||
| const ScopedLockType sl (getLock()); | |||
| const int hashIndex = generateHashFor (keyToRemove); | |||
| HashEntry* entry = slots [hashIndex]; | |||
| HashEntry* entry = slots.getUnchecked (hashIndex); | |||
| HashEntry* previous = nullptr; | |||
| while (entry != nullptr) | |||
| @@ -33,7 +33,7 @@ | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 53 | |||
| #define JUCE_BUILDNUMBER 85 | |||
| #define JUCE_BUILDNUMBER 86 | |||
| /** Current Juce version number. | |||
| @@ -276,7 +276,9 @@ uint32 Time::getMillisecondCounter() noexcept | |||
| uint32 Time::getApproximateMillisecondCounter() noexcept | |||
| { | |||
| jassert (TimeHelpers::lastMSCounterValue != 0); | |||
| if (TimeHelpers::lastMSCounterValue == 0) | |||
| getMillisecondCounter(); | |||
| return TimeHelpers::lastMSCounterValue; | |||
| } | |||
| @@ -298,6 +298,10 @@ public: | |||
| system clock. It should be accurate to within a few millisecs, depending on platform, | |||
| hardware, etc. | |||
| Being a 32-bit return value, it will of course wrap back to 0 after 2^32 seconds of | |||
| uptime, so be careful to take that into account. If you need a 64-bit time, you can | |||
| use currentTimeMillis() instead. | |||
| @see getApproximateMillisecondCounter | |||
| */ | |||
| static uint32 getMillisecondCounter() noexcept; | |||
| @@ -72,13 +72,14 @@ public: | |||
| { | |||
| const uint32 now = Time::getMillisecondCounter(); | |||
| if (now <= lastTime) | |||
| if (now == lastTime) | |||
| { | |||
| wait (2); | |||
| wait (1); | |||
| continue; | |||
| } | |||
| const int elapsed = now - lastTime; | |||
| const int elapsed = now >= lastTime ? (now - lastTime) | |||
| : (std::numeric_limits<uint32>::max() - (lastTime - now)); | |||
| lastTime = now; | |||
| const int timeUntilFirstTimer = getTimeUntilFirstTimer (elapsed); | |||
| @@ -373,20 +373,22 @@ public: | |||
| { | |||
| if (isVisible()) | |||
| { | |||
| WeakReference<Component> deletionChecker (this); | |||
| activeSubMenu = nullptr; | |||
| currentChild = nullptr; | |||
| exitModalState (item != nullptr ? item->itemId : 0); | |||
| if (makeInvisible) | |||
| setVisible (false); | |||
| if (item != nullptr | |||
| && item->commandManager != nullptr | |||
| && item->itemId != 0) | |||
| { | |||
| *managerOfChosenCommand = item->commandManager; | |||
| } | |||
| exitModalState (item != nullptr ? item->itemId : 0); | |||
| if (makeInvisible && (deletionChecker != nullptr)) | |||
| setVisible (false); | |||
| } | |||
| } | |||
| @@ -69,6 +69,13 @@ inline void deleteAndZero (Type& pointer) { delete poi | |||
| template <typename Type> | |||
| inline Type* addBytesToPointer (Type* pointer, int bytes) noexcept { return (Type*) (((char*) pointer) + bytes); } | |||
| /** A handy function which returns the difference between any two pointers, in bytes. | |||
| The address of the second pointer is subtracted from the first, and the difference in bytes is returned. | |||
| */ | |||
| template <typename Type1, typename Type2> | |||
| inline int getAddressDifference (Type1* pointer1, Type2* pointer2) noexcept { return (int) (((const char*) pointer1) - (const char*) pointer2); } | |||
| //============================================================================== | |||
| /* In a win32 DLL build, we'll expose some malloc/free functions that live inside the DLL, and use these for | |||
| allocating all the objects - that way all juce objects in the DLL and in the host will live in the same heap, | |||
| @@ -142,7 +142,7 @@ int64 Time::getHighResolutionTicks() noexcept | |||
| timespec t; | |||
| clock_gettime (CLOCK_MONOTONIC, &t); | |||
| return (t.tv_sec * (int64) 1000000) + (t.tv_nsec / (int64) 1000); | |||
| return (t.tv_sec * (int64) 1000000) + (t.tv_nsec / 1000); | |||
| } | |||
| int64 Time::getHighResolutionTicksPerSecond() noexcept | |||
| @@ -155,7 +155,7 @@ int64 Time::getHighResolutionTicks() noexcept | |||
| timespec t; | |||
| clock_gettime (CLOCK_MONOTONIC, &t); | |||
| return (t.tv_sec * (int64) 1000000) + (t.tv_nsec / (int64) 1000); | |||
| return (t.tv_sec * (int64) 1000000) + (t.tv_nsec / 1000); | |||
| } | |||
| int64 Time::getHighResolutionTicksPerSecond() noexcept | |||
| @@ -274,8 +274,6 @@ public: | |||
| timerCallback(); | |||
| } | |||
| ~ScreenSaverDefeater() {} | |||
| void timerCallback() | |||
| { | |||
| if (Process::isForegroundProcess()) | |||
| @@ -190,13 +190,15 @@ public: | |||
| { | |||
| mach_timebase_info_data_t timebase; | |||
| (void) mach_timebase_info (&timebase); | |||
| highResTimerFrequency = (int64) (1.0e9 * timebase.denom / timebase.numer); | |||
| highResTimerToMillisecRatio = timebase.numer / (1.0e6 * timebase.denom); | |||
| highResTimerFrequency = (timebase.denom * (int64) 1000000000) / timebase.numer; | |||
| numerator = timebase.numer; | |||
| denominator = timebase.denom * (int64) 1000000; | |||
| highResTimerToMillisecRatio = numerator / (double) denominator; | |||
| } | |||
| inline uint32 millisecondsSinceStartup() const noexcept | |||
| { | |||
| return (uint32) (mach_absolute_time() * highResTimerToMillisecRatio); | |||
| return (uint32) ((mach_absolute_time() * numerator) / denominator); | |||
| } | |||
| inline double getMillisecondCounterHiRes() const noexcept | |||
| @@ -205,6 +207,9 @@ public: | |||
| } | |||
| int64 highResTimerFrequency; | |||
| private: | |||
| int64 numerator, denominator; | |||
| double highResTimerToMillisecRatio; | |||
| }; | |||
| @@ -308,7 +308,7 @@ public: | |||
| template <typename DestCharPointerType, typename SrcCharPointerType> | |||
| static int copyWithDestByteLimit (DestCharPointerType& dest, SrcCharPointerType src, int maxBytes) noexcept | |||
| { | |||
| int numBytesDone = 0; | |||
| typename DestCharPointerType::CharType const* const startAddress = dest.getAddress(); | |||
| maxBytes -= sizeof (typename DestCharPointerType::CharType); // (allow for a terminating null) | |||
| for (;;) | |||
| @@ -320,12 +320,12 @@ public: | |||
| if (c == 0 || maxBytes < 0) | |||
| break; | |||
| numBytesDone += bytesNeeded; | |||
| dest.write (c); | |||
| } | |||
| dest.writeNull(); | |||
| return numBytesDone; | |||
| return getAddressDifference (dest.getAddress(), startAddress); | |||
| } | |||
| template <typename DestCharPointerType, typename SrcCharPointerType> | |||
| @@ -58,7 +58,7 @@ Identifier::Identifier (const String& name_) | |||
| { | |||
| /* An Identifier string must be suitable for use as a script variable or XML | |||
| attribute, so it can only contain this limited set of characters.. */ | |||
| jassert (name_.containsOnly ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_") && name_.isNotEmpty()); | |||
| jassert (isValidIdentifier (name_)); | |||
| } | |||
| Identifier::Identifier (const char* const name_) | |||
| @@ -66,11 +66,17 @@ Identifier::Identifier (const char* const name_) | |||
| { | |||
| /* An Identifier string must be suitable for use as a script variable or XML | |||
| attribute, so it can only contain this limited set of characters.. */ | |||
| jassert (toString().containsOnly ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_") && toString().isNotEmpty()); | |||
| jassert (isValidIdentifier (toString())); | |||
| } | |||
| Identifier::~Identifier() | |||
| { | |||
| } | |||
| bool Identifier::isValidIdentifier (const String& possibleIdentifier) noexcept | |||
| { | |||
| return possibleIdentifier.isNotEmpty() | |||
| && possibleIdentifier.containsOnly ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"); | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| @@ -78,6 +78,13 @@ public: | |||
| /** Returns this identifier's raw string pointer. */ | |||
| operator const String::CharPointerType() const noexcept { return name; } | |||
| /** Checks a given string for characters that might not be valid in an Identifier. | |||
| Since Identifiers are used as a script variables and XML attributes, they should only contain | |||
| alphanumeric characters and underscores. | |||
| */ | |||
| static bool isValidIdentifier (const String& possibleIdentifier) noexcept; | |||
| private: | |||
| //============================================================================== | |||
| String::CharPointerType name; | |||
| @@ -2052,7 +2052,7 @@ struct StringCopier | |||
| jassert (maxBufferSizeBytes >= 0); // keep this value positive, or no characters will be copied! | |||
| if (buffer == nullptr) | |||
| return (int) CharPointerType_Dest::getBytesRequiredFor (source); | |||
| return (int) (CharPointerType_Dest::getBytesRequiredFor (source) + sizeof (typename CharPointerType_Dest::CharType)); | |||
| return CharPointerType_Dest (buffer).writeWithDestByteLimit (source, maxBufferSizeBytes); | |||
| } | |||