| @@ -1,58 +1,58 @@ | |||||
| package com.roli.juce; | |||||
| import android.app.DialogFragment; | |||||
| import android.content.Intent; | |||||
| import android.os.Bundle; | |||||
| public class FragmentOverlay extends DialogFragment | |||||
| { | |||||
| @Override | |||||
| public void onCreate (Bundle state) | |||||
| { | |||||
| super.onCreate (state); | |||||
| cppThis = getArguments ().getLong ("cppThis"); | |||||
| if (cppThis != 0) | |||||
| onCreateNative (cppThis, state); | |||||
| } | |||||
| @Override | |||||
| public void onStart () | |||||
| { | |||||
| super.onStart (); | |||||
| if (cppThis != 0) | |||||
| onStartNative (cppThis); | |||||
| } | |||||
| public void onRequestPermissionsResult (int requestCode, | |||||
| String[] permissions, | |||||
| int[] grantResults) | |||||
| { | |||||
| if (cppThis != 0) | |||||
| onRequestPermissionsResultNative (cppThis, requestCode, | |||||
| permissions, grantResults); | |||||
| } | |||||
| @Override | |||||
| public void onActivityResult (int requestCode, int resultCode, Intent data) | |||||
| { | |||||
| if (cppThis != 0) | |||||
| onActivityResultNative (cppThis, requestCode, resultCode, data); | |||||
| } | |||||
| public void close () | |||||
| { | |||||
| cppThis = 0; | |||||
| dismiss (); | |||||
| } | |||||
| //============================================================================== | |||||
| private long cppThis = 0; | |||||
| private native void onActivityResultNative (long myself, int requestCode, int resultCode, Intent data); | |||||
| private native void onCreateNative (long myself, Bundle state); | |||||
| private native void onStartNative (long myself); | |||||
| private native void onRequestPermissionsResultNative (long myself, int requestCode, | |||||
| String[] permissions, int[] grantResults); | |||||
| } | |||||
| package com.roli.juce; | |||||
| import android.app.DialogFragment; | |||||
| import android.content.Intent; | |||||
| import android.os.Bundle; | |||||
| public class FragmentOverlay extends DialogFragment | |||||
| { | |||||
| @Override | |||||
| public void onCreate (Bundle state) | |||||
| { | |||||
| super.onCreate (state); | |||||
| cppThis = getArguments ().getLong ("cppThis"); | |||||
| if (cppThis != 0) | |||||
| onCreateNative (cppThis, state); | |||||
| } | |||||
| @Override | |||||
| public void onStart () | |||||
| { | |||||
| super.onStart (); | |||||
| if (cppThis != 0) | |||||
| onStartNative (cppThis); | |||||
| } | |||||
| public void onRequestPermissionsResult (int requestCode, | |||||
| String[] permissions, | |||||
| int[] grantResults) | |||||
| { | |||||
| if (cppThis != 0) | |||||
| onRequestPermissionsResultNative (cppThis, requestCode, | |||||
| permissions, grantResults); | |||||
| } | |||||
| @Override | |||||
| public void onActivityResult (int requestCode, int resultCode, Intent data) | |||||
| { | |||||
| if (cppThis != 0) | |||||
| onActivityResultNative (cppThis, requestCode, resultCode, data); | |||||
| } | |||||
| public void close () | |||||
| { | |||||
| cppThis = 0; | |||||
| dismiss (); | |||||
| } | |||||
| //============================================================================== | |||||
| private long cppThis = 0; | |||||
| private native void onActivityResultNative (long myself, int requestCode, int resultCode, Intent data); | |||||
| private native void onCreateNative (long myself, Bundle state); | |||||
| private native void onStartNative (long myself); | |||||
| private native void onRequestPermissionsResultNative (long myself, int requestCode, | |||||
| String[] permissions, int[] grantResults); | |||||
| } | |||||
| @@ -1,407 +1,407 @@ | |||||
| package com.roli.juce; | |||||
| import java.lang.Runnable; | |||||
| import java.io.*; | |||||
| import java.net.URL; | |||||
| import java.net.HttpURLConnection; | |||||
| import java.util.concurrent.CancellationException; | |||||
| import java.util.concurrent.Future; | |||||
| import java.util.concurrent.Executors; | |||||
| import java.util.concurrent.ExecutorService; | |||||
| import java.util.concurrent.ExecutionException; | |||||
| import java.util.concurrent.Callable; | |||||
| import java.util.concurrent.locks.ReentrantLock; | |||||
| import java.util.concurrent.atomic.*; | |||||
| public class JuceHTTPStream | |||||
| { | |||||
| public JuceHTTPStream(String address, boolean isPostToUse, byte[] postDataToUse, | |||||
| String headersToUse, int timeOutMsToUse, | |||||
| int[] statusCodeToUse, StringBuffer responseHeadersToUse, | |||||
| int numRedirectsToFollowToUse, String httpRequestCmdToUse) throws IOException | |||||
| { | |||||
| isPost = isPostToUse; | |||||
| postData = postDataToUse; | |||||
| headers = headersToUse; | |||||
| timeOutMs = timeOutMsToUse; | |||||
| statusCode = statusCodeToUse; | |||||
| responseHeaders = responseHeadersToUse; | |||||
| totalLength = -1; | |||||
| numRedirectsToFollow = numRedirectsToFollowToUse; | |||||
| httpRequestCmd = httpRequestCmdToUse; | |||||
| connection = createConnection(address, isPost, postData, headers, timeOutMs, httpRequestCmd); | |||||
| } | |||||
| public static final JuceHTTPStream createHTTPStream(String address, boolean isPost, byte[] postData, | |||||
| String headers, int timeOutMs, int[] statusCode, | |||||
| StringBuffer responseHeaders, int numRedirectsToFollow, | |||||
| String httpRequestCmd) | |||||
| { | |||||
| // timeout parameter of zero for HttpUrlConnection is a blocking connect (negative value for juce::URL) | |||||
| if (timeOutMs < 0) | |||||
| timeOutMs = 0; | |||||
| else if (timeOutMs == 0) | |||||
| timeOutMs = 30000; | |||||
| for (; ; ) | |||||
| { | |||||
| try | |||||
| { | |||||
| JuceHTTPStream httpStream = new JuceHTTPStream(address, isPost, postData, headers, | |||||
| timeOutMs, statusCode, responseHeaders, | |||||
| numRedirectsToFollow, httpRequestCmd); | |||||
| return httpStream; | |||||
| } catch (Throwable e) | |||||
| { | |||||
| } | |||||
| return null; | |||||
| } | |||||
| } | |||||
| private final HttpURLConnection createConnection(String address, boolean isPost, byte[] postData, | |||||
| String headers, int timeOutMs, String httpRequestCmdToUse) throws IOException | |||||
| { | |||||
| HttpURLConnection newConnection = (HttpURLConnection) (new URL(address).openConnection()); | |||||
| try | |||||
| { | |||||
| newConnection.setInstanceFollowRedirects(false); | |||||
| newConnection.setConnectTimeout(timeOutMs); | |||||
| newConnection.setReadTimeout(timeOutMs); | |||||
| // headers - if not empty, this string is appended onto the headers that are used for the request. It must therefore be a valid set of HTML header directives, separated by newlines. | |||||
| // So convert headers string to an array, with an element for each line | |||||
| String headerLines[] = headers.split("\\n"); | |||||
| // Set request headers | |||||
| for (int i = 0; i < headerLines.length; ++i) | |||||
| { | |||||
| int pos = headerLines[i].indexOf(":"); | |||||
| if (pos > 0 && pos < headerLines[i].length()) | |||||
| { | |||||
| String field = headerLines[i].substring(0, pos); | |||||
| String value = headerLines[i].substring(pos + 1); | |||||
| if (value.length() > 0) | |||||
| newConnection.setRequestProperty(field, value); | |||||
| } | |||||
| } | |||||
| newConnection.setRequestMethod(httpRequestCmd); | |||||
| if (isPost) | |||||
| { | |||||
| newConnection.setDoOutput(true); | |||||
| if (postData != null) | |||||
| { | |||||
| OutputStream out = newConnection.getOutputStream(); | |||||
| out.write(postData); | |||||
| out.flush(); | |||||
| } | |||||
| } | |||||
| return newConnection; | |||||
| } catch (Throwable e) | |||||
| { | |||||
| newConnection.disconnect(); | |||||
| throw new IOException("Connection error"); | |||||
| } | |||||
| } | |||||
| private final InputStream getCancellableStream(final boolean isInput) throws ExecutionException | |||||
| { | |||||
| synchronized (createFutureLock) | |||||
| { | |||||
| if (hasBeenCancelled.get()) | |||||
| return null; | |||||
| streamFuture = executor.submit(new Callable<BufferedInputStream>() | |||||
| { | |||||
| @Override | |||||
| public BufferedInputStream call() throws IOException | |||||
| { | |||||
| return new BufferedInputStream(isInput ? connection.getInputStream() | |||||
| : connection.getErrorStream()); | |||||
| } | |||||
| }); | |||||
| } | |||||
| try | |||||
| { | |||||
| return streamFuture.get(); | |||||
| } catch (InterruptedException e) | |||||
| { | |||||
| return null; | |||||
| } catch (CancellationException e) | |||||
| { | |||||
| return null; | |||||
| } | |||||
| } | |||||
| public final boolean connect() | |||||
| { | |||||
| boolean result = false; | |||||
| int numFollowedRedirects = 0; | |||||
| while (true) | |||||
| { | |||||
| result = doConnect(); | |||||
| if (!result) | |||||
| return false; | |||||
| if (++numFollowedRedirects > numRedirectsToFollow) | |||||
| break; | |||||
| int status = statusCode[0]; | |||||
| if (status == 301 || status == 302 || status == 303 || status == 307) | |||||
| { | |||||
| // Assumes only one occurrence of "Location" | |||||
| int pos1 = responseHeaders.indexOf("Location:") + 10; | |||||
| int pos2 = responseHeaders.indexOf("\n", pos1); | |||||
| if (pos2 > pos1) | |||||
| { | |||||
| String currentLocation = connection.getURL().toString(); | |||||
| String newLocation = responseHeaders.substring(pos1, pos2); | |||||
| try | |||||
| { | |||||
| // Handle newLocation whether it's absolute or relative | |||||
| URL baseUrl = new URL(currentLocation); | |||||
| URL newUrl = new URL(baseUrl, newLocation); | |||||
| String transformedNewLocation = newUrl.toString(); | |||||
| if (transformedNewLocation != currentLocation) | |||||
| { | |||||
| // Clear responseHeaders before next iteration | |||||
| responseHeaders.delete(0, responseHeaders.length()); | |||||
| synchronized (createStreamLock) | |||||
| { | |||||
| if (hasBeenCancelled.get()) | |||||
| return false; | |||||
| connection.disconnect(); | |||||
| try | |||||
| { | |||||
| connection = createConnection(transformedNewLocation, isPost, | |||||
| postData, headers, timeOutMs, | |||||
| httpRequestCmd); | |||||
| } catch (Throwable e) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| } | |||||
| } else | |||||
| { | |||||
| break; | |||||
| } | |||||
| } catch (Throwable e) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| } else | |||||
| { | |||||
| break; | |||||
| } | |||||
| } else | |||||
| { | |||||
| break; | |||||
| } | |||||
| } | |||||
| return result; | |||||
| } | |||||
| private final boolean doConnect() | |||||
| { | |||||
| synchronized (createStreamLock) | |||||
| { | |||||
| if (hasBeenCancelled.get()) | |||||
| return false; | |||||
| try | |||||
| { | |||||
| try | |||||
| { | |||||
| inputStream = getCancellableStream(true); | |||||
| } catch (ExecutionException e) | |||||
| { | |||||
| if (connection.getResponseCode() < 400) | |||||
| { | |||||
| statusCode[0] = connection.getResponseCode(); | |||||
| connection.disconnect(); | |||||
| return false; | |||||
| } | |||||
| } finally | |||||
| { | |||||
| statusCode[0] = connection.getResponseCode(); | |||||
| } | |||||
| try | |||||
| { | |||||
| if (statusCode[0] >= 400) | |||||
| inputStream = getCancellableStream(false); | |||||
| else | |||||
| inputStream = getCancellableStream(true); | |||||
| } catch (ExecutionException e) | |||||
| { | |||||
| } | |||||
| for (java.util.Map.Entry<String, java.util.List<String>> entry : connection.getHeaderFields().entrySet()) | |||||
| { | |||||
| if (entry.getKey() != null && entry.getValue() != null) | |||||
| { | |||||
| responseHeaders.append(entry.getKey() + ": " | |||||
| + android.text.TextUtils.join(",", entry.getValue()) + "\n"); | |||||
| if (entry.getKey().compareTo("Content-Length") == 0) | |||||
| totalLength = Integer.decode(entry.getValue().get(0)); | |||||
| } | |||||
| } | |||||
| return true; | |||||
| } catch (IOException e) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| } | |||||
| } | |||||
| static class DisconnectionRunnable implements Runnable | |||||
| { | |||||
| public DisconnectionRunnable(HttpURLConnection theConnection, | |||||
| InputStream theInputStream, | |||||
| ReentrantLock theCreateStreamLock, | |||||
| Object theCreateFutureLock, | |||||
| Future<BufferedInputStream> theStreamFuture) | |||||
| { | |||||
| connectionToDisconnect = theConnection; | |||||
| inputStream = theInputStream; | |||||
| createStreamLock = theCreateStreamLock; | |||||
| createFutureLock = theCreateFutureLock; | |||||
| streamFuture = theStreamFuture; | |||||
| } | |||||
| public void run() | |||||
| { | |||||
| try | |||||
| { | |||||
| if (!createStreamLock.tryLock()) | |||||
| { | |||||
| synchronized (createFutureLock) | |||||
| { | |||||
| if (streamFuture != null) | |||||
| streamFuture.cancel(true); | |||||
| } | |||||
| createStreamLock.lock(); | |||||
| } | |||||
| if (connectionToDisconnect != null) | |||||
| connectionToDisconnect.disconnect(); | |||||
| if (inputStream != null) | |||||
| inputStream.close(); | |||||
| } catch (IOException e) | |||||
| { | |||||
| } finally | |||||
| { | |||||
| createStreamLock.unlock(); | |||||
| } | |||||
| } | |||||
| private HttpURLConnection connectionToDisconnect; | |||||
| private InputStream inputStream; | |||||
| private ReentrantLock createStreamLock; | |||||
| private Object createFutureLock; | |||||
| Future<BufferedInputStream> streamFuture; | |||||
| } | |||||
| public final void release() | |||||
| { | |||||
| DisconnectionRunnable disconnectionRunnable = new DisconnectionRunnable(connection, | |||||
| inputStream, | |||||
| createStreamLock, | |||||
| createFutureLock, | |||||
| streamFuture); | |||||
| synchronized (createStreamLock) | |||||
| { | |||||
| hasBeenCancelled.set(true); | |||||
| connection = null; | |||||
| } | |||||
| Thread disconnectionThread = new Thread(disconnectionRunnable); | |||||
| disconnectionThread.start(); | |||||
| } | |||||
| public final int read(byte[] buffer, int numBytes) | |||||
| { | |||||
| int num = 0; | |||||
| try | |||||
| { | |||||
| synchronized (createStreamLock) | |||||
| { | |||||
| if (inputStream != null) | |||||
| num = inputStream.read(buffer, 0, numBytes); | |||||
| } | |||||
| } catch (IOException e) | |||||
| { | |||||
| } | |||||
| if (num > 0) | |||||
| position += num; | |||||
| return num; | |||||
| } | |||||
| public final long getPosition() | |||||
| { | |||||
| return position; | |||||
| } | |||||
| public final long getTotalLength() | |||||
| { | |||||
| return totalLength; | |||||
| } | |||||
| public final boolean isExhausted() | |||||
| { | |||||
| return false; | |||||
| } | |||||
| public final boolean setPosition(long newPos) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| private boolean isPost; | |||||
| private byte[] postData; | |||||
| private String headers; | |||||
| private int timeOutMs; | |||||
| String httpRequestCmd; | |||||
| private HttpURLConnection connection; | |||||
| private int[] statusCode; | |||||
| private StringBuffer responseHeaders; | |||||
| private int totalLength; | |||||
| private int numRedirectsToFollow; | |||||
| private InputStream inputStream; | |||||
| private long position; | |||||
| private final ReentrantLock createStreamLock = new ReentrantLock(); | |||||
| private final Object createFutureLock = new Object(); | |||||
| private AtomicBoolean hasBeenCancelled = new AtomicBoolean(); | |||||
| private final ExecutorService executor = Executors.newCachedThreadPool(Executors.defaultThreadFactory()); | |||||
| Future<BufferedInputStream> streamFuture; | |||||
| } | |||||
| package com.roli.juce; | |||||
| import java.lang.Runnable; | |||||
| import java.io.*; | |||||
| import java.net.URL; | |||||
| import java.net.HttpURLConnection; | |||||
| import java.util.concurrent.CancellationException; | |||||
| import java.util.concurrent.Future; | |||||
| import java.util.concurrent.Executors; | |||||
| import java.util.concurrent.ExecutorService; | |||||
| import java.util.concurrent.ExecutionException; | |||||
| import java.util.concurrent.Callable; | |||||
| import java.util.concurrent.locks.ReentrantLock; | |||||
| import java.util.concurrent.atomic.*; | |||||
| public class JuceHTTPStream | |||||
| { | |||||
| public JuceHTTPStream(String address, boolean isPostToUse, byte[] postDataToUse, | |||||
| String headersToUse, int timeOutMsToUse, | |||||
| int[] statusCodeToUse, StringBuffer responseHeadersToUse, | |||||
| int numRedirectsToFollowToUse, String httpRequestCmdToUse) throws IOException | |||||
| { | |||||
| isPost = isPostToUse; | |||||
| postData = postDataToUse; | |||||
| headers = headersToUse; | |||||
| timeOutMs = timeOutMsToUse; | |||||
| statusCode = statusCodeToUse; | |||||
| responseHeaders = responseHeadersToUse; | |||||
| totalLength = -1; | |||||
| numRedirectsToFollow = numRedirectsToFollowToUse; | |||||
| httpRequestCmd = httpRequestCmdToUse; | |||||
| connection = createConnection(address, isPost, postData, headers, timeOutMs, httpRequestCmd); | |||||
| } | |||||
| public static final JuceHTTPStream createHTTPStream(String address, boolean isPost, byte[] postData, | |||||
| String headers, int timeOutMs, int[] statusCode, | |||||
| StringBuffer responseHeaders, int numRedirectsToFollow, | |||||
| String httpRequestCmd) | |||||
| { | |||||
| // timeout parameter of zero for HttpUrlConnection is a blocking connect (negative value for juce::URL) | |||||
| if (timeOutMs < 0) | |||||
| timeOutMs = 0; | |||||
| else if (timeOutMs == 0) | |||||
| timeOutMs = 30000; | |||||
| for (; ; ) | |||||
| { | |||||
| try | |||||
| { | |||||
| JuceHTTPStream httpStream = new JuceHTTPStream(address, isPost, postData, headers, | |||||
| timeOutMs, statusCode, responseHeaders, | |||||
| numRedirectsToFollow, httpRequestCmd); | |||||
| return httpStream; | |||||
| } catch (Throwable e) | |||||
| { | |||||
| } | |||||
| return null; | |||||
| } | |||||
| } | |||||
| private final HttpURLConnection createConnection(String address, boolean isPost, byte[] postData, | |||||
| String headers, int timeOutMs, String httpRequestCmdToUse) throws IOException | |||||
| { | |||||
| HttpURLConnection newConnection = (HttpURLConnection) (new URL(address).openConnection()); | |||||
| try | |||||
| { | |||||
| newConnection.setInstanceFollowRedirects(false); | |||||
| newConnection.setConnectTimeout(timeOutMs); | |||||
| newConnection.setReadTimeout(timeOutMs); | |||||
| // headers - if not empty, this string is appended onto the headers that are used for the request. It must therefore be a valid set of HTML header directives, separated by newlines. | |||||
| // So convert headers string to an array, with an element for each line | |||||
| String headerLines[] = headers.split("\\n"); | |||||
| // Set request headers | |||||
| for (int i = 0; i < headerLines.length; ++i) | |||||
| { | |||||
| int pos = headerLines[i].indexOf(":"); | |||||
| if (pos > 0 && pos < headerLines[i].length()) | |||||
| { | |||||
| String field = headerLines[i].substring(0, pos); | |||||
| String value = headerLines[i].substring(pos + 1); | |||||
| if (value.length() > 0) | |||||
| newConnection.setRequestProperty(field, value); | |||||
| } | |||||
| } | |||||
| newConnection.setRequestMethod(httpRequestCmd); | |||||
| if (isPost) | |||||
| { | |||||
| newConnection.setDoOutput(true); | |||||
| if (postData != null) | |||||
| { | |||||
| OutputStream out = newConnection.getOutputStream(); | |||||
| out.write(postData); | |||||
| out.flush(); | |||||
| } | |||||
| } | |||||
| return newConnection; | |||||
| } catch (Throwable e) | |||||
| { | |||||
| newConnection.disconnect(); | |||||
| throw new IOException("Connection error"); | |||||
| } | |||||
| } | |||||
| private final InputStream getCancellableStream(final boolean isInput) throws ExecutionException | |||||
| { | |||||
| synchronized (createFutureLock) | |||||
| { | |||||
| if (hasBeenCancelled.get()) | |||||
| return null; | |||||
| streamFuture = executor.submit(new Callable<BufferedInputStream>() | |||||
| { | |||||
| @Override | |||||
| public BufferedInputStream call() throws IOException | |||||
| { | |||||
| return new BufferedInputStream(isInput ? connection.getInputStream() | |||||
| : connection.getErrorStream()); | |||||
| } | |||||
| }); | |||||
| } | |||||
| try | |||||
| { | |||||
| return streamFuture.get(); | |||||
| } catch (InterruptedException e) | |||||
| { | |||||
| return null; | |||||
| } catch (CancellationException e) | |||||
| { | |||||
| return null; | |||||
| } | |||||
| } | |||||
| public final boolean connect() | |||||
| { | |||||
| boolean result = false; | |||||
| int numFollowedRedirects = 0; | |||||
| while (true) | |||||
| { | |||||
| result = doConnect(); | |||||
| if (!result) | |||||
| return false; | |||||
| if (++numFollowedRedirects > numRedirectsToFollow) | |||||
| break; | |||||
| int status = statusCode[0]; | |||||
| if (status == 301 || status == 302 || status == 303 || status == 307) | |||||
| { | |||||
| // Assumes only one occurrence of "Location" | |||||
| int pos1 = responseHeaders.indexOf("Location:") + 10; | |||||
| int pos2 = responseHeaders.indexOf("\n", pos1); | |||||
| if (pos2 > pos1) | |||||
| { | |||||
| String currentLocation = connection.getURL().toString(); | |||||
| String newLocation = responseHeaders.substring(pos1, pos2); | |||||
| try | |||||
| { | |||||
| // Handle newLocation whether it's absolute or relative | |||||
| URL baseUrl = new URL(currentLocation); | |||||
| URL newUrl = new URL(baseUrl, newLocation); | |||||
| String transformedNewLocation = newUrl.toString(); | |||||
| if (transformedNewLocation != currentLocation) | |||||
| { | |||||
| // Clear responseHeaders before next iteration | |||||
| responseHeaders.delete(0, responseHeaders.length()); | |||||
| synchronized (createStreamLock) | |||||
| { | |||||
| if (hasBeenCancelled.get()) | |||||
| return false; | |||||
| connection.disconnect(); | |||||
| try | |||||
| { | |||||
| connection = createConnection(transformedNewLocation, isPost, | |||||
| postData, headers, timeOutMs, | |||||
| httpRequestCmd); | |||||
| } catch (Throwable e) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| } | |||||
| } else | |||||
| { | |||||
| break; | |||||
| } | |||||
| } catch (Throwable e) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| } else | |||||
| { | |||||
| break; | |||||
| } | |||||
| } else | |||||
| { | |||||
| break; | |||||
| } | |||||
| } | |||||
| return result; | |||||
| } | |||||
| private final boolean doConnect() | |||||
| { | |||||
| synchronized (createStreamLock) | |||||
| { | |||||
| if (hasBeenCancelled.get()) | |||||
| return false; | |||||
| try | |||||
| { | |||||
| try | |||||
| { | |||||
| inputStream = getCancellableStream(true); | |||||
| } catch (ExecutionException e) | |||||
| { | |||||
| if (connection.getResponseCode() < 400) | |||||
| { | |||||
| statusCode[0] = connection.getResponseCode(); | |||||
| connection.disconnect(); | |||||
| return false; | |||||
| } | |||||
| } finally | |||||
| { | |||||
| statusCode[0] = connection.getResponseCode(); | |||||
| } | |||||
| try | |||||
| { | |||||
| if (statusCode[0] >= 400) | |||||
| inputStream = getCancellableStream(false); | |||||
| else | |||||
| inputStream = getCancellableStream(true); | |||||
| } catch (ExecutionException e) | |||||
| { | |||||
| } | |||||
| for (java.util.Map.Entry<String, java.util.List<String>> entry : connection.getHeaderFields().entrySet()) | |||||
| { | |||||
| if (entry.getKey() != null && entry.getValue() != null) | |||||
| { | |||||
| responseHeaders.append(entry.getKey() + ": " | |||||
| + android.text.TextUtils.join(",", entry.getValue()) + "\n"); | |||||
| if (entry.getKey().compareTo("Content-Length") == 0) | |||||
| totalLength = Integer.decode(entry.getValue().get(0)); | |||||
| } | |||||
| } | |||||
| return true; | |||||
| } catch (IOException e) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| } | |||||
| } | |||||
| static class DisconnectionRunnable implements Runnable | |||||
| { | |||||
| public DisconnectionRunnable(HttpURLConnection theConnection, | |||||
| InputStream theInputStream, | |||||
| ReentrantLock theCreateStreamLock, | |||||
| Object theCreateFutureLock, | |||||
| Future<BufferedInputStream> theStreamFuture) | |||||
| { | |||||
| connectionToDisconnect = theConnection; | |||||
| inputStream = theInputStream; | |||||
| createStreamLock = theCreateStreamLock; | |||||
| createFutureLock = theCreateFutureLock; | |||||
| streamFuture = theStreamFuture; | |||||
| } | |||||
| public void run() | |||||
| { | |||||
| try | |||||
| { | |||||
| if (!createStreamLock.tryLock()) | |||||
| { | |||||
| synchronized (createFutureLock) | |||||
| { | |||||
| if (streamFuture != null) | |||||
| streamFuture.cancel(true); | |||||
| } | |||||
| createStreamLock.lock(); | |||||
| } | |||||
| if (connectionToDisconnect != null) | |||||
| connectionToDisconnect.disconnect(); | |||||
| if (inputStream != null) | |||||
| inputStream.close(); | |||||
| } catch (IOException e) | |||||
| { | |||||
| } finally | |||||
| { | |||||
| createStreamLock.unlock(); | |||||
| } | |||||
| } | |||||
| private HttpURLConnection connectionToDisconnect; | |||||
| private InputStream inputStream; | |||||
| private ReentrantLock createStreamLock; | |||||
| private Object createFutureLock; | |||||
| Future<BufferedInputStream> streamFuture; | |||||
| } | |||||
| public final void release() | |||||
| { | |||||
| DisconnectionRunnable disconnectionRunnable = new DisconnectionRunnable(connection, | |||||
| inputStream, | |||||
| createStreamLock, | |||||
| createFutureLock, | |||||
| streamFuture); | |||||
| synchronized (createStreamLock) | |||||
| { | |||||
| hasBeenCancelled.set(true); | |||||
| connection = null; | |||||
| } | |||||
| Thread disconnectionThread = new Thread(disconnectionRunnable); | |||||
| disconnectionThread.start(); | |||||
| } | |||||
| public final int read(byte[] buffer, int numBytes) | |||||
| { | |||||
| int num = 0; | |||||
| try | |||||
| { | |||||
| synchronized (createStreamLock) | |||||
| { | |||||
| if (inputStream != null) | |||||
| num = inputStream.read(buffer, 0, numBytes); | |||||
| } | |||||
| } catch (IOException e) | |||||
| { | |||||
| } | |||||
| if (num > 0) | |||||
| position += num; | |||||
| return num; | |||||
| } | |||||
| public final long getPosition() | |||||
| { | |||||
| return position; | |||||
| } | |||||
| public final long getTotalLength() | |||||
| { | |||||
| return totalLength; | |||||
| } | |||||
| public final boolean isExhausted() | |||||
| { | |||||
| return false; | |||||
| } | |||||
| public final boolean setPosition(long newPos) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| private boolean isPost; | |||||
| private byte[] postData; | |||||
| private String headers; | |||||
| private int timeOutMs; | |||||
| String httpRequestCmd; | |||||
| private HttpURLConnection connection; | |||||
| private int[] statusCode; | |||||
| private StringBuffer responseHeaders; | |||||
| private int totalLength; | |||||
| private int numRedirectsToFollow; | |||||
| private InputStream inputStream; | |||||
| private long position; | |||||
| private final ReentrantLock createStreamLock = new ReentrantLock(); | |||||
| private final Object createFutureLock = new Object(); | |||||
| private AtomicBoolean hasBeenCancelled = new AtomicBoolean(); | |||||
| private final ExecutorService executor = Executors.newCachedThreadPool(Executors.defaultThreadFactory()); | |||||
| Future<BufferedInputStream> streamFuture; | |||||
| } | |||||
| @@ -1,493 +1,493 @@ | |||||
| package com.roli.juce; | |||||
| import android.app.Activity; | |||||
| import android.app.Application; | |||||
| import android.content.Context; | |||||
| import android.graphics.Canvas; | |||||
| import android.graphics.ColorMatrix; | |||||
| import android.graphics.ColorMatrixColorFilter; | |||||
| import android.graphics.Paint; | |||||
| import android.graphics.Rect; | |||||
| import android.os.Bundle; | |||||
| import android.text.InputType; | |||||
| import android.view.KeyEvent; | |||||
| import android.view.MotionEvent; | |||||
| import android.view.View; | |||||
| import android.view.ViewGroup; | |||||
| import android.view.ViewTreeObserver; | |||||
| import android.view.inputmethod.BaseInputConnection; | |||||
| import android.view.inputmethod.EditorInfo; | |||||
| import android.view.inputmethod.InputConnection; | |||||
| import android.view.inputmethod.InputMethodManager; | |||||
| import java.lang.reflect.Method; | |||||
| public final class ComponentPeerView extends ViewGroup | |||||
| implements View.OnFocusChangeListener, Application.ActivityLifecycleCallbacks | |||||
| { | |||||
| public ComponentPeerView (Context context, boolean opaque_, long host) | |||||
| { | |||||
| super (context); | |||||
| if (Application.class.isInstance (context)) | |||||
| { | |||||
| ((Application) context).registerActivityLifecycleCallbacks (this); | |||||
| } else | |||||
| { | |||||
| ((Application) context.getApplicationContext ()).registerActivityLifecycleCallbacks (this); | |||||
| } | |||||
| this.host = host; | |||||
| setWillNotDraw (false); | |||||
| opaque = opaque_; | |||||
| setFocusable (true); | |||||
| setFocusableInTouchMode (true); | |||||
| setOnFocusChangeListener (this); | |||||
| // swap red and blue colours to match internal opengl texture format | |||||
| ColorMatrix colorMatrix = new ColorMatrix (); | |||||
| float[] colorTransform = {0, 0, 1.0f, 0, 0, | |||||
| 0, 1.0f, 0, 0, 0, | |||||
| 1.0f, 0, 0, 0, 0, | |||||
| 0, 0, 0, 1.0f, 0}; | |||||
| colorMatrix.set (colorTransform); | |||||
| paint.setColorFilter (new ColorMatrixColorFilter (colorMatrix)); | |||||
| java.lang.reflect.Method method = null; | |||||
| try | |||||
| { | |||||
| method = getClass ().getMethod ("setLayerType", int.class, Paint.class); | |||||
| } catch (SecurityException e) | |||||
| { | |||||
| } catch (NoSuchMethodException e) | |||||
| { | |||||
| } | |||||
| if (method != null) | |||||
| { | |||||
| try | |||||
| { | |||||
| int layerTypeNone = 0; | |||||
| method.invoke (this, layerTypeNone, null); | |||||
| } catch (java.lang.IllegalArgumentException e) | |||||
| { | |||||
| } catch (java.lang.IllegalAccessException e) | |||||
| { | |||||
| } catch (java.lang.reflect.InvocationTargetException e) | |||||
| { | |||||
| } | |||||
| } | |||||
| } | |||||
| public void clear () | |||||
| { | |||||
| host = 0; | |||||
| } | |||||
| //============================================================================== | |||||
| private native void handlePaint (long host, Canvas canvas, Paint paint); | |||||
| @Override | |||||
| public void onDraw (Canvas canvas) | |||||
| { | |||||
| if (host == 0) | |||||
| return; | |||||
| handlePaint (host, canvas, paint); | |||||
| } | |||||
| @Override | |||||
| public boolean isOpaque () | |||||
| { | |||||
| return opaque; | |||||
| } | |||||
| private boolean opaque; | |||||
| private long host; | |||||
| private Paint paint = new Paint (); | |||||
| //============================================================================== | |||||
| private native void handleMouseDown (long host, int index, float x, float y, long time); | |||||
| private native void handleMouseDrag (long host, int index, float x, float y, long time); | |||||
| private native void handleMouseUp (long host, int index, float x, float y, long time); | |||||
| @Override | |||||
| public boolean onTouchEvent (MotionEvent event) | |||||
| { | |||||
| if (host == 0) | |||||
| return false; | |||||
| 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); | |||||
| return true; | |||||
| case MotionEvent.ACTION_CANCEL: | |||||
| case MotionEvent.ACTION_UP: | |||||
| 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); | |||||
| int n = event.getPointerCount (); | |||||
| if (n > 1) | |||||
| { | |||||
| int point[] = new int[2]; | |||||
| getLocationOnScreen (point); | |||||
| for (int i = 1; i < n; ++i) | |||||
| handleMouseDrag (host, event.getPointerId (i), event.getX (i) + point[0], event.getY (i) + point[1], time); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| case MotionEvent.ACTION_POINTER_UP: | |||||
| { | |||||
| int i = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; | |||||
| if (i == 0) | |||||
| { | |||||
| handleMouseUp (host, event.getPointerId (0), event.getRawX (), event.getRawY (), time); | |||||
| } else | |||||
| { | |||||
| int point[] = new int[2]; | |||||
| getLocationOnScreen (point); | |||||
| handleMouseUp (host, event.getPointerId (i), event.getX (i) + point[0], event.getY (i) + point[1], time); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| case MotionEvent.ACTION_POINTER_DOWN: | |||||
| { | |||||
| int i = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; | |||||
| if (i == 0) | |||||
| { | |||||
| handleMouseDown (host, event.getPointerId (0), event.getRawX (), event.getRawY (), time); | |||||
| } else | |||||
| { | |||||
| int point[] = new int[2]; | |||||
| getLocationOnScreen (point); | |||||
| handleMouseDown (host, event.getPointerId (i), event.getX (i) + point[0], event.getY (i) + point[1], time); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| default: | |||||
| break; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| //============================================================================== | |||||
| private native void handleKeyDown (long host, int keycode, int textchar); | |||||
| 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) | |||||
| { | |||||
| InputMethodManager imm = (InputMethodManager) getContext ().getSystemService (Context.INPUT_METHOD_SERVICE); | |||||
| if (imm != null) | |||||
| { | |||||
| 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 (); | |||||
| } | |||||
| } | |||||
| } | |||||
| public void backButtonPressed () | |||||
| { | |||||
| if (host == 0) | |||||
| return; | |||||
| handleBackButton (host); | |||||
| } | |||||
| @Override | |||||
| public boolean onKeyDown (int keyCode, KeyEvent event) | |||||
| { | |||||
| if (host == 0) | |||||
| return false; | |||||
| switch (keyCode) | |||||
| { | |||||
| case KeyEvent.KEYCODE_VOLUME_UP: | |||||
| case KeyEvent.KEYCODE_VOLUME_DOWN: | |||||
| return super.onKeyDown (keyCode, event); | |||||
| case KeyEvent.KEYCODE_BACK: | |||||
| { | |||||
| ((Activity) getContext ()).onBackPressed (); | |||||
| return true; | |||||
| } | |||||
| default: | |||||
| break; | |||||
| } | |||||
| handleKeyDown (host, keyCode, event.getUnicodeChar ()); | |||||
| return true; | |||||
| } | |||||
| @Override | |||||
| public boolean onKeyUp (int keyCode, KeyEvent event) | |||||
| { | |||||
| if (host == 0) | |||||
| return false; | |||||
| handleKeyUp (host, keyCode, event.getUnicodeChar ()); | |||||
| return true; | |||||
| } | |||||
| @Override | |||||
| public boolean onKeyMultiple (int keyCode, int count, KeyEvent event) | |||||
| { | |||||
| if (host == 0) | |||||
| return false; | |||||
| if (keyCode != KeyEvent.KEYCODE_UNKNOWN || event.getAction () != KeyEvent.ACTION_MULTIPLE) | |||||
| return super.onKeyMultiple (keyCode, count, event); | |||||
| if (event.getCharacters () != null) | |||||
| { | |||||
| int utf8Char = event.getCharacters ().codePointAt (0); | |||||
| handleKeyDown (host, utf8Char, utf8Char); | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| //============================================================================== | |||||
| private final class KeyboardDismissListener | |||||
| { | |||||
| public KeyboardDismissListener (ComponentPeerView viewToUse) | |||||
| { | |||||
| view = viewToUse; | |||||
| } | |||||
| private void startListening () | |||||
| { | |||||
| view.getViewTreeObserver ().addOnGlobalLayoutListener (viewTreeObserver); | |||||
| } | |||||
| private void stopListening () | |||||
| { | |||||
| view.getViewTreeObserver ().removeGlobalOnLayoutListener (viewTreeObserver); | |||||
| } | |||||
| private class TreeObserver implements ViewTreeObserver.OnGlobalLayoutListener | |||||
| { | |||||
| TreeObserver () | |||||
| { | |||||
| keyboardShown = false; | |||||
| } | |||||
| @Override | |||||
| public void onGlobalLayout () | |||||
| { | |||||
| Rect r = new Rect (); | |||||
| View parentView = getRootView (); | |||||
| int diff = 0; | |||||
| if (parentView == null) | |||||
| { | |||||
| getWindowVisibleDisplayFrame (r); | |||||
| diff = getHeight () - (r.bottom - r.top); | |||||
| } else | |||||
| { | |||||
| parentView.getWindowVisibleDisplayFrame (r); | |||||
| diff = parentView.getHeight () - (r.bottom - r.top); | |||||
| } | |||||
| // Arbitrary threshold, surely keyboard would take more than 20 pix. | |||||
| if (diff < 20 && keyboardShown) | |||||
| { | |||||
| keyboardShown = false; | |||||
| handleKeyboardHidden (view.host); | |||||
| } | |||||
| if (!keyboardShown && diff > 20) | |||||
| keyboardShown = true; | |||||
| } | |||||
| ; | |||||
| private boolean keyboardShown; | |||||
| } | |||||
| ; | |||||
| private ComponentPeerView view; | |||||
| private TreeObserver viewTreeObserver = new TreeObserver (); | |||||
| } | |||||
| private KeyboardDismissListener keyboardDismissListener = new KeyboardDismissListener (this); | |||||
| // this is here to make keyboard entry work on a Galaxy Tab2 10.1 | |||||
| @Override | |||||
| public InputConnection onCreateInputConnection (EditorInfo outAttrs) | |||||
| { | |||||
| outAttrs.actionLabel = ""; | |||||
| outAttrs.hintText = ""; | |||||
| outAttrs.initialCapsMode = 0; | |||||
| outAttrs.initialSelEnd = outAttrs.initialSelStart = -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); | |||||
| } | |||||
| //============================================================================== | |||||
| @Override | |||||
| protected void onSizeChanged (int w, int h, int oldw, int oldh) | |||||
| { | |||||
| super.onSizeChanged (w, h, oldw, oldh); | |||||
| if (host != 0) | |||||
| viewSizeChanged (host); | |||||
| } | |||||
| @Override | |||||
| protected void onLayout (boolean changed, int left, int top, int right, int bottom) | |||||
| { | |||||
| } | |||||
| private native void viewSizeChanged (long host); | |||||
| @Override | |||||
| public void onFocusChange (View v, boolean hasFocus) | |||||
| { | |||||
| if (host == 0) | |||||
| return; | |||||
| if (v == this) | |||||
| focusChanged (host, hasFocus); | |||||
| } | |||||
| private native void focusChanged (long host, boolean hasFocus); | |||||
| public void setViewName (String newName) | |||||
| { | |||||
| } | |||||
| public void setSystemUiVisibilityCompat (int visibility) | |||||
| { | |||||
| Method systemUIVisibilityMethod = null; | |||||
| try | |||||
| { | |||||
| systemUIVisibilityMethod = this.getClass ().getMethod ("setSystemUiVisibility", int.class); | |||||
| } catch (SecurityException e) | |||||
| { | |||||
| return; | |||||
| } catch (NoSuchMethodException e) | |||||
| { | |||||
| return; | |||||
| } | |||||
| if (systemUIVisibilityMethod == null) return; | |||||
| try | |||||
| { | |||||
| systemUIVisibilityMethod.invoke (this, visibility); | |||||
| } catch (java.lang.IllegalArgumentException e) | |||||
| { | |||||
| } catch (java.lang.IllegalAccessException e) | |||||
| { | |||||
| } catch (java.lang.reflect.InvocationTargetException e) | |||||
| { | |||||
| } | |||||
| } | |||||
| public boolean isVisible () | |||||
| { | |||||
| return getVisibility () == VISIBLE; | |||||
| } | |||||
| public void setVisible (boolean b) | |||||
| { | |||||
| setVisibility (b ? VISIBLE : INVISIBLE); | |||||
| } | |||||
| public boolean containsPoint (int x, int y) | |||||
| { | |||||
| return true; //xxx needs to check overlapping views | |||||
| } | |||||
| //============================================================================== | |||||
| private native void handleAppPaused (long host); | |||||
| private native void handleAppResumed (long host); | |||||
| @Override | |||||
| public void onActivityPaused (Activity activity) | |||||
| { | |||||
| if (host == 0) | |||||
| return; | |||||
| handleAppPaused (host); | |||||
| } | |||||
| @Override | |||||
| public void onActivityStopped (Activity activity) | |||||
| { | |||||
| } | |||||
| @Override | |||||
| public void onActivitySaveInstanceState (Activity activity, Bundle bundle) | |||||
| { | |||||
| } | |||||
| @Override | |||||
| public void onActivityDestroyed (Activity activity) | |||||
| { | |||||
| } | |||||
| @Override | |||||
| public void onActivityCreated (Activity activity, Bundle bundle) | |||||
| { | |||||
| } | |||||
| @Override | |||||
| public void onActivityStarted (Activity activity) | |||||
| { | |||||
| } | |||||
| @Override | |||||
| public void onActivityResumed (Activity activity) | |||||
| { | |||||
| if (host == 0) | |||||
| return; | |||||
| // Ensure that navigation/status bar visibility is correctly restored. | |||||
| handleAppResumed (host); | |||||
| } | |||||
| } | |||||
| package com.roli.juce; | |||||
| import android.app.Activity; | |||||
| import android.app.Application; | |||||
| import android.content.Context; | |||||
| import android.graphics.Canvas; | |||||
| import android.graphics.ColorMatrix; | |||||
| import android.graphics.ColorMatrixColorFilter; | |||||
| import android.graphics.Paint; | |||||
| import android.graphics.Rect; | |||||
| import android.os.Bundle; | |||||
| import android.text.InputType; | |||||
| import android.view.KeyEvent; | |||||
| import android.view.MotionEvent; | |||||
| import android.view.View; | |||||
| import android.view.ViewGroup; | |||||
| import android.view.ViewTreeObserver; | |||||
| import android.view.inputmethod.BaseInputConnection; | |||||
| import android.view.inputmethod.EditorInfo; | |||||
| import android.view.inputmethod.InputConnection; | |||||
| import android.view.inputmethod.InputMethodManager; | |||||
| import java.lang.reflect.Method; | |||||
| public final class ComponentPeerView extends ViewGroup | |||||
| implements View.OnFocusChangeListener, Application.ActivityLifecycleCallbacks | |||||
| { | |||||
| public ComponentPeerView (Context context, boolean opaque_, long host) | |||||
| { | |||||
| super (context); | |||||
| if (Application.class.isInstance (context)) | |||||
| { | |||||
| ((Application) context).registerActivityLifecycleCallbacks (this); | |||||
| } else | |||||
| { | |||||
| ((Application) context.getApplicationContext ()).registerActivityLifecycleCallbacks (this); | |||||
| } | |||||
| this.host = host; | |||||
| setWillNotDraw (false); | |||||
| opaque = opaque_; | |||||
| setFocusable (true); | |||||
| setFocusableInTouchMode (true); | |||||
| setOnFocusChangeListener (this); | |||||
| // swap red and blue colours to match internal opengl texture format | |||||
| ColorMatrix colorMatrix = new ColorMatrix (); | |||||
| float[] colorTransform = {0, 0, 1.0f, 0, 0, | |||||
| 0, 1.0f, 0, 0, 0, | |||||
| 1.0f, 0, 0, 0, 0, | |||||
| 0, 0, 0, 1.0f, 0}; | |||||
| colorMatrix.set (colorTransform); | |||||
| paint.setColorFilter (new ColorMatrixColorFilter (colorMatrix)); | |||||
| java.lang.reflect.Method method = null; | |||||
| try | |||||
| { | |||||
| method = getClass ().getMethod ("setLayerType", int.class, Paint.class); | |||||
| } catch (SecurityException e) | |||||
| { | |||||
| } catch (NoSuchMethodException e) | |||||
| { | |||||
| } | |||||
| if (method != null) | |||||
| { | |||||
| try | |||||
| { | |||||
| int layerTypeNone = 0; | |||||
| method.invoke (this, layerTypeNone, null); | |||||
| } catch (java.lang.IllegalArgumentException e) | |||||
| { | |||||
| } catch (java.lang.IllegalAccessException e) | |||||
| { | |||||
| } catch (java.lang.reflect.InvocationTargetException e) | |||||
| { | |||||
| } | |||||
| } | |||||
| } | |||||
| public void clear () | |||||
| { | |||||
| host = 0; | |||||
| } | |||||
| //============================================================================== | |||||
| private native void handlePaint (long host, Canvas canvas, Paint paint); | |||||
| @Override | |||||
| public void onDraw (Canvas canvas) | |||||
| { | |||||
| if (host == 0) | |||||
| return; | |||||
| handlePaint (host, canvas, paint); | |||||
| } | |||||
| @Override | |||||
| public boolean isOpaque () | |||||
| { | |||||
| return opaque; | |||||
| } | |||||
| private boolean opaque; | |||||
| private long host; | |||||
| private Paint paint = new Paint (); | |||||
| //============================================================================== | |||||
| private native void handleMouseDown (long host, int index, float x, float y, long time); | |||||
| private native void handleMouseDrag (long host, int index, float x, float y, long time); | |||||
| private native void handleMouseUp (long host, int index, float x, float y, long time); | |||||
| @Override | |||||
| public boolean onTouchEvent (MotionEvent event) | |||||
| { | |||||
| if (host == 0) | |||||
| return false; | |||||
| 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); | |||||
| return true; | |||||
| case MotionEvent.ACTION_CANCEL: | |||||
| case MotionEvent.ACTION_UP: | |||||
| 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); | |||||
| int n = event.getPointerCount (); | |||||
| if (n > 1) | |||||
| { | |||||
| int point[] = new int[2]; | |||||
| getLocationOnScreen (point); | |||||
| for (int i = 1; i < n; ++i) | |||||
| handleMouseDrag (host, event.getPointerId (i), event.getX (i) + point[0], event.getY (i) + point[1], time); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| case MotionEvent.ACTION_POINTER_UP: | |||||
| { | |||||
| int i = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; | |||||
| if (i == 0) | |||||
| { | |||||
| handleMouseUp (host, event.getPointerId (0), event.getRawX (), event.getRawY (), time); | |||||
| } else | |||||
| { | |||||
| int point[] = new int[2]; | |||||
| getLocationOnScreen (point); | |||||
| handleMouseUp (host, event.getPointerId (i), event.getX (i) + point[0], event.getY (i) + point[1], time); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| case MotionEvent.ACTION_POINTER_DOWN: | |||||
| { | |||||
| int i = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; | |||||
| if (i == 0) | |||||
| { | |||||
| handleMouseDown (host, event.getPointerId (0), event.getRawX (), event.getRawY (), time); | |||||
| } else | |||||
| { | |||||
| int point[] = new int[2]; | |||||
| getLocationOnScreen (point); | |||||
| handleMouseDown (host, event.getPointerId (i), event.getX (i) + point[0], event.getY (i) + point[1], time); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| default: | |||||
| break; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| //============================================================================== | |||||
| private native void handleKeyDown (long host, int keycode, int textchar); | |||||
| 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) | |||||
| { | |||||
| InputMethodManager imm = (InputMethodManager) getContext ().getSystemService (Context.INPUT_METHOD_SERVICE); | |||||
| if (imm != null) | |||||
| { | |||||
| 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 (); | |||||
| } | |||||
| } | |||||
| } | |||||
| public void backButtonPressed () | |||||
| { | |||||
| if (host == 0) | |||||
| return; | |||||
| handleBackButton (host); | |||||
| } | |||||
| @Override | |||||
| public boolean onKeyDown (int keyCode, KeyEvent event) | |||||
| { | |||||
| if (host == 0) | |||||
| return false; | |||||
| switch (keyCode) | |||||
| { | |||||
| case KeyEvent.KEYCODE_VOLUME_UP: | |||||
| case KeyEvent.KEYCODE_VOLUME_DOWN: | |||||
| return super.onKeyDown (keyCode, event); | |||||
| case KeyEvent.KEYCODE_BACK: | |||||
| { | |||||
| ((Activity) getContext ()).onBackPressed (); | |||||
| return true; | |||||
| } | |||||
| default: | |||||
| break; | |||||
| } | |||||
| handleKeyDown (host, keyCode, event.getUnicodeChar ()); | |||||
| return true; | |||||
| } | |||||
| @Override | |||||
| public boolean onKeyUp (int keyCode, KeyEvent event) | |||||
| { | |||||
| if (host == 0) | |||||
| return false; | |||||
| handleKeyUp (host, keyCode, event.getUnicodeChar ()); | |||||
| return true; | |||||
| } | |||||
| @Override | |||||
| public boolean onKeyMultiple (int keyCode, int count, KeyEvent event) | |||||
| { | |||||
| if (host == 0) | |||||
| return false; | |||||
| if (keyCode != KeyEvent.KEYCODE_UNKNOWN || event.getAction () != KeyEvent.ACTION_MULTIPLE) | |||||
| return super.onKeyMultiple (keyCode, count, event); | |||||
| if (event.getCharacters () != null) | |||||
| { | |||||
| int utf8Char = event.getCharacters ().codePointAt (0); | |||||
| handleKeyDown (host, utf8Char, utf8Char); | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| //============================================================================== | |||||
| private final class KeyboardDismissListener | |||||
| { | |||||
| public KeyboardDismissListener (ComponentPeerView viewToUse) | |||||
| { | |||||
| view = viewToUse; | |||||
| } | |||||
| private void startListening () | |||||
| { | |||||
| view.getViewTreeObserver ().addOnGlobalLayoutListener (viewTreeObserver); | |||||
| } | |||||
| private void stopListening () | |||||
| { | |||||
| view.getViewTreeObserver ().removeGlobalOnLayoutListener (viewTreeObserver); | |||||
| } | |||||
| private class TreeObserver implements ViewTreeObserver.OnGlobalLayoutListener | |||||
| { | |||||
| TreeObserver () | |||||
| { | |||||
| keyboardShown = false; | |||||
| } | |||||
| @Override | |||||
| public void onGlobalLayout () | |||||
| { | |||||
| Rect r = new Rect (); | |||||
| View parentView = getRootView (); | |||||
| int diff = 0; | |||||
| if (parentView == null) | |||||
| { | |||||
| getWindowVisibleDisplayFrame (r); | |||||
| diff = getHeight () - (r.bottom - r.top); | |||||
| } else | |||||
| { | |||||
| parentView.getWindowVisibleDisplayFrame (r); | |||||
| diff = parentView.getHeight () - (r.bottom - r.top); | |||||
| } | |||||
| // Arbitrary threshold, surely keyboard would take more than 20 pix. | |||||
| if (diff < 20 && keyboardShown) | |||||
| { | |||||
| keyboardShown = false; | |||||
| handleKeyboardHidden (view.host); | |||||
| } | |||||
| if (!keyboardShown && diff > 20) | |||||
| keyboardShown = true; | |||||
| } | |||||
| ; | |||||
| private boolean keyboardShown; | |||||
| } | |||||
| ; | |||||
| private ComponentPeerView view; | |||||
| private TreeObserver viewTreeObserver = new TreeObserver (); | |||||
| } | |||||
| private KeyboardDismissListener keyboardDismissListener = new KeyboardDismissListener (this); | |||||
| // this is here to make keyboard entry work on a Galaxy Tab2 10.1 | |||||
| @Override | |||||
| public InputConnection onCreateInputConnection (EditorInfo outAttrs) | |||||
| { | |||||
| outAttrs.actionLabel = ""; | |||||
| outAttrs.hintText = ""; | |||||
| outAttrs.initialCapsMode = 0; | |||||
| outAttrs.initialSelEnd = outAttrs.initialSelStart = -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); | |||||
| } | |||||
| //============================================================================== | |||||
| @Override | |||||
| protected void onSizeChanged (int w, int h, int oldw, int oldh) | |||||
| { | |||||
| super.onSizeChanged (w, h, oldw, oldh); | |||||
| if (host != 0) | |||||
| viewSizeChanged (host); | |||||
| } | |||||
| @Override | |||||
| protected void onLayout (boolean changed, int left, int top, int right, int bottom) | |||||
| { | |||||
| } | |||||
| private native void viewSizeChanged (long host); | |||||
| @Override | |||||
| public void onFocusChange (View v, boolean hasFocus) | |||||
| { | |||||
| if (host == 0) | |||||
| return; | |||||
| if (v == this) | |||||
| focusChanged (host, hasFocus); | |||||
| } | |||||
| private native void focusChanged (long host, boolean hasFocus); | |||||
| public void setViewName (String newName) | |||||
| { | |||||
| } | |||||
| public void setSystemUiVisibilityCompat (int visibility) | |||||
| { | |||||
| Method systemUIVisibilityMethod = null; | |||||
| try | |||||
| { | |||||
| systemUIVisibilityMethod = this.getClass ().getMethod ("setSystemUiVisibility", int.class); | |||||
| } catch (SecurityException e) | |||||
| { | |||||
| return; | |||||
| } catch (NoSuchMethodException e) | |||||
| { | |||||
| return; | |||||
| } | |||||
| if (systemUIVisibilityMethod == null) return; | |||||
| try | |||||
| { | |||||
| systemUIVisibilityMethod.invoke (this, visibility); | |||||
| } catch (java.lang.IllegalArgumentException e) | |||||
| { | |||||
| } catch (java.lang.IllegalAccessException e) | |||||
| { | |||||
| } catch (java.lang.reflect.InvocationTargetException e) | |||||
| { | |||||
| } | |||||
| } | |||||
| public boolean isVisible () | |||||
| { | |||||
| return getVisibility () == VISIBLE; | |||||
| } | |||||
| public void setVisible (boolean b) | |||||
| { | |||||
| setVisibility (b ? VISIBLE : INVISIBLE); | |||||
| } | |||||
| public boolean containsPoint (int x, int y) | |||||
| { | |||||
| return true; //xxx needs to check overlapping views | |||||
| } | |||||
| //============================================================================== | |||||
| private native void handleAppPaused (long host); | |||||
| private native void handleAppResumed (long host); | |||||
| @Override | |||||
| public void onActivityPaused (Activity activity) | |||||
| { | |||||
| if (host == 0) | |||||
| return; | |||||
| handleAppPaused (host); | |||||
| } | |||||
| @Override | |||||
| public void onActivityStopped (Activity activity) | |||||
| { | |||||
| } | |||||
| @Override | |||||
| public void onActivitySaveInstanceState (Activity activity, Bundle bundle) | |||||
| { | |||||
| } | |||||
| @Override | |||||
| public void onActivityDestroyed (Activity activity) | |||||
| { | |||||
| } | |||||
| @Override | |||||
| public void onActivityCreated (Activity activity, Bundle bundle) | |||||
| { | |||||
| } | |||||
| @Override | |||||
| public void onActivityStarted (Activity activity) | |||||
| { | |||||
| } | |||||
| @Override | |||||
| public void onActivityResumed (Activity activity) | |||||
| { | |||||
| if (host == 0) | |||||
| return; | |||||
| // Ensure that navigation/status bar visibility is correctly restored. | |||||
| handleAppResumed (host); | |||||
| } | |||||
| } | |||||
| @@ -1,107 +1,107 @@ | |||||
| package com.roli.juce; | |||||
| import android.graphics.Bitmap; | |||||
| import android.net.http.SslError; | |||||
| import android.os.Message; | |||||
| import android.webkit.WebResourceResponse; | |||||
| import android.webkit.WebView; | |||||
| import android.webkit.WebViewClient; | |||||
| import android.webkit.SslErrorHandler; | |||||
| import android.webkit.WebChromeClient; | |||||
| //============================================================================== | |||||
| public class JuceWebView | |||||
| { | |||||
| static public class Client extends WebViewClient | |||||
| { | |||||
| public Client (long hostToUse) | |||||
| { | |||||
| host = hostToUse; | |||||
| } | |||||
| public void hostDeleted () | |||||
| { | |||||
| synchronized (hostLock) | |||||
| { | |||||
| host = 0; | |||||
| } | |||||
| } | |||||
| public void onPageFinished (WebView view, String url) | |||||
| { | |||||
| if (host == 0) | |||||
| return; | |||||
| webViewPageLoadFinished (host, view, url); | |||||
| } | |||||
| public void onReceivedSslError (WebView view, SslErrorHandler handler, SslError error) | |||||
| { | |||||
| if (host == 0) | |||||
| return; | |||||
| webViewReceivedSslError (host, view, handler, error); | |||||
| } | |||||
| public void onPageStarted (WebView view, String url, Bitmap favicon) | |||||
| { | |||||
| if (host != 0) | |||||
| webViewPageLoadStarted (host, view, url); | |||||
| } | |||||
| public WebResourceResponse shouldInterceptRequest (WebView view, String url) | |||||
| { | |||||
| synchronized (hostLock) | |||||
| { | |||||
| if (host != 0) | |||||
| { | |||||
| boolean shouldLoad = webViewPageLoadStarted (host, view, url); | |||||
| if (shouldLoad) | |||||
| return null; | |||||
| } | |||||
| } | |||||
| return new WebResourceResponse ("text/html", null, null); | |||||
| } | |||||
| private native boolean webViewPageLoadStarted (long host, WebView view, String url); | |||||
| private native void webViewPageLoadFinished (long host, WebView view, String url); | |||||
| private native void webViewReceivedSslError (long host, WebView view, SslErrorHandler handler, SslError error); | |||||
| private long host; | |||||
| private final Object hostLock = new Object (); | |||||
| } | |||||
| static public class ChromeClient extends WebChromeClient | |||||
| { | |||||
| public ChromeClient (long hostToUse) | |||||
| { | |||||
| host = hostToUse; | |||||
| } | |||||
| @Override | |||||
| public void onCloseWindow (WebView window) | |||||
| { | |||||
| webViewCloseWindowRequest (host, window); | |||||
| } | |||||
| @Override | |||||
| public boolean onCreateWindow (WebView view, boolean isDialog, | |||||
| boolean isUserGesture, Message resultMsg) | |||||
| { | |||||
| webViewCreateWindowRequest (host, view); | |||||
| return false; | |||||
| } | |||||
| private native void webViewCloseWindowRequest (long host, WebView view); | |||||
| private native void webViewCreateWindowRequest (long host, WebView view); | |||||
| private long host; | |||||
| private final Object hostLock = new Object (); | |||||
| } | |||||
| } | |||||
| package com.roli.juce; | |||||
| import android.graphics.Bitmap; | |||||
| import android.net.http.SslError; | |||||
| import android.os.Message; | |||||
| import android.webkit.WebResourceResponse; | |||||
| import android.webkit.WebView; | |||||
| import android.webkit.WebViewClient; | |||||
| import android.webkit.SslErrorHandler; | |||||
| import android.webkit.WebChromeClient; | |||||
| //============================================================================== | |||||
| public class JuceWebView | |||||
| { | |||||
| static public class Client extends WebViewClient | |||||
| { | |||||
| public Client (long hostToUse) | |||||
| { | |||||
| host = hostToUse; | |||||
| } | |||||
| public void hostDeleted () | |||||
| { | |||||
| synchronized (hostLock) | |||||
| { | |||||
| host = 0; | |||||
| } | |||||
| } | |||||
| public void onPageFinished (WebView view, String url) | |||||
| { | |||||
| if (host == 0) | |||||
| return; | |||||
| webViewPageLoadFinished (host, view, url); | |||||
| } | |||||
| public void onReceivedSslError (WebView view, SslErrorHandler handler, SslError error) | |||||
| { | |||||
| if (host == 0) | |||||
| return; | |||||
| webViewReceivedSslError (host, view, handler, error); | |||||
| } | |||||
| public void onPageStarted (WebView view, String url, Bitmap favicon) | |||||
| { | |||||
| if (host != 0) | |||||
| webViewPageLoadStarted (host, view, url); | |||||
| } | |||||
| public WebResourceResponse shouldInterceptRequest (WebView view, String url) | |||||
| { | |||||
| synchronized (hostLock) | |||||
| { | |||||
| if (host != 0) | |||||
| { | |||||
| boolean shouldLoad = webViewPageLoadStarted (host, view, url); | |||||
| if (shouldLoad) | |||||
| return null; | |||||
| } | |||||
| } | |||||
| return new WebResourceResponse ("text/html", null, null); | |||||
| } | |||||
| private native boolean webViewPageLoadStarted (long host, WebView view, String url); | |||||
| private native void webViewPageLoadFinished (long host, WebView view, String url); | |||||
| private native void webViewReceivedSslError (long host, WebView view, SslErrorHandler handler, SslError error); | |||||
| private long host; | |||||
| private final Object hostLock = new Object (); | |||||
| } | |||||
| static public class ChromeClient extends WebChromeClient | |||||
| { | |||||
| public ChromeClient (long hostToUse) | |||||
| { | |||||
| host = hostToUse; | |||||
| } | |||||
| @Override | |||||
| public void onCloseWindow (WebView window) | |||||
| { | |||||
| webViewCloseWindowRequest (host, window); | |||||
| } | |||||
| @Override | |||||
| public boolean onCreateWindow (WebView view, boolean isDialog, | |||||
| boolean isUserGesture, Message resultMsg) | |||||
| { | |||||
| webViewCreateWindowRequest (host, view); | |||||
| return false; | |||||
| } | |||||
| private native void webViewCloseWindowRequest (long host, WebView view); | |||||
| private native void webViewCreateWindowRequest (long host, WebView view); | |||||
| private long host; | |||||
| private final Object hostLock = new Object (); | |||||
| } | |||||
| } | |||||
| @@ -1,56 +1,56 @@ | |||||
| package com.roli.juce; | |||||
| import android.content.Context; | |||||
| import android.graphics.Canvas; | |||||
| import android.view.SurfaceView; | |||||
| public class JuceOpenGLView extends SurfaceView | |||||
| { | |||||
| private long host = 0; | |||||
| JuceOpenGLView (Context context, long nativeThis) | |||||
| { | |||||
| super (context); | |||||
| host = nativeThis; | |||||
| } | |||||
| public void cancel () | |||||
| { | |||||
| host = 0; | |||||
| } | |||||
| //============================================================================== | |||||
| @Override | |||||
| protected void onAttachedToWindow () | |||||
| { | |||||
| super.onAttachedToWindow (); | |||||
| if (host != 0) | |||||
| onAttchedWindowNative (host); | |||||
| } | |||||
| @Override | |||||
| protected void onDetachedFromWindow () | |||||
| { | |||||
| if (host != 0) | |||||
| onDetachedFromWindowNative (host); | |||||
| super.onDetachedFromWindow (); | |||||
| } | |||||
| @Override | |||||
| protected void dispatchDraw (Canvas canvas) | |||||
| { | |||||
| super.dispatchDraw (canvas); | |||||
| if (host != 0) | |||||
| onDrawNative (host, canvas); | |||||
| } | |||||
| //============================================================================== | |||||
| private native void onAttchedWindowNative (long nativeThis); | |||||
| private native void onDetachedFromWindowNative (long nativeThis); | |||||
| private native void onDrawNative (long nativeThis, Canvas canvas); | |||||
| } | |||||
| package com.roli.juce; | |||||
| import android.content.Context; | |||||
| import android.graphics.Canvas; | |||||
| import android.view.SurfaceView; | |||||
| public class JuceOpenGLView extends SurfaceView | |||||
| { | |||||
| private long host = 0; | |||||
| JuceOpenGLView (Context context, long nativeThis) | |||||
| { | |||||
| super (context); | |||||
| host = nativeThis; | |||||
| } | |||||
| public void cancel () | |||||
| { | |||||
| host = 0; | |||||
| } | |||||
| //============================================================================== | |||||
| @Override | |||||
| protected void onAttachedToWindow () | |||||
| { | |||||
| super.onAttachedToWindow (); | |||||
| if (host != 0) | |||||
| onAttchedWindowNative (host); | |||||
| } | |||||
| @Override | |||||
| protected void onDetachedFromWindow () | |||||
| { | |||||
| if (host != 0) | |||||
| onDetachedFromWindowNative (host); | |||||
| super.onDetachedFromWindow (); | |||||
| } | |||||
| @Override | |||||
| protected void dispatchDraw (Canvas canvas) | |||||
| { | |||||
| super.dispatchDraw (canvas); | |||||
| if (host != 0) | |||||
| onDrawNative (host, canvas); | |||||
| } | |||||
| //============================================================================== | |||||
| private native void onAttchedWindowNative (long nativeThis); | |||||
| private native void onDetachedFromWindowNative (long nativeThis); | |||||
| private native void onDrawNative (long nativeThis, Canvas canvas); | |||||
| } | |||||
| @@ -1,65 +1,65 @@ | |||||
| package com.roli.juce; | |||||
| import android.hardware.camera2.CameraCaptureSession; | |||||
| import android.hardware.camera2.CaptureRequest; | |||||
| import android.hardware.camera2.TotalCaptureResult; | |||||
| import android.hardware.camera2.CaptureFailure; | |||||
| import android.hardware.camera2.CaptureResult; | |||||
| public class CameraCaptureSessionCaptureCallback extends CameraCaptureSession.CaptureCallback | |||||
| { | |||||
| private native void cameraCaptureSessionCaptureCompleted (long host, boolean isPreview, CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result); | |||||
| private native void cameraCaptureSessionCaptureFailed (long host, boolean isPreview, CameraCaptureSession session, CaptureRequest request, CaptureFailure failure); | |||||
| private native void cameraCaptureSessionCaptureProgressed (long host, boolean isPreview, CameraCaptureSession session, CaptureRequest request, CaptureResult partialResult); | |||||
| private native void cameraCaptureSessionCaptureStarted (long host, boolean isPreview, CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber); | |||||
| private native void cameraCaptureSessionCaptureSequenceAborted (long host, boolean isPreview, CameraCaptureSession session, int sequenceId); | |||||
| private native void cameraCaptureSessionCaptureSequenceCompleted (long host, boolean isPreview, CameraCaptureSession session, int sequenceId, long frameNumber); | |||||
| CameraCaptureSessionCaptureCallback (long hostToUse, boolean shouldBePreview) | |||||
| { | |||||
| host = hostToUse; | |||||
| preview = shouldBePreview; | |||||
| } | |||||
| @Override | |||||
| public void onCaptureCompleted (CameraCaptureSession session, CaptureRequest request, | |||||
| TotalCaptureResult result) | |||||
| { | |||||
| cameraCaptureSessionCaptureCompleted (host, preview, session, request, result); | |||||
| } | |||||
| @Override | |||||
| public void onCaptureFailed (CameraCaptureSession session, CaptureRequest request, CaptureFailure failure) | |||||
| { | |||||
| cameraCaptureSessionCaptureFailed (host, preview, session, request, failure); | |||||
| } | |||||
| @Override | |||||
| public void onCaptureProgressed (CameraCaptureSession session, CaptureRequest request, | |||||
| CaptureResult partialResult) | |||||
| { | |||||
| cameraCaptureSessionCaptureProgressed (host, preview, session, request, partialResult); | |||||
| } | |||||
| @Override | |||||
| public void onCaptureSequenceAborted (CameraCaptureSession session, int sequenceId) | |||||
| { | |||||
| cameraCaptureSessionCaptureSequenceAborted (host, preview, session, sequenceId); | |||||
| } | |||||
| @Override | |||||
| public void onCaptureSequenceCompleted (CameraCaptureSession session, int sequenceId, long frameNumber) | |||||
| { | |||||
| cameraCaptureSessionCaptureSequenceCompleted (host, preview, session, sequenceId, frameNumber); | |||||
| } | |||||
| @Override | |||||
| public void onCaptureStarted (CameraCaptureSession session, CaptureRequest request, long timestamp, | |||||
| long frameNumber) | |||||
| { | |||||
| cameraCaptureSessionCaptureStarted (host, preview, session, request, timestamp, frameNumber); | |||||
| } | |||||
| private long host; | |||||
| private boolean preview; | |||||
| } | |||||
| package com.roli.juce; | |||||
| import android.hardware.camera2.CameraCaptureSession; | |||||
| import android.hardware.camera2.CaptureRequest; | |||||
| import android.hardware.camera2.TotalCaptureResult; | |||||
| import android.hardware.camera2.CaptureFailure; | |||||
| import android.hardware.camera2.CaptureResult; | |||||
| public class CameraCaptureSessionCaptureCallback extends CameraCaptureSession.CaptureCallback | |||||
| { | |||||
| private native void cameraCaptureSessionCaptureCompleted (long host, boolean isPreview, CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result); | |||||
| private native void cameraCaptureSessionCaptureFailed (long host, boolean isPreview, CameraCaptureSession session, CaptureRequest request, CaptureFailure failure); | |||||
| private native void cameraCaptureSessionCaptureProgressed (long host, boolean isPreview, CameraCaptureSession session, CaptureRequest request, CaptureResult partialResult); | |||||
| private native void cameraCaptureSessionCaptureStarted (long host, boolean isPreview, CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber); | |||||
| private native void cameraCaptureSessionCaptureSequenceAborted (long host, boolean isPreview, CameraCaptureSession session, int sequenceId); | |||||
| private native void cameraCaptureSessionCaptureSequenceCompleted (long host, boolean isPreview, CameraCaptureSession session, int sequenceId, long frameNumber); | |||||
| CameraCaptureSessionCaptureCallback (long hostToUse, boolean shouldBePreview) | |||||
| { | |||||
| host = hostToUse; | |||||
| preview = shouldBePreview; | |||||
| } | |||||
| @Override | |||||
| public void onCaptureCompleted (CameraCaptureSession session, CaptureRequest request, | |||||
| TotalCaptureResult result) | |||||
| { | |||||
| cameraCaptureSessionCaptureCompleted (host, preview, session, request, result); | |||||
| } | |||||
| @Override | |||||
| public void onCaptureFailed (CameraCaptureSession session, CaptureRequest request, CaptureFailure failure) | |||||
| { | |||||
| cameraCaptureSessionCaptureFailed (host, preview, session, request, failure); | |||||
| } | |||||
| @Override | |||||
| public void onCaptureProgressed (CameraCaptureSession session, CaptureRequest request, | |||||
| CaptureResult partialResult) | |||||
| { | |||||
| cameraCaptureSessionCaptureProgressed (host, preview, session, request, partialResult); | |||||
| } | |||||
| @Override | |||||
| public void onCaptureSequenceAborted (CameraCaptureSession session, int sequenceId) | |||||
| { | |||||
| cameraCaptureSessionCaptureSequenceAborted (host, preview, session, sequenceId); | |||||
| } | |||||
| @Override | |||||
| public void onCaptureSequenceCompleted (CameraCaptureSession session, int sequenceId, long frameNumber) | |||||
| { | |||||
| cameraCaptureSessionCaptureSequenceCompleted (host, preview, session, sequenceId, frameNumber); | |||||
| } | |||||
| @Override | |||||
| public void onCaptureStarted (CameraCaptureSession session, CaptureRequest request, long timestamp, | |||||
| long frameNumber) | |||||
| { | |||||
| cameraCaptureSessionCaptureStarted (host, preview, session, request, timestamp, frameNumber); | |||||
| } | |||||
| private long host; | |||||
| private boolean preview; | |||||
| } | |||||
| @@ -1,53 +1,53 @@ | |||||
| package com.roli.juce; | |||||
| import android.hardware.camera2.CameraCaptureSession; | |||||
| public class CameraCaptureSessionStateCallback extends CameraCaptureSession.StateCallback | |||||
| { | |||||
| private native void cameraCaptureSessionActive (long host, CameraCaptureSession session); | |||||
| private native void cameraCaptureSessionClosed (long host, CameraCaptureSession session); | |||||
| private native void cameraCaptureSessionConfigureFailed (long host, CameraCaptureSession session); | |||||
| private native void cameraCaptureSessionConfigured (long host, CameraCaptureSession session); | |||||
| private native void cameraCaptureSessionReady (long host, CameraCaptureSession session); | |||||
| CameraCaptureSessionStateCallback (long hostToUse) | |||||
| { | |||||
| host = hostToUse; | |||||
| } | |||||
| @Override | |||||
| public void onActive (CameraCaptureSession session) | |||||
| { | |||||
| cameraCaptureSessionActive (host, session); | |||||
| } | |||||
| @Override | |||||
| public void onClosed (CameraCaptureSession session) | |||||
| { | |||||
| cameraCaptureSessionClosed (host, session); | |||||
| } | |||||
| @Override | |||||
| public void onConfigureFailed (CameraCaptureSession session) | |||||
| { | |||||
| cameraCaptureSessionConfigureFailed (host, session); | |||||
| } | |||||
| @Override | |||||
| public void onConfigured (CameraCaptureSession session) | |||||
| { | |||||
| cameraCaptureSessionConfigured (host, session); | |||||
| } | |||||
| @Override | |||||
| public void onReady (CameraCaptureSession session) | |||||
| { | |||||
| cameraCaptureSessionReady (host, session); | |||||
| } | |||||
| private long host; | |||||
| } | |||||
| package com.roli.juce; | |||||
| import android.hardware.camera2.CameraCaptureSession; | |||||
| public class CameraCaptureSessionStateCallback extends CameraCaptureSession.StateCallback | |||||
| { | |||||
| private native void cameraCaptureSessionActive (long host, CameraCaptureSession session); | |||||
| private native void cameraCaptureSessionClosed (long host, CameraCaptureSession session); | |||||
| private native void cameraCaptureSessionConfigureFailed (long host, CameraCaptureSession session); | |||||
| private native void cameraCaptureSessionConfigured (long host, CameraCaptureSession session); | |||||
| private native void cameraCaptureSessionReady (long host, CameraCaptureSession session); | |||||
| CameraCaptureSessionStateCallback (long hostToUse) | |||||
| { | |||||
| host = hostToUse; | |||||
| } | |||||
| @Override | |||||
| public void onActive (CameraCaptureSession session) | |||||
| { | |||||
| cameraCaptureSessionActive (host, session); | |||||
| } | |||||
| @Override | |||||
| public void onClosed (CameraCaptureSession session) | |||||
| { | |||||
| cameraCaptureSessionClosed (host, session); | |||||
| } | |||||
| @Override | |||||
| public void onConfigureFailed (CameraCaptureSession session) | |||||
| { | |||||
| cameraCaptureSessionConfigureFailed (host, session); | |||||
| } | |||||
| @Override | |||||
| public void onConfigured (CameraCaptureSession session) | |||||
| { | |||||
| cameraCaptureSessionConfigured (host, session); | |||||
| } | |||||
| @Override | |||||
| public void onReady (CameraCaptureSession session) | |||||
| { | |||||
| cameraCaptureSessionReady (host, session); | |||||
| } | |||||
| private long host; | |||||
| } | |||||
| @@ -1,43 +1,42 @@ | |||||
| package com.roli.juce; | |||||
| import android.hardware.camera2.CameraDevice; | |||||
| public class CameraDeviceStateCallback extends CameraDevice.StateCallback | |||||
| { | |||||
| private native void cameraDeviceStateClosed (long host, CameraDevice camera); | |||||
| private native void cameraDeviceStateDisconnected (long host, CameraDevice camera); | |||||
| private native void cameraDeviceStateError (long host, CameraDevice camera, int error); | |||||
| private native void cameraDeviceStateOpened (long host, CameraDevice camera); | |||||
| CameraDeviceStateCallback (long hostToUse) | |||||
| { | |||||
| host = hostToUse; | |||||
| } | |||||
| @Override | |||||
| public void onClosed (CameraDevice camera) | |||||
| { | |||||
| cameraDeviceStateClosed (host, camera); | |||||
| } | |||||
| @Override | |||||
| public void onDisconnected (CameraDevice camera) | |||||
| { | |||||
| cameraDeviceStateDisconnected (host, camera); | |||||
| } | |||||
| @Override | |||||
| public void onError (CameraDevice camera, int error) | |||||
| { | |||||
| cameraDeviceStateError (host, camera, error); | |||||
| } | |||||
| @Override | |||||
| public void onOpened (CameraDevice camera) | |||||
| { | |||||
| cameraDeviceStateOpened (host, camera); | |||||
| } | |||||
| private long host; | |||||
| } | |||||
| package com.roli.juce; | |||||
| import android.hardware.camera2.CameraDevice; | |||||
| public class CameraDeviceStateCallback extends CameraDevice.StateCallback | |||||
| { | |||||
| private native void cameraDeviceStateClosed (long host, CameraDevice camera); | |||||
| private native void cameraDeviceStateDisconnected (long host, CameraDevice camera); | |||||
| private native void cameraDeviceStateError (long host, CameraDevice camera, int error); | |||||
| private native void cameraDeviceStateOpened (long host, CameraDevice camera); | |||||
| CameraDeviceStateCallback (long hostToUse) | |||||
| { | |||||
| host = hostToUse; | |||||
| } | |||||
| @Override | |||||
| public void onClosed (CameraDevice camera) | |||||
| { | |||||
| cameraDeviceStateClosed (host, camera); | |||||
| } | |||||
| @Override | |||||
| public void onDisconnected (CameraDevice camera) | |||||
| { | |||||
| cameraDeviceStateDisconnected (host, camera); | |||||
| } | |||||
| @Override | |||||
| public void onError (CameraDevice camera, int error) | |||||
| { | |||||
| cameraDeviceStateError (host, camera, error); | |||||
| } | |||||
| @Override | |||||
| public void onOpened (CameraDevice camera) | |||||
| { | |||||
| cameraDeviceStateOpened (host, camera); | |||||
| } | |||||
| private long host; | |||||
| } | |||||
| @@ -1,24 +1,24 @@ | |||||
| package com.roli.juce; | |||||
| import android.view.OrientationEventListener; | |||||
| import android.content.Context; | |||||
| public class JuceOrientationEventListener extends OrientationEventListener | |||||
| { | |||||
| private native void deviceOrientationChanged (long host, int orientation); | |||||
| public JuceOrientationEventListener (long hostToUse, Context context, int rate) | |||||
| { | |||||
| super (context, rate); | |||||
| host = hostToUse; | |||||
| } | |||||
| @Override | |||||
| public void onOrientationChanged (int orientation) | |||||
| { | |||||
| deviceOrientationChanged (host, orientation); | |||||
| } | |||||
| private long host; | |||||
| } | |||||
| package com.roli.juce; | |||||
| import android.view.OrientationEventListener; | |||||
| import android.content.Context; | |||||
| public class JuceOrientationEventListener extends OrientationEventListener | |||||
| { | |||||
| private native void deviceOrientationChanged (long host, int orientation); | |||||
| public JuceOrientationEventListener (long hostToUse, Context context, int rate) | |||||
| { | |||||
| super (context, rate); | |||||
| host = hostToUse; | |||||
| } | |||||
| @Override | |||||
| public void onOrientationChanged (int orientation) | |||||
| { | |||||
| deviceOrientationChanged (host, orientation); | |||||
| } | |||||
| private long host; | |||||
| } | |||||
| @@ -1,53 +1,53 @@ | |||||
| package com.roli.juce; | |||||
| import android.media.session.MediaController; | |||||
| import android.media.session.MediaSession; | |||||
| import android.media.MediaMetadata; | |||||
| import android.media.session.PlaybackState; | |||||
| import java.util.List; | |||||
| //============================================================================== | |||||
| public class MediaControllerCallback extends MediaController.Callback | |||||
| { | |||||
| private native void mediaControllerAudioInfoChanged (long host, MediaController.PlaybackInfo info); | |||||
| private native void mediaControllerMetadataChanged (long host, MediaMetadata metadata); | |||||
| private native void mediaControllerPlaybackStateChanged (long host, PlaybackState state); | |||||
| private native void mediaControllerSessionDestroyed (long host); | |||||
| MediaControllerCallback (long hostToUse) | |||||
| { | |||||
| host = hostToUse; | |||||
| } | |||||
| @Override | |||||
| public void onAudioInfoChanged (MediaController.PlaybackInfo info) | |||||
| { | |||||
| mediaControllerAudioInfoChanged (host, info); | |||||
| } | |||||
| @Override | |||||
| public void onMetadataChanged (MediaMetadata metadata) | |||||
| { | |||||
| mediaControllerMetadataChanged (host, metadata); | |||||
| } | |||||
| @Override | |||||
| public void onPlaybackStateChanged (PlaybackState state) | |||||
| { | |||||
| mediaControllerPlaybackStateChanged (host, state); | |||||
| } | |||||
| @Override | |||||
| public void onQueueChanged (List<MediaSession.QueueItem> queue) | |||||
| { | |||||
| } | |||||
| @Override | |||||
| public void onSessionDestroyed () | |||||
| { | |||||
| mediaControllerSessionDestroyed (host); | |||||
| } | |||||
| private long host; | |||||
| } | |||||
| package com.roli.juce; | |||||
| import android.media.session.MediaController; | |||||
| import android.media.session.MediaSession; | |||||
| import android.media.MediaMetadata; | |||||
| import android.media.session.PlaybackState; | |||||
| import java.util.List; | |||||
| //============================================================================== | |||||
| public class MediaControllerCallback extends MediaController.Callback | |||||
| { | |||||
| private native void mediaControllerAudioInfoChanged (long host, MediaController.PlaybackInfo info); | |||||
| private native void mediaControllerMetadataChanged (long host, MediaMetadata metadata); | |||||
| private native void mediaControllerPlaybackStateChanged (long host, PlaybackState state); | |||||
| private native void mediaControllerSessionDestroyed (long host); | |||||
| MediaControllerCallback (long hostToUse) | |||||
| { | |||||
| host = hostToUse; | |||||
| } | |||||
| @Override | |||||
| public void onAudioInfoChanged (MediaController.PlaybackInfo info) | |||||
| { | |||||
| mediaControllerAudioInfoChanged (host, info); | |||||
| } | |||||
| @Override | |||||
| public void onMetadataChanged (MediaMetadata metadata) | |||||
| { | |||||
| mediaControllerMetadataChanged (host, metadata); | |||||
| } | |||||
| @Override | |||||
| public void onPlaybackStateChanged (PlaybackState state) | |||||
| { | |||||
| mediaControllerPlaybackStateChanged (host, state); | |||||
| } | |||||
| @Override | |||||
| public void onQueueChanged (List<MediaSession.QueueItem> queue) | |||||
| { | |||||
| } | |||||
| @Override | |||||
| public void onSessionDestroyed () | |||||
| { | |||||
| mediaControllerSessionDestroyed (host); | |||||
| } | |||||
| private long host; | |||||
| } | |||||
| @@ -1,78 +1,78 @@ | |||||
| package com.roli.juce; | |||||
| import android.media.session.MediaSession; | |||||
| import java.lang.String; | |||||
| import android.os.Bundle; | |||||
| import android.content.Intent; | |||||
| import java.util.List; | |||||
| //============================================================================== | |||||
| public class MediaSessionCallback extends MediaSession.Callback | |||||
| { | |||||
| private native void mediaSessionPause (long host); | |||||
| private native void mediaSessionPlay (long host); | |||||
| private native void mediaSessionPlayFromMediaId (long host, String mediaId, Bundle extras); | |||||
| private native void mediaSessionSeekTo (long host, long pos); | |||||
| private native void mediaSessionStop (long host); | |||||
| MediaSessionCallback (long hostToUse) | |||||
| { | |||||
| host = hostToUse; | |||||
| } | |||||
| @Override | |||||
| public void onPause () | |||||
| { | |||||
| mediaSessionPause (host); | |||||
| } | |||||
| @Override | |||||
| public void onPlay () | |||||
| { | |||||
| mediaSessionPlay (host); | |||||
| } | |||||
| @Override | |||||
| public void onPlayFromMediaId (String mediaId, Bundle extras) | |||||
| { | |||||
| mediaSessionPlayFromMediaId (host, mediaId, extras); | |||||
| } | |||||
| @Override | |||||
| public void onSeekTo (long pos) | |||||
| { | |||||
| mediaSessionSeekTo (host, pos); | |||||
| } | |||||
| @Override | |||||
| public void onStop () | |||||
| { | |||||
| mediaSessionStop (host); | |||||
| } | |||||
| @Override | |||||
| public void onFastForward () {} | |||||
| @Override | |||||
| public boolean onMediaButtonEvent (Intent mediaButtonIntent) | |||||
| { | |||||
| return true; | |||||
| } | |||||
| @Override | |||||
| public void onRewind () {} | |||||
| @Override | |||||
| public void onSkipToNext () {} | |||||
| @Override | |||||
| public void onSkipToPrevious () {} | |||||
| @Override | |||||
| public void onSkipToQueueItem (long id) {} | |||||
| private long host; | |||||
| } | |||||
| package com.roli.juce; | |||||
| import android.media.session.MediaSession; | |||||
| import java.lang.String; | |||||
| import android.os.Bundle; | |||||
| import android.content.Intent; | |||||
| import java.util.List; | |||||
| //============================================================================== | |||||
| public class MediaSessionCallback extends MediaSession.Callback | |||||
| { | |||||
| private native void mediaSessionPause (long host); | |||||
| private native void mediaSessionPlay (long host); | |||||
| private native void mediaSessionPlayFromMediaId (long host, String mediaId, Bundle extras); | |||||
| private native void mediaSessionSeekTo (long host, long pos); | |||||
| private native void mediaSessionStop (long host); | |||||
| MediaSessionCallback (long hostToUse) | |||||
| { | |||||
| host = hostToUse; | |||||
| } | |||||
| @Override | |||||
| public void onPause () | |||||
| { | |||||
| mediaSessionPause (host); | |||||
| } | |||||
| @Override | |||||
| public void onPlay () | |||||
| { | |||||
| mediaSessionPlay (host); | |||||
| } | |||||
| @Override | |||||
| public void onPlayFromMediaId (String mediaId, Bundle extras) | |||||
| { | |||||
| mediaSessionPlayFromMediaId (host, mediaId, extras); | |||||
| } | |||||
| @Override | |||||
| public void onSeekTo (long pos) | |||||
| { | |||||
| mediaSessionSeekTo (host, pos); | |||||
| } | |||||
| @Override | |||||
| public void onStop () | |||||
| { | |||||
| mediaSessionStop (host); | |||||
| } | |||||
| @Override | |||||
| public void onFastForward () {} | |||||
| @Override | |||||
| public boolean onMediaButtonEvent (Intent mediaButtonIntent) | |||||
| { | |||||
| return true; | |||||
| } | |||||
| @Override | |||||
| public void onRewind () {} | |||||
| @Override | |||||
| public void onSkipToNext () {} | |||||
| @Override | |||||
| public void onSkipToPrevious () {} | |||||
| @Override | |||||
| public void onSkipToQueueItem (long id) {} | |||||
| private long host; | |||||
| } | |||||
| @@ -1,37 +1,37 @@ | |||||
| package com.roli.juce; | |||||
| import android.database.ContentObserver; | |||||
| import android.app.Activity; | |||||
| import android.net.Uri; | |||||
| //============================================================================== | |||||
| public class SystemVolumeObserver extends ContentObserver | |||||
| { | |||||
| private native void mediaSessionSystemVolumeChanged (long host); | |||||
| SystemVolumeObserver (Activity activityToUse, long hostToUse) | |||||
| { | |||||
| super (null); | |||||
| activity = activityToUse; | |||||
| host = hostToUse; | |||||
| } | |||||
| void setEnabled (boolean shouldBeEnabled) | |||||
| { | |||||
| if (shouldBeEnabled) | |||||
| activity.getApplicationContext ().getContentResolver ().registerContentObserver (android.provider.Settings.System.CONTENT_URI, true, this); | |||||
| else | |||||
| activity.getApplicationContext ().getContentResolver ().unregisterContentObserver (this); | |||||
| } | |||||
| @Override | |||||
| public void onChange (boolean selfChange, Uri uri) | |||||
| { | |||||
| if (uri.toString ().startsWith ("content://settings/system/volume_music")) | |||||
| mediaSessionSystemVolumeChanged (host); | |||||
| } | |||||
| private Activity activity; | |||||
| private long host; | |||||
| } | |||||
| package com.roli.juce; | |||||
| import android.database.ContentObserver; | |||||
| import android.app.Activity; | |||||
| import android.net.Uri; | |||||
| //============================================================================== | |||||
| public class SystemVolumeObserver extends ContentObserver | |||||
| { | |||||
| private native void mediaSessionSystemVolumeChanged (long host); | |||||
| SystemVolumeObserver (Activity activityToUse, long hostToUse) | |||||
| { | |||||
| super (null); | |||||
| activity = activityToUse; | |||||
| host = hostToUse; | |||||
| } | |||||
| void setEnabled (boolean shouldBeEnabled) | |||||
| { | |||||
| if (shouldBeEnabled) | |||||
| activity.getApplicationContext ().getContentResolver ().registerContentObserver (android.provider.Settings.System.CONTENT_URI, true, this); | |||||
| else | |||||
| activity.getApplicationContext ().getContentResolver ().unregisterContentObserver (this); | |||||
| } | |||||
| @Override | |||||
| public void onChange (boolean selfChange, Uri uri) | |||||
| { | |||||
| if (uri.toString ().startsWith ("content://settings/system/volume_music")) | |||||
| mediaSessionSystemVolumeChanged (host); | |||||
| } | |||||
| private Activity activity; | |||||
| private long host; | |||||
| } | |||||