Support multiple overrides in TrackSelectionView and factor out Builder.

Supporting multiple overrides allows to select tracks from multiple groups, if
enabled. As more options are added, the creation of the dialog is moved to a
separate builder class.

PiperOrigin-RevId: 233366282
This commit is contained in:
tonihei 2019-02-11 10:01:34 +00:00 committed by Andrew Lewis
parent fc2710498a
commit abb53d7ce7
6 changed files with 389 additions and 136 deletions

View file

@ -60,6 +60,8 @@
`PlayerNotificationManager` has been fixed. Apps using
`DownloadNotificationUtil` should switch to using
`DownloadNotificationHelper`.
* Move creation of dialogs for `TrackSelectionView`s to
`TrackSelectionDialogBuilder` and add option to select multiple overrides.
### 2.9.5 ###

View file

@ -24,7 +24,6 @@ import android.net.Uri;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.annotation.Nullable;
import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageButton;
@ -45,11 +44,13 @@ import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.scheduler.Requirements;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.SelectionOverride;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelectionUtil;
import com.google.android.exoplayer2.ui.DefaultTrackNameProvider;
import com.google.android.exoplayer2.ui.TrackNameProvider;
import com.google.android.exoplayer2.ui.TrackSelectionView;
import com.google.android.exoplayer2.ui.TrackSelectionDialogBuilder;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.Util;
@ -229,8 +230,7 @@ public class DownloadTracker implements DownloadManager.Listener {
implements DownloadHelper.Callback,
DialogInterface.OnClickListener,
DialogInterface.OnDismissListener,
View.OnClickListener,
TrackSelectionView.DialogCallback {
View.OnClickListener {
private final DownloadHelper downloadHelper;
private final String name;
@ -290,29 +290,19 @@ public class DownloadTracker implements DownloadManager.Listener {
@Override
public void onClick(View v) {
Integer rendererIndex = (Integer) v.getTag();
TrackGroupArray trackGroupArray = mappedTrackInfo.getTrackGroups(rendererIndex);
String dialogTitle = getTrackTypeString(mappedTrackInfo.getRendererType(rendererIndex));
Pair<AlertDialog, TrackSelectionView> dialogPair =
TrackSelectionView.getDialog(
new TrackSelectionDialogBuilder(
dialog.getContext(),
dialogTitle,
mappedTrackInfo,
rendererIndex,
parameters,
/* callback= */ this);
dialogPair.second.setShowDisableOption(true);
dialogPair.second.setAllowAdaptiveSelections(false);
dialogPair.first.show();
}
// TrackSelectionView.DialogCallback implementation.
@Override
public void onTracksSelected(DefaultTrackSelector.Parameters parameters) {
for (int i = 0; i < downloadHelper.getPeriodCount(); i++) {
downloadHelper.replaceTrackSelections(/* periodIndex= */ i, parameters);
}
this.parameters = parameters;
updateSelectionList();
(isDisabled, overrides) -> updateTracks(rendererIndex, isDisabled, overrides))
.setShowDisableOption(true)
.setIsDisabled(parameters.getRendererDisabled(rendererIndex))
.setOverride(parameters.getSelectionOverride(rendererIndex, trackGroupArray))
.build()
.show();
}
// DialogInterface.OnClickListener implementation.
@ -332,6 +322,21 @@ public class DownloadTracker implements DownloadManager.Listener {
// Internal methods.
private void updateTracks(
int rendererIndex, boolean isDisabled, List<SelectionOverride> overrides) {
parameters =
TrackSelectionUtil.updateParametersWithOverride(
parameters,
rendererIndex,
mappedTrackInfo.getTrackGroups(rendererIndex),
isDisabled,
overrides.isEmpty() ? null : overrides.get(0));
for (int i = 0; i < downloadHelper.getPeriodCount(); i++) {
downloadHelper.replaceTrackSelections(/* periodIndex= */ i, parameters);
}
updateSelectionList();
}
private void updateSelectionList() {
selectionList.removeAllViews();
for (int i = 0; i < mappedTrackInfo.getRendererCount(); i++) {

View file

@ -16,7 +16,6 @@
package com.google.android.exoplayer2.demo;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
@ -68,7 +67,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.ui.DebugTextViewHelper;
import com.google.android.exoplayer2.ui.PlayerControlView;
import com.google.android.exoplayer2.ui.PlayerView;
import com.google.android.exoplayer2.ui.TrackSelectionView;
import com.google.android.exoplayer2.ui.TrackSelectionDialogBuilder;
import com.google.android.exoplayer2.ui.spherical.SphericalSurfaceView;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.HttpDataSource;
@ -307,11 +306,11 @@ public class PlayerActivity extends Activity
|| (rendererType == C.TRACK_TYPE_AUDIO
&& mappedTrackInfo.getTypeSupport(C.TRACK_TYPE_VIDEO)
== MappedTrackInfo.RENDERER_SUPPORT_NO_TRACKS);
Pair<AlertDialog, TrackSelectionView> dialogPair =
TrackSelectionView.getDialog(this, title, trackSelector, rendererIndex);
dialogPair.second.setShowDisableOption(true);
dialogPair.second.setAllowAdaptiveSelections(allowAdaptiveSelections);
dialogPair.first.show();
new TrackSelectionDialogBuilder(/* context= */ this, title, trackSelector, rendererIndex)
.setShowDisableOption(true)
.setAllowAdaptiveSelections(allowAdaptiveSelections)
.build()
.show();
}
}
}

View file

@ -19,9 +19,11 @@ import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.chunk.MediaChunk;
import com.google.android.exoplayer2.source.chunk.MediaChunkIterator;
import com.google.android.exoplayer2.source.chunk.MediaChunkListIterator;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.SelectionOverride;
import com.google.android.exoplayer2.trackselection.TrackSelection.Definition;
import com.google.android.exoplayer2.util.Assertions;
import java.util.Arrays;
@ -75,6 +77,34 @@ public final class TrackSelectionUtil {
return selections;
}
/**
* Updates {@link DefaultTrackSelector.Parameters} with an override.
*
* @param parameters The current {@link DefaultTrackSelector.Parameters} to build upon.
* @param rendererIndex The renderer index to update.
* @param trackGroupArray The {@link TrackGroupArray} of the renderer.
* @param isDisabled Whether the renderer should be set disabled.
* @param override An optional override for the renderer. If null, no override will be set and an
* existing override for this renderer will be cleared.
* @return The updated {@link DefaultTrackSelector.Parameters}.
*/
public static DefaultTrackSelector.Parameters updateParametersWithOverride(
DefaultTrackSelector.Parameters parameters,
int rendererIndex,
TrackGroupArray trackGroupArray,
boolean isDisabled,
@Nullable SelectionOverride override) {
DefaultTrackSelector.ParametersBuilder builder =
parameters
.buildUpon()
.clearSelectionOverrides(rendererIndex)
.setRendererDisabled(rendererIndex, isDisabled);
if (override != null) {
builder.setSelectionOverride(rendererIndex, trackGroupArray, override);
}
return builder.build();
}
/**
* Returns average bitrate for chunks in bits per second. Chunks are included in average until
* {@code maxDurationMs} or the first unknown length chunk.

View file

@ -0,0 +1,234 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.ui;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.SelectionOverride;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo;
import com.google.android.exoplayer2.trackselection.TrackSelectionUtil;
import com.google.android.exoplayer2.util.Assertions;
import java.util.Collections;
import java.util.List;
/** Builder for a dialog with a {@link TrackSelectionView}. */
public final class TrackSelectionDialogBuilder {
/** Callback which is invoked when a track selection has been made. */
public interface DialogCallback {
/**
* Called when tracks are selected.
*
* @param isDisabled Whether the renderer is disabled.
* @param overrides List of selected track selection overrides for the renderer.
*/
void onTracksSelected(boolean isDisabled, List<SelectionOverride> overrides);
}
private final Context context;
private final CharSequence title;
private final MappedTrackInfo mappedTrackInfo;
private final int rendererIndex;
private final DialogCallback callback;
private boolean allowAdaptiveSelections;
private boolean allowMultipleOverrides;
private boolean showDisableOption;
@Nullable private TrackNameProvider trackNameProvider;
private boolean isDisabled;
private List<SelectionOverride> overrides;
/**
* Creates a builder for a track selection dialog.
*
* @param context The context of the dialog.
* @param title The title of the dialog.
* @param mappedTrackInfo The {@link MappedTrackInfo} containing the track information.
* @param rendererIndex The renderer index in the {@code mappedTrackInfo} for which the track
* selection is shown.
* @param callback The {@link DialogCallback} invoked when a track selection has been made.
*/
public TrackSelectionDialogBuilder(
Context context,
CharSequence title,
MappedTrackInfo mappedTrackInfo,
int rendererIndex,
DialogCallback callback) {
this.context = context;
this.title = title;
this.mappedTrackInfo = mappedTrackInfo;
this.rendererIndex = rendererIndex;
this.callback = callback;
overrides = Collections.emptyList();
}
/**
* Creates a builder for a track selection dialog which automatically updates a {@link
* DefaultTrackSelector}.
*
* @param context The context of the dialog.
* @param title The title of the dialog.
* @param trackSelector A {@link DefaultTrackSelector} whose current selection is used to set up
* the dialog and which is updated when new tracks are selected in the dialog.
* @param rendererIndex The renderer index in the {@code trackSelector} for which the track
* selection is shown.
*/
public TrackSelectionDialogBuilder(
Context context, CharSequence title, DefaultTrackSelector trackSelector, int rendererIndex) {
this.context = context;
this.title = title;
this.mappedTrackInfo = Assertions.checkNotNull(trackSelector.getCurrentMappedTrackInfo());
this.rendererIndex = rendererIndex;
TrackGroupArray rendererTrackGroups = mappedTrackInfo.getTrackGroups(rendererIndex);
DefaultTrackSelector.Parameters selectionParameters = trackSelector.getParameters();
isDisabled = selectionParameters.getRendererDisabled(rendererIndex);
SelectionOverride override =
selectionParameters.getSelectionOverride(rendererIndex, rendererTrackGroups);
overrides = override == null ? Collections.emptyList() : Collections.singletonList(override);
this.callback =
(newIsDisabled, newOverrides) ->
trackSelector.setParameters(
TrackSelectionUtil.updateParametersWithOverride(
selectionParameters,
rendererIndex,
rendererTrackGroups,
newIsDisabled,
newOverrides.isEmpty() ? null : newOverrides.get(0)));
}
/**
* Sets whether the selection is initially shown as disabled.
*
* @param isDisabled Whether the selection is initially shown as disabled.
* @return This builder, for convenience.
*/
public TrackSelectionDialogBuilder setIsDisabled(boolean isDisabled) {
this.isDisabled = isDisabled;
return this;
}
/**
* Sets the initial selection override to show.
*
* @param override The initial override to show, or null for no override.
* @return This builder, for convenience.
*/
public TrackSelectionDialogBuilder setOverride(@Nullable SelectionOverride override) {
return setOverrides(
override == null ? Collections.emptyList() : Collections.singletonList(override));
}
/**
* Sets the list of initial selection overrides to show.
*
* <p>Note that only the first override will be used unless {@link
* #setAllowMultipleOverrides(boolean)} is set to {@code true}.
*
* @param overrides The list of initial overrides to show. There must be at most one override for
* each track group.
* @return This builder, for convenience.
*/
public TrackSelectionDialogBuilder setOverrides(List<SelectionOverride> overrides) {
this.overrides = overrides;
return this;
}
/**
* Sets whether adaptive selections (consisting of more than one track) can be made.
*
* <p>For the selection view to enable adaptive selection it is necessary both for this feature to
* be enabled, and for the target renderer to support adaptation between the available tracks.
*
* @param allowAdaptiveSelections Whether adaptive selection is enabled.
* @return This builder, for convenience.
*/
public TrackSelectionDialogBuilder setAllowAdaptiveSelections(boolean allowAdaptiveSelections) {
this.allowAdaptiveSelections = allowAdaptiveSelections;
return this;
}
/**
* Sets whether multiple overrides can be set and selected, i.e. tracks from multiple track groups
* can be selected.
*
* @param allowMultipleOverrides Whether multiple track selection overrides are allowed.
* @return This builder, for convenience.
*/
public TrackSelectionDialogBuilder setAllowMultipleOverrides(boolean allowMultipleOverrides) {
this.allowMultipleOverrides = allowMultipleOverrides;
return this;
}
/**
* Sets whether an option is available for disabling the renderer.
*
* @param showDisableOption Whether the disable option is shown.
* @return This builder, for convenience.
*/
public TrackSelectionDialogBuilder setShowDisableOption(boolean showDisableOption) {
this.showDisableOption = showDisableOption;
return this;
}
/**
* Sets the {@link TrackNameProvider} used to generate the user visible name of each track and
* updates the view with track names queried from the specified provider.
*
* @param trackNameProvider The {@link TrackNameProvider} to use, or null to use the default.
*/
public TrackSelectionDialogBuilder setTrackNameProvider(
@Nullable TrackNameProvider trackNameProvider) {
this.trackNameProvider = trackNameProvider;
return this;
}
/** Builds the dialog. */
public AlertDialog build() {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
// Inflate with the builder's context to ensure the correct style is used.
LayoutInflater dialogInflater = LayoutInflater.from(builder.getContext());
View dialogView = dialogInflater.inflate(R.layout.exo_track_selection_dialog, /* root= */ null);
TrackSelectionView selectionView = dialogView.findViewById(R.id.exo_track_selection_view);
selectionView.setAllowMultipleOverrides(allowMultipleOverrides);
selectionView.setAllowAdaptiveSelections(allowAdaptiveSelections);
selectionView.setShowDisableOption(showDisableOption);
if (trackNameProvider != null) {
selectionView.setTrackNameProvider(trackNameProvider);
}
selectionView.init(mappedTrackInfo, rendererIndex, isDisabled, overrides);
Dialog.OnClickListener okClickListener =
(dialog, which) ->
callback.onTracksSelected(selectionView.getIsDisabled(), selectionView.getOverrides());
return builder
.setTitle(title)
.setView(dialogView)
.setPositiveButton(android.R.string.ok, okClickListener)
.setNegativeButton(android.R.string.cancel, null)
.create();
}
}

View file

@ -15,14 +15,13 @@
*/
package com.google.android.exoplayer2.ui;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.res.TypedArray;
import android.support.annotation.AttrRes;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Pair;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.CheckedTextView;
@ -34,115 +33,49 @@ import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.SelectionOverride;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo;
import com.google.android.exoplayer2.util.Assertions;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/** A view for making track selections. */
public class TrackSelectionView extends LinearLayout {
/** Callback which is invoked when a track selection has been made. */
public interface DialogCallback {
/**
* Called when track are selected.
*
* @param parameters The {@link DefaultTrackSelector.Parameters} for the selected tracks.
*/
void onTracksSelected(DefaultTrackSelector.Parameters parameters);
}
private final int selectableItemBackgroundResourceId;
private final LayoutInflater inflater;
private final CheckedTextView disableView;
private final CheckedTextView defaultView;
private final ComponentListener componentListener;
private final SparseArray<SelectionOverride> overrides;
private boolean allowAdaptiveSelections;
private boolean allowMultipleOverrides;
private TrackNameProvider trackNameProvider;
private CheckedTextView[][] trackViews;
private @MonotonicNonNull MappedTrackInfo mappedTrackInfo;
private int rendererIndex;
private DefaultTrackSelector.Parameters parameters;
private TrackGroupArray trackGroups;
private boolean isDisabled;
@Nullable private SelectionOverride override;
/**
* Gets a pair consisting of a dialog and the {@link TrackSelectionView} that will be shown by it.
*
* <p>The dialog shows the current configuration of the provided {@code TrackSelector} and updates
* the parameters when closing the dialog.
*
* @param context The parent context.
* @param title The dialog's title.
* @param trackSelector The track selector.
* @param rendererIndex The index of the renderer.
* @return The dialog and the {@link TrackSelectionView} that will be shown by it.
*/
public static Pair<AlertDialog, TrackSelectionView> getDialog(
Context context, CharSequence title, DefaultTrackSelector trackSelector, int rendererIndex) {
return getDialog(
context,
title,
Assertions.checkNotNull(trackSelector.getCurrentMappedTrackInfo()),
rendererIndex,
trackSelector.getParameters(),
trackSelector::setParameters);
}
/**
* Gets a pair consisting of a dialog and the {@link TrackSelectionView} that will be shown by it.
*
* @param context The parent context.
* @param title The dialog's title.
* @param mappedTrackInfo The {@link MappedTrackInfo}.
* @param rendererIndex The index of the renderer.
* @param parameters The {@link DefaultTrackSelector.Parameters}.
* @param callback The {@link DialogCallback} invoked when the dialog is closed successfully.
* @return The dialog and the {@link TrackSelectionView} that will be shown by it.
*/
public static Pair<AlertDialog, TrackSelectionView> getDialog(
Context context,
CharSequence title,
MappedTrackInfo mappedTrackInfo,
int rendererIndex,
DefaultTrackSelector.Parameters parameters,
DialogCallback callback) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
// Inflate with the builder's context to ensure the correct style is used.
LayoutInflater dialogInflater = LayoutInflater.from(builder.getContext());
View dialogView = dialogInflater.inflate(R.layout.exo_track_selection_dialog, null);
TrackSelectionView selectionView = dialogView.findViewById(R.id.exo_track_selection_view);
selectionView.init(mappedTrackInfo, rendererIndex, parameters);
Dialog.OnClickListener okClickListener =
(dialog, which) -> callback.onTracksSelected(selectionView.getSelectionParameters());
AlertDialog dialog =
builder
.setTitle(title)
.setView(dialogView)
.setPositiveButton(android.R.string.ok, okClickListener)
.setNegativeButton(android.R.string.cancel, null)
.create();
return Pair.create(dialog, selectionView);
}
/** Creates a track selection view. */
public TrackSelectionView(Context context) {
this(context, null);
}
/** Creates a track selection view. */
public TrackSelectionView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
/** Creates a track selection view. */
@SuppressWarnings("nullness")
public TrackSelectionView(
Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
super(context, attrs, defStyleAttr);
overrides = new SparseArray<>();
TypedArray attributeArray =
context
.getTheme()
@ -153,7 +86,6 @@ public class TrackSelectionView extends LinearLayout {
inflater = LayoutInflater.from(context);
componentListener = new ComponentListener();
trackNameProvider = new DefaultTrackNameProvider(getResources());
parameters = DefaultTrackSelector.Parameters.DEFAULT;
trackGroups = TrackGroupArray.EMPTY;
// View for disabling the renderer.
@ -197,6 +129,24 @@ public class TrackSelectionView extends LinearLayout {
}
}
/**
* Sets whether tracks from multiple track groups can be selected. This results in multiple {@link
* SelectionOverride SelectionOverrides} to be returned by {@link #getOverrides()}.
*
* @param allowMultipleOverrides Whether multiple track selection overrides can be selected.
*/
public void setAllowMultipleOverrides(boolean allowMultipleOverrides) {
if (this.allowMultipleOverrides != allowMultipleOverrides) {
this.allowMultipleOverrides = allowMultipleOverrides;
if (!allowMultipleOverrides && overrides.size() > 1) {
for (int i = overrides.size() - 1; i > 0; i--) {
overrides.remove(i);
}
}
updateViews();
}
}
/**
* Sets whether an option is available for disabling the renderer.
*
@ -223,28 +173,42 @@ public class TrackSelectionView extends LinearLayout {
*
* @param mappedTrackInfo The {@link MappedTrackInfo}.
* @param rendererIndex The index of the renderer.
* @param parameters The {@link DefaultTrackSelector.Parameters}.
* @param isDisabled Whether the renderer should be initially shown as disabled.
* @param overrides List of initial overrides to be shown for this renderer. There must be at most
* one override for each track group. If {@link #setAllowMultipleOverrides(boolean)} hasn't
* been set to {@code true}, only the first override is used.
*/
public void init(
MappedTrackInfo mappedTrackInfo,
int rendererIndex,
DefaultTrackSelector.Parameters parameters) {
boolean isDisabled,
List<SelectionOverride> overrides) {
this.mappedTrackInfo = mappedTrackInfo;
this.rendererIndex = rendererIndex;
this.parameters = parameters;
this.isDisabled = isDisabled;
int maxOverrides = allowMultipleOverrides ? overrides.size() : Math.min(overrides.size(), 1);
for (int i = 0; i < maxOverrides; i++) {
SelectionOverride override = overrides.get(i);
this.overrides.put(override.groupIndex, override);
}
updateViews();
}
/** Returns the {@link DefaultTrackSelector.Parameters} for the current selection. */
public DefaultTrackSelector.Parameters getSelectionParameters() {
DefaultTrackSelector.ParametersBuilder parametersBuilder = parameters.buildUpon();
parametersBuilder.setRendererDisabled(rendererIndex, isDisabled);
if (override != null) {
parametersBuilder.setSelectionOverride(rendererIndex, trackGroups, override);
} else {
parametersBuilder.clearSelectionOverrides(rendererIndex);
/** Returns whether the renderer is disabled. */
public boolean getIsDisabled() {
return isDisabled;
}
/**
* Returns the list of selected track selection overrides. There will be at most one override for
* each track group.
*/
public List<SelectionOverride> getOverrides() {
List<SelectionOverride> overrideList = new ArrayList<>(overrides.size());
for (int i = 0; i < overrides.size(); i++) {
overrideList.add(overrides.valueAt(i));
}
return parametersBuilder.build();
return overrideList;
}
// Private methods.
@ -266,14 +230,19 @@ public class TrackSelectionView extends LinearLayout {
trackGroups = mappedTrackInfo.getTrackGroups(rendererIndex);
isDisabled = parameters.getRendererDisabled(rendererIndex);
override = parameters.getSelectionOverride(rendererIndex, trackGroups);
// Add per-track views.
if (trackGroups.length == 1 && trackGroups.get(0).length == 1) {
// Don't add group selection if there is nothing to select from.
trackViews = new CheckedTextView[0][0];
updateViewStates();
return;
}
trackViews = new CheckedTextView[trackGroups.length][];
boolean enableMultipleChoiceForMultipleOverrides =
allowMultipleOverrides && trackGroups.length > 1;
for (int groupIndex = 0; groupIndex < trackGroups.length; groupIndex++) {
TrackGroup group = trackGroups.get(groupIndex);
boolean enableAdaptiveSelections =
boolean enableMultipleChoiceForAdaptiveSelections =
allowAdaptiveSelections
&& trackGroups.get(groupIndex).length > 1
&& mappedTrackInfo.getAdaptiveSupport(rendererIndex, groupIndex, false)
@ -284,7 +253,7 @@ public class TrackSelectionView extends LinearLayout {
addView(inflater.inflate(R.layout.exo_list_divider, this, false));
}
int trackViewLayoutId =
enableAdaptiveSelections
enableMultipleChoiceForAdaptiveSelections || enableMultipleChoiceForMultipleOverrides
? android.R.layout.simple_list_item_multiple_choice
: android.R.layout.simple_list_item_single_choice;
CheckedTextView trackView =
@ -310,11 +279,11 @@ public class TrackSelectionView extends LinearLayout {
private void updateViewStates() {
disableView.setChecked(isDisabled);
defaultView.setChecked(!isDisabled && override == null);
defaultView.setChecked(!isDisabled && overrides.size() == 0);
for (int i = 0; i < trackViews.length; i++) {
SelectionOverride override = overrides.get(i);
for (int j = 0; j < trackViews[i].length; j++) {
trackViews[i][j].setChecked(
override != null && override.groupIndex == i && override.containsTrack(j));
trackViews[i][j].setChecked(override != null && override.containsTrack(j));
}
}
}
@ -332,12 +301,12 @@ public class TrackSelectionView extends LinearLayout {
private void onDisableViewClicked() {
isDisabled = true;
override = null;
overrides.clear();
}
private void onDefaultViewClicked() {
isDisabled = false;
override = null;
overrides.clear();
}
private void onTrackViewClicked(View view) {
@ -346,9 +315,21 @@ public class TrackSelectionView extends LinearLayout {
Pair<Integer, Integer> tag = (Pair<Integer, Integer>) view.getTag();
int groupIndex = tag.first;
int trackIndex = tag.second;
if (override == null || override.groupIndex != groupIndex || !allowAdaptiveSelections) {
// A new override is being started.
override = new SelectionOverride(groupIndex, trackIndex);
SelectionOverride override = overrides.get(groupIndex);
if (!allowMultipleOverrides && override == null && overrides.size() > 0) {
// A new override is being started and we don't allow multiple overrides.
overrides.clear();
}
if (override == null || !allowAdaptiveSelections) {
// Update override for current group.
if (((CheckedTextView) view).isChecked()) {
overrides.remove(groupIndex);
if (overrides.size() == 0) {
isDisabled = true;
}
} else {
overrides.put(groupIndex, new SelectionOverride(groupIndex, trackIndex));
}
} else {
// An existing override is being modified.
int overrideLength = override.length;
@ -357,15 +338,17 @@ public class TrackSelectionView extends LinearLayout {
// Remove the track from the override.
if (overrideLength == 1) {
// The last track is being removed, so the override becomes empty.
override = null;
isDisabled = true;
overrides.remove(groupIndex);
if (overrides.size() == 0) {
isDisabled = true;
}
} else {
int[] tracks = getTracksRemoving(overrideTracks, trackIndex);
override = new SelectionOverride(groupIndex, tracks);
overrides.put(groupIndex, new SelectionOverride(groupIndex, tracks));
}
} else {
int[] tracks = getTracksAdding(overrideTracks, trackIndex);
override = new SelectionOverride(groupIndex, tracks);
overrides.put(groupIndex, new SelectionOverride(groupIndex, tracks));
}
}
}