diff options
Diffstat (limited to 'src/android/app/src/main/java/org/yuzu/yuzu_emu/model/DriverViewModel.kt')
-rw-r--r-- | src/android/app/src/main/java/org/yuzu/yuzu_emu/model/DriverViewModel.kt | 175 |
1 files changed, 120 insertions, 55 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/DriverViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/DriverViewModel.kt index 62945ad65..76accf8f3 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/DriverViewModel.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/DriverViewModel.kt @@ -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) } } |