Add audio device selection. Fixes #3553.
This commit is contained in:
1
AUTHORS
1
AUTHORS
@@ -31,6 +31,7 @@ Also thanks to:
|
|||||||
* Daniel Derejvanik (Harisson)
|
* Daniel Derejvanik (Harisson)
|
||||||
* Danny Keary (Dan9550)
|
* Danny Keary (Dan9550)
|
||||||
* Erasmus Schroder (rasco)
|
* Erasmus Schroder (rasco)
|
||||||
|
* Fahrradkette
|
||||||
* Frank Razenberg (zzattack)
|
* Frank Razenberg (zzattack)
|
||||||
* Igor Popov (ihptru)
|
* Igor Popov (ihptru)
|
||||||
* Iran
|
* Iran
|
||||||
|
|||||||
@@ -104,7 +104,8 @@ namespace OpenRA.GameRules
|
|||||||
public bool Repeat = false;
|
public bool Repeat = false;
|
||||||
public bool MapMusic = true;
|
public bool MapMusic = true;
|
||||||
public string Engine = "AL";
|
public string Engine = "AL";
|
||||||
|
public string Device = null;
|
||||||
|
|
||||||
public SoundCashTicks SoundCashTickType = SoundCashTicks.Extreme;
|
public SoundCashTicks SoundCashTickType = SoundCashTicks.Extreme;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -77,6 +77,20 @@ namespace OpenRA
|
|||||||
video = null;
|
video = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static SoundDevice[] AvailableDevices()
|
||||||
|
{
|
||||||
|
var defaultDevices = new []
|
||||||
|
{
|
||||||
|
new SoundDevice("AL", null, "Default Output"),
|
||||||
|
new SoundDevice("Null", null, "Output Disabled")
|
||||||
|
};
|
||||||
|
|
||||||
|
var alDevices = OpenAlSoundEngine.AvailableDevices()
|
||||||
|
.Select(d => new SoundDevice("AL", d, d));
|
||||||
|
|
||||||
|
return defaultDevices.Concat(alDevices).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
public static void SetListenerPosition(float2 position) { soundEngine.SetListenerPosition(position); }
|
public static void SetListenerPosition(float2 position) { soundEngine.SetListenerPosition(position); }
|
||||||
|
|
||||||
static ISound Play(Player player, string name, bool headRelative, WPos pos, float volumeModifier)
|
static ISound Play(Player player, string name, bool headRelative, WPos pos, float volumeModifier)
|
||||||
@@ -348,6 +362,24 @@ namespace OpenRA
|
|||||||
void SetSoundVolume(float volume, ISound music, ISound video);
|
void SetSoundVolume(float volume, ISound music, ISound video);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class SoundDevice
|
||||||
|
{
|
||||||
|
public readonly string Engine;
|
||||||
|
public readonly string Device;
|
||||||
|
public readonly string Label;
|
||||||
|
|
||||||
|
public SoundDevice(string engine, string device, string label)
|
||||||
|
{
|
||||||
|
Engine = engine;
|
||||||
|
Device = device;
|
||||||
|
Label = label;
|
||||||
|
|
||||||
|
// Limit label to 32 characters
|
||||||
|
if (Label.Length > 32)
|
||||||
|
Label = "..." + Label.Substring(Label.Length - 32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
interface ISoundSource { }
|
interface ISoundSource { }
|
||||||
|
|
||||||
public interface ISound
|
public interface ISound
|
||||||
@@ -372,13 +404,51 @@ namespace OpenRA
|
|||||||
Dictionary<int, PoolSlot> sourcePool = new Dictionary<int, PoolSlot>();
|
Dictionary<int, PoolSlot> sourcePool = new Dictionary<int, PoolSlot>();
|
||||||
const int POOL_SIZE = 32;
|
const int POOL_SIZE = 32;
|
||||||
|
|
||||||
|
static string[] QueryDevices(string label, int type)
|
||||||
|
{
|
||||||
|
// Clear error bit
|
||||||
|
Al.alGetError();
|
||||||
|
|
||||||
|
var devices = Alc.alcGetStringv(IntPtr.Zero, type);
|
||||||
|
if (Al.alGetError() != Al.AL_NO_ERROR)
|
||||||
|
{
|
||||||
|
Log.Write("sound", "Failed to query OpenAL device list using {0}", label);
|
||||||
|
return new string[] {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string[] AvailableDevices()
|
||||||
|
{
|
||||||
|
// Returns all devices under windows vista and newer
|
||||||
|
if (Alc.alcIsExtensionPresent(IntPtr.Zero, "ALC_ENUMERATE_ALL_EXT") == Alc.ALC_TRUE)
|
||||||
|
return QueryDevices("ALC_ENUMERATE_ALL_EXT", Alc.ALC_ALL_DEVICES_SPECIFIER);
|
||||||
|
|
||||||
|
if (Alc.alcIsExtensionPresent(IntPtr.Zero, "ALC_ENUMERATION_EXT") == Alc.ALC_TRUE)
|
||||||
|
return QueryDevices("ALC_ENUMERATION_EXT", Alc.ALC_DEVICE_SPECIFIER);
|
||||||
|
|
||||||
|
return new string[] {};
|
||||||
|
}
|
||||||
|
|
||||||
public OpenAlSoundEngine()
|
public OpenAlSoundEngine()
|
||||||
{
|
{
|
||||||
Console.WriteLine("Using OpenAL sound engine");
|
Console.WriteLine("Using OpenAL sound engine");
|
||||||
//var str = Alc.alcGetString(IntPtr.Zero, Alc.ALC_DEFAULT_DEVICE_SPECIFIER);
|
|
||||||
var dev = Alc.alcOpenDevice(null);
|
if (Game.Settings.Sound.Device != null)
|
||||||
|
Console.WriteLine("Using device `{0}`", Game.Settings.Sound.Device);
|
||||||
|
else
|
||||||
|
Console.WriteLine("Using default device");
|
||||||
|
|
||||||
|
var dev = Alc.alcOpenDevice(Game.Settings.Sound.Device);
|
||||||
if (dev == IntPtr.Zero)
|
if (dev == IntPtr.Zero)
|
||||||
throw new InvalidOperationException("Can't create OpenAL device");
|
{
|
||||||
|
Console.WriteLine("Failed to open device. Falling back to default");
|
||||||
|
dev = Alc.alcOpenDevice(null);
|
||||||
|
if (dev == IntPtr.Zero)
|
||||||
|
throw new InvalidOperationException("Can't create OpenAL device");
|
||||||
|
}
|
||||||
|
|
||||||
var ctx = Alc.alcCreateContext(dev, IntPtr.Zero);
|
var ctx = Alc.alcCreateContext(dev, IntPtr.Zero);
|
||||||
if (ctx == IntPtr.Zero)
|
if (ctx == IntPtr.Zero)
|
||||||
throw new InvalidOperationException("Can't create OpenAL context");
|
throw new InvalidOperationException("Can't create OpenAL context");
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
|
|||||||
{
|
{
|
||||||
enum PanelType { General, Input }
|
enum PanelType { General, Input }
|
||||||
|
|
||||||
|
SoundDevice soundDevice;
|
||||||
PanelType Settings = PanelType.General;
|
PanelType Settings = PanelType.General;
|
||||||
ColorPreviewManagerWidget colorPreview;
|
ColorPreviewManagerWidget colorPreview;
|
||||||
World world;
|
World world;
|
||||||
@@ -112,6 +113,13 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
|
|||||||
shellmapMusicCheckbox.IsChecked = () => soundSettings.MapMusic;
|
shellmapMusicCheckbox.IsChecked = () => soundSettings.MapMusic;
|
||||||
shellmapMusicCheckbox.OnClick = () => soundSettings.MapMusic ^= true;
|
shellmapMusicCheckbox.OnClick = () => soundSettings.MapMusic ^= true;
|
||||||
|
|
||||||
|
var devices = Sound.AvailableDevices();
|
||||||
|
soundDevice = devices.FirstOrDefault(d => d.Engine == soundSettings.Engine && d.Device == soundSettings.Device) ?? devices.First();
|
||||||
|
|
||||||
|
var audioDeviceDropdown = generalPane.Get<DropDownButtonWidget>("AUDIO_DEVICE");
|
||||||
|
audioDeviceDropdown.OnMouseDown = _ => ShowAudioDeviceDropdown(audioDeviceDropdown, soundSettings, devices);
|
||||||
|
audioDeviceDropdown.GetText = () => soundDevice.Label;
|
||||||
|
|
||||||
// Input pane
|
// Input pane
|
||||||
var inputPane = panel.Get("INPUT_CONTROLS");
|
var inputPane = panel.Get("INPUT_CONTROLS");
|
||||||
inputPane.IsVisible = () => Settings == PanelType.Input;
|
inputPane.IsVisible = () => Settings == PanelType.Input;
|
||||||
@@ -147,6 +155,8 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
|
|||||||
int.TryParse(windowWidth.Text, out x);
|
int.TryParse(windowWidth.Text, out x);
|
||||||
int.TryParse(windowHeight.Text, out y);
|
int.TryParse(windowHeight.Text, out y);
|
||||||
graphicsSettings.WindowedSize = new int2(x,y);
|
graphicsSettings.WindowedSize = new int2(x,y);
|
||||||
|
soundSettings.Device = soundDevice.Device;
|
||||||
|
soundSettings.Engine = soundDevice.Engine;
|
||||||
Game.Settings.Save();
|
Game.Settings.Save();
|
||||||
Ui.CloseWindow();
|
Ui.CloseWindow();
|
||||||
onExit();
|
onExit();
|
||||||
@@ -194,5 +204,24 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic
|
|||||||
dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, options.Keys, setupItem);
|
dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, options.Keys, setupItem);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ShowAudioDeviceDropdown(DropDownButtonWidget dropdown, SoundSettings s, SoundDevice[] devices)
|
||||||
|
{
|
||||||
|
var i = 0;
|
||||||
|
var options = devices.ToDictionary(d => (i++).ToString(), d => d);
|
||||||
|
|
||||||
|
Func<string, ScrollItemWidget, ScrollItemWidget> setupItem = (o, itemTemplate) =>
|
||||||
|
{
|
||||||
|
var item = ScrollItemWidget.Setup(itemTemplate,
|
||||||
|
() => soundDevice == options[o],
|
||||||
|
() => soundDevice = options[o]);
|
||||||
|
|
||||||
|
item.Get<LabelWidget>("LABEL").GetText = () => options[o].Label;
|
||||||
|
return item;
|
||||||
|
};
|
||||||
|
|
||||||
|
dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, options.Keys, setupItem);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
public class SettingsMenuLogic
|
public class SettingsMenuLogic
|
||||||
{
|
{
|
||||||
Widget bg;
|
Widget bg;
|
||||||
|
SoundDevice soundDevice;
|
||||||
|
|
||||||
[ObjectCreator.UseCtor]
|
[ObjectCreator.UseCtor]
|
||||||
public SettingsMenuLogic(Action onExit)
|
public SettingsMenuLogic(Action onExit)
|
||||||
@@ -103,12 +104,13 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
mapMusicCheckbox.IsChecked = () => Game.Settings.Sound.MapMusic;
|
mapMusicCheckbox.IsChecked = () => Game.Settings.Sound.MapMusic;
|
||||||
mapMusicCheckbox.OnClick = () => Game.Settings.Sound.MapMusic ^= true;
|
mapMusicCheckbox.OnClick = () => Game.Settings.Sound.MapMusic ^= true;
|
||||||
|
|
||||||
var soundEngineDropdown = audio.Get<DropDownButtonWidget>("SOUND_ENGINE");
|
var devices = Sound.AvailableDevices();
|
||||||
soundEngineDropdown.OnMouseDown = _ => ShowSoundEngineDropdown(soundEngineDropdown, soundSettings);
|
soundDevice = devices.FirstOrDefault(d => d.Engine == soundSettings.Engine && d.Device == soundSettings.Device) ?? devices.First();
|
||||||
soundEngineDropdown.GetText = () => soundSettings.Engine == "AL" ?
|
|
||||||
"OpenAL" : soundSettings.Engine == "Null" ? "None" : "OpenAL";
|
var audioDeviceDropdown = audio.Get<DropDownButtonWidget>("AUDIO_DEVICE");
|
||||||
|
audioDeviceDropdown.OnMouseDown = _ => ShowAudioDeviceDropdown(audioDeviceDropdown, soundSettings, devices);
|
||||||
|
audioDeviceDropdown.GetText = () => soundDevice.Label;
|
||||||
|
|
||||||
|
|
||||||
// Display
|
// Display
|
||||||
var display = bg.Get("DISPLAY_PANE");
|
var display = bg.Get("DISPLAY_PANE");
|
||||||
var gs = Game.Settings.Graphics;
|
var gs = Game.Settings.Graphics;
|
||||||
@@ -244,6 +246,8 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
int.TryParse(windowHeight.Text, out y);
|
int.TryParse(windowHeight.Text, out y);
|
||||||
gs.WindowedSize = new int2(x,y);
|
gs.WindowedSize = new int2(x,y);
|
||||||
int.TryParse(maxFrameRate.Text, out gs.MaxFramerate);
|
int.TryParse(maxFrameRate.Text, out gs.MaxFramerate);
|
||||||
|
soundSettings.Device = soundDevice.Device;
|
||||||
|
soundSettings.Engine = soundDevice.Engine;
|
||||||
Game.Settings.Save();
|
Game.Settings.Save();
|
||||||
Ui.CloseWindow();
|
Ui.CloseWindow();
|
||||||
onExit();
|
onExit();
|
||||||
@@ -325,7 +329,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
textBox.OnEnterKey = () => { textBox.YieldKeyboardFocus(); return true; };
|
textBox.OnEnterKey = () => { textBox.YieldKeyboardFocus(); return true; };
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool ShowRendererDropdown(DropDownButtonWidget dropdown, GraphicSettings s)
|
static bool ShowRendererDropdown(DropDownButtonWidget dropdown, GraphicSettings s)
|
||||||
{
|
{
|
||||||
var options = new Dictionary<string, string>()
|
var options = new Dictionary<string, string>()
|
||||||
{
|
{
|
||||||
@@ -346,20 +350,18 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool ShowSoundEngineDropdown(DropDownButtonWidget dropdown, SoundSettings s)
|
bool ShowAudioDeviceDropdown(DropDownButtonWidget dropdown, SoundSettings s, SoundDevice[] devices)
|
||||||
{
|
{
|
||||||
var options = new Dictionary<string, string>()
|
var i = 0;
|
||||||
{
|
var options = devices.ToDictionary(d => (i++).ToString(), d => d);
|
||||||
{ "OpenAL", "AL" },
|
|
||||||
{ "None", "Null" },
|
|
||||||
};
|
|
||||||
|
|
||||||
Func<string, ScrollItemWidget, ScrollItemWidget> setupItem = (o, itemTemplate) =>
|
Func<string, ScrollItemWidget, ScrollItemWidget> setupItem = (o, itemTemplate) =>
|
||||||
{
|
{
|
||||||
var item = ScrollItemWidget.Setup(itemTemplate,
|
var item = ScrollItemWidget.Setup(itemTemplate,
|
||||||
() => s.Engine == options[o],
|
() => soundDevice == options[o],
|
||||||
() => s.Engine = options[o]);
|
() => soundDevice = options[o]);
|
||||||
item.Get<LabelWidget>("LABEL").GetText = () => o;
|
|
||||||
|
item.Get<LabelWidget>("LABEL").GetText = () => options[o].Label;
|
||||||
return item;
|
return item;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -50,30 +50,44 @@ Container@SETTINGS_PANEL:
|
|||||||
Y:6
|
Y:6
|
||||||
Width:PARENT_RIGHT-35
|
Width:PARENT_RIGHT-35
|
||||||
Height:PARENT_BOTTOM-12
|
Height:PARENT_BOTTOM-12
|
||||||
|
Checkbox@SHOW_SHELLMAP:
|
||||||
|
X:15
|
||||||
|
Y:80
|
||||||
|
Width:200
|
||||||
|
Height:20
|
||||||
|
Font:Regular
|
||||||
|
Text:Show Shellmap
|
||||||
|
Checkbox@SHELLMAP_MUSIC:
|
||||||
|
X:15
|
||||||
|
Y:110
|
||||||
|
Width:200
|
||||||
|
Height:20
|
||||||
|
Font:Regular
|
||||||
|
Text:Shellmap Music
|
||||||
Label@DEBUG_TITLE:
|
Label@DEBUG_TITLE:
|
||||||
X:15
|
X:15
|
||||||
Y:100
|
Y:150
|
||||||
Width:340
|
Width:340
|
||||||
Font:Bold
|
Font:Bold
|
||||||
Text:Debug
|
Text:Debug
|
||||||
Align:Center
|
Align:Center
|
||||||
Checkbox@PERFTEXT_CHECKBOX:
|
Checkbox@PERFTEXT_CHECKBOX:
|
||||||
X:15
|
X:15
|
||||||
Y:120
|
Y:170
|
||||||
Width:300
|
Width:300
|
||||||
Height:20
|
Height:20
|
||||||
Font:Regular
|
Font:Regular
|
||||||
Text:Show Performance Text
|
Text:Show Performance Text
|
||||||
Checkbox@PERFGRAPH_CHECKBOX:
|
Checkbox@PERFGRAPH_CHECKBOX:
|
||||||
X:15
|
X:15
|
||||||
Y:150
|
Y:200
|
||||||
Width:300
|
Width:300
|
||||||
Height:20
|
Height:20
|
||||||
Font:Regular
|
Font:Regular
|
||||||
Text:Show Performance Graph
|
Text:Show Performance Graph
|
||||||
Checkbox@CHECKUNSYNCED_CHECKBOX:
|
Checkbox@CHECKUNSYNCED_CHECKBOX:
|
||||||
X:15
|
X:15
|
||||||
Y:180
|
Y:230
|
||||||
Width:300
|
Width:300
|
||||||
Height:20
|
Height:20
|
||||||
Font:Regular
|
Font:Regular
|
||||||
@@ -130,7 +144,7 @@ Container@SETTINGS_PANEL:
|
|||||||
MaxLength:5
|
MaxLength:5
|
||||||
Label@VIDEO_DESC:
|
Label@VIDEO_DESC:
|
||||||
X:375
|
X:375
|
||||||
Y:65
|
Y:68
|
||||||
Width:340
|
Width:340
|
||||||
Height:25
|
Height:25
|
||||||
Font:Tiny
|
Font:Tiny
|
||||||
@@ -138,58 +152,65 @@ Container@SETTINGS_PANEL:
|
|||||||
Text:Mode/Resolution changes will be applied after the game is restarted
|
Text:Mode/Resolution changes will be applied after the game is restarted
|
||||||
Checkbox@PIXELDOUBLE_CHECKBOX:
|
Checkbox@PIXELDOUBLE_CHECKBOX:
|
||||||
X:375
|
X:375
|
||||||
Y:90
|
Y:110
|
||||||
Width:200
|
Width:200
|
||||||
Height:20
|
Height:20
|
||||||
Font:Regular
|
Font:Regular
|
||||||
Text:Enable Pixel Doubling
|
Text:Enable Pixel Doubling
|
||||||
Checkbox@SHOW_SHELLMAP:
|
|
||||||
X:375
|
|
||||||
Y:120
|
|
||||||
Width:200
|
|
||||||
Height:20
|
|
||||||
Font:Regular
|
|
||||||
Text:Show Shellmap
|
|
||||||
Label@AUDIO_TITLE:
|
Label@AUDIO_TITLE:
|
||||||
X:375
|
X:375
|
||||||
Y:160
|
Y:150
|
||||||
Width:340
|
Width:340
|
||||||
Font:Bold
|
Font:Bold
|
||||||
Text:Sound
|
Text:Sound
|
||||||
Align:Center
|
Align:Center
|
||||||
Label@SOUND_LABEL:
|
Label@SOUND_LABEL:
|
||||||
X:375
|
X:375
|
||||||
Y:175
|
Y:164
|
||||||
Width:95
|
Width:95
|
||||||
Height:25
|
Height:25
|
||||||
Align:Right
|
Align:Right
|
||||||
Text:Sound Volume:
|
Text:Sound Volume:
|
||||||
Slider@SOUND_SLIDER:
|
Slider@SOUND_SLIDER:
|
||||||
X:475
|
X:475
|
||||||
Y:180
|
Y:170
|
||||||
Width:240
|
Width:240
|
||||||
Height:20
|
Height:20
|
||||||
Ticks:5
|
Ticks:5
|
||||||
Label@MUSIC_LABEL:
|
Label@MUSIC_LABEL:
|
||||||
X:375
|
X:375
|
||||||
Y:205
|
Y:194
|
||||||
Width:95
|
Width:95
|
||||||
Height:25
|
Height:25
|
||||||
Align:Right
|
Align:Right
|
||||||
Text:Music Volume:
|
Text:Music Volume:
|
||||||
Slider@MUSIC_SLIDER:
|
Slider@MUSIC_SLIDER:
|
||||||
X:475
|
X:475
|
||||||
Y:210
|
Y:200
|
||||||
Width:240
|
Width:240
|
||||||
Height:20
|
Height:20
|
||||||
Ticks:5
|
Ticks:5
|
||||||
Checkbox@SHELLMAP_MUSIC:
|
Label@AUDIO_DEVICE_LABEL:
|
||||||
X:375
|
X:375
|
||||||
Y:240
|
Y:229
|
||||||
Width:200
|
Width:75
|
||||||
Height:20
|
Height:20
|
||||||
|
Text:Audio Device:
|
||||||
|
DropDownButton@AUDIO_DEVICE:
|
||||||
|
X:475
|
||||||
|
Y:230
|
||||||
|
Width:240
|
||||||
|
Height:25
|
||||||
Font:Regular
|
Font:Regular
|
||||||
Text:Shellmap Music
|
Text:Default Device
|
||||||
|
Label@AUDIO_DESC:
|
||||||
|
X:375
|
||||||
|
Y:258
|
||||||
|
Width:340
|
||||||
|
Height:25
|
||||||
|
Font:Tiny
|
||||||
|
Align:Center
|
||||||
|
Text:Device changes will be applied after the game is restarted
|
||||||
Background@INPUT_CONTROLS:
|
Background@INPUT_CONTROLS:
|
||||||
Width:740
|
Width:740
|
||||||
Height:290
|
Height:290
|
||||||
|
|||||||
@@ -182,19 +182,24 @@ Background@SETTINGS_MENU:
|
|||||||
Width:200
|
Width:200
|
||||||
Height:20
|
Height:20
|
||||||
Text: Autoplay Music After Map Load
|
Text: Autoplay Music After Map Load
|
||||||
Label@SOUND_ENGINE_LABEL:
|
Label@AUDIO_DEVICE_LABEL:
|
||||||
X:0
|
X:0
|
||||||
Y:150
|
Y:150
|
||||||
Width:75
|
Width:75
|
||||||
Height:25
|
Height:25
|
||||||
Text:Sound Engine:
|
Text:Audio Device:
|
||||||
DropDownButton@SOUND_ENGINE:
|
DropDownButton@AUDIO_DEVICE:
|
||||||
X:100
|
X:100
|
||||||
Y:150
|
Y:150
|
||||||
Width:120
|
Width:250
|
||||||
Height:25
|
Height:25
|
||||||
Font:Regular
|
Font:Regular
|
||||||
Text:OpenAL
|
Label@AUDIO_DESC:
|
||||||
|
Y:175
|
||||||
|
Width:200
|
||||||
|
Height:25
|
||||||
|
Font:Tiny
|
||||||
|
Text:Device changes will be applied after the game is restarted.
|
||||||
Container@DISPLAY_PANE:
|
Container@DISPLAY_PANE:
|
||||||
X:37
|
X:37
|
||||||
Y:100
|
Y:100
|
||||||
|
|||||||
Reference in New Issue
Block a user