Skip to content

Commit

Permalink
Merge branch 'develop' of github.com:ourfor/iPlay into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
ourfor committed Dec 10, 2024
2 parents 2096581 + c12ece2 commit 221319d
Show file tree
Hide file tree
Showing 65 changed files with 1,600 additions and 416 deletions.
4 changes: 3 additions & 1 deletion android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ dependencies {
implementation(libs.jackson.annotations)
implementation(libs.jackson.databind)

implementation(libs.libvlc.all)

// http
implementation(libs.okhttp)

Expand Down Expand Up @@ -115,5 +117,5 @@ dependencies {
implementation libs.androidx.room.runtime
annotationProcessor libs.androidx.room.compiler

debugImplementation("com.reqable.android:user-certificate-trust:1.0.0")
debugImplementation(libs.user.certificate.trust)
}
10 changes: 1 addition & 9 deletions android/app/src/main/java/top/ourfor/app/iplayx/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@

import androidx.appcompat.app.AppCompatDelegate;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
Expand All @@ -18,10 +16,8 @@
import lombok.val;
import top.ourfor.app.iplayx.bean.JSONAdapter;
import top.ourfor.app.iplayx.bean.KVStorage;
import top.ourfor.app.iplayx.common.annotation.ViewController;
import top.ourfor.app.iplayx.config.AppSetting;
import top.ourfor.app.iplayx.module.FontModule;
import top.ourfor.app.iplayx.util.AnnotationUtil;
import top.ourfor.app.iplayx.util.DeviceUtil;
import top.ourfor.app.iplayx.util.JacksonJsonAdapter;
import top.ourfor.app.iplayx.util.MMKVStorage;
Expand All @@ -39,11 +35,7 @@ public void onCreate() {
val crashManager = new CrashManager(this);
Thread.setDefaultUncaughtExceptionHandler(crashManager);
val context = getApplicationContext();
try {
FontModule.scanExternalFont(context);
} catch (Exception e) {
log.error("failed scan external font", e);
}
FontModule.initFont(context);
DeviceUtil.init(context);
XSET(Application.class, this);
XSET(Context.class, context);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@
import lombok.EqualsAndHashCode;
import lombok.Setter;
import lombok.With;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import top.ourfor.app.iplayx.bean.JSONAdapter;
import top.ourfor.app.iplayx.common.api.EmbyLikeApi;
import top.ourfor.app.iplayx.common.type.MediaPlayState;
import top.ourfor.app.iplayx.model.EmbySiteInfo;
import top.ourfor.app.iplayx.store.GlobalStore;
import top.ourfor.app.iplayx.util.HTTPUtil;
import top.ourfor.app.iplayx.util.HTTPModel;
Expand All @@ -35,8 +37,9 @@
import top.ourfor.app.iplayx.common.model.SiteEndpointModel;
import top.ourfor.app.iplayx.model.SiteModel;

@Builder
@With
@Slf4j
@Builder
@EqualsAndHashCode
public class EmbyApi implements EmbyLikeApi {
private static final String kDeviceProfile = "{\"DeviceProfile\":{\"MaxStaticBitrate\":140000000,\"MaxStreamingBitrate\":140000000,\"MusicStreamingTranscodingBitrate\":192000,\"DirectPlayProfiles\":[{\"Container\":\"mp4,m4v\",\"Type\":\"Video\",\"VideoCodec\":\"h264,h265,hevc,vp8,vp9\",\"AudioCodec\":\"mp3,aac,opus,flac,vorbis\"},{\"Container\":\"mkv\",\"Type\":\"Video\",\"VideoCodec\":\"h264,h265,hevc,vp8,vp9\",\"AudioCodec\":\"mp3,aac,opus,flac,vorbis\"},{\"Container\":\"flv\",\"Type\":\"Video\",\"VideoCodec\":\"h264\",\"AudioCodec\":\"aac,mp3\"},{\"Container\":\"mov\",\"Type\":\"Video\",\"VideoCodec\":\"h264\",\"AudioCodec\":\"mp3,aac,opus,flac,vorbis\"},{\"Container\":\"opus\",\"Type\":\"Audio\"},{\"Container\":\"mp3\",\"Type\":\"Audio\",\"AudioCodec\":\"mp3\"},{\"Container\":\"mp2,mp3\",\"Type\":\"Audio\",\"AudioCodec\":\"mp2\"},{\"Container\":\"aac\",\"Type\":\"Audio\",\"AudioCodec\":\"aac\"},{\"Container\":\"m4a\",\"AudioCodec\":\"aac\",\"Type\":\"Audio\"},{\"Container\":\"mp4\",\"AudioCodec\":\"aac\",\"Type\":\"Audio\"},{\"Container\":\"flac\",\"Type\":\"Audio\"},{\"Container\":\"webma,webm\",\"Type\":\"Audio\"},{\"Container\":\"wav\",\"Type\":\"Audio\",\"AudioCodec\":\"PCM_S16LE,PCM_S24LE\"},{\"Container\":\"ogg\",\"Type\":\"Audio\"},{\"Container\":\"webm\",\"Type\":\"Video\",\"AudioCodec\":\"vorbis,opus\",\"VideoCodec\":\"VP8,VP9\"}],\"TranscodingProfiles\":[{\"Container\":\"aac\",\"Type\":\"Audio\",\"AudioCodec\":\"aac\",\"Context\":\"Streaming\",\"Protocol\":\"hls\",\"MaxAudioChannels\":\"2\",\"MinSegments\":\"2\",\"BreakOnNonKeyFrames\":true},{\"Container\":\"aac\",\"Type\":\"Audio\",\"AudioCodec\":\"aac\",\"Context\":\"Streaming\",\"Protocol\":\"http\",\"MaxAudioChannels\":\"2\"},{\"Container\":\"mp3\",\"Type\":\"Audio\",\"AudioCodec\":\"mp3\",\"Context\":\"Streaming\",\"Protocol\":\"http\",\"MaxAudioChannels\":\"2\"},{\"Container\":\"opus\",\"Type\":\"Audio\",\"AudioCodec\":\"opus\",\"Context\":\"Streaming\",\"Protocol\":\"http\",\"MaxAudioChannels\":\"2\"},{\"Container\":\"wav\",\"Type\":\"Audio\",\"AudioCodec\":\"wav\",\"Context\":\"Streaming\",\"Protocol\":\"http\",\"MaxAudioChannels\":\"2\"},{\"Container\":\"opus\",\"Type\":\"Audio\",\"AudioCodec\":\"opus\",\"Context\":\"Static\",\"Protocol\":\"http\",\"MaxAudioChannels\":\"2\"},{\"Container\":\"mp3\",\"Type\":\"Audio\",\"AudioCodec\":\"mp3\",\"Context\":\"Static\",\"Protocol\":\"http\",\"MaxAudioChannels\":\"2\"},{\"Container\":\"aac\",\"Type\":\"Audio\",\"AudioCodec\":\"aac\",\"Context\":\"Static\",\"Protocol\":\"http\",\"MaxAudioChannels\":\"2\"},{\"Container\":\"wav\",\"Type\":\"Audio\",\"AudioCodec\":\"wav\",\"Context\":\"Static\",\"Protocol\":\"http\",\"MaxAudioChannels\":\"2\"},{\"Container\":\"mkv\",\"Type\":\"Video\",\"AudioCodec\":\"mp3,aac,opus,flac,vorbis\",\"VideoCodec\":\"h264,h265,hevc,vp8,vp9\",\"Context\":\"Static\",\"MaxAudioChannels\":\"2\",\"CopyTimestamps\":true},{\"Container\":\"m4s,ts\",\"Type\":\"Video\",\"AudioCodec\":\"mp3,aac\",\"VideoCodec\":\"h264,h265,hevc\",\"Context\":\"Streaming\",\"Protocol\":\"hls\",\"MaxAudioChannels\":\"2\",\"MinSegments\":\"2\",\"BreakOnNonKeyFrames\":true,\"ManifestSubtitles\":\"vtt\"},{\"Container\":\"webm\",\"Type\":\"Video\",\"AudioCodec\":\"vorbis\",\"VideoCodec\":\"vpx\",\"Context\":\"Streaming\",\"Protocol\":\"http\",\"MaxAudioChannels\":\"2\"},{\"Container\":\"mp4\",\"Type\":\"Video\",\"AudioCodec\":\"mp3,aac,opus,flac,vorbis\",\"VideoCodec\":\"h264\",\"Context\":\"Static\",\"Protocol\":\"http\"}],\"ContainerProfiles\":[],\"CodecProfiles\":[{\"Type\":\"VideoAudio\",\"Codec\":\"aac\",\"Conditions\":[{\"Condition\":\"Equals\",\"Property\":\"IsSecondaryAudio\",\"Value\":\"false\",\"IsRequired\":\"false\"}]},{\"Type\":\"VideoAudio\",\"Conditions\":[{\"Condition\":\"Equals\",\"Property\":\"IsSecondaryAudio\",\"Value\":\"false\",\"IsRequired\":\"false\"}]},{\"Type\":\"Video\",\"Codec\":\"h264\",\"Conditions\":[{\"Condition\":\"EqualsAny\",\"Property\":\"VideoProfile\",\"Value\":\"high|main|baseline|constrained baseline|high 10\",\"IsRequired\":false},{\"Condition\":\"LessThanEqual\",\"Property\":\"VideoLevel\",\"Value\":\"62\",\"IsRequired\":false}]},{\"Type\":\"Video\",\"Codec\":\"hevc\",\"Conditions\":[{\"Condition\":\"EqualsAny\",\"Property\":\"VideoCodecTag\",\"Value\":\"hvc1\",\"IsRequired\":false}]}],\"SubtitleProfiles\":[{\"Format\":\"vtt\",\"Method\":\"Hls\"},{\"Format\":\"eia_608\",\"Method\":\"VideoSideData\",\"Protocol\":\"hls\"},{\"Format\":\"eia_708\",\"Method\":\"VideoSideData\",\"Protocol\":\"hls\"},{\"Format\":\"vtt\",\"Method\":\"External\"},{\"Format\":\"ass\",\"Method\":\"External\"},{\"Format\":\"ssa\",\"Method\":\"External\"}],\"ResponseProfiles\":[{\"Type\":\"Video\",\"Container\":\"m4v\",\"MimeType\":\"video/mp4\"}]}}\n";
Expand Down Expand Up @@ -80,7 +83,8 @@ public static void login(String server, String username, String password, Consum
return;
}
} catch (MalformedURLException | NullPointerException e) {
e.printStackTrace();
log.error("Failed to parse server url: {}", server);
log.error("Error: ", e);
}
completion.accept(null);
});
Expand Down Expand Up @@ -568,4 +572,30 @@ public void trackPlay(MediaPlayState state, EmbyPlaybackData data, Consumer<Obje
});

}

