From f002efc5c190008d8b2339f5c0cd2b5fec07c3fa Mon Sep 17 00:00:00 2001 From: FongMi Date: Sat, 7 Jan 2023 13:29:51 +0800 Subject: [PATCH] Support track - part 4 --- .../tv/ui/activity/DetailActivity.java | 10 +- .../android/tv/ui/activity/LiveActivity.java | 4 +- .../com/fongmi/android/tv/bean/Track.java | 23 +- .../tv/ui/custom/TrackSelectionDialog.java | 310 +++++------------- .../tv/ui/custom/TrackSelectionDialog2.java | 111 ------- 5 files changed, 90 insertions(+), 368 deletions(-) delete mode 100644 app/src/main/java/com/fongmi/android/tv/ui/custom/TrackSelectionDialog2.java diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/DetailActivity.java b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/DetailActivity.java index fecdedcba..cc402a4d7 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/DetailActivity.java +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/DetailActivity.java @@ -40,7 +40,6 @@ import com.fongmi.android.tv.player.ExoUtil; import com.fongmi.android.tv.player.Players; import com.fongmi.android.tv.ui.custom.CustomKeyDownVod; import com.fongmi.android.tv.ui.custom.TrackSelectionDialog; -import com.fongmi.android.tv.ui.custom.TrackSelectionDialog2; import com.fongmi.android.tv.ui.custom.dialog.DescDialog; import com.fongmi.android.tv.ui.presenter.ArrayPresenter; import com.fongmi.android.tv.ui.presenter.EpisodePresenter; @@ -194,7 +193,6 @@ public class DetailActivity extends BaseActivity implements CustomKeyDownVod.Lis mBinding.control.decode.setOnClickListener(view -> onDecode()); mBinding.control.ending.setOnClickListener(view -> onEnding()); mBinding.control.opening.setOnClickListener(view -> onOpening()); - //mBinding.control.opening.setOnClickListener(view -> onTracks()); mBinding.control.replay.setOnClickListener(view -> getPlayer(true)); mBinding.control.speed.setOnLongClickListener(view -> onSpeedLong()); mBinding.control.ending.setOnLongClickListener(view -> onEndingReset()); @@ -585,13 +583,7 @@ public class DetailActivity extends BaseActivity implements CustomKeyDownVod.Lis private void onTracks(View view) { int type = Integer.parseInt(view.getTag().toString()); - TrackSelectionDialog2.create(this).player(mPlayers).type(type).show(); - hideControl(); - } - - private void onTracks() { - TrackSelectionDialog.createForPlayer(mPlayers.exo(), dialog -> { - }).show(getSupportFragmentManager(), "tracks"); + TrackSelectionDialog.create(this).player(mPlayers).type(type).show(); hideControl(); } diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/LiveActivity.java b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/LiveActivity.java index 03d6f44d5..f1c457c8b 100644 --- a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/LiveActivity.java +++ b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/LiveActivity.java @@ -35,7 +35,7 @@ import com.fongmi.android.tv.player.source.TVBus; import com.fongmi.android.tv.player.source.ZLive; import com.fongmi.android.tv.ui.custom.CustomKeyDownLive; import com.fongmi.android.tv.ui.custom.CustomLiveListView; -import com.fongmi.android.tv.ui.custom.TrackSelectionDialog2; +import com.fongmi.android.tv.ui.custom.TrackSelectionDialog; import com.fongmi.android.tv.ui.custom.dialog.LiveDialog; import com.fongmi.android.tv.ui.custom.dialog.PassDialog; import com.fongmi.android.tv.ui.presenter.ChannelPresenter; @@ -320,7 +320,7 @@ public class LiveActivity extends BaseActivity implements GroupPresenter.OnClick private void onTracks(View view) { int type = Integer.parseInt(view.getTag().toString()); - TrackSelectionDialog2.create(this).player(mPlayers).type(type).show(); + TrackSelectionDialog.create(this).player(mPlayers).type(type).show(); hideControl(); } diff --git a/app/src/main/java/com/fongmi/android/tv/bean/Track.java b/app/src/main/java/com/fongmi/android/tv/bean/Track.java index 2d35957a2..6fe1c729f 100644 --- a/app/src/main/java/com/fongmi/android/tv/bean/Track.java +++ b/app/src/main/java/com/fongmi/android/tv/bean/Track.java @@ -2,14 +2,13 @@ package com.fongmi.android.tv.bean; public class Track { + private int group; + private int track; private String name; - private int index; - private int playerType; private boolean selected; - public Track(int playerType, String name) { + public Track(String name) { this.name = name; - this.playerType = playerType; } public String getName() { @@ -20,20 +19,20 @@ public class Track { this.name = name; } - public int getIndex() { - return index; + public int getGroup() { + return group; } - public void setIndex(int index) { - this.index = index; + public void setGroup(int group) { + this.group = group; } - public int getPlayerType() { - return playerType; + public int getTrack() { + return track; } - public void setPlayerType(int playerType) { - this.playerType = playerType; + public void setTrack(int track) { + this.track = track; } public boolean isSelected() { diff --git a/app/src/main/java/com/fongmi/android/tv/ui/custom/TrackSelectionDialog.java b/app/src/main/java/com/fongmi/android/tv/ui/custom/TrackSelectionDialog.java index 9ed693515..17566dc1a 100644 --- a/app/src/main/java/com/fongmi/android/tv/ui/custom/TrackSelectionDialog.java +++ b/app/src/main/java/com/fongmi/android/tv/ui/custom/TrackSelectionDialog.java @@ -1,272 +1,114 @@ package com.fongmi.android.tv.ui.custom; -import android.app.Dialog; -import android.content.DialogInterface; -import android.content.res.Resources; -import android.os.Bundle; -import android.util.SparseArray; +import android.app.Activity; import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; +import android.view.WindowManager; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.appcompat.app.AppCompatDialog; -import androidx.fragment.app.DialogFragment; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentManager; -import androidx.fragment.app.FragmentPagerAdapter; -import androidx.viewpager.widget.ViewPager; +import androidx.appcompat.app.AlertDialog; -import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.ExoPlayer; -import com.google.android.exoplayer2.Player; +import com.fongmi.android.tv.bean.Track; +import com.fongmi.android.tv.databinding.DialogTrackBinding; +import com.fongmi.android.tv.player.Players; +import com.fongmi.android.tv.ui.adapter.TrackAdapter; +import com.fongmi.android.tv.utils.ResUtil; import com.google.android.exoplayer2.Tracks; -import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.trackselection.TrackSelectionOverride; -import com.google.android.exoplayer2.trackselection.TrackSelectionParameters; -import com.google.android.exoplayer2.ui.R; -import com.google.android.exoplayer2.ui.TrackSelectionView; -import com.google.android.material.tabs.TabLayout; -import com.google.common.collect.ImmutableList; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; -public final class TrackSelectionDialog extends DialogFragment { +import tv.danmaku.ijk.media.player.misc.IjkTrackInfo; - public static final ImmutableList SUPPORTED_TRACK_TYPES = ImmutableList.of(C.TRACK_TYPE_VIDEO, C.TRACK_TYPE_AUDIO, C.TRACK_TYPE_TEXT); - private final SparseArray tabFragments; - private final ArrayList tabTrackTypes; - private DialogInterface.OnClickListener onClickListener; - private DialogInterface.OnDismissListener onDismissListener; +public final class TrackSelectionDialog implements TrackAdapter.OnClickListener { - public TrackSelectionDialog() { - tabFragments = new SparseArray<>(); - tabTrackTypes = new ArrayList<>(); - setRetainInstance(true); - } - - /** - * Returns whether a track selection dialog will have content to display if initialized with the - * specified {@link Player}. - */ - public static void setVisible(ExoPlayer player, View view) { - view.setVisibility(willHaveContent(player.getCurrentTracks()) ? View.VISIBLE : View.GONE); - } + private final DialogTrackBinding binding; + private final TrackNameProvider provider; + private final TrackAdapter adapter; + private final AlertDialog dialog; + private Players player; + private int type; - /** - * Returns whether a track selection dialog will have content to display if initialized with the - * specified {@link Tracks}. - */ - public static boolean willHaveContent(Tracks tracks) { - for (Tracks.Group trackGroup : tracks.getGroups()) { - if (SUPPORTED_TRACK_TYPES.contains(trackGroup.getType())) { - return true; - } - } - return false; + public static TrackSelectionDialog create(Activity activity) { + return new TrackSelectionDialog(activity); } - /** - * Creates a dialog for a given {@link Player}, whose parameters will be automatically updated - * when tracks are selected. - * - * @param player The {@link Player}. - * @param onDismissListener A {@link DialogInterface.OnDismissListener} to call when the dialog is - * dismissed. - */ - public static TrackSelectionDialog createForPlayer(Player player, DialogInterface.OnDismissListener onDismissListener) { - return createForTracksAndParameters(player.getCurrentTracks(), player.getTrackSelectionParameters(), true, false, player::setTrackSelectionParameters, onDismissListener); + public TrackSelectionDialog(Activity activity) { + this.binding = DialogTrackBinding.inflate(LayoutInflater.from(activity)); + this.dialog = new MaterialAlertDialogBuilder(activity).setView(binding.getRoot()).create(); + this.adapter = new TrackAdapter(this); + this.provider = new TrackNameProvider(); } - /** - * Creates a dialog for given {@link Tracks} and {@link TrackSelectionParameters}. - * - * @param tracks The {@link Tracks} describing the tracks to display. - * @param trackSelectionParameters The initial {@link TrackSelectionParameters}. - * @param allowAdaptiveSelections Whether adaptive selections (consisting of more than one track) - * can be made. - * @param allowMultipleOverrides Whether tracks from multiple track groups can be selected. - * @param trackSelectionListener Called when tracks are selected. - * @param onDismissListener {@link DialogInterface.OnDismissListener} called when the dialog is - * dismissed. - */ - public static TrackSelectionDialog createForTracksAndParameters(Tracks tracks, TrackSelectionParameters trackSelectionParameters, boolean allowAdaptiveSelections, boolean allowMultipleOverrides, TrackSelectionListener trackSelectionListener, DialogInterface.OnDismissListener onDismissListener) { - TrackSelectionDialog trackSelectionDialog = new TrackSelectionDialog(); - trackSelectionDialog.init(tracks, trackSelectionParameters, allowAdaptiveSelections, allowMultipleOverrides, (dialog, which) -> { - TrackSelectionParameters.Builder builder = trackSelectionParameters.buildUpon(); - for (int i = 0; i < SUPPORTED_TRACK_TYPES.size(); i++) { - int trackType = SUPPORTED_TRACK_TYPES.get(i); - builder.setTrackTypeDisabled(trackType, trackSelectionDialog.getIsDisabled(trackType)); - builder.clearOverridesOfType(trackType); - Map overrides = trackSelectionDialog.getOverrides(trackType); - for (TrackSelectionOverride override : overrides.values()) builder.addOverride(override); - } - trackSelectionListener.onTracksSelected(builder.build()); - }, onDismissListener); - return trackSelectionDialog; + public TrackSelectionDialog type(int type) { + this.type = type; + return this; } - private static String getTrackTypeString(Resources resources, @C.TrackType int trackType) { - switch (trackType) { - case C.TRACK_TYPE_VIDEO: - return resources.getString(R.string.exo_track_selection_title_video); - case C.TRACK_TYPE_AUDIO: - return resources.getString(R.string.exo_track_selection_title_audio); - case C.TRACK_TYPE_TEXT: - return resources.getString(R.string.exo_track_selection_title_text); - default: - throw new IllegalArgumentException(); - } + public TrackSelectionDialog player(Players player) { + this.player = player; + return this; } - private void init(Tracks tracks, TrackSelectionParameters trackSelectionParameters, boolean allowAdaptiveSelections, boolean allowMultipleOverrides, DialogInterface.OnClickListener onClickListener, DialogInterface.OnDismissListener onDismissListener) { - this.onClickListener = onClickListener; - this.onDismissListener = onDismissListener; - for (int i = 0; i < SUPPORTED_TRACK_TYPES.size(); i++) { - @C.TrackType int trackType = SUPPORTED_TRACK_TYPES.get(i); - ArrayList trackGroups = new ArrayList<>(); - for (Tracks.Group trackGroup : tracks.getGroups()) { - if (trackGroup.getType() == trackType) { - trackGroups.add(trackGroup); - } - } - if (!trackGroups.isEmpty()) { - TrackSelectionViewFragment tabFragment = new TrackSelectionViewFragment(); - tabFragment.init(trackGroups, trackSelectionParameters.disabledTrackTypes.contains(trackType), trackSelectionParameters.overrides, allowAdaptiveSelections, allowMultipleOverrides); - tabFragments.put(trackType, tabFragment); - tabTrackTypes.add(trackType); - } - } + public void show() { + setRecyclerView(); + setDialog(); } - /** - * Returns whether the disabled option is selected for the specified track type. - * - * @param trackType The track type. - * @return Whether the disabled option is selected for the track type. - */ - public boolean getIsDisabled(int trackType) { - TrackSelectionViewFragment trackView = tabFragments.get(trackType); - return trackView != null && trackView.isDisabled; + private void setRecyclerView() { + binding.recycler.setHasFixedSize(true); + binding.recycler.addItemDecoration(new SpaceItemDecoration(1, 16)); + binding.recycler.setAdapter(adapter.addAll(getTrack())); + binding.recycler.scrollToPosition(adapter.getSelected()); } - /** - * Returns the selected track overrides for the specified track type. - * - * @param trackType The track type. - * @return The track overrides for the track type. - */ - public Map getOverrides(int trackType) { - TrackSelectionViewFragment trackView = tabFragments.get(trackType); - return trackView == null ? Collections.emptyMap() : trackView.overrides; - } - - @NonNull - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - Dialog dialog = new AppCompatDialog(getActivity()); + private void setDialog() { + WindowManager.LayoutParams params = dialog.getWindow().getAttributes(); + params.width = (int) (ResUtil.getScreenWidthPx() * 0.4f); + dialog.getWindow().setAttributes(params); dialog.getWindow().setDimAmount(0); - return dialog; + dialog.show(); } - @Override - public void onDismiss(@NonNull DialogInterface dialog) { - super.onDismiss(dialog); - onDismissListener.onDismiss(dialog); + private List getTrack() { + List items = new ArrayList<>(); + if (player.isExo()) addExoTrack(items); + if (player.isIjk()) addIjkTrack(items); + return items; } - @Override - public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - View dialogView = inflater.inflate(com.fongmi.android.tv.R.layout.dialog_tracks, container, false); - TabLayout tabLayout = dialogView.findViewById(com.fongmi.android.tv.R.id.track_selection_dialog_tab_layout); - ViewPager viewPager = dialogView.findViewById(com.fongmi.android.tv.R.id.track_selection_dialog_view_pager); - TextView cancelButton = dialogView.findViewById(com.fongmi.android.tv.R.id.track_selection_dialog_cancel_button); - TextView okButton = dialogView.findViewById(com.fongmi.android.tv.R.id.track_selection_dialog_ok_button); - viewPager.setAdapter(new FragmentAdapter(getChildFragmentManager())); - tabLayout.setupWithViewPager(viewPager); - tabLayout.setVisibility(tabFragments.size() > 1 ? View.VISIBLE : View.GONE); - cancelButton.setOnClickListener(view -> dismiss()); - okButton.setOnClickListener(view -> { - onClickListener.onClick(getDialog(), DialogInterface.BUTTON_POSITIVE); - dismiss(); - }); - return dialogView; - } - - public interface TrackSelectionListener { - - void onTracksSelected(TrackSelectionParameters trackSelectionParameters); - } - - /** - * Fragment to show a track selection in tab of the track selection dialog. - */ - public static final class TrackSelectionViewFragment extends Fragment implements TrackSelectionView.TrackSelectionListener { - - private List trackGroups; - private boolean allowAdaptiveSelections; - private boolean allowMultipleOverrides; - Map overrides; - boolean isDisabled; - - public TrackSelectionViewFragment() { - setRetainInstance(true); - } - - public void init(List trackGroups, boolean isDisabled, Map overrides, boolean allowAdaptiveSelections, boolean allowMultipleOverrides) { - this.trackGroups = trackGroups; - this.isDisabled = isDisabled; - this.allowAdaptiveSelections = allowAdaptiveSelections; - this.allowMultipleOverrides = allowMultipleOverrides; - // TrackSelectionView does this filtering internally, but we need to do it here as well to - // handle the case where the TrackSelectionView is never created. - this.overrides = new HashMap<>(TrackSelectionView.filterOverrides(overrides, trackGroups, allowMultipleOverrides)); - } - - @Override - public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.exo_track_selection_dialog, container, /* attachToRoot= */ false); - TrackSelectionView trackSelectionView = rootView.findViewById(R.id.exo_track_selection_view); - trackSelectionView.setShowDisableOption(true); - trackSelectionView.setAllowMultipleOverrides(allowMultipleOverrides); - trackSelectionView.setAllowAdaptiveSelections(allowAdaptiveSelections); - trackSelectionView.init(trackGroups, isDisabled, overrides, null, this); - return rootView; - } - - @Override - public void onTrackSelectionChanged(boolean isDisabled, @NonNull Map overrides) { - this.isDisabled = isDisabled; - this.overrides = overrides; + private void addExoTrack(List items) { + List groups = player.exo().getCurrentTracks().getGroups(); + for (int i = 0; i < groups.size(); i++) { + Tracks.Group trackGroup = groups.get(i); + if (trackGroup.getType() != type) continue; + for (int j = 0; j < trackGroup.length; j++) { + Track item = new Track(provider.getTrackName(trackGroup.getTrackFormat(j))); + item.setSelected(trackGroup.isTrackSelected(j)); + item.setGroup(i); + item.setTrack(j); + items.add(item); + } } } - private final class FragmentAdapter extends FragmentPagerAdapter { - - public FragmentAdapter(FragmentManager fragmentManager) { - super(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); - } - - @NonNull - @Override - public Fragment getItem(int position) { - return tabFragments.get(tabTrackTypes.get(position)); - } - - @Override - public int getCount() { - return tabTrackTypes.size(); + private void addIjkTrack(List items) { + int track = player.ijk().getSelectedTrack(type); + IjkTrackInfo[] trackInfos = player.ijk().getTrackInfo(); + for (int i = 0; i < trackInfos.length; i++) { + IjkTrackInfo trackInfo = trackInfos[i]; + if (trackInfo.getTrackType() != type) continue; + Track item = new Track(provider.getTrackName(trackInfo)); + item.setSelected(track == i); + item.setTrack(i); + items.add(item); } + } - @Override - public CharSequence getPageTitle(int position) { - return getTrackTypeString(getResources(), tabTrackTypes.get(position)); - } + @Override + public void onItemClick(Track item) { + if (player.isExo()) player.exo().setTrackSelectionParameters(player.exo().getTrackSelectionParameters().buildUpon().setOverrideForType(new TrackSelectionOverride(player.exo().getCurrentTracks().getGroups().get(item.getGroup()).getMediaTrackGroup(), item.getTrack())).build()); + if (player.isIjk()) player.ijk().selectTrack(item.getTrack()); + dialog.dismiss(); } } \ No newline at end of file diff --git a/app/src/main/java/com/fongmi/android/tv/ui/custom/TrackSelectionDialog2.java b/app/src/main/java/com/fongmi/android/tv/ui/custom/TrackSelectionDialog2.java deleted file mode 100644 index f481f3db0..000000000 --- a/app/src/main/java/com/fongmi/android/tv/ui/custom/TrackSelectionDialog2.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.fongmi.android.tv.ui.custom; - -import android.app.Activity; -import android.view.LayoutInflater; -import android.view.WindowManager; - -import androidx.appcompat.app.AlertDialog; - -import com.fongmi.android.tv.bean.Track; -import com.fongmi.android.tv.databinding.DialogTrackBinding; -import com.fongmi.android.tv.player.Players; -import com.fongmi.android.tv.ui.adapter.TrackAdapter; -import com.fongmi.android.tv.utils.ResUtil; -import com.google.android.exoplayer2.Tracks; -import com.google.android.material.dialog.MaterialAlertDialogBuilder; - -import java.util.ArrayList; -import java.util.List; - -import tv.danmaku.ijk.media.player.misc.IjkTrackInfo; - -public final class TrackSelectionDialog2 implements TrackAdapter.OnClickListener { - - private final DialogTrackBinding binding; - private final TrackNameProvider provider; - private final TrackAdapter adapter; - private final AlertDialog dialog; - private Players player; - private int type; - - public static TrackSelectionDialog2 create(Activity activity) { - return new TrackSelectionDialog2(activity); - } - - public TrackSelectionDialog2(Activity activity) { - this.binding = DialogTrackBinding.inflate(LayoutInflater.from(activity)); - this.dialog = new MaterialAlertDialogBuilder(activity).setView(binding.getRoot()).create(); - this.adapter = new TrackAdapter(this); - this.provider = new TrackNameProvider(); - } - - public TrackSelectionDialog2 type(int type) { - this.type = type; - return this; - } - - public TrackSelectionDialog2 player(Players player) { - this.player = player; - return this; - } - - public void show() { - setRecyclerView(); - setDialog(); - } - - private void setRecyclerView() { - binding.recycler.setHasFixedSize(true); - binding.recycler.addItemDecoration(new SpaceItemDecoration(1, 16)); - binding.recycler.setAdapter(adapter.addAll(getTrack())); - binding.recycler.scrollToPosition(adapter.getSelected()); - } - - private void setDialog() { - WindowManager.LayoutParams params = dialog.getWindow().getAttributes(); - params.width = (int) (ResUtil.getScreenWidthPx() * 0.4f); - dialog.getWindow().setAttributes(params); - dialog.getWindow().setDimAmount(0); - dialog.show(); - } - - private List getTrack() { - List items = new ArrayList<>(); - if (player.isExo()) addExoTrack(items); - if (player.isIjk()) addIjkTrack(items); - return items; - } - - private void addExoTrack(List items) { - for (Tracks.Group trackGroup : player.exo().getCurrentTracks().getGroups()) { - if (trackGroup.getType() != type) continue; - for (int i = 0; i < trackGroup.length; i++) { - items.add(new Track(player.getPlayer(), provider.getTrackName(trackGroup.getTrackFormat(i)))); - } - } - } - - private void addIjkTrack(List items) { - int track = player.ijk().getSelectedTrack(type); - IjkTrackInfo[] trackInfos = player.ijk().getTrackInfo(); - for (int index = 0; index < trackInfos.length; index++) { - IjkTrackInfo trackInfo = trackInfos[index]; - if (trackInfo.getTrackType() != type) continue; - Track item = new Track(player.getPlayer(), provider.getTrackName(trackInfo)); - item.setSelected(track == index); - item.setIndex(index); - items.add(item); - } - } - - @Override - public void onItemClick(Track item) { - if (player.isExo()) { - - } - if (player.isIjk()) { - player.ijk().selectTrack(item.getIndex()); - } - dialog.dismiss(); - } -} \ No newline at end of file