This commit is contained in:
LagradOst 2023-10-26 21:40:45 +02:00
parent afe82140fd
commit 49b905c089
6 changed files with 147 additions and 21 deletions

View file

@ -261,7 +261,7 @@ dependencies {
// color palette for images -> colors // color palette for images -> colors
implementation("androidx.palette:palette-ktx:1.0.0") implementation("androidx.palette:palette-ktx:1.0.0")
implementation("com.github.recloudstream:Aria2cStream:0.0.1") implementation("com.github.recloudstream:Aria2cStream:0.0.3")
} }
tasks.register("androidSourcesJar", Jar::class) { tasks.register("androidSourcesJar", Jar::class) {

View file

@ -1569,14 +1569,13 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
//val defaultDirectory = "${filesDir.path}/torrent_tmp" //val defaultDirectory = "${filesDir.path}/torrent_tmp"
//File(defaultDirectory).deleteRecursively() //File(defaultDirectory).deleteRecursively()
navigate( /*navigate(
R.id.global_to_navigation_player, GeneratorPlayer.newInstance( R.id.global_to_navigation_player, GeneratorPlayer.newInstance(
ExtractorLinkGenerator( ExtractorLinkGenerator(
listOf( listOf(
ExtractorLink( ExtractorLink(
source = "", source = "",
name = "hello world", name = "hello world",
url = "",
"", "",
Qualities.Unknown.value, Qualities.Unknown.value,
type = INFER_TYPE type = INFER_TYPE
@ -1585,7 +1584,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
emptyList() emptyList()
) )
) )
) )*/
// Used to check current focus for TV // Used to check current focus for TV
// main { // main {

View file

@ -135,7 +135,7 @@ abstract class AbstractPlayerFragment(
} }
} }
private fun updateIsPlaying(wasPlaying : CSPlayerLoading, open fun updateIsPlaying(wasPlaying : CSPlayerLoading,
isPlaying : CSPlayerLoading) { isPlaying : CSPlayerLoading) {
val isPlayingRightNow = CSPlayerLoading.IsPlaying == isPlaying val isPlayingRightNow = CSPlayerLoading.IsPlaying == isPlaying
val isPausedRightNow = CSPlayerLoading.IsPaused == isPlaying val isPausedRightNow = CSPlayerLoading.IsPaused == isPlaying

View file

@ -56,6 +56,7 @@ import com.lagradost.cloudstream3.TvType
import com.lagradost.cloudstream3.USER_AGENT import com.lagradost.cloudstream3.USER_AGENT
import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.mvvm.debugAssert import com.lagradost.cloudstream3.mvvm.debugAssert
import com.lagradost.cloudstream3.mvvm.launchSafe
import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
import com.lagradost.cloudstream3.ui.subtitles.SaveCaptionStyle import com.lagradost.cloudstream3.ui.subtitles.SaveCaptionStyle
@ -67,10 +68,15 @@ import com.lagradost.cloudstream3.utils.ExtractorLinkPlayList
import com.lagradost.cloudstream3.utils.ExtractorLinkType import com.lagradost.cloudstream3.utils.ExtractorLinkType
import com.lagradost.cloudstream3.utils.ExtractorUri import com.lagradost.cloudstream3.utils.ExtractorUri
import com.lagradost.cloudstream3.utils.SubtitleHelper.fromTwoLettersToLanguage import com.lagradost.cloudstream3.utils.SubtitleHelper.fromTwoLettersToLanguage
import com.lagradost.fetchbutton.aria2c.Aria2Args
import com.lagradost.fetchbutton.aria2c.Aria2Settings import com.lagradost.fetchbutton.aria2c.Aria2Settings
import com.lagradost.fetchbutton.aria2c.Aria2Starter import com.lagradost.fetchbutton.aria2c.Aria2Starter
import com.lagradost.fetchbutton.aria2c.BtPieceSelector
import com.lagradost.fetchbutton.aria2c.DownloadListener import com.lagradost.fetchbutton.aria2c.DownloadListener
import com.lagradost.fetchbutton.aria2c.DownloadStatusTell import com.lagradost.fetchbutton.aria2c.DownloadStatusTell
import com.lagradost.fetchbutton.aria2c.FileAllocationType
import com.lagradost.fetchbutton.aria2c.FollowMetaLinkType
import com.lagradost.fetchbutton.aria2c.UriRequest
import com.lagradost.fetchbutton.aria2c.newUriRequest import com.lagradost.fetchbutton.aria2c.newUriRequest
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -119,6 +125,9 @@ class CS3IPlayer : IPlayer {
private var lastMuteVolume: Float = 1.0f private var lastMuteVolume: Float = 1.0f
private var currentLink: ExtractorLink? = null private var currentLink: ExtractorLink? = null
private var currentAria2cRequestLink: ExtractorLink? = null
private var currentAria2cRequestId: Long? = null
private var currentDownloadedFile: ExtractorUri? = null private var currentDownloadedFile: ExtractorUri? = null
private var hasUsedFirstRender = false private var hasUsedFirstRender = false
@ -262,7 +271,7 @@ class CS3IPlayer : IPlayer {
link: ExtractorLink, link: ExtractorLink,
requestId: Long, requestId: Long,
) { ) {
val minimumBytes : Long = 30 shl 20 val minimumBytes: Long = 30 shl 20
var hasFileChecked = false var hasFileChecked = false
while (true) { while (true) {
val gid = DownloadListener.sessionIdToGid[requestId] val gid = DownloadListener.sessionIdToGid[requestId]
@ -354,6 +363,8 @@ class CS3IPlayer : IPlayer {
?: throw Exception("Not downloaded enough") ?: throw Exception("Not downloaded enough")
activity.runOnUiThread { activity.runOnUiThread {
//Log.i(TAG, "downloaded data: $metadata") //Log.i(TAG, "downloaded data: $metadata")
exoPlayer?.release()
exoPlayer = null
loadOfflinePlayer( loadOfflinePlayer(
activity, activity,
ExtractorUri( ExtractorUri(
@ -400,13 +411,64 @@ class CS3IPlayer : IPlayer {
private suspend fun playAria2c(activity: Activity, link: ExtractorLink) { private suspend fun playAria2c(activity: Activity, link: ExtractorLink) {
// ephemeral id based on url to make it unique // ephemeral id based on url to make it unique
val requestId = link.url.hashCode().toLong() val requestId = link.url.hashCode().toLong()
currentAria2cRequestId = requestId
currentAria2cRequestLink = link
val uriReq = newUriRequest( val uriReq = UriRequest(
id = requestId, id = requestId,
uri = link.url, uris = listOf(link.url),
fileName = null, args = Aria2Args(
seed = false, headers = link.headers,
stream = true, referer = link.referer,
/** torrent specifics to make it possible to stream */
seedRatio = 0.0f,
seedTimeMin = 0.0f,
btPieceSelector = BtPieceSelector.Inorder,
followTorrent = FollowMetaLinkType.Mem,
fileAllocation = FileAllocationType.None,
btPrioritizePiece = "head=30M,tail=30M",
/** Best trackers to make it faster */
btTracker = listOf(
"udp://tracker.opentrackr.org:1337/announce",
"https://tracker2.ctix.cn/announce",
"https://tracker1.520.jp:443/announce",
"udp://opentracker.i2p.rocks:6969/announce",
"udp://open.tracker.cl:1337/announce",
"udp://open.demonii.com:1337/announce",
"http://tracker.openbittorrent.com:80/announce",
"udp://tracker.openbittorrent.com:6969/announce",
"udp://open.stealth.si:80/announce",
"udp://exodus.desync.com:6969/announce",
"udp://tracker-udp.gbitt.info:80/announce",
"udp://explodie.org:6969/announce",
"https://tracker.gbitt.info:443/announce",
"http://tracker.gbitt.info:80/announce",
"udp://uploads.gamecoast.net:6969/announce",
"udp://tracker1.bt.moack.co.kr:80/announce",
"udp://tracker.tiny-vps.com:6969/announce",
"udp://tracker.theoks.net:6969/announce",
"udp://tracker.dump.cl:6969/announce",
"udp://tracker.bittor.pw:1337/announce",
"https://tracker1.520.jp:443/announce",
"udp://opentracker.i2p.rocks:6969/announce",
"udp://open.tracker.cl:1337/announce",
"udp://open.demonii.com:1337/announce",
"http://tracker.openbittorrent.com:80/announce",
"udp://tracker.openbittorrent.com:6969/announce",
"udp://open.stealth.si:80/announce",
"udp://exodus.desync.com:6969/announce",
"udp://tracker-udp.gbitt.info:80/announce",
"udp://explodie.org:6969/announce",
"https://tracker.gbitt.info:443/announce",
"http://tracker.gbitt.info:80/announce",
"udp://uploads.gamecoast.net:6969/announce",
"udp://tracker1.bt.moack.co.kr:80/announce",
"udp://tracker.tiny-vps.com:6969/announce",
"udp://tracker.theoks.net:6969/announce",
"udp://tracker.dump.cl:6969/announce",
"udp://tracker.bittor.pw:1337/announce"
)
)
) )
val metadata = val metadata =
@ -421,6 +483,7 @@ class CS3IPlayer : IPlayer {
} }
try { try {
saveData()
awaitAria2c(activity, link, requestId) awaitAria2c(activity, link, requestId)
} catch (t: Throwable) { } catch (t: Throwable) {
// if we detect any download error then we delete it as we don't want any useless background tasks // if we detect any download error then we delete it as we don't want any useless background tasks
@ -500,6 +563,7 @@ class CS3IPlayer : IPlayer {
if (link != null) { if (link != null) {
loadOnlinePlayer(context, link) loadOnlinePlayer(context, link)
} else if (data != null) { } else if (data != null) {
currentAria2cRequestId = null
loadOfflinePlayer(context, data) loadOfflinePlayer(context, data)
} }
} }
@ -1320,10 +1384,64 @@ class CS3IPlayer : IPlayer {
} }
override fun onPlayerError(error: PlaybackException) { override fun onPlayerError(error: PlaybackException) {
// If the Network fails then ignore the exception if the duration is set. val aria2cRequestId = currentAria2cRequestId
// This is to switch mirrors automatically if the stream has not been fetched, but val loadedLink = currentAria2cRequestLink
// allow playing the buffer without internet as then the duration is fetched.
when { when {
// if we are loading an torrent, then we will get these errors, in that case
// we just treat it as buffering
aria2cRequestId != null && loadedLink != null &&
(error.errorCode == PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE
|| error.errorCode == PlaybackException.ERROR_CODE_PARSING_MANIFEST_MALFORMED
|| error.errorCode == PlaybackException.ERROR_CODE_PARSING_CONTAINER_MALFORMED
|| error.errorCode == PlaybackException.ERROR_CODE_PARSING_CONTAINER_UNSUPPORTED
) -> {
val gid = DownloadListener.sessionIdToGid[aria2cRequestId]
Log.i(TAG, "Aria2 error $error error ${error.errorCode}")
if(gid == null) {
event(ErrorEvent(error))
super.onPlayerError(error)
return
}
event(
StatusEvent(
wasPlaying = CSPlayerLoading.IsPlaying,
isPlaying = CSPlayerLoading.IsBuffering
)
)
CoroutineScope(Dispatchers.IO).launchSafe {
for (i in 0..5) {
val metadata = DownloadListener.getInfo(gid)
event(
DownloadEvent(
downloadedBytes = metadata.downloadedLength,
downloadSpeed = metadata.downloadSpeed,
totalBytes = metadata.totalLength,
connections = metadata.items.sumOf { it.connections }
)
)
delay(1000)
}
// CommonActivity.activity?.runOnUiThread {
// exoPlayer?.prepare()
// }
// shitty solution to release it every time, however we will get timeout otherwise
CommonActivity.activity?.let { act ->
try {
awaitAria2c(act, loadedLink, aria2cRequestId)
} catch (t : Throwable) {
event(ErrorEvent(t))
}
}
}
}
// If the Network fails then ignore the exception if the duration is set.
// This is to switch mirrors automatically if the stream has not been fetched, but
// allow playing the buffer without internet as then the duration is fetched.
error.errorCode == PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED error.errorCode == PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED
&& exoPlayer?.duration != TIME_UNSET -> { && exoPlayer?.duration != TIME_UNSET -> {
exoPlayer?.prepare() exoPlayer?.prepare()
@ -1554,6 +1672,7 @@ class CS3IPlayer : IPlayer {
Log.i(TAG, "loadOnlinePlayer $link") Log.i(TAG, "loadOnlinePlayer $link")
try { try {
currentLink = link currentLink = link
currentAria2cRequestId = null
if (ignoreSSL) { if (ignoreSSL) {
// Disables ssl check // Disables ssl check

View file

@ -109,6 +109,14 @@ class GeneratorPlayer : FullScreenPlayer() {
showDownloadProgress(event) showDownloadProgress(event)
} }
/*override fun updateIsPlaying(wasPlaying: CSPlayerLoading, isPlaying: CSPlayerLoading) {
super.updateIsPlaying(wasPlaying, isPlaying)
if(isPlaying == CSPlayerLoading.IsPlaying)
activity?.runOnUiThread {
}
}*/
private fun showDownloadProgress(event: DownloadEvent?) { private fun showDownloadProgress(event: DownloadEvent?) {
activity?.runOnUiThread { activity?.runOnUiThread {
if(event == null) { if(event == null) {

View file

@ -30,19 +30,19 @@
app:show_timeout="0" /> app:show_timeout="0" />
<FrameLayout <FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black" android:background="@android:color/black"
android:backgroundTint="@android:color/black"> android:backgroundTint="@android:color/black"
android:id="@+id/download_header"
android:visibility="gone"
tools:visibility="visible"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout <LinearLayout
android:id="@+id/download_header"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:gravity="center" android:gravity="center"
android:orientation="vertical" android:orientation="vertical">
android:visibility="gone"
tools:visibility="visible">
<TextView <TextView
android:id="@+id/downloaded_progress_text" android:id="@+id/downloaded_progress_text"