initial work on multi driver selection

This commit is contained in:
Emmanuel Hansen 2023-07-08 19:36:30 +00:00
parent d6ba9ad8f5
commit 953559c71c
3 changed files with 338 additions and 21 deletions

View File

@ -31,6 +31,29 @@ class TitleUpdateViewModel(val titleId: String) {
}
fun Add() {
var callBack = storageHelper.onFileSelected
storageHelper.onFileSelected = { requestCode, files ->
run {
storageHelper.onFileSelected = callBack
if(requestCode == UpdateRequestCode)
{
var file = files.firstOrNull()
file?.apply {
var path = Helpers.getPath(storageHelper.storage.context, file.uri)
if(!path.isNullOrEmpty()){
data?.apply {
if(!paths.contains(path)) {
paths.add(path)
pathsState?.clear()
pathsState?.addAll(paths)
}
}
}
}
}
}
}
storageHelper.openFilePicker(UpdateRequestCode)
}
@ -86,27 +109,6 @@ class TitleUpdateViewModel(val titleId: String) {
}
storageHelper = MainActivity.StorageHelper!!
storageHelper.onFileSelected = { requestCode, files ->
run {
if(requestCode == UpdateRequestCode)
{
var file = files.firstOrNull()
file?.apply {
var path = Helpers.getPath(storageHelper.storage.context, file.uri)
if(!path.isNullOrEmpty()){
data?.apply {
if(!paths.contains(path)) {
paths.add(path)
pathsState?.clear()
pathsState?.addAll(paths)
}
}
}
}
}
}
}
}
}

View File

@ -0,0 +1,159 @@
package org.ryujinx.android.viewmodels
import androidx.compose.runtime.MutableState
import com.anggrayudi.storage.file.extension
import com.google.gson.Gson
import org.ryujinx.android.Helpers
import org.ryujinx.android.MainActivity
import java.io.File
import java.util.zip.ZipFile
class VulkanDriverViewModel(val activity: MainActivity) {
var selected: String = ""
companion object {
val DriverRequestCode: Int = 1003
const val DriverFolder: String = "drivers"
}
private fun getAppPath() : String {
var appPath =
(MainActivity.AppPath ?: activity.getExternalFilesDir(null)?.absolutePath ?: "");
appPath += "/"
return appPath
}
fun ensureDriverPath() : File {
var driverPath = getAppPath() + DriverFolder
var driverFolder = File(driverPath)
if(!driverFolder.exists())
driverFolder.mkdirs()
return driverFolder
}
fun getAvailableDrivers() : MutableList<DriverMetadata> {
var driverFolder = ensureDriverPath()
var folders = driverFolder.walkTopDown()
var drivers = mutableListOf<DriverMetadata>()
var selectedDriverFile = File(driverFolder.absolutePath + "/selected");
if(selectedDriverFile.exists()){
selected = selectedDriverFile.readText()
if(!File(selected).exists()) {
selected = ""
saveSelected()
}
}
var gson = Gson()
for (folder in folders){
if(folder.isDirectory() && folder.parent == driverFolder.absolutePath){
var meta = File(folder.absolutePath + "/meta.json")
if(meta.exists()){
var metadata = gson.fromJson(meta.readText(), DriverMetadata::class.java)
if(metadata.name.isNotEmpty()) {
var driver = folder.absolutePath + "/${metadata.libraryName}"
metadata.driverPath = driver
if (File(driver).exists())
drivers.add(metadata)
}
}
}
}
return drivers
}
fun saveSelected() {
var driverFolder = ensureDriverPath()
var selectedDriverFile = File(driverFolder.absolutePath + "/selected")
selectedDriverFile.writeText(selected)
}
fun removeSelected(){
if(selected.isNotEmpty()){
var sel = File(selected)
if(sel.exists()) {
var parent = sel.parentFile
parent.deleteRecursively()
}
selected = ""
saveSelected()
}
}
fun add(refresh: MutableState<Boolean>) {
activity.storageHelper?.apply {
var callBack = this.onFileSelected
onFileSelected = { requestCode, files ->
run {
onFileSelected = callBack
if(requestCode == DriverRequestCode)
{
var file = files.firstOrNull()
file?.apply {
var path = Helpers.getPath(storage.context, file.uri)
if(!path.isNullOrEmpty()){
var name = file.name?.removeSuffix("." + file.extension) ?: ""
var driverFolder = ensureDriverPath()
var extractionFolder = File(driverFolder.absolutePath + "/${name}")
extractionFolder.mkdirs()
ZipFile(path)?.use { zip ->
zip.entries().asSequence().forEach { entry ->
zip.getInputStream(entry).use { input ->
val filePath = extractionFolder.absolutePath + File.separator + entry.name
if (!entry.isDirectory) {
var length = input.available()
val bytesIn = ByteArray(length)
input.read(bytesIn)
File(filePath).writeBytes(bytesIn)
} else {
val dir = File(filePath)
dir.mkdir()
}
}
}
}
}
}
refresh.value = true
}
}
}
openFilePicker(DriverRequestCode,
filterMimeTypes = arrayOf("application/zip")
)
}
}
}
data class DriverMetadata(
var schemaVersion : Int = 0,
var name : String = "",
var description : String = "",
var author : String = "",
var packageVersion : String = "",
var vendor : String = "",
var driverVersion : String = "",
var minApi : Int = 0,
var libraryName : String = "",
var driverPath : String = ""
)

