music-graphics-1.7: src/Music/Graphics/Diagrams.hs
{-# LANGUAGE NoMonomorphismRestriction, TypeFamilies, FlexibleContexts #-}
module Music.Graphics.Diagrams (
-- draw,
-- writeGraphic,
-- openGraphic
) where
import Music.Score
import Music.Pitch
import Diagrams.Prelude hiding (Time, Duration)
import qualified Diagrams.Backend.SVG as SVG
-- test
import Music.Prelude.Basic
import Control.Lens
import System.Process
import Text.Blaze.Svg.Renderer.Utf8 (renderSvg)
import qualified Data.ByteString.Lazy as ByteString
--
--
-- timeToDouble :: Time -> Double
-- timeToDouble = realToFrac . (.-. origin)
-- durationToDouble :: Duration -> Double
-- durationToDouble = realToFrac
-- pitchToDouble :: Music.Pitch.Pitch -> Double
-- pitchToDouble = realToFrac . semitones . (.-. c)
--
-- draw :: (Renderable (Path R2) b, Real a) => Score a -> Diagram b R2
-- draw = bg whitesmoke . scaleX 20{-TODO-} . mconcat . fmap drawNote . fmap (map1 timeToDouble . map2 durationToDouble . map3 realToFrac) . (^. events)
-- where
-- map1 f (a,b,c) = (f a,b,c)
-- map2 f (a,b,c) = (a,f b,c)
-- map3 f (a,b,c) = (a,b,f c)
-- drawNote (t,d,x) = translateY x $ translateX (t.+^(d^/2)) $ scaleX d $ noteShape
-- noteShape = lcA transparent $ fcA (blue `withOpacity` 0.5) $ square 1
--
-- writeGraphic :: FilePath -> Score Double -> IO ()
-- writeGraphic path x = do
-- let dia = draw x
-- let svg = renderDia SVG.SVG (SVG.SVGOptions (Dims 1800 (1800/20)) Nothing) dia
-- let bs = renderSvg svg
-- ByteString.writeFile path bs
--
-- openGraphic :: Score Double -> IO ()
-- openGraphic x = do
-- writeGraphic "test.svg" x
-- -- FIXME find best reader
-- system "open -a Firefox test.svg"
-- return ()
-- drawScores
-- :: (Integral p, p ~ Pitch b, HasPitch b, Voice b ~ NotePart, HasVoice b)
-- => Score b -> Score c -> Diagram SVG R2
-- drawScores notes cmds = notes1D <> notes2D <> cmdsD <> middleLines <> crossLines
-- where
-- notes1 = mfilter (\x -> getPartGroup (getVoice x) == 1) notes
-- notes2 = mfilter (\x -> getPartGroup (getVoice x) == 2) notes
--
-- notes1D = mconcat $ fmap (drawNote 1) $ perform notes1
-- notes2D = mconcat $ fmap (drawNote 2) $ perform notes2
-- cmdsD = mconcat $ fmap drawCmd $ perform cmds
-- middleLines = translateX ((/ 2) $ totalDur) (hrule $ totalDur)
-- crossLines = mconcat $ fmap (\n -> translateX ((totalDur/5) * n) (vrule 100)) $ [0..5]
--
-- drawNote n (t,d,x) = translateY (getP x + off n) $ translateX (getT (t.+^(d^/2))) $ scaleX (getD d) $ noteShape n
-- off 1 = 50
-- off 2 = (-50)
-- drawCmd (t,d,x) = translateY 0 $ translateX (getT t) $ cmdShape
--
-- noteShape 1 = lcA transparent $ fcA (blue `withOpacity` 0.3) $ square 1
-- noteShape 2 = lcA transparent $ fcA (green `withOpacity` 0.3) $ square 1
-- cmdShape = lcA (red `withOpacity` 0.3) $ vrule (200)
--
-- totalDur = getD $ duration notes
-- getT = fromRational . toRational
-- getD = fromRational . toRational
-- getP = (subtract 60) . fromIntegral . getPitch