-- 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

{-# LANGUAGE RecordWildCards #-}
{- | This is analogous to "Solkattu.Dsl.Solkattu", except it exports
    a mridangam-specific notation without using sollus at all.

    Its sollu type is just 'Mridangam.Stroke', so it doesn't need a StrokeMap.
-}
module Solkattu.Dsl.Mridangam (
    module Solkattu.Dsl.Mridangam
    , module Dsl.Solkattu
    , module Solkattu.Dsl.Generic
    , module Solkattu.Dsl.Interactive
) where
import           Prelude hiding ((.))

import qualified Util.CallStack as CallStack
import           Solkattu.Dsl.Interactive (diff, diffw)
import qualified Solkattu.Dsl.MridangamNotation as MridangamNotation
import qualified Solkattu.Dsl.Solkattu as Dsl.Solkattu
import           Solkattu.Dsl.Solkattu (realizeScore, realizeScoreM)
import qualified Solkattu.Format.Terminal as Terminal
import qualified Solkattu.Instrument.Mridangam as Mridangam
import qualified Solkattu.Korvai as Korvai
import qualified Solkattu.Realize as Realize
import qualified Solkattu.S as S
import qualified Solkattu.Solkattu as Solkattu
import qualified Solkattu.Tala as Tala

import           Global
import           Solkattu.Dsl.Generic


type Sequence = SequenceT Stroke
type Stroke = Realize.Stroke Mridangam.Stroke
type Section = Korvai.Section Sequence

-- | Merge a sequence of left hand strokes with one of right hand strokes.
-- Both sequences must have the same length and structure.
(&) :: CallStack.Stack => Sequence -> Sequence -> Sequence
Sequence
a & :: Stack => Sequence -> Sequence -> Sequence
& Sequence
b = forall g a. [Note g a] -> Sequence g a
S.fromList forall a b. (a -> b) -> a -> b
$ Stack => [NoteT Stroke] -> [NoteT Stroke] -> [NoteT Stroke]
MridangamNotation.merge (forall g a. Sequence g a -> [Note g a]
S.toList Sequence
a) (forall g a. Sequence g a -> [Note g a]
S.toList Sequence
b)

korvai :: Tala.Tala -> [Section] -> Korvai.Korvai
korvai :: Tala -> [Section] -> Korvai
korvai Tala
tala = Tala -> PatternMap Stroke -> [Section] -> Korvai
Korvai.mridangamKorvai Tala
tala PatternMap Stroke
Mridangam.defaultPatterns

korvai1 :: Tala.Tala -> Section -> Korvai.Korvai
korvai1 :: Tala -> Section -> Korvai
korvai1 Tala
tala Section
section = Tala -> [Section] -> Korvai
korvai Tala
tala [Section
section]

-- | Infer Section types, as init is development, last is ending.
korvaiS :: Tala.Tala -> [Sequence] -> Korvai.Korvai
korvaiS :: Tala -> [Sequence] -> Korvai
korvaiS Tala
tala = Tala -> [Section] -> Korvai
korvai Tala
tala forall b c a. (b -> c) -> (a -> b) -> a -> c
 forall sollu. [SequenceT sollu] -> [Section (SequenceT sollu)]
Korvai.inferSections

korvaiS1 :: Tala.Tala -> Sequence -> Korvai.Korvai
korvaiS1 :: Tala -> Sequence -> Korvai
korvaiS1 Tala
tala Sequence
sequence = Tala -> [Sequence] -> Korvai
korvaiS Tala
tala [Sequence
sequence]

Mridangam.Strokes {Sequence g (Note Stroke)
od :: Sequence g (Note Stroke)
_' :: Sequence g (Note Stroke)
o' :: Sequence g (Note Stroke)
o :: Sequence g (Note Stroke)
p' :: Sequence g (Note Stroke)
p :: Sequence g (Note Stroke)
j :: Sequence g (Note Stroke)
y :: Sequence g (Note Stroke)
i :: Sequence g (Note Stroke)
v :: Sequence g (Note Stroke)
u :: Sequence g (Note Stroke)
d :: Sequence g (Note Stroke)
n :: Sequence g (Note Stroke)
l :: Sequence g (Note Stroke)
t :: Sequence g (Note Stroke)
k :: Sequence g (Note Stroke)
od :: forall a. Strokes a -> a
_' :: forall a. Strokes a -> a
o' :: forall a. Strokes a -> a
o :: forall a. Strokes a -> a
p' :: forall a. Strokes a -> a
p :: forall a. Strokes a -> a
j :: forall a. Strokes a -> a
y :: forall a. Strokes a -> a
i :: forall a. Strokes a -> a
v :: forall a. Strokes a -> a
u :: forall a. Strokes a -> a
d :: forall a. Strokes a -> a
n :: forall a. Strokes a -> a
l :: forall a. Strokes a -> a
t :: forall a. Strokes a -> a
k :: forall a. Strokes a -> a
..} = forall g. Strokes (Sequence g (Note Stroke))
Mridangam.notes

-- * interactive utilities

realize, realizep :: Korvai.Korvai -> IO ()
realize :: Korvai -> IO ()
realize = (Config -> Config) -> Korvai -> IO ()
realizeM forall a. a -> a
id
realizep :: Korvai -> IO ()
realizep = (Config -> Config) -> Korvai -> IO ()
realizeM Config -> Config
concrete

realizeM :: (Terminal.Config -> Terminal.Config) -> Korvai.Korvai -> IO ()
realizeM :: (Config -> Config) -> Korvai -> IO ()
realizeM = forall stroke1 stroke2.
(Notation stroke1, Notation stroke2, Ord stroke1) =>
(Stroke stroke1 -> Maybe (Stroke stroke2))
-> Instrument stroke1 -> (Config -> Config) -> Korvai -> IO ()
Dsl.Solkattu._printInstrument forall a. a -> Maybe a
Just Instrument Stroke
Korvai.IMridangam

-- * strokes

on :: Sequence
on :: Sequence
on = forall {g}. Sequence g (Note Stroke)
oStack => Sequence -> Sequence -> Sequence
&forall {g}. Sequence g (Note Stroke)
n

p_, pp :: Sequence
p_ :: Sequence
p_ = forall stroke.
SequenceT (Stroke stroke) -> SequenceT (Stroke stroke)
lt forall {g}. Sequence g (Note Stroke)
p
pp :: Sequence
pp = forall stroke.
SequenceT (Stroke stroke) -> SequenceT (Stroke stroke)
hv forall {g}. Sequence g (Note Stroke)
p

replace :: Sequence -> Sequence -> Sequence -> Sequence
replace :: Sequence -> Sequence -> Sequence -> Sequence
replace Sequence
from Sequence
to = forall g a.
(Eq g, Eq a) =>
Sequence g a -> Sequence g a -> Sequence g a -> Sequence g a
S.replace Sequence
from Sequence
to

-- | Thom -> tha.  This converts even Both strokes.
closedAll :: Sequence -> Sequence
closedAll :: Sequence -> Sequence
closedAll = (Stroke -> Maybe Stroke) -> Sequence -> Sequence
mapMStroke forall a b. (a -> b) -> a -> b
$ \case
    Mridangam.Thoppi (Mridangam.Thom Thom
_) ->
        forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Thoppi -> Stroke
Mridangam.Thoppi (Tha -> Thoppi
Mridangam.Tha Tha
Mridangam.Palm)
    Mridangam.Both (Mridangam.Thom Thom
_) Valantalai
a ->
        forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Thoppi -> Valantalai -> Stroke
Mridangam.Both (Tha -> Thoppi
Mridangam.Tha Tha
Mridangam.Palm) Valantalai
a
    Stroke
s -> forall a. a -> Maybe a
Just Stroke
s

closed :: Sequence -> Sequence
closed :: Sequence -> Sequence
closed = (Stroke -> Maybe Stroke) -> Sequence -> Sequence
mapMStroke forall a b. (a -> b) -> a -> b
$ \case
    Mridangam.Thoppi (Mridangam.Thom Thom
_) ->
        forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Thoppi -> Stroke
Mridangam.Thoppi (Tha -> Thoppi
Mridangam.Tha Tha
Mridangam.Palm)
    Mridangam.Both (Mridangam.Thom Thom
_) Valantalai
a ->
        forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Valantalai -> Stroke
Mridangam.Valantalai Valantalai
a
    Stroke
s -> forall a. a -> Maybe a
Just Stroke
s

noThom :: Sequence -> Sequence
noThom :: Sequence -> Sequence
noThom = (Stroke -> Maybe Stroke) -> Sequence -> Sequence
mapMStroke forall a b. (a -> b) -> a -> b
$ \case
    Mridangam.Thoppi (Mridangam.Thom Thom
_) -> forall a. Maybe a
Nothing
    Mridangam.Both (Mridangam.Thom Thom
_) Valantalai
a -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Valantalai -> Stroke
Mridangam.Valantalai Valantalai
a
    Stroke
s -> forall a. a -> Maybe a
Just Stroke
s

thomLH :: Sequence -> Sequence
thomLH :: Sequence -> Sequence
thomLH = (Note Stroke -> Note Stroke) -> Sequence -> Sequence
mapNote forall a b. (a -> b) -> a -> b
$ \Note Stroke
note -> if Note Stroke
note forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Note Stroke
n, Note Stroke
d] then Note Stroke
o else forall a. Rest a => a
__
    where
    Mridangam.Strokes {Note Stroke
od :: Note Stroke
_' :: Note Stroke
o' :: Note Stroke
p' :: Note Stroke
p :: Note Stroke
j :: Note Stroke
y :: Note Stroke
i :: Note Stroke
v :: Note Stroke
u :: Note Stroke
l :: Note Stroke
t :: Note Stroke
k :: Note Stroke
o :: Note Stroke
d :: Note Stroke
n :: Note Stroke
od :: forall a. Strokes a -> a
_' :: forall a. Strokes a -> a
o' :: forall a. Strokes a -> a
o :: forall a. Strokes a -> a
p' :: forall a. Strokes a -> a
p :: forall a. Strokes a -> a
j :: forall a. Strokes a -> a
y :: forall a. Strokes a -> a
i :: forall a. Strokes a -> a
v :: forall a. Strokes a -> a
u :: forall a. Strokes a -> a
d :: forall a. Strokes a -> a
n :: forall a. Strokes a -> a
l :: forall a. Strokes a -> a
t :: forall a. Strokes a -> a
k :: forall a. Strokes a -> a
..} = forall sollu. NoteT sollu -> Note sollu
Solkattu.Note forall b c a. (b -> c) -> (a -> b) -> a -> c
 forall sollu. sollu -> NoteT sollu
