Browse Source

added URL stream length detection to Mac/win32; fixed a small linux audio bug; added some callbacks to Label to report when its text editor is shown or hidden; fixed a mouse-wheel problem with some types of slider; fixed a small SVG parsing error;

tags/2021-05-28
jules 16 years ago
parent
commit
253e713d02
15 changed files with 513 additions and 903 deletions
  1. +1
    -1
      build/linux/platform_specific_code/juce_linux_Audio.cpp
  2. +3
    -4
      build/linux/platform_specific_code/juce_linux_Network.cpp
  3. +0
    -420
      build/macosx/platform_specific_code/juce_mac_HTTPStream.h
  4. +464
    -464
      build/macosx/platform_specific_code/juce_mac_Network.mm
  5. +2
    -2
      build/win32/platform_specific_code/juce_win32_Network.cpp
  6. +12
    -0
      src/juce_appframework/gui/components/controls/juce_Label.cpp
  7. +9
    -0
      src/juce_appframework/gui/components/controls/juce_Label.h
  8. +1
    -1
      src/juce_appframework/gui/components/filebrowser/juce_FilenameComponent.h
  9. +10
    -1
      src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.cpp
  10. +1
    -1
      src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.h
  11. +2
    -2
      src/juce_appframework/gui/graphics/drawables/juce_SVGParser.cpp
  12. +2
    -2
      src/juce_core/containers/juce_Array.h
  13. +2
    -2
      src/juce_core/containers/juce_OwnedArray.h
  14. +2
    -2
      src/juce_core/containers/juce_SortedSet.h
  15. +2
    -1
      src/juce_core/io/network/juce_URL.cpp

+ 1
- 1
build/linux/platform_specific_code/juce_linux_Audio.cpp View File

@@ -410,7 +410,7 @@ public:
if (inputChannels.getHighestBit() >= 0)
{
for (int i = 0; i <= inputChannels.getHighestBit(); ++i)
for (int i = 0; i <= jmax (inputChannels.getHighestBit(), minChansIn); ++i)
{
inputChannelData [i] = (float*) juce_calloc (sizeof (float) * bufferSize);


+ 3
- 4
build/linux/platform_specific_code/juce_linux_Network.cpp View File

@@ -242,8 +242,7 @@ public:
// 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();
.substring (0, 3).getIntValue();
//int contentLength = findHeaderItem (lines, T("Content-Length:")).getIntValue();
//bool isChunked = findHeaderItem (lines, T("Transfer-Encoding:")).equalsIgnoreCase ("chunked");
@@ -478,7 +477,7 @@ int juce_readFromInternetFile (void* handle, void* buffer, int bytesToRead)
return 0;
}
int juce_getInternetFileContentLength (void* handle)
int64 juce_getInternetFileContentLength (void* handle)
{
JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle;
@@ -488,7 +487,7 @@ int juce_getInternetFileContentLength (void* handle)
jassertfalse
}
return 0;
return -1;
}
int juce_seekInInternetFile (void* handle, int newPosition)


+ 0
- 420
build/macosx/platform_specific_code/juce_mac_HTTPStream.h View File

