| @@ -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() | |||
| @@ -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()); | |||
| @@ -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 | |||
| @@ -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() | |||
| @@ -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, | |||
| @@ -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() | |||
| { | |||
| @@ -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; | |||
| @@ -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; | |||
| @@ -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) | |||
| @@ -25,6 +25,7 @@ package.includepaths = { | |||
| "../../../../../", | |||
| "/usr/include/vst/source/common", | |||
| "/usr/include/vst", | |||
| "/usr/include/freetype2", | |||
| "../../src" | |||
| } | |||
| @@ -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); | |||
| } | |||
| @@ -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); | |||
| @@ -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()); | |||
| @@ -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, | |||
| @@ -85,7 +85,7 @@ bool AudioFormatReader::read (int** destSamples, | |||
| startSampleInSource, numSamplesToRead)) | |||
| return false; | |||
| if (numDestChannels > numChannels) | |||
| if (numDestChannels > (int) numChannels) | |||
| { | |||
| if (fillLeftoverChannelsWithCopies) | |||
| { | |||
| @@ -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; | |||
| } | |||
| @@ -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&) | |||
| { | |||
| @@ -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, | |||
| @@ -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; | |||
| @@ -133,6 +133,10 @@ BEGIN_JUCE_NAMESPACE | |||
| using namespace jpeglibNamespace; | |||
| #if ! JUCE_WIN32 | |||
| using jpeglibNamespace::boolean; | |||
| #endif | |||
| //============================================================================== | |||
| struct JPEGDecodingFailure {}; | |||
| @@ -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(); | |||
| @@ -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; | |||
| @@ -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); | |||
| @@ -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() | |||
| @@ -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. | |||
| @@ -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() | |||
| @@ -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); | |||
| //============================================================================== | |||