idiii-0.0: src/ID3/Parser/Frame.hs
-- | This Module provides parsers for frames.
module ID3.Parser.Frame
where
---- IMPORTS
import Text.ParserCombinators.Poly.State
import ID3.Parser.General
import ID3.Parser.NativeFrames
import ID3.Type.Frame
import ID3.Type.Flags
import Data.Accessor
import Data.Map (Map)
import qualified Data.Map as Map
import qualified Data.ByteString.Lazy as BS
import qualified Data.ByteString.Lazy.Char8 as C
----
parseFrames :: TagParser ([FrameID], Map FrameID ID3Frame)
parseFrames = do
frames <- many1 anyFrame
let idList = map (\f -> f^.frHeader^.frID) frames
return ( idList , Map.fromList (zip idList frames) )
-- | Parses any Frame Header
anyFrameHeader :: TagParser FrameHeader
anyFrameHeader = do
i <- frameID `err` "frame id"
s <- frameSize `err` "frame size"
f <- frameFlags `err` "frame flags"
return $ initFrameHeader [frID^=i, frSize^=s, frFlags^=f]
-- | Parses any Frame
anyFrame :: TagParser ID3Frame
anyFrame = do
h <- anyFrameHeader `err` "frame header"
i <- frameInfo (h^.frID) `err` "frame info"
return $ initID3Frame [frHeader^=h, frInfo^=i]
-- | Parses Frame Header with given id
frameHeader :: FrameID -> TagParser FrameHeader
frameHeader i = do
string i
s <- frameSize
f <- frameFlags
return $ initFrameHeader [frID^=i, frSize^=s, frFlags^=f]
-- | Parses Frame with given id
parseFrame :: FrameID -> TagParser ID3Frame
parseFrame id = do
h <- frameHeader id
i <- frameInfo id
return $ initID3Frame [frHeader^=h, frInfo^=i]
frameID :: TagParser FrameID
frameID = do
name <- count 4 $ upper `onFail` digit
posUpdate (+4)
return $ C.unpack $ BS.pack name
frameSize :: TagParser FrameSize
frameSize = parseSize_ 4
frameFlags = do
s <- frameStatusFlags `err` "status flags"
f <- frameFormatFlags `err` "format flags"
return $ initFrameFlags [status^=s, format^=f]
frameStatusFlags = do
fs <- parseFlags_ [2,3,4]
return $ mkFlags [2,3,4] fs
-- i.e. %0abc0000
frameFormatFlags = do
fs <- parseFlags_ [2,5,6,7,8]
return $ mkFlags [2,5,6,7,8] fs
-- i.e. %0h00kmnp
-- {-- FRAME CONTENT
{-
-If nothing else is said, strings, including numeric strings and URLs
- [URL], are represented as ISO-8859-1 [ISO-8859-1] characters in the
- range $20 - $FF. Such strings are represented in frame descriptions
- as <text string>, or <full text string> if newlines are allowed. If
- nothing else is said newline character is forbidden. In ISO-8859-1 a
- newline is represented, when allowed, with $0A only.
-
- Frames that allow different types of text encoding contains a text
- encoding description byte. Possible encodings:
-
- $00 ISO-8859-1 [ISO-8859-1]. Terminated with $00.
- $01 UTF-16 [UTF-16] encoded Unicode [UNICODE] with BOM. All
- strings in the same frame SHALL have the same byteorder.
- Terminated with $00 00.
- $02 UTF-16BE [UTF-16] encoded Unicode [UNICODE] without BOM.
- Terminated with $00 00.
- $03 UTF-8 [UTF-8] encoded Unicode [UNICODE]. Terminated with $00.
-
- Strings dependent on encoding are represented in frame descriptions
- as <text string according to encoding>, or <full text string
- according to encoding> if newlines are allowed. Any empty strings of
- type $01 which are NULL-terminated may have the Unicode BOM followed
- by a Unicode NULL ($FF FE 00 00 or $FE FF 00 00).
-
- The timestamp fields are based on a subset of ISO 8601. When being as
- precise as possible the format of a time string is
- yyyy-MM-ddTHH:mm:ss (year, "-", month, "-", day, "T", hour (out of
- 24), ":", minutes, ":", seconds), but the precision may be reduced by
- removing as many time indicators as wanted. Hence valid timestamps
- are
- yyyy, yyyy-MM, yyyy-MM-dd, yyyy-MM-ddTHH, yyyy-MM-ddTHH:mm and
- yyyy-MM-ddTHH:mm:ss. All time stamps are UTC. For durations, use
- the slash character as described in 8601, and for multiple non-
- contiguous dates, use multiple strings, if allowed by the frame
- definition.
-
- The three byte language field, present in several frames, is used to
- describe the language of the frame's content, according to ISO-639-2
- [ISO-639-2]. The language should be represented in lower case. If the
- language is not known the string "XXX" should be used.
-
- All URLs [URL] MAY be relative, e.g. "picture.png", "../doc.txt".
-
- If a frame is longer than it should be, e.g. having more fields than
- specified in this document, that indicates that additions to the
- frame have been made in a later version of the ID3v2 standard. This
- is reflected by the revision number in the header of the tag.
--}