From e9cdf4d5a6992e34036cf1a3081e7aad178cd30a Mon Sep 17 00:00:00 2001 From: Yuriy Liskov Date: Fri, 5 Aug 2022 01:30:03 +0300 Subject: [PATCH] player: subtitle style + refactor --- .../playback/managers/PlayerUIManager.java | 3 + .../exoplayer/other/SubtitleManager.java | 31 +++---- .../common/misc/TickleManager.java | 35 ++------ .../common/prefs/DataChangeBase.java | 9 +- .../common/prefs/PlayerData.java | 89 ++++++++++--------- .../common/utils/AppDialogUtil.java | 17 ++-- .../common/utils/WeakHashSet.java | 59 ++++++++++++ 7 files changed, 135 insertions(+), 108 deletions(-) create mode 100644 common/src/main/java/com/liskovsoft/smartyoutubetv2/common/utils/WeakHashSet.java diff --git a/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/managers/PlayerUIManager.java b/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/managers/PlayerUIManager.java index d95e4bc38..e35e4ec1b 100644 --- a/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/managers/PlayerUIManager.java +++ b/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/app/models/playback/managers/PlayerUIManager.java @@ -144,6 +144,9 @@ public class PlayerUIManager extends PlayerEventListenerHelper implements Metada option -> getController().setFormat(UiOptionItem.toFormat(option)), getActivity().getString(R.string.subtitles_disabled))); + OptionCategory stylesCategory = AppDialogUtil.createSubtitleStylesCategory(getActivity(), mPlayerData); + settingsPresenter.appendRadioCategory(stylesCategory.title, stylesCategory.options); + settingsPresenter.showDialog(subtitlesCategoryTitle, this::setSubtitleButtonState); } diff --git a/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/exoplayer/other/SubtitleManager.java b/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/exoplayer/other/SubtitleManager.java index f66c5050c..b7ccb9459 100644 --- a/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/exoplayer/other/SubtitleManager.java +++ b/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/exoplayer/other/SubtitleManager.java @@ -51,15 +51,12 @@ public class SubtitleManager implements TextOutput { } } - public interface OnSelectSubtitleStyle { - void onSelectSubtitleStyle(SubtitleStyle style); - } - public SubtitleManager(Activity activity, int subViewId) { mContext = activity; mSubtitleView = activity.findViewById(subViewId); mPrefs = AppPrefs.instance(activity); mPlayerData = PlayerData.instance(activity); + mPlayerData.setOnChange(this::configureSubtitleView); configureSubtitleView(); } @@ -70,25 +67,25 @@ public class SubtitleManager implements TextOutput { } } - public List getSubtitleStyles() { - return mSubtitleStyles; - } - - public SubtitleStyle getSubtitleStyle() { - return mPlayerData.getSubtitleStyle(); - } - - public void setSubtitleStyle(SubtitleStyle subtitleStyle) { - mPlayerData.setSubtitleStyle(subtitleStyle); - configureSubtitleView(); - } - public void show(boolean show) { if (mSubtitleView != null) { mSubtitleView.setVisibility(show ? View.VISIBLE : View.GONE); } } + private List getSubtitleStyles() { + return mSubtitleStyles; + } + + private SubtitleStyle getSubtitleStyle() { + return mPlayerData.getSubtitleStyle(); + } + + private void setSubtitleStyle(SubtitleStyle subtitleStyle) { + mPlayerData.setSubtitleStyle(subtitleStyle); + configureSubtitleView(); + } + private List forceCenterAlignment(List cues) { List result = new ArrayList<>(); diff --git a/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/misc/TickleManager.java b/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/misc/TickleManager.java index cec0cab3f..30ede9281 100644 --- a/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/misc/TickleManager.java +++ b/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/misc/TickleManager.java @@ -2,18 +2,14 @@ package com.liskovsoft.smartyoutubetv2.common.misc; import android.os.Handler; import android.os.Looper; -import com.liskovsoft.sharedutils.helpers.Helpers; - -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.List; +import com.liskovsoft.smartyoutubetv2.common.utils.WeakHashSet; public class TickleManager { private static TickleManager sInstance; private final Handler mHandler = new Handler(Looper.getMainLooper()); private final Runnable mUpdateHandler = this::updateTickle; // Usually listener is a view. So use weak refs to not hold it forever. - private final List> mListeners = new ArrayList<>(); + private final WeakHashSet mListeners = new WeakHashSet<>(); private boolean mIsEnabled = true; private static final long DEFAULT_INTERVAL_MS = 60_000; private long mIntervalMs = DEFAULT_INTERVAL_MS; @@ -34,9 +30,7 @@ public class TickleManager { } public void addListener(TickleListener listener) { - if (listener != null && !contains(listener)) { - cleanup(); - mListeners.add(new WeakReference<>(listener)); + if (mListeners.add(listener)) { if (mListeners.size() == 1) { // periodic callback not started yet updateTickle(); } else if (isEnabled()) { @@ -46,9 +40,7 @@ public class TickleManager { } public void removeListener(TickleListener listener) { - if (listener != null) { - remove(listener); - } + mListeners.remove(listener); } public void setEnabled(boolean enabled) { @@ -82,25 +74,8 @@ public class TickleManager { mHandler.removeCallbacks(mUpdateHandler); if (isEnabled() && !mListeners.isEmpty()) { - for (WeakReference listener : mListeners) { - if (listener.get() != null) { - listener.get().onTickle(); - } - } - + mListeners.forEach(TickleListener::onTickle); mHandler.postDelayed(mUpdateHandler, mIntervalMs); } } - - private boolean contains(TickleListener listener) { - return Helpers.containsIf(mListeners, item -> listener.equals(item.get())); - } - - private void remove(TickleListener listener) { - Helpers.removeIf(mListeners, item -> listener.equals(item.get())); - } - - private void cleanup() { - Helpers.removeIf(mListeners, item -> item.get() == null); - } } diff --git a/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/prefs/DataChangeBase.java b/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/prefs/DataChangeBase.java index 2b991eeb1..0f9fb2211 100644 --- a/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/prefs/DataChangeBase.java +++ b/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/prefs/DataChangeBase.java @@ -1,10 +1,9 @@ package com.liskovsoft.smartyoutubetv2.common.prefs; -import java.util.HashSet; -import java.util.Set; +import com.liskovsoft.smartyoutubetv2.common.utils.WeakHashSet; public class DataChangeBase { - private final Set mOnChangeList = new HashSet<>(); + private final WeakHashSet mOnChangeList = new WeakHashSet<>(); public void setOnChange(Runnable callback) { mOnChangeList.add(callback); @@ -15,8 +14,6 @@ public class DataChangeBase { } protected void persistState() { - for (Runnable callback : mOnChangeList) { - callback.run(); - } + mOnChangeList.forEach(Runnable::run); } } diff --git a/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/prefs/PlayerData.java b/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/prefs/PlayerData.java index 9f527d769..40c1c0377 100644 --- a/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/prefs/PlayerData.java +++ b/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/prefs/PlayerData.java @@ -18,7 +18,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -public class PlayerData { +public class PlayerData extends DataChangeBase { private static final String VIDEO_PLAYER_DATA = "video_player_data"; public static final int ONLY_UI = 0; public static final int UI_AND_PAUSE = 1; @@ -79,7 +79,7 @@ public class PlayerData { mPrefs = AppPrefs.instance(context); initSubtitleStyles(); initDefaultFormats(); - restoreData(); + restoreState(); } public static PlayerData instance(Context context) { @@ -92,7 +92,7 @@ public class PlayerData { public void setOKButtonBehavior(int option) { mOKButtonBehavior = option; - persistData(); + persistState(); } public int getOKButtonBehavior() { @@ -101,7 +101,7 @@ public class PlayerData { public void setUIHideTimoutSec(int timoutSec) { mUIHideTimeoutSec = timoutSec; - persistData(); + persistState(); } public int getUIHideTimoutSec() { @@ -110,7 +110,7 @@ public class PlayerData { public void enableAbsoluteDate(boolean show) { mIsAbsoluteDateEnabled = show; - persistData(); + persistState(); } public boolean isAbsoluteDateEnabled() { @@ -119,7 +119,7 @@ public class PlayerData { public void setSeekPreviewMode(int mode) { mSeekPreviewMode = mode; - persistData(); + persistState(); } public int getSeekPreviewMode() { @@ -128,7 +128,7 @@ public class PlayerData { public void enableSeekConfirmPause(boolean enable) { mIsSeekConfirmPauseEnabled = enable; - persistData(); + persistState(); } public boolean isSeekConfirmPauseEnabled() { @@ -137,7 +137,7 @@ public class PlayerData { public void enableSeekConfirmPlay(boolean enable) { mIsSeekConfirmPlayEnabled = enable; - persistData(); + persistState(); } public boolean isSeekConfirmPlayEnabled() { @@ -150,7 +150,7 @@ public class PlayerData { public void enableClock(boolean enable) { mIsClockEnabled = enable; - persistData(); + persistState(); } public boolean isGlobalClockEnabled() { @@ -159,7 +159,7 @@ public class PlayerData { public void enableGlobalClock(boolean enable) { mIsGlobalClockEnabled = enable; - persistData(); + persistState(); } public boolean isGlobalEndingTimeEnabled() { @@ -168,7 +168,7 @@ public class PlayerData { public void enableGlobalEndingTime(boolean enable) { mIsGlobalEndingTimeEnabled = enable; - persistData(); + persistState(); } public boolean isRemainingTimeEnabled() { @@ -177,7 +177,7 @@ public class PlayerData { public void enableRemainingTime(boolean enable) { mIsRemainingTimeEnabled = enable; - persistData(); + persistState(); } public boolean isEndingTimeEnabled() { @@ -186,7 +186,7 @@ public class PlayerData { public void enableEndingTime(boolean enable) { mIsEndingTimeEnabled = enable; - persistData(); + persistState(); } public boolean isQualityInfoEnabled() { @@ -195,12 +195,12 @@ public class PlayerData { public void enableQualityInfo(boolean enable) { mIsQualityInfoEnabled = enable; - persistData(); + persistState(); } public void setBackgroundMode(int type) { mBackgroundMode = type; - persistData(); + persistState(); } public int getBackgroundMode() { @@ -209,7 +209,7 @@ public class PlayerData { public void setPlaybackMode(int type) { mPlaybackMode = type; - persistData(); + persistState(); } public int getPlaybackMode() { @@ -223,7 +223,7 @@ public class PlayerData { public void enableRememberSpeed(boolean enable) { mIsRememberSpeedEnabled = enable; mIsRememberSpeedEachEnabled = false; - persistData(); + persistState(); } public boolean isRememberSpeedEachEnabled() { @@ -233,7 +233,7 @@ public class PlayerData { public void enableRememberSpeedEach(boolean enable) { mIsRememberSpeedEachEnabled = enable; mIsRememberSpeedEnabled = false; - persistData(); + persistState(); } public boolean isLegacyCodecsForced() { @@ -242,7 +242,7 @@ public class PlayerData { public void forceLegacyCodecs(boolean enable) { mIsLegacyCodecsForced = enable; - persistData(); + persistState(); } public boolean isAfrEnabled() { @@ -251,7 +251,7 @@ public class PlayerData { public void setAfrEnabled(boolean enabled) { mIsAfrEnabled = enabled; - persistData(); + persistState(); } public boolean isAfrFpsCorrectionEnabled() { @@ -260,7 +260,7 @@ public class PlayerData { public void setAfrFpsCorrectionEnabled(boolean enabled) { mIsAfrFpsCorrectionEnabled = enabled; - persistData(); + persistState(); } public boolean isAfrResSwitchEnabled() { @@ -269,7 +269,7 @@ public class PlayerData { public void setAfrResSwitchEnabled(boolean enabled) { mIsAfrResSwitchEnabled = enabled; - persistData(); + persistState(); } public int getAfrPauseMs() { @@ -278,7 +278,7 @@ public class PlayerData { public void setAfrPauseMs(int pauseSec) { mAfrPauseMs = pauseSec; - persistData(); + persistState(); } public boolean isDoubleRefreshRateEnabled() { @@ -287,7 +287,7 @@ public class PlayerData { public void setDoubleRefreshRateEnabled(boolean enabled) { mIsDoubleRefreshRateEnabled = enabled; - persistData(); + persistState(); } public boolean isTooltipsEnabled() { @@ -296,7 +296,7 @@ public class PlayerData { public void enableTooltips(boolean enable) { mIsTooltipsEnabled = enable; - persistData(); + persistState(); } public boolean isNumberKeySeekEnabled() { @@ -305,7 +305,7 @@ public class PlayerData { public void enableNumberKeySeek(boolean enable) { mIsNumberKeySeekEnabled = enable; - persistData(); + persistState(); } public FormatItem getFormat(int type) { @@ -343,12 +343,12 @@ public class PlayerData { break; } - persistData(); + persistState(); } public void setVideoBufferType(int type) { mVideoBufferType = type; - persistData(); + persistState(); } public int getVideoBufferType() { @@ -365,7 +365,7 @@ public class PlayerData { public void setSubtitleStyle(SubtitleStyle subtitleStyle) { mSubtitleStyleIndex = mSubtitleStyles.indexOf(subtitleStyle); - persistData(); + persistState(); } public float getSubtitleScale() { @@ -374,7 +374,7 @@ public class PlayerData { public void setSubtitleScale(float scale) { mSubtitleScale = scale; - persistData(); + persistState(); } public float getSubtitlePosition() { @@ -383,7 +383,7 @@ public class PlayerData { public void setSubtitlePosition(float position) { mSubtitlePosition = position; - persistData(); + persistState(); } public float getPlayerVolume() { @@ -392,12 +392,12 @@ public class PlayerData { public void setPlayerVolume(float scale) { mPlayerVolume = scale; - persistData(); + persistState(); } public void setVideoZoomMode(int mode) { mVideoZoomMode = mode; - persistData(); + persistState(); } public int getVideoZoomMode() { @@ -406,7 +406,7 @@ public class PlayerData { public void setVideoAspectRatio(float ratio) { mVideoAspectRatio = ratio; - persistData(); + persistState(); } public float getVideoAspectRatio() { @@ -419,7 +419,7 @@ public class PlayerData { } mSpeed = speed; - persistData(); + persistState(); } public float getSpeed() { @@ -432,12 +432,12 @@ public class PlayerData { public void setAudioDelayMs(int delayMs) { mAudioDelayMs = delayMs; - persistData(); + persistState(); } public void enableSonyTimerFix(boolean enable) { mIsSonyTimerFixEnabled = enable; - persistData(); + persistState(); } public boolean isSonyTimerFixEnabled() { @@ -446,7 +446,7 @@ public class PlayerData { public void enableTimeCorrection(boolean enable) { mIsTimeCorrectionEnabled = enable; - persistData(); + persistState(); } public boolean isTimeCorrectionEnabled() { @@ -459,7 +459,7 @@ public class PlayerData { public void enableSkip24Rate(boolean enable) { mIsSkip24RateEnabled = enable; - persistData(); + persistState(); } public boolean isLiveChatEnabled() { @@ -468,7 +468,7 @@ public class PlayerData { public void enableLiveChat(boolean enable) { mIsLiveChatEnabled = enable; - persistData(); + persistState(); } public FormatItem getDefaultAudioFormat() { @@ -499,7 +499,7 @@ public class PlayerData { public void setStartSeekIncrementMs(int startSeekIncrementMs) { mStartSeekIncrementMs = startSeekIncrementMs; - persistData(); + persistState(); } private void initSubtitleStyles() { @@ -525,7 +525,7 @@ public class PlayerData { mDefaultVideoFormats.put("P1", FormatItem.VIDEO_FHD_AVC_60); // Chinese projector (see annoying emails) } - private void restoreData() { + private void restoreState() { String data = mPrefs.getData(VIDEO_PLAYER_DATA); String[] split = Helpers.splitObjectLegacy(data); @@ -582,7 +582,8 @@ public class PlayerData { } } - private void persistData() { + @Override + protected void persistState() { mPrefs.setData(VIDEO_PLAYER_DATA, Helpers.mergeObject(mOKButtonBehavior, mUIHideTimeoutSec, mIsAbsoluteDateEnabled, mSeekPreviewMode, mIsSeekConfirmPauseEnabled, mIsClockEnabled, mIsRemainingTimeEnabled, mBackgroundMode, null, // afrData was there Helpers.toString(mVideoFormat), Helpers.toString(mAudioFormat), Helpers.toString(mSubtitleFormat), @@ -594,5 +595,7 @@ public class PlayerData { mIsGlobalEndingTimeEnabled, mIsEndingTimeEnabled, mIsDoubleRefreshRateEnabled, mIsSeekConfirmPlayEnabled, mStartSeekIncrementMs, null, mSubtitleScale, mPlayerVolume, mIsTooltipsEnabled, mSubtitlePosition, mIsNumberKeySeekEnabled, mIsSkip24RateEnabled, mAfrPauseMs, mIsLiveChatEnabled)); + + super.persistState(); } } diff --git a/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/utils/AppDialogUtil.java b/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/utils/AppDialogUtil.java index dabafc52d..0c21877fe 100644 --- a/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/utils/AppDialogUtil.java +++ b/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/utils/AppDialogUtil.java @@ -14,16 +14,16 @@ import com.liskovsoft.smartyoutubetv2.common.app.models.data.Playlist; import com.liskovsoft.smartyoutubetv2.common.app.models.data.Video; import com.liskovsoft.smartyoutubetv2.common.app.models.playback.controller.PlaybackController; import com.liskovsoft.smartyoutubetv2.common.app.models.playback.controller.PlaybackEngineController; +import com.liskovsoft.smartyoutubetv2.common.app.models.playback.ui.OptionCallback; import com.liskovsoft.smartyoutubetv2.common.app.models.playback.ui.OptionCategory; import com.liskovsoft.smartyoutubetv2.common.app.models.playback.ui.OptionItem; import com.liskovsoft.smartyoutubetv2.common.app.models.playback.ui.UiOptionItem; import com.liskovsoft.smartyoutubetv2.common.app.presenters.AppDialogPresenter; import com.liskovsoft.smartyoutubetv2.common.app.presenters.dialogs.menu.VideoMenuPresenter.VideoMenuCallback; import com.liskovsoft.smartyoutubetv2.common.app.views.ViewManager; +import com.liskovsoft.smartyoutubetv2.common.exoplayer.other.SubtitleManager.SubtitleStyle; import com.liskovsoft.smartyoutubetv2.common.exoplayer.selector.FormatItem; import com.liskovsoft.smartyoutubetv2.common.exoplayer.selector.FormatItem.VideoPreset; -import com.liskovsoft.smartyoutubetv2.common.exoplayer.other.SubtitleManager.OnSelectSubtitleStyle; -import com.liskovsoft.smartyoutubetv2.common.exoplayer.other.SubtitleManager.SubtitleStyle; import com.liskovsoft.smartyoutubetv2.common.misc.AppDataSourceManager; import com.liskovsoft.smartyoutubetv2.common.misc.MediaServiceManager; import com.liskovsoft.smartyoutubetv2.common.prefs.GeneralData; @@ -262,27 +262,20 @@ public class AppDialogUtil { } public static OptionCategory createSubtitleStylesCategory(Context context, PlayerData playerData) { - return createSubtitleStylesCategory(context, playerData, style -> {}); - } - - private static OptionCategory createSubtitleStylesCategory(Context context, PlayerData playerData, OnSelectSubtitleStyle onSelectSubtitleStyle) { List subtitleStyles = playerData.getSubtitleStyles(); String subtitleStyleTitle = context.getString(R.string.subtitle_style); - return OptionCategory.from(SUBTITLE_STYLES_ID, OptionCategory.TYPE_RADIO, subtitleStyleTitle, fromSubtitleStyles(context, playerData, subtitleStyles, onSelectSubtitleStyle)); + return OptionCategory.from(SUBTITLE_STYLES_ID, OptionCategory.TYPE_RADIO, subtitleStyleTitle, fromSubtitleStyles(context, playerData, subtitleStyles)); } - private static List fromSubtitleStyles(Context context, PlayerData playerData, List subtitleStyles, OnSelectSubtitleStyle onSelectSubtitleStyle) { + private static List fromSubtitleStyles(Context context, PlayerData playerData, List subtitleStyles) { List styleOptions = new ArrayList<>(); for (SubtitleStyle subtitleStyle : subtitleStyles) { styleOptions.add(UiOptionItem.from( context.getString(subtitleStyle.nameResId), - option -> { - playerData.setSubtitleStyle(subtitleStyle); - onSelectSubtitleStyle.onSelectSubtitleStyle(subtitleStyle); - }, + option -> playerData.setSubtitleStyle(subtitleStyle), subtitleStyle.equals(playerData.getSubtitleStyle()))); } diff --git a/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/utils/WeakHashSet.java b/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/utils/WeakHashSet.java new file mode 100644 index 000000000..ca61515fb --- /dev/null +++ b/common/src/main/java/com/liskovsoft/smartyoutubetv2/common/utils/WeakHashSet.java @@ -0,0 +1,59 @@ +package com.liskovsoft.smartyoutubetv2.common.utils; + +import com.liskovsoft.sharedutils.helpers.Helpers; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; + +public class WeakHashSet { + public interface OnItem { + void onItem(T item); + } + + private final List> mWeakReferences = new ArrayList<>(); + + public boolean add(T t) { + if (t != null && !contains(t)) { + cleanup(); + mWeakReferences.add(new WeakReference<>(t)); + return true; + } + + return false; + } + + public void remove(T t) { + if (t != null) { + Helpers.removeIf(mWeakReferences, item -> t.equals(item.get())); + } + } + + public int size() { + return mWeakReferences.size(); + } + + public void forEach(OnItem onItem) { + for (WeakReference reference : mWeakReferences) { + if (reference.get() != null) { + onItem.onItem(reference.get()); + } + } + } + + public boolean contains(T t) { + return Helpers.containsIf(mWeakReferences, item -> t.equals(item.get())); + } + + public void clear() { + mWeakReferences.clear(); + } + + public boolean isEmpty() { + return mWeakReferences.isEmpty(); + } + + private void cleanup() { + Helpers.removeIf(mWeakReferences, item -> item.get() == null); + } +}