package info.guardianproject.iocipher.player;
import java.io.IOException;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.Resources;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.net.Uri;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.View;
import android.widget.MediaController;
import android.widget.VideoView;
public class MjpegVideoView extends VideoView {
// settable by the client
private Uri mUri;
// All the stuff we need for playing and showing a video
private SurfaceHolder mSurfaceHolder = null;
private MediaPlayer mMediaPlayer = null;
private boolean mIsPrepared;
private int mVideoWidth;
private int mVideoHeight;
private int mSurfaceWidth;
private int mSurfaceHeight;
private MediaController mMediaController;
private OnCompletionListener mOnCompletionListener;
private MediaPlayer.OnPreparedListener mOnPreparedListener;
private int mCurrentBufferPercentage;
private OnErrorListener mOnErrorListener;
private boolean mStartWhenPrepared;
private int mSeekWhenPrepared;
private Context mContext;
private MjpegInputStream mIn = null;
public MjpegVideoView(Context context) {
super(context);
}
public MjpegVideoView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MjpegVideoView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
private void openVideo() {
if (mUri == null || mSurfaceHolder == null) {
// not ready for playback just yet, will try again later
return;
}
if (mMediaPlayer != null) {
mMediaPlayer.reset();
mMediaPlayer.release();
mMediaPlayer = null;
}
try {
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setOnPreparedListener(mPreparedListener);
mIsPrepared = false;
mMediaPlayer.setOnCompletionListener(mCompletionListener);
mMediaPlayer.setOnErrorListener(mErrorListener);
mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
mCurrentBufferPercentage = 0;
mMediaPlayer.setDataSource(mContext, mUri);
mMediaPlayer.setDisplay(mSurfaceHolder);
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setScreenOnWhilePlaying(true);
mMediaPlayer.prepareAsync();
attachMediaController();
} catch (IOException ex) {
Log.w("VideoView", "Unable to open content: " + mUri, ex);
return;
} catch (IllegalArgumentException ex) {
Log.w("VideoView", "Unable to open content: " + mUri, ex);
return;
}
}
private void attachMediaController() {
if (mMediaPlayer != null && mMediaController != null) {
mMediaController.setMediaPlayer(this);
View anchorView = this.getParent() instanceof View ?
(View)this.getParent() : this;
mMediaController.setAnchorView(anchorView);
mMediaController.setEnabled(mIsPrepared);
}
}
MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
// briefly show the mediacontroller
mIsPrepared = true;
if (mOnPreparedListener != null) {
mOnPreparedListener.onPrepared(mMediaPlayer);
}
if (mMediaController != null) {
mMediaController.setEnabled(true);
}
mVideoWidth = mp.getVideoWidth();
mVideoHeight = mp.getVideoHeight();
if (mVideoWidth != 0 && mVideoHeight != 0) {
//Log.i("@@@@", "video size: " + mVideoWidth +"/"+ mVideoHeight);
getHolder().setFixedSize(mVideoWidth, mVideoHeight);
if (mSurfaceWidth == mVideoWidth && mSurfaceHeight == mVideoHeight) {
// We didn't actually change the size (it was already at the size
// we need), so we won't get a "surface changed" callback, so
// start the video here instead of in the callback.
if (mSeekWhenPrepared != 0) {
mMediaPlayer.seekTo(mSeekWhenPrepared);
}
if (mStartWhenPrepared) {
mMediaPlayer.start();
if (mMediaController != null) {
mMediaController.show();
}
} else if (!isPlaying() && (mSeekWhenPrepared != 0 || getCurrentPosition() > 0)) {
if (mMediaController != null) {
mMediaController.show(0); // show the media controls when we're paused into a video and make 'em stick.
}
}
}
} else {
Log.d("VideoView", "Couldn't get video size after prepare(): " +
mVideoWidth + "/" + mVideoHeight);
// The file was probably truncated or corrupt. Start anyway, so
// that we play whatever short snippet is there and then get
// the "playback completed" event.
if (mStartWhenPrepared) {
mMediaPlayer.start();
}
}
}
};
private MediaPlayer.OnCompletionListener mCompletionListener =
new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
if (mMediaController != null) {
mMediaController.hide();
}
if (mOnCompletionListener != null) {
mOnCompletionListener.onCompletion(mMediaPlayer);
}
}
};
private MediaPlayer.OnErrorListener mErrorListener =
new MediaPlayer.OnErrorListener() {
public boolean onError(MediaPlayer mp, int a, int b) {
Log.d("VideoView", "Error: " + a + "," + b);
if (mMediaController != null) {
mMediaController.hide();
}
/* If an error handler has been supplied, use it and finish. */
if (mOnErrorListener != null) {
if (mOnErrorListener.onError(mMediaPlayer, a, b)) {
return true;
}
}
/* Otherwise, pop up an error dialog so the user knows that
* something bad has happened. Only try and pop up the dialog
* if we're attached to a window. When we're going away and no
* longer have a window, don't bother showing the user an error.
*/
if (getWindowToken() != null) {
Resources r = mContext.getResources();
new AlertDialog.Builder(mContext)
// .setTitle(com.android.internal.R.string.VideoView_error_title)
// .setMessage(com.android.internal.R.string.VideoView_error_text_unknown)
// .setPositiveButton(com.android.internal.R.string.VideoView_error_button,
.setTitle("Video Error")
.setMessage("Video Error unknown")
.setPositiveButton("Positive",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
/* If we get here, there is no onError listener, so
* at least inform them that the video is over.
*/
if (mOnCompletionListener != null) {
mOnCompletionListener.onCompletion(mMediaPlayer);
}
}
})
.setCancelable(false)
.show();
}
return true;
}
};
private MediaPlayer.OnBufferingUpdateListener mBufferingUpdateListener =
new MediaPlayer.OnBufferingUpdateListener() {
public void onBufferingUpdate(MediaPlayer mp, int percent) {
mCurrentBufferPercentage = percent;
}
};
public void setSource(MjpegInputStream source) {
mIn = source;
start();
}
}