1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
//! # Overview
//! Alto is an idiomatic wrapper for the OpenAL 3D audio API and associated extensions (including EFX).
//! This documentation does not describe how to use the OpenAL API itself, but rather explains how
//! it has been adapted for rust and provides the native symbols associated with each function
//! so they can be cross-referenced with the official OpenAL documentation for full details.
//!
//! The core of the API is the [`Alto`](struct.Alto.html) struct. It has no analog in raw OpenAL and
//! represents an implementation of the API itself. From there, instances of familiar OpenAL objects
//! can be instantiated.
//!
//! # WARNING
//! Because Alto interacts with global C state via dynamic linking, having multiple versions of Alto in one project could lead to unsafety.
//! Please make sure only one version of Alto is in your dependency tree at any given time.


#[macro_use]
extern crate lazy_static;
extern crate parking_lot;
extern crate al_sys;

use std::error::Error as StdError;
use std::fmt;
use std::io;


mod alc;
pub use alc::*;


mod al;
pub use al::*;


pub mod ext;


pub mod efx;


pub mod sys {
	pub use al_sys::*;
}


/// An error as reported by `alcGetError` or `alGetError`, plus some Alto specific variants.
#[derive(Debug)]
pub enum AltoError {
	/// `ALC_INVALID_DEVICE`
	InvalidDevice,
	/// `ALC_INVALID_CONTEXT`
	InvalidContext,
	/// `AL_INVALID_NAME`
	InvalidName,
	/// `ALC/AL_INVALID_ENUM`
	InvalidEnum,
	/// `ALC/AL_INVALID_VALUE`
	InvalidValue,
	/// `AL_INVALID_OPERATION`
	InvalidOperation,
	/// `ALC/AL_OUT_OF_MEMORY`
	OutOfMemory,
	UnknownAlcError(sys::ALCint),
	UnknownAlError(sys::ALint),

	/// The underlying implementation is not compatible with the 1.1 spec. Alto specific.
	UnsupportedVersion{major: sys::ALCint, minor: sys::ALCint},
	/// The requested action can't be performed because the required extension is unavaiable. Alto specific.
	ExtensionNotPresent,
	/// Resource creation failed without setting an error code.
	NullError,
	/// A resource belongs to another device and is not eligible.
	WrongDevice,
	/// A resource belongs to another context and is not eligible.
	WrongContext,
	/// There was an underlying IO error, usually from a failure when loading the OpenAL dylib. Alto specific.
	Io(io::Error),
}


pub type AltoResult<T> = ::std::result::Result<T, AltoError>;


impl AltoError {
	fn from_alc(alc: sys::ALCenum) -> AltoError {
		match alc {
			sys::ALC_INVALID_DEVICE => AltoError::InvalidDevice,
			sys::ALC_INVALID_CONTEXT => AltoError::InvalidContext,
			sys::ALC_INVALID_ENUM => AltoError::InvalidEnum,
			sys::ALC_INVALID_VALUE => AltoError::InvalidValue,
			sys::ALC_OUT_OF_MEMORY => AltoError::OutOfMemory,
			e => AltoError::UnknownAlcError(e),
		}
	}


	fn from_al(al: sys::ALenum) -> AltoError {
		match al {
			sys::AL_INVALID_NAME => AltoError::InvalidName,
			sys::AL_INVALID_ENUM => AltoError::InvalidEnum,
			sys::AL_INVALID_VALUE => AltoError::InvalidValue,
			sys::AL_INVALID_OPERATION => AltoError::InvalidOperation,
			sys::AL_OUT_OF_MEMORY => AltoError::OutOfMemory,
			e => AltoError::UnknownAlError(e),
		}
	}
}


impl fmt::Display for AltoError {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "{}", self.description())
	}
}


impl StdError for AltoError {
	fn description(&self) -> &str {
		match *self {
			AltoError::InvalidDevice => "ALTO ERROR: ALC Invalid Device",
			AltoError::InvalidContext => "ALTO ERROR: ALC Invalid Context",
			AltoError::InvalidName => "ALTO ERROR: AL Invalid Name",
			AltoError::InvalidEnum => "ALTO ERROR: ALC Invalid Enum",
			AltoError::InvalidValue => "ALTO ERROR: ALC Invalid Value",
			AltoError::InvalidOperation => "ALTO ERROR: AL Invalid Operation",
			AltoError::OutOfMemory => "ALTO ERROR: ALC Out of Memory",
			AltoError::UnknownAlcError(..) => "ALTO ERROR: Unknown ALC error",
			AltoError::UnknownAlError(..) => "ALTO ERROR: Unknown AL error",

			AltoError::UnsupportedVersion{..} => "ALTO ERROR: Unsupported Version",
			AltoError::ExtensionNotPresent => "ALTO ERROR: Extension Not Present",
			AltoError::NullError => "ALTO ERROR: Return value is NULL with no error code",
			AltoError::WrongDevice => "ALTO ERROR: Resource used on wrong device",
			AltoError::WrongContext => "ALTO ERROR: Resource used on wrong device",
			AltoError::Io(ref io) => io.description(),
		}
	}
}


impl From<io::Error> for AltoError {
	fn from(io: io::Error) -> AltoError {
		AltoError::Io(io)
	}
}


impl From<ext::ExtensionError> for AltoError {
	fn from(_: ext::ExtensionError) -> AltoError {
		AltoError::ExtensionNotPresent
	}
}