-------------------------------------------------------------------------------- -- | -- Module : Sound.OpenAL.ALC.Errors -- Copyright : (c) Sven Panne 2003-2009 -- License : BSD-style (see the file LICENSE) -- -- Maintainer : sven.panne@aedion.de -- Stability : stable -- Portability : portable -- -- This module corresponds to section 6.3.6 (Query for Error Conditions) of the -- OpenAL Specification and Reference (version 1.1). -- -------------------------------------------------------------------------------- module Sound.OpenAL.ALC.Errors ( ALCError(..), ALCErrorCategory(..), alcErrors ) where import Data.StateVar import Sound.OpenAL.ALC.BasicTypes ( ALCenum ) import Sound.OpenAL.ALC.Device ( Device ) import Sound.OpenAL.ALC.QueryUtils ( StringQuery(..), getString ) import Sound.OpenAL.Constants ( alc_NO_ERROR, alc_INVALID_DEVICE, alc_INVALID_CONTEXT, alc_INVALID_ENUM, alc_INVALID_VALUE, alc_OUT_OF_MEMORY, alc_INVALID_OPERATION ) import Sound.OpenAL.Config ( ALCdevice, marshalDevice ) -------------------------------------------------------------------------------- -- | ALC errors consist of a general error category and a description of what -- went wrong. data ALCError = ALCError ALCErrorCategory String deriving ( Eq, Ord, Show ) -------------------------------------------------------------------------------- -- | General ALC error categories. data ALCErrorCategory = ALCInvalidEnum | ALCInvalidValue | ALCInvalidOperation | ALCInvalidDevice | ALCInvalidContext | ALCOutOfMemory deriving ( Eq, Ord, Show ) unmarshalALCErrorCategory :: ALCenum -> ALCErrorCategory unmarshalALCErrorCategory x | x == alc_INVALID_ENUM = ALCInvalidEnum | x == alc_INVALID_VALUE = ALCInvalidValue | x == alc_INVALID_OPERATION = ALCInvalidOperation | x == alc_INVALID_DEVICE = ALCInvalidDevice | x == alc_INVALID_CONTEXT = ALCInvalidContext | x == alc_OUT_OF_MEMORY = ALCOutOfMemory | otherwise = error ("unmarshalALCErrorCategory: illegal value " ++ show x) -------------------------------------------------------------------------------- -- | OpenAL detects only a subset of those conditions that could be considered -- errors. This is because in many cases error checking would adversely impact -- the performance of an error-free program. The state variable 'alcErrors' is -- used to obtain error information. When an error is detected by ALC, a flag is -- set and the error code is recorded. Further errors, if they occur, do not -- affect this recorded code. When 'alcErrors' is read, the error for the given -- device is returned and the flag is cleared, so that a further error will -- again record its code. If reading 'alcErrors' returns @\[\]@ then there has -- been no detectable error since the last time 'alcErrors' (or since the ALC -- was initialized). -- -- When an error flag is set, results of ALC operations are undefined only if -- 'ALCOutOfMemory' has occurred. In other cases, the command generating the -- error is ignored so that it has no effect on ALC state or output buffer -- contents. If the error generating command returns a value, it returns zero. -- If the generating command modifies values through a pointer argument, no -- change is made to these values. These error semantics apply only to ALC -- errors, not to system errors such as memory access errors. alcErrors :: Device -> GettableStateVar [ALCError] alcErrors device = makeGettableStateVar $ do c <- alcGetError (marshalDevice device) if c == alc_NO_ERROR then return [] else do s <- getString (Just device) (ALCErrorCategory c) return [ ALCError (unmarshalALCErrorCategory c) s ] foreign import CALLCONV unsafe "alcGetError" alcGetError :: ALCdevice -> IO ALCenum