module DD.Html where
import Text.XHtml
import Music.Diatonic
import Music.Diatonic.Scale
import Music.Diatonic.Key
import Music.Diatonic.Chord
import Music.Diatonic.Harmony
import List (intersperse)
import Maybe (fromJust)
majorKeys = map majorKey . take 15 . iterate (Music.Diatonic.above Perf5th) $ (flat C)
minorKeys = map minorKey . take 15 . iterate (Music.Diatonic.above Perf5th) $ (flat A)
allNotes = [C, sharp C, flat D, D, sharp D, flat E, E, F,
sharp F, flat G, G, sharp G, flat A, A, sharp A, flat B, B, flat C]
chordTypes = [majorChord, minorChord, diminishedChord, dominant7thChord, major7thChord, minor7thChord, minor7thFlat5thChord]
displayMusicHTML :: String -> Html
displayMusicHTML "" = noHtml
displayMusicHTML (c:cs) = sub c +++ displayMusicHTML cs
where subs = [('b', primHtmlChar "#x266D"),
('#', primHtmlChar "#x266F"),
('o', primHtmlChar "#176")]
sub c = case lookup c subs of
Nothing -> stringToHtml [c]
Just (s) -> s
displayMusicURL :: String -> String
displayMusicURL "" = ""
displayMusicURL (c:cs) = sub c ++ displayMusicURL cs
where subs = [('#', "s"), ('{', ""), ('}', ""), ('(', ""), (')', "")]
sub c = case lookup c subs of
Nothing -> [c]
Just (s) -> s
linkNote :: Note -> Html
linkNote n = bold << hotlink url html
where url = "note" ++ (displayMusicURL . show $ n) ++ ".html"
html = displayMusicHTML . show $ n
linkKey :: Key -> Html
linkKey k = bold << hotlink url html
where url = "key" ++ (displayMusicURL . show $ k) ++ ".html"
html = displayMusicHTML . show $ k
linkChord :: Chord -> Html
linkChord c = bold << hotlink url html
where url = "chord" ++ (displayMusicURL . show $ c) ++ ".html"
html = displayMusicHTML . show $ c
displayScale :: Scale -> Html
displayScale s = tr << (desc +++ (concatHtml . intersperse sep . map cell $ noteList))
where sep = td << ("|" +++ br +++ "|")
cell (d, n) = td << (concatHtml . intersperse br $ [displayMusicHTML . show $ d, linkNote n])
noteList = degrees s
desc = td << ((linkKey . key $ s) +++ ": ")
displayScales :: [Scale] -> Int -> Maybe String -> Html
displayScales ss n desc = table ! [theclass "center", cellspacing 2, cellpadding 4] << (header +++ rows)
where header = case desc of
Nothing -> noHtml
Just d -> tr << (td ! [colspan (n*2)] << (h4 << desc))
rows = concatHtml . map displayScale $ ss
displayHarmony :: Harmony -> Html
displayHarmony h = tr << (desc +++ (concatHtml . intersperse sep . map cell $ chordList))
where sep = td << ("|" +++ br +++ "|")
cell (d, c) = td << (concatHtml . intersperse br $ [displayMusicHTML . showRoman c $ d, linkChord c])
chordList = degrees h
desc = td << ((linkKey . key . scale $ h) +++ ": ")
displayHarmonies :: [Harmony] -> Int -> String -> Html
displayHarmonies hs n desc = table ! [theclass "center", cellspacing 2, cellpadding 4] << (header +++ rows)
where header = tr << (td ! [colspan (n*2)] << (h4 << desc))
rows = concatHtml . map displayHarmony $ hs
displayScaleDegrees :: [(Degree, [a])] -> (a -> Html) -> Html
displayScaleDegrees degList f = tr << (concatHtml . intersperse sep . map cell $ degList)
where sep = td << ("|" +++ br +++ "|" +++ br +++ "|")
cell (d, as) = td ! [valign "top"] << (concatHtml . intersperse br $ (displayMusicHTML . show $ d) : map (\a -> f a) as)
fifths n f fh =
table ! [theclass "center", cellspacing 2, cellpadding 4] <<
tr <<
cells
where cells = concatHtml . intersperse sep . map cell $ noteList
sep = td << ("|" +++ br +++ "|")
cell (d, n) = td ! [width "40"] << (concatHtml . intersperse br $ [stringToHtml ("(" ++ showDist d ++ ")"), fh n])
noteList = zip [-6 .. 6] (map f . circleOfFifths $ n)
showDist d | d == 0 = "-"
showDist d | d > 0 = "+" ++ show d
showDist d = show d
equivKey :: Key -> Key
equivKey k | k == majorKey (sharp G) = majorKey . flat $ A
equivKey k | k == majorKey (sharp A) = majorKey . flat $ B
equivKey k | k == majorKey (sharp D) = majorKey . flat $ E
equivKey k | k == minorKey (flat D) = minorKey . sharp $ C
equivKey k | k == minorKey (flat G) = minorKey . sharp $ A
equivKey k | k == minorKey (flat C) = minorKey . sharp $ D
equivKey k = k