Split PreferenceSettings into AppSettings and EmulationSettings

`PreferenceSettings` was removed in favor of:
* `AppSettings`: stores general purpose settings mostly used for UI configuration and state
* `EmulationSettings`: stores emulation-related settings, most of these are passed to native emulation code
This commit is contained in:
lynxnb 2023-02-22 20:31:07 +01:00 committed by Niccolò Betto
parent 854ea1a42d
commit cd426d9f18
13 changed files with 180 additions and 155 deletions

View File

@ -29,10 +29,11 @@ import emu.skyline.applet.swkbd.SoftwareKeyboardDialog
import emu.skyline.databinding.EmuActivityBinding import emu.skyline.databinding.EmuActivityBinding
import emu.skyline.input.* import emu.skyline.input.*
import emu.skyline.loader.getRomFormat import emu.skyline.loader.getRomFormat
import emu.skyline.settings.AppSettings
import emu.skyline.settings.EmulationSettings
import emu.skyline.settings.NativeSettings
import emu.skyline.utils.ByteBufferSerializable import emu.skyline.utils.ByteBufferSerializable
import emu.skyline.utils.GpuDriverHelper import emu.skyline.utils.GpuDriverHelper
import emu.skyline.settings.NativeSettings
import emu.skyline.settings.PreferenceSettings
import java.nio.ByteBuffer import java.nio.ByteBuffer
import java.nio.ByteOrder import java.nio.ByteOrder
import java.util.concurrent.FutureTask import java.util.concurrent.FutureTask
@ -75,7 +76,9 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
var desiredRefreshRate = 60f var desiredRefreshRate = 60f
@Inject @Inject
lateinit var preferenceSettings : PreferenceSettings lateinit var appSettings : AppSettings
lateinit var emulationSettings : EmulationSettings
@Inject @Inject
lateinit var inputManager : InputManager lateinit var inputManager : InputManager
@ -196,7 +199,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
GpuDriverHelper.ensureFileRedirectDir(this) GpuDriverHelper.ensureFileRedirectDir(this)
emulationThread = Thread { emulationThread = Thread {
executeApplication(rom.toString(), romType, romFd.detachFd(), NativeSettings(this, preferenceSettings), applicationContext.getPublicFilesDir().canonicalPath + "/", applicationContext.filesDir.canonicalPath + "/", applicationInfo.nativeLibraryDir + "/", assets) executeApplication(rom.toString(), romType, romFd.detachFd(), NativeSettings(this, emulationSettings), applicationContext.getPublicFilesDir().canonicalPath + "/", applicationContext.filesDir.canonicalPath + "/", applicationInfo.nativeLibraryDir + "/", assets)
returnFromEmulation() returnFromEmulation()
} }
@ -206,9 +209,11 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
@SuppressLint("SetTextI18n", "ClickableViewAccessibility") @SuppressLint("SetTextI18n", "ClickableViewAccessibility")
override fun onCreate(savedInstanceState : Bundle?) { override fun onCreate(savedInstanceState : Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
requestedOrientation = preferenceSettings.orientation emulationSettings = EmulationSettings.global
requestedOrientation = emulationSettings.orientation
window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
inputHandler = InputHandler(inputManager, preferenceSettings) inputHandler = InputHandler(inputManager, emulationSettings)
setContentView(binding.root) setContentView(binding.root)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
@ -222,7 +227,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
} }
} }
if (preferenceSettings.respectDisplayCutout) { if (emulationSettings.respectDisplayCutout) {
binding.perfStats.setOnApplyWindowInsetsListener(insetsOrMarginHandler) binding.perfStats.setOnApplyWindowInsetsListener(insetsOrMarginHandler)
binding.onScreenControllerToggle.setOnApplyWindowInsetsListener(insetsOrMarginHandler) binding.onScreenControllerToggle.setOnApplyWindowInsetsListener(insetsOrMarginHandler)
} }
@ -230,15 +235,15 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
binding.gameView.holder.addCallback(this) binding.gameView.holder.addCallback(this)
binding.gameView.setAspectRatio( binding.gameView.setAspectRatio(
when (preferenceSettings.aspectRatio) { when (emulationSettings.aspectRatio) {
0 -> Rational(16, 9) 0 -> Rational(16, 9)
1 -> Rational(21, 9) 1 -> Rational(21, 9)
else -> null else -> null
} }
) )
if (preferenceSettings.perfStats) { if (appSettings.perfStats) {
if (preferenceSettings.disableFrameThrottling) if (emulationSettings.disableFrameThrottling)
binding.perfStats.setTextColor(getColor(R.color.colorPerfStatsSecondary)) binding.perfStats.setTextColor(getColor(R.color.colorPerfStatsSecondary))
binding.perfStats.apply { binding.perfStats.apply {
@ -252,7 +257,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
} }
} }
force60HzRefreshRate(!preferenceSettings.maxRefreshRate) force60HzRefreshRate(!emulationSettings.maxRefreshRate)
getSystemService<DisplayManager>()?.registerDisplayListener(this, null) getSystemService<DisplayManager>()?.registerDisplayListener(this, null)
binding.gameView.setOnTouchListener(this) binding.gameView.setOnTouchListener(this)
@ -260,11 +265,11 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
// Hide on screen controls when first controller is not set // Hide on screen controls when first controller is not set
binding.onScreenControllerView.apply { binding.onScreenControllerView.apply {
controllerType = inputHandler.getFirstControllerType() controllerType = inputHandler.getFirstControllerType()
isGone = controllerType == ControllerType.None || !preferenceSettings.onScreenControl isGone = controllerType == ControllerType.None || !appSettings.onScreenControl
setOnButtonStateChangedListener(::onButtonStateChanged) setOnButtonStateChangedListener(::onButtonStateChanged)
setOnStickStateChangedListener(::onStickStateChanged) setOnStickStateChangedListener(::onStickStateChanged)
hapticFeedback = preferenceSettings.onScreenControl && preferenceSettings.onScreenControlFeedback hapticFeedback = appSettings.onScreenControl && appSettings.onScreenControlFeedback
recenterSticks = preferenceSettings.onScreenControlRecenterSticks recenterSticks = appSettings.onScreenControlRecenterSticks
} }
binding.onScreenControllerToggle.apply { binding.onScreenControllerToggle.apply {
@ -278,7 +283,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
override fun onPause() { override fun onPause() {
super.onPause() super.onPause()
if (preferenceSettings.forceMaxGpuClocks) if (emulationSettings.forceMaxGpuClocks)
GpuDriverHelper.forceMaxGpuClocks(false) GpuDriverHelper.forceMaxGpuClocks(false)
changeAudioStatus(false) changeAudioStatus(false)
@ -328,7 +333,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
// Stop forcing 60Hz on exit to allow the skyline UI to run at high refresh rates // Stop forcing 60Hz on exit to allow the skyline UI to run at high refresh rates
getSystemService<DisplayManager>()?.unregisterDisplayListener(this) getSystemService<DisplayManager>()?.unregisterDisplayListener(this)
force60HzRefreshRate(false) force60HzRefreshRate(false)
if (preferenceSettings.forceMaxGpuClocks) if (emulationSettings.forceMaxGpuClocks)
GpuDriverHelper.forceMaxGpuClocks(false) GpuDriverHelper.forceMaxGpuClocks(false)
stopEmulation(false) stopEmulation(false)
@ -341,7 +346,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
// Note: We need FRAME_RATE_COMPATIBILITY_FIXED_SOURCE as there will be a degradation of user experience with FRAME_RATE_COMPATIBILITY_DEFAULT due to game speed alterations when the frame rate doesn't match the display refresh rate // Note: We need FRAME_RATE_COMPATIBILITY_FIXED_SOURCE as there will be a degradation of user experience with FRAME_RATE_COMPATIBILITY_DEFAULT due to game speed alterations when the frame rate doesn't match the display refresh rate
holder.surface.setFrameRate(desiredRefreshRate, if (preferenceSettings.maxRefreshRate) Surface.FRAME_RATE_COMPATIBILITY_DEFAULT else Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE) holder.surface.setFrameRate(desiredRefreshRate, if (emulationSettings.maxRefreshRate) Surface.FRAME_RATE_COMPATIBILITY_DEFAULT else Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE)
while (emulationThread!!.isAlive) while (emulationThread!!.isAlive)
if (setSurface(holder.surface)) if (setSurface(holder.surface))
@ -355,7 +360,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
Log.d(Tag, "surfaceChanged Holder: $holder, Format: $format, Width: $width, Height: $height") Log.d(Tag, "surfaceChanged Holder: $holder, Format: $format, Width: $width, Height: $height")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
holder.surface.setFrameRate(desiredRefreshRate, if (preferenceSettings.maxRefreshRate) Surface.FRAME_RATE_COMPATIBILITY_DEFAULT else Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE) holder.surface.setFrameRate(desiredRefreshRate, if (emulationSettings.maxRefreshRate) Surface.FRAME_RATE_COMPATIBILITY_DEFAULT else Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE)
} }
override fun surfaceDestroyed(holder : SurfaceHolder) { override fun surfaceDestroyed(holder : SurfaceHolder) {
@ -503,7 +508,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
val display = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) display!! else windowManager.defaultDisplay val display = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) display!! else windowManager.defaultDisplay
if (display.displayId == displayId) if (display.displayId == displayId)
force60HzRefreshRate(!preferenceSettings.maxRefreshRate) force60HzRefreshRate(!emulationSettings.maxRefreshRate)
} }
override fun onDisplayAdded(displayId : Int) {} override fun onDisplayAdded(displayId : Int) {}

