Browse Source

tags/2021-05-28
jules 17 years ago
parent
commit
567fe9b1e7
7 changed files with 782 additions and 722 deletions
  1. +270
    -257
      build/linux/platform_specific_code/juce_linux_Network.cpp
  2. +464
    -451
      build/macosx/platform_specific_code/juce_mac_Network.mm
  3. +2
    -1
      build/win32/platform_specific_code/juce_win32_ASIO.cpp
  4. +20
    -0
      build/win32/platform_specific_code/juce_win32_Network.cpp
  5. +23
    -7
      src/juce_appframework/gui/components/controls/juce_Label.cpp
  6. +2
    -5
      src/juce_appframework/gui/components/controls/juce_Label.h
  7. +1
    -1
      src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.cpp

+ 270
- 257
build/linux/platform_specific_code/juce_linux_Network.cpp View File

@@ -104,337 +104,337 @@ bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAdd
/** A HTTP input stream that uses sockets. /** A HTTP input stream that uses sockets.
*/ */
class JUCE_HTTPSocketStream class JUCE_HTTPSocketStream
{
public:
//==============================================================================
JUCE_HTTPSocketStream()
{
public:
//==============================================================================
JUCE_HTTPSocketStream()
: readPosition (0), : readPosition (0),
socketHandle (-1),
levelsOfRedirection (0),
timeoutSeconds (15)
{
}
socketHandle (-1),
levelsOfRedirection (0),
timeoutSeconds (15)
{
}
~JUCE_HTTPSocketStream()
{
closeSocket();
}
~JUCE_HTTPSocketStream()
{
closeSocket();
}
//==============================================================================
bool open (const String& url,
const String& headers,
const MemoryBlock& postData,
const bool isPost,
URL::OpenStreamProgressCallback* callback,
void* callbackContext,
int timeOutMs)
{
closeSocket();
//==============================================================================
bool open (const String& url,
const String& headers,
const MemoryBlock& postData,
const bool isPost,
URL::OpenStreamProgressCallback* callback,
void* callbackContext,
int timeOutMs)
{
closeSocket();
uint32 timeOutTime = Time::getMillisecondCounter();
uint32 timeOutTime = Time::getMillisecondCounter();
if (timeOutMs == 0)
timeOutTime += 60000;
else if (timeOutMs < 0)
timeOutTime = 0xffffffff;
else
timeOutTime += timeOutMs;
if (timeOutMs == 0)
timeOutTime += 60000;
else if (timeOutMs < 0)
timeOutTime = 0xffffffff;
else
timeOutTime += timeOutMs;
String hostName, hostPath;
int hostPort;
String hostName, hostPath;
int hostPort;
if (! decomposeURL (url, hostName, hostPath, hostPort))
return false;
if (! decomposeURL (url, hostName, hostPath, hostPort))
return false;
const struct hostent* host = 0;
int port = 0;
const struct hostent* host = 0;
int port = 0;
String proxyName, proxyPath;
int proxyPort = 0;
String proxyName, proxyPath;
int proxyPort = 0;
String proxyURL (getenv ("http_proxy"));
if (proxyURL.startsWithIgnoreCase (T("http://")))
{
if (! decomposeURL (proxyURL, proxyName, proxyPath, proxyPort))
return false;
String proxyURL (getenv ("http_proxy"));
if (proxyURL.startsWithIgnoreCase (T("http://")))
{
if (! decomposeURL (proxyURL, proxyName, proxyPath, proxyPort))
return false;
host = gethostbyname ((const char*) proxyName.toUTF8());
port = proxyPort;
}
else
{
host = gethostbyname ((const char*) hostName.toUTF8());
port = hostPort;
}
host = gethostbyname ((const char*) proxyName.toUTF8());
port = proxyPort;
}
else
{
host = gethostbyname ((const char*) hostName.toUTF8());
port = hostPort;
}
if (host == 0)
return false;
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 (port);
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 (port);
socketHandle = socket (host->h_addrtype, SOCK_STREAM, 0);
socketHandle = socket (host->h_addrtype, SOCK_STREAM, 0);
if (socketHandle == -1)
return false;
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);
int receiveBufferSize = 16384;
setsockopt (socketHandle, SOL_SOCKET, SO_RCVBUF, (char*) &receiveBufferSize, sizeof (receiveBufferSize));
setsockopt (socketHandle, SOL_SOCKET, SO_KEEPALIVE, 0, 0);
#if JUCE_MAC #if JUCE_MAC
setsockopt (socketHandle, SOL_SOCKET, SO_NOSIGPIPE, 0, 0);
setsockopt (socketHandle, SOL_SOCKET, SO_NOSIGPIPE, 0, 0);
#endif #endif
if (connect (socketHandle, (struct sockaddr*) &address, sizeof (address)) == -1)
if (connect (socketHandle, (struct sockaddr*) &address, sizeof (address)) == -1)
{
closeSocket();
return false;
}
const MemoryBlock requestHeader (createRequestHeader (hostName, hostPort,
proxyName, proxyPort,
hostPath, url,
headers, postData,
isPost));
int totalHeaderSent = 0;
while (totalHeaderSent < requestHeader.getSize())
{
if (Time::getMillisecondCounter() > timeOutTime)
{ {
closeSocket(); closeSocket();
return false; return false;
} }
const MemoryBlock requestHeader (createRequestHeader (hostName, hostPort,
proxyName, proxyPort,
hostPath, url,
headers, postData,
isPost));
int totalHeaderSent = 0;
const int numToSend = jmin (1024, requestHeader.getSize() - totalHeaderSent);
while (totalHeaderSent < requestHeader.getSize())
if (send (socketHandle,
((const char*) requestHeader.getData()) + totalHeaderSent,
numToSend, 0)
!= numToSend)
{ {
if (Time::getMillisecondCounter() > timeOutTime)
{
closeSocket();
return false;
}
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;
}
closeSocket();
return false;
} }
const String responseHeader (readResponse (timeOutTime));
totalHeaderSent += numToSend;
if (responseHeader.isNotEmpty())
if (callback != 0 && ! callback (callbackContext, totalHeaderSent, requestHeader.getSize()))
{ {
//DBG (responseHeader);
StringArray lines;
lines.addLines (responseHeader);
// NB - using charToString() here instead of just T(" "), because that was
// causing a mysterious gcc internal compiler error...
const int statusCode = responseHeader.fromFirstOccurrenceOf (String::charToString (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, timeOutMs);
}
else
{
levelsOfRedirection = 0;
return true;
}
closeSocket();
return false;
} }
closeSocket();
return false;
} }
//==============================================================================
int read (void* buffer, int bytesToRead)
const String responseHeader (readResponse (timeOutTime));
if (responseHeader.isNotEmpty())
{ {
fd_set readbits;
FD_ZERO (&readbits);
FD_SET (socketHandle, &readbits);
//DBG (responseHeader);
struct timeval tv;
tv.tv_sec = timeoutSeconds;
tv.tv_usec = 0;
StringArray lines;
lines.addLines (responseHeader);
if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0)
return 0; // (timeout)
// NB - using charToString() here instead of just T(" "), because that was
// causing a mysterious gcc internal compiler error...
const int statusCode = responseHeader.fromFirstOccurrenceOf (String::charToString (T(' ')), false, false)
.substring (0, 3)
.getIntValue();
//int contentLength = findHeaderItem (lines, T("Content-Length:")).getIntValue();
//bool isChunked = findHeaderItem (lines, T("Transfer-Encoding:")).equalsIgnoreCase ("chunked");
const int bytesRead = jmax (0, recv (socketHandle, buffer, bytesToRead, MSG_WAITALL));
readPosition += bytesRead;
return bytesRead;
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, timeOutMs);
}
else
{
levelsOfRedirection = 0;
return true;
}
} }
//==============================================================================
int readPosition;
closeSocket();
return false;
}
//==============================================================================
int read (void* buffer, int bytesToRead)
{
fd_set readbits;
FD_ZERO (&readbits);
FD_SET (socketHandle, &readbits);
//==============================================================================
juce_UseDebuggingNewOperator
struct timeval tv;
tv.tv_sec = timeoutSeconds;
tv.tv_usec = 0;
private:
int socketHandle, levelsOfRedirection;
const int timeoutSeconds;
if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0)
return 0; // (timeout)
//==============================================================================
void closeSocket()
{
if (socketHandle >= 0)
close (socketHandle);
const int bytesRead = jmax (0, recv (socketHandle, buffer, bytesToRead, MSG_WAITALL));
readPosition += bytesRead;
return bytesRead;
}
socketHandle = -1;
}
//==============================================================================
int readPosition;
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 ");
//==============================================================================
juce_UseDebuggingNewOperator
if (proxyName.isEmpty())
{
header << hostPath << " HTTP/1.0\r\nHost: "
<< hostName << ':' << hostPort;
}
else
{
header << originalURL << " HTTP/1.0\r\nHost: "
<< proxyName << ':' << proxyPort;
}
private:
int socketHandle, levelsOfRedirection;
const int timeoutSeconds;
//==============================================================================
void closeSocket()
{
if (socketHandle >= 0)
close (socketHandle);
header << "\r\nUser-Agent: JUCE/"
<< JUCE_MAJOR_VERSION << '.' << JUCE_MINOR_VERSION
<< "\r\nConnection: Close\r\nContent-Length: "
<< postData.getSize() << "\r\n"
<< headers << "\r\n";
socketHandle = -1;
}
MemoryBlock mb;
mb.append (header.toUTF8(), (int) strlen (header.toUTF8()));
mb.append (postData.getData(), postData.getSize());
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 ");
return mb;
if (proxyName.isEmpty())
{
header << hostPath << " HTTP/1.0\r\nHost: "
<< hostName << ':' << hostPort;
} }
const String readResponse (const uint32 timeOutTime)
else
{ {
int bytesRead = 0, numConsecutiveLFs = 0;
MemoryBlock buffer (1024, true);
header << originalURL << " HTTP/1.0\r\nHost: "
<< proxyName << ':' << proxyPort;
}
while (numConsecutiveLFs < 2 && bytesRead < 32768
&& Time::getMillisecondCounter() <= timeOutTime)
{
fd_set readbits;
FD_ZERO (&readbits);
FD_SET (socketHandle, &readbits);
header << "\r\nUser-Agent: JUCE/"
<< JUCE_MAJOR_VERSION << '.' << JUCE_MINOR_VERSION
<< "\r\nConnection: Close\r\nContent-Length: "
<< postData.getSize() << "\r\n"
<< headers << "\r\n";
struct timeval tv;
tv.tv_sec = timeoutSeconds;
tv.tv_usec = 0;
MemoryBlock mb;
mb.append (header.toUTF8(), (int) strlen (header.toUTF8()));
mb.append (postData.getData(), postData.getSize());
return mb;
}
if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0)
return String::empty; // (timeout)
const String readResponse (const uint32 timeOutTime)
{
int bytesRead = 0, numConsecutiveLFs = 0;
MemoryBlock buffer (1024, true);
buffer.ensureSize (bytesRead + 8, true);
char* const dest = (char*) buffer.getData() + bytesRead;
while (numConsecutiveLFs < 2 && bytesRead < 32768
&& Time::getMillisecondCounter() <= timeOutTime)
{
fd_set readbits;
FD_ZERO (&readbits);
FD_SET (socketHandle, &readbits);
if (recv (socketHandle, dest, 1, 0) == -1)
return String::empty;
struct timeval tv;
tv.tv_sec = timeoutSeconds;
tv.tv_usec = 0;
const char lastByte = *dest;
++bytesRead;
if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0)
return String::empty; // (timeout)
if (lastByte == '\n')
++numConsecutiveLFs;
else if (lastByte != '\r')
numConsecutiveLFs = 0;
}
buffer.ensureSize (bytesRead + 8, true);
char* const dest = (char*) buffer.getData() + bytesRead;
const String header (String::fromUTF8 ((const uint8*) buffer.getData()));
if (recv (socketHandle, dest, 1, 0) == -1)
return String::empty;
if (header.startsWithIgnoreCase (T("HTTP/")))
return header.trimEnd();
const char lastByte = *dest;
++bytesRead;
return String::empty;
if (lastByte == '\n')
++numConsecutiveLFs;
else if (lastByte != '\r')
numConsecutiveLFs = 0;
} }
//==============================================================================
static bool decomposeURL (const String& url,
String& host, String& path, int& port)
{
if (! url.startsWithIgnoreCase (T("http://")))
return false;
const String header (String::fromUTF8 ((const uint8*) buffer.getData()));
const int nextSlash = url.indexOfChar (7, '/');
int nextColon = url.indexOfChar (7, ':');
if (nextColon > nextSlash && nextSlash > 0)
nextColon = -1;
if (header.startsWithIgnoreCase (T("HTTP/")))
return header.trimEnd();
if (nextColon >= 0)
{
host = url.substring (7, nextColon);
return String::empty;
}
if (nextSlash >= 0)
port = url.substring (nextColon + 1, nextSlash).getIntValue();
else
port = url.substring (nextColon + 1).getIntValue();
}
else
{
port = 80;
//==============================================================================
static bool decomposeURL (const String& url,
String& host, String& path, int& port)
{
if (! url.startsWithIgnoreCase (T("http://")))
return false;
if (nextSlash >= 0)
host = url.substring (7, nextSlash);
else
host = url.substring (7);
}
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) if (nextSlash >= 0)
path = url.substring (nextSlash);
port = url.substring (nextColon + 1, nextSlash).getIntValue();
else else
path = T("/");
return true;
port = url.substring (nextColon + 1).getIntValue();
} }
//==============================================================================
static const String findHeaderItem (const StringArray& lines, const String& itemName)
else
{ {
for (int i = 0; i < lines.size(); ++i)
if (lines[i].startsWithIgnoreCase (itemName))
return lines[i].substring (itemName.length()).trim();
port = 80;
return String::empty;
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() bool juce_isOnLine()
@@ -478,6 +478,19 @@ int juce_readFromInternetFile (void* handle, void* buffer, int bytesToRead)
return 0; return 0;
} }
int juce_getInternetFileContentLength (void* handle)
{
JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle;
if (s != 0)
{
//xxx todo
jassertfalse
}
return 0;
}
int juce_seekInInternetFile (void* handle, int newPosition) int juce_seekInInternetFile (void* handle, int newPosition)
{ {
JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle; JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle;


+ 464
- 451
build/macosx/platform_specific_code/juce_mac_Network.mm View File

@@ -1,451 +1,464 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-7 by Raw Material Software ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the
GNU General Public License, as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
JUCE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with JUCE; if not, visit www.gnu.org/licenses or write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
------------------------------------------------------------------------------
If you'd like to release a closed-source product which uses JUCE, commercial
licenses are also available: visit www.rawmaterialsoftware.com/juce for
more information.
==============================================================================
*/
// (This file gets included by juce_mac_NativeCode.mm, rather than being
// compiled on its own).
#if JUCE_INCLUDED_FILE
//==============================================================================
static bool getEthernetIterator (io_iterator_t* matchingServices) throw()
{
mach_port_t masterPort;
if (IOMasterPort (MACH_PORT_NULL, &masterPort) == KERN_SUCCESS)
{
CFMutableDictionaryRef dict = IOServiceMatching (kIOEthernetInterfaceClass);
if (dict != 0)
{
CFMutableDictionaryRef propDict = CFDictionaryCreateMutable (kCFAllocatorDefault,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (propDict != 0)
{
CFDictionarySetValue (propDict, CFSTR (kIOPrimaryInterface), kCFBooleanTrue);
CFDictionarySetValue (dict, CFSTR (kIOPropertyMatchKey), propDict);
CFRelease (propDict);
}
}
return IOServiceGetMatchingServices (masterPort, dict, matchingServices) == KERN_SUCCESS;
}
return false;
}
int SystemStats::getMACAddresses (int64* addresses, int maxNum, const bool littleEndian) throw()
{
int numResults = 0;
io_iterator_t it;
if (getEthernetIterator (&it))
{
io_object_t i;
while ((i = IOIteratorNext (it)) != 0)
{
io_object_t controller;
if (IORegistryEntryGetParentEntry (i, kIOServicePlane, &controller) == KERN_SUCCESS)
{
CFTypeRef data = IORegistryEntryCreateCFProperty (controller,
CFSTR (kIOMACAddress),
kCFAllocatorDefault,
0);
if (data != 0)
{
UInt8 addr [kIOEthernetAddressSize];
zeromem (addr, sizeof (addr));
CFDataGetBytes ((CFDataRef) data, CFRangeMake (0, sizeof (addr)), addr);
CFRelease (data);
int64 a = 0;
for (int i = 6; --i >= 0;)
a = (a << 8) | addr[i];
if (! littleEndian)
a = (int64) swapByteOrder ((uint64) a);
if (numResults < maxNum)
{
*addresses++ = a;
++numResults;
}
}
IOObjectRelease (controller);
}
IOObjectRelease (i);
}
IOObjectRelease (it);
}
return numResults;
}
//==============================================================================
bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAddress,
const String& emailSubject,
const String& bodyText,
const StringArray& filesToAttach)
{
const ScopedAutoReleasePool pool;
String script;
script << "tell application \"Mail\"\r\n"
"set newMessage to make new outgoing message with properties {subject:\""
<< emailSubject.replace (T("\""), T("\\\""))
<< "\", content:\""
<< bodyText.replace (T("\""), T("\\\""))
<< "\" & return & return}\r\n"
"tell newMessage\r\n"
"set visible to true\r\n"
"set sender to \"sdfsdfsdfewf\"\r\n"
"make new to recipient at end of to recipients with properties {address:\""
<< targetEmailAddress
<< "\"}\r\n";
for (int i = 0; i < filesToAttach.size(); ++i)
{
script << "tell content\r\n"
"make new attachment with properties {file name:\""
<< filesToAttach[i].replace (T("\""), T("\\\""))
<< "\"} at after the last paragraph\r\n"
"end tell\r\n";
}
script << "end tell\r\n"
"end tell\r\n";
NSAppleScript* s = [[NSAppleScript alloc]
initWithSource: juceStringToNS (script)];
NSDictionary* error = 0;
const bool ok = [s executeAndReturnError: &error] != nil;
[s release];
return ok;
}
//==============================================================================
END_JUCE_NAMESPACE
using namespace JUCE_NAMESPACE;
//==============================================================================
#define JuceURLConnection MakeObjCClassName(JuceURLConnection)
@interface JuceURLConnection : NSObject
{
NSURLRequest* request;
NSURLConnection* connection;
NSMutableData* data;
Thread* runLoopThread;
bool initialised, hasFailed, hasFinished;
int position;
NSLock* dataLock;
}
- (JuceURLConnection*) initWithRequest: (NSURLRequest*) req withCallback: (URL::OpenStreamProgressCallback*) callback withContext: (void*) context;
- (void) dealloc;
- (void) connection: (NSURLConnection*) connection didReceiveResponse: (NSURLResponse*) response;
- (void) connection: (NSURLConnection*) connection didFailWithError: (NSError*) error;
- (void) connection: (NSURLConnection*) connection didReceiveData: (NSData*) data;
- (void) connectionDidFinishLoading: (NSURLConnection*) connection;
- (BOOL) isOpen;
- (int) read: (char*) dest numBytes: (int) num;
- (int) readPosition;
- (void) stop;
- (void) createConnection;
@end
class JuceURLConnectionMessageThread : public Thread
{
JuceURLConnection* owner;
public:
JuceURLConnectionMessageThread (JuceURLConnection* owner_)
: Thread (T("http connection")),
owner (owner_)
{
startThread();
}
~JuceURLConnectionMessageThread()
{
stopThread (10000);
}
void run()
{
[owner createConnection];
while (! threadShouldExit())
{
const ScopedAutoReleasePool pool;
[[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]];
}
}
};
@implementation JuceURLConnection
- (JuceURLConnection*) initWithRequest: (NSURLRequest*) req
withCallback: (URL::OpenStreamProgressCallback*) callback
withContext: (void*) context;
{
[super init];
request = req;
[request retain];
data = [[NSMutableData data] retain];
dataLock = [[NSLock alloc] init];
connection = 0;
initialised = false;
hasFailed = false;
hasFinished = false;
runLoopThread = new JuceURLConnectionMessageThread (self);
while (runLoopThread->isThreadRunning() && ! initialised)
{
if (callback != 0)
callback (context, -1, [[request HTTPBody] length]);
Thread::sleep (1);
}
return self;
}
- (void) dealloc
{
[self stop];
delete runLoopThread;
[connection release];
[data release];
[dataLock release];
[request release];
[super dealloc];
}
- (void) createConnection
{
connection = [[NSURLConnection alloc] initWithRequest: request
delegate: self];
if (connection == nil)
runLoopThread->signalThreadShouldExit();
}
- (void) connection: (NSURLConnection*) connection didReceiveResponse: (NSURLResponse*) response
{
[dataLock lock];
[data setLength: 0];
[dataLock unlock];
initialised = true;
}
- (void) connection: (NSURLConnection*) connection didFailWithError: (NSError*) error
{
NSLog ([error description]);
hasFailed = true;
initialised = true;
runLoopThread->signalThreadShouldExit();
}
- (void) connection: (NSURLConnection*) connection didReceiveData: (NSData*) newData
{
[dataLock lock];
[data appendData: newData];
[dataLock unlock];
initialised = true;
}
- (void) connectionDidFinishLoading: (NSURLConnection*) connection
{
hasFinished = true;
initialised = true;
runLoopThread->signalThreadShouldExit();
}
- (BOOL) isOpen
{
return connection != 0 && ! hasFailed;
}
- (int) readPosition
{
return position;
}
- (int) read: (char*) dest numBytes: (int) numNeeded
{
int numDone = 0;
while (numNeeded > 0)
{
int available = jmin (numNeeded, [data length]);
if (available > 0)
{
[dataLock lock];
[data getBytes: dest length: available];
[data replaceBytesInRange: NSMakeRange (0, available) withBytes: nil length: 0];
[dataLock unlock];
numDone += available;
numNeeded -= available;
dest += available;
}
else
{
if (hasFailed || hasFinished)
break;
Thread::sleep (1);
}
}
position += numDone;
return numDone;
}
- (void) stop
{
[connection cancel];
runLoopThread->stopThread (10000);
}
@end
BEGIN_JUCE_NAMESPACE
bool juce_isOnLine()
{
return true;
}
void* juce_openInternetFile (const String& url,
const String& headers,
const MemoryBlock& postData,
const bool isPost,
URL::OpenStreamProgressCallback* callback,
void* callbackContext,
int timeOutMs)
{
const ScopedAutoReleasePool pool;
NSMutableURLRequest* req = [NSMutableURLRequest
requestWithURL: [NSURL URLWithString: juceStringToNS (url)]
cachePolicy: NSURLRequestUseProtocolCachePolicy
timeoutInterval: timeOutMs <= 0 ? 60.0 : (timeOutMs / 1000.0)];
if (req == nil)
return 0;
[req setHTTPMethod: isPost ? @"POST" : @"GET"];
//[req setCachePolicy: NSURLRequestReloadIgnoringLocalAndRemoteCacheData];
StringArray headerLines;
headerLines.addLines (headers);
headerLines.removeEmptyStrings (true);
for (int i = 0; i < headerLines.size(); ++i)
{
const String key (headerLines[i].upToFirstOccurrenceOf (T(":"), false, false).trim());
const String value (headerLines[i].fromFirstOccurrenceOf (T(":"), false, false).trim());
if (key.isNotEmpty() && value.isNotEmpty())
[req addValue: juceStringToNS (value) forHTTPHeaderField: juceStringToNS (key)];
}
if (isPost && postData.getSize() > 0)
{
[req setHTTPBody: [NSData dataWithBytes: postData.getData()
length: postData.getSize()]];
}
JuceURLConnection* const s = [[JuceURLConnection alloc] initWithRequest: req
withCallback: callback
withContext: callbackContext];
if ([s isOpen])
return s;
[s release];
return 0;
}
void juce_closeInternetFile (void* handle)
{
JuceURLConnection* const s = (JuceURLConnection*) handle;
if (s != 0)
{
const ScopedAutoReleasePool pool;
[s stop];
[s release];
}
}
int juce_readFromInternetFile (void* handle, void* buffer, int bytesToRead)
{
JuceURLConnection* const s = (JuceURLConnection*) handle;
if (s != 0)
{
const ScopedAutoReleasePool pool;
return [s read: (char*) buffer numBytes: bytesToRead];
}
return 0;
}
int juce_seekInInternetFile (void* handle, int newPosition)
{
JuceURLConnection* const s = (JuceURLConnection*) handle;
if (s != 0)
return [s readPosition];
return 0;
}
#endif
/*
==============================================================================

This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-7 by Raw Material Software ltd.

------------------------------------------------------------------------------

JUCE can be redistributed and/or modified under the terms of the
GNU General Public License, as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.

JUCE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with JUCE; if not, visit www.gnu.org/licenses or write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA

------------------------------------------------------------------------------

If you'd like to release a closed-source product which uses JUCE, commercial
licenses are also available: visit www.rawmaterialsoftware.com/juce for
more information.

==============================================================================
*/

// (This file gets included by juce_mac_NativeCode.mm, rather than being
// compiled on its own).
#if JUCE_INCLUDED_FILE

//==============================================================================
static bool getEthernetIterator (io_iterator_t* matchingServices) throw()
{
mach_port_t masterPort;

if (IOMasterPort (MACH_PORT_NULL, &masterPort) == KERN_SUCCESS)
{
CFMutableDictionaryRef dict = IOServiceMatching (kIOEthernetInterfaceClass);

if (dict != 0)
{
CFMutableDictionaryRef propDict = CFDictionaryCreateMutable (kCFAllocatorDefault,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);

if (propDict != 0)
{
CFDictionarySetValue (propDict, CFSTR (kIOPrimaryInterface), kCFBooleanTrue);

CFDictionarySetValue (dict, CFSTR (kIOPropertyMatchKey), propDict);
CFRelease (propDict);
}
}

return IOServiceGetMatchingServices (masterPort, dict, matchingServices) == KERN_SUCCESS;
}

return false;
}

int SystemStats::getMACAddresses (int64* addresses, int maxNum, const bool littleEndian) throw()
{
int numResults = 0;
io_iterator_t it;

if (getEthernetIterator (&it))
{
io_object_t i;

while ((i = IOIteratorNext (it)) != 0)
{
io_object_t controller;

if (IORegistryEntryGetParentEntry (i, kIOServicePlane, &controller) == KERN_SUCCESS)
{
CFTypeRef data = IORegistryEntryCreateCFProperty (controller,
CFSTR (kIOMACAddress),
kCFAllocatorDefault,
0);
if (data != 0)
{
UInt8 addr [kIOEthernetAddressSize];
zeromem (addr, sizeof (addr));

CFDataGetBytes ((CFDataRef) data, CFRangeMake (0, sizeof (addr)), addr);
CFRelease (data);

int64 a = 0;
for (int i = 6; --i >= 0;)
a = (a << 8) | addr[i];

if (! littleEndian)
a = (int64) swapByteOrder ((uint64) a);

if (numResults < maxNum)
{
*addresses++ = a;
++numResults;
}
}

IOObjectRelease (controller);
}

IOObjectRelease (i);
}

IOObjectRelease (it);
}

return numResults;
}

//==============================================================================
bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAddress,
const String& emailSubject,
const String& bodyText,
const StringArray& filesToAttach)
{
const ScopedAutoReleasePool pool;

String script;
script << "tell application \"Mail\"\r\n"
"set newMessage to make new outgoing message with properties {subject:\""
<< emailSubject.replace (T("\""), T("\\\""))
<< "\", content:\""
<< bodyText.replace (T("\""), T("\\\""))
<< "\" & return & return}\r\n"
"tell newMessage\r\n"
"set visible to true\r\n"
"set sender to \"sdfsdfsdfewf\"\r\n"
"make new to recipient at end of to recipients with properties {address:\""
<< targetEmailAddress
<< "\"}\r\n";

for (int i = 0; i < filesToAttach.size(); ++i)
{
script << "tell content\r\n"
"make new attachment with properties {file name:\""
<< filesToAttach[i].replace (T("\""), T("\\\""))
<< "\"} at after the last paragraph\r\n"
"end tell\r\n";
}

script << "end tell\r\n"
"end tell\r\n";

NSAppleScript* s = [[NSAppleScript alloc]
initWithSource: juceStringToNS (script)];
NSDictionary* error = 0;
const bool ok = [s executeAndReturnError: &error] != nil;
[s release];

return ok;
}

//==============================================================================
END_JUCE_NAMESPACE

using namespace JUCE_NAMESPACE;

//==============================================================================
#define JuceURLConnection MakeObjCClassName(JuceURLConnection)

@interface JuceURLConnection : NSObject
{
NSURLRequest* request;
NSURLConnection* connection;
NSMutableData* data;
Thread* runLoopThread;
bool initialised, hasFailed, hasFinished;
int position;
NSLock* dataLock;
}

- (JuceURLConnection*) initWithRequest: (NSURLRequest*) req withCallback: (URL::OpenStreamProgressCallback*) callback withContext: (void*) context;
- (void) dealloc;
- (void) connection: (NSURLConnection*) connection didReceiveResponse: (NSURLResponse*) response;
- (void) connection: (NSURLConnection*) connection didFailWithError: (NSError*) error;
- (void) connection: (NSURLConnection*) connection didReceiveData: (NSData*) data;
- (void) connectionDidFinishLoading: (NSURLConnection*) connection;

- (BOOL) isOpen;
- (int) read: (char*) dest numBytes: (int) num;
- (int) readPosition;
- (void) stop;
- (void) createConnection;

@end

class JuceURLConnectionMessageThread : public Thread
{
JuceURLConnection* owner;
public:
JuceURLConnectionMessageThread (JuceURLConnection* owner_)
: Thread (T("http connection")),
owner (owner_)
{
startThread();
}

~JuceURLConnectionMessageThread()
{
stopThread (10000);
}

void run()
{
[owner createConnection];

while (! threadShouldExit())
{
const ScopedAutoReleasePool pool;
[[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]];
}
}
};


@implementation JuceURLConnection

- (JuceURLConnection*) initWithRequest: (NSURLRequest*) req
withCallback: (URL::OpenStreamProgressCallback*) callback
withContext: (void*) context;
{
[super init];
request = req;
[request retain];
data = [[NSMutableData data] retain];
dataLock = [[NSLock alloc] init];
connection = 0;
initialised = false;
hasFailed = false;
hasFinished = false;

runLoopThread = new JuceURLConnectionMessageThread (self);

while (runLoopThread->isThreadRunning() && ! initialised)
{
if (callback != 0)
callback (context, -1, [[request HTTPBody] length]);

Thread::sleep (1);
}

return self;
}

- (void) dealloc
{
[self stop];

delete runLoopThread;
[connection release];
[data release];
[dataLock release];
[request release];
[super dealloc];
}

- (void) createConnection
{
connection = [[NSURLConnection alloc] initWithRequest: request
delegate: self];

if (connection == nil)
runLoopThread->signalThreadShouldExit();
}

- (void) connection: (NSURLConnection*) connection didReceiveResponse: (NSURLResponse*) response
{
[dataLock lock];
[data setLength: 0];
[dataLock unlock];
initialised = true;
}

- (void) connection: (NSURLConnection*) connection didFailWithError: (NSError*) error
{
NSLog ([error description]);
hasFailed = true;
initialised = true;
runLoopThread->signalThreadShouldExit();
}

- (void) connection: (NSURLConnection*) connection didReceiveData: (NSData*) newData
{
[dataLock lock];
[data appendData: newData];
[dataLock unlock];
initialised = true;
}

- (void) connectionDidFinishLoading: (NSURLConnection*) connection
{
hasFinished = true;
initialised = true;
runLoopThread->signalThreadShouldExit();
}

- (BOOL) isOpen
{
return connection != 0 && ! hasFailed;
}

- (int) readPosition
{
return position;
}

- (int) read: (char*) dest numBytes: (int) numNeeded
{
int numDone = 0;
while (numNeeded > 0)
{
int available = jmin (numNeeded, [data length]);

if (available > 0)
{
[dataLock lock];
[data getBytes: dest length: available];
[data replaceBytesInRange: NSMakeRange (0, available) withBytes: nil length: 0];
[dataLock unlock];
numDone += available;
numNeeded -= available;
dest += available;
}
else
{
if (hasFailed || hasFinished)
break;

Thread::sleep (1);
}
}

position += numDone;
return numDone;
}

- (void) stop
{
[connection cancel];
runLoopThread->stopThread (10000);
}

@end
BEGIN_JUCE_NAMESPACE


bool juce_isOnLine()
{
return true;
}

void* juce_openInternetFile (const String& url,
const String& headers,
const MemoryBlock& postData,
const bool isPost,
URL::OpenStreamProgressCallback* callback,
void* callbackContext,
int timeOutMs)
{
const ScopedAutoReleasePool pool;

NSMutableURLRequest* req = [NSMutableURLRequest
requestWithURL: [NSURL URLWithString: juceStringToNS (url)]
cachePolicy: NSURLRequestUseProtocolCachePolicy
timeoutInterval: timeOutMs <= 0 ? 60.0 : (timeOutMs / 1000.0)];

if (req == nil)
return 0;

[req setHTTPMethod: isPost ? @"POST" : @"GET"];
//[req setCachePolicy: NSURLRequestReloadIgnoringLocalAndRemoteCacheData];

StringArray headerLines;
headerLines.addLines (headers);
headerLines.removeEmptyStrings (true);

for (int i = 0; i < headerLines.size(); ++i)
{
const String key (headerLines[i].upToFirstOccurrenceOf (T(":"), false, false).trim());
const String value (headerLines[i].fromFirstOccurrenceOf (T(":"), false, false).trim());

if (key.isNotEmpty() && value.isNotEmpty())
[req addValue: juceStringToNS (value) forHTTPHeaderField: juceStringToNS (key)];
}

if (isPost && postData.getSize() > 0)
{
[req setHTTPBody: [NSData dataWithBytes: postData.getData()
length: postData.getSize()]];
}

JuceURLConnection* const s = [[JuceURLConnection alloc] initWithRequest: req
withCallback: callback
withContext: callbackContext];

if ([s isOpen])
return s;

[s release];
return 0;
}

void juce_closeInternetFile (void* handle)
{
JuceURLConnection* const s = (JuceURLConnection*) handle;
if (s != 0)
{
const ScopedAutoReleasePool pool;
[s stop];
[s release];
}
}

int juce_readFromInternetFile (void* handle, void* buffer, int bytesToRead)
{
JuceURLConnection* const s = (JuceURLConnection*) handle;
if (s != 0)
{
const ScopedAutoReleasePool pool;
return [s read: (char*) buffer numBytes: bytesToRead];
}

return 0;
}

int juce_getInternetFileContentLength (void* handle)
{
JuceURLConnection* const s = (JuceURLConnection*) handle;
if (s != 0)
{
//xxx todo
jassertfalse
}

return 0;
}

int juce_seekInInternetFile (void* handle, int newPosition)
{
JuceURLConnection* const s = (JuceURLConnection*) handle;
if (s != 0)
return [s readPosition];

return 0;
}

#endif

+ 2
- 1
build/win32/platform_specific_code/juce_win32_ASIO.cpp View File

@@ -738,7 +738,8 @@ public:
JUCE_TRY JUCE_TRY
{ {
close();
// are there are devices that need to be closed before showing their control panel?
// close();
insideControlPanelModalLoop = true; insideControlPanelModalLoop = true;
const uint32 started = Time::getMillisecondCounter(); const uint32 started = Time::getMillisecondCounter();


+ 20
- 0
build/win32/platform_specific_code/juce_win32_Network.cpp View File

@@ -217,6 +217,26 @@ int juce_seekInInternetFile (void* handle, int newPosition)
} }
} }
int juce_getInternetFileContentLength (void* handle)
{
DWORD result = 0;
const ConnectionAndRequestStruct* const crs = (const ConnectionAndRequestStruct*) handle;
if (crs != 0)
{
DWORD index = 0;
DWORD size = sizeof (result);
HttpQueryInfo (crs->request,
HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,
&result,
&size,
&index);
}
return (int) result;
}
void juce_closeInternetFile (void* handle) void juce_closeInternetFile (void* handle)
{ {
if (handle != 0) if (handle != 0)


+ 23
- 7
src/juce_appframework/gui/components/controls/juce_Label.cpp View File

@@ -80,14 +80,15 @@ void Label::setText (const String& newText,
if (text != newText) if (text != newText)
{ {
text = newText; text = newText;
if (broadcastChangeMessage)
triggerAsyncUpdate();
repaint(); repaint();
if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted())
{
componentMovedOrResized (*ownerComponent, true, true); componentMovedOrResized (*ownerComponent, true, true);
if (broadcastChangeMessage)
callChangeListeners();
}
} }
} }
@@ -220,8 +221,6 @@ bool Label::updateFromTextEditorContents()
if (text != newText) if (text != newText)
{ {
text = newText; text = newText;
triggerAsyncUpdate();
repaint(); repaint();
if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted())
@@ -247,6 +246,9 @@ void Label::hideEditor (const bool discardCurrentEditorContents)
textWasEdited(); textWasEdited();
exitModalState (0); exitModalState (0);
if (changed && isValidComponent())
callChangeListeners();
} }
} }
@@ -332,6 +334,15 @@ void Label::colourChanged()
repaint(); repaint();
} }
void Label::setMinimumHorizontalScale (const float newScale)
{
if (minimumHorizontalScale != newScale)
{
minimumHorizontalScale = newScale;
repaint();
}
}
//============================================================================== //==============================================================================
// We'll use a custom focus traverser here to make sure focus goes from the // We'll use a custom focus traverser here to make sure focus goes from the
// text editor to another component rather than back to the label itself. // text editor to another component rather than back to the label itself.
@@ -371,7 +382,7 @@ void Label::removeListener (LabelListener* const listener) throw()
listeners.removeValue (listener); listeners.removeValue (listener);
} }
void Label::handleAsyncUpdate()
void Label::callChangeListeners()
{ {
for (int i = listeners.size(); --i >= 0;) for (int i = listeners.size(); --i >= 0;)
{ {
@@ -408,7 +419,12 @@ void Label::textEditorReturnKeyPressed (TextEditor& ed)
hideEditor (true); hideEditor (true);
if (changed) if (changed)
{
textWasEdited(); textWasEdited();
if (isValidComponent())
callChangeListeners();
}
} }
} }


