@@ -150,8 +150,6 @@ | |||||
#include "../src/threads/juce_Thread.cpp" | #include "../src/threads/juce_Thread.cpp" | ||||
#include "../src/threads/juce_ThreadPool.cpp" | #include "../src/threads/juce_ThreadPool.cpp" | ||||
#include "../src/threads/juce_TimeSliceThread.cpp" | #include "../src/threads/juce_TimeSliceThread.cpp" | ||||
#include "../src/utilities/juce_DeletedAtShutdown.cpp" | |||||
#include "../src/utilities/juce_UnitTest.cpp" | |||||
#endif | #endif | ||||
#if JUCE_BUILD_MISC | #if JUCE_BUILD_MISC | ||||
@@ -166,6 +164,8 @@ | |||||
#include "../src/utilities/juce_FileBasedDocument.cpp" | #include "../src/utilities/juce_FileBasedDocument.cpp" | ||||
#include "../src/utilities/juce_RecentlyOpenedFilesList.cpp" | #include "../src/utilities/juce_RecentlyOpenedFilesList.cpp" | ||||
#include "../src/utilities/juce_UndoManager.cpp" | #include "../src/utilities/juce_UndoManager.cpp" | ||||
#include "../src/utilities/juce_UnitTest.cpp" | |||||
#include "../src/utilities/juce_DeletedAtShutdown.cpp" | |||||
#include "../src/audio/audio_file_formats/juce_AiffAudioFormat.cpp" | #include "../src/audio/audio_file_formats/juce_AiffAudioFormat.cpp" | ||||
#include "../src/audio/audio_file_formats/juce_AudioFormat.cpp" | #include "../src/audio/audio_file_formats/juce_AudioFormat.cpp" | ||||
#include "../src/audio/audio_file_formats/juce_AudioFormatReader.cpp" | #include "../src/audio/audio_file_formats/juce_AudioFormatReader.cpp" | ||||
@@ -209,11 +209,13 @@ private: | |||||
for (int i = 0; i < files.size(); ++i) | for (int i = 0; i < files.size(); ++i) | ||||
out << " ../" << escapeSpaces (files.getReference(i).toUnixStyle()) << "\\" << newLine; | out << " ../" << escapeSpaces (files.getReference(i).toUnixStyle()) << "\\" << newLine; | ||||
String cFlags ("-fsigned-char"); | |||||
out << newLine | out << newLine | ||||
<< "ifeq ($(CONFIG),Debug)" << newLine | << "ifeq ($(CONFIG),Debug)" << newLine | ||||
<< " LOCAL_CFLAGS +=" << createPreprocessorDefs (true) << newLine | |||||
<< " LOCAL_CFLAGS += -g " << cFlags << createPreprocessorDefs (true) << newLine | |||||
<< "else" << newLine | << "else" << newLine | ||||
<< " LOCAL_CFLAGS +=" << createPreprocessorDefs (false) << newLine | |||||
<< " LOCAL_CFLAGS += " << cFlags << createPreprocessorDefs (false) << newLine | |||||
<< "endif" << newLine | << "endif" << newLine | ||||
<< newLine | << newLine | ||||
<< "include $(BUILD_SHARED_LIBRARY)" << newLine; | << "include $(BUILD_SHARED_LIBRARY)" << newLine; | ||||
@@ -2245,6 +2245,10 @@ private: | |||||
#define JUCE_64BIT_ATOMICS_UNAVAILABLE 1 | #define JUCE_64BIT_ATOMICS_UNAVAILABLE 1 | ||||
#endif | #endif | ||||
#elif JUCE_ANDROID | |||||
#define JUCE_ATOMICS_ANDROID 1 // Android atomic functions | |||||
#define JUCE_64BIT_ATOMICS_UNAVAILABLE 1 | |||||
#elif JUCE_GCC | #elif JUCE_GCC | ||||
#define JUCE_ATOMICS_GCC 1 // GCC with intrinsics | #define JUCE_ATOMICS_GCC 1 // GCC with intrinsics | ||||
@@ -2306,8 +2310,8 @@ inline Type Atomic<Type>::get() const throw() | |||||
#elif JUCE_ATOMICS_WINDOWS | #elif JUCE_ATOMICS_WINDOWS | ||||
return sizeof (Type) == 4 ? castFrom32Bit ((int32) juce_InterlockedExchangeAdd ((volatile long*) &value, (long) 0)) | return sizeof (Type) == 4 ? castFrom32Bit ((int32) juce_InterlockedExchangeAdd ((volatile long*) &value, (long) 0)) | ||||
: castFrom64Bit ((int64) juce_InterlockedExchangeAdd64 ((volatile __int64*) &value, (__int64) 0)); | : castFrom64Bit ((int64) juce_InterlockedExchangeAdd64 ((volatile __int64*) &value, (__int64) 0)); | ||||
#elif JUCE_ANDROID | |||||
return castFrom32Bit (__atomic_cmpxchg (castTo32Bit (value), castTo32Bit (value), (volatile int*) &value)); | |||||
#elif JUCE_ATOMICS_ANDROID | |||||
return value; | |||||
#elif JUCE_ATOMICS_GCC | #elif JUCE_ATOMICS_GCC | ||||
return sizeof (Type) == 4 ? castFrom32Bit ((int32) __sync_add_and_fetch ((volatile int32*) &value, 0)) | return sizeof (Type) == 4 ? castFrom32Bit ((int32) __sync_add_and_fetch ((volatile int32*) &value, 0)) | ||||
: castFrom64Bit ((int64) __sync_add_and_fetch ((volatile int64*) &value, 0)); | : castFrom64Bit ((int64) __sync_add_and_fetch ((volatile int64*) &value, 0)); | ||||
@@ -2317,7 +2321,7 @@ inline Type Atomic<Type>::get() const throw() | |||||
template <typename Type> | template <typename Type> | ||||
inline Type Atomic<Type>::exchange (const Type newValue) throw() | inline Type Atomic<Type>::exchange (const Type newValue) throw() | ||||
{ | { | ||||
#if JUCE_ANDROID | |||||
#if JUCE_ATOMICS_ANDROID | |||||
return castFrom32Bit (__atomic_swap (castTo32Bit (newValue), (volatile int*) &value)); | return castFrom32Bit (__atomic_swap (castTo32Bit (newValue), (volatile int*) &value)); | ||||
#elif JUCE_ATOMICS_MAC || JUCE_ATOMICS_GCC | #elif JUCE_ATOMICS_MAC || JUCE_ATOMICS_GCC | ||||
Type currentVal = value; | Type currentVal = value; | ||||
@@ -2338,7 +2342,7 @@ inline Type Atomic<Type>::operator+= (const Type amountToAdd) throw() | |||||
#elif JUCE_ATOMICS_WINDOWS | #elif JUCE_ATOMICS_WINDOWS | ||||
return sizeof (Type) == 4 ? (Type) (juce_InterlockedExchangeAdd ((volatile long*) &value, (long) amountToAdd) + (long) amountToAdd) | return sizeof (Type) == 4 ? (Type) (juce_InterlockedExchangeAdd ((volatile long*) &value, (long) amountToAdd) + (long) amountToAdd) | ||||
: (Type) (juce_InterlockedExchangeAdd64 ((volatile __int64*) &value, (__int64) amountToAdd) + (__int64) amountToAdd); | : (Type) (juce_InterlockedExchangeAdd64 ((volatile __int64*) &value, (__int64) amountToAdd) + (__int64) amountToAdd); | ||||
#elif JUCE_ANDROID | |||||
#elif JUCE_ATOMICS_ANDROID | |||||
for (;;) | for (;;) | ||||
{ | { | ||||
const Type oldValue (value); | const Type oldValue (value); | ||||
@@ -2366,7 +2370,7 @@ inline Type Atomic<Type>::operator++() throw() | |||||
#elif JUCE_ATOMICS_WINDOWS | #elif JUCE_ATOMICS_WINDOWS | ||||
return sizeof (Type) == 4 ? (Type) juce_InterlockedIncrement ((volatile long*) &value) | return sizeof (Type) == 4 ? (Type) juce_InterlockedIncrement ((volatile long*) &value) | ||||
: (Type) juce_InterlockedIncrement64 ((volatile __int64*) &value); | : (Type) juce_InterlockedIncrement64 ((volatile __int64*) &value); | ||||
#elif JUCE_ANDROID | |||||
#elif JUCE_ATOMICS_ANDROID | |||||
return (Type) __atomic_inc ((volatile int*) &value); | return (Type) __atomic_inc ((volatile int*) &value); | ||||
#elif JUCE_ATOMICS_GCC | #elif JUCE_ATOMICS_GCC | ||||
return (Type) __sync_add_and_fetch (&value, 1); | return (Type) __sync_add_and_fetch (&value, 1); | ||||
@@ -2382,7 +2386,7 @@ inline Type Atomic<Type>::operator--() throw() | |||||
#elif JUCE_ATOMICS_WINDOWS | #elif JUCE_ATOMICS_WINDOWS | ||||
return sizeof (Type) == 4 ? (Type) juce_InterlockedDecrement ((volatile long*) &value) | return sizeof (Type) == 4 ? (Type) juce_InterlockedDecrement ((volatile long*) &value) | ||||
: (Type) juce_InterlockedDecrement64 ((volatile __int64*) &value); | : (Type) juce_InterlockedDecrement64 ((volatile __int64*) &value); | ||||
#elif JUCE_ANDROID | |||||
#elif JUCE_ATOMICS_ANDROID | |||||
return (Type) __atomic_dec ((volatile int*) &value); | return (Type) __atomic_dec ((volatile int*) &value); | ||||
#elif JUCE_ATOMICS_GCC | #elif JUCE_ATOMICS_GCC | ||||
return (Type) __sync_add_and_fetch (&value, -1); | return (Type) __sync_add_and_fetch (&value, -1); | ||||
@@ -2395,8 +2399,10 @@ inline bool Atomic<Type>::compareAndSetBool (const Type newValue, const Type val | |||||
#if JUCE_ATOMICS_MAC | #if JUCE_ATOMICS_MAC | ||||
return sizeof (Type) == 4 ? OSAtomicCompareAndSwap32Barrier ((int32_t) castTo32Bit (valueToCompare), (int32_t) castTo32Bit (newValue), (JUCE_MAC_ATOMICS_VOLATILE int32_t*) &value) | return sizeof (Type) == 4 ? OSAtomicCompareAndSwap32Barrier ((int32_t) castTo32Bit (valueToCompare), (int32_t) castTo32Bit (newValue), (JUCE_MAC_ATOMICS_VOLATILE int32_t*) &value) | ||||
: OSAtomicCompareAndSwap64Barrier ((int64_t) castTo64Bit (valueToCompare), (int64_t) castTo64Bit (newValue), (JUCE_MAC_ATOMICS_VOLATILE int64_t*) &value); | : OSAtomicCompareAndSwap64Barrier ((int64_t) castTo64Bit (valueToCompare), (int64_t) castTo64Bit (newValue), (JUCE_MAC_ATOMICS_VOLATILE int64_t*) &value); | ||||
#elif JUCE_ATOMICS_WINDOWS || JUCE_ANDROID | |||||
#elif JUCE_ATOMICS_WINDOWS | |||||
return compareAndSetValue (newValue, valueToCompare) == valueToCompare; | return compareAndSetValue (newValue, valueToCompare) == valueToCompare; | ||||
#elif JUCE_ATOMICS_ANDROID | |||||
return __atomic_cmpxchg (castTo32Bit (valueToCompare), castTo32Bit (newValue), (volatile int*) &value) == 0; | |||||
#elif JUCE_ATOMICS_GCC | #elif JUCE_ATOMICS_GCC | ||||
return sizeof (Type) == 4 ? __sync_bool_compare_and_swap ((volatile int32*) &value, castTo32Bit (valueToCompare), castTo32Bit (newValue)) | return sizeof (Type) == 4 ? __sync_bool_compare_and_swap ((volatile int32*) &value, castTo32Bit (valueToCompare), castTo32Bit (newValue)) | ||||
: __sync_bool_compare_and_swap ((volatile int64*) &value, castTo64Bit (valueToCompare), castTo64Bit (newValue)); | : __sync_bool_compare_and_swap ((volatile int64*) &value, castTo64Bit (valueToCompare), castTo64Bit (newValue)); | ||||
@@ -2406,8 +2412,8 @@ inline bool Atomic<Type>::compareAndSetBool (const Type newValue, const Type val | |||||
template <typename Type> | template <typename Type> | ||||
inline Type Atomic<Type>::compareAndSetValue (const Type newValue, const Type valueToCompare) throw() | inline Type Atomic<Type>::compareAndSetValue (const Type newValue, const Type valueToCompare) throw() | ||||
{ | { | ||||
#if JUCE_ATOMICS_MAC | |||||
for (;;) // Annoying workaround for OSX only having a bool CAS operation.. | |||||
#if JUCE_ATOMICS_MAC || JUCE_ATOMICS_ANDROID | |||||
for (;;) // Annoying workaround for only having a bool CAS operation.. | |||||
{ | { | ||||
if (compareAndSetBool (newValue, valueToCompare)) | if (compareAndSetBool (newValue, valueToCompare)) | ||||
return valueToCompare; | return valueToCompare; | ||||
@@ -2420,8 +2426,6 @@ inline Type Atomic<Type>::compareAndSetValue (const Type newValue, const Type va | |||||
#elif JUCE_ATOMICS_WINDOWS | #elif JUCE_ATOMICS_WINDOWS | ||||
return sizeof (Type) == 4 ? castFrom32Bit ((int32) juce_InterlockedCompareExchange ((volatile long*) &value, (long) castTo32Bit (newValue), (long) castTo32Bit (valueToCompare))) | return sizeof (Type) == 4 ? castFrom32Bit ((int32) juce_InterlockedCompareExchange ((volatile long*) &value, (long) castTo32Bit (newValue), (long) castTo32Bit (valueToCompare))) | ||||
: castFrom64Bit ((int64) juce_InterlockedCompareExchange64 ((volatile __int64*) &value, (__int64) castTo64Bit (newValue), (__int64) castTo64Bit (valueToCompare))); | : castFrom64Bit ((int64) juce_InterlockedCompareExchange64 ((volatile __int64*) &value, (__int64) castTo64Bit (newValue), (__int64) castTo64Bit (valueToCompare))); | ||||
#elif JUCE_ANDROID | |||||
return castFrom32Bit (__atomic_cmpxchg (castTo32Bit (valueToCompare), castTo32Bit (newValue), (volatile int*) &value)); | |||||
#elif JUCE_ATOMICS_GCC | #elif JUCE_ATOMICS_GCC | ||||
return sizeof (Type) == 4 ? castFrom32Bit ((int32) __sync_val_compare_and_swap ((volatile int32*) &value, castTo32Bit (valueToCompare), castTo32Bit (newValue))) | return sizeof (Type) == 4 ? castFrom32Bit ((int32) __sync_val_compare_and_swap ((volatile int32*) &value, castTo32Bit (valueToCompare), castTo32Bit (newValue))) | ||||
: castFrom64Bit ((int64) __sync_val_compare_and_swap ((volatile int64*) &value, castTo64Bit (valueToCompare), castTo64Bit (newValue))); | : castFrom64Bit ((int64) __sync_val_compare_and_swap ((volatile int64*) &value, castTo64Bit (valueToCompare), castTo64Bit (newValue))); | ||||
@@ -2638,11 +2642,11 @@ public: | |||||
for (;;) | for (;;) | ||||
{ | { | ||||
const int n = *d++; | |||||
const uint32 n = (uint32) (uint8) *d++; | |||||
if ((n & 0x80) != 0) | if ((n & 0x80) != 0) | ||||
{ | { | ||||
int bit = 0x40; | |||||
uint32 bit = 0x40; | |||||
while ((n & bit) != 0) | while ((n & bit) != 0) | ||||
{ | { | ||||
@@ -211,6 +211,7 @@ void JUCEApplication::appWillTerminateByForce() | |||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
#if ! JUCE_ANDROID | |||||
int JUCEApplication::main (const String& commandLine) | int JUCEApplication::main (const String& commandLine) | ||||
{ | { | ||||
ScopedJuceInitialiser_GUI libraryInitialiser; | ScopedJuceInitialiser_GUI libraryInitialiser; | ||||
@@ -263,5 +264,6 @@ int JUCEApplication::main (int argc, const char* argv[]) | |||||
return JUCEApplication::main (cmd); | return JUCEApplication::main (cmd); | ||||
#endif | #endif | ||||
} | } | ||||
#endif | |||||
END_JUCE_NAMESPACE | END_JUCE_NAMESPACE |
@@ -539,7 +539,7 @@ public: | |||||
{ | { | ||||
FSRef fn; | FSRef fn; | ||||
if (FSPathMakeRef ((UInt8*) filename.toUTF8(), &fn, 0) == noErr) | |||||
if (FSPathMakeRef ((UInt8*) filename.toUTF8().getAddress(), &fn, 0) == noErr) | |||||
{ | { | ||||
resFileId = FSOpenResFile (&fn, fsRdPerm); | resFileId = FSOpenResFile (&fn, fsRdPerm); | ||||
@@ -188,18 +188,28 @@ public: | |||||
expect (ByteOrder::swap ((uint32) 0x11223344) == 0x44332211); | expect (ByteOrder::swap ((uint32) 0x11223344) == 0x44332211); | ||||
expect (ByteOrder::swap ((uint64) literal64bit (0x1122334455667788)) == literal64bit (0x8877665544332211)); | expect (ByteOrder::swap ((uint64) literal64bit (0x1122334455667788)) == literal64bit (0x8877665544332211)); | ||||
beginTest ("Atomic types"); | |||||
beginTest ("Atomic int"); | |||||
AtomicTester <int>::testInteger (*this); | AtomicTester <int>::testInteger (*this); | ||||
beginTest ("Atomic unsigned int"); | |||||
AtomicTester <unsigned int>::testInteger (*this); | AtomicTester <unsigned int>::testInteger (*this); | ||||
beginTest ("Atomic int32"); | |||||
AtomicTester <int32>::testInteger (*this); | AtomicTester <int32>::testInteger (*this); | ||||
beginTest ("Atomic uint32"); | |||||
AtomicTester <uint32>::testInteger (*this); | AtomicTester <uint32>::testInteger (*this); | ||||
beginTest ("Atomic long"); | |||||
AtomicTester <long>::testInteger (*this); | AtomicTester <long>::testInteger (*this); | ||||
beginTest ("Atomic void*"); | |||||
AtomicTester <void*>::testInteger (*this); | AtomicTester <void*>::testInteger (*this); | ||||
beginTest ("Atomic int*"); | |||||
AtomicTester <int*>::testInteger (*this); | AtomicTester <int*>::testInteger (*this); | ||||
beginTest ("Atomic float"); | |||||
AtomicTester <float>::testFloat (*this); | AtomicTester <float>::testFloat (*this); | ||||
#if ! JUCE_64BIT_ATOMICS_UNAVAILABLE // 64-bit intrinsics aren't available on some old platforms | #if ! JUCE_64BIT_ATOMICS_UNAVAILABLE // 64-bit intrinsics aren't available on some old platforms | ||||
beginTest ("Atomic int64"); | |||||
AtomicTester <int64>::testInteger (*this); | AtomicTester <int64>::testInteger (*this); | ||||
beginTest ("Atomic uint64"); | |||||
AtomicTester <uint64>::testInteger (*this); | AtomicTester <uint64>::testInteger (*this); | ||||
beginTest ("Atomic double"); | |||||
AtomicTester <double>::testFloat (*this); | AtomicTester <double>::testFloat (*this); | ||||
#endif | #endif | ||||
} | } | ||||
@@ -214,10 +224,15 @@ public: | |||||
{ | { | ||||
Atomic<Type> a, b; | Atomic<Type> a, b; | ||||
a.set ((Type) 10); | a.set ((Type) 10); | ||||
test.expect (a.value == (Type) 10); | |||||
test.expect (a.get() == (Type) 10); | |||||
a += (Type) 15; | a += (Type) 15; | ||||
test.expect (a.get() == (Type) 25); | |||||
a.memoryBarrier(); | a.memoryBarrier(); | ||||
a -= (Type) 5; | a -= (Type) 5; | ||||
test.expect (a.get() == (Type) 20); | |||||
++a; ++a; --a; | ++a; ++a; --a; | ||||
test.expect (a.get() == (Type) 21); | |||||
a.memoryBarrier(); | a.memoryBarrier(); | ||||
testFloat (test); | testFloat (test); | ||||
@@ -111,9 +111,7 @@ public: | |||||
int randomInt = Random::getSystemRandom().nextInt(); | int randomInt = Random::getSystemRandom().nextInt(); | ||||
int64 randomInt64 = Random::getSystemRandom().nextInt64(); | int64 randomInt64 = Random::getSystemRandom().nextInt64(); | ||||
double randomDouble = Random::getSystemRandom().nextDouble(); | double randomDouble = Random::getSystemRandom().nextDouble(); | ||||
String randomString; | |||||
for (int i = 50; --i >= 0;) | |||||
randomString << (juce_wchar) (Random::getSystemRandom().nextInt() & 0xffff); | |||||
String randomString (createRandomWideCharString()); | |||||
MemoryOutputStream mo; | MemoryOutputStream mo; | ||||
mo.writeInt (randomInt); | mo.writeInt (randomInt); | ||||
@@ -129,12 +127,34 @@ public: | |||||
expect (mi.readInt() == randomInt); | expect (mi.readInt() == randomInt); | ||||
expect (mi.readIntBigEndian() == randomInt); | expect (mi.readIntBigEndian() == randomInt); | ||||
expect (mi.readCompressedInt() == randomInt); | expect (mi.readCompressedInt() == randomInt); | ||||
expect (mi.readString() == randomString); | |||||
expectEquals (mi.readString(), randomString); | |||||
expect (mi.readInt64() == randomInt64); | expect (mi.readInt64() == randomInt64); | ||||
expect (mi.readInt64BigEndian() == randomInt64); | expect (mi.readInt64BigEndian() == randomInt64); | ||||
expect (mi.readDouble() == randomDouble); | expect (mi.readDouble() == randomDouble); | ||||
expect (mi.readDoubleBigEndian() == randomDouble); | expect (mi.readDoubleBigEndian() == randomDouble); | ||||
} | } | ||||
static const String createRandomWideCharString() | |||||
{ | |||||
juce_wchar buffer [50]; | |||||
zerostruct (buffer); | |||||
for (int i = 0; i < numElementsInArray (buffer) - 1; ++i) | |||||
{ | |||||
if (Random::getSystemRandom().nextBool()) | |||||
{ | |||||
do | |||||
{ | |||||
buffer[i] = (juce_wchar) (1 + Random::getSystemRandom().nextInt (0x10ffff - 1)); | |||||
} | |||||
while (! CharPointer_UTF16::canRepresent (buffer[i])); | |||||
} | |||||
else | |||||
buffer[i] = (juce_wchar) (1 + Random::getSystemRandom().nextInt (0xff)); | |||||
} | |||||
return buffer; | |||||
} | |||||
}; | }; | ||||
static MemoryStreamTests memoryInputStreamUnitTests; | static MemoryStreamTests memoryInputStreamUnitTests; | ||||
@@ -180,6 +180,11 @@ private: | |||||
#define JUCE_64BIT_ATOMICS_UNAVAILABLE 1 | #define JUCE_64BIT_ATOMICS_UNAVAILABLE 1 | ||||
#endif | #endif | ||||
//============================================================================== | |||||
#elif JUCE_ANDROID | |||||
#define JUCE_ATOMICS_ANDROID 1 // Android atomic functions | |||||
#define JUCE_64BIT_ATOMICS_UNAVAILABLE 1 | |||||
//============================================================================== | //============================================================================== | ||||
#elif JUCE_GCC | #elif JUCE_GCC | ||||
#define JUCE_ATOMICS_GCC 1 // GCC with intrinsics | #define JUCE_ATOMICS_GCC 1 // GCC with intrinsics | ||||
@@ -244,8 +249,8 @@ inline Type Atomic<Type>::get() const throw() | |||||
#elif JUCE_ATOMICS_WINDOWS | #elif JUCE_ATOMICS_WINDOWS | ||||
return sizeof (Type) == 4 ? castFrom32Bit ((int32) juce_InterlockedExchangeAdd ((volatile long*) &value, (long) 0)) | return sizeof (Type) == 4 ? castFrom32Bit ((int32) juce_InterlockedExchangeAdd ((volatile long*) &value, (long) 0)) | ||||
: castFrom64Bit ((int64) juce_InterlockedExchangeAdd64 ((volatile __int64*) &value, (__int64) 0)); | : castFrom64Bit ((int64) juce_InterlockedExchangeAdd64 ((volatile __int64*) &value, (__int64) 0)); | ||||
#elif JUCE_ANDROID | |||||
return castFrom32Bit (__atomic_cmpxchg (castTo32Bit (value), castTo32Bit (value), (volatile int*) &value)); | |||||
#elif JUCE_ATOMICS_ANDROID | |||||
return value; | |||||
#elif JUCE_ATOMICS_GCC | #elif JUCE_ATOMICS_GCC | ||||
return sizeof (Type) == 4 ? castFrom32Bit ((int32) __sync_add_and_fetch ((volatile int32*) &value, 0)) | return sizeof (Type) == 4 ? castFrom32Bit ((int32) __sync_add_and_fetch ((volatile int32*) &value, 0)) | ||||
: castFrom64Bit ((int64) __sync_add_and_fetch ((volatile int64*) &value, 0)); | : castFrom64Bit ((int64) __sync_add_and_fetch ((volatile int64*) &value, 0)); | ||||
@@ -255,7 +260,7 @@ inline Type Atomic<Type>::get() const throw() | |||||
template <typename Type> | template <typename Type> | ||||
inline Type Atomic<Type>::exchange (const Type newValue) throw() | inline Type Atomic<Type>::exchange (const Type newValue) throw() | ||||
{ | { | ||||
#if JUCE_ANDROID | |||||
#if JUCE_ATOMICS_ANDROID | |||||
return castFrom32Bit (__atomic_swap (castTo32Bit (newValue), (volatile int*) &value)); | return castFrom32Bit (__atomic_swap (castTo32Bit (newValue), (volatile int*) &value)); | ||||
#elif JUCE_ATOMICS_MAC || JUCE_ATOMICS_GCC | #elif JUCE_ATOMICS_MAC || JUCE_ATOMICS_GCC | ||||
Type currentVal = value; | Type currentVal = value; | ||||
@@ -276,7 +281,7 @@ inline Type Atomic<Type>::operator+= (const Type amountToAdd) throw() | |||||
#elif JUCE_ATOMICS_WINDOWS | #elif JUCE_ATOMICS_WINDOWS | ||||
return sizeof (Type) == 4 ? (Type) (juce_InterlockedExchangeAdd ((volatile long*) &value, (long) amountToAdd) + (long) amountToAdd) | return sizeof (Type) == 4 ? (Type) (juce_InterlockedExchangeAdd ((volatile long*) &value, (long) amountToAdd) + (long) amountToAdd) | ||||
: (Type) (juce_InterlockedExchangeAdd64 ((volatile __int64*) &value, (__int64) amountToAdd) + (__int64) amountToAdd); | : (Type) (juce_InterlockedExchangeAdd64 ((volatile __int64*) &value, (__int64) amountToAdd) + (__int64) amountToAdd); | ||||
#elif JUCE_ANDROID | |||||
#elif JUCE_ATOMICS_ANDROID | |||||
for (;;) | for (;;) | ||||
{ | { | ||||
const Type oldValue (value); | const Type oldValue (value); | ||||
@@ -304,7 +309,7 @@ inline Type Atomic<Type>::operator++() throw() | |||||
#elif JUCE_ATOMICS_WINDOWS | #elif JUCE_ATOMICS_WINDOWS | ||||
return sizeof (Type) == 4 ? (Type) juce_InterlockedIncrement ((volatile long*) &value) | return sizeof (Type) == 4 ? (Type) juce_InterlockedIncrement ((volatile long*) &value) | ||||
: (Type) juce_InterlockedIncrement64 ((volatile __int64*) &value); | : (Type) juce_InterlockedIncrement64 ((volatile __int64*) &value); | ||||
#elif JUCE_ANDROID | |||||
#elif JUCE_ATOMICS_ANDROID | |||||
return (Type) __atomic_inc ((volatile int*) &value); | return (Type) __atomic_inc ((volatile int*) &value); | ||||
#elif JUCE_ATOMICS_GCC | #elif JUCE_ATOMICS_GCC | ||||
return (Type) __sync_add_and_fetch (&value, 1); | return (Type) __sync_add_and_fetch (&value, 1); | ||||
@@ -320,7 +325,7 @@ inline Type Atomic<Type>::operator--() throw() | |||||
#elif JUCE_ATOMICS_WINDOWS | #elif JUCE_ATOMICS_WINDOWS | ||||
return sizeof (Type) == 4 ? (Type) juce_InterlockedDecrement ((volatile long*) &value) | return sizeof (Type) == 4 ? (Type) juce_InterlockedDecrement ((volatile long*) &value) | ||||
: (Type) juce_InterlockedDecrement64 ((volatile __int64*) &value); | : (Type) juce_InterlockedDecrement64 ((volatile __int64*) &value); | ||||
#elif JUCE_ANDROID | |||||
#elif JUCE_ATOMICS_ANDROID | |||||
return (Type) __atomic_dec ((volatile int*) &value); | return (Type) __atomic_dec ((volatile int*) &value); | ||||
#elif JUCE_ATOMICS_GCC | #elif JUCE_ATOMICS_GCC | ||||
return (Type) __sync_add_and_fetch (&value, -1); | return (Type) __sync_add_and_fetch (&value, -1); | ||||
@@ -333,8 +338,10 @@ inline bool Atomic<Type>::compareAndSetBool (const Type newValue, const Type val | |||||
#if JUCE_ATOMICS_MAC | #if JUCE_ATOMICS_MAC | ||||
return sizeof (Type) == 4 ? OSAtomicCompareAndSwap32Barrier ((int32_t) castTo32Bit (valueToCompare), (int32_t) castTo32Bit (newValue), (JUCE_MAC_ATOMICS_VOLATILE int32_t*) &value) | return sizeof (Type) == 4 ? OSAtomicCompareAndSwap32Barrier ((int32_t) castTo32Bit (valueToCompare), (int32_t) castTo32Bit (newValue), (JUCE_MAC_ATOMICS_VOLATILE int32_t*) &value) | ||||
: OSAtomicCompareAndSwap64Barrier ((int64_t) castTo64Bit (valueToCompare), (int64_t) castTo64Bit (newValue), (JUCE_MAC_ATOMICS_VOLATILE int64_t*) &value); | : OSAtomicCompareAndSwap64Barrier ((int64_t) castTo64Bit (valueToCompare), (int64_t) castTo64Bit (newValue), (JUCE_MAC_ATOMICS_VOLATILE int64_t*) &value); | ||||
#elif JUCE_ATOMICS_WINDOWS || JUCE_ANDROID | |||||
#elif JUCE_ATOMICS_WINDOWS | |||||
return compareAndSetValue (newValue, valueToCompare) == valueToCompare; | return compareAndSetValue (newValue, valueToCompare) == valueToCompare; | ||||
#elif JUCE_ATOMICS_ANDROID | |||||
return __atomic_cmpxchg (castTo32Bit (valueToCompare), castTo32Bit (newValue), (volatile int*) &value) == 0; | |||||
#elif JUCE_ATOMICS_GCC | #elif JUCE_ATOMICS_GCC | ||||
return sizeof (Type) == 4 ? __sync_bool_compare_and_swap ((volatile int32*) &value, castTo32Bit (valueToCompare), castTo32Bit (newValue)) | return sizeof (Type) == 4 ? __sync_bool_compare_and_swap ((volatile int32*) &value, castTo32Bit (valueToCompare), castTo32Bit (newValue)) | ||||
: __sync_bool_compare_and_swap ((volatile int64*) &value, castTo64Bit (valueToCompare), castTo64Bit (newValue)); | : __sync_bool_compare_and_swap ((volatile int64*) &value, castTo64Bit (valueToCompare), castTo64Bit (newValue)); | ||||
@@ -344,8 +351,8 @@ inline bool Atomic<Type>::compareAndSetBool (const Type newValue, const Type val | |||||
template <typename Type> | template <typename Type> | ||||
inline Type Atomic<Type>::compareAndSetValue (const Type newValue, const Type valueToCompare) throw() | inline Type Atomic<Type>::compareAndSetValue (const Type newValue, const Type valueToCompare) throw() | ||||
{ | { | ||||
#if JUCE_ATOMICS_MAC | |||||
for (;;) // Annoying workaround for OSX only having a bool CAS operation.. | |||||
#if JUCE_ATOMICS_MAC || JUCE_ATOMICS_ANDROID | |||||
for (;;) // Annoying workaround for only having a bool CAS operation.. | |||||
{ | { | ||||
if (compareAndSetBool (newValue, valueToCompare)) | if (compareAndSetBool (newValue, valueToCompare)) | ||||
return valueToCompare; | return valueToCompare; | ||||
@@ -358,8 +365,6 @@ inline Type Atomic<Type>::compareAndSetValue (const Type newValue, const Type va | |||||
#elif JUCE_ATOMICS_WINDOWS | #elif JUCE_ATOMICS_WINDOWS | ||||
return sizeof (Type) == 4 ? castFrom32Bit ((int32) juce_InterlockedCompareExchange ((volatile long*) &value, (long) castTo32Bit (newValue), (long) castTo32Bit (valueToCompare))) | return sizeof (Type) == 4 ? castFrom32Bit ((int32) juce_InterlockedCompareExchange ((volatile long*) &value, (long) castTo32Bit (newValue), (long) castTo32Bit (valueToCompare))) | ||||
: castFrom64Bit ((int64) juce_InterlockedCompareExchange64 ((volatile __int64*) &value, (__int64) castTo64Bit (newValue), (__int64) castTo64Bit (valueToCompare))); | : castFrom64Bit ((int64) juce_InterlockedCompareExchange64 ((volatile __int64*) &value, (__int64) castTo64Bit (newValue), (__int64) castTo64Bit (valueToCompare))); | ||||
#elif JUCE_ANDROID | |||||
return castFrom32Bit (__atomic_cmpxchg (castTo32Bit (valueToCompare), castTo32Bit (newValue), (volatile int*) &value)); | |||||
#elif JUCE_ATOMICS_GCC | #elif JUCE_ATOMICS_GCC | ||||
return sizeof (Type) == 4 ? castFrom32Bit ((int32) __sync_val_compare_and_swap ((volatile int32*) &value, castTo32Bit (valueToCompare), castTo32Bit (newValue))) | return sizeof (Type) == 4 ? castFrom32Bit ((int32) __sync_val_compare_and_swap ((volatile int32*) &value, castTo32Bit (valueToCompare), castTo32Bit (newValue))) | ||||
: castFrom64Bit ((int64) __sync_val_compare_and_swap ((volatile int64*) &value, castTo64Bit (valueToCompare), castTo64Bit (newValue))); | : castFrom64Bit ((int64) __sync_val_compare_and_swap ((volatile int64*) &value, castTo64Bit (valueToCompare), castTo64Bit (newValue))); | ||||
@@ -0,0 +1,94 @@ | |||||
/* | |||||
============================================================================== | |||||
This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||||
Copyright 2004-10 by Raw Material Software Ltd. | |||||
------------------------------------------------------------------------------ | |||||
JUCE can be redistributed and/or modified under the terms of the GNU General | |||||
Public License (Version 2), as published by the Free Software Foundation. | |||||
A copy of the license is included in the JUCE distribution, or can be found | |||||
online at www.gnu.org/licenses. | |||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||||
------------------------------------------------------------------------------ | |||||
To release a closed-source product which uses JUCE, commercial licenses are | |||||
available: visit www.rawmaterialsoftware.com/juce for more information. | |||||
============================================================================== | |||||
*/ | |||||
package com.juce; | |||||
import android.content.Context; | |||||
import android.view.*; | |||||
import android.graphics.*; | |||||
//============================================================================== | |||||
public class ComponentPeerView extends View | |||||
{ | |||||
public ComponentPeerView (Context context) | |||||
{ | |||||
super (context); | |||||
} | |||||
//============================================================================== | |||||
private native void handlePaint (Canvas canvas); | |||||
@Override | |||||
public void draw (Canvas canvas) | |||||
{ | |||||
handlePaint (canvas); | |||||
} | |||||
//============================================================================== | |||||
private native void handleMouseDown (float x, float y, long time); | |||||
private native void handleMouseDrag (float x, float y, long time); | |||||
private native void handleMouseUp (float x, float y, long time); | |||||
@Override | |||||
public boolean onTouchEvent (MotionEvent event) | |||||
{ | |||||
System.out.println (event.toString()); | |||||
switch (event.getAction()) | |||||
{ | |||||
case MotionEvent.ACTION_DOWN: handleMouseDown (event.getX(), event.getY(), event.getEventTime()); return true; | |||||
case MotionEvent.ACTION_MOVE: handleMouseDrag (event.getX(), event.getY(), event.getEventTime()); return true; | |||||
case MotionEvent.ACTION_CANCEL: | |||||
case MotionEvent.ACTION_UP: handleMouseUp (event.getX(), event.getY(), event.getEventTime()); return true; | |||||
default: break; | |||||
} | |||||
return false; | |||||
} | |||||
//============================================================================== | |||||
@Override | |||||
protected void onSizeChanged (int w, int h, int oldw, int oldh) | |||||
{ | |||||
} | |||||
@Override | |||||
protected void onLayout (boolean changed, int left, int top, int right, int bottom) | |||||
{ | |||||
} | |||||
public void setViewName (String newName) | |||||
{ | |||||
} | |||||
public boolean isVisible() | |||||
{ | |||||
return true; | |||||
} | |||||
public void setVisible (boolean b) | |||||
{ | |||||
} | |||||
} |
@@ -0,0 +1,131 @@ | |||||
/* | |||||
============================================================================== | |||||
This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||||
Copyright 2004-10 by Raw Material Software Ltd. | |||||
------------------------------------------------------------------------------ | |||||
JUCE can be redistributed and/or modified under the terms of the GNU General | |||||
Public License (Version 2), as published by the Free Software Foundation. | |||||
A copy of the license is included in the JUCE distribution, or can be found | |||||
online at www.gnu.org/licenses. | |||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||||
------------------------------------------------------------------------------ | |||||
To release a closed-source product which uses JUCE, commercial licenses are | |||||
available: visit www.rawmaterialsoftware.com/juce for more information. | |||||
============================================================================== | |||||
*/ | |||||
package com.juce; | |||||
import android.app.Activity; | |||||
import android.os.Bundle; | |||||
import android.content.*; | |||||
import android.view.*; | |||||
import com.juce.ComponentPeerView; | |||||
//============================================================================== | |||||
public class JuceAppActivity extends Activity | |||||
{ | |||||
//============================================================================== | |||||
static | |||||
{ | |||||
System.loadLibrary ("juce_jni"); | |||||
} | |||||
@Override | |||||
public void onCreate (Bundle savedInstanceState) | |||||
{ | |||||
super.onCreate (savedInstanceState); | |||||
messageHandler = new android.os.Handler(); | |||||
viewHolder = new ViewHolder (this); | |||||
setContentView (viewHolder); | |||||
WindowManager wm = (WindowManager) getSystemService (WINDOW_SERVICE); | |||||
Display display = wm.getDefaultDisplay(); | |||||
launchApp (getApplicationInfo().publicSourceDir, | |||||
getApplicationInfo().dataDir, | |||||
display.getWidth(), display.getHeight()); | |||||
} | |||||
@Override | |||||
protected void onDestroy() | |||||
{ | |||||
quitApp(); | |||||
super.onDestroy(); | |||||
} | |||||
//============================================================================== | |||||
public native void launchApp (String appFile, String appDataDir, | |||||
int screenWidth, int screenHeight); | |||||
public native void quitApp(); | |||||
//============================================================================== | |||||
public static void printToConsole (String s) | |||||
{ | |||||
System.out.println (s); | |||||
} | |||||
//============================================================================== | |||||
public native void deliverMessage (long value); | |||||
private android.os.Handler messageHandler; | |||||
public void postMessage (long value) | |||||
{ | |||||
messageHandler.post (new MessageCallback (this, value)); | |||||
} | |||||
class MessageCallback implements java.lang.Runnable | |||||
{ | |||||
public MessageCallback (JuceAppActivity app_, long value_) | |||||
{ | |||||
app = app_; | |||||
value = value_; | |||||
} | |||||
public void run() | |||||
{ | |||||
app.deliverMessage (value); | |||||
} | |||||
private JuceAppActivity app; | |||||
private long value; | |||||
} | |||||
//============================================================================== | |||||
private ViewHolder viewHolder; | |||||
public ComponentPeerView createNewView() | |||||
{ | |||||
ComponentPeerView v = new ComponentPeerView (this); | |||||
viewHolder.addView (v); | |||||
return v; | |||||
} | |||||
public void deleteView (ComponentPeerView view) | |||||
{ | |||||
viewHolder.removeView (view); | |||||
} | |||||
class ViewHolder extends ViewGroup | |||||
{ | |||||
public ViewHolder (Context context) | |||||
{ | |||||
super (context); | |||||
} | |||||
protected void onLayout (boolean changed, int left, int top, int right, int bottom) | |||||
{ | |||||
} | |||||
} | |||||
} |
@@ -108,73 +108,34 @@ const File File::getLinkedTarget() const | |||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
const char* juce_Argv0 = 0; // referenced from juce_Application.cpp | |||||
const File File::getSpecialLocation (const SpecialLocationType type) | const File File::getSpecialLocation (const SpecialLocationType type) | ||||
{ | { | ||||
// TODO | |||||
switch (type) | switch (type) | ||||
{ | { | ||||
case userHomeDirectory: | case userHomeDirectory: | ||||
{ | |||||
const char* homeDir = getenv ("HOME"); | |||||
if (homeDir == 0) | |||||
{ | |||||
struct passwd* const pw = getpwuid (getuid()); | |||||
if (pw != 0) | |||||
homeDir = pw->pw_dir; | |||||
} | |||||
return File (String::fromUTF8 (homeDir)); | |||||
} | |||||
case userDocumentsDirectory: | case userDocumentsDirectory: | ||||
case userMusicDirectory: | case userMusicDirectory: | ||||
case userMoviesDirectory: | case userMoviesDirectory: | ||||
case userApplicationDataDirectory: | case userApplicationDataDirectory: | ||||
return File ("~"); | |||||
return File (android.appDataDir); | |||||
case userDesktopDirectory: | case userDesktopDirectory: | ||||
return File ("~/Desktop"); | return File ("~/Desktop"); | ||||
case commonApplicationDataDirectory: | case commonApplicationDataDirectory: | ||||
return File ("/var"); | |||||
return File (android.appDataDir); | |||||
case globalApplicationsDirectory: | case globalApplicationsDirectory: | ||||
return File ("/usr"); | return File ("/usr"); | ||||
case tempDirectory: | case tempDirectory: | ||||
{ | |||||
File tmp ("/var/tmp"); | |||||
if (! tmp.isDirectory()) | |||||
{ | |||||
tmp = "/tmp"; | |||||
if (! tmp.isDirectory()) | |||||
tmp = File::getCurrentWorkingDirectory(); | |||||
} | |||||
return tmp; | |||||
} | |||||
return File ("~/.temp"); | |||||
case invokedExecutableFile: | case invokedExecutableFile: | ||||
if (juce_Argv0 != 0) | |||||
return File (String::fromUTF8 (juce_Argv0)); | |||||
// deliberate fall-through... | |||||
case currentExecutableFile: | case currentExecutableFile: | ||||
case currentApplicationFile: | case currentApplicationFile: | ||||
return juce_getExecutableFile(); | |||||
case hostApplicationPath: | case hostApplicationPath: | ||||
return juce_readlink ("/proc/self/exe", juce_getExecutableFile()); | |||||
return juce_getExecutableFile(); | |||||
default: | default: | ||||
jassertfalse; // unknown type? | jassertfalse; // unknown type? | ||||
@@ -29,15 +29,13 @@ | |||||
//============================================================================== | //============================================================================== | ||||
// TODO | |||||
class AndroidLowLevelGraphicsContext : public LowLevelGraphicsContext | class AndroidLowLevelGraphicsContext : public LowLevelGraphicsContext | ||||
{ | { | ||||
public: | public: | ||||
AndroidLowLevelGraphicsContext (const GlobalRef& canvas_) | AndroidLowLevelGraphicsContext (const GlobalRef& canvas_) | ||||
: canvas (canvas_), | : canvas (canvas_), | ||||
currentState (new SavedState()), | |||||
currentState (new SavedState()) | |||||
{ | { | ||||
paintStack.add (new GlobalRef()); | |||||
setFill (Colours::black); | setFill (Colours::black); | ||||
} | } | ||||
@@ -55,7 +53,7 @@ public: | |||||
void addTransform (const AffineTransform& transform) | void addTransform (const AffineTransform& transform) | ||||
{ | { | ||||
canvas.callVoidMethod (android.concat, createMatrix (canvas.getEnv(), transform)); | |||||
canvas.callVoidMethod (android.concat, createMatrix (getEnv(), transform).get()); | |||||
} | } | ||||
float getScaleFactor() | float getScaleFactor() | ||||
@@ -70,7 +68,7 @@ public: | |||||
bool clipToRectangleList (const RectangleList& clipRegion) | bool clipToRectangleList (const RectangleList& clipRegion) | ||||
{ | { | ||||
return canvas.callBooleanMethod (android.clipRegion, createRegion (canvas.getEnv(), clipRegion)); | |||||
return canvas.callBooleanMethod (android.clipRegion, createRegion (getEnv(), clipRegion).get()); | |||||
} | } | ||||
void excludeClipRectangle (const Rectangle<int>& r) | void excludeClipRectangle (const Rectangle<int>& r) | ||||
@@ -79,7 +77,7 @@ public: | |||||
void clipToPath (const Path& path, const AffineTransform& transform) | void clipToPath (const Path& path, const AffineTransform& transform) | ||||
{ | { | ||||
(void) canvas.callBooleanMethod (android.clipPath, createPath (canvas.getEnv(), path, transform)); | |||||
(void) canvas.callBooleanMethod (android.clipPath, createPath (getEnv(), path, transform).get()); | |||||
} | } | ||||
void clipToImageAlpha (const Image& sourceImage, const AffineTransform& transform) | void clipToImageAlpha (const Image& sourceImage, const AffineTransform& transform) | ||||
@@ -93,20 +91,21 @@ public: | |||||
const Rectangle<int> getClipBounds() const | const Rectangle<int> getClipBounds() const | ||||
{ | { | ||||
jobject rect = canvas.callObjectMethod (android.getClipBounds2); | |||||
JNIEnv* env = getEnv(); | |||||
const LocalRef<jobject> rect (canvas.callObjectMethod (android.getClipBounds2)); | |||||
const int left = canvas.getEnv()->GetIntField (rect, android.rectLeft); | |||||
const int top = canvas.getEnv()->GetIntField (rect, android.rectTop); | |||||
const int right = canvas.getEnv()->GetIntField (rect, android.rectRight); | |||||
const int bottom = canvas.getEnv()->GetIntField (rect, android.rectBottom); | |||||
const int left = env->GetIntField (rect, android.rectLeft); | |||||
const int top = env->GetIntField (rect, android.rectTop); | |||||
const int right = env->GetIntField (rect, android.rectRight); | |||||
const int bottom = env->GetIntField (rect, android.rectBottom); | |||||
return Rectangle<int> (left, top, right - left, bottom - top); | return Rectangle<int> (left, top, right - left, bottom - top); | ||||
} | } | ||||
bool isClipEmpty() const | bool isClipEmpty() const | ||||
{ | { | ||||
return ! canvas.callBooleanMethod (android.getClipBounds, | |||||
canvas.getEnv()->NewObject (android.rectClass, android.rectConstructor, 0, 0, 0, 0)); | |||||
LocalRef<jobject> tempRect (getEnv()->NewObject (android.rectClass, android.rectConstructor, 0, 0, 0, 0)); | |||||
return ! canvas.callBooleanMethod (android.getClipBounds, tempRect.get()); | |||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
@@ -128,13 +127,13 @@ public: | |||||
{ | { | ||||
canvas.callVoidMethod (android.drawRect, | canvas.callVoidMethod (android.drawRect, | ||||
(float) r.getX(), (float) r.getY(), (float) r.getRight(), (float) r.getBottom(), | (float) r.getX(), (float) r.getY(), (float) r.getRight(), (float) r.getBottom(), | ||||
getCurrentPaint().get()); | |||||
getCurrentPaint()); | |||||
} | } | ||||
void fillPath (const Path& path, const AffineTransform& transform) | void fillPath (const Path& path, const AffineTransform& transform) | ||||
{ | { | ||||
canvas.callVoidMethod (android.drawPath, createPath (canvas.getEnv(), path, transform), | |||||
getCurrentPaint().get()); | |||||
canvas.callVoidMethod (android.drawPath, createPath (getEnv(), path, transform).get(), | |||||
getCurrentPaint()); | |||||
} | } | ||||
void drawImage (const Image& sourceImage, const AffineTransform& transform, bool fillEntireClipAsTiles) | void drawImage (const Image& sourceImage, const AffineTransform& transform, bool fillEntireClipAsTiles) | ||||
@@ -145,17 +144,17 @@ public: | |||||
{ | { | ||||
canvas.callVoidMethod (android.drawLine, line.getStartX(), line.getStartY(), | canvas.callVoidMethod (android.drawLine, line.getStartX(), line.getStartY(), | ||||
line.getEndX(), line.getEndY(), | line.getEndX(), line.getEndY(), | ||||
getCurrentPaint().get()); | |||||
getCurrentPaint()); | |||||
} | } | ||||
void drawVerticalLine (int x, float top, float bottom) | void drawVerticalLine (int x, float top, float bottom) | ||||
{ | { | ||||
canvas.callVoidMethod (android.drawRect, (float) x, top, x + 1.0f, bottom, getCurrentPaint().get()); | |||||
canvas.callVoidMethod (android.drawRect, (float) x, top, x + 1.0f, bottom, getCurrentPaint()); | |||||
} | } | ||||
void drawHorizontalLine (int y, float left, float right) | void drawHorizontalLine (int y, float left, float right) | ||||
{ | { | ||||
canvas.callVoidMethod (android.drawRect, left, (float) y, right, y + 1.0f, getCurrentPaint().get()); | |||||
canvas.callVoidMethod (android.drawRect, left, (float) y, right, y + 1.0f, getCurrentPaint()); | |||||
} | } | ||||
void setFont (const Font& newFont) | void setFont (const Font& newFont) | ||||
@@ -223,21 +222,26 @@ public: | |||||
fillType = newType; | fillType = newType; | ||||
} | } | ||||
jobject getPaint (JNIEnv* env) | |||||
jobject getPaint() | |||||
{ | { | ||||
if (needsUpdate) | if (needsUpdate) | ||||
{ | { | ||||
JNIEnv* env = getEnv(); | |||||
if (paint.get() == 0) | if (paint.get() == 0) | ||||
paint = GlobalRef (env, env->NewObject (android.paintClass, android.paintClassConstructor)); | |||||
{ | |||||
paint = GlobalRef (env->NewObject (android.paintClass, android.paintClassConstructor)); | |||||
paint.callVoidMethod (android.setAntiAlias, true); | |||||
} | |||||
if (fillType.isColour()) | if (fillType.isColour()) | ||||
{ | { | ||||
paint.callVoidMethod (android.setShader, (jobject) 0); | |||||
paint.callObjectMethod (android.setShader, (jobject) 0); | |||||
paint.callVoidMethod (android.setColor, colourToInt (fillType.colour)); | paint.callVoidMethod (android.setColor, colourToInt (fillType.colour)); | ||||
} | } | ||||
else if (fillType.isGradient()) | else if (fillType.isGradient()) | ||||
{ | { | ||||
const ColourGradient& g = fillType.gradient; | |||||
const ColourGradient& g = *fillType.gradient; | |||||
const Point<float> p1 (g.point1); | const Point<float> p1 (g.point1); | ||||
const Point<float> p2 (g.point2); | const Point<float> p2 (g.point2); | ||||
@@ -251,7 +255,7 @@ public: | |||||
for (int i = 0; i < numColours; ++i) | for (int i = 0; i < numColours; ++i) | ||||
{ | { | ||||
colours[i] = g.getColour (i); | |||||
colours[i] = colourToInt (g.getColour (i)); | |||||
positions[i] = (float) g.getColourPosition(i); | positions[i] = (float) g.getColourPosition(i); | ||||
} | } | ||||
@@ -259,7 +263,7 @@ public: | |||||
env->SetFloatArrayRegion (positionsArray, 0, numColours, positions.getData()); | env->SetFloatArrayRegion (positionsArray, 0, numColours, positions.getData()); | ||||
} | } | ||||
jobject tileMode = xxxx | |||||
jobject tileMode = env->GetStaticObjectField (android.shaderTileModeClass, android.clampMode); | |||||
jobject shader; | jobject shader; | ||||
if (fillType.gradient->isRadial) | if (fillType.gradient->isRadial) | ||||
@@ -269,7 +273,7 @@ public: | |||||
p1.getX(), p1.getY(), | p1.getX(), p1.getY(), | ||||
p1.getDistanceFrom (p2), | p1.getDistanceFrom (p2), | ||||
coloursArray, positionsArray, | coloursArray, positionsArray, | ||||
tileMode)); | |||||
tileMode); | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
@@ -277,14 +281,19 @@ public: | |||||
android.linearGradientConstructor, | android.linearGradientConstructor, | ||||
p1.getX(), p1.getY(), p2.getX(), p2.getY(), | p1.getX(), p1.getY(), p2.getX(), p2.getY(), | ||||
coloursArray, positionsArray, | coloursArray, positionsArray, | ||||
tileMode)); | |||||
tileMode); | |||||
} | } | ||||
env->CallVoidMethod (shader, android.setLocalMatrix, createMatrix (fillType.transform)); | |||||
paint.callVoidMethod (android.setShader, shader); | |||||
env->DeleteLocalRef (coloursArray); | |||||
env->DeleteLocalRef (positionsArray); | |||||
env->CallVoidMethod (shader, android.setLocalMatrix, createMatrix (env, fillType.transform).get()); | |||||
paint.callObjectMethod (android.setShader, shader); | |||||
env->DeleteLocalRef (shader); | |||||
} | } | ||||
else | else | ||||
{x | |||||
{ | |||||
} | } | ||||
} | } | ||||
@@ -304,9 +313,12 @@ private: | |||||
ScopedPointer <SavedState> currentState; | ScopedPointer <SavedState> currentState; | ||||
OwnedArray <SavedState> stateStack; | OwnedArray <SavedState> stateStack; | ||||
GlobalRef& getCurrentPaint() throw() { return *paintStack.getUnchecked (paintStack.size() - 1); } | |||||
jobject getCurrentPaint() const | |||||
{ | |||||
return currentState->getPaint(); | |||||
} | |||||
static jobject createPath (JNIEnv* env, const Path& path) | |||||
static const LocalRef<jobject> createPath (JNIEnv* env, const Path& path) | |||||
{ | { | ||||
jobject p = env->NewObject (android.pathClass, android.pathClassConstructor); | jobject p = env->NewObject (android.pathClass, android.pathClassConstructor); | ||||
@@ -325,10 +337,10 @@ private: | |||||
} | } | ||||
} | } | ||||
return p; | |||||
return LocalRef<jobject> (p); | |||||
} | } | ||||
static jobject createPath (JNIEnv* env, const Path& path, const AffineTransform& transform) | |||||
static const LocalRef<jobject> createPath (JNIEnv* env, const Path& path, const AffineTransform& transform) | |||||
{ | { | ||||
if (transform.isIdentity()) | if (transform.isIdentity()) | ||||
return createPath (env, path); | return createPath (env, path); | ||||
@@ -338,7 +350,7 @@ private: | |||||
return createPath (env, tempPath); | return createPath (env, tempPath); | ||||
} | } | ||||
static jobject createMatrix (JNIEnv* env, const AffineTransform& t) | |||||
static const LocalRef<jobject> createMatrix (JNIEnv* env, const AffineTransform& t) | |||||
{ | { | ||||
jobject m = env->NewObject (android.matrixClass, android.matrixClassConstructor); | jobject m = env->NewObject (android.matrixClass, android.matrixClassConstructor); | ||||
@@ -352,25 +364,25 @@ private: | |||||
env->CallVoidMethod (m, android.setValues, javaArray); | env->CallVoidMethod (m, android.setValues, javaArray); | ||||
env->DeleteLocalRef (javaArray); | env->DeleteLocalRef (javaArray); | ||||
return m; | |||||
return LocalRef<jobject> (m); | |||||
} | } | ||||
static jobject createRect (JNIEnv* env, const Rectangle<int>& r) | |||||
static const LocalRef<jobject> createRect (JNIEnv* env, const Rectangle<int>& r) | |||||
{ | { | ||||
return env->NewObject (android.rectClass, android.rectConstructor, | |||||
r.getX(), r.getY(), r.getRight(), r.getBottom()); | |||||
return LocalRef<jobject> (env->NewObject (android.rectClass, android.rectConstructor, | |||||
r.getX(), r.getY(), r.getRight(), r.getBottom())); | |||||
} | } | ||||
static jobject createRegion (JNIEnv* env, const RectangleList& list) | |||||
static const LocalRef<jobject> createRegion (JNIEnv* env, const RectangleList& list) | |||||
{ | { | ||||
jobject region = env->NewObject (android.regionClass, android.regionConstructor); | jobject region = env->NewObject (android.regionClass, android.regionConstructor); | ||||
const int numRects = list.getNumRectangles(); | const int numRects = list.getNumRectangles(); | ||||
for (int i = 0; i < numRects; ++i) | for (int i = 0; i < numRects; ++i) | ||||
env->CallVoidMethod (region, android.regionUnion, createRect (env, list.getRectangle(i))); | |||||
env->CallVoidMethod (region, android.regionUnion, createRect (env, list.getRectangle(i)).get()); | |||||
return region; | |||||
return LocalRef<jobject> (region); | |||||
} | } | ||||
static int colourToInt (const Colour& col) throw() | static int colourToInt (const Colour& col) throw() | ||||
@@ -61,7 +61,7 @@ bool juce_dispatchNextMessageOnSystemQueue (const bool returnIfNoPendingMessages | |||||
//============================================================================== | //============================================================================== | ||||
bool juce_postMessageToSystemQueue (Message* message) | bool juce_postMessageToSystemQueue (Message* message) | ||||
{ | { | ||||
android.activity.callVoidMethod (android.postMessage, (jlong) (pointer_sized_uint) message); | |||||
getEnv()->CallVoidMethod (android.activity, android.postMessage, (jlong) (pointer_sized_uint) message); | |||||
return true; | return true; | ||||
} | } | ||||
@@ -32,9 +32,11 @@ extern JUCE_NAMESPACE::JUCEApplication* juce_CreateApplication(); // (from START | |||||
BEGIN_JUCE_NAMESPACE | BEGIN_JUCE_NAMESPACE | ||||
//============================================================================== | //============================================================================== | ||||
JUCE_JNI_CALLBACK (JuceAppActivity, launchApp, void, (JNIEnv* env, jobject activity, int screenWidth, int screenHeight)) | |||||
JUCE_JNI_CALLBACK (JuceAppActivity, launchApp, void, (JNIEnv* env, jobject activity, | |||||
jstring appFile, jstring appDataDir, | |||||
int screenWidth, int screenHeight)) | |||||
{ | { | ||||
android.initialise (env, activity, screenWidth, screenHeight); | |||||
android.initialise (env, activity, appFile, appDataDir, screenWidth, screenHeight); | |||||
JUCEApplication::createInstance = &juce_CreateApplication; | JUCEApplication::createInstance = &juce_CreateApplication; | ||||
@@ -60,8 +62,8 @@ void PlatformUtilities::beep() | |||||
//============================================================================== | //============================================================================== | ||||
void Logger::outputDebugString (const String& text) | void Logger::outputDebugString (const String& text) | ||||
{ | { | ||||
android.env->CallStaticVoidMethod (android.activityClass, android.printToConsole, | |||||
android.javaString (text)); | |||||
getEnv()->CallStaticVoidMethod (android.activityClass, android.printToConsole, | |||||
javaString (text).get()); | |||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
@@ -107,11 +107,12 @@ BEGIN_JUCE_NAMESPACE | |||||
JAVACLASS (rectClass, "android/graphics/Rect") \ | JAVACLASS (rectClass, "android/graphics/Rect") \ | ||||
JAVACLASS (regionClass, "android/graphics/Region") \ | JAVACLASS (regionClass, "android/graphics/Region") \ | ||||
JAVACLASS (shaderClass, "android/graphics/Shader") \ | JAVACLASS (shaderClass, "android/graphics/Shader") \ | ||||
JAVACLASS (shaderTileModeClass, "android/graphics/Shader$TileMode") \ | |||||
JAVACLASS (linearGradientClass, "android/graphics/LinearGradient") \ | JAVACLASS (linearGradientClass, "android/graphics/LinearGradient") \ | ||||
JAVACLASS (radialGradientClass, "android/graphics/RadialGradient") \ | JAVACLASS (radialGradientClass, "android/graphics/RadialGradient") \ | ||||
//============================================================================== | //============================================================================== | ||||
#define JUCE_JNI_METHODS(METHOD, STATICMETHOD, FIELD) \ | |||||
#define JUCE_JNI_METHODS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ | |||||
\ | \ | ||||
STATICMETHOD (activityClass, printToConsole, "printToConsole", "(Ljava/lang/String;)V") \ | STATICMETHOD (activityClass, printToConsole, "printToConsole", "(Ljava/lang/String;)V") \ | ||||
METHOD (activityClass, createNewView, "createNewView", "()Lcom/juce/ComponentPeerView;") \ | METHOD (activityClass, createNewView, "createNewView", "()Lcom/juce/ComponentPeerView;") \ | ||||
@@ -153,8 +154,10 @@ BEGIN_JUCE_NAMESPACE | |||||
METHOD (paintClass, paintClassConstructor, "<init>", "()V") \ | METHOD (paintClass, paintClassConstructor, "<init>", "()V") \ | ||||
METHOD (paintClass, setColor, "setColor", "(I)V") \ | METHOD (paintClass, setColor, "setColor", "(I)V") \ | ||||
METHOD (paintClass, setShader, "setShader", "(Landroid/graphics/Shader;)Landroid/graphics/Shader;") \ | METHOD (paintClass, setShader, "setShader", "(Landroid/graphics/Shader;)Landroid/graphics/Shader;") \ | ||||
METHOD (paintClass, setAntiAlias, "setAntiAlias", "(Z)V") \ | |||||
\ | \ | ||||
METHOD (shaderClass, setLocalMatrix, "setLocalMatrix", "(Landroid/graphics/Matrix;)V") \ | METHOD (shaderClass, setLocalMatrix, "setLocalMatrix", "(Landroid/graphics/Matrix;)V") \ | ||||
STATICFIELD (shaderTileModeClass, clampMode, "CLAMP", "Landroid/graphics/Shader$TileMode;") \ | |||||
\ | \ | ||||
METHOD (pathClass, pathClassConstructor, "<init>", "()V") \ | METHOD (pathClass, pathClassConstructor, "<init>", "()V") \ | ||||
METHOD (pathClass, moveTo, "moveTo", "(FF)V") \ | METHOD (pathClass, moveTo, "moveTo", "(FF)V") \ | ||||
@@ -180,24 +183,116 @@ BEGIN_JUCE_NAMESPACE | |||||
METHOD (regionClass, regionUnion, "union", "(Landroid/graphics/Rect;)Z"); \ | METHOD (regionClass, regionUnion, "union", "(Landroid/graphics/Rect;)Z"); \ | ||||
//============================================================================== | |||||
class ThreadLocalJNIEnvHolder | |||||
{ | |||||
public: | |||||
ThreadLocalJNIEnvHolder() | |||||
: jvm (0) | |||||
{ | |||||
zeromem (threads, sizeof (threads)); | |||||
zeromem (envs, sizeof (envs)); | |||||
} | |||||
void initialise (JNIEnv* env) | |||||
{ | |||||
env->GetJavaVM (&jvm); | |||||
addEnv (env); | |||||
} | |||||
void attach() | |||||
{ | |||||
JNIEnv* env = 0; | |||||
jvm->AttachCurrentThread (&env, 0); | |||||
if (env != 0) | |||||
addEnv (env); | |||||
} | |||||
void detach() | |||||
{ | |||||
jvm->DetachCurrentThread(); | |||||
const pthread_t thisThread = pthread_self(); | |||||
ScopedLock sl (addRemoveLock); | |||||
for (int i = 0; i < maxThreads; ++i) | |||||
if (threads[i] == thisThread) | |||||
threads[i] = 0; | |||||
} | |||||
JNIEnv* get() const throw() | |||||
{ | |||||
const pthread_t thisThread = pthread_self(); | |||||
for (int i = 0; i < maxThreads; ++i) | |||||
if (threads[i] == thisThread) | |||||
return envs[i]; | |||||
return 0; | |||||
} | |||||
enum { maxThreads = 16 }; | |||||
private: | |||||
JavaVM* jvm; | |||||
pthread_t threads [maxThreads]; | |||||
JNIEnv* envs [maxThreads]; | |||||
CriticalSection addRemoveLock; | |||||
void addEnv (JNIEnv* env) | |||||
{ | |||||
ScopedLock sl (addRemoveLock); | |||||
if (get() == 0) | |||||
{ | |||||
const pthread_t thisThread = pthread_self(); | |||||
for (int i = 0; i < maxThreads; ++i) | |||||
{ | |||||
if (threads[i] == 0) | |||||
{ | |||||
envs[i] = env; | |||||
threads[i] = thisThread; | |||||
return; | |||||
} | |||||
} | |||||
} | |||||
jassertfalse; // too many threads! | |||||
} | |||||
}; | |||||
static ThreadLocalJNIEnvHolder threadLocalJNIEnvHolder; | |||||
struct AndroidThreadScope | |||||
{ | |||||
AndroidThreadScope() { threadLocalJNIEnvHolder.attach(); } | |||||
~AndroidThreadScope() { threadLocalJNIEnvHolder.detach(); } | |||||
}; | |||||
static inline JNIEnv* getEnv() throw() | |||||
{ | |||||
return threadLocalJNIEnvHolder.get(); | |||||
} | |||||
//============================================================================== | //============================================================================== | ||||
class GlobalRef | class GlobalRef | ||||
{ | { | ||||
public: | public: | ||||
GlobalRef() | |||||
: env (0), obj (0) | |||||
inline GlobalRef() throw() | |||||
: obj (0) | |||||
{ | { | ||||
} | } | ||||
GlobalRef (JNIEnv* const env_, jobject obj_) | |||||
: env (env_), | |||||
obj (retain (env_, obj_)) | |||||
inline explicit GlobalRef (jobject obj_) | |||||
: obj (retain (obj_)) | |||||
{ | { | ||||
} | } | ||||
GlobalRef (const GlobalRef& other) | |||||
: env (other.env), | |||||
obj (retain (other.env, other.obj)) | |||||
inline GlobalRef (const GlobalRef& other) | |||||
: obj (retain (other.obj)) | |||||
{ | { | ||||
} | } | ||||
@@ -206,28 +301,22 @@ public: | |||||
clear(); | clear(); | ||||
} | } | ||||
void clear() | |||||
inline void clear() | |||||
{ | { | ||||
if (env != 0) | |||||
{ | |||||
env->DeleteGlobalRef (obj); | |||||
env = 0; | |||||
obj = 0; | |||||
} | |||||
if (obj != 0) | |||||
getEnv()->DeleteGlobalRef (obj); | |||||
} | } | ||||
GlobalRef& operator= (const GlobalRef& other) | |||||
inline GlobalRef& operator= (const GlobalRef& other) | |||||
{ | { | ||||
clear(); | clear(); | ||||
env = other.env; | |||||
obj = retain (env, other.obj); | |||||
obj = retain (other.obj); | |||||
return *this; | return *this; | ||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
inline operator jobject() const throw() { return obj; } | inline operator jobject() const throw() { return obj; } | ||||
inline jobject get() const throw() { return obj; } | inline jobject get() const throw() { return obj; } | ||||
inline JNIEnv* getEnv() const throw() { return env; } | |||||
//============================================================================== | //============================================================================== | ||||
#define DECLARE_CALL_TYPE_METHOD(returnType, typeName) \ | #define DECLARE_CALL_TYPE_METHOD(returnType, typeName) \ | ||||
@@ -235,7 +324,7 @@ public: | |||||
{ \ | { \ | ||||
va_list args; \ | va_list args; \ | ||||
va_start (args, methodID); \ | va_start (args, methodID); \ | ||||
returnType result = env->Call##typeName##MethodV (obj, methodID, args); \ | |||||
returnType result = getEnv()->Call##typeName##MethodV (obj, methodID, args); \ | |||||
va_end (args); \ | va_end (args); \ | ||||
return result; \ | return result; \ | ||||
} | } | ||||
@@ -255,33 +344,101 @@ public: | |||||
{ | { | ||||
va_list args; | va_list args; | ||||
va_start (args, methodID); | va_start (args, methodID); | ||||
env->CallVoidMethodV (obj, methodID, args); | |||||
getEnv()->CallVoidMethodV (obj, methodID, args); | |||||
va_end (args); | va_end (args); | ||||
} | } | ||||
private: | private: | ||||
//============================================================================== | //============================================================================== | ||||
JNIEnv* env; | |||||
jobject obj; | jobject obj; | ||||
static jobject retain (JNIEnv* const env, jobject obj_) | |||||
static inline jobject retain (jobject obj_) | |||||
{ | { | ||||
return env == 0 ? 0 : env->NewGlobalRef (obj_); | |||||
return obj_ == 0 ? 0 : getEnv()->NewGlobalRef (obj_); | |||||
} | } | ||||
}; | }; | ||||
//============================================================================== | |||||
template <typename JavaType> | |||||
class LocalRef | |||||
{ | |||||
public: | |||||
explicit inline LocalRef (JavaType obj_) throw() | |||||
: obj (obj_) | |||||
{ | |||||
} | |||||
inline LocalRef (const LocalRef& other) throw() | |||||
: obj (retain (other.obj)) | |||||
{ | |||||
} | |||||
~LocalRef() | |||||
{ | |||||
if (obj != 0) | |||||
getEnv()->DeleteLocalRef (obj); | |||||
} | |||||
LocalRef& operator= (const LocalRef& other) | |||||
{ | |||||
if (obj != other.obj) | |||||
{ | |||||
if (obj != 0) | |||||
getEnv()->DeleteLocalRef (obj); | |||||
obj = retain (other.obj); | |||||
} | |||||
return *this; | |||||
} | |||||
inline operator JavaType() const throw() { return obj; } | |||||
inline JavaType get() const throw() { return obj; } | |||||
private: | |||||
JavaType obj; | |||||
static JavaType retain (JavaType obj_) | |||||
{ | |||||
return obj_ == 0 ? 0 : (JavaType) getEnv()->NewLocalRef (obj_); | |||||
} | |||||
}; | |||||
//============================================================================== | |||||
static const String juceString (jstring s) | |||||
{ | |||||
JNIEnv* env = getEnv(); | |||||
jboolean isCopy; | |||||
const char* const utf8 = env->GetStringUTFChars (s, &isCopy); | |||||
CharPointer_UTF8 utf8CP (utf8); | |||||
const String result (utf8CP); | |||||
env->ReleaseStringUTFChars (s, utf8); | |||||
return result; | |||||
} | |||||
static const LocalRef<jstring> javaString (const String& s) | |||||
{ | |||||
return LocalRef<jstring> (getEnv()->NewStringUTF (s.toUTF8())); | |||||
} | |||||
//============================================================================== | //============================================================================== | ||||
class AndroidJavaCallbacks | class AndroidJavaCallbacks | ||||
{ | { | ||||
public: | public: | ||||
AndroidJavaCallbacks() : env (0), screenWidth (0), screenHeight (0) | |||||
AndroidJavaCallbacks() : screenWidth (0), screenHeight (0) | |||||
{ | { | ||||
} | } | ||||
void initialise (JNIEnv* env_, jobject activity_, int screenWidth_, int screenHeight_) | |||||
void initialise (JNIEnv* env, jobject activity_, | |||||
jstring appFile_, jstring appDataDir_, | |||||
int screenWidth_, int screenHeight_) | |||||
{ | { | ||||
env = env_; | |||||
activity = GlobalRef (env, activity_); | |||||
threadLocalJNIEnvHolder.initialise (env); | |||||
activity = GlobalRef (activity_); | |||||
appFile = juceString (appFile_); | |||||
appDataDir = juceString (appDataDir_); | |||||
screenWidth = screenWidth_; | screenWidth = screenWidth_; | ||||
screenHeight = screenHeight_; | screenHeight = screenHeight_; | ||||
@@ -300,12 +457,17 @@ public: | |||||
#define CREATE_JNI_FIELD(ownerClass, fieldID, stringName, signature) \ | #define CREATE_JNI_FIELD(ownerClass, fieldID, stringName, signature) \ | ||||
fieldID = env->GetFieldID (ownerClass, stringName, signature); \ | fieldID = env->GetFieldID (ownerClass, stringName, signature); \ | ||||
jassert (fieldID != 0); | jassert (fieldID != 0); | ||||
JUCE_JNI_METHODS (CREATE_JNI_METHOD, CREATE_JNI_STATICMETHOD, CREATE_JNI_FIELD); | |||||
#define CREATE_JNI_STATICFIELD(ownerClass, fieldID, stringName, signature) \ | |||||
fieldID = env->GetStaticFieldID (ownerClass, stringName, signature); \ | |||||
jassert (fieldID != 0); | |||||
JUCE_JNI_METHODS (CREATE_JNI_METHOD, CREATE_JNI_STATICMETHOD, CREATE_JNI_FIELD, CREATE_JNI_STATICFIELD); | |||||
#undef CREATE_JNI_METHOD | #undef CREATE_JNI_METHOD | ||||
} | } | ||||
void shutdown() | void shutdown() | ||||
{ | { | ||||
JNIEnv* env = getEnv(); | |||||
if (env != 0) | if (env != 0) | ||||
{ | { | ||||
#define RELEASE_JNI_CLASS(className, path) env->DeleteGlobalRef (className); | #define RELEASE_JNI_CLASS(className, path) env->DeleteGlobalRef (className); | ||||
@@ -313,29 +475,12 @@ public: | |||||
#undef RELEASE_JNI_CLASS | #undef RELEASE_JNI_CLASS | ||||
activity.clear(); | activity.clear(); | ||||
env = 0; | |||||
} | } | ||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
const String juceString (jstring s) const | |||||
{ | |||||
jboolean isCopy; | |||||
const char* const utf8 = env->GetStringUTFChars (s, &isCopy); | |||||
CharPointer_UTF8 utf8CP (utf8); | |||||
const String result (utf8CP); | |||||
env->ReleaseStringUTFChars (s, utf8); | |||||
return result; | |||||
} | |||||
jstring javaString (const String& s) const | |||||
{ | |||||
return env->NewStringUTF (s.toUTF8()); | |||||
} | |||||
//============================================================================== | |||||
JNIEnv* env; | |||||
GlobalRef activity; | GlobalRef activity; | ||||
String appFile, appDataDir; | |||||
int screenWidth, screenHeight; | int screenWidth, screenHeight; | ||||
//============================================================================== | //============================================================================== | ||||
@@ -345,13 +490,12 @@ public: | |||||
#define DECLARE_JNI_METHOD(ownerClass, methodID, stringName, params) jmethodID methodID; | #define DECLARE_JNI_METHOD(ownerClass, methodID, stringName, params) jmethodID methodID; | ||||
#define DECLARE_JNI_FIELD(ownerClass, fieldID, stringName, signature) jfieldID fieldID; | #define DECLARE_JNI_FIELD(ownerClass, fieldID, stringName, signature) jfieldID fieldID; | ||||
JUCE_JNI_METHODS (DECLARE_JNI_METHOD, DECLARE_JNI_METHOD, DECLARE_JNI_FIELD); | |||||
JUCE_JNI_METHODS (DECLARE_JNI_METHOD, DECLARE_JNI_METHOD, DECLARE_JNI_FIELD, DECLARE_JNI_FIELD); | |||||
#undef DECLARE_JNI_METHOD | #undef DECLARE_JNI_METHOD | ||||
}; | }; | ||||
static AndroidJavaCallbacks android; | static AndroidJavaCallbacks android; | ||||
//============================================================================== | //============================================================================== | ||||
#define JUCE_INCLUDED_FILE 1 | #define JUCE_INCLUDED_FILE 1 | ||||
@@ -77,8 +77,6 @@ int SystemStats::getCpuSpeedInMegaherz() | |||||
int SystemStats::getMemorySizeInMegabytes() | int SystemStats::getMemorySizeInMegabytes() | ||||
{ | { | ||||
// TODO | |||||
struct sysinfo sysi; | struct sysinfo sysi; | ||||
if (sysinfo (&sysi) == 0) | if (sysinfo (&sysi) == 0) | ||||
@@ -125,8 +123,7 @@ void SystemStats::initialiseStats() | |||||
cpuFlags.hasSSE2 = flags.contains ("sse2"); | cpuFlags.hasSSE2 = flags.contains ("sse2"); | ||||
cpuFlags.has3DNow = flags.contains ("3dnow"); | cpuFlags.has3DNow = flags.contains ("3dnow"); | ||||
// TODO | |||||
cpuFlags.numCpus = AndroidStatsHelpers::getCpuInfo ("processor").getIntValue() + 1; | |||||
cpuFlags.numCpus = jmax (1, sysconf (_SC_NPROCESSORS_ONLN)); | |||||
} | } | ||||
void PlatformUtilities::fpuReset() {} | void PlatformUtilities::fpuReset() {} | ||||
@@ -27,6 +27,7 @@ | |||||
// compiled on its own). | // compiled on its own). | ||||
#if JUCE_INCLUDED_FILE | #if JUCE_INCLUDED_FILE | ||||
static ModifierKeys currentModifiers; | |||||
//============================================================================== | //============================================================================== | ||||
class AndroidComponentPeer : public ComponentPeer | class AndroidComponentPeer : public ComponentPeer | ||||
@@ -34,9 +35,9 @@ class AndroidComponentPeer : public ComponentPeer | |||||
public: | public: | ||||
//============================================================================== | //============================================================================== | ||||
AndroidComponentPeer (Component* const component, const int windowStyleFlags) | AndroidComponentPeer (Component* const component, const int windowStyleFlags) | ||||
: ComponentPeer (component, windowStyleFlags) | |||||
: ComponentPeer (component, windowStyleFlags), | |||||
view (android.activity.callObjectMethod (android.createNewView)) | |||||
{ | { | ||||
view = GlobalRef (android.env, android.activity.callObjectMethod (android.createNewView)); | |||||
} | } | ||||
~AndroidComponentPeer() | ~AndroidComponentPeer() | ||||
@@ -57,7 +58,7 @@ public: | |||||
void setTitle (const String& title) | void setTitle (const String& title) | ||||
{ | { | ||||
view.callVoidMethod (android.setViewName, android.javaString (title)); | |||||
view.callVoidMethod (android.setViewName, javaString (title).get()); | |||||
} | } | ||||
void setPosition (int x, int y) | void setPosition (int x, int y) | ||||
@@ -87,7 +88,7 @@ public: | |||||
const Point<int> getScreenPosition() const | const Point<int> getScreenPosition() const | ||||
{ | { | ||||
JNIEnv* const env = view.getEnv(); | |||||
JNIEnv* const env = getEnv(); | |||||
jintArray pos = env->NewIntArray (2); | jintArray pos = env->NewIntArray (2); | ||||
view.callVoidMethod (android.getLocationOnScreen, pos); | view.callVoidMethod (android.getLocationOnScreen, pos); | ||||
@@ -169,6 +170,26 @@ public: | |||||
// TODO | // TODO | ||||
} | } | ||||
//============================================================================== | |||||
void handleMouseDownCallback (float x, float y, int64 time) | |||||
{ | |||||
currentModifiers = currentModifiers.withoutMouseButtons(); | |||||
handleMouseEvent (0, Point<int> ((int) x, (int) y), currentModifiers, time); | |||||
currentModifiers = currentModifiers.withoutMouseButtons().withFlags (ModifierKeys::leftButtonModifier); | |||||
handleMouseEvent (0, Point<int> ((int) x, (int) y), currentModifiers, time); | |||||
} | |||||
void handleMouseDragCallback (float x, float y, int64 time) | |||||
{ | |||||
handleMouseEvent (0, Point<int> ((int) x, (int) y), currentModifiers, time); | |||||
} | |||||
void handleMouseUpCallback (float x, float y, int64 time) | |||||
{ | |||||
currentModifiers = currentModifiers.withoutMouseButtons(); | |||||
handleMouseEvent (0, Point<int> ((int) x, (int) y), currentModifiers, time); | |||||
} | |||||
//============================================================================== | //============================================================================== | ||||
bool isFocused() const | bool isFocused() const | ||||
{ | { | ||||
@@ -188,7 +209,8 @@ public: | |||||
//============================================================================== | //============================================================================== | ||||
void handlePaintCallback (JNIEnv* env, jobject canvas) | void handlePaintCallback (JNIEnv* env, jobject canvas) | ||||
{ | { | ||||
AndroidLowLevelGraphicsContext g (GlobalRef (env, canvas)); | |||||
GlobalRef canvasRef (canvas); | |||||
AndroidLowLevelGraphicsContext g (canvasRef); | |||||
handlePaint (g); | handlePaint (g); | ||||
} | } | ||||
@@ -241,6 +263,12 @@ private: | |||||
JUCE_VIEW_CALLBACK (void, handlePaint, (JNIEnv* env, jobject view, jobject canvas), | JUCE_VIEW_CALLBACK (void, handlePaint, (JNIEnv* env, jobject view, jobject canvas), | ||||
handlePaintCallback (env, canvas)) | handlePaintCallback (env, canvas)) | ||||
JUCE_VIEW_CALLBACK (void, handleMouseDown, (JNIEnv*, jobject view, jfloat x, jfloat y, jlong time), | |||||
handleMouseDownCallback ((float) x, (float) y, (int64) time)) | |||||
JUCE_VIEW_CALLBACK (void, handleMouseDrag, (JNIEnv*, jobject view, jfloat x, jfloat y, jlong time), | |||||
handleMouseDragCallback ((float) x, (float) y, (int64) time)) | |||||
JUCE_VIEW_CALLBACK (void, handleMouseUp, (JNIEnv*, jobject view, jfloat x, jfloat y, jlong time), | |||||
handleMouseUpCallback ((float) x, (float) y, (int64) time)) | |||||
//============================================================================== | //============================================================================== | ||||
ComponentPeer* Component::createNewPeer (int styleFlags, void*) | ComponentPeer* Component::createNewPeer (int styleFlags, void*) | ||||
@@ -294,8 +322,7 @@ void ModifierKeys::updateCurrentModifiers() throw() | |||||
const ModifierKeys ModifierKeys::getCurrentModifiersRealtime() throw() | const ModifierKeys ModifierKeys::getCurrentModifiersRealtime() throw() | ||||
{ | { | ||||
// TODO | |||||
return ModifierKeys(); | |||||
return currentModifiers; | |||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
@@ -486,8 +486,7 @@ void FileOutputStream::flushInternal() | |||||
const File juce_getExecutableFile() | const File juce_getExecutableFile() | ||||
{ | { | ||||
#if JUCE_ANDROID | #if JUCE_ANDROID | ||||
// TODO | |||||
return File::nonexistent; | |||||
return File (android.appFile); | |||||
#else | #else | ||||
Dl_info exeInfo; | Dl_info exeInfo; | ||||
dladdr ((void*) juce_getExecutableFile, &exeInfo); // (can't be a const void* on android) | dladdr ((void*) juce_getExecutableFile, &exeInfo); // (can't be a const void* on android) | ||||
@@ -707,6 +706,11 @@ void JUCE_API juce_threadEntryPoint (void*); | |||||
void* threadEntryProc (void* userData) | void* threadEntryProc (void* userData) | ||||
{ | { | ||||
JUCE_AUTORELEASEPOOL | JUCE_AUTORELEASEPOOL | ||||
#if JUCE_ANDROID | |||||
const AndroidThreadScope androidEnv; | |||||
#endif | |||||
juce_threadEntryPoint (userData); | juce_threadEntryPoint (userData); | ||||
return 0; | return 0; | ||||
} | } | ||||
@@ -744,7 +748,7 @@ void Thread::killThread() | |||||
void Thread::setCurrentThreadName (const String& name) | void Thread::setCurrentThreadName (const String& name) | ||||
{ | { | ||||
#if JUCE_MAC | |||||
#if JUCE_MAC && defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6 | |||||
pthread_setname_np (name.toUTF8()); | pthread_setname_np (name.toUTF8()); | ||||
#elif JUCE_LINUX | #elif JUCE_LINUX | ||||
prctl (PR_SET_NAME, name.toUTF8().getAddress(), 0, 0, 0); | prctl (PR_SET_NAME, name.toUTF8().getAddress(), 0, 0, 0); | ||||
@@ -95,6 +95,7 @@ BEGIN_JUCE_NAMESPACE | |||||
#include "../common/juce_MidiDataConcatenator.h" | #include "../common/juce_MidiDataConcatenator.h" | ||||
#undef Point | #undef Point | ||||
#if ! JUCE_ONLY_BUILD_CORE_LIBRARY | |||||
namespace | namespace | ||||
{ | { | ||||
template <class RectType> | template <class RectType> | ||||
@@ -183,6 +184,7 @@ private: | |||||
static_cast <MessageQueue*> (info)->runLoopCallback(); | static_cast <MessageQueue*> (info)->runLoopCallback(); | ||||
} | } | ||||
}; | }; | ||||
#endif | |||||
//============================================================================== | //============================================================================== | ||||
#define JUCE_INCLUDED_FILE 1 | #define JUCE_INCLUDED_FILE 1 | ||||
@@ -213,11 +213,11 @@ public: | |||||
for (;;) | for (;;) | ||||
{ | { | ||||
const int n = *d++; | |||||
const uint32 n = (uint32) (uint8) *d++; | |||||
if ((n & 0x80) != 0) | if ((n & 0x80) != 0) | ||||
{ | { | ||||
int bit = 0x40; | |||||
uint32 bit = 0x40; | |||||
while ((n & bit) != 0) | while ((n & bit) != 0) | ||||
{ | { | ||||
@@ -2241,7 +2241,7 @@ public: | |||||
{ | { | ||||
buffer[i] = (juce_wchar) (1 + Random::getSystemRandom().nextInt (0x10ffff - 1)); | buffer[i] = (juce_wchar) (1 + Random::getSystemRandom().nextInt (0x10ffff - 1)); | ||||
} | } | ||||
while (buffer[i] >= 0xd800 && buffer[i] <= 0xdfff); // (these code-points are illegal in UTF-16) | |||||
while (! CharPointer_UTF16::canRepresent (buffer[i])); | |||||
} | } | ||||
else | else | ||||
buffer[i] = (juce_wchar) (1 + Random::getSystemRandom().nextInt (0xff)); | buffer[i] = (juce_wchar) (1 + Random::getSystemRandom().nextInt (0xff)); | ||||
@@ -161,8 +161,8 @@ void UnitTestRunner::endTest() | |||||
if (r->failures > 0) | if (r->failures > 0) | ||||
{ | { | ||||
String m ("FAILED!!"); | |||||
m << r->failures << (r->failures == 1 ? "test" : "tests") | |||||
String m ("FAILED!! "); | |||||
m << r->failures << (r->failures == 1 ? " test" : " tests") | |||||
<< " failed, out of a total of " << (r->passes + r->failures); | << " failed, out of a total of " << (r->passes + r->failures); | ||||
logMessage (String::empty); | logMessage (String::empty); | ||||