1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-16 00:34:19 +00:00

Minor clean-ups and tweaks to AudioProcessorGraph, TreeView.

This commit is contained in:
Julian Storer 2010-12-10 21:25:07 +00:00
parent 897c3e1fa7
commit 709f573997
19 changed files with 1976 additions and 2035 deletions

View file

@ -68,34 +68,116 @@ bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAdd
return false;
}
//==============================================================================
/** A HTTP input stream that uses sockets.
*/
class JUCE_HTTPSocketStream
class WebInputStream : public InputStream
{
public:
//==============================================================================
JUCE_HTTPSocketStream()
: readPosition (0),
socketHandle (-1),
levelsOfRedirection (0),
timeoutSeconds (15)
WebInputStream (const String& address_, bool isPost_, const MemoryBlock& postData_,
URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
const String& headers_, int timeOutMs_, StringPairArray* responseHeaders)
: socketHandle (-1), levelsOfRedirection (0),
address (address_), headers (headers_), postData (postData_), position (0),
finished (false), isPost (isPost_), timeOutMs (timeOutMs_)
{
createConnection (progressCallback, progressCallbackContext);
if (responseHeaders != 0 && ! isError())
{
for (int i = 0; i < headerLines.size(); ++i)
{
const String& headersEntry = headerLines[i];
const String key (headersEntry.upToFirstOccurrenceOf (": ", false, false));
const String value (headersEntry.fromFirstOccurrenceOf (": ", false, false));
const String previousValue ((*responseHeaders) [key]);
responseHeaders->set (key, previousValue.isEmpty() ? value : (previousValue + "," + value));
}
}
}
~JUCE_HTTPSocketStream()
~WebInputStream()
{
closeSocket();
}
//==============================================================================
bool open (const String& url,
const String& headers,
const MemoryBlock& postData,
const bool isPost,
URL::OpenStreamProgressCallback* callback,
void* callbackContext,
int timeOutMs)
bool isError() const { return socketHandle < 0; }
bool isExhausted() { return finished; }
int64 getPosition() { return position; }
int64 getTotalLength()
{
jassertfalse; //xxx to do
return -1;
}
int read (void* buffer, int bytesToRead)
{
if (finished || isError())
return 0;
fd_set readbits;
FD_ZERO (&readbits);
FD_SET (socketHandle, &readbits);
struct timeval tv;
tv.tv_sec = jmax (1, timeOutMs / 1000);
tv.tv_usec = 0;
if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0)
return 0; // (timeout)
const int bytesRead = jmax (0, (int) recv (socketHandle, buffer, bytesToRead, MSG_WAITALL));
if (bytesRead == 0)
finished = true;
position += bytesRead;
return bytesRead;
}
bool setPosition (int64 wantedPos)
{
if (isError())
return false;
if (wantedPos != position)
{
finished = false;
if (wantedPos < position)
{
closeSocket();
position = 0;
createConnection (0, 0);
}
skipNextBytes (wantedPos - position);
}
return true;
}
//==============================================================================
private:
int socketHandle, levelsOfRedirection;
StringArray headerLines;
String address, headers;
MemoryBlock postData;
int64 position;
bool finished;
const bool isPost;
const int timeOutMs;
void closeSocket()
{
if (socketHandle >= 0)
close (socketHandle);
socketHandle = -1;
levelsOfRedirection = 0;
}
void createConnection (URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext)
{
closeSocket();
@ -110,9 +192,8 @@ public:
String hostName, hostPath;
int hostPort;
if (! decomposeURL (url, hostName, hostPath, hostPort))
return false;
if (! decomposeURL (address, hostName, hostPath, hostPort))
return;
const struct hostent* host = 0;
int port = 0;
@ -124,7 +205,7 @@ public:
if (proxyURL.startsWithIgnoreCase ("http://"))
{
if (! decomposeURL (proxyURL, proxyName, proxyPath, proxyPort))
return false;
return;
host = gethostbyname (proxyName.toUTF8());
port = proxyPort;
@ -136,64 +217,47 @@ public:
}
if (host == 0)
return false;
return;
struct sockaddr_in address;
zerostruct (address);
memcpy (&address.sin_addr, host->h_addr, host->h_length);
address.sin_family = host->h_addrtype;
address.sin_port = htons (port);
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;
}
struct sockaddr_in socketAddress;
zerostruct (socketAddress);
memcpy (&socketAddress.sin_addr, host->h_addr, host->h_length);
socketAddress.sin_family = host->h_addrtype;
socketAddress.sin_port = htons (port);
const MemoryBlock requestHeader (createRequestHeader (hostName, hostPort, proxyName, proxyPort,
hostPath, url, headers, postData, isPost));
size_t totalHeaderSent = 0;
socketHandle = socket (host->h_addrtype, SOCK_STREAM, 0);
while (totalHeaderSent < requestHeader.getSize())
{
if (Time::getMillisecondCounter() > timeOutTime)
if (socketHandle == -1)
return;
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*) &socketAddress, sizeof (socketAddress)) == -1)
{
closeSocket();
return false;
}
const int numToSend = jmin (1024, (int) (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;
return;
}
}
const String responseHeader (readResponse (timeOutTime));
{
const MemoryBlock requestHeader (createRequestHeader (hostName, hostPort, proxyName, proxyPort,
hostPath, address, headers, postData, isPost));
if (! sendHeader (socketHandle, requestHeader, timeOutTime, progressCallback, progressCallbackContext))
{
closeSocket();
return;
}
}
const String responseHeader (readResponse (socketHandle, timeOutTime));
if (responseHeader.isNotEmpty())
{
@ -208,113 +272,43 @@ public:
String location (findHeaderItem (headerLines, "Location:"));
if (statusCode >= 300 && statusCode < 400
&& location.isNotEmpty())
if (statusCode >= 300 && statusCode < 400 && location.isNotEmpty())
{
if (! location.startsWithIgnoreCase ("http://"))
location = "http://" + location;
if (levelsOfRedirection++ < 3)
return open (location, headers, postData, isPost, callback, callbackContext, timeOutMs);
if (++levelsOfRedirection <= 3)
{
address = location;
createConnection (progressCallback, progressCallbackContext);
return;
}
}
else
{
levelsOfRedirection = 0;
return true;
return;
}
}
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, (int) recv (socketHandle, buffer, bytesToRead, MSG_WAITALL));
readPosition += bytesRead;
return bytesRead;
}
//==============================================================================
int readPosition;
StringArray headerLines;
//==============================================================================
private:
int socketHandle, levelsOfRedirection;
const int timeoutSeconds;
//==============================================================================
void closeSocket()
{
if (socketHandle >= 0)
close (socketHandle);
socketHandle = -1;
}
const MemoryBlock createRequestHeader (const String& hostName,
const int hostPort,
const String& proxyName,
const int proxyPort,
const String& hostPath,
const String& originalURL,
const String& headers,
const MemoryBlock& postData,
const bool isPost)
{
String header (isPost ? "POST " : "GET ");
if (proxyName.isEmpty())
{
header << hostPath << " HTTP/1.0\r\nHost: "
<< hostName << ':' << hostPort;
}
else
{
header << originalURL << " HTTP/1.0\r\nHost: "
<< proxyName << ':' << proxyPort;
}
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 (const uint32 timeOutTime)
static const String readResponse (const int socketHandle, const uint32 timeOutTime)
{
int bytesRead = 0, numConsecutiveLFs = 0;
MemoryBlock buffer (1024, true);
while (numConsecutiveLFs < 2 && bytesRead < 32768
&& Time::getMillisecondCounter() <= timeOutTime)
&& Time::getMillisecondCounter() <= timeOutTime)
{
fd_set readbits;
FD_ZERO (&readbits);
FD_SET (socketHandle, &readbits);
struct timeval tv;
tv.tv_sec = timeoutSeconds;
tv.tv_sec = jmax (1, (int) (timeOutTime - Time::getMillisecondCounter()) / 1000);
tv.tv_usec = 0;
if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0)
@ -343,9 +337,62 @@ private:
return String::empty;
}
//==============================================================================
static bool decomposeURL (const String& url,
String& host, String& path, int& port)
static const MemoryBlock createRequestHeader (const String& hostName, const int hostPort,
const String& proxyName, const int proxyPort,
const String& hostPath, const String& originalURL,
const String& headers, const MemoryBlock& postData,
const bool isPost)
{
String header (isPost ? "POST " : "GET ");
if (proxyName.isEmpty())
{
header << hostPath << " HTTP/1.0\r\nHost: "
<< hostName << ':' << hostPort;
}
else
{
header << originalURL << " HTTP/1.0\r\nHost: "
<< proxyName << ':' << proxyPort;
}
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;
}
static bool sendHeader (int socketHandle, const MemoryBlock& requestHeader, const uint32 timeOutTime,
URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext)
{
size_t totalHeaderSent = 0;
while (totalHeaderSent < requestHeader.getSize())
{
if (Time::getMillisecondCounter() > timeOutTime)
return false;
const int numToSend = jmin (1024, (int) (requestHeader.getSize() - totalHeaderSent));
if (send (socketHandle, static_cast <const char*> (requestHeader.getData()) + totalHeaderSent, numToSend, 0) != numToSend)
return false;
totalHeaderSent += numToSend;
if (progressCallback != 0 && ! progressCallback (progressCallbackContext, totalHeaderSent, requestHeader.getSize()))
return false;
}
return true;
}
static bool decomposeURL (const String& url, String& host, String& path, int& port)
{
if (! url.startsWithIgnoreCase ("http://"))
return false;
@ -382,7 +429,6 @@ private:
return true;
}
//==============================================================================
static const String findHeaderItem (const StringArray& lines, const String& itemName)
{
for (int i = 0; i < lines.size(); ++i)
@ -392,73 +438,19 @@ private:
return String::empty;
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JUCE_HTTPSocketStream);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebInputStream);
};
//==============================================================================
void* juce_openInternetFile (const String& url,
const String& headers,
const MemoryBlock& postData,
const bool isPost,
URL::OpenStreamProgressCallback* callback,
void* callbackContext,
int timeOutMs)
InputStream* URL::createNativeStream (const String& address, bool isPost, const MemoryBlock& postData,
OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
const String& headers, const int timeOutMs, StringPairArray* responseHeaders)
{
ScopedPointer<JUCE_HTTPSocketStream> s (new JUCE_HTTPSocketStream());
ScopedPointer <WebInputStream> wi (new WebInputStream (address, isPost, postData,
progressCallback, progressCallbackContext,
headers, timeOutMs, responseHeaders));
if (s->open (url, headers, postData, isPost, callback, callbackContext, timeOutMs))
return s.release();
return 0;
return wi->isError() ? 0 : wi.release();
}
void juce_closeInternetFile (void* handle)
{
delete static_cast <JUCE_HTTPSocketStream*> (handle);
}
int juce_readFromInternetFile (void* handle, void* buffer, int bytesToRead)
{
JUCE_HTTPSocketStream* const s = static_cast <JUCE_HTTPSocketStream*> (handle);
return s != 0 ? s->read (buffer, bytesToRead) : 0;
}
int64 juce_getInternetFileContentLength (void* handle)
{
JUCE_HTTPSocketStream* const s = static_cast <JUCE_HTTPSocketStream*> (handle);
if (s != 0)
{
//xxx todo
jassertfalse
}
return -1;
}
void juce_getInternetFileHeaders (void* handle, StringPairArray& headers)
{
JUCE_HTTPSocketStream* const s = static_cast <JUCE_HTTPSocketStream*> (handle);
if (s != 0)
{
for (int i = 0; i < s->headerLines.size(); ++i)
{
const String& headersEntry = s->headerLines[i];
const String key (headersEntry.upToFirstOccurrenceOf (": ", false, false));
const String value (headersEntry.fromFirstOccurrenceOf (": ", false, false));
const String previousValue (headers [key]);
headers.set (key, previousValue.isEmpty() ? value : (previousValue + "," + value));
}
}
}
int juce_seekInInternetFile (void* handle, int newPosition)
{
JUCE_HTTPSocketStream* const s = static_cast <JUCE_HTTPSocketStream*> (handle);
return s != 0 ? s->readPosition : 0;
}
#endif