Skip to content

Commit f020f80

Browse files
committed
1 parent 2bd7349 commit f020f80

File tree

2 files changed

+98
-22
lines changed

2 files changed

+98
-22
lines changed

osu.Game/Localisation/AudioSettingsStrings.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ public static class AudioSettingsStrings
2424
/// </summary>
2525
public static LocalisableString VolumeHeader => new TranslatableString(getKey(@"volume_header"), @"Volume");
2626

27+
/// <summary>
28+
/// "Audio backend"
29+
/// </summary>
30+
public static LocalisableString AudioBackend => new TranslatableString(getKey(@"audio_backend"), @"Audio backend");
31+
2732
/// <summary>
2833
/// "Output device"
2934
/// </summary>
@@ -99,6 +104,21 @@ public static class AudioSettingsStrings
99104
/// </summary>
100105
public static LocalisableString AdjustBeatmapOffsetAutomaticallyTooltip => new TranslatableString(getKey(@"adjust_beatmap_offset_automatically_tooltip"), @"If enabled, the offset suggested from last play on a beatmap is automatically applied.");
101106

107+
/// <summary>
108+
/// "In order to change the audio backend, the game will close. Please open it again."
109+
/// </summary>
110+
public static LocalisableString ChangeAudioBackendConfirmation => new TranslatableString(getKey("change_audio_backend_confirmation"), @"In order to change the audio backend, the game will close. Please open it again.");
111+
112+
/// <summary>
113+
/// "Exclusive mode behaviour"
114+
/// </summary>
115+
public static LocalisableString ExclusiveModeBehaviour => new TranslatableString(getKey("exclusive_mode_behaviour"), @"Exclusive mode behaviour");
116+
117+
/// <summary>
118+
/// "Changes to this setting will only apply when using BASSWASAPI backend."
119+
/// </summary>
120+
public static LocalisableString ExclusiveModeAvailabilityNote => new TranslatableString(getKey(@"exclusive_mode_availability_note"), @"Changes to this setting will only apply when using BASSWASAPI backend.");
121+
102122
private static string getKey(string key) => $@"{prefix}:{key}";
103123
}
104124
}

osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs

Lines changed: 78 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,19 @@
33

44
#nullable disable
55

6+
using System.Collections.Generic;
7+
using System.Linq;
8+
using osu.Framework;
69
using osu.Framework.Allocation;
710
using osu.Framework.Audio;
11+
using osu.Framework.Configuration;
812
using osu.Framework.Graphics;
9-
using System.Collections.Generic;
10-
using System.Linq;
1113
using osu.Framework.Localisation;
14+
using osu.Framework.Platform;
15+
using osu.Game.Configuration;
1216
using osu.Game.Graphics.UserInterface;
1317
using osu.Game.Localisation;
18+
using osu.Game.Overlays.Dialog;
1419

