Add custom audio settings

This commit is contained in:
KeatonTheBot
2026-05-25 12:12:09 -05:00
parent a94c18bc0a
commit 645a4c99af
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.EnableLowPowerPptc.Value = customSettingsModel.EnableLowPowerPptc;
ConfigurationState.Instance.System.MemoryManagerMode.Value = (MemoryManagerMode)customSettingsModel.MemoryManagerMode; ConfigurationState.Instance.System.MemoryManagerMode.Value = (MemoryManagerMode)customSettingsModel.MemoryManagerMode;
ConfigurationState.Instance.System.UseHypervisor.Value = customSettingsModel.UseHypervisor; 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.GraphicsBackend.Value = (GraphicsBackend)customSettingsModel.GraphicsBackend;
ConfigurationState.Instance.Graphics.PreferredGpu.Value = customSettingsModel.PreferredGpu; ConfigurationState.Instance.Graphics.PreferredGpu.Value = customSettingsModel.PreferredGpu;
ConfigurationState.Instance.Graphics.EnableShaderCache.Value = customSettingsModel.EnableShaderCache; ConfigurationState.Instance.Graphics.EnableShaderCache.Value = customSettingsModel.EnableShaderCache;
@@ -28,5 +28,10 @@ namespace Ryujinx.UI.Common.Models
public float ResScale { get; set; } public float ResScale { get; set; }
public float MaxAnisotropy { get; set; } public float MaxAnisotropy { get; set; }
public int BackendThreading { 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"> <Compile Update="UI\Windows\CustomSettingsWindow.axaml.cs">
<DependentUpon>CustomSettingsWindow.axaml</DependentUpon> <DependentUpon>CustomSettingsWindow.axaml</DependentUpon>
</Compile> </Compile>
<Compile Update="UI\Views\Settings\CustomSettingsAudioView.axaml.cs">
<DependentUpon>CustomSettingsAudioView.axaml</DependentUpon>
</Compile>
</ItemGroup> </ItemGroup>
</Project> </Project>
@@ -2,6 +2,9 @@ using Avalonia.Controls;
using Avalonia.Media.Imaging; using Avalonia.Media.Imaging;
using Avalonia.Threading; using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel; 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.Common.Locale;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Graphics.Vulkan; using Ryujinx.Graphics.Vulkan;
@@ -131,12 +134,33 @@ namespace Ryujinx.Ava.UI.ViewModels
public int MaxAnisotropyIndex { get; set; } public int MaxAnisotropyIndex { get; set; }
public int BackendThreading { 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) public CustomSettingsViewModel(string titleId, byte[] icon, string titleName)
{ {
AvailableGpus = []; AvailableGpus = [];
ApplicationIdBase = ulong.Parse(titleId, NumberStyles.HexNumber); ApplicationIdBase = ulong.Parse(titleId, NumberStyles.HexNumber);
CustomSettingsModel = CustomSettingsHelper.LoadCustomSettingsJson(CustomSettingsHelper.PathToGameSettingsJson(ApplicationIdBase)); CustomSettingsModel = CustomSettingsHelper.LoadCustomSettingsJson(CustomSettingsHelper.PathToGameSettingsJson(ApplicationIdBase));
Task.Run(CheckSoundBackends);
if (icon is { Length: > 0 }) if (icon is { Length: > 0 })
{ {
using MemoryStream ms = new(icon); 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() private async Task LoadAvailableGpus()
{ {
AvailableGpus.Clear(); AvailableGpus.Clear();
@@ -206,6 +244,8 @@ namespace Ryujinx.Ava.UI.ViewModels
ResScaleIndex = ComputeResScaleIndex(config.Graphics.ResScale); ResScaleIndex = ComputeResScaleIndex(config.Graphics.ResScale);
MaxAnisotropyIndex = ComputeMaxAnisotropyIndex(config.Graphics.MaxAnisotropy); MaxAnisotropyIndex = ComputeMaxAnisotropyIndex(config.Graphics.MaxAnisotropy);
BackendThreading = (int)config.Graphics.BackendThreading.Value; BackendThreading = (int)config.Graphics.BackendThreading.Value;
AudioBackend = config.System.AudioBackend.Value;
Volume = config.System.AudioVolume * 100;
} }
else else
{ {
@@ -230,6 +270,8 @@ namespace Ryujinx.Ava.UI.ViewModels
ResScaleIndex = ComputeResScaleIndex(CustomSettingsModel.ResScale); ResScaleIndex = ComputeResScaleIndex(CustomSettingsModel.ResScale);
MaxAnisotropyIndex = ComputeMaxAnisotropyIndex(CustomSettingsModel.MaxAnisotropy); MaxAnisotropyIndex = ComputeMaxAnisotropyIndex(CustomSettingsModel.MaxAnisotropy);
BackendThreading = CustomSettingsModel.BackendThreading; BackendThreading = CustomSettingsModel.BackendThreading;
AudioBackend = CustomSettingsModel.AudioBackend;
Volume = CustomSettingsModel.AudioVolume * 100;
} }
} }
@@ -263,6 +305,8 @@ namespace Ryujinx.Ava.UI.ViewModels
CustomSettingsModel.ResScale = ComputeResScale(ResScaleIndex); CustomSettingsModel.ResScale = ComputeResScale(ResScaleIndex);
CustomSettingsModel.MaxAnisotropy = ComputeMaxAnisotropy(MaxAnisotropyIndex); CustomSettingsModel.MaxAnisotropy = ComputeMaxAnisotropy(MaxAnisotropyIndex);
CustomSettingsModel.BackendThreading = BackendThreading; CustomSettingsModel.BackendThreading = BackendThreading;
CustomSettingsModel.AudioBackend = AudioBackend;
CustomSettingsModel.AudioVolume = Volume / 100;
CustomSettingsHelper.SaveCustomSettingsJson(CustomSettingsHelper.PathToGameSettingsJson(ApplicationIdBase), CustomSettingsModel); 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:CustomSettingsSystemView Name="SystemPage" />
<settings:CustomSettingsCPUView Name="CpuPage" /> <settings:CustomSettingsCPUView Name="CpuPage" />
<settings:CustomSettingsGraphicsView Name="GraphicsPage" /> <settings:CustomSettingsGraphicsView Name="GraphicsPage" />
<settings:CustomSettingsAudioView Name="AudioPage" />
</Grid> </Grid>
<ui:NavigationView <ui:NavigationView
Grid.Row="1" Grid.Row="1"
@@ -82,6 +83,10 @@
Content="{locale:Locale SettingsTabGraphics}" Content="{locale:Locale SettingsTabGraphics}"
Tag="GraphicsPage" Tag="GraphicsPage"
IconSource="Image" /> IconSource="Image" />
<ui:NavigationViewItem
Content="{locale:Locale SettingsTabAudio}"
IconSource="Audio"
Tag="AudioPage" />
</ui:NavigationView.MenuItems> </ui:NavigationView.MenuItems>
<ui:NavigationView.Styles> <ui:NavigationView.Styles>
<Style Selector="Grid#PlaceholderGrid"> <Style Selector="Grid#PlaceholderGrid">
@@ -94,6 +94,9 @@ namespace Ryujinx.Ava.UI.Windows
case "GraphicsPage": case "GraphicsPage":
NavPanel.Content = GraphicsPage; NavPanel.Content = GraphicsPage;
break; break;
case "AudioPage":
NavPanel.Content = AudioPage;
break;
default: default:
throw new NotImplementedException(); throw new NotImplementedException();
} }