152 lines
No EOL
5.9 KiB
Kotlin
152 lines
No EOL
5.9 KiB
Kotlin
package ani.dantotsu.download.video
|
|
|
|
import android.annotation.SuppressLint
|
|
import android.content.Context
|
|
import android.net.Uri
|
|
import androidx.media3.common.C
|
|
import androidx.media3.common.MediaItem
|
|
import androidx.media3.common.MimeTypes
|
|
import androidx.media3.common.TrackSelectionParameters
|
|
import androidx.media3.common.util.UnstableApi
|
|
import androidx.media3.database.StandaloneDatabaseProvider
|
|
import androidx.media3.datasource.DataSource
|
|
import androidx.media3.datasource.HttpDataSource
|
|
import androidx.media3.datasource.cache.NoOpCacheEvictor
|
|
import androidx.media3.datasource.cache.SimpleCache
|
|
import androidx.media3.datasource.okhttp.OkHttpDataSource
|
|
import androidx.media3.exoplayer.DefaultRenderersFactory
|
|
import androidx.media3.exoplayer.offline.DownloadHelper
|
|
import androidx.media3.exoplayer.offline.DownloadManager
|
|
import androidx.media3.exoplayer.offline.DownloadService
|
|
import androidx.media3.exoplayer.scheduler.Requirements
|
|
import androidx.media3.ui.TrackSelectionDialogBuilder
|
|
import ani.dantotsu.R
|
|
import ani.dantotsu.defaultHeaders
|
|
import ani.dantotsu.logError
|
|
import ani.dantotsu.okHttpClient
|
|
import ani.dantotsu.parsers.Subtitle
|
|
import ani.dantotsu.parsers.SubtitleType
|
|
import ani.dantotsu.parsers.Video
|
|
import ani.dantotsu.parsers.VideoType
|
|
import java.io.File
|
|
import java.io.IOException
|
|
import java.util.concurrent.*
|
|
|
|
object Helper {
|
|
|
|
@SuppressLint("UnsafeOptInUsageError")
|
|
fun downloadVideo(context : Context, video: Video, subtitle: Subtitle?){
|
|
val dataSourceFactory = DataSource.Factory {
|
|
val dataSource: HttpDataSource = OkHttpDataSource.Factory(okHttpClient).createDataSource()
|
|
defaultHeaders.forEach {
|
|
dataSource.setRequestProperty(it.key, it.value)
|
|
}
|
|
video.file.headers.forEach {
|
|
dataSource.setRequestProperty(it.key, it.value)
|
|
}
|
|
dataSource
|
|
}
|
|
val mimeType = when (video.format) {
|
|
VideoType.M3U8 -> MimeTypes.APPLICATION_M3U8
|
|
VideoType.DASH -> MimeTypes.APPLICATION_MPD
|
|
else -> MimeTypes.APPLICATION_MP4
|
|
}
|
|
|
|
val builder = MediaItem.Builder().setUri(video.file.url).setMimeType(mimeType)
|
|
var sub: MediaItem.SubtitleConfiguration? = null
|
|
if (subtitle != null) {
|
|
sub = MediaItem.SubtitleConfiguration
|
|
.Builder(Uri.parse(subtitle.file.url))
|
|
.setSelectionFlags(C.SELECTION_FLAG_FORCED)
|
|
.setMimeType(
|
|
when (subtitle.type) {
|
|
SubtitleType.VTT -> MimeTypes.TEXT_VTT
|
|
SubtitleType.ASS -> MimeTypes.TEXT_SSA
|
|
SubtitleType.SRT -> MimeTypes.APPLICATION_SUBRIP
|
|
SubtitleType.UNKNOWN -> MimeTypes.TEXT_SSA
|
|
}
|
|
)
|
|
.build()
|
|
}
|
|
if (sub != null) builder.setSubtitleConfigurations(mutableListOf(sub))
|
|
val mediaItem = builder.build()
|
|
val downloadHelper = DownloadHelper.forMediaItem(
|
|
context,
|
|
mediaItem,
|
|
DefaultRenderersFactory(context),
|
|
dataSourceFactory
|
|
)
|
|
downloadHelper.prepare(object : DownloadHelper.Callback{
|
|
override fun onPrepared(helper: DownloadHelper) {
|
|
TrackSelectionDialogBuilder(context,"Select thingy",helper.getTracks(0).groups
|
|
) { _, overrides ->
|
|
val params = TrackSelectionParameters.Builder(context)
|
|
overrides.forEach{
|
|
params.addOverride(it.value)
|
|
}
|
|
helper.addTrackSelection(0, params.build())
|
|
MyDownloadService
|
|
DownloadService.sendAddDownload(
|
|
context,
|
|
MyDownloadService::class.java,
|
|
helper.getDownloadRequest(null),
|
|
false
|
|
)
|
|
}.apply {
|
|
setTheme(R.style.DialogTheme)
|
|
setTrackNameProvider {
|
|
if (it.frameRate > 0f) it.height.toString() + "p" else it.height.toString() + "p (fps : N/A)"
|
|
}
|
|
build().show()
|
|
}
|
|
}
|
|
|
|
override fun onPrepareError(helper: DownloadHelper, e: IOException) {
|
|
logError(e)
|
|
}
|
|
})
|
|
}
|
|
|
|
|
|
private var download: DownloadManager? = null
|
|
private const val DOWNLOAD_CONTENT_DIRECTORY = "downloads"
|
|
|
|
@Synchronized
|
|
@UnstableApi
|
|
fun downloadManager(context: Context): DownloadManager {
|
|
return download ?: let {
|
|
val database = StandaloneDatabaseProvider(context)
|
|
val downloadDirectory = File(getDownloadDirectory(context), DOWNLOAD_CONTENT_DIRECTORY)
|
|
val dataSourceFactory = DataSource.Factory {
|
|
val dataSource: HttpDataSource = OkHttpDataSource.Factory(okHttpClient).createDataSource()
|
|
defaultHeaders.forEach {
|
|
dataSource.setRequestProperty(it.key, it.value)
|
|
}
|
|
dataSource
|
|
}
|
|
DownloadManager(
|
|
context,
|
|
database,
|
|
SimpleCache(downloadDirectory, NoOpCacheEvictor(), database),
|
|
dataSourceFactory,
|
|
Executor(Runnable::run)
|
|
).apply {
|
|
requirements = Requirements(Requirements.NETWORK or Requirements.DEVICE_STORAGE_NOT_LOW)
|
|
maxParallelDownloads = 3
|
|
}
|
|
}
|
|
}
|
|
|
|
private var downloadDirectory: File? = null
|
|
|
|
@Synchronized
|
|
private fun getDownloadDirectory(context: Context): File {
|
|
if (downloadDirectory == null) {
|
|
downloadDirectory = context.getExternalFilesDir(null)
|
|
if (downloadDirectory == null) {
|
|
downloadDirectory = context.filesDir
|
|
}
|
|
}
|
|
return downloadDirectory!!
|
|
}
|
|
} |