?      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ converting list of bytes to  value unsynchronisation between s unsychronisation (just unSyncInteger . wordsToInteger)  converting  value to list of bytes synchronisation between s sychronisation (just integerToWords 4 . syncInteger)            SIZE BYTES DThe ID3v2 tag size is stored as a 32 bit synchsafe integer (section I 6.2), making a total of 28 effective bits (representing up to 256MB). AThe ID3v2 tag size is the sum of the byte length of the extended D header, the padding and the frames after unsynchronisation. If a % footer is present this equals to (' total size' - 20) bytes, otherwise  (' total size' - 10) bytes. MEANING OF FLAGS   ) ID3v2 flags %abcd0000 EThe version is followed by the ID3v2 flags field, of which currently  four flags are used: a - Unsynchronisation  Bit 7 in the ' ID3v2 flags' indicates whether or not E unsynchronisation is applied on all frames (see section 6.1 for * details); a set bit indicates usage. b - Extended header >The second bit (bit 6) indicates whether or not the header is I followed by an extended header. The extended header is described in B section 3.2. A set bit indicates the presence of an extended  header. c - Experimental indicator $The third bit (bit 5) is used as an 'experimental indicator'. This H flag SHALL always be set when the tag is in an experimental stage. d - Footer present CBit 4 indicates that a footer (section 3.4) is present at the very C end of the tag. A set bit indicates the presence of a footer. EAll the other flags MUST be cleared. If one of these undefined flags E are set, the tag might not be readable for a parser that does not  know the flags function. id3v2 version  major version . revision number ID3v2 HEADER OVERVIEW DThe first part of the ID3v2 tag is the 10 byte tag header, laid out  as follows:    ID3v2/file identifier "ID3" ' ID3v2 version $04 00 * ID3v2 flags %abcd0000 * ID3v2 size 4 * %0xxxxxxx ,The first three bytes of the tag are always "ID3", to indicate that I this is an ID3v2 tag, directly followed by the two version bytes. The F first byte of ID3v2 version is its major version, while the second D byte is its revision number. In this case this is ID3v2.4.0. All G revisions are backwards compatible while major versions are not. If F software with ID3v2.4.0 and below support should encounter version 9 five or higher it should simply ignore the whole tag. id3v2 version: [major version, revision number] header flags as Bool values full size of tag  Extended Header Flags Meaning 5The extended flags field, with its size described by 'number of flag  bytes', is defined as:    %0bcd0000 FEach flag that is set in the extended header has data attached, which H comes in the order in which the flags are encountered (i.e. the data  for flag b comes before the data for flag c). Unset flags cannot E have any attached data. All unknown flags MUST be unset and their 6 corresponding data removed when a tag is modified. Every set flag'3s data starts with a length byte, which contains a F value between 0 and 128 ($00 - $7f), followed by data that has the H field length indicated by the length byte. If a flag has no attached / data, the value $00 is used as length byte. b - Tag is an update AIf this flag is set, the present tag is an update of a tag found H earlier in the present file or stream. If frames defined as unique < are found in the present tag, they are to override any C corresponding ones found in the earlier tag. This flag has no  corresponding data.   # Flag data length $00 c - CRC data present 'If this flag is set, a CRC-32 [ISO-3309] data is included in the H extended header. The CRC is calculated on all the data between the 1 header and footer as indicated by the header's tag length field, H minus the extended header. Note that this includes the padding (if H there is any), but excludes the footer. The CRC-32 is stored as an B 35 bit synchsafe integer, leaving the upper four bits always  zeroed.   # Flag data length $05 ) Total frame CRC 5 * %0xxxxxxx d - Tag restrictions DFor some applications it might be desired to restrict a tag in more A ways than imposed by the ID3v2 specification. Note that the C presence of these restrictions does not affect how the tag is I decoded, merely how it was restricted before encoding. If this flag . is set the tag is restricted as follows:   # Flag data length $01 ) Restrictions %ppqrrstt p - Tag size restrictions   = 00 No more than 128 frames and 1 MB total tag size. > 01 No more than 64 frames and 128 KB total tag size. = 10 No more than 32 frames and 40 KB total tag size. < 11 No more than 32 frames and 4 KB total tag size. q - Text encoding restrictions    0 No restrictions @ 1 Strings are only encoded with ISO-8859-1 [ISO-8859-1] or  UTF-8 [UTF-8]. "r - Text fields size restrictions    00 No restrictions 6 01 No string is longer than 1024 characters. 5 10 No string is longer than 128 characters. 4 11 No string is longer than 30 characters. :Note that nothing is said about how many bytes is used to H represent those characters, since it is encoding dependent. If a C text frame consists of more than one string, the sum of the ( strungs is restricted as stated.  s - Image encoding restrictions    0 No restrictions 0 1 Images are encoded only with PNG [PNG] or JPEG [JFIF]. t - Image size restrictions   00 No restrictions 5 01 All images are 256x256 pixels or smaller. 3 10 All images are 64x64 pixels or smaller. @ 11 All images are exactly 64x64 pixels, unless required  otherwise. True if tag is an update CRC data present Tag restrictions EXTENDED HEADER OVERVIEW (optional) BThe extended header contains information that can provide further H insight in the structure of the tag, but is not vital to the correct @ parsing of the tag information; hence the extended header is  optional.   * Extended header size 4 * %0xxxxxxx $ Number of flag bytes $01 $ Extended Flags $xx  Where the 'Extended header size'# is the size of the whole extended H header, stored as a 32 bit synchsafe integer. An extended header can 3 thus never have a size of fewer than six bytes. size of extended header flags >Forming empty value to return, if there is no Extended Header  !"#$%& "# !$%&3'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXY5'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYH'WTRPONMLKIFEDCB>=;876543210/.-,*(XYUVUSVQUSQUJSVUJGHSUJSVU?@SA<9:<UJV+)3'GWTRPONMLKIFEDCB>=;876543210/.-,*(XYUVUSVQUSQUJSVUJGHSUJSVU?@SA<9:<UJV+)()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXY3Z[\Parsers state ]^current position in tag ' , headerFlags :: [Bool] -- ^ ' , frFlags :: [Bool]} -- ^ current frame flags _current frame size `current frame encoding a,Just a synonim for one item of input stream bcReturns ^ from \. dUpdates ^ with given function. eSets ^ with given value. f Decrements ^. g Incremets ^. hReturns _ from \. iUpdates _ with given function. jSets _ with given value. k Decrements _. l Incremets _. mReturns ` from \. nUpdates ` with given function. oSets ` with given value. pParses one byte and sets `. q Wrapper for  reiterative parsers.  Mnemonic: if _ > 0 then continue else stop rWrapper for atomic parsers.  Increases ^ and decreases _. r p2 parses a list of elements with individual parser p. = Cannot fail, since an empty list is a valid return value.  Unlike default  , stops if _ became 0. s!Parse a non-empty list of items. tt p end% parses a possibly-empty sequence of p's, terminated by a end. u 'manyTill1\' p end'! parses a non-empty sequence of p's, terminated by a end. v3Parse a list of items separated by discarded junk. w=Parse a non-empty list of items separated by discarded junk. x' count n p'G parses a precise number of items, n, using the parser p, in sequence. yx n p'G parses a precise number of items, n, using the parser p, in sequence. z Hybrid of x and  'sepBy\'' {{B parses values termination symbol, according to current encoding (`). |}"Parses a list of values (as [Token]$) separated with termination symbol ~Parses one value (as [Token]) till termination symbol %Parses one value and returns it as a  %Parses one value and returns it as a  CParses 3 bytes of language value (as a String) and returns a pair (Language , value) TTakes a list of keys and parses a list of values. Result is zip of these two lists. Takes a list of s and applies them by turns.  Parses given a. Parses given list of as.  Parses given  ByteString. Same as  but argument is simple . Parses upper-case letters (as a) Parses digit-symbol (as a)  Parses any a. ' parseSize_ n'G parses n bytes of synchronized size-value, and returns unsynchronized  value. 0Takes template of flags-byte and returns it as [] value. 6 For example, for %abcd0000 template you should use 'parseFlags_ [1..4]'. 9Z[\]^_`abcdefghijklmnopqrstuvwxyz{|}~3a\]^_`[bcdefghijklmnopqrstuvwxyz{|}~Z3Z[\]^_`]^_`abcdefghijklmnopqrstuvwxyz{|}~ Frame status flags Frame format flags  Frame Header  frame ID  frame Size  frame Flags  frame Header frame Information Value +       Parses any Frame Header Parses any Frame "Parses Frame Header with given id Parses Frame with given id  Parses Extended Header as  structure  parser for b flag - $  parser for c flag - CRC data  parser for d flag - restrictions flags 5 TODO: make Flags type and structure for these flags   Parses id3v2 Header  ID3v2 FOOTER (optional) ETo speed up the process of locating an ID3v2 tag when searching from G the end of a file, a footer can be added to the tag. It is REQUIRED D to add a footer to an appended tag, i.e. a tag located after all H audio data. The footer is a copy of the header, but with a different  identifier.   ID3v2 identifier "3DI" ' ID3v2 version $04 00 * ID3v2 flags %abcd0000 * ID3v2 size 4 * %0xxxxxxx   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXY      b bz !"#$%&'()*+,-./0123456789Z[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ :; - !"#$%&'()*+,<=>?@ABCDEFGHIJ-./0123456789  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~     K !""#$%&'())*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~              -.                                  ! " # $ % & ' ( ) * + , -./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRPQSPQTPQUPQVPQWPQXPQYPQZPQ[P\]P\^P_`P_aP_bc idiii-0.0ID3.Parser.UnSyncID3.Type.UnparseID3.Type.FlagsID3.Type.HeaderID3.Type.ExtHeaderID3.Type.FrameInfoID3.Parser.GeneralID3.Parser.NativeFramesID3.Type.Frame ID3.Type.TagID3.Parser.FrameID3.Parser.ExtHeaderID3.Parser.HeaderID3.Parser.Tag ID3.ReadTag ID3.WriteTag ID3.SimpleID3.Type ID3.ParserID3wordsToInteger unSyncInteger unSynchroniseintegerToWords syncInteger synchroniseHasSizesize updateSizeInfStrParsedunparseFlags emptyFlagsallFlags accessFlagTagSizeTagFlags TagVersion ID3Header tagVersion_ tagFlags_tagSize_ExtFlags ID3ExtHeaderemptyID3ExtHeaderinitID3ExtHeaderextSizeextFlags emptyExtFlags initExtFlagsisUpdatecrc restrictions FrameInfoUnknownvalueTCMPisPartASPISIGNPRIVGRIDENCRCOMROWNEUSERPOSSLINKAENCRBUFPOPMemailratingPCNTcounterGEOBAPICmimepicTypepicDataRVRBEQU2RVA2COMMSYLT timeFormatcontentUSLTlangSYTCMLLTETCOMCDIWXXXURLurlTXXXdescrTextenctextUFIDowneridSize TagParserStStatetagPoscurSize curEncodingTokenrunposGet posUpdateposSetposDecposIncsizeGet sizeUpdatesizeSetsizeDecsizeIncencGet encUpdateencSetencReadifSizemany'many1' manyTill' manyTill1'sepBy'sepBy1'countcount' countSepBy' terminatorencPack parseValues parseValue parseString parseNumber parseLanguage formValuesparsersword8word8s byteStringstringupperdigitanyWord8 parseSize_ parseFlags_textInfo FormatFlags StatusFlags FrameFlagsstatusFformatF FrameSizeFrameID FrameHeaderfrID_frSize_frFlags_ FrameNameID3Frame frHeader_frInfo_ID3Tag tagHeader tagExtHeader tagFramestagFramesOrder tagPaddingframe parseFramesanyFrameHeaderanyFrame frameHeader parseFrameframeID frameSizeparseExtHeader parseHeader parseFooterparseTag parseTag_hReadTagreadTag hWriteTagwriteTagTag getArtist setArtistgetTitlesetTitlegetAlbumsetAlbumgetYearsetYeargetTracksetTrack integer-gmpGHC.Integer.TypeInteger initFlagsmkFlagsemptyID3Header initID3Header tagVersiontagFlagstagSizeunsynchextended experimentalfooted showTagFlags extIsUpdateextCrcextRestrictionsextSize_ extFlags_$fShowID3ExtHeader encodeAllinfoTextContent polyparse-1.4 Text.ParserCombinators.Poly.BasemanybaseGHC.BaseString!Text.ParserCombinators.Poly.StateParserghc-primGHC.BoolBool initStatewithSizeskipTillrecode'nonNullerrurlInfo frameInfo emptyID3Frame initID3FramefrHeaderfrInfo textContentemptyFrameHeaderinitFrameHeaderfrIDfrSizefrFlagsemptyFrameFlagsinitFrameFlagsstatusformat frameDiscard fileDiscardreadOnlyshowStatusFlags groupPart compressed encrypted unsychronised dataLengthIdshowFormatFlags initFrame emptyID3Tag initID3TagheaderversionsetSize getFullSize getActualSize framesSize footerSizeextHSizepaddingflags extHeaderframes framesOrdergetFramesetFrame sortFrames frameFlagsframeStatusFlagsframeFormatFlagsparseBparseCparseD parseVersion parseFlags parseSize PolyParsecommit adjustErronFailoneOf'applyfailBaddiscard adjustErrBadoneOfindentoptionalexactlymany1sepBysepBy1 bracketSepbracket manyFinallyreparsestGetstQuerystUpdatesatisfyeofnext runParserPSuccessFailure CommittedResult getFrameText setFrameTextdata-accessor-0.2.1.4 Data.AccessormodAputAgetA=:<..>setValgetValaccessorAccessorData.Accessor.MonadState%:%=Data.Accessor.Basic^:^.^=