From a4bea62392cad1770ea5477281fe53ac64cfce3a Mon Sep 17 00:00:00 2001 From: Blatzar <46196380+Blatzar@users.noreply.github.com> Date: Wed, 29 Dec 2021 01:14:05 +0100 Subject: [PATCH] fixed downloaded subtitles and custom subtitles on downloaded videos --- .../cloudstream3/ui/ControllerActivity.kt | 2 +- .../cloudstream3/ui/player/PlayerFragment.kt | 122 +++++++++++++----- 2 files changed, 93 insertions(+), 31 deletions(-) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/ControllerActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/ControllerActivity.kt index c4d2d52d..e5cad799 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/ControllerActivity.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/ControllerActivity.kt @@ -117,7 +117,7 @@ class SelectSourceController(val view: ImageView, val activity: ControllerActivi bottomSheetDialog.findViewById(R.id.sort_subtitles_holder)?.visibility = GONE } else { val arrayAdapter = ArrayAdapter(view.context, R.layout.sort_bottom_single_choice) - arrayAdapter.add("No Subtitles") + arrayAdapter.add(view.context.getString(R.string.no_subtitles)) arrayAdapter.addAll(subTracks.mapNotNull { it.name }) subtitleList.choiceMode = AbsListView.CHOICE_MODE_SINGLE diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt index 5d05ddf6..7aa1733b 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt @@ -182,6 +182,13 @@ class PlayerFragment : Fragment() { //private var torrentStream: TorrentStream? = null private var lastTorrentUrl = "" + /** + * Tracks reported to be used by exoplayer, since sometimes it has a mind of it's own when selecting subs. + * String = lowercase language as set by .setLanguage("_$langId") + * Boolean = if it's active + * */ + var exoPlayerSelectedTracks = listOf>() + //private val isTorrent: Boolean get() = torrentStream != null private fun initTorrentStream(torrentUrl: String) { if (lastTorrentUrl == torrentUrl) return @@ -541,7 +548,11 @@ class PlayerFragment : Fragment() { when (motionEvent.action) { MotionEvent.ACTION_DOWN -> { // SO YOU CAN PULL DOWN STATUSBAR OR NAVBAR - if (motionEvent.rawY > statusBarHeight && motionEvent.rawX < max(width, height) - navigationBarHeight) { + if (motionEvent.rawY > statusBarHeight && motionEvent.rawX < max( + width, + height + ) - navigationBarHeight + ) { currentX = motionEvent.rawX currentY = motionEvent.rawY isValidTouch = true @@ -772,27 +783,42 @@ class PlayerFragment : Fragment() { // Open file picker private val subsPathPicker = registerForActivityResult(ActivityResultContracts.OpenDocument()) { uri -> - // It lies, it can be null if file manager quits. - if (uri == null) return@registerForActivityResult - val context = context ?: AcraApplication.context ?: return@registerForActivityResult - // RW perms for the path - val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or - Intent.FLAG_GRANT_WRITE_URI_PERMISSION + normalSafeApiCall { + // It lies, it can be null if file manager quits. + if (uri == null) return@normalSafeApiCall + val context = context ?: AcraApplication.context ?: return@normalSafeApiCall + // RW perms for the path + val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or + Intent.FLAG_GRANT_WRITE_URI_PERMISSION - context.contentResolver.takePersistableUriPermission(uri, flags) + context.contentResolver.takePersistableUriPermission(uri, flags) - val file = UniFile.fromUri(context, uri) - println("Selected URI path: $uri - Full path: ${file.filePath}") - // DO NOT REMOVE THE FILE EXTENSION FROM NAME, IT'S NEEDED FOR MIME TYPES - val name = file.name ?: uri.toString() + val file = UniFile.fromUri(context, uri) + println("Loaded subtitle file. Selected URI path: $uri - Name: ${file.name}") + // DO NOT REMOVE THE FILE EXTENSION FROM NAME, IT'S NEEDED FOR MIME TYPES + val name = file.name ?: uri.toString() - viewModel.loadSubtitleFile(uri, name, getEpisode()?.id) - setPreferredSubLanguage(name) - showToast( - activity, - format(context.getString(R.string.player_loaded_subtitles), name), - 1000 - ) + // Sets subs manually if downloaded since the viewModel won't exist. + if (isDownloadedFile && uriData.id != null) + allEpisodesSubs[uriData.id!!] = + (allEpisodesSubs[uriData.id] + ?: hashMapOf()).apply { + this[name] = SubtitleFile(name, uri.toString()) + } + else + viewModel.loadSubtitleFile( + uri, + name, + getEpisode()?.id + ) + + setPreferredSubLanguage(name) + showToast( + activity, + String.format(context.getString(R.string.player_loaded_subtitles), name), + 1000 + ) + } } private class SettingsContentObserver(handler: Handler?, val activity: Activity) : @@ -811,6 +837,13 @@ class PlayerFragment : Fragment() { companion object { fun String.toSubtitleMimeType(): String { return when { + // Checks the file name if downloaded. + startsWith("content://") -> { + UniFile.fromUri( + AcraApplication.context, + Uri.parse(this) + ).name?.toSubtitleMimeType() ?: MimeTypes.APPLICATION_SUBRIP + } endsWith("vtt", true) -> MimeTypes.TEXT_VTT endsWith("srt", true) -> MimeTypes.APPLICATION_SUBRIP endsWith("xml", true) || endsWith("ttml", true) -> MimeTypes.APPLICATION_TTML @@ -1316,9 +1349,23 @@ class PlayerFragment : Fragment() { } } - val startIndexFromMap = - currentSubtitles.map { it.trimEnd() } - .indexOf(preferredSubtitles.trimEnd()) + 1 + /** + * This will get the actual real track played by exoplayer. + * */ + val currentSubtitle = currentSubtitles.firstOrNull { sub -> + exoPlayerSelectedTracks.any { + // The replace is needed as exoplayer translates _ to - + // Also we prefix the languages with _ + it.second && it.first.replace("-", "") .equals( + sub.replace("-", ""), + ignoreCase = true + ) + } + } + + val startIndexFromMap = currentSubtitles.indexOf(currentSubtitle) + 1 +// currentSubtitles.map { it.trimEnd() } +// .indexOf(preferredSubtitles.trimEnd()) + 1 var subtitleIndex = startIndexFromMap if (currentSubtitles.isEmpty()) { @@ -1403,7 +1450,7 @@ class PlayerFragment : Fragment() { ?: realLang else realLang if (!this::exoPlayer.isInitialized) return - (exoPlayer.trackSelector as DefaultTrackSelector?)?.let { trackSelector -> + (exoPlayer.trackSelector as? DefaultTrackSelector?)?.let { trackSelector -> if (lang.isNullOrBlank()) { trackSelector.setParameters( trackSelector.buildUponParameters() @@ -1582,11 +1629,11 @@ class PlayerFragment : Fragment() { setPreferredSubLanguage(it) } - sources_btt.visibility = - if (isDownloadedFile) - if (context?.getSubs()?.isNullOrEmpty() != false) - GONE else VISIBLE - else VISIBLE +// sources_btt.visibility = +// if (isDownloadedFile) +// if (context?.getSubs()?.isNullOrEmpty() != false) +// GONE else VISIBLE +// else VISIBLE player_media_route_button?.isVisible = !isDownloadedFile if (savedInstanceState != null) { @@ -1867,6 +1914,10 @@ class PlayerFragment : Fragment() { if (isDownloadedFile) { if (!supportsDownloadedFiles) return null val list = ArrayList() + + // Adds custom subtitles + allEpisodesSubs[uriData.id]?.values?.forEach { list.add(it) } + VideoDownloadManager.getFolder(this, uriData.relativePath, uriData.basePath) ?.forEach { file -> val name = uriData.displayName.removeSuffix(".mp4") @@ -2194,17 +2245,18 @@ class PlayerFragment : Fragment() { val subSources = sortSubs(subs).map { sub -> // The url can look like .../document/4294 when the name is EnglishSDH.srt val subtitleMimeType = - if (sub.url.startsWith("content")) sub.lang.toSubtitleMimeType() else sub.url.toSubtitleMimeType() + sub.url.toSubtitleMimeType() val langId = sub.lang.trimEnd() //SubtitleHelper.fromLanguageToTwoLetters(it.lang) ?: it.lang + subItemsId.add(langId) val subConfig = MediaItem.SubtitleConfiguration.Builder(Uri.parse(sub.url)) .setMimeType(subtitleMimeType) .setLanguage("_$langId") .setSelectionFlags(C.SELECTION_FLAG_DEFAULT) .build() - SingleSampleMediaSource.Factory(getDataSourceFactory(!sub.url.startsWith("content"))) + SingleSampleMediaSource.Factory(getDataSourceFactory(!sub.url.startsWith("content://"))) .createMediaSource(subConfig, TIME_UNSET) } @@ -2352,6 +2404,16 @@ class PlayerFragment : Fragment() { } exoPlayer.addListener(object : Player.Listener { + + /** + * Records the current used subtitle/track. Needed as exoplayer seems to have loose track language selection. + * */ + override fun onTracksInfoChanged(tracksInfo: TracksInfo) { + exoPlayerSelectedTracks = + tracksInfo.trackGroupInfos.mapNotNull { it.trackGroup.getFormat(0).language?.let { lang -> lang to it.isSelected } } + super.onTracksInfoChanged(tracksInfo) + } + override fun onRenderedFirstFrame() { super.onRenderedFirstFrame() isCurrentlySkippingEp = false