mirror of
https://github.com/TeamNewPipe/NewPipe.git
synced 2024-11-22 19:12:45 +01:00
Merge pull request #5371 from Stypox/merge-player
Merge player classes into a single one
This commit is contained in:
commit
c90696e67e
@ -53,7 +53,7 @@
|
||||
</service>
|
||||
|
||||
<activity
|
||||
android:name=".player.BackgroundPlayerActivity"
|
||||
android:name=".player.PlayQueueActivity"
|
||||
android:label="@string/title_activity_play_queue"
|
||||
android:launchMode="singleTask" />
|
||||
|
||||
|
@ -70,7 +70,7 @@ import org.schabi.newpipe.fragments.BackPressable;
|
||||
import org.schabi.newpipe.fragments.MainFragment;
|
||||
import org.schabi.newpipe.fragments.detail.VideoDetailFragment;
|
||||
import org.schabi.newpipe.fragments.list.search.SearchFragment;
|
||||
import org.schabi.newpipe.player.VideoPlayer;
|
||||
import org.schabi.newpipe.player.Player;
|
||||
import org.schabi.newpipe.player.event.OnKeyDownListener;
|
||||
import org.schabi.newpipe.player.helper.PlayerHolder;
|
||||
import org.schabi.newpipe.player.playqueue.PlayQueue;
|
||||
@ -759,7 +759,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
switch (linkType) {
|
||||
case STREAM:
|
||||
final String intentCacheKey = intent.getStringExtra(
|
||||
VideoPlayer.PLAY_QUEUE_KEY);
|
||||
Player.PLAY_QUEUE_KEY);
|
||||
final PlayQueue playQueue = intentCacheKey != null
|
||||
? SerializedCache.getInstance()
|
||||
.take(intentCacheKey, PlayQueue.class)
|
||||
|
@ -49,7 +49,6 @@ import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.google.android.exoplayer2.ExoPlaybackException;
|
||||
import com.google.android.exoplayer2.PlaybackParameters;
|
||||
import com.google.android.exoplayer2.Player;
|
||||
import com.google.android.material.appbar.AppBarLayout;
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
@ -80,9 +79,8 @@ import org.schabi.newpipe.fragments.list.videos.RelatedVideosFragment;
|
||||
import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
|
||||
import org.schabi.newpipe.local.dialog.PlaylistCreationDialog;
|
||||
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
||||
import org.schabi.newpipe.player.BasePlayer;
|
||||
import org.schabi.newpipe.player.Player;
|
||||
import org.schabi.newpipe.player.MainPlayer;
|
||||
import org.schabi.newpipe.player.VideoPlayerImpl;
|
||||
import org.schabi.newpipe.player.event.OnKeyDownListener;
|
||||
import org.schabi.newpipe.player.event.PlayerServiceExtendedEventListener;
|
||||
import org.schabi.newpipe.player.helper.PlayerHelper;
|
||||
@ -255,14 +253,14 @@ public final class VideoDetailFragment
|
||||
|
||||
private ContentObserver settingsContentObserver;
|
||||
private MainPlayer playerService;
|
||||
private VideoPlayerImpl player;
|
||||
private Player player;
|
||||
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Service management
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
@Override
|
||||
public void onServiceConnected(final VideoPlayerImpl connectedPlayer,
|
||||
public void onServiceConnected(final Player connectedPlayer,
|
||||
final MainPlayer connectedPlayerService,
|
||||
final boolean playAfterConnect) {
|
||||
player = connectedPlayer;
|
||||
@ -539,7 +537,7 @@ public final class VideoDetailFragment
|
||||
break;
|
||||
case R.id.overlay_play_pause_button:
|
||||
if (playerIsNotStopped()) {
|
||||
player.onPlayPause();
|
||||
player.playPause();
|
||||
player.hideControls(0, 0);
|
||||
showSystemUi();
|
||||
} else {
|
||||
@ -805,7 +803,7 @@ public final class VideoDetailFragment
|
||||
// If we are in fullscreen mode just exit from it via first back press
|
||||
if (player != null && player.isFullscreen()) {
|
||||
if (!DeviceUtils.isTablet(activity)) {
|
||||
player.onPause();
|
||||
player.pause();
|
||||
}
|
||||
restoreDefaultOrientation();
|
||||
setAutoPlay(false);
|
||||
@ -850,7 +848,7 @@ public final class VideoDetailFragment
|
||||
|
||||
final PlayQueueItem playQueueItem = item.getPlayQueue().getItem();
|
||||
// Update title, url, uploader from the last item in the stack (it's current now)
|
||||
final boolean isPlayerStopped = player == null || player.isPlayerStopped();
|
||||
final boolean isPlayerStopped = player == null || player.isStopped();
|
||||
if (playQueueItem != null && isPlayerStopped) {
|
||||
updateOverlayData(playQueueItem.getTitle(),
|
||||
playQueueItem.getUploader(), playQueueItem.getThumbnailUrl());
|
||||
@ -1569,7 +1567,7 @@ public final class VideoDetailFragment
|
||||
showMetaInfoInTextView(info.getMetaInfo(), detailMetaInfoTextView, detailMetaInfoSeparator);
|
||||
|
||||
|
||||
if (player == null || player.isPlayerStopped()) {
|
||||
if (player == null || player.isStopped()) {
|
||||
updateOverlayData(info.getName(), info.getUploaderName(), info.getThumbnailUrl());
|
||||
}
|
||||
|
||||
@ -1797,7 +1795,7 @@ public final class VideoDetailFragment
|
||||
setOverlayPlayPauseImage(player != null && player.isPlaying());
|
||||
|
||||
switch (state) {
|
||||
case BasePlayer.STATE_PLAYING:
|
||||
case Player.STATE_PLAYING:
|
||||
if (positionView.getAlpha() != 1.0f
|
||||
&& player.getPlayQueue() != null
|
||||
&& player.getPlayQueue().getItem() != null
|
||||
@ -1814,7 +1812,7 @@ public final class VideoDetailFragment
|
||||
final int duration,
|
||||
final int bufferPercent) {
|
||||
// Progress updates every second even if media is paused. It's useless until playing
|
||||
if (!player.getPlayer().isPlaying() || playQueue == null) {
|
||||
if (!player.isPlaying() || playQueue == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1891,10 +1889,8 @@ public final class VideoDetailFragment
|
||||
|
||||
if (fullscreen) {
|
||||
hideSystemUiIfNeeded();
|
||||
viewPager.setVisibility(View.GONE);
|
||||
} else {
|
||||
showSystemUi();
|
||||
viewPager.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (relatedStreamsLayout != null) {
|
||||
@ -2020,9 +2016,7 @@ public final class VideoDetailFragment
|
||||
}
|
||||
|
||||
private boolean playerIsNotStopped() {
|
||||
return player != null
|
||||
&& player.getPlayer() != null
|
||||
&& player.getPlayer().getPlaybackState() != Player.STATE_IDLE;
|
||||
return player != null && !player.isStopped();
|
||||
}
|
||||
|
||||
private void restoreDefaultBrightness() {
|
||||
@ -2073,7 +2067,7 @@ public final class VideoDetailFragment
|
||||
player.checkLandscape();
|
||||
// Let's give a user time to look at video information page if video is not playing
|
||||
if (globalScreenOrientationLocked(activity) && !player.isPlaying()) {
|
||||
player.onPlay();
|
||||
player.play();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2287,7 +2281,7 @@ public final class VideoDetailFragment
|
||||
// Re-enable clicks
|
||||
setOverlayElementsClickable(true);
|
||||
if (player != null) {
|
||||
player.onQueueClosed();
|
||||
player.closeQueue();
|
||||
}
|
||||
setOverlayLook(appBarLayout, behavior, 0);
|
||||
break;
|
||||
|
@ -1,57 +0,0 @@
|
||||
package org.schabi.newpipe.player;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.view.Menu;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
|
||||
public final class BackgroundPlayerActivity extends ServicePlayerActivity {
|
||||
|
||||
private static final String TAG = "BackgroundPlayerActivity";
|
||||
|
||||
@Override
|
||||
public String getTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSupportActionTitle() {
|
||||
return getResources().getString(R.string.title_activity_play_queue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Intent getBindIntent() {
|
||||
return new Intent(this, MainPlayer.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startPlayerListener() {
|
||||
if (player instanceof VideoPlayerImpl) {
|
||||
((VideoPlayerImpl) player).setActivityListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopPlayerListener() {
|
||||
if (player instanceof VideoPlayerImpl) {
|
||||
((VideoPlayerImpl) player).removeActivityListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerOptionMenuResource() {
|
||||
return R.menu.menu_play_queue_bg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupMenu(final Menu menu) {
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
menu.findItem(R.id.action_switch_popup)
|
||||
.setVisible(!((VideoPlayerImpl) player).popupPlayerSelected());
|
||||
menu.findItem(R.id.action_switch_background)
|
||||
.setVisible(!((VideoPlayerImpl) player).audioPlayerSelected());
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -48,9 +48,9 @@ import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
||||
*/
|
||||
public final class MainPlayer extends Service {
|
||||
private static final String TAG = "MainPlayer";
|
||||
private static final boolean DEBUG = BasePlayer.DEBUG;
|
||||
private static final boolean DEBUG = Player.DEBUG;
|
||||
|
||||
private VideoPlayerImpl playerImpl;
|
||||
private Player player;
|
||||
private WindowManager windowManager;
|
||||
|
||||
private final IBinder mBinder = new MainPlayer.LocalBinder();
|
||||
@ -69,8 +69,6 @@ public final class MainPlayer extends Service {
|
||||
= App.PACKAGE_NAME + ".player.MainPlayer.CLOSE";
|
||||
static final String ACTION_PLAY_PAUSE
|
||||
= App.PACKAGE_NAME + ".player.MainPlayer.PLAY_PAUSE";
|
||||
static final String ACTION_OPEN_CONTROLS
|
||||
= App.PACKAGE_NAME + ".player.MainPlayer.OPEN_CONTROLS";
|
||||
static final String ACTION_REPEAT
|
||||
= App.PACKAGE_NAME + ".player.MainPlayer.REPEAT";
|
||||
static final String ACTION_PLAY_NEXT
|
||||
@ -105,11 +103,10 @@ public final class MainPlayer extends Service {
|
||||
private void createView() {
|
||||
final PlayerBinding binding = PlayerBinding.inflate(LayoutInflater.from(this));
|
||||
|
||||
playerImpl = new VideoPlayerImpl(this);
|
||||
playerImpl.setup(binding);
|
||||
playerImpl.shouldUpdateOnProgress = true;
|
||||
player = new Player(this);
|
||||
player.setupFromView(binding);
|
||||
|
||||
NotificationUtil.getInstance().createNotificationAndStartForeground(playerImpl, this);
|
||||
NotificationUtil.getInstance().createNotificationAndStartForeground(player, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -119,19 +116,19 @@ public final class MainPlayer extends Service {
|
||||
+ "], flags = [" + flags + "], startId = [" + startId + "]");
|
||||
}
|
||||
if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())
|
||||
&& playerImpl.playQueue == null) {
|
||||
&& player.getPlayQueue() == null) {
|
||||
// Player is not working, no need to process media button's action
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
|
||||
if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())
|
||||
|| intent.getStringExtra(VideoPlayer.PLAY_QUEUE_KEY) != null) {
|
||||
NotificationUtil.getInstance().createNotificationAndStartForeground(playerImpl, this);
|
||||
|| intent.getStringExtra(Player.PLAY_QUEUE_KEY) != null) {
|
||||
NotificationUtil.getInstance().createNotificationAndStartForeground(player, this);
|
||||
}
|
||||
|
||||
playerImpl.handleIntent(intent);
|
||||
if (playerImpl.mediaSessionManager != null) {
|
||||
playerImpl.mediaSessionManager.handleMediaButtonIntent(intent);
|
||||
player.handleIntent(intent);
|
||||
if (player.getMediaSessionManager() != null) {
|
||||
player.getMediaSessionManager().handleMediaButtonIntent(intent);
|
||||
}
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
@ -141,20 +138,20 @@ public final class MainPlayer extends Service {
|
||||
Log.d(TAG, "stop() called");
|
||||
}
|
||||
|
||||
if (playerImpl.getPlayer() != null) {
|
||||
playerImpl.wasPlaying = playerImpl.getPlayer().getPlayWhenReady();
|
||||
if (!player.exoPlayerIsNull()) {
|
||||
player.saveWasPlaying();
|
||||
// Releases wifi & cpu, disables keepScreenOn, etc.
|
||||
if (!autoplayEnabled) {
|
||||
playerImpl.onPause();
|
||||
player.pause();
|
||||
}
|
||||
// We can't just pause the player here because it will make transition
|
||||
// from one stream to a new stream not smooth
|
||||
playerImpl.getPlayer().stop(false);
|
||||
playerImpl.setRecovery();
|
||||
player.smoothStopPlayer();
|
||||
player.setRecovery();
|
||||
// Android TV will handle back button in case controls will be visible
|
||||
// (one more additional unneeded click while the player is hidden)
|
||||
playerImpl.hideControls(0, 0);
|
||||
playerImpl.onQueueClosed();
|
||||
player.hideControls(0, 0);
|
||||
player.closeQueue();
|
||||
// Notification shows information about old stream but if a user selects
|
||||
// a stream from backStack it's not actual anymore
|
||||
// So we should hide the notification at all.
|
||||
@ -168,7 +165,7 @@ public final class MainPlayer extends Service {
|
||||
@Override
|
||||
public void onTaskRemoved(final Intent rootIntent) {
|
||||
super.onTaskRemoved(rootIntent);
|
||||
if (!playerImpl.videoPlayerSelected()) {
|
||||
if (!player.videoPlayerSelected()) {
|
||||
return;
|
||||
}
|
||||
onDestroy();
|
||||
@ -181,7 +178,23 @@ public final class MainPlayer extends Service {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "destroy() called");
|
||||
}
|
||||
onClose();
|
||||
|
||||
if (player != null) {
|
||||
// Exit from fullscreen when user closes the player via notification
|
||||
if (player.isFullscreen()) {
|
||||
player.toggleFullscreen();
|
||||
}
|
||||
removeViewFromParent();
|
||||
|
||||
player.saveStreamProgressState();
|
||||
player.setRecovery();
|
||||
player.stopActivityBinding();
|
||||
player.removePopupFromView();
|
||||
player.destroy();
|
||||
}
|
||||
|
||||
NotificationUtil.getInstance().cancelNotificationAndStopForeground(this);
|
||||
stopSelf();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -194,32 +207,6 @@ public final class MainPlayer extends Service {
|
||||
return mBinder;
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Actions
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
private void onClose() {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "onClose() called");
|
||||
}
|
||||
|
||||
if (playerImpl != null) {
|
||||
// Exit from fullscreen when user closes the player via notification
|
||||
if (playerImpl.isFullscreen()) {
|
||||
playerImpl.toggleFullscreen();
|
||||
}
|
||||
removeViewFromParent();
|
||||
|
||||
playerImpl.setRecovery();
|
||||
playerImpl.savePlaybackState();
|
||||
playerImpl.stopActivityBinding();
|
||||
playerImpl.removePopupFromView();
|
||||
playerImpl.destroy();
|
||||
}
|
||||
|
||||
NotificationUtil.getInstance().cancelNotificationAndStopForeground(this);
|
||||
stopSelf();
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Utils
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
@ -227,25 +214,25 @@ public final class MainPlayer extends Service {
|
||||
boolean isLandscape() {
|
||||
// DisplayMetrics from activity context knows about MultiWindow feature
|
||||
// while DisplayMetrics from app context doesn't
|
||||
final DisplayMetrics metrics = (playerImpl != null
|
||||
&& playerImpl.getParentActivity() != null
|
||||
? playerImpl.getParentActivity().getResources()
|
||||
final DisplayMetrics metrics = (player != null
|
||||
&& player.getParentActivity() != null
|
||||
? player.getParentActivity().getResources()
|
||||
: getResources()).getDisplayMetrics();
|
||||
return metrics.heightPixels < metrics.widthPixels;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public View getView() {
|
||||
if (playerImpl == null) {
|
||||
if (player == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return playerImpl.getRootView();
|
||||
return player.getRootView();
|
||||
}
|
||||
|
||||
public void removeViewFromParent() {
|
||||
if (getView() != null && getView().getParent() != null) {
|
||||
if (playerImpl.getParentActivity() != null) {
|
||||
if (player.getParentActivity() != null) {
|
||||
// This means view was added to fragment
|
||||
final ViewGroup parent = (ViewGroup) getView().getParent();
|
||||
parent.removeView(getView());
|
||||
@ -263,8 +250,8 @@ public final class MainPlayer extends Service {
|
||||
return MainPlayer.this;
|
||||
}
|
||||
|
||||
public VideoPlayerImpl getPlayer() {
|
||||
return MainPlayer.this.playerImpl;
|
||||
public Player getPlayer() {
|
||||
return MainPlayer.this.player;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ import static org.schabi.newpipe.player.MainPlayer.ACTION_SHUFFLE;
|
||||
*/
|
||||
public final class NotificationUtil {
|
||||
private static final String TAG = NotificationUtil.class.getSimpleName();
|
||||
private static final boolean DEBUG = BasePlayer.DEBUG;
|
||||
private static final boolean DEBUG = Player.DEBUG;
|
||||
private static final int NOTIFICATION_ID = 123789;
|
||||
|
||||
@Nullable private static NotificationUtil instance = null;
|
||||
@ -76,7 +76,7 @@ public final class NotificationUtil {
|
||||
* @param forceRecreate whether to force the recreation of the notification even if it already
|
||||
* exists
|
||||
*/
|
||||
synchronized void createNotificationIfNeededAndUpdate(final VideoPlayerImpl player,
|
||||
synchronized void createNotificationIfNeededAndUpdate(final Player player,
|
||||
final boolean forceRecreate) {
|
||||
if (forceRecreate || notificationBuilder == null) {
|
||||
notificationBuilder = createNotification(player);
|
||||
@ -85,14 +85,14 @@ public final class NotificationUtil {
|
||||
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
|
||||
}
|
||||
|
||||
private synchronized NotificationCompat.Builder createNotification(
|
||||
final VideoPlayerImpl player) {
|
||||
private synchronized NotificationCompat.Builder createNotification(final Player player) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "createNotification()");
|
||||
}
|
||||
notificationManager = NotificationManagerCompat.from(player.context);
|
||||
final NotificationCompat.Builder builder = new NotificationCompat.Builder(player.context,
|
||||
player.context.getString(R.string.notification_channel_id));
|
||||
notificationManager = NotificationManagerCompat.from(player.getContext());
|
||||
final NotificationCompat.Builder builder =
|
||||
new NotificationCompat.Builder(player.getContext(),
|
||||
player.getContext().getString(R.string.notification_channel_id));
|
||||
|
||||
initializeNotificationSlots(player);
|
||||
|
||||
@ -107,25 +107,25 @@ public final class NotificationUtil {
|
||||
|
||||
// build the compact slot indices array (need code to convert from Integer... because Java)
|
||||
final List<Integer> compactSlotList = NotificationConstants.getCompactSlotsFromPreferences(
|
||||
player.context, player.sharedPreferences, nonNothingSlotCount);
|
||||
player.getContext(), player.getPrefs(), nonNothingSlotCount);
|
||||
final int[] compactSlots = new int[compactSlotList.size()];
|
||||
for (int i = 0; i < compactSlotList.size(); i++) {
|
||||
compactSlots[i] = compactSlotList.get(i);
|
||||
}
|
||||
|
||||
builder.setStyle(new androidx.media.app.NotificationCompat.MediaStyle()
|
||||
.setMediaSession(player.mediaSessionManager.getSessionToken())
|
||||
.setMediaSession(player.getMediaSessionManager().getSessionToken())
|
||||
.setShowActionsInCompactView(compactSlots))
|
||||
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||
.setCategory(NotificationCompat.CATEGORY_TRANSPORT)
|
||||
.setShowWhen(false)
|
||||
.setSmallIcon(R.drawable.ic_newpipe_triangle_white)
|
||||
.setColor(ContextCompat.getColor(player.context, R.color.dark_background_color))
|
||||
.setColorized(player.sharedPreferences.getBoolean(
|
||||
player.context.getString(R.string.notification_colorize_key),
|
||||
true))
|
||||
.setDeleteIntent(PendingIntent.getBroadcast(player.context, NOTIFICATION_ID,
|
||||
.setColor(ContextCompat.getColor(player.getContext(),
|
||||
R.color.dark_background_color))
|
||||
.setColorized(player.getPrefs().getBoolean(
|
||||
player.getContext().getString(R.string.notification_colorize_key), true))
|
||||
.setDeleteIntent(PendingIntent.getBroadcast(player.getContext(), NOTIFICATION_ID,
|
||||
new Intent(ACTION_CLOSE), FLAG_UPDATE_CURRENT));
|
||||
|
||||
return builder;
|
||||
@ -135,20 +135,20 @@ public final class NotificationUtil {
|
||||
* Updates the notification builder and the button icons depending on the playback state.
|
||||
* @param player the player currently open, to take data from
|
||||
*/
|
||||
private synchronized void updateNotification(final VideoPlayerImpl player) {
|
||||
private synchronized void updateNotification(final Player player) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "updateNotification()");
|
||||
}
|
||||
|
||||
// also update content intent, in case the user switched players
|
||||
notificationBuilder.setContentIntent(PendingIntent.getActivity(player.context,
|
||||
notificationBuilder.setContentIntent(PendingIntent.getActivity(player.getContext(),
|
||||
NOTIFICATION_ID, getIntentForNotification(player), FLAG_UPDATE_CURRENT));
|
||||
notificationBuilder.setContentTitle(player.getVideoTitle());
|
||||
notificationBuilder.setContentText(player.getUploaderName());
|
||||
notificationBuilder.setTicker(player.getVideoTitle());
|
||||
updateActions(notificationBuilder, player);
|
||||
final boolean showThumbnail = player.sharedPreferences.getBoolean(
|
||||
player.context.getString(R.string.show_thumbnail_key), true);
|
||||
final boolean showThumbnail = player.getPrefs().getBoolean(
|
||||
player.getContext().getString(R.string.show_thumbnail_key), true);
|
||||
if (showThumbnail) {
|
||||
setLargeIcon(notificationBuilder, player);
|
||||
}
|
||||
@ -174,7 +174,7 @@ public final class NotificationUtil {
|
||||
}
|
||||
|
||||
|
||||
void createNotificationAndStartForeground(final VideoPlayerImpl player, final Service service) {
|
||||
void createNotificationAndStartForeground(final Player player, final Service service) {
|
||||
if (notificationBuilder == null) {
|
||||
notificationBuilder = createNotification(player);
|
||||
}
|
||||
@ -203,17 +203,16 @@ public final class NotificationUtil {
|
||||
// ACTIONS
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
private void initializeNotificationSlots(final VideoPlayerImpl player) {
|
||||
private void initializeNotificationSlots(final Player player) {
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
notificationSlots[i] = player.sharedPreferences.getInt(
|
||||
player.context.getString(NotificationConstants.SLOT_PREF_KEYS[i]),
|
||||
notificationSlots[i] = player.getPrefs().getInt(
|
||||
player.getContext().getString(NotificationConstants.SLOT_PREF_KEYS[i]),
|
||||
NotificationConstants.SLOT_DEFAULTS[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
private void updateActions(final NotificationCompat.Builder builder,
|
||||
final VideoPlayerImpl player) {
|
||||
private void updateActions(final NotificationCompat.Builder builder, final Player player) {
|
||||
builder.mActions.clear();
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
addAction(builder, player, notificationSlots[i]);
|
||||
@ -221,7 +220,7 @@ public final class NotificationUtil {
|
||||
}
|
||||
|
||||
private void addAction(final NotificationCompat.Builder builder,
|
||||
final VideoPlayerImpl player,
|
||||
final Player player,
|
||||
@NotificationConstants.Action final int slot) {
|
||||
final NotificationCompat.Action action = getAction(player, slot);
|
||||
if (action != null) {
|
||||
@ -231,7 +230,7 @@ public final class NotificationUtil {
|
||||
|
||||
@Nullable
|
||||
private NotificationCompat.Action getAction(
|
||||
final VideoPlayerImpl player,
|
||||
final Player player,
|
||||
@NotificationConstants.Action final int selectedAction) {
|
||||
final int baseActionIcon = NotificationConstants.ACTION_ICONS[selectedAction];
|
||||
switch (selectedAction) {
|
||||
@ -252,7 +251,7 @@ public final class NotificationUtil {
|
||||
R.string.exo_controls_fastforward_description, ACTION_FAST_FORWARD);
|
||||
|
||||
case NotificationConstants.SMART_REWIND_PREVIOUS:
|
||||
if (player.playQueue != null && player.playQueue.size() > 1) {
|
||||
if (player.getPlayQueue() != null && player.getPlayQueue().size() > 1) {
|
||||
return getAction(player, R.drawable.exo_notification_previous,
|
||||
R.string.exo_controls_previous_description, ACTION_PLAY_PREVIOUS);
|
||||
} else {
|
||||
@ -261,7 +260,7 @@ public final class NotificationUtil {
|
||||
}
|
||||
|
||||
case NotificationConstants.SMART_FORWARD_NEXT:
|
||||
if (player.playQueue != null && player.playQueue.size() > 1) {
|
||||
if (player.getPlayQueue() != null && player.getPlayQueue().size() > 1) {
|
||||
return getAction(player, R.drawable.exo_notification_next,
|
||||
R.string.exo_controls_next_description, ACTION_PLAY_NEXT);
|
||||
} else {
|
||||
@ -270,23 +269,23 @@ public final class NotificationUtil {
|
||||
}
|
||||
|
||||
case NotificationConstants.PLAY_PAUSE_BUFFERING:
|
||||
if (player.getCurrentState() == BasePlayer.STATE_PREFLIGHT
|
||||
|| player.getCurrentState() == BasePlayer.STATE_BLOCKED
|
||||
|| player.getCurrentState() == BasePlayer.STATE_BUFFERING) {
|
||||
if (player.getCurrentState() == Player.STATE_PREFLIGHT
|
||||
|| player.getCurrentState() == Player.STATE_BLOCKED
|
||||
|| player.getCurrentState() == Player.STATE_BUFFERING) {
|
||||
// null intent -> show hourglass icon that does nothing when clicked
|
||||
return new NotificationCompat.Action(R.drawable.ic_hourglass_top_white_24dp_png,
|
||||
player.context.getString(R.string.notification_action_buffering),
|
||||
player.getContext().getString(R.string.notification_action_buffering),
|
||||
null);
|
||||
}
|
||||
|
||||
case NotificationConstants.PLAY_PAUSE:
|
||||
if (player.getCurrentState() == BasePlayer.STATE_COMPLETED) {
|
||||
if (player.getCurrentState() == Player.STATE_COMPLETED) {
|
||||
return getAction(player, R.drawable.ic_replay_white_24dp_png,
|
||||
R.string.exo_controls_pause_description, ACTION_PLAY_PAUSE);
|
||||
} else if (player.isPlaying()
|
||||
|| player.getCurrentState() == BasePlayer.STATE_PREFLIGHT
|
||||
|| player.getCurrentState() == BasePlayer.STATE_BLOCKED
|
||||
|| player.getCurrentState() == BasePlayer.STATE_BUFFERING) {
|
||||
|| player.getCurrentState() == Player.STATE_PREFLIGHT
|
||||
|| player.getCurrentState() == Player.STATE_BLOCKED
|
||||
|| player.getCurrentState() == Player.STATE_BUFFERING) {
|
||||
return getAction(player, R.drawable.exo_notification_pause,
|
||||
R.string.exo_controls_pause_description, ACTION_PLAY_PAUSE);
|
||||
} else {
|
||||
@ -307,7 +306,7 @@ public final class NotificationUtil {
|
||||
}
|
||||
|
||||
case NotificationConstants.SHUFFLE:
|
||||
if (player.playQueue != null && player.playQueue.isShuffled()) {
|
||||
if (player.getPlayQueue() != null && player.getPlayQueue().isShuffled()) {
|
||||
return getAction(player, R.drawable.exo_controls_shuffle_on,
|
||||
R.string.exo_controls_shuffle_on_description, ACTION_SHUFFLE);
|
||||
} else {
|
||||
@ -326,23 +325,23 @@ public final class NotificationUtil {
|
||||
}
|
||||
}
|
||||
|
||||
private NotificationCompat.Action getAction(final VideoPlayerImpl player,
|
||||
private NotificationCompat.Action getAction(final Player player,
|
||||
@DrawableRes final int drawable,
|
||||
@StringRes final int title,
|
||||
final String intentAction) {
|
||||
return new NotificationCompat.Action(drawable, player.context.getString(title),
|
||||
PendingIntent.getBroadcast(player.context, NOTIFICATION_ID,
|
||||
return new NotificationCompat.Action(drawable, player.getContext().getString(title),
|
||||
PendingIntent.getBroadcast(player.getContext(), NOTIFICATION_ID,
|
||||
new Intent(intentAction), FLAG_UPDATE_CURRENT));
|
||||
}
|
||||
|
||||
private Intent getIntentForNotification(final VideoPlayerImpl player) {
|
||||
private Intent getIntentForNotification(final Player player) {
|
||||
if (player.audioPlayerSelected() || player.popupPlayerSelected()) {
|
||||
// Means we play in popup or audio only. Let's show the play queue
|
||||
return NavigationHelper.getPlayQueueActivityIntent(player.context);
|
||||
return NavigationHelper.getPlayQueueActivityIntent(player.getContext());
|
||||
} else {
|
||||
// We are playing in fragment. Don't open another activity just show fragment. That's it
|
||||
final Intent intent = NavigationHelper.getPlayerIntent(
|
||||
player.context, MainActivity.class, null, true);
|
||||
player.getContext(), MainActivity.class, null, true);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.setAction(Intent.ACTION_MAIN);
|
||||
intent.addCategory(Intent.CATEGORY_LAUNCHER);
|
||||
@ -355,10 +354,9 @@ public final class NotificationUtil {
|
||||
// BITMAP
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
private void setLargeIcon(final NotificationCompat.Builder builder,
|
||||
final VideoPlayerImpl player) {
|
||||
final boolean scaleImageToSquareAspectRatio = player.sharedPreferences.getBoolean(
|
||||
player.context.getString(R.string.scale_to_square_image_in_notifications_key),
|
||||
private void setLargeIcon(final NotificationCompat.Builder builder, final Player player) {
|
||||
final boolean scaleImageToSquareAspectRatio = player.getPrefs().getBoolean(
|
||||
player.getContext().getString(R.string.scale_to_square_image_in_notifications_key),
|
||||
false);
|
||||
if (scaleImageToSquareAspectRatio) {
|
||||
builder.setLargeIcon(getBitmapWithSquareAspectRatio(player.getThumbnail()));
|
||||
|
@ -16,13 +16,11 @@ import android.widget.PopupMenu;
|
||||
import android.widget.SeekBar;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.exoplayer2.PlaybackParameters;
|
||||
import com.google.android.exoplayer2.Player;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.databinding.ActivityPlayerQueueControlBinding;
|
||||
@ -49,19 +47,21 @@ import java.util.List;
|
||||
import static org.schabi.newpipe.player.helper.PlayerHelper.formatSpeed;
|
||||
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
||||
|
||||
public abstract class ServicePlayerActivity extends AppCompatActivity
|
||||
public final class PlayQueueActivity extends AppCompatActivity
|
||||
implements PlayerEventListener, SeekBar.OnSeekBarChangeListener,
|
||||
View.OnClickListener, PlaybackParameterDialog.Callback {
|
||||
|
||||
private static final String TAG = PlayQueueActivity.class.getSimpleName();
|
||||
|
||||
private static final int RECYCLER_ITEM_POPUP_MENU_GROUP_ID = 47;
|
||||
private static final int SMOOTH_SCROLL_MAXIMUM_DISTANCE = 80;
|
||||
|
||||
protected BasePlayer player;
|
||||
protected Player player;
|
||||
|
||||
private boolean serviceBound;
|
||||
private ServiceConnection serviceConnection;
|
||||
|
||||
private boolean seeking;
|
||||
private boolean redraw;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Views
|
||||
@ -73,24 +73,6 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
|
||||
|
||||
private Menu menu;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Abstracts
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public abstract String getTag();
|
||||
|
||||
public abstract String getSupportActionTitle();
|
||||
|
||||
public abstract Intent getBindIntent();
|
||||
|
||||
public abstract void startPlayerListener();
|
||||
|
||||
public abstract void stopPlayerListener();
|
||||
|
||||
public abstract int getPlayerOptionMenuResource();
|
||||
|
||||
public abstract void setupMenu(Menu m);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Activity Lifecycle
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
@ -107,35 +89,32 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
|
||||
setSupportActionBar(queueControlBinding.toolbar);
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setTitle(getSupportActionTitle());
|
||||
getSupportActionBar().setTitle(R.string.title_activity_play_queue);
|
||||
}
|
||||
|
||||
serviceConnection = getServiceConnection();
|
||||
bind();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
if (redraw) {
|
||||
ActivityCompat.recreate(this);
|
||||
redraw = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(final Menu m) {
|
||||
this.menu = m;
|
||||
getMenuInflater().inflate(R.menu.menu_play_queue, m);
|
||||
getMenuInflater().inflate(getPlayerOptionMenuResource(), m);
|
||||
getMenuInflater().inflate(R.menu.menu_play_queue_bg, m);
|
||||
onMaybeMuteChanged();
|
||||
onPlaybackParameterChanged(player.getPlaybackParameters());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Allow to setup visibility of menuItems
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(final Menu m) {
|
||||
setupMenu(m);
|
||||
if (player != null) {
|
||||
menu.findItem(R.id.action_switch_popup)
|
||||
.setVisible(!player.popupPlayerSelected());
|
||||
menu.findItem(R.id.action_switch_background)
|
||||
.setVisible(!player.audioPlayerSelected());
|
||||
}
|
||||
return super.onPrepareOptionsMenu(m);
|
||||
}
|
||||
|
||||
@ -167,14 +146,14 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
|
||||
case R.id.action_switch_popup:
|
||||
if (PermissionHelper.isPopupEnabled(this)) {
|
||||
this.player.setRecovery();
|
||||
NavigationHelper.playOnPopupPlayer(this, player.playQueue, true);
|
||||
NavigationHelper.playOnPopupPlayer(this, player.getPlayQueue(), true);
|
||||
} else {
|
||||
PermissionHelper.showPopupEnablementToast(this);
|
||||
}
|
||||
return true;
|
||||
case R.id.action_switch_background:
|
||||
this.player.setRecovery();
|
||||
NavigationHelper.playOnBackgroundPlayer(this, player.playQueue, true);
|
||||
NavigationHelper.playOnBackgroundPlayer(this, player.getPlayQueue(), true);
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
@ -191,7 +170,8 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void bind() {
|
||||
final boolean success = bindService(getBindIntent(), serviceConnection, BIND_AUTO_CREATE);
|
||||
final Intent bindIntent = new Intent(this, MainPlayer.class);
|
||||
final boolean success = bindService(bindIntent, serviceConnection, BIND_AUTO_CREATE);
|
||||
if (!success) {
|
||||
unbindService(serviceConnection);
|
||||
}
|
||||
@ -202,7 +182,9 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
|
||||
if (serviceBound) {
|
||||
unbindService(serviceConnection);
|
||||
serviceBound = false;
|
||||
stopPlayerListener();
|
||||
if (player != null) {
|
||||
player.removeActivityListener(this);
|
||||
}
|
||||
|
||||
if (player != null && player.getPlayQueueAdapter() != null) {
|
||||
player.getPlayQueueAdapter().unsetSelectedListener();
|
||||
@ -221,12 +203,12 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
|
||||
return new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceDisconnected(final ComponentName name) {
|
||||
Log.d(getTag(), "Player service is disconnected");
|
||||
Log.d(TAG, "Player service is disconnected");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceConnected(final ComponentName name, final IBinder service) {
|
||||
Log.d(getTag(), "Player service is connected");
|
||||
Log.d(TAG, "Player service is connected");
|
||||
|
||||
if (service instanceof PlayerServiceBinder) {
|
||||
player = ((PlayerServiceBinder) service).getPlayerInstance();
|
||||
@ -235,12 +217,14 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
|
||||
}
|
||||
|
||||
if (player == null || player.getPlayQueue() == null
|
||||
|| player.getPlayQueueAdapter() == null || player.getPlayer() == null) {
|
||||
|| player.getPlayQueueAdapter() == null || player.exoPlayerIsNull()) {
|
||||
unbind();
|
||||
finish();
|
||||
} else {
|
||||
buildComponents();
|
||||
startPlayerListener();
|
||||
if (player != null) {
|
||||
player.setActivityListener(PlayQueueActivity.this);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -375,7 +359,7 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
|
||||
@Override
|
||||
public void selected(final PlayQueueItem item, final View view) {
|
||||
if (player != null) {
|
||||
player.onSelected(item);
|
||||
player.selectQueueItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
@ -436,15 +420,15 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
|
||||
if (view.getId() == queueControlBinding.controlRepeat.getId()) {
|
||||
player.onRepeatClicked();
|
||||
} else if (view.getId() == queueControlBinding.controlBackward.getId()) {
|
||||
player.onPlayPrevious();
|
||||
player.playPrevious();
|
||||
} else if (view.getId() == queueControlBinding.controlFastRewind.getId()) {
|
||||
player.onFastRewind();
|
||||
player.fastRewind();
|
||||
} else if (view.getId() == queueControlBinding.controlPlayPause.getId()) {
|
||||
player.onPlayPause();
|
||||
player.playPause();
|
||||
} else if (view.getId() == queueControlBinding.controlFastForward.getId()) {
|
||||
player.onFastForward();
|
||||
player.fastForward();
|
||||
} else if (view.getId() == queueControlBinding.controlForward.getId()) {
|
||||
player.onPlayNext();
|
||||
player.playNext();
|
||||
} else if (view.getId() == queueControlBinding.controlShuffle.getId()) {
|
||||
player.onShuffleClicked();
|
||||
} else if (view.getId() == queueControlBinding.metadata.getId()) {
|
||||
@ -463,7 +447,7 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
|
||||
return;
|
||||
}
|
||||
PlaybackParameterDialog.newInstance(player.getPlaybackSpeed(), player.getPlaybackPitch(),
|
||||
player.getPlaybackSkipSilence(), this).show(getSupportFragmentManager(), getTag());
|
||||
player.getPlaybackSkipSilence(), this).show(getSupportFragmentManager(), TAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -517,10 +501,8 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
|
||||
final PlaylistAppendDialog d = PlaylistAppendDialog.fromPlayQueueItems(playlist);
|
||||
|
||||
PlaylistAppendDialog.onPlaylistFound(getApplicationContext(),
|
||||
() -> d.show(getSupportFragmentManager(), getTag()),
|
||||
() -> PlaylistCreationDialog.newInstance(d)
|
||||
.show(getSupportFragmentManager(), getTag()
|
||||
));
|
||||
() -> d.show(getSupportFragmentManager(), TAG),
|
||||
() -> PlaylistCreationDialog.newInstance(d).show(getSupportFragmentManager(), TAG));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
@ -616,15 +598,15 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
|
||||
|
||||
private void onStateChanged(final int state) {
|
||||
switch (state) {
|
||||
case BasePlayer.STATE_PAUSED:
|
||||
case Player.STATE_PAUSED:
|
||||
queueControlBinding.controlPlayPause
|
||||
.setImageResource(R.drawable.ic_play_arrow_white_24dp);
|
||||
break;
|
||||
case BasePlayer.STATE_PLAYING:
|
||||
case Player.STATE_PLAYING:
|
||||
queueControlBinding.controlPlayPause
|
||||
.setImageResource(R.drawable.ic_pause_white_24dp);
|
||||
break;
|
||||
case BasePlayer.STATE_COMPLETED:
|
||||
case Player.STATE_COMPLETED:
|
||||
queueControlBinding.controlPlayPause
|
||||
.setImageResource(R.drawable.ic_replay_white_24dp);
|
||||
break;
|
||||
@ -633,9 +615,9 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
case BasePlayer.STATE_PAUSED:
|
||||
case BasePlayer.STATE_PLAYING:
|
||||
case BasePlayer.STATE_COMPLETED:
|
||||
case Player.STATE_PAUSED:
|
||||
case Player.STATE_PLAYING:
|
||||
case Player.STATE_COMPLETED:
|
||||
queueControlBinding.controlPlayPause.setClickable(true);
|
||||
queueControlBinding.controlPlayPause.setVisibility(View.VISIBLE);
|
||||
queueControlBinding.controlProgressBar.setVisibility(View.GONE);
|
||||
@ -650,15 +632,15 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
|
||||
|
||||
private void onPlayModeChanged(final int repeatMode, final boolean shuffled) {
|
||||
switch (repeatMode) {
|
||||
case Player.REPEAT_MODE_OFF:
|
||||
case com.google.android.exoplayer2.Player.REPEAT_MODE_OFF:
|
||||
queueControlBinding.controlRepeat
|
||||
.setImageResource(R.drawable.exo_controls_repeat_off);
|
||||
break;
|
||||
case Player.REPEAT_MODE_ONE:
|
||||
case com.google.android.exoplayer2.Player.REPEAT_MODE_ONE:
|
||||
queueControlBinding.controlRepeat
|
||||
.setImageResource(R.drawable.exo_controls_repeat_one);
|
||||
break;
|
||||
case Player.REPEAT_MODE_ALL:
|
||||
case com.google.android.exoplayer2.Player.REPEAT_MODE_ALL:
|
||||
queueControlBinding.controlRepeat
|
||||
.setImageResource(R.drawable.exo_controls_repeat_all);
|
||||
break;
|
||||
@ -700,9 +682,7 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
|
||||
// using rootView.getContext() because getApplicationContext() didn't work
|
||||
final Context context = queueControlBinding.getRoot().getContext();
|
||||
item.setIcon(ThemeHelper.resolveResourceIdFromAttr(context,
|
||||
player.isMuted()
|
||||
? R.attr.ic_volume_off
|
||||
: R.attr.ic_volume_up));
|
||||
player.isMuted() ? R.attr.ic_volume_off : R.attr.ic_volume_up));
|
||||
}
|
||||
}
|
||||
}
|
3973
app/src/main/java/org/schabi/newpipe/player/Player.java
Normal file
3973
app/src/main/java/org/schabi/newpipe/player/Player.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -5,13 +5,13 @@ import android.os.Binder;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
class PlayerServiceBinder extends Binder {
|
||||
private final BasePlayer basePlayer;
|
||||
private final Player player;
|
||||
|
||||
PlayerServiceBinder(@NonNull final BasePlayer basePlayer) {
|
||||
this.basePlayer = basePlayer;
|
||||
PlayerServiceBinder(@NonNull final Player player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
BasePlayer getPlayerInstance() {
|
||||
return basePlayer;
|
||||
Player getPlayerInstance() {
|
||||
return player;
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -7,10 +7,10 @@ import android.view.GestureDetector
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewConfiguration
|
||||
import org.schabi.newpipe.player.BasePlayer
|
||||
import org.schabi.newpipe.player.MainPlayer
|
||||
import org.schabi.newpipe.player.VideoPlayerImpl
|
||||
import org.schabi.newpipe.player.Player
|
||||
import org.schabi.newpipe.player.helper.PlayerHelper
|
||||
import org.schabi.newpipe.player.helper.PlayerHelper.savePopupPositionAndSizeToPrefs
|
||||
import org.schabi.newpipe.util.AnimationUtils
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.hypot
|
||||
@ -18,14 +18,14 @@ import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
/**
|
||||
* Base gesture handling for [VideoPlayerImpl]
|
||||
* Base gesture handling for [Player]
|
||||
*
|
||||
* This class contains the logic for the player gestures like View preparations
|
||||
* and provides some abstract methods to make it easier separating the logic from the UI.
|
||||
*/
|
||||
abstract class BasePlayerGestureListener(
|
||||
@JvmField
|
||||
protected val playerImpl: VideoPlayerImpl,
|
||||
protected val player: Player,
|
||||
@JvmField
|
||||
protected val service: MainPlayer
|
||||
) : GestureDetector.SimpleOnGestureListener(), View.OnTouchListener {
|
||||
@ -78,7 +78,7 @@ abstract class BasePlayerGestureListener(
|
||||
// ///////////////////////////////////////////////////////////////////
|
||||
|
||||
override fun onTouch(v: View, event: MotionEvent): Boolean {
|
||||
return if (playerImpl.popupPlayerSelected()) {
|
||||
return if (player.popupPlayerSelected()) {
|
||||
onTouchInPopup(v, event)
|
||||
} else {
|
||||
onTouchInMain(v, event)
|
||||
@ -86,14 +86,14 @@ abstract class BasePlayerGestureListener(
|
||||
}
|
||||
|
||||
private fun onTouchInMain(v: View, event: MotionEvent): Boolean {
|
||||
playerImpl.gestureDetector.onTouchEvent(event)
|
||||
player.gestureDetector.onTouchEvent(event)
|
||||
if (event.action == MotionEvent.ACTION_UP && isMovingInMain) {
|
||||
isMovingInMain = false
|
||||
onScrollEnd(MainPlayer.PlayerType.VIDEO, event)
|
||||
}
|
||||
return when (event.action) {
|
||||
MotionEvent.ACTION_DOWN, MotionEvent.ACTION_MOVE -> {
|
||||
v.parent.requestDisallowInterceptTouchEvent(playerImpl.isFullscreen)
|
||||
v.parent.requestDisallowInterceptTouchEvent(player.isFullscreen)
|
||||
true
|
||||
}
|
||||
MotionEvent.ACTION_UP -> {
|
||||
@ -105,7 +105,7 @@ abstract class BasePlayerGestureListener(
|
||||
}
|
||||
|
||||
private fun onTouchInPopup(v: View, event: MotionEvent): Boolean {
|
||||
playerImpl.gestureDetector.onTouchEvent(event)
|
||||
player.gestureDetector.onTouchEvent(event)
|
||||
if (event.pointerCount == 2 && !isMovingInPopup && !isResizing) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "onTouch() 2 finger pointer detected, enabling resizing.")
|
||||
@ -157,10 +157,10 @@ abstract class BasePlayerGestureListener(
|
||||
initSecPointerY = (-1).toFloat()
|
||||
|
||||
onPopupResizingEnd()
|
||||
playerImpl.changeState(playerImpl.currentState)
|
||||
player.changeState(player.currentState)
|
||||
}
|
||||
if (!playerImpl.isPopupClosing) {
|
||||
playerImpl.savePositionAndSize()
|
||||
if (!player.isPopupClosing) {
|
||||
savePopupPositionAndSizeToPrefs(player)
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,19 +190,15 @@ abstract class BasePlayerGestureListener(
|
||||
event.getY(0) - event.getY(1).toDouble()
|
||||
)
|
||||
|
||||
val popupWidth = playerImpl.popupWidth.toDouble()
|
||||
val popupWidth = player.popupLayoutParams!!.width.toDouble()
|
||||
// change co-ordinates of popup so the center stays at the same position
|
||||
val newWidth = popupWidth * currentPointerDistance / initPointerDistance
|
||||
initPointerDistance = currentPointerDistance
|
||||
playerImpl.popupLayoutParams.x += ((popupWidth - newWidth) / 2.0).toInt()
|
||||
player.popupLayoutParams!!.x += ((popupWidth - newWidth) / 2.0).toInt()
|
||||
|
||||
playerImpl.checkPopupPositionBounds()
|
||||
playerImpl.updateScreenSize()
|
||||
|
||||
playerImpl.updatePopupSize(
|
||||
min(playerImpl.screenWidth.toDouble(), newWidth).toInt(),
|
||||
-1
|
||||
)
|
||||
player.checkPopupPositionBounds()
|
||||
player.updateScreenSize()
|
||||
player.changePopupSize(min(player.screenWidth.toDouble(), newWidth).toInt())
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -222,7 +218,7 @@ abstract class BasePlayerGestureListener(
|
||||
return true
|
||||
}
|
||||
|
||||
return if (playerImpl.popupPlayerSelected())
|
||||
return if (player.popupPlayerSelected())
|
||||
onDownInPopup(e)
|
||||
else
|
||||
true
|
||||
@ -231,12 +227,10 @@ abstract class BasePlayerGestureListener(
|
||||
private fun onDownInPopup(e: MotionEvent): Boolean {
|
||||
// Fix popup position when the user touch it, it may have the wrong one
|
||||
// because the soft input is visible (the draggable area is currently resized).
|
||||
playerImpl.updateScreenSize()
|
||||
playerImpl.checkPopupPositionBounds()
|
||||
initialPopupX = playerImpl.popupLayoutParams.x
|
||||
initialPopupY = playerImpl.popupLayoutParams.y
|
||||
playerImpl.popupWidth = playerImpl.popupLayoutParams.width.toFloat()
|
||||
playerImpl.popupHeight = playerImpl.popupLayoutParams.height.toFloat()
|
||||
player.updateScreenSize()
|
||||
player.checkPopupPositionBounds()
|
||||
initialPopupX = player.popupLayoutParams!!.x
|
||||
initialPopupY = player.popupLayoutParams!!.y
|
||||
return super.onDown(e)
|
||||
}
|
||||
|
||||
@ -255,15 +249,15 @@ abstract class BasePlayerGestureListener(
|
||||
if (isDoubleTapping)
|
||||
return true
|
||||
|
||||
if (playerImpl.popupPlayerSelected()) {
|
||||
if (playerImpl.player == null)
|
||||
if (player.popupPlayerSelected()) {
|
||||
if (player.exoPlayerIsNull())
|
||||
return false
|
||||
|
||||
onSingleTap(MainPlayer.PlayerType.POPUP)
|
||||
return true
|
||||
} else {
|
||||
super.onSingleTapConfirmed(e)
|
||||
if (playerImpl.currentState == BasePlayer.STATE_BLOCKED)
|
||||
if (player.currentState == Player.STATE_BLOCKED)
|
||||
return true
|
||||
|
||||
onSingleTap(MainPlayer.PlayerType.VIDEO)
|
||||
@ -272,10 +266,10 @@ abstract class BasePlayerGestureListener(
|
||||
}
|
||||
|
||||
override fun onLongPress(e: MotionEvent?) {
|
||||
if (playerImpl.popupPlayerSelected()) {
|
||||
playerImpl.updateScreenSize()
|
||||
playerImpl.checkPopupPositionBounds()
|
||||
playerImpl.updatePopupSize(playerImpl.screenWidth.toInt(), -1)
|
||||
if (player.popupPlayerSelected()) {
|
||||
player.updateScreenSize()
|
||||
player.checkPopupPositionBounds()
|
||||
player.changePopupSize(player.screenWidth.toInt())
|
||||
}
|
||||
}
|
||||
|
||||
@ -285,7 +279,7 @@ abstract class BasePlayerGestureListener(
|
||||
distanceX: Float,
|
||||
distanceY: Float
|
||||
): Boolean {
|
||||
return if (playerImpl.popupPlayerSelected()) {
|
||||
return if (player.popupPlayerSelected()) {
|
||||
onScrollInPopup(initialEvent, movingEvent, distanceX, distanceY)
|
||||
} else {
|
||||
onScrollInMain(initialEvent, movingEvent, distanceX, distanceY)
|
||||
@ -298,19 +292,18 @@ abstract class BasePlayerGestureListener(
|
||||
velocityX: Float,
|
||||
velocityY: Float
|
||||
): Boolean {
|
||||
return if (playerImpl.popupPlayerSelected()) {
|
||||
return if (player.popupPlayerSelected()) {
|
||||
val absVelocityX = abs(velocityX)
|
||||
val absVelocityY = abs(velocityY)
|
||||
if (absVelocityX.coerceAtLeast(absVelocityY) > tossFlingVelocity) {
|
||||
if (absVelocityX > tossFlingVelocity) {
|
||||
playerImpl.popupLayoutParams.x = velocityX.toInt()
|
||||
player.popupLayoutParams!!.x = velocityX.toInt()
|
||||
}
|
||||
if (absVelocityY > tossFlingVelocity) {
|
||||
playerImpl.popupLayoutParams.y = velocityY.toInt()
|
||||
player.popupLayoutParams!!.y = velocityY.toInt()
|
||||
}
|
||||
playerImpl.checkPopupPositionBounds()
|
||||
playerImpl.windowManager
|
||||
.updateViewLayout(playerImpl.rootView, playerImpl.popupLayoutParams)
|
||||
player.checkPopupPositionBounds()
|
||||
player.windowManager!!.updateViewLayout(player.rootView, player.popupLayoutParams)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@ -326,13 +319,13 @@ abstract class BasePlayerGestureListener(
|
||||
distanceY: Float
|
||||
): Boolean {
|
||||
|
||||
if (!playerImpl.isFullscreen) {
|
||||
if (!player.isFullscreen) {
|
||||
return false
|
||||
}
|
||||
|
||||
val isTouchingStatusBar: Boolean = initialEvent.y < getStatusBarHeight(service)
|
||||
val isTouchingNavigationBar: Boolean =
|
||||
initialEvent.y > (playerImpl.rootView.height - getNavigationBarHeight(service))
|
||||
initialEvent.y > (player.rootView.height - getNavigationBarHeight(service))
|
||||
if (isTouchingStatusBar || isTouchingNavigationBar) {
|
||||
return false
|
||||
}
|
||||
@ -340,7 +333,7 @@ abstract class BasePlayerGestureListener(
|
||||
val insideThreshold = abs(movingEvent.y - initialEvent.y) <= MOVEMENT_THRESHOLD
|
||||
if (
|
||||
!isMovingInMain && (insideThreshold || abs(distanceX) > abs(distanceY)) ||
|
||||
playerImpl.currentState == BasePlayer.STATE_COMPLETED
|
||||
player.currentState == Player.STATE_COMPLETED
|
||||
) {
|
||||
return false
|
||||
}
|
||||
@ -371,7 +364,7 @@ abstract class BasePlayerGestureListener(
|
||||
}
|
||||
|
||||
if (!isMovingInPopup) {
|
||||
AnimationUtils.animateView(playerImpl.closeButton, true, 200)
|
||||
AnimationUtils.animateView(player.closeOverlayButton, true, 200)
|
||||
}
|
||||
|
||||
isMovingInPopup = true
|
||||
@ -381,20 +374,20 @@ abstract class BasePlayerGestureListener(
|
||||
val diffY: Float = (movingEvent.rawY - initialEvent.rawY)
|
||||
var posY: Float = (initialPopupY + diffY)
|
||||
|
||||
if (posX > playerImpl.screenWidth - playerImpl.popupWidth) {
|
||||
posX = (playerImpl.screenWidth - playerImpl.popupWidth)
|
||||
if (posX > player.screenWidth - player.popupLayoutParams!!.width) {
|
||||
posX = (player.screenWidth - player.popupLayoutParams!!.width)
|
||||
} else if (posX < 0) {
|
||||
posX = 0f
|
||||
}
|
||||
|
||||
if (posY > playerImpl.screenHeight - playerImpl.popupHeight) {
|
||||
posY = (playerImpl.screenHeight - playerImpl.popupHeight)
|
||||
if (posY > player.screenHeight - player.popupLayoutParams!!.height) {
|
||||
posY = (player.screenHeight - player.popupLayoutParams!!.height)
|
||||
} else if (posY < 0) {
|
||||
posY = 0f
|
||||
}
|
||||
|
||||
playerImpl.popupLayoutParams.x = posX.toInt()
|
||||
playerImpl.popupLayoutParams.y = posY.toInt()
|
||||
player.popupLayoutParams!!.x = posX.toInt()
|
||||
player.popupLayoutParams!!.y = posY.toInt()
|
||||
|
||||
onScroll(
|
||||
MainPlayer.PlayerType.POPUP,
|
||||
@ -405,8 +398,7 @@ abstract class BasePlayerGestureListener(
|
||||
distanceY
|
||||
)
|
||||
|
||||
playerImpl.windowManager
|
||||
.updateViewLayout(playerImpl.rootView, playerImpl.popupLayoutParams)
|
||||
player.windowManager!!.updateViewLayout(player.rootView, player.popupLayoutParams)
|
||||
return true
|
||||
}
|
||||
|
||||
@ -474,16 +466,16 @@ abstract class BasePlayerGestureListener(
|
||||
// ///////////////////////////////////////////////////////////////////
|
||||
|
||||
private fun getDisplayPortion(e: MotionEvent): DisplayPortion {
|
||||
return if (playerImpl.playerType == MainPlayer.PlayerType.POPUP) {
|
||||
return if (player.playerType == MainPlayer.PlayerType.POPUP) {
|
||||
when {
|
||||
e.x < playerImpl.popupWidth / 3.0 -> DisplayPortion.LEFT
|
||||
e.x > playerImpl.popupWidth * 2.0 / 3.0 -> DisplayPortion.RIGHT
|
||||
e.x < player.popupLayoutParams!!.width / 3.0 -> DisplayPortion.LEFT
|
||||
e.x > player.popupLayoutParams!!.width * 2.0 / 3.0 -> DisplayPortion.RIGHT
|
||||
else -> DisplayPortion.MIDDLE
|
||||
}
|
||||
} else /* MainPlayer.PlayerType.VIDEO */ {
|
||||
when {
|
||||
e.x < playerImpl.rootView.width / 3.0 -> DisplayPortion.LEFT
|
||||
e.x > playerImpl.rootView.width * 2.0 / 3.0 -> DisplayPortion.RIGHT
|
||||
e.x < player.rootView.width / 3.0 -> DisplayPortion.LEFT
|
||||
e.x > player.rootView.width * 2.0 / 3.0 -> DisplayPortion.RIGHT
|
||||
else -> DisplayPortion.MIDDLE
|
||||
}
|
||||
}
|
||||
@ -491,14 +483,14 @@ abstract class BasePlayerGestureListener(
|
||||
|
||||
// Currently needed for scrolling since there is no action more the middle portion
|
||||
private fun getDisplayHalfPortion(e: MotionEvent): DisplayPortion {
|
||||
return if (playerImpl.playerType == MainPlayer.PlayerType.POPUP) {
|
||||
return if (player.playerType == MainPlayer.PlayerType.POPUP) {
|
||||
when {
|
||||
e.x < playerImpl.popupWidth / 2.0 -> DisplayPortion.LEFT_HALF
|
||||
e.x < player.popupLayoutParams!!.width / 2.0 -> DisplayPortion.LEFT_HALF
|
||||
else -> DisplayPortion.RIGHT_HALF
|
||||
}
|
||||
} else /* MainPlayer.PlayerType.VIDEO */ {
|
||||
when {
|
||||
e.x < playerImpl.rootView.width / 2.0 -> DisplayPortion.LEFT_HALF
|
||||
e.x < player.rootView.width / 2.0 -> DisplayPortion.LEFT_HALF
|
||||
else -> DisplayPortion.RIGHT_HALF
|
||||
}
|
||||
}
|
||||
@ -522,7 +514,7 @@ abstract class BasePlayerGestureListener(
|
||||
|
||||
companion object {
|
||||
private const val TAG = "BasePlayerGestListener"
|
||||
private val DEBUG = BasePlayer.DEBUG
|
||||
private val DEBUG = Player.DEBUG
|
||||
|
||||
private const val DOUBLE_TAP_DELAY = 550L
|
||||
private const val MOVEMENT_THRESHOLD = 40
|
||||
|
@ -11,15 +11,15 @@ import android.widget.ProgressBar;
|
||||
import androidx.appcompat.content.res.AppCompatResources;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.schabi.newpipe.MainActivity;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.player.BasePlayer;
|
||||
import org.schabi.newpipe.player.MainPlayer;
|
||||
import org.schabi.newpipe.player.VideoPlayerImpl;
|
||||
import org.schabi.newpipe.player.Player;
|
||||
import org.schabi.newpipe.player.helper.PlayerHelper;
|
||||
|
||||
import static org.schabi.newpipe.player.BasePlayer.STATE_PLAYING;
|
||||
import static org.schabi.newpipe.player.VideoPlayer.DEFAULT_CONTROLS_DURATION;
|
||||
import static org.schabi.newpipe.player.VideoPlayer.DEFAULT_CONTROLS_HIDE_TIME;
|
||||
import static org.schabi.newpipe.player.Player.STATE_PLAYING;
|
||||
import static org.schabi.newpipe.player.Player.DEFAULT_CONTROLS_DURATION;
|
||||
import static org.schabi.newpipe.player.Player.DEFAULT_CONTROLS_HIDE_TIME;
|
||||
import static org.schabi.newpipe.util.AnimationUtils.Type.SCALE_AND_ALPHA;
|
||||
import static org.schabi.newpipe.util.AnimationUtils.animateView;
|
||||
|
||||
@ -33,14 +33,14 @@ import static org.schabi.newpipe.util.AnimationUtils.animateView;
|
||||
public class PlayerGestureListener
|
||||
extends BasePlayerGestureListener
|
||||
implements View.OnTouchListener {
|
||||
private static final String TAG = ".PlayerGestureListener";
|
||||
private static final boolean DEBUG = BasePlayer.DEBUG;
|
||||
private static final String TAG = PlayerGestureListener.class.getSimpleName();
|
||||
private static final boolean DEBUG = MainActivity.DEBUG;
|
||||
|
||||
private final int maxVolume;
|
||||
|
||||
public PlayerGestureListener(final VideoPlayerImpl playerImpl, final MainPlayer service) {
|
||||
super(playerImpl, service);
|
||||
maxVolume = playerImpl.getAudioReactor().getMaxVolume();
|
||||
public PlayerGestureListener(final Player player, final MainPlayer service) {
|
||||
super(player, service);
|
||||
maxVolume = player.getAudioReactor().getMaxVolume();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -48,46 +48,44 @@ public class PlayerGestureListener
|
||||
@NotNull final DisplayPortion portion) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "onDoubleTap called with playerType = ["
|
||||
+ playerImpl.getPlayerType() + "], portion = ["
|
||||
+ portion + "]");
|
||||
+ player.getPlayerType() + "], portion = [" + portion + "]");
|
||||
}
|
||||
if (playerImpl.isSomePopupMenuVisible()) {
|
||||
playerImpl.hideControls(0, 0);
|
||||
if (player.isSomePopupMenuVisible()) {
|
||||
player.hideControls(0, 0);
|
||||
}
|
||||
|
||||
if (portion == DisplayPortion.LEFT) {
|
||||
playerImpl.onFastRewind();
|
||||
player.fastRewind();
|
||||
} else if (portion == DisplayPortion.MIDDLE) {
|
||||
playerImpl.onPlayPause();
|
||||
player.playPause();
|
||||
} else if (portion == DisplayPortion.RIGHT) {
|
||||
playerImpl.onFastForward();
|
||||
player.fastForward();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSingleTap(@NotNull final MainPlayer.PlayerType playerType) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "onSingleTap called with playerType = ["
|
||||
+ playerImpl.getPlayerType() + "]");
|
||||
Log.d(TAG, "onSingleTap called with playerType = [" + player.getPlayerType() + "]");
|
||||
}
|
||||
if (playerType == MainPlayer.PlayerType.POPUP) {
|
||||
|
||||
if (playerImpl.isControlsVisible()) {
|
||||
playerImpl.hideControls(100, 100);
|
||||
if (player.isControlsVisible()) {
|
||||
player.hideControls(100, 100);
|
||||
} else {
|
||||
playerImpl.getPlayPauseButton().requestFocus();
|
||||
playerImpl.showControlsThenHide();
|
||||
player.getPlayPauseButton().requestFocus();
|
||||
player.showControlsThenHide();
|
||||
}
|
||||
|
||||
} else /* playerType == MainPlayer.PlayerType.VIDEO */ {
|
||||
|
||||
if (playerImpl.isControlsVisible()) {
|
||||
playerImpl.hideControls(150, 0);
|
||||
if (player.isControlsVisible()) {
|
||||
player.hideControls(150, 0);
|
||||
} else {
|
||||
if (playerImpl.getCurrentState() == BasePlayer.STATE_COMPLETED) {
|
||||
playerImpl.showControls(0);
|
||||
if (player.getCurrentState() == Player.STATE_COMPLETED) {
|
||||
player.showControls(0);
|
||||
} else {
|
||||
playerImpl.showControlsThenHide();
|
||||
player.showControlsThenHide();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -101,8 +99,7 @@ public class PlayerGestureListener
|
||||
final float distanceX, final float distanceY) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "onScroll called with playerType = ["
|
||||
+ playerImpl.getPlayerType() + "], portion = ["
|
||||
+ portion + "]");
|
||||
+ player.getPlayerType() + "], portion = [" + portion + "]");
|
||||
}
|
||||
if (playerType == MainPlayer.PlayerType.VIDEO) {
|
||||
final boolean isBrightnessGestureEnabled =
|
||||
@ -123,8 +120,8 @@ public class PlayerGestureListener
|
||||
}
|
||||
|
||||
} else /* MainPlayer.PlayerType.POPUP */ {
|
||||
final View closingOverlayView = playerImpl.getClosingOverlay();
|
||||
if (playerImpl.isInsideClosingRadius(movingEvent)) {
|
||||
final View closingOverlayView = player.getClosingOverlayView();
|
||||
if (player.isInsideClosingRadius(movingEvent)) {
|
||||
if (closingOverlayView.getVisibility() == View.GONE) {
|
||||
animateView(closingOverlayView, true, 250);
|
||||
}
|
||||
@ -137,17 +134,17 @@ public class PlayerGestureListener
|
||||
}
|
||||
|
||||
private void onScrollMainVolume(final float distanceX, final float distanceY) {
|
||||
playerImpl.getVolumeProgressBar().incrementProgressBy((int) distanceY);
|
||||
final float currentProgressPercent = (float) playerImpl
|
||||
.getVolumeProgressBar().getProgress() / playerImpl.getMaxGestureLength();
|
||||
player.getVolumeProgressBar().incrementProgressBy((int) distanceY);
|
||||
final float currentProgressPercent = (float) player
|
||||
.getVolumeProgressBar().getProgress() / player.getMaxGestureLength();
|
||||
final int currentVolume = (int) (maxVolume * currentProgressPercent);
|
||||
playerImpl.getAudioReactor().setVolume(currentVolume);
|
||||
player.getAudioReactor().setVolume(currentVolume);
|
||||
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "onScroll().volumeControl, currentVolume = " + currentVolume);
|
||||
}
|
||||
|
||||
playerImpl.getVolumeImageView().setImageDrawable(
|
||||
player.getVolumeImageView().setImageDrawable(
|
||||
AppCompatResources.getDrawable(service, currentProgressPercent <= 0
|
||||
? R.drawable.ic_volume_off_white_24dp
|
||||
: currentProgressPercent < 0.25 ? R.drawable.ic_volume_mute_white_24dp
|
||||
@ -155,23 +152,23 @@ public class PlayerGestureListener
|
||||
: R.drawable.ic_volume_up_white_24dp)
|
||||
);
|
||||
|
||||
if (playerImpl.getVolumeRelativeLayout().getVisibility() != View.VISIBLE) {
|
||||
animateView(playerImpl.getVolumeRelativeLayout(), SCALE_AND_ALPHA, true, 200);
|
||||
if (player.getVolumeRelativeLayout().getVisibility() != View.VISIBLE) {
|
||||
animateView(player.getVolumeRelativeLayout(), SCALE_AND_ALPHA, true, 200);
|
||||
}
|
||||
if (playerImpl.getBrightnessRelativeLayout().getVisibility() == View.VISIBLE) {
|
||||
playerImpl.getBrightnessRelativeLayout().setVisibility(View.GONE);
|
||||
if (player.getBrightnessRelativeLayout().getVisibility() == View.VISIBLE) {
|
||||
player.getBrightnessRelativeLayout().setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void onScrollMainBrightness(final float distanceX, final float distanceY) {
|
||||
final Activity parent = playerImpl.getParentActivity();
|
||||
final Activity parent = player.getParentActivity();
|
||||
if (parent == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Window window = parent.getWindow();
|
||||
final WindowManager.LayoutParams layoutParams = window.getAttributes();
|
||||
final ProgressBar bar = playerImpl.getBrightnessProgressBar();
|
||||
final ProgressBar bar = player.getBrightnessProgressBar();
|
||||
final float oldBrightness = layoutParams.screenBrightness;
|
||||
bar.setProgress((int) (bar.getMax() * Math.max(0, Math.min(1, oldBrightness))));
|
||||
bar.incrementProgressBy((int) distanceY);
|
||||
@ -188,7 +185,7 @@ public class PlayerGestureListener
|
||||
+ "currentBrightness = " + currentProgressPercent);
|
||||
}
|
||||
|
||||
playerImpl.getBrightnessImageView().setImageDrawable(
|
||||
player.getBrightnessImageView().setImageDrawable(
|
||||
AppCompatResources.getDrawable(service,
|
||||
currentProgressPercent < 0.25
|
||||
? R.drawable.ic_brightness_low_white_24dp
|
||||
@ -197,11 +194,11 @@ public class PlayerGestureListener
|
||||
: R.drawable.ic_brightness_high_white_24dp)
|
||||
);
|
||||
|
||||
if (playerImpl.getBrightnessRelativeLayout().getVisibility() != View.VISIBLE) {
|
||||
animateView(playerImpl.getBrightnessRelativeLayout(), SCALE_AND_ALPHA, true, 200);
|
||||
if (player.getBrightnessRelativeLayout().getVisibility() != View.VISIBLE) {
|
||||
animateView(player.getBrightnessRelativeLayout(), SCALE_AND_ALPHA, true, 200);
|
||||
}
|
||||
if (playerImpl.getVolumeRelativeLayout().getVisibility() == View.VISIBLE) {
|
||||
playerImpl.getVolumeRelativeLayout().setVisibility(View.GONE);
|
||||
if (player.getVolumeRelativeLayout().getVisibility() == View.VISIBLE) {
|
||||
player.getVolumeRelativeLayout().setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -210,40 +207,40 @@ public class PlayerGestureListener
|
||||
@NotNull final MotionEvent event) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "onScrollEnd called with playerType = ["
|
||||
+ playerImpl.getPlayerType() + "]");
|
||||
+ player.getPlayerType() + "]");
|
||||
}
|
||||
if (playerType == MainPlayer.PlayerType.VIDEO) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "onScrollEnd() called");
|
||||
}
|
||||
|
||||
if (playerImpl.getVolumeRelativeLayout().getVisibility() == View.VISIBLE) {
|
||||
animateView(playerImpl.getVolumeRelativeLayout(), SCALE_AND_ALPHA,
|
||||
if (player.getVolumeRelativeLayout().getVisibility() == View.VISIBLE) {
|
||||
animateView(player.getVolumeRelativeLayout(), SCALE_AND_ALPHA,
|
||||
false, 200, 200);
|
||||
}
|
||||
if (playerImpl.getBrightnessRelativeLayout().getVisibility() == View.VISIBLE) {
|
||||
animateView(playerImpl.getBrightnessRelativeLayout(), SCALE_AND_ALPHA,
|
||||
if (player.getBrightnessRelativeLayout().getVisibility() == View.VISIBLE) {
|
||||
animateView(player.getBrightnessRelativeLayout(), SCALE_AND_ALPHA,
|
||||
false, 200, 200);
|
||||
}
|
||||
|
||||
if (playerImpl.isControlsVisible() && playerImpl.getCurrentState() == STATE_PLAYING) {
|
||||
playerImpl.hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME);
|
||||
if (player.isControlsVisible() && player.getCurrentState() == STATE_PLAYING) {
|
||||
player.hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME);
|
||||
}
|
||||
} else {
|
||||
if (playerImpl == null) {
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
if (playerImpl.isControlsVisible() && playerImpl.getCurrentState() == STATE_PLAYING) {
|
||||
playerImpl.hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME);
|
||||
if (player.isControlsVisible() && player.getCurrentState() == STATE_PLAYING) {
|
||||
player.hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME);
|
||||
}
|
||||
|
||||
if (playerImpl.isInsideClosingRadius(event)) {
|
||||
playerImpl.closePopup();
|
||||
if (player.isInsideClosingRadius(event)) {
|
||||
player.closePopup();
|
||||
} else {
|
||||
animateView(playerImpl.getClosingOverlay(), false, 0);
|
||||
animateView(player.getClosingOverlayView(), false, 0);
|
||||
|
||||
if (!playerImpl.isPopupClosing) {
|
||||
animateView(playerImpl.getCloseButton(), false, 200);
|
||||
if (!player.isPopupClosing()) {
|
||||
animateView(player.getCloseOverlayButton(), false, 200);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -254,12 +251,12 @@ public class PlayerGestureListener
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "onPopupResizingStart called");
|
||||
}
|
||||
playerImpl.showAndAnimateControl(-1, true);
|
||||
playerImpl.getLoadingPanel().setVisibility(View.GONE);
|
||||
player.showAndAnimateControl(-1, true);
|
||||
player.getLoadingPanel().setVisibility(View.GONE);
|
||||
|
||||
playerImpl.hideControls(0, 0);
|
||||
animateView(playerImpl.getCurrentDisplaySeek(), false, 0, 0);
|
||||
animateView(playerImpl.getResizingIndicator(), true, 200, 0);
|
||||
player.hideControls(0, 0);
|
||||
animateView(player.getCurrentDisplaySeek(), false, 0, 0);
|
||||
animateView(player.getResizingIndicator(), true, 200, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -267,7 +264,7 @@ public class PlayerGestureListener
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "onPopupResizingEnd called");
|
||||
}
|
||||
animateView(playerImpl.getResizingIndicator(), false, 100, 0);
|
||||
animateView(player.getResizingIndicator(), false, 100, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
package org.schabi.newpipe.player.event;
|
||||
|
||||
import org.schabi.newpipe.player.MainPlayer;
|
||||
import org.schabi.newpipe.player.VideoPlayerImpl;
|
||||
import org.schabi.newpipe.player.Player;
|
||||
|
||||
public interface PlayerServiceExtendedEventListener extends PlayerServiceEventListener {
|
||||
void onServiceConnected(VideoPlayerImpl player,
|
||||
void onServiceConnected(Player player,
|
||||
MainPlayer playerService,
|
||||
boolean playAfterConnect);
|
||||
void onServiceDisconnected();
|
||||
|
@ -18,7 +18,7 @@ import androidx.fragment.app.DialogFragment;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.util.SliderStrategy;
|
||||
|
||||
import static org.schabi.newpipe.player.BasePlayer.DEBUG;
|
||||
import static org.schabi.newpipe.player.Player.DEBUG;
|
||||
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
||||
|
||||
public class PlaybackParameterDialog extends DialogFragment {
|
||||
|
@ -1,8 +1,15 @@
|
||||
package org.schabi.newpipe.player.helper;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.os.Build;
|
||||
import android.provider.Settings;
|
||||
import android.view.Gravity;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.view.accessibility.CaptioningManager;
|
||||
|
||||
import androidx.annotation.IntDef;
|
||||
@ -11,11 +18,14 @@ import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import com.google.android.exoplayer2.PlaybackParameters;
|
||||
import com.google.android.exoplayer2.Player.RepeatMode;
|
||||
import com.google.android.exoplayer2.SeekParameters;
|
||||
import com.google.android.exoplayer2.text.CaptionStyleCompat;
|
||||
import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection;
|
||||
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
||||
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
|
||||
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout.ResizeMode;
|
||||
import com.google.android.exoplayer2.util.MimeTypes;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
@ -27,6 +37,8 @@ import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||
import org.schabi.newpipe.extractor.stream.SubtitlesStream;
|
||||
import org.schabi.newpipe.extractor.stream.VideoStream;
|
||||
import org.schabi.newpipe.extractor.utils.Utils;
|
||||
import org.schabi.newpipe.player.MainPlayer;
|
||||
import org.schabi.newpipe.player.Player;
|
||||
import org.schabi.newpipe.player.playqueue.PlayQueue;
|
||||
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
|
||||
import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
|
||||
@ -41,13 +53,16 @@ import java.util.Formatter;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static com.google.android.exoplayer2.ui.AspectRatioFrameLayout.RESIZE_MODE_FILL;
|
||||
import static com.google.android.exoplayer2.ui.AspectRatioFrameLayout.RESIZE_MODE_FIT;
|
||||
import static com.google.android.exoplayer2.ui.AspectRatioFrameLayout.RESIZE_MODE_ZOOM;
|
||||
import static com.google.android.exoplayer2.Player.REPEAT_MODE_ALL;
|
||||
import static com.google.android.exoplayer2.Player.REPEAT_MODE_OFF;
|
||||
import static com.google.android.exoplayer2.Player.REPEAT_MODE_ONE;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
import static org.schabi.newpipe.player.Player.IDLE_WINDOW_FLAGS;
|
||||
import static org.schabi.newpipe.player.Player.PLAYER_TYPE;
|
||||
import static org.schabi.newpipe.player.helper.PlayerHelper.AutoplayType.AUTOPLAY_TYPE_ALWAYS;
|
||||
import static org.schabi.newpipe.player.helper.PlayerHelper.AutoplayType.AUTOPLAY_TYPE_NEVER;
|
||||
import static org.schabi.newpipe.player.helper.PlayerHelper.AutoplayType.AUTOPLAY_TYPE_WIFI;
|
||||
@ -71,6 +86,15 @@ public final class PlayerHelper {
|
||||
int AUTOPLAY_TYPE_NEVER = 2;
|
||||
}
|
||||
|
||||
@Retention(SOURCE)
|
||||
@IntDef({MINIMIZE_ON_EXIT_MODE_NONE, MINIMIZE_ON_EXIT_MODE_BACKGROUND,
|
||||
MINIMIZE_ON_EXIT_MODE_POPUP})
|
||||
public @interface MinimizeMode {
|
||||
int MINIMIZE_ON_EXIT_MODE_NONE = 0;
|
||||
int MINIMIZE_ON_EXIT_MODE_BACKGROUND = 1;
|
||||
int MINIMIZE_ON_EXIT_MODE_POPUP = 2;
|
||||
}
|
||||
|
||||
private PlayerHelper() { }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
@ -121,14 +145,16 @@ public final class PlayerHelper {
|
||||
|
||||
@NonNull
|
||||
public static String resizeTypeOf(@NonNull final Context context,
|
||||
@AspectRatioFrameLayout.ResizeMode final int resizeMode) {
|
||||
@ResizeMode final int resizeMode) {
|
||||
switch (resizeMode) {
|
||||
case RESIZE_MODE_FIT:
|
||||
case AspectRatioFrameLayout.RESIZE_MODE_FIT:
|
||||
return context.getResources().getString(R.string.resize_fit);
|
||||
case RESIZE_MODE_FILL:
|
||||
case AspectRatioFrameLayout.RESIZE_MODE_FILL:
|
||||
return context.getResources().getString(R.string.resize_fill);
|
||||
case RESIZE_MODE_ZOOM:
|
||||
case AspectRatioFrameLayout.RESIZE_MODE_ZOOM:
|
||||
return context.getResources().getString(R.string.resize_zoom);
|
||||
case AspectRatioFrameLayout.RESIZE_MODE_FIXED_HEIGHT:
|
||||
case AspectRatioFrameLayout.RESIZE_MODE_FIXED_WIDTH:
|
||||
default:
|
||||
throw new IllegalArgumentException("Unrecognized resize mode: " + resizeMode);
|
||||
}
|
||||
@ -199,23 +225,23 @@ public final class PlayerHelper {
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public static boolean isResumeAfterAudioFocusGain(@NonNull final Context context) {
|
||||
return isResumeAfterAudioFocusGain(context, false);
|
||||
return getPreferences(context)
|
||||
.getBoolean(context.getString(R.string.resume_on_audio_focus_gain_key), false);
|
||||
}
|
||||
|
||||
public static boolean isVolumeGestureEnabled(@NonNull final Context context) {
|
||||
return isVolumeGestureEnabled(context, true);
|
||||
return getPreferences(context)
|
||||
.getBoolean(context.getString(R.string.volume_gesture_control_key), true);
|
||||
}
|
||||
|
||||
public static boolean isBrightnessGestureEnabled(@NonNull final Context context) {
|
||||
return isBrightnessGestureEnabled(context, true);
|
||||
}
|
||||
|
||||
public static boolean isRememberingPopupDimensions(@NonNull final Context context) {
|
||||
return isRememberingPopupDimensions(context, true);
|
||||
return getPreferences(context)
|
||||
.getBoolean(context.getString(R.string.brightness_gesture_control_key), true);
|
||||
}
|
||||
|
||||
public static boolean isAutoQueueEnabled(@NonNull final Context context) {
|
||||
return isAutoQueueEnabled(context, false);
|
||||
return getPreferences(context)
|
||||
.getBoolean(context.getString(R.string.auto_queue_key), false);
|
||||
}
|
||||
|
||||
public static boolean isClearingQueueConfirmationRequired(@NonNull final Context context) {
|
||||
@ -229,7 +255,8 @@ public final class PlayerHelper {
|
||||
final String popupAction = context.getString(R.string.minimize_on_exit_popup_key);
|
||||
final String backgroundAction = context.getString(R.string.minimize_on_exit_background_key);
|
||||
|
||||
final String action = getMinimizeOnExitAction(context, defaultAction);
|
||||
final String action = getPreferences(context)
|
||||
.getString(context.getString(R.string.minimize_on_exit_key), defaultAction);
|
||||
if (action.equals(popupAction)) {
|
||||
return MINIMIZE_ON_EXIT_MODE_POPUP;
|
||||
} else if (action.equals(backgroundAction)) {
|
||||
@ -239,9 +266,23 @@ public final class PlayerHelper {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isMinimizeOnExitToPopup(@NonNull final Context context) {
|
||||
return getMinimizeOnExitAction(context) == MINIMIZE_ON_EXIT_MODE_POPUP;
|
||||
}
|
||||
|
||||
public static boolean isMinimizeOnExitToBackground(@NonNull final Context context) {
|
||||
return getMinimizeOnExitAction(context) == MINIMIZE_ON_EXIT_MODE_BACKGROUND;
|
||||
}
|
||||
|
||||
public static boolean isMinimizeOnExitDisabled(@NonNull final Context context) {
|
||||
return getMinimizeOnExitAction(context) == MINIMIZE_ON_EXIT_MODE_NONE;
|
||||
}
|
||||
|
||||
@AutoplayType
|
||||
public static int getAutoplayType(@NonNull final Context context) {
|
||||
final String type = getAutoplayType(context, context.getString(R.string.autoplay_wifi_key));
|
||||
final String type = getPreferences(context).getString(
|
||||
context.getString(R.string.autoplay_key),
|
||||
context.getString(R.string.autoplay_wifi_key));
|
||||
if (type.equals(context.getString(R.string.autoplay_always_key))) {
|
||||
return AUTOPLAY_TYPE_ALWAYS;
|
||||
} else if (type.equals(context.getString(R.string.autoplay_never_key))) {
|
||||
@ -350,14 +391,32 @@ public final class PlayerHelper {
|
||||
return captioningManager.getFontScale();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context the Android context
|
||||
* @return the screen brightness to use. A value less than 0 (the default) means to use the
|
||||
* preferred screen brightness
|
||||
*/
|
||||
public static float getScreenBrightness(@NonNull final Context context) {
|
||||
//a value of less than 0, the default, means to use the preferred screen brightness
|
||||
return getScreenBrightness(context, -1);
|
||||
final SharedPreferences sp = getPreferences(context);
|
||||
final long timestamp =
|
||||
sp.getLong(context.getString(R.string.screen_brightness_timestamp_key), 0);
|
||||
// Hypothesis: 4h covers a viewing block, e.g. evening.
|
||||
// External lightning conditions will change in the next
|
||||
// viewing block so we fall back to the default brightness
|
||||
if ((System.currentTimeMillis() - timestamp) > TimeUnit.HOURS.toMillis(4)) {
|
||||
return -1;
|
||||
} else {
|
||||
return sp.getFloat(context.getString(R.string.screen_brightness_key), -1);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setScreenBrightness(@NonNull final Context context,
|
||||
final float setScreenBrightness) {
|
||||
setScreenBrightness(context, setScreenBrightness, System.currentTimeMillis());
|
||||
final float screenBrightness) {
|
||||
getPreferences(context).edit()
|
||||
.putFloat(context.getString(R.string.screen_brightness_key), screenBrightness)
|
||||
.putLong(context.getString(R.string.screen_brightness_timestamp_key),
|
||||
System.currentTimeMillis())
|
||||
.apply();
|
||||
}
|
||||
|
||||
public static boolean globalScreenOrientationLocked(final Context context) {
|
||||
@ -376,75 +435,11 @@ public final class PlayerHelper {
|
||||
return PreferenceManager.getDefaultSharedPreferences(context);
|
||||
}
|
||||
|
||||
private static boolean isResumeAfterAudioFocusGain(@NonNull final Context context,
|
||||
final boolean b) {
|
||||
return getPreferences(context)
|
||||
.getBoolean(context.getString(R.string.resume_on_audio_focus_gain_key), b);
|
||||
}
|
||||
|
||||
private static boolean isVolumeGestureEnabled(@NonNull final Context context,
|
||||
final boolean b) {
|
||||
return getPreferences(context)
|
||||
.getBoolean(context.getString(R.string.volume_gesture_control_key), b);
|
||||
}
|
||||
|
||||
private static boolean isBrightnessGestureEnabled(@NonNull final Context context,
|
||||
final boolean b) {
|
||||
return getPreferences(context)
|
||||
.getBoolean(context.getString(R.string.brightness_gesture_control_key), b);
|
||||
}
|
||||
|
||||
private static boolean isRememberingPopupDimensions(@NonNull final Context context,
|
||||
final boolean b) {
|
||||
return getPreferences(context)
|
||||
.getBoolean(context.getString(R.string.popup_remember_size_pos_key), b);
|
||||
}
|
||||
|
||||
private static boolean isUsingInexactSeek(@NonNull final Context context) {
|
||||
return getPreferences(context)
|
||||
.getBoolean(context.getString(R.string.use_inexact_seek_key), false);
|
||||
}
|
||||
|
||||
private static boolean isAutoQueueEnabled(@NonNull final Context context, final boolean b) {
|
||||
return getPreferences(context).getBoolean(context.getString(R.string.auto_queue_key), b);
|
||||
}
|
||||
|
||||
private static void setScreenBrightness(@NonNull final Context context,
|
||||
final float screenBrightness, final long timestamp) {
|
||||
final SharedPreferences.Editor editor = getPreferences(context).edit();
|
||||
editor.putFloat(context.getString(R.string.screen_brightness_key), screenBrightness);
|
||||
editor.putLong(context.getString(R.string.screen_brightness_timestamp_key), timestamp);
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
private static float getScreenBrightness(@NonNull final Context context,
|
||||
final float screenBrightness) {
|
||||
final SharedPreferences sp = getPreferences(context);
|
||||
final long timestamp = sp
|
||||
.getLong(context.getString(R.string.screen_brightness_timestamp_key), 0);
|
||||
// Hypothesis: 4h covers a viewing block, e.g. evening.
|
||||
// External lightning conditions will change in the next
|
||||
// viewing block so we fall back to the default brightness
|
||||
if ((System.currentTimeMillis() - timestamp) > TimeUnit.HOURS.toMillis(4)) {
|
||||
return screenBrightness;
|
||||
} else {
|
||||
return sp
|
||||
.getFloat(context.getString(R.string.screen_brightness_key), screenBrightness);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getMinimizeOnExitAction(@NonNull final Context context,
|
||||
final String key) {
|
||||
return getPreferences(context)
|
||||
.getString(context.getString(R.string.minimize_on_exit_key), key);
|
||||
}
|
||||
|
||||
private static String getAutoplayType(@NonNull final Context context,
|
||||
final String key) {
|
||||
return getPreferences(context).getString(context.getString(R.string.autoplay_key),
|
||||
key);
|
||||
}
|
||||
|
||||
private static SinglePlayQueue getAutoQueuedSinglePlayQueue(
|
||||
final StreamInfoItem streamInfoItem) {
|
||||
final SinglePlayQueue singlePlayQueue = new SinglePlayQueue(streamInfoItem);
|
||||
@ -452,12 +447,168 @@ public final class PlayerHelper {
|
||||
return singlePlayQueue;
|
||||
}
|
||||
|
||||
@Retention(SOURCE)
|
||||
@IntDef({MINIMIZE_ON_EXIT_MODE_NONE, MINIMIZE_ON_EXIT_MODE_BACKGROUND,
|
||||
MINIMIZE_ON_EXIT_MODE_POPUP})
|
||||
public @interface MinimizeMode {
|
||||
int MINIMIZE_ON_EXIT_MODE_NONE = 0;
|
||||
int MINIMIZE_ON_EXIT_MODE_BACKGROUND = 1;
|
||||
int MINIMIZE_ON_EXIT_MODE_POPUP = 2;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Utils used by player
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public static MainPlayer.PlayerType retrievePlayerTypeFromIntent(final Intent intent) {
|
||||
// If you want to open popup from the app just include Constants.POPUP_ONLY into an extra
|
||||
return MainPlayer.PlayerType.values()[
|
||||
intent.getIntExtra(PLAYER_TYPE, MainPlayer.PlayerType.VIDEO.ordinal())];
|
||||
}
|
||||
|
||||
public static boolean isPlaybackResumeEnabled(final Player player) {
|
||||
return player.getPrefs().getBoolean(
|
||||
player.getContext().getString(R.string.enable_watch_history_key), true)
|
||||
&& player.getPrefs().getBoolean(
|
||||
player.getContext().getString(R.string.enable_playback_resume_key), true);
|
||||
}
|
||||
|
||||
@RepeatMode
|
||||
public static int nextRepeatMode(@RepeatMode final int repeatMode) {
|
||||
switch (repeatMode) {
|
||||
case REPEAT_MODE_OFF:
|
||||
return REPEAT_MODE_ONE;
|
||||
case REPEAT_MODE_ONE:
|
||||
return REPEAT_MODE_ALL;
|
||||
case REPEAT_MODE_ALL: default:
|
||||
return REPEAT_MODE_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
@ResizeMode
|
||||
public static int retrieveResizeModeFromPrefs(final Player player) {
|
||||
return player.getPrefs().getInt(player.getContext().getString(R.string.last_resize_mode),
|
||||
AspectRatioFrameLayout.RESIZE_MODE_FIT);
|
||||
}
|
||||
|
||||
@SuppressLint("SwitchIntDef") // only fit, fill and zoom are supported by NewPipe
|
||||
@ResizeMode
|
||||
public static int nextResizeModeAndSaveToPrefs(final Player player,
|
||||
@ResizeMode final int resizeMode) {
|
||||
final int newResizeMode;
|
||||
switch (resizeMode) {
|
||||
case AspectRatioFrameLayout.RESIZE_MODE_FIT:
|
||||
newResizeMode = AspectRatioFrameLayout.RESIZE_MODE_FILL;
|
||||
break;
|
||||
case AspectRatioFrameLayout.RESIZE_MODE_FILL:
|
||||
newResizeMode = AspectRatioFrameLayout.RESIZE_MODE_ZOOM;
|
||||
break;
|
||||
case AspectRatioFrameLayout.RESIZE_MODE_ZOOM:
|
||||
default:
|
||||
newResizeMode = AspectRatioFrameLayout.RESIZE_MODE_FIT;
|
||||
break;
|
||||
}
|
||||
|
||||
player.getPrefs().edit().putInt(
|
||||
player.getContext().getString(R.string.last_resize_mode), resizeMode).apply();
|
||||
return newResizeMode;
|
||||
}
|
||||
|
||||
public static PlaybackParameters retrievePlaybackParametersFromPrefs(final Player player) {
|
||||
final float speed = player.getPrefs().getFloat(player.getContext().getString(
|
||||
R.string.playback_speed_key), player.getPlaybackSpeed());
|
||||
final float pitch = player.getPrefs().getFloat(player.getContext().getString(
|
||||
R.string.playback_pitch_key), player.getPlaybackPitch());
|
||||
final boolean skipSilence = player.getPrefs().getBoolean(player.getContext().getString(
|
||||
R.string.playback_skip_silence_key), player.getPlaybackSkipSilence());
|
||||
return new PlaybackParameters(speed, pitch, skipSilence);
|
||||
}
|
||||
|
||||
public static void savePlaybackParametersToPrefs(final Player player,
|
||||
final float speed,
|
||||
final float pitch,
|
||||
final boolean skipSilence) {
|
||||
player.getPrefs().edit()
|
||||
.putFloat(player.getContext().getString(R.string.playback_speed_key), speed)
|
||||
.putFloat(player.getContext().getString(R.string.playback_pitch_key), pitch)
|
||||
.putBoolean(player.getContext().getString(R.string.playback_skip_silence_key),
|
||||
skipSilence)
|
||||
.apply();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param player {@code screenWidth} and {@code screenHeight} must have been initialized
|
||||
* @return the popup starting layout params
|
||||
*/
|
||||
@SuppressLint("RtlHardcoded")
|
||||
public static WindowManager.LayoutParams retrievePopupLayoutParamsFromPrefs(
|
||||
final Player player) {
|
||||
final boolean popupRememberSizeAndPos = player.getPrefs().getBoolean(
|
||||
player.getContext().getString(R.string.popup_remember_size_pos_key), true);
|
||||
final float defaultSize =
|
||||
player.getContext().getResources().getDimension(R.dimen.popup_default_width);
|
||||
final float popupWidth = popupRememberSizeAndPos
|
||||
? player.getPrefs().getFloat(player.getContext().getString(
|
||||
R.string.popup_saved_width_key), defaultSize)
|
||||
: defaultSize;
|
||||
final float popupHeight = getMinimumVideoHeight(popupWidth);
|
||||
|
||||
final WindowManager.LayoutParams popupLayoutParams = new WindowManager.LayoutParams(
|
||||
(int) popupWidth, (int) popupHeight,
|
||||
popupLayoutParamType(),
|
||||
IDLE_WINDOW_FLAGS,
|
||||
PixelFormat.TRANSLUCENT);
|
||||
popupLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
|
||||
popupLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
|
||||
|
||||
final int centerX = (int) (player.getScreenWidth() / 2f - popupWidth / 2f);
|
||||
final int centerY = (int) (player.getScreenHeight() / 2f - popupHeight / 2f);
|
||||
popupLayoutParams.x = popupRememberSizeAndPos
|
||||
? player.getPrefs().getInt(player.getContext().getString(
|
||||
R.string.popup_saved_x_key), centerX) : centerX;
|
||||
popupLayoutParams.y = popupRememberSizeAndPos
|
||||
? player.getPrefs().getInt(player.getContext().getString(
|
||||
R.string.popup_saved_y_key), centerY) : centerY;
|
||||
|
||||
return popupLayoutParams;
|
||||
}
|
||||
|
||||
public static void savePopupPositionAndSizeToPrefs(final Player player) {
|
||||
if (player.getPopupLayoutParams() != null) {
|
||||
player.getPrefs().edit()
|
||||
.putFloat(player.getContext().getString(R.string.popup_saved_width_key),
|
||||
player.getPopupLayoutParams().width)
|
||||
.putInt(player.getContext().getString(R.string.popup_saved_x_key),
|
||||
player.getPopupLayoutParams().x)
|
||||
.putInt(player.getContext().getString(R.string.popup_saved_y_key),
|
||||
player.getPopupLayoutParams().y)
|
||||
.apply();
|
||||
}
|
||||
}
|
||||
|
||||
public static float getMinimumVideoHeight(final float width) {
|
||||
return width / (16.0f / 9.0f); // Respect the 16:9 ratio that most videos have
|
||||
}
|
||||
|
||||
@SuppressLint("RtlHardcoded")
|
||||
public static WindowManager.LayoutParams buildCloseOverlayLayoutParams() {
|
||||
final int flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
||||
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
|
||||
| WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
|
||||
|
||||
final WindowManager.LayoutParams closeOverlayLayoutParams = new WindowManager.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
popupLayoutParamType(),
|
||||
flags,
|
||||
PixelFormat.TRANSLUCENT);
|
||||
|
||||
closeOverlayLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
|
||||
closeOverlayLayoutParams.softInputMode =
|
||||
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
|
||||
return closeOverlayLayoutParams;
|
||||
}
|
||||
|
||||
public static int popupLayoutParamType() {
|
||||
return Build.VERSION.SDK_INT < Build.VERSION_CODES.O
|
||||
? WindowManager.LayoutParams.TYPE_PHONE
|
||||
: WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
|
||||
}
|
||||
|
||||
public static int retrieveSeekDurationFromPreferences(final Player player) {
|
||||
return Integer.parseInt(Objects.requireNonNull(player.getPrefs().getString(
|
||||
player.getContext().getString(R.string.seek_duration_key),
|
||||
player.getContext().getString(R.string.seek_duration_default_value))));
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ import org.schabi.newpipe.App;
|
||||
import org.schabi.newpipe.MainActivity;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||
import org.schabi.newpipe.player.MainPlayer;
|
||||
import org.schabi.newpipe.player.VideoPlayerImpl;
|
||||
import org.schabi.newpipe.player.Player;
|
||||
import org.schabi.newpipe.player.event.PlayerServiceEventListener;
|
||||
import org.schabi.newpipe.player.event.PlayerServiceExtendedEventListener;
|
||||
import org.schabi.newpipe.player.playqueue.PlayQueue;
|
||||
@ -33,7 +33,7 @@ public final class PlayerHolder {
|
||||
private static ServiceConnection serviceConnection;
|
||||
public static boolean bound;
|
||||
private static MainPlayer playerService;
|
||||
private static VideoPlayerImpl player;
|
||||
private static Player player;
|
||||
|
||||
/**
|
||||
* Returns the current {@link MainPlayer.PlayerType} of the {@link MainPlayer} service,
|
||||
|
@ -3,11 +3,11 @@ package org.schabi.newpipe.player.mediasession;
|
||||
import android.support.v4.media.MediaDescriptionCompat;
|
||||
|
||||
public interface MediaSessionCallback {
|
||||
void onSkipToPrevious();
|
||||
void playPrevious();
|
||||
|
||||
void onSkipToNext();
|
||||
void playNext();
|
||||
|
||||
void onSkipToIndex(int index);
|
||||
void playItemAtIndex(int index);
|
||||
|
||||
int getCurrentPlayingIndex();
|
||||
|
||||
@ -15,7 +15,7 @@ public interface MediaSessionCallback {
|
||||
|
||||
MediaDescriptionCompat getQueueMetadata(int index);
|
||||
|
||||
void onPlay();
|
||||
void play();
|
||||
|
||||
void onPause();
|
||||
void pause();
|
||||
}
|
||||
|
@ -65,18 +65,18 @@ public class PlayQueueNavigator implements MediaSessionConnector.QueueNavigator
|
||||
|
||||
@Override
|
||||
public void onSkipToPrevious(final Player player, final ControlDispatcher controlDispatcher) {
|
||||
callback.onSkipToPrevious();
|
||||
callback.playPrevious();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSkipToQueueItem(final Player player, final ControlDispatcher controlDispatcher,
|
||||
final long id) {
|
||||
callback.onSkipToIndex((int) id);
|
||||
callback.playItemAtIndex((int) id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSkipToNext(final Player player, final ControlDispatcher controlDispatcher) {
|
||||
callback.onSkipToNext();
|
||||
callback.playNext();
|
||||
}
|
||||
|
||||
private void publishFloatingQueueWindow() {
|
||||
|
@ -14,9 +14,9 @@ public class PlayQueuePlaybackController extends DefaultControlDispatcher {
|
||||
@Override
|
||||
public boolean dispatchSetPlayWhenReady(final Player player, final boolean playWhenReady) {
|
||||
if (playWhenReady) {
|
||||
callback.onPlay();
|
||||
callback.play();
|
||||
} else {
|
||||
callback.onPause();
|
||||
callback.pause();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -5,33 +5,33 @@ import android.os.Bundle;
|
||||
import android.support.v4.media.MediaDescriptionCompat;
|
||||
import android.support.v4.media.MediaMetadataCompat;
|
||||
|
||||
import org.schabi.newpipe.player.BasePlayer;
|
||||
import org.schabi.newpipe.player.Player;
|
||||
import org.schabi.newpipe.player.mediasession.MediaSessionCallback;
|
||||
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
|
||||
|
||||
public class BasePlayerMediaSession implements MediaSessionCallback {
|
||||
private final BasePlayer player;
|
||||
public class PlayerMediaSession implements MediaSessionCallback {
|
||||
private final Player player;
|
||||
|
||||
public BasePlayerMediaSession(final BasePlayer player) {
|
||||
public PlayerMediaSession(final Player player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSkipToPrevious() {
|
||||
player.onPlayPrevious();
|
||||
public void playPrevious() {
|
||||
player.playPrevious();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSkipToNext() {
|
||||
player.onPlayNext();
|
||||
public void playNext() {
|
||||
player.playNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSkipToIndex(final int index) {
|
||||
public void playItemAtIndex(final int index) {
|
||||
if (player.getPlayQueue() == null) {
|
||||
return;
|
||||
}
|
||||
player.onSelected(player.getPlayQueue().getItem(index));
|
||||
player.selectQueueItem(player.getPlayQueue().getItem(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -52,11 +52,14 @@ public class BasePlayerMediaSession implements MediaSessionCallback {
|
||||
|
||||
@Override
|
||||
public MediaDescriptionCompat getQueueMetadata(final int index) {
|
||||
if (player.getPlayQueue() == null || player.getPlayQueue().getItem(index) == null) {
|
||||
if (player.getPlayQueue() == null) {
|
||||
return null;
|
||||
}
|
||||
final PlayQueueItem item = player.getPlayQueue().getItem(index);
|
||||
if (item == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final PlayQueueItem item = player.getPlayQueue().getItem(index);
|
||||
final MediaDescriptionCompat.Builder descriptionBuilder
|
||||
= new MediaDescriptionCompat.Builder()
|
||||
.setMediaId(String.valueOf(index))
|
||||
@ -83,12 +86,12 @@ public class BasePlayerMediaSession implements MediaSessionCallback {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlay() {
|
||||
player.onPlay();
|
||||
public void play() {
|
||||
player.play();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
player.onPause();
|
||||
public void pause() {
|
||||
player.pause();
|
||||
}
|
||||
}
|
@ -351,4 +351,19 @@ public final class Localization {
|
||||
private static double round(final double value, final int places) {
|
||||
return new BigDecimal(value).setScale(places, RoundingMode.HALF_UP).doubleValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Workaround to match normalized captions like english to English or deutsch to Deutsch.
|
||||
* @param list the list to search into
|
||||
* @param toFind the string to look for
|
||||
* @return whether the string was found or not
|
||||
*/
|
||||
public static boolean containsCaseInsensitive(final List<String> list, final String toFind) {
|
||||
for (final String i : list) {
|
||||
if (i.equalsIgnoreCase(toFind)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -46,10 +46,9 @@ import org.schabi.newpipe.local.history.StatisticsPlaylistFragment;
|
||||
import org.schabi.newpipe.local.playlist.LocalPlaylistFragment;
|
||||
import org.schabi.newpipe.local.subscription.SubscriptionFragment;
|
||||
import org.schabi.newpipe.local.subscription.SubscriptionsImportFragment;
|
||||
import org.schabi.newpipe.player.BackgroundPlayerActivity;
|
||||
import org.schabi.newpipe.player.BasePlayer;
|
||||
import org.schabi.newpipe.player.PlayQueueActivity;
|
||||
import org.schabi.newpipe.player.Player;
|
||||
import org.schabi.newpipe.player.MainPlayer;
|
||||
import org.schabi.newpipe.player.VideoPlayer;
|
||||
import org.schabi.newpipe.player.helper.PlayerHelper;
|
||||
import org.schabi.newpipe.player.helper.PlayerHolder;
|
||||
import org.schabi.newpipe.player.playqueue.PlayQueue;
|
||||
@ -78,11 +77,11 @@ public final class NavigationHelper {
|
||||
if (playQueue != null) {
|
||||
final String cacheKey = SerializedCache.getInstance().put(playQueue, PlayQueue.class);
|
||||
if (cacheKey != null) {
|
||||
intent.putExtra(VideoPlayer.PLAY_QUEUE_KEY, cacheKey);
|
||||
intent.putExtra(Player.PLAY_QUEUE_KEY, cacheKey);
|
||||
}
|
||||
}
|
||||
intent.putExtra(VideoPlayer.RESUME_PLAYBACK, resumePlayback);
|
||||
intent.putExtra(VideoPlayer.PLAYER_TYPE, VideoPlayer.PLAYER_TYPE_VIDEO);
|
||||
intent.putExtra(Player.RESUME_PLAYBACK, resumePlayback);
|
||||
intent.putExtra(Player.PLAYER_TYPE, MainPlayer.PlayerType.VIDEO.ordinal());
|
||||
|
||||
return intent;
|
||||
}
|
||||
@ -94,7 +93,7 @@ public final class NavigationHelper {
|
||||
final boolean resumePlayback,
|
||||
final boolean playWhenReady) {
|
||||
return getPlayerIntent(context, targetClazz, playQueue, resumePlayback)
|
||||
.putExtra(BasePlayer.PLAY_WHEN_READY, playWhenReady);
|
||||
.putExtra(Player.PLAY_WHEN_READY, playWhenReady);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@ -104,8 +103,8 @@ public final class NavigationHelper {
|
||||
final boolean selectOnAppend,
|
||||
final boolean resumePlayback) {
|
||||
return getPlayerIntent(context, targetClazz, playQueue, resumePlayback)
|
||||
.putExtra(BasePlayer.APPEND_ONLY, true)
|
||||
.putExtra(BasePlayer.SELECT_ON_APPEND, selectOnAppend);
|
||||
.putExtra(Player.APPEND_ONLY, true)
|
||||
.putExtra(Player.SELECT_ON_APPEND, selectOnAppend);
|
||||
}
|
||||
|
||||
public static void playOnMainPlayer(final AppCompatActivity activity,
|
||||
@ -135,7 +134,7 @@ public final class NavigationHelper {
|
||||
|
||||
Toast.makeText(context, R.string.popup_playing_toast, Toast.LENGTH_SHORT).show();
|
||||
final Intent intent = getPlayerIntent(context, MainPlayer.class, queue, resumePlayback);
|
||||
intent.putExtra(VideoPlayer.PLAYER_TYPE, VideoPlayer.PLAYER_TYPE_POPUP);
|
||||
intent.putExtra(Player.PLAYER_TYPE, MainPlayer.PlayerType.POPUP.ordinal());
|
||||
ContextCompat.startForegroundService(context, intent);
|
||||
}
|
||||
|
||||
@ -145,7 +144,7 @@ public final class NavigationHelper {
|
||||
Toast.makeText(context, R.string.background_player_playing_toast, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
final Intent intent = getPlayerIntent(context, MainPlayer.class, queue, resumePlayback);
|
||||
intent.putExtra(VideoPlayer.PLAYER_TYPE, VideoPlayer.PLAYER_TYPE_AUDIO);
|
||||
intent.putExtra(Player.PLAYER_TYPE, MainPlayer.PlayerType.AUDIO.ordinal());
|
||||
ContextCompat.startForegroundService(context, intent);
|
||||
}
|
||||
|
||||
@ -162,7 +161,7 @@ public final class NavigationHelper {
|
||||
final Intent intent = getPlayerEnqueueIntent(
|
||||
context, MainPlayer.class, queue, selectOnAppend, resumePlayback);
|
||||
|
||||
intent.putExtra(VideoPlayer.PLAYER_TYPE, VideoPlayer.PLAYER_TYPE_VIDEO);
|
||||
intent.putExtra(Player.PLAYER_TYPE, MainPlayer.PlayerType.VIDEO.ordinal());
|
||||
ContextCompat.startForegroundService(context, intent);
|
||||
}
|
||||
|
||||
@ -182,7 +181,7 @@ public final class NavigationHelper {
|
||||
Toast.makeText(context, R.string.enqueued, Toast.LENGTH_SHORT).show();
|
||||
final Intent intent = getPlayerEnqueueIntent(
|
||||
context, MainPlayer.class, queue, selectOnAppend, resumePlayback);
|
||||
intent.putExtra(VideoPlayer.PLAYER_TYPE, VideoPlayer.PLAYER_TYPE_POPUP);
|
||||
intent.putExtra(Player.PLAYER_TYPE, MainPlayer.PlayerType.POPUP.ordinal());
|
||||
ContextCompat.startForegroundService(context, intent);
|
||||
}
|
||||
|
||||
@ -198,7 +197,7 @@ public final class NavigationHelper {
|
||||
Toast.makeText(context, R.string.enqueued, Toast.LENGTH_SHORT).show();
|
||||
final Intent intent = getPlayerEnqueueIntent(
|
||||
context, MainPlayer.class, queue, selectOnAppend, resumePlayback);
|
||||
intent.putExtra(VideoPlayer.PLAYER_TYPE, VideoPlayer.PLAYER_TYPE_AUDIO);
|
||||
intent.putExtra(Player.PLAYER_TYPE, MainPlayer.PlayerType.AUDIO.ordinal());
|
||||
ContextCompat.startForegroundService(context, intent);
|
||||
}
|
||||
|
||||
@ -493,7 +492,7 @@ public final class NavigationHelper {
|
||||
if (playQueue != null) {
|
||||
final String cacheKey = SerializedCache.getInstance().put(playQueue, PlayQueue.class);
|
||||
if (cacheKey != null) {
|
||||
intent.putExtra(VideoPlayer.PLAY_QUEUE_KEY, cacheKey);
|
||||
intent.putExtra(Player.PLAY_QUEUE_KEY, cacheKey);
|
||||
}
|
||||
}
|
||||
context.startActivity(intent);
|
||||
@ -531,7 +530,7 @@ public final class NavigationHelper {
|
||||
}
|
||||
|
||||
public static Intent getPlayQueueActivityIntent(final Context context) {
|
||||
final Intent intent = new Intent(context, BackgroundPlayerActivity.class);
|
||||
final Intent intent = new Intent(context, PlayQueueActivity.class);
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context="org.schabi.newpipe.player.BackgroundPlayerActivity">
|
||||
tools:context="org.schabi.newpipe.player.PlayQueueActivity">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appbar"
|
||||
|
@ -145,7 +145,7 @@
|
||||
tools:text="The Video Artist LONG very LONG very Long" />
|
||||
</LinearLayout>
|
||||
|
||||
<Button
|
||||
<TextView
|
||||
android:id="@+id/qualityTextView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="35dp"
|
||||
@ -154,13 +154,12 @@
|
||||
android:gravity="center"
|
||||
android:minWidth="0dp"
|
||||
android:padding="@dimen/player_main_buttons_padding"
|
||||
android:text="720p"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="@android:color/white"
|
||||
android:textStyle="bold"
|
||||
tools:ignore="HardcodedText,RtlHardcoded" />
|
||||
tools:ignore="HardcodedText,RtlHardcoded"
|
||||
tools:text="720p" />
|
||||
|
||||
<Button
|
||||
<TextView
|
||||
android:id="@+id/playbackSpeed"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="35dp"
|
||||
@ -169,7 +168,6 @@
|
||||
android:gravity="center"
|
||||
android:minWidth="0dp"
|
||||
android:padding="@dimen/player_main_buttons_padding"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="@android:color/white"
|
||||
android:textStyle="bold"
|
||||
tools:ignore="RtlHardcoded,RtlSymmetry"
|
||||
@ -216,7 +214,7 @@
|
||||
tools:ignore="RtlHardcoded"
|
||||
tools:visibility="visible">
|
||||
|
||||
<Button
|
||||
<TextView
|
||||
android:id="@+id/resizeTextView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="35dp"
|
||||
|
@ -6,7 +6,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context="org.schabi.newpipe.player.BackgroundPlayerActivity">
|
||||
tools:context="org.schabi.newpipe.player.PlayQueueActivity">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appbar"
|
||||
|
@ -156,11 +156,10 @@
|
||||
android:gravity="center"
|
||||
android:minWidth="0dp"
|
||||
android:padding="@dimen/player_main_buttons_padding"
|
||||
android:text="720p"
|
||||
android:textColor="@android:color/white"
|
||||
android:textStyle="bold"
|
||||
android:visibility="visible"
|
||||
tools:ignore="HardcodedText,RtlHardcoded" />
|
||||
tools:ignore="HardcodedText,RtlHardcoded"
|
||||
tools:text="720p" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/playbackSpeed"
|
||||
@ -350,7 +349,7 @@
|
||||
tools:text="1:06:29" />
|
||||
|
||||
|
||||
<androidx.appcompat.widget.AppCompatSeekBar
|
||||
<org.schabi.newpipe.views.FocusAwareSeekBar
|
||||
android:id="@+id/playbackSeekBar"
|
||||
style="@style/Widget.AppCompat.SeekBar"
|
||||
android:layout_width="0dp"
|
||||
|
@ -1,7 +1,7 @@
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".player.BackgroundPlayerActivity">
|
||||
tools:context=".player.PlayQueueActivity">
|
||||
|
||||
<item
|
||||
android:id="@+id/action_append_playlist"
|
||||
|
@ -21,7 +21,6 @@
|
||||
|
||||
<string name="use_external_video_player_key" translatable="false">use_external_video_player</string>
|
||||
<string name="use_external_audio_player_key" translatable="false">use_external_audio_player</string>
|
||||
<string name="use_old_player_key" translatable="false">use_oldplayer</string>
|
||||
|
||||
<string name="volume_gesture_control_key" translatable="false">volume_gesture_control</string>
|
||||
<string name="brightness_gesture_control_key" translatable="false">brightness_gesture_control</string>
|
||||
@ -33,6 +32,10 @@
|
||||
<string name="screen_brightness_timestamp_key" translatable="false">screen_brightness_timestamp_key</string>
|
||||
<string name="clear_queue_confirmation_key" translatable="false">clear_queue_confirmation_key</string>
|
||||
|
||||
<string name="popup_saved_width_key" translatable="false">popup_saved_width</string>
|
||||
<string name="popup_saved_x_key" translatable="false">popup_saved_x</string>
|
||||
<string name="popup_saved_y_key" translatable="false">popup_saved_y</string>
|
||||
|
||||
<string name="seek_duration_key" translatable="false">seek_duration</string>
|
||||
<string name="seek_duration_default_value" translatable="false">10000</string>
|
||||
<string-array name="seek_duration_description" translatable="false">
|
||||
@ -70,7 +73,6 @@
|
||||
<item>@string/minimize_on_exit_popup_description</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
<string name="autoplay_key" translatable="false">autoplay_key</string>
|
||||
<string name="autoplay_value" translatable="false">@string/autoplay_wifi_key</string>
|
||||
<string name="autoplay_always_key" translatable="false">autoplay_always_key</string>
|
||||
|
@ -25,7 +25,7 @@
|
||||
lines="156,158"/>
|
||||
|
||||
<suppress checks="FileLength"
|
||||
files="VideoPlayerImpl.java"/>
|
||||
files="Player.java"/>
|
||||
|
||||
<suppress checks="FileLength"
|
||||
files="VideoDetailFragment.java"/>
|
||||
|
Loading…
Reference in New Issue
Block a user