diff --git a/modules/juce_audio_devices/native/juce_android_Midi.cpp b/modules/juce_audio_devices/native/juce_android_Midi.cpp index 371ac4c8e2..08825325c8 100644 --- a/modules/juce_audio_devices/native/juce_android_Midi.cpp +++ b/modules/juce_audio_devices/native/juce_android_Midi.cpp @@ -327,7 +327,7 @@ static const uint8 javaMidiByteCode[] = STATICMETHOD (getAndroidMidiDeviceManager, "getAndroidMidiDeviceManager", "(Landroid/content/Context;)Lcom/rmsl/juce/JuceMidiSupport$MidiDeviceManager;") \ STATICMETHOD (getAndroidBluetoothManager, "getAndroidBluetoothManager", "(Landroid/content/Context;)Lcom/rmsl/juce/JuceMidiSupport$BluetoothManager;") -DECLARE_JNI_CLASS_WITH_BYTECODE (JuceMidiSupport, "com/rmsl/juce/JuceMidiSupport", 23, javaMidiByteCode, sizeof (javaMidiByteCode)) +DECLARE_JNI_CLASS_WITH_BYTECODE (JuceMidiSupport, "com/rmsl/juce/JuceMidiSupport", 23, javaMidiByteCode) #undef JNI_CLASS_MEMBERS #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ diff --git a/modules/juce_core/misc/juce_Functional.h b/modules/juce_core/misc/juce_Functional.h index 05eaca5161..e2a8bbfd1f 100644 --- a/modules/juce_core/misc/juce_Functional.h +++ b/modules/juce_core/misc/juce_Functional.h @@ -113,4 +113,19 @@ Object withMember (Object copy, Member OtherObject::* member, Other&& value) template struct ScopeGuard : Fn { ~ScopeGuard() { Fn::operator()(); } }; template ScopeGuard (Fn) -> ScopeGuard; +#ifndef DOXYGEN +namespace detail +{ +template +static constexpr auto toFnPtr (Functor functor, Return (Functor::*) (Args...) const) +{ + return static_cast (functor); +} +} // namespace detail +#endif + +/** Converts a captureless lambda to its equivalent function pointer type. */ +template +static constexpr auto toFnPtr (Functor functor) { return detail::toFnPtr (functor, &Functor::operator()); } + } // namespace juce diff --git a/modules/juce_core/native/juce_android_JNIHelpers.cpp b/modules/juce_core/native/juce_android_JNIHelpers.cpp index eb2c3838b3..45eb542f43 100644 --- a/modules/juce_core/native/juce_android_JNIHelpers.cpp +++ b/modules/juce_core/native/juce_android_JNIHelpers.cpp @@ -62,7 +62,7 @@ static const uint8 invocationHandleByteCode[] = CALLBACK (juce_invokeImplementer, "dispatchInvoke", "(JLjava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;") \ CALLBACK (juce_dispatchDelete, "dispatchFinalize", "(J)V") - DECLARE_JNI_CLASS_WITH_BYTECODE (JuceInvocationHandler, "com/rmsl/juce/JuceInvocationHandler", 10, invocationHandleByteCode, sizeof (invocationHandleByteCode)) + DECLARE_JNI_CLASS_WITH_BYTECODE (JuceInvocationHandler, "com/rmsl/juce/JuceInvocationHandler", 10, invocationHandleByteCode) #undef JNI_CLASS_MEMBERS #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ @@ -116,7 +116,7 @@ struct SystemJavaClassComparator }; //============================================================================== -JNIClassBase::JNIClassBase (const char* cp, int classMinSDK, const void* bc, size_t n) +JNIClassBase::JNIClassBase (const char* cp, int classMinSDK, const uint8* bc, size_t n) : classPath (cp), byteCode (bc), byteCodeSize (n), minSDK (classMinSDK), classRef (nullptr) { SystemJavaClassComparator comparator; @@ -552,12 +552,12 @@ static const uint8 javaFragmentOverlay[] = #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ METHOD (construct, "", "()V") \ METHOD (close, "close", "()V") \ - CALLBACK (FragmentOverlay::onActivityResultNative, "onActivityResultNative", "(JIILandroid/content/Intent;)V") \ - CALLBACK (FragmentOverlay::onCreateNative, "onCreateNative", "(JLandroid/os/Bundle;)V") \ - CALLBACK (FragmentOverlay::onStartNative, "onStartNative", "(J)V") \ - CALLBACK (FragmentOverlay::onRequestPermissionsResultNative, "onRequestPermissionsResultNative", "(JI[Ljava/lang/String;[I)V") + CALLBACK (generatedCallback<&FragmentOverlay::onActivityResultCallback>, "onActivityResultNative", "(JIILandroid/content/Intent;)V") \ + CALLBACK (generatedCallback<&FragmentOverlay::onCreatedCallback>, "onCreateNative", "(JLandroid/os/Bundle;)V") \ + CALLBACK (generatedCallback<&FragmentOverlay::onStartCallback>, "onStartNative", "(J)V") \ + CALLBACK (generatedCallback<&FragmentOverlay::onRequestPermissionsResultCallback>, "onRequestPermissionsResultNative", "(JI[Ljava/lang/String;[I)V") - DECLARE_JNI_CLASS_WITH_BYTECODE (JuceFragmentOverlay, "com/rmsl/juce/FragmentOverlay", 16, javaFragmentOverlay, sizeof(javaFragmentOverlay)) + DECLARE_JNI_CLASS_WITH_BYTECODE (JuceFragmentOverlay, "com/rmsl/juce/FragmentOverlay", 16, javaFragmentOverlay) #undef JNI_CLASS_MEMBERS #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ @@ -590,47 +590,39 @@ void FragmentOverlay::open() env->CallVoidMethod (native.get(), AndroidDialogFragment.show, fm.get(), javaString ("FragmentOverlay").get()); } -void FragmentOverlay::onActivityResultNative (JNIEnv* env, jobject, jlong host, - jint requestCode, jint resultCode, jobject data) +void FragmentOverlay::onCreatedCallback (JNIEnv* env, FragmentOverlay& t, jobject obj) { - if (auto* myself = reinterpret_cast (host)) - myself->onActivityResult (requestCode, resultCode, LocalRef (env->NewLocalRef (data))); + t.onCreated (LocalRef { env->NewLocalRef (obj) }); } -void FragmentOverlay::onCreateNative (JNIEnv* env, jobject, jlong host, jobject bundle) +void FragmentOverlay::onStartCallback (JNIEnv*, FragmentOverlay& t) { - if (auto* myself = reinterpret_cast (host)) - myself->onCreated (LocalRef (env->NewLocalRef (bundle))); + t.onStart(); } -void FragmentOverlay::onStartNative (JNIEnv*, jobject, jlong host) +void FragmentOverlay::onRequestPermissionsResultCallback (JNIEnv* env, FragmentOverlay& t, jint requestCode, jobjectArray jPermissions, jintArray jGrantResults) { - if (auto* myself = reinterpret_cast (host)) - myself->onStart(); -} + Array grantResults; + int n = (jGrantResults != nullptr ? env->GetArrayLength (jGrantResults) : 0); -void FragmentOverlay::onRequestPermissionsResultNative (JNIEnv* env, jobject, jlong host, jint requestCode, - jobjectArray jPermissions, jintArray jGrantResults) -{ - if (auto* myself = reinterpret_cast (host)) + if (n > 0) { - Array grantResults; - int n = (jGrantResults != nullptr ? env->GetArrayLength (jGrantResults) : 0); + auto* data = env->GetIntArrayElements (jGrantResults, nullptr); - if (n > 0) - { - auto* data = env->GetIntArrayElements (jGrantResults, nullptr); + for (int i = 0; i < n; ++i) + grantResults.add (data[i]); - for (int i = 0; i < n; ++i) - grantResults.add (data[i]); + env->ReleaseIntArrayElements (jGrantResults, data, 0); + } - env->ReleaseIntArrayElements (jGrantResults, data, 0); - } + t.onRequestPermissionsResult (requestCode, + javaStringArrayToJuce (LocalRef (jPermissions)), + grantResults); +} - myself->onRequestPermissionsResult (requestCode, - javaStringArrayToJuce (LocalRef (jPermissions)), - grantResults); - } +void FragmentOverlay::onActivityResultCallback (JNIEnv* env, FragmentOverlay& t, jint requestCode, jint resultCode, jobject data) +{ + t.onActivityResult (requestCode, resultCode, LocalRef (env->NewLocalRef (data))); } jobject FragmentOverlay::getNativeHandle() diff --git a/modules/juce_core/native/juce_android_JNIHelpers.h b/modules/juce_core/native/juce_android_JNIHelpers.h index bdfa4c3880..aeb49f97b2 100644 --- a/modules/juce_core/native/juce_android_JNIHelpers.h +++ b/modules/juce_core/native/juce_android_JNIHelpers.h @@ -172,7 +172,7 @@ struct SystemJavaClassComparator; class JNIClassBase { public: - JNIClassBase (const char* classPath, int minSDK, const void* byteCode, size_t byteCodeSize); + JNIClassBase (const char* classPath, int minSDK, const uint8* byteCode, size_t byteCodeSize); virtual ~JNIClassBase(); operator jclass() const noexcept { return classRef; } @@ -210,6 +210,9 @@ private: }; //============================================================================== +template constexpr auto numBytes (const T (&) [N]) { return N; } + constexpr auto numBytes (std::nullptr_t) { return static_cast (0); } + #define CREATE_JNI_METHOD(methodID, stringName, params) methodID = resolveMethod (env, stringName, params); #define CREATE_JNI_STATICMETHOD(methodID, stringName, params) methodID = resolveStaticMethod (env, stringName, params); #define CREATE_JNI_FIELD(fieldID, stringName, signature) fieldID = resolveField (env, stringName, signature); @@ -219,26 +222,26 @@ private: #define DECLARE_JNI_FIELD(fieldID, stringName, signature) jfieldID fieldID; #define DECLARE_JNI_CALLBACK(fieldID, stringName, signature) -#define DECLARE_JNI_CLASS_WITH_BYTECODE(CppClassName, javaPath, minSDK, byteCodeData, byteCodeSize) \ - class CppClassName ## _Class : public JNIClassBase \ - { \ - public: \ - CppClassName ## _Class() : JNIClassBase (javaPath, minSDK, byteCodeData, byteCodeSize) {} \ - \ - void initialiseFields (JNIEnv* env) \ - { \ - Array callbacks; \ - JNI_CLASS_MEMBERS (CREATE_JNI_METHOD, CREATE_JNI_STATICMETHOD, CREATE_JNI_FIELD, CREATE_JNI_STATICFIELD, CREATE_JNI_CALLBACK); \ - resolveCallbacks (env, callbacks); \ - } \ - \ - JNI_CLASS_MEMBERS (DECLARE_JNI_METHOD, DECLARE_JNI_METHOD, DECLARE_JNI_FIELD, DECLARE_JNI_FIELD, DECLARE_JNI_CALLBACK) \ - }; \ - static CppClassName ## _Class CppClassName; +#define DECLARE_JNI_CLASS_WITH_BYTECODE(CppClassName, javaPath, minSDK, byteCodeData) \ + class CppClassName ## _Class : public JNIClassBase \ + { \ + public: \ + CppClassName ## _Class() : JNIClassBase (javaPath, minSDK, byteCodeData, numBytes (byteCodeData)) {} \ + \ + void initialiseFields (JNIEnv* env) \ + { \ + Array callbacks; \ + JNI_CLASS_MEMBERS (CREATE_JNI_METHOD, CREATE_JNI_STATICMETHOD, CREATE_JNI_FIELD, CREATE_JNI_STATICFIELD, CREATE_JNI_CALLBACK); \ + resolveCallbacks (env, callbacks); \ + } \ + \ + JNI_CLASS_MEMBERS (DECLARE_JNI_METHOD, DECLARE_JNI_METHOD, DECLARE_JNI_FIELD, DECLARE_JNI_FIELD, DECLARE_JNI_CALLBACK) \ + }; \ + static inline const CppClassName ## _Class CppClassName; //============================================================================== #define DECLARE_JNI_CLASS_WITH_MIN_SDK(CppClassName, javaPath, minSDK) \ - DECLARE_JNI_CLASS_WITH_BYTECODE (CppClassName, javaPath, minSDK, nullptr, 0) + DECLARE_JNI_CLASS_WITH_BYTECODE (CppClassName, javaPath, minSDK, nullptr) //============================================================================== #define DECLARE_JNI_CLASS(CppClassName, javaPath) \ @@ -1005,20 +1008,20 @@ public: const Array& /*grantResults*/) {} virtual void onActivityResult (int /*requestCode*/, int /*resultCode*/, LocalRef /*data*/) {} + /** @internal */ + static void onCreatedCallback (JNIEnv*, FragmentOverlay&, jobject obj); + /** @internal */ + static void onStartCallback (JNIEnv*, FragmentOverlay&); + /** @internal */ + static void onRequestPermissionsResultCallback (JNIEnv*, FragmentOverlay&, jint requestCode, jobjectArray jPermissions, jintArray jGrantResults); + /** @internal */ + static void onActivityResultCallback (JNIEnv*, FragmentOverlay&, jint requestCode, jint resultCode, jobject data); + protected: jobject getNativeHandle(); private: - GlobalRef native; - -public: - /* internal: do not use */ - static void onActivityResultNative (JNIEnv*, jobject, jlong, jint, jint, jobject); - static void onCreateNative (JNIEnv*, jobject, jlong, jobject); - static void onStartNative (JNIEnv*, jobject, jlong); - static void onRequestPermissionsResultNative (JNIEnv*, jobject, jlong, jint, - jobjectArray, jintArray); }; //============================================================================== @@ -1030,4 +1033,30 @@ void startAndroidActivityForResult (const LocalRef& intent, int request bool androidHasSystemFeature (const String& property); String audioManagerGetProperty (const String& property); +namespace detail +{ + +template +inline constexpr auto generatedCallbackImpl = + juce::toFnPtr (JNICALL [] (JNIEnv* env, jobject, jlong host, Args... args) -> Result + { + if (auto* object = reinterpret_cast (host)) + return Fn (env, *object, args...); + + return {}; + }); + +template +constexpr auto generateCallbackImpl (Result (*) (JNIEnv*, Class&, Args...)) { return generatedCallbackImpl; } + +template +constexpr auto generateCallbackImpl (Result (*) (JNIEnv*, const Class&, Args...)) { return generatedCallbackImpl; } + +} // namespace detail + +// Evaluates to a static function that forwards to the provided Fn, assuming that the +// 'host' argument points to an object on which it is valid to call Fn +template +inline constexpr auto generatedCallback = detail::generateCallbackImpl (Fn); + } // namespace juce diff --git a/modules/juce_core/native/juce_android_Network.cpp b/modules/juce_core/native/juce_android_Network.cpp index f5a3afa89b..c128cc6926 100644 --- a/modules/juce_core/native/juce_android_Network.cpp +++ b/modules/juce_core/native/juce_android_Network.cpp @@ -195,7 +195,7 @@ DECLARE_JNI_CLASS (StringBuffer, "java/lang/StringBuffer") METHOD (isExhausted, "isExhausted", "()Z") \ METHOD (setPosition, "setPosition", "(J)Z") \ -DECLARE_JNI_CLASS_WITH_BYTECODE (HTTPStream, "com/rmsl/juce/JuceHTTPStream", 16, javaJuceHttpStream, sizeof(javaJuceHttpStream)) +DECLARE_JNI_CLASS_WITH_BYTECODE (HTTPStream, "com/rmsl/juce/JuceHTTPStream", 16, javaJuceHttpStream) #undef JNI_CLASS_MEMBERS //============================================================================== diff --git a/modules/juce_core/native/juce_mac_ObjCHelpers.h b/modules/juce_core/native/juce_mac_ObjCHelpers.h index be62813a8b..de20b86a18 100644 --- a/modules/juce_core/native/juce_mac_ObjCHelpers.h +++ b/modules/juce_core/native/juce_mac_ObjCHelpers.h @@ -342,15 +342,6 @@ namespace detail { return joinCompileTimeStr (v, makeCompileTimeStr (others...)); } - - template - static constexpr auto toFnPtr (Functor functor, Return (Functor::*) (Args...) const) - { - return static_cast (functor); - } - - template - static constexpr auto toFnPtr (Functor functor) { return toFnPtr (functor, &Functor::operator()); } } // namespace detail //============================================================================== @@ -396,7 +387,7 @@ struct ObjCClass } template - void addMethod (SEL selector, Fn callbackFn) { addMethod (selector, detail::toFnPtr (callbackFn)); } + void addMethod (SEL selector, Fn callbackFn) { addMethod (selector, toFnPtr (callbackFn)); } template void addMethod (SEL selector, Result (*callbackFn) (id, SEL, Args...)) diff --git a/modules/juce_gui_basics/juce_gui_basics.cpp b/modules/juce_gui_basics/juce_gui_basics.cpp index 4ba1716655..fa1761a68c 100644 --- a/modules/juce_gui_basics/juce_gui_basics.cpp +++ b/modules/juce_gui_basics/juce_gui_basics.cpp @@ -336,6 +336,28 @@ namespace juce #include "native/juce_linux_FileChooser.cpp" #elif JUCE_ANDROID + +namespace juce +{ +static jobject makeAndroidRect (Rectangle r) +{ + return getEnv()->NewObject (AndroidRect, + AndroidRect.constructor, + r.getX(), + r.getY(), + r.getRight(), + r.getBottom()); +} + +static jobject makeAndroidPoint (Point p) +{ + return getEnv()->NewObject (AndroidPoint, + AndroidPoint.create, + p.getX(), + p.getY()); +} +} // namespace juce + #include "juce_core/files/juce_common_MimeTypes.h" #include "native/accessibility/juce_android_Accessibility.cpp" #include "native/juce_android_Windowing.cpp" diff --git a/modules/juce_gui_basics/keyboard/juce_TextInputTarget.h b/modules/juce_gui_basics/keyboard/juce_TextInputTarget.h index 63cb25ee60..fe5ac1a300 100644 --- a/modules/juce_gui_basics/keyboard/juce_TextInputTarget.h +++ b/modules/juce_gui_basics/keyboard/juce_TextInputTarget.h @@ -26,7 +26,6 @@ namespace juce { -//============================================================================== /** An abstract base class which can be implemented by components that function as text editors. diff --git a/modules/juce_gui_basics/native/accessibility/juce_android_Accessibility.cpp b/modules/juce_gui_basics/native/accessibility/juce_android_Accessibility.cpp index 1ac5ed6705..b6b2dee71c 100644 --- a/modules/juce_gui_basics/native/accessibility/juce_android_Accessibility.cpp +++ b/modules/juce_gui_basics/native/accessibility/juce_android_Accessibility.cpp @@ -297,21 +297,13 @@ public: { const auto scale = Desktop::getInstance().getDisplays().getPrimaryDisplay()->scale; - const auto screenBounds = accessibilityHandler.getComponent().getScreenBounds() * scale; + LocalRef screenBounds (makeAndroidRect (accessibilityHandler.getComponent().getScreenBounds() * scale)); - LocalRef rect (env->NewObject (AndroidRect, AndroidRect.constructor, - screenBounds.getX(), screenBounds.getY(), - screenBounds.getRight(), screenBounds.getBottom())); + env->CallVoidMethod (info, AndroidAccessibilityNodeInfo.setBoundsInScreen, screenBounds.get()); - env->CallVoidMethod (info, AndroidAccessibilityNodeInfo.setBoundsInScreen, rect.get()); + LocalRef boundsInParent (makeAndroidRect (accessibilityHandler.getComponent().getBoundsInParent() * scale)); - const auto boundsInParent = accessibilityHandler.getComponent().getBoundsInParent() * scale; - - rect = LocalRef (env->NewObject (AndroidRect, AndroidRect.constructor, - boundsInParent.getX(), boundsInParent.getY(), - boundsInParent.getRight(), boundsInParent.getBottom())); - - env->CallVoidMethod (info, AndroidAccessibilityNodeInfo.setBoundsInParent, rect.get()); + env->CallVoidMethod (info, AndroidAccessibilityNodeInfo.setBoundsInParent, boundsInParent.get()); } const auto state = accessibilityHandler.getCurrentState(); diff --git a/modules/juce_gui_basics/native/java/app/com/rmsl/juce/ComponentPeerView.java b/modules/juce_gui_basics/native/java/app/com/rmsl/juce/ComponentPeerView.java index 48ae16e2c2..9a82e2c19b 100644 --- a/modules/juce_gui_basics/native/java/app/com/rmsl/juce/ComponentPeerView.java +++ b/modules/juce_gui_basics/native/java/app/com/rmsl/juce/ComponentPeerView.java @@ -32,9 +32,19 @@ import android.graphics.Canvas; import android.graphics.ColorMatrix; import android.graphics.ColorMatrixColorFilter; import android.graphics.Paint; +import android.graphics.Point; import android.graphics.Rect; +import android.os.Build; +import android.text.Selection; +import android.text.SpanWatcher; +import android.text.Spannable; +import android.text.Spanned; +import android.text.TextWatcher; +import android.util.Pair; import android.os.Bundle; +import android.text.Editable; import android.text.InputType; +import android.text.SpannableStringBuilder; import android.view.Choreographer; import android.view.KeyEvent; import android.view.MotionEvent; @@ -51,6 +61,7 @@ import android.view.inputmethod.InputMethodManager; import java.lang.reflect.Method; import java.util.ArrayList; + import java.util.List; public final class ComponentPeerView extends ViewGroup @@ -63,9 +74,10 @@ public final class ComponentPeerView extends ViewGroup if (Application.class.isInstance (context)) { ((Application) context).registerActivityLifecycleCallbacks (this); - } else + } + else { - ((Application) context.getApplicationContext ()).registerActivityLifecycleCallbacks (this); + ((Application) context.getApplicationContext()).registerActivityLifecycleCallbacks (this); } this.host = host; @@ -77,7 +89,7 @@ public final class ComponentPeerView extends ViewGroup setOnFocusChangeListener (this); // swap red and blue colours to match internal opengl texture format - ColorMatrix colorMatrix = new ColorMatrix (); + ColorMatrix colorMatrix = new ColorMatrix(); float[] colorTransform = {0, 0, 1.0f, 0, 0, 0, 1.0f, 0, 0, 0, @@ -91,10 +103,12 @@ public final class ComponentPeerView extends ViewGroup try { - method = getClass ().getMethod ("setLayerType", int.class, Paint.class); - } catch (SecurityException e) + method = getClass().getMethod ("setLayerType", int.class, Paint.class); + } + catch (SecurityException e) { - } catch (NoSuchMethodException e) + } + catch (NoSuchMethodException e) { } @@ -104,11 +118,14 @@ public final class ComponentPeerView extends ViewGroup { int layerTypeNone = 0; method.invoke (this, layerTypeNone, null); - } catch (java.lang.IllegalArgumentException e) + } + catch (java.lang.IllegalArgumentException e) { - } catch (java.lang.IllegalAccessException e) + } + catch (java.lang.IllegalAccessException e) { - } catch (java.lang.reflect.InvocationTargetException e) + } + catch (java.lang.reflect.InvocationTargetException e) { } } @@ -116,7 +133,7 @@ public final class ComponentPeerView extends ViewGroup Choreographer.getInstance().postFrameCallback (this); } - public void clear () + public void clear() { host = 0; } @@ -147,14 +164,14 @@ public final class ComponentPeerView extends ViewGroup } @Override - public boolean isOpaque () + public boolean isOpaque() { return opaque; } private final boolean opaque; private long host; - private final Paint paint = new Paint (); + private final Paint paint = new Paint(); //============================================================================== private native void handleMouseDown (long host, int index, float x, float y, long time); @@ -168,25 +185,25 @@ public final class ComponentPeerView extends ViewGroup if (host == 0) return false; - int action = event.getAction (); - long time = event.getEventTime (); + int action = event.getAction(); + long time = event.getEventTime(); switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: - handleMouseDown (host, event.getPointerId (0), event.getRawX (), event.getRawY (), time); + handleMouseDown (host, event.getPointerId (0), event.getRawX(), event.getRawY(), time); return true; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: - handleMouseUp (host, event.getPointerId (0), event.getRawX (), event.getRawY (), time); + handleMouseUp (host, event.getPointerId (0), event.getRawX(), event.getRawY(), time); return true; case MotionEvent.ACTION_MOVE: { - handleMouseDrag (host, event.getPointerId (0), event.getRawX (), event.getRawY (), time); + handleMouseDrag (host, event.getPointerId (0), event.getRawX(), event.getRawY(), time); - int n = event.getPointerCount (); + int n = event.getPointerCount(); if (n > 1) { @@ -206,8 +223,9 @@ public final class ComponentPeerView extends ViewGroup if (i == 0) { - handleMouseUp (host, event.getPointerId (0), event.getRawX (), event.getRawY (), time); - } else + handleMouseUp (host, event.getPointerId (0), event.getRawX(), event.getRawY(), time); + } + else { int point[] = new int[2]; getLocationOnScreen (point); @@ -223,8 +241,9 @@ public final class ComponentPeerView extends ViewGroup if (i == 0) { - handleMouseDown (host, event.getPointerId (0), event.getRawX (), event.getRawY (), time); - } else + handleMouseDown (host, event.getPointerId (0), event.getRawX(), event.getRawY(), time); + } + else { int point[] = new int[2]; getLocationOnScreen (point); @@ -253,32 +272,132 @@ public final class ComponentPeerView extends ViewGroup return false; } + //============================================================================== + public static class TextInputTarget + { + public TextInputTarget (long owner) { host = owner; } + + public boolean isTextInputActive() { return ComponentPeerView.textInputTargetIsTextInputActive (host); } + public int getHighlightedRegionBegin() { return ComponentPeerView.textInputTargetGetHighlightedRegionBegin (host); } + public int getHighlightedRegionEnd() { return ComponentPeerView.textInputTargetGetHighlightedRegionEnd (host); } + public void setHighlightedRegion (int b, int e) { ComponentPeerView.textInputTargetSetHighlightedRegion (host, b, e); } + public String getTextInRange (int b, int e) { return ComponentPeerView.textInputTargetGetTextInRange (host, b, e); } + public void insertTextAtCaret (String text) { ComponentPeerView.textInputTargetInsertTextAtCaret (host, text); } + public int getCaretPosition() { return ComponentPeerView.textInputTargetGetCaretPosition (host); } + public int getTotalNumChars() { return ComponentPeerView.textInputTargetGetTotalNumChars (host); } + public int getCharIndexForPoint (Point point) { return ComponentPeerView.textInputTargetGetCharIndexForPoint (host, point); } + public int getKeyboardType() { return ComponentPeerView.textInputTargetGetKeyboardType (host); } + public void setTemporaryUnderlining (List> list) { ComponentPeerView.textInputTargetSetTemporaryUnderlining (host, list); } + + //============================================================================== + private final long host; + } + + private native static boolean textInputTargetIsTextInputActive (long host); + private native static int textInputTargetGetHighlightedRegionBegin (long host); + private native static int textInputTargetGetHighlightedRegionEnd (long host); + private native static void textInputTargetSetHighlightedRegion (long host, int begin, int end); + private native static String textInputTargetGetTextInRange (long host, int begin, int end); + private native static void textInputTargetInsertTextAtCaret (long host, String text); + private native static int textInputTargetGetCaretPosition (long host); + private native static int textInputTargetGetTotalNumChars (long host); + private native static int textInputTargetGetCharIndexForPoint (long host, Point point); + private native static int textInputTargetGetKeyboardType (long host); + private native static void textInputTargetSetTemporaryUnderlining (long host, List> list); + + private native long getFocusedTextInputTargetPointer (long host); + + private TextInputTarget getFocusedTextInputTarget (long host) + { + final long ptr = getFocusedTextInputTargetPointer (host); + return ptr != 0 ? new TextInputTarget (ptr) : null; + } + //============================================================================== private native void handleKeyDown (long host, int keycode, int textchar, int kbFlags); private native void handleKeyUp (long host, int keycode, int textchar); private native void handleBackButton (long host); private native void handleKeyboardHidden (long host); - public void showKeyboard (String type) + private static int getInputTypeForJuceVirtualKeyboardType (int type) { - InputMethodManager imm = (InputMethodManager) getContext ().getSystemService (Context.INPUT_METHOD_SERVICE); - - if (imm != null) + switch (type) { - if (type.length () > 0) - { - imm.showSoftInput (this, android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT); - imm.setInputMethod (getWindowToken (), type); - keyboardDismissListener.startListening (); - } else - { - imm.hideSoftInputFromWindow (getWindowToken (), 0); - keyboardDismissListener.stopListening (); - } + case 0: // textKeyboard + return InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_VARIATION_NORMAL + | InputType.TYPE_TEXT_FLAG_MULTI_LINE + | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS; + case 1: // numericKeyboard + return InputType.TYPE_CLASS_NUMBER + | InputType.TYPE_NUMBER_VARIATION_NORMAL; + case 2: // decimalKeyboard + return InputType.TYPE_CLASS_NUMBER + | InputType.TYPE_NUMBER_VARIATION_NORMAL + | InputType.TYPE_NUMBER_FLAG_DECIMAL; + case 3: // urlKeyboard + return InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_VARIATION_URI + | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS; + case 4: // emailAddressKeyboard + return InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS + | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS; + case 5: // phoneNumberKeyboard + return InputType.TYPE_CLASS_PHONE; + case 6: // passwordKeyboard + return InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_VARIATION_PASSWORD + | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS; } + + return 0; + } + + InputMethodManager getInputMethodManager() + { + return (InputMethodManager) getContext().getSystemService (Context.INPUT_METHOD_SERVICE); + } + + public void closeInputMethodContext() + { + InputMethodManager imm = getInputMethodManager(); + + if (imm == null) + return; + + if (cachedConnection != null) + cachedConnection.closeConnection(); + + imm.restartInput (this); + } + + public void showKeyboard (int virtualKeyboardType, int selectionStart, int selectionEnd) + { + InputMethodManager imm = getInputMethodManager(); + + if (imm == null) + return; + + // restartingInput causes a call back to onCreateInputConnection, where we'll pick + // up the correct keyboard characteristics to use for the focused TextInputTarget. + imm.restartInput (this); + imm.showSoftInput (this, 0); + keyboardDismissListener.startListening(); } - public void backButtonPressed () + public void hideKeyboard() + { + InputMethodManager imm = getInputMethodManager(); + + if (imm == null) + return; + + imm.hideSoftInputFromWindow (getWindowToken(), 0); + keyboardDismissListener.stopListening(); + } + + public void backButtonPressed() { if (host == 0) return; @@ -292,6 +411,11 @@ public final class ComponentPeerView extends ViewGroup if (host == 0) return false; + // The key event may move the cursor, or in some cases it might enter characters (e.g. + // digits). In this case, we need to reset the IME so that it's aware of the new contents + // of the TextInputTarget. + closeInputMethodContext(); + switch (keyCode) { case KeyEvent.KEYCODE_VOLUME_UP: @@ -299,7 +423,7 @@ public final class ComponentPeerView extends ViewGroup return super.onKeyDown (keyCode, event); case KeyEvent.KEYCODE_BACK: { - backButtonPressed (); + backButtonPressed(); return true; } @@ -309,8 +433,9 @@ public final class ComponentPeerView extends ViewGroup handleKeyDown (host, keyCode, - event.getUnicodeChar (), - event.getMetaState ()); + event.getUnicodeChar(), + event.getMetaState()); + return true; } @@ -320,7 +445,7 @@ public final class ComponentPeerView extends ViewGroup if (host == 0) return false; - handleKeyUp (host, keyCode, event.getUnicodeChar ()); + handleKeyUp (host, keyCode, event.getUnicodeChar()); return true; } @@ -330,17 +455,17 @@ public final class ComponentPeerView extends ViewGroup if (host == 0) return false; - if (keyCode != KeyEvent.KEYCODE_UNKNOWN || event.getAction () != KeyEvent.ACTION_MULTIPLE) + if (keyCode != KeyEvent.KEYCODE_UNKNOWN || (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q && event.getAction() != KeyEvent.ACTION_MULTIPLE)) return super.onKeyMultiple (keyCode, count, event); - if (event.getCharacters () != null) + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q && event.getCharacters() != null) { - int utf8Char = event.getCharacters ().codePointAt (0); + int utf8Char = event.getCharacters().codePointAt (0); handleKeyDown (host, keyCode, utf8Char, - event.getMetaState ()); + event.getMetaState()); return true; } @@ -355,39 +480,40 @@ public final class ComponentPeerView extends ViewGroup view = viewToUse; } - private void startListening () + private void startListening() { - view.getViewTreeObserver ().addOnGlobalLayoutListener (viewTreeObserver); + view.getViewTreeObserver().addOnGlobalLayoutListener (viewTreeObserver); } - private void stopListening () + private void stopListening() { - view.getViewTreeObserver ().removeGlobalOnLayoutListener (viewTreeObserver); + view.getViewTreeObserver().removeOnGlobalLayoutListener (viewTreeObserver); } private class TreeObserver implements ViewTreeObserver.OnGlobalLayoutListener { - TreeObserver () + TreeObserver() { keyboardShown = false; } @Override - public void onGlobalLayout () + public void onGlobalLayout() { - Rect r = new Rect (); + Rect r = new Rect(); - View parentView = getRootView (); + View parentView = getRootView(); int diff; if (parentView == null) { getWindowVisibleDisplayFrame (r); - diff = getHeight () - (r.bottom - r.top); - } else + diff = getHeight() - (r.bottom - r.top); + } + else { parentView.getWindowVisibleDisplayFrame (r); - diff = parentView.getHeight () - (r.bottom - r.top); + diff = parentView.getHeight() - (r.bottom - r.top); } // Arbitrary threshold, surely keyboard would take more than 20 pix. @@ -397,7 +523,7 @@ public final class ComponentPeerView extends ViewGroup handleKeyboardHidden (view.host); } - if (!keyboardShown && diff > 20) + if (! keyboardShown && diff > 20) keyboardShown = true; } @@ -405,26 +531,219 @@ public final class ComponentPeerView extends ViewGroup } private final ComponentPeerView view; - private final TreeObserver viewTreeObserver = new TreeObserver (); + private final TreeObserver viewTreeObserver = new TreeObserver(); } private final KeyboardDismissListener keyboardDismissListener = new KeyboardDismissListener (this); - // this is here to make keyboard entry work on a Galaxy Tab2 10.1 + //============================================================================== + // This implementation is quite similar to the ChangeListener in Android's built-in TextView. + private static final class ChangeWatcher implements SpanWatcher, TextWatcher + { + public ChangeWatcher (ComponentPeerView viewIn, Editable editableIn, TextInputTarget targetIn) + { + view = viewIn; + editable = editableIn; + target = targetIn; + + updateEditableSelectionFromTarget (editable, target); + } + + @Override + public void onSpanAdded (Spannable text, Object what, int start, int end) + { + updateTargetRangesFromEditable (editable, target); + } + + @Override + public void onSpanRemoved (Spannable text, Object what, int start, int end) + { + updateTargetRangesFromEditable (editable, target); + } + + @Override + public void onSpanChanged (Spannable text, Object what, int ostart, int oend, int nstart, int nend) + { + updateTargetRangesFromEditable (editable, target); + } + + @Override + public void afterTextChanged (Editable s) + { + } + + @Override + public void beforeTextChanged (CharSequence s, int start, int count, int after) + { + contentsBeforeChange = s.toString(); + } + + @Override + public void onTextChanged (CharSequence s, int start, int before, int count) + { + if (editable != s || contentsBeforeChange == null) + return; + + final String newText = s.subSequence (start, start + count).toString(); + + int code = 0; + + if (newText.endsWith ("\n") || newText.endsWith ("\r")) + code = KeyEvent.KEYCODE_ENTER; + + if (newText.endsWith ("\t")) + code = KeyEvent.KEYCODE_TAB; + + target.setHighlightedRegion (contentsBeforeChange.codePointCount (0, start), + contentsBeforeChange.codePointCount (0, start + before)); + target.insertTextAtCaret (code != 0 ? newText.substring (0, newText.length() - 1) + : newText); + + // Treating return/tab as individual keypresses rather than part of the composition + // sequence allows TextEditor onReturn and onTab to work as expected. + if (code != 0) + view.onKeyDown (code, new KeyEvent (KeyEvent.ACTION_DOWN, code)); + + updateTargetRangesFromEditable (editable, target); + contentsBeforeChange = null; + } + + private static void updateEditableSelectionFromTarget (Editable editable, TextInputTarget text) + { + final int start = text.getHighlightedRegionBegin(); + final int end = text.getHighlightedRegionEnd(); + + if (start < 0 || end < 0) + return; + + final String string = editable.toString(); + Selection.setSelection (editable, + string.offsetByCodePoints (0, start), + string.offsetByCodePoints (0, end)); + } + + private static void updateTargetSelectionFromEditable (Editable editable, TextInputTarget target) + { + final int start = Selection.getSelectionStart (editable); + final int end = Selection.getSelectionEnd (editable); + + if (start < 0 || end < 0) + return; + + final String string = editable.toString(); + target.setHighlightedRegion (string.codePointCount (0, start), + string.codePointCount (0, end)); + } + + private static List> getUnderlinedRanges (Editable editable) + { + final int start = BaseInputConnection.getComposingSpanStart (editable); + final int end = BaseInputConnection.getComposingSpanEnd (editable); + + if (start < 0 || end < 0) + return null; + + final String string = editable.toString(); + + final ArrayList> pairs = new ArrayList<>(); + pairs.add (new Pair<> (string.codePointCount (0, start), string.codePointCount (0, end))); + return pairs; + } + + private static void updateTargetCompositionRangesFromEditable (Editable editable, TextInputTarget target) + { + target.setTemporaryUnderlining (getUnderlinedRanges (editable)); + } + + private static void updateTargetRangesFromEditable (Editable editable, TextInputTarget target) + { + updateTargetSelectionFromEditable (editable, target); + updateTargetCompositionRangesFromEditable (editable, target); + } + + private final ComponentPeerView view; + private final TextInputTarget target; + private final Editable editable; + private String contentsBeforeChange; + } + + private static final class Connection extends BaseInputConnection + { + Connection (ComponentPeerView viewIn, boolean fullEditor, TextInputTarget targetIn) + { + super (viewIn, fullEditor); + view = viewIn; + target = targetIn; + } + + @Override + public Editable getEditable() + { + if (cached != null) + return cached; + + if (target == null) + return cached = super.getEditable(); + + int length = target.getTotalNumChars(); + String initialText = target.getTextInRange (0, length); + cached = new SpannableStringBuilder (initialText); + // Span the entire range of text, so that we pick up changes at any location. + // Use cached.length rather than target.getTotalNumChars here, because this + // range is in UTF-16 code units, rather than code points. + changeWatcher = new ChangeWatcher (view, cached, target); + cached.setSpan (changeWatcher, 0, cached.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); + return cached; + } + + /** Call this to stop listening for selection/composition updates. + + We do this before closing the current input method context (e.g. when the user + taps on a text view to move the cursor), because otherwise the input system + might send another round of notifications *during* the restartInput call, after we've + requested that the input session should end. + */ + @Override + public void closeConnection() + { + if (cached != null && changeWatcher != null) + cached.removeSpan (changeWatcher); + + cached = null; + target = null; + + super.closeConnection(); + } + + private ComponentPeerView view; + private TextInputTarget target; + private Editable cached; + private ChangeWatcher changeWatcher; + } + @Override public InputConnection onCreateInputConnection (EditorInfo outAttrs) { + TextInputTarget focused = getFocusedTextInputTarget (host); + outAttrs.actionLabel = ""; outAttrs.hintText = ""; outAttrs.initialCapsMode = 0; - outAttrs.initialSelEnd = outAttrs.initialSelStart = -1; + outAttrs.initialSelStart = focused != null ? focused.getHighlightedRegionBegin() : -1; + outAttrs.initialSelEnd = focused != null ? focused.getHighlightedRegionEnd() : -1; outAttrs.label = ""; - outAttrs.imeOptions = EditorInfo.IME_ACTION_DONE | EditorInfo.IME_FLAG_NO_EXTRACT_UI; - outAttrs.inputType = InputType.TYPE_NULL; - - return new BaseInputConnection (this, false); + outAttrs.imeOptions = EditorInfo.IME_ACTION_UNSPECIFIED + | EditorInfo.IME_FLAG_NO_EXTRACT_UI + | EditorInfo.IME_FLAG_NO_ENTER_ACTION; + outAttrs.inputType = focused != null ? getInputTypeForJuceVirtualKeyboardType (focused.getKeyboardType()) + : 0; + + cachedConnection = new Connection (this, true, focused); + return cachedConnection; } + private Connection cachedConnection; + //============================================================================== @Override protected void onSizeChanged (int w, int h, int oldw, int oldh) @@ -463,11 +782,13 @@ public final class ComponentPeerView extends ViewGroup Method systemUIVisibilityMethod = null; try { - systemUIVisibilityMethod = this.getClass ().getMethod ("setSystemUiVisibility", int.class); - } catch (SecurityException e) + systemUIVisibilityMethod = this.getClass().getMethod ("setSystemUiVisibility", int.class); + } + catch (SecurityException e) { return; - } catch (NoSuchMethodException e) + } + catch (NoSuchMethodException e) { return; } @@ -476,18 +797,21 @@ public final class ComponentPeerView extends ViewGroup try { systemUIVisibilityMethod.invoke (this, visibility); - } catch (java.lang.IllegalArgumentException e) + } + catch (java.lang.IllegalArgumentException e) { - } catch (java.lang.IllegalAccessException e) + } + catch (java.lang.IllegalAccessException e) { - } catch (java.lang.reflect.InvocationTargetException e) + } + catch (java.lang.reflect.InvocationTargetException e) { } } - public boolean isVisible () + public boolean isVisible() { - return getVisibility () == VISIBLE; + return getVisibility() == VISIBLE; } public void setVisible (boolean b) @@ -572,11 +896,22 @@ public final class ComponentPeerView extends ViewGroup if (host == 0) return null; - final AccessibilityNodeInfo nodeInfo = AccessibilityNodeInfo.obtain (view, virtualViewId); + final AccessibilityNodeInfo nodeInfo; + + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) + { + nodeInfo = new AccessibilityNodeInfo (view, virtualViewId); + } + else + { + nodeInfo = AccessibilityNodeInfo.obtain (view, virtualViewId); + } if (! populateAccessibilityNodeInfo (host, virtualViewId, nodeInfo)) { - nodeInfo.recycle(); + if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.R) + nodeInfo.recycle(); + return null; } @@ -617,10 +952,10 @@ public final class ComponentPeerView extends ViewGroup } private final JuceAccessibilityNodeProvider nodeProvider = new JuceAccessibilityNodeProvider (this); - private final AccessibilityManager accessibilityManager = (AccessibilityManager) getContext ().getSystemService (Context.ACCESSIBILITY_SERVICE); + private final AccessibilityManager accessibilityManager = (AccessibilityManager) getContext().getSystemService (Context.ACCESSIBILITY_SERVICE); @Override - public AccessibilityNodeProvider getAccessibilityNodeProvider () + public AccessibilityNodeProvider getAccessibilityNodeProvider() { return nodeProvider; } diff --git a/modules/juce_gui_basics/native/java/app/com/rmsl/juce/JuceContentProviderFileObserver.java b/modules/juce_gui_basics/native/java/app/com/rmsl/juce/JuceContentProviderFileObserver.java index a89dc646c1..61f9a070e8 100644 --- a/modules/juce_gui_basics/native/java/app/com/rmsl/juce/JuceContentProviderFileObserver.java +++ b/modules/juce_gui_basics/native/java/app/com/rmsl/juce/JuceContentProviderFileObserver.java @@ -34,7 +34,6 @@ public final class JuceContentProviderFileObserver extends FileObserver public JuceContentProviderFileObserver (long hostToUse, String path, int mask) { super (path, mask); - host = hostToUse; } diff --git a/modules/juce_gui_basics/native/juce_android_ContentSharer.cpp b/modules/juce_gui_basics/native/juce_android_ContentSharer.cpp index fd447ba705..9330d28dec 100644 --- a/modules/juce_gui_basics/native/juce_android_ContentSharer.cpp +++ b/modules/juce_gui_basics/native/juce_android_ContentSharer.cpp @@ -101,7 +101,7 @@ public: class Owner { public: - virtual ~Owner() {} + virtual ~Owner() = default; virtual void cursorClosed (const AndroidContentSharerCursor&) = 0; }; @@ -121,9 +121,9 @@ public: jobject getNativeCursor() { return cursor.get(); } - void cursorClosed() + static void cursorClosed (JNIEnv*, AndroidContentSharerCursor& t) { - MessageManager::callAsync ([this] { owner.cursorClosed (*this); }); + MessageManager::callAsync ([&t] { t.owner.cursorClosed (t); }); } void addRow (LocalRef& values) @@ -141,20 +141,12 @@ private: #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ METHOD (addRow, "addRow", "([Ljava/lang/Object;)V") \ METHOD (constructor, "", "(J[Ljava/lang/String;)V") \ - CALLBACK (contentSharerCursorClosed, "contentSharerCursorClosed", "(J)V") \ + CALLBACK (generatedCallback<&AndroidContentSharerCursor::cursorClosed>, "contentSharerCursorClosed", "(J)V") \ - DECLARE_JNI_CLASS_WITH_BYTECODE (JuceContentProviderCursor, "com/rmsl/juce/JuceContentProviderCursor", 16, javaJuceContentProviderCursor, sizeof (javaJuceContentProviderCursor)) + DECLARE_JNI_CLASS_WITH_BYTECODE (JuceContentProviderCursor, "com/rmsl/juce/JuceContentProviderCursor", 16, javaJuceContentProviderCursor) #undef JNI_CLASS_MEMBERS - - static void JNICALL contentSharerCursorClosed (JNIEnv*, jobject, jlong host) - { - if (auto* myself = reinterpret_cast (host)) - myself->cursorClosed(); - } }; -AndroidContentSharerCursor::JuceContentProviderCursor_Class AndroidContentSharerCursor::JuceContentProviderCursor; - //============================================================================== class AndroidContentSharerFileObserver { @@ -228,20 +220,17 @@ private: METHOD (constructor, "", "(JLjava/lang/String;I)V") \ METHOD (startWatching, "startWatching", "()V") \ METHOD (stopWatching, "stopWatching", "()V") \ - CALLBACK (contentSharerFileObserverEvent, "contentSharerFileObserverEvent", "(JILjava/lang/String;)V") \ + CALLBACK (generatedCallback<&AndroidContentSharerFileObserver::onFileEventCallback>, "contentSharerFileObserverEvent", "(JILjava/lang/String;)V") \ - DECLARE_JNI_CLASS_WITH_BYTECODE (JuceContentProviderFileObserver, "com/rmsl/juce/JuceContentProviderFileObserver", 16, javaJuceContentProviderFileObserver, sizeof (javaJuceContentProviderFileObserver)) + DECLARE_JNI_CLASS_WITH_BYTECODE (JuceContentProviderFileObserver, "com/rmsl/juce/JuceContentProviderFileObserver", 16, javaJuceContentProviderFileObserver) #undef JNI_CLASS_MEMBERS - static void JNICALL contentSharerFileObserverEvent (JNIEnv*, jobject /*fileObserver*/, jlong host, int event, jstring path) + static void onFileEventCallback (JNIEnv*, AndroidContentSharerFileObserver& t, jint event, jstring path) { - if (auto* myself = reinterpret_cast (host)) - myself->onFileEvent (event, LocalRef (path)); + t.onFileEvent (event, LocalRef (path)); } }; -AndroidContentSharerFileObserver::JuceContentProviderFileObserver_Class AndroidContentSharerFileObserver::JuceContentProviderFileObserver; - //============================================================================== class AndroidContentSharerPrepareFilesThread : private Thread { @@ -891,6 +880,4 @@ ContentSharer::Pimpl* ContentSharer::createPimpl() return new ContentSharerNativeImpl (*this); } -ContentSharer::ContentSharerNativeImpl::JuceSharingContentProvider_Class ContentSharer::ContentSharerNativeImpl::JuceSharingContentProvider; - } // namespace juce diff --git a/modules/juce_gui_basics/native/juce_android_Windowing.cpp b/modules/juce_gui_basics/native/juce_android_Windowing.cpp index ab149c140e..1fadc42a53 100644 --- a/modules/juce_gui_basics/native/juce_android_Windowing.cpp +++ b/modules/juce_gui_basics/native/juce_android_Windowing.cpp @@ -25,109 +25,768 @@ namespace juce { + // This byte-code is generated from native/java/com/rmsl/juce/ComponentPeerView.java with min sdk version 16 // See juce_core/native/java/README.txt on how to generate this byte-code. -static const uint8 javaComponentPeerView[] = -{ 31,139,8,8,136,16,72,99,0,3,74,97,118,97,68,101,120,66,121,116,101,67,111,100,101,46,100,101,120,0,165,155,11,124,220,85,149,199,207,253,255,255,51,147,76,38,201,100,242,108,155,180,147,52,208,36,52,201,36,233,35,33,45,180,77,90,154,52,109,98,51,13,52, - 97,23,38,201,36,153,118,242,159,233,204,36,77,4,165,101,89,169,110,113,1,43,139,80,21,177,160,235,11,84,240,193,178,187,40,42,174,136,128,143,69,87,101,169,139,90,21,92,20,20,151,5,187,191,115,239,157,201,164,15,89,119,147,207,119,206,185,231,62,254, - 247,113,238,185,247,159,199,120,120,206,29,104,91,75,23,61,245,207,167,202,99,239,248,192,190,187,191,252,216,84,255,10,199,175,90,191,95,180,235,111,191,112,251,209,245,68,113,34,154,27,90,227,35,253,245,240,58,162,181,66,217,59,65,183,131,104,27,100, - 192,73,180,156,203,230,18,93,15,57,229,38,114,112,186,128,40,85,71,84,81,72,244,53,20,248,58,120,28,124,27,124,15,252,24,156,4,191,1,111,128,194,21,68,171,64,19,104,1,107,193,70,176,9,116,131,237,96,7,232,7,54,184,17,188,11,188,27,220,10,110,3,119,130, - 187,192,61,224,31,193,203,160,192,79,84,15,186,193,56,184,1,220,7,254,5,252,4,188,10,242,171,137,58,192,229,32,14,142,130,207,131,111,130,159,129,229,53,68,151,130,4,184,23,60,11,10,86,162,143,32,4,110,6,79,131,37,181,68,65,112,16,188,31,124,9,156,4, - 214,5,68,43,193,70,48,0,82,224,14,112,31,248,54,248,25,112,92,136,250,96,59,24,7,215,128,163,224,3,224,4,248,12,120,16,60,10,158,6,223,3,63,2,207,129,83,224,215,224,119,224,53,64,171,208,30,200,5,5,160,24,84,128,229,160,6,52,128,70,208,10,218,193,70, - 208,13,122,193,46,48,8,70,192,40,152,0,251,192,219,193,123,192,7,193,199,193,231,193,163,224,73,240,67,240,115,240,50,56,13,60,88,247,101,160,5,116,128,109,96,0,236,7,179,96,30,28,5,199,192,113,112,2,124,18,60,0,190,4,190,5,158,5,191,7,142,122,140,1, - 148,130,86,208,14,54,131,110,176,3,76,131,57,112,29,184,9,220,1,62,6,30,3,63,5,47,1,209,128,241,131,85,160,5,108,4,59,192,16,216,15,230,192,77,224,78,112,47,248,60,248,42,248,22,120,6,60,15,126,15,156,23,97,92,160,1,92,12,174,0,127,9,198,193,36,56,12, - 110,5,39,192,231,192,87,193,119,193,73,240,42,200,89,141,53,6,117,96,45,232,5,65,48,13,14,130,183,129,67,224,40,184,5,220,13,62,13,190,12,158,0,63,4,63,5,47,130,255,2,102,35,214,20,212,131,86,176,3,12,131,16,136,131,89,240,118,240,14,240,78,240,183,224, - 118,112,55,184,31,124,1,252,19,248,10,120,6,188,0,254,8,138,154,176,15,193,102,16,4,211,96,6,220,0,142,129,187,193,39,193,195,224,171,224,73,240,44,120,1,188,2,222,0,174,102,172,27,88,10,234,65,0,244,131,81,16,6,54,184,21,220,9,238,1,143,130,111,128, - 39,193,191,131,23,129,51,64,84,6,106,193,37,96,15,72,128,235,192,187,193,29,224,99,224,11,224,49,240,12,248,25,160,22,212,5,30,80,2,42,65,13,88,5,26,193,122,112,49,216,12,122,193,0,8,129,40,120,59,184,9,188,15,28,7,31,4,31,6,31,1,31,7,247,129,207,130, - 60,60,6,33,142,138,64,37,168,34,21,7,17,114,8,33,133,16,54,8,97,130,16,22,8,33,128,176,197,73,111,77,130,91,19,220,146,224,82,4,183,32,44,37,97,218,9,211,70,205,28,83,213,16,168,21,180,129,53,96,45,64,8,38,132,102,106,7,29,224,98,29,139,55,128,141,224, - 18,112,41,216,4,54,131,45,160,139,99,53,216,74,42,94,95,6,182,131,30,208,11,118,128,62,176,11,188,5,140,3,27,196,72,197,250,3,164,198,154,254,242,104,233,173,82,227,23,233,180,214,217,206,115,98,104,187,79,235,21,176,151,66,58,181,189,2,228,240,92,105, - 123,129,182,151,234,182,210,122,73,150,94,174,245,50,176,68,63,107,137,214,235,116,59,75,179,218,231,53,9,84,41,157,215,162,93,151,169,207,106,103,181,110,167,92,235,155,170,84,27,172,111,135,190,76,175,203,128,110,135,245,43,116,59,1,221,14,151,225, - 181,186,90,247,135,215,107,170,74,205,231,90,93,38,168,117,126,214,30,173,199,161,15,105,157,159,123,185,214,175,133,126,133,214,143,66,223,171,245,219,161,15,107,253,4,244,17,173,127,2,250,149,90,255,2,244,191,208,250,35,208,175,210,250,215,179,236, - 79,101,233,223,135,30,210,250,115,89,246,23,178,244,87,178,244,215,179,218,180,150,47,216,61,89,122,9,244,171,181,94,153,101,127,189,114,65,231,181,248,75,173,111,207,106,179,54,171,60,207,243,168,214,87,195,62,166,245,53,89,101,186,179,244,190,229,202, - 127,215,233,57,15,107,61,8,251,132,214,175,204,210,167,160,79,106,61,5,125,74,235,215,66,143,104,253,8,244,253,90,63,6,125,159,214,143,103,217,217,247,162,90,63,1,251,180,214,31,200,42,255,200,114,222,59,130,254,154,148,172,22,28,55,234,232,58,82,242, - 235,82,10,122,92,203,39,180,252,150,150,79,106,249,148,46,255,67,226,88,83,67,203,133,146,171,4,199,157,117,244,111,196,178,154,86,8,142,65,42,191,90,231,87,35,167,65,240,94,168,160,183,17,75,131,254,69,202,106,250,129,148,43,232,121,41,215,209,107,82, - 230,209,27,196,49,44,32,247,45,75,151,148,235,200,173,211,249,82,10,218,173,211,131,188,86,216,97,253,196,247,192,11,201,33,120,207,59,233,46,98,89,70,247,67,230,98,135,89,82,174,39,55,242,221,136,132,156,206,211,246,60,60,37,79,240,60,169,180,23,37, - 63,34,101,35,25,130,227,139,65,31,32,150,229,244,33,82,233,191,215,242,211,196,49,71,229,179,252,160,148,22,157,208,233,143,75,105,210,39,72,197,166,79,106,249,41,41,5,125,78,203,207,179,31,163,252,61,82,94,68,15,18,239,249,85,178,63,165,136,182,175, - 72,185,129,126,39,101,37,253,129,56,134,4,232,176,150,57,130,227,69,7,253,43,113,76,200,167,159,74,137,241,8,142,47,106,92,203,16,237,89,46,71,196,126,76,202,213,84,32,88,110,161,10,185,174,109,50,127,5,102,226,22,41,151,208,109,58,253,119,82,118,210, - 105,185,222,45,178,156,31,237,254,150,120,157,85,189,106,216,19,90,38,165,244,82,74,202,165,180,68,40,185,84,250,67,157,44,95,131,21,155,145,178,149,102,165,236,166,131,82,150,208,156,150,243,82,118,209,91,165,92,74,55,104,249,78,41,47,166,119,75,89, - 69,239,145,114,37,189,79,202,98,58,46,101,1,189,95,74,39,125,88,251,223,61,58,255,94,41,219,233,163,82,186,233,62,237,127,159,209,229,62,43,101,14,61,32,165,90,15,120,55,125,81,63,239,33,45,255,65,203,135,181,95,255,163,148,126,250,39,237,223,255,172, - 243,31,209,245,191,164,229,151,181,124,84,202,26,250,138,148,151,208,87,165,236,160,239,105,249,140,148,23,208,41,41,107,233,23,90,254,82,203,95,233,252,23,116,250,69,45,127,45,101,33,253,167,148,245,244,146,148,205,244,27,41,55,211,203,82,42,191,170, - 209,126,197,233,223,235,253,248,170,148,202,207,184,252,127,73,121,41,9,185,126,107,201,163,101,190,148,77,228,149,114,25,249,164,92,67,197,58,93,162,203,149,106,89,166,243,203,133,154,151,58,193,251,88,249,103,61,60,248,99,82,110,165,239,202,125,109, - 208,183,165,244,209,133,130,207,66,85,174,9,59,239,110,226,243,208,164,119,73,105,208,179,196,103,98,41,125,135,248,14,179,84,251,177,58,219,211,103,52,94,25,233,1,156,9,87,235,67,210,175,237,124,198,242,89,193,249,223,132,188,78,231,87,235,250,77,89, - 245,127,132,252,91,117,62,159,241,69,164,206,102,171,74,229,191,128,252,135,116,254,74,157,159,174,159,163,229,189,8,208,187,215,170,123,202,27,56,188,173,181,234,46,83,160,109,43,33,27,128,169,243,215,64,191,68,151,185,76,218,77,169,127,174,69,181,57, - 34,220,20,247,242,211,70,140,60,248,124,14,90,225,119,226,47,181,168,187,159,79,4,71,221,116,192,187,14,246,60,163,12,83,211,98,24,86,135,97,145,203,91,68,193,209,60,58,224,175,198,206,245,16,151,11,142,169,178,38,229,89,7,6,218,105,203,140,219,232,48, - 94,60,109,123,121,188,46,111,221,207,45,253,252,103,90,212,253,170,6,51,30,247,30,150,163,229,103,115,191,79,182,168,51,242,124,207,54,169,72,248,124,109,171,150,156,253,204,64,7,109,113,120,176,55,95,194,51,121,223,187,133,237,175,71,44,247,136,186, - 159,157,93,250,98,89,186,238,23,28,199,45,217,159,87,91,212,221,56,24,87,229,56,167,204,144,119,92,163,3,101,124,216,23,193,3,238,236,124,67,220,32,222,235,186,247,160,179,19,35,115,83,221,75,38,250,203,99,180,90,213,186,142,248,242,49,198,107,97,243, - 209,149,94,143,188,63,230,32,197,99,205,111,85,247,164,98,103,9,213,24,30,148,227,89,8,38,243,41,216,86,64,182,247,50,148,242,136,14,177,97,193,230,223,1,239,88,40,209,141,18,110,115,55,46,238,187,47,16,244,233,224,45,100,90,107,175,94,74,123,146,152, - 7,179,140,124,230,149,208,210,229,131,169,124,244,187,21,35,241,88,220,127,75,206,195,122,234,114,112,249,14,211,69,235,175,118,144,175,152,235,240,179,150,192,147,109,111,5,143,236,140,103,212,125,139,215,146,125,174,29,99,40,148,227,44,208,227,228, - 40,22,247,55,98,7,140,120,65,113,161,190,127,11,57,47,219,81,158,247,88,220,203,111,12,5,25,251,64,198,190,70,218,13,125,99,191,162,85,249,115,208,91,40,247,4,123,16,63,247,234,86,117,199,15,250,11,209,71,126,83,192,56,171,189,232,245,114,60,185,32,83, - 110,242,188,229,86,200,114,5,240,120,30,137,141,114,28,51,124,46,95,89,220,191,20,231,116,141,149,135,222,56,209,171,145,99,101,72,85,83,28,47,135,199,114,71,142,21,35,181,2,169,58,153,42,65,187,93,88,107,143,181,212,113,45,218,197,10,66,95,97,85,160, - 94,17,85,90,14,216,230,113,174,187,173,118,107,156,86,184,57,141,119,66,26,62,238,131,150,194,73,117,229,157,165,208,166,113,151,179,253,182,252,140,225,60,170,65,155,113,47,143,189,216,42,161,149,155,215,35,150,241,109,219,246,91,232,121,144,251,228, - 192,254,245,59,136,91,116,225,169,62,211,246,190,77,247,164,80,248,46,92,57,209,129,241,140,230,84,209,206,28,167,203,87,94,153,147,39,53,59,48,71,65,167,199,108,55,75,200,103,248,106,87,118,95,76,62,199,1,239,53,152,7,143,115,167,211,114,248,74,125, - 82,218,129,67,244,30,235,128,244,100,143,101,251,221,116,140,61,195,203,190,206,99,84,99,57,70,117,119,228,91,117,47,130,95,129,95,128,239,128,167,225,40,153,247,34,245,117,232,82,250,179,210,103,126,169,124,190,131,151,97,111,242,30,247,242,58,155,23, - 221,37,26,62,32,90,142,11,163,249,132,104,188,91,144,142,52,68,63,214,254,51,232,247,201,152,108,201,40,72,244,124,218,223,2,131,84,109,22,96,255,59,100,236,123,177,85,253,92,48,190,39,74,213,93,110,233,219,233,58,175,165,243,2,91,81,199,35,253,49,157, - 103,182,165,243,54,103,242,92,242,70,137,153,211,121,179,206,43,100,148,224,54,29,58,6,44,107,83,251,103,112,147,47,43,214,152,152,101,182,196,3,253,184,137,213,189,182,48,158,149,186,45,126,39,28,198,152,10,116,31,248,171,190,77,157,3,62,236,149,28, - 216,184,92,91,155,42,59,56,112,86,251,176,196,47,31,32,71,72,175,47,241,250,14,80,221,203,233,189,119,73,91,122,239,149,232,119,101,101,239,214,246,61,222,82,217,119,67,239,225,222,54,146,247,109,219,219,35,199,41,99,38,250,226,163,186,63,154,186,143, - 3,109,250,204,146,245,212,219,247,112,150,205,169,207,129,209,55,153,151,157,122,94,210,229,163,111,82,126,87,102,30,85,63,102,207,209,143,67,231,176,29,201,178,89,250,89,55,183,169,51,222,39,248,134,48,18,48,72,73,147,246,182,32,126,190,180,55,224,162, - 189,1,167,182,230,98,15,192,11,188,123,3,22,242,115,228,237,38,30,168,37,191,40,210,227,229,117,250,96,155,58,243,207,221,255,224,150,50,138,239,190,156,172,183,212,253,129,253,202,148,190,251,247,231,173,211,182,245,244,105,57,238,77,155,200,10,113, - 29,55,158,195,103,254,231,218,212,253,35,120,168,8,235,228,39,206,105,71,79,7,15,35,26,121,249,13,198,141,40,82,194,210,178,177,190,144,14,27,167,125,46,229,57,93,135,102,115,250,180,127,241,154,186,241,44,246,239,71,219,212,187,163,207,59,152,64,79, - 248,172,22,56,171,133,58,49,87,231,240,207,55,56,199,246,22,232,246,242,89,58,93,7,196,13,179,206,183,96,126,235,94,140,5,150,209,141,185,56,65,79,217,222,13,24,97,29,191,224,25,106,156,252,243,140,37,90,22,107,60,250,204,62,217,166,126,246,228,163,193, - 235,241,108,167,124,182,179,67,152,120,114,71,110,46,158,153,135,72,225,22,190,154,214,106,23,197,54,85,210,237,15,225,41,191,181,113,22,231,225,116,109,23,124,67,81,186,237,127,59,251,173,131,91,226,62,230,113,31,15,139,99,170,143,62,111,221,51,106, - 238,121,189,78,183,169,251,219,226,185,87,35,102,27,143,213,73,110,35,190,123,55,86,13,117,127,71,58,26,224,220,95,179,224,83,185,58,238,84,173,81,107,25,187,162,138,130,179,217,173,182,227,153,202,135,103,225,195,92,167,80,175,101,19,234,84,162,161, - 193,167,81,218,228,145,11,83,206,186,40,20,182,151,207,93,119,46,175,93,1,229,185,190,119,203,105,186,72,252,94,122,109,221,111,6,191,237,131,180,253,197,184,239,240,58,151,112,89,7,175,119,1,143,249,233,217,156,32,143,184,168,238,71,111,94,114,72,149, - 124,236,205,75,238,65,73,219,203,49,203,157,231,43,90,191,172,129,124,213,43,43,219,17,119,182,209,19,228,91,186,246,161,106,226,86,184,141,79,113,27,254,50,150,194,231,232,118,120,28,215,239,249,90,169,237,47,87,150,178,110,167,199,121,253,196,215,202, - 210,237,126,223,237,22,117,207,161,31,127,133,55,7,188,108,62,120,203,73,183,200,233,112,87,208,255,118,4,245,52,113,58,187,63,255,151,158,112,75,117,63,252,243,123,16,212,61,184,224,255,221,131,160,236,1,150,89,184,164,175,177,111,113,28,106,214,146, - 227,23,191,155,38,165,239,25,242,238,115,207,26,245,174,129,62,226,254,224,34,143,177,212,196,45,187,100,101,55,238,15,142,81,39,238,15,242,46,48,71,173,22,223,71,93,232,119,62,246,63,120,221,231,91,89,131,219,131,201,183,135,28,220,9,118,90,134,201, - 183,134,3,70,221,175,243,141,186,23,192,47,193,41,246,247,34,244,109,153,220,187,136,122,70,115,89,99,133,121,81,93,195,106,254,85,71,38,222,62,157,181,55,76,109,253,193,26,117,151,110,55,92,196,51,146,64,137,2,242,109,170,251,111,30,159,138,201,255, - 177,70,197,1,190,139,241,173,121,169,241,180,188,139,85,227,105,43,48,239,237,136,30,182,247,58,236,80,183,216,40,138,49,219,118,96,21,5,48,226,94,89,222,14,92,72,94,43,216,82,140,27,114,64,182,159,206,241,25,118,224,2,242,26,42,175,133,231,247,183,11, - 247,217,63,172,73,223,91,175,149,189,230,223,35,242,87,250,231,205,60,182,90,216,86,107,123,250,171,253,140,244,246,51,210,92,191,76,175,87,49,158,80,168,109,105,106,180,204,33,117,230,151,232,254,84,106,123,181,150,134,166,70,207,101,19,93,44,237,1, - 109,15,224,148,86,82,200,113,8,253,237,160,133,243,222,208,253,72,159,243,86,70,23,186,125,67,231,187,228,207,224,149,109,157,44,107,102,234,231,103,234,178,116,234,60,39,173,147,249,108,115,105,153,171,165,71,215,45,144,189,163,204,28,20,103,198,188, - 78,143,173,70,218,249,12,114,72,153,30,133,42,191,94,203,118,93,79,232,187,23,203,124,221,15,214,139,50,249,69,89,99,204,207,140,125,73,166,63,170,109,159,126,94,77,166,36,233,159,79,169,210,130,212,190,18,117,228,104,105,10,52,97,20,27,200,185,33,98, - 71,82,151,144,113,73,39,21,108,30,24,232,235,233,218,28,236,233,223,117,85,79,55,185,183,236,233,233,235,190,42,184,119,96,43,121,183,204,68,162,227,93,49,123,34,50,217,180,47,52,27,162,178,174,216,116,60,102,135,237,212,64,56,156,24,138,132,15,42,187, - 163,123,235,150,61,151,145,216,70,198,182,30,114,110,235,219,60,212,191,155,68,15,25,61,245,0,119,177,94,50,122,251,168,170,119,102,44,188,121,108,44,156,76,70,70,35,209,72,106,126,87,108,60,60,144,136,205,70,198,195,9,42,223,17,158,31,141,133,18,227, - 221,145,228,116,36,153,236,139,36,83,97,27,25,162,143,140,62,180,214,135,102,250,250,200,236,67,2,31,189,252,209,71,101,125,33,123,60,17,139,140,55,135,226,241,230,205,99,169,200,44,90,238,164,53,139,237,241,120,52,50,22,74,69,98,118,109,186,76,95,100, - 34,60,54,63,22,13,119,133,162,209,209,208,216,254,100,39,45,57,95,173,236,172,177,152,141,158,165,154,187,88,206,165,178,179,38,19,161,248,84,100,44,217,220,21,178,103,67,104,112,249,57,178,98,209,88,98,91,36,154,10,39,206,159,191,51,148,74,68,230,58, - 169,254,79,230,47,106,170,226,236,162,3,161,136,141,254,149,159,157,179,59,60,134,140,226,76,70,44,217,188,101,198,30,143,134,59,169,36,219,216,179,37,98,143,115,235,13,25,235,44,86,190,185,107,42,150,8,199,100,115,225,68,237,182,68,104,58,51,141,157, - 84,249,39,202,102,247,70,230,98,217,183,206,134,185,155,75,23,103,236,140,241,196,235,188,250,197,121,236,125,181,253,246,182,216,216,76,178,107,42,100,79,134,211,238,146,61,168,76,209,236,201,201,24,47,75,196,102,226,157,180,238,236,156,96,34,28,238, - 31,77,134,19,179,24,91,191,125,89,52,54,26,138,246,133,230,99,51,169,133,199,172,248,211,245,58,169,101,113,129,80,182,231,55,47,218,7,59,67,118,104,146,171,180,254,175,171,240,214,233,177,39,98,103,245,255,77,234,164,183,91,39,53,45,174,23,177,227,51, - 169,233,112,106,42,54,222,188,37,148,68,227,72,195,195,109,56,138,244,255,11,206,95,126,235,120,36,21,75,168,238,52,156,191,216,89,77,54,190,73,217,157,82,207,204,206,165,125,99,177,233,230,196,116,50,218,188,15,161,164,249,172,120,84,251,39,35,76,39, - 109,123,211,6,206,19,131,106,23,175,108,199,255,181,157,78,170,126,179,170,157,84,43,139,192,217,18,144,241,144,61,223,60,59,26,13,217,251,155,179,34,114,39,213,244,141,135,162,179,145,253,205,33,219,142,165,100,140,106,222,106,143,69,99,201,136,61,217, - 21,13,37,101,240,57,187,76,15,166,63,161,243,171,207,145,191,51,60,61,170,11,132,81,164,234,28,69,6,35,147,118,40,53,147,8,243,182,226,35,160,25,221,155,196,54,15,37,6,195,7,102,194,246,24,114,138,178,115,212,227,106,178,76,61,209,104,120,50,20,85,139, - 181,117,110,44,28,87,46,81,123,142,50,137,201,153,105,204,80,86,169,226,236,82,8,194,147,106,106,23,140,187,98,131,51,99,83,202,127,178,234,249,178,138,244,143,238,147,49,176,42,203,54,24,30,155,73,192,109,206,83,101,16,49,215,158,100,191,93,176,37,194, - 19,81,180,131,110,204,198,212,81,17,12,37,38,195,217,189,93,122,142,226,170,107,157,84,170,242,102,82,145,104,243,230,68,34,52,207,174,210,73,133,89,102,182,144,247,12,67,39,89,242,152,246,100,123,38,137,33,242,12,109,221,61,200,231,121,87,127,247,214, - 133,212,174,205,59,183,146,49,212,67,142,161,30,124,65,237,37,231,80,111,207,182,109,189,100,65,114,70,47,103,152,67,189,210,194,39,237,80,239,48,10,178,194,167,237,144,52,245,13,35,183,111,24,103,241,208,48,90,24,150,173,137,97,50,161,145,133,143,62, - 86,251,200,49,220,203,186,5,129,243,123,152,173,56,183,157,195,125,210,236,96,9,251,8,46,13,35,61,228,27,57,219,91,138,71,206,177,88,110,21,222,106,3,129,64,70,111,201,210,91,179,244,182,44,125,77,150,190,54,75,95,151,165,175,207,210,219,161,231,41,125, - 91,52,52,153,164,252,69,113,149,74,66,231,136,223,228,12,201,192,198,53,89,246,133,70,195,81,202,9,233,251,6,45,9,141,143,159,251,52,161,220,144,118,242,36,137,81,42,226,99,116,203,76,42,21,179,7,18,120,76,120,156,156,163,49,36,167,33,229,41,77,206,49, - 121,193,32,215,152,60,253,198,201,129,139,76,40,65,121,99,28,241,98,56,246,55,167,56,145,185,42,80,129,76,4,19,33,59,57,17,75,76,83,25,162,75,83,86,148,105,82,81,134,242,249,122,131,123,67,82,182,130,7,168,91,14,30,16,155,65,122,217,88,34,28,74,157,29, - 101,57,250,147,53,30,153,152,32,215,120,76,94,8,72,132,201,17,230,243,155,252,19,184,70,156,179,78,114,203,124,144,155,207,229,18,242,60,39,199,132,20,158,137,133,211,125,156,242,100,138,35,100,207,56,21,76,112,251,193,200,116,120,87,200,142,37,105,25, - 54,220,162,214,183,101,21,174,60,51,115,209,181,51,87,230,202,101,43,204,168,59,67,201,253,120,102,41,27,22,238,128,250,190,71,249,48,115,176,195,194,134,19,73,202,225,36,251,44,185,89,211,133,60,28,3,120,236,220,75,249,148,237,225,200,228,84,138,138, - 161,202,211,45,187,143,121,210,152,76,133,16,59,101,137,62,29,76,250,237,65,76,120,216,150,237,33,104,132,6,17,132,85,123,42,132,200,94,203,165,66,212,150,43,228,89,48,160,101,23,82,187,67,7,175,72,43,123,229,179,118,199,98,41,126,52,121,145,24,156,135, - 23,78,15,34,132,68,240,244,2,88,246,216,17,246,35,30,164,236,205,153,151,27,57,5,67,145,204,118,224,58,151,99,253,98,7,131,177,253,232,108,101,38,45,11,69,195,56,7,227,209,208,188,114,11,11,185,87,200,207,189,36,166,168,2,43,12,151,94,180,68,219,99,252, - 148,66,157,19,143,15,132,102,120,23,120,51,134,221,225,36,246,75,198,178,37,179,97,40,95,89,186,181,15,234,36,14,228,238,216,65,108,205,76,114,79,156,74,50,9,121,88,111,143,140,143,163,243,250,169,59,99,120,164,172,179,200,144,8,77,166,219,148,6,52,163, - 219,148,151,109,42,214,137,112,130,119,153,246,172,156,169,80,82,249,118,249,20,188,110,48,54,161,93,32,17,155,86,243,132,34,168,45,119,130,53,21,67,192,23,17,114,195,115,250,229,25,146,36,51,50,61,77,133,252,234,22,9,69,187,66,241,228,78,172,15,229, - 107,195,96,56,186,213,30,207,228,35,9,55,73,96,83,201,43,85,112,62,30,38,143,84,175,82,215,43,202,193,195,134,66,209,25,4,146,8,14,174,253,97,60,44,153,113,192,156,72,178,63,30,194,73,78,75,34,201,96,12,39,233,214,185,56,130,135,244,200,173,118,8,11, - 58,142,182,147,122,113,201,181,63,60,223,197,253,41,223,127,158,119,184,252,116,198,224,20,207,168,35,42,67,99,62,92,34,156,224,238,237,194,29,136,172,104,120,34,69,206,104,216,158,76,77,145,83,119,85,216,100,217,188,146,46,59,124,112,23,43,57,118,58, - 222,120,236,236,173,236,140,141,114,224,34,43,22,29,159,146,159,7,169,40,102,167,223,247,186,100,224,26,167,226,5,83,119,56,153,74,196,230,217,143,22,140,218,215,178,106,166,157,109,217,130,105,48,52,27,78,207,151,218,146,89,229,229,228,47,110,98,48, - 21,139,199,97,42,71,24,145,253,56,227,50,140,206,219,240,173,131,148,31,203,126,171,161,130,216,162,3,131,60,49,91,238,13,25,90,40,55,102,167,29,59,95,170,59,103,162,169,72,156,151,68,38,225,156,57,124,14,201,170,40,49,24,121,107,56,29,80,209,146,90, - 90,217,146,51,166,22,220,165,228,85,168,55,131,35,36,133,248,230,136,75,199,118,199,67,9,148,148,81,35,63,190,200,189,29,113,121,84,84,197,99,241,153,232,121,15,135,162,56,252,122,209,155,34,137,4,185,18,234,37,156,106,18,225,73,118,151,196,249,223,207, - 185,48,78,185,36,92,64,43,87,81,101,34,60,141,9,81,147,212,111,159,113,174,58,18,50,230,154,201,112,138,10,146,28,157,51,47,204,228,65,90,78,53,251,51,149,103,167,122,212,212,200,61,198,213,178,222,70,100,181,190,180,223,82,5,82,231,124,15,165,210,100, - 58,178,238,137,100,133,202,101,231,52,243,107,64,8,7,118,82,197,90,233,230,249,201,69,49,214,157,78,70,85,159,46,143,68,163,187,98,41,233,52,158,36,182,85,58,140,161,34,82,153,24,131,194,236,142,170,95,184,190,34,27,190,184,144,172,72,170,222,244,44, - 60,75,143,212,146,7,153,149,154,138,36,201,201,159,181,1,45,91,96,229,99,205,68,75,80,121,34,114,102,82,19,237,242,192,16,179,228,152,149,177,197,37,69,255,4,89,252,126,71,133,252,153,237,130,185,108,8,198,246,96,65,189,179,103,29,49,179,145,68,106,38, - 20,213,39,164,123,118,97,42,196,65,18,115,100,204,5,64,11,104,5,109,96,13,137,121,122,208,50,232,99,134,171,96,184,145,30,182,196,39,12,87,149,145,247,180,49,87,181,207,164,231,197,210,159,236,160,39,44,227,253,6,236,5,244,29,75,188,79,184,170,30,55, - 222,90,245,91,147,238,20,141,141,183,58,136,126,98,153,159,48,174,251,43,225,42,120,116,5,189,108,8,66,91,27,232,53,131,92,171,71,76,227,6,35,255,157,166,56,45,74,155,230,94,53,233,61,194,216,183,65,20,21,69,54,24,201,42,7,109,16,121,78,52,96,168,30, - 24,235,246,26,59,14,54,210,191,27,226,126,126,220,153,242,20,154,44,120,128,94,84,98,163,121,179,120,93,124,67,184,86,27,207,81,167,241,71,113,208,120,74,28,156,51,190,115,205,115,71,132,225,112,111,110,220,208,180,97,195,37,35,38,29,21,238,107,77,113, - 147,104,223,112,111,181,105,62,39,218,68,121,105,96,185,105,252,88,24,162,168,194,97,204,25,253,232,139,67,56,76,167,219,184,232,132,195,237,36,167,112,26,78,179,161,193,152,93,237,48,26,140,228,106,106,87,125,104,55,238,55,62,45,21,139,149,207,24,159, - 93,108,205,40,142,116,246,3,156,188,147,251,252,174,74,154,135,216,65,175,152,198,125,198,131,108,191,73,136,227,152,184,163,75,71,232,55,22,242,232,118,158,62,250,165,201,159,119,88,198,97,113,35,178,233,152,37,14,179,252,163,41,37,26,186,71,89,254, - 166,146,222,157,41,117,151,46,117,68,203,15,153,226,13,44,215,142,29,141,195,59,134,155,232,122,33,142,168,202,143,152,198,61,198,99,92,125,89,35,189,42,196,109,80,143,136,178,66,63,157,48,140,31,112,178,234,70,163,180,202,152,174,50,10,59,155,118,132, - 141,153,222,43,141,249,94,250,134,97,254,64,220,34,243,141,162,119,24,137,170,219,70,246,29,49,29,168,212,28,190,148,30,209,117,11,110,244,87,222,70,95,52,29,239,20,207,138,187,141,119,25,239,224,206,220,111,90,159,50,190,40,78,137,159,35,181,241,198, - 97,250,168,122,238,141,198,215,169,202,120,232,186,170,29,102,238,117,70,159,233,250,144,97,26,143,210,94,99,211,106,81,92,24,80,120,251,204,188,147,194,216,184,193,244,28,54,58,54,10,97,186,31,23,70,163,168,204,191,212,225,118,120,90,28,121,251,156, - 238,38,81,92,102,92,211,185,193,233,217,40,170,74,217,190,216,104,108,19,85,5,244,164,41,62,137,153,247,155,226,184,209,38,124,101,134,103,53,198,185,194,164,247,138,192,114,7,73,165,105,165,131,78,6,26,232,113,83,252,7,247,253,63,77,113,3,100,164,146, - 142,24,226,195,168,253,21,147,158,16,43,154,246,237,152,187,122,201,141,228,228,197,50,106,197,61,70,69,141,113,129,113,141,229,59,41,202,139,141,85,48,84,186,202,69,121,79,121,97,249,206,114,179,188,181,220,161,74,85,203,82,6,74,13,100,202,151,24,23, - 114,121,81,225,87,138,81,177,162,162,218,89,126,211,122,167,88,177,222,37,44,81,110,144,33,44,247,205,126,225,171,59,124,200,122,106,121,189,120,105,185,16,79,173,16,226,5,112,202,143,108,225,49,196,205,254,198,67,135,172,7,170,155,196,247,171,201,116, - 82,1,215,16,190,102,212,57,190,82,28,241,127,147,63,158,231,143,215,87,10,227,88,173,48,30,174,37,231,146,202,34,31,182,131,79,125,175,69,225,231,107,81,228,225,58,124,124,151,63,94,224,143,35,245,248,56,193,31,143,212,59,174,55,72,0,11,184,180,254,231, - 80,2,220,96,131,248,81,189,16,71,27,132,248,40,120,184,193,20,127,104,40,23,55,95,132,52,248,38,120,14,188,2,78,172,22,226,187,224,20,120,29,220,220,40,196,243,224,246,38,148,3,119,53,99,55,5,132,56,214,34,172,167,192,243,45,200,107,117,136,231,214,97, - 138,214,27,226,80,187,33,78,180,59,73,80,249,18,145,249,62,200,19,211,81,148,245,123,156,180,76,255,95,26,255,14,33,253,191,105,252,187,133,244,255,167,169,191,177,85,255,163,198,191,87,72,255,159,154,147,22,254,87,205,244,42,157,127,207,36,252,234,255, - 47,6,160,59,253,170,62,255,157,162,240,42,59,255,109,162,225,87,207,229,255,109,51,117,121,254,251,63,203,175,126,119,196,127,39,232,240,171,254,241,223,22,242,31,55,114,251,242,111,29,189,202,206,255,83,247,63,73,81,207,80,140,55,0,0,0,0 }; +static const uint8 javaComponentPeerView[] +{ + 0x1f, 0x8b, 0x08, 0x08, 0x16, 0x5e, 0x87, 0x63, 0x00, 0x03, 0x63, 0x6c, + 0x61, 0x73, 0x73, 0x65, 0x73, 0x2e, 0x64, 0x65, 0x78, 0x00, 0xad, 0x7c, + 0x0b, 0x7c, 0x94, 0xd5, 0xb5, 0xef, 0xda, 0xdf, 0x3c, 0x33, 0x79, 0xcd, + 0x4c, 0x02, 0xe1, 0xcd, 0x24, 0xa0, 0xe4, 0x9d, 0x21, 0xbc, 0x12, 0x12, + 0x20, 0x21, 0x04, 0x4c, 0x08, 0x10, 0xc8, 0x10, 0x24, 0xa1, 0xca, 0x90, + 0x0c, 0x64, 0x64, 0x98, 0x19, 0x66, 0x26, 0x01, 0x7c, 0x15, 0x29, 0x0a, + 0xf5, 0x51, 0xb1, 0xda, 0x4a, 0xd5, 0xf6, 0x58, 0xaf, 0x2f, 0x3c, 0xea, + 0x41, 0xc5, 0xfa, 0xa8, 0xb6, 0xd6, 0xaa, 0xd5, 0xa3, 0xa7, 0xea, 0x39, + 0xf6, 0x96, 0xdb, 0x63, 0xab, 0x1e, 0xb5, 0xad, 0xad, 0x57, 0xed, 0xa9, + 0xad, 0x7a, 0x8f, 0x3d, 0xde, 0xff, 0xda, 0x7b, 0xcf, 0xe4, 0x1b, 0x12, + 0xd4, 0xde, 0xdf, 0x4d, 0xf8, 0x7f, 0x6b, 0xed, 0xb5, 0xd6, 0x7e, 0xaf, + 0xbd, 0xf6, 0xde, 0xdf, 0x84, 0x19, 0x0c, 0xed, 0x75, 0xf9, 0xe7, 0x2d, + 0xa0, 0xee, 0xef, 0xbf, 0xfb, 0xe4, 0x77, 0xef, 0x38, 0xfe, 0xef, 0xe7, + 0xdc, 0x31, 0xe9, 0xf1, 0x87, 0x7e, 0x3c, 0xf2, 0xe2, 0x88, 0x38, 0x74, + 0xe6, 0xbc, 0x07, 0xde, 0xff, 0xaa, 0xbf, 0x8b, 0x28, 0x4e, 0x44, 0x7b, + 0x7b, 0xe7, 0x7b, 0x49, 0xff, 0x44, 0x56, 0x13, 0x85, 0x84, 0x92, 0xaf, + 0x04, 0xac, 0x76, 0xa2, 0x21, 0xd0, 0x69, 0x0e, 0xa2, 0x59, 0xa0, 0x9f, + 0xe6, 0x12, 0xfd, 0x1c, 0xb4, 0x38, 0x9f, 0x08, 0x22, 0x3a, 0x58, 0x44, + 0xf4, 0xc2, 0x22, 0xa2, 0xc1, 0x62, 0x22, 0x5f, 0x2d, 0x51, 0x19, 0x70, + 0x06, 0x50, 0x0e, 0x54, 0x01, 0xb5, 0x40, 0x3d, 0xb0, 0x00, 0x58, 0x02, + 0xb4, 0x02, 0xab, 0x80, 0x75, 0xc0, 0x39, 0xc0, 0x08, 0x70, 0x00, 0xb8, + 0x14, 0xf8, 0x3a, 0x70, 0x25, 0x70, 0x04, 0xb8, 0x0e, 0xf8, 0x0e, 0xf0, + 0x5d, 0xe0, 0x16, 0xe0, 0x76, 0xe0, 0x18, 0x70, 0x0f, 0x70, 0x1f, 0xf0, + 0x12, 0xf0, 0x0e, 0xf0, 0x2e, 0xf0, 0x01, 0xf0, 0x17, 0xe0, 0x13, 0xe0, + 0x33, 0xc0, 0x52, 0x47, 0xe4, 0x04, 0xf2, 0x01, 0x2f, 0x50, 0x09, 0x6c, + 0x05, 0x2e, 0x00, 0xbe, 0x0d, 0xdc, 0x07, 0xbc, 0x0c, 0xfc, 0x09, 0x98, + 0xe6, 0x27, 0x5a, 0x08, 0x74, 0x03, 0x61, 0xe0, 0x52, 0xe0, 0x06, 0xe0, + 0x38, 0xf0, 0x1c, 0xf0, 0x26, 0xf0, 0x19, 0x30, 0x79, 0x2e, 0x51, 0x0b, + 0xb0, 0x05, 0xd8, 0x0d, 0x5c, 0x06, 0xdc, 0x0f, 0xbc, 0x04, 0xbc, 0x03, + 0xd8, 0xea, 0x89, 0xfc, 0x40, 0x3b, 0x70, 0x2e, 0x70, 0x3d, 0xf0, 0x30, + 0xf0, 0x47, 0x60, 0xe6, 0x3c, 0xa2, 0x4d, 0xc0, 0x21, 0xe0, 0x5e, 0xe0, + 0x57, 0x40, 0xce, 0x7c, 0xa2, 0xc5, 0xc0, 0x10, 0x70, 0x0c, 0xf8, 0x13, + 0x50, 0xbd, 0x00, 0x79, 0x81, 0x03, 0xc0, 0xed, 0xc0, 0x33, 0xc0, 0x3b, + 0x80, 0x73, 0x21, 0xc6, 0x15, 0x58, 0x00, 0x6c, 0x06, 0xbe, 0x0a, 0x5c, + 0x07, 0x3c, 0x04, 0x3c, 0x0f, 0xfc, 0x01, 0xf8, 0x6f, 0xa0, 0x06, 0xf3, + 0xd0, 0x01, 0x6c, 0x05, 0x12, 0xc0, 0x41, 0xe0, 0x2a, 0xe0, 0x5a, 0xe0, + 0x56, 0xe0, 0x7e, 0xe0, 0x41, 0xe0, 0x11, 0xe0, 0x47, 0xc0, 0x53, 0xc0, + 0xf3, 0xc0, 0x8b, 0xc0, 0x2f, 0x81, 0x5f, 0x03, 0x6f, 0x01, 0xef, 0x00, + 0xef, 0x01, 0x1f, 0x02, 0x9f, 0x00, 0x7f, 0x03, 0x8c, 0x06, 0xb4, 0x03, + 0x28, 0x04, 0x8a, 0x81, 0xc9, 0x80, 0x0f, 0xa8, 0x00, 0xea, 0x80, 0xf9, + 0xc0, 0x62, 0xa0, 0x05, 0x58, 0x01, 0x74, 0x01, 0xeb, 0x80, 0x00, 0xd0, + 0x07, 0x9c, 0x0b, 0x0c, 0x00, 0xe7, 0x01, 0x71, 0x20, 0x05, 0xec, 0x03, + 0x2e, 0x01, 0x0e, 0x03, 0x57, 0x02, 0x47, 0x80, 0x5b, 0x81, 0x47, 0x80, + 0xa7, 0x81, 0x97, 0x81, 0xdf, 0x00, 0x7f, 0x04, 0x3e, 0x06, 0x6c, 0x8d, + 0x98, 0x4f, 0x60, 0x26, 0x50, 0x0d, 0x34, 0x02, 0x2b, 0x81, 0x1e, 0xe0, + 0x5c, 0x60, 0x27, 0xb0, 0x07, 0xf8, 0x1a, 0x70, 0x35, 0x70, 0x23, 0x70, + 0x07, 0xf0, 0x00, 0xf0, 0x04, 0xf0, 0x22, 0xf0, 0x36, 0xf0, 0x9f, 0xc0, + 0x47, 0x5c, 0xd6, 0x62, 0xa2, 0xd9, 0xc0, 0x22, 0xa0, 0x13, 0xd8, 0x00, + 0xf4, 0x01, 0x11, 0xe0, 0x02, 0xe0, 0x00, 0x70, 0x2d, 0x70, 0x37, 0xf0, + 0x08, 0xf0, 0x1c, 0x70, 0x12, 0x78, 0x0f, 0xc8, 0x6d, 0xc2, 0x38, 0x00, + 0x33, 0x80, 0x72, 0xa0, 0x13, 0xd8, 0x08, 0x0c, 0x00, 0xfb, 0x81, 0xef, + 0x01, 0xc7, 0x80, 0x47, 0x81, 0x97, 0x81, 0x37, 0x81, 0x4f, 0x00, 0x67, + 0x33, 0xea, 0x05, 0xe6, 0x00, 0x4b, 0x81, 0x4e, 0x60, 0x13, 0x10, 0x02, + 0xf6, 0x03, 0xb7, 0x00, 0xf7, 0x00, 0xcf, 0x02, 0x6f, 0x00, 0x7f, 0x05, + 0xf2, 0x97, 0x60, 0xee, 0x81, 0xe5, 0x40, 0x0f, 0x30, 0x04, 0x8c, 0x00, + 0x97, 0x00, 0xdf, 0x04, 0x6e, 0x06, 0x8e, 0x01, 0xf7, 0x03, 0x3f, 0x06, + 0x5e, 0x02, 0xde, 0x04, 0xfe, 0x02, 0xd8, 0x96, 0x12, 0x95, 0x00, 0xd5, + 0x40, 0x33, 0xb0, 0x1e, 0xd8, 0x0a, 0xc4, 0x81, 0x6f, 0x00, 0xd7, 0x01, + 0x37, 0x00, 0x27, 0x80, 0xa7, 0x81, 0x5f, 0x02, 0xef, 0x00, 0x1f, 0x03, + 0x8e, 0x65, 0xe8, 0x23, 0x50, 0x09, 0x34, 0x01, 0x5d, 0x40, 0x3f, 0x30, + 0x04, 0x5c, 0x04, 0x5c, 0x01, 0xdc, 0x0a, 0xdc, 0x0b, 0x9c, 0x00, 0x9e, + 0x00, 0x5e, 0x06, 0x5e, 0x07, 0xfe, 0x04, 0x7c, 0x0a, 0xb8, 0x5a, 0x88, + 0xa6, 0x03, 0x73, 0x80, 0x3a, 0xa0, 0x09, 0x68, 0x07, 0xce, 0x06, 0x92, + 0xc0, 0xc5, 0xc0, 0xf5, 0xc0, 0xed, 0xc0, 0x3d, 0xc0, 0x83, 0xc0, 0x0f, + 0x81, 0xe7, 0x80, 0x97, 0x81, 0xb7, 0x81, 0x8f, 0x81, 0xfc, 0x56, 0xcc, + 0x3b, 0x50, 0x0f, 0xac, 0x03, 0xb6, 0x01, 0xc3, 0xc0, 0x37, 0x80, 0x6f, + 0x03, 0xb7, 0x01, 0x0f, 0x02, 0x3f, 0x05, 0x7e, 0x0e, 0xfc, 0x1a, 0xf8, + 0x2d, 0xf0, 0x01, 0xf0, 0x19, 0x90, 0xb7, 0x9c, 0x68, 0x2a, 0x50, 0x09, + 0x34, 0x02, 0xab, 0x80, 0x75, 0x40, 0x2f, 0x10, 0x02, 0x0e, 0x02, 0xd7, + 0x03, 0x37, 0x03, 0x4f, 0x01, 0xff, 0x01, 0xbc, 0x07, 0x7c, 0x0a, 0x88, + 0x36, 0x22, 0x0f, 0x30, 0x13, 0x68, 0x00, 0xd6, 0x02, 0x5b, 0x80, 0x11, + 0xe0, 0x20, 0x70, 0x15, 0x70, 0x2b, 0xf0, 0x13, 0xe0, 0x57, 0xc0, 0xef, + 0x80, 0xbf, 0x02, 0xc6, 0x0a, 0xcc, 0x35, 0xe0, 0x03, 0xea, 0x80, 0x65, + 0xc0, 0x5a, 0xa0, 0x1f, 0xd8, 0x0e, 0x44, 0x81, 0xab, 0x81, 0x13, 0xc0, + 0x6f, 0x00, 0x7b, 0x3b, 0xd1, 0x99, 0x40, 0x3b, 0xb0, 0x1d, 0x38, 0x0c, + 0xdc, 0x05, 0xbc, 0x08, 0x7c, 0x04, 0x7c, 0x06, 0x38, 0x10, 0x94, 0x3d, + 0xc0, 0x44, 0xa0, 0x11, 0x18, 0x04, 0x0e, 0x02, 0x77, 0x00, 0xf7, 0x02, + 0x0f, 0x01, 0x8f, 0x03, 0x3f, 0x07, 0x5e, 0x07, 0x0a, 0x10, 0xa3, 0xdd, + 0x40, 0x09, 0x70, 0x06, 0x70, 0x26, 0x30, 0x07, 0x28, 0x07, 0x2a, 0x80, + 0x4a, 0xa0, 0x0a, 0xa8, 0x06, 0x6a, 0x00, 0x84, 0x4f, 0x42, 0x58, 0x24, + 0x84, 0x3c, 0x42, 0x58, 0x23, 0x84, 0x2f, 0x42, 0xb8, 0x22, 0x84, 0x27, + 0x42, 0x28, 0x22, 0x84, 0x19, 0x42, 0x38, 0x20, 0x2c, 0x47, 0xc2, 0x12, + 0x22, 0xb8, 0x34, 0xc1, 0x45, 0x09, 0xae, 0x46, 0x70, 0x19, 0xc2, 0x94, + 0x13, 0xa6, 0x8b, 0x30, 0xe4, 0x84, 0xa1, 0x23, 0x0c, 0x03, 0xa1, 0x6b, + 0xd4, 0xae, 0xf7, 0x93, 0x55, 0xc0, 0x59, 0x40, 0x07, 0xd0, 0x09, 0x60, + 0xbb, 0x21, 0x6c, 0x43, 0xb4, 0x06, 0x58, 0x0b, 0xac, 0x03, 0xba, 0x81, + 0xf5, 0xc0, 0x06, 0xa0, 0x07, 0x08, 0x00, 0x1b, 0x81, 0x5e, 0x60, 0x13, + 0x70, 0x36, 0xb0, 0x19, 0xe8, 0x03, 0xfa, 0x81, 0x2d, 0xc0, 0x57, 0x80, + 0x73, 0x80, 0x73, 0x81, 0xad, 0x40, 0x10, 0xd8, 0x46, 0x6a, 0xef, 0xfa, + 0x1a, 0xf0, 0x0d, 0xe0, 0x6a, 0xe0, 0x08, 0x70, 0x0d, 0xa9, 0x71, 0x49, + 0xff, 0x14, 0x6a, 0x7a, 0xa2, 0x4a, 0x8d, 0x95, 0xd0, 0x69, 0xaf, 0xe6, + 0x59, 0x5e, 0xa4, 0xf9, 0xc7, 0xc0, 0x17, 0x6b, 0xfe, 0x29, 0xf0, 0x13, + 0x34, 0xff, 0x02, 0xf8, 0x89, 0x9a, 0x7f, 0xc5, 0xc4, 0xbf, 0x6a, 0xe2, + 0xdf, 0xaa, 0x52, 0xf3, 0x60, 0xe8, 0xf2, 0x27, 0x69, 0x9e, 0xcb, 0x99, + 0xac, 0xf9, 0x77, 0xc1, 0x4f, 0x03, 0xb5, 0x6b, 0x9b, 0x52, 0xc0, 0x09, + 0x7c, 0xa8, 0xe5, 0x6e, 0x2d, 0x67, 0xde, 0x63, 0xe2, 0x27, 0x9b, 0xf8, + 0xe9, 0x26, 0xde, 0xa7, 0x79, 0x96, 0x95, 0xe9, 0xbe, 0x94, 0x69, 0xfe, + 0x53, 0x5d, 0xe6, 0x2c, 0x53, 0x5d, 0xec, 0x1f, 0xd6, 0x6a, 0x25, 0x9f, + 0xa3, 0xe5, 0x33, 0x49, 0xf9, 0x06, 0xb7, 0x93, 0x6d, 0xd8, 0x47, 0xf2, + 0x60, 0x33, 0x83, 0x94, 0x6f, 0x3c, 0xa6, 0xcb, 0x99, 0x6f, 0xaa, 0x6b, + 0x91, 0xae, 0x6b, 0xa6, 0xe6, 0x39, 0xef, 0x2c, 0xcd, 0x17, 0x23, 0xef, + 0x6c, 0x52, 0xfe, 0x33, 0xad, 0x5a, 0x95, 0xc9, 0xfc, 0x6c, 0x5d, 0x6f, + 0x93, 0x2e, 0x67, 0x86, 0xe6, 0xb9, 0x7c, 0x9f, 0xe6, 0xab, 0x75, 0x5e, + 0xf6, 0xb7, 0x06, 0x9d, 0x57, 0xfa, 0x5c, 0xb5, 0xea, 0x13, 0xf3, 0x67, + 0x55, 0xab, 0x79, 0x6f, 0xd1, 0xe5, 0x84, 0x35, 0xcf, 0xed, 0x39, 0x4f, + 0xf3, 0x5c, 0xe6, 0x4e, 0xcd, 0x77, 0xc3, 0x3e, 0xa2, 0xf9, 0x2d, 0xe0, + 0x77, 0x69, 0x9e, 0xdb, 0x1c, 0xd5, 0xfc, 0x10, 0xe4, 0x31, 0xcd, 0x73, + 0x1b, 0xe2, 0x9a, 0xdf, 0x0b, 0x7e, 0xb7, 0xe6, 0x0f, 0x82, 0x4f, 0x6a, + 0xfe, 0x4a, 0xf0, 0x09, 0xcd, 0x1f, 0x35, 0xf1, 0x37, 0x83, 0x4f, 0x69, + 0xfe, 0x4e, 0xf0, 0xc3, 0x9a, 0x3f, 0x0e, 0xfe, 0x7c, 0xcd, 0x3f, 0x6c, + 0x92, 0x3f, 0x61, 0xe2, 0x9f, 0x05, 0xff, 0x55, 0xcd, 0xbf, 0x64, 0x92, + 0xbf, 0x6a, 0xe2, 0xdf, 0x32, 0xf1, 0xef, 0x9a, 0xf8, 0x16, 0x53, 0xf9, + 0x1f, 0x82, 0xdf, 0xa3, 0xf9, 0x4f, 0xc1, 0x5f, 0xa0, 0x79, 0x27, 0x26, + 0xf9, 0x42, 0xcd, 0x17, 0xd7, 0x8c, 0xe6, 0x9d, 0x6d, 0xe2, 0xab, 0x4d, + 0xfc, 0x7c, 0xf0, 0x23, 0xe9, 0x72, 0x30, 0x56, 0x17, 0x6b, 0xbe, 0xd9, + 0x64, 0x73, 0x73, 0xd5, 0x28, 0xcf, 0x3e, 0xb3, 0x2f, 0x5d, 0x3e, 0xf8, + 0x8b, 0x34, 0xbf, 0xa2, 0x66, 0xb4, 0x6d, 0xdd, 0xe0, 0xf7, 0x6b, 0xfe, + 0x6c, 0x53, 0x39, 0xbc, 0x76, 0xf6, 0x6a, 0x7e, 0xd0, 0x24, 0x8f, 0xd7, + 0x8c, 0xca, 0xf7, 0x9a, 0xca, 0x39, 0x68, 0x6e, 0xbf, 0x69, 0x1c, 0xae, + 0x84, 0xfc, 0x12, 0xcd, 0x5f, 0x07, 0xfe, 0x80, 0xe6, 0x6f, 0x32, 0xd9, + 0xdf, 0x6d, 0xe2, 0x4f, 0xd4, 0xa8, 0xf8, 0xc1, 0xf1, 0x8c, 0x7f, 0x0e, + 0x6a, 0x9e, 0xfd, 0xe7, 0xd2, 0x34, 0x5f, 0x33, 0xca, 0x3f, 0x0b, 0xfe, + 0x32, 0xcd, 0xbf, 0x02, 0xfe, 0x90, 0xe6, 0xd9, 0x97, 0x0e, 0x6b, 0xfe, + 0x55, 0xc8, 0xbf, 0xae, 0xf9, 0xdf, 0x83, 0xbf, 0x42, 0xf3, 0x1f, 0x82, + 0xbf, 0x5c, 0xf3, 0x9f, 0x9a, 0xe4, 0x3c, 0xb6, 0x57, 0x6a, 0xde, 0x8a, + 0xc5, 0x77, 0x95, 0xe6, 0x8b, 0x6b, 0x47, 0xed, 0xe3, 0xa6, 0xbc, 0xdc, + 0xdf, 0x7c, 0x44, 0x9c, 0x7f, 0x22, 0x45, 0xfb, 0x04, 0xc7, 0x3b, 0x41, + 0x83, 0xc4, 0x7b, 0xc0, 0x3c, 0x3a, 0xa6, 0xe9, 0xdf, 0x24, 0x15, 0xf4, + 0x99, 0xa6, 0xfc, 0x8f, 0xa9, 0xd0, 0xd4, 0xd0, 0xd4, 0x22, 0x94, 0x7d, + 0xa1, 0xe0, 0x7d, 0xa3, 0x89, 0x1e, 0x21, 0xa6, 0x1e, 0x7a, 0x4c, 0xd2, + 0x1a, 0x5a, 0x2d, 0xe5, 0xb5, 0x14, 0x14, 0xbc, 0xa7, 0x78, 0xe8, 0x38, + 0x31, 0x2d, 0xa7, 0xfb, 0x25, 0x55, 0xfa, 0x0a, 0xad, 0xaf, 0x04, 0xdd, + 0xa4, 0x29, 0xa7, 0xab, 0xd0, 0xe2, 0x02, 0x49, 0xab, 0xe9, 0x6c, 0xc1, + 0xfb, 0x90, 0xd2, 0x57, 0x6b, 0x7d, 0x35, 0x34, 0x03, 0x82, 0xe3, 0x8f, + 0x41, 0xff, 0x4d, 0x1c, 0x7b, 0x4a, 0xe9, 0x4e, 0x49, 0x2b, 0xe8, 0x3e, + 0x49, 0xd3, 0xf2, 0x6a, 0xca, 0x17, 0x4c, 0x2b, 0xc9, 0x2b, 0x69, 0x2b, + 0x55, 0x49, 0x9a, 0x4b, 0xd5, 0x82, 0xe3, 0xce, 0x7c, 0x0a, 0xc1, 0xce, + 0x86, 0x9d, 0x6b, 0xae, 0xe0, 0xf8, 0x9a, 0x4f, 0x4f, 0x13, 0xd3, 0x52, + 0x7a, 0x13, 0x34, 0x07, 0xed, 0x75, 0x48, 0xba, 0x89, 0x16, 0x40, 0xef, + 0xc2, 0xae, 0xc6, 0xe9, 0x5c, 0x2d, 0xcf, 0xc5, 0x08, 0x2e, 0x14, 0x3c, + 0x9e, 0x2a, 0xed, 0x41, 0xbd, 0x6e, 0xc1, 0xb4, 0x9b, 0xe6, 0x49, 0xba, + 0x9e, 0x96, 0x08, 0xde, 0x33, 0x72, 0xe8, 0x0d, 0x52, 0xf4, 0x3f, 0x24, + 0x6d, 0xa1, 0x66, 0xc1, 0xfb, 0xc4, 0x5a, 0x99, 0xaf, 0x04, 0xbb, 0x1a, + 0xd3, 0xc9, 0xc8, 0xf1, 0x4b, 0x49, 0xdb, 0xa8, 0x0e, 0xfa, 0x29, 0x68, + 0x37, 0xcb, 0xa7, 0xa0, 0xdc, 0x9f, 0x4a, 0x5a, 0x46, 0xcf, 0xea, 0xf4, + 0xaf, 0x34, 0xfd, 0x1d, 0xe8, 0x54, 0xad, 0x67, 0xfa, 0x94, 0xa4, 0x2e, + 0x79, 0x1f, 0xe3, 0xf4, 0xab, 0x92, 0x5a, 0xe8, 0xd7, 0x92, 0xe2, 0x4c, + 0xa1, 0xe9, 0x6b, 0x92, 0x0a, 0x7a, 0x57, 0xd3, 0xff, 0x4d, 0x1c, 0xa3, + 0x0d, 0x7a, 0x59, 0xd2, 0x25, 0xf4, 0x47, 0xe2, 0x58, 0xdb, 0x28, 0xeb, + 0x9f, 0x81, 0x9d, 0xb4, 0x54, 0x30, 0xdd, 0x42, 0x65, 0x92, 0x56, 0xd3, + 0x19, 0x82, 0xe3, 0xef, 0x59, 0xf4, 0x8f, 0xa4, 0x68, 0xbd, 0xe0, 0xb8, + 0xbb, 0x99, 0x72, 0x05, 0xc7, 0xdc, 0x95, 0x32, 0x5f, 0x19, 0x7a, 0x58, + 0x24, 0xd3, 0xe5, 0xe4, 0x17, 0x1c, 0xeb, 0xd5, 0x38, 0xcd, 0xc6, 0x8e, + 0xaf, 0x68, 0x39, 0x9d, 0x90, 0xd4, 0x49, 0xff, 0xac, 0xe9, 0xf3, 0x92, + 0xba, 0xe9, 0x5f, 0x88, 0xf7, 0x9a, 0x20, 0x7d, 0x2a, 0x69, 0x3b, 0xcd, + 0x17, 0x4c, 0x07, 0x68, 0xa5, 0xf4, 0xab, 0xd5, 0x32, 0x7f, 0x39, 0x4e, + 0x17, 0x77, 0x4b, 0xba, 0x8e, 0xee, 0x95, 0xf4, 0x4c, 0xfa, 0xad, 0xa4, + 0xad, 0x74, 0xa6, 0xb4, 0x5b, 0x4e, 0x73, 0x84, 0x4a, 0x97, 0x0b, 0x65, + 0x57, 0x21, 0xe9, 0x32, 0xea, 0xd7, 0x74, 0x8b, 0xa6, 0x5f, 0xd1, 0xf4, + 0x1c, 0xe9, 0x97, 0x6b, 0x64, 0xf9, 0x15, 0xba, 0x7d, 0x15, 0xba, 0x3d, + 0x95, 0x38, 0x95, 0x38, 0x24, 0x2d, 0xa6, 0x47, 0x25, 0x9d, 0x43, 0x3f, + 0xd2, 0xe9, 0x1f, 0x4b, 0xda, 0x4f, 0x35, 0xd2, 0x6f, 0x3b, 0xa4, 0x5d, + 0x15, 0xf2, 0xcf, 0x94, 0xfe, 0xaa, 0xf2, 0x55, 0x43, 0xfe, 0x2d, 0x4d, + 0xbf, 0x2d, 0xe9, 0x14, 0xba, 0x5e, 0xd2, 0x72, 0x5a, 0x25, 0x14, 0x3d, + 0x4b, 0xfa, 0x75, 0x8d, 0xb4, 0x67, 0xff, 0x7e, 0x46, 0x52, 0x07, 0xfd, + 0x4c, 0xa7, 0xff, 0x55, 0xd3, 0x7f, 0xd3, 0xf4, 0xa4, 0xa4, 0xb3, 0xe8, + 0x2d, 0x9d, 0x7e, 0x5b, 0xd2, 0x1e, 0xb2, 0xc9, 0x72, 0x36, 0x93, 0x4b, + 0xd2, 0x4a, 0x6a, 0x94, 0x34, 0x40, 0x2d, 0xd2, 0xff, 0x17, 0xcb, 0xf2, + 0x6b, 0x71, 0x3a, 0xfa, 0xa6, 0xa4, 0x36, 0xba, 0x56, 0xd2, 0xf9, 0x74, + 0x9d, 0xa4, 0x79, 0x74, 0x54, 0xd2, 0x4e, 0xfa, 0x8e, 0xa4, 0x21, 0xba, + 0x41, 0xd2, 0x99, 0x74, 0xa3, 0xa6, 0x37, 0x49, 0x3a, 0x48, 0xdf, 0xd5, + 0xf9, 0xbf, 0x27, 0x69, 0x1d, 0xfd, 0x83, 0xa4, 0xb3, 0xe9, 0x66, 0x49, + 0xe7, 0xd1, 0xf7, 0xb5, 0xfe, 0x16, 0x4d, 0xff, 0x87, 0xa4, 0x76, 0xba, + 0x55, 0xa7, 0x6f, 0x93, 0xb4, 0x9c, 0xee, 0xd1, 0xf4, 0x01, 0x4d, 0x1f, + 0x94, 0xb4, 0x8f, 0x1e, 0x96, 0xb4, 0x86, 0x7e, 0x28, 0xe9, 0x02, 0x7a, + 0x42, 0xd2, 0x19, 0xf4, 0x13, 0x49, 0x27, 0xd2, 0x93, 0x92, 0xe6, 0xd3, + 0x0b, 0x92, 0x4e, 0xa6, 0x17, 0x49, 0xad, 0xef, 0x97, 0x74, 0x1c, 0x78, + 0x59, 0xdb, 0xbf, 0x22, 0xe9, 0x24, 0xfa, 0x85, 0xa4, 0x16, 0xfa, 0x9f, + 0x92, 0x9e, 0x4d, 0xff, 0x4b, 0x52, 0x2f, 0xbd, 0x2e, 0x69, 0x11, 0xfd, + 0x5e, 0xe7, 0x7b, 0x47, 0xd2, 0x42, 0xfa, 0x83, 0xa4, 0x6a, 0x3d, 0xd4, + 0xe2, 0xf7, 0x3d, 0xdd, 0x9e, 0xf7, 0x35, 0xfd, 0x40, 0xd3, 0x3f, 0x49, + 0x3a, 0x97, 0xfe, 0x53, 0x52, 0x3f, 0xfd, 0x59, 0x8f, 0xc7, 0x87, 0x5a, + 0xff, 0x17, 0x9d, 0xff, 0xaf, 0x9a, 0x7e, 0xa4, 0xe9, 0xc7, 0x92, 0xd6, + 0xd3, 0x27, 0x92, 0x9e, 0x4b, 0xff, 0x47, 0xf7, 0xff, 0xbf, 0x24, 0xdd, + 0x4c, 0x39, 0x42, 0xd1, 0x3c, 0x49, 0x17, 0xd1, 0x04, 0x49, 0x17, 0xd2, + 0x44, 0x4d, 0x4b, 0x34, 0x9d, 0xa4, 0xf5, 0x93, 0x75, 0x7a, 0x8a, 0xa6, + 0x53, 0x25, 0x2d, 0xa1, 0x69, 0x92, 0x36, 0xd1, 0x74, 0x49, 0x57, 0xd1, + 0x0c, 0x49, 0xb7, 0x91, 0x4f, 0x52, 0xb5, 0xbe, 0x6b, 0xf5, 0xfa, 0xe6, + 0xf4, 0x2c, 0x49, 0x7b, 0x69, 0xb6, 0x50, 0x71, 0xf4, 0x0c, 0x6d, 0x5f, + 0x29, 0xe9, 0x56, 0xaa, 0x95, 0x74, 0x23, 0x2d, 0xd2, 0xb4, 0x41, 0xd2, + 0x15, 0xd4, 0x24, 0x54, 0x1c, 0x5e, 0x26, 0x69, 0x0f, 0xb5, 0xea, 0xf4, + 0x72, 0x6d, 0xd7, 0xa6, 0xe9, 0x0a, 0x49, 0xab, 0xa8, 0x5d, 0x28, 0x3f, + 0xe8, 0x12, 0xca, 0x2f, 0xd6, 0xe8, 0xf4, 0x5a, 0x4d, 0xd7, 0x69, 0xda, + 0x2d, 0x94, 0x5f, 0xad, 0xd7, 0xe9, 0x0d, 0x42, 0xf9, 0x57, 0x8f, 0x50, + 0x7e, 0x1c, 0x10, 0x6a, 0xbc, 0x37, 0x0a, 0xe5, 0xc7, 0xbd, 0x42, 0x8d, + 0xfb, 0x36, 0xc1, 0xe7, 0xd1, 0xa9, 0xd4, 0x21, 0x69, 0x19, 0x6d, 0x16, + 0x7c, 0x26, 0x3d, 0x83, 0xfe, 0x9d, 0x98, 0x6e, 0x27, 0xa7, 0xdc, 0x07, + 0x0c, 0xb2, 0x4b, 0x3a, 0x9d, 0xb6, 0x0a, 0x3e, 0x77, 0xaa, 0x38, 0xd5, + 0x88, 0x93, 0xe7, 0x73, 0x92, 0xaa, 0x7c, 0x4d, 0xf0, 0x9b, 0x1f, 0x10, + 0x53, 0x2b, 0x3d, 0x24, 0xe9, 0x0e, 0x7a, 0x5c, 0x52, 0x15, 0xf7, 0x59, + 0x5e, 0x2c, 0xe9, 0x2c, 0xea, 0x14, 0x7c, 0x1e, 0xf5, 0x91, 0x43, 0xf0, + 0x1d, 0x48, 0x95, 0xb7, 0x14, 0xf5, 0xdd, 0x45, 0xea, 0x9e, 0xe5, 0x26, + 0x75, 0xbe, 0x3d, 0x8a, 0x7d, 0x3c, 0x0f, 0xf4, 0x55, 0x5c, 0x7c, 0x0a, + 0xf8, 0x12, 0x44, 0xea, 0x0e, 0xe6, 0x26, 0x75, 0xa6, 0xe5, 0x1f, 0xd6, + 0x7f, 0x08, 0x7d, 0x97, 0xd6, 0x57, 0x6a, 0xfd, 0x2c, 0x93, 0xde, 0x8a, + 0x4b, 0xd3, 0x76, 0xad, 0xaf, 0xd2, 0x72, 0x2e, 0xff, 0x66, 0x5d, 0xfe, + 0x34, 0xe8, 0x2f, 0xd5, 0xfa, 0x6a, 0x53, 0xfd, 0xe9, 0xfc, 0xd5, 0xd0, + 0x1f, 0xd5, 0x7a, 0x3e, 0xd7, 0x8b, 0x53, 0xf4, 0xcd, 0xd0, 0x3f, 0xa1, + 0xf5, 0x7c, 0xd6, 0xe7, 0x7b, 0x06, 0x9f, 0xc5, 0xef, 0xd4, 0xe5, 0x07, + 0xa0, 0xff, 0x58, 0xeb, 0xed, 0x7c, 0x3e, 0x00, 0x2d, 0xae, 0x50, 0x77, + 0xc5, 0xdd, 0xee, 0xb9, 0x98, 0x31, 0x17, 0xa8, 0x9f, 0xa9, 0x58, 0xcc, + 0x27, 0x06, 0x61, 0xa1, 0xf2, 0xd9, 0x51, 0xf7, 0x53, 0x90, 0xe4, 0xd9, + 0xca, 0x8c, 0xa5, 0x14, 0x77, 0xbf, 0x80, 0x71, 0x2c, 0xb3, 0x94, 0x90, + 0xd7, 0x1a, 0xf5, 0x3f, 0x83, 0x98, 0xcf, 0x39, 0x7e, 0x22, 0xeb, 0x97, + 0x69, 0xe1, 0xb2, 0x71, 0x9a, 0xed, 0xe3, 0x7e, 0x37, 0x59, 0x6c, 0x51, + 0xdf, 0xbf, 0xa0, 0x7c, 0x8f, 0xe1, 0xb5, 0x79, 0x6c, 0x56, 0x8c, 0x3d, + 0xdf, 0x95, 0x66, 0x54, 0xf0, 0x7e, 0x8c, 0xb3, 0x8f, 0x9b, 0x23, 0x43, + 0xbf, 0x28, 0xa0, 0x7e, 0x23, 0x8f, 0xfa, 0x2d, 0xf9, 0xb4, 0xdb, 0xb7, + 0x14, 0xd6, 0x7c, 0xc7, 0x33, 0x32, 0xb7, 0x2d, 0xd5, 0x4f, 0x96, 0xd9, + 0xf0, 0xcb, 0x7c, 0x65, 0x85, 0x7a, 0x87, 0x99, 0x70, 0x3f, 0x8e, 0x74, + 0x9e, 0xe8, 0x17, 0xb9, 0x19, 0x3d, 0xe7, 0x9a, 0x57, 0xa1, 0xee, 0x5e, + 0x01, 0x91, 0x47, 0x01, 0x83, 0x4b, 0x6d, 0xc1, 0xbe, 0x57, 0x80, 0x3c, + 0x0e, 0xa9, 0x6f, 0x3e, 0x8d, 0x3e, 0x9d, 0x7f, 0xd5, 0x69, 0xf4, 0x39, + 0xd0, 0xf3, 0x98, 0x75, 0x57, 0xa8, 0x7b, 0x47, 0xa0, 0x25, 0x8f, 0xe6, + 0x75, 0x87, 0x41, 0x73, 0x31, 0x0f, 0x18, 0xab, 0x81, 0xe3, 0x43, 0x09, + 0xff, 0x63, 0x14, 0x72, 0xe6, 0xd9, 0xb8, 0x6d, 0x3c, 0x0a, 0x53, 0x9c, + 0x06, 0x45, 0x7d, 0x3f, 0xc3, 0x39, 0xd3, 0xe5, 0xf4, 0x52, 0xa3, 0x33, + 0x9f, 0xa6, 0x38, 0x2d, 0x19, 0x49, 0x03, 0xf8, 0x72, 0x8b, 0xd7, 0x59, + 0x6e, 0x29, 0x72, 0x2e, 0x47, 0x3c, 0x10, 0x52, 0x33, 0x01, 0xe3, 0xdf, + 0x20, 0xac, 0x54, 0xe4, 0x5c, 0x42, 0x81, 0xd6, 0x7c, 0x0a, 0x2c, 0xcf, + 0x95, 0xa3, 0x6b, 0xd8, 0x5d, 0x46, 0xa0, 0x2d, 0x97, 0x8e, 0x8f, 0x70, + 0xca, 0x62, 0x77, 0xd9, 0xa3, 0xfe, 0x2d, 0x54, 0x6a, 0x0f, 0xac, 0xcc, + 0xa7, 0x06, 0x27, 0x66, 0xc0, 0xfd, 0x2c, 0xcf, 0x9d, 0xe3, 0xa4, 0xc3, + 0xf1, 0x59, 0xd4, 0xff, 0xcf, 0x64, 0x73, 0xe4, 0x61, 0xfc, 0xfb, 0x10, + 0x21, 0x58, 0x1b, 0x68, 0x2f, 0xa0, 0x32, 0xfb, 0x14, 0x8a, 0xfb, 0x8b, + 0xc8, 0xee, 0x8c, 0xfa, 0x6f, 0xa6, 0x4b, 0xed, 0x81, 0x76, 0xc8, 0x57, + 0xaa, 0x1e, 0x86, 0xc8, 0x6b, 0xeb, 0x6f, 0xcf, 0x95, 0xe3, 0x60, 0xc8, + 0x7e, 0xee, 0xa8, 0x50, 0xfe, 0x13, 0x75, 0x6f, 0xc4, 0xcc, 0xb9, 0x40, + 0x7b, 0x99, 0x5a, 0x17, 0xa3, 0x85, 0x4d, 0x56, 0xb4, 0xdc, 0xc3, 0xbe, + 0x61, 0xc1, 0x0c, 0x78, 0x8d, 0xa8, 0xff, 0x39, 0x8c, 0x11, 0x6c, 0x98, + 0x5a, 0x5d, 0xd6, 0xdd, 0xfe, 0x02, 0xb2, 0x58, 0x0b, 0xe4, 0x3c, 0xf2, + 0x98, 0x26, 0xf5, 0x98, 0xee, 0x76, 0x37, 0x2a, 0x6f, 0xf1, 0x7d, 0x05, + 0x73, 0x37, 0xaa, 0x3f, 0x5f, 0xcf, 0xe9, 0x6e, 0x5f, 0x2b, 0xfc, 0x7e, + 0xb7, 0x6f, 0x19, 0x9e, 0x6a, 0x4e, 0x55, 0x5b, 0x0e, 0xe8, 0xb6, 0xec, + 0x76, 0xe7, 0x23, 0xcd, 0x5e, 0x97, 0xc7, 0x54, 0xc8, 0xb6, 0x08, 0x53, + 0x5b, 0x2c, 0xdc, 0x96, 0x67, 0xb0, 0xee, 0x5c, 0x72, 0xcc, 0x66, 0x09, + 0x97, 0x85, 0x47, 0xc9, 0x6a, 0x29, 0x90, 0x3e, 0x6f, 0x43, 0x19, 0xdf, + 0xa8, 0x50, 0x77, 0xd2, 0x40, 0x77, 0x21, 0x4e, 0x95, 0x16, 0xac, 0x93, + 0x40, 0xb7, 0x07, 0x33, 0x98, 0x43, 0x31, 0x77, 0x3d, 0xcf, 0x1a, 0xf5, + 0x43, 0xe3, 0x41, 0x7f, 0xf9, 0x6d, 0x85, 0x8b, 0x02, 0xeb, 0x3d, 0xc4, + 0xa5, 0x9e, 0x8d, 0x1e, 0xe6, 0x21, 0xfa, 0x4e, 0xa0, 0xb8, 0xaf, 0x10, + 0x65, 0xf5, 0xaf, 0x2f, 0x94, 0xe7, 0xa6, 0x40, 0x8f, 0x97, 0x02, 0x01, + 0x0f, 0xc5, 0x5b, 0x16, 0x92, 0xbf, 0xb5, 0xbf, 0xdb, 0x8d, 0x1c, 0x85, + 0xf0, 0xce, 0x1c, 0xd8, 0xb8, 0x2c, 0x45, 0x56, 0x2f, 0x25, 0x02, 0xb9, + 0x24, 0xea, 0x03, 0xb2, 0x54, 0xc4, 0x01, 0xfc, 0x72, 0x9f, 0x6e, 0xd4, + 0x63, 0x12, 0xf7, 0xd7, 0x92, 0xdb, 0xe8, 0x17, 0x5e, 0xac, 0x01, 0x0f, + 0x7a, 0x6d, 0xe1, 0x33, 0x3c, 0xe4, 0xb7, 0x55, 0xa8, 0x77, 0x16, 0x01, + 0x1f, 0xb7, 0x33, 0x87, 0x02, 0xa5, 0x6e, 0xc4, 0x70, 0x1b, 0x25, 0x7c, + 0x2e, 0x8c, 0x0e, 0xac, 0x21, 0xef, 0xf7, 0x79, 0xd0, 0xea, 0x3a, 0xd8, + 0x17, 0xa0, 0x2c, 0x43, 0xf6, 0xef, 0xde, 0x0a, 0x75, 0x5f, 0x0f, 0x6c, + 0x2d, 0xc2, 0x38, 0xf1, 0xdb, 0x94, 0x5c, 0xb4, 0x7f, 0x22, 0xaa, 0x9c, + 0x0b, 0x07, 0x6e, 0xb4, 0xa1, 0xc7, 0xc6, 0x56, 0xd8, 0x16, 0x89, 0x19, + 0x34, 0xdf, 0xed, 0x42, 0x1f, 0xca, 0x28, 0x30, 0x50, 0x8c, 0x76, 0x54, + 0x92, 0xdf, 0x51, 0xee, 0x08, 0x6c, 0x2d, 0xc6, 0x0c, 0x54, 0xe1, 0xae, + 0x0c, 0xef, 0x18, 0x50, 0x65, 0x58, 0x28, 0xd7, 0xba, 0xbb, 0x7b, 0x90, + 0xda, 0x86, 0x5d, 0x8e, 0x46, 0x87, 0x8b, 0xb6, 0x3a, 0x0c, 0x5a, 0x50, + 0x62, 0xc3, 0x18, 0x71, 0xa4, 0xf2, 0x18, 0xdc, 0x2f, 0xa7, 0x9e, 0xab, + 0x47, 0x75, 0x4c, 0xf9, 0xbc, 0xfa, 0xbd, 0xee, 0x79, 0x0e, 0x78, 0xf6, + 0x0e, 0x65, 0xe1, 0x80, 0xc5, 0x6e, 0x7f, 0x08, 0x91, 0x38, 0xcf, 0x51, + 0x9e, 0x9b, 0x2d, 0xdd, 0x2e, 0xa5, 0x0d, 0x0e, 0xac, 0x01, 0xf7, 0x13, + 0x90, 0xb9, 0x1c, 0x51, 0xdf, 0x4a, 0xdc, 0x5f, 0xf3, 0x1c, 0x1e, 0x87, + 0xc7, 0x70, 0x61, 0x2c, 0xf9, 0x9d, 0xcb, 0xd3, 0x15, 0xea, 0x1d, 0x84, + 0xb9, 0xce, 0x89, 0x18, 0xc4, 0xb9, 0x08, 0x39, 0x8d, 0x56, 0x2b, 0x79, + 0x1d, 0x85, 0x0e, 0x93, 0x4e, 0x88, 0xa4, 0x38, 0xe8, 0xf8, 0xd6, 0x1e, + 0xfb, 0x0e, 0x9e, 0x61, 0xe8, 0x2c, 0x72, 0xd4, 0x89, 0x7e, 0x5e, 0xa1, + 0xde, 0xe1, 0x94, 0x09, 0x15, 0xed, 0x04, 0x79, 0x44, 0x5a, 0xf7, 0x0b, + 0x3d, 0x5f, 0xfd, 0xa2, 0x08, 0x3a, 0x8e, 0xc0, 0xfd, 0x46, 0xb1, 0xf6, + 0x61, 0xd6, 0xff, 0xba, 0x82, 0xef, 0x21, 0xac, 0x9f, 0xa8, 0x63, 0x9b, + 0x57, 0x6c, 0x81, 0xb7, 0x14, 0x98, 0xe2, 0xed, 0x5b, 0x15, 0xea, 0x7d, + 0x58, 0x19, 0x22, 0x60, 0xdc, 0x2d, 0xa3, 0xcc, 0xfa, 0x89, 0x14, 0xf0, + 0x94, 0xa0, 0x77, 0xfb, 0x65, 0x34, 0x6b, 0x44, 0xee, 0x8c, 0xcc, 0x77, + 0x10, 0xb2, 0x51, 0x8b, 0x0b, 0xd8, 0xa3, 0xc4, 0x06, 0x83, 0xdf, 0xb1, + 0x09, 0x2a, 0xcf, 0x8b, 0xfa, 0xca, 0x40, 0xa3, 0xee, 0xd2, 0x2c, 0xf9, + 0x7d, 0xc6, 0x7d, 0xa5, 0x45, 0xf0, 0x9c, 0x05, 0x62, 0x0a, 0x6d, 0xdc, + 0x30, 0x81, 0x1a, 0x8c, 0x89, 0x18, 0xff, 0x2d, 0xe0, 0x02, 0x1b, 0x50, + 0x52, 0x59, 0x09, 0x3c, 0x76, 0x22, 0x46, 0x62, 0x9d, 0x5c, 0x2f, 0x7a, + 0x76, 0x2d, 0xbb, 0xfd, 0x03, 0x54, 0x6f, 0x65, 0xfb, 0x46, 0xc3, 0x81, + 0x33, 0x83, 0x8d, 0xbc, 0xee, 0x2d, 0xdd, 0x13, 0xe4, 0x0d, 0x54, 0xc8, + 0x38, 0xfc, 0x17, 0xb4, 0x9d, 0xfb, 0x10, 0xc0, 0x19, 0x8d, 0xe7, 0x9b, + 0xc7, 0x85, 0xfd, 0xf4, 0xbf, 0x2a, 0xd4, 0xbb, 0xb8, 0x7e, 0x51, 0xa2, + 0xfb, 0x5d, 0x26, 0xe0, 0x3d, 0xbe, 0x4e, 0x5e, 0x23, 0x62, 0x32, 0x46, + 0x69, 0x92, 0x1c, 0x03, 0xa1, 0x4b, 0xe2, 0x72, 0xac, 0x32, 0xfe, 0x77, + 0x13, 0xe9, 0xf2, 0xb3, 0xe5, 0xeb, 0xa5, 0x3c, 0xbd, 0x0e, 0x9c, 0x95, + 0x7a, 0xff, 0xf2, 0x4d, 0x42, 0x5f, 0x2f, 0x91, 0xf1, 0x23, 0x50, 0x3a, + 0x19, 0xa3, 0x33, 0x47, 0x46, 0x89, 0xb4, 0x5d, 0xfe, 0x69, 0xed, 0xca, + 0xb3, 0xec, 0xbc, 0x95, 0x2a, 0xd6, 0xf4, 0xf8, 0xa6, 0xc0, 0xcf, 0xcf, + 0x85, 0xce, 0x25, 0xdb, 0x9f, 0xd6, 0x97, 0x64, 0xe9, 0x23, 0x19, 0xbd, + 0x55, 0xfb, 0xf7, 0x34, 0xb3, 0xde, 0x1f, 0x25, 0xb7, 0xc5, 0x65, 0x29, + 0xb4, 0x8c, 0xe6, 0x2f, 0xcb, 0xca, 0xbf, 0x75, 0x4c, 0xf9, 0x73, 0xb2, + 0xf4, 0x43, 0x63, 0xf4, 0xd5, 0x59, 0xfa, 0xd8, 0x18, 0xfd, 0xdc, 0x2c, + 0xfd, 0xae, 0x8c, 0x9e, 0x77, 0x27, 0x1e, 0xbf, 0x85, 0x66, 0x7d, 0xcb, + 0x79, 0xe4, 0x6e, 0xcb, 0xb3, 0x78, 0x2c, 0x6a, 0xbe, 0x78, 0x9c, 0x97, + 0x54, 0x2a, 0x1f, 0x57, 0x73, 0xd5, 0x07, 0x2f, 0x29, 0xc8, 0xf4, 0xad, + 0x4d, 0xeb, 0x54, 0xdf, 0x76, 0xa2, 0x6f, 0x05, 0x99, 0x72, 0x3b, 0xcc, + 0xba, 0x96, 0x30, 0xca, 0x1d, 0xcd, 0xd7, 0x9d, 0x95, 0x2f, 0x28, 0xf3, + 0x19, 0xda, 0x6f, 0x7a, 0x2b, 0xb5, 0xdf, 0xb8, 0x67, 0x4a, 0xbf, 0xe1, + 0x5d, 0x98, 0xcb, 0xeb, 0xaf, 0x54, 0xef, 0x03, 0x7b, 0xba, 0xa7, 0x23, + 0xf6, 0xec, 0xc3, 0x7d, 0x28, 0x4f, 0x9e, 0x89, 0xfb, 0x83, 0x16, 0x00, + 0x6b, 0xd6, 0xd8, 0xbc, 0xcd, 0x4e, 0xde, 0x3f, 0x37, 0x20, 0x07, 0xef, + 0x41, 0x58, 0xa9, 0xd6, 0x72, 0xc3, 0xfb, 0xe1, 0xe6, 0x41, 0x27, 0xe2, + 0xa1, 0x5d, 0xee, 0x47, 0x90, 0x59, 0x36, 0x0f, 0x38, 0x60, 0xef, 0xe2, + 0x73, 0x77, 0xf7, 0xe6, 0x20, 0xbf, 0x29, 0xe0, 0xbd, 0x8a, 0xdf, 0x38, + 0xbb, 0xc4, 0x6e, 0xf7, 0xc5, 0xbc, 0x36, 0x50, 0x52, 0x0e, 0x76, 0xbf, + 0x0a, 0xf2, 0x7a, 0xe2, 0x2d, 0xcb, 0x71, 0xf2, 0xec, 0xef, 0x9d, 0x46, + 0x1e, 0xfb, 0xe8, 0x98, 0xee, 0xac, 0x54, 0x67, 0x92, 0xa8, 0x7b, 0x2f, + 0xd2, 0xdc, 0x0e, 0xab, 0x88, 0xfa, 0x70, 0x66, 0x04, 0x3f, 0x13, 0x77, + 0x48, 0x8f, 0x3e, 0x93, 0xb0, 0x6d, 0xbc, 0x92, 0x64, 0x9c, 0xdd, 0xed, + 0x7b, 0xd8, 0x34, 0xf6, 0x36, 0x29, 0x1b, 0xd6, 0xba, 0x78, 0xe0, 0x76, + 0x72, 0xd7, 0x2b, 0x9d, 0x5d, 0xfe, 0x12, 0x5d, 0xa4, 0x75, 0x23, 0xf6, + 0x6b, 0xe4, 0xbe, 0x52, 0xa8, 0xd7, 0x50, 0xfa, 0x47, 0xfa, 0xa6, 0xa7, + 0x50, 0xa4, 0xc7, 0xed, 0x32, 0x3d, 0x6e, 0x1b, 0xdd, 0x3e, 0x69, 0x6b, + 0xe8, 0x75, 0x72, 0x45, 0x25, 0xe7, 0xe6, 0xb6, 0x1e, 0xe0, 0xbe, 0x61, + 0xe7, 0xc2, 0x58, 0xb9, 0x31, 0x32, 0xb0, 0xca, 0x85, 0x15, 0x47, 0x95, + 0x23, 0x95, 0xea, 0xbd, 0x6a, 0xe0, 0xc8, 0x54, 0xd8, 0x55, 0xc8, 0xfa, + 0x1a, 0x70, 0x97, 0xed, 0xf9, 0xe6, 0x74, 0xa4, 0x27, 0x23, 0xe5, 0xb2, + 0x46, 0xdd, 0xd3, 0x99, 0xda, 0xa2, 0xee, 0x19, 0x4c, 0xed, 0x51, 0xf7, + 0x14, 0xd0, 0x5c, 0x87, 0xe3, 0x9a, 0x11, 0xe7, 0xa5, 0x28, 0xd9, 0x3b, + 0xa5, 0xd0, 0xe5, 0x75, 0x15, 0xba, 0x72, 0xd1, 0x0a, 0x6e, 0xff, 0xf5, + 0x95, 0x2a, 0xae, 0xf7, 0xec, 0x9f, 0x9e, 0x1d, 0x5b, 0x73, 0x0a, 0x73, + 0xa2, 0xee, 0x04, 0xea, 0xf5, 0xb6, 0x78, 0x3d, 0xf5, 0x39, 0x33, 0x71, + 0x47, 0x9b, 0x44, 0xf5, 0x39, 0x13, 0x41, 0x27, 0x83, 0x7a, 0xa9, 0xe7, + 0x6b, 0x5c, 0x6b, 0x89, 0xae, 0x65, 0x22, 0x53, 0x87, 0xe3, 0x80, 0xf8, + 0xd6, 0x88, 0xfd, 0x72, 0xb4, 0xb7, 0x50, 0xc4, 0xfc, 0xb3, 0xe9, 0xa8, + 0xcb, 0x25, 0xcb, 0x89, 0xa3, 0x9c, 0x42, 0x91, 0xaf, 0xe3, 0xfa, 0xb1, + 0x4a, 0xf5, 0x6e, 0xb8, 0xe7, 0xc8, 0xf4, 0x53, 0xf6, 0x90, 0x42, 0xa3, + 0xd1, 0xe5, 0x27, 0xb5, 0x8f, 0x4d, 0xa7, 0x05, 0x6e, 0x9e, 0xf3, 0x62, + 0xcc, 0x96, 0x8b, 0xbc, 0xb3, 0xea, 0xfd, 0x38, 0x11, 0x94, 0x6e, 0xcd, + 0xc5, 0x1e, 0x35, 0x95, 0x6b, 0x9e, 0x00, 0x79, 0x5e, 0x6e, 0x43, 0x6e, + 0x49, 0x86, 0x8f, 0xfa, 0x9e, 0xc6, 0x19, 0xdc, 0xe5, 0xe8, 0xb9, 0x8e, + 0xf5, 0x13, 0x39, 0x9f, 0xd3, 0x71, 0xad, 0xb8, 0x9d, 0x5b, 0x64, 0x91, + 0x3d, 0x2f, 0x34, 0x62, 0x2d, 0x67, 0xd0, 0xb1, 0xe7, 0x5d, 0x18, 0x01, + 0x8e, 0xfb, 0x16, 0x39, 0x77, 0x8f, 0x56, 0xaa, 0xcf, 0x14, 0xd8, 0x67, + 0xb3, 0xc6, 0xc0, 0x5e, 0x68, 0xe7, 0x1e, 0xf2, 0xfe, 0x14, 0xdf, 0x74, + 0x05, 0xd9, 0x82, 0xde, 0x89, 0x85, 0x76, 0xb6, 0x55, 0xf3, 0xf1, 0x24, + 0xf2, 0xf1, 0xbd, 0xce, 0xe9, 0xf4, 0x90, 0x93, 0x47, 0x04, 0x63, 0xe8, + 0x75, 0x8d, 0x96, 0x80, 0xfe, 0xb8, 0x52, 0x62, 0x12, 0x76, 0x75, 0x17, + 0xa5, 0xb0, 0x22, 0xbd, 0x94, 0x9b, 0xfb, 0x0b, 0xf1, 0x19, 0x79, 0xa7, + 0x37, 0x88, 0xf7, 0xa9, 0xfe, 0xe5, 0x93, 0xe4, 0xad, 0xad, 0x7f, 0xe3, + 0x1a, 0xf2, 0xd6, 0xd7, 0x97, 0xfe, 0x2b, 0x79, 0x37, 0x14, 0x5b, 0xf8, + 0xf5, 0x5f, 0x7d, 0xe9, 0x2a, 0xf2, 0x6e, 0xab, 0x2f, 0xe5, 0xdc, 0x0f, + 0xfa, 0xdf, 0x40, 0xf1, 0x8d, 0xb8, 0x47, 0xf6, 0x5c, 0x82, 0x3e, 0xf9, + 0xa6, 0xd1, 0x31, 0xac, 0x8d, 0x14, 0xc6, 0x06, 0x65, 0x5a, 0x53, 0xd8, + 0xeb, 0x41, 0x6d, 0x4e, 0x78, 0xb2, 0xf5, 0x07, 0x23, 0x4e, 0xfe, 0x4c, + 0xa5, 0x7c, 0xce, 0xac, 0x37, 0xda, 0x60, 0xf9, 0x55, 0xcc, 0x56, 0xcf, + 0x01, 0x95, 0x27, 0x87, 0xfd, 0xc2, 0x37, 0x93, 0xa9, 0x6d, 0x85, 0x5d, + 0xb8, 0x0e, 0x6c, 0x7f, 0x26, 0x14, 0xf5, 0xf9, 0x38, 0x8d, 0xfb, 0xa0, + 0xc8, 0x3f, 0xe0, 0xb9, 0x1d, 0x5b, 0x99, 0x2c, 0xa5, 0x54, 0xb4, 0x89, + 0x80, 0x08, 0xa5, 0x4b, 0x2b, 0xcc, 0xff, 0xfb, 0x5a, 0x70, 0xd5, 0xff, + 0xd7, 0x16, 0x5c, 0x25, 0x5b, 0xf0, 0x65, 0xea, 0xe5, 0x4f, 0x94, 0x52, + 0x62, 0x2a, 0xcb, 0x0a, 0x17, 0xbd, 0x56, 0x45, 0xb3, 0xde, 0x53, 0x2d, + 0xf8, 0x3d, 0x79, 0x27, 0x2e, 0xf8, 0xeb, 0xac, 0x4c, 0xdb, 0xc3, 0x28, + 0x83, 0xdb, 0x11, 0xe6, 0x7a, 0xad, 0x05, 0xae, 0x03, 0x2b, 0x9e, 0xb1, + 0x72, 0x3b, 0x64, 0xda, 0x56, 0x90, 0x7f, 0x60, 0xe3, 0x33, 0xb2, 0x4c, + 0xc3, 0x6d, 0xcf, 0x94, 0x7b, 0xd2, 0xee, 0x16, 0xe5, 0xbf, 0xf9, 0x72, + 0xed, 0xb8, 0xfa, 0x4b, 0xb7, 0x58, 0xf5, 0x8d, 0xe3, 0x88, 0x8a, 0x16, + 0x1f, 0x54, 0xaa, 0xcf, 0xb8, 0xe2, 0xfe, 0xf3, 0xa9, 0xcd, 0x96, 0x6b, + 0xe5, 0xcf, 0xa9, 0xe6, 0x1a, 0x56, 0xec, 0xf3, 0x4e, 0xac, 0xf9, 0x1a, + 0xc8, 0x37, 0x50, 0x8b, 0x8d, 0xe3, 0x81, 0x67, 0x9c, 0x98, 0x75, 0x7f, + 0x26, 0x66, 0x8d, 0xd5, 0x3d, 0xf0, 0x39, 0xba, 0xe3, 0x9f, 0xa3, 0xfb, + 0x81, 0x69, 0x8f, 0x52, 0x6d, 0xfc, 0x28, 0xad, 0xf3, 0xdf, 0x87, 0xb3, + 0xed, 0xe9, 0xf2, 0x9d, 0xc8, 0xe4, 0x4b, 0x9f, 0x31, 0xf8, 0x87, 0xef, + 0xae, 0x55, 0xf2, 0x34, 0xc7, 0x11, 0xad, 0x98, 0x2e, 0xe1, 0x88, 0x40, + 0x5e, 0x3f, 0xf3, 0xa5, 0x92, 0x2f, 0x46, 0xcf, 0x98, 0x62, 0x75, 0xe1, + 0x0c, 0xec, 0xf5, 0xb1, 0x44, 0xa8, 0x92, 0x84, 0x43, 0x96, 0xc1, 0x9f, + 0xd1, 0xf1, 0xb8, 0xf0, 0x5a, 0xe5, 0xf2, 0x73, 0x49, 0x9d, 0xcd, 0x6c, + 0xe3, 0xb4, 0x31, 0xee, 0xbf, 0x10, 0x6d, 0xcc, 0xcb, 0x9c, 0x69, 0xb2, + 0x75, 0x23, 0x19, 0x9d, 0x55, 0xfe, 0x12, 0xfd, 0x2d, 0xdd, 0xfe, 0x96, + 0x07, 0x11, 0xe3, 0xd3, 0xf9, 0x54, 0xfb, 0xe3, 0x3a, 0x66, 0xf7, 0xf8, + 0xa6, 0xcb, 0xfb, 0xbb, 0xba, 0x33, 0x62, 0xbf, 0xc3, 0x1d, 0x9c, 0x77, + 0xdb, 0xb8, 0x6f, 0x16, 0xce, 0x4f, 0x65, 0x68, 0x4f, 0xdc, 0xcd, 0xf1, + 0xad, 0xbf, 0xa5, 0x14, 0xa7, 0xa5, 0x6a, 0xd4, 0xd3, 0x45, 0xad, 0xd6, + 0xfe, 0xd6, 0x19, 0x48, 0x55, 0x22, 0xd5, 0x2e, 0x53, 0x33, 0xe5, 0x7e, + 0x64, 0xc5, 0xa9, 0x70, 0x8a, 0x71, 0x07, 0xf1, 0x7e, 0x84, 0x1b, 0x88, + 0x98, 0x29, 0x4a, 0xa9, 0xbf, 0x75, 0x2a, 0x4d, 0xc3, 0x19, 0x2d, 0xea, + 0xfb, 0x31, 0xad, 0x97, 0xf7, 0x45, 0x27, 0xcd, 0xb4, 0x71, 0x9a, 0x3f, + 0xb3, 0x2d, 0x77, 0x45, 0xdd, 0x42, 0xde, 0x3f, 0x47, 0x65, 0x7d, 0xab, + 0xe0, 0x5d, 0xb8, 0x0f, 0xde, 0x8b, 0xfa, 0xb7, 0xac, 0xf4, 0xc1, 0xdb, + 0xa3, 0xbe, 0x3b, 0x68, 0x10, 0xda, 0x3b, 0xe5, 0xf3, 0x18, 0xad, 0xa0, + 0x32, 0x47, 0x0e, 0xda, 0x65, 0x41, 0x14, 0x2b, 0x72, 0x16, 0xd3, 0xac, + 0xc3, 0xcb, 0xe9, 0x4c, 0x27, 0x7f, 0x3a, 0x1c, 0xf5, 0x59, 0xe9, 0x10, + 0x95, 0x39, 0x5d, 0x68, 0xbf, 0x8d, 0xf6, 0x22, 0xed, 0xa0, 0xfd, 0xe4, + 0x9d, 0xe3, 0x75, 0x46, 0xdd, 0x3f, 0xe5, 0xf6, 0x61, 0xbf, 0x5c, 0x2c, + 0x66, 0x25, 0x56, 0xd0, 0x36, 0x4b, 0x19, 0xad, 0xb1, 0x18, 0xb6, 0x69, + 0x96, 0x5c, 0xa6, 0xb8, 0xa1, 0xfe, 0x48, 0x8e, 0x5f, 0xb9, 0xe1, 0xd8, + 0xdf, 0x80, 0x99, 0x98, 0xb5, 0xa7, 0x9d, 0xf4, 0x1b, 0x02, 0xb1, 0x46, + 0x38, 0x6c, 0x6b, 0x9c, 0x0e, 0xd8, 0x3c, 0x4f, 0x2d, 0x8e, 0xdd, 0x72, + 0x1c, 0xf9, 0xc6, 0xea, 0x45, 0x6b, 0xe5, 0xe7, 0xbc, 0x16, 0xab, 0xbc, + 0xff, 0x8c, 0xfe, 0xec, 0x5f, 0x46, 0x7f, 0x57, 0xfa, 0xd4, 0x1f, 0xa5, + 0xe7, 0xcf, 0x18, 0xd9, 0x5f, 0xf6, 0x13, 0xef, 0xf9, 0x76, 0x32, 0x8c, + 0xc5, 0x17, 0x35, 0x5c, 0x64, 0x59, 0x78, 0x95, 0x58, 0x70, 0x95, 0x68, + 0xbe, 0x4a, 0x98, 0x7d, 0xc0, 0x2a, 0x7d, 0xf8, 0x51, 0xf4, 0xa1, 0x80, + 0x4e, 0x95, 0xc7, 0xfd, 0x57, 0x4a, 0xb9, 0xd9, 0x2f, 0xa4, 0x7d, 0xcb, + 0x23, 0xf0, 0x8b, 0xb1, 0xf6, 0xbb, 0xfd, 0x0f, 0x49, 0xfb, 0xf4, 0x5d, + 0x60, 0x6e, 0x95, 0x3a, 0x73, 0x64, 0xef, 0x25, 0x16, 0xf4, 0x3d, 0xee, + 0x3f, 0x8c, 0xd3, 0x50, 0x81, 0xc9, 0xaf, 0x16, 0x55, 0x29, 0x9f, 0x63, + 0x9f, 0xee, 0x83, 0x6f, 0xa5, 0x75, 0xf2, 0x7d, 0x46, 0x95, 0x8a, 0x07, + 0x51, 0xf7, 0x45, 0xf2, 0xec, 0xc2, 0xef, 0x22, 0x0a, 0x70, 0xf2, 0x9d, + 0x26, 0x6f, 0x8b, 0x51, 0x77, 0x1b, 0xdf, 0x11, 0x7c, 0xf3, 0xc9, 0x27, + 0xef, 0x88, 0x6a, 0x1f, 0x5b, 0xa1, 0x3f, 0x0f, 0x1f, 0xa7, 0xee, 0x4d, + 0x5f, 0xc7, 0xee, 0xa5, 0x67, 0xc3, 0xce, 0xb3, 0xd1, 0x2b, 0xcf, 0x87, + 0xaa, 0xcd, 0x5d, 0xfa, 0xb3, 0x73, 0xae, 0xcb, 0x92, 0xa9, 0x2b, 0xea, + 0xfe, 0x5a, 0xe6, 0x3d, 0xc0, 0x3c, 0xf4, 0x31, 0xe0, 0x9f, 0x81, 0x59, + 0xe6, 0xbf, 0x0b, 0x28, 0xa0, 0xec, 0x33, 0x4e, 0xfa, 0x5d, 0xce, 0x78, + 0xef, 0x77, 0xec, 0xfa, 0x2c, 0xd9, 0x93, 0x1e, 0x97, 0x16, 0xdd, 0x36, + 0x1b, 0xda, 0x66, 0x53, 0xe3, 0x72, 0x19, 0x59, 0x85, 0xd9, 0xb6, 0xef, + 0x73, 0x6c, 0x0f, 0x69, 0xdb, 0x2f, 0x5b, 0xff, 0x78, 0x32, 0x87, 0xbe, + 0x53, 0x07, 0xab, 0x54, 0x1c, 0x19, 0x3b, 0x5e, 0x81, 0x0d, 0xa5, 0x14, + 0xdf, 0x70, 0x04, 0x63, 0xc6, 0xf6, 0x4e, 0x7d, 0x56, 0x1e, 0x3a, 0xad, + 0xfd, 0xbc, 0x5e, 0x1b, 0xc5, 0x5b, 0x86, 0xc9, 0xb6, 0x5b, 0xf5, 0xc3, + 0x3e, 0xa6, 0x4e, 0xbb, 0x3e, 0x4b, 0xc6, 0x75, 0x19, 0xb1, 0x8d, 0x67, + 0x52, 0x69, 0x5b, 0x8f, 0x17, 0x25, 0x59, 0xf9, 0xaf, 0x3b, 0x0c, 0x6b, + 0x03, 0xf4, 0x71, 0xff, 0x0f, 0xa9, 0xd4, 0xa2, 0xea, 0x34, 0x64, 0x8c, + 0xb9, 0x40, 0x7f, 0xce, 0xcf, 0x6b, 0xd2, 0x2e, 0xd7, 0xe4, 0x52, 0xe1, + 0xf5, 0xce, 0x9a, 0x85, 0x55, 0x69, 0x2d, 0xc3, 0xda, 0x5f, 0x63, 0xb5, + 0xd8, 0xe4, 0x7a, 0xb4, 0xa4, 0xe7, 0x6d, 0x56, 0xa9, 0x5a, 0x8d, 0x0e, + 0xdc, 0xa6, 0xd7, 0x38, 0x84, 0x8d, 0x57, 0xe2, 0x56, 0x91, 0xfe, 0x1b, + 0x0b, 0x2f, 0x5a, 0xc4, 0x73, 0x9d, 0xab, 0xd6, 0x88, 0xaf, 0xc1, 0x67, + 0x59, 0xe8, 0x5b, 0xe0, 0x6b, 0xf6, 0x7d, 0xce, 0xf8, 0xb1, 0xf4, 0xb2, + 0x2a, 0x15, 0x6b, 0xf9, 0x1d, 0x96, 0x57, 0x60, 0x1f, 0x6a, 0x8d, 0xfa, + 0xee, 0xd6, 0xef, 0x73, 0xd2, 0xef, 0x3e, 0xae, 0xd4, 0xfe, 0xc7, 0x7e, + 0x44, 0xf2, 0xd6, 0x2b, 0xfd, 0x08, 0x5e, 0x2a, 0xe4, 0xbb, 0x96, 0x05, + 0x24, 0x8c, 0x80, 0x60, 0x2f, 0x5a, 0x23, 0xdf, 0x13, 0xed, 0xb7, 0xe1, + 0xb9, 0xfa, 0x86, 0xae, 0x3e, 0xba, 0xd9, 0xca, 0xf9, 0x0b, 0x9a, 0x6b, + 0x6a, 0x6a, 0xe9, 0x49, 0x2b, 0x8f, 0x35, 0xd4, 0xff, 0x98, 0x66, 0x1e, + 0xb2, 0xea, 0xf1, 0x2c, 0xa0, 0xfb, 0xd2, 0xb2, 0x67, 0x35, 0x73, 0xc7, + 0x9d, 0x62, 0xa2, 0xe7, 0xeb, 0x27, 0x3a, 0x96, 0x88, 0xa2, 0xe2, 0xdb, + 0x0f, 0xd1, 0xdb, 0x56, 0x34, 0x16, 0x65, 0xf6, 0xaf, 0x3e, 0x8b, 0xae, + 0xb6, 0x31, 0x4f, 0xd7, 0x49, 0xd2, 0x4c, 0x7f, 0xd6, 0xaa, 0xbe, 0xd5, + 0x1d, 0x74, 0x97, 0x8d, 0x0a, 0xb6, 0xac, 0xde, 0xb7, 0x7a, 0xef, 0x05, + 0x27, 0x4e, 0xd0, 0x2d, 0x36, 0x5d, 0x39, 0x3d, 0x0d, 0xf1, 0xa1, 0x2e, + 0xb4, 0x61, 0xbf, 0x03, 0x2d, 0x7b, 0xfb, 0xbc, 0xcb, 0x77, 0x3e, 0xb5, + 0x9a, 0x6e, 0x61, 0x5e, 0x78, 0x3c, 0x27, 0x9e, 0xa6, 0xfb, 0x1c, 0xd2, + 0xf2, 0x4d, 0xba, 0xc9, 0x21, 0x8b, 0xfe, 0xc4, 0xce, 0xa4, 0x8f, 0x3e, + 0xb0, 0xc0, 0x24, 0x4c, 0x1f, 0xa1, 0xbb, 0xfd, 0xc7, 0xf6, 0xfe, 0xa2, + 0xf9, 0xad, 0xfe, 0x1a, 0x64, 0xd8, 0x4b, 0xaf, 0xb2, 0x9c, 0x5e, 0xb3, + 0xb0, 0x95, 0xb1, 0x68, 0xb3, 0xd1, 0xb9, 0x87, 0xde, 0xe6, 0x21, 0xf9, + 0x03, 0x3f, 0x8e, 0xf2, 0xeb, 0x9d, 0xef, 0xf1, 0xe3, 0x66, 0x83, 0xcd, + 0xbe, 0xc3, 0xec, 0x0d, 0xfc, 0xf8, 0x3e, 0x3f, 0xfe, 0x81, 0x1f, 0x37, + 0x19, 0xb2, 0x9e, 0x6f, 0x4b, 0x83, 0xef, 0xca, 0xe7, 0x8d, 0x4a, 0x74, + 0x8b, 0x4c, 0x3c, 0xe1, 0xc0, 0xe3, 0x97, 0x3c, 0x8c, 0x87, 0x6b, 0x9a, + 0xfb, 0x6e, 0x0b, 0xaf, 0x5e, 0x73, 0xa8, 0x96, 0x7e, 0xc7, 0x39, 0xdb, + 0x58, 0xdd, 0xa6, 0x07, 0xab, 0xcd, 0xa6, 0x87, 0xef, 0x18, 0x4b, 0xef, + 0xb5, 0xe3, 0x71, 0x39, 0xe7, 0x3f, 0x4c, 0x37, 0xca, 0xb6, 0xdd, 0x65, + 0x78, 0xde, 0xaf, 0x5d, 0x1d, 0x32, 0x86, 0x3b, 0xb7, 0xd0, 0xcf, 0x2c, + 0xb2, 0x8f, 0x4f, 0xbf, 0x79, 0xfb, 0xe1, 0xba, 0x90, 0x71, 0xfe, 0x10, + 0x3d, 0x2e, 0x4d, 0xee, 0xa0, 0x47, 0x84, 0xa0, 0xce, 0x3b, 0x56, 0x1b, + 0x67, 0x08, 0x5f, 0x81, 0x28, 0x29, 0x5a, 0x62, 0xe4, 0x8a, 0x39, 0x8a, + 0x59, 0x2f, 0xca, 0x0a, 0x44, 0xb1, 0xfb, 0x8a, 0x9d, 0xc6, 0x6e, 0x70, + 0xc6, 0x05, 0x62, 0x42, 0x01, 0x3d, 0xcc, 0xe5, 0xdf, 0x46, 0x6d, 0xb2, + 0xb1, 0x6d, 0xb2, 0x48, 0x3a, 0x4b, 0x12, 0xe3, 0xb7, 0xd4, 0x64, 0xfc, + 0xd1, 0xd8, 0x63, 0x7c, 0xdf, 0xb2, 0x67, 0xaf, 0x71, 0xf5, 0xbe, 0xd7, + 0x0f, 0x47, 0x8e, 0x36, 0x37, 0x2f, 0x69, 0x6e, 0x5e, 0x7a, 0x7d, 0x4b, + 0xf3, 0x5d, 0x46, 0x81, 0x98, 0x52, 0x60, 0xe4, 0x3f, 0x40, 0xdf, 0xc4, + 0x18, 0x1d, 0xa5, 0xcb, 0x05, 0x55, 0xd3, 0xbb, 0xe8, 0xd0, 0x85, 0xab, + 0x97, 0xd0, 0xf7, 0xd0, 0x82, 0x82, 0xa3, 0x4b, 0xe8, 0x10, 0x54, 0x17, + 0x1e, 0xa2, 0x27, 0xed, 0x9c, 0xa4, 0x77, 0x98, 0x7c, 0x87, 0xae, 0x95, + 0x4a, 0xfa, 0x4c, 0xce, 0xf6, 0x43, 0xf4, 0xbe, 0x4d, 0xf5, 0x7d, 0xc9, + 0x21, 0xba, 0x86, 0x0d, 0x50, 0x6e, 0x49, 0x01, 0x3d, 0x00, 0x76, 0x33, + 0x7d, 0x62, 0xc8, 0x86, 0x5c, 0xbc, 0xba, 0x59, 0xdd, 0xcf, 0x8a, 0x10, + 0x81, 0xd9, 0xdf, 0x67, 0x92, 0xda, 0xe7, 0xa7, 0xc1, 0x9f, 0x27, 0xe9, + 0x35, 0x20, 0x48, 0xd9, 0xa4, 0xdf, 0x67, 0x18, 0x19, 0xe4, 0xc9, 0x74, + 0x9e, 0xb6, 0x49, 0xff, 0x1d, 0xd2, 0x3c, 0x4d, 0x6b, 0x35, 0x75, 0x6a, + 0xfb, 0xe9, 0x3a, 0xff, 0x19, 0x5a, 0x5e, 0xad, 0xe5, 0xb5, 0x7a, 0x7d, + 0x35, 0x62, 0x7f, 0x64, 0x79, 0x93, 0x6e, 0x83, 0x61, 0xaa, 0xaf, 0x09, + 0xbb, 0x38, 0xf3, 0x9e, 0x4c, 0x5a, 0xc5, 0xed, 0x74, 0x9b, 0xac, 0x19, + 0x5e, 0xbd, 0x0b, 0x4d, 0xdf, 0x35, 0x0d, 0xad, 0x33, 0xb4, 0xce, 0xd0, + 0xeb, 0x59, 0x95, 0xef, 0x90, 0xe7, 0x27, 0x25, 0x6b, 0xd2, 0x74, 0x99, + 0xa6, 0xad, 0xb2, 0x04, 0x8b, 0xd6, 0xe3, 0x26, 0x62, 0xaa, 0x47, 0xbd, + 0x13, 0xb0, 0x48, 0xda, 0xaa, 0xc7, 0x46, 0xbd, 0x9b, 0x60, 0x9a, 0xa3, + 0x69, 0xbe, 0xce, 0xeb, 0xc1, 0xd9, 0x55, 0x7e, 0x26, 0x61, 0x6a, 0x6b, + 0x31, 0x7a, 0xcb, 0x29, 0xbb, 0x89, 0x4f, 0xf7, 0x25, 0x3d, 0xee, 0xd3, + 0x34, 0x9d, 0x9e, 0x19, 0xbf, 0x56, 0x59, 0x4e, 0xad, 0x2c, 0x31, 0x3d, + 0x76, 0xb5, 0x5a, 0xd6, 0x2a, 0x65, 0x56, 0x39, 0xfe, 0xa3, 0x65, 0x35, + 0x6a, 0x59, 0xa3, 0xa9, 0xff, 0x8d, 0x32, 0xa5, 0xee, 0x9f, 0x4c, 0x5b, + 0x49, 0xed, 0xc1, 0xad, 0xa6, 0x7c, 0x8c, 0xe5, 0x9a, 0xb6, 0xe9, 0xbe, + 0xb2, 0xa6, 0xd0, 0xc4, 0x4f, 0xc9, 0xf8, 0xc5, 0x14, 0xd3, 0x18, 0x17, + 0x66, 0xe6, 0xae, 0x4c, 0xeb, 0xdd, 0xba, 0xcc, 0xa9, 0xba, 0x9e, 0xda, + 0x8c, 0xa5, 0x6a, 0x5b, 0x6d, 0xc6, 0x5a, 0xe4, 0x90, 0x70, 0x11, 0x2e, + 0xc9, 0xa2, 0x9c, 0x8c, 0xf2, 0x4e, 0x12, 0x15, 0x64, 0x6f, 0x0e, 0x47, + 0xc3, 0xa9, 0xa5, 0x64, 0x2c, 0x6d, 0x22, 0xeb, 0xd2, 0x26, 0x3c, 0xed, + 0xfc, 0xac, 0xe8, 0xa5, 0xfc, 0xb6, 0xa1, 0x60, 0x74, 0x47, 0x68, 0x53, + 0x30, 0x35, 0x30, 0x14, 0x4a, 0xd0, 0xc4, 0xb6, 0xd8, 0xae, 0x78, 0x2c, + 0x1a, 0x8a, 0xa6, 0xba, 0x43, 0xa1, 0x44, 0x6f, 0x38, 0xb4, 0xa7, 0xf6, + 0xbc, 0xe0, 0x48, 0x90, 0x5c, 0x6d, 0xb1, 0x68, 0x34, 0x34, 0x90, 0x0a, + 0xc7, 0xa2, 0x24, 0x56, 0x92, 0xb1, 0xb2, 0x83, 0x44, 0x07, 0x19, 0x1d, + 0x15, 0x40, 0x07, 0x59, 0x3a, 0x3a, 0x38, 0xd1, 0x09, 0xa6, 0xb3, 0x0b, + 0x4c, 0x17, 0x89, 0x4e, 0x32, 0x3a, 0x19, 0x5d, 0x34, 0xbd, 0x73, 0x78, + 0x20, 0xd4, 0x3a, 0x30, 0x10, 0x4a, 0x26, 0xc3, 0xdb, 0xc2, 0x91, 0x70, + 0x6a, 0xdf, 0xda, 0xd8, 0x60, 0xa8, 0x3b, 0x11, 0x1b, 0x09, 0x0f, 0xa2, + 0xc6, 0x92, 0xd5, 0xa1, 0x7d, 0xdb, 0x62, 0xc1, 0xc4, 0xe0, 0x8a, 0x70, + 0x72, 0x57, 0x38, 0x99, 0xec, 0x0a, 0x27, 0x53, 0xa1, 0x28, 0x14, 0x02, + 0x25, 0x75, 0xa1, 0xec, 0x2e, 0x2e, 0xbb, 0xab, 0x93, 0xac, 0x5d, 0x9d, + 0x92, 0xeb, 0x82, 0x48, 0xca, 0x21, 0xc3, 0xa3, 0x8b, 0x26, 0x76, 0x05, + 0xa3, 0x83, 0x89, 0x58, 0x78, 0xb0, 0x2e, 0x18, 0x8f, 0xd7, 0xb5, 0xa2, + 0x91, 0x23, 0xa8, 0xa4, 0x89, 0xe6, 0x67, 0xcb, 0xe3, 0xf1, 0x48, 0x78, + 0x20, 0xc8, 0x3d, 0x98, 0x9d, 0xb6, 0xe9, 0x0a, 0x6f, 0x0f, 0x0d, 0xec, + 0x1b, 0x88, 0x84, 0xda, 0x82, 0x91, 0xc8, 0xb6, 0xe0, 0xc0, 0xce, 0x64, + 0x13, 0x4d, 0x3e, 0x5d, 0x2e, 0xb3, 0x6a, 0x20, 0x16, 0x45, 0x23, 0x53, + 0x75, 0x6d, 0x4c, 0xf7, 0xa6, 0xcc, 0xaa, 0x1d, 0x89, 0x60, 0x7c, 0x28, + 0x3c, 0x90, 0xac, 0x6b, 0x0b, 0x46, 0x47, 0x82, 0x28, 0x70, 0xc6, 0x38, + 0xaa, 0x58, 0x24, 0x96, 0x58, 0x19, 0x8e, 0xa4, 0x42, 0x89, 0xd3, 0xeb, + 0xd7, 0x04, 0x53, 0x89, 0xf0, 0xde, 0x26, 0xaa, 0xf8, 0x5c, 0x7d, 0x56, + 0x51, 0x93, 0xc6, 0x9a, 0x76, 0x07, 0xc3, 0xd1, 0xd4, 0xf8, 0x9a, 0x98, + 0xd4, 0x94, 0x8c, 0xd5, 0x6c, 0xc0, 0x44, 0x37, 0xd1, 0x94, 0x8c, 0x22, + 0x96, 0xac, 0x5b, 0x3e, 0x1c, 0x8e, 0x0c, 0xce, 0xee, 0x6d, 0xdf, 0xd0, + 0xd3, 0xb1, 0x6e, 0x6d, 0x13, 0x15, 0x65, 0xeb, 0xa2, 0x83, 0x91, 0x50, + 0x13, 0x15, 0x9b, 0x85, 0x1d, 0xcb, 0xc3, 0xd1, 0x41, 0x6e, 0xd3, 0x68, + 0xf9, 0x3c, 0x52, 0x75, 0xed, 0x83, 0xe1, 0x54, 0x70, 0x1b, 0x9b, 0x4f, + 0xca, 0x56, 0xf4, 0x84, 0x22, 0xca, 0xbf, 0xcc, 0x35, 0x2b, 0x4d, 0x3c, + 0x18, 0xd5, 0xfe, 0x39, 0x36, 0x17, 0x74, 0x51, 0x55, 0xde, 0x19, 0xa7, + 0xd1, 0xf4, 0x60, 0x98, 0xa2, 0x3b, 0x64, 0x07, 0xb8, 0x80, 0x53, 0x0a, + 0x0f, 0xe0, 0x91, 0x29, 0x7c, 0xb4, 0x5b, 0xc3, 0xa9, 0x70, 0x84, 0xc7, + 0x6e, 0x7c, 0x61, 0x33, 0x55, 0x66, 0x84, 0x23, 0x58, 0x23, 0x75, 0x6d, + 0x43, 0xb1, 0x44, 0x28, 0x26, 0x07, 0x30, 0x94, 0x98, 0xbd, 0x32, 0x11, + 0xdc, 0x95, 0x71, 0xa9, 0x26, 0x9a, 0xf6, 0x39, 0xb6, 0xe6, 0xf1, 0x91, + 0x5a, 0xac, 0x86, 0xf6, 0x91, 0x50, 0x34, 0x6b, 0xfc, 0xa5, 0x62, 0x4d, + 0x8c, 0x07, 0x47, 0xeb, 0x2a, 0xb2, 0x75, 0xbc, 0x4e, 0x67, 0xaf, 0x8b, + 0xae, 0x8c, 0x0d, 0x0c, 0x27, 0xd5, 0x7a, 0x4e, 0xaf, 0x22, 0x73, 0xf3, + 0x33, 0xa6, 0xe6, 0x51, 0xcc, 0x08, 0x57, 0x25, 0x62, 0xc3, 0xf1, 0x26, + 0x5a, 0x38, 0x56, 0x13, 0x48, 0x84, 0x42, 0xeb, 0xb6, 0x25, 0x43, 0x89, + 0x11, 0xf4, 0x6d, 0x5d, 0x74, 0x55, 0x24, 0xb6, 0x2d, 0x18, 0xe9, 0x0a, + 0xee, 0x8b, 0x0d, 0xa7, 0x46, 0xab, 0x99, 0xf9, 0xf9, 0xf9, 0x9a, 0x68, + 0x6e, 0xb6, 0x41, 0xd0, 0x1c, 0x10, 0xea, 0xb2, 0xc2, 0xc3, 0x9a, 0x60, + 0x34, 0xb8, 0x83, 0xb3, 0xd4, 0x7f, 0xe9, 0x2c, 0x1c, 0x51, 0x3a, 0xa2, + 0xdb, 0x63, 0x63, 0xda, 0xff, 0x05, 0x79, 0xd2, 0x51, 0xa8, 0x89, 0x6a, + 0xb3, 0xf3, 0x85, 0xa3, 0xf1, 0xe1, 0xd4, 0xae, 0x50, 0x6a, 0x28, 0x36, + 0x58, 0xb7, 0x3c, 0x98, 0x44, 0xe1, 0x48, 0x8f, 0xc6, 0x40, 0xb3, 0xb7, + 0x8d, 0xb1, 0x67, 0x17, 0x8f, 0x25, 0x54, 0x73, 0x2a, 0x4f, 0x6f, 0x36, + 0xa6, 0xc8, 0x9a, 0x2f, 0xb0, 0x5d, 0x23, 0xf9, 0xcc, 0xe8, 0xd4, 0x75, + 0x0d, 0xc4, 0x76, 0xd5, 0x25, 0x76, 0x25, 0x23, 0x75, 0xe7, 0x21, 0xc2, + 0xd6, 0x8d, 0x89, 0xdc, 0xb3, 0xb3, 0x42, 0x7b, 0x13, 0x55, 0x7f, 0x71, + 0x06, 0x53, 0x6b, 0x96, 0x7d, 0xa1, 0xf5, 0xe7, 0xc6, 0xf5, 0x26, 0x5a, + 0xf9, 0x85, 0x05, 0x9c, 0x26, 0xf2, 0xcf, 0xce, 0x76, 0x9c, 0xc6, 0xff, + 0xd7, 0x72, 0xd8, 0xe7, 0xbe, 0x28, 0x2b, 0x2f, 0x7f, 0x39, 0xb8, 0x81, + 0x60, 0x62, 0x47, 0x08, 0x2b, 0xab, 0xf4, 0x8b, 0xb2, 0x34, 0x51, 0x59, + 0xd7, 0x60, 0x30, 0x32, 0x12, 0xde, 0x59, 0x87, 0x00, 0x13, 0x4b, 0xc9, + 0xbd, 0xa1, 0xae, 0x3d, 0x3a, 0x10, 0x89, 0x25, 0x11, 0x67, 0xda, 0x22, + 0xc1, 0xa4, 0x0c, 0xfa, 0x63, 0x6d, 0x3a, 0x30, 0xb8, 0x09, 0xad, 0x2f, + 0x1d, 0x47, 0xbf, 0x26, 0xb4, 0x6b, 0x9b, 0x36, 0x08, 0xc1, 0x64, 0xfa, + 0x38, 0x26, 0x3d, 0xe1, 0x1d, 0xd1, 0x60, 0x6a, 0x38, 0x21, 0xc3, 0x27, + 0x6f, 0xcc, 0x75, 0x11, 0x4c, 0x31, 0x42, 0x4a, 0x30, 0xd1, 0x13, 0xda, + 0x3d, 0x1c, 0x8a, 0x0e, 0x40, 0xe3, 0x31, 0x6b, 0x54, 0x75, 0x65, 0x26, + 0x51, 0x47, 0x24, 0x12, 0xda, 0x11, 0x8c, 0xa8, 0x99, 0x6b, 0xdf, 0x3b, + 0x10, 0x8a, 0xab, 0x09, 0x9f, 0x3d, 0x8e, 0x4d, 0x62, 0xc7, 0xf0, 0x2e, + 0xf4, 0xdd, 0x64, 0x55, 0x64, 0xb6, 0xc2, 0xe6, 0x27, 0x5d, 0xb1, 0xd4, + 0x24, 0x5c, 0x1b, 0xeb, 0x19, 0x1e, 0x18, 0x52, 0xbe, 0x6a, 0xca, 0xe7, + 0x35, 0x99, 0xac, 0xdb, 0x76, 0x9e, 0xdc, 0x61, 0xa6, 0x9b, 0x64, 0x3d, + 0xa1, 0x81, 0xe1, 0x04, 0x7c, 0xe8, 0x34, 0x59, 0x54, 0x10, 0xe7, 0x35, + 0x32, 0x2a, 0x4b, 0x84, 0xb6, 0xf3, 0x96, 0x81, 0x66, 0x8c, 0xc4, 0xd4, + 0x16, 0xad, 0x26, 0xd1, 0x54, 0xc4, 0x94, 0x71, 0xcc, 0x55, 0xd3, 0x9a, + 0x68, 0x82, 0xd2, 0xc9, 0xa0, 0xde, 0x9a, 0x48, 0x04, 0xf7, 0xb1, 0xdf, + 0x34, 0x91, 0xdb, 0x24, 0x1e, 0x5f, 0xd2, 0x4c, 0x8e, 0x9e, 0x15, 0xab, + 0xcf, 0xed, 0x58, 0x1b, 0x20, 0x6b, 0x60, 0x73, 0x77, 0x3b, 0x15, 0x9e, + 0xe2, 0x45, 0x94, 0x67, 0xf6, 0x60, 0x12, 0xbd, 0x64, 0xf4, 0xe2, 0xc0, + 0xd2, 0x8b, 0xe3, 0x8b, 0xb5, 0x97, 0x8f, 0x4a, 0x36, 0x7e, 0xe2, 0x2c, + 0xd3, 0xdb, 0x49, 0xf6, 0xde, 0xce, 0x8e, 0x95, 0x2b, 0x71, 0xba, 0xe9, + 0xed, 0x94, 0x8a, 0x4e, 0x56, 0x58, 0x7a, 0x71, 0x76, 0xc2, 0xa3, 0x8b, + 0xc5, 0x7c, 0xe0, 0xe9, 0xed, 0xec, 0x83, 0x35, 0x33, 0x5d, 0x5c, 0x46, + 0x97, 0x34, 0xed, 0x52, 0xa6, 0x7c, 0x0c, 0xea, 0x85, 0x11, 0x04, 0x2c, + 0x77, 0x48, 0x22, 0xab, 0xea, 0x92, 0x59, 0x71, 0x2b, 0x06, 0xdb, 0xd7, + 0x29, 0x9f, 0x38, 0x53, 0xf5, 0xf6, 0xa1, 0xd2, 0x3e, 0x69, 0x22, 0xfa, + 0xc8, 0xd2, 0xc7, 0xa6, 0x78, 0x74, 0x31, 0x0b, 0x35, 0x0c, 0x6d, 0x7d, + 0x9d, 0x9c, 0xb6, 0x82, 0xb0, 0x80, 0x35, 0xa8, 0xd6, 0xde, 0xd7, 0x25, + 0xc5, 0x36, 0xa6, 0x90, 0xf7, 0xe3, 0x18, 0xd8, 0xdf, 0x41, 0xde, 0xfe, + 0xb1, 0xee, 0x56, 0xd4, 0x3f, 0xce, 0x6c, 0xbb, 0x54, 0x2c, 0x9e, 0xed, + 0xf7, 0xfb, 0x33, 0xfc, 0x5c, 0xf0, 0xb9, 0xa3, 0xbc, 0x29, 0x91, 0xa5, + 0xa9, 0x37, 0x27, 0xe6, 0x99, 0x13, 0xf3, 0xcd, 0x89, 0x05, 0xe6, 0xc4, + 0x42, 0x73, 0x62, 0x91, 0x39, 0xd1, 0x60, 0x4e, 0x34, 0x9a, 0x5a, 0x53, + 0x6f, 0xe2, 0xe7, 0x99, 0xf8, 0xf9, 0x26, 0x7e, 0x81, 0x89, 0x5f, 0x68, + 0xe2, 0x17, 0x99, 0xf8, 0x06, 0x13, 0xdf, 0x38, 0x5a, 0xd9, 0xca, 0x48, + 0x70, 0x47, 0x92, 0xf2, 0xb3, 0xb6, 0x24, 0x2a, 0x0e, 0x8e, 0xb3, 0xf5, + 0x71, 0x0e, 0x76, 0xe0, 0xae, 0xe0, 0xb6, 0x50, 0x84, 0x2c, 0xc1, 0xc1, + 0x41, 0x9a, 0x8c, 0xc7, 0xf8, 0x7b, 0x2f, 0xb9, 0x83, 0xdb, 0x71, 0xfa, + 0x63, 0x1f, 0x54, 0x01, 0x7f, 0x90, 0x3c, 0x7c, 0xf0, 0x58, 0x3e, 0x9c, + 0x4a, 0xc5, 0xa2, 0xdd, 0x09, 0x94, 0x2e, 0x45, 0xa1, 0xed, 0x38, 0x77, + 0x98, 0xad, 0xec, 0xdb, 0x62, 0xb0, 0xd8, 0x45, 0xf6, 0x81, 0x20, 0x36, + 0x88, 0x41, 0x72, 0x2b, 0x6a, 0x3a, 0xe9, 0xe7, 0x0f, 0x64, 0x5d, 0x0e, + 0x6c, 0x38, 0x29, 0x07, 0x13, 0x54, 0xc8, 0xa1, 0x2e, 0x64, 0x32, 0x2b, + 0x91, 0x02, 0xd3, 0x1e, 0xa5, 0x8f, 0xc5, 0x94, 0x3b, 0xc0, 0x3b, 0x02, + 0x9f, 0x33, 0x5b, 0x53, 0x54, 0x90, 0x49, 0xb4, 0xc5, 0x86, 0xa3, 0x29, + 0x14, 0x0e, 0x2b, 0x9c, 0x4e, 0x93, 0x52, 0x46, 0xc5, 0xfa, 0x4c, 0x9d, + 0x5c, 0x2e, 0x1b, 0xaa, 0x1a, 0x49, 0x53, 0x07, 0x12, 0xa1, 0x60, 0x6a, + 0xec, 0x36, 0xc3, 0xbb, 0x2b, 0x39, 0x06, 0x63, 0xf2, 0xa8, 0x45, 0xce, + 0x90, 0x3e, 0x55, 0x82, 0x8b, 0x0e, 0x26, 0x37, 0x85, 0x53, 0x43, 0xe4, + 0xdb, 0x8e, 0x03, 0xe8, 0xb8, 0xf9, 0x92, 0xcb, 0xf7, 0xf1, 0x30, 0x50, + 0x0e, 0x5b, 0xc8, 0x33, 0x13, 0xe5, 0x6d, 0x1f, 0x3d, 0x3a, 0x0d, 0xd2, + 0x54, 0xac, 0xe1, 0xac, 0x9c, 0xd2, 0x88, 0x83, 0x7f, 0xc7, 0x20, 0x4d, + 0x3b, 0x55, 0x99, 0x75, 0x9b, 0xc9, 0x91, 0x5a, 0x39, 0x2a, 0x85, 0x19, + 0x76, 0x4d, 0x30, 0xb9, 0x13, 0xc5, 0x4e, 0x60, 0xc1, 0xe8, 0x7d, 0x22, + 0x3d, 0x48, 0x6e, 0x88, 0xdb, 0x82, 0x89, 0x50, 0xaa, 0x1b, 0x1b, 0x88, + 0xcc, 0x59, 0xcc, 0x12, 0x84, 0xf4, 0x0e, 0x9c, 0xa0, 0xf7, 0xae, 0x8c, + 0x25, 0xd4, 0x00, 0xe5, 0x6b, 0x29, 0x5c, 0x23, 0x94, 0x48, 0x92, 0x93, + 0x93, 0xbc, 0xdc, 0xa8, 0x88, 0x39, 0xde, 0xa6, 0x78, 0xff, 0xe1, 0x63, + 0x6f, 0x7b, 0x54, 0x55, 0x96, 0x25, 0xec, 0x49, 0x05, 0x13, 0x29, 0x72, + 0x49, 0xb1, 0x9e, 0x1d, 0x8e, 0x95, 0xe9, 0x81, 0xcb, 0xe3, 0x04, 0x1f, + 0x2e, 0x03, 0x61, 0x0c, 0xe8, 0x64, 0xa4, 0x64, 0xa7, 0x43, 0x83, 0xa7, + 0xc6, 0x36, 0xdf, 0x69, 0x55, 0xb2, 0x99, 0x7a, 0x0c, 0xce, 0x0a, 0x85, + 0x77, 0x0c, 0xa5, 0x64, 0x39, 0x67, 0x81, 0x8b, 0x70, 0x2a, 0x34, 0xb8, + 0x21, 0xb4, 0x03, 0xfd, 0x5b, 0x8e, 0x27, 0x9c, 0x66, 0x3c, 0x15, 0xb7, + 0x9c, 0xbb, 0x23, 0x4b, 0x35, 0x8f, 0xfa, 0x84, 0xb4, 0x30, 0xeb, 0x10, + 0x44, 0x67, 0xa6, 0xc5, 0x81, 0x7d, 0xf1, 0x10, 0x46, 0x8a, 0x8f, 0x24, + 0xbd, 0xe1, 0x44, 0x6a, 0x38, 0x18, 0x49, 0x1f, 0x0a, 0x58, 0x23, 0xbb, + 0xda, 0x11, 0x4d, 0xa6, 0x82, 0xd8, 0x20, 0xe5, 0xc4, 0x64, 0x69, 0xb9, + 0xc6, 0x2e, 0xbd, 0x85, 0xac, 0x8b, 0xf6, 0xc0, 0xe5, 0x42, 0x51, 0x39, + 0x20, 0xa8, 0x2c, 0x88, 0x71, 0x4b, 0x85, 0x64, 0x9f, 0x54, 0xd5, 0x32, + 0xbb, 0xee, 0xaa, 0x72, 0xe4, 0xbc, 0x51, 0x01, 0x5a, 0xea, 0x40, 0x6a, + 0x43, 0x70, 0xcf, 0xd9, 0x69, 0x66, 0xb3, 0xac, 0x7c, 0x43, 0x2c, 0x96, + 0xe2, 0xae, 0xc8, 0xdc, 0x99, 0xab, 0x0e, 0x77, 0xd7, 0x63, 0x16, 0xa8, + 0x49, 0x62, 0x8f, 0xe8, 0xd9, 0x87, 0xd5, 0xbd, 0xab, 0x07, 0x3b, 0x48, + 0x18, 0x4d, 0x2e, 0x80, 0x44, 0x8d, 0xf6, 0x06, 0xb9, 0x2c, 0xd8, 0x22, + 0x80, 0x43, 0x41, 0x64, 0xed, 0xf0, 0x2e, 0xf6, 0x09, 0xe5, 0x04, 0x1b, + 0xf9, 0xc6, 0x15, 0x09, 0x47, 0x31, 0x9a, 0x6c, 0x95, 0x94, 0xd9, 0x36, + 0x46, 0xc3, 0xbc, 0xf0, 0xd8, 0x4a, 0x1a, 0x9d, 0x7a, 0x32, 0x97, 0x7e, + 0xd5, 0x1b, 0xce, 0x04, 0x24, 0xce, 0xb3, 0x09, 0x0b, 0x23, 0xb6, 0x27, + 0x10, 0xdb, 0x89, 0x71, 0x98, 0x96, 0x49, 0x4b, 0xa3, 0x48, 0x08, 0xa7, + 0xac, 0x78, 0x24, 0xb8, 0x4f, 0xad, 0x3c, 0x2b, 0xb4, 0x67, 0xcb, 0xe7, + 0x66, 0x9a, 0x84, 0xe5, 0x83, 0x8b, 0x60, 0xd6, 0xe2, 0x38, 0x2b, 0xc6, + 0x55, 0x14, 0x6a, 0x4d, 0x3c, 0xde, 0x1d, 0x64, 0xc7, 0x21, 0x77, 0x46, + 0xb0, 0x21, 0x94, 0xc4, 0x11, 0x23, 0x23, 0x59, 0x9e, 0x09, 0x5c, 0x94, + 0xaf, 0x24, 0x2b, 0xf4, 0x1a, 0xd7, 0x49, 0x4c, 0xdc, 0x8a, 0xd8, 0x9e, + 0x28, 0xe5, 0x66, 0x92, 0x1b, 0xe3, 0x54, 0x9c, 0x49, 0xc8, 0x49, 0x3d, + 0x2b, 0x3c, 0x38, 0x88, 0x96, 0xeb, 0x5a, 0xd7, 0xc4, 0x50, 0xa5, 0xcc, + 0x93, 0x25, 0x48, 0x04, 0x77, 0xa4, 0xcb, 0x94, 0x02, 0x14, 0xa3, 0xcb, + 0x94, 0x57, 0x66, 0x2a, 0xd2, 0x89, 0x50, 0x02, 0xe1, 0x68, 0x97, 0x5e, + 0xd3, 0x79, 0x43, 0x58, 0xe5, 0xe9, 0x6a, 0xa8, 0x84, 0x53, 0x3d, 0xb1, + 0xed, 0xda, 0x5d, 0x13, 0xb1, 0x5d, 0x6a, 0xa0, 0xc8, 0x39, 0x84, 0x12, + 0x64, 0x8c, 0xb1, 0x0e, 0xc5, 0x92, 0x58, 0x75, 0x58, 0x53, 0xeb, 0xe4, + 0x91, 0x24, 0x49, 0x85, 0xfc, 0x26, 0x26, 0x1c, 0x8c, 0xb4, 0x05, 0xe3, + 0xc9, 0x35, 0x98, 0x18, 0xca, 0xd7, 0x02, 0x38, 0x01, 0xfb, 0x43, 0xe1, + 0x68, 0x52, 0x79, 0x43, 0x4e, 0x38, 0xed, 0xe0, 0x94, 0x27, 0xd9, 0x73, + 0xd5, 0xa5, 0x80, 0x3c, 0x88, 0x9d, 0xa1, 0x84, 0xac, 0xa7, 0x55, 0x45, + 0x10, 0x72, 0xa2, 0xde, 0xde, 0x60, 0x64, 0x38, 0x44, 0xf6, 0x30, 0x4e, + 0x45, 0x3b, 0x43, 0xa8, 0x3a, 0x99, 0x71, 0x7c, 0x67, 0x38, 0xb9, 0x2e, + 0x1e, 0xc4, 0x31, 0x11, 0x59, 0x93, 0x99, 0xc5, 0x2b, 0x5f, 0x86, 0x60, + 0xc9, 0x43, 0x14, 0xc3, 0xc9, 0xad, 0x7d, 0x6f, 0x3c, 0x12, 0x4b, 0x04, + 0x95, 0x7b, 0x72, 0x68, 0x18, 0x44, 0x0b, 0x92, 0x7a, 0xee, 0xa9, 0x64, + 0xe7, 0x69, 0xde, 0xd6, 0xe4, 0xa7, 0x15, 0x3d, 0x43, 0x3c, 0xd4, 0xb6, + 0x88, 0xdc, 0xba, 0xec, 0x91, 0x50, 0x74, 0x07, 0x82, 0xb1, 0x35, 0xca, + 0x53, 0x98, 0x17, 0x35, 0x87, 0x4a, 0x7b, 0x6c, 0x1b, 0x87, 0x7f, 0xf2, + 0xc6, 0xb6, 0x6f, 0x4f, 0x86, 0x52, 0xcb, 0xf7, 0xb5, 0xa5, 0xf7, 0x87, + 0x24, 0x79, 0x62, 0xd1, 0xf4, 0x3b, 0x9a, 0x36, 0xb9, 0x01, 0x20, 0x2c, + 0x8c, 0x8a, 0x56, 0x84, 0x92, 0xa9, 0x44, 0x6c, 0x1f, 0x7b, 0xcd, 0xa8, + 0x50, 0x7b, 0x96, 0x29, 0x67, 0xda, 0xb5, 0xa6, 0x8e, 0x8a, 0x7a, 0x82, + 0x23, 0xa1, 0xf4, 0x70, 0xa8, 0x85, 0x6d, 0xb2, 0x97, 0xc3, 0x9d, 0x5d, + 0x44, 0x4f, 0x2a, 0x16, 0x8f, 0x43, 0x54, 0x82, 0x70, 0x2d, 0xdb, 0x71, + 0xca, 0xa5, 0x0d, 0x9d, 0x88, 0xc2, 0x93, 0xf6, 0x50, 0x7e, 0xcc, 0x7c, + 0xfb, 0xa6, 0x82, 0x58, 0xd6, 0x56, 0x4d, 0x79, 0xb1, 0xa8, 0x5c, 0x09, + 0x32, 0xc2, 0x52, 0x4e, 0x2c, 0x9a, 0x76, 0xe3, 0x7c, 0xc9, 0xae, 0x19, + 0x8e, 0xa4, 0xc2, 0x71, 0x0c, 0xaf, 0x43, 0x26, 0xe1, 0x8a, 0x4e, 0xde, + 0xfc, 0x65, 0x56, 0x58, 0xf4, 0x84, 0xcf, 0x0f, 0xa5, 0xf7, 0xa6, 0x5c, + 0x24, 0x11, 0xcd, 0x5b, 0xe1, 0xe1, 0x83, 0x52, 0x87, 0x44, 0x5a, 0xa7, + 0x93, 0x1b, 0x42, 0xbb, 0x50, 0x97, 0x4c, 0x9a, 0xb7, 0x7b, 0xb4, 0x41, + 0x4d, 0xb0, 0x6c, 0x83, 0x3d, 0xa6, 0x3c, 0xc1, 0x16, 0x97, 0xde, 0x9e, + 0x1f, 0xcf, 0xf2, 0xf3, 0xe9, 0xf1, 0x58, 0x7c, 0x38, 0x72, 0xda, 0x8d, + 0xd7, 0x83, 0x6d, 0x25, 0x95, 0xf5, 0x96, 0x83, 0x1c, 0x09, 0xf5, 0x26, + 0x8d, 0xca, 0x12, 0x88, 0xe4, 0x70, 0x8a, 0xc4, 0xe9, 0x5f, 0xb2, 0xd1, + 0xb4, 0x84, 0x6c, 0xe2, 0x69, 0xce, 0x33, 0x2e, 0xa5, 0xe5, 0xae, 0x50, + 0x1e, 0x8e, 0x2f, 0x3c, 0x2d, 0x72, 0xdc, 0xc9, 0x02, 0x3f, 0xa1, 0x82, + 0x24, 0x6f, 0x61, 0x99, 0xb7, 0x5e, 0x94, 0x97, 0xd4, 0x1b, 0x92, 0xdc, + 0xc7, 0x4a, 0xcc, 0xa9, 0x0e, 0xd5, 0x63, 0xb9, 0xcc, 0x8a, 0x93, 0xe3, + 0xec, 0x37, 0x32, 0x33, 0xaa, 0xc7, 0xf1, 0x89, 0xd7, 0xd7, 0x24, 0xa4, + 0xc6, 0x7d, 0x8d, 0x22, 0xed, 0x32, 0x51, 0x9a, 0x1c, 0x9c, 0xe2, 0xe6, + 0x4d, 0x48, 0xa6, 0x23, 0xf5, 0xc6, 0xb0, 0x29, 0x86, 0x4e, 0x1d, 0x57, + 0xcc, 0xdb, 0x71, 0x30, 0x25, 0x5b, 0x18, 0x08, 0x61, 0x67, 0x4e, 0x04, + 0x13, 0xfb, 0xd2, 0x21, 0x1b, 0x9b, 0x34, 0xe5, 0x26, 0x55, 0x74, 0x5e, + 0x2b, 0xc3, 0x5d, 0x32, 0x2b, 0x2a, 0xbb, 0xd2, 0x49, 0x74, 0x91, 0x07, + 0x60, 0x53, 0x38, 0x12, 0x59, 0x1b, 0x4b, 0x49, 0xdf, 0xcb, 0x4b, 0x62, + 0xc9, 0x65, 0x82, 0x52, 0x3e, 0xa7, 0x32, 0x41, 0x09, 0xc6, 0x3c, 0x7c, + 0xaa, 0x1f, 0x5c, 0x49, 0x7e, 0x12, 0x2e, 0x3d, 0x9a, 0xcc, 0x4d, 0x0e, + 0x6f, 0x4b, 0xdf, 0x1c, 0x29, 0x07, 0x89, 0xa4, 0xbc, 0x68, 0x91, 0x3d, + 0xa5, 0x76, 0xfb, 0x99, 0xa9, 0xec, 0x3d, 0x7e, 0xd5, 0xa9, 0x67, 0x95, + 0x59, 0xe3, 0x18, 0x8c, 0x39, 0xba, 0x94, 0x8f, 0x35, 0x3a, 0xcd, 0xa9, + 0xe0, 0xcc, 0x2f, 0x61, 0xc9, 0x51, 0x72, 0xc6, 0x58, 0xbb, 0xac, 0x2d, + 0x7d, 0xfa, 0x58, 0xbd, 0x79, 0xff, 0x1c, 0xa7, 0x5b, 0xd9, 0xdb, 0xa9, + 0xef, 0x14, 0x83, 0x8e, 0x31, 0xa1, 0x76, 0x8c, 0xc5, 0x98, 0x88, 0x7a, + 0xea, 0xd0, 0xf4, 0x8c, 0xe7, 0x80, 0xa7, 0x76, 0xb8, 0xe7, 0x34, 0xce, + 0x61, 0x4f, 0x0d, 0x85, 0x71, 0x77, 0xd2, 0x74, 0x2e, 0x39, 0x53, 0x31, + 0x75, 0x27, 0x26, 0x0b, 0x26, 0x94, 0x4a, 0x87, 0xe3, 0x83, 0x58, 0xae, + 0xe9, 0xe3, 0x5c, 0xc6, 0x55, 0x79, 0x53, 0xd2, 0x07, 0xb7, 0x0a, 0x65, + 0xa2, 0x52, 0xfa, 0x68, 0xc8, 0x26, 0xea, 0xac, 0xc0, 0x86, 0x99, 0xc3, + 0xe0, 0x0c, 0xb3, 0xe9, 0x38, 0xfa, 0x52, 0xb3, 0x3e, 0xab, 0xae, 0x8c, + 0x89, 0x6d, 0x44, 0x6e, 0x43, 0x0e, 0x49, 0xd6, 0x6d, 0x27, 0xeb, 0x88, + 0x3c, 0xfd, 0xf0, 0xd3, 0x1c, 0xce, 0xdc, 0x23, 0xa7, 0x1e, 0x47, 0x12, + 0x17, 0x5f, 0xbc, 0xa2, 0xe1, 0x82, 0x32, 0x0e, 0x14, 0x38, 0xcb, 0x97, + 0x2d, 0x2e, 0x83, 0x23, 0x95, 0x55, 0x97, 0x0d, 0xa0, 0xc1, 0xe1, 0x88, + 0xdc, 0x96, 0x6a, 0x76, 0x61, 0x3d, 0x43, 0x91, 0x40, 0xc5, 0xc1, 0x64, + 0x08, 0xca, 0xa1, 0x60, 0xb2, 0x06, 0x37, 0x14, 0x84, 0x96, 0xe1, 0x5d, + 0xc9, 0xb2, 0xc5, 0xdb, 0x83, 0x91, 0x64, 0xa8, 0xba, 0x6c, 0x57, 0x38, + 0x5a, 0x13, 0x8c, 0x87, 0xcb, 0x16, 0xcf, 0x5d, 0x58, 0x5d, 0x86, 0xa2, + 0x93, 0xc8, 0x8b, 0x6c, 0xf3, 0x6a, 0xe7, 0xd5, 0xd6, 0xfb, 0x6b, 0x06, + 0x43, 0x23, 0x55, 0xc1, 0x58, 0x32, 0xbe, 0xa0, 0xec, 0x22, 0x32, 0xea, + 0xc5, 0x6b, 0xc6, 0x34, 0x67, 0x89, 0xb5, 0x64, 0x5e, 0x89, 0xbd, 0x64, + 0xa0, 0x64, 0x71, 0x49, 0x1f, 0x7e, 0x73, 0x8c, 0x3a, 0x88, 0x27, 0xd5, + 0x1a, 0x7e, 0xe3, 0x76, 0x61, 0x9d, 0x72, 0x8d, 0x51, 0x92, 0x3b, 0xca, + 0xe6, 0xab, 0x3c, 0x76, 0xe4, 0x39, 0xa7, 0xc4, 0x83, 0x3c, 0xed, 0x25, + 0x4e, 0xa5, 0xf5, 0x42, 0x3b, 0x45, 0x65, 0xad, 0x56, 0x12, 0x03, 0x92, + 0x1d, 0xa3, 0xca, 0xa9, 0xc6, 0x5c, 0xce, 0x2a, 0x26, 0x55, 0x8d, 0x96, + 0x91, 0xae, 0xd3, 0xa5, 0xcc, 0x72, 0x60, 0xb6, 0x3d, 0xad, 0xb5, 0x99, + 0xb4, 0x32, 0xa7, 0x6d, 0x52, 0xe5, 0xa4, 0x8a, 0x49, 0xe5, 0x93, 0xaa, + 0x27, 0xd5, 0x90, 0xd5, 0x6e, 0xcf, 0x35, 0x84, 0x97, 0x7f, 0x17, 0x5e, + 0xb2, 0xdf, 0x7a, 0xb2, 0xc2, 0xe2, 0x7a, 0xab, 0xdc, 0xe6, 0xda, 0x5f, + 0x23, 0x5c, 0x2f, 0x00, 0xef, 0x02, 0x57, 0xd6, 0x2e, 0x12, 0x07, 0x2b, + 0x85, 0x38, 0x5a, 0x69, 0x88, 0x87, 0x41, 0x4f, 0x02, 0x1f, 0x73, 0xba, + 0x8a, 0xac, 0xc2, 0x28, 0x34, 0x84, 0xfc, 0x5d, 0xbe, 0x7f, 0xbf, 0xf5, + 0xf5, 0xba, 0x36, 0xb1, 0xdf, 0x0f, 0x8b, 0x5a, 0x32, 0x84, 0xb5, 0xe8, + 0x88, 0x4f, 0x78, 0xdb, 0x51, 0xe8, 0x91, 0x79, 0x2b, 0xc5, 0xc3, 0x10, + 0x7f, 0x58, 0x2f, 0xc4, 0xc3, 0x73, 0x85, 0xb8, 0xbb, 0x1e, 0x6a, 0x31, + 0xc1, 0x10, 0x47, 0x7c, 0x9d, 0xc8, 0x75, 0x7c, 0xde, 0x6a, 0xf1, 0xca, + 0x3c, 0xb2, 0xd8, 0xa9, 0x84, 0x73, 0x08, 0x6f, 0x17, 0xf2, 0xdc, 0xb9, + 0x40, 0x1c, 0xf6, 0x9d, 0xe4, 0xc7, 0x07, 0xfc, 0x38, 0xb2, 0x40, 0x18, + 0x87, 0x17, 0x0a, 0xe3, 0xf8, 0x42, 0x12, 0x22, 0x77, 0x8a, 0x77, 0x03, + 0xb7, 0xb5, 0xa1, 0x47, 0x7c, 0xbc, 0x10, 0xed, 0x58, 0x84, 0x62, 0x81, + 0x93, 0xc0, 0xc7, 0xcc, 0x37, 0x40, 0x06, 0x7c, 0x08, 0x9c, 0x84, 0xfe, + 0x48, 0x23, 0xaa, 0x6c, 0x24, 0x47, 0xfd, 0xcc, 0xa9, 0x5e, 0xd9, 0x56, + 0xaf, 0xfa, 0x3d, 0x07, 0x65, 0xbc, 0xb0, 0x0a, 0x85, 0x1f, 0x6d, 0xc2, + 0xe3, 0x85, 0x15, 0x78, 0xec, 0x5f, 0x8d, 0xc7, 0x09, 0x29, 0x93, 0x1c, + 0x2b, 0x5e, 0x5f, 0x89, 0xc7, 0xa7, 0xfc, 0x78, 0x89, 0x93, 0xbf, 0x67, + 0xbb, 0xe3, 0xac, 0x3d, 0xca, 0x76, 0xcf, 0x32, 0x77, 0xb0, 0x1d, 0x8f, + 0x9b, 0xf9, 0xf1, 0x18, 0x3f, 0x4e, 0xb6, 0xdb, 0x0f, 0x18, 0x24, 0x00, + 0x8b, 0x71, 0x74, 0x05, 0x53, 0x83, 0xe1, 0xfa, 0xb0, 0xdd, 0xa1, 0xe5, + 0x7f, 0x0f, 0x26, 0x00, 0xae, 0xcb, 0xc1, 0x7f, 0x59, 0xc0, 0x3e, 0x2e, + 0x5e, 0x5f, 0x2d, 0xc4, 0x95, 0x5d, 0x42, 0xdc, 0x09, 0xbc, 0xdb, 0x24, + 0xc4, 0xab, 0x5d, 0x16, 0xf1, 0x6c, 0xa3, 0x9d, 0xde, 0x5d, 0x3c, 0x41, + 0x5c, 0xb7, 0x46, 0x88, 0xfd, 0xcd, 0x18, 0x24, 0xe0, 0x25, 0xf0, 0x6f, + 0x01, 0x1f, 0x03, 0xb7, 0xae, 0x45, 0x1a, 0x78, 0x0b, 0xf8, 0x18, 0x78, + 0x1d, 0x03, 0x77, 0xe5, 0x3a, 0x21, 0x1e, 0x63, 0xc0, 0xf6, 0xc8, 0x12, + 0x21, 0x0e, 0x2e, 0x15, 0xe2, 0xba, 0x65, 0xc2, 0xfa, 0xee, 0x3a, 0x61, + 0xdd, 0xdf, 0x2d, 0xc4, 0x0b, 0xcb, 0x6c, 0xe2, 0x38, 0xe8, 0xad, 0xeb, + 0xe1, 0x1c, 0xc0, 0xab, 0xeb, 0x49, 0xfd, 0xf0, 0x67, 0x8d, 0x81, 0x55, + 0xea, 0xb3, 0xc7, 0x9d, 0xa0, 0x09, 0x13, 0x7f, 0xd1, 0x2a, 0xa5, 0x3f, + 0x6c, 0x92, 0xdd, 0xa8, 0xf9, 0xdb, 0x41, 0xef, 0x59, 0xa5, 0x3e, 0xdf, + 0x64, 0xf9, 0xc3, 0xc0, 0x4f, 0xb5, 0xfd, 0x0b, 0x26, 0xfb, 0xd7, 0xb4, + 0xec, 0x0f, 0x9a, 0xfe, 0x0d, 0x34, 0xde, 0x39, 0x5a, 0x37, 0xe9, 0xcf, + 0x5d, 0x87, 0x20, 0xbb, 0x50, 0xcb, 0xd3, 0x3f, 0x47, 0x4e, 0xb1, 0xe3, + 0xef, 0x1f, 0x39, 0x0c, 0xd9, 0x4d, 0xa7, 0xd8, 0xdd, 0x79, 0x4a, 0xfa, + 0x89, 0x53, 0xf2, 0xf1, 0xf7, 0x8b, 0x3c, 0x0c, 0xd9, 0x2b, 0xa7, 0xc8, + 0xf9, 0xff, 0x06, 0xbf, 0xd0, 0x39, 0xfa, 0xbd, 0x1c, 0xc2, 0x44, 0xd3, + 0xdf, 0xa3, 0xc5, 0xfd, 0x48, 0x7f, 0x97, 0x16, 0xf7, 0x35, 0xfd, 0x7d, + 0x5a, 0xfc, 0x59, 0x6c, 0xfa, 0x3b, 0xb5, 0xf8, 0x73, 0xda, 0xf4, 0xf7, + 0x6a, 0xf1, 0x67, 0xd4, 0xe9, 0xef, 0xd6, 0x12, 0x3e, 0xf5, 0x1d, 0x27, + 0xfc, 0xfd, 0x5a, 0x16, 0x9f, 0xfa, 0x6c, 0x98, 0xff, 0xaf, 0x9d, 0x70, + 0xab, 0xef, 0x55, 0xe1, 0xff, 0x53, 0x68, 0xf8, 0x54, 0x5d, 0xbe, 0x5a, + 0x94, 0xe9, 0x53, 0x7f, 0x43, 0xc3, 0xf3, 0x41, 0x3e, 0x55, 0x0e, 0xff, + 0x5f, 0x43, 0x8b, 0x5b, 0xfd, 0xdd, 0xc0, 0x20, 0xda, 0x6a, 0xd7, 0x72, + 0xfe, 0x7f, 0x88, 0xdc, 0x70, 0x6e, 0x2b, 0x7f, 0xef, 0xd7, 0xff, 0x05, + 0xf3, 0x27, 0x9b, 0x95, 0x30, 0x4c, 0x00, 0x00 +}; //============================================================================== #if JUCE_PUSH_NOTIFICATIONS && JUCE_MODULE_AVAILABLE_juce_gui_extra @@ -213,6 +872,13 @@ DECLARE_JNI_CLASS_WITH_MIN_SDK (AndroidWindowManagerLayoutParams28, "android/vie DECLARE_JNI_CLASS_WITH_MIN_SDK (AndroidWindowInsetsType, "android/view/WindowInsets$Type", 30) #undef JNI_CLASS_MEMBERS +#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ + FIELD (first, "first", "Ljava/lang/Object;") \ + FIELD (second, "second", "Ljava/lang/Object;") \ + + DECLARE_JNI_CLASS (AndroidPair, "android/util/Pair") +#undef JNI_CLASS_MEMBERS + //============================================================================== namespace { @@ -856,30 +1522,29 @@ public: } } - void handleKeyDownCallback (int k, int kc, int kbFlags) + static void handleKeyDownCallback (JNIEnv*, AndroidComponentPeer& t, int k, int kc, int kbFlags) { ModifierKeys::currentModifiers = ModifierKeys::currentModifiers.withOnlyMouseButtons() .withFlags (translateAndroidKeyboardFlags (kbFlags)); - handleKeyPress (translateAndroidKeyCode (k), static_cast (kc)); + t.handleKeyPress (translateAndroidKeyCode (k), static_cast (kc)); } - void handleKeyUpCallback (int /*k*/, int /*kc*/) + static void handleKeyUpCallback (JNIEnv*, [[maybe_unused]] AndroidComponentPeer& t, [[maybe_unused]] int k, [[maybe_unused]] int kc) { } - void handleBackButtonCallback() + static void handleBackButtonCallback (JNIEnv* env, AndroidComponentPeer& t) { bool handled = false; if (auto* app = JUCEApplicationBase::getInstance()) handled = app->backButtonPressed(); - if (isKioskModeComponent()) - setNavBarsHidden (navBarsHidden); + if (t.isKioskModeComponent()) + t.setNavBarsHidden (t.navBarsHidden); if (! handled) { - auto* env = getEnv(); LocalRef activity (getCurrentActivity()); if (activity != nullptr) @@ -890,17 +1555,27 @@ public: } } - void handleKeyboardHiddenCallback() + static void handleKeyboardHiddenCallback (JNIEnv*, [[maybe_unused]] AndroidComponentPeer& t) { Component::unfocusAllComponents(); } - void handleAppPausedCallback() {} + static void handleAppPausedCallback (JNIEnv*, [[maybe_unused]] AndroidComponentPeer& t) {} - void handleAppResumedCallback() + static void handleAppResumedCallback (JNIEnv*, AndroidComponentPeer& t) { - if (isKioskModeComponent()) - setNavBarsHidden (navBarsHidden); + if (t.isKioskModeComponent()) + t.setNavBarsHidden (t.navBarsHidden); + } + + static jlong handleGetFocusedTextInputTargetCallback (JNIEnv*, AndroidComponentPeer& t) + { + return reinterpret_cast (t.findCurrentTextInputTarget()); + } + + static void handleMovedOrResizedCallback (JNIEnv*, AndroidComponentPeer& t) + { + t.handleMovedOrResized(); } //============================================================================== @@ -916,9 +1591,9 @@ public: return nullptr; } - jboolean populateAccessibilityNodeInfoCallback (jint virtualViewId, jobject info) const + static jboolean populateAccessibilityNodeInfoCallback (JNIEnv*, const AndroidComponentPeer& t, jint virtualViewId, jobject info) { - if (auto* handle = getNativeHandleForViewId (virtualViewId)) + if (auto* handle = t.getNativeHandleForViewId (virtualViewId)) { handle->populateNodeInfo (info); return true; @@ -927,53 +1602,53 @@ public: return false; } - jboolean handlePerformActionCallback (jint virtualViewId, jint action, jobject arguments) const + static jboolean handlePerformActionCallback (JNIEnv*, const AndroidComponentPeer& t, jint virtualViewId, jint action, jobject arguments) { - if (auto* handle = getNativeHandleForViewId (virtualViewId)) + if (auto* handle = t.getNativeHandleForViewId (virtualViewId)) return handle->performAction (action, arguments); return false; } - static jobject getFocusViewIdForHandler (const AccessibilityHandler* handler) + static jobject getFocusViewIdForHandler (JNIEnv* env, const AccessibilityHandler* handler) { if (handler != nullptr) - return getEnv()->NewObject (JavaInteger, - JavaInteger.constructor, - handler->getNativeImplementation()->getVirtualViewId()); + return env->NewObject (JavaInteger, + JavaInteger.constructor, + handler->getNativeImplementation()->getVirtualViewId()); return nullptr; } - jobject getInputFocusViewIdCallback() + static jobject getInputFocusViewIdCallback (JNIEnv* env, AndroidComponentPeer& t) { - if (auto* comp = dynamic_cast (findCurrentTextInputTarget())) - return getFocusViewIdForHandler (comp->getAccessibilityHandler()); + if (auto* comp = dynamic_cast (t.findCurrentTextInputTarget())) + return getFocusViewIdForHandler (env, comp->getAccessibilityHandler()); return nullptr; } - jobject getAccessibilityFocusViewIdCallback() const + static jobject getAccessibilityFocusViewIdCallback (JNIEnv* env, const AndroidComponentPeer& t) { - if (auto* handler = component.getAccessibilityHandler()) + if (auto* handler = t.component.getAccessibilityHandler()) { if (auto* modal = Component::getCurrentlyModalComponent()) { - if (! component.isParentOf (modal) - && component.isCurrentlyBlockedByAnotherModalComponent()) + if (! t.component.isParentOf (modal) + && t.component.isCurrentlyBlockedByAnotherModalComponent()) { if (auto* modalHandler = modal->getAccessibilityHandler()) { if (auto* focusChild = modalHandler->getChildFocus()) - return getFocusViewIdForHandler (focusChild); + return getFocusViewIdForHandler (env, focusChild); - return getFocusViewIdForHandler (modalHandler); + return getFocusViewIdForHandler (env, modalHandler); } } } if (auto* focusChild = handler->getChildFocus()) - return getFocusViewIdForHandler (focusChild); + return getFocusViewIdForHandler (env, focusChild); } return nullptr; @@ -994,59 +1669,49 @@ public: view.callBooleanMethod (AndroidView.requestFocus); } - void handleFocusChangeCallback (bool hasFocus) + static void handleFocusChangeCallback (JNIEnv*, AndroidComponentPeer& t, bool hasFocus) { - if (isFullScreen()) - setFullScreen (true); + if (t.isFullScreen()) + t.setFullScreen (true); if (hasFocus) - handleFocusGain(); + t.handleFocusGain(); else - handleFocusLoss(); + t.handleFocusLoss(); } - static const char* getVirtualKeyboardType (TextInputTarget::VirtualKeyboardType type) noexcept + void textInputRequired (Point, TextInputTarget& target) override { - switch (type) - { - case TextInputTarget::textKeyboard: return "text"; - case TextInputTarget::numericKeyboard: return "number"; - case TextInputTarget::decimalKeyboard: return "numberDecimal"; - case TextInputTarget::urlKeyboard: return "textUri"; - case TextInputTarget::emailAddressKeyboard: return "textEmailAddress"; - case TextInputTarget::phoneNumberKeyboard: return "phone"; - default: jassertfalse; break; - } - - return "text"; + const auto region = target.getHighlightedRegion(); + view.callVoidMethod (ComponentPeerView.showKeyboard, + static_cast (target.getKeyboardType()), + static_cast (region.getStart()), + static_cast (region.getEnd())); } - void textInputRequired (Point, TextInputTarget& target) override + void closeInputMethodContext() override { - view.callVoidMethod (ComponentPeerView.showKeyboard, - javaString (getVirtualKeyboardType (target.getKeyboardType())).get()); + getEnv()->CallVoidMethod (view, ComponentPeerView.closeInputMethodContext); } void dismissPendingTextInput() override { closeInputMethodContext(); - view.callVoidMethod (ComponentPeerView.showKeyboard, javaString ("").get()); + view.callVoidMethod (ComponentPeerView.hideKeyboard); if (! isTimerRunning()) startTimer (500); } //============================================================================== - void handleDoFrameCallback ([[maybe_unused]] int64 frameTimeNanos) + static void handleDoFrameCallback (JNIEnv*, AndroidComponentPeer& t, [[maybe_unused]] int64 frameTimeNanos) { - vBlankListeners.call ([] (auto& l) { l.onVBlank(); }); + t.vBlankListeners.call ([] (auto& l) { l.onVBlank(); }); } - void handlePaintCallback (jobject canvas, jobject paint) + static void handlePaintCallback (JNIEnv* env, AndroidComponentPeer& t, jobject canvas, jobject paint) { - auto* env = getEnv(); - jobject rect = env->CallObjectMethod (canvas, AndroidCanvas.getClipBounds); auto left = env->GetIntField (rect, AndroidRect.left); auto top = env->GetIntField (rect, AndroidRect.top); @@ -1061,30 +1726,30 @@ public: auto sizeNeeded = clip.getWidth() * clip.getHeight(); - if (sizeAllocated < sizeNeeded) + if (t.sizeAllocated < sizeNeeded) { - buffer.clear(); - sizeAllocated = sizeNeeded; - buffer = GlobalRef (LocalRef ((jobject) env->NewIntArray (sizeNeeded))); + t.buffer.clear(); + t.sizeAllocated = sizeNeeded; + t.buffer = GlobalRef (LocalRef ((jobject) env->NewIntArray (sizeNeeded))); } - if (jint* dest = env->GetIntArrayElements ((jintArray) buffer.get(), nullptr)) + if (jint* dest = env->GetIntArrayElements ((jintArray) t.buffer.get(), nullptr)) { { Image temp (new PreallocatedImage (clip.getWidth(), clip.getHeight(), - dest, ! component.isOpaque())); + dest, ! t.component.isOpaque())); { LowLevelGraphicsSoftwareRenderer g (temp); g.setOrigin (-clip.getPosition()); - g.addTransform (AffineTransform::scale (scale)); - handlePaint (g); + g.addTransform (AffineTransform::scale (t.scale)); + t.handlePaint (g); } } - env->ReleaseIntArrayElements ((jintArray) buffer.get(), dest, 0); + env->ReleaseIntArrayElements ((jintArray) t.buffer.get(), dest, 0); - env->CallVoidMethod (canvas, AndroidCanvas.drawBitmap, (jintArray) buffer.get(), 0, clip.getWidth(), + env->CallVoidMethod (canvas, AndroidCanvas.drawBitmap, (jintArray) t.buffer.get(), 0, clip.getWidth(), (jfloat) clip.getX(), (jfloat) clip.getY(), clip.getWidth(), clip.getHeight(), true, paint); } @@ -1144,83 +1809,140 @@ public: }; private: + template + static void mouseCallbackWrapper (JNIEnv*, AndroidComponentPeer& t, jint i, jfloat x, jfloat y, jlong time) { return (t.*Member) (i, Point { x, y }, time); } + //============================================================================== - #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ - METHOD (create, "", "(Landroid/content/Context;ZJ)V") \ - METHOD (clear, "clear", "()V") \ - METHOD (setViewName, "setViewName", "(Ljava/lang/String;)V") \ - METHOD (setVisible, "setVisible", "(Z)V") \ - METHOD (isVisible, "isVisible", "()Z") \ - METHOD (containsPoint, "containsPoint", "(II)Z") \ - METHOD (showKeyboard, "showKeyboard", "(Ljava/lang/String;)V") \ - METHOD (setSystemUiVisibilityCompat, "setSystemUiVisibilityCompat", "(I)V") \ - CALLBACK (handleDoFrameJni, "handleDoFrame", "(JJ)V") \ - CALLBACK (handlePaintJni, "handlePaint", "(JLandroid/graphics/Canvas;Landroid/graphics/Paint;)V") \ - CALLBACK (handleMouseDownJni, "handleMouseDown", "(JIFFJ)V") \ - CALLBACK (handleMouseDragJni, "handleMouseDrag", "(JIFFJ)V") \ - CALLBACK (handleMouseUpJni, "handleMouseUp", "(JIFFJ)V") \ - CALLBACK (handleAccessibleHoverJni, "handleAccessibilityHover", "(JIFFJ)V") \ - CALLBACK (handleKeyDownJni, "handleKeyDown", "(JIII)V") \ - CALLBACK (handleKeyUpJni, "handleKeyUp", "(JII)V") \ - CALLBACK (handleBackButtonJni, "handleBackButton", "(J)V") \ - CALLBACK (handleKeyboardHiddenJni, "handleKeyboardHidden", "(J)V") \ - CALLBACK (viewSizeChangedJni, "viewSizeChanged", "(J)V") \ - CALLBACK (focusChangedJni, "focusChanged", "(JZ)V") \ - CALLBACK (handleAppPausedJni, "handleAppPaused", "(J)V") \ - CALLBACK (handleAppResumedJni, "handleAppResumed", "(J)V") \ - CALLBACK (populateAccessibilityNodeInfoJni, "populateAccessibilityNodeInfo", "(JILandroid/view/accessibility/AccessibilityNodeInfo;)Z") \ - CALLBACK (handlePerformActionJni, "handlePerformAction", "(JIILandroid/os/Bundle;)Z") \ - CALLBACK (getInputFocusViewIdJni, "getInputFocusViewId", "(J)Ljava/lang/Integer;") \ - CALLBACK (getAccessibilityFocusViewIdJni, "getAccessibilityFocusViewId", "(J)Ljava/lang/Integer;") \ - - DECLARE_JNI_CLASS_WITH_BYTECODE (ComponentPeerView, "com/rmsl/juce/ComponentPeerView", 16, javaComponentPeerView, sizeof (javaComponentPeerView)) - #undef JNI_CLASS_MEMBERS - - static void JNICALL handleDoFrameJni (JNIEnv*, jobject /*view*/, jlong host, jlong frameTimeNanos) { if (auto* myself = reinterpret_cast (host)) myself->handleDoFrameCallback (frameTimeNanos); } - static void JNICALL handlePaintJni (JNIEnv*, jobject /*view*/, jlong host, jobject canvas, jobject paint) { if (auto* myself = reinterpret_cast (host)) myself->handlePaintCallback (canvas, paint); } - static void JNICALL handleMouseDownJni (JNIEnv*, jobject /*view*/, jlong host, jint i, jfloat x, jfloat y, jlong time) { if (auto* myself = reinterpret_cast (host)) myself->handleMouseDownCallback (i, Point ((float) x, (float) y), (int64) time); } - static void JNICALL handleMouseDragJni (JNIEnv*, jobject /*view*/, jlong host, jint i, jfloat x, jfloat y, jlong time) { if (auto* myself = reinterpret_cast (host)) myself->handleMouseDragCallback (i, Point ((float) x, (float) y), (int64) time); } - static void JNICALL handleMouseUpJni (JNIEnv*, jobject /*view*/, jlong host, jint i, jfloat x, jfloat y, jlong time) { if (auto* myself = reinterpret_cast (host)) myself->handleMouseUpCallback (i, Point ((float) x, (float) y), (int64) time); } - static void JNICALL handleAccessibleHoverJni(JNIEnv*, jobject /*view*/, jlong host, jint c, jfloat x, jfloat y, jlong time) { if (auto* myself = reinterpret_cast (host)) myself->handleAccessibilityHoverCallback ((int) c, Point ((float) x, (float) y), (int64) time); } - static void JNICALL viewSizeChangedJni (JNIEnv*, jobject /*view*/, jlong host) { if (auto* myself = reinterpret_cast (host)) myself->handleMovedOrResized(); } - static void JNICALL focusChangedJni (JNIEnv*, jobject /*view*/, jlong host, jboolean hasFocus) { if (auto* myself = reinterpret_cast (host)) myself->handleFocusChangeCallback (hasFocus); } - static void JNICALL handleKeyDownJni (JNIEnv*, jobject /*view*/, jlong host, jint k, jint kc, jint kbFlags) { if (auto* myself = reinterpret_cast (host)) myself->handleKeyDownCallback ((int) k, (int) kc, (int) kbFlags); } - static void JNICALL handleKeyUpJni (JNIEnv*, jobject /*view*/, jlong host, jint k, jint kc) { if (auto* myself = reinterpret_cast (host)) myself->handleKeyUpCallback ((int) k, (int) kc); } - static void JNICALL handleBackButtonJni (JNIEnv*, jobject /*view*/, jlong host) { if (auto* myself = reinterpret_cast (host)) myself->handleBackButtonCallback(); } - static void JNICALL handleKeyboardHiddenJni (JNIEnv*, jobject /*view*/, jlong host) { if (auto* myself = reinterpret_cast (host)) myself->handleKeyboardHiddenCallback(); } - static void JNICALL handleAppPausedJni (JNIEnv*, jobject /*view*/, jlong host) { if (auto* myself = reinterpret_cast (host)) myself->handleAppPausedCallback(); } - static void JNICALL handleAppResumedJni (JNIEnv*, jobject /*view*/, jlong host) { if (auto* myself = reinterpret_cast (host)) myself->handleAppResumedCallback(); } - - static jboolean JNICALL populateAccessibilityNodeInfoJni (JNIEnv*, jobject /*view*/, jlong host, jint virtualViewId, jobject info) - { - if (auto* myself = reinterpret_cast (host)) - return myself->populateAccessibilityNodeInfoCallback (virtualViewId, info); + #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ + METHOD (create, "", "(Landroid/content/Context;ZJ)V") \ + METHOD (clear, "clear", "()V") \ + METHOD (setViewName, "setViewName", "(Ljava/lang/String;)V") \ + METHOD (setVisible, "setVisible", "(Z)V") \ + METHOD (isVisible, "isVisible", "()Z") \ + METHOD (containsPoint, "containsPoint", "(II)Z") \ + METHOD (showKeyboard, "showKeyboard", "(III)V") \ + METHOD (hideKeyboard, "hideKeyboard", "()V") \ + METHOD (closeInputMethodContext, "closeInputMethodContext", "()V") \ + METHOD (setSystemUiVisibilityCompat, "setSystemUiVisibilityCompat", "(I)V") \ + CALLBACK (generatedCallback<&AndroidComponentPeer::handleDoFrameCallback>, "handleDoFrame", "(JJ)V") \ + CALLBACK (generatedCallback<&AndroidComponentPeer::handlePaintCallback>, "handlePaint", "(JLandroid/graphics/Canvas;Landroid/graphics/Paint;)V") \ + CALLBACK (generatedCallback<&AndroidComponentPeer::handleKeyDownCallback>, "handleKeyDown", "(JIII)V") \ + CALLBACK (generatedCallback<&AndroidComponentPeer::handleKeyUpCallback>, "handleKeyUp", "(JII)V") \ + CALLBACK (generatedCallback<&AndroidComponentPeer::handleBackButtonCallback>, "handleBackButton", "(J)V") \ + CALLBACK (generatedCallback<&AndroidComponentPeer::handleKeyboardHiddenCallback>, "handleKeyboardHidden", "(J)V") \ + CALLBACK (generatedCallback<&AndroidComponentPeer::handleGetFocusedTextInputTargetCallback>, "getFocusedTextInputTargetPointer", "(J)J") \ + CALLBACK (generatedCallback<&AndroidComponentPeer::handleMovedOrResizedCallback>, "viewSizeChanged", "(J)V") \ + CALLBACK (generatedCallback<&AndroidComponentPeer::handleFocusChangeCallback>, "focusChanged", "(JZ)V") \ + CALLBACK (generatedCallback<&AndroidComponentPeer::handleAppPausedCallback>, "handleAppPaused", "(J)V") \ + CALLBACK (generatedCallback<&AndroidComponentPeer::handleAppResumedCallback>, "handleAppResumed", "(J)V") \ + CALLBACK (generatedCallback<&AndroidComponentPeer::populateAccessibilityNodeInfoCallback>, "populateAccessibilityNodeInfo", "(JILandroid/view/accessibility/AccessibilityNodeInfo;)Z") \ + CALLBACK (generatedCallback<&AndroidComponentPeer::handlePerformActionCallback>, "handlePerformAction", "(JIILandroid/os/Bundle;)Z") \ + CALLBACK (generatedCallback<&AndroidComponentPeer::getInputFocusViewIdCallback>, "getInputFocusViewId", "(J)Ljava/lang/Integer;") \ + CALLBACK (generatedCallback<&AndroidComponentPeer::getAccessibilityFocusViewIdCallback>, "getAccessibilityFocusViewId", "(J)Ljava/lang/Integer;") \ + CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetIsTextInputActive>, "textInputTargetIsTextInputActive", "(J)Z") \ + CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetGetHighlightedRegionBegin>, "textInputTargetGetHighlightedRegionBegin", "(J)I") \ + CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetGetHighlightedRegionEnd>, "textInputTargetGetHighlightedRegionEnd", "(J)I") \ + CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetSetHighlightedRegion>, "textInputTargetSetHighlightedRegion", "(JII)V") \ + CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetGetTextInRange>, "textInputTargetGetTextInRange", "(JII)Ljava/lang/String;") \ + CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetInsertTextAtCaret>, "textInputTargetInsertTextAtCaret", "(JLjava/lang/String;)V") \ + CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetGetCaretPosition>, "textInputTargetGetCaretPosition", "(J)I") \ + CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetGetTotalNumChars>, "textInputTargetGetTotalNumChars", "(J)I") \ + CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetGetCharIndexForPoint>, "textInputTargetGetCharIndexForPoint", "(JLandroid/graphics/Point;)I") \ + CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetGetKeyboardType>, "textInputTargetGetKeyboardType", "(J)I") \ + CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetSetTemporaryUnderlining>, "textInputTargetSetTemporaryUnderlining", "(JLjava/util/List;)V") \ + CALLBACK (generatedCallback<&AndroidComponentPeer::mouseCallbackWrapper<&AndroidComponentPeer::handleMouseDownCallback>>, "handleMouseDown", "(JIFFJ)V") \ + CALLBACK (generatedCallback<&AndroidComponentPeer::mouseCallbackWrapper<&AndroidComponentPeer::handleMouseDragCallback>>, "handleMouseDrag", "(JIFFJ)V") \ + CALLBACK (generatedCallback<&AndroidComponentPeer::mouseCallbackWrapper<&AndroidComponentPeer::handleMouseUpCallback>>, "handleMouseUp", "(JIFFJ)V") \ + CALLBACK (generatedCallback<&AndroidComponentPeer::mouseCallbackWrapper<&AndroidComponentPeer::handleAccessibilityHoverCallback>>, "handleAccessibilityHover", "(JIFFJ)V") \ - return false; + DECLARE_JNI_CLASS_WITH_BYTECODE (ComponentPeerView, "com/rmsl/juce/ComponentPeerView", 16, javaComponentPeerView) + #undef JNI_CLASS_MEMBERS + + static jboolean textInputTargetIsTextInputActive (JNIEnv*, const TextInputTarget& t) + { + return t.isTextInputActive(); } - static jboolean JNICALL handlePerformActionJni (JNIEnv*, jobject /*view*/, jlong host, jint virtualViewId, jint action, jobject arguments) + static jint textInputTargetGetHighlightedRegionBegin (JNIEnv*, const TextInputTarget& t) { - if (auto* myself = reinterpret_cast (host)) - return myself->handlePerformActionCallback (virtualViewId, action, arguments); + return t.getHighlightedRegion().getStart(); + } - return false; + static jint textInputTargetGetHighlightedRegionEnd (JNIEnv*, const TextInputTarget& t) + { + return t.getHighlightedRegion().getEnd(); + } + + static void textInputTargetSetHighlightedRegion (JNIEnv*, TextInputTarget& t, jint b, jint e) + { + t.setHighlightedRegion ({ b, e }); } - static jobject JNICALL getInputFocusViewIdJni (JNIEnv*, jobject /*view*/, jlong host) + static jstring textInputTargetGetTextInRange (JNIEnv* env, const TextInputTarget& t, jint b, jint e) { - if (auto* myself = reinterpret_cast (host)) - return myself->getInputFocusViewIdCallback(); + return env->NewStringUTF (t.getTextInRange ({ b, e }).toUTF8()); + } - return nullptr; + static void textInputTargetInsertTextAtCaret (JNIEnv*, TextInputTarget& t, jstring text) + { + t.insertTextAtCaret (juceString (text)); } - static jobject JNICALL getAccessibilityFocusViewIdJni (JNIEnv*, jobject /*view*/, jlong host) + static jint textInputTargetGetCaretPosition (JNIEnv*, const TextInputTarget& t) { - if (auto* myself = reinterpret_cast (host)) - return myself->getAccessibilityFocusViewIdCallback(); + return t.getCaretPosition(); + } - return nullptr; + static jint textInputTargetGetTotalNumChars (JNIEnv*, const TextInputTarget& t) + { + return t.getTotalNumChars(); + } + + static jint textInputTargetGetCharIndexForPoint (JNIEnv* env, const TextInputTarget& t, jobject point) + { + return t.getCharIndexForPoint ({ env->GetIntField (point, AndroidPoint.x), + env->GetIntField (point, AndroidPoint.y) }); + } + + static jint textInputTargetGetKeyboardType (JNIEnv*, TextInputTarget& t) + { + return t.getKeyboardType(); + } + + static std::optional> getRangeFromPair (JNIEnv* env, jobject pair) + { + if (pair == nullptr) + return {}; + + const auto first = env->GetObjectField (pair, AndroidPair.first); + const auto second = env->GetObjectField (pair, AndroidPair.second); + + if (first == nullptr || second == nullptr) + return {}; + + const auto begin = env->CallIntMethod (first, JavaInteger.intValue); + const auto end = env->CallIntMethod (second, JavaInteger.intValue); + + return Range { begin, end }; + } + + static Array> javaListOfPairToArrayOfRange (JNIEnv* env, jobject list) + { + if (list == nullptr) + return {}; + + Array> result; + + for (jint i = 0; i < env->CallIntMethod (list, JavaList.size); ++i) + if (const auto range = getRangeFromPair (env, env->CallObjectMethod (list, JavaList.get, i))) + result.add (*range); + + return result; + } + + static void textInputTargetSetTemporaryUnderlining (JNIEnv* env, TextInputTarget& t, jobject list) + { + t.setTemporaryUnderlining (javaListOfPairToArrayOfRange (env, list)); } //============================================================================== @@ -1390,7 +2112,6 @@ Point AndroidComponentPeer::lastMousePos; int64 AndroidComponentPeer::touchesDown = 0; AndroidComponentPeer* AndroidComponentPeer::frontWindow = nullptr; GlobalRef AndroidComponentPeer::activityCallbackListener; -AndroidComponentPeer::ComponentPeerView_Class AndroidComponentPeer::ComponentPeerView; //============================================================================== ComponentPeer* Component::createNewPeer (int styleFlags, void* nativeWindow) @@ -1928,7 +2649,7 @@ void Displays::findDisplays (float masterScale) { auto* env = getEnv(); - LocalRef usableSize (env->NewObject (AndroidPoint, AndroidPoint.create, 0, 0)); + LocalRef usableSize (makeAndroidPoint ({})); LocalRef windowServiceString (javaString ("window")); LocalRef displayMetrics (env->NewObject (AndroidDisplayMetrics, AndroidDisplayMetrics.create)); LocalRef windowManager (env->CallObjectMethod (getAppContext().get(), AndroidContext.getSystemService, windowServiceString.get())); @@ -2179,8 +2900,6 @@ const int KeyPress::rewindKey = extendedKeyModifier + 72; juce_handleOnResume(); } }; - - JuceActivityNewIntentListener::JavaActivity_Class JuceActivityNewIntentListener::JavaActivity; #endif } // namespace juce diff --git a/modules/juce_gui_basics/widgets/juce_TextEditor.cpp b/modules/juce_gui_basics/widgets/juce_TextEditor.cpp index aca419cce9..79be3ecca2 100644 --- a/modules/juce_gui_basics/widgets/juce_TextEditor.cpp +++ b/modules/juce_gui_basics/widgets/juce_TextEditor.cpp @@ -948,6 +948,11 @@ TextEditor::TextEditor (const String& name, juce_wchar passwordChar) TextEditor::~TextEditor() { + giveAwayKeyboardFocus(); + + if (auto* peer = getPeer()) + peer->refreshTextInputTarget(); + textValue.removeListener (textHolder); textValue.referTo (Value()); @@ -1240,7 +1245,7 @@ void TextEditor::setText (const String& newText, bool sendTextChangeMessage) textValue = newText; auto oldCursorPos = caretPosition; - bool cursorWasAtEnd = oldCursorPos >= getTotalNumChars(); + auto cursorWasAtEnd = oldCursorPos >= getTotalNumChars(); clearInternal (nullptr); insert (newText, 0, currentFont, findColour (textColourId), nullptr, caretPosition); @@ -1376,26 +1381,23 @@ void TextEditor::repaintText (Range range) } //============================================================================== -void TextEditor::moveCaret (int newCaretPos) +void TextEditor::moveCaret (const int newCaretPos) { - if (newCaretPos < 0) - newCaretPos = 0; - else - newCaretPos = jmin (newCaretPos, getTotalNumChars()); + const auto clamped = std::clamp (newCaretPos, 0, getTotalNumChars()); - if (newCaretPos != getCaretPosition()) - { - caretPosition = newCaretPos; + if (clamped == getCaretPosition()) + return; - if (hasKeyboardFocus (false)) - textHolder->restartTimer(); + caretPosition = clamped; - scrollToMakeSureCursorIsVisible(); - updateCaretPosition(); + if (hasKeyboardFocus (false)) + textHolder->restartTimer(); - if (auto* handler = getAccessibilityHandler()) - handler->notifyAccessibilityEvent (AccessibilityEvent::textChanged); - } + scrollToMakeSureCursorIsVisible(); + updateCaretPosition(); + + if (auto* handler = getAccessibilityHandler()) + handler->notifyAccessibilityEvent (AccessibilityEvent::textChanged); } int TextEditor::getCaretPosition() const diff --git a/modules/juce_gui_basics/windows/juce_ComponentPeer.cpp b/modules/juce_gui_basics/windows/juce_ComponentPeer.cpp index 30b0fc55eb..fdb36953ba 100644 --- a/modules/juce_gui_basics/windows/juce_ComponentPeer.cpp +++ b/modules/juce_gui_basics/windows/juce_ComponentPeer.cpp @@ -182,7 +182,6 @@ bool ComponentPeer::handleKeyPress (const int keyCode, const juce_wchar textChar textCharacter)); } - bool ComponentPeer::handleKeyPress (const KeyPress& keyInfo) { bool keyWasUsed = false; @@ -607,7 +606,7 @@ void ComponentPeer::forceDisplayUpdate() Desktop::getInstance().displays->refresh(); } -void ComponentPeer::globalFocusChanged (Component*) +void ComponentPeer::globalFocusChanged ([[maybe_unused]] Component* comp) { refreshTextInputTarget(); } diff --git a/modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.cpp b/modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.cpp index 6273cbbd3a..dd4345297d 100644 --- a/modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.cpp +++ b/modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.cpp @@ -476,6 +476,11 @@ CodeEditorComponent::CodeEditorComponent (CodeDocument& doc, CodeTokeniser* cons CodeEditorComponent::~CodeEditorComponent() { + giveAwayKeyboardFocus(); + + if (auto* peer = getPeer()) + peer->refreshTextInputTarget(); + document.removeListener (pimpl.get()); } diff --git a/modules/juce_gui_extra/native/juce_android_PushNotifications.cpp b/modules/juce_gui_extra/native/juce_android_PushNotifications.cpp index 5e718c3e85..b382a3b9e3 100644 --- a/modules/juce_gui_extra/native/juce_android_PushNotifications.cpp +++ b/modules/juce_gui_extra/native/juce_android_PushNotifications.cpp @@ -1549,8 +1549,6 @@ struct JuceFirebaseInstanceIdService instance->pimpl->notifyListenersTokenRefreshed (juceString (static_cast (token))); } }; - -JuceFirebaseInstanceIdService::InstanceIdService_Class JuceFirebaseInstanceIdService::InstanceIdService; #endif #if defined(JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME) @@ -1592,8 +1590,6 @@ struct JuceFirebaseMessagingService LocalRef (static_cast (error))); } }; - -JuceFirebaseMessagingService::MessagingService_Class JuceFirebaseMessagingService::MessagingService; #endif //============================================================================== diff --git a/modules/juce_gui_extra/native/juce_android_WebBrowserComponent.cpp b/modules/juce_gui_extra/native/juce_android_WebBrowserComponent.cpp index 462bc43936..b4871cd9c5 100644 --- a/modules/juce_gui_extra/native/juce_android_WebBrowserComponent.cpp +++ b/modules/juce_gui_extra/native/juce_android_WebBrowserComponent.cpp @@ -29,7 +29,7 @@ namespace juce //============================================================================== // This byte-code is generated from native/java/com/rmsl/juce/JuceWebView.java with min sdk version 16 // See juce_core/native/java/README.txt on how to generate this byte-code. -static const unsigned char JuceWebView16ByteCode[] = +static const uint8 JuceWebView16ByteCode[] = {31,139,8,8,150,114,161,94,0,3,74,117,99,101,87,101,98,86,105,101,119,49,54,66,121,116,101,67,111,100,101,46,100,101,120,0,125, 150,93,108,20,85,20,199,207,124,236,78,119,218,110,183,5,74,191,40,109,69,168,72,89,176,162,165,11,88,40,159,101,81,161,88,226, 106,34,211,221,107,59,101,118,102,153,153,109,27,67,16,161,137,134,240,96,4,222,72,140,9,18,35,62,18,195,131,15,4,53,250,226,155, @@ -81,7 +81,7 @@ static const unsigned char JuceWebView16ByteCode[] = //============================================================================== // This byte-code is generated from native/javacore/app/com/rmsl/juce/JuceWebView21.java with min sdk version 21 // See juce_core/native/java/README.txt on how to generate this byte-code. -static const unsigned char JuceWebView21ByteCode[] = +static const uint8 JuceWebView21ByteCode[] = {31,139,8,8,45,103,161,94,0,3,74,117,99,101,87,101,98,86,105,101,119,50,49,46,100,101,120,0,141,151,93,140,27,87,21,199,207, 204,216,30,219,99,59,182,55,251,145,143,221,110,210,173,178,105,154,186,155,164,52,169,211,106,241,38,219,221,48,41,52,155,108, 138,43,85,154,181,47,235,73,188,51,206,204,120,119,65,162,132,80,148,138,34,148,168,20,181,125,129,135,16,129,4,18,168,125,136, @@ -479,82 +479,62 @@ private: #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ METHOD (constructor, "", "(J)V") \ METHOD (hostDeleted, "hostDeleted", "()V") \ - CALLBACK (webViewReceivedHttpError, "webViewReceivedHttpError", "(JLandroid/webkit/WebView;Landroid/webkit/WebResourceRequest;Landroid/webkit/WebResourceResponse;)V") \ - CALLBACK (webViewPageLoadStarted, "webViewPageLoadStarted", "(JLandroid/webkit/WebView;Ljava/lang/String;)Z") \ - CALLBACK (webViewPageLoadFinished, "webViewPageLoadFinished", "(JLandroid/webkit/WebView;Ljava/lang/String;)V") \ - CALLBACK (webViewReceivedSslError, "webViewReceivedSslError", "(JLandroid/webkit/WebView;Landroid/webkit/SslErrorHandler;Landroid/net/http/SslError;)V") \ + CALLBACK (generatedCallback<&Pimpl::webViewReceivedHttpError>, "webViewReceivedHttpError", "(JLandroid/webkit/WebView;Landroid/webkit/WebResourceRequest;Landroid/webkit/WebResourceResponse;)V") \ + CALLBACK (generatedCallback<&Pimpl::webViewPageLoadStarted>, "webViewPageLoadStarted", "(JLandroid/webkit/WebView;Ljava/lang/String;)Z") \ + CALLBACK (generatedCallback<&Pimpl::webViewPageLoadFinished>, "webViewPageLoadFinished", "(JLandroid/webkit/WebView;Ljava/lang/String;)V") \ + CALLBACK (generatedCallback<&Pimpl::webViewReceivedSslError>, "webViewReceivedSslError", "(JLandroid/webkit/WebView;Landroid/webkit/SslErrorHandler;Landroid/net/http/SslError;)V") \ - DECLARE_JNI_CLASS_WITH_BYTECODE (JuceWebViewClient21, "com/rmsl/juce/JuceWebView21$Client", 21, JuceWebView21ByteCode, sizeof (JuceWebView21ByteCode)) + DECLARE_JNI_CLASS_WITH_BYTECODE (JuceWebViewClient21, "com/rmsl/juce/JuceWebView21$Client", 21, JuceWebView21ByteCode) #undef JNI_CLASS_MEMBERS #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ METHOD (constructor, "", "(J)V") \ METHOD (hostDeleted, "hostDeleted", "()V") \ - CALLBACK (webViewPageLoadStarted, "webViewPageLoadStarted", "(JLandroid/webkit/WebView;Ljava/lang/String;)Z") \ - CALLBACK (webViewPageLoadFinished, "webViewPageLoadFinished", "(JLandroid/webkit/WebView;Ljava/lang/String;)V") \ - CALLBACK (webViewReceivedSslError, "webViewReceivedSslError", "(JLandroid/webkit/WebView;Landroid/webkit/SslErrorHandler;Landroid/net/http/SslError;)V") \ + CALLBACK (generatedCallback<&Pimpl::webViewPageLoadStarted>, "webViewPageLoadStarted", "(JLandroid/webkit/WebView;Ljava/lang/String;)Z") \ + CALLBACK (generatedCallback<&Pimpl::webViewPageLoadFinished>, "webViewPageLoadFinished", "(JLandroid/webkit/WebView;Ljava/lang/String;)V") \ + CALLBACK (generatedCallback<&Pimpl::webViewReceivedSslError>, "webViewReceivedSslError", "(JLandroid/webkit/WebView;Landroid/webkit/SslErrorHandler;Landroid/net/http/SslError;)V") \ - DECLARE_JNI_CLASS_WITH_BYTECODE (JuceWebViewClient16, "com/rmsl/juce/JuceWebView$Client", 16, JuceWebView16ByteCode, sizeof (JuceWebView16ByteCode)) + DECLARE_JNI_CLASS_WITH_BYTECODE (JuceWebViewClient16, "com/rmsl/juce/JuceWebView$Client", 16, JuceWebView16ByteCode) #undef JNI_CLASS_MEMBERS - static jboolean JNICALL webViewPageLoadStarted (JNIEnv*, jobject /*activity*/, jlong host, jobject /*webView*/, jstring url) + static jboolean webViewPageLoadStarted (JNIEnv*, Pimpl& t, jstring url) { - if (auto* myself = reinterpret_cast (host)) - return myself->handlePageAboutToLoad (juceString (url)); - - return 0; + return t.handlePageAboutToLoad (juceString (url)); } - static void JNICALL webViewPageLoadFinished (JNIEnv*, jobject /*activity*/, jlong host, jobject /*webView*/, jstring url) + static void webViewPageLoadFinished (JNIEnv*, Pimpl& t, jstring url) { - if (auto* myself = reinterpret_cast (host)) - myself->owner.pageFinishedLoading (juceString (url)); + t.owner.pageFinishedLoading (juceString (url)); } - static void JNICALL webViewReceivedHttpError (JNIEnv*, jobject /*activity*/, jlong host, jobject /*webView*/, jobject /*request*/, jobject errorResponse) + static void webViewReceivedSslError (JNIEnv* env, Pimpl& t, jobject sslError) { - if (auto* myself = reinterpret_cast (host)) - myself->webReceivedHttpError (errorResponse); - } - - static void JNICALL webViewReceivedSslError (JNIEnv*, jobject /*activity*/, jlong host, jobject /*webView*/, jobject /*sslErrorHandler*/, jobject sslError) - { - auto* env = getEnv(); - - if (auto* myself = reinterpret_cast (host)) - { - auto errorString = LocalRef ((jstring) env->CallObjectMethod (sslError, SslError.toString)); - - myself->owner.pageLoadHadNetworkError (juceString (errorString)); - } + const auto errorString = LocalRef ((jstring) env->CallObjectMethod (sslError, SslError.toString)); + t.owner.pageLoadHadNetworkError (juceString (errorString)); } //============================================================================== #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ METHOD (constructor, "", "(J)V") \ - CALLBACK (webViewCloseWindowRequest, "webViewCloseWindowRequest", "(JLandroid/webkit/WebView;)V") \ - CALLBACK (webViewCreateWindowRequest, "webViewCreateWindowRequest", "(JLandroid/webkit/WebView;)V") \ + CALLBACK (generatedCallback<&Pimpl::webViewCloseWindowRequest>, "webViewCloseWindowRequest", "(JLandroid/webkit/WebView;)V") \ + CALLBACK (generatedCallback<&Pimpl::webViewCreateWindowRequest>, "webViewCreateWindowRequest", "(JLandroid/webkit/WebView;)V") \ DECLARE_JNI_CLASS (JuceWebChromeClient, "com/rmsl/juce/JuceWebView$ChromeClient") #undef JNI_CLASS_MEMBERS - static void JNICALL webViewCloseWindowRequest (JNIEnv*, jobject /*activity*/, jlong host, jobject /*webView*/) + static void webViewCloseWindowRequest (JNIEnv*, Pimpl& t, jobject) { - if (auto* myself = reinterpret_cast (host)) - myself->owner.windowCloseRequest(); + t.owner.windowCloseRequest(); } - static void JNICALL webViewCreateWindowRequest (JNIEnv*, jobject /*activity*/, jlong host, jobject /*webView*/) + static void webViewCreateWindowRequest (JNIEnv*, Pimpl& t, jobject) { - if (auto* myself = reinterpret_cast (host)) - myself->owner.newWindowAttemptingToLoad ({}); + t.owner.newWindowAttemptingToLoad ({}); } //============================================================================== - void webReceivedHttpError (jobject errorResponse) + static void webViewReceivedHttpError (JNIEnv* env, Pimpl& t, jobject errorResponse) { - auto* env = getEnv(); - LocalRef responseClass (env->FindClass ("android/webkit/WebResourceResponse")); if (responseClass != nullptr) @@ -565,14 +545,14 @@ private: { auto errorString = LocalRef ((jstring) env->CallObjectMethod (errorResponse, method)); - owner.pageLoadHadNetworkError (juceString (errorString)); + t.owner.pageLoadHadNetworkError (juceString (errorString)); return; } } // Should never get here! jassertfalse; - owner.pageLoadHadNetworkError ({}); + t.owner.pageLoadHadNetworkError ({}); } //============================================================================== @@ -596,9 +576,7 @@ WebBrowserComponent::WebBrowserComponent (const Options& options) addAndMakeVisible (browser.get()); } -WebBrowserComponent::~WebBrowserComponent() -{ -} +WebBrowserComponent::~WebBrowserComponent() = default; //============================================================================== void WebBrowserComponent::goToURL (const String& url, @@ -728,7 +706,4 @@ bool WebBrowserComponent::areOptionsSupported (const Options& options) return (options.getBackend() == Options::Backend::defaultBackend); } -WebBrowserComponent::Pimpl::JuceWebViewClient16_Class WebBrowserComponent::Pimpl::JuceWebViewClient16; -WebBrowserComponent::Pimpl::JuceWebViewClient21_Class WebBrowserComponent::Pimpl::JuceWebViewClient21; -WebBrowserComponent::Pimpl::JuceWebChromeClient_Class WebBrowserComponent::Pimpl::JuceWebChromeClient; } // namespace juce diff --git a/modules/juce_opengl/native/juce_OpenGL_android.h b/modules/juce_opengl/native/juce_OpenGL_android.h index 36f47864aa..dc1c2aa126 100644 --- a/modules/juce_opengl/native/juce_OpenGL_android.h +++ b/modules/juce_opengl/native/juce_OpenGL_android.h @@ -103,26 +103,6 @@ static const uint8 javaJuceOpenGLView[] = }; //============================================================================== -struct AndroidGLCallbacks -{ - static void attachedToWindow (JNIEnv*, jobject, jlong); - static void detachedFromWindow (JNIEnv*, jobject, jlong); - static void dispatchDraw (JNIEnv*, jobject, jlong, jobject); -}; - -//============================================================================== -#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ - METHOD (constructor, "", "(Landroid/content/Context;J)V") \ - METHOD (getParent, "getParent", "()Landroid/view/ViewParent;") \ - METHOD (getHolder, "getHolder", "()Landroid/view/SurfaceHolder;") \ - METHOD (layout, "layout", "(IIII)V" ) \ - CALLBACK (AndroidGLCallbacks::attachedToWindow, "onAttchedWindowNative", "(J)V") \ - CALLBACK (AndroidGLCallbacks::detachedFromWindow, "onDetachedFromWindowNative", "(J)V") \ - CALLBACK (AndroidGLCallbacks::dispatchDraw, "onDrawNative", "(JLandroid/graphics/Canvas;)V") - -DECLARE_JNI_CLASS_WITH_BYTECODE (JuceOpenGLViewSurface, "com/rmsl/juce/JuceOpenGLView", 16, javaJuceOpenGLView, sizeof(javaJuceOpenGLView)) -#undef JNI_CLASS_MEMBERS - //============================================================================== class OpenGLContext::NativeContext : private SurfaceHolderCallback { @@ -266,40 +246,46 @@ public: Component& component; private: - //============================================================================== - friend struct AndroidGLCallbacks; + #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ + METHOD (constructor, "", "(Landroid/content/Context;J)V") \ + METHOD (getParent, "getParent", "()Landroid/view/ViewParent;") \ + METHOD (getHolder, "getHolder", "()Landroid/view/SurfaceHolder;") \ + METHOD (layout, "layout", "(IIII)V" ) \ + CALLBACK (generatedCallback<&NativeContext::attachedToWindow>, "onAttchedWindowNative", "(J)V") \ + CALLBACK (generatedCallback<&NativeContext::detachedFromWindow>, "onDetachedFromWindowNative", "(J)V") \ + CALLBACK (generatedCallback<&NativeContext::dispatchDraw>, "onDrawNative", "(JLandroid/graphics/Canvas;)V") + + DECLARE_JNI_CLASS_WITH_BYTECODE (JuceOpenGLViewSurface, "com/rmsl/juce/JuceOpenGLView", 16, javaJuceOpenGLView) + #undef JNI_CLASS_MEMBERS - void attachedToWindow() + //============================================================================== + static void attachedToWindow (JNIEnv* env, NativeContext& t) { - auto* env = getEnv(); - - LocalRef holder (env->CallObjectMethod (surfaceView.get(), JuceOpenGLViewSurface.getHolder)); + LocalRef holder (env->CallObjectMethod (t.surfaceView.get(), JuceOpenGLViewSurface.getHolder)); - if (surfaceHolderCallback == nullptr) - surfaceHolderCallback = GlobalRef (CreateJavaInterface (this, "android/view/SurfaceHolder$Callback")); + if (t.surfaceHolderCallback == nullptr) + t.surfaceHolderCallback = GlobalRef (CreateJavaInterface (&t, "android/view/SurfaceHolder$Callback")); - env->CallVoidMethod (holder, AndroidSurfaceHolder.addCallback, surfaceHolderCallback.get()); + env->CallVoidMethod (holder, AndroidSurfaceHolder.addCallback, t.surfaceHolderCallback.get()); } - void detachedFromWindow() + static void detachedFromWindow (JNIEnv* env, NativeContext& t) { - if (surfaceHolderCallback != nullptr) + if (t.surfaceHolderCallback != nullptr) { - auto* env = getEnv(); + LocalRef holder (env->CallObjectMethod (t.surfaceView.get(), JuceOpenGLViewSurface.getHolder)); - LocalRef holder (env->CallObjectMethod (surfaceView.get(), JuceOpenGLViewSurface.getHolder)); - - env->CallVoidMethod (holder.get(), AndroidSurfaceHolder.removeCallback, surfaceHolderCallback.get()); - surfaceHolderCallback.clear(); + env->CallVoidMethod (holder.get(), AndroidSurfaceHolder.removeCallback, t.surfaceHolderCallback.get()); + t.surfaceHolderCallback.clear(); } } - void dispatchDraw (jobject /*canvas*/) + static void dispatchDraw (JNIEnv*, NativeContext& t, jobject /*canvas*/) { - const std::lock_guard lock { nativeHandleMutex }; + const std::lock_guard lock { t.nativeHandleMutex }; - if (juceContext != nullptr) - juceContext->triggerRepaint(); + if (t.juceContext != nullptr) + t.juceContext->triggerRepaint(); } bool tryChooseConfig (const std::vector& optionalAttribs) @@ -414,25 +400,6 @@ private: EGLDisplay OpenGLContext::NativeContext::display = EGL_NO_DISPLAY; EGLDisplay OpenGLContext::NativeContext::config; -//============================================================================== -void AndroidGLCallbacks::attachedToWindow (JNIEnv*, jobject /*this*/, jlong host) -{ - if (auto* nativeContext = reinterpret_cast (host)) - nativeContext->attachedToWindow(); -} - -void AndroidGLCallbacks::detachedFromWindow (JNIEnv*, jobject /*this*/, jlong host) -{ - if (auto* nativeContext = reinterpret_cast (host)) - nativeContext->detachedFromWindow(); -} - -void AndroidGLCallbacks::dispatchDraw (JNIEnv*, jobject /*this*/, jlong host, jobject canvas) -{ - if (auto* nativeContext = reinterpret_cast (host)) - nativeContext->dispatchDraw (canvas); -} - //============================================================================== bool OpenGLHelpers::isContextActive() { diff --git a/modules/juce_product_unlocking/native/juce_android_InAppPurchases.cpp b/modules/juce_product_unlocking/native/juce_android_InAppPurchases.cpp index 91422393e9..3a33fbb177 100644 --- a/modules/juce_product_unlocking/native/juce_android_InAppPurchases.cpp +++ b/modules/juce_product_unlocking/native/juce_android_InAppPurchases.cpp @@ -143,7 +143,7 @@ inline StringArray javaListOfStringToJuceStringArray (const LocalRef& j } //============================================================================== -constexpr unsigned char juceBillingClientCompiled[] +constexpr uint8 juceBillingClientCompiled[] { 0x1f, 0x8b, 0x08, 0x08, 0xa4, 0x53, 0xd0, 0x62, 0x04, 0x03, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x65, 0x73, 0x2e, 0x64, 0x65, 0x78, 0x00, 0x9d, 0x5a, @@ -720,42 +720,17 @@ private: METHOD (queryPurchases, "queryPurchases", "()V") \ METHOD (consumePurchase, "consumePurchase", "(Ljava/lang/String;Ljava/lang/String;)V") \ \ - CALLBACK (productDetailsQueryCallback, "productDetailsQueryCallback", "(JLjava/util/List;)V") \ - CALLBACK (purchasesListQueryCallback, "purchasesListQueryCallback", "(JLjava/util/List;)V") \ - CALLBACK (purchaseCompletedCallback, "purchaseCompletedCallback", "(JLcom/android/billingclient/api/Purchase;I)V") \ - CALLBACK (purchaseConsumedCallback, "purchaseConsumedCallback", "(JLjava/lang/String;I)V") + CALLBACK (generatedCallback<&Pimpl::updateProductDetails>, "productDetailsQueryCallback", "(JLjava/util/List;)V") \ + CALLBACK (generatedCallback<&Pimpl::updatePurchasesList>, "purchasesListQueryCallback", "(JLjava/util/List;)V") \ + CALLBACK (generatedCallback<&Pimpl::purchaseCompleted>, "purchaseCompletedCallback", "(JLcom/android/billingclient/api/Purchase;I)V") \ + CALLBACK (generatedCallback<&Pimpl::purchaseConsumed>, "purchaseConsumedCallback", "(JLjava/lang/String;I)V") DECLARE_JNI_CLASS_WITH_BYTECODE (JuceBillingClient, "com/rmsl/juce/JuceBillingClient", 16, - juceBillingClientCompiled, - numElementsInArray (juceBillingClientCompiled)) + juceBillingClientCompiled) #undef JNI_CLASS_MEMBERS - static void JNICALL productDetailsQueryCallback (JNIEnv*, jobject, jlong host, jobject productDetailsList) - { - if (auto* myself = reinterpret_cast (host)) - myself->updateProductDetails (productDetailsList); - } - - static void JNICALL purchasesListQueryCallback (JNIEnv*, jobject, jlong host, jobject purchasesList) - { - if (auto* myself = reinterpret_cast (host)) - myself->updatePurchasesList (purchasesList); - } - - static void JNICALL purchaseCompletedCallback (JNIEnv*, jobject, jlong host, jobject purchase, int responseCode) - { - if (auto* myself = reinterpret_cast (host)) - myself->purchaseCompleted (purchase, responseCode); - } - - static void JNICALL purchaseConsumedCallback (JNIEnv*, jobject, jlong host, jstring productIdentifier, int responseCode) - { - if (auto* myself = reinterpret_cast (host)) - myself->purchaseConsumed (productIdentifier, responseCode); - } - //============================================================================== bool isReady() const { @@ -1095,7 +1070,4 @@ void juce_handleOnResume() }); } - -InAppPurchases::Pimpl::JuceBillingClient_Class InAppPurchases::Pimpl::JuceBillingClient; - } // namespace juce diff --git a/modules/juce_video/native/juce_android_CameraDevice.h b/modules/juce_video/native/juce_android_CameraDevice.h index e55ba1279d..fd29bfb7bd 100644 --- a/modules/juce_video/native/juce_android_CameraDevice.h +++ b/modules/juce_video/native/juce_android_CameraDevice.h @@ -400,7 +400,7 @@ class MediaRecorderOnInfoListener : public AndroidInterfaceImplementer public: struct Owner { - virtual ~Owner() {} + virtual ~Owner() = default; virtual void onInfo (LocalRef& mediaRecorder, int what, int extra) = 0; }; @@ -1711,26 +1711,25 @@ private: //============================================================================== #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ METHOD (constructor, "", "(JZ)V") \ - CALLBACK (cameraCaptureSessionCaptureCompletedCallback, "cameraCaptureSessionCaptureCompleted", "(JZLandroid/hardware/camera2/CameraCaptureSession;Landroid/hardware/camera2/CaptureRequest;Landroid/hardware/camera2/TotalCaptureResult;)V") \ - CALLBACK (cameraCaptureSessionCaptureFailedCallback, "cameraCaptureSessionCaptureFailed", "(JZLandroid/hardware/camera2/CameraCaptureSession;Landroid/hardware/camera2/CaptureRequest;Landroid/hardware/camera2/CaptureFailure;)V") \ - CALLBACK (cameraCaptureSessionCaptureProgressedCallback, "cameraCaptureSessionCaptureProgressed", "(JZLandroid/hardware/camera2/CameraCaptureSession;Landroid/hardware/camera2/CaptureRequest;Landroid/hardware/camera2/CaptureResult;)V") \ - CALLBACK (cameraCaptureSessionCaptureStartedCallback, "cameraCaptureSessionCaptureStarted", "(JZLandroid/hardware/camera2/CameraCaptureSession;Landroid/hardware/camera2/CaptureRequest;JJ)V") \ - CALLBACK (cameraCaptureSessionCaptureSequenceAbortedCallback, "cameraCaptureSessionCaptureSequenceAborted", "(JZLandroid/hardware/camera2/CameraCaptureSession;I)V") \ - CALLBACK (cameraCaptureSessionCaptureSequenceCompletedCallback, "cameraCaptureSessionCaptureSequenceCompleted", "(JZLandroid/hardware/camera2/CameraCaptureSession;IJ)V") - - DECLARE_JNI_CLASS_WITH_BYTECODE (CameraCaptureSessionCaptureCallback, "com/rmsl/juce/CameraCaptureSessionCaptureCallback", 21, CameraSupportByteCode, sizeof(CameraSupportByteCode)) + CALLBACK (generatedCallback<&StillPictureTaker::cameraCaptureSessionCaptureCompletedCallback>, "cameraCaptureSessionCaptureCompleted", "(JZLandroid/hardware/camera2/CameraCaptureSession;Landroid/hardware/camera2/CaptureRequest;Landroid/hardware/camera2/TotalCaptureResult;)V") \ + CALLBACK (generatedCallback<&StillPictureTaker::cameraCaptureSessionCaptureFailedCallback>, "cameraCaptureSessionCaptureFailed", "(JZLandroid/hardware/camera2/CameraCaptureSession;Landroid/hardware/camera2/CaptureRequest;Landroid/hardware/camera2/CaptureFailure;)V") \ + CALLBACK (generatedCallback<&StillPictureTaker::cameraCaptureSessionCaptureProgressedCallback>, "cameraCaptureSessionCaptureProgressed", "(JZLandroid/hardware/camera2/CameraCaptureSession;Landroid/hardware/camera2/CaptureRequest;Landroid/hardware/camera2/CaptureResult;)V") \ + CALLBACK (generatedCallback<&StillPictureTaker::cameraCaptureSessionCaptureStartedCallback>, "cameraCaptureSessionCaptureStarted", "(JZLandroid/hardware/camera2/CameraCaptureSession;Landroid/hardware/camera2/CaptureRequest;JJ)V") \ + CALLBACK (generatedCallback<&StillPictureTaker::cameraCaptureSessionCaptureSequenceAbortedCallback>, "cameraCaptureSessionCaptureSequenceAborted", "(JZLandroid/hardware/camera2/CameraCaptureSession;I)V") \ + CALLBACK (generatedCallback<&StillPictureTaker::cameraCaptureSessionCaptureSequenceCompletedCallback>, "cameraCaptureSessionCaptureSequenceCompleted", "(JZLandroid/hardware/camera2/CameraCaptureSession;IJ)V") + + DECLARE_JNI_CLASS_WITH_BYTECODE (CameraCaptureSessionCaptureCallback, "com/rmsl/juce/CameraCaptureSessionCaptureCallback", 21, CameraSupportByteCode) #undef JNI_CLASS_MEMBERS LocalRef createCaptureSessionCallback (bool createPreviewSession) { - return LocalRef(getEnv()->NewObject (CameraCaptureSessionCaptureCallback, - CameraCaptureSessionCaptureCallback.constructor, - reinterpret_cast (this), - createPreviewSession ? 1 : 0)); + return LocalRef (getEnv()->NewObject (CameraCaptureSessionCaptureCallback, + CameraCaptureSessionCaptureCallback.constructor, + reinterpret_cast (this), + createPreviewSession ? 1 : 0)); } //============================================================================== - enum class State { idle = 0, @@ -2022,71 +2021,53 @@ private: } //============================================================================== - static void cameraCaptureSessionCaptureCompletedCallback (JNIEnv*, jobject /*object*/, jlong host, jboolean isPreview, jobject rawSession, jobject rawRequest, jobject rawResult) + static void cameraCaptureSessionCaptureCompletedCallback (JNIEnv* env, StillPictureTaker& t, jboolean isPreview, jobject rawSession, jobject rawRequest, jobject rawResult) { - if (auto* myself = reinterpret_cast (host)) - { - LocalRef session (getEnv()->NewLocalRef(rawSession)); - LocalRef request (getEnv()->NewLocalRef(rawRequest)); - LocalRef result (getEnv()->NewLocalRef(rawResult)); + LocalRef session (env->NewLocalRef (rawSession)); + LocalRef request (env->NewLocalRef (rawRequest)); + LocalRef result (env->NewLocalRef (rawResult)); - myself->cameraCaptureSessionCaptureCompleted (isPreview != 0, session, request, result); - } + t.cameraCaptureSessionCaptureCompleted (isPreview != 0, session, request, result); } - static void cameraCaptureSessionCaptureFailedCallback (JNIEnv*, jobject /*object*/, jlong host, jboolean isPreview, jobject rawSession, jobject rawRequest, jobject rawResult) + static void cameraCaptureSessionCaptureFailedCallback (JNIEnv* env, StillPictureTaker& t, jboolean isPreview, jobject rawSession, jobject rawRequest, jobject rawResult) { - if (auto* myself = reinterpret_cast (host)) - { - LocalRef session (getEnv()->NewLocalRef(rawSession)); - LocalRef request (getEnv()->NewLocalRef(rawRequest)); - LocalRef result (getEnv()->NewLocalRef(rawResult)); + LocalRef session (env->NewLocalRef (rawSession)); + LocalRef request (env->NewLocalRef (rawRequest)); + LocalRef result (env->NewLocalRef (rawResult)); - myself->cameraCaptureSessionCaptureFailed (isPreview != 0, session, request, result); - } + t.cameraCaptureSessionCaptureFailed (isPreview != 0, session, request, result); } - static void cameraCaptureSessionCaptureProgressedCallback (JNIEnv*, jobject /*object*/, jlong host, jboolean isPreview, jobject rawSession, jobject rawRequest, jobject rawResult) + static void cameraCaptureSessionCaptureProgressedCallback (JNIEnv* env, StillPictureTaker& t, jboolean isPreview, jobject rawSession, jobject rawRequest, jobject rawResult) { - if (auto* myself = reinterpret_cast (host)) - { - LocalRef session (getEnv()->NewLocalRef(rawSession)); - LocalRef request (getEnv()->NewLocalRef(rawRequest)); - LocalRef result (getEnv()->NewLocalRef(rawResult)); + LocalRef session (env->NewLocalRef (rawSession)); + LocalRef request (env->NewLocalRef (rawRequest)); + LocalRef result (env->NewLocalRef (rawResult)); - myself->cameraCaptureSessionCaptureProgressed (isPreview != 0, session, request, result); - } + t.cameraCaptureSessionCaptureProgressed (isPreview != 0, session, request, result); } - static void cameraCaptureSessionCaptureSequenceAbortedCallback (JNIEnv*, jobject /*object*/, jlong host, jboolean isPreview, jobject rawSession, jint sequenceId) + static void cameraCaptureSessionCaptureSequenceAbortedCallback (JNIEnv* env, StillPictureTaker& t, jboolean isPreview, jobject rawSession, jint sequenceId) { - if (auto* myself = reinterpret_cast (host)) - { - LocalRef session (getEnv()->NewLocalRef(rawSession)); + LocalRef session (env->NewLocalRef (rawSession)); - myself->cameraCaptureSessionCaptureSequenceAborted (isPreview != 0, session, sequenceId); - } + t.cameraCaptureSessionCaptureSequenceAborted (isPreview != 0, session, sequenceId); } - static void cameraCaptureSessionCaptureSequenceCompletedCallback (JNIEnv*, jobject /*object*/, jlong host, jboolean isPreview, jobject rawSession, jint sequenceId, jlong frameNumber) + static void cameraCaptureSessionCaptureSequenceCompletedCallback (JNIEnv* env, StillPictureTaker& t, jboolean isPreview, jobject rawSession, jint sequenceId, jlong frameNumber) { - if (auto* myself = reinterpret_cast (host)) - { - LocalRef session (getEnv()->NewLocalRef(rawSession)); + LocalRef session (env->NewLocalRef (rawSession)); - myself->cameraCaptureSessionCaptureSequenceCompleted (isPreview != 0, session, sequenceId, frameNumber); - } + t.cameraCaptureSessionCaptureSequenceCompleted (isPreview != 0, session, sequenceId, frameNumber); } - static void cameraCaptureSessionCaptureStartedCallback (JNIEnv*, jobject /*object*/, jlong host, jboolean isPreview, jobject rawSession, jobject rawRequest, jlong timestamp, jlong frameNumber) + static void cameraCaptureSessionCaptureStartedCallback (JNIEnv* env, StillPictureTaker& t, jboolean isPreview, jobject rawSession, jobject rawRequest, jlong timestamp, jlong frameNumber) { - if (auto* myself = reinterpret_cast (host)) - { - LocalRef session (getEnv()->NewLocalRef(rawSession)); - LocalRef request (getEnv()->NewLocalRef(rawRequest)); + LocalRef session (env->NewLocalRef (rawSession)); + LocalRef request (env->NewLocalRef (rawRequest)); - myself->cameraCaptureSessionCaptureStarted (isPreview != 0, session, request, timestamp, frameNumber); - } + t.cameraCaptureSessionCaptureStarted (isPreview != 0, session, request, timestamp, frameNumber); } }; @@ -2115,11 +2096,11 @@ private: //============================================================================== #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ METHOD (constructor, "", "(J)V") \ - CALLBACK(cameraCaptureSessionActiveCallback, "cameraCaptureSessionActive", "(JLandroid/hardware/camera2/CameraCaptureSession;)V") \ - CALLBACK(cameraCaptureSessionClosedCallback, "cameraCaptureSessionClosed", "(JLandroid/hardware/camera2/CameraCaptureSession;)V") \ - CALLBACK(cameraCaptureSessionConfigureFailedCallback, "cameraCaptureSessionConfigureFailed", "(JLandroid/hardware/camera2/CameraCaptureSession;)V") \ - CALLBACK(cameraCaptureSessionConfiguredCallback, "cameraCaptureSessionConfigured", "(JLandroid/hardware/camera2/CameraCaptureSession;)V") \ - CALLBACK(cameraCaptureSessionReadyCallback, "cameraCaptureSessionReady", "(JLandroid/hardware/camera2/CameraCaptureSession;)V") + CALLBACK (generatedCallback<&CaptureSession::cameraCaptureSessionActiveCallback>, "cameraCaptureSessionActive", "(JLandroid/hardware/camera2/CameraCaptureSession;)V") \ + CALLBACK (generatedCallback<&CaptureSession::cameraCaptureSessionClosedCallback>, "cameraCaptureSessionClosed", "(JLandroid/hardware/camera2/CameraCaptureSession;)V") \ + CALLBACK (generatedCallback<&CaptureSession::cameraCaptureSessionConfigureFailedCallback>, "cameraCaptureSessionConfigureFailed", "(JLandroid/hardware/camera2/CameraCaptureSession;)V") \ + CALLBACK (generatedCallback<&CaptureSession::cameraCaptureSessionConfiguredCallback>, "cameraCaptureSessionConfigured", "(JLandroid/hardware/camera2/CameraCaptureSession;)V") \ + CALLBACK (generatedCallback<&CaptureSession::cameraCaptureSessionReadyCallback>, "cameraCaptureSessionReady", "(JLandroid/hardware/camera2/CameraCaptureSession;)V") DECLARE_JNI_CLASS_WITH_MIN_SDK (CameraCaptureSessionStateCallback, "com/rmsl/juce/CameraCaptureSessionStateCallback", 21) #undef JNI_CLASS_MEMBERS @@ -2161,124 +2142,83 @@ private: env->CallVoidMethod (captureRequestBuilder, CaptureRequestBuilder.set, jKey.get(), jValue.get()); } - void cameraCaptureSessionActive ([[maybe_unused]] jobject session) + //============================================================================== + static void cameraCaptureSessionActiveCallback ([[maybe_unused]] JNIEnv* env, + [[maybe_unused]] CaptureSession& t, + [[maybe_unused]] jobject rawSession) { JUCE_CAMERA_LOG ("cameraCaptureSessionActive()"); } - void cameraCaptureSessionClosed ([[maybe_unused]] jobject session) + static void cameraCaptureSessionClosedCallback ([[maybe_unused]] JNIEnv* env, + CaptureSession& t, + [[maybe_unused]] jobject rawSession) { JUCE_CAMERA_LOG ("cameraCaptureSessionClosed()"); - closedEvent.signal(); + t.closedEvent.signal(); } - void cameraCaptureSessionConfigureFailed ([[maybe_unused]] jobject session) + static void cameraCaptureSessionConfigureFailedCallback ([[maybe_unused]] JNIEnv* env, + CaptureSession& t, + [[maybe_unused]] jobject rawSession) { JUCE_CAMERA_LOG ("cameraCaptureSessionConfigureFailed()"); - MessageManager::callAsync ([weakRef = WeakReference { this }] - { - if (weakRef != nullptr) - weakRef->configuredCallback.captureSessionConfigured (nullptr); - }); + MessageManager::callAsync ([weakRef = WeakReference { &t }] + { + if (weakRef != nullptr) + weakRef->configuredCallback.captureSessionConfigured (nullptr); + }); } - void cameraCaptureSessionConfigured (const LocalRef& session) + static void cameraCaptureSessionConfiguredCallback (JNIEnv* env, CaptureSession& t, jobject rawSession) { + LocalRef session (env->NewLocalRef (rawSession)); JUCE_CAMERA_LOG ("cameraCaptureSessionConfigured()"); - if (pendingClose.get() == 1) + if (t.pendingClose.get() == 1) { // Already closing, bailout. - closedEvent.signal(); + t.closedEvent.signal(); GlobalRef s (session); MessageManager::callAsync ([s]() - { - getEnv()->CallVoidMethod (s, CameraCaptureSession.close); - }); + { + getEnv()->CallVoidMethod (s, CameraCaptureSession.close); + }); return; } { - const ScopedLock lock (captureSessionLock); - captureSession = GlobalRef (session); + const ScopedLock lock (t.captureSessionLock); + t.captureSession = GlobalRef (session); } - MessageManager::callAsync ([weakRef = WeakReference { this }] - { - if (weakRef == nullptr) - return; + MessageManager::callAsync ([weakRef = WeakReference { &t }] + { + if (weakRef == nullptr) + return; - weakRef->stillPictureTaker.reset (new StillPictureTaker (weakRef->captureSession, - weakRef->captureRequestBuilder, - weakRef->previewCaptureRequest, - weakRef->handler, - weakRef->autoFocusMode)); + weakRef->stillPictureTaker.reset (new StillPictureTaker (weakRef->captureSession, + weakRef->captureRequestBuilder, + weakRef->previewCaptureRequest, + weakRef->handler, + weakRef->autoFocusMode)); - weakRef->configuredCallback.captureSessionConfigured (weakRef.get()); - }); + weakRef->configuredCallback.captureSessionConfigured (weakRef.get()); + }); } - void cameraCaptureSessionReady ([[maybe_unused]] const LocalRef& session) + static void cameraCaptureSessionReadyCallback ([[maybe_unused]] JNIEnv* env, + [[maybe_unused]] CaptureSession& t, + [[maybe_unused]] jobject rawSession) { JUCE_CAMERA_LOG ("cameraCaptureSessionReady()"); } - //============================================================================== - static void cameraCaptureSessionActiveCallback (JNIEnv*, jobject, jlong host, jobject rawSession) - { - if (auto* myself = reinterpret_cast (host)) - { - LocalRef session (getEnv()->NewLocalRef(rawSession)); - - myself->cameraCaptureSessionActive (session); - } - } - - static void cameraCaptureSessionClosedCallback (JNIEnv*, jobject, jlong host, jobject rawSession) - { - if (auto* myself = reinterpret_cast (host)) - { - LocalRef session (getEnv()->NewLocalRef(rawSession)); - - myself->cameraCaptureSessionClosed (session); - } - } - - static void cameraCaptureSessionConfigureFailedCallback (JNIEnv*, jobject, jlong host, jobject rawSession) - { - if (auto* myself = reinterpret_cast (host)) - { - LocalRef session (getEnv()->NewLocalRef(rawSession)); - - myself->cameraCaptureSessionConfigureFailed (session); - } - } - - static void cameraCaptureSessionConfiguredCallback (JNIEnv*, jobject, jlong host, jobject rawSession) - { - if (auto* myself = reinterpret_cast (host)) - { - LocalRef session (getEnv()->NewLocalRef(rawSession)); - - myself->cameraCaptureSessionConfigured (session); - } - } - - static void cameraCaptureSessionReadyCallback (JNIEnv*, jobject, jlong host, jobject rawSession) - { - if (auto* myself = reinterpret_cast (host)) - { - LocalRef session (getEnv()->NewLocalRef(rawSession)); - - myself->cameraCaptureSessionReady (session); - } - } - //============================================================================== friend class ScopedCameraDevice; @@ -2374,10 +2314,10 @@ private: //============================================================================== #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ METHOD (constructor, "", "(J)V") \ - CALLBACK (cameraDeviceStateClosedCallback, "cameraDeviceStateClosed", "(JLandroid/hardware/camera2/CameraDevice;)V") \ - CALLBACK (cameraDeviceStateDisconnectedCallback, "cameraDeviceStateDisconnected", "(JLandroid/hardware/camera2/CameraDevice;)V") \ - CALLBACK (cameraDeviceStateErrorCallback, "cameraDeviceStateError", "(JLandroid/hardware/camera2/CameraDevice;I)V") \ - CALLBACK (cameraDeviceStateOpenedCallback, "cameraDeviceStateOpened", "(JLandroid/hardware/camera2/CameraDevice;)V") + CALLBACK (generatedCallback<&ScopedCameraDevice::cameraDeviceStateClosedCallback>, "cameraDeviceStateClosed", "(JLandroid/hardware/camera2/CameraDevice;)V") \ + CALLBACK (generatedCallback<&ScopedCameraDevice::cameraDeviceStateDisconnectedCallback>, "cameraDeviceStateDisconnected", "(JLandroid/hardware/camera2/CameraDevice;)V") \ + CALLBACK (generatedCallback<&ScopedCameraDevice::cameraDeviceStateErrorCallback>, "cameraDeviceStateError", "(JLandroid/hardware/camera2/CameraDevice;I)V") \ + CALLBACK (generatedCallback<&ScopedCameraDevice::cameraDeviceStateOpenedCallback>, "cameraDeviceStateOpened", "(JLandroid/hardware/camera2/CameraDevice;)V") DECLARE_JNI_CLASS_WITH_MIN_SDK (CameraDeviceStateCallback, "com/rmsl/juce/CameraDeviceStateCallback", 21) #undef JNI_CLASS_MEMBERS @@ -2390,92 +2330,66 @@ private: } //============================================================================== - void cameraDeviceStateClosed() + void notifyOpenResult() + { + MessageManager::callAsync ([this]() { owner.cameraOpenFinished (openError); }); + } + + //============================================================================== + static void cameraDeviceStateClosedCallback (JNIEnv*, ScopedCameraDevice& s, jobject) { JUCE_CAMERA_LOG ("cameraDeviceStateClosed()"); - closedEvent.signal(); + s.closedEvent.signal(); } - void cameraDeviceStateDisconnected() + static void cameraDeviceStateDisconnectedCallback (JNIEnv*, ScopedCameraDevice& s, jobject) { JUCE_CAMERA_LOG ("cameraDeviceStateDisconnected()"); - if (pendingOpen.compareAndSetBool (0, 1)) + if (s.pendingOpen.compareAndSetBool (0, 1)) { - openError = "Device disconnected"; + s.openError = "Device disconnected"; - notifyOpenResult(); + s.notifyOpenResult(); } - MessageManager::callAsync ([this]() { close(); }); + MessageManager::callAsync ([&s] { s.close(); }); } - void cameraDeviceStateError (int errorCode) + static void cameraDeviceStateErrorCallback (JNIEnv*, ScopedCameraDevice& s, jobject, jint errorCode) { - String error = cameraErrorCodeToString (errorCode); + auto error = cameraErrorCodeToString (errorCode); JUCE_CAMERA_LOG ("cameraDeviceStateError(), error: " + error); - if (pendingOpen.compareAndSetBool (0, 1)) + if (s.pendingOpen.compareAndSetBool (0, 1)) { - openError = error; + s.openError = error; - notifyOpenResult(); + s.notifyOpenResult(); } - fatalErrorOccurred.set (1); + s.fatalErrorOccurred.set (1); - MessageManager::callAsync ([this, error]() + MessageManager::callAsync ([&s, error]() { - owner.cameraDeviceError (error); - close(); + s.owner.cameraDeviceError (error); + s.close(); }); } - void cameraDeviceStateOpened (const LocalRef& cameraDeviceToUse) + static void cameraDeviceStateOpenedCallback (JNIEnv* env, ScopedCameraDevice& s, jobject cameraDeviceToUse) { JUCE_CAMERA_LOG ("cameraDeviceStateOpened()"); - pendingOpen.set (0); + LocalRef camera (env->NewLocalRef (cameraDeviceToUse)); - cameraDevice = GlobalRef (cameraDeviceToUse); + s.pendingOpen.set (0); - notifyOpenResult(); - } + s.cameraDevice = GlobalRef (camera); - void notifyOpenResult() - { - MessageManager::callAsync ([this]() { owner.cameraOpenFinished (openError); }); - } - - //============================================================================== - static void JNICALL cameraDeviceStateClosedCallback (JNIEnv*, jobject, jlong host, jobject) - { - if (auto* myself = reinterpret_cast(host)) - myself->cameraDeviceStateClosed(); - } - - static void JNICALL cameraDeviceStateDisconnectedCallback (JNIEnv*, jobject, jlong host, jobject) - { - if (auto* myself = reinterpret_cast(host)) - myself->cameraDeviceStateDisconnected(); - } - - static void JNICALL cameraDeviceStateErrorCallback (JNIEnv*, jobject, jlong host, jobject, jint error) - { - if (auto* myself = reinterpret_cast(host)) - myself->cameraDeviceStateError (error); - } - - static void JNICALL cameraDeviceStateOpenedCallback (JNIEnv*, jobject, jlong host, jobject rawCamera) - { - if (auto* myself = reinterpret_cast(host)) - { - LocalRef camera(getEnv()->NewLocalRef(rawCamera)); - - myself->cameraDeviceStateOpened (camera); - } + s.notifyOpenResult(); } }; @@ -2815,7 +2729,7 @@ private: METHOD (constructor, "", "(JLandroid/content/Context;I)V") \ METHOD (disable, "disable", "()V") \ METHOD (enable, "enable", "()V") \ - CALLBACK (deviceOrientationChanged, "deviceOrientationChanged", "(JI)V") + CALLBACK (generatedCallback<&DeviceOrientationChangeListener::orientationChanged>, "deviceOrientationChanged", "(JI)V") DECLARE_JNI_CLASS_WITH_MIN_SDK (OrientationEventListener, "com/rmsl/juce/JuceOrientationEventListener", 21) #undef JNI_CLASS_MEMBERS @@ -2830,7 +2744,7 @@ private: } //============================================================================== - void orientationChanged (int orientation) + static void orientationChanged (JNIEnv*, DeviceOrientationChangeListener& t, jint orientation) { jassert (orientation < 360); @@ -2838,25 +2752,31 @@ private: if (orientation < 0) return; - auto oldOrientation = deviceOrientation; + const auto oldOrientation = t.deviceOrientation; + + t.deviceOrientation = [orientation] + { + if (orientation > (360 - 45) || orientation < 45) + return Desktop::upright; + + if (orientation < 135) + return Desktop::rotatedClockwise; + + if (orientation < 225) + return Desktop::upsideDown; + + return Desktop::rotatedAntiClockwise; + }(); // NB: this assumes natural position to be portrait always, but some devices may be landscape... - if (orientation > (360 - 45) || orientation < 45) - deviceOrientation = Desktop::upright; - else if (orientation < 135) - deviceOrientation = Desktop::rotatedClockwise; - else if (orientation < 225) - deviceOrientation = Desktop::upsideDown; - else - deviceOrientation = Desktop::rotatedAntiClockwise; - if (oldOrientation != deviceOrientation) + if (oldOrientation != t.deviceOrientation) { - lastKnownScreenOrientation = Desktop::getInstance().getCurrentOrientation(); + t.lastKnownScreenOrientation = Desktop::getInstance().getCurrentOrientation(); // Need to update preview transform, but screen orientation will change slightly // later than sensor orientation. - startTimer (500); + t.startTimer (500); } } @@ -2881,12 +2801,6 @@ private: numChecksForOrientationChange = 10; } } - - static void deviceOrientationChanged (JNIEnv*, jobject /*obj*/, jlong host, jint orientation) - { - if (auto* myself = reinterpret_cast (host)) - myself->orientationChanged (orientation); - } }; //============================================================================== @@ -3180,7 +3094,7 @@ private: { auto* env = getEnv(); - auto quitSafelyMethod = env->GetMethodID(AndroidHandlerThread, "quitSafely", "()Z"); + auto quitSafelyMethod = env->GetMethodID (AndroidHandlerThread, "quitSafely", "()Z"); // this code will only run on SDK >= 21 jassert(quitSafelyMethod != nullptr); @@ -3268,9 +3182,3 @@ String CameraDevice::getFileExtension() { return ".mp4"; } - -//============================================================================== -CameraDevice::Pimpl::ScopedCameraDevice::CaptureSession::StillPictureTaker::CameraCaptureSessionCaptureCallback_Class CameraDevice::Pimpl::ScopedCameraDevice::CaptureSession::StillPictureTaker::CameraCaptureSessionCaptureCallback; -CameraDevice::Pimpl::ScopedCameraDevice::CameraDeviceStateCallback_Class CameraDevice::Pimpl::ScopedCameraDevice::CameraDeviceStateCallback; -CameraDevice::Pimpl::ScopedCameraDevice::CaptureSession::CameraCaptureSessionStateCallback_Class CameraDevice::Pimpl::ScopedCameraDevice::CaptureSession::CameraCaptureSessionStateCallback; -CameraDevice::Pimpl::DeviceOrientationChangeListener::OrientationEventListener_Class CameraDevice::Pimpl::DeviceOrientationChangeListener::OrientationEventListener; diff --git a/modules/juce_video/native/juce_android_Video.h b/modules/juce_video/native/juce_android_Video.h index 4f8810f8e6..56d94bbb9a 100644 --- a/modules/juce_video/native/juce_android_Video.h +++ b/modules/juce_video/native/juce_android_Video.h @@ -32,7 +32,7 @@ // // files with min sdk version 21 // See juce_core/native/java/README.txt on how to generate this byte-code. -static const unsigned char MediaSessionByteCode[] = +static const uint8 MediaSessionByteCode[] = { 31,139,8,8,247,108,161,94,0,3,77,101,100,105,97,83,101,115,115,105,111,110,66,121,116,101,67,111,100,101,46,100,101,120,0,149, 152,127,108,28,71,21,199,223,236,253,180,207,190,95,254,221,186,169,211,56,137,19,234,220,145,26,226,228,28,99,199,216,196,233, 249,71,125,182,107,76,168,187,246,109,236,77,238,118,143,221,189,171,45,132,168,170,32,21,209,63,144,74,165,170,82,81,144,64, @@ -757,12 +757,12 @@ private: //============================================================================== #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ METHOD (constructor, "", "(J)V") \ - CALLBACK (audioInfoChanged, "mediaControllerAudioInfoChanged", "(JLandroid/media/session/MediaController$PlaybackInfo;)V") \ - CALLBACK (metadataChanged, "mediaControllerMetadataChanged", "(JLandroid/media/MediaMetadata;)V") \ - CALLBACK (playbackStateChanged, "mediaControllerPlaybackStateChanged", "(JLandroid/media/session/PlaybackState;)V") \ - CALLBACK (sessionDestroyed, "mediaControllerSessionDestroyed", "(J)V") + CALLBACK (generatedCallback<&Controller::audioInfoChanged>, "mediaControllerAudioInfoChanged", "(JLandroid/media/session/MediaController$PlaybackInfo;)V") \ + CALLBACK (generatedCallback<&Controller::metadataChanged>, "mediaControllerMetadataChanged", "(JLandroid/media/MediaMetadata;)V") \ + CALLBACK (generatedCallback<&Controller::playbackStateChanged>, "mediaControllerPlaybackStateChanged", "(JLandroid/media/session/PlaybackState;)V") \ + CALLBACK (generatedCallback<&Controller::sessionDestroyed>, "mediaControllerSessionDestroyed", "(J)V") - DECLARE_JNI_CLASS_WITH_BYTECODE (AndroidMediaControllerCallback, "com/rmsl/juce/MediaControllerCallback", 21, MediaSessionByteCode, sizeof (MediaSessionByteCode)) + DECLARE_JNI_CLASS_WITH_BYTECODE (AndroidMediaControllerCallback, "com/rmsl/juce/MediaControllerCallback", 21, MediaSessionByteCode) #undef JNI_CLASS_MEMBERS LocalRef createControllerCallbacks() @@ -774,32 +774,24 @@ private: //============================================================================== // MediaSessionController callbacks - static void audioInfoChanged (JNIEnv*, jobject, jlong host, [[maybe_unused]] jobject playbackInfo) + static void audioInfoChanged (JNIEnv*, [[maybe_unused]] Controller& t, [[maybe_unused]] jobject playbackInfo) { - if (auto* myself = reinterpret_cast (host)) - { - JUCE_VIDEO_LOG ("MediaSessionController::audioInfoChanged()"); - } + JUCE_VIDEO_LOG ("MediaSessionController::audioInfoChanged()"); } - static void metadataChanged (JNIEnv*, jobject, jlong host, [[maybe_unused]] jobject metadata) + static void metadataChanged (JNIEnv*, [[maybe_unused]] Controller&, [[maybe_unused]] jobject metadata) { - if (auto* myself = reinterpret_cast (host)) - { - JUCE_VIDEO_LOG ("MediaSessionController::metadataChanged()"); - } + JUCE_VIDEO_LOG ("MediaSessionController::metadataChanged()"); } - static void playbackStateChanged (JNIEnv*, jobject, jlong host, jobject state) + static void playbackStateChanged (JNIEnv*, Controller& t, [[maybe_unused]] jobject state) { - if (auto* myself = reinterpret_cast (host)) - myself->stateChanged (state); + t.stateChanged (state); } - static void sessionDestroyed (JNIEnv*, jobject, jlong host) + static void sessionDestroyed (JNIEnv*, [[maybe_unused]] Controller& t) { - if (auto* myself = reinterpret_cast (host)) - JUCE_VIDEO_LOG ("MediaSessionController::sessionDestroyed()"); + JUCE_VIDEO_LOG ("MediaSessionController::sessionDestroyed()"); } }; @@ -1279,11 +1271,11 @@ private: //============================================================================== #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ METHOD (constructor, "", "(J)V") \ - CALLBACK (pauseCallback, "mediaSessionPause", "(J)V") \ - CALLBACK (playCallback, "mediaSessionPlay", "(J)V") \ - CALLBACK (playFromMediaIdCallback, "mediaSessionPlayFromMediaId", "(JLjava/lang/String;Landroid/os/Bundle;)V") \ - CALLBACK (seekToCallback, "mediaSessionSeekTo", "(JJ)V") \ - CALLBACK (stopCallback, "mediaSessionStop", "(J)V") + CALLBACK (generatedCallback<&MediaSession::pauseCallback>, "mediaSessionPause", "(J)V") \ + CALLBACK (generatedCallback<&MediaSession::playCallback>, "mediaSessionPlay", "(J)V") \ + CALLBACK (generatedCallback<&MediaSession::playFromMediaIdCallback>, "mediaSessionPlayFromMediaId", "(JLjava/lang/String;Landroid/os/Bundle;)V") \ + CALLBACK (generatedCallback<&MediaSession::seekToCallback>, "mediaSessionSeekTo", "(JJ)V") \ + CALLBACK (generatedCallback<&MediaSession::stopCallback>, "mediaSessionStop", "(J)V") DECLARE_JNI_CLASS_WITH_MIN_SDK (AndroidMediaSessionCallback, "com/rmsl/juce/MediaSessionCallback", 21) #undef JNI_CLASS_MEMBERS @@ -1297,78 +1289,62 @@ private: //============================================================================== // MediaSession callbacks - static void pauseCallback (JNIEnv*, jobject, jlong host) + static void pauseCallback (JNIEnv*, MediaSession& t) { - if (auto* myself = reinterpret_cast (host)) - { - JUCE_VIDEO_LOG ("MediaSession::pauseCallback()"); - myself->player.pause(); - myself->updatePlaybackState(); - - myself->abandonAudioFocus(); - } + JUCE_VIDEO_LOG ("MediaSession::pauseCallback()"); + t.player.pause(); + t.updatePlaybackState(); + t.abandonAudioFocus(); } - static void playCallback (JNIEnv*, jobject, jlong host) + static void playCallback (JNIEnv* env, MediaSession& t) { - if (auto* myself = reinterpret_cast (host)) - { - JUCE_VIDEO_LOG ("MediaSession::playCallback()"); + JUCE_VIDEO_LOG ("MediaSession::playCallback()"); - myself->requestAudioFocus(); + t.requestAudioFocus(); - if (! myself->hasAudioFocus) - { - myself->errorOccurred ("Application has been denied audio focus. Try again later."); - return; - } + if (! t.hasAudioFocus) + { + t.errorOccurred ("Application has been denied audio focus. Try again later."); + return; + } - getEnv()->CallVoidMethod (myself->nativeMediaSession, AndroidMediaSession.setActive, true); + env->CallVoidMethod (t.nativeMediaSession, AndroidMediaSession.setActive, true); - myself->player.play(); - myself->setSpeed (myself->playSpeedMult); - myself->updatePlaybackState(); - } + t.player.play(); + t.setSpeed (t.playSpeedMult); + t.updatePlaybackState(); } - static void playFromMediaIdCallback (JNIEnv* env, jobject, jlong host, jstring mediaId, jobject extras) + static void playFromMediaIdCallback (JNIEnv* env, MediaSession& t, jstring mediaId, jobject extras) { - if (auto* myself = reinterpret_cast (host)) - { - JUCE_VIDEO_LOG ("MediaSession::playFromMediaIdCallback()"); + JUCE_VIDEO_LOG ("MediaSession::playFromMediaIdCallback()"); - myself->player.load (LocalRef ((jstring) env->NewLocalRef(mediaId)), LocalRef (env->NewLocalRef(extras))); - myself->updatePlaybackState(); - } + t.player.load (LocalRef ((jstring) env->NewLocalRef (mediaId)), LocalRef (env->NewLocalRef (extras))); + t.updatePlaybackState(); } - static void seekToCallback (JNIEnv* /*env*/, jobject, jlong host, jlong pos) + static void seekToCallback (JNIEnv*, MediaSession& t, jlong pos) { - if (auto* myself = reinterpret_cast (host)) - { - JUCE_VIDEO_LOG ("MediaSession::seekToCallback()"); + JUCE_VIDEO_LOG ("MediaSession::seekToCallback()"); - myself->pendingSeekRequest = true; - myself->player.setPlayPosition ((jint) pos); - myself->updatePlaybackState(); - } + t.pendingSeekRequest = true; + t.player.setPlayPosition ((jint) pos); + t.updatePlaybackState(); } - static void stopCallback(JNIEnv* env, jobject, jlong host) + static void stopCallback (JNIEnv* env, MediaSession& t) { - if (auto* myself = reinterpret_cast (host)) - { - JUCE_VIDEO_LOG ("MediaSession::stopCallback()"); + JUCE_VIDEO_LOG ("MediaSession::stopCallback()"); - env->CallVoidMethod (myself->nativeMediaSession, AndroidMediaSession.setActive, false); + env->CallVoidMethod (t.nativeMediaSession, AndroidMediaSession.setActive, false); - myself->player.closeVideo(); - myself->updatePlaybackState(); + t.player.closeVideo(); + t.updatePlaybackState(); - myself->abandonAudioFocus(); + t.abandonAudioFocus(); - myself->owner.closeVideoFinished(); - } + t.owner.closeVideoFinished(); } //============================================================================== @@ -1673,7 +1649,7 @@ private: #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \ METHOD (constructor, "", "(Landroid/app/Activity;J)V") \ METHOD (setEnabled, "setEnabled", "(Z)V") \ - CALLBACK (systemVolumeChangedCallback, "mediaSessionSystemVolumeChanged", "(J)V") + CALLBACK (generatedCallback<&SystemVolumeListener::systemVolumeChanged>, "mediaSessionSystemVolumeChanged", "(J)V") DECLARE_JNI_CLASS_WITH_MIN_SDK (SystemVolumeObserver, "com/rmsl/juce/SystemVolumeObserver", 21) #undef JNI_CLASS_MEMBERS @@ -1693,14 +1669,14 @@ private: // Send first notification instantly to ensure sync. if (shouldBeEnabled) - systemVolumeChanged(); + systemVolumeChanged (getEnv(), *this); } private: //============================================================================== - void systemVolumeChanged() + static void systemVolumeChanged (JNIEnv*, SystemVolumeListener& t) { - MessageManager::callAsync ([weakThis = WeakReference { this }]() mutable + MessageManager::callAsync ([weakThis = WeakReference { &t }] { if (weakThis == nullptr) return; @@ -1711,13 +1687,6 @@ private: } - //============================================================================== - static void systemVolumeChangedCallback (JNIEnv*, jobject, jlong host) - { - if (auto* myself = reinterpret_cast (host)) - myself->systemVolumeChanged(); - } - JUCE_DECLARE_WEAK_REFERENCEABLE (SystemVolumeListener) }; @@ -1829,8 +1798,3 @@ private: //============================================================================== constexpr VideoComponent::Pimpl::MediaSession::Player::StateInfo VideoComponent::Pimpl::MediaSession::Player::stateInfos[]; - -//============================================================================== -VideoComponent::Pimpl::MediaSession::AndroidMediaSessionCallback_Class VideoComponent::Pimpl::MediaSession::AndroidMediaSessionCallback; -VideoComponent::Pimpl::MediaSession::Controller::AndroidMediaControllerCallback_Class VideoComponent::Pimpl::MediaSession::Controller::AndroidMediaControllerCallback; -VideoComponent::Pimpl::SystemVolumeListener::SystemVolumeObserver_Class VideoComponent::Pimpl::SystemVolumeListener::SystemVolumeObserver;