diff --git a/Builds/VisualStudio2012/beast.vcxproj b/Builds/VisualStudio2012/beast.vcxproj
index 04af470a2..5872be298 100644
--- a/Builds/VisualStudio2012/beast.vcxproj
+++ b/Builds/VisualStudio2012/beast.vcxproj
@@ -419,6 +419,22 @@
true
true
+
+ true
+ true
+
+
+ true
+ true
+
+
+ true
+ true
+
+
+ true
+ true
+
true
true
diff --git a/Builds/VisualStudio2012/beast.vcxproj.filters b/Builds/VisualStudio2012/beast.vcxproj.filters
index f2f88ba0b..5a57fbb7e 100644
--- a/Builds/VisualStudio2012/beast.vcxproj.filters
+++ b/Builds/VisualStudio2012/beast.vcxproj.filters
@@ -952,5 +952,17 @@
beast_basics\threads
+
+ beast_core\native
+
+
+ beast_core\native
+
+
+ beast_core\native
+
+
+ beast_core\native
+
\ No newline at end of file
diff --git a/modules/beast_core/beast_core.cpp b/modules/beast_core/beast_core.cpp
index 0514b14c5..4bf563e2a 100644
--- a/modules/beast_core/beast_core.cpp
+++ b/modules/beast_core/beast_core.cpp
@@ -201,6 +201,13 @@ namespace beast
#include "native/beast_linux_SystemStats.cpp"
#include "native/beast_linux_Threads.cpp"
+//==============================================================================
+#elif BEAST_BSD
+#include "native/beast_bsd_Files.cpp"
+#include "native/beast_bsd_Network.cpp"
+#include "native/beast_bsd_SystemStats.cpp"
+#include "native/beast_bsd_Threads.cpp"
+
//==============================================================================
#elif BEAST_ANDROID
#include "native/beast_android_Files.cpp"
diff --git a/modules/beast_core/native/beast_BasicNativeHeaders.h b/modules/beast_core/native/beast_BasicNativeHeaders.h
index 5af5a11d7..21249d82f 100644
--- a/modules/beast_core/native/beast_BasicNativeHeaders.h
+++ b/modules/beast_core/native/beast_BasicNativeHeaders.h
@@ -188,8 +188,17 @@
#if BEAST_BSD
#include
+ #include
+ #include
+ #include
#include
#include
+ #include
+ #include
+
+ // This has to be in the global namespace
+ extern char** environ;
+
#else
#include
#include
diff --git a/modules/beast_core/native/beast_bsd_Files.cpp b/modules/beast_core/native/beast_bsd_Files.cpp
new file mode 100644
index 000000000..6487f80fb
--- /dev/null
+++ b/modules/beast_core/native/beast_bsd_Files.cpp
@@ -0,0 +1,373 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Portions of this file are from JUCE.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+ Please visit http://www.juce.com
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+enum
+{
+ U_ISOFS_SUPER_MAGIC = 0x9660, // linux/iso_fs.h
+ U_MSDOS_SUPER_MAGIC = 0x4d44, // linux/msdos_fs.h
+ U_NFS_SUPER_MAGIC = 0x6969, // linux/nfs_fs.h
+ U_SMB_SUPER_MAGIC = 0x517B // linux/smb_fs.h
+};
+
+//==============================================================================
+bool File::copyInternal (const File& dest) const
+{
+ FileInputStream in (*this);
+
+ if (dest.deleteFile())
+ {
+ {
+ FileOutputStream out (dest);
+
+ if (out.failedToOpen())
+ return false;
+
+ if (out.writeFromInputStream (in, -1) == getSize())
+ return true;
+ }
+
+ dest.deleteFile();
+ }
+
+ return false;
+}
+
+void File::findFileSystemRoots (Array& destArray)
+{
+ destArray.add (File ("/"));
+}
+
+//==============================================================================
+bool File::isOnCDRomDrive() const
+{
+ struct statfs buf;
+
+ return statfs (getFullPathName().toUTF8(), &buf) == 0
+ && buf.f_type == (short) U_ISOFS_SUPER_MAGIC;
+}
+
+bool File::isOnHardDisk() const
+{
+ struct statfs buf;
+
+ if (statfs (getFullPathName().toUTF8(), &buf) == 0)
+ {
+ switch (buf.f_type)
+ {
+ case U_ISOFS_SUPER_MAGIC: // CD-ROM
+ case U_MSDOS_SUPER_MAGIC: // Probably floppy (but could be mounted FAT filesystem)
+ case U_NFS_SUPER_MAGIC: // Network NFS
+ case U_SMB_SUPER_MAGIC: // Network Samba
+ return false;
+
+ default:
+ // Assume anything else is a hard-disk (but note it could
+ // be a RAM disk. There isn't a good way of determining
+ // this for sure)
+ return true;
+ }
+ }
+
+ // Assume so if this fails for some reason
+ return true;
+}
+
+bool File::isOnRemovableDrive() const
+{
+ bassertfalse; // xxx not implemented for linux!
+ return false;
+}
+
+bool File::isHidden() const
+{
+ return getFileName().startsWithChar ('.');
+}
+
+//==============================================================================
+namespace
+{
+ File beast_readlink (const String& file, const File& defaultFile)
+ {
+ const size_t size = 8192;
+ HeapBlock buffer;
+ buffer.malloc (size + 4);
+
+ const size_t numBytes = readlink (file.toUTF8(), buffer, size);
+
+ if (numBytes > 0 && numBytes <= size)
+ return File (file).getSiblingFile (String::fromUTF8 (buffer, (int) numBytes));
+
+ return defaultFile;
+ }
+}
+
+File File::getLinkedTarget() const
+{
+ return beast_readlink (getFullPathName().toUTF8(), *this);
+}
+
+//==============================================================================
+static File resolveXDGFolder (const char* const type, const char* const fallbackFolder)
+{
+ StringArray confLines;
+ File ("~/.config/user-dirs.dirs").readLines (confLines);
+
+ for (int i = 0; i < confLines.size(); ++i)
+ {
+ const String line (confLines[i].trimStart());
+
+ if (line.startsWith (type))
+ {
+ // eg. resolve XDG_MUSIC_DIR="$HOME/Music" to /home/user/Music
+ const File f (line.replace ("$HOME", File ("~").getFullPathName())
+ .fromFirstOccurrenceOf ("=", false, false)
+ .trim().unquoted());
+
+ if (f.isDirectory())
+ return f;
+ }
+ }
+
+ return File (fallbackFolder);
+}
+
+const char* const* beast_argv = nullptr;
+int beast_argc = 0;
+
+File File::getSpecialLocation (const SpecialLocationType type)
+{
+ switch (type)
+ {
+ case userHomeDirectory:
+ {
+ const char* homeDir = getenv ("HOME");
+
+ if (homeDir == nullptr)
+ {
+ struct passwd* const pw = getpwuid (getuid());
+ if (pw != nullptr)
+ homeDir = pw->pw_dir;
+ }
+
+ return File (CharPointer_UTF8 (homeDir));
+ }
+
+ case userDocumentsDirectory: return resolveXDGFolder ("XDG_DOCUMENTS_DIR", "~");
+ case userMusicDirectory: return resolveXDGFolder ("XDG_MUSIC_DIR", "~");
+ case userMoviesDirectory: return resolveXDGFolder ("XDG_VIDEOS_DIR", "~");
+ case userPicturesDirectory: return resolveXDGFolder ("XDG_PICTURES_DIR", "~");
+ case userDesktopDirectory: return resolveXDGFolder ("XDG_DESKTOP_DIR", "~/Desktop");
+ case userApplicationDataDirectory: return File ("~");
+ case commonApplicationDataDirectory: return File ("/var");
+ case globalApplicationsDirectory: return File ("/usr");
+
+ case tempDirectory:
+ {
+ File tmp ("/var/tmp");
+
+ if (! tmp.isDirectory())
+ {
+ tmp = "/tmp";
+
+ if (! tmp.isDirectory())
+ tmp = File::getCurrentWorkingDirectory();
+ }
+
+ return tmp;
+ }
+
+ case invokedExecutableFile:
+ if (beast_argv != nullptr && beast_argc > 0)
+ return File (CharPointer_UTF8 (beast_argv[0]));
+ // deliberate fall-through...
+
+ case currentExecutableFile:
+ case currentApplicationFile:
+ return beast_getExecutableFile();
+
+ case hostApplicationPath:
+ return beast_readlink ("/proc/self/exe", beast_getExecutableFile());
+
+ default:
+ bassertfalse; // unknown type?
+ break;
+ }
+
+ return File::nonexistent;
+}
+
+//==============================================================================
+String File::getVersion() const
+{
+ return String::empty; // xxx not yet implemented
+}
+
+//==============================================================================
+bool File::moveToTrash() const
+{
+ if (! exists())
+ return true;
+
+ File trashCan ("~/.Trash");
+
+ if (! trashCan.isDirectory())
+ trashCan = "~/.local/share/Trash/files";
+
+ if (! trashCan.isDirectory())
+ return false;
+
+ return moveFileTo (trashCan.getNonexistentChildFile (getFileNameWithoutExtension(),
+ getFileExtension()));
+}
+
+//==============================================================================
+class DirectoryIterator::NativeIterator::Pimpl
+{
+public:
+ Pimpl (const File& directory, const String& wildCard_)
+ : parentDir (File::addTrailingSeparator (directory.getFullPathName())),
+ wildCard (wildCard_),
+ dir (opendir (directory.getFullPathName().toUTF8()))
+ {
+ }
+
+ ~Pimpl()
+ {
+ if (dir != nullptr)
+ closedir (dir);
+ }
+
+ bool next (String& filenameFound,
+ bool* const isDir, bool* const isHidden, int64* const fileSize,
+ Time* const modTime, Time* const creationTime, bool* const isReadOnly)
+ {
+ if (dir != nullptr)
+ {
+ const char* wildcardUTF8 = nullptr;
+
+ for (;;)
+ {
+ struct dirent* const de = readdir (dir);
+
+ if (de == nullptr)
+ break;
+
+ if (wildcardUTF8 == nullptr)
+ wildcardUTF8 = wildCard.toUTF8();
+
+ if (fnmatch (wildcardUTF8, de->d_name, FNM_CASEFOLD) == 0)
+ {
+ filenameFound = CharPointer_UTF8 (de->d_name);
+
+ updateStatInfoForFile (parentDir + filenameFound, isDir, fileSize, modTime, creationTime, isReadOnly);
+
+ if (isHidden != nullptr)
+ *isHidden = filenameFound.startsWithChar ('.');
+
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+private:
+ String parentDir, wildCard;
+ DIR* dir;
+
+ BEAST_DECLARE_NON_COPYABLE (Pimpl)
+};
+
+DirectoryIterator::NativeIterator::NativeIterator (const File& directory, const String& wildCard)
+ : pimpl (new DirectoryIterator::NativeIterator::Pimpl (directory, wildCard))
+{
+}
+
+DirectoryIterator::NativeIterator::~NativeIterator()
+{
+}
+
+bool DirectoryIterator::NativeIterator::next (String& filenameFound,
+ bool* const isDir, bool* const isHidden, int64* const fileSize,
+ Time* const modTime, Time* const creationTime, bool* const isReadOnly)
+{
+ return pimpl->next (filenameFound, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly);
+}
+
+
+//==============================================================================
+static bool isFileExecutable (const String& filename)
+{
+ beast_statStruct info;
+
+ return beast_stat (filename, info)
+ && S_ISREG (info.st_mode)
+ && access (filename.toUTF8(), X_OK) == 0;
+}
+
+bool Process::openDocument (const String& fileName, const String& parameters)
+{
+ String cmdString (fileName.replace (" ", "\\ ",false));
+ cmdString << " " << parameters;
+
+ if (URL::isProbablyAWebsiteURL (fileName)
+ || cmdString.startsWithIgnoreCase ("file:")
+ || URL::isProbablyAnEmailAddress (fileName)
+ || File::createFileWithoutCheckingPath (fileName).isDirectory()
+ || ! isFileExecutable (fileName))
+ {
+ // create a command that tries to launch a bunch of likely browsers
+ const char* const browserNames[] = { "xdg-open", "/etc/alternatives/x-www-browser", "firefox", "mozilla",
+ "google-chrome", "chromium-browser", "opera", "konqueror" };
+ StringArray cmdLines;
+
+ for (int i = 0; i < numElementsInArray (browserNames); ++i)
+ cmdLines.add (String (browserNames[i]) + " " + cmdString.trim().quoted());
+
+ cmdString = cmdLines.joinIntoString (" || ");
+ }
+
+ const char* const argv[4] = { "/bin/sh", "-c", cmdString.toUTF8(), 0 };
+
+ const int cpid = fork();
+
+ if (cpid == 0)
+ {
+ setsid();
+
+ // Child process
+ execve (argv[0], (char**) argv, environ);
+ exit (0);
+ }
+
+ return cpid >= 0;
+}
+
+void File::revealToUser() const
+{
+ if (isDirectory())
+ startAsProcess();
+ else if (getParentDirectory().exists())
+ getParentDirectory().startAsProcess();
+}
diff --git a/modules/beast_core/native/beast_bsd_Network.cpp b/modules/beast_core/native/beast_bsd_Network.cpp
new file mode 100644
index 000000000..9cc852ca9
--- /dev/null
+++ b/modules/beast_core/native/beast_bsd_Network.cpp
@@ -0,0 +1,461 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Portions of this file are from JUCE.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+ Please visit http://www.juce.com
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+void MACAddress::findAllAddresses (Array& result)
+{
+#if 1
+ bassertfalse; // VFALCO TODO Implement for FreeBSD
+#else
+ const int s = socket (AF_INET, SOCK_DGRAM, 0);
+ if (s != -1)
+ {
+ char buf [1024];
+ struct ifconf ifc;
+ ifc.ifc_len = sizeof (buf);
+ ifc.ifc_buf = buf;
+ ioctl (s, SIOCGIFCONF, &ifc);
+
+ for (unsigned int i = 0; i < ifc.ifc_len / sizeof (struct ifreq); ++i)
+ {
+ struct ifreq ifr;
+ strcpy (ifr.ifr_name, ifc.ifc_req[i].ifr_name);
+
+ if (ioctl (s, SIOCGIFFLAGS, &ifr) == 0
+ && (ifr.ifr_flags & IFF_LOOPBACK) == 0
+ && ioctl (s, SIOCGIFHWADDR, &ifr) == 0)
+ {
+ result.addIfNotAlreadyThere (MACAddress ((const uint8*) ifr.ifr_hwaddr.sa_data));
+ }
+ }
+
+ close (s);
+ }
+#endif
+}
+
+
+bool Process::openEmailWithAttachments (const String& /* targetEmailAddress */,
+ const String& /* emailSubject */,
+ const String& /* bodyText */,
+ const StringArray& /* filesToAttach */)
+{
+ bassertfalse; // xxx todo
+
+ return false;
+}
+
+
+//==============================================================================
+class WebInputStream : public InputStream
+{
+public:
+ WebInputStream (const String& address_, bool isPost_, const MemoryBlock& postData_,
+ URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
+ const String& headers_, int timeOutMs_, StringPairArray* responseHeaders)
+ : socketHandle (-1), levelsOfRedirection (0),
+ address (address_), headers (headers_), postData (postData_), position (0),
+ finished (false), isPost (isPost_), timeOutMs (timeOutMs_)
+ {
+ createConnection (progressCallback, progressCallbackContext);
+
+ if (responseHeaders != nullptr && ! isError())
+ {
+ for (int i = 0; i < headerLines.size(); ++i)
+ {
+ const String& headersEntry = headerLines[i];
+ const String key (headersEntry.upToFirstOccurrenceOf (": ", false, false));
+ const String value (headersEntry.fromFirstOccurrenceOf (": ", false, false));
+ const String previousValue ((*responseHeaders) [key]);
+ responseHeaders->set (key, previousValue.isEmpty() ? value : (previousValue + "," + value));
+ }
+ }
+ }
+
+ ~WebInputStream()
+ {
+ closeSocket();
+ }
+
+ //==============================================================================
+ bool isError() const { return socketHandle < 0; }
+ bool isExhausted() { return finished; }
+ int64 getPosition() { return position; }
+
+ int64 getTotalLength()
+ {
+ //xxx to do
+ return -1;
+ }
+
+ int read (void* buffer, int bytesToRead)
+ {
+ if (finished || isError())
+ return 0;
+
+ fd_set readbits;
+ FD_ZERO (&readbits);
+ FD_SET (socketHandle, &readbits);
+
+ struct timeval tv;
+ tv.tv_sec = bmax (1, timeOutMs / 1000);
+ tv.tv_usec = 0;
+
+ if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0)
+ return 0; // (timeout)
+
+ const int bytesRead = bmax (0, (int) recv (socketHandle, buffer, bytesToRead, MSG_WAITALL));
+ if (bytesRead == 0)
+ finished = true;
+ position += bytesRead;
+ return bytesRead;
+ }
+
+ bool setPosition (int64 wantedPos)
+ {
+ if (isError())
+ return false;
+
+ if (wantedPos != position)
+ {
+ finished = false;
+
+ if (wantedPos < position)
+ {
+ closeSocket();
+ position = 0;
+ createConnection (0, 0);
+ }
+
+ skipNextBytes (wantedPos - position);
+ }
+
+ return true;
+ }
+
+ //==============================================================================
+private:
+ int socketHandle, levelsOfRedirection;
+ StringArray headerLines;
+ String address, headers;
+ MemoryBlock postData;
+ int64 position;
+ bool finished;
+ const bool isPost;
+ const int timeOutMs;
+
+ void closeSocket()
+ {
+ if (socketHandle >= 0)
+ close (socketHandle);
+
+ socketHandle = -1;
+ levelsOfRedirection = 0;
+ }
+
+ void createConnection (URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext)
+ {
+ closeSocket();
+
+ 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 (address, hostName, hostPath, hostPort))
+ return;
+
+ String serverName, proxyName, proxyPath;
+ int proxyPort = 0;
+ int port = 0;
+
+ const String proxyURL (getenv ("http_proxy"));
+ if (proxyURL.startsWithIgnoreCase ("http://"))
+ {
+ if (! decomposeURL (proxyURL, proxyName, proxyPath, proxyPort))
+ return;
+
+ serverName = proxyName;
+ port = proxyPort;
+ }
+ else
+ {
+ serverName = hostName;
+ port = hostPort;
+ }
+
+ struct addrinfo hints;
+ zerostruct (hints);
+
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_NUMERICSERV;
+
+ struct addrinfo* result = nullptr;
+ if (getaddrinfo (serverName.toUTF8(), String (port).toUTF8(), &hints, &result) != 0 || result == 0)
+ return;
+
+ socketHandle = socket (result->ai_family, result->ai_socktype, 0);
+
+ if (socketHandle == -1)
+ {
+ freeaddrinfo (result);
+ return;
+ }
+
+ int receiveBufferSize = 16384;
+ setsockopt (socketHandle, SOL_SOCKET, SO_RCVBUF, (char*) &receiveBufferSize, sizeof (receiveBufferSize));
+ setsockopt (socketHandle, SOL_SOCKET, SO_KEEPALIVE, 0, 0);
+
+ #if BEAST_MAC
+ setsockopt (socketHandle, SOL_SOCKET, SO_NOSIGPIPE, 0, 0);
+ #endif
+
+ if (connect (socketHandle, result->ai_addr, result->ai_addrlen) == -1)
+ {
+ closeSocket();
+ freeaddrinfo (result);
+ return;
+ }
+
+ freeaddrinfo (result);
+
+ {
+ const MemoryBlock requestHeader (createRequestHeader (hostName, hostPort, proxyName, proxyPort,
+ hostPath, address, headers, postData, isPost));
+
+ if (! sendHeader (socketHandle, requestHeader, timeOutTime, progressCallback, progressCallbackContext))
+ {
+ closeSocket();
+ return;
+ }
+ }
+
+ String responseHeader (readResponse (socketHandle, timeOutTime));
+
+ if (responseHeader.isNotEmpty())
+ {
+ headerLines = StringArray::fromLines (responseHeader);
+
+ const int statusCode = responseHeader.fromFirstOccurrenceOf (" ", false, false)
+ .substring (0, 3).getIntValue();
+
+ //int contentLength = findHeaderItem (lines, "Content-Length:").getIntValue();
+ //bool isChunked = findHeaderItem (lines, "Transfer-Encoding:").equalsIgnoreCase ("chunked");
+
+ String location (findHeaderItem (headerLines, "Location:"));
+
+ if (statusCode >= 300 && statusCode < 400 && location.isNotEmpty())
+ {
+ if (! location.startsWithIgnoreCase ("http://"))
+ location = "http://" + location;
+
+ if (++levelsOfRedirection <= 3)
+ {
+ address = location;
+ createConnection (progressCallback, progressCallbackContext);
+ return;
+ }
+ }
+ else
+ {
+ levelsOfRedirection = 0;
+ return;
+ }
+ }
+
+ closeSocket();
+ }
+
+ //==============================================================================
+ static String readResponse (const int socketHandle, const uint32 timeOutTime)
+ {
+ int bytesRead = 0, numConsecutiveLFs = 0;
+ MemoryBlock buffer (1024, true);
+
+ while (numConsecutiveLFs < 2 && bytesRead < 32768
+ && Time::getMillisecondCounter() <= timeOutTime)
+ {
+ fd_set readbits;
+ FD_ZERO (&readbits);
+ FD_SET (socketHandle, &readbits);
+
+ struct timeval tv;
+ tv.tv_sec = bmax (1, (int) (timeOutTime - Time::getMillisecondCounter()) / 1000);
+ 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 (CharPointer_UTF8 ((const char*) buffer.getData()));
+
+ if (header.startsWithIgnoreCase ("HTTP/"))
+ return header.trimEnd();
+
+ return String::empty;
+ }
+
+ static void writeValueIfNotPresent (MemoryOutputStream& dest, const String& headers, const String& key, const String& value)
+ {
+ if (! headers.containsIgnoreCase (key))
+ dest << "\r\n" << key << ' ' << value;
+ }
+
+ static void writeHost (MemoryOutputStream& dest, const bool isPost, const String& path, const String& host, const int port)
+ {
+ dest << (isPost ? "POST " : "GET ") << path << " HTTP/1.0\r\nHost: " << host;
+
+ if (port > 0)
+ dest << ':' << port;
+ }
+
+ static MemoryBlock createRequestHeader (const String& hostName, const int hostPort,
+ const String& proxyName, const int proxyPort,
+ const String& hostPath, const String& originalURL,
+ const String& userHeaders, const MemoryBlock& postData,
+ const bool isPost)
+ {
+ MemoryOutputStream header;
+
+ if (proxyName.isEmpty())
+ writeHost (header, isPost, hostPath, hostName, hostPort);
+ else
+ writeHost (header, isPost, originalURL, proxyName, proxyPort);
+
+ writeValueIfNotPresent (header, userHeaders, "User-Agent:", "BEAST/" BEAST_STRINGIFY(BEAST_MAJOR_VERSION)
+ "." BEAST_STRINGIFY(BEAST_MINOR_VERSION)
+ "." BEAST_STRINGIFY(BEAST_BUILDNUMBER));
+ writeValueIfNotPresent (header, userHeaders, "Connection:", "Close");
+
+ if (isPost)
+ writeValueIfNotPresent (header, userHeaders, "Content-Length:", String ((int) postData.getSize()));
+
+ header << "\r\n" << userHeaders
+ << "\r\n" << postData;
+
+ return header.getMemoryBlock();
+ }
+
+ static bool sendHeader (int socketHandle, const MemoryBlock& requestHeader, const uint32 timeOutTime,
+ URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext)
+ {
+ size_t totalHeaderSent = 0;
+
+ while (totalHeaderSent < requestHeader.getSize())
+ {
+ if (Time::getMillisecondCounter() > timeOutTime)
+ return false;
+
+ const int numToSend = bmin (1024, (int) (requestHeader.getSize() - totalHeaderSent));
+
+ if (send (socketHandle, static_cast (requestHeader.getData()) + totalHeaderSent, numToSend, 0) != numToSend)
+ return false;
+
+ totalHeaderSent += numToSend;
+
+ if (progressCallback != nullptr && ! progressCallback (progressCallbackContext, totalHeaderSent, requestHeader.getSize()))
+ return false;
+ }
+
+ return true;
+ }
+
+ static bool decomposeURL (const String& url, String& host, String& path, int& port)
+ {
+ if (! url.startsWithIgnoreCase ("http://"))
+ return false;
+
+ 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 = "/";
+
+ return true;
+ }
+
+ static 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;
+ }
+
+ BEAST_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebInputStream)
+};
+
+InputStream* URL::createNativeStream (const String& address, bool isPost, const MemoryBlock& postData,
+ OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
+ const String& headers, const int timeOutMs, StringPairArray* responseHeaders)
+{
+ ScopedPointer wi (new WebInputStream (address, isPost, postData,
+ progressCallback, progressCallbackContext,
+ headers, timeOutMs, responseHeaders));
+
+ return wi->isError() ? nullptr : wi.release();
+}
diff --git a/modules/beast_core/native/beast_bsd_SystemStats.cpp b/modules/beast_core/native/beast_bsd_SystemStats.cpp
new file mode 100644
index 000000000..613ca1529
--- /dev/null
+++ b/modules/beast_core/native/beast_bsd_SystemStats.cpp
@@ -0,0 +1,346 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Portions of this file are from JUCE.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+ Please visit http://www.juce.com
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+// sysinfo() from sysinfo-bsd
+// https://code.google.com/p/sysinfo-bsd/
+/*
+ * Copyright (C) 2010 Kostas Petrikas, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name(s) of the author(s) may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define SI_LOAD_SHIFT 16
+struct sysinfo {
+ long uptime; /* Seconds since boot */
+ unsigned long loads[3]; /* 1, 5, and 15 minute load averages */
+ unsigned long totalram; /* Total usable main memory size */
+ unsigned long freeram; /* Available memory size */
+ unsigned long sharedram; /* Amount of shared memory */
+ unsigned long bufferram; /* Memory used by buffers */
+ unsigned long totalswap; /* Total swap space size */
+ unsigned long freeswap; /* swap space still available */
+ unsigned short procs; /* Number of current processes */
+ unsigned short pad; /* leaving this for linux compatability */
+ unsigned long totalhigh; /* Total high memory size */
+ unsigned long freehigh; /* Available high memory size */
+ unsigned int mem_unit; /* Memory unit size in bytes */
+ char _f[20-2*sizeof(long)-sizeof(int)]; /* leaving this for linux compatability */
+};
+
+#define NLOADS 3
+#define UNIT_S 1024 /*Kb*/
+#define R_IGNORE -1
+
+/*the macros*/
+#define R_ERROR(_EC) {if(_EC > R_IGNORE)errno = _EC; return -1;}
+#define GETSYSCTL(name, var) getsysctl((char*)name, &(var), sizeof(var))
+#define PAGE_2_UNIT(_PAGE) (((double)_PAGE * page_s) / UNIT_S)
+
+/*sysctl wrapper*/
+static int getsysctl(char *name, void *ptr, size_t len){
+ size_t nlen = len;
+ if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1)
+ return -1;
+
+ if (nlen != len)
+ return -1;
+
+ return 0;
+}
+
+int sysinfo(struct sysinfo *info){
+ kvm_t *kvmh;
+ double load_avg[NLOADS];
+ int page_s = getpagesize();
+
+ if (info == NULL)
+ R_ERROR(EFAULT);
+
+ memset(info, 0, sizeof(struct sysinfo));
+ info -> mem_unit = UNIT_S;
+
+ /*kvm init*/
+ if ((kvmh = kvm_open(NULL, "/dev/null", "/dev/null",
+ O_RDONLY, "kvm_open")) == NULL)
+ R_ERROR(0);
+
+ /*load averages*/
+ if (kvm_getloadavg(kvmh, load_avg, NLOADS) == -1)
+ R_ERROR(0);
+
+ info -> loads[0] = (u_long)((float)load_avg[0] * USHRT_MAX);
+ info -> loads[1] = (u_long)((float)load_avg[1] * USHRT_MAX);
+ info -> loads[2] = (u_long)((float)load_avg[2] * USHRT_MAX);
+
+ /*swap space*/
+ struct kvm_swap k_swap;
+
+ if (kvm_getswapinfo(kvmh, &k_swap, 1, 0) == -1)
+ R_ERROR(0);
+
+ info -> totalswap =
+ (u_long)PAGE_2_UNIT(k_swap.ksw_total);
+ info -> freeswap = info -> totalswap -
+ (u_long)PAGE_2_UNIT(k_swap.ksw_used);
+
+ /*processes*/
+ int n_procs;
+
+ if (kvm_getprocs(kvmh, KERN_PROC_ALL, 0, &n_procs) == NULL)
+ R_ERROR(0);
+
+ info -> procs = (u_short)n_procs;
+
+ /*end of kvm session*/
+ if (kvm_close(kvmh) == -1)
+ R_ERROR(0);
+
+ /*uptime*/
+ struct timespec ts;
+
+ if (clock_gettime(CLOCK_UPTIME, &ts) == -1)
+ R_ERROR(R_IGNORE);
+
+ info -> uptime = (long)ts.tv_sec;
+
+ /*ram*/
+ int total_pages,
+ free_pages,
+ active_pages,
+ inactive_pages;
+ u_long shmmax;
+
+ if (GETSYSCTL("vm.stats.vm.v_page_count", total_pages) == -1)
+ R_ERROR(R_IGNORE);
+ if (GETSYSCTL("vm.stats.vm.v_free_count", free_pages) == -1)
+ R_ERROR(R_IGNORE);
+ if (GETSYSCTL("vm.stats.vm.v_active_count", active_pages) == -1)
+ R_ERROR(R_IGNORE);
+ if (GETSYSCTL("vm.stats.vm.v_inactive_count", inactive_pages) == -1)
+ R_ERROR(R_IGNORE);
+ if (GETSYSCTL("kern.ipc.shmmax", shmmax) == -1)
+ R_ERROR(R_IGNORE);
+
+ info -> totalram = (u_long)PAGE_2_UNIT(total_pages);
+ info -> freeram = (u_long)PAGE_2_UNIT(free_pages);
+ info -> bufferram = (u_long)PAGE_2_UNIT(active_pages);
+ info -> sharedram = shmmax / UNIT_S;
+
+ /*high mem (todo)*/
+ info -> totalhigh = 0; /*Does this supose to refer to HMA or reserved ram?*/
+ info -> freehigh = 0;
+
+ return 0;
+}
+
+//==============================================================================
+
+void Logger::outputDebugString (const String& text)
+{
+ std::cerr << text << std::endl;
+}
+
+//==============================================================================
+SystemStats::OperatingSystemType SystemStats::getOperatingSystemType()
+{
+ return FreeBSD;
+}
+
+String SystemStats::getOperatingSystemName()
+{
+ return "FreeBSD";
+}
+
+bool SystemStats::isOperatingSystem64Bit()
+
+{
+ #if BEAST_64BIT
+ return true;
+ #else
+ //xxx not sure how to find this out?..
+ return false;
+ #endif
+}
+
+//==============================================================================
+namespace BSDStatsHelpers
+{
+ String getCpuInfo (const char* const key)
+ {
+ StringArray lines;
+ File ("/proc/cpuinfo").readLines (lines);
+
+ for (int i = lines.size(); --i >= 0;) // (NB - it's important that this runs in reverse order)
+ if (lines[i].startsWithIgnoreCase (key))
+ return lines[i].fromFirstOccurrenceOf (":", false, false).trim();
+
+ return String::empty;
+ }
+}
+
+String SystemStats::getCpuVendor()
+{
+ return BSDStatsHelpers::getCpuInfo ("vendor_id");
+}
+
+int SystemStats::getCpuSpeedInMegaherz()
+{
+ return roundToInt (BSDStatsHelpers::getCpuInfo ("cpu MHz").getFloatValue());
+}
+
+int SystemStats::getMemorySizeInMegabytes()
+{
+ struct sysinfo sysi;
+
+ if (sysinfo (&sysi) == 0)
+ return (sysi.totalram * sysi.mem_unit / (1024 * 1024));
+
+ return 0;
+}
+
+int SystemStats::getPageSize()
+{
+ return sysconf (_SC_PAGESIZE);
+}
+
+//==============================================================================
+String SystemStats::getLogonName()
+{
+ const char* user = getenv ("USER");
+
+ if (user == nullptr)
+ {
+ struct passwd* const pw = getpwuid (getuid());
+ if (pw != nullptr)
+ user = pw->pw_name;
+ }
+
+ return CharPointer_UTF8 (user);
+}
+
+String SystemStats::getFullUserName()
+{
+ return getLogonName();
+}
+
+String SystemStats::getComputerName()
+{
+ char name [256] = { 0 };
+ if (gethostname (name, sizeof (name) - 1) == 0)
+ return name;
+
+ return String::empty;
+}
+
+String getLocaleValue (nl_item key)
+{
+ const char* oldLocale = ::setlocale (LC_ALL, "");
+ return String (const_cast (nl_langinfo (key)));
+ ::setlocale (LC_ALL, oldLocale);
+}
+
+String SystemStats::getUserLanguage()
+{
+ return "Uknown user language";
+}
+
+String SystemStats::getUserRegion()
+{
+ return "Unknown user region";
+}
+
+String SystemStats::getDisplayLanguage()
+{
+ return getUserLanguage();
+}
+
+//==============================================================================
+SystemStats::CPUFlags::CPUFlags()
+{
+ const String flags (BSDStatsHelpers::getCpuInfo ("flags"));
+ hasMMX = flags.contains ("mmx");
+ hasSSE = flags.contains ("sse");
+ hasSSE2 = flags.contains ("sse2");
+ has3DNow = flags.contains ("3dnow");
+
+ numCpus = BSDStatsHelpers::getCpuInfo ("processor").getIntValue() + 1;
+}
+
+//==============================================================================
+uint32 beast_millisecondsSinceStartup() noexcept
+{
+ timespec t;
+ clock_gettime (CLOCK_MONOTONIC, &t);
+
+ return t.tv_sec * 1000 + t.tv_nsec / 1000000;
+}
+
+int64 Time::getHighResolutionTicks() noexcept
+{
+ timespec t;
+ clock_gettime (CLOCK_MONOTONIC, &t);
+
+ return (t.tv_sec * (int64) 1000000) + (t.tv_nsec / 1000);
+}
+
+int64 Time::getHighResolutionTicksPerSecond() noexcept
+{
+ return 1000000; // (microseconds)
+}
+
+double Time::getMillisecondCounterHiRes() noexcept
+{
+ return getHighResolutionTicks() * 0.001;
+}
+
+bool Time::setSystemTimeToThisTime() const
+{
+ timeval t;
+ t.tv_sec = millisSinceEpoch / 1000;
+ t.tv_usec = (millisSinceEpoch - t.tv_sec * 1000) * 1000;
+
+ return settimeofday (&t, 0) == 0;
+}
diff --git a/modules/beast_core/native/beast_bsd_Threads.cpp b/modules/beast_core/native/beast_bsd_Threads.cpp
new file mode 100644
index 000000000..5ce0db555
--- /dev/null
+++ b/modules/beast_core/native/beast_bsd_Threads.cpp
@@ -0,0 +1,85 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Portions of this file are from JUCE.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+ Please visit http://www.juce.com
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+/*
+ Note that a lot of methods that you'd expect to find in this file actually
+ live in beast_posix_SharedCode.h!
+*/
+
+//==============================================================================
+void Process::setPriority (const ProcessPriority prior)
+{
+ const int policy = (prior <= NormalPriority) ? SCHED_OTHER : SCHED_RR;
+ const int minp = sched_get_priority_min (policy);
+ const int maxp = sched_get_priority_max (policy);
+
+ struct sched_param param;
+
+ switch (prior)
+ {
+ case LowPriority:
+ case NormalPriority: param.sched_priority = 0; break;
+ case HighPriority: param.sched_priority = minp + (maxp - minp) / 4; break;
+ case RealtimePriority: param.sched_priority = minp + (3 * (maxp - minp) / 4); break;
+ default: bassertfalse; break;
+ }
+
+ pthread_setschedparam (pthread_self(), policy, ¶m);
+}
+
+void Process::terminate()
+{
+ exit (0);
+}
+
+BEAST_API bool BEAST_CALLTYPE beast_isRunningUnderDebugger()
+{
+ static char testResult = 0;
+
+ if (testResult == 0)
+ {
+ testResult = (char) ptrace (PT_TRACE_ME, 0, 0, 0);
+
+ if (testResult >= 0)
+ {
+ ptrace (PT_DETACH, 0, (caddr_t) 1, 0);
+ testResult = 1;
+ }
+ }
+
+ return testResult < 0;
+}
+
+BEAST_API bool BEAST_CALLTYPE Process::isRunningUnderDebugger()
+{
+ return beast_isRunningUnderDebugger();
+}
+
+static void swapUserAndEffectiveUser()
+{
+ (void) setreuid (geteuid(), getuid());
+ (void) setregid (getegid(), getgid());
+}
+
+void Process::raisePrivilege() { if (geteuid() != 0 && getuid() == 0) swapUserAndEffectiveUser(); }
+void Process::lowerPrivilege() { if (geteuid() == 0 && getuid() != 0) swapUserAndEffectiveUser(); }
diff --git a/modules/beast_core/system/beast_StandardHeader.h b/modules/beast_core/system/beast_StandardHeader.h
index ce4e4f7ef..1c7114275 100644
--- a/modules/beast_core/system/beast_StandardHeader.h
+++ b/modules/beast_core/system/beast_StandardHeader.h
@@ -27,7 +27,7 @@
//==============================================================================
/** Current BEAST version number.
- See also SystemStats::getBEASTVersion() for a string version.
+ See also SystemStats::getBeastVersion() for a string version.
*/
#define BEAST_MAJOR_VERSION 0
#define BEAST_MINOR_VERSION 0
@@ -39,7 +39,7 @@
Bits 8 to 16 = minor version.
Bits 0 to 8 = point release.
- See also SystemStats::getBEASTVersion() for a string version.
+ See also SystemStats::getBeastVersion() for a string version.
*/
#define BEAST_VERSION ((BEAST_MAJOR_VERSION << 16) + (BEAST_MINOR_VERSION << 8) + BEAST_BUILDNUMBER)
diff --git a/modules/beast_core/system/beast_SystemStats.cpp b/modules/beast_core/system/beast_SystemStats.cpp
index 07a8b43c8..81d3b5e1c 100644
--- a/modules/beast_core/system/beast_SystemStats.cpp
+++ b/modules/beast_core/system/beast_SystemStats.cpp
@@ -27,7 +27,7 @@ const SystemStats::CPUFlags& SystemStats::getCPUFlags()
return cpuFlags;
}
-String SystemStats::getBEASTVersion()
+String SystemStats::getBeastVersion()
{
// Some basic tests, to keep an eye on things and make sure these types work ok
// on all platforms. Let me know if any of these assertions fail on your system!
@@ -41,7 +41,7 @@ String SystemStats::getBEASTVersion()
static_bassert (sizeof (int64) == 8);
static_bassert (sizeof (uint64) == 8);
- return "BEAST v" BEAST_STRINGIFY(BEAST_MAJOR_VERSION)
+ return "Beast v" BEAST_STRINGIFY(BEAST_MAJOR_VERSION)
"." BEAST_STRINGIFY(BEAST_MINOR_VERSION)
"." BEAST_STRINGIFY(BEAST_BUILDNUMBER);
}
@@ -55,7 +55,7 @@ String SystemStats::getBEASTVersion()
{
BeastVersionPrinter()
{
- DBG (SystemStats::getBEASTVersion());
+ DBG (SystemStats::getBeastVersion());
}
};
diff --git a/modules/beast_core/system/beast_SystemStats.h b/modules/beast_core/system/beast_SystemStats.h
index 761f7c91b..16f004ea4 100644
--- a/modules/beast_core/system/beast_SystemStats.h
+++ b/modules/beast_core/system/beast_SystemStats.h
@@ -26,7 +26,6 @@
#include "../text/beast_StringArray.h"
-
//==============================================================================
/**
Contains methods for finding out about the current hardware and OS configuration.
@@ -38,7 +37,7 @@ public:
/** Returns the current version of BEAST,
See also the BEAST_VERSION, BEAST_MAJOR_VERSION and BEAST_MINOR_VERSION macros.
*/
- static String getBEASTVersion();
+ static String getBeastVersion();
//==============================================================================
/** The set of possible results of the getOperatingSystemType() method. */
@@ -46,16 +45,16 @@ public:
{
UnknownOS = 0,
- Linux = 0x2000,
- Android = 0x3000,
- iOS = 0x8000,
-
MacOSX_10_4 = 0x1004,
MacOSX_10_5 = 0x1005,
MacOSX_10_6 = 0x1006,
MacOSX_10_7 = 0x1007,
MacOSX_10_8 = 0x1008,
+ Linux = 0x2000,
+ FreeBSD = 0x2001,
+ Android = 0x3000,
+
Win2000 = 0x4105,
WinXP = 0x4106,
WinVista = 0x4107,
@@ -64,6 +63,8 @@ public:
Windows = 0x4000, /**< To test whether any version of Windows is running,
you can use the expression ((getOperatingSystemType() & Windows) != 0). */
+
+ iOS = 0x8000
};
/** Returns the type of operating system we're running on.