Solkattu.note forall b c a. (b -> c) -> (a -> b) -> a -> c
 forall stroke. stroke -> Stroke stroke
Realize.stroke forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
        Strokes Stroke
Mridangam.strokes

-- | Add a 'o' to the first stroke.
o1 :: Sequence -> Sequence
o1 :: Sequence -> Sequence
o1 = forall {g} {a}.
(Note g a -> Note g a) -> Sequence g a -> Sequence g a
maph forall a b. (a -> b) -> a -> b
$ forall a g. (a -> a) -> Note g a -> Note g a
S.map1 forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. (a -> b) -> a -> b
$
    Thoppi -> Stroke -> Stroke
Mridangam.addThoppi (Thom -> Thoppi
Mridangam.Thom Thom
Mridangam.Low)
    where
    maph :: (Note g a -> Note g a) -> Sequence g a -> Sequence g a
maph Note g a -> Note g a
f Sequence g a
seq = case forall g a. Sequence g a -> [Note g a]
S.toList Sequence g a
seq of
        Note g a
n : [Note g a]
ns -> forall g a. [Note g a] -> Sequence g a
S.fromList forall a b. (a -> b) -> a -> b
$ Note g a -> Note g a
f Note g a
n forall a. a -> [a] -> [a]
: [Note g a]
ns
        [] -> forall a. Monoid a => a
