-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:
parent
cb7e94449c
commit
09d8ae1316
|
@ -60,9 +60,12 @@ import org.schabi.newpipe.fragments.BackPressable;
|
||||||
import org.schabi.newpipe.fragments.BaseStateFragment;
|
import org.schabi.newpipe.fragments.BaseStateFragment;
|
||||||
import org.schabi.newpipe.history.HistoryListener;
|
import org.schabi.newpipe.history.HistoryListener;
|
||||||
import org.schabi.newpipe.info_list.InfoItemBuilder;
|
import org.schabi.newpipe.info_list.InfoItemBuilder;
|
||||||
|
import org.schabi.newpipe.player.BackgroundPlayer;
|
||||||
import org.schabi.newpipe.player.MainVideoPlayer;
|
import org.schabi.newpipe.player.MainVideoPlayer;
|
||||||
import org.schabi.newpipe.player.PopupVideoPlayer;
|
import org.schabi.newpipe.player.PopupVideoPlayer;
|
||||||
import org.schabi.newpipe.player.old.PlayVideoActivity;
|
import org.schabi.newpipe.player.old.PlayVideoActivity;
|
||||||
|
import org.schabi.newpipe.playlist.PlayQueue;
|
||||||
|
import org.schabi.newpipe.playlist.SinglePlayQueue;
|
||||||
import org.schabi.newpipe.report.ErrorActivity;
|
import org.schabi.newpipe.report.ErrorActivity;
|
||||||
import org.schabi.newpipe.report.UserAction;
|
import org.schabi.newpipe.report.UserAction;
|
||||||
import org.schabi.newpipe.util.Constants;
|
import org.schabi.newpipe.util.Constants;
|
||||||
|
@ -730,6 +733,15 @@ public class VideoDetailFragment extends BaseStateFragment<StreamInfo> implement
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int resolutionOf(final String resolution) {
|
||||||
|
final String[] candidates = TextUtils.split(resolution, "p");
|
||||||
|
if (candidates.length > 0 && TextUtils.isDigitsOnly(candidates[0])) {
|
||||||
|
return Integer.parseInt(candidates[0]);
|
||||||
|
} else {
|
||||||
|
return Integer.MAX_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void openPopupPlayer() {
|
private void openPopupPlayer() {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !PermissionHelper.checkSystemAlertWindowPermission(activity)) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !PermissionHelper.checkSystemAlertWindowPermission(activity)) {
|
||||||
Toast toast = Toast.makeText(activity, R.string.msg_popup_permission, Toast.LENGTH_LONG);
|
Toast toast = Toast.makeText(activity, R.string.msg_popup_permission, Toast.LENGTH_LONG);
|
||||||
|
@ -744,8 +756,11 @@ public class VideoDetailFragment extends BaseStateFragment<StreamInfo> implement
|
||||||
}
|
}
|
||||||
|
|
||||||
Toast.makeText(activity, R.string.popup_playing_toast, Toast.LENGTH_SHORT).show();
|
Toast.makeText(activity, R.string.popup_playing_toast, Toast.LENGTH_SHORT).show();
|
||||||
Intent mIntent = NavigationHelper.getOpenVideoPlayerIntent(activity, PopupVideoPlayer.class, currentInfo, actionBarHandler.getSelectedVideoStream());
|
|
||||||
activity.startService(mIntent);
|
final PlayQueue playQueue = new SinglePlayQueue(currentInfo);
|
||||||
|
final VideoStream candidate = sortedStreamVideosList.get(actionBarHandler.getSelectedVideoStream());
|
||||||
|
final Intent intent = NavigationHelper.getPlayerIntent(activity, PopupVideoPlayer.class, playQueue, resolutionOf(candidate.resolution));
|
||||||
|
activity.startService(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void openVideoPlayer() {
|
private void openVideoPlayer() {
|
||||||
|
@ -764,7 +779,8 @@ public class VideoDetailFragment extends BaseStateFragment<StreamInfo> implement
|
||||||
|
|
||||||
|
|
||||||
private void openNormalBackgroundPlayer() {
|
private void openNormalBackgroundPlayer() {
|
||||||
activity.startService(NavigationHelper.getOpenBackgroundPlayerIntent(activity, currentInfo));
|
final PlayQueue playQueue = new SinglePlayQueue(currentInfo);
|
||||||
|
activity.startService(NavigationHelper.getPlayerIntent(activity, BackgroundPlayer.class, playQueue));
|
||||||
Toast.makeText(activity, R.string.background_player_playing_toast, Toast.LENGTH_SHORT).show();
|
Toast.makeText(activity, R.string.background_player_playing_toast, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -808,7 +824,9 @@ public class VideoDetailFragment extends BaseStateFragment<StreamInfo> implement
|
||||||
|| (Build.VERSION.SDK_INT < 16);
|
|| (Build.VERSION.SDK_INT < 16);
|
||||||
if (!useOldPlayer) {
|
if (!useOldPlayer) {
|
||||||
// ExoPlayer
|
// ExoPlayer
|
||||||
mIntent = NavigationHelper.getOpenVideoPlayerIntent(activity, MainVideoPlayer.class, currentInfo, actionBarHandler.getSelectedVideoStream());
|
final PlayQueue playQueue = new SinglePlayQueue(currentInfo);
|
||||||
|
final VideoStream candidate = sortedStreamVideosList.get(actionBarHandler.getSelectedVideoStream());
|
||||||
|
mIntent = NavigationHelper.getPlayerIntent(activity, MainVideoPlayer.class, playQueue, resolutionOf(candidate.resolution));
|
||||||
} else {
|
} else {
|
||||||
// Internal Player
|
// Internal Player
|
||||||
mIntent = new Intent(activity, PlayVideoActivity.class)
|
mIntent = new Intent(activity, PlayVideoActivity.class)
|
||||||
|
|
|
@ -24,6 +24,8 @@ import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
|
||||||
import org.schabi.newpipe.player.BackgroundPlayer;
|
import org.schabi.newpipe.player.BackgroundPlayer;
|
||||||
import org.schabi.newpipe.player.MainVideoPlayer;
|
import org.schabi.newpipe.player.MainVideoPlayer;
|
||||||
import org.schabi.newpipe.player.PopupVideoPlayer;
|
import org.schabi.newpipe.player.PopupVideoPlayer;
|
||||||
|
import org.schabi.newpipe.playlist.ExternalPlayQueue;
|
||||||
|
import org.schabi.newpipe.playlist.PlayQueue;
|
||||||
import org.schabi.newpipe.report.UserAction;
|
import org.schabi.newpipe.report.UserAction;
|
||||||
import org.schabi.newpipe.util.ExtractorHelper;
|
import org.schabi.newpipe.util.ExtractorHelper;
|
||||||
import org.schabi.newpipe.util.NavigationHelper;
|
import org.schabi.newpipe.util.NavigationHelper;
|
||||||
|
@ -172,9 +174,14 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Intent buildPlaylistIntent(final Class targetClazz) {
|
private Intent buildPlaylistIntent(final Class targetClazz) {
|
||||||
return NavigationHelper.getExternalPlaylistIntent(
|
final PlayQueue playQueue = new ExternalPlayQueue(
|
||||||
activity, targetClazz, currentInfo, infoListAdapter.getItemsList(), 0
|
currentInfo.service_id,
|
||||||
|
currentInfo.url,
|
||||||
|
currentInfo.next_streams_url,
|
||||||
|
infoListAdapter.getItemsList(),
|
||||||
|
0
|
||||||
);
|
);
|
||||||
|
return NavigationHelper.getPlayerIntent(activity, targetClazz, playQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -335,9 +335,18 @@ public final class BackgroundPlayer extends Service {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUpdateProgress(int currentProgress, int duration, int bufferPercent) {
|
public void onUpdateProgress(int currentProgress, int duration, int bufferPercent) {
|
||||||
if (bigNotRemoteView != null) bigNotRemoteView.setProgressBar(R.id.notificationProgressBar, duration, currentProgress, false);
|
if (bigNotRemoteView != null) {
|
||||||
if (notRemoteView != null) notRemoteView.setProgressBar(R.id.notificationProgressBar, duration, currentProgress, false);
|
bigNotRemoteView.setTextViewText(R.id.notificationSongName, getVideoTitle());
|
||||||
if (bigNotRemoteView != null) bigNotRemoteView.setTextViewText(R.id.notificationTime, getTimeString(currentProgress) + " / " + getTimeString(duration));
|
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);
|
updateNotification(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,7 +405,8 @@ public final class BackgroundPlayer extends Service {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MediaSource sourceOf(final StreamInfo info) {
|
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));
|
return buildMediaSource(audio.url, MediaFormat.getSuffixById(audio.format));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -137,6 +137,7 @@ public abstract class BasePlayer implements Player.EventListener,
|
||||||
public static final String CHANNEL_NAME = "channel_name";
|
public static final String CHANNEL_NAME = "channel_name";
|
||||||
public static final String PLAYBACK_SPEED = "playback_speed";
|
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_QUEUE_INDEX = "restore_queue_index";
|
||||||
public static final String RESTORE_WINDOW_POS = "restore_window_pos";
|
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 (DEBUG) Log.d(TAG, "handleIntent() called with: intent = [" + intent + "]");
|
||||||
if (intent == null) return;
|
if (intent == null) return;
|
||||||
|
|
||||||
setRecovery(
|
// Resolve play queue
|
||||||
intent.getIntExtra(RESTORE_QUEUE_INDEX, 0),
|
if (!intent.hasExtra(PLAY_QUEUE)) return;
|
||||||
intent.getLongExtra(START_POSITION, 0)
|
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()));
|
setPlaybackSpeed(intent.getFloatExtra(PLAYBACK_SPEED, getPlaybackSpeed()));
|
||||||
|
|
||||||
switch (intent.getStringExtra(INTENT_TYPE)) {
|
// Re-initialization
|
||||||
case SINGLE_STREAM:
|
destroyPlayer();
|
||||||
handleSinglePlaylistIntent(intent);
|
if (playQueue != null) playQueue.dispose();
|
||||||
break;
|
if (playbackManager != null) playbackManager.dispose();
|
||||||
case EXTERNAL_PLAYLIST:
|
initPlayer();
|
||||||
handleExternalPlaylistIntent(intent);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
// Good to go...
|
||||||
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);
|
|
||||||
initPlayback(this, queue);
|
initPlayback(this, queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void initPlayback(@NonNull final PlaybackListener listener, @NonNull final PlayQueue 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 = queue;
|
||||||
playQueue.init();
|
playQueue.init();
|
||||||
playbackManager = new MediaSourceManager(this, playQueue);
|
playbackManager = new MediaSourceManager(this, playQueue);
|
||||||
|
@ -976,6 +950,10 @@ public abstract class BasePlayer implements Player.EventListener,
|
||||||
return playQueue != null ? playQueue.getIndex() : -1;
|
return playQueue != null ? playQueue.getIndex() : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getCurrentResolutionTarget() {
|
||||||
|
return trackSelector != null ? trackSelector.getParameters().maxVideoHeight : Integer.MAX_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
public long getPlayerCurrentPosition() {
|
public long getPlayerCurrentPosition() {
|
||||||
return simpleExoPlayer != null ? simpleExoPlayer.getCurrentPosition() : 0L;
|
return simpleExoPlayer != null ? simpleExoPlayer.getCurrentPosition() : 0L;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.google.android.exoplayer2.Player;
|
import com.google.android.exoplayer2.Player;
|
||||||
|
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
|
||||||
|
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||||
|
@ -63,6 +64,8 @@ public final class MainVideoPlayer extends Activity {
|
||||||
private boolean activityPaused;
|
private boolean activityPaused;
|
||||||
private VideoPlayerImpl playerImpl;
|
private VideoPlayerImpl playerImpl;
|
||||||
|
|
||||||
|
private DefaultTrackSelector.Parameters parameters;
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// Activity LifeCycle
|
// Activity LifeCycle
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
@ -107,6 +110,11 @@ public final class MainVideoPlayer extends Activity {
|
||||||
super.onStop();
|
super.onStop();
|
||||||
if (DEBUG) Log.d(TAG, "onStop() called");
|
if (DEBUG) Log.d(TAG, "onStop() called");
|
||||||
activityPaused = true;
|
activityPaused = true;
|
||||||
|
|
||||||
|
if (playerImpl.trackSelector != null) {
|
||||||
|
parameters = playerImpl.trackSelector.getParameters();
|
||||||
|
}
|
||||||
|
|
||||||
if (playerImpl.getPlayer() != null) {
|
if (playerImpl.getPlayer() != null) {
|
||||||
playerImpl.wasPlaying = playerImpl.getPlayer().getPlayWhenReady();
|
playerImpl.wasPlaying = playerImpl.getPlayer().getPlayWhenReady();
|
||||||
playerImpl.setRecovery(
|
playerImpl.setRecovery(
|
||||||
|
@ -128,6 +136,10 @@ public final class MainVideoPlayer extends Activity {
|
||||||
playerImpl.getPlayer().setPlayWhenReady(playerImpl.wasPlaying);
|
playerImpl.getPlayer().setPlayWhenReady(playerImpl.wasPlaying);
|
||||||
playerImpl.initPlayback(playerImpl, playerImpl.playQueue);
|
playerImpl.initPlayback(playerImpl, playerImpl.playQueue);
|
||||||
|
|
||||||
|
if (playerImpl.trackSelector != null && parameters != null) {
|
||||||
|
playerImpl.trackSelector.setParameters(parameters);
|
||||||
|
}
|
||||||
|
|
||||||
activityPaused = false;
|
activityPaused = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -259,7 +271,15 @@ public final class MainVideoPlayer extends Activity {
|
||||||
return;
|
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);
|
context.startService(intent);
|
||||||
destroyPlayer();
|
destroyPlayer();
|
||||||
|
|
||||||
|
|
|
@ -412,7 +412,15 @@ public final class PopupVideoPlayer extends Service {
|
||||||
if (DEBUG) Log.d(TAG, "onFullScreenButtonClicked() called");
|
if (DEBUG) Log.d(TAG, "onFullScreenButtonClicked() called");
|
||||||
Intent intent;
|
Intent intent;
|
||||||
if (!getSharedPreferences().getBoolean(getResources().getString(R.string.use_old_player_key), false)) {
|
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);
|
if (!isStartedFromNewPipe()) intent.putExtra(VideoPlayer.STARTED_FROM_NEWPIPE, false);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
} else {
|
} else {
|
||||||
|
@ -741,7 +749,7 @@ public final class PopupVideoPlayer extends Service {
|
||||||
mainHandler.post(new Runnable() {
|
mainHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
playerImpl.playQueue = new SinglePlayQueue(info, PlayQueueItem.DEFAULT_QUALITY);
|
playerImpl.playQueue = new SinglePlayQueue(info);
|
||||||
playerImpl.playQueue.init();
|
playerImpl.playQueue.init();
|
||||||
playerImpl.playbackManager = new MediaSourceManager(playerImpl, playerImpl.playQueue);
|
playerImpl.playbackManager = new MediaSourceManager(playerImpl, playerImpl.playQueue);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 INDEX_SEL_VIDEO_STREAM = "index_selected_video_stream";
|
||||||
public static final String STARTED_FROM_NEWPIPE = "started_from_newpipe";
|
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 PLAYER_INTENT = "player_intent";
|
||||||
|
public static final String MAX_RESOLUTION = "max_resolution";
|
||||||
|
|
||||||
private VideoStream selectedIndexStream;
|
private VideoStream selectedIndexStream;
|
||||||
|
|
||||||
|
@ -212,36 +212,22 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer.
|
||||||
trackSelector.setTunnelingAudioSessionId(C.generateAudioSessionIdV21(context));
|
trackSelector.setTunnelingAudioSessionId(C.generateAudioSessionIdV21(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void handleIntent(Intent intent) {
|
public void handleIntent(Intent intent) {
|
||||||
super.handleIntent(intent);
|
super.handleIntent(intent);
|
||||||
|
|
||||||
if (intent == null) return;
|
if (intent == null) return;
|
||||||
|
|
||||||
if (intent.getStringExtra(INTENT_TYPE).equals(PLAYER_INTENT)) {
|
final int resolutionTarget = intent.getIntExtra(MAX_RESOLUTION, Integer.MAX_VALUE);
|
||||||
handlePlayerIntent(intent);
|
trackSelector.setParameters(
|
||||||
}
|
// Assume video is horizontal
|
||||||
|
new DefaultTrackSelector.Parameters().withMaxVideoSize(Integer.MAX_VALUE, resolutionTarget)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
public void handleSinglePlaylistIntent(Intent intent) {
|
// Playback Listener
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sync(@Nullable final StreamInfo info) {
|
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 int itemId = menuItem.getItemId();
|
||||||
final TrackGroupInfo info = trackGroupInfos.get(itemId);
|
final TrackGroupInfo info = trackGroupInfos.get(itemId);
|
||||||
|
|
||||||
final DefaultTrackSelector.Parameters parameters = new DefaultTrackSelector.Parameters()
|
DefaultTrackSelector.Parameters parameters;
|
||||||
.withMaxVideoSize(info.format.width, Integer.MAX_VALUE);
|
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);
|
trackSelector.setParameters(parameters);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -21,7 +21,7 @@ import java.util.List;
|
||||||
|
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.annotations.NonNull;
|
import io.reactivex.annotations.NonNull;
|
||||||
import io.reactivex.disposables.Disposable;
|
import io.reactivex.disposables.SerialDisposable;
|
||||||
import io.reactivex.functions.Consumer;
|
import io.reactivex.functions.Consumer;
|
||||||
|
|
||||||
public class MediaSourceManager implements DeferredMediaSource.Callback {
|
public class MediaSourceManager implements DeferredMediaSource.Callback {
|
||||||
|
@ -41,7 +41,7 @@ public class MediaSourceManager implements DeferredMediaSource.Callback {
|
||||||
private List<Integer> sourceToQueueIndex;
|
private List<Integer> sourceToQueueIndex;
|
||||||
|
|
||||||
private Subscription playQueueReactor;
|
private Subscription playQueueReactor;
|
||||||
private Disposable syncReactor;
|
private SerialDisposable syncReactor;
|
||||||
|
|
||||||
private boolean isBlocked;
|
private boolean isBlocked;
|
||||||
|
|
||||||
|
@ -50,6 +50,8 @@ public class MediaSourceManager implements DeferredMediaSource.Callback {
|
||||||
this.playbackListener = listener;
|
this.playbackListener = listener;
|
||||||
this.playQueue = playQueue;
|
this.playQueue = playQueue;
|
||||||
|
|
||||||
|
this.syncReactor = new SerialDisposable();
|
||||||
|
|
||||||
this.sources = new DynamicConcatenatingMediaSource();
|
this.sources = new DynamicConcatenatingMediaSource();
|
||||||
this.sourceToQueueIndex = Collections.synchronizedList(new ArrayList<Integer>());
|
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) {
|
private void load(@Nullable final PlayQueueItem item) {
|
||||||
|
|
|
@ -16,28 +16,21 @@ import io.reactivex.schedulers.Schedulers;
|
||||||
|
|
||||||
public class PlayQueueItem implements Serializable {
|
public class PlayQueueItem implements Serializable {
|
||||||
|
|
||||||
final public static int DEFAULT_QUALITY = -1;
|
|
||||||
|
|
||||||
final private String title;
|
final private String title;
|
||||||
final private String url;
|
final private String url;
|
||||||
final private int serviceId;
|
final private int serviceId;
|
||||||
final private long duration;
|
final private long duration;
|
||||||
|
|
||||||
// Externally mutable, not sure if this is a good idea here
|
|
||||||
private int sortedQualityIndex;
|
|
||||||
|
|
||||||
private Throwable error;
|
private Throwable error;
|
||||||
|
|
||||||
private transient Single<StreamInfo> stream;
|
private transient Single<StreamInfo> stream;
|
||||||
|
|
||||||
PlayQueueItem(final StreamInfo streamInfo, final int sortedQualityIndex) {
|
PlayQueueItem(final StreamInfo streamInfo) {
|
||||||
this.title = streamInfo.name;
|
this.title = streamInfo.name;
|
||||||
this.url = streamInfo.url;
|
this.url = streamInfo.url;
|
||||||
this.serviceId = streamInfo.service_id;
|
this.serviceId = streamInfo.service_id;
|
||||||
this.duration = streamInfo.duration;
|
this.duration = streamInfo.duration;
|
||||||
|
|
||||||
this.sortedQualityIndex = sortedQualityIndex;
|
|
||||||
|
|
||||||
this.stream = Single.just(streamInfo);
|
this.stream = Single.just(streamInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,11 +39,8 @@ public class PlayQueueItem implements Serializable {
|
||||||
this.url = streamInfoItem.url;
|
this.url = streamInfoItem.url;
|
||||||
this.serviceId = streamInfoItem.service_id;
|
this.serviceId = streamInfoItem.service_id;
|
||||||
this.duration = streamInfoItem.duration;
|
this.duration = streamInfoItem.duration;
|
||||||
|
|
||||||
this.sortedQualityIndex = DEFAULT_QUALITY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public String getTitle() {
|
public String getTitle() {
|
||||||
return title;
|
return title;
|
||||||
|
@ -69,14 +59,6 @@ public class PlayQueueItem implements Serializable {
|
||||||
return duration;
|
return duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSortedQualityIndex() {
|
|
||||||
return sortedQualityIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSortedQualityIndex(int sortedQualityIndex) {
|
|
||||||
this.sortedQualityIndex = sortedQualityIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public Throwable getError() {
|
public Throwable getError() {
|
||||||
return error;
|
return error;
|
||||||
|
|
|
@ -7,8 +7,8 @@ import java.util.Collections;
|
||||||
public final class SinglePlayQueue extends PlayQueue {
|
public final class SinglePlayQueue extends PlayQueue {
|
||||||
public static final String STREAM = "stream";
|
public static final String STREAM = "stream";
|
||||||
|
|
||||||
public SinglePlayQueue(final StreamInfo info, final int selectedQualityIndex) {
|
public SinglePlayQueue(final StreamInfo info) {
|
||||||
super(0, Collections.singletonList(new PlayQueueItem(info, selectedQualityIndex)));
|
super(0, Collections.singletonList(new PlayQueueItem(info)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -6,6 +6,7 @@ import android.content.Intent;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.app.FragmentManager;
|
import android.support.v4.app.FragmentManager;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||||
|
|
||||||
|
@ -33,12 +34,15 @@ import org.schabi.newpipe.player.BackgroundPlayer;
|
||||||
import org.schabi.newpipe.player.BasePlayer;
|
import org.schabi.newpipe.player.BasePlayer;
|
||||||
import org.schabi.newpipe.player.VideoPlayer;
|
import org.schabi.newpipe.player.VideoPlayer;
|
||||||
import org.schabi.newpipe.playlist.ExternalPlayQueue;
|
import org.schabi.newpipe.playlist.ExternalPlayQueue;
|
||||||
|
import org.schabi.newpipe.playlist.PlayQueue;
|
||||||
import org.schabi.newpipe.playlist.SinglePlayQueue;
|
import org.schabi.newpipe.playlist.SinglePlayQueue;
|
||||||
import org.schabi.newpipe.settings.SettingsActivity;
|
import org.schabi.newpipe.settings.SettingsActivity;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static android.text.TextUtils.split;
|
||||||
|
|
||||||
@SuppressWarnings({"unused", "WeakerAccess"})
|
@SuppressWarnings({"unused", "WeakerAccess"})
|
||||||
public class NavigationHelper {
|
public class NavigationHelper {
|
||||||
public static final String MAIN_FRAGMENT_TAG = "main_fragment_tag";
|
public static final String MAIN_FRAGMENT_TAG = "main_fragment_tag";
|
||||||
|
@ -46,41 +50,32 @@ public class NavigationHelper {
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// Players
|
// Players
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
public static Intent getPlayerIntent(final Context context,
|
||||||
public static Intent getOpenVideoPlayerIntent(Context context, Class targetClazz, StreamInfo info, int selectedStreamIndex) {
|
final Class targetClazz,
|
||||||
|
final PlayQueue playQueue) {
|
||||||
return new Intent(context, targetClazz)
|
return new Intent(context, targetClazz)
|
||||||
.putExtra(BasePlayer.INTENT_TYPE, VideoPlayer.SINGLE_STREAM)
|
.putExtra(VideoPlayer.PLAY_QUEUE, playQueue);
|
||||||
.putExtra(SinglePlayQueue.STREAM, info)
|
|
||||||
.putExtra(VideoPlayer.INDEX_SEL_VIDEO_STREAM, selectedStreamIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Intent getExternalPlaylistIntent(Context context,
|
public static Intent getPlayerIntent(final Context context,
|
||||||
Class targetClazz,
|
final Class targetClazz,
|
||||||
PlaylistInfo info,
|
final PlayQueue playQueue,
|
||||||
ArrayList<InfoItem> streams,
|
final int maxResolution) {
|
||||||
int index) {
|
return getPlayerIntent(context, targetClazz, playQueue)
|
||||||
return new Intent(context, targetClazz)
|
.putExtra(VideoPlayer.MAX_RESOLUTION, maxResolution);
|
||||||
.putExtra(BasePlayer.INTENT_TYPE, VideoPlayer.EXTERNAL_PLAYLIST)
|
|
||||||
.putExtra(ExternalPlayQueue.SERVICE_ID, info.service_id)
|
|
||||||
.putExtra(ExternalPlayQueue.INDEX, index)
|
|
||||||
.putExtra(ExternalPlayQueue.STREAMS, streams)
|
|
||||||
.putExtra(ExternalPlayQueue.URL, info.url)
|
|
||||||
.putExtra(ExternalPlayQueue.NEXT_PAGE_URL, info.next_streams_url);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Intent getOpenVideoPlayerIntent(Context context, Class targetClazz, VideoPlayer instance) {
|
public static Intent getPlayerIntent(final Context context,
|
||||||
return new Intent(context, targetClazz)
|
final Class targetClazz,
|
||||||
.putExtra(BasePlayer.INTENT_TYPE, VideoPlayer.PLAYER_INTENT)
|
final PlayQueue playQueue,
|
||||||
.putExtra(VideoPlayer.PLAY_QUEUE, instance.getPlayQueue())
|
final int maxResolution,
|
||||||
.putExtra(VideoPlayer.RESTORE_QUEUE_INDEX, instance.getCurrentQueueIndex())
|
final int restoringIndex,
|
||||||
.putExtra(BasePlayer.START_POSITION, instance.getPlayerCurrentPosition())
|
final long startPosition,
|
||||||
.putExtra(BasePlayer.PLAYBACK_SPEED, instance.getPlaybackSpeed());
|
final float playbackSpeed) {
|
||||||
}
|
return getPlayerIntent(context, targetClazz, playQueue, maxResolution)
|
||||||
|
.putExtra(VideoPlayer.RESTORE_QUEUE_INDEX, restoringIndex)
|
||||||
public static Intent getOpenBackgroundPlayerIntent(Context context, StreamInfo info) {
|
.putExtra(BasePlayer.START_POSITION, startPosition)
|
||||||
return new Intent(context, BackgroundPlayer.class)
|
.putExtra(BasePlayer.PLAYBACK_SPEED, playbackSpeed);
|
||||||
.putExtra(BasePlayer.INTENT_TYPE, VideoPlayer.SINGLE_STREAM)
|
|
||||||
.putExtra(SinglePlayQueue.STREAM, info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
Loading…
Reference in New Issue