diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 8e87742a76..4d07c6b846 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -6515,12 +6515,10 @@ END_JUCE_NAMESPACE #include #include #include - #include #include - #else - #include #endif + #include #include #include #include diff --git a/juce_amalgamated.h b/juce_amalgamated.h index b0ac88ed80..a0f6645777 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -335,7 +335,7 @@ #if JUCE_MAC - #include + #include #ifndef NDEBUG #define JUCE_DEBUG 1 @@ -632,8 +632,12 @@ #include #endif -#if JUCE_MAC && ! MACOS_10_3_OR_EARLIER - #include +#if JUCE_MAC + #if MACOS_10_3_OR_EARLIER + #include + #else + #include + #endif #endif #if JUCE_LINUX diff --git a/src/juce_core/basics/juce_PlatformDefs.h b/src/juce_core/basics/juce_PlatformDefs.h index 2b8b50b048..3406d9c5f8 100644 --- a/src/juce_core/basics/juce_PlatformDefs.h +++ b/src/juce_core/basics/juce_PlatformDefs.h @@ -1,369 +1,369 @@ -/* - ============================================================================== - - 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. - - ============================================================================== -*/ - -#ifndef __JUCE_PLATFORMDEFS_JUCEHEADER__ -#define __JUCE_PLATFORMDEFS_JUCEHEADER__ - -//============================================================================== -/* This file figures out which platform is being built, and defines some macros - that the rest of the code can use for OS-specific compilation. - - Macros that will be set here are: - - - One of JUCE_WIN32, JUCE_MAC or JUCE_LINUX. - - Either JUCE_32BIT or JUCE_64BIT, depending on the architecture. - - Either JUCE_LITTLE_ENDIAN or JUCE_BIG_ENDIAN. - - Either JUCE_INTEL or JUCE_PPC - - Either JUCE_GCC or JUCE_MSVC - - On the Mac, it also defines MACOS_10_2_OR_EARLIER if the build is targeting OSX10.2, - and MACOS_10_3_OR_EARLIER if it is targeting either 10.2 or 10.3 - - It also includes a set of macros for debug console output and assertions. - -*/ - -//============================================================================== -#if (defined (_WIN32) || defined (_WIN64)) - #define JUCE_WIN32 1 -#else - #if defined (LINUX) || defined (__linux__) - #define JUCE_LINUX 1 - #else - #define JUCE_MAC 1 - #endif -#endif - -//============================================================================== -#if JUCE_WIN32 - #ifdef _MSC_VER - #ifdef _WIN64 - #define JUCE_64BIT 1 - #else - #define JUCE_32BIT 1 - #endif - #endif - - #ifdef _DEBUG - #define JUCE_DEBUG 1 - #endif - - /** If defined, this indicates that the processor is little-endian. */ - #define JUCE_LITTLE_ENDIAN 1 - - #define JUCE_INTEL 1 -#endif - -//============================================================================== -#if JUCE_MAC - - #include - - #ifndef NDEBUG - #define JUCE_DEBUG 1 - #endif - - #ifdef __LITTLE_ENDIAN__ - #define JUCE_LITTLE_ENDIAN 1 - #else - #define JUCE_BIG_ENDIAN 1 - #endif - - #if defined (__ppc__) || defined (__ppc64__) - #define JUCE_PPC 1 - #else - #define JUCE_INTEL 1 - #endif - - #ifdef __LP64__ - #define JUCE_64BIT 1 - #else - #define JUCE_32BIT 1 - #endif - - #if (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_3) - #define MACOS_10_2_OR_EARLIER 1 - #endif - - #if (! defined (MAC_OS_X_VERSION_10_4)) || (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4) - #define MACOS_10_3_OR_EARLIER 1 - #endif - - #if (! defined (MAC_OS_X_VERSION_10_5)) || (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) - #define MACOS_10_4_OR_EARLIER 1 - #endif -#endif - -//============================================================================== -#if JUCE_LINUX - - #ifdef _DEBUG - #define JUCE_DEBUG 1 - #endif - - // Allow override for big-endian Linux platforms - #ifndef JUCE_BIG_ENDIAN - #define JUCE_LITTLE_ENDIAN 1 - #endif - - #if defined (__LP64__) || defined (_LP64) - #define JUCE_64BIT 1 - #else - #define JUCE_32BIT 1 - #endif - - #define JUCE_INTEL 1 -#endif - -//============================================================================== -#ifdef JUCE_FORCE_DEBUG - #undef JUCE_DEBUG - - #if JUCE_FORCE_DEBUG - #define JUCE_DEBUG 1 - #endif -#endif - -//============================================================================== -// Compiler type macros. - -#ifdef __GNUC__ - #define JUCE_GCC 1 -#elif defined (_MSC_VER) - #define JUCE_MSVC 1 - - #if _MSC_VER >= 1400 - #define JUCE_USE_INTRINSICS 1 - #endif -#else - #error unknown compiler -#endif - -/** This macro defines the C calling convention used as the standard for Juce calls. */ -#if JUCE_MSVC - #define JUCE_CALLTYPE __stdcall -#else - #define JUCE_CALLTYPE -#endif - -//============================================================================== -// Debugging and assertion macros - -// (For info about JUCE_LOG_ASSERTIONS, have a look in juce_Config.h) -#if JUCE_LOG_ASSERTIONS - #define juce_LogCurrentAssertion juce_LogAssertion (__FILE__, __LINE__); -#elif defined (JUCE_DEBUG) - #define juce_LogCurrentAssertion fprintf (stderr, "JUCE Assertion failure in %s, line %d\n", __FILE__, __LINE__); -#else - #define juce_LogCurrentAssertion -#endif - -#ifdef JUCE_DEBUG - //============================================================================== - // If debugging is enabled.. - - /** Writes a string to the standard error stream. - - This is only compiled in a debug build. - - @see Logger::outputDebugString - */ - #define DBG(dbgtext) Logger::outputDebugString (dbgtext); - - /** Printf's a string to the standard error stream. - - This is only compiled in a debug build. - - @see Logger::outputDebugString - */ - #define DBG_PRINTF(dbgprintf) Logger::outputDebugPrintf dbgprintf; - - //============================================================================== - // Assertions.. - - #if JUCE_WIN32 || DOXYGEN - - #if JUCE_USE_INTRINSICS - #pragma intrinsic (__debugbreak) - - /** This will try to break the debugger if one is currently hosting this app. - @see jassert() - */ - #define juce_breakDebugger __debugbreak(); - - #elif JUCE_GCC - /** This will try to break the debugger if one is currently hosting this app. - @see jassert() - */ - #define juce_breakDebugger asm("int $3"); - #else - /** This will try to break the debugger if one is currently hosting this app. - @see jassert() - */ - #define juce_breakDebugger { __asm int 3 } - #endif - #elif JUCE_MAC - #define juce_breakDebugger Debugger(); - #elif JUCE_LINUX - #define juce_breakDebugger kill (0, SIGTRAP); - #endif - - //============================================================================== - /** This will always cause an assertion failure. - - It is only compiled in a debug build, (unless JUCE_LOG_ASSERTIONS is enabled - in juce_Config.h). - - @see jassert() - */ - #define jassertfalse { juce_LogCurrentAssertion; if (JUCE_NAMESPACE::juce_isRunningUnderDebugger()) juce_breakDebugger; } - - //============================================================================== - /** Platform-independent assertion macro. - - This gets optimised out when not being built with debugging turned on. - - Be careful not to call any functions within its arguments that are vital to - the behaviour of the program, because these won't get called in the release - build. - - @see jassertfalse - */ - #define jassert(expression) { if (! (expression)) jassertfalse } - -#else - //============================================================================== - // If debugging is disabled, these dummy debug and assertion macros are used.. - - #define DBG(dbgtext) - #define DBG_PRINTF(dbgprintf) - - #define jassertfalse { juce_LogCurrentAssertion } - - #if JUCE_LOG_ASSERTIONS - #define jassert(expression) { if (! (expression)) jassertfalse } - #else - #define jassert(a) { } - #endif - -#endif - -//============================================================================== -#ifndef DOXYGEN - template struct JuceStaticAssert; - template <> struct JuceStaticAssert { static void dummy() {} }; -#endif - -/** A compile-time assertion macro. - - If the expression parameter is false, the macro will cause a compile error. -*/ -#define static_jassert(expression) JuceStaticAssert::dummy(); - - -//============================================================================== -#if JUCE_CATCH_UNHANDLED_EXCEPTIONS - - #define JUCE_TRY try - - /** Used in try-catch blocks, this macro will send exceptions to the JUCEApplication - object so they can be logged by the application if it wants to. - */ - #define JUCE_CATCH_EXCEPTION \ - catch (const std::exception& e) \ - { \ - JUCEApplication::sendUnhandledException (&e, __FILE__, __LINE__); \ - } \ - catch (...) \ - { \ - JUCEApplication::sendUnhandledException (0, __FILE__, __LINE__); \ - } - - #define JUCE_CATCH_ALL catch (...) {} - #define JUCE_CATCH_ALL_ASSERT catch (...) { jassertfalse } - -#else - - #define JUCE_TRY - #define JUCE_CATCH_EXCEPTION - #define JUCE_CATCH_ALL - #define JUCE_CATCH_ALL_ASSERT - -#endif - -//============================================================================== -// Macros for inlining. - -#if JUCE_MSVC - /** A platform-independent way of forcing an inline function. - - Use the syntax: @code - forcedinline void myfunction (int x) - @endcode - */ - #ifdef JUCE_DEBUG - #define forcedinline __forceinline - #else - #define forcedinline inline - #endif - - /** A platform-independent way of stopping the compiler inlining a function. - - Use the syntax: @code - juce_noinline void myfunction (int x) - @endcode - */ - #define juce_noinline - -#else - /** A platform-independent way of forcing an inline function. - - Use the syntax: @code - forcedinline void myfunction (int x) - @endcode - */ - #ifndef JUCE_DEBUG - #define forcedinline inline __attribute__((always_inline)) - #else - #define forcedinline inline - #endif - - /** A platform-independent way of stopping the compiler inlining a function. - - Use the syntax: @code - juce_noinline void myfunction (int x) - @endcode - */ - #define juce_noinline __attribute__((noinline)) - -#endif - -#endif // __JUCE_PLATFORMDEFS_JUCEHEADER__ +/* + ============================================================================== + + 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. + + ============================================================================== +*/ + +#ifndef __JUCE_PLATFORMDEFS_JUCEHEADER__ +#define __JUCE_PLATFORMDEFS_JUCEHEADER__ + +//============================================================================== +/* This file figures out which platform is being built, and defines some macros + that the rest of the code can use for OS-specific compilation. + + Macros that will be set here are: + + - One of JUCE_WIN32, JUCE_MAC or JUCE_LINUX. + - Either JUCE_32BIT or JUCE_64BIT, depending on the architecture. + - Either JUCE_LITTLE_ENDIAN or JUCE_BIG_ENDIAN. + - Either JUCE_INTEL or JUCE_PPC + - Either JUCE_GCC or JUCE_MSVC + + On the Mac, it also defines MACOS_10_2_OR_EARLIER if the build is targeting OSX10.2, + and MACOS_10_3_OR_EARLIER if it is targeting either 10.2 or 10.3 + + It also includes a set of macros for debug console output and assertions. + +*/ + +//============================================================================== +#if (defined (_WIN32) || defined (_WIN64)) + #define JUCE_WIN32 1 +#else + #if defined (LINUX) || defined (__linux__) + #define JUCE_LINUX 1 + #else + #define JUCE_MAC 1 + #endif +#endif + +//============================================================================== +#if JUCE_WIN32 + #ifdef _MSC_VER + #ifdef _WIN64 + #define JUCE_64BIT 1 + #else + #define JUCE_32BIT 1 + #endif + #endif + + #ifdef _DEBUG + #define JUCE_DEBUG 1 + #endif + + /** If defined, this indicates that the processor is little-endian. */ + #define JUCE_LITTLE_ENDIAN 1 + + #define JUCE_INTEL 1 +#endif + +//============================================================================== +#if JUCE_MAC + + #include + + #ifndef NDEBUG + #define JUCE_DEBUG 1 + #endif + + #ifdef __LITTLE_ENDIAN__ + #define JUCE_LITTLE_ENDIAN 1 + #else + #define JUCE_BIG_ENDIAN 1 + #endif + + #if defined (__ppc__) || defined (__ppc64__) + #define JUCE_PPC 1 + #else + #define JUCE_INTEL 1 + #endif + + #ifdef __LP64__ + #define JUCE_64BIT 1 + #else + #define JUCE_32BIT 1 + #endif + + #if (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_3) + #define MACOS_10_2_OR_EARLIER 1 + #endif + + #if (! defined (MAC_OS_X_VERSION_10_4)) || (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4) + #define MACOS_10_3_OR_EARLIER 1 + #endif + + #if (! defined (MAC_OS_X_VERSION_10_5)) || (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) + #define MACOS_10_4_OR_EARLIER 1 + #endif +#endif + +//============================================================================== +#if JUCE_LINUX + + #ifdef _DEBUG + #define JUCE_DEBUG 1 + #endif + + // Allow override for big-endian Linux platforms + #ifndef JUCE_BIG_ENDIAN + #define JUCE_LITTLE_ENDIAN 1 + #endif + + #if defined (__LP64__) || defined (_LP64) + #define JUCE_64BIT 1 + #else + #define JUCE_32BIT 1 + #endif + + #define JUCE_INTEL 1 +#endif + +//============================================================================== +#ifdef JUCE_FORCE_DEBUG + #undef JUCE_DEBUG + + #if JUCE_FORCE_DEBUG + #define JUCE_DEBUG 1 + #endif +#endif + +//============================================================================== +// Compiler type macros. + +#ifdef __GNUC__ + #define JUCE_GCC 1 +#elif defined (_MSC_VER) + #define JUCE_MSVC 1 + + #if _MSC_VER >= 1400 + #define JUCE_USE_INTRINSICS 1 + #endif +#else + #error unknown compiler +#endif + +/** This macro defines the C calling convention used as the standard for Juce calls. */ +#if JUCE_MSVC + #define JUCE_CALLTYPE __stdcall +#else + #define JUCE_CALLTYPE +#endif + +//============================================================================== +// Debugging and assertion macros + +// (For info about JUCE_LOG_ASSERTIONS, have a look in juce_Config.h) +#if JUCE_LOG_ASSERTIONS + #define juce_LogCurrentAssertion juce_LogAssertion (__FILE__, __LINE__); +#elif defined (JUCE_DEBUG) + #define juce_LogCurrentAssertion fprintf (stderr, "JUCE Assertion failure in %s, line %d\n", __FILE__, __LINE__); +#else + #define juce_LogCurrentAssertion +#endif + +#ifdef JUCE_DEBUG + //============================================================================== + // If debugging is enabled.. + + /** Writes a string to the standard error stream. + + This is only compiled in a debug build. + + @see Logger::outputDebugString + */ + #define DBG(dbgtext) Logger::outputDebugString (dbgtext); + + /** Printf's a string to the standard error stream. + + This is only compiled in a debug build. + + @see Logger::outputDebugString + */ + #define DBG_PRINTF(dbgprintf) Logger::outputDebugPrintf dbgprintf; + + //============================================================================== + // Assertions.. + + #if JUCE_WIN32 || DOXYGEN + + #if JUCE_USE_INTRINSICS + #pragma intrinsic (__debugbreak) + + /** This will try to break the debugger if one is currently hosting this app. + @see jassert() + */ + #define juce_breakDebugger __debugbreak(); + + #elif JUCE_GCC + /** This will try to break the debugger if one is currently hosting this app. + @see jassert() + */ + #define juce_breakDebugger asm("int $3"); + #else + /** This will try to break the debugger if one is currently hosting this app. + @see jassert() + */ + #define juce_breakDebugger { __asm int 3 } + #endif + #elif JUCE_MAC + #define juce_breakDebugger Debugger(); + #elif JUCE_LINUX + #define juce_breakDebugger kill (0, SIGTRAP); + #endif + + //============================================================================== + /** This will always cause an assertion failure. + + It is only compiled in a debug build, (unless JUCE_LOG_ASSERTIONS is enabled + in juce_Config.h). + + @see jassert() + */ + #define jassertfalse { juce_LogCurrentAssertion; if (JUCE_NAMESPACE::juce_isRunningUnderDebugger()) juce_breakDebugger; } + + //============================================================================== + /** Platform-independent assertion macro. + + This gets optimised out when not being built with debugging turned on. + + Be careful not to call any functions within its arguments that are vital to + the behaviour of the program, because these won't get called in the release + build. + + @see jassertfalse + */ + #define jassert(expression) { if (! (expression)) jassertfalse } + +#else + //============================================================================== + // If debugging is disabled, these dummy debug and assertion macros are used.. + + #define DBG(dbgtext) + #define DBG_PRINTF(dbgprintf) + + #define jassertfalse { juce_LogCurrentAssertion } + + #if JUCE_LOG_ASSERTIONS + #define jassert(expression) { if (! (expression)) jassertfalse } + #else + #define jassert(a) { } + #endif + +#endif + +//============================================================================== +#ifndef DOXYGEN + template struct JuceStaticAssert; + template <> struct JuceStaticAssert { static void dummy() {} }; +#endif + +/** A compile-time assertion macro. + + If the expression parameter is false, the macro will cause a compile error. +*/ +#define static_jassert(expression) JuceStaticAssert::dummy(); + + +//============================================================================== +#if JUCE_CATCH_UNHANDLED_EXCEPTIONS + + #define JUCE_TRY try + + /** Used in try-catch blocks, this macro will send exceptions to the JUCEApplication + object so they can be logged by the application if it wants to. + */ + #define JUCE_CATCH_EXCEPTION \ + catch (const std::exception& e) \ + { \ + JUCEApplication::sendUnhandledException (&e, __FILE__, __LINE__); \ + } \ + catch (...) \ + { \ + JUCEApplication::sendUnhandledException (0, __FILE__, __LINE__); \ + } + + #define JUCE_CATCH_ALL catch (...) {} + #define JUCE_CATCH_ALL_ASSERT catch (...) { jassertfalse } + +#else + + #define JUCE_TRY + #define JUCE_CATCH_EXCEPTION + #define JUCE_CATCH_ALL + #define JUCE_CATCH_ALL_ASSERT + +#endif + +//============================================================================== +// Macros for inlining. + +#if JUCE_MSVC + /** A platform-independent way of forcing an inline function. + + Use the syntax: @code + forcedinline void myfunction (int x) + @endcode + */ + #ifdef JUCE_DEBUG + #define forcedinline __forceinline + #else + #define forcedinline inline + #endif + + /** A platform-independent way of stopping the compiler inlining a function. + + Use the syntax: @code + juce_noinline void myfunction (int x) + @endcode + */ + #define juce_noinline + +#else + /** A platform-independent way of forcing an inline function. + + Use the syntax: @code + forcedinline void myfunction (int x) + @endcode + */ + #ifndef JUCE_DEBUG + #define forcedinline inline __attribute__((always_inline)) + #else + #define forcedinline inline + #endif + + /** A platform-independent way of stopping the compiler inlining a function. + + Use the syntax: @code + juce_noinline void myfunction (int x) + @endcode + */ + #define juce_noinline __attribute__((noinline)) + +#endif + +#endif // __JUCE_PLATFORMDEFS_JUCEHEADER__ diff --git a/src/juce_core/basics/juce_StandardHeader.h b/src/juce_core/basics/juce_StandardHeader.h index b64ae7c9cc..bad91d8855 100644 --- a/src/juce_core/basics/juce_StandardHeader.h +++ b/src/juce_core/basics/juce_StandardHeader.h @@ -1,149 +1,153 @@ -/* - ============================================================================== - - 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. - - ============================================================================== -*/ - -#ifndef __JUCE_STANDARDHEADER_JUCEHEADER__ -#define __JUCE_STANDARDHEADER_JUCEHEADER__ - -//============================================================================== -/** Current Juce version number. - - See also SystemStats::getJUCEVersion() for a string version. -*/ -#define JUCE_MAJOR_VERSION 1 -#define JUCE_MINOR_VERSION 46 - -/** Current Juce version number. - - Bits 16 to 32 = major version. - Bits 8 to 16 = minor version. - Bits 0 to 8 = point release (not currently used). - - See also SystemStats::getJUCEVersion() for a string version. -*/ -#define JUCE_VERSION ((JUCE_MAJOR_VERSION << 16) + (JUCE_MINOR_VERSION << 8)) - - -//============================================================================== -#include "../../../juce_Config.h" - -//============================================================================== -#ifdef JUCE_NAMESPACE - #define BEGIN_JUCE_NAMESPACE namespace JUCE_NAMESPACE { - #define END_JUCE_NAMESPACE } -#else - #define BEGIN_JUCE_NAMESPACE - #define END_JUCE_NAMESPACE -#endif - -//============================================================================== -// This sets up the JUCE_WIN32, JUCE_MAC, or JUCE_LINUX macros -#include "juce_PlatformDefs.h" - -// Now we'll include any OS headers we need.. (at this point we are outside the Juce namespace). -#if JUCE_MSVC - #pragma warning (push) - #pragma warning (disable: 4514 4245 4100) -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if JUCE_MAC || JUCE_LINUX - #include -#endif - -#if JUCE_USE_INTRINSICS - #include -#endif - -#if JUCE_MAC && ! MACOS_10_3_OR_EARLIER - #include -#endif - -#if JUCE_LINUX - #include -#endif - -#if JUCE_MSVC && JUCE_DEBUG - #include -#endif - -#if JUCE_MSVC - #pragma warning (pop) -#endif - -//============================================================================== -// DLL building settings on Win32 -#if JUCE_MSVC - #ifdef JUCE_DLL_BUILD - #define JUCE_API __declspec (dllexport) - #pragma warning (disable: 4251) - #elif defined (JUCE_DLL) - #define JUCE_API __declspec (dllimport) - #pragma warning (disable: 4251) - #endif -#endif - -#ifndef JUCE_API - /** This macro is added to all juce public class declarations. */ - #define JUCE_API -#endif - -/** This macro is added to all juce public function declarations. */ -#define JUCE_PUBLIC_FUNCTION JUCE_API JUCE_CALLTYPE - - -//============================================================================== -// Now include some basics that are needed by most of the Juce classes... -BEGIN_JUCE_NAMESPACE - -extern bool JUCE_API JUCE_CALLTYPE juce_isRunningUnderDebugger() throw(); - -#if JUCE_LOG_ASSERTIONS - extern void JUCE_API juce_LogAssertion (const char* filename, const int lineNum) throw(); -#endif - -#include "juce_Memory.h" -#include "juce_MathsFunctions.h" -#include "juce_DataConversions.h" -#include "juce_Logger.h" - -END_JUCE_NAMESPACE - - -#endif // __JUCE_STANDARDHEADER_JUCEHEADER__ +/* + ============================================================================== + + 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. + + ============================================================================== +*/ + +#ifndef __JUCE_STANDARDHEADER_JUCEHEADER__ +#define __JUCE_STANDARDHEADER_JUCEHEADER__ + +//============================================================================== +/** Current Juce version number. + + See also SystemStats::getJUCEVersion() for a string version. +*/ +#define JUCE_MAJOR_VERSION 1 +#define JUCE_MINOR_VERSION 46 + +/** Current Juce version number. + + Bits 16 to 32 = major version. + Bits 8 to 16 = minor version. + Bits 0 to 8 = point release (not currently used). + + See also SystemStats::getJUCEVersion() for a string version. +*/ +#define JUCE_VERSION ((JUCE_MAJOR_VERSION << 16) + (JUCE_MINOR_VERSION << 8)) + + +//============================================================================== +#include "../../../juce_Config.h" + +//============================================================================== +#ifdef JUCE_NAMESPACE + #define BEGIN_JUCE_NAMESPACE namespace JUCE_NAMESPACE { + #define END_JUCE_NAMESPACE } +#else + #define BEGIN_JUCE_NAMESPACE + #define END_JUCE_NAMESPACE +#endif + +//============================================================================== +// This sets up the JUCE_WIN32, JUCE_MAC, or JUCE_LINUX macros +#include "juce_PlatformDefs.h" + +// Now we'll include any OS headers we need.. (at this point we are outside the Juce namespace). +#if JUCE_MSVC + #pragma warning (push) + #pragma warning (disable: 4514 4245 4100) +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if JUCE_MAC || JUCE_LINUX + #include +#endif + +#if JUCE_USE_INTRINSICS + #include +#endif + +#if JUCE_MAC + #if MACOS_10_3_OR_EARLIER + #include + #else + #include + #endif +#endif + +#if JUCE_LINUX + #include +#endif + +#if JUCE_MSVC && JUCE_DEBUG + #include +#endif + +#if JUCE_MSVC + #pragma warning (pop) +#endif + +//============================================================================== +// DLL building settings on Win32 +#if JUCE_MSVC + #ifdef JUCE_DLL_BUILD + #define JUCE_API __declspec (dllexport) + #pragma warning (disable: 4251) + #elif defined (JUCE_DLL) + #define JUCE_API __declspec (dllimport) + #pragma warning (disable: 4251) + #endif +#endif + +#ifndef JUCE_API + /** This macro is added to all juce public class declarations. */ + #define JUCE_API +#endif + +/** This macro is added to all juce public function declarations. */ +#define JUCE_PUBLIC_FUNCTION JUCE_API JUCE_CALLTYPE + + +//============================================================================== +// Now include some basics that are needed by most of the Juce classes... +BEGIN_JUCE_NAMESPACE + +extern bool JUCE_API JUCE_CALLTYPE juce_isRunningUnderDebugger() throw(); + +#if JUCE_LOG_ASSERTIONS + extern void JUCE_API juce_LogAssertion (const char* filename, const int lineNum) throw(); +#endif + +#include "juce_Memory.h" +#include "juce_MathsFunctions.h" +#include "juce_DataConversions.h" +#include "juce_Logger.h" + +END_JUCE_NAMESPACE + + +#endif // __JUCE_STANDARDHEADER_JUCEHEADER__ diff --git a/src/juce_core/io/network/juce_Socket.cpp b/src/juce_core/io/network/juce_Socket.cpp index 368891db56..b8e4a7ee17 100644 --- a/src/juce_core/io/network/juce_Socket.cpp +++ b/src/juce_core/io/network/juce_Socket.cpp @@ -1,636 +1,634 @@ -/* - ============================================================================== - - 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. - - ============================================================================== -*/ - -#ifdef _WIN32 - #include - - #ifdef _MSC_VER - #pragma warning (disable : 4127 4389 4018) - #endif - -#else - #if defined (LINUX) || defined (__linux__) - #include - #include - #include - #include - #include - #include - #else - #include - #endif - - #include - #include - #include -#endif - -#include "../../basics/juce_StandardHeader.h" - -BEGIN_JUCE_NAMESPACE - -#include "juce_Socket.h" -#include "../../threads/juce_ScopedLock.h" -#include "../../threads/juce_Thread.h" - - -//============================================================================== -#if JUCE_WIN32 - -typedef int (__stdcall juce_CloseWin32SocketLibCall) (void); -juce_CloseWin32SocketLibCall* juce_CloseWin32SocketLib = 0; - -static void initWin32Sockets() -{ - static CriticalSection lock; - const ScopedLock sl (lock); - - if (juce_CloseWin32SocketLib == 0) - { - WSADATA wsaData; - const WORD wVersionRequested = MAKEWORD (1, 1); - WSAStartup (wVersionRequested, &wsaData); - - juce_CloseWin32SocketLib = &WSACleanup; - } -} - -#endif - -//============================================================================== -static bool resetSocketOptions (const int handle, const bool isDatagram) throw() -{ - if (handle <= 0) - return false; - - const int sndBufSize = 65536; - const int rcvBufSize = 65536; - const int one = 1; - - return setsockopt (handle, SOL_SOCKET, SO_RCVBUF, (const char*) &rcvBufSize, sizeof (int)) == 0 - && setsockopt (handle, SOL_SOCKET, SO_SNDBUF, (const char*) &sndBufSize, sizeof (int)) == 0 - && (isDatagram || (setsockopt (handle, IPPROTO_TCP, TCP_NODELAY, (const char*) &one, sizeof (int)) == 0)); -} - -static bool bindSocketToPort (const int handle, const int port) throw() -{ - if (handle == 0 || port <= 0) - return false; - - struct sockaddr_in servTmpAddr; - zerostruct (servTmpAddr); - servTmpAddr.sin_family = PF_INET; - servTmpAddr.sin_addr.s_addr = htonl (INADDR_ANY); - servTmpAddr.sin_port = htons ((uint16) port); - - return bind (handle, (struct sockaddr*) &servTmpAddr, sizeof (struct sockaddr_in)) >= 0; -} - -static int readSocket (const int handle, - void* const destBuffer, const int maxBytesToRead, - bool volatile& connected) throw() -{ - int bytesRead = 0; - - while (bytesRead < maxBytesToRead) - { - int bytesThisTime; - -#if JUCE_WIN32 - bytesThisTime = recv (handle, ((char*) destBuffer) + bytesRead, maxBytesToRead - bytesRead, 0); -#else - while ((bytesThisTime = ::read (handle, ((char*) destBuffer) + bytesRead, maxBytesToRead - bytesRead)) < 0 - && errno == EINTR - && connected) - { - } -#endif - - if (bytesThisTime <= 0 || ! connected) - { - if (bytesRead == 0) - bytesRead = -1; - - break; - } - - bytesRead += bytesThisTime; - } - - return bytesRead; -} - -static int waitForReadiness (const int handle, const bool forReading, - const int timeoutMsecs) throw() -{ - struct timeval timeout; - struct timeval* timeoutp; - - if (timeoutMsecs >= 0) - { - timeout.tv_sec = timeoutMsecs / 1000; - timeout.tv_usec = (timeoutMsecs % 1000) * 1000; - timeoutp = &timeout; - } - else - { - timeoutp = 0; - } - - fd_set rset, wset; - FD_ZERO (&rset); - FD_SET (handle, &rset); - FD_ZERO (&wset); - FD_SET (handle, &wset); - - fd_set* const prset = forReading ? &rset : 0; - fd_set* const pwset = forReading ? 0 : &wset; - -#if JUCE_WIN32 - if (select (handle + 1, prset, pwset, 0, timeoutp) < 0) - return -1; -#else - { - int result; - while ((result = select (handle + 1, prset, pwset, 0, timeoutp)) < 0 - && errno == EINTR) - { - } - - if (result < 0) - return -1; - } -#endif - - { - int opt; - -#if defined (JUCE_LINUX) || (defined (JUCE_MAC) && ! MACOS_10_2_OR_EARLIER) - socklen_t len = sizeof (opt); -#else - int len = sizeof (opt); -#endif - - if (getsockopt (handle, SOL_SOCKET, SO_ERROR, (char*) &opt, &len) < 0 - || opt != 0) - return -1; - } - - if ((forReading && FD_ISSET (handle, &rset)) - || ((! forReading) && FD_ISSET (handle, &wset))) - return 1; - - return 0; -} - -static bool setSocketBlockingState (const int handle, const bool shouldBlock) throw() -{ -#if JUCE_WIN32 - u_long nonBlocking = shouldBlock ? 0 : 1; - - if (ioctlsocket (handle, FIONBIO, &nonBlocking) != 0) - return false; -#else - int socketFlags = fcntl (handle, F_GETFL, 0); - - if (socketFlags == -1) - return false; - - if (shouldBlock) - socketFlags &= ~O_NONBLOCK; - else - socketFlags |= O_NONBLOCK; - - if (fcntl (handle, F_SETFL, socketFlags) != 0) - return false; -#endif - - return true; -} - -static bool connectSocket (int volatile& handle, - const bool isDatagram, - void** serverAddress, - const String& hostName, - const int portNumber, - const int timeOutMillisecs) throw() -{ - struct hostent* const hostEnt = gethostbyname (hostName); - - if (hostEnt == 0) - return false; - - struct in_addr targetAddress; - memcpy (&targetAddress.s_addr, - *(hostEnt->h_addr_list), - sizeof (targetAddress.s_addr)); - - struct sockaddr_in servTmpAddr; - zerostruct (servTmpAddr); - servTmpAddr.sin_family = PF_INET; - servTmpAddr.sin_addr = targetAddress; - servTmpAddr.sin_port = htons ((uint16) portNumber); - - if (handle < 0) - handle = (int) socket (AF_INET, isDatagram ? SOCK_DGRAM : SOCK_STREAM, 0); - - if (handle < 0) - return false; - - if (isDatagram) - { - *serverAddress = new struct sockaddr_in(); - *((struct sockaddr_in*) *serverAddress) = servTmpAddr; - - return true; - } - - setSocketBlockingState (handle, false); - - const int result = ::connect (handle, (struct sockaddr*) &servTmpAddr, sizeof (struct sockaddr_in)); - - if (result < 0) - { -#if JUCE_WIN32 - if (result == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK) -#else - if (errno == EINPROGRESS) -#endif - { - if (waitForReadiness (handle, false, timeOutMillisecs) != 1) - { - setSocketBlockingState (handle, true); - return false; - } - } - } - - setSocketBlockingState (handle, true); - resetSocketOptions (handle, false); - - return true; -} - -//============================================================================== -StreamingSocket::StreamingSocket() - : portNumber (0), - handle (-1), - connected (false), - isListener (false) -{ -#if JUCE_WIN32 - initWin32Sockets(); -#endif -} - -StreamingSocket::StreamingSocket (const String& hostName_, - const int portNumber_, - const int handle_) - : hostName (hostName_), - portNumber (portNumber_), - handle (handle_), - connected (true), - isListener (false) -{ -#if JUCE_WIN32 - initWin32Sockets(); -#endif - - resetSocketOptions (handle_, false); -} - -StreamingSocket::~StreamingSocket() -{ - close(); -} - -//============================================================================== -int StreamingSocket::read (void* destBuffer, const int maxBytesToRead) -{ - return (connected && ! isListener) ? readSocket (handle, destBuffer, maxBytesToRead, connected) - : -1; -} - -int StreamingSocket::write (const void* sourceBuffer, const int numBytesToWrite) -{ - if (isListener || ! connected) - return -1; - -#if JUCE_WIN32 - return send (handle, (const char*) sourceBuffer, numBytesToWrite, 0); -#else - int result; - - while ((result = ::write (handle, sourceBuffer, numBytesToWrite)) < 0 - && errno == EINTR) - { - } - - return result; -#endif -} - -//============================================================================== -int StreamingSocket::waitUntilReady (const bool readyForReading, - const int timeoutMsecs) const -{ - return connected ? waitForReadiness (handle, readyForReading, timeoutMsecs) - : -1; -} - -//============================================================================== -bool StreamingSocket::bindToPort (const int port) -{ - return bindSocketToPort (handle, port); -} - -bool StreamingSocket::connect (const String& remoteHostName, - const int remotePortNumber, - const int timeOutMillisecs) -{ - if (isListener) - { - jassertfalse // a listener socket can't connect to another one! - return false; - } - - if (connected) - close(); - - hostName = remoteHostName; - portNumber = remotePortNumber; - isListener = false; - - connected = connectSocket (handle, false, 0, remoteHostName, - remotePortNumber, timeOutMillisecs); - - if (! (connected && resetSocketOptions (handle, false))) - { - close(); - return false; - } - - return true; -} - -void StreamingSocket::close() -{ -#if JUCE_WIN32 - closesocket (handle); - connected = false; -#else - if (connected) - { - connected = false; - - if (isListener) - { - // need to do this to interrupt the accept() function.. - StreamingSocket temp; - temp.connect ("localhost", portNumber, 1000); - } - } - - ::close (handle); -#endif - - hostName = String::empty; - portNumber = 0; - handle = -1; - isListener = false; -} - -//============================================================================== -bool StreamingSocket::createListener (const int newPortNumber) -{ - if (connected) - close(); - - hostName = "listener"; - portNumber = newPortNumber; - isListener = true; - - struct sockaddr_in servTmpAddr; - zerostruct (servTmpAddr); - servTmpAddr.sin_family = PF_INET; - servTmpAddr.sin_addr.s_addr = htonl (INADDR_ANY); - servTmpAddr.sin_port = htons ((uint16) portNumber); - - handle = (int) socket (AF_INET, SOCK_STREAM, 0); - - if (handle < 0) - return false; - - const int reuse = 1; - setsockopt (handle, SOL_SOCKET, SO_REUSEADDR, (const char*) &reuse, sizeof (reuse)); - - if (bind (handle, (struct sockaddr*) &servTmpAddr, sizeof (struct sockaddr_in)) < 0 - || listen (handle, SOMAXCONN) < 0) - { - close(); - return false; - } - - connected = true; - return true; -} - -StreamingSocket* StreamingSocket::waitForNextConnection() const -{ - jassert (isListener || ! connected); // to call this method, you first have to use createListener() to - // prepare this socket as a listener. - - if (connected && isListener) - { - struct sockaddr address; - -#if defined (JUCE_LINUX) || (defined (JUCE_MAC) && ! MACOS_10_2_OR_EARLIER) - socklen_t len = sizeof (sockaddr); -#else - int len = sizeof (sockaddr); -#endif - const int newSocket = (int) accept (handle, &address, &len); - - if (newSocket >= 0 && connected) - return new StreamingSocket (inet_ntoa (((struct sockaddr_in*) &address)->sin_addr), - portNumber, newSocket); - } - - return 0; -} - -bool StreamingSocket::isLocal() const throw() -{ - return hostName == T("127.0.0.1"); -} - - -//============================================================================== -//============================================================================== -DatagramSocket::DatagramSocket (const int localPortNumber) - : portNumber (0), - handle (-1), - connected (false), - serverAddress (0) -{ -#if JUCE_WIN32 - initWin32Sockets(); -#endif - - handle = (int) socket (AF_INET, SOCK_DGRAM, 0); - bindToPort (localPortNumber); -} - -DatagramSocket::DatagramSocket (const String& hostName_, const int portNumber_, - const int handle_, const int localPortNumber) - : hostName (hostName_), - portNumber (portNumber_), - handle (handle_), - connected (true), - serverAddress (0) -{ -#if JUCE_WIN32 - initWin32Sockets(); -#endif - - resetSocketOptions (handle_, true); - bindToPort (localPortNumber); -} - -DatagramSocket::~DatagramSocket() -{ - close(); - - delete ((struct sockaddr_in*) serverAddress); - serverAddress = 0; -} - -void DatagramSocket::close() -{ -#if JUCE_WIN32 - closesocket (handle); - connected = false; -#else - connected = false; - ::close (handle); -#endif - - hostName = String::empty; - portNumber = 0; - handle = -1; -} - -bool DatagramSocket::bindToPort (const int port) -{ - return bindSocketToPort (handle, port); -} - -bool DatagramSocket::connect (const String& remoteHostName, - const int remotePortNumber, - const int timeOutMillisecs) -{ - if (connected) - close(); - - hostName = remoteHostName; - portNumber = remotePortNumber; - - connected = connectSocket (handle, true, &serverAddress, - remoteHostName, remotePortNumber, - timeOutMillisecs); - - if (! (connected && resetSocketOptions (handle, true))) - { - close(); - return false; - } - - return true; -} - -DatagramSocket* DatagramSocket::waitForNextConnection() const -{ - struct sockaddr address; - -#if defined (JUCE_LINUX) || (defined (JUCE_MAC) && ! MACOS_10_2_OR_EARLIER) - socklen_t len = sizeof (sockaddr); -#else - int len = sizeof (sockaddr); -#endif - - while (waitUntilReady (true, -1) == 1) - { - char buf[1]; - - if (recvfrom (handle, buf, 0, 0, &address, &len) > 0) - { - return new DatagramSocket (inet_ntoa (((struct sockaddr_in*) &address)->sin_addr), - ntohs (((struct sockaddr_in*) &address)->sin_port), - -1, -1); - } - } - - return 0; -} - -//============================================================================== -int DatagramSocket::waitUntilReady (const bool readyForReading, - const int timeoutMsecs) const -{ - return connected ? waitForReadiness (handle, readyForReading, timeoutMsecs) - : -1; -} - -int DatagramSocket::read (void* destBuffer, const int maxBytesToRead) -{ - return connected ? readSocket (handle, destBuffer, maxBytesToRead, connected) - : -1; -} - -int DatagramSocket::write (const void* sourceBuffer, const int numBytesToWrite) -{ - // You need to call connect() first to set the server address.. - jassert (serverAddress != 0 && connected); - - return connected ? sendto (handle, (const char*) sourceBuffer, - numBytesToWrite, 0, - (const struct sockaddr*) serverAddress, - sizeof (struct sockaddr_in)) - : -1; -} - -bool DatagramSocket::isLocal() const throw() -{ - return hostName == T("127.0.0.1"); -} - - -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. + + ============================================================================== +*/ + +#ifdef _WIN32 + #include + + #ifdef _MSC_VER + #pragma warning (disable : 4127 4389 4018) + #endif + +#else + #if defined (LINUX) || defined (__linux__) + #include + #include + #include + #include + #include + #endif + + #include + #include + #include + #include +#endif + +#include "../../basics/juce_StandardHeader.h" + +BEGIN_JUCE_NAMESPACE + +#include "juce_Socket.h" +#include "../../threads/juce_ScopedLock.h" +#include "../../threads/juce_Thread.h" + + +//============================================================================== +#if JUCE_WIN32 + +typedef int (__stdcall juce_CloseWin32SocketLibCall) (void); +juce_CloseWin32SocketLibCall* juce_CloseWin32SocketLib = 0; + +static void initWin32Sockets() +{ + static CriticalSection lock; + const ScopedLock sl (lock); + + if (juce_CloseWin32SocketLib == 0) + { + WSADATA wsaData; + const WORD wVersionRequested = MAKEWORD (1, 1); + WSAStartup (wVersionRequested, &wsaData); + + juce_CloseWin32SocketLib = &WSACleanup; + } +} + +#endif + +//============================================================================== +static bool resetSocketOptions (const int handle, const bool isDatagram) throw() +{ + if (handle <= 0) + return false; + + const int sndBufSize = 65536; + const int rcvBufSize = 65536; + const int one = 1; + + return setsockopt (handle, SOL_SOCKET, SO_RCVBUF, (const char*) &rcvBufSize, sizeof (int)) == 0 + && setsockopt (handle, SOL_SOCKET, SO_SNDBUF, (const char*) &sndBufSize, sizeof (int)) == 0 + && (isDatagram || (setsockopt (handle, IPPROTO_TCP, TCP_NODELAY, (const char*) &one, sizeof (int)) == 0)); +} + +static bool bindSocketToPort (const int handle, const int port) throw() +{ + if (handle == 0 || port <= 0) + return false; + + struct sockaddr_in servTmpAddr; + zerostruct (servTmpAddr); + servTmpAddr.sin_family = PF_INET; + servTmpAddr.sin_addr.s_addr = htonl (INADDR_ANY); + servTmpAddr.sin_port = htons ((uint16) port); + + return bind (handle, (struct sockaddr*) &servTmpAddr, sizeof (struct sockaddr_in)) >= 0; +} + +static int readSocket (const int handle, + void* const destBuffer, const int maxBytesToRead, + bool volatile& connected) throw() +{ + int bytesRead = 0; + + while (bytesRead < maxBytesToRead) + { + int bytesThisTime; + +#if JUCE_WIN32 + bytesThisTime = recv (handle, ((char*) destBuffer) + bytesRead, maxBytesToRead - bytesRead, 0); +#else + while ((bytesThisTime = ::read (handle, ((char*) destBuffer) + bytesRead, maxBytesToRead - bytesRead)) < 0 + && errno == EINTR + && connected) + { + } +#endif + + if (bytesThisTime <= 0 || ! connected) + { + if (bytesRead == 0) + bytesRead = -1; + + break; + } + + bytesRead += bytesThisTime; + } + + return bytesRead; +} + +static int waitForReadiness (const int handle, const bool forReading, + const int timeoutMsecs) throw() +{ + struct timeval timeout; + struct timeval* timeoutp; + + if (timeoutMsecs >= 0) + { + timeout.tv_sec = timeoutMsecs / 1000; + timeout.tv_usec = (timeoutMsecs % 1000) * 1000; + timeoutp = &timeout; + } + else + { + timeoutp = 0; + } + + fd_set rset, wset; + FD_ZERO (&rset); + FD_SET (handle, &rset); + FD_ZERO (&wset); + FD_SET (handle, &wset); + + fd_set* const prset = forReading ? &rset : 0; + fd_set* const pwset = forReading ? 0 : &wset; + +#if JUCE_WIN32 + if (select (handle + 1, prset, pwset, 0, timeoutp) < 0) + return -1; +#else + { + int result; + while ((result = select (handle + 1, prset, pwset, 0, timeoutp)) < 0 + && errno == EINTR) + { + } + + if (result < 0) + return -1; + } +#endif + + { + int opt; + +#if defined (JUCE_LINUX) || (defined (JUCE_MAC) && ! MACOS_10_2_OR_EARLIER) + socklen_t len = sizeof (opt); +#else + int len = sizeof (opt); +#endif + + if (getsockopt (handle, SOL_SOCKET, SO_ERROR, (char*) &opt, &len) < 0 + || opt != 0) + return -1; + } + + if ((forReading && FD_ISSET (handle, &rset)) + || ((! forReading) && FD_ISSET (handle, &wset))) + return 1; + + return 0; +} + +static bool setSocketBlockingState (const int handle, const bool shouldBlock) throw() +{ +#if JUCE_WIN32 + u_long nonBlocking = shouldBlock ? 0 : 1; + + if (ioctlsocket (handle, FIONBIO, &nonBlocking) != 0) + return false; +#else + int socketFlags = fcntl (handle, F_GETFL, 0); + + if (socketFlags == -1) + return false; + + if (shouldBlock) + socketFlags &= ~O_NONBLOCK; + else + socketFlags |= O_NONBLOCK; + + if (fcntl (handle, F_SETFL, socketFlags) != 0) + return false; +#endif + + return true; +} + +static bool connectSocket (int volatile& handle, + const bool isDatagram, + void** serverAddress, + const String& hostName, + const int portNumber, + const int timeOutMillisecs) throw() +{ + struct hostent* const hostEnt = gethostbyname (hostName); + + if (hostEnt == 0) + return false; + + struct in_addr targetAddress; + memcpy (&targetAddress.s_addr, + *(hostEnt->h_addr_list), + sizeof (targetAddress.s_addr)); + + struct sockaddr_in servTmpAddr; + zerostruct (servTmpAddr); + servTmpAddr.sin_family = PF_INET; + servTmpAddr.sin_addr = targetAddress; + servTmpAddr.sin_port = htons ((uint16) portNumber); + + if (handle < 0) + handle = (int) socket (AF_INET, isDatagram ? SOCK_DGRAM : SOCK_STREAM, 0); + + if (handle < 0) + return false; + + if (isDatagram) + { + *serverAddress = new struct sockaddr_in(); + *((struct sockaddr_in*) *serverAddress) = servTmpAddr; + + return true; + } + + setSocketBlockingState (handle, false); + + const int result = ::connect (handle, (struct sockaddr*) &servTmpAddr, sizeof (struct sockaddr_in)); + + if (result < 0) + { +#if JUCE_WIN32 + if (result == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK) +#else + if (errno == EINPROGRESS) +#endif + { + if (waitForReadiness (handle, false, timeOutMillisecs) != 1) + { + setSocketBlockingState (handle, true); + return false; + } + } + } + + setSocketBlockingState (handle, true); + resetSocketOptions (handle, false); + + return true; +} + +//============================================================================== +StreamingSocket::StreamingSocket() + : portNumber (0), + handle (-1), + connected (false), + isListener (false) +{ +#if JUCE_WIN32 + initWin32Sockets(); +#endif +} + +StreamingSocket::StreamingSocket (const String& hostName_, + const int portNumber_, + const int handle_) + : hostName (hostName_), + portNumber (portNumber_), + handle (handle_), + connected (true), + isListener (false) +{ +#if JUCE_WIN32 + initWin32Sockets(); +#endif + + resetSocketOptions (handle_, false); +} + +StreamingSocket::~StreamingSocket() +{ + close(); +} + +//============================================================================== +int StreamingSocket::read (void* destBuffer, const int maxBytesToRead) +{ + return (connected && ! isListener) ? readSocket (handle, destBuffer, maxBytesToRead, connected) + : -1; +} + +int StreamingSocket::write (const void* sourceBuffer, const int numBytesToWrite) +{ + if (isListener || ! connected) + return -1; + +#if JUCE_WIN32 + return send (handle, (const char*) sourceBuffer, numBytesToWrite, 0); +#else + int result; + + while ((result = ::write (handle, sourceBuffer, numBytesToWrite)) < 0 + && errno == EINTR) + { + } + + return result; +#endif +} + +//============================================================================== +int StreamingSocket::waitUntilReady (const bool readyForReading, + const int timeoutMsecs) const +{ + return connected ? waitForReadiness (handle, readyForReading, timeoutMsecs) + : -1; +} + +//============================================================================== +bool StreamingSocket::bindToPort (const int port) +{ + return bindSocketToPort (handle, port); +} + +bool StreamingSocket::connect (const String& remoteHostName, + const int remotePortNumber, + const int timeOutMillisecs) +{ + if (isListener) + { + jassertfalse // a listener socket can't connect to another one! + return false; + } + + if (connected) + close(); + + hostName = remoteHostName; + portNumber = remotePortNumber; + isListener = false; + + connected = connectSocket (handle, false, 0, remoteHostName, + remotePortNumber, timeOutMillisecs); + + if (! (connected && resetSocketOptions (handle, false))) + { + close(); + return false; + } + + return true; +} + +void StreamingSocket::close() +{ +#if JUCE_WIN32 + closesocket (handle); + connected = false; +#else + if (connected) + { + connected = false; + + if (isListener) + { + // need to do this to interrupt the accept() function.. + StreamingSocket temp; + temp.connect ("localhost", portNumber, 1000); + } + } + + ::close (handle); +#endif + + hostName = String::empty; + portNumber = 0; + handle = -1; + isListener = false; +} + +//============================================================================== +bool StreamingSocket::createListener (const int newPortNumber) +{ + if (connected) + close(); + + hostName = "listener"; + portNumber = newPortNumber; + isListener = true; + + struct sockaddr_in servTmpAddr; + zerostruct (servTmpAddr); + servTmpAddr.sin_family = PF_INET; + servTmpAddr.sin_addr.s_addr = htonl (INADDR_ANY); + servTmpAddr.sin_port = htons ((uint16) portNumber); + + handle = (int) socket (AF_INET, SOCK_STREAM, 0); + + if (handle < 0) + return false; + + const int reuse = 1; + setsockopt (handle, SOL_SOCKET, SO_REUSEADDR, (const char*) &reuse, sizeof (reuse)); + + if (bind (handle, (struct sockaddr*) &servTmpAddr, sizeof (struct sockaddr_in)) < 0 + || listen (handle, SOMAXCONN) < 0) + { + close(); + return false; + } + + connected = true; + return true; +} + +StreamingSocket* StreamingSocket::waitForNextConnection() const +{ + jassert (isListener || ! connected); // to call this method, you first have to use createListener() to + // prepare this socket as a listener. + + if (connected && isListener) + { + struct sockaddr address; + +#if defined (JUCE_LINUX) || (defined (JUCE_MAC) && ! MACOS_10_2_OR_EARLIER) + socklen_t len = sizeof (sockaddr); +#else + int len = sizeof (sockaddr); +#endif + const int newSocket = (int) accept (handle, &address, &len); + + if (newSocket >= 0 && connected) + return new StreamingSocket (inet_ntoa (((struct sockaddr_in*) &address)->sin_addr), + portNumber, newSocket); + } + + return 0; +} + +bool StreamingSocket::isLocal() const throw() +{ + return hostName == T("127.0.0.1"); +} + + +//============================================================================== +//============================================================================== +DatagramSocket::DatagramSocket (const int localPortNumber) + : portNumber (0), + handle (-1), + connected (false), + serverAddress (0) +{ +#if JUCE_WIN32 + initWin32Sockets(); +#endif + + handle = (int) socket (AF_INET, SOCK_DGRAM, 0); + bindToPort (localPortNumber); +} + +DatagramSocket::DatagramSocket (const String& hostName_, const int portNumber_, + const int handle_, const int localPortNumber) + : hostName (hostName_), + portNumber (portNumber_), + handle (handle_), + connected (true), + serverAddress (0) +{ +#if JUCE_WIN32 + initWin32Sockets(); +#endif + + resetSocketOptions (handle_, true); + bindToPort (localPortNumber); +} + +DatagramSocket::~DatagramSocket() +{ + close(); + + delete ((struct sockaddr_in*) serverAddress); + serverAddress = 0; +} + +void DatagramSocket::close() +{ +#if JUCE_WIN32 + closesocket (handle); + connected = false; +#else + connected = false; + ::close (handle); +#endif + + hostName = String::empty; + portNumber = 0; + handle = -1; +} + +bool DatagramSocket::bindToPort (const int port) +{ + return bindSocketToPort (handle, port); +} + +bool DatagramSocket::connect (const String& remoteHostName, + const int remotePortNumber, + const int timeOutMillisecs) +{ + if (connected) + close(); + + hostName = remoteHostName; + portNumber = remotePortNumber; + + connected = connectSocket (handle, true, &serverAddress, + remoteHostName, remotePortNumber, + timeOutMillisecs); + + if (! (connected && resetSocketOptions (handle, true))) + { + close(); + return false; + } + + return true; +} + +DatagramSocket* DatagramSocket::waitForNextConnection() const +{ + struct sockaddr address; + +#if defined (JUCE_LINUX) || (defined (JUCE_MAC) && ! MACOS_10_2_OR_EARLIER) + socklen_t len = sizeof (sockaddr); +#else + int len = sizeof (sockaddr); +#endif + + while (waitUntilReady (true, -1) == 1) + { + char buf[1]; + + if (recvfrom (handle, buf, 0, 0, &address, &len) > 0) + { + return new DatagramSocket (inet_ntoa (((struct sockaddr_in*) &address)->sin_addr), + ntohs (((struct sockaddr_in*) &address)->sin_port), + -1, -1); + } + } + + return 0; +} + +//============================================================================== +int DatagramSocket::waitUntilReady (const bool readyForReading, + const int timeoutMsecs) const +{ + return connected ? waitForReadiness (handle, readyForReading, timeoutMsecs) + : -1; +} + +int DatagramSocket::read (void* destBuffer, const int maxBytesToRead) +{ + return connected ? readSocket (handle, destBuffer, maxBytesToRead, connected) + : -1; +} + +int DatagramSocket::write (const void* sourceBuffer, const int numBytesToWrite) +{ + // You need to call connect() first to set the server address.. + jassert (serverAddress != 0 && connected); + + return connected ? sendto (handle, (const char*) sourceBuffer, + numBytesToWrite, 0, + (const struct sockaddr*) serverAddress, + sizeof (struct sockaddr_in)) + : -1; +} + +bool DatagramSocket::isLocal() const throw() +{ + return hostName == T("127.0.0.1"); +} + + +END_JUCE_NAMESPACE