mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-29 00:23:31 -04:00
144 lines
3.9 KiB
C#
144 lines
3.9 KiB
C#
// ClassicalSharp copyright 2014-2016 UnknownShadow200 | Licensed under MIT
|
|
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 )
|
|
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;
|
|
}
|
|
}
|
|
}
|