openshot-audio  0.1.2
juce_android_JNIHelpers.h
Go to the documentation of this file.
1 /*
2  ==============================================================================
3 
4  This file is part of the juce_core module of the JUCE library.
5  Copyright (c) 2015 - ROLI Ltd.
6 
7  Permission to use, copy, modify, and/or distribute this software for any purpose with
8  or without fee is hereby granted, provided that the above copyright notice and this
9  permission notice appear in all copies.
10 
11  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
12  TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
13  NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
15  IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16  CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 
18  ------------------------------------------------------------------------------
19 
20  NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
21  All other JUCE modules are covered by a dual GPL/commercial license, so if you are
22  using any other modules, be sure to check that you also comply with their license.
23 
24  For more details, visit www.juce.com
25 
26  ==============================================================================
27 */
28 
29 #ifndef JUCE_ANDROID_JNIHELPERS_H_INCLUDED
30 #define JUCE_ANDROID_JNIHELPERS_H_INCLUDED
31 
32 #if ! (defined (JUCE_ANDROID_ACTIVITY_CLASSNAME) && defined (JUCE_ANDROID_ACTIVITY_CLASSPATH))
33  #error "The JUCE_ANDROID_ACTIVITY_CLASSNAME and JUCE_ANDROID_ACTIVITY_CLASSPATH macros must be set!"
34 #endif
35 
36 //==============================================================================
37 extern JNIEnv* getEnv() noexcept;
38 
39 //==============================================================================
40 class GlobalRef
41 {
42 public:
43  inline GlobalRef() noexcept : obj (0) {}
44  inline explicit GlobalRef (jobject o) : obj (retain (o)) {}
45  inline GlobalRef (const GlobalRef& other) : obj (retain (other.obj)) {}
46  ~GlobalRef() { clear(); }
47 
48  inline void clear()
49  {
50  if (obj != 0)
51  {
52  getEnv()->DeleteGlobalRef (obj);
53  obj = 0;
54  }
55  }
56 
57  inline GlobalRef& operator= (const GlobalRef& other)
58  {
59  jobject newObj = retain (other.obj);
60  clear();
61  obj = newObj;
62  return *this;
63  }
64 
65  //==============================================================================
66  inline operator jobject() const noexcept { return obj; }
67  inline jobject get() const noexcept { return obj; }
68 
69  //==============================================================================
70  #define DECLARE_CALL_TYPE_METHOD(returnType, typeName) \
71  returnType call##typeName##Method (jmethodID methodID, ... ) const \
72  { \
73  va_list args; \
74  va_start (args, methodID); \
75  returnType result = getEnv()->Call##typeName##MethodV (obj, methodID, args); \
76  va_end (args); \
77  return result; \
78  }
79 
80  DECLARE_CALL_TYPE_METHOD (jobject, Object)
81  DECLARE_CALL_TYPE_METHOD (jboolean, Boolean)
83  DECLARE_CALL_TYPE_METHOD (jchar, Char)
84  DECLARE_CALL_TYPE_METHOD (jshort, Short)
85  DECLARE_CALL_TYPE_METHOD (jint, Int)
86  DECLARE_CALL_TYPE_METHOD (jlong, Long)
87  DECLARE_CALL_TYPE_METHOD (jfloat, Float)
88  DECLARE_CALL_TYPE_METHOD (jdouble, Double)
89  #undef DECLARE_CALL_TYPE_METHOD
90 
91  void callVoidMethod (jmethodID methodID, ... ) const
92  {
93  va_list args;
94  va_start (args, methodID);
95  getEnv()->CallVoidMethodV (obj, methodID, args);
96  va_end (args);
97  }
98 
99 private:
100  //==============================================================================
101  jobject obj;
102 
103  static inline jobject retain (jobject obj)
104  {
105  return obj == 0 ? 0 : getEnv()->NewGlobalRef (obj);
106  }
107 };
108 
109 //==============================================================================
110 template <typename JavaType>
111 class LocalRef
112 {
113 public:
114  explicit inline LocalRef (JavaType o) noexcept : obj (o) {}
115  inline LocalRef (const LocalRef& other) noexcept : obj (retain (other.obj)) {}
116  ~LocalRef() { clear(); }
117 
118  void clear()
119  {
120  if (obj != 0)
121  getEnv()->DeleteLocalRef (obj);
122  }
123 
124  LocalRef& operator= (const LocalRef& other)
125  {
126  jobject newObj = retain (other.obj);
127  clear();
128  obj = newObj;
129  return *this;
130  }
131 
132  inline operator JavaType() const noexcept { return obj; }
133  inline JavaType get() const noexcept { return obj; }
134 
135 private:
136  JavaType obj;
137 
138  static JavaType retain (JavaType obj)
139  {
140  return obj == 0 ? 0 : (JavaType) getEnv()->NewLocalRef (obj);
141  }
142 };
143 
144 //==============================================================================
145 namespace
146 {
147  String juceString (JNIEnv* env, jstring s)
148  {
149  const char* const utf8 = env->GetStringUTFChars (s, nullptr);
150  CharPointer_UTF8 utf8CP (utf8);
151  const String result (utf8CP);
152  env->ReleaseStringUTFChars (s, utf8);
153  return result;
154  }
155 
156  String juceString (jstring s)
157  {
158  return juceString (getEnv(), s);
159  }
160 
161  LocalRef<jstring> javaString (const String& s)
162  {
163  return LocalRef<jstring> (getEnv()->NewStringUTF (s.toUTF8()));
164  }
165 
166  LocalRef<jstring> javaStringFromChar (const juce_wchar c)
167  {
168  char utf8[8] = { 0 };
169  CharPointer_UTF8 (utf8).write (c);
170  return LocalRef<jstring> (getEnv()->NewStringUTF (utf8));
171  }
172 }
173 
174 //==============================================================================
176 {
177 public:
178  explicit JNIClassBase (const char* classPath);
179  virtual ~JNIClassBase();
180 
181  inline operator jclass() const noexcept { return classRef; }
182 
183  static void initialiseAllClasses (JNIEnv*);
184  static void releaseAllClasses (JNIEnv*);
185 
186 protected:
187  virtual void initialiseFields (JNIEnv*) = 0;
188 
189  jmethodID resolveMethod (JNIEnv*, const char* methodName, const char* params);
190  jmethodID resolveStaticMethod (JNIEnv*, const char* methodName, const char* params);
191  jfieldID resolveField (JNIEnv*, const char* fieldName, const char* signature);
192  jfieldID resolveStaticField (JNIEnv*, const char* fieldName, const char* signature);
193 
194 private:
195  const char* const classPath;
196  jclass classRef;
197 
198  static Array<JNIClassBase*>& getClasses();
199  void initialise (JNIEnv*);
200  void release (JNIEnv*);
201 
203 };
204 
205 //==============================================================================
206 #define CREATE_JNI_METHOD(methodID, stringName, params) methodID = resolveMethod (env, stringName, params);
207 #define CREATE_JNI_STATICMETHOD(methodID, stringName, params) methodID = resolveStaticMethod (env, stringName, params);
208 #define CREATE_JNI_FIELD(fieldID, stringName, signature) fieldID = resolveField (env, stringName, signature);
209 #define CREATE_JNI_STATICFIELD(fieldID, stringName, signature) fieldID = resolveStaticField (env, stringName, signature);
210 #define DECLARE_JNI_METHOD(methodID, stringName, params) jmethodID methodID;
211 #define DECLARE_JNI_FIELD(fieldID, stringName, signature) jfieldID fieldID;
212 
213 #define DECLARE_JNI_CLASS(CppClassName, javaPath) \
214  class CppClassName ## _Class : public JNIClassBase \
215  { \
216  public: \
217  CppClassName ## _Class() : JNIClassBase (javaPath) {} \
218  \
219  void initialiseFields (JNIEnv* env) \
220  { \
221  JNI_CLASS_MEMBERS (CREATE_JNI_METHOD, CREATE_JNI_STATICMETHOD, CREATE_JNI_FIELD, CREATE_JNI_STATICFIELD); \
222  } \
223  \
224  JNI_CLASS_MEMBERS (DECLARE_JNI_METHOD, DECLARE_JNI_METHOD, DECLARE_JNI_FIELD, DECLARE_JNI_FIELD); \
225  }; \
226  static CppClassName ## _Class CppClassName;
227 
228 
229 //==============================================================================
230 #if defined (__arm__)
231  #define JUCE_ARM_SOFT_FLOAT_ABI __attribute__ ((pcs("aapcs")))
232 #else
233  #define JUCE_ARM_SOFT_FLOAT_ABI
234 #endif
235 
236 #define JUCE_JNI_CALLBACK(className, methodName, returnType, params) \
237  extern "C" __attribute__ ((visibility("default"))) JUCE_ARM_SOFT_FLOAT_ABI returnType JUCE_JOIN_MACRO (JUCE_JOIN_MACRO (Java_, className), _ ## methodName) params
238 
239 //==============================================================================
241 {
242 public:
243  AndroidSystem();
244 
245  void initialise (JNIEnv*, jobject activity, jstring appFile, jstring appDataDir);
246  void shutdown (JNIEnv*);
247 
248  //==============================================================================
249  GlobalRef activity;
250  String appFile, appDataDir;
251  int screenWidth, screenHeight, dpi;
252 };
253 
254 extern AndroidSystem android;
255 
256 //==============================================================================
258 {
259 public:
261  : jvm (nullptr)
262  {
263  zeromem (threads, sizeof (threads));
264  zeromem (envs, sizeof (envs));
265  }
266 
267  void initialise (JNIEnv* env)
268  {
269  // NB: the DLL can be left loaded by the JVM, so the same static
270  // objects can end up being reused by subsequent runs of the app
271  zeromem (threads, sizeof (threads));
272  zeromem (envs, sizeof (envs));
273 
274  env->GetJavaVM (&jvm);
275  addEnv (env);
276  }
277 
278  JNIEnv* attach() noexcept
279  {
280  if (android.activity != nullptr)
281  {
282  if (JNIEnv* env = attachToCurrentThread())
283  {
284  SpinLock::ScopedLockType sl (addRemoveLock);
285  return addEnv (env);
286  }
287 
288  jassertfalse;
289  }
290 
291  return nullptr;
292  }
293 
295  {
296  if (android.activity != nullptr)
297  {
298  jvm->DetachCurrentThread();
299  removeCurrentThreadFromCache();
300  }
301  }
302 
304  {
305  const pthread_t thisThread = pthread_self();
306 
307  SpinLock::ScopedLockType sl (addRemoveLock);
308 
309  for (int i = 0; i < maxThreads; ++i)
310  {
311  if (threads[i] == thisThread)
312  {
313  threads[i] = 0;
314  envs[i] = nullptr;
315  }
316  }
317  }
318 
320  {
321  if (JNIEnv* env = get())
322  return env;
323 
324  SpinLock::ScopedLockType sl (addRemoveLock);
325 
326  if (JNIEnv* env = get())
327  return env;
328 
329  if (JNIEnv* env = attachToCurrentThread())
330  return addEnv (env);
331 
332  return nullptr;
333  }
334 
335 private:
336  JavaVM* jvm;
337  enum { maxThreads = 32 };
338  pthread_t threads [maxThreads];
339  JNIEnv* envs [maxThreads];
340  SpinLock addRemoveLock;
341 
342  JNIEnv* addEnv (JNIEnv* env) noexcept
343  {
344  const pthread_t thisThread = pthread_self();
345 
346  for (int i = 0; i < maxThreads; ++i)
347  {
348  if (threads[i] == 0)
349  {
350  envs[i] = env;
351  threads[i] = thisThread;
352  return env;
353  }
354  }
355 
356  jassertfalse; // too many threads!
357  return nullptr;
358  }
359 
360  JNIEnv* get() const noexcept
361  {
362  const pthread_t thisThread = pthread_self();
363 
364  for (int i = 0; i < maxThreads; ++i)
365  if (threads[i] == thisThread)
366  return envs[i];
367 
368  return nullptr;
369  }
370 
371  JNIEnv* attachToCurrentThread()
372  {
373  JNIEnv* env = nullptr;
374  jvm->AttachCurrentThread (&env, nullptr);
375  return env;
376  }
377 };
378 
380 
382 {
383  AndroidThreadScope() { threadLocalJNIEnvHolder.attach(); }
384  ~AndroidThreadScope() { threadLocalJNIEnvHolder.detach(); }
385 };
386 
387 //==============================================================================
388 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
389  METHOD (createNewView, "createNewView", "(ZJ)L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$ComponentPeerView;") \
390  METHOD (deleteView, "deleteView", "(L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$ComponentPeerView;)V") \
391  METHOD (deleteOpenGLView, "deleteOpenGLView", "(L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$OpenGLView;)V") \
392  METHOD (postMessage, "postMessage", "(J)V") \
393  METHOD (finish, "finish", "()V") \
394  METHOD (getClipboardContent, "getClipboardContent", "()Ljava/lang/String;") \
395  METHOD (setClipboardContent, "setClipboardContent", "(Ljava/lang/String;)V") \
396  METHOD (excludeClipRegion, "excludeClipRegion", "(Landroid/graphics/Canvas;FFFF)V") \
397  METHOD (renderGlyph, "renderGlyph", "(CLandroid/graphics/Paint;Landroid/graphics/Matrix;Landroid/graphics/Rect;)[I") \
398  STATICMETHOD (createHTTPStream, "createHTTPStream", "(Ljava/lang/String;Z[BLjava/lang/String;I[ILjava/lang/StringBuffer;I)L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$HTTPStream;") \
399  METHOD (launchURL, "launchURL", "(Ljava/lang/String;)V") \
400  METHOD (showMessageBox, "showMessageBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \
401  METHOD (showOkCancelBox, "showOkCancelBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \
402  METHOD (showYesNoCancelBox, "showYesNoCancelBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \
403  STATICMETHOD (getLocaleValue, "getLocaleValue", "(Z)Ljava/lang/String;") \
404  METHOD (scanFile, "scanFile", "(Ljava/lang/String;)V") \
405  METHOD (getTypeFaceFromAsset, "getTypeFaceFromAsset", "(Ljava/lang/String;)Landroid/graphics/Typeface;") \
406  METHOD (getTypeFaceFromByteArray,"getTypeFaceFromByteArray","([B)Landroid/graphics/Typeface;")
407 
408 DECLARE_JNI_CLASS (JuceAppActivity, JUCE_ANDROID_ACTIVITY_CLASSPATH);
409 #undef JNI_CLASS_MEMBERS
410 
411 //==============================================================================
412 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
413  METHOD (constructor, "<init>", "(I)V") \
414  METHOD (setColor, "setColor", "(I)V") \
415  METHOD (setAlpha, "setAlpha", "(I)V") \
416  METHOD (setTypeface, "setTypeface", "(Landroid/graphics/Typeface;)Landroid/graphics/Typeface;") \
417  METHOD (ascent, "ascent", "()F") \
418  METHOD (descent, "descent", "()F") \
419  METHOD (setTextSize, "setTextSize", "(F)V") \
420  METHOD (getTextWidths, "getTextWidths", "(Ljava/lang/String;[F)I") \
421  METHOD (setTextScaleX, "setTextScaleX", "(F)V") \
422  METHOD (getTextPath, "getTextPath", "(Ljava/lang/String;IIFFLandroid/graphics/Path;)V") \
423  METHOD (setShader, "setShader", "(Landroid/graphics/Shader;)Landroid/graphics/Shader;") \
424 
425 DECLARE_JNI_CLASS (Paint, "android/graphics/Paint");
426 #undef JNI_CLASS_MEMBERS
427 
428 //==============================================================================
429 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
430  METHOD (constructor, "<init>", "()V") \
431  METHOD (setValues, "setValues", "([F)V") \
432 
433 DECLARE_JNI_CLASS (Matrix, "android/graphics/Matrix");
434 #undef JNI_CLASS_MEMBERS
435 
436 //==============================================================================
437 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
438  METHOD (constructor, "<init>", "(IIII)V") \
439  FIELD (left, "left", "I") \
440  FIELD (right, "right", "I") \
441  FIELD (top, "top", "I") \
442  FIELD (bottom, "bottom", "I") \
443 
444 DECLARE_JNI_CLASS (RectClass, "android/graphics/Rect");
445 #undef JNI_CLASS_MEMBERS
446 
447 #endif // JUCE_ANDROID_JNIHELPERS_H_INCLUDED
GlobalRef(const GlobalRef &other)
Definition: juce_android_JNIHelpers.h:45
void removeCurrentThreadFromCache()
Definition: juce_android_JNIHelpers.h:303
#define DECLARE_JNI_CLASS(CppClassName, javaPath)
Definition: juce_android_JNIHelpers.h:213
unsigned char Byte
Definition: zconf.h:274
ThreadLocalJNIEnvHolder() noexcept
Definition: juce_android_JNIHelpers.h:260
#define noexcept
Definition: juce_CompilerSupport.h:141
LocalRef(const LocalRef &other) noexcept
Definition: juce_android_JNIHelpers.h:115
String appFile
Definition: juce_android_JNIHelpers.h:250
Definition: juce_ScopedLock.h:59
void zeromem(void *memory, size_t numBytes) noexcept
Definition: juce_Memory.h:34
Definition: juce_CharPointer_UTF8.h:38
~AndroidThreadScope()
Definition: juce_android_JNIHelpers.h:384
Definition: juce_SpinLock.h:46
#define jassertfalse
Definition: juce_PlatformDefs.h:141
Definition: juce_String.h:43
int screenWidth
Definition: juce_android_JNIHelpers.h:251
void write(const juce_wchar charToWrite) noexcept
Definition: juce_CharPointer_UTF8.h:330
void initialise(JNIEnv *env)
Definition: juce_android_JNIHelpers.h:267
AndroidSystem android
Definition: juce_android_SystemStats.cpp:158
#define const
AndroidThreadScope()
Definition: juce_android_JNIHelpers.h:383
GlobalRef() noexcept
Definition: juce_android_JNIHelpers.h:43
LocalRef & operator=(const LocalRef &other)
Definition: juce_android_JNIHelpers.h:124
JNIEnv * getOrAttach() noexcept
Definition: juce_android_JNIHelpers.h:319
JNIEnv * getEnv() noexcept
Definition: juce_android_SystemStats.cpp:107
void detach() noexcept
Definition: juce_android_JNIHelpers.h:294
Definition: juce_android_JNIHelpers.h:240
#define DECLARE_CALL_TYPE_METHOD(returnType, typeName)
Definition: juce_android_JNIHelpers.h:70
~LocalRef()
Definition: juce_android_JNIHelpers.h:116
ThreadLocalJNIEnvHolder threadLocalJNIEnvHolder
Definition: juce_android_SystemStats.cpp:101
Definition: juce_Array.h:60
Definition: juce_android_JNIHelpers.h:111
#define JUCE_DECLARE_NON_COPYABLE(className)
Definition: juce_PlatformDefs.h:191
Definition: juce_android_JNIHelpers.h:381
Definition: juce_android_JNIHelpers.h:40
Definition: juce_android_JNIHelpers.h:257
LocalRef(JavaType o) noexcept
Definition: juce_android_JNIHelpers.h:114
GlobalRef(jobject o)
Definition: juce_android_JNIHelpers.h:44
~GlobalRef()
Definition: juce_android_JNIHelpers.h:46
void clear()
Definition: juce_android_JNIHelpers.h:118
void callVoidMethod(jmethodID methodID,...) const
Definition: juce_android_JNIHelpers.h:91
Definition: juce_android_JNIHelpers.h:175
void clear()
Definition: juce_android_JNIHelpers.h:48
wchar_t juce_wchar
Definition: juce_CharacterFunctions.h:49
CharPointer_UTF8 toUTF8() const
Definition: juce_String.cpp:2057
JNIEnv * attach() noexcept
Definition: juce_android_JNIHelpers.h:278
GlobalRef activity
Definition: juce_android_JNIHelpers.h:249