Add custom audio settings

This commit is contained in:
KeatonTheBot
2026-09-05 14:13:06 -05:00
parent db35be690f
commit 19a8d1445e
8 changed files with 154 additions and 0 deletions
@@ -78,6 +78,8 @@ namespace Ryujinx.UI.Common.Helper
ConfigurationState.Instance.System.EnableLowPowerPptc.Value = customSettingsModel.EnableLowPowerPptc;
ConfigurationState.Instance.System.MemoryManagerMode.Value = (MemoryManagerMode)customSettingsModel.MemoryManagerMode;
ConfigurationState.Instance.System.UseHypervisor.Value = customSettingsModel.UseHypervisor;
ConfigurationState.Instance.System.AudioBackend.Value = customSettingsModel.AudioBackend;
ConfigurationState.Instance.System.AudioVolume.Value = customSettingsModel.AudioVolume;
ConfigurationState.Instance.Graphics.GraphicsBackend.Value = (GraphicsBackend)customSettingsModel.GraphicsBackend;
ConfigurationState.Instance.Graphics.PreferredGpu.Value = customSettingsModel.PreferredGpu;
ConfigurationState.Instance.Graphics.EnableShaderCache.Value = customSettingsModel.EnableShaderCache;
@@ -28,5 +28,10 @@ namespace Ryujinx.UI.Common.Models
public float ResScale { get; set; }
public float MaxAnisotropy { get; set; }
public int BackendThreading { get; set; }
public int IsOpenAlEnabled { get; set; }
public int IsSDL2Enabled { get; set; }
public int IsSoundIoEnabled { get; set; }
public AudioBackend AudioBackend { get; set; }
public float AudioVolume { get; set; }
}
}
+3
View File
@@ -178,5 +178,8 @@
<Compile Update="UI\Windows\CustomSettingsWindow.axaml.cs">
<DependentUpon>CustomSettingsWindow.axaml</DependentUpon>
</Compile>
<Compile Update="UI\Views\Settings\CustomSettingsAudioView.axaml.cs">
<DependentUpon>CustomSettingsAudioView.axaml</DependentUpon>
</Compile>
</ItemGroup>
</Project>
@@ -2,6 +2,9 @@ using Avalonia.Controls;
using Avalonia.Media.Imaging;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using Ryujinx.Audio.Backends.OpenAL;
using Ryujinx.Audio.Backends.SDL2;
using Ryujinx.Audio.Backends.SoundIo;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Graphics.Vulkan;
@@ -131,12 +134,33 @@ namespace Ryujinx.Ava.UI.ViewModels
public int MaxAnisotropyIndex { get; set; }
public int BackendThreading { get; set; }
// Audio settings
public bool IsOpenAlEnabled { get; set; }
public bool IsSoundIoEnabled { get; set; }
public bool IsSDL2Enabled { get; set; }
public AudioBackend AudioBackend { get; set; }
public float Volume
{
get;
set
{
field = value;
ConfigurationState.Instance.System.AudioVolume.Value = field / 100;
OnPropertyChanged();
}
}
public CustomSettingsViewModel(string titleId, byte[] icon, string titleName)
{
AvailableGpus = [];
ApplicationIdBase = ulong.Parse(titleId, NumberStyles.HexNumber);
CustomSettingsModel = CustomSettingsHelper.LoadCustomSettingsJson(CustomSettingsHelper.PathToGameSettingsJson(ApplicationIdBase));
Task.Run(CheckSoundBackends);
if (icon is { Length: > 0 })
{
using MemoryStream ms = new(icon);
@@ -150,6 +174,20 @@ namespace Ryujinx.Ava.UI.ViewModels
}
}
public async Task CheckSoundBackends()
{
IsOpenAlEnabled = OpenALHardwareDeviceDriver.IsSupported;
IsSoundIoEnabled = SoundIoHardwareDeviceDriver.IsSupported;
IsSDL2Enabled = SDL2HardwareDeviceDriver.IsSupported;
await Dispatcher.UIThread.InvokeAsync(() =>
{
OnPropertyChanged(nameof(IsOpenAlEnabled));
OnPropertyChanged(nameof(IsSoundIoEnabled));
OnPropertyChanged(nameof(IsSDL2Enabled));
});
}
private async Task LoadAvailableGpus()
{
AvailableGpus.Clear();
@@ -206,6 +244,8 @@ namespace Ryujinx.Ava.UI.ViewModels
ResScaleIndex = ComputeResScaleIndex(config.Graphics.ResScale);
MaxAnisotropyIndex = ComputeMaxAnisotropyIndex(config.Graphics.MaxAnisotropy);
BackendThreading = (int)config.Graphics.BackendThreading.Value;
AudioBackend = config.System.AudioBackend.Value;
Volume = config.System.AudioVolume * 100;
}
else
{
@@ -230,6 +270,8 @@ namespace Ryujinx.Ava.UI.ViewModels
ResScaleIndex = ComputeResScaleIndex(CustomSettingsModel.ResScale);
MaxAnisotropyIndex = ComputeMaxAnisotropyIndex(CustomSettingsModel.MaxAnisotropy);
BackendThreading = CustomSettingsModel.BackendThreading;
AudioBackend = CustomSettingsModel.AudioBackend;
Volume = CustomSettingsModel.AudioVolume * 100;
}
}
@@ -263,6 +305,8 @@ namespace Ryujinx.Ava.UI.ViewModels
CustomSettingsModel.ResScale = ComputeResScale(ResScaleIndex);
CustomSettingsModel.MaxAnisotropy = ComputeMaxAnisotropy(MaxAnisotropyIndex);
CustomSettingsModel.BackendThreading = BackendThreading;
CustomSettingsModel.AudioBackend = AudioBackend;
CustomSettingsModel.AudioVolume = Volume / 100;
CustomSettingsHelper.SaveCustomSettingsJson(CustomSettingsHelper.PathToGameSettingsJson(ApplicationIdBase), CustomSettingsModel);
}
@@ -0,0 +1,80 @@
<UserControl
x:Class="Ryujinx.Ava.UI.Views.Settings.CustomSettingsAudioView"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
mc:Ignorable="d"
x:DataType="viewModels:CustomSettingsViewModel">
<Design.DataContext>
<viewModels:SettingsViewModel />
</Design.DataContext>
<ScrollViewer
Name="AudioPage"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto">
<Border Classes="settings">
<StackPanel
Margin="10"
HorizontalAlignment="Stretch"
Orientation="Vertical"
Spacing="10">
<TextBlock Classes="h1" Text="{locale:Locale SettingsTabAudio}" />
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
<TextBlock VerticalAlignment="Center"
Text="{locale:Locale SettingsTabSystemAudioBackend}"
ToolTip.Tip="{locale:Locale AudioBackendTooltip}"
Width="250" />
<ComboBox SelectedIndex="{Binding AudioBackend}"
Width="350"
HorizontalContentAlignment="Left">
<ComboBoxItem
Content="{locale:Locale SettingsTabSystemAudioBackendDummy}" />
<ComboBoxItem
IsEnabled="{Binding IsOpenAlEnabled}"
Content="{locale:Locale SettingsTabSystemAudioBackendOpenAL}" />
<ComboBoxItem
IsEnabled="{Binding IsSoundIoEnabled}"
Content="{locale:Locale SettingsTabSystemAudioBackendSoundIO}" />
<ComboBoxItem
IsEnabled="{Binding IsSDL2Enabled}"
Content="{locale:Locale SettingsTabSystemAudioBackendSDL2}" />
</ComboBox>
</StackPanel>
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
<TextBlock VerticalAlignment="Center"
Text="{locale:Locale SettingsTabSystemAudioVolume}"
ToolTip.Tip="{locale:Locale AudioVolumeTooltip}"
Width="250" />
<ui:NumberBox Value="{Binding Volume}"
ToolTip.Tip="{locale:Locale AudioVolumeTooltip}"
Width="350"
SmallChange="1"
LargeChange="10"
SimpleNumberFormat="F0"
SpinButtonPlacementMode="Inline"
Minimum="0"
Maximum="100" />
</StackPanel>
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
<controls:SliderScroll Value="{Binding Volume}"
Margin="250,0,0,0"
ToolTip.Tip="{locale:Locale AudioVolumeTooltip}"
Minimum="0"
Maximum="100"
SmallChange="1"
TickFrequency="1"
IsSnapToTickEnabled="True"
LargeChange="10"
Width="350" />
</StackPanel>
</StackPanel>
</Border>
</ScrollViewer>
</UserControl>
@@ -0,0 +1,12 @@
using Avalonia.Controls;
namespace Ryujinx.Ava.UI.Views.Settings
{
public partial class CustomSettingsAudioView : UserControl
{
public CustomSettingsAudioView()
{
InitializeComponent();
}
}
}
@@ -32,6 +32,7 @@
<settings:CustomSettingsSystemView Name="SystemPage" />
<settings:CustomSettingsCPUView Name="CpuPage" />
<settings:CustomSettingsGraphicsView Name="GraphicsPage" />
<settings:CustomSettingsAudioView Name="AudioPage" />
</Grid>
<ui:NavigationView
Grid.Row="1"
@@ -82,6 +83,10 @@
Content="{locale:Locale SettingsTabGraphics}"
Tag="GraphicsPage"
IconSource="Image" />
<ui:NavigationViewItem
Content="{locale:Locale SettingsTabAudio}"
IconSource="Audio"
Tag="AudioPage" />
</ui:NavigationView.MenuItems>
<ui:NavigationView.Styles>
<Style Selector="Grid#PlaceholderGrid">
@@ -94,6 +94,9 @@ namespace Ryujinx.Ava.UI.Windows
case "GraphicsPage":
NavPanel.Content = GraphicsPage;
break;
case "AudioPage":
NavPanel.Content = AudioPage;
break;
default:
throw new NotImplementedException();
}