Skip to content

Commit

Permalink
feat: mpv.conf settings
Browse files Browse the repository at this point in the history
  • Loading branch information
abdallahmehiz committed Jun 8, 2024
1 parent 1ec4996 commit 0012ca2
Show file tree
Hide file tree
Showing 8 changed files with 195 additions and 6 deletions.
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ dependencies {
implementation(libs.androidx.constraintlayout)
implementation(libs.androidx.compose.constraintlayout)
implementation(libs.androidx.material3.icons.extended)
implementation(libs.androidx.documentfile)

implementation(libs.aniyomi.mpv.lib)
implementation(libs.aniyomi.ffmpeg.kit)
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/live/mehiz/mpvkt/di/PreferencesModule.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package live.mehiz.mpvkt.di

import live.mehiz.mpvkt.preferences.AdvancedPreferences
import live.mehiz.mpvkt.preferences.AppearancePreferences
import live.mehiz.mpvkt.preferences.AudioPreferences
import live.mehiz.mpvkt.preferences.DecoderPreferences
Expand All @@ -19,4 +20,5 @@ val PreferencesModule = module {
singleOf(::DecoderPreferences)
singleOf(::SubtitlesPreferences)
singleOf(::AudioPreferences)
singleOf(::AdvancedPreferences)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package live.mehiz.mpvkt.preferences

import live.mehiz.mpvkt.preferences.preference.PreferenceStore

class AdvancedPreferences(preferenceStore: PreferenceStore) {
val mpvConfStorageUri = preferenceStore.getString("mpv_conf_storage_location_uri")
val mpvConf = preferenceStore.getString("mpv.conf")
}
31 changes: 26 additions & 5 deletions app/src/main/java/live/mehiz/mpvkt/ui/player/PlayerActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ import android.view.WindowManager
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.WindowCompat
import androidx.documentfile.provider.DocumentFile
import `is`.xyz.mpv.MPVLib
import `is`.xyz.mpv.Utils
import live.mehiz.mpvkt.databinding.PlayerLayoutBinding
import live.mehiz.mpvkt.preferences.AdvancedPreferences
import live.mehiz.mpvkt.preferences.AudioPreferences
import live.mehiz.mpvkt.preferences.DecoderPreferences
import live.mehiz.mpvkt.preferences.PlayerPreferences
Expand All @@ -35,9 +37,10 @@ class PlayerActivity : AppCompatActivity() {
private val decoderPreferences by inject<DecoderPreferences>()
private val audioPreferences by inject<AudioPreferences>()
private val subtitlesPreferences by inject<SubtitlesPreferences>()
private val advancedPreferences by inject<AdvancedPreferences>()

override fun onCreate(savedInstanceState: Bundle?) {
if(playerPreferences.drawOverDisplayCutout.get()) enableEdgeToEdge()
if (playerPreferences.drawOverDisplayCutout.get()) enableEdgeToEdge()
super.onCreate(savedInstanceState)
window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
Expand Down Expand Up @@ -77,24 +80,25 @@ class PlayerActivity : AppCompatActivity() {
private fun setupMPV() {

Utils.copyAssets(this)
copyMPVConfigFiles()

player.initialize(
applicationContext.filesDir.path,
applicationContext.cacheDir.path,
"v",
if(decoderPreferences.gpuNext.get()) "gpu-next" else "gpu"
if (decoderPreferences.gpuNext.get()) "gpu-next" else "gpu",
)

MPVLib.setPropertyString(
"hwdec",
if (decoderPreferences.tryHWDecoding.get()) "auto-copy" else "no"
if (decoderPreferences.tryHWDecoding.get()) "auto-copy" else "no",
)
when(decoderPreferences.debanding.get()) {
when (decoderPreferences.debanding.get()) {
Debanding.None -> {}
Debanding.CPU -> MPVLib.setPropertyString("vf", "gradfun=radius=12")
Debanding.GPU -> MPVLib.setPropertyString("deband", "yes")
}
if(decoderPreferences.useYUV420P.get()) MPVLib.setPropertyString("vf", "format=yuv420p")
if (decoderPreferences.useYUV420P.get()) MPVLib.setPropertyString("vf", "format=yuv420p")

player.addObserver(PlayerObserver(this))
}
Expand All @@ -107,6 +111,23 @@ class PlayerActivity : AppCompatActivity() {
MPVLib.setPropertyString("slang", subtitlesPreferences.preferredLanguages.get())
}

private fun copyMPVConfigFiles() {
val applicationPath = applicationContext.filesDir.path
try {
DocumentFile.fromTreeUri(this, Uri.parse(advancedPreferences.mpvConfStorageUri.get()))!!.listFiles().forEach {
if (it.isDirectory) {
DocumentFile.fromFile(File(applicationPath)).createDirectory(it.name!!)
return@forEach
}
val input = contentResolver.openInputStream(it.uri)
input!!.copyTo(File(applicationPath + "/" + it.name).outputStream())
}
} catch (e: Exception) {
File(applicationContext.filesDir.path + "/mpv.conf").writeText(advancedPreferences.mpvConf.get())
Log.e("PlayerActivity", "Couldn't copy mpv configuration files: ${e.message}")
}
}

private fun parsePathFromIntent(intent: Intent): String? {
val filepath: String? = when (intent.action) {
Intent.ACTION_VIEW -> intent.data?.let { resolveUri(it) }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package live.mehiz.mpvkt.ui.preferences

import android.content.Intent
import android.net.Uri
import android.os.Environment
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.util.fastJoinToString
import androidx.documentfile.provider.DocumentFile
import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import live.mehiz.mpvkt.R
import live.mehiz.mpvkt.preferences.AdvancedPreferences
import live.mehiz.mpvkt.preferences.preference.collectAsState
import me.zhanghai.compose.preference.ProvidePreferenceLocals
import me.zhanghai.compose.preference.TextFieldPreference
import me.zhanghai.compose.preference.preference
import org.koin.compose.koinInject
import kotlin.io.path.deleteIfExists
import kotlin.io.path.outputStream
import kotlin.io.path.readLines

object AdvancedPreferencesScreen : Screen {
@OptIn(ExperimentalMaterial3Api::class)
@Composable
override fun Content() {
val context = LocalContext.current
val navigator = LocalNavigator.currentOrThrow
val preferences = koinInject<AdvancedPreferences>()

val getMPVConfLocation: (String) -> String = {
Environment.getExternalStorageDirectory().canonicalPath + "/" + Uri.decode(it).substringAfterLast(":")
}
Scaffold(
topBar = {
TopAppBar(
title = {
Text(stringResource(R.string.pref_advanced))
},
navigationIcon = {
IconButton(onClick = { navigator.pop() }) {
Icon(Icons.AutoMirrored.Default.ArrowBack, null)
}
},
)
},
) { padding ->
ProvidePreferenceLocals {
val locationPicker = rememberLauncherForActivityResult(
ActivityResultContracts.OpenDocumentTree(),
) { uri ->
if (uri == null) return@rememberLauncherForActivityResult

val flags = Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION
context.contentResolver.takePersistableUriPermission(uri, flags)
preferences.mpvConfStorageUri.set(uri.toString())
}
val mpvConfStorageLocation by preferences.mpvConfStorageUri.collectAsState()
LazyColumn(
Modifier
.fillMaxSize()
.padding(padding),
) {
preference(
"mpv_storage_location",
title = { Text(stringResource(R.string.pref_advanced_mpv_conf_storage_location)) },
summary = {
if (mpvConfStorageLocation.isNotBlank()) {
Text(getMPVConfLocation(mpvConfStorageLocation))
}
},
onClick = {
locationPicker.launch(null)
},
)
item {
var mpvConf by remember { mutableStateOf(preferences.mpvConf.get()) }
LaunchedEffect(true) {
if (mpvConfStorageLocation.isBlank()) return@LaunchedEffect
withContext(Dispatchers.IO) {
val tempFile = kotlin.io.path.createTempFile()
runCatching {
val uri = DocumentFile.fromTreeUri(
context,
Uri.parse(mpvConfStorageLocation),
)!!.findFile("mpv.conf")!!.uri
context.contentResolver.openInputStream(uri)?.copyTo(tempFile.outputStream())
preferences.mpvConf.set(tempFile.readLines().fastJoinToString("\n"))
}
tempFile.deleteIfExists()
}
}
TextFieldPreference(
value = mpvConf,
onValueChange = { mpvConf = it },
title = { Text(stringResource(R.string.pref_advanced_mpv_conf)) },
textToValue = {
preferences.mpvConf.set(it)
if (mpvConfStorageLocation.isNotBlank()) {
val tree = DocumentFile.fromTreeUri(context, Uri.parse(mpvConfStorageLocation))!!
val uri = if (tree.findFile("mpv.conf") == null) {
val conf = tree.createFile("text/plain", "mpv.conf")!!
conf.renameTo("mpv.conf")
conf.uri
} else {
tree.findFile("mpv.conf")!!.uri
}
val out = context.contentResolver.openOutputStream(uri)
out!!.write(it.toByteArray())
out.flush()
out.close()
}
it
},
summary = { Text(mpvConf.lines()[0]) },
)
}
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.ArrowBack
import androidx.compose.material.icons.outlined.Audiotrack
import androidx.compose.material.icons.outlined.Code
import androidx.compose.material.icons.outlined.Memory
import androidx.compose.material.icons.outlined.Palette
import androidx.compose.material.icons.outlined.PlayCircle
Expand All @@ -25,7 +26,6 @@ import cafe.adriel.voyager.navigator.currentOrThrow
import live.mehiz.mpvkt.R
import me.zhanghai.compose.preference.ProvidePreferenceLocals
import me.zhanghai.compose.preference.preference
import me.zhanghai.compose.preference.preferenceTheme

object PreferencesScreen : Screen {
@OptIn(ExperimentalMaterial3Api::class)
Expand Down Expand Up @@ -80,6 +80,12 @@ object PreferencesScreen : Screen {
icon = { Icon(Icons.Outlined.Audiotrack, null) },
onClick = { navigator.push(AudioPreferencesScreen) },
)
preference(
key = "advanced",
title = { Text(text = stringResource(R.string.pref_advanced)) },
icon = { Icon(Icons.Outlined.Code, null) },
onClick = { navigator.push(AdvancedPreferencesScreen) }
)
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@

<string name="pref_audio">Audio</string>

<string name="pref_advanced">Advanced</string>
<string name="pref_advanced_mpv_conf_storage_location">pick mpv configuration storage location</string>
<string name="pref_advanced_mpv_conf">Edit mpv.conf</string>
<string name="pref_advanced_input_conf">Edit input.conf</string>

<string name="player_sheets_add_ext_sub">Add external subtitles</string>
<string name="player_sheets_add_ext_audio">Add external audio tracks</string>
<string name="player_sheets_tracks_off">Off</string>
Expand Down
1 change: 1 addition & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ androidx-recyclerview = { group = "androidx.recyclerview", name = "recyclerview"
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version = "2.1.4" }
androidx-material3-icons-extended = { group = "androidx.compose.material", name = "material-icons-extended", version = "1.6.7" }
androidx-compose-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout-compose", version = "1.0.1" }
androidx-documentfile = { group = "androidx.documentfile", name = "documentfile", version = "1.0.1" }

aniyomi-mpv-lib = { module = "com.github.aniyomiorg:aniyomi-mpv-lib", version = "1.15.n" }
aniyomi-ffmpeg-kit = { module = "com.github.jmir1:ffmpeg-kit", version = "1.15" }
Expand Down

0 comments on commit 0012ca2

Please sign in to comment.