diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/CastActivity.java b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/CastActivity.java
index de94fc636..8adfd368e 100644
--- a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/CastActivity.java
+++ b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/CastActivity.java
@@ -465,7 +465,7 @@ public class CastActivity extends BaseActivity implements CustomKeyDownCast.List
@Override
public void onSpeedUp() {
if (!mPlayers.isPlaying() || !mPlayers.canAdjustSpeed()) return;
- mBinding.control.speed.setText(mPlayers.setSpeed(mPlayers.getSpeed() < 3 ? 3 : 5));
+ mBinding.control.speed.setText(mPlayers.setSpeed(Setting.getSpeed()));
mBinding.widget.speed.startAnimation(ResUtil.getAnim(R.anim.forward));
mBinding.widget.speed.setVisibility(View.VISIBLE);
}
diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/SettingPlayerActivity.java b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/SettingPlayerActivity.java
index ea58b1ad9..42b1de66d 100644
--- a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/SettingPlayerActivity.java
+++ b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/SettingPlayerActivity.java
@@ -11,17 +11,22 @@ import com.fongmi.android.tv.R;
import com.fongmi.android.tv.Setting;
import com.fongmi.android.tv.databinding.ActivitySettingPlayerBinding;
import com.fongmi.android.tv.impl.BufferCallback;
+import com.fongmi.android.tv.impl.SpeedCallback;
import com.fongmi.android.tv.impl.SubtitleCallback;
import com.fongmi.android.tv.impl.UaCallback;
import com.fongmi.android.tv.ui.base.BaseActivity;
import com.fongmi.android.tv.ui.dialog.BufferDialog;
+import com.fongmi.android.tv.ui.dialog.SpeedDialog;
import com.fongmi.android.tv.ui.dialog.SubtitleDialog;
import com.fongmi.android.tv.ui.dialog.UaDialog;
import com.fongmi.android.tv.utils.ResUtil;
-public class SettingPlayerActivity extends BaseActivity implements UaCallback, BufferCallback, SubtitleCallback {
+import java.text.DecimalFormat;
+
+public class SettingPlayerActivity extends BaseActivity implements UaCallback, BufferCallback, SpeedCallback, SubtitleCallback {
private ActivitySettingPlayerBinding mBinding;
+ private DecimalFormat format;
private String[] caption;
private String[] render;
private String[] scale;
@@ -43,9 +48,11 @@ public class SettingPlayerActivity extends BaseActivity implements UaCallback, B
@Override
protected void initView() {
setVisible();
+ format = new DecimalFormat("0.#");
mBinding.render.requestFocus();
mBinding.uaText.setText(Setting.getUa());
mBinding.tunnelText.setText(getSwitch(Setting.isTunnel()));
+ mBinding.speedText.setText(format.format(Setting.getSpeed()));
mBinding.bufferText.setText(String.valueOf(Setting.getBuffer()));
mBinding.subtitleText.setText(String.valueOf(Setting.getSubtitle()));
mBinding.rtspText.setText((rtsp = ResUtil.getStringArray(R.array.select_rtsp))[Setting.getRtsp()]);
@@ -59,6 +66,7 @@ public class SettingPlayerActivity extends BaseActivity implements UaCallback, B
mBinding.ua.setOnClickListener(this::onUa);
mBinding.rtsp.setOnClickListener(this::setRtsp);
mBinding.scale.setOnClickListener(this::setScale);
+ mBinding.speed.setOnClickListener(this::onSpeed);
mBinding.buffer.setOnClickListener(this::onBuffer);
mBinding.render.setOnClickListener(this::setRender);
mBinding.tunnel.setOnClickListener(this::setTunnel);
@@ -93,6 +101,16 @@ public class SettingPlayerActivity extends BaseActivity implements UaCallback, B
mBinding.scaleText.setText(scale[index]);
}
+ private void onSpeed(View view) {
+ SpeedDialog.create(this).show();
+ }
+
+ @Override
+ public void setSpeed(float speed) {
+ mBinding.speedText.setText(format.format(speed));
+ Setting.putSpeed(speed);
+ }
+
private void onBuffer(View view) {
BufferDialog.create(this).show();
}
diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/VideoActivity.java b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/VideoActivity.java
index 71f12b4ca..8d37b4556 100644
--- a/app/src/leanback/java/com/fongmi/android/tv/ui/activity/VideoActivity.java
+++ b/app/src/leanback/java/com/fongmi/android/tv/ui/activity/VideoActivity.java
@@ -1369,7 +1369,7 @@ public class VideoActivity extends BaseActivity implements CustomKeyDownVod.List
@Override
public void onSpeedUp() {
if (!mPlayers.isPlaying() || !mPlayers.canAdjustSpeed()) return;
- mBinding.control.speed.setText(mPlayers.setSpeed(mPlayers.getSpeed() < 3 ? 3 : 5));
+ mBinding.control.speed.setText(mPlayers.setSpeed(Setting.getSpeed()));
mBinding.widget.speed.startAnimation(ResUtil.getAnim(R.anim.forward));
mBinding.widget.speed.setVisibility(View.VISIBLE);
}
diff --git a/app/src/leanback/java/com/fongmi/android/tv/ui/dialog/SpeedDialog.java b/app/src/leanback/java/com/fongmi/android/tv/ui/dialog/SpeedDialog.java
new file mode 100644
index 000000000..fe83d208f
--- /dev/null
+++ b/app/src/leanback/java/com/fongmi/android/tv/ui/dialog/SpeedDialog.java
@@ -0,0 +1,53 @@
+package com.fongmi.android.tv.ui.dialog;
+
+import android.view.LayoutInflater;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.FragmentActivity;
+
+import com.fongmi.android.tv.Setting;
+import com.fongmi.android.tv.databinding.DialogSpeedBinding;
+import com.fongmi.android.tv.impl.SpeedCallback;
+import com.fongmi.android.tv.utils.KeyUtil;
+import com.google.android.material.dialog.MaterialAlertDialogBuilder;
+
+public class SpeedDialog {
+
+ private final DialogSpeedBinding binding;
+ private final SpeedCallback callback;
+ private final AlertDialog dialog;
+
+ public static SpeedDialog create(FragmentActivity activity) {
+ return new SpeedDialog(activity);
+ }
+
+ public SpeedDialog(FragmentActivity activity) {
+ this.callback = (SpeedCallback) activity;
+ this.binding = DialogSpeedBinding.inflate(LayoutInflater.from(activity));
+ this.dialog = new MaterialAlertDialogBuilder(activity).setView(binding.getRoot()).create();
+ }
+
+ public void show() {
+ initDialog();
+ initView();
+ initEvent();
+ }
+
+ private void initDialog() {
+ dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
+ dialog.show();
+ }
+
+ private void initView() {
+ binding.slider.setValue(Setting.getSpeed());
+ }
+
+ private void initEvent() {
+ binding.slider.addOnChangeListener((slider, value, fromUser) -> callback.setSpeed(value));
+ binding.slider.setOnKeyListener((view, keyCode, event) -> {
+ boolean enter = KeyUtil.isEnterKey(event);
+ if (enter) dialog.dismiss();
+ return enter;
+ });
+ }
+}
diff --git a/app/src/leanback/res/layout/activity_setting_player.xml b/app/src/leanback/res/layout/activity_setting_player.xml
index 2edf0517b..8b66f7ee6 100644
--- a/app/src/leanback/res/layout/activity_setting_player.xml
+++ b/app/src/leanback/res/layout/activity_setting_player.xml
@@ -167,6 +167,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/fongmi/android/tv/Setting.java b/app/src/main/java/com/fongmi/android/tv/Setting.java
index 7ef9a9ed6..05ce7ebbf 100644
--- a/app/src/main/java/com/fongmi/android/tv/Setting.java
+++ b/app/src/main/java/com/fongmi/android/tv/Setting.java
@@ -257,6 +257,14 @@ public class Setting {
Prefers.put("zhuyin", zhuyin);
}
+ public static float getSpeed() {
+ return Math.min(Math.max(Prefers.getFloat("speed", 3), 2), 5);
+ }
+
+ public static void putSpeed(float speed) {
+ Prefers.put("speed", speed);
+ }
+
public static float getThumbnail() {
return 0.3f * getQuality() + 0.4f;
}
diff --git a/app/src/main/java/com/fongmi/android/tv/impl/SpeedCallback.java b/app/src/main/java/com/fongmi/android/tv/impl/SpeedCallback.java
new file mode 100644
index 000000000..cb72e5a0c
--- /dev/null
+++ b/app/src/main/java/com/fongmi/android/tv/impl/SpeedCallback.java
@@ -0,0 +1,6 @@
+package com.fongmi.android.tv.impl;
+
+public interface SpeedCallback {
+
+ void setSpeed(float speed);
+}
diff --git a/app/src/main/java/com/fongmi/android/tv/player/Players.java b/app/src/main/java/com/fongmi/android/tv/player/Players.java
index 501651541..7b69b8247 100644
--- a/app/src/main/java/com/fongmi/android/tv/player/Players.java
+++ b/app/src/main/java/com/fongmi/android/tv/player/Players.java
@@ -273,7 +273,7 @@ public class Players implements Player.Listener, ParseCallback {
public String toggleSpeed() {
float speed = getSpeed();
- speed = speed == 1 ? 3f : 1f;
+ speed = speed == 1 ? Setting.getSpeed() : 1;
return setSpeed(speed);
}
diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml
index c1fbebf16..758a1b786 100644
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ b/app/src/main/res/values-zh-rCN/strings.xml
@@ -86,6 +86,7 @@
后台播放
隧道模式
缓冲时间
+ 长按倍速
RTSP 通道
User-Agent
diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml
index 0e3ffb089..b743d3d30 100644
--- a/app/src/main/res/values-zh-rTW/strings.xml
+++ b/app/src/main/res/values-zh-rTW/strings.xml
@@ -86,6 +86,7 @@
背景播放
隧道模式
緩衝時間
+ 長按倍速
RTSP 通道
User-Agent
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 3ee7ddf50..87b5a0054 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -87,6 +87,7 @@
Background play
Tunnel mode
Buffer time
+ Press speed
RTSP channel
User-Agent
diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/activity/LiveActivity.java b/app/src/mobile/java/com/fongmi/android/tv/ui/activity/LiveActivity.java
index a0b390b89..10e631be7 100644
--- a/app/src/mobile/java/com/fongmi/android/tv/ui/activity/LiveActivity.java
+++ b/app/src/mobile/java/com/fongmi/android/tv/ui/activity/LiveActivity.java
@@ -946,7 +946,7 @@ public class LiveActivity extends BaseActivity implements CustomKeyDownLive.List
@Override
public void onSpeedUp() {
if (mPlayers.isLive() || !mPlayers.isPlaying() || !mPlayers.canAdjustSpeed()) return;
- mBinding.control.action.speed.setText(mPlayers.setSpeed(mPlayers.getSpeed() < 3 ? 3 : 5));
+ mBinding.control.action.speed.setText(mPlayers.setSpeed(Setting.getSpeed()));
mBinding.widget.speed.startAnimation(ResUtil.getAnim(R.anim.forward));
mBinding.widget.speed.setVisibility(View.VISIBLE);
}
diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java b/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java
index 8b289f1f2..d02dc01eb 100644
--- a/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java
+++ b/app/src/mobile/java/com/fongmi/android/tv/ui/activity/VideoActivity.java
@@ -1412,7 +1412,7 @@ public class VideoActivity extends BaseActivity implements Clock.Callback, Custo
@Override
public void onSpeedUp() {
if (!mPlayers.isPlaying() || !mPlayers.canAdjustSpeed()) return;
- mBinding.control.action.speed.setText(mPlayers.setSpeed(mPlayers.getSpeed() < 3 ? 3 : 5));
+ mBinding.control.action.speed.setText(mPlayers.setSpeed(Setting.getSpeed()));
mBinding.widget.speed.startAnimation(ResUtil.getAnim(R.anim.forward));
mBinding.widget.speed.setVisibility(View.VISIBLE);
}
diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/dialog/SpeedDialog.java b/app/src/mobile/java/com/fongmi/android/tv/ui/dialog/SpeedDialog.java
new file mode 100644
index 000000000..d0ef1efd9
--- /dev/null
+++ b/app/src/mobile/java/com/fongmi/android/tv/ui/dialog/SpeedDialog.java
@@ -0,0 +1,54 @@
+package com.fongmi.android.tv.ui.dialog;
+
+import android.content.DialogInterface;
+import android.view.LayoutInflater;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.Fragment;
+
+import com.fongmi.android.tv.R;
+import com.fongmi.android.tv.Setting;
+import com.fongmi.android.tv.databinding.DialogSpeedBinding;
+import com.fongmi.android.tv.impl.SpeedCallback;
+import com.google.android.material.dialog.MaterialAlertDialogBuilder;
+
+public class SpeedDialog {
+
+ private final DialogSpeedBinding binding;
+ private final SpeedCallback callback;
+ private float value;
+
+ public static SpeedDialog create(Fragment fragment) {
+ return new SpeedDialog(fragment);
+ }
+
+ public SpeedDialog(Fragment fragment) {
+ this.callback = (SpeedCallback) fragment;
+ this.binding = DialogSpeedBinding.inflate(LayoutInflater.from(fragment.getContext()));
+ }
+
+ public void show() {
+ initDialog();
+ initView();
+ }
+
+ private void initDialog() {
+ AlertDialog dialog = new MaterialAlertDialogBuilder(binding.getRoot().getContext()).setTitle(R.string.player_speed).setView(binding.getRoot()).setPositiveButton(R.string.dialog_positive, this::onPositive).setNegativeButton(R.string.dialog_negative, this::onNegative).create();
+ dialog.getWindow().setDimAmount(0);
+ dialog.show();
+ }
+
+ private void initView() {
+ binding.slider.setValue(value = Setting.getSpeed());
+ }
+
+ private void onPositive(DialogInterface dialog, int which) {
+ callback.setSpeed(binding.slider.getValue());
+ dialog.dismiss();
+ }
+
+ private void onNegative(DialogInterface dialog, int which) {
+ callback.setSpeed(value);
+ dialog.dismiss();
+ }
+}
diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/SettingPlayerFragment.java b/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/SettingPlayerFragment.java
index dad9d7fb9..75450c173 100644
--- a/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/SettingPlayerFragment.java
+++ b/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/SettingPlayerFragment.java
@@ -14,18 +14,23 @@ import com.fongmi.android.tv.R;
import com.fongmi.android.tv.Setting;
import com.fongmi.android.tv.databinding.FragmentSettingPlayerBinding;
import com.fongmi.android.tv.impl.BufferCallback;
+import com.fongmi.android.tv.impl.SpeedCallback;
import com.fongmi.android.tv.impl.SubtitleCallback;
import com.fongmi.android.tv.impl.UaCallback;
import com.fongmi.android.tv.ui.base.BaseFragment;
import com.fongmi.android.tv.ui.dialog.BufferDialog;
+import com.fongmi.android.tv.ui.dialog.SpeedDialog;
import com.fongmi.android.tv.ui.dialog.SubtitleDialog;
import com.fongmi.android.tv.ui.dialog.UaDialog;
import com.fongmi.android.tv.utils.ResUtil;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
-public class SettingPlayerFragment extends BaseFragment implements UaCallback, BufferCallback, SubtitleCallback {
+import java.text.DecimalFormat;
+
+public class SettingPlayerFragment extends BaseFragment implements UaCallback, BufferCallback, SpeedCallback, SubtitleCallback {
private FragmentSettingPlayerBinding mBinding;
+ private DecimalFormat format;
private String[] background;
private String[] caption;
private String[] render;
@@ -48,8 +53,10 @@ public class SettingPlayerFragment extends BaseFragment implements UaCallback, B
@Override
protected void initView() {
setVisible();
+ format = new DecimalFormat("0.#");
mBinding.uaText.setText(Setting.getUa());
mBinding.tunnelText.setText(getSwitch(Setting.isTunnel()));
+ mBinding.speedText.setText(format.format(Setting.getSpeed()));
mBinding.bufferText.setText(String.valueOf(Setting.getBuffer()));
mBinding.subtitleText.setText(String.valueOf(Setting.getSubtitle()));
mBinding.rtspText.setText((rtsp = ResUtil.getStringArray(R.array.select_rtsp))[Setting.getRtsp()]);
@@ -64,6 +71,7 @@ public class SettingPlayerFragment extends BaseFragment implements UaCallback, B
mBinding.ua.setOnClickListener(this::onUa);
mBinding.rtsp.setOnClickListener(this::setRtsp);
mBinding.scale.setOnClickListener(this::onScale);
+ mBinding.speed.setOnClickListener(this::onSpeed);
mBinding.buffer.setOnClickListener(this::onBuffer);
mBinding.render.setOnClickListener(this::setRender);
mBinding.tunnel.setOnClickListener(this::setTunnel);
@@ -101,6 +109,16 @@ public class SettingPlayerFragment extends BaseFragment implements UaCallback, B
}).show();
}
+ private void onSpeed(View view) {
+ SpeedDialog.create(this).show();
+ }
+
+ @Override
+ public void setSpeed(float speed) {
+ mBinding.speedText.setText(format.format(speed));
+ Setting.putSpeed(speed);
+ }
+
private void onBuffer(View view) {
BufferDialog.create(this).show();
}
diff --git a/app/src/mobile/res/layout/dialog_speed.xml b/app/src/mobile/res/layout/dialog_speed.xml
new file mode 100644
index 000000000..5fc653028
--- /dev/null
+++ b/app/src/mobile/res/layout/dialog_speed.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/mobile/res/layout/fragment_setting_player.xml b/app/src/mobile/res/layout/fragment_setting_player.xml
index b307a9253..f5e5b8241 100644
--- a/app/src/mobile/res/layout/fragment_setting_player.xml
+++ b/app/src/mobile/res/layout/fragment_setting_player.xml
@@ -188,6 +188,42 @@
+
+
+
+
+
+
+
+
+
+
floats = Arrays.asList("speed");
+
private static SharedPreferences getPrefers() {
return PreferenceManager.getDefaultSharedPreferences(Init.context());
}
@@ -104,6 +108,10 @@ public class Prefers {
}
private static Object convert(Map.Entry entry) {
- return entry.getValue();
+ if (floats.contains(entry.getKey())) {
+ return Float.parseFloat(entry.getValue().toString());
+ } else {
+ return entry.getValue();
+ }
}
}
diff --git a/catvod/src/main/java/com/github/catvod/utils/UriUtil.java b/catvod/src/main/java/com/github/catvod/utils/UriUtil.java
index 0b07bf974..4140e0abd 100644
--- a/catvod/src/main/java/com/github/catvod/utils/UriUtil.java
+++ b/catvod/src/main/java/com/github/catvod/utils/UriUtil.java
@@ -159,7 +159,7 @@ public final class UriUtil {
} else if (i == segmentStart + 2 && uri.charAt(segmentStart) == '.' && uri.charAt(segmentStart + 1) == '.') {
// Given "abc/def/../ghi", remove "def/../" to get "abc/ghi".
int prevSegmentStart = uri.lastIndexOf("/", segmentStart - 2) + 1;
- int removeFrom = prevSegmentStart > offset ? prevSegmentStart : offset;
+ int removeFrom = Math.max(prevSegmentStart, offset);
uri.delete(removeFrom, nextSegmentStart);
limit -= nextSegmentStart - removeFrom;
segmentStart = prevSegmentStart;