mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-22 01:34:21 +00:00
429 lines
12 KiB
Text
429 lines
12 KiB
Text
/*
|
|
==============================================================================
|
|
|
|
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
|
Copyright 2004-10 by Raw Material Software Ltd.
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
JUCE can be redistributed and/or modified under the terms of the GNU General
|
|
Public License (Version 2), as published by the Free Software Foundation.
|
|
A copy of the license is included in the JUCE distribution, or can be found
|
|
online at www.gnu.org/licenses.
|
|
|
|
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.
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
To release a closed-source product which uses JUCE, commercial licenses are
|
|
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
|
|
|
|
//==============================================================================
|
|
int SystemStats::getMACAddresses (int64* addresses, int maxNum, const bool littleEndian)
|
|
{
|
|
#ifndef IFT_ETHER
|
|
#define IFT_ETHER 6
|
|
#endif
|
|
|
|
ifaddrs* addrs = 0;
|
|
int numResults = 0;
|
|
|
|
if (getifaddrs (&addrs) == 0)
|
|
{
|
|
const ifaddrs* cursor = addrs;
|
|
|
|
while (cursor != 0 && numResults < maxNum)
|
|
{
|
|
sockaddr_storage* sto = (sockaddr_storage*) cursor->ifa_addr;
|
|
if (sto->ss_family == AF_LINK)
|
|
{
|
|
const sockaddr_dl* const sadd = (const sockaddr_dl*) cursor->ifa_addr;
|
|
|
|
if (sadd->sdl_type == IFT_ETHER)
|
|
{
|
|
const uint8* const addr = ((const uint8*) sadd->sdl_data) + sadd->sdl_nlen;
|
|
|
|
uint64 a = 0;
|
|
for (int i = 6; --i >= 0;)
|
|
a = (a << 8) | addr [littleEndian ? i : (5 - i)];
|
|
|
|
*addresses++ = (int64) a;
|
|
++numResults;
|
|
}
|
|
}
|
|
|
|
cursor = cursor->ifa_next;
|
|
}
|
|
|
|
freeifaddrs (addrs);
|
|
}
|
|
|
|
return numResults;
|
|
}
|
|
|
|
//==============================================================================
|
|
bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAddress,
|
|
const String& emailSubject,
|
|
const String& bodyText,
|
|
const StringArray& filesToAttach)
|
|
{
|
|
#if JUCE_IPHONE
|
|
//xxx probably need to use MFMailComposeViewController
|
|
jassertfalse
|
|
return false;
|
|
#else
|
|
const ScopedAutoReleasePool pool;
|
|
|
|
String script;
|
|
script << "tell application \"Mail\"\r\n"
|
|
"set newMessage to make new outgoing message with properties {subject:\""
|
|
<< emailSubject.replace ("\"", "\\\"")
|
|
<< "\", content:\""
|
|
<< bodyText.replace ("\"", "\\\"")
|
|
<< "\" & 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 ("\"", "\\\"")
|
|
<< "\"} 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;
|
|
#endif
|
|
}
|
|
|
|
//==============================================================================
|
|
END_JUCE_NAMESPACE
|
|
|
|
using namespace JUCE_NAMESPACE;
|
|
|
|
//==============================================================================
|
|
#define JuceURLConnection MakeObjCClassName(JuceURLConnection)
|
|
|
|
@interface JuceURLConnection : NSObject
|
|
{
|
|
@public
|
|
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 ("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, (int) [[request HTTPBody] length]);
|
|
|
|
Thread::sleep (1);
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
- (void) dealloc
|
|
{
|
|
[self stop];
|
|
|
|
deleteAndZero (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*) conn didReceiveResponse: (NSURLResponse*) response
|
|
{
|
|
(void) conn;
|
|
[dataLock lock];
|
|
[data setLength: 0];
|
|
[dataLock unlock];
|
|
initialised = true;
|
|
contentLength = [response expectedContentLength];
|
|
}
|
|
|
|
- (void) connection: (NSURLConnection*) conn didFailWithError: (NSError*) error
|
|
{
|
|
(void) conn;
|
|
DBG (nsStringToJuce ([error description]));
|
|
hasFailed = true;
|
|
initialised = true;
|
|
|
|
if (runLoopThread != 0)
|
|
runLoopThread->signalThreadShouldExit();
|
|
}
|
|
|
|
- (void) connection: (NSURLConnection*) conn didReceiveData: (NSData*) newData
|
|
{
|
|
(void) conn;
|
|
[dataLock lock];
|
|
[data appendData: newData];
|
|
[dataLock unlock];
|
|
initialised = true;
|
|
}
|
|
|
|
- (void) connectionDidFinishLoading: (NSURLConnection*) conn
|
|
{
|
|
(void) conn;
|
|
hasFinished = true;
|
|
initialised = true;
|
|
|
|
if (runLoopThread != 0)
|
|
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, (int) [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];
|
|
|
|
if (runLoopThread != 0)
|
|
runLoopThread->stopThread (10000);
|
|
}
|
|
|
|
@end
|
|
BEGIN_JUCE_NAMESPACE
|
|
|
|
|
|
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 (":", false, false).trim());
|
|
const String value (headerLines[i].fromFirstOccurrenceOf (":", 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
|