/*
* Protocoder
* A prototyping platform for Android devices
*
* Victor Diaz Barrales victormdb@gmail.com
*
* Copyright (C) 2014 Victor Diaz
* Copyright (C) 2013 Motorola Mobility LLC
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software
* is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
package org.protocoderrunner.apprunner.api;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Typeface;
import android.media.FaceDetector;
import android.os.Handler;
import android.util.Base64;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AnticipateInterpolator;
import android.view.animation.AnticipateOvershootInterpolator;
import android.view.animation.BounceInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import org.protocoderrunner.apidoc.annotation.APIMethod;
import org.protocoderrunner.apidoc.annotation.APIParam;
import org.protocoderrunner.apprunner.AppRunnerSettings;
import org.protocoderrunner.apprunner.PInterface;
import org.protocoderrunner.apprunner.ProtocoderScript;
import org.protocoderrunner.apprunner.api.other.SignalUtils;
import org.protocoderrunner.sensors.WhatIsRunning;
import org.protocoderrunner.utils.MLog;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
public class PUtil extends PInterface {
private final Handler handler;
ArrayList<Runnable> rl = new ArrayList<Runnable>();
public PUtil(Context a) {
super(a);
WhatIsRunning.getInstance().add(this);
handler = new Handler();
}
// --------- getRequest ---------//
interface getRequestCB {
void event(int eventType, String responseString);
}
public class Looper {
Runnable task;
public int delay;
boolean paused = false;
Looper(final int duration, final LooperCB callbackkfn) {
delay = duration;
task = new Runnable() {
@Override
public void run() {
callbackkfn.event();
if (!paused) {
handler.postDelayed(this, delay);
}
}
};
handler.post(task);
rl.add(task);
}
@ProtocoderScript
@APIMethod(description = "Change the current delay to a new one", example = "")
@APIParam(params = { "duration" })
public void setDelay(int duration) {
this.delay = duration;
}
@ProtocoderScript
@APIMethod(description = "Pause the looper", example = "")
@APIParam(params = { "boolean" })
public void pause(boolean b) {
this.paused = b;
if (b == false) {
handler.postDelayed(task, delay);
}
}
@ProtocoderScript
@APIMethod(description = "Stop the looper", example = "")
public void stop() {
handler.removeCallbacks(task);
}
}
// --------- Looper ---------//
public interface LooperCB {
void event();
}
@ProtocoderScript
@APIMethod(description = "Creates a looper that loops a given function every 'n' milliseconds", example = "")
@APIParam(params = { "milliseconds", "function()" })
public Looper loop(final int duration, final LooperCB callbackkfn) {
return new Looper(duration, callbackkfn);
}
// --------- delay ---------//
public interface delayCB {
void event();
}
@ProtocoderScript
@APIMethod(description = "Delay a given function 'n' milliseconds", example = "")
@APIParam(params = { "milliseconds", "function()" })
public void delay(final int duration, final delayCB fn) {
Runnable task = new Runnable() {
@Override
public void run() {
// handler.postDelayed(this, duration);
fn.event();
handler.removeCallbacks(this);
rl.remove(this);
}
};
handler.postDelayed(task, duration);
rl.add(task);
}
@ProtocoderScript
@APIMethod(description = "Stop all timers", example = "")
@APIParam(params = { "" })
public void stopAllTimers() {
Iterator<Runnable> ir = rl.iterator();
while (ir.hasNext()) {
handler.removeCallbacks(ir.next());
// handler.post(ir.next());
}
}
public void stop() {
stopAllTimers();
}
// http://stackoverflow.com/questions/4605527/converting-pixels-to-dp
@ProtocoderScript
@APIMethod(description = "Convert given dp to pixels", example = "")
@APIParam(params = { "" })
public float dpToPixels(float dp) {
Resources resources = a.get().getResources();
DisplayMetrics metrics = resources.getDisplayMetrics();
float px = dp * (metrics.densityDpi / 160f);
return px;
}
@ProtocoderScript
@APIMethod(description = "Convert given px to dp", example = "")
@APIParam(params = { "" })
public float pixelsToDp(float px) {
Resources resources = a.get().getResources();
DisplayMetrics metrics = resources.getDisplayMetrics();
float dp = px / (metrics.densityDpi / 160f);
return dp;
}
@ProtocoderScript
@APIMethod(description = "Convert given mm to pixels", example = "")
@APIParam(params = { "" })
public float mmToPixels(float mm) {
float px = TypedValue
.applyDimension(TypedValue.COMPLEX_UNIT_MM, mm, a.get().getResources().getDisplayMetrics());
return px;
}
@ProtocoderScript
@APIMethod(description = "Convert given pixels to mm", example = "")
@APIParam(params = { "" })
public float pixelsToMm(int px) {
float onepx = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 1, a.get().getResources()
.getDisplayMetrics());
return px * onepx;
}
public interface AnimCB {
void event(float data);
}
@ProtocoderScript
@APIMethod(description = "Animate a variable from min to max in a specified time using 'bounce', 'linear', 'decelerate', 'anticipate', 'aovershoot', 'accelerate' type ", example = "")
@APIParam(params = { "" })
public ValueAnimator anim(String type, float min, float max, int time, final AnimCB callback) {
TimeInterpolator interpolator = null;
if (type.equals("bounce")) {
interpolator = new BounceInterpolator();
} else if (type.equals("linear")) {
interpolator = new LinearInterpolator();
} else if (type.equals("decelerate")) {
interpolator = new DecelerateInterpolator();
} else if (type.equals("anticipate")) {
interpolator = new AnticipateInterpolator();
} else if (type.equals("aovershoot")) {
interpolator = new AnticipateOvershootInterpolator();
} else {
interpolator = new AccelerateDecelerateInterpolator();
}
ValueAnimator va = ValueAnimator.ofFloat(min, max);
va.setDuration(time);
va.setInterpolator(interpolator);
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
Float value = (Float) animation.getAnimatedValue();
callback.event(value);
MLog.d(TAG, "val " + value + " " + animation.getAnimatedValue());
}
});
return va;
}
@ProtocoderScript
@APIMethod(description = "Parse a color and return and int representing it", example = "")
@APIParam(params = { "colorString" })
public int parseColor(String c) {
return Color.parseColor(c);
}
@ProtocoderScript
@APIMethod(description = "Loads a font", example = "")
@APIParam(params = { "fontFile" })
public Typeface loadFont(String fontName) {
return Typeface.createFromFile(AppRunnerSettings.get().project.getStoragePath() + File.separator + fontName);
}
@ProtocoderScript
@APIMethod(description = "Detect faces in a bitmap", example = "")
@APIParam(params = { "Bitmap", "numFaces" })
public int detectFaces(Bitmap bmp, int num_faces) {
FaceDetector face_detector = new FaceDetector(bmp.getWidth(), bmp.getHeight(), num_faces);
FaceDetector.Face[] faces = new FaceDetector.Face[num_faces];
int face_count = face_detector.findFaces(bmp, faces);
return face_count;
}
@ProtocoderScript
@APIMethod(description = "Converts byte array to bmp", example = "")
@APIParam(params = { "encodedImage" })
public Bitmap decodeBase64ToBitmap(String encodedImage) {
byte[] decodedString = Base64.decode(encodedImage, Base64.DEFAULT);
MLog.d(TAG, "bytes--> " + decodedString);
BitmapFactory.Options bitmap_options = new BitmapFactory.Options();
bitmap_options.inPreferredConfig = Bitmap.Config.RGB_565;
final Bitmap bitmap = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length, bitmap_options);
MLog.d(TAG, "bitmap --> " + bitmap);
return bitmap;
}
public SignalUtils signal(int n) {
return new SignalUtils(a.get(), n);
}
}