Browse Source

tags/2021-05-28
jules 17 years ago
parent
commit
1c431212eb
19 changed files with 4226 additions and 3863 deletions
  1. +1
    -1
      build/linux/juce_premake.lua
  2. +15
    -1
      build/linux/platform_specific_code/juce_linux_Network.cpp
  3. +12
    -12
      build/macosx/platform_specific_code/juce_mac_Files.cpp
  4. +31
    -33
      build/macosx/platform_specific_code/juce_mac_HTTPStream.h
  5. +191
    -137
      build/macosx/platform_specific_code/juce_mac_Network.cpp
  6. +3604
    -3582
      build/macosx/platform_specific_code/juce_mac_Windowing.cpp
  7. +116
    -27
      build/win32/platform_specific_code/juce_win32_Network.cpp
  8. +1
    -1
      juce_Config.h
  9. +8
    -3
      src/juce_appframework/gui/components/controls/juce_ListBox.cpp
  10. +2
    -1
      src/juce_appframework/gui/components/controls/juce_ListBox.h
  11. +2
    -2
      src/juce_appframework/gui/components/controls/juce_Slider.cpp
  12. +10
    -4
      src/juce_appframework/gui/components/controls/juce_TableListBox.cpp
  13. +9
    -4
      src/juce_appframework/gui/components/controls/juce_TableListBox.h
  14. +9
    -6
      src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.cpp
  15. +10
    -0
      src/juce_core/basics/juce_SystemStats.cpp
  16. +13
    -1
      src/juce_core/basics/juce_SystemStats.h
  17. +147
    -36
      src/juce_core/io/network/juce_URL.cpp
  18. +40
    -12
      src/juce_core/io/network/juce_URL.h
  19. +5
    -0
      src/juce_core/misc/juce_PlatformUtilities.h

+ 1
- 1
build/linux/juce_premake.lua View File

@@ -21,7 +21,7 @@ package.config["Debug"].defines = { "LINUX=1", "DEBUG=1", "_DEBUG=1" };
package.config["Debug"].buildoptions = { "-D_DEBUG -ggdb -Wall" }
package.config["Release"].defines = { "LINUX=1", "NDEBUG=1" };
package.config["Release"].buildoptions = { "-Wall" }
package.config["Release"].buildoptions = { "-O2 -Wall -fvisibility=hidden" }
package.includepaths = {


+ 15
- 1
build/linux/platform_specific_code/juce_linux_Network.cpp View File

@@ -44,16 +44,30 @@ BEGIN_JUCE_NAMESPACE
#include "../../../src/juce_core/text/juce_StringArray.h"
#include "../../../src/juce_core/basics/juce_SystemStats.h"
#include "../../../src/juce_core/containers/juce_MemoryBlock.h"
#include "../../../src/juce_core/misc/juce_PlatformUtilities.h"
#include "../../../src/juce_core/io/network/juce_URL.h"
// we'll borrow the mac's socket-based http streaming code..
#include "../../macosx/platform_specific_code/juce_mac_HTTPStream.h"
//==============================================================================
int SystemStats::getMACAddresses (int64* addresses, int maxNum) throw()
int SystemStats::getMACAddresses (int64* addresses, int maxNum, const bool littleEndian) throw()
{
// xxx todo
return 0;
}
bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAddress,
const String& emailSubject,
const String& bodyText,
const StringArray& filesToAttach)
{
jassertfalse // xxx todo
return false;
}
END_JUCE_NAMESPACE

+ 12
- 12
build/macosx/platform_specific_code/juce_mac_Files.cpp View File

