Add VanillaMediaPlayer class
This commit adds a new VanillaMediaPlayer class, extending the media player The class helps to simplify some tasks and also provides a nice getDataSource method
This commit is contained in:
parent
3974138451
commit
411db0bc91
@ -26,13 +26,18 @@ public class BastpUtil {
|
||||
private RGLruCache rgCache;
|
||||
|
||||
public BastpUtil() {
|
||||
rgCache = new RGLruCache(16); /* Cache up to 16 entries */
|
||||
rgCache = new RGLruCache(64); /* Cache up to 64 entries */
|
||||
}
|
||||
|
||||
|
||||
/** Returns the ReplayGain values of 'path' as <track,album>
|
||||
*/
|
||||
public float[] getReplayGainValues(String path) {
|
||||
if(path == null) {
|
||||
// path must not be null
|
||||
path = "//null\\";
|
||||
}
|
||||
|
||||
float[] cached = rgCache.get(path);
|
||||
|
||||
if(cached == null) {
|
||||
|
@ -43,7 +43,6 @@ import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.media.audiofx.AudioEffect;
|
||||
import android.media.AudioManager;
|
||||
import android.media.MediaPlayer;
|
||||
import android.os.Build;
|
||||
@ -301,8 +300,8 @@ public final class PlaybackService extends Service
|
||||
|
||||
private Looper mLooper;
|
||||
private Handler mHandler;
|
||||
MediaPlayer mMediaPlayer;
|
||||
MediaPlayer mPreparedMediaPlayer;
|
||||
VanillaMediaPlayer mMediaPlayer;
|
||||
VanillaMediaPlayer mPreparedMediaPlayer;
|
||||
private boolean mMediaPlayerInitialized;
|
||||
private PowerManager.WakeLock mWakeLock;
|
||||
private NotificationManager mNotificationManager;
|
||||
@ -404,6 +403,7 @@ public final class PlaybackService extends Service
|
||||
mPlayCounts = new PlayCountsHelper(this);
|
||||
|
||||
mMediaPlayer = getNewMediaPlayer();
|
||||
mPreparedMediaPlayer = getNewMediaPlayer();
|
||||
mBastpUtil = new BastpUtil();
|
||||
mReadahead = new ReadaheadThread();
|
||||
mReadahead.start();
|
||||
@ -554,14 +554,15 @@ public final class PlaybackService extends Service
|
||||
|
||||
if (mMediaPlayer != null) {
|
||||
saveState(mMediaPlayer.getCurrentPosition());
|
||||
Intent i = new Intent(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION);
|
||||
i.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, mMediaPlayer.getAudioSessionId());
|
||||
i.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, getPackageName());
|
||||
sendBroadcast(i);
|
||||
mMediaPlayer.release();
|
||||
mMediaPlayer = null;
|
||||
}
|
||||
|
||||
if (mPreparedMediaPlayer != null) {
|
||||
mPreparedMediaPlayer.release();
|
||||
mPreparedMediaPlayer = null;
|
||||
}
|
||||
|
||||
MediaButtonReceiver.unregisterMediaButton(this);
|
||||
|
||||
try {
|
||||
@ -582,24 +583,18 @@ public final class PlaybackService extends Service
|
||||
/**
|
||||
* Returns a new MediaPlayer object
|
||||
*/
|
||||
private MediaPlayer getNewMediaPlayer() {
|
||||
MediaPlayer mp = new MediaPlayer();
|
||||
private VanillaMediaPlayer getNewMediaPlayer() {
|
||||
VanillaMediaPlayer mp = new VanillaMediaPlayer(this);
|
||||
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
||||
mp.setOnCompletionListener(this);
|
||||
mp.setOnErrorListener(this);
|
||||
return mp;
|
||||
}
|
||||
|
||||
public void prepareMediaPlayer(MediaPlayer mp, String path) throws IOException{
|
||||
public void prepareMediaPlayer(VanillaMediaPlayer mp, String path) throws IOException{
|
||||
mp.setDataSource(path);
|
||||
mp.prepare();
|
||||
|
||||
Intent i = new Intent(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION);
|
||||
i.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, mp.getAudioSessionId());
|
||||
i.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, getPackageName());
|
||||
sendBroadcast(i);
|
||||
|
||||
applyReplayGain(mp, path);
|
||||
applyReplayGain(mp);
|
||||
}
|
||||
|
||||
|
||||
@ -608,23 +603,17 @@ public final class PlaybackService extends Service
|
||||
* the (maybe just changed) user settings
|
||||
*/
|
||||
private void refreshReplayGainValues() {
|
||||
Song curSong = getSong(0);
|
||||
|
||||
if(mMediaPlayer == null)
|
||||
return;
|
||||
if(curSong == null)
|
||||
return;
|
||||
|
||||
applyReplayGain(mMediaPlayer, curSong.path);
|
||||
if(mPreparedMediaPlayer != null) {
|
||||
applyReplayGain(mPreparedMediaPlayer, getSong(1).path);
|
||||
}
|
||||
applyReplayGain(mMediaPlayer);
|
||||
applyReplayGain(mPreparedMediaPlayer);
|
||||
}
|
||||
|
||||
|
||||
private void applyReplayGain(MediaPlayer mp, String path) {
|
||||
/***
|
||||
* Reads the replay gain value of the media players data source
|
||||
* and adjusts the volume
|
||||
*/
|
||||
private void applyReplayGain(VanillaMediaPlayer mp) {
|
||||
|
||||
float[] rg = getReplayGainValues(path); /* track, album */
|
||||
float[] rg = getReplayGainValues(mp.getDataSource()); /* track, album */
|
||||
float adjust = 0f;
|
||||
|
||||
if(mReplayGainAlbumEnabled) {
|
||||
@ -674,22 +663,16 @@ public final class PlaybackService extends Service
|
||||
* re-creates a newone if needed.
|
||||
*/
|
||||
private void triggerGaplessUpdate() {
|
||||
|
||||
if(mMediaPlayerInitialized != true)
|
||||
return;
|
||||
|
||||
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN)
|
||||
return; /* setNextMediaPlayer is supported since JB */
|
||||
|
||||
if(mPreparedMediaPlayer != null) {
|
||||
/* an old prepared player exists and is
|
||||
* most likely invalid -> destroy it now
|
||||
*/
|
||||
mMediaPlayer.setNextMediaPlayer(null);
|
||||
mPreparedMediaPlayer.release();
|
||||
mPreparedMediaPlayer = null;
|
||||
}
|
||||
|
||||
|
||||
// Reset any preparations
|
||||
mMediaPlayer.setNextMediaPlayer(null);
|
||||
mPreparedMediaPlayer.reset();
|
||||
|
||||
int fa = finishAction(mState);
|
||||
Song nextSong = getSong(1);
|
||||
if( nextSong != null
|
||||
@ -697,7 +680,6 @@ public final class PlaybackService extends Service
|
||||
&& fa != SongTimeline.FINISH_STOP_CURRENT
|
||||
&& !mTimeline.isEndOfQueue() ) {
|
||||
try {
|
||||
mPreparedMediaPlayer = getNewMediaPlayer();
|
||||
prepareMediaPlayer(mPreparedMediaPlayer, nextSong.path);
|
||||
mMediaPlayer.setNextMediaPlayer(mPreparedMediaPlayer);
|
||||
Log.d("VanillaMusic", "New media player prepared with path "+nextSong.path);
|
||||
@ -1197,12 +1179,12 @@ public final class PlaybackService extends Service
|
||||
mMediaPlayerInitialized = false;
|
||||
mMediaPlayer.reset();
|
||||
|
||||
if(mPreparedMediaPlayer != null &&
|
||||
mPreparedMediaPlayer.isPlaying()) {
|
||||
|
||||
mMediaPlayer.release();
|
||||
if(mPreparedMediaPlayer.isPlaying()) {
|
||||
VanillaMediaPlayer tmpPlayer = mMediaPlayer;
|
||||
mMediaPlayer = mPreparedMediaPlayer;
|
||||
mPreparedMediaPlayer = null;
|
||||
mPreparedMediaPlayer = tmpPlayer;
|
||||
mPreparedMediaPlayer.reset();
|
||||
Log.v("VanillaMusic", "Swapped media players");
|
||||
}
|
||||
else if(song.path != null) {
|
||||
prepareMediaPlayer(mMediaPlayer, song.path);
|
||||
@ -1210,10 +1192,9 @@ public final class PlaybackService extends Service
|
||||
|
||||
|
||||
mMediaPlayerInitialized = true;
|
||||
|
||||
// Cancel any queued gapless triggers: we are updating it right now
|
||||
// Cancel any pending gapless updates and re-send them
|
||||
mHandler.removeMessages(GAPLESS_UPDATE);
|
||||
triggerGaplessUpdate();
|
||||
mHandler.sendEmptyMessage(GAPLESS_UPDATE);
|
||||
|
||||
if (mPendingSeek != 0 && mPendingSeekSong == song.id) {
|
||||
mMediaPlayer.seekTo(mPendingSeek);
|
||||
@ -1677,7 +1658,7 @@ public final class PlaybackService extends Service
|
||||
// This might get canceled if setCurrentSong() also fired a call
|
||||
// to processSong();
|
||||
mHandler.removeMessages(GAPLESS_UPDATE);
|
||||
mHandler.sendEmptyMessageDelayed(GAPLESS_UPDATE, 350);
|
||||
mHandler.sendEmptyMessageDelayed(GAPLESS_UPDATE, 500);
|
||||
|
||||
ArrayList<PlaybackActivity> list = sActivities;
|
||||
for (int i = list.size(); --i != -1; )
|
||||
|
110
src/ch/blinkenlights/android/vanilla/VanillaMediaPlayer.java
Normal file
110
src/ch/blinkenlights/android/vanilla/VanillaMediaPlayer.java
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Adrian Ulrich <adrian@blinkenlights.ch>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
package ch.blinkenlights.android.vanilla;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.media.MediaPlayer;
|
||||
import android.media.audiofx.AudioEffect;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
|
||||
public class VanillaMediaPlayer extends MediaPlayer {
|
||||
|
||||
private Context mContext;
|
||||
private String mDataSource;
|
||||
private int mClaimedAudioSessionId = 0;
|
||||
|
||||
/**
|
||||
* Constructs a new VanillaMediaPlayer class
|
||||
*/
|
||||
public VanillaMediaPlayer(Context context) {
|
||||
super();
|
||||
mContext = context;
|
||||
_claimAudioSession();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the media player to an unconfigured state
|
||||
*/
|
||||
public void reset() {
|
||||
mDataSource = null;
|
||||
super.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases the media player and frees any claimed AudioEffect
|
||||
*/
|
||||
public void release() {
|
||||
_releaseAudioSession();
|
||||
mDataSource = null;
|
||||
super.release();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the data source to use
|
||||
*/
|
||||
public void setDataSource(String dataSource) throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
|
||||
mDataSource = dataSource;
|
||||
super.setDataSource(mDataSource);
|
||||
_claimAudioSession();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configured data source, may be null
|
||||
*/
|
||||
public String getDataSource() {
|
||||
return mDataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new AudioEffect for our AudioSession
|
||||
*/
|
||||
private void _claimAudioSession() {
|
||||
// No active audio session -> claim one
|
||||
Log.v("VanillaMusic", "_claimAudioSession() -> "+mClaimedAudioSessionId+" -> "+this);
|
||||
if (mClaimedAudioSessionId == 0) {
|
||||
mClaimedAudioSessionId = this.getAudioSessionId();
|
||||
Intent i = new Intent(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION);
|
||||
i.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, mClaimedAudioSessionId);
|
||||
i.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, mContext.getPackageName());
|
||||
mContext.sendBroadcast(i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases a previously claimed audio session id
|
||||
*/
|
||||
private void _releaseAudioSession() {
|
||||
Log.v("VanillaMusic", "_releaseAudioSession() "+mClaimedAudioSessionId+" -> "+this);
|
||||
|
||||
if (mClaimedAudioSessionId != 0) {
|
||||
Intent i = new Intent(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION);
|
||||
i.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, mClaimedAudioSessionId);
|
||||
i.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, mContext.getPackageName());
|
||||
mContext.sendBroadcast(i);
|
||||
mClaimedAudioSessionId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user