-- Copyright 2016 Evan Laforge
-- This program is distributed under the terms of the GNU General Public
-- License 3.0, see COPYING or http://www.gnu.org/licenses/gpl-3.0.txt

-- | Types for "Derive.Inst", split apart to reduce dependencies.
module Instrument.InstT where
import qualified Data.Text as Text

import qualified Util.Serialize as Serialize
import Global


-- | This is an instrument name qualified by synth name.  It should uniquely
-- address a single instrument.  It's different from
-- a 'Derive.ScoreTypes.Instrument', which addresses a particular instantiation
-- of an instrument in a particular score.
data Qualified = Qualified SynthName Name deriving (Int -> Qualified -> ShowS
[Qualified] -> ShowS
Qualified -> String
(Int -> Qualified -> ShowS)
-> (Qualified -> String)
-> ([Qualified] -> ShowS)
-> Show Qualified
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Qualified] -> ShowS
$cshowList :: [Qualified] -> ShowS
show :: Qualified -> String
$cshow :: Qualified -> String
showsPrec :: Int -> Qualified -> ShowS
$cshowsPrec :: Int -> Qualified -> ShowS
Show, Qualified -> Qualified -> Bool
(Qualified -> Qualified -> Bool)
-> (Qualified -> Qualified -> Bool) -> Eq Qualified
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Qualified -> Qualified -> Bool
$c/= :: Qualified -> Qualified -> Bool
== :: Qualified -> Qualified -> Bool
$c== :: Qualified -> Qualified -> Bool
Eq, Eq Qualified
Eq Qualified
-> (Qualified -> Qualified -> Ordering)
-> (Qualified -> Qualified -> Bool)
-> (Qualified -> Qualified -> Bool)
-> (Qualified -> Qualified -> Bool)
-> (Qualified -> Qualified -> Bool)
-> (Qualified -> Qualified -> Qualified)
-> (Qualified -> Qualified -> Qualified)
-> Ord Qualified
Qualified -> Qualified -> Bool
Qualified -> Qualified -> Ordering
Qualified -> Qualified -> Qualified
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Qualified -> Qualified -> Qualified
$cmin :: Qualified -> Qualified -> Qualified
max :: Qualified -> Qualified -> Qualified
$cmax :: Qualified -> Qualified -> Qualified
>= :: Qualified -> Qualified -> Bool
$c>= :: Qualified -> Qualified -> Bool
> :: Qualified -> Qualified -> Bool
$c> :: Qualified -> Qualified -> Bool
<= :: Qualified -> Qualified -> Bool
$c<= :: Qualified -> Qualified -> Bool
< :: Qualified -> Qualified -> Bool
$c< :: Qualified -> Qualified -> Bool
compare :: Qualified -> Qualified -> Ordering
$ccompare :: Qualified -> Qualified -> Ordering
Ord)

synth :: Qualified -> SynthName
synth :: Qualified -> SynthName
synth (Qualified SynthName
synth SynthName
_) = SynthName
synth

name :: Qualified -> Name
name :: Qualified -> SynthName
name (Qualified SynthName
_ SynthName
name) = SynthName
name

instance Pretty Qualified where pretty :: Qualified -> SynthName
pretty = Qualified -> SynthName
show_qualified

instance Serialize.Serialize Qualified where
    put :: Putter Qualified
put (Qualified SynthName
a SynthName
b) = Putter SynthName
forall a. Serialize a => Putter a
Serialize.put SynthName
a PutM () -> PutM () -> PutM ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Putter SynthName
forall a. Serialize a => Putter a
Serialize.put SynthName
b
    get :: Get Qualified
get = SynthName -> SynthName -> Qualified
Qualified (SynthName -> SynthName -> Qualified)
-> Get SynthName -> Get (SynthName -> Qualified)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get SynthName
forall a. Serialize a => Get a
Serialize.get Get (SynthName -> Qualified) -> Get SynthName -> Get Qualified
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Get SynthName
forall a. Serialize a => Get a
Serialize.get

-- | Short but unabbreviated lowercase name with no spaces.  It should
-- follow 'Ui.Id.valid_symbol'.
type SynthName = Text

-- | A name uniquely addresses this instrument within a synth.  It should also
-- follow 'Ui.Id.valid_symbol'.
type Name = Text

parse_qualified :: Text -> Qualified
parse_qualified :: SynthName -> Qualified
parse_qualified SynthName
text = SynthName -> SynthName -> Qualified
Qualified SynthName
pre (Int -> SynthName -> SynthName
Text.drop Int
1 SynthName
post)
    where (SynthName
pre, SynthName
post) = (Char -> Bool) -> SynthName -> (SynthName, SynthName)
Text.break (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
==Char
'/') SynthName
text

show_qualified :: Qualified -> Text
show_qualified :: Qualified -> SynthName
show_qualified (Qualified SynthName
synth SynthName
name) = SynthName
synth SynthName -> SynthName -> SynthName
forall a. Semigroup a => a -> a -> a
<> SynthName
"/" SynthName -> SynthName -> SynthName
forall a. Semigroup a => a -> a -> a
<> SynthName
name

-- | This will always resolve to an empty instrument, for Dummy allocations.
dummy :: Qualified
dummy :: Qualified
dummy = SynthName -> SynthName -> Qualified
Qualified SynthName
"dummy" SynthName
""