mempty

mapMStroke :: (Mridangam.Stroke -> Maybe Mridangam.Stroke) -> Sequence
    -> Sequence
mapMStroke :: (Stroke -> Maybe Stroke) -> Sequence -> Sequence
mapMStroke Stroke -> Maybe Stroke
f = (Note Stroke -> Note Stroke) -> Sequence -> Sequence
mapNote forall a b. (a -> b) -> a -> b
$ \case
    Solkattu.Note NoteT Stroke
n -> case forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse Stroke -> Maybe Stroke
f (forall sollu. NoteT sollu -> sollu
Solkattu._sollu NoteT Stroke
n) of
        Maybe Stroke
Nothing -> forall sollu. Space -> Note sollu
Solkattu.Space Space
Solkattu.Rest
        Just Stroke
s -> forall sollu. NoteT sollu -> Note sollu
Solkattu.Note forall a b. (a -> b) -> a -> b
$ NoteT Stroke
n { _sollu :: Stroke
Solkattu._sollu = Stroke
s }
    Note Stroke
note -> Note Stroke
note

mapNote :: (Solkattu.Note Stroke -> Solkattu.Note Stroke)
    -> Sequence -> Sequence
mapNote :: (Note Stroke -> Note Stroke) -> Sequence -> Sequence
mapNote = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap

