Add option for default media player (Internal, VLC and browser) & fixed VLC detection

This commit is contained in:
Blatzar 2022-10-06 00:14:42 +02:00
parent 03eb17149f
commit fbbcdb4889
8 changed files with 102 additions and 22 deletions

View file

@ -21,6 +21,10 @@
android:name="android.software.leanback" android:name="android.software.leanback"
android:required="false" /> android:required="false" />
<queries>
<package android:name="org.videolan.vlc" />
</queries>
<!--TODO https://stackoverflow.com/questions/41799732/chromecast-button-not-visible-in-android--> <!--TODO https://stackoverflow.com/questions/41799732/chromecast-button-not-visible-in-android-->
<application <application
android:name=".AcraApplication" android:name=".AcraApplication"

View file

@ -1,6 +1,7 @@
package com.lagradost.cloudstream3.ui.result package com.lagradost.cloudstream3.ui.result
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@ -9,6 +10,7 @@ import android.widget.TextView
import androidx.core.view.isGone import androidx.core.view.isGone
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.widget.ContentLoadingProgressBar import androidx.core.widget.ContentLoadingProgressBar
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.button.MaterialButton import com.google.android.material.button.MaterialButton
@ -60,6 +62,22 @@ class EpisodeAdapter(
private val clickCallback: (EpisodeClickEvent) -> Unit, private val clickCallback: (EpisodeClickEvent) -> Unit,
private val downloadClickCallback: (DownloadClickEvent) -> Unit, private val downloadClickCallback: (DownloadClickEvent) -> Unit,
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { ) : 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() var cardList: MutableList<ResultEpisode> = mutableListOf()
private val mBoundViewHolders: HashSet<DownloadButtonViewHolder> = HashSet() private val mBoundViewHolders: HashSet<DownloadButtonViewHolder> = HashSet()

View file

@ -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.DownloadButtonSetup.handleDownloadClick
import com.lagradost.cloudstream3.ui.download.EasyDownloadButton import com.lagradost.cloudstream3.ui.download.EasyDownloadButton
import com.lagradost.cloudstream3.ui.quicksearch.QuickSearchFragment 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.isTrueTvSettings
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.*
@ -455,7 +456,8 @@ open class ResultFragment : ResultTrailerPlayer() {
val apiName: String, val apiName: String,
val showFillers: Boolean, val showFillers: Boolean,
val dubStatus: DubStatus, val dubStatus: DubStatus,
val start: AutoResume? val start: AutoResume?,
val playerAction: Int
) )
private fun getStoredData(context: Context): StoredData? { private fun getStoredData(context: Context): StoredData? {
@ -469,6 +471,8 @@ open class ResultFragment : ResultTrailerPlayer() {
) DubStatus.Dubbed else DubStatus.Subbed ) DubStatus.Dubbed else DubStatus.Subbed
val startAction = arguments?.getInt(START_ACTION_BUNDLE) val startAction = arguments?.getInt(START_ACTION_BUNDLE)
val playerAction = getPlayerAction(context)
val start = startAction?.let { action -> val start = startAction?.let { action ->
val startValue = arguments?.getInt(START_VALUE_BUNDLE) val startValue = arguments?.getInt(START_VALUE_BUNDLE)
val resumeEpisode = arguments?.getInt(EPISODE_BUNDLE) val resumeEpisode = arguments?.getInt(EPISODE_BUNDLE)
@ -483,7 +487,7 @@ open class ResultFragment : ResultTrailerPlayer() {
season = resumeSeason season = resumeSeason
) )
} }
return StoredData(url, apiName, showFillers, dubStatus, start) return StoredData(url, apiName, showFillers, dubStatus, start, playerAction)
} }
private fun reloadViewModel(success: Boolean = false) { private fun reloadViewModel(success: Boolean = false) {
@ -774,7 +778,8 @@ open class ResultFragment : ResultTrailerPlayer() {
viewModel.handleAction( viewModel.handleAction(
activity, activity,
EpisodeClickEvent( EpisodeClickEvent(
ACTION_PLAY_EPISODE_IN_PLAYER, value.result storedData?.playerAction ?: ACTION_PLAY_EPISODE_IN_PLAYER,
value.result
) )
) )
} }

View file

@ -1,10 +1,7 @@
package com.lagradost.cloudstream3.ui.result package com.lagradost.cloudstream3.ui.result
import android.app.Activity import android.app.Activity
import android.content.ClipData import android.content.*
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.net.Uri import android.net.Uri
import android.util.Log import android.util.Log
import android.widget.Toast 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.IGenerator
import com.lagradost.cloudstream3.ui.player.RepoLinkGenerator import com.lagradost.cloudstream3.ui.player.RepoLinkGenerator
import com.lagradost.cloudstream3.ui.player.SubtitleData 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.ui.subtitles.SubtitlesFragment
import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.*
import com.lagradost.cloudstream3.utils.AppUtils.getNameFull import com.lagradost.cloudstream3.utils.AppUtils.getNameFull
@ -973,9 +971,11 @@ class ResultViewModel2 : ViewModel() {
File.createTempFile("mirrorlist", ".m3u8", outputDir) File.createTempFile("mirrorlist", ".m3u8", outputDir)
} }
var text = "#EXTM3U" 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) { for (link in data.links) {
text += "\n#EXTINF:, ${link.name}\n${link.url}" text += "\n#EXTINF:, ${link.name}\n${link.url}"
} }
@ -999,11 +999,10 @@ class ResultViewModel2 : ViewModel() {
val startId = VLC_FROM_PROGRESS val startId = VLC_FROM_PROGRESS
var position = startId val position = when (startId) {
if (startId == VLC_FROM_START) { VLC_FROM_START -> 1
position = 1 VLC_FROM_PROGRESS -> 0
} else if (startId == VLC_FROM_PROGRESS) { else -> 0
position = 0
} }
vlcIntent.putExtra("position", position) vlcIntent.putExtra("position", position)
@ -1013,7 +1012,13 @@ class ResultViewModel2 : ViewModel() {
act.startActivityForResult(vlcIntent, VLC_REQUEST_CODE) act.startActivityForResult(vlcIntent, VLC_REQUEST_CODE)
} catch (e: Exception) { } catch (e: Exception) {
logError(e) logError(e)
showToast(act, e.toString(), Toast.LENGTH_LONG) 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)
}
}
} }
} }
@ -1073,9 +1078,10 @@ class ResultViewModel2 : ViewModel() {
click.copy(action = ACTION_CHROME_CAST_EPISODE) click.copy(action = ACTION_CHROME_CAST_EPISODE)
) )
} else { } else {
val action = getPlayerAction(ctx)
handleEpisodeClickEvent( handleEpisodeClickEvent(
activity, 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 val idIndex = ep.key.id
for ((index, i) in ep.value.withIndex()) { for ((index, i) in ep.value.withIndex()) {
val episode = i.episode ?: (index + 1) 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)) { if (!existingEpisodes.contains(id)) {
existingEpisodes.add(id) existingEpisodes.add(id)
val seasonData = loadResponse.seasonNames.getSeason(i.season) val seasonData = loadResponse.seasonNames.getSeason(i.season)
@ -1888,7 +1895,10 @@ class ResultViewModel2 : ViewModel() {
if (ep.getWatchProgress() > 0.9) continue if (ep.getWatchProgress() > 0.9) continue
handleAction( handleAction(
activity, activity,
EpisodeClickEvent(ACTION_PLAY_EPISODE_IN_PLAYER, ep) EpisodeClickEvent(
getPlayerAction(activity),
ep
)
) )
break break
} }
@ -1905,7 +1915,10 @@ class ResultViewModel2 : ViewModel() {
?: return@launchSafe ?: return@launchSafe
handleAction( handleAction(
activity, activity,
EpisodeClickEvent(ACTION_PLAY_EPISODE_IN_PLAYER, episode) EpisodeClickEvent(
getPlayerAction(activity),
episode
)
) )
} }
} }

View file

@ -113,6 +113,22 @@ class SettingsPlayer : PreferenceFragmentCompat() {
return@setOnPreferenceClickListener true 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 { getPref(R.string.subtitle_settings_key)?.setOnPreferenceClickListener {
SubtitlesFragment.push(activity, false) SubtitlesFragment.push(activity, false)
return@setOnPreferenceClickListener true return@setOnPreferenceClickListener true

View file

@ -33,6 +33,18 @@
<item>6</item> <item>6</item>
</array> </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"> <array name="limit_title_rez_pref_names">
<item>@string/resolution_and_title</item> <item>@string/resolution_and_title</item>
<item>@string/title</item> <item>@string/title</item>

View file

@ -14,6 +14,7 @@
<string name="subtitle_settings_key" translatable="false">subtitle_settings_key</string> <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="subtitle_settings_chromecast_key" translatable="false">subtitle_settings_chromecast_key</string>
<string name="quality_pref_key" translatable="false">quality_pref_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_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="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> <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="extension_install_first">Install the extension first</string>
<string name="hls_playlist">HLS Playlist</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> </resources>

View file

@ -18,6 +18,11 @@
android:title="@string/watch_quality_pref" android:title="@string/watch_quality_pref"
android:icon="@drawable/ic_baseline_hd_24" /> 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 <Preference
android:key="@string/prefer_limit_title_key" android:key="@string/prefer_limit_title_key"
android:title="@string/limit_title" android:title="@string/limit_title"