diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/CustomSubtitleDecoderFactory.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/CustomSubtitleDecoderFactory.kt index 482f6b11..f727e8c0 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/CustomSubtitleDecoderFactory.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/CustomSubtitleDecoderFactory.kt @@ -1,6 +1,8 @@ package com.lagradost.cloudstream3.ui.player +import android.content.Context import android.util.Log +import androidx.preference.PreferenceManager import com.google.android.exoplayer2.Format import com.google.android.exoplayer2.text.SubtitleDecoder import com.google.android.exoplayer2.text.SubtitleDecoderFactory @@ -11,15 +13,29 @@ import com.google.android.exoplayer2.text.subrip.SubripDecoder import com.google.android.exoplayer2.text.ttml.TtmlDecoder import com.google.android.exoplayer2.text.webvtt.WebvttDecoder import com.google.android.exoplayer2.util.MimeTypes +import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.mvvm.logError import org.mozilla.universalchardet.UniversalDetector import java.nio.ByteBuffer class CustomDecoder : SubtitleDecoder { companion object { + fun updateForcedEncoding(context: Context) { + val settingsManager = PreferenceManager.getDefaultSharedPreferences(context) + val value = settingsManager.getString( + context.getString(R.string.subtitles_encoding_key), + null + ) + overrideEncoding = if (value.isNullOrBlank()) { + null + } else { + value + } + } + private const val UTF_8 = "UTF-8" private const val TAG = "CustomDecoder" - private var overrideEncoding: String? = null //TODO MAKE SETTING + private var overrideEncoding: String? = null var regexSubtitlesToRemoveCaptions = false val bloatRegex = listOf( @@ -69,7 +85,7 @@ class CustomDecoder : SubtitleDecoder { // this way we read the subtitle file and decide what decoder to use instead of relying on mimetype Log.i(TAG, "Got data from queueInputBuffer") - var str = try { + var (str, charset) = try { data.position(0) val fullDataArr = ByteArray(data.remaining()) data.get(fullDataArr) @@ -80,7 +96,7 @@ class CustomDecoder : SubtitleDecoder { detector.handleData(fullDataArr, 0, fullDataArr.size) detector.dataEnd() - detector.detectedCharset // "windows-1256" adabic + detector.detectedCharset // "windows-1256" } Log.i( @@ -93,14 +109,24 @@ class CustomDecoder : SubtitleDecoder { logError(e) UTF_8 } - var fullStr = try { - String(fullDataArr, charset(encoding)) + + var (fullStr, charset) = try { + val set = charset(encoding) + Pair(String(fullDataArr, set), set) } catch (e: Exception) { Log.e(TAG, "Failed to parse using encoding $encoding") logError(e) - fullDataArr.decodeToString() + Pair(fullDataArr.decodeToString(), charset(UTF_8)) } + bloatRegex.forEach { rgx -> + fullStr = fullStr.replace(rgx, "\n") + } + + fullStr.replace(Regex("(\r\n|\r|\n){2,}"), "\n") + // fullStr = "1\n00:00:01,616 --> 00:00:40,200\n" + + // "تــــرجــمة" + Log.i( TAG, "Encoded Text start: " + fullStr.substring( @@ -108,14 +134,7 @@ class CustomDecoder : SubtitleDecoder { minOf(fullStr.length, 300) ) ) - - bloatRegex.forEach { rgx -> - fullStr = fullStr.replace(rgx, "\n") - } - - fullStr.replace(Regex("(\r\n|\r|\n){2,}"), "\n") - - fullStr + Pair(fullStr, charset) } catch (e: Exception) { Log.e(TAG, "Failed to parse text returning plain data") logError(e) @@ -149,7 +168,7 @@ class CustomDecoder : SubtitleDecoder { } } - buff.data = ByteBuffer.wrap(str.toByteArray()) + buff.data = ByteBuffer.wrap(str.toByteArray(charset = charset)) decoder.queueInputBuffer(buff) Log.i( diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt index aa8b165c..68053cb6 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt @@ -15,7 +15,6 @@ import androidx.core.view.isVisible import androidx.lifecycle.ViewModelProvider import androidx.preference.PreferenceManager import com.google.android.exoplayer2.util.MimeTypes -import com.google.android.material.button.MaterialButton import com.hippo.unifile.UniFile import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull @@ -24,6 +23,7 @@ import com.lagradost.cloudstream3.mvvm.Resource import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.mvvm.normalSafeApiCall import com.lagradost.cloudstream3.mvvm.observe +import com.lagradost.cloudstream3.ui.player.CustomDecoder.Companion.updateForcedEncoding import com.lagradost.cloudstream3.ui.player.PlayerSubtitleHelper.Companion.toSubtitleMimeType import com.lagradost.cloudstream3.ui.result.ResultEpisode import com.lagradost.cloudstream3.ui.result.ResultFragment @@ -32,11 +32,13 @@ import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSet import com.lagradost.cloudstream3.ui.subtitles.SubtitlesFragment import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.Coroutines.ioSafe +import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showDialog import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe import com.lagradost.cloudstream3.utils.UIHelper.hideSystemUI import com.lagradost.cloudstream3.utils.UIHelper.popCurrentPage import kotlinx.android.synthetic.main.fragment_player.* import kotlinx.android.synthetic.main.player_custom_layout.* +import kotlinx.android.synthetic.main.player_select_source_and_subs.* import kotlinx.coroutines.Job class GeneratorPlayer : FullScreenPlayer() { @@ -241,14 +243,8 @@ class GeneratorPlayer : FullScreenPlayer() { val sourceDialog = sourceBuilder.create() selectSourceDialog = sourceDialog sourceDialog.show() - val providerList = - sourceDialog.findViewById(R.id.sort_providers)!! - val subtitleList = - sourceDialog.findViewById(R.id.sort_subtitles)!! - val applyButton = - sourceDialog.findViewById(R.id.apply_btt)!! - val cancelButton = - sourceDialog.findViewById(R.id.cancel_btt)!! + val providerList = sourceDialog.sort_providers + val subtitleList = sourceDialog.sort_subtitles val footer: TextView = layoutInflater.inflate(R.layout.sort_bottom_footer_add_choice, null) as TextView @@ -314,11 +310,56 @@ class GeneratorPlayer : FullScreenPlayer() { subtitleList.setItemChecked(which, true) } - cancelButton.setOnClickListener { + sourceDialog.cancel_btt?.setOnClickListener { sourceDialog.dismissSafe(activity) } - applyButton.setOnClickListener { + sourceDialog.subtitles_encoding_format?.apply { + val settingsManager = PreferenceManager.getDefaultSharedPreferences(ctx) + + val prefNames = ctx.resources.getStringArray(R.array.subtitles_encoding_list) + val prefValues = ctx.resources.getStringArray(R.array.subtitles_encoding_values) + + val value = settingsManager.getString( + ctx.getString(R.string.subtitles_encoding_key), + null + ) + val index = prefValues.indexOf(value) + text = prefNames[if(index == -1) 0 else index] + } + + sourceDialog.subtitles_click_settings?.setOnClickListener { + val settingsManager = PreferenceManager.getDefaultSharedPreferences(ctx) + + val prefNames = ctx.resources.getStringArray(R.array.subtitles_encoding_list) + val prefValues = ctx.resources.getStringArray(R.array.subtitles_encoding_values) + + val currentPrefMedia = + settingsManager.getString( + getString(R.string.subtitles_encoding_key), + null + ) + + val index = prefValues.indexOf(currentPrefMedia) + sourceDialog.dismissSafe(activity) + activity?.showDialog( + prefNames.toList(), + if(index == -1) 0 else index, + ctx.getString(R.string.subtitles_encoding), + true, + {}) { + settingsManager.edit() + .putString( + ctx.getString(R.string.subtitles_encoding_key), + prefValues[it] + ) + .apply() + println("FORCED ENCODING: ${prefValues[it]}") + updateForcedEncoding(ctx) + } + } + + sourceDialog.apply_btt?.setOnClickListener { var init = false if (sourceIndex != startSource) { init = true @@ -668,6 +709,7 @@ class GeneratorPlayer : FullScreenPlayer() { val settingsManager = PreferenceManager.getDefaultSharedPreferences(ctx) titleRez = settingsManager.getInt(getString(R.string.prefer_limit_title_rez_key), 3) limitTitle = settingsManager.getInt(getString(R.string.prefer_limit_title_key), 0) + updateForcedEncoding(ctx) } unwrapBundle(savedInstanceState) diff --git a/app/src/main/res/layout/player_select_source_and_subs.xml b/app/src/main/res/layout/player_select_source_and_subs.xml index c99ff6ff..1efa00be 100644 --- a/app/src/main/res/layout/player_select_source_and_subs.xml +++ b/app/src/main/res/layout/player_select_source_and_subs.xml @@ -62,19 +62,37 @@ android:orientation="horizontal" tools:ignore="UseCompoundDrawables"> - + android:layout_marginTop="10dp" + android:orientation="horizontal" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + + + + + + - + @id/cast_button_type_rewind_30_seconds @id/cast_button_type_play_pause_toggle @@ -269,4 +269,94 @@ Amoled Light + + + + @string/automatic + Universal (UTF-8) + Universal (UTF-16) + Universal (big endian UTF-16) + Universal (little endian UTF-16) + Universal, Chinese (GB18030) + Western European (Latin-9) + Western European (Windows-1252) + Western European (IBM 00850) + Eastern European (Latin-2) + Eastern European (Windows-1250) + Esperanto (Latin-3) + Nordic (Latin-6) + Cyrillic (Windows-1251) + Russian (KOI8-R) + Ukrainian (KOI8-U) + Arabic (ISO 8859-6) + Arabic (Windows-1256) + Greek (ISO 8859-7) + Greek (Windows-1253) + Hebrew (ISO 8859-8) + Hebrew (Windows-1255) + Turkish (ISO 8859-9) + Turkish (Windows-1254) + Thai (TIS 620-2533/ISO 8859-11) + Thai (Windows-874) + Baltic (Latin-7) + Baltic (Windows-1257) + Celtic (Latin-8) + South-Eastern European (Latin-10) + Simplified Chinese (ISO-2022-CN-EXT) + Simplified Chinese Unix (EUC-CN) + Japanese (7-bits JIS/ISO-2022-JP-2) + Japanese Unix (EUC-JP) + Japanese (Shift JIS) + Korean (EUC-KR/CP949) + Korean (ISO-2022-KR) + Traditional Chinese (Big5) + Traditional Chinese Unix (EUC-TW) + Hong-Kong Supplementary (HKSCS) + Vietnamese (VISCII) + Vietnamese (Windows-1258) + + + + UTF-8 + UTF-16 + UTF-16BE + UTF-16LE + GB18030 + ISO-8859-15 + Windows-1252 + IBM850 + ISO-8859-2 + Windows-1250 + ISO-8859-3 + ISO-8859-10 + Windows-1251 + KOI8-R + KOI8-U + ISO-8859-6 + Windows-1256 + ISO-8859-7 + Windows-1253 + ISO-8859-8 + Windows-1255 + ISO-8859-9 + Windows-1254 + ISO-8859-11 + Windows-874 + ISO-8859-13 + Windows-1257 + ISO-8859-14 + ISO-8859-16 + ISO-2022-CN-EXT + EUC-CN + ISO-2022-JP-2 + EUC-JP + Shift_JIS + CP949 + ISO-2022-KR + Big5 + ISO-2022-TW + Big5-HKSCS + VISCII + Windows-1258 + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4569994a..22d7002b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -51,6 +51,7 @@ show_logcat_key bottom_title_key poster_ui_key + subtitles_encoding_key %d %s | %sMB @@ -418,6 +419,7 @@ Provider languages App Layout Preferred media + Subtitle encoding Preferred media and language User interface