{-# LANGUAGE ViewPatterns #-}
module Cmd.Msg where
import Control.DeepSeq (deepseq)
import qualified Data.Map as Map
import qualified Data.Text as Text
import qualified Data.Vector as Vector
import qualified System.IO as IO
import qualified Util.Log as Log
import qualified Util.Pretty as Pretty
import qualified App.ReplProtocol as ReplProtocol
import qualified Cmd.InputNote as InputNote
import qualified Cmd.KeyLayouts as KeyLayouts
import qualified Derive.Derive as Derive
import qualified Derive.Score as Score
import qualified Derive.ScoreT as ScoreT
import qualified Derive.TrackWarp as TrackWarp
import qualified Local.KeyLayout
import qualified Midi.Midi as Midi
import qualified Perform.Transport as Transport
import qualified Synth.ImGc as ImGc
import qualified Ui.Id as Id
import qualified Ui.Key as Key
import qualified Ui.Track as Track
import qualified Ui.Ui as Ui
import qualified Ui.UiMsg as UiMsg
import Control.Monad
import Global
import Types
data Msg =
Ui UiMsg.UiMsg
| Midi Midi.ReadMessage
| InputNote InputNote.Input
| Transport Transport.Status
| DeriveStatus BlockId DeriveStatus
| Socket IO.Handle ReplProtocol.Query
deriving (Int -> Msg -> ShowS
[Msg] -> ShowS
Msg -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Msg] -> ShowS
$cshowList :: [Msg] -> ShowS
show :: Msg -> String
$cshow :: Msg -> String
showsPrec :: Int -> Msg -> ShowS
$cshowsPrec :: Int -> Msg -> ShowS
Show)
show_short :: Msg -> Text
show_short :: Msg -> Text
show_short = \case
Ui UiMsg
ui -> UiMsg -> Text
UiMsg.show_short UiMsg
ui
Midi ReadMessage
midi -> forall a. Pretty a => a -> Text
pretty ReadMessage
midi
InputNote Input
note -> forall a. Pretty a => a -> Text
pretty Input
note
Transport Status
status -> forall a. Pretty a => a -> Text
pretty Status
status
DeriveStatus BlockId
bid DeriveStatus
status -> forall a. Ident a => a -> Text
Id.ident_text BlockId
bid forall a. Semigroup a => a -> a -> a
<> Text
":" forall a. Semigroup a => a -> a -> a
<> case DeriveStatus
status of
DeriveStatus
OutOfDate -> Text
"OutOfDate"
DeriveStatus
Deriving -> Text
"Deriving"
DeriveComplete {} -> Text
"DeriveComplete"
status :: DeriveStatus
status@(ImStatus {}) -> forall a. Pretty a => a -> Text
pretty DeriveStatus
status
Socket Handle
_hdl Query
query -> forall a. Pretty a => a -> Text
pretty Query
query
instance Pretty Msg where
pretty :: Msg -> Text
pretty = \case
Ui UiMsg
msg -> Text
"Ui: " forall a. Semigroup a => a -> a -> a
<> forall a. Pretty a => a -> Text
pretty UiMsg
msg
Midi ReadMessage
msg -> Text
"Midi: " forall a. Semigroup a => a -> a -> a
<> forall a. Pretty a => a -> Text
pretty ReadMessage
msg
InputNote Input
msg -> Text
"Input: " forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> Text
showt Input
msg
Transport Status
status -> forall a. Pretty a => a -> Text
pretty Status
status
DeriveStatus BlockId
bid DeriveStatus
status -> Text
"DeriveStatus: " forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> Text
showt BlockId
bid forall a. Semigroup a => a -> a -> a
<> Text
": "
forall a. Semigroup a => a -> a -> a
<> forall a. Pretty a => a -> Text
pretty DeriveStatus
status
Socket Handle
_hdl Query
query -> Text
"Socket: " forall a. Semigroup a => a -> a -> a
<> forall a. Pretty a => a -> Text
pretty Query
query
data DeriveStatus =
OutOfDate
| Deriving
| DeriveComplete !Performance !ImStarted
| ImStatus !BlockId !(Set TrackId) !ImStatus
deriving (Int -> DeriveStatus -> ShowS
[DeriveStatus] -> ShowS
DeriveStatus -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [DeriveStatus] -> ShowS
$cshowList :: [DeriveStatus] -> ShowS
show :: DeriveStatus -> String
$cshow :: DeriveStatus -> String
showsPrec :: Int -> DeriveStatus -> ShowS
$cshowsPrec :: Int -> DeriveStatus -> ShowS
Show)
instance Pretty DeriveStatus where
pretty :: DeriveStatus -> Text
pretty = \case
ImStatus BlockId
block_id Set TrackId
track_ids ImStatus
status ->
forall a. Pretty a => a -> Text
pretty BlockId
block_id forall a. Semigroup a => a -> a -> a
<> Text
":" forall a. Semigroup a => a -> a -> a
<> forall a. Pretty a => a -> Text
pretty Set TrackId
track_ids forall a. Semigroup a => a -> a -> a
<> Text
":" forall a. Semigroup a => a -> a -> a
<> forall a. Pretty a => a -> Text
pretty ImStatus
status
DeriveStatus
status -> forall a. Show a => a -> Text
showt DeriveStatus
status
data ImStarted = ImStarted
| ImUnnecessary
deriving (Int -> ImStarted -> ShowS
[ImStarted] -> ShowS
ImStarted -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ImStarted] -> ShowS
$cshowList :: [ImStarted] -> ShowS
show :: ImStarted -> String
$cshow :: ImStarted -> String
showsPrec :: Int -> ImStarted -> ShowS
$cshowsPrec :: Int -> ImStarted -> ShowS
Show)
data ImStatus =
ImRenderingRange !ScoreT.Instrument !RealTime !RealTime
| ImWaveformsCompleted ![Track.WaveformChunk]
| ImComplete !Bool !(Maybe ImGc.Stats)
deriving (Int -> ImStatus -> ShowS
[ImStatus] -> ShowS
ImStatus -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ImStatus] -> ShowS
$cshowList :: [ImStatus] -> ShowS
show :: ImStatus -> String
$cshow :: ImStatus -> String
showsPrec :: Int -> ImStatus -> ShowS
$cshowsPrec :: Int -> ImStatus -> ShowS
Show)
instance Pretty ImStatus where
pretty :: ImStatus -> Text
pretty = \case
ImRenderingRange Instrument
inst RealTime
start RealTime
end ->
forall a. Pretty a => a -> Text
pretty Instrument
inst forall a. Semigroup a => a -> a -> a
<> Text
"(" forall a. Semigroup a => a -> a -> a
<> forall a. Pretty a => a -> Text
pretty RealTime
start forall a. Semigroup a => a -> a -> a
<> Text
"--" forall a. Semigroup a => a -> a -> a
<> forall a. Pretty a => a -> Text
pretty RealTime
end forall a. Semigroup a => a -> a -> a
<> Text
")"
ImWaveformsCompleted [WaveformChunk]
waves -> Text
"ImWaveformsCompleted:"
forall a. Semigroup a => a -> a -> a
<> Text -> [Text] -> Text
Text.intercalate Text
"," (forall a b. (a -> b) -> [a] -> [b]
map (String -> Text
txt forall b c a. (b -> c) -> (a -> b) -> a -> c
. WaveformChunk -> String
Track._filename) [WaveformChunk]
waves)
ImComplete Bool
failed Maybe Stats
_ -> Text
"ImComplete" forall a. Semigroup a => a -> a -> a
<> if Bool
failed then Text
"(failed)" else Text
""
data Performance = Performance {
Performance -> Cache
perf_derive_cache :: Derive.Cache
, Performance -> Vector Event
perf_events :: Vector.Vector Score.Event
, Performance -> [Msg]
perf_logs :: [Log.Msg]
, Performance -> Bool
perf_logs_written :: Bool
, Performance -> TrackDynamic
perf_track_dynamic :: Derive.TrackDynamic
, Performance -> [Integrated]
perf_integrated :: [Derive.Integrated]
, Performance -> ScoreDamage
perf_damage :: Derive.ScoreDamage
, Performance -> [TrackWarp]
perf_warps :: [TrackWarp.TrackWarp]
, Performance -> TrackSignals
perf_track_signals :: Track.TrackSignals
, Performance -> BlockDeps
perf_block_deps :: Derive.BlockDeps
, Performance -> Map TrackId (Set Instrument)
perf_track_instruments :: Map TrackId (Set ScoreT.Instrument)
, Performance -> State
perf_ui_state :: Ui.State
}
force_performance :: Performance -> ()
force_performance :: Performance -> ()
force_performance (Performance Cache
_cache Vector Event
events [Msg]
logs Bool
_logs_written TrackDynamic
track_dyn
[Integrated]
_integrated ScoreDamage
_damage [TrackWarp]
warps TrackSignals
track_sigs BlockDeps
block_deps Map TrackId (Set Instrument)
_track_insts State
ui_state) =
[Msg]
logs forall a b. NFData a => a -> b -> b
`deepseq` Vector Event
events forall a b. NFData a => a -> b -> b
`deepseq` [TrackWarp]
warps forall a b. NFData a => a -> b -> b
`deepseq` TrackDynamic
track_dyn
forall a b. NFData a => a -> b -> b
`deepseq` TrackSignals
track_sigs forall a b. NFData a => a -> b -> b
`deepseq` BlockDeps
block_deps forall a b. NFData a => a -> b -> b
`deepseq` State
ui_state
forall a b. NFData a => a -> b -> b
`deepseq` ()
instance Show Performance where
show :: Performance -> String
show Performance
perf = String
"((Performance " forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> String
show (forall a. Vector a -> Int
Vector.length (Performance -> Vector Event
perf_events Performance
perf))
forall a. Semigroup a => a -> a -> a
<> String
" events " forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> String
show (forall (t :: * -> *) a. Foldable t => t a -> Int
length (Performance -> [Msg]
perf_logs Performance
perf)) forall a. Semigroup a => a -> a -> a
<> String
" logs))"
instance Pretty Performance where
format :: Performance -> Doc
format (Performance Cache
cache Vector Event
events [Msg]
logs Bool
logs_written TrackDynamic
track_dynamic
[Integrated]
integrated ScoreDamage
damage [TrackWarp]
warps TrackSignals
track_signals BlockDeps
block_deps Map TrackId (Set Instrument)
track_insts
State
_ui_state) =
Doc -> [(Text, Doc)] -> Doc
Pretty.record Doc
"Performance"
[ (Text
"cache", forall a. Pretty a => a -> Doc
Pretty.format forall a b. (a -> b) -> a -> b
$ forall k a. Map k a -> [k]
Map.keys forall a b. (a -> b) -> a -> b
$ (\(Derive.Cache Map CacheKey Cached
c) -> Map CacheKey Cached
c) Cache
cache)
, (Text
"events", forall a. Pretty a => a -> Doc
Pretty.format (forall a. Vector a -> Int
Vector.length Vector Event
events))
, (Text
"logs", forall a. Pretty a => a -> Doc
Pretty.format [Msg]
logs)
, (Text
"logs_written", forall a. Pretty a => a -> Doc
Pretty.format Bool
logs_written)
, (Text
"track_dynamic", forall a. Pretty a => a -> Doc
Pretty.format TrackDynamic
track_dynamic)
, (Text
"integrated", forall a. Pretty a => a -> Doc
Pretty.format [Integrated]
integrated)
, (Text
"damage", forall a. Pretty a => a -> Doc
Pretty.format ScoreDamage
damage)
, (Text
"warps", forall a. Pretty a => a -> Doc
Pretty.format [TrackWarp]
warps)
, (Text
"track_signals", forall a. Pretty a => a -> Doc
Pretty.format TrackSignals
track_signals)
, (Text
"block_deps", forall a. Pretty a => a -> Doc
Pretty.format BlockDeps
block_deps)
, (Text
"track_instruments", forall a. Pretty a => a -> Doc
Pretty.format Map TrackId (Set Instrument)
track_insts)
]
mouse :: Msg -> Maybe UiMsg.MouseEvent
mouse :: Msg -> Maybe MouseEvent
mouse (Ui (UiMsg.UiMsg Context
_ (UiMsg.MsgEvent (UiMsg.Mouse MouseEvent
mouse)))) =
forall a. a -> Maybe a
Just MouseEvent
mouse
mouse Msg
_ = forall a. Maybe a
Nothing
mouse_down :: Msg -> Bool
mouse_down :: Msg -> Bool
mouse_down Msg
msg = case Msg -> Maybe MouseEvent
mouse Msg
msg of
Just (UiMsg.MouseEvent { mouse_state :: MouseEvent -> MouseState
UiMsg.mouse_state = UiMsg.MouseDown Int
_ }) -> Bool
True
Maybe MouseEvent
_ -> Bool
False
kbd :: Msg -> Maybe (UiMsg.KbdState, [Key.Modifier], Key.Key, Maybe Char)
kbd :: Msg -> Maybe (KbdState, [Modifier], Key, Maybe Char)
kbd (Ui (UiMsg.UiMsg Context
_ (UiMsg.MsgEvent (UiMsg.Kbd KbdState
state [Modifier]
mods Key
key Maybe Char
text)))) =
forall a. a -> Maybe a
Just (KbdState
state, [Modifier]
mods, Key
key, Maybe Char
text)
kbd Msg
_ = forall a. Maybe a
Nothing
key :: Msg -> Maybe (UiMsg.KbdState, Key.Key)
key :: Msg -> Maybe (KbdState, Key)
key (Msg -> Maybe (KbdState, [Modifier], Key, Maybe Char)
kbd -> Just (KbdState
state, [Modifier]
_, Key
key, Maybe Char
_)) = forall a. a -> Maybe a
Just (KbdState
state, Key
key)
key Msg
_ = forall a. Maybe a
Nothing
key_down :: Msg -> Maybe Key.Key
key_down :: Msg -> Maybe Key
key_down (Msg -> Maybe (KbdState, Key)
key -> Just (KbdState
UiMsg.KeyDown, Key
k)) = forall a. a -> Maybe a
Just Key
k
key_down Msg
_ = forall a. Maybe a
Nothing
text :: Msg -> Maybe (Key.Key, Maybe Char)
text :: Msg -> Maybe (Key, Maybe Char)
text (Msg -> Maybe (KbdState, [Modifier], Key, Maybe Char)
kbd -> Just (KbdState
UiMsg.KeyDown, [Modifier]
_, Key
key, Maybe Char
text)) = forall a. a -> Maybe a
Just (Key
key, Maybe Char
text)
text Msg
_ = forall a. Maybe a
Nothing
key_mods :: Msg -> Maybe [Key.Modifier]
key_mods :: Msg -> Maybe [Modifier]
key_mods (Msg -> Maybe (KbdState, [Modifier], Key, Maybe Char)
kbd -> Just (KbdState
_, [Modifier]
mods, Key
_, Maybe Char
_)) = forall a. a -> Maybe a
Just [Modifier]
mods
key_mods Msg
_ = forall a. Maybe a
Nothing
keycap :: Msg -> Maybe (UiMsg.KbdState, Char)
keycap :: Msg -> Maybe (KbdState, Char)
keycap Msg
msg = case Msg -> Maybe (KbdState, Key)
key Msg
msg of
Just (KbdState
state, Key.Char Char
c) -> forall a. a -> Maybe a
Just (KbdState
state, Char
c)
Maybe (KbdState, Key)
_ -> forall a. Maybe a
Nothing
char :: Msg -> Maybe (UiMsg.KbdState, Char)
char :: Msg -> Maybe (KbdState, Char)
char (Msg -> Maybe (KbdState, [Modifier], Key, Maybe Char)
kbd -> Just (KbdState
state, [Modifier]
mods, Key.Char Char
c, Maybe Char
_))
| Modifier
Key.Shift forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Modifier]
mods =
(KbdState
state,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Layout -> Char -> Maybe Char
KeyLayouts.to_shifted Layout
Local.KeyLayout.layout Char
c
| Bool
otherwise= forall a. a -> Maybe a
Just (KbdState
state, Char
c)
char Msg
_ = forall a. Maybe a
Nothing
char_down :: Msg -> Maybe Char
char_down :: Msg -> Maybe Char
char_down (Msg -> Maybe (KbdState, Char)
char -> Just (KbdState
UiMsg.KeyDown, Char
c)) = forall a. a -> Maybe a
Just Char
c
char_down Msg
_ = forall a. Maybe a
Nothing
midi :: Msg -> Maybe Midi.Message
midi :: Msg -> Maybe Message
midi (Midi (Midi.ReadMessage { rmsg_msg :: ReadMessage -> Message
Midi.rmsg_msg = Message
msg })) = forall a. a -> Maybe a
Just Message
msg
midi Msg
_ = forall a. Maybe a
Nothing
context :: Msg -> Maybe UiMsg.Context
context :: Msg -> Maybe Context
context (Ui (UiMsg.UiMsg Context
context Msg
_)) = forall a. a -> Maybe a
Just Context
context
context Msg
_ = forall a. Maybe a
Nothing
context_track :: Msg -> Maybe (TrackNum, UiMsg.Track)
context_track :: Msg -> Maybe (Int, Track)
context_track = Context -> Maybe (Int, Track)
UiMsg.ctx_track forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< Msg -> Maybe Context
context
context_track_pos :: Msg -> Maybe (TrackNum, ScoreTime)
context_track_pos :: Msg -> Maybe (Int, ScoreTime)
context_track_pos Msg
msg = Msg -> Maybe (Int, Track)
context_track Msg
msg forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \(Int
tracknum, Track
t) -> case Track
t of
UiMsg.Track ScoreTime
pos -> forall a. a -> Maybe a
Just (Int
tracknum, ScoreTime
pos)
Track
_ -> forall a. Maybe a
Nothing