From f8abb03b401135cefb416af5b2742f4248a5fb76 Mon Sep 17 00:00:00 2001 From: Matthias Kiefer Date: Mon, 27 Oct 2014 16:10:17 +0100 Subject: [PATCH 1/2] Added support for APEv2 cover tags --- beets/mediafile.py | 67 ++++++++++++++++++++++++++++++++++++++++- test/rsrc/image.ape | Bin 0 -> 14279 bytes test/test_mediafile.py | 3 +- 3 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 test/rsrc/image.ape diff --git a/beets/mediafile.py b/beets/mediafile.py index 95bbd309dd..11c0459fdd 100644 --- a/beets/mediafile.py +++ b/beets/mediafile.py @@ -868,7 +868,7 @@ class VorbisImageStorageStyle(ListStorageStyle): base64-encoded. Values are `Image` objects. """ formats = ['OggOpus', 'OggTheora', 'OggSpeex', 'OggVorbis', - 'OggFlac', 'APEv2File', 'WavPack', 'Musepack', 'MonkeysAudio'] + 'OggFlac'] def __init__(self): super(VorbisImageStorageStyle, self).__init__( @@ -950,6 +950,70 @@ def delete(self, mutagen_file): mutagen_file.clear_pictures() +class APEv2ImageStorageStyle(ListStorageStyle): + """Store images in APEv2 tags. Values are `Image` objects. + """ + formats = ['APEv2File', 'WavPack', 'Musepack', 'MonkeysAudio', 'OptimFROG'] + + _APE_COVER_TAG_NAMES = {ImageType.other: 'Cover Art (other)', + ImageType.icon: 'Cover Art (icon)', + ImageType.other_icon: 'Cover Art (other icon)', + ImageType.front: 'Cover Art (front)', + ImageType.back: 'Cover Art (back)', + ImageType.leaflet: 'Cover Art (leaflet)', + ImageType.media: 'Cover Art (media)', + ImageType.lead_artist: 'Cover Art (lead)', + ImageType.artist: 'Cover Art (artist)', + ImageType.conductor: 'Cover Art (conductor)', + ImageType.group: 'Cover Art (band)', + ImageType.composer: 'Cover Art (composer)', + ImageType.lyricist: 'Cover Art (lyricist)', + ImageType.recording_location: 'Cover Art (studio)', + ImageType.recording_session: 'Cover Art (recording)', + ImageType.performance: 'Cover Art (performance)', + ImageType.screen_capture: 'Cover Art (movie scene)', + ImageType.fish: 'Cover Art (colored fish)', + ImageType.illustration: 'Cover Art (illustration)', + ImageType.artist_logo: 'Cover Art (band logo)', + ImageType.publisher_logo: 'Cover Art (publisher logo)' + } + + def __init__(self): + super(APEv2ImageStorageStyle, self).__init__(key='') + + def fetch(self, mutagen_file): + images = [] + for cover_type, cover_tag in APEv2ImageStorageStyle._APE_COVER_TAG_NAMES.iteritems(): + try: + frame = mutagen_file[cover_tag] + text_delimiter_index = frame.value.find('\x00') + comment = frame.value[0:text_delimiter_index] if text_delimiter_index > 0 else None + image_data = frame.value[text_delimiter_index+1:] + images.append(Image(data=image_data, type=cover_type, desc=comment)) + except KeyError: + pass + + return images + + def set_list(self, mutagen_file, values): + self.delete(mutagen_file) + + for image in values: + image_type = image.type if image.type is not None else ImageType.other + comment = image.desc if image.desc else '' + image_data = comment + "\x00" + image.data + cover_tag = APEv2ImageStorageStyle._APE_COVER_TAG_NAMES[image_type] + mutagen_file[cover_tag] = image_data + + def delete(self, mutagen_file): + """Remove all images from the file. + """ + for cover_tag in APEv2ImageStorageStyle._APE_COVER_TAG_NAMES.itervalues(): + try: + del mutagen_file[cover_tag] + except KeyError: + pass + # MediaField is a descriptor that represents a single logical field. It # aggregates several StorageStyles describing how to access the data for # each file type. @@ -1206,6 +1270,7 @@ def __init__(self): ASFImageStorageStyle(), VorbisImageStorageStyle(), FlacImageStorageStyle(), + APEv2ImageStorageStyle(), ) def __get__(self, mediafile, _): diff --git a/test/rsrc/image.ape b/test/rsrc/image.ape new file mode 100644 index 0000000000000000000000000000000000000000..f8a559289eac60d0dcc3a81cb1bac42640b8ac44 GIT binary patch literal 14279 zcmbumbBr%v5a{_G+r}N+wr$(CZQHgzcWmp9Z5wxNd-nd`d;2!oWRuNqb*fIKPMwqb z^hy8G-6>f?VS+RS0DuJm0AT)8(0}@$Y%%}O@jtuHKn~4thH5|TGyU!OczPXy@?R7g zAW{tg0R8h2|Jnb1g?~N;c{|pBv*7>ql$xzWB%mua+uW<~@W&4G6u7})?5qx7cuAO6 zcV9zwqi1s_;wx>cBVbbL(J-2{Anj}6jsgCmlH5lAY)zZ&hT`T%;)ybc$dZ)JP*zHw zQEXTsRD@$4+tJ41tt3ViPB*!ObuxMW7{2-H-# zEqf`QtL(z~Dar6x0ddW$hfkz({=2ymH&2@nm#>ev1iy7P_B|@mz@m4;(dDuGF6{pH z*)~`q4v|~NyGxvbyettN;Ae;$gl_VM$dMP(EE$~}=C2qy8HXuV63<8Tl>|%FnB~b1 zt$SB9yVDm}$z}#{j#MCl&I4iV7Ku7Jhc-*{WmU+eAd=gqtcKWx>d!O!Jsth0+?zs+hL1g7@pS%q?WExr{93xL0%i z^9aR~E#6sWIK4cIIuOYV5EmH??sCP96c~oFz+5!yjHrlY{`c2 z02!e09wA)RpV-Ge1XL;yrKW>da0&MhT&7!ptIEcBvd% z^8|UmmuoqzaYDmEJEvp~r?mGNm$ye9T-Jg2`qZ8{k#nAcS`>U4xEs=Td^rmn)ZRQ^ z-?K|0-LA9kHX^Xp#zvb%#vyzsjrWg;ZBfOFWD7e7WLqXQ0+<9<@*Log%%~_!PtN2XGKQurUh)Ly{?Kq5PmZ zhglWBe@W+}wJ$D0j4hH;Hnb*kT5TDYRvCcyo=3wAa+FN1ropCEqV@$Z6JaIqg>f4x zF}K4dLx@!7s>8S)k5V4aHYsCg&tMhD#cxbZH438p&d!|&g{!PY_ln>cLug2Vp}K#n zi}H=_C6cFd%>|~8qsi-GZTQqY)G}^{^_Zm_Lp|5AGK53NCpteg5Zxf7XM6`cB+Y^DtQ%*8V2u;K- z=78+BQXlb4eM~9YrRft`Z;dDfT1YlRzS|K9^2C>NV-_`poBG(Hv((RI-j~N+(NxZ% z_p^2zUm3WAVkoT34`S1O93@2U6l}?;!J)04MuVQm(+2HmZE__qTJ3Rcvrn!|QNL3t z+Dzj&eq;yXc)i;gl%C43KB!%}L~Cru9?nu6VB(w|%O!1r?Pulj#H3Rsvi@1OtkyF9 z6}me6Z*bL|+~b$^WtSHZ8QhJY^VdiT`huWY+t3BG)4sv+XgW_UxDk$}7hq}NPesvI z2QJi9c5b`K?9YvI;?l_!{&TKvn+1zoc@+-y6Y0tDD`VpbP0`I; zB!3mX_MKVah~Tis0WFBEH;nN&orQ^N)WFtKPy8kr|B9N3-;azvtr{f8$ z89ywH7|)U^^7(4|3s&?9;q5Z}T;}Jx28vyyw1`r)OM81?TZ?4A7h$9md^oMA?^-%b z{SQV->B3;nm1!10llX3(Ch{tFC&d4f&a{7lCrbNt8f`6%CKgPRI0h5#aiNX1S!e^c z2#jqC<1Y?n>H3?jLM9`VZXT@A(II)FB~cPBBuxiCrUtko^FU_6nm&%e>)*-|O;&`N z7!i|PTQ~)1Ak_;~Dz6(T-mg%ad*g6a+CFn6;fEeJL$t&qMpxsvxF_9Gt`E<{33^BDNXldLYByM|n55BC2YUbV<<#A@Ul@qG~;N z@5A7A!+nr^j{9D9nToy?b;Rwm_Hw_!gJ>|)Xixl%KJbmxIN860H(}NFzc#S`5Rf}V z=E-TwLs{wKo0*QeHczlUYzHGS<5ZW*9VAjSn&Y(N85~&+ajV&}eKk6m>C1x%p_o|j z{xCGTE9bHoJ_7BAG63cO^8k5urJzc|N) zO|q`eOk8G8rcW1y)+G(Aw*VG^v*%GOiK4gJsuKysoSt$z;*LoYs$J}U2pBWvd{|G& z9hD1Dyucj;R!BFw>a2RE6_>FxZoLwbJ34VrsEN>@zScp~8Pofbe})gvrR&kXZ-%`y zp#rzc@Yu@LANJ-)yN3qro91HigSrr&H(Mbga7|YWP+?7-VoCQANF@Fx#&iPk(Bi^J z*+_0hqg+4Il2L7p(!BG?=d9^LnjHlLrfSu5XJU4sShep z+6hD)%h{u==r}D)rr06MDV70o5qRDgIg8{`m9FdB0k?QQa4` zM|Y0ok4%nVz-{3(Z1-l?LpPbbqaN(@?p=dd9hjGAm)ZBVI3S9Tu2PhOOo1$TM_5g; zZuZwM%C0{j9Z9|H>^gm~?XF$u#mTI0AVuC6lU>=T!?{5b;dHJ2lOa9a?u(!HZr5o3JtaUXS_BnJf3w<$ zn<`jvco~~jmJOc2eJ17wix_>mm^|Gs6e*xRSwOnEx=%RaXZMH0zN}V)n7x7b_pLZ| z{&Sz>G}hb$dQ_u zV3*V=rTf0sY^*rty~M4?_F1!EP-irwIahD?Fx9g`n^wG2q6k z%O4nUN6&SC_D`^yxOSoT{iqhW1OplKs>&E;(o&HXR#P#@Q4j(W+voJl4&1T8OJuD* z7ZUl-t)t6PsV=m!l9kThdb-DgrSJ59)bHrN;ypd|@PJR1OAR_kHSSm%vyKQzpy2h4G=>F+V)j#p%ipbot{Bg*3d$cu#%9J%KE#LPpu<3)lQAmzKpNBK3EMBrn*EqZk%(lkJ zR}^L}qO0qi7!?^(mI=fsYa}ZHjp20Ntv%Q2sAe7Vn^}hGeWPNA&&T$YVrm^oY#ffp z*s1qiuG$K9`cMMFm_$O^_>uH0$Bvhg~ir%WmIp;YhGcx(5TI6@a~7w5=p=BA!UKr^0Xpzn7C!0Ff3z_k->#1UV>Viep4+{!Ok-x_Uu z;Z?18esbS@dLbiLyFJ85)ir9fq(D1iA!{ZaE;683rNJBEVq8adIr^~IPh%cVPE~&& z8{k6r;?(ed75=1i=Mc`1d`hgBR`y5^2_|&v>zHJo?`URaxkN}#_Ld)d!7mVEm66hP z6M3gmz@-I`Sl$i~*Dc;iR&_ncnl={M+PylK#*Bx8x;ITCXb?I+ecIOe5n<%e4YE!# za1?T&KqOrVl4V=Jcy>9UPi>pGe;*YR%45U6kFYM#6N|Yu&i8g92<}1{N|Llbze&oH zoT=%K;3CD%xIA@cz;qx*=mf;-JyX>Pm21$O2BH~wk66Hg&&WLBpO>=EsIgdFiDC%c ziw;=C#4*w;Wf?f))H{Z*TA5s3-uMWb0R0jFf`t1xU1OsMv<^ooaO4a zKPD#Ipd`;cif!*yBck^(jF>_w8^uxgC0#}G%*(V(B|hmz6I#UH-xMlaeh6X}#G7Fn z1__a%^MjwQYT*mIv=hUn!SZGSV?#lF_RWaDr$e5od@OxDsrDu&QX}JtooW=6%dr1+ z(e5950Hb%c^kv8eV;Iy8BtV9+kr+QO5)Awi+IYg`O8=HaO|rEXUgM2B6r=a$I9NH< z+Yq@Gbna-bCHBzIgh&;xl2*~pSQ%-=S?cYveKlO&_x-dFgM?8-f5&Y;I0_1Y!=Top zYLff)(k7l;PnQWJIgx#iu&)fI6E?&@Q=;_cODpAdSh!*|UE_Y@ree3 z#fTfN=%o0cso$Bsa~#Ae8(eDWTs!7c_JAbepj`&PRo|3jmpm4dQmoDg_@#Ti`T@&i z0V57mhmDqjma7p_>I|b7&$L}5`V#H4`5^pa;#X=%o#Mt z#ev9hxhl#q?;L-ONTbGb{%jgryKgv;9&6|sepFSJP^A5ddKNdElu`w6(%;+BZbPoy zWkPlsx59l^k}oX6GEx}j@pzX_8rJ+~!gYVG9G-UjEYMaRQ>rclfmj)oBvh%w7uHaw zXl-g9Sv>mrL_maJu?%P z*fzR5VW&n~3yms8=FK>rOP7uRrSn91uUF%0*h1hwfTGGJU^unzNmuJ8>;)vp2_c<) zo#VnSMO8OMT=q3by`Pl!+&7Daw%%YFL0Y&B;k4mUkG2q+;En**6}gbBqR1J7l!PX} z4vvjrG${epkh++q!ZM5Q9C04+ZzxtC<9TpAY)OsX!#Ec5pv={5yy!Eu`e(zE&%E)^ z!&5;3PvSQM*KVrp*fQYOiIoK!i`1#XA z<6*R}iO^bw$S-4^Jn3OjVyeZH?kFcxC31dQ^_tKlmWl4j%#ZxAtm1N*Yc_wf44b4X&&jN64UPQ>&}@V`-qnDkY=Ysv zIIFtLp9xj2#YW%mTi(Ty2=#qZY<1D^;N&Rx&%c@6UBoeaYgS;iw{8mFmqM*8lb4;J zXdqGXnhG&<+Z`dsFhXBDl_Os{Wds640k${+F$aqcNEDM|bL<~aLQp&#VKr{3w&;$zm#MWeR7gorRke8Dd zI(4b#dk4x>Ru;(Ycb`qHL-hI%j_bhge*JN32U|y~Zq@p$bz=ovGpYAQVjdTCOWSbM z#X-<;$xZBs!3lg$C!xwzrvoGwZ=ffRxyLbuV_HV-n3i3)KvbY;@5ghGVUB5?F`I>b znCfZ#u=a!NE79CdiEo(U)KPBo+&CZCLqr_qZkL{}Vs!>2@snp&r0_u%=ija2nVtFJ z&>wMx4iPP@oTe+XgVH#`J>H|n9#>n0N=Lp*D=D#xB*Jwb*Qe&H+Ds@U?KWcw1+g<= z_ak26!#TC+qcr%NthsVnLQWo}QGOtt`Brvm{kfS@S?WCI$v=5@ffpI;rLD_uZr=~y zoqM2Y2pM9#!p&Y=`B1kUJi%iG$MM{i78cJtk|ajcajX|&UE#X$%3_Zmf1fH9#}S)) zh};-=oh$Rq@_%_qat?Z1*sr-0`2nZarLfHsy)hQr9AxlK_iGh&c~9s?RX&&zVx~je zgKAb#gPXbID>tKFkwVp4@>ktK9?zm~1s*g2Kvf zJ0LlrO{#pg=)Uk{+vFn0KR89;FDkU25B)!{%z$53pW z!fUiexyd!tDS!wzrH*_8@0qT}fkSxXpSb*OLTQqdJpK?DTiOy5A6l!P38-zJm&9@+ z(G=pqcl#A6uvWmp79V9s+D`Wc(v~nm&8R<73$X*dF`Mrj(+Aa z>mTDj1s8O=-Yg1su;j?L`8)V-vUxT8D?vY)mcBdE`UDQ(DEEFS9d{=q;)?Kcv!8@c zV5~19OE`6K;_j^0Rsq%lOM9!j_;LujmM>VB5Y^o6SZgkzYVCe?>ENd<%Gu+x-Du(p zm`03u`SGP1AiL2tjYs$TbG@m&ekb~{eZcE8SdKpcJ%azI3>b}HNfKOPd-{y+wG zEB1cLCy8A1 zEv46<>)oIR&!(>bisS(@bR7B^5%e|&O$5DpEnL7MxX)8v2H#n}Ygy|gT0iHY+E4rk zX5RP${XMI7z$GnVvi8s`6501%47At^Iswj#_r;xK!y4F=y9G{MDfID~=M!_IZu;@j zS;Xe1f)1;k$lK+59*+Glj67q(G3B!ZHCsOI?*m_JQ7(iyqR-B0l@SE;D z#Ve~Q*EJ7-`6&9kos(7CsVu6ZXUow^{%o$rs~T1_q&gUO7+4zF&d;XkI^{#!SQXFj zFPTN#pW)yZDFo5yt09pCpI4J(VXKZj++D$P>Z1to)yO6H2pY_7C@15QFWIe{D%s@O z)sk3icrj`7jKxvt&%#kHV-KLSg3Ad?8%51HDkawrco+F3rlM{{y`K9Pb%C#=ogn|7 z;GsE#?=Am7D!Fx8TXk_LXZowE(}r zL1jX=)+~1d`)5IDq^SI~W+aU8eT~y%Mt3I=S%;~Oy9zg^!pg8tTwhWc6rYa$X3;I2 z2PYYTqli`{8EDJ>HT2~HIb{mmuxm>2E>d^!G|vwR&s${*;3X0YqMFze+L~esrh({2 zOf$Z$$#u1xJraCK46s%<1V@eGQ`E3CAJgU}H=~WDeBnY|4$TB{$n_!JL=gF+?zz=n zApDY{{GOurAsBCkkYN;|_tSDUN-~V74(K>;Rfa(37GLm2HxO=(BPB?bP}7?7y$cTIz zfH-6;@KaWR@>>i9^2t}@S;~Ojdj1%a#nil6>1Biv-JX?b?pU!sXmDquZFVpHneKHP zMVtZ!eAuhp`#=c8BIsRQr1ez_wd7ge)_~dGCdYb`?O+#H@4?Ii-7PO*eRbs>^p%?iD8v;QAa{U7)^p+br8tampdB=HGyN~ZqWF!mmd@3ve8AK{{5)# z*Yo}BFhG0$F*UN|IVtWL0v0t^Zc=mP#-lWUYYtj%yM3xr7i%Zf6NYwLe9RGEaB3V> zaJVhs&12(KW@R4ncUcyLzh6-eeP3TqJWSt(9}p*+L+`syG3Ir37r?R*n*yx@)X=$X z6rBhv=tyT%Gv&}NWSBTT0?ZKUNf%YAu@Cf_WtdV3& zq2A4}yGS{M8+QwH%%D%kDD$5}evPlQuS9?GSnckzc2;;XS`!)EI#Lrod2#$r(-)-K zf<(CV{P4KQ4la>|;hw5pPK3+4BT;&f{QFP2%^FrX2mLm31rTL~YklLTHMmYdFe#^X zEHDf>q`!AEZ%OT_Ynd+zPzuvl%k*`5`BL43?*JR0zC*63^WRcjziz9t^rLa{ zXZ?P!QF4lv&+JAHEK_%+plM%PMM8X{MJEOakOt6Yz`FahZLsp3Xp-M@==~KGGU8}% z-6(d$G^kc6H(<3a&wVGRmN5;`VKWOxmp6Fv$H~0KsNaA7s>ggXquu{?8) zqmmxkkz0po15W*EupFs}w$iv+I6qZqn}P0)i|>qQU1ng9EzAHue>ym}i*|j&GyOq) zc8N)%W-RO~2m}s#M%tqM{*tUib0YQh!3isqa+=QuCke_DS=NdLXeM0{b~j|1jD-ez zv0(-nv6d|5&sV{zkp4R27(OR_rKpUU#-dIn_WTgZx55Z(VDvVC;Aa%oOXD{?dwIF0 z}%FuyLLzp8IbmLn~bQ@x#QpaF=oCPrhK7koCvZ>GH&u~wsLJg6e zAR5@o2rm4=a0lF;Ow=CUd>s_>yo+0L(plrtOlEi1!SOQE7u8!Th+QXOK(FxoS)uApjm z-!mdrpjy{4nO=`CYz%S@$KA6^I&H(o{{^a6-(ZBC1ZSi`D2CDC^&5vbIAVR}7NQ9@ zNk?sFjS_;A){=k2<@-cbri)kEhKedUBc*DO0UPf8zOt8pXYrKESmGcON^CU{C-4W> zgjaq%AkL43RmH84Ooe8AfAP0_JG%Cy^pmq<4~&0F)!H)e&_VMlDiWQ8gyGSmy1v!V z47m>a5n70rUYQMu^cp-uf>3wJ?azwE4bSfM1Yt6cFW=Kb4P5ouG&jxvP6>=dSBl#O z=P1WB3&X;Id})jSE)n=nn>my~!pjnnlMYcU>l{(U7x+MIMVb%kzJ0OWC^rY)4J;vC zec_=h1brYXAxzf@>|39CC~?5qcV_Ykl@vpBwRE=2-t2K9*W6%7iYbPnHZcE!O<=H= zqbtk}+4mt+yHgkK$(tBaQR(N8$0jy zi+i0@D8ZcrUoa)h$QgdSbjj>R6#+socLrdNuuF|&T!ilhrLB`JSXF(-)>4{=Uz@z1 zn2pO{zBqDL$G}_*RFH4~Rf#U94QIecINI_qw zY%;@zzqEKcycbd5pwubwhmByb$ua?LCnkY%Wgm7ykwh;H7AT$nTp^#amySZUsR)F2 zD=<&T)`0N=G4)HjWgHujHh48nWnU6`Lwl=l-2OnIgq1Ey6V*-H_qnpsv6216qLxUX zIt#IKV=d_rnBAoSsu)qIrHr3Eh+92=(@txQhTFE)$NmCr&FM-kwk`o|Ojbk3L@!5H zhS?c}Zc(j*d7Xz$P=45IyI76W55uGPM`@p2_E!VlEH=|S&lLI2@ffZ-6SjhEx^9lZ z*r6sgvX{P2Eux!R)EMiqEAF3(7g!C8J)I?}1Su981pg*fJsmhX<5G%VD~Xu2#ilYY zWb5`=WaKG>oBI%p?TuZx4-P@z&;eVas7iVPlMi29j*|CLA)ct? z8uJ(7Ma8A_tGVJMeI7`pfsO-y`E6mWkM~J7XqF#G+`3-%F}5@;4UAN@bas>LK&DsS z$Fb?+asT}hn-SeO$653qOia-}mmQ{}lKIZkXHXz-ZzuV@IPeeAU+%;6i0P`VJ4-?` z5%Vu%@tRo_JZ5&m(mB8(FgVjel)Cp!o62+`O32ac-f+_6_*%3TdzK*Fn)C;aW8@ZJ zuPtu5@L)2@g?SS6SH>7i5Ay&KdluXnqN3SFN*qKB%Up%w?PAbUAuO9FJWBUz?Uj8G z%321q;&hWj9w?Np{LG5$#v=NVWN-2$u&g`F)LEb_V~=@NrK+EDoy(x7pb&z*v(?m` zsvq4NBNgcA=%;@a9GlXy>zx*ypkHO?Nj7M8W1@}>=`Hda#l|z@sj+h^S>J-dB|nG= z-Z-_2nZ>}G=bsP{BXKx6%cgDk z*VG;q61p+Is-G%`ptvg}JLT))*#7QhOx1S9%q<2N?B^BeG}s^DknW&y`+0Sn^2v5?K41dX4_ zX=whX=%h|@Q8K@b1Wx|aCd9|n>~44#43uue!pM3k!5($z+UrG+f8v;&$W`Y*nw88x z4E+VN-6Jj7WPH(vzn326js~X7dl%{)ruj-J+6Qob7ejpO;gt_ek+tv@oYNDAG5dh5 zR4MPId#db$i1EKpGKexU74el=DZ27s=6M8ECVgD{k!UYgWpX^$y?JlB6Y@(&VkQ|D ztWpv_3+&bRj0v>DSgCmFfabm7Q-7<1cc;GM&7BYa9{JquPJ>tJ`4y8`+$j`8P4|u& zuuZy&PTrvP4s90Tk55`n1GQ zLY{L%Obp=EB@`gbn0kocE)x5a2@{K&quNdVV_3qLabr+Zj8njfu4C02Q~9w~M*Qb- zVxVfOAB@$nMGHEon%g<;s$(r5vCf{ehLwPeaF(Pey%5pB_AySXbD;ucUYI)PTY}q> zfKWz0=q~U#_B@0oF21#((eF3?mSlB8SFY2MYE=Xy-s`rYg^BX(z`p^8yGbhzp8{e0{fT2L zxP`u7kX`|3kxM%wfdfP#?W*K4LloZ_B?_1K$4B|cIG-`r00nIwo*H6L6B;KfeC zHGTZn&3?MDFoXr+1Ag>WkwtT8W{O5>Hw6O6$A^J;tZskts3t`>YpvJ zZX(dEh3PG@O*-w=rJL~m*flt2nMhz%_5?>k%HR&zqZzMrfdM!X$_77yFb*Ve)#K4y zQnqUp$K{_)AsQxXJg2>4z_Q#%;45WO#H7S6FMD(zNt!7#JO8DR=?|NK&SPCz9weuE zexd0ZZT#)3?eFBi{avs!Ygb?i35~KJsd5sw$cZ1QfrNoL>s;Oh5_Jj;r_;7pz}uPg zc#V|72!&46Zft)vOn+W@7#iA|jE@8Z8hn;#4bM+bI}IkG{@WTl)YW>75r)Amn|2#9 zel8`W8iEy}(fsc05cT)#iZLVta0Yr;fny+dgjWAGHmlB`MNL+!7j3+~HIFp#{=2$e zSbU`}O*o?>(DxyI3ev#PRhi5SLpY1Za#o5q&qX`F+{ElNkto`dfvyO8iTedGZ`UJJ zvjln-Vad@pC2BF7fri(iu7Vd;u)__Gn|Cvz55uw@o~$GudX;Z{Z@qpeq^Nl(TXS&(YCB+Ej=_|ns=nwq9>I4~b#w0#HXp%$wj`I3HMm=)Eb;9Q zI@L>@>jq_Y2D9Es2P@&bU?3o$WL9Yj7PY*>U!XsssX8-rGY6xTxc)6aY zO}>fu{QZHeR-YssRImg-v^1#E#b>`7TNL$# zsSOXwT;e+Obg#TI?r^GQzt$U&VYo7Xw2K`t%UsTK03Msb2LjJWg0_0^B=)PSVzg;kp%{^X-Yr~M~k$eE_>?_56_ijF{rTH8c+(;vlJ}T8-_!rx*k;eYHS`Fi$OWwy#=|Lb7xj{SnkLG47#+|sbc^fSrU$7 z)S>qSucT|*ZrY@qfZB#;LB<46lKxG4(cofs8dC^-;UUDTTB1Uv;VPku560K?zcFuta(qh2bPjin zpXHP?HI-ZtBra{C`%|m#qfL=vZ&bN9 ze{HY$Y5blgG9DnZ5pZpvXXt&qANyKeBwvFLQZCYn>Oa(~0Mj9LIa_jyinhZlDP^5P zIH9W0QS{m$;T0e~@Imf-o&TUy`2!(O)UwuYBK|H)`ppF99hJi$2h;lo;gUEyVooKmERe) zaa%)qntgvxnND?g{Onuc2nT->4$TmKXj(Dq;O>^S2zy*A`3JMEdrdtY?~#T{Ukvh7 z%O-Y@Yl#$uh9-B5uoDb|vp3XpF@;h)-cMLdgl6MHHhCA=N3Q=(AGl&rN*g>8htcBV zXvwa0nD)0G=8Kc_R25dar!9~SqR_z0F9px=P#&!ptU(C2#WG<`!QnJg@s#`ulvF8~ z<6d%#O7HdJCxVx3tk(B6CXTRDtcy{TMzu#Ij{(g$)Zp-%8n_n@*rgu2 zA=(SBg(diKi{6kj=-$879-{PXfjm*-(01Nx3r(6{YTJB2*2F3Eco>S_4|pEPpu>;g z=AYUGYZBEphTQ~jbtUda?&8b&Z;*Q2F+30a4;4Ix+k_)Va<(f7w>)~2&6(q{U;YX> zE0ehh3)pO3o_f)5g>zvgeW~2@Ap%iFC2pu@)Vd#yOy0+ZTWVszHy$cX%g8dV8JE?r zt=PKti!;r7R%Musr0SHX*3oRga;umXCAV}ty0%sT$NKrjz~Q$XulYQ#*&aTAXLL*< zT`BSQZx0gZ&Zx3QpSdhC9=b8^?5?4tY8?iVq6tc#8Wm3?5R#d*BmBwk5rY*97CeOhm+jR?JDWl~G*-6`Xb`+!APYNi`hH~Pe&fg>`{_3c;!Flm zgdgFRKJ=E^SBT>&^h!EX@Q7Hwy9mSN)$rJKn2uNKNp*s@ogJ-bQk=HV3k`vPH2lI_ zNd?c=C-UsoRn2ZrD|W|54PZFLlM7W)K9F~OnyYJApLE#W9#ww{b(zmO0lW0WG%%`b z86N}G^7Cl?emCM0Q!~`Q=;Bb=Q@J0am&&LfnepyXy zjGfb9=5=K|P%!*yn%{l_Nq~NZ)ikpf)YH}0-uzn47{|hALSbC-Y7%T>V7-y4llDH^ zzHE;*sOz!sXWq#1GpS6YP9&kE1oD_>3CcCiI(Y{ws;7G$V!{}?&LbCqpJaTm3por) zOIa0qdVC8*fNKHQd~efqqZb5Wr1sahAgLj($&cgWhz7s;$z<2zSVt5p>|F)`8P-zh z0K0L7_YA#kI69E1lks{57-BHk(4*D?HBS-0Gvh+7 zB+`vDE7;bC=?{yNN8{c&K6;&Z@h61RZjjhgt9;z&7dxR6iTc z!yOdfkXtVO$SEiGh|{ZuxqVr150*ReSmEUOy(l#5+qsYwknvCVSzO_QQ3m`GMloSY z_`!gr*HCsWgkx-6CBu-HdE0pW3)pvlK`5o{@0BJ-hJ&Qg-TuC0m#Im=io}y`df#%b zqh)tS5dcCKckC;=SukMPqdD@?*H>mu6gX$x|FqFX{MX8(|6fm!pn|B1ptz{U90UO1 z4FUiF{}%)R3jT-vXUhNSe=%WuH&Z79K_?di3Nt5rI~PiTp^cHNErIcWaX_SkoH!gb zHuS$lI7tZ+rT?`E1oFS7Y!Q+x{{|=r2~B4J0Ont#5ey0tAS>s;)+7iQNm)^d9bjm9 zSVSox^vr)DEEiD?7h!u_TT?q1fUuLPp^K>rfxD%P1%bGvtb%$VJjTByG)WOb706ZN z&z~QD5D*ZQe;Nb~;KTs|nGf|R|Ca!e6qOUH6*36&|5w8Q4ZzUJ#nSm7fs2JH!T(D!BG?qA&4ANnF13FA&G?=2GEq|Z%LSqoPwaB(J?Twut~|tDJZE}SlQS)IJtyH zM8(7 Date: Tue, 28 Oct 2014 08:25:44 +0100 Subject: [PATCH 2/2] Style adjustments --- beets/mediafile.py | 63 +++++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/beets/mediafile.py b/beets/mediafile.py index 11c0459fdd..ace8288b40 100644 --- a/beets/mediafile.py +++ b/beets/mediafile.py @@ -955,41 +955,44 @@ class APEv2ImageStorageStyle(ListStorageStyle): """ formats = ['APEv2File', 'WavPack', 'Musepack', 'MonkeysAudio', 'OptimFROG'] - _APE_COVER_TAG_NAMES = {ImageType.other: 'Cover Art (other)', - ImageType.icon: 'Cover Art (icon)', - ImageType.other_icon: 'Cover Art (other icon)', - ImageType.front: 'Cover Art (front)', - ImageType.back: 'Cover Art (back)', - ImageType.leaflet: 'Cover Art (leaflet)', - ImageType.media: 'Cover Art (media)', - ImageType.lead_artist: 'Cover Art (lead)', - ImageType.artist: 'Cover Art (artist)', - ImageType.conductor: 'Cover Art (conductor)', - ImageType.group: 'Cover Art (band)', - ImageType.composer: 'Cover Art (composer)', - ImageType.lyricist: 'Cover Art (lyricist)', - ImageType.recording_location: 'Cover Art (studio)', - ImageType.recording_session: 'Cover Art (recording)', - ImageType.performance: 'Cover Art (performance)', - ImageType.screen_capture: 'Cover Art (movie scene)', - ImageType.fish: 'Cover Art (colored fish)', - ImageType.illustration: 'Cover Art (illustration)', - ImageType.artist_logo: 'Cover Art (band logo)', - ImageType.publisher_logo: 'Cover Art (publisher logo)' - } + _APE_COVER_TAG_NAMES = { + ImageType.other: 'Cover Art (other)', + ImageType.icon: 'Cover Art (icon)', + ImageType.other_icon: 'Cover Art (other icon)', + ImageType.front: 'Cover Art (front)', + ImageType.back: 'Cover Art (back)', + ImageType.leaflet: 'Cover Art (leaflet)', + ImageType.media: 'Cover Art (media)', + ImageType.lead_artist: 'Cover Art (lead)', + ImageType.artist: 'Cover Art (artist)', + ImageType.conductor: 'Cover Art (conductor)', + ImageType.group: 'Cover Art (band)', + ImageType.composer: 'Cover Art (composer)', + ImageType.lyricist: 'Cover Art (lyricist)', + ImageType.recording_location: 'Cover Art (studio)', + ImageType.recording_session: 'Cover Art (recording)', + ImageType.performance: 'Cover Art (performance)', + ImageType.screen_capture: 'Cover Art (movie scene)', + ImageType.fish: 'Cover Art (colored fish)', + ImageType.illustration: 'Cover Art (illustration)', + ImageType.artist_logo: 'Cover Art (band logo)', + ImageType.publisher_logo: 'Cover Art (publisher logo)'} def __init__(self): super(APEv2ImageStorageStyle, self).__init__(key='') def fetch(self, mutagen_file): images = [] - for cover_type, cover_tag in APEv2ImageStorageStyle._APE_COVER_TAG_NAMES.iteritems(): + for cover_type, cover_tag in \ + APEv2ImageStorageStyle._APE_COVER_TAG_NAMES.iteritems(): try: frame = mutagen_file[cover_tag] text_delimiter_index = frame.value.find('\x00') - comment = frame.value[0:text_delimiter_index] if text_delimiter_index > 0 else None - image_data = frame.value[text_delimiter_index+1:] - images.append(Image(data=image_data, type=cover_type, desc=comment)) + comment = frame.value[0:text_delimiter_index] \ + if text_delimiter_index > 0 else None + image_data = frame.value[text_delimiter_index + 1:] + images.append(Image(data=image_data, type=cover_type, + desc=comment)) except KeyError: pass @@ -999,8 +1002,8 @@ def set_list(self, mutagen_file, values): self.delete(mutagen_file) for image in values: - image_type = image.type if image.type is not None else ImageType.other - comment = image.desc if image.desc else '' + image_type = image.type or ImageType.other + comment = image.desc or '' image_data = comment + "\x00" + image.data cover_tag = APEv2ImageStorageStyle._APE_COVER_TAG_NAMES[image_type] mutagen_file[cover_tag] = image_data @@ -1008,12 +1011,14 @@ def set_list(self, mutagen_file, values): def delete(self, mutagen_file): """Remove all images from the file. """ - for cover_tag in APEv2ImageStorageStyle._APE_COVER_TAG_NAMES.itervalues(): + for cover_tag in \ + APEv2ImageStorageStyle._APE_COVER_TAG_NAMES.itervalues(): try: del mutagen_file[cover_tag] except KeyError: pass + # MediaField is a descriptor that represents a single logical field. It # aggregates several StorageStyles describing how to access the data for # each file type.