-- | Nrt editing
module Sound.Sc3.Server.Nrt.Edit where

import Data.List {- base -}

import qualified Data.List.Ordered {- data-ordlist -}

import qualified Sound.Osc.Datum as Osc {- hosc -}
import qualified Sound.Osc.Packet as Osc {- hosc -}

import qualified Sound.Sc3.Common.Base {- hsc3 -}
import qualified Sound.Sc3.Server.Command {- hsc3 -}
import Sound.Sc3.Server.Nrt {- hsc3 -}

-- | Merge two Nrt scores.  Retains internal nrt_end messages.
nrt_merge :: Nrt -> Nrt -> Nrt
nrt_merge :: Nrt -> Nrt -> Nrt
nrt_merge (Nrt [Bundle]
p) (Nrt [Bundle]
q) = [Bundle] -> Nrt
Nrt (forall a. Ord a => [a] -> [a] -> [a]
Data.List.Ordered.merge [Bundle]
p [Bundle]
q)

-- | Merge a set of Nrt.  Retains internal 'nrt_end' messages.
nrt_merge_set :: [Nrt] -> Nrt
nrt_merge_set :: [Nrt] -> Nrt
nrt_merge_set = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Nrt -> Nrt -> Nrt
nrt_merge Nrt
nrt_empty

-- | The empty Nrt.
nrt_empty :: Nrt
nrt_empty :: Nrt
nrt_empty = [Bundle] -> Nrt
Nrt []

-- | Add bundle at first permissable location of Nrt.
nrt_insert_pre :: Osc.Bundle -> Nrt -> Nrt
nrt_insert_pre :: Bundle -> Nrt -> Nrt
nrt_insert_pre Bundle
p (Nrt [Bundle]
q) = [Bundle] -> Nrt
Nrt (forall a. Ord a => a -> [a] -> [a]
insert Bundle
p [Bundle]
q)

-- | Add bundle at last permissable location of Nrt.
nrt_insert_post :: Osc.Bundle -> Nrt -> Nrt
nrt_insert_post :: Bundle -> Nrt -> Nrt
nrt_insert_post Bundle
p (Nrt [Bundle]
q) = [Bundle] -> Nrt
Nrt (forall a. Ord a => a -> [a] -> [a]
Sound.Sc3.Common.Base.insert_post Bundle
p [Bundle]
q)

-- | bundleTime of last of nrt_bundles.
nrt_end_time :: Nrt -> Osc.Time
nrt_end_time :: Nrt -> Time
nrt_end_time = Bundle -> Time
Osc.bundleTime forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> a
last forall b c a. (b -> c) -> (a -> b) -> a -> c
. Nrt -> [Bundle]
nrt_bundles

-- | Delete any internal nrt_end messages, and require one at the final bundle.
nrt_close :: Nrt -> Nrt
nrt_close :: Nrt -> Nrt
nrt_close (Nrt [Bundle]
l) =
    let is_nrt_end_msg :: Message -> Bool
is_nrt_end_msg = (forall a. Eq a => a -> a -> Bool
== String
"/nrt_end") forall b c a. (b -> c) -> (a -> b) -> a -> c
. Message -> String
Osc.messageAddress
        bundle_map :: (Time -> Time) -> ([Message] -> [Message]) -> Bundle -> Bundle
bundle_map Time -> Time
t_f [Message] -> [Message]
m_f (Osc.Bundle Time
t [Message]
m) = Time -> [Message] -> Bundle
Osc.Bundle (Time -> Time
t_f Time
t) ([Message] -> [Message]
m_f [Message]
m) -- apply temporal and message functions to bundle
        rem_end_msg :: Bundle -> Bundle
rem_end_msg = (Time -> Time) -> ([Message] -> [Message]) -> Bundle -> Bundle
bundle_map forall a. a -> a
id (forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. Message -> Bool
is_nrt_end_msg))
        req_end_msg :: Bundle -> Bundle
req_end_msg = let f :: [Message] -> [Message]
f [Message]
m = if forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Message -> Bool
is_nrt_end_msg [Message]
m
                                then [Message]
m
                                else [Message]
m forall a. [a] -> [a] -> [a]
++ [Message
Sound.Sc3.Server.Command.nrt_end]
                      in (Time -> Time) -> ([Message] -> [Message]) -> Bundle -> Bundle
bundle_map forall a. a -> a
id [Message] -> [Message]
f
    in [Bundle] -> Nrt
Nrt (forall a b. (a -> b) -> (a -> b) -> [a] -> [b]
Sound.Sc3.Common.Base.at_last Bundle -> Bundle
rem_end_msg Bundle -> Bundle
req_end_msg [Bundle]
l)

-- | Append /q/ to /p/, assumes last timestamp at /p/ precedes first at /q/.
nrt_append :: Nrt -> Nrt -> Nrt
nrt_append :: Nrt -> Nrt -> Nrt
nrt_append (Nrt [Bundle]
p) (Nrt [Bundle]
q) = [Bundle] -> Nrt
Nrt ([Bundle]
p forall a. [a] -> [a] -> [a]
++ [Bundle]
q)