View File

@ -13,24 +13,34 @@ import androidx.compose.animation.expandVertically
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkVertically
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.KeyboardArrowUp
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.AlertDialogDefaults
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Slider
import androidx.compose.material3.Surface
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
@ -42,6 +52,7 @@ import androidx.compose.ui.draw.rotate
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import org.ryujinx.android.viewmodels.SettingsViewModel
import org.ryujinx.android.viewmodels.VulkanDriverViewModel
class SettingViews {
companion object {
@ -273,6 +284,151 @@ class SettingViews {
enableTextureRecompression.value = !enableTextureRecompression.value
})
}
/*Row(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp),
horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.CenterVertically
) {
var isDriverSelectorOpen = remember {
mutableStateOf(false)
}
var driverViewModel = VulkanDriverViewModel(settingsViewModel.activity)
var isChanged = remember {
mutableStateOf(false)
}
var refresh = remember {
mutableStateOf(false)
}
var drivers = driverViewModel.getAvailableDrivers()
var selectedDriver = remember {
mutableStateOf(0)
}
if(refresh.value) {
isChanged.value = true
refresh.value = false
}
if(isDriverSelectorOpen.value){
AlertDialog(onDismissRequest = {
isDriverSelectorOpen.value = false
if(isChanged.value){
driverViewModel.saveSelected()
}
}) {
Column {
Surface(
modifier = Modifier
.wrapContentWidth()
.wrapContentHeight(),
shape = MaterialTheme.shapes.large,
tonalElevation = AlertDialogDefaults.TonalElevation
) {
if (!isChanged.value) {
selectedDriver.value =
drivers.indexOfFirst { it.driverPath == driverViewModel.selected } + 1
isChanged.value = true
}
Column {
Column (modifier = Modifier
.fillMaxWidth()
.height(300.dp)) {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
) {
RadioButton(
selected = selectedDriver.value == 0 || driverViewModel.selected.isEmpty(),
onClick = {
selectedDriver.value = 0
isChanged.value = true
driverViewModel.selected = ""
})
Column {
Text(text = "Default",
modifier = Modifier
.fillMaxWidth()
.clickable {
selectedDriver.value = 0
isChanged.value = true
driverViewModel.selected =
""
})
}
}
var driverIndex = 1
for (driver in drivers) {
var ind = driverIndex
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
) {
RadioButton(
selected = selectedDriver.value == ind,
onClick = {
selectedDriver.value = ind
isChanged.value = true
driverViewModel.selected =
driver.driverPath
})
Column {
Text(text = driver.libraryName,
modifier = Modifier
.fillMaxWidth()
.clickable {
selectedDriver.value =
ind
isChanged.value =
true
driverViewModel.selected =
driver.driverPath
})
}
}
driverIndex++
}
}
Row(
horizontalArrangement = Arrangement.End,
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
) {
Button(onClick = {
driverViewModel.removeSelected()
refresh.value = true
}, modifier = Modifier.padding(8.dp)) {
Text(text = "Remove")
}
Button(onClick = {
driverViewModel.add(refresh)
refresh.value = true
}, modifier = Modifier.padding(8.dp)) {
Text(text = "Add")
}
}
}
}
}
}
}
TextButton(
{
isChanged.value = false
isDriverSelectorOpen.value = !isDriverSelectorOpen.value
},
modifier = Modifier.align(Alignment.CenterVertically)
){
Text(text = "Drivers")
}
}
*/
}
}
}