1520
namespace osu.Game.Overlays.Settings.Sections.Audio
1621
{
@@ -21,49 +26,93 @@ public partial class AudioDevicesSettings : SettingsSubsection
2126
[Resolved]
2227
private AudioManager audio { get; set; }
2328

24-
private SettingsDropdown<string> dropdown;
29+
private SettingsDropdown<AudioBackend> backend;
30+
private SettingsDropdown<string> device;
31+
private SettingsDropdown<AudioExclusiveModeBehaviour> exclusiveModeBehaviour;
32+
33+
private bool automaticBackendInUse;
2534

2635
[BackgroundDependencyLoader]
27-
private void load()
36+
private void load(FrameworkConfigManager config, OsuGame game, IDialogOverlay dialogOverlay)
2837
{
38+
var currentBackend = config.GetBindable<AudioBackend>(FrameworkSetting.AudioBackend);
39+
var currentExclusiveModeBehaviour = localConfig.GetBindable<AudioExclusiveModeBehaviour>(FrameworkSetting.AudioExclusiveModeBehaviour);
40+
// Audio backend selection is currently only available on Windows for now.
41+
currentBackend.Disabled = RuntimeInfo.OS != RuntimeInfo.Platform.Windows;
42+
currentExclusiveModeBehaviour.Disabled = RuntimeInfo.OS != RuntimeInfo.Platform.Windows;
43+
automaticBackendInUse = currentBackend.Value == AudioBackend.Automatic;
44+
2945
Children = new Drawable[]
3046
{
31-
dropdown = new AudioDeviceSettingsDropdown
47+
backend = new SettingsEnumDropdown<AudioBackend>
48+
{
49+
LabelText = AudioSettingsStrings.AudioBackend,
50+
Keywords = new[] { "backend", "bass", "wasapi" },
51+
Current = currentBackend,
52+
Items = game.GetPreferredAudioBackendsForCurrentPlatform(),
53+
},
54+
device = new AudioDeviceSettingsDropdown
3255
{
3356
LabelText = AudioSettingsStrings.OutputDevice,
34-
Keywords = new[] { "speaker", "headphone", "output" }
35-
}
57+
Keywords = new[] { "speaker", "headphone", "output" },
58+
},
59+
exclusiveModeBehaviour = new SettingsEnumDropdown<AudioExclusiveModeBehaviour>
60+
{
61+
LabelText = AudioSettingsStrings.ExclusiveModeBehaviour,
62+
Keywords = new[] { "exclusive", "latency" },
63+
Current = currentExclusiveModeBehaviour,
64+
},
3665
};
3766

67+
currentBackend.BindValueChanged(r =>
68+
{
69+
if (r.NewValue != AudioBackend.BassWasapi)
70+
exclusiveModeBehaviour.SetNoticeText(AudioSettingsStrings.ExclusiveModeAvailabilityNote, true);
71+
else
72+
exclusiveModeBehaviour.ClearNoticeText();
73+
74+
// Up to here is executed immediately.
75+
if (r.OldValue == r.NewValue)
76+
return;
77+
78+
if (r.NewValue == game.ResolvedAudioBackend)
79+
return;
80+
81+
if (r.NewValue == AudioBackend.Automatic && automaticBackendInUse)
82+
return;
83+
84+
if (game?.RestartAppWhenExited() == true)
85+
{
86+
game.AttemptExit();
87+
}
88+
else
89+
{
90+
dialogOverlay?.Push(new ConfirmDialog(AudioSettingsStrings.ChangeAudioBackendConfirmation, () => game?.AttemptExit(), () =>
91+
{
92+
currentBackend.Value = automaticBackendInUse ? AudioBackend.Automatic : game?.ResolvedAudioBackend ?? AudioBackend.Automatic;
93+
}));
94+
}
95+
}, true);
96+
3897
updateItems();
3998

4099
audio.OnNewDevice += onDeviceChanged;
41100
audio.OnLostDevice += onDeviceChanged;
42-
dropdown.Current = audio.AudioDevice;
101+
device.Current = audio.AudioDevice;
43102
}
44103

45-
private void onDeviceChanged(string name) => updateItems();
104+
private void onDeviceChanged(KeyValuePair<string, string> _) => updateItems();
46105

47106
private void updateItems()
48107
{
49108
var deviceItems = new List<string> { string.Empty };
50-
deviceItems.AddRange(audio.AudioDeviceNames);
109+
deviceItems.AddRange(audio.AudioDevices.Keys);
51110

52111
string preferredDeviceName = audio.AudioDevice.Value;
53112
if (deviceItems.All(kv => kv != preferredDeviceName))
54113
deviceItems.Add(preferredDeviceName);
55114

56-
// The option dropdown for audio device selection lists all audio
57-
// device names. Dropdowns, however, may not have multiple identical
58-
// keys. Thus, we remove duplicate audio device names from
59-
// the dropdown. BASS does not give us a simple mechanism to select
60-
// specific audio devices in such a case anyways. Such
61-
// functionality would require involved OS-specific code.
62-
dropdown.Items = deviceItems
63-
// Dropdown doesn't like null items. Somehow we are seeing some arrive here (see https://github.com/ppy/osu/issues/21271)
64-
.Where(i => i != null)
65-
.Distinct()
66-
.ToList();
115+
device.Items = deviceItems.ToList();
67116
}
68117

69118
protected override void Dispose(bool isDisposing)
@@ -83,8 +132,15 @@ private partial class AudioDeviceSettingsDropdown : SettingsDropdown<string>
83132

84133
private partial class AudioDeviceDropdownControl : DropdownControl
85134
{
135+
[Resolved]
136+
private AudioManager audio { get; set; }
137+
86138
protected override LocalisableString GenerateItemText(string item)
87-
=> string.IsNullOrEmpty(item) ? CommonStrings.Default : base.GenerateItemText(item);
139+
=> string.IsNullOrEmpty(item)
140+
? CommonStrings.Default
141+
: audio is AudioManager manager && manager.AudioDevices.TryGetValue(item, out string value)
142+
? value
143+
: item;
88144
}
89145
}
90146
}

0 commit comments

Comments
 (0)