#region --- License --- /* Copyright (c) 2008 the OpenTK team * See license.txt for license details * http://www.opentk.com */ #endregion using System; using System.Collections.Generic; using System.Text; using OpenTK.OpenAL; using OpenTK.OpenAL.Enums; namespace OpenTK.Audio { /// /// Provides methods to create and use an audio context. /// public sealed class AudioContext : IDisposable { #region --- Fields --- bool disposed; static List available_devices; IntPtr device_handle, context_handle; static object audio_context_lock = new object(); #endregion #region --- Constructors --- // Runs before the actual class constructor, to load available devices. static AudioContext() { LoadAvailableDevices(); } /// Constructs a new AudioContext, using the default audio device. /// Occurs when no audio devices are available. public AudioContext() { if (available_devices.Count == 0) throw new NotSupportedException("No audio hardware is available."); CreateContext(available_devices[0], 44100, 0, false); } /// Constructs a new AudioContext, using the specified audio device. /// The name of the audio device to use. /// /// Use AudioContext.AvailableDevices to obtain a list of all available audio /// devices. /// public AudioContext(string device) { } #endregion #region --- Private Members --- #region static void LoadAvailableDevices() // Loads all available audio devices into the available_devices array. static void LoadAvailableDevices() { lock (audio_context_lock) { if (available_devices == null) { available_devices = new List(); available_devices.AddRange(Alc.GetString(IntPtr.Zero, OpenTK.OpenAL.Enums.AlcGetStringList.AllDevicesSpecifier)); } } } #endregion #region void CreateContext(string device) /// /// Creates the audio context using the specified device. /// The device descriptor obtained through AudioContext.AvailableDevices. /// Frequency for mixing output buffer, in units of Hz. /// Refresh intervalls, in units of Hz. /// Flag, indicating a synchronous context. /// /// Occurs when the specified device is not available, or is in use by another program. /// /// /// Occurs when an audio context could not be created with the specified parameters. /// void CreateContext(string device, int freq, int refresh, bool sync) { if (String.IsNullOrEmpty(device)) throw new ArgumentNullException("device"); if (freq < 0) throw new ArgumentOutOfRangeException("freq", freq, "Should be greater than zero"); if (refresh < 0) throw new ArgumentOutOfRangeException("refresh", refresh, "Should be greater than zero"); device_handle = Alc.OpenDevice(device); if (device_handle == IntPtr.Zero) throw new InvalidAudioDeviceException(); List attributes = new List(); if (freq != 0) { attributes.Add((int)AlcContextAttributes.Frequency); attributes.Add(freq); } if (refresh != 0) { attributes.Add((int)AlcContextAttributes.Refresh); attributes.Add(refresh); } attributes.Add((int)AlcContextAttributes.Frequency); attributes.Add(sync ? 1 : 0); context_handle = Alc.CreateContext(device_handle, attributes.ToArray()); if (context_handle == IntPtr.Zero) { Alc.CloseDevice(device_handle); throw new InvalidAudioContextException(); } } #endregion #endregion #region --- Public Members --- #region public static string[] AvailableDevices /// /// Gets a System.String array containing all available audio devices. /// public static IEnumerable AvailableDevices { get { return (IEnumerable)available_devices; } } #endregion #endregion #region --- IDisposable Members --- public void Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } void Dispose(bool manual) { if (!disposed) { if (manual) { } disposed = true; } } ~AudioContext() { this.Dispose(false); } #endregion } #region --- Exceptions --- public class InvalidAudioDeviceException : Exception { public InvalidAudioDeviceException() : base("The specified audio device does not exist or is tied up by another application.") { } } public class InvalidAudioContextException : Exception { public InvalidAudioContextException() : base("The audio context could not be created with the specified parameters.") { } } #endregion }