diff --git a/.gitmodules b/.gitmodules index cfc1f2fa..388021f4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -70,3 +70,15 @@ [submodule "app/src/unstable/assets/sources/spotify"] path = app/src/unstable/assets/sources/spotify url = ../plugins/spotify.git +[submodule "app/src/stable/assets/sources/bitchute"] + path = app/src/stable/assets/sources/bitchute + url = ../plugins/bitchute.git +[submodule "app/src/unstable/assets/sources/bitchute"] + path = app/src/unstable/assets/sources/bitchute + url = ../plugins/bitchute.git +[submodule "app/src/unstable/assets/sources/dailymotion"] + path = app/src/unstable/assets/sources/dailymotion + url = ../plugins/dailymotion.git +[submodule "app/src/stable/assets/sources/dailymotion"] + path = app/src/stable/assets/sources/dailymotion + url = ../plugins/dailymotion.git diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSSource.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSSource.kt index a658f5cb..45ace168 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSSource.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSSource.kt @@ -50,7 +50,7 @@ abstract class JSSource { _requestExecutor = obj.getOrDefault(_config, "requestExecutor", "JSSource.requestExecutor", null)?.let { JSRequest(plugin, it, null, null, true); } - hasRequestExecutor = _requestModifier != null || obj.has("getRequestExecutor"); + hasRequestExecutor = _requestExecutor != null || obj.has("getRequestExecutor"); } fun getRequestModifier(): IRequestModifier? { diff --git a/app/src/main/java/com/futo/platformplayer/downloads/VideoDownload.kt b/app/src/main/java/com/futo/platformplayer/downloads/VideoDownload.kt index b5e96b11..7de33363 100644 --- a/app/src/main/java/com/futo/platformplayer/downloads/VideoDownload.kt +++ b/app/src/main/java/com/futo/platformplayer/downloads/VideoDownload.kt @@ -94,6 +94,18 @@ class VideoDownload { @Transient val audioSourceToUse: IAudioSource? get () = if(requiresLiveAudioSource) audioSourceLive as IAudioSource? else audioSource as IAudioSource?; + var requireVideoSource: Boolean = false; + var requireAudioSource: Boolean = false; + + @Contextual + @Transient + val isVideoDownloadReady: Boolean get() = !requireVideoSource || + ((requiresLiveVideoSource && isLiveVideoSourceValid) || (!requiresLiveVideoSource && videoSource != null)); + @Contextual + @Transient + val isAudioDownloadReady: Boolean get() = !requireAudioSource || + ((requiresLiveAudioSource && isLiveAudioSourceValid) || (!requiresLiveAudioSource && audioSource != null)); + var subtitleSource: SubtitleRawSource?; @kotlinx.serialization.Serializable(with = OffsetDateTimeNullableSerializer::class) @@ -159,6 +171,8 @@ class VideoDownload { this.requiresLiveVideoSource = false; this.requiresLiveAudioSource = false; this.targetVideoName = videoSource?.name; + this.requireVideoSource = targetPixelCount != null + this.requireAudioSource = targetBitrate != null; //TODO: May not be a valid check.. can only be determined after live fetch? } constructor(video: IPlatformVideoDetails, videoSource: IVideoSource?, audioSource: IAudioSource?, subtitleSource: SubtitleRawSource?) { this.video = SerializedPlatformVideo.fromVideo(video); @@ -177,6 +191,8 @@ class VideoDownload { this.targetAudioName = audioSource?.name; this.targetPixelCount = if(videoSource != null) (videoSource.width * videoSource.height).toLong() else null; this.targetBitrate = if(audioSource != null) audioSource.bitrate.toLong() else null; + this.requireVideoSource = videoSource != null; + this.requireAudioSource = audioSource != null; } fun withGroup(groupType: String, groupID: String): VideoDownload { @@ -322,8 +338,10 @@ class VideoDownload { throw DownloadException("Audio source is not supported for downloading (yet)", false); } - if(((!requiresLiveVideoSource && videoSource == null) || (requiresLiveVideoSource && !isLiveVideoSourceValid)) || ((!requiresLiveAudioSource && audioSource == null) || (requiresLiveAudioSource && !isLiveAudioSourceValid))) - throw DownloadException("No valid sources found for video/audio"); + if(!isVideoDownloadReady) + throw DownloadException("No valid sources found for video"); + if(!isAudioDownloadReady) + throw DownloadException("No valid sources found for audio"); } } @@ -369,6 +387,7 @@ class VideoDownload { sourcesToDownload.add(async { Logger.i(TAG, "Started downloading video"); + var lastEmit = 0L; val progressCallback = { length: Long, totalRead: Long, speed: Long -> synchronized(progressLock) { lastVideoLength = length; @@ -381,9 +400,14 @@ class VideoDownload { val total = lastVideoRead + lastAudioRead; if(totalLength > 0) { val percentage = (total / totalLength.toDouble()); - onProgress?.invoke(percentage); progress = percentage; - onProgressChanged.emit(percentage); + + val now = System.currentTimeMillis(); + if(now - lastEmit > 200) { + lastEmit = System.currentTimeMillis(); + onProgress?.invoke(percentage); + onProgressChanged.emit(percentage); + } } } } @@ -403,6 +427,7 @@ class VideoDownload { sourcesToDownload.add(async { Logger.i(TAG, "Started downloading audio"); + var lastEmit = 0L; val progressCallback = { length: Long, totalRead: Long, speed: Long -> synchronized(progressLock) { lastAudioLength = length; @@ -415,9 +440,14 @@ class VideoDownload { val total = lastVideoRead + lastAudioRead; if(totalLength > 0) { val percentage = (total / totalLength.toDouble()); - onProgress?.invoke(percentage); progress = percentage; - onProgressChanged.emit(percentage); + + val now = System.currentTimeMillis(); + if(now - lastEmit > 200) { + lastEmit = System.currentTimeMillis(); + onProgress?.invoke(percentage); + onProgressChanged.emit(percentage); + } } } } diff --git a/app/src/main/java/com/futo/platformplayer/helpers/VideoHelper.kt b/app/src/main/java/com/futo/platformplayer/helpers/VideoHelper.kt index 860c2daa..23fa2b73 100644 --- a/app/src/main/java/com/futo/platformplayer/helpers/VideoHelper.kt +++ b/app/src/main/java/com/futo/platformplayer/helpers/VideoHelper.kt @@ -193,7 +193,7 @@ class VideoHelper { fun estimateSourceSize(source: IVideoSource?): Int { if(source == null) return 0; - if(source is IVideoUrlSource) { + if(source is IVideoSource) { if(source.bitrate ?: 0 <= 0 || source.duration.toInt() == 0) return 0; return (source.duration / 8).toInt() * source.bitrate!!; @@ -202,7 +202,7 @@ class VideoHelper { } fun estimateSourceSize(source: IAudioSource?): Int { if(source == null) return 0; - if(source is IAudioUrlSource) { + if(source is IAudioSource) { if(source.bitrate <= 0 || source.duration?.toInt() ?: 0 == 0) return 0; return (source.duration!! / 8).toInt() * source.bitrate; diff --git a/app/src/main/java/com/futo/platformplayer/services/DownloadService.kt b/app/src/main/java/com/futo/platformplayer/services/DownloadService.kt index 86f8a07b..39fc5562 100644 --- a/app/src/main/java/com/futo/platformplayer/services/DownloadService.kt +++ b/app/src/main/java/com/futo/platformplayer/services/DownloadService.kt @@ -205,9 +205,7 @@ class DownloadService : Service() { download.targetBitrate = download.audioSource!!.bitrate.toLong(); download.audioSource = null; } - if(download.videoDetails == null || - ((download.videoSource == null && download.audioSource == null) && - (download.requiresLiveVideoSource && !download.isLiveVideoSourceValid) && (download.requiresLiveAudioSource && !download.isLiveAudioSourceValid))) + if(download.videoDetails == null || (!download.isVideoDownloadReady || !download.isAudioDownloadReady)) download.changeState(VideoDownload.State.PREPARING); notifyDownload(download); @@ -224,7 +222,7 @@ class DownloadService : Service() { download.progress = progress; val currentTime = System.currentTimeMillis(); - if (currentTime - lastNotifyTime > 500) { + if (currentTime - lastNotifyTime > 800) { notifyDownload(download); lastNotifyTime = currentTime; } diff --git a/app/src/stable/AndroidManifest.xml b/app/src/stable/AndroidManifest.xml index a5fdd260..a30bb7af 100644 --- a/app/src/stable/AndroidManifest.xml +++ b/app/src/stable/AndroidManifest.xml @@ -33,6 +33,11 @@ + + + + + @@ -57,6 +62,11 @@ + + + + + diff --git a/app/src/stable/assets/sources/bitchute b/app/src/stable/assets/sources/bitchute new file mode 160000 index 00000000..41fe8f79 --- /dev/null +++ b/app/src/stable/assets/sources/bitchute @@ -0,0 +1 @@ +Subproject commit 41fe8f79735176cd8a0ae8c971936cafed00fa16 diff --git a/app/src/stable/assets/sources/dailymotion b/app/src/stable/assets/sources/dailymotion new file mode 160000 index 00000000..069aa3d3 --- /dev/null +++ b/app/src/stable/assets/sources/dailymotion @@ -0,0 +1 @@ +Subproject commit 069aa3d31a35559e45c1fe1ea1eb2a94d3b5d120 diff --git a/app/src/stable/res/raw/plugin_config.json b/app/src/stable/res/raw/plugin_config.json index a1da4004..3b7dacec 100644 --- a/app/src/stable/res/raw/plugin_config.json +++ b/app/src/stable/res/raw/plugin_config.json @@ -10,7 +10,9 @@ "aac9e9f0-24b5-11ee-be56-0242ac120002": "sources/patreon/PatreonConfig.json", "9d703ff5-c556-4962-a990-4f000829cb87": "sources/nebula/NebulaConfig.json", "cf8ea74d-ad9b-489e-a083-539b6aa8648c": "sources/bilibili/build/BiliBiliConfig.json", - "4e365633-6d3f-4267-8941-fdc36631d813": "sources/spotify/build/SpotifyConfig.json" + "4e365633-6d3f-4267-8941-fdc36631d813": "sources/spotify/build/SpotifyConfig.json", + "9c87e8db-e75d-48f4-afe5-2d203d4b95c5": "sources/dailymotion/build/DailymotionConfig.json", + "e8b1ad5f-0c6d-497d-a5fa-0a785a16d902": "sources/bitchute/BitchuteConfig.json" }, "SOURCES_EMBEDDED_DEFAULT": [ "35ae969a-a7db-11ed-afa1-0242ac120002" diff --git a/app/src/unstable/AndroidManifest.xml b/app/src/unstable/AndroidManifest.xml index 9affd8ab..1304222e 100644 --- a/app/src/unstable/AndroidManifest.xml +++ b/app/src/unstable/AndroidManifest.xml @@ -34,6 +34,11 @@ + + + + + @@ -58,6 +63,11 @@ + + + + + diff --git a/app/src/unstable/assets/sources/bitchute b/app/src/unstable/assets/sources/bitchute new file mode 160000 index 00000000..41fe8f79 --- /dev/null +++ b/app/src/unstable/assets/sources/bitchute @@ -0,0 +1 @@ +Subproject commit 41fe8f79735176cd8a0ae8c971936cafed00fa16 diff --git a/app/src/unstable/assets/sources/dailymotion b/app/src/unstable/assets/sources/dailymotion new file mode 160000 index 00000000..069aa3d3 --- /dev/null +++ b/app/src/unstable/assets/sources/dailymotion @@ -0,0 +1 @@ +Subproject commit 069aa3d31a35559e45c1fe1ea1eb2a94d3b5d120 diff --git a/app/src/unstable/res/raw/plugin_config.json b/app/src/unstable/res/raw/plugin_config.json index 551c5470..4e4cc1dc 100644 --- a/app/src/unstable/res/raw/plugin_config.json +++ b/app/src/unstable/res/raw/plugin_config.json @@ -10,7 +10,9 @@ "aac9e9f0-24b5-11ee-be56-0242ac120002": "sources/patreon/PatreonConfig.json", "9d703ff5-c556-4962-a990-4f000829cb87": "sources/nebula/NebulaConfig.json", "cf8ea74d-ad9b-489e-a083-539b6aa8648c": "sources/bilibili/build/BiliBiliConfig.json", - "4e365633-6d3f-4267-8941-fdc36631d813": "sources/spotify/build/SpotifyConfig.json" + "4e365633-6d3f-4267-8941-fdc36631d813": "sources/spotify/build/SpotifyConfig.json", + "9c87e8db-e75d-48f4-afe5-2d203d4b95c5": "sources/dailymotion/build/DailymotionConfig.json", + "e8b1ad5f-0c6d-497d-a5fa-0a785a16d902": "sources/bitchute/BitchuteConfig.json" }, "SOURCES_EMBEDDED_DEFAULT": [ "35ae969a-a7db-11ed-afa1-0242ac120002"