/*
* Copyright (C) 2012 YIXIA.COM
*
* 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.vanco.abplayer.view;
import io.vov.vitamio.MediaPlayer;
import io.vov.vitamio.MediaPlayer.OnBufferingUpdateListener;
import io.vov.vitamio.MediaPlayer.OnCompletionListener;
import io.vov.vitamio.MediaPlayer.OnErrorListener;
import io.vov.vitamio.MediaPlayer.OnHWRenderFailedListener;
import io.vov.vitamio.MediaPlayer.OnInfoListener;
import io.vov.vitamio.MediaPlayer.OnPreparedListener;
import io.vov.vitamio.MediaPlayer.OnSeekCompleteListener;
import io.vov.vitamio.MediaPlayer.OnTimedTextListener;
import io.vov.vitamio.MediaPlayer.OnVideoSizeChangedListener;
import io.vov.vitamio.Vitamio;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.view.SurfaceHolder;
import com.vanco.abplayer.util.Logger;
import com.yixia.zi.utils.Log;
public class PlayerService extends Service implements
OnBufferingUpdateListener, OnCompletionListener, OnPreparedListener,
OnVideoSizeChangedListener, OnErrorListener, OnInfoListener,
OnSeekCompleteListener, OnTimedTextListener {
private MediaPlayer mPlayer;
private VPlayerListener mListener;
private Uri mUri;
private Uri mOldUri;
private float mSeekTo = -1f;
private boolean mFromNotification;
private String[] mSubPaths;
private boolean mInitialized;
private final IBinder mBinder = new LocalBinder();
private TelephonyManager mTelephonyManager;
private int mCurrentState;
private SurfaceHolder mSurfaceHolder;
public static final int VPLYAER_NOTIFICATION_ID = 1;
public static final int STATE_PREPARED = -1;
public static final int STATE_PLAYING = 0;
public static final int STATE_NEED_RESUME = 1;
public static final int STATE_STOPPED = 2;
public static final int STATE_RINGING = 3;
private int mLastAudioTrack = -1;
private String mLastSubTrack;
private int mLastSubTrackId = -1;
private long mMediaId = -1l;
public class LocalBinder extends Binder {
public PlayerService getService() {
return PlayerService.this;
}
}
@Override
public void onCreate() {
super.onCreate();
mInitialized = false;
mTelephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
mTelephonyManager.listen(mPhoneListener,
PhoneStateListener.LISTEN_CALL_STATE);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (Vitamio.isInitialized(this)) {
vplayerInit(intent.getBooleanExtra("isHWCodec", false));
} else {
stopSelf();
}
Log.d("CREATE OK");
return super.onStartCommand(intent, flags, startId);
}
private void vplayerInit(boolean isHWCodec) {
mPlayer = new MediaPlayer(PlayerService.this.getApplicationContext(),
isHWCodec);
mPlayer.setOnHWRenderFailedListener(new OnHWRenderFailedListener() {
@Override
public void onFailed() {
if (mListener != null)
mListener.onHWRenderFailed();
}
});
mPlayer.setOnBufferingUpdateListener(PlayerService.this);
mPlayer.setOnCompletionListener(PlayerService.this);
mPlayer.setOnPreparedListener(PlayerService.this);
mPlayer.setOnVideoSizeChangedListener(PlayerService.this);
mPlayer.setOnErrorListener(PlayerService.this);
mPlayer.setOnInfoListener(PlayerService.this);
}
public void releaseContext() {
if (mPlayer != null)
mPlayer.release();
mPlayer = null;
}
@Override
public IBinder onBind(Intent intent) {
Log.d("BIND OK : " + intent.getPackage());
return mBinder;
}
@Override
public void onDestroy() {
super.onDestroy();
release(true);
releaseContext();
}
public boolean isInitialized() {
return mInitialized;
}
private String mTitle;
public boolean initialize(Uri filePath, String displayName,
boolean saveUri, float startPos, VPlayerListener listener,
int parentId, boolean isHWCodec) {
if (mPlayer == null)
vplayerInit(isHWCodec);
mTitle = displayName;
mListener = listener;
mOldUri = mUri;
mUri = filePath;
mSeekTo = startPos;
mMediaId = -1;
mLastAudioTrack = -1;
mLastSubTrackId = -1;
mLastSubTrack = "";
setMediaTrack();
Log.i("%s ==> %s, %s, %s, %s", mOldUri, mUri, mInitialized, mPrepared,
mVideoSizeKnown);
mFromNotification = mInitialized && mUri != null
&& mUri.equals(mOldUri);
mListener.onOpenStart();
if (!mFromNotification)
openVideo();
else
openSuccess();
return mInitialized;
}
private void setMediaTrack() {
}
private void openVideo() {
if (mUri == null || mPlayer == null)
return;
mPlayer.reset();
mInitialized = false;
mPrepared = false;
mVideoSizeKnown = false;
try {
mPlayer.setScreenOnWhilePlaying(true);
mPlayer.setDataSource(PlayerService.this, mUri);
// if (mLastAudioTrack != -1)
// mPlayer.setInitialAudioTrack(mLastAudioTrack);
// if (mLastSubTrackId != -1)
// mPlayer.setInitialSubTrack(mLastSubTrackId);
if (mSurfaceHolder != null && mSurfaceHolder.getSurface() != null
&& mSurfaceHolder.getSurface().isValid())
mPlayer.setDisplay(mSurfaceHolder);
mPlayer.prepareAsync();
} catch (IllegalArgumentException e) {
Logger.e("openVideo", e);
} catch (IllegalStateException e) {
Logger.e("openVideo", e);
} catch (IOException e) {
Logger.e("openVideo", e);
}
}
public Uri getUri() {
return mUri;
}
public long getMediaId() {
return mMediaId;
}
public int getLastAudioTrack() {
return mLastAudioTrack;
}
public String getLastSubTrack() {
return mLastSubTrack;
}
public int getLastSubTrackId() {
return mLastSubTrackId;
}
public void setVPlayerListener(VPlayerListener listener) {
mListener = listener;
}
public void setState(int state) {
mCurrentState = state;
}
public boolean needResume() {
return mInitialized
&& (mCurrentState == STATE_NEED_RESUME || mCurrentState == STATE_PREPARED);
}
public boolean ringingState() {
return mInitialized && mCurrentState == STATE_RINGING;
}
public void release() {
release(true);
}
private void release(boolean all) {
if (mPlayer != null) {
if (mListener != null)
mListener.onCloseStart();
mPlayer.reset();
mInitialized = false;
mPrepared = false;
mVideoSizeKnown = false;
if (mListener != null)
mListener.onCloseComplete();
}
if (all) {
mListener = null;
mUri = null;
}
}
public void stop() {
if (mInitialized) {
mPlayer.pause();
}
}
public void start() {
if (mInitialized) {
mPlayer.start();
setState(STATE_PLAYING);
}
}
public void setDisplay(SurfaceHolder surface) {
mSurfaceHolder = surface;
if (mPlayer != null)
mPlayer.setDisplay(surface);
}
public void releaseSurface() {
if (mInitialized)
mPlayer.releaseDisplay();
}
public boolean isPlaying() {
return (mInitialized && mPlayer.isPlaying());
}
public int getVideoWidth() {
if (mInitialized)
return mPlayer.getVideoWidth();
return 0;
}
public int getVideoHeight() {
if (mInitialized)
return mPlayer.getVideoHeight();
return 0;
}
public float getVideoAspectRatio() {
if (mInitialized)
return mPlayer.getVideoAspectRatio();
return 0f;
}
public long getDuration() {
if (mInitialized)
return mPlayer.getDuration();
return 0;
}
public long getCurrentPosition() {
if (mInitialized)
return mPlayer.getCurrentPosition();
return 0;
}
public Bitmap getCurrentFrame() {
if (mInitialized)
return mPlayer.getCurrentFrame();
return null;
}
public float getBufferProgress() {
if (mInitialized)
return mPlayer.getBufferProgress();
return 0f;
}
public void seekTo(float percent) {
if (mInitialized)
mPlayer.seekTo((int) (percent * getDuration()));
}
public String getMetaEncoding() {
if (mInitialized)
return mPlayer.getMetaEncoding();
return null;
}
public void setAudioTrack(int num) {
if (mInitialized)
mPlayer.selectTrack(num);
// mPlayer.setAudioTrack(num);
}
public int getAudioTrack() {
if (mInitialized)
return mPlayer.getAudioTrack();
return 0;
}
// public HashMap<String, Integer> getAudioTrackMap() {
// if (!mInitialized)
// return null;
// String enc = VP.DEFAULT_META_ENCODING;
// return mPlayer.getAudioTrackMap(enc.equals(VP.DEFAULT_META_ENCODING) ?
// getMetaEncoding() : enc);
// }
//
// public HashMap<String, Object> getSubTrackMap() {
// if (!mInitialized)
// return null;
// String enc = VP.DEFAULT_SUB_ENCODING;
// HashMap<String, Object> trackMap = new HashMap<String, Object>();
// HashMap<String, Integer> m =
// mPlayer.getSubTrackMap(enc.equals(VP.DEFAULT_SUB_ENCODING) ?
// getMetaEncoding() : enc);
// if (m != null)
// for (String k : m.keySet())
// trackMap.put(k, m.get(k));
//
// if (mSubPaths != null)
// for (String s : mSubPaths)
// trackMap.put(new File(s).getName(), s);
//
// return trackMap;
// }
//
// public int getSubTrack() {
// if (mInitialized)
// return mPlayer.getSubTrack();
// return 0;
// }
//
// public void setSubTrack(int id) {
// if (mInitialized)
// mPlayer.setSubTrack(id);
// }
//
// public String getSubPath() {
// if (mInitialized)
// return mPlayer.getSubPath();
// return null;
// }
public void setSubShown(boolean shown) {
if (mInitialized)
mPlayer.setTimedTextShown(shown);// setSubtitleShown ->
// setTimedTextShown 4.0
}
public boolean isBuffering() {
return (mInitialized && mPlayer.isBuffering());
}
public void setBuffer(int bufSize) {
if (mInitialized)
mPlayer.setBufferSize(bufSize);
}
public void setVolume(float left, float right) {
if (mInitialized) {
if (left <= 0f)
left = 0f;
else if (left >= 1f)
left = 1f;
if (right <= 0f)
right = 0f;
else if (right >= 1f)
right = 1f;
mPlayer.setVolume(left, right);
}
}
public void setVideoQuality(int quality) {
if (mInitialized)
mPlayer.setVideoQuality(quality);
}
public void setDeinterlace(boolean deinterlace) {
if (mInitialized)
mPlayer.setDeinterlace(deinterlace);
}
// public int getSubLocation() {
// if (mInitialized)
// return mPlayer.getSubLocation();
// return -1;
// }
//
public void setSubEncoding(String encoding) {
if (mInitialized) {
String enc = encoding.equals(VP.DEFAULT_SUB_ENCODING) ? null
: encoding;
mPlayer.setTimedTextEncoding(enc);// setSubEncoding ->
// setTimedTextEncoding
}
}
public void setSubPath(String subPath) {
if (mInitialized)
mPlayer.addTimedTextSource(subPath);
// mPlayer.setSubPath(subPath);
}
public static interface VPlayerListener {
public void onHWRenderFailed();
public void onVideoSizeChanged(int width, int height);
public void onSubChanged(String text);
public void onSubChanged(byte[] pixels, int width, int height);
public void onOpenStart();
public void onOpenSuccess();
public void onOpenFailed();
public void onBufferStart();
public void onBufferComplete();
public void onDownloadRateChanged(int kbPerSec);
public void onPlaybackComplete();
public void onCloseStart();
public void onCloseComplete();
}
private PhoneStateListener mPhoneListener = new PhoneStateListener() {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
case TelephonyManager.CALL_STATE_RINGING:
if (isPlaying()) {
stop();
setState(STATE_RINGING);
}
break;
default:
break;
}
}
};
private boolean mVideoSizeKnown = false;
private boolean mPrepared = false;
@Override
public void onVideoSizeChanged(MediaPlayer arg0, int arg1, int arg2) {
mVideoSizeKnown = true;
if (mListener != null)
mListener.onVideoSizeChanged(arg1, arg2);
}
@Override
public void onPrepared(MediaPlayer arg0) {
mPrepared = true;
openSuccess();
}
private void openSuccess() {
mInitialized = true;
if (!mFromNotification && mSeekTo > 0 && mSeekTo < 1)
seekTo(mSeekTo);
mSeekTo = -1;
mListener.onOpenSuccess();
if (!mFromNotification) {
setSubEncoding(VP.DEFAULT_SUB_ENCODING);
if (mUri != null)
mSubPaths = getSubFiles(mUri.getPath());
if (mSubPaths != null)
setSubPath(FileUtils.getCanonical(new File(mSubPaths[0])));
setSubShown(VP.DEFAULT_SUB_SHOWN);
}
}
@Override
public void onCompletion(MediaPlayer arg0) {
if (mListener != null) {
mListener.onPlaybackComplete();
} else {
release(true);
}
}
@Override
public void onBufferingUpdate(MediaPlayer arg0, int arg1) {
}
@Override
public void onSeekComplete(MediaPlayer arg0) {
}
@Override
public boolean onInfo(MediaPlayer arg0, int arg1, int arg2) {
switch (arg1) {
case MediaPlayer.MEDIA_INFO_BUFFERING_START:
if (mListener != null)
mListener.onBufferStart();
else
mPlayer.pause();
break;
case MediaPlayer.MEDIA_INFO_BUFFERING_END:
if (mListener != null)
mListener.onBufferComplete();
else
mPlayer.start();
break;
case MediaPlayer.MEDIA_INFO_DOWNLOAD_RATE_CHANGED:
if (mListener != null)
mListener.onDownloadRateChanged(arg2);
break;
}
return true;
}
@Override
public boolean onError(MediaPlayer arg0, int arg1, int arg2) {
mListener.onOpenFailed();
return true;
}
private String[] getSubFiles(String videoPath) {
ArrayList<String> files = new ArrayList<String>();
for (String ext : MediaPlayer.SUB_TYPES) {
File s = new File(videoPath.substring(0,
videoPath.lastIndexOf('.') > 0 ? videoPath.lastIndexOf('.')
: videoPath.length())
+ ext);
if (s.exists() && s.isFile() && s.canRead())
files.add(s.getAbsolutePath());
}
if (files.isEmpty())
return null;
else
return files.toArray(new String[files.size()]);
}
@Override
public void onTimedText(String text) {
if (mListener != null)
mListener.onSubChanged(text);
}
@Override
public void onTimedTextUpdate(byte[] pixels, int width, int height) {
if (mListener != null)
mListener.onSubChanged(pixels, width, height);
}
// @Override
// public void onSubtitleUpdate(String arg0) {
// if (mListener != null)
// mListener.onSubChanged(arg0);
// }
//
// @Override
// public void onSubtitleUpdate(byte[] arg0, int arg1, int arg2) {
// if (mListener != null)
// mListener.onSubChanged(arg0, arg1, arg2);
// }
}