mirror of
https://github.com/videolan/vlc-android
synced 2024-11-23 18:05:36 +08:00
Add the hearing unpaired flag to opensubtitles queries
This commit is contained in:
parent
48e4cecb6b
commit
cba5d3ead4
@ -28,5 +28,6 @@ data class ExternalSub (
|
||||
val subtitlePath: String,
|
||||
val mediaPath: String,
|
||||
val subLanguageID: String,
|
||||
val movieReleaseName: String
|
||||
val movieReleaseName: String,
|
||||
val hearingImpaired: Boolean
|
||||
)
|
||||
|
@ -18,11 +18,13 @@ interface IOpenSubtitleService {
|
||||
|
||||
|
||||
@GET("subtitles")
|
||||
suspend fun query( @Query("languages") languageId: String = "",
|
||||
@Query("movieHash") movieHash: String? = null,
|
||||
@Query("query") name: String? = null,
|
||||
@Query("imdb_id") imdbId: String? = null ,
|
||||
suspend fun query(
|
||||
@Query("episode_number") episode: Int? = null,
|
||||
@Query("hearing_impaired") hearingImpaired: String,
|
||||
@Query("imdb_id") imdbId: String? = null,
|
||||
@Query("languages") languageId: String = "",
|
||||
@Query("moviehash") movieHash: String? = null,
|
||||
@Query("query") name: String? = null,
|
||||
@Query("season_number") season: Int? = null,
|
||||
): OpenSubV1
|
||||
|
||||
|
@ -10,15 +10,24 @@ class OpenSubtitleRepository(private val openSubtitleService: IOpenSubtitleServi
|
||||
*/
|
||||
|
||||
|
||||
suspend fun queryWithHash(movieByteSize: Long, movieHash: String?, languageIds: List<String>?): OpenSubV1 {
|
||||
val actualLanguageIds = languageIds?.toSet()?.run { if (contains("") || isEmpty()) setOf("") else this } ?: setOf("")
|
||||
suspend fun queryWithHash(
|
||||
movieByteSize: Long,
|
||||
movieHash: String?,
|
||||
languageIds: List<String>?,
|
||||
hearingImpaired: Boolean
|
||||
): OpenSubV1 {
|
||||
val actualLanguageIds =
|
||||
languageIds?.toSet()?.run { if (contains("") || isEmpty()) setOf("") else this }
|
||||
?: setOf("")
|
||||
return openSubtitleService.query(
|
||||
// movieByteSize = movieByteSize.toString(),
|
||||
movieHash = movieHash ?: "",
|
||||
languageId = actualLanguageIds.joinToString(","))
|
||||
languageId = actualLanguageIds.sorted().joinToString(","),
|
||||
hearingImpaired = if (hearingImpaired) "only" else "include"
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun queryWithName(name: String, episode: Int?, season: Int?, languageIds: List<String>?): OpenSubV1 {
|
||||
suspend fun queryWithName(name: String, episode: Int?, season: Int?, languageIds: List<String>?, hearingImpaired: Boolean): OpenSubV1 {
|
||||
val actualEpisode = episode ?: 0
|
||||
val actualSeason = season ?: 0
|
||||
val actualLanguageIds = languageIds?.toSet()?.run { if (contains("") || isEmpty()) setOf("") else this } ?: setOf("")
|
||||
@ -26,7 +35,10 @@ class OpenSubtitleRepository(private val openSubtitleService: IOpenSubtitleServi
|
||||
name = name,
|
||||
episode = actualEpisode,
|
||||
season = actualSeason,
|
||||
languageId = actualLanguageIds.joinToString(","))
|
||||
languageId = actualLanguageIds.sorted().joinToString(","),
|
||||
hearingImpaired = if (hearingImpaired) "only" else "include"
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -0,0 +1,13 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:width="18dp"
|
||||
android:height="18dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
|
||||
<path
|
||||
android:fillColor="?attr/colorControlNormal"
|
||||
android:pathData="M6.03,3.2C7.15,2.44 8.51,2 10,2c3.93,0 7,3.07 7,7c0,1.26 -0.38,2.65 -1.07,3.9c-0.02,0.04 -0.05,0.08 -0.08,0.13l-1.48,-1.48C14.77,10.69 15,9.8 15,9c0,-2.8 -2.2,-5 -5,-5C9.08,4 8.24,4.26 7.5,4.67L6.03,3.2zM17.21,14.38l1.43,1.43C20.11,13.93 21,11.57 21,9c0,-3.04 -1.23,-5.79 -3.22,-7.78l-1.42,1.42C17.99,4.26 19,6.51 19,9C19,11.02 18.33,12.88 17.21,14.38zM10,6.5c-0.21,0 -0.4,0.03 -0.59,0.08l3.01,3.01C12.47,9.4 12.5,9.21 12.5,9C12.5,7.62 11.38,6.5 10,6.5zM21.19,21.19L2.81,2.81L1.39,4.22l2.13,2.13C3.19,7.16 3,8.05 3,9h2c0,-0.36 0.05,-0.71 0.12,-1.05l6.61,6.61c-0.88,0.68 -1.78,1.41 -2.27,2.9c-0.5,1.5 -1,2.01 -1.71,2.38C7.56,19.94 7.29,20 7,20c-1.1,0 -2,-0.9 -2,-2H3c0,2.21 1.79,4 4,4c0.57,0 1.13,-0.12 1.64,-0.35c1.36,-0.71 2.13,-1.73 2.73,-3.55c0.32,-0.98 0.9,-1.43 1.71,-2.05c0.03,-0.02 0.05,-0.04 0.08,-0.06l6.62,6.62L21.19,21.19z"
|
||||
tools:fillColor="@color/white" />
|
||||
|
||||
</vector>
|
@ -976,6 +976,7 @@
|
||||
<string name="sub_result_by_name">Results for %s</string>
|
||||
<string name="sub_result_by_name_season">Season %s</string>
|
||||
<string name="sub_result_by_name_episode">Episode %s</string>
|
||||
<string name="sub_result_by_name_hearing_impaired">only hearing impaired</string>
|
||||
|
||||
<string name="sub_result_by_file">Results for your file</string>
|
||||
<string name="donate">Help VLC</string>
|
||||
|
@ -17,9 +17,9 @@
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="50dp"
|
||||
android:focusable="true"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:focusable="true"
|
||||
android:minHeight="50dp"
|
||||
android:nextFocusRight="@+id/download_sub"
|
||||
android:nextFocusForward="@+id/download_sub">
|
||||
|
||||
@ -34,16 +34,29 @@
|
||||
android:text="@{subtitleItem.movieReleaseName.trim()}"
|
||||
android:textColor="?attr/font_default"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/language"
|
||||
app:layout_constraintEnd_toStartOf="@+id/imageView20"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintHorizontal_chainStyle="spread"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Attack.on.Titan.S02E01.DUBBED.HDTV.x264-W4F" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/imageView20"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:visibility="@{subtitleItem.hearingImpaired ? View.VISIBLE : View.GONE}"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/sub_title"
|
||||
app:layout_constraintStart_toEndOf="@+id/sub_title"
|
||||
app:layout_constraintTop_toTopOf="@+id/sub_title"
|
||||
app:srcCompat="@drawable/ic_hearing_impaired" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/language"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:fontFamily="sans-serif-light"
|
||||
android:gravity="center_vertical"
|
||||
@ -52,9 +65,9 @@
|
||||
android:textColor="?attr/font_default"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/barrier"
|
||||
app:layout_constraintEnd_toStartOf="@+id/download_sub"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/sub_title"
|
||||
app:layout_constraintStart_toEndOf="@+id/imageView20"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="En" />
|
||||
|
||||
@ -63,14 +76,16 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:focusable="true"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:focusable="true"
|
||||
android:importantForAccessibility="no"
|
||||
android:padding="4dp"
|
||||
android:src="@{subtitleItem.state == State.Downloaded ? @drawable/ic_done : @drawable/ic_download_subtitles }"
|
||||
android:visibility="@{subtitleItem.state == State.Downloading ? View.GONE : View.VISIBLE}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/language"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:srcCompat="@drawable/ic_download_subtitles" />
|
||||
|
||||
|
@ -152,6 +152,8 @@ class SubtitleDownloaderDialogFragment : VLCBottomSheetDialogFragment() {
|
||||
viewModel.observableSearchLanguage.set(selectedLanguages)
|
||||
}
|
||||
})
|
||||
//todo
|
||||
viewModel.observableSearchHearingImpaired.set(true)
|
||||
|
||||
binding.retryButton.setOnClickListener {
|
||||
viewModel.onRefresh()
|
||||
|
@ -8,7 +8,8 @@ data class SubtitleItem (
|
||||
val subLanguageID: String,
|
||||
val movieReleaseName: String,
|
||||
val state: State,
|
||||
val zipDownloadLink: String
|
||||
val zipDownloadLink: String,
|
||||
val hearingImpaired: Boolean
|
||||
)
|
||||
|
||||
enum class State {
|
||||
|
@ -44,8 +44,8 @@ class ExternalSubRepository(private val externalSubDao: ExternalSubDao, private
|
||||
val downloadingSubtitles: LiveData<Map<Long, SubtitleItem>>
|
||||
get() = _downloadingSubtitles as LiveData<Map<Long, SubtitleItem>>
|
||||
|
||||
fun saveDownloadedSubtitle(idSubtitle: String, subtitlePath: String, mediaPath: String, language: String, movieReleaseName: String): Job {
|
||||
return GlobalScope.launch(coroutineContextProvider.IO) { externalSubDao.insert(org.videolan.vlc.mediadb.models.ExternalSub(idSubtitle, subtitlePath, mediaPath, language, movieReleaseName)) }
|
||||
fun saveDownloadedSubtitle(idSubtitle: String, subtitlePath: String, mediaPath: String, language: String, movieReleaseName: String, hearingImpaired: Boolean): Job {
|
||||
return GlobalScope.launch(coroutineContextProvider.IO) { externalSubDao.insert(org.videolan.vlc.mediadb.models.ExternalSub(idSubtitle, subtitlePath, mediaPath, language, movieReleaseName, hearingImpaired)) }
|
||||
}
|
||||
|
||||
fun getDownloadedSubtitles(mediaUri: Uri): LiveData<List<org.videolan.vlc.mediadb.models.ExternalSub>> {
|
||||
|
@ -88,7 +88,8 @@ object VLCDownloadManager: BroadcastReceiver(), DefaultLifecycleObserver {
|
||||
it,
|
||||
mediaUri.path!!,
|
||||
subLanguageID,
|
||||
movieReleaseName
|
||||
movieReleaseName,
|
||||
hearingImpaired
|
||||
)
|
||||
}
|
||||
else
|
||||
|
@ -29,6 +29,7 @@ import org.videolan.vlc.R
|
||||
import org.videolan.vlc.gui.dialogs.State
|
||||
import org.videolan.vlc.gui.dialogs.SubtitleItem
|
||||
import org.videolan.vlc.repository.ExternalSubRepository
|
||||
import org.videolan.vlc.util.TextUtils
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
@ -39,6 +40,7 @@ class SubtitlesModel(private val context: Context, private val mediaUri: Uri, pr
|
||||
val observableSearchEpisode = ObservableField<String>()
|
||||
val observableSearchSeason = ObservableField<String>()
|
||||
val observableSearchLanguage = ObservableField<List<String>>()
|
||||
val observableSearchHearingImpaired = ObservableField<Boolean>()
|
||||
private var previousSearchLanguage: List<String>? = null
|
||||
val manualSearchEnabled = ObservableBoolean(false)
|
||||
|
||||
@ -49,7 +51,7 @@ class SubtitlesModel(private val context: Context, private val mediaUri: Uri, pr
|
||||
|
||||
private val apiResultLiveData: MutableLiveData<List<Data>> = MutableLiveData()
|
||||
private val downloadedLiveData = ExternalSubRepository.getInstance(context).getDownloadedSubtitles(mediaUri).map { list ->
|
||||
list.map { SubtitleItem(it.idSubtitle, mediaUri, it.subLanguageID, it.movieReleaseName, State.Downloaded, "") }
|
||||
list.map { SubtitleItem(it.idSubtitle, mediaUri, it.subLanguageID, it.movieReleaseName, State.Downloaded, "", it.hearingImpaired) }
|
||||
}
|
||||
|
||||
private val downloadingLiveData = ExternalSubRepository.getInstance(context).downloadingSubtitles
|
||||
@ -109,26 +111,28 @@ class SubtitlesModel(private val context: Context, private val mediaUri: Uri, pr
|
||||
val exist = history?.find { it.idSubtitle == openSubtitle.attributes.subtitleId }
|
||||
val state = exist?.state ?: State.NotDownloaded
|
||||
if (openSubtitle.attributes.files.isNotEmpty())
|
||||
list.add(SubtitleItem(openSubtitle.attributes.subtitleId, mediaUri, openSubtitle.attributes.language, openSubtitle.attributes.featureDetails.movieName, state, OpenSubtitleClient.getDownloadLink(openSubtitle.attributes.files.first().fileId)))
|
||||
list.add(SubtitleItem(openSubtitle.attributes.subtitleId, mediaUri, openSubtitle.attributes.language, openSubtitle.attributes.featureDetails.movieName, state, OpenSubtitleClient.getDownloadLink(openSubtitle.attributes.files.first().fileId), openSubtitle.attributes.hearingImpaired))
|
||||
}
|
||||
list
|
||||
}
|
||||
|
||||
private suspend fun getSubtitleByName(name: String, episode: Int?, season: Int?, languageIds: List<String>?): OpenSubV1 {
|
||||
private suspend fun getSubtitleByName(name: String, episode: Int?, season: Int?, languageIds: List<String>?, hearingImpaired: Boolean): OpenSubV1 {
|
||||
if (BuildConfig.DEBUG) Log.d(this::class.java.simpleName, "Getting subs by name with $name")
|
||||
val builder = StringBuilder(context.getString(R.string.sub_result_by_name, "<i>$name</i>"))
|
||||
season?.let { builder.append(" - ").append(context.getString(R.string.sub_result_by_name_season, "<i>$it</i>")) }
|
||||
episode?.let { builder.append(" - ").append(context.getString(R.string.sub_result_by_name_episode, "<i>$it</i>")) }
|
||||
season?.let { builder.append(" ${TextUtils.SEPARATOR} ").append(context.getString(R.string.sub_result_by_name_season, "<i>$it</i>")) }
|
||||
episode?.let { builder.append(" ${TextUtils.SEPARATOR} ").append(context.getString(R.string.sub_result_by_name_episode, "<i>$it</i>")) }
|
||||
languageIds?.let { if (languageIds.isNotEmpty()) builder.append(" ${TextUtils.SEPARATOR} ").append("<i>${it.joinToString(", ")}</i>") }
|
||||
if (hearingImpaired) builder.append(" ${TextUtils.SEPARATOR} ").append(context.getString(R.string.sub_result_by_name_hearing_impaired))
|
||||
observableResultDescription.set(Html.fromHtml(builder.toString()))
|
||||
manualSearchEnabled.set(true)
|
||||
return OpenSubtitleRepository.getInstance().queryWithName(name, episode, season, languageIds)
|
||||
return OpenSubtitleRepository.getInstance().queryWithName(name, episode, season, languageIds, hearingImpaired)
|
||||
}
|
||||
|
||||
private suspend fun getSubtitleByHash(movieByteSize: Long, movieHash: String?, languageIds: List<String>?): OpenSubV1 {
|
||||
private suspend fun getSubtitleByHash(movieByteSize: Long, movieHash: String?, languageIds: List<String>?, hearingImpaired: Boolean): OpenSubV1 {
|
||||
if (BuildConfig.DEBUG) Log.d(this::class.java.simpleName, "Getting subs by hash with $movieHash")
|
||||
manualSearchEnabled.set(false)
|
||||
observableResultDescription.set(context.getString(R.string.sub_result_by_file).toSpanned())
|
||||
return OpenSubtitleRepository.getInstance().queryWithHash(movieByteSize, movieHash, languageIds)
|
||||
return OpenSubtitleRepository.getInstance().queryWithHash(movieByteSize, movieHash, languageIds, hearingImpaired)
|
||||
}
|
||||
|
||||
fun onRefresh() {
|
||||
@ -155,17 +159,17 @@ class SubtitlesModel(private val context: Context, private val mediaUri: Uri, pr
|
||||
if (videoFile.exists()) {
|
||||
val hash = FileUtils.computeHash(videoFile)
|
||||
val fileLength = videoFile.length()
|
||||
val hashSubs = getSubtitleByHash(fileLength, hash, observableSearchLanguage.get()).data
|
||||
val hashSubs = getSubtitleByHash(fileLength, hash, observableSearchLanguage.get(), observableSearchHearingImpaired.get() ?: false).data
|
||||
// No result for hash. Falling back to name search
|
||||
if (hashSubs.isEmpty()) getSubtitleByName(videoFile.name, null, null, observableSearchLanguage.get()).data else hashSubs
|
||||
if (hashSubs.isEmpty()) getSubtitleByName(videoFile.name, null, null, observableSearchLanguage.get(), observableSearchHearingImpaired.get() ?: false).data else hashSubs
|
||||
} else {
|
||||
getSubtitleByName(name, null, null, observableSearchLanguage.get()).data
|
||||
getSubtitleByName(name, null, null, observableSearchLanguage.get(), observableSearchHearingImpaired.get() ?: false).data
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
observableSearchName.get()?.let {
|
||||
getSubtitleByName(it, observableSearchEpisode.get()?.toInt(), observableSearchSeason.get()?.toInt(), observableSearchLanguage.get()).data
|
||||
getSubtitleByName(it, observableSearchEpisode.get()?.toInt(), observableSearchSeason.get()?.toInt(), observableSearchLanguage.get(), observableSearchHearingImpaired.get() ?: false).data
|
||||
} ?: listOf()
|
||||
}
|
||||
if (isActive) apiResultLiveData.postValue(subs)
|
||||
|
Loading…
Reference in New Issue
Block a user