The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

387 lines
12KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-10 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. package com.juce;
  19. import android.app.Activity;
  20. import android.app.AlertDialog;
  21. import android.content.DialogInterface;
  22. import android.os.Bundle;
  23. import android.content.Context;
  24. import android.view.ViewGroup;
  25. import android.graphics.Paint;
  26. import android.graphics.Canvas;
  27. import android.graphics.Path;
  28. import android.graphics.Bitmap;
  29. import android.graphics.Matrix;
  30. import android.graphics.RectF;
  31. import android.graphics.Rect;
  32. import android.text.ClipboardManager;
  33. import com.juce.ComponentPeerView;
  34. import java.io.BufferedInputStream;
  35. import java.io.IOException;
  36. import java.io.InputStream;
  37. import java.io.OutputStream;
  38. import java.net.URL;
  39. import java.net.HttpURLConnection;
  40. //==============================================================================
  41. public final class JuceAppActivity extends Activity
  42. {
  43. //==============================================================================
  44. static
  45. {
  46. System.loadLibrary ("juce_jni");
  47. }
  48. @Override
  49. public final void onCreate (Bundle savedInstanceState)
  50. {
  51. super.onCreate (savedInstanceState);
  52. viewHolder = new ViewHolder (this);
  53. setContentView (viewHolder);
  54. }
  55. @Override
  56. protected final void onDestroy()
  57. {
  58. quitApp();
  59. super.onDestroy();
  60. }
  61. private void callAppLauncher()
  62. {
  63. launchApp (getApplicationInfo().publicSourceDir,
  64. getApplicationInfo().dataDir);
  65. }
  66. //==============================================================================
  67. public native void launchApp (String appFile, String appDataDir);
  68. public native void quitApp();
  69. public native void setScreenSize (int screenWidth, int screenHeight);
  70. //==============================================================================
  71. public static final void printToConsole (String s)
  72. {
  73. android.util.Log.i ("Juce", s);
  74. }
  75. //==============================================================================
  76. public native void deliverMessage (long value);
  77. private android.os.Handler messageHandler = new android.os.Handler();
  78. public final void postMessage (long value)
  79. {
  80. messageHandler.post (new MessageCallback (value));
  81. }
  82. final class MessageCallback implements Runnable
  83. {
  84. public MessageCallback (long value_)
  85. {
  86. value = value_;
  87. }
  88. public final void run()
  89. {
  90. deliverMessage (value);
  91. }
  92. private long value;
  93. }
  94. //==============================================================================
  95. private ViewHolder viewHolder;
  96. public final ComponentPeerView createNewView (boolean opaque)
  97. {
  98. ComponentPeerView v = new ComponentPeerView (this, opaque);
  99. viewHolder.addView (v);
  100. return v;
  101. }
  102. public final void deleteView (ComponentPeerView view)
  103. {
  104. viewHolder.removeView (view);
  105. }
  106. final class ViewHolder extends ViewGroup
  107. {
  108. public ViewHolder (Context context)
  109. {
  110. super (context);
  111. setDescendantFocusability (ViewGroup.FOCUS_AFTER_DESCENDANTS);
  112. setFocusable (false);
  113. }
  114. protected final void onLayout (boolean changed, int left, int top, int right, int bottom)
  115. {
  116. setScreenSize (getWidth(), getHeight());
  117. if (isFirstResize)
  118. {
  119. isFirstResize = false;
  120. callAppLauncher();
  121. }
  122. }
  123. private boolean isFirstResize = true;
  124. }
  125. public final void excludeClipRegion (android.graphics.Canvas canvas, float left, float top, float right, float bottom)
  126. {
  127. canvas.clipRect (left, top, right, bottom, android.graphics.Region.Op.DIFFERENCE);
  128. }
  129. //==============================================================================
  130. public final String getClipboardContent()
  131. {
  132. ClipboardManager clipboard = (ClipboardManager) getSystemService (CLIPBOARD_SERVICE);
  133. return clipboard.getText().toString();
  134. }
  135. public final void setClipboardContent (String newText)
  136. {
  137. ClipboardManager clipboard = (ClipboardManager) getSystemService (CLIPBOARD_SERVICE);
  138. clipboard.setText (newText);
  139. }
  140. //==============================================================================
  141. public final void showMessageBox (String title, String message, final long callback)
  142. {
  143. AlertDialog.Builder builder = new AlertDialog.Builder (this);
  144. builder.setTitle (title)
  145. .setMessage (message)
  146. .setCancelable (true)
  147. .setPositiveButton ("OK", new DialogInterface.OnClickListener()
  148. {
  149. public void onClick (DialogInterface dialog, int id)
  150. {
  151. dialog.cancel();
  152. JuceAppActivity.this.alertDismissed (callback, 0);
  153. }
  154. });
  155. builder.create().show();
  156. }
  157. public final void showOkCancelBox (String title, String message, final long callback)
  158. {
  159. AlertDialog.Builder builder = new AlertDialog.Builder (this);
  160. builder.setTitle (title)
  161. .setMessage (message)
  162. .setCancelable (true)
  163. .setPositiveButton ("OK", new DialogInterface.OnClickListener()
  164. {
  165. public void onClick (DialogInterface dialog, int id)
  166. {
  167. dialog.cancel();
  168. JuceAppActivity.this.alertDismissed (callback, 1);
  169. }
  170. })
  171. .setNegativeButton ("Cancel", new DialogInterface.OnClickListener()
  172. {
  173. public void onClick (DialogInterface dialog, int id)
  174. {
  175. dialog.cancel();
  176. JuceAppActivity.this.alertDismissed (callback, 0);
  177. }
  178. });
  179. builder.create().show();
  180. }
  181. public final void showYesNoCancelBox (String title, String message, final long callback)
  182. {
  183. AlertDialog.Builder builder = new AlertDialog.Builder (this);
  184. builder.setTitle (title)
  185. .setMessage (message)
  186. .setCancelable (true)
  187. .setPositiveButton ("Yes", new DialogInterface.OnClickListener()
  188. {
  189. public void onClick (DialogInterface dialog, int id)
  190. {
  191. dialog.cancel();
  192. JuceAppActivity.this.alertDismissed (callback, 1);
  193. }
  194. })
  195. .setNegativeButton ("No", new DialogInterface.OnClickListener()
  196. {
  197. public void onClick (DialogInterface dialog, int id)
  198. {
  199. dialog.cancel();
  200. JuceAppActivity.this.alertDismissed (callback, 2);
  201. }
  202. })
  203. .setNeutralButton ("Cancel", new DialogInterface.OnClickListener()
  204. {
  205. public void onClick (DialogInterface dialog, int id)
  206. {
  207. dialog.cancel();
  208. JuceAppActivity.this.alertDismissed (callback, 0);
  209. }
  210. });
  211. builder.create().show();
  212. }
  213. public native void alertDismissed (long callback, int id);
  214. //==============================================================================
  215. public final int[] renderGlyph (char glyph, Paint paint, Matrix matrix, Rect bounds)
  216. {
  217. Path p = new Path();
  218. paint.getTextPath (String.valueOf (glyph), 0, 1, 0.0f, 0.0f, p);
  219. RectF boundsF = new RectF();
  220. p.computeBounds (boundsF, true);
  221. matrix.mapRect (boundsF);
  222. boundsF.roundOut (bounds);
  223. bounds.left--;
  224. bounds.right++;
  225. final int w = bounds.width();
  226. final int h = bounds.height();
  227. Bitmap bm = Bitmap.createBitmap (w, h, Bitmap.Config.ARGB_8888);
  228. Canvas c = new Canvas (bm);
  229. matrix.postTranslate (-bounds.left, -bounds.top);
  230. c.setMatrix (matrix);
  231. c.drawPath (p, paint);
  232. int sizeNeeded = w * h;
  233. if (cachedRenderArray.length < sizeNeeded)
  234. cachedRenderArray = new int [sizeNeeded];
  235. bm.getPixels (cachedRenderArray, 0, w, 0, 0, w, h);
  236. bm.recycle();
  237. return cachedRenderArray;
  238. }
  239. private int[] cachedRenderArray = new int [256];
  240. //==============================================================================
  241. public static class HTTPStream
  242. {
  243. public HTTPStream (HttpURLConnection connection_) throws IOException
  244. {
  245. connection = connection_;
  246. inputStream = new BufferedInputStream (connection.getInputStream());
  247. }
  248. public final void release()
  249. {
  250. try
  251. {
  252. inputStream.close();
  253. }
  254. catch (IOException e)
  255. {}
  256. connection.disconnect();
  257. }
  258. public final int read (byte[] buffer, int numBytes)
  259. {
  260. int num = 0;
  261. try
  262. {
  263. num = inputStream.read (buffer, 0, numBytes);
  264. }
  265. catch (IOException e)
  266. {}
  267. if (num > 0)
  268. position += num;
  269. return num;
  270. }
  271. public final long getPosition()
  272. {
  273. return position;
  274. }
  275. public final long getTotalLength()
  276. {
  277. return -1;
  278. }
  279. public final boolean isExhausted()
  280. {
  281. return false;
  282. }
  283. public final boolean setPosition (long newPos)
  284. {
  285. return false;
  286. }
  287. private HttpURLConnection connection;
  288. private InputStream inputStream;
  289. private long position;
  290. }
  291. public static final HTTPStream createHTTPStream (String address, boolean isPost, byte[] postData,
  292. String headers, int timeOutMs, java.lang.StringBuffer responseHeaders)
  293. {
  294. try
  295. {
  296. HttpURLConnection connection = (HttpURLConnection) (new URL (address).openConnection());
  297. if (connection != null)
  298. {
  299. try
  300. {
  301. if (isPost)
  302. {
  303. connection.setConnectTimeout (timeOutMs);
  304. connection.setDoOutput (true);
  305. connection.setChunkedStreamingMode (0);
  306. OutputStream out = connection.getOutputStream();
  307. out.write (postData);
  308. out.flush();
  309. }
  310. return new HTTPStream (connection);
  311. }
  312. catch (Throwable e)
  313. {
  314. connection.disconnect();
  315. }
  316. }
  317. }
  318. catch (Throwable e)
  319. {}
  320. return null;
  321. }
  322. }