packages feed

musicxml-0.1.2: src/Text/XML/MusicXML/Opus.lhs

\begin{code}
-- |  
-- Maintainer : silva.samuel@alumni.uminho.pt
-- Stability  : experimental
-- Portability: HaXML
-- 
module Text.XML.MusicXML.Opus where
import Text.XML.MusicXML.Common 
import Text.XML.MusicXML.Link
import Text.XML.HaXml.Types (Content,
    DocTypeDecl(..), ExternalID(..), PubidLiteral(..), SystemLiteral(..))
import Control.Monad (MonadPlus(..))
import Prelude (FilePath, Maybe(..), Show, Eq, Monad(..), (++), (.), 
                map, concat)
\end{code}

\begin{musicxml}
	An opus collects MusicXML scores together into a larger
	entity. The individual scores could be movements in a
	symphony, scenes or acts in an opera, or songs in an
	album. The opus definition allows arbitrary nesting
	either via an opus (included in the document) or an
	opus-link (linked like scores). Future versions of the
	MusicXML format may expand this DTD to include reference
	data and other metadata related to musical scores.
	
	Suggested use:
\begin{verbatim}	
	<!DOCTYPE opus PUBLIC
		"-//Recordare//DTD MusicXML 2.0 Opus//EN"
		"http://www.musicxml.org/dtds/opus.dtd">
\end{verbatim}
\end{musicxml}
\begin{code}
-- |
doctype :: DocTypeDecl
doctype = DTD "opus" 
  (Just (PUBLIC (PubidLiteral "-//Recordare//DTD MusicXML 2.0 Opus//EN") 
               (SystemLiteral "http://www.musicxml.org/dtds/opus.dtd"))) 
    []
-- |
getFiles :: Opus -> [FilePath]
getFiles (_,(_,l)) = concat (map (\ x -> getFiles_aux1 x) l)
    where getFiles_aux1 (Opus_1 o) = getFiles o
          getFiles_aux1 (Opus_2 (x,_)) = [getFiles_aux2 x]
          getFiles_aux1 (Opus_3 ((x,_),_)) = [getFiles_aux2 x]
          getFiles_aux2 (_,x,_,_,_,_,_) = x
\end{code}

\begin{musicxml}
	Opus is the document element. The document-attributes
	entity includes the version attribute and is defined in
	the common.mod file.
\end{musicxml}
\begin{code}
-- * Opus
-- |
type Opus = (Document_Attributes, (Maybe Title, [Opus_]))
-- |
read_Opus :: Eq i => StateT Result [Content i] Opus
read_Opus = do
    y <- read_ELEMENT "opus"
    y1 <- read_1 read_Document_Attributes (attributes y)
    y2 <- read_2 (read_MAYBE read_Title) (read_LIST read_Opus_) (childs y)
    return (y1,y2)
-- |
show_Opus :: Opus -> [Content ()]
show_Opus (a,(b,c)) = 
    show_ELEMENT "opus" 
        (show_Document_Attributes a)
        (show_MAYBE show_Title b ++ show_LIST show_Opus_ c)
-- |
data Opus_ = Opus_1 Opus | Opus_2 Opus_Link | Opus_3 Score
    deriving (Eq, Show)
-- |
read_Opus_ :: Eq i => StateT Result [Content i] Opus_
read_Opus_ = 
    (read_Opus >>= return . Opus_1) `mplus`
    (read_Opus_Link >>= return . Opus_2) `mplus`
    (read_Score >>= return . Opus_3) 
-- |
show_Opus_ :: Opus_ -> [Content ()]
show_Opus_ (Opus_1 x) = show_Opus x
show_Opus_ (Opus_2 x) = show_Opus_Link x
show_Opus_ (Opus_3 x) = show_Score x
\end{code}

\begin{musicxml}
	The score elements provide the links to the individual 
	movements. The new-page attribute, added in Version
	2.0, is used to indicate if the first page of the score is 
	different than the last page of the previous score. If
	new-page is "yes", then a different page is used; if
	"no", then the same page is used. The default value is
	implementation-dependent.
\end{musicxml}
\begin{code}
-- |
type Score = ((Link_Attributes, Maybe Yes_No), ())
-- |
read_Score :: StateT Result [Content i] Score
read_Score = do
    y <- read_ELEMENT "score"
    y1 <- read_2 read_Link_Attributes 
                 (read_IMPLIED "new-page" read_Yes_No) (attributes y)
    return (y1,())
-- |
show_Score :: Score -> [Content ()]
show_Score ((a,b),_) = 
    show_ELEMENT "score" 
        (show_Link_Attributes a ++ show_IMPLIED "new-page" show_Yes_No b) []
\end{code}

\begin{musicxml}
	An opus-link provides a link to another opus document,
	allowing for multiple levels of opus collections via
	linking as well as nesting.
\end{musicxml}
\begin{code}
-- |
type Opus_Link = (Link_Attributes, ())
-- |
read_Opus_Link :: StateT Result [Content i] Opus_Link
read_Opus_Link = do
    y <- read_ELEMENT "opus-link"
    y1 <- read_1 read_Link_Attributes (attributes y)
    return (y1,())
-- |
show_Opus_Link :: Opus_Link -> [Content ()]
show_Opus_Link (a,_) = 
    show_ELEMENT "opus-link" (show_Link_Attributes a) []
\end{code}

\begin{musicxml}
	Future versions may include metadata elements. In
	this version, we just include the title of the opus.
\end{musicxml}
\begin{code}
-- |
type Title = PCDATA
-- |
read_Title :: StateT Result [Content i] Title
read_Title = do
    y <- read_ELEMENT "title"
    read_1 read_PCDATA (childs y)
-- |
show_Title :: Title -> [Content ()]
show_Title a = 
    show_ELEMENT "title" [] (show_PCDATA a)
\end{code}