www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - ID3 tag reader module in D - id3tag.d

reply James Dunne <jdunne4 bradley.edu> writes:
Attached is a present for anyone wishing for a native D ID3 tag reader! :)

It works with Phobos streams.  An example program is included in a debug {}
block to test it yourselves.  ID3v2 and v1 tags are supported.  I don't know
about 100% ID3v1, but I'm pulling the most relevant fields from v2.

The default behavior is to find an ID3v2 tag at the start of the stream and an
ID3v1 tag at 0x80 bytes from the end of the stream, in that order.

Enjoy!

P.S. - feel free to post/use this code anywhere you like, but give credit where
credit is due.

Regards,
James Dunne
begin 0644 id3tag.d
M+R\ 240S(%1A9R!R971R:65V86P 1"!M;V1U;&4N#0HO+R!W<FET=&5N(&)Y
M($IA;65S($1U;FYE#0H-"B\O("AC*2!#;W!Y<FEG:'0 2F%M97, 1'5N;F4 
M,C`P-"P ,C`P-0T*+R\ ,#8 1&5C+B`R,#`T#0H-"FUO9'5L90EI9#-T86<[
M#0H-"FEM<&]R=`ES=&0N<W1R96%M.PT*:6UP;W)T"7-T9"YI;G1R:6YS:6,[
M#0II;7!O<G0)<W1D+G-T<FEN9SL-" T*+R\ 02!V97)Y('-I;7!L92!T86< 
M<W1R=6-T=7)E+"!O;FQY#0HO+R!C;VYC97)N960 =VET:"!S:6UP;&4 <V]N
M9R!D971A:6QS+ T*<W1R=6-T($E$,U1A9R![#0H)+R\ ,2!F;W( 240S=C$L
M(#( 9F]R($E$,W8R#0H):6YT"0EI9#-V97)S:6]N.PT*"2\O(%1H92!C;VUM
M;VX 9FEE;&1S. T*"6-H87);70ET:71L93L-" EC:&%R6UT)87)T:7-T.PT*
M"6-H87);70EA;&)U;3L-" EI;G0)"7EE87([#0H):6YT"0ET<F%C:RP =')A
M8VMS.PT*"6-H87);70EG96YR93L-"GT[#0H-"B\O($5X8V5P=&EO;B!T:')O
M=VX 8GD <F5A9$E$,U1A9R I. T*8VQA<W, 240S17AC97!T:6]N(#H 17AC
M97!T:6]N('L-" ET:&ES*&-H87);72!M<V<I('L-" D)<W5P97(H;7-G*3L-
M" E]#0I]#0H-"B\O(%)E861S(&%N($E$,R!T86< 9G)O;2!A;B!-4#, <W1R
M96%M+ T*+R\ 4W1R96%M(&UU<W0 8F4 870 ;&5A<W0 8F]T:"!S965K86)L
M92!A;F0 <F5A9&%B;&4N#0H-"B\O(%1H:7, 9G5N8W1I;VX <F5T=7)N<R!A
M;B!)1#-486< <W1R=6-T=7)E(')E<')E<V5N=&EN9R!T:&4-"B\O($E$,R!I
M;F9O<FUA=&EO;B!R96%D(&EN+B` 240S=C( =&%G(&ES('-E87)C:&5D(&9O
M<B!F:7)S="P-"B\O(&%N9"!I9B!N;W0 9F]U;F0L($E$,W8Q(&ES('-E87)C
M:&5D(&9O<BX ($EF(&YE:71H97( :7, 9F]U;F0-"B\O('1H92!F=6YC=&EO
M;B!R971U<FYS("=N=6QL)RX-" T*240S5&%G*B!R96%D240S5&%G*%-T<F5A
M;2!S=')E86TI('L-" E)1#-486<J"71A9SL-" T*"2\O(%)E860 82!S=')I
M;F< 9G)O;2!A('-T<F5A;3H-" EC:&%R6UT <F5A9%-T<FEN9RA3=')E86T 
M<W1R96%M+"!I;G0 =&%G;&5N*2![#0H)"2\O(%)E860 =&AE('-T<FEN9SH-
M" D)8VAA<BH)<W1R(#T ;F5W(&-H87);=&%G;&5N73L-" D)<W1R96%M+G)E
M861";&]C:RAC87-T*'9O:60J*7-T<BP =&%G;&5N*3L-" T*"0ER971U<FX 
M<W1R6S` +BX =&%G;&5N72YD=7`[#0H)?0T*#0H)+R\ 5&5S="!S=')E86T 
M<')O<&5R=&EE<SH-" EI9B`H(7-T<F5A;2YS965K86)L92D =&AR;W< ;F5W
M($E$,T5X8V5P=&EO;B B4W1R96%M(&UU<W0 8F4 <V5E:V%B;&4B*3L-" EI
M9B`H(7-T<F5A;2YR96%D86)L92D =&AR;W< ;F5W($E$,T5X8V5P=&EO;B B
M4W1R96%M(&UU<W0 8F4 <F5A9&%B;&4B*3L-" T*"6-H87(J"6)L:R`](&YE
M=R!C:&%R6S1=.PT*"6-O;G-T(&-H87);,UT):&5A9"`]("))1#,B.PT*#0H)
M+R\ 3&]O:R!F;W( 86X 240S('8R('1A9R!A="!T:&4 <W1A<G0 ;V8 =&AE
M('-T<F5A;3H-" ES=')E86TN<V5E:R P>#`P+"!3965K4&]S+E-E="D[#0H)
M<W1R96%M+G)E861";&]C:RAC87-T*'9O:60J*6)L:RP -"D[#0H-" EI9B`H
M*&)L:ULP("XN(#-=(#T](&AE860I("8F("AB;&M;,UT /3T ,RDI('L-" D)
M+R\ 5&AE(&-O9&4 8F5L;W< :7, 8F%S960 =&]T86QL>2!O;B!M>2!H86-K
M:6YG(&%B:6QI='DL(&%N9"!)(&MN;W< :70-" D)+R\ =&\ 8F4 :6YC;W)R
M96-T(&9O<B!C97)T86EN($E$,W8R(&QA>6]U=',N("!)(&AA=F4 >65T('1O
M(&AA8VL ;W5T#0H)"2\O('1H870 9F]R;6%T+ T*#0H)"6)O;VP)9&]N92`]
M(&9A;'-E.PT*"0EU:6YT"71A9VQE;CL-" D)=7-H;W)T"61U;6UY.PT*#0H)
M"71A9R`](&YE=R!)1#-486<[#0H)"71A9RYI9#-V97)S:6]N(#T ,CL-" T*
M"0DO+R!3:VEP(#8 8GET97,Z#0H)"7-T<F5A;2YS965K*#!X,#8L(%-E96M0
M;W,N0W5R<F5N="D[#0H-" D)+R\ 2V5E<"!R96%D:6YG(&)L;V-K<R!O9B`T
M+6-H87)A8W1E<B!I9&5N=&EF:65R<SH-" D)=VAI;&4 *"%D;VYE*2![#0H)
M"0DO+R!296%D('1H92!B;&]C:R!I9&5N=&EF:65R. T*"0D)<W1R96%M+G)E
M861";&]C:RAC87-T*'9O:60J*6)L:RP -"D[#0H)"0EI9B`H8FQK6S!=(#T]
M(#`I(&)R96%K.PT*#0H)"0DO+R!296%D('1H92!L96YG=& Z#0H)"0ES=')E
M86TN<F5A9$)L;V-K*&-A<W0H=F]I9"HI)G1A9VQE;BP -"D[#0H)"0EV97)S
M:6]N("A,:71T;&5%;F1I86XI('1A9VQE;B`](&)S=V%P*'1A9VQE;BD[#0H)
M"0DO+R!296%D(#( 9'5M8B!B>71E<SH-" D)"7-T<F5A;2YR96%D0FQO8VLH
M8V%S="AV;VED*BDF9'5M;7DL(#(I.PT*"0D)+R\ 9'5M;7D <VAO=6QD(&)E
M(&)Y=&4M<W=A<'!E9"!A;'-O("AO;FQY(&%S(&$ =7-H;W)T*0T*"0D)+R\ 
M:&]W979E<BP :70 :7, ;F5V97( =7-E9"X-" T*"0D)+R\ 3F]W+"!W:&%T
M('1O(&1O('=I=&  =&AE('-T<FEN9S\-" D)"7-W:71C:"`H8FQK6S` +BX 
M-%TI('L-" D)"0DO+R!3;VYG('1I=&QE. T*"0D)"6-A<V4 (E1)5#(B. T*
M"0D)"0ES=')E86TN<V5E:R Q+"!3965K4&]S+D-U<G)E;G0I.R`M+71A9VQE
M;CL-" D)"0D)=&%G+G1I=&QE(#T <F5A9%-T<FEN9RAS=')E86TL('1A9VQE
M;BD[#0H)"0D)"6)R96%K.PT*"0D)"2\O(%-O;F< 87)T:7-T. T*"0D)"6-A
M<V4 (E1013$B+"`B5%!%,B(Z#0H)"0D)"7-T<F5A;2YS965K*#$L(%-E96M0
M;W,N0W5R<F5N="D[("TM=&%G;&5N.PT*"0D)"0ET86<N87)T:7-T(#T <F5A
M9%-T<FEN9RAS=')E86TL('1A9VQE;BD[#0H)"0D)"6)R96%K.PT*"0D)"2\O
M($%L8G5M('1I=&QE. T*"0D)"6-A<V4 (E1!3$(B. T*"0D)"0ES=')E86TN
M<V5E:R Q+"!3965K4&]S+D-U<G)E;G0I.R`M+71A9VQE;CL-" D)"0D)=&%G
M+F%L8G5M(#T <F5A9%-T<FEN9RAS=')E86TL('1A9VQE;BD[#0H)"0D)"6)R
M96%K.PT*"0D)"2\O(%-O;F< 9V5N<F4Z#0H)"0D)8V%S92`B5$-/3B(Z#0H)
M"0D)"7-T<F5A;2YS965K*#$L(%-E96M0;W,N0W5R<F5N="D[("TM=&%G;&5N
M.PT*"0D)"0ET86<N9V5N<F4 /2!R96%D4W1R:6YG*'-T<F5A;2P =&%G;&5N
M*3L-" D)"0D)8G)E86L[#0H)"0D)+R\ 4V]N9R!T<F%C:SH ("AC86X 86QS
M;R!B92`B;B].(B!F;W)M870 =VAE<F4 ;B!I<R!T<F%C:R!A;F0 3B!I<R!T
M<F%C:W,I#0H)"0D)8V%S92`B5%)#2R(Z#0H)"0D)"7-T<F5A;2YS965K*#$L
M(%-E96M0;W,N0W5R<F5N="D[("TM=&%G;&5N.PT*"0D)"0EC:&%R6UU;72!T
M<FMS=')S(#T <W!L:70H<F5A9%-T<FEN9RAS=')E86TL('1A9VQE;BDL("(O
M(BD[#0H)"0D)"71A9RYT<F%C:R`](&%T;VDH=')K<W1R<ULP72D[#0H)"0D)
M"2\O($EF(&YO("\ <V5P87)A=&]R+"!J=7-T('-E="!A(&1U;6( 9&5F875L
M="!F;W( ;6%X=')A8VMS. T*"0D)"0EI9B`H=')K<W1R<RYL96YG=&  /3T 
M,BD-" D)"0D)"71A9RYT<F%C:W, /2!A=&]I*'1R:W-T<G-;,5TI.PT*"0D)
M"0EE;'-E#0H)"0D)"0ET86<N=')A8VMS(#T ,#L-" D)"0D)8G)E86L[#0H)
M"0D)+R\ 06QB=6T >65A<B!R96QE87-E. T*"0D)"6-A<V4 (E1915(B. T*
M"0D)"0ES=')E86TN<V5E:R Q+"!3965K4&]S+D-U<G)E;G0I.R`M+71A9VQE
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
&?0T*?0T*
`
end
Dec 06 2004
parent "Niko Korhonen" <niktheblak hotmail.com> writes:
I've actually been working for a full object oriented tag processing library 
for D quite a while now :)

It currently supports:

ID3v1 and limited ID3v2
limited Lyrics3
APEv1 and v2 (full support)
VorbisComment

It features a CLI tag scanner program which examines files for known tags.

I've been working on two versions of the library; one for D and one for 
.NET. My biggest problem is to which version I should concentrate on, and 
which version I should publish. I've already decided that  won't be updating 
both versions when I start hacking ID3v2 and Lyrics3 support (such a pain!). 
But which one to drop, I can't decide.

I personally enjoy working in D very much, but I also have to ask myself the 
question: which version of the library will be more useful to the community, 
the one in relatively unknown language called D or the one made with C#, 
usable from every .NET language. It's a tough decision, I tells you.

Whichever version should I choose to work with will be published under BSD 
license, naturally. 
Dec 07 2004