mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-11-04 09:13:00 +00:00 
			
		
		
		
	Merge player classes into a single one
This commit is contained in:
		@@ -68,7 +68,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;
 | 
			
		||||
@@ -763,7 +763,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;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -2020,9 +2018,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 +2069,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 +2283,7 @@ public final class VideoDetailFragment
 | 
			
		||||
                        // Re-enable clicks
 | 
			
		||||
                        setOverlayElementsClickable(true);
 | 
			
		||||
                        if (player != null) {
 | 
			
		||||
                            player.onQueueClosed();
 | 
			
		||||
                            player.closeQueue();
 | 
			
		||||
                        }
 | 
			
		||||
                        setOverlayLook(appBarLayout, behavior, 0);
 | 
			
		||||
                        break;
 | 
			
		||||
 
 | 
			
		||||
@@ -26,15 +26,15 @@ public final class BackgroundPlayerActivity extends ServicePlayerActivity {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void startPlayerListener() {
 | 
			
		||||
        if (player instanceof VideoPlayerImpl) {
 | 
			
		||||
            ((VideoPlayerImpl) player).setActivityListener(this);
 | 
			
		||||
        if (player != null) {
 | 
			
		||||
            player.setActivityListener(this);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void stopPlayerListener() {
 | 
			
		||||
        if (player instanceof VideoPlayerImpl) {
 | 
			
		||||
            ((VideoPlayerImpl) player).removeActivityListener(this);
 | 
			
		||||
        if (player != null) {
 | 
			
		||||
            player.removeActivityListener(this);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -45,13 +45,11 @@ public final class BackgroundPlayerActivity extends ServicePlayerActivity {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void setupMenu(final Menu menu) {
 | 
			
		||||
        if (player == null) {
 | 
			
		||||
            return;
 | 
			
		||||
        if (player != null) {
 | 
			
		||||
            menu.findItem(R.id.action_switch_popup)
 | 
			
		||||
                    .setVisible(!player.popupPlayerSelected());
 | 
			
		||||
            menu.findItem(R.id.action_switch_background)
 | 
			
		||||
                    .setVisible(!player.audioPlayerSelected());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        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()));
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,6 @@ 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;
 | 
			
		||||
@@ -55,7 +54,7 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
 | 
			
		||||
    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;
 | 
			
		||||
@@ -167,14 +166,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);
 | 
			
		||||
@@ -235,7 +234,7 @@ 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 {
 | 
			
		||||
@@ -375,7 +374,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 +435,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()) {
 | 
			
		||||
@@ -616,15 +615,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 +632,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 +649,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 +699,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));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
										
											
												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();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -354,4 +354,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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -47,9 +47,8 @@ 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.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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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"/>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user