引入长按倍速播放(借鉴taka);图床增加更多图片格式的支持;播放进度常驻

pull/69/head
21561 3 years ago
parent a2737b3999
commit db366092ef
  1. 96
      app/src/main/java/com/github/tvbox/osc/api/ApiConfig.java
  2. 62
      app/src/main/java/com/github/tvbox/osc/player/controller/VodController.java
  3. 26
      app/src/main/res/layout/player_vod_control_view.xml

@ -41,6 +41,8 @@ import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author pj567
@ -88,9 +90,11 @@ public class ApiConfig {
String content = json;
try {
if (AES.isJson(content)) return content;
if(content.contains("**")){
String[] data = json.split("\\*\\*");
content = new String(Base64.decode(data[1], Base64.DEFAULT));
Pattern pattern = Pattern.compile("[A-Za-z0]{8}\\*\\*");
Matcher matcher = pattern.matcher(content);
if(matcher.find()){
content=content.substring(content.indexOf(matcher.group()) + 10);
content = new String(Base64.decode(content, Base64.DEFAULT));
}
if (content.startsWith("2423")) {
String data = content.substring(content.indexOf("2324") + 4, content.length() - 26);
@ -322,15 +326,18 @@ public class ApiConfig {
vipParseFlags = DefaultConfig.safeJsonStringList(infoJson, "flags");
// 解析地址
parseBeanList.clear();
for (JsonElement opt : infoJson.get("parses").getAsJsonArray()) {
JsonObject obj = (JsonObject) opt;
ParseBean pb = new ParseBean();
pb.setName(obj.get("name").getAsString().trim());
pb.setUrl(obj.get("url").getAsString().trim());
String ext = obj.has("ext") ? obj.get("ext").getAsJsonObject().toString() : "";
pb.setExt(ext);
pb.setType(DefaultConfig.safeJsonInt(obj, "type", 0));
parseBeanList.add(pb);
if(infoJson.has("parses")){
JsonArray parses = infoJson.get("parses").getAsJsonArray();
for (JsonElement opt : parses) {
JsonObject obj = (JsonObject) opt;
ParseBean pb = new ParseBean();
pb.setName(obj.get("name").getAsString().trim());
pb.setUrl(obj.get("url").getAsString().trim());
String ext = obj.has("ext") ? obj.get("ext").getAsJsonObject().toString() : "";
pb.setExt(ext);
pb.setType(DefaultConfig.safeJsonInt(obj, "type", 0));
parseBeanList.add(pb);
}
}
// 获取默认解析
if (parseBeanList != null && parseBeanList.size() > 0) {
@ -347,6 +354,11 @@ public class ApiConfig {
liveChannelGroupList.clear(); //修复从后台切换重复加载频道列表
try {
String lives = infoJson.get("lives").getAsJsonArray().toString();
// if(lives.indexOf("group")==-1){
// String defaultLiveTxt="[{\"group\":\"redirect\",\"channels\":[{\"name\":\"redirect\",\"urls\":[\"proxy://do=live&type=txt&ext=defaultLiveTxt\"]}]}]";
// JsonArray fengMilives = infoJson.get("lives").getAsJsonArray();
// lives=defaultLiveTxt.replace("defaultLiveTxt",fengMilives.get(0).getAsJsonObject().get("url").getAsString());
// }
int index = lives.indexOf("proxy://");
if (index != -1) {
int endIndex = lives.lastIndexOf("\"");
@ -369,12 +381,12 @@ public class ApiConfig {
extUrlFix = Base64.encodeToString(extUrlFix.getBytes("UTF-8"), Base64.DEFAULT | Base64.URL_SAFE | Base64.NO_WRAP);
url = url.replace(extUrl, extUrlFix);
}
// System.out.println("url :"+url);
// System.out.println("urlLive :"+url);
LiveChannelGroup liveChannelGroup = new LiveChannelGroup();
liveChannelGroup.setGroupName(url);
liveChannelGroupList.add(liveChannelGroup);
} else {
loadLives(infoJson.get("lives").getAsJsonArray());
if(lives.contains("group"))loadLives(infoJson.get("lives").getAsJsonArray());
}
} catch (Throwable th) {
th.printStackTrace();
@ -410,37 +422,41 @@ public class ApiConfig {
}
}
// 广告地址
for (JsonElement host : infoJson.getAsJsonArray("ads")) {
AdBlocker.addAdHost(host.getAsString());
if(infoJson.has("ads")){
for (JsonElement host : infoJson.getAsJsonArray("ads")) {
AdBlocker.addAdHost(host.getAsString());
}
}
// IJK解码配置
boolean foundOldSelect = false;
String ijkCodec = Hawk.get(HawkConfig.IJK_CODEC, "");
ijkCodes = new ArrayList<>();
for (JsonElement opt : infoJson.get("ijk").getAsJsonArray()) {
JsonObject obj = (JsonObject) opt;
String name = obj.get("group").getAsString();
LinkedHashMap<String, String> baseOpt = new LinkedHashMap<>();
for (JsonElement cfg : obj.get("options").getAsJsonArray()) {
JsonObject cObj = (JsonObject) cfg;
String key = cObj.get("category").getAsString() + "|" + cObj.get("name").getAsString();
String val = cObj.get("value").getAsString();
baseOpt.put(key, val);
if(infoJson.has("ijk")){
boolean foundOldSelect = false;
String ijkCodec = Hawk.get(HawkConfig.IJK_CODEC, "");
for (JsonElement opt : infoJson.get("ijk").getAsJsonArray()) {
JsonObject obj = (JsonObject) opt;
String name = obj.get("group").getAsString();
LinkedHashMap<String, String> baseOpt = new LinkedHashMap<>();
for (JsonElement cfg : obj.get("options").getAsJsonArray()) {
JsonObject cObj = (JsonObject) cfg;
String key = cObj.get("category").getAsString() + "|" + cObj.get("name").getAsString();
String val = cObj.get("value").getAsString();
baseOpt.put(key, val);
}
IJKCode codec = new IJKCode();
codec.setName(name);
codec.setOption(baseOpt);
if (name.equals(ijkCodec) || TextUtils.isEmpty(ijkCodec)) {
codec.selected(true);
ijkCodec = name;
foundOldSelect = true;
} else {
codec.selected(false);
}
ijkCodes.add(codec);
}
IJKCode codec = new IJKCode();
codec.setName(name);
codec.setOption(baseOpt);
if (name.equals(ijkCodec) || TextUtils.isEmpty(ijkCodec)) {
codec.selected(true);
ijkCodec = name;
foundOldSelect = true;
} else {
codec.selected(false);
if (!foundOldSelect && ijkCodes.size() > 0) {
ijkCodes.get(0).selected(true);
}
ijkCodes.add(codec);
}
if (!foundOldSelect && ijkCodes.size() > 0) {
ijkCodes.get(0).selected(true);
}
}

@ -101,8 +101,10 @@ public class VodController extends BaseController {
boolean mIsDragging;
LinearLayout mProgressRoot;
TextView mProgressText;
TextView seekTime;
ImageView mProgressIcon;
LinearLayout mBottomRoot;
LinearLayout bottomCenterContainer;
LinearLayout mTopRoot1;
LinearLayout mTopRoot2;
LinearLayout mParseRoot;
@ -134,6 +136,8 @@ public class VodController extends BaseController {
Runnable myRunnable;
int myHandleSeconds = 6000;//闲置多少毫秒秒关闭底栏 默认6秒
int videoPlayState = 0;
private Runnable myRunnable2 = new Runnable() {
@Override
public void run() {
@ -146,6 +150,9 @@ public class VodController extends BaseController {
String width = Integer.toString(mControlWrapper.getVideoSize()[0]);
String height = Integer.toString(mControlWrapper.getVideoSize()[1]);
mVideoSize.setText("[ " + width + " X " + height +" ]");
int getCurrentPosition = (int) (mControlWrapper.getCurrentPosition() / 1000.0);
int getDuration = (int) (mControlWrapper.getDuration() / 1000.0);
seekTime.setText(String.format("%02d", getCurrentPosition / 60) + ":" + String.format("%02d", getCurrentPosition % 60) + " | " + String.format("%02d", getDuration / 60) + ":" + String.format("%02d", getDuration % 60));
mHandler.postDelayed(this, 1000);
}
@ -191,6 +198,9 @@ public class VodController extends BaseController {
mZimuBtn = findViewById(R.id.zimu_select);
mAudioTrackBtn = findViewById(R.id.audio_track_select);
mLandscapePortraitBtn = findViewById(R.id.landscape_portrait);
bottomCenterContainer = findViewById(R.id.tv_bottom_center_container);
seekTime = findViewById(R.id.tv_seek_time);
initSubtitleInfo();
myHandle = new Handler();
@ -320,13 +330,14 @@ public class VodController extends BaseController {
mPlayerConfig.put("sp", speed);
updatePlayerCfgView();
listener.updatePlayerCfg();
speed_old = speed;
mControlWrapper.setSpeed(speed);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
// takagen99: Add long press to reset speed
mPlayerSpeedBtn.setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
@ -334,6 +345,7 @@ public class VodController extends BaseController {
mPlayerConfig.put("sp", 1.0f);
updatePlayerCfgView();
listener.updatePlayerCfg();
speed_old = 1.0f;
mControlWrapper.setSpeed(1.0f);
} catch (JSONException e) {
e.printStackTrace();
@ -607,7 +619,7 @@ public class VodController extends BaseController {
initLandscapePortraitBtnInfo();
}
void initLandscapePortraitBtnInfo() {
public void initLandscapePortraitBtnInfo() {
double screenSqrt = ScreenUtils.getSqrt(mActivity);
if (screenSqrt < 20.0) {
mLandscapePortraitBtn.setVisibility(View.VISIBLE);
@ -792,13 +804,16 @@ public class VodController extends BaseController {
@Override
protected void onPlayStateChanged(int playState) {
super.onPlayStateChanged(playState);
videoPlayState = playState;
switch (playState) {
case VideoView.STATE_IDLE:
break;
case VideoView.STATE_PLAYING:
bottomCenterContainer.setVisibility(VISIBLE);
startProgress();
break;
case VideoView.STATE_PAUSED:
bottomCenterContainer.setVisibility(GONE);
mTopRoot1.setVisibility(GONE);
mTopRoot2.setVisibility(GONE);
mPlayTitle.setVisibility(VISIBLE);
@ -828,11 +843,13 @@ public class VodController extends BaseController {
}
void showBottom() {
bottomCenterContainer.setVisibility(GONE);
mHandler.removeMessages(1003);
mHandler.sendEmptyMessage(1002);
}
void hideBottom() {
bottomCenterContainer.setVisibility(VISIBLE);
mHandler.removeMessages(1002);
mHandler.sendEmptyMessage(1003);
}
@ -880,6 +897,47 @@ public class VodController extends BaseController {
return super.dispatchKeyEvent(event);
}
private boolean fromLongPress;
private float speed_old = 1.0f;
@Override
public void onLongPress(MotionEvent e) {
if (videoPlayState!=VideoView.STATE_PAUSED) {
fromLongPress = true;
try {
speed_old = (float) mPlayerConfig.getDouble("sp");
float speed = 3.0f;
mPlayerConfig.put("sp", speed);
updatePlayerCfgView();
mBottomRoot.setVisibility(VISIBLE);
listener.updatePlayerCfg();
mControlWrapper.setSpeed(speed);
} catch (JSONException f) {
f.printStackTrace();
}
}
}
@Override
public boolean onTouchEvent(MotionEvent e) {
if (e.getAction() == MotionEvent.ACTION_UP) {
if (fromLongPress) {
fromLongPress =false;
try {
float speed = speed_old;
mPlayerConfig.put("sp", speed);
updatePlayerCfgView();
mBottomRoot.setVisibility(GONE);
listener.updatePlayerCfg();
mControlWrapper.setSpeed(speed);
} catch (JSONException f) {
f.printStackTrace();
}
}
}
return super.onTouchEvent(e);
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
myHandle.removeCallbacks(myRunnable);

@ -85,6 +85,32 @@
android:textColor="@android:color/white"
android:textSize="@dimen/ts_20" />
</LinearLayout>
<LinearLayout
android:id="@+id/tv_bottom_center_container"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:tag="tv_top_container"
android:visibility="gone"
tools:visibility="visible"
android:layout_gravity="right"
android:layout_marginRight="@dimen/vs_20"
android:layout_marginTop="@dimen/vs_10"
android:orientation="vertical">
<TextView
android:id="@+id/tv_seek_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:ellipsize="end"
android:maxLines="1"
android:paddingTop="@dimen/vs_20"
android:paddingRight="@dimen/vs_20"
android:tag="vod_control_pause_time"
android:text="00:00 | 00:00"
android:textColor="@android:color/white"
android:textSize="@dimen/ts_20" />
</LinearLayout>
<com.github.tvbox.osc.subtitle.widget.SimpleSubtitleView
android:id="@+id/subtitle_view"

Loading…
Cancel
Save