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