| @@ -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; | |||
| } | |||
| //============================================================================== | |||