@Override
public void getSiteInfo(Consumer<Object> completion) {
if (site == null ||
site.getEndpoint() == null ||
site.getUser() == null) return;

// /emby/system/info/public
HTTPModel model = HTTPModel.builder()
.url(site.getEndpoint().getBaseUrl() + "emby/system/info/public")
.method("GET")
.modelClass(EmbySiteInfo.class)
.build();

HTTPUtil.request(model, response -> {
if (Objects.isNull(response)) {
completion.accept(null);
return;
}
if (response instanceof EmbySiteInfo) {
completion.accept(response);
return;
}
completion.accept(null);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import top.ourfor.app.iplayx.model.EmbyPageableModel;
import top.ourfor.app.iplayx.model.EmbyPlaybackData;
import top.ourfor.app.iplayx.model.EmbyPlaybackModel;
import top.ourfor.app.iplayx.model.EmbySiteInfo;
import top.ourfor.app.iplayx.model.EmbyUserData;
import top.ourfor.app.iplayx.model.EmbyUserModel;
import top.ourfor.app.iplayx.model.ImageType;
Expand All @@ -36,6 +37,7 @@
import top.ourfor.app.iplayx.util.HTTPModel;
import top.ourfor.app.iplayx.util.HTTPUtil;

@Setter
@Builder
@With
@EqualsAndHashCode
Expand All @@ -45,7 +47,6 @@ public class JellyfinApi implements EmbyLikeApi {
private static final String authHeaderValue = String.format("MediaBrowser Client=\"%s\", Device=\"%s\", DeviceId=\"%s\", Version=\"%s\"", "iPlay", "Android", "9999999", "v1.0.0");


@Setter
SiteModel site;

public static void login(String server, String username, String password, Consumer<Object> completion) {
Expand Down Expand Up @@ -579,4 +580,30 @@ public void getSimilar(String id, Consumer<Object> completion) {
completion.accept(null);
});
}

@Override
public void getSiteInfo(Consumer<Object> completion) {
if (site == null ||
site.getEndpoint() == null ||
site.getUser() == null) return;

// /emby/system/info/public
HTTPModel model = HTTPModel.builder()
.url(site.getEndpoint().getBaseUrl() + "system/info/public")
.method("GET")
.modelClass(EmbySiteInfo.class)
.build();

HTTPUtil.request(model, response -> {
if (Objects.isNull(response)) {
completion.accept(null);
return;
}
if (response instanceof EmbySiteInfo) {
completion.accept(response);
return;
}
completion.accept(null);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ default void setSiteModel(SiteModel site) { }

static void login(String server, String username, String password, Consumer<Object> completion) { }

default void getSiteInfo(Consumer<Object> completion) { }

default void getAlbums(Consumer<Object> completion) { }

default void getAlbumLatestMedias(String id, Consumer<Object> completion) { }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package top.ourfor.app.iplayx.common.type;

public enum PlayerKernelType {
MPV,
EXO,
VLC,
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import lombok.val;
import top.ourfor.app.iplayx.bean.KVStorage;
import top.ourfor.app.iplayx.common.type.LayoutType;
import top.ourfor.app.iplayx.common.type.PlayerKernelType;
import top.ourfor.app.iplayx.common.type.VideoDecodeType;
import top.ourfor.app.iplayx.common.type.PictureQuality;
import top.ourfor.app.iplayx.page.setting.theme.ThemeColorModel;
Expand All @@ -42,6 +43,7 @@ public class AppSetting {
public PictureQuality pictureQuality;
public boolean usePictureMultiThread;
public boolean useExoPlayer;
public PlayerKernelType playerKernel;
public String mpvConfig;
public String fontFamily;
public String webHomePage;
Expand All @@ -58,11 +60,11 @@ static AppSetting getShared() {
instance.turnOffAutoUpgrade = DeviceUtil.isTV || DeviceUtil.isDebugPackage;
instance.webHomePage = "https://bing.com";
instance.pictureQuality = PictureQuality.Auto;
instance.useExoPlayer = false;
instance.playerKernel = PlayerKernelType.MPV;
instance.layoutType = LayoutType.Auto;
if (DeviceUtil.isTV) {
instance.videoDecodeType = VideoDecodeType.Hardware;
instance.useExoPlayer = true;
instance.playerKernel = PlayerKernelType.EXO;
}
}
return instance;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package top.ourfor.app.iplayx.model;

import com.fasterxml.jackson.annotation.JsonProperty;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.With;

@Data
@With
@Builder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
public class EmbySiteInfo {
@JsonProperty("ServerName")
String ServerName;
@JsonProperty("Version")
String Version;
@JsonProperty("Id")
String Id;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
import java.util.List;
import java.util.Map;

import lombok.extern.slf4j.Slf4j;
import top.ourfor.app.iplayx.config.AppSetting;

@Slf4j
public class FontModule {
static private String moduleName = "FontModule";

static private Map<String, Typeface> systemFontMap;

static Map<String, Typeface> getSystemFontMap() throws NoSuchFieldException, IllegalAccessException {
Expand All @@ -28,10 +28,8 @@ static Map<String, Typeface> getSystemFontMap() throws NoSuchFieldException, Ill
static public void obtainSystemFont() {
try {
systemFontMap = getSystemFontMap();
} catch (NoSuchFieldException e) {
Log.d(moduleName, e.toString());
} catch (IllegalAccessException e) {
Log.d(moduleName, e.toString());
} catch (NoSuchFieldException | IllegalAccessException e) {
log.error("obtain system font failed", e);
}
}

Expand All @@ -58,15 +56,23 @@ public static String getFontPath(Context context) {
return fontDir.getPath();
}

public static void initFont(Context context) {
try {
scanExternalFont(context);
} catch (Exception e) {
log.error("scan external font failed", e);
}
}

public static void scanExternalFont(Context context) throws IllegalAccessException, NoSuchMethodException, NoSuchFieldException {
File filesDir = context.getExternalFilesDir("");
File fontDir = new File(filesDir, "font");
if (!fontDir.exists()) {
boolean created = fontDir.mkdirs();
if (created) {
Log.d(moduleName, "create fontDir success: " + fontDir.getPath());
log.debug("create fontDir success: {}", fontDir.getPath());
} else {
Log.d(moduleName, "create fontDir failed: " + fontDir.getPath());
log.debug("create fontDir failed: {}", fontDir.getPath());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

public interface Page {
default int id() { return -1; }
default String title() { return null; }
default void create(Context context, Map<String, Object> params) {}
default void destroy() {}

Expand Down
12 changes: 7 additions & 5 deletions android/app/src/main/java/top/ourfor/app/iplayx/page/Router.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ public class Router implements Navigator {
pageType.put(R.id.audioPage, PageType.AUDIO_CONFIG);
pageType.put(R.id.playerPage, PageType.PLAYER);
pageType.put(R.id.musicPage, PageType.MUSIC);
pageType.put(R.id.cachePage, PageType.CACHE);
pageType.put(R.id.picturePage, PageType.IMAGE_CONFIG);
pageType.put(R.id.musicPlayerPage, PageType.MUSIC_PLAYER);
pageType.put(R.id.webPage, PageType.WEB);
}
Expand Down Expand Up @@ -156,9 +158,9 @@ public void pushPage(String name, Map<String, Object> params) {
public void pushPage(Page newPage, Map<String, Object> params) {
val pages = navigators.computeIfAbsent(stackId, k -> new Stack<>());
if (pages.isEmpty()) return;
val page = pages.peek();
page.viewWillDisappear();
pageId.put(newPage, page.id());
val oldPage = pages.peek();
oldPage.viewWillDisappear();
pageId.put(newPage, oldPage.id());
newPage.create(container.getContext(), params);
pages.push(newPage);
val view = newPage.view();
Expand All @@ -168,8 +170,8 @@ public void pushPage(Page newPage, Map<String, Object> params) {
if (view instanceof PageLifecycle lifecycle) {
lifecycle.onAttach();
}
pushPageAnimation(page, newPage);
onNavigateChange(page.id());
pushPageAnimation(oldPage, newPage);
onNavigateChange(newPage.id());
}

@Override
Expand Down
Loading

0 comments on commit 221319d

Please sign in to comment.