@@ -58,6 +58,9 @@ | |||||
#if (defined (_WIN32) || defined (_WIN64)) | #if (defined (_WIN32) || defined (_WIN64)) | ||||
#define JUCE_WIN32 1 | #define JUCE_WIN32 1 | ||||
#define JUCE_WINDOWS 1 | #define JUCE_WINDOWS 1 | ||||
#elif defined (JUCE_ANDROID) | |||||
#undef JUCE_ANDROID | |||||
#define JUCE_ANDROID 1 | |||||
#elif defined (LINUX) || defined (__linux__) | #elif defined (LINUX) || defined (__linux__) | ||||
#define JUCE_LINUX 1 | #define JUCE_LINUX 1 | ||||
#elif defined (__APPLE_CPP__) || defined(__APPLE_CC__) | #elif defined (__APPLE_CPP__) || defined(__APPLE_CC__) | ||||
@@ -69,9 +72,6 @@ | |||||
#else | #else | ||||
#define JUCE_MAC 1 | #define JUCE_MAC 1 | ||||
#endif | #endif | ||||
#elif defined (JUCE_ANDROID) | |||||
#undef JUCE_ANDROID | |||||
#define JUCE_ANDROID 1 | |||||
#else | #else | ||||
#error "Unknown platform!" | #error "Unknown platform!" | ||||
#endif | #endif | ||||
@@ -25746,34 +25746,21 @@ void AudioDeviceManager::addMidiInputCallback (const String& name, | |||||
{ | { | ||||
removeMidiInputCallback (name, callbackToAdd); | removeMidiInputCallback (name, callbackToAdd); | ||||
if (name.isEmpty()) | |||||
if (name.isEmpty() || isMidiInputEnabled (name)) | |||||
{ | { | ||||
const ScopedLock sl (midiCallbackLock); | |||||
midiCallbacks.add (callbackToAdd); | midiCallbacks.add (callbackToAdd); | ||||
midiCallbackDevices.add (String::empty); | |||||
} | |||||
else | |||||
{ | |||||
for (int i = enabledMidiInputs.size(); --i >= 0;) | |||||
{ | |||||
if (enabledMidiInputs[i]->getName() == name) | |||||
{ | |||||
const ScopedLock sl (midiCallbackLock); | |||||
midiCallbacks.add (callbackToAdd); | |||||
midiCallbackDevices.add (enabledMidiInputs[i]->getName()); | |||||
break; | |||||
} | |||||
} | |||||
midiCallbackDevices.add (name); | |||||
} | } | ||||
} | } | ||||
void AudioDeviceManager::removeMidiInputCallback (const String& name, MidiInputCallback* /*callback*/) | |||||
void AudioDeviceManager::removeMidiInputCallback (const String& name, MidiInputCallback* callback) | |||||
{ | { | ||||
const ScopedLock sl (midiCallbackLock); | |||||
for (int i = midiCallbacks.size(); --i >= 0;) | for (int i = midiCallbacks.size(); --i >= 0;) | ||||
{ | { | ||||
if (midiCallbackDevices[i] == name) | |||||
if (midiCallbackDevices[i] == name && midiCallbacks.getUnchecked(i) == callback) | |||||
{ | { | ||||
const ScopedLock sl (midiCallbackLock); | |||||
midiCallbacks.remove (i); | midiCallbacks.remove (i); | ||||
midiCallbackDevices.remove (i); | midiCallbackDevices.remove (i); | ||||
} | } | ||||
@@ -26782,7 +26769,19 @@ AudioSampleBuffer::AudioSampleBuffer (float** dataToReferTo, | |||||
allocatedBytes (0) | allocatedBytes (0) | ||||
{ | { | ||||
jassert (numChannels_ > 0); | jassert (numChannels_ > 0); | ||||
allocateChannels (dataToReferTo); | |||||
allocateChannels (dataToReferTo, 0); | |||||
} | |||||
AudioSampleBuffer::AudioSampleBuffer (float** dataToReferTo, | |||||
const int numChannels_, | |||||
const int startSample, | |||||
const int numSamples) throw() | |||||
: numChannels (numChannels_), | |||||
size (numSamples), | |||||
allocatedBytes (0) | |||||
{ | |||||
jassert (numChannels_ > 0); | |||||
allocateChannels (dataToReferTo, startSample); | |||||
} | } | ||||
void AudioSampleBuffer::setDataToReferTo (float** dataToReferTo, | void AudioSampleBuffer::setDataToReferTo (float** dataToReferTo, | ||||
@@ -26797,10 +26796,10 @@ void AudioSampleBuffer::setDataToReferTo (float** dataToReferTo, | |||||
numChannels = newNumChannels; | numChannels = newNumChannels; | ||||
size = newNumSamples; | size = newNumSamples; | ||||
allocateChannels (dataToReferTo); | |||||
allocateChannels (dataToReferTo, 0); | |||||
} | } | ||||
void AudioSampleBuffer::allocateChannels (float** const dataToReferTo) | |||||
void AudioSampleBuffer::allocateChannels (float** const dataToReferTo, int offset) | |||||
{ | { | ||||
// (try to avoid doing a malloc here, as that'll blow up things like Pro-Tools) | // (try to avoid doing a malloc here, as that'll blow up things like Pro-Tools) | ||||
if (numChannels < numElementsInArray (preallocatedChannelSpace)) | if (numChannels < numElementsInArray (preallocatedChannelSpace)) | ||||
@@ -26818,7 +26817,7 @@ void AudioSampleBuffer::allocateChannels (float** const dataToReferTo) | |||||
// you have to pass in the same number of valid pointers as numChannels | // you have to pass in the same number of valid pointers as numChannels | ||||
jassert (dataToReferTo[i] != 0); | jassert (dataToReferTo[i] != 0); | ||||
channels[i] = dataToReferTo[i]; | |||||
channels[i] = dataToReferTo[i] + offset; | |||||
} | } | ||||
channels [numChannels] = 0; | channels [numChannels] = 0; | ||||
@@ -52200,7 +52199,7 @@ private: | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
while (! text.isEmpty() || text.isWhitespace()) | |||||
while (! (text.isEmpty() || text.isWhitespace())) | |||||
{ | { | ||||
++text; | ++text; | ||||
++numChars; | ++numChars; | ||||
@@ -80262,23 +80261,19 @@ namespace ColourHelpers | |||||
else | else | ||||
{ | { | ||||
s = jmin (1.0f, s); | s = jmin (1.0f, s); | ||||
h = jlimit (0.0f, 1.0f, h); | |||||
h = (h - std::floor (h)) * 6.0f + 0.00001f; // need a small adjustment to compensate for rounding errors | h = (h - std::floor (h)) * 6.0f + 0.00001f; // need a small adjustment to compensate for rounding errors | ||||
const float f = h - std::floor (h); | const float f = h - std::floor (h); | ||||
const uint8 x = (uint8) roundToInt (v * (1.0f - s)); | const uint8 x = (uint8) roundToInt (v * (1.0f - s)); | ||||
const float y = v * (1.0f - s * f); | |||||
const float z = v * (1.0f - (s * (1.0f - f))); | |||||
if (h < 1.0f) | if (h < 1.0f) | ||||
{ | { | ||||
r = intV; | r = intV; | ||||
g = (uint8) roundToInt (z); | |||||
g = (uint8) roundToInt (v * (1.0f - (s * (1.0f - f)))); | |||||
b = x; | b = x; | ||||
} | } | ||||
else if (h < 2.0f) | else if (h < 2.0f) | ||||
{ | { | ||||
r = (uint8) roundToInt (y); | |||||
r = (uint8) roundToInt (v * (1.0f - s * f)); | |||||
g = intV; | g = intV; | ||||
b = x; | b = x; | ||||
} | } | ||||
@@ -80286,31 +80281,25 @@ namespace ColourHelpers | |||||
{ | { | ||||
r = x; | r = x; | ||||
g = intV; | g = intV; | ||||
b = (uint8) roundToInt (z); | |||||
b = (uint8) roundToInt (v * (1.0f - (s * (1.0f - f)))); | |||||
} | } | ||||
else if (h < 4.0f) | else if (h < 4.0f) | ||||
{ | { | ||||
r = x; | r = x; | ||||
g = (uint8) roundToInt (y); | |||||
g = (uint8) roundToInt (v * (1.0f - s * f)); | |||||
b = intV; | b = intV; | ||||
} | } | ||||
else if (h < 5.0f) | else if (h < 5.0f) | ||||
{ | { | ||||
r = (uint8) roundToInt (z); | |||||
r = (uint8) roundToInt (v * (1.0f - (s * (1.0f - f)))); | |||||
g = x; | g = x; | ||||
b = intV; | b = intV; | ||||
} | } | ||||
else if (h < 6.0f) | |||||
else | |||||
{ | { | ||||
r = intV; | r = intV; | ||||
g = x; | g = x; | ||||
b = (uint8) roundToInt (y); | |||||
} | |||||
else | |||||
{ | |||||
r = 0; | |||||
g = 0; | |||||
b = 0; | |||||
b = (uint8) roundToInt (v * (1.0f - s * f)); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -80398,7 +80387,7 @@ Colour::Colour (const float hue, | |||||
const float brightness, | const float brightness, | ||||
const float alpha) throw() | const float alpha) throw() | ||||
{ | { | ||||
uint8 r = getRed(), g = getGreen(), b = getBlue(); | |||||
uint8 r, g, b; | |||||
ColourHelpers::convertHSBtoRGB (hue, saturation, brightness, r, g, b); | ColourHelpers::convertHSBtoRGB (hue, saturation, brightness, r, g, b); | ||||
argb.setARGB (ColourHelpers::floatAlphaToInt (alpha), r, g, b); | argb.setARGB (ColourHelpers::floatAlphaToInt (alpha), r, g, b); | ||||
@@ -80417,7 +80406,7 @@ Colour::Colour (const float hue, | |||||
const float brightness, | const float brightness, | ||||
const uint8 alpha) throw() | const uint8 alpha) throw() | ||||
{ | { | ||||
uint8 r = getRed(), g = getGreen(), b = getBlue(); | |||||
uint8 r, g, b; | |||||
ColourHelpers::convertHSBtoRGB (hue, saturation, brightness, r, g, b); | ColourHelpers::convertHSBtoRGB (hue, saturation, brightness, r, g, b); | ||||
argb.setARGB (alpha, r, g, b); | argb.setARGB (alpha, r, g, b); | ||||
@@ -80604,10 +80593,7 @@ const Colour Colour::withRotatedHue (const float amountToRotate) const throw() | |||||
float h, s, b; | float h, s, b; | ||||
getHSB (h, s, b); | getHSB (h, s, b); | ||||
h += amountToRotate; | |||||
h -= std::floor (h); | |||||
return Colour (h, s, b, getAlpha()); | |||||
return Colour (h + amountToRotate, s, b, getAlpha()); | |||||
} | } | ||||
float Colour::getSaturation() const throw() | float Colour::getSaturation() const throw() | ||||
@@ -278509,18 +278495,126 @@ END_JUCE_NAMESPACE | |||||
BEGIN_JUCE_NAMESPACE | BEGIN_JUCE_NAMESPACE | ||||
#define JUCE_INCLUDED_FILE 1 | |||||
#define JUCE_JNI_CALLBACK(className, methodName, returnType, params) \ | |||||
extern "C" __attribute__ ((visibility("default"))) returnType Java_com_juce_ ## className ## _ ## methodName params | |||||
#define JUCE_JNI_CLASSES(JAVACLASS) \ | |||||
JAVACLASS (activityClass, "com/juce/JuceAppActivity") \ | |||||
JAVACLASS (componentPeerViewClass, "com/juce/ComponentPeerView") \ | |||||
JAVACLASS (fileClass, "java/io/File") \ | |||||
JAVACLASS (contextClass, "android/content/Context") \ | |||||
JAVACLASS (canvasClass, "android/graphics/Canvas") \ | |||||
JAVACLASS (paintClass, "android/graphics/Paint") \ | |||||
#define JUCE_JNI_METHODS(METHOD, STATICMETHOD) \ | |||||
\ | |||||
STATICMETHOD (activityClass, printToConsole, "printToConsole", "(Ljava/lang/String;)V") \ | |||||
METHOD (activityClass, createNewView, "createNewView", "()Lcom/juce/ComponentPeerView;") \ | |||||
METHOD (activityClass, deleteView, "deleteView", "(Lcom/juce/ComponentPeerView;)V") \ | |||||
\ | |||||
METHOD (fileClass, fileExists, "exists", "()Z") \ | |||||
\ | |||||
METHOD (componentPeerViewClass, layout, "layout", "(IIII)V") \ | |||||
\ | |||||
METHOD (canvasClass, drawRect, "drawRect", "(FFFFLandroid/graphics/Paint;)V") \ | |||||
\ | |||||
METHOD (paintClass, paintClassConstructor, "<init>", "()V") \ | |||||
METHOD (paintClass, setColor, "setColor", "(I)V") \ | |||||
class GlobalRef | |||||
{ | |||||
public: | |||||
GlobalRef() | |||||
: env (0), obj (0) | |||||
{ | |||||
} | |||||
// Now include the actual code files.. | |||||
GlobalRef (JNIEnv* const env_, jobject obj_) | |||||
: env (env_), | |||||
obj (retain (env_, obj_)) | |||||
{ | |||||
} | |||||
/*** Start of inlined file: juce_android_SystemStats.cpp ***/ | |||||
// (This file gets included by juce_android_NativeCode.cpp, rather than being | |||||
// compiled on its own). | |||||
#if JUCE_INCLUDED_FILE | |||||
GlobalRef (const GlobalRef& other) | |||||
: env (other.env), | |||||
obj (retain (other.env, other.obj)) | |||||
{ | |||||
} | |||||
END_JUCE_NAMESPACE | |||||
extern JUCE_NAMESPACE::JUCEApplication* juce_CreateApplication(); // (from START_JUCE_APPLICATION) | |||||
BEGIN_JUCE_NAMESPACE | |||||
~GlobalRef() | |||||
{ | |||||
release(); | |||||
} | |||||
GlobalRef& operator= (const GlobalRef& other) | |||||
{ | |||||
release(); | |||||
env = other.env; | |||||
obj = retain (env, other.obj); | |||||
return *this; | |||||
} | |||||
GlobalRef& operator= (jobject newObj) | |||||
{ | |||||
jassert (env != 0 || newObj == 0); | |||||
if (newObj != obj && env != 0) | |||||
{ | |||||
release(); | |||||
obj = retain (env, newObj); | |||||
} | |||||
} | |||||
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) \ | |||||
returnType call##typeName##Method (jmethodID methodID, ... ) \ | |||||
{ \ | |||||
returnType result; \ | |||||
va_list args; \ | |||||
va_start (args, methodID); \ | |||||
result = env->Call##typeName##MethodV (obj, methodID, args); \ | |||||
va_end (args); \ | |||||
return result; \ | |||||
} | |||||
DECLARE_CALL_TYPE_METHOD (jobject, Object) | |||||
DECLARE_CALL_TYPE_METHOD (jboolean, Boolean) | |||||
DECLARE_CALL_TYPE_METHOD (jbyte, Byte) | |||||
DECLARE_CALL_TYPE_METHOD (jchar, Char) | |||||
DECLARE_CALL_TYPE_METHOD (jshort, Short) | |||||
DECLARE_CALL_TYPE_METHOD (jint, Int) | |||||
DECLARE_CALL_TYPE_METHOD (jlong, Long) | |||||
DECLARE_CALL_TYPE_METHOD (jfloat, Float) | |||||
DECLARE_CALL_TYPE_METHOD (jdouble, Double) | |||||
#undef DECLARE_CALL_TYPE_METHOD | |||||
void callVoidMethod (jmethodID methodID, ... ) | |||||
{ | |||||
va_list args; | |||||
va_start (args, methodID); | |||||
env->CallVoidMethodV (obj, methodID, args); | |||||
va_end (args); | |||||
} | |||||
private: | |||||
JNIEnv* env; | |||||
jobject obj; | |||||
void release() | |||||
{ | |||||
if (env != 0) | |||||
env->DeleteGlobalRef (obj); | |||||
} | |||||
static jobject retain (JNIEnv* const env, jobject obj_) | |||||
{ | |||||
return env == 0 ? 0 : env->NewGlobalRef (obj_); | |||||
} | |||||
}; | |||||
class AndroidJavaCallbacks | class AndroidJavaCallbacks | ||||
{ | { | ||||
@@ -278529,37 +278623,85 @@ public: | |||||
{ | { | ||||
} | } | ||||
void initialise (JNIEnv* env_, jobject activity) | |||||
void initialise (JNIEnv* env_, jobject activity_) | |||||
{ | { | ||||
env = env_; | env = env_; | ||||
activityClass = (jclass) env->NewGlobalRef (env->GetObjectClass (activity)); | |||||
activity = GlobalRef (env, activity_); | |||||
printToConsole = env->GetStaticMethodID (activityClass, "printToConsole", "(Ljava/lang/String;)V"); | |||||
jassert (printToConsole != 0); | |||||
#define CREATE_JNI_CLASS(className, path) \ | |||||
className = (jclass) env->NewGlobalRef (env->FindClass (path)); \ | |||||
jassert (className != 0); | |||||
JUCE_JNI_CLASSES (CREATE_JNI_CLASS); | |||||
#undef CREATE_JNI_CLASS | |||||
#define CREATE_JNI_METHOD(ownerClass, methodID, stringName, params) \ | |||||
methodID = env->GetMethodID (ownerClass, stringName, params); \ | |||||
jassert (methodID != 0); | |||||
#define CREATE_JNI_STATICMETHOD(ownerClass, methodID, stringName, params) \ | |||||
methodID = env->GetStaticMethodID (ownerClass, stringName, params); \ | |||||
jassert (methodID != 0); | |||||
JUCE_JNI_METHODS (CREATE_JNI_METHOD, CREATE_JNI_STATICMETHOD); | |||||
#undef CREATE_JNI_METHOD | |||||
} | } | ||||
void shutdown() | void shutdown() | ||||
{ | { | ||||
if (env != 0) | if (env != 0) | ||||
{ | { | ||||
env->DeleteGlobalRef (activityClass); | |||||
#define RELEASE_JNI_CLASS(className, path) env->DeleteGlobalRef (className); | |||||
JUCE_JNI_CLASSES (RELEASE_JNI_CLASS); | |||||
#undef RELEASE_JNI_CLASS | |||||
activity = 0; | |||||
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; | JNIEnv* env; | ||||
GlobalRef activity; | |||||
#define DECLARE_JNI_CLASS(className, path) jclass className; | |||||
JUCE_JNI_CLASSES (DECLARE_JNI_CLASS); | |||||
#undef DECLARE_JNI_CLASS | |||||
jclass activityClass; | |||||
jmethodID printToConsole; | |||||
#define DECLARE_JNI_METHOD(ownerClass, methodID, stringName, params) jmethodID methodID; | |||||
JUCE_JNI_METHODS (DECLARE_JNI_METHOD, DECLARE_JNI_METHOD); | |||||
#undef DECLARE_JNI_METHOD | |||||
}; | }; | ||||
static AndroidJavaCallbacks androidEnv; | |||||
static AndroidJavaCallbacks android; | |||||
#define JUCE_JNI_CALLBACK(className, methodName, returnType, params) \ | |||||
extern "C" __attribute__ ((visibility("default"))) returnType Java_com_juce_launch_ ## className ## _ ## methodName params | |||||
#define JUCE_INCLUDED_FILE 1 | |||||
// Now include the actual code files.. | |||||
/*** Start of inlined file: juce_android_Misc.cpp ***/ | |||||
// (This file gets included by juce_android_NativeCode.cpp, rather than being | |||||
// compiled on its own). | |||||
#if JUCE_INCLUDED_FILE | |||||
END_JUCE_NAMESPACE | |||||
extern JUCE_NAMESPACE::JUCEApplication* juce_CreateApplication(); // (from START_JUCE_APPLICATION) | |||||
BEGIN_JUCE_NAMESPACE | |||||
JUCE_JNI_CALLBACK (JuceAppActivity, launchApp, void, (JNIEnv* env, jobject activity)) | JUCE_JNI_CALLBACK (JuceAppActivity, launchApp, void, (JNIEnv* env, jobject activity)) | ||||
{ | { | ||||
androidEnv.initialise (env, activity); | |||||
android.initialise (env, activity); | |||||
JUCEApplication::createInstance = &juce_CreateApplication; | JUCEApplication::createInstance = &juce_CreateApplication; | ||||
@@ -278573,7 +278715,7 @@ JUCE_JNI_CALLBACK (JuceAppActivity, quitApp, void, (JNIEnv* env, jobject activit | |||||
{ | { | ||||
JUCEApplication::appWillTerminateByForce(); | JUCEApplication::appWillTerminateByForce(); | ||||
androidEnv.shutdown(); | |||||
android.shutdown(); | |||||
} | } | ||||
void PlatformUtilities::beep() | void PlatformUtilities::beep() | ||||
@@ -278583,10 +278725,34 @@ void PlatformUtilities::beep() | |||||
void Logger::outputDebugString (const String& text) | void Logger::outputDebugString (const String& text) | ||||
{ | { | ||||
androidEnv.env->CallStaticVoidMethod (androidEnv.activityClass, androidEnv.printToConsole, | |||||
androidEnv.env->NewStringUTF (text.toUTF8())); | |||||
android.env->CallStaticVoidMethod (android.activityClass, android.printToConsole, | |||||
android.javaString (text)); | |||||
} | } | ||||
void SystemClipboard::copyTextToClipboard (const String& text) | |||||
{ | |||||
// TODO | |||||
} | |||||
const String SystemClipboard::getTextFromClipboard() | |||||
{ | |||||
String result; | |||||
// TODO | |||||
return result; | |||||
} | |||||
#endif | |||||
/*** End of inlined file: juce_android_Misc.cpp ***/ | |||||
/*** Start of inlined file: juce_android_SystemStats.cpp ***/ | |||||
// (This file gets included by juce_android_NativeCode.cpp, rather than being | |||||
// compiled on its own). | |||||
#if JUCE_INCLUDED_FILE | |||||
SystemStats::OperatingSystemType SystemStats::getOperatingSystemType() | SystemStats::OperatingSystemType SystemStats::getOperatingSystemType() | ||||
{ | { | ||||
return Android; | return Android; | ||||
@@ -278726,7 +278892,6 @@ bool Time::setSystemTimeToThisTime() const | |||||
#endif | #endif | ||||
/*** End of inlined file: juce_android_SystemStats.cpp ***/ | /*** End of inlined file: juce_android_SystemStats.cpp ***/ | ||||
// (must be first) | |||||
/*** Start of inlined file: juce_posix_SharedCode.h ***/ | /*** Start of inlined file: juce_posix_SharedCode.h ***/ | ||||
/* | /* | ||||
@@ -279504,7 +279669,6 @@ void Thread::setCurrentThreadAffinityMask (const uint32 affinityMask) | |||||
/*** End of inlined file: juce_posix_SharedCode.h ***/ | /*** End of inlined file: juce_posix_SharedCode.h ***/ | ||||
/*** Start of inlined file: juce_android_Files.cpp ***/ | /*** Start of inlined file: juce_android_Files.cpp ***/ | ||||
// (This file gets included by juce_android_NativeCode.cpp, rather than being | // (This file gets included by juce_android_NativeCode.cpp, rather than being | ||||
// compiled on its own). | // compiled on its own). | ||||
@@ -280263,7 +280427,8 @@ const Typeface::Ptr Typeface::createSystemTypefaceFor (const Font& font) | |||||
class AndroidLowLevelGraphicsContext : public LowLevelGraphicsContext | class AndroidLowLevelGraphicsContext : public LowLevelGraphicsContext | ||||
{ | { | ||||
public: | public: | ||||
AndroidLowLevelGraphicsContext() | |||||
AndroidLowLevelGraphicsContext (const GlobalRef& canvas_) | |||||
: canvas (canvas_) | |||||
{ | { | ||||
} | } | ||||
@@ -280288,12 +280453,12 @@ public: | |||||
bool clipToRectangle (const Rectangle<int>& r) | bool clipToRectangle (const Rectangle<int>& r) | ||||
{ | { | ||||
return false; | |||||
return true; | |||||
} | } | ||||
bool clipToRectangleList (const RectangleList& clipRegion) | bool clipToRectangleList (const RectangleList& clipRegion) | ||||
{ | { | ||||
return false; | |||||
return true; | |||||
} | } | ||||
void excludeClipRectangle (const Rectangle<int>& r) | void excludeClipRectangle (const Rectangle<int>& r) | ||||
@@ -280315,7 +280480,7 @@ public: | |||||
const Rectangle<int> getClipBounds() const | const Rectangle<int> getClipBounds() const | ||||
{ | { | ||||
return Rectangle<int>(); | |||||
return Rectangle<int> (0, 0, 1000, 1000); | |||||
} | } | ||||
bool isClipEmpty() const | bool isClipEmpty() const | ||||
@@ -280341,6 +280506,8 @@ public: | |||||
void setFill (const FillType& fillType) | void setFill (const FillType& fillType) | ||||
{ | { | ||||
currentPaint = android.env->NewObject (android.paintClass, android.paintClassConstructor); | |||||
currentPaint.callVoidMethod (android.setColor, fillType.colour.getARGB()); | |||||
} | } | ||||
void setOpacity (float newOpacity) | void setOpacity (float newOpacity) | ||||
@@ -280353,6 +280520,9 @@ public: | |||||
void fillRect (const Rectangle<int>& r, bool replaceExistingContents) | void fillRect (const Rectangle<int>& r, bool replaceExistingContents) | ||||
{ | { | ||||
canvas.callVoidMethod (android.drawRect, | |||||
(float) r.getX(), (float) r.getY(), (float) r.getRight(), (float) r.getBottom(), | |||||
currentPaint.get()); | |||||
} | } | ||||
void fillPath (const Path& path, const AffineTransform& transform) | void fillPath (const Path& path, const AffineTransform& transform) | ||||
@@ -280389,6 +280559,8 @@ public: | |||||
} | } | ||||
private: | private: | ||||
GlobalRef canvas, currentPaint; | |||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AndroidLowLevelGraphicsContext); | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AndroidLowLevelGraphicsContext); | ||||
}; | }; | ||||
@@ -280408,11 +280580,13 @@ public: | |||||
AndroidComponentPeer (Component* const component, const int windowStyleFlags) | AndroidComponentPeer (Component* const component, const int windowStyleFlags) | ||||
: ComponentPeer (component, windowStyleFlags) | : ComponentPeer (component, windowStyleFlags) | ||||
{ | { | ||||
// TODO | |||||
view = GlobalRef (android.env, android.activity.callObjectMethod (android.createNewView)); | |||||
} | } | ||||
~AndroidComponentPeer() | ~AndroidComponentPeer() | ||||
{ | { | ||||
android.activity.callVoidMethod (android.deleteView, view.get()); | |||||
view = 0; | |||||
} | } | ||||
void* getNativeHandle() const | void* getNativeHandle() const | ||||
@@ -280439,7 +280613,8 @@ public: | |||||
void setBounds (int x, int y, int w, int h, bool isNowFullScreen) | void setBounds (int x, int y, int w, int h, bool isNowFullScreen) | ||||
{ | { | ||||
// TODO | |||||
DBG ("Window size: " << x << " " << y << " " << w << " " << h); | |||||
view.callVoidMethod (android.layout, x, y, x + w, y + h); | |||||
} | } | ||||
const Rectangle<int> getBounds() const | const Rectangle<int> getBounds() const | ||||
@@ -280537,6 +280712,12 @@ public: | |||||
// TODO | // TODO | ||||
} | } | ||||
void handlePaintCallback (JNIEnv* env, jobject canvas) | |||||
{ | |||||
AndroidLowLevelGraphicsContext g (GlobalRef (env, canvas)); | |||||
handlePaint (g); | |||||
} | |||||
void repaint (const Rectangle<int>& area) | void repaint (const Rectangle<int>& area) | ||||
{ | { | ||||
// TODO | // TODO | ||||
@@ -280552,11 +280733,38 @@ public: | |||||
// TODO | // TODO | ||||
} | } | ||||
static AndroidComponentPeer* findPeerForJavaView (jobject viewToFind) | |||||
{ | |||||
for (int i = getNumPeers(); --i >= 0;) | |||||
{ | |||||
AndroidComponentPeer* const ap = static_cast <AndroidComponentPeer*> (getPeer(i)); | |||||
jassert (dynamic_cast <AndroidComponentPeer*> (getPeer(i)) != 0); | |||||
if (ap->view == viewToFind) | |||||
return ap; | |||||
} | |||||
return 0; | |||||
} | |||||
private: | private: | ||||
GlobalRef view; | |||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AndroidComponentPeer); | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AndroidComponentPeer); | ||||
}; | }; | ||||
#define JUCE_VIEW_CALLBACK(returnType, javaMethodName, params, juceMethodInvocation) \ | |||||
JUCE_JNI_CALLBACK (ComponentPeerView, javaMethodName, returnType, params) \ | |||||
{ \ | |||||
AndroidComponentPeer* const peer = AndroidComponentPeer::findPeerForJavaView (view); \ | |||||
if (peer != 0) \ | |||||
peer->juceMethodInvocation; \ | |||||
} | |||||
JUCE_VIEW_CALLBACK (void, handlePaint, (JNIEnv* env, jobject view, jobject canvas), | |||||
handlePaintCallback (env, canvas)) | |||||
ComponentPeer* Component::createNewPeer (int styleFlags, void*) | ComponentPeer* Component::createNewPeer (int styleFlags, void*) | ||||
{ | { | ||||
return new AndroidComponentPeer (this, styleFlags); | return new AndroidComponentPeer (this, styleFlags); | ||||
@@ -280641,11 +280849,17 @@ void juce_setKioskComponent (Component* kioskModeComponent, bool enableOrDisable | |||||
{ | { | ||||
} | } | ||||
static int screenWidth = 0, screenHeight = 0; | |||||
void juce_updateMultiMonitorInfo (Array <Rectangle<int> >& monitorCoords, const bool clipToWorkArea) | void juce_updateMultiMonitorInfo (Array <Rectangle<int> >& monitorCoords, const bool clipToWorkArea) | ||||
{ | { | ||||
// TODO | |||||
monitorCoords.add (Rectangle<int> (0, 0, screenWidth, screenHeight)); | |||||
} | |||||
monitorCoords.add (Rectangle<int> (0, 0, 640, 480)); | |||||
JUCE_JNI_CALLBACK (JuceAppActivity, setScreenSize, void, (JNIEnv* env, jobject activity, int w, int h)) | |||||
{ | |||||
screenWidth = w; | |||||
screenHeight = h; | |||||
} | } | ||||
const Image juce_createIconForFile (const File& file) | const Image juce_createIconForFile (const File& file) | ||||
@@ -280768,29 +280982,6 @@ void FileChooser::showPlatformDialog (Array<File>& results, | |||||
/*** End of inlined file: juce_android_FileChooser.cpp ***/ | /*** End of inlined file: juce_android_FileChooser.cpp ***/ | ||||
/*** Start of inlined file: juce_android_Misc.cpp ***/ | |||||
// (This file gets included by juce_android_NativeCode.cpp, rather than being | |||||
// compiled on its own). | |||||
#if JUCE_INCLUDED_FILE | |||||
void SystemClipboard::copyTextToClipboard (const String& text) | |||||
{ | |||||
// TODO | |||||
} | |||||
const String SystemClipboard::getTextFromClipboard() | |||||
{ | |||||
String result; | |||||
// TODO | |||||
return result; | |||||
} | |||||
#endif | |||||
/*** End of inlined file: juce_android_Misc.cpp ***/ | |||||
/*** Start of inlined file: juce_android_WebBrowserComponent.cpp ***/ | /*** Start of inlined file: juce_android_WebBrowserComponent.cpp ***/ | ||||
// (This file gets included by juce_android_NativeCode.cpp, rather than being | // (This file gets included by juce_android_NativeCode.cpp, rather than being | ||||
// compiled on its own). | // compiled on its own). | ||||
@@ -73,7 +73,7 @@ namespace JuceDummyNamespace {} | |||||
*/ | */ | ||||
#define JUCE_MAJOR_VERSION 1 | #define JUCE_MAJOR_VERSION 1 | ||||
#define JUCE_MINOR_VERSION 53 | #define JUCE_MINOR_VERSION 53 | ||||
#define JUCE_BUILDNUMBER 24 | |||||
#define JUCE_BUILDNUMBER 25 | |||||
/** Current Juce version number. | /** Current Juce version number. | ||||
@@ -105,6 +105,9 @@ namespace JuceDummyNamespace {} | |||||
#if (defined (_WIN32) || defined (_WIN64)) | #if (defined (_WIN32) || defined (_WIN64)) | ||||
#define JUCE_WIN32 1 | #define JUCE_WIN32 1 | ||||
#define JUCE_WINDOWS 1 | #define JUCE_WINDOWS 1 | ||||
#elif defined (JUCE_ANDROID) | |||||
#undef JUCE_ANDROID | |||||
#define JUCE_ANDROID 1 | |||||
#elif defined (LINUX) || defined (__linux__) | #elif defined (LINUX) || defined (__linux__) | ||||
#define JUCE_LINUX 1 | #define JUCE_LINUX 1 | ||||
#elif defined (__APPLE_CPP__) || defined(__APPLE_CC__) | #elif defined (__APPLE_CPP__) || defined(__APPLE_CC__) | ||||
@@ -116,9 +119,6 @@ namespace JuceDummyNamespace {} | |||||
#else | #else | ||||
#define JUCE_MAC 1 | #define JUCE_MAC 1 | ||||
#endif | #endif | ||||
#elif defined (JUCE_ANDROID) | |||||
#undef JUCE_ANDROID | |||||
#define JUCE_ANDROID 1 | |||||
#else | #else | ||||
#error "Unknown platform!" | #error "Unknown platform!" | ||||
#endif | #endif | ||||
@@ -34408,6 +34408,27 @@ public: | |||||
int numChannels, | int numChannels, | ||||
int numSamples) throw(); | int numSamples) throw(); | ||||
/** Creates a buffer using a pre-allocated block of memory. | |||||
Note that if the buffer is resized or its number of channels is changed, it | |||||
will re-allocate memory internally and copy the existing data to this new area, | |||||
so it will then stop directly addressing this memory. | |||||
@param dataToReferTo a pre-allocated array containing pointers to the data | |||||
for each channel that should be used by this buffer. The | |||||
buffer will only refer to this memory, it won't try to delete | |||||
it when the buffer is deleted or resized. | |||||
@param numChannels the number of channels to use - this must correspond to the | |||||
number of elements in the array passed in | |||||
@param startSample the offset within the arrays at which the data begins | |||||
@param numSamples the number of samples to use - this must correspond to the | |||||
size of the arrays passed in | |||||
*/ | |||||
AudioSampleBuffer (float** dataToReferTo, | |||||
int numChannels, | |||||
int startSample, | |||||
int numSamples) throw(); | |||||
/** Copies another buffer. | /** Copies another buffer. | ||||
This buffer will make its own copy of the other's data, unless the buffer was created | This buffer will make its own copy of the other's data, unless the buffer was created | ||||
@@ -34761,7 +34782,7 @@ private: | |||||
float* preallocatedChannelSpace [32]; | float* preallocatedChannelSpace [32]; | ||||
void allocateData(); | void allocateData(); | ||||
void allocateChannels (float** dataToReferTo); | |||||
void allocateChannels (float** dataToReferTo, int offset); | |||||
JUCE_LEAK_DETECTOR (AudioSampleBuffer); | JUCE_LEAK_DETECTOR (AudioSampleBuffer); | ||||
}; | }; | ||||
@@ -795,34 +795,21 @@ void AudioDeviceManager::addMidiInputCallback (const String& name, | |||||
{ | { | ||||
removeMidiInputCallback (name, callbackToAdd); | removeMidiInputCallback (name, callbackToAdd); | ||||
if (name.isEmpty()) | |||||
if (name.isEmpty() || isMidiInputEnabled (name)) | |||||
{ | { | ||||
const ScopedLock sl (midiCallbackLock); | |||||
midiCallbacks.add (callbackToAdd); | midiCallbacks.add (callbackToAdd); | ||||
midiCallbackDevices.add (String::empty); | |||||
} | |||||
else | |||||
{ | |||||
for (int i = enabledMidiInputs.size(); --i >= 0;) | |||||
{ | |||||
if (enabledMidiInputs[i]->getName() == name) | |||||
{ | |||||
const ScopedLock sl (midiCallbackLock); | |||||
midiCallbacks.add (callbackToAdd); | |||||
midiCallbackDevices.add (enabledMidiInputs[i]->getName()); | |||||
break; | |||||
} | |||||
} | |||||
midiCallbackDevices.add (name); | |||||
} | } | ||||
} | } | ||||
void AudioDeviceManager::removeMidiInputCallback (const String& name, MidiInputCallback* /*callback*/) | |||||
void AudioDeviceManager::removeMidiInputCallback (const String& name, MidiInputCallback* callback) | |||||
{ | { | ||||
const ScopedLock sl (midiCallbackLock); | |||||
for (int i = midiCallbacks.size(); --i >= 0;) | for (int i = midiCallbacks.size(); --i >= 0;) | ||||
{ | { | ||||
if (midiCallbackDevices[i] == name) | |||||
if (midiCallbackDevices[i] == name && midiCallbacks.getUnchecked(i) == callback) | |||||
{ | { | ||||
const ScopedLock sl (midiCallbackLock); | |||||
midiCallbacks.remove (i); | midiCallbacks.remove (i); | ||||
midiCallbackDevices.remove (i); | midiCallbackDevices.remove (i); | ||||
} | } | ||||
@@ -80,7 +80,19 @@ AudioSampleBuffer::AudioSampleBuffer (float** dataToReferTo, | |||||
allocatedBytes (0) | allocatedBytes (0) | ||||
{ | { | ||||
jassert (numChannels_ > 0); | jassert (numChannels_ > 0); | ||||
allocateChannels (dataToReferTo); | |||||
allocateChannels (dataToReferTo, 0); | |||||
} | |||||
AudioSampleBuffer::AudioSampleBuffer (float** dataToReferTo, | |||||
const int numChannels_, | |||||
const int startSample, | |||||
const int numSamples) throw() | |||||
: numChannels (numChannels_), | |||||
size (numSamples), | |||||
allocatedBytes (0) | |||||
{ | |||||
jassert (numChannels_ > 0); | |||||
allocateChannels (dataToReferTo, startSample); | |||||
} | } | ||||
void AudioSampleBuffer::setDataToReferTo (float** dataToReferTo, | void AudioSampleBuffer::setDataToReferTo (float** dataToReferTo, | ||||
@@ -95,10 +107,10 @@ void AudioSampleBuffer::setDataToReferTo (float** dataToReferTo, | |||||
numChannels = newNumChannels; | numChannels = newNumChannels; | ||||
size = newNumSamples; | size = newNumSamples; | ||||
allocateChannels (dataToReferTo); | |||||
allocateChannels (dataToReferTo, 0); | |||||
} | } | ||||
void AudioSampleBuffer::allocateChannels (float** const dataToReferTo) | |||||
void AudioSampleBuffer::allocateChannels (float** const dataToReferTo, int offset) | |||||
{ | { | ||||
// (try to avoid doing a malloc here, as that'll blow up things like Pro-Tools) | // (try to avoid doing a malloc here, as that'll blow up things like Pro-Tools) | ||||
if (numChannels < numElementsInArray (preallocatedChannelSpace)) | if (numChannels < numElementsInArray (preallocatedChannelSpace)) | ||||
@@ -116,7 +128,7 @@ void AudioSampleBuffer::allocateChannels (float** const dataToReferTo) | |||||
// you have to pass in the same number of valid pointers as numChannels | // you have to pass in the same number of valid pointers as numChannels | ||||
jassert (dataToReferTo[i] != 0); | jassert (dataToReferTo[i] != 0); | ||||
channels[i] = dataToReferTo[i]; | |||||
channels[i] = dataToReferTo[i] + offset; | |||||
} | } | ||||
channels [numChannels] = 0; | channels [numChannels] = 0; | ||||
@@ -70,6 +70,27 @@ public: | |||||
int numChannels, | int numChannels, | ||||
int numSamples) throw(); | int numSamples) throw(); | ||||
/** Creates a buffer using a pre-allocated block of memory. | |||||
Note that if the buffer is resized or its number of channels is changed, it | |||||
will re-allocate memory internally and copy the existing data to this new area, | |||||
so it will then stop directly addressing this memory. | |||||
@param dataToReferTo a pre-allocated array containing pointers to the data | |||||
for each channel that should be used by this buffer. The | |||||
buffer will only refer to this memory, it won't try to delete | |||||
it when the buffer is deleted or resized. | |||||
@param numChannels the number of channels to use - this must correspond to the | |||||
number of elements in the array passed in | |||||
@param startSample the offset within the arrays at which the data begins | |||||
@param numSamples the number of samples to use - this must correspond to the | |||||
size of the arrays passed in | |||||
*/ | |||||
AudioSampleBuffer (float** dataToReferTo, | |||||
int numChannels, | |||||
int startSample, | |||||
int numSamples) throw(); | |||||
/** Copies another buffer. | /** Copies another buffer. | ||||
This buffer will make its own copy of the other's data, unless the buffer was created | This buffer will make its own copy of the other's data, unless the buffer was created | ||||
@@ -429,7 +450,7 @@ private: | |||||
float* preallocatedChannelSpace [32]; | float* preallocatedChannelSpace [32]; | ||||
void allocateData(); | void allocateData(); | ||||
void allocateChannels (float** dataToReferTo); | |||||
void allocateChannels (float** dataToReferTo, int offset); | |||||
JUCE_LEAK_DETECTOR (AudioSampleBuffer); | JUCE_LEAK_DETECTOR (AudioSampleBuffer); | ||||
}; | }; | ||||
@@ -33,7 +33,7 @@ | |||||
*/ | */ | ||||
#define JUCE_MAJOR_VERSION 1 | #define JUCE_MAJOR_VERSION 1 | ||||
#define JUCE_MINOR_VERSION 53 | #define JUCE_MINOR_VERSION 53 | ||||
#define JUCE_BUILDNUMBER 24 | |||||
#define JUCE_BUILDNUMBER 25 | |||||
/** Current Juce version number. | /** Current Juce version number. | ||||
@@ -43,6 +43,9 @@ | |||||
#if (defined (_WIN32) || defined (_WIN64)) | #if (defined (_WIN32) || defined (_WIN64)) | ||||
#define JUCE_WIN32 1 | #define JUCE_WIN32 1 | ||||
#define JUCE_WINDOWS 1 | #define JUCE_WINDOWS 1 | ||||
#elif defined (JUCE_ANDROID) | |||||
#undef JUCE_ANDROID | |||||
#define JUCE_ANDROID 1 | |||||
#elif defined (LINUX) || defined (__linux__) | #elif defined (LINUX) || defined (__linux__) | ||||
#define JUCE_LINUX 1 | #define JUCE_LINUX 1 | ||||
#elif defined (__APPLE_CPP__) || defined(__APPLE_CC__) | #elif defined (__APPLE_CPP__) || defined(__APPLE_CC__) | ||||
@@ -54,9 +57,6 @@ | |||||
#else | #else | ||||
#define JUCE_MAC 1 | #define JUCE_MAC 1 | ||||
#endif | #endif | ||||
#elif defined (JUCE_ANDROID) | |||||
#undef JUCE_ANDROID | |||||
#define JUCE_ANDROID 1 | |||||
#else | #else | ||||
#error "Unknown platform!" | #error "Unknown platform!" | ||||
#endif | #endif | ||||
@@ -310,7 +310,7 @@ private: | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
while (! text.isEmpty() || text.isWhitespace()) | |||||
while (! (text.isEmpty() || text.isWhitespace())) | |||||
{ | { | ||||
++text; | ++text; | ||||
++numChars; | ++numChars; | ||||
@@ -54,23 +54,19 @@ namespace ColourHelpers | |||||
else | else | ||||
{ | { | ||||
s = jmin (1.0f, s); | s = jmin (1.0f, s); | ||||
h = jlimit (0.0f, 1.0f, h); | |||||
h = (h - std::floor (h)) * 6.0f + 0.00001f; // need a small adjustment to compensate for rounding errors | h = (h - std::floor (h)) * 6.0f + 0.00001f; // need a small adjustment to compensate for rounding errors | ||||
const float f = h - std::floor (h); | const float f = h - std::floor (h); | ||||
const uint8 x = (uint8) roundToInt (v * (1.0f - s)); | const uint8 x = (uint8) roundToInt (v * (1.0f - s)); | ||||
const float y = v * (1.0f - s * f); | |||||
const float z = v * (1.0f - (s * (1.0f - f))); | |||||
if (h < 1.0f) | if (h < 1.0f) | ||||
{ | { | ||||
r = intV; | r = intV; | ||||
g = (uint8) roundToInt (z); | |||||
g = (uint8) roundToInt (v * (1.0f - (s * (1.0f - f)))); | |||||
b = x; | b = x; | ||||
} | } | ||||
else if (h < 2.0f) | else if (h < 2.0f) | ||||
{ | { | ||||
r = (uint8) roundToInt (y); | |||||
r = (uint8) roundToInt (v * (1.0f - s * f)); | |||||
g = intV; | g = intV; | ||||
b = x; | b = x; | ||||
} | } | ||||
@@ -78,31 +74,25 @@ namespace ColourHelpers | |||||
{ | { | ||||
r = x; | r = x; | ||||
g = intV; | g = intV; | ||||
b = (uint8) roundToInt (z); | |||||
b = (uint8) roundToInt (v * (1.0f - (s * (1.0f - f)))); | |||||
} | } | ||||
else if (h < 4.0f) | else if (h < 4.0f) | ||||
{ | { | ||||
r = x; | r = x; | ||||
g = (uint8) roundToInt (y); | |||||
g = (uint8) roundToInt (v * (1.0f - s * f)); | |||||
b = intV; | b = intV; | ||||
} | } | ||||
else if (h < 5.0f) | else if (h < 5.0f) | ||||
{ | { | ||||
r = (uint8) roundToInt (z); | |||||
r = (uint8) roundToInt (v * (1.0f - (s * (1.0f - f)))); | |||||
g = x; | g = x; | ||||
b = intV; | b = intV; | ||||
} | } | ||||
else if (h < 6.0f) | |||||
else | |||||
{ | { | ||||
r = intV; | r = intV; | ||||
g = x; | g = x; | ||||
b = (uint8) roundToInt (y); | |||||
} | |||||
else | |||||
{ | |||||
r = 0; | |||||
g = 0; | |||||
b = 0; | |||||
b = (uint8) roundToInt (v * (1.0f - s * f)); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -192,7 +182,7 @@ Colour::Colour (const float hue, | |||||
const float brightness, | const float brightness, | ||||
const float alpha) throw() | const float alpha) throw() | ||||
{ | { | ||||
uint8 r = getRed(), g = getGreen(), b = getBlue(); | |||||
uint8 r, g, b; | |||||
ColourHelpers::convertHSBtoRGB (hue, saturation, brightness, r, g, b); | ColourHelpers::convertHSBtoRGB (hue, saturation, brightness, r, g, b); | ||||
argb.setARGB (ColourHelpers::floatAlphaToInt (alpha), r, g, b); | argb.setARGB (ColourHelpers::floatAlphaToInt (alpha), r, g, b); | ||||
@@ -211,7 +201,7 @@ Colour::Colour (const float hue, | |||||
const float brightness, | const float brightness, | ||||
const uint8 alpha) throw() | const uint8 alpha) throw() | ||||
{ | { | ||||
uint8 r = getRed(), g = getGreen(), b = getBlue(); | |||||
uint8 r, g, b; | |||||
ColourHelpers::convertHSBtoRGB (hue, saturation, brightness, r, g, b); | ColourHelpers::convertHSBtoRGB (hue, saturation, brightness, r, g, b); | ||||
argb.setARGB (alpha, r, g, b); | argb.setARGB (alpha, r, g, b); | ||||
@@ -404,10 +394,7 @@ const Colour Colour::withRotatedHue (const float amountToRotate) const throw() | |||||
float h, s, b; | float h, s, b; | ||||
getHSB (h, s, b); | getHSB (h, s, b); | ||||
h += amountToRotate; | |||||
h -= std::floor (h); | |||||
return Colour (h, s, b, getAlpha()); | |||||
return Colour (h + amountToRotate, s, b, getAlpha()); | |||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
@@ -33,7 +33,8 @@ | |||||
class AndroidLowLevelGraphicsContext : public LowLevelGraphicsContext | class AndroidLowLevelGraphicsContext : public LowLevelGraphicsContext | ||||
{ | { | ||||
public: | public: | ||||
AndroidLowLevelGraphicsContext() | |||||
AndroidLowLevelGraphicsContext (const GlobalRef& canvas_) | |||||
: canvas (canvas_) | |||||
{ | { | ||||
} | } | ||||
@@ -59,12 +60,12 @@ public: | |||||
bool clipToRectangle (const Rectangle<int>& r) | bool clipToRectangle (const Rectangle<int>& r) | ||||
{ | { | ||||
return false; | |||||
return true; | |||||
} | } | ||||
bool clipToRectangleList (const RectangleList& clipRegion) | bool clipToRectangleList (const RectangleList& clipRegion) | ||||
{ | { | ||||
return false; | |||||
return true; | |||||
} | } | ||||
void excludeClipRectangle (const Rectangle<int>& r) | void excludeClipRectangle (const Rectangle<int>& r) | ||||
@@ -86,7 +87,7 @@ public: | |||||
const Rectangle<int> getClipBounds() const | const Rectangle<int> getClipBounds() const | ||||
{ | { | ||||
return Rectangle<int>(); | |||||
return Rectangle<int> (0, 0, 1000, 1000); | |||||
} | } | ||||
bool isClipEmpty() const | bool isClipEmpty() const | ||||
@@ -113,6 +114,8 @@ public: | |||||
//============================================================================== | //============================================================================== | ||||
void setFill (const FillType& fillType) | void setFill (const FillType& fillType) | ||||
{ | { | ||||
currentPaint = android.env->NewObject (android.paintClass, android.paintClassConstructor); | |||||
currentPaint.callVoidMethod (android.setColor, fillType.colour.getARGB()); | |||||
} | } | ||||
void setOpacity (float newOpacity) | void setOpacity (float newOpacity) | ||||
@@ -126,6 +129,9 @@ public: | |||||
//============================================================================== | //============================================================================== | ||||
void fillRect (const Rectangle<int>& r, bool replaceExistingContents) | void fillRect (const Rectangle<int>& r, bool replaceExistingContents) | ||||
{ | { | ||||
canvas.callVoidMethod (android.drawRect, | |||||
(float) r.getX(), (float) r.getY(), (float) r.getRight(), (float) r.getBottom(), | |||||
currentPaint.get()); | |||||
} | } | ||||
void fillPath (const Path& path, const AffineTransform& transform) | void fillPath (const Path& path, const AffineTransform& transform) | ||||
@@ -162,6 +168,8 @@ public: | |||||
} | } | ||||
private: | private: | ||||
GlobalRef canvas, currentPaint; | |||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AndroidLowLevelGraphicsContext); | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AndroidLowLevelGraphicsContext); | ||||
}; | }; | ||||
@@ -27,6 +27,42 @@ | |||||
// compiled on its own). | // compiled on its own). | ||||
#if JUCE_INCLUDED_FILE | #if JUCE_INCLUDED_FILE | ||||
END_JUCE_NAMESPACE | |||||
extern JUCE_NAMESPACE::JUCEApplication* juce_CreateApplication(); // (from START_JUCE_APPLICATION) | |||||
BEGIN_JUCE_NAMESPACE | |||||
//============================================================================== | |||||
JUCE_JNI_CALLBACK (JuceAppActivity, launchApp, void, (JNIEnv* env, jobject activity)) | |||||
{ | |||||
android.initialise (env, activity); | |||||
JUCEApplication::createInstance = &juce_CreateApplication; | |||||
initialiseJuce_GUI(); | |||||
if (! JUCEApplication::createInstance()->initialiseApp (String::empty)) | |||||
exit (0); | |||||
} | |||||
JUCE_JNI_CALLBACK (JuceAppActivity, quitApp, void, (JNIEnv* env, jobject activity)) | |||||
{ | |||||
JUCEApplication::appWillTerminateByForce(); | |||||
android.shutdown(); | |||||
} | |||||
//============================================================================== | |||||
void PlatformUtilities::beep() | |||||
{ | |||||
// TODO | |||||
} | |||||
//============================================================================== | |||||
void Logger::outputDebugString (const String& text) | |||||
{ | |||||
android.env->CallStaticVoidMethod (android.activityClass, android.printToConsole, | |||||
android.javaString (text)); | |||||
} | |||||
//============================================================================== | //============================================================================== | ||||
void SystemClipboard::copyTextToClipboard (const String& text) | void SystemClipboard::copyTextToClipboard (const String& text) | ||||
@@ -90,11 +90,214 @@ BEGIN_JUCE_NAMESPACE | |||||
#include "../../containers/juce_ScopedValueSetter.h" | #include "../../containers/juce_ScopedValueSetter.h" | ||||
#include "../common/juce_MidiDataConcatenator.h" | #include "../common/juce_MidiDataConcatenator.h" | ||||
//============================================================================== | |||||
#define JUCE_JNI_CALLBACK(className, methodName, returnType, params) \ | |||||
extern "C" __attribute__ ((visibility("default"))) returnType Java_com_juce_ ## className ## _ ## methodName params | |||||
//============================================================================== | |||||
#define JUCE_JNI_CLASSES(JAVACLASS) \ | |||||
JAVACLASS (activityClass, "com/juce/JuceAppActivity") \ | |||||
JAVACLASS (componentPeerViewClass, "com/juce/ComponentPeerView") \ | |||||
JAVACLASS (fileClass, "java/io/File") \ | |||||
JAVACLASS (contextClass, "android/content/Context") \ | |||||
JAVACLASS (canvasClass, "android/graphics/Canvas") \ | |||||
JAVACLASS (paintClass, "android/graphics/Paint") \ | |||||
//============================================================================== | |||||
#define JUCE_JNI_METHODS(METHOD, STATICMETHOD) \ | |||||
\ | |||||
STATICMETHOD (activityClass, printToConsole, "printToConsole", "(Ljava/lang/String;)V") \ | |||||
METHOD (activityClass, createNewView, "createNewView", "()Lcom/juce/ComponentPeerView;") \ | |||||
METHOD (activityClass, deleteView, "deleteView", "(Lcom/juce/ComponentPeerView;)V") \ | |||||
\ | |||||
METHOD (fileClass, fileExists, "exists", "()Z") \ | |||||
\ | |||||
METHOD (componentPeerViewClass, layout, "layout", "(IIII)V") \ | |||||
\ | |||||
METHOD (canvasClass, drawRect, "drawRect", "(FFFFLandroid/graphics/Paint;)V") \ | |||||
\ | |||||
METHOD (paintClass, paintClassConstructor, "<init>", "()V") \ | |||||
METHOD (paintClass, setColor, "setColor", "(I)V") \ | |||||
//============================================================================== | |||||
class GlobalRef | |||||
{ | |||||
public: | |||||
GlobalRef() | |||||
: env (0), obj (0) | |||||
{ | |||||
} | |||||
GlobalRef (JNIEnv* const env_, jobject obj_) | |||||
: env (env_), | |||||
obj (retain (env_, obj_)) | |||||
{ | |||||
} | |||||
GlobalRef (const GlobalRef& other) | |||||
: env (other.env), | |||||
obj (retain (other.env, other.obj)) | |||||
{ | |||||
} | |||||
~GlobalRef() | |||||
{ | |||||
release(); | |||||
} | |||||
GlobalRef& operator= (const GlobalRef& other) | |||||
{ | |||||
release(); | |||||
env = other.env; | |||||
obj = retain (env, other.obj); | |||||
return *this; | |||||
} | |||||
GlobalRef& operator= (jobject newObj) | |||||
{ | |||||
jassert (env != 0 || newObj == 0); | |||||
if (newObj != obj && env != 0) | |||||
{ | |||||
release(); | |||||
obj = retain (env, newObj); | |||||
} | |||||
} | |||||
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) \ | |||||
returnType call##typeName##Method (jmethodID methodID, ... ) \ | |||||
{ \ | |||||
returnType result; \ | |||||
va_list args; \ | |||||
va_start (args, methodID); \ | |||||
result = env->Call##typeName##MethodV (obj, methodID, args); \ | |||||
va_end (args); \ | |||||
return result; \ | |||||
} | |||||
DECLARE_CALL_TYPE_METHOD (jobject, Object) | |||||
DECLARE_CALL_TYPE_METHOD (jboolean, Boolean) | |||||
DECLARE_CALL_TYPE_METHOD (jbyte, Byte) | |||||
DECLARE_CALL_TYPE_METHOD (jchar, Char) | |||||
DECLARE_CALL_TYPE_METHOD (jshort, Short) | |||||
DECLARE_CALL_TYPE_METHOD (jint, Int) | |||||
DECLARE_CALL_TYPE_METHOD (jlong, Long) | |||||
DECLARE_CALL_TYPE_METHOD (jfloat, Float) | |||||
DECLARE_CALL_TYPE_METHOD (jdouble, Double) | |||||
#undef DECLARE_CALL_TYPE_METHOD | |||||
void callVoidMethod (jmethodID methodID, ... ) | |||||
{ | |||||
va_list args; | |||||
va_start (args, methodID); | |||||
env->CallVoidMethodV (obj, methodID, args); | |||||
va_end (args); | |||||
} | |||||
private: | |||||
JNIEnv* env; | |||||
jobject obj; | |||||
void release() | |||||
{ | |||||
if (env != 0) | |||||
env->DeleteGlobalRef (obj); | |||||
} | |||||
static jobject retain (JNIEnv* const env, jobject obj_) | |||||
{ | |||||
return env == 0 ? 0 : env->NewGlobalRef (obj_); | |||||
} | |||||
}; | |||||
//============================================================================== | |||||
class AndroidJavaCallbacks | |||||
{ | |||||
public: | |||||
AndroidJavaCallbacks() : env (0) | |||||
{ | |||||
} | |||||
void initialise (JNIEnv* env_, jobject activity_) | |||||
{ | |||||
env = env_; | |||||
activity = GlobalRef (env, activity_); | |||||
#define CREATE_JNI_CLASS(className, path) \ | |||||
className = (jclass) env->NewGlobalRef (env->FindClass (path)); \ | |||||
jassert (className != 0); | |||||
JUCE_JNI_CLASSES (CREATE_JNI_CLASS); | |||||
#undef CREATE_JNI_CLASS | |||||
#define CREATE_JNI_METHOD(ownerClass, methodID, stringName, params) \ | |||||
methodID = env->GetMethodID (ownerClass, stringName, params); \ | |||||
jassert (methodID != 0); | |||||
#define CREATE_JNI_STATICMETHOD(ownerClass, methodID, stringName, params) \ | |||||
methodID = env->GetStaticMethodID (ownerClass, stringName, params); \ | |||||
jassert (methodID != 0); | |||||
JUCE_JNI_METHODS (CREATE_JNI_METHOD, CREATE_JNI_STATICMETHOD); | |||||
#undef CREATE_JNI_METHOD | |||||
} | |||||
void shutdown() | |||||
{ | |||||
if (env != 0) | |||||
{ | |||||
#define RELEASE_JNI_CLASS(className, path) env->DeleteGlobalRef (className); | |||||
JUCE_JNI_CLASSES (RELEASE_JNI_CLASS); | |||||
#undef RELEASE_JNI_CLASS | |||||
activity = 0; | |||||
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; | |||||
//============================================================================== | |||||
#define DECLARE_JNI_CLASS(className, path) jclass className; | |||||
JUCE_JNI_CLASSES (DECLARE_JNI_CLASS); | |||||
#undef DECLARE_JNI_CLASS | |||||
#define DECLARE_JNI_METHOD(ownerClass, methodID, stringName, params) jmethodID methodID; | |||||
JUCE_JNI_METHODS (DECLARE_JNI_METHOD, DECLARE_JNI_METHOD); | |||||
#undef DECLARE_JNI_METHOD | |||||
}; | |||||
static AndroidJavaCallbacks android; | |||||
//============================================================================== | //============================================================================== | ||||
#define JUCE_INCLUDED_FILE 1 | #define JUCE_INCLUDED_FILE 1 | ||||
// Now include the actual code files.. | // Now include the actual code files.. | ||||
#include "juce_android_SystemStats.cpp" // (must be first) | |||||
#include "juce_android_Misc.cpp" | |||||
#include "juce_android_SystemStats.cpp" | |||||
#include "../common/juce_posix_SharedCode.h" | #include "../common/juce_posix_SharedCode.h" | ||||
#include "juce_android_Files.cpp" | #include "juce_android_Files.cpp" | ||||
#include "../common/juce_posix_NamedPipe.cpp" | #include "../common/juce_posix_NamedPipe.cpp" | ||||
@@ -105,7 +308,6 @@ BEGIN_JUCE_NAMESPACE | |||||
#include "juce_android_GraphicsContext.cpp" | #include "juce_android_GraphicsContext.cpp" | ||||
#include "juce_android_Windowing.cpp" | #include "juce_android_Windowing.cpp" | ||||
#include "juce_android_FileChooser.cpp" | #include "juce_android_FileChooser.cpp" | ||||
#include "juce_android_Misc.cpp" | |||||
#include "juce_android_WebBrowserComponent.cpp" | #include "juce_android_WebBrowserComponent.cpp" | ||||
#include "juce_android_OpenGLComponent.cpp" | #include "juce_android_OpenGLComponent.cpp" | ||||
#include "juce_android_Midi.cpp" | #include "juce_android_Midi.cpp" | ||||
@@ -27,80 +27,6 @@ | |||||
// compiled on its own). | // compiled on its own). | ||||
#if JUCE_INCLUDED_FILE | #if JUCE_INCLUDED_FILE | ||||
END_JUCE_NAMESPACE | |||||
extern JUCE_NAMESPACE::JUCEApplication* juce_CreateApplication(); // (from START_JUCE_APPLICATION) | |||||
BEGIN_JUCE_NAMESPACE | |||||
//============================================================================== | |||||
class AndroidJavaCallbacks | |||||
{ | |||||
public: | |||||
AndroidJavaCallbacks() : env (0) | |||||
{ | |||||
} | |||||
void initialise (JNIEnv* env_, jobject activity) | |||||
{ | |||||
env = env_; | |||||
activityClass = (jclass) env->NewGlobalRef (env->GetObjectClass (activity)); | |||||
printToConsole = env->GetStaticMethodID (activityClass, "printToConsole", "(Ljava/lang/String;)V"); | |||||
jassert (printToConsole != 0); | |||||
} | |||||
void shutdown() | |||||
{ | |||||
if (env != 0) | |||||
{ | |||||
env->DeleteGlobalRef (activityClass); | |||||
} | |||||
} | |||||
//============================================================================== | |||||
JNIEnv* env; | |||||
jclass activityClass; | |||||
jmethodID printToConsole; | |||||
}; | |||||
static AndroidJavaCallbacks androidEnv; | |||||
//============================================================================== | |||||
#define JUCE_JNI_CALLBACK(className, methodName, returnType, params) \ | |||||
extern "C" __attribute__ ((visibility("default"))) returnType Java_com_juce_launch_ ## className ## _ ## methodName params | |||||
//============================================================================== | |||||
JUCE_JNI_CALLBACK (JuceAppActivity, launchApp, void, (JNIEnv* env, jobject activity)) | |||||
{ | |||||
androidEnv.initialise (env, activity); | |||||
JUCEApplication::createInstance = &juce_CreateApplication; | |||||
initialiseJuce_GUI(); | |||||
if (! JUCEApplication::createInstance()->initialiseApp (String::empty)) | |||||
exit (0); | |||||
} | |||||
JUCE_JNI_CALLBACK (JuceAppActivity, quitApp, void, (JNIEnv* env, jobject activity)) | |||||
{ | |||||
JUCEApplication::appWillTerminateByForce(); | |||||
androidEnv.shutdown(); | |||||
} | |||||
//============================================================================== | |||||
void PlatformUtilities::beep() | |||||
{ | |||||
// TODO | |||||
} | |||||
//============================================================================== | |||||
void Logger::outputDebugString (const String& text) | |||||
{ | |||||
androidEnv.env->CallStaticVoidMethod (androidEnv.activityClass, androidEnv.printToConsole, | |||||
androidEnv.env->NewStringUTF (text.toUTF8())); | |||||
} | |||||
//============================================================================== | //============================================================================== | ||||
SystemStats::OperatingSystemType SystemStats::getOperatingSystemType() | SystemStats::OperatingSystemType SystemStats::getOperatingSystemType() | ||||
@@ -36,11 +36,13 @@ public: | |||||
AndroidComponentPeer (Component* const component, const int windowStyleFlags) | AndroidComponentPeer (Component* const component, const int windowStyleFlags) | ||||
: ComponentPeer (component, windowStyleFlags) | : ComponentPeer (component, windowStyleFlags) | ||||
{ | { | ||||
// TODO | |||||
view = GlobalRef (android.env, android.activity.callObjectMethod (android.createNewView)); | |||||
} | } | ||||
~AndroidComponentPeer() | ~AndroidComponentPeer() | ||||
{ | { | ||||
android.activity.callVoidMethod (android.deleteView, view.get()); | |||||
view = 0; | |||||
} | } | ||||
void* getNativeHandle() const | void* getNativeHandle() const | ||||
@@ -67,7 +69,8 @@ public: | |||||
void setBounds (int x, int y, int w, int h, bool isNowFullScreen) | void setBounds (int x, int y, int w, int h, bool isNowFullScreen) | ||||
{ | { | ||||
// TODO | |||||
DBG ("Window size: " << x << " " << y << " " << w << " " << h); | |||||
view.callVoidMethod (android.layout, x, y, x + w, y + h); | |||||
} | } | ||||
const Rectangle<int> getBounds() const | const Rectangle<int> getBounds() const | ||||
@@ -167,6 +170,12 @@ public: | |||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
void handlePaintCallback (JNIEnv* env, jobject canvas) | |||||
{ | |||||
AndroidLowLevelGraphicsContext g (GlobalRef (env, canvas)); | |||||
handlePaint (g); | |||||
} | |||||
void repaint (const Rectangle<int>& area) | void repaint (const Rectangle<int>& area) | ||||
{ | { | ||||
// TODO | // TODO | ||||
@@ -182,14 +191,42 @@ public: | |||||
// TODO | // TODO | ||||
} | } | ||||
private: | |||||
//============================================================================== | //============================================================================== | ||||
static AndroidComponentPeer* findPeerForJavaView (jobject viewToFind) | |||||
{ | |||||
for (int i = getNumPeers(); --i >= 0;) | |||||
{ | |||||
AndroidComponentPeer* const ap = static_cast <AndroidComponentPeer*> (getPeer(i)); | |||||
jassert (dynamic_cast <AndroidComponentPeer*> (getPeer(i)) != 0); | |||||
if (ap->view == viewToFind) | |||||
return ap; | |||||
} | |||||
return 0; | |||||
} | |||||
private: | |||||
//============================================================================== | |||||
GlobalRef view; | |||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AndroidComponentPeer); | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AndroidComponentPeer); | ||||
}; | }; | ||||
//============================================================================== | |||||
#define JUCE_VIEW_CALLBACK(returnType, javaMethodName, params, juceMethodInvocation) \ | |||||
JUCE_JNI_CALLBACK (ComponentPeerView, javaMethodName, returnType, params) \ | |||||
{ \ | |||||
AndroidComponentPeer* const peer = AndroidComponentPeer::findPeerForJavaView (view); \ | |||||
if (peer != 0) \ | |||||
peer->juceMethodInvocation; \ | |||||
} | |||||
JUCE_VIEW_CALLBACK (void, handlePaint, (JNIEnv* env, jobject view, jobject canvas), | |||||
handlePaintCallback (env, canvas)) | |||||
//============================================================================== | |||||
ComponentPeer* Component::createNewPeer (int styleFlags, void*) | ComponentPeer* Component::createNewPeer (int styleFlags, void*) | ||||
{ | { | ||||
return new AndroidComponentPeer (this, styleFlags); | return new AndroidComponentPeer (this, styleFlags); | ||||
@@ -282,11 +319,17 @@ void juce_setKioskComponent (Component* kioskModeComponent, bool enableOrDisable | |||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
static int screenWidth = 0, screenHeight = 0; | |||||
void juce_updateMultiMonitorInfo (Array <Rectangle<int> >& monitorCoords, const bool clipToWorkArea) | void juce_updateMultiMonitorInfo (Array <Rectangle<int> >& monitorCoords, const bool clipToWorkArea) | ||||
{ | { | ||||
// TODO | |||||
monitorCoords.add (Rectangle<int> (0, 0, screenWidth, screenHeight)); | |||||
} | |||||
monitorCoords.add (Rectangle<int> (0, 0, 640, 480)); | |||||
JUCE_JNI_CALLBACK (JuceAppActivity, setScreenSize, void, (JNIEnv* env, jobject activity, int w, int h)) | |||||
{ | |||||
screenWidth = w; | |||||
screenHeight = h; | |||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||