| @@ -378,7 +378,7 @@ public: | |||
| destShape.startNewSubPath (x2, y2); | |||
| } | |||
| else | |||
| else | |||
| { | |||
| 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) | |||
| { | |||
| getFindFileInfo (findData, firstResult, isDir, isHidden, fileSize, | |||
| getFindFileInfo (findData, firstResult, isDir, isHidden, fileSize, | |||
| modTime, creationTime, isReadOnly); | |||
| 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(); | |||
| if (! (cache.loadThumb (*this, newSource->hashCode()) | |||
| if (! (cache.loadThumb (*this, newSource->hashCode()) | |||
| && 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); | |||
| /** Returns true if note-stealing is enabled. | |||
| @see setNoteStealingEnabled | |||
| @see setNoteStealingEnabled | |||
| */ | |||
| bool isNoteStealingEnabled() const throw() { return shouldStealNotes; } | |||
| @@ -465,7 +465,7 @@ protected: | |||
| /** 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. | |||
| */ | |||
| void startVoice (SynthesiserVoice* const voice, | |||
| @@ -160,10 +160,10 @@ const String InterprocessConnection::getConnectedHostName() const | |||
| return "localhost"; | |||
| } | |||
| else if (socket != 0) | |||
| { | |||
| { | |||
| if (! socket->isLocal()) | |||
| return socket->getHostName(); | |||
| return "localhost"; | |||
| } | |||
| @@ -139,8 +139,8 @@ public: | |||
| NamedPipe* getPipe() const throw() { return pipe; } | |||
| /** 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. | |||
| */ | |||
| const String getConnectedHostName() const; | |||
| @@ -103,11 +103,11 @@ void ProgressBar::timerCallback() | |||
| { | |||
| double newProgress = progress; | |||
| if (currentValue != newProgress | |||
| if (currentValue != newProgress | |||
| || newProgress < 0 || newProgress >= 1.0 | |||
| || currentMessage != displayedMessage) | |||
| { | |||
| if (currentValue < newProgress | |||
| if (currentValue < newProgress | |||
| && newProgress >= 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; | |||
| if (style == RotaryHorizontalDrag | |||
| if (style == RotaryHorizontalDrag | |||
| || style == RotaryVerticalDrag | |||
| || style == IncDecButtons | |||
| || ((style == LinearHorizontal || style == LinearVertical || style == LinearBar) | |||
| @@ -2213,7 +2213,7 @@ void TextEditor::insert (const String& text, | |||
| } | |||
| 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 | |||
| int index = 0; | |||
| @@ -538,8 +538,8 @@ void LookAndFeel::drawProgressBar (Graphics& g, ProgressBar& progressBar, | |||
| Path p; | |||
| 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 - 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) | |||
| { | |||
| g.fillAll (textEditor.findColour (TextEditor::backgroundColourId)); | |||
| @@ -169,7 +169,7 @@ public: | |||
| /** Draws a progress bar. | |||
| 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. | |||
| (Used by progress bars in AlertWindow). | |||
| @@ -986,7 +986,7 @@ static bool openMovie (QTNewMoviePropertyElement* props, int prop, Movie& movie) | |||
| jassert (prop <= 5); | |||
| OSStatus err = NewMovieFromProperties (prop, props, 0, 0, &movie); | |||
| return err == noErr; | |||
| } | |||
| @@ -1015,7 +1015,7 @@ bool juce_OpenQuickTimeMovieFromStream (InputStream* input, Movie& movie, Handle | |||
| { | |||
| CFStringRef filePath = juceStringToCFString (fin->getFile().getFullPathName()); | |||
| QTNewDataReferenceFromFullPathCFString (filePath, (QTPathStyle) kQTNativeDefaultPathStyle, 0, | |||
| QTNewDataReferenceFromFullPathCFString (filePath, (QTPathStyle) kQTNativeDefaultPathStyle, 0, | |||
| &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 | |||
| // working out in advance which one the stream contains, rather than just trying | |||
| // each one) | |||
| const char* const suffixesToTry[] = { "\04.mov", "\04.mp3", | |||
| const char* const suffixesToTry[] = { "\04.mov", "\04.mp3", | |||
| "\04.avi", "\04.m4a" }; | |||
| for (int i = 0; i < numElementsInArray (suffixesToTry) && ! ok; ++i) | |||
| @@ -198,7 +198,7 @@ public: | |||
| /** @internal */ | |||
| void resized(); | |||
| #endif | |||
| juce_UseDebuggingNewOperator | |||
| 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, | |||
| 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. | |||
| */ | |||