Cleanup, haddocks

This commit is contained in:
jgk
2021-04-05 11:36:54 +02:00
parent dfee9b2f37
commit 772103f92c
9 changed files with 56 additions and 56 deletions
+39 -13
View File
@@ -1,45 +1,64 @@
{-|
Module : Sound
Description : Channel selection and storage
This module checks for empty channels and plays sounds on them, using data chunks loaded into an IntMap,
and sound specifications of type 'Sound' loaded into a Map.
Uses SDL.Mixer.
-}
module Sound
where
import Sound.Preload
import Control.Monad
import qualified SDL.Mixer as Mix
import Data.Maybe
import qualified Data.IntMap as IM
import qualified Data.Map as M
import Control.Monad
import Control.Lens
{- | Play sounds from a list of indices.
Each sound is played once if there is a free channel.
-}
playSoundQueue :: SoundData a -> [Int] -> IO ()
playSoundQueue sd ns = forM_ ns $ \n -> playIfFree (_loadedChunks sd IM.! n) Mix.Once
-- this can be cleaned up
{- | Given a chunk, attempt to play this on a free channel a given number of
times. Returns 'Just' the channel if succeeds.
-}
playIfFree :: Mix.Chunk -> Mix.Times -> IO (Maybe Mix.Channel)
playIfFree c times = do
mayChan <- Mix.getAvailable Mix.DefaultGroup
case mayChan of
Nothing -> return Nothing
Just i -> Just <$> Mix.playOn i times c
{- | Given a chunk and sound specification, play the chunk according to the specification
if there is a free channel.
On success return 'Just' an updated sound specification.
-}
playSoundIfFree :: Mix.Chunk -> Sound -> IO (Maybe Sound)
playSoundIfFree c s = case _soundTime s of
Just _ -> (playIfFree c Mix.Forever) >>= return . f
Just _ -> playIfFree c Mix.Forever >>= return . f
Nothing -> playIfFree c Mix.Once >>= return . f
where
f :: Maybe Mix.Channel -> Maybe Sound
f = fmap (\chan -> (s & soundChannel .~ Just chan))
f = fmap ( \chan -> s & soundChannel ?~ chan)
{- Stop a channel if it was playing.
Always returns 'IO' 'Nothing'.
-}
haltMaybe :: Maybe Mix.Channel -> IO (Maybe Sound)
haltMaybe (Just x) = Mix.halt x >> return Nothing
haltMaybe Nothing = return Nothing
-- logic: check if sound is playing:
-- if so, decrement timers, and/or stop playing and remove
-- if not, check if there is free channel:
-- if so, start playing
-- if not, remove sound
{- Play a sound according to it's specification.
Logic: check if sound is playing:
- If so, decrement timers, and/or stop playing and remove
- If not, check if there is free channel:
- If so, start playing
- If not, remove sound.
-}
playSound :: SoundData a -> Sound -> IO (Maybe Sound)
playSound sd s = case _soundChannel s of
Just i -> case _soundTime s of
@@ -51,15 +70,22 @@ playSound sd s = case _soundChannel s of
)
Nothing -> playSoundIfFree (_loadedChunks sd IM.! _soundType s) s
{- Play all sounds and create new sound data.
-}
playSounds :: SoundData a -> IO (SoundData a)
playSounds sd = do
newSounds <- mapM (playSound sd) (_playingSounds sd)
return $ sd & playingSounds .~ M.mapMaybe id newSounds
{- Update sound specifications by overwriting an old Map with a new Map.
Copies any information about channels from the old Map to the new Map.
-}
updatePlaying :: Ord a => M.Map a Sound -> M.Map a Sound -> M.Map a Sound
updatePlaying new old = M.unionWith f new old
where
f newSound oldSound = newSound {_soundChannel = _soundChannel oldSound}
{- Start playing new sounds and update sound specifications.
-}
playAndUpdate :: Ord a => M.Map a Sound -> SoundData a -> IO (SoundData a)
playAndUpdate new sd = playSounds $ over playingSounds (updatePlaying new) sd