| @@ -378,7 +378,7 @@ public: | |||||
| destShape.startNewSubPath (x2, y2); | destShape.startNewSubPath (x2, y2); | ||||
| } | } | ||||
| else | |||||
| else | |||||
| { | { | ||||
| destShape.startNewSubPath (x, y); | destShape.startNewSubPath (x, y); | ||||
| } | } | ||||
| @@ -1,406 +1,406 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| 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 __JUCE_MAC_HTTPSTREAM_JUCEHEADER__ | |||||
| #define __JUCE_MAC_HTTPSTREAM_JUCEHEADER__ | |||||
| // (This file gets included by the mac + linux networking code) | |||||
| //============================================================================== | |||||
| /** A HTTP input stream that uses sockets. | |||||
| */ | |||||
| class JUCE_HTTPSocketStream | |||||
| { | |||||
| public: | |||||
| //============================================================================== | |||||
| JUCE_HTTPSocketStream() | |||||
| : statusCode (0), | |||||
| readPosition (0), | |||||
| socketHandle (-1), | |||||
| levelsOfRedirection (0), | |||||
| timeoutSeconds (15) | |||||
| { | |||||
| } | |||||
| ~JUCE_HTTPSocketStream() | |||||
| { | |||||
| closeSocket(); | |||||
| } | |||||
| //============================================================================== | |||||
| bool open (const String& url, | |||||
| const String& headers, | |||||
| const MemoryBlock& postData, | |||||
| const bool isPost, | |||||
| URL::OpenStreamProgressCallback* callback, | |||||
| void* callbackContext) | |||||
| { | |||||
| closeSocket(); | |||||
| String hostName, hostPath; | |||||
| int hostPort; | |||||
| if (! decomposeURL (url, hostName, hostPath, hostPort)) | |||||
| return false; | |||||
| struct hostent* const host | |||||
| = gethostbyname ((const char*) hostName.toUTF8()); | |||||
| if (host == 0) | |||||
| return false; | |||||
| struct sockaddr_in address; | |||||
| zerostruct (address); | |||||
| memcpy ((void*) &address.sin_addr, (const void*) host->h_addr, host->h_length); | |||||
| address.sin_family = host->h_addrtype; | |||||
| address.sin_port = htons (hostPort); | |||||
| socketHandle = socket (host->h_addrtype, SOCK_STREAM, 0); | |||||
| if (socketHandle == -1) | |||||
| return false; | |||||
| int receiveBufferSize = 16384; | |||||
| setsockopt (socketHandle, SOL_SOCKET, SO_RCVBUF, (char*) &receiveBufferSize, sizeof (receiveBufferSize)); | |||||
| setsockopt (socketHandle, SOL_SOCKET, SO_KEEPALIVE, 0, 0); | |||||
| #if JUCE_MAC | |||||
| setsockopt (socketHandle, SOL_SOCKET, SO_NOSIGPIPE, 0, 0); | |||||
| #endif | |||||
| if (connect (socketHandle, (struct sockaddr*) &address, sizeof (address)) == -1) | |||||
| { | |||||
| closeSocket(); | |||||
| return false; | |||||
| } | |||||
| String proxyURL (getenv ("http_proxy")); | |||||
| if (! proxyURL.startsWithIgnoreCase (T("http://"))) | |||||
| proxyURL = String::empty; | |||||
| const MemoryBlock requestHeader (createRequestHeader (hostName, hostPath, | |||||
| proxyURL, url, | |||||
| hostPort, | |||||
| headers, postData, | |||||
| isPost)); | |||||
| int totalHeaderSent = 0; | |||||
| while (totalHeaderSent < requestHeader.getSize()) | |||||
| { | |||||
| const int numToSend = jmin (1024, requestHeader.getSize() - totalHeaderSent); | |||||
| if (send (socketHandle, | |||||
| ((const char*) requestHeader.getData()) + totalHeaderSent, | |||||
| numToSend, 0) | |||||
| != numToSend) | |||||
| { | |||||
| closeSocket(); | |||||
| return false; | |||||
| } | |||||
| totalHeaderSent += numToSend; | |||||
| if (callback != 0 && ! callback (callbackContext, totalHeaderSent, requestHeader.getSize())) | |||||
| { | |||||
| closeSocket(); | |||||
| return false; | |||||
| } | |||||
| } | |||||
| const String responseHeader (readResponse()); | |||||
| if (responseHeader.isNotEmpty()) | |||||
| { | |||||
| //DBG (responseHeader); | |||||
| StringArray lines; | |||||
| lines.addLines (responseHeader); | |||||
| statusCode = responseHeader.fromFirstOccurrenceOf (T(" "), false, false) | |||||
| .substring (0, 3).getIntValue(); | |||||
| //int contentLength = findHeaderItem (lines, T("Content-Length:")).getIntValue(); | |||||
| //bool isChunked = findHeaderItem (lines, T("Transfer-Encoding:")).equalsIgnoreCase ("chunked"); | |||||
| String location (findHeaderItem (lines, T("Location:"))); | |||||
| if (statusCode >= 300 && statusCode < 400 | |||||
| && location.isNotEmpty()) | |||||
| { | |||||
| if (! location.startsWithIgnoreCase (T("http://"))) | |||||
| location = T("http://") + location; | |||||
| if (levelsOfRedirection++ < 3) | |||||
| return open (location, headers, postData, isPost, callback, callbackContext); | |||||
| } | |||||
| else | |||||
| { | |||||
| levelsOfRedirection = 0; | |||||
| return true; | |||||
| } | |||||
| } | |||||
| closeSocket(); | |||||
| return false; | |||||
| } | |||||
| //============================================================================== | |||||
| int read (void* buffer, int bytesToRead) | |||||
| { | |||||
| fd_set readbits; | |||||
| FD_ZERO (&readbits); | |||||
| FD_SET (socketHandle, &readbits); | |||||
| struct timeval tv; | |||||
| tv.tv_sec = timeoutSeconds; | |||||
| tv.tv_usec = 0; | |||||
| if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0) | |||||
| return 0; // (timeout) | |||||
| const int bytesRead = jmax (0, recv (socketHandle, buffer, bytesToRead, MSG_WAITALL)); | |||||
| readPosition += bytesRead; | |||||
| return bytesRead; | |||||
| } | |||||
| //============================================================================== | |||||
| int statusCode, readPosition; | |||||
| //============================================================================== | |||||
| juce_UseDebuggingNewOperator | |||||
| private: | |||||
| int socketHandle, levelsOfRedirection; | |||||
| const int timeoutSeconds; | |||||
| //============================================================================== | |||||
| void closeSocket() | |||||
| { | |||||
| if (socketHandle >= 0) | |||||
| close (socketHandle); | |||||
| socketHandle = -1; | |||||
| } | |||||
| const MemoryBlock createRequestHeader (const String& hostName, | |||||
| const String& hostPath, | |||||
| const String& proxyURL, | |||||
| const String& originalURL, | |||||
| const int hostPort, | |||||
| const String& headers, | |||||
| const MemoryBlock& postData, | |||||
| const bool isPost) | |||||
| { | |||||
| String header (isPost ? "POST " : "GET "); | |||||
| if (proxyURL.isEmpty()) | |||||
| { | |||||
| header << hostPath << " HTTP/1.0\r\nHost: " | |||||
| << hostName << ':' << hostPort; | |||||
| } | |||||
| else | |||||
| { | |||||
| String proxyName, proxyPath; | |||||
| int proxyPort; | |||||
| if (! decomposeURL (proxyURL, proxyName, proxyPath, proxyPort)) | |||||
| return MemoryBlock(); | |||||
| header << originalURL << " HTTP/1.0\r\nHost: " | |||||
| << proxyName << ':' << proxyPort; | |||||
| /* xxx needs finishing | |||||
| const char* proxyAuth = getenv ("http_proxy_auth"); | |||||
| if (proxyAuth != 0) | |||||
| header << T("\r\nProxy-Authorization: ") << Base64Encode (proxyAuth); | |||||
| */ | |||||
| } | |||||
| header << "\r\nUser-Agent: JUCE/" | |||||
| << JUCE_MAJOR_VERSION << '.' << JUCE_MINOR_VERSION | |||||
| << "\r\nConnection: Close\r\nContent-Length: " | |||||
| << postData.getSize() << "\r\n" | |||||
| << headers << "\r\n"; | |||||
| MemoryBlock mb; | |||||
| mb.append (header.toUTF8(), (int) strlen (header.toUTF8())); | |||||
| mb.append (postData.getData(), postData.getSize()); | |||||
| return mb; | |||||
| } | |||||
| const String readResponse() | |||||
| { | |||||
| int bytesRead = 0, numConsecutiveLFs = 0; | |||||
| MemoryBlock buffer (1024, true); | |||||
| while (numConsecutiveLFs < 2 && bytesRead < 32768) | |||||
| { | |||||
| fd_set readbits; | |||||
| FD_ZERO (&readbits); | |||||
| FD_SET (socketHandle, &readbits); | |||||
| struct timeval tv; | |||||
| tv.tv_sec = timeoutSeconds; | |||||
| tv.tv_usec = 0; | |||||
| if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0) | |||||
| return String::empty; // (timeout) | |||||
| buffer.ensureSize (bytesRead + 8, true); | |||||
| char* const dest = (char*) buffer.getData() + bytesRead; | |||||
| if (recv (socketHandle, dest, 1, 0) == -1) | |||||
| return String::empty; | |||||
| const char lastByte = *dest; | |||||
| ++bytesRead; | |||||
| if (lastByte == '\n') | |||||
| ++numConsecutiveLFs; | |||||
| else if (lastByte != '\r') | |||||
| numConsecutiveLFs = 0; | |||||
| } | |||||
| const String header (String::fromUTF8 ((const uint8*) buffer.getData())); | |||||
| if (header.startsWithIgnoreCase (T("HTTP/"))) | |||||
| return header.trimEnd(); | |||||
| return String::empty; | |||||
| } | |||||
| //============================================================================== | |||||
| static bool decomposeURL (const String& url, | |||||
| String& host, String& path, int& port) | |||||
| { | |||||
| if (! url.startsWithIgnoreCase (T("http://"))) | |||||
| return false; | |||||
| const int nextSlash = url.indexOfChar (7, '/'); | |||||
| int nextColon = url.indexOfChar (7, ':'); | |||||
| if (nextColon > nextSlash && nextSlash > 0) | |||||
| nextColon = -1; | |||||
| if (nextColon >= 0) | |||||
| { | |||||
| host = url.substring (7, nextColon); | |||||
| if (nextSlash >= 0) | |||||
| port = url.substring (nextColon + 1, nextSlash).getIntValue(); | |||||
| else | |||||
| port = url.substring (nextColon + 1).getIntValue(); | |||||
| } | |||||
| else | |||||
| { | |||||
| port = 80; | |||||
| if (nextSlash >= 0) | |||||
| host = url.substring (7, nextSlash); | |||||
| else | |||||
| host = url.substring (7); | |||||
| } | |||||
| if (nextSlash >= 0) | |||||
| path = url.substring (nextSlash); | |||||
| else | |||||
| path = T("/"); | |||||
| return true; | |||||
| } | |||||
| //============================================================================== | |||||
| static const String findHeaderItem (const StringArray& lines, const String& itemName) | |||||
| { | |||||
| for (int i = 0; i < lines.size(); ++i) | |||||
| if (lines[i].startsWithIgnoreCase (itemName)) | |||||
| return lines[i].substring (itemName.length()).trim(); | |||||
| return String::empty; | |||||
| } | |||||
| }; | |||||
| //============================================================================== | |||||
| 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) | |||||
| { | |||||
| JUCE_HTTPSocketStream* const s = new JUCE_HTTPSocketStream(); | |||||
| if (s->open (url, headers, postData, isPost, | |||||
| callback, callbackContext)) | |||||
| return s; | |||||
| delete s; | |||||
| return 0; | |||||
| } | |||||
| void juce_closeInternetFile (void* handle) | |||||
| { | |||||
| JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle; | |||||
| if (s != 0) | |||||
| delete s; | |||||
| } | |||||
| int juce_readFromInternetFile (void* handle, void* buffer, int bytesToRead) | |||||
| { | |||||
| JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle; | |||||
| if (s != 0) | |||||
| return s->read (buffer, bytesToRead); | |||||
| return 0; | |||||
| } | |||||
| int juce_seekInInternetFile (void* handle, int newPosition) | |||||
| { | |||||
| JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle; | |||||
| if (s != 0) | |||||
| return s->readPosition; | |||||
| return 0; | |||||
| } | |||||
| #endif // __JUCE_MAC_HTTPSTREAM_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 __JUCE_MAC_HTTPSTREAM_JUCEHEADER__ | |||||
| #define __JUCE_MAC_HTTPSTREAM_JUCEHEADER__ | |||||
| // (This file gets included by the mac + linux networking code) | |||||
| //============================================================================== | |||||
| /** A HTTP input stream that uses sockets. | |||||
| */ | |||||
| class JUCE_HTTPSocketStream | |||||
| { | |||||
| public: | |||||
| //============================================================================== | |||||
| JUCE_HTTPSocketStream() | |||||
| : statusCode (0), | |||||
| readPosition (0), | |||||
| socketHandle (-1), | |||||
| levelsOfRedirection (0), | |||||
| timeoutSeconds (15) | |||||
| { | |||||
| } | |||||
| ~JUCE_HTTPSocketStream() | |||||
| { | |||||
| closeSocket(); | |||||
| } | |||||
| //============================================================================== | |||||
| bool open (const String& url, | |||||
| const String& headers, | |||||
| const MemoryBlock& postData, | |||||
| const bool isPost, | |||||
| URL::OpenStreamProgressCallback* callback, | |||||
| void* callbackContext) | |||||
| { | |||||
| closeSocket(); | |||||
| String hostName, hostPath; | |||||
| int hostPort; | |||||
| if (! decomposeURL (url, hostName, hostPath, hostPort)) | |||||
| return false; | |||||
| struct hostent* const host | |||||
| = gethostbyname ((const char*) hostName.toUTF8()); | |||||
| if (host == 0) | |||||
| return false; | |||||
| struct sockaddr_in address; | |||||
| zerostruct (address); | |||||
| memcpy ((void*) &address.sin_addr, (const void*) host->h_addr, host->h_length); | |||||
| address.sin_family = host->h_addrtype; | |||||
| address.sin_port = htons (hostPort); | |||||
| socketHandle = socket (host->h_addrtype, SOCK_STREAM, 0); | |||||
| if (socketHandle == -1) | |||||
| return false; | |||||
| int receiveBufferSize = 16384; | |||||
| setsockopt (socketHandle, SOL_SOCKET, SO_RCVBUF, (char*) &receiveBufferSize, sizeof (receiveBufferSize)); | |||||
| setsockopt (socketHandle, SOL_SOCKET, SO_KEEPALIVE, 0, 0); | |||||
| #if JUCE_MAC | |||||
| setsockopt (socketHandle, SOL_SOCKET, SO_NOSIGPIPE, 0, 0); | |||||
| #endif | |||||
| if (connect (socketHandle, (struct sockaddr*) &address, sizeof (address)) == -1) | |||||
| { | |||||
| closeSocket(); | |||||
| return false; | |||||
| } | |||||
| String proxyURL (getenv ("http_proxy")); | |||||
| if (! proxyURL.startsWithIgnoreCase (T("http://"))) | |||||
| proxyURL = String::empty; | |||||
| const MemoryBlock requestHeader (createRequestHeader (hostName, hostPath, | |||||
| proxyURL, url, | |||||
| hostPort, | |||||
| headers, postData, | |||||
| isPost)); | |||||
| int totalHeaderSent = 0; | |||||
| while (totalHeaderSent < requestHeader.getSize()) | |||||
| { | |||||
| const int numToSend = jmin (1024, requestHeader.getSize() - totalHeaderSent); | |||||
| if (send (socketHandle, | |||||
| ((const char*) requestHeader.getData()) + totalHeaderSent, | |||||
| numToSend, 0) | |||||
| != numToSend) | |||||
| { | |||||
| closeSocket(); | |||||
| return false; | |||||
| } | |||||
| totalHeaderSent += numToSend; | |||||
| if (callback != 0 && ! callback (callbackContext, totalHeaderSent, requestHeader.getSize())) | |||||
| { | |||||
| closeSocket(); | |||||
| return false; | |||||
| } | |||||
| } | |||||
| const String responseHeader (readResponse()); | |||||
| if (responseHeader.isNotEmpty()) | |||||
| { | |||||
| //DBG (responseHeader); | |||||
| StringArray lines; | |||||
| lines.addLines (responseHeader); | |||||
| statusCode = responseHeader.fromFirstOccurrenceOf (T(" "), false, false) | |||||
| .substring (0, 3).getIntValue(); | |||||
| //int contentLength = findHeaderItem (lines, T("Content-Length:")).getIntValue(); | |||||
| //bool isChunked = findHeaderItem (lines, T("Transfer-Encoding:")).equalsIgnoreCase ("chunked"); | |||||
| String location (findHeaderItem (lines, T("Location:"))); | |||||
| if (statusCode >= 300 && statusCode < 400 | |||||
| && location.isNotEmpty()) | |||||
| { | |||||
| if (! location.startsWithIgnoreCase (T("http://"))) | |||||
| location = T("http://") + location; | |||||
| if (levelsOfRedirection++ < 3) | |||||
| return open (location, headers, postData, isPost, callback, callbackContext); | |||||
| } | |||||
| else | |||||
| { | |||||
| levelsOfRedirection = 0; | |||||
| return true; | |||||
| } | |||||
| } | |||||
| closeSocket(); | |||||
| return false; | |||||
| } | |||||
| //============================================================================== | |||||
| int read (void* buffer, int bytesToRead) | |||||
| { | |||||
| fd_set readbits; | |||||
| FD_ZERO (&readbits); | |||||
| FD_SET (socketHandle, &readbits); | |||||
| struct timeval tv; | |||||
| tv.tv_sec = timeoutSeconds; | |||||
| tv.tv_usec = 0; | |||||
| if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0) | |||||
| return 0; // (timeout) | |||||
| const int bytesRead = jmax (0, recv (socketHandle, buffer, bytesToRead, MSG_WAITALL)); | |||||
| readPosition += bytesRead; | |||||
| return bytesRead; | |||||
| } | |||||
| //============================================================================== | |||||
| int statusCode, readPosition; | |||||
| //============================================================================== | |||||
| juce_UseDebuggingNewOperator | |||||
| private: | |||||
| int socketHandle, levelsOfRedirection; | |||||
| const int timeoutSeconds; | |||||
| //============================================================================== | |||||
| void closeSocket() | |||||
| { | |||||
| if (socketHandle >= 0) | |||||
| close (socketHandle); | |||||
| socketHandle = -1; | |||||
| } | |||||
| const MemoryBlock createRequestHeader (const String& hostName, | |||||
| const String& hostPath, | |||||
| const String& proxyURL, | |||||
| const String& originalURL, | |||||
| const int hostPort, | |||||
| const String& headers, | |||||
| const MemoryBlock& postData, | |||||
| const bool isPost) | |||||
| { | |||||
| String header (isPost ? "POST " : "GET "); | |||||
| if (proxyURL.isEmpty()) | |||||
| { | |||||
| header << hostPath << " HTTP/1.0\r\nHost: " | |||||
| << hostName << ':' << hostPort; | |||||
| } | |||||
| else | |||||
| { | |||||
| String proxyName, proxyPath; | |||||
| int proxyPort; | |||||
| if (! decomposeURL (proxyURL, proxyName, proxyPath, proxyPort)) | |||||
| return MemoryBlock(); | |||||
| header << originalURL << " HTTP/1.0\r\nHost: " | |||||
| << proxyName << ':' << proxyPort; | |||||
| /* xxx needs finishing | |||||
| const char* proxyAuth = getenv ("http_proxy_auth"); | |||||
| if (proxyAuth != 0) | |||||
| header << T("\r\nProxy-Authorization: ") << Base64Encode (proxyAuth); | |||||
| */ | |||||
| } | |||||
| header << "\r\nUser-Agent: JUCE/" | |||||
| << JUCE_MAJOR_VERSION << '.' << JUCE_MINOR_VERSION | |||||
| << "\r\nConnection: Close\r\nContent-Length: " | |||||
| << postData.getSize() << "\r\n" | |||||
| << headers << "\r\n"; | |||||
| MemoryBlock mb; | |||||
| mb.append (header.toUTF8(), (int) strlen (header.toUTF8())); | |||||
| mb.append (postData.getData(), postData.getSize()); | |||||
| return mb; | |||||
| } | |||||
| const String readResponse() | |||||
| { | |||||
| int bytesRead = 0, numConsecutiveLFs = 0; | |||||
| MemoryBlock buffer (1024, true); | |||||
| while (numConsecutiveLFs < 2 && bytesRead < 32768) | |||||
| { | |||||
| fd_set readbits; | |||||
| FD_ZERO (&readbits); | |||||
| FD_SET (socketHandle, &readbits); | |||||
| struct timeval tv; | |||||
| tv.tv_sec = timeoutSeconds; | |||||
| tv.tv_usec = 0; | |||||
| if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0) | |||||
| return String::empty; // (timeout) | |||||
| buffer.ensureSize (bytesRead + 8, true); | |||||
| char* const dest = (char*) buffer.getData() + bytesRead; | |||||
| if (recv (socketHandle, dest, 1, 0) == -1) | |||||
| return String::empty; | |||||
| const char lastByte = *dest; | |||||
| ++bytesRead; | |||||
| if (lastByte == '\n') | |||||
| ++numConsecutiveLFs; | |||||
| else if (lastByte != '\r') | |||||
| numConsecutiveLFs = 0; | |||||
| } | |||||
| const String header (String::fromUTF8 ((const uint8*) buffer.getData())); | |||||
| if (header.startsWithIgnoreCase (T("HTTP/"))) | |||||
| return header.trimEnd(); | |||||
| return String::empty; | |||||
| } | |||||
| //============================================================================== | |||||
| static bool decomposeURL (const String& url, | |||||
| String& host, String& path, int& port) | |||||
| { | |||||
| if (! url.startsWithIgnoreCase (T("http://"))) | |||||
| return false; | |||||
| const int nextSlash = url.indexOfChar (7, '/'); | |||||
| int nextColon = url.indexOfChar (7, ':'); | |||||
| if (nextColon > nextSlash && nextSlash > 0) | |||||
| nextColon = -1; | |||||
| if (nextColon >= 0) | |||||
| { | |||||
| host = url.substring (7, nextColon); | |||||
| if (nextSlash >= 0) | |||||
| port = url.substring (nextColon + 1, nextSlash).getIntValue(); | |||||
| else | |||||
| port = url.substring (nextColon + 1).getIntValue(); | |||||
| } | |||||
| else | |||||
| { | |||||
| port = 80; | |||||
| if (nextSlash >= 0) | |||||
| host = url.substring (7, nextSlash); | |||||
| else | |||||
| host = url.substring (7); | |||||
| } | |||||
| if (nextSlash >= 0) | |||||
| path = url.substring (nextSlash); | |||||
| else | |||||
| path = T("/"); | |||||
| return true; | |||||
| } | |||||
| //============================================================================== | |||||
| static const String findHeaderItem (const StringArray& lines, const String& itemName) | |||||
| { | |||||
| for (int i = 0; i < lines.size(); ++i) | |||||
| if (lines[i].startsWithIgnoreCase (itemName)) | |||||
| return lines[i].substring (itemName.length()).trim(); | |||||
| return String::empty; | |||||
| } | |||||
| }; | |||||
| //============================================================================== | |||||
| 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) | |||||
| { | |||||
| JUCE_HTTPSocketStream* const s = new JUCE_HTTPSocketStream(); | |||||
| if (s->open (url, headers, postData, isPost, | |||||
| callback, callbackContext)) | |||||
| return s; | |||||
| delete s; | |||||
| return 0; | |||||
| } | |||||
| void juce_closeInternetFile (void* handle) | |||||
| { | |||||
| JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle; | |||||
| if (s != 0) | |||||
| delete s; | |||||
| } | |||||
| int juce_readFromInternetFile (void* handle, void* buffer, int bytesToRead) | |||||
| { | |||||
| JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle; | |||||
| if (s != 0) | |||||
| return s->read (buffer, bytesToRead); | |||||
| return 0; | |||||
| } | |||||
| int juce_seekInInternetFile (void* handle, int newPosition) | |||||
| { | |||||
| JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle; | |||||
| if (s != 0) | |||||
| return s->readPosition; | |||||
| return 0; | |||||
| } | |||||
| #endif // __JUCE_MAC_HTTPSTREAM_JUCEHEADER__ | |||||
| @@ -568,7 +568,7 @@ void* juce_findFileStart (const String& directory, const String& wildCard, Strin | |||||
| if (h != INVALID_HANDLE_VALUE) | if (h != INVALID_HANDLE_VALUE) | ||||
| { | { | ||||
| getFindFileInfo (findData, firstResult, isDir, isHidden, fileSize, | |||||
| getFindFileInfo (findData, firstResult, isDir, isHidden, fileSize, | |||||
| modTime, creationTime, isReadOnly); | modTime, creationTime, isReadOnly); | ||||
| return h; | return h; | ||||
| } | } | ||||
| @@ -1,113 +1,113 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| 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 __JUCE_AUDIOCDBURNER_JUCEHEADER__ | |||||
| #define __JUCE_AUDIOCDBURNER_JUCEHEADER__ | |||||
| #include "juce_AudioFormatReader.h" | |||||
| #include "../audio_sources/juce_AudioSource.h" | |||||
| //============================================================================== | |||||
| /** | |||||
| */ | |||||
| class AudioCDBurner | |||||
| { | |||||
| public: | |||||
| //============================================================================== | |||||
| /** Returns a list of available optical drives. | |||||
| Use openDevice() to open one of the items from this list. | |||||
| */ | |||||
| static const StringArray findAvailableDevices(); | |||||
| /** Tries to open one of the optical drives. | |||||
| The deviceIndex is an index into the array returned by findAvailableDevices(). | |||||
| */ | |||||
| static AudioCDBurner* openDevice (const int deviceIndex); | |||||
| /** Destructor. */ | |||||
| ~AudioCDBurner(); | |||||
| //============================================================================== | |||||
| /** Returns true if there's a writable disk in the drive. | |||||
| */ | |||||
| bool isDiskPresent() const; | |||||
| /** Returns the number of free blocks on the disk. | |||||
| There are 75 blocks per second, at 44100Hz. | |||||
| */ | |||||
| int getNumAvailableAudioBlocks() const; | |||||
| /** Adds a track to be written. | |||||
| The source passed-in here will be kept by this object, and it will | |||||
| be used and deleted at some point in the future, either during the | |||||
| burn() method or when this AudioCDBurner object is deleted. Your caller | |||||
| method shouldn't keep a reference to it or use it again after passing | |||||
| it in here. | |||||
| */ | |||||
| bool addAudioTrack (AudioSource* source, int numSamples); | |||||
| /** | |||||
| Return true to cancel the current burn operation | |||||
| */ | |||||
| class BurnProgressListener | |||||
| { | |||||
| public: | |||||
| BurnProgressListener() throw() {} | |||||
| virtual ~BurnProgressListener() {} | |||||
| /** Called at intervals to report on the progress of the AudioCDBurner. | |||||
| To cancel the burn, return true from this. | |||||
| */ | |||||
| virtual bool audioCDBurnProgress (float proportionComplete) = 0; | |||||
| }; | |||||
| const String burn (BurnProgressListener* listener, | |||||
| const bool ejectDiscAfterwards, | |||||
| const bool peformFakeBurnForTesting); | |||||
| //============================================================================== | |||||
| juce_UseDebuggingNewOperator | |||||
| private: | |||||
| AudioCDBurner (const int deviceIndex); | |||||
| void* internal; | |||||
| }; | |||||
| #endif // __JUCE_AUDIOCDBURNER_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 __JUCE_AUDIOCDBURNER_JUCEHEADER__ | |||||
| #define __JUCE_AUDIOCDBURNER_JUCEHEADER__ | |||||
| #include "juce_AudioFormatReader.h" | |||||
| #include "../audio_sources/juce_AudioSource.h" | |||||
| //============================================================================== | |||||
| /** | |||||
| */ | |||||
| class AudioCDBurner | |||||
| { | |||||
| public: | |||||
| //============================================================================== | |||||
| /** Returns a list of available optical drives. | |||||
| Use openDevice() to open one of the items from this list. | |||||
| */ | |||||
| static const StringArray findAvailableDevices(); | |||||
| /** Tries to open one of the optical drives. | |||||
| The deviceIndex is an index into the array returned by findAvailableDevices(). | |||||
| */ | |||||
| static AudioCDBurner* openDevice (const int deviceIndex); | |||||
| /** Destructor. */ | |||||
| ~AudioCDBurner(); | |||||
| //============================================================================== | |||||
| /** Returns true if there's a writable disk in the drive. | |||||
| */ | |||||
| bool isDiskPresent() const; | |||||
| /** Returns the number of free blocks on the disk. | |||||
| There are 75 blocks per second, at 44100Hz. | |||||
| */ | |||||
| int getNumAvailableAudioBlocks() const; | |||||
| /** Adds a track to be written. | |||||
| The source passed-in here will be kept by this object, and it will | |||||
| be used and deleted at some point in the future, either during the | |||||
| burn() method or when this AudioCDBurner object is deleted. Your caller | |||||
| method shouldn't keep a reference to it or use it again after passing | |||||
| it in here. | |||||
| */ | |||||
| bool addAudioTrack (AudioSource* source, int numSamples); | |||||
| /** | |||||
| Return true to cancel the current burn operation | |||||
| */ | |||||
| class BurnProgressListener | |||||
| { | |||||
| public: | |||||
| BurnProgressListener() throw() {} | |||||
| virtual ~BurnProgressListener() {} | |||||
| /** Called at intervals to report on the progress of the AudioCDBurner. | |||||
| To cancel the burn, return true from this. | |||||
| */ | |||||
| virtual bool audioCDBurnProgress (float proportionComplete) = 0; | |||||
| }; | |||||
| const String burn (BurnProgressListener* listener, | |||||
| const bool ejectDiscAfterwards, | |||||
| const bool peformFakeBurnForTesting); | |||||
| //============================================================================== | |||||
| juce_UseDebuggingNewOperator | |||||
| private: | |||||
| AudioCDBurner (const int deviceIndex); | |||||
| void* internal; | |||||
| }; | |||||
| #endif // __JUCE_AUDIOCDBURNER_JUCEHEADER__ | |||||
| @@ -105,7 +105,7 @@ void AudioThumbnail::setSource (InputSource* const newSource) | |||||
| clear(); | clear(); | ||||
| if (! (cache.loadThumb (*this, newSource->hashCode()) | |||||
| if (! (cache.loadThumb (*this, newSource->hashCode()) | |||||
| && isFullyLoaded())) | && isFullyLoaded())) | ||||
| { | { | ||||
| { | { | ||||
| @@ -1,412 +1,412 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| 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 "../../../../juce_Config.h" | |||||
| #if JUCE_QUICKTIME | |||||
| #if ! defined (_WIN32) | |||||
| #include <Quicktime/Movies.h> | |||||
| #include <Quicktime/QTML.h> | |||||
| #include <Quicktime/QuickTimeComponents.h> | |||||
| #include <Quicktime/MediaHandlers.h> | |||||
| #include <Quicktime/ImageCodec.h> | |||||
| #else | |||||
| #ifdef _MSC_VER | |||||
| #pragma warning (push) | |||||
| #pragma warning (disable : 4100) | |||||
| #endif | |||||
| /* If you've got an include error here, you probably need to install the QuickTime SDK and | |||||
| add its header directory to your include path. | |||||
| Alternatively, if you don't need any QuickTime services, just turn off the JUC_QUICKTIME | |||||
| flag in juce_Config.h | |||||
| */ | |||||
| #include <Movies.h> | |||||
| #include <QTML.h> | |||||
| #include <QuickTimeComponents.h> | |||||
| #include <MediaHandlers.h> | |||||
| #include <ImageCodec.h> | |||||
| #ifdef _MSC_VER | |||||
| #pragma warning (pop) | |||||
| #endif | |||||
| #endif | |||||
| #include "../../../juce_core/basics/juce_StandardHeader.h" | |||||
| BEGIN_JUCE_NAMESPACE | |||||
| #include "juce_QuickTimeAudioFormat.h" | |||||
| #include "../../../juce_core/text/juce_LocalisedStrings.h" | |||||
| #include "../../../juce_core/threads/juce_Thread.h" | |||||
| #include "../../../juce_core/io/network/juce_URL.h" | |||||
| bool juce_OpenQuickTimeMovieFromStream (InputStream* input, Movie& movie, Handle& dataHandle); | |||||
| #define qtFormatName TRANS("QuickTime file") | |||||
| static const tchar* const extensions[] = { T(".mov"), T(".mp3"), T(".mp4"), 0 }; | |||||
| //============================================================================== | |||||
| class QTAudioReader : public AudioFormatReader | |||||
| { | |||||
| public: | |||||
| QTAudioReader (InputStream* const input_, const int trackNum_) | |||||
| : AudioFormatReader (input_, qtFormatName), | |||||
| ok (false), | |||||
| movie (0), | |||||
| trackNum (trackNum_), | |||||
| extractor (0), | |||||
| lastSampleRead (0), | |||||
| lastThreadId (0), | |||||
| dataHandle (0) | |||||
| { | |||||
| bufferList = (AudioBufferList*) juce_calloc (256); | |||||
| #ifdef WIN32 | |||||
| if (InitializeQTML (0) != noErr) | |||||
| return; | |||||
| #endif | |||||
| if (EnterMovies() != noErr) | |||||
| return; | |||||
| #if JUCE_MAC | |||||
| EnterMoviesOnThread (0); | |||||
| #endif | |||||
| bool opened = juce_OpenQuickTimeMovieFromStream (input_, movie, dataHandle); | |||||
| if (! opened) | |||||
| return; | |||||
| { | |||||
| const int numTracks = GetMovieTrackCount (movie); | |||||
| int trackCount = 0; | |||||
| for (int i = 1; i <= numTracks; ++i) | |||||
| { | |||||
| track = GetMovieIndTrack (movie, i); | |||||
| media = GetTrackMedia (track); | |||||
| OSType mediaType; | |||||
| GetMediaHandlerDescription (media, &mediaType, 0, 0); | |||||
| if (mediaType == SoundMediaType | |||||
| && trackCount++ == trackNum_) | |||||
| { | |||||
| ok = true; | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| if (! ok) | |||||
| return; | |||||
| ok = false; | |||||
| lengthInSamples = GetMediaDecodeDuration (media); | |||||
| usesFloatingPointData = false; | |||||
| samplesPerFrame = (int) (GetMediaDecodeDuration (media) / GetMediaSampleCount (media)); | |||||
| trackUnitsPerFrame = GetMovieTimeScale (movie) * samplesPerFrame | |||||
| / GetMediaTimeScale (media); | |||||
| OSStatus err = MovieAudioExtractionBegin (movie, 0, &extractor); | |||||
| unsigned long output_layout_size; | |||||
| err = MovieAudioExtractionGetPropertyInfo (extractor, | |||||
| kQTPropertyClass_MovieAudioExtraction_Audio, | |||||
| kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout, | |||||
| 0, &output_layout_size, 0); | |||||
| if (err != noErr) | |||||
| return; | |||||
| AudioChannelLayout* const qt_audio_channel_layout | |||||
| = (AudioChannelLayout*) juce_calloc (output_layout_size); | |||||
| err = MovieAudioExtractionGetProperty (extractor, | |||||
| kQTPropertyClass_MovieAudioExtraction_Audio, | |||||
| kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout, | |||||
| output_layout_size, qt_audio_channel_layout, 0); | |||||
| qt_audio_channel_layout->mChannelLayoutTag = kAudioChannelLayoutTag_Stereo; | |||||
| err = MovieAudioExtractionSetProperty (extractor, | |||||
| kQTPropertyClass_MovieAudioExtraction_Audio, | |||||
| kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout, | |||||
| sizeof (qt_audio_channel_layout), | |||||
| qt_audio_channel_layout); | |||||
| juce_free (qt_audio_channel_layout); | |||||
| err = MovieAudioExtractionGetProperty (extractor, | |||||
| kQTPropertyClass_MovieAudioExtraction_Audio, | |||||
| kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription, | |||||
| sizeof (inputStreamDesc), | |||||
| &inputStreamDesc, 0); | |||||
| if (err != noErr) | |||||
| return; | |||||
| inputStreamDesc.mFormatFlags = kAudioFormatFlagIsSignedInteger | |||||
| | kAudioFormatFlagIsPacked | |||||
| | kAudioFormatFlagsNativeEndian; | |||||
| inputStreamDesc.mBitsPerChannel = sizeof (SInt16) * 8; | |||||
| inputStreamDesc.mChannelsPerFrame = jmin (2, inputStreamDesc.mChannelsPerFrame); | |||||
| inputStreamDesc.mBytesPerFrame = sizeof (SInt16) * inputStreamDesc.mChannelsPerFrame; | |||||
| inputStreamDesc.mBytesPerPacket = inputStreamDesc.mBytesPerFrame; | |||||
| err = MovieAudioExtractionSetProperty (extractor, | |||||
| kQTPropertyClass_MovieAudioExtraction_Audio, | |||||
| kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription, | |||||
| sizeof (inputStreamDesc), | |||||
| &inputStreamDesc); | |||||
| if (err != noErr) | |||||
| return; | |||||
| Boolean allChannelsDiscrete = false; | |||||
| err = MovieAudioExtractionSetProperty (extractor, | |||||
| kQTPropertyClass_MovieAudioExtraction_Movie, | |||||
| kQTMovieAudioExtractionMoviePropertyID_AllChannelsDiscrete, | |||||
| sizeof (allChannelsDiscrete), | |||||
| &allChannelsDiscrete); | |||||
| if (err != noErr) | |||||
| return; | |||||
| bufferList->mNumberBuffers = 1; | |||||
| bufferList->mBuffers[0].mNumberChannels = inputStreamDesc.mChannelsPerFrame; | |||||
| bufferList->mBuffers[0].mDataByteSize = (UInt32) (samplesPerFrame * inputStreamDesc.mBytesPerFrame) + 16; | |||||
| bufferList->mBuffers[0].mData = malloc (bufferList->mBuffers[0].mDataByteSize); | |||||
| sampleRate = inputStreamDesc.mSampleRate; | |||||
| bitsPerSample = 16; | |||||
| numChannels = inputStreamDesc.mChannelsPerFrame; | |||||
| detachThread(); | |||||
| ok = true; | |||||
| } | |||||
| ~QTAudioReader() | |||||
| { | |||||
| if (dataHandle != 0) | |||||
| DisposeHandle (dataHandle); | |||||
| if (extractor != 0) | |||||
| { | |||||
| MovieAudioExtractionEnd (extractor); | |||||
| extractor = 0; | |||||
| } | |||||
| checkThreadIsAttached(); | |||||
| DisposeMovie (movie); | |||||
| juce_free (bufferList->mBuffers[0].mData); | |||||
| juce_free (bufferList); | |||||
| } | |||||
| bool read (int** destSamples, | |||||
| int64 startSample, | |||||
| int numSamples) | |||||
| { | |||||
| checkThreadIsAttached(); | |||||
| int done = 0; | |||||
| while (numSamples > 0) | |||||
| { | |||||
| if (! loadFrame ((int) startSample)) | |||||
| return false; | |||||
| const int numToDo = jmin (numSamples, samplesPerFrame); | |||||
| for (unsigned int j = 0; j < inputStreamDesc.mChannelsPerFrame; ++j) | |||||
| { | |||||
| if (destSamples[j] != 0) | |||||
| { | |||||
| const short* const src = ((const short*) bufferList->mBuffers[0].mData) + j; | |||||
| for (int i = 0; i < numToDo; ++i) | |||||
| destSamples[j][done + i] = src [i << 1] << 16; | |||||
| } | |||||
| } | |||||
| done += numToDo; | |||||
| startSample += numToDo; | |||||
| numSamples -= numToDo; | |||||
| } | |||||
| detachThread(); | |||||
| return true; | |||||
| } | |||||
| bool loadFrame (const int sampleNum) | |||||
| { | |||||
| if (lastSampleRead != sampleNum) | |||||
| { | |||||
| TimeRecord time; | |||||
| time.scale = (TimeScale) inputStreamDesc.mSampleRate; | |||||
| time.base = 0; | |||||
| time.value.hi = 0; | |||||
| time.value.lo = (UInt32) sampleNum; | |||||
| OSStatus err = MovieAudioExtractionSetProperty (extractor, | |||||
| kQTPropertyClass_MovieAudioExtraction_Movie, | |||||
| kQTMovieAudioExtractionMoviePropertyID_CurrentTime, | |||||
| sizeof (time), &time); | |||||
| if (err != noErr) | |||||
| return false; | |||||
| } | |||||
| bufferList->mBuffers[0].mDataByteSize = inputStreamDesc.mBytesPerFrame * samplesPerFrame; | |||||
| UInt32 outFlags = 0; | |||||
| UInt32 actualNumSamples = samplesPerFrame; | |||||
| OSStatus err = MovieAudioExtractionFillBuffer (extractor, &actualNumSamples, | |||||
| bufferList, &outFlags); | |||||
| lastSampleRead = sampleNum + samplesPerFrame; | |||||
| return err == noErr; | |||||
| } | |||||
| juce_UseDebuggingNewOperator | |||||
| bool ok; | |||||
| private: | |||||
| Movie movie; | |||||
| Media media; | |||||
| Track track; | |||||
| const int trackNum; | |||||
| double trackUnitsPerFrame; | |||||
| int samplesPerFrame; | |||||
| int lastSampleRead, lastThreadId; | |||||
| MovieAudioExtractionRef extractor; | |||||
| AudioStreamBasicDescription inputStreamDesc; | |||||
| AudioBufferList* bufferList; | |||||
| Handle dataHandle; | |||||
| /*OSErr readMovieStream (long offset, long size, void* dataPtr) | |||||
| { | |||||
| input->setPosition (offset); | |||||
| input->read (dataPtr, size); | |||||
| return noErr; | |||||
| } | |||||
| static OSErr readMovieStreamProc (long offset, long size, void* dataPtr, void* userRef) | |||||
| { | |||||
| return ((QTAudioReader*) userRef)->readMovieStream (offset, size, dataPtr); | |||||
| }*/ | |||||
| //============================================================================== | |||||
| void checkThreadIsAttached() | |||||
| { | |||||
| #if JUCE_MAC | |||||
| if (Thread::getCurrentThreadId() != lastThreadId) | |||||
| EnterMoviesOnThread (0); | |||||
| AttachMovieToCurrentThread (movie); | |||||
| #endif | |||||
| } | |||||
| void detachThread() | |||||
| { | |||||
| #if JUCE_MAC | |||||
| DetachMovieFromCurrentThread (movie); | |||||
| #endif | |||||
| } | |||||
| }; | |||||
| //============================================================================== | |||||
| QuickTimeAudioFormat::QuickTimeAudioFormat() | |||||
| : AudioFormat (qtFormatName, (const tchar**) extensions) | |||||
| { | |||||
| } | |||||
| QuickTimeAudioFormat::~QuickTimeAudioFormat() | |||||
| { | |||||
| } | |||||
| const Array <int> QuickTimeAudioFormat::getPossibleSampleRates() | |||||
| { | |||||
| return Array<int>(); | |||||
| } | |||||
| const Array <int> QuickTimeAudioFormat::getPossibleBitDepths() | |||||
| { | |||||
| return Array<int>(); | |||||
| } | |||||
| bool QuickTimeAudioFormat::canDoStereo() | |||||
| { | |||||
| return true; | |||||
| } | |||||
| bool QuickTimeAudioFormat::canDoMono() | |||||
| { | |||||
| return true; | |||||
| } | |||||
| //============================================================================== | |||||
| AudioFormatReader* QuickTimeAudioFormat::createReaderFor (InputStream* sourceStream, | |||||
| const bool deleteStreamIfOpeningFails) | |||||
| { | |||||
| QTAudioReader* r = new QTAudioReader (sourceStream, 0); | |||||
| if (! r->ok) | |||||
| { | |||||
| if (! deleteStreamIfOpeningFails) | |||||
| r->input = 0; | |||||
| deleteAndZero (r); | |||||
| } | |||||
| return r; | |||||
| } | |||||
| AudioFormatWriter* QuickTimeAudioFormat::createWriterFor (OutputStream* /*streamToWriteTo*/, | |||||
| double /*sampleRateToUse*/, | |||||
| unsigned int /*numberOfChannels*/, | |||||
| int /*bitsPerSample*/, | |||||
| const StringPairArray& /*metadataValues*/, | |||||
| int /*qualityOptionIndex*/) | |||||
| { | |||||
| jassertfalse // not yet implemented! | |||||
| return 0; | |||||
| } | |||||
| END_JUCE_NAMESPACE | |||||
| #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. | |||||
| ============================================================================== | |||||
| */ | |||||
| #include "../../../../juce_Config.h" | |||||
| #if JUCE_QUICKTIME | |||||
| #if ! defined (_WIN32) | |||||
| #include <Quicktime/Movies.h> | |||||
| #include <Quicktime/QTML.h> | |||||
| #include <Quicktime/QuickTimeComponents.h> | |||||
| #include <Quicktime/MediaHandlers.h> | |||||
| #include <Quicktime/ImageCodec.h> | |||||
| #else | |||||
| #ifdef _MSC_VER | |||||
| #pragma warning (push) | |||||
| #pragma warning (disable : 4100) | |||||
| #endif | |||||
| /* If you've got an include error here, you probably need to install the QuickTime SDK and | |||||
| add its header directory to your include path. | |||||
| Alternatively, if you don't need any QuickTime services, just turn off the JUC_QUICKTIME | |||||
| flag in juce_Config.h | |||||
| */ | |||||
| #include <Movies.h> | |||||
| #include <QTML.h> | |||||
| #include <QuickTimeComponents.h> | |||||
| #include <MediaHandlers.h> | |||||
| #include <ImageCodec.h> | |||||
| #ifdef _MSC_VER | |||||
| #pragma warning (pop) | |||||
| #endif | |||||
| #endif | |||||
| #include "../../../juce_core/basics/juce_StandardHeader.h" | |||||
| BEGIN_JUCE_NAMESPACE | |||||
| #include "juce_QuickTimeAudioFormat.h" | |||||
| #include "../../../juce_core/text/juce_LocalisedStrings.h" | |||||
| #include "../../../juce_core/threads/juce_Thread.h" | |||||
| #include "../../../juce_core/io/network/juce_URL.h" | |||||
| bool juce_OpenQuickTimeMovieFromStream (InputStream* input, Movie& movie, Handle& dataHandle); | |||||
| #define qtFormatName TRANS("QuickTime file") | |||||
| static const tchar* const extensions[] = { T(".mov"), T(".mp3"), T(".mp4"), 0 }; | |||||
| //============================================================================== | |||||
| class QTAudioReader : public AudioFormatReader | |||||
| { | |||||
| public: | |||||
| QTAudioReader (InputStream* const input_, const int trackNum_) | |||||
| : AudioFormatReader (input_, qtFormatName), | |||||
| ok (false), | |||||
| movie (0), | |||||
| trackNum (trackNum_), | |||||
| extractor (0), | |||||
| lastSampleRead (0), | |||||
| lastThreadId (0), | |||||
| dataHandle (0) | |||||
| { | |||||
| bufferList = (AudioBufferList*) juce_calloc (256); | |||||
| #ifdef WIN32 | |||||
| if (InitializeQTML (0) != noErr) | |||||
| return; | |||||
| #endif | |||||
| if (EnterMovies() != noErr) | |||||
| return; | |||||
| #if JUCE_MAC | |||||
| EnterMoviesOnThread (0); | |||||
| #endif | |||||
| bool opened = juce_OpenQuickTimeMovieFromStream (input_, movie, dataHandle); | |||||
| if (! opened) | |||||
| return; | |||||
| { | |||||
| const int numTracks = GetMovieTrackCount (movie); | |||||
| int trackCount = 0; | |||||
| for (int i = 1; i <= numTracks; ++i) | |||||
| { | |||||
| track = GetMovieIndTrack (movie, i); | |||||
| media = GetTrackMedia (track); | |||||
| OSType mediaType; | |||||
| GetMediaHandlerDescription (media, &mediaType, 0, 0); | |||||
| if (mediaType == SoundMediaType | |||||
| && trackCount++ == trackNum_) | |||||
| { | |||||
| ok = true; | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| if (! ok) | |||||
| return; | |||||
| ok = false; | |||||
| lengthInSamples = GetMediaDecodeDuration (media); | |||||
| usesFloatingPointData = false; | |||||
| samplesPerFrame = (int) (GetMediaDecodeDuration (media) / GetMediaSampleCount (media)); | |||||
| trackUnitsPerFrame = GetMovieTimeScale (movie) * samplesPerFrame | |||||
| / GetMediaTimeScale (media); | |||||
| OSStatus err = MovieAudioExtractionBegin (movie, 0, &extractor); | |||||
| unsigned long output_layout_size; | |||||
| err = MovieAudioExtractionGetPropertyInfo (extractor, | |||||
| kQTPropertyClass_MovieAudioExtraction_Audio, | |||||
| kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout, | |||||
| 0, &output_layout_size, 0); | |||||
| if (err != noErr) | |||||
| return; | |||||
| AudioChannelLayout* const qt_audio_channel_layout | |||||
| = (AudioChannelLayout*) juce_calloc (output_layout_size); | |||||
| err = MovieAudioExtractionGetProperty (extractor, | |||||
| kQTPropertyClass_MovieAudioExtraction_Audio, | |||||
| kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout, | |||||
| output_layout_size, qt_audio_channel_layout, 0); | |||||
| qt_audio_channel_layout->mChannelLayoutTag = kAudioChannelLayoutTag_Stereo; | |||||
| err = MovieAudioExtractionSetProperty (extractor, | |||||
| kQTPropertyClass_MovieAudioExtraction_Audio, | |||||
| kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout, | |||||
| sizeof (qt_audio_channel_layout), | |||||
| qt_audio_channel_layout); | |||||
| juce_free (qt_audio_channel_layout); | |||||
| err = MovieAudioExtractionGetProperty (extractor, | |||||
| kQTPropertyClass_MovieAudioExtraction_Audio, | |||||
| kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription, | |||||
| sizeof (inputStreamDesc), | |||||
| &inputStreamDesc, 0); | |||||
| if (err != noErr) | |||||
| return; | |||||
| inputStreamDesc.mFormatFlags = kAudioFormatFlagIsSignedInteger | |||||
| | kAudioFormatFlagIsPacked | |||||
| | kAudioFormatFlagsNativeEndian; | |||||
| inputStreamDesc.mBitsPerChannel = sizeof (SInt16) * 8; | |||||
| inputStreamDesc.mChannelsPerFrame = jmin (2, inputStreamDesc.mChannelsPerFrame); | |||||
| inputStreamDesc.mBytesPerFrame = sizeof (SInt16) * inputStreamDesc.mChannelsPerFrame; | |||||
| inputStreamDesc.mBytesPerPacket = inputStreamDesc.mBytesPerFrame; | |||||
| err = MovieAudioExtractionSetProperty (extractor, | |||||
| kQTPropertyClass_MovieAudioExtraction_Audio, | |||||
| kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription, | |||||
| sizeof (inputStreamDesc), | |||||
| &inputStreamDesc); | |||||
| if (err != noErr) | |||||
| return; | |||||
| Boolean allChannelsDiscrete = false; | |||||
| err = MovieAudioExtractionSetProperty (extractor, | |||||
| kQTPropertyClass_MovieAudioExtraction_Movie, | |||||
| kQTMovieAudioExtractionMoviePropertyID_AllChannelsDiscrete, | |||||
| sizeof (allChannelsDiscrete), | |||||
| &allChannelsDiscrete); | |||||
| if (err != noErr) | |||||
| return; | |||||
| bufferList->mNumberBuffers = 1; | |||||
| bufferList->mBuffers[0].mNumberChannels = inputStreamDesc.mChannelsPerFrame; | |||||
| bufferList->mBuffers[0].mDataByteSize = (UInt32) (samplesPerFrame * inputStreamDesc.mBytesPerFrame) + 16; | |||||
| bufferList->mBuffers[0].mData = malloc (bufferList->mBuffers[0].mDataByteSize); | |||||
| sampleRate = inputStreamDesc.mSampleRate; | |||||
| bitsPerSample = 16; | |||||
| numChannels = inputStreamDesc.mChannelsPerFrame; | |||||
| detachThread(); | |||||
| ok = true; | |||||
| } | |||||
| ~QTAudioReader() | |||||
| { | |||||
| if (dataHandle != 0) | |||||
| DisposeHandle (dataHandle); | |||||
| if (extractor != 0) | |||||
| { | |||||
| MovieAudioExtractionEnd (extractor); | |||||
| extractor = 0; | |||||
| } | |||||
| checkThreadIsAttached(); | |||||
| DisposeMovie (movie); | |||||
| juce_free (bufferList->mBuffers[0].mData); | |||||
| juce_free (bufferList); | |||||
| } | |||||
| bool read (int** destSamples, | |||||
| int64 startSample, | |||||
| int numSamples) | |||||
| { | |||||
| checkThreadIsAttached(); | |||||
| int done = 0; | |||||
| while (numSamples > 0) | |||||
| { | |||||
| if (! loadFrame ((int) startSample)) | |||||
| return false; | |||||
| const int numToDo = jmin (numSamples, samplesPerFrame); | |||||
| for (unsigned int j = 0; j < inputStreamDesc.mChannelsPerFrame; ++j) | |||||
| { | |||||
| if (destSamples[j] != 0) | |||||
| { | |||||
| const short* const src = ((const short*) bufferList->mBuffers[0].mData) + j; | |||||
| for (int i = 0; i < numToDo; ++i) | |||||
| destSamples[j][done + i] = src [i << 1] << 16; | |||||
| } | |||||
| } | |||||
| done += numToDo; | |||||
| startSample += numToDo; | |||||
| numSamples -= numToDo; | |||||
| } | |||||
| detachThread(); | |||||
| return true; | |||||
| } | |||||
| bool loadFrame (const int sampleNum) | |||||
| { | |||||
| if (lastSampleRead != sampleNum) | |||||
| { | |||||
| TimeRecord time; | |||||
| time.scale = (TimeScale) inputStreamDesc.mSampleRate; | |||||
| time.base = 0; | |||||
| time.value.hi = 0; | |||||
| time.value.lo = (UInt32) sampleNum; | |||||
| OSStatus err = MovieAudioExtractionSetProperty (extractor, | |||||
| kQTPropertyClass_MovieAudioExtraction_Movie, | |||||
| kQTMovieAudioExtractionMoviePropertyID_CurrentTime, | |||||
| sizeof (time), &time); | |||||
| if (err != noErr) | |||||
| return false; | |||||
| } | |||||
| bufferList->mBuffers[0].mDataByteSize = inputStreamDesc.mBytesPerFrame * samplesPerFrame; | |||||
| UInt32 outFlags = 0; | |||||
| UInt32 actualNumSamples = samplesPerFrame; | |||||
| OSStatus err = MovieAudioExtractionFillBuffer (extractor, &actualNumSamples, | |||||
| bufferList, &outFlags); | |||||
| lastSampleRead = sampleNum + samplesPerFrame; | |||||
| return err == noErr; | |||||
| } | |||||
| juce_UseDebuggingNewOperator | |||||
| bool ok; | |||||
| private: | |||||
| Movie movie; | |||||
| Media media; | |||||
| Track track; | |||||
| const int trackNum; | |||||
| double trackUnitsPerFrame; | |||||
| int samplesPerFrame; | |||||
| int lastSampleRead, lastThreadId; | |||||
| MovieAudioExtractionRef extractor; | |||||
| AudioStreamBasicDescription inputStreamDesc; | |||||
| AudioBufferList* bufferList; | |||||
| Handle dataHandle; | |||||
| /*OSErr readMovieStream (long offset, long size, void* dataPtr) | |||||
| { | |||||
| input->setPosition (offset); | |||||
| input->read (dataPtr, size); | |||||
| return noErr; | |||||
| } | |||||
| static OSErr readMovieStreamProc (long offset, long size, void* dataPtr, void* userRef) | |||||
| { | |||||
| return ((QTAudioReader*) userRef)->readMovieStream (offset, size, dataPtr); | |||||
| }*/ | |||||
| //============================================================================== | |||||
| void checkThreadIsAttached() | |||||
| { | |||||
| #if JUCE_MAC | |||||
| if (Thread::getCurrentThreadId() != lastThreadId) | |||||
| EnterMoviesOnThread (0); | |||||
| AttachMovieToCurrentThread (movie); | |||||
| #endif | |||||
| } | |||||
| void detachThread() | |||||
| { | |||||
| #if JUCE_MAC | |||||
| DetachMovieFromCurrentThread (movie); | |||||
| #endif | |||||
| } | |||||
| }; | |||||
| //============================================================================== | |||||
| QuickTimeAudioFormat::QuickTimeAudioFormat() | |||||
| : AudioFormat (qtFormatName, (const tchar**) extensions) | |||||
| { | |||||
| } | |||||
| QuickTimeAudioFormat::~QuickTimeAudioFormat() | |||||
| { | |||||
| } | |||||
| const Array <int> QuickTimeAudioFormat::getPossibleSampleRates() | |||||
| { | |||||
| return Array<int>(); | |||||
| } | |||||
| const Array <int> QuickTimeAudioFormat::getPossibleBitDepths() | |||||
| { | |||||
| return Array<int>(); | |||||
| } | |||||
| bool QuickTimeAudioFormat::canDoStereo() | |||||
| { | |||||
| return true; | |||||
| } | |||||
| bool QuickTimeAudioFormat::canDoMono() | |||||
| { | |||||
| return true; | |||||
| } | |||||
| //============================================================================== | |||||
| AudioFormatReader* QuickTimeAudioFormat::createReaderFor (InputStream* sourceStream, | |||||
| const bool deleteStreamIfOpeningFails) | |||||
| { | |||||
| QTAudioReader* r = new QTAudioReader (sourceStream, 0); | |||||
| if (! r->ok) | |||||
| { | |||||
| if (! deleteStreamIfOpeningFails) | |||||
| r->input = 0; | |||||
| deleteAndZero (r); | |||||
| } | |||||
| return r; | |||||
| } | |||||
| AudioFormatWriter* QuickTimeAudioFormat::createWriterFor (OutputStream* /*streamToWriteTo*/, | |||||
| double /*sampleRateToUse*/, | |||||
| unsigned int /*numberOfChannels*/, | |||||
| int /*bitsPerSample*/, | |||||
| const StringPairArray& /*metadataValues*/, | |||||
| int /*qualityOptionIndex*/) | |||||
| { | |||||
| jassertfalse // not yet implemented! | |||||
| return 0; | |||||
| } | |||||
| END_JUCE_NAMESPACE | |||||
| #endif | |||||
| @@ -332,7 +332,7 @@ public: | |||||
| void setNoteStealingEnabled (const bool shouldStealNotes); | void setNoteStealingEnabled (const bool shouldStealNotes); | ||||
| /** Returns true if note-stealing is enabled. | /** Returns true if note-stealing is enabled. | ||||
| @see setNoteStealingEnabled | |||||
| @see setNoteStealingEnabled | |||||
| */ | */ | ||||
| bool isNoteStealingEnabled() const throw() { return shouldStealNotes; } | bool isNoteStealingEnabled() const throw() { return shouldStealNotes; } | ||||
| @@ -465,7 +465,7 @@ protected: | |||||
| /** Starts a specified voice playing a particular sound. | /** Starts a specified voice playing a particular sound. | ||||
| You'll probably never need to call this, it's used internally by noteOn(), but | |||||
| You'll probably never need to call this, it's used internally by noteOn(), but | |||||
| may be needed by subclasses for custom behaviours. | may be needed by subclasses for custom behaviours. | ||||
| */ | */ | ||||
| void startVoice (SynthesiserVoice* const voice, | void startVoice (SynthesiserVoice* const voice, | ||||
| @@ -160,10 +160,10 @@ const String InterprocessConnection::getConnectedHostName() const | |||||
| return "localhost"; | return "localhost"; | ||||
| } | } | ||||
| else if (socket != 0) | else if (socket != 0) | ||||
| { | |||||
| { | |||||
| if (! socket->isLocal()) | if (! socket->isLocal()) | ||||
| return socket->getHostName(); | return socket->getHostName(); | ||||
| return "localhost"; | return "localhost"; | ||||
| } | } | ||||
| @@ -139,8 +139,8 @@ public: | |||||
| NamedPipe* getPipe() const throw() { return pipe; } | NamedPipe* getPipe() const throw() { return pipe; } | ||||
| /** Returns the name of the machine at the other end of this connection. | /** Returns the name of the machine at the other end of this connection. | ||||
| This will return an empty string if the other machine isn't known for | |||||
| This will return an empty string if the other machine isn't known for | |||||
| some reason. | some reason. | ||||
| */ | */ | ||||
| const String getConnectedHostName() const; | const String getConnectedHostName() const; | ||||
| @@ -103,11 +103,11 @@ void ProgressBar::timerCallback() | |||||
| { | { | ||||
| double newProgress = progress; | double newProgress = progress; | ||||
| if (currentValue != newProgress | |||||
| if (currentValue != newProgress | |||||
| || newProgress < 0 || newProgress >= 1.0 | || newProgress < 0 || newProgress >= 1.0 | ||||
| || currentMessage != displayedMessage) | || currentMessage != displayedMessage) | ||||
| { | { | ||||
| if (currentValue < newProgress | |||||
| if (currentValue < newProgress | |||||
| && newProgress >= 0 && newProgress < 1.0 | && newProgress >= 0 && newProgress < 1.0 | ||||
| && currentValue >= 0 && newProgress < 1.0) | && currentValue >= 0 && newProgress < 1.0) | ||||
| { | { | ||||
| @@ -1206,7 +1206,7 @@ void Slider::mouseDrag (const MouseEvent& e) | |||||
| double scaledMousePos = (mousePos - sliderRegionStart) / (double) sliderRegionSize; | double scaledMousePos = (mousePos - sliderRegionStart) / (double) sliderRegionSize; | ||||
| if (style == RotaryHorizontalDrag | |||||
| if (style == RotaryHorizontalDrag | |||||
| || style == RotaryVerticalDrag | || style == RotaryVerticalDrag | ||||
| || style == IncDecButtons | || style == IncDecButtons | ||||
| || ((style == LinearHorizontal || style == LinearVertical || style == LinearBar) | || ((style == LinearHorizontal || style == LinearVertical || style == LinearBar) | ||||
| @@ -2213,7 +2213,7 @@ void TextEditor::insert (const String& text, | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| repaintText (insertIndex, -1); // must do this before and after changing the data, in case | |||||
| repaintText (insertIndex, -1); // must do this before and after changing the data, in case | |||||
| // a line gets moved due to word wrap | // a line gets moved due to word wrap | ||||
| int index = 0; | int index = 0; | ||||
| @@ -538,8 +538,8 @@ void LookAndFeel::drawProgressBar (Graphics& g, ProgressBar& progressBar, | |||||
| Path p; | Path p; | ||||
| for (float x = (float) (stripeWidth - position); x < width + stripeWidth; x += stripeWidth) | for (float x = (float) (stripeWidth - position); x < width + stripeWidth; x += stripeWidth) | ||||
| p.addQuadrilateral (x, 0.0f, | |||||
| x + stripeWidth * 0.5f, 0.0f, | |||||
| p.addQuadrilateral (x, 0.0f, | |||||
| x + stripeWidth * 0.5f, 0.0f, | |||||
| x, (float) height, | x, (float) height, | ||||
| x - stripeWidth * 0.5f, (float) height); | x - stripeWidth * 0.5f, (float) height); | ||||
| @@ -1083,7 +1083,7 @@ void LookAndFeel::drawMenuBarItem (Graphics& g, | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| void LookAndFeel::fillTextEditorBackground (Graphics& g, int /*width*/, int /*height*/, | |||||
| void LookAndFeel::fillTextEditorBackground (Graphics& g, int /*width*/, int /*height*/, | |||||
| TextEditor& textEditor) | TextEditor& textEditor) | ||||
| { | { | ||||
| g.fillAll (textEditor.findColour (TextEditor::backgroundColourId)); | g.fillAll (textEditor.findColour (TextEditor::backgroundColourId)); | ||||
| @@ -169,7 +169,7 @@ public: | |||||
| /** Draws a progress bar. | /** Draws a progress bar. | ||||
| If the progress value is less than 0 or greater than 1.0, this should draw a spinning | If the progress value is less than 0 or greater than 1.0, this should draw a spinning | ||||
| bar that fills the whole space (i.e. to say that the app is still busy but the progress | |||||
| bar that fills the whole space (i.e. to say that the app is still busy but the progress | |||||
| isn't known). It can use the current time as a basis for playing an animation. | isn't known). It can use the current time as a basis for playing an animation. | ||||
| (Used by progress bars in AlertWindow). | (Used by progress bars in AlertWindow). | ||||
| @@ -986,7 +986,7 @@ static bool openMovie (QTNewMoviePropertyElement* props, int prop, Movie& movie) | |||||
| jassert (prop <= 5); | jassert (prop <= 5); | ||||
| OSStatus err = NewMovieFromProperties (prop, props, 0, 0, &movie); | OSStatus err = NewMovieFromProperties (prop, props, 0, 0, &movie); | ||||
| return err == noErr; | return err == noErr; | ||||
| } | } | ||||
| @@ -1015,7 +1015,7 @@ bool juce_OpenQuickTimeMovieFromStream (InputStream* input, Movie& movie, Handle | |||||
| { | { | ||||
| CFStringRef filePath = juceStringToCFString (fin->getFile().getFullPathName()); | CFStringRef filePath = juceStringToCFString (fin->getFile().getFullPathName()); | ||||
| QTNewDataReferenceFromFullPathCFString (filePath, (QTPathStyle) kQTNativeDefaultPathStyle, 0, | |||||
| QTNewDataReferenceFromFullPathCFString (filePath, (QTPathStyle) kQTNativeDefaultPathStyle, 0, | |||||
| &dr.dataRef, &dr.dataRefType); | &dr.dataRef, &dr.dataRefType); | ||||
| @@ -1039,7 +1039,7 @@ bool juce_OpenQuickTimeMovieFromStream (InputStream* input, Movie& movie, Handle | |||||
| // different types to get QT to try. (We should really be a bit smarter here by | // different types to get QT to try. (We should really be a bit smarter here by | ||||
| // working out in advance which one the stream contains, rather than just trying | // working out in advance which one the stream contains, rather than just trying | ||||
| // each one) | // each one) | ||||
| const char* const suffixesToTry[] = { "\04.mov", "\04.mp3", | |||||
| const char* const suffixesToTry[] = { "\04.mov", "\04.mp3", | |||||
| "\04.avi", "\04.m4a" }; | "\04.avi", "\04.m4a" }; | ||||
| for (int i = 0; i < numElementsInArray (suffixesToTry) && ! ok; ++i) | for (int i = 0; i < numElementsInArray (suffixesToTry) && ! ok; ++i) | ||||
| @@ -198,7 +198,7 @@ public: | |||||
| /** @internal */ | /** @internal */ | ||||
| void resized(); | void resized(); | ||||
| #endif | #endif | ||||
| juce_UseDebuggingNewOperator | juce_UseDebuggingNewOperator | ||||
| private: | private: | ||||
| @@ -1,365 +1,365 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| 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 __JUCE_PLATFORMDEFS_JUCEHEADER__ | |||||
| #define __JUCE_PLATFORMDEFS_JUCEHEADER__ | |||||
| //============================================================================== | |||||
| /* This file figures out which platform is being built, and defines some macros | |||||
| that the rest of the code can use for OS-specific compilation. | |||||
| Macros that will be set here are: | |||||
| - One of JUCE_WIN32, JUCE_MAC or JUCE_LINUX. | |||||
| - Either JUCE_32BIT or JUCE_64BIT, depending on the architecture. | |||||
| - Either JUCE_LITTLE_ENDIAN or JUCE_BIG_ENDIAN. | |||||
| - Either JUCE_INTEL or JUCE_PPC | |||||
| - Either JUCE_GCC or JUCE_MSVC | |||||
| On the Mac, it also defines MACOS_10_2_OR_EARLIER if the build is targeting OSX10.2, | |||||
| and MACOS_10_3_OR_EARLIER if it is targeting either 10.2 or 10.3 | |||||
| It also includes a set of macros for debug console output and assertions. | |||||
| */ | |||||
| //============================================================================== | |||||
| #if (defined (_WIN32) || defined (_WIN64)) | |||||
| #define JUCE_WIN32 1 | |||||
| #else | |||||
| #ifdef LINUX | |||||
| #define JUCE_LINUX 1 | |||||
| #else | |||||
| #define JUCE_MAC 1 | |||||
| #endif | |||||
| #endif | |||||
| //============================================================================== | |||||
| #if JUCE_WIN32 | |||||
| #ifdef _MSC_VER | |||||
| #ifdef _WIN64 | |||||
| #define JUCE_64BIT 1 | |||||
| #else | |||||
| #define JUCE_32BIT 1 | |||||
| #endif | |||||
| #endif | |||||
| #ifdef _DEBUG | |||||
| #define JUCE_DEBUG 1 | |||||
| #endif | |||||
| /** If defined, this indicates that the processor is little-endian. */ | |||||
| #define JUCE_LITTLE_ENDIAN 1 | |||||
| #define JUCE_INTEL 1 | |||||
| #endif | |||||
| //============================================================================== | |||||
| #if JUCE_MAC | |||||
| #include <CoreServices/CoreServices.h> | |||||
| #ifndef NDEBUG | |||||
| #define JUCE_DEBUG 1 | |||||
| #endif | |||||
| #ifdef __LITTLE_ENDIAN__ | |||||
| #define JUCE_LITTLE_ENDIAN 1 | |||||
| #else | |||||
| #define JUCE_BIG_ENDIAN 1 | |||||
| #endif | |||||
| #if defined (__ppc__) || defined (__ppc64__) | |||||
| #define JUCE_PPC 1 | |||||
| #else | |||||
| #define JUCE_INTEL 1 | |||||
| #endif | |||||
| #ifdef __LP64__ | |||||
| #define JUCE_64BIT 1 | |||||
| #else | |||||
| #define JUCE_32BIT 1 | |||||
| #endif | |||||
| #if (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_3) | |||||
| #define MACOS_10_2_OR_EARLIER 1 | |||||
| #endif | |||||
| #if (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4) | |||||
| #define MACOS_10_3_OR_EARLIER 1 | |||||
| #endif | |||||
| #endif | |||||
| //============================================================================== | |||||
| #if JUCE_LINUX | |||||
| #ifdef _DEBUG | |||||
| #define JUCE_DEBUG 1 | |||||
| #endif | |||||
| // Allow override for big-endian Linux platforms | |||||
| #ifndef JUCE_BIG_ENDIAN | |||||
| #define JUCE_LITTLE_ENDIAN 1 | |||||
| #endif | |||||
| #if defined (__LP64__) || defined (_LP64) | |||||
| #define JUCE_64BIT 1 | |||||
| #else | |||||
| #define JUCE_32BIT 1 | |||||
| #endif | |||||
| #define JUCE_INTEL 1 | |||||
| #endif | |||||
| //============================================================================== | |||||
| #ifdef JUCE_FORCE_DEBUG | |||||
| #undef JUCE_DEBUG | |||||
| #if JUCE_FORCE_DEBUG | |||||
| #define JUCE_DEBUG 1 | |||||
| #endif | |||||
| #endif | |||||
| //============================================================================== | |||||
| // Compiler type macros. | |||||
| #ifdef __GNUC__ | |||||
| #define JUCE_GCC 1 | |||||
| #elif defined (_MSC_VER) | |||||
| #define JUCE_MSVC 1 | |||||
| #if _MSC_VER >= 1400 | |||||
| #define JUCE_USE_INTRINSICS 1 | |||||
| #endif | |||||
| #else | |||||
| #error unknown compiler | |||||
| #endif | |||||
| /** This macro defines the C calling convention used as the standard for Juce calls. */ | |||||
| #if JUCE_MSVC | |||||
| #define JUCE_CALLTYPE __stdcall | |||||
| #else | |||||
| #define JUCE_CALLTYPE | |||||
| #endif | |||||
| //============================================================================== | |||||
| // Debugging and assertion macros | |||||
| // (For info about JUCE_LOG_ASSERTIONS, have a look in juce_Config.h) | |||||
| #if JUCE_LOG_ASSERTIONS | |||||
| #define juce_LogCurrentAssertion juce_LogAssertion (__FILE__, __LINE__); | |||||
| #elif defined (JUCE_DEBUG) | |||||
| #define juce_LogCurrentAssertion fprintf (stderr, "JUCE Assertion failure in %s, line %d\n", __FILE__, __LINE__); | |||||
| #else | |||||
| #define juce_LogCurrentAssertion | |||||
| #endif | |||||
| #ifdef JUCE_DEBUG | |||||
| //============================================================================== | |||||
| // If debugging is enabled.. | |||||
| /** Writes a string to the standard error stream. | |||||
| This is only compiled in a debug build. | |||||
| @see Logger::outputDebugString | |||||
| */ | |||||
| #define DBG(dbgtext) Logger::outputDebugString (dbgtext); | |||||
| /** Printf's a string to the standard error stream. | |||||
| This is only compiled in a debug build. | |||||
| @see Logger::outputDebugString | |||||
| */ | |||||
| #define DBG_PRINTF(dbgprintf) Logger::outputDebugPrintf dbgprintf; | |||||
| //============================================================================== | |||||
| // Assertions.. | |||||
| #if JUCE_WIN32 || DOXYGEN | |||||
| #if JUCE_USE_INTRINSICS | |||||
| #pragma intrinsic (__debugbreak) | |||||
| /** This will try to break the debugger if one is currently hosting this app. | |||||
| @see jassert() | |||||
| */ | |||||
| #define juce_breakDebugger __debugbreak(); | |||||
| #elif JUCE_GCC | |||||
| /** This will try to break the debugger if one is currently hosting this app. | |||||
| @see jassert() | |||||
| */ | |||||
| #define juce_breakDebugger asm("int $3"); | |||||
| #else | |||||
| /** This will try to break the debugger if one is currently hosting this app. | |||||
| @see jassert() | |||||
| */ | |||||
| #define juce_breakDebugger { __asm int 3 } | |||||
| #endif | |||||
| #elif JUCE_MAC | |||||
| #define juce_breakDebugger Debugger(); | |||||
| #elif JUCE_LINUX | |||||
| #define juce_breakDebugger kill (0, SIGTRAP); | |||||
| #endif | |||||
| //============================================================================== | |||||
| /** This will always cause an assertion failure. | |||||
| It is only compiled in a debug build, (unless JUCE_LOG_ASSERTIONS is enabled | |||||
| in juce_Config.h). | |||||
| @see jassert() | |||||
| */ | |||||
| #define jassertfalse { juce_LogCurrentAssertion; if (JUCE_NAMESPACE::juce_isRunningUnderDebugger()) juce_breakDebugger; } | |||||
| //============================================================================== | |||||
| /** Platform-independent assertion macro. | |||||
| This gets optimised out when not being built with debugging turned on. | |||||
| Be careful not to call any functions within its arguments that are vital to | |||||
| the behaviour of the program, because these won't get called in the release | |||||
| build. | |||||
| @see jassertfalse | |||||
| */ | |||||
| #define jassert(expression) { if (! (expression)) jassertfalse } | |||||
| #else | |||||
| //============================================================================== | |||||
| // If debugging is disabled, these dummy debug and assertion macros are used.. | |||||
| #define DBG(dbgtext) | |||||
| #define DBG_PRINTF(dbgprintf) | |||||
| #define jassertfalse { juce_LogCurrentAssertion } | |||||
| #if JUCE_LOG_ASSERTIONS | |||||
| #define jassert(expression) { if (! (expression)) jassertfalse } | |||||
| #else | |||||
| #define jassert(a) { } | |||||
| #endif | |||||
| #endif | |||||
| //============================================================================== | |||||
| #ifndef DOXYGEN | |||||
| template <bool b> struct JuceStaticAssert; | |||||
| template <> struct JuceStaticAssert <true> { static void dummy() {} }; | |||||
| #endif | |||||
| /** A compile-time assertion macro. | |||||
| If the expression parameter is false, the macro will cause a compile error. | |||||
| */ | |||||
| #define static_jassert(expression) JuceStaticAssert<expression>::dummy(); | |||||
| //============================================================================== | |||||
| #if JUCE_CATCH_UNHANDLED_EXCEPTIONS | |||||
| #define JUCE_TRY try | |||||
| /** Used in try-catch blocks, this macro will send exceptions to the JUCEApplication | |||||
| object so they can be logged by the application if it wants to. | |||||
| */ | |||||
| #define JUCE_CATCH_EXCEPTION \ | |||||
| catch (const std::exception& e) \ | |||||
| { \ | |||||
| JUCEApplication::sendUnhandledException (&e, __FILE__, __LINE__); \ | |||||
| } \ | |||||
| catch (...) \ | |||||
| { \ | |||||
| JUCEApplication::sendUnhandledException (0, __FILE__, __LINE__); \ | |||||
| } | |||||
| #define JUCE_CATCH_ALL catch (...) {} | |||||
| #define JUCE_CATCH_ALL_ASSERT catch (...) { jassertfalse } | |||||
| #else | |||||
| #define JUCE_TRY | |||||
| #define JUCE_CATCH_EXCEPTION | |||||
| #define JUCE_CATCH_ALL | |||||
| #define JUCE_CATCH_ALL_ASSERT | |||||
| #endif | |||||
| //============================================================================== | |||||
| // Macros for inlining. | |||||
| #if JUCE_MSVC | |||||
| /** A platform-independent way of forcing an inline function. | |||||
| Use the syntax: @code | |||||
| forcedinline void myfunction (int x) | |||||
| @endcode | |||||
| */ | |||||
| #ifdef JUCE_DEBUG | |||||
| #define forcedinline __forceinline | |||||
| #else | |||||
| #define forcedinline inline | |||||
| #endif | |||||
| /** A platform-independent way of stopping the compiler inlining a function. | |||||
| Use the syntax: @code | |||||
| juce_noinline void myfunction (int x) | |||||
| @endcode | |||||
| */ | |||||
| #define juce_noinline | |||||
| #else | |||||
| /** A platform-independent way of forcing an inline function. | |||||
| Use the syntax: @code | |||||
| forcedinline void myfunction (int x) | |||||
| @endcode | |||||
| */ | |||||
| #ifndef JUCE_DEBUG | |||||
| #define forcedinline inline __attribute__((always_inline)) | |||||
| #else | |||||
| #define forcedinline inline | |||||
| #endif | |||||
| /** A platform-independent way of stopping the compiler inlining a function. | |||||
| Use the syntax: @code | |||||
| juce_noinline void myfunction (int x) | |||||
| @endcode | |||||
| */ | |||||
| #define juce_noinline __attribute__((noinline)) | |||||
| #endif | |||||
| #endif // __JUCE_PLATFORMDEFS_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 __JUCE_PLATFORMDEFS_JUCEHEADER__ | |||||
| #define __JUCE_PLATFORMDEFS_JUCEHEADER__ | |||||
| //============================================================================== | |||||
| /* This file figures out which platform is being built, and defines some macros | |||||
| that the rest of the code can use for OS-specific compilation. | |||||
| Macros that will be set here are: | |||||
| - One of JUCE_WIN32, JUCE_MAC or JUCE_LINUX. | |||||
| - Either JUCE_32BIT or JUCE_64BIT, depending on the architecture. | |||||
| - Either JUCE_LITTLE_ENDIAN or JUCE_BIG_ENDIAN. | |||||
| - Either JUCE_INTEL or JUCE_PPC | |||||
| - Either JUCE_GCC or JUCE_MSVC | |||||
| On the Mac, it also defines MACOS_10_2_OR_EARLIER if the build is targeting OSX10.2, | |||||
| and MACOS_10_3_OR_EARLIER if it is targeting either 10.2 or 10.3 | |||||
| It also includes a set of macros for debug console output and assertions. | |||||
| */ | |||||
| //============================================================================== | |||||
| #if (defined (_WIN32) || defined (_WIN64)) | |||||
| #define JUCE_WIN32 1 | |||||
| #else | |||||
| #ifdef LINUX | |||||
| #define JUCE_LINUX 1 | |||||
| #else | |||||
| #define JUCE_MAC 1 | |||||
| #endif | |||||
| #endif | |||||
| //============================================================================== | |||||
| #if JUCE_WIN32 | |||||
| #ifdef _MSC_VER | |||||
| #ifdef _WIN64 | |||||
| #define JUCE_64BIT 1 | |||||
| #else | |||||
| #define JUCE_32BIT 1 | |||||
| #endif | |||||
| #endif | |||||
| #ifdef _DEBUG | |||||
| #define JUCE_DEBUG 1 | |||||
| #endif | |||||
| /** If defined, this indicates that the processor is little-endian. */ | |||||
| #define JUCE_LITTLE_ENDIAN 1 | |||||
| #define JUCE_INTEL 1 | |||||
| #endif | |||||
| //============================================================================== | |||||
| #if JUCE_MAC | |||||
| #include <CoreServices/CoreServices.h> | |||||
| #ifndef NDEBUG | |||||
| #define JUCE_DEBUG 1 | |||||
| #endif | |||||
| #ifdef __LITTLE_ENDIAN__ | |||||
| #define JUCE_LITTLE_ENDIAN 1 | |||||
| #else | |||||
| #define JUCE_BIG_ENDIAN 1 | |||||
| #endif | |||||
| #if defined (__ppc__) || defined (__ppc64__) | |||||
| #define JUCE_PPC 1 | |||||
| #else | |||||
| #define JUCE_INTEL 1 | |||||
| #endif | |||||
| #ifdef __LP64__ | |||||
| #define JUCE_64BIT 1 | |||||
| #else | |||||
| #define JUCE_32BIT 1 | |||||
| #endif | |||||
| #if (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_3) | |||||
| #define MACOS_10_2_OR_EARLIER 1 | |||||
| #endif | |||||
| #if (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4) | |||||
| #define MACOS_10_3_OR_EARLIER 1 | |||||
| #endif | |||||
| #endif | |||||
| //============================================================================== | |||||
| #if JUCE_LINUX | |||||
| #ifdef _DEBUG | |||||
| #define JUCE_DEBUG 1 | |||||
| #endif | |||||
| // Allow override for big-endian Linux platforms | |||||
| #ifndef JUCE_BIG_ENDIAN | |||||
| #define JUCE_LITTLE_ENDIAN 1 | |||||
| #endif | |||||
| #if defined (__LP64__) || defined (_LP64) | |||||
| #define JUCE_64BIT 1 | |||||
| #else | |||||
| #define JUCE_32BIT 1 | |||||
| #endif | |||||
| #define JUCE_INTEL 1 | |||||
| #endif | |||||
| //============================================================================== | |||||
| #ifdef JUCE_FORCE_DEBUG | |||||
| #undef JUCE_DEBUG | |||||
| #if JUCE_FORCE_DEBUG | |||||
| #define JUCE_DEBUG 1 | |||||
| #endif | |||||
| #endif | |||||
| //============================================================================== | |||||
| // Compiler type macros. | |||||
| #ifdef __GNUC__ | |||||
| #define JUCE_GCC 1 | |||||
| #elif defined (_MSC_VER) | |||||
| #define JUCE_MSVC 1 | |||||
| #if _MSC_VER >= 1400 | |||||
| #define JUCE_USE_INTRINSICS 1 | |||||
| #endif | |||||
| #else | |||||
| #error unknown compiler | |||||
| #endif | |||||
| /** This macro defines the C calling convention used as the standard for Juce calls. */ | |||||
| #if JUCE_MSVC | |||||
| #define JUCE_CALLTYPE __stdcall | |||||
| #else | |||||
| #define JUCE_CALLTYPE | |||||
| #endif | |||||
| //============================================================================== | |||||
| // Debugging and assertion macros | |||||
| // (For info about JUCE_LOG_ASSERTIONS, have a look in juce_Config.h) | |||||
| #if JUCE_LOG_ASSERTIONS | |||||
| #define juce_LogCurrentAssertion juce_LogAssertion (__FILE__, __LINE__); | |||||
| #elif defined (JUCE_DEBUG) | |||||
| #define juce_LogCurrentAssertion fprintf (stderr, "JUCE Assertion failure in %s, line %d\n", __FILE__, __LINE__); | |||||
| #else | |||||
| #define juce_LogCurrentAssertion | |||||
| #endif | |||||
| #ifdef JUCE_DEBUG | |||||
| //============================================================================== | |||||
| // If debugging is enabled.. | |||||
| /** Writes a string to the standard error stream. | |||||
| This is only compiled in a debug build. | |||||
| @see Logger::outputDebugString | |||||
| */ | |||||
| #define DBG(dbgtext) Logger::outputDebugString (dbgtext); | |||||
| /** Printf's a string to the standard error stream. | |||||
| This is only compiled in a debug build. | |||||
| @see Logger::outputDebugString | |||||
| */ | |||||
| #define DBG_PRINTF(dbgprintf) Logger::outputDebugPrintf dbgprintf; | |||||
| //============================================================================== | |||||
| // Assertions.. | |||||
| #if JUCE_WIN32 || DOXYGEN | |||||
| #if JUCE_USE_INTRINSICS | |||||
| #pragma intrinsic (__debugbreak) | |||||
| /** This will try to break the debugger if one is currently hosting this app. | |||||
| @see jassert() | |||||
| */ | |||||
| #define juce_breakDebugger __debugbreak(); | |||||
| #elif JUCE_GCC | |||||
| /** This will try to break the debugger if one is currently hosting this app. | |||||
| @see jassert() | |||||
| */ | |||||
| #define juce_breakDebugger asm("int $3"); | |||||
| #else | |||||
| /** This will try to break the debugger if one is currently hosting this app. | |||||
| @see jassert() | |||||
| */ | |||||
| #define juce_breakDebugger { __asm int 3 } | |||||
| #endif | |||||
| #elif JUCE_MAC | |||||
| #define juce_breakDebugger Debugger(); | |||||
| #elif JUCE_LINUX | |||||
| #define juce_breakDebugger kill (0, SIGTRAP); | |||||
| #endif | |||||
| //============================================================================== | |||||
| /** This will always cause an assertion failure. | |||||
| It is only compiled in a debug build, (unless JUCE_LOG_ASSERTIONS is enabled | |||||
| in juce_Config.h). | |||||
| @see jassert() | |||||
| */ | |||||
| #define jassertfalse { juce_LogCurrentAssertion; if (JUCE_NAMESPACE::juce_isRunningUnderDebugger()) juce_breakDebugger; } | |||||
| //============================================================================== | |||||
| /** Platform-independent assertion macro. | |||||
| This gets optimised out when not being built with debugging turned on. | |||||
| Be careful not to call any functions within its arguments that are vital to | |||||
| the behaviour of the program, because these won't get called in the release | |||||
| build. | |||||
| @see jassertfalse | |||||
| */ | |||||
| #define jassert(expression) { if (! (expression)) jassertfalse } | |||||
| #else | |||||
| //============================================================================== | |||||
| // If debugging is disabled, these dummy debug and assertion macros are used.. | |||||
| #define DBG(dbgtext) | |||||
| #define DBG_PRINTF(dbgprintf) | |||||
| #define jassertfalse { juce_LogCurrentAssertion } | |||||
| #if JUCE_LOG_ASSERTIONS | |||||
| #define jassert(expression) { if (! (expression)) jassertfalse } | |||||
| #else | |||||
| #define jassert(a) { } | |||||
| #endif | |||||
| #endif | |||||
| //============================================================================== | |||||
| #ifndef DOXYGEN | |||||
| template <bool b> struct JuceStaticAssert; | |||||
| template <> struct JuceStaticAssert <true> { static void dummy() {} }; | |||||
| #endif | |||||
| /** A compile-time assertion macro. | |||||
| If the expression parameter is false, the macro will cause a compile error. | |||||
| */ | |||||
| #define static_jassert(expression) JuceStaticAssert<expression>::dummy(); | |||||
| //============================================================================== | |||||
| #if JUCE_CATCH_UNHANDLED_EXCEPTIONS | |||||
| #define JUCE_TRY try | |||||
| /** Used in try-catch blocks, this macro will send exceptions to the JUCEApplication | |||||
| object so they can be logged by the application if it wants to. | |||||
| */ | |||||
| #define JUCE_CATCH_EXCEPTION \ | |||||
| catch (const std::exception& e) \ | |||||
| { \ | |||||
| JUCEApplication::sendUnhandledException (&e, __FILE__, __LINE__); \ | |||||
| } \ | |||||
| catch (...) \ | |||||
| { \ | |||||
| JUCEApplication::sendUnhandledException (0, __FILE__, __LINE__); \ | |||||
| } | |||||
| #define JUCE_CATCH_ALL catch (...) {} | |||||
| #define JUCE_CATCH_ALL_ASSERT catch (...) { jassertfalse } | |||||
| #else | |||||
| #define JUCE_TRY | |||||
| #define JUCE_CATCH_EXCEPTION | |||||
| #define JUCE_CATCH_ALL | |||||
| #define JUCE_CATCH_ALL_ASSERT | |||||
| #endif | |||||
| //============================================================================== | |||||
| // Macros for inlining. | |||||
| #if JUCE_MSVC | |||||
| /** A platform-independent way of forcing an inline function. | |||||
| Use the syntax: @code | |||||
| forcedinline void myfunction (int x) | |||||
| @endcode | |||||
| */ | |||||
| #ifdef JUCE_DEBUG | |||||
| #define forcedinline __forceinline | |||||
| #else | |||||
| #define forcedinline inline | |||||
| #endif | |||||
| /** A platform-independent way of stopping the compiler inlining a function. | |||||
| Use the syntax: @code | |||||
| juce_noinline void myfunction (int x) | |||||
| @endcode | |||||
| */ | |||||
| #define juce_noinline | |||||
| #else | |||||
| /** A platform-independent way of forcing an inline function. | |||||
| Use the syntax: @code | |||||
| forcedinline void myfunction (int x) | |||||
| @endcode | |||||
| */ | |||||
| #ifndef JUCE_DEBUG | |||||
| #define forcedinline inline __attribute__((always_inline)) | |||||
| #else | |||||
| #define forcedinline inline | |||||
| #endif | |||||
| /** A platform-independent way of stopping the compiler inlining a function. | |||||
| Use the syntax: @code | |||||
| juce_noinline void myfunction (int x) | |||||
| @endcode | |||||
| */ | |||||
| #define juce_noinline __attribute__((noinline)) | |||||
| #endif | |||||
| #endif // __JUCE_PLATFORMDEFS_JUCEHEADER__ | |||||
| @@ -346,7 +346,7 @@ public: | |||||
| bool setReadOnly (const bool shouldBeReadOnly, | bool setReadOnly (const bool shouldBeReadOnly, | ||||
| const bool applyRecursively = false) const throw(); | const bool applyRecursively = false) const throw(); | ||||
| /** Returns true if this file is a hidden or system file. | |||||
| /** Returns true if this file is a hidden or system file. | |||||
| The criteria for deciding whether a file is hidden are platform-dependent. | The criteria for deciding whether a file is hidden are platform-dependent. | ||||
| */ | */ | ||||