-Generify all player intents to use play queues.

-Fixed sync updates out-of-sync on background notification.
-Fixed main video player destroyed on resume.
-Fixed track selection using wrong dimension for parameter.
-Fixed background player to use default audio quality.
-Removed quality index from single queue items.
This commit is contained in:
John Zhen M 2017-09-24 20:14:58 -07:00 committed by John Zhen Mo
parent cb7e94449c
commit 09d8ae1316
11 changed files with 151 additions and 139 deletions

View file

@ -335,9 +335,18 @@ public final class BackgroundPlayer extends Service {
@Override
public void onUpdateProgress(int currentProgress, int duration, int bufferPercent) {
if (bigNotRemoteView != null) bigNotRemoteView.setProgressBar(R.id.notificationProgressBar, duration, currentProgress, false);
if (notRemoteView != null) notRemoteView.setProgressBar(R.id.notificationProgressBar, duration, currentProgress, false);
if (bigNotRemoteView != null) bigNotRemoteView.setTextViewText(R.id.notificationTime, getTimeString(currentProgress) + " / " + getTimeString(duration));
if (bigNotRemoteView != null) {
bigNotRemoteView.setTextViewText(R.id.notificationSongName, getVideoTitle());
bigNotRemoteView.setTextViewText(R.id.notificationArtist, getUploaderName());
bigNotRemoteView.setProgressBar(R.id.notificationProgressBar, duration, currentProgress, false);
bigNotRemoteView.setTextViewText(R.id.notificationTime, getTimeString(currentProgress) + " / " + getTimeString(duration));
}
if (notRemoteView != null) {
notRemoteView.setTextViewText(R.id.notificationSongName, getVideoTitle());
notRemoteView.setTextViewText(R.id.notificationArtist, getUploaderName());
notRemoteView.setProgressBar(R.id.notificationProgressBar, duration, currentProgress, false);
}
updateNotification(-1);
}
@ -396,7 +405,8 @@ public final class BackgroundPlayer extends Service {
@Override
public MediaSource sourceOf(final StreamInfo info) {
final AudioStream audio = ListHelper.getHighestQualityAudio(info.audio_streams);
final int index = ListHelper.getDefaultAudioFormat(context, info.audio_streams);
final AudioStream audio = info.audio_streams.get(index);
return buildMediaSource(audio.url, MediaFormat.getSuffixById(audio.format));
}

View file

@ -137,6 +137,7 @@ public abstract class BasePlayer implements Player.EventListener,
public static final String CHANNEL_NAME = "channel_name";
public static final String PLAYBACK_SPEED = "playback_speed";
public static final String PLAY_QUEUE = "play_queue";
public static final String RESTORE_QUEUE_INDEX = "restore_queue_index";
public static final String RESTORE_WINDOW_POS = "restore_window_pos";
@ -252,59 +253,32 @@ public abstract class BasePlayer implements Player.EventListener,
if (DEBUG) Log.d(TAG, "handleIntent() called with: intent = [" + intent + "]");
if (intent == null) return;
setRecovery(
intent.getIntExtra(RESTORE_QUEUE_INDEX, 0),
intent.getLongExtra(START_POSITION, 0)
);
// Resolve play queue
if (!intent.hasExtra(PLAY_QUEUE)) return;
final Serializable playQueueCandidate = intent.getSerializableExtra(PLAY_QUEUE);
if (!(playQueueCandidate instanceof PlayQueue)) return;
final PlayQueue queue = (PlayQueue) playQueueCandidate;
// Resolve playback details
if (intent.hasExtra(RESTORE_QUEUE_INDEX) && intent.hasExtra(START_POSITION)) {
setRecovery(
intent.getIntExtra(RESTORE_QUEUE_INDEX, 0),
intent.getLongExtra(START_POSITION, 0)
);
}
setPlaybackSpeed(intent.getFloatExtra(PLAYBACK_SPEED, getPlaybackSpeed()));
switch (intent.getStringExtra(INTENT_TYPE)) {
case SINGLE_STREAM:
handleSinglePlaylistIntent(intent);
break;
case EXTERNAL_PLAYLIST:
handleExternalPlaylistIntent(intent);
break;
default:
break;
}
}
// Re-initialization
destroyPlayer();
if (playQueue != null) playQueue.dispose();
if (playbackManager != null) playbackManager.dispose();
initPlayer();
@SuppressWarnings("unchecked")
public void handleExternalPlaylistIntent(Intent intent) {
final int serviceId = intent.getIntExtra(ExternalPlayQueue.SERVICE_ID, -1);
final int index = intent.getIntExtra(ExternalPlayQueue.INDEX, 0);
final Serializable serializable = intent.getSerializableExtra(ExternalPlayQueue.STREAMS);
final String url = intent.getStringExtra(ExternalPlayQueue.URL);
final String nextPageUrl = intent.getStringExtra(ExternalPlayQueue.NEXT_PAGE_URL);
List<InfoItem> info = new ArrayList<>();
if (serializable instanceof List) {
for (final Object o : (List) serializable) {
if (o instanceof InfoItem) info.add((StreamInfoItem) o);
}
}
final PlayQueue queue = new ExternalPlayQueue(serviceId, url, nextPageUrl, info, index);
initPlayback(this, queue);
}
@SuppressWarnings("unchecked")
public void handleSinglePlaylistIntent(Intent intent) {
final Serializable serializable = intent.getSerializableExtra(SinglePlayQueue.STREAM);
if (!(serializable instanceof StreamInfo)) return;
final PlayQueue queue = new SinglePlayQueue((StreamInfo) serializable, PlayQueueItem.DEFAULT_QUALITY);
// Good to go...
initPlayback(this, queue);
}
protected void initPlayback(@NonNull final PlaybackListener listener, @NonNull final PlayQueue queue) {
destroyPlayer();
initPlayer();
if (playQueue != null) playQueue.dispose();
if (playbackManager != null) playbackManager.dispose();
playQueue = queue;
playQueue.init();
playbackManager = new MediaSourceManager(this, playQueue);
@ -976,6 +950,10 @@ public abstract class BasePlayer implements Player.EventListener,
return playQueue != null ? playQueue.getIndex() : -1;
}
public int getCurrentResolutionTarget() {
return trackSelector != null ? trackSelector.getParameters().maxVideoHeight : Integer.MAX_VALUE;
}
public long getPlayerCurrentPosition() {
return simpleExoPlayer != null ? simpleExoPlayer.getCurrentPosition() : 0L;
}

View file

@ -39,6 +39,7 @@ import android.widget.TextView;
import android.widget.Toast;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.stream.StreamInfo;
@ -63,6 +64,8 @@ public final class MainVideoPlayer extends Activity {
private boolean activityPaused;
private VideoPlayerImpl playerImpl;
private DefaultTrackSelector.Parameters parameters;
/*//////////////////////////////////////////////////////////////////////////
// Activity LifeCycle
//////////////////////////////////////////////////////////////////////////*/
@ -107,6 +110,11 @@ public final class MainVideoPlayer extends Activity {
super.onStop();
if (DEBUG) Log.d(TAG, "onStop() called");
activityPaused = true;
if (playerImpl.trackSelector != null) {
parameters = playerImpl.trackSelector.getParameters();
}
if (playerImpl.getPlayer() != null) {
playerImpl.wasPlaying = playerImpl.getPlayer().getPlayWhenReady();
playerImpl.setRecovery(
@ -128,6 +136,10 @@ public final class MainVideoPlayer extends Activity {
playerImpl.getPlayer().setPlayWhenReady(playerImpl.wasPlaying);
playerImpl.initPlayback(playerImpl, playerImpl.playQueue);
if (playerImpl.trackSelector != null && parameters != null) {
playerImpl.trackSelector.setParameters(parameters);
}
activityPaused = false;
}
}
@ -259,7 +271,15 @@ public final class MainVideoPlayer extends Activity {
return;
}
final Intent intent = NavigationHelper.getOpenVideoPlayerIntent(context, PopupVideoPlayer.class, this);
final Intent intent = NavigationHelper.getPlayerIntent(
context,
PopupVideoPlayer.class,
this.getPlayQueue(),
this.getCurrentResolutionTarget(),
this.getCurrentQueueIndex(),
this.getPlayerCurrentPosition(),
this.getPlaybackSpeed()
);
context.startService(intent);
destroyPlayer();

View file

@ -412,7 +412,15 @@ public final class PopupVideoPlayer extends Service {
if (DEBUG) Log.d(TAG, "onFullScreenButtonClicked() called");
Intent intent;
if (!getSharedPreferences().getBoolean(getResources().getString(R.string.use_old_player_key), false)) {
intent = NavigationHelper.getOpenVideoPlayerIntent(context, MainVideoPlayer.class, this);
intent = NavigationHelper.getPlayerIntent(
context,
MainVideoPlayer.class,
this.getPlayQueue(),
this.getCurrentResolutionTarget(),
this.getCurrentQueueIndex(),
this.getPlayerCurrentPosition(),
this.getPlaybackSpeed()
);
if (!isStartedFromNewPipe()) intent.putExtra(VideoPlayer.STARTED_FROM_NEWPIPE, false);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
} else {
@ -741,7 +749,7 @@ public final class PopupVideoPlayer extends Service {
mainHandler.post(new Runnable() {
@Override
public void run() {
playerImpl.playQueue = new SinglePlayQueue(info, PlayQueueItem.DEFAULT_QUALITY);
playerImpl.playQueue = new SinglePlayQueue(info);
playerImpl.playQueue.init();
playerImpl.playbackManager = new MediaSourceManager(playerImpl, playerImpl.playQueue);
}

View file

@ -93,8 +93,8 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer.
public static final String INDEX_SEL_VIDEO_STREAM = "index_selected_video_stream";
public static final String STARTED_FROM_NEWPIPE = "started_from_newpipe";
public static final String PLAY_QUEUE = "play_queue";
public static final String PLAYER_INTENT = "player_intent";
public static final String MAX_RESOLUTION = "max_resolution";
private VideoStream selectedIndexStream;
@ -212,36 +212,22 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer.
trackSelector.setTunnelingAudioSessionId(C.generateAudioSessionIdV21(context));
}
@Override
@SuppressWarnings("unchecked")
public void handleIntent(Intent intent) {
super.handleIntent(intent);
if (intent == null) return;
if (intent.getStringExtra(INTENT_TYPE).equals(PLAYER_INTENT)) {
handlePlayerIntent(intent);
}
final int resolutionTarget = intent.getIntExtra(MAX_RESOLUTION, Integer.MAX_VALUE);
trackSelector.setParameters(
// Assume video is horizontal
new DefaultTrackSelector.Parameters().withMaxVideoSize(Integer.MAX_VALUE, resolutionTarget)
);
}
@SuppressWarnings("unchecked")
public void handleSinglePlaylistIntent(Intent intent) {
final Serializable serializable = intent.getSerializableExtra(SinglePlayQueue.STREAM);
if (!(serializable instanceof StreamInfo)) return;
final int sortedStreamsIndex = intent.getIntExtra(INDEX_SEL_VIDEO_STREAM, -1);
final PlayQueue queue = new SinglePlayQueue((StreamInfo) serializable, sortedStreamsIndex);
initPlayback(this, queue);
}
@SuppressWarnings("unchecked")
public void handlePlayerIntent(Intent intent) {
final Serializable serializable = intent.getSerializableExtra(PLAY_QUEUE);
if (!(serializable instanceof PlayQueue)) return;
final PlayQueue queue = (PlayQueue) serializable;
initPlayback(this, queue);
}
/*//////////////////////////////////////////////////////////////////////////
// Playback Listener
//////////////////////////////////////////////////////////////////////////*/
@Override
public void sync(@Nullable final StreamInfo info) {
@ -518,8 +504,14 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer.
final int itemId = menuItem.getItemId();
final TrackGroupInfo info = trackGroupInfos.get(itemId);
final DefaultTrackSelector.Parameters parameters = new DefaultTrackSelector.Parameters()
.withMaxVideoSize(info.format.width, Integer.MAX_VALUE);
DefaultTrackSelector.Parameters parameters;
if (info.format.width > info.format.height) {
// Check if video horizontal
parameters = new DefaultTrackSelector.Parameters().withMaxVideoSize(Integer.MAX_VALUE, info.format.height);
} else {
// Or if vertical
parameters = new DefaultTrackSelector.Parameters().withMaxVideoSize(info.format.width, Integer.MAX_VALUE);
}
trackSelector.setParameters(parameters);
return true;

View file

@ -21,7 +21,7 @@ import java.util.List;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;
import io.reactivex.disposables.SerialDisposable;
import io.reactivex.functions.Consumer;
public class MediaSourceManager implements DeferredMediaSource.Callback {
@ -41,7 +41,7 @@ public class MediaSourceManager implements DeferredMediaSource.Callback {
private List<Integer> sourceToQueueIndex;
private Subscription playQueueReactor;
private Disposable syncReactor;
private SerialDisposable syncReactor;
private boolean isBlocked;
@ -50,6 +50,8 @@ public class MediaSourceManager implements DeferredMediaSource.Callback {
this.playbackListener = listener;
this.playQueue = playQueue;
this.syncReactor = new SerialDisposable();
this.sources = new DynamicConcatenatingMediaSource();
this.sourceToQueueIndex = Collections.synchronizedList(new ArrayList<Integer>());
@ -216,7 +218,7 @@ public class MediaSourceManager implements DeferredMediaSource.Callback {
}
};
currentItem.getStream().subscribe(syncPlayback, onError);
syncReactor.set(currentItem.getStream().subscribe(syncPlayback, onError));
}
private void load(@Nullable final PlayQueueItem item) {