diff --git a/app/src/main/assets/scripts/source.js b/app/src/main/assets/scripts/source.js index 4e14fd27..ebf84b0c 100644 --- a/app/src/main/assets/scripts/source.js +++ b/app/src/main/assets/scripts/source.js @@ -365,16 +365,20 @@ class VideoUrlSource { this.url = obj.url; if(obj.requestModifier) this.requestModifier = obj.requestModifier; + + // deprecated api conversion + if(obj.licenseUri) + this.drmLicenseUri = obj.licenseUri; + + if(obj.drmLicenseUri) + this.drmLicenseUri = obj.drmLicenseUri; + if(obj.getLicenseRequestExecutor) + this.getLicenseRequestExecutor = obj.getLicenseRequestExecutor; } } class VideoUrlWidevineSource extends VideoUrlSource { constructor(obj) { super(obj); - this.plugin_type = "VideoUrlWidevineSource"; - - this.drmLicenseUri = obj.licenseUri; - if(obj.getLicenseRequestExecutor) - this.getLicenseRequestExecutor = obj.getLicenseRequestExecutor; } } class VideoUrlRangeSource extends VideoUrlSource { @@ -402,16 +406,6 @@ class AudioUrlSource { this.language = obj.language ?? Language.UNKNOWN; if(obj.requestModifier) this.requestModifier = obj.requestModifier; - } -} -class AudioUrlWidevineSource extends AudioUrlSource { - constructor(obj) { - super(obj); - this.plugin_type = "AudioUrlWidevineSource"; - - this.drmLicenseUri = obj.licenseUri; - if(obj.getLicenseRequestExecutor) - this.getLicenseRequestExecutor = obj.getLicenseRequestExecutor; // deprecated api conversion if(obj.bearerToken) { @@ -429,6 +423,19 @@ class AudioUrlWidevineSource extends AudioUrlSource { } } } + // deprecated api conversion + if(obj.licenseUri) + this.drmLicenseUri = obj.licenseUri; + + if(obj.drmLicenseUri) + this.drmLicenseUri = obj.drmLicenseUri; + if(obj.getLicenseRequestExecutor) + this.getLicenseRequestExecutor = obj.getLicenseRequestExecutor; + } +} +class AudioUrlWidevineSource extends AudioUrlSource { + constructor(obj) { + super(obj); } } class AudioUrlRangeSource extends AudioUrlSource { @@ -471,16 +478,20 @@ class DashSource { this.requestModifier = obj.requestModifier; if(obj.getRequestExecutor) this.getRequestExecutor = obj.getRequestExecutor; + + // deprecated api conversion + if(obj.licenseUri) + this.drmLicenseUri = obj.licenseUri; + + if(obj.drmLicenseUri) + this.drmLicenseUri = obj.drmLicenseUri; + if(obj.getLicenseRequestExecutor) + this.getLicenseRequestExecutor = obj.getLicenseRequestExecutor; } } class DashWidevineSource extends DashSource { constructor(obj) { super(obj); - this.plugin_type = "DashWidevineSource"; - - this.drmLicenseUri = obj.licenseUri; - if(obj.getLicenseRequestExecutor) - this.getLicenseRequestExecutor = obj.getLicenseRequestExecutor; } } class DashManifestRawSource { @@ -513,7 +524,9 @@ class DashManifestRawAudioSource { this.manifest = obj.manifest ?? null; if(obj.requestModifier) this.requestModifier = obj.requestModifier; - this.drmLicenseUri = obj.drmLicenseUri; + + if(obj.drmLicenseUri) + this.drmLicenseUri = obj.drmLicenseUri; if(obj.getLicenseRequestExecutor) this.getLicenseRequestExecutor = obj.getLicenseRequestExecutor; } diff --git a/app/src/main/java/com/futo/platformplayer/api/media/models/streams/sources/IAudioUrlWidevineSource.kt b/app/src/main/java/com/futo/platformplayer/api/media/models/streams/sources/IAudioUrlWidevineSource.kt deleted file mode 100644 index 7e2908aa..00000000 --- a/app/src/main/java/com/futo/platformplayer/api/media/models/streams/sources/IAudioUrlWidevineSource.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.futo.platformplayer.api.media.models.streams.sources - -interface IAudioUrlWidevineSource : IAudioUrlSource diff --git a/app/src/main/java/com/futo/platformplayer/api/media/models/streams/sources/IDashManifestWidevineSource.kt b/app/src/main/java/com/futo/platformplayer/api/media/models/streams/sources/IDashManifestWidevineSource.kt deleted file mode 100644 index 9b0e3f8f..00000000 --- a/app/src/main/java/com/futo/platformplayer/api/media/models/streams/sources/IDashManifestWidevineSource.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.futo.platformplayer.api.media.models.streams.sources - -interface IDashManifestWidevineSource { - val url: String -} diff --git a/app/src/main/java/com/futo/platformplayer/api/media/models/streams/sources/IVideoUrlWidevineSource.kt b/app/src/main/java/com/futo/platformplayer/api/media/models/streams/sources/IVideoUrlWidevineSource.kt deleted file mode 100644 index 3ea27f5c..00000000 --- a/app/src/main/java/com/futo/platformplayer/api/media/models/streams/sources/IVideoUrlWidevineSource.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.futo.platformplayer.api.media.models.streams.sources - -interface IVideoUrlWidevineSource : IVideoUrlSource diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSAudioUrlWidevineSource.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSAudioUrlWidevineSource.kt deleted file mode 100644 index ad75125b..00000000 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSAudioUrlWidevineSource.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.futo.platformplayer.api.media.platforms.js.models.sources - -import com.caoccao.javet.values.reference.V8ValueObject -import com.futo.platformplayer.api.media.models.streams.sources.IAudioUrlWidevineSource -import com.futo.platformplayer.api.media.platforms.js.JSClient -import com.futo.platformplayer.api.media.platforms.js.models.JSRequestExecutor -import com.futo.platformplayer.engine.V8Plugin -import com.futo.platformplayer.getOrThrow - -class JSAudioUrlWidevineSource : JSAudioUrlSource, IAudioUrlWidevineSource { - @Suppress("ConvertSecondaryConstructorToPrimary") - constructor(plugin: JSClient, obj: V8ValueObject) : super(plugin, obj) { - val contextName = "JSAudioUrlWidevineSource" - val config = plugin.config - } - - override fun toString(): String { - val url = getAudioUrl() - return "(name=$name, container=$container, bitrate=$bitrate, codec=$codec, url=$url, language=$language, duration=$duration, hasLicenseRequestExecutor=${hasLicenseRequestExecutor}, drmLicenseUri=$drmLicenseUri)" - } -} diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSDashManifestWidevineSource.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSDashManifestWidevineSource.kt deleted file mode 100644 index b205d574..00000000 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSDashManifestWidevineSource.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.futo.platformplayer.api.media.platforms.js.models.sources - -import com.caoccao.javet.values.reference.V8ValueObject -import com.futo.platformplayer.api.media.models.streams.sources.IDashManifestSource -import com.futo.platformplayer.api.media.models.streams.sources.IDashManifestWidevineSource -import com.futo.platformplayer.api.media.models.streams.sources.IVideoUrlSource -import com.futo.platformplayer.api.media.platforms.js.JSClient -import com.futo.platformplayer.api.media.platforms.js.models.JSRequestExecutor -import com.futo.platformplayer.engine.V8Plugin -import com.futo.platformplayer.getOrNull -import com.futo.platformplayer.getOrThrow - -class JSDashManifestWidevineSource : IVideoUrlSource, IDashManifestSource, - IDashManifestWidevineSource, JSSource { - override val width: Int = 0 - override val height: Int = 0 - override val container: String = "application/dash+xml" - override val codec: String = "Dash" - override val name: String - override val bitrate: Int? = null - override val url: String - override val duration: Long - - override var priority: Boolean = false - - @Suppress("ConvertSecondaryConstructorToPrimary") - constructor(plugin: JSClient, obj: V8ValueObject) : super(TYPE_DASH, plugin, obj) { - val contextName = "DashWidevineSource" - val config = plugin.config - name = _obj.getOrThrow(config, "name", contextName) - url = _obj.getOrThrow(config, "url", contextName) - duration = _obj.getOrThrow(config, "duration", contextName) - - priority = obj.getOrNull(config, "priority", contextName) ?: false - } - - override fun getVideoUrl(): String { - return url - } -} \ No newline at end of file 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 830c6125..c3d57707 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 @@ -53,7 +53,7 @@ abstract class JSSource { } hasRequestExecutor = _requestExecutor != null || obj.has("getRequestExecutor"); - drmLicenseUri = _obj.getOrThrow(_config, "drmLicenseUri", "JSSource.drmLicenseUri") + drmLicenseUri = _obj.getOrDefault(_config, "drmLicenseUri", "JSSource.drmLicenseUri", null) hasLicenseRequestExecutor = obj.has("getLicenseRequestExecutor") } @@ -115,22 +115,17 @@ abstract class JSSource { const val TYPE_AUDIO_WITH_METADATA = "AudioUrlRangeSource"; const val TYPE_VIDEO_WITH_METADATA = "VideoUrlRangeSource"; const val TYPE_DASH = "DashSource"; - const val TYPE_DASH_WIDEVINE = "DashWidevineSource"; const val TYPE_DASH_RAW = "DashRawSource"; const val TYPE_DASH_RAW_AUDIO = "DashRawAudioSource"; const val TYPE_HLS = "HLSSource"; - const val TYPE_AUDIOURL_WIDEVINE = "AudioUrlWidevineSource" - const val TYPE_VIDEOURL_WIDEVINE = "VideoUrlWidevineSource" fun fromV8VideoNullable(plugin: JSClient, obj: V8Value?) : IVideoSource? = obj.orNull { fromV8Video(plugin, it as V8ValueObject) }; fun fromV8Video(plugin: JSClient, obj: V8ValueObject) : IVideoSource? { val type = obj.getString("plugin_type"); return when(type) { TYPE_VIDEOURL -> JSVideoUrlSource(plugin, obj); - TYPE_VIDEOURL_WIDEVINE -> JSVideoUrlWidevineSource(plugin, obj); TYPE_VIDEO_WITH_METADATA -> JSVideoUrlRangeSource(plugin, obj); TYPE_HLS -> fromV8HLS(plugin, obj); - TYPE_DASH_WIDEVINE -> JSDashManifestWidevineSource(plugin, obj) TYPE_DASH -> fromV8Dash(plugin, obj); TYPE_DASH_RAW -> fromV8DashRaw(plugin, obj); else -> { @@ -152,7 +147,6 @@ abstract class JSSource { TYPE_HLS -> JSHLSManifestAudioSource.fromV8HLS(plugin, obj); TYPE_AUDIOURL -> JSAudioUrlSource(plugin, obj); TYPE_DASH_RAW_AUDIO -> fromV8DashRawAudio(plugin, obj); - TYPE_AUDIOURL_WIDEVINE -> JSAudioUrlWidevineSource(plugin, obj); TYPE_AUDIO_WITH_METADATA -> JSAudioUrlRangeSource(plugin, obj); else -> { Logger.w("JSSource", "Unknown audio type ${type}"); diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSVideoUrlWidevineSource.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSVideoUrlWidevineSource.kt deleted file mode 100644 index 9d374ee6..00000000 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSVideoUrlWidevineSource.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.futo.platformplayer.api.media.platforms.js.models.sources - -import com.caoccao.javet.values.reference.V8ValueObject -import com.futo.platformplayer.api.media.models.streams.sources.IVideoUrlWidevineSource -import com.futo.platformplayer.api.media.platforms.js.JSClient -import com.futo.platformplayer.api.media.platforms.js.models.JSRequestExecutor -import com.futo.platformplayer.engine.V8Plugin -import com.futo.platformplayer.getOrThrow - -class JSVideoUrlWidevineSource : JSVideoUrlSource, IVideoUrlWidevineSource { - @Suppress("ConvertSecondaryConstructorToPrimary") - constructor(plugin: JSClient, obj: V8ValueObject) : super(plugin, obj) { - val contextName = "JSAudioUrlWidevineSource" - val config = plugin.config - } - - override fun toString(): String { - val url = getVideoUrl() - return "(width=$width, height=$height, container=$container, codec=$codec, name=$name, bitrate=$bitrate, duration=$duration, url=$url, hasLicenseRequestExecutor=$hasLicenseRequestExecutor, drmLicenseUri=$drmLicenseUri)" - } -} \ No newline at end of file diff --git a/app/src/main/java/com/futo/platformplayer/views/video/FutoVideoPlayerBase.kt b/app/src/main/java/com/futo/platformplayer/views/video/FutoVideoPlayerBase.kt index a6694394..975bd0c3 100644 --- a/app/src/main/java/com/futo/platformplayer/views/video/FutoVideoPlayerBase.kt +++ b/app/src/main/java/com/futo/platformplayer/views/video/FutoVideoPlayerBase.kt @@ -23,6 +23,7 @@ import androidx.media3.exoplayer.dash.DashMediaSource import androidx.media3.exoplayer.dash.manifest.DashManifestParser import androidx.media3.exoplayer.drm.DefaultDrmSessionManager import androidx.media3.exoplayer.drm.HttpMediaDrmCallback +import androidx.media3.exoplayer.drm.MediaDrmCallback import androidx.media3.exoplayer.hls.HlsMediaSource import androidx.media3.exoplayer.source.MediaSource import androidx.media3.exoplayer.source.MergingMediaSource @@ -34,14 +35,11 @@ import com.futo.platformplayer.api.media.models.chapters.IChapter import com.futo.platformplayer.api.media.models.streams.VideoMuxedSourceDescriptor import com.futo.platformplayer.api.media.models.streams.sources.IAudioSource import com.futo.platformplayer.api.media.models.streams.sources.IAudioUrlSource -import com.futo.platformplayer.api.media.models.streams.sources.IAudioUrlWidevineSource import com.futo.platformplayer.api.media.models.streams.sources.IDashManifestSource -import com.futo.platformplayer.api.media.models.streams.sources.IDashManifestWidevineSource import com.futo.platformplayer.api.media.models.streams.sources.IHLSManifestAudioSource import com.futo.platformplayer.api.media.models.streams.sources.IHLSManifestSource import com.futo.platformplayer.api.media.models.streams.sources.IVideoSource import com.futo.platformplayer.api.media.models.streams.sources.IVideoUrlSource -import com.futo.platformplayer.api.media.models.streams.sources.IVideoUrlWidevineSource import com.futo.platformplayer.api.media.models.streams.sources.LocalAudioSource import com.futo.platformplayer.api.media.models.streams.sources.LocalVideoSource import com.futo.platformplayer.api.media.models.subtitles.ISubtitleSource @@ -413,11 +411,9 @@ abstract class FutoVideoPlayerBase : RelativeLayout { val didSet = when(videoSource) { is LocalVideoSource -> { swapVideoSourceLocal(videoSource); true; } is JSVideoUrlRangeSource -> { swapVideoSourceUrlRange(videoSource); true; } - is IDashManifestWidevineSource -> { swapVideoSourceDashWidevine(videoSource); true } is IDashManifestSource -> { swapVideoSourceDash(videoSource); true;} - is JSDashManifestRawSource -> swapVideoSourceDashRaw(videoSource, play, resume); + is JSDashManifestRawSource -> swapVideoSourceDashRaw(videoSource, play, resume) is IHLSManifestSource -> { swapVideoSourceHLS(videoSource); true; } - is IVideoUrlWidevineSource -> { swapVideoSourceUrlWidevine(videoSource); true; } is IVideoUrlSource -> { swapVideoSourceUrl(videoSource); true; } null -> { _lastVideoMediaSource = null; true;} else -> throw IllegalArgumentException("Unsupported video source [${videoSource.javaClass.simpleName}]"); @@ -430,8 +426,7 @@ abstract class FutoVideoPlayerBase : RelativeLayout { is LocalAudioSource -> {swapAudioSourceLocal(audioSource); true; } is JSAudioUrlRangeSource -> { swapAudioSourceUrlRange(audioSource); true; } is JSHLSManifestAudioSource -> { swapAudioSourceHLS(audioSource); true; } - is JSDashManifestRawAudioSource -> swapAudioSourceDashRaw(audioSource, play, resume); - is IAudioUrlWidevineSource -> { swapAudioSourceUrlWidevine(audioSource); true; } + is JSDashManifestRawAudioSource -> swapAudioSourceDashRaw(audioSource, play, resume) is IAudioUrlSource -> { swapAudioSourceUrl(audioSource); true; } null -> { _lastAudioMediaSource = null; true; } else -> throw IllegalArgumentException("Unsupported video source [${audioSource.javaClass.simpleName}]"); @@ -471,80 +466,50 @@ abstract class FutoVideoPlayerBase : RelativeLayout { } else throw IllegalArgumentException("source without itag data..."); } + @OptIn(UnstableApi::class) private fun swapVideoSourceUrl(videoSource: IVideoUrlSource) { Logger.i(TAG, "Loading VideoSource [Url]"); - val dataSource = if(videoSource is JSSource && videoSource.requiresCustomDatasource) + val dataSource = if (videoSource is JSSource && videoSource.requiresCustomDatasource) videoSource.getHttpDataSourceFactory() else DefaultHttpDataSource.Factory().setUserAgent(DEFAULT_USER_AGENT); - _lastVideoMediaSource = ProgressiveMediaSource.Factory(dataSource) - .createMediaSource(MediaItem.fromUri(videoSource.getVideoUrl())); - } - @OptIn(UnstableApi::class) - private fun swapVideoSourceUrlWidevine(videoSource: IVideoUrlWidevineSource) { - Logger.i(TAG, "Loading VideoSource [UrlWidevine]"); - if (!MediaDrm.isCryptoSchemeSupported(C.WIDEVINE_UUID)) { - throw IllegalArgumentException("Device does not support Widevine") - } + val drmCallback = if (videoSource is JSSource) getDrmCallback(videoSource, dataSource) else null - val dataSource = if(videoSource is JSSource && videoSource.requiresCustomDatasource) - videoSource.getHttpDataSourceFactory() - else - DefaultHttpDataSource.Factory().setUserAgent(DEFAULT_USER_AGENT) - - val baseCallback = HttpMediaDrmCallback((videoSource as JSSource).drmLicenseUri, dataSource) - - val callback = if (videoSource.hasLicenseRequestExecutor) { - PluginMediaDrmCallback(baseCallback, videoSource.getLicenseRequestExecutor()!!, videoSource.drmLicenseUri!!) - } else { - baseCallback - } - - _lastVideoMediaSource = ProgressiveMediaSource.Factory(dataSource) - .setDrmSessionManagerProvider { + val factory = ProgressiveMediaSource.Factory(dataSource) + if (drmCallback != null) { + factory.setDrmSessionManagerProvider { DefaultDrmSessionManager.Builder() .setMultiSession(true) - .build(callback) + .build(drmCallback) } - .createMediaSource( - MediaItem.fromUri(videoSource.getVideoUrl()) - ) + } + + _lastVideoMediaSource = factory + .createMediaSource(MediaItem.fromUri(videoSource.getVideoUrl())); } + @OptIn(UnstableApi::class) private fun swapVideoSourceDash(videoSource: IDashManifestSource) { Logger.i(TAG, "Loading VideoSource [Dash]"); - val dataSource = if(videoSource is JSSource && (videoSource.requiresCustomDatasource)) + val dataSource = if (videoSource is JSSource && (videoSource.requiresCustomDatasource)) videoSource.getHttpDataSourceFactory() else DefaultHttpDataSource.Factory().setUserAgent(DEFAULT_USER_AGENT); - _lastVideoMediaSource = DashMediaSource.Factory(dataSource) - .createMediaSource(MediaItem.fromUri(videoSource.url)) - } - @OptIn(UnstableApi::class) - private fun swapVideoSourceDashWidevine(videoSource: IDashManifestWidevineSource) { - Logger.i(TAG, "Loading VideoSource [DashWidevine]") - if (!MediaDrm.isCryptoSchemeSupported(C.WIDEVINE_UUID)) { - throw IllegalArgumentException("Device does not support Widevine") + val drmCallback = + if (videoSource is JSSource) getDrmCallback(videoSource, dataSource) else null + + val factory = DashMediaSource.Factory(dataSource) + if (drmCallback != null) { + factory.setDrmSessionManagerProvider { + DefaultDrmSessionManager.Builder().setMultiSession(true).build(drmCallback) + } } - val dataSource = - if (videoSource is JSSource && (videoSource.requiresCustomDatasource)) videoSource.getHttpDataSourceFactory() - else DefaultHttpDataSource.Factory().setUserAgent(DEFAULT_USER_AGENT) - - val baseCallback = HttpMediaDrmCallback((videoSource as JSSource).drmLicenseUri, dataSource) - - val callback = if (videoSource.hasLicenseRequestExecutor) { - PluginMediaDrmCallback(baseCallback, videoSource.getLicenseRequestExecutor()!!, videoSource.drmLicenseUri!!) - } else { - baseCallback - } - - _lastVideoMediaSource = DashMediaSource.Factory(dataSource).setDrmSessionManagerProvider { - DefaultDrmSessionManager.Builder().setMultiSession(true).build(callback) - }.createMediaSource(MediaItem.fromUri(videoSource.url)) + _lastVideoMediaSource = + factory.createMediaSource(MediaItem.fromUri(videoSource.url)) } @OptIn(UnstableApi::class) private fun swapVideoSourceDashRaw(videoSource: JSDashManifestRawSource, play: Boolean, resume: Boolean): Boolean { @@ -639,15 +604,28 @@ abstract class FutoVideoPlayerBase : RelativeLayout { } else throw IllegalArgumentException("source without itag data...") } + @OptIn(UnstableApi::class) private fun swapAudioSourceUrl(audioSource: IAudioUrlSource) { Logger.i(TAG, "Loading AudioSource [Url]"); - val dataSource = if(audioSource is JSSource && audioSource.requiresCustomDatasource) + val dataSource = if (audioSource is JSSource && audioSource.requiresCustomDatasource) audioSource.getHttpDataSourceFactory() else DefaultHttpDataSource.Factory().setUserAgent(DEFAULT_USER_AGENT); - _lastAudioMediaSource = ProgressiveMediaSource.Factory(dataSource) - .createMediaSource(MediaItem.fromUri(audioSource.getAudioUrl())); + + val drmCallback = + if (audioSource is JSSource) getDrmCallback(audioSource, dataSource) else null + + val factory = ProgressiveMediaSource.Factory(dataSource) + if (drmCallback != null) { + factory.setDrmSessionManagerProvider { + DefaultDrmSessionManager.Builder() + .setMultiSession(true) + .build(drmCallback) + } + } + _lastAudioMediaSource = + factory.createMediaSource(MediaItem.fromUri(audioSource.getAudioUrl())); } @OptIn(UnstableApi::class) private fun swapAudioSourceHLS(audioSource: IHLSManifestAudioSource) { @@ -662,102 +640,73 @@ abstract class FutoVideoPlayerBase : RelativeLayout { @OptIn(UnstableApi::class) private fun swapAudioSourceDashRaw(audioSource: JSDashManifestRawAudioSource, play: Boolean, resume: Boolean): Boolean { - Logger.i(TAG, "Loading AudioSource [DashRaw]") + Logger.i(TAG, "Loading AudioSource [DashRaw]"); val dataSource = if (audioSource.requiresCustomDatasource) audioSource.getHttpDataSourceFactory() else - DefaultHttpDataSource.Factory().setUserAgent(DEFAULT_USER_AGENT) + DefaultHttpDataSource.Factory().setUserAgent(DEFAULT_USER_AGENT); - val baseCallback = HttpMediaDrmCallback(audioSource.drmLicenseUri, dataSource) - - val callback = - if (audioSource.hasLicenseRequestExecutor && audioSource.drmLicenseUri != null) { - PluginMediaDrmCallback(baseCallback, audioSource.getLicenseRequestExecutor()!!, audioSource.drmLicenseUri) - } else { - baseCallback - } - - _lastVideoMediaSource = DashMediaSource.Factory(dataSource).setDrmSessionManagerProvider { - DefaultDrmSessionManager.Builder().setMultiSession(true).build(callback) - }.createMediaSource(MediaItem.fromUri(audioSource.url)) + val drmCallback = getDrmCallback(audioSource, dataSource) if (audioSource.hasGenerate) { findViewTreeLifecycleOwner()?.lifecycle?.coroutineScope?.launch(Dispatchers.IO) { - val generated = audioSource.generate() + val generated = audioSource.generate(); if (generated != null) { withContext(Dispatchers.Main) { val factory = DashMediaSource.Factory(dataSource) - if (audioSource.drmLicenseUri != null) { - if (!MediaDrm.isCryptoSchemeSupported(C.WIDEVINE_UUID)) { - throw IllegalArgumentException("Device does not support Widevine") - } + if (drmCallback != null) { factory.setDrmSessionManagerProvider { DefaultDrmSessionManager.Builder().setMultiSession(true) - .build(callback) + .build(drmCallback) } } - _lastVideoMediaSource = factory.createMediaSource( - DashManifestParser().parse( - Uri.parse(audioSource.url), - ByteArrayInputStream(generated.toByteArray() ?: ByteArray(0)) - ) - ) - loadSelectedSources(play, resume) + _lastVideoMediaSource = factory + .createMediaSource( + DashManifestParser().parse( + Uri.parse(audioSource.url), + ByteArrayInputStream(generated.toByteArray() ?: ByteArray(0)) + ) + ); + loadSelectedSources(play, resume); } } } - return false + return false; } else { val factory = DashMediaSource.Factory(dataSource) - if (audioSource.drmLicenseUri != null) { - if (!MediaDrm.isCryptoSchemeSupported(C.WIDEVINE_UUID)) { - throw IllegalArgumentException("Device does not support Widevine") - } + if (drmCallback != null) { factory.setDrmSessionManagerProvider { DefaultDrmSessionManager.Builder().setMultiSession(true) - .build(callback) + .build(drmCallback) } } - _lastVideoMediaSource = factory.createMediaSource( - DashManifestParser().parse( - Uri.parse(audioSource.url), - ByteArrayInputStream(audioSource.manifest?.toByteArray() ?: ByteArray(0)) - ) - ) - return true + _lastVideoMediaSource = factory + .createMediaSource( + DashManifestParser().parse( + Uri.parse(audioSource.url), + ByteArrayInputStream(audioSource.manifest?.toByteArray() ?: ByteArray(0)) + ) + ); + return true; } } @OptIn(UnstableApi::class) - private fun swapAudioSourceUrlWidevine(audioSource: IAudioUrlWidevineSource) { - Logger.i(TAG, "Loading AudioSource [UrlWidevine]") - - if (!MediaDrm.isCryptoSchemeSupported(C.WIDEVINE_UUID)) { - throw IllegalArgumentException("Device does not support Widevine") - } - - val dataSource = if (audioSource is JSSource && audioSource.requiresCustomDatasource) - audioSource.getHttpDataSourceFactory() - else - DefaultHttpDataSource.Factory().setUserAgent(DEFAULT_USER_AGENT) - - val baseCallback = HttpMediaDrmCallback((audioSource as JSSource).drmLicenseUri, dataSource) - - val callback = if (audioSource.hasLicenseRequestExecutor) { - PluginMediaDrmCallback(baseCallback, audioSource.getLicenseRequestExecutor()!!, audioSource.drmLicenseUri!!) - } else { - baseCallback - } - - _lastAudioMediaSource = ProgressiveMediaSource.Factory(dataSource) - .setDrmSessionManagerProvider { - DefaultDrmSessionManager.Builder() - .setMultiSession(true) - .build(callback) + private fun getDrmCallback(source: JSSource, dataSource: HttpDataSource.Factory): MediaDrmCallback? { + return if (source.drmLicenseUri != null) { + if (!MediaDrm.isCryptoSchemeSupported(C.WIDEVINE_UUID)) { + throw IllegalArgumentException("Device does not support Widevine") } - .createMediaSource( - MediaItem.fromUri(audioSource.getAudioUrl()) - ) + + val delegateCallback = + HttpMediaDrmCallback(source.drmLicenseUri, dataSource) + + if (source.hasLicenseRequestExecutor) { + PluginMediaDrmCallback(delegateCallback, source.getLicenseRequestExecutor()!!, source.drmLicenseUri) + } else { + delegateCallback + } + } else null } //Prefered source selection