add getVolume to playback interface and improve progress handler
This commit is contained in:
parent
b1ffa78a2e
commit
2c8229b0dc
4 changed files with 61 additions and 58 deletions
|
|
@ -2,10 +2,10 @@ package com.dkanada.gramophone.service;
|
|||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.Environment;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.dkanada.gramophone.App;
|
||||
import com.dkanada.gramophone.R;
|
||||
import com.dkanada.gramophone.model.Song;
|
||||
import com.dkanada.gramophone.service.playback.Playback;
|
||||
|
|
@ -118,7 +118,8 @@ public class MultiPlayer implements Playback {
|
|||
LeastRecentlyUsedCacheEvictor recentlyUsedCache = new LeastRecentlyUsedCacheEvictor(Long.MAX_VALUE);
|
||||
ExoDatabaseProvider databaseProvider = new ExoDatabaseProvider(context);
|
||||
|
||||
simpleCache = new SimpleCache(new File(Environment.getExternalStorageDirectory() + "/Gelli/cache"), recentlyUsedCache, databaseProvider);
|
||||
File file = new File(App.getInstance().getApplicationInfo().dataDir + "/Gelli/exoplayer");
|
||||
simpleCache = new SimpleCache(file, recentlyUsedCache, databaseProvider);
|
||||
dataSource = buildDataSourceFactory();
|
||||
}
|
||||
|
||||
|
|
@ -184,12 +185,7 @@ public class MultiPlayer implements Playback {
|
|||
.createMediaSource(uri);
|
||||
}
|
||||
|
||||
if (mediaSource.getSize() < position) {
|
||||
mediaSource.addMediaSource(mediaSource.getSize(), source);
|
||||
} else {
|
||||
mediaSource.addMediaSource(position, source);
|
||||
}
|
||||
|
||||
mediaSource.addMediaSource(Math.min(mediaSource.getSize(), position), source);
|
||||
if (position == 0) start();
|
||||
}
|
||||
});
|
||||
|
|
@ -247,7 +243,7 @@ public class MultiPlayer implements Playback {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getPosition() {
|
||||
public int getProgress() {
|
||||
if (!isReady) return -1;
|
||||
return (int) exoPlayer.getCurrentPosition();
|
||||
}
|
||||
|
|
@ -259,7 +255,7 @@ public class MultiPlayer implements Playback {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setPosition(int position) {
|
||||
public void setProgress(int position) {
|
||||
exoPlayer.seekTo(position);
|
||||
}
|
||||
|
||||
|
|
@ -267,4 +263,9 @@ public class MultiPlayer implements Playback {
|
|||
public void setVolume(int volume) {
|
||||
exoPlayer.setVolume(volume / 100f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVolume() {
|
||||
return (int) (exoPlayer.getVolume() * 100);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,8 +63,10 @@ import java.util.ArrayList;
|
|||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class MusicService extends Service implements SharedPreferences.OnSharedPreferenceChangeListener, Playback.PlaybackCallbacks {
|
||||
public static final String PHONOGRAPH_PACKAGE_NAME = "com.dkanada.gramophone";
|
||||
|
|
@ -78,7 +80,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
public static final String ACTION_REWIND = PHONOGRAPH_PACKAGE_NAME + ".rewind";
|
||||
public static final String ACTION_QUIT = PHONOGRAPH_PACKAGE_NAME + ".quitservice";
|
||||
public static final String ACTION_PENDING_QUIT = PHONOGRAPH_PACKAGE_NAME + ".pendingquitservice";
|
||||
public static final String INTENT_EXTRA_PLAYLIST = PHONOGRAPH_PACKAGE_NAME + "intentextra.playlist";
|
||||
public static final String INTENT_EXTRA_PLAYLIST = PHONOGRAPH_PACKAGE_NAME + ".intentextra.playlist";
|
||||
public static final String INTENT_EXTRA_SHUFFLE_MODE = PHONOGRAPH_PACKAGE_NAME + ".intentextra.shufflemode";
|
||||
|
||||
public static final String APP_WIDGET_UPDATE = PHONOGRAPH_PACKAGE_NAME + ".appwidgetupdate";
|
||||
|
|
@ -101,7 +103,6 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
public static final int FOCUS_CHANGE = 6;
|
||||
public static final int DUCK = 7;
|
||||
public static final int UNDUCK = 8;
|
||||
public static final int RESTORE_QUEUES = 9;
|
||||
|
||||
public static final int SHUFFLE_MODE_NONE = 0;
|
||||
public static final int SHUFFLE_MODE_SHUFFLE = 1;
|
||||
|
|
@ -111,6 +112,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
public static final int REPEAT_MODE_THIS = 2;
|
||||
|
||||
public static final int SAVE_QUEUE = 0;
|
||||
public static final int LOAD_QUEUE = 9;
|
||||
|
||||
private final IBinder musicBinder = new MusicBinder();
|
||||
|
||||
|
|
@ -121,10 +123,13 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
private AppWidgetClassic appWidgetClassic = AppWidgetClassic.getInstance();
|
||||
|
||||
private Playback playback;
|
||||
|
||||
private List<Song> playingQueue = new ArrayList<>();
|
||||
private List<Song> originalPlayingQueue = new ArrayList<>();
|
||||
|
||||
private int position = -1;
|
||||
private int nextPosition = -1;
|
||||
|
||||
private int shuffleMode;
|
||||
private int repeatMode;
|
||||
private boolean queuesRestored;
|
||||
|
|
@ -146,6 +151,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
private ThrottledSeekHandler throttledSeekHandler;
|
||||
private QueueSaveHandler queueSaveHandler;
|
||||
private ProgressHandler progressHandler;
|
||||
|
||||
private HandlerThread playerHandlerThread;
|
||||
private HandlerThread queueSaveHandlerThread;
|
||||
|
||||
|
|
@ -176,16 +182,13 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getClass().getName());
|
||||
wakeLock.setReferenceCounted(false);
|
||||
|
||||
playback = new MultiPlayer(this);
|
||||
playback.setCallbacks(this);
|
||||
|
||||
playerHandlerThread = new HandlerThread(PlaybackHandler.class.getName());
|
||||
playerHandlerThread.start();
|
||||
playerHandler = new PlaybackHandler(this, playerHandlerThread.getLooper());
|
||||
|
||||
playback = new MultiPlayer(this);
|
||||
playback.setCallbacks(this);
|
||||
|
||||
initMediaSession();
|
||||
|
||||
// queue saving needs to run on a separate thread so that it doesn't block the playback handler events
|
||||
queueSaveHandlerThread = new HandlerThread(QueueSaveHandler.class.getName(), Process.THREAD_PRIORITY_BACKGROUND);
|
||||
queueSaveHandlerThread.start();
|
||||
queueSaveHandler = new QueueSaveHandler(this, queueSaveHandlerThread.getLooper());
|
||||
|
|
@ -200,6 +203,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
PreferenceUtil.getInstance(this).registerOnSharedPreferenceChangedListener(this);
|
||||
|
||||
initNotification();
|
||||
initMediaSession();
|
||||
restoreState();
|
||||
|
||||
mediaSession.setActive(true);
|
||||
|
|
@ -388,8 +392,8 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
notifyChange(SHUFFLE_MODE_CHANGED);
|
||||
notifyChange(REPEAT_MODE_CHANGED);
|
||||
|
||||
playerHandler.removeMessages(RESTORE_QUEUES);
|
||||
playerHandler.sendEmptyMessage(RESTORE_QUEUES);
|
||||
playerHandler.removeMessages(LOAD_QUEUE);
|
||||
playerHandler.sendEmptyMessage(LOAD_QUEUE);
|
||||
}
|
||||
|
||||
private synchronized void restoreQueuesAndPositionIfNecessary() {
|
||||
|
|
@ -843,7 +847,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
}
|
||||
|
||||
public int getSongProgressMillis() {
|
||||
return playback.getPosition();
|
||||
return playback.getProgress();
|
||||
}
|
||||
|
||||
public int getSongDurationMillis() {
|
||||
|
|
@ -861,7 +865,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
|
||||
public int seek(int millis) {
|
||||
synchronized (this) {
|
||||
playback.setPosition(millis);
|
||||
playback.setProgress(millis);
|
||||
throttledSeekHandler.notifySeek();
|
||||
return millis;
|
||||
}
|
||||
|
|
@ -1112,7 +1116,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
service.prepareNextImpl();
|
||||
break;
|
||||
|
||||
case RESTORE_QUEUES:
|
||||
case LOAD_QUEUE:
|
||||
service.restoreQueuesAndPositionIfNecessary();
|
||||
break;
|
||||
|
||||
|
|
@ -1196,33 +1200,29 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
|
||||
@Override
|
||||
public void run() {
|
||||
saveProgress();
|
||||
notifyChange(PLAY_STATE_CHANGED);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ProgressHandler extends Handler {
|
||||
private WeakReference<MusicService> mService;
|
||||
private Timer mTimer;
|
||||
|
||||
private ScheduledExecutorService executorService;
|
||||
private Future<?> task;
|
||||
|
||||
public ProgressHandler(MusicService service, Looper looper) {
|
||||
super(looper);
|
||||
|
||||
mService = new WeakReference<>(service);
|
||||
mTimer = new Timer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(@NonNull final Message msg) {
|
||||
final MusicService service = mService.get();
|
||||
if (service == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (msg.what) {
|
||||
case PLAY_SONG:
|
||||
case TRACK_WENT_TO_NEXT:
|
||||
onStart();
|
||||
case TRACK_WENT_TO_NEXT:
|
||||
onNext();
|
||||
break;
|
||||
case TRACK_ENDED:
|
||||
onStop();
|
||||
|
|
@ -1230,20 +1230,21 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
}
|
||||
|
||||
public void onStart() {
|
||||
if (executorService != null) executorService.shutdownNow();
|
||||
|
||||
executorService = Executors.newScheduledThreadPool(1);
|
||||
task = executorService.scheduleAtFixedRate(this::onProgress, 10, 10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public void onNext() {
|
||||
PlaybackStartInfo startInfo = new PlaybackStartInfo();
|
||||
TimerTask mTask = new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
onProgress();
|
||||
}
|
||||
};
|
||||
|
||||
startInfo.setItemId(mService.get().getCurrentSong().id);
|
||||
startInfo.setVolumeLevel(mService.get().playback.getVolume());
|
||||
startInfo.setCanSeek(true);
|
||||
startInfo.setIsPaused(false);
|
||||
|
||||
App.getApiClient().ReportPlaybackStartAsync(startInfo, new EmptyResponse());
|
||||
mTimer.schedule(mTask, 10000, 10000);
|
||||
}
|
||||
|
||||
public void onProgress() {
|
||||
|
|
@ -1252,26 +1253,26 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
// TODO these cause a wrong thread error
|
||||
long progress = mService.get().getSongProgressMillis();
|
||||
double duration = mService.get().getSongDurationMillis();
|
||||
if (progress / duration > 0.9) onStop();
|
||||
if (progress / duration > 0.9) {
|
||||
Song current = mService.get().getCurrentSong();
|
||||
String user = App.getApiClient().getCurrentUserId();
|
||||
Date time = new Date(System.currentTimeMillis());
|
||||
|
||||
App.getApiClient().MarkPlayedAsync(current.id, user, time, new Response<>());
|
||||
}
|
||||
|
||||
progressInfo.setItemId(mService.get().getCurrentSong().id);
|
||||
progressInfo.setPositionTicks(progress * 10000);
|
||||
progressInfo.setCanSeek(true);
|
||||
progressInfo.setVolumeLevel(mService.get().playback.getVolume());
|
||||
progressInfo.setIsPaused(!mService.get().playback.isPlaying());
|
||||
progressInfo.setCanSeek(true);
|
||||
|
||||
App.getApiClient().ensureWebSocket();
|
||||
App.getApiClient().ReportPlaybackProgressAsync(progressInfo, new EmptyResponse());
|
||||
}
|
||||
|
||||
public void onStop() {
|
||||
mTimer.purge();
|
||||
|
||||
Song current = mService.get().getCurrentSong();
|
||||
String user = App.getApiClient().getCurrentUserId();
|
||||
Date time = new Date(System.currentTimeMillis());
|
||||
|
||||
if (current == Song.EMPTY_SONG) return;
|
||||
App.getApiClient().MarkPlayedAsync(current.id, user, time, new Response<>());
|
||||
task.cancel(true);
|
||||
executorService.shutdownNow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,14 +19,16 @@ public interface Playback {
|
|||
|
||||
boolean isPlaying();
|
||||
|
||||
int getPosition();
|
||||
int getProgress();
|
||||
|
||||
int getDuration();
|
||||
|
||||
void setPosition(int position);
|
||||
void setProgress(int position);
|
||||
|
||||
void setVolume(int volume);
|
||||
|
||||
int getVolume();
|
||||
|
||||
interface PlaybackCallbacks {
|
||||
void onTrackStarted();
|
||||
|
||||
|
|
|
|||
|
|
@ -55,16 +55,16 @@ public class SplashActivity extends AbsBaseActivity {
|
|||
builder.setMessage(R.string.battery_optimizations_message)
|
||||
.setTitle(R.string.battery_optimizations_title)
|
||||
.setNegativeButton(R.string.ignore, (dialog, id) -> login())
|
||||
.setPositiveButton(R.string.disable, (dialog, id) -> openPowerSettings(SplashActivity.this))
|
||||
.setPositiveButton(R.string.disable, (dialog, id) -> openPowerSettings())
|
||||
.show();
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.M)
|
||||
private void openPowerSettings(Context context) {
|
||||
private void openPowerSettings() {
|
||||
Intent intent = new Intent();
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.setAction(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
|
||||
context.startActivity(intent);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
public void login() {
|
||||
|
|
@ -102,6 +102,5 @@ public class SplashActivity extends AbsBaseActivity {
|
|||
Intent intent = new Intent(this, LoginActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue