forked from recloudstream/cloudstream
Add option for default media player (Internal, VLC and browser) & fixed VLC detection
This commit is contained in:
parent
03eb17149f
commit
fbbcdb4889
8 changed files with 102 additions and 22 deletions
|
@ -21,6 +21,10 @@
|
|||
android:name="android.software.leanback"
|
||||
android:required="false" />
|
||||
|
||||
<queries>
|
||||
<package android:name="org.videolan.vlc" />
|
||||
</queries>
|
||||
|
||||
<!--TODO https://stackoverflow.com/questions/41799732/chromecast-button-not-visible-in-android-->
|
||||
<application
|
||||
android:name=".AcraApplication"
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.lagradost.cloudstream3.ui.result
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
@ -9,6 +10,7 @@ import android.widget.TextView
|
|||
import androidx.core.view.isGone
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.widget.ContentLoadingProgressBar
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.button.MaterialButton
|
||||
|
@ -60,6 +62,22 @@ class EpisodeAdapter(
|
|||
private val clickCallback: (EpisodeClickEvent) -> Unit,
|
||||
private val downloadClickCallback: (DownloadClickEvent) -> Unit,
|
||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
companion object {
|
||||
/**
|
||||
* @return ACTION_PLAY_EPISODE_IN_PLAYER, ACTION_PLAY_EPISODE_IN_BROWSER or ACTION_PLAY_EPISODE_IN_VLC_PLAYER depending on player settings.
|
||||
* See array.xml/player_pref_values
|
||||
**/
|
||||
fun getPlayerAction(context: Context): Int {
|
||||
val settingsManager = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
return when (settingsManager.getInt(context.getString(R.string.player_pref_key), 1)) {
|
||||
1 -> ACTION_PLAY_EPISODE_IN_PLAYER
|
||||
2 -> ACTION_PLAY_EPISODE_IN_VLC_PLAYER
|
||||
3 -> ACTION_PLAY_EPISODE_IN_BROWSER
|
||||
else -> ACTION_PLAY_EPISODE_IN_PLAYER
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var cardList: MutableList<ResultEpisode> = mutableListOf()
|
||||
|
||||
private val mBoundViewHolders: HashSet<DownloadButtonViewHolder> = HashSet()
|
||||
|
|
|
@ -38,6 +38,7 @@ import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_DOWNLOAD
|
|||
import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick
|
||||
import com.lagradost.cloudstream3.ui.download.EasyDownloadButton
|
||||
import com.lagradost.cloudstream3.ui.quicksearch.QuickSearchFragment
|
||||
import com.lagradost.cloudstream3.ui.result.EpisodeAdapter.Companion.getPlayerAction
|
||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
|
||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
|
@ -455,7 +456,8 @@ open class ResultFragment : ResultTrailerPlayer() {
|
|||
val apiName: String,
|
||||
val showFillers: Boolean,
|
||||
val dubStatus: DubStatus,
|
||||
val start: AutoResume?
|
||||
val start: AutoResume?,
|
||||
val playerAction: Int
|
||||
)
|
||||
|
||||
private fun getStoredData(context: Context): StoredData? {
|
||||
|
@ -469,6 +471,8 @@ open class ResultFragment : ResultTrailerPlayer() {
|
|||
) DubStatus.Dubbed else DubStatus.Subbed
|
||||
val startAction = arguments?.getInt(START_ACTION_BUNDLE)
|
||||
|
||||
val playerAction = getPlayerAction(context)
|
||||
|
||||
val start = startAction?.let { action ->
|
||||
val startValue = arguments?.getInt(START_VALUE_BUNDLE)
|
||||
val resumeEpisode = arguments?.getInt(EPISODE_BUNDLE)
|
||||
|
@ -483,7 +487,7 @@ open class ResultFragment : ResultTrailerPlayer() {
|
|||
season = resumeSeason
|
||||
)
|
||||
}
|
||||
return StoredData(url, apiName, showFillers, dubStatus, start)
|
||||
return StoredData(url, apiName, showFillers, dubStatus, start, playerAction)
|
||||
}
|
||||
|
||||
private fun reloadViewModel(success: Boolean = false) {
|
||||
|
@ -774,7 +778,8 @@ open class ResultFragment : ResultTrailerPlayer() {
|
|||
viewModel.handleAction(
|
||||
activity,
|
||||
EpisodeClickEvent(
|
||||
ACTION_PLAY_EPISODE_IN_PLAYER, value.result
|
||||
storedData?.playerAction ?: ACTION_PLAY_EPISODE_IN_PLAYER,
|
||||
value.result
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
package com.lagradost.cloudstream3.ui.result
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.*
|
||||
import android.net.Uri
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
|
@ -33,6 +30,7 @@ import com.lagradost.cloudstream3.ui.player.GeneratorPlayer
|
|||
import com.lagradost.cloudstream3.ui.player.IGenerator
|
||||
import com.lagradost.cloudstream3.ui.player.RepoLinkGenerator
|
||||
import com.lagradost.cloudstream3.ui.player.SubtitleData
|
||||
import com.lagradost.cloudstream3.ui.result.EpisodeAdapter.Companion.getPlayerAction
|
||||
import com.lagradost.cloudstream3.ui.subtitles.SubtitlesFragment
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.getNameFull
|
||||
|
@ -973,9 +971,11 @@ class ResultViewModel2 : ViewModel() {
|
|||
File.createTempFile("mirrorlist", ".m3u8", outputDir)
|
||||
}
|
||||
var text = "#EXTM3U"
|
||||
for (sub in data.subs) {
|
||||
text += "\n#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID=\"subs\",NAME=\"${sub.name}\",DEFAULT=NO,AUTOSELECT=NO,FORCED=NO,LANGUAGE=\"${sub.name}\",URI=\"${sub.url}\""
|
||||
}
|
||||
|
||||
// With subtitles it doesn't work for no reason :(
|
||||
// for (sub in data.subs) {
|
||||
// text += "\n#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID=\"subs\",NAME=\"${sub.name}\",DEFAULT=NO,AUTOSELECT=NO,FORCED=NO,LANGUAGE=\"${sub.name}\",URI=\"${sub.url}\""
|
||||
// }
|
||||
for (link in data.links) {
|
||||
text += "\n#EXTINF:, ${link.name}\n${link.url}"
|
||||
}
|
||||
|
@ -999,11 +999,10 @@ class ResultViewModel2 : ViewModel() {
|
|||
|
||||
val startId = VLC_FROM_PROGRESS
|
||||
|
||||
var position = startId
|
||||
if (startId == VLC_FROM_START) {
|
||||
position = 1
|
||||
} else if (startId == VLC_FROM_PROGRESS) {
|
||||
position = 0
|
||||
val position = when (startId) {
|
||||
VLC_FROM_START -> 1
|
||||
VLC_FROM_PROGRESS -> 0
|
||||
else -> 0
|
||||
}
|
||||
|
||||
vlcIntent.putExtra("position", position)
|
||||
|
@ -1013,9 +1012,15 @@ class ResultViewModel2 : ViewModel() {
|
|||
act.startActivityForResult(vlcIntent, VLC_REQUEST_CODE)
|
||||
} catch (e: Exception) {
|
||||
logError(e)
|
||||
main {
|
||||
if (e is ActivityNotFoundException) {
|
||||
showToast(act, txt(R.string.vlc_not_found_error), Toast.LENGTH_LONG)
|
||||
} else {
|
||||
showToast(act, e.toString(), Toast.LENGTH_LONG)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun handleAction(activity: Activity?, click: EpisodeClickEvent) = viewModelScope.launchSafe {
|
||||
handleEpisodeClickEvent(activity, click)
|
||||
|
@ -1073,9 +1078,10 @@ class ResultViewModel2 : ViewModel() {
|
|||
click.copy(action = ACTION_CHROME_CAST_EPISODE)
|
||||
)
|
||||
} else {
|
||||
val action = getPlayerAction(ctx)
|
||||
handleEpisodeClickEvent(
|
||||
activity,
|
||||
click.copy(action = ACTION_PLAY_EPISODE_IN_PLAYER)
|
||||
click.copy(action = action)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1592,7 +1598,8 @@ class ResultViewModel2 : ViewModel() {
|
|||
val idIndex = ep.key.id
|
||||
for ((index, i) in ep.value.withIndex()) {
|
||||
val episode = i.episode ?: (index + 1)
|
||||
val id = mainId + episode + idIndex * 1_000_000 + (i.season?.times(10_000) ?: 0)
|
||||
val id =
|
||||
mainId + episode + idIndex * 1_000_000 + (i.season?.times(10_000) ?: 0)
|
||||
if (!existingEpisodes.contains(id)) {
|
||||
existingEpisodes.add(id)
|
||||
val seasonData = loadResponse.seasonNames.getSeason(i.season)
|
||||
|
@ -1888,7 +1895,10 @@ class ResultViewModel2 : ViewModel() {
|
|||
if (ep.getWatchProgress() > 0.9) continue
|
||||
handleAction(
|
||||
activity,
|
||||
EpisodeClickEvent(ACTION_PLAY_EPISODE_IN_PLAYER, ep)
|
||||
EpisodeClickEvent(
|
||||
getPlayerAction(activity),
|
||||
ep
|
||||
)
|
||||
)
|
||||
break
|
||||
}
|
||||
|
@ -1905,7 +1915,10 @@ class ResultViewModel2 : ViewModel() {
|
|||
?: return@launchSafe
|
||||
handleAction(
|
||||
activity,
|
||||
EpisodeClickEvent(ACTION_PLAY_EPISODE_IN_PLAYER, episode)
|
||||
EpisodeClickEvent(
|
||||
getPlayerAction(activity),
|
||||
episode
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -113,6 +113,22 @@ class SettingsPlayer : PreferenceFragmentCompat() {
|
|||
return@setOnPreferenceClickListener true
|
||||
}
|
||||
|
||||
getPref(R.string.player_pref_key)?.setOnPreferenceClickListener {
|
||||
val prefNames = resources.getStringArray(R.array.player_pref_names)
|
||||
val prefValues = resources.getIntArray(R.array.player_pref_values)
|
||||
val current = settingsManager.getInt(getString(R.string.player_pref_key), 1)
|
||||
|
||||
activity?.showBottomDialog(
|
||||
prefNames.toList(),
|
||||
prefValues.indexOf(current),
|
||||
getString(R.string.player_pref),
|
||||
true,
|
||||
{}) {
|
||||
settingsManager.edit().putInt(getString(R.string.player_pref_key), prefValues[it]).apply()
|
||||
}
|
||||
return@setOnPreferenceClickListener true
|
||||
}
|
||||
|
||||
getPref(R.string.subtitle_settings_key)?.setOnPreferenceClickListener {
|
||||
SubtitlesFragment.push(activity, false)
|
||||
return@setOnPreferenceClickListener true
|
||||
|
|
|
@ -33,6 +33,18 @@
|
|||
<item>6</item>
|
||||
</array>
|
||||
|
||||
<array name="player_pref_names">
|
||||
<item>@string/player_settings_play_in_app</item>
|
||||
<item>@string/player_settings_play_in_vlc</item>
|
||||
<item>@string/player_settings_play_in_browser</item>
|
||||
</array>
|
||||
|
||||
<array name="player_pref_values">
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
<item>3</item>
|
||||
</array>
|
||||
|
||||
<array name="limit_title_rez_pref_names">
|
||||
<item>@string/resolution_and_title</item>
|
||||
<item>@string/title</item>
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
<string name="subtitle_settings_key" translatable="false">subtitle_settings_key</string>
|
||||
<string name="subtitle_settings_chromecast_key" translatable="false">subtitle_settings_chromecast_key</string>
|
||||
<string name="quality_pref_key" translatable="false">quality_pref_key</string>
|
||||
<string name="player_pref_key" translatable="false">player_pref_key</string>
|
||||
<string name="prefer_limit_title_key" translatable="false">prefer_limit_title_key</string>
|
||||
<string name="prefer_limit_title_rez_key" translatable="false">prefer_limit_title_rez_key</string>
|
||||
<string name="video_buffer_size_key" translatable="false">video_buffer_size_key</string>
|
||||
|
@ -628,4 +629,10 @@
|
|||
<string name="extension_install_first">Install the extension first</string>
|
||||
|
||||
<string name="hls_playlist">HLS Playlist</string>
|
||||
|
||||
<string name="player_pref">Preferred video player</string>
|
||||
<string name="player_settings_play_in_app">Internal player</string>
|
||||
<string name="player_settings_play_in_vlc">VLC</string>
|
||||
<string name="player_settings_play_in_browser">Browser</string>
|
||||
<string name="vlc_not_found_error">VLC not found</string>
|
||||
</resources>
|
||||
|
|
|
@ -18,6 +18,11 @@
|
|||
android:title="@string/watch_quality_pref"
|
||||
android:icon="@drawable/ic_baseline_hd_24" />
|
||||
|
||||
<Preference
|
||||
android:key="@string/player_pref_key"
|
||||
android:title="@string/player_pref"
|
||||
android:icon="@drawable/netflix_play" />
|
||||
|
||||
<Preference
|
||||
android:key="@string/prefer_limit_title_key"
|
||||
android:title="@string/limit_title"
|
||||
|
|
Loading…
Reference in a new issue