@@ -471,38 +471,38 @@ void juce_createDirectory (const String& fileName) throw()
void* juce_fileOpen (const String& fileName, bool forWriting) throw()
{
const char* const fileNameUTF8 = fileName.toUTF8();
const char* mode = "rb";
int flags = O_RDONLY;
if (forWriting)
{
if (juce_fileExists (fileName, false))
{
FILE* const f = fopen (fileNameUTF8, "r+b");
const int f = open (fileNameUTF8, O_RDWR, 00644);
if (f != 0)
fseek (f, 0, SEEK_END);
if (f != -1)
lseek (f, 0, SEEK_END);
return (void*) f;
}
else
{
mode = "w+b";
flags = O_RDWR + O_CREAT;
}
}
return (void*) fopen (fileNameUTF8, mode);
return (void*) open (fileNameUTF8, flags, 00644);
}
void juce_fileClose (void* handle) throw()
{
if (handle != 0)
fclose ((FILE*) handle);
close ((int) handle);
}
int juce_fileRead (void* handle, void* buffer, int size) throw()
{
if (handle != 0)
return fread (buffer, 1, size, (FILE*) handle);
return read ((int) handle, buffer, size);
return 0;
}
@@ -510,14 +510,14 @@ int juce_fileRead (void* handle, void* buffer, int size) throw()
int juce_fileWrite (void* handle, const void* buffer, int size) throw()
{
if (handle != 0)
return fwrite (buffer, 1, size, (FILE*) handle);
return write ((int) handle, buffer, size);
return 0;
}
int64 juce_fileSetPosition (void* handle, int64 pos) throw()
{
if (handle != 0 && fseek ((FILE*) handle, pos, SEEK_SET) == 0)
if (handle != 0 && lseek ((int) handle, pos, SEEK_SET) == pos)
return pos;
return -1;
@@ -526,7 +526,7 @@ int64 juce_fileSetPosition (void* handle, int64 pos) throw()
int64 juce_fileGetPosition (void* handle) throw()
{
if (handle != 0)
return ftell ((FILE*) handle);
return lseek ((int) handle, 0, SEEK_CUR);
else
return -1;
}
@@ -534,7 +534,7 @@ int64 juce_fileGetPosition (void* handle) throw()
void juce_fileFlush (void* handle) throw()
{
if (handle != 0)
fflush ((FILE*) handle);
fsync ((int) handle);
}
const StringArray juce_getFileSystemRoots() throw()


+ 31
- 33
build/macosx/platform_specific_code/juce_mac_HTTPStream.h View File

@@ -58,7 +58,8 @@ public:
//==============================================================================
bool open (const String& url,
const String& optionalPostText,
const String& headers,
const MemoryBlock& postData,
const bool isPost)
{
closeSocket();
@@ -101,15 +102,14 @@ public:
if (! proxyURL.startsWithIgnoreCase (T("http://")))
proxyURL = String::empty;
const String requestHeader (createRequestHeader (hostName, hostPath,
proxyURL, url,
hostPort, optionalPostText,
isPost));
const MemoryBlock requestHeader (createRequestHeader (hostName, hostPath,
proxyURL, url,
hostPort,
headers, postData,
isPost));
const char* const utf8Header = (const char*) requestHeader.toUTF8();
const int headerLen = strlen (utf8Header);
if (! send (socketHandle, utf8Header, headerLen, 0) == headerLen)
if (send (socketHandle, requestHeader.getData(), requestHeader.getSize(), 0)
!= requestHeader.getSize())
{
closeSocket();
return false;
@@ -140,7 +140,7 @@ public:
location = T("http://") + location;
if (levelsOfRedirection++ < 3)
return open (location, optionalPostText, isPost);
return open (location, headers, postData, isPost);
}
else
{
@@ -191,13 +191,14 @@ private:
socketHandle = -1;
}
const String createRequestHeader (const String& hostName,
const String& hostPath,
const String& proxyURL,
const String& originalURL,
const int hostPort,
const String& optionalPostText,
const bool isPost)
const MemoryBlock createRequestHeader (const String& hostName,
const String& hostPath,
const String& proxyURL,
const String& originalURL,
const int hostPort,
const String& headers,
const MemoryBlock& postData,
const bool isPost)
{
String header (isPost ? "POST " : "GET ");
@@ -212,7 +213,7 @@ private:
int proxyPort;
if (! decomposeURL (proxyURL, proxyName, proxyPath, proxyPort))
return String::empty;
return MemoryBlock();
header << originalURL << " HTTP/1.1\r\nHost: "
<< proxyName << ':' << proxyPort;
@@ -226,20 +227,14 @@ private:
header << "\r\nUser-Agent: JUCE/"
<< JUCE_MAJOR_VERSION << '.' << JUCE_MINOR_VERSION
<< "\r\nConnection: Close\r\n";
<< "\r\nConnection: Close\r\n"
<< headers << "\r\n";
if (isPost && optionalPostText.isNotEmpty())
{
const char* const postTextUTF8 = (const char*) optionalPostText.toUTF8();
header << "Content-type: application/x-www-form-urlencoded\r\nContent-length: "
<< (int) strlen (postTextUTF8) << "\r\n\r\n"
<< optionalPostText;
}
MemoryBlock mb;
mb.append (header.toUTF8(), (int) strlen (header.toUTF8()));
mb.append (postData.getData(), postData.getSize());
header << "\r\n";
//DBG (header);
return header;
return mb;
}
const String readResponse()
@@ -341,12 +336,15 @@ bool juce_isOnLine()
}
void* juce_openInternetFile (const String& url,
const String& optionalPostText,
const bool isPost)
const String& headers,
const MemoryBlock& postData,
const bool isPost,
URL::OpenStreamProgressCallback* callback,
void* callbackContext)
{
JUCE_HTTPSocketStream* const s = new JUCE_HTTPSocketStream();
if (s->open (url, optionalPostText, isPost))
if (s->open (url, headers, postData, isPost))
return s;
delete s;


+ 191
- 137
build/macosx/platform_specific_code/juce_mac_Network.cpp View File

@@ -1,137 +1,191 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-7 by Raw Material Software ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the
GNU General Public License, as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
JUCE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with JUCE; if not, visit www.gnu.org/licenses or write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
------------------------------------------------------------------------------
If you'd like to release a closed-source product which uses JUCE, commercial
licenses are also available: visit www.rawmaterialsoftware.com/juce for
more information.
==============================================================================
*/
#include "../../../src/juce_core/basics/juce_StandardHeader.h"
#include <IOKit/IOKitLib.h>
#include <IOKit/network/IOEthernetInterface.h>
#include <IOKit/network/IONetworkInterface.h>
#include <IOKit/network/IOEthernetController.h>
#include <Carbon/Carbon.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
BEGIN_JUCE_NAMESPACE
#include "../../../src/juce_core/text/juce_String.h"
#include "../../../src/juce_core/basics/juce_Time.h"
#include "../../../src/juce_core/basics/juce_SystemStats.h"
#include "../../../src/juce_core/containers/juce_MemoryBlock.h"
#include "../../../src/juce_core/text/juce_StringArray.h"
#include "juce_mac_HTTPStream.h"
//==============================================================================
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) 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 (numResults < maxNum)
{
*addresses++ = a;
++numResults;
}
}
IOObjectRelease (controller);
}
IOObjectRelease (i);
}
IOObjectRelease (it);
}
return numResults;
}
END_JUCE_NAMESPACE
/*
==============================================================================

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

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

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

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

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

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

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

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

#include "../../../src/juce_core/basics/juce_StandardHeader.h"
#include <IOKit/IOKitLib.h>
#include <IOKit/network/IOEthernetInterface.h>
#include <IOKit/network/IONetworkInterface.h>
#include <IOKit/network/IOEthernetController.h>
#include <Carbon/Carbon.h>

#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>

BEGIN_JUCE_NAMESPACE

#include "../../../src/juce_core/text/juce_String.h"
#include "../../../src/juce_core/basics/juce_Time.h"
#include "../../../src/juce_core/basics/juce_SystemStats.h"
#include "../../../src/juce_core/containers/juce_MemoryBlock.h"
#include "../../../src/juce_core/text/juce_StringArray.h"
#include "../../../src/juce_core/misc/juce_PlatformUtilities.h"
#include "../../../src/juce_core/io/network/juce_URL.h"
#include "juce_mac_HTTPStream.h"


//==============================================================================
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)
{
String script;
script << "tell application \"Mail\"\r\n"
"set newMessage to make new outgoing message with properties {subject:\""
<< emailSubject
<< "\", content:\""
<< bodyText
<< "\" & 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]
<< "\"} at after the last paragraph\r\n"
"end tell\r\n";
}

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

DBG (script);
ComponentInstance comp = OpenDefaultComponent (kOSAComponentType, kOSAGenericScriptingComponentSubtype);
OSAID resultID;
AEDesc source;
AECreateDesc (typeUTF8Text, (Ptr) script.toUTF8(), strlen (script.toUTF8()), &source);
OSAError err = OSACompileExecute (comp, &source,
kOSANullScript, kOSAModeNull,
&resultID);
AEDisposeDesc (&source);
CloseComponent (comp);

return false;
}


END_JUCE_NAMESPACE

+ 3604
- 3582
build/macosx/platform_specific_code/juce_mac_Windowing.cpp
File diff suppressed because it is too large
View File


+ 116
- 27
build/win32/platform_specific_code/juce_win32_Network.cpp View File

@@ -38,6 +38,7 @@
#include <wininet.h>
#include <nb30.h>
#include <iphlpapi.h>
#include <mapi.h>
#include "../../../src/juce_core/basics/juce_StandardHeader.h"
BEGIN_JUCE_NAMESPACE
@@ -46,6 +47,8 @@ BEGIN_JUCE_NAMESPACE
#include "juce_win32_DynamicLibraryLoader.h"
#include "../../../src/juce_core/basics/juce_SystemStats.h"
#include "../../../src/juce_core/containers/juce_MemoryBlock.h"
#include "../../../src/juce_core/misc/juce_PlatformUtilities.h"
#include "../../../src/juce_core/io/network/juce_URL.h"
#ifndef INTERNET_FLAG_NEED_FILE
#define INTERNET_FLAG_NEED_FILE 0x00000010
@@ -72,11 +75,16 @@ struct ConnectionAndRequestStruct
static HINTERNET sessionHandle = 0;
void* juce_openInternetFile (const String& url,
const String& postText,
const bool isPost)
const String& headers,
const MemoryBlock& postData,
const bool isPost,
URL::OpenStreamProgressCallback* callback,
void* callbackContext)
{
if (sessionHandle == 0)
sessionHandle = InternetOpen (_T("juce"), INTERNET_OPEN_TYPE_PRECONFIG, 0, 0, 0);
sessionHandle = InternetOpen (_T("juce"),
INTERNET_OPEN_TYPE_PRECONFIG,
0, 0, 0);
if (sessionHandle != 0)
{
@@ -92,9 +100,7 @@ void* juce_openInternetFile (const String& url,
uc.lpszUrlPath = file;
uc.lpszHostName = server;
if (InternetCrackUrl (url, 0,
ICU_ESCAPE | ICU_DECODE,
&uc))
if (InternetCrackUrl (url, 0, ICU_ESCAPE | ICU_DECODE, &uc))
{
const bool isFtp = url.startsWithIgnoreCase (T("ftp:"));
@@ -102,8 +108,8 @@ void* juce_openInternetFile (const String& url,
uc.lpszHostName,
uc.nPort,
_T(""), _T(""),
(isFtp) ? INTERNET_SERVICE_FTP
: INTERNET_SERVICE_HTTP,
isFtp ? INTERNET_SERVICE_FTP
: INTERNET_SERVICE_HTTP,
0, 0);
if (connection != 0)
@@ -129,24 +135,52 @@ void* juce_openInternetFile (const String& url,
isPost ? _T("POST")
: _T("GET"),
uc.lpszUrlPath,
0, 0,
mimeTypes,
INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE, 0);
0, 0, mimeTypes,
INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE,
0);
if (request != 0)
{
// (this header is needed to make webservers process a POST request correctly)
const String hdr ("Content-Type: application/x-www-form-urlencoded");
if (HttpSendRequest (request,
hdr, hdr.length(),
(void*) (const char*) postText,
postText.length()))
INTERNET_BUFFERS buffers;
zerostruct (buffers);
buffers.dwStructSize = sizeof (INTERNET_BUFFERS);
buffers.lpcszHeader = (const char*) headers;
buffers.dwHeadersLength = headers.length();
buffers.dwBufferTotal = (DWORD) postData.getSize();
ConnectionAndRequestStruct* result = 0;
if (HttpSendRequestEx (request, &buffers, 0, HSR_INITIATE, 0))
{
ConnectionAndRequestStruct* const result = new ConnectionAndRequestStruct();
result->connection = connection;
result->request = request;
return result;
int bytesSent = 0;
for (;;)
{
const int bytesToDo = jmin (1024, postData.getSize() - bytesSent);
DWORD bytesDone = 0;
if (bytesToDo > 0
&& ! InternetWriteFile (request,
((const char*) postData.getData()) + bytesSent,
bytesToDo, &bytesDone))
{
break;
}
if (bytesToDo == 0 || (int) bytesDone < bytesToDo)
{
result = new ConnectionAndRequestStruct();
result->connection = connection;
result->request = request;
HttpEndRequest (request, 0, 0, 0);
return result;
}
bytesSent += bytesDone;
if (callback != 0 && ! callback (callbackContext, bytesSent, postData.getSize()))
break;
}
}
InternetCloseHandle (request);
@@ -222,7 +256,8 @@ void juce_closeInternetFile (void* handle)
}
}
static int getMACAddressViaGetAdaptersInfo (int64* addresses, int maxNum) throw()
//==============================================================================
static int getMACAddressViaGetAdaptersInfo (int64* addresses, int maxNum, const bool littleEndian) throw()
{
int numFound = 0;
@@ -251,6 +286,9 @@ static int getMACAddressViaGetAdaptersInfo (int64* addresses, int maxNum) throw(
for (unsigned int i = 0; i < adapter->AddressLength; ++i)
mac = (mac << 8) | adapter->Address[i];
if (littleEndian)
mac = (int64) swapByteOrder ((uint64) mac);
if (numFound < maxNum && mac != 0)
addresses [numFound++] = mac;
@@ -262,7 +300,7 @@ static int getMACAddressViaGetAdaptersInfo (int64* addresses, int maxNum) throw(
return numFound;
}
static int getMACAddressesViaNetBios (int64* addresses, int maxNum) throw()
static int getMACAddressesViaNetBios (int64* addresses, int maxNum, const bool littleEndian) throw()
{
int numFound = 0;
@@ -315,6 +353,9 @@ static int getMACAddressesViaNetBios (int64* addresses, int maxNum) throw()
for (unsigned int i = 0; i < 6; ++i)
mac = (mac << 8) | astat.adapt.adapter_address[i];
if (littleEndian)
mac = (int64) swapByteOrder ((uint64) mac);
if (numFound < maxNum && mac != 0)
addresses [numFound++] = mac;
}
@@ -326,14 +367,62 @@ static int getMACAddressesViaNetBios (int64* addresses, int maxNum) throw()
return numFound;
}
int SystemStats::getMACAddresses (int64* addresses, int maxNum) throw()
int SystemStats::getMACAddresses (int64* addresses, int maxNum, const bool littleEndian) throw()
{
int numFound = getMACAddressViaGetAdaptersInfo (addresses, maxNum);
int numFound = getMACAddressViaGetAdaptersInfo (addresses, maxNum, littleEndian);
if (numFound == 0)
numFound = getMACAddressesViaNetBios (addresses, maxNum);
numFound = getMACAddressesViaNetBios (addresses, maxNum, littleEndian);
return numFound;
}
//==============================================================================
typedef ULONG (WINAPI *MAPISendMailType) (LHANDLE, ULONG, lpMapiMessage, FLAGS, ULONG);
bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAddress,
const String& emailSubject,
const String& bodyText,
const StringArray& filesToAttach)
{
HMODULE h = LoadLibraryA ("MAPI32.dll");
MAPISendMailType mapiSendMail = (MAPISendMailType) GetProcAddress (h, "MAPISendMail");
bool ok = false;
if (mapiSendMail != 0)
{
MapiMessage message;
zerostruct (message);
message.lpszSubject = (LPTSTR) (LPCTSTR) emailSubject;
message.lpszNoteText = (LPTSTR) (LPCTSTR) bodyText;
MapiRecipDesc recip;
zerostruct (recip);
recip.ulRecipClass = MAPI_TO;
recip.lpszName = (LPTSTR) (LPCTSTR) targetEmailAddress;
message.nRecipCount = 1;
message.lpRecips = &recip;
MemoryBlock mb (sizeof (MapiFileDesc) * filesToAttach.size());
mb.fillWith (0);
MapiFileDesc* files = (MapiFileDesc*) mb.getData();
message.nFileCount = filesToAttach.size();
message.lpFiles = files;
for (int i = 0; i < filesToAttach.size(); ++i)
{
files[i].nPosition = (ULONG) -1;
files[i].lpszPathName = (LPTSTR) (LPCTSTR) filesToAttach [i];
}
ok = (mapiSendMail (0, 0, &message, MAPI_DIALOG, 0) == SUCCESS_SUCCESS);
}
FreeLibrary (h);
return ok;
}
END_JUCE_NAMESPACE

+ 1
- 1
juce_Config.h View File

@@ -141,7 +141,7 @@
/** Enabling this builds support for VST audio plugins.
@see VSTPluginFormat, AudioPluginFormat, AudioPluginFormatManager, JUCE_PLUGINHOST_AU
*/
#define JUCE_PLUGINHOST_VST 1
//#define JUCE_PLUGINHOST_VST 1
/** Enabling this builds support for AudioUnit audio plugins.
@see AudioUnitPluginFormat, AudioPluginFormat, AudioPluginFormatManager, JUCE_PLUGINHOST_VST


+ 8
- 3
src/juce_appframework/gui/components/controls/juce_ListBox.cpp View File

@@ -666,11 +666,16 @@ int ListBox::getRowNumberOfComponent (Component* const rowComponent) const throw
return viewport->getRowNumberOfComponent (rowComponent);
}
const Rectangle ListBox::getRowPosition (const int rowNumber) const throw()
const Rectangle ListBox::getRowPosition (const int rowNumber,
const bool relativeToComponentTopLeft) const throw()
{
const int rowHeight = getRowHeight();
int y = viewport->getY() + rowHeight * rowNumber;
return Rectangle (0, rowHeight * rowNumber,
if (relativeToComponentTopLeft)
y -= viewport->getViewPositionY();
return Rectangle (viewport->getX(), y,
viewport->getViewedComponent()->getWidth(), rowHeight);
}
@@ -890,7 +895,7 @@ void ListBox::setHeaderComponent (Component* const newHeaderComponent)
void ListBox::repaintRow (const int rowNumber) throw()
{
const Rectangle r (getRowPosition (rowNumber));
const Rectangle r (getRowPosition (rowNumber, true));
repaint (r.getX(), r.getY(), r.getWidth(), r.getHeight());
}


+ 2
- 1
src/juce_appframework/gui/components/controls/juce_ListBox.h View File

@@ -402,7 +402,8 @@ public:
This may be off-screen, and the range of the row number that is passed-in is
not checked to see if it's a valid row.
*/
const Rectangle getRowPosition (const int rowNumber) const throw();
const Rectangle getRowPosition (const int rowNumber,
const bool relativeToComponentTopLeft) const throw();
/** Finds the row component for a given row in the list.


+ 2
- 2
src/juce_appframework/gui/components/controls/juce_Slider.cpp View File

@@ -598,7 +598,7 @@ double Slider::getValueFromText (const String& text)
while (t.startsWithChar (T('+')))
t = t.substring (1).trimStart();
return t.initialSectionContainingOnly (T("0123456789.-"))
return t.initialSectionContainingOnly (T("0123456789.,-"))
.getDoubleValue();
}
@@ -847,7 +847,7 @@ void Slider::resized()
}
}
const int indent = getLookAndFeel().getSliderThumbRadius (*this) + 2;
const int indent = getLookAndFeel().getSliderThumbRadius (*this);
if (style == LinearBar)
{


+ 10
- 4
src/juce_appframework/gui/components/controls/juce_TableListBox.cpp View File

@@ -388,10 +388,16 @@ bool TableListBox::isAutoSizeMenuOptionShown() const throw()
return autoSizeOptionsShown;
}
const Rectangle TableListBox::getCellPosition (const int columnId, const int rowNumber) const
const Rectangle TableListBox::getCellPosition (const int columnId,
const int rowNumber,
const bool relativeToComponentTopLeft) const
{
const Rectangle headerCell (header->getColumnPosition (header->getIndexOfColumnId (columnId, true)));
const Rectangle row (getRowPosition (rowNumber));
Rectangle headerCell (header->getColumnPosition (header->getIndexOfColumnId (columnId, true)));
if (relativeToComponentTopLeft)
headerCell.translate (header->getX(), 0);
const Rectangle row (getRowPosition (rowNumber, relativeToComponentTopLeft));
return Rectangle (headerCell.getX(), row.getY(),
headerCell.getWidth(), row.getHeight());
@@ -406,7 +412,7 @@ void TableListBox::scrollToEnsureColumnIsOnscreen (const int columnId)
const Rectangle pos (header->getColumnPosition (header->getIndexOfColumnId (columnId, true)));
double x = scrollbar->getCurrentRangeStart();
double w = scrollbar->getCurrentRangeSize();
const double w = scrollbar->getCurrentRangeSize();
if (pos.getX() < x)
x = pos.getX();


+ 9
- 4
src/juce_appframework/gui/components/controls/juce_TableListBox.h View File

@@ -264,11 +264,16 @@ public:
/** Returns the position of one of the cells in the table.
Co-ordinates are relative to the table component's top-left. The row number isn't
checked to see if it's in-range, but the column ID must exist or this will
return an empty rectangle.
If relativeToComponentTopLeft is true, the co-ordinates are relative to
the table component's top-left. The row number isn't checked to see if it's
in-range, but the column ID must exist or this will return an empty rectangle.
If relativeToComponentTopLeft is false, the co-ords are relative to the
top-left of the table's top-left cell.
*/
const Rectangle getCellPosition (const int columnId, const int rowNumber) const;
const Rectangle getCellPosition (const int columnId,
const int rowNumber,
const bool relativeToComponentTopLeft) const;
/** Scrolls horizontally if necessary to make sure that a particular column is visible.


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

@@ -57,7 +57,7 @@ BEGIN_JUCE_NAMESPACE
#include "../filebrowser/juce_FilenameComponent.h"
#include "../filebrowser/juce_DirectoryContentsDisplayComponent.h"
#include "../filebrowser/juce_FileSearchPathListComponent.h"
#include "../filebrowser/juce_FileBrowserComponent.h"
#include "../filebrowser/juce_FileBrowserComponent.h"
#include "../layout/juce_GroupComponent.h"
#include "../properties/juce_PropertyComponent.h"
#include "../juce_Desktop.h"
@@ -814,6 +814,9 @@ void LookAndFeel::getIdealPopupMenuItemSize (const String& text,
{
Font font (getPopupMenuFont());
if (standardMenuItemHeight > 0 && font.getHeight() > standardMenuItemHeight / 1.3f)
font.setHeight (standardMenuItemHeight / 1.3f);
idealHeight = standardMenuItemHeight > 0 ? standardMenuItemHeight : roundFloatToInt (font.getHeight() * 1.3f);
idealWidth = font.getStringWidth (text) + idealHeight * 2;
}
@@ -1137,7 +1140,7 @@ void LookAndFeel::drawLinearSliderBackground (Graphics& g,
const Slider::SliderStyle /*style*/,
Slider& slider)
{
const float sliderRadius = (float) getSliderThumbRadius (slider);
const float sliderRadius = (float) (getSliderThumbRadius (slider) - 2);
const Colour trackColour (slider.findColour (Slider::trackColourId));
const Colour gradCol1 (trackColour.overlaidWith (Colours::black.withAlpha (slider.isEnabled() ? 0.25f : 0.13f)));
@@ -1186,7 +1189,7 @@ void LookAndFeel::drawLinearSliderThumb (Graphics& g,
const Slider::SliderStyle style,
Slider& slider)
{
const float sliderRadius = (float) getSliderThumbRadius (slider);
const float sliderRadius = (float) (getSliderThumbRadius (slider) - 2);
Colour knobColour (createBaseColour (slider.findColour (Slider::thumbColourId),
slider.hasKeyboardFocus (false) && slider.isEnabled(),
@@ -1277,7 +1280,7 @@ void LookAndFeel::drawLinearSlider (Graphics& g,
Colour baseColour (createBaseColour (slider.findColour (Slider::thumbColourId)
.withMultipliedSaturation (slider.isEnabled() ? 1.0f : 0.5f),
false,
isMouseOver,
isMouseOver,
isMouseOver || slider.isMouseButtonDown()));
drawShinyButtonShape (g,
@@ -1297,7 +1300,7 @@ int LookAndFeel::getSliderThumbRadius (Slider& slider)
{
return jmin (7,
slider.getHeight() / 2,
slider.getWidth() / 2);
slider.getWidth() / 2) + 2;
}
void LookAndFeel::drawRotarySlider (Graphics& g,
@@ -2358,7 +2361,7 @@ void LookAndFeel::drawFileBrowserRow (Graphics& g, int width, int height,
Button* LookAndFeel::createFileBrowserGoUpButton()
{
DrawableButton* goUpButton = new DrawableButton ("up", DrawableButton::ImageOnButtonBackground);
Path arrowPath;
arrowPath.addArrow (50.0f, 100.0f, 50.0f, 0.0, 40.0f, 100.0f, 50.0f);


+ 10
- 0
src/juce_core/basics/juce_SystemStats.cpp View File

@@ -40,6 +40,7 @@ BEGIN_JUCE_NAMESPACE
#include "juce_Atomic.h"
#include "../threads/juce_Thread.h"
#include "../text/juce_LocalisedStrings.h"
void juce_initialiseStrings();
//==============================================================================
@@ -78,6 +79,7 @@ void JUCE_PUBLIC_FUNCTION initialiseJuce_NonGUI()
juceInitialisedNonGUI = true;
DBG (SystemStats::getJUCEVersion());
juce_initialiseStrings();
SystemStats::initialiseStats();
Random::getSystemRandom().setSeed (Time::currentTimeMillis());
}
@@ -89,6 +91,10 @@ void JUCE_PUBLIC_FUNCTION initialiseJuce_NonGUI()
extern juce_CloseWin32SocketLibCall* juce_CloseWin32SocketLib;
#endif
#if JUCE_DEBUG
extern void juce_CheckForDanglingStreams();
#endif
void JUCE_PUBLIC_FUNCTION shutdownJuce_NonGUI()
{
if (juceInitialisedNonGUI)
@@ -102,6 +108,10 @@ void JUCE_PUBLIC_FUNCTION shutdownJuce_NonGUI()
LocalisedStrings::setCurrentMappings (0);
Thread::stopAllThreads (3000);
#if JUCE_DEBUG
juce_CheckForDanglingStreams();
#endif
juceInitialisedNonGUI = false;
}
}


+ 13
- 1
src/juce_core/basics/juce_SystemStats.h View File

@@ -152,9 +152,21 @@ public:
@param addresses an array into which the MAC addresses should be copied
@param maxNum the number of elements in this array
@param littleEndian the endianness of the numbers to return. Note that
the default values of this parameter are different on
Mac/PC to avoid breaking old software that was written
before this parameter was added (when the two systems
defaulted to using different endiannesses). In newer
software you probably want to specify an explicit value
for this.
@returns the number of MAC addresses that were found
*/
static int getMACAddresses (int64* addresses, int maxNum) throw();
static int getMACAddresses (int64* addresses, int maxNum,
#if JUCE_MAC
const bool littleEndian = true) throw();
#else
const bool littleEndian = false) throw();
#endif
//==============================================================================


+ 147
- 36
src/juce_core/io/network/juce_URL.cpp View File

@@ -35,6 +35,7 @@ BEGIN_JUCE_NAMESPACE
#include "juce_URL.h"
#include "../../basics/juce_Random.h"
#include "../../text/juce_XmlDocument.h"
@@ -79,7 +80,9 @@ URL::URL (const String& url_)
URL::URL (const URL& other)
: url (other.url),
parameters (other.parameters)
parameters (other.parameters),
filesToUpload (other.filesToUpload),
mimeTypes (other.mimeTypes)
{
}
@@ -87,6 +90,8 @@ const URL& URL::operator= (const URL& other)
{
url = other.url;
parameters = other.parameters;
filesToUpload = other.filesToUpload;
mimeTypes = other.mimeTypes;
return *this;
}
@@ -95,7 +100,7 @@ URL::~URL() throw()
{
}
const String URL::getMangledParameters() const
static const String getMangledParameters (const StringPairArray& parameters)
{
String p;
@@ -104,9 +109,9 @@ const String URL::getMangledParameters() const
if (i > 0)
p += T("&");
p << addEscapeChars (parameters.getAllKeys() [i])
p << URL::addEscapeChars (parameters.getAllKeys() [i])
<< T("=")
<< addEscapeChars (parameters.getAllValues() [i]);
<< URL::addEscapeChars (parameters.getAllValues() [i]);
}
return p;
@@ -115,7 +120,7 @@ const String URL::getMangledParameters() const
const String URL::toString (const bool includeGetParameters) const
{
if (includeGetParameters && parameters.size() > 0)
return url + T("?") + getMangledParameters();
return url + T("?") + getMangledParameters (parameters);
else
return url;
}
@@ -153,8 +158,12 @@ bool URL::isProbablyAnEmailAddress (const String& possibleEmailAddress)
//==============================================================================
void* juce_openInternetFile (const String& url,
const String& optionalPostText,
const bool isPost);
const String& headers,
const MemoryBlock& optionalPostData,
const bool isPost,
URL::OpenStreamProgressCallback* callback,
void* callbackContext);
void juce_closeInternetFile (void* handle);
int juce_readFromInternetFile (void* handle, void* dest, int bytesToRead);
int juce_seekInInternetFile (void* handle, int newPosition);
@@ -164,23 +173,25 @@ int juce_getStatusCodeFor (void* handle);
//==============================================================================
class WebInputStream : public InputStream
{
String url, postText;
int64 position;
bool finished, isPost;
void* handle;
public:
//==============================================================================
WebInputStream (const String& url_,
const String& postText_,
const bool isPost_)
: url (url_),
postText (postText_),
position (0),
WebInputStream (const URL& url,
const bool isPost_,
URL::OpenStreamProgressCallback* const progressCallback_,
void* const progressCallbackContext_)
: position (0),
finished (false),
isPost (isPost_)
isPost (isPost_),
progressCallback (progressCallback_),
progressCallbackContext (progressCallbackContext_)
{
handle = juce_openInternetFile (url, postText, isPost);
server = url.toString (! isPost);
if (isPost_)
createHeadersAndPostData (url);
handle = juce_openInternetFile (server, headers, postData, isPost,
progressCallback_, progressCallbackContext_);
}
~WebInputStream()
@@ -188,7 +199,7 @@ public:
juce_closeInternetFile (handle);
}
bool isError() const
bool isError() const throw()
{
return handle == 0;
}
@@ -253,7 +264,8 @@ public:
position = 0;
finished = false;
handle = juce_openInternetFile (url, postText, isPost);
handle = juce_openInternetFile (server, headers, postData, isPost,
progressCallback, progressCallbackContext);
}
skipNextBytes (wantedPos - position);
@@ -262,26 +274,105 @@ public:
return true;
}
};
InputStream* URL::createInputStream (const bool usePostCommand) const
{
WebInputStream* wi
= (usePostCommand) ? new WebInputStream (url, getMangledParameters(), true)
: new WebInputStream (toString (true), String::empty, false);
//==============================================================================
juce_UseDebuggingNewOperator
if (wi->isError())
private:
String server, headers;
MemoryBlock postData;
int64 position;
bool finished;
const bool isPost;
void* handle;
URL::OpenStreamProgressCallback* const progressCallback;
void* const progressCallbackContext;
void createHeadersAndPostData (const URL& url)
{
delete wi;
wi = 0;
if (url.getFilesToUpload().size() > 0)
{
// need to upload some files, so do it as multi-part...
String boundary (String::toHexString (Random::getSystemRandom().nextInt64()));
headers << "Content-Type: multipart/form-data; boundary=" << boundary << "\r\n";
appendUTF8ToPostData ("--" + boundary);
int i;
for (i = 0; i < url.getParameters().size(); ++i)
{
String s;
s << "\r\nContent-Disposition: form-data; name=\""
<< url.getParameters().getAllKeys() [i]
<< "\"\r\n\r\n"
<< url.getParameters().getAllValues() [i]
<< "\r\n--"
<< boundary;
appendUTF8ToPostData (s);
}
for (i = 0; i < url.getFilesToUpload().size(); ++i)
{
const File f (url.getFilesToUpload().getAllValues() [i]);
const String paramName (url.getFilesToUpload().getAllKeys() [i]);
String s;
s << "\r\nContent-Disposition: form-data; name=\""
<< paramName
<< "\"; filename=\""
<< f.getFileName()
<< "\"\r\n";
const String mimeType (url.getMimeTypesOfUploadFiles()
.getValue (paramName, String::empty));
if (mimeType.isNotEmpty())
s << "Content-Type: " << mimeType << "\r\n";
s << "Content-Transfer-Encoding: binary\r\n\r\n";
appendUTF8ToPostData (s);
f.loadFileAsData (postData);
s = "\r\n--" + boundary;
appendUTF8ToPostData (s);
}
appendUTF8ToPostData ("--\r\n");
}
else
{
// just a short text attachment, so use simple url encoding..
const String params (getMangledParameters (url.getParameters()));
headers = "Content-Type: application/x-www-form-urlencoded\r\nContent-length: "
+ String ((int) strlen (params.toUTF8()))
+ "\r\n";
appendUTF8ToPostData (params);
}
}
return wi;
}
void appendUTF8ToPostData (const String& text) throw()
{
postData.append (text.toUTF8(),
(int) strlen (text.toUTF8()));
}
WebInputStream (const WebInputStream&);
const WebInputStream& operator= (const WebInputStream&);
};
InputStream* URL::createPostInputStream (const String& postText) const
InputStream* URL::createInputStream (const bool usePostCommand,
OpenStreamProgressCallback* const progressCallback,
void* const progressCallbackContext) const
{
WebInputStream* wi = new WebInputStream (url, postText, true);
WebInputStream* wi = new WebInputStream (*this, usePostCommand,
progressCallback, progressCallbackContext);
if (wi->isError())
{
@@ -338,11 +429,31 @@ const URL URL::withParameter (const String& parameterName,
return u;
}
const StringPairArray& URL::getParameters() const
const URL URL::withFileToUpload (const String& parameterName,
const File& fileToUpload,
const String& mimeType) const
{
URL u (*this);
u.filesToUpload.set (parameterName, fileToUpload.getFullPathName());
u.mimeTypes.set (parameterName, mimeType);
return u;
}
const StringPairArray& URL::getParameters() const throw()
{
return parameters;
}
const StringPairArray& URL::getFilesToUpload() const throw()
{
return filesToUpload;
}
const StringPairArray& URL::getMimeTypesOfUploadFiles() const throw()
{
return mimeTypes;
}
//==============================================================================
const String URL::removeEscapeChars (const String& s)
{


+ 40
- 12
src/juce_core/io/network/juce_URL.h View File

@@ -87,6 +87,18 @@ public:
const URL withParameter (const String& parameterName,
const String& parameterValue) const;
/** Returns a copy of this URl, with a file-upload type parameter added to it.
When performing a POST where one of your parameters is a binary file, this
lets you specify the file.
Note that the filename is stored, but the file itself won't actually be read
until this URL is later used to create a network input stream.
*/
const URL withFileToUpload (const String& parameterName,
const File& fileToUpload,
const String& mimeType) const;
/** Returns a set of all the parameters encoded into the url.
E.g. for the url "www.fish.com?type=haddock&amount=some+fish", this array would
@@ -96,7 +108,18 @@ public:
@see getNamedParameter, withParameter
*/
const StringPairArray& getParameters() const;
const StringPairArray& getParameters() const throw();
/** Returns the set of files that should be uploaded as part of a POST operation.
This is the set of files that were added to the URL with the withFileToUpload()
method.
*/
const StringPairArray& getFilesToUpload() const throw();
/** Returns the set of mime types associated with each of the upload files.
*/
const StringPairArray& getMimeTypesOfUploadFiles() const throw();
//==============================================================================
/** Tries to launch the system's default browser to open the URL.
@@ -119,21 +142,28 @@ public:
static bool isProbablyAnEmailAddress (const String& possibleEmailAddress);
//==============================================================================
/** This callback function can be used by the createInputStream() method.
It allows your app to receive progress updates during a lengthy POST operation. If you
want to continue the operation, this should return true, or false to abort.
*/
typedef bool (OpenStreamProgressCallback) (void* context, int bytesSent, int totalBytes);
/** Attempts to open a stream that can read from this URL.
@param usePostCommand if true, it will try to do use a http 'POST' to pass
the paramters, otherwise it'll encode them into the
URL and do a 'GET'.
@param progressCallback if this is non-zero, it lets you supply a callback function
to keep track of the operation's progress. This can be useful
for lengthy POST operations, so that you can provide user feedback.
@param progressCallbackContext if a callback is specified, this value will be passed to
the function
*/
InputStream* createInputStream (const bool usePostCommand) const;
InputStream* createInputStream (const bool usePostCommand,
OpenStreamProgressCallback* const progressCallback = 0,
void* const progressCallbackContext = 0) const;
/** Attempts to open a stream to read from this URL using a http POST command.
Normally you'd use the createInputStream (true) method instead of this, as
this will pass the given block of text instead of any parameters
that were added to the this URL with the withParameter() method.
*/
InputStream* createPostInputStream (const String& postText) const;
//==============================================================================
/** Tries to download the entire contents of this URL into a binary data block.
@@ -206,9 +236,7 @@ public:
private:
String url;
StringPairArray parameters;
const String getMangledParameters() const;
StringPairArray parameters, filesToUpload, mimeTypes;
};


+ 5
- 0
src/juce_core/misc/juce_PlatformUtilities.h View File

@@ -47,6 +47,11 @@ public:
/** Plays the operating system's default alert 'beep' sound. */
static void beep();
static bool launchEmailWithAttachments (const String& targetEmailAddress,
const String& emailSubject,
const String& bodyText,
const StringArray& filesToAttach);
#if JUCE_MAC || DOXYGEN
//==============================================================================
/** MAC ONLY - Turns a String into a pascal string. */


Loading…
Cancel
Save