mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-01-23 09:34:35 -05:00
6b43c396bd
Adds in the option to force OpenAL. More specifically, adds in the code for the option to have an effect.
143 lines
3.9 KiB
C#
143 lines
3.9 KiB
C#
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
|
|
using System;
|
|
using System.IO;
|
|
using System.Threading;
|
|
using SharpWave;
|
|
using SharpWave.Codecs.Vorbis;
|
|
|
|
namespace ClassicalSharp.Audio {
|
|
|
|
public sealed partial class AudioPlayer : IGameComponent {
|
|
|
|
IAudioOutput musicOut;
|
|
IAudioOutput[] monoOutputs, stereoOutputs;
|
|
string[] files, musicFiles;
|
|
Thread musicThread;
|
|
Game game;
|
|
|
|
public void Init(Game game) {
|
|
this.game = game;
|
|
string path = Path.Combine(Program.AppDirectory, "audio");
|
|
if (Directory.Exists(path))
|
|
files = Directory.GetFiles(path);
|
|
else
|
|
files = new string[0];
|
|
|
|
game.UseMusic = Options.GetBool(OptionsKey.UseMusic, false);
|
|
SetMusic(game.UseMusic);
|
|
game.UseSound = Options.GetBool(OptionsKey.UseSound, false);
|
|
SetSound(game.UseSound);
|
|
game.UserEvents.BlockChanged += PlayBlockSound;
|
|
}
|
|
|
|
public void Ready(Game game) { }
|
|
public void Reset(Game game) { }
|
|
public void OnNewMap(Game game) { }
|
|
public void OnNewMapLoaded(Game game) { }
|
|
|
|
public void SetMusic(bool enabled) {
|
|
if (enabled)
|
|
InitMusic();
|
|
else
|
|
DisposeMusic();
|
|
}
|
|
|
|
const StringComparison comp = StringComparison.OrdinalIgnoreCase;
|
|
void InitMusic() {
|
|
int musicCount = 0;
|
|
for (int i = 0; i < files.Length; i++) {
|
|
if (files[i].EndsWith(".ogg", comp)) musicCount++;
|
|
}
|
|
|
|
musicFiles = new string[musicCount];
|
|
for (int i = 0, j = 0; i < files.Length; i++) {
|
|
if (!files[i].EndsWith(".ogg", comp)) continue;
|
|
musicFiles[j] = files[i]; j++;
|
|
}
|
|
|
|
disposingMusic = false;
|
|
musicThread = MakeThread(DoMusicThread, ref musicOut,
|
|
"ClassicalSharp.DoMusic");
|
|
}
|
|
|
|
EventWaitHandle musicHandle = new EventWaitHandle(false, EventResetMode.AutoReset);
|
|
void DoMusicThread() {
|
|
if (musicFiles.Length == 0) return;
|
|
Random rnd = new Random();
|
|
while (!disposingMusic) {
|
|
string file = musicFiles[rnd.Next(0, musicFiles.Length)];
|
|
string path = Path.Combine(Program.AppDirectory, file);
|
|
Utils.LogDebug("playing music file: " + file);
|
|
|
|
using (FileStream fs = File.OpenRead(path)) {
|
|
OggContainer container = new OggContainer(fs);
|
|
try {
|
|
musicOut.PlayStreaming(container);
|
|
} catch (InvalidOperationException ex) {
|
|
HandleMusicError(ex);
|
|
return;
|
|
} catch (Exception ex) {
|
|
ErrorHandler.LogError("AudioPlayer.DoMusicThread()", ex);
|
|
game.Chat.Add("&cError while trying to play music file " + Path.GetFileName(file));
|
|
}
|
|
}
|
|
if (disposingMusic) break;
|
|
|
|
int delay = 2000 * 60 + rnd.Next(0, 5000 * 60);
|
|
musicHandle.WaitOne(delay, false);
|
|
}
|
|
}
|
|
|
|
void HandleMusicError(InvalidOperationException ex) {
|
|
ErrorHandler.LogError("AudioPlayer.DoMusicThread()", ex);
|
|
if (ex.Message == "No audio devices found")
|
|
game.Chat.Add("&cNo audio devices found, disabling music.");
|
|
else
|
|
game.Chat.Add("&cAn error occured when trying to play music, disabling music.");
|
|
|
|
SetMusic(false);
|
|
game.UseMusic = false;
|
|
}
|
|
|
|
bool disposingMusic;
|
|
public void Dispose() {
|
|
DisposeMusic();
|
|
DisposeSound();
|
|
musicHandle.Close();
|
|
game.UserEvents.BlockChanged -= PlayBlockSound;
|
|
}
|
|
|
|
void DisposeMusic() {
|
|
disposingMusic = true;
|
|
musicHandle.Set();
|
|
DisposeOf(ref musicOut, ref musicThread);
|
|
}
|
|
|
|
Thread MakeThread(ThreadStart func, ref IAudioOutput output, string name) {
|
|
output = GetPlatformOut();
|
|
output.Create(10);
|
|
|
|
Thread thread = new Thread(func);
|
|
thread.Name = name;
|
|
thread.IsBackground = true;
|
|
thread.Start();
|
|
return thread;
|
|
}
|
|
|
|
IAudioOutput GetPlatformOut() {
|
|
if (OpenTK.Configuration.RunningOnWindows && !Options.GetBool(OptionsKey.ForceOpenAL, false))
|
|
return new WinMmOut();
|
|
return new OpenALOut();
|
|
}
|
|
|
|
void DisposeOf(ref IAudioOutput output, ref Thread thread) {
|
|
if (output == null) return;
|
|
output.Stop();
|
|
thread.Join();
|
|
|
|
output.Dispose();
|
|
output = null;
|
|
thread = null;
|
|
}
|
|
}
|
|
}
|