package info.guardianproject.iocipher.player;
import java.io.IOException;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.MediaController;
import android.widget.Toast;
import android.widget.MediaController.MediaPlayerControl;
public class MjpegView extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = "MjpegView";
public final static int SIZE_STANDARD = 1;
public final static int SIZE_BEST_FIT = 4;
public final static int SIZE_FULLSCREEN = 8;
//private MjpegViewThread thread;
private MjpegInputStream mIn = null;
//private boolean mRun = false;
private boolean mIsPrepared = false;
private boolean surfaceDone = false;
private MediaController mMediaController;
private boolean alreadyStarted = false;
private Context mContext;
private MjpegPlayer mPlayer;
/*
public class MjpegViewThread extends Thread {
private SurfaceHolder mSurfaceHolder;
private int frameCounter = 0;
private long start, fpsstart;
private long pause;
private Bitmap ovl;
private int ovlpostop = 5;
public MjpegViewThread(SurfaceHolder surfaceHolder, Context context) { mSurfaceHolder = surfaceHolder; }
private Rect destRect(int bmw, int bmh) {
int tempx;
int tempy;
if (displayMode == MjpegView.SIZE_STANDARD) {
tempx = (dispWidth / 2) - (bmw / 2);
tempy = (dispHeight / 2) - (bmh / 2);
return new Rect(tempx, tempy, bmw + tempx, bmh + tempy);
}
if (displayMode == MjpegView.SIZE_BEST_FIT) {
float bmasp = (float) bmw / (float) bmh;
bmw = dispWidth;
bmh = (int) (dispWidth / bmasp);
if (bmh > dispHeight) {
bmh = dispHeight;
bmw = (int) (dispHeight * bmasp);
}
tempx = (dispWidth / 2) - (bmw / 2);
tempy = (dispHeight / 2) - (bmh / 2);
return new Rect(tempx, tempy, bmw + tempx, bmh + tempy);
}
if (displayMode == MjpegView.SIZE_FULLSCREEN) return new Rect(0, 0, dispWidth, dispHeight);
return null;
}
public void setSurfaceSize(int width, int height) {
synchronized(mSurfaceHolder) {
dispWidth = width;
dispHeight = height;
}
}
private Bitmap makeOverlay(Paint p, String text) {
Rect b = new Rect();
p.getTextBounds(text, 0, text.length(), b);
int bwidth = b.width()+2;
int bheight = b.height()+2;
Bitmap bm = Bitmap.createBitmap(bwidth, bheight, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bm);
p.setColor(overlayBackgroundColor);
c.drawRect(0, 0, bwidth, bheight, p);
p.setColor(overlayTextColor);
c.drawText(text, -b.left+1, (bheight/2)-((p.ascent()+p.descent())/2)+1, p);
return bm;
}
private void drawOverlay(Canvas c, Paint p, Bitmap overlay) {
c.drawBitmap(overlay, 5, ovlpostop, p);
ovlpostop += 5 + overlay.getHeight();
}
public void run() {
start = System.currentTimeMillis();
fpsstart = System.currentTimeMillis();
Log.v("MjpegView", "Start at " + start);
PorterDuffXfermode mode = new PorterDuffXfermode(PorterDuff.Mode.DST_OVER);
Bitmap bm;
int left, top;
Rect destRect = null;
Canvas c = null;
Paint p = new Paint();
String fps = "";
while (mRun) {
if(surfaceDone) {
try {
c = mSurfaceHolder.lockCanvas();
synchronized (mSurfaceHolder) {
try {
ovlpostop = 5; //set start position (top) for overlay-table
if (state == STATE_PLAY) {
bm = mIn.readMjpegFrame();
destRect = destRect(bm.getWidth(),bm.getHeight());
c.drawColor(Color.BLACK);
c.drawBitmap(bm, null, destRect, p);
//*
if(showFps) {
//p.setXfermode(mode);
if(ovl != null) {
top = ((ovlPos & 1) == 1) ? destRect.top : destRect.bottom-ovl.getHeight();
left = ((ovlPos & 8) == 8) ? destRect.left : destRect.right -ovl.getWidth();
//c.drawBitmap(ovl, left, top, p);
drawOverlay(c, p, ovl);
}
//p.setXfermode(null);
frameCounter++;
if((System.currentTimeMillis() - start) >= 1000) {
fps = String.valueOf(frameCounter)+"fps";
Log.v(TAG, "FPS: " + fps);
frameCounter = 0;
fpsstart = System.currentTimeMillis();
ovl = makeOverlay(overlayPaint, fps);
}
}
//*
}
else if (state == STATE_PAUSE){
String time = "T-" + (System.currentTimeMillis()-pause)/1000 + " sec";
Bitmap ovl1 = makeOverlay(overlayPaint, "PAUSED");
//c.drawBitmap(ovl1, 5, 5, p);
Bitmap ovl2 = makeOverlay(overlayPaint, time);
drawOverlay(c, p, ovl1);
drawOverlay(c, p, ovl2);
//c.drawBitmap(ovl1, 5, 5+2*ovl1.getHeight(), p);
}
setDuration(System.currentTimeMillis()-start);
} catch (IOException e) {}
}
} finally {
if (c != null) {
mSurfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
synchronized(mSurfaceHolder) {
c = mSurfaceHolder.lockCanvas();
c.drawColor(Color.BLACK);
mSurfaceHolder.unlockCanvasAndPost(c);
}
}
}
*/
private void init(Context context) {
mContext = context;
SurfaceHolder holder = getHolder();
holder.addCallback(this);
//thread = new MjpegViewThread(holder, context);
setFocusable(true);
mPlayer = new MjpegPlayer(holder, mContext, mIn);
mPlayer.setDisplay(getWidth(), getHeight(), MjpegView.SIZE_BEST_FIT);
mIsPrepared = true;
attachMediaController();
mPlayer.showFps(true);
}
public void startPlayback() {
if (alreadyStarted) {
Log.v(TAG, "Creating new MjpegPlayer (MjpegPlayer)");
//thread = new MjpegViewThread(holder, mContext);
init(mContext);
}
if(mIn != null) {
//mRun = true;
Log.v(TAG, "Starting Playback:");
alreadyStarted = true;
mPlayer.startPlayback();
//thread.start();
}
}
public void stopPlayback() {
//mRun = false;
mIsPrepared = false;
mPlayer.stopPlayback();
/*
boolean retry = true;
while(retry) {
try {
//thread.join();
retry = false;
} catch (InterruptedException e) {}
}*/
}
public MjpegView(Context context, AttributeSet attrs) { super(context, attrs); init(context); }
public void surfaceChanged(SurfaceHolder holder, int f, int w, int h) { mPlayer.setSurfaceSize(w, h); }
public void surfaceDestroyed(SurfaceHolder holder) {
surfaceDone = false;
stopPlayback();
}
public MjpegView(Context context) {
super(context);
init(context);
}
public void surfaceCreated(SurfaceHolder holder) {
surfaceDone = true;
}
public void showFps(boolean b) {
mPlayer.showFps(b);
}
public void setSource(MjpegInputStream source) {
mIn = source;
mPlayer.setSource(mIn);
}
/*
public void setOverlayPaint(Paint p) {
overlayPaint = p;
}
public void setOverlayTextColor(int c) {
overlayTextColor = c;
}
public void setOverlayBackgroundColor(int c) {
overlayBackgroundColor = c;
}
public void setOverlayPosition(int p) {
ovlPos = p;
}
*/
public void setMediaController(MediaController controller) {
if (mMediaController != null) {
mMediaController.hide();
}
mMediaController = controller;
attachMediaController();
//enable the MediaController. Without this the buttons will not work! (in the emulator...)
}
private View.OnClickListener next = new OnClickListener() {
public void onClick(View v) {
Log.v(TAG, "Clicked NEXT");
mPlayer.seekToLive();
}
};
private View.OnClickListener prev = new OnClickListener() {
public void onClick(View v) {
Log.v(TAG, "Clicked PREV");
mPlayer.seekToBegin();
}
};
private void attachMediaController() {
if (mMediaController != null) {
mMediaController.setMediaPlayer(mPlayer);
View anchorView = this.getParent() instanceof View ?
(View)this.getParent() : this;
mMediaController.setAnchorView(anchorView);
mMediaController.setEnabled(mIsPrepared);
mMediaController.setPrevNextListeners(next, prev);
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (mIsPrepared && mMediaController != null) {
toggleMediaControlsVisiblity();
}
return false;
}
@Override
public boolean onTrackballEvent(MotionEvent ev) {
if (mIsPrepared && mMediaController != null) {
toggleMediaControlsVisiblity();
}
return false;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if (mIsPrepared &&
keyCode != KeyEvent.KEYCODE_BACK &&
keyCode != KeyEvent.KEYCODE_VOLUME_UP &&
keyCode != KeyEvent.KEYCODE_VOLUME_DOWN &&
keyCode != KeyEvent.KEYCODE_MENU &&
keyCode != KeyEvent.KEYCODE_CALL &&
keyCode != KeyEvent.KEYCODE_ENDCALL &&
//mMediaPlayer != null &&
mMediaController != null) {
if (keyCode == KeyEvent.KEYCODE_HEADSETHOOK) {
if (mPlayer.isPlaying()) {
mPlayer.pause();
mMediaController.show();
} else {
start();
mMediaController.hide();
}
return true;
} else {
toggleMediaControlsVisiblity();
}
}
return super.onKeyDown(keyCode, event);
}
private void toggleMediaControlsVisiblity() {
if (mMediaController.isShowing()) {
mMediaController.hide();
} else {
mMediaController.show();
}
}
// public void pause() {
// mPlayer.pause();
//
// //this.thread.pause = System.currentTimeMillis();
// Log.v(TAG, "Pause Button pressed");
// /*
// if (isPlaying() && state==STATE_PLAY) {
// state = STATE_PAUSE;
// Log.v(TAG, "new state: pause");
// }
// else {
// state = STATE_PLAY;
// Log.v(TAG, "new state: play");
// }
// */
//
// }
public void start() {
//Toast.makeText(mContext, "START!", Toast.LENGTH_SHORT).show();
Log.v(TAG, "START!");
startPlayback();
}
public boolean isPlaying() {
return mPlayer.isPlaying();
}
}