@@ -1,420 +0,0 @@
/*
==============================================================================
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 the mac + linux networking code)
//==============================================================================
/** A HTTP input stream that uses sockets.
*/
class JUCE_HTTPSocketStream
{
public:
//==============================================================================
JUCE_HTTPSocketStream()
: 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,
int timeOutMs)
{
closeSocket();
uint32 timeOutTime = Time::getMillisecondCounter();
if (timeOutMs == 0)
timeOutTime += 60000;
else if (timeOutMs < 0)
timeOutTime = 0xffffffff;
else
timeOutTime += timeOutMs;
String hostName, hostPath;
int hostPort;
if (! decomposeURL (url, hostName, hostPath, hostPort))
return false;
const struct hostent* host = 0;
int port = 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;
host = gethostbyname ((const char*) proxyName.toUTF8());
port = proxyPort;
}
else
{
host = gethostbyname ((const char*) hostName.toUTF8());
port = hostPort;
}
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);
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;
}
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();
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;
}
}
const String responseHeader (readResponse (timeOutTime));
if (responseHeader.isNotEmpty())
{
//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;
}
//==============================================================================
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 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 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)
{
int bytesRead = 0, numConsecutiveLFs = 0;
MemoryBlock buffer (1024, true);
while (numConsecutiveLFs < 2 && bytesRead < 32768
&& Time::getMillisecondCounter() <= timeOutTime)
{
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,
int timeOutMs)
{
JUCE_HTTPSocketStream* const s = new JUCE_HTTPSocketStream();
if (s->open (url, headers, postData, isPost,
callback, callbackContext, timeOutMs))
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;
}

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

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

+ 2
- 2
build/win32/platform_specific_code/juce_win32_Network.cpp View File

@@ -217,9 +217,9 @@ int juce_seekInInternetFile (void* handle, int newPosition)
}
}
int juce_getInternetFileContentLength (void* handle)
int64 juce_getInternetFileContentLength (void* handle)
{
DWORD result = 0;
DWORD result = -1;
const ConnectionAndRequestStruct* const crs = (const ConnectionAndRequestStruct*) handle;
if (crs != 0)


+ 12
- 0
src/juce_appframework/gui/components/controls/juce_Label.cpp View File

@@ -212,11 +212,21 @@ void Label::showEditor()
resized();
repaint();
editorShown (editor);
enterModalState();
editor->grabKeyboardFocus();
}
}
void Label::editorShown (TextEditor* editorComponent)
{
}
void Label::editorAboutToBeHidden (TextEditor* editorComponent)
{
}
bool Label::updateFromTextEditorContents()
{
jassert (editor != 0);
@@ -242,6 +252,8 @@ void Label::hideEditor (const bool discardCurrentEditorContents)
{
if (editor != 0)
{
editorAboutToBeHidden (editor);
const bool changed = (! discardCurrentEditorContents)
&& updateFromTextEditorContents();


+ 9
- 0
src/juce_appframework/gui/components/controls/juce_Label.h View File

@@ -308,6 +308,15 @@ protected:
/** Called when the text has been altered.
*/
virtual void textWasChanged();
/** Called when the text editor has just appeared, due to a user click or other
focus change.
*/
virtual void editorShown (TextEditor* editorComponent);
/** Called when the text editor is going to be deleted, after editing has finished.
*/
virtual void editorAboutToBeHidden (TextEditor* editorComponent);
private:
String text;


+ 1
- 1
src/juce_appframework/gui/components/filebrowser/juce_FilenameComponent.h View File

@@ -47,7 +47,7 @@ class FilenameComponent;
Use FilenameComponent::addListener() and FilenameComponent::removeListener() to
register one of these objects for event callbacks when the filename is changed.
@See FilenameComponent
@see FilenameComponent
*/
class JUCE_API FilenameComponentListener
{


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

@@ -1584,9 +1584,18 @@ Button* LookAndFeel::createSliderButton (const bool isIncrement)
return new TextButton (isIncrement ? "+" : "-", String::empty);
}
class SliderLabelComp : public Label
{
public:
SliderLabelComp() : Label (String::empty, String::empty) {}
~SliderLabelComp() {}
void mouseWheelMove (const MouseEvent&, float, float) {}
};
Label* LookAndFeel::createSliderTextBox (Slider& slider)
{
Label* const l = new Label (T("n"), String::empty);
Label* const l = new SliderLabelComp();
l->setJustificationType (Justification::centred);


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

@@ -176,7 +176,7 @@ public:
const bool isButtonDown);
//==============================================================================
/** AlertWindow handling..
/* AlertWindow handling..
*/
virtual AlertWindow* createAlertWindow (const String& title,
const String& message,


+ 2
- 2
src/juce_appframework/gui/graphics/drawables/juce_SVGParser.cpp View File

@@ -352,8 +352,8 @@ private:
y2 = lastY + (lastY - lastY2);
path.cubicTo (x2, y2, x, y, x3, y3);
lastX2 = x2;
lastY2 = y2;
lastX2 = x;
lastY2 = y;
lastX = x3;
lastY = y3;
}


+ 2
- 2
src/juce_core/containers/juce_Array.h View File

@@ -70,8 +70,8 @@ public:
@see ArrayAllocationBase
*/
Array (const int granularity_ = juceDefaultArrayGranularity) throw()
: ArrayAllocationBase <ElementType> (granularity_),
Array (const int granularity = juceDefaultArrayGranularity) throw()
: ArrayAllocationBase <ElementType> (granularity),
numUsed (0)
{
}


+ 2
- 2
src/juce_core/containers/juce_OwnedArray.h View File

@@ -71,8 +71,8 @@ public:
@see ArrayAllocationBase
*/
OwnedArray (const int granularity_ = juceDefaultArrayGranularity) throw()
: ArrayAllocationBase <ObjectClass*> (granularity_),
OwnedArray (const int granularity = juceDefaultArrayGranularity) throw()
: ArrayAllocationBase <ObjectClass*> (granularity),
numUsed (0)
{
}


+ 2
- 2
src/juce_core/containers/juce_SortedSet.h View File

@@ -76,8 +76,8 @@ public:
@see ArrayAllocationBase
*/
SortedSet (const int granularity_ = juceDefaultArrayGranularity) throw()
: ArrayAllocationBase <ElementType> (granularity_),
SortedSet (const int granularity = juceDefaultArrayGranularity) throw()
: ArrayAllocationBase <ElementType> (granularity),
numUsed (0)
{
}


+ 2
- 1
src/juce_core/io/network/juce_URL.cpp View File

@@ -180,6 +180,7 @@ void* juce_openInternetFile (const String& url,
void juce_closeInternetFile (void* handle);
int juce_readFromInternetFile (void* handle, void* dest, int bytesToRead);
int juce_seekInInternetFile (void* handle, int newPosition);
int64 juce_getInternetFileContentLength (void* handle);
//==============================================================================
@@ -228,7 +229,7 @@ public:
//==============================================================================
int64 getTotalLength()
{
return -1;
return juce_getInternetFileContentLength (handle);
}
bool isExhausted()


Loading…
Cancel
Save