Reorganized and cleaned up the playback service a bit. Added the ability to fade a song in/out on play/pause.
This commit is contained in:
parent
b32feb38fe
commit
257791eff6
13 changed files with 324 additions and 174 deletions
|
|
@ -27,8 +27,8 @@ android {
|
|||
applicationId "com.kabouzeid.gramophone"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 22
|
||||
versionCode 33
|
||||
versionName "0.9.18b dev-1"
|
||||
versionCode 35
|
||||
versionName "0.9.19b dev-1"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
|
|
|
|||
|
|
@ -11,11 +11,9 @@ import android.preference.PreferenceManager;
|
|||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.kabouzeid.gramophone.App;
|
||||
import com.kabouzeid.gramophone.R;
|
||||
import com.kabouzeid.gramophone.loader.SongLoader;
|
||||
import com.kabouzeid.gramophone.misc.AppKeys;
|
||||
import com.kabouzeid.gramophone.model.MusicRemoteEvent;
|
||||
import com.kabouzeid.gramophone.model.Song;
|
||||
import com.kabouzeid.gramophone.service.MusicService;
|
||||
import com.kabouzeid.gramophone.util.InternalStorageUtil;
|
||||
|
|
@ -46,13 +44,11 @@ public class MusicPlayerRemote {
|
|||
MusicService.MusicBinder binder = (MusicService.MusicBinder) service;
|
||||
musicService = binder.getService();
|
||||
musicService.restorePreviousState(restoredOriginalQueue, playingQueue, position);
|
||||
postToBus(MusicRemoteEvent.SERVICE_CONNECTED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
musicService = null;
|
||||
postToBus(MusicRemoteEvent.SERVICE_DISCONNECTED);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -278,11 +274,6 @@ public class MusicPlayerRemote {
|
|||
}
|
||||
}
|
||||
|
||||
private static void postToBus(int event) {
|
||||
MusicRemoteEvent musicRemoteEvent = new MusicRemoteEvent(event);
|
||||
App.bus.post(musicRemoteEvent);
|
||||
}
|
||||
|
||||
public static int getAudioSessionId() {
|
||||
if (musicService != null) {
|
||||
return musicService.getAudioSessionId();
|
||||
|
|
@ -304,8 +295,6 @@ public class MusicPlayerRemote {
|
|||
playingQueue = restoredQueue;
|
||||
MusicPlayerRemote.restoredOriginalQueue = restoredOriginalQueue;
|
||||
position = restoredPosition;
|
||||
|
||||
postToBus(MusicRemoteEvent.STATE_RESTORED);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "error while restoring music service state", e);
|
||||
playingQueue = new ArrayList<>();
|
||||
|
|
|
|||
|
|
@ -1,36 +0,0 @@
|
|||
package com.kabouzeid.gramophone.model;
|
||||
|
||||
/**
|
||||
* @author Karim Abou Zeid (kabouzeid)
|
||||
*/
|
||||
public class MusicRemoteEvent {
|
||||
public static final int PLAY = 0;
|
||||
public static final int PAUSE = 1;
|
||||
public static final int RESUME = 2;
|
||||
public static final int STOP = 3;
|
||||
public static final int NEXT = 4;
|
||||
public static final int PREV = 5;
|
||||
public static final int TRACK_CHANGED = 6;
|
||||
|
||||
public static final int SONG_COMPLETED = 7;
|
||||
public static final int QUEUE_COMPLETED = 8;
|
||||
|
||||
public static final int SERVICE_CONNECTED = 9;
|
||||
public static final int SERVICE_DISCONNECTED = 10;
|
||||
|
||||
public static final int STATE_SAVED = 11;
|
||||
public static final int STATE_RESTORED = 12;
|
||||
|
||||
public static final int SHUFFLE_MODE_CHANGED = 13;
|
||||
public static final int REPEAT_MODE_CHANGED = 14;
|
||||
|
||||
private final int action;
|
||||
|
||||
public MusicRemoteEvent(int action) {
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public int getAction() {
|
||||
return action;
|
||||
}
|
||||
}
|
||||
|
|
@ -16,23 +16,26 @@ import android.media.RemoteControlClient;
|
|||
import android.media.audiofx.AudioEffect;
|
||||
import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.PowerManager;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.kabouzeid.gramophone.App;
|
||||
import com.kabouzeid.gramophone.R;
|
||||
import com.kabouzeid.gramophone.appwidget.MusicPlayerWidget;
|
||||
import com.kabouzeid.gramophone.helper.PlayingNotificationHelper;
|
||||
import com.kabouzeid.gramophone.helper.ShuffleHelper;
|
||||
import com.kabouzeid.gramophone.misc.AppKeys;
|
||||
import com.kabouzeid.gramophone.model.MusicRemoteEvent;
|
||||
import com.kabouzeid.gramophone.model.Song;
|
||||
import com.kabouzeid.gramophone.util.InternalStorageUtil;
|
||||
import com.kabouzeid.gramophone.util.MusicUtil;
|
||||
import com.kabouzeid.gramophone.util.PreferenceUtils;
|
||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||
import com.nostra13.universalimageloader.core.assist.FailReason;
|
||||
import com.nostra13.universalimageloader.core.assist.ImageSize;
|
||||
|
|
@ -41,10 +44,14 @@ import com.nostra13.universalimageloader.core.imageaware.NonViewAware;
|
|||
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class MusicService extends Service implements MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener, AudioManager.OnAudioFocusChangeListener {
|
||||
public static final String PHONOGRAPH_PACKAGE_NAME = "com.kabouzeid.gramophone";
|
||||
public static final String MUSIC_PACKAGE_NAME = "com.android.music";
|
||||
|
||||
public static final String ACTION_TOGGLE_PLAYBACK = "com.kabouzeid.gramophone.action.TOGGLE_PLAYBACK";
|
||||
public static final String ACTION_PLAY = "com.kabouzeid.gramophone.action.PLAY";
|
||||
public static final String ACTION_RESUME = "com.kabouzeid.gramophone.action.RESUME";
|
||||
|
|
@ -53,8 +60,18 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
|||
public static final String ACTION_SKIP = "com.kabouzeid.gramophone.action.SKIP";
|
||||
public static final String ACTION_REWIND = "com.kabouzeid.gramophone.action.REWIND";
|
||||
public static final String ACTION_QUIT = "com.kabouzeid.gramophone.action.QUIT";
|
||||
public static final String META_CHANGED = "com.android.music.metachanged";
|
||||
public static final String PLAYSTATE_CHANGED = "com.android.music.playstatechanged";
|
||||
|
||||
public static final String META_CHANGED = "com.kabouzeid.gramophone.metachanged";
|
||||
public static final String PLAYSTATE_CHANGED = "com.kabouzeid.gramophone.playstatechanged";
|
||||
public static final String REPEATMODE_CHANGED = "com.kabouzeid.gramophone.repeatmodechanged";
|
||||
public static final String SHUFFLEMODE_CHANGED = "com.kabouzeid.gramophone.shufflemodechanged";
|
||||
|
||||
private static final int FOCUSCHANGE = 5;
|
||||
private static final int DUCK = 6;
|
||||
private static final int UNDUCK = 7;
|
||||
private static final int FADEDOWNANDPAUSE = 8;
|
||||
private static final int FADEUPANDRESUME = 9;
|
||||
|
||||
public static final int SHUFFLE_MODE_NONE = 0;
|
||||
public static final int SHUFFLE_MODE_SHUFFLE = 1;
|
||||
public static final int REPEAT_MODE_NONE = 0;
|
||||
|
|
@ -88,6 +105,9 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
|||
private RemoteControlClient remoteControlClient;
|
||||
private PowerManager.WakeLock wakeLock;
|
||||
private String currentAlbumArtUri;
|
||||
private MusicPlayerHandler playerHandler;
|
||||
|
||||
private boolean fadingDown = false;
|
||||
|
||||
public MusicService() {
|
||||
}
|
||||
|
|
@ -107,6 +127,11 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
|||
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getClass().getName());
|
||||
wakeLock.setReferenceCounted(false);
|
||||
|
||||
final HandlerThread thread = new HandlerThread("MusicPlayerHandler",
|
||||
android.os.Process.THREAD_PRIORITY_BACKGROUND);
|
||||
thread.start();
|
||||
playerHandler = new MusicPlayerHandler(this, thread.getLooper());
|
||||
|
||||
registerEverything();
|
||||
}
|
||||
|
||||
|
|
@ -226,20 +251,11 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
|||
player.release();
|
||||
player = null;
|
||||
}
|
||||
playingNotificationHelper.updatePlayState(isPlaying());
|
||||
MusicPlayerWidget.updateWidgetsPlayState(this, isPlaying());
|
||||
remoteControlClient.setPlaybackState(RemoteControlClient.PLAYSTATE_STOPPED);
|
||||
notifyOnMusicRemoteEventListeners(MusicRemoteEvent.STOP);
|
||||
notifyChange(PLAYSTATE_CHANGED);
|
||||
}
|
||||
|
||||
public boolean isPlaying() {
|
||||
return player != null && isPlayerPrepared && player.isPlaying();
|
||||
}
|
||||
|
||||
private void notifyOnMusicRemoteEventListeners(int event) {
|
||||
MusicRemoteEvent musicRemoteEvent = new MusicRemoteEvent(event);
|
||||
App.bus.post(musicRemoteEvent);
|
||||
return player != null && isPlayerPrepared && !fadingDown && player.isPlaying();
|
||||
}
|
||||
|
||||
public void saveQueues() {
|
||||
|
|
@ -274,13 +290,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
|||
|
||||
@Override
|
||||
public void onCompletion(MediaPlayer mp) {
|
||||
notifyOnMusicRemoteEventListeners(MusicRemoteEvent.SONG_COMPLETED);
|
||||
if (isLastTrack() && getRepeatMode() == REPEAT_MODE_NONE) {
|
||||
notifyOnMusicRemoteEventListeners(MusicRemoteEvent.QUEUE_COMPLETED);
|
||||
playingNotificationHelper.updatePlayState(isPlaying());
|
||||
MusicPlayerWidget.updateWidgetsPlayState(this, isPlaying());
|
||||
remoteControlClient.setPlaybackState(RemoteControlClient.PLAYSTATE_STOPPED);
|
||||
notifyOnMusicRemoteEventListeners(MusicRemoteEvent.STOP);
|
||||
notifyChange(PLAYSTATE_CHANGED);
|
||||
} else {
|
||||
acquireWakeLock(30000);
|
||||
|
|
@ -293,7 +303,6 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
|||
if (isPlayerPrepared) {
|
||||
setPosition(getNextPosition(force));
|
||||
playSong();
|
||||
notifyOnMusicRemoteEventListeners(MusicRemoteEvent.NEXT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -313,28 +322,17 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
|||
} catch (Exception e) {
|
||||
player.reset();
|
||||
player = null;
|
||||
|
||||
notifyOnMusicRemoteEventListeners(MusicRemoteEvent.STOP);
|
||||
playingNotificationHelper.updatePlayState(false);
|
||||
MusicPlayerWidget.updateWidgetsPlayState(this, false);
|
||||
remoteControlClient.setPlaybackState(RemoteControlClient.PLAYSTATE_STOPPED);
|
||||
notifyChange(PLAYSTATE_CHANGED);
|
||||
|
||||
Toast.makeText(getApplicationContext(), getResources().getString(R.string.unplayable_file), Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
currentSongId = playingQueue.get(getPosition()).id;
|
||||
updateNotification();
|
||||
updateWidgets();
|
||||
updateRemoteControlClient();
|
||||
notifyChange(META_CHANGED);
|
||||
} else {
|
||||
playingNotificationHelper.updatePlayState(false);
|
||||
MusicPlayerWidget.updateWidgetsPlayState(this, false);
|
||||
notifyChange(PLAYSTATE_CHANGED);
|
||||
}
|
||||
}
|
||||
notifyOnMusicRemoteEventListeners(MusicRemoteEvent.TRACK_CHANGED);
|
||||
}
|
||||
|
||||
private void openAudioEffectSession() {
|
||||
|
|
@ -467,7 +465,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
|||
PreferenceManager.getDefaultSharedPreferences(this).edit()
|
||||
.putInt(AppKeys.SP_REPEAT_MODE, repeatMode)
|
||||
.apply();
|
||||
notifyOnMusicRemoteEventListeners(MusicRemoteEvent.REPEAT_MODE_CHANGED);
|
||||
notifyChange(REPEATMODE_CHANGED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -477,20 +475,15 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
|||
isPlayerPrepared = false;
|
||||
player.reset();
|
||||
player = null;
|
||||
notifyOnMusicRemoteEventListeners(MusicRemoteEvent.STOP);
|
||||
notifyChange(PLAYSTATE_CHANGED);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepared(MediaPlayer mp) {
|
||||
player.start();
|
||||
isPlayerPrepared = true;
|
||||
openAudioEffectSession();
|
||||
playingNotificationHelper.updatePlayState(isPlaying());
|
||||
MusicPlayerWidget.updateWidgetsPlayState(this, isPlaying());
|
||||
remoteControlClient.setPlaybackState(RemoteControlClient.PLAYSTATE_PLAYING);
|
||||
notifyOnMusicRemoteEventListeners(MusicRemoteEvent.PLAY);
|
||||
notifyChange(PLAYSTATE_CHANGED);
|
||||
resumePlaying();
|
||||
savePosition();
|
||||
releaseWakeLock();
|
||||
}
|
||||
|
|
@ -661,25 +654,38 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
|||
}
|
||||
|
||||
public void pausePlaying() {
|
||||
if (PreferenceUtils.getInstance(this).fadePlayPauseAndInterruptions()) {
|
||||
playerHandler.removeMessages(FADEUPANDRESUME);
|
||||
playerHandler.sendEmptyMessage(FADEDOWNANDPAUSE);
|
||||
} else {
|
||||
pause();
|
||||
}
|
||||
}
|
||||
|
||||
private void pause() {
|
||||
fadingDown = false;
|
||||
if (isPlaying()) {
|
||||
player.pause();
|
||||
playingNotificationHelper.updatePlayState(isPlaying());
|
||||
MusicPlayerWidget.updateWidgetsPlayState(this, isPlaying());
|
||||
remoteControlClient.setPlaybackState(RemoteControlClient.PLAYSTATE_PAUSED);
|
||||
notifyOnMusicRemoteEventListeners(MusicRemoteEvent.PAUSE);
|
||||
notifyChange(PLAYSTATE_CHANGED);
|
||||
}
|
||||
}
|
||||
|
||||
public void resumePlaying() {
|
||||
if (PreferenceUtils.getInstance(this).fadePlayPauseAndInterruptions()) {
|
||||
playerHandler.removeMessages(FADEDOWNANDPAUSE);
|
||||
playerHandler.sendEmptyMessage(FADEUPANDRESUME);
|
||||
} else {
|
||||
player.setVolume(1f, 1f);
|
||||
resume();
|
||||
}
|
||||
}
|
||||
|
||||
private void resume() {
|
||||
fadingDown = false;
|
||||
if (!isPlaying()) {
|
||||
if (requestFocus()) {
|
||||
if (isPlayerPrepared()) {
|
||||
player.start();
|
||||
playingNotificationHelper.updatePlayState(isPlaying());
|
||||
MusicPlayerWidget.updateWidgetsPlayState(this, isPlaying());
|
||||
remoteControlClient.setPlaybackState(RemoteControlClient.PLAYSTATE_PLAYING);
|
||||
notifyOnMusicRemoteEventListeners(MusicRemoteEvent.RESUME);
|
||||
notifyChange(PLAYSTATE_CHANGED);
|
||||
} else {
|
||||
playSong();
|
||||
|
|
@ -694,7 +700,6 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
|||
if (position != -1) {
|
||||
setPosition(getPreviousPosition(force));
|
||||
playSong();
|
||||
notifyOnMusicRemoteEventListeners(MusicRemoteEvent.PREV);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -788,7 +793,6 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
|||
this.shuffleMode = shuffleMode;
|
||||
ShuffleHelper.makeShuffleList(this.playingQueue, getPosition());
|
||||
setPosition(0);
|
||||
notifyOnMusicRemoteEventListeners(MusicRemoteEvent.SHUFFLE_MODE_CHANGED);
|
||||
break;
|
||||
case SHUFFLE_MODE_NONE:
|
||||
this.shuffleMode = shuffleMode;
|
||||
|
|
@ -800,24 +804,39 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
|||
}
|
||||
}
|
||||
setPosition(newPosition);
|
||||
notifyOnMusicRemoteEventListeners(MusicRemoteEvent.SHUFFLE_MODE_CHANGED);
|
||||
break;
|
||||
}
|
||||
notifyChange(SHUFFLEMODE_CHANGED);
|
||||
}
|
||||
|
||||
private void notifyChange(final String what) {
|
||||
//to let other apps know whats playing. i.E. last.fm (scrobbling) or musixmatch
|
||||
final Intent intent = new Intent(what);
|
||||
final Intent internalIntent = new Intent(what);
|
||||
final int position = getPosition();
|
||||
if (position >= 0 && !playingQueue.isEmpty()) {
|
||||
final Song currentSong = playingQueue.get(position);
|
||||
intent.putExtra("id", currentSong.id);
|
||||
intent.putExtra("artist", currentSong.artistName);
|
||||
intent.putExtra("album", currentSong.albumName);
|
||||
intent.putExtra("track", currentSong.title);
|
||||
internalIntent.putExtra("id", currentSong.id);
|
||||
internalIntent.putExtra("artist", currentSong.artistName);
|
||||
internalIntent.putExtra("album", currentSong.albumName);
|
||||
internalIntent.putExtra("track", currentSong.title);
|
||||
}
|
||||
internalIntent.putExtra("playing", isPlaying());
|
||||
sendStickyBroadcast(internalIntent);
|
||||
|
||||
//to let other apps know whats playing. i.E. last.fm (scrobbling) or musixmatch
|
||||
final Intent publicMusicIntent = new Intent(internalIntent);
|
||||
publicMusicIntent.setAction(what.replace(PHONOGRAPH_PACKAGE_NAME, MUSIC_PACKAGE_NAME));
|
||||
sendStickyBroadcast(publicMusicIntent);
|
||||
|
||||
if (what.equals(PLAYSTATE_CHANGED)) {
|
||||
final boolean isPlaying = isPlaying();
|
||||
playingNotificationHelper.updatePlayState(isPlaying);
|
||||
MusicPlayerWidget.updateWidgetsPlayState(this, isPlaying);
|
||||
remoteControlClient.setPlaybackState(isPlaying ? RemoteControlClient.PLAYSTATE_PLAYING : RemoteControlClient.PLAYSTATE_PAUSED);
|
||||
} else if (what.equals(META_CHANGED)) {
|
||||
updateNotification();
|
||||
updateWidgets();
|
||||
updateRemoteControlClient();
|
||||
}
|
||||
intent.putExtra("playing", isPlaying());
|
||||
sendStickyBroadcast(intent);
|
||||
}
|
||||
|
||||
public int getAudioSessionId() {
|
||||
|
|
@ -841,4 +860,113 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
|||
return MusicService.this;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class MusicPlayerHandler extends Handler {
|
||||
private final WeakReference<MusicService> mService;
|
||||
private float currentDuckVolume = 1.0f;
|
||||
private float currentPlayPauseFadeVolume = 1.0f;
|
||||
|
||||
public MusicPlayerHandler(final MusicService service, final Looper looper) {
|
||||
super(looper);
|
||||
mService = new WeakReference<>(service);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(final Message msg) {
|
||||
final MusicService service = mService.get();
|
||||
if (service == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (msg.what) {
|
||||
case DUCK:
|
||||
currentDuckVolume -= .05f;
|
||||
if (currentDuckVolume > .2f) {
|
||||
sendEmptyMessageDelayed(DUCK, 10);
|
||||
} else {
|
||||
currentDuckVolume = .2f;
|
||||
}
|
||||
service.player.setVolume(currentDuckVolume, currentDuckVolume);
|
||||
break;
|
||||
|
||||
case UNDUCK:
|
||||
currentDuckVolume += .05f;
|
||||
if (currentDuckVolume < 1.0f) {
|
||||
sendEmptyMessageDelayed(UNDUCK, 10);
|
||||
} else {
|
||||
currentDuckVolume = 1.0f;
|
||||
}
|
||||
service.player.setVolume(currentDuckVolume, currentDuckVolume);
|
||||
break;
|
||||
|
||||
case FADEDOWNANDPAUSE:
|
||||
if (!service.fadingDown) {
|
||||
service.fadingDown = true;
|
||||
service.notifyChange(PLAYSTATE_CHANGED);
|
||||
}
|
||||
service.fadingDown = true;
|
||||
currentPlayPauseFadeVolume -= .1f;
|
||||
if (currentPlayPauseFadeVolume > 0f) {
|
||||
sendEmptyMessageDelayed(FADEDOWNANDPAUSE, 10);
|
||||
} else {
|
||||
currentPlayPauseFadeVolume = 0f;
|
||||
service.fadingDown = false;
|
||||
service.pause();
|
||||
}
|
||||
service.player.setVolume(currentPlayPauseFadeVolume, currentPlayPauseFadeVolume);
|
||||
break;
|
||||
|
||||
case FADEUPANDRESUME:
|
||||
service.resume();
|
||||
currentPlayPauseFadeVolume += .1f;
|
||||
if (currentPlayPauseFadeVolume < 1.0f) {
|
||||
sendEmptyMessageDelayed(FADEUPANDRESUME, 10);
|
||||
} else {
|
||||
currentPlayPauseFadeVolume = 1.0f;
|
||||
}
|
||||
service.player.setVolume(currentPlayPauseFadeVolume, currentPlayPauseFadeVolume);
|
||||
break;
|
||||
|
||||
case FOCUSCHANGE:
|
||||
switch (msg.arg1) {
|
||||
case AudioManager.AUDIOFOCUS_GAIN:
|
||||
if (!service.isPlaying()) {
|
||||
if (service.wasPlayingBeforeFocusLoss) {
|
||||
service.resumePlaying();
|
||||
service.wasPlayingBeforeFocusLoss = false;
|
||||
}
|
||||
}
|
||||
removeMessages(DUCK);
|
||||
sendEmptyMessage(UNDUCK);
|
||||
break;
|
||||
|
||||
case AudioManager.AUDIOFOCUS_LOSS:
|
||||
// Lost focus for an unbounded amount of time: stop playback and release media player
|
||||
service.wasPlayingBeforeFocusLoss = false;
|
||||
service.pausePlaying();
|
||||
service.unregisterEverything();
|
||||
break;
|
||||
|
||||
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
|
||||
// Lost focus for a short time, but we have to stop
|
||||
// playback. We don't release the media player because playback
|
||||
// is likely to resume
|
||||
service.wasPlayingBeforeFocusLoss = service.isPlaying();
|
||||
service.pausePlaying();
|
||||
break;
|
||||
|
||||
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
|
||||
// Lost focus for a short time, but it's ok to keep playing
|
||||
// at an attenuated level
|
||||
if (!service.isPlayerPrepared()) {
|
||||
service.setUpMediaPlayerIfNeeded();
|
||||
}
|
||||
removeMessages(UNDUCK);
|
||||
sendEmptyMessage(DUCK);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ import com.kabouzeid.gramophone.interfaces.KabViewsDisableAble;
|
|||
import com.kabouzeid.gramophone.loader.AlbumSongLoader;
|
||||
import com.kabouzeid.gramophone.loader.ArtistSongLoader;
|
||||
import com.kabouzeid.gramophone.loader.PlaylistSongLoader;
|
||||
import com.kabouzeid.gramophone.model.MusicRemoteEvent;
|
||||
import com.kabouzeid.gramophone.model.Song;
|
||||
import com.kabouzeid.gramophone.model.UIPreferenceChangedEvent;
|
||||
import com.kabouzeid.gramophone.ui.activities.base.AbsFabActivity;
|
||||
|
|
@ -300,11 +299,9 @@ public class MainActivity extends AbsFabActivity
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onMusicRemoteEvent(MusicRemoteEvent event) {
|
||||
super.onMusicRemoteEvent(event);
|
||||
if (event.getAction() == MusicRemoteEvent.STATE_RESTORED || event.getAction() == MusicRemoteEvent.TRACK_CHANGED) {
|
||||
updateNavigationDrawerHeader();
|
||||
}
|
||||
public void onPlayingMetaChanged() {
|
||||
super.onPlayingMetaChanged();
|
||||
updateNavigationDrawerHeader();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ import com.kabouzeid.gramophone.helper.bitmapblur.StackBlurManager;
|
|||
import com.kabouzeid.gramophone.loader.SongFilePathLoader;
|
||||
import com.kabouzeid.gramophone.misc.AppKeys;
|
||||
import com.kabouzeid.gramophone.misc.SmallTransitionListener;
|
||||
import com.kabouzeid.gramophone.model.MusicRemoteEvent;
|
||||
import com.kabouzeid.gramophone.model.Song;
|
||||
import com.kabouzeid.gramophone.service.MusicService;
|
||||
import com.kabouzeid.gramophone.ui.activities.base.AbsFabActivity;
|
||||
|
|
@ -469,19 +468,21 @@ public class MusicControllerActivity extends AbsFabActivity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onMusicRemoteEvent(MusicRemoteEvent event) {
|
||||
super.onMusicRemoteEvent(event);
|
||||
switch (event.getAction()) {
|
||||
case MusicRemoteEvent.TRACK_CHANGED:
|
||||
updateCurrentSong();
|
||||
break;
|
||||
case MusicRemoteEvent.REPEAT_MODE_CHANGED:
|
||||
updateRepeatState();
|
||||
break;
|
||||
case MusicRemoteEvent.SHUFFLE_MODE_CHANGED:
|
||||
updateShuffleState();
|
||||
break;
|
||||
}
|
||||
public void onPlayingMetaChanged() {
|
||||
super.onPlayingMetaChanged();
|
||||
updateCurrentSong();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRepeatModeChanged() {
|
||||
super.onRepeatModeChanged();
|
||||
updateRepeatState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShuffleModeChanged() {
|
||||
super.onShuffleModeChanged();
|
||||
updateShuffleState();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import com.squareup.otto.Subscribe;
|
|||
/**
|
||||
* @author Karim Abou Zeid (kabouzeid)
|
||||
*/
|
||||
public abstract class AbsBaseActivity extends ThemeBaseActivity implements KabViewsDisableAble {
|
||||
public abstract class AbsBaseActivity extends AbsThemeActivity implements KabViewsDisableAble {
|
||||
|
||||
private App app;
|
||||
private boolean areViewsEnabled;
|
||||
|
|
|
|||
|
|
@ -12,39 +12,28 @@ import android.view.View;
|
|||
import android.widget.Toast;
|
||||
|
||||
import com.afollestad.materialdialogs.ThemeSingleton;
|
||||
import com.kabouzeid.gramophone.App;
|
||||
import com.kabouzeid.gramophone.R;
|
||||
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
||||
import com.kabouzeid.gramophone.misc.SmallOnGestureListener;
|
||||
import com.kabouzeid.gramophone.model.MusicRemoteEvent;
|
||||
import com.kabouzeid.gramophone.model.Song;
|
||||
import com.kabouzeid.gramophone.util.NavigationUtil;
|
||||
import com.kabouzeid.gramophone.util.Util;
|
||||
import com.kabouzeid.gramophone.views.PlayPauseDrawable;
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
import hugo.weaving.DebugLog;
|
||||
|
||||
/**
|
||||
* @author Karim Abou Zeid (kabouzeid)
|
||||
*/
|
||||
public abstract class AbsFabActivity extends AbsBaseActivity {
|
||||
public abstract class AbsFabActivity extends AbsPlaybackStatusActivity {
|
||||
public static final String TAG = AbsFabActivity.class.getSimpleName();
|
||||
|
||||
private FloatingActionButton fab;
|
||||
private PlayPauseDrawable playPauseDrawable;
|
||||
private final Object busEventListener = new Object() {
|
||||
@Subscribe
|
||||
public void onBusEvent(MusicRemoteEvent event) {
|
||||
onMusicRemoteEvent(event);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onPostCreate(Bundle savedInstanceState) {
|
||||
super.onPostCreate(savedInstanceState);
|
||||
try {
|
||||
App.bus.register(busEventListener);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
setUpFab();
|
||||
}
|
||||
|
||||
|
|
@ -116,6 +105,14 @@ public abstract class AbsFabActivity extends AbsBaseActivity {
|
|||
}
|
||||
}
|
||||
|
||||
protected void animateUpdateFabState() {
|
||||
if (MusicPlayerRemote.isPlaying()) {
|
||||
setFabPause();
|
||||
} else {
|
||||
setFabPlay();
|
||||
}
|
||||
}
|
||||
|
||||
protected FloatingActionButton getFab() {
|
||||
if (fab == null) {
|
||||
fab = (FloatingActionButton) findViewById(R.id.fab);
|
||||
|
|
@ -145,33 +142,11 @@ public abstract class AbsFabActivity extends AbsBaseActivity {
|
|||
return sharedViewsWithFab;
|
||||
}
|
||||
|
||||
@DebugLog
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
try {
|
||||
App.bus.unregister(busEventListener);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
protected void onMusicRemoteEvent(MusicRemoteEvent event) {
|
||||
switch (event.getAction()) {
|
||||
case MusicRemoteEvent.PLAY:
|
||||
setFabPause();
|
||||
break;
|
||||
case MusicRemoteEvent.PAUSE:
|
||||
setFabPlay();
|
||||
break;
|
||||
case MusicRemoteEvent.RESUME:
|
||||
setFabPause();
|
||||
break;
|
||||
case MusicRemoteEvent.STOP:
|
||||
setFabPlay();
|
||||
break;
|
||||
case MusicRemoteEvent.QUEUE_COMPLETED:
|
||||
setFabPlay();
|
||||
break;
|
||||
}
|
||||
public void onPlayStateChanged() {
|
||||
super.onPlayStateChanged();
|
||||
animateUpdateFabState();
|
||||
}
|
||||
|
||||
private void setFabPlay() {
|
||||
|
|
@ -181,8 +156,4 @@ public abstract class AbsFabActivity extends AbsBaseActivity {
|
|||
private void setFabPause() {
|
||||
playPauseDrawable.animatedPause();
|
||||
}
|
||||
|
||||
private void setFabColor() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
package com.kabouzeid.gramophone.ui.activities.base;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
|
||||
import com.kabouzeid.gramophone.service.MusicService;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* @author Karim Abou Zeid (kabouzeid)
|
||||
*/
|
||||
public abstract class AbsPlaybackStatusActivity extends AbsBaseActivity {
|
||||
private PlaybackStatus playbackStatus;
|
||||
|
||||
public void onPlayingMetaChanged() {
|
||||
|
||||
}
|
||||
|
||||
public void onPlayStateChanged() {
|
||||
|
||||
}
|
||||
|
||||
public void onRepeatModeChanged() {
|
||||
|
||||
}
|
||||
|
||||
public void onShuffleModeChanged() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
|
||||
playbackStatus = new PlaybackStatus(this);
|
||||
|
||||
final IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(MusicService.PLAYSTATE_CHANGED);
|
||||
filter.addAction(MusicService.SHUFFLEMODE_CHANGED);
|
||||
filter.addAction(MusicService.REPEATMODE_CHANGED);
|
||||
filter.addAction(MusicService.META_CHANGED);
|
||||
|
||||
registerReceiver(playbackStatus, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
try {
|
||||
unregisterReceiver(playbackStatus);
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
private static final class PlaybackStatus extends BroadcastReceiver {
|
||||
|
||||
private final WeakReference<AbsPlaybackStatusActivity> reference;
|
||||
|
||||
public PlaybackStatus(final AbsPlaybackStatusActivity activity) {
|
||||
reference = new WeakReference<>(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
switch (action) {
|
||||
case MusicService.META_CHANGED:
|
||||
reference.get().onPlayingMetaChanged();
|
||||
break;
|
||||
case MusicService.PLAYSTATE_CHANGED:
|
||||
reference.get().onPlayStateChanged();
|
||||
break;
|
||||
case MusicService.REPEATMODE_CHANGED:
|
||||
reference.get().onRepeatModeChanged();
|
||||
break;
|
||||
case MusicService.SHUFFLEMODE_CHANGED:
|
||||
reference.get().onShuffleModeChanged();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@ import com.kabouzeid.gramophone.util.Util;
|
|||
* @author Aidan Follestad (afollestad), Karim Abou Zeid (kabouzeid)
|
||||
*/
|
||||
|
||||
public abstract class ThemeBaseActivity extends AppCompatActivity implements KabViewsDisableAble {
|
||||
public abstract class AbsThemeActivity extends AppCompatActivity implements KabViewsDisableAble {
|
||||
private int colorPrimary;
|
||||
private int colorPrimaryDarker;
|
||||
private int colorAccent;
|
||||
|
|
@ -40,6 +40,7 @@ public final class PreferenceUtils {
|
|||
public static final String LARGER_TITLE_BOX_NOW_PLAYING = "larger_title_box_now_playing";
|
||||
public static final String ALTERNATIVE_PROGRESS_SLIDER_NOW_PLAYING = "alternative_progress_slider_now_playing";
|
||||
public static final String PLAYBACK_CONTROLLER_CARD_NOW_PLAYING = "playback_controller_card_now_playing";
|
||||
public static final String FADE_PLAY_PAUSE = "fade_play_pause";
|
||||
|
||||
private static PreferenceUtils sInstance;
|
||||
|
||||
|
|
@ -187,6 +188,10 @@ public final class PreferenceUtils {
|
|||
return mPreferences.getBoolean(ALTERNATIVE_PROGRESS_SLIDER_NOW_PLAYING, false);
|
||||
}
|
||||
|
||||
public final boolean fadePlayPauseAndInterruptions() {
|
||||
return mPreferences.getBoolean(FADE_PLAY_PAUSE, true);
|
||||
}
|
||||
|
||||
// public final boolean downloadMissingArtistImages() {
|
||||
// return mPreferences.getBoolean(DOWNLOAD_MISSING_ARTIST_IMAGES, true);
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@
|
|||
<string name="pref_title_colored_navigation_bar_tag_editor">Tag editor</string>
|
||||
<string name="pref_title_colored_navigation_bar_other_screens">Everywhere else</string>
|
||||
<string name="pref_title_colored_album_footers">Colored album footers</string>
|
||||
<string name="pref_title_fade_play_pause">Fade play/pause</string>
|
||||
<string name="pref_title_force_square_album_art">Force square album art</string>
|
||||
<string name="pref_title_opaque_toolbar_now_playing">Opaque toolbar</string>
|
||||
<string name="pref_title_opaque_statusbar_now_playing">Opaque statusbar</string>
|
||||
|
|
@ -139,6 +140,7 @@
|
|||
<string name="song">Song</string>
|
||||
<string name="pref_only_lollipop">"Only available on Lollipop."</string>
|
||||
<string name="pref_summary_colored_album_footers">"Album footers in the grid are colored with the album cover\'s palette."</string>
|
||||
<string name="pref_summary_fade_play_pause">"Fades the song in/out on play/pause."</string>
|
||||
<string name="pref_summary_force_square_album_art">Album art in the now playing view is forced to be squared.</string>
|
||||
<string name="pref_summary_opaque_toolbar_now_playing">The toolbar is opaque and do not cover the album art.</string>
|
||||
<string name="pref_summary_opaque_statusbar_now_playing">The statusbar is opaque and do not cover the album art.</string>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,14 @@
|
|||
|
||||
<com.kabouzeid.gramophone.prefs.DynamicPreferenceCategory android:title="@string/pref_header_audio">
|
||||
|
||||
<CheckBoxPreference
|
||||
android:layout="@layout/preference_custom"
|
||||
android:defaultValue="true"
|
||||
android:key="fade_play_pause"
|
||||
android:title="@string/pref_title_fade_play_pause"
|
||||
android:summary="@string/pref_summary_fade_play_pause"
|
||||
android:widgetLayout="@layout/preference_dynamic_checkbox" />
|
||||
|
||||
<Preference
|
||||
android:key="equalizer"
|
||||
android:title="@string/equalizer" />
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue