/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.softwinner.TvdVideo; import java.io.File; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Collections; import android.app.Dialog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.IContentProvider; import android.content.Intent; import android.content.DialogInterface.OnCancelListener; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.res.Resources; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.hardware.input.InputManager; import android.media.MediaPlayer; import android.media.MediaPlayer.SubInfo; import android.media.MediaPlayer.TrackInfoVendor; import android.net.Uri; import android.os.Handler; import android.os.Message; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.provider.MediaStore; import android.provider.MediaStore.Video; import android.util.Log; import android.view.DisplayManagerAw; import android.view.Gravity; import android.view.IWindowManager; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import com.softwinner.TvdVideo.JumpView.OnTimeConfirmListener; public class MovieViewControl implements MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener, MediaController.OnListDataChanged, VideoView.OnSubFocusItems{ @SuppressWarnings("unused") private static final String TAG = "MovieViewControl"; private static final String STORE_NAME = "VideoSetting"; private static final String EDITOR_SUBGATE = "MovieViewControl.SUBGATE"; private static final String EDITOR_SUBSELECT = "MovieViewControl.SUBSELECT"; private static final String EDITOR_SUBCHARSET = "MovieViewControl.SUBCHARSET"; private static final String EDITOR_SUBCOLOR = "MovieViewControl.SUBCOLOR"; private static final String EDITOR_SUBCHARSIZE = "MovieViewControl.SUBCHARSIZE"; private static final String EDITOR_SUBOFFSET = "MovieViewControl.SUBOFFSET"; private static final String EDITOR_SUBDELAY = "MovieViewControl.SUBDELAY"; private static final String EDITOR_ZOOM = "MovieViewControl.MODEZOOM"; private static final String EDITOR_MODE3D = "MovieViewControl.MODE3D"; private static final String EDITOR_MODEREPEAT = "MovieViewControl.MODEREPEAT"; private static final String EDITOR_TRACK = "MovieViewControl.TRACK"; private static final int DISMISS_DIALOG = 0x10; private static final int DISMISS_DELAY = 5000; // 5 s private BookmarkService mBookmarkService; private JumpView mJumpView; private final VideoView mVideoView; private final View mProgressView; private Dialog mReplayDialog; private Message mDismissMsg; private Uri mUri; private Context mContext; private boolean mToQuit = false; private boolean mOnPause, mFinishOnCompletion; private String mPlayListType; private final SharedPreferences sp; private final SharedPreferences.Editor editor; private Resources mRes; private int mCurrentIndex = 0, mRepeatMode = 0; private int mVideoPosition = 0; private ArrayList<String> mPlayList; private MediaController mMediaController; private Toast mJumpToast; private MyToast mSubtitleToast, mAudioToast, mPrevToast, mNextToast, mStopToast, mRepeatToast; private String[] mTransformSubtitle, mTransformTrack; private BroadcastReceiver mBroadcastReceiver; Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub if(msg.what == DISMISS_DIALOG && mReplayDialog.isShowing()) { mReplayDialog.dismiss(); } } }; Runnable mMode3DRunnable = null; Runnable mRepeatRunnable = null; Runnable mTrackRunnable = null; Runnable mZoomRunnable = null; Runnable mSubsetRunnable = null; Runnable mPlayingChecker = new Runnable() { public void run() { if (mVideoView.isPlaying()) { mProgressView.setVisibility(View.GONE); } else { mHandler.postDelayed(mPlayingChecker, 250); } } }; Runnable mPlayRunnable = new Runnable() { @Override public void run() { setImageButtonListener(); mVideoView.setVideoURI(mUri); mMediaController.setFilePathTextView(mUri.getPath()); mVideoView.requestFocus(); mVideoView.start(); mHandler.removeCallbacks(mPlayRunnable); } }; class MyToast extends Toast { View mNextView; int mDuration; public MyToast(Context context) { super(context); // TODO Auto-generated constructor stub LayoutInflater inflate = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mNextView = inflate.inflate(R.layout.transient_notification, null); mDuration = MyToast.LENGTH_SHORT; super.setView(mNextView); super.setDuration(mDuration); super.setGravity(Gravity.LEFT | Gravity.TOP, 100, 0); } @Override public void onHide() { // TODO Auto-generated method stub super.onHide(); if(mSubtitleToast.isShowing() && mTransformSubtitle != null) { String newSub = (String) ((TextView)mSubtitleToast.getView().findViewById(R.id.message)).getText(); for(int i = 0;i < mTransformSubtitle.length;i++) { if(newSub.equals(mTransformSubtitle[i])) { mVideoView.switchSub(i); break; } } }else if(mAudioToast.isShowing() && mTransformTrack != null){ String newTrack = (String) ((TextView)mAudioToast.getView().findViewById(R.id.message)).getText(); for(int i = 0;i < mTransformTrack.length;i++) { if(newTrack.equals(mTransformTrack[i])) { mVideoView.switchTrack(i); break; } } } } } public static String formatDuration(final Context context, int durationMs) { int duration = durationMs / 1000; int h = duration / 3600; int m = (duration - h * 3600) / 60; int s = duration - (h * 3600 + m * 60); String durationValue; if (h == 0) { durationValue = String.format("%02d:%02d", m, s); } else { durationValue = String.format("%d:%02d:%02d", h, m, s); } return durationValue; } public MovieViewControl(View rootView, Context context, Intent intent) { mVideoView = (VideoView) rootView.findViewById(R.id.surface_view); mProgressView = rootView.findViewById(R.id.progress_indicator); mContext = context; Log.d(TAG, "constructor: call Uri2File2Uri"); mUri = Uri2File2Uri(intent.getData()); mRes = mContext.getResources(); sp = mContext.getSharedPreferences(STORE_NAME, Context.MODE_PRIVATE); editor = sp.edit(); initToast(); // For streams that we expect to be slow to start up, show a // progress spinner until playback starts. String scheme = mUri.getScheme(); Log.d(TAG, "constructor: call getScheme() return " + scheme); if ("http".equalsIgnoreCase(scheme) || "rtsp".equalsIgnoreCase(scheme)) { mHandler.postDelayed(mPlayingChecker, 250); } else { mProgressView.setVisibility(View.GONE); } /* create playlist */ mFinishOnCompletion = intent.getBooleanExtra(MediaStore.EXTRA_FINISH_ON_COMPLETION, true); mPlayListType = intent.getStringExtra(MediaStore.PLAYLIST_TYPE); Log.d(TAG, "mPlayListType = " + mPlayListType); mPlayList = new ArrayList<String>(); if(mPlayListType != null) { if(mPlayListType.equalsIgnoreCase(MediaStore.PLAYLIST_TYPE_CUR_FOLDER)) { /* create playlist from current folder */ createFolderDispList(); } else if(mPlayListType.equalsIgnoreCase(MediaStore.PLAYLIST_TYPE_MEDIA_PROVIDER)) { /* create playlist from mediaprovider */ createMediaProviderDispList(mUri, mContext); } } else { Log.w(TAG,"*********** scheme is null or scheme != file, create playlist failed *************"); } mVideoView.setBDFolderPlayMode(intent.getBooleanExtra(MediaStore.EXTRA_BD_FOLDER_PLAY_MODE, false)); mVideoView.setOnSubFocusItems(this); mVideoView.setOnErrorListener(this); mVideoView.setOnCompletionListener(this); mVideoView.setVideoURI(mUri); Log.d(TAG, "constructor: create MediaController()"); mMediaController = new MediaController(context); setImageButtonListener(); mVideoView.setMediaController(mMediaController); Log.d(TAG, "constructor: mMediaController.setFilePathTextView(" + mUri.getPath() + ")"); mMediaController.setFilePathTextView(mUri.getPath()); // make the video view handle keys for seeking and pausing mVideoView.requestFocus(); mMediaController.setOnListDataChanged(this); mBookmarkService = new BookmarkService(mContext); final int bookmark = getBookmark(); if (bookmark > 0) { replayVideoDialog(); mVideoView.seekTo(bookmark); // deleteBookmark(); } Log.d(TAG, "constructor: call mVideoView.start()"); mVideoView.start(); } private Uri Uri2File2Uri(Uri videoUri) { String path = null; Cursor c = null; IContentProvider mMediaProvider = mContext.getContentResolver().acquireProvider("media"); String[] VIDEO_PROJECTION = new String[] { Video.Media.DATA }; Log.d(TAG, "enter Uri2File2Uri: videoUri = " + videoUri); /* get video file */ try { c = mMediaProvider.query(videoUri, VIDEO_PROJECTION, null, null, null, null); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } if(c != null) { Log.d(TAG, "mediaProvider.query return c != null"); try { while (c.moveToNext()) { path = c.getString(0); } } finally { c.close(); c = null; } } if(path != null) { return Uri.fromFile(new File(path)); }else { Log.w(TAG,"************ Uri2File2Uri failed ***************"); return videoUri; } } private void replayVideoDialog() { LayoutInflater inflate = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); View replayView = inflate.inflate(R.layout.dialog_replay, null); ((Button)replayView.findViewById(R.id.replay_confirm)).setOnClickListener(new View.OnClickListener(){ public void onClick(View arg0) { mHandler.removeMessages(DISMISS_DIALOG); mReplayDialog.dismiss(); mVideoView.setVideoURI(mUri); mVideoView.start(); } }); ((Button)replayView.findViewById(R.id.replay_cancel)).setOnClickListener(new View.OnClickListener(){ public void onClick(View arg0) { mHandler.removeMessages(DISMISS_DIALOG); mReplayDialog.dismiss(); } }); mReplayDialog = new Dialog(mContext,R.style.dialog); mReplayDialog.setContentView(replayView); mReplayDialog.show(); mDismissMsg = mHandler.obtainMessage(DISMISS_DIALOG); mHandler.sendMessageDelayed(mDismissMsg, DISMISS_DELAY); } private void initToast() { mJumpToast = Toast.makeText(mContext, "", Toast.LENGTH_SHORT); mJumpToast.setGravity(Gravity.CENTER, 0, 0); mSubtitleToast = new MyToast(mContext); mAudioToast = new MyToast(mContext); mPrevToast = new MyToast(mContext); mNextToast = new MyToast(mContext); mStopToast = new MyToast(mContext); mRepeatToast = new MyToast(mContext); ImageView imageView; imageView = (ImageView) mSubtitleToast.getView().findViewById(R.id.message_image); imageView.setImageResource(R.drawable.button_subtitle); imageView = (ImageView) mAudioToast.getView().findViewById(R.id.message_image); imageView.setImageResource(R.drawable.button_track); imageView = (ImageView) mPrevToast.getView().findViewById(R.id.message_image); imageView.setImageResource(R.drawable.button_prev); imageView = (ImageView) mNextToast.getView().findViewById(R.id.message_image); imageView.setImageResource(R.drawable.button_next); imageView = (ImageView) mStopToast.getView().findViewById(R.id.message_image); imageView.setImageResource(R.drawable.button_stop); imageView = (ImageView) mRepeatToast.getView().findViewById(R.id.message_image); imageView.setImageResource(R.drawable.button_repeat); TextView textView; textView = (TextView) mPrevToast.getView().findViewById(R.id.message); textView.setVisibility(View.GONE); textView = (TextView) mPrevToast.getView().findViewById(R.id.message); textView.setVisibility(View.GONE); } public void subFocusItems() { /* repeat mode */ mRepeatMode = sp.getInt(EDITOR_MODEREPEAT, 0); /* sub gate */ boolean gate = sp.getBoolean(EDITOR_SUBGATE, true); mVideoView.setSubGate(gate); /* sub color */ int[] listColor = mRes.getIntArray(R.array.screen_color_values); int clorIndex = sp.getInt(EDITOR_SUBCOLOR, 0); mVideoView.setSubColor(listColor[clorIndex]); /* sub char size */ int[] listCharsize = mRes.getIntArray(R.array.screen_charsize_values); int charsizeIndex = sp.getInt(EDITOR_SUBCHARSIZE, 2); mVideoView.setSubFontSize(listCharsize[charsizeIndex]); /* zoom mode */ int zoom = sp.getInt(EDITOR_ZOOM, 0); mVideoView.setZoomMode(zoom); } private static boolean uriSupportsBookmarks(Uri uri) { if (uri.getScheme() == null) { return false; } return ("file".equalsIgnoreCase(uri.getScheme())); } private int getBookmark() { return mBookmarkService.findByPath(mUri.getPath()); } private boolean deleteBookmark() { return mBookmarkService.delete(mUri.getPath()); } private void setBookmark(int bookmark) { if (!uriSupportsBookmarks(mUri)) { return; } String path = mUri.getPath(); if( mBookmarkService.findByPath(path) != 0 ) { mBookmarkService.update(path, bookmark); } else { mBookmarkService.save(path, bookmark); } } @Override public void initSubAndTrackInfo() { // TODO Auto-generated method stub /* get track info */ mTransformTrack = null; TrackInfoVendor[] trackList = mVideoView.getTrackList(); if(trackList != null) { int trackCount = trackList.length; mTransformTrack = new String[trackList.length]; for(int i = 0;i < trackCount;i++) { try { if(trackList[i].charset.equals(MediaPlayer.CHARSET_UNKNOWN)) { mTransformTrack[i] = new String(trackList[i].name, "UTF-8"); } else { mTransformTrack[i] = new String(trackList[i].name, trackList[i].charset); } } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block Log.w(TAG, "*********** unsupported encoding: "+trackList[i].charset); e.printStackTrace(); } } } /* get sub info */ mTransformSubtitle = null; SubInfo[] subList = mVideoView.getSubList(); if(subList != null) { int subCount = subList.length; mTransformSubtitle = new String[subList.length]; for(int i = 0;i < subCount;i++) { try { if(subList[i].charset.equals(MediaPlayer.CHARSET_UNKNOWN)) { mTransformSubtitle[i] = new String(subList[i].name, "UTF-8"); } else { mTransformSubtitle[i] = new String(subList[i].name, subList[i].charset); } } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block Log.w(TAG, "*********** unsupported encoding: "+subList[i].charset); e.printStackTrace(); } } } } private void sendKeyIntent(int keycode){ final int keyCode = keycode; // to avoid deadlock, start a thread to perform operations Thread sendKeyDelay = new Thread(){ public void run() { try { int count = 1; IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window")); for(int i = 0; i < count; i++){ Thread.sleep(100); long now = SystemClock.uptimeMillis(); if(!mOnPause) { KeyEvent keyDown = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 0); InputManager.getInstance().injectInputEvent(keyDown, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC); // wm.injectKeyEvent(keyDown, false); KeyEvent keyUp = new KeyEvent(now, now, KeyEvent.ACTION_UP, keyCode, 0); InputManager.getInstance().injectInputEvent(keyUp, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC); // wm.injectKeyEvent(keyUp, false); } } } catch (InterruptedException e) { e.printStackTrace(); }/* catch (RemoteException e) { e.printStackTrace(); }*/ } }; sendKeyDelay.start(); } private void createFolderDispList() { String fileNameText, filePathText; File filePath; String[] fileEndingVideo = mRes.getStringArray(R.array.fileEndingVideo); fileNameText = mUri.getPath(); int index = fileNameText.lastIndexOf('/'); if(index >= 0) { filePathText = fileNameText.substring(0, index); filePath = new File(filePathText); File[] fileList = filePath.listFiles(); if(fileList != null && filePath.isDirectory()) { for(File currenFile : fileList) { String fileName = currenFile.getName(); int indexPoint = fileName.lastIndexOf('.'); if(indexPoint > 0 && currenFile.isFile()) { String fileEnd = fileName.substring(indexPoint+1); for(int i = 0;i < fileEndingVideo.length; i++) { if(fileEnd.equalsIgnoreCase(fileEndingVideo[i])) { mPlayList.add(currenFile.getPath()); break; } } } } } } Collections.sort(mPlayList); /* get current index */ mCurrentIndex = 0; String mCurrentPath = mUri.getPath(); for(int i = 0;i < mPlayList.size();i++) { if( mCurrentPath.equalsIgnoreCase(mPlayList.get(i)) ) { mCurrentIndex = i; break; } } } private void createMediaProviderDispList(Uri uri, Context mContext) { Cursor c = null; IContentProvider mMediaProvider = mContext.getContentResolver().acquireProvider("media"); Uri mVideoUri = Video.Media.getContentUri("external"); String[] VIDEO_PROJECTION = new String[] { Video.Media.DATA }; /* get playlist */ try { c = mMediaProvider.query(mVideoUri, VIDEO_PROJECTION, null, null, null, null); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } if(c != null) { try { while (c.moveToNext()) { String path = c.getString(0); if(new File(path).exists()){ mPlayList.add(path); } } } finally { c.close(); c = null; } /* get current index */ mCurrentIndex = 0; String mCurrentPath = mUri.getPath(); for(int i = 0;i < mPlayList.size();i++) { if( mCurrentPath.equalsIgnoreCase(mPlayList.get(i)) ) { mCurrentIndex = i; break; } } } } private void updateDispList(String mediaPath) { int size = mPlayList.size(); String path; if(size > 0) { for(int i = size - 1; i >= 0; i--) { path = mPlayList.get(i); if(path.startsWith(mediaPath)) { mPlayList.remove(i); } } } } private void setImageButtonListener() { String scheme = mUri.getScheme(); if(scheme != null && scheme.equalsIgnoreCase("file")) { mMediaController.setPrevNextListeners(mNextListener, mPrevListener); } else { mMediaController.setPrevNextListeners(null, null); } if(mPlayList.size() > 0) { mMediaController.setRepeatListener(mRepeatModeListener); } mMediaController.set3DListener(mMode3DListener); mMediaController.setTrackListener(mTrackListener); mMediaController.setZoomListener(mZoomListener); mMediaController.setSubsetListener(mSubsetListener); mMediaController.setJumpListener(mJumpClickListener); } View.OnClickListener mNextListener = new View.OnClickListener() { public void onClick(View v) { PlayNext(); } }; View.OnClickListener mPrevListener = new View.OnClickListener() { public void onClick(View v) { PlayPrev(); } }; @Override public void OnMediaPrevKeyClickListener() { // TODO Auto-generated method stub mPrevToast.show(); PlayPrev(); } @Override public void OnMediaNextKeyClickListener() { // TODO Auto-generated method stub mNextToast.show(); PlayNext(); } @Override public void OnMediaStopKeyClickListener() { // TODO Auto-generated method stub mStopToast.show(); sendKeyIntent(KeyEvent.KEYCODE_BACK); } @Override public void OnMediaRepeatKeyClickListener() { // TODO Auto-generated method stub if(mPlayList.size() > 0) { String[] listModeRepeat = mRes.getStringArray(R.array.screen_repeat_entries); mRepeatMode = (mRepeatMode+1)%listModeRepeat.length; editor.putInt(EDITOR_MODEREPEAT, mRepeatMode); editor.commit(); TextView tv = (TextView) mRepeatToast.getView().findViewById(R.id.message); tv.setText(listModeRepeat[mRepeatMode]); mRepeatToast.show(); } else { TextView tv = (TextView) mRepeatToast.getView().findViewById(R.id.message); tv.setText(R.string.playlist_miss); mRepeatToast.show(); } } @Override public void OnMediaSubtitleKeyClickListener() { // TODO Auto-generated method stub TextView tv = (TextView) mSubtitleToast.getView().findViewById(R.id.message); if(mTransformSubtitle != null) { int focus; int subCount = mTransformSubtitle.length; focus = mVideoView.getCurSub(); /*if(mSubtitleToast.isShowing())*/ { String currentSub = tv.getText().toString(); for(int i = 0;i < mTransformSubtitle.length;i++) { if(currentSub.equals(mTransformSubtitle[i])) { focus = i; break; } } focus = (focus+1)%subCount; } if(focus < subCount) { tv.setText(mTransformSubtitle[focus]); } } else { String[] SubList = mRes.getStringArray(R.array.screen_select_entries); tv.setText(SubList[0]); } mSubtitleToast.show(); } @Override public void OnMediaAudioKeyClickListener() { // TODO Auto-generated method stub TextView tv = (TextView) mAudioToast.getView().findViewById(R.id.message); if(mTransformTrack != null) { int trackCount = mTransformTrack.length; int focus = mVideoView.getCurTrack(); /*if(mAudioToast.isShowing())*/ { String currentTrack = tv.getText().toString(); for(int i = 0;i < mTransformTrack.length;i++) { if(currentTrack.equals(mTransformTrack[i])) { focus = i; break; } } focus = (focus+1)%trackCount; } if(focus < trackCount) { tv.setText(mTransformTrack[focus]); } } else { String[] TrackList = mRes.getStringArray(R.array.screen_track_entries); tv.setText(TrackList[0]); } mAudioToast.show(); } private void PlayPrev() { int size = mPlayList.size(); if(mCurrentIndex >= 0 && size > 0) { if(size == 1) { mCurrentIndex = 0; } else if(mCurrentIndex == 0) { mCurrentIndex = size - 1; } else { mCurrentIndex = (mCurrentIndex-1)%size; } mUri = Uri.fromFile(new File(mPlayList.get(mCurrentIndex))); playFile(); } } private void PlayNext() { int size = mPlayList.size(); if(mCurrentIndex >= 0 && size > 0) { mCurrentIndex = (mCurrentIndex+1)%size; mUri = Uri.fromFile(new File(mPlayList.get(mCurrentIndex))); playFile(); } } private void playFile() { //mWakeLock.acquire(); mHandler.postDelayed(mPlayRunnable,500); //mWakeLock.release(); } View.OnClickListener mJumpClickListener = new View.OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub mMediaController.setHolding(true); OnTimeConfirmListener confirmListener = new OnTimeConfirmListener() { @Override public void onTimeConfirm(int time) { // TODO Auto-generated method stub Log.i("jump","*************time: "+time); int duration = mVideoView.getDuration()/1000; if(time <= duration) { mVideoView.seekTo(time*1000); }else { String string = mContext.getResources().getString(R.string.overflow_toast); string += String.format("%02d:%02d:%02d",duration/3600, duration/60%60, duration%60); mJumpToast.setText(string); mJumpToast.show(); } mJumpView.jumpViewDismiss(); mMediaController.setHolding(false); } }; OnCancelListener cancelListener = new OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { // TODO Auto-generated method stub mJumpView.jumpViewDismiss(); mMediaController.setHolding(false); } }; int duration = mVideoView.getDuration()/1000; mJumpView = new JumpView(mContext, duration, confirmListener); mJumpView.setOnCancelListener(cancelListener); } }; View.OnFocusChangeListener mMode3DListener = new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { // TODO Auto-generated method stub if(mMediaController.getMediaControlFocusId() == R.id.mode3D) { return; } if(hasFocus) { mMode3DRunnable = new Runnable() { @Override public void run() { // TODO Auto-generated method stub Log.w(TAG, "Mode3D has focused"); //int currentMode = mVideoView.getOutputDimensionType(); String[] listMode3D = mRes.getStringArray(R.array.screen_3d_entries); mMediaController.setListViewData(R.id.mode3D, 0, listMode3D); } }; mHandler.postDelayed(mMode3DRunnable, 200); } else { if(mMode3DRunnable != null) { mHandler.removeCallbacks(mMode3DRunnable); mMode3DRunnable = null; } } } }; View.OnFocusChangeListener mRepeatModeListener = new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { // TODO Auto-generated method stub if(mMediaController.getMediaControlFocusId() == R.id.repeat) { return; } if(hasFocus) { mRepeatRunnable = new Runnable() { @Override public void run() { // TODO Auto-generated method stub Log.w(TAG, "Mode repeat has focused"); int currentMode = sp.getInt(EDITOR_MODEREPEAT, 0); String[] listModeRepeat = mRes.getStringArray(R.array.screen_repeat_entries); mMediaController.setListViewData(R.id.repeat, currentMode, listModeRepeat); } }; mHandler.postDelayed(mRepeatRunnable, 200); } else { if(mRepeatRunnable != null) { mHandler.removeCallbacks(mRepeatRunnable); mRepeatRunnable = null; } } } }; View.OnFocusChangeListener mTrackListener = new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { // TODO Auto-generated method stub if(mMediaController.getMediaControlFocusId() == R.id.track) { return; } if(hasFocus) { mTrackRunnable = new Runnable() { @Override public void run() { // TODO Auto-generated method stub if(mTransformTrack != null) { int currentTrack = mVideoView.getCurTrack(); mMediaController.setListViewData(R.id.track, currentTrack, mTransformTrack); } else { mMediaController.setListViewData(R.id.track, 0, mRes.getStringArray(R.array.screen_track_entries)); } } }; mHandler.postDelayed(mTrackRunnable, 200); } else { if(mTrackRunnable != null) { mHandler.removeCallbacks(mTrackRunnable); mTrackRunnable = null; } } } }; View.OnFocusChangeListener mZoomListener = new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { // TODO Auto-generated method stub if(mMediaController.getMediaControlFocusId() == R.id.zoom) { return; } if(hasFocus) { mZoomRunnable = new Runnable() { @Override public void run() { // TODO Auto-generated method stub int currentMode = sp.getInt(EDITOR_ZOOM, 0); String[] listModeZoom = mRes.getStringArray(R.array.screen_zoom_entries); mMediaController.setListViewData(R.id.zoom, currentMode, listModeZoom); } }; mHandler.postDelayed(mZoomRunnable, 200); } else { if(mZoomRunnable != null) { mHandler.removeCallbacks(mZoomRunnable); mZoomRunnable = null; } } } }; View.OnFocusChangeListener mSubsetListener = new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { // TODO Auto-generated method stub if(mMediaController.getMediaControlFocusId() == R.id.subset) { return; } if(hasFocus) { mSubsetRunnable = new Runnable() { @Override public void run() { // TODO Auto-generated method stub String[] listSubset = mRes.getStringArray(R.array.screen_subset_entries); mMediaController.setListViewData(R.id.subset, 0, listSubset); } }; mHandler.postDelayed(mSubsetRunnable, 200); } else { if(mSubsetRunnable != null) { mHandler.removeCallbacks(mSubsetRunnable); mSubsetRunnable = null; } } } }; public void onCompletion(MediaPlayer arg0) { if(mJumpView != null) { mJumpView.jumpViewDismiss(); } onCompletion(); } public void onCompletion() { // TODO Auto-generated method stub mVideoView.setOnErrorListener(this); int size = mPlayList.size(); Log.i(TAG,"************************ in onCompletion, mToQuit: "+mToQuit+", mPlayList size: "+size+", mRepeatMode"+mRepeatMode); if(mCurrentIndex >= 0 && size > 0) { switch(mRepeatMode) { case 0: // repeat all { mCurrentIndex = (mCurrentIndex+1)%size; break; } case 1: // sequence play { if(mCurrentIndex + 1 < size) { mCurrentIndex++; }else { mToQuit = true; return; } break; } case 2: //repeat one { break; } case 3: // random play { mCurrentIndex = (int)(Math.random() * size); break; } default: break; } File nextFile = new File(mPlayList.get(mCurrentIndex)); if (!nextFile.exists()){ mToQuit = true; }else { mUri = Uri.fromFile(nextFile); playFile(); } } if(size == 0 && mFinishOnCompletion) { mToQuit = true; } } public void onPause() { mOnPause = true; mContext.unregisterReceiver(mBroadcastReceiver); mVideoPosition = mVideoView.getCurrentPosition(); int duration = mVideoView.getDuration(); // current time > 10s and save current position if(mVideoPosition > 10 * 1000 && duration - mVideoPosition > 10 * 1000) { setBookmark(mVideoPosition - 3 * 1000); } else{ deleteBookmark(); } if(mJumpView != null) { mJumpView.jumpViewDismiss(); } mHandler.removeCallbacksAndMessages(null); mVideoView.suspend(); } public void onResume() { if(mOnPause){ mVideoView.seekTo(mVideoPosition); mVideoView.resume(); mOnPause = false; } /* receive the device eject message */ mBroadcastReceiver = new BroadcastReceiver(){ @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub final String action = intent.getAction(); final String mediaPath = intent.getData().getPath(); if(action.equals(Intent.ACTION_MEDIA_EJECT)) { String path = mUri.getPath(); Log.i(TAG,"*********** media eject **********"); /* the current video's media was eject */ if(path.startsWith(mediaPath)) { Toast toast = Toast.makeText(mContext, R.string.play_finish, Toast.LENGTH_SHORT); toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); onCompletion(); } else if(mPlayList.size() > 0){ updateDispList(mediaPath); } } } }; IntentFilter iFilter = new IntentFilter(); iFilter.addAction(Intent.ACTION_MEDIA_EJECT); iFilter.addDataScheme("file"); mContext.registerReceiver(mBroadcastReceiver , iFilter); } public void onDestroy() { mVideoView.stopPlayback(); mBookmarkService.close(); } @Override public boolean onError(MediaPlayer arg0, int arg1, int arg2) { // TODO Auto-generated method stub mHandler.removeCallbacksAndMessages(null); mProgressView.setVisibility(View.GONE); mToQuit = true; return false; } public boolean toQuit() { return mToQuit; } @Override public void OnListDataChangedListener(int mediaControlFocusId, int selectedIterm) { // TODO Auto-generated method stub switch(mediaControlFocusId) { case R.id.mode3D: { if(selectedIterm > 1) { setSublistData(selectedIterm); } else { mMediaController.setGridViewData(selectedIterm, 0); } /* int focusItem = selectedIterm; int[] list = mRes.getIntArray(R.array.screen_3d_values); int currentMode = mVideoView.getOutputDimensionType(); if(currentMode == list[focusItem]) { break; } focusItem = focusItem%list.length; if( mVideoView.setOutputDimensionType(focusItem) != 0 ) { Log.w(TAG, "*********** change the 3D mode failed !"); } */ break; } case R.id.repeat: { mRepeatMode = selectedIterm; editor.putInt(EDITOR_MODEREPEAT, selectedIterm); editor.commit(); break; } case R.id.track: { if(selectedIterm == mVideoView.getCurTrack()) { break; } if( mVideoView.switchTrack(selectedIterm) != 0) { Log.w(TAG, "*********** change the sub track failed !"); } break; } case R.id.zoom: { if(selectedIterm == mVideoView.getZoomMode()) { break; } mVideoView.setZoomMode(selectedIterm); editor.putInt(EDITOR_ZOOM, selectedIterm); editor.commit(); break; } case R.id.subset: { setSublistData(selectedIterm); break; } default: break; } } private void setSublistData(int selectedIterm) { switch(selectedIterm) { case 0: { // set sub gate if(mMediaController.getMediaControlFocusId() == R.id.subset) { boolean gate = sp.getBoolean(EDITOR_SUBGATE, true); int focus = (gate==true) ? 0 : 1; String[] listGate = mRes.getStringArray(R.array.screen_gate_entries); mMediaController.setSublistViewData(0, focus, listGate); } break; } case 1: { // set sub select if(mMediaController.getMediaControlFocusId() == R.id.subset) { int focus = 0; if(mTransformSubtitle != null) { int subCount = mTransformSubtitle.length; focus = mVideoView.getCurSub(); mMediaController.setSublistViewData(1, focus, mTransformSubtitle); } else { String[] transformSub = mRes.getStringArray(R.array.screen_select_entries); mMediaController.setSublistViewData(1, focus, transformSub); } } break; } case 2: { // set sub color if(mMediaController.getMediaControlFocusId() == R.id.subset) { int focus = sp.getInt(EDITOR_SUBCOLOR, 0); String[] listColor = mRes.getStringArray(R.array.screen_color_entries); mMediaController.setSublistViewData(2, focus, listColor); } else if(mMediaController.getMediaControlFocusId() == R.id.mode3D) { /* set the 3D anaglagh */ int[] listAnaglaghValue = mRes.getIntArray(R.array.screen_3d_anaglagh_values); int currentAnaglagh = mVideoView.getAnaglaghType(); int focus = 0; for(int i = 0; i < listAnaglaghValue.length; i++ ) { if(currentAnaglagh == listAnaglaghValue[i]) { focus = i; break; } } String[] listAnaglaghEntry = mRes.getStringArray(R.array.screen_3d_anaglagh_entries); mMediaController.setSublistViewData(2, focus, listAnaglaghEntry); } break; } case 3: { // set sub charsize if(mMediaController.getMediaControlFocusId() == R.id.subset) { int focus = sp.getInt(EDITOR_SUBCHARSIZE, 2); String[] listcharsize = mRes.getStringArray(R.array.screen_charsize_entries); mMediaController.setSublistViewData(3, focus, listcharsize); } else if(mMediaController.getMediaControlFocusId() == R.id.mode3D) { /* set the 3D anaglagh */ int[] listAnaglaghValue = mRes.getIntArray(R.array.screen_3d_anaglagh_values); int currentAnaglagh = mVideoView.getAnaglaghType(); int focus = 0; for(int i = 0; i < listAnaglaghValue.length; i++ ) { if(currentAnaglagh == listAnaglaghValue[i]) { focus = i; break; } } String[] listAnaglaghEntry = mRes.getStringArray(R.array.screen_3d_anaglagh_entries); mMediaController.setSublistViewData(3, focus, listAnaglaghEntry); } break; } case 4: // set sub charset { int focus = 0; String currentCharset = mVideoView.getSubCharset(); String[] charsetValue = mRes.getStringArray(R.array.screen_charset_values); String[] listCharset = mRes.getStringArray(R.array.screen_charset_entries); for(int i = 0; i < charsetValue.length; i++) { if(currentCharset.equalsIgnoreCase(charsetValue[i])) { focus = i; break; } } mMediaController.setSublistViewData(4, focus, listCharset); break; } case 5: // set sub delay { int focus = 3; int subDelay = mVideoView.getSubDelay(); int[] listValue = mRes.getIntArray(R.array.screen_delay_values); for(int i = 0;i < listValue.length;i++) { if(subDelay == listValue[i]) { focus = i; break; } } String[] listDelay = mRes.getStringArray(R.array.screen_delay_entries); mMediaController.setSublistViewData(5, focus, listDelay); break; } case 6: { String[] listOffset = mRes.getStringArray(R.array.screen_offset_entries); mMediaController.setSublistViewData(6, 0, listOffset); break; } } } @Override public void OnSublistDataChangedListener(int listFoucsIndex, int selectedIterm) { // TODO Auto-generated method stub if(mMediaController.getMediaControlFocusId() == R.id.subset) { setSubsetListData(listFoucsIndex, selectedIterm); } else if(mMediaController.getMediaControlFocusId() == R.id.mode3D) { setMode3DListData(listFoucsIndex, selectedIterm); } } private void setSubsetListData(int listFoucsIndex, int selectedIterm) { switch(listFoucsIndex) { case 0: // set sub gate { boolean switchOn; if(selectedIterm == 0) { switchOn = true; } else { switchOn = false; } mVideoView.setSubGate(switchOn); editor.putBoolean(EDITOR_SUBGATE, switchOn); editor.commit(); break; } case 1: // set sub select { if(mVideoView.switchSub(selectedIterm) != 0) { Log.w(TAG, "*********** change the sub select failed !"); } break; } case 2: // set sub color { int[] listColor = mRes.getIntArray(R.array.screen_color_values); if(mVideoView.setSubColor(listColor[selectedIterm]) != 0) { Log.w(TAG, "*********** change the sub color failed !"); } else { editor.putInt(EDITOR_SUBCOLOR, selectedIterm); editor.commit(); } break; } case 3: // set sub charsize { int[] listCharsize = mRes.getIntArray(R.array.screen_charsize_values); if(mVideoView.setSubFontSize(listCharsize[selectedIterm]) != 0) { Log.w(TAG, "*********** change the sub font size failed !"); } else { editor.putInt(EDITOR_SUBCHARSIZE, selectedIterm); editor.commit(); } break; } case 4: // set sub charset { String[] listCharSet = mRes.getStringArray(R.array.screen_charset_values); if(mVideoView.setSubCharset(listCharSet[selectedIterm]) != 0) { Log.w(TAG, "*********** change the sub charset failed !"); } else { editor.putInt(EDITOR_SUBCHARSET, selectedIterm); editor.commit(); } break; } case 5: // set sub delay { int[] listDelay = mRes.getIntArray(R.array.screen_delay_values); if(mVideoView.setSubDelay(listDelay[selectedIterm]) != 0) { Log.w(TAG, "*********** change the sub delay failed !"); } break; } case 6: // set sub offset { int[] listOffset = mRes.getIntArray(R.array.screen_offset_values); if(mVideoView.setSubPosition(listOffset[selectedIterm]) != 0) { Log.w(TAG, "*********** change the sub offset failed !"); } break; } } } private void setMode3DListData(int listFoucsIndex, int selectedIterm) { // anaglagh mode if(listFoucsIndex >= 2) { if(listFoucsIndex == 2) { mVideoView.setInputDimensionType(MediaPlayer.PICTURE_3D_MODE_SIDE_BY_SIDE); } else if(listFoucsIndex == 3) { mVideoView.setInputDimensionType(MediaPlayer.PICTURE_3D_MODE_TOP_TO_BOTTOM); } switch(selectedIterm) { case 0: { mVideoView.setAnaglaghType(MediaPlayer.ANAGLAGH_RED_BLUE); break; } case 1: { mVideoView.setAnaglaghType(MediaPlayer.ANAGLAGH_RED_GREEN); break; } case 2: { mVideoView.setAnaglaghType(MediaPlayer.ANAGLAGH_RED_CYAN); break; } case 3: { mVideoView.setAnaglaghType(MediaPlayer.ANAGLAGH_COLOR); break; } case 4: { mVideoView.setAnaglaghType(MediaPlayer.ANAGLAGH_HALF_COLOR); break; } case 5: { mVideoView.setAnaglaghType(MediaPlayer.ANAGLAGH_OPTIMIZED); break; } case 6: { mVideoView.setAnaglaghType(MediaPlayer.ANAGLAGH_YELLOW_BLUE); break; } } mVideoView.setOutputDimensionType(MediaPlayer.DISPLAY_3D_MODE_ANAGLAGH); } else { // 2D | 3D if(listFoucsIndex == 0) { // 2D switch(selectedIterm) { case 0: { mVideoView.setInputDimensionType(MediaPlayer.PICTURE_3D_MODE_SIDE_BY_SIDE); mVideoView.setOutputDimensionType(MediaPlayer.DISPLAY_3D_MODE_HALF_PICTURE); break; } case 1: { mVideoView.setInputDimensionType(MediaPlayer.PICTURE_3D_MODE_TOP_TO_BOTTOM); mVideoView.setOutputDimensionType(MediaPlayer.DISPLAY_3D_MODE_HALF_PICTURE); break; } case 2: { mVideoView.setOutputDimensionType(MediaPlayer.DISPLAY_3D_MODE_2D); break; } } } else if(listFoucsIndex == 1) { // 3D /* check Mode 3D enable */ DisplayManagerAw displayManager = (DisplayManagerAw) mContext.getSystemService(Context.DISPLAY_SERVICE_AW); int displayType = displayManager.getDisplayOutputType(0); if(displayType != DisplayManagerAw.DISPLAY_OUTPUT_TYPE_HDMI || displayType == DisplayManagerAw.DISPLAY_OUTPUT_TYPE_HDMI && displayManager.isSupport3DMode() <= 0 ) { int id = R.string.not_hdmi; if(displayType == DisplayManagerAw.DISPLAY_OUTPUT_TYPE_HDMI) { id = R.string.not_support; } Toast toast = Toast.makeText(mContext, id, Toast.LENGTH_SHORT); toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); return; } switch(selectedIterm) { case 0: { mVideoView.setInputDimensionType(MediaPlayer.PICTURE_3D_MODE_SIDE_BY_SIDE); break; } case 1: { mVideoView.setInputDimensionType(MediaPlayer.PICTURE_3D_MODE_TOP_TO_BOTTOM); break; } case 2: { mVideoView.setInputDimensionType(MediaPlayer.PICTURE_3D_MODE_DOUBLE_STREAM); break; } case 3: { mVideoView.setInputDimensionType(MediaPlayer.PICTURE_3D_MODE_LINE_INTERLEAVE); break; } case 4: { mVideoView.setInputDimensionType(MediaPlayer.PICTURE_3D_MODE_COLUME_INTERLEAVE); break; } } mVideoView.setOutputDimensionType(MediaPlayer.DISPLAY_3D_MODE_3D); } } } } class BookmarkService { private final int MAXRECORD = 100; private MangerDatabase dbmanger; public BookmarkService(Context context) { dbmanger=new MangerDatabase(context); } public void save(String path, int bookmark) { long time = System.currentTimeMillis(); SQLiteDatabase database= dbmanger.getWritableDatabase(); if(getCount() == MAXRECORD) { long oldestTime = time; Cursor cursor = database.query(MangerDatabase.NAME, null, null, null, null, null, null); if(cursor != null) { try { while(cursor.moveToNext()) { long recordTime = cursor.getLong(2); if(recordTime < oldestTime) { oldestTime = recordTime; } } } finally { cursor.close(); } } if(oldestTime < time) { database.execSQL("delete from "+MangerDatabase.NAME+" where "+MangerDatabase.TIME+"=?" ,new Object[] {oldestTime}); } } database.execSQL("insert into "+MangerDatabase.NAME+"("+ MangerDatabase.PATH+","+MangerDatabase.BOOKMARK+","+MangerDatabase.TIME+ ") values(?,?,?)", new Object[] {path, bookmark, time}); } public boolean delete(String path) { boolean ret = false; SQLiteDatabase database= dbmanger.getWritableDatabase(); Cursor cursor = database.rawQuery("select * from "+MangerDatabase.NAME+" where "+MangerDatabase.PATH+"=?" , new String[]{path}); if(cursor != null) { database.execSQL("delete from "+MangerDatabase.NAME+" where "+MangerDatabase.PATH+"=?" ,new Object[] {path}); cursor.close(); ret = true; } return ret; } public void update(String path, int bookmark) { long time = System.currentTimeMillis(); SQLiteDatabase database= dbmanger.getWritableDatabase(); database.execSQL("update "+MangerDatabase.NAME+" set "+ MangerDatabase.BOOKMARK+"=?,"+MangerDatabase.TIME+"=? where "+MangerDatabase.PATH+"=?" , new Object[] {bookmark, time, path}); } public int findByPath(String path) { int ret = 0; SQLiteDatabase database= dbmanger.getWritableDatabase(); Cursor cursor = database.rawQuery("select * from "+MangerDatabase.NAME+" where "+MangerDatabase.PATH+"=?" , new String[]{path}); if(cursor != null) { try { if(cursor.moveToNext()) { ret = cursor.getInt(1); } } finally { cursor.close(); } } return ret; } public int getCount() { long count = 0; SQLiteDatabase database= dbmanger.getWritableDatabase(); Cursor cursor = database.rawQuery("select count(*) from "+MangerDatabase.NAME, null); if(cursor != null) { try { if(cursor.moveToLast()) { count = cursor.getLong(0); } } finally { cursor.close(); } } return (int)count; } public void close() { dbmanger.close(); } } class MangerDatabase extends SQLiteOpenHelper { public static final String NAME="breakpoint"; public static final String PATH="path"; public static final String BOOKMARK="bookmark"; public static final String TIME="time"; private static final int version = 1; public MangerDatabase(Context context) { super(context, NAME, null, version); // TODO Auto-generated constructor stub } @Override public void onCreate(SQLiteDatabase arg0) { // TODO Auto-generated method stub Log.w("MangerDatabase", "*********** create MangerDatabase !"); arg0.execSQL("CREATE TABLE IF NOT EXISTS "+NAME+" ("+PATH+" varchar PRIMARY KEY, "+BOOKMARK+" INTEGR, "+TIME+" LONG)"); } @Override public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) { // TODO Auto-generated method stub arg0.execSQL("DROP TABLE IF EXISTS "+NAME); onCreate(arg0); } }