summaryrefslogtreecommitdiffstats
path: root/src/org/codeaurora/gallery3d/video
diff options
context:
space:
mode:
Diffstat (limited to 'src/org/codeaurora/gallery3d/video')
-rw-r--r--src/org/codeaurora/gallery3d/video/BookmarkActivity.java244
-rw-r--r--src/org/codeaurora/gallery3d/video/BookmarkEnhance.java138
-rw-r--r--src/org/codeaurora/gallery3d/video/BookmarkHooker.java76
-rwxr-xr-xsrc/org/codeaurora/gallery3d/video/CodeauroraVideoView.java1032
-rw-r--r--src/org/codeaurora/gallery3d/video/DmReceiver.java65
-rwxr-xr-xsrc/org/codeaurora/gallery3d/video/ExtensionHelper.java6
-rw-r--r--src/org/codeaurora/gallery3d/video/MovieTitleHelper.java108
-rwxr-xr-xsrc/org/codeaurora/gallery3d/video/SettingsActivity.java251
-rw-r--r--src/org/codeaurora/gallery3d/video/StreamingHooker.java78
9 files changed, 1997 insertions, 1 deletions
diff --git a/src/org/codeaurora/gallery3d/video/BookmarkActivity.java b/src/org/codeaurora/gallery3d/video/BookmarkActivity.java
new file mode 100644
index 000000000..ed653f63a
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/BookmarkActivity.java
@@ -0,0 +1,244 @@
+package org.codeaurora.gallery3d.video;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.content.Intent;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.AdapterView;
+import android.widget.AdapterView.AdapterContextMenuInfo;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.EditText;
+import android.widget.ListView;
+import android.widget.SimpleCursorAdapter;
+import android.widget.TextView;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.app.MovieActivity;
+
+public class BookmarkActivity extends Activity implements OnItemClickListener {
+ private static final String TAG = "BookmarkActivity";
+ private static final boolean LOG = true;
+
+ private BookmarkEnhance mBookmark;
+ private BookmarkAdapter mAdapter;
+ private Cursor mCursor;
+ private ListView mListView;
+ private TextView mEmptyView;
+
+ private static final int MENU_DELETE_ALL = 1;
+ private static final int MENU_DELETE_ONE = 2;
+ private static final int MENU_EDIT = 3;
+
+ public static final String KEY_LOGO_BITMAP = "logo-bitmap";
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.bookmark);
+
+ Bitmap logo = getIntent().getParcelableExtra(KEY_LOGO_BITMAP);
+ if (logo != null) {
+ getActionBar().setLogo(new BitmapDrawable(getResources(), logo));
+ }
+
+ mListView = (ListView) findViewById(android.R.id.list);
+ mEmptyView = (TextView) findViewById(android.R.id.empty);
+
+ mBookmark = new BookmarkEnhance(this);
+ mCursor = mBookmark.query();
+ mAdapter = new BookmarkAdapter(this, R.layout.bookmark_item, null, new String[] {},
+ new int[] {});
+ mListView.setEmptyView(mEmptyView);
+ mListView.setAdapter(mAdapter);
+ mAdapter.changeCursor(mCursor);
+
+ mListView.setOnItemClickListener(this);
+ registerForContextMenu(mListView);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ }
+
+ @Override
+ protected void onDestroy() {
+ if (mAdapter != null) {
+ mAdapter.changeCursor(null);
+ }
+ super.onDestroy();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(final Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ menu.add(0, MENU_DELETE_ALL, 0, R.string.delete_all)
+ .setIcon(android.R.drawable.ic_menu_delete);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(final MenuItem item) {
+ switch (item.getItemId()) {
+ case MENU_DELETE_ALL:
+ mBookmark.deleteAll();
+ return true;
+ default:
+ break;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ private class BookmarkAdapter extends SimpleCursorAdapter {
+
+ public BookmarkAdapter(final Context context, final int layout, final Cursor c,
+ final String[] from, final int[] to) {
+ super(context, layout, c, from, to);
+ }
+
+ @Override
+ public View newView(final Context context, final Cursor cursor, final ViewGroup parent) {
+ final View view = super.newView(context, cursor, parent);
+ final ViewHolder holder = new ViewHolder();
+ holder.mTitleView = (TextView) view.findViewById(R.id.title);
+ holder.mDataView = (TextView) view.findViewById(R.id.data);
+ view.setTag(holder);
+ return view;
+ }
+
+ @Override
+ public void bindView(final View view, final Context context, final Cursor cursor) {
+ final ViewHolder holder = (ViewHolder) view.getTag();
+ holder.mId = cursor.getLong(BookmarkEnhance.INDEX_ID);
+ holder.mTitle = cursor.getString(BookmarkEnhance.INDEX_TITLE);
+ holder.mData = cursor.getString(BookmarkEnhance.INDEX_DATA);
+ holder.mMimetype = cursor.getString(BookmarkEnhance.INDEX_MIME_TYPE);
+ holder.mTitleView.setText(holder.mTitle);
+ holder.mDataView.setText(holder.mData);
+ }
+
+ @Override
+ public void changeCursor(final Cursor c) {
+ super.changeCursor(c);
+ }
+
+ }
+
+ private class ViewHolder {
+ long mId;
+ String mTitle;
+ String mData;
+ String mMimetype;
+ TextView mTitleView;
+ TextView mDataView;
+ }
+
+ @Override
+ public void onItemClick(final AdapterView<?> parent, final View view, final int position,
+ final long id) {
+ final Object o = view.getTag();
+ if (o instanceof ViewHolder) {
+ final ViewHolder holder = (ViewHolder) o;
+ finish();
+ final Intent intent = new Intent(this, MovieActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ String mime = "video/*";
+ if (!(holder.mMimetype == null || "".equals(holder.mMimetype.trim()))) {
+ mime = holder.mMimetype;
+ }
+ intent.setDataAndType(Uri.parse(holder.mData), mime);
+ startActivity(intent);
+ }
+ if (LOG) {
+ Log.v(TAG, "onItemClick(" + position + ", " + id + ")");
+ }
+ }
+
+ @Override
+ public void onCreateContextMenu(final ContextMenu menu, final View v,
+ final ContextMenuInfo menuInfo) {
+ super.onCreateContextMenu(menu, v, menuInfo);
+ menu.add(0, MENU_DELETE_ONE, 0, R.string.delete);
+ menu.add(0, MENU_EDIT, 0, R.string.edit);
+ }
+
+ @Override
+ public boolean onContextItemSelected(final MenuItem item) {
+ final AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
+ switch (item.getItemId()) {
+ case MENU_DELETE_ONE:
+ mBookmark.delete(info.id);
+ return true;
+ case MENU_EDIT:
+ final Object obj = info.targetView.getTag();
+ if (obj instanceof ViewHolder) {
+ showEditDialog((ViewHolder) obj);
+ } else {
+ Log.w(TAG, "wrong context item info " + info);
+ }
+ return true;
+ default:
+ return super.onContextItemSelected(item);
+ }
+ }
+
+ private void showEditDialog(final ViewHolder holder) {
+ if (LOG) {
+ Log.v(TAG, "showEditDialog(" + holder + ")");
+ }
+ if (holder == null) {
+ return;
+ }
+ final LayoutInflater inflater = LayoutInflater.from(this);
+ final View v = inflater.inflate(R.layout.bookmark_edit_dialog, null);
+ final EditText titleView = (EditText) v.findViewById(R.id.title);
+ final EditText dataView = (EditText) v.findViewById(R.id.data);
+ titleView.setText(holder.mTitle);
+ dataView.setText(holder.mData);
+
+ final AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(R.string.edit);
+ builder.setView(v);
+ builder.setIcon(R.drawable.ic_menu_display_bookmark);
+ builder.setPositiveButton(android.R.string.ok, new OnClickListener() {
+
+ @Override
+ public void onClick(final DialogInterface dialog, final int which) {
+ mBookmark.update(holder.mId, titleView.getText().toString(),
+ dataView.getText().toString(), 0);
+ }
+
+ });
+ builder.setNegativeButton(android.R.string.cancel, null);
+ final AlertDialog dialog = builder.create();
+ dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
+ dialog.setInverseBackgroundForced(true);
+ dialog.show();
+ }
+}
diff --git a/src/org/codeaurora/gallery3d/video/BookmarkEnhance.java b/src/org/codeaurora/gallery3d/video/BookmarkEnhance.java
new file mode 100644
index 000000000..fc3ed9b0f
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/BookmarkEnhance.java
@@ -0,0 +1,138 @@
+package org.codeaurora.gallery3d.video;
+
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.util.Log;
+
+import com.android.gallery3d.R;
+
+public class BookmarkEnhance {
+ private static final String TAG = "BookmarkEnhance";
+ private static final boolean LOG = true;
+
+ private static final Uri BOOKMARK_URI = Uri.parse("content://media/internal/bookmark");
+
+ public static final String COLUMN_ID = "_id";
+ public static final String COLUMN_DATA = "_data";
+ public static final String COLUMN_TITLE = "_display_name";
+ public static final String COLUMN_ADD_DATE = "date_added";
+ public static final String COLUMN_MEDIA_TYPE = "mime_type";
+ private static final String COLUMN_POSITION = "position";
+ private static final String COLUMN_MIME_TYPE = "media_type";
+
+ private static final String NULL_HOCK = COLUMN_POSITION;
+ public static final String ORDER_COLUMN = COLUMN_ADD_DATE + " ASC ";
+ private static final String VIDEO_STREAMING_MEDIA_TYPE = "streaming";
+
+ public static final int INDEX_ID = 0;
+ public static final int INDEX_DATA = 1;
+ public static final int INDEX_TITLE = 2;
+ public static final int INDEX_ADD_DATE = 3;
+ public static final int INDEX_MIME_TYPE = 4;
+ private static final int INDEX_POSITION = 5;
+ private static final int INDEX_MEDIA_TYPE = 6;
+
+ public static final String[] PROJECTION = new String[] {
+ COLUMN_ID,
+ COLUMN_DATA,
+ COLUMN_TITLE,
+ COLUMN_ADD_DATE,
+ COLUMN_MIME_TYPE,
+ };
+
+ private final Context mContext;
+ private final ContentResolver mCr;
+
+ public BookmarkEnhance(final Context context) {
+ mContext = context;
+ mCr = context.getContentResolver();
+ }
+
+ public Uri insert(final String title, final String uri, final String mimeType,
+ final long position) {
+ final ContentValues values = new ContentValues();
+ final String mytitle = (title == null ? mContext.getString(R.string.default_title) : title);
+ values.put(COLUMN_TITLE, mytitle);
+ values.put(COLUMN_DATA, uri);
+ values.put(COLUMN_POSITION, position);
+ values.put(COLUMN_ADD_DATE, System.currentTimeMillis());
+ values.put(COLUMN_MEDIA_TYPE, VIDEO_STREAMING_MEDIA_TYPE);
+ values.put(COLUMN_MIME_TYPE, mimeType);
+ final Uri insertUri = mCr.insert(BOOKMARK_URI, values);
+ if (LOG) {
+ Log.v(TAG, "insert(" + title + "," + uri + ", " + position + ") return "
+ + insertUri);
+ }
+ return insertUri;
+ }
+
+ public int delete(final long id) {
+ final Uri uri = ContentUris.withAppendedId(BOOKMARK_URI, id);
+ final int count = mCr.delete(uri, null, null);
+ if (LOG) {
+ Log.v(TAG, "delete(" + id + ") return " + count);
+ }
+ return count;
+ }
+
+ public int deleteAll() {
+ final int count = mCr.delete(BOOKMARK_URI, COLUMN_MEDIA_TYPE + "=? ", new String[] {
+ VIDEO_STREAMING_MEDIA_TYPE
+ });
+ if (LOG) {
+ Log.v(TAG, "deleteAll() return " + count);
+ }
+ return count;
+ }
+
+ public boolean exists(final String uri) {
+ final Cursor cursor = mCr.query(BOOKMARK_URI,
+ PROJECTION,
+ COLUMN_DATA + "=? and " + COLUMN_MEDIA_TYPE + "=? ",
+ new String[] {
+ uri, VIDEO_STREAMING_MEDIA_TYPE
+ },
+ null
+ );
+ boolean exist = false;
+ if (cursor != null) {
+ exist = cursor.moveToFirst();
+ cursor.close();
+ }
+ if (LOG) {
+ Log.v(TAG, "exists(" + uri + ") return " + exist);
+ }
+ return exist;
+ }
+
+ public Cursor query() {
+ final Cursor cursor = mCr.query(BOOKMARK_URI,
+ PROJECTION,
+ COLUMN_MEDIA_TYPE + "='" + VIDEO_STREAMING_MEDIA_TYPE + "' ",
+ null,
+ ORDER_COLUMN
+ );
+ if (LOG) {
+ Log.v(TAG, "query() return cursor=" + (cursor == null ? -1 : cursor.getCount()));
+ }
+ return cursor;
+ }
+
+ public int update(final long id, final String title, final String uri, final int position) {
+ final ContentValues values = new ContentValues();
+ values.put(COLUMN_TITLE, title);
+ values.put(COLUMN_DATA, uri);
+ values.put(COLUMN_POSITION, position);
+ final Uri updateUri = ContentUris.withAppendedId(BOOKMARK_URI, id);
+ final int count = mCr.update(updateUri, values, null, null);
+ if (LOG) {
+ Log.v(TAG, "update(" + id + ", " + title + ", " + uri + ", " + position + ")" +
+ " return " + count);
+ }
+ return count;
+ }
+}
diff --git a/src/org/codeaurora/gallery3d/video/BookmarkHooker.java b/src/org/codeaurora/gallery3d/video/BookmarkHooker.java
new file mode 100644
index 000000000..9d7697d7a
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/BookmarkHooker.java
@@ -0,0 +1,76 @@
+package org.codeaurora.gallery3d.video;
+
+import android.content.Intent;
+import android.view.Menu;
+import android.view.MenuItem;
+
+import com.android.gallery3d.R;
+import org.codeaurora.gallery3d.ext.MovieUtils;
+
+public class BookmarkHooker extends MovieHooker {
+ private static final String TAG = "BookmarkHooker";
+ private static final boolean LOG = true;
+
+ private static final String ACTION_BOOKMARK = "org.codeaurora.bookmark.VIEW";
+ private static final int MENU_BOOKMARK_ADD = 1;
+ private static final int MENU_BOOKMARK_DISPLAY = 2;
+ private MenuItem mMenuBookmarks;
+ private MenuItem mMenuBookmarkAdd;
+
+ public static final String KEY_LOGO_BITMAP = "logo-bitmap";
+
+ @Override
+ public boolean onCreateOptionsMenu(final Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ mMenuBookmarkAdd = menu.add(0, getMenuActivityId(MENU_BOOKMARK_ADD), 0,
+ R.string.bookmark_add);
+ mMenuBookmarks = menu.add(0, getMenuActivityId(MENU_BOOKMARK_DISPLAY), 0,
+ R.string.bookmark_display);
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(final Menu menu) {
+ super.onPrepareOptionsMenu(menu);
+ if (MovieUtils.isLocalFile(getMovieItem().getUri(), getMovieItem().getMimeType())) {
+ if (mMenuBookmarkAdd != null) {
+ mMenuBookmarkAdd.setVisible(false);
+ }
+ if (mMenuBookmarks != null) {
+ mMenuBookmarks.setVisible(false);
+ }
+ } else {
+ if (mMenuBookmarkAdd != null) {
+ mMenuBookmarkAdd.setVisible(true);
+ }
+ if (mMenuBookmarks != null) {
+ mMenuBookmarks.setVisible(true);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(final MenuItem item) {
+ super.onOptionsItemSelected(item);
+ switch (getMenuOriginalId(item.getItemId())) {
+ case MENU_BOOKMARK_ADD:
+ getPlayer().addBookmark();
+ return true;
+ case MENU_BOOKMARK_DISPLAY:
+ gotoBookmark();
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private void gotoBookmark() {
+ final Intent intent = new Intent(ACTION_BOOKMARK);
+ intent.addCategory(Intent.CATEGORY_DEFAULT);
+ intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
+ | Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);
+ intent.putExtra(KEY_LOGO_BITMAP, getIntent().getParcelableExtra(KEY_LOGO_BITMAP));
+ getContext().startActivity(intent);
+ }
+}
diff --git a/src/org/codeaurora/gallery3d/video/CodeauroraVideoView.java b/src/org/codeaurora/gallery3d/video/CodeauroraVideoView.java
new file mode 100755
index 000000000..39bf532e6
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/CodeauroraVideoView.java
@@ -0,0 +1,1032 @@
+package org.codeaurora.gallery3d.video;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.media.AudioManager;
+import android.media.MediaPlayer;
+import android.media.Metadata;
+import android.media.MediaPlayer.OnCompletionListener;
+import android.media.MediaPlayer.OnErrorListener;
+import android.media.MediaPlayer.OnInfoListener;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Message;
+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.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.MediaController;
+import android.widget.MediaController.MediaPlayerControl;
+
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * Displays a video file. The VideoView class
+ * can load images from various sources (such as resources or content
+ * providers), takes care of computing its measurement from the video so that
+ * it can be used in any layout manager, and provides various display options
+ * such as scaling and tinting.
+ */
+public class CodeauroraVideoView extends SurfaceView implements MediaPlayerControl {
+ private static final boolean LOG = true;
+ private String TAG = "CodeauroraVideoView";
+ // settable by the client
+ private Uri mUri;
+ private Map<String, String> mHeaders;
+
+ // all possible internal states
+ private static final int STATE_ERROR = -1;
+ private static final int STATE_IDLE = 0;
+ private static final int STATE_PREPARING = 1;
+ private static final int STATE_PREPARED = 2;
+ private static final int STATE_PLAYING = 3;
+ private static final int STATE_PAUSED = 4;
+ private static final int STATE_PLAYBACK_COMPLETED = 5;
+ private static final int STATE_SUSPENDED = 6;
+ private static final int MSG_LAYOUT_READY = 1;
+
+ // mCurrentState is a VideoView object's current state.
+ // mTargetState is the state that a method caller intends to reach.
+ // For instance, regardless the VideoView object's current state,
+ // calling pause() intends to bring the object to a target state
+ // of STATE_PAUSED.
+ private int mCurrentState = STATE_IDLE;
+ private int mTargetState = STATE_IDLE;
+
+ // All the stuff we need for playing and showing a video
+ private SurfaceHolder mSurfaceHolder = null;
+ private MediaPlayer mMediaPlayer = null;
+ private int mAudioSession;
+ private int mVideoWidth;
+ private int mVideoHeight;
+ private int mSurfaceWidth;
+ private int mSurfaceHeight;
+ private int mDuration;
+ private MediaController mMediaController;
+ private OnCompletionListener mOnCompletionListener;
+ private MediaPlayer.OnPreparedListener mOnPreparedListener;
+ private MediaPlayer.OnBufferingUpdateListener mOnBufferingUpdateListener;
+ private MediaPlayer.OnVideoSizeChangedListener mVideoSizeListener;
+ private MediaPlayer.OnPreparedListener mPreparedListener;
+ private int mCurrentBufferPercentage;
+ private OnErrorListener mOnErrorListener;
+ private OnInfoListener mOnInfoListener;
+ private int mSeekWhenPrepared; // recording the seek position while preparing
+ private boolean mCanPause;
+ private boolean mCanSeekBack;
+ private boolean mCanSeekForward;
+ private boolean mHasGotPreparedCallBack = false;
+ private boolean mNeedWaitLayout = false;
+ private boolean mHasGotMetaData = false;
+ private boolean mOnResumed;
+
+ private final Handler mHandler = new Handler() {
+ public void handleMessage(final Message msg) {
+ if (LOG) {
+ Log.v(TAG, "handleMessage() to do prepare. msg=" + msg);
+ }
+ switch (msg.what) {
+ case MSG_LAYOUT_READY:
+ if (mMediaPlayer == null || mUri == null) {
+ Log.w(TAG, "Cannot prepare play! mMediaPlayer=" + mMediaPlayer
+ + ", mUri=" + mUri);
+ } else {
+ doPreparedIfReady(mMediaPlayer);
+ }
+ break;
+ default:
+ Log.w(TAG, "Unhandled message " + msg);
+ break;
+ }
+ }
+ };
+
+ public CodeauroraVideoView(Context context) {
+ super(context);
+ initVideoView();
+ initialize();
+ }
+
+ public CodeauroraVideoView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ initVideoView();
+ initialize();
+ }
+
+ public CodeauroraVideoView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ initVideoView();
+ initialize();
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int width = getDefaultSize(mVideoWidth, widthMeasureSpec);
+ int height = getDefaultSize(mVideoHeight, heightMeasureSpec);
+ if (mVideoWidth > 0 && mVideoHeight > 0) {
+
+ int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
+ int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
+ int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
+ int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
+
+ if (widthSpecMode == MeasureSpec.EXACTLY && heightSpecMode == MeasureSpec.EXACTLY) {
+ // the size is fixed
+ width = widthSpecSize;
+ height = heightSpecSize;
+
+ // for compatibility, we adjust size based on aspect ratio
+ if ( mVideoWidth * height < width * mVideoHeight ) {
+ width = height * mVideoWidth / mVideoHeight;
+ } else if ( mVideoWidth * height > width * mVideoHeight ) {
+ height = width * mVideoHeight / mVideoWidth;
+ }
+ } else if (widthSpecMode == MeasureSpec.EXACTLY) {
+ // only the width is fixed, adjust the height to match aspect ratio if possible
+ width = widthSpecSize;
+ height = width * mVideoHeight / mVideoWidth;
+ if (heightSpecMode == MeasureSpec.AT_MOST && height > heightSpecSize) {
+ // couldn't match aspect ratio within the constraints
+ height = heightSpecSize;
+ }
+ } else if (heightSpecMode == MeasureSpec.EXACTLY) {
+ // only the height is fixed, adjust the width to match aspect ratio if possible
+ height = heightSpecSize;
+ width = height * mVideoWidth / mVideoHeight;
+ if (widthSpecMode == MeasureSpec.AT_MOST && width > widthSpecSize) {
+ // couldn't match aspect ratio within the constraints
+ width = widthSpecSize;
+ }
+ } else {
+ // neither the width nor the height are fixed, try to use actual video size
+ width = mVideoWidth;
+ height = mVideoHeight;
+ if (heightSpecMode == MeasureSpec.AT_MOST && height > heightSpecSize) {
+ height = heightSpecSize;
+ width = height * mVideoWidth / mVideoHeight;
+ }
+ if (widthSpecMode == MeasureSpec.AT_MOST && width > widthSpecSize) {
+ width = widthSpecSize;
+ height = width * mVideoHeight / mVideoWidth;
+ }
+ }
+ } else {
+ // no size yet, just adopt the given spec sizes
+ }
+ setMeasuredDimension(width, height);
+ if (mNeedWaitLayout) { // when OnMeasure ok, start video.
+ mNeedWaitLayout = false;
+ mHandler.sendEmptyMessage(MSG_LAYOUT_READY);
+ }
+ }
+
+ @Override
+ public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+ super.onInitializeAccessibilityEvent(event);
+ event.setClassName(CodeauroraVideoView.class.getName());
+ }
+
+ @Override
+ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(info);
+ info.setClassName(CodeauroraVideoView.class.getName());
+ }
+
+ public int resolveAdjustedSize(int desiredSize, int measureSpec) {
+ return getDefaultSize(desiredSize, measureSpec);
+ }
+
+ private void initVideoView() {
+ mVideoWidth = 0;
+ mVideoHeight = 0;
+ getHolder().addCallback(mSHCallback);
+ getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
+ setFocusable(true);
+ setFocusableInTouchMode(true);
+ requestFocus();
+ mCurrentState = STATE_IDLE;
+ mTargetState = STATE_IDLE;
+ }
+
+ private void initialize() {
+ mPreparedListener = new MediaPlayer.OnPreparedListener() {
+ public void onPrepared(final MediaPlayer mp) {
+ if (LOG) {
+ Log.v(TAG, "mPreparedListener.onPrepared(" + mp + ")");
+ }
+ //Here we can get meta data from mediaplayer.
+ // Get the capabilities of the player for this stream
+ final Metadata data = mp.getMetadata(MediaPlayer.METADATA_ALL,
+ MediaPlayer.BYPASS_METADATA_FILTER);
+ if (data != null) {
+ mCanPause = !data.has(Metadata.PAUSE_AVAILABLE)
+ || data.getBoolean(Metadata.PAUSE_AVAILABLE);
+ mCanSeekBack = !data.has(Metadata.SEEK_BACKWARD_AVAILABLE)
+ || data.getBoolean(Metadata.SEEK_BACKWARD_AVAILABLE);
+ mCanSeekForward = !data.has(Metadata.SEEK_FORWARD_AVAILABLE)
+ || data.getBoolean(Metadata.SEEK_FORWARD_AVAILABLE);
+ } else {
+ mCanPause = true;
+ mCanSeekBack = true;
+ mCanSeekForward = true;
+ Log.w(TAG, "Metadata is null!");
+ }
+ if (LOG) {
+ Log.v(TAG, "mPreparedListener.onPrepared() mCanPause=" + mCanPause);
+ }
+ mHasGotPreparedCallBack = true;
+ doPreparedIfReady(mMediaPlayer);
+ }
+ };
+
+ mErrorListener = new MediaPlayer.OnErrorListener() {
+ public boolean onError(final MediaPlayer mp, final int frameworkErr, final int implErr) {
+ Log.d(TAG, "Error: " + frameworkErr + "," + implErr);
+ if (mCurrentState == STATE_ERROR) {
+ Log.w(TAG, "Duplicate error message. error message has been sent! " +
+ "error=(" + frameworkErr + "," + implErr + ")");
+ return true;
+ }
+ //record error position and duration
+ //here disturb the original logic
+ mSeekWhenPrepared = getCurrentPosition();
+ if (LOG) {
+ Log.v(TAG, "onError() mSeekWhenPrepared=" + mSeekWhenPrepared + ", mDuration=" + mDuration);
+ }
+ //for old version Streaming server, getduration is not valid.
+ mDuration = Math.abs(mDuration);
+ mCurrentState = STATE_ERROR;
+ mTargetState = STATE_ERROR;
+ if (mMediaController != null) {
+ mMediaController.hide();
+ }
+
+ /* If an error handler has been supplied, use it and finish. */
+ if (mOnErrorListener != null) {
+ if (mOnErrorListener.onError(mMediaPlayer, frameworkErr, implErr)) {
+ 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) {
+ final Resources r = mContext.getResources();
+ int messageId;
+
+ if (frameworkErr == MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK) {
+ messageId = com.android.internal.R.string.VideoView_error_text_invalid_progressive_playback;
+ } else {
+ messageId = com.android.internal.R.string.VideoView_error_text_unknown;
+ }
+ new AlertDialog.Builder(mContext)
+ .setMessage(messageId)
+ .setPositiveButton(com.android.internal.R.string.VideoView_error_button,
+ 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;
+ }
+ };
+
+ mBufferingUpdateListener = new MediaPlayer.OnBufferingUpdateListener() {
+ public void onBufferingUpdate(final MediaPlayer mp, final int percent) {
+ mCurrentBufferPercentage = percent;
+ if (mOnBufferingUpdateListener != null) {
+ mOnBufferingUpdateListener.onBufferingUpdate(mp, percent);
+ }
+ if (LOG) {
+ Log.v(TAG, "onBufferingUpdate() Buffering percent: " + percent);
+ Log.v(TAG, "onBufferingUpdate() mTargetState=" + mTargetState);
+ Log.v(TAG, "onBufferingUpdate() mCurrentState=" + mCurrentState);
+ }
+ }
+ };
+
+ mSizeChangedListener = new MediaPlayer.OnVideoSizeChangedListener() {
+ public void onVideoSizeChanged(final MediaPlayer mp, final int width, final int height) {
+ mVideoWidth = mp.getVideoWidth();
+ mVideoHeight = mp.getVideoHeight();
+ if (LOG) {
+ Log.v(TAG, "OnVideoSizeChagned(" + width + "," + height + ")");
+ Log.v(TAG, "OnVideoSizeChagned(" + mVideoWidth + "," + mVideoHeight + ")");
+ Log.v(TAG, "OnVideoSizeChagned() mCurrentState=" + mCurrentState);
+ }
+ if (mVideoWidth != 0 && mVideoHeight != 0) {
+ getHolder().setFixedSize(mVideoWidth, mVideoHeight);
+ if (mCurrentState == STATE_PREPARING) {
+ mNeedWaitLayout = true;
+ }
+ }
+ if (mVideoSizeListener != null) {
+ mVideoSizeListener.onVideoSizeChanged(mp, width, height);
+ }
+ CodeauroraVideoView.this.requestLayout();
+ }
+ };
+
+ getHolder().removeCallback(mSHCallback);
+ mSHCallback = new SurfaceHolder.Callback() {
+ public void surfaceChanged(final SurfaceHolder holder, final int format, final int w, final int h) {
+ if (LOG) {
+ Log.v(TAG, "surfaceChanged(" + holder + ", " + format + ", " + w + ", " + h + ")");
+ Log.v(TAG, "surfaceChanged() mMediaPlayer=" + mMediaPlayer + ", mTargetState=" + mTargetState
+ + ", mVideoWidth=" + mVideoWidth + ", mVideoHeight=" + mVideoHeight);
+ }
+ mSurfaceWidth = w;
+ mSurfaceHeight = h;
+ final boolean isValidState = (mTargetState == STATE_PLAYING);
+ final boolean hasValidSize = (mVideoWidth == w && mVideoHeight == h);
+ if (mMediaPlayer != null && isValidState && hasValidSize) {
+ if (mSeekWhenPrepared != 0) {
+ seekTo(mSeekWhenPrepared);
+ }
+ Log.v(TAG, "surfaceChanged() start()");
+ start();
+ }
+ }
+
+ public void surfaceCreated(final SurfaceHolder holder) {
+ if (LOG) {
+ Log.v(TAG, "surfaceCreated(" + holder + ")");
+ }
+ mSurfaceHolder = holder;
+ openVideo();
+ }
+
+ public void surfaceDestroyed(final SurfaceHolder holder) {
+ // after we return from this we can't use the surface any more
+ if (LOG) {
+ Log.v(TAG, "surfaceDestroyed(" + holder + ")");
+ }
+ mSurfaceHolder = null;
+ if (mMediaController != null) {
+ mMediaController.hide();
+ }
+ release(true);
+ }
+ };
+ getHolder().addCallback(mSHCallback);
+ }
+
+ public void setVideoPath(String path) {
+ setVideoURI(Uri.parse(path));
+ }
+
+ public void setVideoURI(Uri uri) {
+ setVideoURI(uri, null);
+ }
+
+ /**
+ * @hide
+ */
+ public void setVideoURI(Uri uri, Map<String, String> headers) {
+ Log.d(TAG,"setVideoURI uri = " + uri);
+ mDuration = -1;
+ setResumed(true);
+ mUri = uri;
+ mHeaders = headers;
+ mSeekWhenPrepared = 0;
+ openVideo();
+ requestLayout();
+ invalidate();
+ }
+
+ public void stopPlayback() {
+ if (mMediaPlayer != null) {
+ mMediaPlayer.stop();
+ mMediaPlayer.release();
+ mMediaPlayer = null;
+ mCurrentState = STATE_IDLE;
+ mTargetState = STATE_IDLE;
+ }
+ }
+
+ private void openVideo() {
+ clearVideoInfo();
+ if (mUri == null || mSurfaceHolder == null) {
+ // not ready for playback just yet, will try again later
+ return;
+ }
+ // Tell the music playback service to pause
+ // TODO: these constants need to be published somewhere in the framework.
+ Intent i = new Intent("com.android.music.musicservicecommand");
+ i.putExtra("command", "pause");
+ mContext.sendBroadcast(i);
+ // we shouldn't clear the target state, because somebody might have
+ // called start() previously
+ release(false);
+ if ("".equalsIgnoreCase(String.valueOf(mUri))) {
+ Log.w(TAG, "Unable to open content: " + mUri);
+ mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
+ return;
+ }
+ try {
+ mMediaPlayer = new MediaPlayer();
+ if (mAudioSession != 0) {
+ mMediaPlayer.setAudioSessionId(mAudioSession);
+ } else {
+ mAudioSession = mMediaPlayer.getAudioSessionId();
+ }
+ mMediaPlayer.setOnPreparedListener(mPreparedListener);
+ mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener);
+ mMediaPlayer.setOnCompletionListener(mCompletionListener);
+ mMediaPlayer.setOnErrorListener(mErrorListener);
+ mMediaPlayer.setOnInfoListener(mOnInfoListener);
+ mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
+ mCurrentBufferPercentage = 0;
+ mMediaPlayer.setDataSource(mContext, mUri, mHeaders);
+ mMediaPlayer.setDisplay(mSurfaceHolder);
+ mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
+ mMediaPlayer.setScreenOnWhilePlaying(true);
+ mMediaPlayer.prepareAsync();
+ // we don't set the target state here either, but preserve the
+ // target state that was there before.
+ mCurrentState = STATE_PREPARING;
+ attachMediaController();
+ } catch (IOException ex) {
+ Log.w(TAG, "Unable to open content: " + mUri, ex);
+ mCurrentState = STATE_ERROR;
+ mTargetState = STATE_ERROR;
+ mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
+ return;
+ } catch (IllegalArgumentException ex) {
+ Log.w(TAG, "Unable to open content: " + mUri, ex);
+ mCurrentState = STATE_ERROR;
+ mTargetState = STATE_ERROR;
+ mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
+ return;
+ }
+ }
+
+ public void setMediaController(MediaController controller) {
+ if (mMediaController != null) {
+ mMediaController.hide();
+ }
+ mMediaController = controller;
+ attachMediaController();
+ }
+
+ 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(isInPlaybackState());
+ }
+ }
+
+ private boolean isHTTPStreaming(Uri mUri) {
+ if (mUri != null){
+ String scheme = mUri.toString();
+ if (scheme.startsWith("http://") || scheme.startsWith("https://")) {
+ if (scheme.endsWith(".m3u8") || scheme.endsWith(".m3u")
+ || scheme.contains("m3u8") || scheme.endsWith(".mpd")) {
+ // HLS or DASH streaming source
+ return false;
+ }
+ // HTTP streaming
+ return true;
+ }
+ }
+ return false;
+ }
+
+ MediaPlayer.OnVideoSizeChangedListener mSizeChangedListener =
+ new MediaPlayer.OnVideoSizeChangedListener() {
+ public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
+ mVideoWidth = mp.getVideoWidth();
+ mVideoHeight = mp.getVideoHeight();
+ if (mVideoWidth != 0 && mVideoHeight != 0) {
+ getHolder().setFixedSize(mVideoWidth, mVideoHeight);
+ requestLayout();
+ }
+ }
+ };
+
+ private MediaPlayer.OnCompletionListener mCompletionListener =
+ new MediaPlayer.OnCompletionListener() {
+ public void onCompletion(MediaPlayer mp) {
+ mCurrentState = STATE_PLAYBACK_COMPLETED;
+ mTargetState = STATE_PLAYBACK_COMPLETED;
+ if (mMediaController != null) {
+ mMediaController.hide();
+ }
+ if (mOnCompletionListener != null) {
+ mOnCompletionListener.onCompletion(mMediaPlayer);
+ }
+ }
+ };
+
+ private MediaPlayer.OnErrorListener mErrorListener =
+ new MediaPlayer.OnErrorListener() {
+ public boolean onError(MediaPlayer mp, int framework_err, int impl_err) {
+ Log.d(TAG, "Error: " + framework_err + "," + impl_err);
+ mCurrentState = STATE_ERROR;
+ mTargetState = STATE_ERROR;
+ if (mMediaController != null) {
+ mMediaController.hide();
+ }
+
+ /* If an error handler has been supplied, use it and finish. */
+ if (mOnErrorListener != null) {
+ if (mOnErrorListener.onError(mMediaPlayer, framework_err, impl_err)) {
+ 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();
+ int messageId;
+
+ if (framework_err == MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK) {
+ messageId = com.android.internal.R.string.VideoView_error_text_invalid_progressive_playback;
+ } else {
+ messageId = com.android.internal.R.string.VideoView_error_text_unknown;
+ }
+
+ new AlertDialog.Builder(mContext)
+ .setMessage(messageId)
+ .setPositiveButton(com.android.internal.R.string.VideoView_error_button,
+ 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;
+ }
+ };
+
+ /**
+ * Register a callback to be invoked when the media file
+ * is loaded and ready to go.
+ *
+ * @param l The callback that will be run
+ */
+ public void setOnPreparedListener(MediaPlayer.OnPreparedListener l) {
+ mOnPreparedListener = l;
+ }
+
+ /**
+ * Register a callback to be invoked when the end of a media file
+ * has been reached during playback.
+ *
+ * @param l The callback that will be run
+ */
+ public void setOnCompletionListener(OnCompletionListener l) {
+ mOnCompletionListener = l;
+ }
+
+ /**
+ * Register a callback to be invoked when an error occurs
+ * during playback or setup. If no listener is specified,
+ * or if the listener returned false, VideoView will inform
+ * the user of any errors.
+ *
+ * @param l The callback that will be run
+ */
+ public void setOnErrorListener(OnErrorListener l) {
+ mOnErrorListener = l;
+ }
+
+ /**
+ * Register a callback to be invoked when an informational event
+ * occurs during playback or setup.
+ *
+ * @param l The callback that will be run
+ */
+ public void setOnInfoListener(OnInfoListener l) {
+ mOnInfoListener = l;
+ }
+
+ SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback() {
+ public void surfaceChanged(SurfaceHolder holder, int format,
+ int w, int h) {
+ mSurfaceWidth = w;
+ mSurfaceHeight = h;
+ boolean isValidState = (mTargetState == STATE_PLAYING);
+ boolean hasValidSize = (mVideoWidth == w && mVideoHeight == h);
+ if (mMediaPlayer != null && isValidState && hasValidSize) {
+ if (mSeekWhenPrepared != 0) {
+ seekTo(mSeekWhenPrepared);
+ }
+ start();
+ }
+ }
+
+ public void surfaceCreated(SurfaceHolder holder) {
+ /*
+ if (mCurrentState == STATE_SUSPENDED) {
+ mSurfaceHolder = holder;
+ mMediaPlayer.setDisplay(mSurfaceHolder);
+ if (mMediaPlayer.resume()) {
+ mCurrentState = STATE_PREPARED;
+ if (mSeekWhenPrepared != 0) {
+ seekTo(mSeekWhenPrepared);
+ }
+ if (mTargetState == STATE_PLAYING) {
+ start();
+ }
+ return;
+ } else {
+ release(false);
+ }
+ }
+ mSurfaceHolder = holder;
+ openVideo();
+ */
+
+ if (LOG) {
+ Log.v(TAG, "surfaceCreated(" + holder + ")");
+ }
+ if (mCurrentState == STATE_SUSPENDED) {
+ mSurfaceHolder = holder;
+ mMediaPlayer.setDisplay(mSurfaceHolder);
+ release(false);
+ }
+ mSurfaceHolder = holder;
+ openVideo();
+ }
+
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ // after we return from this we can't use the surface any more
+ mSurfaceHolder = null;
+ if (mMediaController != null) mMediaController.hide();
+ if (isHTTPStreaming(mUri) && mCurrentState == STATE_SUSPENDED) {
+ // Don't call release() while run suspend operation
+ return;
+ }
+ release(true);
+ }
+ };
+
+ /*
+ * release the media player in any state
+ */
+ private void release(boolean cleartargetstate) {
+ if (mMediaPlayer != null) {
+ mMediaPlayer.reset();
+ mMediaPlayer.release();
+ mMediaPlayer = null;
+ mCurrentState = STATE_IDLE;
+ if (cleartargetstate) {
+ mTargetState = STATE_IDLE;
+ }
+ }
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ if (isInPlaybackState() && mMediaController != null) {
+ toggleMediaControlsVisiblity();
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onTrackballEvent(MotionEvent ev) {
+ if (isInPlaybackState() && mMediaController != null) {
+ toggleMediaControlsVisiblity();
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ final boolean isKeyCodeSupported = keyCode != KeyEvent.KEYCODE_BACK &&
+ keyCode != KeyEvent.KEYCODE_VOLUME_UP &&
+ keyCode != KeyEvent.KEYCODE_VOLUME_DOWN &&
+ keyCode != KeyEvent.KEYCODE_VOLUME_MUTE &&
+ keyCode != KeyEvent.KEYCODE_MENU &&
+ keyCode != KeyEvent.KEYCODE_CALL &&
+ keyCode != KeyEvent.KEYCODE_ENDCALL &&
+ keyCode != KeyEvent.KEYCODE_CAMERA;
+ if (isInPlaybackState() && isKeyCodeSupported && mMediaController != null) {
+ if (event.getRepeatCount() == 0 && (keyCode == KeyEvent.KEYCODE_HEADSETHOOK ||
+ keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE)) {
+ if (mMediaPlayer.isPlaying()) {
+ pause();
+ mMediaController.show();
+ } else {
+ start();
+ mMediaController.hide();
+ }
+ return true;
+ } else if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY) {
+ if (!mMediaPlayer.isPlaying()) {
+ start();
+ mMediaController.hide();
+ }
+ return true;
+ } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP
+ || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE) {
+ if (mMediaPlayer.isPlaying()) {
+ pause();
+ mMediaController.show();
+ }
+ return true;
+ } else if (keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD ||
+ keyCode == KeyEvent.KEYCODE_MEDIA_NEXT ||
+ keyCode == KeyEvent.KEYCODE_MEDIA_PREVIOUS ||
+ keyCode == KeyEvent.KEYCODE_MEDIA_REWIND ||
+ keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE ||
+ keyCode == KeyEvent.KEYCODE_HEADSETHOOK) {
+ // consume media action, so if video view if front,
+ // other media player will not play any sounds.
+ return true;
+ } else {
+ toggleMediaControlsVisiblity();
+ }
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+
+ private void toggleMediaControlsVisiblity() {
+ if (mMediaController.isShowing()) {
+ mMediaController.hide();
+ } else {
+ mMediaController.show();
+ }
+ }
+
+ @Override
+ public void start() {
+ if (isInPlaybackState()) {
+ mMediaPlayer.start();
+ mCurrentState = STATE_PLAYING;
+ }
+ mTargetState = STATE_PLAYING;
+ }
+
+ @Override
+ public void pause() {
+ if (isInPlaybackState()) {
+ if (mMediaPlayer.isPlaying()) {
+ mMediaPlayer.pause();
+ mCurrentState = STATE_PAUSED;
+ }
+ }
+ mTargetState = STATE_PAUSED;
+ }
+
+ public void suspend() {
+ // HTTP streaming will call mMediaPlayer->suspend(), others will call release()
+ /*
+ if (isHTTPStreaming(mUri) && mCurrentState != STATE_PREPARING) {
+ if (mMediaPlayer.suspend()) {
+ mTargetState = mCurrentState;
+ mCurrentState = STATE_SUSPENDED;
+ return;
+ }
+ }*/
+ release(false);
+ }
+
+ public void resume() {
+ setResumed(true);
+ openVideo();
+ }
+
+ @Override
+ public int getDuration() {
+ final boolean inPlaybackState = isInPlaybackState();
+ if (LOG) {
+ Log.v(TAG, "getDuration() mDuration=" + mDuration + ", inPlaybackState="
+ + inPlaybackState);
+ }
+ if (inPlaybackState) {
+ if (mDuration > 0) {
+ return mDuration;
+ }
+ // in case the duration is zero or smaller than zero for streaming
+ // video
+ int tempDuration = mMediaPlayer.getDuration();
+ if (tempDuration <= 0) {
+ return mDuration;
+ } else {
+ mDuration = tempDuration;
+ }
+
+ return mDuration;
+ }
+ return mDuration;
+ }
+
+ @Override
+ public int getCurrentPosition() {
+ int position = 0;
+ if (mSeekWhenPrepared > 0) {
+ // if connecting error before seek,
+ // we should remember this position for retry
+ position = mSeekWhenPrepared;
+ // /M: if player not started, getCurrentPosition() will lead to NE.
+ } else if (isInPlaybackState()) {
+ position = mMediaPlayer.getCurrentPosition();
+ }
+ if (LOG) {
+ Log.v(TAG, "getCurrentPosition() return " + position
+ + ", mSeekWhenPrepared=" + mSeekWhenPrepared);
+ }
+ return position;
+ }
+
+ @Override
+ public void seekTo(int msec) {
+ if (isInPlaybackState()) {
+ mMediaPlayer.seekTo(msec);
+ mSeekWhenPrepared = 0;
+ } else {
+ mSeekWhenPrepared = msec;
+ }
+ }
+
+ @Override
+ public boolean isPlaying() {
+ return isInPlaybackState() && mMediaPlayer.isPlaying();
+ }
+
+ @Override
+ public int getBufferPercentage() {
+ if (mMediaPlayer != null) {
+ return mCurrentBufferPercentage;
+ }
+ return 0;
+ }
+
+ private boolean isInPlaybackState() {
+ return (mMediaPlayer != null &&
+ mCurrentState != STATE_ERROR &&
+ mCurrentState != STATE_IDLE &&
+ mCurrentState != STATE_PREPARING &&
+ mCurrentState != STATE_SUSPENDED);
+ }
+
+ @Override
+ public boolean canPause() {
+ return mCanPause;
+ }
+
+ @Override
+ public boolean canSeekBackward() {
+ return mCanSeekBack;
+ }
+
+ @Override
+ public boolean canSeekForward() {
+ return mCanSeekForward;
+ }
+
+ @Override
+ public int getAudioSessionId() {
+ if (mAudioSession == 0) {
+ MediaPlayer foo = new MediaPlayer();
+ mAudioSession = foo.getAudioSessionId();
+ foo.release();
+ }
+ return mAudioSession;
+ }
+
+ // for duration displayed
+ public void setDuration(final int duration) {
+ if (LOG) {
+ Log.v(TAG, "setDuration(" + duration + ")");
+ }
+ mDuration = (duration > 0 ? -duration : duration);
+ }
+
+ public void setVideoURI(final Uri uri, final Map<String, String> headers,
+ final boolean hasGotMetaData) {
+ if (LOG) {
+ Log.v(TAG, "setVideoURI(" + uri + ", " + headers + ")");
+ }
+ // clear the flags
+ mHasGotMetaData = hasGotMetaData;
+ setVideoURI(uri, headers);
+ }
+
+ private void doPreparedIfReady(final MediaPlayer mp) {
+ if (LOG) {
+ Log.v(TAG, "doPreparedIfReady() mHasGotPreparedCallBack=" + mHasGotPreparedCallBack
+ + ", mHasGotMetaData=" + mHasGotMetaData + ", mNeedWaitLayout="
+ + mNeedWaitLayout
+ + ", mCurrentState=" + mCurrentState);
+ }
+ if (mHasGotPreparedCallBack && mHasGotMetaData && !mNeedWaitLayout) {
+ doPrepared(mp);
+ }
+ }
+
+ private void doPrepared(final MediaPlayer mp) {
+ if (LOG) {
+ Log.v(TAG, "doPrepared(" + mp + ") start");
+ }
+ mCurrentState = STATE_PREPARED;
+ if (mOnPreparedListener != null) {
+ mOnPreparedListener.onPrepared(mMediaPlayer);
+ }
+ mVideoWidth = mp.getVideoWidth();
+ mVideoHeight = mp.getVideoHeight();
+
+ // mSeekWhenPrepared may be changed after seekTo()
+ final int seekToPosition = mSeekWhenPrepared;
+ if (seekToPosition != 0) {
+ seekTo(seekToPosition);
+ }
+ if (mVideoWidth != 0 && mVideoHeight != 0) {
+ getHolder().setFixedSize(mVideoWidth, mVideoHeight);
+ }
+
+ if (mTargetState == STATE_PLAYING) {
+ start();
+ }
+ if (LOG) {
+ Log.v(TAG, "doPrepared() end video size: " + mVideoWidth + "," + mVideoHeight
+ + ", mTargetState=" + mTargetState + ", mCurrentState=" + mCurrentState);
+ }
+ }
+
+ /**
+ * surfaceCreate will invoke openVideo after the activity stoped. Here set
+ * this flag to avoid openVideo after the activity stoped.
+ *
+ * @param resume
+ */
+ public void setResumed(final boolean resume) {
+ if (LOG) {
+ Log.v(TAG, "setResumed(" + resume + ") mUri=" + mUri + ", mOnResumed=" + mOnResumed);
+ }
+ mOnResumed = resume;
+ }
+
+ private void clearVideoInfo() {
+ if (LOG) {
+ Log.v(TAG, "clearVideoInfo()");
+ }
+ mHasGotPreparedCallBack = false;
+ mNeedWaitLayout = false;
+ }
+
+ public void clearSeek() {
+ if (LOG) {
+ Log.v(TAG, "clearSeek() mSeekWhenPrepared=" + mSeekWhenPrepared);
+ }
+ mSeekWhenPrepared = 0;
+ }
+
+ public void clearDuration() {
+ if (LOG) {
+ Log.v(TAG, "clearDuration() mDuration=" + mDuration);
+ }
+ mDuration = -1;
+ }
+
+ public boolean isTargetPlaying() {
+ if (LOG) {
+ Log.v(TAG, "isTargetPlaying() mTargetState=" + mTargetState);
+ }
+ return mTargetState == STATE_PLAYING;
+ }
+}
diff --git a/src/org/codeaurora/gallery3d/video/DmReceiver.java b/src/org/codeaurora/gallery3d/video/DmReceiver.java
new file mode 100644
index 000000000..616ce33d6
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/DmReceiver.java
@@ -0,0 +1,65 @@
+package org.codeaurora.gallery3d.video;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.net.Uri;
+import android.os.PowerManager;
+import android.preference.PreferenceManager;
+import android.provider.Settings.System;
+import android.util.Log;
+
+public class DmReceiver extends BroadcastReceiver {
+ private static final String TAG = "DmReceiver";
+ public static final String WRITE_SETTING_ACTION = "streaming.action.WRITE_SETTINGS";
+ public static final String BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED";
+
+ private SharedPreferences mPref;
+ static final int STREAMING_CONNPROFILE_IO_HANDLER_TYPE = 1;
+ static final int STREAMING_MAX_UDP_PORT_IO_HANDLER_TYPE = 3;
+ static final int STREAMING_MIN_UDP_PORT_IO_HANDLER_TYPE = 4;
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (mPref == null) {
+ mPref = PreferenceManager.getDefaultSharedPreferences(context);
+ }
+ if (BOOT_COMPLETED.equals(intent.getAction())) {
+ String rtpMaxport = mPref.getString(SettingsActivity.PREFERENCE_RTP_MAXPORT, "65535");
+ String rtpMinport = mPref.getString(SettingsActivity.PREFERENCE_RTP_MINPORT, "8192");
+ String apn = mPref.getString(SettingsActivity.PREFERENCE_APN, "CMWAP");
+ System.putString(context.getContentResolver(),
+ "streaming_max_udp_port", rtpMaxport);
+ System.putString(context.getContentResolver(),
+ "streaming_min_udp_port", rtpMinport);
+ System.putString(context.getContentResolver(), "apn", apn);
+ } else if (WRITE_SETTING_ACTION.equals(intent.getAction())) {
+ int valueType = intent.getIntExtra("type", 0);
+ String value = intent.getStringExtra("value");
+ if (valueType == STREAMING_MAX_UDP_PORT_IO_HANDLER_TYPE) {
+ mPref.edit().putString(SettingsActivity.PREFERENCE_RTP_MAXPORT,
+ value).commit();
+ System.putString(context.getContentResolver(),
+ "streaming_max_udp_port", value);
+ } else if (valueType == STREAMING_MIN_UDP_PORT_IO_HANDLER_TYPE) {
+ mPref.edit().putString(SettingsActivity.PREFERENCE_RTP_MINPORT,
+ value).commit();
+ System.putString(context.getContentResolver(),
+ "streaming_min_udp_port", value);
+ } else if (valueType == STREAMING_CONNPROFILE_IO_HANDLER_TYPE) {
+ mPref.edit().putString(SettingsActivity.PREFERENCE_APN,
+ value).commit();
+ System.putString(context.getContentResolver(),
+ "apn", value);
+ }
+ }
+ }
+}
diff --git a/src/org/codeaurora/gallery3d/video/ExtensionHelper.java b/src/org/codeaurora/gallery3d/video/ExtensionHelper.java
index 7694cbfff..f95e9c09f 100755
--- a/src/org/codeaurora/gallery3d/video/ExtensionHelper.java
+++ b/src/org/codeaurora/gallery3d/video/ExtensionHelper.java
@@ -18,6 +18,7 @@ public class ExtensionHelper {
final ActivityHookerGroup group = new ActivityHookerGroup();
boolean loop = context.getResources().getBoolean(R.bool.loop);
boolean stereo = context.getResources().getBoolean(R.bool.stereo);
+ boolean streaming = context.getResources().getBoolean(R.bool.streaming);
if (loop == true) {
group.addHooker(new LoopVideoHooker()); // add it for common feature.
@@ -25,7 +26,10 @@ public class ExtensionHelper {
if (stereo == true) {
group.addHooker(new StereoAudioHooker()); // add it for common feature.
}
-
+ if (streaming == true) {
+ group.addHooker(new StreamingHooker());
+ group.addHooker(new BookmarkHooker());
+ }
return group;
}
}
diff --git a/src/org/codeaurora/gallery3d/video/MovieTitleHelper.java b/src/org/codeaurora/gallery3d/video/MovieTitleHelper.java
new file mode 100644
index 000000000..5f2229d5e
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/MovieTitleHelper.java
@@ -0,0 +1,108 @@
+package org.codeaurora.gallery3d.video;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteException;
+import android.net.Uri;
+import android.provider.MediaStore;
+import android.provider.OpenableColumns;
+import android.util.Log;
+
+
+import java.io.File;
+
+public class MovieTitleHelper {
+ private static final String TAG = "MovieTitleHelper";
+ private static final boolean LOG = true;
+
+ public static String getTitleFromMediaData(final Context context, final Uri uri) {
+ String title = null;
+ Cursor cursor = null;
+ try {
+ String data = Uri.decode(uri.toString());
+ data = data.replaceAll("'", "''");
+ final String where = "_data LIKE '%" + data.replaceFirst("file:///", "") + "'";
+ cursor = context.getContentResolver().query(
+ MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
+ new String[] {
+ OpenableColumns.DISPLAY_NAME
+ }, where, null, null);
+ if (LOG) {
+ Log.v(
+ TAG,
+ "setInfoFromMediaData() cursor="
+ + (cursor == null ? "null" : cursor.getCount()));
+ }
+ if (cursor != null && cursor.moveToFirst()) {
+ title = cursor.getString(0);
+ }
+ } catch (final SQLiteException ex) {
+ ex.printStackTrace();
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+ if (LOG) {
+ Log.v(TAG, "setInfoFromMediaData() return " + title);
+ }
+ return title;
+ }
+
+ public static String getTitleFromDisplayName(final Context context, final Uri uri) {
+ String title = null;
+ Cursor cursor = null;
+ try {
+ cursor = context.getContentResolver().query(uri,
+ new String[] {
+ OpenableColumns.DISPLAY_NAME
+ }, null, null, null);
+ if (cursor != null && cursor.moveToFirst()) {
+ title = cursor.getString(0);
+ }
+ } catch (final SQLiteException ex) {
+ ex.printStackTrace();
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+ if (LOG) {
+ Log.v(TAG, "getTitleFromDisplayName() return " + title);
+ }
+ return title;
+ }
+
+ public static String getTitleFromUri(final Uri uri) {
+ final String title = Uri.decode(uri.getLastPathSegment());
+ if (LOG) {
+ Log.v(TAG, "getTitleFromUri() return " + title);
+ }
+ return title;
+ }
+
+ public static String getTitleFromData(final Context context, final Uri uri) {
+ String title = null;
+ Cursor cursor = null;
+ try {
+ cursor = context.getContentResolver().query(uri,
+ new String[] {
+ "_data"
+ }, null, null, null);
+ if (cursor != null && cursor.moveToFirst()) {
+ final File file = new File(cursor.getString(0));
+ title = file.getName();
+ }
+ } catch (final SQLiteException ex) {
+ ex.printStackTrace();
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+ if (LOG) {
+ Log.v(TAG, "getTitleFromData() return " + title);
+ }
+ return title;
+ }
+}
diff --git a/src/org/codeaurora/gallery3d/video/SettingsActivity.java b/src/org/codeaurora/gallery3d/video/SettingsActivity.java
new file mode 100755
index 000000000..450f10d7c
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/SettingsActivity.java
@@ -0,0 +1,251 @@
+package org.codeaurora.gallery3d.video;
+
+import android.app.ActionBar;
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.SystemProperties;
+import android.preference.CheckBoxPreference;
+import android.preference.EditTextPreference;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceCategory;
+import android.preference.RingtonePreference;
+import android.preference.PreferenceScreen;
+import android.provider.ContactsContract;
+import android.provider.Telephony;
+import android.telephony.TelephonyManager;
+import android.text.method.DigitsKeyListener;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.MenuItem;
+import com.android.gallery3d.R;
+
+import java.util.ArrayList;
+
+public class SettingsActivity extends PreferenceActivity {
+
+ public static final String PREFERENCE_RTP_MINPORT = "rtp_min_port";
+ public static final String PREFERENCE_RTP_MAXPORT = "rtp_max_port";
+ public static final String PREFERENCE_RTCP_MINPORT = "rtcp_min_port";
+ public static final String PREFERENCE_RTCP_MAXPORT = "rtcp_max_port";
+ public static final String PREFERENCE_BUFFER_SIZE = "buffer_size";
+ public static final String PREFERENCE_APN = "apn";
+
+ private EditTextPreference mRtpMinPort;
+ private EditTextPreference mRtpMaxPort;
+ private EditTextPreference mRtcpMinPort;
+ private EditTextPreference mRtcpMaxPort;
+ private EditTextPreference mBufferSize;
+ private PreferenceScreen mApn;
+ private CheckBoxPreference mRepeat;
+
+ private static final int SELECT_APN = 1;
+ public static final String PREFERRED_APN_URI = "content://telephony/carriers/preferapn";
+ private static final Uri PREFERAPN_URI = Uri.parse(PREFERRED_APN_URI);
+ private static final int ID_INDEX = 0;
+ private static final int NAME_INDEX = 1;
+
+ private boolean mUseNvOperatorForEhrpd = SystemProperties.getBoolean(
+ "persist.radio.use_nv_for_ehrpd", false);
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ addPreferencesFromResource(R.xml.rtsp_settings_preferences);
+
+ SharedPreferences mPref;
+ mPref = getPreferenceScreen().getSharedPreferences();
+ String rtpMinport = mPref.getString(PREFERENCE_RTP_MINPORT, "8192");
+ String rtpMaxport = mPref.getString(PREFERENCE_RTP_MAXPORT, "65535");
+ String rtcpMinport = mPref.getString(PREFERENCE_RTCP_MAXPORT, null);
+ String rtcpMaxport = mPref.getString(PREFERENCE_RTCP_MAXPORT, null);
+ String bufferSize = mPref.getString(PREFERENCE_BUFFER_SIZE, null);
+
+ mRtpMinPort = (EditTextPreference) findPreference(PREFERENCE_RTP_MINPORT);
+ mRtpMinPort.getEditText().setKeyListener(DigitsKeyListener.getInstance("0123456789"));
+ mRtpMinPort.setSummary(rtpMinport);
+ mRtpMinPort.setText(rtpMinport);
+ mRtpMinPort.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ final String summary = newValue.toString();
+ mRtpMinPort.setSummary(summary);
+ Log.d("rtsp", "z66 summary = " + summary);
+ android.provider.Settings.System.putString(getContentResolver(),
+ "streaming_min_udp_port", summary);
+ return true;
+ }
+ });
+
+ mRtpMaxPort = (EditTextPreference) findPreference(PREFERENCE_RTP_MAXPORT);
+ mRtpMaxPort.getEditText().setKeyListener(DigitsKeyListener.getInstance("0123456789"));
+ mRtpMaxPort.setSummary(rtpMaxport);
+ mRtpMaxPort.setText(rtpMaxport);
+ mRtpMaxPort.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ final String summary = newValue.toString();
+ mRtpMaxPort.setSummary(summary);
+ Log.w("rtsp", "z82 summary = " + summary);
+ android.provider.Settings.System.putString(getContentResolver(),
+ "streaming_max_udp_port", summary);
+ return true;
+ }
+ });
+ mRtcpMinPort = (EditTextPreference) findPreference(PREFERENCE_RTCP_MINPORT);
+ mRtcpMinPort.getEditText().setKeyListener(DigitsKeyListener.getInstance("0123456789"));
+ mRtcpMinPort.setSummary(rtcpMinport);
+ mRtcpMinPort.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ final String summary = newValue.toString();
+ mRtcpMinPort.setSummary(summary);
+ return true;
+ }
+ });
+ mRtcpMaxPort = (EditTextPreference) findPreference(PREFERENCE_RTCP_MAXPORT);
+ mRtcpMaxPort.getEditText().setKeyListener(DigitsKeyListener.getInstance("0123456789"));
+ mRtcpMaxPort.setSummary(rtcpMaxport);
+ mRtcpMaxPort.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ final String summary = newValue.toString();
+ mRtcpMaxPort.setSummary(summary);
+ return true;
+ }
+ });
+
+ mBufferSize = (EditTextPreference) findPreference(PREFERENCE_BUFFER_SIZE);
+ mBufferSize.getEditText().setKeyListener(DigitsKeyListener.getInstance("0123456789"));
+ mBufferSize.setSummary(bufferSize);
+ mBufferSize.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ final String summary = newValue.toString();
+ mBufferSize.setSummary(summary);
+ return true;
+ }
+ });
+
+ mApn = (PreferenceScreen) findPreference(PREFERENCE_APN);
+ mApn.setSummary(getDefaultApnName());
+ mApn.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
+ public boolean onPreferenceClick(Preference preference) {
+ Intent intent = new Intent();
+ intent.setClassName("com.android.settings", "com.android.settings.ApnSettings");
+ startActivityForResult(intent, SELECT_APN);
+ return true;
+ }
+ });
+
+ ActionBar ab = getActionBar();
+ ab.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
+ ab.setDisplayHomeAsUpEnabled(true);
+ ab.setTitle(R.string.setting);
+ }
+
+ private String getDefaultApnName() {
+
+ // to find default key
+ String key = null;
+ String name = null;
+ Cursor cursor = getContentResolver().query(PREFERAPN_URI, new String[] {
+ "_id"
+ }, null, null, Telephony.Carriers.DEFAULT_SORT_ORDER);
+ if (cursor.getCount() > 0) {
+ cursor.moveToFirst();
+ key = cursor.getString(ID_INDEX);
+ Log.v("settingActivty", "default apn key = " + key);
+ }
+ cursor.close();
+
+ // to find default proxy
+ String where = getOperatorNumericSelection();
+
+ cursor = getContentResolver().query(Telephony.Carriers.CONTENT_URI, new String[] {
+ "_id", "name", "apn", "type"
+ }, where, null, Telephony.Carriers.DEFAULT_SORT_ORDER);
+
+ while (cursor != null && cursor.moveToNext()) {
+ String curKey = cursor.getString(cursor.getColumnIndex("_id"));
+ String curName = cursor.getString(cursor.getColumnIndex("name"));
+ if (curKey.equals(key)) {
+ Log.d("rtsp", "getDefaultApnName, find, key=" + curKey + ",curName=" + curName);
+ name = curName;
+ break;
+ }
+ }
+
+ if (cursor != null) {
+ cursor.close();
+ }
+ return name;
+
+ }
+
+ private String getSelectedApnKey() {
+ String key = null;
+
+ Cursor cursor = getContentResolver().query(PREFERAPN_URI, new String[] {
+ "_id", "name"
+ }, null, null, null);
+ if (cursor.getCount() > 0) {
+ cursor.moveToFirst();
+ key = cursor.getString(NAME_INDEX);
+ }
+ cursor.close();
+
+ Log.w("rtsp", "getSelectedApnKey key = " + key);
+ if (null == key)
+ return new String("null");
+ return key;
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ switch (requestCode) {
+ case SELECT_APN:
+ setResult(resultCode);
+ finish();
+ Log.w("rtsp", "onActivityResult requestCode = " + requestCode);
+ break;
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // TODO Auto-generated method stub
+ if (item.getItemId() == android.R.id.home) {
+ finish();
+ }
+ return true;
+ }
+
+ private String getOperatorNumericSelection() {
+ String[] mccmncs = getOperatorNumeric();
+ String where;
+ where = (mccmncs[0] != null) ? "numeric=\"" + mccmncs[0] + "\"" : "";
+ where += (mccmncs[1] != null) ? " or numeric=\"" + mccmncs[1] + "\"" : "";
+ Log.d("SettingsActivity", "getOperatorNumericSelection: " + where);
+ return where;
+ }
+
+ private String[] getOperatorNumeric() {
+ ArrayList<String> result = new ArrayList<String>();
+ String mccMncFromSim = null;
+ if (mUseNvOperatorForEhrpd) {
+ String mccMncForEhrpd = SystemProperties.get("ro.cdma.home.operator.numeric", null);
+ if (mccMncForEhrpd != null && mccMncForEhrpd.length() > 0) {
+ result.add(mccMncForEhrpd);
+ }
+ }
+
+ mccMncFromSim = TelephonyManager.getDefault().getSimOperator();
+
+ if (mccMncFromSim != null && mccMncFromSim.length() > 0) {
+ result.add(mccMncFromSim);
+ }
+ return result.toArray(new String[2]);
+ }
+}
diff --git a/src/org/codeaurora/gallery3d/video/StreamingHooker.java b/src/org/codeaurora/gallery3d/video/StreamingHooker.java
new file mode 100644
index 000000000..d4fa43fc5
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/StreamingHooker.java
@@ -0,0 +1,78 @@
+package org.codeaurora.gallery3d.video;
+
+import android.content.Intent;
+import android.net.Uri;
+import android.provider.Browser;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+
+import com.android.gallery3d.R;
+import org.codeaurora.gallery3d.ext.MovieUtils;
+
+public class StreamingHooker extends MovieHooker {
+ private static final String TAG = "StreamingHooker";
+ private static final boolean LOG = true;
+
+ private static final String ACTION_STREAMING = "org.codeaurora.settings.streaming";
+ private static final int MENU_INPUT_URL = 1;
+ private static final int MENU_SETTINGS = 2;
+ private static final int MENU_DETAIL = 3;
+
+ public static final String KEY_LOGO_BITMAP = "logo-bitmap";
+
+ @Override
+ public boolean onCreateOptionsMenu(final Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ // when in rtsp streaming type, generally it only has one uri.
+ menu.add(0, getMenuActivityId(MENU_INPUT_URL), 0, R.string.input_url);
+ menu.add(0, getMenuActivityId(MENU_SETTINGS), 0, R.string.streaming_settings);
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(final Menu menu) {
+ super.onPrepareOptionsMenu(menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(final MenuItem item) {
+ super.onOptionsItemSelected(item);
+ switch (getMenuOriginalId(item.getItemId())) {
+ case MENU_INPUT_URL:
+ gotoInputUrl();
+ return true;
+ case MENU_SETTINGS:
+ gotoSettings();
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private void gotoInputUrl() {
+ final String appName = getClass().getName();
+ final Intent intent = new Intent();
+ intent.setAction(Intent.ACTION_VIEW);
+ intent.setData(Uri.parse("about:blank"));
+ intent.putExtra("inputUrl", true);
+ intent.putExtra(Browser.EXTRA_APPLICATION_ID, appName);
+ getContext().startActivity(intent);
+ if (LOG) {
+ Log.v(TAG, "gotoInputUrl() appName=" + appName);
+ }
+ }
+
+ private void gotoSettings() {
+ final Intent intent = new Intent(ACTION_STREAMING);
+ // intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
+ // | Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);
+ // intent.putExtra(KEY_LOGO_BITMAP,
+ // getIntent().getParcelableExtra(KEY_LOGO_BITMAP));
+ getContext().startActivity(intent);
+ if (LOG) {
+ Log.v(TAG, "gotoInputUrl()");
+ }
+ }
+}