% from AutoTrack by Stefan Ratschan \section{Chord-Symbol-, Scale- and other Charts} \label{sec:charts} \begin{haskelllisting}
> module Haskore.Interface.AutoTrack.ChartBar
>           (T(Cons), dur, chords, readChordSymbol,
>            length) where
> import qualified Haskore.Music        as Music
> import qualified Data.List            as List
> import qualified Haskore.Interface.AutoTrack.ChordSymbol as ChordSymbol
> import qualified Haskore.Interface.AutoTrack.Transposeable as Transposeable
> import           Data.Char(isSpace, isAlpha)
> import           Haskore.Basic.Duration(wn, (%+), )
> import Prelude hiding (length)
\end{haskelllisting} A bar consists of a time signature and a list of chord symbols. Bars have the following input syntax: \begin{verbatim} bar = { chord | timeSig | '%' | '_' } timeSig = '(' int '/' int ')' \end{verbatim} If no time signature is provided then a default is used (within chord chart the time signature of the bar before, and 4/4 for the first bar). The character '\%' is a short-cut for the chords just before. The character '\_' denotes a break. \begin{haskelllisting}
> data T = Cons {
>     dur    :: Music.Dur,
>     chords :: [ Maybe ChordSymbol.T ]
>   } deriving Show
>
> length :: Integral a => T -> a
> length = fromIntegral . List.length . chords
> instance Read T where
>   readsPrec _ = readChordSymbol wn Nothing
> readChordSymbol :: Music.Dur -> Maybe ChordSymbol.T -> ReadS T
> readChordSymbol oldSig oldChord (c:s) | isSpace c = readChordSymbol oldSig oldChord s
> readChordSymbol _      oldChord s@('(':_) = 
>     [ (Cons r b, r2) | (r, r1) <- readSig s, 
>                            (Cons _ b, r2) <- readChordSymbol r oldChord r1 ]
> readChordSymbol oldSig (Just chord) ('%':r) = 
>     [ (Cons oldSig (Just chord:b), r1) | (Cons _ b, r1) <- readChordSymbol oldSig (Just chord) r ]
> readChordSymbol oldSig (Just _) ('_':r) = 
>     [ (Cons oldSig (Nothing:b), r1) | (Cons _ b, r1) <- readChordSymbol oldSig Nothing r ]
> readChordSymbol oldSig _ s@(d:_) | isAlpha d = 
>     [ (Cons oldSig (Just c:b), r2) | (c, r1) <- reads s, 
>                                     (Cons _ b, r2) <- readChordSymbol oldSig (Just c) r1 ] 
> readChordSymbol oldSig _ s = [ (Cons oldSig [], s) ]
>
> readSig :: ReadS Music.Dur
> readSig s@('(':_) =
>    let readRatio s' =
>           [ (p%+q, r1) |
>                 (p,'/':r) <- reads s', (q, r1) <- reads r ]
>    in  readParen True readRatio s
> readSig _ = []
\end{haskelllisting} Bars can be transposed. \begin{haskelllisting}
> instance Transposeable.C T where
>   transpose i (Cons d l) = Cons d (fmap (fmap (Transposeable.transpose i)) l)
\end{haskelllisting}