    -- | Monad class implementing an Open Sound Control transport.
    module Sound.OSC.Transport.Monad where

    import Control.Monad {- base -}
    import Data.List {- base -}
    import Data.Maybe {- base -}

    import qualified Control.Monad.Trans.Reader as R {- transformers -}
    import qualified Control.Monad.IO.Class as M {- transformers -}

    import qualified Sound.OSC.Datum as Datum {- hosc -}
    import qualified Sound.OSC.Transport.FD as FD {- hosc -}
    import qualified Sound.OSC.Packet as Packet {- hosc -}
    import qualified Sound.OSC.Wait as Wait {- hosc -}

    -- | Sender monad.
    class Monad m => SendOSC m where
       -- | Encode and send an OSC packet.
       sendPacket :: Packet.Packet -> m ()

    -- | Receiver monad.
    class Monad m => RecvOSC m where
       -- | Receive and decode an OSC packet.
       recvPacket :: m Packet.Packet

    -- | 'DuplexOSC' is the union of 'SendOSC' and 'RecvOSC'.
    class (SendOSC m,RecvOSC m) => DuplexOSC m where

    -- | 'Transport' is 'DuplexOSC' with a 'MonadIO' constraint.
    class (DuplexOSC m,M.MonadIO m) => Transport m where

    -- | 'SendOSC' over 'ReaderT'.
    instance (FD.Transport t,M.MonadIO io) => SendOSC (R.ReaderT t io) where
       sendPacket :: Packet -> ReaderT t io ()
    sendPacket p :: Packet
    p = (t -> io ()) -> ReaderT t io ()
    forall r (m :: * -> *) a. (r -> m a) -> ReaderT r m a
    R.ReaderT (IO () -> io ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    M.liftIO (IO () -> io ()) -> (t -> IO ()) -> t -> io ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (t -> Packet -> IO ()) -> Packet -> t -> IO ()
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip t -> Packet -> IO ()
    forall t. Transport t => t -> Packet -> IO ()
    FD.sendPacket Packet
    p)

    -- | 'RecvOSC' over 'ReaderT'.
    instance (FD.Transport t,M.MonadIO io) => RecvOSC (R.ReaderT t io) where
       recvPacket :: ReaderT t io Packet
    recvPacket = (t -> io Packet) -> ReaderT t io Packet
    forall r (m :: * -> *) a. (r -> m a) -> ReaderT r m a
    R.ReaderT (IO Packet -> io Packet
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    M.liftIO (IO Packet -> io Packet) -> (t -> IO Packet) -> t -> io Packet
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . t -> IO Packet
    forall t. Transport t => t -> IO Packet
    FD.recvPacket)

    -- | 'DuplexOSC' over 'ReaderT'.
    instance (FD.Transport t,M.MonadIO io) => DuplexOSC (R.ReaderT t io) where

    -- | 'Transport' over 'ReaderT'.
    instance (FD.Transport t,M.MonadIO io) => Transport (R.ReaderT t io) where

    -- | Transport connection.
    type Connection t a = R.ReaderT t IO a

    -- | Bracket Open Sound Control communication.
    withTransport :: FD.Transport t => IO t -> Connection t a -> IO a
    withTransport :: IO t -> Connection t a -> IO a
    withTransport u :: IO t
    u = IO t -> (t -> IO a) -> IO a
    forall t a. Transport t => IO t -> (t -> IO a) -> IO a
    FD.withTransport IO t
    u ((t -> IO a) -> IO a)
    -> (Connection t a -> t -> IO a) -> Connection t a -> IO a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Connection t a -> t -> IO a
    forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
    R.runReaderT

    -- * Send

    -- | Type restricted synonym for 'sendOSC'.
    sendMessage :: SendOSC m => Packet.Message -> m ()
    sendMessage :: Message -> m ()
    sendMessage = Packet -> m ()
    forall (m :: * -> *). SendOSC m => Packet -> m ()
    sendPacket (Packet -> m ()) -> (Message -> Packet) -> Message -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Message -> Packet
    Packet.Packet_Message

    -- | Type restricted synonym for 'sendOSC'.
    sendBundle :: SendOSC m => Packet.Bundle -> m ()
    sendBundle :: Bundle -> m ()
    sendBundle = Packet -> m ()
    forall (m :: * -> *). SendOSC m => Packet -> m ()
    sendPacket (Packet -> m ()) -> (Bundle -> Packet) -> Bundle -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Bundle -> Packet
    Packet.Packet_Bundle

    -- * Receive

    -- | Variant of 'recvPacket' that runs 'packet_to_bundle'.
    recvBundle :: (RecvOSC m) => m Packet.Bundle
    recvBundle :: m Bundle
    recvBundle = (Packet -> Bundle) -> m Packet -> m Bundle
    forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
    liftM Packet -> Bundle
    Packet.packet_to_bundle m Packet
    forall (m :: * -> *). RecvOSC m => m Packet
    recvPacket

    -- | Variant of 'recvPacket' that runs 'packet_to_message'.
    recvMessage :: (RecvOSC m) => m (Maybe Packet.Message)
    recvMessage :: m (Maybe Message)
    recvMessage = (Packet -> Maybe Message) -> m Packet -> m (Maybe Message)
    forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
    liftM Packet -> Maybe Message
    Packet.packet_to_message m Packet
    forall (m :: * -> *). RecvOSC m => m Packet
    recvPacket

    -- | Erroring variant.
    recvMessage_err :: RecvOSC m => m Packet.Message
    recvMessage_err :: m Message
    recvMessage_err = (Maybe Message -> Message) -> m (Maybe Message) -> m Message
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (Message -> Maybe Message -> Message
    forall a. a -> Maybe a -> a
    fromMaybe ([Char] -> Message
    forall a. HasCallStack => [Char] -> a
    error "recvMessage")) m (Maybe Message)
    forall (m :: * -> *). RecvOSC m => m (Maybe Message)
    recvMessage

    -- | Variant of 'recvPacket' that runs 'packetMessages'.
    recvMessages :: (RecvOSC m) => m [Packet.Message]
    recvMessages :: m [Message]
    recvMessages = (Packet -> [Message]) -> m Packet -> m [Message]
    forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
    liftM Packet -> [Message]
    Packet.packetMessages m Packet
    forall (m :: * -> *). RecvOSC m => m Packet
    recvPacket

    -- * Wait

    -- | Wait for a 'Packet' where the supplied predicate is 'True',
    -- discarding intervening packets.
    waitUntil :: (RecvOSC m) => (Packet.Packet -> Bool) -> m Packet.Packet
    waitUntil :: (Packet -> Bool) -> m Packet
    waitUntil f :: Packet -> Bool
    f = (Packet -> Bool) -> m Packet -> m Packet
    forall (m :: * -> *) a. Monad m => (a -> Bool) -> m a -> m a
    Wait.untilPredicate Packet -> Bool
    f m Packet
    forall (m :: * -> *). RecvOSC m => m Packet
    recvPacket

    -- | Wait for a 'Packet' where the supplied function does not give
    -- 'Nothing', discarding intervening packets.
    waitFor :: (RecvOSC m) => (Packet.Packet -> Maybe a) -> m a
    waitFor :: (Packet -> Maybe a) -> m a
    waitFor f :: Packet -> Maybe a
    f = (Packet -> Maybe a) -> m Packet -> m a
    forall (m :: * -> *) a b. Monad m => (a -> Maybe b) -> m a -> m b
    Wait.untilMaybe Packet -> Maybe a
    f m Packet
    forall (m :: * -> *). RecvOSC m => m Packet
    recvPacket

    -- | 'waitUntil' 'packet_is_immediate'.
    waitImmediate :: RecvOSC m => m Packet.Packet
    waitImmediate :: m Packet
    waitImmediate = (Packet -> Bool) -> m Packet
    forall (m :: * -> *). RecvOSC m => (Packet -> Bool) -> m Packet
    waitUntil Packet -> Bool
    Packet.packet_is_immediate

    -- | 'waitFor' 'packet_to_message', ie. an incoming 'Message' or
    -- immediate mode 'Bundle' with one element.
    waitMessage :: RecvOSC m => m Packet.Message
    waitMessage :: m Message
    waitMessage = (Packet -> Maybe Message) -> m Message
    forall (m :: * -> *) a. RecvOSC m => (Packet -> Maybe a) -> m a
    waitFor Packet -> Maybe Message
    Packet.packet_to_message

    -- | A 'waitFor' for variant using 'packet_has_address' to match on
    -- the 'Address_Pattern' of incoming 'Packets'.
    waitAddress :: RecvOSC m => Packet.Address_Pattern -> m Packet.Packet
    waitAddress :: [Char] -> m Packet
    waitAddress s :: [Char]
    s =
        let f :: Packet -> Maybe Packet
    f o :: Packet
    o = if [Char] -> Packet -> Bool
    Packet.packet_has_address [Char]
    s Packet
    o then Packet -> Maybe Packet
    forall a. a -> Maybe a
    Just Packet
    o else Maybe Packet
    forall a. Maybe a
    Nothing
        in (Packet -> Maybe Packet) -> m Packet
    forall (m :: * -> *) a. RecvOSC m => (Packet -> Maybe a) -> m a
    waitFor Packet -> Maybe Packet
    f

    -- | Variant on 'waitAddress' that returns matching 'Message'.
    waitReply :: RecvOSC m => Packet.Address_Pattern -> m Packet.Message
    waitReply :: [Char] -> m Message
    waitReply s :: [Char]
    s =
        let f :: Packet -> Message
    f = Message -> Maybe Message -> Message
    forall a. a -> Maybe a -> a
    fromMaybe ([Char] -> Message
    forall a. HasCallStack => [Char] -> a
    error "waitReply: message not located?") (Maybe Message -> Message)
    -> (Packet -> Maybe Message) -> Packet -> Message
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .
                (Message -> Bool) -> [Message] -> Maybe Message
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
    find ([Char] -> Message -> Bool
    Packet.message_has_address [Char]
    s) ([Message] -> Maybe Message)
    -> (Packet -> [Message]) -> Packet -> Maybe Message
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .
                Packet -> [Message]
    Packet.packetMessages
        in (Packet -> Message) -> m Packet -> m Message
    forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
    liftM Packet -> Message
    f ([Char] -> m Packet
    forall (m :: * -> *). RecvOSC m => [Char] -> m Packet
    waitAddress [Char]
    s)

    -- | Variant of 'waitReply' that runs 'messageDatum'.
    waitDatum :: RecvOSC m => Packet.Address_Pattern -> m [Datum.Datum]
    waitDatum :: [Char] -> m [Datum]
    waitDatum = (Message -> [Datum]) -> m Message -> m [Datum]
    forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
    liftM Message -> [Datum]
    Packet.messageDatum (m Message -> m [Datum])
    -> ([Char] -> m Message) -> [Char] -> m [Datum]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [Char] -> m Message
    forall (m :: * -> *). RecvOSC m => [Char] -> m Message
    waitReply