module Perform.Transport (
Status(..), Info(..)
, PlayControl(..), play_control
, stop_player, poll_stop_player
, ActivePlayers, active_players
, player_started, player_stopped
, poll_player_stopped, wait_player_stopped
, TempoFunction, ClosestWarpFunction, InverseTempoFunction, Stop(..)
) where
import qualified Control.Concurrent.MVar as MVar
import qualified Control.Concurrent.STM as STM
import qualified Control.Concurrent.STM.TVar as TVar
import qualified Util.Thread as Thread
import qualified Derive.Warp as Warp
import qualified Midi.Interface as Interface
import qualified Ui.Ui as Ui
import Global
import Types
data Status = Playing | Stopped !PlayControl
deriving (Status -> Status -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Status -> Status -> Bool
$c/= :: Status -> Status -> Bool
== :: Status -> Status -> Bool
$c== :: Status -> Status -> Bool
Eq, Int -> Status -> ShowS
[Status] -> ShowS
Status -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Status] -> ShowS
$cshowList :: [Status] -> ShowS
show :: Status -> String
$cshow :: Status -> String
showsPrec :: Int -> Status -> ShowS
$cshowsPrec :: Int -> Status -> ShowS
Show)
instance Pretty Status where pretty :: Status -> Text
pretty = forall a. Show a => a -> Text
showt
data Info = Info {
Info -> Status -> IO ()
info_send_status :: Status -> IO ()
, Info -> Message -> IO ()
info_midi_writer :: Interface.Message -> IO ()
, Info -> IO ()
info_midi_abort :: IO ()
, Info -> IO RealTime
info_get_current_time :: IO RealTime
, Info -> MVar State
info_state :: MVar.MVar Ui.State
}
newtype PlayControl = PlayControl Thread.Flag
deriving (PlayControl -> PlayControl -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PlayControl -> PlayControl -> Bool
$c/= :: PlayControl -> PlayControl -> Bool
== :: PlayControl -> PlayControl -> Bool
$c== :: PlayControl -> PlayControl -> Bool
Eq, Int -> PlayControl -> ShowS
[PlayControl] -> ShowS
PlayControl -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PlayControl] -> ShowS
$cshowList :: [PlayControl] -> ShowS
show :: PlayControl -> String
$cshow :: PlayControl -> String
showsPrec :: Int -> PlayControl -> ShowS
$cshowsPrec :: Int -> PlayControl -> ShowS
Show)
play_control :: IO PlayControl
play_control :: IO PlayControl
play_control = Flag -> PlayControl
PlayControl forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO Flag
Thread.flag
stop_player :: PlayControl -> IO ()
stop_player :: PlayControl -> IO ()
stop_player (PlayControl Flag
flag) = Flag -> IO ()
Thread.set Flag
flag
poll_stop_player :: Thread.Seconds -> PlayControl -> IO Bool
poll_stop_player :: Seconds -> PlayControl -> IO Bool
poll_stop_player Seconds
timeout (PlayControl Flag
flag) = Seconds -> Flag -> IO Bool
Thread.poll Seconds
timeout Flag
flag
newtype ActivePlayers = ActivePlayers (TVar.TVar Int)
active_players :: IO ActivePlayers
active_players :: IO ActivePlayers
active_players = TVar Int -> ActivePlayers
ActivePlayers forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. a -> IO (TVar a)
TVar.newTVarIO Int
0
player_started :: ActivePlayers -> IO ()
player_started :: ActivePlayers -> IO ()
player_started (ActivePlayers TVar Int
running) =
forall a. STM a -> IO a
STM.atomically forall a b. (a -> b) -> a -> b
$ forall a. TVar a -> (a -> a) -> STM ()
TVar.modifyTVar' TVar Int
running (forall a. Num a => a -> a -> a
+Int
1)
player_stopped :: ActivePlayers -> IO ()
player_stopped :: ActivePlayers -> IO ()
player_stopped (ActivePlayers TVar Int
running) =
forall a. STM a -> IO a
STM.atomically forall a b. (a -> b) -> a -> b
$ forall a. TVar a -> (a -> a) -> STM ()
TVar.modifyTVar' TVar Int
running (forall a. Num a => a -> a -> a
subtract Int
1)
poll_player_stopped :: Thread.Seconds -> ActivePlayers -> IO Bool
poll_player_stopped :: Seconds -> ActivePlayers -> IO Bool
poll_player_stopped Seconds
timeout ctl :: ActivePlayers
ctl@(ActivePlayers TVar Int
running)
| Seconds
timeout forall a. Ord a => a -> a -> Bool
<= Seconds
0 = (forall a. Ord a => a -> a -> Bool
<=Int
0) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. TVar a -> IO a
TVar.readTVarIO TVar Int
running
| Bool
otherwise = forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False (forall a b. a -> b -> a
const Bool
True) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
forall a. Seconds -> IO a -> IO (Maybe a)
Thread.timeout Seconds
timeout (ActivePlayers -> IO ()
wait_player_stopped ActivePlayers
ctl)
wait_player_stopped :: ActivePlayers -> IO ()
wait_player_stopped :: ActivePlayers -> IO ()
wait_player_stopped (ActivePlayers TVar Int
running) = forall a. STM a -> IO a
STM.atomically forall a b. (a -> b) -> a -> b
$ do
Int
val <- forall a. TVar a -> STM a
STM.readTVar TVar Int
running
if Int
val forall a. Ord a => a -> a -> Bool
<= Int
0 then forall (m :: * -> *) a. Monad m => a -> m a
return () else forall a. STM a
STM.retry
type TempoFunction = BlockId -> TrackId -> ScoreTime -> [RealTime]
type ClosestWarpFunction = BlockId -> TrackId -> RealTime -> Warp.Warp
type InverseTempoFunction =
Stop -> RealTime -> [(BlockId, [(TrackId, ScoreTime)])]
data Stop =
StopAtEnd
| NoStop
deriving (Stop -> Stop -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Stop -> Stop -> Bool
$c/= :: Stop -> Stop -> Bool
== :: Stop -> Stop -> Bool
$c== :: Stop -> Stop -> Bool
Eq, Int -> Stop -> ShowS
[Stop] -> ShowS
Stop -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Stop] -> ShowS
$cshowList :: [Stop] -> ShowS
show :: Stop -> String
$cshow :: Stop -> String
showsPrec :: Int -> Stop -> ShowS
$cshowsPrec :: Int -> Stop -> ShowS
Show)