From 89cb61165a01f344d8cf5c44d414309fa5d13b48 Mon Sep 17 00:00:00 2001 From: xeinebiu Date: Sun, 14 Jan 2024 22:12:15 +0100 Subject: [PATCH 1/8] feat: show video track selectors on PlayerControlView --- .../androidx/media3/ui/PlayerControlView.java | 112 +++++++++++++++++- .../main/res/drawable/exo_ic_videotrack.xml | 9 ++ .../ui/src/main/res/values/drawables.xml | 1 + libraries/ui/src/main/res/values/ids.xml | 1 + 4 files changed, 119 insertions(+), 4 deletions(-) create mode 100644 libraries/ui/src/main/res/drawable/exo_ic_videotrack.xml diff --git a/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java b/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java index 3fd19a0c8f3..984162d9968 100644 --- a/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java +++ b/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java @@ -265,6 +265,8 @@ public interface OnFullScreenModeChangedListener { private static final int SETTINGS_PLAYBACK_SPEED_POSITION = 0; private static final int SETTINGS_AUDIO_TRACK_SELECTION_POSITION = 1; + private static final int SETTINGS_VIDEO_TRACK_SELECTION_POSITION = 2; + private final PlayerControlViewLayoutManager controlViewLayoutManager; private final Resources resources; private final ComponentListener componentListener; @@ -276,6 +278,7 @@ public interface OnFullScreenModeChangedListener { private final SettingsAdapter settingsAdapter; private final PlaybackSpeedAdapter playbackSpeedAdapter; private final TextTrackSelectionAdapter textTrackSelectionAdapter; + private final VideoTrackSelectionAdapter videoTrackSelectionAdapter; private final AudioTrackSelectionAdapter audioTrackSelectionAdapter; // TODO(insun): Add setTrackNameProvider to use customized track name provider. private final TrackNameProvider trackNameProvider; @@ -298,6 +301,7 @@ public interface OnFullScreenModeChangedListener { @Nullable private final View settingsButton; @Nullable private final View playbackSpeedButton; @Nullable private final View audioTrackButton; + @Nullable private final View videoTrackButton; @Nullable private final TextView durationView; @Nullable private final TextView positionView; @Nullable private final TimeBar timeBar; @@ -469,6 +473,11 @@ public PlayerControlView( audioTrackButton.setOnClickListener(componentListener); } + videoTrackButton = findViewById(R.id.exo_video_track); + if (videoTrackButton != null) { + videoTrackButton.setOnClickListener(componentListener); + } + TimeBar customTimeBar = findViewById(R.id.exo_progress); View timeBarPlaceholder = findViewById(R.id.exo_progress_placeholder); if (customTimeBar != null) { @@ -546,16 +555,23 @@ public PlayerControlView( controlViewLayoutManager = new PlayerControlViewLayoutManager(this); controlViewLayoutManager.setAnimationEnabled(animationEnabled); - String[] settingTexts = new String[2]; - Drawable[] settingIcons = new Drawable[2]; + String[] settingTexts = new String[3]; + Drawable[] settingIcons = new Drawable[3]; settingTexts[SETTINGS_PLAYBACK_SPEED_POSITION] = resources.getString(R.string.exo_controls_playback_speed); settingIcons[SETTINGS_PLAYBACK_SPEED_POSITION] = getDrawable(context, resources, R.drawable.exo_styled_controls_speed); + settingTexts[SETTINGS_AUDIO_TRACK_SELECTION_POSITION] = resources.getString(R.string.exo_track_selection_title_audio); settingIcons[SETTINGS_AUDIO_TRACK_SELECTION_POSITION] = getDrawable(context, resources, R.drawable.exo_styled_controls_audiotrack); + + settingTexts[SETTINGS_VIDEO_TRACK_SELECTION_POSITION] = + resources.getString(R.string.exo_track_selection_title_video); + settingIcons[SETTINGS_VIDEO_TRACK_SELECTION_POSITION] = + getDrawable(context, resources, R.drawable.exo_styled_controls_videotrack); + settingsAdapter = new SettingsAdapter(settingTexts, settingIcons); settingsWindowMargin = resources.getDimensionPixelSize(R.dimen.exo_settings_offset); settingsView = @@ -585,6 +601,7 @@ public PlayerControlView( resources.getString(R.string.exo_controls_cc_disabled_description); textTrackSelectionAdapter = new TextTrackSelectionAdapter(); audioTrackSelectionAdapter = new AudioTrackSelectionAdapter(); + videoTrackSelectionAdapter = new VideoTrackSelectionAdapter(); playbackSpeedAdapter = new PlaybackSpeedAdapter( resources.getStringArray(R.array.exo_controls_playback_speeds), PLAYBACK_SPEEDS); @@ -1153,13 +1170,18 @@ private void updateTrackLists() { private void initTrackSelectionAdapter() { textTrackSelectionAdapter.clear(); audioTrackSelectionAdapter.clear(); + videoTrackSelectionAdapter.clear(); + if (player == null || !player.isCommandAvailable(COMMAND_GET_TRACKS) || !player.isCommandAvailable(COMMAND_SET_TRACK_SELECTION_PARAMETERS)) { return; } + Tracks tracks = player.getCurrentTracks(); audioTrackSelectionAdapter.init(gatherSupportedTrackInfosOfType(tracks, C.TRACK_TYPE_AUDIO)); + videoTrackSelectionAdapter.init(gatherSupportedTrackInfosOfType(tracks, C.TRACK_TYPE_VIDEO)); + if (controlViewLayoutManager.getShowButton(subtitleButton)) { textTrackSelectionAdapter.init(gatherSupportedTrackInfosOfType(tracks, C.TRACK_TYPE_TEXT)); } else { @@ -1439,6 +1461,8 @@ private void onSettingViewClicked(int position) { displaySettingsWindow(playbackSpeedAdapter, checkNotNull(settingsButton)); } else if (position == SETTINGS_AUDIO_TRACK_SELECTION_POSITION) { displaySettingsWindow(audioTrackSelectionAdapter, checkNotNull(settingsButton)); + } else if(position == SETTINGS_VIDEO_TRACK_SELECTION_POSITION) { + displaySettingsWindow(videoTrackSelectionAdapter, checkNotNull(settingsButton)); } else { settingsWindow.dismiss(); } @@ -1554,7 +1578,7 @@ private boolean shouldEnablePlayPauseButton() { return player != null && player.isCommandAvailable(COMMAND_PLAY_PAUSE) && (!player.isCommandAvailable(COMMAND_GET_TIMELINE) - || !player.getCurrentTimeline().isEmpty()); + || !player.getCurrentTimeline().isEmpty()); } @SuppressLint("InlinedApi") @@ -1745,7 +1769,10 @@ public void onClick(View view) { } else if (audioTrackButton == view) { controlViewLayoutManager.removeHideCallbacks(); displaySettingsWindow(audioTrackSelectionAdapter, audioTrackButton); - } else if (subtitleButton == view) { + } else if (videoTrackButton == view) { + controlViewLayoutManager.removeHideCallbacks(); + displaySettingsWindow(videoTrackSelectionAdapter, videoTrackButton); + } else if (subtitleButton == view) { controlViewLayoutManager.removeHideCallbacks(); displaySettingsWindow(textTrackSelectionAdapter, subtitleButton); } @@ -2071,6 +2098,83 @@ public void init(List trackInformations) { } } + private final class VideoTrackSelectionAdapter extends TrackSelectionAdapter { + + @Override + public void onBindViewHolderAtZeroPosition(SubSettingViewHolder holder) { + // Audio track selection option includes "Auto" at the top. + holder.textView.setText(R.string.exo_track_selection_auto); + // hasSelectionOverride is true means there is an explicit track selection, not "Auto". + TrackSelectionParameters parameters = checkNotNull(player).getTrackSelectionParameters(); + boolean hasSelectionOverride = hasSelectionOverride(parameters); + holder.checkView.setVisibility(hasSelectionOverride ? INVISIBLE : VISIBLE); + holder.itemView.setOnClickListener( + v -> { + if (player == null + || !player.isCommandAvailable(COMMAND_SET_TRACK_SELECTION_PARAMETERS)) { + return; + } + + TrackSelectionParameters trackSelectionParameters = + player.getTrackSelectionParameters(); + + castNonNull(player) + .setTrackSelectionParameters( + trackSelectionParameters + .buildUpon() + .clearOverridesOfType(C.TRACK_TYPE_VIDEO) + .setTrackTypeDisabled(C.TRACK_TYPE_VIDEO, /* disabled= */ false) + .build()); + + settingsAdapter.setSubTextAtPosition( + SETTINGS_VIDEO_TRACK_SELECTION_POSITION, + getResources().getString(R.string.exo_track_selection_auto)); + + settingsWindow.dismiss(); + }); + } + + private boolean hasSelectionOverride(TrackSelectionParameters trackSelectionParameters) { + for (int i = 0; i < tracks.size(); i++) { + TrackGroup trackGroup = tracks.get(i).trackGroup.getMediaTrackGroup(); + if (trackSelectionParameters.overrides.containsKey(trackGroup)) { + return true; + } + } + return false; + } + + @Override + public void onTrackSelection(String subtext) { + settingsAdapter.setSubTextAtPosition(SETTINGS_VIDEO_TRACK_SELECTION_POSITION, subtext); + } + + @Override + public void init(List trackInformations) { + this.tracks = trackInformations; + // Update subtext in settings menu with current audio track selection. + TrackSelectionParameters params = checkNotNull(player).getTrackSelectionParameters(); + if (trackInformations.isEmpty()) { + settingsAdapter.setSubTextAtPosition( + SETTINGS_VIDEO_TRACK_SELECTION_POSITION, + getResources().getString(R.string.exo_track_selection_none)); + } else if (!hasSelectionOverride(params)) { + settingsAdapter.setSubTextAtPosition( + SETTINGS_VIDEO_TRACK_SELECTION_POSITION, + getResources().getString(R.string.exo_track_selection_auto)); + } else { + for (int i = 0; i < trackInformations.size(); i++) { + TrackInformation track = trackInformations.get(i); + if (track.isSelected()) { + settingsAdapter.setSubTextAtPosition( + SETTINGS_VIDEO_TRACK_SELECTION_POSITION, track.trackName); + break; + } + } + } + } + } + private abstract class TrackSelectionAdapter extends RecyclerView.Adapter { protected List tracks; diff --git a/libraries/ui/src/main/res/drawable/exo_ic_videotrack.xml b/libraries/ui/src/main/res/drawable/exo_ic_videotrack.xml new file mode 100644 index 00000000000..ee3eccecdec --- /dev/null +++ b/libraries/ui/src/main/res/drawable/exo_ic_videotrack.xml @@ -0,0 +1,9 @@ + + + diff --git a/libraries/ui/src/main/res/values/drawables.xml b/libraries/ui/src/main/res/values/drawables.xml index 6c65577a44c..39bd31f3667 100644 --- a/libraries/ui/src/main/res/values/drawables.xml +++ b/libraries/ui/src/main/res/values/drawables.xml @@ -59,5 +59,6 @@ @drawable/exo_ic_settings @drawable/exo_ic_check @drawable/exo_ic_audiotrack + @drawable/exo_ic_videotrack @drawable/exo_ic_speed diff --git a/libraries/ui/src/main/res/values/ids.xml b/libraries/ui/src/main/res/values/ids.xml index b0c1632693e..6c38bf4669e 100644 --- a/libraries/ui/src/main/res/values/ids.xml +++ b/libraries/ui/src/main/res/values/ids.xml @@ -45,6 +45,7 @@ + From 2f307bc5228a0641982088820a8a51d9a269ca63 Mon Sep 17 00:00:00 2001 From: Arzan Nebiu <50703441+xeinebiu@users.noreply.github.com> Date: Sat, 20 Jan 2024 01:31:44 +0100 Subject: [PATCH 2/8] Update PlayerControlView.java fix: code comment typos on PlayerControlView.java --- .../src/main/java/androidx/media3/ui/PlayerControlView.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java b/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java index 984162d9968..157da9deb99 100644 --- a/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java +++ b/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java @@ -1461,7 +1461,7 @@ private void onSettingViewClicked(int position) { displaySettingsWindow(playbackSpeedAdapter, checkNotNull(settingsButton)); } else if (position == SETTINGS_AUDIO_TRACK_SELECTION_POSITION) { displaySettingsWindow(audioTrackSelectionAdapter, checkNotNull(settingsButton)); - } else if(position == SETTINGS_VIDEO_TRACK_SELECTION_POSITION) { + } else if (position == SETTINGS_VIDEO_TRACK_SELECTION_POSITION) { displaySettingsWindow(videoTrackSelectionAdapter, checkNotNull(settingsButton)); } else { settingsWindow.dismiss(); @@ -2102,7 +2102,7 @@ private final class VideoTrackSelectionAdapter extends TrackSelectionAdapter { @Override public void onBindViewHolderAtZeroPosition(SubSettingViewHolder holder) { - // Audio track selection option includes "Auto" at the top. + // Video track selection option includes "Auto" at the top. holder.textView.setText(R.string.exo_track_selection_auto); // hasSelectionOverride is true means there is an explicit track selection, not "Auto". TrackSelectionParameters parameters = checkNotNull(player).getTrackSelectionParameters(); @@ -2152,7 +2152,7 @@ public void onTrackSelection(String subtext) { @Override public void init(List trackInformations) { this.tracks = trackInformations; - // Update subtext in settings menu with current audio track selection. + // Update subtext in settings menu with current video track selection. TrackSelectionParameters params = checkNotNull(player).getTrackSelectionParameters(); if (trackInformations.isEmpty()) { settingsAdapter.setSubTextAtPosition( From 188cfb6a9921138f07c3888ca578ed35126f4f54 Mon Sep 17 00:00:00 2001 From: microkatz Date: Fri, 26 Jan 2024 11:14:11 +0000 Subject: [PATCH 3/8] Format with google-java-format --- .../src/main/java/androidx/media3/ui/PlayerControlView.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java b/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java index 157da9deb99..091cc76ef49 100644 --- a/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java +++ b/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java @@ -1578,7 +1578,7 @@ private boolean shouldEnablePlayPauseButton() { return player != null && player.isCommandAvailable(COMMAND_PLAY_PAUSE) && (!player.isCommandAvailable(COMMAND_GET_TIMELINE) - || !player.getCurrentTimeline().isEmpty()); + || !player.getCurrentTimeline().isEmpty()); } @SuppressLint("InlinedApi") @@ -1772,7 +1772,7 @@ public void onClick(View view) { } else if (videoTrackButton == view) { controlViewLayoutManager.removeHideCallbacks(); displaySettingsWindow(videoTrackSelectionAdapter, videoTrackButton); - } else if (subtitleButton == view) { + } else if (subtitleButton == view) { controlViewLayoutManager.removeHideCallbacks(); displaySettingsWindow(textTrackSelectionAdapter, subtitleButton); } From 6d010f890a36998fd34a9d3f369e9d33b1c80411 Mon Sep 17 00:00:00 2001 From: microkatz Date: Fri, 26 Jan 2024 11:21:01 +0000 Subject: [PATCH 4/8] Added release notes for PlayerControlView video track selection --- RELEASENOTES.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 2d8e0e92088..3f7b9db7200 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -18,6 +18,9 @@ * IMA extension: * Session: * UI: + * Add video track selection functionality to settings pop-up menu in + `PlayerControlView` + ([#972](https://github.com/androidx/media/pull/972)). * Downloads: * OkHttp Extension: * Cronet Extension: From 0eea10c82efc80d57d24383314f3e5515b10ca41 Mon Sep 17 00:00:00 2001 From: microkatz Date: Fri, 26 Jan 2024 11:31:01 +0000 Subject: [PATCH 5/8] Added AOSP Header in new drawable xml file --- .../src/main/res/drawable/exo_ic_videotrack.xml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/libraries/ui/src/main/res/drawable/exo_ic_videotrack.xml b/libraries/ui/src/main/res/drawable/exo_ic_videotrack.xml index ee3eccecdec..93a07dabf25 100644 --- a/libraries/ui/src/main/res/drawable/exo_ic_videotrack.xml +++ b/libraries/ui/src/main/res/drawable/exo_ic_videotrack.xml @@ -1,3 +1,19 @@ + + Date: Fri, 26 Jan 2024 12:44:02 +0000 Subject: [PATCH 6/8] Moved exo_ic_videotrack.xml file to correct folder --- .../res/{drawable => drawable-anydpi-v21}/exo_ic_videotrack.xml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename libraries/ui/src/main/res/{drawable => drawable-anydpi-v21}/exo_ic_videotrack.xml (100%) diff --git a/libraries/ui/src/main/res/drawable/exo_ic_videotrack.xml b/libraries/ui/src/main/res/drawable-anydpi-v21/exo_ic_videotrack.xml similarity index 100% rename from libraries/ui/src/main/res/drawable/exo_ic_videotrack.xml rename to libraries/ui/src/main/res/drawable-anydpi-v21/exo_ic_videotrack.xml From 5a57345580088228e3d96ce742bb36aa84ba8a24 Mon Sep 17 00:00:00 2001 From: microkatz Date: Fri, 26 Jan 2024 13:07:42 +0000 Subject: [PATCH 7/8] Added back linter and copybara comments that were removed --- .../main/java/androidx/media3/ui/PlayerControlView.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java b/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java index 091cc76ef49..f159af3274f 100644 --- a/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java +++ b/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java @@ -193,7 +193,8 @@ public class PlayerControlView extends FrameLayout { static { - MediaLibraryInfo.registerModule("media3.ui"); + MediaLibraryInfo.registerModule("media3.ui"); // copybara:media3-only + // copybara:exo-only MediaLibraryInfo.registerModule("goog.exo.ui"); } /** @@ -261,10 +262,10 @@ public interface OnFullScreenModeChangedListener { // LINT.IfChange(playback_speeds) private static final float[] PLAYBACK_SPEEDS = new float[] {0.25f, 0.5f, 0.75f, 1f, 1.25f, 1.5f, 2f}; - + // LINT.ThenChange("../../../../res/values/strings.xml:playback_speeds") + private static final int SETTINGS_PLAYBACK_SPEED_POSITION = 0; private static final int SETTINGS_AUDIO_TRACK_SELECTION_POSITION = 1; - private static final int SETTINGS_VIDEO_TRACK_SELECTION_POSITION = 2; private final PlayerControlViewLayoutManager controlViewLayoutManager; From e12345c2873dc8d7b59944f85e308b69bb096a81 Mon Sep 17 00:00:00 2001 From: microkatz Date: Fri, 26 Jan 2024 15:52:11 +0000 Subject: [PATCH 8/8] Correcting some processing comments --- .../src/main/java/androidx/media3/ui/PlayerControlView.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java b/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java index f159af3274f..29a0958b8d1 100644 --- a/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java +++ b/libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java @@ -193,8 +193,7 @@ public class PlayerControlView extends FrameLayout { static { - MediaLibraryInfo.registerModule("media3.ui"); // copybara:media3-only - // copybara:exo-only MediaLibraryInfo.registerModule("goog.exo.ui"); + MediaLibraryInfo.registerModule("media3.ui"); } /** @@ -263,7 +262,7 @@ public interface OnFullScreenModeChangedListener { private static final float[] PLAYBACK_SPEEDS = new float[] {0.25f, 0.5f, 0.75f, 1f, 1.25f, 1.5f, 2f}; // LINT.ThenChange("../../../../res/values/strings.xml:playback_speeds") - + private static final int SETTINGS_PLAYBACK_SPEED_POSITION = 0; private static final int SETTINGS_AUDIO_TRACK_SELECTION_POSITION = 1; private static final int SETTINGS_VIDEO_TRACK_SELECTION_POSITION = 2;