|
|
@@ -7,81 +7,83 @@ import androidx.lifecycle.ViewModel
|
|
|
import androidx.lifecycle.viewModelScope
|
|
|
import kotlinx.coroutines.Dispatchers
|
|
|
import kotlinx.coroutines.flow.MutableStateFlow
|
|
|
+import kotlinx.coroutines.flow.SharingStarted
|
|
|
import kotlinx.coroutines.flow.StateFlow
|
|
|
+import kotlinx.coroutines.flow.combine
|
|
|
+import kotlinx.coroutines.flow.stateIn
|
|
|
import kotlinx.coroutines.launch
|
|
|
import kotlinx.coroutines.withContext
|
|
|
import org.yuzu.yuzu_emu.R
|
|
|
import org.yuzu.yuzu_emu.YuzuApplication
|
|
|
+import org.yuzu.yuzu_emu.features.settings.model.StringSetting
|
|
|
+import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
|
|
|
import org.yuzu.yuzu_emu.utils.FileUtil
|
|
|
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
|
|
|
import org.yuzu.yuzu_emu.utils.GpuDriverMetadata
|
|
|
+import org.yuzu.yuzu_emu.utils.NativeConfig
|
|
|
import java.io.BufferedOutputStream
|
|
|
import java.io.File
|
|
|
|
|
|
class DriverViewModel : ViewModel() {
|
|
|
private val _areDriversLoading = MutableStateFlow(false)
|
|
|
- val areDriversLoading: StateFlow<Boolean> get() = _areDriversLoading
|
|
|
-
|
|
|
private val _isDriverReady = MutableStateFlow(true)
|
|
|
- val isDriverReady: StateFlow<Boolean> get() = _isDriverReady
|
|
|
-
|
|
|
private val _isDeletingDrivers = MutableStateFlow(false)
|
|
|
- val isDeletingDrivers: StateFlow<Boolean> get() = _isDeletingDrivers
|
|
|
|
|
|
- private val _driverList = MutableStateFlow(mutableListOf<Pair<String, GpuDriverMetadata>>())
|
|
|
+ val isInteractionAllowed: StateFlow<Boolean> =
|
|
|
+ combine(
|
|
|
+ _areDriversLoading,
|
|
|
+ _isDriverReady,
|
|
|
+ _isDeletingDrivers
|
|
|
+ ) { loading, ready, deleting ->
|
|
|
+ !loading && ready && !deleting
|
|
|
+ }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), initialValue = false)
|
|
|
+
|
|
|
+ private val _driverList = MutableStateFlow(GpuDriverHelper.getDrivers())
|
|
|
val driverList: StateFlow<MutableList<Pair<String, GpuDriverMetadata>>> get() = _driverList
|
|
|
|
|
|
var previouslySelectedDriver = 0
|
|
|
var selectedDriver = -1
|
|
|
|
|
|
- private val _selectedDriverMetadata =
|
|
|
- MutableStateFlow(
|
|
|
- GpuDriverHelper.customDriverData.name
|
|
|
- ?: YuzuApplication.appContext.getString(R.string.system_gpu_driver)
|
|
|
- )
|
|
|
- val selectedDriverMetadata: StateFlow<String> get() = _selectedDriverMetadata
|
|
|
+ // Used for showing which driver is currently installed within the driver manager card
|
|
|
+ private val _selectedDriverTitle = MutableStateFlow("")
|
|
|
+ val selectedDriverTitle: StateFlow<String> get() = _selectedDriverTitle
|
|
|
|
|
|
private val _newDriverInstalled = MutableStateFlow(false)
|
|
|
val newDriverInstalled: StateFlow<Boolean> get() = _newDriverInstalled
|
|
|
|
|
|
val driversToDelete = mutableListOf<String>()
|
|
|
|
|
|
- val isInteractionAllowed
|
|
|
- get() = !areDriversLoading.value && isDriverReady.value && !isDeletingDrivers.value
|
|
|
-
|
|
|
init {
|
|
|
- _areDriversLoading.value = true
|
|
|
- viewModelScope.launch {
|
|
|
- withContext(Dispatchers.IO) {
|
|
|
- val drivers = GpuDriverHelper.getDrivers()
|
|
|
- val currentDriverMetadata = GpuDriverHelper.customDriverData
|
|
|
- for (i in drivers.indices) {
|
|
|
- if (drivers[i].second == currentDriverMetadata) {
|
|
|
- setSelectedDriverIndex(i)
|
|
|
- break
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // If a user had installed a driver before the manager was implemented, this zips
|
|
|
- // the installed driver to UserData/gpu_drivers/CustomDriver.zip so that it can
|
|
|
- // be indexed and exported as expected.
|
|
|
- if (selectedDriver == -1) {
|
|
|
- val driverToSave =
|
|
|
- File(GpuDriverHelper.driverStoragePath, "CustomDriver.zip")
|
|
|
- driverToSave.createNewFile()
|
|
|
- FileUtil.zipFromInternalStorage(
|
|
|
- File(GpuDriverHelper.driverInstallationPath!!),
|
|
|
- GpuDriverHelper.driverInstallationPath!!,
|
|
|
- BufferedOutputStream(driverToSave.outputStream())
|
|
|
- )
|
|
|
- drivers.add(Pair(driverToSave.path, currentDriverMetadata))
|
|
|
- setSelectedDriverIndex(drivers.size - 1)
|
|
|
- }
|
|
|
+ val currentDriverMetadata = GpuDriverHelper.installedCustomDriverData
|
|
|
+ findSelectedDriver(currentDriverMetadata)
|
|
|
+
|
|
|
+ // If a user had installed a driver before the manager was implemented, this zips
|
|
|
+ // the installed driver to UserData/gpu_drivers/CustomDriver.zip so that it can
|
|
|
+ // be indexed and exported as expected.
|
|
|
+ if (selectedDriver == -1) {
|
|
|
+ val driverToSave =
|
|
|
+ File(GpuDriverHelper.driverStoragePath, "CustomDriver.zip")
|
|
|
+ driverToSave.createNewFile()
|
|
|
+ FileUtil.zipFromInternalStorage(
|
|
|
+ File(GpuDriverHelper.driverInstallationPath!!),
|
|
|
+ GpuDriverHelper.driverInstallationPath!!,
|
|
|
+ BufferedOutputStream(driverToSave.outputStream())
|
|
|
+ )
|
|
|
+ _driverList.value.add(Pair(driverToSave.path, currentDriverMetadata))
|
|
|
+ setSelectedDriverIndex(_driverList.value.size - 1)
|
|
|
+ }
|
|
|
|
|
|
- _driverList.value = drivers
|
|
|
- _areDriversLoading.value = false
|
|
|
- }
|
|
|
+ // If a user had installed a driver before the config was reworked to be multiplatform,
|
|
|
+ // we have save the path of the previously selected driver to the new setting.
|
|
|
+ if (StringSetting.DRIVER_PATH.getString(true).isEmpty() && selectedDriver > 0 &&
|
|
|
+ StringSetting.DRIVER_PATH.global
|
|
|
+ ) {
|
|
|
+ StringSetting.DRIVER_PATH.setString(_driverList.value[selectedDriver].first)
|
|
|
+ NativeConfig.saveGlobalConfig()
|
|
|
+ } else {
|
|
|
+ findSelectedDriver(GpuDriverHelper.customDriverSettingData)
|
|
|
}
|
|
|
+ updateDriverNameForGame(null)
|
|
|
}
|
|
|
|
|
|
fun setSelectedDriverIndex(value: Int) {
|
|
|
@@ -98,9 +100,9 @@ class DriverViewModel : ViewModel() {
|
|
|
fun addDriver(driverData: Pair<String, GpuDriverMetadata>) {
|
|
|
val driverIndex = _driverList.value.indexOfFirst { it == driverData }
|
|
|
if (driverIndex == -1) {
|
|
|
- setSelectedDriverIndex(_driverList.value.size)
|
|
|
_driverList.value.add(driverData)
|
|
|
- _selectedDriverMetadata.value = driverData.second.name
|
|
|
+ setSelectedDriverIndex(_driverList.value.size - 1)
|
|
|
+ _selectedDriverTitle.value = driverData.second.name
|
|
|
?: YuzuApplication.appContext.getString(R.string.system_gpu_driver)
|
|
|
} else {
|
|
|
setSelectedDriverIndex(driverIndex)
|
|
|
@@ -111,8 +113,31 @@ class DriverViewModel : ViewModel() {
|
|
|
_driverList.value.remove(driverData)
|
|
|
}
|
|
|
|
|
|
- fun onCloseDriverManager() {
|
|
|
+ fun onOpenDriverManager(game: Game?) {
|
|
|
+ if (game != null) {
|
|
|
+ SettingsFile.loadCustomConfig(game)
|
|
|
+ }
|
|
|
+
|
|
|
+ val driverPath = StringSetting.DRIVER_PATH.getString()
|
|
|
+ if (driverPath.isEmpty()) {
|
|
|
+ setSelectedDriverIndex(0)
|
|
|
+ } else {
|
|
|
+ findSelectedDriver(GpuDriverHelper.getMetadataFromZip(File(driverPath)))
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ fun onCloseDriverManager(game: Game?) {
|
|
|
_isDeletingDrivers.value = true
|
|
|
+ StringSetting.DRIVER_PATH.setString(driverList.value[selectedDriver].first)
|
|
|
+ updateDriverNameForGame(game)
|
|
|
+ if (game == null) {
|
|
|
+ NativeConfig.saveGlobalConfig()
|
|
|
+ } else {
|
|
|
+ NativeConfig.savePerGameConfig()
|
|
|
+ NativeConfig.unloadPerGameConfig()
|
|
|
+ NativeConfig.reloadGlobalConfig()
|
|
|
+ }
|
|
|
+
|
|
|
viewModelScope.launch {
|
|
|
withContext(Dispatchers.IO) {
|
|
|
driversToDelete.forEach {
|
|
|
@@ -125,23 +150,29 @@ class DriverViewModel : ViewModel() {
|
|
|
_isDeletingDrivers.value = false
|
|
|
}
|
|
|
}
|
|
|
+ }
|
|
|
+
|
|
|
+ // It is the Emulation Fragment's responsibility to load per-game settings so that this function
|
|
|
+ // knows what driver to load.
|
|
|
+ fun onLaunchGame() {
|
|
|
+ _isDriverReady.value = false
|
|
|
|
|
|
- if (GpuDriverHelper.customDriverData == driverList.value[selectedDriver].second) {
|
|
|
+ val selectedDriverFile = File(StringSetting.DRIVER_PATH.getString())
|
|
|
+ val selectedDriverMetadata = GpuDriverHelper.customDriverSettingData
|
|
|
+ if (GpuDriverHelper.installedCustomDriverData == selectedDriverMetadata) {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- _isDriverReady.value = false
|
|
|
viewModelScope.launch {
|
|
|
withContext(Dispatchers.IO) {
|
|
|
- if (selectedDriver == 0) {
|
|
|
+ if (selectedDriverMetadata.name == null) {
|
|
|
GpuDriverHelper.installDefaultDriver()
|
|
|
setDriverReady()
|
|
|
return@withContext
|
|
|
}
|
|
|
|
|
|
- val driverToInstall = File(driverList.value[selectedDriver].first)
|
|
|
- if (driverToInstall.exists()) {
|
|
|
- GpuDriverHelper.installCustomDriver(driverToInstall)
|
|
|
+ if (selectedDriverFile.exists()) {
|
|
|
+ GpuDriverHelper.installCustomDriver(selectedDriverFile)
|
|
|
} else {
|
|
|
GpuDriverHelper.installDefaultDriver()
|
|
|
}
|
|
|
@@ -150,9 +181,43 @@ class DriverViewModel : ViewModel() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private fun findSelectedDriver(currentDriverMetadata: GpuDriverMetadata) {
|
|
|
+ if (driverList.value.size == 1) {
|
|
|
+ setSelectedDriverIndex(0)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ driverList.value.forEachIndexed { i: Int, driver: Pair<String, GpuDriverMetadata> ->
|
|
|
+ if (driver.second == currentDriverMetadata) {
|
|
|
+ setSelectedDriverIndex(i)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ fun updateDriverNameForGame(game: Game?) {
|
|
|
+ if (!GpuDriverHelper.supportsCustomDriverLoading()) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if (game == null || NativeConfig.isPerGameConfigLoaded()) {
|
|
|
+ updateName()
|
|
|
+ } else {
|
|
|
+ SettingsFile.loadCustomConfig(game)
|
|
|
+ updateName()
|
|
|
+ NativeConfig.unloadPerGameConfig()
|
|
|
+ NativeConfig.reloadGlobalConfig()
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun updateName() {
|
|
|
+ _selectedDriverTitle.value = GpuDriverHelper.customDriverSettingData.name
|
|
|
+ ?: YuzuApplication.appContext.getString(R.string.system_gpu_driver)
|
|
|
+ }
|
|
|
+
|
|
|
private fun setDriverReady() {
|
|
|
_isDriverReady.value = true
|
|
|
- _selectedDriverMetadata.value = GpuDriverHelper.customDriverData.name
|
|
|
+ _selectedDriverTitle.value = GpuDriverHelper.customDriverSettingData.name
|
|
|
?: YuzuApplication.appContext.getString(R.string.system_gpu_driver)
|
|
|
}
|
|
|
}
|