\begin{code} -- | -- Maintainer : silva.samuel@alumni.uminho.pt -- Stability : experimental -- Portability: HaXML -- module Text.XML.MusicXML ( module Text.XML.MusicXML, module Text.XML.MusicXML.Common, module Text.XML.MusicXML.Attributes, module Text.XML.MusicXML.Identity, module Text.XML.MusicXML.Barline, module Text.XML.MusicXML.Link, module Text.XML.MusicXML.Direction, module Text.XML.MusicXML.Layout, module Text.XML.MusicXML.Note, module Text.XML.MusicXML.Score, module Text.XML.MusicXML.Partwise, module Text.XML.MusicXML.Timewise, ) where import Prelude (IO, Int, String, FilePath, Monad(..), Show(..), Eq(..), Ord(..), Maybe(..), Bool(..), either, maybe, otherwise, fromEnum, snd, mapM, readFile, writeFile, (.), (++), (+)) -- base package import qualified Data.Map as Map -- containers package import Control.Monad (MonadPlus(..)) -- base package import System.Time (CalendarTime(..), getClockTime, toCalendarTime) -- old-time package import System.Directory (doesFileExist) -- directory package import Text.PrettyPrint.HughesPJ -- pretty package import Text.XML.HaXml.Types -- HaXml package import Text.XML.HaXml.Parse (xmlParse') -- HaXml package import Text.XML.HaXml.Pretty (document) -- HaXml package import Text.XML.HaXml.Posn (Posn, noPos) -- HaXml package import Text.XML.MusicXML.Common hiding ( Tenths, read_Tenths, show_Tenths, Directive, read_Directive, show_Directive) -- MusicXML package import Text.XML.MusicXML.Attributes -- MusicXML package import Text.XML.MusicXML.Barline -- MusicXML package import Text.XML.MusicXML.Link -- MusicXML package import Text.XML.MusicXML.Direction -- MusicXML package import Text.XML.MusicXML.Identity -- MusicXML package import Text.XML.MusicXML.Layout -- MusicXML package import Text.XML.MusicXML.Note -- MusicXML package import Text.XML.MusicXML.Score hiding (Opus, read_Opus, show_Opus) -- MusicXML package import Text.XML.MusicXML.Partwise hiding (doctype, Part, read_Part, show_Part, Measure, read_Measure, show_Measure) -- MusicXML package import Text.XML.MusicXML.Timewise hiding (doctype, Part, read_Part, show_Part, Measure, read_Measure, show_Measure) -- MusicXML package import Text.XML.MusicXML.Opus hiding (doctype) -- MusicXML package import Text.XML.MusicXML.Container hiding (doctype) -- MusicXML package import qualified Text.XML.MusicXML.Partwise as Partwise -- MusicXML package import qualified Text.XML.MusicXML.Timewise as Timewise -- MusicXML package import qualified Text.XML.MusicXML.Opus as Opus -- MusicXML package import qualified Text.XML.MusicXML.Container as Container -- MusicXML package \end{code} \begin{code} -- * MusicXML -- | data ScoreDoc = Partwise Score_Partwise | Timewise Score_Timewise deriving (Eq, Show) data MusicXMLDoc = Score ScoreDoc | Opus Opus | Container Container deriving (Eq, Show) -- | data MusicXMLRec = MusicXMLRec (Map.Map FilePath MusicXMLDoc) deriving (Eq, Show) \end{code} \begin{code} -- | read_DOCUMENT :: STM Result [Content Posn] a -> Document Posn -> Result a read_DOCUMENT r (Document _ _ x _) = stateM r [CElem x noPos] >>= (return.snd) -- | read_MusicXML_Partwise :: Document Posn -> Result Score_Partwise read_MusicXML_Partwise = read_DOCUMENT read_Score_Partwise -- | read_MusicXML_Timewise :: Document Posn -> Result Score_Timewise read_MusicXML_Timewise = read_DOCUMENT read_Score_Timewise -- | read_MusicXML_Opus :: Document Posn -> Result Opus read_MusicXML_Opus = read_DOCUMENT read_Opus -- | read_MusicXML_Container :: Document Posn -> Result Container read_MusicXML_Container = read_DOCUMENT read_Container -- | show_DOCUMENT :: DocTypeDecl -> (t -> [Content i]) -> t -> Result (Document i) show_DOCUMENT doct f doc = case f doc of [(CElem processed _)] -> return (Document (Prolog (Just xmldecl) [] (Just doct) []) [] processed []) _ -> fail "internal error" -- | show_MusicXML_Partwise :: Score_Partwise -> Result (Document ()) show_MusicXML_Partwise = show_DOCUMENT Partwise.doctype show_Score_Partwise -- | show_MusicXML_Timewise :: Score_Timewise -> Result (Document ()) show_MusicXML_Timewise = show_DOCUMENT Partwise.doctype show_Score_Timewise -- | show_MusicXML_Opus :: Opus -> Result (Document ()) show_MusicXML_Opus x = show_DOCUMENT Opus.doctype show_Opus x -- | show_MusicXML_Container :: Container -> Result (Document ()) show_MusicXML_Container x = show_DOCUMENT Container.doctype show_Container x -- | update_MusicXML_Partwise :: ([Software], Encoding_Date) -> Score_Partwise -> Score_Partwise update_MusicXML_Partwise = update_Score_Partwise -- | update_MusicXML_Timewise :: ([Software], Encoding_Date) -> Score_Timewise -> Score_Timewise update_MusicXML_Timewise = update_Score_Timewise \end{code} \begin{code} -- | read_MusicXMLDoc :: Document Posn -> Result MusicXMLDoc read_MusicXMLDoc doc = (read_DOCUMENT read_Score_Partwise doc >>= return .Score .Partwise) `mplus` (read_DOCUMENT read_Score_Timewise doc >>= return .Score .Timewise) `mplus` (read_DOCUMENT read_Opus doc >>= return . Opus) `mplus` (read_DOCUMENT read_Container doc >>= return . Container) `mplus` fail " or or or " -- | show_MusicXMLDoc :: MusicXMLDoc -> Result (Document ()) show_MusicXMLDoc (Score (Partwise doc)) = show_MusicXML_Partwise doc show_MusicXMLDoc (Score (Timewise doc)) = show_MusicXML_Timewise doc show_MusicXMLDoc (Opus doc) = show_MusicXML_Opus doc show_MusicXMLDoc (Container doc) = show_MusicXML_Container doc -- | update_MusicXMLDoc :: ([Software], Encoding_Date) -> MusicXMLDoc -> MusicXMLDoc update_MusicXMLDoc x (Score (Partwise doc)) = Score (Partwise (update_MusicXML_Partwise x doc)) update_MusicXMLDoc x (Score (Timewise doc)) = Score (Timewise (update_MusicXML_Timewise x doc)) update_MusicXMLDoc _ y = y -- | read_MusicXMLRec :: FilePath -> IO (Map.Map FilePath MusicXMLDoc) read_MusicXMLRec f = do x <- read_FILE read_MusicXMLDoc f >>= \a -> return (f, a) case isOK (snd x) of True -> do xs <- mapM (\f' -> read_FILE read_MusicXMLDoc f' >>= \a -> return (f', a)) (Text.XML.MusicXML.getFiles (fromOK (snd x))) return (Map.map fromOK (Map.filter isOK (Map.fromList (x:xs)))) False -> return (Map.empty) \end{code} \begin{code} -- | read_CONTENTS :: (Document Posn -> Result a) -> FilePath -> Prelude.String -> Result a read_CONTENTS f filepath contents = either fail f (xmlParse' filepath contents) -- | show_CONTENTS :: (a -> Result (Document i)) -> a -> Prelude.String show_CONTENTS f musicxml = maybe (fail "undefined error") (renderStyle (Style LeftMode 100 1.5) . document) ((toMaybe . f) musicxml) -- | read_FILE :: (Document Posn -> Result a) -> FilePath -> IO (Result a) read_FILE f filepath = do exists <- doesFileExist filepath case exists of True -> readFile filepath >>= return . (read_CONTENTS f) filepath False -> (return . fail) ("no file: " ++ show filepath) -- | show_FILE :: (a -> Result (Document i)) -> FilePath -> a -> IO () show_FILE f filepath musicxml = writeFile filepath (show_CONTENTS f musicxml) \end{code} \begin{code} -- | xmldecl :: XMLDecl xmldecl = XMLDecl "1.0" Nothing Nothing -- | getFiles :: MusicXMLDoc -> [FilePath] getFiles (Score _) = [] getFiles (Opus x) = Text.XML.MusicXML.Opus.getFiles x getFiles (Container x) = Text.XML.MusicXML.Container.getFiles x -- | toMaybe :: Result a -> Maybe a toMaybe (Ok x) = Just x toMaybe (Error _) = Nothing -- | getTime uses old-time library. At future versions can be defined as: -- @getTime :: IO Prelude.String@ -- @getTime = getCurrentTime >>= return . show . utctDay@ getTime :: IO Encoding_Date getTime = getClockTime >>= toCalendarTime >>= return . (\(CalendarTime yyyy mm dd _ _ _ _ _ _ _ _ _) -> show4 yyyy ++ "-" ++ show2 (fromEnum mm + 1) ++ "-" ++ show2 dd) -- | show2, show3, show4 :: Int -> Prelude.String show2 x | (x < 0) = show2 (-x) | otherwise = case show x of; [a] -> '0':a:[]; y -> y show3 x | (x < 0) = show3 (-x) | otherwise = case show2 x of; [a,b] -> '0':a:b:[]; y -> y show4 x | (x < 0) = show4 (-x) | otherwise = case show3 x of; [a,b,c] -> '0':a:b:c:[]; y -> y \end{code} \begin{verbatim} getTime :: IO Prelude.String getTime = getCurrentTime >>= return . show . utctDay \end{verbatim}