View File

@ -23,6 +23,7 @@ import androidx.core.view.WindowCompat
import androidx.core.view.isInvisible import androidx.core.view.isInvisible
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.documentfile.provider.DocumentFile import androidx.documentfile.provider.DocumentFile
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
@ -36,7 +37,8 @@ import emu.skyline.loader.AppEntry
import emu.skyline.loader.LoaderResult import emu.skyline.loader.LoaderResult
import emu.skyline.loader.RomFormat import emu.skyline.loader.RomFormat
import emu.skyline.provider.DocumentsProvider import emu.skyline.provider.DocumentsProvider
import emu.skyline.settings.PreferenceSettings import emu.skyline.settings.AppSettings
import emu.skyline.settings.EmulationSettings
import emu.skyline.settings.SettingsActivity import emu.skyline.settings.SettingsActivity
import emu.skyline.utils.GpuDriverHelper import emu.skyline.utils.GpuDriverHelper
import emu.skyline.utils.WindowInsetsHelper import emu.skyline.utils.WindowInsetsHelper
@ -52,11 +54,11 @@ class MainActivity : AppCompatActivity() {
private val binding by lazy { MainActivityBinding.inflate(layoutInflater) } private val binding by lazy { MainActivityBinding.inflate(layoutInflater) }
@Inject @Inject
lateinit var preferenceSettings : PreferenceSettings lateinit var appSettings : AppSettings
private val adapter = GenericAdapter() private val adapter = GenericAdapter()
private val layoutType get() = LayoutType.values()[preferenceSettings.layoutType] private val layoutType get() = LayoutType.values()[appSettings.layoutType]
private val missingIcon by lazy { ContextCompat.getDrawable(this, R.drawable.default_icon)!!.toBitmap(256, 256) } private val missingIcon by lazy { ContextCompat.getDrawable(this, R.drawable.default_icon)!!.toBitmap(256, 256) }
@ -84,14 +86,14 @@ class MainActivity : AppCompatActivity() {
private val documentPicker = registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { private val documentPicker = registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) {
it?.let { uri -> it?.let { uri ->
contentResolver.takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION) contentResolver.takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
preferenceSettings.searchLocation = uri.toString() appSettings.searchLocation = uri.toString()
loadRoms(false) loadRoms(false)
} }
} }
private val settingsCallback = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { private val settingsCallback = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if (preferenceSettings.refreshRequired) loadRoms(false) if (appSettings.refreshRequired) loadRoms(false)
} }
private fun AppItem.toViewItem() = AppViewItem(layoutType, this, missingIcon, ::selectStartGame, ::selectShowGameDialog) private fun AppItem.toViewItem() = AppViewItem(layoutType, this, missingIcon, ::selectStartGame, ::selectShowGameDialog)
@ -99,7 +101,7 @@ class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState : Bundle?) { override fun onCreate(savedInstanceState : Bundle?) {
// Need to create new instance of settings, dependency injection happens // Need to create new instance of settings, dependency injection happens
AppCompatDelegate.setDefaultNightMode( AppCompatDelegate.setDefaultNightMode(
when ((PreferenceSettings(this).appTheme)) { when ((AppSettings(this).appTheme)) {
0 -> AppCompatDelegate.MODE_NIGHT_NO 0 -> AppCompatDelegate.MODE_NIGHT_NO
1 -> AppCompatDelegate.MODE_NIGHT_YES 1 -> AppCompatDelegate.MODE_NIGHT_YES
2 -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM 2 -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
@ -112,11 +114,12 @@ class MainActivity : AppCompatActivity() {
WindowCompat.setDecorFitsSystemWindows(window, false) WindowCompat.setDecorFitsSystemWindows(window, false)
WindowInsetsHelper.applyToActivity(binding.root, binding.appList) WindowInsetsHelper.applyToActivity(binding.root, binding.appList)
PreferenceSettings.setDefaultValues(this) PreferenceManager.setDefaultValues(this, R.xml.app_preferences, false)
PreferenceManager.setDefaultValues(this, R.xml.emulation_preferences, false)
adapter.apply { adapter.apply {
setHeaderItems(listOf(HeaderRomFilterItem(formatOrder, if (preferenceSettings.romFormatFilter == 0) null else formatOrder[preferenceSettings.romFormatFilter - 1]) { romFormat -> setHeaderItems(listOf(HeaderRomFilterItem(formatOrder, if (appSettings.romFormatFilter == 0) null else formatOrder[appSettings.romFormatFilter - 1]) { romFormat ->
preferenceSettings.romFormatFilter = romFormat?.let { formatOrder.indexOf(romFormat) + 1 } ?: 0 appSettings.romFormatFilter = romFormat?.let { formatOrder.indexOf(romFormat) + 1 } ?: 0
formatFilter = romFormat formatFilter = romFormat
populateAdapter() populateAdapter()
})) }))
@ -136,7 +139,7 @@ class MainActivity : AppCompatActivity() {
} }
viewModel.stateData.observe(this, ::handleState) viewModel.stateData.observe(this, ::handleState)
loadRoms(!preferenceSettings.refreshRequired) loadRoms(!appSettings.refreshRequired)
binding.searchBar.apply { binding.searchBar.apply {
binding.logIcon.setOnClickListener { binding.logIcon.setOnClickListener {
@ -219,11 +222,11 @@ class MainActivity : AppCompatActivity() {
binding.appList.layoutManager = CustomLayoutManager(gridSpan) binding.appList.layoutManager = CustomLayoutManager(gridSpan)
setAppListDecoration() setAppListDecoration()
if (preferenceSettings.searchLocation.isEmpty()) documentPicker.launch(null) if (appSettings.searchLocation.isEmpty()) documentPicker.launch(null)
} }
private fun getDataItems() = mutableListOf<DataItem>().apply { private fun getDataItems() = mutableListOf<DataItem>().apply {
if (preferenceSettings.groupByFormat) { if (appSettings.groupByFormat) {
appEntries?.let { entries -> appEntries?.let { entries ->
val formats = formatFilter?.let { listOf(it) } ?: formatOrder val formats = formatFilter?.let { listOf(it) } ?: formatOrder
for (format in formats) { for (format in formats) {
@ -254,7 +257,7 @@ class MainActivity : AppCompatActivity() {
private fun sortGameList(gameList : List<AppEntry>) : List<AppEntry> { private fun sortGameList(gameList : List<AppEntry>) : List<AppEntry> {
val sortedApps : MutableList<AppEntry> = mutableListOf<AppEntry>() val sortedApps : MutableList<AppEntry> = mutableListOf<AppEntry>()
gameList.forEach { entry -> sortedApps.add(entry) } gameList.forEach { entry -> sortedApps.add(entry) }
when (preferenceSettings.sortAppsBy) { when (appSettings.sortAppsBy) {
SortingOrder.AlphabeticalAsc.ordinal -> sortedApps.sortBy { it.name } SortingOrder.AlphabeticalAsc.ordinal -> sortedApps.sortBy { it.name }
SortingOrder.AlphabeticalDesc.ordinal -> sortedApps.sortByDescending { it.name } SortingOrder.AlphabeticalDesc.ordinal -> sortedApps.sortByDescending { it.name }
} }
@ -280,7 +283,7 @@ class MainActivity : AppCompatActivity() {
private fun selectStartGame(appItem : AppItem) { private fun selectStartGame(appItem : AppItem) {
if (binding.swipeRefreshLayout.isRefreshing) return if (binding.swipeRefreshLayout.isRefreshing) return
if (preferenceSettings.selectAction) { if (appSettings.selectAction) {
AppDialog.newInstance(appItem).show(supportFragmentManager, "game") AppDialog.newInstance(appItem).show(supportFragmentManager, "game")
} else if (appItem.loaderResult == LoaderResult.Success) { } else if (appItem.loaderResult == LoaderResult.Success) {
startActivity(Intent(this, EmulationActivity::class.java).apply { data = appItem.uri; putExtra(EmulationActivity.ReturnToMainTag, true); addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) }) startActivity(Intent(this, EmulationActivity::class.java).apply { data = appItem.uri; putExtra(EmulationActivity.ReturnToMainTag, true); addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) })
@ -294,8 +297,8 @@ class MainActivity : AppCompatActivity() {
} }
private fun loadRoms(loadFromFile : Boolean) { private fun loadRoms(loadFromFile : Boolean) {
viewModel.loadRoms(this, loadFromFile, Uri.parse(preferenceSettings.searchLocation), preferenceSettings.systemLanguage) viewModel.loadRoms(this, loadFromFile, Uri.parse(appSettings.searchLocation), EmulationSettings.global.systemLanguage)
preferenceSettings.refreshRequired = false appSettings.refreshRequired = false
} }
private fun populateAdapter() { private fun populateAdapter() {
@ -330,7 +333,7 @@ class MainActivity : AppCompatActivity() {
super.onResume() super.onResume()
// Try to return to normal GPU clocks upon resuming back to main activity, to avoid GPU being stuck at max clocks after a crash // Try to return to normal GPU clocks upon resuming back to main activity, to avoid GPU being stuck at max clocks after a crash
if (preferenceSettings.forceMaxGpuClocks) if (EmulationSettings.global.forceMaxGpuClocks)
GpuDriverHelper.forceMaxGpuClocks(false) GpuDriverHelper.forceMaxGpuClocks(false)
var layoutTypeChanged = false var layoutTypeChanged = false

View File

@ -27,6 +27,8 @@ class SkylineApplication : Application() {
companion object { companion object {
lateinit var instance : SkylineApplication lateinit var instance : SkylineApplication
private set private set
val context : Context get() = instance.applicationContext
} }
override fun onCreate() { override fun onCreate() {

View File

@ -11,7 +11,7 @@ import dagger.hilt.InstallIn
import dagger.hilt.android.EntryPointAccessors import dagger.hilt.android.EntryPointAccessors
import dagger.hilt.components.SingletonComponent import dagger.hilt.components.SingletonComponent
import emu.skyline.input.InputManager import emu.skyline.input.InputManager
import emu.skyline.settings.PreferenceSettings import emu.skyline.settings.AppSettings
@EntryPoint @EntryPoint
@InstallIn(SingletonComponent::class) @InstallIn(SingletonComponent::class)
@ -24,7 +24,7 @@ fun Context.getInputManager() = EntryPointAccessors.fromApplication(this, InputM
@EntryPoint @EntryPoint
@InstallIn(SingletonComponent::class) @InstallIn(SingletonComponent::class)
interface SettingsProviderEntryPoint { interface SettingsProviderEntryPoint {
fun preferenceSettings() : PreferenceSettings fun appSettings() : AppSettings
} }
fun Context.getSettings() = EntryPointAccessors.fromApplication(this, SettingsProviderEntryPoint::class.java).preferenceSettings() fun Context.getSettings() = EntryPointAccessors.fromApplication(this, SettingsProviderEntryPoint::class.java).appSettings()

View File

@ -29,7 +29,7 @@ import emu.skyline.input.dialog.ButtonDialog
import emu.skyline.input.dialog.RumbleDialog import emu.skyline.input.dialog.RumbleDialog
import emu.skyline.input.dialog.StickDialog import emu.skyline.input.dialog.StickDialog
import emu.skyline.input.onscreen.OnScreenEditActivity import emu.skyline.input.onscreen.OnScreenEditActivity
import emu.skyline.settings.PreferenceSettings import emu.skyline.settings.AppSettings
import emu.skyline.utils.WindowInsetsHelper import emu.skyline.utils.WindowInsetsHelper
import javax.inject.Inject import javax.inject.Inject
@ -62,7 +62,7 @@ class ControllerActivity : AppCompatActivity() {
val buttonItems = mutableListOf<ControllerButtonViewItem>() val buttonItems = mutableListOf<ControllerButtonViewItem>()
@Inject @Inject
lateinit var preferenceSettings : PreferenceSettings lateinit var appSettings : AppSettings
@Inject @Inject
lateinit var inputManager : InputManager lateinit var inputManager : InputManager
@ -85,19 +85,19 @@ class ControllerActivity : AppCompatActivity() {
items.add(ControllerHeaderItem(getString(R.string.osc))) items.add(ControllerHeaderItem(getString(R.string.osc)))
val oscSummary = { checked : Boolean -> getString(if (checked) R.string.osc_shown else R.string.osc_not_shown) } val oscSummary = { checked : Boolean -> getString(if (checked) R.string.osc_shown else R.string.osc_not_shown) }
items.add(ControllerCheckBoxViewItem(getString(R.string.osc_enable), oscSummary.invoke(preferenceSettings.onScreenControl), preferenceSettings.onScreenControl) { item, position -> items.add(ControllerCheckBoxViewItem(getString(R.string.osc_enable), oscSummary.invoke(appSettings.onScreenControl), appSettings.onScreenControl) { item, position ->
item.summary = oscSummary.invoke(item.checked) item.summary = oscSummary.invoke(item.checked)
preferenceSettings.onScreenControl = item.checked appSettings.onScreenControl = item.checked
adapter.notifyItemChanged(position) adapter.notifyItemChanged(position)
}) })
items.add(ControllerCheckBoxViewItem(getString(R.string.osc_feedback), getString(R.string.osc_feedback_description), preferenceSettings.onScreenControlFeedback) { item, position -> items.add(ControllerCheckBoxViewItem(getString(R.string.osc_feedback), getString(R.string.osc_feedback_description), appSettings.onScreenControlFeedback) { item, position ->
preferenceSettings.onScreenControlFeedback = item.checked appSettings.onScreenControlFeedback = item.checked
adapter.notifyItemChanged(position) adapter.notifyItemChanged(position)
}) })
items.add(ControllerCheckBoxViewItem(getString(R.string.osc_recenter_sticks), "", preferenceSettings.onScreenControlRecenterSticks) { item, position -> items.add(ControllerCheckBoxViewItem(getString(R.string.osc_recenter_sticks), "", appSettings.onScreenControlRecenterSticks) { item, position ->
preferenceSettings.onScreenControlRecenterSticks = item.checked appSettings.onScreenControlRecenterSticks = item.checked
adapter.notifyItemChanged(position) adapter.notifyItemChanged(position)
}) })

View File

@ -10,14 +10,10 @@ import android.hardware.Sensor
import android.hardware.SensorEvent import android.hardware.SensorEvent
import android.hardware.SensorEventListener import android.hardware.SensorEventListener
import android.hardware.SensorManager import android.hardware.SensorManager
import android.view.InputDevice import android.view.*
import android.view.KeyEvent
import android.view.MotionEvent
import android.view.OrientationEventListener
import android.view.View
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import emu.skyline.settings.EmulationSettings
import emu.skyline.utils.ByteBufferSerializable import emu.skyline.utils.ByteBufferSerializable
import emu.skyline.settings.PreferenceSettings
import emu.skyline.utils.u64 import emu.skyline.utils.u64
import java.nio.ByteBuffer import java.nio.ByteBuffer
import java.nio.ByteOrder import java.nio.ByteOrder
@ -26,7 +22,7 @@ import kotlin.math.abs
/** /**
* Handles input events during emulation * Handles input events during emulation
*/ */
class InputHandler(private val inputManager : InputManager, private val preferenceSettings : PreferenceSettings) : SensorEventListener { class InputHandler(private val inputManager : InputManager, private val emulationSettings : EmulationSettings) : SensorEventListener {
companion object { companion object {
/** /**
* This initializes a guest controller in libskyline * This initializes a guest controller in libskyline
@ -117,7 +113,7 @@ class InputHandler(private val inputManager : InputManager, private val preferen
if (controller.type != ControllerType.None) { if (controller.type != ControllerType.None) {
val type = when (controller.type) { val type = when (controller.type) {
ControllerType.None -> throw IllegalArgumentException() ControllerType.None -> throw IllegalArgumentException()
ControllerType.HandheldProController -> if (preferenceSettings.isDocked) ControllerType.ProController.id else ControllerType.HandheldProController.id ControllerType.HandheldProController -> if (emulationSettings.isDocked) ControllerType.ProController.id else ControllerType.HandheldProController.id
ControllerType.ProController, ControllerType.JoyConLeft, ControllerType.JoyConRight -> controller.type.id ControllerType.ProController, ControllerType.JoyConLeft, ControllerType.JoyConRight -> controller.type.id
} }

View File

@ -15,7 +15,7 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import emu.skyline.R import emu.skyline.R
import emu.skyline.databinding.OnScreenEditActivityBinding import emu.skyline.databinding.OnScreenEditActivityBinding
import emu.skyline.settings.PreferenceSettings import emu.skyline.settings.AppSettings
import javax.inject.Inject import javax.inject.Inject
@AndroidEntryPoint @AndroidEntryPoint
@ -26,7 +26,7 @@ class OnScreenEditActivity : AppCompatActivity() {
private var editMode = false private var editMode = false
@Inject @Inject
lateinit var preferenceSettings : PreferenceSettings lateinit var appSettings : AppSettings
private val closeAction : () -> Unit = { private val closeAction : () -> Unit = {
if (editMode) { if (editMode) {
@ -103,7 +103,7 @@ class OnScreenEditActivity : AppCompatActivity() {
} }
} }
binding.onScreenControllerView.recenterSticks = preferenceSettings.onScreenControlRecenterSticks binding.onScreenControllerView.recenterSticks = appSettings.onScreenControlRecenterSticks
actions.forEach { pair -> actions.forEach { pair ->
binding.fabParent.addView(LayoutInflater.from(this).inflate(R.layout.on_screen_edit_mini_fab, binding.fabParent, false).apply { binding.fabParent.addView(LayoutInflater.from(this).inflate(R.layout.on_screen_edit_mini_fab, binding.fabParent, false).apply {

View File

@ -23,14 +23,13 @@ import emu.skyline.adapter.GpuDriverViewItem
import emu.skyline.adapter.SelectableGenericAdapter import emu.skyline.adapter.SelectableGenericAdapter
import emu.skyline.adapter.SpacingItemDecoration import emu.skyline.adapter.SpacingItemDecoration
import emu.skyline.databinding.GpuDriverActivityBinding import emu.skyline.databinding.GpuDriverActivityBinding
import emu.skyline.settings.EmulationSettings
import emu.skyline.utils.GpuDriverHelper import emu.skyline.utils.GpuDriverHelper
import emu.skyline.utils.GpuDriverInstallResult import emu.skyline.utils.GpuDriverInstallResult
import emu.skyline.settings.PreferenceSettings
import emu.skyline.utils.WindowInsetsHelper import emu.skyline.utils.WindowInsetsHelper
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject
/** /**
* This activity is used to manage the installed gpu drivers and select one to use. * This activity is used to manage the installed gpu drivers and select one to use.
@ -41,8 +40,7 @@ class GpuDriverActivity : AppCompatActivity() {
private val adapter = SelectableGenericAdapter(0) private val adapter = SelectableGenericAdapter(0)
@Inject lateinit var emulationSettings : EmulationSettings
lateinit var preferenceSettings : PreferenceSettings
/** /**
* The callback called after a user picked a driver to install. * The callback called after a user picked a driver to install.
@ -73,10 +71,10 @@ class GpuDriverActivity : AppCompatActivity() {
// Insert the system driver entry at the top of the list. // Insert the system driver entry at the top of the list.
items.add(GpuDriverViewItem(GpuDriverHelper.getSystemDriverMetadata(this)) { items.add(GpuDriverViewItem(GpuDriverHelper.getSystemDriverMetadata(this)) {
preferenceSettings.gpuDriver = PreferenceSettings.SYSTEM_GPU_DRIVER emulationSettings.gpuDriver = EmulationSettings.SYSTEM_GPU_DRIVER
}) })
if (preferenceSettings.gpuDriver == PreferenceSettings.SYSTEM_GPU_DRIVER) { if (emulationSettings.gpuDriver == EmulationSettings.SYSTEM_GPU_DRIVER) {
adapter.selectedPosition = 0 adapter.selectedPosition = 0
} }
@ -85,7 +83,7 @@ class GpuDriverActivity : AppCompatActivity() {
onDelete = { position, wasChecked -> onDelete = { position, wasChecked ->
// If the driver was selected, select the system driver as the active one // If the driver was selected, select the system driver as the active one
if (wasChecked) if (wasChecked)
preferenceSettings.gpuDriver = PreferenceSettings.SYSTEM_GPU_DRIVER emulationSettings.gpuDriver = EmulationSettings.SYSTEM_GPU_DRIVER
Snackbar.make(binding.root, "${metadata.label} deleted", Snackbar.LENGTH_LONG).setAction(R.string.undo) { Snackbar.make(binding.root, "${metadata.label} deleted", Snackbar.LENGTH_LONG).setAction(R.string.undo) {
this@GpuDriverActivity.adapter.run { this@GpuDriverActivity.adapter.run {
@ -94,7 +92,7 @@ class GpuDriverActivity : AppCompatActivity() {
if (wasChecked) { if (wasChecked) {
// Only notify previous to avoid notifying items before indexes have updated, the newly inserted item will be updated on bind // Only notify previous to avoid notifying items before indexes have updated, the newly inserted item will be updated on bind
selectAndNotifyPrevious(position) selectAndNotifyPrevious(position)
preferenceSettings.gpuDriver = metadata.label emulationSettings.gpuDriver = metadata.label
} }
} }
}.addCallback(object : Snackbar.Callback() { }.addCallback(object : Snackbar.Callback() {
@ -108,11 +106,11 @@ class GpuDriverActivity : AppCompatActivity() {
} }
onClick = { onClick = {
preferenceSettings.gpuDriver = metadata.label emulationSettings.gpuDriver = metadata.label
} }
}) })
if (preferenceSettings.gpuDriver == metadata.label) { if (emulationSettings.gpuDriver == metadata.label) {
adapter.selectedPosition = index + 1 // Add 1 to account for the system driver entry adapter.selectedPosition = index + 1 // Add 1 to account for the system driver entry
} }
} }
@ -175,6 +173,7 @@ class GpuDriverActivity : AppCompatActivity() {
installCallback.launch(intent) installCallback.launch(intent)
} }
emulationSettings = EmulationSettings.global
populateAdapter() populateAdapter()
} }

View File

@ -13,8 +13,8 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.Preference.SummaryProvider import androidx.preference.Preference.SummaryProvider
import androidx.preference.R import androidx.preference.R
import emu.skyline.settings.EmulationSettings
import emu.skyline.utils.GpuDriverHelper import emu.skyline.utils.GpuDriverHelper
import emu.skyline.settings.PreferenceSettings
import emu.skyline.R as SkylineR import emu.skyline.R as SkylineR
/** /**
@ -29,9 +29,9 @@ class GpuDriverPreference @JvmOverloads constructor(context : Context, attrs : A
val supportsCustomDriverLoading = GpuDriverHelper.supportsCustomDriverLoading() val supportsCustomDriverLoading = GpuDriverHelper.supportsCustomDriverLoading()
if (supportsCustomDriverLoading) { if (supportsCustomDriverLoading) {
summaryProvider = SummaryProvider<GpuDriverPreference> { summaryProvider = SummaryProvider<GpuDriverPreference> {
sharedPreferences?.getString(key, PreferenceSettings.SYSTEM_GPU_DRIVER)?.let { sharedPreferences?.getString(key, EmulationSettings.SYSTEM_GPU_DRIVER)?.let {
var driver = it var driver = it
if (it == PreferenceSettings.SYSTEM_GPU_DRIVER) if (it == EmulationSettings.SYSTEM_GPU_DRIVER)
driver = context.getString(SkylineR.string.system_driver) driver = context.getString(SkylineR.string.system_driver)
context.getString(SkylineR.string.gpu_driver_config_desc, driver) context.getString(SkylineR.string.gpu_driver_config_desc, driver)

View File

@ -0,0 +1,37 @@
/*
* SPDX-License-Identifier: MPL-2.0
* Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
*/
package emu.skyline.settings
import android.content.Context
import dagger.hilt.android.qualifiers.ApplicationContext
import emu.skyline.utils.sharedPreferences
import javax.inject.Inject
import javax.inject.Singleton
/**
* Settings used by the app globally
*/
@Singleton
class AppSettings @Inject constructor(@ApplicationContext private val context : Context) {
// Emulator
var searchLocation by sharedPreferences(context, "")
var appTheme by sharedPreferences(context, 2)
var layoutType by sharedPreferences(context, 1)
var groupByFormat by sharedPreferences(context, true)
var sortAppsBy by sharedPreferences(context, 0)
var selectAction by sharedPreferences(context, false)
var perfStats by sharedPreferences(context, false)
var logLevel by sharedPreferences(context, 3)
// Input
var onScreenControl by sharedPreferences(context, true)
var onScreenControlFeedback by sharedPreferences(context, true)
var onScreenControlRecenterSticks by sharedPreferences(context, true)
// Other
var romFormatFilter by sharedPreferences(context, 0)
var refreshRequired by sharedPreferences(context, false)
}

View File

@ -0,0 +1,66 @@
/*
* SPDX-License-Identifier: MPL-2.0
* Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
*/
package emu.skyline.settings
import android.content.Context
import android.content.pm.ActivityInfo
import emu.skyline.R
import emu.skyline.SkylineApplication
import emu.skyline.utils.sharedPreferences
/**
* Settings used during emulation.
*/
class EmulationSettings private constructor(context : Context, prefName : String?) {
// Whether this is the global settings
val isGlobal = prefName == null
// Custom settings toggle, should be ignored for global settings
var useCustomSettings by sharedPreferences(context, false, prefName = prefName)
// System
var isDocked by sharedPreferences(context, true, prefName = prefName)
var usernameValue by sharedPreferences(context, context.getString(R.string.username_default), prefName = prefName)
var profilePictureValue by sharedPreferences(context, "", prefName = prefName)
var systemLanguage by sharedPreferences(context, 1, prefName = prefName)
var systemRegion by sharedPreferences(context, -1, prefName = prefName)
// Display
var forceTripleBuffering by sharedPreferences(context, true, prefName = prefName)
var disableFrameThrottling by sharedPreferences(context, false, prefName = prefName)
var maxRefreshRate by sharedPreferences(context, false, prefName = prefName)
var aspectRatio by sharedPreferences(context, 0, prefName = prefName)
var orientation by sharedPreferences(context, ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE, prefName = prefName)
var respectDisplayCutout by sharedPreferences(context, false, prefName = prefName)
var disableShaderCache by sharedPreferences(context, false, prefName = prefName)
// GPU
var gpuDriver by sharedPreferences(context, SYSTEM_GPU_DRIVER, prefName = prefName)
var executorSlotCountScale by sharedPreferences(context, 6, prefName = prefName)
var executorFlushThreshold by sharedPreferences(context, 256, prefName = prefName)
var useDirectMemoryImport by sharedPreferences(context, false, prefName = prefName)
var forceMaxGpuClocks by sharedPreferences(context, false, prefName = prefName)
// Hacks
var enableFastGpuReadbackHack by sharedPreferences(context, false, prefName = prefName)
var enableFastReadbackWrites by sharedPreferences(context, false, prefName = prefName)
var disableSubgroupShuffle by sharedPreferences(context, false, prefName = prefName)
// Audio
var isAudioOutputDisabled by sharedPreferences(context, false, prefName = prefName)
// Debug
var validationLayer by sharedPreferences(context, false, prefName = prefName)
companion object {
const val SYSTEM_GPU_DRIVER = "system"
/**
* The global emulation settings instance
*/
val global by lazy { EmulationSettings(SkylineApplication.context, null) }
}
}

View File

@ -47,7 +47,7 @@ data class NativeSettings(
// Debug // Debug
var validationLayer : Boolean var validationLayer : Boolean
) { ) {
constructor(context : Context, pref : PreferenceSettings) : this( constructor(context : Context, pref : EmulationSettings) : this(
pref.isDocked, pref.isDocked,
pref.usernameValue, pref.usernameValue,
pref.profilePictureValue, pref.profilePictureValue,

View File

@ -1,83 +0,0 @@
/*
* SPDX-License-Identifier: MPL-2.0
* Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
*/
package emu.skyline.settings
import android.content.Context
import android.content.pm.ActivityInfo
import androidx.preference.PreferenceManager
import dagger.hilt.android.qualifiers.ApplicationContext
import emu.skyline.R
import emu.skyline.utils.sharedPreferences
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class PreferenceSettings @Inject constructor(@ApplicationContext private val context : Context) {
// Emulator
var searchLocation by sharedPreferences(context, "")
var appTheme by sharedPreferences(context, 2)
var layoutType by sharedPreferences(context, 1)
var groupByFormat by sharedPreferences(context, true)
var sortAppsBy by sharedPreferences(context, 0)
var selectAction by sharedPreferences(context, false)
var perfStats by sharedPreferences(context, false)
var logLevel by sharedPreferences(context, 3)
// System
var isDocked by sharedPreferences(context, true)
var usernameValue by sharedPreferences(context, context.getString(R.string.username_default))
var profilePictureValue by sharedPreferences(context, "")
var systemLanguage by sharedPreferences(context, 1)
var systemRegion by sharedPreferences(context, -1)
// Display
var forceTripleBuffering by sharedPreferences(context, true)
var disableFrameThrottling by sharedPreferences(context, false)
var maxRefreshRate by sharedPreferences(context, false)
var aspectRatio by sharedPreferences(context, 0)
var orientation by sharedPreferences(context, ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE)
var respectDisplayCutout by sharedPreferences(context, false)
var disableShaderCache by sharedPreferences(context, false)
// GPU
var gpuDriver by sharedPreferences(context, SYSTEM_GPU_DRIVER)
var executorSlotCountScale by sharedPreferences(context, 6)
var executorFlushThreshold by sharedPreferences(context, 256)
var useDirectMemoryImport by sharedPreferences(context, false)
var forceMaxGpuClocks by sharedPreferences(context, false)
// Hacks
var enableFastGpuReadbackHack by sharedPreferences(context, false)
var enableFastReadbackWrites by sharedPreferences(context, false)
var disableSubgroupShuffle by sharedPreferences(context, false)
// Audio
var isAudioOutputDisabled by sharedPreferences(context, false)
// Debug
var validationLayer by sharedPreferences(context, false)
// Input
var onScreenControl by sharedPreferences(context, true)
var onScreenControlFeedback by sharedPreferences(context, true)
var onScreenControlRecenterSticks by sharedPreferences(context, true)
// Other
var romFormatFilter by sharedPreferences(context, 0)
var refreshRequired by sharedPreferences(context, false)
companion object {
const val SYSTEM_GPU_DRIVER = "system"
/**
* Sets the default values for global preferences
*/
fun setDefaultValues(context : Context) {
PreferenceManager.setDefaultValues(context, R.xml.app_preferences, false)
PreferenceManager.setDefaultValues(context, R.xml.emulation_preferences, false)
}
}
}