{- | Shared vocabulary for the audio subsystem: the commands sent to a
playback worker ('AudioCommand'), what state that worker reports back
('PlaybackStatus'), and how a backend is selected and configured
('BackendType', 'AudioConfig'). Kept separate from "Termtab.Audio" so
that "Termtab.Audio.Playback" and "Termtab.Audio.PlaybackThread" can
depend on just the vocabulary without pulling in a concrete backend.
-}
module Termtab.Audio.Types (
    AudioCommand (..),
    PlaybackStatus (..),
    AudioConfig (..),
    BackendType (..),
) where

import Termtab.Types (MeasureIndex, MidiChannel, MidiProgram, Pitch, Velocity)

{- | A message sent to "Termtab.Audio.PlaybackThread"'s worker loop. The
@CmdNote*@\/@CmdProgramChange@ variants are low-level one-off events
(mirroring the synchronous @engine*@ calls in "Termtab.Audio"); @CmdPlay@
\/ @CmdStop@ \/ @CmdPause@ \/ @CmdSeek@ control song-level transport
state; 'CmdShutdown' tells the worker thread to exit.
-}
data AudioCommand
    = CmdNoteOn MidiChannel Pitch Velocity
    | CmdNoteOff MidiChannel Pitch
    | CmdProgramChange MidiChannel MidiProgram
    | CmdPlay
    | CmdStop
    | CmdPause
    | CmdSeek MeasureIndex
    | CmdShutdown
    deriving (Int -> AudioCommand -> ShowS
[AudioCommand] -> ShowS
AudioCommand -> String
(Int -> AudioCommand -> ShowS)
-> (AudioCommand -> String)
-> ([AudioCommand] -> ShowS)
-> Show AudioCommand
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> AudioCommand -> ShowS
showsPrec :: Int -> AudioCommand -> ShowS
$cshow :: AudioCommand -> String
show :: AudioCommand -> String
$cshowList :: [AudioCommand] -> ShowS
showList :: [AudioCommand] -> ShowS
Show, AudioCommand -> AudioCommand -> Bool
(AudioCommand -> AudioCommand -> Bool)
-> (AudioCommand -> AudioCommand -> Bool) -> Eq AudioCommand
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: AudioCommand -> AudioCommand -> Bool
== :: AudioCommand -> AudioCommand -> Bool
$c/= :: AudioCommand -> AudioCommand -> Bool
/= :: AudioCommand -> AudioCommand -> Bool
Eq)

{- | Current transport state of song playback, as reported by
"Termtab.Audio.PlaybackThread" for the UI to display.
-}
data PlaybackStatus
    = Playing
    | Paused
    | Stopped
    deriving (Int -> PlaybackStatus -> ShowS
[PlaybackStatus] -> ShowS
PlaybackStatus -> String
(Int -> PlaybackStatus -> ShowS)
-> (PlaybackStatus -> String)
-> ([PlaybackStatus] -> ShowS)
-> Show PlaybackStatus
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PlaybackStatus -> ShowS
showsPrec :: Int -> PlaybackStatus -> ShowS
$cshow :: PlaybackStatus -> String
show :: PlaybackStatus -> String
$cshowList :: [PlaybackStatus] -> ShowS
showList :: [PlaybackStatus] -> ShowS
Show, PlaybackStatus -> PlaybackStatus -> Bool
(PlaybackStatus -> PlaybackStatus -> Bool)
-> (PlaybackStatus -> PlaybackStatus -> Bool) -> Eq PlaybackStatus
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PlaybackStatus -> PlaybackStatus -> Bool
== :: PlaybackStatus -> PlaybackStatus -> Bool
$c/= :: PlaybackStatus -> PlaybackStatus -> Bool
/= :: PlaybackStatus -> PlaybackStatus -> Bool
Eq)

{- | Backend configuration needed to start an 'Termtab.Audio.AudioEngine'.
Currently just the SoundFont (@.sf2@) file FluidSynth should load.
-}
newtype AudioConfig = AudioConfig
    { AudioConfig -> String
acSoundFontPath :: FilePath
    }
    deriving (Int -> AudioConfig -> ShowS
[AudioConfig] -> ShowS
AudioConfig -> String
(Int -> AudioConfig -> ShowS)
-> (AudioConfig -> String)
-> ([AudioConfig] -> ShowS)
-> Show AudioConfig
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> AudioConfig -> ShowS
showsPrec :: Int -> AudioConfig -> ShowS
$cshow :: AudioConfig -> String
show :: AudioConfig -> String
$cshowList :: [AudioConfig] -> ShowS
showList :: [AudioConfig] -> ShowS
Show, AudioConfig -> AudioConfig -> Bool
(AudioConfig -> AudioConfig -> Bool)
-> (AudioConfig -> AudioConfig -> Bool) -> Eq AudioConfig
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: AudioConfig -> AudioConfig -> Bool
== :: AudioConfig -> AudioConfig -> Bool
$c/= :: AudioConfig -> AudioConfig -> Bool
/= :: AudioConfig -> AudioConfig -> Bool
Eq)

{- | Which synthesis backend to use. See 'Termtab.Audio.startAudioEngine' —
only 'BackendFluidSynth' is currently implemented.
-}
data BackendType
    = BackendFluidSynth
    | BackendPortMidi
    deriving (Int -> BackendType -> ShowS
[BackendType] -> ShowS
BackendType -> String
(Int -> BackendType -> ShowS)
-> (BackendType -> String)
-> ([BackendType] -> ShowS)
-> Show BackendType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> BackendType -> ShowS
showsPrec :: Int -> BackendType -> ShowS
$cshow :: BackendType -> String
show :: BackendType -> String
$cshowList :: [BackendType] -> ShowS
showList :: [BackendType] -> ShowS
Show, BackendType -> BackendType -> Bool
(BackendType -> BackendType -> Bool)
-> (BackendType -> BackendType -> Bool) -> Eq BackendType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: BackendType -> BackendType -> Bool
== :: BackendType -> BackendType -> Bool
$c/= :: BackendType -> BackendType -> Bool
/= :: BackendType -> BackendType -> Bool
Eq)