@@ -150,8 +150,6 @@ | |||
#include "../src/threads/juce_Thread.cpp" | |||
#include "../src/threads/juce_ThreadPool.cpp" | |||
#include "../src/threads/juce_TimeSliceThread.cpp" | |||
#include "../src/utilities/juce_DeletedAtShutdown.cpp" | |||
#include "../src/utilities/juce_UnitTest.cpp" | |||
#endif | |||
#if JUCE_BUILD_MISC | |||
@@ -166,6 +164,8 @@ | |||
#include "../src/utilities/juce_FileBasedDocument.cpp" | |||
#include "../src/utilities/juce_RecentlyOpenedFilesList.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_AudioFormat.cpp" | |||
#include "../src/audio/audio_file_formats/juce_AudioFormatReader.cpp" | |||
@@ -209,11 +209,13 @@ private: | |||
for (int i = 0; i < files.size(); ++i) | |||
out << " ../" << escapeSpaces (files.getReference(i).toUnixStyle()) << "\\" << newLine; | |||
String cFlags ("-fsigned-char"); | |||
out << newLine | |||
<< "ifeq ($(CONFIG),Debug)" << newLine | |||
<< " LOCAL_CFLAGS +=" << createPreprocessorDefs (true) << newLine | |||
<< " LOCAL_CFLAGS += -g " << cFlags << createPreprocessorDefs (true) << newLine | |||
<< "else" << newLine | |||
<< " LOCAL_CFLAGS +=" << createPreprocessorDefs (false) << newLine | |||
<< " LOCAL_CFLAGS += " << cFlags << createPreprocessorDefs (false) << newLine | |||
<< "endif" << newLine | |||
<< newLine | |||
<< "include $(BUILD_SHARED_LIBRARY)" << newLine; | |||
@@ -2245,6 +2245,10 @@ private: | |||
#define JUCE_64BIT_ATOMICS_UNAVAILABLE 1 | |||
#endif | |||
#elif JUCE_ANDROID | |||
#define JUCE_ATOMICS_ANDROID 1 // Android atomic functions | |||
#define JUCE_64BIT_ATOMICS_UNAVAILABLE 1 | |||
#elif JUCE_GCC | |||
#define JUCE_ATOMICS_GCC 1 // GCC with intrinsics | |||
@@ -2306,8 +2310,8 @@ inline Type Atomic<Type>::get() const throw() | |||
#elif JUCE_ATOMICS_WINDOWS | |||
return sizeof (Type) == 4 ? castFrom32Bit ((int32) juce_InterlockedExchangeAdd ((volatile long*) &value, (long) 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 | |||
return sizeof (Type) == 4 ? castFrom32Bit ((int32) __sync_add_and_fetch ((volatile int32*) &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> | |||
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)); | |||
#elif JUCE_ATOMICS_MAC || JUCE_ATOMICS_GCC | |||
Type currentVal = value; | |||
@@ -2338,7 +2342,7 @@ inline Type Atomic<Type>::operator+= (const Type amountToAdd) throw() | |||
#elif JUCE_ATOMICS_WINDOWS | |||
return sizeof (Type) == 4 ? (Type) (juce_InterlockedExchangeAdd ((volatile long*) &value, (long) amountToAdd) + (long) amountToAdd) | |||
: (Type) (juce_InterlockedExchangeAdd64 ((volatile __int64*) &value, (__int64) amountToAdd) + (__int64) amountToAdd); | |||
#elif JUCE_ANDROID | |||
#elif JUCE_ATOMICS_ANDROID | |||
for (;;) | |||
{ | |||
const Type oldValue (value); | |||
@@ -2366,7 +2370,7 @@ inline Type Atomic<Type>::operator++() throw() | |||
#elif JUCE_ATOMICS_WINDOWS | |||
return sizeof (Type) == 4 ? (Type) juce_InterlockedIncrement ((volatile long*) &value) | |||
: (Type) juce_InterlockedIncrement64 ((volatile __int64*) &value); | |||
#elif JUCE_ANDROID | |||
#elif JUCE_ATOMICS_ANDROID | |||
return (Type) __atomic_inc ((volatile int*) &value); | |||
#elif JUCE_ATOMICS_GCC | |||
return (Type) __sync_add_and_fetch (&value, 1); | |||
@@ -2382,7 +2386,7 @@ inline Type Atomic<Type>::operator--() throw() | |||
#elif JUCE_ATOMICS_WINDOWS | |||
return sizeof (Type) == 4 ? (Type) juce_InterlockedDecrement ((volatile long*) &value) | |||
: (Type) juce_InterlockedDecrement64 ((volatile __int64*) &value); | |||
#elif JUCE_ANDROID | |||
#elif JUCE_ATOMICS_ANDROID | |||
return (Type) __atomic_dec ((volatile int*) &value); | |||
#elif JUCE_ATOMICS_GCC | |||
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 | |||
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); | |||
#elif JUCE_ATOMICS_WINDOWS || JUCE_ANDROID | |||
#elif JUCE_ATOMICS_WINDOWS | |||
return compareAndSetValue (newValue, valueToCompare) == valueToCompare; | |||
#elif JUCE_ATOMICS_ANDROID | |||
return __atomic_cmpxchg (castTo32Bit (valueToCompare), castTo32Bit (newValue), (volatile int*) &value) == 0; | |||
#elif JUCE_ATOMICS_GCC | |||
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)); | |||
@@ -2406,8 +2412,8 @@ inline bool Atomic<Type>::compareAndSetBool (const Type newValue, const Type val | |||
template <typename Type> | |||
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)) | |||
return valueToCompare; | |||
@@ -2420,8 +2426,6 @@ inline Type Atomic<Type>::compareAndSetValue (const Type newValue, const Type va | |||
#elif JUCE_ATOMICS_WINDOWS | |||
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))); | |||
#elif JUCE_ANDROID | |||
return castFrom32Bit (__atomic_cmpxchg (castTo32Bit (valueToCompare), castTo32Bit (newValue), (volatile int*) &value)); | |||
#elif JUCE_ATOMICS_GCC | |||
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))); | |||
@@ -2638,11 +2642,11 @@ public: | |||
for (;;) | |||
{ | |||
const int n = *d++; | |||
const uint32 n = (uint32) (uint8) *d++; | |||
if ((n & 0x80) != 0) | |||
{ | |||
int bit = 0x40; | |||
uint32 bit = 0x40; | |||
while ((n & bit) != 0) | |||
{ | |||
@@ -211,6 +211,7 @@ void JUCEApplication::appWillTerminateByForce() | |||
} | |||
//============================================================================== | |||
#if ! JUCE_ANDROID | |||
int JUCEApplication::main (const String& commandLine) | |||
{ | |||
ScopedJuceInitialiser_GUI libraryInitialiser; | |||
@@ -263,5 +264,6 @@ int JUCEApplication::main (int argc, const char* argv[]) | |||
return JUCEApplication::main (cmd); | |||
#endif | |||
} | |||
#endif | |||
END_JUCE_NAMESPACE |
@@ -539,7 +539,7 @@ public: | |||
{ | |||
FSRef fn; | |||
if (FSPathMakeRef ((UInt8*) filename.toUTF8(), &fn, 0) == noErr) | |||
if (FSPathMakeRef ((UInt8*) filename.toUTF8().getAddress(), &fn, 0) == noErr) | |||
{ | |||
resFileId = FSOpenResFile (&fn, fsRdPerm); | |||
@@ -188,18 +188,28 @@ public: | |||
expect (ByteOrder::swap ((uint32) 0x11223344) == 0x44332211); | |||
expect (ByteOrder::swap ((uint64) literal64bit (0x1122334455667788)) == literal64bit (0x8877665544332211)); | |||
beginTest ("Atomic types"); | |||
beginTest ("Atomic int"); | |||
AtomicTester <int>::testInteger (*this); | |||
beginTest ("Atomic unsigned int"); | |||
AtomicTester <unsigned int>::testInteger (*this); | |||
beginTest ("Atomic int32"); | |||
AtomicTester <int32>::testInteger (*this); | |||
beginTest ("Atomic uint32"); | |||
AtomicTester <uint32>::testInteger (*this); | |||
beginTest ("Atomic long"); | |||
AtomicTester <long>::testInteger (*this); | |||
beginTest ("Atomic void*"); | |||
AtomicTester <void*>::testInteger (*this); | |||
beginTest ("Atomic int*"); | |||
AtomicTester <int*>::testInteger (*this); | |||
beginTest ("Atomic float"); | |||
AtomicTester <float>::testFloat (*this); | |||
#if ! JUCE_64BIT_ATOMICS_UNAVAILABLE // 64-bit intrinsics aren't available on some old platforms | |||
beginTest ("Atomic int64"); | |||
AtomicTester <int64>::testInteger (*this); | |||
beginTest ("Atomic uint64"); | |||
AtomicTester <uint64>::testInteger (*this); | |||
beginTest ("Atomic double"); | |||
AtomicTester <double>::testFloat (*this); | |||
#endif | |||
} | |||
@@ -214,10 +224,15 @@ public: | |||
{ | |||
Atomic<Type> a, b; | |||
a.set ((Type) 10); | |||
test.expect (a.value == (Type) 10); | |||
test.expect (a.get() == (Type) 10); | |||
a += (Type) 15; | |||
test.expect (a.get() == (Type) 25); | |||
a.memoryBarrier(); | |||
a -= (Type) 5; | |||
test.expect (a.get() == (Type) 20); | |||
++a; ++a; --a; | |||
test.expect (a.get() == (Type) 21); | |||
a.memoryBarrier(); | |||
testFloat (test); | |||
@@ -111,9 +111,7 @@ public: | |||
int randomInt = Random::getSystemRandom().nextInt(); | |||
int64 randomInt64 = Random::getSystemRandom().nextInt64(); | |||
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; | |||
mo.writeInt (randomInt); | |||
@@ -129,12 +127,34 @@ public: | |||
expect (mi.readInt() == randomInt); | |||
expect (mi.readIntBigEndian() == randomInt); | |||
expect (mi.readCompressedInt() == randomInt); | |||
expect (mi.readString() == randomString); | |||
expectEquals (mi.readString(), randomString); | |||
expect (mi.readInt64() == randomInt64); | |||
expect (mi.readInt64BigEndian() == randomInt64); | |||
expect (mi.readDouble() == 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; | |||
@@ -180,6 +180,11 @@ private: | |||
#define JUCE_64BIT_ATOMICS_UNAVAILABLE 1 | |||
#endif | |||
//============================================================================== | |||
#elif JUCE_ANDROID | |||
#define JUCE_ATOMICS_ANDROID 1 // Android atomic functions | |||
#define JUCE_64BIT_ATOMICS_UNAVAILABLE 1 | |||
//============================================================================== | |||
#elif JUCE_GCC | |||
#define JUCE_ATOMICS_GCC 1 // GCC with intrinsics | |||
@@ -244,8 +249,8 @@ inline Type Atomic<Type>::get() const throw() | |||
#elif JUCE_ATOMICS_WINDOWS | |||
return sizeof (Type) == 4 ? castFrom32Bit ((int32) juce_InterlockedExchangeAdd ((volatile long*) &value, (long) 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 | |||
return sizeof (Type) == 4 ? castFrom32Bit ((int32) __sync_add_and_fetch ((volatile int32*) &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> | |||
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)); | |||
#elif JUCE_ATOMICS_MAC || JUCE_ATOMICS_GCC | |||
Type currentVal = value; | |||
@@ -276,7 +281,7 @@ inline Type Atomic<Type>::operator+= (const Type amountToAdd) throw() | |||
#elif JUCE_ATOMICS_WINDOWS | |||
return sizeof (Type) == 4 ? (Type) (juce_InterlockedExchangeAdd ((volatile long*) &value, (long) amountToAdd) + (long) amountToAdd) | |||
: (Type) (juce_InterlockedExchangeAdd64 ((volatile __int64*) &value, (__int64) amountToAdd) + (__int64) amountToAdd); | |||
#elif JUCE_ANDROID | |||
#elif JUCE_ATOMICS_ANDROID | |||
for (;;) | |||
{ | |||
const Type oldValue (value); | |||
@@ -304,7 +309,7 @@ inline Type Atomic<Type>::operator++() throw() | |||
#elif JUCE_ATOMICS_WINDOWS | |||
return sizeof (Type) == 4 ? (Type) juce_InterlockedIncrement ((volatile long*) &value) | |||
: (Type) juce_InterlockedIncrement64 ((volatile __int64*) &value); | |||
#elif JUCE_ANDROID | |||
#elif JUCE_ATOMICS_ANDROID | |||
return (Type) __atomic_inc ((volatile int*) &value); | |||
#elif JUCE_ATOMICS_GCC | |||
return (Type) __sync_add_and_fetch (&value, 1); | |||
@@ -320,7 +325,7 @@ inline Type Atomic<Type>::operator--() throw() | |||
#elif JUCE_ATOMICS_WINDOWS | |||
return sizeof (Type) == 4 ? (Type) juce_InterlockedDecrement ((volatile long*) &value) | |||
: (Type) juce_InterlockedDecrement64 ((volatile __int64*) &value); | |||
#elif JUCE_ANDROID | |||
#elif JUCE_ATOMICS_ANDROID | |||
return (Type) __atomic_dec ((volatile int*) &value); | |||
#elif JUCE_ATOMICS_GCC | |||
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 | |||
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); | |||
#elif JUCE_ATOMICS_WINDOWS || JUCE_ANDROID | |||
#elif JUCE_ATOMICS_WINDOWS | |||
return compareAndSetValue (newValue, valueToCompare) == valueToCompare; | |||
#elif JUCE_ATOMICS_ANDROID | |||
return __atomic_cmpxchg (castTo32Bit (valueToCompare), castTo32Bit (newValue), (volatile int*) &value) == 0; | |||
#elif JUCE_ATOMICS_GCC | |||
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)); | |||
@@ -344,8 +351,8 @@ inline bool Atomic<Type>::compareAndSetBool (const Type newValue, const Type val | |||
template <typename Type> | |||
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)) | |||
return valueToCompare; | |||
@@ -358,8 +365,6 @@ inline Type Atomic<Type>::compareAndSetValue (const Type newValue, const Type va | |||
#elif JUCE_ATOMICS_WINDOWS | |||
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))); | |||
#elif JUCE_ANDROID | |||
return castFrom32Bit (__atomic_cmpxchg (castTo32Bit (valueToCompare), castTo32Bit (newValue), (volatile int*) &value)); | |||
#elif JUCE_ATOMICS_GCC | |||
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))); | |||
@@ -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) | |||
{ | |||
// TODO | |||
switch (type) | |||
{ | |||
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 userMusicDirectory: | |||
case userMoviesDirectory: | |||
case userApplicationDataDirectory: | |||
return File ("~"); | |||
return File (android.appDataDir); | |||
case userDesktopDirectory: | |||
return File ("~/Desktop"); | |||
case commonApplicationDataDirectory: | |||
return File ("/var"); | |||
return File (android.appDataDir); | |||
case globalApplicationsDirectory: | |||
return File ("/usr"); | |||
case tempDirectory: | |||
{ | |||
File tmp ("/var/tmp"); | |||
if (! tmp.isDirectory()) | |||
{ | |||
tmp = "/tmp"; | |||
if (! tmp.isDirectory()) | |||
tmp = File::getCurrentWorkingDirectory(); | |||
} | |||
return tmp; | |||
} | |||
return File ("~/.temp"); | |||
case invokedExecutableFile: | |||
if (juce_Argv0 != 0) | |||
return File (String::fromUTF8 (juce_Argv0)); | |||
// deliberate fall-through... | |||
case currentExecutableFile: | |||
case currentApplicationFile: | |||
return juce_getExecutableFile(); | |||
case hostApplicationPath: | |||
return juce_readlink ("/proc/self/exe", juce_getExecutableFile()); | |||
return juce_getExecutableFile(); | |||
default: | |||
jassertfalse; // unknown type? | |||
@@ -29,15 +29,13 @@ | |||
//============================================================================== | |||
// TODO | |||
class AndroidLowLevelGraphicsContext : public LowLevelGraphicsContext | |||
{ | |||
public: | |||
AndroidLowLevelGraphicsContext (const GlobalRef& canvas_) | |||
: canvas (canvas_), | |||
currentState (new SavedState()), | |||
currentState (new SavedState()) | |||
{ | |||
paintStack.add (new GlobalRef()); | |||
setFill (Colours::black); | |||
} | |||
@@ -55,7 +53,7 @@ public: | |||
void addTransform (const AffineTransform& transform) | |||
{ | |||
canvas.callVoidMethod (android.concat, createMatrix (canvas.getEnv(), transform)); | |||
canvas.callVoidMethod (android.concat, createMatrix (getEnv(), transform).get()); | |||
} | |||
float getScaleFactor() | |||
@@ -70,7 +68,7 @@ public: | |||
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) | |||
@@ -79,7 +77,7 @@ public: | |||
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) | |||
@@ -93,20 +91,21 @@ public: | |||
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); | |||
} | |||
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, | |||
(float) r.getX(), (float) r.getY(), (float) r.getRight(), (float) r.getBottom(), | |||
getCurrentPaint().get()); | |||
getCurrentPaint()); | |||
} | |||
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) | |||
@@ -145,17 +144,17 @@ public: | |||
{ | |||
canvas.callVoidMethod (android.drawLine, line.getStartX(), line.getStartY(), | |||
line.getEndX(), line.getEndY(), | |||
getCurrentPaint().get()); | |||
getCurrentPaint()); | |||
} | |||
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) | |||
{ | |||
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) | |||
@@ -223,21 +222,26 @@ public: | |||
fillType = newType; | |||
} | |||
jobject getPaint (JNIEnv* env) | |||
jobject getPaint() | |||
{ | |||
if (needsUpdate) | |||
{ | |||
JNIEnv* env = getEnv(); | |||
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()) | |||
{ | |||
paint.callVoidMethod (android.setShader, (jobject) 0); | |||
paint.callObjectMethod (android.setShader, (jobject) 0); | |||
paint.callVoidMethod (android.setColor, colourToInt (fillType.colour)); | |||
} | |||
else if (fillType.isGradient()) | |||
{ | |||
const ColourGradient& g = fillType.gradient; | |||
const ColourGradient& g = *fillType.gradient; | |||
const Point<float> p1 (g.point1); | |||
const Point<float> p2 (g.point2); | |||
@@ -251,7 +255,7 @@ public: | |||
for (int i = 0; i < numColours; ++i) | |||
{ | |||
colours[i] = g.getColour (i); | |||
colours[i] = colourToInt (g.getColour (i)); | |||
positions[i] = (float) g.getColourPosition(i); | |||
} | |||
@@ -259,7 +263,7 @@ public: | |||
env->SetFloatArrayRegion (positionsArray, 0, numColours, positions.getData()); | |||
} | |||
jobject tileMode = xxxx | |||
jobject tileMode = env->GetStaticObjectField (android.shaderTileModeClass, android.clampMode); | |||
jobject shader; | |||
if (fillType.gradient->isRadial) | |||
@@ -269,7 +273,7 @@ public: | |||
p1.getX(), p1.getY(), | |||
p1.getDistanceFrom (p2), | |||
coloursArray, positionsArray, | |||
tileMode)); | |||
tileMode); | |||
} | |||
else | |||
{ | |||
@@ -277,14 +281,19 @@ public: | |||
android.linearGradientConstructor, | |||
p1.getX(), p1.getY(), p2.getX(), p2.getY(), | |||
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 | |||
{x | |||
{ | |||
} | |||
} | |||
@@ -304,9 +313,12 @@ private: | |||
ScopedPointer <SavedState> currentState; | |||
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); | |||
@@ -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()) | |||
return createPath (env, path); | |||
@@ -338,7 +350,7 @@ private: | |||
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); | |||
@@ -352,25 +364,25 @@ private: | |||
env->CallVoidMethod (m, android.setValues, 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); | |||
const int numRects = list.getNumRectangles(); | |||
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() | |||
@@ -61,7 +61,7 @@ bool juce_dispatchNextMessageOnSystemQueue (const bool returnIfNoPendingMessages | |||
//============================================================================== | |||
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; | |||
} | |||
@@ -32,9 +32,11 @@ extern JUCE_NAMESPACE::JUCEApplication* juce_CreateApplication(); // (from START | |||
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; | |||
@@ -60,8 +62,8 @@ void PlatformUtilities::beep() | |||
//============================================================================== | |||
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 (regionClass, "android/graphics/Region") \ | |||
JAVACLASS (shaderClass, "android/graphics/Shader") \ | |||
JAVACLASS (shaderTileModeClass, "android/graphics/Shader$TileMode") \ | |||
JAVACLASS (linearGradientClass, "android/graphics/LinearGradient") \ | |||
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") \ | |||
METHOD (activityClass, createNewView, "createNewView", "()Lcom/juce/ComponentPeerView;") \ | |||
@@ -153,8 +154,10 @@ BEGIN_JUCE_NAMESPACE | |||
METHOD (paintClass, paintClassConstructor, "<init>", "()V") \ | |||
METHOD (paintClass, setColor, "setColor", "(I)V") \ | |||
METHOD (paintClass, setShader, "setShader", "(Landroid/graphics/Shader;)Landroid/graphics/Shader;") \ | |||
METHOD (paintClass, setAntiAlias, "setAntiAlias", "(Z)V") \ | |||
\ | |||
METHOD (shaderClass, setLocalMatrix, "setLocalMatrix", "(Landroid/graphics/Matrix;)V") \ | |||
STATICFIELD (shaderTileModeClass, clampMode, "CLAMP", "Landroid/graphics/Shader$TileMode;") \ | |||
\ | |||
METHOD (pathClass, pathClassConstructor, "<init>", "()V") \ | |||
METHOD (pathClass, moveTo, "moveTo", "(FF)V") \ | |||
@@ -180,24 +183,116 @@ BEGIN_JUCE_NAMESPACE | |||
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 | |||
{ | |||
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(); | |||
} | |||
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(); | |||
env = other.env; | |||
obj = retain (env, other.obj); | |||
obj = retain (other.obj); | |||
return *this; | |||
} | |||
//============================================================================== | |||
inline operator jobject() 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) \ | |||
@@ -235,7 +324,7 @@ public: | |||
{ \ | |||
va_list args; \ | |||
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); \ | |||
return result; \ | |||
} | |||
@@ -255,33 +344,101 @@ public: | |||
{ | |||
va_list args; | |||
va_start (args, methodID); | |||
env->CallVoidMethodV (obj, methodID, args); | |||
getEnv()->CallVoidMethodV (obj, methodID, args); | |||
va_end (args); | |||
} | |||
private: | |||
//============================================================================== | |||
JNIEnv* env; | |||
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 | |||
{ | |||
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_; | |||
screenHeight = screenHeight_; | |||
@@ -300,12 +457,17 @@ public: | |||
#define CREATE_JNI_FIELD(ownerClass, fieldID, stringName, signature) \ | |||
fieldID = env->GetFieldID (ownerClass, stringName, signature); \ | |||
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 | |||
} | |||
void shutdown() | |||
{ | |||
JNIEnv* env = getEnv(); | |||
if (env != 0) | |||
{ | |||
#define RELEASE_JNI_CLASS(className, path) env->DeleteGlobalRef (className); | |||
@@ -313,29 +475,12 @@ public: | |||
#undef RELEASE_JNI_CLASS | |||
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; | |||
String appFile, appDataDir; | |||
int screenWidth, screenHeight; | |||
//============================================================================== | |||
@@ -345,13 +490,12 @@ public: | |||
#define DECLARE_JNI_METHOD(ownerClass, methodID, stringName, params) jmethodID methodID; | |||
#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 | |||
}; | |||
static AndroidJavaCallbacks android; | |||
//============================================================================== | |||
#define JUCE_INCLUDED_FILE 1 | |||
@@ -77,8 +77,6 @@ int SystemStats::getCpuSpeedInMegaherz() | |||
int SystemStats::getMemorySizeInMegabytes() | |||
{ | |||
// TODO | |||
struct sysinfo sysi; | |||
if (sysinfo (&sysi) == 0) | |||
@@ -125,8 +123,7 @@ void SystemStats::initialiseStats() | |||
cpuFlags.hasSSE2 = flags.contains ("sse2"); | |||
cpuFlags.has3DNow = flags.contains ("3dnow"); | |||
// TODO | |||
cpuFlags.numCpus = AndroidStatsHelpers::getCpuInfo ("processor").getIntValue() + 1; | |||
cpuFlags.numCpus = jmax (1, sysconf (_SC_NPROCESSORS_ONLN)); | |||
} | |||
void PlatformUtilities::fpuReset() {} | |||
@@ -27,6 +27,7 @@ | |||
// compiled on its own). | |||
#if JUCE_INCLUDED_FILE | |||
static ModifierKeys currentModifiers; | |||
//============================================================================== | |||
class AndroidComponentPeer : public ComponentPeer | |||
@@ -34,9 +35,9 @@ class AndroidComponentPeer : public ComponentPeer | |||
public: | |||
//============================================================================== | |||
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() | |||
@@ -57,7 +58,7 @@ public: | |||
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) | |||
@@ -87,7 +88,7 @@ public: | |||
const Point<int> getScreenPosition() const | |||
{ | |||
JNIEnv* const env = view.getEnv(); | |||
JNIEnv* const env = getEnv(); | |||
jintArray pos = env->NewIntArray (2); | |||
view.callVoidMethod (android.getLocationOnScreen, pos); | |||
@@ -169,6 +170,26 @@ public: | |||
// 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 | |||
{ | |||
@@ -188,7 +209,8 @@ public: | |||
//============================================================================== | |||
void handlePaintCallback (JNIEnv* env, jobject canvas) | |||
{ | |||
AndroidLowLevelGraphicsContext g (GlobalRef (env, canvas)); | |||
GlobalRef canvasRef (canvas); | |||
AndroidLowLevelGraphicsContext g (canvasRef); | |||
handlePaint (g); | |||
} | |||
@@ -241,6 +263,12 @@ private: | |||
JUCE_VIEW_CALLBACK (void, handlePaint, (JNIEnv* env, jobject view, jobject 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*) | |||
@@ -294,8 +322,7 @@ void ModifierKeys::updateCurrentModifiers() throw() | |||
const ModifierKeys ModifierKeys::getCurrentModifiersRealtime() throw() | |||
{ | |||
// TODO | |||
return ModifierKeys(); | |||
return currentModifiers; | |||
} | |||
//============================================================================== | |||
@@ -486,8 +486,7 @@ void FileOutputStream::flushInternal() | |||
const File juce_getExecutableFile() | |||
{ | |||
#if JUCE_ANDROID | |||
// TODO | |||
return File::nonexistent; | |||
return File (android.appFile); | |||
#else | |||
Dl_info exeInfo; | |||
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) | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
#if JUCE_ANDROID | |||
const AndroidThreadScope androidEnv; | |||
#endif | |||
juce_threadEntryPoint (userData); | |||
return 0; | |||
} | |||
@@ -744,7 +748,7 @@ void Thread::killThread() | |||
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()); | |||
#elif JUCE_LINUX | |||
prctl (PR_SET_NAME, name.toUTF8().getAddress(), 0, 0, 0); | |||
@@ -95,6 +95,7 @@ BEGIN_JUCE_NAMESPACE | |||
#include "../common/juce_MidiDataConcatenator.h" | |||
#undef Point | |||
#if ! JUCE_ONLY_BUILD_CORE_LIBRARY | |||
namespace | |||
{ | |||
template <class RectType> | |||
@@ -183,6 +184,7 @@ private: | |||
static_cast <MessageQueue*> (info)->runLoopCallback(); | |||
} | |||
}; | |||
#endif | |||
//============================================================================== | |||
#define JUCE_INCLUDED_FILE 1 | |||
@@ -213,11 +213,11 @@ public: | |||
for (;;) | |||
{ | |||
const int n = *d++; | |||
const uint32 n = (uint32) (uint8) *d++; | |||
if ((n & 0x80) != 0) | |||
{ | |||
int bit = 0x40; | |||
uint32 bit = 0x40; | |||
while ((n & bit) != 0) | |||
{ | |||
@@ -2241,7 +2241,7 @@ public: | |||
{ | |||
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 | |||
buffer[i] = (juce_wchar) (1 + Random::getSystemRandom().nextInt (0xff)); | |||
@@ -161,8 +161,8 @@ void UnitTestRunner::endTest() | |||
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); | |||
logMessage (String::empty); | |||