@@ -58,6 +58,9 @@ | |||
#if (defined (_WIN32) || defined (_WIN64)) | |||
#define JUCE_WIN32 1 | |||
#define JUCE_WINDOWS 1 | |||
#elif defined (JUCE_ANDROID) | |||
#undef JUCE_ANDROID | |||
#define JUCE_ANDROID 1 | |||
#elif defined (LINUX) || defined (__linux__) | |||
#define JUCE_LINUX 1 | |||
#elif defined (__APPLE_CPP__) || defined(__APPLE_CC__) | |||
@@ -69,9 +72,6 @@ | |||
#else | |||
#define JUCE_MAC 1 | |||
#endif | |||
#elif defined (JUCE_ANDROID) | |||
#undef JUCE_ANDROID | |||
#define JUCE_ANDROID 1 | |||
#else | |||
#error "Unknown platform!" | |||
#endif | |||
@@ -25746,34 +25746,21 @@ void AudioDeviceManager::addMidiInputCallback (const String& name, | |||
{ | |||
removeMidiInputCallback (name, callbackToAdd); | |||
if (name.isEmpty()) | |||
if (name.isEmpty() || isMidiInputEnabled (name)) | |||
{ | |||
const ScopedLock sl (midiCallbackLock); | |||
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;) | |||
{ | |||
if (midiCallbackDevices[i] == name) | |||
if (midiCallbackDevices[i] == name && midiCallbacks.getUnchecked(i) == callback) | |||
{ | |||
const ScopedLock sl (midiCallbackLock); | |||
midiCallbacks.remove (i); | |||
midiCallbackDevices.remove (i); | |||
} | |||
@@ -26782,7 +26769,19 @@ AudioSampleBuffer::AudioSampleBuffer (float** dataToReferTo, | |||
allocatedBytes (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, | |||
@@ -26797,10 +26796,10 @@ void AudioSampleBuffer::setDataToReferTo (float** dataToReferTo, | |||
numChannels = newNumChannels; | |||
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) | |||
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 | |||
jassert (dataToReferTo[i] != 0); | |||
channels[i] = dataToReferTo[i]; | |||
channels[i] = dataToReferTo[i] + offset; | |||
} | |||
channels [numChannels] = 0; | |||
@@ -52200,7 +52199,7 @@ private: | |||
} | |||
else | |||
{ | |||
while (! text.isEmpty() || text.isWhitespace()) | |||
while (! (text.isEmpty() || text.isWhitespace())) | |||
{ | |||
++text; | |||
++numChars; | |||
@@ -80262,23 +80261,19 @@ namespace ColourHelpers | |||
else | |||
{ | |||
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 | |||
const float f = h - std::floor (h); | |||
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) | |||
{ | |||
r = intV; | |||
g = (uint8) roundToInt (z); | |||
g = (uint8) roundToInt (v * (1.0f - (s * (1.0f - f)))); | |||
b = x; | |||
} | |||
else if (h < 2.0f) | |||
{ | |||
r = (uint8) roundToInt (y); | |||
r = (uint8) roundToInt (v * (1.0f - s * f)); | |||
g = intV; | |||
b = x; | |||
} | |||
@@ -80286,31 +80281,25 @@ namespace ColourHelpers | |||
{ | |||
r = x; | |||
g = intV; | |||
b = (uint8) roundToInt (z); | |||
b = (uint8) roundToInt (v * (1.0f - (s * (1.0f - f)))); | |||
} | |||
else if (h < 4.0f) | |||
{ | |||
r = x; | |||
g = (uint8) roundToInt (y); | |||
g = (uint8) roundToInt (v * (1.0f - s * f)); | |||
b = intV; | |||
} | |||
else if (h < 5.0f) | |||
{ | |||
r = (uint8) roundToInt (z); | |||
r = (uint8) roundToInt (v * (1.0f - (s * (1.0f - f)))); | |||
g = x; | |||
b = intV; | |||
} | |||
else if (h < 6.0f) | |||
else | |||
{ | |||
r = intV; | |||
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 alpha) throw() | |||
{ | |||
uint8 r = getRed(), g = getGreen(), b = getBlue(); | |||
uint8 r, g, b; | |||
ColourHelpers::convertHSBtoRGB (hue, saturation, brightness, r, g, b); | |||
argb.setARGB (ColourHelpers::floatAlphaToInt (alpha), r, g, b); | |||
@@ -80417,7 +80406,7 @@ Colour::Colour (const float hue, | |||
const float brightness, | |||
const uint8 alpha) throw() | |||
{ | |||
uint8 r = getRed(), g = getGreen(), b = getBlue(); | |||
uint8 r, g, b; | |||
ColourHelpers::convertHSBtoRGB (hue, saturation, brightness, 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; | |||
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() | |||
@@ -278509,18 +278495,126 @@ END_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 | |||
{ | |||
@@ -278529,37 +278623,85 @@ public: | |||
{ | |||
} | |||
void initialise (JNIEnv* env_, jobject activity) | |||
void initialise (JNIEnv* env_, jobject activity_) | |||
{ | |||
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() | |||
{ | |||
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; | |||
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)) | |||
{ | |||
androidEnv.initialise (env, activity); | |||
android.initialise (env, activity); | |||
JUCEApplication::createInstance = &juce_CreateApplication; | |||
@@ -278573,7 +278715,7 @@ JUCE_JNI_CALLBACK (JuceAppActivity, quitApp, void, (JNIEnv* env, jobject activit | |||
{ | |||
JUCEApplication::appWillTerminateByForce(); | |||
androidEnv.shutdown(); | |||
android.shutdown(); | |||
} | |||
void PlatformUtilities::beep() | |||
@@ -278583,10 +278725,34 @@ void PlatformUtilities::beep() | |||
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() | |||
{ | |||
return Android; | |||
@@ -278726,7 +278892,6 @@ bool Time::setSystemTimeToThisTime() const | |||
#endif | |||
/*** End of inlined file: juce_android_SystemStats.cpp ***/ | |||
// (must be first) | |||
/*** 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 ***/ | |||
/*** Start of inlined file: juce_android_Files.cpp ***/ | |||
// (This file gets included by juce_android_NativeCode.cpp, rather than being | |||
// compiled on its own). | |||
@@ -280263,7 +280427,8 @@ const Typeface::Ptr Typeface::createSystemTypefaceFor (const Font& font) | |||
class AndroidLowLevelGraphicsContext : public LowLevelGraphicsContext | |||
{ | |||
public: | |||
AndroidLowLevelGraphicsContext() | |||
AndroidLowLevelGraphicsContext (const GlobalRef& canvas_) | |||
: canvas (canvas_) | |||
{ | |||
} | |||
@@ -280288,12 +280453,12 @@ public: | |||
bool clipToRectangle (const Rectangle<int>& r) | |||
{ | |||
return false; | |||
return true; | |||
} | |||
bool clipToRectangleList (const RectangleList& clipRegion) | |||
{ | |||
return false; | |||
return true; | |||
} | |||
void excludeClipRectangle (const Rectangle<int>& r) | |||
@@ -280315,7 +280480,7 @@ public: | |||
const Rectangle<int> getClipBounds() const | |||
{ | |||
return Rectangle<int>(); | |||
return Rectangle<int> (0, 0, 1000, 1000); | |||
} | |||
bool isClipEmpty() const | |||
@@ -280341,6 +280506,8 @@ public: | |||
void setFill (const FillType& fillType) | |||
{ | |||
currentPaint = android.env->NewObject (android.paintClass, android.paintClassConstructor); | |||
currentPaint.callVoidMethod (android.setColor, fillType.colour.getARGB()); | |||
} | |||
void setOpacity (float newOpacity) | |||
@@ -280353,6 +280520,9 @@ public: | |||
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) | |||
@@ -280389,6 +280559,8 @@ public: | |||
} | |||
private: | |||
GlobalRef canvas, currentPaint; | |||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AndroidLowLevelGraphicsContext); | |||
}; | |||
@@ -280408,11 +280580,13 @@ public: | |||
AndroidComponentPeer (Component* const component, const int windowStyleFlags) | |||
: ComponentPeer (component, windowStyleFlags) | |||
{ | |||
// TODO | |||
view = GlobalRef (android.env, android.activity.callObjectMethod (android.createNewView)); | |||
} | |||
~AndroidComponentPeer() | |||
{ | |||
android.activity.callVoidMethod (android.deleteView, view.get()); | |||
view = 0; | |||
} | |||
void* getNativeHandle() const | |||
@@ -280439,7 +280613,8 @@ public: | |||
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 | |||
@@ -280537,6 +280712,12 @@ public: | |||
// TODO | |||
} | |||
void handlePaintCallback (JNIEnv* env, jobject canvas) | |||
{ | |||
AndroidLowLevelGraphicsContext g (GlobalRef (env, canvas)); | |||
handlePaint (g); | |||
} | |||
void repaint (const Rectangle<int>& area) | |||
{ | |||
// TODO | |||
@@ -280552,11 +280733,38 @@ public: | |||
// 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: | |||
GlobalRef view; | |||
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*) | |||
{ | |||
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) | |||
{ | |||
// 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) | |||
@@ -280768,29 +280982,6 @@ void FileChooser::showPlatformDialog (Array<File>& results, | |||
/*** 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 ***/ | |||
// (This file gets included by juce_android_NativeCode.cpp, rather than being | |||
// compiled on its own). | |||
@@ -73,7 +73,7 @@ namespace JuceDummyNamespace {} | |||
*/ | |||
#define JUCE_MAJOR_VERSION 1 | |||
#define JUCE_MINOR_VERSION 53 | |||
#define JUCE_BUILDNUMBER 24 | |||
#define JUCE_BUILDNUMBER 25 | |||
/** Current Juce version number. | |||
@@ -105,6 +105,9 @@ namespace JuceDummyNamespace {} | |||
#if (defined (_WIN32) || defined (_WIN64)) | |||
#define JUCE_WIN32 1 | |||
#define JUCE_WINDOWS 1 | |||
#elif defined (JUCE_ANDROID) | |||
#undef JUCE_ANDROID | |||
#define JUCE_ANDROID 1 | |||
#elif defined (LINUX) || defined (__linux__) | |||
#define JUCE_LINUX 1 | |||
#elif defined (__APPLE_CPP__) || defined(__APPLE_CC__) | |||
@@ -116,9 +119,6 @@ namespace JuceDummyNamespace {} | |||
#else | |||
#define JUCE_MAC 1 | |||
#endif | |||
#elif defined (JUCE_ANDROID) | |||
#undef JUCE_ANDROID | |||
#define JUCE_ANDROID 1 | |||
#else | |||
#error "Unknown platform!" | |||
#endif | |||
@@ -34408,6 +34408,27 @@ public: | |||
int numChannels, | |||
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. | |||
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]; | |||
void allocateData(); | |||
void allocateChannels (float** dataToReferTo); | |||
void allocateChannels (float** dataToReferTo, int offset); | |||
JUCE_LEAK_DETECTOR (AudioSampleBuffer); | |||
}; | |||
@@ -795,34 +795,21 @@ void AudioDeviceManager::addMidiInputCallback (const String& name, | |||
{ | |||
removeMidiInputCallback (name, callbackToAdd); | |||
if (name.isEmpty()) | |||
if (name.isEmpty() || isMidiInputEnabled (name)) | |||
{ | |||
const ScopedLock sl (midiCallbackLock); | |||
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;) | |||
{ | |||
if (midiCallbackDevices[i] == name) | |||
if (midiCallbackDevices[i] == name && midiCallbacks.getUnchecked(i) == callback) | |||
{ | |||
const ScopedLock sl (midiCallbackLock); | |||
midiCallbacks.remove (i); | |||
midiCallbackDevices.remove (i); | |||
} | |||
@@ -80,7 +80,19 @@ AudioSampleBuffer::AudioSampleBuffer (float** dataToReferTo, | |||
allocatedBytes (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, | |||
@@ -95,10 +107,10 @@ void AudioSampleBuffer::setDataToReferTo (float** dataToReferTo, | |||
numChannels = newNumChannels; | |||
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) | |||
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 | |||
jassert (dataToReferTo[i] != 0); | |||
channels[i] = dataToReferTo[i]; | |||
channels[i] = dataToReferTo[i] + offset; | |||
} | |||
channels [numChannels] = 0; | |||
@@ -70,6 +70,27 @@ public: | |||
int numChannels, | |||
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. | |||
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]; | |||
void allocateData(); | |||
void allocateChannels (float** dataToReferTo); | |||
void allocateChannels (float** dataToReferTo, int offset); | |||
JUCE_LEAK_DETECTOR (AudioSampleBuffer); | |||
}; | |||
@@ -33,7 +33,7 @@ | |||
*/ | |||
#define JUCE_MAJOR_VERSION 1 | |||
#define JUCE_MINOR_VERSION 53 | |||
#define JUCE_BUILDNUMBER 24 | |||
#define JUCE_BUILDNUMBER 25 | |||
/** Current Juce version number. | |||
@@ -43,6 +43,9 @@ | |||
#if (defined (_WIN32) || defined (_WIN64)) | |||
#define JUCE_WIN32 1 | |||
#define JUCE_WINDOWS 1 | |||
#elif defined (JUCE_ANDROID) | |||
#undef JUCE_ANDROID | |||
#define JUCE_ANDROID 1 | |||
#elif defined (LINUX) || defined (__linux__) | |||
#define JUCE_LINUX 1 | |||
#elif defined (__APPLE_CPP__) || defined(__APPLE_CC__) | |||
@@ -54,9 +57,6 @@ | |||
#else | |||
#define JUCE_MAC 1 | |||
#endif | |||
#elif defined (JUCE_ANDROID) | |||
#undef JUCE_ANDROID | |||
#define JUCE_ANDROID 1 | |||
#else | |||
#error "Unknown platform!" | |||
#endif | |||
@@ -310,7 +310,7 @@ private: | |||
} | |||
else | |||
{ | |||
while (! text.isEmpty() || text.isWhitespace()) | |||
while (! (text.isEmpty() || text.isWhitespace())) | |||
{ | |||
++text; | |||
++numChars; | |||
@@ -54,23 +54,19 @@ namespace ColourHelpers | |||
else | |||
{ | |||
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 | |||
const float f = h - std::floor (h); | |||
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) | |||
{ | |||
r = intV; | |||
g = (uint8) roundToInt (z); | |||
g = (uint8) roundToInt (v * (1.0f - (s * (1.0f - f)))); | |||
b = x; | |||
} | |||
else if (h < 2.0f) | |||
{ | |||
r = (uint8) roundToInt (y); | |||
r = (uint8) roundToInt (v * (1.0f - s * f)); | |||
g = intV; | |||
b = x; | |||
} | |||
@@ -78,31 +74,25 @@ namespace ColourHelpers | |||
{ | |||
r = x; | |||
g = intV; | |||
b = (uint8) roundToInt (z); | |||
b = (uint8) roundToInt (v * (1.0f - (s * (1.0f - f)))); | |||
} | |||
else if (h < 4.0f) | |||
{ | |||
r = x; | |||
g = (uint8) roundToInt (y); | |||
g = (uint8) roundToInt (v * (1.0f - s * f)); | |||
b = intV; | |||
} | |||
else if (h < 5.0f) | |||
{ | |||
r = (uint8) roundToInt (z); | |||
r = (uint8) roundToInt (v * (1.0f - (s * (1.0f - f)))); | |||
g = x; | |||
b = intV; | |||
} | |||
else if (h < 6.0f) | |||
else | |||
{ | |||
r = intV; | |||
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 alpha) throw() | |||
{ | |||
uint8 r = getRed(), g = getGreen(), b = getBlue(); | |||
uint8 r, g, b; | |||
ColourHelpers::convertHSBtoRGB (hue, saturation, brightness, r, g, b); | |||
argb.setARGB (ColourHelpers::floatAlphaToInt (alpha), r, g, b); | |||
@@ -211,7 +201,7 @@ Colour::Colour (const float hue, | |||
const float brightness, | |||
const uint8 alpha) throw() | |||
{ | |||
uint8 r = getRed(), g = getGreen(), b = getBlue(); | |||
uint8 r, g, b; | |||
ColourHelpers::convertHSBtoRGB (hue, saturation, brightness, 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; | |||
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 | |||
{ | |||
public: | |||
AndroidLowLevelGraphicsContext() | |||
AndroidLowLevelGraphicsContext (const GlobalRef& canvas_) | |||
: canvas (canvas_) | |||
{ | |||
} | |||
@@ -59,12 +60,12 @@ public: | |||
bool clipToRectangle (const Rectangle<int>& r) | |||
{ | |||
return false; | |||
return true; | |||
} | |||
bool clipToRectangleList (const RectangleList& clipRegion) | |||
{ | |||
return false; | |||
return true; | |||
} | |||
void excludeClipRectangle (const Rectangle<int>& r) | |||
@@ -86,7 +87,7 @@ public: | |||
const Rectangle<int> getClipBounds() const | |||
{ | |||
return Rectangle<int>(); | |||
return Rectangle<int> (0, 0, 1000, 1000); | |||
} | |||
bool isClipEmpty() const | |||
@@ -113,6 +114,8 @@ public: | |||
//============================================================================== | |||
void setFill (const FillType& fillType) | |||
{ | |||
currentPaint = android.env->NewObject (android.paintClass, android.paintClassConstructor); | |||
currentPaint.callVoidMethod (android.setColor, fillType.colour.getARGB()); | |||
} | |||
void setOpacity (float newOpacity) | |||
@@ -126,6 +129,9 @@ public: | |||
//============================================================================== | |||
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) | |||
@@ -162,6 +168,8 @@ public: | |||
} | |||
private: | |||
GlobalRef canvas, currentPaint; | |||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AndroidLowLevelGraphicsContext); | |||
}; | |||
@@ -27,6 +27,42 @@ | |||
// 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)) | |||
{ | |||
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) | |||
@@ -90,11 +90,214 @@ BEGIN_JUCE_NAMESPACE | |||
#include "../../containers/juce_ScopedValueSetter.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 | |||
// 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 "juce_android_Files.cpp" | |||
#include "../common/juce_posix_NamedPipe.cpp" | |||
@@ -105,7 +308,6 @@ BEGIN_JUCE_NAMESPACE | |||
#include "juce_android_GraphicsContext.cpp" | |||
#include "juce_android_Windowing.cpp" | |||
#include "juce_android_FileChooser.cpp" | |||
#include "juce_android_Misc.cpp" | |||
#include "juce_android_WebBrowserComponent.cpp" | |||
#include "juce_android_OpenGLComponent.cpp" | |||
#include "juce_android_Midi.cpp" | |||
@@ -27,80 +27,6 @@ | |||
// compiled on its own). | |||
#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() | |||
@@ -36,11 +36,13 @@ public: | |||
AndroidComponentPeer (Component* const component, const int windowStyleFlags) | |||
: ComponentPeer (component, windowStyleFlags) | |||
{ | |||
// TODO | |||
view = GlobalRef (android.env, android.activity.callObjectMethod (android.createNewView)); | |||
} | |||
~AndroidComponentPeer() | |||
{ | |||
android.activity.callVoidMethod (android.deleteView, view.get()); | |||
view = 0; | |||
} | |||
void* getNativeHandle() const | |||
@@ -67,7 +69,8 @@ public: | |||
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 | |||
@@ -167,6 +170,12 @@ public: | |||
} | |||
//============================================================================== | |||
void handlePaintCallback (JNIEnv* env, jobject canvas) | |||
{ | |||
AndroidLowLevelGraphicsContext g (GlobalRef (env, canvas)); | |||
handlePaint (g); | |||
} | |||
void repaint (const Rectangle<int>& area) | |||
{ | |||
// TODO | |||
@@ -182,14 +191,42 @@ public: | |||
// 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); | |||
}; | |||
//============================================================================== | |||
#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*) | |||
{ | |||
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) | |||
{ | |||
// 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; | |||
} | |||
//============================================================================== | |||