+ 2
- 5
src/juce_appframework/gui/components/controls/juce_Label.h View File

@@ -33,7 +33,6 @@
#define __JUCE_LABEL_JUCEHEADER__ #define __JUCE_LABEL_JUCEHEADER__
#include "../juce_ComponentDeletionWatcher.h" #include "../juce_ComponentDeletionWatcher.h"
#include "../../../events/juce_AsyncUpdater.h"
#include "juce_TextEditor.h" #include "juce_TextEditor.h"
class Label; class Label;
@@ -69,8 +68,7 @@ public:
class JUCE_API Label : public Component, class JUCE_API Label : public Component,
public SettableTooltipClient, public SettableTooltipClient,
protected TextEditorListener, protected TextEditorListener,
private ComponentListener,
private AsyncUpdater
private ComponentListener
{ {
public: public:
//============================================================================== //==============================================================================
@@ -295,8 +293,6 @@ protected:
/** @internal */ /** @internal */
void textEditorFocusLost (TextEditor& editor); void textEditorFocusLost (TextEditor& editor);
/** @internal */ /** @internal */
void handleAsyncUpdate();
/** @internal */
void colourChanged(); void colourChanged();
/** Creates the TextEditor component that will be used when the user has clicked on the label. /** Creates the TextEditor component that will be used when the user has clicked on the label.
@@ -325,6 +321,7 @@ private:
bool leftOfOwnerComp : 1; bool leftOfOwnerComp : 1;
bool updateFromTextEditorContents(); bool updateFromTextEditorContents();
void callChangeListeners();
Label (const Label&); Label (const Label&);
const Label& operator= (const Label&); const Label& operator= (const Label&);


+ 1
- 1
src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.cpp View File

@@ -547,7 +547,7 @@ void LookAndFeel::drawProgressBar (Graphics& g, ProgressBar& progressBar,
Path p; Path p;
for (float x = (float) (-stripeWidth - position); x < width + stripeWidth; x += stripeWidth)
for (float x = (float) (- position); x < width + stripeWidth; x += stripeWidth)
p.addQuadrilateral (x, 0.0f, p.addQuadrilateral (x, 0.0f,
x + stripeWidth * 0.5f, 0.0f, x + stripeWidth * 0.5f, 0.0f,
x, (float) height, x, (float) height,


Loading…
Cancel
Save