From 04f0303b84111a82ed8e21243e904c51a36e946e Mon Sep 17 00:00:00 2001 From: jules Date: Fri, 10 Jul 2009 16:26:27 +0000 Subject: [PATCH] small fixes for fonts on mac and win32; changed Thread::setPriority to return a bool; added a File::getVolumeTotalSize() method; added a freetype path to the linux makefile; tweaked the jucer to make cached image variable names more readable; tweaked the hit-spots in the resizable borders of very small windows; moved ResizableWindow background painting into the LookAndFeel; made the broadcast flag of a DatagramSocket an optional constructor parameter; --- .../juce_linux_Threads.cpp | 6 +- .../platform_specific_code/juce_mac_Fonts.mm | 3 + .../juce_mac_Network.mm | 929 +++++++------- .../juce_mac_Threads.mm | 4 +- .../juce_posix_SharedCode.h | 14 +- .../juce_win32_Files.cpp | 20 +- .../juce_win32_Fonts.cpp | 4 +- .../juce_win32_NativeIncludes.h | 4 + .../juce_win32_Network.cpp | 17 +- .../demo/build/linux/premake.lua | 1 + .../src/model/jucer_GeneratedCode.cpp | 771 ++++++------ .../model/paintelements/jucer_FillType.cpp | 2 +- .../paintelements/jucer_PaintElementImage.h | 1072 ++++++++--------- juce_amalgamated.cpp | 170 ++- juce_amalgamated.h | 29 +- .../audio_file_formats/juce_AudioFormat.cpp | 2 +- .../layout/juce_ResizableBorderComponent.cpp | 16 +- .../lookandfeel/juce_LookAndFeel.cpp | 6 + .../components/lookandfeel/juce_LookAndFeel.h | 4 + .../windows/juce_ResizableWindow.cpp | 12 +- .../image_file_formats/juce_JPEGLoader.cpp | 4 + src/juce_core/io/files/juce_File.h | 8 + src/juce_core/io/network/juce_Socket.cpp | 18 +- src/juce_core/io/network/juce_Socket.h | 8 +- src/juce_core/threads/juce_Thread.cpp | 16 +- src/juce_core/threads/juce_Thread.h | 6 +- src/juce_core/threads/juce_ThreadPool.cpp | 9 +- src/juce_core/threads/juce_ThreadPool.h | 3 +- 28 files changed, 1668 insertions(+), 1490 deletions(-) diff --git a/build/linux/platform_specific_code/juce_linux_Threads.cpp b/build/linux/platform_specific_code/juce_linux_Threads.cpp index afa2c59839..e841201c1d 100644 --- a/build/linux/platform_specific_code/juce_linux_Threads.cpp +++ b/build/linux/platform_specific_code/juce_linux_Threads.cpp @@ -112,7 +112,7 @@ Thread::ThreadID Thread::getCurrentThreadId() throw() // priority 1 to 10 where 5=normal, 1=low. If the handle is 0, sets the // priority of the current thread -void juce_setThreadPriority (void* handle, int priority) throw() +bool juce_setThreadPriority (void* handle, int priority) throw() { struct sched_param param; int policy, maxp, minp, pri; @@ -137,8 +137,10 @@ void juce_setThreadPriority (void* handle, int priority) throw() param.sched_priority = jlimit (1, 127, 1 + (priority * 126) / 11); - pthread_setschedparam ((pthread_t) handle, policy, ¶m); + return pthread_setschedparam ((pthread_t) handle, policy, ¶m) == 0; } + + return false; } void Thread::setCurrentThreadAffinityMask (const uint32 affinityMask) throw() diff --git a/build/macosx/platform_specific_code/juce_mac_Fonts.mm b/build/macosx/platform_specific_code/juce_mac_Fonts.mm index aac5b68b57..020b6d0c12 100644 --- a/build/macosx/platform_specific_code/juce_mac_Fonts.mm +++ b/build/macosx/platform_specific_code/juce_mac_Fonts.mm @@ -288,6 +288,9 @@ bool Typeface::findAndAddSystemGlyph (juce_wchar character) throw() // This method is only safe to be called from the normal UI thread.. jassert (MessageManager::getInstance()->isThisTheMessageThread()); + if (character == 0) + return false; + FontHelper* const helper = FontHelperCache::getInstance() ->getFont (getName(), isBold(), isItalic()); diff --git a/build/macosx/platform_specific_code/juce_mac_Network.mm b/build/macosx/platform_specific_code/juce_mac_Network.mm index ae8c849a4d..63e35aa9b7 100644 --- a/build/macosx/platform_specific_code/juce_mac_Network.mm +++ b/build/macosx/platform_specific_code/juce_mac_Network.mm @@ -1,464 +1,465 @@ -/* - ============================================================================== - - This file is part of the JUCE library - "Jules' Utility Class Extensions" - Copyright 2004-7 by Raw Material Software ltd. - - ------------------------------------------------------------------------------ - - JUCE can be redistributed and/or modified under the terms of the - GNU General Public License, as published by the Free Software Foundation; - either version 2 of the License, or (at your option) any later version. - - JUCE is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with JUCE; if not, visit www.gnu.org/licenses or write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - ------------------------------------------------------------------------------ - - If you'd like to release a closed-source product which uses JUCE, commercial - licenses are also available: visit www.rawmaterialsoftware.com/juce for - more information. - - ============================================================================== -*/ - -// (This file gets included by juce_mac_NativeCode.mm, rather than being -// compiled on its own). -#if JUCE_INCLUDED_FILE - -//============================================================================== -static bool getEthernetIterator (io_iterator_t* matchingServices) throw() -{ - mach_port_t masterPort; - - if (IOMasterPort (MACH_PORT_NULL, &masterPort) == KERN_SUCCESS) - { - CFMutableDictionaryRef dict = IOServiceMatching (kIOEthernetInterfaceClass); - - if (dict != 0) - { - CFMutableDictionaryRef propDict = CFDictionaryCreateMutable (kCFAllocatorDefault, - 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - - if (propDict != 0) - { - CFDictionarySetValue (propDict, CFSTR (kIOPrimaryInterface), kCFBooleanTrue); - - CFDictionarySetValue (dict, CFSTR (kIOPropertyMatchKey), propDict); - CFRelease (propDict); - } - } - - return IOServiceGetMatchingServices (masterPort, dict, matchingServices) == KERN_SUCCESS; - } - - return false; -} - -int SystemStats::getMACAddresses (int64* addresses, int maxNum, const bool littleEndian) throw() -{ - int numResults = 0; - io_iterator_t it; - - if (getEthernetIterator (&it)) - { - io_object_t i; - - while ((i = IOIteratorNext (it)) != 0) - { - io_object_t controller; - - if (IORegistryEntryGetParentEntry (i, kIOServicePlane, &controller) == KERN_SUCCESS) - { - CFTypeRef data = IORegistryEntryCreateCFProperty (controller, - CFSTR (kIOMACAddress), - kCFAllocatorDefault, - 0); - if (data != 0) - { - UInt8 addr [kIOEthernetAddressSize]; - zeromem (addr, sizeof (addr)); - - CFDataGetBytes ((CFDataRef) data, CFRangeMake (0, sizeof (addr)), addr); - CFRelease (data); - - int64 a = 0; - for (int i = 6; --i >= 0;) - a = (a << 8) | addr[i]; - - if (! littleEndian) - a = (int64) swapByteOrder ((uint64) a); - - if (numResults < maxNum) - { - *addresses++ = a; - ++numResults; - } - } - - IOObjectRelease (controller); - } - - IOObjectRelease (i); - } - - IOObjectRelease (it); - } - - return numResults; -} - -//============================================================================== -bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAddress, - const String& emailSubject, - const String& bodyText, - const StringArray& filesToAttach) -{ - const ScopedAutoReleasePool pool; - - String script; - script << "tell application \"Mail\"\r\n" - "set newMessage to make new outgoing message with properties {subject:\"" - << emailSubject.replace (T("\""), T("\\\"")) - << "\", content:\"" - << bodyText.replace (T("\""), T("\\\"")) - << "\" & return & return}\r\n" - "tell newMessage\r\n" - "set visible to true\r\n" - "set sender to \"sdfsdfsdfewf\"\r\n" - "make new to recipient at end of to recipients with properties {address:\"" - << targetEmailAddress - << "\"}\r\n"; - - for (int i = 0; i < filesToAttach.size(); ++i) - { - script << "tell content\r\n" - "make new attachment with properties {file name:\"" - << filesToAttach[i].replace (T("\""), T("\\\"")) - << "\"} at after the last paragraph\r\n" - "end tell\r\n"; - } - - script << "end tell\r\n" - "end tell\r\n"; - - NSAppleScript* s = [[NSAppleScript alloc] - initWithSource: juceStringToNS (script)]; - NSDictionary* error = 0; - const bool ok = [s executeAndReturnError: &error] != nil; - [s release]; - - return ok; -} - -//============================================================================== -END_JUCE_NAMESPACE - -using namespace JUCE_NAMESPACE; - -//============================================================================== -#define JuceURLConnection MakeObjCClassName(JuceURLConnection) - -@interface JuceURLConnection : NSObject -{ - NSURLRequest* request; - NSURLConnection* connection; - NSMutableData* data; - Thread* runLoopThread; - bool initialised, hasFailed, hasFinished; - int position; - int64 contentLength; - NSLock* dataLock; -} - -- (JuceURLConnection*) initWithRequest: (NSURLRequest*) req withCallback: (URL::OpenStreamProgressCallback*) callback withContext: (void*) context; -- (void) dealloc; -- (void) connection: (NSURLConnection*) connection didReceiveResponse: (NSURLResponse*) response; -- (void) connection: (NSURLConnection*) connection didFailWithError: (NSError*) error; -- (void) connection: (NSURLConnection*) connection didReceiveData: (NSData*) data; -- (void) connectionDidFinishLoading: (NSURLConnection*) connection; - -- (BOOL) isOpen; -- (int) read: (char*) dest numBytes: (int) num; -- (int) readPosition; -- (void) stop; -- (void) createConnection; - -@end - -class JuceURLConnectionMessageThread : public Thread -{ - JuceURLConnection* owner; - -public: - JuceURLConnectionMessageThread (JuceURLConnection* owner_) - : Thread (T("http connection")), - owner (owner_) - { - } - - ~JuceURLConnectionMessageThread() - { - stopThread (10000); - } - - void run() - { - [owner createConnection]; - - while (! threadShouldExit()) - { - const ScopedAutoReleasePool pool; - [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]]; - } - } -}; - - -@implementation JuceURLConnection - -- (JuceURLConnection*) initWithRequest: (NSURLRequest*) req - withCallback: (URL::OpenStreamProgressCallback*) callback - withContext: (void*) context; -{ - [super init]; - request = req; - [request retain]; - data = [[NSMutableData data] retain]; - dataLock = [[NSLock alloc] init]; - connection = 0; - initialised = false; - hasFailed = false; - hasFinished = false; - contentLength = -1; - - runLoopThread = new JuceURLConnectionMessageThread (self); - runLoopThread->startThread(); - - while (runLoopThread->isThreadRunning() && ! initialised) - { - if (callback != 0) - callback (context, -1, [[request HTTPBody] length]); - - Thread::sleep (1); - } - - return self; -} - -- (void) dealloc -{ - [self stop]; - - delete runLoopThread; - [connection release]; - [data release]; - [dataLock release]; - [request release]; - [super dealloc]; -} - -- (void) createConnection -{ - connection = [[NSURLConnection alloc] initWithRequest: request - delegate: [self retain]]; - - if (connection == nil) - runLoopThread->signalThreadShouldExit(); -} - -- (void) connection: (NSURLConnection*) connection didReceiveResponse: (NSURLResponse*) response -{ - [dataLock lock]; - [data setLength: 0]; - [dataLock unlock]; - initialised = true; - contentLength = [response expectedContentLength]; -} - -- (void) connection: (NSURLConnection*) connection didFailWithError: (NSError*) error -{ - DBG (nsStringToJuce ([error description])); - hasFailed = true; - initialised = true; - runLoopThread->signalThreadShouldExit(); -} - -- (void) connection: (NSURLConnection*) connection didReceiveData: (NSData*) newData -{ - [dataLock lock]; - [data appendData: newData]; - [dataLock unlock]; - initialised = true; -} - -- (void) connectionDidFinishLoading: (NSURLConnection*) connection -{ - hasFinished = true; - initialised = true; - runLoopThread->signalThreadShouldExit(); -} - -- (BOOL) isOpen -{ - return connection != 0 && ! hasFailed; -} - -- (int) readPosition -{ - return position; -} - -- (int) read: (char*) dest numBytes: (int) numNeeded -{ - int numDone = 0; - - while (numNeeded > 0) - { - int available = jmin (numNeeded, [data length]); - - if (available > 0) - { - [dataLock lock]; - [data getBytes: dest length: available]; - [data replaceBytesInRange: NSMakeRange (0, available) withBytes: nil length: 0]; - [dataLock unlock]; - - numDone += available; - numNeeded -= available; - dest += available; - } - else - { - if (hasFailed || hasFinished) - break; - - Thread::sleep (1); - } - } - - position += numDone; - return numDone; -} - -- (void) stop -{ - [connection cancel]; - runLoopThread->stopThread (10000); -} - -@end -BEGIN_JUCE_NAMESPACE - - -bool juce_isOnLine() -{ - return true; -} - -void* juce_openInternetFile (const String& url, - const String& headers, - const MemoryBlock& postData, - const bool isPost, - URL::OpenStreamProgressCallback* callback, - void* callbackContext, - int timeOutMs) -{ - const ScopedAutoReleasePool pool; - - NSMutableURLRequest* req = [NSMutableURLRequest - requestWithURL: [NSURL URLWithString: juceStringToNS (url)] - cachePolicy: NSURLRequestUseProtocolCachePolicy - timeoutInterval: timeOutMs <= 0 ? 60.0 : (timeOutMs / 1000.0)]; - - if (req == nil) - return 0; - - [req setHTTPMethod: isPost ? @"POST" : @"GET"]; - //[req setCachePolicy: NSURLRequestReloadIgnoringLocalAndRemoteCacheData]; - - StringArray headerLines; - headerLines.addLines (headers); - headerLines.removeEmptyStrings (true); - - for (int i = 0; i < headerLines.size(); ++i) - { - const String key (headerLines[i].upToFirstOccurrenceOf (T(":"), false, false).trim()); - const String value (headerLines[i].fromFirstOccurrenceOf (T(":"), false, false).trim()); - - if (key.isNotEmpty() && value.isNotEmpty()) - [req addValue: juceStringToNS (value) forHTTPHeaderField: juceStringToNS (key)]; - } - - if (isPost && postData.getSize() > 0) - { - [req setHTTPBody: [NSData dataWithBytes: postData.getData() - length: postData.getSize()]]; - } - - JuceURLConnection* const s = [[JuceURLConnection alloc] initWithRequest: req - withCallback: callback - withContext: callbackContext]; - - if ([s isOpen]) - return s; - - [s release]; - return 0; -} - -void juce_closeInternetFile (void* handle) -{ - JuceURLConnection* const s = (JuceURLConnection*) handle; - - if (s != 0) - { - const ScopedAutoReleasePool pool; - [s stop]; - [s release]; - } -} - -int juce_readFromInternetFile (void* handle, void* buffer, int bytesToRead) -{ - JuceURLConnection* const s = (JuceURLConnection*) handle; - - if (s != 0) - { - const ScopedAutoReleasePool pool; - return [s read: (char*) buffer numBytes: bytesToRead]; - } - - return 0; -} - -int64 juce_getInternetFileContentLength (void* handle) -{ - JuceURLConnection* const s = (JuceURLConnection*) handle; - - if (s != 0) - return s->contentLength; - - return -1; -} - -int juce_seekInInternetFile (void* handle, int newPosition) -{ - JuceURLConnection* const s = (JuceURLConnection*) handle; - - if (s != 0) - return [s readPosition]; - - return 0; -} - -#endif +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +// (This file gets included by juce_mac_NativeCode.mm, rather than being +// compiled on its own). +#if JUCE_INCLUDED_FILE + +//============================================================================== +static bool getEthernetIterator (io_iterator_t* matchingServices) throw() +{ + mach_port_t masterPort; + + if (IOMasterPort (MACH_PORT_NULL, &masterPort) == KERN_SUCCESS) + { + CFMutableDictionaryRef dict = IOServiceMatching (kIOEthernetInterfaceClass); + + if (dict != 0) + { + CFMutableDictionaryRef propDict = CFDictionaryCreateMutable (kCFAllocatorDefault, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + if (propDict != 0) + { + CFDictionarySetValue (propDict, CFSTR (kIOPrimaryInterface), kCFBooleanTrue); + + CFDictionarySetValue (dict, CFSTR (kIOPropertyMatchKey), propDict); + CFRelease (propDict); + } + } + + return IOServiceGetMatchingServices (masterPort, dict, matchingServices) == KERN_SUCCESS; + } + + return false; +} + +int SystemStats::getMACAddresses (int64* addresses, int maxNum, const bool littleEndian) throw() +{ + int numResults = 0; + io_iterator_t it; + + if (getEthernetIterator (&it)) + { + io_object_t i; + + while ((i = IOIteratorNext (it)) != 0) + { + io_object_t controller; + + if (IORegistryEntryGetParentEntry (i, kIOServicePlane, &controller) == KERN_SUCCESS) + { + CFTypeRef data = IORegistryEntryCreateCFProperty (controller, + CFSTR (kIOMACAddress), + kCFAllocatorDefault, + 0); + if (data != 0) + { + UInt8 addr [kIOEthernetAddressSize]; + zeromem (addr, sizeof (addr)); + + CFDataGetBytes ((CFDataRef) data, CFRangeMake (0, sizeof (addr)), addr); + CFRelease (data); + + int64 a = 0; + for (int i = 6; --i >= 0;) + a = (a << 8) | addr[i]; + + if (! littleEndian) + a = (int64) swapByteOrder ((uint64) a); + + if (numResults < maxNum) + { + *addresses++ = a; + ++numResults; + } + } + + IOObjectRelease (controller); + } + + IOObjectRelease (i); + } + + IOObjectRelease (it); + } + + return numResults; +} + +//============================================================================== +bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAddress, + const String& emailSubject, + const String& bodyText, + const StringArray& filesToAttach) +{ + const ScopedAutoReleasePool pool; + + String script; + script << "tell application \"Mail\"\r\n" + "set newMessage to make new outgoing message with properties {subject:\"" + << emailSubject.replace (T("\""), T("\\\"")) + << "\", content:\"" + << bodyText.replace (T("\""), T("\\\"")) + << "\" & return & return}\r\n" + "tell newMessage\r\n" + "set visible to true\r\n" + "set sender to \"sdfsdfsdfewf\"\r\n" + "make new to recipient at end of to recipients with properties {address:\"" + << targetEmailAddress + << "\"}\r\n"; + + for (int i = 0; i < filesToAttach.size(); ++i) + { + script << "tell content\r\n" + "make new attachment with properties {file name:\"" + << filesToAttach[i].replace (T("\""), T("\\\"")) + << "\"} at after the last paragraph\r\n" + "end tell\r\n"; + } + + script << "end tell\r\n" + "end tell\r\n"; + + NSAppleScript* s = [[NSAppleScript alloc] + initWithSource: juceStringToNS (script)]; + NSDictionary* error = 0; + const bool ok = [s executeAndReturnError: &error] != nil; + [s release]; + + return ok; +} + +//============================================================================== +END_JUCE_NAMESPACE + +using namespace JUCE_NAMESPACE; + +//============================================================================== +#define JuceURLConnection MakeObjCClassName(JuceURLConnection) + +@interface JuceURLConnection : NSObject +{ +@public + NSURLRequest* request; + NSURLConnection* connection; + NSMutableData* data; + Thread* runLoopThread; + bool initialised, hasFailed, hasFinished; + int position; + int64 contentLength; + NSLock* dataLock; +} + +- (JuceURLConnection*) initWithRequest: (NSURLRequest*) req withCallback: (URL::OpenStreamProgressCallback*) callback withContext: (void*) context; +- (void) dealloc; +- (void) connection: (NSURLConnection*) connection didReceiveResponse: (NSURLResponse*) response; +- (void) connection: (NSURLConnection*) connection didFailWithError: (NSError*) error; +- (void) connection: (NSURLConnection*) connection didReceiveData: (NSData*) data; +- (void) connectionDidFinishLoading: (NSURLConnection*) connection; + +- (BOOL) isOpen; +- (int) read: (char*) dest numBytes: (int) num; +- (int) readPosition; +- (void) stop; +- (void) createConnection; + +@end + +class JuceURLConnectionMessageThread : public Thread +{ + JuceURLConnection* owner; + +public: + JuceURLConnectionMessageThread (JuceURLConnection* owner_) + : Thread (T("http connection")), + owner (owner_) + { + } + + ~JuceURLConnectionMessageThread() + { + stopThread (10000); + } + + void run() + { + [owner createConnection]; + + while (! threadShouldExit()) + { + const ScopedAutoReleasePool pool; + [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]]; + } + } +}; + + +@implementation JuceURLConnection + +- (JuceURLConnection*) initWithRequest: (NSURLRequest*) req + withCallback: (URL::OpenStreamProgressCallback*) callback + withContext: (void*) context; +{ + [super init]; + request = req; + [request retain]; + data = [[NSMutableData data] retain]; + dataLock = [[NSLock alloc] init]; + connection = 0; + initialised = false; + hasFailed = false; + hasFinished = false; + contentLength = -1; + + runLoopThread = new JuceURLConnectionMessageThread (self); + runLoopThread->startThread(); + + while (runLoopThread->isThreadRunning() && ! initialised) + { + if (callback != 0) + callback (context, -1, [[request HTTPBody] length]); + + Thread::sleep (1); + } + + return self; +} + +- (void) dealloc +{ + [self stop]; + + delete runLoopThread; + [connection release]; + [data release]; + [dataLock release]; + [request release]; + [super dealloc]; +} + +- (void) createConnection +{ + connection = [[NSURLConnection alloc] initWithRequest: request + delegate: [self retain]]; + + if (connection == nil) + runLoopThread->signalThreadShouldExit(); +} + +- (void) connection: (NSURLConnection*) connection didReceiveResponse: (NSURLResponse*) response +{ + [dataLock lock]; + [data setLength: 0]; + [dataLock unlock]; + initialised = true; + contentLength = [response expectedContentLength]; +} + +- (void) connection: (NSURLConnection*) connection didFailWithError: (NSError*) error +{ + DBG (nsStringToJuce ([error description])); + hasFailed = true; + initialised = true; + runLoopThread->signalThreadShouldExit(); +} + +- (void) connection: (NSURLConnection*) connection didReceiveData: (NSData*) newData +{ + [dataLock lock]; + [data appendData: newData]; + [dataLock unlock]; + initialised = true; +} + +- (void) connectionDidFinishLoading: (NSURLConnection*) connection +{ + hasFinished = true; + initialised = true; + runLoopThread->signalThreadShouldExit(); +} + +- (BOOL) isOpen +{ + return connection != 0 && ! hasFailed; +} + +- (int) readPosition +{ + return position; +} + +- (int) read: (char*) dest numBytes: (int) numNeeded +{ + int numDone = 0; + + while (numNeeded > 0) + { + int available = jmin (numNeeded, [data length]); + + if (available > 0) + { + [dataLock lock]; + [data getBytes: dest length: available]; + [data replaceBytesInRange: NSMakeRange (0, available) withBytes: nil length: 0]; + [dataLock unlock]; + + numDone += available; + numNeeded -= available; + dest += available; + } + else + { + if (hasFailed || hasFinished) + break; + + Thread::sleep (1); + } + } + + position += numDone; + return numDone; +} + +- (void) stop +{ + [connection cancel]; + runLoopThread->stopThread (10000); +} + +@end +BEGIN_JUCE_NAMESPACE + + +bool juce_isOnLine() +{ + return true; +} + +void* juce_openInternetFile (const String& url, + const String& headers, + const MemoryBlock& postData, + const bool isPost, + URL::OpenStreamProgressCallback* callback, + void* callbackContext, + int timeOutMs) +{ + const ScopedAutoReleasePool pool; + + NSMutableURLRequest* req = [NSMutableURLRequest + requestWithURL: [NSURL URLWithString: juceStringToNS (url)] + cachePolicy: NSURLRequestUseProtocolCachePolicy + timeoutInterval: timeOutMs <= 0 ? 60.0 : (timeOutMs / 1000.0)]; + + if (req == nil) + return 0; + + [req setHTTPMethod: isPost ? @"POST" : @"GET"]; + //[req setCachePolicy: NSURLRequestReloadIgnoringLocalAndRemoteCacheData]; + + StringArray headerLines; + headerLines.addLines (headers); + headerLines.removeEmptyStrings (true); + + for (int i = 0; i < headerLines.size(); ++i) + { + const String key (headerLines[i].upToFirstOccurrenceOf (T(":"), false, false).trim()); + const String value (headerLines[i].fromFirstOccurrenceOf (T(":"), false, false).trim()); + + if (key.isNotEmpty() && value.isNotEmpty()) + [req addValue: juceStringToNS (value) forHTTPHeaderField: juceStringToNS (key)]; + } + + if (isPost && postData.getSize() > 0) + { + [req setHTTPBody: [NSData dataWithBytes: postData.getData() + length: postData.getSize()]]; + } + + JuceURLConnection* const s = [[JuceURLConnection alloc] initWithRequest: req + withCallback: callback + withContext: callbackContext]; + + if ([s isOpen]) + return s; + + [s release]; + return 0; +} + +void juce_closeInternetFile (void* handle) +{ + JuceURLConnection* const s = (JuceURLConnection*) handle; + + if (s != 0) + { + const ScopedAutoReleasePool pool; + [s stop]; + [s release]; + } +} + +int juce_readFromInternetFile (void* handle, void* buffer, int bytesToRead) +{ + JuceURLConnection* const s = (JuceURLConnection*) handle; + + if (s != 0) + { + const ScopedAutoReleasePool pool; + return [s read: (char*) buffer numBytes: bytesToRead]; + } + + return 0; +} + +int64 juce_getInternetFileContentLength (void* handle) +{ + JuceURLConnection* const s = (JuceURLConnection*) handle; + + if (s != 0) + return s->contentLength; + + return -1; +} + +int juce_seekInInternetFile (void* handle, int newPosition) +{ + JuceURLConnection* const s = (JuceURLConnection*) handle; + + if (s != 0) + return [s readPosition]; + + return 0; +} + +#endif diff --git a/build/macosx/platform_specific_code/juce_mac_Threads.mm b/build/macosx/platform_specific_code/juce_mac_Threads.mm index 43f9c03e81..d2c722ecd5 100644 --- a/build/macosx/platform_specific_code/juce_mac_Threads.mm +++ b/build/macosx/platform_specific_code/juce_mac_Threads.mm @@ -77,7 +77,7 @@ Thread::ThreadID Thread::getCurrentThreadId() throw() return (ThreadID) pthread_self(); } -void juce_setThreadPriority (void* handle, int priority) throw() +bool juce_setThreadPriority (void* handle, int priority) throw() { if (handle == 0) handle = (void*) pthread_self(); @@ -86,7 +86,7 @@ void juce_setThreadPriority (void* handle, int priority) throw() int policy; pthread_getschedparam ((pthread_t) handle, &policy, ¶m); param.sched_priority = jlimit (1, 127, 1 + (priority * 126) / 11); - pthread_setschedparam ((pthread_t) handle, policy, ¶m); + return pthread_setschedparam ((pthread_t) handle, policy, ¶m) == 0; } void Thread::yield() throw() diff --git a/build/macosx/platform_specific_code/juce_posix_SharedCode.h b/build/macosx/platform_specific_code/juce_posix_SharedCode.h index 441e84674a..e879f8ce44 100644 --- a/build/macosx/platform_specific_code/juce_posix_SharedCode.h +++ b/build/macosx/platform_specific_code/juce_posix_SharedCode.h @@ -339,14 +339,20 @@ static bool doStatFS (const File* file, struct statfs& result) throw() int64 File::getBytesFreeOnVolume() const throw() { - int64 free_space = 0; + struct statfs buf; + if (doStatFS (this, buf)) + return (int64) buf.f_bsize * (int64) buf.f_bavail; // Note: this returns space available to non-super user + return 0; +} + +int64 File::getVolumeTotalSize() const throw() +{ struct statfs buf; if (doStatFS (this, buf)) - // Note: this returns space available to non-super user - free_space = (int64) buf.f_bsize * (int64) buf.f_bavail; + return (int64) buf.f_bsize * (int64) buf.f_blocks; - return free_space; + return 0; } const String juce_getVolumeLabel (const String& filenameOnVolume, diff --git a/build/win32/platform_specific_code/juce_win32_Files.cpp b/build/win32/platform_specific_code/juce_win32_Files.cpp index c406b09d5d..65886419e1 100644 --- a/build/win32/platform_specific_code/juce_win32_Files.cpp +++ b/build/win32/platform_specific_code/juce_win32_Files.cpp @@ -364,22 +364,30 @@ const String juce_getVolumeLabel (const String& filenameOnVolume, return String (dest); } -int64 File::getBytesFreeOnVolume() const throw() +static int64 getDiskSpaceInfo (String fn, const bool total) throw() { - String fn (getFullPathName()); if (fn[1] == T(':')) fn = fn.substring (0, 2) + T("\\"); - ULARGE_INTEGER spc; - ULARGE_INTEGER tot; - ULARGE_INTEGER totFree; + ULARGE_INTEGER spc, tot, totFree; if (GetDiskFreeSpaceEx (fn, &spc, &tot, &totFree)) - return (int64)(spc.QuadPart); + return (int64) (total ? tot.QuadPart + : spc.QuadPart); return 0; } +int64 File::getBytesFreeOnVolume() const throw() +{ + return getDiskSpaceInfo (getFullPathName(), false); +} + +int64 File::getVolumeTotalSize() const throw() +{ + return getDiskSpaceInfo (getFullPathName(), true); +} + //============================================================================== static unsigned int getWindowsDriveType (const String& fileName) throw() { diff --git a/build/win32/platform_specific_code/juce_win32_Fonts.cpp b/build/win32/platform_specific_code/juce_win32_Fonts.cpp index f4046b79af..bdf47f48ed 100644 --- a/build/win32/platform_specific_code/juce_win32_Fonts.cpp +++ b/build/win32/platform_specific_code/juce_win32_Fonts.cpp @@ -62,7 +62,7 @@ static int CALLBACK wfontEnum1 (ENUMLOGFONTEXW* lpelfe, zerostruct (lf); lf.lfWeight = FW_DONTCARE; - lf.lfOutPrecision = OUT_TT_ONLY_PRECIS; + lf.lfOutPrecision = OUT_OUTLINE_PRECIS; lf.lfQuality = DEFAULT_QUALITY; lf.lfCharSet = DEFAULT_CHARSET; lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; @@ -91,7 +91,7 @@ const StringArray Font::findAllTypefaceNames() throw() zerostruct (lf); lf.lfWeight = FW_DONTCARE; - lf.lfOutPrecision = OUT_TT_ONLY_PRECIS; + lf.lfOutPrecision = OUT_OUTLINE_PRECIS; lf.lfQuality = DEFAULT_QUALITY; lf.lfCharSet = DEFAULT_CHARSET; lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; diff --git a/build/win32/platform_specific_code/juce_win32_NativeIncludes.h b/build/win32/platform_specific_code/juce_win32_NativeIncludes.h index 91e95c61c6..975d62bb16 100644 --- a/build/win32/platform_specific_code/juce_win32_NativeIncludes.h +++ b/build/win32/platform_specific_code/juce_win32_NativeIncludes.h @@ -201,8 +201,12 @@ public: HRESULT CoCreateInstance (REFCLSID rclsid, DWORD dwClsContext) { +#ifndef __MINGW32__ operator= (0); return ::CoCreateInstance (rclsid, 0, dwClsContext, __uuidof(T), (void**) &p); +#else + return S_FALSE; +#endif } T* p; diff --git a/build/win32/platform_specific_code/juce_win32_Network.cpp b/build/win32/platform_specific_code/juce_win32_Network.cpp index cb027a6eaa..260764c514 100644 --- a/build/win32/platform_specific_code/juce_win32_Network.cpp +++ b/build/win32/platform_specific_code/juce_win32_Network.cpp @@ -219,22 +219,25 @@ int juce_seekInInternetFile (void* handle, int newPosition) int64 juce_getInternetFileContentLength (void* handle) { - DWORD result = -1; const ConnectionAndRequestStruct* const crs = (const ConnectionAndRequestStruct*) handle; if (crs != 0) { DWORD index = 0; + DWORD result = 0; DWORD size = sizeof (result); - HttpQueryInfo (crs->request, - HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, - &result, - &size, - &index); + if (HttpQueryInfo (crs->request, + HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, + &result, + &size, + &index)) + { + return (int64) result; + } } - return (int) result; + return -1; } void juce_closeInternetFile (void* handle) diff --git a/extras/audio plugins/demo/build/linux/premake.lua b/extras/audio plugins/demo/build/linux/premake.lua index f3782f6840..6c140cb6a4 100644 --- a/extras/audio plugins/demo/build/linux/premake.lua +++ b/extras/audio plugins/demo/build/linux/premake.lua @@ -25,6 +25,7 @@ package.includepaths = { "../../../../../", "/usr/include/vst/source/common", "/usr/include/vst", + "/usr/include/freetype2", "../../src" } diff --git a/extras/the jucer/src/model/jucer_GeneratedCode.cpp b/extras/the jucer/src/model/jucer_GeneratedCode.cpp index e2fd20cef5..1c6433903c 100644 --- a/extras/the jucer/src/model/jucer_GeneratedCode.cpp +++ b/extras/the jucer/src/model/jucer_GeneratedCode.cpp @@ -1,383 +1,388 @@ -/* - ============================================================================== - - This file is part of the JUCE library - "Jules' Utility Class Extensions" - Copyright 2004-7 by Raw Material Software ltd. - - ------------------------------------------------------------------------------ - - JUCE can be redistributed and/or modified under the terms of the - GNU General Public License, as published by the Free Software Foundation; - either version 2 of the License, or (at your option) any later version. - - JUCE is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with JUCE; if not, visit www.gnu.org/licenses or write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - ------------------------------------------------------------------------------ - - If you'd like to release a closed-source product which uses JUCE, commercial - licenses are also available: visit www.rawmaterialsoftware.com/juce for - more information. - - ============================================================================== -*/ - -#include "../jucer_Headers.h" -#include "jucer_GeneratedCode.h" - - -//============================================================================== -GeneratedCode::GeneratedCode (const JucerDocument* const document_) - : document (document_), - suffix (0) -{ -} - -GeneratedCode::~GeneratedCode() -{ -} - -int GeneratedCode::getUniqueSuffix() -{ - return ++suffix; -} - -//============================================================================== -String& GeneratedCode::getCallbackCode (const String& requiredParentClass, - const String& returnType, - const String& prototype, - const bool hasPrePostUserSections) -{ - String parentClass (requiredParentClass); - if (parentClass.isNotEmpty() - && ! (parentClass.startsWith (T("public ")) - || parentClass.startsWith (T("private ")) - || parentClass.startsWith (T("protected ")))) - { - parentClass = T("public ") + parentClass; - } - - for (int i = callbacks.size(); --i >= 0;) - { - CallbackMethod* const cm = callbacks.getUnchecked(i); - - if (cm->requiredParentClass == parentClass - && cm->returnType == returnType - && cm->prototype == prototype) - return cm->content; - } - - CallbackMethod* const cm = new CallbackMethod(); - callbacks.add (cm); - - cm->requiredParentClass = parentClass; - cm->returnType = returnType; - cm->prototype = prototype; - cm->hasPrePostUserSections = hasPrePostUserSections; - return cm->content; -} - -void GeneratedCode::removeCallback (const String& returnType, const String& prototype) -{ - for (int i = callbacks.size(); --i >= 0;) - { - CallbackMethod* const cm = callbacks.getUnchecked(i); - - if (cm->returnType == returnType && cm->prototype == prototype) - callbacks.remove (i); - } -} - -void GeneratedCode::addImageResourceLoader (const String& imageMemberName, const String& resourceName) -{ - initialisers.add (imageMemberName + T(" (0)")); - - privateMemberDeclarations - << "Image* " << imageMemberName << ";\n"; - - if (resourceName.isNotEmpty()) - { - constructorCode - << imageMemberName << " = ImageCache::getFromMemory (" - << resourceName << ", " << resourceName << "Size);\n"; - - destructorCode - << "ImageCache::release (" << imageMemberName << ");\n"; - } -} - -const StringArray GeneratedCode::getExtraParentClasses() const -{ - StringArray s; - - for (int i = 0; i < callbacks.size(); ++i) - { - CallbackMethod* const cm = callbacks.getUnchecked(i); - s.add (cm->requiredParentClass); - } - - return s; -} - -const String GeneratedCode::getCallbackDeclarations() const -{ - String s; - - for (int i = 0; i < callbacks.size(); ++i) - { - CallbackMethod* const cm = callbacks.getUnchecked(i); - - s << cm->returnType << " " << cm->prototype << ";\n"; - } - - return s; -} - -const String GeneratedCode::getCallbackDefinitions() const -{ - String s; - - for (int i = 0; i < callbacks.size(); ++i) - { - CallbackMethod* const cm = callbacks.getUnchecked(i); - - const String userCodeBlockName (T("User") - + makeValidCppIdentifier (cm->prototype.upToFirstOccurrenceOf (T("("), false, false), - true, true, false).trim()); - - if (userCodeBlockName.isNotEmpty() && cm->hasPrePostUserSections) - { - s << cm->returnType << " " << className << "::" << cm->prototype - << "\n{\n //[" << userCodeBlockName << "_Pre]\n //[/" << userCodeBlockName - << "_Pre]\n\n " - << indentCode (cm->content.trim(), 4) - << "\n\n //[" << userCodeBlockName << "_Post]\n //[/" << userCodeBlockName - << "_Post]\n}\n\n"; - } - else - { - s << cm->returnType << " " << className << "::" << cm->prototype - << "\n{\n " - << indentCode (cm->content.trim(), 4) - << "\n}\n\n"; - } - } - - return s; -} - -//============================================================================== -const String GeneratedCode::getClassDeclaration() const -{ - StringArray parentClassLines; - parentClassLines.addTokens (parentClasses, T(","), 0); - parentClassLines.addArray (getExtraParentClasses()); - - parentClassLines.trim(); - parentClassLines.removeEmptyStrings(); - parentClassLines.removeDuplicates (false); - - if (parentClassLines.contains (T("public Button"), false)) - parentClassLines.removeString (("public Component"), false); - - String r (T("class ")); - r << className << T(" : "); - - r += parentClassLines.joinIntoString (T(",\n") + String::repeatedString (T(" "), r.length())); - - return r; -} - -const String GeneratedCode::getInitialiserList() const -{ - StringArray inits (initialisers); - - if (parentClassInitialiser.isNotEmpty()) - inits.insert (0, parentClassInitialiser); - - inits.trim(); - inits.removeEmptyStrings(); - inits.removeDuplicates (false); - - String s; - - if (inits.size() == 0) - return s; - - s << " : "; - - for (int i = 0; i < inits.size(); ++i) - { - String init (inits[i]); - - while (init.endsWithChar (T(','))) - init = init.dropLastCharacters (1); - - s << init; - - if (i < inits.size() - 1) - s << ",\n "; - else - s << "\n"; - } - - return s; -} - -static const String getIncludeFileCode (StringArray files) -{ - files.trim(); - files.removeEmptyStrings(); - files.removeDuplicates (false); - - String s; - - for (int i = 0; i < files.size(); ++i) - s << T("#include \"") << files[i] << T("\"\n"); - - return s; -} - -//============================================================================== -static void replaceTemplate (String& text, const String& itemName, const String& value) -{ - for (;;) - { - const int index = text.indexOf (T("%%") + itemName + T("%%")); - - if (index < 0) - break; - - int indentLevel = 0; - - for (int i = index; --i >= 0;) - { - if (text[i] == T('\n')) - break; - - ++indentLevel; - } - - text = text.replaceSection (index, itemName.length() + 4, - indentCode (value, indentLevel)); - } -} - -//============================================================================== -static bool getUserSection (const StringArray& lines, const String& tag, StringArray& resultLines) -{ - const int start = indexOfLineStartingWith (lines, T("//[") + tag + T("]"), 0); - - if (start < 0) - return false; - - const int end = indexOfLineStartingWith (lines, T("//[/") + tag + T("]"), start + 1); - - for (int i = start + 1; i < end; ++i) - resultLines.add (lines [i]); - - return true; -} - -static void copyAcrossUserSections (String& dest, const String& src) -{ - StringArray srcLines, dstLines; - srcLines.addLines (src); - dstLines.addLines (dest); - - for (int i = 0; i < dstLines.size(); ++i) - { - if (dstLines[i].trimStart().startsWith (T("//["))) - { - String tag (dstLines[i].trimStart().substring (3)); - tag = tag.upToFirstOccurrenceOf (T("]"), false, false); - - jassert (! tag.startsWithChar (T('/'))); - - if (! tag.startsWithChar (T('/'))) - { - const int endLine = indexOfLineStartingWith (dstLines, - T("//[/") + tag + T("]"), - i + 1); - - if (endLine > i) - { - StringArray sourceLines; - - if (getUserSection (srcLines, tag, sourceLines)) - { - int j; - for (j = endLine - i; --j > 0;) - dstLines.remove (i + 1); - - for (j = 0; j < sourceLines.size(); ++j) - dstLines.insert (++i, sourceLines [j].trimEnd()); - - ++i; - } - else - { - i = endLine; - } - } - } - } - - dstLines.set (i, dstLines[i].trimEnd()); - } - - dest = dstLines.joinIntoString (T("\n")) + T("\n"); -} - -//============================================================================== -void GeneratedCode::applyToCode (String& code, - const String& fileNameRoot, - const bool isForPreview, - const String& oldFileWithUserData) const -{ - // header guard.. - String headerGuard ("__JUCER_HEADER_"); - headerGuard << className.toUpperCase().retainCharacters (T("ABCDEFGHIJKLMNOPQRSTUVWXYZ")) - << "_" << fileNameRoot.toUpperCase().retainCharacters (T("ABCDEFGHIJKLMNOPQRSTUVWXYZ")) - << "_" << String::toHexString (Random::getSystemRandom().nextInt()).toUpperCase() - << "__"; - replaceTemplate (code, "headerGuard", headerGuard); - - replaceTemplate (code, "creationTime", Time::getCurrentTime().toString (true, true, true)); - - replaceTemplate (code, "className", className); - replaceTemplate (code, "constructorParams", constructorParams); - replaceTemplate (code, "initialisers", getInitialiserList()); - - replaceTemplate (code, "classDeclaration", getClassDeclaration()); - replaceTemplate (code, "privateMemberDeclarations", privateMemberDeclarations); - replaceTemplate (code, "publicMemberDeclarations", getCallbackDeclarations() + "\n" + publicMemberDeclarations); - - replaceTemplate (code, "methodDefinitions", getCallbackDefinitions()); - - replaceTemplate (code, "includeFilesH", getIncludeFileCode (includeFilesH)); - replaceTemplate (code, "includeFilesCPP", getIncludeFileCode (includeFilesCPP)); - - replaceTemplate (code, "constructor", constructorCode); - replaceTemplate (code, "destructor", destructorCode); - - if (! isForPreview) - { - replaceTemplate (code, "metadata", jucerMetadata); - replaceTemplate (code, "staticMemberDefinitions", staticMemberDefinitions); - } - else - { - replaceTemplate (code, "metadata", T(" << Metadata isn't shown in the code preview >>\n")); - replaceTemplate (code, "staticMemberDefinitions", T("// Static member declarations and resources would go here... (these aren't shown in the code preview)")); - } - - copyAcrossUserSections (code, oldFileWithUserData); -} +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#include "../jucer_Headers.h" +#include "jucer_GeneratedCode.h" + + +//============================================================================== +GeneratedCode::GeneratedCode (const JucerDocument* const document_) + : document (document_), + suffix (0) +{ +} + +GeneratedCode::~GeneratedCode() +{ +} + +int GeneratedCode::getUniqueSuffix() +{ + return ++suffix; +} + +//============================================================================== +String& GeneratedCode::getCallbackCode (const String& requiredParentClass, + const String& returnType, + const String& prototype, + const bool hasPrePostUserSections) +{ + String parentClass (requiredParentClass); + if (parentClass.isNotEmpty() + && ! (parentClass.startsWith (T("public ")) + || parentClass.startsWith (T("private ")) + || parentClass.startsWith (T("protected ")))) + { + parentClass = T("public ") + parentClass; + } + + for (int i = callbacks.size(); --i >= 0;) + { + CallbackMethod* const cm = callbacks.getUnchecked(i); + + if (cm->requiredParentClass == parentClass + && cm->returnType == returnType + && cm->prototype == prototype) + return cm->content; + } + + CallbackMethod* const cm = new CallbackMethod(); + callbacks.add (cm); + + cm->requiredParentClass = parentClass; + cm->returnType = returnType; + cm->prototype = prototype; + cm->hasPrePostUserSections = hasPrePostUserSections; + return cm->content; +} + +void GeneratedCode::removeCallback (const String& returnType, const String& prototype) +{ + for (int i = callbacks.size(); --i >= 0;) + { + CallbackMethod* const cm = callbacks.getUnchecked(i); + + if (cm->returnType == returnType && cm->prototype == prototype) + callbacks.remove (i); + } +} + +void GeneratedCode::addImageResourceLoader (const String& imageMemberName, const String& resourceName) +{ + const String initialiser (imageMemberName + T(" (0)")); + + if (! initialisers.contains (initialiser, false)) + { + initialisers.add (initialiser); + + privateMemberDeclarations + << "Image* " << imageMemberName << ";\n"; + + if (resourceName.isNotEmpty()) + { + constructorCode + << imageMemberName << " = ImageCache::getFromMemory (" + << resourceName << ", " << resourceName << "Size);\n"; + + destructorCode + << "ImageCache::release (" << imageMemberName << ");\n"; + } + } +} + +const StringArray GeneratedCode::getExtraParentClasses() const +{ + StringArray s; + + for (int i = 0; i < callbacks.size(); ++i) + { + CallbackMethod* const cm = callbacks.getUnchecked(i); + s.add (cm->requiredParentClass); + } + + return s; +} + +const String GeneratedCode::getCallbackDeclarations() const +{ + String s; + + for (int i = 0; i < callbacks.size(); ++i) + { + CallbackMethod* const cm = callbacks.getUnchecked(i); + + s << cm->returnType << " " << cm->prototype << ";\n"; + } + + return s; +} + +const String GeneratedCode::getCallbackDefinitions() const +{ + String s; + + for (int i = 0; i < callbacks.size(); ++i) + { + CallbackMethod* const cm = callbacks.getUnchecked(i); + + const String userCodeBlockName (T("User") + + makeValidCppIdentifier (cm->prototype.upToFirstOccurrenceOf (T("("), false, false), + true, true, false).trim()); + + if (userCodeBlockName.isNotEmpty() && cm->hasPrePostUserSections) + { + s << cm->returnType << " " << className << "::" << cm->prototype + << "\n{\n //[" << userCodeBlockName << "_Pre]\n //[/" << userCodeBlockName + << "_Pre]\n\n " + << indentCode (cm->content.trim(), 4) + << "\n\n //[" << userCodeBlockName << "_Post]\n //[/" << userCodeBlockName + << "_Post]\n}\n\n"; + } + else + { + s << cm->returnType << " " << className << "::" << cm->prototype + << "\n{\n " + << indentCode (cm->content.trim(), 4) + << "\n}\n\n"; + } + } + + return s; +} + +//============================================================================== +const String GeneratedCode::getClassDeclaration() const +{ + StringArray parentClassLines; + parentClassLines.addTokens (parentClasses, T(","), 0); + parentClassLines.addArray (getExtraParentClasses()); + + parentClassLines.trim(); + parentClassLines.removeEmptyStrings(); + parentClassLines.removeDuplicates (false); + + if (parentClassLines.contains (T("public Button"), false)) + parentClassLines.removeString (("public Component"), false); + + String r (T("class ")); + r << className << T(" : "); + + r += parentClassLines.joinIntoString (T(",\n") + String::repeatedString (T(" "), r.length())); + + return r; +} + +const String GeneratedCode::getInitialiserList() const +{ + StringArray inits (initialisers); + + if (parentClassInitialiser.isNotEmpty()) + inits.insert (0, parentClassInitialiser); + + inits.trim(); + inits.removeEmptyStrings(); + inits.removeDuplicates (false); + + String s; + + if (inits.size() == 0) + return s; + + s << " : "; + + for (int i = 0; i < inits.size(); ++i) + { + String init (inits[i]); + + while (init.endsWithChar (T(','))) + init = init.dropLastCharacters (1); + + s << init; + + if (i < inits.size() - 1) + s << ",\n "; + else + s << "\n"; + } + + return s; +} + +static const String getIncludeFileCode (StringArray files) +{ + files.trim(); + files.removeEmptyStrings(); + files.removeDuplicates (false); + + String s; + + for (int i = 0; i < files.size(); ++i) + s << T("#include \"") << files[i] << T("\"\n"); + + return s; +} + +//============================================================================== +static void replaceTemplate (String& text, const String& itemName, const String& value) +{ + for (;;) + { + const int index = text.indexOf (T("%%") + itemName + T("%%")); + + if (index < 0) + break; + + int indentLevel = 0; + + for (int i = index; --i >= 0;) + { + if (text[i] == T('\n')) + break; + + ++indentLevel; + } + + text = text.replaceSection (index, itemName.length() + 4, + indentCode (value, indentLevel)); + } +} + +//============================================================================== +static bool getUserSection (const StringArray& lines, const String& tag, StringArray& resultLines) +{ + const int start = indexOfLineStartingWith (lines, T("//[") + tag + T("]"), 0); + + if (start < 0) + return false; + + const int end = indexOfLineStartingWith (lines, T("//[/") + tag + T("]"), start + 1); + + for (int i = start + 1; i < end; ++i) + resultLines.add (lines [i]); + + return true; +} + +static void copyAcrossUserSections (String& dest, const String& src) +{ + StringArray srcLines, dstLines; + srcLines.addLines (src); + dstLines.addLines (dest); + + for (int i = 0; i < dstLines.size(); ++i) + { + if (dstLines[i].trimStart().startsWith (T("//["))) + { + String tag (dstLines[i].trimStart().substring (3)); + tag = tag.upToFirstOccurrenceOf (T("]"), false, false); + + jassert (! tag.startsWithChar (T('/'))); + + if (! tag.startsWithChar (T('/'))) + { + const int endLine = indexOfLineStartingWith (dstLines, + T("//[/") + tag + T("]"), + i + 1); + + if (endLine > i) + { + StringArray sourceLines; + + if (getUserSection (srcLines, tag, sourceLines)) + { + int j; + for (j = endLine - i; --j > 0;) + dstLines.remove (i + 1); + + for (j = 0; j < sourceLines.size(); ++j) + dstLines.insert (++i, sourceLines [j].trimEnd()); + + ++i; + } + else + { + i = endLine; + } + } + } + } + + dstLines.set (i, dstLines[i].trimEnd()); + } + + dest = dstLines.joinIntoString (T("\n")) + T("\n"); +} + +//============================================================================== +void GeneratedCode::applyToCode (String& code, + const String& fileNameRoot, + const bool isForPreview, + const String& oldFileWithUserData) const +{ + // header guard.. + String headerGuard ("__JUCER_HEADER_"); + headerGuard << className.toUpperCase().retainCharacters (T("ABCDEFGHIJKLMNOPQRSTUVWXYZ")) + << "_" << fileNameRoot.toUpperCase().retainCharacters (T("ABCDEFGHIJKLMNOPQRSTUVWXYZ")) + << "_" << String::toHexString (Random::getSystemRandom().nextInt()).toUpperCase() + << "__"; + replaceTemplate (code, "headerGuard", headerGuard); + + replaceTemplate (code, "creationTime", Time::getCurrentTime().toString (true, true, true)); + + replaceTemplate (code, "className", className); + replaceTemplate (code, "constructorParams", constructorParams); + replaceTemplate (code, "initialisers", getInitialiserList()); + + replaceTemplate (code, "classDeclaration", getClassDeclaration()); + replaceTemplate (code, "privateMemberDeclarations", privateMemberDeclarations); + replaceTemplate (code, "publicMemberDeclarations", getCallbackDeclarations() + "\n" + publicMemberDeclarations); + + replaceTemplate (code, "methodDefinitions", getCallbackDefinitions()); + + replaceTemplate (code, "includeFilesH", getIncludeFileCode (includeFilesH)); + replaceTemplate (code, "includeFilesCPP", getIncludeFileCode (includeFilesCPP)); + + replaceTemplate (code, "constructor", constructorCode); + replaceTemplate (code, "destructor", destructorCode); + + if (! isForPreview) + { + replaceTemplate (code, "metadata", jucerMetadata); + replaceTemplate (code, "staticMemberDefinitions", staticMemberDefinitions); + } + else + { + replaceTemplate (code, "metadata", T(" << Metadata isn't shown in the code preview >>\n")); + replaceTemplate (code, "staticMemberDefinitions", T("// Static member declarations and resources would go here... (these aren't shown in the code preview)")); + } + + copyAcrossUserSections (code, oldFileWithUserData); +} diff --git a/extras/the jucer/src/model/paintelements/jucer_FillType.cpp b/extras/the jucer/src/model/paintelements/jucer_FillType.cpp index f2d77f7e8b..fa39a1126d 100644 --- a/extras/the jucer/src/model/paintelements/jucer_FillType.cpp +++ b/extras/the jucer/src/model/paintelements/jucer_FillType.cpp @@ -182,7 +182,7 @@ void FillType::fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode case imageBrush: { - const String imageVariable (T("internalCachedImage") + String (code.getUniqueSuffix())); + const String imageVariable ("cachedImage_" + imageResourceName + "_" + String (code.getUniqueSuffix())); code.addImageResourceLoader (imageVariable, imageResourceName); diff --git a/extras/the jucer/src/model/paintelements/jucer_PaintElementImage.h b/extras/the jucer/src/model/paintelements/jucer_PaintElementImage.h index 86fd22e777..4a243c9722 100644 --- a/extras/the jucer/src/model/paintelements/jucer_PaintElementImage.h +++ b/extras/the jucer/src/model/paintelements/jucer_PaintElementImage.h @@ -1,536 +1,536 @@ -/* - ============================================================================== - - This file is part of the JUCE library - "Jules' Utility Class Extensions" - Copyright 2004-7 by Raw Material Software ltd. - - ------------------------------------------------------------------------------ - - JUCE can be redistributed and/or modified under the terms of the - GNU General Public License, as published by the Free Software Foundation; - either version 2 of the License, or (at your option) any later version. - - JUCE is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with JUCE; if not, visit www.gnu.org/licenses or write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - - ------------------------------------------------------------------------------ - - If you'd like to release a closed-source product which uses JUCE, commercial - licenses are also available: visit www.rawmaterialsoftware.com/juce for - more information. - - ============================================================================== -*/ - -#ifndef __JUCER_PAINTELEMENTIMAGE_JUCEHEADER__ -#define __JUCER_PAINTELEMENTIMAGE_JUCEHEADER__ - -#include "../jucer_PaintRoutine.h" -#include "../../properties/jucer_FilePropertyComponent.h" -#include "jucer_ImageResourceProperty.h" -#include "jucer_PaintElementUndoableAction.h" - - -//============================================================================== -/** -*/ -class PaintElementImage : public PaintElement -{ -public: - enum StretchMode - { - stretched = 0, - proportional = 1, - proportionalReducingOnly = 2 - }; - - //============================================================================== - PaintElementImage (PaintRoutine* owner) - : PaintElement (owner, T("Image")), - opacity (1.0), - mode (stretched) - { - } - - ~PaintElementImage() - { - } - - //============================================================================== - const Drawable* getDrawable() - { - JucerDocument* const document = getDocument(); - - if (document != 0) - return document->getResources().getDrawable (resourceName); - - return 0; - } - - void draw (Graphics& g, const ComponentLayout* layout, const Rectangle& parentArea) - { - const Rectangle r (position.getRectangle (parentArea, layout)); - - const Drawable* const image = getDrawable(); - - if (image != 0) - { - g.setColour (Colours::black.withAlpha ((float) opacity)); - - image->drawWithin (g, r.getX(), r.getY(), r.getWidth(), r.getHeight(), - mode == stretched ? RectanglePlacement::stretchToFit - : (mode == proportionalReducingOnly ? (RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize) - : RectanglePlacement::centred)); - } - else - { - g.setColour (Colours::grey.withAlpha (0.5f)); - g.fillRect (r); - - g.setColour (Colours::black); - g.drawText (T("(image missing)"), - r.getX(), r.getY(), r.getWidth(), r.getHeight(), - Justification::centred, true); - } - } - - //============================================================================== - void getEditableProperties (Array & properties) - { - PaintElement::getEditableProperties (properties); - - properties.add (new ImageElementResourceProperty (this)); - properties.add (new StretchModeProperty (this)); - properties.add (new OpacityProperty (this)); - properties.add (new ResetSizeProperty (this)); - } - - void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) - { - String r; - - if (opacity > 0) - { - if (dynamic_cast (getDrawable()) != 0) - { - const String imageVariable (T("internalCachedImage") + String (code.getUniqueSuffix())); - - code.addImageResourceLoader (imageVariable, resourceName); - - if (opacity >= 254.0 / 255.0) - r << "g.setColour (Colours::black);\n"; - else - r << "g.setColour (Colours::black.withAlpha (" << valueToFloat (opacity) << "));\n"; - - String x, y, w, h; - positionToCode (position, getDocument()->getComponentLayout(), x, y, w, h); - - if (mode == stretched) - { - r << "g.drawImage (" << imageVariable << ",\n " - << x << ", " << y << ", " << w << ", " << h - << ",\n 0, 0, " - << imageVariable << "->getWidth(), " - << imageVariable << "->getHeight());\n\n"; - } - else - { - r << "g.drawImageWithin (" << imageVariable << ",\n " - << x << ", " << y << ", " << w << ", " << h - << ",\n "; - - if (mode == proportionalReducingOnly) - r << "RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize"; - else - r << "RectanglePlacement::centred"; - - r << ",\n false);\n\n"; - } - - paintMethodCode += r; - } - else - { - if (resourceName.isNotEmpty()) - { - const String imageVariable (T("drawable") + String (code.getUniqueSuffix())); - - code.privateMemberDeclarations - << "Drawable* " << imageVariable << ";\n"; - - code.constructorCode - << imageVariable << " = Drawable::createFromImageData (" - << resourceName << ", " << resourceName << "Size);\n"; - - code.destructorCode - << "deleteAndZero (" << imageVariable << ");\n"; - - if (opacity >= 254.0 / 255.0) - r << "g.setColour (Colours::black);\n"; - else - r << "g.setColour (Colours::black.withAlpha (" << valueToFloat (opacity) << "));\n"; - - String x, y, w, h; - positionToCode (position, code.document->getComponentLayout(), x, y, w, h); - - r << "jassert (" << imageVariable << " != 0);\n" - << "if (" << imageVariable << " != 0)\n " - << imageVariable << "->drawWithin (g, " - << x << ", " << y << ", " << w << ", " << h - << ",\n" - << String::repeatedString (T(" "), imageVariable.length() + 18) - << (mode == stretched ? "RectanglePlacement::stretchToFit" - : (mode == proportionalReducingOnly ? "RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize" - : "RectanglePlacement::centred")) - << ");\n\n"; - - paintMethodCode += r; - } - else - { - jassertfalse // this resource isn't valid! - } - } - } - } - - //============================================================================== - class SetResourceAction : public PaintElementUndoableAction - { - public: - SetResourceAction (PaintElementImage* const element, const String& newResource_) - : PaintElementUndoableAction (element), - newResource (newResource_) - { - oldResource = element->getResource(); - } - - bool perform() - { - showCorrectTab(); - getElement()->setResource (newResource, false); - return true; - } - - bool undo() - { - showCorrectTab(); - getElement()->setResource (oldResource, false); - return true; - } - - private: - String newResource, oldResource; - }; - - void setResource (const String& newName, const bool undoable) - { - if (resourceName != newName) - { - if (undoable) - { - perform (new SetResourceAction (this, newName), - T("Change image resource")); - } - else - { - resourceName = newName; - changed(); - } - } - - repaint(); - } - - const String getResource() const - { - return resourceName; - } - - //============================================================================== - class SetOpacityAction : public PaintElementUndoableAction - { - public: - SetOpacityAction (PaintElementImage* const element, const double newOpacity_) - : PaintElementUndoableAction (element), - newOpacity (newOpacity_) - { - oldOpacity = element->getOpacity(); - } - - bool perform() - { - showCorrectTab(); - getElement()->setOpacity (newOpacity, false); - return true; - } - - bool undo() - { - showCorrectTab(); - getElement()->setOpacity (oldOpacity, false); - return true; - } - - private: - double newOpacity, oldOpacity; - }; - - void setOpacity (double newOpacity, const bool undoable) - { - newOpacity = jlimit (0.0, 1.0, newOpacity); - - if (opacity != newOpacity) - { - if (undoable) - { - perform (new SetOpacityAction (this, newOpacity), - T("Change image opacity")); - } - else - { - opacity = newOpacity; - changed(); - } - } - } - - double getOpacity() const throw() { return opacity; } - - //============================================================================== - static const tchar* getTagName() throw() { return T("IMAGE"); } - - void resetToImageSize() - { - const Drawable* const image = getDrawable(); - - if (image != 0 && getParentComponent() != 0) - { - const Rectangle parentArea (((PaintRoutineEditor*) getParentComponent())->getComponentArea()); - - Rectangle r (getCurrentBounds (parentArea)); - - float x, y, w, h; - image->getBounds (x, y, w, h); - - r.setSize ((int) (w + 1.0f), (int) (h + 1.0f)); - - setCurrentBounds (r, parentArea, true); - } - } - - //============================================================================== - class SetStretchModeAction : public PaintElementUndoableAction - { - public: - SetStretchModeAction (PaintElementImage* const element, const StretchMode newValue_) - : PaintElementUndoableAction (element), - newValue (newValue_) - { - oldValue = element->getStretchMode(); - } - - bool perform() - { - showCorrectTab(); - getElement()->setStretchMode (newValue, false); - return true; - } - - bool undo() - { - showCorrectTab(); - getElement()->setStretchMode (oldValue, false); - return true; - } - - private: - StretchMode newValue, oldValue; - }; - - StretchMode getStretchMode() const throw() { return mode; } - - void setStretchMode (const StretchMode newMode, const bool undoable) - { - if (mode != newMode) - { - if (undoable) - { - perform (new SetStretchModeAction (this, newMode), - T("Change image mode")); - } - else - { - mode = newMode; - changed(); - } - } - } - - //============================================================================== - XmlElement* createXml() const - { - XmlElement* e = new XmlElement (getTagName()); - position.applyToXml (*e); - e->setAttribute (T("resource"), resourceName); - e->setAttribute (T("opacity"), opacity); - e->setAttribute (T("mode"), (int) mode); - - return e; - } - - bool loadFromXml (const XmlElement& xml) - { - if (xml.hasTagName (getTagName())) - { - position.restoreFromXml (xml, position); - resourceName = xml.getStringAttribute (T("resource"), String::empty); - opacity = xml.getDoubleAttribute (T("opacity"), 1.0); - mode = (StretchMode) xml.getIntAttribute (T("mode"), (int) stretched); - - repaint(); - return true; - } - else - { - jassertfalse - return false; - } - } - - //============================================================================== - juce_UseDebuggingNewOperator - -private: - String resourceName; - double opacity; - StretchMode mode; - - //============================================================================== - class ImageElementResourceProperty : public ImageResourceProperty - { - public: - ImageElementResourceProperty (PaintElementImage* const element_) - : ImageResourceProperty (element_, T("image source")) - { - } - - //============================================================================== - void setResource (const String& newName) - { - element->setResource (newName, true); - } - - const String getResource() const - { - return element->getResource(); - } - }; - - //============================================================================== - class OpacityProperty : public SliderPropertyComponent, - private ChangeListener - { - public: - OpacityProperty (PaintElementImage* const element_) - : SliderPropertyComponent (T("opacity"), 0.0, 1.0, 0.001), - element (element_) - { - element->getDocument()->addChangeListener (this); - } - - ~OpacityProperty() - { - element->getDocument()->removeChangeListener (this); - } - - void setValue (const double newValue) - { - element->getDocument()->getUndoManager().undoCurrentTransactionOnly(); - - element->setOpacity (newValue, true); - } - - const double getValue() const - { - return element->getOpacity(); - } - - void changeListenerCallback (void*) - { - refresh(); - } - - private: - PaintElementImage* const element; - }; - - class StretchModeProperty : public ChoicePropertyComponent, - private ChangeListener - { - public: - StretchModeProperty (PaintElementImage* const element_) - : ChoicePropertyComponent (T("stretch mode")), - element (element_) - { - choices.add (T("Stretched to fit")); - choices.add (T("Maintain aspect ratio")); - choices.add (T("Maintain aspect ratio, only reduce in size")); - - element->getDocument()->addChangeListener (this); - } - - ~StretchModeProperty() - { - element->getDocument()->removeChangeListener (this); - } - - void setIndex (const int newIndex) - { - element->setStretchMode ((StretchMode) newIndex, true); - } - - int getIndex() const - { - return (int) element->getStretchMode(); - } - - void changeListenerCallback (void*) - { - refresh(); - } - - private: - PaintElementImage* const element; - }; - - class ResetSizeProperty : public ButtonPropertyComponent - { - public: - ResetSizeProperty (PaintElementImage* const element_) - : ButtonPropertyComponent (T("reset"), false), - element (element_) - { - } - - void buttonClicked() - { - element->resetToImageSize(); - } - - const String getButtonText() const { return T("reset to image size"); } - - private: - PaintElementImage* const element; - }; -}; - - -#endif // __JUCER_PAINTELEMENTIMAGE_JUCEHEADER__ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-7 by Raw Material Software ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the + GNU General Public License, as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + JUCE is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JUCE; if not, visit www.gnu.org/licenses or write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------------ + + If you'd like to release a closed-source product which uses JUCE, commercial + licenses are also available: visit www.rawmaterialsoftware.com/juce for + more information. + + ============================================================================== +*/ + +#ifndef __JUCER_PAINTELEMENTIMAGE_JUCEHEADER__ +#define __JUCER_PAINTELEMENTIMAGE_JUCEHEADER__ + +#include "../jucer_PaintRoutine.h" +#include "../../properties/jucer_FilePropertyComponent.h" +#include "jucer_ImageResourceProperty.h" +#include "jucer_PaintElementUndoableAction.h" + + +//============================================================================== +/** +*/ +class PaintElementImage : public PaintElement +{ +public: + enum StretchMode + { + stretched = 0, + proportional = 1, + proportionalReducingOnly = 2 + }; + + //============================================================================== + PaintElementImage (PaintRoutine* owner) + : PaintElement (owner, T("Image")), + opacity (1.0), + mode (stretched) + { + } + + ~PaintElementImage() + { + } + + //============================================================================== + const Drawable* getDrawable() + { + JucerDocument* const document = getDocument(); + + if (document != 0) + return document->getResources().getDrawable (resourceName); + + return 0; + } + + void draw (Graphics& g, const ComponentLayout* layout, const Rectangle& parentArea) + { + const Rectangle r (position.getRectangle (parentArea, layout)); + + const Drawable* const image = getDrawable(); + + if (image != 0) + { + g.setColour (Colours::black.withAlpha ((float) opacity)); + + image->drawWithin (g, r.getX(), r.getY(), r.getWidth(), r.getHeight(), + mode == stretched ? RectanglePlacement::stretchToFit + : (mode == proportionalReducingOnly ? (RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize) + : RectanglePlacement::centred)); + } + else + { + g.setColour (Colours::grey.withAlpha (0.5f)); + g.fillRect (r); + + g.setColour (Colours::black); + g.drawText (T("(image missing)"), + r.getX(), r.getY(), r.getWidth(), r.getHeight(), + Justification::centred, true); + } + } + + //============================================================================== + void getEditableProperties (Array & properties) + { + PaintElement::getEditableProperties (properties); + + properties.add (new ImageElementResourceProperty (this)); + properties.add (new StretchModeProperty (this)); + properties.add (new OpacityProperty (this)); + properties.add (new ResetSizeProperty (this)); + } + + void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) + { + String r; + + if (opacity > 0) + { + if (dynamic_cast (getDrawable()) != 0) + { + const String imageVariable ("cachedImage_" + resourceName); + + code.addImageResourceLoader (imageVariable, resourceName); + + if (opacity >= 254.0 / 255.0) + r << "g.setColour (Colours::black);\n"; + else + r << "g.setColour (Colours::black.withAlpha (" << valueToFloat (opacity) << "));\n"; + + String x, y, w, h; + positionToCode (position, getDocument()->getComponentLayout(), x, y, w, h); + + if (mode == stretched) + { + r << "g.drawImage (" << imageVariable << ",\n " + << x << ", " << y << ", " << w << ", " << h + << ",\n 0, 0, " + << imageVariable << "->getWidth(), " + << imageVariable << "->getHeight());\n\n"; + } + else + { + r << "g.drawImageWithin (" << imageVariable << ",\n " + << x << ", " << y << ", " << w << ", " << h + << ",\n "; + + if (mode == proportionalReducingOnly) + r << "RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize"; + else + r << "RectanglePlacement::centred"; + + r << ",\n false);\n\n"; + } + + paintMethodCode += r; + } + else + { + if (resourceName.isNotEmpty()) + { + const String imageVariable (T("drawable") + String (code.getUniqueSuffix())); + + code.privateMemberDeclarations + << "Drawable* " << imageVariable << ";\n"; + + code.constructorCode + << imageVariable << " = Drawable::createFromImageData (" + << resourceName << ", " << resourceName << "Size);\n"; + + code.destructorCode + << "deleteAndZero (" << imageVariable << ");\n"; + + if (opacity >= 254.0 / 255.0) + r << "g.setColour (Colours::black);\n"; + else + r << "g.setColour (Colours::black.withAlpha (" << valueToFloat (opacity) << "));\n"; + + String x, y, w, h; + positionToCode (position, code.document->getComponentLayout(), x, y, w, h); + + r << "jassert (" << imageVariable << " != 0);\n" + << "if (" << imageVariable << " != 0)\n " + << imageVariable << "->drawWithin (g, " + << x << ", " << y << ", " << w << ", " << h + << ",\n" + << String::repeatedString (T(" "), imageVariable.length() + 18) + << (mode == stretched ? "RectanglePlacement::stretchToFit" + : (mode == proportionalReducingOnly ? "RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize" + : "RectanglePlacement::centred")) + << ");\n\n"; + + paintMethodCode += r; + } + else + { + jassertfalse // this resource isn't valid! + } + } + } + } + + //============================================================================== + class SetResourceAction : public PaintElementUndoableAction + { + public: + SetResourceAction (PaintElementImage* const element, const String& newResource_) + : PaintElementUndoableAction (element), + newResource (newResource_) + { + oldResource = element->getResource(); + } + + bool perform() + { + showCorrectTab(); + getElement()->setResource (newResource, false); + return true; + } + + bool undo() + { + showCorrectTab(); + getElement()->setResource (oldResource, false); + return true; + } + + private: + String newResource, oldResource; + }; + + void setResource (const String& newName, const bool undoable) + { + if (resourceName != newName) + { + if (undoable) + { + perform (new SetResourceAction (this, newName), + T("Change image resource")); + } + else + { + resourceName = newName; + changed(); + } + } + + repaint(); + } + + const String getResource() const + { + return resourceName; + } + + //============================================================================== + class SetOpacityAction : public PaintElementUndoableAction + { + public: + SetOpacityAction (PaintElementImage* const element, const double newOpacity_) + : PaintElementUndoableAction (element), + newOpacity (newOpacity_) + { + oldOpacity = element->getOpacity(); + } + + bool perform() + { + showCorrectTab(); + getElement()->setOpacity (newOpacity, false); + return true; + } + + bool undo() + { + showCorrectTab(); + getElement()->setOpacity (oldOpacity, false); + return true; + } + + private: + double newOpacity, oldOpacity; + }; + + void setOpacity (double newOpacity, const bool undoable) + { + newOpacity = jlimit (0.0, 1.0, newOpacity); + + if (opacity != newOpacity) + { + if (undoable) + { + perform (new SetOpacityAction (this, newOpacity), + T("Change image opacity")); + } + else + { + opacity = newOpacity; + changed(); + } + } + } + + double getOpacity() const throw() { return opacity; } + + //============================================================================== + static const tchar* getTagName() throw() { return T("IMAGE"); } + + void resetToImageSize() + { + const Drawable* const image = getDrawable(); + + if (image != 0 && getParentComponent() != 0) + { + const Rectangle parentArea (((PaintRoutineEditor*) getParentComponent())->getComponentArea()); + + Rectangle r (getCurrentBounds (parentArea)); + + float x, y, w, h; + image->getBounds (x, y, w, h); + + r.setSize ((int) (w + 1.0f), (int) (h + 1.0f)); + + setCurrentBounds (r, parentArea, true); + } + } + + //============================================================================== + class SetStretchModeAction : public PaintElementUndoableAction + { + public: + SetStretchModeAction (PaintElementImage* const element, const StretchMode newValue_) + : PaintElementUndoableAction (element), + newValue (newValue_) + { + oldValue = element->getStretchMode(); + } + + bool perform() + { + showCorrectTab(); + getElement()->setStretchMode (newValue, false); + return true; + } + + bool undo() + { + showCorrectTab(); + getElement()->setStretchMode (oldValue, false); + return true; + } + + private: + StretchMode newValue, oldValue; + }; + + StretchMode getStretchMode() const throw() { return mode; } + + void setStretchMode (const StretchMode newMode, const bool undoable) + { + if (mode != newMode) + { + if (undoable) + { + perform (new SetStretchModeAction (this, newMode), + T("Change image mode")); + } + else + { + mode = newMode; + changed(); + } + } + } + + //============================================================================== + XmlElement* createXml() const + { + XmlElement* e = new XmlElement (getTagName()); + position.applyToXml (*e); + e->setAttribute (T("resource"), resourceName); + e->setAttribute (T("opacity"), opacity); + e->setAttribute (T("mode"), (int) mode); + + return e; + } + + bool loadFromXml (const XmlElement& xml) + { + if (xml.hasTagName (getTagName())) + { + position.restoreFromXml (xml, position); + resourceName = xml.getStringAttribute (T("resource"), String::empty); + opacity = xml.getDoubleAttribute (T("opacity"), 1.0); + mode = (StretchMode) xml.getIntAttribute (T("mode"), (int) stretched); + + repaint(); + return true; + } + else + { + jassertfalse + return false; + } + } + + //============================================================================== + juce_UseDebuggingNewOperator + +private: + String resourceName; + double opacity; + StretchMode mode; + + //============================================================================== + class ImageElementResourceProperty : public ImageResourceProperty + { + public: + ImageElementResourceProperty (PaintElementImage* const element_) + : ImageResourceProperty (element_, T("image source")) + { + } + + //============================================================================== + void setResource (const String& newName) + { + element->setResource (newName, true); + } + + const String getResource() const + { + return element->getResource(); + } + }; + + //============================================================================== + class OpacityProperty : public SliderPropertyComponent, + private ChangeListener + { + public: + OpacityProperty (PaintElementImage* const element_) + : SliderPropertyComponent (T("opacity"), 0.0, 1.0, 0.001), + element (element_) + { + element->getDocument()->addChangeListener (this); + } + + ~OpacityProperty() + { + element->getDocument()->removeChangeListener (this); + } + + void setValue (const double newValue) + { + element->getDocument()->getUndoManager().undoCurrentTransactionOnly(); + + element->setOpacity (newValue, true); + } + + const double getValue() const + { + return element->getOpacity(); + } + + void changeListenerCallback (void*) + { + refresh(); + } + + private: + PaintElementImage* const element; + }; + + class StretchModeProperty : public ChoicePropertyComponent, + private ChangeListener + { + public: + StretchModeProperty (PaintElementImage* const element_) + : ChoicePropertyComponent (T("stretch mode")), + element (element_) + { + choices.add (T("Stretched to fit")); + choices.add (T("Maintain aspect ratio")); + choices.add (T("Maintain aspect ratio, only reduce in size")); + + element->getDocument()->addChangeListener (this); + } + + ~StretchModeProperty() + { + element->getDocument()->removeChangeListener (this); + } + + void setIndex (const int newIndex) + { + element->setStretchMode ((StretchMode) newIndex, true); + } + + int getIndex() const + { + return (int) element->getStretchMode(); + } + + void changeListenerCallback (void*) + { + refresh(); + } + + private: + PaintElementImage* const element; + }; + + class ResetSizeProperty : public ButtonPropertyComponent + { + public: + ResetSizeProperty (PaintElementImage* const element_) + : ButtonPropertyComponent (T("reset"), false), + element (element_) + { + } + + void buttonClicked() + { + element->resetToImageSize(); + } + + const String getButtonText() const { return T("reset to image size"); } + + private: + PaintElementImage* const element; + }; +}; + + +#endif // __JUCER_PAINTELEMENTIMAGE_JUCEHEADER__ diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 28cacaa8ef..d8f88c3783 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -627,8 +627,12 @@ public: HRESULT CoCreateInstance (REFCLSID rclsid, DWORD dwClsContext) { +#ifndef __MINGW32__ operator= (0); return ::CoCreateInstance (rclsid, 0, dwClsContext, __uuidof(T), (void**) &p); +#else + return S_FALSE; +#endif } T* p; @@ -7313,7 +7317,7 @@ static void initWin32Sockets() #endif -static bool resetSocketOptions (const int handle, const bool isDatagram) throw() +static bool resetSocketOptions (const int handle, const bool isDatagram, const bool allowBroadcast) throw() { const int sndBufSize = 65536; const int rcvBufSize = 65536; @@ -7322,7 +7326,7 @@ static bool resetSocketOptions (const int handle, const bool isDatagram) throw() return handle > 0 && setsockopt (handle, SOL_SOCKET, SO_RCVBUF, (const char*) &rcvBufSize, sizeof (rcvBufSize)) == 0 && setsockopt (handle, SOL_SOCKET, SO_SNDBUF, (const char*) &sndBufSize, sizeof (sndBufSize)) == 0 - && (isDatagram ? (setsockopt (handle, SOL_SOCKET, SO_BROADCAST, (const char*) &one, sizeof (one)) == 0) + && (isDatagram ? ((! allowBroadcast) || setsockopt (handle, SOL_SOCKET, SO_BROADCAST, (const char*) &one, sizeof (one)) == 0) : (setsockopt (handle, IPPROTO_TCP, TCP_NODELAY, (const char*) &one, sizeof (one)) == 0)); } @@ -7524,7 +7528,7 @@ static bool connectSocket (int volatile& handle, } setSocketBlockingState (handle, true); - resetSocketOptions (handle, false); + resetSocketOptions (handle, false, false); return true; } @@ -7553,7 +7557,7 @@ StreamingSocket::StreamingSocket (const String& hostName_, initWin32Sockets(); #endif - resetSocketOptions (handle_, false); + resetSocketOptions (handle_, false, false); } StreamingSocket::~StreamingSocket() @@ -7618,7 +7622,7 @@ bool StreamingSocket::connect (const String& remoteHostName, connected = connectSocket (handle, false, 0, remoteHostName, remotePortNumber, timeOutMillisecs); - if (! (connected && resetSocketOptions (handle, false))) + if (! (connected && resetSocketOptions (handle, false, false))) { close(); return false; @@ -7717,10 +7721,11 @@ bool StreamingSocket::isLocal() const throw() return hostName == T("127.0.0.1"); } -DatagramSocket::DatagramSocket (const int localPortNumber) +DatagramSocket::DatagramSocket (const int localPortNumber, const bool allowBroadcast_) : portNumber (0), handle (-1), connected (true), + allowBroadcast (allowBroadcast_), serverAddress (0) { #if JUCE_WIN32 @@ -7737,13 +7742,14 @@ DatagramSocket::DatagramSocket (const String& hostName_, const int portNumber_, portNumber (portNumber_), handle (handle_), connected (true), + allowBroadcast (false), serverAddress (0) { #if JUCE_WIN32 initWin32Sockets(); #endif - resetSocketOptions (handle_, true); + resetSocketOptions (handle_, true, allowBroadcast); bindToPort (localPortNumber); } @@ -7789,7 +7795,7 @@ bool DatagramSocket::connect (const String& remoteHostName, remoteHostName, remotePortNumber, timeOutMillisecs); - if (! (connected && resetSocketOptions (handle, true))) + if (! (connected && resetSocketOptions (handle, true, allowBroadcast))) { close(); return false; @@ -15276,7 +15282,7 @@ BEGIN_JUCE_NAMESPACE // these functions are implemented in the platform-specific code. void* juce_createThread (void* userData) throw(); void juce_killThread (void* handle) throw(); -void juce_setThreadPriority (void* handle, int priority) throw(); +bool juce_setThreadPriority (void* handle, int priority) throw(); void juce_setCurrentThreadName (const String& name) throw(); #if JUCE_WIN32 void juce_CloseThreadHandle (void* handle) throw(); @@ -15437,17 +15443,21 @@ void Thread::stopThread (const int timeOutMilliseconds) throw() } } -void Thread::setPriority (const int priority) throw() +bool Thread::setPriority (const int priority) throw() { const ScopedLock sl (startStopLock); - threadPriority_ = priority; - juce_setThreadPriority (threadHandle_, priority); + const bool worked = juce_setThreadPriority (threadHandle_, priority); + + if (worked) + threadPriority_ = priority; + + return worked; } -void Thread::setCurrentThreadPriority (const int priority) throw() +bool Thread::setCurrentThreadPriority (const int priority) throw() { - juce_setThreadPriority (0, priority); + return juce_setThreadPriority (0, priority); } void Thread::setAffinityMask (const uint32 affinityMask) throw() @@ -15792,15 +15802,20 @@ const StringArray ThreadPool::getNamesOfAllJobs (const bool onlyReturnActiveJobs return s; } -void ThreadPool::setThreadPriorities (const int newPriority) +bool ThreadPool::setThreadPriorities (const int newPriority) { + bool ok = true; + if (priority != newPriority) { priority = newPriority; for (int i = numThreads; --i >= 0;) - threads[i]->setPriority (newPriority); + if (! threads[i]->setPriority (newPriority)) + ok = false; } + + return ok; } bool ThreadPool::runNextJob() @@ -18334,7 +18349,7 @@ bool AudioFormatReader::read (int** destSamples, startSampleInSource, numSamplesToRead)) return false; - if (numDestChannels > numChannels) + if (numDestChannels > (int) numChannels) { if (fillLeftoverChannelsWithCopies) { @@ -58564,14 +58579,22 @@ void ResizableBorderComponent::updateMouseZone (const MouseEvent& e) throw() if (ResizableBorderComponent::hitTest (e.x, e.y)) { - if (e.x < jmax (borderSize.getLeft(), proportionOfWidth (0.1f))) + if (e.x < jmax (borderSize.getLeft(), + proportionOfWidth (0.1f), + jmin (10, proportionOfWidth (0.33f)))) newZone |= zoneL; - else if (e.x >= jmin (getWidth() - borderSize.getRight(), proportionOfWidth (0.9f))) + else if (e.x >= jmin (getWidth() - borderSize.getRight(), + proportionOfWidth (0.9f), + getWidth() - jmin (10, proportionOfWidth (0.33f)))) newZone |= zoneR; - if (e.y < jmax (borderSize.getTop(), proportionOfHeight (0.1f))) + if (e.y < jmax (borderSize.getTop(), + proportionOfHeight (0.1f), + jmin (10, proportionOfHeight (0.33f)))) newZone |= zoneT; - else if (e.y >= jmin (getHeight() - borderSize.getBottom(), proportionOfHeight (0.9f))) + else if (e.y >= jmin (getHeight() - borderSize.getBottom(), + proportionOfHeight (0.9f), + getHeight() - jmin (10, proportionOfHeight (0.33f)))) newZone |= zoneB; } @@ -62399,6 +62422,12 @@ void LookAndFeel::drawResizableFrame (Graphics&, int /*w*/, int /*h*/, { } +void LookAndFeel::fillResizableWindowBackground (Graphics& g, int /*w*/, int /*h*/, + const BorderSize& /*border*/, ResizableWindow& window) +{ + g.fillAll (window.getBackgroundColour()); +} + void LookAndFeel::drawResizableWindowBorder (Graphics& g, int w, int h, const BorderSize& border, ResizableWindow&) { @@ -74212,7 +74241,8 @@ void ResizableWindow::setBoundsConstrained (int x, int y, int w, int h) void ResizableWindow::paint (Graphics& g) { - g.fillAll (getBackgroundColour()); + getLookAndFeel().fillResizableWindowBackground (g, getWidth(), getHeight(), + getBorderThickness(), *this); if (! isFullScreen()) { @@ -74398,7 +74428,14 @@ bool ResizableWindow::restoreWindowStateFromString (const String& s) const Rectangle screen (Desktop::getInstance().getMonitorAreaContaining (r.getX(), r.getY())); - r = r.getIntersection (screen); + if (! screen.contains (r)) + { + r.setSize (jmin (r.getWidth(), screen.getWidth()), + jmin (r.getHeight(), screen.getHeight())); + + r.setPosition (jlimit (screen.getX(), screen.getRight() - r.getWidth(), r.getX()), + jlimit (screen.getY(), screen.getBottom() - r.getHeight(), r.getY())); + } lastNonFullScreenPos = r; @@ -215018,6 +215055,10 @@ BEGIN_JUCE_NAMESPACE using namespace jpeglibNamespace; +#if ! JUCE_WIN32 + using jpeglibNamespace::boolean; +#endif + struct JPEGDecodingFailure {}; static void fatalErrorHandler (j_common_ptr) @@ -242133,22 +242174,30 @@ const String juce_getVolumeLabel (const String& filenameOnVolume, return String (dest); } -int64 File::getBytesFreeOnVolume() const throw() +static int64 getDiskSpaceInfo (String fn, const bool total) throw() { - String fn (getFullPathName()); if (fn[1] == T(':')) fn = fn.substring (0, 2) + T("\\"); - ULARGE_INTEGER spc; - ULARGE_INTEGER tot; - ULARGE_INTEGER totFree; + ULARGE_INTEGER spc, tot, totFree; if (GetDiskFreeSpaceEx (fn, &spc, &tot, &totFree)) - return (int64)(spc.QuadPart); + return (int64) (total ? tot.QuadPart + : spc.QuadPart); return 0; } +int64 File::getBytesFreeOnVolume() const throw() +{ + return getDiskSpaceInfo (getFullPathName(), false); +} + +int64 File::getVolumeTotalSize() const throw() +{ + return getDiskSpaceInfo (getFullPathName(), true); +} + static unsigned int getWindowsDriveType (const String& fileName) throw() { TCHAR n[4]; @@ -242864,22 +242913,25 @@ int juce_seekInInternetFile (void* handle, int newPosition) int64 juce_getInternetFileContentLength (void* handle) { - DWORD result = -1; const ConnectionAndRequestStruct* const crs = (const ConnectionAndRequestStruct*) handle; if (crs != 0) { DWORD index = 0; + DWORD result = 0; DWORD size = sizeof (result); - HttpQueryInfo (crs->request, - HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, - &result, - &size, - &index); + if (HttpQueryInfo (crs->request, + HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, + &result, + &size, + &index)) + { + return (int64) result; + } } - return (int) result; + return -1; } void juce_closeInternetFile (void* handle) @@ -246577,7 +246629,7 @@ static int CALLBACK wfontEnum1 (ENUMLOGFONTEXW* lpelfe, zerostruct (lf); lf.lfWeight = FW_DONTCARE; - lf.lfOutPrecision = OUT_TT_ONLY_PRECIS; + lf.lfOutPrecision = OUT_OUTLINE_PRECIS; lf.lfQuality = DEFAULT_QUALITY; lf.lfCharSet = DEFAULT_CHARSET; lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; @@ -246606,7 +246658,7 @@ const StringArray Font::findAllTypefaceNames() throw() zerostruct (lf); lf.lfWeight = FW_DONTCARE; - lf.lfOutPrecision = OUT_TT_ONLY_PRECIS; + lf.lfOutPrecision = OUT_OUTLINE_PRECIS; lf.lfQuality = DEFAULT_QUALITY; lf.lfCharSet = DEFAULT_CHARSET; lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; @@ -257044,14 +257096,20 @@ static bool doStatFS (const File* file, struct statfs& result) throw() int64 File::getBytesFreeOnVolume() const throw() { - int64 free_space = 0; + struct statfs buf; + if (doStatFS (this, buf)) + return (int64) buf.f_bsize * (int64) buf.f_bavail; // Note: this returns space available to non-super user + + return 0; +} +int64 File::getVolumeTotalSize() const throw() +{ struct statfs buf; if (doStatFS (this, buf)) - // Note: this returns space available to non-super user - free_space = (int64) buf.f_bsize * (int64) buf.f_bavail; + return (int64) buf.f_bsize * (int64) buf.f_blocks; - return free_space; + return 0; } const String juce_getVolumeLabel (const String& filenameOnVolume, @@ -258597,7 +258655,7 @@ Thread::ThreadID Thread::getCurrentThreadId() throw() // priority 1 to 10 where 5=normal, 1=low. If the handle is 0, sets the // priority of the current thread -void juce_setThreadPriority (void* handle, int priority) throw() +bool juce_setThreadPriority (void* handle, int priority) throw() { struct sched_param param; int policy, maxp, minp, pri; @@ -258622,8 +258680,10 @@ void juce_setThreadPriority (void* handle, int priority) throw() param.sched_priority = jlimit (1, 127, 1 + (priority * 126) / 11); - pthread_setschedparam ((pthread_t) handle, policy, ¶m); + return pthread_setschedparam ((pthread_t) handle, policy, ¶m) == 0; } + + return false; } void Thread::setCurrentThreadAffinityMask (const uint32 affinityMask) throw() @@ -266469,6 +266529,7 @@ using namespace JUCE_NAMESPACE; @interface JuceURLConnection : NSObject { +@public NSURLRequest* request; NSURLConnection* connection; NSMutableData* data; @@ -266808,7 +266869,7 @@ Thread::ThreadID Thread::getCurrentThreadId() throw() return (ThreadID) pthread_self(); } -void juce_setThreadPriority (void* handle, int priority) throw() +bool juce_setThreadPriority (void* handle, int priority) throw() { if (handle == 0) handle = (void*) pthread_self(); @@ -266817,7 +266878,7 @@ void juce_setThreadPriority (void* handle, int priority) throw() int policy; pthread_getschedparam ((pthread_t) handle, &policy, ¶m); param.sched_priority = jlimit (1, 127, 1 + (priority * 126) / 11); - pthread_setschedparam ((pthread_t) handle, policy, ¶m); + return pthread_setschedparam ((pthread_t) handle, policy, ¶m) == 0; } void Thread::yield() throw() @@ -267159,14 +267220,20 @@ static bool doStatFS (const File* file, struct statfs& result) throw() int64 File::getBytesFreeOnVolume() const throw() { - int64 free_space = 0; + struct statfs buf; + if (doStatFS (this, buf)) + return (int64) buf.f_bsize * (int64) buf.f_bavail; // Note: this returns space available to non-super user + + return 0; +} +int64 File::getVolumeTotalSize() const throw() +{ struct statfs buf; if (doStatFS (this, buf)) - // Note: this returns space available to non-super user - free_space = (int64) buf.f_bsize * (int64) buf.f_bavail; + return (int64) buf.f_bsize * (int64) buf.f_blocks; - return free_space; + return 0; } const String juce_getVolumeLabel (const String& filenameOnVolume, @@ -272043,6 +272110,9 @@ bool Typeface::findAndAddSystemGlyph (juce_wchar character) throw() // This method is only safe to be called from the normal UI thread.. jassert (MessageManager::getInstance()->isThisTheMessageThread()); + if (character == 0) + return false; + FontHelper* const helper = FontHelperCache::getInstance() ->getFont (getName(), isBold(), isItalic()); diff --git a/juce_amalgamated.h b/juce_amalgamated.h index 62feb81486..74207f0d23 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -6720,9 +6720,17 @@ public: /** Returns the number of bytes free on the drive that this file lives on. @returns the number of bytes free, or 0 if there's a problem finding this out + @see getVolumeTotalSize */ int64 getBytesFreeOnVolume() const throw(); + /** Returns the total size of the drive that contains this file. + + @returns the total number of bytes that the volume can hold + @see getBytesFreeOnVolume + */ + int64 getVolumeTotalSize() const throw(); + /** Returns true if this file is on a CD or DVD drive. */ bool isOnCDRomDrive() const throw(); @@ -12436,9 +12444,13 @@ public: make a connection, but will save the destination you've provided. After this, you can call read() or write(). + If enableBroadcasting is true, the socket will be allowed to send broadcast messages + (may require extra privileges on linux) + To wait for other sockets to connect to this one, call waitForNextConnection(). */ - DatagramSocket (const int localPortNumber); + DatagramSocket (const int localPortNumber, + const bool enableBroadcasting = false); /** Destructor. */ ~DatagramSocket(); @@ -12526,7 +12538,7 @@ public: private: String hostName; int volatile portNumber, handle; - bool connected; + bool connected, allowBroadcast; void* serverAddress; DatagramSocket (const String& hostname, const int portNumber, const int handle, const int localPortNumber); @@ -14427,19 +14439,21 @@ public: bool waitForThreadToExit (const int timeOutMilliseconds) const throw(); /** Changes the thread's priority. + May return false if for some reason the priority can't be changed. @param priority the new priority, in the range 0 (lowest) to 10 (highest). A priority of 5 is normal. */ - void setPriority (const int priority) throw(); + bool setPriority (const int priority) throw(); /** Changes the priority of the caller thread. Similar to setPriority(), but this static method acts on the caller thread. + May return false if for some reason the priority can't be changed. @see setPriority */ - static void setCurrentThreadPriority (const int priority) throw(); + static bool setCurrentThreadPriority (const int priority) throw(); /** Sets the affinity mask for the thread. @@ -15101,8 +15115,9 @@ public: /** Changes the priority of all the threads. This will call Thread::setPriority() for each thread in the pool. + May return false if for some reason the priority can't be changed. */ - void setThreadPriorities (const int newPriority); + bool setThreadPriorities (const int newPriority); juce_UseDebuggingNewOperator @@ -54048,6 +54063,10 @@ public: int w, int h, const BorderSize& borders); + virtual void fillResizableWindowBackground (Graphics& g, int w, int h, + const BorderSize& border, + ResizableWindow& window); + virtual void drawResizableWindowBorder (Graphics& g, int w, int h, const BorderSize& border, diff --git a/src/juce_appframework/audio/audio_file_formats/juce_AudioFormat.cpp b/src/juce_appframework/audio/audio_file_formats/juce_AudioFormat.cpp index ed29cd91bb..f2407f3c43 100644 --- a/src/juce_appframework/audio/audio_file_formats/juce_AudioFormat.cpp +++ b/src/juce_appframework/audio/audio_file_formats/juce_AudioFormat.cpp @@ -85,7 +85,7 @@ bool AudioFormatReader::read (int** destSamples, startSampleInSource, numSamplesToRead)) return false; - if (numDestChannels > numChannels) + if (numDestChannels > (int) numChannels) { if (fillLeftoverChannelsWithCopies) { diff --git a/src/juce_appframework/gui/components/layout/juce_ResizableBorderComponent.cpp b/src/juce_appframework/gui/components/layout/juce_ResizableBorderComponent.cpp index e8e388d2dc..1a5054b120 100644 --- a/src/juce_appframework/gui/components/layout/juce_ResizableBorderComponent.cpp +++ b/src/juce_appframework/gui/components/layout/juce_ResizableBorderComponent.cpp @@ -173,14 +173,22 @@ void ResizableBorderComponent::updateMouseZone (const MouseEvent& e) throw() if (ResizableBorderComponent::hitTest (e.x, e.y)) { - if (e.x < jmax (borderSize.getLeft(), proportionOfWidth (0.1f))) + if (e.x < jmax (borderSize.getLeft(), + proportionOfWidth (0.1f), + jmin (10, proportionOfWidth (0.33f)))) newZone |= zoneL; - else if (e.x >= jmin (getWidth() - borderSize.getRight(), proportionOfWidth (0.9f))) + else if (e.x >= jmin (getWidth() - borderSize.getRight(), + proportionOfWidth (0.9f), + getWidth() - jmin (10, proportionOfWidth (0.33f)))) newZone |= zoneR; - if (e.y < jmax (borderSize.getTop(), proportionOfHeight (0.1f))) + if (e.y < jmax (borderSize.getTop(), + proportionOfHeight (0.1f), + jmin (10, proportionOfHeight (0.33f)))) newZone |= zoneT; - else if (e.y >= jmin (getHeight() - borderSize.getBottom(), proportionOfHeight (0.9f))) + else if (e.y >= jmin (getHeight() - borderSize.getBottom(), + proportionOfHeight (0.9f), + getHeight() - jmin (10, proportionOfHeight (0.33f)))) newZone |= zoneB; } diff --git a/src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.cpp b/src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.cpp index 3a5265d95b..76cbe9fef3 100644 --- a/src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.cpp +++ b/src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.cpp @@ -1744,6 +1744,12 @@ void LookAndFeel::drawResizableFrame (Graphics&, int /*w*/, int /*h*/, } //============================================================================== +void LookAndFeel::fillResizableWindowBackground (Graphics& g, int /*w*/, int /*h*/, + const BorderSize& /*border*/, ResizableWindow& window) +{ + g.fillAll (window.getBackgroundColour()); +} + void LookAndFeel::drawResizableWindowBorder (Graphics& g, int w, int h, const BorderSize& border, ResizableWindow&) { diff --git a/src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.h b/src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.h index 3802aac9d6..48aeca3a3e 100644 --- a/src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.h +++ b/src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.h @@ -452,6 +452,10 @@ public: const BorderSize& borders); //============================================================================== + virtual void fillResizableWindowBackground (Graphics& g, int w, int h, + const BorderSize& border, + ResizableWindow& window); + virtual void drawResizableWindowBorder (Graphics& g, int w, int h, const BorderSize& border, diff --git a/src/juce_appframework/gui/components/windows/juce_ResizableWindow.cpp b/src/juce_appframework/gui/components/windows/juce_ResizableWindow.cpp index e06b3a6dd4..3d1a764c6f 100644 --- a/src/juce_appframework/gui/components/windows/juce_ResizableWindow.cpp +++ b/src/juce_appframework/gui/components/windows/juce_ResizableWindow.cpp @@ -313,7 +313,8 @@ void ResizableWindow::setBoundsConstrained (int x, int y, int w, int h) //============================================================================== void ResizableWindow::paint (Graphics& g) { - g.fillAll (getBackgroundColour()); + getLookAndFeel().fillResizableWindowBackground (g, getWidth(), getHeight(), + getBorderThickness(), *this); if (! isFullScreen()) { @@ -501,7 +502,14 @@ bool ResizableWindow::restoreWindowStateFromString (const String& s) const Rectangle screen (Desktop::getInstance().getMonitorAreaContaining (r.getX(), r.getY())); - r = r.getIntersection (screen); + if (! screen.contains (r)) + { + r.setSize (jmin (r.getWidth(), screen.getWidth()), + jmin (r.getHeight(), screen.getHeight())); + + r.setPosition (jlimit (screen.getX(), screen.getRight() - r.getWidth(), r.getX()), + jlimit (screen.getY(), screen.getBottom() - r.getHeight(), r.getY())); + } lastNonFullScreenPos = r; diff --git a/src/juce_appframework/gui/graphics/imaging/image_file_formats/juce_JPEGLoader.cpp b/src/juce_appframework/gui/graphics/imaging/image_file_formats/juce_JPEGLoader.cpp index 32b12dffeb..e397a9f187 100644 --- a/src/juce_appframework/gui/graphics/imaging/image_file_formats/juce_JPEGLoader.cpp +++ b/src/juce_appframework/gui/graphics/imaging/image_file_formats/juce_JPEGLoader.cpp @@ -133,6 +133,10 @@ BEGIN_JUCE_NAMESPACE using namespace jpeglibNamespace; +#if ! JUCE_WIN32 + using jpeglibNamespace::boolean; +#endif + //============================================================================== struct JPEGDecodingFailure {}; diff --git a/src/juce_core/io/files/juce_File.h b/src/juce_core/io/files/juce_File.h index b80e7878f1..a6c3a7552e 100644 --- a/src/juce_core/io/files/juce_File.h +++ b/src/juce_core/io/files/juce_File.h @@ -699,9 +699,17 @@ public: /** Returns the number of bytes free on the drive that this file lives on. @returns the number of bytes free, or 0 if there's a problem finding this out + @see getVolumeTotalSize */ int64 getBytesFreeOnVolume() const throw(); + /** Returns the total size of the drive that contains this file. + + @returns the total number of bytes that the volume can hold + @see getBytesFreeOnVolume + */ + int64 getVolumeTotalSize() const throw(); + /** Returns true if this file is on a CD or DVD drive. */ bool isOnCDRomDrive() const throw(); diff --git a/src/juce_core/io/network/juce_Socket.cpp b/src/juce_core/io/network/juce_Socket.cpp index 58c82081a4..20e628c2f2 100644 --- a/src/juce_core/io/network/juce_Socket.cpp +++ b/src/juce_core/io/network/juce_Socket.cpp @@ -88,7 +88,7 @@ static void initWin32Sockets() #endif //============================================================================== -static bool resetSocketOptions (const int handle, const bool isDatagram) throw() +static bool resetSocketOptions (const int handle, const bool isDatagram, const bool allowBroadcast) throw() { const int sndBufSize = 65536; const int rcvBufSize = 65536; @@ -97,7 +97,7 @@ static bool resetSocketOptions (const int handle, const bool isDatagram) throw() return handle > 0 && setsockopt (handle, SOL_SOCKET, SO_RCVBUF, (const char*) &rcvBufSize, sizeof (rcvBufSize)) == 0 && setsockopt (handle, SOL_SOCKET, SO_SNDBUF, (const char*) &sndBufSize, sizeof (sndBufSize)) == 0 - && (isDatagram ? (setsockopt (handle, SOL_SOCKET, SO_BROADCAST, (const char*) &one, sizeof (one)) == 0) + && (isDatagram ? ((! allowBroadcast) || setsockopt (handle, SOL_SOCKET, SO_BROADCAST, (const char*) &one, sizeof (one)) == 0) : (setsockopt (handle, IPPROTO_TCP, TCP_NODELAY, (const char*) &one, sizeof (one)) == 0)); } @@ -299,7 +299,7 @@ static bool connectSocket (int volatile& handle, } setSocketBlockingState (handle, true); - resetSocketOptions (handle, false); + resetSocketOptions (handle, false, false); return true; } @@ -329,7 +329,7 @@ StreamingSocket::StreamingSocket (const String& hostName_, initWin32Sockets(); #endif - resetSocketOptions (handle_, false); + resetSocketOptions (handle_, false, false); } StreamingSocket::~StreamingSocket() @@ -397,7 +397,7 @@ bool StreamingSocket::connect (const String& remoteHostName, connected = connectSocket (handle, false, 0, remoteHostName, remotePortNumber, timeOutMillisecs); - if (! (connected && resetSocketOptions (handle, false))) + if (! (connected && resetSocketOptions (handle, false, false))) { close(); return false; @@ -500,10 +500,11 @@ bool StreamingSocket::isLocal() const throw() //============================================================================== //============================================================================== -DatagramSocket::DatagramSocket (const int localPortNumber) +DatagramSocket::DatagramSocket (const int localPortNumber, const bool allowBroadcast_) : portNumber (0), handle (-1), connected (true), + allowBroadcast (allowBroadcast_), serverAddress (0) { #if JUCE_WIN32 @@ -520,13 +521,14 @@ DatagramSocket::DatagramSocket (const String& hostName_, const int portNumber_, portNumber (portNumber_), handle (handle_), connected (true), + allowBroadcast (false), serverAddress (0) { #if JUCE_WIN32 initWin32Sockets(); #endif - resetSocketOptions (handle_, true); + resetSocketOptions (handle_, true, allowBroadcast); bindToPort (localPortNumber); } @@ -572,7 +574,7 @@ bool DatagramSocket::connect (const String& remoteHostName, remoteHostName, remotePortNumber, timeOutMillisecs); - if (! (connected && resetSocketOptions (handle, true))) + if (! (connected && resetSocketOptions (handle, true, allowBroadcast))) { close(); return false; diff --git a/src/juce_core/io/network/juce_Socket.h b/src/juce_core/io/network/juce_Socket.h index 07087a48d6..dfe2c1d811 100644 --- a/src/juce_core/io/network/juce_Socket.h +++ b/src/juce_core/io/network/juce_Socket.h @@ -195,10 +195,14 @@ public: To use the socket for sending, call the connect() method. This will not immediately make a connection, but will save the destination you've provided. After this, you can call read() or write(). + + If enableBroadcasting is true, the socket will be allowed to send broadcast messages + (may require extra privileges on linux) To wait for other sockets to connect to this one, call waitForNextConnection(). */ - DatagramSocket (const int localPortNumber); + DatagramSocket (const int localPortNumber, + const bool enableBroadcasting = false); /** Destructor. */ ~DatagramSocket(); @@ -291,7 +295,7 @@ public: private: String hostName; int volatile portNumber, handle; - bool connected; + bool connected, allowBroadcast; void* serverAddress; DatagramSocket (const String& hostname, const int portNumber, const int handle, const int localPortNumber); diff --git a/src/juce_core/threads/juce_Thread.cpp b/src/juce_core/threads/juce_Thread.cpp index d11f7e72a4..0f1f0a3fe1 100644 --- a/src/juce_core/threads/juce_Thread.cpp +++ b/src/juce_core/threads/juce_Thread.cpp @@ -42,7 +42,7 @@ BEGIN_JUCE_NAMESPACE // these functions are implemented in the platform-specific code. void* juce_createThread (void* userData) throw(); void juce_killThread (void* handle) throw(); -void juce_setThreadPriority (void* handle, int priority) throw(); +bool juce_setThreadPriority (void* handle, int priority) throw(); void juce_setCurrentThreadName (const String& name) throw(); #if JUCE_WIN32 void juce_CloseThreadHandle (void* handle) throw(); @@ -210,17 +210,21 @@ void Thread::stopThread (const int timeOutMilliseconds) throw() } //============================================================================== -void Thread::setPriority (const int priority) throw() +bool Thread::setPriority (const int priority) throw() { const ScopedLock sl (startStopLock); - threadPriority_ = priority; - juce_setThreadPriority (threadHandle_, priority); + const bool worked = juce_setThreadPriority (threadHandle_, priority); + + if (worked) + threadPriority_ = priority; + + return worked; } -void Thread::setCurrentThreadPriority (const int priority) throw() +bool Thread::setCurrentThreadPriority (const int priority) throw() { - juce_setThreadPriority (0, priority); + return juce_setThreadPriority (0, priority); } void Thread::setAffinityMask (const uint32 affinityMask) throw() diff --git a/src/juce_core/threads/juce_Thread.h b/src/juce_core/threads/juce_Thread.h index 8702212a18..21f702f83d 100644 --- a/src/juce_core/threads/juce_Thread.h +++ b/src/juce_core/threads/juce_Thread.h @@ -158,19 +158,21 @@ public: //============================================================================== /** Changes the thread's priority. + May return false if for some reason the priority can't be changed. @param priority the new priority, in the range 0 (lowest) to 10 (highest). A priority of 5 is normal. */ - void setPriority (const int priority) throw(); + bool setPriority (const int priority) throw(); /** Changes the priority of the caller thread. Similar to setPriority(), but this static method acts on the caller thread. + May return false if for some reason the priority can't be changed. @see setPriority */ - static void setCurrentThreadPriority (const int priority) throw(); + static bool setCurrentThreadPriority (const int priority) throw(); //============================================================================== /** Sets the affinity mask for the thread. diff --git a/src/juce_core/threads/juce_ThreadPool.cpp b/src/juce_core/threads/juce_ThreadPool.cpp index c458c8cbd0..6447c7893e 100644 --- a/src/juce_core/threads/juce_ThreadPool.cpp +++ b/src/juce_core/threads/juce_ThreadPool.cpp @@ -313,15 +313,20 @@ const StringArray ThreadPool::getNamesOfAllJobs (const bool onlyReturnActiveJobs return s; } -void ThreadPool::setThreadPriorities (const int newPriority) +bool ThreadPool::setThreadPriorities (const int newPriority) { + bool ok = true; + if (priority != newPriority) { priority = newPriority; for (int i = numThreads; --i >= 0;) - threads[i]->setPriority (newPriority); + if (! threads[i]->setPriority (newPriority)) + ok = false; } + + return ok; } bool ThreadPool::runNextJob() diff --git a/src/juce_core/threads/juce_ThreadPool.h b/src/juce_core/threads/juce_ThreadPool.h index 222954c244..1364bf3b11 100644 --- a/src/juce_core/threads/juce_ThreadPool.h +++ b/src/juce_core/threads/juce_ThreadPool.h @@ -265,8 +265,9 @@ public: /** Changes the priority of all the threads. This will call Thread::setPriority() for each thread in the pool. + May return false if for some reason the priority can't be changed. */ - void setThreadPriorities (const int newPriority); + bool setThreadPriorities (const int newPriority); //==============================================================================