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

-- | Operations on control tracks.
module Cmd.Repl.LControl where
import qualified Prelude
import           Prelude hiding (round)

import qualified Util.Num as Num
import qualified Cmd.Cmd as Cmd
import qualified Cmd.ControlTrack as ControlTrack
import qualified Cmd.ModifyEvents as ModifyEvents

import qualified Derive.DeriveT as DeriveT
import qualified Derive.Parse
import qualified Derive.ParseTitle as ParseTitle
import qualified Derive.ScoreT as ScoreT
import qualified Derive.ShowVal as ShowVal

import qualified Perform.Signal as Signal

import           Global
import           Types


-- | Multiply the controls in the selection by the given amount.
multiply :: Signal.Y -> Cmd.CmdL ()
multiply :: Y -> CmdL ()
multiply Y
factor = forall (m :: * -> *). M m => (Y -> Y) -> m ()
map_val (forall a. Num a => a -> a -> a
*Y
factor)

-- | Multiply but keep in 0--1.
multiply01 :: Signal.Y -> Cmd.CmdL ()
multiply01 :: Y -> CmdL ()
multiply01 Y
factor = forall (m :: * -> *). M m => (Y -> Y) -> m ()
map_val (forall a. Ord a => a -> a -> a -> a
Num.clamp Y
0 Y
1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. Num a => a -> a -> a
*Y
factor))

-- | Multiply but keep in -1 -- 1.
multiply_11 :: Signal.Y -> Cmd.CmdL ()
multiply_11 :: Y -> CmdL ()
multiply_11 Y
factor = forall (m :: * -> *). M m => (Y -> Y) -> m ()
map_val (forall a. Ord a => a -> a -> a -> a
Num.clamp (-Y
1) Y
1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. Num a => a -> a -> a
*Y
factor))

-- | Round selected controls to the given number of decimal places.  Useful
-- after a 'multiply'.
round :: Int -> Cmd.CmdL ()
round :: Int -> CmdL ()
round Int
places = forall (m :: * -> *). M m => (Y -> Y) -> m ()
map_val forall a b. (a -> b) -> a -> b
$
    (forall a. Fractional a => a -> a -> a
/ Y
10forall a b. (Num a, Integral b) => a -> b -> a
^Int
places) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (RealFrac a, Integral b) => a -> b
Prelude.round forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. Num a => a -> a -> a
* Y
10forall a b. (Num a, Integral b) => a -> b -> a
^Int
places)

map_val :: Cmd.M m => (Signal.Y -> Signal.Y) -> m ()
map_val :: forall (m :: * -> *). M m => (Y -> Y) -> m ()
map_val Y -> Y
f = forall (m :: * -> *). M m => Track m -> m ()
ModifyEvents.selection forall a b. (a -> b) -> a -> b
$
    forall (m :: * -> *). Monad m => (Text -> Text) -> Track m
ModifyEvents.text forall a b. (a -> b) -> a -> b
$ \Text
text -> forall a. a -> Maybe a -> a
fromMaybe Text
text ((Y -> Y) -> Text -> Maybe Text
ControlTrack.modify_val Y -> Y
f Text
text)

-- | Map controls with the given name.
map_named :: Cmd.M m => Text -> (Signal.Y -> Signal.Y) -> ModifyEvents.Track m
map_named :: forall (m :: * -> *). M m => Text -> (Y -> Y) -> Track m
map_named Text
name Y -> Y
f =
    forall (m :: * -> *). M m => (Text -> Bool) -> Track m -> Track m
ModifyEvents.tracks_named (forall a. Eq a => a -> a -> Bool
==Text
name) forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *). Monad m => (Text -> Text) -> Track m
ModifyEvents.text forall a b. (a -> b) -> a -> b
$ \Text
text ->
        forall a. a -> Maybe a -> a
fromMaybe Text
text ((Y -> Y) -> Text -> Maybe Text
ControlTrack.modify_val Y -> Y
f Text
text)

score_to_hex :: Cmd.CmdL ()
score_to_hex :: CmdL ()
score_to_hex = forall (m :: * -> *). M m => Track m -> m ()
ModifyEvents.all_blocks forall a b. (a -> b) -> a -> b
$
    forall (m :: * -> *). M m => (Text -> Bool) -> Track m -> Track m
ModifyEvents.tracks_named Text -> Bool
ParseTitle.is_signal_track forall a b. (a -> b) -> a -> b
$
        forall (m :: * -> *). Monad m => (Text -> Text) -> Track m
ModifyEvents.text Text -> Text
to_hex

block_to_hex :: BlockId -> Cmd.CmdL ()
block_to_hex :: BlockId -> CmdL ()
block_to_hex BlockId
block_id = forall (m :: * -> *). M m => BlockId -> Track m -> m ()
ModifyEvents.block BlockId
block_id forall a b. (a -> b) -> a -> b
$
    forall (m :: * -> *). M m => (Text -> Bool) -> Track m -> Track m
ModifyEvents.tracks_named Text -> Bool
ParseTitle.is_signal_track forall a b. (a -> b) -> a -> b
$
        forall (m :: * -> *). Monad m => (Text -> Text) -> Track m
ModifyEvents.text Text -> Text
to_hex

to_hex :: Text -> Text
to_hex :: Text -> Text
to_hex Text
text =
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (forall a b. a -> b -> a
const Text
text) Val -> Text
to_num forall a b. (a -> b) -> a -> b
$
        Text -> Either Text Val
Derive.Parse.parse_val (Partial -> Text
ControlTrack._val Partial
partial)
    where
    to_num :: Val -> Text
to_num Val
v = case Val -> Maybe (Typed Y)
DeriveT.constant_val Val
v of
        Just (ScoreT.Typed Type
ScoreT.Untyped Y
n)
            | Y
0 forall a. Ord a => a -> a -> Bool
<= Y
n Bool -> Bool -> Bool
&& Y
n forall a. Ord a => a -> a -> Bool
<= Y
1 -> Partial -> Text
ControlTrack.unparse forall a b. (a -> b) -> a -> b
$
                Partial
partial { _val :: Text
ControlTrack._val = Y -> Text
ShowVal.show_hex_val Y
n }
        Maybe (Typed Y)
_ -> Text
text
    partial :: Partial
partial = Text -> Partial
ControlTrack.parse Text
text