-- | Parse a string to mridangam strokes.
strM :: CallStack.Stack => String -> Sequence
strM :: Stack => String -> Sequence
strM String
str = forall b a. Monoid b => (a -> b) -> [a] -> b
mconcatMap forall {g} {stroke}.
Rest (Sequence g (Note (Stroke stroke))) =>
Maybe stroke -> Sequence g (Note (Stroke stroke))
toSeq forall a b. (a -> b) -> a -> b
$ forall a. Stack => Either Text a -> a
Solkattu.check forall a b. (a -> b) -> a -> b
$ String -> Either Text [Maybe Stroke]
Mridangam.fromString String
str
    where
    toSeq :: Maybe stroke -> Sequence g (Note (Stroke stroke))
toSeq Maybe stroke
Nothing = forall a. Rest a => a
__
    toSeq (Just stroke
stroke) = forall stroke g. stroke -> Sequence g (Note (Stroke stroke))
Realize.strokeToSequence stroke
stroke

-- * fragments

-- | Taka and takatiku from solkattu.
kp, kpnp :: Sequence
kp :: Sequence
kp = forall {g}. Sequence g (Note Stroke)
kforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
p
kpnp :: Sequence
kpnp = forall {g}. Sequence g (Note Stroke)
kforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
pforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
nforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
p

ktkno :: Sequence
ktkno :: Sequence
ktkno = forall {g}. Sequence g (Note Stroke)
kforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
tforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
kforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
nforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
o

kt, tk, ktkt :: Sequence
kt :: Sequence
kt = forall {g}. Sequence g (Note Stroke)
kforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
t
tk :: Sequence
tk = forall {g}. Sequence g (Note Stroke)
tforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
k
ktkt :: Sequence
ktkt = forall {g}. Sequence g (Note Stroke)
kforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
tforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
kforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
t

ktpk :: Sequence
ktpk :: Sequence
ktpk = forall {g}. Sequence g (Note Stroke)
kforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
tforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
pforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
k

ktok :: Sequence
ktok :: Sequence
ktok = forall {g}. Sequence g (Note Stroke)
kforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
tforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
oforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
k

pk :: Sequence
pk :: Sequence
pk = forall {g}. Sequence g (Note Stroke)
pforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
k

takadinna, kook :: Sequence
takadinna :: Sequence
takadinna = forall {g}. Sequence g (Note Stroke)
kforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
oforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
oforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
k
kook :: Sequence
kook = forall {g}. Sequence g (Note Stroke)
kforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
oforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
oforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
k

nakatiku :: Sequence
nakatiku :: Sequence
nakatiku = forall sollu.
GroupType -> Text -> SequenceT sollu -> SequenceT sollu
namedT GroupType
Solkattu.GPattern Text
"8n" (forall {g}. Sequence g (Note Stroke)
nforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
pforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
uforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
pforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
kforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
tforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
pforall a. Monoid a => a -> a -> a
.forall {g}. Sequence g (Note Stroke)
k)
    -- also t.p.u.k.t.p.k