k9copy/0000755000175000017550000000000012417736223012552 5ustar emulatoremulatork9copy/data/0000755000175000017550000000000012412271773013462 5ustar emulatoremulatork9copy/data/mencoder.xml0000644000175000017550000052535012412271773016012 0ustar emulatoremulator k9copy/data/aright.png0000644000175000017550000000101612412271773015444 0ustar emulatoremulatorPNG  IHDRasRGBbKGD pHYs:tIME M`IDAT8˥=oA߽;NQQ!A|.JGN+VX4-@V?"-[ur3yhqJozkr? Znq[urtj; JycF>/jZ`ms!l6?U*Fq vP!R @kMŢeY֭8Bp LӤQ! CH)!mJ|BA-X}J)mY;cfR$I)%|}:_od2l6PJAJDBx%RJ)c/m0T$k)hxLӤ!x6N981L~.˳`/poVCq3SuIZIENDB`k9copy/data/anim.mng0000644000175000017550000216673612412271773015136 0ustar emulatoremulatorMNG  MHDRdG? TERMd6EstEXtTitleCreated using The GIMP]wgAMA|QtIME ZFRAMd2M IHDRg- IDATx^YdIs?K77ʬ{)螞iрh$  d3Ii4#!FbG=^=zwlj7ʮngv,NǏv(| Cx* +ԁR 28a;+0{ ,I KVp xU³P-yXѐ.0~GpU # 1)X jղ^- Gd^Ya0Šʞh@rx/äH\~؆b^Zuw݀z3 [qT+AЌ aH"T0 ZEyjZ,Mɒl2!KS$ѓ|sdpMp`&?BM>\i@ T!Bp:z]vւz#++njCh5*QcZ Eǁ<0cl4"zzpgGnVy@փd `{dlf7vk bhpWZ :ڀN# aXDQqՒFCVW--ؠP[^&j[-VZ%cjwҔ|2AIJ~do۷0eϠ~?ߙL,~IFM֏+X>WO. !FT;kkZ6+VP]Z"n6En7D6aFlT*8FFA#!@P+std>l0 c}1NvJ  voGg!r}<߆ QVcseEl;s^Bcs΅ TMz~<:Tlo3}[:~ȭ~[${/=c3–oLwoz@لn~_ ^Y]X]beZmt[jzM'Oܤ},qKDP!dORJxymڡSXC߹# {~uo8\R*?6_iG.: 8+RϬ'y&9^667EueETMz8*2aD֨$A+J>hdwѝ;zp޿zUWw]e[ MZ~$pdτSK,mqs'Y:^Ih +{kk2 jJS]1sGͰR6›7 FGpE/gWag|LbiB܅ss=[/-57ztd9sFN}յ5jǏ?{DJc17o>n^ss<>xO;ɝ)?i]KJpc='}SrEuuY50ic>'Z)^;-&O_U7y'@ ooG^)|cPm M3ux᜔6+S˭9ϰOнtօ z9 #O|GGȗoN9UkkTEEA\Ͱo緶 //tg/]^yE\@ɢЋ<>hX1CɂByP8֠21qB# YsES8;2#H q6AS?Qt쓧NʙW_>w5eS[ρ`AUֆc/.OsMc9C;>μڲ9 C*6%ь"qR eJxwȓes1©Μ\˿r33T c  ` ۅI<)lQY455'zMjݮ<)xӾ\-m&ޣ<>\B /v^fsjhWg?K%l6Aty>-r]:*Mw ^zC,> *8%I<BԂCzYG'DExz}/֞*yxQ֦r 1=<,S,;؊@˅ CV  A@@Υ;,m9Js˭OFB dCn&o:,ePV Ȃg&?;oN.L:qKmc lnJ[\N=cUÏ ?rO6g_~rS+WPD!:ctNyxBڎx6e;~?R,hQwۉm+\QG#c=; x# -/m࿺/~Y\_NOqJS~l0@M&p5XQy?iJ#ſwZ4xY>`/,aaȽwO] QEӡsFC?#d( 'a"|J޽pJ>%Oψօ 䣑9cdbR*PܑIJTCFYY^$3ڲ3DIXR]^Fj-G׮ET, 8;7pKȂ}t9 g^m_yls66f d2e )Ż(0,dW@/Q0 X(9 #4^r A^qs[|0 :/\gRԎGHI>3%Ttx(2@Vݹ=sLZ_|0X,iS|kEa ZѠD[͛ioA+σh ګ/6~+O|5pcCP%L?2/8H}@`/$Vt:$wp8 2R>@ W/'.OɗΟoYg:˟|̟쳄Yov&Eۅca٬0WT?p?Qg:l%zLxwq0\Mf*VKoܨ޾{we^@EW'O}K (fp8+Ý[DˈBJs|Qq6v3scBXwQUEmCe{-MAt2ڂ7'l  ^j,~@9 qz+J_b(W\Llo32}}>ksMv v^^n zN<@Ek36FCJ1! EѶәAug^0$j D)@l+ಀ7~sr/ҕ_\{e*.2 II{=^o:KjHW,+j-}3{E6>i*Lvw߽Kg<^ń́pjAPBa# %x,pCsx<>SHY3br9F'35aFuubᇒ?G݃_zCJr^n_dtBOT9{ʊY0}hv-%p-T¥gRRE4@]̼{/ 牐re-Q\]C[V+ *ΎbkKz 6 /vͳ/d@vp9%̀˞/&BeF82%Y`Okw0'̷P\~hZ OйCvG)Mgnܠz5؅Ge瞂0<̥K3&O~K5-wp@6GAy}{[z(^wvY{\޽2Xr<`&X|9⠔O1ewQg 0h~!m^% ?]^1mӄ/+5gSʹsTWV} [9xi˺v/qޭmO&dv|8,4-rM.#3빝 F{i{ v])Y?w<}lK2]1nG)*I@kjۥsǏ<43 *Ϯv?/ThnήQ=e~!Z ~ X_Μ'd`mP#`$\8U_9Ro,V9D8 ܦMܯE7:Yڷ`t~RyNЊc֢oD}7{g-pYczĉ>]L)~4[[!Ȍ4X0=j@Na2^\"-l|=hRŀ`Wg6!%Hy8R6zޓ-:i]8 j1t55RJ8F?k$q>×wOUʪkO=^@eiu^i6W>hWDnbdwޞX&p1B q۸m.Lw[ڏ˔<,b@(dyR0"zk^X@i[~3v(^E-51ܸ{y]ineJ TVKAccCĝ@t(R 0E㽔9`{9LtO85)ӝ/Ra=], |^+WBx\gB0ZM{y^VaS.'IQQEI:Ǐ 0{}*@>]D'NSDeef^t84/L*,O,?WldR|2)%UWFޚ|Z(d-Wb)hH>PlZKIb*ds%>ŋjU_SMr}BxeNtdk}]v_f$$~a-3>H͉)E%~Aiqa(-,0͗0^ѯwgo}[&-¸sY6|kn0˂jcD !nd.{vt![ǞzQ|9&U9ڱ A iaGJ"љC)B|0,%vO@wpVvƽ|Р-ox= _xj)ΧMD0E̬)n4r8e428{j@'*pjV/\ǔqvғ/T<#g|JG|c9[q]ogF-ݗ@Q,\Z}ǗX ?1}Y9ρ_^ vgy9stF45=h@>sŊs`j0$0$p[%Gy"_1hdlLeS+OHy_ݓ,օ ib];{j s\>" ɓ MQDscӧ9[y7Ih r(cX';aXkta1FC#v~ EO+΍g,°(#2NMWn å$1?a S>-^f*Dg4޹ͥ[Ҧ;wQ#ϑql:-/t$ߎkIr.go{omq\kZ@hMw~'b mf;D`~쥕NVnc"CPdhzgjH;fܸscTEݣ[KrR|ex. ߅samY`uWNg&=к6aNsm-Xcɲg&Gsl|շ'vMԖ5Cy^U2e I*I ; A0'l8$ G L[P,P]TAVڟanN-ĖSkbϙSn7aBscޗl  X"}8|spu@*Ab [)1УcL'Zk Ʌ02 - IDAT |lk *?m+\kᐰѠLDf$3w̎b8m>dk xNQs(e@)JjMx01 dd1ϭښT=*M9mDKAűN`C0"*M;ݝ6VqkznBPyn@$! *j2) EŌnm+~p@pGX:sLxw-/B)rN5Zm6@‹ӂ22wǕ0)++CBIRnG-ȹ~2+ř^JWXnܵSf:$)*W|tJHY J=3D"}(?׆dB&^p}_| |SU횱` iKGW {V_[.r+ѠZpxڸa>m+g^nu¸c,e`|P㞭x4"R7:Q ̲-esn/]DF!q ҃ƻQ\Jic!={ͻH Ĭ=x/q!K7I~geA=/ N1qCeyiZZ)G6;Eٖx3 `bSɓ+a-EGڂ_nKDžsP^R|ʬ <:qLrp`*RhX^0 %` ɇ9d"RJ h8,ƀu&",e!7Ō|d)SY;׉ L#)aHlw:ĝ٪: 24p]j/ e'[XЧ>aFLh& Y}^sU2NH/lw=`>>/O&VMjAB8Z~԰ZE٦# &Q1V (ef"&Sם@4̏Ϧ ;wכ~0`ӫUZ0_K8ݾdgf :ӧtD6R!^^&V U&Qs0Mrr4dgZYPRk]46϶M)è> ;^+)3ʭE$Qd*B" CF K|wd a@j$3%wCp24]",>u@^`Uʬ2hDb` a!ÐV#j6n6H; nݢ{KmS+VΙ3ٶ$ +lhqs΃l8$ кuͽc dfuiv L3 æYij f\Z.KWef.ʲbr3ќK a!r` ڣo @P/D:)ۋ>@]3Y\Vil"N`aO]Bgf j9_:>۷97H{ne{{{`K!j"n|t ן>^$뛛"t>*ܸ)Lz8tW)Xl8>TnTܺeMP/ΧՔUYٴORNuaFDz Q '{PTg-< PJN9f"O\C!eQ`wN" P0N]; Uz0c,cwyun}[n7דdzr*ݽ[xNz0^IO=EOZ[2+*SJd!%6LAa.cfjh[Ͳߴf0s5OSD!A0D6\q|NCMѱbQ#e%0]:bj4s1 8o"#"gn"03z8AJ&1;7{+zZP.@KyF+GWZ)2E)!Ðxi eLvvHʌLLJө+gaJt`9 mpr.+l/}UՃcIU4'a(* 80WL!0V&A`liJ_@e7ܯMޒhyh{\Fj*^n}?~>)\S[Pñ.mX~kw_ں.(j: 98FV,5l4"yU+s7Cݱ P$ʦ)I  xϜ,+dnV24жw/( ulEފ Q?'Z3us _D`-- ǤΛo[[߀ `j du?̿^o,_KKTWWϣfQDQlZB(7Nli~ drf>fhtͭz[OU)D B=P gVyYLHYk>^~ =`c];)[&zXV"Ʉݷ7hۅk ~{%Iwԯg^ {oh:E47*2mTbJk(gjÊe;㺁Pd6Maa\J)U9C[̀;7Q ggZDB,20;BR0'Z) @2 a׻w_{Mu5M}]3")RsHl_WׇCNw:BrvU v)FX-șsړRyf;-s"*MQe1lΧ"d>ANC Êvm'ZMYg>gz=)a\3se"Zzm~! ' >'}Ew;P_]5֗;vXϫ:Έg6]Mܳ 5ǀ.|gd>hL[BA@DPuAfKQ4 .kp[Z};/LeXF繙o !PYF2{yAH $MϏUrp $`R ,ڱUMȇJMWv ,U< g+*[)1{X)b:bb:,-ֶRY>8i:X>x}$t SU0ufl>-Z)'I>V*ᆂ;6K ~W+5TI"-; llڄ@hv-s02MtfSwaE+S]"l)SZE”/ lB!-mL;0g9)SX0 gYu\(@k!tL.ܕYUkeB[;g9g>NŽΧa6}e[w=uiZ`>S@ ^@޳̏Z|e擡/vg4=L{8pI;@hAT5rY<&8kͦj5B:11ihmL=؈WR45m>|9s|TҌc,3SҔ\)r(l&GS(+W8ZfB22fϔ2Q4% C[!aIeiJx"eYWn̑%ZVvel׈b2 @Y+ac 3;iT-lD*[ 7|aiy2R0(Pi9pl |}y  XgāR,f>OHK]yjV̢L׹a>'jE1y|m-_v* Q\Z7En#3ŧbl" 89s r_\O Q1PYFdP+im 1/|BQ͗cS1ڔ'l:VI,HWAeyYlDk?GӈG׫߷r4N@a8رcF{{?F\ 2-ω̬H9y q 6eDh0[ȇ\<>q|钙) 䣑hD61: 8q"ٮhF=p 0\o:BڦMZ|o,|QxFNj6ynVi; +PYfMԏ'T| iME'oSV4j?xʕҙ3ɇC&L]80c*80>I2Bg2γL p3lnh4Z 2τeƛc.0u͹Gg>WfAnE?9*3A^ϬqKhq670|n֭Wn(5'^6?S_Z=w|But (a42 fm~ ^T\[&Tfz,+ޏ(!L Y.̌RZ)ދ<1]>gسqtfO+UV*1]V'cdڧ?WWVk_J?pMz7ʁqϯ66/njP[_ngV$z=5|^|04_ ,H > -iHfhcIB*;la$ZzFa*5$ Øo|>xraPwnGM6!Iz=F7oӔxy6쬭BeYT*w 8Z)-@AVۭ676+WDq!#- ܇}pڜ*g'Ltti|`Od n,MT\ εߟk/Xeţ0L\0,&gW>.ҮWT3۟6'fkd e:  UzOLl8lIR3NZ0nð^Q-jհ]Gxg;$nNqͪ8!aJXe Ǔ`>' =jtl31SB;I6T]PVCSLʓsD ذij< ) eYet6;wݽdoXt6шq2qa46Z<OĭI,0 ܟ"o)3;B;w10Il=d9g O ˲ 5,BJ)9 Hcj(6po=L}@΁g>_w7o.ws:I}mbK"lW[ˑ3C-~_CuP:jv]mi||\6<11̓p/a LcV2*3qn۶l<&@"Q 0,'sR3CZ^kڂ^k|VB7&=ixܤv,=W͌fx'iV;ݗ, Yf"JݻŬ(lmT/2@{\6!Q%`QeŬg[]30!hpZk~79 ZAϤ/ja([ˎ|AkU ͘pPfqnfldL'v :m #,3`0UϗqLh7xl/%+ çs#F cvA'rG[?g` '|Aq,6W>Ucf":8  ̾#1؜=4^D2 uQcSS!龙쐐|?ls"OHiLzl'ކ|o!omx~ߌ[,`,$ jNd>ޮZ;=7bju J|Lf{KXe @f65Mhͧ._y2qUls~}(]H-(9ZPWX/ՐAL2v}e/Dž q:M $zW|L:ۃ{Y<6(Edk/X|ܯsb5 i>|s' `b|>nl/m,"o**5o>:aS iڽ'" u,#Cu"IǍBGαJ;;G|1ûj8'heWvw5-h>(S#3e"pB GOȨ8f=GqUR!l6ya}z"NsbAS$NJ*_c-|~mQ2߾ͮ~ pN0FIƽa[(3b|A0  9pI(>b (EU)39 q3[\ _>M"!%anv_Z2&aCqXҐfcKok-~ C`d o {7odI}8#$߃gLܾ֖4#AVA(.ݥfqI7U0njh]G[fPYfY%,3Nz*.c'Nt"qKh=t t66AI}3705gӜI=F{{F:6 ЌFɏʏ]q:e!`&;ׯ0?-Ge- $؃[;Y1ّ VZB#3vRL{ >wa֭EVZ`|0lXD|TvhMwo7+E"s#hԥSXt5ԳV3-Ӆ#aVyΨcm|e,G @VR|z\th?n *PuWP ܋\Mcv^7xxc4*fn(I;C,#v׿JT77M|׮1{~y[wﲋY #͗r>ʕD1)Eߧr.aȉZNMg}*c/˩׬&׮q`:*H<=;2vw^;Pvuӕ}z7npw0BևVia2_rق^ >2"!4=?/и22=EdIvwy-4 0[v%GhvmW˜V=: 'X|#0v__}}~[k1v/P俍ɫ;_wbE0Ba1e8К>~J\[9^+20PMܺիx=`ji%gz:rڽ=mlBQP$F  %"BK@(L !$R(Q 3$E>aLiۄ˰f{4һ;] ؄W_(˥z}4MӴ, vddbޢiS%Hn7y ÐZI׸꫼nsYk\f&p~sҒ_k6ᐛ)+HwĀ{#FnF6N](.^.]pws 7GzTLm 8kO?=+}.OW!FThĤѠ&F#꯽^|=<B)r>OZ,9C~i"p?йq^uZ;Rw2 2˒=0y& 0tC+%~" 1_N*h* g 2s:<(,1p vݸA7"-tXbi䓜# dε-o|<1GU#JlZ)7o g yS; y(f&ٳ"/MR-\ybL(Y!TeS2#ag%RطI`oA(6;&  '%hZiSd(y̘?L:@H7_<ƕ+LmR]l6i Rr^|''ٷ%c\'[@β[B6+d6JbJӹ'PvHU$]unaЃr_=}v3 8Sq#G%>'i5M%L%L y= m;20YQ3QV.G\\(PzLD;$߇H1Qkׯ~I|Wk c90t}l2v>Z]*arj5Ԯ]{χh!R}WHD$Rx!z7F#7_3n^~Gt*dRvMc6RIeJx.Ipc)|FBL~0#ZtC~B*P"5FO CeDHWBB!UDJM9HH/Ǡ5G7U5 VYS/Y*^j-dB8H< z @4gAi#Q䙤6h:FO&>|Ӈ<6g3UzJi%ˉK ̓v! Noc0 f6|.G h!I`VNvyYRǴ^glzMn2g4MD?ȫQ&R 8hcň }IkTiNB<ù=a|fcG.^$cڮm'W^!t]6ݽ=n1Wr^jmɅO& E_C.0`ҩ$ƭ7Xm7>^@w/j52,,,̪ftzS\!0dQD*EѠ)1:s+ d1)RopIVNdP|xyJ*eC'OrXxq0 ץ9K#FI套PQ7ylk-$3OL$òMquUփw@M; q_v;.iTSgRЙJ0W˼pH42jiw{u"R4dXF=o<_v4>1Y\}:/OtN70ETqޘLp_{ 7h1;uDBȵב:/EӧOs _0yXc}4/< $c&.ݽ=n4rG;pe?3C# @o'"+"eyo0 v^SjVr!" BwT8Қ?p=ɓ8IqiX6 JZrYSS:q+&&cȄ}ɶ!B pm:%@clK#9A{1!mήjh%THÐ0U(!)yEx>: GC% @^g߁ЉQai)-/SJz2k)Oϛ3Lvwomvi' ݮep4yVcIN\S(V1- AZͽ=փ]ڏ C?^`>:JѠ=̀G_R5noZV0s Or3a9ʏ|؃7m|foV]|] iR{oosF)6(le'T|"(""z]Z-A a~+HNC}! ~?&3W÷ުhf!p2Fvq,h `XV6z3ɨٗ~6ڈw[*B&z.b:5J++$Ϛ0Άa,,.ruKyUAl?](Ӭ_H)R }:>SduH EKP,s9r9שml|,ukkX4 J#.--KH8ZEe1h6֭[E\aߞ/?[k_{T?DQNjS(`欩Nq )2*++v*Yࠚ5%.8 Jj2MrڬS3*%jIk42ZOe8<"O X|) 'Nj߹2kyzoE߿#`?]NS(˔YOiiGF#$HQ3M>#<76p*9Xڽt//SɓԧX{9{,bLLasD SN^ݻҰ̽^K0˨٤_hA_˃:}Ejw_ǵRN8dTA-JI4^JƴŐ 4,1H>1'Ne=} X|qde@ C )/Vj#?wE1hʼuN.]׮[6=wxL;6}G"hTyq8s$j>*5 LDu" (L9p Lno]F0PX\$[ dZj2u& aH>Mjj5Jeb8I3)fH$ņnðݦQ[ ؅Fÿ~Å Cu0FO&JhK4ڀ:!ی4)RɖldERXL3#j YZ)Qnӑ LR4n4ܼիܼ}[o.|9DGF@)tlxyCx ӞN DzULC(4WB1 HC$;CӿӲL>OZ.Uʖ4#yX( z=i7-=R* u> \FK \Oj2|pyxUå \ArSp] 2[NB؆:pNȄ8au=$>Z5[#b.|И]wL2v0$v nflRp(1Zݫ7N!>N!1LXQdľohm¹b'NT5 _dLfG3)ZMYKxDs2tpM&&nŤblѷm}u-C=G`p' .mo~&s*rgu:fZ5J j58^,J؎17 :0 $,yf瘼q/EF)Dz.^QG2Q|?nhv10W*-~ O.Ey76Ccs0Bi:%[.%f2>ɩ6C#]Έ0a]TDpt*vz:>nw ;Z>"t!L|!>?p$`̰+&|k cȏʄáfm<6sZͰs9Ba>lqpe0P]oOV#[*KG29ii9אLBcJtIHJ3H4IA3REIZ1 Hc0N&f^w8?1<J6CN͇_}0E_"Z\ \9yl䡪H2%v6{@P{!ٮҥ*=wy-8ZTH)Z&) PUe:2utSn& z:1|EïpurчG%([g d 28f)3$v$^vR SPyؔ(PN or"(Ώ%0ElpglS6\B;VFHh:`& #MbN{ jt}SP>JE, bR0qO JP&Zj¢ 86X( "% A2{xKA7F 7#xEG\Q{'E!Xŀ%&,iXҷriRgƘ"uY:tLQ4OR7~  eIENDB`FRAMd{Z IHDRg- IDATx^yd}|GU]333; DR)xDPeYRX`Xvl#d9h[+2CT")A.ٙ9#3_e9vv_̗o~??PDO pk1@WB  @ef )\UNom{ş $I KVpxAcP-[ѐ.0~[?pY5 #I?q x V$|@Y3>bY +_Ya0Šnj|_sx#¤G\~؆#1*<[&4PBf VIÐ8 E\Da!QJF9Y% dB$I'yY<fp>F3}+#GM~dX!|7&p}G$؂zÇdVOAFT;Z6+VP]Z"n6En7D6aFlT*8FFA#!@B9:y^2QIB6$pRpk+ݸ1[ۣ`RM_>9/']x&%c9TOG QVc}eE=ٳt:穬6:"| 4%d|yE~oׯ뫓IF;f6 y:3g]%Z p=HB +e'ckvNb9w|lc#;RM<_Y*X,?4 4p9*ߩÿW{IC++G=x1lʊ,/5OK0,qgYY:wgNh +k~W)d63$br{ 7acelC0м?7K~;߹ [7}RK.<ۄ,g{V[=\{ɓq硇DIgR]]v8Qc{j<6ow~Uvz7wn^yx7[4a ߹pJ%Sѱ'>!䓢zR!j6a8G|NR&_; &յ^x{{}ȶ!|y`o|}j j_Sg<^,Z^n;ǩg{" rF$,(%.ߜj5sUTWW,/ ^:a[ߊml諣љwqN/[oî{*Aὔ&pR=y'+|c?O:{ډmm!:ͥԡ.!=,ZkdT**nhu]Ye=IvrЃ#'M+{t 8z=>tx4R13Tβi"l)H0w#.s3L66x~7E䯍Fh oI|x{΀Ax>܁_}z.>xQz9Ss<'B/f,}b;%(TqiA)dcJF3Rpfdf70 xٿԡs|$\xVyqѽxQ^mhM!LOz]pab_0 ߋT}5(EMKen_L|F0چI؄y1Xÿw~ ~,=r\O|"8 b'E*++)tW|c,ݳh=g9Sˢ{]wfIQDnᩣG PZ2ϣZ$-Can>p6ASGHS'?C/^},qk5*˦& /`*^:\rKv ie!{TmjKKEh/ds !n` O8x΅},~k?OGZ-fI<ͤ)lQY455'zujݮ<)xվG38?,MA?Ϲ_@O<'a!7zR!ÐBFFPۓa} gS؉w m~,\z9v[ٟ/#=G dCno:8PP(\+e `grɝ0 D!ANR[[cy:RooW&/,kjU]dw'.sc>[9ɕK#e1:Mʥ_'?)O1*M}5րb@A)ӔC]h~须w)ҿ <8}] KmwRT*DNαc ~7/| |h5 xR=R>$OO䣑cdbR*PǹܡIJT}F΍>"ݻt$3ڲ"IXR]^Fj-GWDlmU, 83pŋȂҽw9 5S/ǟ{lx'&d$R.^da%Y4"@/au7 X)5 #48&nNkgOv-xk&=}`u/\'G~Eqid{|42KmCFf4a0c@r*y[  ܊0ŒQAeiC\y~5M3XoП+/Gpy<\{9&ҝ^7g;&L kp*ǎ9!#R؊3 1ڻ>.;/0~!%AJ!uKaPܔR!{9 tϜ;x֞}V4O$l4HwvHHm7ˡ53,@92 eڹP|%cuXyrh%ʌW:.|TJ>RA`:!T&noYvt!N!?;'sv:GǣGE ~ߜ IebZLk#`6\S%{:pp>t(Jtߙ<8s~:·uR0fkIlR?rz%׮Uoܺ2F^} s>DED l8.]]"eD B!q߯6}v6`f{L.*HRvpni BӔ\F8dcMbcO#w>Wt?O}Sr%jkkɄ& 3糆 0$k`aX= d_6 aso6$r\m1;B!QEh 8Mib_ p|PK-; qѣ>iT]dz$ӕ-`2 S8 _1R ;egu7 ĤcN0J鸫4ˆ`vl8ڊߡ \(m42Г Rkh$v^ n(uR&|-'vu'x惫K?8<}|Vg_Fmjݽ%+K)}esE,f*sw쥲̼? #?/OT|r8H̀A Wn<nٺXGejSmδ!Иjkќ0-t~"Ѻ`@l24+rNEg@1Z4VC(0M>}ޅއ YpNpgHWA!F׮t϶o+kwtw/!D{eY,=ԥq#t lC+TJ6sC(#`$\8*)Mo,V9Dܦ?EWb@VL-~eA5"ω:ZqZt7~a|; }м$g>y)?A}m " HHz=ϫm`g:NW86L(O/NeX~|Rb6!%H/rͧʼ* &׹iz2/Q ,CY1CscBԗWΙ:V ѪGRYZ"O c`хG ,]~VY6&bE{iyPr<;Zu=f > 2͉m R ѹ9wW 6fPhT6T8ږߌ*GQ}`yas0D s!nj^`42<}>+#}BPvȥ\aG˔3lI='"p ^aʕW j:pzZM{\|gyeZOs< sr`'$x/>YxWP2D45dۡ&s4R|eF b ']ku`>}_}-ٌWx0+:B KKt{vpk_/J3?&jVB=B !/lERdLnj9Wdvs w+BzCC D;D) L~[f;@p4z+ .Xq_ΝӑNcn. Uj4f3< q>tf302` Vى(b d|Th22a9ň1:G}(Eh/ŸV!dtgZ_Hk׹>l؃=|3sh?B9|4L\:̞Fѣ?΅[M&lNN>\=~.TDE(1Kqv҃/T4Cg|J]c>1yr٭p*.{Rܰ(JKK&Ǧ},ڱV[jUA4pH6)*gY03<>błԷ)U4OT[p~ݖü|42SjvCD !؁c>!z;ݖ,EO/+ĺsw|j s\:;wIB(ޮ$?ׂ~ cǎG=YVEEH1UXa[eطvw~iй;%<0, PS31BB"IO"E:|`NeATz``Aݻ\(mscsGE:Ǧ2K'Oyո$gx +6\=q Ѯ]6$*A(,L#YM~ġY…0M C=8h0/zf:4Bǀ@Ev`ahuE9 FX> 8p^sXMQө5ǀ]wsf¸dy!G#t5 YLngVL Fsj$aHϲ<:h`&ڭ)lf 5kFA( THiN)Z5 5MnѲc L:(2V j5*gH}W1 &OHşLg"v_[Xݕo/. %qMX\] VXv |2!M'-l=i|N*3=kmA@vSY kaJ[nNѮžgL܌ z ̕{ ٸAA6T;Eb p4p…n./7%ƕ 21 ӹ@vG^1t'Zk IDAT Ʌ02L-f|lk *?n_029 g!aAey(ω͢I$(+kpR8߿Ml=~m="G)_ +6v㻻53O'# X[Z`ѐVSĈA%a?=Dםct,[X 45')`d{{ZŁͻusQV3"Ls$AQ0VQI Qdc%bZӯ*˹c=wn>Pm9p~ Jcu52[-6k iAN[]^~hZAhP9697NfsxԌ u&O``fL|<.@XLY ) Pa;-r 0 a+1 AStrv _OcsǀªXա[ϕ}8! 7y .Guϝ3Hy6TDZE(/ÈVi)a ۈ{Eu]uxn$P&v~7R1yN؉V0L:%jLV*2yM/zs {Ц)m@\mEaH٤lhZ?^ZZdVj`dm0HdPo'z0aBSE1r/)[%@eOim3zŒymEJȓڒcHheGkF]a>ЁE%fqL( lk0 ɥ4[gLeڪDYAs7zU*Y6#m_( ÉSn `e+eraS>χCR6^Z!Gm,3_[nr9?a8 FeYzDac{|{ܻUF!BJFZ#jaYv=mshV##0ˋ}ZUnVzDHc_0 *(" #Pk=9ZWa٠,snߤ+ۓE/ Of .0ICf!tQPt\fV#.=.}mX(;1‚>A3cE3~a= 6y*nmTѹ@+[0څqipn.z |21S$!@kj٤A+!tzlZ%c *ȵ9%;:Y,)om $dzJXv5v8ݸdkիf ѣ4NJxyZ%VD:I4Iضb(jfAJMUtѴ:0>6 +@VNČIBE[!u`-#K|JѩX d46SZ<33,`!3?<^0J5RHL>L:djDͦmF<' ]Nv^W*ĭ"ͱ&A`XgCs<!ȆC \;rMkVgf1lE8`FxUf,+N +8!tCXq>Wj0c3 p7A,ۄÒ,R3 e{k& w0C#؎EvTx|:ytfV Uv@#7dt{o^~9KN7R-Zn->ãO>v/^uw:hi dn @eá^2`ivs p`SYf9Pe^ss˚?OO),#짳阤΍Z(eN|0V *e#4{ N9&"OZC!eQ`we?w'Lvhr[hd[@-||AJTs̓e^_7_6$RCۓSP`֭ڛo6Ou: 7o J|aN|"ڒNQ UjC)mYiw G{a߁`3^-XSfقo vir5OSD!A0D֜YV*g8Q!?N_<~;)ߋ*fx 9m!NN/r^)R:Mg PIdҨ2kSӓN43|,X2L @6 W9MM'/_bXj!%A>0W(a:M %K|) ED hUZ"J`߯~-^~OܐKhZ[MeëWݼo}+y{p#+ xj8x,}|娐.(j: 91qVXfA*[Nb!`bہ_ԅ@VӛLCݱP$)I L/(3`GQ6 iǀNC lA)L4eݽ=Ӕ|N.VVA 0d{ ^~׾76v?& |Y`?ѫ/}qsS_J\7<9b|5"20bB{{Ep`ˬD'66@kn}sZq.sSYKJ"9(0ZVvv| lj z)3 t0s;)[&sfc"V3E {W[mlzw*$u _3/h:E47*2mTbJk(go׃Նv\6 i屡Ll}l <ۆrf((v=Y!7#e >`%]Aī5Z/T-Ăh^-I,(=JVpyd! c~/i ~Cë3#)?n&ɟ߼r%//i:E ALGʑ[UM&(; ,aA29so{aOJO| ȶ r=4Eyb s`B;#MBO.,.+Z۽!h5eE{ <ۊ†q͔Αrj @kM:ލ^/ÂIv#[Z?}tר9b//V*ᚂK ~di$v[6mB Aq_4tfM[wS.^Y9wwힻ{|,@h3P'b "> B%mg&JY)]q,v|ؼXE@tkYA:\V{&KnIH,*ϵ2]Hl3c'eBXMt\=w8-0E\yS]R("myX Z|e擡QqXE0 U s(+W‚8V  Yk4 7,̹/MqךMjBk;kABY`9&vLlZӡh2s<56bj+FbU6>9pޫiU\iJ9=Y(kd ĴZ|mke|k ) 0p[>Ĕ#-٤Dce%<fYWa]/CKZʸD!+e]i 6씧P̳WS|cO;fӔ Yc<ϕ@(Q8EsX{ܵ|'NHKwL%sb*Hl?i:N, F`YQ`/dx>>iRH[}_`z[DŽviSh !]eAeyY=<_X L^> OVj饣?N)D 'LA`hY)1xXfDfUwd=| Βd[yn.h\,܅Ƨ>[>콰)HOYea7"K.O)1Fda2BN-/0,X`C\DynA6]_QyϚ o4MIm)#|ɜc>e=*v6Z>aTD&:y. T^$LqLqJg={Z[Q7$B=epjzVs'/]j/=P%l6Akdo.ĜsLhlE m#hDez dp`LTi*Mѳc>,goyWfK0-f |}eWh6,Mvw;ٞwG|2fO\ڵROR9Uhg;WZO2 F#^0pX4ؼזc>bY s^|)gZ3&jH}:FV~que%n8Q/S[JߤmSIy8Zs^jG w2J|$?k"aHq| stiۘx2 yV[851|] wvDL>m4Ŷ xLwiJLnvVWYz, *ʙ[NMώGVJ ADvUv͵`%Q?~\l(avz 0i p K3T=&s;Y=hsA`*m4P9\w^g4+ԩI$,p0kBq8+Oa4!}c>0%^YD::iθ|b\B6P欓Ѡ^P9rDy$<Ȥ׋ᰑO&Jz;2j¸z]FUv$;;޼IW|SفʕEXV3y|ځo_=jt24{D9}Hfe*gZ%tZ-Y__*Iȇح1.t#(=  JЮsG̗f>'앭pHNa+L&T$$iBfXxt`32KBo; Ak*.(EX!}$ bv".V؄ql4j< ) eYet7ݺdgt4UVCH{,-|W54cxL2A\Os̔v2|*M436H7]d>a9فq[A~1t00 0Fc2kRYZL9dҲU0Yy@dg|Oygta#-wN|y4(H'd!yL^F0=%)L9*6O|m3BV*fPd:ʂ/HL8{6k  Dc7$׉~*;8Õ}${=;;zeY/y9:v?L:Ib(mLa}XD` ǝ3j7;]Qx IGIl{VZvGldΡʬAv`[Bf̔ؼ߉W{|`RAP)}soeIx8|j<<܀] |n0Bܖdl6@yZfNEp-SL`P."­n@߉OfL"T]kz䝾|Bcj|=idiiSRo xm2?9EFRB ́//˂t|! [,@{|ql: \Di8&j,/23mcx  RJM&-u̓R3CZZ1կsMG#>N47ߜ\[x8 4vEy OH w;,Yf"Jѭ[Ū;Jsp[hoqu" ӷd,Xr˼ ~f>0X!!HG#hWJߋ @2|q<h8H2, ̇0ea>g5*PfN8 87+6hr{SwFTY?~ai/㘨 n6 -vEçs3"F cA'7ϞVq8!{|Nφq,6W>Ucf"# 7GD3Rv;r./PLimNG!U؁Z ? ,aOWcE{0_!Niud0m|=Yk__`#OQ_—k}>O" |S=[^2YEPRmgB>r*!-C{"^72B;U'$n|7 U20ڢ?=nyy[כOjJZ@1$]Z|N1%94Y&r ~/d>pñt~g8.>T*4m2BOiN,hbcEگu拱9F(Be^ލln_|7t<љ]--$hgRyl" W g~7>j8e"bsx:DA`'LӮsLJ)Ҝ^uW@_l$ єMfӽ=x(@]P`AAISa:Q`@d=xe+q2%yl%0Mda`|6Nw/BJ3\I j1+e:RYU2g1 aNO2t`:6ֹm3~[09v@JڦR&R8y0,&&džE]3DHIh;g:ooӿyS5?(M2We3*0S8 5%ew|p>೶tAte]:M l*f^XfMHi6?*Mbzdl@92~3-DhRj9B9.@-'ƾ ƒt0`뱙$݇^<"JW?,IQqIG"#i*7%{ʽ0d{믛=$Se h *ˌUʬm=L[{1'Xp%j4bzM67~M~߬ L*4nQxgΎQMl?Ch{Ahf#g.t:e!`KwغzU߀~*|̗y,o s$Gj OloW+dc^by5zׯ,D v<7_!>81@܋@T裄*ЌwJ,"$aWze_7 y_(JkɄt<6[e<@\1FjE6GX0&6mYD`:24E$7naW?)+<2ȵ??T/hh{QEei**`%ޮa>2z_*7_|+µ-RZ`p''*\8w=@+ K-znLC?Zk7WE83G]KI^RC٤eĵ2]:܃t=*qo.|io9lY@SK+-PAB>*Pմ|9[fx̑+W8}&hd.f50rWMktaTig~\|kb׶/_;Pvuӕ^k׸5 rt?94n_z@|F$@iYw+!9;(E}euC0[\[`lwl3S"FkZs|s/32*lm1||s3<{fzYA.wIQma8C|H  a#F|pb)QGH>8v`ā8J9$ȑr(cvؾﮮ͇؋.@zjsw`k6lG*=ٖI>pNdKmURH)nlo`'-,A4-_òbws3y5>p_Gέ_[i\҂"WaڶxoA'Msv}I*JqLZe\UdGb蚆EJH[aS~ F2jd\qb|pxk;fWgB2iZ9T6s۴d\.Zl9xj*IOBD(yN0l'yO^}mX/麮AVCӒ'#RL7U'QUw|8I ٤zukLi*pncҒ_)6)|HwD#BnFV:W^귾ŋy-ws 7CzTL!<Mr$߸A}]l"d{𔦱>̬ v<믣F\ETU0D=71i4(Jgшo7c$Odb~0Xؠv4%rx!`@gs7M5Z)"-8LFh31,8 N P;Rrw00Kc84u} d{ĺ3LeI"-TɢS'H˜k+Wx_:.cF  D!"vS7nIiϵϛPN&/c4 3gx)>MY o꫌;&&`NF膁]̴ƽZ"4Ğ2vJ-/! !|3T/}{ڵlu d i SI3$\qM vwa#Ƽh⑆M)1 r9 EDԩ2h.˗ۨ8fvIjDf;<Ş-*؆!Y uL&{4e NGnJEN;Xgv {p+~_x܄"|~>SӅl䗖.JU\@4ޮfz]8>ҷ7dΣz &[*Q穌dP=i c{\~u&A]nOVoL&+6ok5\"- XĴmjRFڵ>Db_{B" LǸ!zF#@o?bѽn~Gt .dRMm֬bQ똹fQksNɼbB.8djpXia*@ɶ "5XQR>m4z G_!]"njzT^A)߻>nv?i,gEFI_(fd+2ɽTJ )Ʉ`|ÃۿnXzFUCűV=hdsÑ(Mi6nmqrb؟4j*5]iδ٤l*w4mD?+:Q:A3`!*Muz~rs6ϿNAtʔOgOU-/fY80v7}%rgm2y(ɨ'K!XS \S?/!LYKKKKX2f"cOLzÐS,BDRuI؝2"3'HMkf4ޅ _lXlc.F+Wr* \H{4D8!IH ÑvPGQl aH^7Ae&&N{ѼuMy4/@px)r\FE)&Hsu_@V#"ڎ-'!^#p]n1Wr^j,iɅN^XVݫ 4=t*qE uq<;_w#q;|(P?Gp=J:jL>0 `Z ޔ|CApH;qXjqLѠ2:s3d>)Ro p OdeQtx~`J a'NpYx 4|ǡ}J0B3f+!xLc{4벥7=ё 2i㏳vX׫'7%_ggGmU{/|hg >=-fngGu] ]wzjUl?]TI.%v!tʨݦň:K7 qL#K{KK"B4k5NSGau`6&t*)ڝ,8*q1vhKQnpnW݌OZ8 ( ɖdmR”zx3hsmz~K/g/ / !BAZN#k5OJ tӔmS4JrϷ t|s(;If SdRd!6#1N惖g!׽Ϛ&gVVx dUT,bߗ&a@B:]qGgkKm\L|Bt2J@fϾFPJQDűdVR2v-kv8пrVKKTIt[@AY]j'8vV>ORA7 bU6vwY}v8l?]nc3//RyITuL 8zbJM?t^2y>ɕ~3,=Kq 6vI(4Mc.&af$: ЀINCN@]xۄnDF5Kfig2Ih:,ɔJ3_ҧH:{YQsΙ%9㏳xJC@cX|g6mL=K/Q>u T fH#dN;H䃘 ]K1Y,OSOӧeiB,4]岜O(wSaȴף_^uw ×#4>4<Lw}nS`uH evFh6ujgPX[#aId`;r?|{iI^D*FXq(\fS]ywÐk0w&G F*<OaXӡja>k=e8r eusك8Y`ՓFg[|b>ORXQVgJ5䅘0E-)2%V}),~Ӭ?O?vL+=gvwY;ѥ:ۦT*QZ\dIʏ=FqcR!";j&BӥD#sʕ3> Cr{y,]@Xdyk @*ދ8iˑfXlBnii/N#q(Sdr9KK 8#D|q{% X岜g$4S:j5V~g53!tt]_&yl+ǮV+ VVU|+Va8a2dd¤ݦv~x =xe}2w% @UMxXnc[م e[]t}܃AJ[tMOhgl|N 3]&rJƱ-| q^\[ą ,?fg/aYϓ_^FuN34meIyX7YNJyBű\T c$Hhݺn6]NA0?`{ ?ߎ%60 =}<{0 <vFa}]rdžJuzA<)y,0? e7 8鎐MqUε۸gl'Oħ>S9wu=o 4,ȔJ76XI@%_E|{Wڇ3vC~q5u uKHmO񛀊 V0dH}Q[[|i*iKi*Y*#ו}s#{Ssg'Έ 4p2̩S?OPX_'S*J}JHq%^8vPܿp<]n0`0١C5uV _ h pЦ~(Q+p,XOZOLǤXAR)fvۼʉD<<D#eOXpkyCE?_\$[.dZȪ2u& AEʽH>Ij*V<{1$v ܙ{9tzq1h0liMQWN}䃇KF PAF#-L4Jϗ8Q'C4^jl3ҤK%[B{q$REbV*䖗g]8u;vq;$UAF΍\ʍ[=/ -xwЅ/y0 N`q9龯өffƁ,q4b2lHvӲL.GR!&UʆMCyX( p{=i;-;nW!hu~·y(w7a%=AErݏK%f3Bum.u~H_u奜ʴ锲@&v:>VK Cya҇})Jyu'paUG)ÙN q4|Ck: QbP-*! Suҿ"fOd\aY).,‡u'p,iL⹽N-&] \ Cu:ïнA!l dFpE0byx& (%v`JydIU>%I08ImˤcџL⛞5tuK!0WM~ aSP?ká1P]^8-IV͐y4=T=!ϑ.|gDL |a]Tpt*v:>nw ;Z>Bt !L<>?h$`̰K:|s Ї"ȍ8 XE ժf6V#4IDAT>/9lv/kH7yB</%߼PhX#+ZfO0sdpq,l9$% G8`?Yшqpc|anhv(Ql+U$iLTOw᧻l#keɯ:NiZͶb.GZ%[,b'#[g^5$!HTHQHJ$ZJA3 bH%)F<&LD8pH4b48nC \tx+yK ?2u26SV] ߧ<8L~QH8ҥ*=y%8J0ʗRMR$$VpȤgҙN6cDѣF9*d_SeXZ2d\deEֲLJK4*ʄVD\N S}/JDGl<ϛtAkSQtu(D]" \<5s0[Xu^0Z|`\b,&lB$Ūe:탒 )P&*N30Gaf[Į 6%^?x(脡+E1C^ %WC}L$A| "  )>m(VKe m[s9lV3Y2aJ(0f_*!ӉMo Ĝ'RO2٠RNu "|q]&FAJ6#Ibjpp'?CƀY?́UlXy0`tu-Z0d2BDC&_N3iI?9BT%*7JaHAJ1"ƱȴPGTw4:<*cG(ÀM3:C\j@ TW Ap&n.{AӑUYmE!j4 j@1a@kt)xL6 }=eׯ~_ ;;hR-^!5>[~w|,~4'±cB\]αrk.ܤsuf^GGJS-ׯ3vݗ^bws뭷x5}e6tᖆfk߁P6W3XքXV^vZ-NI)Ϟ%]Z p}"@V*++hOV>r ȭ[a8+nO3GoK?ÀMcb 8KRX]O>p{`G榨 QIPZEF2 A"$hPIB>Ҕt8$L0qC\уwQ׿lw/_e0=~KYGB.l<ݍ8n;q"8~YGon6JZ?,"FҔdgGn{o)f3lU$C:.i ~؞?'\& <{zgkcnsS֩SϝN vp(Z)tj ]FoUv^{o+7n N{oj} \?Io|H&t??Z>dt\<񄨮!+fs5s2(ޙ޺lkOԻ?{Ovvf/B YJ..8T[d~Of=8>G>BGi]@P0AςHrՉV3GJu}ʊ(6[drj7~]{~[%(_v*Tl~\Onnv~Cd=SO:wɓmuBtC#B{aY TUu8J/d{:4pqkޛ~HW(gZ~z=pLx_l~l؏!+3 ,[/rg3wG"qhߍxB˟G#&׮1u7~7x_zd2x[-o}t' cOzG}T~䓢sSB/F,}=c%;!(TqhA)dSJF3RpvbF92x-rp R)lVygkǟx"\{1{Qڰ(D0ľaKߋ,4u(EC3|+/<0فJ܂o ƀgaY8HC?+OE?vt=lj瞣}qg5*溞. /a*^>\u<@x?jBx2 Ժ]ь"qJql82Lvxc7` wOӏ?@'??ʍgT c ` ۅӇq$*lYYqOªaNmc&^ON[t{^i36}>rMx7O4k?`sE='}QM0]Ae sA\펻J;@B/O`u!BJ㨏cJ v0Z~?lye|}wie]>0{{Ǟz'?|9}acFXU}]2β#Q@Xmh \0$l@ѠTd<]"mņwRT*DN }7LB |7 ExR޻pR?.Oȏօ 䓉9Slf*TZs)#eyNdeD`sgy:4lI겇p" $V ˗#+I c%u_dI޻icHwwINwLrj֞UY99]~)lÙG}Ž?//0!%AJ!ySqPڒR1\ݽ>OCp7ԧS ]mҽ=pۍrh 89б1Tf3wcޝ=g鵧>zGٯ;>{Fl84lmŢ°lV8ż5fa8+``^?\~<p>Ou(nFtߙwqfcN Lpm6Mkk[-9}7WGXl{t&l~~,G͏ޣ"XVFd|_%BXF Rt@&} aye岯!,m]^}4!i-x=,B'/m\ߡxz?OFOgG?=g>#W/]͘mm1u|cd*XyyA`+@X/Z7R K.{~Lyםz!Ð"l4YF4G#qk8\ \ߡlN_:+Qo=-Tz=d >I?%a $W,+,a\B,ąbO>`qWy*o\ ׅ+?C}w L(BfHQ_\Wꔆww7؃_9=dqG(ޠy tlgXvu{C(k!pE㕤\Q?,K\ȯ/~>\$O;\;̅0_Ol=8PHI\#w LuwI~yq dJzANdw*7 Li+G92 1b;EdR, UD!.aǻe!~WqFR9}`ĝy_xF;;Wfg%hrĥgK{䘮H)߾t,q8c;!2a)ep,Ukɾ4Ā8Yxe^Γ#f|>29]C[^+ *-O0l׆wh5N^lm\Z25/OFieJR;?**X`BQ UٲwJ~ۼs[*L>lZw<:sD+2عzr׺)="𙵵O>_BsSAqd77a|}{{d1gڗ#&*ֆy-|7l.Zi4Ny86Dz?g}`?{^)挿< /o|}4?>y]z+\R}o6[ .r<ΞW7Uݞ+MtحƜ[4e T^86g32IO>[ c~ 0Y_l=Wҗ[.;J^0lDϴsʸ^+q=*MQIZTĽӧrJ-,Msz ulFK:}G/VWV~iucvi4 کU:^I6Beq63iVz; 嶢M#Z;΋[hXgeaHm}byZmua\3^"@9w?x=} qNTAVG  mY7E1aR*_ytZ'#V1*~Q -0P ng0~^s!8pqh^!Ҩ?A@ף{x,}r7'7o8Z#=;&7'mkc ieJ)Zօ a >u[9RJTO&aNeQ[n&2;lL|pELݸZ)ֈ<'th1Zk{o7~n|#wӧӧʼn'VgԴR(w[ 1_^zNS6KSeYl4*U2kBJrnrݧʼ* *׹z2;/Q у̘`!+ o+GT~V_kkkq֦[ESR E,]W,LPq|e%}gWV\mf殃ROÁxFٳ|I4V_|YE%r(>ͳgcQo4Y*SPowD MDya45݄`K\&N6 /_y}_Jq]?Vso0[\z{yeZOs<Ir(n>kO'Y[[nSTP*%2hLwEӀ= Xld 2,#u̧>T~O= /ϭ88-{E E^P.Kuh v=`+)3(B~_wevvkJ+r,ȖIr`2_ [;Eh݊%p"!e|q!ߖk X r*w\yt* ν:3Ɲ#eFc̺ނj:E A܆O>maTFtqZB4%2Ҕ""rBZf>4̷z pq.FLmmV+WWWi6!݊ڀWev瞣*7lRf9gKqNtÆĢȀ@vOl{e%jzRTȲ yU`74,8hXZ:ŽSI Cr կ[yg +&L?7;0諷mKk] }eXZ~<C$!HSd`NTHnv\`+O[-Qo6ioyn@k~Y;&7Us(~=gWn}EaԊ$1KHðo2S *t=X,hsw߱K }@#"ycSA@meSt^{-%ɹpZ@hM+_;XovE:fJhPeYFh%̃VzqLRtaR3S2NR1Lm Zej63s3\R3&NɬCfuk2u" hyІкYG4j>_io{g89YFED5Q#>Qt:j53HӔ4MQj C0^>""N ޥRSJV ``_6f3~4"N㥶 k`鿏"jV#NZ{A+NHOg"Kv\X[غ+h]L AJv^Ʊd3xqh5{vzNE&SJQ ڶ|XU̗i!E$1,y``f1x<`-i|"Tf,kmA@v-ZPaXi *u,)7[1]Y[`|lCϦ]yn/͆A6T;э"х!4z\Yil6 ,Ȳ<7oz)݅8q } IDAT)Dkm1\YF6eq8pW/\kѠBDf%* xq|:PVsyqQʼ/R vv͉~?zϸc dd)kjlw:^C)䞥]zucX(>(q45Ҕl4b3nms׎+BPyn@$! *j6+ E;vl\TW3@au 5\} xJq殗(uR78^e1Ia1tg+HHY kn̳qlXkVb6#dw0rv۸/\o`1_jc@_UpqUf]3,@2[yt 0>g! 7K7]č^z]aub^t [Y<W*V١#v{@/JR*l"<7,' x|vZ 0֬J"0 3*R1e랟{g+6^0"};<`99v{@F C&fS4&8nvJ&jc oet]s-9w4*J靗lW*IH}gtJnagSFW*,V̍FNŢ+ss@ f8ˆ  c)zt,*1CHP@e8e\{!?>]{hM.Y:;_djv%ʲz^kQBH)~ۉsn `YtbTj֎9qq$%" MN1[ZC0\guAF`.?.nXTvb‚>A3bE aXςͿ;]S0.sML~: ElFQ#M&КZ%n6Aj=`^?WVp( lshp JV/ea"&sם@4??MH>w~kSIhDϿKb 0*afףJlXq>3~6+Wg)ch9C#j AJP2"t`6qRIbTܸd1.@Q*UrmE]mp0BqʌrnqDiV@z]Da(#؈az @Xi4:ˀAF?|7 ` f mu;w>/\/XQ̚ZKdBb]00aHX5Fk  dl4br˗} ׯ^Ztx^7V4aE{~6|xB$AZ\;r]Vft;_;lE<`F{ϥ¹tUf,3onfHk # az!r_`… Z-zh [ӎ*V$)>@]7Y\Fw,Pytff Uva~Y護\oW^nrڿv-MF\ T+3gfx'ޣ榈;Br̍BlTnTݺeMP/猧՜UY's:G{XűB) ճ]bڴP!DL'xoRʌ(Aם8+3ّEFmfq8GͧcZ% 92oK/q_W_I@TT!Xy[ӝNdq$4|1Hd[4BW*5!zpg pp 6SKE܂5-H`7#,f/y" XQ$*D-R9DZ)nU~0gp`c: \7dWx+_~֭ ^?ys P@"?K[[2?ZcqKum蝱h?˕~= VV,qlcC @L H" Mocn\( 䃠t͠]c?Ak5ZZUѽZGHJD+eXR IfJT1Ħ5pw|3+4 -ᵅ)ҭ$[/=ʱĝNQ!Ӹʲ#P ,aA2kxx\8\\zOF'>:-s"*MQ^KKl1B]_`-0*[JPA`;wXڮ D9+{ fW^n'^%:|vsLZkH_Wo0o|NЏ7oj쭝cN}mL[_Y1a=a#$vFv 4rO/~]ܳjR"?`Dn" 呐 `e(D @PX :-Ccp8YR__%04l;p ,hu_e$i w@Rx#/%iz~2doOI"2*@Xc*ȇJ+G;kg8]QF錍JSҐA`δ۱ړ&]pu޳A6Wٶ`ga)el!J~}s,P;|>Vy]Wuݳ.M {W*/yb8W:Q<EWsPL Lp*9+daAT5J[Y&8kͦj5uZiPXMCk:]f1FG,Pͭb*Qi1罊f[eʕJ3߼|Vs,j=s@%@t`EZf>gifϲ[>Jy;L IV E[!aIۥcYSm9p^꽞N`P╰S1]qmzUfuDߥUܷ@oӎ4eP|p̀a8:8+U^`@ q˙׊?iAS`eZ 9Q-ZǏAopf[o;&v/>c]o1c7g6|6!2NBmi:M3[RJ NA)OJ>iD_Hij鱟͗cƲZ_`YZDŽvjSY "6zJ'67/O#]> OVt̙u4" Io&N3Zkp^)Te1`F0o|K~ω̬h(1nAy?B( o~{ou| 0zT`Ri5VMtEÒA23?528AXя֞Ϩ_+J%SkVWڏt}Jlw<&c̎ >ܻ;80cB .-cR+pud;LȳLO npLi4M[_ s-tםx ]4so 9ql&\Y㞣234ͺYzkO<gi3w]{{u~矚Xn>;Yp:s&ah*a2)E[}2q\,+||R.0y,\e\ t" @k>] % !ݞVUV*E L ͧS;;DpH`gj7O_{{oJKmwRIy?x,?|pڱc̪0_O2Fs2_62 b2αQo|D`63MPA ӕY,#^+tOǥ#,0VR-a>'=?6{nF+ q67,So'@FVaX˨ajخ'e T,jZ]}ieV|D@Q5Nu*AW]}2L$8>(}F,YNѝ3 =*m-VPFFGT6j!jd}sS$!c7L\׍4{cVsK;(Ly(2@0w|UnW6t<&UJY&lv:IfY@nJ͊9dltZ8gvwc:%K>ugE*~Tt ¸Nшd0 "*B]˺Z|b&f,lHmWy$4n6H};v1BB)o4b40VJ~_͎÷$ys:?9Lc@gt!0Vp)|>ṡe>EF>e|],Dͦ-iEG6FŎZ sHcF$ð`^75v:E>E$f}ω`>!QEfﳕ$z &rF2 x<6߆sN< >e>aYUmc?n;=7bjuJ|LfktoKa>alj5hOW?\dk(Z601P[,y0n1+3+/8Zh4104E) 7'z?OFGfw Y ass_BL.@6.P imvG!Y؁Z΁m%"3A"@؝5vlw |+yhzd4" zG|_J:s)olF1~ #2.e> XX|*|+;K[& uCl8@L}N%eh0$ՉN[E9*oo3LdS7pNyF_'!5a8߼H[?fd g1l2y^ ݞ#@P6 ˰>=9)~fcEگu>~mQ215 X\_|qo'HC!la 8./Gf> e2s@9p-c>|J ^X NrT67ٙ5&R[!XҐfcC-n)&f#n}wwWH)i6hvE](2 IDAT ss'#Y.38@Q,$Łu-P}K<0ݸȍ+|Ƕa"U27`OQV~tx7߼vܹ/~JR̐A€ "Xh| ೬ CDl6/[>ܒ!ж`Dk׹CW0>h@W.K`h/Ɍ1ۣj2 Tr ru*F }53f9H(Ig{cׯ_oV*שڵH!:f {.FVxt 35dhb자etlsn`ps쀔fM (Z)2L,qT$`UTn: g- BJBk3_> OAWav"Pm|*5nBAHc4E ;uXF_f8jU1`f8ӼuM'ƾ lDh&$!r_#$ г_f^zN͗X,{0| -~^ uO뢒TC-L[} 1͓'^H5fl1ǥ`&62AHC3705ӜI]&:: ЌFɏ]q(Bgp*W0\-Kd2z/p8ISr垙ZZ)fn.ڵK[Z` a4w]ٰj56~ZTLZ,a !%.+0ukDݗҚl6#NR,#2WDqLѠjQk$ ʀ}CPaH2ѿ~~_@_?-+~d,w?hnoz,2 }`%9kׁ0]µ/~/W_mR (!IWׁ{h!T{v>|Tں~\}.C0^&~S0cᐺtu>NZI=ˈk5c2];܃}fL}n][iއ/Lqr$DBo㽽ZLɕ=?!eu(ZZ>Kod;=SPNE^ ޹hetEPZi v61|͛_2߼f1tQn$H)Z!՛7Y CNjtm:ǎZ_'pl|?Ok xo42c;իW?+HF2Nk|!xm+E)5,c套BdMO D l2_Ĝ"|.'ZKSN)NU| / 1 VM޺+Z.96rd71GV竍#bП)gɕN%Y5*\e[QM]̙7'%u9le}\W.sq@*/S{;Лͨzz‚Օ{qs4oB6_Vxzҗ8aFkWL՘4ˬ cƫmuB9|Nr 9JQ_]z.fiݨjی1Ɣ  ;I껧瞝YA.$IQ$rvAJ/9 Ñ X #$Hlْ(x.ɽf}9].mBtU~Wsm#4$Tx&7W{?ts&vIe&2gMl BJi;"U۵M8zDPsiTZCk׮ c}wD@NN)<H KI0Ҧ);$_BL'yXW,U*<:BXa1l"BT@ X"+I/nl| _4L@ȷLVA=M6#!ױj&ۧE!W8RvA')wTfb%)t]&ނЅ4o wL@eFldL?< @!K b-:0 Cbh:W^/V'@7QkM٤>s!tG 3"jH`j 76peBuyy.?I5xQ1bwiJۑϰӡ=90:r>{cXveT_!aX4Նۍ wL^{M?{rM@aXERi$;o) ŒpN~M^"!d}.p0Xz!{lRumd1.#*HJ j`+⫯ARAH2F{Z1?dY̭p$yss>~G5_yW]kcc72bY#&rT$Czav+1w٥:ʌThn  2s:4n*,1p o\F9n"-tXbix,'~͡s/~k_cAFCQH:4w\y5\BoExyX!` dX8u>q*'OR9}Z8aHy,V  0-D; h$BL}vQVj5D{+#DAS?j_e*1BRj|V"%'32١M/81 4&%hZ|b&C󰑇%uL/GE&Z)6)9vmdv#Yvmɘ- gY-!Ph{l\Bqfr%eboJ;EN[EEEsgatF~Gx|ۿ^[|U>󜲂-EIؚ p5,G@aMVԡ 䁼#m Ӝt55ordeʅ3!CTO}:$C$Ȑsl*ŕW]( }5} iC*0t]lv>Z]*arU T\C)-$dJwvxm0t Cnu7E_u# ?,ej4fTb&v>]ƔS2- 8&6}z~Bˑ)Ej(%(C)sj;KկTck=MH5m7U3 YS/Y33d{RDpz{"0)EӜD3Imx,j53ku~ηwE@_{\eObj/kV[dx U4rq8`: >mB cBJqe‚T{:_ /6R"/GdJc#*yQ:=? 9#'s9ziFF1ɮΒ_\$0q΢шqM7Xy5.px;o X,(a',$K 5*O C: nܸ/*mecڝ΍}}ۡQg*֚VFә)aI LB m1Ik-q(:6iFx$ 8;FH0-%$w6s8?ƒ1(>+@i~ʉd`= ~^ޔ|-5CpGxɕNu>-4M#uULS :Si&j#c&0|۸B&0<:J\WZ|v,%|OO-,pg8AD\pH4!x>3?̟9331 BTa^p_y7h1;5ב:/+9#'Npӟ 0yXcNarInjm\86b>ӟ=# ~ߌ`z.(("[HX&I SM`H k6qwvtTGH7-%y>BAZ݇UN"GX=v ').0m[w AIK]69? |P`G(9Kz Sd.Rd[!2 1L惑 =O6X{1dUAX*aH*aΔ"niml荝A|F|.E=% @ ^EZZSZX dR2v7gr ^DݦKTzJtZ@Aރijc8rN@vfӲЈTVYf%95N= <fT'faף-=7uz-HL8я24G)ر/ݪPaOC.>J2wvx9Enr sl6>kv._fG&CcRL 'O %% ӔO$wSEQĸӡ;W ڂ _ ig+ÿ3|)|ʑf`G# d--MeaeTG.&HQ7M>t(<,UJE3vo- ,?(O:$a LN@Z%73CqyN](`rdɌ cG#F&M6u}%+0#w*v[^;ا$,Ex,L%~ujf2@;#d&soH:%540V*,,pdc xgVV8vgY ɋb9 1L"nr9HyT3YNJiB+%;9P2 9azG!}/.TTƞ'$SS!S''Έ0<q<ԉ9CQ\]%S.J}NHq%^i&9|;X_4 [1nomb}0_i{7ߦ(U\W<8bmjU2 Y2KTrJ#Lu'/*& SS | K9ia)eLZ]Az7!h¨ Rd}Ώ֖;[7u6ԑ[tB& Suӿo!&Oe\8)N{u'h(iDynM :;\E*x;pcFcp- 3]q 1VZ]p*Ģ؁)I%U{ȗl#ch&t3nCk9k](u.mƭnΨ^m45uF뾯.B| Mn~>{; ;6|6ugᴫTl:c2K33FivBJRNjEtX1ƚ DfD%zZ3/"N屨ȕ9nuqSf0tF5m<~gt{}x΃o\|ǻ]c7z=c2*Ov Li GHz"L0u~ZK.u*xBh~ o/ /3l ύ_t R߷fTXv.S(H4ZҍaPOyK7-8Њ LC$RbϦX>qpe0P ]o8$p]ͦ yz;w 5KI}#) v~l? ?݆'jJ-T\캙0r9SVɖJL.'qqb CHltzGM)Հ𫃃{JYxÅOesZ[k1˞ZPL$Sbg{wZ)!]Ix;⁣h@E8PEg0! Z%p]>nAMk((AقZY"dgd㘥\rءzIV_6LiCaS8%p)V*zTm=ċ/_p3v%`yXiOZ\س`XsM!X.Kj.e:탒,▤)P&*N30ab[Į 6%^\ p iEjM >cj/G+\|@$~| " g,I>GsP,5B,ڶQB.gylְY2-]L˚~L'g-SJV2٠֒N"& h>l§<8E.Sv4eY4 id,L&#Dd1,BJ Ri8]GQ!Ai8ɴXB(+*_V.߃ p?ʰ`m+&X}≰%++LlxVQ CD gF% Z)TF4% c{{ouԭ~7k&gY& p~%_}@VG#l<KqܼxTy"[ˢFABXRviV ,$NҴÕ>Jh^I2y6{|ֺK/OC?ԁ?([;k%/ߺ5:Sv;t> ,Ϟ?u=Ǜ^T}G48KbE*++)t|c-=h}Hs X.vUΫws?"‚_DQmSa(Q~v-M |` ?q6AlU+~16?l^K/Ѿx5e3]ρ`AUֆC/.OrKv |ye!sTmjKKEb}02VBxg'7` O🝂?t>u|ʗ_Ƌ/y1kk|`1V0tsyrn,8hc`aՉ^AckZ+gΈ|{;? .6aRO[- ؂gῺ /|\}G^z)z%?n! T0ui_4= #D V{b(48&TL$R62|ie\>1u_gW>l/}):KbnjE`u*Ww;uw!˔:N>''a!=4zr!ÐBFFP=8Ѩ>)m!A}֏vNgիD /P;}ǐɛ,**\+e `grGɽϥν$;$Z Czۥt۫L?dY{ W&PF#~\<L&\> m_.|Ԛ@E1"s<' Hi늏Px?wM7p-'wMu2;R.K_ nYW*3@IoVѨڇd޸ 7z9K _KOZ;BC4THTȣ+<$'cx81^/֞=I9]~)\)"y1aǟ˗8]*NFAugGFJGpN+CEOYsq駞ϭ+W0RU&Y# ?ydw,v2:ϑQTTƓPJVI+̓W2t/ұHW w$Bc$FRRNE'?ȲЇߘyr#OvϝzoSOHٽD.OBƉB}Y`P,. fZZ#`áfl wK*nFЙwq|蚐fcN Lpm6Mꫫ[-9;wVp 6g OkW^<E+$Xc Ɖ|借\zl4M]+ÝAQN*JhQa]hm 3wcBXwQjD[Ce{-MAt2ކ>"N tRxݳ=;kkWO<? "XzEo7R`}o5|X.Y v^^NJh}"|y f"lccBөAu^0$j D)Pl+઀kXQ677^xO;::i`$b_T9ZY~BByNqLE 3Rr3`a+w_X*(9\'mFHG)+g;?zG.n˜#Nw?߀w>9?t+<+W/^d9v&@7q*8ͷ 9&ٹ- ](k!pEaSgC/Jg]V=˯/~>\%O;Xϓa80Y9ZC:H?@~?ȴ^øf>E<7.ngVxE677i!Zg(h@0aN9VLEx\, UD18/&<sB80|N76qCe7!ޥsUiA<<+W=ƥ˗ţWt X2$=~ieBsS+!cKT%d=Ͽ{Q8OrQb>Dw]5-ڂZaHPwwEۺ$0h÷7>gVϟ)67YYY!INh룵ݩ;!wR&T0DŽZ)!8&9B>6;he"1g+y)f̷P|ٮysu !Z-?9dwF[o-Z."@1m^ox1:wSX^^f:73M C>\ǂ0ːй1`wEDJW":RJX'>A}5.| !fahs/4?&Y~Z<oT/ܼY]0?YBql ٳsΉU*Y)IZ3qb^x1e^KxtJf7GbK3?"qȁŀY$s빝 gJz&E{{,=dQb3mܵ2ʸ^+q=*MQIZT.g:u!؀;^7ϟS~vllnRɲtJ2g!J֖0^` cB˓Ĵ螣vp8]Z Z{yN!t|ZnXZBs ,XЫ@HIغuBn8}MЂEw{(x_\ب.J@JI$iJe2\CEL`BOpZ]l8s8)[w'JsWV:IX82>E;Py^2 -{ﯲω5=vd_mݧᰘYWl!%Hi[Fu*֫28|ڪ4v|^KG)tF3cfcťq!\2tRťƆX]]R9Yc?Ü 8BY|,:7Y6S30M.?F*!]c6ೀ+3!і<b>{>ԬBtuWYZWYh<}gpVb \$'ꂟ[[:kkbcs50$MSia|H)Zx%bu* _ZBvYԔe9mQd0/9 ҿ'y2&{hXIywϊPŒa}]ÎJ1pE4XZ5aAN? YF+zm2"9_օ |m}]t] 7ϭ‘q̷HtֱJSM]Fq-B.FbkFTH < j-\ƱV31K|/OV3tNAP=m>ReW^={G7OfuuvMRa82Nd~wO` H+d 0/~ceXFfZO|gz@][qp @~2\:.]֏ ! @DR_?wy9⥥߿|fuuu!zː'09/(D{t96Wff/!e)  L_S{u: Sټ_o.;w)3,Vf3\ _z:/02`¨VŕLj! M(~kvBJ{h2D϶PMAb@ XVh9}!E~@qaoֆw*VMt>x&/ehP__g)ܹx:}n58@yhkiIl6 sG 5 '$*_LcgV?rU|+_ȌǤ1yr٭ xUfx9JrÖK(es.-k!^b^d Nr{y9jwbiiJRtR uGES!z7ݕ, Ν-p`m"ˇ|w]!y)2hnlv*$Ϸ<Ľ#yjymz%& 2s{Poyh]scJyeqgSʭϱ!Z$f iiej~*"p>0WeATz``A㝻\ezasdj,9C筷Z\ q[wO'.NFt:53^o[%)h{rGC7F.N!FY(̄Ref* EZ"gFvF"mAfCk5v}ƛ㞓efxsF]оQ#˞ˍOp#ب~emMv:je-2 #jf nR>tRBj 5 Lf㥶 k`鿏RҰZ%'VEh>p 088!S8p`񙪈p]8֖ڂ\x{u11)mzZDzeMNvtm:QL)RjXpw+3עU+NG#h6ZҎ\EX֮X  Xb0 S tWѮu9n.te]o!ae]jP[Z#բnbC5vV h!̼2aH,?~kJɬgz BZg;/usUf:$!L CwFKQ v<ۦ}smJLdBFNn+O ? V:@2뚱` 2ͣkX=-oFY'n4w=][ou j/ ŸRj5{8h 0*wl"<7,'@k/\7Q. X*MsNtJt,TJ{~1e?lfpzЦ+u@\<ۥBF C&fS48qVg*냰2>Lː-`cBSE1*[% IGjwim7,bʼԈ"uJe꒹qȉXteyH g0aa,e~Z1vЁE%fr\( lk1Kwɥ4Kg'LeݭDYy\zVkQBH)~qhw@,0a¿q'(AU8Z[6NJ$T j4s(4gllW3r`Lшƍ@b!!+[.1 9`T@6A_/{2|4BHIhPtD- 0.r`t;H?Pk4D\QTd-4]>)f/if9Z_:&|qpB.4K7IRIzՅlAPY^6>VˀC+e`WyNOzf%Tk$1ַsfXKfё`([q(TfK*wLzf!ʰ!@{ZCz s3MSd/t6E# C X~0R!"Bty^,:s[a.z;v]b>a]A.1 >_,"f Of;GR"$t;U5 ed>-»;/ N[XЧaFLh.,XOһ;]S0.3֖-t @za<5FZFǠ5aJlR z~Zq~gdeݟB39`~"&4N edQCJʆC^o][LV k5|.f:ш[Lww^t<+L8wJKn#+ejZeE<'%'QirQtwpE =^+syb|yDiV@z]Da(#؈az /@Xi4:ˀAF?|7 0wϯ#B9x`|u̚ZKxLb]00aHX5Fk  dl8d|&kn^ZtΟ' UfV0h33dIօ#u\չف43ݤfφ+sip.]*LZC0aB"n+tJCNsG g:׈tXCEC3Kә+v$VmMgc|￯wx#il?=s)RRTDۍϝ[[O'-w:vhi dn @e{5eb̄=vsʼ]-k:zt>cI=9Z(eθ`T^u?3kw>;{.!)@s8+3ىEFmfq8G-||AJTs̓ey^׿o|{}4$R#kɩBvN}g;۷Fx%Ih>Qc>judhUj&C)7hWh;0lk*-[:sʬ5ܳiC0$cF@ 7Jb""_ݡHMTwb7r6b /rV_)3S:׍hj$a:+ _m$ׂrZBXNg<^27/ReٳB!*˘qF:O%)\i:3|5\L :gkE4"?\45F _v_b$*BJ8&CQ)|aQ$0, 9Ftbݼ߇a]-֞Z'6VWSYuƷosL+}9[)\S{Pf Wp,wu!e]FQ8{6rf1qV1XfAk4xL:[s,fEmu=9 i{*Mg]ʱ\(HMSH;"+(3`GQ( aE@4hfqӁ^w^ JGLV/"~bu4Ǥwe7xߘv^ f  Q]"iafX)ȧS_w|S=y_|WT;s(I;P/|A{FY⥥0}^ʴRYo+>0˕~= VV,qlcC @L HMaa\9(eP B 0yk[z&uݫeҲaRaWJ5$)Q֤{oҴ߇5 o%~Ko$\~g;BqeGnuW5HY6‚@e9wnùBҹO| ud[DT<"b > }09u|Ayb mlv\7hpMJ*tM٢q)gz֤áߺa4_9) /ߦj//w찞0tfOm;#\k]X.N5)Ry0vOm7- " s$c(=ˉrW,J03BVnͿW aXx/eXF繙/Lḡ4!*H&|?1?+Iq'p@ ֱˀvlUe3ߟPq%9hBw6< +*(1޻_)b C2#әx7V)*0VHΝ}0Ca6a*VxYfhZ)'I>Q*#m{|O+5TI"-; tlօ@v-s12Mt恞3w ~E+]"9@hs~eb>[ $!2^SPJK a/o1þp;'@k!tL{.ܑYUkeBwzr@b_;) :MjEn},KAĕ70k! (w ,>p‚τ0h2 .J _\>[ߍȼB€8V  Yk4 w,̹/MqךMjBkJ, a Fu(c@{/OX0Y(UL*Xc>!823+Mɕ"gy<̳:`*XƓ9r6٥W\+RގxҸBaHlRYZczYUm9p^ݮN`P╰S1]qmzUfuDߥUܷ@oӎ4e P|p:tf$cv8r|Ba s(|ohWˣtO+unEDhmnSkk 8]ޫDqlsi\_q-vdfjTM;@լ89u=uds|}LD1K5$_WB,=V%.,,@QUg" Qkֿ1T+tC,HWYBPY^>+/}[[WւfN.?ϮWxܹWi=bqɱnji2L%Zsa ft .Y=?l9_v.8Kqn;ps|``_0Uf>E6=43"܌2 :eDh<Gj j6OOn-?) xL6&,D l˂ \s-W40gUw඿K|Eh @P`>c=*a;,ұDXv Uf礣QѰd D&tcNV*l=\^z_)_JOyG#Ͻs39&r:"f$uWG< 74NTopc6p )N m]5aGjLZ#LtNqidzLv"ϩW2L]pz *.\ rO=;M|NuB, ķk=dB:Ӧql1vl86+*/~Q&~F|:Tjۉ Qv2jEXH2}`6=7*a:g|>$ωk:$MUn(d:$IRw[q9|P1;BI;gzTf 98,#T1=+l4*qCj֖TIB>n!|iF)Ǭ瀗9vP2QdV9>`r>y'>'mhDNa7Lדl$Lb's`Nz`#BFZ"0hRڜ~$ ӽbt"*Vql4j RV˲b -Ʒo3s~8ʍ yUzOm9,oO|EM&$áyԛqRJӟH8Q-hiss2°B dH;LHCSaZ2wLfiGeij:-ahsHR|2)}L1%vg#B;6'vh+`>f|23sv.hO} ӭNF(gݡB|U)iGDL{jwra+6Oxm:0Vrj!+X(2c҃ B);)06kCz(FS|  L۲ϓIp_,7~N=HN25"tݰ/7cAT ǽ3>|4Y`ߪ]*ϭLN& $I}bkKk"ѵfllAaͦ)~/:_|/.4aH)«~C5; ϒhx< f~@<{̇we>EF>e|]@!KKP)HLS֙ ka"X.d86Ƈ-2v.Z-*˨ܶmdB65 DJ)\?Ed2Vj|a@?4`"οO~`@o:#?ޡ{Mll|k2LE7 C|BYZp23`vj3E ;wY'"Mwp= `KBZJ{\6!Q%`QeŬg[]2hLm1~Z!ֵ Nc2p('p[<1k [/ wCǶ0pm+PfL8 8736 Zp y*@8&j4MB l21^|e1tn<xp2at_/_Xӿo#/-1B|ءg>a-q/g8B+NVcf":8 IbG-׀<9}W0,.FNO}33I!!--!<|0*Nq@Q֞Y1A:Nb>&CzpP0Fle @f65Mchͧ._y2q5lw~} I8:t0YFOQjD׋! C\°!k旟q'##;,s[9˯@!gP n vP"<6;#T,|aftMD e N;;^ bFIC~dڮ#{;r{8FLS8^o|, Áo`wBsޅgsO%voe~{idAAcHͷ p ܻTBZy~ڡ:)q Yc>#gX%!]qއl5yr`xiY|a͌"!%anv_Z2&R[XҐfcGo{m~up #`d8ABJIDk,`Ca[) (s3op IDATNVsg_E)k=X,H4\Cv@u/58+v"7gviFI ȟ|ˍ=nÁ{{ŋ_HJekI> t#`b9YVÁV!"6ݭ\LB-un&:}e R]N&~x|I ES6/T-Pf9JSJ/VFSad8dYFޜwqFBI vw?֭fRammzNf JP'T|1}' fFF,ݚ,1_> OAWav"PmI*5nBAHc4E ;uXF_f?ycqeRVj9B1N:4 {&O<c߇aUfA:2In?)0"J/^y?g|~ߧ^ ,c'BcD5|\wm^oVBnڨ 20 ƺDޱʭ> ,]B5hݻMwvz L,94nRd`Nl?Ch- 4`C!jE!zo`u} cgh @`wzqhDq|^m}b֮V6o,(,S@ k~0^0<jl<aJ;4.Y )IMvx67 JqN,d)dbfy!Z%cVZm `ڪ ؼ=d1:dh E$![4r/~?+QQ%V a9 9kׁ0^ͯ~ۯƵ7]Rbu5*=\7(E3nS0ctuڽKfzjpewx1/푘trR.o@+ȯ]կR*-\\_bU)gӔ+>OL&DժJd|< vEh&Lz=yCk>w `"'|;y]m~h~h4"W|+1W!f;й a&-,k2a5ݾM>/˙լSF׮q77yM쟉R9p|cj?tJۥ><>;a~Gɉk_W(4֎YΜ}E(R2)KEmuQhRHEMiH6Eqnjڂ]ndWDI$Eq9o?<3{y)(Q`Ν;s,yy3lԪURO8%`cK܍K G) -.5dhUc Q.JqIWh`\њC6ݼH!k~^}yO=lavɶLs%%[jCNHv}c>9B~nwjiTZ`s:[ׯ[D@`{N~ d29m(r?I%qU|r +ZLw[Hݪ%6hZHm |;:p#628 1p0`N7xi"䙅o4{*mFCc i-J^B1!/^q4NRoi0(yN2hX&.|ٗӼ+3i~}GBɗ'2QdlH3;K>K0$h>wW^V ZO% ?|h͠բ3pc2BppoD _3Z_) "eoqy^R6{'= r}GŘݑBc#*lG?npdaM|:Rb59sדQ}v2&)cq ӔVKwkKo5\P*jwVgkӧm|~X.ByQ#3{nR'䎒ϐ G7nz5.]Qu 1Nˏ>ʓON B^Ic pDU SI!zʊt9w*/>[JTJ;I&yϪ^!-ÇY<~yߧ}: r-~)b仛@udEeIH<qPqL U۬ޔ؝p TgaR\(,..F6QRNw[g `6~uN7iJMӧ9?Nv~g~Ȝk˗)|Kx#nU KjoEڜLݸA&//'W_{o>?k[@8|`$V5C13OO|TN,N=/Ȩf̭TJ EZj{DhɳQ0t5&cE@pnXR1ssj5R"Jn\ϒp-nvgFwvom~?Dy'yC1#FI 2>#PvnmQש+uooy x[4GD[rr@u4"sIO 2bJq5r׮1C|iMg߾>}8 |VoK؂mSX\AkqK%\\Fyqիw|"wD@X Z) \;`NtƟvsj5dTN+Zۛz©K4䂼: F&>J?!L(rdEJI#P':n`k"+5;c䵞%UxG#К~~ov?n,eK%I_(edU2fF*dh{"0)EӜD3Imd"u3zMxwwD@a6lcdq$ްFG1EBecÑ8m4謯sp+-İ?b,jWW..J51ah|u"::"fCJe` MP)쵱bD5*$Yg!8\yqMds2a­dWUW/-]\:gx̤ӡxe~p:88ȝAwX*(c',$K 5n1Sf  looJy[1_nδ[WܻQ߻paVl6ucE"PÒ@RbZ~QJu ;6'P&Cya 8;AH0+%$w:3g8?#1(߷cVJ; d}gW:ks2jUԹ!co:VxR]4uL&j | }ox_ٳg]SبsL2Kq!!IG&[[3g/.☖벍A67?K?[_ōM=qy)gUpvOgmͱz9)jg:Ĩ٤~>? {x ^}?UYv\C>|rugX8u Z l"* ƈdlǸ8f\c/mېjt*5~ُo o9@H?Hk q$6"kG$mK.c0(i=.e#SG ?8Cyih0a%P l W':Fɶ|0msbyO>Iqel&10D0 S2ҙWQ>u aw(t7~/Ep JIOf-%iyqߡ&˗iv:I%Ǯ4Hvv%irVc9S(V1- AZ[[j?fÜxY֞}ca\ fAף-7=7uz-KHLǖ9p$FjcǾt0:fvI;AL͝^ }.Z(9w:_ʧvU"p]z}Ҥx<`Jd˯C JCn^q0}Rd6#*rx49C'N#̟81uaJ%CA@[g6ǟz=G1rߟJ 99n?cZ$({-d9<8+ʪ(vjS(`洩Nq ge2Tx!djLBP.( TUJ&WM; 1%Rdp2<Vz=*)g,:OP8tHWΕ\˓[[[v: <\rLy~G<0ÇU䗗@#9S1`t8aF JM&:ڍ@>`:?`(˗ n^8tt*E8 %RX,e9CTbi}@Z R6 ˶qy2,R 'V/,Li_E1I&`C!gO&~!~9kk8g, [:Yy 'ݽ~$a LN@V#WR\Y!Sa Xf"qC+5d:#XqE{cFC_ *d:J@~W6^g:(;qF @!,'c)}rY$[" o/Vj#=Arш`8td޺~I`s&;Wꛭ>:]08{&S*_*+Ips9ByiSXX)$l$e6rb_&I S 6l|+ɧ>xsFjE br֤ViZ%ہa~-HHoG0u:D?2n6i\Lp.}~,ju" C%(L r|EűV*Fi,oJX$"*w#@NHjԖj8p%n~d0Uɸ8mZwvM՗!؄ FoP 2MPa>1C# Iؗi/uB)iR-!]|vԱfFfRV䗖O?JEv:xd`QN 6\zËnå1j~#D{h =ea' %gPj7ib2"۞~N˒2\GS~v gǻ_YtܜQ$cQ#S(`9IOD%dq,1„\"RhJi.015${=vl߃'] V+YVZl"3vč5A$%:K?+z{^軁9&/DcQ+symøeMߏZp;y1|y0W*k_(2z``--QLȖ˨POV#[*KG2݊kH!HTHAHN$)ϩZUbJ')`4"E.`@o8yԕR-PM0y=~O=??o>\N9ux2a8"ɔGdVJHD f=jxhH@J"3IaPR.qǰӡ=p#Q-}FЎ+~'+G>pE|PP?]Xdd㘥\rءzIV_6LiCaS8%p)V*zTm=ċ/|ۇu0n%`XOV\s`T-yۦR,X5Ik2R}AIcqK(T0-ubW΄xRu/]Kvdx4bH jxW"i? o?>LӄS|ֆ`UXL%6Q\>v6K&ò iYS/DնcSJ&Z҉qzQBty0 ֺ jja~MWÃwd,x( 1Yt"d`)U;oVi42E&"Z2rژvdNN htKTn( Ð fSJeZ{5x"!pه(^&BGeX6eDJV +f2A{d4X,9 `?R&c("Zq<5NX1>(PF b"q " Ypʄ6ENe耝+#$40`dÑEyZ=:> (A%ۢ@ ^Tc`ױwA JPCC&,[l¼ 86XV0;DTK&A!eN nD𒂋*A%B &TMXа!o*&C&»D]d-S4 ԉ?C?ăG),IENDB`FRAMd{Z IHDRg- IDATx^y%I~իzgvfɑw)DrIHh4mA" 0ۂ Ca@ -XE4iIr;=}yD/=.mdȈȈo|W& D`.Ùt%4:@ $A9lp? n6[ 5,XpA$\pY@a!]0d5`\p$<&`K%6/[ի@+CFS !M!aᮆ [w&E'`*cTUx +Mh֡ޅv0lAPA32!qR!"8&Cj)SP(diJ$d Y$dY>teQA;F Áwk XC\mAu. Xewe%w:$v:DQAX58&ՐQThsC|<&F#~1w}\݅l`0푱ivå qG$*D&An:*2aDd֨$A+J>hdwݻzpfoܸ1~%נ?; oЧ  ?'`",qs̙`}k~KXgol6JX{Z?-pBFa@^SiJ+&wޒq6@FxhCʻ3ç?Ml~r߂Zmeuavbuܹ#u-++Μ!j?} BǦòw޺믳;lVwݻ[[Z߽ R"~jK t .T*O??\ׯ2R!j6a8|Z)\;losz_VF ۅWO#x'O]<݄X\ߨT6[k.,>u A^$%ũAfj EDQAgc#l~­<3 ݾ}y[zޑ w>%b>*|o~2<\>֮=|9Ӣs sL/fzTE>9;!(TqhA)dcJF3Rpadf^<>Q֡şM~qsjks'hXn~bgi?Ohm=e4xFi0ipsi:mm8 ]V*Du=ʵk, ^`;gwq|xO{R^_|R@psׯիT*鮆, - ևlTeh^zU8w9mZ)f=m3>qsEiʲH ?6a*^0nS[X(Y܃:C>U6;Ȍ'K\ş~gX{y:>JueŐ BJ3P AS]XD֒$\y^kdQ Ճek/^/磼*RYgSu\wj:NE>Ӑh =T0$l@ѠTpXV {1Q?r^`^K擟}l$;$\$F}|&O9,  \+e 'PgrGAvqօi"Ð^'vp ww+wm'Y1ԪG=g]]y'^|BD-sTs50C}Lhm~<&+ x<)J%M8MضP>AO{4Rj<mMOq2@=t?=љ'^e, C0ru5րN,8*M8UzEM'L9;cat ) *VJCg}V!{\Ia2o~mGF 8|~g˗K>*Zk'7Q ?vn)Rjux LƝ VfpTe;7pG@`sܽt跄qFmm `ƟsVTZэ;;$˂.L!P0'w?8{ףG]]FX_֠݃FRew$R'w`n%UWN"4zX9R^r A^qs[]xgޙ /jBW֮\+.^lmqEqhZۅ`zgkLb3a Ď6ܽm28PeC8sT _*qB;8t]#L{;WjUx.ܚpJ?.8Wzx].^dmmN@}菅Q\%jz? _{ӄs熌K*NS8}3W<*KZܻ'0noHKxaéh.^s<ܼpA^tu:Ye)YȕDk3>:7MZn;!ZL̯)+S*M*g{iNET!K$;Z)D!O=E6 /}o4=.U08ēg^?챍s.G._+u$IBfdFZ{d֤YWn.B1|N|OQA%̓us g=)7BCX+sV矧B}e%H_\Vo_ Y_m^K./@(HӔdBhT07C`$0[U^>NQ~UE/ PJQa?כֿn*PIBPP]Y}k>g:2l .M#z8|`qseW̙SOst]("2$a<dCys6CQ @!گZR>~3xJT?"% a6]+sZ"8w.pHߨoz]]Fpz|`__3χ+gΰQ9Lu>N42yNQdKN0͋bj%ÐP<i6ML:Ji|Xao~;􌎔^O Wpvwl2 VqoTfOK{!*SӮr Qqwߕ 2W0C3M@s߿nmmN&"$a2)J){h03qielYҹ_A@6\aRUSPBC3$(5|"wMAue!2y_KoHs^ۏ]vqU:Jt< ͐A"yo/0`{0HTCيwMvdJ!`&1،+ӣ==>|?ݥ_iMXӴ.^dWn߮O2_O#:GKX ~~msvyLZ%˲b/IrW,\3lHrS)EhC|2!spX7E}Np{nW詑^I!()_6}έL<.ʬLw*MQIZT.M6Μ:kKpyx`\?KB!1J•+áyʹ7܀)3 \[_h4,4E5_ŦQPNsC4% -?(̌2p6ON37әnP"W/o|Nֈ<'th1Zk}̛owܞٷS7[X[8s F!D1[v"3Mgclq`21 GY.~ sVt6)}k_ OyUlI>mM$)܊ʮsTG)tj j6#bpM"ũ +_XX^/e* y:;32tnzghLb2'ÆSphq ,,wڪGCggȗ]͹R8߮G*  gr9j y8U/.mllQ 9T{+Qy\t\:?Nx$):jh;GY#qn<X?{e6J`h4uzgݎY^&k@yӐfN6(2"0Ձ|V9SS鹅##ٌWx/+u~B t]c,B}qoo34Q8ⅅkaq2-;" =+# ևeg^XiV8(^QR!$\wDpTn^ݹBT6;7ǝ{~uf:w|wRf1: Uj++4E W!nAg8VF/,EZ-iZnهFQ5GCCkt!e1Z)BƐ@#f7 Xh9~!m͆=|>iЇox=?DZ/L|64 g"Yfa ꫫ,9{M&O3 8ű%t-/_n-,ȥ%f~8ͻQC IbzęB;C|2G|SCʑW]̌}Y(J 9 cӇő r̙k/.FnW,,,PT&שI$6S}Ph0$0$pQdHs{$ &?:YXR$&^=|*%ֺJs4.|q9fF9p.C$!HSd\[cyVLn==Ñ\X_?rjzI~̍9}8 5ҹByPͩS31Ǣ0K’l! CL.G T> [ ,iswݩLCcu'E:&" y$[\=p WΞ}>viu:4bm=GQ8Q̼14q* !0ࡂLLXڙ`@F!4[t#fͯ6MVG<6MesLl+ۅ3n3luAb"@A}m ǝVYoaVo$`|l4T*b٭ ;E&@+@*PL7vL \LWԬc2kŔI_[QDX7Pa(0#z|nfgynl89,і4j:ٸo{W0>Yfv/F<'j4-/SoBD,Ln3# بzieEv:jYeEw^ q9t^FAćP!i:j& Ae!j2! 1OKm$n`)cfvVxLjͳg"_AG4grD:|tY|*¹8Οk}$n u++RN=:OA^u(2Rfw<ꧧc1NjJ6Y0O&!p8]`{N\A]%iEsdSanVEvM,>3d f{qJW*DųqGK  X"k}|uGpX\\lAֆ8A@> aȕed!*5C8+ pmI~%k ѴӒ$d!aAeq(ω͢I$#{fvŋ#ߦӑX[ϥ_[»grE8Ry2$T۴mGj<%`maᳵFC;Q z!m=:X Y ԼF)`dwwڂ[i+e {t<7$L j5 E9vj\*Tl+##= rbog;76\8?o| 1QDjQoY L3Pt'jhZqf_/Ak4[ 1=<i{yf8^a1I a1ug HHY i) !{<̹6j%&2!HNNn ~zf;tMVevhƒ(Hsp6b^ExmIlv~.Fzr.K4:vRnŕUDv9ߓxGăOyu]uxn$( &(ͪ4-=;he; IWөLP"+;|VYb9B8B1=MS۰Iˑ͑6UhTMZͦhFq5#`{aa#sZMl [^rI8?)TQRL!to^6f\%~S#+^d|kKfFŢ)ss%@ f:  SvϧiW YTb:4>rp6 ,]Ckr)"S{qQ4wv*Q}WlTZT1Rb 8;";8(OqRQ̒- 'i!`RV*f j4L5fnҘ:Mʑ)ϋ 6lBRRr/:s~1pʪ r>)}2{,#ȇCčNG0R *09FCĵJ!7giH6&t-cX"]? Ҕ'IHz=SXL%Y,㘸ӡhƴZ-C K yGui]A9IGov9؂M&OvC7t- Vx?G %wLzCV!QCt״<' t<͘i"T|(aJ8  עJ(ѝ}/#ڣzes^Ŋ9wH{{pRwn.D&qC6DPt\C3d;@KK_*DaAnaI 1؂Q=mKﺶT4Oshmђɏ H0LS3kThZV& X Q[j8Kfk+\!OIi~A8ܣ#Xrpo[H`@o: @+tjV3RYZ"j6 q>2s7{USvmdBHPTL$`$1&Mnd1)VkTڂ.VGBW&tQT`ha|(#y1ʪټF$v &m2 k5f~6act nߦ{oIS+V#*aIPU}#<!ȆC \;rMkVgfG4;!;lE8PF{xUf,3onVHkN J0E\pʕ+Z-m07~3t$qs0| TSŸ.CO#pQKәY+w$Vmy2oyGjvW۷`0ȥZJIRn7Z<>nolׯ w:!*ܼ)r Քq<%M##P'2?͑*[[t|xZMXeU?M$unT7jDq,p= joiv# z=9++٩!6S fNj^7 '&;/}Mӗx3I=' ʽ{nnv:իw Rмx1HdW؉UjC)m'LIz9GB{޷PMeeKRv=O슠ݑ{=f/y" XQ$*DRيXDQG>>2 ˽anbR>U3r: b:fW0¬uh4j5T0yE^y`>ׂrZBXNg4Z:5՗J q,B!*˘1ڢ*3utzp`p鴗{ɔiˤs=r[h#H+a rp*I PT@py!`Ka0 gH8f|87!ᝰGY8L0]s.g[^~n%l4͛7K;}wR`t!԰x,{U!e]FQ܌8FV5Cl4"u!#-͢DtA]xd`ImJik]>2D83IA BЁeV(*^T0*7o,$tE8@Lmu+_?- "}bm4ǤzW_卯}&ܛK_2( 7+m.zc'xa;cy,(KA:y8)-km=YGܨO8]s뫞#ֺsMeiF B{D jAH8dr󏇆67G!k~GGNdf GV3E 7o{߿𢆿fnPB>{P /n&t0tM6SY*1mGUVh*l6SCK@ߍahZsPFQ,L2GyaZ[=0*W32 RzJUpLEYULiMݷoz7M{=x[/ix}&#~ t;I~bƍ/yqu8I-+,[9rkeU#, Tf;!gέ?w/I[)O<ٖDJS'd [ t '#sQ&Zp~7K陯\7hz9^!6ktӸSLZk@Qz{0|}؏iե7ޠl/.g촞W1tf;#$vEv4r.nN_.ٿiR%"=)m3- ":/3$vްf>Iw 7dzꈅ߹̈́M `leE 3 LWR7)orkZ=d{G*a Z$LI& >ܳq`J>\曧lWped;ȳL 9Lӻi4MV&OyqȪC]#UV{R<{~K_j'O?IӗZP9J55xps j½U%Q}~t00'4D9 Lx{HCV*>Qxd3.e n  h(cJh]ep'LfZana.v[ժQ}=;; %98 98.qͮ8!aJX}iGyV"|`DƔiMcJ-LF$IUh>)瑬psC(4SŽ vۼ}Hf (Hc#*U,  dJZ!U[c&]FwcsK;G(yV*v ORܚO^q彲=I)`2dJ2l&Id2)6(IyxAG>? =v+O<KBBf ta6c(IdwH{=K26a5"[WBJjYVAݹ]F1+6G9]6aJXIZK:{ͽ1ϕ ͘g6 zySoq!fJ}3L&;pJ)c[9Skˇs??>xpCsC2'd`Ct00y,3LmOeaj2)^!Vlx\ 4O13,?¸wҸP~;ˣ0F'4WvB,C)y (]Ald^=ora 6O|m3BV*f`8*Kl4"=80a\S(0y0foHX5~*;8S6$a1Ӄ,2xͫ"^nɤL̇]3c5!+\|8|׹#M,onwvPcf$ Hz=mb3jh:r#ldCY-5m M3SbAl2>)S^Ҍ  z=J^*AN$oçGp T6O\O\d2jsaJ4\oH;Ko :Wt>lFpqLjQY\Def<ν-&f5PH)E6NcT)OzJ͐! i#w 06q'y.i?gF~Da/7pJo=9pSFQ.yGX0u(|BJf#܉g 8S*3Rv {%S@ 7y>˜AŬjtAY¾i_ΎmӢ|lд:`@2Ru${oRgF!Ʉ87'>p+P.bVw CX!|*/VwJDaRہ%#|TBZV=0$NՉ.CO)C%d*H;;G=o7Ñ^>5a8}yO<3x8J=Wlyʧ8f=FqUGR!l6iVa}zN9X!UEگu拱y-|LųyD*zar0`vSAoG}&BUR!])%V|Ҫ`Y !r䚧|>Q2<.őexyISٴS$$̷͛I*ӍT*6 V4>J+ȏT@p`o'4Mʄχ) 0U>G8kȼPo7xSbI Y3^6ZB;CK:]}qW3RNIȟ4 wJYT IDAT.w@Q VX~n_JERZOyG4!0,,a|Vp LD!"6//[Gh1"L Ӵ,uyvוr:Ok%I0def|1=8j2 T_[ehe̍N, {=}+kxXAwvwv>{ΝfRaeezNf3JqM8 y< l%P2waY2^S Q!C.f! Nun75yйmߖ .}NҬ)E+TF4Ν+MvS"s $3ww߽z5|4D_AjcgمI;!`\8M1O S|t.( aE@iAJ͋f8IfMHitT]l`:rQr9vU)۬`Kvws>08\1UW`Z2%N=TnA_4ϞeUn@KΏ:Ulo $YU34nQxoޞ)`;XX~FI:0Q!`O-vnw`2_ *q"F?^i aHLJX !=o>DpޮV oл} J6ɉQ4G^(<j=(aJ;4]R1q1K>a.cyUӻ}ېTIg` &LHcU6ȳ *QSm4Zm KɀMۇ N(0$ ؿs} I9\"_|7tw/zAET*fEU檡=f,|s]G|8dp&27^{wvH-TrE¹5`ZaTݢ hopxk_cgo[{{"p>8)N{G}RҩiPk6gqf:n6OsZN%o>|iQ[Ʃ ?Rשj4qn#`ajZ>˼+bH#C9%wC,#qWJT76L|  n`|o׾Ɨc­G: ]鉁H)Z>~{XCjtm:VVj5J舧y0Co=5?8n9EnvpG juR)R"l<|)x/KgQ&k Y/#ҳϚڟJΨ}zW^[_ W*#iPN KdUkifrZ5D̗3Dښ }UyZ0gVgz C|)G\iKgO<|~s sA~14MbjP,߸wG#%u95Ʉ7= p9RN3?{&c{LomwwN&Ի]j\~ {.-<= r~_QWWBS} 1])|BiysJ\d"%,) @u&Rp t ?]6(ܺ vb81ںinkNYDg̜Re9;3g<<ϛ=wݰ$LqGj9N t]RZm$Si3N#w LZs۷;#4$Tw:x=&^{Z=x0v5|ϲK*3YIpndKmURzH)ڮolpځ`~l&unR}?&ෲ'\'_(dsC: )iHbwj)# $k5+LXZf La!}tiqL5FkQİٔ0:W_iM!^I*ȹ޳H{ul!ZעsȋWz!·~7R(yN2hX&./pT5ңbni,J;+?npdw">ZsgדC~+#&)8iJ ץM.+5{=5/^9wv[Q(ݧ-Kb#}.- LI4D5Z/u*ߏ"n!d}.p0X|XziB1txxc_#a*@w8d\S\ZZ!;/_~|-$C$Ȉsl(ō7qndl>՚΁m3}pxV4K؂mSAk3.Vיt \>G_!] !njz/b#4oqaQ,&~yˑVɔJ9HJEG#^ P4iP0 ޔݗ<3! @4HQwc} T" J0 à\$tĶm1!t SMSAhun>05erMyLvv44_y[?wC^AǐyXAmQiJ6I>=|qxM6'&~&23C~a9c&W_e?nq|B@av;`A$Y8cO!F:Rl {ڭ-(8^~kk+l6t;QVjZK/@)naBd(ΒVxhkεkZ P Ď\AHs6+Ј,{ddxyO0CqL;9v2PÙ#[`'R]>AbbQCz-a0S.VE>z#"S'0u< ɮq}:'}~ }w% /\zKJIΝa~ާKk87tj RwVA7AƍvkF>uK*817GR!_.lRVjwbvCMQqLuFkqbzlzB 譯bms?{Upvl'ffX>ygfFZ=o70`:ґN%1j6K~˻;m! koR`  ( iVL/@"GCV2Ԃ]" QSzY2ݭ-G#n!בуIO[9~'d=r2~G!bUqcǏs駙y0\vC17T{ExnǺFFvaYmy!O( / zᶔ|M9Z6Μ@ a?Q.#-/Xj(&:CQY,$ R5{`@40lhv Q2p[)n >-!{0xr~ť%rZI ia ҙ#}z}gKAo8of7x[ ҕ+_}\-Kd6NlRHeLJRZ'0~A&khv:I%Ǯ4H= ەHrɅZ9vHV.\r4Q  ≚:>}pr+nWE&}49=7O3C̞>-a)Xf9t9"Ak)%YlGOعs<яR>uJl[) +9HWSEQĤۥ&7 ڄ_7x`jQq~ֆQq9°@G(%`wb|T\Z >q$fWو'j#m3 ˎl2%J 8332ΚPKAadEffg9l%v^UAl?](ɓ,?O R }:YffxGdב"%\Ae8,9KVV?}2%lV()lG](KH8ZEeo4۷E܀A~σ?>ZpPxxem->uy"+ӴetWB+Q0AO AI8$'X tdjL!R.( TUJVWqjiRaF|K`JS,Y<{Gp쯔%'UYX౭-f}u: HiuZ%(;&0{4dh2an4E\>NAޞOk[+Q՜,]$#FaORYX@+QX\J%hNȡnP+%j0ll>O&#W*MJs*xqWDLi)ͱ<pȕ)"*#</u"U !W:S >a(ۄ1US%ۦR"]?,8ǂ8,>0j @ _j$i.NȄ(8,0l~Ϥa͸ӡ~ Qo3|p }kBNs_ rt ::aP<۷XiRK%2n۫rb_&I ~l*IzO4 SRaOv++ySa$!$$׃aw&\aȋr{=! 7s}\a;̣?3nh!ph㱡#鸠PUt U-ڀJ&%_*b)/Yb:lfFfRUpfg]h%=;One& ؼ~mW ܆cL~-{w2^ϥ =YN^?0t4>WR!M~.PpUA/=ó&|Jk}y͛NǪZMF,*2V6鉗 :%Fn$_*1UM =%^#}Abϓr"¦S}$mz MI W!h_zd]{5\!\-w2 5,s5Nbզ^NȄ8au7|ӿhUY ffv`r4`*nӡ͠`gkHoG~&WӸo8hB2C8'cLȈ}JڄIJQdIU>%I08~; Eų](u.:&6nm67  zWW |w {콣p>zskpUk ݮnj(PU*2x(#na;4 JUJTniS.az {2 EF)zDznaKoJ \qsIDATrJq;i_صHҥ)19?"L&v?fQàݦq#Bm0ῆ?p_0@f9S1GJe^ 6NDV3l![(Și.;kIˏz$_JRHCah>ԑSA,c/*vG0: YuF#ejp랧8 q>COdߗ 0W2mR-,nf0y1J(if%i I0-ubW 6%^.Aby шaҎ"Ӛ6'^%Gpkx'`&S6|8:P,Uc>Yl(:Qprˑq,[@ISl& fۂSJ&Z("`'rI: z:=>~G'bb[U{IENDB`FRAMd{Z IHDRg- IDATx^y%I~E>ff/CrťHZ4AڔD_(iHI D2@P |AS@؂e4@r35;}Tw~yEEfWU}L_!eFFDFF|/𧐘\,)Xeh9@!  1`7vR1.0.$ 8h`xwQN (y\ mJ2~o#]쏀O):8,#&ly{d 0#i;~SU`;!<@|[%b|wosQqݙ kj5T*67r"J33j5Z N}8Awi Q$IG!iloc>F.}Y7n {B vxo/$|6>[:PY!$\TV4Fí.-Z M*u*zn ZS*>}Pq]BJ$1,`Ex  t:ȢIl8 G{{|ǺqNG{At.п1jAUm X`gp!rdqs3xU4ΜAi~n 7 Ag#)]D޿[ow:v_ǭŝ8ή1xw7= 1oÖU?X>1 \hss6ҪFu4VWQ_[Cuu fN JQZ*P:foփΎp8ù6=˫UYƷV%](Z) O+'w+$%x*0 ):s2 @K%x*!\wĻ].W_w^e dC?k(?v8EK@0.~ W?T_ O,.ַ.]Nt%R?{YYzT<|Q~^' Jıec^]Exi34LpHc>W ~/ȹ˗K?Ywӟ / jP`Lnk#> B:R n hP'V heGigFHr q"{-^?"7X-H5&,7 Tpf`LG!Cq)%̝3`wv׸/_gWGBt|| /<ܯ/|mn51)?ʉp$MBOB4ii:Cq6 }OJ*KKh=ϟ'9(  ?˱#A1[?0SjK~ny}9q}b @P`L$!$yRL*CUP,;}ԡ@yԓҧ) WV<Ḟ_y%6}= txׇXbC K^+\ix6N@D.IϥY61_rJ(T# aC@XLcaPh u]uMRMd4ǁ(/.rEZkk^.c pfr"!hF8?={+&֐*0!AMa+xzP+g_xӧN]@O9U4M<qm $g#&@ux\Y6|Sp%4P> pk5PJApFf }Bpp0mҥw6saccaՅ` &EL%9O6B*xdb eMS-Qh8#}tCpr~PBÌuA\뢶 Z;^F gCx|J8:ŏMdpwy󘛛CF4$Adž7=]FD6B{Pc8DG`:Y4k&;\ 1V!8FHN>&'T:O&)᤮80R uH8lKa^.'>.…+W*ϟNaqqFsij6t?խ6.E'"R3mS B+k("V?뗄v[>l1|L4t pFÇ`wzC^\>کS?vdu}cnmmaqi aՋ}|\M4G1@S -hOZExHQ7sR*b%dQιfh}]S 88Vŕ3g=EO>g C!$R  UrOVz4ü>? BvH4 B\8ߺ3 u{T97&Nhp"~;njg#w(jFsN'~\Յ9u&\5nH(*?3Fi* -b e@o>Z4?Bia? -)7eITB0?ϝË^9'8+Wfas/.on:/]"khZ<Y!IDQMsZO|pii.8//caq)^! hRZȥ׆GIu҃ZlLL;0&Y1B*}*!(Mʻ]'bk8 8 l~K&Pyiphs. Dmxznz!̋BN8cWgǁx4%01F`5|Hj$ ,_:98g~y<\\Xٳs//n9CN=FR9(2#B m@Bt=x}usPe&3 v4i((`5z9O1"r!/)(4ejaOA(re.RIwG|!$YuG[VVӹ'7fgg8NͲ 3ĴJ1pq V*J2B36(OigI7L6TjΛO !j5<a޽7e?js|bnMw ,-/cffqc8"cC@`T"^$0q18CcOL)" 'TLӤ0Q9>{I{lMP>2cGXg[l~N?nbN Χ_K㈎t阂%Ǚ' ȍt$IV=jtJUd+B['&GA1;Cp*ŗWyH]POia:T24l42ղ7tB3PftFM ]}z_ET e$q3Ṛe5sTNZE'̌sp[򃎇6¹E277RXnמ( 99))LβHDZc&jL.@n|pE;T"S9iMV t~4J++XY[fU9;p*]]Dc~,.-a~~YeYv;XͪB<'73\~&@vNkxߺF.MDGy0 /S6ѠG6Pa6rnTG%&g"ǡj@ XrYzoy*SfL HBXui>s u8cuTVvUl(_.8@Dynt٤VFv9ȹ)>/T&lg>Ұ 0 "xDZE(M>[݌4uϳ| 9MԗlbX$DSp埪xV4MJ%Sj'`IB@، y\@f|."S*DuZSId hLDp|J{0|XB3\V:97}B v8ڝ.XISPCuq'N`yAx '=`T6g/ UT*eOIq$1B5Lu!SXcEb!rJXV L&Q^T*DSi}}^H}yM:}׎ kkh_NM8]8++jzZJbf1_ۖTH5 8M!!&V{D:|\64Yl2tX~U^@LW<_mL ua3ebCK@jmDqv$HB)Ӫ5͓P6sd 1pl8OlP-i| x&[!&;uqCnJ_+LU,urdbp9Am G=RTfcL/߇[ h4HHX[:)={߭TfffPV8pPz90V qƇBӍ{ IDATqC0"ןYl8D끧 G|u Tv`BѸђ$ȆC J33W*Ub5qȗ/pNMCm=~Iߟu }L8~sIR AzNǻ+c$1fJ !\=Tc2?GC#S2Kۃnr2C" [Up];:әS I& !NDZiQϓձVBB@h"hR(v$j?_DUycpCPσ_!ױ}qFI(F\(W*R}" XrUmR2ui7C)qۅr$IȐ ݩ"RA5ZL!0U*~@on_H"q$iaW+Q5u^+&m*eK2UC#9GTe+R~JE S> "& OrǪ|rUM *WR(: 4A0J嫳Q4̐^˲O=yV0,{<Ԍ~vMD|7&aI#ˁHٲP0Džn$Q*xl:NFp5Ay XmLd!Ro6B7Wl\xڏr ȕJHĤۤ݋䳯ͳ h6P RA eu,۪z~OR!~RBEQR*&dlBM#HOXpfYG!veaF} 3o4P}Z$"\rU.ƐH]$|LFl*XַarX8#`ǔYhooo'T_q$0pU82HUTZFO7!ȆC$a:ruuHWZU͚&#T&gQqi:^ɹȋZB5Iaz~wdjҸk>@f*D6<wd<>Yԑ8A^WK,uѻqCnYN{J)RZ-o .\춞o4j&8nI;r|`Mg^lضБqknhhs: 0&HhSAQɎ "LF#ݢ;U xa(L+O{-ĽwI߼{wx'I.CՒp> _7 lzFNN6v.lR j 5 QMeERvڝ%jFPZzcVJ+KgpׅhFRIl4ByʧUIWB"5-i9W|, WqFpd+@Q`gJ|dr.Sd8OF}ik{]\ף/t<7c̀W906p2.e_ |D07'N߇< EEA:}'8ɖ)[MW LKVI5#SWi !}]EhWE+׸P yeu4$4l2i"GPOGC6ah3j`q3PR<,ѻsG<|=qwg'!DgxCʁ?]x@›ݮqyJu}~97}S 9-U(*W8ZBbю3dSat7*jO&O(km# {Qi3Wߣ"u! `c@OxtHX ΘYF*|m*w$OWD(x"*ڜ窺_"@7C@BU*xmQ$Qaa$db6Mbu{lɄǑ㸕 -W*Y2<T'}\R\&B_E:9"V"BTD!4L,TX*mD|*fQM|Z49qler*Wqy3 WC@,x|;!IJ̥@$j&ڷ B8^@6iFi4!U&c'7J fI‚G3N5k9WMm*BVC,/,Aif,zeyqgOh.\:NGN3B@PiBT*e c6,JY-?miGfi,UX_QUY"zOTih 4i{dVBr "r#&6(X.*![-\DJܩ;;p|gkJ}e6r4 ?)1"űT2BeZjR$2+w^|)`p^EHB&ddAm`Hc ?癮;}NV!C::xɁn^ Ǡpyn_,_tN%?L?(^_J߭?vbydɭV!C$NI,+&#D>ts|Z 7I>JHw6edC/O4}HӔߊ"(HtԹ7)"ka/i䛠|/'$+_!<ANG3V n˗,^j߿_u?|wPNfc̙R ,I+p84կ!Tگ**JR>},jT>\ Tj?K4ފ=ٛSLy+@=eW[*O("Dj5>5;?i?++W^Rwop"Mߪ gbu.@ʬY2(B`tDŸWv<},sRz<T4q\V+..:/pyPO Q.}c$ȉS9iK>jT΀k^q$ᤖ('7R 5#* _mTAK%>0TZ<~3rTJa>.2M]?+,3vqW~aHzA ծAn#$^o<ŝɷ!pnGs, MIV }ʧAYtFHҔ'@7i$$v$ RziMHVtQtZXc"S>*m' Ǝrx\}@ (ːFLr+ hhJy ctTbǔݧzr&d^Pϓo96aI2j"{t8DʹHb8~;$IDZyA҃R$nگFPӿG)1@QWyfQd0XOq$ Mw8t܉HHQ,| Rtu&#'CcEHY`B2vL&[mqRR fy}TJ0y͢t46vQ-Q,Q?q5iteObq(@P|2!bL0`'%CF~O&qo;0&7̳[,ՈH6ij,]`1U,iXZ T/ &!WF# ֆU!yǮ/ q^bHۏgxc V=KD.dYvqFO⸑C1|o}'?yaWT>AeQo^ׅ 5"NI gwjSZ!R] ]6kd#r6qP!@+~*GJTFU~fD:!щc1 w\-.~3~hd>ӥaIOhoh@(|^HSIK%m@=NÇf IS\PJ9Ԑڐ@ [,39S;\ϲTl"ha{Bۅ $qh4FQDlA"nE v'K"J*"3FUԕcN2LF#C,8`Fp> ,@ëTWYe]c~;)_ԕ >d@:aED|"_yĪd&rq@3 36揣|*V)i{8TaQ߇WcBjz=d x=Vq]tnʅ NHrfOSBBZx}ʧA0&T"B``7I.;R 70 p4+*H2ۯ;A!11oԏÕR?5]'jZ;b qd#%" YLcDTeWʆF]~J/,Uu~%Hh^,CUQmL%`*N ue"!06YI)MU>EWUO"߳|*ou`n+9g#ɄwQ3G!8׍fO;_g}c|v;Q$,ɑV>E4%9! S a+!Ot*BBq]a(epPIԔ {֔)#ݰJ X"ZoiL%`0z}F#!ŋl|#{Tg'**pqc ̖T擫NZ2Q kj8MC2&TkB$a䃧<,C}Iȿd+o< İGGǹEEӿ~ETaԑ&Q>ESGJkD\NNxPu"ƍ"B)0+7$T<^DT~ i|?eTpO/nJ)*P{T哇0O 4SJVZǣ(W-Ppk E$Y4=V6*BkKZ{{@G!|ڵg67RZMI+LMt7'T\TT| 1qd" Fl67F IDATvt9'$ ɨf1( xQ^Ai&FT2{Y.^ Q q(qaoRyaLe!P$i3G]WNx @F1N]@B丹gZZx"FBj-fB YȹZS/5YLUXAR9ۦ@9(JL(EemͼM#VCVN}?Jƙ` >.n }߼S~q$oyR4_L $l GMs4߬jאOقEAT(THUqS7Nv#T6UDM6Pa58cRT(YEpeW c()"Lj35Kա־păt0n o8k}g>Kz.0 UNWv,74l.G=;;H:qarLJYt ![Ȁl]K^g9 goU*T $\+E˹JܕՓbvv[vM>WWF2=*?u<Bw:޻;w6߽^ fHN_]6u]E ;_n ݺի޿oHxO"Z e M@XAC>}_Buիkaƽv}<#6@GH)azfr0˲8Rbp<Gu+Qg N;۸E2~cs}T}>|9JFje@i*&+6~+;ʲ&p0}޽"G:Zi ;s$&+(! J(}.(ƒo} _~}e l@i $d 4ٴ HRFN !gmo߾˝ޙʑ]w~{.#r6, (@|H'F`P a2 $N^"',68"d٣ pH>kp[Hg!9@k9{;Fvfw;Lk67iuftu|cn6?m.\T*5ɞK iMc{(ﻂRGrRaTш%S`|\[6M Ok6ɵ6QPւ~.yž?uo+/jM!4ByiZ 9D6YST~\RZ9xJ:"|H2$1|}ǡhMMWNm ij 3|٬4d6d1Mo")`tj4/\`WyUUsshMѠ6qTG7"jHm` V IX⋼op%^"\SȍwCv3BJ%xgnx^C*@!pCkuv:[dD CJm8-Us9:|k~c~w=_/=ۍƏٹ|r{Ti~U|P[  :kk4^W^p!CuJ䓓qèⱍ V^}|$j~aJ~iI*k\^{]-¥b IãK@%BqGm߼IE.ZH /f@h,=ˉA2gg<ֻvWx̀VTs"6G#:kkRrpr y}$ 0R)O⑏ɓNYߧ}ٯ~ŗ^bl2 4qaD;( aj1ltZu x[n3fZPT,T*A&C/p;;tRasg t" q֒͒O(X[#!ubLo+ toXQEd}Bҥ,cɐ&`TKd1G@)eaJeͦ 3;(*bM;;} BG=^>~gfm-TEy2 硔dQ2yH@->Z6-*(:Զ,MK2IQÒӶs9ʃCTOb}H{g؈"߸}CguִmBƧg*ھυt],E{=j;;s }|琄qum;+++_j6?/STJB*v|A*% %~ 1izt9(B2PmRH(BUF6=ǡ@HW*1C䵞&UXКnݏ)B&CP=M"@!!S.*0L*:0tp=i(zr@0&NiDJ $ѨZ;á Q]t]]ʲRbQz'A eY0&hZihsui[M#SJ2y&0ը_͗^;>6"/+EhQDcQ/jy]\.g"{ms1l6lF8( vUuify!eIVo+|M.s;oXb,$Kd\eIsFs}m}%[чO[W`{V-^nHfI5 ,ZzX(aݦjf?-GR)ssسI:?2ڢuko -`#WҜf9J~12v⥅`ZJ_T'ϝ>4o,99ҥV,#ŋ$;;T98\,3"rYԹ;͈$$U$vU5E[/޽ Zt+ϟ?j H]B{6HĽ"4{  vDFtvvӾraƨ٤ԶyV{K -ǀ2͑+hEvSGWV8zy08l#pص1Mi2ztimm *8Q333,8=3#An m`2ӑT |y|3{B@uk<3(84} LVDAx0ns}|by;st̸eﳉ" >\y4 HeR| }3䗖&90854&.@ݰբjU_`t'{Sݎ 3\z=_WǬTJEZDYE{A:^NE;&/# 3BNZ݇N"'Y9vt\`Xly(h{B,私r>8#G0Y)X14E(rrx]2|WXƚ62}w QY}IKKd*uຠ|I;td FA!p]z}gKnЃ/w p<E?aWl[[ľ/L)5*@GրAբ%O"Jd}A* +ǎq9ҹrYqPRaukecGߴqX]ϳ{ jF7v=!U]f\y6EN̝>MQ++$FGJQJuA|%n0鸵ë@ׁ/TSxOիWG/QB>P,M`Bt:GXDZAܦA#FE6r%lB]guiapjnN1̞:5La8y vb:ϣ&BUeqY}J'N.݉Rđ~"Nk)t'ٳ(Cj$Uk0@`4bjѬո\>~GejgUa~,J(gdz {y92 @,=crH,YӲHg228u1S.'(&AѴ0 R,9{=\bqGyȯ.>yu#lO[!2p) v3ϠRRCq&'BtH71muWGH>4D)N76;Ʊg1!2M|THnuX(ØAV":X+ۃ3i=nz=ƝЯ^˞^}}! v;mLd(L&FT*p]0EIŨZfe`KdLD`Bߗm|) m)OVDY瓞G{cd*I$AE_2N&$uI,Ʉ{0$8i[2joo3l޼z=F87|p fouy޿mv:`2"a<0ޖBd6rBW$I> 6lSJIOR?u ˶)HM|we'k\R⹮NgjǸ>zj5Dks7v<_`7/=u~y?9%BI0h椰2N2$5Zq wzS0"=tLRò@XήTHJO+V"H{;=d8HXqpI^4 ;;- Q'0WSG2_;`l:"Nj%jM'Kf[*S"(vD2; bb1_> ERNTEOB0 8z=m[[J6؃^f*~G?Q;G9UG鴤Af *)Yb2N&GoDG" dT*XU}2q zvg[׺]ִ7!li _gau^B3DcqJEf,J%Rf:db0aL{|Č`B艿.[aHrObo$/H8MZʺ]i4:zAzzu5`؁;d `F?zozї"tf}c4R6<̴Klu v*ĒpZRMMJNH BXC9r]~u㈕nfnSVW1|ك_Hya7͋=;azn.,=QFABU:d3^"? jq.OH3ED&yu{$cr TMeyIc?-Ê]B!HVQS1pu:ZƆn4?j%>{/^O+WDQhmlrYffU*dJ%8L9U1_I tc&jUGoSA`r  v )7t'n[-6vprݰuN c!vYq6=Ȟ#_<8+aJT(Β)eug)aId GHX"Q4|YyT>M|;G &Vx Z-z&NA@mp{0t+}P& @<U!a-ٶQ) P _(˶Ir2gR.! ބBN$&], OP 1!}!#L,lv 0$r%>8؋!gIDATwƃk4tXoax6x]9_῏%Cc(R5On?nj͗'8yԼmB6KR!S(`#oh{# NP$R*YR0Lֻxm=Qqpukb\ f]vףFQԀ^FC4¯>tx #7o8.T 1:4y2Sbe2{w:tJ]0o:} Og!L"s`3M1 3 2MRєIaF+-]:MkQbݣHHHXg>ycGJ[Xׅk.n=H&|܂jL mHeȃa#i$# ibH$~Z Z>pRAk&C]|rN!\ X]wk 1ق3ȧL 4,LXҲHNojMuRSPA{=\u'^[\ Z aP Opڂ X4aрYfMH[`*O%ÃP0"e&@BBJz!rW8*A{y!XIe4,j8ԭ\FʿTdslďj KA$4() AGC˹}|Äa;}(IENDB`FRAMd{Z IHDRg- IDATx^y%I~ի>{z%W"E(YDa٠(ےhX$H4 HmöD-X%dw'gvwfw?""_WGL̮ȈȈo~GFo1B~   8¥cX @WB  @dpV Rnnлo>9 . . <)4sP𾆝!a}w A !`UZ *@lK/2a0ŰhxxM;k9;0.">=Pf V*,5Yz 7ðAHʰa(J  Uz߃1 nk%}K*wp9 h7ۂx ?zz`R]6|q V9O2girF쟐K?mwM)׮ 7ښ.,!Y5*IJ|0@)iG>2a߹{Ol7o};7ׇ10=@h|O(JX,gWxnֿQ1k?mnK drZBFa@͞SiJ#ߖq6@Fx.pA>nj`{rO>!l4!^>U['3WteP9d[ҹpAΝAui*QSj42 ]]v]}wyww4:x[w^aJOl4aNZk4%5~l!?GuqY50i}C>/@ѣG8x}_Vo_>/oR;>qU T*Ν. ngŮ0ȱ$\m( >JYR  ]9jfV.-QAqt׿o>z y/OoNJqbzϬln=/]ܺpF/]YmMzi(\>#OxtMSmBD2 TU.%v9@7d{44pu%?Tɟܨ^wq…Z]_o\~ .vV~A_#(BV%:˦>&{,3ON"} :7o޻'Ə?m6ך7XW{Z_{7ڻ ^7_Ջk\xճgڭL<)JbcU'AkCc$i-ݯ>eR7Jb73w6Kӕ?Kg=;?*rg{卛7ټ|uy*ڕ6nsqu}{vc#Xŋ,//ni40G3[^aV3m XTj; 4UΞv,5( AE?_z6[r\ObM+~//й~ … j g-ͣla?N#_ 6d=?0un?}3`TmjssEL'd-ç:[fBʛ[~?rB+ի\{*zS2J+%狯FZ3amm9G>\R3(9`kEVW,,мxXy-/_}V@ 57Ïh##E:K˹WvF|Eqics177G-`SȠ5*=9]UPQ_|<)8h3P|Pxy(L1cDнq"C!eXַĻo*_Հ.OZ3._W_|.]]{Yy֘^#&0֖mx3A9CkDUβ;'قS~"q.2 [-$Pk4hՃ7Gn o+.O O]/B뿽{7<3\x 2(eU,ܮ~G@LNUJ1pȎ; V T-m4NtE%<"><\l6_>wߺs7^*^.έ@@R<ϧH96m N7Q#؅d +I& zɍSOt=N#Ńҡz=^php xЀOh(y? vftuqY__h D)Ee}5 )lO+9'_prݼql>|kׯg_gqq$ x0y2([;ޖ v#LQfbAA#Pg# z̃55Gru8&c"!vwa4jni|TDN _Zr]T9w钸KZeyYPW@Nj'p $w.ظAN>& UkRY];"&aDVĕ н~t`s^h\~]^te:J)4-<1jLc?3apGL7Bs~h ̼~)Dj)a;3irpRTT:e8խ-)Uy 7 q88~ܥK܅ &++BT`TPiH;Tx)0UE>8zpF,CHqwRf6M C{l4B)_{{k8}[$8'nWyf榼p2\^&I˭ZP+@Gg_@~ fA?A?6Sᬛ{pHؓB)}i N~ ¼3jOS]Z /T;#g>`Gc8 4Ϝk뛛/mnnK.177GE;IӴ RSnsiJk0qGB+0p>+Ju*ziR: Q|mm uSYJJYv:^"t 6'=>^llFpĹu.QeI0 r9sZ#đѵRd@)Y|}Duf3PE?8Q#~JJA mV 5Dp׿^ݽww`:pee]=>\Z]2 DQdeё;{1@i֨<7̬BIw? @j\N'EQp6}Q[R*Si$ե%\x^xvN'n?H"`Z ͛.ݸŋvTU4e8Nxv#OB_ ,#T\&,Oe͑lUx֚g^~eo{ԟށ7nÿ xJ<1zs~dem-`eevMEE}hE޼z`H&ɕ2v`9~B|j$i9-&j$8&qCerk_*'y y̧;Feyq9ZZOZIٛotG)!;P@kmh2P6CCeҥ'Q©bzJVY++V_o6YqL}ugx,/ug>f xl…3++bie )){)݉l†pZkpx>J΄6>:(i7(L82| pyO֌Z-yEܽ[9ν_,G1gW67pyVVW|:t_#=?ZceQ<3qߩqm@W4ܖ$^א6vJ !JmS)a /7goܨ^l6;gg/|2+Ax[^_?^,..RVF:$)R|ݎ;W#0Œfh4Ga.O2y #I3oRuO5:WMs!=x>T*qKg}U`~|.O";O xsuW むE듕n aҌdoXz>dt(Am OYqsx|2 ӈsSW>m[GܿV e峄Ck31Ў@hP{k/kkᦔgcK-3Tx,^ha~gs,,.K$1#^`ܿ|X;k=SOI{+0 wO H+a(+_[s&Zg/Щw*Ð/|<[6j:KIm76ԅg~P>lPڨѡ`%)O#?SfWTzBJcn+WH}Vܛo h} NTS>7ڹx9sF.vi4hm]FToպd6ݸ 9PiJ>["~ҡn{ˏYw~>GB7|_A|ھ 9Z#ӡhEWշ hûg,.pN]wgjB-whm"{ӾW8e~|8,e??nDcZe+R,Q>Ul#ɧuХs+۪US(eqF&e/\u!7ũ +[\/./E* yO:{\ o pb23}p1-R%%\YA[vHt͹R8߮E  gr96j ᚟Y8Uҏ/}$WVXZZ" éiVY,Bœzz| LR%xE&(2yqN?#};mO4,<8L'ߔ| F+"Z\ڬUܹx/@k]}~j`NTOAe?tt bS-_wwG|ߺۢG|}RL(Nz؂؇K¶!>JqUOߏV~=8ju+˓բ}Uy&*5gal'*ڳ>="vJBg8o+78,("Kɇ9pHʈ,]8'|V9d#qo1|d{)![ yUfp:LWYV| ssWVXc MLH93특9*JQ:s#e+(w~Y`2>IPaHnT* l4D~á)lT8" 3t'W#߱g.Ҝ2U _wORN?Kw}.l8|yl'f!ٴ7nZOy;}wK|)!eК׾wvw[? ߸t5v$[ fѠRnޟO@GxE5VY*S@+@*YT*FڌVY \ W̺G#2kŐJ&_[QDX#CFys#;SscyaߕQ5]wxSauZ vCbbRۄ:ͥ`!e'ˮ!sjvW;6z(LyAhwZB֟kl'Z% X,Lcl0Ll-i| TfZ!Ƀ.pR@6PaX"O EzyN6s=E!0i/n( aZ*MsZxL_\өLP"+Yæoj H6Uo$uG,G6G.~<aH٤lpZ_88>WDV`Z)>Worl#F}oo!MtGjص\)w |R1y&2oɇdnjQ,2GtnޑxB $AZw LWNU͎&?E$8p_sTYf̐J a!,|"ܕ+W*Z`.;hl(Flƞ  U~ix|ytff;TD6QCtsz׳vw^BK)V*Fχ7d}mMĝaeH=7s27n /2'divs rdSYf瞺9Re^us?OO,#꧳I΍:Z(eι"`T^m?"ӓ֮Pp$t\M'Xhl84-fj^7 '--}w;I2Wj`[r*,=|X_~zS`/$ K:ztNvw ;Jd!%m= ^kއ#Xa/llIι牝ּr5Ogp0$cF@7MJe#cERLHaP|֬sw[ݡ8o1_#xX e``"03z46 Z $G#_}UϫoJ^z ekA-!y3.\ _hk8u!Ðxne emQ:OMK:=80StΌdTeҹv-QH{$DNSȰWl98ZEHIa(* XuާBE" ):$ ƹ if[{;S1oZh\Fj*ܹ}ɻ6z [p?,p!԰³}x>̿s/~񌐲.(j~9cd* Z1$̆C^GLϩ.U1[-jKD_ԅHVΩ4Tc9/ ((v$)D:0`|Eūe2q@G0e,Oi&fnn ȇcXM1o׾6G~1 `b dp|sy%/~q!>ssTDŽ*YQt0 88([7 Nl\hˠh:rF|M[_6վ+2ܥ$5(ax!ߞTaV8LS֯}x̅tvd[*MQI+l1BӹO0BLNb2ʛGo~kNWH )5yi\ʉ]&5iW`0uZ9`/PO?9ʹy}a=ЙmxfC%=к9t~8giR%"=`뱠m5-D`HHH1O*w|u|dGNz_{,( J)lX}UFnCx']DHp_%"OV}R)*[U٤ύ|t%9hGBf<ݿ}(]cc*=(B % 1B<2A|rv+wv4ݎȼ6L > i& )Mht$H,<-VjʓDZun٤ -~QZ9R4el=Mx܅דֵ;'VAwf_ɗ' +_Y|qXRY,އ FK{/ "uhb\(@k!tLGJH,*ϵ2m;WC$կ|N%GO&j5V p BxPg\'Pe"fV`iQ؀qgHBDqFCp>, s A5Z)ZMhm;-R(K,DB؆Ckc:Uf)=F,PMZ(UL*TӦ'S>G !823+Mɕ"gxLdAÊWVIB&(G>z4(''ߪsCfle]e hNVZ,$+e ^ ;Sj& XeF.%|Sʧ>!=9OS@ w Cyn;x~ZcAa2]L(dˣtN+(mZYKKzyc(_l՛gΈh;23^g8"Ϸ|Et>1{J kӚQLtfjd,r,6wm3~~4ך݂8&SdEj(UT/|&vu)~b,xZ= ϝyYZ0,?NؑYcFk |B =j ѪS(S8#XeaAfVwd}T%0tS}20>-|^t$6eDh;wG`/߀ߜ|4,flf4OJ !xl̪C2ǨSB rYL5uޒDsքP@~ k8 "lUt0(;nsqYgB*Qsxd 5126 +^zyo$+_V?wf{…Jl=Y1''׺/В| YG@i4Mu½V&L n~r昙8J,L6 BҏFAUf&&{{潏y=3v  >Ff޻M/XwThҥ߻љr:>ah a8$7 8o!+_m8sU.VOR>wji*!T yKͣstn+qm.woa@OR>tUJQV#cdP\]Xgox^_$Mz'ʁWq#gGk/3g[U%Q=^7WD"0C3MPQ/+!kx)BG &aN|fM70`)f*TYv7U|)C>1{DY`gi˗ʲ0T*>\?3{Z)-@AVۭ67E}uUȼٖF[[wvHm 07]s2=%s;Y}ʇ4*8KS==u+$IZ>N|0MJo00|?`7i iGT3۟6r۷}aAR(Z/Ll0hqR3NZ0nð^Q-jը.mL8!aJXNxӎ|D>(A)39NG#J`?! [IRniGe”6E"_v+9vr RQA@n`76R@VĝQ%kkR% `9"iF)Ǭ爗9vPQds}<|폊|.}T)v }Vf0I0< QN1:Z-cƱQ(2*x.4e;(>xCƻQnLWMsX&}.aIOR?b!yfIygp/&w"`7|N)Nd0!L|/c3 rB dHwF)0}eY;&39*ssXCyCZLnf^Qe|Uzp^OC^:D@;F1\8H[|eR~}!̍|ql6#ܓpqLjQGe?-ۖFdc5PH)E6cT)OZJM! i#ӽ"0ac9ܗ43#Qx[~C;-/c4LO|AHf|*%ṪE ÇY'"Mwp="` KBʂ G^!Qլ%PQeŬg[AOhN80!HCZowxkP}9[ w7,qǘʜ07{Bm PfL8 8736 Z"t?L @8&j4MCBKl42v!CӹHC;jL~k_K;;;;KKKm&8yT>s8I(*eHL cf Aj~&OxZ^S^7 5v:E:EI*M iq+`B>!1EfV-—f`y ԼP&O2|?_ (hGA!W>Ov%J̊ UsT`@EzpPh>a,j56rtdUhecIR>w!ͷX$a,c>$`{{{Qg<ah:̄a*8M6| z| PH)B1Q@ 7YQa9Y؁Zؚ""3A"@ؕmx>)W捴N!|%nבy3Q[c8nO4eǑO^ UY'9"|*|+c;K[% u0 Rv` +!бwөShaHXg7|4 U3ަ7zo9I^<_9^p֚0,^$s}G0kGOOyMU{6⓫ABl!$ Ns)ժJ:m,{ `ټeٿCGCGk/}=z㩉>foɎ"_O\fP>xB f)O>GTϯlqds:_g$l(Rfe9mE*y/Cя{H4_1HkoowwwfֶCpnWv+@gk:a Y:Q)-P%0dqszh /5 wa:+v"7gJe%%"(g)yo{;;<W)Xc ߾wecKJekI> gL2vc)g |AD#f?7Ad`V2 2]N?im$ }}7؇7j9ñ7+ KKKu2QBcmBRZ IDATWvs&aY6@y( HkdZ(*ZNTbF ZB ѹ}Ƀm5-\ܽ mS"V  )i;W0* 7ٗkMG!%m##4/m:HBLLDS0ORobA@!& K[ADW >91H ZkUڡi!bKIo =b=CyRPiM6FU,#2WDqLѠjQk$ Z["cܡaHw>[{{j4B9\"^}g've "*3L1|e2B Fov<EXHi]A(\8 ̝@+ G-ZޮO /m~f7+կ]zJ`= ~S0c^tu{{u:ԚMYF\!5Č@sO!*}=~S  ~R^Vl6ǹ7F,B#7YQA+IB!`B(r&V߾MK_Ukk0|of!o/~/<|e74t+'"hz4{=>d1 9[i9CkiVS 6]]^܆|<;ʲ&zݻ?#HmnD+C@@+d8o0ᏼ߫Z?]m4>86_q#.'\& 4ZTkB \v[V'¼ш۷9phn׹]&'pD*ݓC{tc.nCQAL;ڏ{}Cz&l9|GQǶΜsN +LL 4RI60cUSqojW{G(LWx{ѣG/2}5;Șbc&-`lٜ #̲S̬oΟA@;ܺC!G⭭,Q׉x{5Hl@k֦'w1r}utWsrc䒻=E]N`8A !`ÆeHlvXbp#mDB,PVڋ\אs}]oUOϱrKrmBTw]]z}}&ibA$J\[\L@Xcͦ+/ ݺE7xig畢&4|iUgɚ&>>6ѥZ{kL4Q@SoBBKt1,uZD.|!Зpx_Z;;rEL%_2npfwL1{ۿΖ0 ӕDJd3**9R2h yÐK!wGD&RX[U*X"\?_E)i<ٵ>@ר-Ф#FH}WM?-6<vAz=*_ o%x:{%dםdm3}CTOz挞ʼn"Ngی9H@.=-%pa833 xk/bWZN^O^W*nNx[|T9;KVò,l&" !7DddsKɵq_gEl_Wξha tF7xy<> ]aEˢ8?U(RD-)V2?Oڵ;>DFjo%%`6\>;$N~[\^[o/ضmSհSǧaضn0M8F=!ql{& PqRIK )u!H{^us5Ф+513U?M="}}4or,e{dүy332Fj8֩~3b;&@O()-#ݔDFCm|)?ڻ[wE@M! ;B*݋8 RfH,˚,0'CFDFnLhid1!(-/ľC׸ |m85T>RFE`=^4 ")J*yg^DQ#3>˸ݦlyx~:;Kaa&ez7`֍\p'&*P,Rױ,hI@h@X\o1١}[[[꒔&gSwo/^?5M,IV|t&eSJM|J)<|'IBmSéױgf&xhsΕ+Z?h;rM'XIOCA`ZJоsscc vpV2PÙ#WbR]aps[|;ipp!:* ΅݌HFR Fgn(1wٲ D"'_d׃XVO/ѽt^M;agk ^I-,ǀ <(V*VM*R6H!9a? U(|B(Y`B|>?LKK&1}@Ɂa %;~X`0h(*zKɐ}cX8~\OrT/^<a0dRlx4c8s>A躴o>%3?cш^p5RDLKr=òqΞ%73 lUaLВ :2nJ5ٝVG6xY OG?Jii `i0qJOݍ;:h4$R`ww](#G0 ]qgNSd.2tM1p1Je~頧EVZMGwGu vSE:Ф3 =CqоuK0L`g; Q|ҟ<%YՓԦ'"BLFDR.^^x3 + jji2_0xVc1?OX$?3vPVcus0d#s:hﮮrXy9fNF% AøѠ5L̀$d7dsf^nglӋ;sѣVVIU%QBGj.Y%q:qs{o}>ӀK/;N@o_g/>K*rSTM`B\.7=-qqb&50gp<4BD-T`ֶYv"sT(/,y֌J'!ȕJr]6SrZzU6<~S9~\FFAJ\Y(MjxxA']@4Yvej++̟:Eiyf.,q*q0Idx.uM.1`Ѕ?_5^Z[KN9<(aXju2x,aPTϕ%*+ UF8h9brHufGP8T**:ǩ>U zG^az еg*]h5!L$yG%}d!0MR Rb*} aLJҪR5!)R̟:8TVVtMY(|07';8!Zz!~C!ftvv4+ `ڽ|;{J@V+h~ J~mYs۶}:sDN PFԑIZmt?R-oE*%aYrNFZ^+U%]kbĺ]l$/&qmmyu7 ¯({I>˿tm5uόcsnnx,T*b|O$1Jkdd6; Rb%/.-)'*tD\*MB02 n5yj [-z[[477iRD됴<v.ύ<#뢀81 Ě&A'Rjr)T`6܄\Hv}'\jid&f>OV* k8.u!t{gM)u\_^k_~ӧUEWqOB\K*]7^r]{^18\(Pȗ8i8N0&ȤTdHa ZR@xPz0!3Y'IDATiph ^6q]pHiH)[ >~}x0~O +?s[x oQW\<|0>TǨ$Sd٣C]IITLF2Mf urZyqiR$V ]o0`1th{kmCX(U1. %J##B\>/|q0-]Hßd#.L+k ǔ'Sn6Ҷ]>qJU80ԶR rrQ ^m~&`p43Cȕ _"U aMS C Cئmۚnfr9=l{tKUn8HV /I/r](UlP# #~T`ބY xRr&9%0tGrmz1taVJ'qL^'ɤ8]gcH.đrn r,$0CV 8kM 桔$4r bEfyID)!285 /H+ \0x; P2 X&,P7nBSBn6(!I@&'{xSB'Fk1(>G/[DI*`΀,*8[.R_AQ 4bHEwIh (ݢdG:I:z :=>{$h IENDB`FRAMd{Z IHDRg- IDATx^yeI~ɳw߾VztWuWwO`mec;0a /#C8 ;!AC؄X̨g}ꪮzUzL=ᆳz{q='Of%?9;;)(:i@b|X`Ňmj@P@a $(e CA_'/`FM7ຂ+0k  7$ |Im(_N7a΃l l*=oT>%4_$0ASeUII=|*] I0#.zP`>V˰Pzmh֠ZFC A@"*Ð \"D)2$!cш4IXL4fYO ] {{][Kᎂ~;k,CE~Ї+!<[f (B3ժ^X𫭖Wͦ(ZaFP.jxQDPap*4>pH.5ߧvY&@z. {@a_v@DPƕeW`5hՂ`VVA5 \<KKZ-*QAhQ_.#@NQ@dF,qL3ߧ`wNvhvtIN!<Z U~ {o7s*DuV[rkaRirTj4 Q.f^'l6 *zT‹"0ď"(BBSTR ,ˁ̆Cdz!qC[]:ۣ~7Iہ}»#x)_?NZ&,|gi4-DMtܜXbvkgFUJ :A[ xgno{^+>M.(,eß? F_tN5h7Koo\S+?z*l+g%w#dMpkh]Leq1Ϗ"DjU{̔!#<?k5:vfj54 JEUXj;GŨd{BVσJGg?ysgÅwKŎXI|Kؕ.YzZՕr/ @'c8&IB uq^nq¯TR.S^X4;+0jo=葺;l˲]HN=QA9VܥK?uKkk [[X]_h033CZ\.v ʧg*Ε{A M'^OʌATRҳCq sVdd>~ӏ 'D~~[ЯՈh=,Ybxz7~}`% Mo)A߳z_pgW67+++\deujZR e<% \tĔҐylDŽsR垟JӱGks7n$Vʭ[{IpiރOS r⟸x+W7e^ݦR!O < GaJirvbjP@0|'a0[j+7o֖q267YZZlڄu#)JLL$OĵvZmg5y:k*Ukka /|vC7[Ÿ>nĻ acʕ /gugg^\xQMv>!cg2/MfQIi7jJmGY]*5TffD= źb^w-t?;gkeŋ WzW]㩧\.SV'TOJ=< fy8aʪdcwQN(S~s!D޻RYY47G}sҒX~m4{q<{ @U_ >nO M[gf/_֯]ԍ榸:333y-X;̈́YrS ~mVu^Irܜ$SZOaC^!fQ}7nPa ~_ ҕ+S<]zmn]\7wA_q<7 r}q SL)XYJc'\ߩ>ٳ*5ߧ|x!l%Ǯiom7o.mݸo^O?fhΚ bz9)neH94S,wj)5YYv,?<}~h%FJеhnj={{?ԳφO].}9666jx4Ms]5A/ص^OxzA+'ii*] RJ'@fbq~IwFREkyF߯h8- ^_xg77[[1??O^ϡtG(6&LoDŽGZڸc8 (s~9BvO3Mv3 @a" oQ|Ë?[CB#1l ڗoۗ{>sSׯ_g~~j @njF adקلvp(*!(4]}c<Ҏxه|҃51 |qE j> k{Di֡Y[^ KWڥKKŭ-.]R4MId\lY x\iq&؉qY@ݎ蘭LSiM;axæ_'[r"MD!~ buc/oݼyڕ׽KXZZj!$I|ɲSY@íGrN6-n7eZ.S=RB*ZA;90E)9Y/<\j?|_B)}=N~L;zQKfweVFoQA ߴWaM#³Y1[SF4+@8C s;cLIGxA͛!RʠwwŰcG1v3W~zme+\zjR8r_fԢh..A yΎsw9r6c)~8θYwbO 7횦φSGs\ᅞ" >9 Td8x啙>21l>]8Vqg._,.] Ah4"I2)e:Ab$!M#~+ 15T;Ώ2('q\OŠVZasLSd磭,=ixS&%0&L54w%%2+kkg~׿^޻{߷3CϬ\,abRT0p`2P_ mفPe#h)# sS:,fQ8ǵ1 &8FeIxBR^X`UVHGGw߻=% 6466g}ҍlnnn)$I`0}4BW a)d[/W``W;2B6 drl4B)Eum_Dxw۷{͉gp?^_嵵`kke&a[Bh[1BL ײ:}Jh}?$S/ߜVAya"KSok_Oˇ3n}kvX7&x8&5^PQSB׌A+_$xWcmk2M E{%!&I_Q9;EISab/ K<#HĿۍnj;g\\]/^Z\^ >YMV$SI?P2O©23عЁo"N1Vfar+|spೀZBF٧ C+~3of(_gw/_nmk.,ш~h4P? qJw*k,Ri<͊VS EoL$8&1ՌNd Et'|֏{>Q>wҜTZei\Λo7//.iGtSl77F… b~~r<DtbX'Y?~)uae,EJőw _'D8=݈(wwݞYxLs~֭_~)$eJD6 VVx%pevn\xWV~lyc#|DWh4+(uY~Ɔw˃BM1GUhNMcUĵ'b42(f]/n'T4bqO9q6NN"){Mg G su;Oȃb什LZҪs2MWtZ.*U]4N3+Ugq yKe oI1B5lyeff2u櫘{p,|J{ǹ[^qRgHJOXS]ZbEqyvֿ.DueARgfKKb~~RDe}n%<6-q຦@*Rz@LeNq1ƤRWT#j9Q>>_LYwpίNe6ljJRR_]eu}J%"x=iv&?#skkm-,xK,,,P*&Y\U>k %i~s 6OKcu<1̌S\SFc)gKY3](É7IzZ&?f8biT+*gEݦZ+ &O43EJ+5w7XR=j/X /C>!hf_7YبÿWd0}<8NLŽ777G^կQiV\7M& qԔ9v5xJVU]G:~J#3KHs\^fefXo/bҎU-fVV~9;6m133CTʳ\~rE;i]E A@fK%z$P̅Ml0eLsJ!C)Jע~#R'LQ?ߞj5JR>s}5BNZd2nR`8Ri#M3C. 2pHj=@p,l!AEhkhMs4Pc=;pd.9aߦ2qךU@`fmU08iJx*k5*T oZ~&m{% `ZjQT@;-@D-nvXg{hoiO$me!ba`@~ S UQD mXq&`4p@zST3qK /("(Zb& ,u2ܵk>;[^~>aa0bkJ) dBhҔ'9Xy9V^Ͷ#LOݴ'ըW^߿|n]}Sl4xVT*JLhN=,|3;DuLeig[D03xt#D]Iǟ9[STF#N'?U\+03>mdƜast B-f!ΏmwPu QuN93EzRܻV>ɦ)Y1qnOcJAä20t@ ۚk>d^) CuRIAM)VQd c20`oH@wg?AkG S6-,26;63eFrB*St]m9|>"lVdJ Sg$&l43B˺i(_[rY?vP84*=Q؅u/[)`@#mR4(}Ǚ6Ye4ABX_IPE*H{=ӽsߦRѠu"A_. VE<<!H}b\[YV'f iIOdg˕qY6^걀2MuJʼ>ADE"vsO8sRD:֔RZ;h')YQGbZ)BWXQ4`@ dr(nE`Fmׄ3ݏRN >&V#0e5eW_v߃CN/~8T(XN< o/. ϫza66"G^ ( JI#gUfʨdR'd_{27i`k@Q( E\`l;`-UT66jzH$kuĔѼ("98;&ohooq-z,^G![`RSq ~lFdʜrq hwlۢI~ 2^2ei!nlL{b|@*}nù6m_8̺+׀ ^m֊s-[8s4e_ae 'c?%_ӑXX( UlχLtSGYy\w(Ci+a;ǵ)t{B v@WB"Q;N-֦_aH0 Ss-&!s͵hblRB 2v38omxAYT eߖK];~]$ (U68KXӀao P$@1 rDA:m9-̴^.s2& !qk5Ri;Q(^XL㯁NI4`Y%TLLJCef}Yˈq)aTjpg&<ݏ-TJ2)|RH&հBUOs(0Į獿[b "uJ33( MR78ќ2XV*jEN"`y9P&}ؠ\ S=-)#_W߀DžoBGB2gIH ᄬ,Nj5ϛlxm@q)zieBfS4`7֜ZE/gfE5ezfF#Rk[Ьe=W s" Ǥ|քx͹@zI tBU-"ӶcEsg~M\kJgCHOHi BPK/]+kk|ķ|g? /,܅ 3kvTw$|Ei" Nx{7L[wZif݋5ϛ|o!4e(yD67oVw6G~߂oM>~ #F\]m޸GJ`! HG6 *hU/WC\1\ dGL3E d'}K1J[IcN[ uٶ@\&QYF4aN6EAg>Sy|$_o׋)_RWjʏ?lsRPRd>!Cґ~c "oslo}e N4UC $I I$ߊ`!(.';iqv܄Y f ^ժ+Г~ t!9=aտ?{K_=yz]淶ZW.^D ;~&n<]~5kfU?= JJ%}?4j]/- >+++ ̶L0#1&|_ܴ(LgO~ Tf4Id /8j®E`Jo0֎V}n53s=R%VQiOge#ޝ;5AFT4?/W+w:Qײ(o'|  j6ZfSV}< ><$><q8!ALP.}^+.YB 2 *NC'{dO0 v8WqWsXP\(uw^ݏ+#D9 M >9'5{yؓ~DJnz>+SGh#cFQ>AH 9)`,H=߼ @)J6HIPLO J3{'NGϒk4t0-IpyZ42f瓣l|Lժ>?ϼ@gOS?aBLg:zeY gpS)F?;pRJ@P)=y> fQ QA~ v;@:mۚ#]LH:/dY0 ź6vZrhJz`X/ Hu8n =挃H UZmc}K47;N;fFx4ˁEWδi~N>bBh/Ɵ77zfl&ij!tzĝ{e\l={hԣ)0)Q{J̵WR>@kft_Gӡ/LU{{i3 *81Mw݊p]4 7EWya8Wҟgv\뚱Q*;) C%@. ͫ~Gu*M',n])jUy;M<zzҠUH¤#J)pk4>7h4lsx\"|E\Iۮx= "4|&EP. JT׶!HOrvL?ZEf,|5+B@1w?[H.~oƻ֗1{x`0?eͅV>x ' Bo|@7NT2]-<|:Id PIO9BCC`Xx ![^**4,3SzmA2to)|/h@z=o8 J68 .i~]]++AOx}u-xy$>aZ%HSLH,F3_(ъ(S=~n0Nߋ"Z^P6˅IW4TT[pZ?_~#퀾Bq)y-:oO\%TPLbyQDXm!H C^ߨ0 CzUlj&k WZ/jl$D!!)LaK^1},.sR^t}=/,q>(J$kKnj]tȼյcL~ zF#|'t0.E*e۵b|`1>ٲӟBJd (blWR:GZ_ң}S *]ִ 0$yӾ4OIQ̽LzĽNGI +]ۻyޣ^2FDQ41.hqmצdy*K.۲2J!TR&۾iα@J!#[G6۾ⵊ VӔtՉ ߓ|@XŽ]AցtЙ gX׳(zn`R ȅTuߵ+ge@1ϬhW8)ʲ|L/OZR^+)Bu!tLx;͚&2 QEu싡~-<u4efOho109)ɵ/awwt]F@Uk.Dq݋NicpMS>> zpcGX 4d: #VgfIJT2u&?y=#IcF~invBJTtԽ4obk'=Rj(!ĉeBצWt5|8.'B!DA l(W.^L@2Cr .f!뱃6QL6n V-G@QRI󨭯S;;y&C3ɪa>ք~&m]&0JThL*|tsLt4L0 LXk2|ߢyWx,bA_Ws}ĩ楔iPp؏aB蚿c<ՅR ک˗_~>\8nsPVr6;6 M\2yAƽ{{%IT_%^Z! <e>kȠkH]!3StQD}uk׈mZ ڰf ;;ݮQfSA}:Mcq0&5$qU#7!L~ν{޽a4_ ,sT7NviA@EG,Z4}4=OFsxxoo'loϲd0h%/j4XrЊf!aSO4M{W*鸘!r-v|GtM'Rpʦ)Y"\&"ʵFJ_Ab`ȋ sV:lχĽ=8P pE;/޿Uk50T#JIbo|Ei=#MS.||{;fR8H믓&4*,6<88nM0^2M?Jqp^~wUvOWJ|4=t@ۥyU̴ZTuiJT(qp|&|Ӹne xͻav_,-ڙ{kwggTRT7Fi@ߓ)%{{{ܺu۷os]ۅ06H2ʓ|K)n+n Bw@#Mܡ/2յ5Y6QN{=zw0|w~Wy_奇CO=D@(%nzÇ f"J%WR -xJ馮QKwgz=@ևͲgv޽a5Mv^5̂Tܶ4siʃַoݻwwkWZU,RCwȧ*=a$M}5֘{E)Qwa旿/ f!:Æ=tdY)IFppHX.kPB+#P0DbGxS)އw:/9 )7?UռNC'W|yEss N[R$I`0`0x+ARɉrTT5;w`n$ш;׹}nc MϽ{M 22=۷iFTm*G7v:|{!]tZ_WQ0#;b4.B &+UT/hRj54MfEsJUD j3K}GLƹMRpmFzM%]q_䛿6_Vbdr\(1Tq :`,6EOel߹s_@Ö9vA]}W.b\u:?j0 sBRT0k.gY,|rYFfʠ"ocyU;KrJl# $  Hā8 NX q| 91ACĊ%l!*^:^Opjwɵ =]z! DJ\[Z@ "`XKfS$ oܠu"/R4䙆@o=4ld3Odyl[K"1opH-C!@-rbgjq>|!_p-t9Bc²D.'¥im~<[lQ>v+WoNۥ)P|plycDž`I)ri@D)D.3^3Q׿?c^>wFhhH"c h'Gp²857ǃ<ĉere)AJÈ?,(<(hZyVFŋ/%I_?sZkGVr\ZRFe`WӪԐN7(Z-677|2qo7U !`vuT1t8/#!a2 ƍ\tׯ$ ;15|}=A@Fz%JWAU#hc/Q1[[#W/ǽW^{!Z@8xM>#%\'yvӧ*N} <1lq3ee۸33.U:Rp'BL²0tU&cowD@8ˠxN&u!1eQ(V9qz=!A!RJҜF\Xi8&f)hJbr.G%pW&ageu1 v.\`jtx}w-" #cc!llnp8/XVfo6RPZ} KRNs0v>}Wt&NI=7CP~|רBr?|捑~ER(P!W`eL]*:z>Cc |J@ٲ&Ai!wd Ux vvh|z)ģqjU"6I fqv1N."y5*|[BS.6]εs:ZM_| ,ZochR٣9~?<쳌m&1cn~{6;Kqa&~݋Y{%}9<ȝCoX((58 Z',L:8fK )MXSwo7ϟ?7Mf4<9m$J>$"<ϣnyޞ`tUTCƣM:.jq@y 4gEN,,ퟆB;A`ȣcyr<~,ȏ0CiJ;Ig`Oրe27;7GV) dux$a̹4U!V)hu.tحVD Iq<2mpy<WpmwX{{ɟmJ':ΐ],' fg9vZ- (Tͯ~θݦ[nm.Cv/@߅e(|9Jjf{-2Hnw,>‘g)#ӔA@ocͯ֋/>`@ :mlhI>}K{xqxzvqgguRk% Lb~fİdgmM1K Xx;+az٭bJRRJLHW(&ɴ;~x<> Ri-՞8wW!Ճ17:Oe1؞S;pu` mGr}ai1=~I0Egvvw2ICz.Ǖ R\GLKr ²<8ܙ3gf}ƞZeF-k+G4e=\cu`ye8+>~8%=g$AVkK.G\y!(Őt9h)CSm/Ybt$*r xʲ897Ǒ'{!'ON*TN.[@6|YSOԎ'_ $2  {Rɶ3#<;>ʃ'tV²tZMD0B'U$ n6\d|.;ƻ^W8NJHO 8X,R(p]w'ضMĉRHxa~aD-hU[\eץQ*1Lmi^g5TGA\f)d ͠JǏ|,cp*d4Y^2y8xL V*Ͳ,-/S_YaIyfIv@6N;7a2fH&˸ۥ.]ΛIt;{F kkmuN;ҲZ6qD$x݄gZȑ#7^5.:23BTK%**WWqIR0)J\Hun^`0 <x x)u]Eܤ$GW(]jJѠq;3CqqQ(o}tӥ+qC$1N.o& .Y z/!nm'R-"M-۲y4 DJ);!d\fyy|>Oј%[A [_&ũe)>FPPJ 33 z$tORòTX 8y\P)UG-矧Bޘ nf:Yz1>S&lȲte/puܙKK:33{J DеʣV:뻻J%W`؅F`vxO ZQBg[(ROmbjTW9vf:%ZeD*X<}cc7JҔ$ztQeAj5fy f< <ѳg=sfZweQZX MPKV^0Msʾa9xR@Iwgáeg3x}_ 4}$ e!I4qtG.CD)m= O݁?yLY](Pq۫ҽUHO\~o8[*I懃G#>333e*;r8CJ!JNw(q2IPeb[a9L7 f kFʆ}=$oz M10߄~I6 lZE90籰H^G$# EJm#T*dT|7LPi+4 Rڛ2 <4 4v^nKkQA5T&l{|3)^‹3O;ha$IT*q<~(i \$8"ᔜ"'L퓌ӄS:hm OgP:މ(1("a'yǨףڃX^?K?^!VyɆ:7eJ0 EVhLTHAVIH@{EC;$h R--!SgӒļ|H=[fj7L#}|v:]nh$aA./u/q`7h>]TZmgg~vvEfgg#qmp8KjM_pbÑ])wBDCQHJ=3#ī ld0hiz\It$~Klv:[ʲ~/F_dV$Q$dSsq$))]^F FVeQpH Z-y UHZ_& V5duvt~?s08lM_/:s_}I1s ZW XTؚmCP\/ɹ.ykn2eiV01!ʩQx1}̶ cF!^NzJ5ԎE8^DDw7T⩟d?\](W1m #ʮ+J+b| Bb; ,D֠'/l'o Ĕ'36Ҷ]IF(TA( j[)@zE,ˋ?P/D|q CEȗP 5pel[,K,Kl\.h˦1`LGIIg]rS$$qLzܘRTRk/}b.E ߌ]Hp/ 6|ԁa0S ".Xet2tBٲٶ, qX1QJB(IHҏi:5}t Iz p.vW|n[_x `Ղ3<;p<8.9MB+mtMQ?H"UT@ C K"]pNŸI%   ҠeOXhâ 68٣۔Nw@% SHR==)N k (g+[DY&`΂ ,*8[nR/EG,4'꣧-tQ+tN  =}>..'rDz&<~=IENDB`FRAMd{Z IHDRg- IDATx^y%I~wz9⊻&w+Z"EXJ,&m0,X$Ȧ  D؀mђ?xe /ijIK,wgwfw瞞wyE8^|u1ӻȪȈ| }Fa6p\`jP@@p@/z {p>02.N;y<`J9lQ"KyX@T0~o3]F8σS59 O(p`wAHk1p2@vs/>"P _kY^βopm,ǁlr` s$AEq "aȃ$a8NI x8JQ莀~Oxw|9nm lM  pb̏eJ[a Su˲OkͦW*ԟ^LJNPyp Pׅσ:NrIxh8D<!t:|ncxp;;;VW,>BZxn}3ƹ%M+_mT*QP FjŅ*u8R N`.,m?CMcQ$c$a} mm2١ [-] :> q\FQ$Cc=3! TBKJ\Y\OK% f2Jr߉sUpEpE82|v+u]Pǁ庠 b  g пrq7}拉5jaWu־mv< B?&r&bOG&>;;޿owkػ~w $Q[=Q}&tj1JA!4[+ˡ5ݺ]zqo^{81>r|a;鸟f(p?T~`ܹ+s 5kaij< "^_Da ' P, `IJ`>,σS.#EhHF#;{͛o/Ǘo׀ W詶oW[֧ ?XY_ZQ_Z^&Y]["VVVPV177q3 {A)!V.U֧ňeX.yyEVwuE07PZ݃5E|f <ǁߎ߹ LS `pGjZՍ\}~//j"2eY cRIT9cz<׶Q&gok׬Np;XԲ9zQX:sp,-/cqi sssdðm۠"7n@(<Z X`ΗW_~٫]ZZ €9p܋P?s擫‚NzjR{V->~_T̙\Z[+xgΞVVV ˲dn\?qg`f㉧Yvf@wʊ ㇯}pS݂VwnC2`}7}|k 4Zs~ c|Ƈn z .&VWWQVu- LN, #Ym}rQ}.G6 9砶-.ev؄R{Mrc<>56t~ɬ|ܹ|s΅g綷u0kl78|ucnC;OM96Oh-P!V;s[/ʹȅs.\Hrkkk( 185}{mnGa 'B1fe:0s0SggͰH}*R JE n؎ $'[֪k.Qv:.I75N;dZ4ІeSs2M+<OHG? لlZx\]{{[P}0ۖٳgQVa۶v @E2ƘDM FQ8232G,?\"JPX tcq zuyc .J/^<5ppOonueZq10xr08 ny~&U!MTj!^Z};_=%` (ͭs]8{666Py(h4aQJLgVJt:4C!*ch ˂/C_YK/1p۹yzmd* k~ʊEe8+ܧ@S d25\+ ]L)S$ٲJcONKl­T1]zUrӱVq \C5?[̭U9mI7 CG?(tԌ|Q*{Va@rp?D=e]M3=Nh|zqk?[ܴWױz 0d)qJȹ=+Spe4=aRLWU#PYM"MȦpj#)?pC}ß G+9lGQ:{mܿw:8DthYO,IрyS=aNU 4'=Ϙh#LD+lv8\l`LgGiDt#K0D{:u- >u<2I)_[>} 1( ,ayZ 5,- `-߹DvZϜ.[S]mA芇2t-}^QMLfl^!'/sL<[ML;u1QSSʗg_^/gl2  s.@(EJg޽ی?N6x\z'jFC, P\AlSR,eoW6&33˦Hš~I 35;MЋ](uX,mfs簰M=>Iqvbqg/l&$I0u֫MVZ MfÄgcVnJ餙xU\(С #|1E^Kf/TA/O)HC0BVCu{pHnʭ^22a;RecoӅEj5 ض=`V̄(K:V~)E4ڠcǩ&!S=RJM 2afSI>uW)d+v*ΞER[Yq+\ٳc־5't$ B`ϛv7ݲTfBhfzŒpOMʦ+tF >YlWLX(ctx ʞa <[bgΐzݺH_~tK|H;1SP!%4 ݙe>.T>R0ihMDֆes+%e,b3wG]yYv2wέ|lE4Mض=5*C廬2JbM?㓘(YTֱƏ)$ l6Aң|L5r:J?$Ŋ ` ll`G3?+:@r+9?O*BsfQL;e|R3 qD$lyF袃|)`y޴<* 61p6iCJ yhlRUKKP"8ʫ,-yY6X\y+xqyFr\Hl31k,;}(rɮq/mJx=ʗL륁RxU<_3,DŽWpU.^Ĩղ>2i;6j۪j@I6B$#+4(0 *%ɇ.n TLQeY^YF(2ltyeE:{U&JRx<OX|"é01dű(9UT ,/O~ĴTMV~\;ZTUr9*cLtU.mܕw49iebA* "PМz&Df$),25>H@" 8 bTQ|\9]iʿ>DjSS>3 N݇q}NlI’Ϸ:ZaO{fX]\\7WR" ru{T{M=% `DQx$ڿ @ $ z+Բ:fu| 0i2!e=  1yn*4V$  |**p.xU|T=WPTP(h竲4@O1@*!xs-K(4cPFHc!u!y6"L#2ەe,4<ʧKB1Lx7nOYWɗaW_u+v`ZfX*B\.xո?@e gq @.7 7) EF"ĒxX{.3Tgu8}uaCH,K@+(ESI"pFv6ZS 4URKѩ:N#q[s$H+J˰}fӚs]Z p'2P*j+2|߇8⦘YfN I=.SeH$ Căh~`< (R0IEd}6*U y)ܔt^0ﱊ'[bKua *RuR/O~ ΟzPQ,aYpnzyTtxB(H8,$!"ʅ<z=QSYJMʌ[΁hRi C!BzN)u " Hb9Eg|Zy ²X6HXhx"Nޣztø%X![(}ZC3,tHȮ|3iYvR36LIx8੖|? RPn  6ˢHǟ+LVaT<\N:|R ojPZ1 E.`a5j3R)U&\ꅦ XDX$ȵ9,W+y/ j&i0GY:N 9I;DPfêW2b8乜h"˒hD$ Ra$ P5e҃)* ,,BMpLfxJ!,&*N q#l\^rN9'_,6swr98 JP/vbftӆ?5 p( I"@)ˉfBN j5tÙ堢Y)e;[),S0%d8D$ú*@, iKrYR^a+KBHdp+uѦU*:Bh$ʂUB$ va302a#Α}DtkK,.% D*`h^bd`'5d2$jxHus Is>i OfE/m#W.PmX&@}8^%Iz/"@\Tn'Q,YlGx4қj0(@)m)V*p+"YQPt;I*yXC6D財NP4r }Ǚ@R= yߤnnd׆_R%Lf<Hïw>0 $5\Thp[es6P,}<sK,,4ys? :NU(@꼒b g"Bz|^(_bl4NCvv`pv@,Kql: 4CO T@˲z?f@TiG;!D17UG# F6|N(~2Bu`߾#\nʙ3}.a TQáO§*!B8 *W LNe Xd؟Im2NN(ϩ?/X@"MiΘ,عl%6P9ܧnooyەe)@Gf(%K^~?B>8>QԲD{rNbqw?x[oEv)r9R՜[^Y\k.Qe RI@]% bo*oŢ'FRMX=e:"ӄűꦠV'R5?L8F,ՏǓ6Irjhy8K=qU;ttVEW |[*ˣq\ܨrrMQ@j(TU=qWڶm7 ufdLVYvM,w"4A ]l#yڵ;ﰛQsxψvE@'~10۷/\QX[[|&:ˑb 0 ĤABbY0ڗTX]'evOL+uOb, !R\6PTZm¤$V-)?l@0ܳNb'\q64N\F,h0ݝvMnݓ§tpѽVk~U^5>dL,+#DPNAJrtS ٷ>''dIu*2&Dwc:S^{B,r PY7]3-\:Y6ϔ"[M&2 *(˾,I;Ip~/I,޷/Q5vY$ lB@ʾUUCgw( y UVTe:U٘ +=D4uQ]^b @ YĄ[:,G5JH&N*JE!$ 1cqe$Y x3QĒ0RWexj] R)Ecg14Ux>]xbF(%)MK !ngmʲs"؟jr)FeԲ8''@Baǜ% qLL|&9SA"_S:1 "d ,g,Zg2Uյ*N gh !F+- qqaVQqfdC&X-hPDZeDq+nXN>O8:K)!b"OOiR='d|`LҪ)ÄO)QPяX "$!diT# 0aI72B+^ZǹrPfJO |Dm.VQ]81l19%Zbq'#rJ&<#r?DV0M̲J`2%uL=@DyZ)sED!ŒfMYZ<-mO:>!eaPPǁS."]j6kV,!t\b[.\ IJW5u(A@0 P"nyT6>&_'|!x3STEQ4KrX(-}ma#ǎ3s@􄀊HDbʏVF0Ʊ n|* 25;"đc|EiJ0%@5ބ +N7+L),Ya  E([~2q Ҿsw>x}/p,R%1R@2 G#A9 j$CR6.!;t _@>Y`#3~I'yV3SIwԦuͬc@7eF XtwpE$AoڹV^|1|z1ssԅ2gFTB>ݫ=W9E{=^q VL0#IkJT/K>2_ڈlzQFH☏o(ڍGQD4XiQp8,}ݥ65A$@а>bz[.иrōeۗܽ W_COW,gjcsRΕ-j"F#ݮPPg,RS>u̍lI*ikS0I3`WgTjKzS gƝ?ɱ.u\N'4cj)yh~뷺ܜ[\^o~<:2(\;]ͅ /+'V.'`C|~` *!IƘȶg۰\13NOuqvn< Y$ˢNdm>ueb{PNa{=d{"fB`{luځ ,eKgn)#x!:yE,!pO Faj)4ń2 )wiQi@վHG­t1@óBV*pJ%꯬PHC7 I#eTdOzbJ7u1{L49%dd|Tɗ=1# |Vd[aa %*)_Zf7ä:8m#Layv>?U> @ C]1KTeB3GH$GCƌ}5 B8(4"+ 16~iQiK#FkĨ` sq!E-tVV@/Am[P*%Ǻ9hۢ1#$Q l9\)'֤QٗV</ ߇|t-68$ aGaF'lwLc0.O@- H,UT$ 6Z[*rb`(/z"\Fe0yGb>BAOΗyCibIbbnA1N<`V~0"TٰiWnΙ,?G-O$N bY$pxj?1@DI4 vaÕ5c*k DdSˑ3j(lbYHՔPX=%OSKa)ME(B8`b7L706FD)J`Yʗu~ c$i3Co>m#U8x85cTj8S4L:s.}co q<]dm؞'qQIp|_,dFS>5T5!Q[|=i.GI]d]'`<2Id&0$Y~MMKǝB+e7)bmcāx @CC-*'V5cƦ!ZټBe?%o<#D.*Fx w_V:a4t)JXeɴ鍒CFs9$\E;@E9 Dd GoQ*XzfT f+m 0vqs>v{q0>7`0%ـ nfkulZ:YJS# 1'l>8h$B|\3O%\NXJ,cr7Mu#DD1ZgǯٳVլ7dL= OJY7)J̹ ŠPĢ XDŽ *zD^Q 7\9{Q*}Pc"8bը+F&(+$Da+2 |RQNatL`8|~p8D i8̄71niMKS47JBrX{"FX'Yh.'>&ӰʈLRQbQsXtZ{OɊ&;T >o1@jL#VN eE"!8TovXD)*{ H+u#ZLP\"jjIK|^qX#H1@JLVvdvӢ|䳡h .o1/sfm& p n1 4TΧǦeMT*.7,|3QWe/.rAPHŷ-G U@J"! B,1Y-+mؾ/ǰeW 吸 6Sp0(l8e3%J~h9l{xiJM2mF9'?Na'ަ=u'WV.XԕBdפ a4e} HJY$)/ŲS|xd8`qqZLOJ2o_ |#LԾ WdMq7spsnL$t`L N0Tű++WYv|,E|\ d}__or:~џBޏaB#g* tQ6X,sXjXRKJ+]^QeD\ʠ|1Y3`pOu7PxhH#D4TE_9'+&(}jx!Zja1Mv$o_v{s^;:rS_K2!To`[0 ʻG+_v>r*;VIܲ@S~z`%0vc- IDAT0Hbo.XT:ؤY4Y2í TԆ3 $\/#Hž2 Ub6FH`Xm9bܠ lYl*؍Pgb{;@0~t0ӎF/u:~muC- u"b0lhzhZzMioWۮ׫"Hoo \a9c PnN> `{ʲrz&| Br m}# 26 q T8F \σ x2\N)*w> UC|PF8N~-.m'_B_wZ}p@B #JLt/ [pRq~{awwwŃʢ\A9nFs 3['ݑLn< LJKZM6A ]\vqի+ƽv}`Ae~>>ʝ "8OEJ%/c0bu m$Itش@paW9G>GXߏSJ12˲TchZz*n޼;wL@Nc0H"88hjtWPc$o/<++"1DԜ),ăoc}x+_1BG: pCG܃h6yTeTQj6Z*8;~} pHo'XY{~8-˨jUCe ڲ<1vwwo6ܹ]a80k.ZPWϣ-.(QMBP\YK/?Hu]Nkװ[meLLAtK߇ SIsԢkQ..plAqk]_`g_;^zR釽Bv] CR>58m&$qĬ `EQhht*.. s0.11۷d4_RdQ޾ۯm\0?1Rs*E4m,@ϷZpoD-jjE%zLwܽA/O ^lfc n(Is6t:X]_GVã9jAn ;N _v?i:q9U!1!3̈́$Y<zA\.c<*!σR˸- %.BB"a!FWE/vѿu {oWwwU@׀hZb `MFBB,-' 1p Bu >6eC! D(ܨm#í^!k٩d`0Ž}jI)VDV6}ܿnݻwV²,j J%:H~h# m0F;XInUuwu gCR(Y%#YIep/lC8bp'c$,HDE2%g{{Wwuíp#?Ps砫#<H}`1 _bJDK/q+Wt9xr/Gר0[-Фx3gcc7np](BJIXff8{,HGM ,D$ncQZgoEhښN+ɕJLn* 3ߛTb&@#cyЇ;G\ϳ1vp2@WJ<0Mz+ !qEa:zl RQs÷D@h8ؠ^&&F˲raa ĺ8O.x|` .%eY r\VPd&c֔r.G7 H5M@ػvi}*9ov-twhN}ɘWM6M]-P@)E4, V\Svu A~ۃ"N-#]ElEgwaa'hQ ||ܻpOիQZRRJ2B!3M3Iv/囇8Cc82L<]F#5sbBR)]dsv Jcrǘ4d3)@pSJnݾ}60dR7ԁǁ 0䈺Œ%ˢU,R^[R`6vAuqƭ[&;?/$>I7˫ ;1 w/}x^r9d0 r9;qrRR #|p 4mjJX`B8%J ur5Ф 4qbzT1:"2R =njvK ʕ #J@^'W"HJgD x79fXPʆ J !xS~T/4Srۇ?ǷE@w0m!. kBU݋8MRHgH,ʶ"%t:뱿h4R :KKK4MJR:gO*I 8V ʷ 'e !}mB_R oORlRTm[+i"DR"Vʼn꩸}F=(&bsKK%CdI0ȣ.r<}2~X|q8E= TjX2f}~g{]Eqt!,-4U6BkF$%H!{{ܜN6 =69V@_xOv~zRQ|],3ELYfճgMy7l#m%1n[_WWcy|{7[B@n^)X(JY #]PTgwxK<1tzDqa}}\.ǭ<۽A_%R90L9J"Zu.>ҙ3z=v*~!U:iݧOsh=  CTyᙽ}j/8 }6[džREWyWr=òϲxY={^Xza=Ft[J֖MU~w e|O_Rφq|\E[cՂ6fJs^x|A.^0 H)ydcL/:0reȩƋd>!x"g_|ٳӪTX)0z#WWygE:pqB : nЉc65v+f# ^VBgQ^YD^xʤȆ\&mqmµ!hѷ]?{OϴN[HCR,8F|h8ٺ@u]QJވ3rEd>@DzJ9S>M>I.0,K6BPQ1ocL 3Pk#49'oRAiNeN>4 C:}b֥3!B+>xP\ x&|:O-% +׮sReO8BdQ<sg00RQhyt: C L1QJ:2nѪ8p0x`iN\LTPFh?hpr{ `#h2h믟<^`?*{=&{{tF#:hYJl/}攗fO@+(yjy~*e`dLiĆDp X3 /,py4 +yN}6 6; \,='_|ٳU0S Aɜwȇ1ۥYIa';ҀD"(b3UvAmA8o&m! h0 mRc0#M m8!/4MZΝc:=hc? MdTz >èkVqE@~VU*JmevYS*GA\jquٖ2BKQC|TgY|3X 2 Tc4<3PFdrp[xxm}=>wį۶|IðjZ Jk ,aP9u;Oy?&5mm!BH >яb7YR"dcJR( W,R]X`e06eW|XxSOQ:qB/%*֌\Ooo{fU!yJ"dƧj:scQ9y^w&O! ]{&X1YKJJqGwQ5_Som$ 흝i1R|BıapVḘ|>m!2yZVvܔt[Tok.2Wpy iƙ3 +QU˗aE* Fr)&CN؋/R^[# .V/..S<+|I^~iUv]S^YL*0m[3QPRf=L*O&L:l[A݂q^um% %B5eܩ^J~[P@Jݡ4M"KKKTU_xm)Lu vX Bg/+cDRҥ*9.`^ը/.rbcfCGVW9}2͋geւ@ﯔο+(--! fz/m]%+_Esʁf9)U/RީYǺIt창+A&D=?|zL}oM}# !8uCbHEOh6R)v}b'Q0Y&aY[fi=NxF8wʚ"nNmӜ~Yy{?$!}3Mr\JI}3  VJWcy*^G0 `w=u5 O<;c! N?o?cfo BEb:f8Rax !a&R  bnQFp1#3/Y>sbcOhd S ,DI{ #gx*!J㐚Y`8:iäc=ף(ׅz' |kktQ_ AY]]E# N Ȫ/)]I%D@&J )何OB"k>XMum*FX<|G07&R>bh:% #<|anӾ}>G#~{Bt­N(Ur`rxRz:R>+5KnHqX_R!Dǚ*hP I }9 _z]JL=IV%[F]l.n;n˨aowWu]u-+ ~$<x_:95u/'saadB٤lRV ҩt&UTREPR{*_ueDr"ևym8[dB亚xNmڎ#q qOG[N~767$3x:^uQ@EƬBZy" qp0c_F7zY(Ph4wеU!8hD42qYWJ݁#~P p֭/O ÿhq< w2a8R)T*,:rX?O~5!KFW"ԷЋ{ ĉM[C$vm1-CЁ~'$N~~1_O&K qXZ^h,!Ut0%|ɧR'QFKITNyXʧ{ɀ}!}ݍuu3aﳿǖqG)Ն ;|. 燊G7?XZz> gN`2w}?SJσ&Ǵzxn7_Yk~w8.V*-6Mi6,,,h4 MbRNjT\|)A+ۉC.EЙ.j=o>nz]ڃ"PiL|/!zIva_L&x8 u@x)zbH9)FAPGL0Lbz+_JyIqdh8#AJIa !f~e#}M F8Hz12t8jvǷ!C0;|&t#G; tq:D۽vr"&jzNTZR(pAP$|A < !hT-E! ZEt0!SEIrh$^\L&>hqz{R6#N݇_w>rx bߟl=QPNJjDVcaqZFT*E Sľu%&a̪o. 13: 9}t)hR&$V \hd0N'j1U5Lqss鵅:ᓓѨXVEJe&ndF2&w1y\NW0t^HCΛ8H,2}/Ԏ |?u 锑)' e[E&0IDAT GxE~}7wSlwmLk0~\/WR$:#jP̆eErM>͵%S2v:ľk='##Jʹ!ܦK%H|;o:e2!(b]PcXSތtI?.Qx0ō|l~OVbre=AixV (6mm X$_(P gۘBB <MXib}ØdzJfJ)E%D }CrجV0̒iaait%!0MLysHg`%&7N(ԕ] Si+OJ5mV&'+oAEG)@>f|ďU/\2L oC F #];\A4fVJ/H)YIO AZ6cx-%jw徫8ߕ Og~LԓK\5Y ǂ(iyEd@IX)bҚ(V(- _% 7b!aq_Tl3&\MX6e@˄+y;< ٔgQ1XwoKŰz/K6~Y) })Q X0neu+W_h@.BG.KBW@O/t ^ = =>;% xϚIENDB`FRAMd{Z IHDRg- IDATx^y$I~W_kfk.K+ZDP)2 -hA òEa%X%:L2r9{}Lzu?""+*_{@VfƕYFJ=>FAc a- >=U <@ )fnI{0t.{ÿK/%`Ig,y?S/gWוQJ J@d=7$0A  )xxMk[0w6r9.5gQ΍6op{VH ֍_O~T|? =jQQ2w @JR,#M8&I8gOSFYV0˚=BC`—^ 7 i%`* lTziaaa+6DU*Z5zՠ䕛MQ^X k5rVË"J/ PY 8F$pHq ^й{t,z+Lރq >#GkeM`;!  To4^Zh`}qR{}l^Thx~}Elr?mˌڪxEF l4e(/A3ЅL912Iz=C0:8w}.NGzloVbd{w^jKKym0@.QRaorO>CR*n?zfggucknnvzN٤\.ST}f[%4ᔔS(AP*X˗Y|Y=}{oFwں?vn }JO,|?nno3gX٩m;'xIKKKMpyNᄈ <\&*m[[8fƻwwzrڵ`m aK_N1ݏ8CU*}j̙xi-gϊ5sh0'1^ǯTV.S^Y(0j_ _jtuk8ܹe[??'ُܛ` QgΟW\]ڪp[gh4hZT\>n,{ "x~Dye֕+D&͝kny_ Jwa-bR>1PXmnܹޮrssE UF}$(P)RqSc Li!ѫ6nAV#ZZbg}6\=חFO `Ͻ1 xk_<{K;; 찱7 [)x~t|s!JiCG!3I)/bNz^nE/]Z׮o׮'U{>쏕UX(/.sW\tI\yYonSTg0/)R66]m /n9 Z g/lmQ;.O^xO= Wy{Źsؠh=bw,~2=xo*0ǟ;1JibE񟷹<6J&VKPBzK.>=}Lm}מzꏬ;W9{w'x(y/4jfGq'ĝZJM+bҎ7yVbD mGKK|VcY~y?_i6h|VJ8}pة_Ǚvca  J ,Ө}fg?w[[,//SsYy߮\2>W( Z6L(|C_vOE 0h\@Xgx+F:F<p^{G~+WSWLZd)"„(Y8ܰ ؃l4R yyfa jF;I/}ю[ֵF:?]88Ѩsm|TuhxҙŹ 8<(MS3YPV˸2 wVO 4sKSC#:,%մ#|Ǜ7l>g+$q܅ o?E³voyXXX@JI$e'XVt/1Jv,ӪcB[W /q.: ߓy2`0˻^(eug=xȏwGыgΟgΝox/^dm}jxi++TWVd4jmjk ox̆x WW?uEqyZAx<&IdR f$!M#ag+Ʊv)$r^eTQN'b̌Qxm6'qi|usg'S e \$hxl܁W/\ +>+lon Ð4Mh%XIy^NkrkLb8I BgCYJJdW*Tϙ{H_jwo߆އtcp}} ~v`ecյ5lL$voj-T7i0E̸SCbX>vpЎ##ђR&kWVh]>x{N|5{7؆/]~'_vrL$ )HK4D |kذŴga qTy#nIV|J+d1J)[["2Mœu_ߒO[7ᷦ"LEnt̙_ .\:f0 s,gVqBL : (>npJa(!~HP'(_~:MX!46d/Ÿ+o=ĒG&O/\\P:{V1&Xq?SBXƠ/I6N܄`V1Z`f !x%/og%wNKn0BAQ`E6wqmm;*~dnn']X]_+,-->YM5$L. If>wP e3`6s͂C4Df’%_އʦG(S  z / ٿ}o̲<)0?~yBu,,..2 )s2K\DBL x:g~ԹP,d*c-{啕%2FQ^ZuUTB.i)pn:qcg"pO% t}nUi)Iǽs-K4} &\^# Oݦu2`ݸQ:s۷Z t&NVkcagOzkmjALpV%q WtwnZ峊*ABL`l4j q ؝" 9ǖ|VeÅϳsnQ]Dg'loonmo|B-6X"!Ly,RZ$ta2~*]eˍ oF%->eWI\Xĺ l<$ъ:յ5ϝ+BTO_t<&*~\]^[˔Jm©ꀟZYᥭVV:+++A05*M#Yu:K kźa私h1>ӟCǃ:g2Sxjhyu>WDa]MVG:di$>IÒ5^q XaI$\z'_# vvXhjDQR4}Cp*,(NMY)ܓB.:̋je]F hJe`8n%'zPeYzJ%K_?I gΰ~? m8Q~߿2fRDg83܌vUm>Ͽ&m47EBRTF)uDBYꖻ+M^!t{3:A] zIŽTX" uG'<=8|XJ+͆.bmn*upoE1~!5VΞecvx!LA4KsFCTujfug %ᴻs'( 3։d$Cqފ:"I^T*Dy] icoͦ[$푶@_Y2(B1,.:so}+_up W67m4m j|i@J)R# S$8'b6Fᣟȣ/E:\S욺,1TT>K,äOzSԴm|Ku7G) zBIZ% C}SRWgNKӆ0`ɨ%Q҄# H~?74~a*ٗ &/gh[eL&Tx Vu fذmnxK\<E Cт\4sX[\\^~>d(9B)mcFw:-mPRi۽dJp81Zt0 (-.faɠĩ/5#^,>-)ϟO9Xgt@JMRrId 1PҘIJ]Zk.,jsNMOIS<(t#R(J 8!>8`?o IDAT)nMllHStO2M8F/Vws L7_}!,,)̖+uGHxs<޺D5sKB!%@)0$j46؇&J,,ˋOWj5Q3_,B XrEo^L!q,c)3.(1}|ɤ Jx^N*=4τ;Bd}cJǤBFNl <5lz*(_j*%[Uqejf Yd™{/Vn|8+Cbsn! S7j56ժ .^kpKl4;xޅTrt{,\aV|2SH%Ai$%2Æ 6~$i*ɤnHihEEݦhuϲwe$.qgY˜M"cm}ۦLwk _/. reFtl8K A.QHKLK"O)22JMȳL& ^)_-.Za WR0 WLb @_lQYn0KَR8&e)2PR[j\fD D :1T1`LxW*2I@ $Bu,frLEy󋔓/y\IErb\" Gc)ĥ8I|]^T*ZmJKK:i4w2ۣ}xuٳmfT"Z\/ea2bErlfV0d74d5&yІZQ]Yn8.Tޒm=G Dž;QPLO) &)i&&rzژ*z]MZ /PYF3s͛6w^*5,;GP:~U&!5RyC-"Hxr)"ͤ3re4~6-Φ+S=P.~3=BZI!JQ$hde˗/* 2sJ) =mErQTYnny챽OۓfRe~u`G&aT]wr{j7fҹs'=88HByGTv;\<{6jnm=^[["ZX h44[-d~S}:}jzQ4!UUfD.d *j*3i SD(LSR~*ILSmC{PFW03N0,wܺ[r hQ<*'Ay#z(~VZ)ݷf׹/o[qtEIa)tO0}mlj 2FoJ^y:ZP&@yTlaa8\zb8˗_n*)xQ$j V 9փZeY-PJjgbrH.ElxM@!.'rh#ÄZS0ު$2?D 6(Z PA0E@KB.\"X"`(q.f/¾ v~&?RA)[޻ǝ~5~Fz`&pSE xO߅ŷ7VU0 kۑk1QW.#C0ʂR(4 ᐤ峪dKeTvwHf ԤmdL^j<@R$Ҥ)<ӓ"k+(*`a>H&7m;`-&$ǧ%TQ9p:ҹPjzчf ^t:ty7W2܃߀cxm '%L*lRG)Y^/|a)VkO?Ee=H5e0$(&-!`x*fD%kɕi5s6E@-n]ճTJ6*/ |iS|13E%i g-[i~JusQ$Zqa`>s},`ϒPT㳰)J)~_uޕu _|=+K׮Q]^53}Ȗ01FzO$] MN̩7ڰn̨h^3YP0!nlLg3 &tIe)KDžt?LS=+IȤ$cxڑLAE+*\$w!Ny(4 zREmi)،":iږ٠3t`ZTŝD>rB GŹz[׳,SSG4{Vo^%ߔ|]ʜ% c GhG͢E|[=.u5yM!!6m7,[ F VZ_]Q ʌIMmDA,YYu9餞BLʹz@:ItBLTu+*ڬsp]l/ ;u}χY،X{HndPr> /ٳէ!R6Db6[|W$WQf䳰$!M<+JSLxچYpϏ&8`gG/y 11@P2CzH~n"[?~y0o7'Ga9mիz4 !x̴gf~gY:gsvmv$A&K!e0=;o̟E6nYnEgAɋ!I!U(ӌax6*I M KL/J;o =%VF.gՍ age>qhw>`0)Nn|="Ǐ–3c2%;}ʇ{?"8M5tWn8,KiIiϊcq,Xk^+RB Ӕۥ&iOM:pPQ-(-/ƥK~wQ:Բ8o'|  j6ZfSVN{'C3=+NAP.x^;"䛥lG|@d4Rq1ܶa{BpqaKsX,ݬ{Tv_t?}/FDaH聴 CI4G+ ^L@hxխ-O1`eq>ZD~^tQ1Sċ;K(s^cf KRTb"T7'*|Vf0q3 Jwt@3ލ^V*2 (@%~;tz\Qgޗd4$^?&Iw:Z-Jr<Η@J &ӓu(oh0>8`tp ш46?,_0Tk+W;6!yzҰۥ.IaRJ)pm<=7 x\7wsguݏ;wQL LJZ-CXO]<H)Ic^ EUZRN!4iM"Y7eHS>!tV#QGgzv/7IS&B!Q;D$C L\x`KƒBAX.T*6**4, 'Y>UryAB ]n+7 ߋ;B@xnL' VqҔ.UQ]%`?N}1qQ*STi]ӛS"w.tO_*Lo6Fb%BLF3PJV]`7uR{P40$u:¬/cY(_l@7>qOURfCR}Ñ*}*ZͭtՉ AO9a Y}g6\fQa#^pR ,^ftQE(.&݂ݻivmzu/^\K%z=7R0 ЁLw~~ HVebi/Fz[+ϴaaLSF.ݻw|0YŊ⋯v;8a^x<5P%=v0dq.i7 ɆRPB^}@enISMJpd{P[-mR)O_DO @pxcOHk9#* @0{_=<8듌tP$=>݊**]qƷ*_]Lu)5YbH_̻1pE%!_B7TE_9K'+&ؗC>誆=88oΝ.|wxNGJ%$%_tunI6p6 {8.MR@>J[e|Q)%Id4ZQSݾR6Cd "?*f'6~^n)]xk XK@wݽ{^*XYYZ%dޅKZu\"EX7!LNi]) %`gnb'1Y5ךRߏq>{nJ7'7k{{/ZIv7v W6}ֹ _\5<n*Њ#ë*% RexF%ٻ$)˅5ʩ~E0GGa^JvBirlOC`,i?0+UB^Uw:tof-uC׷h.N$ ۝N=v^Gc0 (:B"Dsg"񘃃Rp{q6{ ,ѽw7: rraړO4M{W*M!@h8x-|t$LrJHcHOMS4EQLEk5ʍfT4;? Z|xA@ӹ{NGCGq*7V`oϫjaHTI(bnW{Gz=n߾ͽ{xT]ԒzJ)Fwӌn&ˀL_:Ik\t(y?mgRXvйvۯ»_2{>8'%>س >bg fGXViv:TӔRL4JuCگ/g=ŽG: QX `Radau axJվƽ] YzeOMA۷Fl6i9:HsR>?MSݻ7 x nݺŽ{x*"n*l,Kd:*IzI)$MY|uԷXzEǚRp;~|__%& fItƵ=tdY)IvDш\D ݇!Jj¨TN|cpj71_[F˵v DU>;$y6$Jpp8=CŸPvNRӡRa>{$.\<2c&(T=ϣ\.STziݥDcVZG"|D!@|fd07-H+c}CPi$}U}Vsrj\ZEɒe$6/J !Æepd;R"ā#8 l `YNb*IQ$w=f瞾͇+ܥ[虞aHV3 ,4g';~ ﳵ.ziZNi6{m۶zlmmveJ>'QDfbFy?7xWx^(Bh({CԌ Y"ynZEMG#öBs~"f(!#LXUW_!3T[/ T6<*D҃/o޽p|饗OK>)U&p8`08RQ.i4,,,h4VJ u8 H5Nk4- ˬeCH0iQ'J%r'XzQ4e$%V-`h,.R]\jQ)T*0$pvwIw  &VԹ$5i#o2/vage _~ᙧOl58Ir-%qCOu]F~tz8L&ܹshyOףﳽ{{LE4T_YJsZ-f^w0c|hm3W`--!Ҕ籇!Gm]6wvt }:Ij{ xXVϟZ`V0 tU^Mt*6 }d<^ o D`peϲ~@QըeY ']Ryw3)٘WR)ߧ뱳Cg8 ät,Ωd{LU)&G*'AK6B<{ <»Ay 1Gꫣ'/]Hʧ4}YVa0M3ՂRǥHk1tz(aOwh0 d% hx_z=nEQC ƛxsQ'jJi,//3qg0j' ..\*?}[P1BAm,TU* el6Nq`\d;YFF5l߄$L#: .=]!F eZ'ϟgQl4Z'Ӕb̩3SG9<4t`5;j@P`ZTʩU:kk,]H}u) $Yc;` k54F"Q\шܸsIMG[cd--#ӿ\VN4V+wDtA*` Jj4M6gΜKoގj][{fFAr}kcOaJ* FR"e\\xL˶sK \;>AV._wS;}Z=_dƭeݥ$MàZ.S,YƧ=w#X_nc';^_0=+N)N,k$3r=I)| ['}F4ǡtru+\.SYP^J\դ?4eZrJKبQ y((%S5 '!K+YEVm35:J~4yyYkk~z2ĩw ё| 0M~YRi6)jT;6SVV(w:k5 ժzL"ax}Wuq}lʛQ܄so;B) |0Y,<_u렴* B B˲X^^l]ZbthKPM4Zi )3)'E&_JSRJE{i[[,D%yxfuWplZ/PQ[^0MjĞ{ ժUV/RqdY&I)ŕjg]<]&qãg!/Fې 'OJ@@sQw0'm)U)aXE$VjC'q"Oz4%㤔ǔROin#e<<VyY~zh?8i +(딚MjTEoi*G@b)wμ#*'S >LC"&=>[jW!7-B@ͽQ4X(LJ$~uxF&#  x'PRsDωR]0lY;wF)pGXy1gRt'I Pe{ 'ix."y huƶN&!pr׶IK_䃷og^W(xrSVWW1 ((]ҥ $>I|RPʙ1 RjS,]HZF}uJC|w!;'I90LIׄaTDC0znbxx5Ǒ 6W]v{`ߏwϽGzE?^*M0JA Zk/VO)g ǥN"`t4cDђL$ʖv:[-OkzLEޓo\"EƞG8F! > v /HI>xxxBϻ4u"벰f4M"5KJiַ@J$QԜ)=avBS|_7bMJ7 f$Q!Wm\жI|4"t1) n%?v͛ |ϓ=2Lmm:F# NI1Oy 42#Hy3 S58m@\kaJpd{x"ۖ;a_~="N@~t4|)_r8,trVĠj;)$$R? NH.31OB9{|RJ" 4 6vS^hdow4 ඔQB;;N//?ߞL3~3V=5e$hq.U8kpd3Red˛5@ r9-C QDx6k8;ݕ8w@W'.pjzb+"Ĕr-}태@2A )Wb5C@׀O-.~αm[fFѠhP͚taX$6jx~8!#ɲ(qa5yd*#%aR#Kکʰy/ s.}"#=Oz҉cS䤯$^+!|){F#`~ |dfb,j5h`jIDAT)VP 8&HP\bfeN:됆!fT63NM& E ^Hu%s<(ǝNqA0ȩr,B_y75C$qc s^/j=˲>h6fI^7ZrTcQ$`Exc5ETB6 #0j Q(P,ڂ1gLɌRJe% qdD@FAa(8R> q ۡ*^;!KH\Þu?jdbZejSF˘[xFBl͗_Vmdd43♅bQA{Rd΍vMmjkER⧩ Zk/lH}%bO0~SW\ ߄ Pp<n˲lB=t%d:Q0-iNZ'iR*aVRF(IHTiOr[AxJy lr _ˤM|GOco8>l~T.?^jGxcʙČ 0 f !F9WcJI*)( Ap H7|Ml!~IX>1 w;+&tM\P09;dJ$:I S8Ha3\>ઔ>?+ X4m¢ gPs+WQ_:TQD.AyjK=P#l) % 6oxj$IENDB`FRAMd{Z IHDRg- IDATx^yeY^s}|gVVf-]]=#0aXXl+,R[`a;(;Ⱁ@IL73={O/K}9}ݼ/e޳|;w !X/0 XP:<@zЋ;#v ŀ8c[zťOXlyda!T.o=x1L@XSd|I3 ܔ] F8p,`qvS._ Zިr/· ^pP7 @%!+!Ќ$]1=p' ~۞ ǁm_x޵r]Ri:?Rkr<+U'WUэb YX'KlN>ΏRPRB10D|Q"ql 8.hqǕ>2=;} 5Gm n%`(0*OTjgj67W)vRaRuVTPY!n:#1g?o.BqҧcPCD~|xxhwvvrN{q,v0O3$~6lJy۾P*?Pj4.ԗ6 R+]\JEE<rBR A; yX`~lV>&D"}q@~Aǂvv vvV nNGnUaXq't|>8mA24WWo\[^^u1?oUj5V^J*<\E.8p]nAyG~hò8` /4r?R8"8NAh0@ tÉBCavpjyB,O{ x |J[ ߲l,ؕrO5]k4 FfbJ|>۶aYJDe?F#`+5OC|Ç_n_{t㰭ꌟq[В$*P/r?X_ZK[[7ssrƫ&+U*h4jV(J(rp]7!I>merp H]tU8"똻u ۻᰱ/ hxxn;?!` X( ?^ƅ O-.6׭ek (JSsI`0X̲`{|N"D#Zlw͛Ϋ7o6nܾ(:>xiZ> *=\eq Ս7WVZױUj5pAiIHm'DrAYe;bP~" Zewnd΋{FvϏk7>~X\zW/^ͅ\ca/:JRR+ =2x00ׅϣ~"/ᅬ'}j.Jz5˻S"~l XjܲZX[,.;.]̖WV9uðmg(^g@-% 0yz*D;_W{|ƍZ<U<[n:ݏ;.Z.o;}kEkic-..b}}=102l™kga샾P$$XyM f9zU]]K/n;8.C_ ߾td?R<{y~zx_XYa+kk(˨jN \g?}?sO;{vgx%·@#Wx+[[6667J(Y$|(80UA)OUܲ3QD#0U ++([]8Ҳn+a/n.V:Ƿ~(l X߼pS+׮kׯsayyry$]i2?t%v{@o GŸq^!TĐR \BJc >Q4m xgg{׊KK?ceܹŋ¥KcI/AAY$=SL_ "9ꤑ3J)3>:g%+ePDaq-s~jW_-P >nUO4׵K|omamm ZmlVQ{6>,$M8H !u=43R6낻.e~* ٌs;Bm`3~և05C# /__x'Vϝs.]667{VAz33|Ѵp&"_:܉$4@GBB@]C6&R Kp j5Kޖ~ A[87om_kO@%6K.\O|`Eey~kֹ-,b~~R)!@ҷKZMceF=v 3J?ݓf` ǶQڂS*/0 C1$#WW'ǟ|ҹ| {<Pd}41Hb$,>v0iLB$ dseBf#z E;nXty u0nq@'S\K@/^skϳs[[8<JQ!ԓ E*H 8+8+qH?CNekANqgnG4pմ,kOV, kW }/9_U ^C``+p'ׯ/\7ϟ"*08I,dYRa #WB<6NH/KY^qN;g@rM~9|jC+p!!@*>J?v\i}sooocqi %śV@`Lvܸ=fqPF*"0!q0 EёY0ᎋPZҐZt11Zt̸Jai7EAlnbe|ZS@~=I fge]y zqE x<KT_JpEL3rsgKz`18@R‡cGY-] ǰ x`]!*/X߻{_~t8=KKKO6~vycn./caqssspL[IBDTj$T3iptuG U.N9##,(J 7]V +g|)y(ց/]vWz|>0 1,4h& M%&j g%ӐTY#MɲN’B }H)᭮b!]~]s?޺ TS ?Q_[U{kk KKK28GD$NVq)!0Ʀk=NxgSB (2[V;e$29-$'̶ַa.e,>8}_Z=;U\XYϝZXZbͥ%,qӐ03MOIm;x,b̂0 RBqf2LJho*M6QLL,_zt2#u5)x1pA޽oތ!?p#p d?疶-{ucKh4}OI,3I8˟LM l$L`z; Ȣ2Gg摺FBBL6I6T3˜# 3p&0BR<4_Gyf~B}o' >K5?3녍 6??|>? %oZ!TaljfK8?Ro'AƪR+&I HNڲGSDf)KS_ɗ/#" wjꀔy:X]^Ɠ|6pa8.;YZ_/^j}?1<+)7f&y4tL$ /0MCfL2t:f|8ڟRtSCtEi R)Б 0Mc^>7_j2|8G<BXr:j/"[7VGT U'9S+W-W77_\ZB^GXmS̪$;N),)):Nm$dl^,4jR1 ؝"}")T_S|<|WWeƼ*i$~ NM{u}-//'7B$"!0MnY$$4arz{T LMheK >Yf#oOUBcq>`"P1!$&SJ- Noqsva]ak?>x,NM@lm~ޛ_\drIgq RӬX<@T)TFO2Phݙu> |EdJSnח'cm kXJ%aPpJ\yY8Uϭ>Sm6&l۞fEё]VHAV&}|JJ@BV}'tf2UX7PD&4LR57(u "#ID<T+.],3kn? I :bBJF uAp*_g1E}t-zt4JEStl #Ť])5qH6ɗ@!r5Te e8QWsieT*r F63Mktp'O4BDwul>`ϴI vҾf3f@/,0fs6R:mʟ@H/8Q:MM}#)4RH2a(4(.-zd/n+@u&8V ?;,--\.178^e?,Z@ 54{^fsM+Kr M~0h${L@U)⑿?BZFܴ,IlS?,(RsEx [^ƥ=|<8 XV)_(j|nnR ~f]+M@Sn?HJ8*NCl0K3)':z|%RWD}0GjȾKBMPYZr&Ȁ4iT-זh8zj5r%b2P, '1^i~Aɼ,LP&FjN@&HLu]GǸ|U>M,)eҕFX& S:N8?3FqPZ\Dsc˭V |=`L֖^̼R E:x&L8xYN֞$8 dnY:f$(Je(i4>Qii 4%#]", F5T~-\qW!`ser~R\X,&]ϗt~PzH)TZJG;(#U.x>TZq #]ܶ!pםNTER#U _Bi#Ł&u$|4]כR7)(N;96MwM|H p_JE@J_xeW/,/`֛Irth"r\RtEg("uLAsV~AdxH{$]f"q`%q|>ߓ@3>ӆB0 zWK2BP֬C*0c#vU3eT3x.u<ʧ,SWt|=QLD(6 IiqMN/97OcP-Д/P.Xq4rm)8VjUur+P֯ItƦC:NɊP$k)c !An۰=V.#c0'F TwcRb)OR$$PH%~V8\}R"n\Z FsN} W*5sWpr98 ι#g 1+!N^Ik{R@ Hq j ޒVAMJ)t/WϤ@" |" I_ 2qu\V' iK["6pRQzDIXIJ=M>TB, :f|>u3QQ L$MBOq f<8oaN#Pd[\\GCvvbpv,K=76T*FV>+8qPEV`܎0aqiRT3:)Z:I &H%-$@AqrEcp<9`uL՜V@˲@md ?w)L8A:=)UJ$SMKjT"cDF6#Ύzs92)c%]**@ޏCE2cCH4RqO DE&D$"^d\?E$tI<.QFGiQ8JWDj,"Uj"1BՄer]@Ov\`Tƙ))ófV*r3 GtQ4>J'Zs۶a[l]Ǜ@Kx7ߌͰs~n`s$\uVVW'Wrou*rYYD#~Su*䬤u'd"uH$rM%(jAp2(%QH&m2VTjh 8ktStM')19vZ&)p4dP*7ɹZòow=y7 qW Xͽ=oJj.Н ΟS9hz"eCDd9j뙮 Ұ"5EzDVeMRR;re%[lXƵaf۰l2qX`M0r]9'+S0 AiYr}-NH'FB*4jŷ,K] [@ )^/}H}-(fq:]Jg+Rˊ6Z "v]_ j[ǡ^O É)3dBiґE.)&iA"3\B0TF~r)gO*|sX ˶Y`Lh8̶) MR2CniBD1ݎ;6? zAG R̸"1dwf~8;!p[EГ-x|<4jVs s;S\_wMr]|l4@JH(F~?G@3xJt(57!(7HFKH&?WZJ!8^d\M9l@Z V|:N22M&3é*0wʙ>NG:RNOVO_zp)GH v>Z<+I ,.>8xss?j9"@)N1p8(SMe;BHըHyXDXI)45U(LX,wVkHreG "I&"=(#y<&e0 hݛ!ǘC `~Y6up_^nv͛vuڤu}IQ&UW|[-a8GU.u e K~ ]*>& =uy'!!<жma)oUTD!YD"_ MV}&gƒnL)ȴX &I$cYnY$250Yatlps0P(U C @BD[_x%I w,AGݮz=Iu+RSu cln;bU04elY'mtn7 3l10,2V:9P!QBK8 [{|:p|xj!66j ?:m#z:DZQ(U[K(L0ƱIt3Gi>jhTwB= Ś!& D4Mq`g# Jՙ[5qv/qÏug˥Jeeܸz  G#D AQ'jHʥI"lIv"_* 7l315^9H)pp|BJpw !~7P#9ȗJ}ڪ6.^̕76,n*F#ݮR0)~0+8W:IȅVœQ,gqT "`E7fg_&9=F̴96OJ5 =ԗ>(8`DᱭNWR^#o! _H \ybiO*,,0+Ztt:}2BBUlq:mGjE#bF2?`Q0K-Ga D4kb`mx 2?0m&xYni㎳pa¶mF~"@J Э/z LDmrͽu8hԗBHp˲BR|iqj^ƼeF3@3xpB8NSܲMW-lɸi(Tʧ a+jG%*EpD ܧS矿~^%l4Lef!t' ز _| a?F `0Mm}/\ypX}?o,;V*yܩT+tbCMjVc v>;=D,eK> #0`l!:e"pNG <NKsQLR cnn"&ݏ;N#}8NB0T=Ioj!U1mޫ[)E ̲` j*%Wk$cG z=Of1&aΤ|>Ia@uXp8D( PYAz}?uq@n֯?qоmc4%JhziD#cxw]5Sqo>8OFDƹ.F{{mej䊈U?ev>` `\/ˡIG')_L>0Ztg4# #!^ |@Mb2uA9NvKwF:fsXTX#ZIEe*3ICno1n1# 8N䶚gr?R$f+_|Hx 8FDZ8G <;c4K4O$io;0M(s4&א|1UTӷ(UBmv%Zpe\NMPhE^a_ CE!z`!)'ӵetXjjwrEQ:{vZ߯:s6xrgYa;N#Ni7rՠ\EQ4@Ekb~n,fќ9ijh8PDP+i1L+) eوkfheni0q򙿜+5,N%2J8KR Ka7PJ}zs*hDqr ;W~R<8\]3t!|Yv >J壁ԄmQN/@&u!='G!}?Q `6L7s3šHގs'P\.KH%,>Y!TtB }'"XLiu c,[NSUhq!ЎwxG{k/zFgf~g~;YqD 8bU Pat8SE0@<|vo"Q"Vj'ŀx4/0vqOJ9|;#d<`1Gdee kwl"s$jGǤRJ8eO4- \u4_`\=upK%EBMh,K-83J?ͱtzYʗ&) !pVRF[(uI)'.)_.KB!A1ӰNaz}]g| j ݮl tZ7bh8p]7D0ctKÙ&1vd6BZg?~R ZTr Q"QvW19W' ȪuW }ܔ@B>2CG Dcp/Ʈ|~d"3J'iHGnA:64M/ !&dqH008 r9إRb2$uwA&9$RE*X-{ |P/nô"0vAKpt49 |zvk@}}?5P`M"d?$U:FR4Nޠ^R|"NF@;=pj|Inڑj ypUbQ EdLDP/Zc_0؟1|`8?^fsJ$LI@U[\iKڤ<ݛd ǰTIwm1JV%i28#Lܙj5ඝ+du]Dq.X/nm}}Oa\njy&LBL{1l- kkN}I1^D)՗$EF5Ra&Z@jՙjvSFT0{Q.C8`Y:3υ20(I4Ij5LPRs8qqvqSJT =8xY֛çkZ$R T&Kgr:T@ut8PHcpJH5I8O3ݔeBƱRCGj j!K#=KJN"MɊgF.cDϿO}Ku]xj\Mq4fNE4 m< \i"fmw6vvKhs#Bظ(vzNɕ5Lnd)j>~_ rS2V 6F`XmiE-i+B]Z_dL5N{px{wLH@t^k}Cض u04L,"rOv^V^ OHE[ֱ{#; j")-{ /_ϣۻxN pFSz o>+e<BJDp-KL(W^yoܹ]A0,qa j quPI@ "4^1VW1e.D޻_*uc`D }s!]\(GBBՇm9j[w:hM)q x 0W^}OJ\|Ȼ.!\W}Ňazz Tnw7{@~~j,de_?,,Z Ε%l$0M4Ҋ(X\\x8ś7)JCq?WR4oٹvs>Ct0s6tB߳AwuAOqgLVk:\A8N2{ d&LRf3*ϣh}T*s|>B9h}CZ-r900 b(g@B`Q" 6E-^sRb<&>Vtim1N |ji}nށP[Qk?D c `L)޸m#ǭ^O!𛾺S+04yW(2s>?LV/mwpp֭[{.h/Vassr9nn=ܺu onpθiSI!tvvпu n  sG^{ P 0}5*fP[J+Z8p{4 aP`B^ e5(%6:jVDŽqKƹZjc8D]ywo _x|Ww\˭v b޽7nz%+5eq4 ,--lbqq1661jP;Ω{mzzz粞]ǎ$XB@@d@DBq6BHN"Xl"G!PN".^zo3;̭gZ:{ꚞάg:U]0 2RJ|?G4͌9aB+:#GHq}uls|WGeҽ1#X8vSmp<:ǫ(hB!E] =ػ{" @?7xhvVE>qiS~x75%8M|>OTP(Go ^iYb0|>O>_B$yM1 .^B 鰇RYGwx}_2'\NMK(uˉ76 &~_>L+t2[?HbeEowq a'_)Q'||7Μ83zYrê !jR4us|$" Ca00q] PSW(,R4u"jJ8>~RY,b SS<1)W]|n,%Jj&(pxbǼOJ>OeieĶ֖jeʭ%ZWC~w1!l.o:aG,8z7k#.mlWOTBPjQ(ħVB 'a(Ud2(iSJ5' +4LӤT,R*P@r(8kNSTDdR2ξֈW0 K%x:Y@TlR$:_%LF# ,@]*@4Ii0ޝg*Zh'w]W^1|{" 7a}hiBp81LnQ@Px̍7xt]z\|mFt_%kXZZbuL A2<Q)Skk?HSzJ-o?hk?zJyMllmɄ+>ImvO&Y][6BV)fjbP~a*9s?10 "ϣnj8HQ陽NK/% MjpSJn<DUXO<裬'Mm>m8t]lyNgfy޴ !M&5bRDݦ^sq9y$ԗ DU}Nh>n- Ξv(9RC;&j".Ґm6.pP$M:KR6pevOp'9BB :uH0]:3/>IҿyS(Jw.m_\_H3nv=F1g(&!۶Bu¶m a*L`m*ZN:'N`uu5zaݽB=EBP&Mh60P$8c8s=C)`G϶H| [ >3_S^Fy>^( g>)ϜNum tV1a#I@.zU:n(a{Kx_໗. b"ĿjUT^O۠@UIP(mLu855kZ-\[[cqqqT{ AUP;93{y'OR׉d :˦ɶ>g+Q,/ʹs,<GAJո5P̓,9nE*E5X8q#P;vrhd0{~ Tgx2!?`䲪$d0p)I S G\b R#M͜i㰰@՚[!bq*VR,YXX^Wn ۴tСUV+&))RH!V2E)Jl5ӦɳZ1;4fTsi)܀"E=X\Z͛*< % Voz_yJjE?SM0 A JZ(Ve>onИW#>`^%S"W,Rn(6*l2yGR#k,.6

\K6u?W*QjW T SIR,q)rB&}qd )uHp-J@ W)O>د82I&mxfZm6ΒPcPVٔ|9dZs茿:f6&^?aw ¶VƗ ;ߎG zO oEQk]pZR71h5BM e^mݷAѤR>)*e eDCj7vSQpxgw8Vp]Jم ;|-/Ty!-W?w&Ϸ纆L$j58>I gYr+}̤;D#ř{׆HTr="R_mFjGvmrGqpG#z۲oۼ-pvąA!N{9Ͽ,Roxg &R |pr'<{$A;SNDrM@Pyng8dF{R]S{vY6fk 3qZ/56++miZ|C]jөٔ,gQ\dxIBSM ?gO]&vOw4j*@bGOp$`#M'ʞ u% iD>ZUcu|8 6 ӼUAS1\*+&aiCDe]G١Mm0yv'Ǒ{A 41\1NJ<lϥ0 rV3Z6zf9mҊ]5g1o~94Ccj&3EYTzNZ5jFeYf9#8I* IzŃy3TO ٠RvIB$ QnJ'宔raCfE@LJ//PCO@Dg8R98-pJ%7M˲JB\6ʖE1k/dmh3 a8*y,0ݥ;ϛewN.3>' I&FQD %~@m . C xY}H(^cw5GIDAT,G*O R)Q.)eA|!5RC}n޸F!3ճE gRFIB":t{Dƒ$V*%[)UP n_j_-g˖u6g-ce勊F\jQ>0RB"NҸr7S q*%@2G"-qU+X. ?6.'q\; ZU|T:_VO'ylRKAm+,5#7BlÐsa2`r)24Bû)쥰.NpWʃ7< dԝL |s(zqhs,6¤z ĕF(?쨢։Q $* P $C000>>GDrh]IENDB`FRAMd{Z IHDRg- IDATx^y$}ͬ~9oޛݙ]A!&Š(Ңe9hR6E:차B ;PXؖt8H[a"`Ssξ2G:^;]UyUU秿yV'':)l,E Xr hX@%> DB%aD]Oq?1vᏓuq.Z88ڱKbC8qϢW}Aa cg qf5 Dux II58esx[֎h`O;5uv`<mu]ضC`5!#q_ b}o5z@\TRh^VssrbWUV*Y`jF}rσySxAw6u- B׿ LPHcD!aӑvã#NGd?Iw8]Gj.ʞm_*W*/(7˛rW*_rʼR R EGRAXD\gGEmV :>::GGvX9v xn=7}Xʟ4[XzVWW%4M,,,T*Z ˲ NB!XI0x٠e".>x`Bm?P+Uu^[X`jfzZ rJݸ U[>Gc PlB[)PWN﵇gKG+k_ͦaobXj6/]z~nia- ^o6ϙ9??|d1˂<NDaG2!hhoe[ݯ|=uyΝ! !$P}5ҏ671?\Y] l}cX[[C^|O;ɤ<I38:=1,pǁ]*ODV{{wwe47p^߇5E xVp49Ç>wPxQ˗d}kkqem\\䋫>7FrbtO&4J! 'h}`quay/y2{x [|<.ݐr.}HAXܲ_Z\_UZp]y)d-on%lll J~nA,`[Ţ< &r}ߪ/98wGIR lDq~>l\իז֊|quR^T>hIrb#Ax8U([X@U*[[۷qﭷ*w ]`qlԁ_of Cvh ?Qp*.\auu5mXE,5$ՠ8+ƙtYMjT R j>d0ʃ,88`(oJ_ʋ*2}^lŋ/lmWVpak +i2'<[qLH&糜?1R!qVܵkB}rx~V-="{` Լf\p/\u%vhX,cy=)BL7hHiV@]aRB)Rœpj58 V0XG}_-[/ !f6>0f/=ϯll4Vlnmaii j5U>fA$Z#1Ȥ*Y B/R]0bS$" C{dߡܶ]u, kPpfW/!n[ ˷߇G7y ;;ͥ|乵 +׮ͭ-,@PW>--՜`Z!Oа}"ۆ\;bzjz-E_<p ,sK׮Y[;;x駱̗Rͫ6=r>!lYdlҏ79u?ɤZ T /`,~zۿ]q&`mGOP g|c϶/]=+WWP*ILwqP^CQ{FGCԝֳLI hpMJ9ӌg,u~Vh$x,E{%j<]nU0ِd\@L?#Sӌq>U3m86rͷ.vx-??L#>&;¶εkpwz=}*>d` D`YOv'}2Ƙ*;V1/|r ڹE%, 0]a G7"==v,_]|.^,_.loŋqH?U(RAƔʸ2 wi5fM;K\F 8za5iM uW?6z]-_O%vJv7{? KWZ!(J$IpZ1K%=eU'jkKG]%c֭hyq: &2~9,CVC#?69OE~H;~`e}qş]pwvv S `śU@`LvҼIv4$R5$hg j,C SgGqx hʤjfLZ ?˞[*Mn"!0m]SOᣵ>xOIBg[[^X_޶>[@р8ab<p(H8),"RCrȞ4:g?>}; )cǡנK! Vm ̲h8D_.}7ln [ܴVV98d-O'J}ML5Þ6ώ_)&U-Ncs(GΪchFM’B H)ᯭa!=u۹uzGn~*llښtf 58Gfca[taMQOɞP0[V9Hy2-,Ր1_y5Tc Z=fC_Y.mnuؤoM7UYJLZƀR(R*)Nf?j2|B`#!, F˗ k#?+3+_Զ"_Z^F@TmSLNRc KGh*9 #Ss )_n&٘0)t>3 >R@bVCE?V˫L=>JJ@Y^˙bSy:3*l;MР:6SDaMC5`ql$>I`MQg]*^@E[o]/rT| (mm h/.TCn4P4N35iRs 1uе}-Q(@LE FI2j($U=)T}6%aN:j++|Ѳ EWzM;UמygyuV(  FmfFSfݲBv,3EO2 l2xcLJ&ɾ)哙^Pd_/ CR:fX3nj1ǭѸzV˚Uno+SЭ׿lϣ]cHyJf(L-bRC)e=10@2y|, t' eJ'~0oq<|BRxOuL >SRwLy/8}(Ps./c^Ā?5iTt( iK'd)25/f>T%̼/A`<MCj2@bj 8jVI|,)e:FSX& )}'Gaܙm# CXQ8(/-aas+Vac"fX_^^i.,ȉXuuM$gix5R@7v?Ny』zNܕ+l&2,:! T:B2sB-O )Ӛ CM@"%0AC!R fN)"PET8Xx!(O%i3LfƣtP B( x**V:*\NJjtm 5=No H[5 Na :T-ZDqU,5@`ZjZ0 } CP&@T3“ IDAT ˄@U@Jpǁ[VZk6)JTu]0ѲfP'Mo/Z$SIQ1pڌc),4RNbj.^VU}>|f Nq@ Ype:Ƈq4c UB@& R ~ypgXU7`Zn1ӌ3-{<nBOLRh\_C*TN 0՚%5I$ʙ$t!vHM2 *eNq .Oi@bjYJ!T`#sS䮯qd<M^JJkKy'X\]/_@~M=>LU1Mu?P` @j=%I'-PIn@HP$[KpBxJ!&f )px]gO%B?CGQCJ~h{"?>]$Ar h8Mf/>ݸvkk̭`W*[C$~-fZ(mX u8XD,]eT@lkit˺eyN_IћFP|˲]']O{>ܵ~.2v}& `'I6]嗫RJ6z"v] H$R-SShʎ2,t"^"uL2*SH52t$sMI%y`r]X  >s0` B6eA1N:6-/~U>2жYJ>vz]z]yXsIE"#-ߓ-xf< 4iV+s;Spir]p, x4BLTKULRH)߀K!iIѫ?I-JMi29l@Z t 06]Nu'UA$ʙ=iRN?_R?˲!.pwo:kQMaWﲰon1b੻~7I~𫇇`:Lĺ1|(W2Фp%FPI:Y|~8*4"Iy.=SjYp8GAGB,SP,NL˞'fӱ ǹRp<Ơד 胱6oYۣe~&|dXDa$I#p 1ԃ]Y'0*R "!$Ii#R4a iBJ)AOtqNuMxÂT-`zQ1XB)cL(/f)_?o#s3Oڧc.1I)e`,2)wz3N5}IK$R1:.L;.~M#u)e r:AL_\'|aLu06 Ep)Cju;-N^ڴoG ?4ZJd_x>γ2`yeLJB.REKi<$'Gpp"iB!iTj0##8h[ıEH@ HCdeV'm;(pyϼG@kYj`RAd=3{RJ X13e 'Ybo4wbd]K/S0@ũjYף #OJ+ 1R>xc'I D@^)YI eyi1gM s.0hB4vR؃)em)~yq*s葉 4Rk]~'"dGyJZ]]4]S3$p4BJ4d\]aS@LאB?@5$'x`NfyU4SI-ҞuμcӍsBtT0mB}ea6AwFAcŲJߛ:1 *S*hg  v Hd8D!tzb cL ;N:?PuVT>0w<!c9n(ڋHFQH`e!n'i䝗,{l@MD=ziBL껮.,2K]AjHK?}.\ k/vyriqV0!vics5zXOiG(8O  $!YtL[(mL;cӝ>ITlXEDZzӧ뺈(P(`qi Eg}vWKx8%>=EG>b}VqqYAA# T#$I8'H>,ʗaZȉ10Dxփ邱wGh>٦[6xynYqDQRND=7 @PHKPպJ[>spl!}nYSV+~ᕗge 'ےa!V p8)N㖥&njaKLC3)V>p5A Dq No^}Ollay-a΢|4.3/iyF,dZD0`0H{be94ty15@y1@$GA znjRFAkn~Ϭ[en&5 X(tćHғAhJ:u8hm6jxLjC=3IҵJ~J>1[} msKhq81^ I0Y&LzN؄,7?˱ikS>UTӻ8NaO1" A GR7oLR?z=D>6  ;PJ)|l||KM@Mnv[8wjkjA-ԙCŰiٌ'Y~eɞ7FXg Q#%I#GXcBzi{喙jg9IGG#H, \J0PVjD_y|Y>(v@3T$t !"-31{q/F#F H'3yʗog9ΚyӔ\e~*)UP+h*H͛*\"5f3ۆyOFpeJ7SBz{ҨEߗ] SdBd`<~~4 Rfdt?شl$w2>0 g@BB Ŕ+ ̖I8g7L+GnR8S>}qUjD4arfc}fx8~h['c+_s8RUǩQcB@ !L?~_Njxcp<v*YP2qzs~)~ H'ndw @ƣ |<3~H-/xfXcӲ: (dqOE 8mZ& ]N\Vj`MLʗ5FF# c_ʆw_{3[Vk :*P6QY 7R{ B\M%sy^@}Rj9sRmO^jZ-}}mD]53IDZ!!ӏG2۶QCst|,]糋E(V"N.L/ tq߇ERcl cݮl /lv[ ~e4ӕhz }ypiy;٬,z P39h6˲QJuPLcjlo\nӘm}UczzJ\|6G p0(}i8/'jaZ%TJd*OeA1-mO?5Kiʗݲq^u\Xr*~sq=FIDUQDj9Z+~xô"1vEKx0u6L[oF 0̈́M 3Or7ʦVn(J1@g'X+Djpu8xC~pjcjsp!L]Gg`8_~fs #B@gU[e?&LUA=tK&e 0$}TGuA/\DI J?:V {@Ow&Zj'.oo}waB!!CCFo`Efg Y[e9nh2w3(z$`Ԏ&VQOV>Q:|3p2)9/n'0Ո ]y_~ d㐝 X?>[. XXXi-c.LyL)|ȍ1ąf6BPcFE?mwkTH#<8Gi}N P0܈bZ Թ}09l=(V =▔hۙ7N{xfY_/XӱRRz*MfA1=g7S O2' ҵSlX:p<}?yIBy:Şq,drU,,#4/)U?4y|1Q0,rK9{RE؈"\vqm|qLH,yeJ%#uiU4' iV(uPQ{a" ;w_Ɲ^×m\0& Hy0fL$E4m@[-n ǢRCnڏ]t`q,;_~3q"j\MMipe/ ((JXZZx.>/%ZU T\9zPu6Eh}&J޹;onh<3ݻwѺ}n ; ~ju:}sAbBf Y6S1Ɣ6݃] <@_:sK+_QT0Ae?i>Cp=\~wA4ife,,,`ii)661jh4yRb4M#r>Hʛ J8RvB+!a/^ 4|UFPťYr(0?bYhaEPl6t:޼_!wr}ev~.<hd(ǭjASjTI7e'< àR*88Q2-7HS׻]ڼ5"IRv_*Pc=(l0 *VI}0BGCS. fkqL二q#f#؍ c) 3_wϝ>zJìմ4M,rAyG8p8d2.A L}ELӤ\.&@ʞ.ʮe%,ˢ9N4)*Z ˲0MRDR!ДZ)hKn$CzU(MAt(xuoq"Uàa m˵%FBբLڵ;~wгRbV>Mwo+0r#77h}}˃VY,Z܎RR<&4*p41N:s BK6e qE)+n4Z-&e$ @W*' a*JUL< e&Z =3g8&v]`<ƛLrB t X5MдC6B}:c!9_4Q0irqJU2$aQT((rp8bvN(rLdeevMZ\.AjE~&/_իFCuzsu( "$EoP@:?XG>;0}|n~:ncP^^1 op8dl~\ wIJJY5Xc4sH>))Bh43No d7Fxz=>[[[\rqʯV,//C=jJBݦhPH Cq=w>'tse$y"m0fߤ+DGhیod6ߘN\3Tjatv[AAmAP$4 _ "q;'Hǃ]jp-˹C2/7%1 `:2L1fb^7Gc{{~`08d*:u*VVVrɲ,,ˢRIAJ5 ܩSyY=Dcn%B w4^|Q.qNFl9ׂBp16tdea܃J)3p1`sU6EؚLҫk!hWxʛo?wfB<%uJM ~4TZsQXc- q:DQt:%MS񘽽=.n(ׄ2.} J)ZEVp9}4kkkԴz1*8bI 'NpgYY?HwmGż p\]D3"rcc9'Ob$ݪH`a<&.e:nL\/oe=' w._B^YfL^ˠ@fJV1M淁TՍF<VdSTRWjp}}%:N 6Il-Z  3O=ʼn瞣A^g6H#dFw{?Tb޶SJ 8Q/gJkybR*?t{ Fݚ^,XY:aIP4*U2>N4xډTMUy .{Ϩ.]t1Q>A80?L}$ [Y*}N>%^uq:V+WiR*R)Y[[T*t*o JJLKuJ*I*Ag a`YTeLR0Hu:O<=NI :{14ΎFd\~YP)UTZ-*&ֱcZ-jB"IE4gĞ'o\캸>-]qm6t/wW9~>m4Q J\.rBgP4MVVVfpE6y bZJҪk*͟cq s͖UjJ5ҋtg8uڬew*Օ4]ByF (T*KVIPM΋hE9S HSD\mMrIlC?1|l0l)^IILJUZ=y-Q|Tz^ěVDVZ-2P >)= G! 0<  ˢXS=qr6@uHY TJ4k^)D2$!<9.v8df1t/.fE;SY! ?k ]v\.qbQ"9Wy \$Q'ΧTҴhXVz,2ZS(Zr:m$ski*ۑGN0kDF&ȽAc5,0p2qvwqC_;-ތd<[ 8[jIu$;~~jy8ŬHe8IRJE8,@-(iM͟s܋, I0qteɔ>o Ez_Q֚-JIH7Fx.a&^޵k߼noJo7Y,(I@~?V0t0tЊ"A Z+/Vj^),r68Z-WJ2J⬈(gm ={=Wyi,FG8F! >{{ W` /:V ˿xW¯wn꺅%\ץn穲$3|gYTV ((I'zAuh =qN%x!dz/ (aqHPNc$oZ*\޾ \.W54͏UX5iTbU9}T`'-WQT&I T[o9[/ͤHA!(3"΂@̂/pP8Q$#}HHm" e{ˋ?TP!;}!^9s]>o7Dx>?8Di "$48{) O`3WR4U) _p+F(WKb,J$MOI'3vfǬnĕa5ۛHHOCNIh0 t5v0W}|=DIENDB`FRAMd{Z IHDRg- IDATx^y$I~ȣzkgԒK,E<-ڦA)ҰaI@_Ca CPaP`0EҼfwvggzg{uyE_Vdw13Tf\YoYٟh,gll,`,e-T b`p =&%/9eb@ km?k;,Οql8%\FP}8\σe`9b&:- UV yD+xg%pG%ЙKav;ݶ8 ]zѮVqj[6R*ylۆ뺰m;ues28!F Uα EU#}3'1px@m_sj{+zjj_ZNĝr٥\ׅp'8`lVqbottq\E4.#l\𳻻q! CIb$xe$!>?FC 9{T5g߱z@mRTo6_i4BZzUUjX^GbeGZEy^!mg?ew]0:6laaag*dp8dA'.ؽҠktå$@FǘR"x8Nc\ T=۾^^iZ?\mVWղ_~ƫ:*T*}Z rjYrӪsQ@gz 22X1kя" C0D4" Xb>``cpA܏z?$YH9>6~*>0U ^񥍍O,,-m5[^\&/,pRaF^V*8\MX6:ӑMp.8`>*WB& D! $)D"zS>x''ٰ-t:hkxn_ŷ} XO-,-5vfX^^ 6PTPeYJض ]r>D!<>}>۳_zip.^{ G#ޞ1OڌamؓphUJZ];;o...5*f7X^GFD@ZEVCIw.Gqc TnCJ $p 8 [[X{ёx>9~ r|f{y*9\.j_XXY^ڲVoXZ^FELșcGl1˂<N Dai8D2 tc;w}=s}VǷg[? "Їھ-oYtʕh-.*666l6S2)hS _.fY`8+@Y(B ~ժ]YX8LP~j <'p2‡>VwTzl7nF̗YsaV j5mەSO4EI!^o}`yuayZ7n}x~~=C *o׷SKەWSO?ױxy:\D1=nՂX::Bp|;o~^ָY9nN | |}\fj_ʊz [YYVjR꘱Gq0CխrY9σR,DZ\߷v_vwdAT[;#=#>3l\Ņk~͛V66Wvv:[DVCل}&Bf[RJ86m?sX%4oބ[[[غ{_޽{KqiX[MtY}p\~oի?Uz&^]lll`}}=XU,u$G´T0gYQ=8PޅFKՐ;T.,sHF#}~Z?&O&kC)Ia/ .]׮WWnxem{X[_O <΃$eQc+T!jyڋ^u R8nv<܉\[~@nkW՛7o\n><_Z-tz,_O҄s;4} YS>0v?XjX[TL͔p3Uq P^GdUa8^4|k\1Ο+<W^-_q_)<3l x Oy1k߷yy#s׮_w~Y~ƍtLukca,{TUd\ v!6Z @RAŲ 7S`'.p{|p,+;nYۻxghK +yEvRfK*` !dvfx,_BL m]X@ɲ`W*XxE,o֏wr:XT'˛ׯOݼ6JH$_/kO*O U]") 餔_EM1QLN5PK=Sou<{_W~97s/-T*p!@)A85=pvZ jbĭp~t߼нg&|Lv?[^g_xyM͛X\\AD FQv^x]&y񤔘ݎ <6;!?q#cEI9sϱwM]q\ch>j.0V|[Dh]@7WnkJ׮;;vUhq#қ E*H 88/YvVO߆iyy8 QǥH vezúea@MDAwOo^[7~bl`[[_\yo_4 !EQ$y,<yfƻhL Pǟ)C\i>~1 h <ㇴZo<.z:߸!Di/I74pjQi&@y5-0wtdt  `ty@&EQ_[*M~"!0]m]OFE,GVm.-OX7mnmjqq0 1NSVyRJpSXGL3f<3it|<@b^V/HX2 0/<|\g3=2/wv~y{im ++XXX8AfrEj> T$ha"voFRU*ۄdYp+OıqJ7n`AգQq?U~㽇)y$[@makWo쭭+W$ItVnZy%4b*ٹOOc;ӤRSsHѲNc­E2Ӥկ)HcBB D1?{yw+| uOۅo6iyyjR Em22R;|~XMZhef0V|8fg¬v3x)|f|"VsNڵkX|p\Vva[[[?\Y-n( AR!0~EPqc0vٴM녚-lpk6&@T}8NAz3é_^Fs&! H)eVᯬ}*mmv:iPJ\\WV"JRZ7o!=yiWvJ e4|jwnOj2@3R(Gqt2ѽa#R:77S.;U.yEv6KKK?Jcibii mgYq|}WԦ#(; ~3ځdE0LZ0 DPP|LR35Jj&|^;pRAc{/8_6&(s/-/FR뺐RMB@<;+̴*_I)/3~8:m):{Ǧ_aPJ`3q=P&IzR"m—KPGZ M4emvn< [[:QQ*00LҝmfASyfvB.DJwu~X.%;=6;4@yΎeO{i$C^(ʇ|̸fZc$DML:kWv?g7sm6no...]cH")3 f12uk&yx\%0ñ=L/NA (+$INqL:68(f'0N!硼*kU2ց 403N ++*jc?~Ky2(Q̟d׽hQMtUƧLT/1S)$ACpAueKW`uK.S58$A@J%\)z>GsU/jRATJ1X3$7x3/]GM  KaEq %9$:lw]P02c" g'c5ԕ#Q"O#54B+) ;MO:TPi:qq'$SVMr*qR;#?Foj iE?.Ȥ2ima #hz 43 `[H*d:xo*Lpjuh̶o|) "WUjR(PT4A/D2nQ]Z\7In@HP$KpBW$I $j;\yWF" VYiYŶm\%EMG$Q{Ԅ <؊;΋'LIY(wٶ>/$ CqĉZ۸m6U~ڎCBC|f?C15c8Q=K#)Q]qiFJ&3H#nzr`H"~TdH V([e 6<}</fB 7py>->N0Pzfϲ,pA |<c:bpV0Vp)v<$fJV`$ZDpj,T"WNVP1lJoI$ӘD $d6;gmsXqE* vRi_"-<jig;+a,J̩D1գ%#\Mqdhnpahka2c RU-`eU.x<[$Dy`!3 23 DU&U*3 ytTuE(_"U$ji'e.`. ,o<`ƍrvuPg~I)3R{EW*Lg>x}OR>RJ CL& aoNG}9 0 7qme&m{{S`nVSf"IӼIU~]wi8UD74&l"V|/WʙAS&Z5 P#Lf'LE#S0Lrrp\`3y Gjv)yX{Bйy5{v0w[o#9x,"cw̺eךz5=n?y,!׮i4`~:v-1uAi􆥂cfH*t!%#ZJꗺ1DmòmXla%rTq]9V;f@ C͒?~yy?6iK9zJoYV|6t||;ヒo~x[}a4dH!eKլ{tA8 6w]Vbܶ6qBA 5  (RSvh "RJ:‘_"uLr*SHu2t$keL<0a.,f%YEh8lP Ӑ_( wֹiEF?m )e{[o|C텝nw<aBIR2K ù$n$)Ǔ}f88-qzu=l2@JH(p#3S]բ g (7 #RHu&hVORK)CX #:Or-ـT/@^=j`,[ٱ@`!_rρAgy%, ao|גϼj0 x#Pїlv G`$/bOZ}|||3 W>&EHua{bA (EC4 ܲ2v XըJed D Z@'URj?]Lԏ9rZSF0x{X; P|5M l~q`C퉽I$N@@ 3wI0éhx{K[;}{JukK j H2DrsZrJ&]-S\ #'t@Ǥ@O{Iz n۴ F2rqyPyȨЊ> ,,~y)Ul,5F~a~a !GPaVNXeCpK el}ӟn/Ǩlmm4N’` Io p]>Z!x@fu|yȊ3ڀ͞P /px|w'ɛ0dn#d͛U]⡔=tn߆z@

E|F`0dc0zn`UJႆ1o^ڊԦF&{XKS2_RS@z bE]>=Yߣe~&|dXDi$IFnA˓8`"5 )DGHkubn MAБreMSkF^R,艮))~XL8g B@***yʗ/rdE~fItn6y?&)LeY}( ?%#_O/"!CIK$R1L;~M#u)e rA̪4\Z'|aL 0Ql\pE*|au)ʛM2Dƹq} YTa ^-&k2ɡ Xj;2Rj}T%RΆ3)iTO HQÄ|Tylj)W!U< TXE3vP˚ ײ:JVz^o:P9&mw$_.VN,]y)Pc 8UX61zT"mDIyD:&|>0@kx @QP@j-py38ܴ5Ku] ,`_R@7c錡~ų_/L*6~uy: ڹ @{i@07hx1gᦲxL#|dYR@<(QsifEf(;<6?f-:uiO1B'dT*aeuUIENNN;NBU@2PoIT? eW\i.?,*`xrTI)8xY "E#Eȃ ;˙y],n@ MDm4b!fK]Mt]eaiu%I-˪}W-ht?('[*ZEڕ+mU ~_)xVƍ 쁾OR>F=*|t.eM#cꄄ5 G9IT hs)`p]QЖJ%,lZN#`{r)I(ڛ0'NQUb ܶ*ޘYm%w׼2J%s^ph4R$Q[jAĖvƑZ|E0 G%, <nj! ycoiLW$}M<0g9tE~y΋qDQVRf{IvM&!P*<4M-Xcss `4ZF6Ӧu V{lYp5毭;ےa1NxS>0j3NFr$I EE=`,W (TWHi"yYyw&ʥ !HRKRf:c-aq %QA"v1vUc:EşI0]T*T/|^<$ N&&L8>=`2@h ,&@97-Eg8TqHbضzkٮ~=8ABm2޹@B !éTR ?]&Z!>Fݮq={ Ao0.M< 38g-Oy?'$?$IڸDn8eLl$ )9CL fYRiJ%8ZU3%.A)t1ƹ01BDfSw0|{:8L) =TEWn9ϛy\eq*)U@:iՐA1xB(v!^&=m؞@>jn|𔆐m# CL}CBwp;N_,T- ~3Ëg;'-aX0ƲD1WwX#܄1>=K~'PH|G͈h2t8D/&t|w͕LL&t~+y=d|_sqy^4:# 1B; *2σ].nW"U"Qmo7 )x/L0@J9=RO'1t:ef(__QA̸Ywy*0SB.L^Hĩթ1pQZw]8 jUASģ~?m~;)_hQ&dt Cї{vv:Ng :+PQy 7PLH \EL`2P wxO[|_H6Z$Hm2rρV>2|sāzҸqcx|.@Fa<Cy86 ڌg:7->ל瀙jJhªu!0L<cPi8pu8ժh迮+]ƠAmI߇Iy!e70t:?h _QQA*|ss/ˇZs~)G0\Džm1]P؀|v^J䩷EYZUKA @FG#}"_dsw:ΏFd^Q; ?r&tn~y/q a j1K, 4QHE^PbTg˲`9Dch|2^S_ OF#91A:4aY tlP~ U>ϼ# hu}'auz<sq H H 9l߇hm6T*j^R"66\~;p$D7T29esF2~enqQV3A/|y<\yM.||k1y">gj_\$6I<{c  | >=DJ><9N@g.Yjgop0^JRB,`<ɛ/:g,[3]ń4MJ4LKe~?QJOQ{X D< z"5kI!2|ftT'*0}3OCv&`Y99jT|ό&43vScMtlq!Ԝ7? * R'9JMB څ ^U*az|nDV40U1a)F$v:~wDMv.1ffΕZ 0L~x-̴spk^p8Dm a. G#qГoB~k_}?u:FJ B-7_pOpZ IDAT9"_QS]2]Y=3 d2Am1\W)M[̈́<σXDEL&L&V.S^.)3-=yγd}jakkK_U0>/_vq]ny#`̇ HhT@;w[-[ǢmqfYG#L}hyVL/|S?8xy5 pz&&@<\y >)%* VVV0NQױZ,Kצ+B^na@$ !l6vԤ@BA #׿IN>3v]̠ǀj #u(I{x+(Z%=:w;;A? v] @=>dYz(>IQĄ4ʋ8S>޽Ź}fۨj=}}ݻx7qttYs~z[J5&Hjb4%8ađ#fC aP5Q1l6rsuخzYѰ`&|)pKBP4RJnu͘0q^1sx t_βKկ~U~͛stNP՘hi5ȘH9{ pq#8::qm{""MzuF*OSL&t:Z-0yL&{#Yz{Ω˩{Wwu;;zlDXB@@d@DBqE !N$' V@6PDovwf{ݫN[ꚞ_zurtg vww e f NJݿ(Rj3?2ZD٤Pa͙,IH\x6#&fh:TaAi!8nH|_5Cו!×Bݓ~xS⪰*^W{ki3$e4hhrp82NsBiJ%&N* R)Rk}q*Ĺ à^s̙\z8 A;BBLDl+{/2Lz=|n`w:ruCF/gosӃJJ5`AI|_,u vv888׳,؇]~0nA k{꩟J JtrXTs,"MՄe ZʀA8DFXVBV\.qnfwwtzWR&vFACLQvf$F j_ G9MT,jSO?nKt$ !' UojWW)60;E!h!_O; Pog`^n6IjE>I*1FdBW}?ۇIЃ'?`xx[zgj8IՏm>QδvҒS\e4?|I|L&ܹh4<|ߧ͛3.ʼbmm/㏳IR\.Bȫ%kǤfJR Ȓd"M mmq駱ҔqZE'B=p:ep=<**ָxKj{xƲxve͋)@] t$fG, ><@^xKOf *JnqT*ɲ[\ifAl6c2ihgcQ n^~`p;|:N8Uqљ4U,ː,e/\sϱ 1cƨ8iHQᙣnWZg3ƣí `GJ<@eX:,y"us( 6'^n${#f4<]?2+\Hg4}^ \F5GKC>*IT x!V\~խ-BjZU(B8n|У5y!_"y&|~k~ o r|ƍ?m2ɲUժvD^?!94tkV̲@F({q?ksjjX[[ *v;AcVk F]&(XNT׉&\ (wcѶqf< X}.pU~jR,8aj>a'QwhDL$QkQAvFvpǥ}"M 08m\fYFXKtdssbHϫI4,U봔ՒVU"5,ˢZX^}dVDeZeIOƷxxF.F'.̯Mj,)+ʭf:V R,35,# Ts{yj^e[Q܂sDUB\4key4UPZKYv4MutpMӖƢ5Msߥ%NMs,>6Mkj{mm ۶9w\|F0^JRU*T:aPt=}rYM*zyVSv;Cf2MU.w:%Hx~./E %/NC х(aS)ɷIk Iz(DX\R8)FlޜLؖRކt%O~XxG p֭?~'U]&l:lEV˽cСMBo|rbÂss%|0d4Umx7L{=U1ʽ0o@w /U;wh0rE:sNq:Z-<&" Ei,^~턔R, 4 n잧шhD舽 ඔQ\w o9t:/4'fk eu$ Z8s)VZMj,fY-,?6 'TݟjK/_mijV81}9Ny%;g.ujz7MGejܐr+}y7yNVeTZ|AVK@)enY\ Pi0Tzw4nv' #)CoS{vY$9z^Wߞ9'ZGGk+++tYYYauuVu6ԩ6.lɸxK&Z% ˽ 8>Οz̆C[jT:d nïk'#I@@Ə= r86#">yuKk/4pD[Ev@si ͷO)Y\yp4_Z18(~A:ht *G4)gWVK}c|4<9 ZMVV4ͼJKbQj2.btzhEHd=r-_wTa#G{7IUThZnE`umFAjܱ$\&-E.Q;!R),S[(ȒDdD* sfjSg8dlUmDM%;~#WݻۅIku[qlG tju1EVZQ7):@VZE/j-d{ǣ礔B?(G4) 3RN^XʴM>-}ϓ3 qS䤯$^!|9zF#`~єDg2j~Z*jؕJӫK+5C{:1MUKjQ6{+ıId)=,U;dNKyܶ |w6ÉcIXJ gʱ}վhm]"%ͽ|j?mTUs^"jFm۔:vZ`'1a^,p݌ T>r]{/U d g 1 ^tXJ)G 9M!a7Tǧ'FYw42R~% 'ɲ{7[İm[T*J(6y~a^oYpыքG-)5ܸ3 (EҴнq4V8&MXMv@J4AIWmkM!=bn;|5k[0Qw 5qϴۏٶÕzLzU(\(JrҼZXi[qQ2.s1%Fm°@d7q-$!ISBT?;?i.d!d$r^)|+vq+Ge ;Vma|X,۶ڶmE^W(PP(0)E !ä,+'IDATe,BRdeٍ0 Ap͟K"ne|nf0}w<5F6__jjRrz4-03MeYVղ,Ӵ,1WBT@Ȩ2*TõJDVUf0`@BB{ S8Ja;2>{R)CЛƽ;F*֋B,4.$i~[0BPBX!2.FKL쐬?$]FSf00rw]|w(#%xm-IENDB`FRAMd{Z IHDRg- IDATx^Y$I~ǑwVe]]==sZb! -a40DH (I#L2Qd'Q"%2i fD7K`ݹvv{;+]HOȬk阌#"2HGRZl,% XvU hX@%> DB%QF}(sTp`c$8.F^Sk$@Gx&oz[\rzfrceB\.W*\2TBTBQTP,Q.iU/^JV^_\&[[[l6jP*PV ˲΄IT% n, %׾}*"GG|LJ{zwbpx6ʻ~@ 11Bn:2IVS*wϯڝ~;B89^?:k} p,6//,//lnZ˫l}sכMPJs:pǡ6Ҙe}XZEqy"Fm6Ywܣ;w7[F__H?P pe}õ ~\][ Qױ3zJyJ! camwإƉ(Bn`nnlKÇF/J?Oӧ2 ~llm-KK|imh4P.]X p a!#n{__W͛a|\JF-s>u^Pxך/~qckl\u0* lS4IORudb[ŢZ<^B,DZ\߷jvk_swhaO/:n?Q}Jo\K~ʵkח׋[@RA^}Ң[oyZOE*Z_ZEuk67y.nᰰ, :N> }j._xnn.^.aggX[[:zK? yy𝒖lV'L91!wU*]X@ Xe!\*'oF})/IOTɀ"x].]/\Vqqu xynn? y9/xt_2bOr_՛7Kwh?Q}5ŋ?~ڵ+/k/WRbv{,g)!~'I~̥R98STߋ^~wm{W -𶹟C[@h_z鯬nn6ֶ͝\2j|fA8 'ѬcIU=b'˶8\U͌uXc1)-q/=>05 `s>^|ڵ_/ x"VWWQTn9N̸ )xd=7!"66wv{ g Qt ~nLL<)!0ۤ[rO< fYh\"6{}4_~KJ1<,s>\|ٹ +=\<1yz}xg|xuЧ*zkKsz8'}Kn۰+pR %˂p菁8q@^?}=s,nylmme@[8OGr*^_s0G2IJ`ϓB 0npP,إ^yb?գ_-*qLR)8"|*،Ru<z93ؽ4=}7s*j5VVP){#JgQ?*xɲ6j6X]_"r KZPo$=S^J,ɳ]=PRc{WFe۶ fplm82X}"ww|0e|J:C@c/;W]c_EALLWΊӣ4+YvǚqN?xr x5Qr\ch>*''x\>1T'Sw2P-+WKKm\t *8E0gu>(/-';;K.^ö Qe !u`@i\0"q|*mzyy9p&D.>T8luuk WZ EGdG'v--Z?ëֵ^bh4pq# C .)*)%8YQgQYҏaOӌ~^9Ԥ,;j}Zb4)hyR$U,__,l#Q׊?ί'peeO^`VW8! 3-yndBB* |41UO{=Jڧ%۪iGթjPLuLJfmSkPrk6 /VoEwsN* ?}^~[[[h4<Qa4MxM4B Ȟ;%T7,ߴ$UL<9= A_4= K $ ^cv-s?>Tslmll|TU8u878gʽn&0Z{kV|:N@lf}/_ۅ Fؤo/!f9!0(z<&Xya4uq>GՕw, !<NϦ/>P5PSrR6lׅ^`I_/>~+~lŋVVXke , ILw$BuyԞx۶uuqiR烐 =,O|S~l|"to#LC&jV1RA k7nԿ$^ fz,__\οm_U4MAp O%tgؤc<vJ\)d6K@3PP鎨O1(~~Rs>}]K2I, BJؾ+rMokw[t%dGgkhŲ~rysxta8yTQ酧'^5F$IyL͋˓#%Ne7e%)TuSzN }ey:O|I 16ugo3|i D`پ >rA&%XPq]H)Y7? p[fUpcsO՗s}sfѽ^s؅ !蓤3ɋ&qfulvLGOw yH-lpk6x >Eg(R͂OJ0,,/TUK~"8,82e4/^d;ͦu1 suneSEqy-..P(dN|^Y"(&)|)pL]KSET'7Y lN \O3O窂_moa}ZŖWVj`48OjY5S\^yҝځs6+& H 0M9߼6_*ݡTͧ7(wcm}q ۥj[[X{Q,s7YR^ [[zki \Ug=_jsyq(yr*u'e1R(,z.up4RL`LP<[όKPGJՍ VWeuu/濶ETU  F6`ͰYrVxS䆀:- uv6dUq8YO5|he4KLh?_ڏV+m Ѹv vZ| yrNNjZg:[GX\\D%va!Ig,9M^.=IN9RfJz'}\Y3L96OJA (edN'q4q<|";)x $<V (%s M:`bT*0Ʋ9~TM-/I$GOs>N:-tY7ŧ맠MCke2|*gR VWFA!ߙdhj׋+:_XX@\c @0YJwYbs;OgG`祛g|i<9)Ӏ"tw¥Wj|0Gjʾc$Ad<Ps먮`^G Xf|itmWWl:Fu %b2P}Va䅓ΊѾ>xeM,hHO}}֏oZͦPc Y|R%nQ,^*g b'G™m# CXQ8(//uV‡aCoKSl^+(o]O5Gz!ux0EPF?'t 8}|iARmh&xg$ `bj7n0ܶk}+slTi4^6j(JlKc^g㈀!"yt>i"OeYHz8K]r2x6KiRҧ瘁G 0ʟ;|H pH1ˀh[;9R2=L `\~lK Bc5O{=}tuf:Mf <=nVG1a`!  %zDs@yANOjk $Qm8:Sxbrk 0 K4q』FITBqq~D 8BkZ(d_jNpm]y?KM'^L[H$tّDImCA|)t=<2QUjR8PEw,탶)g;^>] %H]V}VZp]^p %Rn4U}L]y:og!Q碷ogCPǀHqXMg:4Uy D7^)f[/ݷ.^Z TW:vpt,5MeXu@.ȯ;>35RJ)(/Cxr8$p!'pUq:ㅀPm%I_'! !jj@ #H)bmRWk5>lΪ&*Iޥ)#h"Bs -OfGwRN\}2eYm;[L8I&tbq88H,d8D9d`y^6@m:5\r->|i8vQq$Axܲ` ]@OXrJXݴ?IRvHK4e:.fgu:8<>J'zࣦ~^LJEݖnWz=1Xu] lX2zlAXB"W1u bܚ^C <5,Xzř[%i(SMĪcr81e&8cĩe> vXؠ9y[fBw)y\=I~&Rɽi[?OUWR^c<|ŭ7p8$Fn5v؆ R3@?|D!xDcf"Hׁ`iBJnGI!˖D1kDmòmXlareJ7 `.s'v@P ٛpZpmvuzlFP~2i|2ttt;}o~⭷ߎpGR Z[XX.IE8iem@a;%خ D `>x[v9 :6!ISPdH&KQ:i$cM)<0a.,fY*%vq!ԡA0P 0 6o[W^~S1DRۍ7=v}ܹqC~oݰ}r2 0!v,Nh<8iW|.ݽq\I}YB@=l4RgPƣ~_A3fd|JT]jQ g( t'hRRLaeG"}#ܲ HKyM7uƦ``X 0 6p>tI96_r?˲!.q[o7Q O8BtTJi0Aj$k<Hp,r= C4abםlqV*1-'Kp%tЦLIխz7%Be~,@Zqr:.Nӗ<@Y0=軑1={p+vwwq|u<5 'P/a ^-áPTxv# SPG9[zYU&խ,mysmHpDZ-SZERzS =Km6=YtSrqyP&dThyBB 湟R*X3,5Laa^va}!PL.OJ )Ka1Q &YaI 0$ G@rԍB 9zx֞LS>AL* G" 4#㩱lLZ$50A3J̆vt|g@Mv:Q2?FBa > o0 juQpȉ,! jR>W/4R *.Xa DkaR4^}gqvhKI#)`,{%ũuh{ |iVsuE??U{҇1AL #FPկLGQMH; vEוsH/O5YUj##e)\H"w4cP[t٘ʛ=ײ-F {,#wO {RѾ Gb,"%XݶKd ;jeɵ"RĵGRȫBJH&n @M#r4zz& @OIzܲ:c@ F/< my )/L?i&\п cR$YՅ @ڴc8H dVYuVs˝$~u#w)(R $z:龧X'3I$6LØal*8T fq]ʓoZϓDyzGqP}VdTQQjSs,`"ue =ݖR9ci$ݟr|,rtH!iTkIL|瓊c8VSH`: "HTXyg3vP`fyiG:xw~-K,U*h4uc @ |U\ՈXeu,˲m(mc&r`LUgn&z[ Xi1}e)qtO<XvI" 9LxbJu3m޶.M"ҋιXPZ^Fo Vj8kC_q>>h T;p dCՑ]N9d z;ģzP3nY/e4z; |>Nq`4`$P/tQؤm02cB!]ʾR$'n u#5bP[uR6W+̎0(BF"Qc@zjT+ld|ُP/mB 6ַMGTfy {10q!ی/h!lۆj, /p !^ D_[Qaf%s8[(Yk˗WJ/"ؐ`C^qvclzz|)\u>Z>Nc{ǣ8c1p@(dE˄\[|>K2p@hiG/XT}u3]ׅeYh$IeYowwwKe} q|,LaWTZ5׽P*]Z;V0n=p&sMCDaVfbL WpI'bըGg9mK~Χq5H`> 7gmZL@h|lI'`"9`p]Qe ,-/\[n߮1VH]7v%2Ƕ YYXZD"D|x8B# T'$IV@SzrՓqVuˍQ0K10Dxփ邱fG,WWy[tyyblpQeլ=$QOF#!P(9&fj@$ID§j/܋掣K<9?.HԆ03|޶)s?9Ϫ\nBa!uƦ'Jړq޾F X I8*t5Iwfӕ 5U9}τp>Y/۪×!$ pǔ4WFaF%LzNXOwf@eCU8`O1{dl[5AoWxve(!HblW=b>R)Pm?o/7HRP0ĸD8ov=`[Va´pe<͊4M1kQIP 0Qs\E߇'c Gq\nYl"PpeX(m>OdЌ10`A"ӟpph4bTxBL?L|yz~mS1r>s溃Ez&IT\Pw}kGOi']t}]=)p3_ ,- am2m.IԳ>0 _]"4!mK)AY%V*B!)GϞ106i^D>:A I|;o_?0?E v>xgsF+2WǙD" 8cwQSU/T7a.D L{B|Pߓx_4a⡔r=ŝ h$LoOOew1g-'$*U& ~R`s![jr]a gLmD$Hhx6 Coʥvn5[-d@fA?+4nV8 %rCnf2PpFw]¶UDžqP_QC0QWLQ2πv>>9@Xi( p4~̗ v?9! BnCz=>o[>cZJLƦa,uζma0 <ӷi/t\8~im8[HC$EE~ s498& |Ա  ._>О!?|-q7z[B4Z nTR-5+bAO!| Ww?6:8" _WLp;;9ONNry H&~^3LL3?:L|ǢuӁ!L4>Qa L*-(4තxPwJ<eYxnc 2e n^~ݝN l^0y1ǛyیMW&p'\tO]RvR^z_? j)jE;#z=x)x"Ԁ'I!Dݮ|z;f\>>rP@ՂSbڄ@1h8jQ87EaMRк1;!B{F1NmK`cP)qV4I!PBQ؀S*0>: 7dTM\bv]X$˃nwDt `fY,V׳{TA͂bVx67 utu`(=mQ?F "|vtr,I&rCG9*j|Ew7Ҏ +U[2sՏA15b`Q0> /yt ௾?^B^ (# u02ƦxNab<#)@L|γ ˲P.QP(:I0#-HԬ$fwR[YQU`yMo7Ͼ˜1cAÇ8_ot t:e۵>*a69Д "jT899ACFf@fF@u],--M c5Pΐ!(AZH ) w+S$BJAh3,8s5Çǃppppm`$s[ˣkXĥKf}-@AFyw`ƥ`j&zQ-js|NZ r~-'Et O"f׆} #vn >BaA p.%6tGT}},`ѶV,VJXSmç٬)~#< pH?f_zÇ?WU4 f@2is>=>cᅬcaNwd*3OTBE(J`\.caa!;63jIDAT]vqp^@gXGn 33e9H9;<)ш"lFvq})%J1QV8c+p8`0@A P]G0I}^AL1>|~oȌ"]nuWP )al`H4Q`=` og>hA}Ń۷ŝ `来Gsi:q9t!!ӥCyEw+l6j6PzˢHvB1 ~8<<~vW(qpp7o߸2^ p&bP-BѴ*ԟ"o0^Ri $nAA~rHMlx1Ɣ mD!@4~>Py.=2 p?|[E *X*DZ7wxqC|G^*Jvn7mݻpxxi GKhB&>|7oč7bQq3*cp;*<͠&j^Voqh7w`I C `0%\jc8D y|ۯ];ßpŅR|G̪ATD;V-Y~xn޼{!ԋ4f+++hZX^^1F6c<RJFqD'syat:`0aboo.>ܿ@lR `L x`Pf骗C9Bs}.bEm,|xk8@UZ0ku:(J\Hh Bt+ׅH#܍"y_Mlg{{jDJ/JX\\2xf<n{.nܸ;w ՛ bvgZNQvݬ' N~cBNuK$8>> G7f4x7q W!5* ^8P/_w|.sjVL(7@(9D8^ܲjcT=A1Ǹr"nI{4F4?72ή>fw c2X@kɲHka2e-vaȋe>maj3{tuיwFd72*zgggG eVYUO<Bd`FCmZP zԾף07S CIMf hjd>?_#OAQnOI,LӤT*ضmAjVQ׶mܹCc2yҨ+BP("RZ(?.'Q\NMK(ul`@&FjI}0Cm:?;"ٌ>#a0~nD]&+i\*5ʵHjJXL\n1M KwR,|Ƕm!Ʉl)F /P~bPZf3yB(T*j5*rB@EXEݻG>O}|;1BWbJ"JY.&082A,bTVW e=k5RRE}u'Pi߇PF.?oK<ˢ{tķl[0S= 7wwdkks'f>jR?JN~$XJjp41NSs(JTٴ Tu])ٕ~ZVfIZ%c&5KG}{{{)!!XEAFfDZXJ YVկ ԊE&Z #?_EDt7L&L9e\j߈aIi!}(8Qn\W-4:>G}͏D@g<=! kBuV ]!1MOJ{ AJR5r&ǼL<9wL@}ۯ}~jp|jFEH~r*&!,H'}xٌh>0 L&ܽ{h8Kףﳷǭ[888`<CeX/^dssJBTnh4.jiiիt.\Gnn2-TJq0 sGDW ߲߻}<KR+ ɋ6;;my@@Z[IL{=wwir < ཋǃX?T*$N NPq<q67oDNCY3Ӿ#z} P… 鱶Nj5 \t%UmY_,I*?Bz/^dst~KEQ Fg]8NG#l۞=) ggesg:k Q.i d1|ˇ_n_}+W~<0_W\*!PjAeHc} PPaJaI0 vv&Z\,Y__ܹs\rK.C"UC٤lh40 PMZ+a&zMvvvvLV /LY_FR  qjs#u`R+"xvvx‹Z<4"HU s|,߈hnLYݎ }s5}w||E2W3|̶/C+XmLj]r6Ppn>m86!ıڤF:ȸpΝcgg߫\.l6YYYH#q ;j5v/^dkkrav-w)4$ Pru P)1Qjb(wPf:g_AB&j]:$B(˩xL ݓx=Cr6wJ@oܸ{6I~~}꺝xnu5B+6Ihx,//^̙3fqHx}NB¢jESΟӯxy\>u|r snmj}Ušڊ‡x.zl^{t׃@ހ/o̿cc' o嗣$ZZ.'COb,oe02XYMS+>Gbuu5%+++t:BWVV) zٳuDtsA'ǂL&o559j̵k'?Zdq0W ڿC$BdDhHz=h1>? 0*ϑ$XJ,HaZлJZZ*>GVcbc]Z+uZ['K҉& EV~?p4t?<>,u<ҟ? 0Bl"N&,͏ P,(ܤKT77)ol+Ti4_\RZϭFL]y]nFo{f {F3gZTz1o'a4FYe>a4MΝ;wO:J]1 ߉zNCZMXVWWt/"t:*ʜx$ps<|Pɺ *2U_tlo8ٳM@Pg¼j:ŜNy(I\pȠfq|>C\(|JJ>%mN6$I( iNlnnR(t:y5鲇VBAiiNVZMV)),5LӤZ*똦&_˗95QN;4 ˩,`35TYU2ΝcccWrHv]R 0F\ݷ^xARIM*fQ(Քi+c5Op2IqjE8i9vFo$|xcwwۮʲ18NXr(NURI,ٖ>uIrˊ;__RJ666& C._'r raqA!8Op5a*eεO$JJ)I2^ ry2`2 , o<&tnA;U+> o\aw*b1"njuzF$ X&2iN#`tCO.Si&#\v$I8{,OǧW@oA |HE"/#e>C"mw8>Vbz\.I$#$ =xa,eHyM!HXH ƷnKν~s+,l6n8VNA?VD}_fIɗU@P&a>4I|?qmu g3"Qij,f>Czl;g, pko߳-M]8D c1eALs]&'Ã-tdz'Cp 5 PFJԎKm[FtޚLؕRށxoGO#sPxx?~˿"o(ZZpfjVj4:UZ$8LV O}<2@cNsw%vt0d`ex3Xшe}oBЇ~#&''N@ q~j4|9_fk ۶Y[_j!-U5$)Yidot<!-i.6ho2QCfc=;R=8 |vֵ?Q<5o_:js2WtfbFEj]Gنm&5YV疕1,N{쁘_ #ANE.xL8kkۊl<p śa܅df|Ճ>ז?I!aw+d_I_Rny+F#jm^q98Y6[&#!)Z(L:]>KBky_qptt;2G#ƳYrc)#pyb$:z^:ߜZ7W6kmVVVhZ'|CP6fS6Y2fo#W28\rЊED.j=oq;|1z1#P" f>~u _=OJj 0~8_fxޥ8 q@xKcR:J>?"Ke%ԏgq9R 4%E"奌c'cչ+uЦ֛N ߗmcϓq  !J<8-϶]G}h0xn8hufvPPͮY,Ag>.LXx^K4ysh&W.f3ef'Dz68I>$=,pgˇ_UcSl4/+f#'ZF*F0 ji`IL*8]NCD|$M a##0ltK'6) $L*Z{8dMmDM%[co_.TCC@n/o|.,5L,\ŨZjFiHIfӮ?/9BWrlEϓ0ϋa`K~YOQTg֙!ubQp, ς Cv_Kí} 1kZZPX|T^r[ar-4ir)&XCy daMR]ďUz&|"2R;1 1Fj7O+It:M_h|~P,|Њd; 8'BԀB;@!2D@&'c j{a{훉`?G#zE%«xw{w$c|`i?B00o`KP3 \@z!Ћ8 ؍  TmiY582ke|9AuariB@F߇?X^X:`?'Y_}CK͊ozӼVvJg rVJ㺦[,V.ǭ|lۆm۰,k|e LLh" :M[&__FW<x @Ut0,p<n2BTz\VT*F\,r "j\.ZX,"8p'iT@)Gpxppv[%{c%FzeH`x~7[=MC&lbZV3zZmqJX̻JX.3P@P@uQ*Q,hӫ^yRrg* A(B)`p T񛂀%tJoo|l.--Uk]3*+7-XR'Dr, m'UN6t9 RJ!X!)sGid0Lp|w9<9a}o'{2}(1|61K7;v:o$|p090o__,m4ܜY2籰zfBr '`q.z#rW%̡cOý=6|G'z^ȣ(hC_{ߐ\j\kqs۫ssJQ(UlbzjJbR\ܹ }\ޟ SƮוrFJV:87Nﴇk'xWO瓎o΁|>Z/^vBښVx^Gs~=^~h,*_X4}DVCֽm ÛCkBo '\k_(/,|ʕ՗jVְTU4 ,PBVܲ- f"Z;8`w],F`Po >p2O4^U~u}}~ie%WˬhVX,&m|>`'R)/"9c0]m_6>/޽kw])W߻ 'X*7WWWi^e<,[Z^<.$Tq`rk5++c_[җڝ;ap +RGt7>q\j.Jsuo֯^zunaXr-,,`mm-`J%'.+` 0MՍ|^ǁl"W3ò uʊY쭣#p4ZߍC`-mEUz ]G?xƍ +++|~y-T*ZuD>nXE9\NeYem ky҃W>0?֪Ϸ>|bϿj}_Z[+\qW76,//' ¿ .T%cR@ @s'50 ؍*/h0oV1z9w4ZK!?SsևWeyc㿸rkK%\]_r2L*yL#«);: S)'D'͛Br]t5[;pl?s1`tSKW7֯_n"_WՐt?MReIGHR OH!J!f8U*ϣXۿm>|ܗK!?o(pjڋ/榱+XXX@\NO,W؏Yi]JqiBʧjf e䗗ᮬ,Iiewa/p+#OE-k׮w>/WnիWR45e8YH=iBGM6ӖhB~WzyP^sউ\|ʊVc>a8^m`맂\/sūWW_מy>If1䢸_I#MY^$~Ix$(RU6c`nY/-!h[f/To]=@_}Dx⺯Էgyٛ7uUTթ鳳 hD74dM;3x!R&m6av&sssy]x|M!nX|dg[[O}ŕWgndW1x8 40i<6eNYJg E(h440E,?+GZ5joQnJ@kO ~͛{9uݤp,<fg,]pq_;!3~+;MF"!2deڟ) $c @0` h2^~ٰǿ+e9V?8|J^X/_]v' <  FBXZX'߬¼(VxݞJ/Y OCwB')8R>:x1ZZ0}G#!c96=`c|֍?}_{go`/P(9m!j_ၳR6 ?&i2M67a`\y|7!pk n ?6͛륗^q=w.}x7ED`Y<,\&~,𬴨 ~+`s0#LH91Pw6 ۆjR c)_NzL}= gE2U=]o)`Qt3T7,HT0a8r Cns|-!!pTG>Ə^Z\[_[[[XX\뺉y7*8R;k ݓPAyx.z*e7RX7M̽"B}h.p(8G +ׯW{neuk_v ׮_뺐REQf Ԣz!Y GH]2Hu:G2!HV*Oi66F0W~:~ CP9O z4we0zp`8Dk_ww? 5[@w: R}sǖ\1KK_X@рeYb+Qi@&=_"* ha"ߧ4 fEڍ2eB"i{ƧXnzy|7y3%EPj^xvMVqAh4MPWB`pz2JI"a0MSHE`zAJ we ٻw-!~zT Xj?X[]ŕssspPOHEiU[0ZBG !!V!<.X<# @|4acpMؕ 0K_*{1Vkۧ#pk~ӕ_̭\VmRNz#oJRB`3ASLaʲ)YiͲg.S=`6|YK+m75I!9}K)Lm]Zϳ/zvhG&3w"k..h0 DQ4E>#$<˝ړnfrUY(1+&gRN|S~l| 2K|P#3`J?e[}(5w#𵹹/,nm[˛ʕ+X\ZB^y͵+W0l&C.Qa<'U/VZ uxJ%4H9^DnΚ3M)ڴ.<Η::braW/&!0 \C~[sge{?RӸ0ju"j T.xMؤW&plYz8Z8{'{:Ʀf0o]do3)EK&X`QRAɶ!d_>8m&7fUpmm jem---%h7=B$!bёKCLqc(x)Msl)#w@T}0L&@h}OBUT=O#d@!a*.,~*۪׍u: Pr?Vsr\Rd"nDBj{>i^1zi9KNAƪS );Ap2{qXJtJX^]f>oOz6p*f󋍕*&[X\DلiSˬ0<վ˪jfr st%elzl0:h@'t$J@4&i%wV/P"5hPH/F6Z8I:PBf:_~aXwyC0 O*k@ne}_oϳJPKZ,7uH9,] gQ>MD⣲O!Eu~!2ՓB:n+ U*7\eζsp_[[Ӌ˘C\F.`0h4JvM*rOPWА T/8"K_F^O{'Mq4(ae| *j7n`js5 ~zivj:77R<CMXR,;(0 Gs"ḶB'YfN_RhC?OH^\FQt"כC_S'kB ǐQqo6QX\dbќ27 Lp`-..T*17 hY =~ju?MQeůO=F(9;OG)Me4p*rgjOqw~%3D0ܲP\X@,Z|J>|3ťz[*1XD!z?*œ$:#^D0]EPdEYK&kčM>3/v#%m`@LI(4iOj2OEඝ|`3_v7 iw 6_,j/k5* d R iQ@'Qx:@!pZٓ46tNH/!O\i#E2S<&ģ8DNuw>&>8AFB9UW"5&oq& }fW*($_߀"$jZGVEeAHC$ѡ,BuK0 X a)&!!!HU'TȢ+UkG~ D4{v uQl6mJ>_JZJ uaYCj]P4@dbz^,q!26]0 es4₦*qSdkALt[/S0I7?['.^ PSe*|er3x?W zba*((J@/%׉uN$_0 ydJCH /D8g"M"_BlTNI=!rrKcng0_~KPJ 4E 2x;wK f!UYJQLAL*TP1"?9 )dUf(ieB b )- v\Z&7pJͩן bcj-Mt,H^",宻esR}$S/:f&N,H9 9"  RS_H%1b ' H@D#d,Q8)‰8=pgJk"լB@FBn9pk X Y?:&+|;0! U=EQ4E4 Gvi&4?=]I6Z< IDATIA R 1ў_)ORk$$P"IE‰ʍ)\kgB> R"xpM>=J[!p9BJM0pzߜ" fr`L6!Nв0+|fg~P_LmrTi;@F06SXe Ai-fMG2&CB(V,䀌ۆD/2$cI(?EHr"D: Go6^OHB ir4<h7WH}Kzdt2"[,tp?UHJNBnD~ʿeYm;!iYЋHI/'GȚA2_,A0)b .)ՓquSIխQqi~iFXc2$&DF( Z'8Rt"a@jE@u7ǁm *I"mBo>mCGY~o# Bֳm{JT%!cA29,B>GXLkubJ2Id=wrMX4Dʍ :ZqįڄO(E F*Iv0:dڎD!P,ꈄ!,eir X9)B?xjH{YqTEo0i&GG v0PT`f2FēR=:~ H 2ΧLVHDDbrq&b2nE:GA~QP'a`63 4~X~z.7ӏ)U;HN,Jv9S {LfsȞKhM)%>FzNn%{ݮzc08mۨjlJ &TK))ѣ{=80ܶ'd"'jM:D:0^%(b$jd4Q<)&J,a~2IHSe l;eSg=]dP"Q4iɢTRoɹ=^ prrݝloHh8 s۲XZ5ss"s,,*O!Ӹ!pL""'2&j&2ڋ"cڑ}w|Hi=f-Q& ӄa̴, X 6mf|:tB{:IlިOǡ=Tf* 瓡cC|pěoFL*h8WWV( S:&mE!L33`0cu0M3Q>7L8M:‘?& (yB PyIZS=$s 4Y`Dާhvô,{t !҄۝u#+|􂤕" iÇ{boopb (*vfa"Rr$ipL Q e|JT]XŨ A)F2"XB8nrA0z#-{ B$"q!unz 8u;VƦ``X 0!!_PiL_#)'&Y0 nܽuK7 x~$ġ 5Ɲ`8<(^߯Js9h6aAf%i`(3 C1lm52HzDHN)qRuPJęzY90S}@eX tt2t84uˠP7R?Ըg!^wFї}?Іan1]Gس,nlZkkVaz[1HA" q< :rkH+*ZJȈVsRØyFj7 ቀ n D-J -6*tY>R*XKK}6N7 !8"`H){^N'ltWٱnŁ46Cj l[OFI ¸rT+c Qxz@2)'S'JDbVᏘIU,c%Ʌ\iB$mEjQgc*lHB2_PS@)҇&^x5,ť?@|2^Kū^/6hm?h@!<)e@۲E/AjMLY)T@)^()_/ HGJ-j0]&#rD%w<^>4EIaI9i+d3v3 N<auR zux@PB)2Q,M5yP0 bR03NFc PUqZmcZ*I%5w OPdpZKI4t;:Oͺ֑Nv2"~蜫rŞ5f@; Cj u!JsB.VTR\.@-Ur@J _HDژnʦOg)8\jte]iCq1 o5ҥqR1\.EF^8999lZT;p $?̡ _m{myy677XYI9aɧ^z C5L|R*ԫO]J+_S VuGA0گ(M0QP/tY2~dgalҶZ H1\.{koxs/Qvu AoU9ǹ+Ź|^Z-aaAҜN7t1]RjJH)[dܟ&M=GtaiETig{VYY׺V ]J} !AuaV^eBE8~=|Wփ 8}8̲,;Y\/- _(6K[[F5&3N7pAƘ:NGJGT>0w8! C9oAp "&AڜvåJb(R[/XRdW@0\\dQq0J'{{jLø v0jWԁ*8 "ښqIIYa]gܩl _'zD}`0HFIr9e,.. X, CS  um3;cYjkGsaI 5q&LO-E>|G`@t0K?t}`NτFc PKMSy!L&M4IiR1mu|/eM6'cZpD@"뺤)R}?doԍZ,bx NK)_/IQ@mX`8D @$A@=o*@y\P៧|iuNC v4l&FH E@<1Ҝ5Kτ36<(O4oLJ2]f>G|1Zx`C1@( 8  y_ |zTjP/rLۥϺN#O\H}_}K'`.ڤVR$t H|ԹS/jA-3S/\U_/MC$xn_G#HFQ4#o42荵mOX',:9teLJ?ȵtO&PLuaBF:g zf2D)ՋI0+ D>@DxqL|@|Z>.a_{v[)Up֑.x妻Y~κN#O:ݴ;ZK $49BqaHL<>jq)dZWc.BxG~×G#bz0hevE8O#Ju &A[TPW}x&s5(Prg8n9IR3q*-ȵt|,KOo(="]qQO7[#v.)Bo|K؄ v%D4`3 mD Q `d c`PSqQSY)|mC!ÓG cW=4_l^=P)eRI+Uui#.T:O40MM0&7MHfZG#${]Oyo< GߟҹNϲI3mV`R !)"E6+*BA jpWFO !f?:GG8"W29 w:nvqQ,O=L4ʗK+t^'eoO??e'YMSxPwJ"' x2W v[-=_` $w]~Nrd^0Dy҅ϺflMN7YHE'~!jwg=k2@& 0zpbA/ Pv8A \"O Pcoە{N!I@0 o|~1ˡluݩqڄ:k2:]F? cl2KA纝' Byٓ0cL_StgD4E0QX]U.0>>N 7'Dr"RN8i0, 20n?8.K/OM8㷙a|prjZMJ CmC 7쳮Ӎgu CuHYatL?,# F>RQnAC;1)窗1^L  0vq8dt^?6j5] @tA]ԎJGvZ$M \1fa(T*rh&D V\qqxG[" [?*H}Mt0n1jU{ % K&}T~g1pRk頻>!f:s ~:v~p3mVig]gs|tBǴ}ڎ/۶1???5<9n,e" "_.p#j }.SsY#u0ylllL=Nn;;;>61#6'Vю8F S}(w:V*pv>?93+x4!NG7GwGæq! {:9>n\7a>}&diIdzV w) u˲B)%2S|>(zY1޽[n@MM! tm\#Ӆ0$-`H>DHA} ~~C̙&yTeTQj6acm0Y"%"σ|hP|4 &p0?!fY\.V%iHk2Yʧa[xCjfH) xX,h$iS9Wncx'(ΙkyD&D!-SNYl5`pD-x(ӈ òTWf¸A_.` o5W_NN.!l[>$uYP ^LqqIHiIIDk{;_?; " dj5: ˲5t!IC'EV^-uw d'p ~7iaã10/64 aד`y!\_xtpr#V|>@4ND:O+]Hm$juQVR۸u֫pOrKzDCj5m r0.ܹ۷o>..1#w!w.MzK~ut#V>(Ju]dLuJ|c@nvvvp%Kj'ڶBTzz)t]7iyض0 v!" aYVFu*iаx "$[H%,@28adaY2Ƈ6څ l˖e >YZ{v鞦<##ޗoQQY=OLPdedDfe㹟vzMs%RmEG/T/(-,Pf}qL8D)mFL9Mz݈Z.!ĉt@yH:z҆o<D@׶uW²WA"6dH,KZ"1ᘈ1 t:PR6KKKz&Hm޽{Ʉ~ŠX,RYZZ^S.OH(p' 찻x<>VNբlvAt:4:f2-F"m.^ȵk׸qovDa2K4dց2e&̾p0 1GN9M!Xj4,,h9n|"+gRɼstϓ0᧻o|哯cxR78Fc?"F?f8.vzr}m;uŠr Tzvf3JV#gYV#~:[[[KlnnRTPJ1t%,!O0ggoקS;}Q׀W,KKomQ^ZE\H3'N]vvԛө>ᅨ\ J$jp5[sWI-ILFщq6jP(ut]z6!ŋӭnSVKyI57:S,Sw^~eX\\D)m;N&YE) Lcӡ/{8dw2D)msxxHӡEzRT*v)aD1,,,@$HbcJXE`}}-nܸ۷Y^^X,zTp86`PAOj~kaH/IE/qqXyYn [[VJKD0HC.Bҩ;g0`ϣ#u'I];;άv^{W^zgGGBAș43؃&xYydt t:TN&\MD/RcRd\xϳjzUTXXX`yy Tƍ\r :1|82 TNK1:=јΞ f} 2:}wvWWټyEq$Af$Bhɗד}&O'8!Cs% ?&[z^+l?FaԳ:j6۶8ܼO#;.7Qk:VD\n}}B/ֈGlKKK\|W_}+Wp9&ki-ǹ^ϣ=6p WWWk4ΟBҔRzq|lv15Y!_ CuF.v6ϝ_ww_T^zV)h4'$!I}emE)&p-mfi$"+++)766X^^j7H&6m) czE.]4 #V3- ^*V5ZXB-˶fY8*⧕R="Ir\NL&ZVj#"ŴTʄ@)Z?! KbQiHY#i Y:d h`YxtyyVWW,+ T߼yWrjŢnQcG8QkŸ."zUcBdrBLѠXR^\@mm*Ej|[9t%%cӷp:(zwwt0t_toMC͝Bl9* p>G/JHW4?Zݦh: Q 41G^F4^#8׹fWVVT*?5_΅ J !-эD^YYZEA[K*a%yD(=߃岞U/J\H^PH\3wJJT\xL4Ã;B<?y? /O&.O$McU*8>!vd'bG^kxK>{Rq%(ի㱶v"vF(u%NFA%O=Qr|p0=WrڑPAI Rj &g+BfJT.h?ML:C;a܁ІOu;b./|UKRT!H}o0OyҜE,鲛_HbQOFqRJ677Y]]Mm$9;jaI&4.( 5v/Z<5#J`ԱY,0 'o0`rp3p[q'?H@7 0m7')?I zq$=TzEgK>qJ`Y:aj|$e1 qdNjZN|_oRgB6d?>d}mw'uV=G|^/+U,k9PЅJ頵b<^0H#,iFyBeI? dg4>f3[ȳ (Jc|tC=h0 Lp}ƽGA8_P$C (䗗q4U$) CLU?gIJ@Ў!a4pXOr ]h2!<"!v]M>8Ow2w$څ<1~pw ߜryu]Vǩ$9f8-ӎ+udx'{A̶wӳU[o<&<`2a:tF(A2c1kPP pWxe: L^ޱrJȇJylχ|g)gÄTx^:2q}reY5˲y3,D.G>C@_RKA$ JJ' 2IDQq;ڋʊIENDB`FRAMd{Z IHDRg- IDATx^y%I~Ew_쮣{fڙ!R$Z-QkI2(R6E 6L lˆ iC!ɰd"4%@E4%˝}tOwWwU#%?TTfƝ_~| = Md l@V nu8, `G>pS? 12LYӲ>cpeW, yV.;a`9K(%af\b6A x- ÷ n )I;f:n49 7^,m׬|1s9#4Mض 4cg8lcH)!0D}<=/\wzޞ?ޞu_Ftߪ'`q7+y\*}GTTmVz\.c:ar*mض ˲, T/)e|G f3LG#Nb6lMFɨ?>><Fg;;U7-+-(7i۵Ze %t:4 mET*agAŰcW虌w a1~  M8$P/rjf\jJ j*J2rc۰m;¶Lsj }vxhG|o2i a=|x57vy?!` X* ?Rҕ+/4;ҥ 66x@{i Ȟ GNN$m!3PȇӒ0 3Oǻlpۍwv3!.oLo 1U:^VjmeVlqpFO cL08c@g?MnJf8/ØN>P~p<'6p.IM`sWڿv[\ZY[5*5(JmW(bDtSt`i ̶a_իl͛Fo٬xSʵ]ׁy%` qw+ii}fqeOU,l"σsO;]Y[<axWڗ߸Qt#X <nprqg77kNXtu:lllr |N19Q((#n#h0ò qښYC;n.l j&'[[?zڵ띵¥mVQ.Q8N|4h9\vk`W*ln67,_LrبOgI!vS?Q|.omaggkkkX]]zK/J>@w(pIK:t%H(% ZSx#sX4_㰕7}> N`tjV._׮m^r]{y^P(ďҍ8AJE$-AJ0B AB(%ȟqZU.c{͗_g?e/o~8>z:7F^<_]بno;;NJ+E$X\QÁۄDX #0U (Y[aY0-' |p gz8}1e`cʕʧ>{Ͻ"|2VVVP.̲' 鰏iELcch$~'] SnU*(jdYl141Jl^?| 8:`/Rm<1dc#&`TS?}ɶZx|vZM&DRT n0epbE@~8ę>гc@^x |G}{XylnnT%".jEY8Oy<7I: ɤTDiϓ^1pӄl"g0E4_|_4_ѯjEf[p6>v,^^rg>sO=5fbXZX'߹r,_\}k[[-vy{[[[TыڞP(RAƔ.jt/wN_y=,K < -VR˜|)8 zÊa`@5~woO&חw=NՍxƳ/XrBAZ~,}9nfE8:-^gyu1))6`&ᦑE>jS9|j7'#t-! pQ"Cdm%~y}k'/_.mlnt8Nz&FY G@~=/(yPq:,ER :xQ-B)MG0Aa:oY3~M}CzիWK@9 ztPE*/f{T0vѲaPfXd׿^ݿ_~ L?r^YRf ˲ D+QY*& m4'H䣅z"q'G=Nt")3dԥۄH)Dծ^juˇ]~݇|RH\}_&:<|t:MxPWB`7A"%hiJ.x_ǻ(6GE J+ =]Gg(_|$,c vv0׾ƞq3rüXYZtug׷sk.I)#^R&Lۆγϲug?Q K^e^^Fلa|@"}Yq:Y7Tg,948z&RS>}_M+d0_Dyk Gロ/>29l2LƲaZ?(\tZ-ē@]dj4t 1()lV4N ˂NEHgAC&\/4H :XJ"Y T4PݬR߇}0TH #];yfg |VVƆsjQ},%N*) ɦ#c4uDӑ;-O]pZ9X3mnOXb; /vT$UP#bsԟ~kxa84q]!Zχ^fSN'_klⅥO.hAۤ\Y'i8O,P#Yꄻ͗V>'${O|OaA7Mm4\AU ۩g x`gqZv<!fYjPވI"rw3O9,lP>~3'KOw2| qp20 uԮ^?;wr7nMR~ 5 ?sЩV?;˨(RMfMF]K7D| <,d <_b0)Eb惑H`aZEٶ!dW_V>x gzu,:\`+++ E7=B$!bіKCOqz`0xyZXN)N >EdH|RBx~qzZAnJ%8/FøƘ~|G87e.SViu:j! Na>+"A$$SJQ"!N'Ël>F' ?At2FшXJJJX]_v`Oz5p.v͵W6,/n42 NwY] ]tLaYiNd0uT}AOi0's0~B)^DԑnTl"yYrOf&V_|[7|c NW*+@nmsl/-jXxKW]M8-L;o|R"KWEx}HR.X'GRj(0V=)Gɗ =O>ruTWVa VZ:Tg}'WWjPT:7po(< RC@GHOʏ}TPCBdދ#i&҄|(_G1c `j_ik^}izܼRIvFcjM0YJChPN{X^D`~-B:~Sb"")+0NyD H(A )`0A!|veV/%s &O`SVSNZ^^F\c,^Go15]X]Ѳzd8-aeOu:E`g)_x mZYYOpfA).,-0uݗg<*`Z}j])jlT*1~&  ] YH( "QVi9c %Bu>''4SQ8ɟ&BσRKXvsx;<:B֖W N̜R a%t$q **w$,-Z*$!_ V*D HS8&퉹@-\Fq=ܶ!<0Ph4P[_Gm5_O(BWW/UuUx =I_EHGiKnDOԖsVd\)RG eR1"rm=Iyt?JD|H p]18 %_]ʶ?:,J/RXD. Pt҅M_GGꭿ]GdӻY"hØR@ZA[/ω$_ 14#T ;$BHjFOO$ytS^q*'Zt EZ-82U B5'Ok!vW(ģ_"$5jXGV/yeAFHC$ѡ/2Y$P=4 eSX~|!ۈI|B ,R(:xWxqAJө:aW*0vh6.y\ןV*pe%.zw^B7QuE aiBF.᧓)TR)<1•⤭`Qx-/ ۆY,"_e;O&O=gKFhT*0 uGz]t|D4:LD.i0'ʀ'dAh#)OBM"_LlTTNI=!R}P$启TPT[t?jo+R2q`f5=O_Yj̉A#"}B꦳H%kNՃ)/" 9RH DuG~G0!j\S.4c zZ7EV~15&`چ: RH,aYᄳ¥Tɔrx΋DEe L1>IA@JE }~rDxDZ,b 'eL8* GqS*F E8:Z+vUW!Jeo۹+. )O}E8oEJ/|O:ՅEqte]+=LIxj' % d< ȒXFcHb݄RH"v~,I=sR-ٟ |4/P.Xq:M)4Vj5۶s+D/F: >> YN8&+}V80' @?')0'iQmzzϲ,„,@@J"sKC$i[/ #QS:"ȩ+dtEcia!f3 FVC`W5s IDATN)9)X,ag~IDjiHhƗr)jED3 i.MNBT^uz@,0 eꜢMr]>@,pRQъAFr(&^-tp2vB iASroN " r90l6t dل8F¢YX&y %2dض\.wbywdR=cLRbqRuǺ^)^1A2 e7(2" DQ!)LJ 2eO>ma`birh׬WP}..Ed[wΊnp}ˆT˲`vL>4%"ӵTnNʏDDCc>Cu äɨ$h$hM"\@*GdˑI~QR .B?jt H 3]*`4MEtg;öxEL]N)O i=mNB P Lm #RL&8, BR)&.ĔRP}! 5 /zwEQ~ J&xBْ:H%/F' H$="ԊB0Hrf& !AW3W,V /2ӣE=4R8-iat~R*W 1)'LScz=F @.CZ'zljzxT  A.FPF0J$Q36_JMz=9W^}Ki!q=ܻs7_hN&@ra[jF2ٕgaAƿgYxDT!D Z*@s`D5rB䜜t^DXDHe"#B2V j#f:0D` 4a63-:/I\n۶mFȧC'IV,=OHS4K9zf.󩧣#C۸_dMSR jl/ap)rljmE!\׍@٨RJDЍ"XuRS-"PݪN:?*GFydRh?&AF?tݸk7W:mr3 iMӲn$IH'B: $v#+}t" nt]~}o=MƓB=S& °4{c;_ahCJ΁}r DQ]eDDQNX-ʈ JdDQ&|F[RKID'}H3iQ0 ;Rƒ]0lp8Osy V1p>r>mE@"a<Ǹ{^ Wx|4~uwB! ۊduݗ0|~Mfipbt(D HHHH9Vcd "[Ĩ ⑬*5Ӊ `'uT7CZWfvL{)U0"%AD4NjHA7N@mA*wBHDT KC*#2AD2ť0rTk=/O{@t=Ty17Mz Le3e hY۴#PNSR |HD~w~ !mPA0 Rʡz/ݻg---qSJRF!A4؏0zRv E &Q}Mx$l6(adɓ4Ҏɗ&!k?,脋%:'WW#1p2}8N'G$ߚ繽^",uッU( |)'T (j41B.35 ?!F*zBS@٨Bt` Pi 1 N' E/`ZS:Yar(Nz֝^?]f3C9s!kBu?[`?5JLn!TBJCD 2&$f>x [l:l$Fa8%c5 8?A@a. 78EJzlX2v e #7fa~!p#=˶0|!+oh{r_ TOD$!J(PsaD(DŽDDp<87 1 ZaF"PV-Rtx#daX7~>i7RA0c(ntc00rL0V2 t@JDhABJ$NR·lPtRת-Q Ed;1cs!gH nT=4YyӾZiOH~s4 e8Rrh|?9(AljJ(ڶy#80ۅz AuqRX4rEOi D*VM9u2"N< PxyR%V"Pcemɥg$A\'?@kj`\F`,E@ |deT*Kb,JJ">?IJH 09/D y/R&[Jm*wD@-LF5X|Äzw O^ 8٭Q4t?O:֑.䨓.:ymZEh4tvnAv8a`1T>uK+|Ꮑ|)>|BϛN6..7+M?+~V涝fa #\.{woؽwRqð7 PG^C5U/iTj F S&G$P-?q&R) #/RʇHv"1a4x 2P_nl8h".;4Gy/*3k?X#*"Ky4!Z#8 l6/a(^ ^zM<2B9,r-˲Vҕbsfse}gǨEdԚ?KrB$#=G:82@9/I@}]&ViwZiNO#\BX @APzwB̗Z=Εh, CnFxoi{AK)CU ϗvն7+u\]/uE zgdrLg)K # |i0n,ɥ z#G9iK'Z`")뺰mǤrXtPpVՌnU]8_΅{cee-7*U!BTƤ~jRx<ʗGfzA"Xb`Hcۄҧ;}=]_,061,˂q7;S"a:BZs[hm)3LUéYZE+tQ#z=s6]=!  'eG;E\=HT)Nt{5A_{ջ?zduG$))^6+ ,P8 C-w2h U#0`,1f}OqOBy'QtR ;בOiӎHC1,kR難cL L(8)OB=ncupa0=&QJy~}# ZUM2/c_$A@u\wl\JtOiׅu?6MFyj`B9W#jʗ glygi>n)/0`qP9AE/3c&S Ld`67q( B|sz['Նqm/q|N'%A0v29@$Tue)E^,V4> /"yo:, e1=I@K$tSX;zOX',:9?$c: Oġ.uoɎ3Mݮ$"GlDQ !#OB`=9|E` PCl0ד Ч'8JenՋa'Eaz4M>/M&2G,kØOӐPuHN%WQ5("O'c`!?Ahay7gɋ锑R |4Ku?}&l642! c'wQͧit%b>Ph|PiN1 p_J9~nNq/@pG#  ]7*?59\L75tZ9֑o[|i6^:#1':r2m~ :g)1`'Mb06' ccx1 Nztt7Bǣ4zNsU:Ӿ(</ax$"G -ro.R+"N x:̪"0M'R'T3l"ǘc4 zCCXHxж__J9m3 I]4/+\GV-jTO74$^Z.o󏍛Lh|(oE!LK!'"|| x8E:]7zLc90С7Dj0=4T<ӎ.U5=Ba>C?YnjEF#eE~-mR'| WO?&.8=R29dɰד^81_aI*VӜ^N&"RP:NE>J>1MvA"S4se cv J%q*߹yso:h8~8^!zid5gSqY4ydkd5׍A!a"z; =x#$?vmn8Nb^4P/arjOclu?=~S16M~O~z9|1}Liu">mMS4ӄ" e!W.ß͔JyFjhM\`ômu=x ܖ]_zL`nZ?+5!u7t< H'N8M4:DG*0 08eyUh>ھH8W 15bx`#@_Iq&WOɗJ/7u 8@)!PcrѾyI7*M󸴙aJ*r\MRz\`N4ZY G ҐRbw^dĤw]@J'i0kzۋL)3H~q+w kd:$ LGp00Gʓ2m~HM:""jzvvz=tB۴ڏ>/۶d׀.>1L0 oYv{Mt{-Le~BpLymAa6"2 \N30q+o/ZpVP* ؅Hƀy? a(E 8ǭ,;~=6s,~~2㣣vqa9-Bqi'@ō7pm&,&X־/"T*`L B|fǘfy&{=GSn8W*7+F*/{XB<4ypibP@RAui vV0lÏP U/R"t]FGG7.Nh/-¹ 8p߿c̲xRA^ @]"䲔O<믿wyxzxWJn=)87~/4_,`d۶̕[zÝEW+)/".)3-=it}^cccaƋeax}ܹs7o۷qݸ%_4UTrO!ydD1m .۷Qw]8: G#``VV_ӴW4ygv3PQ4MK ! >/]B^.pY]t[mFoL_L] ?>v~ǁeY:$ӡFuQT%"`>2zn7h4vNWinzyDa:&9$%B`6sNx}xp:8(Jt:q>ҵv6ru-0Gue p}ݺ7&TP*8º >r"  5EsvV c)GGrW-dg뭻T}R씊EZHe^=MN>D`0p}vlS mlnn H>4Ƣ(Dct[nk_}b0q4Mlnn0 ܻwn?, Fjivt Ma [x}M?ҫbttj#!0 j` RJ&c,WdC.&c7 _ N{f8џ&iY~Posu,fPe\bOeY!!<uۤBp[n~ RJ8Jf5# Că À ap`<^ #E~10DRAZET;n(h2Vۈ ?ý=} ~Bxhk?uߪW BX,"ņnO$;MtpcВL}˲P(gD@ 8Wm(qǘR@qP*P,Q(`6 `0j;Lppp;w,f3ݻwq||F[[[X]]˗1qƍ0豖bɨ@f3GVCBlDjaXj/l0=>};~ypVOŻ~觋ժeYjZlGXQ$15J%Pn"|>r+ٟXǛNF#ZW*j5TUEa~_}Kt]GGG{nLcܻw7Q\IO)+a E7a$f&>FxJ8F9'Sy  NՋFro<~~9x$;]c}1귈I-h$iji,̉8Nq||`0Ą"r9TUxtjwxx?.nܸnȋsr8r qxxw1d]DdyUVf]]Gmwuu{zhX<^,/–,H%$@2dZd@XF! KȋWlYX+ /{;WuםwFf|Q3;|ա3"e硫vNCQѠV͍7~z~ړ4M۶Y\\^S(NzI-vUÇB[GoX.)7XSeo0 M(b||Lcm!}ugڙvk_ukׯtlk(Tn8mZe@8C=QQ(V,..RV)J'7"& nCvvve48i*Gaii5&zvm@9&nj4XE"///syvFnxLG#w8{'aϵo;go|՟jMM6ضT5 aF:)ÛL&}: (Oitv'l@MϧrjU*qљ$Q9]}2?B!UK.+I@Je;:ډ&0D>E0}K#TPZisŷ_& S(t&_woO$GB]+oտ#FIrVva?Z u% Tqj^/C)zDJ !v 9>>(RפT"+++={mR$*bXXX`aazi*JM ˲jɵk׸y&VBV~?0c'v]Bˏ V(}FRJuZf3AбV`0H oMs677ؠVϫTԔrd&,bcfہLY@u] |ۅ vs>15Iɲ@viT(Jc~vH @1a eA{ ?&Y{ F/QKDJcyy&4Q*,K$BZzĝ8>;>1F;;ΜRt3o ӴiUYًUmB?"K<8hbkoV*u$/|;j5&J%fYZZbkk7oBL-r9:Ν;a0@l`&k"eJZIQؠ0Hy0Mrx5cY#!=qG;qm>s$ .>%2̙8f34 BZ*C kkk fzZ U:Zi5Y|<9a* V+-,+ T_~˗/s9* 3UթG:<@M˴2W QFŷ} J TVWWV(4X2R $銚BZ4uIM8e:a߇qpyws% ;;kf0iYywTPZ_b*D_ej+;\M#9siԤ#8Sf=l/--avZzΝ;Vl.PyiirD:q=U6$ح&W˶1 ժR|>reO2$*;ľ?[ãӡp1_Cv!O1x}FRʅ ˗/.a/T%r:oΙ< rtb31C{e3`B(ʙ@JDK!U,O&-h?.1C[a܂pB@~4M;bDZy^:&H}1OyҜF,鲛>Si:#\v !6m_ &OH@D}Eș!e> z8֋F x^h$ߊd\k E^ 70 ;ԝ񘵵5 C0 圄aH>/hAm0#iz4Qx{ϵST,Y__gii RY]R'I- )4$ `qB l Ce1 PC`@88v􎏹8.&j}|3 % ^u:? i޲Z&*R+lFY4-[EJ)  ]q=h2!v]EшI>m$څ w<~}/^P{hƞݮ"Qi4=2}$\n mY})OWK8ɾ~A8V!ɄPzxّR>b1c(u˿,o8^F;Q tZޱrJȇ*i'QŘ+祍!ш`8$ p]Q͸x4{A݁V?7_8wjSnKax2Yp啕N{Z uP0dIɒ?m{{>@R@4 ( t 6piL}}J)υޞ3_Y3@+1Y^&cjZ=|~VpI,amye~?^{7ȩ'? z{`@4!q`@g_vG#ފ"L|xÇ4xiqn,")yF^Osj5-DwNy͓YkFoM!T[*^uqw1q}xɑ>~srrY'^:v֛;vWGGK,Hբh MSڴ dɘ?F|dOm& =cymƽn`XMT:xs27NR$~w M'JCJ]8 O[tOm^ Yv xsf%~MAJ"N@K)T+;tcBeHq$I@҇p}LZ/%^jt:#O<T۽vKjh,.R^{Z-UBa2kŒx=wn4濟ՏfsI0r%[$ l!1 ]ν{>hq>GB6#&-_uԼ/=5^/b;OVf4:%:QQVӋI8O*8]NCD|nY%l`w= Ɩ HI pz=t>/Fpotjݽ jc?W&]Ռ~cTU**$%]g dYCu01k=v>t>f$?O$AXyQl!DؑU9(ŋ&f_ K`|+Pcm?򿄞]pZmRQVtN./U9|G+I\Pu~B̪Y-5ċ MÑ`2)q\B<]i7cxb 1_ D qbY0 ӬQahc0 CJ)2BP 1Rj]Ȳ?2 0 a})壼mݻ6#|>[ekvIENDB`FRAMd{Z IHDRg- IDATx^i$Iz<̌+3陝K\IA@$@@$H$L!DLH4 @  .vwݹg{z3.w"<"^WF/!LCH4p`&P7" |EqFHI?,&j h]1-˶4m˺jv._( ϣະs98׋|/ /Qt'7* Xr[ՊX.X*]6zV. y׵Rɴs9.q8۶'g6!Db @E $x8 ~s99x0~?~3|!$ XJ+ZjZ5RlU*V,X^gJz\R ||>eMU@!$G8pxpp)ݮAnzzGoANoe]-˯U?YZ_\T( nQTXXDXDuQ.Q(P*W6a$MaS6Qs.0y<`0h4`0x<`0p0ðNzh8x`xzxawȾg~n0:=P%u2wh|WZ]ZZug4+4[,R|-m84*Tҩf'1 R(#F#Ctm1DwOOQ^pl=avI~X0oU*7?WFU5Vmn-//c~~ CBXDRA>`y.>)p>B}WPNuApMs^fsniy٪Zlum XYYAVCр fFЍA$T!@'Q P"W@/ CW'}&` pZkZ_]vVVVrs25(JI߮P(;Y 2`, |Ubct`qw<.b|J%` Wsϱe,.-h 'im^2L,`S&d+n_ܩc`kpoz:.Z.Jku]]‚x[XXZ2(godț+&# @qm ym:kVWV׾lnk/n=gOU5?ָr凯mmXXY)\0旗*2j\MY.ʳFOΰm[-ԶT*ֶ;_sX? ܞSCBU^˗pimxyk \&VVV ,&*aHp\Xr"qgA@d.} рh⋈,1}X*o7lR_+do}=s^,+WK׮^h.-: d"^VODχYul4abиqsخ˖ܱww`qw+< gJ@˗W͛bLzB,4AJE$5/A15ȌQIjvn4^}+],o[}7rxy|O[Jlׁ\\y//՗76̵M\Z_*J|*IW60=-'TAE!OΙam1QX^ӶM&iٶu/>|wpM[I$f>_?\g/\zEŗ_f/_ĒYdAw{҄ԡGÄ;wA7>g_\;ũaYU*(jdl163# ]*pj%?| __x?xrҵk#'UrQ<_b|ҽHOHUԍ0MrJ(,,?d/Bm}Oh#:`V]yݸ,+X]]EVX>UEOly0, p0D M -fVw79ONOрOF-Ϳq3r} vi}q϶mi I(G++_:'~BBGB(hȲo`JX#vBfx=<t<p0Mzƍ&yu݉M.*v}.p6N& YOKЉ+\u:,8r XD|eگUx\kST§>Y/^]zݼ׍[[lum FbdJ*<<=nssth'!X8iLjy>~шX +0xBxjpmͭ˯=s[[ŗ^" =CTx* x$yYH (pH@\v\"Ţ xn\ PZ6*,UpQՙ55qwb٧+!a5/F,LV0À#W?<46dDG>J+?zrim}"\MToVő"ݬ'NdM4=2a7sTaYh޼p<ry=}w}#zk֥_Y4._׮u]!~(URpfS tÆ##dߴgMO`q|or.`.Xg?|2۵!y1Kc KC`@i~?Z|ess]rZ e%ͮy !mT!jҼ G5oV4!:tg1sESB!oPY_sjM fѣppJ֏olƆu&[][C^m/!r 1y !`FR4"Rur4TP4qTV$hYs(Y(]Y3M Q ]6Нxl...4K.Y%/,hmp>(&@ґ/|1U{<ߧɇ*QDTȒ3B*^'DJnx@oPv 6Bϳ.Uw"qXʍ]qhbī<M%@'AIBLTģ*Z.oV!$j*шdY &wa ypWV0aȞ{ܻgGoO sz뫫lqebS$R/@^!d1 Q=i6"`,lVs/9$,c V N( ~=阃v{<ۏm 9?OnlV.]bcB#^z0yABL*cJLnH5 A$$8~DLVy,Xwi /"cWRߵ X9*~d//˗7YkqFi&# "ԟ$w˲Y6fah&T2AdRɧ|P!3`˘{ynnQ8$.G"k77 k%,.-ann.yy%KTNs'"=cx8Y8ORY3uCeAB '5^@ S*T?BFrbQr|_w:8|&ec4_X[+\t5M',X*\Usi6+YnYFzf=jD'OH%ʧOp9/8 "y0y8:kkXYZK|~Fv>Z/_-Y׮M,dY#;ݝPxl LV2AYEAK7+*&b%<ʹz(JUP!$U,=}Y]_)is[ݘBll&K}OV.hlүzCuWUAZWV9 ʗnD>y _b1) D#{r C10BիXvXs.͔paK /Xt V+r8izIHTQmdGBL[(ÐoBY1ţ (o"_L.5L Mb3 D!i"Wv8έ޹2"0,.L@V[ycaqzbBix<'&Cd%g 9^05>"!s~ `"V)gb0b "ق%q`$VA&XVQf_><[OL 7-,|[ZZJ(^}څHBĢ_O&HX< '4qΊ6\f擇aB6D'~b粩y"!< a&R ._fssc3qa\'jͦ\X`f\.p2ZYaWjOw UeT` Md勏'vIZ8ţxD,H%e,bPKg95YPJkV-,.jmVae55TԔf5UIU(yd~rPƫQ;0 0@rb*q 9DvTGQ0T"N !߸V:_~a؍w޹~[Y_[Z-oYȗ_Yw5a wQ*H?*4< $Tea"iU@<׃"<Q|[=`˨d̛f|2Pӳ\\yᅗkk|qyfJ\.=٦VzvT A4Q,x"VLtE6j8@3ӄCLqw~%\?<^9^;i3XVh6k5hT*1~j_+@iONY HoV:T{=DL ""}=p9B I^$}<x p.PY\R? *`Ԗ~27gWuVՐ&ԏgY19_i+8z=Og٩B8-&Kn\B"YJ#%L&B27q' E9p<'8.`a FiaKn>(qL%`mqqiz-[*u=UIOJBY; D0UE9dE0uУ7-Y|IC!Q׋ ĤQɝ )c T/vCpp3MP[]Em&kJ `kyf^R\X,&]h͗ E/EG*Hͷ G ݈ -ٓEYS+@yr(&MHr}=!&vkJ1!`WTOOˎ?Oَ1R\X,"%wt}*`~\<ɸo:Mmfx۴cR Cn_7_`" HNF) bBKk $؝ₐNP:aȶaFQXDل[.5ӴaJ$ig?hj|@2¢UdU4\_D\@D" XdI|4Mm'SX>|o@IAz7b^yHIJW`_q%c!F: NuQj̆0|" Kjua۶T\Y"9OP͋ڿF@5j<*(nqVYa$A,!RGe*X&vSq򅗦*VYͶY X7)l6_3JLAH㜃 !@Ql%}-Mn|NHxLNULȧADpJW2&W2A.;3Xv@J&!}0U %&U ȅiBĈ! @`L"VȘ41$7!(B\t :|``Bgqn-2K&p"emqWH /:6*2tdM㝆No6IgYVrDd* " &ݜAz=)Z 0WDNhx18OR1}BHoBT0V>TB4MhX@F>8 i $B~u{N~κǜD :eq #Ry Àm( (J q)U)|/! D4I,"I2"Jԍ/H#$;=)D$DPm!lee6M_\XU sّG,Roۣ@O6M!1˲##Rah`SKi"ˡZ&T~)לMS^Aۿ(, .2"H(YLi}B]Ո2n!C灇l~Cp B0MX,aPbLvڵ\`9j]T}4wgOC !@h4BmE^` aqTu6jj5p]7iMY'2Sk@WA hUHEPn&GBJ*fDPşxfn}-+X(v#JY ϯ@* H+( p4 X)ԛ| 9x''6޾͏Dߏ! Àc۬^sͦ9Ȯ>< (6m0brΓf@eIF˚!| 1b#C#ҐgTrLRR;|;_b"eLy"DAfY0- 0˶Y0m`M0pQaT w*IlRб.D OM&Hq{?oVx C8y3I@^Fʊ!87(ua9yI7}T eɁS&_Plr.RB"_B yIZ˞T|ѹ, , ZӰl*)PTT QJnֹ:ѕ$ pmqޞ>=î8{FsFQi4ۋeo.(r a4dHu%"R~]Iȸ(4؀;dD\QP07%qπKq4S 9 06Nbs@JB:(tρN$" vqrrn7|3_qyGrλa<(M^l'3V2eɷK(oD>*۴K aÐRx Ò:HF"&WDܪGB$qflE$U0`̒д+ "J&*<*fT=_ *k#cL{z=po;{{'a}e<C/a _͇á H{m֕r{mt:L RU!C~i NBa pD&p9ݒ(q@Ǥ1?QD5HO,Ea vJՉb!8ʟYviF HDvquݮs>#H! y!Dϋ鄧GG/wvvy<^J@&}5<^ĸY $x|$Gg攦OT"FqL$@6݊9,D4MK%*NJ,C~Ӊ@:β;*8dlR @xh4`sI|NOO+BR^?9<,مB[(m5?YޞtSI1W-&R`rϣbB(S+Vv炮1W;m6'/|4B_*(ZMp*t0͏~LzQ*xA'ƞcw(:$1s }#旨a0 FQt ]0v/]ɨ@*")7 ef""$HGԧDX="4a0Ӟ <Zj˸Y@e(^/6(}?epι'8gGDKa0F%~ IBԝ89\ҟ#KFD8OLTrcl 0&)DB RŨEJ|{!d٩n/ӹEл =?1!D`LBH8$_F'0C|.w„QE*GF'n $Cr*iFIM1(_ hЛBJU.j 7gA<""1&4MXJ*Ţ Ug *8ͼ²'.Te|  LOG*m"w!&99TyD0HGLjsD'0tPeeϳg,ATͲ< U2 5MX.>7:x$T>eT*YaEX*%+$Q.SWր|&d2iFa"ӁK(2c<| dg5`+Rx<%#0x#98'?.XZNWs {Z7zPf2]|rvIcrXX\nyy/AvAǐM1 Pqgmyya|{ټXYI @5S&jLn ʧKWL@>}26 AW4AGQL@B40~dga,)=iJ\.|g>ٹTrݛAv9 ?Ao Ø/\zl*ssF^OVhrsIdq隄v,(H1)F3O|i/dhD܁J#uæ^깮h"ie(iifgvD>څB$ w!<60.Ll<9zQO] _y }o3"0mN.kڶ@#њ0ɲ$M7 wT6%j> #0`lb":>K~'WBxѱ.O,KzQIF5dBIEsz>öӇ ~^61&9 G$BKɨBRՋZrWa锑Zމ$R>D4#.hG5"N@}{5P W>W _\:Vh"ز,F#>N*9|_Lh42x<c4%" ť)1&b!G3E , pp <0vbrH=a4!wcͬFg|B%0"G!pB~h8Ȥ;։Vɧ*Jh]& _\Br <;uP@DDY|kگ$rKlD@](ӔφVĉ,=K6Fqat=CiZ}ϫqPBx榺Y~f>r@a\d#D2jjR:d^$bQKVۦS`"سV>4c 0`A!<Q!8hH8|*4KU;":4S>0 j iO*5dn)H5) DLBM? GO J1vEKj3Ā;xh8d%jL'j=˯j?\nfHyhHӀM~uI}/*Y:P PjxW$L~! ccIv>:'i|;C?[]Xxc<~h4J>EP+V>5=TӞf C '$}id"B|G' tFURӁ|+_FS`La@B<òFvB ߹}/ F|0#"UVé~UY*x9JHN攠gNQ(f!҈WR'L#rLɧ°"ym@3 /vecn[s I$ C9!>A8-Z I<< LC''FQ*?|-r{[BHmL0f+ȪߴJcIe*I;L_6nYHѦ3޸lH6o-X|ݽ`~':ACF/TBcYDYTQ+|Z@GLo3FjGDi0@KF33dknW송9R.CՂb*TivYjXJAǪGK׼Sds9Dc}18c4 LVD>)0À80m"0n?8. 6OזTK4?(ZՒRL_XJ:סVnuVjTrW D$"'C:¨ЉL/jt$a´ K$aB\S/x u8}FŹ_ݟ?ʗJ6u] @)A9UXN.pa-~888ϬfvYaTu- rZQs v{IYL6Cpщ8:́*DBp{B7  cF __ǻ?lۨT* i"~N&KT0 qppz >02"2&o(+سZE, !+8$!_NDKV/]B^z>A><9~^; E@hw9>\nt:\m# oZp> 1Zy86qv[tmx8z6oa]ܹsoƇ~]t]xQTBX7qu]DIf%D '@tЄ-#6XAXQ\trz Ӷa#GY1aq Cjc8D{gG]C_lno歭>:1Phe.f19("}DnvvvpܿA uӹ9,..jaaa!_ѫ16:ch4JȘ$?#%\N w:dr0[wynƒAa(JXXX@>OnW,4Mc}}FfB| pw17qg#  CNbC1q`p4BA -<<4{K:`oeT,lNv {ZW<<n۷q޽OU(hZX__?3Gv,t:4n{ " NNNpzz ۖF#|GW۷on7)uh44v~L4LD*** rGG <0@_ $xlNsq4V!*,0ƒyEf ''xpz T{?t?~RzZ %|#.bI.-KncN Uۖ;L B2²,$.۶>+F^>t:S]ERA VWWEA Lwf"~p^0XRnHքlm`p{AශoO L}/j|R(b\.f JYʧlFPHht8b4jzT&4an / ۶>[p}$+W˗/c0Ν;:Htsc&BlJ\raڲ*8Ǹph:x"xd'ժm6jZҏ"ձ 19J>\4Q.e'U F>'֕JZ jbQӑҡ8=1߿;;;vEFFkkkzj'c>еPn(Ð}R< 8<\N"F #f]r|h_ #8x,?dlY0P.oZh,\,hDF899nB(B.CZEB^JŐh#|p퉸 @\RW\F8::RRq2 (_p]j%Ǒ7Xu$PaR1z'vATB^GTJv `0Hq>cܿnh6X\\* )&888Hq|_.\i!EnZt_kqcߙ=ǻnv7l U+*RU Aࡋ Q.@R)*"(  mUi6nk{8g$y~Ҭw~syܸq#sNȎ%(c`vv6..3MB4Fqđ$2ȧ4(Xe s cff3T1}l~ w27񍯼[j-w+D6znFDB`B:s]eb4ݦ| ڂeY<b{{׮].lΜ /,,lX^^gnn.S$,~diϝ;fz 0 h ? d۲?A{66 ::<+8@?vxZpyn&JssHIds dؓ3:onG ^A(<@ez )rf /n6euo@܎@F- Y`B.zwĉl[\\lJ9.A 3/˜.,i*3?gwi\xfBڎdv!Y}Gí[)|p8F;:A_WC\ih),74Ǧ;z)F >B/-F/uwFB<s~٬T1_8"It]?i BJYh6m @vıLi^۶jnnr5!bF5={a8E 333YNQD, %&SB4e4M?/_ uV*iH9S*赚TDA c "I% |˂j (Jv90EqK?B\`B8 F$W4HH|`?=i(kL,åR Xy;uvvKKKvٍC^YY:.]SNayy9#期:L<"8u]G/ Y+8s-QY^Uei"ee)X7\| ׶p5IpZ'C&_<4^;våR2REVevV"䕅l0EQ033O5MˈM޸iVJʘw"iT*礛eaa|2zlMUUj5?~9r3&+wE܈Na/^jH"PoBGoB~f\˩F#h:)ǨG$_x  7|CןBt<8WTEa^g6QuJTB uz=kw/")2-HeIiBLB>BHU*4h@Ӵ,P}9sǏBLf2 Kcue0bbĨD7-@J3*KЁ"M@.yc&2 .zn(J# s^ܴcMS4C*tы"TVE[\\ih4&JuF+ʘ#I˷2?K6筭aii ΝdzJ &uRIP.@BUUF:bX; !sFH`G ko6E>? |# i @D,e$9Vd<٦OVct#!'O"c9s&s<~&x]88"!!8R*J! BH<`G4"mĞ݆jx)K@d ]GB@۳tEMUk c?].I03D8O&4i#`tڣ6IMu]ΌpyiU4̦*ATfM㤲izocY;  pؿyS$;(9ICgz r#` rxl Bǁs680֕u;G. Q 6PBȠ5yi:YąԈ'QD&Tǣ;7: w7#wTKig1d4By- m:^nVy>(<^zkk_.wv<\\*\;EQU:OL..)"=:<6tgGaIy|-\ qZ2v00$rp#~5wڣc% tЅ3g>(E,Cr6VT;,VJo`dG~K-m  ׃ov:Yá *u>﵁MDz`n|_x} ?Czt?9z^vȃ(Z8qʮ+׬.g,G>w}Hۢc4YEN𭐏I?I 'c\ibWpƿ9Zxub+@']]gxD!OͽCzJfP5l=43oY'@N4z>ߟt[c9)jFB  +DH x15!O0xv,ݱ9$_Ԋŷu-]j^YVj8FZ.*pTu&Q/剗W:zc<E!v8Y=P! ac{ W?; `p 4JJx:| gꢧa<|>I@˲f*#sa2c2`<a4`` ݮu|N= /A{oe].˯U+]/.^(J\vr(U*,_,X,(( (J+S^00 HP(9 <a8b<c8b2`8b4bc4Aˇ~4p8|4`y&8}a4ncwwq|v:錻A0᛻{ҟHZ.ꋋ߻]fUm4ZͨZFRj*J2r lNO I{dn~N^# :=:w;;:޽7?#C`|Pz/_Rcatam\XZb+kkFmny\.͚:4m Uу~n{;;8:8[A5:ڝvww{_O5,ӈpM󕅅^UkZFu~Z@/at!dO^GGP@Vc,cVh9GָI?_>LE)çK4˽V+W~pu}}~ie%77?o//ZzR\Mz6{2cmt:|&;?tš_=^;ޟ/z|j *kkzqEv5ť%4 D1 46Y(9GՂy80=<`mINv:R1pGƧ@˽Z]ٹgu}\X0/\` X[[K:rDU z`&0aFcϛNk[C7'OU5?ٸtG\JƆ1̖WWQ.Qn|4hxi&2ڎBr9`;76<0r{Xnq}pPxխJ^Z[+^~/]&VVVt,* aHpX{A-|D!/8%BR_,Eot㥁}?e~K>q^,K W^h.-:d"^VOgDO~ϋ!pbrv]t=S\~eD ܿtO\~}bLz yП&H ]M~$!fTPtLI#f 8>94^}+=W,[{/rxy|Gp7Z}yc\ąu,,,R$ʧb taEx\wۄz|  (,/]Yi&´l|` >p3ڧ˗˟̏/hŋXZZB\Nf0jW/ۓ&~t|p:>>:@g&?1, JZl2faV:&zEƋſs~…+WWs%ɪy0~G/x|{g@挂 4a6 KK5(?ٿ;?>P 43#:`V]qמY^_g66Z>;Pϋ?o!Դq>Urqpj<ၴlѹ_`ò`8 3Mԟf=vw2?#όF͟XxѾ:m+'棸%tx !He@(hȲo`JXo](P7߬6==C~\LuwVoXxys}s=nm?oK*4`fg<NƩ$;!+Y~ :qHAz81@4ah2/l:L*VZ/vR=nlym۸q㯽ׯ.aaajOjRc6fn_㪎fκV1mGvى6`d*瑫Vhd揎 sw\0ׇ D8^S/׍M,,.uD1 8|3 8 Vòмqdιn}k<\}<1X|wVV77/+p]BjEQfT ȕu`atVdoVȦ'˝1Z QX- HVɌr]r~V neImwj#g7ϖ2&tj,J]AB2njҸ m͂^wZ{fBs g"M>!m=!arȷZc5R3@ h؜Fhxl\RS?a^q^öGǩD4S5|vJέxxJhXF|D#e/H#<!஬`WÐ]s޻g'L9n?bmll`qq1YBjU 3T/ K-*4>t3/L1|ZEokݮ9l7_(fnnFn6)ĴK["te+!^j Hܩz0zfB*Ñ4aֽfi75/N>mSC'vPǹ#b"NerKKXxyr0'/2ۂD&|Z7y Ŕ|DP].c`6;;[jFѿʁp; p<_k6?,olX+.`qi sssvO%Jҩ$ND&{Ʀd YY~:Y/Tt*fQ FT?BFrF u1(_?̯o8l<8i6?Vpk6S@f,eɪy94J NinYEzN{8(|͞ױ AO'ಷ_pAE!`puTְs&pyxh\xGJKK?fm^jdI#;ݝPxl`}uiNfiqʜs^ӑ(aV p"|I;/Fb:+h fʕ0Pv +{{x߷|Zzc17Ӎ|DL\"ڤzCu騪 +< Jnp:Y$ !|tN H=S=ņ!ejae,\b,yVyqn ?v_pV+r$zIHT.j!BՋȭa|ա>iG%3!?/&/~|1 4QrhdomVo^VvXM@V[ycaqzbB;wN&6c^Nd&gG$$CmO3tL=ς NH31//5vFbdBEjeǁ_^#s_x+ 5kk_[XΕ5|PDs EGO&ձ1y HH4pm="'*Op2tg b<KKzprKӀSjBy\FR Iӫ9ݬ U g,A$wZ:T{]EvB{ꪧȧ[b/dC~9ԱI<dp.?PY\R?N3p0jKK?^+:jrIKy!NrP\D>xiߊf0A}:^,be,;ځ\D;m@" +%HMH!5q,D3`6J h]v;P[}tf4j-P,%IOJBY{Ԃ\;]a~i:t"N"D)I ")!eLc Qq}4QCmu[ouߘ&Lb&[7zjb1YBsz=-R= 0TjFGH^DOԖ C"i GG@0I FfB #aYRd$1y ?6BtQ4|Ć1&?1 9D)hQ678Arpr9V瓌QǽBl׳p^8bd*QA$W:@ӢYS{.$!i)$U_BR9XA9FȧI@d2|rĊc qR8+X!~UI~}TE?Z>>Ujϲ :?卪bɎ^vØ~AH#?dT7!`C35FX\HxLNU@'S "@8 L`:*sst|[Rs݂v(g~Q3@/YA_i.Պf&,JNNN@z?U?Y)A~<$H_(*HI)dA"Z%QnN>I.U3# NB eZaYroN6,@ IDAT*)lM&T!MHZf,,_|'eLd8\.wb iuS2 !{־iXGMRbR?)$ ;!1͛dJ&!`ĤIKWQ(&Y(eHծa`+ZeL>E@˺nǙND2 P<{zIG,_=Y8˟W[ȍOm$,+y^"2T^NDDrWg`?C&BIQ.E}BHoBT!F(wQB!`pJ%L41ny8 p>m4SDۄ_^S,IwsP?# 0d[q<.zzb4 8jZ-V1F& UBH2SmByK VˁҬj C'zB (T#uu$}-,`;lXhzB Kn8IGgl(ԛt 9xܺŏ`0F Àc۬^sͦ9.? (m<۶aD'020SvJ7Z'P/Af0A%$TI d+_'{BL^A$cӡ#ܻ{>>#o{p4G!84jh/XQs. C9.q23M,@ @W|~ΉU 20NU|4q@8TXE " p||;7oz+_Qo0yDp{aܹ(GM^խl'3Vҳe%H|j >_L 5S"`LLnU# !%lIU 6,=mX TT2QQqAYR >=crܳ|ww7=@nAnG Pm{KkkښvR:T I'NȔI(DKwdx\+9aL@O{@Vf@D@˂aYfhضcN=Ai8MsNB ,Hd>`k {{QAO8p8$B(*n9<|hwmuU20 \sY vB-U4|1`"@V݊9,DiIiիB%Y!?lD dgٝj@U(](M&wM= CO@t*BR^?>8(څBOѽtRdYt?'$\B?0&R?QDqGZݙa,N Ko t"+,{ "MOfdaIOU$!~_L7 N]G7@:dr.'H%Q@||D3$~D7qH](qP3@'V֑~}=c' L,ϣ@/8d)eXw?ߝLGLJ% @@4|hKd}%ztNi"?4DYmH!8xF&M6TL| cu gR< ryFjG߬k=;s:J{{ZNv=|63Ľr\r]iR1[+UV\F.0]POAO契 )6B>Ƴ/OIig0I\jT;]ѲkPzԡͺ}i`'ea!aaqQz罴v@VŀTH@qk9fRce%4 a8Y3um"Vc2YF0ʧI+fAW~E)EQL@@f,0~dgalڶSZ 0  %5lo_( :^o25`[50ײ^)5ܜQד(J/PID)E؟nOF2+){/)=)Cä`> gGAjFt0©qVH'A;R=σ8*˒/,ຬT?1j.v m˪m{1?_i-/XY[K}lH H$RX|Y HϑOnH>e |>Ysn Mh^/lN- 5\num'< 1d 0Q`VWWm0XÖ`eUӭYZE3tq!r0M@Ypy=A7}B9~HBU ٟ]эJxÐ=Rߗ[s3)TrGꌥ$=]jQ# .BGjܺ{L {ْPK?cE"C$ hyIo'LOfiBVA-,{*\=KGt$"R;β jR%+hzfioCHeubik^O ?%5LL5}Lz= ;1 0>]{NWTUpJP/PWN&jIȨqaHȴ HġjA;N5C<9xc`!C {=8LF1#< 0hevyu8KԣaH5W,G7T=AЁtZRM&+a^8}h0%YG@DO԰ |^@09A@ M&/G#y^l"vQݳ]iR#4`Jҿ$t,D`|@zJ^=&O߳ c `,i`to.mlvkՂMW 1Y 7HWojAҳ9?2PpESOd#S{a$mOJO}{YT0%3 !F.|_GckzLh8zs(yCՌՆU?_k?:ejXJe%ơ)Ð R="e"e=!G5MRǃF D' x*f0/t]{8&9YtǦ,ѕJ??ϵ =Yf$DZIt78Yip@:TRo>aL*O?Rv2OM p^'ڜGc}`K6vvd`iOcUIuY dc$flU ݃ԊH% =YiUA$WCu<OD>q!FQ'(fp0~#r.BL H0NW>rWU =YJzAiʧ4[&RYi> zt͢J@:x=:aʙӶ^=%o$ߺ}?t>h0`0Hm-B-:WU`i*8uC@Zk*}6뚱? A/ce6 ٶOL1ǨF>r+I@FӠ;t0SU*@ &TwNW1]N3U2tB"{ԟKnG瀌Dz*lZAF=j\** X7jϊO~f7 Y9tjZQ 20O 4gz=w0m@im[J\V NkPgfZ%Qz|cY :WT?Kt[UJyMFFO#=u& a8]cɹ)ar E^@ho*$`f_j\iN7flJ֡nujT< H$Ĵ=E~tt)+ @:tPK8NNexPcrŒ ^G}@ è87?|j^G׃dFmkGdTsuI;-T *Ma&J*r\2@USrK8PSۓs<'32BL{锎0!8hy ۖn?x o [z0gƃ/uY(iԡMϺ"aȆyt:hIaT u{ݎ?8O P8h~vq||h^L^,j;1!+j`f4ӡ.Ctp6t_y睭,^:dž[,¶R&"!r龊,vYӏ!`88881GE0~eQյP(ҥK34;Ia{{C&IWzi2b՘T*T*.(n#RI=〙$]L<òn{{x2au`3+~{Z9M~JR"͂tQ7smܾ}ÃRf,\SɗebBT*0&;DB!yQ CL&ܹs7oᅬJP 9 P؍ˢ[sF>!{<3ĕ0Y""σ7`pthߡ,̶JzY "dOux߇%"BS,"c(Jh4ɽ)͆!Ž^GGGx_OڃTY//4p-8<(d;-.'ABmasxp0o̫|bzFIOMtςjeYA$8+).".35ieN0]u!d (0-ܹstq(A} Oءe#pC ^G^"*H13M!&8 -.PYP{<~M; E@hz}n7. ۶ߴ< 1Zy@~MasssX\\DBҾ16:cB`<'dLr.n295ûヒ7oI0 J%,,, 'Uz'7 2MX__G@DP@>OR Z vh+-.!# wlFw00UEBr+"!ݣ#lx z?]*cE\vK"fp1BdOw$)p-ܻw/iS dfZOQz' n~cr5 t:mx<7xn!z^'h`}}ib{{v hVfUTUT*Y6\EZM^ h"6qI4V!Nc,nat|1t:!gdknJj,|=F:m>q[Lu hYrmO?\ض9( K-JxX~~C93A,qppnd!\ERA VWWEN Lvzebs 4M[IDEFƐaa$;0D0wwq/6UGtC owſQ-W 㜣X,"% }Ӝ~4Sy>AK&˿۶Q(9Z" (X,&զz?*xuvu0DKm-ضT7oq||z.]2.^p۷oc2s"sXBr uSBGLaڲ*8Ǥ.q h_d|ptHݻ_Y^^_~Xڶm'*xRB̡`LR VWj4T\NڟTpǣa K?JRAVCZEXDELrNOy||mz=t#F5\|9ԑ򄐋 YG/a6)G@F0&7h!(= F{{bw8F:XQ_0vY3P."&0 2Y0"x<1Br*Z:\Wo["!޽?oFNe22 rG`2$!e:'71j(˸z*nܸ^x!n$=a^r@BRKrv{>{aߗSla(gZH[.\WsN9v,08fZEVKqL) uvvvpa0G 8o c(TIv͟")3Ѩn|Ny|pxlk/sG{{?U*UZ!yPHHLIGp8n2|ȁ{nc4a<>nݺmt:@fb>z=Q0x0䥁[z4DPY۶u888pxxTw…ĴZMV,d"g^(_̏][YNUz=3=س^kQ`R' HHh"."BhEXJ(/ !$(.Q&؞=9uMMeI;SLӸp1;; )8Nj'M)>:n޼ !|Of^k0 -h:8Qm4PF)x,HwꗜU <V+U3:8<*B\MRCv)9'N*h44M`nnRO@ɲ,,//8}4aYt]!%zi0[X>wwwSSVa6lۆz v n" L2fg!PsE0Cq+ 2$IGܼ)o(M= +/G_~)˲RIA&yY"zi.áʥmhڤLl5jUgYSr26_HGl*x}1:u O=N>Ǐmu]&}5!sq *Nqz]ibmm +++0V/>NPҡҤ hI 8ӱWH^;+W^|4Ks۲f۶(謭H8_,QLeB=T:&)cvv)177z> YPlpnn~?%8=0D'NɓX__ lFrr 0VUJr|Yw跐2mNfu C`2srs0MCZEVS;!aA& $롿+{Ew?@~3Q'r DKLHqaK""Y:F1] F]΂)0\.!JMflbbqqv;}pO>SNaii)%望l>LŢ*B9,ok5,N 0*T)X5\^VK^ƕ$5`^?p .vxyk?vߗ\_f@VKM* =隦aff&͟f% CJmUR$/mF^GZMylllŋh4멲e]QհvF@"iWNqJV3ǻ6v?驗4 hhFB }]tZ-\I\ɁO?pbi)eӌsM48zj#"eU**bz7s7:RYRZ"`اҨF0R<8s P:?ѯL"ۤ@dzRI"(3L!5i灏͛h4R(ܺ[E5`^rtF^x׶Ou CtKPU!t`6RM[Yuss9tcdu]g٦U,..ܹsX[[K+L(E'EGRIcwB&@?BNsFH`2G^ۭ~E$][ |.mmNFoaxçS0꺞:IH!Q*$]m!r. @8p:.; -`f#% NQai+Ta*hM^I\HY܉HyBeI}Ӿ0TH'ܐ7=֝pB4vd#C!w^a]y*Q(bهVi/|8W~`ԓmE2@봍5K;mOo`n cRL7)>Cs |'q_~~:[[V)^ 27+.ll0n}P,~r<*F7Or>`ZFYbe,a`x'0|kA%N`4tؒRxP ]~̙eLp8Q".1Qa8b4Ӷ1rX u.G^ãGl^\9vC!{N\,6{,Nڣ$ g,z޹!俟EX}i7fVUMM#<5عz9F\zZ-Ofܽ C#O@Nzt:I^6J{gUVan~Z qò 4d '❐%^v/tJyW]`0@U|3 Y ?Go|<7P2_U1mfV,T- eSuR:l gjM5TgosVզah]CkVXuN w]8Wh$AVC_?o}_ˣw, ++gMpPxjU.T*V,JZIaZ}RVPVQ`&.)ܴ60EvyBL=q8F@ 8DQq6u]9x0 pf?; r]ilSJET*iRT.i8./'cd%$Rh8|KWK u]WwiQ?.z}4͏Ultø` 'KRa\.4+jjʘ%g>Bc|yHG6^ֹnE2DZW*{#ûxp̶b\4bsiiYZW(0&`P`(>YNSƋc$cr%)^A(\$0 /kv{8`YURdZu}YӴ5]g èM0c]yRB(sH!d9H8II ]!8IkJ&4 BV0 FTZ) 3bq q2VcLj1 @1F ƘR )e )#)PJٗjm0~ۍp'.fsssS|}M2pIENDB`FRAMd{Z IHDRg- IDATx^ye~[]U==3ݳI~dm~zAX~B‚b%dc[A„@cB6 #cزk̼y==S]ogIrJv&ìT qض=E>۶HiB}a8E@_ha! x4ޠn>_ }!& 2 xѱ bXV |* ,˱r J2˸.rR4t"-˚)#)yFڭz.:zn~N{ݮj^Qa/=Ug_mW s\ڲvrr_U*;啕+\.BYdYd\|L\ixjkF1Sn8 CpΥ}cc} C}F#} }] z=ky xZ'' u_zw_Rq~M!Apm7׿ZoSB ժf,W,"DKRm]J6t!8qw9|Œ~fS]<=Vv{t|rrj=;>Nm`O[eKV9#JzTYJaii ˨T*f( HG ia<c0l8<T*L&۶n!D<^.z4njn@ӰnFn><|ۍ?p0h Xd2S)r榹77Rx.iiFN?MnkU.n+^n6['GG?T>X 4?[X^+\UV֬R667uJ%TUnHk^ 0`YM#tnT&\X*Ŭl0R)l _z4<9Fg S }rSO(JaƍZZ]_OU5VVQ.ⱝ뺱ipO$ {!&Z''h$<::>=;9͡K'z|j%`(o67VvUv-UTUXbWH2d&zNGحVǏ ߲>/_K~}=O:R*Z}cV^Rmy\r-//css3V0b4xkYT rEGj5+ɺ7;|'U qZk7k;;ood7n: 2 ,ĥy%BIT*uEhd?ӫ|XO'Lu\˵Wkus3۸zXPgP,B"eHAOCapx/_bx+``W} o_vqƍ7V2U\j$lLFzˡa^|=좸L44TXQmmuS,ީ!qp>'?Q@1]W۷nw+r0 p dK3(-`o.a]Y/gW^\qعy^x!HV-O-˄uwg*%- 0Pd+y'U@<>6nfu_loO7o޹v:666P*5X4eY-EQ!nFe,'089aXweF;oqc-`+~rc4c+7l7_}O\ٱosFTw6=MxteE133v  lYD5ڃ;@@OYp 0 s/lܾ^xEܸyZ L&t=i̓hEaUv%pc_22(ݸ!xwAa4 }Vx^w|MlcsjlGJ=;U/¬{"uw9^Hk.0=xFxn,pm۷W^y/۷nf/߽MdY R>-6>0?. "Wu'~ؘt}ة |f0S) jEPˬ>Evf'A_I@e10Ðtbɉa f0lpOg*sƵk?qjnsk \׍xK" t0Ʀk%5ExxϳHIIتʚXحv7]/_KKK)no+W!uӈjY*_z1~^[*?upI o׮^++V0M3>ȧ*z"4$`QT#DžyeCw"o*Si |^ah/}% M*qp%gW+XY]ERév""OOͨ(q̀ۓpQ0y.U'uH^r""" dw,TDuQyl~۷a[\q ¥ b/onf\jJyS0XW/OD Cy Eky~IP%,e"iP:*,ubT $ޔ2"DLL"J>y0i82X_]]\> LW^wlnZ7nL-4NSqޘtCUGW^& tyiy, |:.DHꑝs)IHstLV6 f(ߺ#v-=k JGRjo,<\6=<JuStU +䜇E$ʥ"N>>XBqn6=;Ee!S7t:>_3 Kr_}7\A-:$ȶmahw$HjRGcFWBLK/":vW 0+J>uLϚddS􂩒/"!0@8&R2J7n ƃC%YnZ%cyerlBD'wFSc2&ZN|%' G$$CcO3tLl *"L/=GR EBV~M{c!8)(on~{iy77jA.DJQ'ݱ< &,iKYƦ׾t]>{ҝ{Ґ_pR !k} as9˨\ʶ+6cnms0E*#Zͭ-/ZT*78'm8* *ƞ$>N\E$TuYɧ?F/2qxjҌ'wR[[g2vRsMB]kouz˲YApn\TaT1L*IU$wNj$edyzP'I;~VI#GSRH%nVZH="+h}fQ+ }/|?#$ ַ+pY8Ϗ5_c . !&?JYx=K\$.K})"ơ'SROa,T$O =O>| WW%LeXJz*.$K/]+kkj( HRB`8=,2\>_>TbU!0!ݫu5m@4ޓB0e'8fԸ_8.c0S*|6j7o|ޭ9_,p!RJFVC>va! w,'$MYxDBz< :u06=ACuw_N8~̮S]"dLI>٧I`4C42:++YKS6P&d~l σ1W@ScP,> ԐjE}pIdR D,>IJ; ZREd$!DŽaT1 A )f.-''ǯ/I JlFVɗJFZE.cRݜJHP%,X'A'"IRyDSuIK_!hLIsHt I7 Kᑴ cTBae2t̔J.ˬT*!J].I?Χ}?ϝpe@i)+yztTӽ.0BP)DKBr|Q;,a6r˨_f3}>.Q,Vn>\l"ι=-xvSAeLjyPs9HnISMf?|Au&`d7 .SBx K@O;! a8灙&2 J(޿d< EhIڝ|r\FXD6wК/=^aj| Pê4jHr.@QdHzaȝ=IdG$Rɧ_ A BM쪿IOxp<c 2 _Slߵ |ӳB3 ^)W*l6T*A +i,"RկpBH,O0&%atqZNK2:tSa4`D8"<粛C< c8C,2|( B9'، `jnEd2HTAOU$5,,. `$4D*hyQWdIr4M3GV'/ SP%^>2p(0 \zݬ:Q [c! +o  ۶eJO  <@ DeQǷPMG%JpIuHiu{4<GX fH<"za/Mǁ"],mܓ')3Xy*lRA.i0/#*qGPKӉƧ:t{"A˲$˲`߿rrv!!I>-T 7% O)% S)  Y̔J_fBk ]/Mo4Qh*|_YH4WuaI9ȝ"! I] 5y&9,@4 CԋH$ȍΐxFa8!f0lN>P2v$f7rRy)ͲlEy4z̓%"</ɟpL!&J 8+O'Ĵ1i|LSV:/q"}/  X 0ƀPkf˨Q cD8G|øR,N{]BYX4,$|2XAم¨ I+OIpdVTn3xd>$Y`<$s|"=)!FòXv8t,!nc Һ8LeگJBau<$I=,')~?0! @}&Uϲ :(<Ս*IUȼ) 1DaȨ~$ tBD#2 !b #r/3&!hq.PTX,e%D8G@7\7cRa _ԇyS2&W2A*:7ؤ݀ y`lh@4&&p] BD/l@л]P:T0D<8 IDAT,S$e@ݮva`Tl²ex$вnQ+a({T%5$YzpQ8qHӳo6ljgYVDd " IMz9)=) "zj=zW~BRʑdI0 DŽTD"&`8#SC@X4\4Mje"4lj_8 PI"1VwT:+,p_\*gz93%T<0 ضL&\.RBOR*h@-ޅv5L(y@`]?>,Ąp"cGȭ\cC#vumY ,;@1E7+Պ\umQG { ! ujWH`X#RAp~V^ORiHR(2՟i5gӔʋHLӿ(.pTB I) F KN$A 7~PNp+!`&T 0 ([@5*4K7nHe2)|JBVPK*$ԫ6˟G'C:Ba8G4~ 0082X.ciyjƽ uBH2SoBuKv`@eV"9&d$(lD)(D#("{I?=ms3؎c6LN CJL(p4OdS*Io4  9xgg8޿녃amV.Jf.^`Aƿg6&P]<"7䒝y%df_d^DV [D)*s}̲`ZLam`2&`*uqF>0A%$TI $K,5N픦e1SG+g?ɉ p8Ib1]VW׭0 A ÐcE9q<&c9,P9ub-fTF/"7"SD:" Z}dD8S>CsǁiY,0XSj6S=O*E5I⼒LEugW_ȀKOU>!?{Cj A]!!aFfsŵ90 I]vUFaRW<3Nr#72$`$}a#i)2Gi23M,@R KtDR7np8VGŦiXt*XE "3M oVo9NyrB5l0ǯaQIJz=֬I,yJ@W׭:$ 5S%iRQwJ="21. JR0`̒ghvƌ$ "2QI1}Vzx*g#ǘv899!?<< ς0h{hA8<mw67Mn3u,HR9T H/  MiBR|΅$O#8#HG{q&@1%%e, 3OhضcD 7NA6<̓~ꦻS#aGF}Hy M@ӴT2QMJ$CaS{}EJT^UNC4`4h8p9?4=H ȟ<Z"l6NN2v&瓭ladY0Ns~4NYb Ll #*3M0ӄ dZ7M L2"KYOEOfɮ7 |DBvh<aB]Cf5w0lxQu0ĿCdIF[%NFݮs,+8'+?T?JdWpA}1!iH 1!_ Ƙ`NΘan0l*+|>T*`1V%^^F=܅"_1ZctCxY}?.DjT7]%فkPzաM2_|z0da!JayeEw:x|wkk}4r8)!]q6n Ojkx0 gԽ4&#y K>]'y'EDl%f |>7ZAe&I'Odl0bPQ@*yxh>߿s;~:N}D5D`[%0 ײ^jBbx) 7GMϤn?BPtϑ|iJ~ CSuæت]hD&]ngtdW݈| H@BȽymau]Wh0Hs_!?q#x׶|oxda0۶T*Um{dUf)"3 Yy)P-ZF]ґ%&r%DJ8Iρ|rt8pc@'NgxzIt6dYq>٪O{ CMD}eah?;_/:΋lvgskkaV/㮗_2&r3&[stI%@D ϋ|:!AxB9@YQe](՟1OM[_Įӕ$R=v!p'ޅbYed\J%чnjI C1l۲Je^.-kk677q y$,j&_骆c3ӣ G-L9}3{<>Lݏ$`<6EzU7/2*xIn<{mǛ<1  0NQ*77a666l[u93-[.|ZtQ#,*D%NՐ ]']uyvz9ö'J 7dGD(uIb2TE=1j_aLɤ^3+C h4䧚`sgI x7oX*0oHG_ĮC- ݫn4lY!|N*9&0&7Xh0 )9?{n'.RaUC\u7}]nTH=OADP J>RglzJ@"Ҙ L1=@$T 9f1[0!pg<x84uQ%Jjh_w /bWAm$wj\q<=K"",K+ՆqeN>ץ`:gJ6IFc0toD?JhSsZb5u *'Y~zf]FܔK 靿:h8B$!!IGW@^@"uDl jIngW3M@3 Cw:p}jszp42I@j<ΧM|Iz]EO} uDjL`Z5U'k$!\q&P`BsmQ]%\haYqzڽ92x4; x<0HjT< =ms'>":N&D`lW>D/PWUGc `,z8ĨC{<?o,/i4^pLAmЏ[ѕR{; 7 yJA:I0$,2 ! 0y 06Q%)GMCd|}\ )k], ` pA!DGŝ# x ш#!UVaUyvzeiL$!5*RS~D:E|hH3^u$y0,C1M@x /_vzl+:ɮ#!&/(, 7Ԇ&iH8h4d"&cSQM͟FOt ÈǞTlB}`B m4W'>_԰@r8Γl!f` 3ˆT@zgg8h6q t9h1]n2z Hj$rOSFmYi0fVz^y0&Tt[}DD=n>)0ӌ'ytApo !Lgg_sttKRp]wj^lޘPEREnzvIdU75R16YVCK|zLFv@ꕞhxLXS"| m0ĨDXt:M-Ff_ɞ^*RӜ؄dס6dWN5W D$b20zXDJ<G- 5_zFqbu/j9\%crŒ~N 1 z?㨸3ӹrNIZԍdTIGv9%ȵчi"ˡX,"Jųv_‘CϹ{sxEFN5Ec0l[ccq/>ң0~nncz=xPN4=ɞDDÐxVnfn7N@Uw݈s9z%<n N'^~?^, 81J!mBZgϓu}tF͛@[?ӱw!vo 7m˭LDB}Iݒ_ Cnz8881qrrrn6`ݮ%Qk&kצvꈚ&)n>vwwjh40&3mPi1rr<4QPAH$]D<òvGGp4 o_X`3Ӄnzu棷$uW8u"sf`ww?" 0`IJ$wfBP(1e2E31Cܻwri*z]r!BڱE>GRA>GTB.>J:Ox׋c{= x faavmBr9&uM@Dd$oǏq|| ϓKH$f}l1r9T8o*aqqAヒ7|of<nt$ju6EV*˲-Gv=3-5_!h+B`x9Xoz/N HѲՆ|ߏ?qw.SZD\$iO;{t]p#\.cssaƛea~#ÇţGrqHP(A} O~dz]2^Nrr؈i"1tIACm,$e~7q/˶Jѡ;)DɧKxtlF( X]]EͲW ~vnV '2$ ^(JhZSF888owyR)y[XMq#"(ce hYlĤh4<^Ajai&B$>o>hAc4|w>`<uf8$NhKRsl64 C| _qzzN׉뺨VڂiGD׋'ijXհbB?Kل(K" "D~p^)cXL/aǭ118;C [-Pz܋D4v_m5P`'2J,Kn_}y#1@4P:eKpD@˒ۘl{Rc&ŶA&mboYV?Jh$|A|壏~kmmi4?-m۶q 5:/iNvmI" !9!p||NJP,QQ.x@NNOOG+_ p:7y oܽc ~ԭ>HLHGl!6vwwl61 0qrrSZV<$pVKrK p8% ,ˊ׈oݺ- X__G&#'T:fsj)>gggJÇqrr`ÐCL&z[nڵkX޼3'M-+@p;9G/z>0?5Ċ,<Vq ~0u>0䥉[zi C9O[ݞ#vmqrrǏFcj HrJlz<&f2ɕ0_p.W~lj%6^~elmmT*A9vv8Qr!Ǭá\V0>88 vwwqtt5] /-!` 1 iFk<~,o}&|leK!$G!Rjpvvvn!)/8h4hZ8<<15!ͩT KKK͛7& &bϓ HPlmmxWQV8F#yToٌǀT%޵Fԥmw۞xfG;  @)< !!"E<@2 qH"VyV"wvv2ѩT*p'Μ9 .`ii KKKm(0MHd,OCcL*.g]$aăE|E &eoڭ[]i+k|Mٶ)]O 2+VHv.n+`/sN6)'[r@ٶZJ\nqqV+#'c%}aaI Cp%dL# ]?crHgYVSq-K* ttuϺòq(M>oq;Ip āO$ By!DsM46 P2X(5XR" jZv|㪍H HAv,)-UIG($44l0O?4\eT*Ώ d+˲@6i4й16yX(DHR;2a1 3o|ƻ;p(_`sXd +# f8Qk !Sы"TVPq4MTusloFPu]gۦgbaaW^rV u]TtRFr " ݋B&M !@93ãӁ6^"l$p (0 0|?sγ4eYHZ6zDT=4=kAB`aaϟGǸrJxPi}&BAV&.BB@BhHS!! vݝ<7.!p? `}{-h^rXLu!ı|/=|Io(u:LRBAΌp5i%4̦載tLymovߛF4M%)X I87 ƯoF#ݹ~_|+IySA> wKaqEwpE0&0&(2UEGV>L@XDBрaȬG"ku]HGpoi:e1PG Aw` :nwZƩ:xBT(=0LSv !Ŧ%.F4)O(~Ð!չ!o^=qxo)h)@3DfeH‚h \s$Lf9e_40= Ђ 2Lz[HmG۴VIu~5p1R&՛Fƴߤsc=w[] C^!L4pv:Xb :>2|8uTqwsf~3C h|tdӺ6V~QN GAhN (6'8/ )F`b/{Zxqݽ XTgf~l^\.?537W68\{TDAcntmLga{*(j4Ԫy^ՎF#t]Áp8~A|& < buG[F~b۵Zƪ**8mY UgU4Sxњ̇W 4_][Οӓv7@eLIR:33c9ê33bۨ6JD6Ȧ|WM3Y۬4L#mѩvi*^IA`40 0#`8 ÿa{ysy% aei;,i8Jqr* \ 7\SwLØkLQ ߊN# w0(F^`_Yy0 Qם՝9' h3ssoWlYwێs\VVQTPVaYJ.)j+RIZt0MKI@Lja! C4h$C9^moo  RTzʩVWӴreͲ,V.Q,XɲP(R}sb3 Y{zDHZRzBL urIbjI@CF}/ !mlllkljw}3ڲeY/;tønbhJ%RW*JN5L|yHG6\Dc7"؋[ |`+\3 HsY(\-YU]>Z(~Ȳ%˲$"8b4a h&5 )H R< Q!Qwx$axKӴ;;ob0m{8?X,)U*+4M[u}0anl3i5 ``c bćo"IENDB`FRAMd{Z IHDRg- IDATx^wdI~sUWWq3k#@   J I ER$*F?DIAAH$H@ { ޺i[]]/K;$p`&P6, |F@#N`q*Y𻜀d@ cL˺k7qǶmҙ R42 ;Nô,03 E(QF=a4aEѻazht~ww7 a[nݱL)kRf*eYpe4M'C(E0Dxay~KAި0~k eմe(\볹ܕb-K|>v]L;2LYǁ8m{|m Mh$ ^{! 7^okOۧ/_mA+A_6_sH@/9\>ZTLX, |* ,˱r J2˸.rR4t"-˚# )>Fڭz.:zn~N{ݮj^Ia~ӯvk59@.mY7rg򿙫Tndr;n>o ffq]yd2r9MaqkL HP(90y]JjRZJ []]"PTPՐfQ(0Lv_4w saL{+wm޸qai)wec\ZYakFRAmqq.5͚94mj 5ѽnvGhbwgGݰlGG?ѠT>X 4?_XZ+\VVVWR765J%,,,uݘp@O 0 5]5B9.vd+KF*euZP^6?p80  |q}Vms3r*u6[Y] Nc6_k HsLsj5xNC,,{{F`YVBzhۿTBjSWS@JV[_ӕWe}sT]Z2\aKKK؈|LS WFh6x#ԟ/\(Dˀs~A˂e!JT*!"<|TcL*x1jGϼSU׀Wk7o+w;wnb7nĕ+WBl6 ](d8$:2i9/}*aBqid3IX1KYپT/PKōJ?[znoo޼qm߻g,rO۶}_4f hȟTYzz.y^y{;;xwv|Nw7%૦7J\Ooܿ'޸ennm7obuuJBTjj> 2z>*t{y2Q4#`6RdѲ, ^(evWY7Go< 2yxWW^)n+Wbee|>^`MU rσ_6ϧwM6c T u]ع*:aj?Kg=''`0UWV{ces3ws{ۼ2Q,v?o,PaZ( n@/b G"O_NM4]ׯ{;w`ssNi<rH ͪYIH~4D'$?+,A'nR:I1]WP4Q,Fv#X>!,TUX?z,rֶݻK7o2nܼu (Z^0_*fUEt" *pςV1 0 ٪vj 9k5Fw) M[fK`@nqmlmŮ]R˲f8` \~HaW͋󢐔g,$= F@3,!LPxXī@ |_ؚDz:<\Ëׯ{l}crmOCb-BΓiDL3&秂g_Ϫ  t"/@GLib`—|ke@g*K |r\bVVض ΧOJzuЕJsD>4τ.EEiҜ" s0ÀN#]t&VMg]=9)< oY'H3 66͗_}rt: 0Fh* UML! {%// -pI$7c` sD!ܵ5,:xۏ9C |xOM \7-Yׯ_rS$^|pBM' cg."q^ k=OUv˚XyMv6Vi_?Ͷ&[[?~zj|>!&#^:z ZLk:ƒ5!0 Or)J1+Y*yuMuPZB@*9  d_ղ`9ܕ,ݽ"czrPKaˬ}GS"ԟ$u^)*¼2ӡ;ϮC}ɄPG: 'Šq7QsmypZ}A'"g/om{ׯ[kW`yeJ%>)%Iө$対Ti>Oz%$FYPӘNŬ8:H~*uJC@"L\X+ |<&^ƟIV.=y~IEz=jJ>f/KvI!pQ$9 2A0i82X[Y}\RKkW7767c%i2ଦ#7ݟP|ljx`|ue+Owt,sQ4/6 &ZpLH 0ӄ͂ʷoc] O8Sy^pnp~5lB# KKRjlax6&]{TwZ֕UrE$ʥ"N>>|zYg Cs0,dj5Tn͛j:wɞ kr_{+WPd6(h4^nT` TiEV+0>]PafQɧQ\GvØxHa  Mr7 njõ!g__]nR22,9MjugW 9?>yP_0~tUwW*/!B ,`;GB|C x [J)(ol|{iiml Zէ]UP%47i,qgAY0!TU꧇g@!~BH ! C ;իlR1s+nt PR?RVVHRqyڊOCnI~*H$ y$С벚O^U~}NHA^"qj~$^ƣXJrX]_Lsۓq!V}aam3ZXZ^FVC*fP ] e6$ *QӔXͧUY/e,T!"9h=")"b͢W^榽N,%gS[\drn6 Gȗ_*mYD g!B?I>J6U$Ye!Xqx w!UQX_GqeX4TU4s vō?j&p8nsCׄ[j`~~EHLGT*5<\m,ZI}$7M2*> G#(N#S!ʹ8$i̝)Ғ|>XǏ_]d ,g>u Tj4ɤړ}zx Ly$wx1ir#3BD1g 0f6 wq ++Ucyw$s5`XLZ/r90&PfݿHPmT$A$I 7/}hB''OB@i|%Mk~9BGr.xd| l4$`mu^\~P.#_,"ƻ]h͗F/TO!$abJWFˆhQ9{(}2mi=0Ξ$2#YL^y']!Gd?'ÏM3 ycp!P~Mj!g $s^)W*l6T*a($~V<ϴTn:=lj3KSf t3:: 4}UgW3$!\nL?7& !I(lpEYdUQ2M;ErNf5YZ(d2hKUqg@B' D!PEˋ@&*N@4:Q :|TnY삺vcnABp%(g4^LбCPj0prVP$bh<mE"J@5`j'K'骧]Hix(y|O#0`R0V6tJJRO[2D"nrJR 43B$j:j`:$JW'/n !ǘ߿rrv9A*0v4"sD璄҅ Vm{_N$̔J_fBi"^/gMo6QWU gR3V^QA wJH4$5*tn_^dxFa8f0lN>PJ6^,ӕL6˲_,bLΣ7BȦH2,U$yBC2l^+UҬcб<J5qS ˌ_@~U!Ig8I i3QN ,ˊ “lTMj$@Maȝe7IBaT¨$ rG AbJO hp48HJ(T*,wz˲%",,5 L!0- IDAT4|/Ir&rW' &`DhvQtF !bF( '8BJrȘi P,{=NqxI $BauwMg{C@Ð}=q< HHflF&A.KMJL! l~ D@tSouҝυ!#S1DB1!0ܨܚ0mp("v]f[aKPg5MV*-\vѢ7*慛4Bjj~զM]zab8jדT`&RbwL$1y(7,D"Dy<4aRY@NtT&c9 ^ BHU]S $M^uYT0|>V>ih]!z!.NONptxN)wc0 X.JƊ2PYXqkBͺԚlL`:yy< q?PBDB$jãz=`8 gFXL/,,YQsq]!sxwc 1Aʩ"F%OBB!D⩕ 1"ϋƲ'-tZt80-f+|,X~Zx$o$A`(<:Hк#0& H}7z~p=|=~tx7[A0A9?0d0rhl.} 'ȁӐ!Kͮ8aRS<˨;@Î`"p6`MH3&K#af0LY0(3MqtP j!.6MHBթ\"i?4>:NOO[oox~~#j8\dyEQQIJ Z<eY}-lD>%:`j:~e7&b" RUeIP1Ic``<F@Ӷ3X 1! G5OyUë aTcr޳^~x08~@ F`n> \'8m;mlvfj_r^2ʮ(,s81 9 ~L:ߋӋf7B)-, egy 7E@öc\zDЅDH5 !d<~ꦻh2淪<F{8>:ڝN_✿9pI$# -zQurrqx߷n*0&P'?pqEkѸ Z!.D>V1Vl ȑ4MRDEn*T% &jWݓ΃.p9"PyUm:6Qo4hp8!!' }kZ!Dln뙓;ɀV6['0ٝmY05Ҁr>* y)Pڌ&i`i 2=7M#.&u7˝HI¬0=uQ˧j$!nW<FQtIw =Cj`AЉ]0F &&Xs$ԉsW9o$qLdk,#Q+FOHr{VPZ 0(vQc9=-qE7*A{Db&)m^ Pi@i0Àac1BD"gJJt$CHrS+ݓ]"y{^" C0Ɔiv H$C/cn::eBDԅNŐ0рIU7,;<22z)4 cr: Ѡ7 9R蕪]Ԝ')mWσxj2 62 Ţgf/-hqF^P( Eqt:m]=uZ$LLR܋? eϞ! Pn D#R/րd#D:Adty%(0fIazŐ 5M0ϣ\q=! ( 5,Ye0٬D=qC%<= _g3 x;x ]3 ˥!P'0:T7&Uy0vvItb%r]ϫj Vf9|6N3G|>n0l*+|>T*`1V%^^F=ܳ.=;T0!F$ E FA8ҌMAu5ZH ޫWj$; y>Χw>iRz pzzZo6d?pRC lNV9@05S&ژgG/Tw՟κI<0ӌ5`pW0Ple.6)N=)|R&};CT*{߿s{A:NR5 Ja,f雮eV3J( SMoPI'6.7=J> I>i/:xI@4'MUTLl=ɮh {|ߏ À0MkW`朿E?y3|6 hdEa0۶T*Um{Xf?[XXY2Kc2rOղe54_Rx_y^ :&`A `T@X: t3oQi$K; _ Ee-d>3 4MeEafa2{~BHfc|8/-d7667WbRKfa܌Iy2WIdٚov8xD|Bxd>gG *(՟1OM[]u+ic̶-TBmuXF}?>c4 C ihtU%O֍3H03` -땭~QKrٓŰm;TQ$LJt:R0nުc̴,#S,n"A9 gF3'$_epzUq`4!WapHA/xnlxI#a|4))\5)<{ȟF)774&Z}X+xj*BP2 0a;sql[~@#њ0IYUy qyͧ=<0MҼ065F8+!K˒AH *)u¨U:誻ϳˡ=((FP1&]$bUCn<=ݨ7 9"}y4=B%`*H *H|4ɴӳ DB5mP^j<`PyJ?bE"NBž% k CXg fQA4UeP+4ɝ*`]gY_V<+hӔ߆Չ=OeMWIPI,ݧc,ހ>Fat6=Cn) =rIPW}h0xe82ҀTyOLU7"vji>jR,G7<AJTT9)~39yh>l>haYq>ڽa 9y^-DRT'UUif;4 ~0!cӿ$,D`|y/T&z!_FWA ,鋃10hw}0byb"#5`Gz.a3]B?iͧGWH5YL0)t:&h4,$$dÄ摂dFդO>j&{/ lH C0b@~{qgh8~FL%UO ϳӝ,Lk4` RTڜ$/ C,D@1Sj^U7zj°"yM@o |_^~l6kZ 7u$d5f͛ZѤ ǁ?2(싦Od#t ÈTl/Z~q0L AAK$ /v:o  H6䮆Qê*pteڄiV,+^ 5 d4 C6HJ/A-eT ']ڠ3xVySQU$` l6n~dYU24ZIBLkݏ#␝TF|2]|Øh_`Ѹ<1>~NG49om&;0NpUg%U,$eDYn)VDH@*TL* "', 儸Zki~tG)zauL/EF:%To1U$UAOoVҽ^4tͧ4'[iYe>jglgQ%Y4sc0La6xbst$9=[3ͯ|k8ŠCכ:ZBZ!t!Ty*4uCF&ZEB=CԸIv4MS灋0I>r ƐfpɣL`&?^=ZjOW {JRU7]nQWDD իngV˯S.5/ݍe]شzyմ1eC@z8h6q t9hb%un;dtH$rOSFYi0fVz^Oҹ 2\ I􊺨ɨ-<'"Ff\.bT*PjX`B4Y~ G#\j|eߓs8+2BLFTYjm[ k98ޞ8!h*% {nBӱzAW C'dO"aȎyhZvh6vqeT ^uwݍ?8X\\pnN'^~? ^,j?1J!uBΖy+Gv7~JBwO?:=5l-2 9[U$OwK"~5 G^?FD0nWݒ5ڵkSghuDM`;;;hZh4FtӤ1M3&^.C.C>G:Fv\76ԟYLSnL<òv'GGx<EmW/qu\`3n[OZu棷45 :u9GÇ) tKrl6 ! L&W2 ^~hG?{g\5. ^; U"ϣR ϣT*ſ4+d#""σh` ?*… 8^?l( (1i"n'T0 q||~>p|| ߗKEBf,crXXX2w:4 x7oAjF/C M\gYTU`ii 20ͳ߯< ӶWQ > o=_t>}lt: HtW+<  Q߹Li͎4O;{.[GGG8<R*FL&˅v;Ru㳂>6bf}:Q:m/Ӯkc͗dHᩂ&dSuM_М_!vwwϫ㸮RXv:u?IjnhR uex*%- CÇx>#XF\l#Ot:F&eL/?fcMHFboohh6h4Ejj!LSn+tdq C1/uyX.xpiyrCv&뺨T*q3Ș1#ȉ^Çx @~MaJ˨jXZZWt4FD\c tB ØIi T0UvE߇;n|?n<0 \KKKHqBIVibqqXXX@ZE&A:zsJ@l@isyh7bbcrG~pv {rG;& >_ +|͍G`*H0B$5HRxNcىTLfSհyf#Yhۨ'4n$zA===)Zl[~h4cxNNNtblnn4Ml4BDVX__GXDPlu]JT~IDATPEr 4H/@]!edߝc,>napz)Z-H_!h;j4i2J,Kn_y#.bϸCMG,ɶ'p.GDض\9d2qS²xvv>+TGGGFnǏ^nc4AuQ(5#"xB/^zȮMB88lU+4Y F|C>Z{{89h$ GOaYr%uD$zl 1tp|x]<]/>8K~A|ǿwƏfE۶_BOD:U8TɎ2J8\f'U G4~G R(P*P,fEQQhɓ'1!OOONߟd ܸq#Ncȹ/iNvmI" !9!NOOq||NJP,QP.xPNNNN>Çl62 |+++qZ|ADF@s98CJvvv)rxG%*k`Z2&|A1888q>t+ǭ]LxܽCBuZG.Yu H -HAF#t]4/qP.>q %ɓ'$.0@ZbyyJBz=b"xCʕȵZ W\[GŃ Ccx7d:exy?eYVsd2yF|toQ9x[A#<>eq%Ðc|#?PPlZ8===rA 8h4hZ8<<15!ͩT X__ǭ[pƍ0Q$71x0 A-//cssxWq0ɣzfjxIM]ckIGgs# ;w|[+m3>f?躓m:Hћv`0q(n`v[nB"#5/Aƕ+WM,../+ɠX,baa8)auu*rLS~;Clp>Yk9yxxxit,|[YY&ְ\ND,ܜON_qn 硱+vw!$yYzcofe '(¡z ,"{ "Ȋ(xr"eeݹ]Vv{Ugd!]=wgv~dVeVdV/E{aw7^H,J%]e dDzvz.pmhZ&O , z"Rr2/q|"6 鼮jr _WҥK6\u]zT',VVVR d6 #&0&_QʴJrz*7_H2mNw,..jqأp4AF{D0FvwgB@zFQ\)$)r!4Q4eBJ!oI+;:-c-F]ӔY8lnr e$IMN)eRv^x!%Rl4X]]mnji #XI_:'eH%*a岜Ӓ$ $ d;ć[[]u=wBgFKU._B|>4I,TBOiI*T>0dT*q۶aYrZiʈ/m[εV}l6^z dSpV:2D:4S{-nWI( C:4h!qY8C],_B8tMcz=ՑŢ QUU,..X,^;WDjhב%IK!DQ H0 Sj< H samm V ժ#~e&H&7ƲaT}"$I;Rat}f)Rڈښ⸀$ I`n ?F^8S{ >3sa)R I"B`6djZ!H@@vZ'}G.4lS~3<\v V+b,{] %:IfJ " EAz^?!\IC#.I $p77+aAlxA`8,h朧a,41i4jc扨vz$9:nӃ VVVERÃRV79E377Ʀy Eq3F=s2}€! `"<!Щ,ɀ_M3@6|XƚB5(5KJ6uhT+z,O:еh饀 RMVK^NiE=a%t/14pk/z|n f7^#ݯV~8 H`gg_0 9`L*ƌI$ #A*r8aTmO+JXZZBلaȨG*su]O%' (UEH}Hr$6b1ذBӾʥΕnG;ן PBH5Y$ŨIBIsRInO; C5nȚW: :~/DM,I-c C`?Ơ1 p]ɟߘzĹ yt:7LM~\쩧a7"V%iSFLRoӮIb㱜tp&6w32CoG ߽p4lVr]w5˜˜A dIdCsھZӎ q\l2y\ӈp֘vMOz@U\֍b4pww;;qyW[u}skk_Q"]E+(^.g֒k%M#ӃJ>*?&0~Dt=|/3k( sx;wpttu~lzp^_CT I<8)Q$ IV {P}ZRo<i[8<8)GWool|.:;enE_҄X=cf;N,+M'7 I+P'ݤi?p!0d&x):6>:vp0^_B|s{{;{#ƃ9b^ԜŴufgZ siM!ݐI(URdTjG'(I=X\Qg?k~ˌqw/z=n w4Z5?>)f4;A&YEI8FZy漤4Bdj|5[wɧ \GJcȥb->Iz দir1N's5[*J/U]ח4Mk>kF0 ]7 6400v@"C$9G9bEEQ$GIlrw}{?wR?ןhM'*` RiP(Y$+1341f(0HdBDAP$@r-0eAqBlL.C"OOO 4S\]IENDB`FRAMd{Z IHDRg- IDATx^ydI~;3_W]WM\]R< MixH ,P Xe !að)S ۲D4E2E5ܝݹgʪ;_3Gedˬ^~_/#`A X2+:l:Pс8L @/N8~|xR!'`Pf@Mcn f]nq4M;du +n`is8"4ypCaq( wCsǁ K :PӀ[o;KF>,^-lf2aۺ0 X0:4MSM9GEa"Fqay~Q0cSF7<a\+:ΝB>\>T*rPfpyݴmfa۰, e4) FZO<1A )G#~n<Co4vNO? 3.!]Y`g+rRT*j|`EYRabJe|v&L&J@0fj@G8FS}F#!!:6.An{=n~;`[~ov Y@>ckJ_W*++|),P"rr: ,<2WӴ4m$pEXh y<b0`4a0`8`a~zh8x`0l7﻽o{n7V/? ( |{PwrR^,YVӜ\K%dلhm4MX42df88i8FS}?ьtu]`w8D^nGNgtlN~jUc 04`(? P~s(u\5,--ayyjF\bCs1|߇yhZz8881p:vnV>>C:P)wUVVso-R+Z"*2J< lF6iIq^*@AZ\ׯ_[[KvuiI[Z[cZ J|>9\?ni@a߇hZh8i6:>i~NqV恲^qs.mlhlmV/_f7ndkkXY]EVC&I4ܼ~4#MfYqFvqxp1B~&4,Fy~񱫩 SWQ*חK2677FP8TaGZ&&GfZmNt^IzΨ_⋟rZΎ~ v hX,"01Ϣu]G&IFjN6l9fqEHM끏;T*~nn.+:֒\4GEB8^(@iвamrQamm zk5ƲY;ky0zF?zso/u׀c ƍ֋/~ǭ۷7nkׯҥKXZZBXD.K.k8$*2I 9/}*iò,d2YmVmC>9 zx|[ TxnJj?^u'^|/y^s׮assZ \.@Utr͋4PSMӒJRA@RAP`N.aXm:oz˒׍[@Zkw׮nno[X[[CZEXmSy 02j>2T{Ըy2Q4#`&l۞,?a -\7[-6^s'``+ֵkյ_;/TڹsGKX]]EPHV0cS=U GI-fm8qPՐd40A+Kk6y5_߳_aJҔSOZ*fI'/:'jZ5l\7^~SW]3o޾]~=YuM4 =mx.\4}5jRP:id2f`s]׎Шq_yc3>p k-_v71[/7n^ v,y> $<,vpba94M$bsU>kg~g =W7]/xƍڍ!M0Ʀ}TYŗݩf'fş.C}DEcMFʎ̭'8zdk3#`cwwvk/;w̛;;ݻD.i" iq)Y}?̊;]aL MD&x <ک5i/݈oo\>Rܒo8?y퍭-իX]_G^G>OHG&J4Y!E,Wë4jVe4P5rE㪲#i( 0MP_QNJ?:[:O  T_xپ{{n߽kavvP8$?DyPOE' HŢy-n1ag̍m=OZǿ{{|0s++?|w_bo\._+WFjFCdLhYS+VyE=)?Jâ, B^x3`#SO.|_X?!v}sǮҏ_Ν;˨VZ.}K'ıd"t<(Q+ 'C H`«i0Y~g!d瑏@h 988YXva2XŕI0oYn\7._onmiXYY8<#dG829!p) in0+,wi$[|K5ۚ|q XO Sv}֭mkv:p_Tӽ|I##H^VYaUwB,yG`YC7Xİ \?p)r}$p @~i/mnoͮ\r 0X jvd Uc5lryqLsxHˏs4hLJL,=Ij^իW3;/vvv4E uWt APS| U0+Y"QˤapO4rss00M|3jv&1xjܽtW/]2liyZ m#Ϟ@t%-Hd$-v\$ij*EZBZYf/tHװvq4[Kn<X ͟~+/-T*d2AuS}e8D 4?T 0v8O_=oX&^f HH<]zUan>x`u>ߋn=$xbV8T66me}ݸz*VVVP,af2~,PBM% cbHwQh{f$'#=1cW.  p>cCs>Kׄt_J4AӒQ6 j,0+Y,yPUMUUs1H$|*of1K_*~GOL?W| kVAdAfl[ğ/o\U+E< \p.\?il_ei?~\|S/ML>r*2镧KS<Y2T,#9 ?}0]ˁi*7obw{=k "_z;YV?_[^ΔudcgGr<Tt MR䜇E¤ʥg"J>>|jYey4V103 d T]Z&uONǚ5u]z/߾K Վh4#k:'[,y|Z{дױ*gYadrTp2MC4"uؕ ׯ#]{us?}8΅ ˫?-R ˁɝTɨV%pVijq~v' 03A%]UYv9Ā:c8,`J(X8GsxW305Pon䃢0'v.@S%Abd'ĝ9yh1с/<{O +ߧ0Pt΁8aMapQ|mWcNms0m\;eVavRd=I#B8/??-Lj>yeivrD(BbG; JkkXld7'c!h|ZЖWVh4`6+uΏR*`u`y(I,>*VFyvYKjJd:&}(Jq^F.^z [[f ?sp._J \h/U"0{(U.zPpf7Pp.r3ju^0vaL|E6*d|DDYO "JdMOPv]!KW7EM#@pid kYmֽv&= Ldy=i\jaX^)$0Rl~P.kZ | 6s*dY&/CA% "IZyqTR2Ȓ&_#Vˈv*s"E!8.Q\Yj̀O+)$ICj,V*\.ödW~iP1˝pE :J擋RjMOC7F.Ks;ϟq'Pe "QɀD3M䗗Ѹt e[+ID̕jѸ -򲠟_le`QPj*wD%h2*/_% *!M{;## A Fc"hlVV(olt:$IڋJNRATB.KvК/XφTOabeA+\ADD;ē >:5MI#<Ġ{zy9#a`E h>&esTx*[|$0|Jrm;yPS;TeZDB*&w1x_M˄"ŇbZpF,~tg_b-gx2\s &4":BA+뺙 W"1'ؚ$69ZJ%dDx4ABT28?[h40Ii$2dbӥ@T H#Y2% pHEfsy ^Op.FŒX87zͲR+X/|rT,q 'BOq ,@6"ogPNC&L0 /i]4Oj6TAPȩ54 ݲ`rȔJl ,I SǻvƿVsj|z4^#H D#o%ē (]H.a&9Oʥ7M {Nn~9c A 62""V;sOL$Jll.K%FMM t6YDZ Tad@YH4+iRy*SZD@2!!;/4?5,T8 #q΅iZE?ˮILHCEyt LgFBd#kRY#Nnk B"9C9F89dO!F- rjOOm3 ?(3t8YӶaZ4MCMKlΧU Asx|䪛)虀&ua$F%'A% #GMJ0]B%SdہMjeIVB#c&"4 V.lIJa])45[Yض Do4M5 rJKìi 䰌 ˲`9<&ͭLĹY&#b9uH#٪ F8Nf7 ď@|b(BHͮeg2`XDZe9044<h;XtJ^HXdP6 VMw |rB?= i²|a$KD&YYHkIAi|_+i\YDVuWd:+,p_c1?#P+FD_ϲ)G<< CF@2M;y>OKMLLŧ h~ D@t SmUҝ?ıhV)>DQlNJ@ Ŏ4#vqi ,[@қ"kar%Yq,:hQG {q. 5rD`L.i=|D0 .6>! ۶Q*e5g]yГTa895|] IDATQ.?e 0&4☘q&{0o!}8N!: ۆaY*P'=Mlְƃ@V8#ʂ;AiLna8gI@Czp.zNqxpn{.zc5/JU VTjqքu5!ْ4r=P:9\4|ǘ,qs p]Aq_0Cc!&afaZL Hnd CJ&K~8K'gLLIPwBz&]R^Saow݋Oyߏa k4Y\֫®ݺ(J4Z8f@ a(0T8>;9P<ٮId8с؎?e"1'Hi"DAf e14 &L hW-b$,re$5^v'vJSCr?瓦WFP|j2hd?6>x+o6`8 jR)S2׍( 584M8yI7 C |*Y1*Sc&r%M%)eOZ A,l?-MаaLȅIAB 0F8?;H"ͳHIF.  bc88N(h4MmC=p8i\,67N K5 0d(J8}V<#b;N+IOmvS9Ғ0}WpSLVJUi\T:]#1ė_yϋ'=sii $8(O_5mr:<'ʠ(t;yr G]}ALJ&A>^.rVklqY#qFz|y}0v?c@|B4|l4Z(NQm8&cR("J$~/_eg\< Ƙh~u ~4{ r-j4DzrKyY8Ge(S^ol~:qqڦe(ԊOH$!k~SIY7$64h0&yB)r>|tFJT4CHs+ݓ]"y{Z8< C0\]׻$ !E?0Cm2ΣdBxِ0рiU5,{ڕ'|it cSZTReEyqҦ{}<ȏ'W дi"8X*B.`rZgbQP,d2zq`_eH3t9ɤU )dӴdXtx&C0*AҮdTy%(0fiad`P@ZeLg4@Ch>"r*-er9#'+4ʥ{*&%ׇEYӂi_H cƆj@<Q!ѽ6.C̓N"4MK%4?<ilʊv :VAGM1 4hYM[X^R[_O5MCNLޛLkc2%dUX4|.z @ Eiјrg+W,siq@i06I=rP۶Z4:8];΋AnB5 ʚ-2a׳jUT* SMoI$6.7=L> ip*Nj.FXƻhDsx,oT+[MֈV3<v ȟs7dM48]ױ~2 8_(>~=|W 8}4MciZmM\VrkՍm<&3 Y)P.\FYɤ݁/-. O 6za(vH!&&`A `TpX* T3oiKP; ^ Ee-ǓWOD?Pu4VVXEӃOZ9C{ar#) ePmnm762 RRKfa܌ y2Ifٚo^g :!!dd>gG ,(ٟ1ON[_.ӕ4bI{ y,Jv8eiyYarY%OU; 83M(WLsTliXL}6'g,$r2!26ME4._." t9}3>| g}3vo -ҫ-~!KsS0M3VQ$s]q'iL&rxsacc5o0h8cahRIw*V(P:q%`.p= O#`]? ->A2LQնmE X, CiӲ5c"քM$dLȒ(˛k>ը Ʀ&шA@)JuO|wb" D&Jِ ]%]Uyvj94'J 7DGD(qHc2p.$k/jAxǔ дɔ,o200 킎Cf0"cI {&UHvvC*]JW]8"vrY^v`0.8|N29|_ Lh4%P|&s <n=ܽ!RZ2KxL|iuQ̖`Ll<0 !`QAQ3 ˾}.qRglzL@"<ҥ> 0 {v[*qP Cxr'iaUnɈMD0_J&IiqHeC.[.vlTBRU0xFGE] /q0p!`*C/_UקEK>p]}t<v/;Cw>X^h8S^&E+yk>9?REyrD&N)d2 FєfE&!P&4&4&GNCdS[D<0..9_<q%8C@=Fm41VVr<9>.CMwV 0р&J%RQZrsJPH(MiLyWըT \ Y(By\-Tç?rjj5o3`<6_󑿌 !ͪTW+&Tqb"6ҖM,TcU=KHo0M+i"C]tb FV cq/29p;av`jJUSŤU/ZLt󌜿L&"J(X._U#?\~syntt C¦ oT+\0Kȧ7.kb?=~#-\;|N`Q*W|"=Ng LSèjYBZxU>MΩ-`8zz2~.C󀯪q3]Vy۶h48Լؼ>4AnPeM'16Y{M#TMּeCxOFv@򕞍}I0T"mO 坣p, EZfw7{rUNO_-ZOflB+AuO'Y"q>OQ5,U"őF*7g3Z~ie˩,S/x p]>Gƹ_7|Z^ qA}u#;Yѽ6y'4r-bn(Jm; |h\F*q,&+2OFTYrEʬw1h) 1x8} c+j4~t:v~pUTP&ӈi#y6zZz^R*eBW]u#BeYgh*yt:8==p8DM"qfOml6p\b*VJ4萷^:8t/T,DWw%NoOO5'iLD8[eOuK#z4cGGGCD FQ"+U>4ih3lt]OQ(d׍ g^ 0&8}ZnC|0E]7Ը*" a'' q?棷45 *U1Z߿Sf,^vɗ\sE0&Dl6d@<,<{g~4h@Urws1Hѱ#EP@ZEP@\NiV>Od <^ <!BYXzC4bJY "v2iOGGGx7;8::%"Er\1yj$o*~q z-xד 5 B׹\zX^^V t+Ch40i/=Nc9v]I 7tW6S(@&Ӻ.a2Re+; H>qTw.SZr; ΞE+.qppJMDQlZDEÇxQR" d-J_@BO$&r]e\.qd(fOKnLt`QA>wΖv 3'KK<>t')DɧKx4\F(X]]EͲeW N^v/dsFQ~emx7E@07|_Woa8ζoR)7MBFDPE\E,jvR~0 n ZPcbA>z }5,\v:9lժu:di" 'i. JYFVLjX,&[AL&hxzzVپ8p81&~*i>&߿/xQ2Z @Trlil2Q4>99A"1H<'Z;ɠP(nS… kگx'fdASdh^2i82bvl6{NMϣK5l6QT@k-- Cw}DF|\%NvF&eL/?MHܿ?:ZV2 "4 4 ].- LQ!Z{{|[q6 jy0|Mɝu|#f6[ qTդdL J8|,b"{{{>=z ~|XZ jPTC&&dL0HcPƱz p-8<<׾5{x1z^24 |d2IBIVcii [[[jfd2S/c>G\9Z-(8yh4e!"BEA-<\ŷz0󅂓d‘`8O=j<<nGGGŽ{äOf7F[[[g(n2Nfs2NcLFJ"ȫDSn4ŇF>o{n78jڂCBO&ijXױRb@<<NH}xMCybpzv !H hο>9"kV*(0 }=AZ>bϸCMG4 4'ı1bb &M 0 ^"VC׃\LP&u{>4Mt:FoMAXDV:666Ef2hN/ ONDW&3q U/6`8>8 [~ l~+7._K¯d3b6gq#OsP$\`Y<^-a8`4f5Z% bYr\l1&*qF0 vbK}]_&IDAT4=zӄT4Zr pe ܿ8/^.">=aiBqR pQ0LX<1vqtp7{=Z=)-/w?wɏJ%4ͤ_BOF:Y8T&rs%t],K DQ*#BƐ#V)((Jr(i(MprrG%<==.|rQV&]I1\bs= 4'hS?@ib':,tct`?6Sdlw3P("&m]dHqDuqzz#t݄P۶Q*h4PT8xPL񎏏wj4 BIZBAXF@('1*( q^|Eܾ}; j$=QrVC@X8d2K␤VwÇ)JdG&,40Fu$mx<)vQ<5[{ݾCM\qF ,K,U H --8prr2`Y<*J'5nɴ>Cؘn {@g&T ovzrxWwb0nVltfH$&#!$ hZ8>>F/fUp.Nja8u]4MѣGwnMulmma{{+++T*6 ɟh@߼y[[[ut:U0&ֽ[Ԏ&+-<@p8LlF7oĕ+Wpʕdʟ QwL^~?Ϗ.1   k` 0돤t4qd@& (3Լu:y; 6f4df?1NNNDK.%h$}\. \F#Eb^8+?e%o{{w28}^.bYmwwqudzf>a2(7kkkƭ[|>hRU~*e"cspCMSweOwZo ^.r,;DisLϲ'"U=vgV. RT899Aptt ǯq.omKKK7pڵ0Q$61JdN4A*lmmagg/2j,h$mZIPD{!/ `N.CPH{:בϋ;'Q C$$i\j+Ҽ r26̈0uRիWO} X]]nv'u]8(f 2qP r\lX__Ǖ+Wmd.n""cbI}QFF#G@c!S9}T6aD!emBaJsHr_N-BXpP$TJ4Q.QVZ&/ jh !^t /_N4PPi5b"c"r9mq3ɠ8,D"|PHz*VVVb dLLDZs{o fJτmd.D [U=ݓad#}1 A[񇅀MA4H`CSc"Iv33=u}}L6q{vv\nuW{:sνeT*& CuKB)uFy F5"˓mС,wE Df8<?|]׃FAc1M~yuVFA% $APH"D1PQx*-*uGLDa,0:f)˰ ϟj R)lbe<,--1G?!3 4 JRnzpAĎFvJY8M\>8"UVAQgϞXZZy~&_ }x~L;(Є)HU#kC]m:4nW0'?2F.ZZQ! (3vAd yVZR˲ZDRM+ *#,,m;u,,,3g`ii)"d..Q"er0 /M !Jcvh4`ccZзO:J~CEww,k f=pJ3.u(#DF4AOၟG"}cO0 aee%x`j}ڰ85gT* dLIH/<` =>(:܄Wv=gJs;wfػ Ozu]Nmh6IHo|>d;oyr&6_GJ@čv_AޫȲN$@){mzO,],J?04g&r<oYBl0Dɇqpgm@}{v l6/yȥK3vE]^B>nCqY.^r%[\Z2b; %QLnxiUnb9m5MhlnnBVcNp4[7|@Qo6Weof8 #1.qX|Y(dUݻ)#dHxz0iv78 <y4qڭ}hZ0~{jsssCGRDZn͕"T$m %(D28(J=ʘ&Qlg7E¡Z<"1n^vjAgh=իWca# Y?^=c1ŘR!8&QADKtӠjNK:,'!i2k1i|,O-=' `:khKET!߱ i5݅IA8 3 _S 'E#_(|0?!](ibL˂B﵇I,_҈e4"C҉PF4 $8M1Ϧ-Umva4v.x0 <>1±VkouO|$^R2ZÆiJ0_.C>0 4dP"Y28A8L'xd k[wcˇ%`"APPʉ#mp.w0qcێnj=ofMO@D@*2~iYlYA<lStQ‰A)E.?ӤyqJ/M@X4Uߒ$j}gHCoӜ3,볙L\0eY^$iI9EQ EQdYQX"I Kh#)?~0 (21vE7i~i7L3MNӰS)mJi&"<.F!\5oT|0PM^qnod FT*rtq 'Mt ˲`YLӜ!i`pc>0!/o<ƨߏ(;{~tN; /uw<ȁ@4pH7R@/[l.ZX|P(J>|eYV*X>GTbiA6J!J%0s(<v^n}tGӉn[~Q`ov5Y@6e{\B/eڥt6vr9l>R 2 Ҏ\.t:l6D<4-nz5M r3!(.\`0h4`0x<`0p0ðN'zp0pG]7>N6bIApL;Jܷ67RmKUV|d2,[( NDmi²&N69GEqsE(!yfh4h0h8D^nGF#lw:zn/wjXag\Oojbje\.V! #5`~.^(yp]V ^GGGh48::in=Zu4|8?ۍƗ~?ҿ 6RѶ]kW~{Z*LX Q.Q,Q(f`64LӌՏ 8qxN^vnfvwfi?z;pe52~0 hN\*;m}u}mnokrd&9{2u=6jsQ5\˃jѬaàj? HP>4G?_]¥KT76bƶMET*8nhQ0fs.Fҥztb1fF&imZZ>Ӄ~Szz3 }R UK⿶yYYܴ+++V*(JfqqxQpOҌ >FZ6:Z?OxA'z>tj|d5`(j?uY|]%uT*RXc7H3d:FEjp]nGGxPka(z9`ow]m5ZRE~˗/N]VWW0rܙ8jPQCQxZ{k;VSMN FHϬo˕ܵ}@VC>G:aߖ1ϣu]G*GrN:l99fs{DMGF}\M?Jzoog.+&666⁅\42D!R]Q-y4hY0 ضb0 u^ c鴝~rdR//ypЗ}5eX>u߸};oܼݽ~]K.aee|L&QqITe8/@NsQTM9eYHRȤ,m۬چ}bՠ(I0|tB\э7ۯ]ԫ[6* 2LS+yI$Zi ŃRZBl.ǜLF ?ofY~}(KzwrTw ַww]w666P.a|d̯L4՞5jjz& ۶ˏfp}_8 6m |=Rxl ^}nJa-+˗/c}}\.^`T Wrσ_4' &1۶8ARA6LèQ/ C^/n 'i߻_g7o ŒSg'x|&Ln }vR n#hձJr/;~q^}饟꫟yN{۶gVUE+Y&\EY\4}zp.eXNdcll[XV:SiۮVltֳ #`9qW?yeo|Mmڵx q06mn4#IҺ rIA0&!J!Nl4a 93f\ϧv!f4'`6vׯkٖ4~/SYU ̏O8<̋?] 9 C0`&C_}lznpL{_u|iݺsd24-A$<-6>8.?x^/yqˠ0~iHRbo.4-u?a^7v)[խuW}go}%mdYcD>|p[9Eª.JG-偉iEA`s\*P}vΝy>j q >@ C1W'"[I* TX`d6ϝ@DT*bp<ڝ+c5p`۷+d+W*FY|,}9`Q) mTw>!G2/g1o{!q(e0MLMˎ~Ϥ-~۱+Wmwwkkp'<3Z/8̀d(i}@Irya繫H ,,t>Z"0dA۽e?f?ԻhU*usۻ˷o7P*`F|u]?Sq2dB.KB Y|w  Www_e[WX,0xKI| B(3 # D&YRpř?]~ `2γy"gyL*;VMcS/ˎvf]?GJKcq\v.uJ۶c'YP|g/U.}x^8hIH*\7 @ZP(`mm jN6Y_| j:⩚loص[^ATB*F3#^UHe8r\Sʂ UN Æ\e˿(\R8M<'^&!L*CBЃle w4屸 P)~MիX[[ y)2Y>4])iAQ\OYy#28T@XD&C:0t8]Y7nWK"8 هf픛0~qT&30_B.EřEa *TMi$75o.Xs2bWiY fzOТ^8aecG/_]Y[c5T*:wD&RrCnGOqu4?,,*"?j*TFSu]GN!bЍ,Йٽ{% \p/H^~zmw_tyQ.g~2It&$ jEPU{ s?\IP-\S*TnI&66t3 g?GX&W;;nu{;}%VVJ>u5^{e&Ymx*%AmQ AȄbl4jW$OBMgr'GQ1 |AiH_> MS:'ߟ]_ckkXhAڏy#7՟^%/eVļj *,d򩸨#$M Ov&E4]69Xd0v5mbNl] ">`VVVWSjj5XJyT _uLD"yD ,& r%yAvjBrԲgT! A'hi v6RL|b}.&5]zvo|y%T' 2MQa8l*ٟ"MHOJ0X2Se/)}q|rfu{ ,%Wٖ&S,vvʊR2# Ccx7ShJ}<, 2} 8+ouK# kA00;aMs1|GZ Xmno@Q]. =P2p*|&O;r'Ƙؗ,dyV_&~E8D #Fe[.9eKgժS]]ejm4OSIqd- Fne!HV&E5${fBB FFvc[[NY,ॉ\,EjT67_/jjlێ] T]D8Y .jU') 0 +?՗Rtt/>1z*6^y;;f?Sq._͝ LesFS!J['C~_dɚp*Eׯ\)Y_IĹo)[jɴ cdHr!yq e2ʂ|RU"`lvw 5lWU{y1*1=?9MLӠRHjȬR6kV}`~,Nj!ˁ1KZ>i! .o KJ_%l?H "=3OͻWk> 9qQi028++mcx-b!3ju/W,jJl 6s*dy&(C'A% "IREqTR2Ȓ$_"V%VM0O"b5 f\^ΗfTbbmkKy/YdQ:\'WUpv꼩$r~/<F&Br# eZDB*&w1x_y E#"Ao`vD/- z< af2HWpr9f&^ Ŝ`K7ZM+ HӱhK MT28?[l$Hi$2db%@T H_),_D>)ծI]5|dt5Lh$C`0ZMXV\ !m -yqdrʍ|9B-yESm(E#L@9`r&KZUMS $/vbEg4 ݶ[LBM> rDV_#r9S.f % "xeMG”_ zyC-L%d@Dr !Nq.>;Ov5<75jWQyx$&ET>|>N<13H$`Xx:?L_O>O!iLV.'*ZPp[B)U.Lg2,3"ľ?ydY/%#bѕ*d^j1x NTp]7&>i~rr^Ly$9GD@n "0)Pu-?gwiW-fT*۬D8j[6<&WLAL5%QIP HQ"d6YL%yfQeҋ"id?#‰Q0CDAk4B8iLB C7`7=hjڷ3fӰmxo2AĀC>F XD_ϲGr]b8b<4Ml6&.5219GR2h@.ڄv9<<Ɖ"pt!(Eo&H D` 004X*&!ag2YQ$:hQ[D -{q. 5rD`l9ZY) h4`0@F da6 B5d4m:l6[oދqCo8TN(˚ER Q!0E!8T a"{EB#ReA7 fL)  ˪~\X$o`("*TD\~@a0`4c<{[ёj(X xj9yxn5 Ӑ!K.K/ 0 'EfB-c(YvhH ##tu:4]gu1 jTlMco0[$M;{b_r4y@,G:Vrt]yv8==w_Wz w04]};zE] `2 ]u_ c0-*Z<a'rو|$[KttUˤ>3a(Y790"b14 & { uLM L$<)TC /c*)g#ǘzEGGGi3:6php4\w4ڿkmoN}AʗM** F%şgO䓍Ho!bpņ"a@3 :p3L&VJUI\T:]"n; T~206#7plÇ89>;n_(h@A@q+9a:hi̕8qQ& cG_5M+Q)QKG? }D"&`2(cr!,P`>dtvT$Pyem>Po6xh4zQEǘ%A>QFIF'*p2rd97cؽ0 kBkA440 qe8UdMEBs$TsWU©'kdYaͯbfDed@`,ea 0pN!{@a*@E9huN0YK`"IdJr[.ͻj6,0Mc_D!1'(i>?d?JdjwA*X<1py(Fw!H$@/D2`z)>eQNR!7`jTy++_ς2416S BJ5IJeE ?\)HC&+"|sI@h9ty @@,'J)ǁaΞ.ːdrIJ5S^5lb41!#"B~T \ TYIW2`!! xY.}|@R@ۭmT< Bv{5l]cgGrEhX |nV HZ![Ta2 rYqgl{;[(\mn Q 򐯋q y|@) xy}OviPaj-j$;|KPx(Plg.6)N=)|RƦ};C|۶QT`&ZGGッKYǹa!cra1U4m%J]s lΗZTWpvsL8IdQ8MvO'$[?Wj.FX},6 jevU6jEҞg}]v#."s.yϷiq:6/_f0E0N] ^{ci4M˶ilvo-tRYՋ2bMOY~ղe5L*8«.A=/` LsYu4B| n>}QUb$P"EF/Axh3hN(^M^=M@]Q[[cajN>ae ]?Ap9E6Z* r%٨nmU dLe.(5ߢpOR}!! xd>}AvYP?/b(z]v+i<8u]XB1 UeE\ƾ#x14b4*++Ɔmy^EҀDY&D@fɷF%#<y#N4`7Eze732xIn"{iƛ<*1 ɿh(isbh{akk w0(cahBAwJ%+P :I%89㿶L5mJayT4`y(M~hpF|@Gto}ǂ 0xCcs <1rHiDg,yj2U%g`@0" |a =C g|OE *V6UuSUF&1B&m3* tG Np>;@$V %_>0`2 3 ִ$xaC, ;ZsȚE&U쯺P Wh;U.5#6!"R?0W~\ԯ xUQ .ΆUHeM *20v1h x t(n!{[&CM m/'YdW櫺{*%6@N#7L!Ӑ㐦+ B/ ]"\9$7٨E&c`& ] (pxph4bh 0UhKe*<|Uӄ65#<AJThLNib+Y;4Ld擡6j7a.oq0pCn-Dd#'eif;4 ~0%c{/2Y*P Pr|_P00hw?a|C=9zFt }њOΏTrRxF#炐A >&Ʀ4&GNCd%#xa0vq98 sF`01GjEnI-Ǔ2t9 jBT"%7>tB4 F̔|U/_/L/24CauFh~W H/+WZV\u8/^Qyn;0ۼMڐͲ,xi(!1ξhrD6~HWӴIQ| i|L.8v:hzosww  $kraeEvj8y3|m,YI+Z S&xt2ʆ/S  <~];*9_Zg:9 9MIZFT2vjz<'W糚D8d'$Q|9_jbiLW*AӦjo3`>g>-!CTa"wTj!w`V-kVQ|O闁7ٿ1qtrXZ4hD/>ers ;av`fJUS$U/ZLtL&"J(X._U#?\~syntt C¦ oT+&f _)[-_3XH? z`0;dT"߫H$rOSFyi`0f^z^"iTjռIc&knWՠ}@uY۶Q8̼آ>$AnPeM'16]{M#TM׼eChOFv@򕞍}I T"mlbqV ^vs_y[Y~q.W9=XXJu}mƦ T$\q5"L "QÒ]%RRIr=p6/=eYTvj|b"b]4='$T"%௽ƻ7}?NeJup'Q+jY75[iyO"2Ff躎l6B۶W LF;p4U!Ǐ"F Q:c<3NC>~̏wc+j4Ft:v~pUTP&'ٓi#.6zZz^\*eBW]u#BeYVVVfgh*t:8==p8Dۍٿ Chh6t\'$/l%8ttᓰ_}mwZ}z9 LSle"Fغ/#|[ԫ-~8995$TG֮tW\=C#rdnx6&q,+U>,ih3lt]ffJԍ g~:1f< 1t8>q>7~M &c`}iY'c>z+IQS0ɮQ5Qj޽{x?~e7|Id9G>cb@NJ32 0q}x뭷0KSTeAP!w8;R]r9er9`iq70p]M xC<,M`{_<<GT @M<T;$'AxcPd2L&,*J7YDl_:x qerrL&jubgg'V~SA0G<Fp.?Y o9>\Sv1=,-[P.Wy~|QݹLisԁ=hcT*a{{aƛda`c<|ǃѣD@Z (k)mH:B-BX8iF 1pw]}g̖9/|saYaŠDQ4C@,TrO0`uu|Y,q~01 tnyB6!a8::BXD݆3t]x7կ~oSw->V(Ӵ,q`2"2&^0 1П,Z-tݘԣf#m`}}p41p.8z}SÅnOwZJAq`&`Q4{pIgfU*B\z@0J25jqAl_Qa8h^ǫB&^޽{򗿌Gţu0  *N!N/Mf 1b'Z;J!=W1Lg`8 q4'''~q4}4!6^чցոpa]3f:]rqeP3Șp>=,b"hãG7͇eVauu5_ѧ1ZJcHRc4$AEbR*a0_zC4dY"JMz+>Ju+++ARAZE:F*y,"LSlfmZ PQ8nI1< u]Cac3<\f؏gs9';Ʉ#p{Zx? u]t]Ç{.jq b 4gH/ wY㻏0bϷ_Q㞇'" u;?n6i>" Cl_}G{-c3L:dKpD@ۘLsz'Ĉj+t:ndOzz<BTF^zNs8|>JMlmm! CxB/^z8~ ]NTe|P|4fwţGpzzFW\._`{a< GOab%qD$(4M4FG<WK!K>͍l6|P0Mӌ%Th$$¡`L4+ybY*ŚTq4|ҏ@Z%ϣX,P( ø4]EģGbBn7QR64I;\l.g>P&}-ehI#%˂CÁH2Q6NS[v3 {cX]{IDAT 2I8"h4)NNNvcBlFP@VCT 1aKk4;޽{hZ3ii\.8\.h4xH Nh@#Fb\ׯ_۷q8LՊ&FɕJZ | J$}Vƃ)RxG&,$騮(BI~/ws%xj׿~͛-дϤǬj2aH) x^f9`Y,JR'5>:!4Mt!4j^z%\rW\~I: UGhuax?Ը3! Dfa:CG?6[Ʀ2ɄH 6f4xz?F@ٜ.]Z2Lh$>|k><:t[ |z=\5`8$fnp8D#6! ҥKVVVʕNQ(PT 虲,666]lll BV+'%k;/>/ `N&A.{&677͊;_H(k=*oh48<[+QYChT'fcM 4*Hnjny8Uvb-h@Ӧ䩯FĞl6r+Ҽ666br26𫫫q0 1y]*pU|.şDcv;Fqa+z%&eP4+W`{{V\&c4DD 2P"{E^]w0os3' |wO?Df3iF.D<W$Sx˲m6T; $ EiET՘T*( "+ vLpza.]˗c `bLFlwL~2(= ^5loo#ǃ=z&f'E}9S-Q$U~rV쭷zfnm'["+j5StZ`Вa""m5ͮP]~&tirP,榉T*j "VWWh4=ܾ};&*sT*C.$N%6]г,+J0:~3 mm-?q,+Mj6ۭϓ$yzkk :+ޭ?K S*!R4M.Ss N[ZZqZTR* * :G>'mUYTۘwyX^^K.$DGBa<H@llA@v5T]t7Mig$yfmm#g,N@j(z< Í ]WW Lӄ$IH+٦3KDӳ;q5Mխۃ.Mn0ɵk^ 3NV(!_AP (U( em:΅DD yږ ?8% `+1x ǎe%w3 l@`8I~=IDFὍkWWq$XX֢k%%b>Â@|Vb7IƉ((5m ^/_~uNU(+G(*$!aB:nly ,ar}TU0:QJ7C@$xY rC1ld0oEgi|;>Ap85nveq\@iZ$1@Py pй-Yɖ=xYϓ(Y BϬ `bap(VhZPxF?Xxv, ü Xdq*Y.0 "8N샀dƱC};BӁ`Nߎ7o-t8[ܿXڴo2,U!J+P(rG(0*cbG.nSsU,]:sJPxT.-& 2؎Xkӓy1G2iD?:ӡ0j3|Yd .iqMSM[$ Z`߇ع=Ք(z= (rviَeeYX,eYe*.J8V]9(%IGaC;/M88 " [x*'}0 0vhg{! 8WEyv/ P((iB|MqnLװ(kY ) :rQHFRF<{ǃ xsBmw" nɻ W*+i>ZpGTM{P \NK@!7ξ/ZY2AL'WDnER88 6k5]Xa\ʛ%UQ6 i3MS3ק렏 :Q4]1 8KNl8}%^RE00sIhHbaɶ,z.B޲.zVQUU4M4MSUM#cL(@rR!9c x1H1q$ɐi/McA8IrdO4e,U#;zI7$ !g !64 !sSy GzTzX,Kj!Bes9V.YP@\fL\v*T*H@0j@G(B<8ppN~n>t:|D^kۭ~h05W[?UC:, 2\>F\rFyaJ:Kgy+kBYdY3yir9$]iq׫iT H0 EЀu.F`0p0ðN'zp0pGh|0~_vhْ AȘ*P_^jX*VV +TZ&ebt:&m0Me]L6t9((E)=ϋ5#]GFF!zu|u8lw:Qqn99:n/:WfKc5Ѐ9PV-|zTJ---annT*f( HN0t]?L/ Q{Niڍß p}n(?0T#-)Wʕ?Z*KKF^g+XXX2J*2LLYYPhØlιIziJ%l٬ٶkBOo5sF }R rU7ʥҿ|w-./ە9mniUerxldM= H36FhZhh6hpw704]?9Y_[.^6odKKXX\DZE*5ܽ~4#MiDQzuvqxpjU|0QJ LW ]}WMǮTɶ_իߴV Wy|>+:VFF';;8<m ۶Q*!.>XZe,;; |3o!tGu7ݺ};6n+W077Bl6 ](d8$*2i 9+}*iò,R)dimVlC>~-8>(I4|jnw_|kʝ;X**l2٬Aa_lksAH>2Jlܻnl,kl ,--RP(w0c =Ugm Gi]jmd2d2VȥRiu?͹bq6坲y5nmqG߽kk[[-v͡X,Nh=~xچW7lO>Yf0 1<=V.Ds|_0 62fy_r|?T{!xi\7o~k}{R779ض=2Q7.2(R|g׳s-3p"#e,eZֲߘZնQi=o4V_^ ƍn&c6Iè~02&< M_ ڟcb|iR4Fᝐ0k_hz/N5@f2__Y_ݼsb^y767QDOC'B.YWPT.ဋ4Md2Zqn{i/ W4; _<sOllw6؊8~ۋ/SYU LO8IL˟T~^$_y V4QJUluY8e`VfPu]*_٨n`&2VVV0j^(E-~F~q<|Vʍ7+lMw?"36QT{fj 9M~0OOvUөveLPک-j6<v:aA/^xBri ڟ_]M_rj5R)7Bғ$_?_5O,$PcΊmV AL#J4ծ"I"aȟdOau]eY( st=fH¥5ƵkΫZnߎt]D8MнYm8 jE'% W|IvZ}qNG ]|n.W|) JRj,[hC%!]UܦUւ4Ö5,\$L\yQfZVYӌOrve!NR`aqjvz3:& ]~{o~eN?d&(p8XrB1* OOiQ7LOJHFj$vU‘޲,J%,-/67 f+q803bqmW.z{>}]gt4,gMWmpI~$_Ae!ϣVT 3S`[l,/":h /O 9$A ?"ߴYNI16^De?5|Θd2(JZ1wZ\ܶTejV.Y>),Y aݰ,ėĺS+OO'iad\i"͊d9_׿F^PavBp*ʩ~ CւY(i]?S!+?ՇRFa'i\6Rl.L0fO 8oͱbL6 ˲j;f7,?r/ ?>IHjЗ4ydQIsAeّ]OQ4;mc f?GN\}7/,-VşLc4qxC0` d>_ C&!/k`v L"Ƅ{YV=Ht/L)U2Zl&T:ôcyQ8VuJeV!˜xMzU%ɐ8@HȚŚ6Ёv.:0vAH"얔Շt/UÜgia+c 4u&ng]HLL:?o.,, σ!S6dW?+|jH9E}pISI>5

-P̄EuhA-`&Zm#_*ij\ w`S_$\Ԉ$89YgMvWe$A%E?_X{q &48ο92S xJWTBJlێ\~Q$ aQTLs'PZ4>aLWYg'ׇ<Ɣ!;'P{PjUew8Ct]~:swp{7XeyfFy[_T JW-cR xݑdui"pInU?M';:N R^(J||P.#_,"ƿM{TU`T87hQhJɐ40M/$qԆ{zy?Mg8v4 C yCL~z*ܫJ%favD8'0.yyE$rXC&diƟ "ҋ䢳jTD_n 9x=JZU`*̿S׵bt: fTT(jƟK 4H"C&m/ eѕ TN.0@KX?|rÒQ݁DR/cWV#!;31 Ltk\Y,d`&8 =iup/$(kC,v4d()\,Vjj'YnQ!0S 4~ XsJRħ̓x%=@T@-L%d@Dr 6&]Ko^?+4s^(3Ma~NJ&`Td: "z 5iD NL4_pó{ӄ. wJH4$u2tgƟF45K "#48dPX 8s< WrRfYh*U%L#,/ɟp?VLJ^t%OSmƤK5uݸh|Kjd9 M;?M5r5"Xv/F*A- :?pyBa vݲmNb^g}}.nGxO~Pх I'$P8dӔên7-lWT<:c 3A>c28,Je˲VtO_@~e g!I8I1ir[g|aQAI6i`2o CF;a~ӌyqf]$ S v.Br''˧^g v&6meAĩ d $̬0Ϛ^b-S7 N#],aF@MMt6ˬtm11sgې!iLH6ZO4$PX|1aYl>ظU݀183kxF,!ib~$[$DSi~9OK/"G0X, Wt D@2OnP|jLf.CE4PX5i8/,0T#SMӄeY1 ÈKD&YYHkI yد'+8KiImkY(a [vj*wg(lWè=&i8وJi@-f&◔& h-b$, re$5^E IDATv'vJSCr? Nx0SIFKOfۏD_|á7\p1A@\,jƣH|2 4M(074}P9e\"jfdQ!=`&wŘݲgeU dG.L l'I 0Im]FR|r".i?y0 0G^îQ(bAFn2y Ӑ!K.K 0^ 'Y"td2$s 240t,Su|'h78_l8ځNe$HvqrrGϿ/`0hvr]0Qu!Txv0z9<,ql[̚&!'78 +}ߏe+TFNg]5L8zj8 8%i!q@!niT q>& G6OYP aAu#ǘXzh4hDI8o{@439p`f;m][]ͷVWN K刢 2jO䓍E b0Kyr fvjDPDH9 E<~즺@X.cu:r<'&vwvptxvݮEѻQm8 `! 9a:}||yp3dW: 䫯&7TvJGfd(m9B;UlX.tݐD dI'e$ \&+k#tpxpFh4zAE$A>ciY{< I C$5LIneiW8X1D 1'(Ѧi>?d?JdpA*X<1py(Fw!H$@/c0K 0&SXfgP*]Ԝ')mgς\=Q&ҙ +<}?9-G3BH(ZIRz*aN](!$W%jӀsE(!}QP0 +JFYcmi0Kfy+9:Ju'A@hܗ\.g(6fl.$",LsrO asB߇ ߓ;CH)8AՀ*yQ!ѽ6.C̓N!4ME?<\^+AZ)T*p: L&S4m1k۫bm`L@<jg5|}Z3y(}?=Aalђ@µj(m^&/E`<'˜G{omm}4ZV1t b@h eYKKK7mMZZuy9^4 A0Y3l"0p~|ƒUM&Nj"yQ">߇ ci 8۸˄MrO NaĐ߶mTUw%ðv+q^)VIӴl*u#cjtRr#dĉ$©n{?!)ƣQ# @O%|`Smlٮj4Y#.[ 7PLOnD>:B$ <6MӐd:^epnF'7nMZP4fev4ͥJ.~&W.S2☕U_sI ם(k8T;pV%W=/}x1`p@4o>}QUb$P,YF/Ax0h(^Y=M@]Q_X`ajO>ed ]?Ap9E6Z*׋J5X][[yŸ!r3&-\&QkY^03`߇ 1`p⋓D}uWiBմR6?*Ǒ/bW!e7Z6 _ {'&&tZBL(>cs8NKMiKxL|IE_u |a!`Eoy'^$5l"WMueW&f7D mOVDyKc>xxمU"j(/9YB"bF#8aC8N(Y1Cw4鉵N+"kвLJ]ZAܩq v]7^Q q! +冧qe_WҲ*gi6Ie 1h x t {vX(=-zC] m/'eW櫺{*%`R8O& G$d48 Hġn-AN;M6|( 8tFQ_p?<3:i@j(|4I%nE*<|Uӄ65W {$ȍ(OFxO_,Wwh( 0٥St˗/__*$pt}wQ}Ȁ uX[Ӊ$FO +ϲPV,wiZ#4`L&u^dU{2A<5g48GjCnI -Ǔ2t9 kBjT"%w>tB2 f̔|U/_?20~wg vzj+:\w|=5ᦹݛФ ne;]2ɥ(`@н?<4-{RyԲ}eh>4s8m9~KH@vm8O,h YېF+ϲPUsk&JZ0xׂ4d41 Gģ+=LuQ6toV2p*V@uO*c*}QNckN1bSQ5z 5ifIMQ~Dq(7/u4[+ic 5:W5zi@05Tv[V%>_ ԰@r8Βl!` 5=2jҽ$Tͧ]7 !&h|(m̢L@;V5EcDG1ҬKjg[_rnh0~~2{I &rIr&5E 0*)"E M3v!!`l|,~˟{*(/Sb(xS ΰnv`0^%aIT-jYF_& B%]F\~jT7D:!Na7!כ1&n=K~9|ѣ`[^w: *TA{IDIvƒw ig4] 3-iH gѴwXj|P"aḤPc:9aζmud2uYcBIRTʂ$J_MOvclKAF~yڇ!%D䘌G-+Ս&}1(r<@E?A".4 c%`''(J^?ؘdW!7dN6 D$|<0jXDJ##TnƓ:Z~Ie˩AG(<-E5\ʛoo||*D\FE& 2V$jC]ԍddMGv:yu3t]G.CXmj+Dp4U!Ǐ"1zFxG,1mQNE@|߃3qu(87OfS% t~~0TMvO'Q@u]mz=Z-z1UʄFVeYbkTP]E !n6 LXoFD۶N6!ygc ck" 5p0W RʸK_l:ֿ>92,LSe"F8/#|[ԫ#~8::ƙ=$TG֮t׮]8=C#rdn{{{FFل8Tu=&^.C.C>G*Bmj4:3v>I__BO…&co}IY3$MD]4'\$EZ>|mNN{M&_;dYpQ(x鸑QzXG PA-iC2D~oQ[yT*yJ, q>þQHc?S㩸0~aijBr9&uM@DRd!+ ptt~.vwwqttKFBf>,crVqTfnf|Mxы B lZ Z h>TO +G{=EoT㪸0?ۣo'>'jn0QeiJ*p3hWՓ˔Mڙt 1pxxe"  0 1 pxxmbjaoo ÒEݟ?v_KZb5ZNt&4ߴd]4#kT*JuQ(# `*e4k<99AՂm۾ (p81~+ib>>>|z OTZ_ i?ҀnǍ:ԃ?VNå i/gr*S͗NɂUM^К_vvvid2J%,h`gg>p*OFr7n߂ >>|>>.\׍efaYK\nĚ11\65!Mb&>|]j`0@DFuq=|d}V IKKZ?`l>2 * 4mUnPX1X8>>>|'OJu+hZ(`!JshKK1QH,3Pcz= dN{pxx/x^O:4MC.@Tۍ~F8::j0\ٍN珴o>)X\FTa/>Hc`r JPe+2x H|3nGGۡyl/7^ϋ/SB:cQ!¶xw`e|2\E H㈯l&tGK4eYfq)ǘhL&h".Hbi,4nǓ'Oprrf׮]^`qp!]<2L"d^F&m4 !G>kEr/?i6.[,i*4iBdPc0&ݕD՚HK4y,..iyc)Gqx"D&+>bT*籹wqV'&fjzBLT*&$Z-loow1 _.177/e"UE899 <D0{睽7n}k:1z<,MdF<$a&d-8zeYr(Hָx1n*%v3rM#~0QzuG"k(ǍFjx޿<$旾7Ϛm'+ tt$dV EwtVphFcr9FA0hk@߼ykkkuct:U0&iw\$iy!4M !4:n޼k׮ڵk?)_FA vY} =jw ƽ  rݟm7wɈGFT!Zel L~:ĺ!dCfMӌh4c4͉1 ʕ+,;/a(a"cYVqT*s1vz8Qrp>o6ى5-@xQ]q-#ŚT z<|_4M"#0jw}u{s=aZ>eK&Ǥ,K!R8nqrrwy2<ϋ'$(l6nqpp#87۶9`ss1aPb(:'$[XXkZ²,8ToՊǀ&56\W!:=ϙQ􃆮ѨV2Ś2iV,njnpv^14m|Lj$h@rT*&-,,`ii)&'cK ???7 rׯ_ǧ?icqqQM$nv<&0w,,K,B 1ɡribyy׮]*QLƧi&a&8ExQ{8ÇS_2,; ?NxEE>˦m|~BsHXN-BPpP$TJ4Q*Pb.--ZR ZVh1!^rW^5P>i=b"c"Yql>ɜOšA|>XXX* B<٣:16;)ɘXj"1椡B#Z{n^nML*"+uctZ`Жa""m5ⴁeR7Ϣтn:-vJ ia8J#AARy{ii {nL"5(bYV|>?1I-K,jfXXXeYT*qjʍH&A:Ҳi!8/PC0 1اQsss0 #&۷q "~N1??@mlMDHv4uUIF$k}2 bbw7A?N9FѣGbNz=ojb9;;Rv"`DRVHHH"$pHH; lNP8D,9C.? "d7㙝xn8]cO6Qg>T=UzUp|/I8.\ŧl[UPI|Gi+y,ǥp ͂`H EUVv? B(/MUk_뤔BEtf)QI(y">_J@q^_$cOZb&p^CPoU}x^[T?05>*ŗ$8EB|hn88܃}hA@v:[4M~֭d3Nvco!_IH(5(3P7ZËuE@11:ɇ=p5R.E߉׊JG*Zc6|!Z( %3}83p+Eѕrj 1:)""<ˎ/ Ƹ"1O_P4nW,lZ VX___/4p*/^d2W'aHHf LW*mk1JXD|c>M,"bgaia,* z`Ќ۷o4q 8roSJgY<'il}@oE ?e8` JH8冡Zzpp;;;8ȇ,~ƹ!`<zq^L(m4'%p@.[QيcEe&$ 0QuMm$3+XPiU lmmvO&?nnl8&VnbYo ~fHy& ,'P4ɶ}xSF$Q$6}qj _dLUfıځuva4Aە@翑RٙߡSĥFյ_;j^kk\!*T:^GUU26}ϳ|:b繪p8v z. G#M&͌?4;wTܘE'x%ͲRJ,8 IH!Hs4hJ $H&[ϽJji.x$tʘZ:>Tts;pnveWfQ?1M}R,S uZ}vO]}VW<'+:Ak˓*g:iD^4ˡ0k|E PyqBUS 6"0'0i6WW766.#2`M\~;<~hj VWZc |ߟ=T$Ne2MN<'SqH>\U`4߇0 a4qJ9476Zk:yq…e~cu{]jNZ}8jp@E'-RB4DF%4͏oyX[b+cjqoJA9Lx<RJ=L~OL/K<% _p|)۶}p\wV3rM5K FAPPt( Iqd؄t !DJ)"R%l[.!d?KrvaT)xxxA1IENDB`FRAMd{Z IHDRg- IDATx^{%YZ;y3UztcfvfwAfY;@!! #lFPXzz9 2H`/cdDe}tOwWuUWս|8=T[Uau*<; 1 4 ̧E(@I2,:@@/xH h* (]Q5톦BU뺦mnMF: ӲR4TMSU0E؉Q" x ׶:F!\ǁ=a }h?Z# #*@E+nJ/ku={IMz:mi44MC*iSUƈA Gׅcۡ纾8u^n~{>8r_'`0ִee_f/եLTrfڲ4+UuPtda J!JA FVOBE<ALk3p;a9? _ u=o7!Y_H&^JiڧܫbBP(V*l.yfYTb|Rl6 #F:N$iS-`qa'뺰mv^n7QӉ>Nvv=7_5,dӚ^+J^\(-,\2YRV.dydd`ZrLD6EZ *7Lar yp`0`4a0m   z= 鄃^/h0G{n=Ǎ8[H,R. OVjbTJU5_,|X  HfL40:RTĊdI'YaqpƖV+zQvh4vcGv㣣_vWؕ %!)Z3W.JV,VZ\fKKK<2j2 <' UU$ӋBp]`8jF8>9vn:VY4Z‘C2P*Ʒyo(VBJVS<2" ,r Àiu=nV?,(/Rm6:z6MhNo5N`oW;`8\h3M˥wmlܮg/lyuU)˨!sҟ3NFNnN?Lfkq0CMtChNqwZv__z7jhrˀbUt;JjyqiI+jleu X^^FXDReY1fFC( 4mR5Qt^4-3 e2bZժ?k6ŽѨ1QЇ . ! jZX77}emmnqy()sKKXT*!};˲= 25FhZhhh58 p::~tr|h-`(*?U[[,^̶]cKKXX\DRA:-ؼ~,#M0 Q8.S{{i _;V޶8~ijH _*_ɕbu~^]tcuu5`rSM5P_ѶmZ-uup x怏lm[>yƍĥK077|>L& ](8$2:I 9|(T tdaB6khQ~xa@ hJ_[^z+͛X** 2Lד@IRtz4˓EQJTBVCTB6cV&x0a>%k@\*go卍uum}mlnbii r|aLOtte< DIi,GeҌ0 ci`0Te#z?opfmlݍW^7_~}r˗\.`0&=Kr*,ף^Ira, eR N+ռ0w SaP[şzַ-e7mvM͡P(LX=~xRV'-4Er3Ơi lG+JÐٞt|_jZwݷl ^e~\Oܸ};onbeusss0 cbjeR5.dpaJqiEYfDF0aa(T aT+u\ֳ #`4necǷ^ycW66k7n(eY`l&Y9i#IʺrIA0 N4M0F##A]b{WUuS_y66k*VWWf#dOJ'ZYޓ?))_\u/xv (+K_DB&<9\OEȑγgELzErJ(UT* c%|g?S^J^[uo]ب^%eck f4-~1E@< OB&9(?oZpIrJ %RUaB4hS8V/_G=fʍ͛/+/ݺkׯT*AӴ]qy)DK" /1M ⧅GgE̊㓈6 K+4- VsZwjp @忻u'^zI| [ZZBTcl b;MY&1ݬ<⦅'")y$")ݴ09<), t9MEQq.Tm_v|q'Sp HjtƍKW_+4mԀE@H0#Tb ?-,N{OY"gVyL|jB皦~=׿)J<87^][[ W177T*X'I_N#4rc?hY2WV۶;wAk $M"bjUYZa{h'"H#4Dӵrg]OOJ+2|H $L$F1:r12 j,/VՔj5o0x 下!Jf5dz(IT,SlNH򋲖J/LKO0|qeJ%3^{gH| 0tmnJ%X R6+NxE"K~J,Y",#pNR8=Eʺ8s$VWiai j5dZEFm{bWY9LqVx$ t}њ"0!0&IDs1\̗H)1JT*ZTrZg?OZƙTryZ"`STYhIa"x:?+4P>(etlNyu~H'%ECH:i41>~(t:mp̴%@M*ro2旔NHx>-i!) ]IH.|L> !-l:ædbkxD\*r8*ʟ? FXT* ,OndaΟ'p7&B'A& "IRYydR"L~E#V.%\Uո/xeUEt?G6W}rYϗJX,0((Jn~Ί,c(y3CG|×D|&B>$\//3-w.Jypp94_Xn[ىUiMnYʥSn s4H#*D. cRLu@MsrQp4e''Eҏ*y d3CˎH[@.[*myX]E Qt>B7 + P o2D.I\IInVr:Eߟd0Hc8  Xr9S.f)x#aݏ&O/ =H.>&$M~0ݢM ~gΓ‰O+wqDf& F?MM <iD HH4ZFM eiq=("# IMYb89409_R9,EQ 2L'JPJ7LeN~1>&P,Dozre ŸxYQk"IrR-Dp'&>,!i'NL#sV~|e2dnu{ kP)`f: nL? M7 IÐ# Oh(" $YqLAHfL1q҈~9Nv"_'06z[Qf@|JV dI ѯHBY_Γ?) 5OӴ 2(=Ɇ#%צ4Na+ BR.-x̊;O1|:S zo V6[3, z*EJ| ςΛ>M ["UK&' #^|')HFMfy聋"}% ]a!4݇ʂ$ |ɰi0 0mO4 P$#+- 'aZx(L>zEN_HR0 cVd">v]Gb:%&G.* ')ݴΧAVZ0` Tg ΢h'8M@MOi {!a@ʐ6 V.wJ' ,9 Ǔ$ _4ɂ"Ie\'8MiIinV>xN5T1(Qp'8E@˲iRxM$}B1.qZZtx|!F XQx_/JMX?"8Fp?(_'f1q)EU7"F b=Ibz*wVYnZx$["a(P5 BUÀDd fBĬtryQĭ 5$@?G+Z>"F h, @P;$?UkΪ/z_H&4wVt?t C5[KEQ`*c, M4lDP%΂lDPx%rشx'=$ 'C E>Fz jEn7zcPRk5V(07?r˲քuR x@`QŰY9*GwwqݰhD~?!HQtE\s lu*,t62f@<ϧ14T0<=9Q>/EH4(OC?પBÛ IDAT=y%+$T*HXr$!J$I $[,1NTk$8qAM&&v>Ļw_~M^á;DQ8RT*ZJ ]Dz,( +aqn 0V4FQ4~Iq29f9hzdA4)z( 9&RMי++":`"DA 0I1l_DR~FOU`h{{ع{7zΝmpu=o' #ȶWڭւiݻwQEӐ#@.K 0 Y<:rDى2$,v'0Dz@t9ub|IPbad)NDM% @OUUnc_r7pAqw0aO:p8ΫA|dz0JiiHT7"VX,ppdt ` P 3TuTO,"\DݓbAEkEDAF֏1>PQ?8c?~߶w] & p8Zpz;m_Y]͵VWNľ ]c H 9J+*u!d~|; bÉvCTt=;$t!xfY?\ IS,ց<f{8:< :n 0 w4 '` v:~Ѹ<8sss,+~AGQM("#OsryIGrTx epF PU5d(L){4t~1<<),I-褛?A%BdqugI*Y ޞ('+"ӲXPr< yA)y@>W TJjڲouHrd=% %ZY!}rAK+#t$' g4A5KJ$%x3J2;'`nߗl6(2dL6$(ΩNחsVrœOQ?t0 EEiR , 1I~5;=(|6_(6?a8ZV}?jV0~`4(8e-˪*1lr9`1V$\\G9:x|V ]DQ0qv. ccEd'eGeQ6W:hUN#Z(0 /,n77rkkkj~'BZTjuii隡(__VT9@EQ|S,}_ LZcr\-/[21Dd#Q(bԬ~+wQpB@Q!baQ@E&I'Oظo'0b!J]:8P/e-n[x#aPTe.NoZjZ5R* !$.tO"(&'=k>a"" b(HaSV-hq-iL:OaD>څB$({\׍EeYPU˗/3{8La'MW_]z058<);1V,Ben._[ZRVױuo,$r2!26IX41]Rx|^:TLĀ>$=q߄eear"|Iar,?Ǜ<Ϳh0 ) SXD UQ3Ԣ0c)fZ :TyL۶㟶5mJiix ; Ca0  !X*& 7xw:ZI#a|ʈcRY$PZ~61.K"((哝E@Qxw'A  QJ WB8Qu]'Ɠ@DRʄeRQ!C|0t}R c7H,ʨE@$ }LQEO&'\Ns/ @G'!a2NsuU꫐@T:Jg"OD`lK.[@"!E{:Akţx!a<sF*@6)yY=~Gh4B&H#*E[>zt=-+ JA:I`eF(}1Y 06-i>b%0[>$cy  \y_ =@m#YbX|bZ1|_\kNsEƖJ 'N~P:4B3]_x/?HhIn  > _\jZr:=-fᦅ͛htoT 4MNE4D6~HWQ<0prX>ˑ,p8D`GN[Tp0n-0~BEAֆ4bZ1|_59`5ald4MW-(^,C E zD<:DGrEGIT`8!TS E/ZOw:}0_sҴlEMs,($r]C~"NREץ&Ftel}œG㲥4H/٩Qv?#eNnu/PƠ_,sUitIэi@&A֊)H$IuA$Kr? {SU< C x0bw|S  RooF̀IŰxI !呓J粢IɖOvr85%D`j1g,c}X,A 5nn^/{rӬ8^` }OKB"& I%); &-y0*:D@̛gOCCxc'0ACFhuȶGFWg$J@ ?tv;j U"H!tNIR/VLtx}LD$P"(\ק_ߧ_<RV3UU뇇Y0P`Yļج>$AaPEM/'16^s1LL#>T׼ECpOF~#׉@}m1nY|S]z™6o1U}7s|b^ pbİiI~Qq-,PH "QSFNK~HIyD$M|uST/.%]\7 ]{[C8;ُTJ%]X_XȊ:oɉ-,'raW (C&O"8|dutzX2EBG9\#BJ077 \Qx ˀ8:e)Z~OXoFD0`fp^ j톣np.[o~]&/;֟m+V&][aȷH"D8(| }Ǐqtt}SkI#~1,)h]Mĕ+W&vX&)o>vvvnl6av,+Y>$i`9UUceYdYr9idNtCu, KQxK8l6Qtl~ߎ^%\6٬0=d)Yo*ɅaV{agg{{{,\ ɗLQ!σ16M3V2`۶q}{seAA֐_[z\.r\.bBӴ< xQ44l6mL\zcyJ4MI#EGro&y0d'vvvѣD@V >0j)mi\h{*BXeYiAutinm;w&/lSM?Ӝcœa8A@$drO>0`~~m#cqq7ҵS) a8b0nu\.B (hpgm<~o&z-ܹs[w?V(_L 10__,(3&h4BٌBngB@Yw([j9|;r$\vITժt:]ߴD_iNVtr [Nt:hx||V q}R'h^ǫB»Pq=|K_£G:]O4 48^Q?LT6f$ qDP[t:\.DV_鄬YnFh07N<˸0CE3L诤-KQO,iDA㊋粥ܓ9fb?WS, bkkk> v{gF؄Px@(Jq>?~{ݻxct]8(" _vm;%2Ll il6q=NV+~& @VCVh4me]&Z-booc;ÿ?>'e 7ߌ>[Yr̲,e(ʸ PXqh4ǽ{ѣX4V.ZGjT*1t:(0bpi ,)5 0)a0:i\!z^ۏ> rVd&Eɻe'iv{.vvv>iZSsn7@A^1w;^ v_4Fx/ݻh4vL,BRTU>_|Vj+++( Z-XB?"l۞ =|P5~z8::zc9,<fyV/P,i|=R<,5)V=t| 4Hi/u]Dr b4u{iwm'R |xt|!vuKυ" ]gliڷ2ƐUuk\)1p||#tݘP0P(PP*`Yx}O>|w}C՚(KQr9,..er9xF!\m;EEr9lmm֭[qFjIOEJZ|>˲NcxHRyK@#]a~c`^=Rs {oڍWOjxJe"M S$0$ZAB*B6ETD_i!\p%lmma{{ߏ'ԏ%( , :n:W3t IDAT ?~0#h\.j߇i"Eah48:8@^[#;wSx/v<vR)F?h[@i_v kkk~:ct:`{hud |㕖^c8BQx4Mj5\v W\+Wue||hggQ}ܹs羜"x&qQټ4|0dh▱4H@rAgyt:v0 u=~888@^DwҥjOd⁋m _!_IR[__͛7b(}^.G&vwwcCЏ?\%똟G6-,?dxx_]i6|ʅoF`.gyuck(+L' ?wR|)H|`qp]70Dٌwg?Ef0077lmmacc#&LM B!SD+a{{ * Rlj}@nggwRS=:5|%ի͛7fGV8=-VF>|익gz]j%MYxbQвe'%V!bkFz= Ct:|B~) 2.]ann.~@^iP(R@<'=eY,--a{{XZZB6_h { ZσxKqd"ְed'b׿!V>?~G8:l~|1Kw/iѨ)B6-7dҨX$")njnpvZjрS_ =}lrWy,--dl<Ic4>y]*pU|c:ۄ|v0n}ш !xŢ^#"q|r^ibuu˸r VWWje26MCDd030.~@{{#{}y"S1~׹l6cr܄ ①ž" ҧR)y OB2BQbj5&* rJv"Kpr9:_#&0*"-:u=Br^"ǃ='&'E~8S-aU~tVkuΝ;ό|s" tzo?0LQj1i<σi ZR4^%BdFɯ:P⑚U&tMEOvsp:5GBNby4!b/--accn݊I@#FsV*lll M b@To{9YV*xDyE GDN;-a89 J8vF?/>#<7y0t \(%*A,+BGD@MKUaF\,48_8"Zbcc P.c&:UU籺:I" ?c|4xTN{%vsTo`\ׅ}t4]ԏzm۶ 's# xdR?EQ PTEa^r9#S)|D d2XXX@*B\˕+*MudeҒ"h?B~e&MOՍqi|rI֎0ʗ*Ɉd->WWALC<ۋGGpcOd!a{`lMeMӇ'SO!0BHiZ \sssƖ*ȂPSI$ ?peR*_f筬`~~׮]juܢEV,+" BvŠ~|Q>ԯ0.Mbgg#4͞m?ܽ{W;[]y8?tDA} 'ا)QTÃţ(0??˗/7N#:K> ƪQTS=g$Ue"ĦQ:H$&ɤ]q}ZOߔJD8INL7-Al). yt(^|1NꇇQhF߻>~xa^aAQ>?|55)A0TNII'QrrE>kL U:.,!9:_mz=^;y}4j4rB 0y #?,^. Ơ0Y~9^9^nGGGn#6gY 1V8;)}5NF78r?@r .GYʈ#$ *+lj8% ݢ݆=v{ݏ.|+`?34흜_*Bl%qL("r腢I{e;12p$NSe(ρL@JJ4-QT:z>{=1qOv=ߡsVoMQwpnj %+LFy+?h*Y)}g>2VghnF!{='fFIݻEz2&xq4H.9]D@y*'P`aq\q("aE0J\,{f| z"J^y?6Mk~ɲmu]mxmϖ09]T8y(rP%qM˰HpgJ),4 f00 Ŵ34M8t>l4DlaU@bT񢩕Q&_;)2s<9"8!z4D$RQJ9Oǯ!W{p W*7 Ӽ*3J廦inU "YOAPu* hzc,px1JW&`$"2H4c2O#EQvϥ0p>B8k~Z~հ몪n)򸪪kٚ &DQ@U   9<s9ƹ`RX|缓񇔱jofRmiʸy뛕ju[^<q4!d(Gq@'dB"BP"y!F -M> fisƆBnfYDp+\ 1/|IENDB`MEND! k9copy/data/CTestTestfile.cmake0000664000175000017550000000050312412271773017206 0ustar emulatoremulator# CMake generated Testfile for # Source directory: /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/data # Build directory: /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/data # # This file includes the relevant testing commands required for # testing this directory and lists subdirectories to be tested as well. k9copy/data/Makefile0000664000175000017550000001476512412271773015141 0ustar emulatoremulator# CMAKE generated file: DO NOT EDIT! # Generated by "Unix Makefiles" Generator, CMake Version 2.8 # Default target executed when no arguments are given to make. default_target: all .PHONY : default_target #============================================================================= # Special targets provided by cmake. # Disable implicit rules so canonical targets will work. .SUFFIXES: # Remove some rules from gmake that .SUFFIXES does not remove. SUFFIXES = .SUFFIXES: .hpux_make_needs_suffix_list # Suppress display of executed commands. $(VERBOSE).SILENT: # A target that is always out of date. cmake_force: .PHONY : cmake_force #============================================================================= # Set environment variables for the build. # The shell in which to execute make rules. SHELL = /bin/sh # The CMake executable. CMAKE_COMMAND = /usr/bin/cmake # The command to remove a file. RM = /usr/bin/cmake -E remove -f # Escaping for special characters. EQUALS = = # The program to use to edit the cache. CMAKE_EDIT_COMMAND = /usr/bin/ccmake # The top-level source directory on which CMake was run. CMAKE_SOURCE_DIR = /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 # The top-level build directory on which CMake was run. CMAKE_BINARY_DIR = /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 #============================================================================= # Targets provided globally by CMake. # Special rule for the target edit_cache edit_cache: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." /usr/bin/ccmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) .PHONY : edit_cache # Special rule for the target edit_cache edit_cache/fast: edit_cache .PHONY : edit_cache/fast # Special rule for the target install install: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." /usr/bin/cmake -P cmake_install.cmake .PHONY : install # Special rule for the target install install/fast: preinstall/fast @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." /usr/bin/cmake -P cmake_install.cmake .PHONY : install/fast # Special rule for the target install/local install/local: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..." /usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake .PHONY : install/local # Special rule for the target install/local install/local/fast: install/local .PHONY : install/local/fast # Special rule for the target list_install_components list_install_components: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"Unspecified\"" .PHONY : list_install_components # Special rule for the target list_install_components list_install_components/fast: list_install_components .PHONY : list_install_components/fast # Special rule for the target package package: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Run CPack packaging tool..." cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && /usr/bin/cpack --config ./CPackConfig.cmake .PHONY : package # Special rule for the target package package/fast: package .PHONY : package/fast # Special rule for the target package_source package_source: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Run CPack packaging tool for source..." cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && /usr/bin/cpack --config ./CPackSourceConfig.cmake /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CPackSourceConfig.cmake .PHONY : package_source # Special rule for the target package_source package_source/fast: package_source .PHONY : package_source/fast # Special rule for the target rebuild_cache rebuild_cache: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." /usr/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) .PHONY : rebuild_cache # Special rule for the target rebuild_cache rebuild_cache/fast: rebuild_cache .PHONY : rebuild_cache/fast # Special rule for the target test test: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running tests..." /usr/bin/ctest --force-new-ctest-process $(ARGS) .PHONY : test # Special rule for the target test test/fast: test .PHONY : test/fast # The main all target all: cmake_check_build_system cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(CMAKE_COMMAND) -E cmake_progress_start /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CMakeFiles /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/data/CMakeFiles/progress.marks cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 data/all $(CMAKE_COMMAND) -E cmake_progress_start /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CMakeFiles 0 .PHONY : all # The main clean target clean: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 data/clean .PHONY : clean # The main clean target clean/fast: clean .PHONY : clean/fast # Prepare targets for installation. preinstall: all cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 data/preinstall .PHONY : preinstall # Prepare targets for installation. preinstall/fast: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 data/preinstall .PHONY : preinstall/fast # clear depends depend: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 .PHONY : depend # Help Target help: @echo "The following are some of the valid targets for this Makefile:" @echo "... all (the default if no target is provided)" @echo "... clean" @echo "... depend" @echo "... edit_cache" @echo "... install" @echo "... install/local" @echo "... list_install_components" @echo "... package" @echo "... package_source" @echo "... rebuild_cache" @echo "... test" .PHONY : help #============================================================================= # Special targets to cleanup operation of make. # Special rule to run CMake to check the build system integrity. # No rule that depends on this can have commands that come from listfiles # because they might be regenerated. cmake_check_build_system: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 .PHONY : cmake_check_build_system k9copy/data/CMakeFiles/0000775000175000017550000000000012412271773015427 5ustar emulatoremulatork9copy/data/CMakeFiles/progress.marks0000664000175000017550000000000212412271773020322 0ustar emulatoremulator0 k9copy/data/CMakeFiles/CMakeDirectoryInformation.cmake0000664000175000017550000000124312412271773023504 0ustar emulatoremulator# CMAKE generated file: DO NOT EDIT! # Generated by "Unix Makefiles" Generator, CMake Version 2.8 # Relative path conversion top directories. SET(CMAKE_RELATIVE_PATH_TOP_SOURCE "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4") SET(CMAKE_RELATIVE_PATH_TOP_BINARY "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4") # Force unix paths in dependencies. SET(CMAKE_FORCE_UNIX_PATHS 1) # The C and CXX include file regular expressions for this directory. SET(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") SET(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") SET(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) SET(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) k9copy/data/adown.png0000644000175000017550000000102312412271773015274 0ustar emulatoremulatorPNG  IHDRasRGBbKGD pHYs:tIME &AIDAT8S=Q=ovG  OۀE&MK%B?,X8De;f#!6[.{sDQx ,<O?VuݏffZZk6ư֚RZξ/|_ٶ @DT*AJ uyv]tNMEߌ1t<),3̧mv$˲~jy_iBg}l6 VeY  JFWՋl{p4r3c :*u6ϯ{ޏ4M? !(c(b>$̔$ /x_xxxx. SET(CPACK_BINARY_BUNDLE "") SET(CPACK_BINARY_CYGWIN "") SET(CPACK_BINARY_DEB "OFF") SET(CPACK_BINARY_DRAGNDROP "") SET(CPACK_BINARY_NSIS "OFF") SET(CPACK_BINARY_OSXX11 "") SET(CPACK_BINARY_PACKAGEMAKER "") SET(CPACK_BINARY_RPM "OFF") SET(CPACK_BINARY_STGZ "ON") SET(CPACK_BINARY_TBZ2 "OFF") SET(CPACK_BINARY_TGZ "ON") SET(CPACK_BINARY_TZ "ON") SET(CPACK_BINARY_WIX "") SET(CPACK_BINARY_ZIP "") SET(CPACK_CMAKE_GENERATOR "Unix Makefiles") SET(CPACK_COMPONENT_UNSPECIFIED_HIDDEN "TRUE") SET(CPACK_COMPONENT_UNSPECIFIED_REQUIRED "TRUE") SET(CPACK_GENERATOR "TGZ;TBZ2;TZ") SET(CPACK_IGNORE_FILES "moc_;\\.a;\\.moc;\\.gmo;\\.ts;k9copy$;k9play$;k9xineplayer$;ui_;\\.gz;\\.tar.Z;\\.tar.bz2;\\.tar.xz;\\~$;\\kdevelop;\\automoc;Makefile$;TODO;CMakeCache.txt;install_manifest.txt;cmake_install.cmake;cmake_;CTest;CPack;CMakeLists.txt.user;/CVS/;/CMakeTmp/;/CMakeFiles/;/_CPack_Packages/;/templates/;/\\.svn/;\\.swp$;\\.#;/#;build") SET(CPACK_INSTALLED_DIRECTORIES "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4;/") SET(CPACK_INSTALL_CMAKE_PROJECTS "") SET(CPACK_INSTALL_PREFIX "/usr/local") SET(CPACK_MODULE_PATH "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/cmake;/usr/share/kde4/apps/cmake/modules") SET(CPACK_NSIS_DISPLAY_NAME "k9copy 2.3.8") SET(CPACK_NSIS_INSTALLER_ICON_CODE "") SET(CPACK_NSIS_INSTALLER_MUI_ICON_CODE "") SET(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES") SET(CPACK_NSIS_PACKAGE_NAME "k9copy 2.3.8") SET(CPACK_OUTPUT_CONFIG_FILE "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CPackConfig.cmake") SET(CPACK_PACKAGE_DEFAULT_LOCATION "/") SET(CPACK_PACKAGE_DESCRIPTION_FILE "/usr/share/cmake/Templates/CPack.GenericDescription.txt") SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "k9copy built using CMake") SET(CPACK_PACKAGE_FILE_NAME "k9copy-2.3.8-Source") SET(CPACK_PACKAGE_INSTALL_DIRECTORY "k9copy 2.3.8") SET(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "k9copy 2.3.8") SET(CPACK_PACKAGE_NAME "k9copy") SET(CPACK_PACKAGE_RELOCATABLE "true") SET(CPACK_PACKAGE_VENDOR "Humanity") SET(CPACK_PACKAGE_VERSION "2.3.8") SET(CPACK_PACKAGE_VERSION_MAJOR "2") SET(CPACK_PACKAGE_VERSION_MINOR "3") SET(CPACK_PACKAGE_VERSION_PATCH "8") SET(CPACK_RESOURCE_FILE_LICENSE "/usr/share/cmake/Templates/CPack.GenericLicense.txt") SET(CPACK_RESOURCE_FILE_README "/usr/share/cmake/Templates/CPack.GenericDescription.txt") SET(CPACK_RESOURCE_FILE_WELCOME "/usr/share/cmake/Templates/CPack.GenericWelcome.txt") SET(CPACK_SET_DESTDIR "OFF") SET(CPACK_SOURCE_CYGWIN "") SET(CPACK_SOURCE_GENERATOR "TGZ;TBZ2;TZ") SET(CPACK_SOURCE_IGNORE_FILES "moc_;\\.a;\\.moc;\\.gmo;\\.ts;k9copy$;k9play$;k9xineplayer$;ui_;\\.gz;\\.tar.Z;\\.tar.bz2;\\.tar.xz;\\~$;\\kdevelop;\\automoc;Makefile$;TODO;CMakeCache.txt;install_manifest.txt;cmake_install.cmake;cmake_;CTest;CPack;CMakeLists.txt.user;/CVS/;/CMakeTmp/;/CMakeFiles/;/_CPack_Packages/;/templates/;/\\.svn/;\\.swp$;\\.#;/#;build") SET(CPACK_SOURCE_INSTALLED_DIRECTORIES "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4;/") SET(CPACK_SOURCE_OUTPUT_CONFIG_FILE "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CPackSourceConfig.cmake") SET(CPACK_SOURCE_PACKAGE_FILE_NAME "k9copy-2.3.8-Source") SET(CPACK_SOURCE_TBZ2 "ON") SET(CPACK_SOURCE_TGZ "ON") SET(CPACK_SOURCE_TOPLEVEL_TAG "Linux-Source") SET(CPACK_SOURCE_TZ "ON") SET(CPACK_SOURCE_ZIP "OFF") SET(CPACK_STRIP_FILES "") SET(CPACK_SYSTEM_NAME "Linux") SET(CPACK_TOPLEVEL_TAG "Linux-Source") SET(CPACK_WIX_SIZEOF_VOID_P "8") k9copy/main.cpp0000644000175000017550000001432312412313607014175 0ustar emulatoremulator/*************************************************************************** * Developer: Pauline123 , (C) 2014 * Copyright (C) 2007 by Jean-Michel * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "dvdread/dvd_reader.h" #include "k9copy.h" #include "k9common.h" #if QT_VERSION >= 0x050000 #else #include #include #include #endif #include "k9assistant.h" #include "k9dialogs.h" #include #include #include #include #include #if QT_VERSION >= 0x050000 #include #include #include #include #include #else #include #endif #include "k9batch.h" static const char description[] = I18N_NOOP("A DVD Backup software for KDE"); static const char version[] = VERSION ; int main(int argc, char **argv) { k9batch batch; if (batch.exec(argc,argv)) return 1; #if QT_VERSION >= 0x050000 KAboutData about("k9copy", i18n("K9copy"), version, i18n(description), KAboutLicense::GPL, i18n("

Copyright (C) 2014 Pauline123

" "

(C) 2004-2011 Jean-Michel PETIT

"), QStringLiteral("k9copy-reloaded.sourceforge.net"), QString(i18n("

Please report bugs to:

")) + QStringLiteral("

pauline123@users.sourceforge.net

")); about.addAuthor(i18n("Pauline123"), i18n("developer"), "pauline123@users.sourceforge.net", 0); about.addAuthor(i18n("Jean-Michel PETIT"), i18n("developer"), "k9copy@free.fr", 0); QList people = about.authors(); about.addCredit(people[0].name(), people[0].task()); #else KAboutData about("k9copy", 0, ki18n("k9copy"), version, ki18n(description), KAboutData::License_GPL, ki18n("

(C) 2014 Pauline123

" "

(C) 2004-2011 Jean-Michel PETIT

"), KLocalizedString(), 0, "pauline123@users.sourceforge.net"); about.addAuthor( ki18n("Pauline123"), KLocalizedString(), "pauline123@users.sourceforge.net" ); about.addAuthor( ki18n("Jean-Michel PETIT"), KLocalizedString(), "k9copy@free.fr" ); about.setTranslator(ki18n("_: NAME OF TRANSLATORS\\nYour names") ,ki18n("_: EMAIL OF TRANSLATORS\\nYour emails")); #endif #if QT_VERSION >= 0x050000 QApplication app(argc, argv); QCommandLineParser parser; KAboutData::setApplicationData(about); parser.addVersionOption(); parser.addHelpOption(); #else KCmdLineArgs::init(argc, argv, &about); #endif #if QT_VERSION >= 0x050000 parser.addOption(QCommandLineOption(QStringList() << QLatin1String("input"), i18n("input device"), QLatin1String("device"))); parser.addOption(QCommandLineOption(QStringList() << QLatin1String("output"), i18n("output device"), QLatin1String("device"))); parser.addOption(QCommandLineOption(QStringList() << QLatin1String("assistant"), i18n("the k9copy backup assistant"))); about.setupCommandLine(&parser); parser.process(app); about.processCommandLine(&parser); #else KCmdLineOptions options; options.add( "input ", ki18n("input device")); options.add("output ", ki18n("output device")); options.add("dvdtitle ", ki18n("title to play")); options.add("assistant", ki18n("the k9copy backup assistant")); KCmdLineArgs::addCmdLineOptions( options ); #endif // parser.addOption(QCommandLineOption(QStringList() << QLatin1String("+[URL]"), i18n( "Document to open" ))); #if QT_VERSION >= 0x050000 // QApplication app(argc, argv); #else KApplication app; #endif k9Tools::setMainThread(); if (app.isSessionRestored()) { RESTORE(k9Copy); } else { // no session.. just start up normally #if QT_VERSION >= 0x050000 QString InputOptionArg( parser.value("input")); QString OutputOptionArg( parser.value("output")); #else KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); QString InputOptionArg( args->getOption("input")); QString OutputOptionArg( args->getOption("output")); #endif k9Config::checkCodecs(); #if QT_VERSION >= 0x050000 if (!parser.isSet("assistant")) { #else if (!args->isSet("assistant")) { #endif k9Copy *widget = new k9Copy; if (InputOptionArg !="") { widget->setInput( InputOptionArg); widget->fileOpen(); } if (OutputOptionArg !="") widget->setOutput( OutputOptionArg); if ((InputOptionArg !="") && (OutputOptionArg!="")) widget->clone( InputOptionArg,OutputOptionArg); widget->show(); } else { k9Assistant *ast=k9Assistant::createAssistant(); if (InputOptionArg !="") ast->setPath(InputOptionArg); k9Dialogs::setMainWidget(ast); QTimer::singleShot (10, ast, SLOT (run ())); } int res=app.exec(); k9Config config; if (config.getPrefDelTmpFiles()) k9Tools::clearOutput(); return res; } } k9copy/CPackConfig.cmake0000644000175000017550000000640012412271773015662 0ustar emulatoremulator# This file will be configured to contain variables for CPack. These variables # should be set in the CMake list file of the project before CPack module is # included. The list of available CPACK_xxx variables and their associated # documentation may be obtained using # cpack --help-variable-list # # Some variables are common to all generators (e.g. CPACK_PACKAGE_NAME) # and some are specific to a generator # (e.g. CPACK_NSIS_EXTRA_INSTALL_COMMANDS). The generator specific variables # usually begin with CPACK__xxxx. SET(CPACK_BINARY_BUNDLE "") SET(CPACK_BINARY_CYGWIN "") SET(CPACK_BINARY_DEB "OFF") SET(CPACK_BINARY_DRAGNDROP "") SET(CPACK_BINARY_NSIS "OFF") SET(CPACK_BINARY_OSXX11 "") SET(CPACK_BINARY_PACKAGEMAKER "") SET(CPACK_BINARY_RPM "OFF") SET(CPACK_BINARY_STGZ "ON") SET(CPACK_BINARY_TBZ2 "OFF") SET(CPACK_BINARY_TGZ "ON") SET(CPACK_BINARY_TZ "ON") SET(CPACK_BINARY_WIX "") SET(CPACK_BINARY_ZIP "") SET(CPACK_CMAKE_GENERATOR "Unix Makefiles") SET(CPACK_COMPONENT_UNSPECIFIED_HIDDEN "TRUE") SET(CPACK_COMPONENT_UNSPECIFIED_REQUIRED "TRUE") SET(CPACK_GENERATOR "STGZ;TGZ;TZ") SET(CPACK_INSTALL_CMAKE_PROJECTS "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4;k9copy;ALL;/") SET(CPACK_INSTALL_PREFIX "/usr/local") SET(CPACK_MODULE_PATH "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/cmake;/usr/share/kde4/apps/cmake/modules") SET(CPACK_NSIS_DISPLAY_NAME "k9copy 2.3.8") SET(CPACK_NSIS_INSTALLER_ICON_CODE "") SET(CPACK_NSIS_INSTALLER_MUI_ICON_CODE "") SET(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES") SET(CPACK_NSIS_PACKAGE_NAME "k9copy 2.3.8") SET(CPACK_OUTPUT_CONFIG_FILE "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CPackConfig.cmake") SET(CPACK_PACKAGE_DEFAULT_LOCATION "/") SET(CPACK_PACKAGE_DESCRIPTION_FILE "/usr/share/cmake/Templates/CPack.GenericDescription.txt") SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "k9copy built using CMake") SET(CPACK_PACKAGE_FILE_NAME "k9copy-2.3.8-Linux") SET(CPACK_PACKAGE_INSTALL_DIRECTORY "k9copy 2.3.8") SET(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "k9copy 2.3.8") SET(CPACK_PACKAGE_NAME "k9copy") SET(CPACK_PACKAGE_RELOCATABLE "true") SET(CPACK_PACKAGE_VENDOR "Humanity") SET(CPACK_PACKAGE_VERSION "2.3.8") SET(CPACK_PACKAGE_VERSION_MAJOR "2") SET(CPACK_PACKAGE_VERSION_MINOR "3") SET(CPACK_PACKAGE_VERSION_PATCH "8") SET(CPACK_RESOURCE_FILE_LICENSE "/usr/share/cmake/Templates/CPack.GenericLicense.txt") SET(CPACK_RESOURCE_FILE_README "/usr/share/cmake/Templates/CPack.GenericDescription.txt") SET(CPACK_RESOURCE_FILE_WELCOME "/usr/share/cmake/Templates/CPack.GenericWelcome.txt") SET(CPACK_SET_DESTDIR "OFF") SET(CPACK_SOURCE_CYGWIN "") SET(CPACK_SOURCE_GENERATOR "TGZ;TBZ2;TZ") SET(CPACK_SOURCE_IGNORE_FILES "moc_;\\.a;\\.moc;\\.gmo;\\.ts;k9copy$;k9play$;k9xineplayer$;ui_;\\.gz;\\.tar.Z;\\.tar.bz2;\\.tar.xz;\\~$;\\kdevelop;\\automoc;Makefile$;TODO;CMakeCache.txt;install_manifest.txt;cmake_install.cmake;cmake_;CTest;CPack;CMakeLists.txt.user;/CVS/;/CMakeTmp/;/CMakeFiles/;/_CPack_Packages/;/templates/;/\\.svn/;\\.swp$;\\.#;/#;build") SET(CPACK_SOURCE_OUTPUT_CONFIG_FILE "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CPackSourceConfig.cmake") SET(CPACK_SOURCE_TBZ2 "ON") SET(CPACK_SOURCE_TGZ "ON") SET(CPACK_SOURCE_TZ "ON") SET(CPACK_SOURCE_ZIP "OFF") SET(CPACK_SYSTEM_NAME "Linux") SET(CPACK_TOPLEVEL_TAG "Linux") SET(CPACK_WIX_SIZEOF_VOID_P "8") k9copy/hi48-app-k9copy.png0000755000175000017550000001354612412271773016041 0ustar emulatoremulatorPNG  IHDR00WsRGBbKGD pHYsnnޱtIME 6Nv,IDAThŚy]GuUu׷{bٖ} xwXq<38 00&&`5 26L/Ȳ%˲%YZjz}߾w?Z$SS[uZ3~{==;Y̿0ڝYDrVu\۶aMߏqW H$s}ޱ[&X=;7ꩫ9LżX.c)4a$)DR.lf-;H,?}27^52Xɸe^ҳ)j׽ĔU[ٶ ,>/*p|싇^~k;Qhԑ4t: 'R,.J>ɣOٲ`]wnZ+,ޚun[wּt|3>X85/n{}J Zh!H2vF2?_QUpk12` 6-Ïχ&,ΣͶ|RM-ɋwO>z˝U2^Smh-%8n:ٌgyjp4u+$ucP⑧y)"蠊!AcHưRJEqds)yYC @(Sܓ ݮY-g'$3/۶~rPچbseAFS' }P6:9L cgz7*hV́T 3mZ1&IlbXۛ3'_n|&zELNiv\vqAT8@OWB}[m/M2!8> .i_Hn.p-lj8f^\BZ9g@AyG?uW4~ՏW,p{6h<{|F$Ið-L9KkQD %5-/DH JJ aiX!:9:1|@G+'@[>vɏUc~U}ߺxG+p-N40,(б"Tw!=.n0Е,fS"O8Y,a A(Њ=5 8NG4Cd3]2uWJ!kr}Um{LTofmY"gaמ,_6C *QeIwmu l; fDPPZQs뮩\2vm*NS YrXr f*9҉YڝP '׭7q_ul˖Kf./u&ӻ;2:Sc6hJP S5 !ZD,p8z|˶qz׋fw~:y&Ϳ=\IV'gᇂP l2J#5CXG7櫿t ZMa(NOϧHˮ\bh~O~lnz?.,JD 27uUbqiI!:ii'e@j"! uDkOE c)7@DIJv !cc Hƴsv:KgN{k亲,9BH LA.=WmN4ꚙ(Į݇.]lϿ}}Rɟshm_o7m8O-p4ً\a՗1vt\hۂt$1jxJH!k|[LGa!gRM<^x "[TXS3go_^~j׽ooTܧ?}y e'Lx]b>IfKȆR* B@T ݌ UY,>Kd2aN ,«@  6W81B iB4F3MS'&?]sXLw:ͦ=ǎuD@z%βg@`v/ WI!К_z߮*5tЖaEðR-ɮl3m,HөPGBhbaXeaEF+ BN@kJ:2,nVQTG *M^Ē)~o5% YUkM7M\; iz+k[ܿ?IvGxt]7VmMUG8@,,HDqvã9 FtR4*Ӗ< TSQM2NQJ4q2Idiڱ}/?r'w]/xwv6=}[~otd(-w-3h%Jv[ID?̢eISDYkX,tZ*HMy|  "vM>H3`U/*AL*شj8,۞~[ocW\y?wGyy-x-9 w%;-FC\٘:IC߀:4M3\3Qv:vX+Ե6"&CT lki<^bvVڋ,ᷝ''qc:<.48еW9D׿:@w2:!#6 9-q = i.KcJp&v|,(w2^BBp"~: Rb6RSsӏ ~n~wW\{FL$脨~ߟ{o_{p\ZbZGhtЁ-Z&BF0jQY,6[7[Nꜷ8q'y\"ʴ@*PBbJC(Kœn?ѹk6H+Q €åzxu /g/[)B_#t!tA.*ʐ*gNTo{j|saSϊR:Ar[u𫨰ͳ@ Pf}鹦v4W{0:n PZ%44qƏ$>)J+䎍Рaxhgw]Pxr [~~SbDK3hb-FhIfDlIFEuaX6ቓv;dmNRXnzB_$qi-+I7Eoj#*zH8igf":}=:  0vL})dl2BS(aXezV(eݏex~DinFģB:eN@@9;\AkE^h2`& M(ʼnwQ;3 N?v+ Ö2e_ΈѮ)N tmILV-;E*j5q8 @%tI=5>K0a*9폍=/E%NZuB3u`a5J 19C^ qZ6 UdjjjM%K 0guiH8 0ӝj#"~cOT3]ʸ׎^Em\Zn{T/p:$CatN$1N@[6否), Y͒ᵊp&|x,-Gå+[OΔ /j7׏:NҮaVa^ A4@)Rh5ci>5,'N L,Ӥ29^ysEv hR^wo>xoK۾ ϟm{:{u-Qd\$& IiczIkP,WiK:Z|aet(R,_=n\GGm<@'LQiNU`fX}?y^h74~z<7noR~F+Ea\Ĕ.*2j ZЎr45za.5/B*:Նpe bȠ(:r5ySΑM~)\O5\%Il$b3@$6OV晞LAS,J=F)Ly.&aF!AW;급J#V9? 0 aHLvDe&=&C㉙/>3_°zCF|pKW^'=]CO3a:Ah--Dۋ`jBG/w/U~S"J:x*aǶ]~PJ ProjectExplorer.Project.ActiveTarget 0 ProjectExplorer.Project.EditorSettings true false true Cpp CppGlobal QmlJS QmlJSGlobal 2 UTF-8 false 4 false 80 true true 1 true false 0 true 0 8 true 1 true true true false ProjectExplorer.Project.PluginSettings ProjectExplorer.Project.Target.0 Desktop Desktop {9ae72e58-cf8b-453e-b953-330be977b121} 0 0 0 false /home/emulator/Desktop/k9copy-project/TESTBED_KDE4-build false false true Make CMakeProjectManager.MakeStep 1 Build ProjectExplorer.BuildSteps.Build clean true false true Make CMakeProjectManager.MakeStep 1 Clean ProjectExplorer.BuildSteps.Clean 2 false all CMakeProjectManager.CMakeBuildConfiguration 1 0 Deploy ProjectExplorer.BuildSteps.Deploy 1 Deploy locally ProjectExplorer.DefaultDeployConfiguration 1 false false false false true 0.01 10 true 1 25 1 true false true valgrind 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 k9copy false 2 k9copy CMakeProjectManager.CMakeRunConfiguration.k9copy 3768 false true false false true false false false false true 0.01 10 true 1 25 1 true false true valgrind 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 k9play false -1 k9play CMakeProjectManager.CMakeRunConfiguration.k9play 3768 false true false false true false false false false true 0.01 10 true 1 25 1 true false true valgrind 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 k9xineplayer false -1 k9xineplayer CMakeProjectManager.CMakeRunConfiguration.k9xineplayer 3768 false true false false true 3 ProjectExplorer.Project.TargetCount 1 ProjectExplorer.Project.Updater.EnvironmentId {5b3c61a6-07f9-41db-80d2-e2d74b1a875e} ProjectExplorer.Project.Updater.FileVersion 15 k9copy/hi32-app-k9copy.png0000755000175000017550000000610612412271774016025 0ustar emulatoremulatorPNG  IHDR szzsRGBbKGD pHYsnnޱtIME %+^7c IDATXÝyUƟ|v{};,d3l#$!A1PEI2#Sdg,-ua1H Dc$$;w,̼:<꼧yql-[\Yj׻XS9' S3|}+?{pg;!={ouoǮK4ш  8#8n#.eXԦ鉌rK]zR@nr5$[?=n*\2 $ EsIF:zQXuzpnׯ,?'λ޻>xKE:lAV~Bt5hIH=ԀƄׅD7f쉾޾ϽxA0~=xY61S䱓N7ErvfRFQ7 a0bhI4p¸ E¼Z ЀE#|o\ (غi."@BµK``.>0="&u-˗ 3:<|p];v~SkExPAJw$K#Jc^2xj946i؂JOgdTg X= g8z,^ڒ,>+}/ZoFBjM^H W=.GENIՀ`iX5`~2Bxi@ Iϴcz Zj+{n}%] SнXΎ8QC>Et Je%نXTAT1]ʗ<\$#X`H^ʵ^]w I>?->G/x4V-x@*+Q(I334Lq jj j9vJy(ӥe@lkk@8K7э;I8S߻|eMQܽd:qD 4p15RFSܤI~Gr>t 7#zOw/=[*Ζ=uu|aO~ JFGs$44xYZg S8qŠ½|m;wX8(elDŽT2](*| X?~19%لi1Mm}}[N_xq6XLalt R!?5L5 f)S0;y;Z|V~47SлM8y7>zW7DFx~kyCognZ4ByBq8N (vaQtbBj tB4Dos5>t]X7>P=g۷4o|"ײh񪳇^}f*E%Tg1<^XCPbhALCcCH@i a*|ߔ8QK ՛L&xÐ~۷ݗƚ.JU.*gP -8PX+V&c+^ޅ,a@C٨VjܵmARQrٓ{74-$,NԌ [q82@H@7`℀ezf25z<LP~ X`'=Dhdh-;N9:_ܶnm9O([H06֮[8?}j sfUU  2< k`IZj8ëx6|[= <^#WU:J`ҷs~k;O]qj5̆am=aQ 0%Iruca ב;;ݴWPjtɎܺySǨ:yN*Aa"5&0jwx+6jHG~2ʩkZ\C`, R%fU\I4vJ3c͹H3"MC2Uׇ^%#Cm f,}M#A%6OSzj.I70IE F&TEAً32/(#O`~kuDZ2& M$8I׵sNHCI:B p}H\2TT($ *|q8T@2JiHMkt'rhOQ* 113|j)ZG=z}gfPj^F<VA`s҇Ff::*O] G0P-`*2YXv1?;"|]kk|^}L ʈy $Fhn$(U|BS5,t>n,[[y…G'T˗vw V$H\.͆I\膁x4DsNzw^zqiR[M,.S ku霯_ɦJ<]3w@ 'G|dn)]mRcQOgs8龯 (*G,/~ |xIENDB`k9copy/CMakeLists.txt~0000644000175000017550000003573112412305662015513 0ustar emulatoremulatorproject(k9copy) set (VERSION 3.0.0) # where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked option(QT5_BUILD "Build with Qt5/KF5" OFF) #Options ON or OFF OFF=QT4 if(QT5_BUILD) #With above Setting this corresponds to my check of: #if QT_VERSION >= 0x050000 message("Qt5 Version") else() message("Qt4 Version") endif() #SET(CMAKE_BUILD_TYPE Debug) if(QT5_BUILD) # Add "tags" target and make my_project depending on this target. set_source_files_properties(tags PROPERTIES GENERATED true) add_custom_target(SCRIPTED_EDITS COMMAND chmod +x ${CMAKE_SOURCE_DIR}/setupUI4Qt5.sh && ${CMAKE_SOURCE_DIR}/setupUI4Qt5.sh WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) find_package(ECM REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake) Include(ECMInstallIcons) include(KDEInstallDirs) include(KDECompilerSettings) include(KDECMakeSettings) include(FeatureSummary) find_package(Phonon4Qt5 REQUIRED) find_package(X11 REQUIRED) find_package(Qt5X11Extras REQUIRED) find_package(Qt5Xml REQUIRED) find_package(Qt5DBus REQUIRED) find_package(Qt5Gui REQUIRED) find_package(Qt5Widgets REQUIRED) find_package(KF5 COMPONENTS REQUIRED I18n Config Su CoreAddons WidgetsAddons DocTools XmlGui Solid KIO IconThemes) else() SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") set_source_files_properties(tags PROPERTIES GENERATED true) add_custom_target(SCRIPTED_EDITS COMMAND chmod +x ${CMAKE_SOURCE_DIR}/setupUI4Qt4.sh && ${CMAKE_SOURCE_DIR}/setupUI4Qt4.sh WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) find_package(KDE4 REQUIRED) include (KDE4Defaults) endif(QT5_BUILD) INCLUDE(CheckFunctionExists) INCLUDE(CheckVariableExists) INCLUDE(CheckTypeSize) INCLUDE(CMakeDetermineSystem) INCLUDE(CheckIncludeFiles) INCLUDE(FindLibMpeg2) INCLUDE(FindXine) #INCLUDE(FindAvcodec) INCLUDE(FindAvformat) #INCLUDE(FindAvutil) INCLUDE(FindFFmpegScale) #INCLUDE(FindLibDvdread) # usage: CHECK_INCLUDE_FILES (
) CHECK_INCLUDE_FILES(inttypes.h HAVE_INTTYPES_H) # inttypes.h CHECK_INCLUDE_FILES(stddef.h HAVE_STDDEF_H) # stddef.h CHECK_INCLUDE_FILES(stdint.h HAVE_STDINT_H) # stdint.h CHECK_INCLUDE_FILES(stdlib.h HAVE_STDLIB_H) # stdlib.h CHECK_INCLUDE_FILES(string.h HAVE_STRING_H) # string.h CHECK_INCLUDE_FILES(sys/stat.h HAVE_SYS_STAT_H) # stat.h CHECK_INCLUDE_FILES(sys/types.h HAVE_SYS_TYPES_H) # types.h CHECK_INCLUDE_FILES(unistd.h HAVE_UNISTD_H) # unistd.h CHECK_INCLUDE_FILES(malloc.h HAVE_MALLOC_H) # malloc.h FINDFFMPEGSCALE("swscale") CONFIGURE_FILE(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h) # do config checks ######################################## # check dependencies ######################################## MESSAGE(STATUS "Checking dependencies" ) FINDXINE("xine.h" "xine") FINDLIBMPEG2("mpeg2dec/mpeg2.h" "mpeg2") FIND_LIBRARY(LIBMPEG2CONVERT_LIBRARY NAMES mpeg2convert PATHS ) IF (LIBMPEG2CONVERT_LIBRARY) MESSAGE(STATUS "Found library mpeg2convert: ${LIBMPEG2CONVERT_LIBRARY}") ELSE (LIBMPEG2CONVERT_LIBRARY) MESSAGE(FATAL_ERROR "Could not find mpeg2convert") ENDIF (LIBMPEG2CONVERT_LIBRARY) FIND_LIBRARY(LIBDL_LIBRARY NAMES "dl" PATHS ) IF (LIBDL_LIBRARY) MESSAGE(STATUS "Found library libdl: ${LIBDL_LIBRARY}") ELSE (LIBDL_LIBRARY) FIND_LIBRARY(LIBDL_LIBRARY NAMES "c" PATHS ) MESSAGE(STATUS "Found library libc: ${LIBDL_LIBRARY}") ENDIF (LIBDL_LIBRARY) #FINDLIBDVDREAD("dvdread/ifo_types.h" "dvdread") #FINDAVFORMAT("avformat") #FINDAVCODEC("avcodec") #FINDAVUTIL("avutil") add_definitions( -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS) add_subdirectory( src/libdvdnav-NOW) #from dvdnav add_subdirectory( src/libdvdnav-NOW/dvdnav) add_subdirectory( src/libdvdnav-NOW/vm) add_subdirectory( src/core ) add_subdirectory( src/mpeg2) add_subdirectory(src/vamps) add_subdirectory(src/devices) add_subdirectory(src/mplayer) add_subdirectory(src/assistant) add_subdirectory(src/import) add_subdirectory(src/batch) add_subdirectory(icons) add_subdirectory(data) add_subdirectory(po) add_subdirectory(doc) include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/src/libdvdnav-NOW #from dvdnav ${CMAKE_CURRENT_SOURCE_DIR}/src/devices ${CMAKE_CURRENT_SOURCE_DIR}/src/core ${CMAKE_CURRENT_SOURCE_DIR}/src/vamps ${CMAKE_CURRENT_SOURCE_DIR}/src/backup ${CMAKE_CURRENT_SOURCE_DIR}/src/mpeg2 ${CMAKE_CURRENT_SOURCE_DIR}/src/main ${CMAKE_CURRENT_SOURCE_DIR}/src/mplayer ${CMAKE_CURRENT_SOURCE_DIR}/src/assistant ${CMAKE_CURRENT_SOURCE_DIR}/src/import ${CMAKE_CURRENT_SOURCE_DIR}/src/player ${CMAKE_CURRENT_SOURCE_DIR}/src/subtitles ${CMAKE_CURRENT_SOURCE_DIR}/src/libdvdread-NOW #from dvdread ${CMAKE_CURRENT_SOURCE_DIR}/src/batch ${KDE4_INCLUDES} ${QT_INCLUDES} #${LIBDVDREAD_INCLUDE_DIR}/dvdread ${AVCODEC_INCLUDE_DIR} ${AVFORMAT_INCLUDE_DIR} ${AVUTIL_INCLUDE_DIR} ${FFMPEGSCALE_INCLUDE_DIR} ${FFMPEG_INCLUDE_DIR} ) set (devices_SRCS src/devices/k9cddrive.cpp ) set (subtitles_SRCS src/subtitles/k9subtitle2pgm.cpp ) set (libdvdnav_SRCS # src/dvdnav/decoder.c # src/dvdnav/dvdnav.c # src/dvdnav/highlight.c # src/dvdnav/navigation.c # src/dvdnav/read_cache.c # src/dvdnav/remap.c # src/dvdnav/searching.c # src/dvdnav/settings.c # src/dvdnav/vm.c # src/dvdnav/vmcmd.c #UPDATED TO CURRENT: src/libdvdnav-NOW/dvdnav.c src/libdvdnav-NOW/highlight.c src/libdvdnav-NOW/read_cache.c src/libdvdnav-NOW/searching.c src/libdvdnav-NOW/navigation.c src/libdvdnav-NOW/settings.c src/libdvdnav-NOW/vm/decoder.c src/libdvdnav-NOW/vm/getset.c src/libdvdnav-NOW/vm/play.c src/libdvdnav-NOW/vm/vm.c src/libdvdnav-NOW/vm/vmcmd.c src/libdvdnav-NOW/vm/vmget.c ) set (vamps_SRCS src/vamps/k9fifo.cpp src/vamps/k9requant.cpp src/vamps/k9vamps.cpp ) set (dvdread_SRCS # src/dvdread/dvd_input.c # src/dvdread/dvd_reader.c # src/dvdread/dvd_udf.c # src/dvdread/ifo_read.c # src/dvdread/md5.c # src/dvdread/nav_read.c src/libdvdread-NOW/dvd_input.c src/libdvdread-NOW/dvd_reader.c src/libdvdread-NOW/dvd_udf.c src/libdvdread-NOW/ifo_read.c src/libdvdread-NOW/md5.c src/libdvdread-NOW/nav_read.c ) set (core_SRCS src/core/k9dvd.cpp src/core/k9dvdtitle.cpp src/core/k9dvdtitleset.cpp src/core/k9dvdchapter.cpp src/core/k9dvdsize.cpp src/core/k9process.cpp src/core/k9tools.cpp src/core/k9dvdread.cpp src/core/k9cellcopylist.cpp src/core/k9cell.cpp src/core/k9dvdprogress.cpp src/core/k9ifo2.cpp src/core/k9titleencopt.cpp src/core/k9config.cpp src/core/k9saveimage.cpp src/core/k9drawimage.cpp src/core/k9progress.cpp src/core/k9burnprogress.cpp src/core/k9audiocodecs.cpp src/core/k9videocodecs.cpp src/core/k9burndvd.cpp src/core/k9dvdbackupinterface.cpp src/core/k9dialogs.cpp src/core/k9log.cpp src/core/k9logview.cpp ) if(QT5_BUILD) qt5_wrap_ui(core_SRCS src/core/dvdprogress.ui src/core/progress.ui src/core/k9logview.ui ) else() #if not Qt5 Build kde4_add_ui_files(core_SRCS src/core/dvdprogress.ui src/core/progress.ui src/core/k9logview.ui ) endif() set (backup_SRCS src/backup/k9dvdbackup.cpp src/backup/k9script.cpp src/backup/k9backupdlg.cpp src/backup/k9dvdauthor.cpp src/backup/k9mp4enc.cpp src/backup/k9mp4dlg.cpp src/backup/k9execcopy.cpp src/backup/k9convertaudio.cpp src/player/k9play.cpp ) if(QT5_BUILD) qt5_wrap_ui(backup_SRCS src/backup/backupdlg.ui src/backup/mp4dlg.ui ) else() kde4_add_ui_files(backup_SRCS src/backup/backupdlg.ui src/backup/mp4dlg.ui ) endif() set (mpeg2_SRCS src/mpeg2/k9decodethread.cpp src/mpeg2/k9plaympeg2.cpp src/mpeg2/kdecmpeg2.cpp ) set (mplayer_SRCS src/mplayer/k9mplayer.cpp src/mplayer/k9xine.cpp src/mplayer/k9phonon.cpp ) if(QT5_BUILD) qt5_wrap_ui(mplayer_SRCS src/mplayer/mplayer.ui src/mplayer/phonon.ui ) else() kde4_add_ui_files(mplayer_SRCS src/mplayer/mplayer.ui src/mplayer/phonon.ui ) endif() set (import_SRCS src/import/k9chapteredit.cpp src/import/k9avidecode.cpp src/import/k9avifile.cpp src/import/k9import.cpp src/import/k9lvitemimport.cpp src/import/k9menubutton.cpp src/import/k9menu.cpp src/import/k9menuedit.cpp src/import/k9menuscene.cpp src/import/k9newdvd.cpp src/import/k9newtitle.cpp src/import/k9title.cpp src/import/k9processlist.cpp src/import/k9importfiles.cpp ) if(QT5_BUILD) qt5_wrap_ui(import_SRCS src/import/chapterEdit.ui src/import/import.ui src/import/menuEdit.ui src/import/newTitle.ui src/import/processList.ui ) else() kde4_add_ui_files(import_SRCS src/import/chapterEdit.ui src/import/import.ui src/import/menuEdit.ui src/import/newTitle.ui src/import/processList.ui ) endif() set (assistant_SRCS src/assistant/k9assistant.cpp src/assistant/k9astsource.cpp src/assistant/k9astdestination.cpp src/assistant/k9asttitles.cpp src/assistant/k9aststreams.cpp src/assistant/k9astmp4.cpp src/assistant/k9astmpeg.cpp src/assistant/k9astdvdoption.cpp ) if(QT5_BUILD) qt5_wrap_ui(assistant_SRCS src/assistant/astsource.ui src/assistant/astdestination.ui src/assistant/asttitles.ui src/assistant/aststreams.ui src/assistant/astmp4.ui src/assistant/astmpeg.ui src/assistant/astdvdoption.ui ) else() kde4_add_ui_files(assistant_SRCS src/assistant/astsource.ui src/assistant/astdestination.ui src/assistant/asttitles.ui src/assistant/aststreams.ui src/assistant/astmp4.ui src/assistant/astmpeg.ui src/assistant/astdvdoption.ui ) endif() set (main_SRCS src/main/k9main.cpp src/main/k9langselect.cpp src/main/k9playbackoptions.cpp src/main/k9updatefactor.cpp src/main/kviewmpeg2.cpp src/main/k9cropselect.cpp src/main/k9titlefactor.cpp src/main/k9mp4title.cpp src/main/k9settings.cpp src/main/k9copy.cpp src/main/kconfigdlg.cpp src/main/k9prefdvd.cpp src/main/k9prefmencoder.cpp src/main/k9mencodercmdgen.cpp src/main/k9ffmpegcmdgen.cpp src/main/k9prefmpeg4.cpp src/main/k9prefpreview.cpp src/main/k9prefauthor.cpp src/main/k9prefdirs.cpp src/batch/k9batch.cpp ) set (player_SRCS src/player/main.cpp ) if(QT5_BUILD) qt5_wrap_ui(main_SRCS src/main/k9mainw.ui src/main/configDlg.ui src/main/playbackoptionsw.ui src/main/prefDVD.ui src/main/prefMPEG4.ui src/main/prefMencoder.ui src/main/prefAuthor.ui src/main/prefpreview.ui src/main/langselectw.ui src/main/viewmpeg2.ui src/main/titlefactor.ui src/main/mencoderCmdGen.ui src/main/ffmpegCmdGen.ui src/main/prefDirs.ui ) else() kde4_add_ui_files(main_SRCS src/main/k9mainw.ui src/main/configDlg.ui src/main/playbackoptionsw.ui src/main/prefDVD.ui src/main/prefMPEG4.ui src/main/prefMencoder.ui src/main/prefAuthor.ui src/main/prefpreview.ui src/main/langselectw.ui src/main/viewmpeg2.ui src/main/titlefactor.ui src/main/mencoderCmdGen.ui src/main/ffmpegCmdGen.ui src/main/prefDirs.ui ) endif() set (batch_SRCS src/batch/main.cpp ) set (k9copylib_SRCS # ${libdvdnav_SRCS} ${core_SRCS} ${vamps_SRCS} ${mpeg2_SRCS} ${subtitles_SRCS} # src/dvdread/dvd_input.c # src/dvdread/dvd_reader.c # src/dvdread/dvd_udf.c # src/dvdread/ifo_read.c # src/dvdread/md5.c # src/dvdread/nav_read.c # ${dvdread_SRCS} ${backup_SRCS} ) set(k9copy_SRCS ${devices_SRCS} ${mplayer_SRCS} ${import_SRCS} ${main_SRCS} ${assistant_SRCS} main.cpp ) set(k9play_SRCS ${player_SRCS} ) set (k9xineplayer_SRCS src/xine/main.cpp src/xine/k9xineplayer.cpp ) add_library(dvdread STATIC ${dvdread_SRCS}) add_library(dvdnav STATIC ${libdvdnav_SRCS}) target_link_libraries(dvdnav dvdread) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -export-dynamic ") if(QT5_BUILD) message("Qt5 Version") add_library(k9copylib STATIC ${k9copylib_SRCS}) target_link_libraries(k9copylib dvdread dvdnav KF5::WidgetsAddons #Tier 1 KF5::Su #Tier 3 KF5::I18n #Tier 1 KF5::ConfigCore #Tier 1 KF5::Solid #Tier 1 ${LIBMPEG2_LIBRARY} ${LIBMPEG2CONVERT_LIBRARY} ${LIBDL_LIBRARY} Qt5::Xml ) else() message("Qt4 Version") kde4_add_library(k9copylib STATIC ${k9copylib_SRCS}) target_link_libraries(k9copylib dvdread dvdnav ${KDE4_KDEUI_LIBS} ${KDE4_KDESU_LIBS} ${KDE4_KIO_LIBS} ${LIBMPEG2_LIBRARY} ${LIBMPEG2CONVERT_LIBRARY} ${LIBDL_LIBRARY}) endif(QT5_BUILD) add_dependencies(k9copylib SCRIPTED_EDITS) if(QT5_BUILD) qt5_wrap_ui(k9copy_SRCS ) add_executable(k9copy ${k9copy_SRCS}) add_executable(k9play ${k9play_SRCS}) add_executable(k9xineplayer ${k9xineplayer_SRCS}) else() kde4_add_ui_files(k9copy_SRCS ) kde4_add_executable(k9copy ${k9copy_SRCS}) kde4_add_executable(k9play ${k9play_SRCS}) kde4_add_executable(k9xineplayer ${k9xineplayer_SRCS}) MESSAGE(STATUS "Found library solid: ${KDE4_SOLID_LIBS}") endif() ####### Static and non Static Library ################################ if(QT5_BUILD) message("Qt5 Version") target_link_libraries(k9copy k9copylib KF5::WidgetsAddons KF5::XmlGui KF5::IconThemes KF5::KIOCore KF5::KIOWidgets ${PHONON_LIBRARY} KF5::I18n ) target_link_libraries(k9play k9copylib KF5::WidgetsAddons KF5::XmlGui) target_link_libraries(k9xineplayer KF5::WidgetsAddons KF5::XmlGui KF5::I18n Qt5::X11Extras ${XINE_LIBRARY} ${X11_X11_LIB} ) else() message("Qt4 Version") target_link_libraries(k9copy k9copylib ${KDE4_KDEUI_LIBS} ${PHONON_LIBRARY} ${KDE4_SOLID_LIBS}) target_link_libraries(k9play k9copylib ${KDE4_KDEUI_LIBS} ) target_link_libraries(k9xineplayer ${KDE4_KDEUI_LIBS} ${XINE_LIBRARY} ${X11_X11_LIB} ) endif(QT5_BUILD) install(TARGETS k9copy DESTINATION ${BIN_INSTALL_DIR} ) install(TARGETS k9play DESTINATION ${BIN_INSTALL_DIR} ) install(TARGETS k9xineplayer DESTINATION ${BIN_INSTALL_DIR} ) ########### install files ############### install( FILES k9copy.desktop k9copy_assistant.desktop DESTINATION ${XDG_APPS_INSTALL_DIR} ) #install( FILES k9copy.kcfg DESTINATION ${KCFG_INSTALL_DIR} ) install( FILES k9copyui.rc DESTINATION ${DATA_INSTALL_DIR}/k9copy ) install(FILES k9copy_open.desktop DESTINATION ${DATA_INSTALL_DIR}/solid/actions) install(FILES k9copy_assistant_open.desktop DESTINATION ${DATA_INSTALL_DIR}/solid/actions) if(QT5_BUILD) ecm_install_icons( ${ICON_INSTALL_DIR} ) else() kde4_install_icons( ${ICON_INSTALL_DIR} ) endif() ############package############### SET(CPACK_PACKAGE_VERSION_MAJOR "2") SET(CPACK_PACKAGE_VERSION_MINOR "3") SET(CPACK_PACKAGE_VERSION_PATCH "8") SET(CPACK_PACKAGE_NAME "k9copy") SET(CPACK_SOURCE_IGNORE_FILES "moc_" "\\\\.a" "\\\\.moc" "\\\\.gmo" "\\\\.ts" "k9copy$" "k9play$" "k9xineplayer$" "ui_" "\\\\.gz" "\\\\.tar.Z" "\\\\.tar.bz2" "\\\\.tar.xz" "\\\\~$" "\\\\kdevelop" "\\\\automoc" "Makefile$" "TODO" "CMakeCache.txt" "install_manifest.txt" "cmake_install.cmake" "cmake_" "CTest" "CPack" "CMakeLists.txt.user" "/CVS/" "/CMakeTmp/" "/CMakeFiles/" "/_CPack_Packages/" "/templates/" "/\\\\.svn/" "\\\\.swp$" "\\\\.#" "/#" "build" ) #SET(CPACK_INSTALL_CMAKE_PROJECTS "${CMAKE_CURRENT_BINARY_DIR};K9Copy;ALL;/" ) INCLUDE(CPack) k9copy/icons/0000755000175000017550000000000012412271774013665 5ustar emulatoremulatork9copy/icons/hi22-action-cycle.png0000644000175000017550000000240712412271774017512 0ustar emulatoremulatorPNG  IHDRĴl;bKGD pHYs.#.#x?vtIME wtEXtCommentCreated with The GIMPd%nkIDAT8˅U]lU>ovfv[݂B+6'" PM&  !>?T M XIoݝٙs|;$|r9瞋ܗ!jYn ȶLH%m3Zk3PJʎ6j~nj+1)r71\MYe[ƈw9b*!! s̘ы1 \z<*lb~^Wk x`4 ~ČŔҚoҎgZw-+ZBNeZog^fRhGȶ͟53:v3ZӾB&q -3SF-R]-PȊN2z>j[^i͙ۿ+_(>47EJkJ k)%_\0t:o-; vv$}dXie11`gӛ Wr.MWO~d R5=LKv/IydܺzB ju\ș|aU"T7jS)bB-i0}גză&KJ복CMYJa?a(0F !ԉ1$c*FTr.vPJT feZحC+& jŭDXX͑RAþ;fFH fCk[SBδP!TsP E7.4[?הү82NB/ ;7~6nf=LJnݽ][}Zv\=W}5ϝp[x(NACq.fs{[翏,w.mϛnl`.HI!I&ŏRe2sM:yt?;BPZc['q\ynkxƾ/lIIENDB`k9copy/icons/hi48-action-mpeg.png0000644000175000017550000001164212412271774017354 0ustar emulatoremulatorPNG  IHDR00WsRGBbKGDC pHYs  tIME+6"IDATh՚{t՝?[RdɶdٖeYؖ凌M2lHl3pf89$f2'afdY2 `b0XmYm%wKRwWohY!N&g;u[U}ު[߃zޔY5¢9nۧzeYӖeM&Hd# >_Ou=PTT s5p\]`xѾwmttd@zzʕ+̟?O䒛ei15v pD-.9wSΜ9CCC<<<4F4MwQQKlohX5@I^i)5s|X^g4"lBgg ?pgg#Hm|>Olr˶r-1'%-ō]uwo xM]Ç s'SVil,ɣhB_W_W~[uu J< Q=~?04Cƍ[Yߴu _Br~ɶOQ8@AA*,*Xue#!@Mk֬>YK+x\IlWLBJď?ihhqmT0'wдnEgQ\2k͡P8 ߙ@ PyݺuOqmYK)xѴ_dIX6;ww$o|>8Y>|ƛ _=SYQJqI_ܼtrrqTT0<oMȿOS9 A(=CYO=Nǩ M͟`ڍ-!+PmY~pa;C$2EnN +0Eٰ4uRHO/bDc(m|+~uwZxf@庬5P084worF6mƿ\Jʥ)FHKRuՔi:_m3Yrs 2J##c[p8<Rҥ˾]zʲQJK $>C"Ht̯~JU_9KYZi.4`rZ<Cn\.]^ezR -H,;;jYG(++ԴoRW"g( em)|( X|;rWbdt|YG0tԢ޾kuݽre/>ses:I1EI"'twaihl:.r!J%AO Q4lk+mgDSP]5:lGg?禃(IOspE FW(++}֭~U*E]Oӧ(K^"tØ"`X#%hxe%lPϲ Lå)NჳXz M٘'Ot ̥~+kS:[4v<|EfsM7PS5[s6 lvH6`WqH86-""J#//9s48v}l9JiY;98UJTuu=YYYWD ''wis8u_x/eFnM,pY"ēŞ|. vJ6 ,s_N/@47`󆥘bpW?vX;(--}ٲznLf{Pk?uK%lX[IFX7:HXLl```9ɕHwfim9B*./arR\]nfCrvyI$#vy5~v0tMuy޼22#3u9z=Al7N'rsDxўb)eeKR.eLJuW,..U+5_DUU ?C3)Bẅ́nw54\=)gsTg48x֓8TWv:>@Ҳ"h2EFʹffqahkreNKxe18AV)%b`TG9<11ɭmllҚ ngҦk6(͍ NZZ&%ܼ(SH_}xs 4 Q GG$y R`;6-x<~$.vy*:pYWdR$ YFnwZZ,c`WVČTRb;!6mviJh|C(G,Е/=4_  O>cVĸ3y$ eF_St_MEx}5Z\z:jˇ/kF[6 ͥ%C{_rw>Bܶ)Xk(`:t:}Cuj;Kg?Ye&,4 p2:hƬ|E!LLav+P/ u{:Z=}̙ [(Wnj)-tCSǸTӥfIc,,`zi$25l۶b|`.t>yuP0LkOn|c ٷ %uŕs^8$Kyd=6['t vċ.!##ryeYZc@D_v2H3lYSW]zn9(@|F< 5)s<ȾbSSg=;ߎ%4( j8p Sͼ/K/Ǘ~wf Tw{m[ Tǎ#mሆ8:̱˥'KmDK!/'t"q")nzǎD\hezy_a Xdzzzv߿C~aXd ,`ppx^Dqhkk䳀cccdggm6ۉbUrrrxg sN?MII醿c#gCx$O)""wVSO=5`Ŋ7 bH(h4zogW*iJyy?M6]E`޽+ H$>޴݋ +zGQQѬ_PP ""p P($3<3[Gzm[8rss.6xGDDdhhHDDl~ٰaUrػwUB.pxVz;v옭&p|H$"mmmRZZ ̘+/㈈婧EƏk&""wu!244$ ^DDo.Z$?@OO,X@8 ""_}{D")..(^n{U_~KK|_-G{'J);exxX $--Mv)СCrɫ bR^^.r-.x\z{{(:UeWH7Xwީz%VTTu5Tb b]@s.Ŷ|8oXq| 47o&3ٻ v5 2~+PXX&;;@ дjժUUݥz1 X,ƾ^grb Ç_hmm~3 s `{\nnx槥MӬ,7M3C׍۶X,6 ǣH٩eFpr#o3j;I?<`3MWIENDB`k9copy/icons/hi22-action-mpeg.png0000644000175000017550000000247712412271774017352 0ustar emulatoremulatorPNG  IHDRĴl;sRGBbKGDC pHYs  tIME.:IDAT8˭PoSe~]]Gml1R阋˰Ӂ?AB_L4~2H$ t2~n ڎve]o۵k} xs=yN^tYijk>VV*3FXll||,WJ,o $O]tZ;1QuIQ]Ѳ!2$0"j=5B% 4FR3u& _rj;x" ٮ.yK/}JAqLG :Tw@k0@%*![(+X`(mmFUp8rq8׷Y@7{8+5F[C+EHrG &&0A)g_s8fp¢\6C?^B!}a i\^TP T`oŢG"Y|7*'S/oeC쫅(^L,{A4D{q)H$qvx~v'O||I]B9FFc+-, ~[U]|y+*(,ARFG}`2AWbIb g@X#a vno'{EfqI[_Ų9fVj*L6`2*ŧ8GLYYon8 p5Xa|4v؊ՉbmaC&-H`ٹG0]XP[X۽ʧ->&.W5~9؍iLs"*Vu*8hNa/ ×iӋ-çȹjL8^R(?R3ܱlYBsKեY tӄd$IT B!,埴Pʤԟ/.xKOCiB#,̩9YR9(I5Ȑ0@f0ׂP EBԅ #\4A~y?wr>g;uyͰvnBaBaBa```++ݓrJ(ns7f 3g6lfG.\{Og:Uw,ޱx/uq[Bk]5f8lۈK%ݒbH(4 #],JKeeeeevԎ:u9or)ꪓTyu_Woň爧'Uv;NyGJҫ@:RGHɑ0~2~2~4iv8::z]Ծg{V{׺`uVUg o[XC:t ]%]?@q9]~䄜`n8F9F9F`[Y;;;P888\\\_5?3#3#36tzΌhѢ1e̖`f{=8fYj >WGGGaY0886jz+nxɆ'Y}c_߾}}foWW_{ս^OӠtt2CPN9堺U– [333&c'c'c6h •+WbX 1==]мU/;l^~{7޻)U c1,ɒ,SrJN(/ʋ`|f|f|>(v=o">"@ xWx.{^ mmmuq8 F;N$H$$X%"""za055ѱѱѱpcwC>FoC m/B+4NNN:Ϋ R+`4F2Vzޤ7.e ,s-s-s333Z.h]>+|VqպZW!o0oAuiwBPOPOP*U6 E\Y:Kg:N C)2)ynw׿,,,GGGS:PRR' N,kw-A,,,]u=s<*\;)OuA]ޑޑ'''ɛK.444@WW]jUUUE-z<SSSS[NmկUdxڠ6.ե #00?y%TWWCLL [. ,1K +W8;s18t,XZk . RA*NCT Jhj+ݻvڽvoCK}K}K=dvdvdv@ץK] -- ֖-Y[~a~a~a0d 4qiRJ J JL-S@dH@B]x'Jjb TRa2enp?仒J\[p ѾѾJ^*y%NNNz^bk^`/p tԙFԈ`58ݠng7q{NNNt6^d/yl0@-Wru\bQ"U cˏ-?.d?ε?entM7]ry4uB)x*: l6h|=#Ϟ=#~0;^z%H([O~yppc˲"mB9)5M3\T#0n4|/N9B籹 J)m_m|׉DRVIӉZׯ_oƷADB!hqp5J%xOLLXJeKQOoEŗ/_~C]׿C |2lFюbOZΜ9P(I_Rx!b(Jq8vvvP.n:ڶ=s9y򱱱яNׯ&-! p8܉F~04}߯2ƞ)O&,GFF(JSUՏ#Hr-;N( D"Ν;3MDιsԩ$I\.ǚ&<#RB})/\kNIENDB`k9copy/icons/hi48-action-mp4.png0000644000175000017550000001161312412271774017122 0ustar emulatoremulatorPNG  IHDR00WbKGD pHYs  tIME2 JnIDATh՚{t՝?[Rdɶdٖe[~C&`‚3l fn)Rfgg y<aimOض=200ГHO?Ľ녆aꋊ ?_f|@|&5q\bvvv@?t_qq}@ŋϛ9s*,%7"'$-k%kq!p G t8?~ٳw}}=j,6o^KT,˲4-ٜR^+h6/:bJ(..b \Ɂ"'N>z…}Z\ >~}w훲kY0ϴj v_B+ ߞo[ne>L/­i`ZY[ֶFFFѱ?@ݒ%Ky WuyLq=~;##vڵYݸuYB agꨞHmlN`+V_B`ɂ +}x$_%!Dyg/˩aes甓x'OҸjEgQ\28mp$ ?@0X~ժUuםYKSiWAɔ_N g '?OWo}> عM*+J). O󑛗NNNPjBs_?S_"92rAyM8q9{?0Djj :zODXM +KjQGGXOOޏ$`g% ] ŚHk':{oe͞?;M''}(PgrQ4U3hlq5~WXt%i.ڎheee7nV/W˽>q|z/?y41z>sUTakB `2 Q`륬$k`l235ũ|x4+qДeZu)Oww\B0 3~a2hOSIcۋk/s'[oi82vl%8خ\%:؎_(,M kpҲ2knNr6q攨r@NNua_2pt/e6u rc›垗|\ zJ1Ml--'Md {~|,SQ"ǎ|w*,XhLΐT:E]J(HWZHKˤ$6԰vU BB4MCpDpH^!8CC|}q/-"aV.LXY5aQ&9Hb޷چvzRgdggi^$>kYI2j\QI-Ye(sK]B R \qa;Ӱ,44y?ܱV;.1nZVKmM:~/߯w<.^ʺ̬9999"F<9)o}& ,d[pl?JAz'<&6RS#2 qn^&"cy*vpU{ /% }4NPYǿg@ߑC:DqhҙӱR(ƁJ (ze yaď^|KA_3!w['1g{zz݄Ҧ]'k|KͤqY?ooݎ?=H<ᐗ D¦- xp](J..Hns ޸HӇIKw`fł9 ?iCCC/]S|`U=אt뉌 rD=ֿzm/C$<ęg/0]p]qq:6k#d6s׭gorfzcǁQPδu  ݶHVVnϢ4=9M ޏ~&'x}''O^;O\je0,zpQܧ\6_|PNS+K405H8Bttdu/"BFFFqe3ʲ0'$?wN8JoX#LaE_5,(w L#5BZ&٨I_{"4ի=iI!6>Ί8_y!=p0̢XCxa߾}hGʸ|Kbz@St46Ǧ{LGp88I86hkN]-8qi-ZJA_~)|`|lda|c._bcG$cn*?NmΎ^z鷌Q&*vu2އ AJ>(̛7YfC=@GG"?~Jڒ"  Mhii!Σ>a+_ ,[+x0:f*D^Wb<O|%wTTTUj.EgbDq(_~ uYvi_s MM,vy;v===b'ORu(,,\% 6.]tzU\Oii)yyy|>L$7!33>Gv(I><LK/,*++ܲ 0Svbx8F.?gy$_>N9y VWt:?[\\\r9 nGUՉ޷/ӓS4z7W)KV[YY9#77˅$Iضz_=O e֛jihhE$DQDQuCҌ s썿t~ֳo'ƻaÆ,S#@0+N1F:vƲ/\Mej=6mڼn۶[_\d lE۶Q sfSfVrV]VQኂ%e^w]cVe54Ȳi8N$I&9$IȲ,dP-cԓ]s +wV^mn%##I$ ˲P#!l4MDApF!]0MD(Y:#{ξ~5 }$V9׬Y‚eީSLC\ 0 a 6̰3l`֢`R?j&ʲTS^ o*Ta 2p8p8<3Ms0 3l !Wj3ӳ p~ 3sFU0T)EQEH$g5MCUU$Dxض(1~6l&??F"k27"?|+xNZb4=:00`_ G xGEss3O<MMMdggqF}Qسgaru;9+: )^@::Ξr:Ka.](bݺuڵݻwOw^ZZZ^jkkun*$Uv3򝍍ڵko%)[DMMͭق(D"n7Xz2^z%z)JJJuq"wq83tGyi7Hr 5 h?eY%p8ܭ(Κښ"E("'' GԩSB!FGGiooRPPŋ5k8{_|#a?{uBYNT GFF2/^?4!H&i4M IPχrڷo_S]]]q4z Q#%$.,K>+_'fw?o9w';vX;|(ʴ똦y@Xڰ—!cicxe Ր벱$R蒉&\:`(yݺ޹f͚e ܁@IH&΁HhBRA}}=֯x-C0X<@mb+e=wlllt HFѮS-gΜ[VY}ez:|{]8]UQ6/:DM&r!zA봨Y9z:di# Āp8lXu ./BC$4 kn`^I>n~#lr۷E<ƲA'>s4a &~g4> B%Aq3ըZ6}c{;~ w~~=X|>m( m EKW9/_miiqqEEEݜrAR3#qlO{GJpJ6h2+x%U^in?joMR25;/ET{"i{q+vMlį{W)`+DʪUv׷x"~FFDT5VE nr~WZcGx<:6h'2.\w˷Tj籴8[Oc),=5="b?}/z8tɏ ?s{<+oꖗK AmH:G^xǀ.,vC,j/bI0\\EqѨ~+dz'§Itٓ&CԑN5o QME(ozџFx<HCvZe ZړK..p7<փI@ۡ:kǗ.r|4:1fw| D=<ֳz,a#Lt?DL {JnbO[p8+oZ#ɚ<VEJ[Rw4Fkk[[;L5T@3CE㟠n1 Y]_ ObxQV!V y/>{+7W~./K 'U(XOɏ~7.`Loc Zޡш k,A/73K/˙3-tkSIr _w^?E?Ld:#K225^gu!#,y@%"..Q goaRd9osD[_cAsKGGdIFR.z˯^gN(0hqm-Hp7x M|+XkɋaZ+ u {YJ_ VSٽtLId4!iJr SPUXkqAθ{o;A_ȵ73F$'Q4:pkB ^!l nDʢ MS шI2 iR9eU˪7!4H%4[-Zшq:.Zk P \B_ͨI:%zXkʒxh4b2L "M"[? gқ% C4sZ$x̛>|5^6 D$ل-_x\+n۴Z-B HH2%z*\I~tz3v90O;GkT}tyg;<*K1Lc1t:~>khMm'砅zTྯ8) 3Q;}LgiinGӡn(᦮6c4MY6Xw=gλz,o-'CFfѧ$j~ n#"]=z%Y0ܥιbu6˪;G9PQyNQԓJW93 _SQ|uyژϥY0= Ð0 QJaL}VBkMYTdyFUVUA5`8Β˿SB ^ UXBC3ӝ2JRJm?_=']ڪOASh(.M#9/ :rN{S(8=؝_Wlbx Pki7¥OGcIENDB`k9copy/icons/hi22-action-sound.png0000644000175000017550000000532412412271774017544 0ustar emulatoremulatorPNG  IHDR$xbKGDC pHYs   vpAgX _IDATHǽ{TT9:a1#  (" ]"KP䂊iZ!KԫJtWe)h⥂ #"(09ZW{^^0{Wĕ NdX2,erY\www\Yu'ns/ FlFzzz2uuuʻiwHH)sOQPTzw:uk'c;^L>[+VZNi9I3[ΖhhhLzlz՚ؚؚAo5j4˨BP*T~t-^KRQ*JRT`]Wذayrcϖ-?oc=zY{Hi{ù r. կz z z (A~ߠ1h @.ZL-,FKKitc1}r~}>_6 jkjj HFt8A N g ;(;(;EŢb Ov?dw؏݆݆o^---|}/V4woa%f#k{ֵkg7 X@$ GwGwGw@nݡݡkZҨ4* 6-[ܷ8>666뀒[}  .i,++rD^"ƅjcoI"8Jy<@:I:I: IPR|_H"$Xf,3 {e2xIJNcc0b͸Gm{_6SLYL(t{ӆ_wSj`d\%%e/Mq8oPZǾu=װѾ&r#K~ 6E x3q8(@4D4D4 BҸ4.M6acF\ >,/^q[vJR9Pπ舝& \sv ߩjypg @n"7O< &h1c"@TD%  ^(/ p}Ew^fZ3boU7nT3==un[HZCXh8x ;~HA~ rW=qqq²²2S]N"'2y hXO֓t '[Vjqis-9@Une+̥\Ȯl-l.;_ѫ0) :II>A‾o}b Иܘܘ miҶહj 2 " <"Ix`qE"'O>j}Gw#PmQ*&\si~ݤ;7>. 7<'``G@pQ tY, \/^p;w: !!i;m+\ *BE\t6-ΰΰΠ !W?WrJ0laHÞGmt$(G_GSShZjS[t.`acs|^^^ctST1U+ce .k QBD2L%Sd3oYi L];q@Lu|dN97nip`D`Pt=L{8u}/`i-˗._f0LnRj)H:JҮ8c8 02LAfd`(U*J" @{bO)1߅/6VQ?F FcǪtVEO'l9{ίjA;_[;Jw;,ZYRKH>"[fXC-w@Kl 6^r-/Lv 4O#=:R;R;R:~jL&dʡrIpR }Bۺ|@no o o?KϣizRcZi0M?O},h,gPޠAyi!Y!Y!Y3|5_-U*{eiWB\ 2'v⧉P"}fooWF:[a a a o÷r:Nz:::555-1D CXRb!~eDD>2#)*bbFKud̺u3_9:?_P5%>IENDB`k9copy/icons/hi22-action-author.png0000644000175000017550000000237212412271774017716 0ustar emulatoremulatorPNG  IHDRĴl;bKGD pHYs  tIME +}4yIDAT8˥OTW?7f0XAd%mED ˆIФ1 4mi)E*V*J-jPā*a7̏.5iɽ={UX˥\WWWTP!<<<|/+PUx:ƶm,"L2==lvj*d2M3 G;vo%a- Ǥi2 h7nIR]71?ϯX7^螑UUzm4 B!89'ǝj C9ySSUO':_"᫬v/9QJaxF4,0mR5_ ]66[M=x@ t8KD3 ϟ%FG:EEE([uѹQK=WܿD'SCM c\`[ؾ[ӳ`Q-m5ja+NX4p5Ν;*6nJYنiPkUb,n]U%i  !D4.\STm>4d9ܼ֗+)//'i1\Ɇ?E=hLH$twwsYwP!HҘ% rgh`0f, H$D8Z^,|>e,bpp3gΐO?L1!zµ+8!\I/RdY|Fs{dK-t>R"rk.7d2:L=N%]SVeJg#ع'( PÇs0zB,}PWWG" Dҽ4NnAO8i'_L ԍB*466"jW'y216Bؿ?333a{Lúhb=Bl6}F!BЀituuDKK FLsw<>q*;Ŕ&y3(vLK b2N/D< mff&:111Q P }U(/h? )kYgXdC^)SK􊌟+urWT}EP}IENDB`k9copy/icons/hi32-action-mpeg.png0000644000175000017550000000547512412271774017354 0ustar emulatoremulatorPNG  IHDR szzsRGBbKGDC pHYs  tIME0#{l IDATXý{lTgvޙy=c{omi~|ë2f3e$IDVd8G=E ,[fi X,rov47?PclɒhĻV㳋9kNG!p  ۶aٲSu{<'l#m;V:}‘8l3_ [ݺN5䤋ڸOQ|b1q_'e566׏5mwzY i"A~OVo3J[.Ä>QVQ]UԴ.֯#(ĞW9o3=Lw^f߶o5U@NA5 R:S~)o؄}E=Fs6( #H|tr32:IQ,i*99t v݁;vڲm/۶dgY҃ H(ܘpU/+ׯ#QQPPPәrq2d WQ{~EmM 2 A*q=ѾV[[aZ䃓ѿ7lYS4:=TDw,S)QRQ&@r lbLnP$2kcYYYz,/ظvof jxhkK5" B=VQaF8s GUe)N_d͊B2trl1u^x<}f+s:N~IKӒnt{/x' }$))D)Djlw0 `/a# lic4b =4,׷nP/"j@PY^'r3=@UyUlϓf.F@JUQP4= F~9x=,)a/4 *cS:88/{4 AرoU<,q 'Cg晛p8?9r0Kk@QJ*M 9d2FU#AAL[Ƨ@d;x^Uwj*w>ehN49.;XH bW{vۛ-8e<~r-iiF"Q%ZhxQG10%q9TYH&ܩk}Y) #{(q khsH$Bޅ e1z迲K|wW A?AjDe3Sސ!c:C:J*J*BII%⤒q)&G[1Ѡx<3>݂*MG&t4=Pͱ_v`72uJQ(( H54% $viy^o[s ׮rj5,|]E=l$/7_|Gi.kohͫWyjP۰jyF^Y D-&vmYEޱǿ9YOO񱱱ERTs;)+s+,,lijjj(--ɳZY,ssP\QWGG}& ]ꎿ.F22sFcnvvU D\\XE~|4b() xN+qIENDB`k9copy/icons/hi22-action-dvdcopy.png0000644000175000017550000000215612412271774020064 0ustar emulatoremulatorPNG  IHDRĴl;bKGD pHYs  tIME7#kiOIDAT8˵_L[Uǿs{o0IfV)ٺUٟ(1d401m?7x5 0s%kT) dE3/|+`y<5[ν6d2Yu=/..&VV>ss)l!.b |Ʀ&N-sx*ZS1///$Ri|b%Tsdofr?Y[[H, Zp=tac9?6 &{CV‘#[ 刢Y Ji1R)Atv vn|2ر&{ G}iiiRUUA)(`19TUbsf P'VVLrA)c,3r)PX h3'ŮC}%e$' q 9c G}6i9i{a/CR chʏ$ !6!G9{o?>:EE Wcj~Eh:fffFc,ːe$13gu]G4(Aу+N42)lU,Jɵr;OCeYc,S],i!v=^VnĹK|c$@+i(H&PU5d$ {G0D T(y6G^P({( 4Mшء}PC,7-8^^]?dG!m"f=L& :: orݎlcOqܭgqcdӃ޾=/x$6%9,,0~a;(˯ԿT9 EqpVa.@ .CCC7׺;,fwc΍gpp!Wmd/+z1d^uXS^"şa!8IENDB`k9copy/icons/CTestTestfile.cmake0000664000175000017550000000050512412271774017413 0ustar emulatoremulator# CMake generated Testfile for # Source directory: /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/icons # Build directory: /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/icons # # This file includes the relevant testing commands required for # testing this directory and lists subdirectories to be tested as well. k9copy/icons/Makefile0000664000175000017550000001477212412271774015342 0ustar emulatoremulator# CMAKE generated file: DO NOT EDIT! # Generated by "Unix Makefiles" Generator, CMake Version 2.8 # Default target executed when no arguments are given to make. default_target: all .PHONY : default_target #============================================================================= # Special targets provided by cmake. # Disable implicit rules so canonical targets will work. .SUFFIXES: # Remove some rules from gmake that .SUFFIXES does not remove. SUFFIXES = .SUFFIXES: .hpux_make_needs_suffix_list # Suppress display of executed commands. $(VERBOSE).SILENT: # A target that is always out of date. cmake_force: .PHONY : cmake_force #============================================================================= # Set environment variables for the build. # The shell in which to execute make rules. SHELL = /bin/sh # The CMake executable. CMAKE_COMMAND = /usr/bin/cmake # The command to remove a file. RM = /usr/bin/cmake -E remove -f # Escaping for special characters. EQUALS = = # The program to use to edit the cache. CMAKE_EDIT_COMMAND = /usr/bin/ccmake # The top-level source directory on which CMake was run. CMAKE_SOURCE_DIR = /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 # The top-level build directory on which CMake was run. CMAKE_BINARY_DIR = /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 #============================================================================= # Targets provided globally by CMake. # Special rule for the target edit_cache edit_cache: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." /usr/bin/ccmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) .PHONY : edit_cache # Special rule for the target edit_cache edit_cache/fast: edit_cache .PHONY : edit_cache/fast # Special rule for the target install install: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." /usr/bin/cmake -P cmake_install.cmake .PHONY : install # Special rule for the target install install/fast: preinstall/fast @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." /usr/bin/cmake -P cmake_install.cmake .PHONY : install/fast # Special rule for the target install/local install/local: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..." /usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake .PHONY : install/local # Special rule for the target install/local install/local/fast: install/local .PHONY : install/local/fast # Special rule for the target list_install_components list_install_components: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"Unspecified\"" .PHONY : list_install_components # Special rule for the target list_install_components list_install_components/fast: list_install_components .PHONY : list_install_components/fast # Special rule for the target package package: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Run CPack packaging tool..." cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && /usr/bin/cpack --config ./CPackConfig.cmake .PHONY : package # Special rule for the target package package/fast: package .PHONY : package/fast # Special rule for the target package_source package_source: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Run CPack packaging tool for source..." cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && /usr/bin/cpack --config ./CPackSourceConfig.cmake /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CPackSourceConfig.cmake .PHONY : package_source # Special rule for the target package_source package_source/fast: package_source .PHONY : package_source/fast # Special rule for the target rebuild_cache rebuild_cache: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." /usr/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) .PHONY : rebuild_cache # Special rule for the target rebuild_cache rebuild_cache/fast: rebuild_cache .PHONY : rebuild_cache/fast # Special rule for the target test test: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running tests..." /usr/bin/ctest --force-new-ctest-process $(ARGS) .PHONY : test # Special rule for the target test test/fast: test .PHONY : test/fast # The main all target all: cmake_check_build_system cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(CMAKE_COMMAND) -E cmake_progress_start /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CMakeFiles /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/icons/CMakeFiles/progress.marks cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 icons/all $(CMAKE_COMMAND) -E cmake_progress_start /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CMakeFiles 0 .PHONY : all # The main clean target clean: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 icons/clean .PHONY : clean # The main clean target clean/fast: clean .PHONY : clean/fast # Prepare targets for installation. preinstall: all cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 icons/preinstall .PHONY : preinstall # Prepare targets for installation. preinstall/fast: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 icons/preinstall .PHONY : preinstall/fast # clear depends depend: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 .PHONY : depend # Help Target help: @echo "The following are some of the valid targets for this Makefile:" @echo "... all (the default if no target is provided)" @echo "... clean" @echo "... depend" @echo "... edit_cache" @echo "... install" @echo "... install/local" @echo "... list_install_components" @echo "... package" @echo "... package_source" @echo "... rebuild_cache" @echo "... test" .PHONY : help #============================================================================= # Special targets to cleanup operation of make. # Special rule to run CMake to check the build system integrity. # No rule that depends on this can have commands that come from listfiles # because they might be regenerated. cmake_check_build_system: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 .PHONY : cmake_check_build_system k9copy/icons/hi16-action-mpeg.png0000644000175000017550000000142012412271774017340 0ustar emulatoremulatorPNG  IHDRasRGBbKGD pHYs  tIME3IDAT8˅RKa=ϻ d "uL%- 2?!"L&iVX1°M@L͏]cֹyysAܬ-SH%lI@hfw}0L=xRO\^ |_u@ 1bn~ ?(SGO<z9t'8\fwZK4 .ތa+-;Z1Т&DFg.XCS'ȁɒ (,MH9H0ԪYUeTfG0wB$;7F؍>'/D Ws0΂KX\",+qXt~*-;EAEo`rivC)y^Jp @ #,`Ģ!#RÖsEl0$hFEithN}S\5<Bȩ;BnLL=SxDJg=O_-u83Lm6R2 |*WEkO+_CCvZ8wF`syu;vrJ"(MMͬj.\0@4M2H9aL cyeeofݐ@(WSÇYv-i3*X7{R `O>cl i _Y̢tWXaLLMEqD}z9)j*IC500%A 1|̘?*B2}<̳PUUEoo/ 04?'LA fpM^qudYa={b bI}:,#'"'6]Soc/XSo"FٳZV@ʲٳ̤ e,o H2gꎑvxǘٳyǩ;%'Rw7˗/g8n)޽[EP_ȝH*E;1)v=rpp)S޽{;w.k`0}M6mBUHtX-[ez^NaQDSLpX>!2cΜ9HtQ @(b\ SL)JOOS10Fq/㘺&P4Q1SpCv<@1z(\IaA>-J閘5> $.Kss6-FSiiN0e j9q>=ē7x-$$z%- fȟ[3l4C׹,7o>N0 -zj\BqR%>c?ׁfeիKy*N< pH4m#RF`hV #1mwx^uȑoq٩;JqY& 哣l2&O?[&3g[[+VƐE1~G&[5B͎˖=[ȢG%1^E%GJ0GMfF"XDLE#X8mo_h%P[{lPG>緯C[%b$a&@a)Lɼ"`8xˣ?kn3/:{h`XrDB4u45EЉDb8S K'7G1$V_iZݻf 5=ƾ_q+F.AŃ%08Tc,Mժ_\suZQRRR:kVţwLs#ŢOF0J+,\V@u>fxR咒cǎ-z=IT']ӧO7466ԫ+ѵPcIENDB`k9copy/icons/CMakeFiles/0000775000175000017550000000000012412271774015632 5ustar emulatoremulatork9copy/icons/CMakeFiles/progress.marks0000664000175000017550000000000212412271774020525 0ustar emulatoremulator0 k9copy/icons/CMakeFiles/CMakeDirectoryInformation.cmake0000664000175000017550000000124312412271774023707 0ustar emulatoremulator# CMAKE generated file: DO NOT EDIT! # Generated by "Unix Makefiles" Generator, CMake Version 2.8 # Relative path conversion top directories. SET(CMAKE_RELATIVE_PATH_TOP_SOURCE "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4") SET(CMAKE_RELATIVE_PATH_TOP_BINARY "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4") # Force unix paths in dependencies. SET(CMAKE_FORCE_UNIX_PATHS 1) # The C and CXX include file regular expressions for this directory. SET(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") SET(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") SET(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) SET(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) k9copy/icons/hi16-action-dvdcopy.png0000644000175000017550000000203312412271774020061 0ustar emulatoremulatorPNG  IHDRabKGD pHYs  tIME #7?tEXtCommentCreated with The GIMPd%nIDAT8moLu?h1W2k@P3I!03 @/0Q/L4}Cbј1K0IdA:@"ph.>$#"&Y,'h鮮/,X45 d2dHQ,1>N+WrwwKDòWK&( mmmiiJL}DOŊ;gt]/$"_s\F ˲ AKtb } _ه#",{['AS> , %.ğrɲ\@ns4aYx\OcccmTWGG!"x9((/?BcumaЗ":ǣꎝ,s$AE|>45Et:aZ; !99٦jt2[jkkc//v~CѡmeH,pwO/,9? swg!?*n& sm-8?33 VFeeeQz9LFH}J6ӡ魾|04S=Ng2D"Y!"nQٶV0 2JJJd5^>XXXprl۶%IʞinQn%ߠ\n<0^W5 E1sبa}~~lVWWD4vCCN]]ݎiso!`PIENDB`k9copy/icons/hi16-action-mp4.png0000644000175000017550000000136612412271774017121 0ustar emulatoremulatorPNG  IHDRabKGD pHYs  tIME 1pIDAT8˅NKSqs1:u:|0B A Ozz4BDL0ln mv̵9=b/~>?>C m}_&U`Jvlr:|H@iBD&¢Ӌ 주}?`xp'96o ޻r+%)owoKUAm׀̨b>s۱9L6<[Áj-hk=afIjjj5_sE ]ʀ5,<:KH A1 vw|8o!`B9릙d3#h`w!"U ݽ ! $r13o^/F+wVg (E lJ\ #򫟊+Ndg`-ۘ4AXJ<~r|c Rz   >,V(IF E$6W@1AJ/ψ@< 'yrˊ3 f (F "zg=+,c=-_*tjxYg d2Ml[RC3fIENDB`k9copy/icons/hi48-action-author.png0000644000175000017550000001072412412271774017726 0ustar emulatoremulatorPNG  IHDR00WbKGD pHYs  tIME $ aIDATh޽{|Tյǿ5L2! 1hoॠE(^JZkm[*(Y"`"!PBdL239g?Br RONfoZ{&q:*"K( u| Bm%--ܲeqU&OL}}=i 2P!, QUߏ4MLDm720m4zs_uaz 9~8!0 `0i~B,SQQAyy9ABa\u 8Rʛ^$i|>0Ƣ:^Odd$. MӰ, ˲m!p 0< nfJ7?4L$I,ˢ 4Q :::ux~?B!0 t]Tr0vXC$J`Ϧ~_=%U%4dxQ ě7o~,]͞gIJ?{ DnZZ[]6DEΒ'o9pܳnse^:4iӦ}XYm !>#=֍P`7#[VlYvfC~cXcc#[n٥-HO'8N;W'':ޖƪO++IgϞ^cʕ$""s@{7ZB8ӝCښۨ?^G\ IW^yu֑JjJ ֯G{{xN0F^4~L7fNyы~ZWN|=믳j*mӿbk8I6eG-^{ xY?Zp@KQd##Ԍ832*)j;Cqq1---8.Fc3[@Ky,ES$ҳ"KM?mmm]l&M'3$ fkbH eQL1QWػA;ի|B:'qf2dĭ-jp&B؄n<,!r^-X8ZbbH HmWUmYjVc nGSd|M x683|p&Ng=>7w4㧃 {hcg>}oГ444P\\oa\hn!0`gDdۍƀɅ (,9q;eYL].jQ1}M9SûK~~>=YYYض݇>P99 q튮zf5f,ijJI ɯ1<OD˲0 JKKu:LʲCtdlEU5(FvxCqד˲eHLL_OJi u],TM_?[@@ LIJ,B̟?ÇcX2wgIJ;mFs:+t%vmɓO>IRRR/m.V~p2xq#!38PF\}pKK\ H(7jׯ>@ i.LEsc>ŅZTY"ϼyHLLm.#p`~N=q͜R-1.Bmҽ{iT$RSS:u*MMMڵݻwC2b8`ʨ;[Cee%dpg^`3:w eQ0iҤ=䫦QIHKKcѢEq8](N7#| T~;Kvbu..&N… IOO ]׹ڑvv)/ߛEcI(p|̼$ÇN|GYx1i{n4INe|,ʘ1cXhلa0 {bvg3|xU|(} ؕFa &O& f`z6`JMM{@,^][ڵbinl@aÆc,!0MHrrrzg9x >o0w^n+zl]7wgr~Dٵ>$hCrr@/Ε4--K2~x- ,QVVFNN/(;NOiZ***ؾ};;vha م"K<4f,[, 9$3luw&%4cu6`:W$ <ÄB!8i|rbbbzwJ{6SNQZZJIɞs[ؘw׿w)xH&?l :)qn5 dOTTSQԘ/AGaΜ9sHMM7= piigΜᣏ>b͚57MsZZa3+?[Gh2kl n aئQUP$ z9}'<hv-ˢ[rCttNN3~РA?14MllChm l{ BeХp8[7Hcc##A~G8z'.KRx[B~`34H ^\qK⥹>K7ЊlʶpOr&&:z5k"Y](8T qn G&0~p?$[H%ÑD]F ^`yyyBK% as9^IiRUUřSU:2fX*6k wo3yߐ48eA?:*/L f55g+ jժM@ cСdz[% $+ȊJYE-~ln]7y|lޱ?XMvj}N{N{}:7r:<}jeޤXlsAJ]شiS pn"5_Ot*G>3,ݸ=NTcwi*fǮ++Ț?=ɁC'hLgv5.7"6qsMggwz'O l#N$Չ)*OC$~%%!rҘs4-^yv!+6qo۶xi@& i HNٳgV۶kz_F^oԢE?dJJY:U'%}? LdY¥I'cPVÃL\yO|g~4GO;̮c d&ZjahBպ!_5֛3lt_/yw(IuIu$!LP_km6YaI1 Bd`\*K'tԑF?BscOK 8NuҤ^3$ӣg)tCGi8Jk]Ä-ԸΡ3MYTC%:InZFQ4 +)ĒsgyyRM5kV3"tnxExƋp͝""=+bHvOfSӧO?jEM*/**ܳO,IF'NRWH_'t tL3Cqi2.StIz'jT*#&~-[8xMrEIVU-F,U4v@"/_P+7IENDB`k9copy/icons/CMakeLists.txt0000644000175000017550000000021212412271774016420 0ustar emulatoremulator if(QT5_BUILD) ecm_install_icons( ${DATA_INSTALL_DIR}/k9copy/icons) else() kde4_install_icons( ${DATA_INSTALL_DIR}/k9copy/icons) endif() k9copy/icons/cmake_install.cmake0000664000175000017550000005111712412271774017504 0ustar emulatoremulator# Install script for directory: /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/icons # Set the install prefix IF(NOT DEFINED CMAKE_INSTALL_PREFIX) SET(CMAKE_INSTALL_PREFIX "/usr/local") ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") # Set the install configuration name. IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) IF(BUILD_TYPE) STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") ELSE(BUILD_TYPE) SET(CMAKE_INSTALL_CONFIG_NAME "RelWithDebInfo") ENDIF(BUILD_TYPE) MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) # Set the component getting installed. IF(NOT CMAKE_INSTALL_COMPONENT) IF(COMPONENT) MESSAGE(STATUS "Install component: \"${COMPONENT}\"") SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") ELSE(COMPONENT) SET(CMAKE_INSTALL_COMPONENT) ENDIF(COMPONENT) ENDIF(NOT CMAKE_INSTALL_COMPONENT) # Install shared libraries without execute permission? IF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) SET(CMAKE_INSTALL_SO_NO_EXE "0") ENDIF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES "/usr/local/share/apps/k9copy/icons/hicolor/22x22/actions/./cycle.png") IF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) IF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) FILE(INSTALL DESTINATION "/usr/local/share/apps/k9copy/icons/hicolor/22x22/actions/." TYPE FILE RENAME "cycle.png" FILES "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/icons/hi22-action-cycle.png") ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES "/usr/local/share/apps/k9copy/icons/hicolor/48x48/actions/./mpeg.png") IF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) IF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) FILE(INSTALL DESTINATION "/usr/local/share/apps/k9copy/icons/hicolor/48x48/actions/." TYPE FILE RENAME "mpeg.png" FILES "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/icons/hi48-action-mpeg.png") ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES "/usr/local/share/apps/k9copy/icons/hicolor/22x22/actions/./mpeg.png") IF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) IF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) FILE(INSTALL DESTINATION "/usr/local/share/apps/k9copy/icons/hicolor/22x22/actions/." TYPE FILE RENAME "mpeg.png" FILES "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/icons/hi22-action-mpeg.png") ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES "/usr/local/share/apps/k9copy/icons/hicolor/22x22/actions/./subtitle.png") IF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) IF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) FILE(INSTALL DESTINATION "/usr/local/share/apps/k9copy/icons/hicolor/22x22/actions/." TYPE FILE RENAME "subtitle.png" FILES "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/icons/hi22-action-subtitle.png") ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES "/usr/local/share/apps/k9copy/icons/hicolor/22x22/actions/./title.png") IF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) IF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) FILE(INSTALL DESTINATION "/usr/local/share/apps/k9copy/icons/hicolor/22x22/actions/." TYPE FILE RENAME "title.png" FILES "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/icons/hi22-action-title.png") ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES "/usr/local/share/apps/k9copy/icons/hicolor/48x48/actions/./mp4.png") IF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) IF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) FILE(INSTALL DESTINATION "/usr/local/share/apps/k9copy/icons/hicolor/48x48/actions/." TYPE FILE RENAME "mp4.png" FILES "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/icons/hi48-action-mp4.png") ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES "/usr/local/share/apps/k9copy/icons/hicolor/32x32/actions/./dvdcopy.png") IF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) IF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) FILE(INSTALL DESTINATION "/usr/local/share/apps/k9copy/icons/hicolor/32x32/actions/." TYPE FILE RENAME "dvdcopy.png" FILES "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/icons/hi32-action-dvdcopy.png") ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES "/usr/local/share/apps/k9copy/icons/hicolor/48x48/actions/./mencoder.png") IF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) IF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) FILE(INSTALL DESTINATION "/usr/local/share/apps/k9copy/icons/hicolor/48x48/actions/." TYPE FILE RENAME "mencoder.png" FILES "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/icons/hi48-action-mencoder.png") ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES "/usr/local/share/apps/k9copy/icons/hicolor/22x22/actions/./sound.png") IF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) IF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) FILE(INSTALL DESTINATION "/usr/local/share/apps/k9copy/icons/hicolor/22x22/actions/." TYPE FILE RENAME "sound.png" FILES "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/icons/hi22-action-sound.png") ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES "/usr/local/share/apps/k9copy/icons/hicolor/22x22/actions/./author.png") IF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) IF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) FILE(INSTALL DESTINATION "/usr/local/share/apps/k9copy/icons/hicolor/22x22/actions/." TYPE FILE RENAME "author.png" FILES "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/icons/hi22-action-author.png") ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES "/usr/local/share/apps/k9copy/icons/hicolor/32x32/actions/./mpeg.png") IF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) IF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) FILE(INSTALL DESTINATION "/usr/local/share/apps/k9copy/icons/hicolor/32x32/actions/." TYPE FILE RENAME "mpeg.png" FILES "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/icons/hi32-action-mpeg.png") ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES "/usr/local/share/apps/k9copy/icons/hicolor/22x22/actions/./dvdcopy.png") IF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) IF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) FILE(INSTALL DESTINATION "/usr/local/share/apps/k9copy/icons/hicolor/22x22/actions/." TYPE FILE RENAME "dvdcopy.png" FILES "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/icons/hi22-action-dvdcopy.png") ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES "/usr/local/share/apps/k9copy/icons/hicolor/16x16/actions/./mpeg.png") IF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) IF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) FILE(INSTALL DESTINATION "/usr/local/share/apps/k9copy/icons/hicolor/16x16/actions/." TYPE FILE RENAME "mpeg.png" FILES "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/icons/hi16-action-mpeg.png") ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES "/usr/local/share/apps/k9copy/icons/hicolor/32x32/actions/./author.png") IF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) IF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) FILE(INSTALL DESTINATION "/usr/local/share/apps/k9copy/icons/hicolor/32x32/actions/." TYPE FILE RENAME "author.png" FILES "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/icons/hi32-action-author.png") ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES "/usr/local/share/apps/k9copy/icons/hicolor/16x16/actions/./dvdcopy.png") IF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) IF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) FILE(INSTALL DESTINATION "/usr/local/share/apps/k9copy/icons/hicolor/16x16/actions/." TYPE FILE RENAME "dvdcopy.png" FILES "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/icons/hi16-action-dvdcopy.png") ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES "/usr/local/share/apps/k9copy/icons/hicolor/16x16/actions/./mp4.png") IF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) IF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) FILE(INSTALL DESTINATION "/usr/local/share/apps/k9copy/icons/hicolor/16x16/actions/." TYPE FILE RENAME "mp4.png" FILES "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/icons/hi16-action-mp4.png") ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES "/usr/local/share/apps/k9copy/icons/hicolor/48x48/actions/./author.png") IF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) IF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) FILE(INSTALL DESTINATION "/usr/local/share/apps/k9copy/icons/hicolor/48x48/actions/." TYPE FILE RENAME "author.png" FILES "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/icons/hi48-action-author.png") ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES "/usr/local/share/apps/k9copy/icons/hicolor/22x22/actions/./video.png") IF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) IF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) FILE(INSTALL DESTINATION "/usr/local/share/apps/k9copy/icons/hicolor/22x22/actions/." TYPE FILE RENAME "video.png" FILES "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/icons/hi22-action-video.png") ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES "/usr/local/share/apps/k9copy/icons/hicolor/32x32/actions/./mp4.png") IF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) IF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) FILE(INSTALL DESTINATION "/usr/local/share/apps/k9copy/icons/hicolor/32x32/actions/." TYPE FILE RENAME "mp4.png" FILES "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/icons/hi32-action-mp4.png") ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES "/usr/local/share/apps/k9copy/icons/hicolor/22x22/actions/./mp4.png") IF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) IF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) FILE(INSTALL DESTINATION "/usr/local/share/apps/k9copy/icons/hicolor/22x22/actions/." TYPE FILE RENAME "mp4.png" FILES "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/icons/hi22-action-mp4.png") ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES "/usr/local/share/apps/k9copy/icons/hicolor/48x48/actions/./dvdcopy.png") IF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) IF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) FILE(INSTALL DESTINATION "/usr/local/share/apps/k9copy/icons/hicolor/48x48/actions/." TYPE FILE RENAME "dvdcopy.png" FILES "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/icons/hi48-action-dvdcopy.png") ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") set(DESTDIR_VALUE "$ENV{DESTDIR}") if (NOT DESTDIR_VALUE) file(WRITE "/usr/local/share/icons/hicolor/temp.txt" "update") file(REMOVE "/usr/local/share/icons/hicolor/temp.txt") endif (NOT DESTDIR_VALUE) ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") k9copy/icons/hi22-action-video.png0000644000175000017550000000577112412271774017530 0ustar emulatoremulatorPNG  IHDR$xbKGDC pHYsHHFk> vpAgX IDATHǭyPTwǿ{o @ۀРЊB1 %sh8(q1\&j$.5j̋SܷD!@7DD %+{!US3W;TSל{2w˖ ߢdЛTb|Ԍ#cTt?ϛ7TS|3W'T]Kub1|Z%<<$zrSbpxq{y&_ןJ垌#mmՍSG-l`>a@~)&|PM4kYZgI<:C]y!fNB A-njN,ͷ́öH3'#MwuO3מsB?N]wwjV'%Gq[Ҟ 1'4j~X;-EUt+L}M] 00B;w͊ W#gL5 2,ʇ'1QLʺ(su8`뻓EI4nR6J_&u@AGA_;T+LrAn-4.|P HS5,~>~.Kel۪m@2+r)Cw\Ӝ7uDIBYÆ@ taL}|纃|xkn cy448ޯ B6HX{dǾZV꠲(29ݱձ( b3Oa5;$-1L?rEY1/^;3ҳ <2{Dv[^Q)BeC@SIsA G lkobCˏpfZF6G*pz[@HvC^ ݑ沟 (AhchD@Z3Hw̓/W]([PlpkҭI&8$/\X:SyKfyxIfʿ&3Cߠt5z tvHgd|U@¦ѯԀ6&X dvd&dS2U]W>ۥK9tW+!D/a"qBjL?+v֘nHfi<[ Y!YQ^ z}t$39 x xѧ@_ZPyj ɘILP!pnwtߕ#$Kk~F?#s͕Jt%z_28 xzܶD>\n'~}FE0> xGxv*zAS.}iwh7cHGBG"@H31DC"I?z i)))"6c|euY58Ǻ6nTPX'۟n"DF| OS@a(?WKۗ/0c1wɻ@(4 <?<~xpTJR x @*l4e|=[y¬j8JO `^fo:H&EFj]D!l"c {Nʸʸp: Mo]Fe.zRO333!AKųQ,OwD0\b93ʒ 5O>Ωu:BvL)ʜ[<a6mWB"@ ⨁>ca?tyL@{z ^C6dԊi͢(43kPlOKD$R   8<]=/yaa6BWU4.(` ؓ7pK"` vŻTn]k EWտ|*?v-;g^ _h5bw )$&9EJN%`ҙ,@8)|f4VB6hoMi;W(suq9]m/?dya]v/ >l5ךk"R\Dq=JJ{|@"9 0S$X TI `L ;F=e|6PoT ąLmr(P^T(iEcf=w_wɃC!@~qQ}}o2df~&ݎ$ $҇ʬ&n}"Bd@"*7*n >})2b-(8X0az MhA'3'ɇ^=X86I(:R7$wHQBI1A[ݙ[{,v="KER^a-yitR]ww}Ök5]5?\֕ !tWө*Kwskgky~wh/ŸBt)̖,8NKvۑ\;\6 HJMJOPS9!'IlesLkMroPwDP\j )RK"4[`Z9+x/:>/hbLn}k"z'jvOM'{?/ƌ:IENDB`k9copy/icons/hi32-action-mp4.png0000644000175000017550000000547112412271774017120 0ustar emulatoremulatorPNG  IHDR szzbKGD pHYs  tIME la IDATXýylgz?c~3l Ɔñk/nVhJm jT!ڮvnȱ ل &l#6v|`c{<gsaBöVGz;>G+`ʋrss:MKYRŢz|a!D½p͛7n\*srrݷ777ivV# Dc:9<lhd|l``SSS`͚5EEE߬Y[uW[+ܙdeGb0-]^P8]ɔls:&cw[G[277/}m{#{\m##]CQd@IZ2Fx02a#V#Fyr+7EhW~}76n~471tCmuo [ %udeaWQW: J^S 33CO{޹[\.sG֟۞awARБ'xV5@F^>!$ $tZj* .^&HiZJx/X]YDz-MGREޙ`oX_pZZ__؁{P&$/ΓItYQ-E5:F-;@đ¦&^ew8YS\쳰{&ZG008K*]Dii.0A~Ԏ?KEy19}ufQ1j TapffG-qnɷT2))R-,:Gt؋l``x"I,)'zv{f;UM m D 9Z4ܗO{8zyP fLIHlx2/+j彟ʌ|y{#\ZI b1;UY r7>"+ޕ᧻YUQwk)_{z(V$5Ti!0m8[SoeRjwYKϴ蠴P㥓Y@JP%I2 -R (Fm\ a(x RI DcSRpOqe)!z:pu{1z{{4'|!=C=f}Mww7MMM>|*w8|0BdY|=: 8 ѨxšC[nAxDCCH&O=zT466 q%{/}'D8;wt]G?8PYYi477o>l6999Hij> ##Y麟={p99w/**`0F׮]9mee%zb> O?errHMMp8ظq#,ZbSOQ[[<3x^nD"z$Ǐtww)//ҥKM[[V#GD8cڏDkkhjj/xG / .]$mvkFGGԔx饗ǎ###ٳbͷYn_/C\.[mVVM֮) բAazz?QBol_rWñwuLggu]WsnPW\\t:횦i>4DkkK= @u_4UU5=bded؝fc|h!-,,b?k-rWIENDB`k9copy/icons/hi22-action-mp4.png0000644000175000017550000000247112412271774017114 0ustar emulatoremulatorPNG  IHDRĴl;bKGD pHYs  tIME *QFIDAT8˭POSg=R[iR+U Be ݏ8ef}ز}YeLstf&:ulM%De"k޶^{{}p⧝<9CPNgq:vZ-%%ZR9-ShR$2y2 ey' ZL۷qUeAσ8 c87!1_`Yv`ggcRv>Ju<8k5TԬNV+˂ O׶vٵQc@)P\ .%<͛x{Gri477NʢqSz=/N9Eo%Z  vx7AH"ݿ(r9m:jmDalEQV:BH 8.nͳF 0MHMO"=&\xm>7+Kقm P(g[[}mV "81ՠZ*!PA@8|^AKQLb}C%*`x^D2GeFG+ &p{wo\ 9H9R)`A.x4'~G[KLܔCo8N3tػW9 aqېq+bn^D6 !Hy2kXH +@z}icu6ΡGoW5D1֦jc1<AHӉhfA\Jg%$I_Sp}xCWPiJx $ G8| *H>OtŪ2`(,%jPЍA G d 8xtF8&*j@X;liܹ51qob,w;lUeh\vCq+|^l[/бq k̂,FwvޟfGZMZ0 s%}w Ya{^78"1l_ gU1tk E`˖|uU)H$<>xm RPJhh^{/wk OR @2Z.hiҙI,i<B⊝R ny y4RB3^vbA˅/jnPQQQ[ZZN/EBA*333L)Ji_0ԽIENDB`k9copy/icons/hi48-action-dvdcopy.png0000644000175000017550000001125712412271774020076 0ustar emulatoremulatorPNG  IHDR00WbKGD pHYsHHFk>)IDAThŚy|Uǿg-d!$$$Ld ,RT TjV[AѪmXV*-hm+vb+"`H l7w;;{M0V;9'=y=J|( ^w@JJM.S%ryMӌb۶++"HU45.$Ir0xpᢡC4(_zzp8u˲ 2XYyڵ5UZep:#0a²qyEEŤzuEQ$ I꾔iB!UUUo9|fk8WyJp:ϛ70%%EQҲPUI&->n$ uiTDA)Y.9r-@q?Kb toޕn'ӓ@|Om',×PUY"$Pz6bF[cu;%\뮛믟u`lFU^|=^Oe%S)tӻ'(~E*,(5Mͧ\ 'O8qx\}ID$(m_AHBFy/7}ذb)ݞznKD,C$Ip8<_qAm#!1nXMdLMƌM~.$СCx<~> ˲p8d"I$ !z=1t n 66n2n޸ #rJ?,yi}U=zX. M0 (Hp8L8&Dml=;iDB]qKB́~ۍ ktZ^{۷8p`ܹs&M$śW,4MLLici4p P{U#jFWI4sWԤ$IA$,t]t&j Hի_Q{{Zc67wyAA~(ya()@pg=gjA g|ZB 2t}`@}^^ nll蕼}oYN͉?!MLLB!59)^p@IJ>ߏ,99g|Ν|kkm!D/P$.7tpÔQ6P%Ov~oS-j BpHt|dYv3&a*;9CCB47F%u*mo~15ijj 1ذauuuDG@׵{g!Cz +hz,D|]a&W\-0˂sNRusW\^eDi*++_?3ײ>e~1 `0Hyy9`0*=zl߾<iDŋh"ݳ]I%B\Km8@ 8Q'SNqa y뭷غu++WMH8d۶mz B{j=\ב^='O}С]]zaرnꟈ$I4551h dYB/_… e6l؀W^s|>)))A<s[ov'*QFFl7Kgrp Ej2.pȸ⒣L]Nc<c^o/ 逢(!Xn%%%%&i7p8Lkkkiii;JYz3"0hS ]ͽ/IGX&v׮w 06o|WQQѻ˖ݕ( aPVVơC:hnn 55d^|EZ[%IOOKAAݝ$ qQk`៦_ͯMqնAۏ$ f CVVрdԸW_~^^sg׬YSO=ESSSLNNfѢE v!1_:z|'}Ls? &ŠuCV:IJJEMQ>r˗/שּׂ}oN2'Qjkz_, Gmm-ݲ{<ELtnp:i2 ˒4B1#P7=cWV~[Guԩƍ5R?zT˲D"RS]͖[ټy3p;)||Rv2oͪ^7DP$T MtzX?$mcُl^2PE+))ŢVU TT7Mt:9SʫwL'_8K/l/Ex'~ḇю CfH(HkKmm-aǔGD«K$*+tی"e{xy},i'OYOWV^+IŇY>9I}C -mDa܌|.v0MdI¡*85_NaN*c3(F~$ ~ ??x=/piV$"g7'M !^}r3Cߞ#|pXpz}Pd1 ]E߷3g~ /HIIɘ1c'xԀ$ŚhmnDjkii5B4%b*t85!&eFџT; |k΍W w+rqD+1ݹxv asbƊa2DH1Z+j}4Ϳ.aΞeZFCGNuMBa#,lla`6JHBi{C<غm ,=Grrrΐ!Cp-,􉩃 XfDa XH3ۙɩfMnXw;+**Vbϻ?@ɾ,? Ə\qlC*o߾S}MX h[zG Q(J:R4ÖeD4v E.Ş%ÖzTXtSoftwarex O,OL<ϒ@IENDB`k9copy/cmake/0000755000175000017550000000000012412271774013632 5ustar emulatoremulatork9copy/cmake/FindXine.cmake0000644000175000017550000000107212412271774016340 0ustar emulatoremulatorMACRO (FINDXINE _include _lib) FIND_PATH(XINE_INCLUDE_DIR ${_include} PATHS) FIND_LIBRARY(XINE_LIBRARY NAMES ${_lib} PATHS ) IF (XINE_INCLUDE_DIR AND XINE_LIBRARY) SET(INC_FOUND TRUE) ELSE (XINE_INCLUDE_DIR AND XINE_LIBRARY) SET(INC_FOUND FALSE) ENDIF (XINE_INCLUDE_DIR AND XINE_LIBRARY) IF (INC_FOUND) MESSAGE(STATUS "Found library ${_lib}: ${XINE_LIBRARY}") MESSAGE(STATUS "Found include ${_include} : ${XINE_INCLUDE_DIR}") ELSE (INC_FOUND) MESSAGE(FATAL_ERROR "Could not find ${_lib}") ENDIF (INC_FOUND) ENDMACRO (FINDXINE _include _lib )k9copy/cmake/FindAvutil.cmake0000644000175000017550000000230212412271774016676 0ustar emulatoremulatorMACRO (FINDAVUTIL _lib) FIND_PATH(AVUTIL_INCLUDE_DIR_FF "ffmpeg/avutil.h" PATHS) IF (AVUTIL_INCLUDE_DIR_FF) SET (AVUTIL_INCLUDE_DIR "${AVCODEC_INCLUDE_DIR_FF}/ffmpeg") ELSE (AVUTIL_INCLUDE_DIR_FF) FIND_PATH(AVUTIL_INCLUDE_DIR_LAVC "libavutil/avutil.h" PATHS) IF (AVUTIL_INCLUDE_DIR_LAVC) SET (AVUTIL_INCLUDE_DIR "${AVUTIL_INCLUDE_DIR_LAVC}/libavutil") ELSE (AVUTIL_INCLUDE_DIR_LAVC) FIND_PATH(AVUTIL_INCLUDE_DIR_FF_LAVF "ffmpeg/libavutil/avutil.h" PATHS) IF (AVUTIL_INCLUDE_DIR_FF_LAVF) SET (AVUTIL_INCLUDE_DIR "${AVUTIL_INCLUDE_DIR_FF_LAVF}/ffmpeg/libavutil") ENDIF (AVUTIL_INCLUDE_DIR_FF_LAVF) ENDIF (AVUTIL_INCLUDE_DIR_LAVC) ENDIF (AVUTIL_INCLUDE_DIR_FF) FIND_LIBRARY(AVUTIL_LIBRARY NAMES ${_lib} PATHS ) IF (AVUTIL_INCLUDE_DIR AND AVUTIL_LIBRARY) SET(INC_FOUND TRUE) ELSE (AVUTIL_INCLUDE_DIR AND AVUTIL_LIBRARY) SET(INC_FOUND FALSE) ENDIF (AVUTIL_INCLUDE_DIR AND AVUTIL_LIBRARY) IF (INC_FOUND) MESSAGE(STATUS "Found include avutil.h: ${AVUTIL_INCLUDE_DIR}") MESSAGE(STATUS "Found library ${_lib}: ${AVUTIL_LIBRARY}") ELSE (INC_FOUND) MESSAGE(FATAL_ERROR "Could not find ${_lib}") ENDIF (INC_FOUND) ENDMACRO (FINDAVUTIL _lib )k9copy/cmake/FindAvcodec.cmake0000644000175000017550000000251012412271774016777 0ustar emulatoremulatorMACRO (FINDAVCODEC _lib) FIND_PATH(AVCODEC_INCLUDE_DIR_FF "ffmpeg/avcodec.h" PATHS) SET (FFMPEG_INCLUDE_DIR "") IF (AVCODEC_INCLUDE_DIR_FF) SET (AVCODEC_INCLUDE_DIR "${AVCODEC_INCLUDE_DIR_FF}/ffmpeg") ELSE (AVCODEC_INCLUDE_DIR_FF) FIND_PATH(AVCODEC_INCLUDE_DIR_LAVC "libavcodec/avcodec.h" PATHS) IF (AVCODEC_INCLUDE_DIR_LAVC) SET (AVCODEC_INCLUDE_DIR "${AVCODEC_INCLUDE_DIR_LAVC}/libavcodec") ELSE (AVCODEC_INCLUDE_DIR_LAVC) FIND_PATH(AVCODEC_INCLUDE_DIR_FF_LAVC "ffmpeg/libavcodec/avcodec.h" PATHS) IF (AVCODEC_INCLUDE_DIR_FF_LAVC) SET (AVCODEC_INCLUDE_DIR "${AVCODEC_INCLUDE_DIR_FF_LAVC}/ffmpeg/libavcodec") SET (FFMPEG_INCLUDE_DIR "${AVCODEC_INCLUDE_DIR_FF_LAVC}/ffmpeg") ENDIF (AVCODEC_INCLUDE_DIR_FF_LAVC) ENDIF (AVCODEC_INCLUDE_DIR_LAVC) ENDIF (AVCODEC_INCLUDE_DIR_FF) FIND_LIBRARY(AVCODEC_LIBRARY NAMES ${_lib} PATHS ) IF (AVCODEC_INCLUDE_DIR AND AVCODEC_LIBRARY) SET(INC_FOUND TRUE) ELSE (AVCODEC_INCLUDE_DIR AND AVCODEC_LIBRARY) SET(INC_FOUND FALSE) ENDIF (AVCODEC_INCLUDE_DIR AND AVCODEC_LIBRARY) IF (INC_FOUND) MESSAGE(STATUS "Found include avcodec.h: ${AVCODEC_INCLUDE_DIR}") MESSAGE(STATUS "Found library ${_lib}: ${AVCODEC_LIBRARY}") ELSE (INC_FOUND) MESSAGE(FATAL_ERROR "Could not find ${_lib}") ENDIF (INC_FOUND) ENDMACRO (FINDAVCODEC _lib )k9copy/cmake/FindAvformat.cmake0000644000175000017550000000254712412271774017224 0ustar emulatoremulator# - Try to find LibAvformat # Once done this will define # LIBAVFORMAT_FOUND - System has LibAvformat # LIBAVFORMAT_INCLUDE_DIRS - The LibAvformat include directories # LIBAVFORMAT_LIBRARIES - The libraries needed to use LibAvformat # LIBAVFORMAT_DEFINITIONS - Compiler switches required for using LibAvformat #find_package(PkgConfig) #pkg_check_modules(PC_LIBAVFORMAT QUIET libAvFormat) #set(LIBAVFORMAT_DEFINITIONS ${PC_LIBAVFORMAT_CFLAGS_OTHER}) #find_path(LIBAVFORMAT_INCLUDE_DIR ffmpeg/libAvformat/avformat.h # HINTS ${PC_LIBAVFORMAT_INCLUDEDIR} ${PC_LIBAVFORMAT_INCLUDE_DIRS} # PATH_SUFFIXES ffmpeg ) #find_library(LIBAVFORMAT_LIBRARY NAMES libavformat libAvFormat LibAvformat # HINTS ${PC_LIBAVFORMAT_LIBDIR} ${PC_LIBAVFORMAT_LIBRARY_DIRS} ) #set(LIBAVFORMAT_LIBRARIES ${LIBAVFORMAT_LIBRARY} ) #set(LIBAVFORMAT_INCLUDE_DIRS ${LIBAVFORMAT_INCLUDE_DIR} ) #include(FindPackageHandleStandardArgs) # handle the QUIETLY and REQUIRED arguments and set LIBAVFORMAT_FOUND to TRUE # if all listed variables are TRUE #find_package_handle_standard_args(LibAvformat DEFAULT_MSG # LIBAVFORMAT_LIBRARY LIBAVFORMAT_INCLUDE_DIR) #mark_as_advanced(LIBAVFORMAT_INCLUDE_DIR LIBAVFORMAT_LIBRARY ) INCLUDE(FindPkgConfig) PKG_SEARCH_MODULE(LIBAVFORMAT REQUIRED libavformat) INCLUDE_DIRECTORIES(${LIBAVFORMAT_INCLUDE_DIRS}) k9copy/cmake/FindLibMpeg2.cmake0000644000175000017550000000115212412271774017035 0ustar emulatoremulatorMACRO (FINDLIBMPEG2 _include _lib) FIND_PATH(LIBMPEG2_INCLUDE_DIR ${_include} PATHS) FIND_LIBRARY(LIBMPEG2_LIBRARY NAMES ${_lib} PATHS ) IF (LIBMPEG2_INCLUDE_DIR AND LIBMPEG2_LIBRARY) SET(INC_FOUND TRUE) ELSE (LIBMPEG2_INCLUDE_DIR AND LIBMPEG2_LIBRARY) SET(INC_FOUND FALSE) ENDIF (LIBMPEG2_INCLUDE_DIR AND LIBMPEG2_LIBRARY) IF (INC_FOUND) MESSAGE(STATUS "Found library ${_lib}: ${LIBMPEG2_LIBRARY}") MESSAGE(STATUS "Found include ${_include} : ${LIBMPEG2_INCLUDE_DIR}") ELSE (INC_FOUND) MESSAGE(FATAL_ERROR "Could not find ${_lib}") ENDIF (INC_FOUND) ENDMACRO (FINDLIBMPEG2 _include _lib )k9copy/cmake/FindFFmpegScale.cmake0000644000175000017550000000265212412271774017556 0ustar emulatoremulatorMACRO (FINDFFMPEGSCALE _lib) FIND_PATH(FFMPEGSCALE_INCLUDE_DIR_FF "ffmpeg/swscale.h" PATHS) IF (FFMPEGSCALE_INCLUDE_DIR_FF) SET (FFMPEGSCALE_INCLUDE_DIR "${FFMPEGSCALE_INCLUDE_DIR_FF}/ffmpeg") ELSE (FFMPEGSCALE_INCLUDE_DIR_FF) FIND_PATH(FFMPEGSCALE_INCLUDE_DIR_LAVC "libswscale/swscale.h" PATHS) IF (FFMPEGSCALE_INCLUDE_DIR_LAVC) SET (FFMPEGSCALE_INCLUDE_DIR "${FFMPEGSCALE_INCLUDE_DIR_LAVC}/libswscale") ELSE (FFMPEGSCALE_INCLUDE_DIR_LAVC) FIND_PATH(FFMPEGSCALE_INCLUDE_DIR_FF_SCAL "ffmpeg/libswscale/swscale.h" PATHS) IF (FFMPEGSCALE_INCLUDE_DIR_FF_SCAL) SET (FFMPEGSCALE_INCLUDE_DIR "${FFMPEGSCALE_INCLUDE_DIR_FF_SCAL}/ffmpeg/libswscale") ENDIF (FFMPEGSCALE_INCLUDE_DIR_FF_SCAL) ENDIF (FFMPEGSCALE_INCLUDE_DIR_LAVC) ENDIF (FFMPEGSCALE_INCLUDE_DIR_FF) FIND_LIBRARY(FFMPEGSCALE_LIBRARY NAMES ${_lib} PATHS ) IF (FFMPEGSCALE_INCLUDE_DIR AND FFMPEGSCALE_LIBRARY) SET(HAVE_SWSCALE TRUE) ELSE (FFMPEGSCALE_INCLUDE_DIR AND FFMPEGSCALE_LIBRARY) SET(HAVE_SWSCALE FALSE) ENDIF (FFMPEGSCALE_INCLUDE_DIR AND FFMPEGSCALE_LIBRARY) IF (HAVE_SWSCALE) MESSAGE(STATUS "Found library ${_lib}: ${FFMPEGSCALE_LIBRARY}") MESSAGE(STATUS "Found include swscale.h : ${FFMPEGSCALE_INCLUDE_DIR}") ELSE (HAVE_SWSCALE) MESSAGE(STATUS "k9copy will be built without swscale support") #MESSAGE(FATAL_ERROR "Could not find ${_lib}") ENDIF (HAVE_SWSCALE) ENDMACRO (FINDFFMPEGSCALE _lib )k9copy/cmake/FindLibDvdread.cmake0000644000175000017550000000120212412271774017430 0ustar emulatoremulatorMACRO (FINDLIBDVDREAD _include _lib) FIND_PATH(LIBDVDREAD_INCLUDE_DIR ${_include} PATHS) FIND_LIBRARY(LIBDVDREAD_LIBRARY NAMES ${_lib} PATHS ) IF (LIBDVDREAD_INCLUDE_DIR AND LIBDVDREAD_LIBRARY) SET(INC_FOUND TRUE) ELSE (LIBDVDREAD_INCLUDE_DIR AND LIBDVDREAD_LIBRARY) SET(INC_FOUND FALSE) ENDIF (LIBDVDREAD_INCLUDE_DIR AND LIBDVDREAD_LIBRARY) IF (INC_FOUND) MESSAGE(STATUS "Found library ${_lib}: ${LIBDVDREAD_LIBRARY}") MESSAGE(STATUS "Found include ${_include} : ${LIBDVDREAD_INCLUDE_DIR}") ELSE (INC_FOUND) MESSAGE(FATAL_ERROR "Could not find ${_lib}") ENDIF (INC_FOUND) ENDMACRO (FINDLIBDVDREAD _include _lib ) k9copy/doc/0000755000175000017550000000000012412271774013317 5ustar emulatoremulatork9copy/doc/screenshot.png0000644000175000017550000043764512412271774016225 0ustar emulatoremulatorPNG  IHDRɅ pHYs+&tEXtDescriptionClasse de fentres: k9copygBy IDATxgx3e{ʦNR% a^+A( H !4!4 !)H$<ٽs;eOޙ% =!Bun)0:=zOt$!BCp.4:#A!BlhPkq $PB!js,_ފZnmw& WyZ+*N% 'kf@!B㙛YԊZnDWK%KJ[1IhZ[I*/V= fƄB!:Xs'ZTg[K hZj-|,1hJB,6ىּ̎D?Yz4JF}_aM5OvtU#WUhq!B/5^ b"yȆ$=r W5kLf~{)$%%a#N Fn]%DDIU#[Ju椌Isi?ٔyC)g'ThLl2%`B!bܽKٿGz7,.A:KޘX1vQx!Utk*5P#)['@D7x!# UF7U."77*4- M=4q߬)"!BGG;Oz(I#mw<O*S9{`bT}{ KgloGW2zWoΦU1tۛ.e$^KѼ.e#Bu֨ZKMx?*BKr ~mW2~%dmHJqɫ8m0KS9Hg.8f XY̋d=8"ZW!~O>\|ޮ[ 7ps,o9zRd+%]v͞ O=l$ fg[IvAԢWh.yxt~ʫcB` 0reV!B+HWd`WZ?W20L#ycWO^M ߯/Nr%[᫚qa \|WΰɫH/E,0O0E~6-V,Eّq܃O?^ "ZjәTq)]lC|1p%**{9Z"[Q uB!Pw@"j iV5 zU@eaal_QLjv\0$%"/_0ZIF S4tIx*"+Wl*xtijC4L,I}m<"XhKų bH(ɭDR;G@L> HH,H"H&a6My.J&cB9JiǒwSBZHWպey$cLU;s^94_ B ZUyɑ"P1e'幤1?@r>XPP%M! zKgY3P<49(NȑHW3qz3Qi Jek̏V=4E\N/H/@Z܍nݽ`fMZ9>N1v$A((v*9pF%Ts 3hR)E4 EXge02)A];5%GU2ʬH B{F=^Ƙ缲lcs^yUB+\MZ#j[P%]. ?H32Djl+A۫"pWJ㽔r卦2NWJ=n 'N܋?ԩJE"*)$XNͱ& HJ@bYd^g٠X3P"HDvf ZcJ$VZ 91&=AVvH$q@|bD*HĭZB.whdkWI^ )}f:XaE"(mL)ߕ|8 `9й&Ί#I)gfDgY_n\im%we2P*48-yEp.[ռ9قR1y2jF\nKb.B!P܄/sjd+dNr4Q Lp_Y[!6mv[1f3o1"Jx H̅1|s6^VX&[[$6Be5zoF_cַ[[yF` Vbi`rD)iżXYSKؑ$U>h8{ɭ#A!VLx黗y5v[ۄ1>2'h B!Z42?4G!/05u+j}B!0yE!B]&!B炭_OW B!P]^nNcyE!B]&!B!Bu"B.WB!e`B!%>A>zWG`T^^`/rrmtSlܰ~@xHX^}ϛHɚZ*{\zB!P5{uמii_}%6m[njǎMƾf:14֭o\IJ|5y71BDB!-jcLFcgN8>fИCG> 7o+ؿooGď50&jǗ.ye)c'ǎ31sw#34aY;k}8w#Cܱt:G1bhhzl%r(0pPC\3,7ں[7zgV:*Zm#Fvֲ.zƎ^B!P'A߻ȿMzH$>Riik/7K^nQN&+X+WtZݠȨgڴL⢢sgqF:l/?߽7 >?/O;u}*RhX[?f3s%hM_"CB 6`=}d5#\ZX^n 8}~#iq%$4mG11C\\{B!Y4{u=WҮ&MT륓'WT?>wqO?Bkz͛6#`Ҥɗ.^(S'O $Iֻl™ Gf;y#LxiqRL&SXX+x+4]6|_ٿ5\+ gǸY eZzc]MJsvqmT*xlB E!j'ymqݽ7oH~Y&y捯J, H9K';~KK8L.ozm=z 5y?vxū\+z˴2ںfܚB!\[*kȰ቗/:yBKM_v{' Äw˦0dK/\rXUT +4Mţ\8>##l3ކ h8-EEM0++3i!̼]ZR*׌nN8snhҔm$y٨VB!Ԇry-~wFaM\v 3_Erwɘ!C׮܂L&EQ+W}6d谧Y0jXp15 4~CC %%]_A9kb<GnMӯhHwkFX7zyzy}|ńF+ZmCTǔjBNشu0{53Kt¬_lu]{w| vֲ E!jHfn׌W;kYg: ˩hǴHMYGR߷ B!PhFjdZ{KdiTh;O#BՖl!B!Ԯ0yE!B]&!B!Bu`+3Rq B!tO$|-B!B *Si$%!B9!B !Bu"B.WB!e.UUUi)gY)+k~1vyݻ++RSZ-' ܧH$th<_TXT1egl"ltX_TTX\TTRRNN.....b<[:7y˅{Axxxzzyk0N==5myEyyyYԔ1ccn\WTTfaa ';iHdck;z섀mܪ^C~\x`6 OZ[q0&kS^FFzxh_TBIw;,J8_H^Ν9'DB@UjWcF?ulHmEef#GI2KtN8a!}H!E$g ~?f>y;hbDvb{Ko,'!c AĂ9uꤛ+/"n,\J΂$j^P MӌhmzzLy`zhd0HvU;eeeUUUjzo[;Av{o)fz taiZk2>[䃶 !\핼~FF/ab s;,n§0N@$ܙ/&L,~{85$&%ò{wلӾ^$IyAfȮЗ'M~I<e"IcTUۥSkfn7~Ϝ:3tzPs\] D*/$>ޮ,˚Az`Xw%UUUCuttdz,k0>ap>;+sϴUcŋ/1&S2Z[ھW,N|Y;4ER 9tڳxd r"u{v7E#G ^^z1ل!Æwӽ;ʤYy^!k 9u{[߻9yމrYV 0'R{M A8::&@T ܢJsp&S@tIJlaA.zfz vvq,[-*,4Ǐ Q*"i=8emllzk׮դכe..#O1mä2z} BW,ofy:s%j?;-Afũ՚ʒ>>ZGn>MC8EY͌L K{MTd_']itHwy(y?yTVV VV}||+…EYF$#.a}mi؋{}=}5k߷xN:MaF )8D l`wUee23m-c=wj4=zV*JRDiTP(CCC{h&:`j6gOiq@FgZFez}``ر<ϓ$Գ$Ǽmkb\FZ`hLkk7} IK/Oʔ=}\72z#713ksHsw|d72sslTi4KA;e^f34M8q3?s%!1DD'ѦKuŖz[S3Wx[[[}Q_UFVVVL7& ˬ#-<_R\]\0T"!oJ D46#);3FT*%X,($#Gdddm߾$ILP(M%%ٙ0k4&&mzCNq<At\~AC,0>;;mzF#Y\{%$EidW;ϵf z3Gu+IAwiKud4(L%*fћ83 {{Ey/[rWQnNנ LQ/ Io>3bp]h4 [[ZTv/mW}`ۓ(i(vֳֶ*f~{zuڷ,PkKyFn޹koxD^AKGl9&h4,+nڵKRZ*55Dbd2doMVV&fY8~gV1UfH*ST{:m7Kp\}|G.OkrP9*ۙ񼉂 0W_5y~;~_l,\_?]]z@ەI$.eWLe+iѓ]./NuOKA;x??_T*L&l8l6f IDATYD/ X=Q;w d&`dOXDjU\]xj4nP13W9+#FR9_˗_y mA5 ]M~ݺK.3 G9f7]}¹BaΫR4hPzz%ve322Hnr4 $A@ FzB\m9+uq\YYbe&,2/&Y]G\_b+`(K _yl6s"L&ɤ0y Uw^kȺB'$P(/I|mlZ&?7'FFS5rW{*rPHWΰZ6:,=Hdccc6J$ӧ"ޤ_J^y~31Eh4!v|Ii0pކ}H,,,TJl6t?J r?lggg6z۷Ii} {&xW69DMˍ+ޡ&W,WGiN+qf)^!%:lf sLL"ᗘ%]@<AzwPZ/Ƶhvqu9f\QуTj LfckBBC/^-m o8tl6_8w˛7o--)#Ieذ~a>޾N>>ack[TXw޹sJ$Lj*aJk̓$I[[[l4wFߣGchH - М8㇬(MYNl3O%^!hnWOQnIB)xK$< XI/4z;vÑW𪳫)T 5ŝzi[[۾!P緝ZxWچaXw.>wyuthd2>y(??d4iZOO'"iXxx'߂- fΚf.] 8p I666D^l@Hd1xB1s 98Z$o^X<Ê64Ѹ!?Q$I i@ki[$ L2 !2 )o4B11 7||}8mkO' G'ԂNn0w\W-kzyy8:??'&):)JiaGty,JmۖVZ^7]Bڪj_fT=8_DH S3O|eYo013FF Ƃ71j/{L"!Q>n| )P?4sVo)YsnݼQ\TwEEE=VVV )˲z~d..3gi e* 3RLp<&LY$I u緫UomjfurCt!5'44_D"yxoY]\\߼bKGAݽcG:%^SZ W77Kr'?pӆuiiiɻv.gGѿmzl1K$z!,mWwtjaee՚v;)Տyu%yjd2ɤr7www:ŭ:D5=0 :ұt/?A_^YRlm$WWKաE֍3o___??__={Z߰ͫE7bmb'@NAtj\fnax/n0۬B7ez9}~B!-aB!+B!BvZ> 8ogcGX:'<B=N^CCܴfUd4{ga}ܽ돶 %|<|zoh9kM[ Ь|x𪝵l񻋞xܱ]xcF 8tpdC%?ù=d[y#O9GΟ;.ye)c'ǎ3vֲ.[ 59!!u7GNwZ:l6 ~U+zwW_~/ t !QYKJJo,\t z劵?L?d4<Q_g{@[co;r' hA:q5tmۺXqG|j0rR|cM8vHEE9}5F FC+o5F"l}VK Z+AAA5%EE=1}TYY9 <&fEӯ޸C..ycF ;\а9~i['D")դAc.zw߶9q ,`GwOߐ,W»~g|⢢sgqF:lx5k{~N߸afJ8_7cǭzZ]eƙ={6VÇt:ݑZ+xՠ kkƻeOΜBBCjiiiMs$>.FnJKOꞯ7\Qws䆖Jt2Zb}SZ?P5S:fϙ5 | _֭dmHeN:9jhN?z̸EoNo?a `׫%ɈQM(\c'ϜZ yWGY^n 8}~s0yD*jy ~7/7vFƕİ߷|Nvdu^TȪ~ޕը5M<6]#o[/X]!: Jg&pWQQ« "///0'3|||U*d-nt=>zh#Ǐ5q?bc'V?޲i?v4V]\\@0tPdhX$oO8szA#fK~o;MMcTͼj(_ZoT~'\YSk4FeooOD-=YkW28ίmאԪ*U9ٳ}TO2;3׻OzO'} >LԔd[[ے⢆T';nOu׫ ɬGL?ff5tI juMߐ󗮬򋔔ƗMs¥Ǐ?v%%e.aaiii577G":y?sxJUFFzxH0?6>2{VWVZ<̂'str F 67^J%1C@L̐ǎM8ڿA]r_۽/N lߚ;X,Dw '.b6jQa8ȣs$ waf^nqƍ,ջ׮^moHhhZZp, \8w.wHFAum3߼G b_zYVi)>\X]`My٨!Æ'^,̇˗.Iݷ#v_n*Uxڹ!C]x+Jj\8>##l3 W.~{ K >d|*Us+w=q}/[7Nc/xZ~g4kCjtrwvy?qjҥI̚ne^MJ--\Nkdu@>}O=ݲ0hРȌ{  l>>5?֮ih=sjukySDFE'9]XPwXYY$)QbXѢ' CMߩ,Uo6S=`c_Xi~$R E/ȟZ~Ừ*Ւ~|oM,hڔ|<=uEMƎrpt5zT* >hiSz׻`GD%yo~2m} dweW@/KEu,weum;o[Qy}M#ZشuۄISPmY*xIf'R;|":^~9__yYeԴ [ǯHG^&e[7ڳi݋BQU)HfW^*--]LF2s ܜ@>XfkWXPJr+-HG٪O>>X7(ʯBDE)NKX$sHk,4B:b!E+BΠ+~ABA#6+BWB!e`B! L^B!P dZ*B!5@!BAe*/E!-C@?a/)@!ZNC?u,L^B[;؂bGwp݆JmtGիekjo 3jAq{uX݉Jɫe8 U:9u?6B{*9cMl!Rc;AzZwih usZudyY nnFi!Ep-탃 ^7rH8!S^Yg5Z"qwBMude?i|#%wë̪pB%<W/TGi^)#ߘy9]Cl8 E[G"]TL~kڧ9LPǚ8m鏍q SCƓ\] gZz0yE!.x~b3O\E F:Pv 7/$Z>yZճ\Yiko\r\H}ҪRӬj*qttR㸰E 0 66vʔ)u-++swwg˖k׮f3[n7.[ /^T>1I*&eWina'n&F8_R :Ww/DWXo6@[b۷/˲ѣO<9o IDAT޼>:y=vIÆ k|hhh:7om۶O>D, T+Bv0LO<ę3g!C6 6׆<z3GXw RwXFjd@oRgp"iұy&!D%+'U>N&dQi2hWNtS(*KDdnQo-nylICvֲot֭W_s`g-{ᥗ23<´3T*UDh<`ձrX29 ;wKe?7!ɓ'/]` I~0zU+W-_ r-\K5XraV~GQԬY>n)))nݺyU_n]֭[7|ᇻw~[?P(qSHh@V{xxT8dȐF}v#O? F˗ [lYdäI =zt…z$+VL0aٲeeee9eee)ꪴZٳҤRǟ A׮]?~|zz̙3`̙>lNN׃>rJj?Oy9Ag&3fbZmVq4&xg{zy ^~qo!g1xᙳFhۯ'zϝkO\hXqJj."##W^-Hyu֭\RVڵ+99򵞼|V11ۻՒ ;v5'''**ƍs̉Oh޲e߯P(jVu!㒒@VWѣG~$===333lmm]\\߬Ecyӕ_|Ǘ_{ljU<zS3r9o<꬞J@5/ق uv8g)?U?HP!7z8UT&I Jg&9M8ylwϝ-Qyyy={>t v-7 CN<1`PdhX$iccVZ6?ĉ?m۶xzz6^yΜ90eʔg}6//ã14ӧOر?zT*1cƎ;Fy3fYYY5Seooe˖FbWWWݻwO:N:5dooox.\G-//U(AAA}ٿ߿~zafU/??tЉ'V7}}ݳrrr0yES9/_~WhXnozg6?#Rg!B^Xwqt{՟2>3c$s2t&b@tw9w*Ȭ[7oRUEkQ+lvuܹׯK\\ܺuY]hܺuT*駟d2_wiA }5y=Ovނ ܫuT;ֽjօZW[uU-8 u+("*2EQM6=}tL-[xxx兆21Y9s3fHNN Dx9EQ$IRswww\.2ISK4#(.ի^M(m97-/9w)y=2B4r;c36--+k9I/_:ժuqm4P$t5|ssq:!mN0.⅐6͛{3G]jC M m5y[||}5X,6I9Qջv튉x"7iii={4%>СC7>}}nVw܉"BP >Pϕcǎj޼y۶mcoݺ\WP(<EZ o,R{(6Os>!\Ҝ21cjUBMyg3}.]U悜Y9`NRT3ׯ_=٤Ij̘1aaa%] P&5kZT$?+ȴZS_ّӥD^Y">?~d >J khBj kTxoAVd!TjyE< EU(!B&+B!6B! "Bj;!B["ʛ_C]11~)r"Bv^IH7{`e!T%K[ڻ*lRhrI%팖" Ba MʕTvAB[z Ipբ(" v^Q#|<:Dk1h;!T!1$U9?ܻw譖-[-^G^U8Wo)t^ O9| i{m$N6$Kq)̲r%*-=(ڱ kkϿ?ć?̙3|\zuQ:t߿unݺ=qcǎܹ3?@7~Z[[/[r̨.^~?~pg[BOaF8A+d<~(.Ukw?d!usaj';+7Fӳ[DNr\0g|ٱ]LL[}{v7m1MEw  mlӣu\R tAP3B.^87SP4B.;wjzɢO|࣊? 6&k]胀q)S?.]vݻw'B,1"///Eqn5t/M뇅$]=WbB5}\_9"7r%!,i$\ ]|1ysg srjG$x˫w'EDvmh|/^hѲ/$iaay`L-WMXMv>zƵĸN_ >[4M5!mhow/;0;84xJ@@Gi򥋹9cG g/3^x֭gRu#b(Wfj󚒜4?,7Glݲ̩PϫӧOLLJ7|3}t8{lvv8"(==A 7o޼w^6Tǜ9s<==)h4;v,4y۷od2JиNj4}> 6ǸSMj(~Qލ߸~8y:uiJ)^HHHBBB~~>9r qƹs_^(U^^^Z)gwfIsDh4\.͛'޻;ad>?o={xԮ] tppٵgbh7e@(=f[ 5BTXVћItGiP+R>6=z$f)^b͊ v'B(}?knzGu !vrgVVVV4EN5=mlBۄ|mli M^FS^B,--=kƎڻgwhjzo0e]vtttΝ===x(XLtƍcc?§cǎgǎmlllmm@ VXըQ5nܸ33Aݻ7Ś3oظ ukzX}6/^MR&;ѣ7vRw-DڲUoҫwC1.ѽ;vw/{xxnۺ/'$ʪhډFMNYZߞ]вoS6-Z|6`Y4'^xYېku]csi\ b?؊R'}.]ҢR;Mb64 LtwhMwWvBe@P5t7 wkF"CJ$2(*6:8DoVLCW۷oGFF󴰰037r8j&?/_"8~J.@Xw6YeOJ~SMW=/]^9//ߧVk;ef߷w;/:s^uxF`'?!:5#Pѿ͙Ww3_efnYֹ}1s]r~ {ک -#ن~;{W$>t0KW좵 悴ŐzYef2T֢}tڔѺ̗/wGDv jܩsg33e7X [ŨRS҅r%˫TBL~E"}oߺ/) :bϹ\tgN+zwڴ>ьBw7ߺe(1ۦD}ohH!S`IjŪ-PA Ο;۱S-1m`͕k7/?wܹsHH!0/';5fUȤqT! IDAT7~ҴkTB~9þzطe[U斘h{p]ըU葆ލ;x-oM^PĩV-Bֳf~_Ponn]:xO<#fWE]VQֳG%\*5ܹ}oȴ΂JQM7P(--5ŋA>zN:zkkG̈=Kxeu~n!mN0.⅐6͛3_ڽ}NľzWA%#(!d6lگgZ(RТ E.rvqY2 KK?7 Y;ri:zɢǏ͞:mF@V``Ykl*fO>zꤤ$ϙ= B1˯ \O *2Z$$^٥@p~ S3sM_cEŝMIe+lW0ƼbU(UA9& kTx+*[TsD_٤ʭ}YNU..jJ+THu !T|OY5+bc!TTөմإPM_i;!PTrbU oPI`!$TDž8#d""Bط:ҊdXB!*m5BlK,Bg֩e_)EAj!--ߧESaF}pLM#S\|/cǕ(-B"6pΜ{w75aK.Co~( ;#Pu1{6?-WggնuO-iCnn&%sKNGɫ,;s4BkoBػgT&5g[[K+1kWizԘ%zRP1iW ._ۺ曯E%^ˊe $ɉk@ahkR[jfy#)"ISN^MaûɵwnYv]6mkp#giN8{ᒙ9EQg!LS'Of =<=inj{aZj#u/u?bnJ*ZiŦ{Ҕ &* !QLZń izɛܰaf ~vnfgg>; @P>G2cW n1+@:>i;^ef0kƞ}kq=o fn5n4r_عKGLNvJ3 pB5I h4ńh/WMĄWe^t*+zڽi#,ro?y8N23NpRg&~Mm$ UK:m0+/7i\}|?۷o={FC=<--ho#POejʴi= τ"-ۙ@+W\L*4]n忔[B L1(SG I)Itoib>>YUwWgf&Ku'S#POe-P5Bl߹KDW`XӡEnņlXޣT1ROb}jQH(Icʩ<!Sh48wOB!I>_aaJQ DȔRR3> |/_ HI"cVY!)g7TՂ*o&6Bl*jA76BM^X-B4 !TNBTՂ*o8ZH*+ UKJ)"dm." Tir d\Oߔ)r" J } RTj${7j\%A!=mcmS)P2\EH+TxP2{`e*RբUC BUGNӪȞFC=D&[ x\.@*8Y㺰!BXq쮽#I޿7W[UEpX.es-ΗE|6ϱE!.h(쮽|f#x*!,(FTD^1Vl.0;w1{vzkݻw٣GJJwءp)>$֭[_B!W|終Q r,M,_pA0nZdzjFR#j?V 4իWGEE1^~ݠ~}Tj(տ mݺ'Oܿ3h z@!BEUΫ8_Ƴ4#\p%OO-fgg(jD^#Q|]:\v`Νd lܯ_?- 7o~]ׯ_;vX,>zy_B!2J|Hv@L$#,9ae 2999=erBP*/ fw?6}cDD޵KVoݶaÊ-Ȇ/bfZrqq1!B9SiWnFZr̊el6(Ғ+"X\JRVjF8hP]۴mM#F֭[lynܸѸqchcgoԩ11F*6>B!*sUn)Z*~o;_RXrIZ"!44*Mudհa3f6jf̙KV߿wϞ☐/bEG!Beu^-EY|f$IB^n7 LȖ X| STn`e|QFLxΙ_s\S#BU|5;'Box9˶sfIZTYRd-*(rCk8Fyd音B!_t7Æ1[V&+#BekE ^ <_~hRUJBRU 5H8`ALڶW˾}XYY-\lLW(Cy2wƌ\9 'NܹӋFXfF5k?_ڊA @P@]EKwc wJLEDٗkdԥKj4^={g^G\N?ؾ}{T:=zrwܩ75M |p&EQ[l!bLe˖@LLΫ<GM!Lf͚Ν;^A/]vl6;::Z":.![5輶oua ץPL"ʡʘ3gΚի:fWoYYYSL9_/;ut3gP  Ec2<}n֭[FR9;;yI&6mjѢ_TP{>zk׮FFI 1[lmmI ۲eKڵ@ѣOgϞK.Yfܸq4nܘ0`vT!*FE6@|HvFB|]JR8s sQʐ))¤GYsrrֽ[#G /^޺}{ڴi7ʀj5ddd,\pڵˋLHHXtiddnBfU9tИضm۞9sF;aÆ/fE#޽{7޵kBUi-b <7Nڋ2JR4(F:T(}L* gt{+ajnbBP,[YYiCBBC'ORMJJ{򥕕Uddd:kј q\j_tiڵ B"lR fffv)55~ϙTz]O83T ۷owtt8p 4h ---''iy޿ԨQBpÆ lӧO:t޻vbX6mzA!ɪGu_U_D+z_~ Es <{(6CW{T F|]v"щ'11s~A*4ݠaí[޽{w?A!C@hLfff #Ǐ߿fff=B!3BڷoߨQO=zXv-eff'&k׮LѣGW^}QzҤI...LUPK.}݈#ӓ)\./zwܸqA888;vԨQ*b]":55=W2|uǡ ̏za.tCtym3NFoUlo sR_RtTe67B5^NcqG}tkR*UԳ'\>p{Bj X[#m5q-&eᱱ!BLu^Ksпo̮=^ x#7MG^B!`KoZ%t\A$wwnB!TU+Ô)$IzzzzzzCӴRQ5bLȫ"+'!TIp/y pXPǺ*VK?=cVXב]5)]R!+1);iNr‘F/9ڠEFsgRjs ݽ ?>/~M mN]RR^ih1p2 "Uu^~~pK HwC $ҧi/^|%H pssS4b) +s@XDi" 5mFc1FL_W[:Z"S֡|ŨCd N3v^d9CZ=z%6XJM5n=A'Ήuiۀm>~ &Io~ufOd XZq˰h Zϙ+ǎrT4Mͬh 'w8y4U4bQ4Ԩxfo˱>;DUz,INպsᓧi\.Ņi'GǷYv-TԹdI2JdBEӴ6[9l_'lٸNь>bL?7BAѓZh+ԺXKNVw!Q%Iv|8^&AdR%j5h+UPsЧ)??v EKjWH-s-+EAni*SZeXWTJ@*WJ\VH"[ׁ0Uzڀc<ٙf[ZZ*R)erEX,Kmlm233BP()bտ۫Li"$r堯ھiAX,z|+{:s꘡o=*iB]h@WaHʠǖ>WhuoSqfܚvޥi~]u+5@7iLeHE#<1ADZ4!Mvu[_?!ms=z\)(i>zs2\ .('v^A| mwk/Ќd$BPUAfd;;;zJ,+l.%2.RiDgB1 bhDn-ٍ sΝDpϞ9͖h\AҒ B&7}}~܆X:2woHGkSw*`rnBFhljN1ˤV-rn+q)54*I7NQ?dhTG9K*rPէ 9k@avN߅D~~&\ IDAT>}jkkcP(H222X,V^^fXEC4_Iyp ';2₼Z.A7+5U''v{Q Q\e_om;p/n,/ӷ<3cv?Q%VXr=5Cl}#ć~z6gfNtBj۴M#m=[HTjR"W.i@!9%8Jd\ьajȴYZV>M{pT*x;6{xN}䑛g=پDIb+Pue2ɇoncK.ͺIRe掞$I{4ZHG7~f k7_uAږD3OjX!ٺM?ygn7! B$!rj7͏$ H IEQg?I8WEC^U6`"Kke2ͮUVڵ\nVVVF߿Rh&Y$nB]\.]Wr;D^4w@ *&r{e4 .uN[(ØMko\nO</->OR nŸ=5gxfV]L䌤#^mm1n^|F!gTpFF[څ WjΑdgW›<.ȄX$8mH[Rظ4ǫ-,B,UC L :?ї.'<|f4oEѰX,/^(HX,éamUsʎ[UZvMj:;] TAu)@C Luvwݣi:??_,?XujR , +S !TzUz'y!C]{cqB#lUȫޭj"B2WqrZ!B2(k뢏1Xd B!x5sڀu^~~GO!6jdnB!biDI>wlX۶!!/2Wk۶iӦgB.<$8844Tfѣ%I>}7nܼy=zY BU իaÆw[ лOX|bŪ+/X7~nnnP``PsYzClvVV֔)SN:]~](? (*%% ^!BUD 9aK/+sAtR||-ILx777WTr;v:xf8:8hܥ XYY'^ڣgOsrr( _xݻwg'L0vrBꭆ[%BZ0h!IWn޴NZv6J*tEQwF*?3 nnn)))gΜ9}3B!J!8$͛wnF7Z~~#3.عs']veV  !㙘IIIEs`={deB!}45,>>>?3yfԨQΝsrrzy``D"Bչsgfԙf?z lܹ֬s>}?|ҤIovvv^z U͍7n޼٭[?%D!PI}j#z( RqPX,Aϟܹ\.{-3(k(͛7ǎkʐСC-((ҥKL`nںe˖@8w\```f$IKKbgtޝ8{lvv† "MDSSSSSS=Wҥ xxx*Pggg/ eeef!>iڧ6raHOfRhi$&;uT5kpn޼Y,ɣnnn)));vt钯T*%IR;LkJ?LR`_dYB!sAQTӦMϽ [q\mI(21UbµX,!BqL3T*I2 ի[ZZfgg۷O.׭[799Y,Y f{-233I[7֭[Ynٲ>}aaah4fH$bm7,Z7n8w׋ x"SUʯH!Rpc]e.Eb]Jod$ݠrybbbBBMzz'O֭kdΝ;QQQA(Ç{zz+"""5j9;;; ;;_m xo GG]v}JbY&,,lܸqfff E7FEEb7n߿?33GB055h>:t.ڻwoPPP8˖- ܹqVB!>Dtkԫkf.0?ن )ϫD"Q(Jr߾})))JrݻwwppPfffE:q5iSTXغu֭[O:U%BUW-ȔR*SJ??y|/` )qZv*òY5ӕS +E*7XQm R_ Գ' 'I/J<j4s8.=??~\&Y[[矕]BU-8m n@+L?f3 ƖI٢ !< [1ulɔ ( BdyF 7fמb ajGXVKZBGTX}> jOt8m@}Sx\.^4M@ ppp("B}JZ68EQڱU)dl6¢rB!T3ײT*R\.C4MꜜPaB!9[x+B +i Bs^IT*APehRB!d"68yQVWUu}nmn^д- @ ?@D8&ibf 31f 1g>A o&QQy%"Ң-V׽SU~\ >ի>Tw]8)UkL&;;;] h4m;`0NLϽ ͉_[ou߾}M2=z|,X`Ñf`0kL?SJ3(aȑ#;w'D"q饗?-̕Y>v1\½lWPZݳ>;o=6mtC@ `8xbog6㸎P[JP/R߯jYVmm#<{77nP(//O)]&M^x1b|qʕӧO///_v/A+V,_|ƌ)ٳ7VWWWVVVVVnݺRJ]ysinnrD/^֭[MVYY9eʔ_|q-B0,XxƵ7XSS3a„-s=,]tɩI ps`0wL\6!'`'fM`QC3cO\sغukGGDze̙s7G"bwqG8!K ~ϩ੧gϞvڃ ,cb1up‡\U`0 iR?UuՔwuumڴʲN:5 r$w=n޼ywyrsshK{\U`0 5߮]j]K/v/_;o 8ׯ3fW\ڵkǎ{5H)NV5 J.Ylxq\6c '[cٓ8O7ue鼔dZq8}XffM7mJ ˲lN_`0 `8gLw[ }:BP(B?4u`9q6`0 gOy=)X^g s^S?7 `0|XL MӃd2 "X(*(( 5 `,a׏˲֩*i<335`0 n<O&Ap8 `0> &uh֬{6€"B91uGk (`0  60~: afQW#Gv9O&DK/?~<[u.رc\{8J9Ca_[n9|`M6]|g*=i&e0 {;#W:Cm)CmpH}ΫeY|ڵWX|3fgv6nX]]]YYYYYuֻK)uWΙ3yQ^x?[n6mZee)S^|+(Fu{z{gҥ'ON_/Ԧ'5x|VZU]]]RR`0 _&m`X.&0kc1O^}ՑH)VTTkZ뺺:IoX~~+{M:u#GUVuvvN81%e˖mڴJk3wUVm޼Yņo~۶m+**:~rlٲ͛7۶y!;?uBBUUU+WknN'6րqSCi ɬɣ\q]g˟WSFsյiӦ*˲_[[;u`09O<:z躺y޽{x1 ӞyހOmLiF ~Ck}%lq "~_oii9>%CC2x|y*s~ `8?l\]Öé!>:u"++cdi6H555 !UV%挌 XSS yhhhسg̙3}O? ǎ/9sݻ_'DiFI1w}m۶k Pꪯ"Zzȑ#G1L3s̝;w3un `80ұ~ë~ci~{W,62c̯L&ݻgϞƣG+V IDAT@DqnRx.\X^^>q555?p*GM p͚5z뺜zhΜ9wqGMMM4ݳgp+z{{hҤI>?˗sC|jֺuf̘1X5kV~~󇫌;r `, hhlO۪OokrFɀ:}}}㸮~1c\q]vر\sMAA2t6T4 <3&r2̱5.=sDySm`X\[KI_;ugefftMx<ض,˶w}/R"y'?ms `0eaۚ^yBB!OBRƞg_[|}% `09!˖~k:$~k*:Zb0 `Iiz5LD B`0 %`Y:[%"u"Bgff~ `0u`r^?\׍d>3xX`0 G͚uϦWW@D8 1."hZj0 `8KLu^ 窵N&vttQKKKIII4}I`0R'{~įs?;wΚ5k|,X`H3w`0 5&m`X)g0|Uk}ȑ;wrΓd"KǏe4><;v.W{6ΫR,P8xƍˇSشi_|(`0 y{K6㸎P[JP/R߯jYVmm#<{77nP(//O)]&M^x1b|qʕӧO///_v/A+V,_|ƌ)ٳ7VWWWVVVVVnݺRJ]ysinnrD/^֭[MVYY9eʔ_|q}xG2;of„ W]uU[[[J{YtɓS0>xU `0alB7N7N̚&r2̱5.=sDySm`X\[KI_;ugefftMx<ض,˶`0 sƤ K5ǯ*B*=3 `9!˖~k:$~k*:瀽`0 Iiz5LD B`0 %G^qEEQDt3 `3q'I)KҘqQ,Xz׮]\]\\qߪ~~r)Tְ?SJ3(L!|7~@ ?~_uAvF _wsٴi_tά^~_r-pwPرcenܸmկڬY.]WFPJ}- ç2$M|מljܤIO\zK) Guuĺc"i,<LD#cǖ'򢑈e Ks2C̋*O6jo8uÇ/m;wdgg!% vԩGeK񞞮d2YH%qsҶmCam[Y~"&Ic22
dhlhj%≸" 2MZfLVPc g4"0Mq/i'y=uqst6_8XY)ұy}}}999ّH_;p7xcMM̈́ *?RR`0ߔO>?aٳg;.K.d̙of͚u5D{.]:yk__~oR___?iҤŋZ$[7VWWWVVVVVnݺ|RFIOOO<PƎ;\?go|>h*ò^QF\vW瞛m |^x?>D yiPB/Τõ$HuHg(]I qb""DJ 9ٌB",dٚģ"Bbxn$F ڶl[̌Htj咂Ա#KF!P2\qK׮J@erm'E bn\˴˔'HPYqUBSHX!n Œ"LXY r-t-t!`uC֜jRF<%v<Ҳ %c]Ȝ\KS ­ 2" 1BAfsB@` KdBAa&tyMMMmmm999iO?#999p'?yTkll_RR2Xk_ھ}ʞxn78ϟ?߲,B™UUU+WK_җ. -Zh{ 7~]~`8?`4*BE4jiPJIm$c`##FI)P3ZkOz1h82MڂYk]eBIRBdJ}]17'+x睼 /D$ߡRҕ 41`!"hRZJI&D 5rΐ1E\X!Fl -"Dd4$R ai192DĘFФL $4kDS dg~i Ϝ9yN%]5 R)BNki?B@RJJ"B?.D|M01$&ՔV#"3x@ b555pstEq^zu !=A{׮]f*))}k_ݹs[nַ֖ ߞ=/ഁ رcc뺻v+.WCv5u|;~W\qUW_w ^m۶M> cYYY5koZ777׿W^yok׮!IcOmm-[o%KWSC~{ CcTP |gĈ---Bd2y )p9w~ݛaÆo)T'zk_͛_]W/ OB‚}:$`0`얖SIJG3YǚKD<7{EMofe7;ޣ5׿ScJz\b(HkD HpHAٱvvjg[Ö73Ɣ1x}7Hk@WWȑ#Y*2##1YfٳϠ}sW+zjv=KfΜsN߼~z8&!ĵ^jժD"?4Oϐ1gΜ{b]]]@DW9r#SPP0{l~cǎM8qp?g;… 'N WZ5Rrx _Tvv5kow]ssŋpCC` X֭1c`?s֬Y7E 7\b":sm 髝jY[ou]sC7n'Om`07E]',D8wiq@S]v 5i@PVD5߫VJ"XsdH *PVsa :n/I.-]"K iG!9ra K@$SZ!g)," ,$1δT܄TJ2CT:Z[\7 twt[ec.F3go{Qy& \JyR*֖OJ+۶&mm( I-)`# Ɛ % B`0cĈpXW5)D5T1s~5$ % !e#6PtL%lLi! ,@ۃ# F̜}92ڲmsuZX{W{[$퀕{aJqrȻsҤ?wc FBҶ@?%KT{Tk (N}Qwww}}bh4`,ZBCabLII@1IE-# jDF+s<~]սZk3;߫je1&Elgl0y WWR邼U8EA9~x`$۲A`Jo<{kE-KmCߧT߰9~Z߯,!FRՆADQE^{pVc@Ԑ*\1cY+QUeQ €,R9UU᪗K,Hd,x0Q]"*TB jj`_*x9/$(8Ւ4MR}YcT5m6e CCfzl{kڍV+;#!p`v:5+VܴqBsD[eQ*3I}јևFG5gYY^!QU,Y@*mJ#U%HNyYqw壣ci!61ҏ_n+zV{a<=t"n)s!}MxXTM䌍u! !D j^t۪tC ( ZO͠Ǐs۲,z+ 0_A0x>2%J^D1jh^U Z{'kUI+") !Qd#4d8{lٲe˧&QA8A I6Z bޗDQlT/ kpUfh Uv{jYE+(K2XPB2* -k 62d90jt:I5, N$bl[xN\#ձ!Ngyr$Y3/aOY􇇇!$ $''5MBǵZ7C͡$N461& ^Wt+E_@PE*P@@ Hkkmda ^f XQ!;~eŹCڽ2/}"XXl4Xl(K8㈌QUk,0T-+UU\8s ˯Aɹ[O?4usss<;17mFw9gm>?ªq"IeYQ1d8) ‹D"BQlPDyϢ,. B"F" g R["X+R`Ch Q%?QJ (WzD#`ev{.0(,UQq`QIE-|>xUd((g *7F  ,JvP8}Gv>HX8|!z/ˡ(E?E^ˋNkq1y"_jv}({|ry0ZkQ\py_fY/ˢKKo/ I)(%"(>FJ6Ce١|2 GڅwYGU9V]?hI#Pa(JZn5|xgB4*!*c ""*ʃU1(8 7r]+77ƯY=쳳i&Ij㎳:x#J>6MV# Gy{uoP=IkmU{饗tM?eer饗ܹ{?==}n۶m' pomݦ|;կt?/|'>:׾믿d]MNN~;yk_[=۷nO}0`0/}'i*"(@"ExIE1\եb[js;cS5\}ᇷmvWqj ݝDhVZ=Ϫ**@% U+DBEBB@4ʕO؈T5@ȊZ"VYG2&ID (@T(yUfU&)pX _-3;HIT:BDfIBA+Q^DD, AU*]"LEC.B23&!$MY ;~XF1(rTưT. 6I⣋hoYoݞ5kVX6&j6F^CpY^o!Z-Mtdd$>4;<\l,T58Mk*²TڐUe͕ p$TQ@5P8!~>(+eKIl:5lU^nzSXEBlȗY' PU8h6kpqÝfv}n#α`TZD`Q%2,d ~ ZVteSjSsՋ/,G,u=wGGGG|Oï^p[ly]y2Z±n޼.?}lmeYm׾u{[*&''/JK/ܞN"{o_׿_xw{oTV3˿|9폼>'=D3^t/QnذTn_v3:G?ѿ:VEtevW^}|Bk>*czo{8''ܝȀ~j ̵Zڨ7FGj U1@q/Dj E=@ c!x|`2p%*9BШZ_,$B&Fj"CӱYia)yY|,K_tUY{ffX ^iˋnK $Ra%s#]KRE&/OeyYYZU#b{O{n[>đ8c#ĮqϽ~V{ttHEgN-,l&I bQG?pܑNsΕΗ^Vgv;W%s5p`fV5֒@%(2$:, abDTcdQ]C#zL7i){;^\+Ny/\%zEmwڊ`mLCIfáCcco:c !~X"2&"D&1%%4F A"4^meP6pJ޴ecC">33~kzxgffN#;ccc|O8}[vK8pC#]y'}K.Ti?{̌T<>Oٳ-oy>+;O/ҩ3>>#l߾.>p®Ү_4^w|Jʯʛ??< ,4 IDAT\ve]vy$|49Չ 0qIk U&U(؉ l V >E U6]+ QY:D"bb*{nܴNTEŃI6wQEC@YTffJD6rURQ F_,xPx"V{2tŒUρYT!0+{9E }(KWntd 7@EZ44ָ?pJ;eSo<^w聙C۲irb}8.ڴi\uU^{ܱ|{ң?e#y饗 Zs;E]ty7o>~_9!oVoO>y|ή]gy~~׮]ISU oX\\tFݾ}w}=?^wz_|/駟&_s5GOzeM7~KcwTd?qiN-[n^jITA$MԐ5PZ~T0D>"%*c!ey"Z[+}'E J,eY:tךxd@EnwG֬]nmePdYY@U lQdE :4 3g!Zsd" *A3"cQVsc |YZc׮Y~bkjr26,01fs(S)]YZ2151e^|,c_TろtSKm9U%eF+(gjjjhhȑ#ڢ(<B8Uw/~>ȷ??wFܱv->8p[nyUz4OOOc.b⋉' 7W>裿y]wSce6 0W:vuSQXYF6,c 1TVG+(ZBY91 EҺ DI-MDlJp Vk~q~ㆍidd8"" вHQ~O@Z+ ڨk:g Z8A%/*}YSBcIA0xfBW9ӆ 0B3:2ɊS{^{ZF$""c,P-uӫib̓?|g(*Rs^XE8d(+w891>51GhE ,oUDD+G-U(&c@/ dH@@k-JH*2FjŪn8o,Ն,:*VeNJW6kA;{S^di gwZvY@4%CeԬش'E}Z[~|lhʩf3&DD|JcLZc(y٫ ~ǜ+?N:evE /,,رc?Gt:'nW\YʎUX  ܶmo?a?o}[T]J_W:묗]?߿[nyD'Iy>̭VXkp yW+?I3tM+W:~?˖-{V]]vٳ~~~u:w޽{nڴ[n7lp۷>8??nغue]e{n_|vjPq$q$ "9;Wy" ĤJԢ(q!nǠ 蝨jZU%*Xؿ$E}Q-yei 1>x "ՒhXs>Oz}vs֙7J"KƤqjmD5;5.:U#ͅ#lY8xv20 P\D99}V.jRD5dTUD<9fSE%02KZɥs jqcxxm,!ʎ-tn5:6MAd|"ž} w><˳YyOWR#ӫCK˿|[g&%qʥoG^hwB4OW|ՃuadcqϞbkll9raf)4F|;򕯼X#ٟ]ڼyg]8==} 7\r%7ngzz_r4::z70`ǎ_/_^EH+W|衇^9ڧ?|3\rI _Bo>.+;A*4M8"5kR+"PTm " 5ֹ*8 ,ƘzJTdE(*]*<YY/빧|ZYjU˧B(U\ˢgY?˳9%[J@Ԑiĩ>+r=(EV.Ka@! XUUE,X!8RE3N{,Kwzchڤ"6&FGC UhI-M/&GGWZ1ҬG~>q|^wA8TŪ +EKQz'G$#K!*,r$leT+P*ZRJ9he @1|E#juPm444OGHp[JZKO 3>:yz+FMQٹNW}wG ף$>x}~):<2ؽ=gFdDHFhz΁CҤ1>65=nDd֢H"zK}5r?T:[=V=8t^CO>s?glڴiU*"o|ꪓ 0'3꭛o{9ӷy7>e7+`|goX6>,Yߞzf_v붜Chell Оm U% ީ1ڨ7oؘw{~;lGDQ-_h(Yzz~=E`qD$]lЈ1{oLt[M_3sGnzDAUDNNLkaq03_jHYG{/yזl98wd۱16:mT(k SK넴z}xfGg@ݻFj͉81D1ƒQdIkKTk6lظbŊիW=_\w>!(@y><8":JWcv?/|iyd=8QQE9/JWaʢ(\B%l3 0PĪ"GD362~߼bjjj|b9ROkz(SIRCVL ׷wuӷ?:U+1<;0M֮ۿ+˷^ZC;vig] WZn%E[n2TJ@DD%jԆFG&&ǚ$$OMo}s6pJ++{Wo㤃+KD B$(** A 6,eyN[BiL͊U`fUe)JQZ34U@˦N'Uz^EQ8_VߕH$*m#HPT+$9 *$XȨz,> $-,-ʼ٬s(_yG ƀ!Z@!oVg g%sf { A0B]1#*g^j# <,s;AYR\*clb+!0%%E5D`ī &q21H^Y=EKc#ͅ^/n}t(*J73{HV-_9:2"Xm4CCC(ĩw-g9<_X߰USF(ҥ^:f sV06 ^o=z:2::zje/V^?Vw38ȑ#nwlllŊ?. }Q@T("1H(!T2dACdiɎ  (zwY$A$^V4, ,%B3R INkq!M¹b AErHWHP$B4޹NTH(4 t1WQ¨*lDKuR2ρ "b333VU@8|pB2%kYTث !;GZ YX,xER1+y e`QipY ̀ʠ ڦ !N^+ U1 ꒹ *WbEY9r6WX391916y~٬ߟ)ʼGzfG2VPieEatlddacF-]voڸvSSgl؄s;|jnnY|ԝwEE2wQ%VP46bf["XY889?;5? j/+scNx֬Y3==]Roٲe!C^zX`;f*>ϋgv52(89/M_&gZlٲs9i:11vڟ= I|` $L$(%>0 7(6R>sP8 !-ED _DQR*Tqr(( zMի; ~UV_|voxxBxYO>=g s`tl|nIz֙[֮\,a)"&օnW$5k &܁,/f^{4Қq,nA(.0(ԏUt: 9T$FT$]b! vld7lfUHnPq8 IDAT3/ZZuB(ʢpy֚IZ3d{F-w>Ϝ|gdLl#-2"ndžkiXcMEZCUluEY4G(DªUUVeq^!EP49 AP=cTf X.<1k$ւj|lc"8"TUP"!@ ؙbJm5?w[<ȳOyzϮ~'^ƭ[ q}U׾vW~_jrr;k_߾u֗}h `5h\#bXh/?WI#*QeP[՞—%[ eDD";v2̠։Jh@)tC#c!pYRPQ`T**"wދF |wd@C@E 5h X`QǾpfFQ~o`\)[O> Q 02J׿ "!)" "6kgg@%("U&}%ll\,A QʾLbրE"U@@a JZDe5f-H RU4% PTD%M8N\~ukVnټqƕ&}?_|gvpޝw&gZ"ŅtHC N(t: /90N"2PKG \tԊ332{Q-IYeG8(AaTDS 0LeuЏ|!|׮]ILNN"s^صkOa{M%vM7MOO=;Xo0WED>zDtu]{rz9ܹ;ؼys9w5|{;~m۶]qq~Qйé%C1E($v$ukg^4p`"@@AQu!0 "BEt1FN5D!@az`Ǯ"]`/Z"+вe{Yϳҕ.( s`ʷVE9C(JWa"KFYY,jDALA Vc/<˲kiZbk Wη˪= PArU5{oeYU9w[unhhnhQ0F Db"p2~(%qD ~-.IP izp>vHKV瞳T~ABH̜\] @ʓ5翫gv׆ϕ*%pQq}% Y`(2 VJ#DVkM!P (lFq\ @@_#d-m  0""BVJ4wB>өe >O۾UJC^~i]s{fg2bK1kJlcM0hmb''FG4Q*dffƫAehd˖/=>{cvolA|qdhQXT*UO&TZ8ꏯ췖l0WGkyuԭq_{\xgffgƘ}Cz߿!2"~s袋BhzܳgG33 e٭-smtR@D$E|WAf` aQ[k qFQQqƱ1q5(WfJbKAeቁR0)%+Rd@JAX"cŊFƂ yJyX"BlL5Fƈ) H)iiim3ӓRJHJ\)#RSS!{?3SC#[rҔ5e3M\o*䚚 |S/4 BP75g |s>ߜ_d l<88J Ȃ"V EۃTQDBOSl [a\TeP)Yk( 84!#B @DJAP,+"q<6>695F|?ϴ䳹j9L:ۋ}}{ow~Q"0TЂTbۼygsrNgg*3ՙ*R,,^\fsJ΅q`(*Kj\FQGƲ0LyfR~80 (% aqqO|qꓻ2>\ʎ߿`yq\.9bxہ*pM7}+_׾v7Λ7m~ŷv_/<W\(k֬qZz9sʕ_vyg_~彽'^z9s?ߙyӦM03ڭ߰aÅ^x嗿+~_\C3߼+p|/ﭗ]=RinT?O?oo / F*:8S>餓n#\H 4+̢JF B,r\NXFG-5=Y i"R "pZg(KD"H.uA\5Mau0 P٪=fYja+5"S, :SzjR p^z K,-2?Tb(!B  HQ 2LKS>0.WŠN<ḓ.Y"bۋr%4ZՠΤۋ-t'ر{3]ݝ흩Ta?\'T3whk-_ݔ˯8~\-q+"<$@&qq L&hU_p!GOxi-Xгqc\O;֗^z) CT%K@^kO^z޼yp5|3Xj[o{D;{M6LC,Xv-,\prr2'|sΙ3g|˿C)}?sw;)211Eߍ{lժU+W"jnn~7pC6?}qp>6lxG,J^z{y=裗^z͛Ĺ}k=Wn֧z#Ybks9\)Wʕrm|=nyIGGs6rg֬YMMMZ k9&򩧞gy׿fKEMd"u]7<<|?%"cF0M6=#?g?_l*nr 7_މD7'ضmۢE`޽]vٷywmڴ3p/]}G G~ᖖ=Svw7xX12E 6.Jsxtttl|NW7O&"yc!aEBBRJ)Daâ9,ATJE--|3B% |]j%?NgRZ''/+̱RS}0 (#0#R!߂ZkQD eFRm-n-j֔3akVLMfJ3ӥWZ)XU.Wzzzcā:+  "sOe$OCٹ<=396opT8 35)Z0 ƆB`L$+Ϣ#ք֘L:mM&@B(jkˤ|F PE܂eH[fT*5U!nݾYvҐQ8^_ݼeDe3\:T&΢fjOQ0C&fBj:b!imm}mH|᥍|SO]}8޺egޱYc9Daf*j5VFգi^/z!ĝ QP(ܹsϞ=IV5:fϞgueSSϙ3\z'?Bp09|d۶mK,;-[v@ujjjhhc[ouٳfzswϾ}{;fb/^v <y7=ܿxV\iA׽믿w;8?qlٲ[ouCCC###6l8Sy晱 mn^x}W`޽^z~Cލ#?7}! 4 baFO"R2ٜ" mɉɉƎ(&fDIJ*dbl F8DOgt-MmŖŋqŋGQT0W˯\.Br\ $mWؐ|>gEB-(dBi6灜})[C ""DDȖYAƄHZgv4:mms֕dƃÅknѱNJX$E$Z˓JȌZ[˖};oOrl@ N7eNHN{A(0bä ,&H)Or\&LUy׻_۲a caTB^S);2&nݜkdsiBP6m:<65#Snxt\xgJmݲE1jTcOe+}?ƣ(9^q¥.Cm;w",ryxxu8 vt~~kkk[[[2"??\pK.=ʞoy͚5-rns}Q---sT*q!w֯_gc^}͚5L搗/SB0 ?.s={(Rַ=#_K/t-tvvΞ=g=xs=uO`tvvzW\q1Fk}/}馛nZf n喩v/կuYwwC܅4@-H\)VNe"K.UH{wOU:-V\~⥾ֻ4!V%zã}}aX?oa&۲es.;ga9 ,lohoUl*jXmvmݱclll```rrrhtxtbt3T:\ȧQ,\D@!@@`@D< ""(F"DO O o Zӓՙ'rIluGG86FSy6sm"ceT*H JP66֞~+.mmjhqWWOǜb[q$qGR?Gk/x&v tQVy'_v|^16m޻w~.]x 68o{֭[wjwJ*wyw_h6ܳ^F?[=oHaQ,d}OF g jPzJONNsCP BEgyvku֭.[r֙g6,      U&ղ1!5W HMcb '"BL:cc+A"Z4" [l1ȲMBc+ ` "DHH"nj*Sɉ X$stKVXaa?0E"Alnbb5׿gpdpbj<ޯ͡!8,G^P,+Dr ONNڵkɒ%333b_p7:ۦh~+ )1LOrdLs^LSD Q-\xL{[{r96?er_>3t+NMRam߾cwoۇ&ƃR ؄V'gZc1ak1Y:;~b)1E XFV\P At3\bu2w"D. 2b6$XS[Xv]RvNDN""rA)tIŠD"odxP%QS(+TDIJ1ql# $1Ɣè<000H S^J 8vW"j.(BP =RĆ#ccQ(>,`im-r5!2Q%cS3#w윙jδs~3;vFq`5)Ŗ\k5 )@E$M mms{jX4o9sAi`(}~ ^wܹs{zzsqmذ300y4 4@ .AX6R.T:@Ke2PdfzZݱzyܾ\*'zjtlh`xdp<] aX8g1"("b X@0rVP(S@aLBPFby*a@"  !>^ b3J,"@RS ;K5 [$D I7" J[fDH*0[ ] ba]`2昻 E mlAi6" Zk I].p}Ed2w==˖dZZs\@aT@33Aw]vlG"hlRt, ]S !B+ DAbf@'p!sm$pY>- "G\#CDzqZDD}#;$(n ;)@3˕VA MX!)˜f41 * H(J(a脪,\5n D , opI$ՆQ0B6 ,RJ\hiokg ahz|6Mg eDysi[)Or5"BO>V.Ϥ4Bs9S4ˤL!1xbK  h䄭"뜷dJʖWF&ƌPY)ϲ}p!H. A D ٲS7ƀvZ:x>J!JRѮ{K@ 4\ /OĤlZl%={ؾ}rrr=cCJBd-BW/DAV"bAq)ILHxQ@"+f1H"@Izˬ椘jTVPIAD@% 3TFd'3%DWT@l-qk!0`I&'AVX!X7I0 ;-$UbaT'1rg PR$AAr D"dFBD˜kFYP$&j)kIT:}lT ʂԜ׬PWe\nbrb;vn/6盉eL "TcO`w_p{noofsDdg~ SC4@ 4{=:2ky)'{٩\.ONOEqűuGQ2 䄡R15B9V.?V-:Wd=(<P@!w#ateJw`Lv A;BM8I r $̈hQ" 8&$) % $uˈ `$@D+ȱE@# )+DXc+%Bq eH~%kT;YRdb SRPFA\f)錗.4saJ' m۾m<=\Lđaa6Ii/f'v޶ǧ5jU\ l.Aׅ 6ւoHhzmy(nOןwk'&&rZ-Rq5NONN`S>B뢽=ju`lllΜ9^{7|N87w񫯾矏xŊwϟ6Wuڵ駟^j[y~wyҥKȰ+Vp]q?n MhR,@qlY5"uRH@B vL\{{$N)\&dUXZGQr:b>)ǩNKN(%Mn:"zWV7]5sDV+It"J.4te(>)Nʺ"w X`ᢹ + Ԛ$D@A&"c 9a:Ճ{+H&mEG+ɝʹXI򙬧}r9|Rc#![ t6Ny BJg4׷{)AhQnLwGˎm;>#Æ-"rreBjO;OXlbXuW:T*zj;7v{<Zg\6oOR7wGN8駟~;ޱf͚ٳg? ~|͇˰mgv?뮻ษ??>vy+'?|?ɟWz>C+V"h&F`{OA!"a +UkVQ ݟ_!ږ BHz]ّYNjXLhAVpj$ ky؂+@FčZe׺sg*;([fĤn* PD ZŹ8hE 0k c[;4> !8Ņ8ONkAK"h1j@n"$U J 6D @YQ; ȖH7*ܒqR%tijrz |rMͅbМdffeֆe\ 63T0G~*fgwuJS<ɋ/( &0Fq\f`xx4*۱v_~ehLHD&'@+&ܲ b9lzDC6pXDaϼ~\̫7A^=[`m䍍 st/JZCf}_7ccc{ݻsvWy뮻/="a}|3j򕯬]~P(vm˖-;y|~Νgw{-xwe]fo /tk׮g?y"^vر}+뮻wܹ7l 4[ kQ/B X׾}jLoRٓʬRUIT I]F2HDY, զ%p%ikïY?! PjMLT$<I:>t|<],l&el6lXrY:3nf]wuEr}}}_ƍ͛}ͭG>cuuuZj˖-\s?xn/w>`\^t /P.:묫o"u07+½׮]{rݻwϝ;ɀg׮]s=xK.$38hA}zФjnNuzė@WD="%D]ۺ#@(eF$bᄄ] )岸X %,*9VRu>$ ։v\ ܇ZoXJ X\$q tH:MX@BDpeR") gJXk$H*$5u| HH+fD D@%5izNX*"\X16ֲ D֌O''z{w*ebsSk)iSF#TL:5]MsG[sݻ{nܖBZի͛\sg>xG-mذaժU/u]wun͚5Jֻk֬YwwUW_|uݻnf˛n?0p饗>G 4@!I #3ΜZPS""` Q&Nt$ә+"e0YH5!(R,i:$iF 1q""'Q,@D'qxQDL'N*$X;?pκ@,@x&D]+[&+H EaB.ENιA\WrNk 9 ɱt04N],˹`)$1=J|Yk(D4aKB:1j86,R aTH;t:UbG{gSמ x~Ji] T52j+[[P(5 P BL*+fzr53ɢy^y82>tB xȘ䵁jC6P?w'_ukWw䍋$ںuKSijr* Ý;w 8¾֭p©s9w:ԺꀙO<ć~x6lp3tx衇mXa}t[o(}sodo7|3k7pC__J$cu0soo aftSWU7hR[}rV[uMNj\NGB\@ vg}R)Z6yO *GQ$VH\@"S d@ˍNJu*k)1{%$qV.ڋ( ,ɬ֭;`իW򓟜. [yy]{=ع =s9#ȶmۖ,Yrw,[/_㏻O?UW][Çk{{{ׯ_SO=cѢE-?u]˖-;w{̵HoDqU;0;Qft:R6$uM|HZ]JMH ur Sԯ^wH_6@}9 ".TppѣD,SFDdPX ;MuQ+cI, 8q_$<%Lto\&r91 lT)A\>&ÄJ$_i4X+u^fIAbh ȑnfse\6֔‚HD\g@JNA, aL&wmUs\\L>hYxgobK>N2[k`ED"f8kQϢǭزc닛^;4`2 "9 "j:Do}$}^p[3=R=sm{[ĬK.$J&ϻCRl6{ݹso|k֬Yh@ggOO}SRID/_~vm]ts={w]wÙg̏?]盛ھ+Bu㥗^[:;;-ZgvS7tS]я~'?E]fwwu׺u/n^vjjj͚5QXbo<h/Da@eCDG:]#3DQgT-;Uͩ:R}]IH;[FV B["%I>0 2$K3-sյɡm,9)W Mf ! #%"J4'P`_,bi!S†vCD#ȾqaveD@B,N+Td1;V* E@)BD bbk]'?95B DR- e2ڔӥRTJl9*F3#[wmMi?Mb`{\:Z,|: "D6jw`0-Z4wQWG;6o{md|D0Bb1Hhuoĥsrз:]=^̥ⷻRXa̔'X$bHˏ_fhaa?#Y{#x-_q(2 {qL[sh8Ƕ %axH IDATPyaM7E uB"Ȁ(L}?n?F͸'ƅ &TIfY|65nbROW'9}-aтըk1sD]u.@-QA\X$egf.;@ Hd?K~;r5eblٲR m)`ɒ%c:c1*@؀QCt,8 "ͬ-@`ASj)Zֵj)hzu{kHE$c ȝ+*R^ɰ1Rx%QG.[¤aRl&|Q@[hd7K]e 3wx5>R֫hFȄ%,Qz}J=o1!9SCzة@ AJ:{1G)RJ[F͗Al!dK,gLLn133= _`Zfm; m[~>^:l&f2 7!gVsm)Ke{6uˎ[sUiև$m7n8??Xl銽;v}=;vXϪpc1?? an#E `tU &Utj08J wTOT6)uZf h?zXu9cN*f\r]`keyY`<07ve@KLÂ'i̭YuUSfoZ.H;),լѬѐ :VF O:M Ց-!Ơ(K!ml#VEdF)e(3ssss&YM`n}fz4/͓$F[Rڙ̎ws/_YnU+WX2Il7M1JEB{?)l:u}vTw{&I6}.npƍnݲc{}n4͑Gnݺ+Ve1c1.~uH/2镬*)jnbLD%hQ ,r@,f̖n:gSY`$d&"dU"sFseK.oV]Ugynd7Z/*Z,Q`-~ #F <kڤ`c* &3#Pk52yҢ5DErsݼwej9lјc%_aCD;lndbuk'&&fgO(_ct-;y+֬^r-_>59dbטN8?Rf5+>u֭;fv>67}X\|T0;;w+V8#~1c1hg]7 ABS0ƑTȠjV@x: "̼%2)PQ)Ucʂ^KqO5 `P5R) pFh>a9$Uz nn:%Fvkxj%bH==YRY&[v݂"G)V5 $$PnRY-)D"yӞ_jXA2v ScI=wA SQd4Ei[d8J1; m2?TIZ1Uw#FTD]gVr3FWӹ^ErjD " n/#2V56zi _oFH8,Iz7I#@faR$V9%|3̜ \RB0s$T9 dFD[f9s-@*% [;w%hze+N-1ҿ5K.7X6, S0q5,1c1h(*r9eJ0AxJ(CT(z'v^}nTft κ?es*Lri$̒GIMfEe(b6UHQZ k*F,;P>-!uS E<~RgX=5R*)g&5 to,R(d[Aݰ 37cTdc @gTJDИg@TMd)YIb(% *;*M@753;w2(ie/2lӡ&]~>{'!ͼՇfqުO߯r=]A~!;??`8{/gʯ\|ﭷ699yo~s~>HpsϽ#;3og<pAΫ1Cl۶/M6Z?~ooO^q1x`ǎ7|._]z{8o~a77W_/}cy{y^lٲ~_>w7%/YnG>{U^<|͟OT2i ]`hVO՞E7:EՅʥ.0Khe,HPk!f)3[֛%m` 9mJ$ѪvNr.JVb2d4(Y d,Y07EX DӢB{(j-Jp%^ݟعsv/='a,S8y[o//&E~x;hwN׽[np;r 'g?dɒիO9N˿=Jc17wߛn)G?pOD~cҥ|rǧDvZ\sp8 ˯i͛7]O[ ^|߸k"]`ΝY _.FD=Sc10 W]u%7o喓O>9v{˖-'?yꩧx=}o?_]}v% =O~_W.³:~}駟 /=p9;"4X0(sZ|`bJB4, `99İh_5BT;a~StXC4ӴbdQD&%IZmg2+u%`c'iʮ@Vhj>s.;).T uQQ`d/ɥzK VYI3enYX$cC}BO9Pw/M3 (m.4% &(P(}7o4(+gnK+2mme4jŊO}!?v 3\ݐ_@mv~vz㬉M^?9ٶ;vLOO,?E(9b(0;Ggk-[կ~)ɟԝwys9O=f:kjjsSG;c<ްm۶_wu?w=͛7XlٕW^wnxSN9ӾotA]tPL_WONNUg}` >O|S:/Ou?$HG *FNr;I$-*PVy$<AhRL&j(HiId֕Q T]ǁ̚ZFPJKKBH =vd ˜L`+lD5%Q!1ZP7af&sdQJ`lHO!==A**(E@E E*PHr(X]fXB&Ԍc(*6LAc)HTFh=@!@C$+nfwL,Mm#mOzӐkYhm)â%UԨ-D(LʪkҽzkZq̑z~[h^(PҠp03?i}w{7mYϪY(L2.`|#܏<㐇_qu]/}Kwy_WlYgaÆK/t5OT~ׯ[>򑏼XW뮻|oo>&''m޼~^tIo}[J~饗r-7nL˿vTY?ٟδ{V^~SO=u\/ΨnMhsBSGoҺqr@P($Rm](e@  fBhe[E2f*'”KQjLHi B= Fa y``rPS -RJgu03& Nߛ9Gy߾e˖;K.npG9c9f~s}c;s=??|G/wЇ>•V;l+$`-3gQQgܬᣙtPR5+jI:6 ˙"ȘkCB]U%.+Q8?RTNlaEDhR dƪ΂QrO%g4vXݺJ 찴Tk3i;SPi(QNڔ3@xd_YjzX5lTXXtٗfUַUP0,"zn ݇ߜ* Y^C eO[gxIlvR+fVjzMxIsq8cO[;O0:צk&&){ {ҥ3k׮>mffFґG?6|0]7ʯʲeˮ|u=P׿Gqc1۶m|)'|r[n+8C^җ>G8ꨣ.ۿ}+_911? /̇K۶{??CMv;7"v3("bats3U9m!i`:3[X$bz9Wd2z^=ђ7MD-0d~?q ORmß;]essny^/}/a<c1 %^ >_=}q˗{D<U;m4v-PIV8cGgITǓ;shQF(͖U͐9[[enUj TFWS ]G1 fj0YQv2\]8q͠Ią,82lԱ=CH($24'Y 4-|P $BF-F 0:L*P'='0WJ,1)$pnpn(#Ǫb-Ӄ"1X}%E#r9HERˁ-d]JRAviZ!27s8w IDAT)-鶵(A ZZP,Z7V)!;iL[Q|w>\yYV.ګ?x.tҗLc1oBgJMa*͝r)KtLjU\DUgUtaPTO9PP]FLėeaiZov/W.īԂF):_Wdt,#~kUEa(R )Fz*ϤQ$$KCQdYHB~x55`NI0 T#Z3'wB\3JKR[Z@%̕ږ.X I5lIhED b إRqD 2P56AA3bW Qh&M= DuID/`!K|;&u+cIdRy8LNn!glhw~v}&5+kV<ҍӃc1cEƽ(32 m]t94BV*EWv%%   ɬ ejUjąuƫk >Ob>TFpjD>!JLZB*D DHNB*SH˪-}\ pV"s^CrVfbnC.G7O*T[)uh)Y:f̓ 4.Ao&{Nwa;̥{ Z0D(Jc=Q&K Xʞ0qbV IoH B9#0sv]H'Жm1gJĬzQojƃ?B`K?v'vK&Ϸ{;+c1Of|pTT43d dP] 4cPRZHFG kB~D(I" yuS`&"J$Յ,&:ԥfYq>d*]dKHPcDfF x!"7B|`!YXɨ"a9w\z vO[gLΞz*6z aޖ"A3M Z]՛ˊYs#=빹;=,ṋfV;d|KAJI0_NE޽(""z֤5BEЂ(ݻ9*HYcMcfY*nMRW0kҘM|bnxaÆ{I31c18'R""G|-|qnW)7 G#&B$@Ij+gpQp"rYo.U^HTꮌ^' eXU%xEPEC%c$ \1"R]UŴm46" (]hxM$MQ 2UsmQlӪ Q PVJXdHGA t,"{ 28̂0X @\5M x0i!٭k $w3bߧbܰ!B%SB,qeRGSP bqpw-X9b 64 ^C!P$3-]`5V(Gh98蠃:蠇@R۶1777c1yd"G`L!CqD*|9e%$WufO(z0q"򻈣Q"B6J2#Dd8UL ת6_4I. 9NRŊijq FrkzzdJ+ DZ`FT\mVӝܸ5/GZjchPc! cG($BSa;?ٸ5^/ELNHJy#f`m۶oڵ[n]|o1c1ƃaOrnֶ@ZȂPKhBz-X ; H:JV5ʩ.żvH@†,>"0 RmYJ$#EQH WeF[@0ˤ.Jfz(HD7frnP1:6[TzG ALݪ N!sTPvdX}Q7>"dQsd>r9|m!MR!JME bXDxe mjjSr* ]nBtD`P@5\ ]Ibybt,0Gǵuwж׬Y7nܾ}mVZ533z1cyPJqs5jS]Qu1 B56"~6fig-1/BkɶT\m^^`ӦZ9tKIXh%1uPgeidkJvnNXj즖TJ, -5Jr0*F YPs{L ڳP QiM1dA6ҁ %ݽ()"7n`)<jUtgA:SbJm'oש|'68dar) DeX5f*]m٣??GsGqU??߾fXz躏>زeۗzw^1I/~nݺOyGuԑG}vug^袋H}>ԧ>;^W>㉋'IJQѶ$p+ژ; :FK%~VLer'(Z_u Q<Z֝k#ݠH/cQ#8hRVy=g:ir[ =AJeBBBa]`dw-{H (|ꐲ V=Op,EQT2 :D @]mGupވ!%BկI&^Kڈ)-$̠U F!Z3%E"RpeaoQeNB^Ϡfn aVvX`ؖ6rӠ,&$Hk! ܠ]ώ>,um۷e˖k/WiӦ:h8=mŊqwꚘލ7~/իW_|1\u .৽i?|ի} ??/c1Ɠ׾n|Gf͚ 7n5y?ncث_`0V^}5_|q7z誫[?{'>Jկ~-zF8餓l߾/~ի^|eoooE/zw$7x,??Xa39 hR6*$H(`jKFZ)yUF> ){OYYfDsfQf@D"J(@UE3L)ֺZTlvp5قdCD-_Ư2x BN-Cֳ$"HMR(atڪ6v 怹1h#`pXXPdWH/itK)m[J%2h!vF@Up}͹wkfّ"R c,B.7F2K!K@\JjG^Zi1ѿ6MAn$Mׇl>FC뮻n: "Bҝw=o{fff}!j*\/oٲ5155uw~nejj=c1gu9眳xgo1sN;.{s/~NlٲMӜz꩗\rɥ^z/&W^y13;;{i=y߸q??/"$< a6\R$0:c:KJTޘ#O4HKg]G6v7zխ2[)8I-UO#.lBd= {HwVVۜH!$H٘.$dW2FS2|=+$QRbe?"d LndL Iu3~!`]5T `v"r,`;R:_G|$GxCѰ! 9Ev4E c:4"Pߦ@hw%9KeMƋGɭY hUZdD%]:>XLa+7MYR챜:Oи(`^sRY'r܍HHBL3%} 5 5IUJ#0de$yCՕfSҚ ϐTOJY%GnКDzMв+Zu+3TL&T2U!.J9-44=!mz42,3}EMh@b87;k52ʀ.W ׳]-H6%, +U Ei6 2*h3xː_֕u(UNF MչM f5(6Uv(0]D'Ba@Э`粶.{}zҥKu]?я&&&LMM\r9QͻMMMܹsO>k=|~3qgs9wn/#13<;Kԧ>꫏>Cٴiӷ;믿{9ծxӟ~y叵]1val( ȨgEȬQgDм%Mk`hyQl ^{CVdm"4_Z$ Ȏ4(( Sa[#Z;vرvaGuԒ%K?~_%5M3 ׽=ojk~c{633#ȣ?)7xEڵk_K1Ox|;y߿nݺC=~=?`[o|;dݺu]t駟޶m4GUՃa'xbכ_w}?#9D>۶n-|.fd qb 3R QS`&TudC!"MܓW`Q8<2\RQŹrXE' }!j,(;ADDZTJx\gPeJFDUC,n _9cFZR]K)MCm,3c(J/J* H%RiC%F=|ȺwGjJ{.+T s(]f0m4Whf%fAY8 =ڈvJ; kQ,`W%%n98"@ktסL ʫv7'Nzɨ,mntOSG\pW#8/|G?%}غukכ<餓g>6S`"c1x, \zI/<\1߿gmHWzg?wpˏ~XyNFꔬqLUZMRYh#GqPr$JqX *E +(Iz] 8$\ܬ0 /ypbT?ify앺X0tճV` *=SmY m"Щ(i 6dBP镝lcu2(uBfiD0<ҙkiJe5BTe2`̀PQ1%o0#ҙ`ߠD/]EJL.c:B%0k\(eKW,[rj 5޼ J[P)2,xѷ/*%rLT?( ʇ<y "=(5 N&$ $=~?;;iӦ/~񋥔u^${Xc1xr~6ǛРRO-]ÛoOkkö-F/S~ePauRn)W=9N^r;5\X\O2pZe{0^Fn%C!B(mch *h)1N7yJ`yFI!7/X4Y9#a0 n IDATt0aTm&)%&Y11JDHޥjX)f]l 5δz5lFA[, uPYuA@*hqM; Mqfɩ%Sj[;=$f%%v~0;GAJ( E@QhhFI cI)Ȣ4Yw> mݻ1c1x"az%˖ F g-;w}{sϝQ%*YeI%ɒ! b N3O@7$ ISChHCә;x$K` T%J5;io}ˊ mM[9չ~{s]{}"9Oyx߇?Ï?M m:Ǧ3%RP3%u%.9ӝ*1옱OEt1zȂ[Sf*;K@f88͝834Ҙ!dLdB$(͜19|AHlj́r mmĭ/cHo:vGPٍ݉:wiߡ,ȳTp(5v5Ɯ{  uDu)2^ V ĔJU0X\u-kHS*-ڳkui[gT/e:!#w-X[ni"K/G78y(ԭnc/g'oWͧ L34L3|hz]'|ԧ#7 teg:TɮaJuֈ98J9fpwJ,p#(]D&v(]\;%&!&3N3uSnŢ3HP8T#!Bod *&rr& l9*ꦿSډ=%1Gr)+IEL39Qb0)БfsD&UL#cbwe5$f@BD+D#[i&NmJ`n-ERL@IKf!wLf4F́;q$HY[H)IYH\aC.7ڝ FuaJ;_{^gife(Ξ^K-:ܝɴ*1W^}?מ;udahXbnQuy?f.QTT  $ݼ:SP,u%WgHg۹7D)BM('8$f1-)  )Y"B1;y"Krl1kr!EvmĖAj̪^L(N`\ sL4B%<;h h)33ttY:CQy ]!H rmnmmo4\&NƜ!@mL0 \3h[J)XT9kMe: $["899HLfZ4&:,QdB N(>fiO՟3>>L3}~Ikꍋ\qx076d:L"ک_w;MWg~O{JAXQ5B 4@cA$Ibކ]5G*$XW! ~I5UQd8$ <uh,N,1&?v6̉ Y_3'3sr2DRl;1?olz(`0399I.P0(IH9cc "D$DQvpWs B q)LԨQIүk3+ṓۛ)  ``m[O'CM:Pe8QRVJkdd$&b唘,j'`@U n]-f "fkɈ:M{ͥTs%؉?:L3}nt)gy=>>L3}ie{[nGS&uiq,Ħ)J)q]mӼǎ;ܵ4z'7n,;I<P"|=`sxDVԍ0A]X(sh9ThQ!f'34!D,ɴ͔],'Qi€w&ҘLVbAY͌+ ҥ#D}& W|gD&X2R#ջ)0*$Lp{X4+EVȵ8s23P0BrU۶Oڴ-T[m[kT])3P~48N 3slZv<`X +L9@«\nl&??PY3֟3>>L3})<+^q\.nl=yiaY]Z\Y]Z^^L٪:%p>L3}),}[[^߽8?4h8pq8U|UչEKYw~ß`3v'u&6UrRw3k9*@QI`XX͘8;(mYRtRE ]ĽD+#f)%q81F9C4(&pÒ(* 2Ra :m2UܒTE ,I&F)%LB .PS/F  h0x:̈-\5|00:4 ^'_S,L$YXvM: s8 q3 S@,[pNIhc`f2s@!'92pY`KE$8/Ru"gL~4L_ԩӛ={/[[]ڿ<NfZnz=YFjO]޶Z-DDLT%rv "]8YK&q%r"F>a&k-fF'raL ]v(ɁFLsx"$r3y+UY  ڪ1 ktk ڶ53WM)AL`ܛhuQtsHUɩ ]ɡlŘUkJ{p|в@ܔ`$f\ݠQܝ!p۴ L" #Gw "'QYt,"S l8=;ZLw@Yȳ Aks/34L3ooMy駎6>}w/-/\yŁt쉓9Օ߫ť6VwM#y;^EM n; BH9G+ 0Uvf̻-D3UO$N8apba8ݻ )e|nqa~a0R"Iar1@,U厜{U#iک{)Zzڴ4dtlmm d2Nv:nc!̺Has73a7Nw(2XfDxOA*)1 )GWўDd,L̴-Q VԈlH 7sGDʒDJ! ҶU- 5` 0Ԍ;~ Op՝$VBLu3o]9V 53̜%: ΒLJ1AAQR&tQfSkQ UD[af:X+.;+ؽkmߞs:`r9Wd\abf$$DܚrS=ѧzδm3LFp3a6Sbm r7]D1Hq8_#F;qA7e䀈1w8+ΪM @Hq W11A-. CXUE8~M;~K'=d"BaRAFDы' t 9Yy'׍^L34L3}.=Cw١[_uS\ vvFτô11Bn*&1{ٳo}յ3j5%\A S1?X;,8$\/4S;}|7ߛd̥֬-'Q[=jHbˆ+a9@7 '#"fYIqbw0%3CQbjfj$062vMM '+(66^Œp% SxI `8wLJ Uh qZa!~9\cnlM_Z34L3rW׿W{_{-7pO?sǟzꮻ7~mػo߾'M9ޞ*Ӯݻ[7I͸hYB5f@rr`#Qg-p쓼hh:3f*}W/69]:455;W%<<}}Ů;L3~|ks>~o|\qŕW#OnSg=yiZj>4IrImUW\n̙A!1[t%MՌռE!oDH!6sfb3PƉX!; d[N`uCȊDU'CDN`yLpYrLe!pi͝9%N"!^j!?SN3UE0r '?ؼC3]}u?_~NT 8$0XNvTKdn`Hp@P`p8ȉ̳#xWș8a!SKθ$\o}q~W'i3L'sUU"’"#M'ʋH2W9PB%j r-\@'m?qܹt⤦ A_Jaaih2-Z"e(s  r6U7 1SӨvF0D b' k[G`Pcs ̔9⑂.a5'E-E;؜PyJRd!{9U7wqRܽ WCGZmb%$2#1Hti̅j]TOL/_-ۮjo63=qU%5\h8 A:G7|p^GbOQ+\{pëWSg&KֿUzl7s[\O iZ7ʹ P-oO|/XikU7]9p-ת^?mo{|_}?y8s؁Go}]FS]xG?f/J<}h87 ||7ty5\wn<7NG8yk+kssN\WG[~Osxs[l3?[w-_ۿ[п}겵﹭/8w?tG?ya2/?և'ePc?fl%Ƿ}wc~cwdr~ō>Сo\{uWVlG۶G-.KWY@׾_gdMJi!nLLcfα #*xY;>{ J`pIəH{VWڻgm}i0 1"NpJ-euJ$*e45\Kczs}ɉ$RZ2Bar G=umBQv{8Osk7eLXuHඓRFB 6`ABD'{j6W"#ig4נ縛1n;L(y tu,w9uYVL-+f$77"Rm9 ; s."Hߍ{"$xn/ v3-bhOc( ) IUu~79tUNUbzezeNnmu^끳9'H7M IDAT/L/ ?yzw'~;^U'o'zue".1+ 9.K|yohuw=ra8ճ[{CGSfI}^{pǷ'/]#pZcVƺ2_xIOicRcr'vף^pçqoSlH3锈[WpW~7}Ǥ9r}晧6;r3o_%_ʲ2'-ִx4p|)\?g?Q @#Չ$<L sCXb[a##I?PÑXJ2NU7KuO66UU$$)b"s&ɔQى% VW 9ЂnK^4%+g??v0][:upg60ѥRej䯼evE}ϑl;^UY^{=7&;/yꩋ͍W.0 ޕ޾c}}k+GojcT~+w{CL3tIF G>}>4XY^bۿ{dSv3 [,pFINtwwwv&!&2# s\׽79=f:qN$ғ_甪\ש")K,Ҕ"m\ƉK6՚͡NMޘgYXZȕZ1k̵'J_/0Նͭ[笴4 gw"wi"TjWR3WUtm E<z Ȍ~kA@L0@YH !Po' ,~uw5âBԃa9ȣjmew.@&3#30"m@N 9Em㎗:2V$1_}q):n;B<Vao}șqxLt[=G.;]?xu+|@sݸbWk_G/N3_8:3i?uW=vb83膊dG/vp}m& K'3 ɣ{O9jD|M[xt7ܲe7Ck ~wܹoyw~nf Nhc<=GX_߽{>M]Gc;sG]z獯_nxרrJݽiͭp8ʋ kO?_omkpu%IYPBp@a \ JQfG&]!dFI 0nu]/--Z]9®] Ŕ3NVPŜr);UҴx{2LZ^_pY]sG15rNOIi07Hrl 7h:RDȫ}Zڦ0LhC̀tMssF!RX-%KN4Rw3.dt;$=3G/H(m̘Jf܂j# a'.!`u3*Y|!,P#&uzgu1A@)Ӌ.^7ݿ~7~k4L:t'G_sswsڟ_6ܜL3}뗿몗d> ~O<ą ύ'cw^XZZZ^]__?p T??ydL^u7xheu-$K1-EMSʋ sg_O<|0U'$J,Fw%fsg &L~bbXKqj$½UkK{wٿk} ߟs=7XJD,R8esXZUן/9(䪇$+mLLno]8{g9qdxL&bm5ii\ ,zRea"Fix<&jkj1Hɂ%s.Z)0F vžk8#XHmU,F`'SΝ՝E\Yl#XLdyT%lPvgDdHZq/;F%7Ls01á7I]gbH~UwLE}5ϟ/ݳk7Ɵ{Qq6%]33`BM7v͵-3gNo=wNrgO^Y\|+y޻y'|_{콜^%م 7V/ INp NsuH `-Djً NaDpR&;sja0km߯T|6Âz_eJMBν4INi*`o[ik$Y-􉓇?Ϟ9szs443\R܈k$&IbJ9),nSefp+Vu/o]6@vfxg" pr'f5GT%:C'0:Ȉ/e?NJbE4:;\NIA,9/~rJ`Rwܬff Z'Y;w:ޭC( Sq{OŪffzOݗ͇sm3/w`>o'[ VW.;t-nFhfڶp8n5gϜ<};omٽ{O߯s2[篿wv VDU%ps9R8x.p_92$Bܛ[صXWu՟ϛ7Xd+^שׯ8U X$I\=$גD0BX KV[ËZ+$U=TR[Dr[ҶT\ `쀪]*&R,U]zu?쎢x86LDFpuqrc+1l"` 0KcIXʜWȈ-V7g.T%.EA v9Y 6L@. Aᮮd (3gIŔٝ<Θ[A ,]WHfif\AFNp)ڈi4Ӷ-,+N4ݻ _/}?x}?~W_}-_uՋ K)UOmU-~ӷ}_ϸ8F,-3 \q,fH cb LbT) si[3;Pwמ~qq_U9I뺪+b$ \d2ĜD&Trə]z6Oϟ95i[ xjaq{v}N@S#Xd .a݊VUιv\Mj*kJkvU 3CW$*"'(DT5dj@쪀x\ Iجkl5`fEG9*58,lfnZfF̗\EbK`,ϵ ~n_>Ybifi_(PKhEYls{^׽JF3Y15Z x<9TpǞc|zc{vẛn:t޽J[D3p_qwؓO>z|>xu+]]ko|}?Cl v\!"#`b0+t.0fq89Y^-+r7\׶L]̩PCL@Ӵ$ϧR3)qUObs9e$KA/KB`ruZۭpĩΞp⤙Rn z8l812̉3= \CTR^zU$BfM+S4Mێ̍@H+3L̦ 5eT0؄8^C0m͡e4ZWf,yeh(H'3ga8@nZJ!⠶wkhzp}' <@0"Ń%zfifiύ⯼FxID:Rd2j?ϝ=5NO),RrRJn{z{.wՍʫ-x_R-*DNDcJ$)&&Ypbv%|Ņܠ߯ j{/U ~c9zT}$$<%!>P {mHx# O6MKsE bDZhy *Oܾ@!9QUk9Y4@k}ۧvZfZc~ b$#bjYP M꺎SJMjǸu `^Rl8jpΑk=/^\.%Up2M軫**DƉ %j.Ge7<թCj ̹K2gF/~Z ԕ}7{K51PUs k6,T-T9^jJ7ѺJ1ͫtȉk 9:ࠚjWjCkpʄU% o,ܐ 6` 69@I  uf2MJ!CfrqUW}sW9*""mkS )c׵gyçӟ˯UW~gsι{駟y X-ߊ@Ba툵N N*$a̙A nR3l4 M,220mǀbswӮon.1 K)bimvl;K!j)ļƩ{Gwwn5,aI"B ($!tiC07!9\ʤh &$B$d _~V,T vGb0q`f17CR9_-OZJDuTC`YP'CsPٷ;@VJ\(5aja2a\p䜉.uǖ3Is1ؐ 6` 6`cمBCyۮc 1Fw1ַ>S{]{])LT&,"Bn6>i>?t;m>~}w?\vٷ9gzm0\s:D]u+efdn$; &̻k.5!$ 1]-XXZEBˡZHmqr8b հcZ ɒs!AN^xggԱn/m&jgjL5ʝ8Ӫ 'R%5DSJMӴ]JY)e`nǚ%1USLj^-SnGvCk.ò*6i1bY{d%Z(:#d]A\(DS \"LDB^0G3E͠[ݠbfV>aa^@S !pPw2lff^O@F aqr"S(u5V;)W08܌7 6` 6 W\@E]""I]t}?ھm4 16"S"$Ϸbjb-a aTTJ1[]16yaκYĤ_63TVfpr{ 5@58sV=ou]3&v!Fgs,HbҢwCd&@W &uGXOy 4lmbobg؇id!&L2N#JuQM#1McQ- rw 2[mq5>kQl\2M}3 NN˪jZJq3S2dw55SfQs{!93"_ՌDX=dA$΂fJ&"KQ&Db^!!{bfUEp=V_.hE@iP5[l7k UlɄCmJ)vof[{{[]w]bӵiڶMQKMvyw_CXwfh&qt lv!< Ũ@pquT%#  0(MMݬY7oSLa !1` 6>("DI)q!!H` f  5l>bոZ,w0 ִ}EwC.M)bP-EkA iU !1r14Mۥf޶6Zt\2di,'6{4Lc (Œ)jd+P5[fJe]j  IDATj)XșjYK105pAN5lp6o13!R5^g({)I31+Nv)D2džnlw/e2J/J$>jK'VomovuyH \,C(tmTɫj8Mlf}uMLSaow/^nmם6@C>9 2@R섵SQDfmu]4})DAD$2!rTW'+b9-W,%ZSBVh,MLiKѹ$gW_M{kWj pfD5C 5V$f659%{S7is EUE283㸚TlȺXj*@rNu" ̀xखBk;\Q%Zi܅ٰΏ ݯ [׶ p7V&ffwkͥsu"NKc` 05S0YDBV7ll|3RUX SwVq\9|{>;ao7n6^IٴmɹiI$RٵqeID)ٔ.jH16]8%ՁˮpP UbfpDy7kSC AS$)%"`qS"bbq 'w1ƮmRJBS5Sr4RnV;;Gvr\#PJJD.!1 Z#j΃Dʓi.؈V+^1S-MKu730'Ue 0GCU*UMf3!qbbL$LRH3Wu;jZ\q±,"i JᬆDAr#"u€3) dXh*a580AYF`C^7` 6fC5ͨ.?(]i;jnom5?:I8c mij @KvaXin65i&@`Q-Nn0YM{pqf9Q]l6κvֵ[[}JM&cb sb2/IH$҈[ Bja }6mbD4MCж hX,Wjڙe-Q=rtw0DD8J!W^i YQ0swsӔs.ӰVôBb.!4x$Ik5B`1vmGd2GW-jDe͝$Di11u1D]QjiܽfA) L XԝKD0⚝ŕp 怹3 d֗ @6`Ό֤r887}:Դݍِ 6` ǥo=w8 oon I7}ղ*{kڧ8jVl iN?YRL̈)Num7 +SU /;GWC)wuS$"q#Bd y ]jvַ];l+H`vWBp fYhZ2/Da|X.JV0E35'Hsqo1Cj2k)09`15,)k5!9̜4(;ڂ [)E-PTxV,g!JB 6by03#"uJɑ8PaZScܫoyqcbQwsBDf2 Z` , f&g ;,TٕAmY-$ @Ts ] Nvv*!ImN]7kBl 6` n"Cxqs>i7\ ֘^y-p̤ZqV~Lif[[C}u}!@XlaDiF`eT-}ߵLX4泾MuoD®JN%23K96)YhN}E!3s LctUu%g73Ӥާm 45 `jucΫa ,zא(wS$HCDbS[vZ&""O-'9Y.E  @DܬEUUkjdDNFL3gJ:@"0w0xpxMuLݝ%bԀw%m(̕I܅*yp!Z ȸ&r9ymc`SaaKoΆnlC{=9rS↿;{{?353*+;g 䵹2Ss{y&r?2OͶo.ƖEia#TKӴZi)9Ocg}/!0S$bG'۟0o[]H,. K} S?K8õdf!f7S7+Sv8e.jHfwj 'dCl=jmhpju/\Bb9* `WSf3x^{LZ-6q1HbalZaVDCh%/qy*9b:z*@HQQʰZrXb\-ˬY$qhDS5)f 1{1IBjBpr7wL4MDo6ƤN&i!RÊ2wG `\ YZ\2(5\Cp&{9P{PmjDp-"jU/D8]h]":Hn2IRƦm^B\)'jܪcA!aXHARFaC^7` 6~\WaX >,3ܕWv}wɧ܌c*7:ksKǔqNn7Bl /%0Vۇvr0i*Z7 2q׫vX䎷>K,D5$&0 ZF7_bl!)F>CLc@B1{L)pe4q,4,aƼ\8LejU5"Դj*,Y K$A5"788$IT׻b9% ")5AbLD]qs.) J9SWR h)ȹ{Mp f*C z&/JDdlR7fAOed L8˜EgXq,ڀTUDCvJ]JS!:Cq::r7ze1V27mK؉XnW@^ %/~b?1p񴧾u|O_q'm|SgB}_69:)'̯9cpT^я|6/z{N=?߰׃ď6?bҁuSSji5TGJѩL:Vբﶚnu ~KZ2Q8}߷mRJ"Z2*gRfG!b^j1IvR7c2XR,nCRԽr4/XJr`Rl*VR0lZU}j.j1DAZJc &0af lUD9f'Ny\:AK(ȦL(eH52Wq ZF%a8$ר䜉sZ66uf&'f $"iof`fmfn*UD wMChSJMnmmO a @"ps27<{h133n5.كY݉=Jүg<q?z.93~'vucN߾/~cC˺9O~CJ` 6fwn|ه97_GK۶?|߰ecpYVgȬY|$مE8hlonvqt}J)T!0qsKJah|>g>4g]VZf`)pA86$!y"r&LMj4sq,㰜S3ߚo{eZ0\ugs:L:R@Cs`H f!$UeZSe]I"8%+3&)P45\b\bKmѢ kQfNAfnFp-[-0VR-^uPSFPA&WU.]'-GY̺|nqZ ]RܙP&rp2 (fJ,PU" Q<֫׬zȂ+&IJ4@8n{“[3|SVk_/8y׻ꫯp-NO_qx~c]6ٿ| ll 'nuOէ|c}|c0OɹxMg?7hkk?e;|kgtI;;OSVO{3>c]_# ?Sy+AG=q}_{ӟqo/~[.w㯇aWO;?/UW]/xϻg>}f~ⓟ{_K^|)y+OVw=dgk'% Dq'sE*S1W\U7-iގcMӻ[׵"b3M8NPˋeyj۶g)\ bńy"⾾ON|(d5XܕCa3va13M ,8) wcʁ|rI L8]sճN>#q)2jSTBvsu5K B,RY!s))j>jR<!jYErTո(C&f8\sɥ1RJf19̍kԹI)n`5V4@U݈Kz^.ݔ]=Soq̮27o1&vZԜ,S+DR40v0H¦qm F :܈cJIFK)DG>7s?}E>~ .|kӟ/{M; 6`o|rY.\'=3{ _yt].>w問=9w=Q|oy[/kG٥ySދC;[~ן/*x1_?=)~[7W=w~߭\ܼAM`@ ;f& RE\-SjR@(ŚvƜ aȋr S ! .5b LTTAIrVEK1@N^'75ÅY(vQbIBۙ',4` } 2ܠnfZMRJ1i-{U;1 j73 F϶zj!)ͤR@)DBtrUJaI)#&va͈ ŲR&s.5+&0 A FUpO0҈ݱumA~HӶ^{.7R>?Ml7}pYgLww̼}oy~*|c/ko{;oy[wOx;ȑ~g^o~4w"wvtl .#_]ݾ{~Ϳ+~Uo_ I_n T5NFL^; Lljk?X"b `Vud[WӸw[M]!DQ8`92yrؚϺoNUK)Fpħ'{'Bqd BPb̜Rl!&Ѭ0ǐxu)j5Y)EqьƱ_v20,_XD8:HXbn4hvf5<``c 1cTބ͜h9%kes/Eݕk 1`kuZUs3w.A1+'ܡĤfXbJmJluBL1=!Ȓ}}U]e̖KhDDDܜAfe $1%\p ,qm T5^DX<|=df/Y п?ӿKF6` AJިX#ߐ\1?wqюRfFUc;>5ZW:9g3SDȇk_'3?G^/yfF2U"r׆ s5\sJT֮j9\* cncr9m;W~ b16!H!i,潽an64h)Ŋ SQ_/ӷ[#DȡMRr BTr$z66g h,í(8DbpW5jDDZ@h 4e n"`!" ꉢ`ShB)2EROMMւ-@6WКOek&3ס pGy`ش֡u"R_iVjU xj$!P Fp$Qה@$,\I]̜"bb^,WC) &CgZ;9)[f'"v1Ӎ)u{k/|;[~ݎ<7^)x{޽X,W%K^G~M> 6`o|>=ѿ.\w>Qԧsn?|yO=_}[.]{_]/}.|[zǯXm*ݏg~{^HOyw=o=מ:|i*~Q+ X7ZS:(b"c+@M@",/8A%CPSS0%rwSeF˪9 mݴ1E(Yrl9rYw1F(%gd~˹j,ŦignͶSیyffc)QxE}Gk:ԉڴ\PLsɦǢZT\t`0(;ݕ9ĘbL"Lj"s 1S1QJM",OKgwX"!iD"bc9$R3elN9jqop3c%C'4oئ1ʼn=+\? IDAT)Ƣ5wc APT4;{q%HRzNJYĵ  ,4׋yc) " |W.1m׵9Ef$kO~y_ַw_>?|+/߲'>3ؐ 6<|__ID>/{؏0C}gy3Ͼmny[_sSo;xo)sJKK?>n?Gyڳ{-x_g=}Xy%/{i'=:sw7mADdP8\d8f:100P] "bjVtҁU&W6--_Q8r0ꔳ\}ӴAK Ɯ?髒ċ펧61.^{Ųj:'j)8DxT8NQ8 Q)e5Ţig?+-9bNdf@5 bTXDIjܙCxԌm '&&ض]J:]Z\vL]͈I (]Sd1U b3C"&9!N>[E3w'PF_m|RdLIjibJD"Z2q 3/Π:xUe撋ªYrɕ{5ͥLhjp mprRuƤB~'xglxO~X,=x۟s'>u rX o׽^U c5Nc/翋?OaOhv6q!_4V툜ICƘ7cCjhY iiX&CJmu1c((ElǢ%HY/Ͼ煷=|VBQbui݄PIb /4MP4NeZ-WiaX 8 8.X Q$b@RKC^S3\̀0WP"b! mӇbhcJ1wSaX]wd)`e2; jD0G3c3Xm[Wcݝ'paI58S̬m:ìE R"B$&Umvʓp&ba+"dpϹTO#b*_,.+9bꌬzfEN:>W", swdq7 [l\c;zg{WT¼}0:t虿]W*mڕ^TYD恃Vl9f IEb"bhnmfm?7bw\ "PWw.yZ.L;B.1ౖ`-Q9gS+ mr V.?7r/I11D|r\PK)Y P3ͫžlj Z82Vaj&R՞  ",,k.j..Z%5w@l$nbg5= p@ 9%" 昦Ij:.Wuj!P)\M*Ub?:Lb})m;Q@Rʤ%bt g2…DdFLDZ5W)05"r&G+ՆP#geDZ~ 3b s` 67^xxG^G^|YG r ֱY[{:"j0IG8!0ǐN??4m:y6?a?h4 3o̜P !S!bf,}/8<@UB"SM>=ø4c<TrΥh$ADLy0͵;jj5L8L0M8ib),, RRJFDTªlY')QJ $AB 'Z鿱w1]{g&IԒD!$D"E"ho(EWJ[kvؕ==K d1F6Id$#+/s>sI3g=GG,NR*5jV:Y +։:H$u:t,C,+&`Hd8#aP32$yVx8R`@UjVQɭm%lq_5+fXVCb 2,s3!<OX\Zx'Z<1Zq䋗Ϧ^&y^2z.H^XOڎf4r%WoT \qdayEO5QV8" 2!""qX'"Äqm3t<i:"R OGn \[6+၆'}KtӺ&➺u')8ODϨ=F Oo_1#*I;O *fx"Օ+x9(_q&+ $`2@ &+*O(:qԈiQz^rJu><xNUy}miQS^Kw((^%vS!*$z:{ªчnчTK8@\(Яu]^^V5_.6;[cG{Bnx䰟[s"zsĨ+/=|<l76_[A̻wf}>=jv377/)~[Бoq5$䵽}{֭Y=rԘ$†DR<,qmz+HNhYさi׆AD={=sTfj?ԩs+#K=ء yʹ+Wd zF*k󾝛vJJ r<"-vM>}:!>Nxy)" tرk҈(jk*BZ__~jz("b:xlD,}} {L4nuo|"{.S?meR?wn%y%ה7_ڦ{^͛5>Fy`JbLJ\rEQQ1<8qSq!aDqv98'Dmn ۵kwG''iÖZ{65Tj쵳kjwLx]p)bl!?9cq,-{pS.I>eiin֧B5aG%3g5ꉌF?/7fܸYS?pӖj%x5vu;~W[[["gB]:wv%M}zv ]8;}#qa!A~!]:طW(>X>PZzAύzA~C{䉩ssM~\}DxנϞEn!F8͙3O۷ qz =}BM:ڷײ 7`tx5SW~MG,,NFF:vV3>{1=wݶuPݻ }mÇpԛu >lH%`$5z̙VZY[g1ab5_zո1Ș>urcM6]fVVɓvEutrʸ};{䔂ǎھ37qa/`hX?~)/7oӆ׆qQ/"C\\ #_"HH,9q.l r 2{.Yѻ/|o^N⑄/f8ZaX|XҢn>T{޹ca\̯eK/7vޟ*77'k?@XS7n;F:|,7'{/=ro-,6<Ү_/aS?<'U#_2̽>>]NNNN>AAN΋,>-Yf8O:~KH^[G5'7G6Ç&%  jҴ)=fD譱-)gtۛX-Wo0RĊ""};vBÇ"jנP:jSaOxRޫߝK9{8!nֿO?u^"j56|R./dWd&TވH"KJJ|uࠨkU,;99ϧO>uJ`^e|ҥKyy/$†DR qmzmX-Y?.2_jii qOumxO{Mls򥼼\KKV=ן._J8hC}(33wߚ5Ⱦ2 +E K, q8p؀OBz>yìBI^nsDf.~="}=[Rq%5<2l_7CtN"O.,qZMD4nFHKA>mP'//oP쯾gБ~}of<Ѳ_V87z/f BBä7nɨk7ϥ/><`rw z?,wrvv͟k`_s3g|0Z=fہJP0koٗ"UeZS;Ho-;E"3};-4ɤT3 ;/<)"ߙ:%J*"wZ335Ɛx95OtBg !"++J/s+s4y%@։ɩE=.^Q\ң.@kW0H^d yLW0wiW?D=M^S#_%F@}a`2i+CWt!$`b%Pq;j~ܯh$a{ϿYR/^^>dիVT8RX0[m;+YG/3glάL[2xc05v=/l'uGD:.)HpH(޳L*-I?'Z=iҤ&M4nxرϟ0LBBҥKmڴ rJ-ZZZ;}m}uZʨ{*slſ}u\';߸":?τ3VVnn͉oDZ"-6z{pwg}^/R eKzyzlۺƣ-aəW\Ș5kܹsЗ >|ĉ.\0aȑ#pDZTk&NDW^^.ѤZO|=Vҥ}{ eYf읷޵oݽk>| Gz_ǰÆTNg|)ȱ&M._Y3r 23+G,l5zׇJryRz|ׯ+[n+W߿|ڵ:dgg,qݹs6mZ#UC*p뻿=ۻş.jg%`葾>|FVVV^=vEutrʸ};{䔢"EBJbCtlxNN--Yѣsk׭]a[ZZ 1hG$>cA~A_;{{sWPommc{Q}XfkCʋ$qskf_)!枟dxgW*EFy`+8$pBLfE$5o"⅄VKJ<ԤiS"9zY3lmذ7'''GV#f"|r .\{n Yf 8Ν;h nM,KD,6iƍj.6;[cG ,RRJzx$H"KJJ|u Ö֮VXDD>~\BDAA1,X}ffaC")7!bE1r٬Y˗/=zG?x`ll ƒ SU\?$}shTs\^;vEVH9st@)MjJ:rb㭭mDԴYbcbcbeⱓ2t;eq,ńˋebE ;_Ϯ]Y][Wj];GD{ܼrcV1"vܹygϞzj]]]҆e[n Opw-WWp=7hi S 柮~׮}7VvM>}ZMDO"2 ׭%Ǐ&6,nV<5]Hܧo~P*ݿWf;ezgNͥ^Iv :~صkiDnGVv`WyN~wqnԈ:tsAKT{q9sjW7&M|{㻇YXZ;ck׮qƥ^~M6}.6;[cG r ˤ#]5"#F~' {}|rrrjb:u^צ׎]U=Pjn.lX؋58S vL+(($oz&Mv^in^ Yz7{h1沊j(kZz ҄ЃKT6 zhCԺN~~Bav2e 3f~5cW57muE \! |j; yCvմ~gRC_N1z|BUP\. cBy4ZmmP}M^ȸ'YYʈavRvmҨh%/GDM6#&oS=,dR}aAyE<ݥX,Dk3F5"yc_2ڧ{^X`ɢDqRPer*u@+Y= G}?.]?޳L*-f%H#yA6lhnnT*ҥKmڴ rPBC... /a~GaWfZhѸqQF)jD?2W"Zh uJ^3oٌay*o{su:OnF=N߈pJeXҥ}{K/**~BbȞݳzߞZe4lc~A͉h'Np„ F)T. ۫Vر~?sk׮;wnƍՈVkSgޟ8Yj`T6 J>'.wOQ5 ,RHU% -X}]YYYS'O)'Sr }pt<չѻOD>Dӏ˥RiXlJx_r寿JD׮]KKK>|8 >߿uF)]شi7nժUW\j%*jFX?.ίηg@K^-eF܅G 5/=߀E2mwzi[fqُ;Jxi!hSO%WDD޽ϕ{H$lJbbb8ѣ7mڔeY"bYI&7nj K'{^dI^^ުUƌsa߿O>RLW*5E' lj՘26mv.Bf͒z֗Nr޳g|2m666iJVX1n8'Ńްa͛;f^^^ bȐ!K,2eJUx%9EJ^ w}򾾼WݹnMlph)NL  %ӧNu0JDwۿGxmw;cFmJ}3[۷_pAxr-X8֭[ta7.44Gd~_H^C*_y`TJ^juARn>{cV/9zuh861*ܼ38::۰i [{z^faJ5z8}JDK^^/^~=[VyQQQ͚5^6o޼yׯ1bDTTT֭e֦M:88̽f߾}nnneƼIc֮;/D&&dr 2< (5:G/7q6 [?:tŋcǎζ[zuV+4p ّ#GL0A*J$B7lذJߙdт/п<)Ӟ+X*tDonc6/(:rwf'Oe*^imiQJ߮f?~DѣG+Sh(++DڵkU =&O8nْED4iʴ _VDJRTq-ƎyRJ$Vr"/Tk͛8Wϵ'O",)صVחLR>}(+#&DdgmeƲH*(RQ&2s?Vo?&YNO#22nJD X˜^],8/Xhq7yP!y2tLvvvrwJ6m֭[oܸP=˖,ZBa{ɢ:4eZ]H^O6gؘo-Ҽfu<?q' y0l֭۠U֧</%$s*J*zr K +Qdee}ɴ[/_üoz JܸDrm\jH^bGV[v,0pp_d[TSW @uvOkڎ4̹q;2+W׶W^m*"<`ffb#YuDNCx ycj;%{XmPefVȾ#VI&m۶-33srƍՈA跳e˖-[91\NqfQ{;;, & +ɰ畈9N'l`Br<_P*Dd!3ˤ,Pz̫U&ĸÜdR3+K=SծX$^JFL^߾T{XȞL^P<{f^Akc2rwi,$f "ke5Ɉ6v|o})˲ ^n>w&[EU 18c%Y9J:} Ar@o#g=#z5{Kv#oYKђ ~oʚ:yҮ轎NNow="[{q`tBrO&@bR V"eM[<۴U*Gӏߟ0v"#跣֮VXTf|\lvƎ^Z-222<c%JHi)/BZ=(vDP|1{}o| K}b úXA5/ fxu=<'䱤3={lذT*D p}3M4xo3/77pBHHȭ[bT*U( ȑ#^^^=p񢋫[\Sj,Zv͟ B*=ٿ=|PH,V{c%^]Ƅϟ|y2?ꥥg`fV1cW3gOw%ɟkח>а~pHUz#q\FGDD8;;d2D"te8?{&977wԨQNNN2?,,,),,f1_p!9rҥg$u'mJ+W;w.22G$ qej|:v4x{ s) ޽R*HjnCumݯ#zGwڵxM}5|PUeTTYIDAT쬭lX)UEJ"jYf./7o޼aeeŲ0wҝ;w>|Ve2,kfffoo +]hݻ;v>}zҤI>>>i3778 Zmnn.mllӴiӼ+yk@˫rÊw1ny,+jU_otzzZI٠}OX (W0)[4v*&˲}5j W͐аMZlYTT00`@o0LzzU*L&S|=,9.i{-8-wIJѷc^W͝}C׵([mG`o`D;w޽7j4;}Nh 7nܘ޻VU|w-,,f'?Ju1R0eAA(˲Æ ʲ({6F"\JK[X%$$X[[^Liva_vv]a@j@PhڕKGy{רQ#a~+9--ͫO@P(m6woss/jZ{{{Ju]77>}4lP8iJJJVk⪼$Dm s\3k\CD66LWZj跓5k,kkF,{ݜssuy2ɫ1P%>%<ŲlJJJ~~ZJIIwph *IXС[H^H^jzjsɌ7ܾID4i9Ȼo.Zid2y``"R(e[\|)>>^X۴l+H^jM'8xfߦ!L.k,'}@ P "D'${pƱ)ct1kԎ@։ɩ;E P y5H @ &+ $`2@ &jSeUo8QTɍ̜eE µۙpm\jH^7c<<&+ $`2@ &+ $`2xHAbr*'SڎWe"l`zjY~/m!xjd7ڎE%O%/N)t:% @ &+ $`2ɨrҸ] /WJ? <=|<;kn~+w6܅ׯZvם|ulֻm1#_z,?,Ylg%KJЮMmCtޱ*%,>*YmS@}VW{{a;jo'3 m޺=V<{B\&5'y{ƞ:{sIxQ cpwoQ^q7J}w߾ufBұSgbN &yꚵ1jMN!~'[(tkd[8TVB6~[vhءͧS'U2e/_C:[@?P%c.^݂:v3hC֭^|hg˫_MT15dxK[02oej/-W'y1r1-Nm٪b~-,,oyիWٽ_oРA_WLplb ߶xCοwv)"ە˗j[6m-t WT嵼q}Wa/ZKK$֞mf|C9wӳ{WٳtKPO]f)**~BRLׯ]3k6;tz;+sMwU6mO<}!yUe/+V&P ovV9g 6ϕ+(>.6<,$(/KѢ>tpG]M!+Ǵ&ɓ'dN$S>\rE;U6:|@jCecBґeWfS oIyCAջWҋ|I^{ukY}{?:<ڷmձ}["J9{UVVVe6h~_۵tޫD۰I=cG-I񹓑1a6n>rcƍEDw22OcWCq2OW۷?t=caaQ3gZjecc/8ϙ||:?7o'efΚ=G$+z82-3ptTL|[I5'\ިq"D|;wӲºzڱM(qkdhޜw _O"6Zʗ.,iNGuZmaLCǍP{݃zwJ<:͡1Raݺ xDJjE[d[v7mywNq6m{EEo ufVKD[6mO.r)abQ\!?q]úD~ٻύkiW\vmްn#)~}gp%Tֽෟl7NZ* 咅 3J*TͥD%nIbyK֨^] {g*uTz}{w{@[]o–X,[l׶ II]Dvv ~ߟB;=۴5lAO\ٷƌR(}-Xؘ8 Q^D⚛V:wnMD,Z[۳_fQӦ|ä#AM6%̞5Jx$KsFD4|/>NID~IITNå/ϧO>uJ`^U }z%اCC5vs.ۣ^`gi~Y^?ɭCD+~X}Z"͂9O˖gyp^y{[;Dbq;OsOƨ53.@Be"##qُ[Ua!hf#Zy ,Rq'##6̯^pao*#tjofflް/gw/]ޮ3?ۻӰ4/ TM6AQ (T#Zkt*#R eRTptP RW# I!{r{QUS U֎쩍o 642YHײSUSc3cm(!G^AqYX * Hm]]<MmTӐ}{ .n1Q{JXcgc@D{;UU;^jvˋ cOXEK]q떣$;EDw* ̧[ Do`2"8`*{َ䡄D'1c!I԰\?{=7&%4mldA_FB׊rWɄG89/l3POA;vKRo/'=ڰ%mzMXBc%ğfWp:&E4׭6oD|xJ<ұCEUeddqyeD+8㦶6ӟc']V|jtv7&(3_L<ߵUEQܯۃR/?}LYY?yW(y}!y Iotߖ~㵴V&I{Y&K y[o׬m޽5xW~&9ؑ_̝{|lwMݼ@{oGzV/Y5uٝeݿ` +t9Bt:Lo\Ǡz5Z=ϛBmFfW%o"d =?f 7cPƴ4AJ%ou=Eb€qzn1'H?yŧmwg   U}wWH^@j yU{Ar-@O b$Em`</jkk WVV&ԺG+{1* {^dxXԈ(';ˊm3NSz/TTT]DEz/_z3 kiW_,tm^222}ܪ' g Nݹ=h'yVC#c37'$+) Rґb zVY3j$<̌[f&DT}2%{ϛOD<^gs ,c顃!Dd˱+.*HOcVAM]]Ii81\nnc#_'F#Fزiǫ>靾@w\II&5kוz|„aLJDq1lkk~}^|#WUU ܶbiȾ=Dd?sȑ#bRysXjhwoܸ~k|dee8Rg@M *{,l,ܺycAAaKR-LxT+Xޙgk&NܿwIKK ]L ;_y_&eY6 !it C}tEw2hCNOr-b}ţۄyqvı k9copy"> ]> The &kmyapplication; Handbook Jean-Michel Petit k9copy@free.fr 2009 Jean-Michel Petit &FDLNotice; 2009-02-19 2.2.0 &kmyapplication; is a dvd backup and authoring tool KDE kdeutils Kapp dvd nothing else Introduction &kmyapplication; is a program that lets you do backup of video DVD. You can select the titles, audio streams and subtitles you want to keep on your backup. &kmyapplication; is also able to preserve the originals menu of the DVD and shrink a 9Gb DVD to make it fit on a 4,7Gb DVD. &kmyapplication; can be used to rip you DVD into all formats supported by MEncoder and ffmpeg. It supports the creation of Matroska video files with multiple audio streams, subtitles and chapters. Using &kmyapplication; Here's a screenshot of &kmyapplication; Screenshot More &kmyapplication; features k9copy includes a wizard which helps making dvd backup easier The wizard Assistant presents a series of pages that makes it easy to copy dvd: Selection of the source of the backup Choice of destination and type of backup Selection of titles Selection of audio tracks and subtitles Options related to the type of copy Credits and License &kmyapplication; Program copyright 2009 Jean-Michel Petit k9copy@free.fr &underFDL; &underGPL; &underBSDLicense; &underArtisticLicense; &underX11License; Installation How to obtain &kmyapplication; You can obtain the latest sources of the packages on the &kmyapplication; web site Requirements In order to successfully use &kmyapplication;, you need the following programs to be installed: dvd re-authoring : dvdauthor dvd burning : wodim and genisoimage mp4, mkv encoding : mencoder and ffmpeg dvd authoring : dvdauthor, mjpegtools &documentation.index; k9copy/doc/CMakeFiles/0000775000175000017550000000000012412271774015264 5ustar emulatoremulatork9copy/doc/CMakeFiles/doc-handbook.dir/0000775000175000017550000000000012412271774020371 5ustar emulatoremulatork9copy/doc/CMakeFiles/doc-handbook.dir/DependInfo.cmake0000664000175000017550000000125512412271774023411 0ustar emulatoremulator# The set of languages for which implicit dependencies are needed: SET(CMAKE_DEPENDS_LANGUAGES ) # The set of files for implicit dependencies of each language: # Preprocessor definitions for this target. SET(CMAKE_TARGET_DEFINITIONS "_BSD_SOURCE" "_DEFAULT_SOURCE" "__STDC_CONSTANT_MACROS" "__STDC_LIMIT_MACROS" ) # Targets to which this target links. SET(CMAKE_TARGET_LINKED_INFO_FILES ) # The include file search paths: SET(CMAKE_C_TARGET_INCLUDE_PATH "doc" ) SET(CMAKE_CXX_TARGET_INCLUDE_PATH ${CMAKE_C_TARGET_INCLUDE_PATH}) SET(CMAKE_Fortran_TARGET_INCLUDE_PATH ${CMAKE_C_TARGET_INCLUDE_PATH}) SET(CMAKE_ASM_TARGET_INCLUDE_PATH ${CMAKE_C_TARGET_INCLUDE_PATH}) k9copy/doc/CMakeFiles/doc-handbook.dir/progress.make0000664000175000017550000000002512412271774023071 0ustar emulatoremulatorCMAKE_PROGRESS_1 = k9copy/doc/CMakeFiles/doc-handbook.dir/depend.internal0000664000175000017550000000014312412271774023364 0ustar emulatoremulator# CMAKE generated file: DO NOT EDIT! # Generated by "Unix Makefiles" Generator, CMake Version 2.8 k9copy/doc/CMakeFiles/doc-handbook.dir/depend.make0000664000175000017550000000014312412271774022465 0ustar emulatoremulator# CMAKE generated file: DO NOT EDIT! # Generated by "Unix Makefiles" Generator, CMake Version 2.8 k9copy/doc/CMakeFiles/doc-handbook.dir/cmake_clean.cmake0000664000175000017550000000034512412271774023617 0ustar emulatoremulatorFILE(REMOVE_RECURSE "CMakeFiles/doc-handbook" "index.cache.bz2" ) # Per-language clean rules from dependency scanning. FOREACH(lang) INCLUDE(CMakeFiles/doc-handbook.dir/cmake_clean_${lang}.cmake OPTIONAL) ENDFOREACH(lang) k9copy/doc/CMakeFiles/doc-handbook.dir/build.make0000664000175000017550000000575212412271774022340 0ustar emulatoremulator# CMAKE generated file: DO NOT EDIT! # Generated by "Unix Makefiles" Generator, CMake Version 2.8 #============================================================================= # Special targets provided by cmake. # Disable implicit rules so canonical targets will work. .SUFFIXES: # Remove some rules from gmake that .SUFFIXES does not remove. SUFFIXES = .SUFFIXES: .hpux_make_needs_suffix_list # Suppress display of executed commands. $(VERBOSE).SILENT: # A target that is always out of date. cmake_force: .PHONY : cmake_force #============================================================================= # Set environment variables for the build. # The shell in which to execute make rules. SHELL = /bin/sh # The CMake executable. CMAKE_COMMAND = /usr/bin/cmake # The command to remove a file. RM = /usr/bin/cmake -E remove -f # Escaping for special characters. EQUALS = = # The program to use to edit the cache. CMAKE_EDIT_COMMAND = /usr/bin/ccmake # The top-level source directory on which CMake was run. CMAKE_SOURCE_DIR = /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 # The top-level build directory on which CMake was run. CMAKE_BINARY_DIR = /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 # Utility rule file for doc-handbook. # Include the progress variables for this target. include doc/CMakeFiles/doc-handbook.dir/progress.make doc/CMakeFiles/doc-handbook: doc/index.cache.bz2 doc/index.cache.bz2: doc/index.docbook doc/index.cache.bz2: /usr/share/kde4/apps/ksgmltools2/customization/kde-chunk.xsl $(CMAKE_COMMAND) -E cmake_progress_report /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CMakeFiles $(CMAKE_PROGRESS_1) @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --blue --bold "Generating index.cache.bz2" cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/doc && /usr/bin/meinproc4 --check --cache /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/doc/index.cache.bz2 /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/doc/index.docbook doc-handbook: doc/CMakeFiles/doc-handbook doc-handbook: doc/index.cache.bz2 doc-handbook: doc/CMakeFiles/doc-handbook.dir/build.make .PHONY : doc-handbook # Rule to build all files generated by this target. doc/CMakeFiles/doc-handbook.dir/build: doc-handbook .PHONY : doc/CMakeFiles/doc-handbook.dir/build doc/CMakeFiles/doc-handbook.dir/clean: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/doc && $(CMAKE_COMMAND) -P CMakeFiles/doc-handbook.dir/cmake_clean.cmake .PHONY : doc/CMakeFiles/doc-handbook.dir/clean doc/CMakeFiles/doc-handbook.dir/depend: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/doc /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/doc /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/doc/CMakeFiles/doc-handbook.dir/DependInfo.cmake --color=$(COLOR) .PHONY : doc/CMakeFiles/doc-handbook.dir/depend k9copy/doc/CMakeFiles/progress.marks0000664000175000017550000000000212412271774020157 0ustar emulatoremulator0 k9copy/doc/CMakeFiles/-home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2.dir/0000775000175000017550000000000012412271774032344 5ustar emulatoremulator././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootk9copy/doc/CMakeFiles/-home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2.dir/DependInfo.cmakek9copy/doc/CMakeFiles/-home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2.dir/Dep0000664000175000017550000000135212412271774033000 0ustar emulatoremulator# The set of languages for which implicit dependencies are needed: SET(CMAKE_DEPENDS_LANGUAGES ) # The set of files for implicit dependencies of each language: # Preprocessor definitions for this target. SET(CMAKE_TARGET_DEFINITIONS "QT_DISABLE_DEPRECATED_BEFORE=0" "_GNU_SOURCE" "_LARGEFILE64_SOURCE" "_XOPEN_SOURCE=500" "__STDC_CONSTANT_MACROS" "__STDC_LIMIT_MACROS" ) # Targets to which this target links. SET(CMAKE_TARGET_LINKED_INFO_FILES ) # The include file search paths: SET(CMAKE_C_TARGET_INCLUDE_PATH "doc" ) SET(CMAKE_CXX_TARGET_INCLUDE_PATH ${CMAKE_C_TARGET_INCLUDE_PATH}) SET(CMAKE_Fortran_TARGET_INCLUDE_PATH ${CMAKE_C_TARGET_INCLUDE_PATH}) SET(CMAKE_ASM_TARGET_INCLUDE_PATH ${CMAKE_C_TARGET_INCLUDE_PATH}) ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootk9copy/doc/CMakeFiles/-home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2.dir/progress.makek9copy/doc/CMakeFiles/-home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2.dir/pro0000664000175000017550000000002512412271774033064 0ustar emulatoremulatorCMAKE_PROGRESS_1 = ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootk9copy/doc/CMakeFiles/-home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2.dir/depend.internalk9copy/doc/CMakeFiles/-home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2.dir/dep0000664000175000017550000000014312412271774033035 0ustar emulatoremulator# CMAKE generated file: DO NOT EDIT! # Generated by "Unix Makefiles" Generator, CMake Version 2.8 ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootk9copy/doc/CMakeFiles/-home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2.dir/depend.makek9copy/doc/CMakeFiles/-home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2.dir/dep0000664000175000017550000000014312412271774033035 0ustar emulatoremulator# CMAKE generated file: DO NOT EDIT! # Generated by "Unix Makefiles" Generator, CMake Version 2.8 ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootk9copy/doc/CMakeFiles/-home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2.dir/cmake_clean.cmakek9copy/doc/CMakeFiles/-home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2.dir/cma0000664000175000017550000000053112412271774033026 0ustar emulatoremulatorFILE(REMOVE_RECURSE "CMakeFiles/-home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2" "index.cache.bz2" ) # Per-language clean rules from dependency scanning. FOREACH(lang) INCLUDE(CMakeFiles/-home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2.dir/cmake_clean_${lang}.cmake OPTIONAL) ENDFOREACH(lang) ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootk9copy/doc/CMakeFiles/-home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2.dir/build.makek9copy/doc/CMakeFiles/-home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2.dir/bui0000664000175000017550000000770212412271774033054 0ustar emulatoremulator# CMAKE generated file: DO NOT EDIT! # Generated by "Unix Makefiles" Generator, CMake Version 2.8 #============================================================================= # Special targets provided by cmake. # Disable implicit rules so canonical targets will work. .SUFFIXES: # Remove some rules from gmake that .SUFFIXES does not remove. SUFFIXES = .SUFFIXES: .hpux_make_needs_suffix_list # Suppress display of executed commands. $(VERBOSE).SILENT: # A target that is always out of date. cmake_force: .PHONY : cmake_force #============================================================================= # Set environment variables for the build. # The shell in which to execute make rules. SHELL = /bin/sh # The CMake executable. CMAKE_COMMAND = /usr/bin/cmake # The command to remove a file. RM = /usr/bin/cmake -E remove -f # Escaping for special characters. EQUALS = = # The program to use to edit the cache. CMAKE_EDIT_COMMAND = /usr/bin/ccmake # The top-level source directory on which CMake was run. CMAKE_SOURCE_DIR = /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 # The top-level build directory on which CMake was run. CMAKE_BINARY_DIR = /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 # Utility rule file for -home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2. # Include the progress variables for this target. include doc/CMakeFiles/-home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2.dir/progress.make doc/CMakeFiles/-home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2: doc/index.cache.bz2 doc/index.cache.bz2: doc/./index.docbook doc/index.cache.bz2: /usr/share/kf5/kdoctools/customization/kde-chunk.xsl $(CMAKE_COMMAND) -E cmake_progress_report /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CMakeFiles $(CMAKE_PROGRESS_1) @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --blue --bold "Generating index.cache.bz2" cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/doc && /usr/bin/meinproc5 --check --cache /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/doc//index.cache.bz2 index.docbook -home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2: doc/CMakeFiles/-home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2 -home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2: doc/index.cache.bz2 -home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2: doc/CMakeFiles/-home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2.dir/build.make .PHONY : -home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2 # Rule to build all files generated by this target. doc/CMakeFiles/-home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2.dir/build: -home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2 .PHONY : doc/CMakeFiles/-home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2.dir/build doc/CMakeFiles/-home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2.dir/clean: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/doc && $(CMAKE_COMMAND) -P CMakeFiles/-home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2.dir/cmake_clean.cmake .PHONY : doc/CMakeFiles/-home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2.dir/clean doc/CMakeFiles/-home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2.dir/depend: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/doc /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/doc /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/doc/CMakeFiles/-home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2.dir/DependInfo.cmake --color=$(COLOR) .PHONY : doc/CMakeFiles/-home-emulator-Desktop-k9copy-project-TESTBED-KDE4-doc-index-cache-bz2.dir/depend k9copy/doc/CMakeFiles/CMakeDirectoryInformation.cmake0000664000175000017550000000124312412271774023341 0ustar emulatoremulator# CMAKE generated file: DO NOT EDIT! # Generated by "Unix Makefiles" Generator, CMake Version 2.8 # Relative path conversion top directories. SET(CMAKE_RELATIVE_PATH_TOP_SOURCE "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4") SET(CMAKE_RELATIVE_PATH_TOP_BINARY "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4") # Force unix paths in dependencies. SET(CMAKE_FORCE_UNIX_PATHS 1) # The C and CXX include file regular expressions for this directory. SET(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") SET(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") SET(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) SET(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) k9copy/doc/CMakeLists.txt0000644000175000017550000000041212412271774016054 0ustar emulatoremulator########### install files ############### # if(QT5_BUILD) kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${HTML_INSTALL_DIR}/en SUBDIR k9copy) else() kde4_create_handbook(index.docbook INSTALL_DESTINATION ${HTML_INSTALL_DIR}/en SUBDIR k9copy) endif() k9copy/doc/cmake_install.cmake0000664000175000017550000000532512412271774017136 0ustar emulatoremulator# Install script for directory: /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/doc # Set the install prefix IF(NOT DEFINED CMAKE_INSTALL_PREFIX) SET(CMAKE_INSTALL_PREFIX "/usr/local") ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") # Set the install configuration name. IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) IF(BUILD_TYPE) STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") ELSE(BUILD_TYPE) SET(CMAKE_INSTALL_CONFIG_NAME "RelWithDebInfo") ENDIF(BUILD_TYPE) MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) # Set the component getting installed. IF(NOT CMAKE_INSTALL_COMPONENT) IF(COMPONENT) MESSAGE(STATUS "Install component: \"${COMPONENT}\"") SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") ELSE(COMPONENT) SET(CMAKE_INSTALL_COMPONENT) ENDIF(COMPONENT) ENDIF(NOT CMAKE_INSTALL_COMPONENT) # Install shared libraries without execute permission? IF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) SET(CMAKE_INSTALL_SO_NO_EXE "0") ENDIF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES "/usr/local/share/doc/HTML/en/k9copy/index.cache.bz2;/usr/local/share/doc/HTML/en/k9copy/index.docbook;/usr/local/share/doc/HTML/en/k9copy/screenshot.png;/usr/local/share/doc/HTML/en/k9copy/assistant.png") IF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) IF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") ENDIF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) FILE(INSTALL DESTINATION "/usr/local/share/doc/HTML/en/k9copy" TYPE FILE FILES "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/doc/index.cache.bz2" "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/doc/index.docbook" "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/doc/screenshot.png" "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/doc/assistant.png" ) ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") execute_process(COMMAND /usr/bin/cmake -E create_symlink "/usr/local/share/doc/HTML/en/common" "$ENV{DESTDIR}/usr/local/share/doc/HTML/en/k9copy/common" ) ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") k9copy/k9copy.shell0000774000175000017550000000044212412271774015025 0ustar emulatoremulator#!/bin/sh # created by cmake, don't edit, changes will be lost LD_LIBRARY_PATH=/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/lib/./:/usr/local/lib64:/usr/lib64/kde4/devel:/usr/lib64${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4/k9copy" "$@" k9copy/lib/0000775000175000017550000000000012412271774013322 5ustar emulatoremulatork9copy/CTestTestfile.cmake0000664000175000017550000000104312412271774016276 0ustar emulatoremulator# CMake generated Testfile for # Source directory: /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 # Build directory: /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 # # This file includes the relevant testing commands required for # testing this directory and lists subdirectories to be tested as well. SUBDIRS(src/dvdnav) SUBDIRS(src/core) SUBDIRS(src/mpeg2) SUBDIRS(src/vamps) SUBDIRS(src/devices) SUBDIRS(src/mplayer) SUBDIRS(src/assistant) SUBDIRS(src/import) SUBDIRS(src/batch) SUBDIRS(icons) SUBDIRS(data) SUBDIRS(po) SUBDIRS(doc) k9copy/k9copy_assistant_open.desktop0000644000175000017550000000113212412271774020472 0ustar emulatoremulator[Desktop Action open] Exec=k9copy --input %f --assistant Icon=k9copy Name=Copy with k9copy (wizard) Name[fr]=Copier avec k9copy (wizard) Name[de]=Kopieren mit k9copy (wizard) Name[tr]=k9copy ile kopyala (wizard) Name[ru]=Копировать при помощи k9copy (Мастер) NAme[uk]=Копіювати за допомогою майстра k9copy [Desktop Entry] X-KDE-Solid-Predicate=[[ StorageVolume.ignored == false AND OpticalDisc.availableContent == 'Data|VideoDvd' ] OR [ StorageVolume.ignored == false AND OpticalDisc.availableContent == 'Data|VideoDvd' ]] Type=Service Actions=open;k9copy/src/0000755000175000017550000000000012417717503013341 5ustar emulatoremulatork9copy/src/batch/0000755000175000017550000000000012412271774014422 5ustar emulatoremulatork9copy/src/batch/k9batch.cpp0000644000175000017550000001222112412271774016451 0ustar emulatoremulator#include "k9batch.h" #include #include "k9execcopy.h" #include "k9dvd.h" #include "k9dvdtitle.h" #include #include void k9batch::showHelp() { k9log::writeln(QString("Usage : %1 [options]").arg(qApp->arguments().at(0))); k9log::writeln("\nOptions:"); k9log::writeln("--input \t\tDevice containing the DVD to copy"); k9log::writeln("--output \t\tDestination of the backup"); k9log::writeln("--output-size \t\tSize of the DVD in Mb (max 8500)"); k9log::writeln("--backup-all\t\t\tPerforms a complete backup of the DVD"); k9log::writeln("--backup-titles \tPerforms a backup of the listed titles"); k9log::writeln("--backup-main\t\t\tPerforms a backup of the main title only"); k9log::writeln("--backup-menus\t\t\tKeep original menus"); k9log::writeln("--prefered-audio-lang \tAudio streams to backup. If the first is not found, takes the second..."); k9log::writeln("--prefered-sub-lang \tSubtitles streams to backup. If the first is not found, takes the second..."); } bool k9batch::exec(int argc, char** argv) { bool isBatch=false; for (int i=0; i < argc; i++) if (strcmp(argv[i],"--batch")==0) isBatch=true; if (!isBatch) return false; QApplication app(argc,argv,false); for (int i=0 ;i < app.arguments().count();i++) { QString arg=app.arguments().at(i); QString nextArg=""; if (i< app.arguments().count() -1) nextArg=app.arguments().at(i+1); if (arg.startsWith("--")) args[arg.replace("--","")]= nextArg.startsWith("--") ? "" : nextArg; } if (args.contains("help")){ showHelp(); return true; } k9Tools::setBatchCopy(true); k9DVD dvd(NULL); dvd.scandvd(args["input"],true); k9ExecCopy execCopy; execCopy.setDvd ( &dvd ); QString path; execCopy.setCopyMenus ( args.contains("backup-menus")); if (args.contains("output-size")) { bool ok; int size; size=args["output-size"].toInt(&ok); if (ok) execCopy.setDvdSize(qMin(size,8500)); } doSelect(dvd); //execCopy.setSpeed ( Ui_MainDlg.cbBurnSpeed->currentText() ); bool bFolder,bISO; bISO=args["output"].endsWith(".iso"); bFolder =!bISO; if ( bFolder) { execCopy.setOutput ( k9ExecCopy::oFolder ); // changed from home to preferred output directory (bkp) path= args["output"]; if ( path=="" ) return true; } else if ( bISO) { // changed QDir::homePath() to m_prefOutput (bkp) path= args["output"]; if ( path =="" ) return true; execCopy.setOutput ( k9ExecCopy::oISO ); } execCopy.setPath ( path ); execCopy.copyDVD(); return true; } void k9batch::doSelectLang(k9DVDTitle *title){ k9log::writeln(QString("title %1 - VTS %2 selected").arg(title->getnumTitle()).arg(title->getVTS())); QStringList prefAudio=args["prefered-audio-lang"].split(","); bool found=false; for (int iAudio=0;iAudio getaudioStreamCount() && !found;iAudio++) { foreach(QString lang,prefAudio) { if (title->getaudioStream(iAudio)->getlangCod()==lang) { title->getaudioStream(iAudio)->setselected(true); k9log::writeln (QString("---selected Audio %1").arg(lang)); found=true; break; } } } QStringList prefSub=args["prefered-sub-lang"].split(","); found=false; for (int iSub=0;iSub getsubPictureCount() && !found;iSub++) { foreach(QString lang,prefSub) { if (title->getsubtitle(iSub)->getlangCod()==lang) { k9log::writeln (QString("---selected Subtitle %1").arg(lang)); title->getsubtitle(iSub)->setselected(true); found=true; break; } } } foreach (k9DVDTitle *t,title->getTitles()) doSelectLang(t); if (!title->isSelected()) title->setvideoSelected(true); } void k9batch::doSelect(k9DVD &dvd) { if (args.contains("backup-all")) { for (int itt=0; itt getnumTitle()==stitle.toInt()) doSelectLang(title); } } } else if (args.contains("backup-main")) { k9DVDTitle *longest=NULL; for (int itt=0; itt getIndexed()) longest=title; } else { if (title->gettotalsize_mb() > longest->gettotalsize_mb()) longest=title; } } doSelectLang(longest); } } k9copy/src/batch/CTestTestfile.cmake0000664000175000017550000000051512412271774020151 0ustar emulatoremulator# CMake generated Testfile for # Source directory: /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/src/batch # Build directory: /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/src/batch # # This file includes the relevant testing commands required for # testing this directory and lists subdirectories to be tested as well. k9copy/src/batch/Makefile0000664000175000017550000001501612412271774016067 0ustar emulatoremulator# CMAKE generated file: DO NOT EDIT! # Generated by "Unix Makefiles" Generator, CMake Version 2.8 # Default target executed when no arguments are given to make. default_target: all .PHONY : default_target #============================================================================= # Special targets provided by cmake. # Disable implicit rules so canonical targets will work. .SUFFIXES: # Remove some rules from gmake that .SUFFIXES does not remove. SUFFIXES = .SUFFIXES: .hpux_make_needs_suffix_list # Suppress display of executed commands. $(VERBOSE).SILENT: # A target that is always out of date. cmake_force: .PHONY : cmake_force #============================================================================= # Set environment variables for the build. # The shell in which to execute make rules. SHELL = /bin/sh # The CMake executable. CMAKE_COMMAND = /usr/bin/cmake # The command to remove a file. RM = /usr/bin/cmake -E remove -f # Escaping for special characters. EQUALS = = # The program to use to edit the cache. CMAKE_EDIT_COMMAND = /usr/bin/ccmake # The top-level source directory on which CMake was run. CMAKE_SOURCE_DIR = /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 # The top-level build directory on which CMake was run. CMAKE_BINARY_DIR = /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 #============================================================================= # Targets provided globally by CMake. # Special rule for the target edit_cache edit_cache: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." /usr/bin/ccmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) .PHONY : edit_cache # Special rule for the target edit_cache edit_cache/fast: edit_cache .PHONY : edit_cache/fast # Special rule for the target install install: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." /usr/bin/cmake -P cmake_install.cmake .PHONY : install # Special rule for the target install install/fast: preinstall/fast @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." /usr/bin/cmake -P cmake_install.cmake .PHONY : install/fast # Special rule for the target install/local install/local: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..." /usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake .PHONY : install/local # Special rule for the target install/local install/local/fast: install/local .PHONY : install/local/fast # Special rule for the target list_install_components list_install_components: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"Unspecified\"" .PHONY : list_install_components # Special rule for the target list_install_components list_install_components/fast: list_install_components .PHONY : list_install_components/fast # Special rule for the target package package: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Run CPack packaging tool..." cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && /usr/bin/cpack --config ./CPackConfig.cmake .PHONY : package # Special rule for the target package package/fast: package .PHONY : package/fast # Special rule for the target package_source package_source: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Run CPack packaging tool for source..." cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && /usr/bin/cpack --config ./CPackSourceConfig.cmake /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CPackSourceConfig.cmake .PHONY : package_source # Special rule for the target package_source package_source/fast: package_source .PHONY : package_source/fast # Special rule for the target rebuild_cache rebuild_cache: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." /usr/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) .PHONY : rebuild_cache # Special rule for the target rebuild_cache rebuild_cache/fast: rebuild_cache .PHONY : rebuild_cache/fast # Special rule for the target test test: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running tests..." /usr/bin/ctest --force-new-ctest-process $(ARGS) .PHONY : test # Special rule for the target test test/fast: test .PHONY : test/fast # The main all target all: cmake_check_build_system cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(CMAKE_COMMAND) -E cmake_progress_start /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CMakeFiles /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/src/batch/CMakeFiles/progress.marks cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 src/batch/all $(CMAKE_COMMAND) -E cmake_progress_start /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CMakeFiles 0 .PHONY : all # The main clean target clean: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 src/batch/clean .PHONY : clean # The main clean target clean/fast: clean .PHONY : clean/fast # Prepare targets for installation. preinstall: all cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 src/batch/preinstall .PHONY : preinstall # Prepare targets for installation. preinstall/fast: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 src/batch/preinstall .PHONY : preinstall/fast # clear depends depend: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 .PHONY : depend # Help Target help: @echo "The following are some of the valid targets for this Makefile:" @echo "... all (the default if no target is provided)" @echo "... clean" @echo "... depend" @echo "... edit_cache" @echo "... install" @echo "... install/local" @echo "... list_install_components" @echo "... package" @echo "... package_source" @echo "... rebuild_cache" @echo "... test" .PHONY : help #============================================================================= # Special targets to cleanup operation of make. # Special rule to run CMake to check the build system integrity. # No rule that depends on this can have commands that come from listfiles # because they might be regenerated. cmake_check_build_system: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 .PHONY : cmake_check_build_system k9copy/src/batch/CMakeLists.cmake0000644000175000017550000000000012412271774017411 0ustar emulatoremulatork9copy/src/batch/CMakeFiles/0000775000175000017550000000000012412271774016367 5ustar emulatoremulatork9copy/src/batch/CMakeFiles/progress.marks0000664000175000017550000000000212412271774021262 0ustar emulatoremulator0 k9copy/src/batch/CMakeFiles/CMakeDirectoryInformation.cmake0000664000175000017550000000124312412271774024444 0ustar emulatoremulator# CMAKE generated file: DO NOT EDIT! # Generated by "Unix Makefiles" Generator, CMake Version 2.8 # Relative path conversion top directories. SET(CMAKE_RELATIVE_PATH_TOP_SOURCE "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4") SET(CMAKE_RELATIVE_PATH_TOP_BINARY "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4") # Force unix paths in dependencies. SET(CMAKE_FORCE_UNIX_PATHS 1) # The C and CXX include file regular expressions for this directory. SET(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") SET(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") SET(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) SET(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) k9copy/src/batch/CMakeLists.txt0000644000175000017550000000000012412271774017150 0ustar emulatoremulatork9copy/src/batch/k9batch.h0000644000175000017550000000044712412271774016125 0ustar emulatoremulator#ifndef k9batch_H #define k9batch_H #include "k9common.h" class k9DVD; class k9DVDTitle; class k9batch { private: QMap args; void showHelp(); void doSelect(k9DVD &dvd); void doSelectLang(k9DVDTitle *title); public: bool exec(int argc, char **argv); }; #endifk9copy/src/batch/cmake_install.cmake0000664000175000017550000000225612412271774020241 0ustar emulatoremulator# Install script for directory: /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/src/batch # Set the install prefix IF(NOT DEFINED CMAKE_INSTALL_PREFIX) SET(CMAKE_INSTALL_PREFIX "/usr/local") ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") # Set the install configuration name. IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) IF(BUILD_TYPE) STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") ELSE(BUILD_TYPE) SET(CMAKE_INSTALL_CONFIG_NAME "RelWithDebInfo") ENDIF(BUILD_TYPE) MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) # Set the component getting installed. IF(NOT CMAKE_INSTALL_COMPONENT) IF(COMPONENT) MESSAGE(STATUS "Install component: \"${COMPONENT}\"") SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") ELSE(COMPONENT) SET(CMAKE_INSTALL_COMPONENT) ENDIF(COMPONENT) ENDIF(NOT CMAKE_INSTALL_COMPONENT) # Install shared libraries without execute permission? IF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) SET(CMAKE_INSTALL_SO_NO_EXE "0") ENDIF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) k9copy/src/main/0000755000175000017550000000000012417731553014266 5ustar emulatoremulatork9copy/src/main/k9prefdvd.cpp0000644000175000017550000001072012412271774016667 0ustar emulatoremulator// // C++ Implementation: // // Description: // // // Developer: Pauline123 , (C) 2014 // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9prefdvd.h" #include #include #include #include "k9tools.h" #include "k9dvd.h" #include #if QT_VERSION >= 0x050000 #include #endif k9prefDVD::k9prefDVD(QWidget* parent) : QWidget(parent) { m_loading=true; Ui_prefDVD.setupUi(this); k9Config config; Ui_prefDVD.urOutput->setMode(KFile::Directory); #if QT_VERSION >= 0x050000 Ui_prefDVD.urOutput->setUrl(QUrl(config.getPrefOutput())); #else Ui_prefDVD.urOutput->setUrl(KUrl(config.getPrefOutput())); #endif Ui_prefDVD.ckK3b->setChecked(config.getPrefK3b()); Ui_prefDVD.ckAutoBurn->setChecked(config.getPrefAutoBurn()); Ui_prefDVD.ckQuickScan->setChecked(config.getQuickScan()); Ui_prefDVD.ckDvdAuthor->setChecked(config.getUseDvdAuthor()); Ui_prefDVD.ckDelTmpFiles->setChecked(config.getPrefDelTmpFiles()); Ui_prefDVD.ckMpegChapter->setChecked(config.getMpegChapters()); Ui_prefDVD.ckUserOps->setChecked(config.getPrefUserOps()); Ui_prefDVD.sbSize->setValue(config.getPrefSize()); Ui_prefDVD.sbSize->setSuffix(" "+ i18n("MB")); loadLanguages(Ui_prefDVD.lwAudioLang,config.getPrefAudioLang()); loadLanguages(Ui_prefDVD.lwSubtitlesLang,config.getPrefSubtitleLang()); switch(config.getPrefReadAhead()) { case 0 : Ui_prefDVD.cbReadAhead->setCurrentIndex(1); break; case 8 : Ui_prefDVD.cbReadAhead->setCurrentIndex(2); break; default: Ui_prefDVD.cbReadAhead->setCurrentIndex(0); break; } m_loading=false; } void k9prefDVD::loadLanguages(QListWidget *_list,const QStringList &_prefered) { m_loading=true; lng arrLng[200]; k9DVD::LangList(arrLng); int index=0; _list->clear(); //selected languages on top of the list foreach (QString lang, _prefered) { lang=lang.mid(0,2); QListWidgetItem *item=new QListWidgetItem(_list); item->setData(Qt::UserRole,QString(lang)); item->setText(QString("%1 - %2").arg(lang).arg(k9DVD::lang_name(arrLng,lang,""))); item->setCheckState(Qt::Checked); _list->addItem(item); } do { if (!_prefered.contains(QString(arrLng[index].code)) && (QString(arrLng[index].code).trimmed()!="")) { QListWidgetItem *item=new QListWidgetItem(_list); item->setData(Qt::UserRole,QString(arrLng[index].code)); item->setText(QString("%1 - %2").arg(arrLng[index].code).arg(arrLng[index].name)); item->setCheckState(Qt::Unchecked); _list->addItem(item); } index++; } while (arrLng[index].code[0]!=0); m_loading=false; } k9prefDVD::~k9prefDVD() { } /*$SPECIALIZATION$*/ void k9prefDVD::save() { k9Config config; config.setPrefOutput( Ui_prefDVD.urOutput->url().path()); config.setPrefK3b(Ui_prefDVD.ckK3b->isChecked()); config.setPrefAutoBurn( Ui_prefDVD.ckAutoBurn->isChecked()); config.setPrefSize(Ui_prefDVD.sbSize->value()); config.setQuickScan( Ui_prefDVD.ckQuickScan->isChecked()); config.setUseDvdAuthor( Ui_prefDVD.ckDvdAuthor->isChecked()); config.setPrefDelTmpFiles(Ui_prefDVD.ckDelTmpFiles->isChecked()); config.setMpegChapters(Ui_prefDVD.ckMpegChapter->isChecked()); config.setPrefUserOps(Ui_prefDVD.ckUserOps->isChecked()); QStringList lang; for (int row=0;row count();row++) { QListWidgetItem *item=Ui_prefDVD.lwAudioLang->item(row); if (item->checkState()==Qt::Checked) lang << item->data(Qt::UserRole).toString(); } config.setPrefAudioLang(lang); lang.clear(); for (int row=0;row count();row++) { QListWidgetItem *item=Ui_prefDVD.lwSubtitlesLang->item(row); if (item->checkState()==Qt::Checked) lang << item->data(Qt::UserRole).toString(); } config.setPrefSubtitleLang(lang); switch(Ui_prefDVD.cbReadAhead->currentIndex()) { case 0 : config.setPrefReadAhead(-1); break; case 1 : config.setPrefReadAhead(0); break; case 2: config.setPrefReadAhead(8); break; } config.save(); } void k9prefDVD::lwAudioLangChanged(QListWidgetItem *item) { if (!m_loading) { } } void k9prefDVD::lwSubtitleLangChanged(QListWidgetItem *item) { if (!m_loading) { } } k9copy/src/main/k9langselect.cpp0000644000175000017550000001254012412271774017360 0ustar emulatoremulator// // C++ Implementation: // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9langselect.h" #include "k9dvd.h" #include "k9dvdtitle.h" #if QT_VERSION >= 0x050000 // Qt5 Code #ifndef FALSE #define FALSE (0) #endif #ifndef TRUE #define TRUE (!FALSE) #endif #endif // Qt5 Code k9LangSelect::k9LangSelect(k9Main *mainWindow,QWidget* parent) : QWidget(parent) { Ui_langSelect.setupUi(this); setMain( mainWindow); m_main->setLangSelect( this); } k9LangSelect::~k9LangSelect() { } /*$SPECIALIZATION$*/ void ckLvLangItem::stateChange(bool state) { if (mainDlg->getupdating()) return; mainDlg->checkLang(language,streamType,state); mainDlg->updateSelection(); // k9DVD *d = mainDlg->dvd; mainDlg->setDVDSize(); mainDlg->updateFactor(); //(mainDlg->factor)->setValue((int) (d->getfactor(mainDlg->withMenus(),true )*100)-100 ); } void k9LangSelect::listViewItemChanged(QTreeWidgetItem *_item,int _col) { if (_item->type()==1001 && _col==0) { ckLvLangItem *it=(ckLvLangItem*)_item; it->stateChange(it->isOn()); } } void k9LangSelect::setMain(k9Main* _value) { m_main = _value; m_dvd=m_main->dvd; } void k9LangSelect::fillLvLanguages() { Ui_langSelect.lvLanguages->clear(); langAudItems.clear(); langSubItems.clear(); QStringList slAudLang,slSubLang; if (m_dvd->getopened()) { k9DVDSubtitle *l_sub; k9DVDAudioStream *l_auds; QList *items=m_main->getItems(); for (int i=0;icount();i++) { k9DVDListItem *litem=(k9DVDListItem*)items->at(i); switch (litem->streamType) { case SUB: { l_sub=litem->subtitle; if (slSubLang.contains(l_sub->getlanguage())==0) slSubLang.append(l_sub->getlanguage()); break; } case AUD: { l_auds=litem->audioStream; if (slAudLang.contains(l_auds->getlanguage())==0) slAudLang.append(l_auds->getlanguage()); break; } default: break; } } } QTreeWidgetItem *audioRoot = new QTreeWidgetItem(Ui_langSelect.lvLanguages); audioRoot->setExpanded( TRUE ); audioRoot->setText(0, i18n("Audio")); foreach ( QString audLang,slAudLang) { ckLvLangItem *lvitem=new ckLvLangItem(audioRoot,m_main); lvitem->setText(0,audLang); lvitem->streamType=AUD; lvitem->language=audLang; langAudItems.append(lvitem); } QTreeWidgetItem *subRoot = new QTreeWidgetItem(Ui_langSelect.lvLanguages); subRoot->setExpanded( TRUE ); subRoot->setText(0, i18n("Subtitles")); foreach ( QString subLang, slSubLang) { ckLvLangItem *lvitem=new ckLvLangItem(subRoot,m_main); lvitem->setText(0,subLang); lvitem->streamType=SUB; lvitem->language=subLang; langSubItems.append(lvitem); } connect(Ui_langSelect.lvLanguages,SIGNAL(itemChanged(QTreeWidgetItem*,int)),this,SLOT(listViewItemChanged(QTreeWidgetItem*,int))); } void k9LangSelect::update() { for (int i=0;ilanguage); for (int i=0;ilanguage); } void k9LangSelect::updateLvLang(const eStreamType streamType,const QString & lang ) { uint Total=0,Selected=0; QString lg; QList *items = m_main->getItems(); for (int i=0;icount();i++) { k9DVDListItem *litem=(k9DVDListItem*)items->at(i); if (litem->streamType==streamType ) { switch (streamType) { case SUB : lg= litem->subtitle->getlanguage(); if (lg==lang) { Total++; if (litem->listItem->isOn()) Selected ++; } break; case AUD : lg=litem->audioStream->getlanguage(); if (lg==lang) { Total++; if (litem->listItem->isOn()) Selected++; } break; default: break; } } } if (streamType==AUD) { foreach (ckLvLangItem *langItem,langAudItems) { if (langItem->language ==lang) { if (Selected==Total) { langItem->setOn(true); } else langItem->setOn(false); } } } if (streamType==SUB) { foreach (ckLvLangItem *langItem, langSubItems){ if (langItem->language ==lang) { if (Selected==Total) { langItem->setOn(true); } else langItem->setOn(false); } } } } void k9LangSelect::selectAll( bool _state) { foreach (ckLvLangItem *langItem,langAudItems){ langItem->setOn(_state); } foreach (ckLvLangItem *langItem,langSubItems){ langItem->setOn(_state); } } void k9LangSelect::clear() { langAudItems.clear(); langSubItems.clear(); Ui_langSelect.lvLanguages->clear(); } k9copy/src/main/k9prefdirs.h0000644000175000017550000000116612412271774016524 0ustar emulatoremulator// // C++ Interface: // // Description: sets independent default dirs for all outputs // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9PREFDIRS_H #define K9PREFDIRS_H #include "k9common.h" #include "ui_prefDirs.h" class k9prefDirs : public QWidget { Q_OBJECT public: k9prefDirs(QWidget* parent = 0); ~k9prefDirs(); /*$PUBLIC_FUNCTIONS$*/ void save(); public slots: /*$PUBLIC_SLOTS$*/ protected: /*$PROTECTED_FUNCTIONS$*/ protected slots: /*$PROTECTED_SLOTS$*/ private: Ui::prefDirs Ui_prefDirs; }; #endif k9copy/src/main/k9updatefactor.h0000644000175000017550000000126512412271774017367 0ustar emulatoremulator// // C++ Interface: k9updatefactor // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9UPDATEFACTOR_H #define K9UPDATEFACTOR_H #include "k9common.h" #include #include #include /** @author Jean-Michel PETIT */ class k9Main; class k9UpdateFactor : public QThread { Q_OBJECT private: QMutex m_mutex; bool m_restart; protected: void run(); public: k9UpdateFactor(QObject *parent = 0, const char *name = 0); ~k9UpdateFactor(); void updateFactor(); signals: void updateFactor_internal(); }; #endif k9copy/src/main/k9prefauthor.h0000644000175000017550000000130712412271774017062 0ustar emulatoremulator// // C++ Interface: // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9PREFAUTHOR_H #define K9PREFAUTHOR_H #include "k9common.h" #include "ui_prefAuthor.h" #include class k9prefAuthor : public QWidget { Q_OBJECT public: k9prefAuthor(QWidget* parent = 0); ~k9prefAuthor(); /*$PUBLIC_FUNCTIONS$*/ void load(); public slots: /*$PUBLIC_SLOTS$*/ virtual void bButtonFontClicked(); virtual void save(); protected: /*$PROTECTED_FUNCTIONS$*/ QFont m_font; protected slots: /*$PROTECTED_SLOTS$*/ private: Ui::prefAuthor Ui_prefAuthor; }; #endif k9copy/src/main/kviewmpeg2.cpp0000755000175000017550000001335712412271774017065 0ustar emulatoremulator/************************************************************************** * Developer: Pauline123 , (C) 2014 * * Copyright (C) 2005 by Jean-Michel Petit * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "k9common.h" #include #include #include #include #include #include #include #include #include #if QT_VERSION >= 0x050000 #include #else #include #endif #include #include #include #include #include #include #include "kviewmpeg2.h" k9Widget::k9Widget(QWidget *parent):QWidget(parent) { } void k9Widget::setImage(QImage *_image) { m_mutex.lock(); m_image=*_image; m_mutex.unlock(); //paintEvent( NULL); update(); } void k9Widget::paintEvent( QPaintEvent *) { // setPaletteBackgroundColor(Qt::black); QPalette palette; palette.setColor(backgroundRole(), Qt::black); setPalette(palette); int top,left; if (m_mutex.tryLock()) { QPainter p(this); double wratio=(double)width()/(double)m_image.width(); double hratio=(double)height()/(double)m_image.height(); double ratio= wratio < hratio ? wratio:hratio; top =(int) (height() -m_image.height()*ratio)/2+1; left =(int) (width() -m_image.width()*ratio)/2 +1; p.scale(ratio,ratio); p.drawImage((int)(left/ratio),(int)(top/ratio),m_image); p.end(); m_mutex.unlock(); } } kViewMPEG2::kViewMPEG2(QWidget *parent):QWidget(parent) { Ui_viewMPEG2.setupUi(this); Ui_viewMPEG2.bPlay->setIcon(SmallIcon("media-playback-start")); Ui_viewMPEG2.bStop->setIcon(SmallIcon("media-playback-stop")); #if QT_VERSION >= 0x050000 setWindowTitle((i18n("Title Preview"))); #else setWindowTitle(KDialog::makeStandardCaption(i18n("Title Preview"),this)); #endif m_widget=NULL; connect(&m_player , SIGNAL(setPosition(uint)), this, SLOT(setPosition(uint))); connect(&m_player , SIGNAL(setMax(uint)), this, SLOT(setMax(uint))); connect(&m_player , SIGNAL(setMin(uint)), this, SLOT(setMin(uint))); connect(&m_timer , SIGNAL(timeout()),this, SLOT(drawImage())); lockSlider=false; stopped=true; Ui_viewMPEG2.gbCrop->hide(); m_layout=new QGridLayout(Ui_viewMPEG2.label); m_player.getDecoder()->setViewMpeg2(this); // connect(m_player.getDecoder() , SIGNAL(pixmapReady(QImage *)), this, SLOT(drawPixmap(QImage *))); m_widget=new k9Widget(Ui_viewMPEG2.label); m_layout->addWidget(m_widget,0,0); } void kViewMPEG2::readSettings() { m_player.stop(); //KSimpleConfig settings("K9Copy"); k9Config config; } kViewMPEG2::~kViewMPEG2() { stopped=true; m_player.stop(); } void kViewMPEG2::lock() { mutex.lock(); } void kViewMPEG2::unlock() { mutex.unlock(); } void kViewMPEG2::setPosition( uint _position) { if (!lockSlider) Ui_viewMPEG2.slider->setValue(_position); } void kViewMPEG2::setMax( uint _position) { Ui_viewMPEG2.slider->setMaximum(_position); } void kViewMPEG2::setMin(uint _position) { Ui_viewMPEG2.slider->setMinimum(_position); } void kViewMPEG2::drawImage(QImage *image) { QMutex mutex; img=*image; mutex.lock(); m_wplay.wait(&mutex,40); m_widget->setImage( &img); } /** No descriptions */ void kViewMPEG2::drawImage() { /*if (qApp==NULL) return; if (m_mutex.tryLock()) { m_widget->setImage( &img); if (qApp!=NULL) m_mutex.unlock(); } */ m_wplay.wakeAll(); } void kViewMPEG2::bPlayClick() { m_timer.start(40); m_player.play(); } int kViewMPEG2::open (k9DVD *_dvd,k9DVDTitle * title,int chapter) { m_timer.start(40); bool play=m_player.isRunning(); m_player.open(_dvd->getdvd()->getDvd(), _dvd->getDevice(),title,chapter); if (play) bPlayClick(); return 1; } /** No descriptions */ void kViewMPEG2::setError(const QString & err) { error=true; errMsg=err; } void kViewMPEG2::resizeEvent(QResizeEvent *) {} void kViewMPEG2::bStopClick() { m_player.stop(); } void kViewMPEG2::sliderReleased() { pause=true; int i; i=Ui_viewMPEG2.slider->value(); m_player.updatePos(i); lockSlider=false; } void kViewMPEG2::closeEvent( QCloseEvent* ce ) { stopped=true; ce->accept(); return; } /** No descriptions */ void kViewMPEG2::sliderPressed() { lockSlider=true; } k9copy/src/main/k9prefmencoder.cpp0000644000175000017550000002346012412271774017713 0ustar emulatoremulator// // C++ Implementation: // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9prefmencoder.h" #include #include "k9mencodercmdgen.h" #include "k9ffmpegcmdgen.h" #if QT_VERSION >= 0x050000 #include #include #include #else #include #endif #include #include "k9tools.h" k9prefMencoder::k9prefMencoder(QWidget* parent) : QWidget(parent) { Ui_prefMencoder.setupUi(this); m_update=false; load(); #if QT_VERSION >= 0x050000 KGuiItem::assign(Ui_prefMencoder.btnAddA, KStandardGuiItem::add() ); KGuiItem::assign(Ui_prefMencoder.btnAddV, KStandardGuiItem::add() ); KGuiItem::assign(Ui_prefMencoder.btnDeleteA, KStandardGuiItem::remove() ); KGuiItem::assign(Ui_prefMencoder.btnDeleteV, KStandardGuiItem::remove() ); KGuiItem::assign(Ui_prefMencoder.bReset, KStandardGuiItem::reset() ); #else Ui_prefMencoder.btnAddA->setGuiItem(KStandardGuiItem::Add); Ui_prefMencoder.btnAddV->setGuiItem(KStandardGuiItem::Add); Ui_prefMencoder.btnDeleteA->setGuiItem(KStandardGuiItem::Remove); Ui_prefMencoder.btnDeleteV->setGuiItem(KStandardGuiItem::Remove); Ui_prefMencoder.bReset->setGuiItem(KStandardGuiItem::Reset ); #endif Ui_prefMencoder.btnOpt1->setIcon(SmallIcon("configure")); Ui_prefMencoder.btnOpt2->setIcon(SmallIcon("configure")); Ui_prefMencoder.btnOpt3->setIcon(SmallIcon("configure")); Ui_prefMencoder.btnOptA->setIcon(SmallIcon("configure")); } void k9prefMencoder::load() { loadAudio(); loadVideo(); } void k9prefMencoder::loadVideo() { Ui_prefMencoder.lbvCodecs->clear(); QListWidgetItem *item; for (int i=0;i < m_codecs.count();i++) { if (m_codecs.getEncoder(i)==Ui_prefMencoder.cbEncoderV->currentText()) { item=new QListWidgetItem(m_codecs.getCodecName(i),Ui_prefMencoder.lbvCodecs); item->setData(Qt::UserRole,i); } } Ui_prefMencoder.lbvCodecs->setCurrentRow(0); } void k9prefMencoder::loadAudio() { Ui_prefMencoder.lbaCodecs->clear(); QListWidgetItem *item; for (int i=0;i < m_audioCodecs.count();i++) { if (m_audioCodecs.getEncoder(i)==Ui_prefMencoder.cbEncoderA->currentText()) { item=new QListWidgetItem(m_audioCodecs.getCodecName(i),Ui_prefMencoder.lbaCodecs); item->setData(Qt::UserRole,i); } } Ui_prefMencoder.lbaCodecs->setCurrentRow(0); } void k9prefMencoder::lbvCodecsCurrentChanged(QListWidgetItem *_item,QListWidgetItem *) { if (_item) { int i=_item->data(Qt::UserRole).toInt(); m_update=true; Ui_prefMencoder.leFourcc->setText(m_codecs.getFourcc(i)); Ui_prefMencoder.teOpt1->setText(m_codecs.getOptions0(i)); Ui_prefMencoder.teOpt2->setText(m_codecs.getOptions1(i)); Ui_prefMencoder.teOpt3->setText(m_codecs.getOptions2(i)); Ui_prefMencoder.leVLabel->setText(_item->text()); m_update=false; } } void k9prefMencoder::lbaCodecsCurrentChanged(QListWidgetItem *_item,QListWidgetItem *) { if (_item) { int i=_item->data(Qt::UserRole).toInt(); m_update=true; Ui_prefMencoder.teOptA->setText(m_audioCodecs.getOptions(i)); Ui_prefMencoder.leALabel->setText(_item->text()); Ui_prefMencoder.leExtension->setText(m_audioCodecs.getExtension(i)); m_update=false; } } void k9prefMencoder::save() { m_codecs.save(); m_audioCodecs.save(); } SelectedEncoder k9prefMencoder::getSelectedEncoderV() { if (Ui_prefMencoder.cbEncoderV->currentText() =="ffmpeg") return FFMPEG; else return MENCODER; } SelectedEncoder k9prefMencoder::getSelectedEncoderA() { if (Ui_prefMencoder.cbEncoderA->currentText() =="ffmpeg") return FFMPEG; else return MENCODER; } void k9prefMencoder::btnOpt1Clicked() { QString s=Ui_prefMencoder.teOpt1->toPlainText(); if (getSelectedEncoderV()==FFMPEG) k9ffmpegCmdGen::getFFMpegCmd(k9ffmpegCmdGen::VIDEO,s); else k9MencoderCmdGen::getMencoderOptions(s,Ui_prefMencoder.cbEncoderV->currentText()); Ui_prefMencoder.teOpt1->setText(s); } void k9prefMencoder::btnOpt2Clicked() { QString s=Ui_prefMencoder.teOpt2->toPlainText(); if (getSelectedEncoderV()==FFMPEG) k9ffmpegCmdGen::getFFMpegCmd(k9ffmpegCmdGen::VIDEO,s); else k9MencoderCmdGen::getMencoderOptions(s,Ui_prefMencoder.cbEncoderV->currentText()); Ui_prefMencoder.teOpt2->setText(s); } void k9prefMencoder::btnOpt3Clicked() { QString s=Ui_prefMencoder.teOpt3->toPlainText(); if (getSelectedEncoderV()==FFMPEG) k9ffmpegCmdGen::getFFMpegCmd(k9ffmpegCmdGen::VIDEO,s); else k9MencoderCmdGen::getMencoderOptions(s,Ui_prefMencoder.cbEncoderV->currentText()); Ui_prefMencoder.teOpt3->setText(s); } void k9prefMencoder::btnOptAClicked() { QString s=Ui_prefMencoder.teOptA->toPlainText(); if (getSelectedEncoderA()==FFMPEG) k9ffmpegCmdGen::getFFMpegCmd(k9ffmpegCmdGen::AUDIO,s); else k9MencoderCmdGen::getMencoderOptions(s,Ui_prefMencoder.cbEncoderA->currentText()); Ui_prefMencoder.teOptA->setHtml(s); } void k9prefMencoder::btnAddVClicked() { int i=m_codecs.count(); QListWidgetItem *item=new QListWidgetItem(i18n("new profile"),Ui_prefMencoder.lbvCodecs); item->setData(Qt::UserRole,i); QString option; if (getSelectedEncoderV()==FFMPEG) option="-vcodec copy"; else option="-ovc copy"; m_codecs.setOptions0(i,option); m_codecs.setOptions1(i,option); m_codecs.setOptions2(i,option); m_codecs.setCodecName(i,i18n("new profile")); m_codecs.setEncoder(i,Ui_prefMencoder.cbEncoderV->currentText()); Ui_prefMencoder.lbvCodecs->setCurrentRow(Ui_prefMencoder.lbvCodecs->count()-1); } void k9prefMencoder::btnDeleteVClicked() { if (Ui_prefMencoder.lbvCodecs->count()>0) { int i=Ui_prefMencoder.lbvCodecs->currentItem()->data(Qt::UserRole).toInt(); int j=Ui_prefMencoder.lbvCodecs->currentRow(); m_codecs.remove(i); QListWidgetItem *item=Ui_prefMencoder.lbvCodecs->currentItem(); if (Ui_prefMencoder.lbvCodecs->count()>0) Ui_prefMencoder.lbvCodecs->setCurrentRow(j); delete item; } } void k9prefMencoder::btnAddAClicked() { int i=m_audioCodecs.count(); QListWidgetItem *item=new QListWidgetItem(i18n("new profile"),Ui_prefMencoder.lbaCodecs); item->setData(Qt::UserRole,i); QString option; if (getSelectedEncoderA()==FFMPEG) option="-acodec copy"; else option="-oac copy"; m_audioCodecs.setOptions (i,option); m_audioCodecs.setCodecName(i,i18n("new profile")); m_audioCodecs.setEncoder(i,Ui_prefMencoder.cbEncoderA->currentText()); Ui_prefMencoder.lbaCodecs->setCurrentRow(Ui_prefMencoder.lbaCodecs->count()-1); } void k9prefMencoder::bResetClicked() { m_codecs.reset(); m_audioCodecs.reset(); load(); Ui_prefMencoder.lbvCodecs->setCurrentItem(0); Ui_prefMencoder.lbaCodecs->setCurrentItem(0); // lbvCodecsCurrentChanged (Ui_prefMencoder.lbvCodecs->item(0),0); // lbaCodecsCurrentChanged (Ui_prefMencoder.lbaCodecs->item(0),0); } void k9prefMencoder::btnDeleteAClicked() { if (Ui_prefMencoder.lbaCodecs->count()>0) { int i=Ui_prefMencoder.lbaCodecs->currentItem()->data(Qt::UserRole).toInt(); int j=Ui_prefMencoder.lbaCodecs->currentRow(); m_audioCodecs.remove(i); QListWidgetItem *item=Ui_prefMencoder.lbaCodecs->currentItem(); if (Ui_prefMencoder.lbaCodecs->count()>0) Ui_prefMencoder.lbaCodecs->setCurrentRow(j); delete item; } } void k9prefMencoder::teOptATextChanged() { if (!m_update) m_audioCodecs.setOptions(Ui_prefMencoder.lbaCodecs->currentItem()->data(Qt::UserRole).toInt(),Ui_prefMencoder.teOptA->toPlainText()); } void k9prefMencoder::teOpt1TextChanged() { if (!m_update) m_codecs.setOptions0(Ui_prefMencoder.lbvCodecs->currentItem()->data(Qt::UserRole).toInt(),Ui_prefMencoder.teOpt1->toPlainText()); } void k9prefMencoder::teOpt2TextChanged() { if (!m_update) m_codecs.setOptions1(Ui_prefMencoder.lbvCodecs->currentItem()->data(Qt::UserRole).toInt(),Ui_prefMencoder.teOpt2->toPlainText()); } void k9prefMencoder::teOpt3TextChanged() { if (!m_update) m_codecs.setOptions2(Ui_prefMencoder.lbvCodecs->currentItem()->data(Qt::UserRole).toInt(),Ui_prefMencoder.teOpt3->toPlainText()); } void k9prefMencoder::leVLabelTextChanged(const QString &_value) { if (!m_update) { Ui_prefMencoder.lbvCodecs->currentItem()->setText(_value); m_codecs.setCodecName(Ui_prefMencoder.lbvCodecs->currentItem()->data(Qt::UserRole).toInt(),_value); } } void k9prefMencoder::leALabelTextChanged(const QString &_value) { if (!m_update) { Ui_prefMencoder.lbaCodecs->currentItem()->setText(_value); m_audioCodecs.setCodecName(Ui_prefMencoder.lbaCodecs->currentItem()->data(Qt::UserRole).toInt(),_value); } } void k9prefMencoder::leFourccTextChanged(const QString &_value) { if (!m_update) { m_codecs.setFourcc(Ui_prefMencoder.lbvCodecs->currentItem()->data(Qt::UserRole).toInt(),_value); } } void k9prefMencoder::leExtensionTextChanged(const QString &_value) { if (!m_update) { m_audioCodecs.setExtension(Ui_prefMencoder.lbaCodecs->currentItem()->data(Qt::UserRole).toInt(),_value); } } void k9prefMencoder::cbEncoderATextChanged(const QString &_value) { Q_UNUSED(_value); // if (!m_update) // m_audioCodecs.setEncoder(Ui_prefMencoder.lbaCodecs->currentItem()->data(Qt::UserRole).toInt(),_value); loadAudio(); } void k9prefMencoder::cbEncoderVTextChanged(const QString &_value) { Q_UNUSED(_value); // if (!m_update) // m_codecs.setEncoder(Ui_prefMencoder.lbvCodecs->currentItem()->data(Qt::UserRole).toInt(),_value); loadVideo(); } k9prefMencoder::~k9prefMencoder() { } /*$SPECIALIZATION$*/ k9copy/src/main/prefMPEG4.ui0000644000175000017550000010141412417731553016317 0ustar emulatoremulator prefMPEG4 0 0 698 372 Form1 0 0 75 true false Qt::Horizontal 490 21 0 0 Encoder 0 0 QTabWidget::West 0 Video 0 0 Codec false 0 0 1 XviD lavc MPEG4 x264 2 pass Alt+2 0 0 Width false 0 0 0 0 70 32767 720 4 0 0 Height false false 0 0 0 0 70 32767 4 0 0 &keep aspect ratio Alt+K true Qt::Horizontal 193 20 false 0 0 0 File size Alt+S 0 0 80 0 QAbstractSpinBox::UpDownArrows MB 1 9999 10 700 0 0 Bitrate Alt+B 0 0 80 16777215 00000; Qt::Horizontal QSizePolicy::Fixed 17 32 0 0 X false 0 0 1 9 Qt::Horizontal 40 20 0 0 0 75 true Cropping 0 0 Top 0 0 10000 0 0 Left 0 0 10000 0 0 Bottom 0 0 10000 0 0 Right 0 0 10000 Qt::Horizontal QSizePolicy::Fixed 48 45 0 0 detect Qt::Horizontal 40 20 Audio 0 0 Codec false 0 0 mp3 faac mp2 ac3 adpcm ima 0 0 Bitrate false 0 0 0 0 70 32767 3 Qt::Horizontal QSizePolicy::Expanding 376 20 1 10 0 0 Gain false Qt::Vertical QSizePolicy::Expanding 20 61 Qt::Vertical QSizePolicy::Expanding 18 92 0 0 use cell cache cbEncoder tabWidget cbMp4Codec ck2passes leMp4Width leMp4Height ckMp4AspectRatio rbSize sbMp4Size rbBitrate leMp4VideoBitrate sbMp4NumberCD sbTop sbLeft sbBottom sbRight bCropDetect cbMp4AudioCodec leMp4AudioBitrate sbAudioGain cbMp4AudioCodec activated(int) prefMPEG4 cbMp4AudioCodecActivated(int) 190 87 20 20 cbMp4Codec activated(int) prefMPEG4 cbMp4CodecActivated(int) 83 80 20 20 ck2passes clicked() prefMPEG4 ck2passesClicked() 221 80 20 20 ckMp4AspectRatio clicked() prefMPEG4 ckMp4AspectRatioClick() 159 108 20 20 rbBitrate clicked() prefMPEG4 rgVideoSizeChanged() 33 175 20 20 rbSize clicked() prefMPEG4 rgVideoSizeChanged() 33 149 20 20 leMp4Width textChanged(QString) prefMPEG4 leMp4WidthTextChanged(QString) 83 95 20 20 leMp4Height textChanged(QString) prefMPEG4 leMp4HeightTextChanged(QString) 83 121 20 20 sbMp4Size valueChanged(int) prefMPEG4 sbMp4SizeValueChanged(int) 105 150 20 20 sbMp4NumberCD valueChanged(int) prefMPEG4 sbMp4NumberCDValueChanged(int) 311 180 20 20 leMp4VideoBitrate textChanged(QString) prefMPEG4 leMp4VideoBitrateTextChanged(QString) 105 175 20 20 sbAudioGain valueChanged(int) prefMPEG4 sbAudioGainValueChanged(int) 110 137 20 20 leMp4AudioBitrate textChanged(QString) prefMPEG4 leMp4AudioBitrateTextChanged(QString) 110 113 20 20 ckUseCache clicked() prefMPEG4 ckUseCacheClick() 29 450 20 20 cbEncoder activated(int) prefMPEG4 cbEncoderActivated(int) 536 20 290 229 bCropDetect clicked() prefMPEG4 bCropClicked() 521 257 580 342 sbTop valueChanged(int) prefMPEG4 sbValueChanged(int) 77 253 148 457 sbLeft valueChanged(int) prefMPEG4 sbValueChanged(int) 179 250 327 457 sbBottom valueChanged(int) prefMPEG4 sbValueChanged(int) 267 250 473 454 sbRight valueChanged(int) prefMPEG4 sbValueChanged(int) 390 240 580 389 cbEncoderActivated(int) bCropClicked() sbValueChanged(int) k9copy/src/main/prefDVD.ui0000644000175000017550000002675412417731553016135 0ustar emulatoremulator prefDVD 0 0 752 474 prefDVD 0 0 Output 0 0 Output directory false 0 0 Clear output directory on exit Alt+Y 0 0 DVD size false 0 0 80 0 9000 100 4400 use dvdAuthor for copy without menus Alt+D one file/chapter (MPEG extraction) Alt+D Enable prohibited user operations 0 0 Burning Burn with k3b Alt+B 0 0 Auto burn Alt+T 0 0 Performances Quick scan Alt+Q 0 0 DVD read ahead 0 0 default skip bad sectors (slow) skip bad sectors (faster) 7 this option can improve reading of DVD having bad sectors. It will require root privileges when opening the DVD. 0 0 Prefered languages 0 0 Audio Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop 0 0 Subtitles Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop true true QAbstractItemView::InternalMove true true QAbstractItemView::InternalMove Qt::Horizontal QSizePolicy::Fixed 40 20 KUrlRequester QFrame
kurlrequester.h
kurlrequester.h lwAudioLang itemChanged(QListWidgetItem*) prefDVD lwAudioLangChanged(QListWidgetItem*) 125 298 143 0 lwSubtitlesLang itemChanged(QListWidgetItem*) prefDVD lwSubtitleLangChanged(QListWidgetItem*) 576 360 565 -1 lwAudioLangChanged(QListWidgetItem*) lwSubtitleLangChanged(QListWidgetItem*)
k9copy/src/main/k9redirect.cpp0000644000175000017550000000233312412271774017037 0ustar emulatoremulator// // C++ Implementation: k9redirect // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "k9redirect.h" #include k9Redirect::k9Redirect() { } k9Redirect::~k9Redirect() { } void k9Redirect::execute() { KProcess *p=new KProcess(); *p << "mencoder"; *p << "-oac" << "lavc" << "-ovc" << "lavc" << "-of" << "mpeg"; *p << "-mpegopts" << "format=dvd" << "-vf" << "scale=720:576,harddup" << "-srate" << "48000" << "-af" << "lavcresample=48000" << "-lavcopts" << "vcodec=mpeg2video:vrc_buf_size=1835:vrc_maxrate=9800:vbitrate=5000:keyint=15:acodec=ac3:abitrate=192:aspect=16/9" << "-ofps" << "25" << "-o" << "/tmp/kde-jmp/k9copy/tmp.mpeg" << "-ss" << "00:00:00.000" << "-endpos" << "00:00:57.360" << "-really-quiet" << "/home/jmp/t.avi"; p->start(KProcess::NotifyOnExit); p->wait(); QFile f("/tmp/kde-jmp/k9copy/tmp.mpeg"); QFile fout; f.open(IO_ReadOnly ); fout.open(IO_WriteOnly,stdout); while ( ! f.atEnd()) { char *buf=new char [2048]; f.readBlock(buf,2048); fout.writeBlock(buf,2048); delete buf; } f.close(); fout.close(); } k9copy/src/main/k9titlefactor.cpp0000644000175000017550000001020112412271774017547 0ustar emulatoremulator// // C++ Implementation: // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9titlefactor.h" #include "k9cellcopylist.h" #include "k9dvdsize.h" #include #include #include #include k9TitleFactor::k9TitleFactor(QWidget* parent) : QWidget(parent) { Ui_titleFactor.setupUi(this); m_current=NULL; m_slFactorPressed=false; m_factor=-1; m_dvd=NULL; m_updating=false; SelectionChanged( NULL,m_withMenus); m_useDvdAuthor=false; Ui_titleFactor.slFactor->setPageStep(0); } k9TitleFactor::~k9TitleFactor() {} /*$SPECIALIZATION$*/ void k9TitleFactor::setUseDvdAuthor( bool _value) { m_useDvdAuthor=_value; } float k9TitleFactor::getFactor() { if (m_factor==-1) m_factor=m_dvd->getfactor( m_withMenus,false,m_useDvdAuthor); return m_factor; } void k9TitleFactor::ckAutoClicked(bool checked) { if (m_current!=NULL && !m_updating) { m_current->setforceFactor(checked); if ( checked) { m_current->setfactor( getFactor()); Ui_titleFactor.slFactor->setValue(m_current->getfactor()*100.0); setMinFactor(); } else { Ui_titleFactor.slFactor->setValue(getFactor()*100.0); Ui_titleFactor.slFactor->setMinimum(100); } double size; size =m_current->getChaptersSize_mb(true) / getFactor(); Ui_titleFactor.lTargetSize->setText(i18n("size : %1 MB").arg(size )); } } void k9TitleFactor::slFactorReleased() { m_slFactorPressed=false; } void k9TitleFactor::slFactorPressed() { if (m_current !=NULL) { m_current->setforceFactor(true); setMinFactor(); } m_slFactorPressed=true; } void k9TitleFactor::slFactor_valueChanged( int ) { if (m_current !=NULL ) { if (m_slFactorPressed) { m_current->setfactor( (double)Ui_titleFactor.slFactor->value() /100); for (int i=0;i getTitles().count();i++) { k9DVDTitle * title=m_current->getTitles().at(i); title->setfactor( (double)Ui_titleFactor.slFactor->value() /100); } m_factor=-1; } double size; if (m_current->getforceFactor()) { Ui_titleFactor.tFactor->setText(QString("%1").arg(m_current->getfactor(),4,'f',2)); size =m_current->getChaptersSize_mb(true) / m_current->getfactor(); } else { Ui_titleFactor.tFactor->setText(QString("%1").arg(getFactor(),4,'f',2)); size =m_current->getChaptersSize_mb(true) / getFactor(); } Ui_titleFactor.lTargetSize->setText(i18n("size : %1 MB").arg(size )); } } void k9TitleFactor::changedTitle(k9DVDTitle *_title) { if (_title ==NULL) { Ui_titleFactor.gbTitle->hide(); Ui_titleFactor.lbTitle->setText(i18n("Select a Title in the treeview...")); return; } Ui_titleFactor.gbTitle->show(); m_current=_title; m_updating=true; Ui_titleFactor.gbTitle->setChecked(m_current->getforceFactor()); m_updating=false; Ui_titleFactor.lbTitle->setText(i18n("Shrink Factor for %1").arg(m_current->getname())); double size; if (m_current->getforceFactor()) { Ui_titleFactor.slFactor->setValue(m_current->getfactor()*100.0); Ui_titleFactor.tFactor->setText(QString("%1").arg(m_current->getfactor(),4,'f',2)); setMinFactor(); size =m_current->getChaptersSize_mb(true) / m_current->getfactor(); } else { Ui_titleFactor.slFactor->setValue(getFactor()*100.0); Ui_titleFactor.tFactor->setText(QString("%1").arg(getFactor(),4,'f',2)); Ui_titleFactor.slFactor->setMinimum(100); size =m_current->getChaptersSize_mb(true) / getFactor(); } Ui_titleFactor.lTargetSize->setText(i18n("size : %1 MB").arg(size )); } void k9TitleFactor::setMinFactor() { k9CellCopyList *lst=new k9CellCopyList(m_dvd->getdvd(),m_dvd); double minFactor=lst->getMinFactor( true); //TODO : corriger pour copie sans menus Ui_titleFactor.slFactor->setMinimum(minFactor*100); delete lst; } void k9TitleFactor::SelectionChanged( k9DVD *_dvd,bool _withMenus) { m_dvd=_dvd; if (_dvd==NULL) m_current=NULL; m_factor=-1; m_withMenus=_withMenus; changedTitle( m_current); } k9copy/src/main/playbackoptionsw.ui0000644000175000017550000002122112417731553020214 0ustar emulatoremulator PlaybackOptionsw 0 0 324 487 DVD playback options 2 &Keep original menus Alt+K false 0 0 QFrame::NoFrame QFrame::Plain 0 2 0 0 QAbstractItemView::InternalMove 0 0 75 true Selected Titles false 0 0 211 100 Qt::LeftToRight QFrame::NoFrame QFrame::Plain 0 0 0 0 75 true Default language false 0 0 0 0 Subtitle false 0 0 0 0 Audio false Qt::Horizontal QSizePolicy::Fixed 16 21 0 0 16777215 16777215 Qt::RightToLeft ckMenu clicked() PlaybackOptionsw ckMenuClick() 20 20 20 20 cbDefAudio activated(int) PlaybackOptionsw cbDefAudioActivated(int) 20 20 20 20 cbDefSub activated(int) PlaybackOptionsw cbDefSubActivated(int) 20 20 20 20 lbSequence currentItemChanged(QListWidgetItem*,QListWidgetItem*) PlaybackOptionsw lbSequenceChanged(QListWidgetItem*,QListWidgetItem*) 20 20 20 20 k9copy/src/main/k9prefmpeg4.h0000644000175000017550000000252212412271774016574 0ustar emulatoremulator// // C++ Interface: // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9PREFMPEG4_H #define K9PREFMPEG4_H #include "k9common.h" #include "ui_prefMPEG4.h" class k9prefMPEG4 : public QWidget { Q_OBJECT public: k9prefMPEG4(QWidget* parent = 0); ~k9prefMPEG4(); /*$PUBLIC_FUNCTIONS$*/ void save(); void load(); public slots: /*$PUBLIC_SLOTS$*/ protected: /*$PROTECTED_FUNCTIONS$*/ protected slots: /*$PROTECTED_SLOTS$*/ virtual void ckMp4AspectRatioClick(); virtual void rgVideoSizeChanged(); virtual void cbMp4CodecActivated( int ){} virtual void cbMp4AudioCodecActivated( int ){} virtual void ck2passesClicked(){} virtual void sbMp4SizeValueChanged( int ){} virtual void sbAudioGainValueChanged( int ){} virtual void sbMp4NumberCDValueChanged( int ) {} virtual void leMp4WidthTextChanged( const QString & ) {} virtual void leMp4HeightTextChanged( const QString & ) {} virtual void leMp4AudioBitrateTextChanged( const QString & ) {} virtual void leMp4VideoBitrateTextChanged( const QString & ) {} virtual void ckUseCacheClick() {} virtual void cbEncoderActivated( int); virtual void bCropClicked() {} virtual void sbValueChanged(int) {} private: Ui::prefMPEG4 Ui_prefMPEG4; }; #endif k9copy/src/main/k9prefdvd.h0000644000175000017550000000140212412271774016331 0ustar emulatoremulator// // C++ Interface: // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9PREFDVD_H #define K9PREFDVD_H #include "k9common.h" #include "ui_prefDVD.h" class k9prefDVD : public QWidget { Q_OBJECT public: k9prefDVD(QWidget* parent = 0); ~k9prefDVD(); /*$PUBLIC_FUNCTIONS$*/ void save(); public slots: /*$PUBLIC_SLOTS$*/ protected: /*$PROTECTED_FUNCTIONS$*/ protected slots: /*$PROTECTED_SLOTS$*/ void lwAudioLangChanged (QListWidgetItem *item); void lwSubtitleLangChanged (QListWidgetItem *item); private: Ui::prefDVD Ui_prefDVD; void loadLanguages(QListWidget *_list,const QStringList &_prefered); bool m_loading; }; #endif k9copy/src/main/viewmpeg2.ui0000755000175000017550000002500212417731553016534 0ustar emulatoremulator ViewMPEG2 0 0 480 319 0 0 0 0 0 0 k9Copy - Title Preview 0 0 255 255 255 0 0 0 255 255 255 0 0 0 0 0 0 0 0 0 true false Crop Top 10000 Left 10000 Bottom 10000 Right 10000 Qt::Vertical 20 40 0 0 detect 0 0 32767 50 QFrame::NoFrame QFrame::Plain 0 0 image1image1 0 0 image2image2 Qt::Horizontal bStop clicked() ViewMPEG2 bStopClick() 38 300 20 20 bPlay clicked() ViewMPEG2 bPlayClick() 66 300 20 20 slider sliderReleased() ViewMPEG2 sliderReleased() 94 297 20 20 slider sliderPressed() ViewMPEG2 sliderPressed() 94 297 20 20 bCropDetect clicked() ViewMPEG2 bCropDetectClick() 426 146 477 207 sbTop valueChanged(int) ViewMPEG2 sbValueChanged(int) 454 42 482 36 sbLeft valueChanged(int) ViewMPEG2 sbValueChanged(int) 418 64 479 74 sbBottom valueChanged(int) ViewMPEG2 sbValueChanged(int) 431 95 478 113 sbRight valueChanged(int) ViewMPEG2 sbValueChanged(int) 411 117 480 152 bCropDetectClick() sbValueChanged(int) k9copy/src/main/k9mainw.ui0000644000175000017550000002176612417731553016220 0ustar emulatoremulator MainDlg 0 0 743 585 0 0 0 200 MainDlg 0 0 Input false 0 0 DVD ISO Image Folder 0 0 true 0 0 Output false 0 0 DVD ISO Image Folder MPEG-4 encoding Audio extraction MPEG-2 extraction QLayout::SetDefaultConstraint 0 0 0 0 false true 0 0 @ false 0 0 true default 0 0 X false 0 0 0 200 Qt::CustomContextMenu dbl-click DVD title to edit true Title Size Length Content KUrlRequester QFrame
kurlrequester.h
cbInputDev cbOutputDev cbBurnSpeed listView1 cbOutputDev activated(int) MainDlg cbOutputDevActivated(int) 159 35 20 20 cbInput currentIndexChanged(int) MainDlg cbInputChanged(int) 111 13 2 72 cbOutput activated(int) MainDlg cbOutputChanged(int) 77 43 4 134 cbInputChanged(int) cbOutputChanged(int)
k9copy/src/main/k9mencodercmdgen.cpp0000644000175000017550000006447412412271774020226 0ustar emulatoremulator// // C++ Implementation: // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "k9mencodercmdgen.h" #include #include #include #include #include #include #include #include #include #include #include #include #if QT_VERSION >=0x050000 #include #include #else #include #include #endif #include class _k9CheckListItem: public QTreeWidgetItem { public: _k9CheckListItem(QTreeWidgetItem *_item):QTreeWidgetItem(_item,1001) { setFlags(Qt::ItemIsUserCheckable |Qt::ItemIsEnabled); setCheckState(0,Qt::Unchecked); }; QString root; QDomDocument doc; int page; QFrame *frame; bool isOn() { return checkState(0)==Qt::Checked;} void setOn(bool value) { setCheckState(0, value ? Qt::Checked : Qt::Unchecked);} void stateChange(bool _state); }; void _k9CheckListItem::stateChange(bool _state) { QDomElement eRoot=doc.documentElement().elementsByTagName(root).item(0).toElement(); QDomElement eCodec=eRoot.elementsByTagName(text(0)).item(0).toElement(); eCodec.setAttribute("selected",_state?"true":"false"); } k9MencoderCmdGen::k9MencoderCmdGen(QWidget* parent,const QString &_cmd,const QString &_encoder) : QWidget(parent),m_encoder(_encoder) { Ui_mencoderCmdGen.setupUi(this); #if QT_VERSION >= 0x050000 setWindowTitle((i18n("MEncoder options"))); #else setWindowTitle(KDialog::makeStandardCaption(i18n("MEncoder options"))); #endif listView=Ui_mencoderCmdGen.listView; wsOptions=Ui_mencoderCmdGen.wsOptions; m_row=0; m_page=1; loadXml(); parseCmd(_cmd); fillListView(); connect( listView,SIGNAL(currentItemChanged ( QTreeWidgetItem *, QTreeWidgetItem * )),this,SLOT(listViewCurrentChanged(QTreeWidgetItem *,QTreeWidgetItem*))); } void k9MencoderCmdGen::fillListView() { listView->clear(); listView->header()->hide(); QTreeWidgetItem *item=new QTreeWidgetItem(listView); item->setExpanded(true); item->setText(0,i18n("Audio Codec")); QDomElement root=m_doc.documentElement().elementsByTagName("AUDIO").item(0).toElement(); for (int i=0; i< root.childNodes().count();i++) { QDomElement eChild=root.childNodes().item(i).toElement(); _k9CheckListItem *child=new _k9CheckListItem(item); child->setText(0,eChild.nodeName()); child->root="AUDIO"; child->doc=m_doc; QDomAttr attr=eChild.attributeNode("selected"); if (!attr.isNull()) child->setOn(attr.value()=="true"); addWidgets(child, "AUDIO",eChild.nodeName()); } item=new QTreeWidgetItem(listView); item->setText(0,i18n("Video Codec")); item->setExpanded(true); root=m_doc.documentElement().elementsByTagName("VIDEO").item(0).toElement(); for (int i=0; i< root.childNodes().count();i++) { QDomElement eChild=root.childNodes().item(i).toElement(); _k9CheckListItem *child=new _k9CheckListItem(item); child->setText(0,eChild.nodeName()); child->root="VIDEO"; child->doc=m_doc; QDomAttr attr=eChild.attributeNode("selected"); if (!attr.isNull()) child->setOn(attr.value()=="true"); addWidgets(child, "VIDEO",eChild.nodeName()); } item=new QTreeWidgetItem(listView); item->setText(0,i18n("Filters")); item->setExpanded(true); root=m_doc.documentElement().elementsByTagName("FILTERS").item(0).toElement(); for (int i=0; i< root.childNodes().count();i++) { QDomElement eChild=root.childNodes().item(i).toElement(); _k9CheckListItem *child=new _k9CheckListItem(item); child->setText(0,eChild.nodeName()); child->root="FILTERS"; child->doc=m_doc; QDomAttr attr=eChild.attributeNode("selected"); if (!attr.isNull()) child->setOn(attr.value()=="true"); addWidgets(child, "FILTERS",eChild.nodeName()); } connect(listView,SIGNAL(itemChanged(QTreeWidgetItem*,int)),this,SLOT(listViewItemChanged(QTreeWidgetItem*,int))); } void k9MencoderCmdGen::listViewItemChanged(QTreeWidgetItem *_item,int _col) { if (_item->type()==1001 && _col==0) { _k9CheckListItem *it=(_k9CheckListItem*)_item; it->stateChange(it->isOn()); } } k9MencoderCmdGen::~k9MencoderCmdGen() { } /*$SPECIALIZATION$*/ void k9MencoderCmdGen::listViewCurrentChanged(QTreeWidgetItem *_item,QTreeWidgetItem *) { if (_item->parent() == NULL) wsOptions->setCurrentIndex(0); else if (_item->type()==1001) { _k9CheckListItem *item=(_k9CheckListItem*) _item; wsOptions->setCurrentIndex(item->page); } } void k9MencoderCmdGen::loadXml() { #if QT_VERSION >= 0x050000 //Qt5 Code QFile file(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QString("k9copy/%1.xml")).arg(m_encoder)); #else // Qt4 Code QFile file(KGlobal::dirs()->findResource( "data", QString("k9copy/%1.xml").arg(m_encoder))); #endif if ( !file.open( QIODevice::ReadOnly ) ) return; if ( !m_doc.setContent( &file ) ) { file.close(); return; } file.close(); } void k9MencoderCmdGen::addWidgets(_k9CheckListItem *_listItem,QString _root,QString _cat) { m_cpt=0; //QVBox *vbox=new QVBox(wsOptions); QWidget *page=new QWidget(); QVBoxLayout *vbox = new QVBoxLayout(page); QFrame *fr=new QFrame(page); vbox->addWidget(fr); _listItem->page=wsOptions->addWidget(page); m_page++; _listItem->frame=fr; QGridLayout *m_grid1=new QGridLayout(fr); m_scrollView=new QScrollArea(fr); //m_scrollView->viewport()->setPaletteBackgroundColor(this->paletteBackgroundColor()); m_scrollView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); m_grid1->addWidget(m_scrollView,0,0); //TODO: suppression de l'object m_grid m_grid=new k9Grid(2,this); m_scrollView->setWidget(m_grid->widget()); //finds the VIDEO node QDomElement eVideo=m_doc.documentElement().elementsByTagName(_root).item(0).toElement(); //gets the codec list QDomNodeList lCodecs=eVideo.elementsByTagName(_cat); for (int i=0; iwidget() ); m_grid->addWidget(ckLabel); ckLabel->setChecked(bSel); ckLabel->setObjectName(QString("ck%1").arg(m_row++)); m_hbox=new k9Grid(2,m_grid->widget()); // m_hbox->setFrameShape(QFrame::StyledPanel); // m_hbox->setFrameShadow(QFrame::Raised); if ( !_eOpt.attributeNode("description").isNull()) { ckLabel->setToolTip(_eOpt.attributeNode("description").value()); ckLabel->setWhatsThis(_eOpt.attributeNode("description").value()); } QDomNodeList lOption=_eOpt.elementsByTagName("subopt"); for (int i=0; iobjectName()); m_grid->addWidget(m_hbox->widget()); } void k9MencoderCmdGen::addInt(QDomElement _eOpt) { QString sName=_eOpt.attributeNode("name").value(); bool blist=false; if (_eOpt.nodeName()=="subopt") blist=true; int iMin=_eOpt.attributeNode("min").value().toInt(); int iMax=_eOpt.attributeNode("max").value().toInt(); int iDefault=_eOpt.attributeNode("default").value().toInt(); k9Grid *parent; if (!blist) { parent=m_grid; } else parent=m_hbox; bool bSel=false; QDomAttr aSel=_eOpt.attributeNode("selected"); if (!aSel.isNull()) bSel=aSel.value()=="true"; QCheckBox *ckLabel=new QCheckBox(sName,parent->widget()); ckLabel->setObjectName(QString("ck%1").arg(m_row++) ); parent->addWidget(ckLabel); ckLabel->setChecked(bSel); // ckLabel->setBackgroundColor(parent->backgroundColor()); if ( !_eOpt.attributeNode("description").isNull()) { ckLabel->setToolTip(_eOpt.attributeNode("description").value()); ckLabel->setWhatsThis(_eOpt.attributeNode("description").value()); } _eOpt.setAttribute("checkbox",ckLabel->objectName()); QSpinBox *sb= new QSpinBox(parent->widget()); sb->setMinimum(iMin); sb->setMaximum(iMax); sb->setValue(iDefault); sb->setSingleStep(1); sb->setObjectName(QString("int%1").arg(m_row++)); parent->addWidget(sb); if (iMax <1000) sb->setFixedWidth(50); else sb->setFixedWidth(100); if( !_eOpt.attributeNode("special").isNull()){ sb->setSpecialValueText(_eOpt.attributeNode("special").value()); if (_eOpt.attributeNode("special").value()== _eOpt.attributeNode("default").value()) sb->setValue(iMin-1); } _eOpt.setAttribute("widget",sb->objectName()); //m_grid->addWidget(label,m_row++,0); } void k9MencoderCmdGen::addFloat(QDomElement _eOpt) { QString sName=_eOpt.attributeNode("name").value(); double dMin=_eOpt.attributeNode("min").value().toDouble(); double dMax=_eOpt.attributeNode("max").value().toDouble(); double dDefault=_eOpt.attributeNode("default").value().toDouble(); bool bSel=false; bool blist=false; if (_eOpt.nodeName()=="subopt") blist=true; k9Grid *parent; if (!blist) { parent=m_grid; } else parent=m_hbox; QDomAttr aSel=_eOpt.attributeNode("selected"); if (!aSel.isNull()) bSel=aSel.value()=="true"; QCheckBox *ckLabel=new QCheckBox(sName,parent->widget()); ckLabel->setObjectName(QString("ck%1").arg(m_row++)); ckLabel->setChecked(bSel); parent->addWidget(ckLabel); if ( !_eOpt.attributeNode("description").isNull()) { ckLabel->setToolTip(_eOpt.attributeNode("description").value()); ckLabel->setWhatsThis(_eOpt.attributeNode("description").value()); } _eOpt.setAttribute("checkbox",ckLabel->objectName()); double dStep=0.01; int iPrecision=2; if (!_eOpt.attributeNode("step").isNull()) { dStep=_eOpt.attributeNode("step").value().toDouble(); } if (!_eOpt.attributeNode("precision").isNull()) { iPrecision=_eOpt.attributeNode("precision").value().toInt(); } QDoubleSpinBox *sb= new QDoubleSpinBox(parent->widget()); sb->setRange(dMin,dMax); sb->setValue(dDefault); sb->setSingleStep(dStep); sb->setDecimals(iPrecision); //QDoubleSpinBox(dMin,dMax,dDefault,parent->widget(),dStep,iPrecision); sb->setObjectName(QString("float%1").arg(m_row++)); parent->addWidget(sb); if (dMax <1000) sb->setFixedWidth(80); else sb->setFixedWidth(120); if( !_eOpt.attributeNode("special").isNull()){ sb->setSpecialValueText(_eOpt.attributeNode("special").value()); } _eOpt.setAttribute("widget",sb->objectName()); } void k9MencoderCmdGen::addBool(QDomElement _eOpt) { QString sName=_eOpt.attributeNode("name").value(); bool blist=false; if (_eOpt.nodeName()=="subopt") blist=true; bool bSel=false; k9Grid *parent; if (!blist) { parent = m_grid; } else parent = m_hbox; QDomAttr aSel=_eOpt.attributeNode("selected"); if (!aSel.isNull()) bSel=aSel.value()=="true"; QCheckBox *ckLabel=new QCheckBox(sName,parent->widget()); ckLabel->setObjectName(QString("ck%1").arg(m_row++)); parent->addWidget(ckLabel); if ( !_eOpt.attributeNode("description").isNull()) { ckLabel->setToolTip(_eOpt.attributeNode("description").value()); ckLabel->setWhatsThis(_eOpt.attributeNode("description").value()); } QWidget *w=new QWidget(parent->widget()); parent->addWidget(w); if ((_eOpt.attributeNode("default").value()=="true") && bSel) ckLabel->setChecked(true); _eOpt.setAttribute("checkbox",ckLabel->objectName()); } void k9MencoderCmdGen::addString(QDomElement _eOpt) { QString sName=_eOpt.attributeNode("name").value(); bool blist=false; if (_eOpt.nodeName()=="subopt") blist=true; QString sDefault=_eOpt.attributeNode("default").value(); k9Grid *parent; if( !blist) { parent=m_grid; } else parent=m_hbox; bool bSel=false; QDomAttr aSel=_eOpt.attributeNode("selected"); if (!aSel.isNull()) bSel=aSel.value()=="true"; QCheckBox *ckLabel=new QCheckBox(sName,parent->widget()); parent->addWidget(ckLabel); ckLabel->setObjectName(QString("ck%1").arg(m_row++)); ckLabel->setChecked(bSel); if ( !_eOpt.attributeNode("description").isNull()) { ckLabel->setToolTip(_eOpt.attributeNode("description").value()); ckLabel->setWhatsThis(_eOpt.attributeNode("description").value()); } _eOpt.setAttribute("checkbox",ckLabel->objectName()); QComboBox *cb=new QComboBox(parent->widget()); cb->setObjectName(QString("string%1").arg(m_row++)); parent->addWidget(cb); QDomNodeList values=_eOpt.elementsByTagName("value"); int def=0; if (values.count()==0) { cb->setEditable(true); cb->setEditText(sDefault); } else { for (int i=0;iaddItem(e.attributeNode("name").value()); if (e.attributeNode("name").value() ==sDefault) def=cb->count()-1; } cb->setCurrentIndex(def); } _eOpt.setAttribute("widget",cb->objectName()); } const QString & k9MencoderCmdGen::getCmd(const QString &_root) { /* QString str; QTextStream ts(&str,IO_WriteOnly); m_doc.save(ts,4); QFile f ("/home/jmp/doc.xml"); f.open(IO_WriteOnly); f.writeBlock(str.latin1(),str.length()); f.close(); */ m_cmd=""; QString m_sepOpt=":"; QString m_sepValues=","; //finds the VIDEO node QDomElement eRoot=m_doc.documentElement().elementsByTagName(_root).item(0).toElement(); //gets the codec list QDomNodeList lCodecs=eRoot.childNodes(); for (int i=0; ifindChild(aCheckBox.value()); if (ck->isChecked()) { if (sCmd1.isEmpty()){ if (eCodec.attributeNode("options").isNull()) sCmd1=" -"+eCodec.tagName()+" "; else sCmd1=eCodec.tagName()+" -"+eCodec.attributeNode("options").value()+" "; } if(aType.isNull()) { //build list eSep=eOpt.attributeNode("separator"); if (!eSep.isNull()) m_sepValues=eSep.value(); QDomNodeList lSubOpt=eOpt.elementsByTagName("subopt"); QString sCmd2=""; QString sTmp=""; for (int k=0;kfindChild(eSOpt.attributeNode("checkbox").value()); if(aSType.value()=="int" && Sck->isChecked()) { QSpinBox *isb= this->findChild(aSWidget.value()); if (!sCmd2.isEmpty()) sCmd2 +=m_sepValues; sCmd2+=sTmp+sPrefix+isb->text().trimmed() ; sTmp=""; } else if(aSType.value()=="float" && Sck->isChecked()) { QDoubleSpinBox *isb= this->findChild(aSWidget.value()); if (!sCmd2.isEmpty()) sCmd2 +=m_sepValues; sCmd2+=sTmp+sPrefix+isb->text().replace(",",".").trimmed(); sTmp=""; } else if(aSType.value()=="string" && Sck->isChecked()) { QComboBox *cb= this->findChild(aSWidget.value()); if (!sCmd2.isEmpty() ) sCmd2 +=m_sepValues; // sCmd2+= cb->text(cb->currentItem()); sCmd2+= sTmp+ sPrefix+cb->currentText(); sTmp=""; }else if(aSType.value()=="bool" && Sck->isChecked()) { if (!sCmd2.isEmpty() ) sCmd2 +=m_sepValues; sCmd2+= sTmp+ eSOpt.attributeNode("name").value(); sTmp=""; } else if(sPrefix==""){ sTmp +=m_sepValues; } } if (!sCmd.isEmpty()) sCmd +=m_sepOpt;; sCmd+= eOpt.attributeNode("name").value() + "=" +sCmd2; }else if(aType.value()=="int") { QSpinBox *isb= this->findChild(aWidget.value()); if (!sCmd.isEmpty()) sCmd +=m_sepOpt; sCmd+= eOpt.attributeNode("name").value() + "=" + isb->text(); } else if(aType.value()=="float") { QDoubleSpinBox *isb= this->findChild(aWidget.value()); if (!sCmd.isEmpty()) sCmd +=m_sepOpt; sCmd+= eOpt.attributeNode("name").value() + "=" + isb->text().replace(",","."); } else if(aType.value()=="string") { QComboBox *cb=this->findChild(aWidget.value()); if (!sCmd.isEmpty()) sCmd +=m_sepOpt; sCmd+= eOpt.attributeNode("name").value() + "=" + cb->currentText(); } else if(aType.value()=="bool") { if (!sCmd.isEmpty()) sCmd +=m_sepOpt; sCmd+=eOpt.attributeNode("name").value() ; } } } m_cmd+=sCmd1+sCmd; } return m_cmd; } bool k9MencoderCmdGen::getMencoderOptions(QString &_cmd,const QString &_encoder) { #if QT_VERSION >= 0x050000 QDialog *dlg= new QDialog(); dlg->setWindowTitle(("MEncoder options")); k9MencoderCmdGen * m_cmdGen=new k9MencoderCmdGen(NULL,_cmd,_encoder); m_cmdGen->m_cmd=_cmd; QVBoxLayout * layoutMenCoder = new QVBoxLayout(dlg); layoutMenCoder->addWidget(m_cmdGen); #else KDialog *dlg= new KDialog(); dlg->setWindowTitle(dlg->makeStandardCaption("MEncoder options")); k9MencoderCmdGen * m_cmdGen=new k9MencoderCmdGen(NULL,_cmd,_encoder); m_cmdGen->m_cmd=_cmd; dlg->setMainWidget(m_cmdGen); #endif dlg->resize(800,600); bool res=dlg->exec(); if (res) { QString m_video=m_cmdGen->getCmd("VIDEO").trimmed(); QString m_audio=m_cmdGen->getCmd("AUDIO").trimmed(); QString m_filters=m_cmdGen->getCmd("FILTERS").trimmed(); if (!m_video.isEmpty()) m_video="-ovc "+m_video; if (!m_audio.isEmpty()) m_audio="-oac " +m_audio; _cmd=" "+m_video+" "+m_audio+" "+m_filters; _cmd=_cmd.trimmed(); } delete m_cmdGen; return res; } void k9MencoderCmdGen::parseCmd(const QString &_cmd){ QString cmd(_cmd); cmd=cmd.replace("\n"," ").trimmed(); QStringList cmdList=cmd.split(" "); for (QStringList::iterator it=cmdList.begin();it!=cmdList.end();++it) { if (*it=="-ovc") { ++it; selectCodec("VIDEO",*it); } else if (*it=="-oac") { ++it; selectCodec("AUDIO",*it); } else { if (*it=="-vf") selectCodec("FILTERS","vf"); else if (*it=="-af") selectCodec("FILTERS","af"); QDomNodeList lRoot=m_doc.documentElement().childNodes(); bool bFound=false; QString sCodec=*it; for (int i=0;i prefDirs 0 0 683 480 prefDirs Output 0 0 MPEG-4 false 0 0 default output directory for MPEG-4 backups 0 0 MPEG-2 false 0 0 default output directory for MPEG-1/MPEG-2 backups 0 0 ISO Images false 0 0 default output directory for ISO image backups 0 0 Audio files false 0 0 default output directory for ISO image backups Qt::Vertical 20 29 Programs 0 0 MEncoder false 0 0 0 0 MPlayer false 0 0 0 0 k3b false 0 0 0 0 dvdauthor false 0 0 0 0 ffmpeg false 0 0 0 0 wodim false 0 0 0 0 genisoimage false 0 0 Qt::Vertical 20 40 KUrlRequester QFrame
kurlrequester.h
kurlrequester.h 10 10 true true false
k9copy/src/main/k9prefdirs.cpp0000644000175000017550000000765712412271774017072 0ustar emulatoremulator// // C++ Implementation: // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9prefdirs.h" #include #include "k9tools.h" #include "k9dvd.h" #if QT_VERSION >= 0x050000 #include #endif k9prefDirs::k9prefDirs(QWidget* parent) : QWidget(parent) { Ui_prefDirs.setupUi(this); k9Config config; // Ui_prefDirs.urDirDVD->setMode(KFile::Directory); Ui_prefDirs.urDirISO->setMode(KFile::Directory); Ui_prefDirs.urDirMPEG4->setMode(KFile::Directory); Ui_prefDirs.urDirMPEG2->setMode(KFile::Directory); Ui_prefDirs.urDirAudio->setMode(KFile::Directory); Ui_prefDirs.urDvdauthor->setMode(KFile::ExistingOnly | KFile::File); Ui_prefDirs.urFFmpeg->setMode(KFile::ExistingOnly | KFile::File); Ui_prefDirs.urGenisoimage->setMode(KFile::ExistingOnly | KFile::File); Ui_prefDirs.urMencoder->setMode(KFile::ExistingOnly | KFile::File); Ui_prefDirs.urMplayer->setMode(KFile::ExistingOnly | KFile::File); Ui_prefDirs.urWodim->setMode(KFile::ExistingOnly | KFile::File); Ui_prefDirs.urK3b->setMode(KFile::ExistingOnly | KFile::File); #if QT_VERSION >= 0x050000 //Ui_prefDirs.urDirDVD->setUrl(QUrl(config.getPrefOutput())); Ui_prefDirs.urDirISO->setUrl(QUrl(config.getPrefOutputIso())); Ui_prefDirs.urDirMPEG4->setUrl(QUrl(config.getPrefOutputMpeg4())); Ui_prefDirs.urDirMPEG2->setUrl(QUrl(config.getPrefOutputMpeg2())); Ui_prefDirs.urDirAudio->setUrl(QUrl(config.getPrefOutputAudio())); Ui_prefDirs.urDvdauthor->setUrl(QUrl(config.getPrefDvdauthorPath(false))); Ui_prefDirs.urFFmpeg->setUrl(QUrl(config.getPrefFFmpegPath(false))); Ui_prefDirs.urGenisoimage->setUrl(QUrl(config.getPrefGenisoimagePath(false))); Ui_prefDirs.urMencoder->setUrl(QUrl(config.getPrefMencoderPath(false))); Ui_prefDirs.urMplayer->setUrl(QUrl(config.getPrefMplayerPath(false))); Ui_prefDirs.urWodim->setUrl(QUrl(config.getPrefWodimPath(false))); Ui_prefDirs.urK3b->setUrl(QUrl(config.getPrefk3bPath(false))); #else //Ui_prefDirs.urDirDVD->setUrl(KUrl(config.getPrefOutput())); Ui_prefDirs.urDirISO->setUrl(KUrl(config.getPrefOutputIso())); Ui_prefDirs.urDirMPEG4->setUrl(KUrl(config.getPrefOutputMpeg4())); Ui_prefDirs.urDirMPEG2->setUrl(KUrl(config.getPrefOutputMpeg2())); Ui_prefDirs.urDirAudio->setUrl(KUrl(config.getPrefOutputAudio())); Ui_prefDirs.urDvdauthor->setUrl(KUrl(config.getPrefDvdauthorPath(false))); Ui_prefDirs.urFFmpeg->setUrl(KUrl(config.getPrefFFmpegPath(false))); Ui_prefDirs.urGenisoimage->setUrl(KUrl(config.getPrefGenisoimagePath(false))); Ui_prefDirs.urMencoder->setUrl(KUrl(config.getPrefMencoderPath(false))); Ui_prefDirs.urMplayer->setUrl(KUrl(config.getPrefMplayerPath(false))); Ui_prefDirs.urWodim->setUrl(KUrl(config.getPrefWodimPath(false))); Ui_prefDirs.urK3b->setUrl(KUrl(config.getPrefk3bPath(false))); #endif } k9prefDirs::~k9prefDirs() { } /*$SPECIALIZATION$*/ void k9prefDirs::save() { k9Config config; // config.setPrefOutput( Ui_prefDirs.urDirDVD->url().path()); config.setPrefOutputAudio ( Ui_prefDirs.urDirAudio->url().path()); config.setPrefOutputIso( Ui_prefDirs.urDirISO->url().path()); config.setPrefOutputMpeg2( Ui_prefDirs.urDirMPEG2->url().path()); config.setPrefOutputMpeg4( Ui_prefDirs.urDirMPEG4->url().path()); config.setPrefDvdauthorPath( Ui_prefDirs.urDvdauthor->url().path()); config.setPrefFFmpegPath( Ui_prefDirs.urFFmpeg->url().path()); config.setPrefGenisoimagePath( Ui_prefDirs.urGenisoimage->url().path()); config.setPrefMencoderPath( Ui_prefDirs.urMencoder->url().path()); config.setPrefMplayerPath( Ui_prefDirs.urMplayer->url().path()); config.setPrefWodimPath( Ui_prefDirs.urWodim->url().path()); config.setPrefk3bPath( Ui_prefDirs.urK3b->url().path()); config.save(); } k9copy/src/main/titlefactor.ui0000644000175000017550000001042412417731553017146 0ustar emulatoremulator titleFactor 0 0 551 164 Shrink Factors 75 true Shrink Factor for Title %1 false 0 0 Change Factor Qt::AlignVCenter false true false 100 250 Qt::Horizontal 10 0.00 false size : %1 MB Qt::Vertical QSizePolicy::Expanding 541 20 slFactor sliderPressed() titleFactor slFactorPressed() 20 20 20 20 slFactor sliderReleased() titleFactor slFactorReleased() 20 20 20 20 slFactor valueChanged(int) titleFactor slFactor_valueChanged(int) 20 20 20 20 gbTitle toggled(bool) titleFactor ckAutoClicked(bool) 20 20 20 20 k9copy/src/main/k9ffmpegcmdgen.cpp0000644000175000017550000001167612412271774017672 0ustar emulatoremulator// // C++ Implementation: k9ffmpegcmdgen // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: <>, (C) 2009 // // Copyright: See COPYING file that comes with this distribution // // #include "k9ffmpegcmdgen.h" #include #if QT_VERSION >= 0x050000 #include #else #include #endif k9ffmpegCmdGen::k9ffmpegCmdGen(QWidget* parent) : QWidget(parent) { Ui_ffmpegCmdGen.setupUi(this); readCodecs(); } k9ffmpegCmdGen::~k9ffmpegCmdGen() { } void k9ffmpegCmdGen::getStdout(char *_data, int _size) { QString tmp(QByteArray(_data,_size)); m_codecs=m_codecs.append(tmp); } void k9ffmpegCmdGen::readCodecs() { k9Config config; k9Process process(this,0); connect (&process,SIGNAL(receivedStdout(char*, int)),this,SLOT(getStdout(char*, int))); process << config.getPrefFFmpegPath(true) <<"-formats"; process.start(); process.sync(); QStringList c=m_codecs.split("\n"); bool skip=true; foreach (QString s,c) { if (!skip && s!="") { bool encoder=s.mid(2,1)=="E"; bool video =s.mid(3,1)=="V"; bool audio =s.mid(3,1)=="A"; QString codecName=s.mid(8,16).trimmed(); if (audio && encoder) Ui_ffmpegCmdGen.acodec->addItem(codecName); else if(video && encoder) Ui_ffmpegCmdGen.vcodec->addItem(codecName); } if (s=="Codecs:") skip=false; if (s=="" && !skip) break; } } void k9ffmpegCmdGen::show (FFMpegCmdType _type) { m_type=_type; QStringList slCmd=m_cmd.split(' '); for ( int i=0; i< slCmd.count();i++) { QString opt=slCmd.at(i); if (opt.startsWith("-")) { QString optName=opt.mid(1); QWidget *w=Ui_ffmpegCmdGen.stkOptions->findChild(optName); QLineEdit *le= dynamic_cast(w); QComboBox *cb= dynamic_cast(w); QSpinBox *ni = dynamic_cast(w); QCheckBox *ck=dynamic_cast(w); if (le) { if (isetText(slCmd.at(++i)); } else if (cb) { if (iisEditable()) cb->setEditText(slCmd.at(++i)); else cb->setCurrentIndex(cb->findText(slCmd.at(++i))); } } else if (ni) { QString text; if (isetSpecialValueText(text); else ni->setValue(val); } else if (ck) { ck->setCheckState(Qt::Checked); } // looking for the corresponding checkbox if (w) { QList wl =Ui_ffmpegCmdGen.stkOptions->findChildren(); foreach (QCheckBox *ck,wl) { if (ck->text() == optName) { ck->setCheckState(Qt::Checked); } } } } } switch ( _type) { case AUDIO: Ui_ffmpegCmdGen.stkOptions->setCurrentIndex(1); break; case VIDEO: Ui_ffmpegCmdGen.stkOptions->setCurrentIndex(0); break; } } bool k9ffmpegCmdGen::getFFMpegCmd(FFMpegCmdType _type,QString &_cmd) { #if QT_VERSION >= 0x050000 QDialog *dlg= new QDialog(); #else KDialog *dlg= new KDialog(); #endif k9ffmpegCmdGen *cmdGen=new k9ffmpegCmdGen(dlg); dlg->resize(cmdGen->width(),cmdGen->height()); cmdGen->setCmd(_cmd); cmdGen->show(_type); #if QT_VERSION >= 0x050000 QVBoxLayout * layoutFFmpeg = new QVBoxLayout(dlg); layoutFFmpeg->addWidget(cmdGen); #else dlg->setMainWidget(cmdGen); #endif dlg->setWindowTitle(i18n("ffmpeg command generator")); if (dlg->exec()) _cmd=cmdGen->getCmd(); delete dlg; return true; } QString k9ffmpegCmdGen::getCmd() { m_cmd.clear(); QStringList cmd; QList wl =Ui_ffmpegCmdGen.stkOptions->findChildren(); foreach(QCheckBox *ck,wl) { if (ck->checkState()==Qt::Checked) { QString name=ck->text().replace("&",""); QWidget *w=Ui_ffmpegCmdGen.stkOptions->findChild(name); cmd << "-"+name; if (w) { QLineEdit *le= dynamic_cast(w); QComboBox *cb= dynamic_cast(w); QSpinBox *ni = dynamic_cast(w); if (le) cmd << le->text(); else if (cb) cmd << cb->currentText(); else if (ni) cmd << ni->text(); } } } m_cmd=cmd.join(" "); return m_cmd; } void k9ffmpegCmdGen::setCmd(const QString& theValue) { m_cmd = theValue; } k9copy/src/main/prefMencoder.ui0000644000175000017550000006357112417731553017252 0ustar emulatoremulator prefMencoder 0 0 668 583 Form1 0 0 75 true Available variables false Qt::Horizontal QSizePolicy::Expanding 121 21 0 0 75 true $PASS $WIDTH $HEIGHT $VIDBR $AUDBR $ASPECT false 0 0 pass number video width video height video bitrate audio bitrate aspect ratio false 0 0 75 true $CROPLEFT $CROPTOP $CROPRIGHT $CROPBOTTOM $CROPWIDTH $CROPHEIGHT false 0 0 left crop coord top crop coord size of right crop size of bottom crop crop width crop height false 0 0 21 QTabWidget::West 0 Video codecs false mencoder ffmpeg 0 0 27 0 0 28 label false leVLabel true fourcc false one pass false Qt::Vertical QSizePolicy::Expanding 20 90 true 0 0 22 22 22 22 first pass false true Qt::Vertical QSizePolicy::Expanding 20 81 22 22 22 22 second pass false true 22 22 22 22 Qt::Vertical QSizePolicy::Expanding 20 60 Audio codecs false mencoder ffmpeg 0 0 27 0 0 28 label false leALabel Qt::Vertical QSizePolicy::Expanding 20 78 0 0 22 22 22 22 0 0 options false extension KPushButton KPushButton
kpushbutton.h
tabWidget2 cbEncoderV lbvCodecs btnAddV btnDeleteV leVLabel leFourcc teOpt1 btnOpt1 teOpt2 btnOpt2 teOpt3 btnOpt3 cbEncoderA lbaCodecs btnAddA btnDeleteA leALabel teOptA btnOptA leExtension bReset kpushbutton.h kpushbutton.h kpushbutton.h kpushbutton.h kpushbutton.h kpushbutton.h kpushbutton.h kpushbutton.h kpushbutton.h lbvCodecs currentItemChanged(QListWidgetItem*,QListWidgetItem*) prefMencoder lbvCodecsCurrentChanged(QListWidgetItem*,QListWidgetItem*) 32 54 20 20 teOpt1 textChanged() prefMencoder teOpt1TextChanged() 198 93 20 20 teOpt2 textChanged() prefMencoder teOpt2TextChanged() 198 217 20 20 leVLabel textChanged(QString) prefMencoder leVLabelTextChanged(QString) 197 53 20 20 teOpt3 textChanged() prefMencoder teOpt3TextChanged() 198 340 20 20 lbaCodecs currentItemChanged(QListWidgetItem*,QListWidgetItem*) prefMencoder lbaCodecsCurrentChanged(QListWidgetItem*,QListWidgetItem*) 32 54 20 20 teOptA textChanged() prefMencoder teOptATextChanged() 175 68 20 20 leALabel textChanged(QString) prefMencoder leALabelTextChanged(QString) 174 53 20 20 btnOpt1 clicked() prefMencoder btnOpt1Clicked() 629 93 20 20 btnOpt2 clicked() prefMencoder btnOpt2Clicked() 629 217 20 20 btnOpt3 clicked() prefMencoder btnOpt3Clicked() 629 340 20 20 btnOptA clicked() prefMencoder btnOptAClicked() 629 68 20 20 btnAddA clicked() prefMencoder btnAddAClicked() 32 444 20 20 btnAddV clicked() prefMencoder btnAddVClicked() 32 444 20 20 btnDeleteA clicked() prefMencoder btnDeleteAClicked() 85 444 20 20 btnDeleteV clicked() prefMencoder btnDeleteVClicked() 85 444 20 20 leFourcc textChanged(QString) prefMencoder leFourccTextChanged(QString) 197 67 20 20 bReset clicked() prefMencoder bResetClicked() 647 534 20 20 cbEncoderA currentIndexChanged(QString) prefMencoder cbEncoderATextChanged(QString) 412 447 335 293 leExtension textChanged(QString) prefMencoder leExtensionTextChanged(QString) 416 447 335 293 cbEncoderV currentIndexChanged(QString) prefMencoder cbEncoderVTextChanged(QString) 424 447 335 293 cbEncoderATextChanged(QString) leExtensionTextChanged(QString) cbEncoderVTextChanged(QString)
k9copy/src/main/k9prefpreview.cpp0000644000175000017550000000452412412271774017600 0ustar emulatoremulator// // C++ Implementation: // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9prefpreview.h" k9prefPreview::k9prefPreview(QWidget* parent) : QWidget(parent) { Ui_prefPreview.setupUi(this); load(); } k9prefPreview::~k9prefPreview() { } /*$SPECIALIZATION$*/ void k9prefPreview::load() { k9Config config; Ui_prefPreview.cbVout->setCurrentIndex(config.getMplayerVout()); Ui_prefPreview.cbAout->setCurrentIndex(config.getMplayerAout()); Ui_prefPreview.rbMplayer->setChecked(config.getUseMplayer()); Ui_prefPreview.cbXVout->setCurrentIndex(config.getXineVout()); Ui_prefPreview.cbXAout->setCurrentIndex(config.getXineAout()); Ui_prefPreview.rbXine->setChecked(config.getUseXine()); Ui_prefPreview.rbPhonon->setChecked(config.getUsePhonon()); Ui_prefPreview.rbInternal->setChecked(!config.getUseMplayer() && !config.getUseXine() && ! config.getUsePhonon()); if (Ui_prefPreview.rbMplayer->isChecked()) rbMplayerClick(); else if (Ui_prefPreview.rbXine->isChecked()) rbXineClick(); else if (Ui_prefPreview.rbPhonon->isChecked()) rbPhononClick(); else rbInternalClick(); } void k9prefPreview::save() { k9Config config; if (Ui_prefPreview.rbMplayer->isChecked()) { config.setMplayerVout( Ui_prefPreview.cbVout->currentIndex()); config.setMplayerAout( Ui_prefPreview.cbAout->currentIndex()); }else if (Ui_prefPreview.rbXine->isChecked()) { config.setXineVout( Ui_prefPreview.cbXVout->currentIndex()); config.setXineAout( Ui_prefPreview.cbXAout->currentIndex()); }else if (Ui_prefPreview.rbPhonon->isChecked()) { } config.setUseMplayer( Ui_prefPreview.rbMplayer->isChecked()); config.setUseXine( Ui_prefPreview.rbXine->isChecked()); config.setUsePhonon( Ui_prefPreview.rbPhonon->isChecked()); config.save(); } void k9prefPreview::rbPhononClick() { Ui_prefPreview.wsOptions->setCurrentIndex(3); } void k9prefPreview::rbInternalClick() { Ui_prefPreview.wsOptions->setCurrentIndex(0); } void k9prefPreview::rbMplayerClick() { Ui_prefPreview.wsOptions->setCurrentIndex(1); } void k9prefPreview::rbXineClick() { Ui_prefPreview.wsOptions->setCurrentIndex(2); } k9copy/src/main/k9prefmencoder.h0000644000175000017550000000332212412271774017353 0ustar emulatoremulator// // C++ Interface: // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9PREFMENCODER_H #define K9PREFMENCODER_H #include "k9common.h" #include "ui_prefMencoder.h" #include "k9videocodecs.h" #include "k9audiocodecs.h" #include #include #include enum SelectedEncoder {FFMPEG,MENCODER}; class k9prefMencoder : public QWidget { Q_OBJECT public: k9prefMencoder(QWidget* parent = 0 ); ~k9prefMencoder(); /*$PUBLIC_FUNCTIONS$*/ void save(void); void load(); public slots: /*$PUBLIC_SLOTS$*/ void teOptATextChanged(); void teOpt1TextChanged(); void teOpt3TextChanged(); void teOpt2TextChanged(); void leVLabelTextChanged(const QString &); void leALabelTextChanged(const QString &); void leFourccTextChanged(const QString &); void cbEncoderATextChanged(const QString &); void cbEncoderVTextChanged(const QString &); void leExtensionTextChanged(const QString&); private: void loadAudio(); void loadVideo(); k9VideoCodecs m_codecs; k9AudioCodecs m_audioCodecs; bool m_update; Ui::prefMencoder Ui_prefMencoder; SelectedEncoder getSelectedEncoderA(); SelectedEncoder getSelectedEncoderV(); protected slots: /*$PROTECTED_SLOTS$*/ void lbvCodecsCurrentChanged(QListWidgetItem *_item,QListWidgetItem*); void lbaCodecsCurrentChanged(QListWidgetItem *_item,QListWidgetItem*); void btnOpt1Clicked(); void btnOpt2Clicked(); void btnOpt3Clicked(); void btnOptAClicked(); void btnAddVClicked(); void btnDeleteVClicked(); void btnAddAClicked(); void btnDeleteAClicked(); void bResetClicked(); }; #endif k9copy/src/main/kconfigdlg.h0000644000175000017550000000352612412271774016553 0ustar emulatoremulator/************************************************************************** * Copyright (C) 2005 by Jean-Michel Petit * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef KCONFIGDLG_H #define KCONFIGDLG_H #include "k9common.h" #include #include #include #include /** @author Jean-Michel PETIT */ class kConfigDlg : public QWidget { Q_OBJECT public: kConfigDlg(QWidget *parent); ~kConfigDlg(); void save(); public slots: void bAddClick(); void bRemoveClick(); private: Ui::configDlg Ui_configDlg; }; #endif k9copy/src/main/k9mp4title.h0000644000175000017550000000343612412271774016452 0ustar emulatoremulator// // C++ Interface: // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9MP4TITLE_H #define K9MP4TITLE_H #include "k9common.h" #include "ui_prefMPEG4.h" #include "k9titleencopt.h" class k9DVDTitle; class k9DVD; class k9MP4Title : public QWidget { Q_OBJECT public: enum eOptTitle {optAudio,optVideo,optAll} ; k9MP4Title(QWidget* parent = 0,eOptTitle options=optAll); void setOptions (eOptTitle _options); void loadCodecs(QStringList _audioEncoders,QStringList _videoEncoders); void testFields(); ~k9MP4Title(); /*$PUBLIC_FUNCTIONS$*/ private: k9TitleEncOpt *m_titleEncOpt; Ui::prefMPEG4 Ui_prefMPEG4; eOptTitle m_options; k9DVD *m_dvd; bool m_updating; QString m_videoOptions,m_audioOptions; public slots: /*$PUBLIC_SLOTS$*/ virtual void ckMp4AspectRatioClick(); virtual void load(); virtual void titleChanged(k9DVDTitle *_title); virtual void selectionChanged(k9DVD *_dvd,bool); protected slots: /*$PROTECTED_SLOTS$*/ virtual void cbMp4CodecActivated( int ); virtual void cbMp4AudioCodecActivated( int ); virtual void ck2passesClicked(); virtual void sbMp4SizeValueChanged( int ); virtual void sbAudioGainValueChanged( int ); virtual void sbMp4NumberCDValueChanged( int ); virtual void leMp4WidthTextChanged( const QString & ); virtual void leMp4HeightTextChanged( const QString & ); virtual void leMp4AudioBitrateTextChanged( const QString & ); virtual void leMp4VideoBitrateTextChanged( const QString & ); virtual void rgVideoSizeChanged(); virtual void ckUseCacheClick(); virtual void cbEncoderActivated(int); virtual void bCropClicked(); virtual void sbValueChanged(int); signals: void updateSelection(); }; #endif k9copy/src/main/k9prefauthor.cpp0000644000175000017550000000317312412271774017420 0ustar emulatoremulator// // C++ Implementation: // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "k9prefauthor.h" #include "k9tools.h" #include #include k9prefAuthor::k9prefAuthor(QWidget* parent) : QWidget(parent) { Ui_prefAuthor.setupUi(this); load(); } void k9prefAuthor::load() { k9Config config; k9Tools::setComboText(Ui_prefAuthor.cbAudioFormat,config.getPrefAudioFormat()); k9Tools::setComboText(Ui_prefAuthor.cbAudioBitrate,QString::number(config.getPrefAudioBitrate())); Ui_prefAuthor.inButtonWidth->setValue(config.getPrefButtonWidth()); Ui_prefAuthor.inButtonHeight->setValue(config.getPrefButtonHeight()); Ui_prefAuthor.cbHiliteColor->setColor(config.getPrefButtonHiliteColor()); Ui_prefAuthor.cbTextColor->setColor(config.getPrefButtonTextColor()); m_font=config.getPrefButtonFont(); } k9prefAuthor::~k9prefAuthor() { } /*$SPECIALIZATION$*/ void k9prefAuthor::bButtonFontClicked() { k9Dialogs::getFont( m_font ); } void k9prefAuthor::save() { k9Config config; config.setPrefAudioFormat(Ui_prefAuthor.cbAudioFormat->currentText()); config.setPrefAudioBitrate(Ui_prefAuthor.cbAudioBitrate->currentText().toInt()); config.setPrefButtonWidth(Ui_prefAuthor.inButtonWidth->value()); config.setPrefButtonHeight(Ui_prefAuthor.inButtonHeight->value()); config.setPrefButtonHiliteColor(Ui_prefAuthor.cbHiliteColor->color()); config.setPrefButtonFont(m_font); config.setPrefButtonTextColor(Ui_prefAuthor.cbTextColor->color()); config.save(); } k9copy/src/main/k9titlefactor.h0000644000175000017550000000224112412271774017221 0ustar emulatoremulator// // C++ Interface: // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9TITLEFACTOR_H #define K9TITLEFACTOR_H #include "k9common.h" #include "ui_titlefactor.h" #include "k9dvd.h" #include "k9dvdtitle.h" class k9TitleFactor : public QWidget { Q_OBJECT public: k9TitleFactor(QWidget* parent = 0); ~k9TitleFactor(); /*$PUBLIC_FUNCTIONS$*/ private : k9DVDTitle *m_current; k9DVD *m_dvd; bool m_slFactorPressed; bool m_withMenus; bool m_useDvdAuthor; float m_factor; bool m_updating; Ui::titleFactor Ui_titleFactor; public slots: /*$PUBLIC_SLOTS$*/ virtual void ckAutoClicked(bool _checked); virtual void slFactorReleased(); virtual void slFactorPressed(); virtual void slFactor_valueChanged( int ); virtual void SelectionChanged( k9DVD *_dvd,bool _withMenus); virtual void changedTitle(k9DVDTitle *_title); virtual void setUseDvdAuthor(bool _value); protected: /*$PROTECTED_FUNCTIONS$*/ void setMinFactor(); float getFactor(); }; #endif k9copy/src/main/k9mp4title.cpp0000644000175000017550000003177212412271774017011 0ustar emulatoremulator// // C++ Implementation: // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "k9mp4title.h" #include "k9dvdtitle.h" #include #include #include #include #include #include #include #include #include #include "k9audiocodecs.h" #include "k9videocodecs.h" #include "k9tools.h" #include "k9cropselect.h" #if QT_VERSION >=0x050000 #include #else #include #endif k9MP4Title::k9MP4Title(QWidget* parent,eOptTitle options) : QWidget(parent),m_options(options) { m_updating=false; Ui_prefMPEG4.setupUi(this); m_titleEncOpt=NULL; load(); Ui_prefMPEG4.ckUseCache->hide(); Ui_prefMPEG4.tabWidget->setEnabled(false); Ui_prefMPEG4.lTitle->setText(i18n("Select a Title in the treeview...")); if (options == optAudio) Ui_prefMPEG4.tabWidget->setTabEnabled(0,false); } void k9MP4Title::setOptions (eOptTitle _options) { switch(_options) { case optAudio: Ui_prefMPEG4.tabWidget->setTabEnabled(0,false); Ui_prefMPEG4.tabWidget->setTabEnabled(1,true); break; case optVideo: Ui_prefMPEG4.tabWidget->setTabEnabled(0,true); Ui_prefMPEG4.tabWidget->setTabEnabled(1,false); break; case optAll: Ui_prefMPEG4.tabWidget->setTabEnabled(0,true); Ui_prefMPEG4.tabWidget->setTabEnabled(1,true); break; } m_options=_options; } k9MP4Title::~k9MP4Title() { } void k9MP4Title::bCropClicked() { #if QT_VERSION >= 0x050000 QDialog dialog(this); dialog.setWindowTitle((i18n("Crop detection"))); #else KDialog dialog(this); dialog.setWindowTitle(KDialog::makeStandardCaption(i18n("Crop detection"))); #endif k9CropSelect cropSelect(&dialog); QRect r; r.setCoords(Ui_prefMPEG4.sbLeft->value(),Ui_prefMPEG4.sbTop->value(),Ui_prefMPEG4.sbRight->value(),Ui_prefMPEG4.sbBottom->value()); cropSelect.setRect(r); cropSelect.setMinimumWidth(600); cropSelect.setMinimumHeight(400); #if QT_VERSION >= 0x050000 QVBoxLayout * layoutCrop = new QVBoxLayout(this); layoutCrop->addWidget(&cropSelect); #else dialog.setMainWidget(&cropSelect); #endif cropSelect.open(m_dvd,m_titleEncOpt->getTitle(),1); if (dialog.exec()== QDialog::Accepted) { QRect r= cropSelect.getRect(); Ui_prefMPEG4.sbTop->setValue(r.top()); Ui_prefMPEG4.sbLeft->setValue(r.left()); Ui_prefMPEG4.sbRight->setValue(r.right()); Ui_prefMPEG4.sbBottom->setValue(r.bottom()); if (m_titleEncOpt) { m_titleEncOpt->getCrop()->setCoords(r.left(),r.top(),r.right(),r.bottom()); } } } void k9MP4Title::load() { k9Config config; Ui_prefMPEG4.sbMp4Size->setValue(config.getPrefMp4Size()); Ui_prefMPEG4.sbMp4Size->setSuffix(" "+ i18n("MB")); Ui_prefMPEG4.sbMp4NumberCD->setValue(config.getPrefMp4NumberCD()); Ui_prefMPEG4.sbAudioGain->setValue(config.getPrefMp4AudioGain()); Ui_prefMPEG4.leMp4Width->setText(config.getPrefMp4Width()); Ui_prefMPEG4.leMp4Height->setText(config.getPrefMp4Height()); Ui_prefMPEG4.ckMp4AspectRatio->setChecked(config.getPrefMp4AspectRatio()); Ui_prefMPEG4.leMp4Height->setEnabled(!Ui_prefMPEG4.ckMp4AspectRatio->isChecked()); Ui_prefMPEG4.ck2passes->setChecked(config.getPrefMp42Passes()); Ui_prefMPEG4.ckUseCache->setChecked(config.getPrefUseCellCache()); Ui_prefMPEG4.leMp4AudioBitrate->setText(config.getPrefMp4AudioBitrate()); Ui_prefMPEG4.leMp4VideoBitrate->setText(config.getPrefMp4VideoBitrate()); loadCodecs(QStringList(),QStringList()); Ui_prefMPEG4.cbMp4AudioCodec->setCurrentIndex(Ui_prefMPEG4.cbMp4AudioCodec->findData(config.getPrefMp4AudioCodec())); Ui_prefMPEG4.cbMp4Codec->setCurrentIndex(Ui_prefMPEG4.cbMp4Codec->findData(config.getPrefMp4Codec())); if(config.getPrefMp4VideoBitrate() =="") Ui_prefMPEG4.rbSize->setChecked(true); else Ui_prefMPEG4.rbBitrate->setChecked(true); } void k9MP4Title::loadCodecs(QStringList _audioEncoders,QStringList _videoEncoders) { k9AudioCodecs audioCodecs; k9VideoCodecs videoCodecs; Ui_prefMPEG4.cbMp4AudioCodec->clear(); Ui_prefMPEG4.cbMp4Codec->clear(); Ui_prefMPEG4.cbEncoder->clear(); for (int i=0;i findText(videoCodecs.getEncoder(i))==-1) Ui_prefMPEG4.cbEncoder->addItem(videoCodecs.getEncoder(i)); } for (int i=0; i findText(audioCodecs.getEncoder(i))==-1) Ui_prefMPEG4.cbEncoder->addItem(audioCodecs.getEncoder(i)); } cbEncoderActivated(Ui_prefMPEG4.cbEncoder->currentIndex()); } /*$SPECIALIZATION$*/ void k9MP4Title::ckMp4AspectRatioClick() { Ui_prefMPEG4.leMp4Height->setEnabled(!Ui_prefMPEG4.ckMp4AspectRatio->isChecked()); if (m_titleEncOpt) m_titleEncOpt->setKeepAspectRatio(Ui_prefMPEG4.ckMp4AspectRatio->isChecked()); } void k9MP4Title::selectionChanged(k9DVD *_dvd,bool) { if (_dvd==NULL) m_titleEncOpt=NULL; if (m_titleEncOpt) Ui_prefMPEG4.tabWidget->setEnabled(m_titleEncOpt->getTitle()->isSelected());; m_dvd=_dvd; } void k9MP4Title::titleChanged( k9DVDTitle *_title) { if (_title) m_dvd=_title->getDvd(); m_updating=true; if (_title==NULL) { m_titleEncOpt=NULL; Ui_prefMPEG4.tabWidget->setEnabled(false); Ui_prefMPEG4.lTitle->setText(i18n("Select a Title in the treeview...")); } else { Ui_prefMPEG4.lTitle->setText(_title->getname()); Ui_prefMPEG4.tabWidget->setEnabled( _title->isSelected()); m_titleEncOpt=_title->getEncOpt(); k9TitleEncOpt *opt=m_titleEncOpt; Ui_prefMPEG4.sbMp4Size->setValue(opt->getMaxSize()); Ui_prefMPEG4.sbMp4NumberCD->setValue(opt->getNumParts() ); Ui_prefMPEG4.sbAudioGain->setValue(opt->getAudioGain() ); Ui_prefMPEG4.leMp4Width->setText(opt->getWidth() ); Ui_prefMPEG4.leMp4Height->setText(opt->getHeight()); Ui_prefMPEG4.ckMp4AspectRatio->setChecked(opt->getKeepAspectRatio()); Ui_prefMPEG4.leMp4Height->setEnabled(!Ui_prefMPEG4.ckMp4AspectRatio->isChecked()); Ui_prefMPEG4.ck2passes->setChecked(opt->get2Passes()); Ui_prefMPEG4.ckUseCache->setChecked(opt->getUseCache()); Ui_prefMPEG4.leMp4AudioBitrate->setText(opt->getAudioBr()); Ui_prefMPEG4.leMp4VideoBitrate->setText(opt->getVideoBr()); for (int i=0; icount();i++) { if (Ui_prefMPEG4.cbEncoder->itemText(i)==opt->getEncoder()) Ui_prefMPEG4.cbEncoder->setCurrentIndex(i); } cbEncoderActivated(Ui_prefMPEG4.cbEncoder->currentIndex()); Ui_prefMPEG4.cbMp4Codec->setCurrentIndex( Ui_prefMPEG4.cbMp4Codec->findData(opt->getCodec() )); Ui_prefMPEG4.cbMp4AudioCodec->setCurrentIndex(Ui_prefMPEG4.cbMp4AudioCodec->findData(opt->getAudioCodec())); if(opt->getVideoBr() =="") Ui_prefMPEG4.rbSize->setChecked(true); else Ui_prefMPEG4.rbBitrate->setChecked(true); Ui_prefMPEG4.sbTop->setValue(opt->getCrop()->top()); Ui_prefMPEG4.sbLeft->setValue(opt->getCrop()->left()); Ui_prefMPEG4.sbRight->setValue(opt->getCrop()->right()); Ui_prefMPEG4.sbBottom->setValue(opt->getCrop()->bottom()); Ui_prefMPEG4.sbTop->setMaximum(_title->getheight().toInt()/2); Ui_prefMPEG4.sbLeft->setMaximum(_title->getwidth().toInt()/2); Ui_prefMPEG4.sbRight->setMaximum(_title->getwidth().toInt()-1); Ui_prefMPEG4.sbBottom->setMaximum(_title->getheight().toInt()-1); Ui_prefMPEG4.sbRight->setMinimum(_title->getwidth().toInt()/2); Ui_prefMPEG4.sbBottom->setMinimum(_title->getheight().toInt()/2); testFields(); } m_updating=false; } void k9MP4Title::testFields() { if (m_titleEncOpt) { int index= k9VideoCodecs::getAbsCodecNum(Ui_prefMPEG4.cbMp4Codec->itemData(Ui_prefMPEG4.cbMp4Codec->currentIndex()).toInt(), m_titleEncOpt->getEncoder()) ; k9VideoCodecs videoCodecs; QString sOptions; if (m_titleEncOpt->get2Passes()) sOptions=videoCodecs.getOptions1(index); else sOptions=videoCodecs.getOptions0(index); m_videoOptions=sOptions; Ui_prefMPEG4.leMp4Width->setEnabled(sOptions.contains("$WIDTH")); Ui_prefMPEG4.ckMp4AspectRatio->setEnabled(sOptions.contains("$HEIGHT")); if (sOptions.contains("$VIDBR")) { Ui_prefMPEG4.leMp4VideoBitrate->setEnabled(m_titleEncOpt->getVideoBr() !=""); Ui_prefMPEG4.sbMp4Size->setEnabled( m_titleEncOpt->getVideoBr() ==""); } else { Ui_prefMPEG4.leMp4VideoBitrate->setEnabled(false); Ui_prefMPEG4.sbMp4Size->setEnabled( false); } Ui_prefMPEG4.sbMp4NumberCD->setEnabled(sOptions.contains("$VIDBR")); Ui_prefMPEG4.rbSize->setEnabled(sOptions.contains("$VIDBR")); Ui_prefMPEG4.rbBitrate->setEnabled(sOptions.contains("$VIDBR")); Ui_prefMPEG4.leMp4Height->setEnabled(sOptions.contains("$HEIGHT") && !Ui_prefMPEG4.ckMp4AspectRatio->isChecked()); Ui_prefMPEG4.sbTop->setEnabled(sOptions.contains("$CROPTOP") || sOptions.contains("$CROPHEIGHT")); Ui_prefMPEG4.sbLeft->setEnabled(sOptions.contains("$CROPLEFT") || sOptions.contains("$CROPWIDTH")); Ui_prefMPEG4.sbRight->setEnabled(sOptions.contains("$CROPRIGHT") || sOptions.contains("CROPWIDTH")); Ui_prefMPEG4.sbBottom->setEnabled(sOptions.contains("$CROPBOTTOM") || sOptions.contains("$CROPHEIGHT")); index=k9AudioCodecs::getAbsCodecNum(Ui_prefMPEG4.cbMp4AudioCodec->itemData(Ui_prefMPEG4.cbMp4AudioCodec->currentIndex()).toInt(),m_titleEncOpt->getEncoder()); k9AudioCodecs audioCodecs; sOptions=audioCodecs.getOptions(index); m_audioOptions=sOptions; Ui_prefMPEG4.leMp4AudioBitrate->setEnabled(sOptions.contains("$AUDBR")); } } void k9MP4Title::cbMp4CodecActivated( int _value) { if (m_titleEncOpt) m_titleEncOpt->setCodec(Ui_prefMPEG4.cbMp4Codec->itemData(_value).toInt()); testFields(); } void k9MP4Title::cbMp4AudioCodecActivated( int _value) { if (m_titleEncOpt) m_titleEncOpt->setAudioCodec(Ui_prefMPEG4.cbMp4AudioCodec->itemData(_value).toInt()); testFields(); } void k9MP4Title::ck2passesClicked() { if (m_titleEncOpt) m_titleEncOpt->set2Passes(Ui_prefMPEG4.ck2passes->isChecked()); } void k9MP4Title::ckUseCacheClick() { if (m_titleEncOpt) m_titleEncOpt->setUseCache(Ui_prefMPEG4.ckUseCache->isChecked()); } void k9MP4Title::sbMp4SizeValueChanged( int _value) { if (m_titleEncOpt) m_titleEncOpt->setMaxSize(_value); } void k9MP4Title::sbMp4NumberCDValueChanged( int _value ) { if (m_titleEncOpt) m_titleEncOpt->setNumParts(_value); } void k9MP4Title::sbAudioGainValueChanged( int _value ) { if (m_titleEncOpt) m_titleEncOpt->setAudioGain(_value); } void k9MP4Title::leMp4WidthTextChanged( const QString & _value) { if (m_titleEncOpt) m_titleEncOpt->setWidth(_value); } void k9MP4Title::leMp4HeightTextChanged( const QString & _value) { if (m_titleEncOpt) m_titleEncOpt->setHeight(_value); } void k9MP4Title::leMp4AudioBitrateTextChanged( const QString & _value) { if (m_titleEncOpt) m_titleEncOpt->setAudioBr(_value); } void k9MP4Title::leMp4VideoBitrateTextChanged( const QString & _value) { if (m_titleEncOpt) m_titleEncOpt->setVideoBr(_value); } void k9MP4Title::sbValueChanged(int) { if (m_titleEncOpt && !m_updating) { m_titleEncOpt->getCrop()->setCoords(Ui_prefMPEG4.sbLeft->value(),Ui_prefMPEG4.sbTop->value(),Ui_prefMPEG4.sbRight->value(),Ui_prefMPEG4.sbBottom->value()); } } void k9MP4Title::rgVideoSizeChanged(){ if (Ui_prefMPEG4.rbSize->isChecked()) Ui_prefMPEG4.leMp4VideoBitrate->setText(""); Ui_prefMPEG4.leMp4VideoBitrate->setEnabled(Ui_prefMPEG4.rbBitrate->isChecked() && m_videoOptions.contains("$VIDBR")); Ui_prefMPEG4.sbMp4Size->setEnabled(Ui_prefMPEG4.rbSize->isChecked() && m_videoOptions.contains("$VIDBR")); } void k9MP4Title::cbEncoderActivated(int _index) { k9AudioCodecs audioCodecs; k9VideoCodecs videoCodecs; if (m_titleEncOpt) m_titleEncOpt->setEncoder(Ui_prefMPEG4.cbEncoder->currentText()); Ui_prefMPEG4.cbMp4AudioCodec->clear(); Ui_prefMPEG4.cbMp4Codec->clear(); int cpt=0; for (int i=0;i itemText(_index)) { Ui_prefMPEG4.cbMp4Codec->addItem(videoCodecs.getCodecName(i),cpt++); } cpt=0; for (int i=0; i itemText(_index)) { Ui_prefMPEG4.cbMp4AudioCodec->addItem(audioCodecs.getCodecName(i),cpt++); } if (m_titleEncOpt) { int index=qMax(0,Ui_prefMPEG4.cbMp4Codec->findData(m_titleEncOpt->getCodec() )); Ui_prefMPEG4.cbMp4Codec->setCurrentIndex(index ); index=qMax(0,Ui_prefMPEG4.cbMp4AudioCodec->findData(m_titleEncOpt->getAudioCodec())); Ui_prefMPEG4.cbMp4AudioCodec->setCurrentIndex(index); } else { Ui_prefMPEG4.cbMp4Codec->setCurrentIndex(0); Ui_prefMPEG4.cbMp4AudioCodec->setCurrentIndex(0); } cbMp4CodecActivated(Ui_prefMPEG4.cbMp4Codec->currentIndex()); cbMp4AudioCodecActivated(Ui_prefMPEG4.cbMp4AudioCodec->currentIndex()); emit updateSelection(); } k9copy/src/main/k9redirect.h0000644000175000017550000000064212412271774016505 0ustar emulatoremulator// // C++ Interface: k9redirect // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9REDIRECT_H #define K9REDIRECT_H #include "k9common.h" #include /** @author Jean-Michel PETIT */ class k9Redirect{ public: k9Redirect(); ~k9Redirect(); void execute(); }; #endif k9copy/src/main/k9updatefactor.cpp0000644000175000017550000000117312412271774017720 0ustar emulatoremulator// // C++ Implementation: k9updatefactor // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "k9updatefactor.h" k9UpdateFactor::k9UpdateFactor(QObject *parent, const char *) : QThread(parent) { } k9UpdateFactor::~k9UpdateFactor() { wait(); } void k9UpdateFactor::run(){ do { m_restart=false; emit updateFactor_internal(); } while (m_restart); } void k9UpdateFactor::updateFactor() { m_mutex.lock(); if (isRunning()) { m_restart=true; } else start(); m_mutex.unlock(); } k9copy/src/main/configDlg.ui0000644000175000017550000001064712417731553016531 0ustar emulatoremulator configDlg 0 0 578 342 0 0 Devices 11 11 11 11 6 6 6 0 0 0 0 Qt::Vertical QSizePolicy::Expanding 20 190 600 0 QAbstractItemView::ExtendedSelection true 0 4 device label Input Output 0 0 Add 27 0 0 Remove 28 KPushButton QWidget
kpushbutton.h
kpushbutton.h kpushbutton.h
k9copy/src/main/k9main.cpp0000644000175000017550000014457712412271774016203 0ustar emulatoremulator/*************************************************************************** * Developer: Pauline123 , (C) 2014 * * Copyright (C) 2005 by Jean-Michel Petit * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "k9main.h" #include "k9dvdauthor.h" #include "k9burndvd.h" #include "k9dvd.h" #include "k9dvdtitle.h" #include "k9dvdtitleset.h" #include "k9dvdbackup.h" #include "k9mp4enc.h" #include "k9settings.h" #include "k9langselect.h" #include "k9updatefactor.h" #include "k9titleencopt.h" #include "k9tools.h" #include #include #include #include #include #include #include #include #include #include #include #include #if QT_VERSION >= 0x050000 #include #include #else #include #include #include #include #endif #include #include "images.h" #include "k9execcopy.h" #include #include "k9dialogs.h" #if QT_VERSION >= 0x050000 // Qt5 Code #ifndef FALSE #define FALSE (0) #endif #ifndef TRUE #define TRUE (!FALSE) #endif #include #else // Qt4 Code #endif ckLvItem::ckLvItem ( QTreeWidgetItem *parent,k9Main *dlg,eObjectType _objectType ) : QTreeWidgetItem ( parent,1001 ) { m_checked=false; mainDlg=dlg; obj=NULL; stream=NULL; streamType=NONE; language=""; objectType=_objectType; setFlags ( Qt::ItemIsUserCheckable |Qt::ItemIsEnabled ); setOn ( false ); } ckLvItem::ckLvItem ( QTreeWidget *parent,k9Main *dlg,eObjectType _objectType ) : QTreeWidgetItem ( parent,1001 ) { m_checked=false; mainDlg=dlg; obj=NULL; stream=NULL; streamType=NONE; language=""; objectType=_objectType; setFlags ( Qt::ItemIsUserCheckable | Qt::ItemIsEnabled ); setOn ( false ); //QCheckBox *bx=new QCheckBox(NULL); //dlg->getTreeView()->setItemWidget ( this, 0, bx ); } k9DVDListItem::k9DVDListItem ( void *DVD,ckLvItem *List,eStreamType type ) { switch ( type ) { case AUD : audioStream= ( k9DVDAudioStream* ) DVD; subtitle=NULL; title=NULL; break; case SUB : subtitle = ( k9DVDSubtitle* ) DVD; audioStream=NULL; title=NULL; break; case VID : subtitle=NULL; audioStream=NULL; title = ( k9DVDTitle* ) DVD; break; default : break; } listItem= List; streamType=type; } void k9Main::clearItems() { while ( !items.isEmpty() ) delete items.takeFirst(); } k9Main::k9Main ( QWidget* parent, const char* , k9CdDrives *_drives ) : QWidget ( parent ) { m_ready=false; Ui_MainDlg.setupUi ( this ); listView1=Ui_MainDlg.listView1; connect ( Ui_MainDlg.cbOutputDev,SIGNAL ( currentIndexChanged ( int ) ),this,SLOT ( cbOutputDevActivated ( int ) ) ); connect ( listView1,SIGNAL ( itemExpanded ( QTreeWidgetItem* ) ),this,SLOT ( expanded ( QTreeWidgetItem* ) ) ); connect ( listView1,SIGNAL ( itemCollapsed ( QTreeWidgetItem* ) ),this,SLOT ( collapsed ( QTreeWidgetItem* ) ) ); connect (listView1->header(),SIGNAL(customContextMenuRequested( const QPoint& )),this,SLOT(showPopup(const QPoint&))); listView1->header()->setContextMenuPolicy(Qt::CustomContextMenu); drives=_drives; m_parent= ( k9Copy* ) parent; QImage img; img.loadFromData ( img_chapter, sizeof ( img_chapter ), "PNG" ); pxChapter.fromImage ( img ); /* m_factory = KLibLoader::self()->factory("libk9copy"); if (m_factory) { dvd=static_cast(m_factory->create(this,"dvd", "k9DVD")); } */ dvd=new k9DVD ( this ); updating=false; // items.setAutoDelete(true); // listView1->setDefaultRenameAction(QListView::Accept); // KStandardDirs kd; m_prefOutput=k9Tools::getTempPath(); connect ( drives,SIGNAL ( deviceAdded ( k9CdDrive* ) ),this,SLOT ( deviceAdded ( k9CdDrive* ) ) ); connect ( drives,SIGNAL ( deviceRemoved ( k9CdDrive* ) ),this,SLOT ( deviceRemoved ( k9CdDrive* ) ) ); readSettings(); emit SelectionChanged ( NULL,true ); m_update=new k9UpdateFactor ( this,"" ); connect ( m_update,SIGNAL ( updateFactor_internal() ),this,SLOT ( updateFactor_internal() ) ); cbOutputChanged(Ui_MainDlg.cbOutput->currentIndex()); cbInputChanged(Ui_MainDlg.cbInput->currentIndex()); Ui_MainDlg.cbInput->setItemIcon(iDVD,SmallIcon("media-optical")); Ui_MainDlg.cbInput->setItemIcon(iISO,SmallIcon("document-open")); Ui_MainDlg.cbInput->setItemIcon(iFolder,SmallIcon("document-open-folder")); Ui_MainDlg.cbOutput->setItemIcon(oDVD,SmallIcon("media-optical-recordable")); Ui_MainDlg.cbOutput->setItemIcon(oISO,SmallIcon("document-open")); Ui_MainDlg.cbOutput->setItemIcon(oMP4,SmallIcon("video-mp4")); Ui_MainDlg.cbOutput->setItemIcon(oMPEG2,SmallIcon("video-mpeg")); Ui_MainDlg.cbOutput->setItemIcon(oAudio,SmallIcon("audio-basic")); Ui_MainDlg.cbOutput->setItemIcon(oFolder,SmallIcon("document-open-folder")); m_ready=true; } k9DVDListItem *k9Main::addListItem ( void *DVD,ckLvItem *List,eStreamType type ) { k9DVDListItem *litem; litem=new k9DVDListItem ( DVD,List,type ); items.append ( litem ); return litem; } /* int LvItem::() const { return(1000); } int ckLvItem::rtti() const { return(1001); } */ bool ckLvItem::operator< ( const QTreeWidgetItem & other ) const { int col=treeWidget()->sortColumn(); if ( other.type() !=1001 ) return true; ckLvItem *litem = ( ckLvItem* ) &other; k9DVDTitleset *titleset1,*titleset2; ckLvItem *l; uint id,id2; if ( col==0 ) { switch ( this->objectType ) { case TITLESET: titleset1= ( k9DVDTitleset* ) obj; titleset2= ( k9DVDTitleset* ) litem->obj; return titleset1->getnum() >titleset2->getnum(); case STREAM: l= ( ckLvItem* ) this; id=streamType*100; id2=litem->streamType*100; if ( streamType==AUD ) { id+= ( ( k9DVDAudioStream* ) l->stream )->getID(); } if ( streamType==SUB ) { id+= ( ( k9DVDSubtitle* ) l->stream )->getID().first(); } if ( litem->streamType==AUD ) { id2+= ( ( k9DVDAudioStream* ) litem->stream )->getID(); } if ( litem->streamType==SUB ) { id2+= ( ( k9DVDSubtitle* ) litem->stream )->getID().first(); } return k9Main::compare ( id,id2 ); break; case CHAPTER: { l= ( ckLvItem* ) this; k9DVDChapter *ch1= ( k9DVDChapter* ) l->obj; k9DVDChapter *ch2= ( k9DVDChapter* ) litem->obj; return k9Main::compare ( ch1->getnum() +ch1->getTitle()->getId() *1000 ,ch2->getnum() +ch2->getTitle()->getId() *1000 ); } break; default: return true; } } if ( col ==1 || col==2) { switch ( this->objectType ) { case TITLESET: titleset1= ( k9DVDTitleset* ) obj; titleset2= ( k9DVDTitleset* ) litem->obj; return k9Main::compare ( titleset1->getsize(),titleset2->getsize() ); break; case STREAM: double size1,size2; l = ( ckLvItem* ) this; size1=l->getstreamSize(); size2=litem->getstreamSize(); return k9Main::compare ( size1,size2 ); break; case CHAPTER: { l= ( ckLvItem* ) this; k9DVDChapter *ch1= ( k9DVDChapter* ) l->obj; k9DVDChapter *ch2= ( k9DVDChapter* ) litem->obj; return k9Main::compare ( ch1->getsectors(),ch2->getsectors() ); } break; case TITLE : { k9DVDTitle* title1= ( k9DVDTitle* ) obj; k9DVDTitle* title2= ( k9DVDTitle* ) litem->obj; return k9Main::compare(title1->gettotalsize_mb() , title2->gettotalsize_mb() ); } break; default: return true; } } return false; } double ckLvItem::getstreamSize() { double size; k9DVDTitle *title; switch ( streamType ) { case SUB: { k9DVDSubtitle *sub= ( k9DVDSubtitle* ) stream; size=sub->getsize_mb(); break; } case AUD: { k9DVDAudioStream *aud= ( k9DVDAudioStream* ) stream; size=aud->getsize_mb(); break; } case VID: { title= ( k9DVDTitle* ) obj; size=title->gettotalvideosize_mb(); break; } default: size=0; break; } return size; } bool LvItem::operator< ( const QTreeWidgetItem & other ) const { int col=treeWidget()->sortColumn(); if ( other.type() ==1001 ) return false; LvItem *litem = ( LvItem* ) &other; k9DVDTitle *title1,*title2; if ( (col ==1 || col==2) && objectType==TITLE ) { title1= ( k9DVDTitle* ) obj; title2= ( k9DVDTitle* ) litem->obj; return k9Main::compare ( title1->gettotalsize_mb(),title2->gettotalsize_mb() ); } if ( col==0 && objectType==TITLE ) { title1= ( k9DVDTitle* ) obj; title2= ( k9DVDTitle* ) litem->obj; return k9Main::compare ( title1->getpgc(),title2->getpgc() ); } return false; } void k9Main::listView1ItemChanged ( QTreeWidgetItem *_item,int _col ) { if ( !dvd->getopened() ) return; if ( _item->type() ==1001 && _col==0 ) { ckLvItem *it= ( ckLvItem* ) _item; it->stateChange ( it->isOn() ); } if ( ( _item->flags() & Qt::ItemIsEditable ) ==Qt::ItemIsEditable ) itemRenamed ( _item,_col ); } void ckLvItem::stateChange ( bool state ) { if ( m_checked ==state ) return; m_checked=state; if ( mainDlg !=NULL ) { if ( mainDlg->getupdating() ) return; switch ( objectType ) { case ROOT : mainDlg->checkAll ( state ); break; case TITLESET: mainDlg->checkTS ( state,this ); break; default : mainDlg->checkTitle ( state,this ); break; } // k9DVD *d = mainDlg->dvd; mainDlg->setDVDSize(); mainDlg->updateFactor(); //(mainDlg->factor)->setValue((int) (d->getfactor(mainDlg->withMenus(),true )*100)-100 ); } } bool k9Main::getupdating() { return updating; } void k9Main::Copy() { switch(Ui_MainDlg.cbOutput->currentIndex()) { case oMP4: CreateMP4(); break; case oMPEG2: extractMPEG2(); break; case oAudio: extractAudio(); break; default: k9ExecCopy execCopy; execCopy.setDvd ( dvd ); QString path; execCopy.setCopyMenus ( withMenus() ); execCopy.setSpeed ( Ui_MainDlg.cbBurnSpeed->currentText() ); if ( m_useDvdAuthor || !withMenus() ) m_playbackOptions->setSequence(); if ( Ui_MainDlg.cbOutput->currentIndex() ==oFolder) { execCopy.setOutput ( k9ExecCopy::oFolder ); // changed from home to preferred output directory (bkp) path= Ui_MainDlg.urOutput->url().path(); if ( path=="" ) return; } else if ( Ui_MainDlg.cbOutput->currentIndex() ==oISO ) { // changed QDir::homePath() to m_prefOutput (bkp) path= Ui_MainDlg.urOutput->url().path(); if ( path =="" ) return; execCopy.setOutput ( k9ExecCopy::oISO ); } else { k9CdDrive * drive= ( k9CdDrive* ) recorderList.at ( Ui_MainDlg.cbOutputDev->currentIndex()); path=drive->device; execCopy.setOutput ( k9ExecCopy::oDVD ); } execCopy.setPath ( path ); execCopy.copyDVD(); break; } changeStatusbar ( i18n ( "Ready" ) ,sbMessage ); } void k9Main::eject() { closeDVD(); drives->eject ( dvd->getDevice() ); } QString k9Main::getDevice ( QComboBox *_combo ) { int index=-1; for ( int i=0; i<_combo->count();i++ ) { QString t =_combo->itemText ( i ); if ( _combo->itemText ( i ) == _combo->currentText() ) index=i; } QString res=""; if ( ( index==-1 ) || ( _combo->currentText() ==i18n ( "ISO Image" ) ) ) { res=_combo->currentText(); } else { k9CdDrive * drive= ( k9CdDrive* ) driveList.at ( index ); res=drive->device; } return res; } void k9Main::Open() { listView1->setSortingEnabled ( false ); int i; k9DVDTitle * l_track; QString t; //QTime h; listView1->disconnect ( SIGNAL ( itemChanged ( QTreeWidgetItem*,int ) ) ); listView1->disconnect ( SIGNAL ( currentItemChanged ( QTreeWidgetItem * , QTreeWidgetItem * ) ) ); disconnect ( m_langSelect->listView(),0,0,0 ); // connect(listView1,SIGNAL(itemRenamed(QListViewItem*,int)),this,SLOT(itemRenamed(QListViewItem *,int))); closeDVD(); listView1->clear(); clearItems(); tsItems.clear(); chItems.clear(); QString sDevice=Ui_MainDlg.cbInput->currentIndex()==iDVD ? getDevice ( Ui_MainDlg.cbInputDev ): Ui_MainDlg.urInput->url().path(); QString sVolName=""; //if no dvd label, try to get it from hal #ifdef HAVE_HAL_H foreach ( k9CdDrive *drive,driveList ) { if ( drive->getDevice() != NULL ) { if ( drive->getDevice()->mountPoint() ==sDevice ) { sVolName=drive->getDevice()->getVolumeName(); sDevice=drive->device; break; } } } #endif k9Config config; if ( sDevice.startsWith ( "/dev/" ) && config.getPrefReadAhead() !=-1 ) k9CdDrive::setReadAhead ( sDevice,config.getPrefReadAhead() ); dvd->scandvd ( sDevice,m_quickScan ); if ( dvd->geterror() ) { k9Dialogs::error ( dvd->geterrMsg(), i18n ( "Open DVD" ) ); return; } m_parent->setDvdOpened(true); if ( dvd->getDVDTitle() ==i18n ( "unknown" ) && sVolName!="" ) { dvd->setDVDTitle ( sVolName ); } root = new ckLvItem ( listView1,this,ROOT ); root->setExpanded ( TRUE ); root->setText ( 0, dvd->getDVDTitle() ); root->setFlags ( root->flags() | Qt::ItemIsEditable ); root->obj=NULL; root->streamType=NONE; root->setIcon ( 0,SmallIcon ( "media-optical" ) ); for ( i=0;igettitlesetCount();i++ ) { ckLvItem *tsItem = new ckLvItem ( root,this,TITLESET ); tsItem->setExpanded ( TRUE ); QString c; c=i18n ( "Titleset %1").arg(i+1 ); tsItem->setText ( 0,c ); QFont font=tsItem->font ( 1 ); font.setWeight ( QFont::Bold ); tsItem->setFont ( 1,font ); tsItem->setText ( 1," "+dvd->gettitleset ( i )->getsize_mb() +" " +i18n ( "MB" ) ); tsItem->setTextAlignment ( 1,Qt::AlignRight ); tsItem->obj=dvd->gettitleset ( i ) ; tsItem->streamType=NONE; // tsItem->setRenameEnabled(0,false); tsItems.append ( tsItem ); tsItem->setIcon ( 0,SmallIcon ( "folder-open" ) ); } for ( i=0;igettitleCount();i++ ) { l_track=dvd->gettitle ( i ); if ( ( l_track->getIndexed() ) ) addTitle ( l_track ); } m_playbackOptions->fillTitleList(); m_langSelect->fillLvLanguages(); listView1->setSortingEnabled ( true ); changeStatusbar ( i18n ( "Ready" ),sbMessage ); emit SelectionChanged ( dvd,withMenus() ); this->setEnabled ( true ); connect ( listView1,SIGNAL ( itemChanged ( QTreeWidgetItem*,int ) ),this,SLOT ( listView1ItemChanged ( QTreeWidgetItem*,int ) ) ); connect ( listView1,SIGNAL ( currentItemChanged ( QTreeWidgetItem * , QTreeWidgetItem * ) ),this,SLOT ( listView1CurrentChanged ( QTreeWidgetItem *,QTreeWidgetItem * ) ) ); resizeColumns(); //call to cbOutputChanged to update the filename cbOutputChanged(Ui_MainDlg.cbOutput->currentIndex()); } void k9Main::resizeEvent ( QResizeEvent * ) { resizeColumns(); } void k9Main::showEvent ( QShowEvent * ) { resizeColumns(); } void k9Main::resizeColumns() { listView1->setColumnWidth ( 0,listView1->viewport()->width() ); listView1->resizeColumnToContents ( 1 ); listView1->resizeColumnToContents ( 2 ); listView1->resizeColumnToContents ( 3 ); listView1->setColumnWidth ( 0,listView1->viewport()->width()-listView1->columnWidth ( 1 )-listView1->columnWidth ( 2 ) -listView1->columnWidth ( 3 )); } void k9Main::setDVDSize() { //k9DVDSize *dvdsize=static_cast(m_factory->create(this,"dvd", "k9DVDSize")); k9DVDSize *dvdsize=new k9DVDSize ( this ); dvdsize->setMaxSizeDyn ( m_prefSize ); delete dvdsize; } k9Main::~k9Main() { clearItems(); delete dvd; } void k9Main::addChapters ( QTreeWidgetItem *_parent,k9DVDTitle *_title ) { LvItem *chapter = new LvItem ( _parent,CHAPTER ); chapter->setText ( 0, i18n ( "chapters" ) ); chapter->setExpanded ( false ); chapter->setIcon ( 0,pxChapter ); int ch=0; for ( int i=0;i< _title->getchapterCount();i++ ) { ckLvItem *it =new ckLvItem ( chapter,this,CHAPTER ); it->setText ( 0,i18n ( "chapter %1").arg(++ch ) ); QString s; s=QString ( "%1" ).arg ( ( double ) ( _title->getChapter ( i )->getsectors() ) /512,0,'f',2 ); it->setText ( 1,i18n ( "%1 MB").arg(s ) ); it->setTextAlignment ( 1,Qt::AlignRight | Qt::AlignVCenter); it->setTextAlignment ( 2,Qt::AlignRight | Qt::AlignVCenter); it->setText(2,_title->getChapter(i)->getLength().toString("h:mm:ss")); it->streamType=CHAP; it->obj=_title->getChapter ( i ); chItems.append ( it ); it->mainTitle=_title; } for ( int j=0;j <_title->getTitles().count();j++ ) { k9DVDTitle *title2=_title->getTitles().at ( j ); for ( int i=0;i< title2->getchapterCount();i++ ) { ckLvItem *it =new ckLvItem ( chapter,this,CHAPTER ); it->setText ( 0,i18n ( "chapter %1").arg(++ch ) ); it->streamType=CHAP; it->obj=title2->getChapter ( i ); QString s; s=QString ( "%1" ).arg ( ( double ) ( title2->getChapter ( i )->getsectors() ) /512,0,'f',2 ); it->setText ( 1,i18n ( "%1 MB").arg(s ) ); it->setTextAlignment ( 1,Qt::AlignRight | Qt::AlignVCenter ); it->setTextAlignment ( 2,Qt::AlignRight | Qt::AlignVCenter ); it->setText(2,title2->getChapter(i)->getLength().toString("h:mm:ss")); chItems.append ( it ); it->mainTitle=_title; } } } /** No descriptions */ void k9Main::addTitle ( k9DVDTitle *track ) { const int col1 =0; const int col2 =1; const int col3 =3; const int col4= 2; k9DVDAudioStream *l_auds; k9DVDSubtitle *l_sub; int i; QString c,ch; listView1->setRootIsDecorated ( true ); LvItem * itemTrack = new LvItem ( tsItems.at ( track->getVTS()-1 ),TITLE ); itemTrack->setExpanded ( false ); itemTrack->setText ( col1,track->getname() ); itemTrack->setFlags ( itemTrack->flags() | Qt::ItemIsEditable ); itemTrack->setIcon ( col1,SmallIcon ( "title" ) ); c.sprintf ( "%.2f ", track->gettotalsize_mb() ); itemTrack->setText ( col2,c+i18n ( "MB" ) ); itemTrack->setText (col4,track->gettotallength().toString ( "h:mm:ss" )); itemTrack->setTextAlignment ( col2,Qt::AlignRight|Qt::AlignVCenter ); itemTrack->setTextAlignment ( col4,Qt::AlignRight|Qt::AlignVCenter ); itemTrack->obj=track; addChapters ( itemTrack,track ); ckLvItem *video; video=new ckLvItem ( itemTrack,this,STREAM ); video->streamType=VID; video->setIcon ( 0,SmallIcon ( "video" ) ); addListItem ( track,video,VID ); video->setExpanded ( false ); c=i18n ( "video %1 ").arg(track->getformat() ); c.append ( " - " + track->getaspectRatio() ); video->setText ( col1, c ); if ( track->gettotalvideosize_mb() ) { c.sprintf ( "%.2f ", track->gettotalvideosize_mb() ); video->setText ( col2,c +i18n ( "MB" ) ); video->setTextAlignment ( col2,Qt::AlignRight ); } video->obj=track; for ( i=0;i< track->getaudioStreamCount();i++ ) { l_auds=track->getaudioStream ( i ); c=i18n ( "audio %1 ").arg(i+1 ); c.append ( l_auds->getlanguage() + " " +l_auds->getformat() +" " ); ch.sprintf ( "%dch ",l_auds->getchannels() ); c.append ( ch+l_auds->getfrequency() +" "+l_auds->getquantization() ); ckLvItem * item = new ckLvItem ( itemTrack,this,STREAM ); item->setIcon ( 0,SmallIcon ( "sound" ) ); item->streamType=AUD; item->language=l_auds->getlanguage(); addListItem ( l_auds,item,AUD ); item->setText ( col1, c ); if ( l_auds->getsize_mb() ) { c.sprintf ( "%.2f ", l_auds->getsize_mb()); item->setText ( col2,c +i18n ( "MB" ) ); item->setTextAlignment ( col2,Qt::AlignRight ); } item->setText ( col3,l_auds->getcontent() ); item->obj=track; item->stream=l_auds; } for ( i=0;i< track->getsubPictureCount();i++ ) { l_sub=track->getsubtitle ( i ); c=i18n ( "subpicture %1 ").arg(i+1 ); c.append ( l_sub->getlanguage() ); ckLvItem * item = new ckLvItem ( itemTrack,this,STREAM ); item->setIcon ( 0,SmallIcon ( "subtitle" ) ); item->streamType=SUB; item->language=l_sub->getlanguage(); addListItem ( l_sub,item,SUB ); item->setText ( col1, c ); if ( l_sub->getsize_mb() ) { c.sprintf ( "%.2f ", l_sub->getsize_mb()); item->setText ( col2,c +i18n ( "MB" ) ); item->setTextAlignment ( col2,Qt::AlignRight ); } item->setText ( col3, l_sub->getcontent() ); item->obj=track; item->stream=l_sub; } } /** No descriptions */ void k9Main::updateSelection() { QMap mAudio; QMap mSubp; k9DVDListItem *litem; for ( int i=0;istreamType) { case AUD: title=litem->audioStream->gettitle(); break; case SUB: title=litem->subtitle->gettitle(); break; case VID: title=litem->title; break; default: title=NULL; break; } bool singleAudio=(Ui_MainDlg.cbOutput->currentIndex()==oMP4) && (title->getEncOpt()->getEncoder()=="mencoder"); bool singleSubp=(Ui_MainDlg.cbOutput->currentIndex()==oMP4) && (title->getEncOpt()->getEncoder()=="mencoder"); bool noSubp=(Ui_MainDlg.cbOutput->currentIndex()==oMP4) && (title->getEncOpt()->getEncoder()=="ffmpeg") && (!Ui_MainDlg.urOutput->url().path().endsWith(".mkv")); switch ( litem->streamType ) { case SUB: k9DVDSubtitle *l_sub; l_sub=litem->subtitle; if (singleSubp && mSubp.contains(title->getnumTitle())) litem->listItem->setOn(false); if (noSubp) litem->listItem->setOn(false); if (litem->listItem->isOn()) mSubp[title->getnumTitle()]=1; l_sub->setselected ( litem->listItem->isOn() ); break; case AUD: k9DVDAudioStream *l_auds; l_auds=litem->audioStream; if (singleAudio && mAudio.contains(title->getnumTitle())) litem->listItem->setOn(false); if (litem->listItem->isOn()) mAudio[title->getnumTitle()]=1; l_auds->setselected ( litem->listItem->isOn() ); break; case VID : k9DVDTitle *l_title; l_title=litem->title; l_title->setvideoSelected ( litem->listItem->isOn() ); //if title is not selected => shrink factor is not forced if ( !l_title->isSelected() ) l_title->setforceFactor ( false ); break; default : break; } } bool supdating=updating; updating=true; for ( int i=0;iobj; it->setOn ( c->getSelected() ); } updating=supdating; } void k9Main::checkLang ( QString lang,eStreamType streamType,bool state ) { updating =true; for ( int i=0;istreamType == streamType ) { switch ( litem->streamType ) { case SUB: k9DVDSubtitle *l_sub; l_sub=litem->subtitle; if ( l_sub->getlanguage() == lang ) { l_sub->setselected ( state ); litem->listItem->setOn ( state ); checked=state; k9DVDTitle *title= ( k9DVDTitle* ) litem->listItem->obj; ckLvItem * itemtitleset= ( ckLvItem* ) litem -> listItem->parent()->parent(); itemtitleset->setOn ( title->gettitleset()->getselected() ); } break; case AUD: k9DVDAudioStream *l_auds; l_auds=litem->audioStream; if ( l_auds->getlanguage() == lang ) { l_auds->setselected ( state ); litem->listItem->setOn ( state ); checked=state; k9DVDTitle *title= ( k9DVDTitle* ) litem->listItem->obj; ckLvItem * itemtitleset= ( ckLvItem* ) litem -> listItem->parent()->parent(); itemtitleset->setOn ( title->gettitleset()->getselected() ); } break; default: break; } //we must check the video item if ( checked ) { for ( int j=0; jlistItem->parent() ==litem->listItem->parent() && litem2->streamType==VID ) { litem2->title->setvideoSelected ( state ); litem2->listItem->setOn ( state ); } } } } } m_playbackOptions->fillTitleList(); updating=false; emit SelectionChanged ( dvd,withMenus() ); } void k9Main::checkTitle ( bool state, ckLvItem *_item ) { m_update->wait(); k9DVDListItem *litem; updating=true; k9DVDTitle *title; if ( _item->streamType==CHAP ) { k9DVDChapter *c= ( k9DVDChapter* ) _item->obj; c->setSelected ( state ); //title=c->getTitle(); title=_item->mainTitle; for ( int i=0;ititle && litem->streamType==VID ) litem->listItem->setOn ( state ); } } else title= ( k9DVDTitle* ) _item->obj; bool singleAudio=(Ui_MainDlg.cbOutput->currentIndex()==oMP4) && (title->getEncOpt()->getEncoder()=="mencoder"); bool singleSubp=(Ui_MainDlg.cbOutput->currentIndex()==oMP4) && (title->getEncOpt()->getEncoder()=="mencoder"); //bool noSubp=(Ui_MainDlg.cbOutput->currentIndex()==oMP4) && (title->getEncOpt()->getEncoder()=="ffmpeg") && (!Ui_MainDlg.urOutput->url().fileName().endsWith(".mkv")); for ( int i=0;ilistItem->parent() == _item->parent() ) { //if current item is video and is unchecked, uncheck audio and subtitles if ( !state && _item->streamType==VID ) { switch ( litem->streamType ) { case SUB: k9DVDSubtitle *l_sub; l_sub=litem->subtitle; litem->listItem->setOn (state); l_sub->setselected ( state); break; case AUD: k9DVDAudioStream *l_auds; l_auds=litem->audioStream; litem->listItem->setOn ( state); l_auds->setselected ( state); break; default: break; } } else if ( litem->streamType == VID && state && ( _item->streamType==SUB || _item->streamType==AUD ) ) { litem->title->setvideoSelected ( state ); litem->listItem->setOn ( state ); } else if ( litem->streamType == AUD && state && _item->streamType==AUD && litem->listItem !=_item) { if (singleAudio) { k9DVDAudioStream *l_auds; l_auds=litem->audioStream; litem->listItem->setOn ( !state); l_auds->setselected ( !state); } } else if ( litem->streamType == SUB && state && _item->streamType==SUB && litem->listItem !=_item) { if (singleSubp) { k9DVDSubtitle *l_subp; l_subp=litem->subtitle; litem->listItem->setOn ( !state); l_subp->setselected ( !state); } } } } updateSelection(); k9DVDTitleset * titleset=NULL; titleset=title->gettitleset(); m_langSelect->update(); //check the titleset checkbox if ( titleset!=NULL ) { ckLvItem * itemtitleset; if ( _item->streamType==CHAP ) itemtitleset= ( ckLvItem* ) _item->parent()->parent()->parent(); else itemtitleset= ( ckLvItem* ) _item->parent()->parent(); itemtitleset->setOn ( titleset->getselected() ); } m_playbackOptions->fillTitleList(); updating=false; emit SelectionChanged ( dvd,withMenus() ); } void k9Main::checkAll ( bool state ) { k9DVDListItem *litem; updating=true; k9Config config; for ( int i=0;istreamType ) { case SUB: if ( state ) litem->listItem->setOn (config.getPrefSubtitleLang().contains(litem->subtitle->getlangCod()) || (config.getPrefSubtitleLang().count()==0)); else litem->listItem->setOn ( state ); break; case AUD: if ( state ) litem->listItem->setOn ( config.getPrefAudioLang().contains( litem->audioStream->getlangCod() ) || (config.getPrefAudioLang().count()==0)); else litem->listItem->setOn ( state ); break; case VID: { k9DVDTitle * l_title; l_title=litem->title; // l_title->setforceSelection(state); litem->listItem->setOn ( state ); // k9DVDTitle *title=(k9DVDTitle*)litem->listItem->obj; ckLvItem * itemtitleset= ( ckLvItem* ) litem -> listItem->parent()->parent(); l_title->gettitleset()->setselected ( state ); itemtitleset->setOn ( l_title->gettitleset()->getselected() ); } break; default: break; } } //m_langSelect->selectAll(state); updateSelection(); m_langSelect->update(); m_playbackOptions->fillTitleList(); updating=false; emit SelectionChanged ( dvd,withMenus() ); } void k9Main::checkTS ( bool _state,ckLvItem *_item ) { k9DVDTitleset *titleset = ( k9DVDTitleset* ) _item->obj; titleset->setselected ( _state ); k9DVDListItem *litem; k9Config config; updating=true; for ( int i=0;ilistItem->parent ()->parent() == _item ) { switch ( litem->streamType ) { case SUB: if ( _state ) litem->listItem->setOn ( config.getPrefSubtitleLang().contains( litem->subtitle->getlangCod()) || (config.getPrefSubtitleLang().count()==0)); else litem->listItem->setOn ( _state ); break; case AUD: if ( _state ) litem->listItem->setOn ( config.getPrefAudioLang().contains( litem->audioStream->getlangCod()) || (config.getPrefAudioLang().count()==0)); else litem->listItem->setOn ( _state ); break; default : litem->listItem->setOn ( _state ); break; } } } m_langSelect->update(); updateSelection(); m_playbackOptions->fillTitleList(); updating=false; emit SelectionChanged ( dvd,withMenus() ); } void k9Main::expanded ( QTreeWidgetItem *item ) { if ( item->type() ==1001 ) { ckLvItem *ckit = ( ckLvItem* ) item; if ( ckit->objectType==TITLESET ) ckit->setIcon ( 0,SmallIcon ( "folder-open" ) ); } // listView1->resizeColumnToContents(0); resizeColumns(); } void k9Main::collapsed ( QTreeWidgetItem *item ) { if ( item->type() ==1001 ) { ckLvItem *ckit = ( ckLvItem* ) item; if ( ckit->objectType==TITLESET ) ckit->setIcon ( 0,SmallIcon ( "folder" ) ); } resizeColumns(); } /** No descriptions */ void k9Main::itemRenamed ( QTreeWidgetItem * item,int ) { k9DVDTitle *t=NULL; QString newText; if ( item->type() ==1000 ) { LvItem *it = ( LvItem* ) item; t= ( k9DVDTitle* ) it->obj; newText=it->text ( 0 ); } else if ( item->type() ==1001 ) { ckLvItem *ckit = ( ckLvItem* ) item; t= ( k9DVDTitle* ) ckit->obj; newText=ckit->text ( 0 ); if ( !ckit->renamed ( newText ) ) return; } QString c; if ( t !=NULL ) { //QMessageBox::critical( this, "test", c.sprintf("%d",it->tag)); t->setname ( newText ); m_playbackOptions->titleRenamed ( t,newText ); } else dvd->setDVDTitle ( item->text ( 0 ) ); } /** No descriptions */ void k9Main::readSettings() { readDrives(); k9Config config; config.read(); m_prefOutput=config.getPrefOutput(); if (config.getInputDev() <100) { Ui_MainDlg.cbInputDev->setCurrentIndex (config.getInputDev() ); Ui_MainDlg.cbInput->setCurrentIndex (iDVD ); } else Ui_MainDlg.cbInput->setCurrentIndex (config.getInputDev() -100 ); if (config.getOutputDev() <100 ) { Ui_MainDlg.cbOutputDev->setCurrentIndex ( config.getOutputDev() ); Ui_MainDlg.cbOutput->setCurrentIndex ( oDVD ); } else Ui_MainDlg.cbOutput->setCurrentIndex ( config.getOutputDev() - 100); m_prefK3b=config.getPrefK3b(); m_prefAutoBurn=config.getPrefAutoBurn(); m_quickScan=config.getQuickScan(); m_prefSize=config.getPrefSize(); //fill the burn speed combo //cbOutputDevActivated( cbOutputDev->currentItem()); cbOutputDevActivated ( config.getOutputDev() ); //m_useDvdAuthor=settings.readBoolEntry("/options/useDvdAuthor",true); m_useDvdAuthor=config.getUseDvdAuthor(); for (int i=0; isetColumnHidden(i,!config.getPrefColumns().at(i)); } } /** No descriptions */ void k9Main::saveSettings() { k9Config config; config.read(); int inputDev=Ui_MainDlg.cbInput->currentIndex() ; inputDev= inputDev==iDVD?Ui_MainDlg.cbInput->currentIndex(): inputDev+100; int outputDev=Ui_MainDlg.cbOutput->currentIndex() ; outputDev= outputDev==oDVD?Ui_MainDlg.cbOutputDev->currentIndex(): outputDev+100; config.setInputDev ( inputDev); config.setOutputDev ( outputDev ); config.setKeepMenus ( withMenus() ); QList cols; for (int i=0;i columnCount();i++) { cols << !listView1->isColumnHidden(i); } config.setPrefColumns(cols); config.save(); } /** No descriptions */ void k9Main::bSaveClick() { saveSettings(); } /** No descriptions */ void k9Main::PreviewTitle() { if ( listView1->currentItem() ==NULL ) return; if ( listView1->currentItem()->type() ==0 ) return; int rtti=listView1->currentItem()->type(); void *obj; if ( rtti==1000 ) { LvItem *it= ( LvItem* ) listView1->currentItem(); obj=it->obj; } else { ckLvItem *it= ( ckLvItem* ) listView1->currentItem(); if ( it->objectType ==TITLESET ) return; obj=it->obj; } if ( obj !=NULL ) { k9DVDTitle *t; ckLvItem *it= ( ckLvItem* ) listView1->currentItem(); int chapter=1; if ( it->objectType==CHAPTER ) { k9DVDChapter *c= ( k9DVDChapter* ) obj; t=c->getTitle(); chapter=c->getnum(); } else t= ( k9DVDTitle* ) obj; //viewer->show(); //viewer->open(dvd,t); emit showPreview ( dvd,t,chapter ); } } void k9Main::CreateMP4() { k9ExecCopy execCopy; execCopy.setDvd ( dvd ); execCopy.setPath(Ui_MainDlg.urOutput->url().path()); execCopy.CreateMP4(); changeStatusbar ( i18n ( "Ready" ) ,sbMessage ); } void k9Main::extractAudio() { k9ExecCopy execCopy; execCopy.setDvd ( dvd ); execCopy.setPath(Ui_MainDlg.urOutput->url().path()); execCopy.extractAudio(); changeStatusbar ( i18n ( "Ready" ) ,sbMessage ); } void k9Main::extractMPEG2() { k9ExecCopy execCopy; execCopy.setDvd ( dvd ); execCopy.setPath(Ui_MainDlg.urOutput->url().path()); execCopy.extractMPEG2(); changeStatusbar ( i18n ( "Ready" ) ,sbMessage ); } void k9Main::deviceAdded ( k9CdDrive *_drive ) { addDrive ( _drive ); } void k9Main::deviceRemoved ( k9CdDrive *_drive ) { if ( _drive->device == dvd->getDevice() ) closeDVD(); int i=driveList.indexOf ( _drive ); driveList.removeAt ( i ); Ui_MainDlg.cbInputDev->removeItem ( i ); i=recorderList.indexOf ( _drive ); recorderList.removeAt ( i ); Ui_MainDlg.cbOutputDev->removeItem ( i ); } void k9Main::addDrive ( k9CdDrive *drive ) { #ifdef HAVE_HAL_H if ( drive->getDevice() !=NULL ) { k9HalDevice *dev=drive->getDevice(); connect ( dev,SIGNAL ( volumeChanged ( const QString &,const QString & ) ),this,SLOT ( volumeChanged ( const QString&,const QString& ) ) ); } #else connect ( drive,SIGNAL ( volumeChanged ( const QString &,const QString & ) ),this,SLOT ( volumeChanged ( const QString&,const QString& ) ) ); #endif if ( drive->canReadDVD ) { QString c ( drive->name + " ("+drive->device+")" ); Ui_MainDlg.cbInputDev->addItem ( c,drive->device ); driveList.append ( drive ); } if ( drive->canWriteDVD ) { Ui_MainDlg.cbOutputDev->addItem ( drive->name+ " ("+drive->device+")",drive->device ); recorderList.append ( drive ); } } /*! \fn k9Main::readDrives() */ void k9Main::readDrives() { bool ready=m_ready; m_ready=false; Ui_MainDlg.cbInputDev->clear(); Ui_MainDlg.cbOutputDev->clear(); driveList.clear(); recorderList.clear(); drives->scanDrives(); m_ready=ready; } void k9Main::volumeChanged ( const QString &device,const QString &volumeName ) { if (!m_ready) return; if ( device==dvd->getDevice() && dvd->getopened() && volumeName=="" ) closeDVD(); else if ( !dvd->getopened() && volumeName !="" && getDevice ( Ui_MainDlg.cbInputDev ) ==device && Ui_MainDlg.cbInput->currentIndex()==iDVD) { Open(); } } /*! \fn k9Main::listView1CurrentChanged( QListViewItem *newItem ) */ void k9Main::listView1CurrentChanged ( QTreeWidgetItem *newItem,QTreeWidgetItem* ) { if ( newItem == NULL ) { m_playbackOptions->enable ( false ); return; } else { if ( !withMenus() ) { m_playbackOptions->enable ( true ); } } k9DVDTitle *title=NULL; if ( newItem->type() ==1000 ) { LvItem *it = ( LvItem* ) newItem; title= ( k9DVDTitle* ) it->obj; } else if ( newItem->type() ==1001 ) { ckLvItem *ckit = ( ckLvItem* ) newItem; if ( ckit->objectType!=TITLESET ) { if ( ( ( ckLvItem* ) newItem )->streamType==CHAP ) { LvItem *parent= ( LvItem* ) ( ckit->parent()->parent() ); title= ( k9DVDTitle* ) parent->obj; } else title= ( k9DVDTitle* ) ckit->obj; } } if ( title !=NULL ) { emit changedTitle ( title ); PreviewTitle(); } } void k9Main::closeDVD() { //viewer->bStopClick(); emit stopPreview(); emit changedTitle ( NULL ); emit SelectionChanged ( NULL,withMenus() ); changeStatusbar ( "",sbFactor ); changeStatusbar ("",sbSelSize); changeStatusbar ( "",sbMessage ); listView1->clear(); clearItems(); m_langSelect->clear(); dvd->close(); m_parent->setDvdOpened(false); } bool k9Main::compare ( double v1,double v2 ) { if ( v1 >v2 ) return true; if ( v1= recorderList.count() || _index <0) return; k9CdDrive * drive= ( k9CdDrive* ) recorderList.at ( _index); if ( drive !=NULL ) { QList list=drive->getWriteSpeeds(); Ui_MainDlg.cbBurnSpeed->clear(); Ui_MainDlg.cbBurnSpeed->addItem ( i18n ( "default" ) ); foreach ( int speed,list ) { Ui_MainDlg.cbBurnSpeed->addItem ( QString::number ( ( double ) ( speed ) /1385 ) ); } #if QT_VERSION >= 0x050000 Ui_MainDlg.urOutput->setMode(KFile::Directory); #else Ui_MainDlg.urOutput->setMode(KFile::Directory); #endif #if QT_VERSION >= 0x050000 Ui_MainDlg.urOutput->setUrl(QUrl(drive->device)); #else Ui_MainDlg.urOutput->setUrl(KUrl(drive->device)); #endif } } void k9Main::bInputOpenClick() { QString result=k9Dialogs::getOpenFileName ( QDir::homePath(),"*.iso", 0,i18n ( "Open ISO Image" ) ); if ( result!="" ) { k9Tools::setComboText ( Ui_MainDlg.cbInputDev,result ); Open(); } } void k9Main::bInputOpenDirClick() { QString result= k9Dialogs::getExistingDirectory ( QDir::homePath() ); //KDirSelectDialog::selectDirectory (QDir::homePath(), false, this,i18n("Open DVD folder")).path(); if ( result!="" ) { k9Tools::setComboText ( Ui_MainDlg.cbInputDev,result ); Open(); } } long k9Main::getFreeSpace ( const QString & _path ) { long fs=k9Tools::getFreeSpace ( _path ); if ( fs!=-1 ) { return fs; } else return -1; } void k9Main::setInput ( QString _input ) { bool found=false; for ( int i=0;i< driveList.count();i++ ) { k9CdDrive *drive= ( k9CdDrive* ) driveList.at ( i ); if ( drive->device == _input ) { Ui_MainDlg.cbInputDev->setCurrentIndex ( i ); Ui_MainDlg.cbInput->setCurrentIndex(iDVD); found=true; } } if ( !found ) { #if QT_VERSION >= 0x050000 Ui_MainDlg.urInput->setUrl(_input ); #else Ui_MainDlg.urInput->setUrl(KUrl(_input) ); #endif Ui_MainDlg.cbInput->setCurrentIndex(iFolder); } } void k9Main::setOutput ( QString _output ) { Ui_MainDlg.cbOutputDev->setCurrentIndex ( 0 ); for ( int i=0 ;i device ); // qDebug ("output=" +c); if ( c==_output ) { Ui_MainDlg.cbOutputDev->setCurrentIndex ( i ); break; } } } void k9Main::Clone ( QString _input,QString _output ) { setInput ( _input ); setOutput ( _output ); m_playbackOptions->setwithMenus ( true ); m_quickScan=true; Open(); checkAll ( true ); Copy(); } void k9Main::updateFactor() { // m_update->updateFactor(); updateFactor_internal(); } void k9Main::updateFactor_internal() { if ( dvd->getopened() && m_mutex.tryLock() ) { updateSelection(); setDVDSize(); double dbfactor=dvd->getfactor ( withMenus(),true,m_useDvdAuthor ); // Ui_MainDlg.factor->setValue((int) ( dbfactor*100)-100 ); uint64_t sizeSelected=dvd->getsizeSelected ( FALSE ); if ( sizeSelected ==0 ) { changeStatusbar ( "",sbFactor ); changeStatusbar ( "",sbSelSize ); } else { changeStatusbar ( QString::number ( dbfactor,'f',2 ),sbFactor ); changeStatusbar ( i18n("%1 MB").arg(QString::number ((double)sizeSelected/512.,'f',2)),sbSelSize); } emit SelectionChanged ( dvd,withMenus() ); m_mutex.unlock(); } } bool k9Main::withMenus() { return m_playbackOptions->withMenus(); } void k9Main::setDrives ( k9CdDrives* _value ) { drives = _value; } void k9Main::cbInputChanged(int _index) { switch (_index) { case iDVD: //DVD Ui_MainDlg.cbInputDev->show(); Ui_MainDlg.urInput->hide(); break; case iISO: //Iso Image Ui_MainDlg.cbInputDev->hide(); Ui_MainDlg.urInput->show(); Ui_MainDlg.urInput->setMode(KFile::ExistingOnly | KFile::File); #if QT_VERSION >= 0x050000 // Qt5 code Ui_MainDlg.urInput->fileDialog()->setAcceptMode(QFileDialog::AcceptOpen); #else() // Qt4 Code Ui_MainDlg.urInput->fileDialog()->setOperationMode(KFileDialog::Opening); #endif() Ui_MainDlg.urInput->setFilter("*.iso|Iso Image (*.iso)"); break; case iFolder: //Folder Ui_MainDlg.cbInputDev->hide(); Ui_MainDlg.urInput->show(); Ui_MainDlg.urInput->setMode(KFile::ExistingOnly | KFile::Directory); #if QT_VERSION >= 0x050000 // Qt5 Code Ui_MainDlg.urInput->fileDialog()->setAcceptMode(QFileDialog::AcceptOpen); #else // Qt4 Code Ui_MainDlg.urInput->fileDialog()->setOperationMode(KFileDialog::Opening); #endif break; } } void k9Main::cbOutputChanged(int _index) { k9Config config; QString title=dvd->getDVDTitle(); title= title.isEmpty() ? i18n("unknown"):title; m_parent->updateDock(_index); switch (_index) { case oDVD: Ui_MainDlg.wOutput->show(); Ui_MainDlg.urOutput->hide(); break; case oISO: Ui_MainDlg.wOutput->hide(); Ui_MainDlg.urOutput->show(); Ui_MainDlg.urOutput->setMode( KFile::File); #if QT_VERSION >= 0x050000 // Qt5 Code Ui_MainDlg.urOutput->fileDialog()->setAcceptMode(QFileDialog::AcceptSave); #else // Qt4 Code Ui_MainDlg.urOutput->fileDialog()->setOperationMode(KFileDialog::Saving); #endif Ui_MainDlg.urOutput->setFilter("*.iso|Iso Image (*.iso)"); #if QT_VERSION >= 0x050000 Ui_MainDlg.urOutput->setUrl(QUrl(QDir::cleanPath(config.getPrefOutputIso()+"/"+title+".iso") )); #else Ui_MainDlg.urOutput->setUrl(KUrl(QDir::cleanPath(config.getPrefOutputIso()+"/"+title+".iso") )); #endif break; case oFolder: case oAudio: Ui_MainDlg.wOutput->hide(); Ui_MainDlg.urOutput->show(); Ui_MainDlg.urOutput->setMode( KFile::Directory); #if QT_VERSION >= 0x050000 //Qt5 Code Ui_MainDlg.urOutput->fileDialog()->setAcceptMode(QFileDialog::AcceptSave); #else Ui_MainDlg.urOutput->fileDialog()->setOperationMode(KFileDialog::Saving); #endif #if QT_VERSION >= 0x050000 Ui_MainDlg.urOutput->setUrl(QUrl(QDir::cleanPath(_index==oAudio?config.getPrefOutputAudio():config.getPrefOutput()))); #else Ui_MainDlg.urOutput->setUrl(KUrl(QDir::cleanPath(_index==oAudio?config.getPrefOutputAudio():config.getPrefOutput()))); #endif break; case oMP4: Ui_MainDlg.wOutput->hide(); Ui_MainDlg.urOutput->show(); Ui_MainDlg.urOutput->setFilter("*.avi|Audio Video Interleave (*.avi)\n*.mpg|MPEG-1 and MPEG-2 systems (*.mpg)\n*.mp4|MPEG-4 format (*.mp4)\n*.asf|Advanced Streaming Format (*.asf)\n*.swf|Adobe Flash (*.swf)\n*.flv|Adobe Flash video files (*.flv)\n*.rm|RealVideo (*.rm)\n*.mov|QuickTime (*.mov)\n*.mkv|Matroska (*.mkv)"); Ui_MainDlg.urOutput->setMode(KFile::File) ; #if QT_VERSION >= 0x050000 // Qt5 Code Ui_MainDlg.urOutput->fileDialog()->setAcceptMode(QFileDialog::AcceptSave); #else Ui_MainDlg.urOutput->fileDialog()->setOperationMode(KFileDialog::Saving); #endif #if QT_VERSION >= 0x050000 Ui_MainDlg.urOutput->setUrl(QUrl(QDir::cleanPath(config.getPrefOutputMpeg4()+"/"+title+".avi") )); #else Ui_MainDlg.urOutput->setUrl(KUrl(QDir::cleanPath(config.getPrefOutputMpeg4()+"/"+title+".avi") )); #endif break; case oMPEG2: Ui_MainDlg.wOutput->hide(); Ui_MainDlg.urOutput->show(); Ui_MainDlg.urOutput->setFilter("*.mpg|MPEG-1 and MPEG-2 systems (*.mpg)"); Ui_MainDlg.urOutput->setMode(KFile::File) ; #if QT_VERSION >= 0x050000 // Qt5 Code Ui_MainDlg.urOutput->fileDialog()->setAcceptMode(QFileDialog::AcceptSave); #else // Qt4 Code Ui_MainDlg.urOutput->fileDialog()->setOperationMode(KFileDialog::Saving); #endif #if QT_VERSION >= 0x050000 Ui_MainDlg.urOutput->setUrl(QUrl(QDir::cleanPath(config.getPrefOutputMpeg2()+"/"+title+".mpg") )); #else Ui_MainDlg.urOutput->setUrl(KUrl(QDir::cleanPath(config.getPrefOutputMpeg2()+"/"+title+".mpg") )); #endif break; } updateSelection(); } void k9Main::showPopup(const QPoint & iPosition) { columns.clear(); QMenu menu(listView1); for (int i=1; i< listView1->columnCount() ;i++) { k9ListColumn *col=new k9ListColumn(listView1,i); columns << col; QAction *m=new QAction(listView1->headerItem()->text(i),this) ; m->setCheckable(true); m->setChecked(!listView1->isColumnHidden(i) ); connect(m, SIGNAL(toggled(bool)), col, SLOT(setVisible(bool))); menu.addAction(m); } menu.exec(listView1->mapToGlobal(iPosition)); } void k9ListColumn::setVisible(bool value) { QTreeWidget *parent=(QTreeWidget*)this->parent() ; parent->setColumnHidden(m_column,!value); k9Main* maindlg=(k9Main*)parent->parent(); maindlg->resizeColumns(); } k9copy/src/main/k9ffmpegcmdgen.h0000644000175000017550000000153312412271774017326 0ustar emulatoremulator// // C++ Interface: k9ffmpegcmdgen // // Description: // // // Author: <>, (C) 2009 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9FFMPEGCMDGEN_H #define K9FFMPEGCMDGEN_H #include "k9common.h" #include "ui_ffmpegCmdGen.h" class k9ffmpegCmdGen : public QWidget { Q_OBJECT public: enum FFMpegCmdType {AUDIO,VIDEO}; k9ffmpegCmdGen(QWidget* parent = 0 ); ~k9ffmpegCmdGen(); /*$PUBLIC_FUNCTIONS$*/ static bool getFFMpegCmd(FFMpegCmdType _type,QString &_cmd); void show (FFMpegCmdType _type); void setCmd(const QString& theValue); QString getCmd() ; public slots: /*$PUBLIC_SLOTS$*/ private: Ui::ffmpegCmdGen Ui_ffmpegCmdGen; FFMpegCmdType m_type; QString m_cmd; QString m_codecs; void readCodecs(); protected slots: void getStdout(char*,int); }; #endif k9copy/src/main/ffmpegCmdGen.ui0000644000175000017550000010302512417731553017150 0ustar emulatoremulator ffmpegCmdGen 0 0 485 359 Form 0 0 0 0 0 Qt::ScrollBarAlwaysOn true 0 -278 449 596 0 0 Set the video bitrate in bit/s (default = 200 kb/s) b $VIDBRk k 0 100000 Set the number of video frames to record vframes 0 100000 Set frame rate (Hz value, fraction or abbreviation), (default = 25) r 0 100000 Set frame size. The format is `wxh' (ffserver default = 160x128, ffmpeg default = same as source) s true $WIDTHx$HEIGHT sqcif qcif cif 4cif qqvga qvga vga svga xga uxga qxga sxga qsxga hsxga wvga wsxga wuxga woxga wqsxga wquxga whuxga cga ega hd480 hd720 hd1080 Set aspect ratio (4:3, 16:9 or 1.3333, 1.7777) aspect true $ASPECT 4:3 16:9 Set top crop band size (in pixels) croptop $CROPTOP 0 100000 Set bottom crop band size (in pixels) cropbottom $CROPBOTTOM 0 100000 Set left crop band size (in pixels) cropleft $CROPLEFT 0 100000 Set right crop band size (in pixels). cropright Set right crop band size (in pixels) $CROPRIGHT 0 100000 Set top pad band size (in pixels) padtop 0 100000 Set bottom pad band size (in pixels) padbottom 0 100000 Qt::Horizontal QSizePolicy::Fixed 100 20 Set left pad band size (in pixels) padleft 0 100000 Set right pad band size (in pixels). padright Set right crop band size (in pixels) 0 100000 Set color of padded bands. The value for padcolor is expressed as a six digit hexadecimal number where the first two digits represent red, the middle two digits green and last two digits blue (default = 000000 (black)) padcolor HHHHHH; Set video bitrate tolerance (in bit/s) bt 0 100000 Set max video bitrate (in bit/s) maxrate 0 100000 Set min video bitrate (in bit/s) minrate 0 100000 Set video buffer verifier buffer size (in bits) bufsize 0 100000 Force video codec to codec. Use the copy special value to tell that the raw codec data must be copied as is vcodec true copy Use same video quality as source (implies VBR) sameq pass $PASS true passlogfile $PASSLOGFILE true threads 16 Qt::Vertical 20 18 0 0 75 true FFMpeg Video options Qt::ScrollBarAsNeeded true 0 0 309 195 0 111 Set the number of audio frames to record aframes 0 100000 Set the audio sampling frequency (default = 44100 Hz) ar 0 100000 44100 Set the audio bitrate in bit/s (default = 64k) ab $AUDBRk k 0 100000 Set the number of audio channels (default = 1) ac 1 7 Qt::Horizontal QSizePolicy::Fixed 100 37 Force audio codec to codec. Use the copy special value to specify that the raw codec data must be copied as is acodec true COPY Force audio tag/fourcc atag nnnnn; Bitstream filters absf dump_extra remove_extra noise mp3comp mp3decomp Qt::Vertical 105 13 0 0 75 true FFMpeg Audio options k9copy/src/main/k9copy.h0000644000175000017550000000673212412271774015664 0ustar emulatoremulator// // C++ Interface: k9copy // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef _K9COPY_H_ #define _K9COPY_H_ #include #include #include "k9common.h" #include "k9cddrive.h" #if QT_VERSION >= 0x050000 #include #include #include #else #include #include #include #endif #include #include static QLabel *sbMessageQt,*sbFactorQt,*sbSelSizeQt; enum eStatusBarId {sbMessage=0,sbFactor=1,sbSelSize=2}; class k9Import; class k9Main; class kViewMPEG2; class k9PlaybackOptions; class k9LangSelect; class k9MP4Title; class k9TitleFactor; class k9MenuEdit; class k9NewTitle; class k9ChapterEdit; class QDockWidget; class k9ImportFiles; class k9Copy : public KXmlGuiWindow { Q_OBJECT friend class k9ImportFiles; public: /** * Default Constructor */ k9Copy(); void clone(QString _input,QString _output); void setInput(QString _input); void setOutput(QString _output); void updateDock(int _output); //KDockWidget* getVisibleDock(); //KMdiToolViewAccessor * setToolWindow(QWidget *_widget,KDockWidget::DockPosition _pos,const QString &tabToolTip,const QString &tabCaption) ; //void removeToolWindow(KMdiToolViewAccessor *toolWin); /** * Default Destructor */ virtual ~k9Copy(); protected: bool queryClose( ); void closeEvent( QCloseEvent* ce ); private slots: void ActionCopy(); void ActionMP4(); void ActionMPEG(); void ActionEject(); void ActionBackup(); void ActionAuthor(); void ActionPlayTitle(); void ActionCreate(); void ActionWizard(); void changeStatusbar(const QString& text,int id); void changeCaption(const QString& text); void optionsConfigureKeys(); void optionsConfigureToolbars(); void newToolbarConfig(); void setGtkStyle(bool); public slots: void fileOpen(); void preferences(); void quit(); void setActions(bool enabled); void setDvdOpened(bool _state); private: void setupAccel(); void setupActions(); void initCodecs(); void createImportWindows(); void createCopyWindows(); void removeToolWindows(); void saveDock(); bool foundGtkStyle(); #if QT_VERSION >= 0x050000 QAction *CopyAction; QAction *PlayTitleAction; QAction *ejectAction; QAction *backupAction; QAction *authorAction; QAction *wizardAction; #else KAction *CopyAction; KAction *PlayTitleAction; KAction *ejectAction; KAction *backupAction; KAction *authorAction; KAction *wizardAction; #endif private: k9Main *m_k9Main; // KMdiChildView *m_k9MainView,*m_k9ImportView; // KMdiToolViewAccessor *m_previewAcc; k9PlaybackOptions *m_options; k9TitleFactor *m_factors; k9LangSelect *m_lang; k9MP4Title *m_mp4; QWidget *m_mp2; k9MenuEdit *m_menuEdit; k9NewTitle *m_newTitle; k9ChapterEdit *m_chapterEdit; k9ImportFiles *m_import; bool m_useXine; bool m_usePhonon; bool m_useMplayer; bool m_useDvdAuthor; QMap m_actions; //QPtrList m_ToolViews; k9CdDrives *m_drives; QDockWidget *m_dockPreview; QDockWidget *m_dockMP4; QDockWidget *m_dockFactor; QDockWidget *m_dockPlayback; QString m_style; }; #endif k9copy/src/main/k9settings.h0000644000175000017550000000176712412271774016555 0ustar emulatoremulator// // C++ Interface: k9settings // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9SETTINGS_H #define K9SETTINGS_H #include "k9common.h" #include "k9prefdvd.h" #include "k9prefmpeg4.h" #include "k9prefmencoder.h" #include "k9prefpreview.h" #include "kconfigdlg.h" #include "k9prefauthor.h" #include "k9prefdirs.h" #include /** @author Jean-Michel PETIT */ class k9Settings:public KPageDialog{ Q_OBJECT public: k9Settings(QWidget *parent,const QString &caption); virtual ~k9Settings(); private: k9prefDVD *m_prefDVD; k9prefMPEG4 *m_prefMPEG4; k9prefMencoder *m_prefMencoder; k9prefPreview *m_prefPreview; kConfigDlg *m_configDlg; k9prefAuthor *m_prefAuthor; k9prefDirs *m_prefDirs; private slots: void slotOkClicked(); void slotApplyClicked(); }; #endif k9copy/src/main/mencoderCmdGen.ui0000644000175000017550000000200012417731553017467 0ustar emulatoremulator mencoderCmdGen 0 0 649 492 MEncoder options 1 kpushbutton.h kpushbutton.h k9copy/src/main/k9settings.cpp0000644000175000017550000000724712412271774017107 0ustar emulatoremulator// // C++ Implementation: k9Settings // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9settings.h" #include #include #include #if QT_VERSION >= 0x050000 #include #include #include #include #else #include #include #include #include #include #endif //Qt5 Code #include k9Settings::k9Settings(QWidget *parent,const QString &): KPageDialog (parent) { setFaceType(KPageDialog::List); #if QT_VERSION >= 0x050000 //Qt5 Code setStandardButtons( QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Apply ); #else // Qt4 Code setButtons( Ok|Apply|Cancel); #endif setWindowTitle((i18n("Settings"))); //setButtons( Default|Ok|Apply|Cancel); //setInitialSize(QSize(750,350), false); KPageWidgetItem *page; m_prefDVD =new k9prefDVD(this); page = addPage(m_prefDVD,i18n("DVD")); page->setHeader(i18n("DVD Backup")); #if QT_VERSION >= 0x050000 page->setIcon(QIcon("dvdcopy")); #else page->setIcon(KIcon("dvdcopy")); #endif m_prefMencoder =new k9prefMencoder(this); page = addPage(m_prefMencoder,i18n("Encoders")); page->setHeader(i18n("MPEG-4 Codecs")); #if QT_VERSION >= 0x050000 page->setIcon(QIcon("mencoder")); #else page->setIcon(KIcon("mencoder")); #endif m_prefMPEG4 =new k9prefMPEG4(this); page = addPage(m_prefMPEG4,i18n("MPEG-4")); page->setHeader(i18n("MPEG-4 Encoding")); #if QT_VERSION >= 0x050000 page->setIcon(QIcon("video-mp4")); #else page->setIcon(KIcon("video-mp4")); #endif m_prefPreview =new k9prefPreview(this); page = addPage(m_prefPreview,i18n("Preview")); page->setHeader(i18n("Title preview")); #if QT_VERSION >= 0x050000 page->setIcon(QIcon("video-projector")); #else page->setIcon(KIcon("video-projector")); #endif m_prefAuthor = new k9prefAuthor(this); page = addPage(m_prefAuthor,i18n("Authoring")); page->setHeader(i18n("Authoring")); #if QT_VERSION >= 0x050000 page->setIcon(QIcon("author")); #else page->setIcon(KIcon("author")); #endif m_prefDirs=new k9prefDirs(this); page = addPage(m_prefDirs,i18n("Paths")); page->setHeader(i18n("Default paths")); #if QT_VERSION >= 0x050000 page->setIcon(QIcon("folder")); #else page->setIcon(KIcon("folder")); #endif m_configDlg=new kConfigDlg(this); page = addPage(m_configDlg,i18n("Devices")); page->setHeader(i18n("Devices not detected by k9copy")); #if QT_VERSION >= 0x050000 page->setIcon(QIcon("drive-optical")); #else page->setIcon(KIcon("drive-optical")); #endif #if QT_VERSION >= 0x050000 connect(buttonBox()->button(QDialogButtonBox::Apply),SIGNAL(clicked()), SLOT(slotApplyClicked())); connect(buttonBox()->button(QDialogButtonBox::Ok),SIGNAL(clicked()), SLOT(slotOkClicked())); #else connect(this, SIGNAL(applyClicked()), SLOT(slotApplyClicked())); connect(this, SIGNAL(okClicked()), SLOT(slotOkClicked())); #endif } void k9Settings::slotOkClicked() { qDebug() << "THIS IS THE SLOT/SIGNAL WORKING"; m_prefDVD->save(); m_prefMPEG4->save(); m_prefMencoder->save(); m_prefPreview->save(); m_prefAuthor->save(); m_configDlg->save(); m_prefDirs->save(); } void k9Settings::slotApplyClicked() { slotOkClicked(); m_prefMPEG4->load(); } k9Settings::~k9Settings() { /* delete m_configDlg; delete m_prefDVD; delete m_prefMPEG4; delete m_prefMencoder; delete m_prefPreview; */ } k9copy/src/main/prefpreview.ui0000644000175000017550000002771512417731553017177 0ustar emulatoremulator prefPreview 0 0 532 466 Form1 true &Internal Player Alt+I MPlayer Alt+M Phonon Xine Player Qt::Horizontal QSizePolicy::Expanding 230 21 0 0 QFrame::NoFrame QFrame::Plain 1 0 Qt::Vertical QSizePolicy::Expanding 21 30 Video output false 0 0 Audio output false X11 Xv OpenGL SDL 0 0 ALSA OSS SDL Qt::Horizontal QSizePolicy::Expanding 81 21 Qt::Vertical QSizePolicy::Expanding 20 21 75 true MPlayer options false 75 true Xine player options Video output false X11 Xv OpenGL SDL Qt::Horizontal QSizePolicy::Expanding 81 21 0 0 Audio output false 0 0 ALSA OSS Qt::Vertical QSizePolicy::Expanding 20 21 Qt::Vertical QSizePolicy::Expanding 246 101 rbInternal clicked() prefPreview rbInternalClick() 143 25 265 232 rbMplayer clicked() prefPreview rbMplayerClick() 143 54 265 232 rbPhonon clicked() prefPreview rbPhononClick() 143 112 265 232 rbXine clicked() prefPreview rbXineClick() 143 83 265 232 rbInternalClick() rbPhononClick() rbMplayerClick() rbXineClick() k9copy/src/main/k9prefmpeg4.cpp0000644000175000017550000001152112412271774017126 0ustar emulatoremulator// // C++ Implementation: // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9prefmpeg4.h" #include #include #include #include #include #include #include "k9audiocodecs.h" #include "k9videocodecs.h" k9prefMPEG4::k9prefMPEG4(QWidget* parent) : QWidget(parent) { Ui_prefMPEG4.setupUi(this); Ui_prefMPEG4.wCrop->hide(); load(); } void k9prefMPEG4::load() { //KSimpleConfig settings("K9Copy"); k9Config config; Ui_prefMPEG4.sbMp4Size->setValue(config.getPrefMp4Size()); Ui_prefMPEG4.sbMp4Size->setSuffix(" "+ i18n("MB")); Ui_prefMPEG4.sbMp4NumberCD->setValue(config.getPrefMp4NumberCD()); Ui_prefMPEG4.sbAudioGain->setValue(config.getPrefMp4AudioGain()); Ui_prefMPEG4.leMp4Width->setText(config.getPrefMp4Width()); Ui_prefMPEG4.leMp4Height->setText(config.getPrefMp4Height()); Ui_prefMPEG4.ckMp4AspectRatio->setChecked(config.getPrefMp4AspectRatio()); Ui_prefMPEG4.leMp4Height->setEnabled(!Ui_prefMPEG4.ckMp4AspectRatio->isChecked()); Ui_prefMPEG4.ck2passes->setChecked(config.getPrefMp42Passes()); Ui_prefMPEG4.leMp4AudioBitrate->setText(config.getPrefMp4AudioBitrate()); Ui_prefMPEG4.leMp4VideoBitrate->setText(config.getPrefMp4VideoBitrate()); k9AudioCodecs audioCodecs; k9VideoCodecs videoCodecs; QStringList encoders; for (int i=0;i clear(); Ui_prefMPEG4.cbEncoder->addItems(encoders); Ui_prefMPEG4.cbEncoder->setCurrentIndex(Ui_prefMPEG4.cbEncoder->findText(config.getPrefMp4Encoder())); cbEncoderActivated(Ui_prefMPEG4.cbEncoder->currentIndex()); Ui_prefMPEG4.cbMp4Codec->setCurrentIndex(config.getPrefMp4Codec()); Ui_prefMPEG4.cbMp4AudioCodec->setCurrentIndex(config.getPrefMp4AudioCodec()); Ui_prefMPEG4.ckUseCache->setChecked(config.getPrefUseCellCache()); if(config.getPrefMp4VideoBitrate() =="") Ui_prefMPEG4.rbSize->setChecked(true); else Ui_prefMPEG4.rbBitrate->setChecked(true); Ui_prefMPEG4.leMp4VideoBitrate->setEnabled(Ui_prefMPEG4.rbBitrate->isChecked()); Ui_prefMPEG4.sbMp4Size->setEnabled(Ui_prefMPEG4.rbSize->isChecked()); } k9prefMPEG4::~k9prefMPEG4() { } void k9prefMPEG4::save() { k9Config config; config.setPrefMp4Codec(Ui_prefMPEG4.cbMp4Codec->currentIndex()); config.setPrefMp4AudioCodec(Ui_prefMPEG4.cbMp4AudioCodec->currentIndex()); config.setPrefMp4Size( (int)Ui_prefMPEG4.sbMp4Size->value()); config.setPrefMp4Encoder(Ui_prefMPEG4.cbEncoder->currentText()); config.setPrefMp4NumberCD( (int)Ui_prefMPEG4.sbMp4NumberCD->value()); config.setPrefMp4AudioGain( (int)Ui_prefMPEG4.sbAudioGain->value()); config.setPrefMp4Width( Ui_prefMPEG4.leMp4Width->text()); config.setPrefMp4Height(Ui_prefMPEG4.leMp4Height->text()); config.setPrefMp4AspectRatio( Ui_prefMPEG4.ckMp4AspectRatio->isChecked()); config.setPrefMp4AudioBitrate( Ui_prefMPEG4.leMp4AudioBitrate->text()); config.setPrefMp4VideoBitrate( Ui_prefMPEG4.leMp4VideoBitrate->text()); config.setPrefMp42Passes(Ui_prefMPEG4.ck2passes->isChecked()); config.setPrefUseCellCache(Ui_prefMPEG4.ckUseCache->isChecked()); config.save(); } void k9prefMPEG4::ckMp4AspectRatioClick() { Ui_prefMPEG4.leMp4Height->setEnabled(!Ui_prefMPEG4.ckMp4AspectRatio->isChecked()); if (Ui_prefMPEG4.ckMp4AspectRatio->isChecked()) Ui_prefMPEG4.leMp4Height->setText(""); } void k9prefMPEG4::rgVideoSizeChanged(){ if (Ui_prefMPEG4.rbSize->isChecked()) Ui_prefMPEG4.leMp4VideoBitrate->setText(""); Ui_prefMPEG4.leMp4VideoBitrate->setEnabled(Ui_prefMPEG4.rbBitrate->isChecked()); Ui_prefMPEG4.sbMp4Size->setEnabled(Ui_prefMPEG4.rbSize->isChecked()); } void k9prefMPEG4::cbEncoderActivated(int _index) { k9AudioCodecs audioCodecs; k9VideoCodecs videoCodecs; Ui_prefMPEG4.cbMp4AudioCodec->clear(); Ui_prefMPEG4.cbMp4Codec->clear(); for (int i=0;i itemText(_index)) { Ui_prefMPEG4.cbMp4Codec->addItem(videoCodecs.getCodecName(i),i); } for (int i=0; i itemText(_index)) { Ui_prefMPEG4.cbMp4AudioCodec->addItem(audioCodecs.getCodecName(i),i); } Ui_prefMPEG4.cbMp4Codec->setCurrentIndex(0); cbMp4CodecActivated(0); Ui_prefMPEG4.cbMp4AudioCodec->setCurrentIndex(0); cbMp4AudioCodecActivated(0); } /*$SPECIALIZATION$*/ k9copy/src/main/langselectw.ui0000644000175000017550000000251212417731553017135 0ustar emulatoremulator langSelect 0 0 600 480 Selection 2 2 2 2 0 0 208 0 Languages k9copy/src/main/k9mencodercmdgen.h0000644000175000017550000000511012412271774017651 0ustar emulatoremulator// // C++ Interface: // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9MENCODERCMDGEN_H #define K9MENCODERCMDGEN_H #include "k9common.h" #include "ui_mencoderCmdGen.h" #include #include #include #include #include class _k9CheckListItem; class k9Grid:public QObject { public: k9Grid (int columns,QWidget *parent) :QObject(parent),m_columns(columns){ m_widget=new QFrame(); m_widget->resize(300,20); m_layout=new QGridLayout(m_widget); m_layout->setSpacing(2); m_col=0;m_row=0; m_rowHeight=0; }; void addWidget(QWidget *_widget) { int h=_widget->height(); m_rowHeight=qMax(h,m_rowHeight); _widget->setParent(m_widget); m_layout->addWidget(_widget,m_row,m_col); m_col++; if (m_col >=m_columns) { m_widget->resize(m_widget->width(),m_widget->height()+m_rowHeight); m_widget->setMinimumSize(0,m_widget->height()); m_col=0; m_row++; m_rowHeight=0; } } QWidget *widget() { return m_widget;} private: int m_columns; int m_col,m_row; int m_rowHeight; QFrame *m_widget; QGridLayout *m_layout; }; class k9MencoderCmdGen : public QWidget { Q_OBJECT public: k9MencoderCmdGen(QWidget* parent,const QString &_cmd,const QString &_encoder); ~k9MencoderCmdGen(); /*$PUBLIC_FUNCTIONS$*/ static bool getMencoderOptions(QString &_cmd,const QString &_encoder); public slots: /*$PUBLIC_SLOTS$*/ private: Ui::mencoderCmdGen Ui_mencoderCmdGen; QTreeWidget *listView; QStackedWidget *wsOptions; QScrollArea *m_scrollView; k9Grid *m_grid; k9Grid *m_hbox; int m_row,m_page,m_cpt; QDomDocument m_doc; QString m_cmd; QString m_encoder; void addWidgets(_k9CheckListItem *_item,QString _root,QString _cat); void loadXml(); void fillListView(); void addInt(QDomElement _eOpt); void addFloat(QDomElement _eOpt); void addBool(QDomElement _eOpt); void addString(QDomElement _eOpt); void addList(QDomElement _eOpt); const QString & getCmd(const QString &_root); void selectCodec(const QString &_root,const QString &_codec); void parseCodecOptions(const QString &_root,const QString &_codec,const QString & _options); void parseCmd(const QString &_cmd); protected: /*$PROTECTED_FUNCTIONS$*/ protected slots: /*$PROTECTED_SLOTS$*/ void listViewCurrentChanged(QTreeWidgetItem *,QTreeWidgetItem*); void listViewItemChanged(QTreeWidgetItem*,int); }; #endif k9copy/src/main/kconfigdlg.cpp0000644000175000017550000001456212412271774017110 0ustar emulatoremulator/************************************************************************** * Developer: Pauline123 , (C) 2014 * * * * Copyright (C) 2005 by Jean-Michel Petit * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "kconfigdlg.h" #include "kmessagebox.h" #include #if QT_VERSION >= 0X050000 #include #include #else // Qt4 #include #include #endif #include #if QT_VERSION >= 0x050000 #include #include #else #include #endif kConfigDlg::kConfigDlg(QWidget *parent) : QWidget(parent) { Ui_configDlg.setupUi(this); #if QT_VERSION >= 0x050000 setWindowTitle((i18n("Devices"))); #else setWindowTitle(KDialog::makeStandardCaption(i18n("Devices"),this)); #endif QStringList ldev; QStringList llabels; QStringList lIO; Ui_configDlg.tblDevices->setColumnWidth(0,150); Ui_configDlg.tblDevices->setColumnWidth(1,210); Ui_configDlg.tblDevices->setColumnWidth(2,40); Ui_configDlg.tblDevices->setColumnWidth(3,45); //KSimpleConfig settings("K9Copy"); k9Config config; ldev=config.getDevices(); llabels=config.getDevicesLabels(); lIO=config.getDevicesIO(); int row=0; foreach ( QString dev,ldev) { Ui_configDlg.tblDevices->setRowCount(row+1); QTableWidgetItem *item = new QTableWidgetItem(0); Ui_configDlg.tblDevices->setItem(row,0,item); item = new QTableWidgetItem(0); Ui_configDlg.tblDevices->setItem(row,1,item); Ui_configDlg.tblDevices->item(row,0)->setText(dev); QString it2=llabels.at(row); Ui_configDlg.tblDevices->item(row,1)->setText(it2); row++; } for ( int j = 0; j < Ui_configDlg.tblDevices->rowCount(); ++j ) { QTableWidgetItem *I = new QTableWidgetItem(0); Ui_configDlg.tblDevices->setItem(j,2,I); I->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); QTableWidgetItem *O = new QTableWidgetItem(0); Ui_configDlg.tblDevices->setItem(j,3,O); O->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); //QStringList::Iterator it=lIO.at(j); QString c=lIO[j]; if((c =="I") || (c =="IO")) I->setCheckState(Qt::Checked); if((c =="O") || (c =="IO")) O->setCheckState(Qt::Checked); // Ui_configDlg.tblDevices->setItem( j, 2, I ); // Ui_configDlg.tblDevices->setItem( j, 3, O); } // buttonCancel->setIcon(KStandardGuiItem::cancel().icon()); // buttonOk->setIcon(KStandardGuiItem::ok().icon()); connect(Ui_configDlg.bAdd,SIGNAL(clicked()),this,SLOT(bAddClick())); connect(Ui_configDlg.bRemove,SIGNAL(clicked()),this,SLOT(bRemoveClick())); #if QT_VERSION >= 0x050000 KGuiItem::assign(Ui_configDlg.bAdd, KStandardGuiItem::add() ); KGuiItem::assign(Ui_configDlg.bRemove, KStandardGuiItem::remove() ); #else Ui_configDlg.bAdd->setGuiItem(KStandardGuiItem::Add); Ui_configDlg.bRemove->setGuiItem(KStandardGuiItem::Remove); #endif } kConfigDlg::~kConfigDlg() {} /*! \fn kConfigDlg::bAddClick() */ void kConfigDlg::bAddClick() { Ui_configDlg.tblDevices->setRowCount(Ui_configDlg.tblDevices->rowCount()+1); QTableWidgetItem *I = new QTableWidgetItem(0); Ui_configDlg.tblDevices->setItem(Ui_configDlg.tblDevices->rowCount()-1,2,I); I->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); I->setCheckState(Qt::Unchecked); QTableWidgetItem *O = new QTableWidgetItem(0); Ui_configDlg.tblDevices->setItem(Ui_configDlg.tblDevices->rowCount()-1,3,O); O->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); O->setCheckState(Qt::Unchecked); } /*! \fn kConfigDlg::bRemoveClick() */ void kConfigDlg::bRemoveClick() { Ui_configDlg.tblDevices->removeRow(Ui_configDlg.tblDevices->currentRow()); } void kConfigDlg::save() { QStringList ldev; QStringList llabels; QStringList lIO; //KSimpleConfig settings("K9Copy"); k9Config config; ldev.clear(); llabels.clear(); for (int i=0;irowCount();i++) { QString c=Ui_configDlg.tblDevices->item(i,0)->text(); if (!c.isEmpty()) { if (QFile::exists(c)) { ldev.append(Ui_configDlg.tblDevices->item(i,0)->text()); c=Ui_configDlg.tblDevices->item(i,1)->text(); if (c.isEmpty()) c=Ui_configDlg.tblDevices->item(i,0)->text(); llabels.append(c); QTableWidgetItem *I = (QTableWidgetItem*)Ui_configDlg.tblDevices->item(i,2); QTableWidgetItem *O = (QTableWidgetItem*)Ui_configDlg.tblDevices->item(i,3); if (O->checkState()==Qt::Checked && I->checkState()==Qt::Checked) { lIO.append("IO"); } else { if (O->checkState()==Qt::Checked) lIO.append("O"); if (I->checkState()==Qt::Checked) lIO.append("I"); if ((!O->checkState()==Qt::Checked ) && (!I->checkState()==Qt::Checked)) { lIO.append("x"); } } } else { k9Dialogs::error( c + " is not a valid device", "Devices"); } } } config.setDevicesLabels(llabels); config.setDevices(ldev); config.setDevicesIO(lIO); config.save(); } k9copy/src/main/images.h0000755000175000017550000007466412412271774015727 0ustar emulatoremulator/************************************************************************** * Copyright (C) 2005 by Jean-Michel Petit * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ static const char* const img_text[] = { "30 30 2 1", ". c None", "# c #eee608", "..............................", "..............................", "..............................", "..............................", "..............................", "..............................", "..............................", "..............................", "..............................", "..............................", "..............................", "..............................", "..............................", "..............................", "...........##.................", "...........##.................", "...........##.................", "....####...##.###....####.....", "...#...##..###.###..##..##....", "...##..##..##...##..##..#.....", "......###..##...##.###........", "...##..##..##...##.###........", "...##..##..##...##..##........", "..###.###..###.##...###.......", "...###.##............####.....", "..............................", "..............................", "..............................", "..............................", ".............................." }; static const char* const img_sound[] = { "30 29 230 2", ".a c None", ".# c None", "Qt c None", "aA c #101820", "aM c #181820", "aL c #181829", "#c c #181c29", ".V c #182029", ".K c #182031", ".6 c #182429", "#q c #182431", "#C c #202031", "bq c #202420", "#d c #202429", ".W c #202431", "#N c #202831", ".7 c #202839", ".M c #202c41", ".8 c #20304a", "bf c #292831", ".L c #292839", "bg c #292c29", "br c #292c31", ".X c #292c41", "bt c #293029", ".Z c #293041", "#k c #29304a", ".w c #29344a", ".Y c #293452", "#1 c #29384a", "#l c #293852", "#m c #293c5a", "bs c #313031", "#A c #313431", ".U c #313441", "#0 c #31344a", ".x c #31384a", "#e c #31385a", ".J c #313c4a", "#r c #313c52", "#n c #31405a", "#u c #314062", "#v c #31446a", "bh c #393439", "a5 c #393839", ".3 c #393c31", ".5 c #393c4a", "az c #393c52", "aa c #39405a", "#Z c #394452", ".N c #39445a", "#S c #394462", "#w c #394862", "af c #39486a", "bi c #413c41", ".l c #414039", "aV c #41444a", ".Q c #414841", "be c #414852", "#p c #414c41", "#G c #414c6a", ".E c #415041", "ak c #41506a", "#T c #415073", "bj c #4a444a", ".j c #4a4841", ".f c #4a4c41", "#h c #4a554a", "#H c #4a597b", "aW c #52505a", "#b c #525062", ".t c #52554a", ".e c #52594a", "bp c #525962", ".v c #525973", "aq c #525d52", "ao c #525d73", "#5 c #525d7b", "#W c #526152", "al c #526183", "#s c #526583", "#6 c #52698b", "#R c #526994", "a6 c #5a555a", "bu c #5a595a", "a7 c #5a5d5a", "aO c #5a5d7b", "ap c #5a615a", "aX c #5a6162", "aN c #5a616a", ".y c #5a6173", "as c #5a617b", "#O c #5a657b", "aD c #5a6583", "ai c #5a6952", "an c #5a698b", "ac c #5a6994", "#U c #5a6d94", "#4 c #5a719c", "bk c #625d62", "bz c #626162", ".i c #62655a", ".F c #626562", "#M c #626573", ".d c #62695a", "#. c #626962", "ar c #626983", ".g c #626d62", "ba c #626d83", "at c #626d8b", ".2 c #62715a", ".G c #627162", "#7 c #62718b", "#t c #627194", "#D c #627594", "#F c #62799c", "by c #6a656a", "a. c #6a696a", ".h c #6a6d62", "aB c #6a717b", "a2 c #6a7194", "#z c #6a756a", "aj c #6a758b", "ay c #6a799c", "ab c #6a7d9c", "ae c #6a7da4", "#Q c #6a81a4", "bA c #736d73", "#X c #73716a", "#j c #737583", ".s c #737973", "#V c #737994", "#o c #737d94", "aK c #737d9c", "aE c #73819c", "#E c #7389ac", ".S c #7b7973", "bx c #7b797b", ".R c #7b7d73", "bl c #7b7d7b", "#f c #7b7d94", "aC c #7b7d9c", "#9 c #7b8173", "a# c #7b8194", ".1 c #7b8573", "ah c #7b857b", "aU c #7b859c", "#8 c #7b897b", "#2 c #7b89a4", "a8 c #838183", ".k c #83857b", "bd c #838594", ".9 c #83899c", "#x c #8389a4", "au c #8389ac", "#I c #838da4", "ad c #838dac", "#3 c #8395b4", ".H c #8b8583", "#B c #8b899c", ".0 c #8b8d9c", ".T c #8b919c", ".I c #8b95a4", ".D c #949194", "#i c #949594", "bc c #9495a4", "bb c #9495ac", ".P c #9499a4", ".u c #9499ac", "aF c #9499b4", ".B c #949d94", "aw c #949db4", "am c #94a1bd", "## c #9c959c", "ag c #9c9994", "bo c #9c999c", ".c c #9ca19c", "a3 c #9ca1b4", "#P c #9ca5c5", "av c #9caabd", "a9 c #a49da4", "#L c #a4a194", "#J c #a4a1a4", "#Y c #a4a1ac", "#g c #a4a59c", ".4 c #a4a5b4", ".n c #a4a5bd", ".C c #a4aaa4", ".A c #a4aabd", "bF c #aca5ac", "#a c #aca5b4", ".r c #acaaa4", ".b c #acaaac", "aY c #acaab4", "bG c #acaeac", ".o c #acaebd", "aP c #acaec5", "aG c #acb6c5", "bB c #b4aeb4", "bm c #b4b2b4", "bH c #b4b6b4", ".O c #b4b6c5", ".m c #b4bac5", "ax c #b4bad5", "#K c #bdb6b4", "bw c #bdb6bd", "bE c #bdbabd", "a1 c #bdbac5", ".p c #bdbacd", ".z c #bdbecd", "aJ c #bdc2d5", "bI c #c5bec5", "#y c #c5c2c5", "aQ c #c5c2d5", ".q c #c5c6cd", "a4 c #c5c6d5", "aT c #c5c6de", "aZ c #cdcacd", "aS c #cdd2de", "aH c #cdd2e6", "bD c #d5ced5", "aR c #d5cede", "bC c #d5d2d5", "b# c #d5d2de", "aI c #d5d6e6", "bn c #ded6de", "bv c #dedade", "a0 c #e6dee6", "b. c #e6e2e6", "bJ c #eee2ee", "Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#", ".aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt", "Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#.b.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#", ".aQt.aQt.aQt.aQt.c.d.e.f.fQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt", "Qt.#Qt.#Qt.#Qt.#Qt.g.h.i.j.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#", ".aQt.aQt.aQt.aQt.a.k.aQt.lQt.aQt.aQt.m.n.o.p.qQt.aQt.aQt.aQt", "Qt.#Qt.#Qt.#Qt.#.r.sQt.#.t.#Qt.#Qt.u.v.w.x.y.z.AQt.#Qt.#Qt.#", ".aQt.aQt.B.C.a.D.E.F.a.r.G.H.aQt.I.J.K.L.M.M.N.O.PQt.aQt.aQt", "Qt.#Qt.#.s.Q.R.c.S.#Qt.k.F.#Qt.T.U.V.W.W.X.Y.Z.0.u.#Qt.#Qt.#", ".aQt.aQt.1.2.3.f.aQt.aQt.aQt.4.5.V.W.6.W.7.Y.8.y.9Qt.aQt.aQt", "Qt.#Qt.#Qt.t#.##Qt.#Qt.#Qt#a#b#c.W#d.W.W.M.Y#e.N#f.#Qt.#Qt.#", ".aQt.aQt#g#h#iQt.aQt.aQt.a#j.V.K.V.W#d#k#l.Y#m#n#oQt.aQt.aQt", "Qt.#Qt.#.c#pQt.#Qt.#Qt.#Qt.x#q.V.W#d#r#s#t#u#v#w#x.#Qt.#Qt.#", ".aQt.a#y#z#A.aQt.aQt.aQt#B#C.V.W.6.U#D#E#F#G#u#H#IQt.aQt.aQt", "Qt.#Qt.##J.#Qt.##K#LQt.##M#q.7#N#N#O#P#Q#R#S#T#U#V.#Qt.#Qt.#", ".aQt.aQt.aQt.aQt#W#X.a#Y#Z#0#1#0#0#2#3#4#T#5#6#U#G#7.aQt.aQt", "Qt.#Qt.#Qt.#Qt#8#9a.Qta##Saa#Saa#Gabac#Saaadae.Naf.vQt.#Qt.#", ".aQt.aQtagagahai.aQt.aaj#S#w#wakal#5#l.w#Vaman#N#lao.aQt.aQt", "Qt.#Qt.#.DapaqahQt.#Qtarak#Tasatauavaw.AaxayazaA.ZaBQt.#Qt.#", ".aQt.aQt.aQt.aQt.aQt.aaCakaDaEaFaGaHaIaJaK#waLaMaNQt.aQt.aQt", "Qt.#Qt.#Qt.#Qt.#Qt.#Qt.uaOaDaPaQaRaSaTaU.5aVaWaXaYaZa0.#Qt.#", ".aQt.aQt.aQt.aQt.aQt.aa1aja2a3a4a4aJaj.Ua5a6a7a.a8a9#yb..aQt", "Qt.#Qt.#Qt.#Qt.#Qt.#Qtb#.9babbbcbdbebfbgbh#AbibjbkblbmbnQt.#", ".aQt.aQt.aQt.aQt.aQt.abnbobp.Ubfbqbrbsbsbt#Aa5bjbua8bmbv.aQt", "Qt.#Qt.#Qt.#Qt.#Qt.#Qtbvbw.Dbxa.bybza7a6a7bzbAbx.DbBbC.#Qt.#", ".aQt.aQt.aQt.aQt.aQt.aQtbvbD#ybEbmbBbF.bbGbmbHbIaZbv.aQt.aQt", "Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#bJ.#Qt.#Qt.#Qt.#Qt.#Qt.#", ".aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt", "Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#" }; static const unsigned char img_preview[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x20, 0x08, 0x06, 0x00, 0x00, 0x00, 0x05, 0x40, 0xc8, 0x7f, 0x00, 0x00, 0x00, 0xd2, 0x49, 0x44, 0x41, 0x54, 0x48, 0x89, 0xe5, 0x96, 0x4b, 0x0e, 0xc3, 0x20, 0x0c, 0x44, 0x4b, 0xd5, 0x53, 0x71, 0x7f, 0xf9, 0x5a, 0xcd, 0x0a, 0xc9, 0x22, 0xb6, 0x33, 0xe3, 0x40, 0x1d, 0xa9, 0xb3, 0x49, 0x84, 0x2c, 0x9e, 0x7f, 0x18, 0x9a, 0x88, 0xbc, 0x2a, 0xf4, 0x2e, 0xa1, 0x56, 0x82, 0x3f, 0x88, 0x51, 0xef, 0xfd, 0x3b, 0xfe, 0x45, 0xa4, 0x65, 0x6d, 0xb4, 0x5a, 0x54, 0x63, 0xbd, 0xd9, 0xac, 0xb1, 0x39, 0x62, 0x43, 0x81, 0xa3, 0x0d, 0x19, 0x79, 0xf0, 0xff, 0x6b, 0xae, 0xe7, 0x80, 0x47, 0x6d, 0xaf, 0x3a, 0x53, 0x44, 0x1a, 0x62, 0x03, 0x83, 0x11, 0xb8, 0x5e, 0x47, 0x6c, 0x2c, 0xb9, 0xe7, 0x38, 0xea, 0xea, 0x15, 0x1d, 0xbf, 0xad, 0xc6, 0x96, 0x73, 0x7a, 0xcd, 0x04, 0x23, 0xf5, 0xcb, 0x3a, 0x32, 0xbe, 0xd0, 0xc8, 0xbc, 0x0b, 0xb3, 0x74, 0x8a, 0x78, 0x75, 0xa4, 0x30, 0xf8, 0x57, 0xda, 0x9a, 0xea, 0x39, 0x7b, 0x3a, 0xf5, 0x5b, 0xc1, 0x91, 0x23, 0x65, 0xa9, 0x0e, 0xef, 0x63, 0x4f, 0xec, 0xa5, 0x6f, 0x89, 0x8e, 0x78, 0x3e, 0x22, 0xd9, 0x29, 0x46, 0x81, 0xbd, 0x48, 0x33, 0x70, 0x18, 0x6c, 0x41, 0xef, 0xc0, 0x21, 0x70, 0x54, 0xd3, 0x2c, 0xfc, 0x12, 0x8c, 0x34, 0x52, 0x06, 0x1e, 0x82, 0x99, 0xee, 0x65, 0xe1, 0x2e, 0x38, 0x73, 0x64, 0x18, 0x78, 0xf8, 0x02, 0x61, 0xa0, 0x2c, 0xdc, 0x7d, 0x73, 0x65, 0xa0, 0x0c, 0x3c, 0x35, 0xb9, 0x56, 0xa8, 0x6c, 0x56, 0x1f, 0x9a, 0x62, 0x93, 0xe0, 0x9f, 0x36, 0x40, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; static const char* const img_video[] = { "30 30 205 2", ".a c None", ".# c None", "Qt c None", ".j c #292452", ".q c #292852", ".i c #39305a", ".p c #393c6a", ".r c #413c5a", "#1 c #413c62", ".k c #414462", "#0 c #4a4483", "#Z c #524ca4", "#O c #52506a", ".D c #5250a4", ".1 c #5250ac", ".d c #5a557b", "## c #5a55ac", ".0 c #5a599c", "al c #5a59a4", "#a c #5a59ac", "#M c #5a5db4", "#R c #5a8de6", ".G c #625973", "#Y c #6259ac", ".u c #625d7b", "#N c #625d9c", "#k c #625dac", ".e c #62619c", ".Y c #6261ac", "#X c #6265b4", "#T c #6295ee", ".Z c #6a61b4", "#j c #6a659c", ".O c #6a65a4", ".2 c #6a65b4", ".T c #6a6d94", "#E c #6a8dd5", ".s c #736973", "a# c #736d8b", ".E c #736da4", ".C c #736db4", "#l c #736dbd", ".H c #73719c", "#P c #7371b4", "a9 c #7371bd", ".P c #7375b4", "#5 c #738dcd", ".l c #7b717b", ".t c #7b757b", "ak c #7b759c", ".c c #7b75a4", ".f c #7b75ac", "b# c #7b75b4", ".X c #7b75bd", ".N c #7b79b4", "#b c #7b79bd", "#i c #7b7da4", "a1 c #7b7db4", "b. c #7b7dbd", "#6 c #7bbaff", "ax c #8379bd", "a3 c #837d8b", "#2 c #837d94", "a8 c #837dc5", "#. c #8381bd", "aZ c #8381c5", "am c #8385bd", "aO c #8b81c5", "a. c #8b85a4", "aU c #8b85bd", "aN c #8b85c5", ".v c #8b89b4", "#B c #8b89bd", ".A c #8b89c5", ".B c #8b89cd", "#u c #8b8dac", "a4 c #8b8db4", "#C c #8b8dc5", ".m c #948da4", ".6 c #948dc5", ".o c #948dcd", "aS c #94918b", "aT c #94919c", "aG c #9491bd", ".7 c #9491c5", "#A c #9491cd", "#v c #9495bd", "bj c #9495cd", "#H c #94a5d5", "#8 c #94c2f6", "aR c #9c919c", "aE c #9c91c5", ".S c #9c95ac", ".F c #9c95b4", "aD c #9c95bd", ".z c #9c95cd", ".M c #9c95d5", "aK c #9c99ac", "#e c #9c99cd", "a0 c #9c99d5", "bg c #9c9dc5", "a5 c #9c9dcd", "a2 c #a499a4", "aw c #a49db4", "#W c #a49dc5", ".h c #a49dcd", ".y c #a49dd5", "ay c #a4a1cd", "bf c #a4a1d5", "aB c #a4a5cd", "aQ c #a4a5d5", "aC c #aca5c5", "aL c #aca5cd", "aF c #aca5d5", "#z c #aca5de", "aJ c #acaaac", "aa c #acaab4", "ba c #acaacd", ".L c #acaad5", "af c #acaeb4", "#s c #acbede", "ag c #acd2f6", "#V c #b4aebd", "#h c #b4aecd", "aV c #b4aed5", "aY c #b4aede", "at c #b4b2b4", "be c #b4b2d5", "aM c #b4b2de", "bd c #b4b2e6", "aI c #b4b6b4", "aj c #b4b6bd", "bi c #b4b6d5", "#q c #b4bac5", "av c #b4bed5", "#r c #b4caf6", "#7 c #b4daff", ".3 c #bdb2de", "aH c #bdb6bd", "as c #bdb6c5", "ar c #bdb6d5", "#L c #bdb6de", "aP c #bdb6e6", "ae c #bdbad5", "aA c #bdbae6", "au c #bdcede", "#J c #c5bec5", "#9 c #c5becd", "#o c #c5bede", ".Q c #c5bee6", ".9 c #c5c2e6", "aX c #c5c2ee", "bb c #c5c6d5", ".b c #c5c6e6", "#g c #cdc2de", "#4 c #cdc6cd", "#f c #cdcad5", ".U c #cdced5", "ai c #cde6f6", "#G c #cde6ff", ".K c #d5caee", "az c #d5cecd", "#U c #d5ced5", "#y c #d5cee6", "#m c #d5ceee", "aq c #d5d2d5", "aW c #d5d2de", "#t c #d5d2e6", ".g c #d5d2ee", ".I c #d5d2f6", "bh c #d5d6de", "#Q c #ded2d5", "a6 c #ded2de", ".w c #ded2ee", ".W c #ded2f6", "#D c #ded6de", ".5 c #ded6ee", ".n c #ded6f6", "a7 c #dedade", ".8 c #dedae6", "#K c #dedaf6", "#S c #def6ff", ".x c #e6d6f6", "#I c #e6dae6", "#d c #e6daf6", "ab c #e6dee6", "#w c #e6def6", "#3 c #e6deff", "bk c #e6e2e6", "bc c #e6e2ee", "#c c #e6e2f6", ".V c #eee2ee", "#p c #eee6ee", ".J c #eee6f6", "ad c #eee6ff", "#n c #eeeaff", "an c #eeeeee", ".R c #eeeef6", "#x c #f6eaff", ".4 c #f6eeff", "ap c #f6f2f6", "ah c #f6ffff", "ao c #fff6ff", "ac c #fffaff", "#F c #ffffff", "Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#", ".aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt", "Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#", ".aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt", "Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.bQt.#Qt.#Qt.#Qt.#Qt.#", ".aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.a.c.d.e.f.g.aQt.aQt.aQt", "Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#.h.i.j.k.l.mQt.#Qt.#Qt.#", ".aQt.aQt.aQt.aQt.aQt.aQt.aQt.nQt.a.o.p.q.r.s.t.u.vQt.aQt.aQt", "Qt.#Qt.#Qt.#Qt.#Qt.#Qt.w.x.y.z.A.B.C.D.E.F.t.G.H.A.#Qt.#Qt.#", ".aQt.aQt.aQt.aQt.a.I.J.K.L.M.A.N.O.D.P.Q.R.S.T.L.U.V.aQt.aQt", "Qt.#Qt.#Qt.#Qt.#Qt.#.W.y.X.Y.Z.0.1.2.3.4.5.6.7.8Qt.#Qt.#Qt.#", ".aQt.aQt.aQt.aQt.9#..2##.D###a#b.z.z#c#d#e.h#fQt.aQt.aQt.aQt", "Qt.#Qt.#Qt.##d#g#h#i#j#k#l.A.3#m#n.n.w.h.B#o#p.#Qt.#Qt.#Qt.#", ".aQt.aQt.a.g#q#r#s#t#u#v.Q#w.4#x#y#z#A#B#C.V.aQt.aQt.aQt.aQt", "Qt.#Qt.#Qt#D#E#F#G#H#I#J#c#K#L.z.X#M#N#O#P.#Qt.#Qt.#Qt.#Qt.#", ".aQt.aQt.g#Q#R#S#S#T#U#V#W.A#X#Y#Z#0#1#2#h.B.aQt.aQt.aQt.aQt", "Qt.#Qt.##3#4#5#6#7#8#9a..O.D###ka#aaabac#p.AQt.#Qt.#Qt.#Qt.#", ".aQt.aad#waeafagahaiajakal##am#9anaoapapaq.o.aQt.aQt.aQt.aQt", "Qt.#Qt.##warasatauavaw.Eax#eay#4abaqaqaz#J#CQt.#Qt.#Qt.#Qt.#", ".aQt.aQt#taAaBaCawaDaE#zaF.zaGaHaIataJaJaKaL.aQt.aQt.aQt.aQt", "Qt.#Qt.#aM.L.zaNaOaNaPaQ#e.6aNaJaRaSaTaUaVaWQt.#Qt.#Qt.#Qt.#", ".aQt.aQtaXaYaZaZ#baZaVa0.AaZa1a2a3a4a5a6a7Qt.aQt.aQt.aQt.aQt", "Qt.#Qt.#Qt.ha8a9.Xb.aM.o.o.7aOb#babbbc.#Qt.#Qt.#Qt.#Qt.#Qt.#", ".aQt.aQt.abdaY#Cb.aNbebfbg#ebh#pabQt.aQt.aQt.aQt.aQt.aQt.aQt", "Qt.#Qt.#Qt.#Qtbi.LbjaF.L#tbkQt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#", ".aQt.aQt.aQt.aQt.aQt.8Qt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt", "Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#", ".aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt", "Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#Qt.#", ".aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt.aQt" }; static const unsigned char img_chapter[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x17, 0x08, 0x06, 0x00, 0x00, 0x00, 0x81, 0x32, 0xf6, 0xe2, 0x00, 0x00, 0x08, 0x6d, 0x49, 0x44, 0x41, 0x54, 0x48, 0x89, 0x3d, 0x95, 0xcb, 0x92, 0x23, 0xc7, 0x79, 0x85, 0xbf, 0xbc, 0x55, 0xa1, 0x50, 0x40, 0xa1, 0x81, 0xee, 0x06, 0xd0, 0xb7, 0x21, 0x7b, 0x24, 0xd2, 0xb2, 0x28, 0x51, 0x61, 0x5b, 0xb2, 0xc3, 0x11, 0xd6, 0x13, 0x68, 0x69, 0x6d, 0xec, 0x95, 0x37, 0x76, 0x38, 0xfc, 0x14, 0xde, 0x39, 0xc2, 0x2f, 0xa0, 0x85, 0x17, 0x76, 0x78, 0xe7, 0x08, 0x79, 0xef, 0x07, 0x70, 0x48, 0x0c, 0x53, 0x66, 0x90, 0x96, 0x4d, 0xce, 0x85, 0xd3, 0x1c, 0x8a, 0xd3, 0xd3, 0x40, 0xdf, 0x00, 0x74, 0x01, 0x85, 0xaa, 0xcc, 0xca, 0x4c, 0x2f, 0x30, 0x9c, 0xdc, 0xe4, 0x2a, 0xff, 0x38, 0x79, 0xce, 0xf9, 0xcf, 0x11, 0x7f, 0xf3, 0xd7, 0x3f, 0xff, 0x8b, 0xdf, 0x7f, 0x6f, 0xfc, 0xf3, 0x41, 0x6f, 0x34, 0xb0, 0x31, 0x92, 0x98, 0x14, 0xa3, 0x25, 0xd6, 0xad, 0x71, 0x6d, 0x45, 0x9e, 0x17, 0x28, 0xa5, 0x49, 0xd3, 0x94, 0x18, 0x23, 0x8d, 0xdb, 0x10, 0x82, 0xe5, 0x66, 0x36, 0xc7, 0xd6, 0x0d, 0x27, 0x67, 0xdf, 0xfd, 0xf4, 0x61, 0x9d, 0x8a, 0xcd, 0x7a, 0xf3, 0xa3, 0x1f, 0xfc, 0xf0, 0x87, 0xcf, 0xbb, 0xdd, 0xec, 0xa6, 0x93, 0xa5, 0xb6, 0xaa, 0xb6, 0x05, 0xc4, 0xe5, 0xd5, 0xec, 0xfa, 0x0f, 0xda, 0x20, 0x87, 0x5a, 0x6b, 0x9c, 0x73, 0xbc, 0xfb, 0xee, 0x3b, 0x4f, 0x9e, 0xfc, 0xef, 0x7f, 0xbd, 0x1f, 0x5c, 0x29, 0x6d, 0x75, 0xcf, 0x66, 0xb5, 0x1c, 0x3c, 0x7b, 0xb1, 0xfe, 0x97, 0xbf, 0xff, 0xc7, 0x7f, 0xfa, 0x85, 0xf8, 0xd9, 0xcf, 0xbe, 0xf7, 0xcb, 0xbf, 0xfb, 0xdb, 0xbf, 0xfc, 0xf3, 0xf7, 0xbe, 0xf3, 0x47, 0xf4, 0xf6, 0xa6, 0x48, 0x63, 0x08, 0xd1, 0xe3, 0x43, 0x83, 0x54, 0x01, 0xad, 0x32, 0x8c, 0x4e, 0x01, 0x88, 0x11, 0x08, 0x20, 0x5b, 0x70, 0x8d, 0xa5, 0xb5, 0x96, 0xf9, 0xcd, 0x2d, 0x37, 0xcb, 0x25, 0x8f, 0xce, 0xce, 0xe8, 0x64, 0x19, 0x52, 0x69, 0x42, 0x14, 0xb4, 0xde, 0x93, 0x24, 0x86, 0x3c, 0xef, 0x91, 0x65, 0x03, 0x82, 0x0f, 0x78, 0x1f, 0xf0, 0xbe, 0xc5, 0xbb, 0x05, 0xde, 0xad, 0x58, 0xdd, 0x5f, 0x70, 0x75, 0xf9, 0x05, 0xff, 0xf6, 0xaf, 0x9f, 0xf0, 0x9f, 0xbf, 0xfe, 0xe2, 0x4f, 0xf5, 0xef, 0xbd, 0xf7, 0xe1, 0xbc, 0xa9, 0x0d, 0xc6, 0x1c, 0xa3, 0xd2, 0x33, 0x2e, 0xaf, 0xe6, 0x1c, 0xec, 0x8f, 0xe9, 0xf5, 0x73, 0xb4, 0x52, 0x34, 0x8d, 0x45, 0x9b, 0x0e, 0x4a, 0x29, 0x04, 0x20, 0x42, 0x40, 0x7a, 0x4f, 0x23, 0x6a, 0x5c, 0x6c, 0xd0, 0xca, 0x90, 0x98, 0x0c, 0xad, 0xa7, 0x74, 0xd2, 0x1e, 0xda, 0x24, 0x38, 0x17, 0x48, 0x4d, 0xa4, 0xdb, 0xed, 0x62, 0x12, 0x8d, 0x14, 0x81, 0x10, 0x1d, 0x31, 0x7a, 0x62, 0x00, 0x29, 0x8e, 0x91, 0x6a, 0x44, 0x37, 0x93, 0x08, 0x71, 0x8d, 0xb3, 0x21, 0x2a, 0x29, 0x5b, 0x7d, 0x32, 0x3d, 0xb9, 0xe9, 0x74, 0xfa, 0xa0, 0x0c, 0x9f, 0x7d, 0xfe, 0x39, 0xb7, 0xf3, 0xd7, 0xfc, 0xe0, 0x83, 0x0f, 0x58, 0xad, 0xee, 0x18, 0x14, 0x7b, 0x7c, 0xf9, 0xe2, 0x29, 0x4a, 0x4a, 0x4e, 0xcf, 0xce, 0xb8, 0xbf, 0xbf, 0x27, 0x51, 0x1d, 0x32, 0x93, 0xf1, 0xe5, 0xd3, 0x2f, 0x39, 0x9d, 0x1e, 0xb1, 0x28, 0x4b, 0x54, 0x9a, 0x80, 0x54, 0x44, 0x21, 0x41, 0x0a, 0x36, 0xcd, 0x9a, 0xa7, 0xcf, 0x9e, 0x32, 0x1a, 0x8d, 0x38, 0x3e, 0x3a, 0x62, 0x58, 0x0c, 0x69, 0xdb, 0x88, 0x10, 0x0a, 0x29, 0x25, 0x51, 0x58, 0x22, 0x80, 0x50, 0x20, 0x25, 0x6b, 0x57, 0xc7, 0x60, 0x54, 0xa3, 0x7b, 0xfd, 0x6e, 0x21, 0x89, 0x78, 0xeb, 0xf9, 0xfa, 0xc5, 0x05, 0xa7, 0xc7, 0xa7, 0x64, 0xa6, 0xcf, 0xcb, 0xaf, 0x5f, 0x52, 0x3d, 0x34, 0xdc, 0xcd, 0x57, 0x0c, 0x06, 0x05, 0xb4, 0x9a, 0xab, 0x6f, 0x6e, 0xc8, 0x3a, 0x29, 0xef, 0x9c, 0x3d, 0x42, 0xa9, 0xc8, 0x62, 0x79, 0xcb, 0x6a, 0x5d, 0xb2, 0x77, 0x38, 0x24, 0xc4, 0x16, 0xf0, 0x5c, 0xbe, 0x7a, 0xcd, 0x93, 0xa7, 0x5f, 0x00, 0x60, 0x14, 0xbc, 0xf6, 0x8e, 0x32, 0x5f, 0x50, 0x96, 0x25, 0x45, 0x51, 0x30, 0x18, 0x0c, 0xc8, 0xb2, 0x2e, 0x1e, 0x41, 0x1d, 0x05, 0x2d, 0x8a, 0xb4, 0x6b, 0x9a, 0xff, 0x79, 0xf2, 0xfc, 0xb7, 0x5a, 0x10, 0x6c, 0x53, 0x5b, 0xea, 0xad, 0xe5, 0xa7, 0x7f, 0xf6, 0x53, 0x16, 0xf7, 0xf7, 0x64, 0x59, 0xc2, 0x64, 0x7c, 0xc8, 0xfe, 0xfe, 0x3e, 0xa3, 0xd1, 0x1e, 0xde, 0xb7, 0x24, 0x89, 0xe6, 0xc7, 0x3f, 0xfe, 0x43, 0x6c, 0x63, 0xe9, 0x24, 0x29, 0x1f, 0x7c, 0xff, 0x03, 0x82, 0x6b, 0x59, 0x94, 0x2b, 0x56, 0x55, 0x89, 0x92, 0x8a, 0x10, 0x22, 0x21, 0x44, 0x94, 0xd4, 0xd4, 0x75, 0x8d, 0x77, 0x9e, 0x6d, 0xb5, 0x45, 0x22, 0x30, 0x46, 0x73, 0x7d, 0x3d, 0x67, 0x36, 0xbb, 0xe2, 0x68, 0x3a, 0xe1, 0x60, 0x3a, 0x25, 0x12, 0xd1, 0x26, 0x41, 0x29, 0x05, 0x80, 0xfe, 0xdd, 0xef, 0xbe, 0x79, 0xf7, 0x60, 0xb4, 0x87, 0x10, 0xe0, 0x7d, 0x60, 0x38, 0x1c, 0xd2, 0x34, 0xf6, 0xcd, 0xdd, 0x50, 0x14, 0x05, 0x10, 0xb1, 0xd6, 0x61, 0x4c, 0x42, 0x6b, 0x1d, 0x8b, 0xe5, 0x02, 0xe9, 0x23, 0xd3, 0xc3, 0x31, 0x2d, 0x81, 0x55, 0x55, 0x12, 0x63, 0x44, 0x4a, 0xc9, 0x70, 0x38, 0x44, 0x29, 0xc5, 0x70, 0x38, 0xe4, 0xf8, 0xf8, 0x18, 0xad, 0x14, 0xeb, 0xf5, 0x1a, 0x6b, 0x2d, 0x00, 0x8b, 0xc5, 0x02, 0x62, 0x60, 0x7f, 0x32, 0xa5, 0xd3, 0xe9, 0x93, 0xa5, 0x05, 0xcb, 0x65, 0xb9, 0x03, 0x73, 0x77, 0x77, 0x77, 0xe0, 0x5a, 0x87, 0x10, 0x82, 0xba, 0xa9, 0xb9, 0xb9, 0xbe, 0x66, 0xb4, 0x37, 0xe4, 0xdb, 0x13, 0x63, 0xc4, 0x39, 0x47, 0x59, 0x96, 0x8c, 0x46, 0x23, 0x5e, 0x5e, 0x5c, 0x70, 0x73, 0x7d, 0xc3, 0x78, 0xff, 0x80, 0xa3, 0xf1, 0x04, 0xef, 0x3d, 0x21, 0x04, 0x00, 0x84, 0x10, 0x24, 0x49, 0x42, 0x8c, 0x91, 0x97, 0x2f, 0x5f, 0x12, 0x63, 0x64, 0x3a, 0x9d, 0x12, 0x42, 0x40, 0x4a, 0x49, 0x92, 0x24, 0x34, 0x4d, 0xcd, 0x7a, 0x23, 0x79, 0xf1, 0xe2, 0x05, 0x8f, 0x1e, 0x8d, 0x11, 0xc2, 0x10, 0xe3, 0xee, 0xbd, 0x2e, 0xd7, 0x1b, 0xa1, 0x4c, 0x8a, 0x4e, 0x12, 0xf0, 0x91, 0xe9, 0x74, 0x42, 0xaf, 0xdb, 0x7b, 0x3b, 0xfc, 0x5b, 0x0a, 0xa7, 0xd3, 0x29, 0x49, 0x62, 0x38, 0x39, 0x39, 0x25, 0xeb, 0x64, 0x8c, 0xf7, 0xf7, 0x91, 0x4a, 0x92, 0xe7, 0x39, 0x5a, 0x27, 0x08, 0xa1, 0x08, 0x01, 0x84, 0x90, 0x14, 0x45, 0xc1, 0xc3, 0xc3, 0x03, 0x5a, 0x6b, 0xac, 0xb5, 0x38, 0xe7, 0x10, 0xc0, 0xab, 0xcb, 0x4b, 0x84, 0x94, 0x5c, 0x5f, 0x5f, 0x33, 0x1a, 0x4d, 0xc0, 0x41, 0xeb, 0x22, 0x26, 0xed, 0xec, 0xc0, 0x48, 0xa9, 0x5e, 0xc6, 0x18, 0x31, 0x89, 0x26, 0x6c, 0x1c, 0xc7, 0xd3, 0x09, 0xd7, 0xf3, 0x6b, 0x26, 0x93, 0xc9, 0x5b, 0xd3, 0x01, 0x64, 0x59, 0xc6, 0xed, 0xed, 0x2d, 0x7b, 0xc3, 0x3d, 0xa6, 0x93, 0x09, 0xf8, 0x40, 0xdb, 0xb6, 0x38, 0xd7, 0x22, 0x84, 0x20, 0x84, 0x40, 0x8c, 0x11, 0x80, 0xaa, 0xaa, 0xe8, 0x76, 0xbb, 0xdc, 0xdc, 0xdc, 0x10, 0x42, 0x20, 0x4d, 0x53, 0xac, 0xb5, 0xc8, 0x37, 0x40, 0x1e, 0x9f, 0x3f, 0xe2, 0xf4, 0xf8, 0x04, 0x2d, 0xc0, 0xb9, 0x96, 0xc6, 0xb5, 0x7c, 0xf5, 0xd5, 0x0b, 0xa9, 0x41, 0x5c, 0x08, 0x11, 0x10, 0xc2, 0x73, 0x7b, 0x7b, 0xcf, 0xfc, 0xf5, 0x0c, 0x11, 0x61, 0x36, 0x9b, 0x71, 0x74, 0x74, 0xc4, 0x62, 0xb1, 0x40, 0x4a, 0x49, 0xb7, 0xdb, 0x45, 0x6b, 0xcd, 0x67, 0x9f, 0x7e, 0xca, 0xc1, 0x68, 0x9f, 0x44, 0x69, 0x32, 0x93, 0x30, 0xbb, 0xbd, 0x41, 0x24, 0xfa, 0x2d, 0x20, 0x88, 0x8c, 0x46, 0x23, 0x96, 0xcb, 0x25, 0x77, 0x77, 0x77, 0x4c, 0xa7, 0x53, 0x66, 0xb3, 0x19, 0xc6, 0x18, 0x62, 0x8c, 0x64, 0x59, 0x86, 0xb5, 0x96, 0x3c, 0xef, 0xa1, 0x68, 0x30, 0xda, 0x20, 0xa5, 0xe4, 0xfc, 0xfc, 0x3b, 0x41, 0xdb, 0xc6, 0x92, 0xf7, 0xbb, 0x74, 0xf3, 0x0e, 0x07, 0x87, 0x63, 0x5c, 0xb5, 0x45, 0x49, 0xb1, 0x0b, 0xac, 0x37, 0x03, 0xa4, 0x94, 0x0c, 0x06, 0x05, 0x4d, 0x63, 0x39, 0x3c, 0x3c, 0x64, 0x7f, 0x38, 0xc4, 0x48, 0x8d, 0x46, 0xb0, 0x6e, 0xb6, 0xd4, 0xad, 0x23, 0xc6, 0x88, 0xd6, 0x9a, 0xba, 0xde, 0x72, 0x70, 0x70, 0x40, 0x55, 0x55, 0x9c, 0x9d, 0x9d, 0xbd, 0x65, 0xb7, 0xd3, 0xe9, 0x50, 0xd7, 0x35, 0xe5, 0xba, 0x24, 0x49, 0x92, 0x1d, 0x93, 0xa1, 0xc5, 0x87, 0x40, 0x0c, 0x62, 0x27, 0x93, 0x6d, 0x41, 0x49, 0x83, 0x40, 0xf2, 0xee, 0xd9, 0x23, 0x12, 0xa3, 0xa8, 0xdf, 0xd0, 0x7c, 0x77, 0x7f, 0x47, 0x08, 0x81, 0xc9, 0x64, 0x42, 0x96, 0xed, 0x74, 0x3d, 0x38, 0xd8, 0x47, 0x49, 0x85, 0x08, 0x11, 0x5f, 0x37, 0x08, 0xad, 0xf8, 0x66, 0xfe, 0x1a, 0x63, 0x34, 0x4a, 0x49, 0x84, 0x80, 0xbc, 0x97, 0x53, 0x6d, 0xb7, 0x54, 0xd5, 0x86, 0xdb, 0xdb, 0x5b, 0x06, 0xc5, 0x80, 0xe9, 0x74, 0x4a, 0x59, 0x96, 0xb4, 0xce, 0xb1, 0x5c, 0xae, 0x08, 0x78, 0xbc, 0xaf, 0x89, 0x7e, 0xc3, 0xed, 0xcd, 0xf5, 0xb7, 0x60, 0x02, 0x21, 0x1a, 0x82, 0x17, 0xbc, 0x78, 0xfa, 0x14, 0x81, 0xa7, 0xd3, 0x49, 0x19, 0x8f, 0xc7, 0x5c, 0x5e, 0xbe, 0xa2, 0xdf, 0x2b, 0x78, 0xfe, 0xfc, 0x39, 0x77, 0x77, 0x77, 0x1c, 0x1e, 0x1e, 0xb2, 0xde, 0x56, 0xec, 0x0d, 0x06, 0xf8, 0xda, 0xb2, 0x5f, 0x0c, 0x98, 0x5f, 0xcf, 0x89, 0x5a, 0xa0, 0x94, 0x04, 0x22, 0x26, 0x31, 0x44, 0x02, 0x1f, 0xfe, 0xe8, 0x43, 0xae, 0xae, 0xae, 0xd8, 0x54, 0x15, 0x21, 0x04, 0xac, 0xb5, 0xcc, 0x66, 0x33, 0x3a, 0x9d, 0xce, 0x8e, 0x0d, 0x09, 0xc8, 0x16, 0xef, 0x4a, 0xba, 0xdd, 0x5d, 0xf7, 0xe9, 0xe1, 0xde, 0x50, 0xe6, 0xdd, 0x9c, 0x10, 0x22, 0x31, 0x46, 0x94, 0x96, 0xbb, 0x35, 0xaf, 0x6b, 0xf6, 0x47, 0xfb, 0x68, 0x6d, 0x68, 0x5b, 0x4f, 0x51, 0x14, 0xa4, 0x69, 0x8a, 0x0b, 0x9e, 0x34, 0x49, 0x51, 0x26, 0x45, 0x6b, 0x4d, 0xde, 0xcd, 0x59, 0xbb, 0x2d, 0x42, 0x08, 0x62, 0x8c, 0x54, 0x55, 0x45, 0xd6, 0xed, 0x20, 0xc4, 0x8e, 0x7a, 0xa5, 0x14, 0xe5, 0x43, 0x49, 0x59, 0x96, 0x84, 0x10, 0x28, 0xcb, 0x12, 0x88, 0xa4, 0x69, 0x0a, 0x3a, 0x23, 0xed, 0x74, 0x18, 0x0c, 0x76, 0x51, 0xa2, 0xc7, 0x93, 0xe9, 0xc8, 0x98, 0x9d, 0x89, 0x8a, 0xa2, 0xa0, 0xdb, 0x4d, 0xe8, 0x66, 0x19, 0x59, 0x96, 0x91, 0x24, 0x09, 0x52, 0x28, 0x4e, 0x4e, 0x76, 0x99, 0xb3, 0xdd, 0x6e, 0x11, 0x5a, 0xe3, 0x1a, 0xcb, 0x20, 0xcf, 0xa9, 0xcb, 0x0d, 0x42, 0x08, 0xca, 0x79, 0x45, 0x8c, 0x11, 0x21, 0x04, 0x4d, 0xd3, 0xb0, 0x7a, 0x58, 0xb2, 0x58, 0x2c, 0x58, 0x2c, 0x16, 0x38, 0xe7, 0xc8, 0xb2, 0x0c, 0x63, 0x0c, 0x21, 0x04, 0xb6, 0xdb, 0x2d, 0xa7, 0x27, 0x27, 0x08, 0xb1, 0x6b, 0x76, 0x01, 0x08, 0xf1, 0x26, 0x67, 0xaa, 0xcd, 0xaa, 0x0a, 0x6f, 0x0c, 0xb8, 0xb8, 0xbf, 0xa3, 0x75, 0x39, 0xab, 0xc5, 0x92, 0x08, 0x18, 0x63, 0x18, 0x14, 0x03, 0xaa, 0x6a, 0x8b, 0xf7, 0x9e, 0x6e, 0x37, 0xc7, 0xb6, 0x16, 0xa3, 0x35, 0xcd, 0xa6, 0xe2, 0xf6, 0x6a, 0xc6, 0x60, 0xb8, 0x47, 0x8c, 0xbb, 0x70, 0xf4, 0xa1, 0xa5, 0x75, 0x16, 0xa5, 0x14, 0xe7, 0xe7, 0xe7, 0x6f, 0xe5, 0xd9, 0x2b, 0x06, 0x38, 0xe7, 0x98, 0xcd, 0x66, 0x0c, 0x06, 0x03, 0xf2, 0x5e, 0x0f, 0x21, 0x04, 0x3e, 0x78, 0x10, 0xd0, 0x4b, 0x0d, 0x5f, 0x7d, 0x75, 0x21, 0x75, 0xb9, 0x5e, 0xfe, 0x49, 0xfd, 0x50, 0x62, 0xdb, 0x40, 0xeb, 0x1a, 0xb6, 0x1b, 0x81, 0x54, 0x1a, 0x29, 0x25, 0xad, 0xab, 0xd1, 0x2a, 0x41, 0x4a, 0x89, 0x52, 0x02, 0xe7, 0x2c, 0xb6, 0xb1, 0x60, 0x02, 0x51, 0x78, 0x06, 0xc3, 0x21, 0x59, 0xb7, 0x8b, 0x94, 0xfa, 0x8d, 0x24, 0x02, 0xa9, 0xa0, 0x5f, 0xec, 0x61, 0x8c, 0xe1, 0xf1, 0xe3, 0xc7, 0x64, 0x59, 0xc6, 0x68, 0x6f, 0xc8, 0xb3, 0x67, 0xcf, 0x78, 0x78, 0x78, 0x60, 0x3c, 0x1e, 0x33, 0xd8, 0x1b, 0x62, 0x3a, 0x1d, 0x9a, 0x5a, 0xa3, 0x92, 0x84, 0xf7, 0xa7, 0x87, 0x9c, 0x9f, 0x3f, 0x0e, 0x3a, 0x06, 0x85, 0x6d, 0x2c, 0x4d, 0x5d, 0xf3, 0xe8, 0xf4, 0x31, 0x49, 0xaa, 0x88, 0x40, 0xbf, 0xdf, 0x47, 0x29, 0x85, 0x49, 0x34, 0x3b, 0xf9, 0x05, 0x02, 0x70, 0x2e, 0x40, 0x80, 0x44, 0x29, 0x9c, 0x75, 0x2c, 0x96, 0x4b, 0x84, 0x90, 0xc4, 0x28, 0x11, 0x18, 0x4e, 0x4e, 0xde, 0x01, 0xb1, 0x5b, 0xf3, 0x2c, 0xcb, 0x98, 0x4c, 0x26, 0xb8, 0xc6, 0xd2, 0xed, 0x76, 0xc9, 0xb2, 0x8c, 0xf1, 0x78, 0xcc, 0xc9, 0xe9, 0x3b, 0x68, 0x99, 0x90, 0x24, 0x1d, 0x5a, 0x07, 0xfd, 0x7e, 0x5f, 0x7c, 0xf4, 0xab, 0x5f, 0xf5, 0xb4, 0x73, 0x56, 0xf8, 0x58, 0x13, 0x45, 0xcd, 0xc7, 0x1f, 0x7f, 0x4e, 0xaf, 0x97, 0x23, 0x95, 0x24, 0x4d, 0x53, 0xf2, 0x3c, 0x27, 0xef, 0x65, 0xf4, 0x7b, 0x39, 0xae, 0x6d, 0xf1, 0xde, 0xa3, 0xb5, 0x21, 0xd1, 0x09, 0x32, 0x46, 0x8a, 0x5e, 0x1f, 0x84, 0x25, 0xc6, 0x2d, 0x21, 0xd4, 0xc4, 0x98, 0x20, 0x84, 0x26, 0x49, 0x13, 0x92, 0x24, 0x79, 0xdb, 0x6f, 0x89, 0x36, 0x24, 0x49, 0x42, 0x51, 0x14, 0x08, 0x21, 0xd0, 0x46, 0xe3, 0x83, 0xa5, 0xf5, 0x0d, 0x88, 0x16, 0x21, 0x45, 0x9c, 0x4c, 0x27, 0x1b, 0xdd, 0xeb, 0xa7, 0x6b, 0xdb, 0x96, 0xb8, 0x76, 0x45, 0xa7, 0x23, 0xa8, 0xeb, 0x0d, 0xde, 0x7b, 0xe4, 0xa0, 0xe0, 0x76, 0xfb, 0x80, 0x75, 0x39, 0xce, 0xe5, 0xa4, 0x69, 0x87, 0xb2, 0x5c, 0x93, 0x24, 0x0a, 0xa3, 0x24, 0x22, 0x44, 0x82, 0xef, 0xe3, 0x83, 0xa5, 0xb6, 0x37, 0x54, 0x5b, 0x8d, 0x54, 0x0d, 0x3d, 0x35, 0x20, 0x86, 0x2e, 0xb6, 0xf1, 0x18, 0xb3, 0x03, 0xe4, 0x7d, 0x0b, 0x04, 0x62, 0x6c, 0x89, 0x31, 0xb2, 0xd9, 0x2c, 0xb0, 0x0f, 0x96, 0xed, 0x66, 0xfe, 0xe6, 0x23, 0x81, 0xaf, 0x2f, 0x2e, 0xd0, 0xdb, 0xaa, 0x4e, 0xb6, 0xd1, 0xb0, 0x7e, 0xb8, 0xe5, 0x64, 0x5a, 0xb0, 0x59, 0x57, 0x1c, 0x4e, 0x0e, 0x51, 0xda, 0xb3, 0x58, 0xac, 0x78, 0xfc, 0xdd, 0x82, 0xa6, 0x59, 0x12, 0x82, 0x66, 0xd0, 0xcf, 0x90, 0x01, 0xb4, 0x00, 0xdb, 0x38, 0x6c, 0x33, 0xe7, 0xe6, 0xf6, 0x15, 0xaf, 0x2e, 0x7e, 0x0b, 0xf6, 0x94, 0x4d, 0xde, 0xa3, 0x2a, 0xfa, 0x04, 0x25, 0xe8, 0xf5, 0x86, 0x64, 0x69, 0xc1, 0xba, 0xac, 0x99, 0x5f, 0xcf, 0x11, 0xa2, 0x45, 0x6a, 0x8f, 0x73, 0x15, 0xbe, 0xa9, 0x70, 0xb6, 0xa2, 0xb5, 0x25, 0x55, 0xb9, 0x60, 0xeb, 0x5a, 0xf1, 0xd9, 0x27, 0xff, 0x9d, 0x69, 0x63, 0x0e, 0xfe, 0xea, 0xdf, 0x7f, 0xf9, 0x1f, 0xe7, 0xc7, 0x27, 0x9f, 0xc6, 0xc3, 0xfd, 0xb3, 0x74, 0xff, 0x60, 0x64, 0x9a, 0xf6, 0xd1, 0xba, 0xb1, 0x9b, 0xb4, 0x18, 0x74, 0x9a, 0xff, 0x7b, 0xf2, 0x45, 0xe1, 0xdc, 0x6a, 0x6b, 0xad, 0x73, 0x49, 0x92, 0x93, 0xc9, 0x7d, 0x68, 0x53, 0x2e, 0x2f, 0x2f, 0xf9, 0xe8, 0xa3, 0x8f, 0xf8, 0xf8, 0x37, 0xbf, 0xe6, 0x7b, 0xdf, 0x7f, 0x3f, 0xfd, 0xe3, 0x9f, 0xd0, 0x18, 0xd3, 0xc9, 0x3f, 0xfe, 0xe4, 0x37, 0x3f, 0x49, 0xfb, 0x56, 0x1d, 0x1d, 0x1d, 0xa3, 0x65, 0xca, 0x76, 0x6b, 0x59, 0xad, 0x56, 0x84, 0x68, 0x91, 0x2a, 0xe0, 0xbd, 0x45, 0xc5, 0x88, 0x51, 0xd0, 0x49, 0x25, 0xdb, 0x4d, 0x73, 0x58, 0x5e, 0xf7, 0xcb, 0x5f, 0xfc, 0xc3, 0x3f, 0x57, 0xff, 0x0f, 0x14, 0xc9, 0x62, 0x82, 0xa2, 0xfd, 0xb2, 0x85, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; k9copy/src/main/CMakeLists.txt0000644000175000017550000000000012412271774017013 0ustar emulatoremulatork9copy/src/main/k9langselect.h0000644000175000017550000000313412412271774017024 0ustar emulatoremulator// // C++ Interface: // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9LANGSELECT_H #define K9LANGSELECT_H #include "k9common.h" #include #include "ui_langselectw.h" #include "k9main.h" class k9Main; class k9DVD; class ckLvLangItem : public QTreeWidgetItem { public: ckLvLangItem( QTreeWidgetItem *parent,k9Main *dlg) : QTreeWidgetItem( parent,1001) { mainDlg=dlg; streamType=NONE; setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled); setOn(false); } bool isOn() { return checkState(0)==Qt::Checked;} void setOn(bool value) { setCheckState(0, value ? Qt::Checked : Qt::Unchecked);} eStreamType streamType; k9Main *mainDlg; QString language; void stateChange(bool state); }; class k9LangSelect : public QWidget { Q_OBJECT public: k9LangSelect(k9Main *mainWindow,QWidget* parent = 0); ~k9LangSelect(); void setMain(k9Main* _value); void fillLvLanguages(); void update(); void clear(); void selectAll(bool _state); QTreeWidget *listView() { return Ui_langSelect.lvLanguages;} /*$PUBLIC_FUNCTIONS$*/ public slots: /*$PUBLIC_SLOTS$*/ void listViewItemChanged(QTreeWidgetItem*,int); protected: /*$PROTECTED_FUNCTIONS$*/ k9Main * m_main; k9DVD *m_dvd; QList langAudItems; QList langSubItems; void updateLvLang(const eStreamType streamType,const QString & lang ); protected slots: /*$PROTECTED_SLOTS$*/ private: Ui::langSelect Ui_langSelect; }; #endif k9copy/src/main/k9playbackoptions.h0000644000175000017550000000327012412271774020106 0ustar emulatoremulator// // C++ Interface: // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9PLAYBACKOPTIONS_H #define K9PLAYBACKOPTIONS_H #include "k9main.h" #include "k9common.h" #include "ui_playbackoptionsw.h" #include "k9dvd.h" #include "k9dvdtitle.h" #include class lbItem : public QListWidgetItem { protected: k9DVDTitle *m_title; public: lbItem(QListWidget * listbox, const QString & text = QString::null ): QListWidgetItem(text,listbox) {} ; void setTitle(k9DVDTitle *_value) { m_title = _value; } k9DVDTitle *getTitle() const { return m_title; } }; class k9Main; class k9PlaybackOptions : public QWidget { Q_OBJECT public: k9PlaybackOptions(k9Main *mainWindow,QWidget* parent = 0); ~k9PlaybackOptions(); /*$PUBLIC_FUNCTIONS$*/ void fillTitleList(); k9DVD *m_dvd; k9Main *m_main; void setDvd(k9DVD* _value) {m_dvd = _value;} void setMain(k9Main* _value); void setSequence(); void titleRenamed (k9DVDTitle *_title, QString _newName); bool withMenus() ; void setwithMenus(bool _value); void enable(bool _value); void clear(); public slots: /*$PUBLIC_SLOTS$*/ virtual void ckMenuClick(); protected: /*$PROTECTED_FUNCTIONS$*/ QList lstAudioDef; QList lstSubDef; protected slots: /*$PROTECTED_SLOTS$*/ virtual void cbDefAudioActivated(int _index); virtual void cbDefSubActivated(int _index); virtual void lbSequenceChanged (QListWidgetItem * _item,QListWidgetItem *); private: Ui::PlaybackOptionsw Ui_playbackOptionsw; }; #endif k9copy/src/main/k9cropselect.cpp0000755000175000017550000002074412412271774017412 0ustar emulatoremulator/************************************************************************** * Developer: Pauline123 , (C) 2014 * Copyright (C) 2005 by Jean-Michel Petit * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "k9common.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "k9cropselect.h" #include "kviewmpeg2.h" #if QT_VERSION >= 0x050000 #include #else #include #endif #include k9CropSelect::k9CropSelect(QWidget *parent):QWidget(parent) { Ui_viewMPEG2.setupUi(this); #if QT_VERSION >= 0x050000 setWindowTitle((i18n("Crop selection"))); #else setWindowTitle(KDialog::makeStandardCaption(i18n("Crop selection"),this)); #endif Ui_viewMPEG2.bPlay->setIcon(SmallIcon("media-playback-start")); Ui_viewMPEG2.bStop->setIcon(SmallIcon("media-playback-stop")); m_widget=NULL; connect(&m_player , SIGNAL(setPosition(uint)), this, SLOT(setPosition(uint))); connect(&m_player , SIGNAL(setMax(uint)), this, SLOT(setMax(uint))); connect(&m_player , SIGNAL(setMin(uint)), this, SLOT(setMin(uint))); connect(&m_timer , SIGNAL(timeout()),this, SLOT(drawImage())); lockSlider=false; stopped=true; m_layout=new QGridLayout(Ui_viewMPEG2.label); m_player.getDecoder()->setViewMpeg2(this); // connect(m_player.getDecoder() , SIGNAL(pixmapReady(QImage *)), this, SLOT(drawPixmap(QImage *))); m_widget=new k9Widget(Ui_viewMPEG2.label); m_layout->addWidget(m_widget,0,0); m_drawing=false; } void k9CropSelect::setRect(QRect _crop) { Ui_viewMPEG2.sbTop->setValue(_crop.top()); Ui_viewMPEG2.sbLeft->setValue(_crop.left()); Ui_viewMPEG2.sbRight->setValue(_crop.right()); Ui_viewMPEG2.sbBottom->setValue(_crop.bottom()); m_rect=_crop; } QRect k9CropSelect::getRect() { QRect r; r.setCoords(Ui_viewMPEG2.sbLeft->value(),Ui_viewMPEG2.sbTop->value(),Ui_viewMPEG2.sbRight->value(),Ui_viewMPEG2.sbBottom->value()); return r; } void k9CropSelect::readSettings() { m_player.stop(); //KSimpleConfig settings("K9Copy"); k9Config config; } k9CropSelect::~k9CropSelect() { stopped=true; m_player.stop(); } void k9CropSelect::lock() { mutex.lock(); } void k9CropSelect::unlock() { mutex.unlock(); } void k9CropSelect::setPosition( uint _position) { if (!lockSlider) Ui_viewMPEG2.slider->setValue(_position); } void k9CropSelect::setMax( uint _position) { Ui_viewMPEG2.slider->setMaximum(_position); } void k9CropSelect::setMin(uint _position) { Ui_viewMPEG2.slider->setMinimum(_position); } double k9CropSelect::getDistance(QRgb color1,QRgb color2) { int B1,B2,R1,R2,G1,G2,A1,A2; QColor c1 (color1); c1.getRgb (&R1,&G1,&B1,&A1); QColor c2 (color2); c2.getRgb(&R2,&G2,&B2,&A2); int distance= sqrt(pow((double)R1-(double)R2,2)) + sqrt(pow((double)G1-(double)G2,2)) +sqrt(pow((double)B1-(double)B2,2)); return distance==255. ? 0. : distance; //Distance(C1,C2) = sqrt((R1-R2)² + (G1-G2)² + (B1-B2)²) } void k9CropSelect::bCropDetectClick() { lock(); int width=img.width(); int height=img.height(); int top=0,bottom=height,left=0,right=width; //scanning top crop bool found=false; for (int y=2; y <(height/2) && !found;y++) { for ( int x=0; x<(width/2) && !found;x++) { double distance=getDistance(m_origImage.pixel(1,1),m_origImage.pixel(x,y)); if (distance>10.) { top=y; found=true; } } } //scanning bottom crop found=false; for (int y=height-2; y >(height/2) && !found;y--) { for ( int x=0; x<(width/2) && !found;x++) { double distance=getDistance(m_origImage.pixel(1,1),m_origImage.pixel(x,y)); if (distance>10.) { bottom=y; found=true; } } } //scanning Left crop found=false; for ( int x=0; x<(width/2) && !found;x++) { for (int y=0; y <(height/2) && !found;y--) { double distance=getDistance(m_origImage.pixel(1,1),m_origImage.pixel(x,y)); if (distance>10.) { left=x; found=true; } } } //scanning Right crop found=false; for ( int x=(width-2); x>(width/2) && !found;x++) { for (int y=0; y <(height/2) && !found;y--) { double distance=getDistance(m_origImage.pixel(1,1),m_origImage.pixel(x,y)); if (distance>10.) { right=x; found=true; } } } unlock(); Ui_viewMPEG2.sbTop->setValue(top); Ui_viewMPEG2.sbBottom->setValue(bottom); Ui_viewMPEG2.sbLeft->setValue(left); Ui_viewMPEG2.sbRight->setValue(right); } void k9CropSelect::sbValueChanged(int){ lock(); m_rect.setCoords(Ui_viewMPEG2.sbLeft->value(),Ui_viewMPEG2.sbTop->value(),Ui_viewMPEG2.sbRight->value(),Ui_viewMPEG2.sbBottom->value()); unlock(); if (!m_player.isRunning()) { drawImage(&m_origImage); } } void k9CropSelect::drawCropping() { QPainter p(&img); p.setOpacity(0.5); QBrush br(Qt::yellow); p.setBrush(br); p.fillRect(0,0,img.width(),m_rect.top(),br); p.fillRect(0,m_rect.bottom(),img.width(),img.height()-m_rect.bottom(),br); p.fillRect(0,0,m_rect.left(),img.height(),br); p.fillRect(m_rect.right(),0,img.width()-m_rect.right(),img.height(),br); p.end(); } void k9CropSelect::drawImage(QImage *image) { if (m_drawing) return; lock(); m_drawing=true; QMutex mutex; mutex.lock(); img=*image; m_origImage=img.copy(); drawCropping(); m_wplay.wait(&mutex,40); m_widget->setImage( &img); m_drawing=false; unlock(); } /** No descriptions */ void k9CropSelect::drawImage() { /*if (qApp==NULL) return; if (m_mutex.tryLock()) { m_widget->setImage( &img); if (qApp!=NULL) m_mutex.unlock(); } */ m_wplay.wakeAll(); } void k9CropSelect::bPlayClick() { m_timer.start(40); m_player.play(); } int k9CropSelect::open (k9DVD *_dvd,k9DVDTitle * title,int chapter) { Ui_viewMPEG2.sbLeft->setMaximum(title->getwidth().toInt()/2); Ui_viewMPEG2.sbRight->setMaximum(title->getwidth().toInt()-1); Ui_viewMPEG2.sbRight->setMinimum(title->getwidth().toInt()/2); Ui_viewMPEG2.sbTop->setMaximum(title->getheight().toInt()/2); Ui_viewMPEG2.sbBottom->setMinimum(title->getheight().toInt()/2); Ui_viewMPEG2.sbBottom->setMaximum(title->getheight().toInt()-1); m_timer.start(40); bool play=m_player.isRunning(); m_player.open(_dvd->getdvd()->getDvd(), _dvd->getDevice(),title,chapter); if (play) bPlayClick(); return 1; } /** No descriptions */ void k9CropSelect::setError(const QString & err) { error=true; errMsg=err; } void k9CropSelect::resizeEvent(QResizeEvent *) {} void k9CropSelect::bStopClick() { m_player.stop(); } void k9CropSelect::sliderReleased() { pause=true; int i; i=Ui_viewMPEG2.slider->value(); m_player.updatePos(i); lockSlider=false; } void k9CropSelect::closeEvent( QCloseEvent* ce ) { stopped=true; ce->accept(); return; } /** No descriptions */ void k9CropSelect::sliderPressed() { lockSlider=true; } k9copy/src/main/k9copy.cpp0000644000175000017550000003676312412312650016213 0ustar emulatoremulator// // C++ Implementation: k9copy // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #include "k9main.h" #include "k9copy.h" #include "k9settings.h" #include "k9playbackoptions.h" #include "k9langselect.h" #include #include #include #include #include #include "k9importfiles.h" #include #include "kviewmpeg2.h" #include "k9titlefactor.h" #include "k9mp4title.h" #include "k9tools.h" #include #include "images.h" //PM DVDNAV #include "dvdread.h" #include "dvdread/dvd_reader.h" #include #include "k9dialogs.h" #include "k9assistant.h" #include "k9videocodecs.h" #include "k9audiocodecs.h" #include "k9importfiles.h" #if QT_VERSION >= 0x050000 #include #include #ifndef FALSE #define FALSE (0) #endif #ifndef TRUE #define TRUE (!FALSE) #endif #include #include #else #include #include #include #endif k9Copy::k9Copy() : KXmlGuiWindow( ) { // accept dnd m_import=NULL; m_mp4=NULL; setAcceptDrops(true); m_style=qApp->style()->objectName(); setDockOptions(QMainWindow::AllowTabbedDocks |QMainWindow::AnimatedDocks); setCorner(Qt::BottomRightCorner,Qt::RightDockWidgetArea); setCorner(Qt::TopRightCorner,Qt::RightDockWidgetArea); setCorner(Qt::BottomLeftCorner,Qt::LeftDockWidgetArea); // then, setup our actions setupActions(); // and a status bar statusBar()->show(); m_drives=new k9CdDrives(this); k9Config config; #if QT_VERSION >= 0x050000 createCopyWindows(); sbFactorQt=new QLabel(this); statusBar()->addPermanentWidget(sbFactorQt,0); sbSelSizeQt=new QLabel(this); statusBar()->addPermanentWidget(sbSelSizeQt,0); setupGUI(); #else createCopyWindows(); statusBar()->insertItem(i18n("Ready"),sbMessage,1); statusBar()->setItemAlignment(sbMessage,Qt::AlignLeft | Qt::AlignVCenter); statusBar()->insertFixedItem("",sbFactor); statusBar()->setItemFixed(sbFactor,100); statusBar()->insertFixedItem("",sbSelSize); statusBar()->setItemFixed(sbSelSize,100); setupGUI(); #endif // backupAction->setChecked(true); int output=config.getOutputDev(); updateDock(output<100?0:output-100); k9Dialogs::setMainWidget(this); setDvdOpened(false); } bool k9Copy::foundGtkStyle() { foreach (QString s , QStyleFactory::keys()) { if (s.toLower()=="gtk+") { return true; } } return false; } void k9Copy::setGtkStyle(bool _checked) { if (_checked) { if (foundGtkStyle()) qApp->setStyle("gtk+"); } else qApp->setStyle(m_style); k9Config config; config.setGtkStyle(_checked); config.save(); } void k9Copy::createCopyWindows() { m_dockMP4=new QDockWidget(this); m_dockFactor=new QDockWidget(this); m_dockPlayback=new QDockWidget(this); m_actions["open"]->setEnabled(true); m_actions["quit"]->setEnabled(true); m_actions["preferences"]->setEnabled(true); m_actions["copy"]->setEnabled(true); m_actions["eject"]->setEnabled(true); m_actions["wizard"]->setEnabled(true); k9Config config; m_useXine=config.getUseXine(); m_usePhonon=config.getUsePhonon(); m_useMplayer=config.getUseMplayer(); m_useDvdAuthor=config.getUseDvdAuthor(); m_k9Main=new k9Main(this,0,m_drives); setCentralWidget(m_k9Main); m_factors =new k9TitleFactor( this); m_factors->setUseDvdAuthor(m_useDvdAuthor); QDockWidget *doc=m_dockFactor;//i18n("Shrink Factor"),this,Qt::Tool); doc->setObjectName("factors"); doc->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable |QDockWidget::DockWidgetClosable ); QDockWidget *firstDock=doc; doc->setWidget(m_factors); doc->setWindowTitle(i18n("Shrink Factor")); addDockWidget(Qt::BottomDockWidgetArea, doc); connect(m_k9Main,SIGNAL(SelectionChanged( k9DVD*,bool )),m_factors,SLOT(SelectionChanged( k9DVD*,bool ))); connect(m_k9Main,SIGNAL(changedTitle( k9DVDTitle* )),m_factors,SLOT(changedTitle( k9DVDTitle* ))); m_mp4=new k9MP4Title(this); doc=m_dockMP4;//i18n("MPEG4 Encoding Options"),this,Qt::Tool); doc->setObjectName("mp4title"); doc->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable |QDockWidget::DockWidgetClosable); doc->setWidget(m_mp4); doc->setWindowTitle(i18n("MPEG4 Encoding Options")); addDockWidget(Qt::BottomDockWidgetArea, doc); tabifyDockWidget(firstDock,doc); connect(m_k9Main,SIGNAL(changedTitle( k9DVDTitle* )),m_mp4,SLOT(titleChanged( k9DVDTitle* ))); connect(m_k9Main,SIGNAL(SelectionChanged( k9DVD*,bool )),m_mp4,SLOT(selectionChanged( k9DVD*,bool ))); connect(m_mp4,SIGNAL(updateSelection()),m_k9Main,SLOT(updateSelection())); // allow the view to change the statusbar and caption connect(m_k9Main, SIGNAL(changeStatusbar(const QString&,int )), this, SLOT(changeStatusbar(const QString&,int))); connect(m_k9Main, SIGNAL(changeCaption(const QString&)), this, SLOT(changeCaption(const QString&))); doc=m_dockPlayback; doc->setObjectName("playbackoptions"); firstDock=doc; doc->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable |QDockWidget::DockWidgetClosable); m_options=new k9PlaybackOptions(m_k9Main,this); doc->setWidget(m_options); doc->setWindowTitle(i18n("DVD playback options")); addDockWidget(Qt::RightDockWidgetArea, doc); m_lang=new k9LangSelect(m_k9Main,this); doc=new QDockWidget(this);//,this,Qt::Tool); doc->setObjectName("langselect"); doc->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable |QDockWidget::DockWidgetClosable); doc->setWidget(m_lang); doc->setWindowTitle(i18n("Selection")); addDockWidget(Qt::RightDockWidgetArea, doc); tabifyDockWidget(firstDock,doc); if (m_useXine) { m_mp2=new k9xine(this); } else if (m_usePhonon) { m_mp2=new k9Phonon(this); }else if (m_useMplayer) m_mp2=new K9Mplayer(this); else m_mp2=new kViewMPEG2(this); doc=new QDockWidget(this);//i18n("Preview"),this,Qt::Tool); doc->setObjectName("preview"); m_dockPreview=doc; doc->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable |QDockWidget::DockWidgetClosable ); doc->setWidget(m_mp2); doc->setWindowTitle(i18n("Preview")); addDockWidget(Qt::RightDockWidgetArea, doc); tabifyDockWidget(firstDock,doc); connect(m_k9Main,SIGNAL(showPreview( k9DVD*, k9DVDTitle*,int )),m_mp2,SLOT(open( k9DVD*, k9DVDTitle*,int ))); connect(m_k9Main,SIGNAL(stopPreview()),m_mp2,SLOT(bStopClick())); setAutoSaveSettings(); } void k9Copy::removeToolWindows() { /* for (KMdiToolViewAccessor *acc=m_ToolViews.first();acc;acc=m_ToolViews.next()) { deleteToolWindow(acc); } m_ToolViews.clear(); */ } void k9Copy::createImportWindows() { if (!m_import) m_import=new k9ImportFiles(this); m_import->show(); k9Dialogs::setMainWidget(m_import); hide(); } k9Copy::~k9Copy() { } void k9Copy::initCodecs() { k9VideoCodecs v(NULL); v.reset(); k9AudioCodecs a(NULL); a.reset(); } bool k9Copy::queryClose ( ) { return true; } void k9Copy::setupActions() { #if QT_VERSION >= 0x050000 CopyAction = new QAction(QIcon("dvdcopy"),i18n("Copy"),this); #else CopyAction = new KAction(KIcon("dvdcopy"),i18n("Copy"),this); #endif connect(CopyAction, SIGNAL(triggered(bool)), SLOT(ActionCopy())); m_actions["copy"]=CopyAction; #if QT_VERSION >= 0x050000 ejectAction = new QAction(QIcon("media-eject"),i18n("Eject"),this); #else ejectAction = new KAction(KIcon("media-eject"),i18n("Eject"),this); #endif connect(ejectAction, SIGNAL(triggered(bool)), SLOT(ActionEject())); m_actions["eject"]=ejectAction; #if QT_VERSION >= 0x050000 wizardAction = new QAction(QIcon("tools-wizard"),i18n("Wizard"),this); #else wizardAction = new KAction(KIcon("tools-wizard"),i18n("Wizard"),this); #endif connect(wizardAction, SIGNAL(triggered(bool)), SLOT(ActionWizard())); m_actions["wizard"]=wizardAction; #if QT_VERSION >= 0x050000 authorAction = new QAction(QIcon("author"),i18n("DVD Author"),this ); #else authorAction = new KAction(KIcon("author"),i18n("DVD Author"),this ); #endif connect(authorAction, SIGNAL(triggered(bool)), SLOT(ActionAuthor())); m_actions["author"]=authorAction; m_actions["open"]=KStandardAction::open(this, SLOT(fileOpen()), (QObject*)actionCollection()); m_actions["quit"]=KStandardAction::quit(this, SLOT(quit()),(QObject*) actionCollection()); m_actions["preferences"]=KStandardAction::preferences(this,SLOT(preferences()),(QObject*)actionCollection()); KStandardAction::keyBindings(this, SLOT(optionsConfigureKeys()), (QObject*)actionCollection()); KStandardAction::configureToolbars(this, SLOT(optionsConfigureToolbars()), (QObject*)actionCollection()); setStandardToolBarMenuEnabled(TRUE); createStandardStatusBarAction(); QStringList slEnv=QProcess::systemEnvironment(); bool bGtk=true; foreach (QString env,slEnv) { if (env.startsWith("KDE_FULL_SESSION=true")) bGtk=false; } if (bGtk && foundGtkStyle()) { #if QT_VERSION >= 0x050000 m_actions["gtk-style"]=new QAction(QIcon("configure"),i18n("Use Gtk Style"),this); #else m_actions["gtk-style"]=new KAction(KIcon("configure"),i18n("Use Gtk Style"),this); #endif m_actions["gtk-style"]->setCheckable(true); connect(m_actions["gtk-style"],SIGNAL(triggered(bool)),this,SLOT(setGtkStyle(bool))); k9Config config; if (config.getGtkStyle()) { m_actions["gtk-style"]->setChecked(true); qApp->setStyle("gtk+"); } } actionCollection()->addAction("Copy",CopyAction); actionCollection()->addAction("Eject",ejectAction); actionCollection()->addAction("Wizard",wizardAction); actionCollection()->addAction("author",authorAction); actionCollection()->addAction("gtk-style",m_actions["gtk-style"]); } void k9Copy::setActions( bool enabled) { m_actions["open"]->setEnabled(enabled); m_actions["quit"]->setEnabled(enabled); m_actions["preferences"]->setEnabled(enabled); m_actions["copy"]->setEnabled(enabled); m_actions["wizard"]->setEnabled(enabled); m_actions["eject"]->setEnabled(enabled); m_mp2->setEnabled(enabled); m_mp4->setEnabled(enabled); m_factors->setEnabled(enabled); m_lang->setEnabled(enabled); m_options->setEnabled(enabled); } void k9Copy::optionsConfigureKeys() { KShortcutsDialog::configure(actionCollection()); } void k9Copy::optionsConfigureToolbars() { KEditToolBar dlg(factory()); connect(&dlg,SIGNAL(newToolbarConfig()),this,SLOT(newToolbarConfig())); dlg.exec(); } void k9Copy::newToolbarConfig() { // this slot is called when user clicks "Ok" or "Apply" in the toolbar editor. // recreate our GUI, and re-apply the settings (e.g. "text under icons", etc.) createGUI(0); } void k9Copy::fileOpen() { m_k9Main->Open(); } void k9Copy::preferences() { k9Settings settings(this,i18n("Settings")); settings.exec(); k9Config config; m_useXine=config.getUseXine(); m_usePhonon=config.getUsePhonon(); m_useMplayer=config.getUseMplayer(); // if (m_k9MainView) { m_k9Main->readSettings(); m_mp2->close(); if (m_useMplayer) m_mp2=new K9Mplayer(this); else if (m_useXine) m_mp2=new k9xine(this); else if (m_usePhonon) m_mp2=new k9Phonon(this); else m_mp2=new kViewMPEG2(this); m_dockPreview->setWidget(m_mp2); connect(m_k9Main,SIGNAL(showPreview( k9DVD*, k9DVDTitle*,int )),m_mp2,SLOT(open( k9DVD*, k9DVDTitle*,int ))); connect(m_k9Main,SIGNAL(stopPreview()),m_mp2,SLOT(bStopClick())); m_mp4->load(); // } } void k9Copy::ActionCopy() { if (m_useMplayer) ((K9Mplayer*)m_mp2)->bStopClick(); else if (m_useXine) ((k9xine*)m_mp2)->bStopClick(); else if (m_usePhonon) ((k9Phonon*)m_mp2)->bStopClick(); else ((kViewMPEG2*)m_mp2)->bStopClick(); m_k9Main->Copy(); } void k9Copy::ActionPlayTitle() { // m_previewAcc->show(); m_k9Main->PreviewTitle(); } void k9Copy::ActionMP4() { m_k9Main->CreateMP4(); } void k9Copy::ActionMPEG() { m_k9Main->extractMPEG2(); } void k9Copy::ActionEject() { m_k9Main->eject(); } void k9Copy::ActionBackup() { createCopyWindows(); } void k9Copy::ActionAuthor() { createImportWindows(); } void k9Copy::ActionCreate() { // m_k9Import->execute(); } void k9Copy::ActionWizard() { hide(); k9Assistant *ast=k9Assistant::createAssistant(); k9Dialogs::setMainWidget(ast); ast->run(); show(); } /*KMdiToolViewAccessor * k9Copy::setToolWindow(QWidget *_widget,KDockWidget::DockPosition _pos,const QString &tabToolTip,const QString &tabCaption) { KMdiToolViewAccessor *acc=addToolWindow(_widget, _pos, getMainDockWidget(),0,tabToolTip,tabCaption); m_ToolViews.append(acc); return acc; } void k9Copy::removeToolWindow(KMdiToolViewAccessor *toolWin) { deleteToolWindow(toolWin); m_ToolViews.removeRef(toolWin); } */ void k9Copy::changeStatusbar(const QString& text,int id) { // display the text on the statusbar #if QT_VERSION >= 0x050000 switch(id) { case sbMessage: statusBar()->showMessage(text,0); break; case sbFactor: sbFactorQt->setText(text); break; case sbSelSize: sbSelSizeQt->setText(text); break; } #else statusBar()->changeItem(text,id); #endif } void k9Copy::changeCaption(const QString& text) { // display the text on the caption setCaption(text); } void k9Copy::clone( QString _input,QString _output) { show(); m_k9Main->Clone( _input,_output); } void k9Copy::setInput(QString _input) { m_k9Main->setInput(_input); } void k9Copy::setOutput(QString _output) { m_k9Main->setOutput(_output); } void k9Copy::quit() { close( ); } void k9Copy::saveDock() { // KConfig config("K9Copy"); // if (m_k9MainView) { // dockManager->writeConfig(&config,"dock"); // m_k9Main->saveSettings(); // } else if (m_k9ImportView) { // dockManager->writeConfig(&config,"dockImport"); // } } void k9Copy::closeEvent( QCloseEvent* ce ) { m_k9Main->saveSettings(); saveAutoSaveSettings(); ce->accept(); qApp->quit(); } void k9Copy::setDvdOpened(bool _state) { m_actions["eject"]->setEnabled(_state); m_actions["copy"]->setEnabled(_state); } void k9Copy::updateDock(int _output) { switch ((k9Main::eOutput)_output) { case k9Main::oDVD: case k9Main::oISO: case k9Main::oFolder: case k9Main::oMPEG2: removeDockWidget(m_dockMP4); restoreDockWidget(m_dockFactor); restoreDockWidget(m_dockPlayback); break; case k9Main::oMP4 : restoreDockWidget(m_dockMP4); removeDockWidget(m_dockFactor); removeDockWidget(m_dockPlayback); if (m_mp4) m_mp4->setOptions(k9MP4Title::optAll); break; case k9Main::oAudio: restoreDockWidget(m_dockMP4); removeDockWidget(m_dockFactor); removeDockWidget(m_dockPlayback); if (m_mp4) m_mp4->setOptions(k9MP4Title::optAudio); break; } } k9copy/src/main/k9playbackoptions.cpp0000644000175000017550000001356012412271774020444 0ustar emulatoremulator// // C++ Implementation: // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9playbackoptions.h" #if QT_VERSION >= 0x050000 #include #else #include #endif #include k9PlaybackOptions::k9PlaybackOptions(k9Main *mainWindow, QWidget* parent) : QWidget(parent) { Ui_playbackOptionsw.setupUi(this); setMain( mainWindow); m_main->setPlaybackOptions(this); enable(false); k9Config config; Ui_playbackOptionsw.ckMenu->setChecked(config.getKeepMenus()); ckMenuClick(); } k9PlaybackOptions::~k9PlaybackOptions() { } /*$SPECIALIZATION$*/ void k9PlaybackOptions::setMain(k9Main* _value) { m_main = _value; m_dvd=m_main->dvd; } void k9PlaybackOptions::fillTitleList() { QString txt; if (Ui_playbackOptionsw.lbSequence->currentItem() !=NULL) Ui_playbackOptionsw.lbSequence->currentItem()->text(); Ui_playbackOptionsw.lbSequence->clear(); k9DVDTitle *title=m_dvd->getstart(); bool found=title !=NULL; //Reconstitution de l'ordre de lecture à partir des titres du DVD while (found) { if (title->isSelected()) { lbItem *item=new lbItem(Ui_playbackOptionsw.lbSequence,title->getname()); item->setTitle(title); if (title->getname()==txt) Ui_playbackOptionsw.lbSequence->setCurrentItem(item); } title=title->getnextTitle(); found=title!=NULL; } for (int i=0;igettitleCount();i++) { k9DVDTitle* l_track=m_dvd->gettitle(i); if (l_track->getIndexed()) { QString sTitle=l_track->getname(); if(l_track->isSelected()) { bool foundtitle=false; for (int j=0; jcount();j++) { lbItem *tmp=(lbItem*)Ui_playbackOptionsw.lbSequence->item(j); if (tmp->getTitle() == l_track) foundtitle=true; } if (!foundtitle) { lbItem *item=new lbItem(Ui_playbackOptionsw.lbSequence,sTitle); item->setTitle(l_track); if (sTitle==txt) Ui_playbackOptionsw.lbSequence->setCurrentItem(item); } } } } if (Ui_playbackOptionsw.lbSequence->currentRow()==-1) Ui_playbackOptionsw.lbSequence->setCurrentRow(0); setSequence(); enable(!Ui_playbackOptionsw.ckMenu->isChecked() ); } void k9PlaybackOptions::ckMenuClick() { if (m_main!=NULL) { enable((!Ui_playbackOptionsw.ckMenu->isChecked()) && m_dvd->getopened()); m_main->updateFactor(); } else enable(false); } void k9PlaybackOptions::setSequence() { for (int i=0;i gettitleCount();i++) m_dvd->gettitle(i)->setnextTitle( NULL); lbItem *lbi = (lbItem*)Ui_playbackOptionsw.lbSequence->item(0); if (lbi !=NULL) { lbItem *lbi2; m_dvd->setstart(lbi->getTitle()); for (int i=0 ; i < Ui_playbackOptionsw.lbSequence->count()-1;i++) { lbi=(lbItem*)Ui_playbackOptionsw.lbSequence->item(i); lbi2=(lbItem*)Ui_playbackOptionsw.lbSequence->item(i+1); lbi->getTitle()->setnextTitle(lbi2->getTitle()); } } } void k9PlaybackOptions::lbSequenceChanged(QListWidgetItem *_item,QListWidgetItem *) { if (_item == NULL) return; lbItem *lbi=(lbItem*) _item; k9DVDTitle *title=lbi->getTitle(); Ui_playbackOptionsw.cbDefAudio->clear(); Ui_playbackOptionsw.cbDefSub->clear(); lstAudioDef.clear(); lstSubDef.clear(); Ui_playbackOptionsw.cbDefAudio->addItem(i18n("default")); lstAudioDef.append(NULL); Ui_playbackOptionsw.cbDefSub->addItem(i18n("none")); lstSubDef.append(NULL); for (int i=0;i < title->getaudioStreamCount();i++) { if (title->getaudioStream(i)->getselected()) { // if ( !title->getDefAudioSet()) // title->setDefAudio(title->getaudioStream(i)); Ui_playbackOptionsw.cbDefAudio->addItem( QString("%1 - %2").arg(title->getaudioStream(i)->getID()).arg(title->getaudioStream(i)->getlanguage())); if (title->getaudioStream(i)==title->getDefAudio()) { Ui_playbackOptionsw.cbDefAudio->setCurrentIndex(Ui_playbackOptionsw.cbDefAudio->count()-1); } lstAudioDef.append(title->getaudioStream(i)); } } for (int i=0;i < title->getsubPictureCount();i++) { if (title->getsubtitle(i)->getselected()) { QPixmap icon; Ui_playbackOptionsw.cbDefSub->addItem(QString("%1 - %2").arg(title->getsubtitle(i)->getID().first()).arg(title->getsubtitle(i)->getlanguage())); if (title->getsubtitle(i)==title->getDefSubtitle()) { Ui_playbackOptionsw.cbDefSub->setCurrentIndex(Ui_playbackOptionsw.cbDefSub->count()-1); } lstSubDef.append(title->getsubtitle(i)); } } } void k9PlaybackOptions::cbDefAudioActivated(int _index) { int cur=Ui_playbackOptionsw.lbSequence->currentRow(); lbItem *lbi=(lbItem*)Ui_playbackOptionsw.lbSequence->item(cur); lbi->getTitle()->setDefAudio(lstAudioDef.at(_index)); } void k9PlaybackOptions::cbDefSubActivated(int _index) { int cur=Ui_playbackOptionsw.lbSequence->currentRow(); lbItem *lbi=(lbItem*)Ui_playbackOptionsw.lbSequence->item(cur); lbi->getTitle()->setDefSubtitle(lstSubDef.at(_index)); } void k9PlaybackOptions::titleRenamed (k9DVDTitle *_title, QString _newName) { for (int j=0; jcount();j++) { lbItem *tmp=(lbItem*)Ui_playbackOptionsw.lbSequence->item(j); if (tmp->getTitle() == _title) { Ui_playbackOptionsw.lbSequence->item(j)->setText(_newName); break; } } } bool k9PlaybackOptions::withMenus() { return Ui_playbackOptionsw.ckMenu->isChecked(); } void k9PlaybackOptions::setwithMenus(bool _value) { Ui_playbackOptionsw.ckMenu->setChecked(_value); } void k9PlaybackOptions::enable(bool _value) { Ui_playbackOptionsw.frPlayback->setEnabled(_value); } void k9PlaybackOptions::clear() { Ui_playbackOptionsw.lbSequence->clear(); enable(false); } k9copy/src/main/k9main.h0000644000175000017550000001633012412271774015631 0ustar emulatoremulator// // C++ Interface: // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9MAIN_H #define K9MAIN_H #include "k9common.h" #include "k9cddrive.h" #include "ui_k9mainw.h" #include "k9playbackoptions.h" #include #include #include "k9copy.h" #include #if QT_VERSION >= 0x050000 #include #else #include #endif #include #include #include enum eStreamType {SUB,AUD,VID,NONE,CHAP} ; enum eObjectType {TITLE,CHAPTER,TITLESET,STREAM,ROOT}; class LvItem : public QTreeWidgetItem { public: LvItem( QTreeWidgetItem *parent,eObjectType _objectType) : QTreeWidgetItem( parent,1000), obj( NULL ) { objectType=_objectType; } LvItem( QTreeWidget *parent,eObjectType _objectType) : QTreeWidgetItem( parent,1000), obj( NULL ) { objectType=_objectType; } eObjectType objectType; QObject *obj; // virtual int rtti () const; bool operator< ( const QTreeWidgetItem & other ) const ; // void paintCell ( QPainter * p, const QColorGroup & cg, int column, int width, int align ); }; class k9Main; class k9DVD; class k9DVDAudioStream; class k9DVDSubtitle; class k9DVDTitle; class k9PlaybackOptions; class k9LangSelect; class k9UpdateFactor; class ckLvItem : public QTreeWidgetItem { public: ckLvItem( QTreeWidgetItem *parent,k9Main *dlg,eObjectType _objectType); ckLvItem( QTreeWidget *parent,k9Main *dlg,eObjectType _objectType); eStreamType streamType; eObjectType objectType; k9Main *mainDlg; k9DVDTitle *mainTitle; void *obj; void *stream; QString language; // virtual int rtti () const; // void paintCell ( QPainter * p, const QColorGroup & cg, int column, int width, int align ); // int compare ( QListViewItem * i, int col, bool ascending ) const; double getstreamSize(); bool isOn() { return checkState(0)==Qt::Checked; } void setOn(bool value) { setCheckState(0, value ? Qt::Checked : Qt::Unchecked); } void stateChange(bool state); bool renamed(QString _text) { if (_text != m_text) { _text=m_text; return true; } return false; }; bool operator< ( const QTreeWidgetItem & other ) const ; private: bool m_checked; QString m_text; }; class k9DVDListItem : public QObject { Q_OBJECT public: k9DVDAudioStream *audioStream; k9DVDSubtitle *subtitle; k9DVDTitle *title; ckLvItem *listItem; eStreamType streamType; public: k9DVDListItem(void *DVD,ckLvItem *List,eStreamType type); }; class k9ListColumn : public QObject { Q_OBJECT private: int m_column; public: k9ListColumn (QTreeWidget *parent, int column):QObject((QObject*)parent),m_column(column) {} public slots: void setVisible(bool); }; class k9Main : public QWidget { Q_OBJECT public: enum eOutput {oDVD=0,oISO=1,oFolder=2,oMP4=3,oAudio=4,oMPEG2=5}; enum eInput {iDVD=0,iISO=1,iFolder=2}; k9Main(QWidget* parent = 0, const char* name = 0, k9CdDrives *_drives=0 ); ~k9Main(); /*$PUBLIC_FUNCTIONS$*/ void addTitle(k9DVDTitle *track); void addChapters(QTreeWidgetItem *_parent,k9DVDTitle *_title); void checkAll(bool state); void checkTS( bool _state,ckLvItem *_item ); void checkTitle(bool state, ckLvItem *_item); void checkLang(QString lang, eStreamType streamType,bool state); bool getupdating(); void saveSettings(); void setDVDSize(); static bool compare(double v1,double v2); void readSettings(); void resizeColumns(); bool getquickScan() { return m_quickScan; }; void setPlaybackOptions(k9PlaybackOptions *_value) { m_playbackOptions=_value; }; void setLangSelect(k9LangSelect *_value) { m_langSelect=_value; }; QList *getItems() { return &items; }; void updateFactor(); bool withMenus(); k9DVD *dvd; void eject(); QTreeWidget *getTreeView() { return listView1; }; private slots: virtual void listView1CurrentChanged( QTreeWidgetItem *,QTreeWidgetItem* ); virtual void bSaveClick(); virtual void cbOutputDevActivated(int); virtual void bInputOpenClick(); virtual void bInputOpenDirClick(); virtual void cbInputChanged(int); virtual void cbOutputChanged(int); virtual void updateFactor_internal(); virtual void deviceAdded(k9CdDrive *_drive); virtual void deviceRemoved(k9CdDrive *_drive); virtual void expanded(QTreeWidgetItem*); virtual void collapsed (QTreeWidgetItem*); virtual void listView1ItemChanged(QTreeWidgetItem*,int); virtual void showPopup(const QPoint & iPosition); public slots: /*$PUBLIC_SLOTS$*/ virtual void PreviewTitle(); virtual void CreateMP4(); virtual void extractMPEG2 (); virtual void extractAudio(); virtual void Copy(); virtual void Open(); virtual void Clone(QString _input,QString _output); virtual void setInput(QString _input); virtual void setOutput(QString _output); virtual void volumeChanged(const QString &device,const QString &volumeName); virtual void updateSelection(); void setDrives(k9CdDrives* _value); protected: /*$PROTECTED_FUNCTIONS$*/ bool m_ready; QTreeWidget *listView1; QList items; QList columns; k9DVDListItem *addListItem(void *DVD,ckLvItem *List,eStreamType type); void readDrives(); void addDrive (k9CdDrive *_drive); k9Copy *m_parent; QVector tsItems; QVector chItems; ckLvItem * root; QList driveList; QList recorderList; k9CdDrives *drives; QPixmap pxVideo; QPixmap pxSound; QPixmap pxText; QPixmap pxChapter; QMutex m_mutex; bool updating; bool fspFinish; long fspAvail; void closeDVD(); QString getDevice(QComboBox *_combo); k9UpdateFactor *m_update; //PREFERENCES QString m_prefOutput; bool m_useDvdAuthor; bool m_quickScan; int m_prefSize; bool m_prefK3b; bool m_prefMenu; bool m_prefAutoBurn; k9PlaybackOptions *m_playbackOptions; k9LangSelect *m_langSelect; QDockWidget *m_dockWidget; void resizeEvent ( QResizeEvent * event ); void showEvent ( QShowEvent * event); protected slots: /*$PROTECTED_SLOTS$*/ void itemRenamed ( QTreeWidgetItem *item, int col ); signals: // Signals /** No descriptions */ void sig_progress(QString str); void changeStatusbar(const QString& str,int id); void changeCaption(const QString& str); void showPreview(k9DVD *_dvd,k9DVDTitle * title,int chapter); void stopPreview(); void SelectionChanged(k9DVD *_dvd,bool _withMenus); void changedTitle(k9DVDTitle *_title); private: void fillLvLanguages(); void updateLvLang(const eStreamType streamType,const QString & lang) ; long getFreeSpace(const QString & _path); void clearItems(); Ui::MainDlg Ui_MainDlg; }; #endif k9copy/src/main/kviewmpeg2.h0000755000175000017550000000636112412271774016527 0ustar emulatoremulator/************************************************************************** * Developer: Pauline123 , (C) 2014 * Copyright (C) 2005 by Jean-Michel Petit * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef KVIEWMPEG2_H #define KVIEWMPEG2_H #include "k9dvdtitle.h" #include #include "ui_viewmpeg2.h" #include #include #include #include #include #include "k9plaympeg2.h" #include "k9mplayer.h" #include "k9xine.h" #include "k9phonon.h" #include "k9internalplayer.h" #include /** *@author */ class k9Widget : public QWidget { Q_OBJECT protected: QImage m_image; QMutex m_mutex; void paintEvent ( QPaintEvent * _event); public: k9Widget (QWidget *_parent); void setImage(QImage *_image); }; class kViewMPEG2 : public QWidget,k9InternalPlayer { Q_OBJECT public: kViewMPEG2(QWidget *parent); ~kViewMPEG2(); virtual void drawImage( QImage *image); private: QMutex mutex; k9DVDTitle *m_title; QString dev; int selTitle; unsigned long idxLect; bool pause; bool lockSlider; QImage img; bool stopped; /** No descriptions */ void lock(); void unlock(); QString file; QString errMsg; bool error; QString length; uint startSector; uint lastSector; k9PlayMPEG2 m_player; QGridLayout *m_layout; k9Widget *m_widget; Ui::ViewMPEG2 Ui_viewMPEG2; QMutex m_mutex; QTimer m_timer; QWaitCondition m_wplay; protected: void closeEvent( QCloseEvent* ); void resizeEvent ( QResizeEvent * ); public slots: // Public slots /** No descriptions */ int open (k9DVD *_dvd,k9DVDTitle * title,int chapter); void sbValueChanged(int) {} void bCropDetectClick() {} void setError(const QString & err); void setPosition(uint _position); void setMax(uint _position); void setMin(uint _position); void bPlayClick(); void bStopClick(); void readSettings(); void sliderReleased(); void sliderPressed(); void drawImage(); }; #endif k9copy/src/main/prefAuthor.ui0000644000175000017550000001670112417731553016751 0ustar emulatoremulator prefAuthor 0 0 598 478 Authoring options Audio 100 0 AC3 MP2 128 160 192 224 256 320 384 448 Format false Bitrate false Qt::Horizontal QSizePolicy::Expanding 151 21 Qt::Vertical QSizePolicy::Expanding 20 60 Buttons Width false Qt::Horizontal QSizePolicy::Expanding 121 31 Height false 480 0 480 700 0 700 Font Hilite color false Text color false KPushButton KPushButton
kpushbutton.h
KColorButton KPushButton
kcolorbutton.h
kpushbutton.h kcolorbutton.h kcolorbutton.h bButtonFont clicked() prefAuthor bButtonFontClicked() 20 20 20 20
k9copy/src/main/k9cropselect.h0000755000175000017550000000626612412271774017062 0ustar emulatoremulator/************************************************************************** * Developer: Pauline123 , (C) 2014 * Copyright (C) 2005 by Jean-Michel Petit * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef K9CROPSELECT_H #define K9CROPSELECT_H #include "k9dvdtitle.h" #include #include "ui_viewmpeg2.h" #include #include #include #include #include #include "k9plaympeg2.h" #include "k9mplayer.h" #include "k9xine.h" #include "k9phonon.h" #include "k9internalplayer.h" #include #include class k9Widget; class k9CropSelect : public QWidget,k9InternalPlayer { Q_OBJECT public: k9CropSelect(QWidget *parent); ~k9CropSelect(); virtual void drawImage( QImage *image); private: QMutex mutex; k9DVDTitle *m_title; QString dev; int selTitle; unsigned long idxLect; bool pause; bool lockSlider; bool m_drawing; QImage img,m_origImage; bool stopped; /** No descriptions */ void lock(); void unlock(); QString file; QString errMsg; bool error; QString length; uint startSector; uint lastSector; k9PlayMPEG2 m_player; QGridLayout *m_layout; k9Widget *m_widget; Ui::ViewMPEG2 Ui_viewMPEG2; QTimer m_timer; QWaitCondition m_wplay; double getDistance(QRgb color1,QRgb color2) ; QRect m_rect; protected: void closeEvent( QCloseEvent* ); void resizeEvent ( QResizeEvent * ); public slots: // Public slots /** No descriptions */ int open (k9DVD *_dvd,k9DVDTitle * title,int chapter); void setError(const QString & err); void setPosition(uint _position); void setMax(uint _position); void setMin(uint _position); void bPlayClick(); void bStopClick(); void readSettings(); void sliderReleased(); void sliderPressed(); void drawImage(); void bCropDetectClick(); void sbValueChanged(int); void setRect(QRect _crop); void drawCropping(); QRect getRect(); }; #endif k9copy/src/main/k9prefpreview.h0000644000175000017550000000131612412271774017241 0ustar emulatoremulator// // C++ Interface: // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9PREFPREVIEW_H #define K9PREFPREVIEW_H #include "k9common.h" #include "ui_prefpreview.h" class k9prefPreview : public QWidget { Q_OBJECT public: k9prefPreview(QWidget* parent = 0); ~k9prefPreview(); /*$PUBLIC_FUNCTIONS$*/ void save(); public slots: /*$PUBLIC_SLOTS$*/ void rbInternalClick(); void rbMplayerClick(); void rbXineClick(); void rbPhononClick(); protected: /*$PROTECTED_FUNCTIONS$*/ void load(); protected slots: /*$PROTECTED_SLOTS$*/ private: Ui::prefPreview Ui_prefPreview; }; #endif k9copy/src/core/0000755000175000017550000000000012417731553014272 5ustar emulatoremulatork9copy/src/core/k9progress.h0000644000175000017550000000257312412271774016561 0ustar emulatoremulator// // C++ Interface: // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9PROGRESS_H #define K9PROGRESS_H #include "k9common.h" #include "ui_progress.h" #include #include #include "k9drawimage.h" #include #include class k9Progress : public QDialog { Q_OBJECT public: k9Progress(QWidget* parent = 0); ~k9Progress(); virtual k9Process * getProcess() const; virtual void setProgress(long _position,long _total); virtual void setLabelText(const QString _text); virtual void setElapsed(const QString _text); virtual void setTitle(const QString _text); virtual void setImage(QString _fileName) ; virtual void setImage(const QImage &_image); virtual void setMovie(QString _fileName); virtual int execute(); bool getCanceled() const; /*$PUBLIC_FUNCTIONS$*/ public slots: /*$PUBLIC_SLOTS$*/ protected: /*$PROTECTED_FUNCTIONS$*/ k9Process *m_process; k9DrawImage *m_wimage; bool m_canceled; void closeEvent ( QCloseEvent * event ); void showEvent ( QShowEvent * event ); protected slots: /*$PROTECTED_SLOTS$*/ void bCancelClick(); void gbOutputToggled(bool state); private: Ui::Progress Ui_Progress; int m_outputSize; QMovie *m_movie; }; #endif k9copy/src/core/k9process.cpp0000644000175000017550000000701412412271774016721 0ustar emulatoremulator// // C++ Implementation: k9process // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "k9process.h" #include "k9common.h" #include #include #include "k9tools.h" #include #include "k9dialogs.h" k9Process::k9Process(QObject *parent, const char *) : KProcess(parent),m_waitSync(false) { setOutputChannelMode (KProcess::SeparateChannels); //connect(this,SIGNAL(processExited( K3Process* )),this,SLOT(slotProcessExited( K3Process* ))); connect(this,SIGNAL(readyReadStandardError ()),this,SLOT(slotReadyReadStandardError ())); connect(this,SIGNAL(readyReadStandardOutput ()),this,SLOT(slotReadyReadStandardOutput ())); connect(this,SIGNAL(finished ( int , QProcess::ExitStatus )),this,SLOT(slotFinished(int, QProcess::ExitStatus))); connect(this,SIGNAL(started()),this,SLOT(slotStarted())); connect(this,SIGNAL(error(QProcess::ProcessError)),this,SLOT(slotError(QProcess::ProcessError))); m_shellCmd=false; m_debugOutput=false; } k9Process::~k9Process() { } void k9Process::syncStart() { m_waitSync=true; QEventLoop eventLoop; m_eventLoop=&eventLoop; eventLoop.exec(); } void k9Process::sync() { m_waitSync=true; if (state() == QProcess::NotRunning) return; QEventLoop eventLoop; m_eventLoop=&eventLoop; //QApplication::eventLoop()->enterLoop(); eventLoop.exec(); } void k9Process::slotReadyReadStandardError() { QByteArray ba=readAllStandardError(); getStderr(ba); emit receivedStderr(ba.data(), ba.length()); emit receivedStderr(this,ba.data(), ba.length()); } void k9Process::slotReadyReadStandardOutput() { QByteArray ba=readAllStandardOutput(); getStdout(ba); emit receivedStdout( ba.data(), ba.length()); emit receivedStdout(this, ba.data(), ba.length()); } void k9Process::getStdout(QByteArray ba) { if (m_debugOutput) { qDebug() << ba; } } void k9Process::getStderr(QByteArray ba) { if (m_debugOutput) { qDebug() << ba; } } void k9Process::wait() { waitForFinished(-1); } void k9Process::slotFinished( int,QProcess::ExitStatus) { if (m_waitSync) { //QApplication::eventLoop()->exitLoop(); m_eventLoop->exit(); m_waitSync=false; } emit processExited(this); } void k9Process::slotStarted() { if (m_waitSync) { m_eventLoop->exit(); m_waitSync=false; } } void k9Process::slotError(QProcess::ProcessError ) { if (m_waitSync) { m_eventLoop->exit(); m_waitSync=false; } } const QString & k9Process::debug() { m_debug=""; for (int i=0;i { public: static bool compareItems ( k9CellCopyVTS *item1,k9CellCopyVTS *item2 ); }; class k9CellCopyList : public QList { public: k9CellCopyList(k9DVDRead * _dvdHandle,k9DVD *_DVD); double getfactor(bool _withMenus,bool _streams); double gettotalSize(); double getforcedSize(bool _withFactor); double getMinFactor(bool _withMenus); k9CellVTSList VTSList; ~k9CellCopyList(); void addInbytes(const uint64_t& _value) { m_inbytes += _value; } void addOutbytes(const uint64_t& _value) { m_outbytes += _value; } void addFrcinbytes(const uint64_t& _value) { m_frcinbytes += _value; } void addFrcoutbytes(const uint64_t& _value) { m_frcoutbytes += _value; } private: k9DVD *DVD; k9DVDRead *dvdHandle; uint64_t m_inbytes,m_outbytes; uint64_t m_frcinbytes,m_frcoutbytes; void fill(); k9Cell *addCell(int _VTS,int _pgc,int _id,uint32_t startSector,uint32_t lastSector,uchar _angleBlock); bool checkSelected(k9Cell *_cell); void addStreams(k9DVDTitle *_title,k9Cell *_cell); void setVTS(uint _numVTS,uint32_t _size); //QPtrList VTSList; void sortVTSList(); void clearList(); }; #endif k9copy/src/core/k9dvdbackupinterface.h0000644000175000017550000000374212412271774020540 0ustar emulatoremulator/*************************************************************************** * Copyright (C) 2007 by Jean-Michel * * jm_petit@laposte.net * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef K9DVDBACKUPINTERFACE_H #define K9DVDBACKUPINTERFACE_H #include #include class k9vamps; class k9DVDBackupInterface : public QObject { Q_OBJECT public: enum eStreamType { AUDIO,SUBPICTURE,VIDEO,NAV}; k9DVDBackupInterface(QObject *parent = 0); ~k9DVDBackupInterface(); protected: k9vamps *m_vamps; public slots: virtual void setVamps(k9vamps *_vamps) {m_vamps=_vamps;} virtual k9vamps *getVamps() {return m_vamps;}; virtual void getOutput(uchar *buffer,uint32_t size) =0; virtual void getOutput(eStreamType streamType,int streamNumber,uchar *buffer,uint32_t size)=0; }; #endif k9copy/src/core/k9dvdread.cpp0000644000175000017550000000656712412306626016663 0ustar emulatoremulator// // C++ Implementation: k9dvdread // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9dvdread.h" //PM DVDNAV #include "dvdread.h" #include "dvdread/dvd_reader.h" #include "k9ifo2.h" k9DVDRead::k9DVDRead(){ m_dvd=NULL; } void k9DVDRead::deleteIfos() { // while (!m_ifos.isEmpty()) delete m_ifos.takeFirst(); qDeleteAll(m_ifos); m_ifos.clear(); } void k9DVDRead::deleteFiles() { // while (!m_files.isEmpty()) delete m_files.takeFirst(); qDeleteAll(m_files); m_files.clear(); } k9DVDRead::~k9DVDRead() { if (m_dvd !=NULL) close(); deleteIfos(); deleteFiles(); } k9DVDFile::k9DVDFile(k9DVDRead *_dvd) { m_file=NULL; m_dvd=_dvd; } k9DVDFile::~k9DVDFile() { if (m_file != NULL) close(); } /*! \fn k9DVDRead::openDevice(const QString & _device) */ void k9DVDRead::openDevice(const QString & _device) { m_dvd=DVDOpen(_device.toUtf8()); //turn UDF cache off //DVDUDFCacheLevel(m_dvd, 0 ); if (m_dvd) { k9Ifo2 *ifoz=new k9Ifo2(this); ifoz->openIFO(0); m_ifos.append(ifoz); ifo_handle_t *hifoz=ifoz->getIFO(); if(!hifoz) { m_dvd=NULL; return; } int nrTS= hifoz->vmgi_mat->vmg_nr_of_title_sets; for (int iTS=1 ; iTS<=nrTS;iTS++) { k9Ifo2 *ifo=new k9Ifo2(this); if (!ifo->openIFO(iTS)) { close(); return; } m_ifos.append(ifo); } } } k9Ifo2 *k9DVDRead::getIfo(int _num) { k9Ifo2 *ifo=m_ifos[_num]; return ifo; } QString k9DVDRead::getDiscId() { uchar ID[17]; QString id=""; if (DVDDiscID(m_dvd,ID) !=-1) { ID[16]=0; id=QString::fromLatin1((const char*)ID); } return id; } /*! \fn k9DVDRead::close() */ void k9DVDRead::close() { DVDClose(m_dvd); deleteIfos(); deleteFiles(); m_dvd=NULL; } bool k9DVDRead::opened() { return (m_dvd !=NULL); } k9DVDFile * k9DVDRead::openIfo(uint _vts) { k9DVDFile *file =new k9DVDFile(this); file->openIfo(_vts); m_files.append(file); return file; } k9DVDFile *k9DVDRead::openMenu(uint _vts) { k9DVDFile *file =new k9DVDFile(this); file->openMenu(_vts); m_files.append(file); return file; } k9DVDFile *k9DVDRead::openTitle(uint _vts) { k9DVDFile *file =new k9DVDFile(this); file->openTitle(_vts); m_files.append(file); return file; } /*! \fn k9DVDFile::openIfo(uint _vts) */ void k9DVDFile::openIfo(uint _vts) { m_file=DVDOpenFile(m_dvd->getDvd(),_vts,DVD_READ_INFO_FILE); } /*! \fn k9DVDFile::openMenu(uint _vts) */ void k9DVDFile::openMenu(uint _vts) { m_file=DVDOpenFile(m_dvd->getDvd() ,_vts,DVD_READ_MENU_VOBS); } /*! \fn k9DVDFile::openTitle(uint _vts) */ void k9DVDFile::openTitle(uint _vts) { m_file=DVDOpenFile(m_dvd->getDvd(),_vts,DVD_READ_TITLE_VOBS); } /*! \fn k9DVDFile::close() */ void k9DVDFile::close() { if (m_file !=NULL) { DVDCloseFile(m_file); m_file=NULL; } } /*! \fn k9DVDFile::read(uchar *_buffer,uint32_t _size) */ int k9DVDFile::readBytes(uchar *_buffer,uint32_t _size) { if (m_file !=NULL) return DVDReadBytes(m_file,_buffer,_size); else return -1; } int k9DVDFile::readBlocks(uint32_t _sector,uint32_t _size,uchar*_buffer) { if (m_file !=NULL) { return DVDReadBlocks(m_file,_sector,_size,_buffer); } else return -1; } k9copy/src/core/processList.ui0000644000175000017550000000704712417731553017153 0ustar emulatoremulator processList processList 0 0 600 480 Process List unnamed Processes true true Elapsed true true ... true true lProcess bCancel 0 0 0 0 &Cancel Alt+C 2 spacer1 Horizontal Expanding 361 20 bCancel clicked() processList bCancelClick() bCancelClick() kpushbutton.h k9copy/src/core/k9cellcopylist.cpp0000644000175000017550000002741212412271774017755 0ustar emulatoremulator/*************************************************************************** * Copyright (C) 2005 by Jean-Michel Petit * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "k9cellcopylist.h" #include "k9dvdtitle.h" #include "k9ifo2.h" bool k9CellVTSList::compareItems ( k9CellCopyVTS *item1, k9CellCopyVTS *item2 ) { k9CellCopyVTS * it1,*it2; it1=item1; it2=item2; if (it1->getsize() >it2->getsize()) return false; else if (it1->getsize() getsize()) return true; else { if (it1->getnum()>it2->getnum()) return false; else return true; } } uint k9CellCopyVTS::getnum() { return num; } void k9CellCopyVTS::addsize(uint32_t _size) { size+=_size; } uint64_t k9CellCopyVTS::getsize() { return size; } void k9CellCopyList::clearList() { while (!isEmpty()) delete takeFirst(); } k9CellCopyList::k9CellCopyList(k9DVDRead * _dvdHandle,k9DVD *_DVD) { //setAutoDelete(true); DVD=_DVD; dvdHandle=_dvdHandle; fill(); } k9CellCopyList::~k9CellCopyList() { clearList(); } /*! \fn k9CellCopyList::fill() */ void k9CellCopyList::fill() { // k9Ifo2 kifo(dvdHandle) ,kifoZero(dvdHandle); ifo_handle_t *hifo,*hifoZero; k9Ifo2 *kifo,*kifoZero; kifoZero=dvdHandle->getIfo(0); hifoZero=kifoZero->getIFO(); // kifoZero.openIFO( 0); int nrTS= hifoZero->vmgi_mat->vmg_nr_of_title_sets; for (int iTS=1 ; iTS<=nrTS;iTS++) { //kifo.openIFO( iTS); kifo=dvdHandle->getIfo(iTS); hifo=kifo->getIFO(); c_adt_t *c_adt = hifo->vts_c_adt; uint32_t length = c_adt->last_byte + 1 - C_ADT_SIZE; cell_adr_t *ptr; ptr= c_adt->cell_adr_table; uint32_t imax=length/sizeof(cell_adr_t); for (uint32_t i = 0; i startSector ==startSector && cell->vts==_VTS) { bFound=true; if (cell->lastSector!=lastSector ) qDebug("last sector doesn't match"); } if (!bFound && (_VTS vts || (startSectorstartSector && cell->vts ==_VTS ) )) { bInsert=true; position=i; } } if (!bFound) { cell = new k9Cell(); cell->vts=_VTS; cell->startSector=startSector; cell->lastSector=lastSector; cell->pgc=_pgc; cell->id=_id; cell->angleBlock=_angleBlock; cell->selected=checkSelected(cell); if (bInsert) insert(position,cell); else append(cell); uint32_t isize; isize= cell->selected ? ((lastSector-startSector)*2048):2; setVTS(_VTS,isize); } return(cell); } void k9CellCopyList::setVTS(uint _numVTS,uint32_t _size) { bool bfound=false; for (int iVTS=0; iVTSgetnum()==_numVTS) { VTS->addsize(_size); bfound=true; } } if (!bfound) { k9CellCopyVTS * VTS= new k9CellCopyVTS(_numVTS); VTS->addsize(_size); VTSList.append(VTS); } } void k9CellCopyList::sortVTSList() { qSort(VTSList.begin(),VTSList.end(),k9CellVTSList::compareItems); } void k9CellCopyList::addStreams(k9DVDTitle *_title,k9Cell *_cell) { k9DVDSubtitle *l_sub; k9DVDAudioStream *l_auds; for (int i=0;i<_title->getaudioStreamCount();i++) { l_auds=_title->getaudioStream(i); if (l_auds->getselected()) { bool found=false; foreach (int audio,_cell->audio) { if (audio == l_auds->getID()) found=true; } if (!found) _cell->audio.append(l_auds->getID()); } } for (int i=0;i<_title->getsubPictureCount();i++) { QString c; l_sub=_title->getsubtitle(i); if (l_sub->getselected()) { bool found=false; foreach ( int sub,_cell->subpicture) { if (l_sub->getID().contains(sub)) found=true; } if (!found) _cell->subpicture+=l_sub->getID(); } } } /*! \fn k9CellCopyList::checkSelected(k9Cell *_cell) */ bool k9CellCopyList::checkSelected(k9Cell *_cell) { bool selected=false; for (int i=0; i< DVD->gettitleCount();i++) { k9DVDTitle *title=DVD->gettitle(i); //FACTOR if ( title->getVTS()==_cell->vts && title ->isSelected()) { if ( title->getVTS()==_cell->vts) { // { && title ->isSelected()) { for (int j=0; j getchapterCount();j++) { k9DVDChapter * chapter= title->getChapter(j); if (_cell->startSector >= chapter->getstartSector() && _cell->startSector<=chapter->getendSector()) { //add a reference to the title in the titles list from the cell _cell->addTitle( title); //FACTOR // if (title->isSelected()) { if (chapter->getSelected()) { addStreams (title,_cell); selected=true; } } } } } return selected; } double k9CellCopyList::gettotalSize() { double totalSize=0; for (int iCell=0;iCellcopied) { if (cell->selected) { if (cell->angleBlock==angleNone) totalSize += cell->lastSector-cell->startSector; else if (cell->angleBlock==angleStart) { uint32_t start=0,end=0; start=cell->startSector; // loop inside the angle block to find the last sector. while (((k9Cell*)at(iCell))->angleBlock !=angleNone) { end=((k9Cell*)at(iCell))->lastSector; iCell++; } iCell--; totalSize += end-start; } } else totalSize += 1; // } } return (totalSize*2048); ; } //gives the final size of cells with a forced shrink factor double k9CellCopyList::getforcedSize(bool _withFactor) { double totalSize=0; for (int iCell=0;iCellgetFactor():1; double size=0; // if (!cell->copied) { if (cell->selected && cell->getforceFactor() ) { if (cell->angleBlock==angleNone) size = cell->lastSector-cell->startSector; else if (cell->angleBlock==angleStart) { uint32_t start=0,end=0; start=cell->startSector; // loop inside the angle block to find the last sector. while (((k9Cell*)at(iCell))->angleBlock !=angleNone) { end=((k9Cell*)at(iCell))->lastSector; iCell++; } iCell--; size += end-start; } totalSize += (size/factor); } // } } return (totalSize*2048); } double k9CellCopyList::getMinFactor(bool _withMenus) { double fforced=getforcedSize( false); double MaxSize=k9DVDSize::getMaxSize(); MaxSize*=1024*1024; double menuSize=0; if (_withMenus) menuSize=DVD->getmenuSize(); menuSize= menuSize*2048; //totalSize=part of dvd with auto shrink factor/2.5 //double totalSize=gettotalSize()+menuSize - (fforced-m_frcinbytes) -m_inbytes; double totalSize=gettotalSize()+menuSize - (fforced) -m_inbytes; totalSize/=2.50; qDebug() << QString("totalSize(%1)=gettotalSize()(%2)+menuSize(%3) -(fforced(%4))-m_inbytes(%6)").arg(totalSize).arg(gettotalSize()).arg(menuSize).arg(fforced).arg(m_frcinbytes).arg(m_inbytes); double minFactor=(fforced-m_frcinbytes) /(MaxSize- (totalSize +m_outbytes) - m_frcoutbytes) ; qDebug() << QString("minfactor(%1)=(fforced(%2) -m_frinbytes(%3))/(MacSize(%4)-totalSize(%5)-m_outbytes(%6) - m_frcoutbytes(%7))").arg(minFactor).arg(fforced).arg(m_frcinbytes).arg(MaxSize).arg(totalSize).arg(m_outbytes).arg(m_frcoutbytes); if (minFactor<1) minFactor=1; return minFactor; } double k9CellCopyList::getfactor(bool _withMenus,bool _streams) { double totalSize=gettotalSize(); if (_streams) { double unsel=0; for (int i=0;igettitleCount();i++) { k9DVDTitle *track=DVD->gettitle(i); for (int j=0; jgetaudioStreamCount();j++) { k9DVDAudioStream *audio=track->getaudioStream(j); if (! audio->getselected()) unsel+=audio->getsize_mb(); } for (int j=0; jgetsubPictureCount();j++) { k9DVDSubtitle *sub=track->getsubtitle(j); if (! sub->getselected()) unsel+=sub->getsize_mb(); } } unsel*=1024*1024; totalSize-=unsel; } double menuSize=0; if (_withMenus) menuSize=DVD->getmenuSize(); menuSize= menuSize*2048; double dvdSize=k9DVDSize::getMaxSize() ; dvdSize*=1024*1024; double factor; double fforced=getforcedSize(false)-m_frcinbytes; double fforcedsh=getforcedSize(true)-m_frcoutbytes; double dvdSize2=dvdSize-m_outbytes -fforcedsh; // dvdSize2 -=menuSize; if (dvdSize2 <0) { factor=2.5; //qDebug(QString("dvdSize (%1)- _outbytes(%2) - fforcedsh(%3)=%4").arg(dvdSize).arg(m_outbytes).arg(fforcedsh).arg(dvdSize2)); } else { factor=(totalSize +menuSize - fforced -m_inbytes)/ dvdSize2 ; factor = (int)(factor*100); factor /=100; factor+=0.01; // } // uint64_t o=m_outbytes; // uint64_t i=m_inbytes; //if (o==0) // o=1; //qDebug(QString("factor : %1 realise : %2").arg(factor).arg((double)i/(double)o)); if (factor<=1) factor=1; else if (factor>3) factor=3; } return (factor); } k9copy/src/core/k9log.cpp0000644000175000017550000000165012412271774016024 0ustar emulatoremulator#include "k9log.h" #include #include k9log m_instance; QMutex m_mutex; k9log::k9log() { } k9log::~k9log() { qDeleteAll(m_list); } void k9log::write(QString s) { QTextStream out (stdout); out << s; } void k9log::writer(QString s) { QTextStream out (stdout); out << s << "\r"; } void k9log::writeln(QString s) { QTextStream out (stdout); out << s <<"\n"; } void k9log::add(QString s,k9logLevel::type level) { k9logEntry *entry=new k9logEntry(); entry->level=level; entry->text=s; m_mutex.lock(); m_instance.list() << entry; m_mutex.unlock(); } k9logEntry* k9log::dequeue () { m_mutex.lock(); k9logEntry *entry=m_instance.list().dequeue(); m_mutex.unlock(); return entry; } int k9log::count() { int c; m_mutex.lock(); c=m_instance.list().count(); m_mutex.unlock(); return c; } QQueue &k9log::list() {return m_list;} k9copy/src/core/k9dvdtitleset.h0000644000175000017550000000170212412271774017241 0ustar emulatoremulator// // C++ Interface: k9dvdtitleset // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9DVDTITLESET_H #define K9DVDTITLESET_H #include #include #include "k9dvdtitle.h" class k9DVDTitleset { private: int m_num; uint32_t m_size; QList titles; bool m_selected; bool m_updating; bool m_audioStreams[8]; public: k9DVDTitleset( uint _num,uint32_t _size); virtual void add(k9DVDTitle *_title); virtual int count(); virtual k9DVDTitle *gettitle(uint _pos); virtual uint32_t getsize(); virtual const QString getsize_mb(); virtual bool getselected(); virtual void setselected(bool state); virtual void updateSelection(); virtual int getnum(); virtual void setAudio(int _id,bool _selected); virtual int getNewAudioStreamId(int _oldId); virtual ~k9DVDTitleset() {}; } ; #endif k9copy/src/core/k9burndvd.h0000644000175000017550000000576512412271774016367 0ustar emulatoremulator/************************************************************************** * Copyright (C) 2005 by Jean-Michel Petit * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef k9BurnDVD_H #define k9BurnDVD_H #include "k9burnprogress.h" /** @author Jean-Michel PETIT */ class k9BurnDVD: public QObject { Q_OBJECT public: k9BurnDVD(); ~k9BurnDVD(); virtual void setburnDevice( const QString& _newVal); virtual const QString& getburnDevice(); virtual QWidget* getDialog() {return progress;} void setworkDir( const QString& _newVal); void setvolId(QString _newVal); void setUseK3b(bool _newVal); void setAutoBurn (bool _newVal); void burn(); void makeIso(QString _filename); void setSpeed(const QString& _value) { m_speed = _value;} void setEject(bool theValue); bool isCancelled() { return cancelled;} private: QTime *time; k9BurnProgress *progress; k9Process *proc; k9Process *proc2; QString volId; float burnSpeed; QString burnDevice; QStringList lastMsg; QString workDir; QString m_filename; bool cancelled; bool useK3b; bool m_eject; bool autoBurn; bool iso; bool m_cdrkit; void burnWithGrowisofs(); void burnWithGenisoimage(); void getGenisoimageCmd(QStringList &_cmd,QString _fileName,bool _printSize); void getWodimCmd(QStringList &_cmd); void burnWithK3b(); void eject(const QString &device); const QString &getImageSize(); QString imageSize; QString m_speed; k9Config *m_config; private slots: // Private slots void growisoStderr( char *buffer, int buflen); void growisoStdout(char *buffer, int buflen); void mkisoSizeStderr(char *buffer, int buflen); void mkisoSizeStdout(char *buffer, int buflen); }; #endif k9copy/src/core/k9dvdtitle.cpp0000644000175000017550000003502312412271774017063 0ustar emulatoremulator/************************************************************************** * Copyright (C) 2005 by Jean-Michel Petit * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "k9dvdtitle.h" #include #include "k9dvdtitleset.h" #include "k9titleencopt.h" //*******************k9DVDAudioStream************** k9DVDAudioStream::k9DVDAudioStream() { size_mb=0; selected=false; } /** Read property of QString format. */ const QString& k9DVDAudioStream::getformat() { return format; } /** Read property of QString frequency. */ const QString& k9DVDAudioStream::getfrequency() { return frequency; } /** Read property of QString quantization. */ const QString& k9DVDAudioStream::getquantization() { return quantization; } /** Read property of int channels. */ const int& k9DVDAudioStream::getchannels() { return channels; } /** Read property of int appMode. */ const int& k9DVDAudioStream::getappMode() { return appMode; } /** Read property of QString content. */ const QString& k9DVDAudioStream::getcontent() { return content; } /** Read property of float size_mb. */ const float& k9DVDAudioStream::getsize_mb() { return size_mb; } /** Read property of bool selected. */ const bool& k9DVDAudioStream::getselected() { return selected; } /** Write property of bool selected. */ void k9DVDAudioStream::setselected( const bool& _newVal) { bool before=title->isSelected(); selected = _newVal; title->gettitleset()->setAudio(getID(),_newVal); title->gettitleset()->updateSelection(); bool after=title->isSelected(); if (after!=before) title->selectChapters( after); } /** Read property of QString langCod. */ const QString& k9DVDAudioStream::getlangCod() { return langCod; } /** Read property of QString language. */ const QString& k9DVDAudioStream::getlanguage() { return language; } k9DVDTitle * k9DVDAudioStream::gettitle() { return title; } int k9DVDAudioStream::getID() { return(id); } //*******************k9DVDSubtitle ******************* k9DVDSubtitle::k9DVDSubtitle() { size_mb=0; selected=false; } /** Read property of QString langCod. */ const QString& k9DVDSubtitle::getlangCod() { return langCod; } /** Read property of QString language. */ const QString& k9DVDSubtitle::getlanguage() { return language; } /** Read property of int num. */ const int& k9DVDSubtitle::getnum() { return num; } /** Read property of QString content. */ const QString& k9DVDSubtitle::getcontent() { return content; } /** Read property of bool selected. */ const bool& k9DVDSubtitle::getselected() { return selected; } /** Write property of bool selected. */ void k9DVDSubtitle::setselected( const bool& _newVal) { bool before=title->isSelected(); selected = _newVal; title->gettitleset()->updateSelection(); bool after=title->isSelected(); if (after!=before) title->selectChapters(after); } /** Read property of float size_mb. */ const float& k9DVDSubtitle::getsize_mb() { return size_mb; } k9DVDTitle * k9DVDSubtitle::gettitle() { return title; } /*! \fn k9DVDSubtitle::getID() */ QList& k9DVDSubtitle::getID() { return id; } //************************* k9DVDTitle *************************** /** No descriptions */ k9DVDAudioStream* k9DVDTitle::addAudioStream() { k9DVDAudioStream *auds; auds = new k9DVDAudioStream; auds->title=this; audioStreams.append(auds); return(auds); } /** No descriptions */ k9DVDSubtitle* k9DVDTitle::addSubtitle(int num) { k9DVDSubtitle *subt; subt = new k9DVDSubtitle; subt->title=this; subt->num=num; subtitles.append(subt); return(subt); } /** No descriptions */ k9DVDChapter* k9DVDTitle::addChapter(int num) { k9DVDChapter *chap; chap = new k9DVDChapter; chap->m_title=this; chap->num = num; chap->id=k9DVDChapter::getcptChapter(); chapters.append(chap); return(chap); } k9DVDChapter* k9DVDTitle::getChapter(int num) { return (k9DVDChapter*)chapters.at(num); } /** No descriptions */ k9DVDAudioStream *k9DVDTitle::getaudioStream(int num) { return (k9DVDAudioStream*)audioStreams.at(num); } /** Read property of int chapterCount. */ const int& k9DVDTitle::getchapterCount() { return chapterCount; } /** Read property of int streamCount. */ const int& k9DVDTitle::getstreamCount() { return streamCount; } /** Read property of int audioStreamCount. */ const int& k9DVDTitle::getaudioStreamCount() { return audioStreamCount; } /** Read property of int audioStreamCount. */ const int& k9DVDTitle::getsubPictureCount() { return subPictureCount; } /** Read property of int streamCount. */ const QTime& k9DVDTitle::getlength() { return length; } /** Read property of int streamCount. */ const int& k9DVDTitle::getnumTitle() { return numTitle; } /** No descriptions */ k9DVDSubtitle *k9DVDTitle::getsubtitle(int num) { return (k9DVDSubtitle*)subtitles.at(num); } /** Read property of float size_mb. */ const float& k9DVDTitle::getsize_mb() { return size_mb; } float k9DVDTitle::gettotalsize_mb() { float size =size_mb; for (int i=0;igetsize_mb(); } return size; } //If _selected=true, returns the size of selected chapters, otherwise returns size of //unselected ones float k9DVDTitle::getChaptersSize_mb(bool _selected) { return (getChaptersSize(_selected)/512); } //If _selected=true, returns the size of selected chapters, otherwise returns size of //unselected ones uint64_t k9DVDTitle::getChaptersSize(bool _selected) { uint64_t total=0; for (int i=0;igetSelected()==_selected) { total+= chap->getsectors(); } } for (int i=0;igetChaptersSize(_selected); } return total; } float k9DVDTitle::gettotalvideosize_mb() { float size =videosize_mb; for (int i=0;igetvideosize_mb(); } return size; } QTime k9DVDTitle::gettotallength() { QTime totalTime=getlength(); for (int i=0;igetlength()); totalTime=totalTime.addMSecs(msecs); } return totalTime; } QTime k9DVDTitle::getSelectedLength() { QTime totalTime(0,0); foreach (k9DVDChapter *chapter,chapters) { if (chapter->getSelected()) { QTime t; int msecs= t.msecsTo(chapter->getLength()); totalTime=totalTime.addMSecs(msecs); } } for (int i=0;i tchapters=tmp->getChapters(); foreach (k9DVDChapter *chapter,tchapters) { if (chapter->getSelected()) { QTime t; int msecs= t.msecsTo(chapter->getLength()); totalTime=totalTime.addMSecs(msecs); } } } return totalTime; } /** Read property of float videosize_mb. */ const float& k9DVDTitle::getvideosize_mb() { return videosize_mb; } /** Read property of int VTS. */ const int& k9DVDTitle::getVTS() { return VTS; } /** Read property of int TTN. */ const int& k9DVDTitle::getTTN() { return TTN; } /** Read property of float FPS. */ const float& k9DVDTitle::getFPS() { return FPS; } /** Read property of QString format. */ const QString& k9DVDTitle::getformat() { return format; } /** Read property of QString aspectRatio. */ const QString& k9DVDTitle::getaspectRatio() { return aspectRatio; } /** Read property of QString width. */ const QString& k9DVDTitle::getwidth() { return width; } /** Read property of QString height. */ const QString& k9DVDTitle::getheight() { return height; } /** Read property of QString palette. */ void k9DVDTitle::getpalette(int i,QString & c) { c=palette[i]; } /** Read property of QString DF. */ const QString& k9DVDTitle::getDF() { return DF; } /** Read property of int angleCount. */ const int& k9DVDTitle::getangleCount() { return angleCount; } bool k9DVDTitle::isSelected() { k9DVDAudioStream *l_auds; k9DVDSubtitle *l_sub; int i; if (forceSelection) return true; for (i=0;igetselected()) { return(true); } } for (i=0;igetselected()) { return(true); } } return(false); } void k9DVDTitle::setvideoSelected(bool _state,bool _updateChapters) { bool before=isSelected(); forceSelection = _state; gettitleset()->updateSelection(); bool after=isSelected(); if ((after!=before) && _updateChapters) { selectChapters(after); // emit selectionChanged(); } } /** Read property of QString name. */ const QString& k9DVDTitle::getname() { return name; } /** Write property of QString name. */ void k9DVDTitle::setname( const QString& _newVal) { name = _newVal; } /*! \fn k9DVDTitle::getpgc() */ int k9DVDTitle::getpgc() { return(pgc); } /*! \fn k9DVDTitle::setNextTitle(k9DVDTitle * nextTitle) */ void k9DVDTitle::setnextTitle(k9DVDTitle * nTitle) { nextTitle=nTitle; } /*! \fn k9DVDTitle::getnextTitle() */ k9DVDTitle* k9DVDTitle::getnextTitle() { return nextTitle; } k9DVDAudioStream* k9DVDTitle::getDefAudio() const { return m_defAudio; } void k9DVDTitle::setDefAudio(k9DVDAudioStream* _value) { m_defAudio = _value; m_defAudioSet = true; } k9DVDSubtitle* k9DVDTitle::getDefSubtitle() const { return m_defSubtitle; } void k9DVDTitle::setDefSubtitle(k9DVDSubtitle* _value) { m_defSubtitle = _value; m_defSubtitleSet=true; } void k9DVDTitle::clearAudioStreams() { // while (!audioStreams.isEmpty()) delete audioStreams.takeFirst(); qDeleteAll(audioStreams); audioStreams.clear(); } void k9DVDTitle::clearSubtitles() { //while (!subtitles.isEmpty()) delete subtitles.takeFirst(); qDeleteAll(subtitles); subtitles.clear(); } void k9DVDTitle::clearChapters() { // while (!chapters.isEmpty()) delete chapters.takeFirst(); qDeleteAll(chapters); chapters.clear(); } k9DVDTitle::k9DVDTitle(k9DVD *_dvd) { // audioStreams.setAutoDelete(true); // chapters.setAutoDelete(true); // subtitles.setAutoDelete(true); m_dvd=_dvd; size_mb=0; videosize_mb=0; vobusize_mb=0; nextTitle=NULL; m_defAudio=NULL; m_defSubtitle=NULL; m_defAudioSet=false; m_defSubtitleSet=false; forceSelection=false; m_forceFactor=false; m_factor=0; m_encOpt=NULL; m_mainTitle=NULL; } k9DVDTitle::~k9DVDTitle() { clearAudioStreams(); clearChapters(); clearSubtitles(); } k9TitleEncOpt* k9DVDTitle::getEncOpt() { if (!m_encOpt) m_encOpt=new k9TitleEncOpt(this); return m_encOpt; } void k9DVDTitle::setSelected(bool _state) { k9Config config; for (int i=0;i < getaudioStreamCount();i++) { if (_state) { bool sel=false; if (config.getPrefAudioLang().count()==0) sel=true; else sel=config.getPrefAudioLang().contains(getaudioStream(i)->getlangCod()); getaudioStream(i)->setselected(sel); //if ((getaudioStream(i)->getlangCod()== config.getPrefAudioLang()) ||(config.getPrefAudioLang().trimmed() =="")) // getaudioStream(i)->setselected(true); //else // getaudioStream(i)->setselected(false); } else getaudioStream(i)->setselected(_state); } for (int i=0;i < getsubPictureCount();i++) { if (_state) { bool sel=false; if (config.getPrefSubtitleLang().count()==0) sel=true; else sel=config.getPrefSubtitleLang().contains(getsubtitle(i)->getlangCod()); getsubtitle(i)->setselected(sel); // if ((getsubtitle(i)->getlangCod()== config.getPrefSubtitleLang()) ||(config.getPrefSubtitleLang().trimmed() =="")) // getsubtitle(i)->setselected(true); //else // getsubtitle(i)->setselected(false); } else getsubtitle(i)->setselected(_state); } setvideoSelected(_state); } void k9DVDTitle::selectChapters(bool _state) { for (int i=0;i < chapterCount;i++) { getChapter(i)->setSelected( _state); } for (int iTitle=0;iTitleselectChapters(_state); } emit selectionChanged(); } #define BETWEEN(a,min,max) (a>=min && a<=max)?true:false k9DVDChapter *k9DVDTitle::getChapterFromSector(uint32_t _sector) { foreach(k9DVDChapter *chapter,chapters) { if (BETWEEN(_sector,chapter->getstartSector(),chapter->getendSector())) return chapter; } foreach (k9DVDTitle *title,m_titles) foreach(k9DVDChapter *chapter,title->chapters) if (BETWEEN(_sector,chapter->getstartSector(),chapter->getendSector())) return chapter; //default : no corresponding chapter return NULL; } k9DVDTitle* k9DVDTitle::getMainTitle() const { return m_mainTitle; } k9DVD* k9DVDTitle::getDvd() const { return m_dvd; } k9copy/src/core/k9dvdbackupinterface.cpp0000644000175000017550000000303212412271774021063 0ustar emulatoremulator/*************************************************************************** * Copyright (C) 2007 by Jean-Michel * * jm_petit@laposte.net * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "k9dvdbackupinterface.h" k9DVDBackupInterface::k9DVDBackupInterface(QObject *parent) : QObject(parent) { } k9DVDBackupInterface::~k9DVDBackupInterface() { } k9copy/src/core/k9drawimage.h0000644000175000017550000000141212412271774016644 0ustar emulatoremulator// // C++ Interface: k9drawimage // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9DRAWIMAGE_H #define K9DRAWIMAGE_H #include #include #include #include #include /** @author Jean-Michel PETIT */ class k9DrawImage : public QWidget { Q_OBJECT public: k9DrawImage(QWidget *parent = 0); void setImage(QString _fileName); void setImage(const QImage &_image); ~k9DrawImage(); private: QPixmap m_pixmap; QImage m_image; QMutex m_mutex; bool m_repaint; QTimer m_timer; protected: void paintEvent ( QPaintEvent *); protected slots: void timerDone(); }; #endif k9copy/src/core/k9titleencopt.h0000644000175000017550000000313012412271774017235 0ustar emulatoremulator// // C++ Interface: k9titleencopt // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9TITLEENCOPT_H #define K9TITLEENCOPT_H #include #include /** @author Jean-Michel PETIT */ class k9DVDTitle; class k9TitleEncOpt : public QObject { Q_OBJECT public: k9TitleEncOpt(k9DVDTitle *parent ); ~k9TitleEncOpt(); k9DVDTitle *getTitle() { return (k9DVDTitle*)parent();} public: int getMaxSize(); void setMaxSize(int); int getNumParts(); void setNumParts(int); int getAudioGain(); void setAudioGain(int); const QString & getWidth(); void setWidth(QString); const QString & getHeight(); void setHeight(QString); const QString & getAudioBr(); void setAudioBr(QString); const QString & getVideoBr(); void setVideoBr(QString); bool getKeepAspectRatio(); void setKeepAspectRatio(bool); bool get2Passes(); void set2Passes(bool); bool getUseCache(); void setUseCache(bool); int getCodec(); void setCodec(int); int getAudioCodec(); void setAudioCodec(int); const QString & getEncoder(); void setEncoder(const QString &); QRect *getCrop(); private: int m_maxSize; int m_numParts; QString m_width; QString m_height; bool m_keepAspectRatio; bool m_2Passes; QString m_audioBr,m_videoBr; int m_codec,m_audioCodec; int m_audioGain; bool m_useCache; QString m_encoder; QRect m_crop; public slots: void load(); }; #endif k9copy/src/core/k9dialogs.h0000644000175000017550000000444712412271774016341 0ustar emulatoremulator/*************************************************************************** * Copyright (C) 2007 by Jean-Michel * * jm_petit@laposte.net * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef K9DIALOGS_H #define K9DIALOGS_H #include #include #include /** @author Jean-Michel */ class k9Dialogs { public: static QString getOpenFileName (const QString &_initialDir,const QString &_filter,QWidget *_parent,const QString &_title); static QString getSaveFileName (const QString &_initialDir,const QString &_filter,QWidget *_parent,const QString &_title); static QString getExistingDirectory (const QString &_initialDir) ; static void error(const QString &_message,const QString &_title,const QStringList &_detail=QStringList()) ; static void information(const QString &_message,const QString &_title) ; static int warningContinueCancel(const QString & _message,const QString & _title,const QStringList &_detail=QStringList()); static void setMainWidget(QWidget *_widget); static QWidget *getMainWidget(); static bool getFont(QFont &font); }; #endif k9copy/src/core/k9burnprogress.h0000644000175000017550000000233212412271774017441 0ustar emulatoremulator// // C++ Interface: // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9BURNPROGRESS_H #define K9BURNPROGRESS_H #include "k9common.h" #include "ui_progress.h" #include "k9logview.h" #include #include #include class k9BurnProgress : public QDialog { Q_OBJECT public: k9BurnProgress(QWidget* parent = 0); ~k9BurnProgress(); virtual k9Process * getProcess() const; virtual void setProgress(long _position,long _total); virtual void setLabelText(const QString _text); virtual void setElapsed(const QString _text); virtual void setTitle(const QString _text); virtual void setMovie(QString _fileName); virtual int execute(); bool getCanceled() const; /*$PUBLIC_FUNCTIONS$*/ public slots: /*$PUBLIC_SLOTS$*/ protected: /*$PROTECTED_FUNCTIONS$*/ k9Process *m_process; bool m_canceled; void closeEvent ( QCloseEvent * event ); protected slots: /*$PROTECTED_SLOTS$*/ void bCancelClick(); void gbOutputToggled(bool state); private: Ui::Progress Ui_Progress; k9LogView *m_logView; int m_outputSize; }; #endif k9copy/src/core/k9logview.ui0000644000175000017550000000111612417731553016550 0ustar emulatoremulator k9LogView 0 0 392 292 Form k9copy/src/core/k9config.cpp0000644000175000017550000002435012412271774016512 0ustar emulatoremulator// // C++ Implementation: k9config // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "k9config.h" #include #if QT_VERSION >= 0x050000 #include #else #include #include #endif #include #include "k9audiocodecs.h" #include "k9videocodecs.h" k9Config::k9Config() { m_config=NULL; read(); } void k9Config::read() { // if (! m_config->hasGroup( "options")) // readOldConfig(); if (m_config!=NULL) delete m_config; m_config=new KConfig("K9Copy"); KConfigGroup group=m_config->group("dir"); m_prefOutput=group.readEntry("output",(QDir::tempPath() + '/' + "k9copy/")); m_prefOutputMpeg4=group.readEntry("outputMpeg4",QDir::homePath() ); m_prefOutputMpeg2=group.readEntry("outputMpeg2",QDir::homePath()); m_prefOutputIso=group.readEntry("outputIso",QDir::homePath()); m_prefOutputAudio=group.readEntry("outputAudio",QDir::homePath()); #if QT_VERSION >= 0x050000 group=m_config->group("programs"); m_prefMencoderPath=group.readEntry("Mencoder",""); if (m_prefMencoderPath.isEmpty()) m_prefMencoderPath=QStandardPaths::findExecutable("mencoder"); m_prefMplayerPath=group.readEntry("Mplayer",""); if (m_prefMplayerPath.isEmpty()) m_prefMplayerPath=QStandardPaths::findExecutable("mplayer"); m_prefk3bPath=group.readEntry("k3b",""); if (m_prefk3bPath.isEmpty()) m_prefk3bPath=QStandardPaths::findExecutable("k3b"); m_prefDvdauthorPath=group.readEntry("Dvdauthor",""); if (m_prefDvdauthorPath.isEmpty()) m_prefDvdauthorPath=QStandardPaths::findExecutable("dvdauthor"); m_prefFFmpegPath=group.readEntry("FFMpeg",""); if (m_prefFFmpegPath.isEmpty()) m_prefFFmpegPath=QStandardPaths::findExecutable("ffmpeg"); m_prefWodimPath=group.readEntry("Wodim",""); if (m_prefWodimPath.isEmpty()) m_prefWodimPath=QStandardPaths::findExecutable("wodim"); m_prefGenisoimagePath=group.readEntry("Genisoimage",""); if (m_prefGenisoimagePath.isEmpty()) m_prefGenisoimagePath=QStandardPaths::findExecutable("genisoimage"); #else group=m_config->group("programs"); m_prefMencoderPath=group.readEntry("Mencoder",""); if (m_prefMencoderPath.isEmpty()) m_prefMencoderPath=KStandardDirs::findExe("mencoder"); m_prefMplayerPath=group.readEntry("Mplayer",""); if (m_prefMplayerPath.isEmpty()) m_prefMplayerPath=KStandardDirs::findExe("mplayer"); m_prefk3bPath=group.readEntry("k3b",""); if (m_prefk3bPath.isEmpty()) m_prefk3bPath=KStandardDirs::findExe("k3b"); m_prefDvdauthorPath=group.readEntry("Dvdauthor",""); if (m_prefDvdauthorPath.isEmpty()) m_prefDvdauthorPath=KStandardDirs::findExe("dvdauthor"); m_prefFFmpegPath=group.readEntry("FFMpeg",""); if (m_prefFFmpegPath.isEmpty()) m_prefFFmpegPath=KStandardDirs::findExe("ffmpeg"); m_prefWodimPath=group.readEntry("Wodim",""); if (m_prefWodimPath.isEmpty()) m_prefWodimPath=KStandardDirs::findExe("wodim"); m_prefGenisoimagePath=group.readEntry("Genisoimage",""); if (m_prefGenisoimagePath.isEmpty()) m_prefGenisoimagePath=KStandardDirs::findExe("genisoimage"); #endif group=m_config->group("devices"); m_InputDev=group.readEntry("input",0); m_OutputDev=group.readEntry("output",0); group=m_config->group("options"); m_GtkStyle=group.readEntry("GtkStyle",false); m_prefK3b=group.readEntry("usek3b",false); m_prefAutoBurn=group.readEntry("autoburn",false); m_quickScan=group.readEntry("quickscan",true); m_prefSize=group.readEntry("dvdsize",4400); m_useDvdAuthor=group.readEntry("useDvdAuthor",true); m_keepMenus=group.readEntry("keepMenus",true); m_prefDelTmpFiles=group.readEntry("deltmpfiles",false); m_prefReadAhead=group.readEntry("readahead",-1); m_prefUserOps=group.readEntry("userops",false); QString lang(qgetenv("LANGUAGE")); QStringList llang; llang << lang.left(2); m_prefAudioLang=group.readEntry("audiolang",llang); m_prefSubtitleLang=group.readEntry("subtitlelang",llang); m_prefVersion=group.readEntry("version","0.0.0"); group=m_config->group("mp4"); m_prefMp4Codec=group.readEntry("codec",0); m_prefMp4Encoder=group.readEntry("encoder","mencoder"); m_prefMp4Size=group.readEntry("size",700); m_prefMp4NumberCD=group.readEntry("numberCD",1); m_prefMp4Width=group.readEntry("width","720"); m_prefMp4Height=group.readEntry("height",""); m_prefMp4AspectRatio=group.readEntry("aspectRatio",true); m_prefMp42Passes=group.readEntry("2passes",false); m_prefMp4AudioBitrate=group.readEntry("audiobitrate","128"); m_prefMp4VideoBitrate=group.readEntry("videobitrate" ""); m_prefMp4AudioCodec=group.readEntry("audiocodec",0); m_prefMp4AudioGain=group.readEntry("audiogain",7); m_prefUseCellCache=group.readEntry("usecellcache",true); m_prefMpegChapters=group.readEntry("mpegchapters",true); group=m_config->group("devices"); m_devices=group.readEntry("dev",QStringList()); m_devicesLabels=group.readEntry("labels",QStringList()); m_devicesIO=group.readEntry("IO",QStringList()); group=m_config->group("preview"); m_useMplayer=group.readEntry("useMplayer",false); m_useGL=group.readEntry("useGL",false); m_MplayerVout=group.readEntry("MplayerVout",0); m_MplayerAout=group.readEntry("MplayerAout",0); m_useXine=group.readEntry("useXine",false); m_XineVout=group.readEntry("XineVout",0); m_XineAout=group.readEntry("XineAout",0); m_usePhonon=group.readEntry("usePhonon",false); group=m_config->group("authoring"); m_prefAudioFormat=group.readEntry("audioFormat","AC3"); m_prefAudioBitrate=group.readEntry("audioBitrate",192); m_prefButtonWidth=group.readEntry("buttonWidth",50); m_prefButtonHeight=group.readEntry("buttonHeight",40); m_prefButtonHiliteColor=group.readEntry("buttonHiliteColor",QColor(Qt::yellow)); m_prefButtonTextColor=group.readEntry("buttonTextColor",QColor(Qt::yellow)); m_prefButtonFont=group.readEntry("buttonFont"); group = m_config->group("gui"); QList defCol; defCol << true << true <("columns",defCol); m_prefShowOutput=group.readEntry("showOutput",true); } void k9Config::save() { KConfigGroup group=m_config->group("dir"); group.writeEntry("output",m_prefOutput); group.writeEntry("outputMpeg4",m_prefOutputMpeg4); group.writeEntry("outputMpeg2",m_prefOutputMpeg2); group.writeEntry("outputAudio",m_prefOutputAudio); group.writeEntry("outputIso",m_prefOutputIso); group=m_config->group("programs"); group.writeEntry("Mencoder",m_prefMencoderPath); group.writeEntry("Mplayer",m_prefMplayerPath); group.writeEntry("k3b",m_prefk3bPath); group.writeEntry("Dvdauthor",m_prefDvdauthorPath); group.writeEntry("FFmpeg",m_prefFFmpegPath); group.writeEntry("Wodim",m_prefWodimPath); group.writeEntry("Genisoimage",m_prefGenisoimagePath); group=m_config->group("devices"); group.writeEntry("input", m_InputDev); group.writeEntry("output",m_OutputDev); group=m_config->group("options"); group.writeEntry("GtkStyle",m_GtkStyle); group.writeEntry("usek3b",m_prefK3b); group.writeEntry("autoburn",m_prefAutoBurn); group.writeEntry("quickscan",m_quickScan); group.writeEntry("dvdsize",m_prefSize); group.writeEntry("useDvdAuthor",m_useDvdAuthor); group.writeEntry("keepMenus",m_keepMenus); group.writeEntry("deltmpfiles",m_prefDelTmpFiles); group.writeEntry("readahead",m_prefReadAhead); group.writeEntry("userops",m_prefUserOps); group.writeEntry("audiolang",m_prefAudioLang); group.writeEntry("subtitlelang",m_prefSubtitleLang); group.writeEntry("version",m_prefVersion); group=m_config->group("mp4"); group.writeEntry("codec",m_prefMp4Codec); group.writeEntry("encoder",m_prefMp4Encoder); group.writeEntry("size",m_prefMp4Size); group.writeEntry("numberCD",m_prefMp4NumberCD); group.writeEntry("width",m_prefMp4Width); group.writeEntry("height",m_prefMp4Height); group.writeEntry("audiobitrate",m_prefMp4AudioBitrate); group.writeEntry("videobitrate",m_prefMp4VideoBitrate); group.writeEntry("aspectRatio",m_prefMp4AspectRatio); group.writeEntry("2passes",m_prefMp42Passes); group.writeEntry("audiogain",m_prefMp4AudioGain); group.writeEntry("audiocodec", m_prefMp4AudioCodec); group.writeEntry("usecellcache",m_prefUseCellCache); group.writeEntry("mpegchapters",m_prefMpegChapters); group=m_config->group("devices"); group.writeEntry("dev",m_devices); group.writeEntry("labels",m_devicesLabels); group.writeEntry("IO",m_devicesIO); group=m_config->group("preview"); group.writeEntry("useMplayer",m_useMplayer); group.writeEntry("useGL",m_useGL); group.writeEntry("MplayerVout",m_MplayerVout); group.writeEntry("MplayerAout",m_MplayerAout); group.writeEntry("useXine",m_useXine); group.writeEntry("XineVout",m_XineVout); group.writeEntry("XineAout",m_XineAout); group.writeEntry("usePhonon",m_usePhonon); group=m_config->group("authoring"); group.writeEntry("audioFormat",m_prefAudioFormat); group.writeEntry("audioBitrate",m_prefAudioBitrate); group.writeEntry("buttonWidth",m_prefButtonWidth); group.writeEntry("buttonHeight",m_prefButtonHeight); group.writeEntry("buttonHiliteColor",m_prefButtonHiliteColor); group.writeEntry("buttonTextColor",m_prefButtonTextColor); group.writeEntry("buttonFont",m_prefButtonFont); group=m_config->group("gui"); group.writeEntry("columns",m_prefColumns); group.writeEntry("showOutput",m_prefShowOutput); } k9Config::~k9Config() { delete m_config; } KConfig* k9Config::getConfig() { if (m_config ==NULL) read(); return m_config; } void k9Config::checkCodecs() { k9Config *config=new k9Config(); if (config->getPrefVersion() != VERSION) { k9AudioCodecs acodec; acodec.reset(); k9VideoCodecs vcodec; vcodec.reset(); delete config; config=new k9Config(); config->setPrefVersion(VERSION); config->save(); } delete config; } k9copy/src/core/k9dvdsize.h0000644000175000017550000000111612412271774016355 0ustar emulatoremulator// // C++ Interface: k9dvdsize // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9DVDSIZE_H #define K9DVDSIZE_H #include /** @author Jean-Michel PETIT */ class k9DVDSize:public QObject { Q_OBJECT private: static int m_size; public: k9DVDSize(QObject *parent=0,const char *name=0) ; static int getMaxSize(); static void setMaxSize(int _size); virtual int getMaxSizeDyn(); virtual void setMaxSizeDyn(int _size); ~k9DVDSize(); }; #endif k9copy/src/core/k9tools.cpp0000644000175000017550000001105612412271774016404 0ustar emulatoremulator// // C++ Implementation: k9tools // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9tools.h" #include "k9common.h" #include #include #include #include #ifdef __FreeBSD__ #include #else #include #endif #include "k9dialogs.h" #include #include #include #include #include #include #include #include QStringList m_temporaryDirs; QString g_password=""; bool gBatchCopy=false; Qt::HANDLE g_mainThread; void k9Tools::setMainThread(){ g_mainThread=QThread::currentThreadId(); } static bool isMainThread(); const QString k9Tools::getTempPath() { QString sPath; sPath=QString("%1/%2/").arg(QDir::tempPath() + '/' + "k9copy/"); return sPath; } void k9Tools::addTemporaryDir(const QString & dir) { m_temporaryDirs << dir; } void k9Tools::processEvents() { if (QThread::currentThreadId()== g_mainThread) qApp->processEvents(QEventLoop::AllEvents,1); else qDebug() << "Not the main thread processEvents skipped"; } bool k9Tools::getBatchCopy() { return gBatchCopy; } void k9Tools::setBatchCopy(bool _value) { gBatchCopy=_value; } QString k9Tools::findExe(const QString _program) { QString path(qgetenv("PATH")); QStringList paths=path.split(":"); foreach (QString p,paths) { QString fullPath=QDir::cleanPath(p+"/"+_program); if (QFile::exists(fullPath)) return fullPath; } return _program; } bool k9Tools::checkProgram(QString _progName,bool _msg) { #if QT_VERSION >= 0x050000 bool res=QStandardPaths::findExecutable( _progName) !=NULL ; #else // Qt4 Code bool res= KStandardDirs::findExe( _progName,NULL,false) !=NULL ; #endif if (_msg && !res) k9Dialogs::error(i18n("Error starting program %1").arg(_progName),i18n("Running program")); return res; } bool k9Tools::runAsRoot(const QString &_command,const QString &_description) { KDESu::SuProcess suprocess("root",_command.toUtf8()); int res=3; while (res==3) { if (suprocess.checkInstall(g_password.toUtf8())!=0) { KPasswordDialog pwd(k9Dialogs::getMainWidget(),KPasswordDialog::UsernameReadOnly ); KUser user; QString username=suprocess.useUsersOwnPassword()?user.loginName():QString("root"); pwd.setUsername(username); pwd.setPrompt(i18n("Enter the root password")); pwd.addCommentLine("",_description); if (!pwd.exec()) return false; g_password=pwd.password(); res=suprocess.exec(g_password.toUtf8()); } else res=suprocess.exec(g_password.toUtf8()); if (res==3) k9Dialogs::error(i18n("The root password is not valid"),i18n("Running program")); } return res==0; } void k9Tools::clearOutput() { foreach(QString dir,m_temporaryDirs) { qDebug() << "clear " << dir; k9Tools::clearOutput(dir); } } const QString k9Tools::randomFileName() { static int prev=0; QTime t(0,0,0); srand(t.msecsTo(QTime::currentTime())); int res=rand(); if (res==prev) res=rand(); prev=res; return QString::number(res % 99999999); } void k9Tools::clearOutput(QString name) { QDir dir(name); //delete files in directory QStringList lst = dir.entryList(QStringList( "*"),QDir::Files |QDir::Hidden ); foreach (QString c,lst) { //QString c(( *it ).latin1() ); dir.remove (c); } //scanning subdir QStringList lstdir = dir.entryList( QStringList("*"),QDir::Dirs ); foreach ( QString c,lstdir) { if ((c!=".") && c!="..") { clearOutput(dir.absoluteFilePath(c)); dir.rmdir(c); } } } void k9Tools::setComboText(QComboBox *_cb,const QString &_text) { int i = _cb->findText(_text); if (i != -1) _cb->setCurrentIndex(i); else if (_cb->isEditable()) _cb->setEditText(_text); else _cb->setItemText(_cb->currentIndex(), _text); } long k9Tools::getFreeSpace(const QString &_path) { struct statfs sfs; #if QT_VERSION >= 0x050000 if (statfs(_path.toLatin1(),&sfs) !=-1) { #else if (statfs(_path.toAscii(),&sfs) !=-1) { #endif uint64_t fs=((uint64_t)sfs.f_bavail*(uint64_t)sfs.f_bsize); fs/=(1024*1024); return fs; } else return -1; } k9copy/src/core/k9logview.cpp0000644000175000017550000000361312412271774016720 0ustar emulatoremulator// Developer: Pauline123 , (C) 2014 #include "k9logview.h" #include "k9common.h" #include "ui_k9logview.h" #include #if QT_VERSION >= 0x050000 // Qt 5 Code #else // Qt 4 Code #endif k9LogView::k9LogView(QWidget *parent) : QWidget(parent), m_ui(new Ui::k9LogView) { m_ui->setupUi(this); m_started=true; QTimer::singleShot(1000,this,SLOT(timerDone())); } k9LogView::~k9LogView() { delete m_ui; } void k9LogView::closeEvent ( QCloseEvent * ) { m_started=false; } void k9LogView::changeEvent(QEvent *e) { QWidget::changeEvent(e); switch (e->type()) { case QEvent::LanguageChange: m_ui->retranslateUi(this); break; default: break; } } void k9LogView::timerDone() { k9logEntry *logItem; while (k9log::count()>0 && m_started) { logItem=k9log::dequeue(); if (logItem) { QIcon *icon; switch(logItem->level) { case k9logLevel::ERROR : #if QT_VERSION >= 0x050000 icon=new QIcon("dialog-error"); icon->pixmap(24); #else icon=new QIcon(SmallIcon("dialog-error")); #endif break; case k9logLevel::WARNING : #if QT_VERSION >= 0x050000 icon=new QIcon("dialog-warning"); icon->pixmap(24); #else icon=new QIcon(SmallIcon("dialog-warning")); #endif break; default: #if QT_VERSION >= 0x050000 icon=new QIcon("dialog-information"); icon->pixmap(24); #else icon=new QIcon(SmallIcon("dialog-information")); #endif break; } m_ui->lwLogs->addItem(new QListWidgetItem(*icon,logItem->text,0)); m_ui->lwLogs->scrollToBottom(); delete icon; } } if (m_started) QTimer::singleShot(1000,this,SLOT(timerDone())); } QListWidget *k9LogView::list() { return m_ui->lwLogs; } k9copy/src/core/k9audiocodecs.h0000644000175000017550000000201012412271774017161 0ustar emulatoremulator// // C++ Interface: k9audiocodecs // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9AUDIOCODECS_H #define K9AUDIOCODECS_H #include "k9common.h" #include /** @author Jean-Michel PETIT */ class _k9AudioCodec; class k9AudioCodecs : public QObject { Q_OBJECT public: k9AudioCodecs(QObject *parent = 0); ~k9AudioCodecs(); void save(); int count(); void setOptions(int _num,QString _value); void setCodecName(int _num,QString _value); void setEncoder(int _num,QString _value); void setExtension(int _num,QString _value); QString getOptions(int _num); QString getCodecName(int _num); QString getEncoder(int _num); QString getExtension(int _num); void remove(int _num); void reset(); static int getAbsCodecNum(int _num,const QString &_encoder); private: QMap m_codecs; k9Config *m_config; }; #endif k9copy/src/core/k9dvdtitleset.cpp0000644000175000017550000000571412412271774017603 0ustar emulatoremulator// // C++ Implementation: k9dvdtitleset // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9dvdtitleset.h" k9DVDTitleset::k9DVDTitleset( uint _num,uint32_t _size) { m_num=_num; m_size=_size; m_selected=false; m_updating=false; for (uint i=0;i<8;i++) m_audioStreams[i]=false; }; const QString k9DVDTitleset::getsize_mb() { double size_mb=(double)m_size /512; QString c; c.sprintf("%.2f",size_mb); return c; } int k9DVDTitleset::getnum() { return m_num; } void k9DVDTitleset::add(k9DVDTitle * _title) { titles.append(_title); } int k9DVDTitleset::count() { return titles.count(); } k9DVDTitle * k9DVDTitleset::gettitle(uint _pos) { return titles.at(_pos); } uint32_t k9DVDTitleset::getsize() { return m_size; } bool k9DVDTitleset::getselected() { return m_selected; } void k9DVDTitleset::setselected(bool _state) { // selectionner / d�electionner tous les titres for (int i=0; igetaudioStreamCount();j++) title->getaudioStream(j)->setselected(_state); for (int j=0;jgetsubPictureCount();j++) title->getsubtitle(j)->setselected(_state); title->setvideoSelected(_state); */ title->setSelected(_state); } m_selected=_state;; } void k9DVDTitleset::updateSelection() { if (m_updating) return; m_updating=true; bool selected=m_selected; m_selected=false; //check if at least on title is selected for (int i=0; iisSelected() && title->getIndexed()) m_selected=true; } //if titleset selected, we select all features. otherwise they are unselected if (selected !=m_selected) for (int i=0; igetIndexed() && title->isSelected()) for (int iTitle=0;iTitle getTitles().count();iTitle++) { k9DVDTitle *title2=title->getTitles().at(iTitle); for (int j=0; j getaudioStreamCount();j++) title2->getaudioStream(j)->setselected(title->getaudioStream(j)->getselected()); for (int j=0;jgetsubPictureCount();j++) title2->getsubtitle(j)->setselected(title2->getsubtitle(j)->getselected()); title2->setvideoSelected(true); } } m_updating=false; } void k9DVDTitleset::setAudio(int _id,bool _selected) { m_audioStreams[_id -1]=_selected; } int k9DVDTitleset::getNewAudioStreamId(int _oldId) { int newId=0; //Returns the new stream Id, only if the stream is selected. Otherwise, returns 0 if (m_audioStreams[_oldId-1]) { /* for (int i=0; i<_oldId;i++) { if (m_audioStreams[i]) newId++; } */ return _oldId; } return newId; } k9copy/src/core/dvdprogress.ui0000755000175000017550000000562412417731553017205 0ustar emulatoremulator DVDProgress 0 0 278 150 0 0 0 150 400 150 WaitCursor DVD Analyze WaitCursor false WaitCursor 100 false WaitCursor false WaitCursor 100 100 false WaitCursor false k9copy/src/core/k9common.h0000644000175000017550000000211412412306523016163 0ustar emulatoremulator// // C++ Interface: k9common // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "config.h" #ifndef __STDC_LIMIT_MACROS #endif #ifndef __STDC_CONSTANT_MACROS #define __STDC_CONSTANT_MACROS #endif #if defined(HAVE_INTTYPES_H) #include #elif defined( HAVE_STDINT_H) #include #endif #ifdef __FreeBSD__ #include #endif #include "dvdread/ifo_types.h" //PM DVDREAD #include "dvdread/dvd_reader.h" //PM DVDREAD #include "dvdread/ifo_read.h" //PM DVDREAD #include "dvdread/nav_read.h" //PM DVDREAD #include "dvdread/nav_types.h" //PM DVDREAD #include #ifndef DVD_BLOCK_LEN #define DVD_BLOCK_LEN 2048 #endif #include "k9dvdsize.h" #include #include "k9dialogs.h" #include "k9log.h" #include "k9tools.h" #if QT_VERSION >= 0x050000 #include #else //Qt4 Code #include #endif #include "k9config.h" #include "k9process.h" k9copy/src/core/k9burndvd.cpp0000644000175000017550000003547012412271774016716 0ustar emulatoremulator/************************************************************************** * Developer: Pauline123 , (C) 2014 * Copyright (C) 2005 by Jean-Michel Petit * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "k9burndvd.h" #include #include #if QT_VERSION >= 0x050000 #include #include #else #include #include #endif #include "k9cddrive.h" #include k9BurnDVD::k9BurnDVD() : QObject(NULL) { cancelled=false; useK3b=false; autoBurn=false; m_eject=false; volId="K9Copy"; iso=false; m_filename=""; progress=new k9BurnProgress(NULL); #if QT_VERSION >= 0x050000 // Qt5 code QString s=QStandardPaths::locate(QStandardPaths::GenericDataLocation, "k9copy/anim.mng"); #else // Qt4 code QString s= KGlobal::dirs()->findResource( "data", "k9copy/anim.mng"); #endif progress->setMovie(s); m_cdrkit=k9Tools::checkProgram("genisoimage") && k9Tools::checkProgram("wodim"); m_config=new k9Config; } k9BurnDVD::~k9BurnDVD() { delete m_config; delete progress; } /** Read property of QString burnDevice. */ const QString& k9BurnDVD::getburnDevice() { return burnDevice; } /** Write property of QString burnDevice. */ void k9BurnDVD::setburnDevice( const QString& _newVal) { burnDevice = _newVal; } /** Write property of QString workDir. */ void k9BurnDVD::setworkDir( const QString& _newVal) { workDir = _newVal; if (!workDir.endsWith("/")) workDir +='/'; } void k9BurnDVD::makeIso(QString _filename) { iso=true; m_filename=_filename; } void k9BurnDVD::setvolId(QString _newVal) { volId=_newVal.replace(" ","_"); } void k9BurnDVD::setUseK3b(bool _newVal) { useK3b=_newVal; } void k9BurnDVD::setAutoBurn(bool _newVal) { autoBurn=_newVal; } void k9BurnDVD::burn() { if (!useK3b) { if (! m_cdrkit) burnWithGrowisofs(); else burnWithGenisoimage(); } else burnWithK3b(); } void k9BurnDVD::burnWithK3b() { k9Process *k3b = new k9Process(); k9Config config; *k3b << config.getPrefk3bPath(true); *k3b << QDir::cleanPath(workDir+ "/VIDEO_TS"); *k3b << "-videodvd"; k3b->startDetached (); delete k3b; } void k9BurnDVD::mkisoSizeStderr(char *buffer, int buflen) { QString c=QString::fromLatin1( buffer,buflen);// (proc2->readStderr()); imageSize=c.replace("\n",""); ; } void k9BurnDVD::mkisoSizeStdout(char *buffer, int buflen) { QString c=QString::fromLatin1(buffer,buflen);// (proc2->readStdout()); imageSize=c.replace("\n",""); ; } const QString &k9BurnDVD::getImageSize() { QString c; c="mkisofs"; proc2=new k9Process; *proc2 << c; *proc2 <<"-quiet"; *proc2 <<"-print-size"; *proc2 <<"-dvd-video"; *proc2 <<"-udf"; *proc2 <<"-r"; *proc2 <<"-V "+volId; *proc2 << KShell::quoteArg (QDir::cleanPath(workDir)); connect( proc2, SIGNAL(receivedStderr(char *, int )),this, SLOT(mkisoSizeStderr(char *, int)) ); connect( proc2, SIGNAL(receivedStdout(char *, int)),this, SLOT(mkisoSizeStdout(char *, int)) ); if (proc2->start()) { proc2->sync(); if (proc2->exitStatus()==0) { delete proc2; k9log::add(i18n("image size : %1").arg(imageSize),k9logLevel::INFO); return imageSize; } } delete proc2; imageSize="0"; return imageSize; } void k9BurnDVD::getGenisoimageCmd(QStringList &_cmd,QString _fileName,bool _printSize) { QString progname=m_config->getPrefGenisoimagePath(true); _cmd << progname; _cmd << "-gui"; _cmd << "-v"; _cmd << "-graft-points"; _cmd << "-volid" << volId; _cmd <<"-appid" << "k9copy"; _cmd << "-volset-size" << "1"; _cmd << "-volset-seqno" << "1"; _cmd << "-no-cache-inodes" << "-udf"; _cmd << "-iso-level" << "1"; _cmd << "-dvd-video"; if (!_printSize) { if (_fileName !="") { _cmd <<"-o"; _cmd << KShell::quoteArg(_fileName); } } else { _cmd << "-print-size" << "-quiet"; } _cmd << KShell::quoteArg(QDir::cleanPath(workDir )); } void k9BurnDVD::getWodimCmd(QStringList &_cmd) { _cmd << "|" + m_config->getPrefWodimPath(true); _cmd << "-dao"; _cmd << "-overburn"; _cmd << "-data"; _cmd << "-v"; if (m_speed !=i18n("default")) _cmd << QString("speed=%1").arg(m_speed); _cmd << QString("dev=%1").arg(burnDevice); // _cmd << QString("tsize=%1s").arg(getImageSize()); _cmd << QString("tsize=%1s").arg(imageSize); _cmd << "-"; } void k9BurnDVD::burnWithGenisoimage() { time = new QTime(0,0); time->start(); #if QT_VERSION >= 0x050000 progress->setWindowTitle((i18n("Burning DVD"))); #else progress->setWindowTitle(KDialog::makeStandardCaption(i18n("Burning DVD"),progress)); #endif progress->setTitle(i18n("Burning DVD")); proc=progress->getProcess(); bool bok=false; while (!cancelled && !bok) { burnSpeed=0; QString fileName=""; if (iso) { fileName=m_filename; if (fileName =="") fileName=k9Dialogs::getSaveFileName (QDir::homePath(),"*.iso", 0,i18n("Save image to disk")); if (fileName =="") { cancelled=true; } } proc->clearProgram(); QStringList procCmd,proc2Cmd; getGenisoimageCmd(procCmd,fileName,false); connect( proc, SIGNAL(receivedStderr(char *, int)),this, SLOT(growisoStderr( char *, int)) ); connect( proc, SIGNAL(receivedStdout(char *, int)),this, SLOT(growisoStdout( char *, int)) ); if (!iso) { k9Process *proc2=new k9Process(NULL,NULL); getGenisoimageCmd(proc2Cmd,"",true); connect( proc2, SIGNAL(receivedStderr(char *, int )),this, SLOT(mkisoSizeStderr(char *, int)) ); connect( proc2, SIGNAL(receivedStdout(char *, int)),this, SLOT(mkisoSizeStdout(char *, int)) ); k9log::add(i18n("computing image size"),k9logLevel::INFO); proc2->setShellCommand(proc2Cmd.join(" "));; k9log::add(i18n("starting thread : %1").arg(proc2Cmd.join(" ")),k9logLevel::INFO); proc2->start(); proc2->sync(); getWodimCmd(procCmd); if (m_eject) eject(burnDevice); if (!autoBurn) { #if QT_VERSION >= 0x050000 if ( k9Dialogs::warningContinueCancel ( i18n("Insert a recordable DVD"), i18n("DVD burning"))!=QMessageBox::Ignore) #else if ( k9Dialogs::warningContinueCancel ( i18n("Insert a recordable DVD"), i18n("DVD burning"))!=KMessageBox::Continue) #endif cancelled=true; } } proc->setShellCommand(procCmd.join(" ")); if (!cancelled) { k9log::add(i18n("start burning"),k9logLevel::INFO); k9log::add(i18n("starting thread : %1").arg(procCmd.join(" ")),k9logLevel::INFO); int res=progress->execute(); if ( res==-1 ) { k9log::add(i18n("Error"),k9logLevel::ERROR); k9Dialogs::error( i18n("Error burning DVD :\n")+i18n("Unable to run %1").arg("genisoimage"), i18n("DVD burning") ); cancelled=true; } else { if ((proc->exitStatus()==0)&& (proc->exitCode()==0)) { bok=true; k9log::add(i18n("Success"),k9logLevel::INFO); k9Dialogs::information( i18n("DVD Burning finished"), i18n("DVD burning") ); } else { k9log::add(i18n("Error"),k9logLevel::ERROR); QString c; if(!iso) eject(burnDevice); c=i18n("An error occured while Burning DVD") +"\n" +i18n("Insert an other DVD"); #if QT_VERSION >= 0x050000 if ( k9Dialogs::warningContinueCancel ( c, i18n("DVD burning"),lastMsg)!=QMessageBox::Ignore) { #else if ( k9Dialogs::warningContinueCancel ( c, i18n("DVD burning"),lastMsg)!=KMessageBox::Continue) { #endif cancelled=true; } } } } } } void k9BurnDVD::burnWithGrowisofs() { time = new QTime(0,0); time->start(); #if QT_VERSION >= 0x050000 progress->setWindowTitle((i18n("Burning DVD"))); #else progress->setWindowTitle(KDialog::makeStandardCaption(i18n("Burning DVD"),progress)); #endif progress->setTitle(i18n("Burning DVD")); bool bok=false; while (!cancelled && !bok) { burnSpeed=0; QString c,progname; if (iso) progname="mkisofs"; else progname="growisofs"; proc=progress->getProcess(); *proc << progname; if (!iso) { *proc <<"-overburn"; *proc <<"-Z"; *proc <debug()),k9logLevel::INFO); int res=progress->execute(); if ( res==-1 ) { k9log::add(i18n("Error"),k9logLevel::ERROR); k9Dialogs::error( i18n("Error burning DVD :\n")+i18n("Unable to run %1").arg(progname), i18n("DVD burning") ); cancelled=true; } else { if (proc->exitStatus()==0) { k9log::add(i18n("Success"),k9logLevel::INFO); bok=true; k9Dialogs::information( i18n("DVD Burning finished"), i18n("DVD burning") ); //delete temporary files // clearOutput(workDir+"dvd"); } else { k9log::add(i18n("Error"),k9logLevel::ERROR); QString c; c=i18n("An error occured while Burning DVD") +"\n" +i18n("Insert an other DVD"); if ( k9Dialogs::warningContinueCancel ( c, i18n("DVD burning"),lastMsg)!=KMessageBox::Continue) { cancelled=true; } } } } } delete time; } /** No descriptions */ void k9BurnDVD::growisoStderr(char *buffer, int buflen) { QString str(QByteArray( buffer,buflen));// (proc->readStderr()); QStringList strl=str.split("\n"); foreach (QString c,strl) { c=c.replace("\r",""); if (c.isEmpty()) continue; //qDebug() << c; char s[255]; int a,b; int pos; lastMsg << c; if (lastMsg.count() >50) lastMsg.removeFirst(); if (c.contains("Current Write Speed")) { sscanf(c.toUtf8(),"%s \"Current Write Speed\" is %d.%d",s,&a,&b); burnSpeed=a+b/10; } if (c.contains("Speed set to")) { sscanf(c.toUtf8(),"Speed set to %d",&a); burnSpeed=a/1385; } progress->setTitle(i18n("Burning DVD")); progress->setLabelText(i18n("Current write speed :%1 x").arg(burnSpeed)); if (c.contains("% done")) { pos=c.indexOf("%"); if (pos!=-1) { c=c.mid(1,pos-4); //progress->setLabelText(c); progress->setProgress(c.toInt(),100); float m_percent=c.toFloat()/100; QTime time2(0,0); time2=time2.addMSecs(time->elapsed()); if (m_percent>0) { QTime time3(0,0); QString m_remain; time3=time3.addMSecs((uint32_t)(time->elapsed()*(1/m_percent))); m_remain=time3.toString("hh:mm:ss"); progress->setElapsed(time2.toString("hh:mm:ss") +" / " +m_remain); } } } else k9log::add(i18n("%1").arg(c),k9logLevel::INFO); } } void k9BurnDVD::growisoStdout(char *buffer, int buflen) { QString c=QString::fromLatin1( buffer,buflen);// (proc->readStdout()); int pos; pos=c.indexOf("STAT"); if (pos!=-1) { c=c.mid(pos); progress->setLabelText(c); } } void k9BurnDVD::eject(const QString &device) { k9Process *process =new k9Process(); if (k9Tools::checkProgram("kdeeject")) *process <<"kdeeject" << device; else *process <<"eject" << device; process->start(); process->wait(); delete process; } void k9BurnDVD::setEject(bool theValue) { m_eject = theValue; } k9copy/src/core/progress.ui0000644000175000017550000002212112417731553016473 0ustar emulatoremulator Progress 0 0 463 457 0 0 WaitCursor false k9Copy 0 0 75 true WaitCursor -- false 0 0 ArrowCursor 26 Qt::Horizontal QSizePolicy::Expanding 161 21 0 0 Output true true 0 0 0 255 255 255 0 0 0 255 255 255 0 0 0 0 0 0 0 0 0 true QFrame::NoFrame QFrame::Plain Qt::AlignCenter false 0 0 QFrame::StyledPanel QFrame::Raised 0 0 WaitCursor Elapsed Time false WaitCursor 0 0 true WaitCursor Qt::AlignVCenter false 0 0 WaitCursor false KPushButton KPushButton
kpushbutton.h
bCancel clicked() Progress bCancelClick() 20 20 20 20 gbOutput toggled(bool) Progress gbOutputToggled(bool) 235 174 235 232 gbOutputToggled(bool)
k9copy/src/core/k9audiocodecs.cpp0000644000175000017550000001047612412271774017533 0ustar emulatoremulator// // C++ Implementation: k9audiocodecs // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "k9audiocodecs.h" #include #include class _k9AudioCodec { public: _k9AudioCodec():name(""),options(""),encoder(""),extension("") {} _k9AudioCodec(QString _name,QString _options,QString _encoder,QString _extension="") { name=_name; options=_options; encoder=_encoder; extension=_extension; } QString name; QString options; QString encoder; QString extension; }; k9AudioCodecs::k9AudioCodecs(QObject *parent) : QObject(parent) { m_config=new k9Config(); KConfig *config= m_config->getConfig(); KConfigGroup group=config->group("codecs"); int nbAudio=group.readEntry("AudioCount",0); //adds default codecs if (nbAudio==0) { reset(); m_config=new k9Config(); } for (int cpt=0;cpt group(QString("audiocodec%1").arg(cpt)); m_codecs[cpt] = _k9AudioCodec(group.readEntry("name"),group.readEntry("opt",""),group.readEntry("encoder","mencoder"),group.readEntry("extension")); } delete m_config; } void k9AudioCodecs::reset() { m_codecs[0]=_k9AudioCodec("copy","-oac copy","mencoder"); m_codecs[1]=_k9AudioCodec("mp2","-oac lavc -lavcopts acodec=mp2:abitrate=$AUDBR","mencoder"); m_codecs[2]=_k9AudioCodec("ac3","-oac lavc -lavcopts acodec=ac3:abitrate=$AUDBR","mencoder"); m_codecs[3]=_k9AudioCodec("IMA Adaptive PCM","-oac lavc -lavcopts acodec=adpcm_ima_wav:abitrate=$AUDBR","mencoder"); m_codecs[4]=_k9AudioCodec("sonic","-oac lavc -lavcopts acodec=sonic:abitrate=$AUDBR","mencoder"); m_codecs[5]=_k9AudioCodec("aac","-oac faac -faacopts br=$AUDBR","mencoder"); m_codecs[6]=_k9AudioCodec("mp3 (lame)","-oac mp3lame -lameopts abr:br=$AUDBR","mencoder"); m_codecs[7]=_k9AudioCodec("copy","-codec:a copy","ffmpeg",""); m_codecs[8]=_k9AudioCodec("mp3","-codec:a libmp3lame -ab $AUDBRk -ac 2 -ar 44100","ffmpeg",".mp3"); m_codecs[9]=_k9AudioCodec("vorbis","-codec:a vorbis -ab $AUDBRk -ac 2 -ar 44100","ffmpeg",".ogg"); m_codecs[10]=_k9AudioCodec("aac","-codec:a libfaac -ab $AUDBRk -ac 2 -ar 44100","ffmpeg",".aac"); save(); } void k9AudioCodecs::save() { m_config=new k9Config(); KConfig *config= m_config->getConfig(); KConfigGroup group; int cpt=0; for (QMap::iterator i=m_codecs.begin();i!=m_codecs.end();++i) { group=config->group(QString("audiocodec%1").arg(cpt)); group.writeEntry("name",i.value().name); group.writeEntry("opt", i.value().options); group.writeEntry("encoder", i.value().encoder); group.writeEntry("extension",i.value().extension); cpt++; } group=config->group("codecs"); group.writeEntry("AudioCount",cpt); m_config->save(); delete m_config; } int k9AudioCodecs::count() { return m_codecs.count(); } void k9AudioCodecs::setOptions(int _num,QString _value) { m_codecs[_num].options=_value; } void k9AudioCodecs::setEncoder(int _num,QString _value) { m_codecs[_num].encoder=_value; } void k9AudioCodecs::setCodecName(int _num,QString _value) { m_codecs[_num].name=_value; } void k9AudioCodecs::setExtension(int _num,QString _value) { m_codecs[_num].extension=_value; } QString k9AudioCodecs::getOptions(int _num) { return m_codecs[_num].options; } QString k9AudioCodecs::getCodecName(int _num) { return m_codecs[_num].name; } int k9AudioCodecs::getAbsCodecNum(int _num,const QString &_encoder) { k9AudioCodecs a(0); int nb=a.count(); int num=0; for (int i=0;i0) { for (int i=_num;i, * H�kan Hjort * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ //#include #if defined(WORDS_BIGENDIAN) /* All bigendian systems are fine, just ignore the swaps. */ /* PM ADDED B2N_8 */ //#define B2N_8(x) (void)(x) #define B2N_16(x) (void)(x) #define B2N_32(x) (void)(x) #define B2N_64(x) (void)(x) #else #define B2N_8(x) \ x = ((x >> 4) & 0xff) + ((x << 4) &0xff) /* For __FreeBSD_version */ #if defined(HAVE_SYS_PARAM_H) #include #endif #if defined(__linux__) #include #define B2N_16(x) x = bswap_16(x) #define B2N_32(x) x = bswap_32(x) #define B2N_64(x) x = bswap_64(x) #elif defined(__NetBSD__) #include #define B2N_16(x) BE16TOH(x) #define B2N_32(x) BE32TOH(x) #define B2N_64(x) BE64TOH(x) #elif defined(__OpenBSD__) #include #define B2N_16(x) x = swap16(x) #define B2N_32(x) x = swap32(x) #define B2N_64(x) x = swap64(x) #elif defined(__FreeBSD__) && __FreeBSD_version >= 470000 #include #define B2N_16(x) x = be16toh(x) #define B2N_32(x) x = be32toh(x) #define B2N_64(x) x = be64toh(x) /* This is a slow but portable implementation, it has multiple evaluation * problems so beware. * Old FreeBSD's and Solaris don't have or any other such * functionality! */ #elif defined(__FreeBSD__) || defined(__sun) || defined(__bsdi__) #define B2N_16(x) \ x = ((((x) & 0xff00) >> 8) | \ (((x) & 0x00ff) << 8)) #define B2N_32(x) \ x = ((((x) & 0xff000000) >> 24) | \ (((x) & 0x00ff0000) >> 8) | \ (((x) & 0x0000ff00) << 8) | \ (((x) & 0x000000ff) << 24)) #define B2N_64(x) \ x = ((((x) & 0xff00000000000000) >> 56) | \ (((x) & 0x00ff000000000000) >> 40) | \ (((x) & 0x0000ff0000000000) >> 24) | \ (((x) & 0x000000ff00000000) >> 8) | \ (((x) & 0x00000000ff000000) << 8) | \ (((x) & 0x0000000000ff0000) << 24) | \ (((x) & 0x000000000000ff00) << 40) | \ (((x) & 0x00000000000000ff) << 56)) #else /* If there isn't a header provided with your system with this functionality * add the relevant || define( ) to the portable implementation above. */ #error "You need to add endian swap macros for you're system" #endif #endif /* WORDS_BIGENDIAN */ #endif /* BSWAP_H_INCLUDED */ k9copy/src/core/k9dvdsize.cpp0000644000175000017550000000107612412271774016715 0ustar emulatoremulator// // C++ Implementation: k9dvdsize // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9dvdsize.h" int DVD_MAX_SIZE=4400; k9DVDSize::k9DVDSize(QObject *,const char *) { } int k9DVDSize::getMaxSize(){ return DVD_MAX_SIZE; } void k9DVDSize::setMaxSize(int _size){ DVD_MAX_SIZE=_size; } int k9DVDSize::getMaxSizeDyn(){ return DVD_MAX_SIZE; } void k9DVDSize::setMaxSizeDyn(int _size){ DVD_MAX_SIZE=_size; } k9DVDSize::~k9DVDSize() { } k9copy/src/core/k9cell.cpp0000755000175000017550000003104612412271774016167 0ustar emulatoremulator/************************************************************************** * Copyright (C) 2005 by Jean-Michel Petit * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "k9cell.h" #include "k9dvdtitleset.h" bool k9VobuList::compareItems (const k9Vobu *item1,const k9Vobu *item2 ) { return(item1->oldSector < item2->oldSector); } void k9VobuList::clearList() { // while (!isEmpty()) delete takeFirst(); qDeleteAll(*this); clear(); } k9Vobu * k9VobuList::findVobu(uint32_t sector) { uint32_t c=count(); c--; //if (c >0) { k9Vobu *v1,*v2; v1=first(); v2=last(); if (v1==NULL) return NULL; if (sector >= v1->oldSector && sector <= v2->oldSector) return findVobu(sector,0,c); else return NULL; //} } k9Vobu * k9VobuList::findVobu(uint32_t sector, uint32_t start, uint32_t end) { long lstart=start; long lend=end; while (lstart <=lend) { long m =(lstart+lend)/2; k9Vobu *v = (k9Vobu *)at(m); if ( v->oldSector == sector) { return v; } else if ( v->oldSector >sector) { lend = m-1; } else { lstart=m+1; } } return NULL; } uint32_t k9Cell::getnewSize() { uint32_t size=0; //for (k9Vobu * vobu=vobus.first();vobu;vobu=vobus.next()) for (int i=0; isize; } return size; } int k9Cell::getStreamID(int type) { int abase=0; if (type >= 0x80 && type <= 0x87) { // AC3 audio abase = 0x80; } else if (type >= 0x88 && type <= 0x8f) { // DTS audio abase = 0x88; } else if (type >= 0xa0 && type <= 0xbf) { // LPCM audio abase = 0xa0; } else if (type >= 0xc0 && type <= 0xdf) { // MPEG audio abase = 0xc0; } else if (type >=0x20 && type <=0x3f) { //subpicture; abase =0x20; } return (type-abase ); } streamType_t k9Cell::identifyStream( uchar *buffer,int *packetType ) { *packetType = buffer[17]; if ( (*packetType >= 0xE0) && (*packetType <= 0xEF) ) { // video streams return stVideo; } else if ( *packetType == 0xBB ) { // system header return stOther; } else if ( *packetType == 0xBE ) { // padding return stOther; } else if ( *packetType == 0xBF ) { // nav pack return stOther; } else if ( (*packetType >= 0xC0) && (*packetType <= 0xDF) ) { // mpeg audio return stAudio; } else if ( *packetType == 0xBD ) { // private stream, check content *packetType = buffer[23+buffer[22]]; if (( (*packetType >=0x80) && (*packetType <=0x8f)) || ((*packetType >=0xa0) && (*packetType <=0xa7)) || ((*packetType >=0xc0) && (*packetType <=0xdf))) return stAudio; if ( (*packetType >=0x20) && (*packetType <=0x3f)) return stSubpicture; return stOther; } else return stOther; } int k9Cell::isNavPack (uchar *_ptr) { uint32_t start_code; uchar *ptr=_ptr; if ((ptr [0]!=0) || (ptr [1] !=0) || (ptr [2] != 0x01) || (ptr [3] != 0xba)) return 0; if ((ptr [4] & 0xc0) != 0x40) return 0; // ptr += 14; start_code = (uint32_t) (ptr [14]) << 24; start_code |= (uint32_t) (ptr [15]) << 16; start_code |= (uint32_t) (ptr [16]) << 8; start_code |= (uint32_t) (ptr [17]); if (start_code != 0x000001bb) return 0; // ptr += 24; start_code = (uint32_t) (ptr [0x26]) << 24; start_code |= (uint32_t) (ptr [0x27]) << 16; start_code |= (uint32_t) (ptr [0x28]) << 8; start_code |= (uint32_t) (ptr [0x29]); if (start_code != 0x000001bf) return 0; // ptr += 986; start_code = (uint32_t) (ptr [0x400]) << 24; start_code |= (uint32_t) (ptr [0x401]) << 16; start_code |= (uint32_t) (ptr [0x402]) << 8; start_code |= (uint32_t) (ptr [0x403]); if (start_code != 0x000001bf) return 0; return 1; } k9Cell::k9Cell() { // vobus.setAutoDelete(true); numVobu=0; vts=0; pgc=0; vob=0; startSector=0; lastSector=0; //TO REMOVE oldStartSector=0; //TO REMOVE oldLastSector=0; //TO REMOVE newSize=0; id=0; selected=false; copied=false; //TO REMOVE nbVideoNew=0; //TO REMOVE nbVideoOld=0; angleBlock=angleNone; } k9Cell::~k9Cell() { vobus.clearList(); } //add a title in the title list (titles using this cell) void k9Cell::addTitle( k9DVDTitle *_title) { m_titles.append( _title); } bool k9Cell::getforceFactor() { bool m_forced=false; for (int i=0; i< m_titles.count() && !m_forced ;i++) { k9DVDTitle *title=m_titles.at(i); if (title->getforceFactor()) m_forced=true; } return m_forced; } // returns the shrink factor. float k9Cell::getFactor() { float factor=0; for (int i=0; i< m_titles.count() ;i++) { k9DVDTitle *title=m_titles.at(i); if ((title->getfactor()< factor || factor==0 ) && title->getforceFactor() ) factor=title->getfactor(); } return factor; } //looking for the end reference frame adress block void k9Cell::addRefStream(k9Vobu *_vobu,uchar *_buffer,uint32_t _position) { if (_vobu->firstRefOk && _vobu->secondRefOk && _vobu->thirdRefOk) return; //offset of frame uint start=0x16+_buffer[0x16]+1; //PES Length uint length=_buffer[0x12]; length=(length <<8 ) + _buffer[0x13]; //end of PES uint end=0x14+length; if ( _vobu->frameType!=0x18) { if (!_vobu->firstRefOk) _vobu->firstRef=_position; else if (!_vobu->secondRefOk) _vobu->secondRef=_position; else if (!_vobu->thirdRefOk) _vobu->thirdRef=_position; } for (uint i=start;i frameType!=0x18) && (_vobu->frameType!=0)) { if (!_vobu->firstRefOk) { _vobu->firstRefOk=true; _vobu->firstRef=_position; } else if (!_vobu->secondRefOk) { _vobu->secondRefOk=true; _vobu->secondRef=_position; } else if (!_vobu->thirdRefOk) { _vobu->thirdRefOk=true; _vobu->thirdRef=_position; } } //keep the current frame type _vobu->frameType=frameType; } } } k9Vobu * k9Cell::addVobu(uint32_t _sector) { k9Vobu * vobu = new k9Vobu(this,_sector); vobus.append(vobu); return vobu; } void k9Cell::addNewVobus(char *_buffer,uint32_t _len,uint32_t _position,int _vobNum,long _vobPos) { uint32_t start= _position ;//lastSector - _len ; k9Vobu *vobu; for (uint32_t i= 0 ; i<_len ;i+=DVD_BLOCK_LEN) { if (isNavPack((uchar*)_buffer+i)) { vobu=(k9Vobu*)vobus.at(numVobu); vobu->newSector=i/DVD_BLOCK_LEN +start; numVobu++; vobu->vobNum=_vobNum; vobu->vobPos=_vobPos; //QString c; //c.sprintf("vobu : %d old: %d new :%d",numVobu-1,vobu->oldSector,vobu->newSector); //qDebug (c.latin1()); } else { streamType_t st; int packetType,id; st=k9Cell::identifyStream((uchar*)_buffer+i,&packetType); vobu=(k9Vobu*)vobus.at(numVobu-1); switch (st) { case stAudio: id=k9Cell::getStreamID(packetType); if (vobu->firstAudio[id]==-1) { vobu->firstAudio[id]= ((i/ DVD_BLOCK_LEN) + start) - vobu->newSector; } break; case stSubpicture: id=k9Cell::getStreamID(packetType); if ((id >=0) && (id<32)) { if (vobu->firstSubp[id]==-1) { vobu->firstSubp[id]= ((i / DVD_BLOCK_LEN)+start) - vobu->newSector; } } break; case stVideo: addRefStream(vobu,(uchar*)_buffer+i,(i/DVD_BLOCK_LEN +start) - vobu->newSector); if (vobu->firstVideo==-1) { vobu->firstVideo = ((i / DVD_BLOCK_LEN)+start) - vobu->newSector; } //TO REMOVE nbVideoNew++; break; default: break; } } vobu->size= _position-vobu->newSector; // �v�ifier lastSector=_position; } } k9Vobu::k9Vobu(k9Cell *_parent,uint32_t _oldSector) { parent=_parent; oldSector = _oldSector; newSector = 0; size=0; for (int i=0;i<8;i++) firstAudio[i]=-1; for (int i=0;i<32;i++) firstSubp[i]=-1; firstVideo=-1; empty=false; vobPos=0; vobNum=0; frameType=0; firstRef=0; secondRef=0; thirdRef=0; firstRefOk=false; secondRefOk=false; thirdRefOk=false; } /*! \fn k9Cell::findVobu(int _oldSector) */ k9Vobu * k9Cell::findVobu(uint32_t _oldSector) { return vobus.findVobu(_oldSector) ; } k9Vobu::~k9Vobu() {} k9Cell* k9CellList::addCell(int _vts,int _pgc, int _vob) { k9Cell* cell=new k9Cell; cell->cellList=this; cell->vts=_vts; cell->vob=_vob; cell->pgc=_pgc; if (count()!=0) { k9Cell *prev=(k9Cell*)last(); if (prev->vts==_vts) { cell->startSector= prev->lastSector +1; if (_pgc!=prev->pgc) cell->id=1; else cell->id=prev->id+1; } } else { cell->startSector = 0; cell->id=1; } append (cell); return(cell); } k9Vobu *k9CellList::findVobu(uint32_t sector) { k9Vobu *vobu=NULL; k9Cell *cell=findCell(sector); if (cell==NULL) return NULL; else return cell->findVobu(sector); int nbCells=count(); for (int i=0;i findVobu(sector); if (vobu !=NULL) { return vobu; } cell = (k9Cell*)at(nbCells-1-i); vobu = cell->findVobu(sector); if (vobu !=NULL) { return vobu; } } return vobu; } k9Cell * k9CellList::findCell(uint32_t sector) { return findCell(sector,0,count()-1); } k9Cell * k9CellList::findCell(uint32_t sector, uint32_t start, uint32_t end) { long lstart=start; long lend=end; while (lstart <=lend) { long m =(lstart+lend)/2; k9Cell *cell = (k9Cell *)at(m); k9Vobu *fv=cell->vobus.first(); k9Vobu *lv=cell->vobus.last(); if ( sector >=fv->oldSector && sector<= lv->oldSector) { return cell; } else if ( fv->oldSector >sector) { lend = m-1; } else { lstart=m+1; } } return NULL; } k9DVDTitleset * k9Cell::getTitleset() { k9DVDTitle *title=m_titles.at(0); return title->gettitleset(); } k9copy/src/core/k9cell.h0000755000175000017550000000751612412271774015641 0ustar emulatoremulator/*************************************************************************** * Copyright (C) 2005 by Jean-Michel Petit * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef K9CELL_H #define K9CELL_H #include "k9dvdtitle.h" enum streamType_t {stAudio,stVideo,stSubpicture,stOther}; /** @author Jean-Michel Petit */ class k9CellList; class k9Cell; class k9DVDTitleset; class k9Vobu { public: k9Vobu(k9Cell * parent,uint32_t _oldSector); ~k9Vobu(); uint32_t newSector; uint32_t oldSector; uint32_t size; int firstAudio[8]; int firstSubp[32]; int firstVideo; bool empty; k9Cell *parent; long vobPos; int vobNum; uchar frameType; uint32_t firstRef,secondRef,thirdRef; bool firstRefOk,secondRefOk,thirdRefOk; }; class k9VobuList : public QList { public: k9Vobu *findVobu(uint32_t sector); void clearList(); private: k9Vobu * findVobu(uint32_t sector, uint32_t start, uint32_t end); protected: static bool compareItems (const k9Vobu *item1, const k9Vobu *item2 ) ; }; class k9Cell { public: k9Cell(); ~k9Cell(); k9Vobu * addVobu(uint32_t _sector); void addNewVobus(char *_buffer,uint32_t _len,uint32_t _position,int _vobNum,long _vobPos); static int isNavPack (uchar *ptr); static streamType_t identifyStream( uchar *buffer,int * packetType ); static int getStreamID(int type); k9Vobu * findVobu(uint32_t _oldSector); uint32_t getnewSize(); void addTitle(k9DVDTitle *_title); k9DVDTitleset * getTitleset(); bool getforceFactor(); float getFactor(); public: k9VobuList vobus; int vts; int pgc; int vob; uint32_t startSector; uint32_t lastSector; //TO REMOVE uint32_t ; //TO REMOVE uint32_t ; //TO REMOVE uint32_t newSize; uchar angleBlock; //TO REMOVE int nbVideoNew,nbVideoOld; int id; bool selected; bool copied; QList audio; QList subpicture; k9CellList *cellList; private: int numVobu; void addRefStream(k9Vobu *_vobu,uchar *_buffer,uint32_t _position); QList m_titles; }; class k9CellList : public QList { private: uint32_t m_position; k9Cell * findCell(uint32_t sector); k9Cell * findCell(uint32_t sector, uint32_t start, uint32_t end); public: k9CellList() { m_position=0; }; k9Cell *addCell(int _vts, int _pgc,int _vob); k9Vobu *findVobu(uint32_t sector); void setPosition(const uint32_t& _value) { m_position = _value; } uint32_t getPosition() const { return m_position; } }; #endif k9copy/src/core/CTestTestfile.cmake0000664000175000017550000000051312412271774020016 0ustar emulatoremulator# CMake generated Testfile for # Source directory: /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/src/core # Build directory: /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/src/core # # This file includes the relevant testing commands required for # testing this directory and lists subdirectories to be tested as well. k9copy/src/core/Makefile0000664000175000017550000001501112412271774015731 0ustar emulatoremulator# CMAKE generated file: DO NOT EDIT! # Generated by "Unix Makefiles" Generator, CMake Version 2.8 # Default target executed when no arguments are given to make. default_target: all .PHONY : default_target #============================================================================= # Special targets provided by cmake. # Disable implicit rules so canonical targets will work. .SUFFIXES: # Remove some rules from gmake that .SUFFIXES does not remove. SUFFIXES = .SUFFIXES: .hpux_make_needs_suffix_list # Suppress display of executed commands. $(VERBOSE).SILENT: # A target that is always out of date. cmake_force: .PHONY : cmake_force #============================================================================= # Set environment variables for the build. # The shell in which to execute make rules. SHELL = /bin/sh # The CMake executable. CMAKE_COMMAND = /usr/bin/cmake # The command to remove a file. RM = /usr/bin/cmake -E remove -f # Escaping for special characters. EQUALS = = # The program to use to edit the cache. CMAKE_EDIT_COMMAND = /usr/bin/ccmake # The top-level source directory on which CMake was run. CMAKE_SOURCE_DIR = /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 # The top-level build directory on which CMake was run. CMAKE_BINARY_DIR = /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 #============================================================================= # Targets provided globally by CMake. # Special rule for the target edit_cache edit_cache: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." /usr/bin/ccmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) .PHONY : edit_cache # Special rule for the target edit_cache edit_cache/fast: edit_cache .PHONY : edit_cache/fast # Special rule for the target install install: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." /usr/bin/cmake -P cmake_install.cmake .PHONY : install # Special rule for the target install install/fast: preinstall/fast @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." /usr/bin/cmake -P cmake_install.cmake .PHONY : install/fast # Special rule for the target install/local install/local: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..." /usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake .PHONY : install/local # Special rule for the target install/local install/local/fast: install/local .PHONY : install/local/fast # Special rule for the target list_install_components list_install_components: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"Unspecified\"" .PHONY : list_install_components # Special rule for the target list_install_components list_install_components/fast: list_install_components .PHONY : list_install_components/fast # Special rule for the target package package: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Run CPack packaging tool..." cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && /usr/bin/cpack --config ./CPackConfig.cmake .PHONY : package # Special rule for the target package package/fast: package .PHONY : package/fast # Special rule for the target package_source package_source: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Run CPack packaging tool for source..." cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && /usr/bin/cpack --config ./CPackSourceConfig.cmake /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CPackSourceConfig.cmake .PHONY : package_source # Special rule for the target package_source package_source/fast: package_source .PHONY : package_source/fast # Special rule for the target rebuild_cache rebuild_cache: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." /usr/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) .PHONY : rebuild_cache # Special rule for the target rebuild_cache rebuild_cache/fast: rebuild_cache .PHONY : rebuild_cache/fast # Special rule for the target test test: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running tests..." /usr/bin/ctest --force-new-ctest-process $(ARGS) .PHONY : test # Special rule for the target test test/fast: test .PHONY : test/fast # The main all target all: cmake_check_build_system cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(CMAKE_COMMAND) -E cmake_progress_start /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CMakeFiles /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/src/core/CMakeFiles/progress.marks cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 src/core/all $(CMAKE_COMMAND) -E cmake_progress_start /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CMakeFiles 0 .PHONY : all # The main clean target clean: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 src/core/clean .PHONY : clean # The main clean target clean/fast: clean .PHONY : clean/fast # Prepare targets for installation. preinstall: all cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 src/core/preinstall .PHONY : preinstall # Prepare targets for installation. preinstall/fast: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 src/core/preinstall .PHONY : preinstall/fast # clear depends depend: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 .PHONY : depend # Help Target help: @echo "The following are some of the valid targets for this Makefile:" @echo "... all (the default if no target is provided)" @echo "... clean" @echo "... depend" @echo "... edit_cache" @echo "... install" @echo "... install/local" @echo "... list_install_components" @echo "... package" @echo "... package_source" @echo "... rebuild_cache" @echo "... test" .PHONY : help #============================================================================= # Special targets to cleanup operation of make. # Special rule to run CMake to check the build system integrity. # No rule that depends on this can have commands that come from listfiles # because they might be regenerated. cmake_check_build_system: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 .PHONY : cmake_check_build_system k9copy/src/core/k9videocodecs.cpp0000644000175000017550000004645012412271774017541 0ustar emulatoremulator// // C++ Implementation: k9videocodecs // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "k9videocodecs.h" #include #include class _k9VideoCodec { public: _k9VideoCodec():name(""),fourcc(""),optPass1(""),optPass2(""),optOnePass(""),encoder(""){} _k9VideoCodec(QString _name,QString _fourcc,QString _optOnePass,QString _optPass1,QString _optPass2,QString _encoder) { name=_name; fourcc=_fourcc; optOnePass=_optOnePass; optPass1=_optPass1; optPass2=_optPass2; encoder=_encoder; } QString name; QString fourcc; QString optPass1; QString optPass2; QString optOnePass; QString encoder; }; k9VideoCodecs::k9VideoCodecs(QObject *parent) : QObject(parent) { m_config=new k9Config(); KConfig *config= m_config->getConfig(); KConfigGroup group=config->group("codecs"); int nbVideo=group.readEntry("VideoCount",0); bool bReset; bReset=(nbVideo==0); //adds default codecs if (bReset) { reset(); m_config=new k9Config(); } for (int cpt=0;cpt group(QString("videocodec%1").arg(cpt)); m_codecs[cpt] = _k9VideoCodec(group.readEntry("name"), group.readEntry("fourcc",""),group.readEntry("opt1",""),group.readEntry("opt2",""),group.readEntry("opt3",""),group.readEntry("encoder","mencoder")); } delete m_config; } void k9VideoCodecs::reset() { m_codecs[0]=_k9VideoCodec("copy","","-ovc copy","-ovc copy","-ovc copy","mencoder"); m_codecs[1]=_k9VideoCodec("XviD","","-ovc xvid -xvidencopts bitrate=$VIDBR:aspect=$ASPECT -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc xvid -xvidencopts bitrate=$VIDBR:turbo:pass=$PASS:aspect=$ASPECT -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc xvid -xvidencopts bitrate=$VIDBR:turbo:pass=$PASS:aspect=$ASPECT -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","mencoder"); m_codecs[2]=_k9VideoCodec("x264","","-ovc x264 -x264encopts bitrate=$VIDBR:threads=0 -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc x264 -x264encopts bitrate=$VIDBR:turbo=1:pass=$PASS:threads=0 -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc x264 -x264encopts bitrate=$VIDBR:turbo=1:pass=$PASS:threads=0 -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","mencoder"); m_codecs[3]=_k9VideoCodec("MJPEG","","-ovc lavc -lavcopts vcodec=mjpeg:vhq:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=mjpeg:vhq:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=mjpeg:vhq:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","mencoder"); m_codecs[4]=_k9VideoCodec("LJPEG","","-ovc lavc -lavcopts vcodec=ljpeg:vhq:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=ljpeg:vhq:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=ljpeg:vhq:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","mencoder"); m_codecs[5]=_k9VideoCodec("H261","","-ovc lavc -lavcopts vcodec=h261:vhq:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=h261:vhq:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=h261:vhq:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","mencoder"); m_codecs[6]=_k9VideoCodec("H263","","-ovc lavc -lavcopts vcodec=h263:vhq:v4mv:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=h263:vhq:v4mv:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=h263:vhq:v4mv:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","mencoder"); m_codecs[7]=_k9VideoCodec("H263+","","-ovc lavc -lavcopts vcodec=h263p:vhq:v4mv:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=h263p:vhq:v4mv:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=h263p:vhq:v4mv:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","mencoder"); m_codecs[8]=_k9VideoCodec("MPEG-4 (DivX 4/5)","DIVX","-ovc lavc -lavcopts vcodec=mpeg4:vhq:v4mv:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=mpeg4:vhq:v4mv:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=mpeg4:vhq:v4mv:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","mencoder"); m_codecs[9]=_k9VideoCodec("MS MPEG-4 (DivX 3)","DIVX","-ovc lavc -lavcopts vcodec=msmpeg4:vhq:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=msmpeg4:vhq:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=msmpeg4:vhq:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","mencoder"); m_codecs[10]=_k9VideoCodec("MS MPEG-4 v2","","-ovc lavc -lavcopts vcodec=msmpeg4v2:vhq:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=msmpeg4v2:vhq:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=msmpeg4v2:vhq:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","mencoder"); m_codecs[11]=_k9VideoCodec("WMV7","","-ovc lavc -lavcopts vcodec=wmv1:vhq:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=wmv1:vhq:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=wmv1:vhq:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","mencoder"); m_codecs[12]=_k9VideoCodec("WMV8","","-ovc lavc -lavcopts vcodec=wmv2:vhq:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=wmv2:vhq:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=wmv2:vhq:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","mencoder"); m_codecs[13]=_k9VideoCodec("RealVideo","","-ovc lavc -lavcopts vcodec=rv10:vhq:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=rv10:vhq:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=rv10:vhq:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","mencoder"); m_codecs[14]=_k9VideoCodec("MPEG-1 Video","","-ovc lavc -lavcopts vcodec=mpeg1video:vhq:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=mpeg1video:vhq:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=mpeg1video:vhq:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","mencoder"); m_codecs[15]=_k9VideoCodec("MPEG-2 Video","","-ovc lavc -lavcopts vcodec=mpeg2video:vhq:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=mpeg2video:vhq:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=mpeg2video:vhq:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","mencoder"); m_codecs[16]=_k9VideoCodec("Huffmann yuv","","-ovc lavc -lavcopts vcodec=huffyuv:vhq:v4mv:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:format=422p -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=huffyuv:vhq:v4mv:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT::format=422p:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=huffyuv:vhq:v4mv:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT::format=422p:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","mencoder"); m_codecs[17]=_k9VideoCodec("ffv Huffmann","","-ovc lavc -lavcopts vcodec=ffvhuff:vhq:v4mv:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=ffvhuff:vhq:v4mv:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=ffvhuff:vhq:v4mv:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","mencoder"); m_codecs[18]=_k9VideoCodec("ASUS v1","","-ovc lavc -lavcopts vcodec=asv1:vhq:v4mv:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=asv1:vhq:v4mv:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=asv1:vhq:v4mv:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","mencoder"); m_codecs[19]=_k9VideoCodec("ASUS v2","","-ovc lavc -lavcopts vcodec=asv2:vhq:v4mv:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=asv2:vhq:v4mv:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=asv2:vhq:v4mv:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","mencoder"); m_codecs[20]=_k9VideoCodec("flv","","-ovc lavc -lavcopts vcodec=flv:vhq:v4mv:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=flv:vhq:v4mv:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","-ovc lavc -lavcopts vcodec=flv:vhq:v4mv:vqmin=2:vbitrate=$VIDBR:aspect=$ASPECT:turbo:vpass=$PASS -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP,scale=$WIDTH:$HEIGHT,dsize=$ASPECT","mencoder"); m_codecs[21]=_k9VideoCodec("copy","","-codec:v copy","-codec:v copy","-codec:v copy","ffmpeg"); m_codecs[22]=_k9VideoCodec("x264","","-b $VIDBRk -s $WIDTHx$HEIGHT -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP -aspect $ASPECT -codec:v libx264 -level 30","-b $VIDBRk -s $WIDTHx$HEIGHT -vf crop=$WIDTH-$CROPRIGHT-$CROPLEFT:$HEIGHT-$CROPTOP-$CROPBOTTOM:$CROPLEFT:$CROPTOP -aspect $ASPECT -codec:v libx264 -pass $PASS -passlogfile $PASSLOGFILE -level 30","-b $VIDBRk -s $WIDTHx$HEIGHT -vf crop=$WIDTH-$CROPRIGHT-$CROPLEFT:$HEIGHT-$CROPTOP-$CROPBOTTOM:$CROPLEFT:$CROPTOP -aspect $ASPECT -codec:v libx264 -pass $PASS -passlogfile $PASSLOGFILE -level 30","ffmpeg"); m_codecs[23]=_k9VideoCodec("x264 (high)","","-b $VIDBRk -s $WIDTHx$HEIGHT -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP -aspect $ASPECT -codec:v libx264 -level 30 -flags +loop+mv4 -cmp 256 -partitions +parti4x4+parti8x8+partp4x4+partp8x8+partb8x8 -me_method hex -subq 7 -trellis 1 -refs 5 -bf 3 -b-pyramid normal -weightb 1 -mixed-refs 1 -8x8dct 1 -coder 1 -me_range 16 -g 250 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -qmin 10 -qmax 51 -qdiff 4","-b $VIDBRk -s $WIDTHx$HEIGHT -vf crop=$WIDTH-$CROPRIGHT-$CROPLEFT:$HEIGHT-$CROPTOP-$CROPBOTTOM:$CROPLEFT:$CROPTOP -aspect $ASPECT -codec:v libx264 -level 30 -flags +loop+mv4 -cmp 256 -partitions +parti4x4+parti8x8+partp4x4+partp8x8+partb8x8 -me_method hex -subq 7 -trellis 1 -refs 5 -bf 3 -b-pyramid normal -weightb 1 -mixed-refs 1 -8x8dct 1 -coder 1 -me_range 16 -g 250 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -qmin 10 -qmax 51 -qdiff 4 -pass $PASS -passlogfile $PASSLOGFILE","-b $VIDBRk -s $WIDTHx$HEIGHT -vf crop=$WIDTH-$CROPRIGHT-$CROPLEFT:$HEIGHT-$CROPTOP-$CROPBOTTOM:$CROPLEFT:$CROPTOP -aspect $ASPECT -codec:v libx264 -level 30 -flags +loop+mv4 -cmp 256 -partitions +parti4x4+parti8x8+partp4x4+partp8x8+partb8x8 -me_method hex -subq 7 -trellis 1 -refs 5 -bf 3 -b-pyramid normal -weightb 1 -mixed-refs 1 -8x8dct 1 -coder 1 -me_range 16 -g 250 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -qmin 10 -qmax 51 -qdiff 4 -pass $PASS -passlogfile $PASSLOGFILE","ffmpeg"); m_codecs[24]=_k9VideoCodec("MPEG-4 ","","-b $VIDBRk -s $WIDTHx$HEIGHT -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP -aspect $ASPECT -codec:v mpeg4 ","-b $VIDBRk -s $WIDTHx$HEIGHT -vf crop=$WIDTH-$CROPRIGHT-$CROPLEFT:$HEIGHT-$CROPTOP-$CROPBOTTOM:$CROPLEFT:$CROPTOP -aspect $ASPECT -codec:v mpeg4 -pass $PASS -passlogfile $PASSLOGFILE","-b $VIDBRk -s $WIDTHx$HEIGHT -vf crop=$WIDTH-$CROPRIGHT-$CROPLEFT:$HEIGHT-$CROPTOP-$CROPBOTTOM:$CROPLEFT:$CROPTOP -aspect $ASPECT -codec:v mpeg4 -pass $PASS -passlogfile $PASSLOGFILE","ffmpeg"); m_codecs[25]=_k9VideoCodec("Flash Video","","-b $VIDBRk -s $WIDTHx$HEIGHT -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP -aspect $ASPECT -codec:v flv ","-b $VIDBRk -s $WIDTHx$HEIGHT -vf crop=$WIDTH-$CROPRIGHT-$CROPLEFT:$HEIGHT-$CROPTOP-$CROPBOTTOM:$CROPLEFT:$CROPTOP -aspect $ASPECT -codec:v flv -pass $PASS -passlogfile $PASSLOGFILE","-b $VIDBRk -s $WIDTHx$HEIGHT -vf crop=$WIDTH-$CROPRIGHT-$CROPLEFT:$HEIGHT-$CROPTOP-$CROPBOTTOM:$CROPLEFT:$CROPTOP -aspect $ASPECT -codec:v flv -pass $PASS -passlogfile $PASSLOGFILE","ffmpeg"); m_codecs[26]=_k9VideoCodec("Windows Media 8","","-b $VIDBRk -s $WIDTHx$HEIGHT -vf crop=$CROPWIDTH:$CROPHEIGHT:$CROPLEFT:$CROPTOP -aspect $ASPECT -codec:v wmv2","-b $VIDBRk -s $WIDTHx$HEIGHT -vf crop=$WIDTH-$CROPRIGHT-$CROPLEFT:$HEIGHT-$CROPTOP-$CROPBOTTOM:$CROPLEFT:$CROPTOP -aspect $ASPECT -codec:v wmv2 -pass $PASS -passlogfile $PASSLOGFILE","-b $VIDBRk -s $WIDTHx$HEIGHT -vf crop=$WIDTH-$CROPRIGHT-$CROPLEFT:$HEIGHT-$CROPTOP-$CROPBOTTOM:$CROPLEFT:$CROPTOP -aspect $ASPECT -codec:v wmv2 -pass $PASS -passlogfile $PASSLOGFILE","ffmpeg"); save(); } void k9VideoCodecs::save() { m_config=new k9Config(); KConfig *config= m_config->getConfig(); KConfigGroup group=config->group("codecs"); int cpt=0; for (QMap::iterator i=m_codecs.begin();i!=m_codecs.end();++i) { group=config->group(QString("videocodec%1").arg(cpt)); group.writeEntry("name", i.value().name); group.writeEntry("fourcc", i.value().fourcc); group.writeEntry("opt1",i.value().optOnePass); group.writeEntry("opt2", i.value().optPass1); group.writeEntry("opt3",i.value().optPass2); group.writeEntry("encoder",i.value().encoder); cpt++; } group=config->group("codecs"); group.writeEntry("VideoCount",cpt); m_config->save(); delete m_config; } int k9VideoCodecs::count() { return m_codecs.count(); } void k9VideoCodecs::setFourcc(int _num,QString _value) { m_codecs[_num].fourcc=_value; } void k9VideoCodecs::setOptions0(int _num,QString _value) { m_codecs[_num].optOnePass=_value; } void k9VideoCodecs::setOptions1(int _num,QString _value) { m_codecs[_num].optPass1=_value; } void k9VideoCodecs::setOptions2(int _num,QString _value) { m_codecs[_num].optPass2=_value; } void k9VideoCodecs::setCodecName(int _num,QString _value) { m_codecs[_num].name=_value; } void k9VideoCodecs::setEncoder(int _num,QString _value) { m_codecs[_num].encoder=_value; } QString k9VideoCodecs::getFourcc(int _num) { return m_codecs[_num].fourcc; } QString k9VideoCodecs::getOptions0(int _num) { return m_codecs[_num].optOnePass; } QString k9VideoCodecs::getOptions1(int _num) { return m_codecs[_num].optPass1; } QString k9VideoCodecs::getOptions2(int _num) { return m_codecs[_num].optPass2; } QString k9VideoCodecs::getCodecName(int _num) { return m_codecs[_num].name; } int k9VideoCodecs::getAbsCodecNum(int _num,const QString &_encoder) { k9VideoCodecs v(0); int nb=v.count(); int num=0; for (int i=0;i0) { for(int i=_num;i, (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9dvdchapter.h" #include "k9dvdtitle.h" //************************* k9DVDChapter************************ /** Read property of int num. */ const int& k9DVDChapter::getnum() { return num; } /** Read property of QTime length. */ const QTime& k9DVDChapter::getLength() { return m_length; } /** Read property of int sectors. */ const int& k9DVDChapter::getsectors() { return sectors; } const QTime& k9DVDChapter::getTime() { return m_time; } k9DVDTitle *k9DVDChapter::getTitle() { return m_title; } void k9DVDChapter::clearCells() { // while (!cells.isEmpty()) delete cells.takeFirst(); qDeleteAll(cells); cells.clear(); } k9DVDChapter::~k9DVDChapter() { clearCells(); } k9DVDChapter::k9DVDChapter():QObject() { m_length.setHMS(0,0,0); num=0; sectors=0; startSector=0; endSector=0; m_selected=false; m_time.setHMS(0,0,0); } bool k9DVDChapter::getSelected() const { return m_selected; } void k9DVDChapter::setSelected(bool _value) { if (_value && !m_title->isSelected() ) { m_title->setvideoSelected( true,false); // m_title->selectChapters( false); } m_selected = _value; emit selectionChanged(); } void k9DVDChapter::setLength(const QTime& theValue) { m_length = theValue; } void k9DVDChapter::setTime(const QTime& theValue) { m_time = theValue; } k9copy/src/core/k9dvdtitle.h0000644000175000017550000002115712412271774016533 0ustar emulatoremulator/************************************************************************** * Copyright (C) 2005 by Jean-Michel Petit * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef K9DVDTITLE_H #define K9DVDTITLE_H #include "k9dvd.h" #include "k9dvdchapter.h" #include #include class k9DVDTitleSet; class k9DVDVideoStream { friend class k9DVDTitle; private: // Private attributes public: // Public methods }; class k9DVDAudioStream { friend class k9DVDTitle; friend class k9DVD; private: // Private attributes /** */ QString langCod; /** */ QString language; /** */ QString format; /** */ QString frequency; /** */ QString quantization; /** */ int channels; /** */ int appMode; /** */ QString content; /** */ float size_mb; /** */ bool selected; int id; k9DVDTitle *title; int m_streamId; public: // Public methods k9DVDAudioStream(); /** Read property of QString langCod. */ virtual const QString& getlangCod(); /** Read property of QString language. */ virtual const QString& getlanguage(); /** Read property of QString format. */ virtual const QString& getformat(); /** Read property of QString frequency. */ virtual const QString& getfrequency(); /** Read property of QString quantization. */ virtual const QString& getquantization(); /** Read property of int channels. */ virtual const int& getchannels(); /** Read property of int appMode. */ virtual const int& getappMode(); /** Read property of QString content. */ virtual const QString& getcontent(); /** Read property of float size_mb. */ virtual const float& getsize_mb(); /** Write property of bool selected. */ virtual void setselected( const bool& _newVal); /** Read property of bool selected. */ virtual const bool& getselected(); virtual k9DVDTitle* gettitle(); virtual int getID(); virtual int getStreamId() const { return m_streamId; }; virtual ~k9DVDAudioStream() {}; }; class k9DVDSubtitle { friend class k9DVDTitle; friend class k9DVD; private: // Private attributes /** */ QString langCod; /** */ QString language; /** */ int num; /** */ QString content; /** */ float size_mb; /** */ bool selected; QList id; k9DVDTitle *title; public: // Public methods k9DVDSubtitle(); /** Read property of QString langCod. */ virtual const QString& getlangCod(); /** Read property of QString language. */ virtual const QString& getlanguage(); /** Read property of int num. */ virtual const int& getnum(); /** Read property of QString content. */ virtual const QString& getcontent(); /** Read property of float size_mb. */ virtual const float& getsize_mb(); /** Write property of bool selected. */ virtual void setselected( const bool& _newVal); /** Read property of bool selected. */ virtual const bool& getselected(); virtual k9DVDTitle* gettitle(); virtual QList& getID(); virtual ~k9DVDSubtitle() {}; }; class k9TitleEncOpt; class k9DVDTitle : public QObject { Q_OBJECT friend class k9DVD; private: // Public attributes unsigned int ts_nr; int chapterCount; int streamCount; int audioStreamCount; int subPictureCount; QTime length; k9DVDVideoStream videoStream; QList< k9DVDAudioStream*> audioStreams; QList subtitles; int VTS; int TTN; float FPS; QString format; QString aspectRatio; int numTitle; QString width; QString height; QStringList palette; QString DF; float size_mb; int angleCount; float videosize_mb; float vobusize_mb; QString name; k9DVDTitle* nextTitle; int id; k9DVDTitleset *m_titleset; k9DVDAudioStream *m_defAudio; k9DVDSubtitle *m_defSubtitle; bool m_defAudioSet; bool m_defSubtitleSet; QList m_titles; uint32_t m_sectors; bool m_forceFactor; float m_factor; k9TitleEncOpt *m_encOpt; k9DVDTitle *m_mainTitle; public: // Public methods k9DVDTitle(k9DVD *dvd); ~k9DVDTitle(); virtual k9DVDTitleset *gettitleset() { return m_titleset; }; virtual const int& getchapterCount(); virtual const int& getstreamCount(); virtual const int& getaudioStreamCount(); virtual const int& getsubPictureCount(); virtual const QTime& getlength(); virtual QTime gettotallength(); virtual QTime getSelectedLength(); virtual const int& getVTS(); virtual const int& getTTN(); virtual const float& getFPS(); virtual const QString& getformat(); virtual const QString& getaspectRatio(); virtual const QString& getwidth(); virtual const QString& getheight(); virtual void getpalette(int i,QString & c); virtual const QString& getDF(); virtual const int& getangleCount(); virtual const int& getnumTitle(); virtual k9DVDAudioStream *getaudioStream(int num); virtual k9DVDSubtitle *getsubtitle(int num); virtual const float& getsize_mb(); virtual float gettotalsize_mb(); virtual float gettotalvideosize_mb(); virtual float getChaptersSize_mb(bool _selected); virtual uint64_t getChaptersSize(bool _selected); virtual const float& getvideosize_mb(); virtual bool isSelected(); virtual void setname( const QString& _newVal); virtual const QString& getname(); virtual int getpgc(); virtual void setnextTitle(k9DVDTitle * nTitle); virtual k9DVDTitle* getnextTitle(); virtual k9DVDChapter *getChapter(int num); virtual bool getIndexed() { return indexed; }; virtual void setvideoSelected(bool _state,bool _updateChapters=true); virtual void setSelected(bool _state); virtual int getId() { return id; }; virtual void setDefAudio(k9DVDAudioStream* _value); virtual k9DVDAudioStream* getDefAudio() const; virtual void setDefSubtitle(k9DVDSubtitle* _value); virtual k9DVDSubtitle* getDefSubtitle() const; virtual k9DVDChapter *getChapterFromSector(uint32_t _sector); virtual bool getDefAudioSet() const { return m_defAudioSet; }; virtual bool getDefSubtitleSet() const { return m_defSubtitleSet; }; virtual QList< k9DVDTitle* > getTitles() const { return m_titles; }; virtual uint32_t getsectors() { return m_sectors; }; virtual float getfactor() { return m_factor; }; virtual bool getforceFactor() { return m_forceFactor; }; virtual void selectChapters(bool _state); virtual QList< k9DVDChapter *> getChapters() const { return chapters; }; virtual k9TitleEncOpt* getEncOpt() ; public slots: virtual void setfactor(float _value) { m_factor=_value; }; virtual void setforceFactor(bool _value) { m_forceFactor=_value; }; k9DVDTitle* getMainTitle() const; k9DVD* getDvd() const; signals: void selectionChanged(); private: // Private methods k9DVDAudioStream* addAudioStream(); k9DVDChapter* addChapter(int num); k9DVDSubtitle* addSubtitle(int num); void clearAudioStreams(); void clearSubtitles(); void clearChapters(); QList chapters; bool indexed; bool forceSelection; int pgc; k9DVD *m_dvd; public: // Public attributes }; #endif k9copy/src/core/k9saveimage.cpp0000644000175000017550000000367212412271774017212 0ustar emulatoremulator// // C++ Implementation: k9saveimage // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "k9saveimage.h" #include "k9decodethread.h" #include #include void k9SaveImage::drawImage(QImage *_image) { m_cpt++; if (m_cpt ==20) { m_mutex.lock(); m_image=*_image; m_mutex.unlock(); //m_decoder->pause(); } } k9SaveImage::k9SaveImage() : QThread() { m_tempFile= new QTemporaryFile(k9Tools::getTempPath()+"k9pXXXXXX.png"); m_tempFile->open(); m_tempFile->setAutoRemove(true); m_decoder=new k9DecodeThread(); m_decoder->setSaveImage(this); //connect(m_decoder, SIGNAL(pixmapReady(QImage*)), this, SLOT(drawImage(QImage*))); } k9SaveImage::~k9SaveImage() { wait(); delete m_decoder; delete m_tempFile; } void k9SaveImage::play() { m_cpt=0; m_stop=false; m_timer.start(); m_decoder->start(LowestPriority); } void k9SaveImage::stop() { m_stop=true; wait(); //m_decoder->stop(); } void k9SaveImage::addData(uchar *_buffer, uint32_t _size) { if (m_timer.elapsed() >=7000 ) { if (m_mutex.tryLock()) { m_size=_size; m_buffer=new uchar[m_size]; memcpy(m_buffer,_buffer,m_size); m_mutex.unlock(); start(LowestPriority); } m_timer.restart(); } } void k9SaveImage::run() { m_mutex.lock(); m_cpt=0; m_decoder->addData(m_buffer ,m_size); delete m_buffer; QString sFileName=m_tempFile->fileName(); m_image.save(sFileName,"PNG"); m_fileName=sFileName; sFileName="\rINFOIMAGE:"+sFileName; fprintf(stderr, "%s", (const char*) sFileName.toUtf8()); m_mutex.unlock(); } QString k9SaveImage::getFileName() { m_mutex.lock(); QString ret( m_fileName.isNull() ? QString(""):m_fileName); m_mutex.unlock(); return ret; } k9copy/src/core/k9ifo2.cpp0000644000175000017550000007610512412511232016073 0ustar emulatoremulator/*************************************************************************** * Copyright (C) 2005 by Jean-Michel Petit * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "k9ifo2.h" #include "bswap.h" //PM DVDNAV #include "dvdread.h" #include "dvdread/dvd_reader.h" #include #include //PM TRYING THIS FUNCTION //PM TRYING THIS FUNCTION k9Ifo2::k9Ifo2(k9DVDRead *_dvdread) { _ifo=NULL; m_dvd=_dvdread; m_VTSVobs=0; } k9Ifo2::~k9Ifo2() { closeIFO(); } /*! \fn k9Ifo2::setDevice(QString &_device) */ void k9Ifo2::setDevice(QString &_device) { device=_device; } /*! \fn k9Ifo2::setOutput(QString &_output) */ void k9Ifo2::setOutput(QString &_output) { output=_output; } void k9Ifo2::setVTSVobs(uint32_t _sector) { m_VTSVobs=_sector; } uint32_t k9Ifo2::getSize() { return m_size; } /*! \fn k9Ifo2::openIFO(int _num) */ ifo_handle_t * k9Ifo2::openIFO(int _num) { _ifo = ifoOpen(m_dvd->getDvd(), _num); if (_ifo) { numIfo=_num; if( _ifo->vtsi_mat) m_size=_ifo->vtsi_mat->vtsi_last_sector +1; else m_size=_ifo->vmgi_mat->vmgi_last_sector+1; } return _ifo; } /*! \fn k9Ifo2::IFOClose( ifo_handle_t* _ifo) */ void k9Ifo2::closeIFO() { if(_ifo!=NULL) { ifoClose(_ifo); _ifo=NULL; } } ifo_handle_t * k9Ifo2::getIFO() { return _ifo; } /*! \fn k9Ifo2::saveIFO(ifo_handle_t* _ifo) */ void k9Ifo2::saveIFO() { uint32_t size; /* DVD handler */ k9DVDFile *dvdfile; bool mainIfo = (numIfo==0); QString filename,filename2; if (mainIfo) { filename="/VIDEO_TS/VIDEO_TS.IFO"; } else { filename.sprintf("/VIDEO_TS/VTS_%02d_0.IFO",numIfo); } if (numIfo==0) size=_ifo->vmgi_mat->vmgi_last_sector +1; else size=_ifo->vtsi_mat->vtsi_last_sector +1; size*=DVD_BLOCK_LEN; // if (k9UDFFindFile(dvd,(char*) filename.latin1(), &size)) { if (size > 0) { uchar *buffer ; buffer=new uchar[size]; bufCopy=new uchar[size]; m_buffer=new uchar[size*2]; memset(buffer,0,size); memset(bufCopy,0,size); memset(m_buffer,0,size*2); //Lecture du fichier IFO original et sauvegarde dans buffer if ((dvdfile = m_dvd->openIfo(numIfo))== 0) { fprintf(stderr, "Failed opening IFO for titleset %d\n", 0); free(buffer); return; } /* if(DVDFileSeek(dvd_file, 0)!=0) { return; } */ if (dvdfile->readBytes(buffer,size) != (int)size) { fprintf(stderr, "Error reading IFO for titleset %d\n", 0); free(buffer); dvdfile->close(); return; } memcpy(bufCopy,buffer,size); bufCopySize=size; dvdfile->close(); if (mainIfo) { m_position=0; updateVMG(buffer); m_position=1024; //sizeof(vmgi_mat_t); updateFP_PGC(buffer); _ifo->vmgi_mat->vmgi_last_byte=m_position -1; updateTT_SRPT(buffer); updatePGCI_UT(buffer); updateVTS_ATRT(buffer); updateTXTDT_MGI(buffer); updateC_ADT(buffer,true); updateVOBU_ADMAP(buffer,true); updateVMG(buffer); } else { m_position=0; updateVTS(buffer); m_position=sizeof(vtsi_mat_t); //_ifo->vtsi_mat->vtsi_last_byte=m_position -1; updateVTS_PTT_SRPT(buffer); updatePGCIT(buffer); updatePGCI_UT(buffer); updateVTS_TMAPT(buffer); updateC_ADT(buffer,true); updateVOBU_ADMAP(buffer,true); updateC_ADT(buffer, false); updateVOBU_ADMAP(buffer,false); updateVTS(buffer); } m_position=round(m_position); //sauvegarder buffer dans fichier if (mainIfo) { filename=output + "/VIDEO_TS.IFO"; filename2=output + "/VIDEO_TS.BUP"; } else { filename.sprintf("/VTS_%02d_0.IFO",numIfo); filename=output + filename; filename2.sprintf("/VTS_%02d_0.BUP",numIfo); filename2=output + filename2; } QFile ifofile (filename); ifofile.remove(); ifofile.open(QIODevice::WriteOnly); if (ifofile.write((char*)m_buffer,m_position) == -1) { QString sError("erreur"); } ifofile.close(); QFile ifofile2 (filename2); ifofile2.remove(); ifofile2.open(QIODevice::WriteOnly); if (ifofile2.write((char*)m_buffer,m_position) == -1) { QString sError("erreur"); } ifofile2.close(); delete buffer; delete bufCopy; delete m_buffer; } } /*! \fn k9Ifo2::updateVMG(uchar * _buffer) */ void k9Ifo2::updateVMG(uchar * ) { vmgi_mat_t vmgi_mat; memcpy(&vmgi_mat,_ifo->vmgi_mat,sizeof(vmgi_mat_t)); uint32_t lastSector=vmgi_mat.vmgi_last_sector; //JMP : à vérifier if (m_position !=0) { lastSector=(round(m_position) - DVD_BLOCK_LEN) / DVD_BLOCK_LEN; //lastByte=vmgi_mat.vmgi_last_sector * DVD_BLOCK_LEN +DVD_BLOCK_LEN -1; vmgi_mat.vmg_last_sector+=2*(lastSector-vmgi_mat.vmgi_last_sector); } vmgi_mat.vmgi_last_sector=lastSector; if (vmgi_mat.vmgm_vobs !=0) vmgi_mat.vmgm_vobs=vmgi_mat.vmgi_last_sector +1; B2N_32(vmgi_mat.vmg_last_sector); B2N_32(vmgi_mat.vmgi_last_sector); B2N_32(vmgi_mat.vmg_category); B2N_16(vmgi_mat.vmg_nr_of_volumes); B2N_16(vmgi_mat.vmg_this_volume_nr); B2N_16(vmgi_mat.vmg_nr_of_title_sets); B2N_64(vmgi_mat.vmg_pos_code); B2N_32(vmgi_mat.vmgi_last_byte); B2N_32(vmgi_mat.first_play_pgc); B2N_32(vmgi_mat.vmgm_vobs); B2N_32(vmgi_mat.tt_srpt); B2N_32(vmgi_mat.vmgm_pgci_ut); B2N_32(vmgi_mat.ptl_mait); B2N_32(vmgi_mat.vts_atrt); B2N_32(vmgi_mat.txtdt_mgi); B2N_32(vmgi_mat.vmgm_c_adt); B2N_32(vmgi_mat.vmgm_vobu_admap); //PM B2N_8(vmgi_mat.vmgm_video_attr); //PM SEE BSWAP.H //PM B2N_16(vmgi_mat.vmgm_video_attr) ; //PM THIS IS A CHANGE..... //PM if this works do: /* uint16_t MPEG_VERSION = (vmgi_mat.vmgm_video_attr.mpeg_version); uint16_t VIDEO_FORMAT = (vmgi_mat.vmgm_video_attr.video_format); uint16_t DISPLAY_ASPECT = (vmgi_mat.vmgm_video_attr.display_aspect_ratio); uint16_t PERMITTED_DF = (vmgi_mat.vmgm_video_attr.permitted_df); uint16_t Line21_CC_1 = (vmgi_mat.vmgm_video_attr.line21_cc_1); uint16_t line21_CC_2 = (vmgi_mat.vmgm_video_attr.line21_cc_2); uint16_t Unkown1 = (vmgi_mat.vmgm_video_attr.unknown1); uint16_t BIT_RATE = (vmgi_mat.vmgm_video_attr.bit_rate); uint16_t PICTURE_SIZE = (vmgi_mat.vmgm_video_attr.picture_size); uint16_t LETTERBOXED =(vmgi_mat.vmgm_video_attr.letterboxed); uint16_t FILM_MODE =(vmgi_mat.vmgm_video_attr.film_mode); B2N_16(MPEG_VERSION); B2N_16(VIDEO_FORMAT); B2N_16(DISPLAY_ASPECT); B2N_16(PERMITTED_DF); B2N_16(Line21_CC_1); B2N_16(line21_CC_2); B2N_16(Unkown1); B2N_16(BIT_RATE); B2N_16(PICTURE_SIZE); B2N_16(LETTERBOXED); B2N_16(FILM_MODE); (vmgi_mat.vmgm_video_attr.mpeg_version)=MPEG_VERSION; (vmgi_mat.vmgm_video_attr.video_format)=VIDEO_FORMAT ; (vmgi_mat.vmgm_video_attr.display_aspect_ratio)=DISPLAY_ASPECT ; (vmgi_mat.vmgm_video_attr.permitted_df)=PERMITTED_DF ; (vmgi_mat.vmgm_video_attr.line21_cc_1)=Line21_CC_1 ; (vmgi_mat.vmgm_video_attr.line21_cc_2)=line21_CC_2 ; (vmgi_mat.vmgm_video_attr.unknown1)=Unkown1 ; (vmgi_mat.vmgm_video_attr.bit_rate)=BIT_RATE ; (vmgi_mat.vmgm_video_attr.picture_size)=PICTURE_SIZE ; (vmgi_mat.vmgm_video_attr.letterboxed)=LETTERBOXED; (vmgi_mat.vmgm_video_attr.film_mode)=FILM_MODE; */ //PM ENDS HERE B2N_16(vmgi_mat.vmgm_audio_attr.lang_code); B2N_16(vmgi_mat.vmgm_audio_attr.lang_code); B2N_16(vmgi_mat.vmgm_subp_attr.lang_code); memcpy(m_buffer,&vmgi_mat,sizeof(vmgi_mat_t)); } /*! \fn k9Ifo2::updateFP_PGC(uchar * _buffer) */ void k9Ifo2::updateFP_PGC(uchar * _buffer) { //int offset=_ifo->vmgi_mat->first_play_pgc; _ifo->vmgi_mat->first_play_pgc=m_position; return updatePGC(_buffer,_ifo->first_play_pgc,m_position); } /*! \fn k9Ifo2::updatePGC(uchar *_buffer,pgc_t *_pgc,int _offset) */ void k9Ifo2::updatePGC(uchar *_buffer,pgc_t *_pgc,int _offset) { pgc_t pgc; memcpy(&pgc,_pgc,sizeof(pgc_t)); uint start=m_position; m_position+=PGC_SIZE; if(pgc.command_tbl_offset != 0) { pgc.command_tbl_offset=PGC_SIZE; updatePGC_COMMAND_TBL(_buffer ,pgc.command_tbl ,m_position); } if(pgc.program_map_offset != 0) { pgc.program_map_offset=m_position-start; updatePGC_PROGRAM_MAP(_buffer, pgc.program_map,pgc.nr_of_programs ,m_position); } if(pgc.cell_playback_offset != 0) { pgc.cell_playback_offset=m_position-start; updatePGC_CELL_PLAYBACK_TBL(_buffer ,pgc.cell_playback,pgc.nr_of_cells,m_position); } if(pgc.cell_position_offset != 0) { pgc.cell_position_offset=m_position-start; updatePGC_CELL_POSITION_TBL(_buffer,pgc.cell_position,pgc.nr_of_cells,m_position); } B2N_16(pgc.command_tbl_offset); B2N_16(pgc.next_pgc_nr); B2N_16(pgc.prev_pgc_nr); B2N_16(pgc.goup_pgc_nr); B2N_16(pgc.program_map_offset); B2N_16(pgc.cell_playback_offset); B2N_16(pgc.cell_position_offset); int i; for(i = 0; i < 8; i++) B2N_16(pgc.audio_control[i]); for(i = 0; i < 32; i++) B2N_32(pgc.subp_control[i]); for(i = 0; i < 16; i++) B2N_32(pgc.palette[i]); memcpy(m_buffer+_offset,&pgc,PGC_SIZE); } /*! \fn k9Ifo2::updatePGC_COMMAND_TBL(uchar *_buffer,pgc_command_tbl_t *_cmd_tbl,int offset) */ void k9Ifo2::updatePGC_COMMAND_TBL(uchar *,pgc_command_tbl_t *_cmd_tbl,int _offset) { struct { uint16_t nr_of_pre; uint16_t nr_of_post; uint16_t nr_of_cell; uint16_t last_byte; } ATTRIBUTE_PACKED cmd_tbl; memcpy(&cmd_tbl,_cmd_tbl,sizeof(cmd_tbl)); //moves the offset to save vm_cmd m_position+=sizeof(cmd_tbl); if(_cmd_tbl->nr_of_pre != 0) { unsigned int pre_cmds_size = _cmd_tbl->nr_of_pre * COMMAND_DATA_SIZE; memcpy(m_buffer + m_position,_cmd_tbl->pre_cmds,pre_cmds_size); m_position+=pre_cmds_size; } if(_cmd_tbl->nr_of_post != 0) { unsigned int post_cmds_size = _cmd_tbl->nr_of_post * COMMAND_DATA_SIZE; memcpy(m_buffer + m_position,_cmd_tbl->post_cmds,post_cmds_size); m_position+=post_cmds_size; } if(_cmd_tbl->nr_of_cell != 0) { unsigned int cell_cmds_size = _cmd_tbl->nr_of_cell * COMMAND_DATA_SIZE; memcpy(m_buffer +m_position,_cmd_tbl->cell_cmds,cell_cmds_size); m_position+=cell_cmds_size; } B2N_16(cmd_tbl.nr_of_pre); B2N_16(cmd_tbl.nr_of_post); B2N_16(cmd_tbl.nr_of_cell); cmd_tbl.last_byte=m_position-_offset-1; B2N_16(cmd_tbl.last_byte); memcpy(m_buffer+_offset,&cmd_tbl,sizeof(cmd_tbl)); } /*! \fn k9Ifo2::updatePGC_PROGRAM_MAP(uchar *_buffer, pgc_program_map_t *_program_map, int _nr, int_offset */ void k9Ifo2::updatePGC_PROGRAM_MAP(uchar *, pgc_program_map_t *_program_map, int _nr, int _offset) { int size = _nr * sizeof(pgc_program_map_t); memcpy(m_buffer+_offset, _program_map, size); // pad to word boundary size += size % 2; m_position += size; } /*! \fn k9Ifo2::updatePGC_CELL_PLAYBACK_TBL(uchar *_buffer, cell_playback_t *_cell_playback,int _nr, int _offset) */ void k9Ifo2::updatePGC_CELL_PLAYBACK_TBL(uchar *, cell_playback_t *_cell_playback,int _nr, int _offset) { cell_playback_t *cell_playback; int size = _nr * sizeof(cell_playback_t); //cell_playback=(cell_playback_t*) malloc(size); cell_playback=new cell_playback_t[_nr]; memcpy(cell_playback,_cell_playback,size); for( int i = 0; i < _nr; i++) { B2N_32(cell_playback[i].first_sector); B2N_32(cell_playback[i].first_ilvu_end_sector); B2N_32(cell_playback[i].last_vobu_start_sector); B2N_32(cell_playback[i].last_sector); } memcpy(m_buffer + _offset,cell_playback,size); m_position+=size; //free(cell_playback); delete[] cell_playback; } /*! \fn k9Ifo2::updatePGC_CELL_POSITION_TBL(uchar *_buffer,cell_position_t *_cell_position,int _nr, int _offset) */ void k9Ifo2::updatePGC_CELL_POSITION_TBL(uchar *,cell_position_t *_cell_position,int _nr, int _offset) { cell_position_t * cell_position; int size = _nr * sizeof(cell_position_t); //cell_position=(cell_position_t*)malloc(size); cell_position=new cell_position_t[_nr]; memcpy(cell_position,_cell_position,size); for( int i = 0; i < _nr; i++) { B2N_16(cell_position[i].vob_id_nr); } memcpy(m_buffer + _offset,cell_position,size); m_position+=size; //free(cell_position); delete[] cell_position; } int k9Ifo2::round(int _value) { return ((_value-1)|(DVD_BLOCK_LEN-1))+1; // DVD_BLOCK_LEN-1 = 0x7FF } /*! \fn k9Ifo2::updateTT_SRPT(uchar *_buffer) */ void k9Ifo2::updateTT_SRPT(uchar *) { if(_ifo->vmgi_mat->tt_srpt != 0) { tt_srpt_t * tt_srpt; //tt_srpt=(tt_srpt_t*) malloc(sizeof(tt_srpt_t)); tt_srpt=new tt_srpt_t; // int offset= _ifo->vmgi_mat->tt_srpt * DVD_BLOCK_LEN; m_position=round(m_position); int offset=m_position; _ifo->vmgi_mat->tt_srpt=m_position/DVD_BLOCK_LEN; memcpy (tt_srpt,_ifo->tt_srpt,sizeof(tt_srpt_t)); int info_length = tt_srpt->last_byte + 1 - TT_SRPT_SIZE; title_info_t * title_info; //title_info =(title_info_t*) malloc(info_length); title_info = new title_info_t[info_length / sizeof(title_info_t)]; memcpy(title_info, tt_srpt->title,info_length); for(int i = 0; i < tt_srpt->nr_of_srpts; i++) { B2N_16(title_info[i].nr_of_ptts); B2N_16(title_info[i].parental_id); B2N_32(title_info[i].title_set_sector); } memcpy(m_buffer+offset+TT_SRPT_SIZE,title_info,info_length); delete[] title_info; m_position +=info_length; B2N_16(tt_srpt->nr_of_srpts); B2N_32(tt_srpt->last_byte); memcpy(m_buffer+offset,tt_srpt,TT_SRPT_SIZE); delete tt_srpt; } } void k9Ifo2::updatePGCI_UT(uchar *_buffer) { int sector,sector2; if(_ifo->vmgi_mat) { if(_ifo->vmgi_mat->vmgm_pgci_ut == 0) return; m_position=round(m_position); _ifo->vmgi_mat->vmgm_pgci_ut=m_position/DVD_BLOCK_LEN; } else if(_ifo->vtsi_mat) { if(_ifo->vtsi_mat->vtsm_pgci_ut == 0) return; m_position=round(m_position); _ifo->vtsi_mat->vtsm_pgci_ut=m_position/DVD_BLOCK_LEN; } else { return; } sector2=sector=m_position; if (_ifo->pgci_ut !=NULL) { pgci_ut_t * pgci_ut; //pgci_ut = (pgci_ut_t*) malloc( sizeof(pgci_ut_t)); pgci_ut = new pgci_ut_t; memcpy (pgci_ut,_ifo->pgci_ut,sizeof(pgci_ut_t)); m_position+=PGCI_UT_SIZE; sector2=m_position; pgci_lu_t pgci_lu[_ifo->pgci_ut->nr_of_lus]; m_position+=_ifo->pgci_ut->nr_of_lus*PGCI_LU_SIZE; memcpy(pgci_lu,_ifo->pgci_ut->lu,_ifo->pgci_ut->nr_of_lus*sizeof(pgci_lu_t)); for(int i = 0; i < _ifo->pgci_ut->nr_of_lus; i++) { B2N_16(pgci_lu[i].lang_code); pgci_lu[i].lang_start_byte=m_position - sector; B2N_32(pgci_lu[i].lang_start_byte); updatePGCIT_internal(_buffer,_ifo->pgci_ut->lu[i].pgcit,m_position); } for (int i=0;i <_ifo->pgci_ut->nr_of_lus;i++) memcpy(m_buffer+sector2+i*PGCI_LU_SIZE ,&(pgci_lu[i]),PGCI_LU_SIZE); B2N_16(pgci_ut->nr_of_lus); pgci_ut->last_byte=m_position-sector-1; B2N_32(pgci_ut->last_byte); memcpy(m_buffer+sector,pgci_ut,PGCI_UT_SIZE); delete pgci_ut; } } void k9Ifo2::updatePGCIT(uchar *_buffer) { if(!_ifo->vtsi_mat) return ; if(_ifo->vtsi_mat->vts_pgcit == 0) /* mandatory */ return ; m_position=round(m_position); _ifo->vtsi_mat->vts_pgcit=m_position / DVD_BLOCK_LEN; updatePGCIT_internal(_buffer,_ifo->vts_pgcit,_ifo->vtsi_mat->vts_pgcit * DVD_BLOCK_LEN); } void k9Ifo2::updatePGCIT_internal(uchar *_buffer, pgcit_t *_pgcit, int _offset) { pgcit_t * pgcit; //pgcit=(pgcit_t*)malloc(sizeof(pgcit_t)); pgcit=new pgcit_t; memcpy(pgcit,_pgcit,sizeof(pgcit_t)); int offset=m_position+PGCIT_SIZE; m_position+=PGCIT_SIZE; pgci_srp_t pgci_srp[_pgcit->nr_of_pgci_srp]; memcpy(pgci_srp,_pgcit->pgci_srp,sizeof(pgci_srp_t)*_pgcit->nr_of_pgci_srp); m_position+=_pgcit->nr_of_pgci_srp*PGCI_SRP_SIZE; for(int i = 0; i < _pgcit->nr_of_pgci_srp; i++) { B2N_16(pgci_srp[i].ptl_id_mask); pgci_srp[i].pgc_start_byte=m_position-_offset; B2N_32(pgci_srp[i].pgc_start_byte); //JMP:faux updatePGC(_buffer,_pgcit->pgci_srp[i].pgc,m_position); } for(int i = 0; i < _pgcit->nr_of_pgci_srp; i++) memcpy(m_buffer+offset+i*PGCI_SRP_SIZE,&(pgci_srp[i]),PGCI_SRP_SIZE); B2N_16(pgcit->nr_of_pgci_srp); pgcit->last_byte=m_position-_offset-1; B2N_32(pgcit->last_byte); memcpy(m_buffer+_offset ,pgcit,PGCIT_SIZE); delete pgcit; } void k9Ifo2::updatePTL_MAIT(uchar *) { if(!_ifo->vmgi_mat) return; _ifo->vmgi_mat->ptl_mait = 0; return; } void k9Ifo2::updateVTS_ATRT(uchar *_buffer) { if(_ifo->vmgi_mat->vts_atrt == 0) return; uint32_t orig=_ifo->vmgi_mat->vts_atrt * DVD_BLOCK_LEN; m_position=round(m_position); _ifo->vmgi_mat->vts_atrt=m_position/DVD_BLOCK_LEN; memcpy(m_buffer+m_position,_buffer+orig,_ifo->vts_atrt->last_byte+1); m_position+=_ifo->vts_atrt->last_byte+1; /* int sector = _ifo->vmgi_mat->vts_atrt * DVD_BLOCK_LEN; vts_atrt_t *vts_atrt; vts_atrt = (vts_atrt_t*)malloc(sizeof(vts_atrt_t)); memcpy(vts_atrt,_ifo->vts_atrt,VTS_ATRT_SIZE); B2N_16(vts_atrt->nr_of_vtss); B2N_32(vts_atrt->last_byte); memcpy(m_buffer+sector,vts_atrt,VTS_ATRT_SIZE); free(vts_atrt); m_position+=VTS_ATRT_SIZE; sector += VTS_ATRT_SIZE; memcpy(m_buffer+sector,_buffer +orig+VTS_ATRT_SIZE ,VTS_ATTRIBUTES_SIZE*_ifo->vts_atrt->nr_of_vtss); m_position+=VTS_ATTRIBUTES_SIZE*_ifo->vts_atrt->nr_of_vtss; */ } void k9Ifo2::updateTXTDT_MGI(uchar * _buffer) { if(_ifo->vmgi_mat->txtdt_mgi == 0) return; struct { char disc_name[15]; char nr_of_language_units; uint32_t last_byte; txtdt_lu_t *lu; } ATTRIBUTE_PACKED txtdtmgi; m_position=round(m_position); int orig=_ifo->vmgi_mat->txtdt_mgi*DVD_BLOCK_LEN; int offset=m_position; _ifo->vmgi_mat->txtdt_mgi =m_position/ DVD_BLOCK_LEN; memcpy(&txtdtmgi,_buffer+orig,sizeof(txtdtmgi)); B2N_32(txtdtmgi.last_byte); memcpy(m_buffer+offset,_buffer+orig ,txtdtmgi.last_byte+1); m_position+=txtdtmgi.last_byte+1; } void k9Ifo2::updateC_ADT(uchar * _buffer, bool _isMenu) { if(_ifo->vmgi_mat) { if(_ifo->vmgi_mat->vmgm_c_adt != 0) { m_position =round(m_position); // _ifo->vmgi_mat->vmgm_c_adt=m_position/ DVD_BLOCK_LEN; updateC_ADT_Internal(_buffer,_ifo->menu_c_adt,m_position); } } else if(_ifo->vtsi_mat) { if(_ifo->vtsi_mat->vtsm_c_adt != 0 && _isMenu) { m_position=round(m_position); //sector = _ifo->vtsi_mat->vtsm_c_adt=m_position / DVD_BLOCK_LEN; updateC_ADT_Internal(_buffer,_ifo->menu_c_adt,m_position); } if (_ifo->vtsi_mat->vts_c_adt !=0 && !_isMenu) { m_position=round(m_position); //sector = _ifo->vtsi_mat->vts_c_adt=m_position / DVD_BLOCK_LEN; updateC_ADT_Internal(_buffer,_ifo->vts_c_adt,m_position); } } else { return ; } } void k9Ifo2::updateC_ADT_Internal(uchar *,c_adt_t *_c_adt,int _sector) { c_adt_t * c_adt; //c_adt =(c_adt_t*) malloc (sizeof(c_adt_t)); c_adt =new c_adt_t; memcpy(c_adt,_c_adt,sizeof(c_adt_t)); int offset =_sector + C_ADT_SIZE; m_position+=C_ADT_SIZE; int info_length = _c_adt->last_byte + 1 - C_ADT_SIZE; cell_adr_t *cell_adr,*ptr; //cell_adr=(cell_adr_t*) malloc(sizeof(cell_adr_t)); cell_adr=new cell_adr_t; ptr= _c_adt->cell_adr_table; for(uint i = 0; i < info_length/sizeof(cell_adr_t); i++) { memcpy(cell_adr,&(ptr[i]),sizeof(cell_adr_t)); B2N_16(cell_adr->vob_id); B2N_32(cell_adr->start_sector); B2N_32(cell_adr->last_sector); memcpy(m_buffer+offset,cell_adr,sizeof(cell_adr_t)); offset+=sizeof(cell_adr_t); //ptr+=sizeof(cell_adr_t); } m_position+=info_length; delete cell_adr; B2N_16(c_adt->nr_of_vobs); c_adt->last_byte=m_position-_sector-1; B2N_32(c_adt->last_byte); memcpy(m_buffer+_sector,c_adt,C_ADT_SIZE); delete c_adt; } void k9Ifo2::updateVOBU_ADMAP(uchar * _buffer, bool _isMenu) { int sector; if(_ifo->vmgi_mat) { if(_ifo->vmgi_mat->vmgm_vobu_admap == 0) return ; sector = m_position=round(m_position);//_ifo->vmgi_mat->vmgm_vobu_admap * DVD_BLOCK_LEN; _ifo->vmgi_mat->vmgm_vobu_admap=m_position/DVD_BLOCK_LEN; updateVOBU_ADMAP_Internal(_buffer,_ifo->menu_vobu_admap,sector); } else if(_ifo->vtsi_mat) { if(_ifo->vtsi_mat->vtsm_vobu_admap != 0 && _isMenu) { sector = m_position=round(m_position);//sector = _ifo->vtsi_mat->vtsm_vobu_admap * DVD_BLOCK_LEN; _ifo->vtsi_mat->vtsm_vobu_admap=m_position/DVD_BLOCK_LEN; updateVOBU_ADMAP_Internal(_buffer,_ifo->menu_vobu_admap,sector); } if (_ifo->vtsi_mat->vts_vobu_admap !=0 && !_isMenu) { sector = m_position=round(m_position);//sector = _ifo->vtsi_mat->vts_vobu_admap * DVD_BLOCK_LEN; _ifo->vtsi_mat->vts_vobu_admap=m_position/DVD_BLOCK_LEN; updateVOBU_ADMAP_Internal(_buffer,_ifo->vts_vobu_admap,sector); } } else { return ; } } void k9Ifo2::updateVOBU_ADMAP_Internal(uchar *,vobu_admap_t *_vobu_admap,int _sector) { vobu_admap_t *vobu_admap; //vobu_admap=(vobu_admap_t*)malloc(sizeof(vobu_admap_t)); vobu_admap=new vobu_admap_t; memcpy(vobu_admap,_vobu_admap,sizeof(vobu_admap_t)); int offset = _sector + VOBU_ADMAP_SIZE; m_position+=VOBU_ADMAP_SIZE; int info_length = _vobu_admap->last_byte + 1 - VOBU_ADMAP_SIZE; uint32_t *vobu_start_sectors; //vobu_start_sectors=(uint32_t*)malloc(info_length); vobu_start_sectors=new uint32_t[info_length/sizeof(uint32_t)]; memcpy(vobu_start_sectors,_vobu_admap->vobu_start_sectors,info_length); for(uint i = 0; i < info_length/sizeof(uint32_t); i++) B2N_32(vobu_start_sectors[i]); memcpy(m_buffer+offset,vobu_start_sectors,info_length); m_position+=info_length; delete[] vobu_start_sectors; vobu_admap->last_byte=m_position-_sector-1; B2N_32(vobu_admap->last_byte); memcpy(m_buffer+_sector,vobu_admap,VOBU_ADMAP_SIZE); delete vobu_admap; } void k9Ifo2::updateVTS(uchar *) { vtsi_mat_t *vtsi_mat; //vtsi_mat = (vtsi_mat_t *)malloc(sizeof(vtsi_mat_t)); vtsi_mat = new vtsi_mat_t; memcpy(vtsi_mat,_ifo->vtsi_mat,sizeof(vtsi_mat_t)); uint32_t lastSector=vtsi_mat->vtsi_last_sector; //uint32_t lastByte=vtsi_mat->vtsi_last_byte; //JMP : à vérifier if (m_position >0) { lastSector=(round(m_position)-DVD_BLOCK_LEN) /DVD_BLOCK_LEN; //lastByte=vtsi_mat->vtsi_last_sector*DVD_BLOCK_LEN +DVD_BLOCK_LEN-1; vtsi_mat->vts_last_sector+=2*(lastSector-vtsi_mat->vtsi_last_sector); if (m_VTSVobs !=0) vtsi_mat->vtstt_vobs+=m_VTSVobs; else vtsi_mat->vtstt_vobs+=lastSector-vtsi_mat->vtsi_last_sector; } m_size=lastSector+1; vtsi_mat->vtsi_last_sector=lastSector; //vtsi_mat->vtsi_last_byte=lastByte; if (vtsi_mat->vtsm_vobs !=0) vtsi_mat->vtsm_vobs= vtsi_mat->vtsi_last_sector +1 ; B2N_32(vtsi_mat->vts_last_sector); B2N_32(vtsi_mat->vtsi_last_sector); B2N_32(vtsi_mat->vts_category); B2N_32(vtsi_mat->vtsi_last_byte); B2N_32(vtsi_mat->vtsm_vobs); B2N_32(vtsi_mat->vtstt_vobs); B2N_32(vtsi_mat->vts_ptt_srpt); B2N_32(vtsi_mat->vts_pgcit); B2N_32(vtsi_mat->vtsm_pgci_ut); B2N_32(vtsi_mat->vts_tmapt); B2N_32(vtsi_mat->vtsm_c_adt); B2N_32(vtsi_mat->vtsm_vobu_admap); B2N_32(vtsi_mat->vts_c_adt); B2N_32(vtsi_mat->vts_vobu_admap); B2N_16(vtsi_mat->vtsm_audio_attr.lang_code); B2N_16(vtsi_mat->vtsm_subp_attr.lang_code); for(int i = 0; i < 8; i++) B2N_16(vtsi_mat->vts_audio_attr[i].lang_code); for(int i = 0; i < 32; i++) B2N_16(vtsi_mat->vts_subp_attr[i].lang_code); memcpy(m_buffer,vtsi_mat,sizeof(vtsi_mat_t)); delete vtsi_mat; } void k9Ifo2::updateVTS_PTT_SRPT(uchar *_buffer) { if(!_ifo->vtsi_mat) return ; if(_ifo->vtsi_mat->vts_ptt_srpt == 0) /* mandatory */ return ; vts_ptt_srpt_t * vts_ptt_srpt; //vts_ptt_srpt = (vts_ptt_srpt_t *)malloc(sizeof(vts_ptt_srpt_t)); vts_ptt_srpt = new vts_ptt_srpt_t; memcpy(vts_ptt_srpt,_ifo->vts_ptt_srpt,sizeof(vts_ptt_srpt_t)); int orig=_ifo->vtsi_mat->vts_ptt_srpt * DVD_BLOCK_LEN; int offset = m_position=round(m_position);//_ifo->vtsi_mat->vts_ptt_srpt * DVD_BLOCK_LEN; _ifo->vtsi_mat->vts_ptt_srpt=m_position/DVD_BLOCK_LEN; B2N_16(vts_ptt_srpt->nr_of_srpts); B2N_32(vts_ptt_srpt->last_byte); memcpy(m_buffer+offset,vts_ptt_srpt,VTS_PTT_SRPT_SIZE); delete vts_ptt_srpt; m_position+=VTS_PTT_SRPT_SIZE; int info_length = _ifo->vts_ptt_srpt->last_byte + 1 - VTS_PTT_SRPT_SIZE; memcpy(m_buffer+m_position,_buffer+orig+VTS_PTT_SRPT_SIZE, info_length); m_position+=info_length; } /*! \fn k9Ifo2::checkBuffer() */ void k9Ifo2::updateVTS_TMAPT(uchar *) { if(!_ifo->vtsi_mat) return ; if(_ifo->vtsi_mat->vts_tmapt == 0) { /* optional(?) */ return ; } vts_tmapt_t *vts_tmapt1,*vts_tmapt; vts_tmapt=_ifo->vts_tmapt; int info_length = vts_tmapt->nr_of_tmaps * 4; uint32_t offsets[vts_tmapt->nr_of_tmaps]; //vts_tmapt1 = (vts_tmapt_t *)malloc(VTS_TMAPT_SIZE); vts_tmapt1 = new vts_tmapt_t; memcpy(vts_tmapt1,_ifo->vts_tmapt,VTS_TMAPT_SIZE); uint32_t offset = m_position=round(m_position); _ifo->vtsi_mat->vts_tmapt =m_position / DVD_BLOCK_LEN; int offset0=offset; offset+=VTS_TMAPT_SIZE; m_position +=VTS_TMAPT_SIZE; offset += info_length; m_position+=info_length; info_length=0; vts_tmap_t *tmap=vts_tmapt->tmap; //loop on tmaps to compute total size for (int i=0;i nr_of_tmaps;i++) { int tmapSize=VTS_TMAP_SIZE+tmap[i].nr_of_entries*sizeof(map_ent_t); info_length+=tmapSize+4; } //tmap = (vts_tmap_t *)malloc(sizeof(vts_tmap_t)* vts_tmapt->nr_of_tmaps); tmap = new vts_tmap_t[vts_tmapt->nr_of_tmaps]; memcpy(tmap,vts_tmapt->tmap,sizeof(vts_tmap_t)* vts_tmapt->nr_of_tmaps); vts_tmapt1->last_byte=VTS_TMAPT_SIZE+info_length-1; for(int i = 0; i < vts_tmapt->nr_of_tmaps; i++) { int tmapSize=VTS_TMAP_SIZE+tmap[i].nr_of_entries*sizeof(map_ent_t); int nr_map_ent=tmap[i].nr_of_entries; B2N_16(tmap[i].nr_of_entries); offsets[i]=m_position-offset0; B2N_32(offsets[i]); memcpy(m_buffer+m_position,&(tmap[i]),VTS_TMAP_SIZE); m_position+=VTS_TMAP_SIZE; offset+=VTS_TMAP_SIZE; if(nr_map_ent == 0) { // Early out if zero entries continue; } int info_length2 = tmapSize-VTS_TMAP_SIZE; //map_ent_t *map_ent = (map_ent_t *)malloc(info_length2); map_ent_t *map_ent = new map_ent_t[info_length2/sizeof(map_ent_t)]; memcpy(map_ent,tmap[i].map_ent,info_length2); for(int j = 0; j < nr_map_ent; j++) { B2N_32(map_ent[j]); memcpy(m_buffer+m_position,&(map_ent[j]),sizeof(map_ent_t)); offset+=sizeof(map_ent_t); m_position+=sizeof(map_ent_t); } delete map_ent; } delete[] tmap; B2N_16(vts_tmapt1->nr_of_tmaps); B2N_32(vts_tmapt1->last_byte); memcpy(m_buffer+offset0,vts_tmapt1,VTS_TMAPT_SIZE); memcpy(m_buffer+offset0+VTS_TMAPT_SIZE,offsets,vts_tmapt->nr_of_tmaps*4); delete vts_tmapt1; } void k9Ifo2::checkBuffer(QString lib,uchar* _buffer) { /* for (int j=0;jpci_gi.nv_pck_lbn); B2N_16(pci->pci_gi.vobu_cat); B2N_32(pci->pci_gi.vobu_s_ptm); B2N_32(pci->pci_gi.vobu_e_ptm); B2N_32(pci->pci_gi.vobu_se_e_ptm); /* pci nsml_agli */ for(i = 0; i < 9; i++) B2N_32(pci->nsml_agli.nsml_agl_dsta[i]); /* pci hli hli_gi */ B2N_16(pci->hli.hl_gi.hli_ss); B2N_32(pci->hli.hl_gi.hli_s_ptm); B2N_32(pci->hli.hl_gi.hli_e_ptm); B2N_32(pci->hli.hl_gi.btn_se_e_ptm); /* pci hli btn_colit */ for(i = 0; i < 3; i++) for(j = 0; j < 2; j++) B2N_32(pci->hli.btn_colit.btn_coli[i][j]); /* NOTE: I've had to change the structure from the disk layout to get * the packing to work with Sun's Forte C compiler. */ /* pci hli btni */ for(i = 0; i < 36; i++) { char tmp[sizeof(pci->hli.btnit[i])], swap; memcpy(tmp, &(pci->hli.btnit[i]), sizeof(pci->hli.btnit[i])); /* Byte 4 to 7 are 'rotated' was: ABCD EFGH IJ is: ABCG DEFH IJ */ swap = tmp[6]; tmp[6] = tmp[5]; tmp[5] = tmp[4]; tmp[4] = tmp[3]; tmp[3] = swap; /* Then there are the two B2N_24(..) calls */ #ifndef WORDS_BIGENDIAN swap = tmp[0]; tmp[0] = tmp[2]; tmp[2] = swap; swap = tmp[4]; tmp[4] = tmp[6]; tmp[6] = swap; #endif memcpy(&(pci->hli.btnit[i]), tmp, sizeof(pci->hli.btnit[i])); } } k9copy/src/core/k9dvd.h0000755000175000017550000001312112412271774015464 0ustar emulatoremulator/************************************************************************** * Copyright (C) 2005 by Jean-Michel Petit * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef K9DVD_H #define K9DVD_H #include "k9common.h" #include #include "k9dvdread.h" #include #include #include struct streamSize { unsigned char id; float size_mb; float percent; }; struct stream_counter { unsigned char id; int count; float size_mb; float percent; }; class k9DVDProgress; class k9DVDChapter; class k9DVDTitle; class k9DVDTitleset; /** get the DVD structure with titles lengths and streams lengths. *@author */ struct lng { char code[3]; QString name;}; class k9DVD : public QObject { Q_OBJECT private: QObjectList m_titles; QList m_titlesets; QString m_title; int m_titleCount; k9DVDTitle *m_longestTitle; QStringList m_lvideoFormat; QStringList m_laspectRatio; QStringList m_lquantization; QStringList m_lmpegVersion; QStringList m_lvideoHeight; QStringList m_lvideoWidth; QStringList m_lpermittedDf; QStringList m_laudioFormat; QStringList m_lsampleFreq; QStringList m_laudioType; QStringList m_lsubpType; QStringList m_langCode; QStringList m_langName; double m_frames_per_s[4]; uint m_menuSize; k9DVDProgress *m_progressDlg; QString m_Device; bool m_error; QString m_errMsg; bool m_opened; QString m_format; k9DVDTitle* m_start; int m_titlesetCount; lng *m_arrLng; public: k9DVD(QObject *parent=0) ; ~k9DVD(); static void LangList(lng *arrLng); /** * Opens and estimates the size of each stream * @param device input device * @return return code (0=ok) */ virtual int scandvd (const QString & device,bool _quickScan); /** * gets the title of the DVD * @return DVD title */ virtual const QString& getDVDTitle(); /** * set the title of the DVD * @param _newVal the new DVD title */ virtual void setDVDTitle(const QString &_newVal); /** * * @return returns the number of titles */ virtual const int& gettitleCount(); /** * * @return returns the number of titlesets */ virtual const int& gettitlesetCount(); /** * returns a title of the DVD * @param num the title number * @return the title */ virtual k9DVDTitle* gettitle(int num); /** * returns a title (which is in tt_srpt) * @param num the title number * @return the title */ virtual k9DVDTitle* gettitleByNum(int VTS,int num); virtual k9DVDTitle *getlongestTitle(); virtual float getfactor(bool withMenus,bool _streams,bool _useDvdAuthor); virtual const QString& getDevice(); virtual const bool& geterror(); virtual const QString& geterrMsg(); virtual const bool& getopened(); virtual uint64_t getsizeSelected(bool _streams); virtual QString &getFormat(); virtual k9DVDTitle* getstart(); virtual void setstart(k9DVDTitle* title); virtual int getnewTitleNum(k9DVDTitle *title); virtual int getmenuSize(); virtual void close(); virtual k9DVDTitleset *gettitleset(int num); virtual k9DVDRead * getdvd() {return &m_dvd;} static QString lang_name(lng* arrLng,const QString & code,const QString & name); int dvdtime2msec(dvd_time_t *dt); private: // Private methods k9DVDRead m_dvd; k9DVDTitle* addTitle(k9DVDTitleset *titleset,int id,int num,uint _VTS,int _pgc,uint32_t _startSector, bool _indexed); float calcVobuSize(ifo_handle_t *_ifo,k9DVDChapter *_chapter); long stream_vob( int title, unsigned long startblock, unsigned long lastblock, struct stream_counter *sc); int identify_stream( unsigned char *buffer ) ; int get_title_name(const char* dvd_device, char* title); void calcStreamSize(k9DVDTitle & title); void setError(const QString &err); int getVampsID(int type); int calcNumTitle(ifo_handle_t *ifo,int _vts,int _ttn); void deleteTitles(); void deleteTitlesets(); public slots: // Public slots void slotVobProgress(unsigned int position,unsigned int total); void slotTitleProgress(unsigned int position,unsigned int total); void slotTitleText(QString &text); void slotTotalText(QString &text); signals: // Signals void sigVobProgress(unsigned int position,unsigned int total); void sigTitleProgress(unsigned int position,unsigned int total); void sigTitleText(QString &text); void sigTotalText(QString &text); }; #endif k9copy/src/core/k9ifo2.h0000644000175000017550000000700512412344325015540 0ustar emulatoremulator/*************************************************************************** * Copyright (C) 2005 by Jean-Michel Petit * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef K9IFO2_H #define K9IFO2_H #include "k9dvdread.h" #include /** @author Jean-Michel Petit */ class k9Ifo2 { public: k9Ifo2(k9DVDRead *_dvdread); ~k9Ifo2(); void setDevice(QString &_device); void setOutput(QString &_output); ifo_handle_t * openIFO(int _num); void closeIFO(); void saveIFO(); ifo_handle_t * getIFO(); static void navRead_PCI(pci_t *pci, uchar *buffer); void setVTSVobs(uint32_t _sector); uint32_t getSize(); int test; protected: QString device; QString output; ifo_handle_t *_ifo; int numIfo; private: QFile* outputFile; long cellSize; uchar * bufCopy,*m_buffer; int bufCopySize; k9DVDRead *m_dvd; uint m_position; uint32_t m_VTSVobs,m_size; private: int round(int); void updateVMG(uchar * _buffer); void updateFP_PGC(uchar * _buffer); void updatePGC_COMMAND_TBL(uchar *_buffer,pgc_command_tbl_t *_cmd_tbl,int offset); void updatePGC_PROGRAM_MAP(uchar *_buffer,pgc_program_map_t *_program_map, int _nr,int _offset); void updatePGC_CELL_PLAYBACK_TBL(uchar *_buffer, cell_playback_t *_cell_playback,int _nr, int _offset); void updatePGC_CELL_POSITION_TBL(uchar *_buffer,cell_position_t *_cell_position,int _nr, int _offset); void updatePGC(uchar *_buffer,pgc_t *_pgc,int _offset); void updateTT_SRPT(uchar *_buffer); void updatePGCI_UT(uchar *_buffer); void updatePTL_MAIT(uchar *_buffer); void updateVTS_ATRT(uchar *_buffer); void updateTXTDT_MGI(uchar * _buffer); void updateC_ADT(uchar * _buffer, bool _isMenu); void updateVOBU_ADMAP(uchar * _buffer, bool _isMenu); void updatePGCIT(uchar *_buffer); void updatePGCIT_internal(uchar *_buffer, pgcit_t *_pgcit, int offset); void updateVTS(uchar *_buffer); void updateVTS_PTT_SRPT(uchar *_buffer); void updateVTS_TMAPT(uchar *_buffer) ; void updateC_ADT_Internal(uchar *_buffer,c_adt_t *_c_adt,int _sector); void updateVOBU_ADMAP_Internal(uchar *_buffer,vobu_admap_t *_vobu_admap,int _sector); void checkBuffer(QString lib,uchar *_buffer); }; #endif k9copy/src/core/k9burnprogress.cpp0000644000175000017550000000672112412271774020002 0ustar emulatoremulator// // C++ Implementation: // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9burnprogress.h" #include #include #include #include #include #include #include #include #include #if QT_VERSION >= 0x050000 #include #include #endif k9BurnProgress::k9BurnProgress(QWidget* parent) : QDialog(parent) { Ui_Progress.setupUi(this); setModal(true); m_process=new k9Process(this,0); m_logView=new k9LogView(this); Ui_Progress.image->setPalette(this->palette()); QGridLayout *l=new QGridLayout(Ui_Progress.image); l->setMargin(0); l->addWidget(m_logView,0,0); #if QT_VERSION >= 0x050000 KGuiItem::assign(Ui_Progress.bCancel, KStandardGuiItem::stop() ); #else Ui_Progress.bCancel->setGuiItem(KStandardGuiItem::Stop); #endif #if QT_VERSION >= 0x050000 // Qt5 code QString aright=QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kmyapp/aright.png"); QString adown=QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kmyapp/adown.png"); #else // Qt4 code QString adown=KGlobal::dirs()->findResource( "data", QString("k9copy/adown.png")); QString aright=KGlobal::dirs()->findResource( "data", QString("k9copy/aright.png")); #endif Ui_Progress.gbOutput->setStyleSheet("*::indicator:unchecked {image:url("+aright+"); } *::indicator:checked {image:url("+adown+"); } "); } k9BurnProgress::~k9BurnProgress() { delete m_process; } void k9BurnProgress::setElapsed(const QString _text) { Ui_Progress.lblElapsed->setText(_text); } void k9BurnProgress::setTitle(const QString _text) { Ui_Progress.lblTitle->setText(_text); } void k9BurnProgress::setLabelText(const QString _text) { Ui_Progress.LabelText->setText(_text); } void k9BurnProgress::setProgress(long _position,long _total) { Ui_Progress.ProgressBar->setRange(0,_total); Ui_Progress.ProgressBar->setValue(_position); } int k9BurnProgress::execute() { if (! m_process->isRunning()) { qDebug() << m_process->debug(); if (!m_process->start()) return -1; } // m_timer.start(200,FALSE); show(); m_canceled=false; //the sync method allows to wait for the process end while receiving stdout. m_process->sync(); // m_timer.stop(); close(); if (m_canceled) return 0; else if (m_process->normalExit()) return 1; else return -1; } void k9BurnProgress::bCancelClick() { m_process->kill(); m_canceled=true; } k9Process* k9BurnProgress::getProcess() const { return m_process; } /*$SPECIALIZATION$*/ void k9BurnProgress::setMovie(QString _fileName) { Q_UNUSED(_fileName) } bool k9BurnProgress::getCanceled() const { return m_canceled; } void k9BurnProgress::gbOutputToggled(bool state) { if (!state) { m_outputSize=Ui_Progress.image->height(); this->resize(this->width(),this->height()-m_outputSize); m_outputSize-=Ui_Progress.image->height(); this->setMaximumHeight(this->height()); } else { this->setMaximumHeight(32768); this->resize(this->width(),this->height()+m_outputSize); } Ui_Progress.image->setVisible(state); } void k9BurnProgress::closeEvent ( QCloseEvent * ) { } k9copy/src/core/k9progress.cpp0000644000175000017550000000776112412271774017120 0ustar emulatoremulator// // C++ Implementation: // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9progress.h" #include #include #include #include #include #include #include #include #if QT_VERSION >= 0x050000 #include #include #endif k9Progress::k9Progress(QWidget* parent) : QDialog(parent) { Ui_Progress.setupUi(this); setModal(true); m_process=new k9Process(this,0); m_wimage=new k9DrawImage(Ui_Progress.image); QGridLayout *l=new QGridLayout(Ui_Progress.image); l->addWidget(m_wimage,0,0); #if QT_VERSION >= 0x050000 // Qt5 code KGuiItem::assign(Ui_Progress.bCancel, KStandardGuiItem::stop() ); QString aright=QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kmyapp/aright.png"); QString adown=QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kmyapp/adown.png"); #else // Qt4 code Ui_Progress.bCancel->setGuiItem(KStandardGuiItem::Stop); QString adown=KGlobal::dirs()->findResource( "data", QString("k9copy/adown.png")); QString aright=KGlobal::dirs()->findResource( "data", QString("k9copy/aright.png")); #endif Ui_Progress.gbOutput->setStyleSheet("*::indicator:unchecked {image:url("+aright+"); } *::indicator:checked {image:url("+adown+"); } "); m_movie=NULL; } void k9Progress::showEvent ( QShowEvent * ) { k9Config config; Ui_Progress.gbOutput->setChecked(config.getPrefShowOutput()); } k9Progress::~k9Progress() { delete m_process; } void k9Progress::setElapsed(const QString _text) { Ui_Progress.lblElapsed->setText(_text); } void k9Progress::setTitle(const QString _text) { Ui_Progress.lblTitle->setText(_text); } void k9Progress::setLabelText(const QString _text) { Ui_Progress.LabelText->setText(_text); } void k9Progress::setProgress(long _position,long _total) { Ui_Progress.ProgressBar->setRange(0,_total); Ui_Progress.ProgressBar->setValue(_position); } int k9Progress::execute() { if (! m_process->isRunning()) { qDebug() << m_process->debug(); if (!m_process->start()) return -1; } // m_timer.start(200,FALSE); show(); m_canceled=false; //the sync method allows to wait for the process end while receiving stdout. m_process->sync(); // m_timer.stop(); close(); if (m_canceled) return 0; else if (m_process->normalExit()) return 1; else return -1; } void k9Progress::bCancelClick() { m_process->kill(); m_canceled=true; } k9Process* k9Progress::getProcess() const { return m_process; } /*$SPECIALIZATION$*/ void k9Progress::setImage(QString _fileName) { m_wimage->setImage(_fileName); } void k9Progress::setImage(const QImage &_image) { m_wimage->setImage(_image); } void k9Progress::setMovie(QString _fileName) { m_wimage->hide(); Ui_Progress.image->setPalette(this->palette()); m_movie=new QMovie(_fileName); m_movie->start(); Ui_Progress.image->setMovie(m_movie); } bool k9Progress::getCanceled() const { return m_canceled; } void k9Progress::gbOutputToggled(bool state) { k9Config config; if (!state) { m_outputSize=Ui_Progress.image->height(); if (m_movie) Ui_Progress.image->clear(); Ui_Progress.image->setMinimumSize(0,0); this->resize(this->width(),this->height()-m_outputSize); m_outputSize-=Ui_Progress.image->height(); this->setMaximumHeight(this->height()); } else { this->setMaximumHeight(32768); this->resize(this->width(),this->height()+m_outputSize); if (m_movie) Ui_Progress.image->setMovie(m_movie); } config.setPrefShowOutput(state); config.save(); Ui_Progress.image->setVisible(state); } void k9Progress::closeEvent ( QCloseEvent * ) { } k9copy/src/core/k9config.h0000644000175000017550000003214712412271774016162 0ustar emulatoremulator// // C++ Interface: k9config // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9CONFIG_H #define K9CONFIG_H #include #include #include #if QT_VERSION >= 0x050000 #else // Qt4 Code #include #endif #include /** @author Jean-Michel PETIT */ class k9Config { private: KConfig *m_config; int m_InputDev; int m_OutputDev; bool m_keepMenus; QList m_prefColumns; QString m_prefOutput; QString m_prefOutputIso; QString m_prefOutputMpeg4; QString m_prefOutputMpeg2; QString m_prefOutputAudio; QString m_prefMencoderPath; QString m_prefMplayerPath; QString m_prefk3bPath; QString m_prefDvdauthorPath; QString m_prefFFmpegPath; QString m_prefWodimPath; QString m_prefGenisoimagePath; QString m_prefVersion; bool m_useDvdAuthor; bool m_quickScan; int m_prefSize; bool m_prefK3b; bool m_prefMenu; bool m_prefAutoBurn; int m_prefMp4Codec; QString m_prefMp4Encoder; int m_prefMp4AudioCodec; int m_prefMp4AudioGain; int m_prefMp4Size; int m_prefMp4NumberCD; int m_prefAudioBitrate; int m_prefButtonWidth; int m_prefButtonHeight; int m_prefReadAhead; bool m_prefMp4AspectRatio; bool m_prefMp42Passes; bool m_prefDelTmpFiles; bool m_prefUseCellCache; bool m_prefMpegChapters; bool m_prefUserOps; bool m_prefShowOutput; bool m_GtkStyle; QString m_prefMp4Width; QString m_prefMp4Height; QString m_prefMp4AudioBitrate; QString m_prefMp4VideoBitrate; QString m_prefAudioFormat; QString m_prefCodecAudio,m_prefCodecVideo,m_prefCodecLabel; QStringList m_prefAudioLang,m_prefSubtitleLang; QStringList m_devices; QStringList m_devicesLabels; QStringList m_devicesIO; QColor m_prefButtonHiliteColor; QColor m_prefButtonTextColor; QFont m_prefButtonFont; bool m_useMplayer; bool m_useGL; int m_MplayerVout; int m_MplayerAout; bool m_useXine; int m_XineVout; int m_XineAout; bool m_usePhonon; public: k9Config(); void read(); void save(); ~k9Config(); void setInputDev ( const int& _value ) { m_InputDev = _value; } int getInputDev() const { return m_InputDev; } void setOutputDev ( const int& _value ) { m_OutputDev = _value; } int getOutputDev() const { return m_OutputDev; } void setKeepMenus ( bool _value ) { m_keepMenus = _value; } bool getMpegChapters() const { return m_prefMpegChapters; } void setMpegChapters ( bool _value ) { m_prefMpegChapters=_value; } bool getGtkStyle() const { return m_GtkStyle; } void setGtkStyle ( bool _value ) { m_GtkStyle=_value; } bool getKeepMenus() const { return m_keepMenus; } void setPrefOutput ( const QString& _value ) { m_prefOutput = _value; } QString getPrefOutput() const { return m_prefOutput; } void setPrefOutputMpeg4 ( const QString& _value ) { m_prefOutputMpeg4 = _value; } QString getPrefOutputMpeg4() const { return m_prefOutputMpeg4; } void setPrefOutputIso ( const QString& _value ) { m_prefOutputIso = _value; } QString getPrefOutputIso() const { return m_prefOutputIso; } void setPrefOutputMpeg2 ( const QString& _value ) { m_prefOutputMpeg2 = _value; } QString getPrefOutputMpeg2() const { return m_prefOutputMpeg2; } void setPrefOutputAudio ( const QString& _value ) { m_prefOutputAudio = _value; } QString getPrefOutputAudio() const { return m_prefOutputAudio; } void setPrefAudioFormat ( const QString &_value ) { m_prefAudioFormat=_value; } QString getPrefAudioFormat() const { return m_prefAudioFormat; } void setPrefMencoderPath( const QString& _value ) { m_prefMencoderPath = _value; } QString getPrefMencoderPath(bool quoted) const { if (quoted) return KShell::quoteArg(m_prefMencoderPath); else return m_prefMencoderPath; } void setPrefMplayerPath( const QString& _value ) { m_prefMplayerPath = _value; } QString getPrefMplayerPath(bool quoted) const { if (quoted) return KShell::quoteArg(m_prefMplayerPath); else return m_prefMplayerPath; } void setPrefk3bPath( const QString& _value ) { m_prefk3bPath = _value; } QString getPrefk3bPath(bool quoted) const { if (quoted) return KShell::quoteArg(m_prefk3bPath); else return m_prefk3bPath; } void setPrefDvdauthorPath( const QString& _value ) { m_prefDvdauthorPath = _value; } QString getPrefDvdauthorPath(bool quoted) const { if (quoted) return KShell::quoteArg(m_prefDvdauthorPath); else return m_prefDvdauthorPath; } void setPrefFFmpegPath( const QString& _value ) { m_prefFFmpegPath = _value; } QString getPrefFFmpegPath(bool quoted) const { if (quoted) return KShell::quoteArg(m_prefFFmpegPath); else return m_prefFFmpegPath; } void setPrefWodimPath( const QString& _value ) { m_prefWodimPath = _value; } QString getPrefWodimPath(bool quoted) const { if (quoted) return KShell::quoteArg(m_prefWodimPath); else return m_prefWodimPath; } void setPrefGenisoimagePath( const QString& _value ) { m_prefGenisoimagePath = _value; } QString getPrefGenisoimagePath(bool quoted) const { if (quoted) return KShell::quoteArg(m_prefGenisoimagePath); else return m_prefGenisoimagePath; } void setPrefVersion ( const QString& _value ) { m_prefVersion = _value; } QString getPrefVersion() const { return m_prefVersion; } void setUseDvdAuthor ( bool _value ) { m_useDvdAuthor = _value; } bool getUseDvdAuthor() const { return m_useDvdAuthor; } void setPrefDelTmpFiles ( bool _value ) { m_prefDelTmpFiles=_value; } bool getPrefDelTmpFiles() const { return m_prefDelTmpFiles; } void setPrefUseCellCache ( bool _value ) { m_prefUseCellCache=_value; } bool getPrefUseCellCache() const { return m_prefUseCellCache; } void setQuickScan ( bool _value ) { m_quickScan = _value; } bool getQuickScan() const { return m_quickScan; } void setPrefSize ( const int& _value ) { m_prefSize = _value; } int getPrefSize() const { return m_prefSize; } void setPrefK3b ( bool _value ) { m_prefK3b = _value; } bool getPrefK3b() const { return m_prefK3b; } void setPrefMenu ( bool _value ) { m_prefMenu = _value; } bool getPrefMenu() const { return m_prefMenu; } void setPrefAutoBurn ( bool _value ) { m_prefAutoBurn = _value; } bool getPrefAutoBurn() const { return m_prefAutoBurn; } void setPrefMp4Codec ( const int& _value ) { m_prefMp4Codec = _value; } int getPrefMp4Codec() const { return m_prefMp4Codec; } void setPrefMp4Encoder ( const QString& _value ) { m_prefMp4Encoder = _value; } QString getPrefMp4Encoder() const { return m_prefMp4Encoder; } void setPrefMp4AudioCodec ( const int& _value ) { m_prefMp4AudioCodec = _value; } int getPrefMp4AudioCodec() const { return m_prefMp4AudioCodec; } void setPrefMp4Size ( const int& _value ) { m_prefMp4Size = _value; } int getPrefMp4Size() const { return m_prefMp4Size; } void setPrefMp4AudioGain ( const int& _value ) { m_prefMp4AudioGain = _value; } int getPrefMp4AudioGain() const { return m_prefMp4AudioGain; } void setPrefMp4NumberCD ( const int& _value ) { m_prefMp4NumberCD = _value; } int getPrefMp4NumberCD() const { return m_prefMp4NumberCD; } void setPrefMp4Width ( const QString& _value ) { m_prefMp4Width = _value; } QString getPrefMp4Width() const { return m_prefMp4Width; } void setPrefMp4Height ( const QString& _value ) { m_prefMp4Height = _value; } QString getPrefMp4Height() const { return m_prefMp4Height; } void setPrefMp4AudioBitrate ( const QString& _value ) { m_prefMp4AudioBitrate = _value; } QString getPrefMp4AudioBitrate() const { return m_prefMp4AudioBitrate; } void setPrefMp4VideoBitrate ( const QString& _value ) { m_prefMp4VideoBitrate = _value; } QString getPrefMp4VideoBitrate() const { return m_prefMp4VideoBitrate; } void setDevices ( const QStringList& _value ) { m_devices = _value; } QStringList getDevices() const { return m_devices; } void setDevicesLabels ( const QStringList& _value ) { m_devicesLabels = _value; } QStringList getDevicesLabels() const { return m_devicesLabels; } void setDevicesIO ( const QStringList& _value ) { m_devicesIO = _value; } QStringList getDevicesIO() const { return m_devicesIO; } void setUseMplayer ( bool _value ) { m_useMplayer = _value; } bool getUseMplayer() const { return m_useMplayer; } void setUseXine ( bool _value ) { m_useXine = _value; } bool getUseXine() const { return m_useXine; } void setUsePhonon ( bool _value ) { m_usePhonon=_value; } bool getUsePhonon() const { return m_usePhonon; } void setUseGL ( bool _value ) { m_useGL = _value; } bool getUseGL() const { return m_useGL; } void setPrefMp4AspectRatio ( bool _value ) { m_prefMp4AspectRatio = _value; } bool getPrefMp4AspectRatio() const { return m_prefMp4AspectRatio; } void setPrefMp42Passes ( bool _value ) { m_prefMp42Passes = _value; } bool getPrefMp42Passes() const { return m_prefMp42Passes; } void setMplayerVout ( const int& _value ) { m_MplayerVout = _value; } int getMplayerVout() const { return m_MplayerVout; } void setMplayerAout ( const int& _value ) { m_MplayerAout = _value; } int getMplayerAout() const { return m_MplayerAout; } void setXineVout ( const int& _value ) { m_XineVout = _value; } int getXineVout() const { return m_XineVout; } void setXineAout ( const int& _value ) { m_XineAout = _value; } int getXineAout() const { return m_XineAout; } bool getPrefShowOutput() const{ return m_prefShowOutput; } void setPrefShowOutput(bool _value) { m_prefShowOutput=_value; } void setPrefAudioBitrate ( int _value ) { m_prefAudioBitrate = _value; } int getPrefAudioBitrate() const { return m_prefAudioBitrate; } void setPrefButtonWidth ( int _value ) { m_prefButtonWidth = _value; } int getPrefButtonWidth() const { return m_prefButtonWidth; } void setPrefButtonHeight ( int _value ) { m_prefButtonHeight = _value; } int getPrefButtonHeight() const { return m_prefButtonHeight; } void setPrefButtonHiliteColor ( const QColor& _value ) { m_prefButtonHiliteColor = _value; } QColor getPrefButtonHiliteColor() const { return m_prefButtonHiliteColor; } void setPrefButtonTextColor ( const QColor& _value ) { m_prefButtonTextColor = _value; } QColor getPrefButtonTextColor() const { return m_prefButtonTextColor; } void setPrefButtonFont ( const QFont& _value ) { m_prefButtonFont = _value; } QFont getPrefButtonFont() const { return m_prefButtonFont; } void setPrefReadAhead ( int _value ) { m_prefReadAhead = _value; } int getPrefReadAhead() const { return m_prefReadAhead; } KConfig* getConfig() ; void setPrefUserOps ( bool theValue ) { m_prefUserOps = theValue; } bool getPrefUserOps() const { return m_prefUserOps; } void setPrefAudioLang ( const QStringList& theValue ) { m_prefAudioLang = theValue; } QStringList getPrefAudioLang() const { return m_prefAudioLang; } void setPrefSubtitleLang ( const QStringList& theValue ) { m_prefSubtitleLang = theValue; } QStringList getPrefSubtitleLang() const { return m_prefSubtitleLang; } QList getPrefColumns() const { return m_prefColumns; } void setPrefColumns(const QList & value) { m_prefColumns=value; } static void checkCodecs(); }; #endif k9copy/src/core/k9logview.h0000644000175000017550000000076412412271774016371 0ustar emulatoremulator#ifndef K9LOGVIEW_H #define K9LOGVIEW_H #include #include #include #include namespace Ui { class k9LogView; } class k9LogView : public QWidget { Q_OBJECT public: k9LogView(QWidget *parent = 0); ~k9LogView(); QListWidget *list(); protected: void changeEvent(QEvent *e); void closeEvent ( QCloseEvent * event ); private slots: void timerDone(); private: Ui::k9LogView *m_ui; bool m_started; }; #endif // K9LOGVIEW_H k9copy/src/core/k9dvdchapter.h0000644000175000017550000000474512412271774017044 0ustar emulatoremulator// // C++ Interface: k9dvdchapter // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9DVDCHAPTER_H #define K9DVDCHAPTER_H #include "k9common.h" #include "k9dvd.h" static int cptChapter=0; enum angleBlock_t {angleNone=0,angleInside=1,angleStart=3,angleEnd=5}; class k9DVDTitle; class k9ChapterCell { public: k9ChapterCell(uint _id,uint _angle) { m_id=_id; m_angle=_angle; m_angleBlock=angleNone; }; uint getid() { return m_id; }; uint getangle() { return m_angle; }; uchar getangleBlock() { return m_angleBlock; }; void setangleBlock(uchar _angleBlock) { m_angleBlock=_angleBlock; }; void setstartSector(uint32_t _value) { m_startSector=_value; }; uint32_t getstartSector() { return m_startSector; }; void setlastSector(uint32_t _value) { m_lastSector=_value; }; uint32_t getlastSector() { return m_lastSector; }; private: uint m_id; uint m_angle; uchar m_angleBlock; uint32_t m_startSector,m_lastSector; }; class k9DVDChapter:public QObject { Q_OBJECT friend class k9DVDTitle; friend class k9DVD; private: // Private attributes /** */ int num; int id; /** */ QTime m_length; QTime m_time; /** */ int sectors; unsigned long startSector; unsigned long endSector; k9DVDTitle *m_title; bool m_selected; static int getcptChapter() { cptChapter ++; return cptChapter; }; static void setcptChapter(int _newValue) { cptChapter=_newValue; }; void clearCells(); public: // Public methods k9DVDChapter(); ~k9DVDChapter(); /** Read property of int num. */ virtual const int& getnum(); /** Read property of QTime length. */ virtual const QTime& getLength(); /** Read property of int sectors. */ virtual const int& getsectors(); QList cells; QList startSectors; virtual const QTime & getTime(); virtual k9DVDTitle * getTitle(); unsigned long getstartSector() { return startSector; }; unsigned long getendSector() { return endSector; }; void setSelected(bool _value); bool getSelected() const; void setLength(const QTime& theValue); void setTime(const QTime& theValue); signals: void selectionChanged(); }; #endif k9copy/src/core/k9titleencopt.cpp0000644000175000017550000000630412412271774017576 0ustar emulatoremulator// // C++ Implementation: k9titleencopt // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "k9common.h" #include "k9titleencopt.h" #include "k9dvdtitle.h" k9TitleEncOpt::k9TitleEncOpt(k9DVDTitle *parent) : QObject(parent) { connect (parent,SIGNAL(selectionChanged()),this,SLOT(load())); load(); } k9TitleEncOpt::~k9TitleEncOpt() { } void k9TitleEncOpt::load() { //KSimpleConfig settings("K9Copy"); k9Config config; int size_mb=(int)getTitle()->gettotalsize_mb(); m_crop.setCoords(0,0,getTitle()->getwidth().toInt()-1,getTitle()->getheight().toInt()-1); m_maxSize=config.getPrefMp4Size(); if(m_maxSize > size_mb) m_maxSize=size_mb ; m_numParts=config.getPrefMp4NumberCD(); m_width=config.getPrefMp4Width(); m_height=config.getPrefMp4Height(); m_keepAspectRatio=config.getPrefMp4AspectRatio(); m_2Passes=config.getPrefMp42Passes(); m_audioBr=config.getPrefMp4AudioBitrate(); m_codec=config.getPrefMp4Codec(); m_audioCodec=config.getPrefMp4AudioCodec (); m_audioGain=config.getPrefMp4AudioGain(); m_videoBr=config.getPrefMp4VideoBitrate(); m_useCache=config.getPrefUseCellCache(); m_encoder=config.getPrefMp4Encoder(); } int k9TitleEncOpt::getMaxSize() { return m_maxSize; } void k9TitleEncOpt::setMaxSize(int _value) { m_maxSize=_value; } int k9TitleEncOpt::getNumParts() { return m_numParts; } void k9TitleEncOpt::setNumParts(int _value) { m_numParts=_value; } int k9TitleEncOpt::getAudioGain() { return m_audioGain; } void k9TitleEncOpt::setAudioGain(int _value) { m_audioGain=_value; } const QString & k9TitleEncOpt::getWidth() { return m_width; } void k9TitleEncOpt::setWidth(QString _value) { m_width=_value; } const QString & k9TitleEncOpt::getHeight() { return m_height; } void k9TitleEncOpt::setHeight(QString _value) { m_height=_value; } const QString & k9TitleEncOpt::getAudioBr() { return m_audioBr; } void k9TitleEncOpt::setAudioBr(QString _value) { m_audioBr=_value; } const QString & k9TitleEncOpt::getVideoBr() { return m_videoBr; } void k9TitleEncOpt::setVideoBr(QString _value) { m_videoBr=_value; } bool k9TitleEncOpt::getKeepAspectRatio() { return m_keepAspectRatio; } void k9TitleEncOpt::setKeepAspectRatio(bool _value) { m_keepAspectRatio=_value; } bool k9TitleEncOpt::get2Passes() { return m_2Passes; } void k9TitleEncOpt::set2Passes(bool _value) { m_2Passes=_value; } QRect *k9TitleEncOpt::getCrop() { return &m_crop; } int k9TitleEncOpt::getCodec() { return m_codec; } void k9TitleEncOpt::setCodec(int _value) { m_codec=_value; } int k9TitleEncOpt::getAudioCodec() { return m_audioCodec; } void k9TitleEncOpt::setAudioCodec(int _value) { m_audioCodec=_value; } bool k9TitleEncOpt::getUseCache() { k9Config config; m_useCache=config.getPrefUseCellCache(); return m_useCache; } void k9TitleEncOpt::setUseCache(bool _value) { m_useCache=_value; } void k9TitleEncOpt::setEncoder(const QString &_value) { m_encoder=_value; } const QString & k9TitleEncOpt::getEncoder() { return m_encoder; } k9copy/src/core/CMakeLists.txt0000644000175000017550000000000012412271774017017 0ustar emulatoremulatork9copy/src/core/k9videocodecs.h0000644000175000017550000000227312412271774017201 0ustar emulatoremulator// // C++ Interface: k9videocodecs // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9VIDEOCODECS_H #define K9VIDEOCODECS_H #include "k9common.h" #include #include /** @author Jean-Michel PETIT */ class _k9VideoCodec; class k9VideoCodecs : public QObject { Q_OBJECT public: k9VideoCodecs(QObject *parent = 0); ~k9VideoCodecs(); void save(); void setFourcc(int _num,QString _value); void setOptions0(int _num,QString _value); void setOptions1(int _num,QString _value); void setOptions2(int _num,QString _value); void setCodecName(int _num,QString _value); void setEncoder(int _num,QString _value); void remove(int _num); QString getFourcc(int _num); QString getOptions0(int _num); QString getOptions1(int _num); QString getOptions2(int _num); QString getCodecName(int _num); QString getEncoder(int _num); int count(); void reset(); static int getAbsCodecNum(int _num,const QString &_encoder); private: QMap m_codecs; k9Config *m_config; }; #endif k9copy/src/core/k9dvd.cpp0000755000175000017550000012220212412271774016020 0ustar emulatoremulator/************************************************************************** * Copyright (C) 2005 by Jean-Michel Petit * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "k9dvd.h" #include "k9dvdtitle.h" #include "k9dvdtitleset.h" #include "k9cellcopylist.h" #include "k9dvdprogress.h" #include "k9ifo2.h" #include #include k9DVDTitle* k9DVD::gettitle(int num) { return ((k9DVDTitle*)m_titles.at(num)); } k9DVDTitle* k9DVD::gettitleByNum(int VTS,int numPgc) { for (int i=0; i < m_titles.count();i++) { k9DVDTitle *track=(k9DVDTitle*)m_titles.at(i); if (track->getIndexed()) { if ((track->getpgc()==(numPgc-1)) && (track->getVTS()==VTS)) return track; //if (track->getnumTitle()==num) //return track; } } // if no title found for (int i=0; i < m_titles.count();i++) { k9DVDTitle *track=(k9DVDTitle*)m_titles.at(i); if ((track->getpgc()==(numPgc-1)) && (track->getVTS()==VTS)) return track; } return (NULL); } /** Read property of int longestTitle. */ k9DVDTitle *k9DVD::getlongestTitle() { return m_longestTitle; } /** Read property of QString title. */ const QString& k9DVD::getDVDTitle() { return m_title; } void k9DVD::setDVDTitle(const QString &_newVal) { m_title=_newVal; } /** Read property of int titleCount. */ const int& k9DVD::gettitleCount() { return m_titleCount; } /** Read property of int titlesetCount. */ const int& k9DVD::gettitlesetCount() { return m_titlesetCount; } k9DVDTitleset *k9DVD::gettitleset(int num) { if (num >=m_titlesets.count()) return NULL; else return m_titlesets[num]; } int k9DVD::getmenuSize() { return m_menuSize; } k9DVD::k9DVD(QObject *parent) :QObject(parent) { m_error=false; m_opened=false; m_arrLng=new lng[200]; k9DVD::LangList(m_arrLng); // m_titles.setAutoDelete(true); // m_titlesets.setAutoDelete(true); m_lvideoFormat.append("NTSC"); m_lvideoFormat.append("PAL"); m_laspectRatio.append("4:3"); m_laspectRatio.append("16:9"); m_laspectRatio.append("?:?"); m_laspectRatio.append("16:9"); m_lquantization.append("16bps"); m_lquantization.append("20bps"); m_lquantization.append("24bps"); m_lquantization.append("drc"); m_lmpegVersion.append("mpeg1"); m_lmpegVersion.append("mpeg2"); m_lvideoHeight.append("480"); m_lvideoHeight.append("576"); m_lvideoHeight.append("???"); m_lvideoHeight.append("576"); m_lvideoWidth.append("720"); m_lvideoWidth.append("704"); m_lvideoWidth.append("352"); m_lvideoWidth.append("352"); m_lpermittedDf.append(""); m_lpermittedDf.append("noletterbox"); m_lpermittedDf.append("nopanscan"); m_lpermittedDf.append("noletterbox & nopanscan"); m_laudioFormat.append("ac3"); m_laudioFormat.append("?"); m_laudioFormat.append("mp2"); m_laudioFormat.append("mp2"); m_laudioFormat.append("pcm"); m_laudioFormat.append("sdds"); m_laudioFormat.append("dts"); m_lsampleFreq.append("48kHz"); m_lsampleFreq.append("48kHz"); m_lsampleFreq.append("Error"); m_laudioType.append(""); m_laudioType.append("Normal"); m_laudioType.append(i18n("for visually impaired")); m_laudioType.append(i18n("director's comments")); m_laudioType.append(i18n("alternate director's comments")); m_lsubpType.append(""); m_lsubpType.append("Normal"); m_lsubpType.append(i18n("Large")); m_lsubpType.append(i18n("Children")); m_lsubpType.append(i18n("reserved")); m_lsubpType.append(i18n("Normal captions")); m_lsubpType.append(i18n("Large captions")); m_lsubpType.append(i18n("Children captions")); m_lsubpType.append(""); m_lsubpType.append(i18n("Forced")); m_lsubpType.append(i18n("reserved")); m_lsubpType.append(i18n("reserved")); m_lsubpType.append(i18n("reserved")); m_lsubpType.append(i18n("Director's comments")); m_lsubpType.append(i18n("Large director's comments")); m_lsubpType.append(i18n("Director's comments for children")); m_frames_per_s[0]=-1.0; m_frames_per_s[1]=25.00; m_frames_per_s[2]=-1.0; m_frames_per_s[3]=29.97; m_start=NULL; } k9DVD::~k9DVD() { if (m_dvd.opened()) m_dvd.close(); deleteTitles(); deleteTitlesets(); delete[] m_arrLng; } void k9DVD::deleteTitles() { //while (!m_titles.isEmpty()) delete m_titles.takeFirst(); qDeleteAll(m_titles); m_titles.clear(); } void k9DVD::deleteTitlesets() { // while (!m_titlesets.isEmpty())delete m_titlesets.takeFirst(); qDeleteAll(m_titlesets); m_titlesets.clear(); } int k9DVD::dvdtime2msec(dvd_time_t *dt) { double fps = m_frames_per_s[(dt->frame_u & 0xc0) >> 6]; long ms; ms = (((dt->hour & 0xf0) >> 3) * 5 + (dt->hour & 0x0f)) * 3600000; ms += (((dt->minute & 0xf0) >> 3) * 5 + (dt->minute & 0x0f)) * 60000; ms += (((dt->second & 0xf0) >> 3) * 5 + (dt->second & 0x0f)) * 1000; if (fps > 0) ms +=(long)( ((dt->frame_u & 0x30) >> 3) * 5 + (dt->frame_u & 0x0f) * 1000.0 / fps); return ms; } /* * The following method is based on code from vobcopy, by Robos, with thanks. */ int k9DVD::get_title_name(const char* dvd_device, char* title) { FILE *filehandle = 0; int i; QString c; if (! (filehandle = fopen(dvd_device, "r"))) { c=i18n("Couldn't open %1 for title\n").arg(dvd_device); // setError(c ); strcpy(title, i18n("unknown").toUtf8()); return -1; } if ( fseek(filehandle, 32808, SEEK_SET )) { fclose(filehandle); c=i18n("Couldn't seek in %1 for title\n").arg(dvd_device); setError(c); strcpy(title, i18n("unknown").toUtf8()); return -1; } if ( 32 != (i = fread(title, 1, 32, filehandle)) ) { fclose(filehandle); // c=i18n("Couldn't read enough bytes for title.\n"); // setError(c); strcpy(title, i18n("unknown").toUtf8()); return 0; } fclose (filehandle); title[32] = '\0'; while (i-- > 2) if (title[i] == ' ') title[i] = '\0'; return 0; } void k9DVD::LangList(lng *_arrLng) { lng arrLng[] = { { " ", i18n("Not Specified") }, { "aa", i18n("Afar") }, { "ab", i18n("Abkhazian") }, { "af", i18n("Afrikaans") }, { "am", i18n("Amharic")}, { "ar", i18n("Arabic") }, { "as", i18n("Assamese") }, { "ay", i18n("Aymara") }, { "az", i18n("Azerbaijani") }, { "ba", i18n("Bashkir") }, { "be", i18n("Byelorussian") }, { "bg", i18n("Bulgarian") }, { "bh", i18n("Bihari") }, { "bi", i18n("Bislama") }, { "bn", i18n("Bengali; Bangla") }, { "bo", i18n("Tibetan") }, { "br", i18n("Breton") }, { "ca", i18n("Catalan") }, { "co", i18n("Corsican") }, { "cs", i18n("Czech") }, { "cy", i18n("Welsh") }, { "da", i18n("Dansk") }, { "de", i18n("Deutsch") }, { "dz", i18n("Bhutani") }, { "el", i18n("Greek") }, { "en", i18n("English") }, { "eo", i18n("Esperanto") }, { "es", i18n("Espanol") }, { "et", i18n("Estonian") }, { "eu", i18n("Basque") }, { "fa", i18n("Persian") }, { "fi", i18n("Suomi") }, { "fj", i18n("Fiji") }, { "fo", i18n("Faroese") }, { "fr", i18n("Francais") }, { "fy", i18n("Frisian") }, { "ga", i18n("Gaelic") }, { "gd", i18n("Scots Gaelic") }, { "gl", i18n("Galician") }, { "gn", i18n("Guarani") }, { "gu", i18n("Gujarati") }, { "ha", i18n("Hausa") }, { "he", i18n("Hebrew") }, { "hi", i18n("Hindi") }, { "hr", i18n("Hrvatski") }, { "hu", i18n("Magyar") }, { "hy", i18n("Armenian") }, { "ia", i18n("Interlingua") }, { "id", i18n("Indonesian") }, { "ie", i18n("Interlingue") }, { "ik", i18n("Inupiak") }, { "in", i18n("Indonesian") }, { "is", i18n("Islenska") }, { "it", i18n("Italiano") }, { "iu", i18n("Inuktitut") }, { "iw", i18n("Hebrew") }, { "ja", i18n("Japanese") }, { "ji", i18n("Yiddish") }, { "jw", i18n("Javanese") }, { "ka", i18n("Georgian") }, { "kk", i18n("Kazakh") }, { "kl", i18n("Greenlandic") }, { "km", i18n("Cambodian") }, { "kn", i18n("Kannada") }, { "ko", i18n("Korean") }, { "ks", i18n("Kashmiri") }, { "ku", i18n("Kurdish") }, { "ky", i18n("Kirghiz") }, { "la", i18n("Latin") }, { "ln", i18n("Lingala") }, { "lo", i18n("Laothian") }, { "lt", i18n("Lithuanian") }, { "lv", i18n("Latvian, Lettish") }, { "mg", i18n("Malagasy") }, { "mi", i18n("Maori") }, { "mk", i18n("Macedonian") }, { "ml", i18n("Malayalam") }, { "mn", i18n("Mongolian") }, { "mo", i18n("Moldavian") }, { "mr", i18n("Marathi") }, { "ms", i18n("Malay") }, { "mt", i18n("Maltese") }, { "my", i18n("Burmese") }, { "na", i18n("Nauru") }, { "ne", i18n("Nepali") }, { "nl", i18n("Nederlands") }, { "no", i18n("Norsk") }, { "oc", i18n("Occitan") }, { "om", i18n("Oromo") }, { "or", i18n("Oriya") }, { "pa", i18n("Punjabi") }, { "pl", i18n("Polish") }, { "ps", i18n("Pashto, Pushto") }, { "pt", i18n("Portugues") }, { "qu", i18n("Quechua") }, { "rm", i18n("Rhaeto-Romance") }, { "rn", i18n("Kirundi") }, { "ro", i18n("Romanian") }, { "ru", i18n("Russian") }, { "rw", i18n("Kinyarwanda") }, { "sa", i18n("Sanskrit") }, { "sd", i18n("Sindhi") }, { "sg", i18n("Sangho") }, { "sh", i18n("Serbo-Croatian") }, { "si", i18n("Sinhalese") }, { "sk", i18n("Slovak") }, { "sl", i18n("Slovenian") }, { "sm",i18n( "Samoan") }, { "sn", i18n("Shona") }, { "so", i18n("Somali") }, { "sq", i18n("Albanian") }, { "sr", i18n("Serbian") }, { "ss", i18n("Siswati") }, { "st", i18n("Sesotho") }, { "su", i18n("Sundanese") }, { "sv", i18n("Svenska") }, { "sw", i18n("Swahili") }, { "ta", i18n("Tamil") }, { "te", i18n("Telugu") }, { "tg", i18n("Tajik") }, { "th", i18n("Thai") }, { "ti", i18n("Tigrinya") }, { "tk", i18n("Turkmen") }, { "tl", i18n("Tagalog") }, { "tn", i18n("Setswana") }, { "to", i18n("Tonga") }, { "tr", i18n("Turkish") }, { "ts", i18n("Tsonga") }, { "tt", i18n("Tatar") }, { "tw", i18n("Twi") }, { "ug", i18n("Uighur") }, { "uk", i18n("Ukrainian") }, { "ur", i18n("Urdu") }, { "uz", i18n("Uzbek") }, { "vi", i18n("Vietnamese") }, { "vo", i18n("Volapuk") }, { "wo", i18n("Wolof") }, { "xh", i18n("Xhosa") }, { "yi", i18n("Yiddish") }, { "yo", i18n("Yoruba") }, { "za", i18n("Zhuang") }, { "zh", i18n("Chinese") }, { "zu", i18n("Zulu") }, { "xx", i18n("Unknown") }, { "\0", i18n("Unknown") } }; for (uint i=0; i <(sizeof(arrLng)/sizeof(lng));i++) { _arrLng[i]=arrLng[i]; } } QString k9DVD::lang_name(lng *arrLng,const QString& code,const QString & name) { QString c; int i=0; //lng* arrLng=m_arrLng; c=i18n("Unknown"); for (i=0 ; arrLng[i].code[0]!=0;i++) { lng l =arrLng[i]; if (name=="") { if (code==l.code) { c = l.name; } } else { if (name==l.name) { c = l.code; } } } return c; } int k9DVD::calcNumTitle(ifo_handle_t *ifo,int _vts,int _ttn) { for (int i=0; i< ifo->tt_srpt->nr_of_srpts;i++) { if (ifo->tt_srpt->title[i].title_set_nr==_vts && ifo->tt_srpt->title[i].vts_ttn == _ttn) return (i+1); } return 0; } int k9DVD::scandvd (const QString & device,bool _quickScan) { char ctitle[255]; k9DVDChapter::setcptChapter(0); ifo_handle_t *ifo_zero, *ifo; pgcit_t *vts_pgcit; vtsi_mat_t *vtsi_mat; vmgi_mat_t *vmgi_mat; audio_attr_t *audio_attr; video_attr_t *video_attr; subp_attr_t *subp_attr; pgc_t *pgc; int i, j, ltitles, cell, vts_ttn, title_set_nr; QString langCode; int has_title = 0; int max_length = 0; bool ok; tt_srpt_t *tt_srpt; QString txt,c; m_start=NULL; int menuSizes[100]; for ( j=0; j<100;j++) menuSizes[j]=0; deleteTitles(); m_Device=device; m_error=false; m_errMsg=""; if (!_quickScan) { m_progressDlg= new k9DVDProgress(0); m_progressDlg->setpbTitleStep(0); m_progressDlg->setpbTotalStep(0); connect(this, SIGNAL(sigVobProgress(unsigned int,unsigned int)), this, SLOT(slotVobProgress(unsigned int,unsigned int))); connect(this, SIGNAL(sigTitleProgress(unsigned int,unsigned int)), this, SLOT(slotTitleProgress(unsigned int,unsigned int))); connect(this, SIGNAL(sigTitleText(QString&)), this, SLOT(slotTitleText(QString&))); connect(this, SIGNAL(sigTotalText(QString&)), this, SLOT(slotTotalText(QString&))); m_progressDlg->show(); } else m_progressDlg=NULL; k9Tools::processEvents(); k9DVDTitle *l_track; k9DVDAudioStream *l_auds; k9DVDChapter *l_chap; k9DVDSubtitle *l_sub; QString sh,sm,ss; /* ret = stat(device.latin1(), &dvd_stat); if ( ret < 0 ) { c=i18n("Can't find device %1\n").arg( device); setError(c); return 1; } */ if (m_dvd.opened()) m_dvd.close(); m_dvd.openDevice(device); if ( !m_dvd.opened() ) { c=i18n("Can't open disc %1!\n").arg(device); setError(c); return 2; } // k9Ifo2 kifo_zero(&m_dvd),kifo(&m_dvd); // kifo_zero.openIFO( 0); k9Ifo2 *kifo_zero= m_dvd.getIfo(0); k9Ifo2 *kifo; ifo_zero = kifo_zero->getIFO(); if ( !ifo_zero ) { c=i18n("Can't open main ifo!\n"); setError(c); return 3; } ltitles = ifo_zero->tt_srpt->nr_of_srpts; m_titleCount = 0; has_title = get_title_name(device.toUtf8(), ctitle); vmgi_mat = ifo_zero->vmgi_mat; m_titlesetCount = vmgi_mat->vmg_nr_of_title_sets; menuSizes[0]=vmgi_mat->vmg_last_sector; m_title=( has_title ? i18n("unknown") : ctitle); for (int ts=1;ts <=m_titlesetCount;ts++) { tt_srpt = ifo_zero->tt_srpt; kifo=m_dvd.getIfo(ts); ifo = kifo->getIFO(); if (ifo==NULL) { //ifo is null when trying to open a protected dvd setError(i18n("Can't open disc %1!\n").arg(device)); return 2; //continue; } //add the titleset in the titleset list k9DVDTitleset *titleset = new k9DVDTitleset(ts,ifo->vtsi_mat->vts_last_sector -ifo->vtsi_mat->vtstt_vobs-1); m_titlesets.append(titleset); for (j=0; j < ifo->vts_pgcit->nr_of_pgci_srp; j++) { // tt_srpt->title[j].title_set_nr); // GENERAL vtsi_mat = ifo->vtsi_mat; vts_pgcit = ifo->vts_pgcit; pgc = vts_pgcit->pgci_srp[j].pgc; //retrieve the ttn int ttn=(vts_pgcit->pgci_srp[j].entry_id) & 0x7F; bool entryPgc= (vts_pgcit->pgci_srp[j].entry_id & 0x80)==0x80; int numTitle=calcNumTitle(ifo_zero,ts,ttn); //JMP : vérifier la numérotation des titres ...... if (vtsi_mat && (pgc->nr_of_cells >0)) { m_titleCount++; vts_ttn = ttn;//ifo->vts_ptt_srpt->title[j].ptt[0].pgcn; //ifo_zero->tt_srpt->title[j].vts_ttn; //JMPtxt=i18n("Title %1").arg(indexedCount); txt=i18n("Title %1").arg(numTitle); emit sigTotalText (txt); emit sigTitleProgress(numTitle,ltitles); video_attr = &vtsi_mat->vts_video_attr; vmgi_mat = ifo_zero->vmgi_mat; title_set_nr = ts; //ifo_zero->tt_srpt->title[j].title_set_nr; menuSizes[title_set_nr]=vtsi_mat->vtstt_vobs + vtsi_mat->vtsi_last_sector +1; //vts_pgcit->pgci_srp[ifo->vts_ptt_srpt->title[vts_ttn - 1].ptt[0].pgcn - 1].pgc; int titleStartSector=pgc->cell_playback[0].first_sector; //l_track=addTitle(j+1,title_set_nr,ifo->vts_ptt_srpt->title[vts_ttn - 1].ptt[0].pgcn - 1,titleStartSector,isTitleIndex(ifo_zero,ts,vts_ttn)); l_track=addTitle(titleset,m_titleCount, numTitle,title_set_nr,j,titleStartSector, entryPgc); titleset->add (l_track); sh.sprintf("%02x",pgc->playback_time.hour); sm.sprintf("%02x",pgc->playback_time.minute); ss.sprintf("%02x",pgc->playback_time.second); l_track->length.setHMS(sh.toInt(&ok,10),sm.toInt(&ok,10),ss.toInt(&ok,10)); //printf(i18n("Title: %02d, Length: %02x:%02x:%02x "), j+1, pgc->playback_time.hour, pgc->playback_time.minute, pgc->playback_time.second); if (dvdtime2msec(&pgc->playback_time) > max_length && entryPgc) { max_length = dvdtime2msec(&pgc->playback_time); m_longestTitle = l_track; } l_track->chapterCount = pgc->nr_of_programs;// ifo_zero->tt_srpt->title[j].nr_of_ptts; l_track->audioStreamCount = vtsi_mat->nr_of_vts_audio_streams; l_track->subPictureCount = vtsi_mat->nr_of_vts_subp_streams; l_track->VTS = ts;// ifo_zero->tt_srpt->title[j].title_set_nr; l_track->TTN = ttn; // ifo_zero->tt_srpt->title[j].vts_ttn; l_track->FPS = m_frames_per_s[(pgc->playback_time.frame_u & 0xc0) >> 6]; l_track->format= m_lvideoFormat[video_attr->video_format]; m_format = l_track->format; /* QStringList::Iterator it; it= videoFormat.at(video_attr->video_format); c= (*it).latin1(); */ l_track->aspectRatio =m_laspectRatio[video_attr->display_aspect_ratio]; l_track->width = m_lvideoWidth[video_attr->picture_size]; ; l_track->height = m_lvideoHeight[video_attr->video_format]; l_track->DF = m_lpermittedDf[video_attr->permitted_df]; for (i=0; i<16; i++) { QString pal; pal.sprintf("%08x",pgc->palette[i]); l_track->palette.append(pal); } // ANGLES l_track->angleCount = ifo_zero->tt_srpt->title[j].nr_of_angles; // AUDIO // for (i=0; inr_of_vts_audio_streams; i++) { l_track->audioStreamCount=0; for (i=0; inr_of_vts_audio_streams; i++) { if (pgc->audio_control[i]>>8 !=0) { l_track->audioStreamCount++; l_auds=l_track->addAudioStream(); l_auds->id = 1+ ((pgc->audio_control[i]>>8) & 0x7) ; //this only true for AC3 streams l_auds->m_streamId = (pgc->audio_control[i]>>8); audio_attr = &vtsi_mat->vts_audio_attr[i]; //dts stream starts at 0x88 if (audio_attr->audio_format==6) l_auds->m_streamId +=8; //JMPaudio_attr = &vtsi_mat->vts_audio_attr[l_auds->id-1]; langCode.sprintf("%c%c", audio_attr->lang_code>>8, audio_attr->lang_code & 0xff); if (! (audio_attr->lang_code>>8)) { langCode = "xx"; } l_auds->langCod=langCode; l_auds->language=lang_name(m_arrLng,l_auds->langCod,""); if (l_auds->language==i18n("Unknown")) l_auds->langCod="xx"; l_auds->format= m_laudioFormat[audio_attr->audio_format]; l_auds->frequency = m_lsampleFreq[audio_attr->sample_frequency]; l_auds->quantization = m_lquantization[audio_attr->quantization]; l_auds->channels = audio_attr->channels+1; l_auds->appMode = audio_attr->application_mode; l_auds->content = m_laudioType[audio_attr->code_extension]; //if (((pgc->audio_control[i]>>8) & 0x80) ==0x80) { //} else { // l_auds->id=1; //} } } l_track->m_defAudio=NULL; l_track->m_defSubtitle=NULL; // CHAPTERS cell = 0; unsigned long total_sectors = 0; l_track->chapterCount= pgc->nr_of_programs; for (i=0;i < l_track->chapterCount;i++) l_track->addChapter(i+1); k9DVDChapter *l_pchap=NULL; for (i=0; inr_of_programs; i++) { int second=0, minute=0, hour=0, tmp; char hex[3]; int next = pgc->program_map[i+1]; unsigned long sectors = 0; l_chap = l_track->getChapter(i); //first sector l_chap->startSector=pgc->cell_playback[cell].first_sector; ; l_chap->endSector=0; if (i == pgc->nr_of_programs - 1) next = pgc->nr_of_cells + 1; int iangleStart=-1,iangleEnd=-1; while (cell < next - 1) { //using c2 otherwise the value of cell were lost //int c2=cell; //l_chap->cells.append(c2); int startSect=pgc->cell_playback[cell].first_sector; l_chap->startSectors.append(startSect); snprintf(hex,3, "%02x", pgc->cell_playback[cell].playback_time.second); tmp = second + atoi(hex); minute = minute + (tmp / 60); second = tmp % 60; snprintf(hex,3, "%02x", pgc->cell_playback[cell].playback_time.minute); tmp = minute + atoi(hex); hour = hour + (tmp / 60); minute = tmp % 60; l_chap->endSector= pgc->cell_playback[cell].last_sector; //last sector /* Check if we're entering an angle block. (vamp_play-title) */ int cell2=cell; if ( pgc->cell_playback[ cell ].block_type == BLOCK_TYPE_ANGLE_BLOCK && cell>iangleEnd ) { iangleStart=cell; for ( int idc = 0;; ++idc ) { k9ChapterCell * chapterCell=new k9ChapterCell(cell2+idc,idc+1); l_chap->cells.append(chapterCell); chapterCell->setstartSector(pgc->cell_playback[cell2+idc].first_sector); chapterCell->setlastSector(pgc->cell_playback[cell2+idc].last_sector); if (idc==0) chapterCell->setangleBlock(angleStart); else chapterCell->setangleBlock(angleInside); if ( pgc->cell_playback[ cell2 + idc ].block_mode == BLOCK_MODE_LAST_CELL ) { iangleEnd=cell2+idc; chapterCell->setangleBlock(angleEnd); sectors += pgc->cell_playback[iangleEnd].last_sector - pgc->cell_playback[iangleStart].first_sector + 1; break; } } } else { if (!(cell>=iangleStart && cell <=iangleEnd)) { k9ChapterCell * chapterCell=new k9ChapterCell(cell,1); l_chap->cells.append(chapterCell); chapterCell->setstartSector(pgc->cell_playback[cell].first_sector); chapterCell->setlastSector(pgc->cell_playback[cell].last_sector); sectors += pgc->cell_playback[cell].last_sector - pgc->cell_playback[cell].first_sector + 1; } } cell++; } l_track->vobusize_mb += calcVobuSize(ifo,l_chap); total_sectors += sectors; l_chap->setLength(QTime(hour,minute,second)); l_chap->sectors=sectors; if (l_pchap!=NULL) { QTime t(0,0,0); int position; position=t.secsTo(l_pchap->getLength()); t=l_pchap->getTime().addSecs(position); l_chap->setTime(t); } l_pchap=l_chap; } l_track->size_mb =((float)total_sectors *2048)/(1024*1024); l_track->m_sectors= total_sectors; // SUBTITLES l_track->subPictureCount=0; for (i=0; inr_of_vts_subp_streams; i++) { if (pgc->subp_control[i]>>24 !=0) { l_sub=l_track->addSubtitle(i+1); unsigned char subpc; subpc=pgc->subp_control[i]>>24; if ((subpc & 0x80)==0x80) { if (l_track->aspectRatio=="4:3") { l_sub->id.append(1+ (subpc & 0x1F)); } else { subpc=(pgc->subp_control[i]>>16) & 0x1F; l_sub->id.append(1+ subpc); subpc=(pgc->subp_control[i]>>8) & 0x1F; if (! l_sub->id.contains(1+ subpc) && ! l_track->DF.contains("noletterbox")) l_sub->id.append(1+ subpc); subpc=pgc->subp_control[i] & 0x1F; if (! l_sub->id.contains(1+ subpc) && ! l_track->DF.contains("nopanscan")) l_sub->id.append(1+ subpc); } } l_track->subPictureCount++; subp_attr = &vtsi_mat->vts_subp_attr[i]; langCode.sprintf("%c%c", subp_attr->lang_code>>8, subp_attr->lang_code & 0xff); if (!(subp_attr->lang_code>>8)) { langCode ="xx"; } //JMP : l_sub->setselected(!titleIndexed); l_sub->langCod=langCode; l_sub->language=lang_name(m_arrLng,langCode,""); l_sub->content= m_lsubpType[subp_attr->code_extension]; } } if (entryPgc && !_quickScan) calcStreamSize(*l_track); } } //kifo.closeIFO(); } m_menuSize=0; for (j=0;j<100;j++) m_menuSize+=menuSizes[j]; //kifo_zero.closeIFO(); if (!_quickScan) delete m_progressDlg; m_progressDlg=0; m_opened=true; //m_dvd.close(); return 0; } float k9DVD::calcVobuSize(ifo_handle_t *_ifo,k9DVDChapter *_chapter) { vobu_admap_t * vobu_admap = _ifo->vts_vobu_admap; int length = vobu_admap->last_byte + 1 - VOBU_ADMAP_SIZE; float total=0; for (uint32_t i = 0; i < length/sizeof(uint32_t); i++) { if (vobu_admap->vobu_start_sectors[i] >= _chapter->startSector &&vobu_admap->vobu_start_sectors[i] <= _chapter->endSector) total++; } total=total*2048; total=total/(1024*1024); return total; } /** Adds a new track in the titles list the list is sorted by VTS and pgc*/ k9DVDTitle* k9DVD::addTitle(k9DVDTitleset *_titleset,int id,int num,uint _VTS,int _pgc,uint32_t _startSector,bool _indexed) { k9DVDTitle *track,*tmp; track = new k9DVDTitle(this); track->numTitle=num; track->indexed=_indexed; track->id=id; track->m_titleset=_titleset; //JMP : modification track->forceSelection = false; // !_indexed; track->ts_nr=_VTS; track->pgc=_pgc; bool bappend=true; for (int i=0;igetChapter(0); if (tmp->ts_nr >_VTS) { bappend=false; } else if ( (tmp->ts_nr==_VTS) && ((tmp->pgc >_pgc) || (chap->getstartSector() > _startSector)) ) { bappend=false; } if (!bappend) { m_titles.insert(i,track); break; } } if (bappend) m_titles.append(track); track->name=i18n("Title %1").arg(num); if (!_indexed) { for (int i=0;inumTitle==num && tmp->indexed) { tmp->m_titles.append(track); track->m_mainTitle=tmp; } } } return(track); } void k9DVD::calcStreamSize(k9DVDTitle & track) { struct stream_counter streams[64]; int stream_count; int start = 0; int stop = 0; k9DVDChapter *c_start,*c_stop; struct streamSize streamList[64]; int c, x; QString pg; for ( x=0 ; x<64 ; x++ ) { // init stream usage list streams[x].id = 0; streams[x].count = 0; streams[x].size_mb = 0; streams[x].percent = 0; streamList[x].id=0; streamList[x].percent=0; streamList[x].size_mb=0; } x = 0; c = 0; if ( track.chapterCount == 2 ) { // select which chapters to probe for stream sizes start=0; stop=1; } if (track.chapterCount == 1) { start=0; stop=0; } if (track.chapterCount >2) { start=0; stop=(int)(track.chapterCount-1); } c_start=(k9DVDChapter*)track.chapters.at(start); c_stop=(k9DVDChapter*)track.chapters.at(stop); pg=i18n("reading title"); emit sigTitleText(pg); //probe stream usage c = stream_vob( track.ts_nr,c_start->startSector, c_stop->endSector, streams); for ( x=0 ; x<64 ; x++ ) { if ( streams[x].id == 0 ) break; streams[x].percent = (float)streams[x].count / (float)(c / 100.); // calc usage in percent } // create streamlist with all streams stream_count=0; for ( c=0 ; c<64 ; c++ ) { if ( streams[c].id == 0 ) break; streamList[stream_count].id = streams[c].id; if ( stream_count >= 64 ) break; stream_count++; x++; } // other_streams_mb = 0; // calc size of all selected streams for ( x=0 ; xvideosize_mb = streamList[x].size_mb; } for (i=0;iaudioStreamCount;i++) { l_auds=(k9DVDAudioStream*)l_track->audioStreams.at(i); for (x=0;x<64;x++) { if (streamList[x].id==0) break; int id=streamList[x].id; if (( (id >=0x80) && (id <=0x8f)) || ((id >=0xa0) && (id <=0xa7)) || ((id >=0xc0) && (id <=0xdf))) { if ( getVampsID(id) == l_auds->id) { l_auds->size_mb = streamList[x].size_mb; //stop the loop, go to next audio stream break; } } } } for (i=0;isubPictureCount;i++) { l_sub=(k9DVDSubtitle*)l_track->subtitles.at(i); for (x=0;x<64;x++) { if (streamList[x].id==0) break; int id=streamList[x].id; if ( (id >=0x20) && (id <=0x3f)) { if ( l_sub->id.contains(id - 0x20 +1) ) { l_sub->size_mb = streamList[x].size_mb; break; } } } } } int k9DVD::identify_stream( unsigned char *buffer ) { uint8_t packet_type = buffer[17]; if ( (packet_type >= 0xE0) && (packet_type <= 0xEF) ) { // video streams ; } else if ( packet_type == 0xBB ) { // system header ; } else if ( packet_type == 0xBE ) { // padding ; } else if ( packet_type == 0xBF ) { // nav pack ; } else if ( (packet_type >= 0xC0) && (packet_type <= 0xDF) ) { // mpeg audio ; } else if ( packet_type == 0xBD ) { // private stream, check content packet_type = buffer[23+buffer[22]]; } return packet_type; } long k9DVD::stream_vob( int title, unsigned long startblock, unsigned long lastblock, struct stream_counter *sc) { k9DVDFile *dvdfile; //JMP unsigned char buffer[DVD_VIDEO_LB_LEN]; unsigned char buffer[DVD_VIDEO_LB_LEN*800]; unsigned char *ptrbuff; int blocksize=800,y; int step=(int)((lastblock-startblock)/800) / 10;// * 0.05; if (step==0) step=1; unsigned char stream_id; long total=0; unsigned long i, x ,nbread=0; ssize_t size; QString c; dvdfile =m_dvd.openTitle( title); if ( !dvdfile ) { c=i18n("Error opening vobs for title %1\n").arg(title); setError(c); return 0; } i = startblock; while ( (i >= startblock) && (i <= lastblock) && (blocksize>0)) { // read blocks size= dvdfile->readBlocks( i,blocksize , buffer); emit sigVobProgress(i-startblock,lastblock-startblock); total+=size; if ( !size ) { c=i18n("ERROR reading block %1\n").arg(i); setError(c); break; } ptrbuff=buffer; for (y=0;y lastblock) blocksize=lastblock-i; } dvdfile->close(); return total; } uint64_t k9DVD::getsizeSelected(bool ) { uint64_t selstreams=0,vidstreams=0; int i; k9DVDTitle *l_track; bool withvideo; for (i=0;iisSelected() && l_track->getIndexed(); if ( withvideo) { vidstreams +=l_track->getChaptersSize(true); /* vidstreams +=l_track->getsectors(); if (_streams) { for (x=0;xaudioStreamCount;x++) { l_auds=l_track->getaudioStream(x); if (!l_auds->selected) selstreams += l_auds->size_mb*512; } for (x=0;xsubPictureCount;x++) { l_sub=l_track->getsubtitle(x); if (!l_sub->selected) selstreams += l_sub->size_mb*512; } }*/ } } vidstreams -=selstreams; return (vidstreams ); } float k9DVD::getfactor(bool _withMenus,bool _streams,bool _useDvdAuthor) { if (!_useDvdAuthor || _withMenus) { //m_dvd.openDevice(Device); k9CellCopyList *cellCopyList =new k9CellCopyList(&m_dvd,this); double factor=cellCopyList->getfactor(_withMenus,_streams); //m_dvd.close(); return (factor); } else { float selstreams=0,vidstreams=0,l_factor; int i,x; k9DVDTitle *l_track; k9DVDAudioStream *l_auds; k9DVDSubtitle *l_sub; bool withvideo; double forced=0,forcedsh=0; for (i=0;iisSelected() && l_track->getIndexed(); if ( withvideo) { //size_mb = size of titles - size of unselected chapters float size_mb=l_track->gettotalsize_mb()-l_track->getChaptersSize_mb( false) ; //gettotalsize_mb does include parts of titles vidstreams +=size_mb ; if (l_track->getforceFactor()) { forced+=size_mb; forcedsh+=(size_mb/l_track->getfactor()); } if (_streams) { for (x=0;xaudioStreamCount;x++) { l_auds=l_track->getaudioStream(x); if (!l_auds->selected) selstreams += l_auds->size_mb; } for (x=0;xsubPictureCount;x++) { l_sub=l_track->getsubtitle(x); if (!l_sub->selected) selstreams += l_sub->size_mb; } } } } vidstreams -=selstreams; l_factor = ((float) vidstreams - forced) / (k9DVDSize::getMaxSize() - forcedsh); l_factor = (int)((l_factor+0.01)*100); l_factor /=100; if (l_factor <1) l_factor=1; return(l_factor); } } void k9DVD::slotVobProgress(unsigned int position,unsigned int total) { m_progressDlg->setpbTitleStep(position); m_progressDlg->setpbTitleTotalSteps(total); k9Tools::processEvents(); } void k9DVD::slotTitleProgress(unsigned int position,unsigned int total) { m_progressDlg->setpbTotalStep(position); m_progressDlg->setpbTotalTotalSteps(total); k9Tools::processEvents(); } void k9DVD::slotTitleText(QString& text) { m_progressDlg->setlblTitle(text); k9Tools::processEvents(); } void k9DVD::slotTotalText(QString& text) { m_progressDlg->setlblTotal(text); k9Tools::processEvents(); } const QString& k9DVD::getDevice() { return m_Device; } const bool& k9DVD::geterror() { return m_error; } const QString& k9DVD::geterrMsg() { return m_errMsg; } void k9DVD::setError(const QString & err) { m_error=true; m_errMsg=err; if (m_progressDlg !=NULL) m_progressDlg->hide(); } const bool& k9DVD::getopened() { return m_opened; } QString &k9DVD::getFormat() { return (m_format); } int k9DVD::getVampsID(int type) { int abase=0; if (type >= 0x80 && type <= 0x87) { // AC3 audio abase = 0x80; } else if (type >= 0x88 && type <= 0x8f) { // DTS audio abase = 0x88; } else if (type >= 0xa0 && type <= 0xbf) { // LPCM audio abase = 0xa0; } else if (type >= 0xc0 && type <= 0xdf) { // MPEG audio abase = 0xc0; } return (type-abase +1); } k9DVDTitle* k9DVD::getstart() { return m_start; } void k9DVD::setstart(k9DVDTitle* title) { m_start=title; } // returns the title number in the reauthored DVD int k9DVD::getnewTitleNum(k9DVDTitle *title) { int num=0; k9DVDTitle *tr; for (int i=0 ;i < m_titleCount;i++) { tr=gettitle(i); if (tr->isSelected() && tr->getIndexed()) { ++num; if (tr->getnumTitle() == title->getnumTitle()) return(num); } } return(-1); } void k9DVD::close() { m_opened=false; if (m_dvd.opened()) m_dvd.close(); deleteTitles(); deleteTitlesets(); } k9copy/src/core/k9dvdprogress.h0000755000175000017550000000415212412271774017255 0ustar emulatoremulator/************************************************************************** * Copyright (C) 2005 by Jean-Michel Petit * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef K9DVDPROGRESS_H #define K9DVDPROGRESS_H #include "ui_dvdprogress.h" /** *@author */ class k9DVDProgress : public QDialog{ Q_OBJECT public: k9DVDProgress(QWidget* parent ); ~k9DVDProgress(); /** No descriptions */ void setpbTitleTotalSteps(unsigned int total); /** No descriptions */ void setpbTitleStep(unsigned int position); /** No descriptions */ void setpbTotalTotalSteps(int total); /** No descriptions */ void setpbTotalStep(int position); /** No descriptions */ void setlblTitle(QString & text); /** No descriptions */ void setlblTotal(QString& text); protected: void closeEvent( QCloseEvent* ce ); private: Ui::DVDProgress Ui_DVDProgress; }; #endif k9copy/src/core/k9log.h0000644000175000017550000000107612412271774015473 0ustar emulatoremulator#ifndef K9LOG_H #define K9LOG_H #include #include namespace k9logLevel { enum type {WARNING,INFO,ERROR}; } class k9logEntry { public: QString text; k9logLevel::type level; }; class k9log { private: QQueue m_list; public: k9log(); ~k9log(); QQueue &list(); static void add(QString s,k9logLevel::type level); static k9logEntry* dequeue (); static int count(); static void write(QString s); static void writer(QString s); static void writeln(QString s); }; #endif // K9LOG_H k9copy/src/core/k9process.h0000644000175000017550000000271012412271774016364 0ustar emulatoremulator// // C++ Interface: k9process // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9PROCESS_H #define K9PROCESS_H #include #include #include /** @author Jean-Michel PETIT */ class k9Process : public KProcess { Q_OBJECT public: k9Process(QObject *parent = 0, const char *name = 0); void sync(); const QString & debug(); ~k9Process(); int getElapsed() const; virtual bool start (); void setShellCommand (const QString &cmd); void clearProgram(); void wait(); bool isRunning(); bool normalExit(); void setDebugOutput(bool theValue); private: bool m_waitSync; bool m_shellCmd; QString m_debug; bool m_debugOutput; QTime m_elapsed; QEventLoop *m_eventLoop; void syncStart(); protected: virtual void getStdout(QByteArray data); virtual void getStderr(QByteArray data); private slots: void slotReadyReadStandardError (); void slotReadyReadStandardOutput (); void slotStarted(); void slotError(QProcess::ProcessError ); void slotFinished ( int exitCode, QProcess::ExitStatus exitStatus ); signals: void receivedStderr(char *, int); void receivedStdout(char *, int ); void receivedStderr(k9Process*,char *, int); void receivedStdout(k9Process*,char *, int ); void processExited(k9Process *); }; #endif k9copy/src/core/k9tools.h0000644000175000017550000000213612412271774016050 0ustar emulatoremulator// // C++ Interface: k9tools // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9TOOLS_H #define K9TOOLS_H #include #include #include /** @author Jean-Michel PETIT */ class k9Tools{ private: k9Tools() {} ~k9Tools(){} public: static bool checkProgram(QString _progName,bool _msg=false); static void clearOutput(QString name); static void clearOutput(); static void setComboText(QComboBox *_cb,const QString &_text); static long getFreeSpace(const QString &_path); static bool runAsRoot(const QString &_command,const QString &_description); static void addTemporaryDir(const QString &dir); static const QString getTempPath() ; static const QString randomFileName(); static QString findExe(const QString _program); static void processEvents(); static void setBatchCopy(bool); static bool getBatchCopy(); static void setMainThread(); }; #endif k9copy/src/core/k9dvdread.h0000644000175000017550000000236612412271774016326 0ustar emulatoremulator// // C++ Interface: k9dvdread // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9DVDREAD_H #define K9DVDREAD_H #include "k9common.h" #include /** @author Jean-Michel PETIT */ class k9DVDRead; class k9Ifo2; class k9DVDFile { friend class k9DVDRead; private: dvd_file_t *m_file; k9DVDRead *m_dvd; void openIfo(uint _vts); void openMenu(uint _vts); void openTitle(uint _vts); public: k9DVDFile(k9DVDRead *_dvd); ~k9DVDFile(); void close(); int readBytes(uchar *_buffer,uint32_t _size); int readBlocks(uint32_t _sector,uint32_t _size,uchar*_buffer); }; class k9DVDRead{ friend class k9DVDTitle; private: dvd_reader_t *m_dvd; QList m_files; QList m_ifos; void deleteIfos(); void deleteFiles(); public: k9DVDRead(); ~k9DVDRead(); void openDevice(const QString & _device); k9DVDFile *openIfo(uint _vts); k9DVDFile *openMenu(uint _vts); k9DVDFile *openTitle(uint _vts); k9Ifo2 *getIfo(int _num); QString getDiscId(); void close(); bool opened(); dvd_reader_t* getDvd() const { return m_dvd; } }; #endif k9copy/src/core/cmake_install.cmake0000664000175000017550000000225512412271774020107 0ustar emulatoremulator# Install script for directory: /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/src/core # Set the install prefix IF(NOT DEFINED CMAKE_INSTALL_PREFIX) SET(CMAKE_INSTALL_PREFIX "/usr/local") ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") # Set the install configuration name. IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) IF(BUILD_TYPE) STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") ELSE(BUILD_TYPE) SET(CMAKE_INSTALL_CONFIG_NAME "RelWithDebInfo") ENDIF(BUILD_TYPE) MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) # Set the component getting installed. IF(NOT CMAKE_INSTALL_COMPONENT) IF(COMPONENT) MESSAGE(STATUS "Install component: \"${COMPONENT}\"") SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") ELSE(COMPONENT) SET(CMAKE_INSTALL_COMPONENT) ENDIF(COMPONENT) ENDIF(NOT CMAKE_INSTALL_COMPONENT) # Install shared libraries without execute permission? IF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) SET(CMAKE_INSTALL_SO_NO_EXE "0") ENDIF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) k9copy/src/core/k9dvdprogress.cpp0000755000175000017550000000535612412271774017617 0ustar emulatoremulator/************************************************************************** * Developer: Pauline123 , (C) 2014 * Copyright (C) 2005 by Jean-Michel Petit * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "k9common.h" #include "k9dvdprogress.h" #include #include #include #if QT_VERSION >= 0x050000 #include #else #include #endif k9DVDProgress::k9DVDProgress(QWidget* ) { Ui_DVDProgress.setupUi(this); #if QT_VERSION >= 0x050000 setWindowTitle((i18n("DVD Analyze"))); #else setWindowTitle(KDialog::makeStandardCaption(i18n("DVD Analyze"),this)); #endif } k9DVDProgress::~k9DVDProgress(){ } /** No descriptions */ void k9DVDProgress::setpbTitleTotalSteps(unsigned int total){ Ui_DVDProgress.pbTitle->setMaximum(total); } /** No descriptions */ void k9DVDProgress::setpbTitleStep(unsigned int position){ Ui_DVDProgress.pbTitle->setValue(position); } /** No descriptions */ void k9DVDProgress::setpbTotalTotalSteps(int total){ Ui_DVDProgress.pbTotal->setMaximum(total); } /** No descriptions */ void k9DVDProgress::setpbTotalStep(int position){ Ui_DVDProgress.pbTotal->setValue(position); } /** No descriptions */ void k9DVDProgress::setlblTitle(QString & text){ Ui_DVDProgress.lblTitle->setText(text); } /** No descriptions */ void k9DVDProgress::setlblTotal(QString& text){ Ui_DVDProgress.lblTotal->setText(text); } void k9DVDProgress::closeEvent( QCloseEvent* ce ) { ce->ignore(); return; } k9copy/src/core/k9drawimage.cpp0000644000175000017550000000303212412271774017177 0ustar emulatoremulator// // C++ Implementation: k9drawimage // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "k9drawimage.h" #include #include k9DrawImage::k9DrawImage ( QWidget *parent ) : QWidget ( parent ) { m_repaint=false; connect ( &m_timer,SIGNAL ( timeout() ),this,SLOT ( timerDone() ) ); m_timer.start ( 500 ); } k9DrawImage::~k9DrawImage() { } void k9DrawImage::timerDone() { if ( m_repaint ) { update(); m_repaint=false; } } void k9DrawImage::setImage ( const QImage &_image ) { m_mutex.lock(); // m_pixmap=QPixmap::fromImage(_image); m_image=_image; m_mutex.unlock(); m_repaint=true; } void k9DrawImage::setImage ( QString _fileName ) { m_mutex.lock(); m_image.load ( _fileName ); m_mutex.unlock(); m_repaint=true; } void k9DrawImage::paintEvent ( QPaintEvent * ) { int top,left; QPainter p ( this ); if ( m_mutex.tryLock() ) { m_pixmap=QPixmap::fromImage ( m_image ); double wratio= ( double ) width() / ( double ) m_pixmap.width(); double hratio= ( double ) height() / ( double ) m_pixmap.height(); double ratio= wratio < hratio ? wratio:hratio; top = ( int ) ( height() -m_pixmap.height() *ratio ) /2+1; left = ( int ) ( width() -m_pixmap.width() *ratio ) /2 ; p.scale ( ratio,ratio ); p.drawPixmap ( ( int ) ( left/ratio ), ( int ) ( top/ratio ),m_pixmap ); m_repaint=false; m_mutex.unlock(); } } k9copy/src/core/k9saveimage.h0000644000175000017550000000207712412271774016655 0ustar emulatoremulator// // C++ Interface: k9saveimage // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9SAVEIMAGE_H #define K9SAVEIMAGE_H #include #include #include #include #include "k9fifo.h" #include /** @author Jean-Michel PETIT */ typedef enum { FrameType_B=0x18,FrameType_I=0x08,FrameType_P=0x10,FrameType_D=0x20} eFrameType; class k9DecodeThread; class k9SaveImage : public QThread { Q_OBJECT public: k9SaveImage(); ~k9SaveImage(); void play(); void stop(); void addData(uchar *_buffer, uint32_t _size); protected: void run(); public slots: void drawImage(QImage*); QString getFileName() ; private: k9DecodeThread *m_decoder; k9MemoryFifo m_fifo; bool m_stop; QTime m_timer; uint m_cpt; QTemporaryFile *m_tempFile; uchar *m_buffer; uint32_t m_size; QMutex m_mutex; QImage m_image; QString m_fileName; }; #endif k9copy/src/core/k9dialogs.cpp0000644000175000017550000001337612412271774016675 0ustar emulatoremulator/*************************************************************************** * Developer: Pauline123 , (C) 2014 * Copyright (C) 2007 by Jean-Michel * * jm_petit@laposte.net * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "k9dialogs.h" #include "k9common.h" #include #include #include #if QT_VERSION >= 0x050000 #include #include #include #include #else #include #include #include #include #endif #include #include "k9tools.h" #if QT_VERSION >= 0x050000 // Qt5 code #include #include #else // Qt4 code #endif QWidget * k9MainWidget; void k9Dialogs::setMainWidget(QWidget *_widget) { k9MainWidget=_widget; } QWidget* k9Dialogs::getMainWidget() { return k9MainWidget; } QString k9Dialogs::getOpenFileName (const QString &_initialDir,const QString &_filter,QWidget *_parent,const QString &_title) { #if QT_VERSION >= 0x050000 return QFileDialog::getOpenFileName ( _parent,_title,_initialDir,_filter); #else // Qt4 Code return KFileDialog::getOpenFileName (_initialDir,_filter, _parent,_title); #endif } QString k9Dialogs::getSaveFileName (const QString &_initialDir,const QString &_filter,QWidget *_parent,const QString &_title) { #if QT_VERSION >= 0x050000 return QFileDialog::getSaveFileName ( _parent,_title,_initialDir,_filter); #else // Qt4 Code return KFileDialog::getSaveFileName (_initialDir,_filter, _parent,_title); #endif } QString k9Dialogs::getExistingDirectory (const QString &_initialDir) { #if QT_VERSION >= 0x050000 return QFileDialog::getExistingDirectory(0,i18n("select a directory"),_initialDir); #else // Qt4 KDE4 Code return KFileDialog::getExistingDirectory (_initialDir); #endif } void k9Dialogs::error(const QString &_message,const QString &_title,const QStringList &_detail) { if (k9Tools::getBatchCopy()) { k9log::writeln(QString("Error : %1\n%2").arg(_message).arg(_detail.join("\n"))); return; } QWidget *activeWindow=QApplication::activeWindow(); if (activeWindow==0) activeWindow=k9MainWidget; QStringList body; body << ""+_message +"" << "" ; body << _detail; #if QT_VERSION >= 0x050000 QMessageBox message(QMessageBox::Critical,_title,_message,QMessageBox::Ok,activeWindow) ; message.exec(); #else KNotification *notify=KNotification::event(KNotification::Error,_title,body.join("
"),KIcon("k9copy").pixmap(48)); notify->setText(body.join("
")); notify->setTitle(_title); notify->sendEvent(); KMessageBox::errorList(activeWindow,_message,_detail,_title); #endif } void k9Dialogs::information(const QString &_message, const QString &_title) { if (k9Tools::getBatchCopy()) { k9log::writeln(QString("Information : %1").arg(_message)); return; } QWidget *activeWindow=QApplication::activeWindow(); if (activeWindow==0) activeWindow=k9MainWidget; #if QT_VERSION >= 0x050000 QMessageBox message(QMessageBox::Information,_title, _message, 0, activeWindow); message.exec(); #else KNotification *notify=KNotification::event(KNotification::Notification ,_title,_message,KIcon("k9copy").pixmap(48)); notify->sendEvent(); notify->activate(); KMessageBox::information(activeWindow,_message,_title); #endif } int k9Dialogs::warningContinueCancel(const QString & _message,const QString & _title,const QStringList &_detail) { QWidget *activeWindow=QApplication::activeWindow(); if (activeWindow==0) activeWindow=k9MainWidget; #if QT_VERSION >= 0x050000 QMessageBox message(QMessageBox::Warning,_title,_message,QMessageBox::Ignore | QMessageBox::Cancel,activeWindow); message.setButtonText(QMessageBox::Ignore, i18n("Continue")); int ret = message.exec(); if (ret == QMessageBox::Ignore) // Continue is 5 in KDE land... this Ignore must be 5, and Cancel is 1 {qDebug() << "Continue Clicked"; qDebug() << ret; return 5;} else {qDebug() << "Cancel Clicked"; qDebug() << ret; return 2;} #else return KMessageBox::warningContinueCancelList(activeWindow,_message,_detail,_title); #endif } bool k9Dialogs::getFont(QFont &font) { #if QT_VERSION >= 0x050000 bool ok; QFont res=QFontDialog::getFont ( &ok,font,k9MainWidget); if (ok) { font=res; return true; } else return false; #else int result= KFontDialog::getFont( font ); if (result==KFontDialog::Accepted) return true; else return false; #endif } k9copy/src/backup/0000755000175000017550000000000012417731553014607 5ustar emulatoremulatork9copy/src/backup/k9backupdlg.cpp0000644000175000017550000001550112412271774017514 0ustar emulatoremulator/*************************************************************************** * Developer: Pauline123 , (C) 2014 * Copyright (C) 2005 by Jean-Michel Petit * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "k9backupdlg.h" #include #include #include #include #include #if QT_VERSION >= 0x050000 // Qt 5 Code #include #include #else // Qt 4 Code #include #include #include #endif #include #include #include #include #include "k9drawimage.h" #if QT_VERSION >= 0x050000 #include #include #include #else #include #endif k9BackupDlg::k9BackupDlg(QWidget* parent) : QDialog(parent),k9InternalPlayer() { ui_backupDlg.setupUi(this); setModal(true); #if QT_VERSION >= 0x050000 setWindowTitle((i18n("Backup progression"))); #else setWindowTitle(KDialog::makeStandardCaption(i18n("Backup progression"),this)); #endif Abort=false; timer = new QTimer( this ); time.start(); connect( timer, SIGNAL(timeout()), this, SLOT(timerDone()) ); timer->start(500 ); totalCopied=0; m_progressTotal=0; m_progressLabel=""; m_totalSteps=0; m_factor=""; m_progress=0; // connect(&m_decoder, SIGNAL(pixmapReady(QImage *)), this, SLOT(drawPixmap(QImage *))); m_decoder.setBackupDlg(this); m_stop=false; m_playmovie=true; m_wimage=new k9DrawImage(ui_backupDlg.image); QGridLayout *l=new QGridLayout(ui_backupDlg.image); l->addWidget(m_wimage,0,0); #if QT_VERSION >= 0x050000 KGuiItem::assign(ui_backupDlg.bAbort, KStandardGuiItem::stop() ); #else ui_backupDlg.bAbort->setGuiItem(KStandardGuiItem::Stop); #endif #if QT_VERSION >= 0x050000 // Qt5 code QString aright=QStandardPaths::locate(QStandardPaths::GenericDataLocation, "k9copy/aright.png"); QString adown=QStandardPaths::locate(QStandardPaths::GenericDataLocation, "k9copy/adown.png"); #else // Qt4 code QString aright=KGlobal::dirs()->findResource( "data", QString("k9copy/aright.png")); QString adown=KGlobal::dirs()->findResource( "data", QString("k9copy/adown.png")); #endif ui_backupDlg.gbOutput->setStyleSheet("*::indicator:unchecked {image:url("+aright+"); } *::indicator:checked {image:url("+adown+"); } "); m_timer.start(); } void k9BackupDlg::drawImage(QImage *_image) { //m_wimage->setImage(*_image); static int cpt=0; if (cpt>4) { m_image=*_image; m_wimage->setImage(m_image); cpt=0; } else cpt++; } void k9BackupDlg::bPlayToggled( bool state) { m_playmovie=state; } void k9BackupDlg::gbOutputToggled(bool state) { m_playmovie=state; if (!state) { m_outputSize=ui_backupDlg.image->height(); this->resize(this->width(),this->height()-m_outputSize); m_outputSize-=ui_backupDlg.image->height(); this->setMaximumHeight(this->height()); } else { this->setMaximumHeight(32768); this->resize(this->width(),this->height()+m_outputSize); } k9Config config; config.setPrefShowOutput(state); config.save(); ui_backupDlg.image->setVisible(state); } void k9BackupDlg::playMovie(uchar *_data,uint32_t _size) { if (!m_playmovie || (m_timer.elapsed() <3000)) return;; if (m_mutex.tryLock()) { uint32_t maxSize=_size; for (uint32_t i=0;i< maxSize-2048;i+=2048) { m_decoder.addData(_data+i ,2048); } // m_decoder.Stop(); m_mutex.unlock(); } m_timer.restart(); } k9BackupDlg::~k9BackupDlg() { delete timer; } void k9BackupDlg::updateMe() { ui_backupDlg.lblStep->setText(m_progressLabel); ui_backupDlg.pbTotal->setValue(m_progressTotal); ui_backupDlg.pbStep->setMaximum(m_totalSteps); ui_backupDlg.lblFactor->setText(m_factor); ui_backupDlg.pbStep->setValue(m_progress); } void k9BackupDlg::timerDone() { m_mutex.lock(); QTime time2(0,0); time2=time2.addMSecs(time.elapsed()); QString remain("--:--:--"); if (m_progressTotal>0) { QTime time3(0,0); time3=time3.addMSecs((time.elapsed()/m_progressTotal)*ui_backupDlg.pbTotal->maximum()); remain=time3.toString("hh:mm:ss"); } ui_backupDlg.lblTime->setText(time2.toString("hh:mm:ss") +" / " +remain); updateMe(); m_mutex.unlock(); } void k9BackupDlg::setTotalSteps(uint32_t _totalSteps) { m_mutex.lock(); m_totalSteps=_totalSteps; m_mutex.unlock(); } void k9BackupDlg::setProgress(uint32_t _position) { m_mutex.lock(); m_progress=_position; m_mutex.unlock(); } void k9BackupDlg::setTotalMax(uint32_t _max) { m_mutex.lock(); ui_backupDlg.pbTotal->setMaximum(_max); m_mutex.unlock(); } void k9BackupDlg::setProgressTotal(uint32_t _position) { m_mutex.lock(); totalCopied+=_position; uint64_t total=totalCopied*2048; total/=(1024*1024); m_progressTotal=total; m_mutex.unlock(); } void k9BackupDlg::setProgressLabel(QString _text) { m_mutex.lock(); m_progressLabel=_text; update(); m_mutex.unlock(); } bool k9BackupDlg::getAbort() { return Abort; } void k9BackupDlg::bAbortClick() { Abort=true; close(); } void k9BackupDlg::setFactor(QString _factor) { m_mutex.lock(); m_factor=_factor; m_mutex.unlock(); } void k9BackupDlg::showEvent ( QShowEvent * ) { k9Config config; ui_backupDlg.gbOutput->setChecked(config.getPrefShowOutput()); } /*$SPECIALIZATION$*/ k9copy/src/backup/k9dvdauthor.h0000755000175000017550000000567612412271774017244 0ustar emulatoremulator/************************************************************************** * Copyright (C) 2005 by Jean-Michel Petit * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef K9DVDAUTHOR_H #define K9DVDAUTHOR_H #include "k9common.h" #include "k9dvd.h" #include "k9progress.h" #include #include #include #include #include /** *@author */ class k9DVDAuthor : public QObject { Q_OBJECT public: k9DVDAuthor(QObject *DVDStruct) ; ~k9DVDAuthor(); virtual void setworkDir( const QString& _newVal); virtual const QString& getworkDir(); virtual bool getError(); virtual void author(); virtual void setburnDVD( const bool& _newVal); virtual const bool& getburnDVD(); virtual QWidget *getDialog(){return progress;}; private: // Private attributes /** */ QTime *time; k9DVD* DVD; double factor; QDomDocument *xml; QString lastMsg,totSize,inject; QString m_tempPath; k9Process *proc; QString workDir; k9Progress *progress; bool cancelled; bool error; bool burnDVD; bool m_firsttitle; uint64_t m_totalSize; uint64_t m_forced,m_forcedsh; uint32_t m_copied,m_lastPos; QTemporaryFile *m_xml,*m_inject; QList files; void createXML(); void addTitle(QDomElement &root, k9DVDTitle *title); void createMenus(bool preview); void addMenus(QDomElement &titleSet); void processMenu(); void spumux(); void setProgress(long _position,long _total) ; int execProcess(); private slots: // Private slots /** No descriptions */ void DVDAuthorStderr(char *buffer, int buflen); void DVDAuthorStdout(char *buffer, int buflen); /** No descriptions */ void stopProcess(); }; #endif k9copy/src/backup/k9script.cpp0000644000175000017550000002611712412307773017070 0ustar emulatoremulator// // C++ Implementation: k9script // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9script.h" #include "k9dvd.h" #include "k9dvdtitle.h" #include "bswap.h" //PM DVDNAV #include "dvdread.h" #include "dvdread/dvd_reader.h" #include k9Script::k9Script(ifo_handle_t *_ifo, k9DVD *_dvd ) { m_ifo=_ifo; m_dvd=_dvd; } k9Script::~k9Script() {} vm_cmd_t *k9Script::GOTO(char line,char register1,char value) { uchar* cmd=(uchar*) &m_cmd; cmd[0]=0; cmd[1]=0xA1; cmd[2]=0; cmd[3]=register1; cmd[4]=0; cmd[5]=value; cmd[6]=0; cmd[7]=line; return &m_cmd; } vm_cmd_t *k9Script::GOTO(char line) { uchar* cmd=(uchar*) &m_cmd; cmd[0]=0; cmd[1]=0x01; cmd[2]=0; cmd[3]=0; cmd[4]=0; cmd[5]=0; cmd[6]=0; cmd[7]=line; return &m_cmd; } vm_cmd_t *k9Script::JUMPTT(char title,char register1,char register2) { uchar* cmd=(uchar*) &m_cmd; cmd[0]=0x30; cmd[1]=0x22; cmd[2]=0; cmd[3]=0; cmd[4]=0; cmd[5]=title; cmd[6]=register1; cmd[7]=register2; return &m_cmd; } vm_cmd_t *k9Script::JUMPVMGM_MENU() { uchar* cmd=(uchar*) &m_cmd; cmd[0]=0x30; cmd[1]=0x06; cmd[2]=0; cmd[3]=0; cmd[4]=0; cmd[5]=0x42; cmd[6]=0; cmd[7]=0; return &m_cmd; } vm_cmd_t *k9Script::CALLVMGM_MENU() { uchar* cmd=(uchar*) &m_cmd; cmd[0]=0x30; cmd[1]=0x08; cmd[2]=0; cmd[3]=0; cmd[4]=0x01; cmd[5]=0x42; cmd[6]=0; cmd[7]=0; return &m_cmd; } vm_cmd_t *k9Script::EXIT(char register1,char register2) { uchar* cmd=(uchar*) &m_cmd; cmd[0]=0x30; cmd[1]=0x21; cmd[2]=0; cmd[3]=0; cmd[4]=0; cmd[5]=0; cmd[6]=register1; cmd[7]=register2; return &m_cmd; } vm_cmd_t *k9Script::setGPRM(char numReg,uint16_t value) { uchar* cmd=(uchar*) &m_cmd; cmd[0]=0x71; cmd[1]=0; cmd[2]=0; cmd[3]=numReg; B2N_16(value); memcpy(cmd+4,&value,sizeof(uint16_t)); cmd[6]=0; cmd[7]=0; return &m_cmd; } vm_cmd_t *k9Script::setGPRMREG(char numReg,uint16_t value) { uchar* cmd=(uchar*) &m_cmd; cmd[0]=0x61; cmd[1]=0; cmd[2]=0; cmd[3]=numReg; B2N_16(value); memcpy(cmd+4,&value,sizeof(uint16_t)); cmd[6]=0; cmd[7]=0; return &m_cmd; } vm_cmd_t *k9Script::setSTN(char numAudio,char numSubpicture) { uchar* cmd=(uchar*) &m_cmd; cmd[0]=0x51; cmd[1]=0; cmd[2]=0; cmd[3]=numAudio==0 ? 0 : 0x80+numAudio-1; cmd[4]=numSubpicture==0 ? 0 : 0xC0+numSubpicture-1; cmd[5]=0; cmd[6]=0; cmd[7]=0; return &m_cmd; } vm_cmd_t *k9Script::setSTN(char numAngle) { uchar* cmd=(uchar*) &m_cmd; cmd[0]=0x51; cmd[1]=0; cmd[2]=0; cmd[3]=0; cmd[4]=0; cmd[5]=numAngle==0 ? 0 : 0x80+numAngle-1; cmd[6]=0; cmd[7]=0; return &m_cmd; } void k9Script::updatePGCIUT() { //first, free the old PGCIUT ifoFree_PGCI_UT(m_ifo); m_ifo->pgci_ut = (pgci_ut_t*) malloc(sizeof(pgci_ut_t)); pgci_ut_t* pgci_ut = m_ifo->pgci_ut; pgci_ut->zero_1=0; pgci_ut->nr_of_lus=1; pgci_ut->lu = (pgci_lu_t*) malloc(sizeof(pgci_lu_t)); pgci_lu_t *lu =pgci_ut->lu; uchar * lng=(uchar*) &(lu->lang_code); lng[0]='n'; lng[1]='e'; lu->lang_extension=0; lu->exists=0x80; pgcit_t *pgcit=(pgcit_t*) malloc(sizeof(pgcit_t)); lu->pgcit=pgcit; memset(pgcit,0,sizeof(pgcit_t)); pgcit->nr_of_pgci_srp=1; pgci_srp_t * srp=(pgci_srp_t*)malloc(sizeof(pgci_srp_t)); memset(srp,0,sizeof(pgci_srp_t)); pgcit->pgci_srp=srp; srp->entry_id=0x82; pgc_t *pgc=(pgc_t*)malloc(sizeof(pgc_t)); srp->pgc=pgc; memset(pgc,0,sizeof(pgc_t)); pgc_command_tbl_t * command_tbl=(pgc_command_tbl_t*) malloc(sizeof(pgc_command_tbl_t)); pgc->command_tbl=command_tbl; pgc->command_tbl_offset=1; memset(command_tbl,0,sizeof(pgc_command_tbl_t)); if (m_ifo->vmgi_mat != NULL) updatePGCIUT_VMG(command_tbl); else updatePGCIUT_VTS(command_tbl); } void k9Script::updateFPPGC() { ifoFree_FP_PGC(m_ifo); pgc_t*pgc=(pgc_t*)malloc(sizeof(pgc_t)); m_ifo->first_play_pgc=pgc; memset(pgc,0,sizeof(pgc_t)); pgc_command_tbl_t * command_tbl=(pgc_command_tbl_t*) malloc(sizeof(pgc_command_tbl_t)); pgc->command_tbl=command_tbl; pgc->command_tbl_offset=1; memset(command_tbl,0,sizeof(pgc_command_tbl_t)); // set GRPM(0)= First Title addPreCmd(command_tbl,JUMPTT(m_dvd->getstart()->getnumTitle(),0,0)); // jump VMGM Menu //addPreCmd(command_tbl,JUMPVMGM_MENU()); } void k9Script::updatePGC(pgc_t *_pgc ,int numVTS,int numPGC) { k9DVDTitle *title=NULL; for (int i=0; i gettitleCount();i++) { title=m_dvd->gettitle(i); if (title->getVTS()== numVTS && title->getTTN()==numPGC && title->getIndexed()) break; } pgc_command_tbl_t *command_tbl=_pgc->command_tbl; if (command_tbl ==NULL) { command_tbl=(pgc_command_tbl_t*) malloc(sizeof(pgc_command_tbl_t)); _pgc->command_tbl=command_tbl; _pgc->command_tbl_offset=1; memset(command_tbl,0,sizeof(pgc_command_tbl_t)); } if (numPGC==0) return; for (int i=0; i < command_tbl->nr_of_pre;i++) { //replace all JUMPs by a goto to the last line of cell commands ( link to next title) char *cmd=(char*)&(command_tbl->pre_cmds[i]); if (cmd[0]==0x30) { char NOP[8]={0,0,0,0,0,0,0,0}; memcpy(cmd,NOP,8); } } if (title->isSelected()) { char numSubP=0,numAudio=0; if (title->getDefSubtitle() !=NULL) numSubP=title->getDefSubtitle()->getnum(); if (title->getDefAudio() !=NULL) numAudio=title->getDefAudio()->getID(); if (numSubP+numAudio >0) { char *c=(char*)command_tbl->pre_cmds; bool binsert=false; if (c==NULL) binsert=true; else if ( *c==0x51) binsert=true; if (binsert) memcpy(command_tbl->pre_cmds,setSTN( numAudio,numSubP),8); else insertPreCmd(command_tbl,setSTN( numAudio,numSubP)); } } for (int i=0; i < command_tbl->nr_of_cell;i++) { //replace all JUMPs by a goto to the last line of cell commands ( link to next title) JumpVmg(&(command_tbl->cell_cmds[i])); } for (int i=0; i < command_tbl->nr_of_post;i++) { //replace all JUMPs by a goto to the last line of cell commands ( link to next title) JumpVmg(&(command_tbl->post_cmds[i])); } bool insertCall=true; if (command_tbl->nr_of_post !=0) { vm_cmd_t *cmd=&command_tbl->post_cmds[command_tbl->nr_of_post -1]; if (memcmp(cmd,CALLVMGM_MENU(),8)==0) insertCall=false; } if (insertCall) for (int i=0; i gettitleCount();i++) { k9DVDTitle *title=m_dvd->gettitle(i); if (title->getVTS()== numVTS && title->getTTN()==numPGC && title->isSelected() && title->getIndexed()) { addPostCmd(command_tbl,CALLVMGM_MENU()); break; } } } // replace the actual jump by a jump to he vmgm menu void k9Script::JumpVmg(vm_cmd_t * command) { char *cmd=(char*) command; if (cmd[0]==0x30) { cmd[1]=(cmd[1] & 0xF0) + 0x08; //0x20 =conditionnal jump cmd[2]=cmd[3]=0; cmd[4]=0x01; cmd[5]=0x42; } } void k9Script::updatePGCIUT_VTS(pgc_command_tbl_t *command_tbl) { addPreCmd( command_tbl, JUMPVMGM_MENU()); } void k9Script::updatePGCIUT_VMG(pgc_command_tbl_t *command_tbl) { command_tbl->nr_of_pre=0; command_tbl->pre_cmds=NULL; //initialisation of the registers for (int i=0;i<=15;i++) if (i!=1) addPreCmd( command_tbl,setGPRM( i,0)); addTitles(command_tbl); } void k9Script::addTitles(pgc_command_tbl_t *command_tbl) { char NOP[8]={0,0,0,0,0,0,0,0}; //Set GPRM(1) = current title (SPRM(4)) addPreCmd(command_tbl,setGPRMREG(1,0x84)); int nbSelected=0; for (int i=0;igettitleCount();i++) { k9DVDTitle *title=m_dvd->gettitle(i); if (title->isSelected() && title->getIndexed()) nbSelected++; } int a=0; for (int i=0;igettitleCount();i++) { k9DVDTitle *title=m_dvd->gettitle(i); if (title->isSelected() && title->getIndexed()) { //SI GPRM1=numTitle, GOTO i*3 addPreCmd(command_tbl,GOTO(16+nbSelected+a*3+2,1,title->getnumTitle())); a++; } } addPreCmd( command_tbl,EXIT(0,0)); for (int i=0;igettitleCount();i++) { k9DVDTitle *title=m_dvd->gettitle(i); if (title->isSelected() && title->getIndexed()) { //initialization of register 1 addPreCmd(command_tbl,setGPRM(1,0)); //set default subtitle and audio stream addPreCmd(command_tbl,(vm_cmd_t*)NOP); //jump to title if (title->getnextTitle()!=NULL) addPreCmd(command_tbl,JUMPTT(title->getnextTitle()->getnumTitle(),0,0)); else addPreCmd(command_tbl,EXIT(0,0)); } } } void k9Script::addPreCmd(pgc_command_tbl_t *command_tbl,vm_cmd_t *cmd) { command_tbl->nr_of_pre++; if (command_tbl->pre_cmds == NULL) command_tbl->pre_cmds=(vm_cmd_t*)malloc(sizeof(vm_cmd_t)); else command_tbl->pre_cmds=(vm_cmd_t*) realloc(command_tbl->pre_cmds,sizeof(vm_cmd_t)*command_tbl->nr_of_pre); memcpy(&(command_tbl->pre_cmds[command_tbl->nr_of_pre-1]),cmd,sizeof(vm_cmd_t)); } void k9Script::insertPreCmd(pgc_command_tbl_t *command_tbl,vm_cmd_t *cmd) { command_tbl->nr_of_pre++; if (command_tbl->pre_cmds == NULL) command_tbl->pre_cmds=(vm_cmd_t*)malloc(sizeof(vm_cmd_t)); else command_tbl->pre_cmds=(vm_cmd_t*) realloc(command_tbl->pre_cmds,sizeof(vm_cmd_t)*command_tbl->nr_of_pre); for (int i=command_tbl->nr_of_pre-2;i>=0;i--) { memcpy(&(command_tbl->pre_cmds[i+1]),&(command_tbl->pre_cmds[i]),sizeof(vm_cmd_t)); char *cmd=(char*)&(command_tbl->pre_cmds[i+1]); if (cmd[0]==0 && (cmd[1]&0x01==0x01)) cmd[7]++; } memcpy(&(command_tbl->pre_cmds[0]),cmd,sizeof(vm_cmd_t)); } void k9Script::addPostCmd(pgc_command_tbl_t *command_tbl,vm_cmd_t *cmd) { command_tbl->nr_of_post++; if (command_tbl->post_cmds == NULL) command_tbl->post_cmds=(vm_cmd_t*)malloc(sizeof(vm_cmd_t)); else command_tbl->post_cmds=(vm_cmd_t*) realloc(command_tbl->post_cmds,sizeof(vm_cmd_t)*command_tbl->nr_of_post); memcpy(&(command_tbl->post_cmds[command_tbl->nr_of_post-1]),cmd,sizeof(vm_cmd_t)); } void k9Script::addCellCmd(pgc_command_tbl_t *command_tbl,vm_cmd_t *cmd) { command_tbl->nr_of_cell++; if (command_tbl->cell_cmds == NULL) command_tbl->cell_cmds=(vm_cmd_t*)malloc(sizeof(vm_cmd_t)); else command_tbl->cell_cmds=(vm_cmd_t*) realloc(command_tbl->cell_cmds,sizeof(vm_cmd_t)*command_tbl->nr_of_cell); memcpy(&(command_tbl->cell_cmds[command_tbl->nr_of_cell-1]),cmd,sizeof(vm_cmd_t)); } k9copy/src/backup/k9dvdbackup.h0000755000175000017550000001175612412271774017203 0ustar emulatoremulator/*************************************************************************** * Copyright (C) 2005 by Jean-Michel Petit * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef K9DVDBACKUP_H #define K9DVDBACKUP_H #include "k9common.h" #include "k9cell.h" #include "k9cellcopylist.h" #include "k9dvdread.h" #include #include #include #include #include "k9dvdbackupinterface.h" /** @author Jean-Michel Petit */ class k9BackupDlg; class k9Ifo2; class k9TitleSet : public QObject { Q_OBJECT public: k9TitleSet(int _VTS); ~k9TitleSet(); uint32_t startSector; uint32_t lastSector; int VTS; uint32_t menuSize; k9CellList cells,menuCells; k9Cell*addCell(int _vts,int _pgc, int _vob); uint32_t getSize(); k9Ifo2 *ifoTitle; private: void clearCells(); }; class k9TitleSetList:public QVector { public: static bool compareItems ( k9TitleSet *item1, k9TitleSet *item2 ); }; class k9CadtList:public QList { public: static bool compareItems(cell_adr_t *item1,cell_adr_t *item2); }; class k9vamps; class k9DVDBackup : public k9DVDBackupInterface { Q_OBJECT public: k9DVDBackup(QObject *_dvd) ; ~k9DVDBackup(); virtual void setDevice(QString _device); virtual void setOutput(QString _output); virtual QString getErrMsg(); virtual void execute(); virtual bool geterror(); virtual void setWithMenus(bool _value); virtual QWidget *getDialog() {return (QWidget*)backupDlg;}; public slots: void getOutput(uchar *buffer,uint32_t size); void getOutput(eStreamType streamType,int streamNumber,uchar *buffer,uint32_t size){Q_UNUSED(streamType); Q_UNUSED(streamNumber); Q_UNUSED(buffer); Q_UNUSED(size);}; void setUserOps(bool theValue); protected: QString device; QString output; bool wrote; private: k9DVDRead *m_dvdread; bool m_copyMenu; bool m_withMenu; bool m_forcedFactor; bool m_userOps; k9DVD *DVD; QString errMsg; QString vampsMsg; QFile* outputFile; long cellSize; long currVTS; k9TitleSet *currTS; int currVOB; ifo_handle_t *m_ifo; k9Cell *currCell,*cellOut;//,*currCopyCell; k9CellCopyList *m_cellCopyList; uint32_t m_position,m_vmgSize; bool m_preserve; //uint64_t m_inbytes,m_outbytes; k9TitleSetList titleSets; float argFactor; uint64_t argSize; void prepareVTS(int VTS); void playCell (int vts_num, k9Cell *_cell,bool _empty=false); uint32_t findNextVobu(uint32_t _sector); uint32_t copyVobu(k9DVDFile *_fileHandle,uint32_t _startSector,k9Vobu *_vobu,bool _empty=false); void copyCell(int VTS, k9Cell *_cell,bool _empty); // void copyAngleBlock(k9CellCopyList *_list,uint _num); void copyEmptyPgc(int _vts,k9Cell *_cell); void updateVob(k9CellList *_cells); void updateIfo(); void updateMainIfo(); void updatePgci_ut(ifo_handle_t *_hifo); void update4Menu(ifo_handle_t *_hifo); void setDummyPack(uchar *_buffer); void setDummyNavPack(uchar *_buffer,uint32_t _sector); uint32_t copyMenu2(int _vts); k9CellList vmgCells; k9Vobu * remapVobu(uint32_t *value); k9Vobu * remapOffset(uint32_t _sector,uint32_t *offset,int dir); k9BackupDlg *backupDlg; uint getLastCell(k9CellCopyList *_cellCopyList,uint _index); void calcFactor(); void forceFactor(double _factor); bool error; void seterror(const QString &_msg); bool isAborted(); void setTotalSteps(uint32_t); void setTotalMax(uint32_t); void setProgress(uint32_t); void setProgressTotal(uint32_t); void setProgressLabel(QString); void showFactor(QString); uint32_t m_total,m_totalMax; k9vamps *vamps; QQueue vobuQueue; QMutex mutex; }; #endif k9copy/src/backup/k9script.h0000644000175000017550000000275712412271774016542 0ustar emulatoremulator// // C++ Interface: k9script // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9SCRIPT_H #define K9SCRIPT_H #include "k9common.h" /** @author Jean-Michel PETIT */ class k9DVD; class k9Script{ private: ifo_handle_t *m_ifo; k9DVD *m_dvd; vm_cmd_t m_cmd; protected: vm_cmd_t *JUMPTT(char title,char register1,char register2); vm_cmd_t *JUMPVMGM_MENU(); vm_cmd_t *GOTO(char line,char register1,char value); vm_cmd_t *GOTO(char line); vm_cmd_t *setGPRM(char numReg,uint16_t value); vm_cmd_t *setGPRMREG(char numReg,uint16_t value); vm_cmd_t *CALLVMGM_MENU(); vm_cmd_t *setSTN(char numAudio,char numSubpicture); vm_cmd_t *setSTN(char numAngle); vm_cmd_t *EXIT(char register1,char register2); void addPreCmd(pgc_command_tbl_t *command_tbl,vm_cmd_t *cmd); void insertPreCmd(pgc_command_tbl_t *command_tbl,vm_cmd_t *cmd); void addPostCmd(pgc_command_tbl_t *command_tbl,vm_cmd_t *cmd); void addCellCmd(pgc_command_tbl_t *command_tbl,vm_cmd_t *cmd); void updatePGCIUT_VMG(pgc_command_tbl_t *command_tbl); void updatePGCIUT_VTS(pgc_command_tbl_t *command_tbl); void JumpVmg(vm_cmd_t * cmd) ; void addTitles(pgc_command_tbl_t *command_tbl); public: k9Script(ifo_handle_t *_ifo,k9DVD *_dvd); void updatePGCIUT(); void updateFPPGC(); void updatePGC(pgc_t *_pgc,int numVTS,int numPGC); ~k9Script(); }; #endif k9copy/src/backup/k9mp4enc.cpp0000644000175000017550000007726212412271774016762 0ustar emulatoremulator// // C++ Implementation: k9mp4enc // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9mp4enc.h" #include "k9mp4dlg.h" #include #include #include #include #include "k9tools.h" #include "k9audiocodecs.h" #include "k9videocodecs.h" #include "k9convertaudio.h" #include #include "k9dialogs.h" #include #include #include "k9ifo2.h" #include "k9cell.h" #include "k9vamps.h" #include "k9log.h" #include #include #if QT_VERSION >= 0x050000 //Qt 5 Code #ifndef FALSE #define FALSE (0) #endif #ifndef TRUE #define TRUE (!FALSE) #endif #include #else // Qt 4 Code #include #endif #define BASE_CONV_AUDIO 0 #define BASE_CONV_VIDEO 10 k9MP4Enc::k9MP4Enc(QObject *parent) : k9DVDBackupInterface(parent) { m_fourcc=m_height=m_width=m_audioBitrate=m_videoBitrate=m_filename=""; m_codec=0; //lavc_mp4; m_audioCodec=0; m_cpt=-1; m_parts=1; m_mpeg2=false; m_extractAudio=false; m_extractMkv=false; m_extractSubtitle=false; QStringList laudio; QStringList llabels; QStringList lvideo; k9Config config; m_splitChapters=config.getMpegChapters(); m_ffmpegPath=config.getPrefFFmpegPath(true); m_mencoderPath=config.getPrefMencoderPath(true); timer = new QTimer( this ); connect( timer, SIGNAL(timeout()), this, SLOT(timerDone()) ); m_progress=new k9MP4Dlg(k9Dialogs::getMainWidget()); m_progress->setModal(true); } QString k9MP4Enc::round16(QString _wh) { if (_wh !="") { int value=_wh.toInt()/16; return QString::number(value*16); } else return _wh; } QString k9MP4Enc::getChapterList(k9DVDTitle *_title) { QString res=""; QList chapters=_title->getChapters(); foreach (k9DVDChapter *chapter ,chapters) { QTime t; long l=t.msecsTo(chapter->getLength()); if (chapter->getSelected() && l>1 ) { res+=res=="" ? QString::number( chapter->getnum()) : ","+QString::number( chapter->getnum()); } } QList titles=_title->getTitles(); foreach (k9DVDTitle *title,titles) { chapters=title->getChapters(); foreach (k9DVDChapter *chapter,chapters) { if (chapter->getSelected()) { res+=res=="" ? QString::number( chapter->getnum()) : ","+QString::number( chapter->getnum()); } } } return res; } int k9MP4Enc::getselectedSubp(k9DVDTitle *_title) { for (int i=0;i< _title->getsubPictureCount();i++) { if (_title->getsubtitle( i)->getselected()) { return _title->getsubtitle(i)->getID().first()-1; } } //nos subtitle selected return -1; } bool k9MP4Enc::check() { if (m_mpeg2) return true; QString sCodecA,sCodecV; k9AudioCodecs *audioCodecs=new k9AudioCodecs(0); sCodecA=audioCodecs->getEncoder(m_audioCodec); if (m_extractAudio && sCodecA !="ffmpeg") { k9log::add(i18n("Audio extraction can only be done with ffmpeg"),k9logLevel::ERROR); k9Dialogs::error(i18n("Audio extraction can only be done with ffmpeg"),i18n("Encoding error")); return false; } k9VideoCodecs *videoCodecs=new k9VideoCodecs(0); sCodecV=videoCodecs->getEncoder (m_codec); if (m_extractMkv && sCodecV!="ffmpeg") { k9log::add(i18n("Matroska encoding can only be done with ffmpeg"),k9logLevel::ERROR); k9Dialogs::error(i18n("Matroska encoding can only be done with ffmpeg"),i18n("Encoding error")); return false; } if (!m_extractAudio) { if ( ! k9Tools::checkProgram(sCodecV) ) { k9log::add(i18n("Unable to run %1").arg(sCodecV),k9logLevel::ERROR); k9Dialogs::error (i18n("Unable to run %1").arg(sCodecV) , i18n("Encoding error")); m_error = TRUE; return false; } } if ((sCodecA!=sCodecV) || m_extractAudio) { if ( ! k9Tools::checkProgram(sCodecA) ) { k9log::add(i18n("Unable to run %1").arg(sCodecV),k9logLevel::ERROR); k9Dialogs::error (i18n("Unable to run %1").arg(sCodecA) , i18n("Encoding error")); m_error = TRUE; return false; } } return true; } void k9MP4Enc::execute(k9DVDTitle *_title) { if (m_mpeg2) k9log::add(i18n("Starting extraction of %1, chapters %2").arg(_title->getname()).arg(getChapterList( _title)),k9logLevel::INFO); else k9log::add(i18n("Starting encoding of %1, chapters %2").arg(_title->getname()).arg(getChapterList( _title)),k9logLevel::INFO); k9log::add(i18n("source : %1").arg(m_device),k9logLevel::INFO); k9log::add(i18n("destination : %1").arg(m_filename),k9logLevel::INFO); k9log::add(i18n("disk cache : %1").arg( m_usecache ? i18n("activated"):i18n("disabled")),k9logLevel::INFO); m_currentChapter=0; m_error=false; m_outputFile=NULL; m_converters[BASE_CONV_VIDEO]=NULL; if (m_mpeg2 || m_extractAudio) { m_parts=1; m_2pass=false; } m_error = !check(); if (m_error) return; time = new QTime(0,0); m_percent=m_totalBytes=m_offset=0; m_remain="--:--:--"; m_totalSize=_title->getChaptersSize(true); k9log::add(i18n("size : %1 MB").arg(m_totalSize/512),k9logLevel::INFO); if (!m_mpeg2) { k9log::add(i18n("audio bitrate : %1").arg(m_audioBitrate),k9logLevel::INFO); if (!m_extractAudio) { if (m_videoBitrate !="") k9log::add(i18n("user defined video bitrate : %1").arg(m_videoBitrate),k9logLevel::INFO); else k9log::add(i18n("calculated video bitrate : %1").arg(getBitRate(_title)),k9logLevel::INFO); } } QString injectName; k9Config config; injectName=config.getPrefOutput()+"/k9v"+k9Tools::randomFileName()+".tmp"; int maxPass=0; int pass=0; //build the cell list for mpeg2 extraction QMultiMap chapterCells; QStringList chapters; for ( m_part =1 ; (m_part <=m_parts) && !m_error ;m_part++) { if (m_2pass) { maxPass=2; pass=1; } QString passLogFileName; k9Config config; passLogFileName=QDir::cleanPath(config.getPrefOutput()+"/k9v"+k9Tools::randomFileName() +".temp"); m_passLogFile=passLogFileName; do { if (!m_mpeg2) k9log::add(i18n("starting pass %1 of %2").arg(pass==0 ? 1:pass).arg(maxPass==0 ? 1 : maxPass),k9logLevel::INFO); m_totalBytes=0; m_vamps=new k9vamps(this,m_usecache);; m_player=new k9play(this); uint32_t nbSectors= m_totalSize / m_parts ; uint32_t startSector= nbSectors*(m_part-1); uint32_t endSector= startSector+nbSectors; m_stderr=""; m_title=_title; if (m_width=="") { m_width=_title->getwidth(); } if (m_width.toInt() % 2 !=0) m_width=QString::number(m_width.toInt()+1); double h=(double)_title->getheight().toInt(); double w=(double)_title->getwidth().toInt(); double ratio=( m_width.toDouble()/w); k9VideoCodecs videoCodecs; // if a cropping zone has been defined, the aspect ratio is based on it else we keep // the original aspect ratio if ((m_crop.height() != (int) h) || (m_crop.width() !=(int) w)) { // n is the ratio between the video resolution and the rendering aspect ratio double n; if (_title->getaspectRatio() =="16:9") n=(16.0 *h)/(9.0*w); else n=(4.0 *h)/(3.0*w); m_aspect=QString::number(n*( (double)m_crop.width()/(double)m_crop.height())); } else m_aspect=_title->getaspectRatio(); if (videoCodecs.getEncoder(m_codec)=="mencoder") m_aspect=m_aspect.replace(":","/"); if (m_height=="" || m_height=="0") { double height=h*ratio; m_height=QString::number((int)round(height+0.1)); //with mencoder, video is resized after the cropping has been applied //=> height=height - (cropheight*aspectratio) if (videoCodecs.getEncoder(m_codec)=="mencoder") m_height= QString::number((int)(m_height.toInt() -(h-m_crop.height())*ratio)); } if (videoCodecs.getEncoder(m_codec)=="ffmpeg") { //with ffmpeg, crop is applied on the resized video => crop size must be calculated according to ratio QRect newrect(m_crop.left()*ratio,m_crop.top()*ratio,m_crop.width()*ratio,m_crop.height()*ratio); m_crop=newrect; } if (m_height.toInt()%2 !=0) m_height=QString::number(m_height.toInt()+1); if (m_audioBitrate=="") m_audioBitrate="128"; if (m_size=="") m_size="700"; if (m_filename=="") m_filename=k9Dialogs::getSaveFileName (QDir::homePath(),"*.avi", 0,i18n("Save file to disk")); if (m_filename =="") return; QDir d=QDir::root(); if (d.exists(m_filename)) d.remove(m_filename); m_progress->setbitrate(QString::number(getBitRate(_title))); if (! m_videoBitrate.isEmpty()) { if (!m_mpeg2 && !m_extractAudio && !m_extractMkv) { m_progress->setsize(QString::number(m_parts) +" * "+m_size +i18n("MB")); } else m_progress->setsize(m_size +i18n("MB") ); } else m_progress->setsize(""); m_player->setendSector(QString::number(endSector)); QStringList cmd; m_player->setinject(injectName); m_player->setDevice(m_device); m_player->setTitle(_title->getnumTitle()); m_player->setchapterList(getChapterList( _title)); if (m_part==1 || m_mpeg2 ||m_extractAudio ) { m_player->setinitStatus(true); m_player->setcontinue(false); } else { m_player->setcontinue(true); m_player->setinitStatus(false); } if (pass==1) m_player->setfirstPass(true); else m_player->setfirstPass(false); if (pass !=1) { QStringList streams; for (int i=0;i<_title->getaudioStreamCount();i++) { if (_title->getaudioStream(i)->getselected()) { streams <getaudioStream(i)->getID()); } } if (streams.count() >0) m_player->setaudioFilter(streams.join(",")); if (getselectedSubp( _title) !=-1) { streams.clear(); for (int i=0; i<_title->getsubPictureCount();i++) { if (_title->getsubtitle(i)->getselected()) { streams << QString::number(_title->getsubtitle(i)->getID().first()); } } m_player->setsubpictureFilter(streams.join(",")); } } m_player->setuseCache(m_usecache); if (m_mpeg2) { m_progress->setbitrate("--"); double size; if (_title->getforceFactor()) { size = _title->getChaptersSize_mb(true)/_title->getfactor(); m_player->setvampsFactor(QString::number(_title->getfactor())); m_player->setforcedFactor(true); } else size = _title->getChaptersSize_mb(true); m_progress->setsize(QString::number(size) +i18n("MB")); if (!m_splitChapters) { m_outputFile=new QFile(m_filename); //removes an existing file; m_outputFile->remove(); m_outputFile->open(QIODevice::WriteOnly); } } else if (m_extractAudio) { // m_offset+=m_totalBytes; // buildAudioCmd(_title); if (!m_splitChapters) buildAudioCmd(_title); } else { //cmd << "-of" << "avi"; if (m_extractSubtitle && pass!=1) buildSubtitleCmd(_title); buildVideoCmd(pass,m_part,_title,passLogFileName,cmd); } if ((m_parts >1 ) && (m_mpeg2|| m_extractAudio)) ++ichapterCells; time->start(); connect(m_progress,SIGNAL(sigCancel()),this,SLOT(slotCancel())); m_canceled=false; m_progress->show(); timer->start(500); //connect(m_player,SIGNAL(sigPosition(uint, uint)),this,SLOT(getPosition(uint, uint))); QEventLoop eventLoop; //enters an new event loop which is stopped at end of the playing thread m_eventLoop= &eventLoop; m_player->setEventLoop(&eventLoop); m_player->execute(); Flush(); foreach (k9ConvertAudio *c,m_converters) { if (c) { c->end(true); } } foreach(k9Subtitle2Pgm *s,m_subtitles) { if (s) { s->end(); } } qDeleteAll(m_subtitles); if (m_canceled) { m_error=true; } if (maxPass >0) pass++; delete m_player; m_player = NULL; } while (pass<=maxPass && !m_error && m_2pass && !m_canceled); if (!m_canceled) m_offset+=m_totalBytes+ (m_vamps !=NULL ? m_vamps->getSkippedBytes():0); } if (m_mpeg2 && m_outputFile) { m_outputFile->close(); delete m_outputFile; } foreach (k9ConvertAudio *c,m_convertersToDelete) { c->end(); delete c; } QFile::remove(injectName); if (!m_msgError.isEmpty()) k9Dialogs::error (m_msgError, i18n("Encoding error"),m_ErrorDetail); } void k9MP4Enc::buildSubtitleCmd(k9DVDTitle *title) { for (int i=0; i< title->getsubPictureCount();i++) { if (title->getsubtitle(i)->getselected()) { QStringList cmd; QString path=QDir::cleanPath( QString("%1/title%2-part%3-subtitle%4%5").arg(m_filename).arg(m_title->getnumTitle()).arg(m_part).arg(i+1).arg("")); QString path2=QDir::cleanPath( QString("%1/title%2-part%3-subtitle%4%5").arg(m_filename).arg(m_title->getnumTitle()).arg(m_part).arg(i+1).arg("mpg")); QFile::remove(path+".sub"); QFile::remove(path+".idx"); k9Subtitle2Pgm *subtitle2pgm=new k9Subtitle2Pgm(this); m_subtitles[title->getsubtitle(i)->getID().first()]=subtitle2pgm; subtitle2pgm->setBaseName(path); for (int ipalette=0;ipalette<16;ipalette++) { QString s; title->getpalette(ipalette,s); subtitle2pgm->setPalette(ipalette,s.toUInt()); } subtitle2pgm->setLangCod(title->getsubtitle(i)->getlangCod()); subtitle2pgm->setTrackCod(0x20+title->getsubtitle(i)->getID().first()-1); k9ResultingFile *rf=new k9ResultingFile(this); rf->title=m_title->getnumTitle(); rf->filename=path+".idx"; rf->subtitle=true; m_resultingFiles.insert(rf->title,rf); } } } void k9MP4Enc::buildAudioCmd(k9DVDTitle *title) { k9AudioCodecs *audioCodecs=new k9AudioCodecs(0); m_encoder=FFMPEG; for (int i=0;igetaudioStreamCount();i++) { if (title->getaudioStream(i)->getselected()) { k9DVDAudioStream *stream = title->getaudioStream(i); QStringList cmd; QString sCodec=""; sCodec=audioCodecs->getCodecName(m_audioCodec); QString sAOption=replaceParams(audioCodecs->getOptions(m_audioCodec)).trimmed(); m_progress->setTitleLabel(i18n("Encoding %1").arg(sCodec)); QString path,ext=audioCodecs->getExtension(m_audioCodec) ; if (!ext.startsWith(".")) ext="."+ext; QDir().mkpath(m_filename); path=QDir::cleanPath( QString("%1/title%2-part%3-audio%4-%6-%5").arg(m_filename).arg(m_title->getnumTitle()).arg(m_currentChapter).arg(i+1).arg(ext).arg(stream->getlanguage()) ); QFile::remove(path); cmd << m_ffmpegPath << "-i" << "/dev/stdin" <getOptions1(m_codec)); break; case 2: sVOption=replaceParams(videoCodecs->getOptions2(m_codec)); break; default: sVOption=replaceParams(videoCodecs->getOptions0(m_codec)); break; } sCodec=videoCodecs->getCodecName(m_codec); sVOption=sVOption.trimmed(); cmd << m_ffmpegPath << "-i" << "/dev/stdin"; cmd << sVOption.split(" "); if (pass >0) m_progress->setTitleLabel(i18n("Encoding %1").arg(sCodec)+" - "+i18n("pass %1").arg(pass)); else m_progress->setTitleLabel(i18n("Encoding %1").arg(sCodec)); if (m_fourcc !="") cmd << "-vtag" << m_fourcc; else if (videoCodecs->getFourcc(m_codec)!="") cmd << "-vtag" << videoCodecs->getFourcc(m_codec); QString sAOption=""; sAOption=replaceParams(audioCodecs->getOptions(m_audioCodec)).trimmed(); QStringList slNewAudio; delete audioCodecs; delete videoCodecs; bool audio=false; //looking for first audio selected int nbAudio=0; if (m_pass != 1 ) { for (int i=0;igetaudioStreamCount();i++) { if (title->getaudioStream(i)->getselected()) { if (nbAudio>0) slNewAudio << "-newaudio"; else cmd << sAOption.split(" "); audio=true; nbAudio++; } } } QString path=m_filename; if (m_pass==1) { path="/dev/null"; } else if (m_extractMkv) { QString ext(".avi"); QDir().mkpath(m_filename); path=QDir::cleanPath( QString("%1/title%2-part%3-video%4").arg(m_filename).arg(m_title->getnumTitle()).arg(m_part).arg(ext)); QFile::remove(path); k9ResultingFile *rf=new k9ResultingFile(this); rf->title=m_title->getnumTitle(); rf->filename=path; rf->video=true; m_resultingFiles.insert(rf->title,rf); }else { if (m_parts>1) { QString ext=m_filename.section(".",-1); if (ext!="") ext="."+ext; path=m_filename.left(m_filename.length()-ext.length()); path=path+QString::number(m_part)+ext; } } if (path.toUpper().endsWith("MPEG") || path.toUpper().endsWith("MPG")) cmd << "-f" << "mpeg"; else if (path.toUpper().endsWith("AVI") || m_pass==1) cmd << "-f" << "avi"; else { // cmd << "-of" << "lavf"; // cmd << "-lavfopts" << "i_certify_that_my_video_stream_does_not_use_b_frames"; } //synchronize audio cmd << "-async" << "44100" ; cmd << "-y" << KShell::quoteArg(path); cmd << slNewAudio; // if (m_extractMkv) { k9log::add(i18n("starting thread : %1").arg(cmd.join(" ")),k9logLevel::INFO); k9ConvertAudio *converter=new k9ConvertAudio("",cmd); //converter->setDebug(true); m_converters[BASE_CONV_VIDEO]=converter; m_convertersToDelete << converter; if (m_extractMkv && m_pass!=1) for (int i=0;igetaudioStreamCount();i++) if (title->getaudioStream(i)->getselected()) m_converters[BASE_CONV_AUDIO+i]=converter; // } } void k9MP4Enc::buildMEncoderCmd(int pass,int part,k9DVDTitle *title,const QString &passLogFileName,QStringList &cmd) { m_encoder=FFMPEG; bool audio=false; QString sPass=""; QString sCodec=""; k9AudioCodecs *audioCodecs=new k9AudioCodecs(0); k9VideoCodecs *videoCodecs=new k9VideoCodecs(0); QString sVOption; m_pass=pass; switch (pass) { case 1: sVOption=replaceParams(videoCodecs->getOptions1(m_codec)); break; case 2: sVOption=replaceParams(videoCodecs->getOptions2(m_codec)); break; default: sVOption=replaceParams(videoCodecs->getOptions0(m_codec)); break; } sCodec=videoCodecs->getCodecName(m_codec); sVOption=sVOption.trimmed(); int pos; cmd << m_mencoderPath << "/dev/stdin"; if (pass >0) cmd << "-passlogfile" << passLogFileName; cmd << sVOption.split(" "); QString sAOption=""; sAOption=replaceParams(audioCodecs->getOptions(m_audioCodec)).trimmed(); if (pass >0) m_progress->setTitleLabel(i18n("Encoding %1").arg(sCodec)+" - "+i18n("pass %1").arg(pass)); else m_progress->setTitleLabel(i18n("Encoding %1").arg(sCodec)); if (m_fourcc !="") cmd << "-ffourcc" << m_fourcc; else if (videoCodecs->getFourcc(m_codec)!="") cmd << "-ffourcc" << videoCodecs->getFourcc(m_codec); delete audioCodecs; delete videoCodecs; //looking for first audio selected for (int i=0;igetaudioStreamCount();i++) { if (title->getaudioStream(i)->getselected()) { //cmd << "-oac" << sAOption; pos=sAOption.indexOf("-af"); if (pos==-1) cmd << "-af" <1) { QString ext=m_filename.section(".",-1); if (ext!="") ext="."+ext; path=m_filename.left(m_filename.length()-ext.length()); path=path+QString::number(part)+ext; } if (pass==1) cmd << "-o" << "/dev/null"; else cmd <<"-o" << KShell::quoteArg(path); if (path.toUpper().endsWith("MPEG") || path.toUpper().endsWith("MPG")) cmd << "-of" << "mpeg"; else if (path.toUpper().endsWith("AVI")) cmd << "-of" << "avi"; else { // cmd << "-of" << "lavf"; // cmd << "-lavfopts" << "i_certify_that_my_video_stream_does_not_use_b_frames"; } k9log::add(i18n("starting thread : %1").arg(cmd.join(" ")),k9logLevel::INFO); k9ConvertAudio *converter=new k9ConvertAudio("",cmd); converter->setDebug(false); m_converters[BASE_CONV_VIDEO]=converter; m_convertersToDelete << converter; } void k9MP4Enc::slotCancel() { k9log::add(i18n("cancel requested"),k9logLevel::WARNING); m_canceled=true; timer->stop(); m_player->abort(); foreach (k9ConvertAudio *c,m_converters) { if (c) { c->end(false); } } } QString k9MP4Enc::replaceParams(QString _value) { QString str=_value; str.replace("$PASSLOGFILE",m_passLogFile); str.replace("$PASS",QString::number(m_pass)); str.replace("$WIDTH",m_width); str.replace("$HEIGHT",m_height); str.replace("$VIDBR",QString::number(getBitRate(m_title))); str.replace("$AUDBR",m_audioBitrate); int c=m_crop.top(); if (c%2 !=0) c++; str.replace("$CROPTOP",QString::number(c)); c=m_crop.left(); if (c%2 !=0) c++; str.replace("$CROPLEFT",QString::number(c)); c=m_height.toInt()- m_crop.bottom()-1; if (c%2 !=0) c++; str.replace("$CROPBOTTOM",QString::number(c)); c=m_width.toInt()-m_crop.right()-1; if (c%2 !=0) c++; str.replace("$CROPRIGHT",QString::number(c)); str.replace("$CROPWIDTH",QString::number(m_crop.width())); str.replace("$CROPHEIGHT",QString::number(m_crop.height())); //str.replace("$ASPECT",QString::number((double)m_crop.width()/(double)m_crop.height())); str.replace("$ASPECT",m_aspect); return str; } int k9MP4Enc::getBitRate(k9DVDTitle *_title) { // bitrate video = (MB *8388.608) /SEC - bitrate audio if (m_videoBitrate!="") { m_progress->setsize(""); return m_videoBitrate.toInt(); } else { int size=m_size.toInt(); float titleSize=_title->getChaptersSize_mb( true); if ( titleSize< (float)size) size=(int)(titleSize/m_parts) ; m_progress->setsize(QString::number(m_parts)+" * " +QString::number(size) +i18n("MB") ); QTime t1(0,0); int sec=t1.secsTo(_title->getSelectedLength()); if (sec==0) return 0; int nbAudioStreams=0; for (int i=0;i<_title->getaudioStreamCount();i++) if (_title->getaudioStream(i)->getselected()) nbAudioStreams++; nbAudioStreams=1; int bitrate=((8*size*m_parts*1024)-(m_audioBitrate.toInt()*nbAudioStreams*sec))/sec; // qDebug() << "bitrate:" << bitrate << " sec:" <setfps(m_converters[BASE_CONV_VIDEO]->getFps()); if (m_totalSize !=0) { m_percent=(float)(m_offset+m_totalBytes+( m_vamps!=NULL? m_vamps->getSkippedBytes():0)) / (float)m_totalSize; // qDebug() <<"offset" << m_offset << " total readen:" << m_totalBytes << " total skipped : " << (m_vamps!=NULL? m_vamps->getSkippedBytes():0) << " total title :" << m_totalSize << "percent" << m_percent; } QTime time2(0,0); time2=time2.addMSecs(time->elapsed()); if (m_percent>0) { QTime time3(0,0); time3=time3.addMSecs((uint32_t)(time->elapsed()*(1/m_percent))); m_remain=time3.toString("hh:mm:ss"); } m_percent*=100; m_progress->setProgress((int)m_percent); m_progress->setremain(time2.toString("hh:mm:ss") +" / " +m_remain); m_progress->setImage(m_player->getSaveImage()->getFileName()); // m_progress->Update(); } } bool k9MP4Enc::isCanceled() { return (m_canceled || m_error); } void k9MP4Enc::getOutput(eStreamType streamType,int streamNumber,uchar *buffer,uint32_t size) { if (isCanceled()) return; if ((streamType==NAV) && !m_mpeg2) { pci_t pci_pack; k9Ifo2::navRead_PCI(&pci_pack,buffer-14+ 0x2d); k9DVDChapter *ch=m_title->getChapterFromSector(pci_pack.pci_gi.nv_pck_lbn); bool chapterChanged=ch->getnum()!=m_currentChapter; m_currentChapter=ch->getnum(); if (m_extractAudio && m_splitChapters && chapterChanged) { foreach( k9ConvertAudio *c, m_convertersToDelete) { if (!c->isRunning()) { m_convertersToDelete.removeOne(c); delete c; } } foreach (k9ConvertAudio *c,m_converters) { if (c) { c->end(false); } } buildAudioCmd(m_title); } } if (m_converters.contains(streamNumber -1 +BASE_CONV_AUDIO ) && (streamType==AUDIO)) { k9ConvertAudio *c=m_converters[BASE_CONV_AUDIO -1 +streamNumber]; if (!c->Error()) c->addData(buffer,size); else { m_player->setAborted(true); m_error=true; m_msgError=i18n("An error occured while encoding the %1 stream").arg(i18n("audio")); m_ErrorDetail=c->getOutput(); k9log::add(m_msgError,k9logLevel::ERROR); } } if (streamType==NAV) { foreach(k9Subtitle2Pgm *sub,m_subtitles) { sub->addData(buffer,size); } } //bool copyNav=(m_encoder==FFMPEG ) && (streamType==NAV); bool copyNav=(streamType==NAV); if ((streamType==VIDEO || copyNav) ||( !m_mpeg2 && !m_extractAudio && !m_extractMkv)) { k9ConvertAudio *c=m_converters[BASE_CONV_VIDEO]; if (c) { if (!c->Error()) c->addData(buffer,size); else { m_player->setAborted(true); m_error=true; m_msgError=i18n("An error occured while encoding the %1 stream").arg(i18n("video")); m_ErrorDetail=c->getOutput(); k9log::add(m_msgError,k9logLevel::ERROR); } } } if ((streamType==SUBPICTURE) && (m_subtitles.contains(streamNumber))) { m_subtitles[streamNumber]->addData(buffer,size); } } void k9MP4Enc::getOutput(uchar *buffer,uint32_t size) { m_totalBytes+= size/2048 ; if (m_mpeg2 ) { //waiting for free space in the fifo buffer (readen by mencoder process) m_fifo.addData(buffer,size); //Exits the eventloop executed by flush when fifo buffer is empty m_eventLoop->exit(); } } void k9MP4Enc::Flush() { QIODevice *output; if (!m_splitChapters) output=m_outputFile; else output=NULL; uchar buffer[40960]; int size; do { while (m_fifo.count()>0 ) { size=m_fifo.readData(buffer,2048); if (m_mpeg2 && m_splitChapters && k9Cell::isNavPack(buffer)) { pci_t pci_pack; k9Ifo2::navRead_PCI(&pci_pack,buffer+ 0x2d); k9DVDChapter *ch=m_title->getChapterFromSector(pci_pack.pci_gi.nv_pck_lbn); if ((ch->getnum() != m_currentChapter) || !output) { m_currentChapter=ch->getnum(); QString path=m_filename; QString ext=m_filename.section(".",-1); if (ext!="") ext="."+ext; path=m_filename.left(m_filename.length()-ext.length()); //path=QString("%1-chapter%2-cell%3%4").arg(path).arg(ichapterCells.key()).arg(ichapterCells.value()).arg(ext); path=QString("%1-chapter%2%3").arg(path).arg(m_currentChapter).arg(ext); if (m_outputFile) m_outputFile->close(); m_outputFile=new QFile(path); //removes an existing file; m_outputFile->remove(); m_outputFile->open(QIODevice::WriteOnly); output=m_outputFile; } } if (output) output->write((char*)buffer,size); } if (!m_player->terminated() && !m_canceled) m_eventLoop->exec(); } while (!m_player->terminated() && !m_canceled && m_mpeg2); m_player->wait(); } k9MP4Enc::~k9MP4Enc() { delete m_progress; } QMultiMap< int, k9ResultingFile* > k9MP4Enc::getResultingFiles() const { return m_resultingFiles; } void k9MP4Enc::setSplitChapters(bool theValue) { m_splitChapters = theValue; } k9copy/src/backup/k9convertaudio.h0000644000175000017550000000267612412271774017740 0ustar emulatoremulator// // C++ Interface: k9convertaudio // // Description: // // // Author: <>, (C) 2008 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9CONVERTAUDIO_H #define K9CONVERTAUDIO_H #include "k9common.h" #include #include "k9fifo.h" #include #include class k9ConvertAudio: public QThread { Q_OBJECT public: k9ConvertAudio(const QString &_output,const QStringList &_cmd) ; ~k9ConvertAudio(); void addData(uchar *_buffer,int _size); void end(bool _wait=true); static void test(); QString getFps() const; void setFps(const QString& theValue); QStringList getCmd() const; void setDebug(bool theValue); protected: virtual void run(); public slots: void finished ( int exitCode, QProcess::ExitStatus exitStatus ); bool Error() const; QStringList & getOutput() ; private: k9Process *m_process; QString m_fileName; k9MemoryFifo *m_fifo; bool m_nodata; QStringList m_cmd; QStringList m_output; QWaitCondition m_dataReady; QEventLoop m_eventLoop; QMutex m_mutex; QString m_fps; bool m_debug; bool m_error; }; class _k9ConvertOutput: public QObject { Q_OBJECT public: _k9ConvertOutput(k9ConvertAudio *parent); private: k9ConvertAudio *m_parent; public slots: void getStdout(char *buffer, int buflen) ; void finished ( int exitCode, QProcess::ExitStatus exitStatus ); }; #endif k9copy/src/backup/backupdlg.ui0000644000175000017550000002551012417731553017105 0ustar emulatoremulator backupDlg 0 0 418 437 0 0 0 0 9999 9999 500 230 WaitCursor Backup progression 0 0 WaitCursor QFrame::NoFrame QFrame::Raised <p align="left"><b>DVD Backup</b></p> false 0 0 QFrame::StyledPanel QFrame::Raised 0 0 WaitCursor Elapsed Time false 0 0 WaitCursor --:--:-- / --:--:-- false WaitCursor 0.0 false 0 0 true WaitCursor Current step false WaitCursor WaitCursor 4400 true Qt::Horizontal QSizePolicy::Fixed 40 20 Qt::Horizontal QSizePolicy::Expanding 336 24 0 0 ArrowCursor 26 true 0 0 Output true true 0 0 0 0 255 255 255 0 0 0 255 255 255 0 0 0 0 0 0 0 0 0 WaitCursor true true false KPushButton KPushButton
kpushbutton.h
kpushbutton.h kpushbutton.h bAbort clicked() backupDlg bAbortClick() 20 20 20 20 gbOutput toggled(bool) backupDlg gbOutputToggled(bool) 202 157 202 227 gbOutputToggled(bool)
k9copy/src/backup/k9mp4dlg.cpp0000644000175000017550000000532412412271774016751 0ustar emulatoremulator// // C++ Implementation: // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9mp4dlg.h" #include #include #include #include #include "k9drawimage.h" #include "k9logview.h" #if QT_VERSION >= 0x050000 #include #include #include #include #else #include #include #endif k9MP4Dlg::k9MP4Dlg(QWidget* parent) : QDialog(parent) { Ui_MP4Dlg.setupUi(this); setModal(true); #if QT_VERSION >= 0x050000 setWindowTitle((i18n("Encoding"))); #else setWindowTitle(KDialog::makeStandardCaption(i18n("Encoding"),this)); #endif m_wimage=new k9DrawImage(Ui_MP4Dlg.image); QGridLayout *l=new QGridLayout(Ui_MP4Dlg.image); l->addWidget(m_wimage,0,0); l = new QGridLayout(Ui_MP4Dlg.tabLog); k9LogView *log=new k9LogView(Ui_MP4Dlg.tabLog); l->setSpacing(6); l->setMargin(0); l->addWidget(log, 0, 0, 1, 1); m_update=true; m_timer.start(); m_timerUpdate.setInterval(200); connect(&m_timerUpdate,SIGNAL(timeout()),this,SLOT(Update())); m_timerUpdate.start(); #if QT_VERSION >= 0x050000 KGuiItem::assign(Ui_MP4Dlg.bCancel, KStandardGuiItem::stop() ); #else Ui_MP4Dlg.bCancel->setGuiItem(KStandardGuiItem::Stop); #endif } k9MP4Dlg::~k9MP4Dlg() { } /*$SPECIALIZATION$*/ void k9MP4Dlg::Update() { if (m_update) { m_update=false; Ui_MP4Dlg.lblTitle->setText(m_titleLabel); Ui_MP4Dlg.lblfps->setText(m_fps); Ui_MP4Dlg.lblRemain->setText(m_remain); Ui_MP4Dlg.pbProgress->setValue(m_progress); Ui_MP4Dlg.lblbitrate->setText(m_bitrate); Ui_MP4Dlg.lblsize->setText(m_size); Ui_MP4Dlg.lbllabelSize->setHidden(m_size.isEmpty()); m_wimage->setImage(m_fileName); } } void k9MP4Dlg::Cancel() { //QDialog::accept(); emit sigCancel(); } void k9MP4Dlg::setTitleLabel(QString _titleLabel) { m_titleLabel=_titleLabel; m_update=true; } void k9MP4Dlg::setfps(QString _fps) { m_fps=_fps; m_update=true; } void k9MP4Dlg::setremain(QString _remain) { if (m_timer.elapsed() >=1000) { m_remain=_remain; m_timer.restart(); } } void k9MP4Dlg::setProgress(int _progress) { m_progress=_progress; m_update=true; } void k9MP4Dlg::setbitrate(QString _bitrate) { m_bitrate=_bitrate; m_update=true; } void k9MP4Dlg::setsize( QString _size) { m_size=_size; m_update=true; } void k9MP4Dlg::setImage(QString _fileName) { m_fileName=_fileName; m_update=true; } k9copy/src/backup/k9execcopy.cpp0000644000175000017550000003545612412271774017412 0ustar emulatoremulator// // C++ Implementation: k9execcopy // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: <>, (C) 2008 // // Copyright: See COPYING file that comes with this distribution // // #include "k9execcopy.h" #include "k9dialogs.h" #include "k9dvdsize.h" #include "k9dvdbackup.h" #include "k9dvdauthor.h" #include "k9tools.h" #include #include "k9dvdtitle.h" #include "k9burndvd.h" #include "k9play.h" #include #include "k9mp4enc.h" #include #include "k9titleencopt.h" #include "k9audiocodecs.h" #include "k9videocodecs.h" k9ExecCopy::k9ExecCopy():QObject(0) { m_speed= i18n("default"); m_dvdSize=0; } void k9ExecCopy::copyDVD() { k9Config config; m_cancelled=false; QString filename; if (!m_dvd->getopened()) { k9Dialogs::error( i18n("DVD is not opened"), i18n("DVD Copy")); return; } k9DVDSize *dvdsize=new k9DVDSize(); dvdsize->setMaxSizeDyn(m_dvdSize==0 ?config.getPrefSize():m_dvdSize); delete dvdsize; QString outputDir=config.getPrefOutput() ; if (m_output !=oFolder) k9Tools::addTemporaryDir(outputDir+"/"+m_dvd->getDVDTitle()); bool burn=false; int cancel; cancel=KMessageBox::Cancel; if (m_output==oISO) { filename=m_path; } else { if (m_output==oFolder) outputDir= m_path; QDir dir(m_path); if (!dir.exists()) { dir.mkpath(m_path); } } long fs=k9Tools::getFreeSpace(outputDir); int maxSize=config.getPrefSize() < (m_dvd->getsizeSelected(false)/512) ? config.getPrefSize():(m_dvd->getsizeSelected(false)/512); if ((fs < maxSize) && (fs !=-1)) { if (k9Dialogs::warningContinueCancel ( i18n("Insufficient disk space on %1\n%2 MB expected.").arg(outputDir).arg(config.getPrefSize()),i18n("DVD Copy"))==cancel) return; } // eliminates overwritten DVD copies (bkp) QDir dir(outputDir+"/"+m_dvd->getDVDTitle()); if (dir.exists() && !k9Tools::getBatchCopy()) { if (k9Dialogs::warningContinueCancel( i18n("Directory already exists.\nPlease choose another location or rename the DVD title."), i18n("Warning!"))==cancel) return; } // stopPreview(); if (!config.getUseDvdAuthor() || m_copyMenus) { k9DVDBackup *backup=new k9DVDBackup(m_dvd); backup->setOutput(outputDir); backup->setDevice(m_dvd->getDevice()); backup->setWithMenus( m_copyMenus); backup->setUserOps(config.getPrefUserOps()); backup->execute(); burn=backup->getErrMsg()==""; delete backup; } else { k9DVDAuthor *b=new k9DVDAuthor(m_dvd); b->setworkDir(outputDir); b->author(); if (!b->getError()) burn=true; delete b; } m_cancelled=!burn; if (burn && m_output!=oFolder) { k9BurnDVD b; b.setworkDir(outputDir +"/"+ m_dvd->getDVDTitle()); b.setUseK3b(config.getPrefK3b()); b.setAutoBurn(config.getPrefAutoBurn()); b.setvolId(m_dvd->getDVDTitle()); b.setSpeed(m_speed); if (m_output==oDVD) { b.setburnDevice(m_path); m_dvd->close(); if (m_dvd->getDevice()==m_path) { b.setAutoBurn(false); b.setEject(true); } } else b.makeIso(m_path); b.burn(); m_cancelled=b.isCancelled(); } else if (burn && m_output==oFolder) k9Dialogs::information( i18n("Selected titles have been successfully extracted"), i18n("DVD Copy") ); config.setKeepMenus(m_copyMenus); config.save(); } void k9ExecCopy::CreateMP4() { k9Config config; if (!m_dvd->getopened()) { k9Dialogs::error( i18n("DVD is not opened"), i18n("MPEG-4 Encoding")); return; } QString filename=m_path; int cpt=0; bool bStop=false; QDir dir(config.getPrefOutput()); if (!dir.exists()) { dir.mkpath(config.getPrefOutput()); } for (int i=0; i < m_dvd->gettitleCount();i++) { k9DVDTitle *t=m_dvd->gettitle(i); if (t->isSelected() && t->getIndexed() ) { QString name; if (filename=="") filename=k9Dialogs::getSaveFileName (QDir::homePath(),"*.avi|Audio Video Interleave (*.avi)\n*.mpg|MPEG-1 and MPEG-2 systems (*.mpg)\n*.mp4|MPEG-4 format (*.mp4)\n*.asf|Advanced Streaming Format (*.asf)\n*.swf|Adobe Flash (*.swf)\n*.flv|Adobe Flash video files (*.flv)\n*.rm|RealVideo (*.rm)\n*.mov|QuickTime (*.mov)\n*.mkv|Matroska (*.mkv)", 0,i18n("Save file to disk")); if (filename=="") { bStop=true; break; } QString path=filename; bool matroska=filename.endsWith(".mkv"); k9MP4Enc *mp4=new k9MP4Enc(); if (cpt >0) { QString ext=filename.section(".",-1); if (ext!="") ext="."+ext; path=filename.left(filename.length()-ext.length()); path=path+QString::number(cpt)+ext; mp4->setFilename(path); } else mp4->setFilename(filename); cpt++; k9TitleEncOpt * opt=t->getEncOpt(); mp4->setDevice(m_dvd->getDevice()); mp4->setAudioBitrate(opt->getAudioBr()); mp4->setVideoBitrate(opt->getVideoBr()); mp4->setCrop(*opt->getCrop()); mp4->setCodec(k9VideoCodecs::getAbsCodecNum(opt->getCodec(),opt->getEncoder())); mp4->setAudioCodec(k9AudioCodecs::getAbsCodecNum(opt->getAudioCodec(), opt->getEncoder())); mp4->setSize(QString::number(opt->getMaxSize())); mp4->setAudioGain(QString::number(opt->getAudioGain())); mp4->setNumberCD(QString::number(opt->getNumParts())); mp4->setWidth(opt->getWidth() ); mp4->setHeight(opt->getHeight()); mp4->set2Passes( opt->get2Passes()); mp4->setUseCache(opt->getUseCache()); if (matroska) { if ( ! k9Tools::checkProgram("mkvmerge") ) { k9Dialogs::error (i18n("Unable to run %1").arg("mkvmerge") , i18n("Encoding error")); delete mp4; return ; } mp4->setExtractAudio(false); mp4->setExtractMkv(true); mp4->setExtractSubtitle(true); mp4->setSplitChapters(false); mp4->setFilename(config.getPrefOutput()+"/"+k9Tools::randomFileName()); } mp4->execute(t); bStop=mp4->isCanceled(); if (matroska && !bStop) { createMkv(t,path,mp4->getResultingFiles(),opt->getNumParts(),mp4->getAspect()); } delete mp4; if (bStop) break; } } if (!bStop) k9Dialogs::information( i18n("Selected titles have been successfully encoded"), i18n("Encoding") ); } void k9ExecCopy::MkvStdout(char *buffer, int size) { QByteArray ba(buffer,size); m_outputMsg << ba; if (m_outputMsg.count() > 50) m_outputMsg.removeFirst(); QStringList sl=QString(ba).split("\r"); foreach(QString s,sl) { if (s.contains("gress:")) { int p =s.indexOf("%"); if (p!=-1) { QString pos=s.mid(p-3,3).trimmed(); m_mkvPos=pos.toInt(); #if QT_VERSION >= 0x050000 m_progressDialog->setValue(m_mkvPos); #else m_progressDialog->progressBar()->setValue(m_mkvPos); #endif } } } } void k9ExecCopy::createMkv(k9DVDTitle *_title,const QString &_filename,QMultiMap< int, k9ResultingFile* > _files,int _nbParts, const QString &_aspect) { k9Process process; process << "mkvmerge" << "-o" << _filename; process.setDebugOutput(false); int streamId=1; k9Config config; QFile mkvChapter(config.getPrefOutput()+"/"+k9Tools::randomFileName()); mkvChapter.open(QIODevice::ReadWrite); QList chapters=_title->getChapters(); short int num=1; QTime startTime(0,0,0); foreach (k9DVDChapter *chapter ,chapters) { if (chapter->getSelected()) { QString start=QString("CHAPTER%1=%2\n").arg(num,2,10,QChar('0')).arg(startTime.toString("hh:mm:ss.zzz")); startTime=startTime.addMSecs(QTime().msecsTo(chapter->getLength())); mkvChapter.write(start.toUtf8()); QString name=QString("CHAPTER%1NAME=Chapter %2\n").arg(num,2,10,QChar('0')).arg(num); mkvChapter.write(name.toUtf8()); num++; } } QList titles=_title->getTitles(); foreach (k9DVDTitle *title,titles) { chapters=title->getChapters(); foreach (k9DVDChapter *chapter,chapters) { if (chapter->getSelected()) { QString start=QString("CHAPTER%1=%2\n").arg(num,2,10,QChar('0')).arg(startTime.toString("hh:mm:ss.zzz")); startTime=startTime.addMSecs(QTime().msecsTo(chapter->getLength())); mkvChapter.write(start.toUtf8()); QString name=QString("CHAPTER%1NAME=Chapter %2\n").arg(num,2,10,QChar('0')).arg(num); mkvChapter.write(name.toUtf8()); num++; } } } mkvChapter.close(); for (int i=0;i<_title->getaudioStreamCount();i++) { if (_title->getaudioStream(i)->getselected()) { QString lng(_title->getaudioStream(i)->getlangCod()); process <<"--language" << QString("%1:%2").arg(streamId++).arg(lng.replace("xx","und")); } } process << "--chapters" << mkvChapter.fileName(); QString aspect=_aspect; process << "--aspect-ratio" << QString("0:%1").arg(aspect.replace(":","/")); qint64 totalSize=0; connect(&process,SIGNAL(receivedStdout(char*, int)),this,SLOT(MkvStdout(char*, int))); connect(&process, SIGNAL(finished ( int , QProcess::ExitStatus )),this,SLOT(finished(int, QProcess::ExitStatus))); foreach (k9ResultingFile *rf,_files) { process << rf->filename; QString fname= rf->filename; if (fname.endsWith(".idx")) fname=fname.replace(".idx",".sub"); QFileInfo inf(fname); totalSize+=inf.size(); } totalSize/=(1024*1024); if (_nbParts >1) process << "--split"<< QString("size:%1m").arg((int)(totalSize/_nbParts)); qDebug() << process.debug(); #if QT_VERSION >= 0x050000 m_progressDialog=new QProgressDialog(k9Dialogs::getMainWidget() ); m_progressDialog->setCancelButton(false); #else m_progressDialog=new KProgressDialog(k9Dialogs::getMainWidget() ); m_progressDialog->showCancelButton(false); #endif #if QT_VERSION >= 0x050000 m_progressDialog->setMaximum(100); #else m_progressDialog->progressBar()->setMaximum(100); #endif m_progressDialog->setAutoClose(true); m_progressDialog->setLabelText(i18n("Muxing Matroska file")); process.start(); //process.sync(); m_progressDialog->exec(); process.wait(); delete m_progressDialog; foreach (k9ResultingFile *rf,_files) { QFile f(rf->filename); f.remove(); } mkvChapter.remove(); if ( m_mkvPos !=100) k9Dialogs::error(i18n("An error occured while running mkvmerge"),i18n("Muxing Matroska"),m_outputMsg); m_outputMsg.clear(); } void k9ExecCopy::extractMPEG2() { k9Config config; if (!m_dvd->getopened()) { k9Dialogs::error( i18n("DVD is not opened"), i18n("MPEG-4 Encoding")); return; } QString filename=m_path; int cpt=0; bool bStop=false; QDir dir(config.getPrefOutput()); if (!dir.exists()) { dir.mkpath(config.getPrefOutput()); } for (int i=0; i < m_dvd->gettitleCount();i++) { k9DVDTitle *t=m_dvd->gettitle(i); if (t->isSelected() && t->getIndexed() ) { QString name; if (filename=="") filename=k9Dialogs::getSaveFileName (QDir::homePath(),"*.mpg|MPEG-1 and MPEG-2 systems (*.mpg)", 0,i18n("Save file to disk")); if (filename=="") { bStop=true; break; } k9MP4Enc *mp4=new k9MP4Enc(); mp4->setMpeg2(true); if (cpt >0) { QString ext=filename.section(".",-1); if (ext!="") ext="."+ext; QString path=filename.left(filename.length()-ext.length()); path=path+QString::number(cpt)+ext; mp4->setFilename(path); } else mp4->setFilename(filename); cpt++; mp4->setDevice(m_dvd->getDevice()); mp4->setUseCache(false); mp4->execute(t); bStop=mp4->isCanceled(); delete mp4; if (bStop) break; } } if (!bStop) k9Dialogs::information( i18n("Selected titles have been successfully extracted"), i18n("Encoding") ); } void k9ExecCopy::extractAudio() { k9Config config; if (!m_dvd->getopened()) { k9Dialogs::error( i18n("DVD is not opened"), i18n("Audio Extraction")); return; } QString filename=m_path; int cpt=0; bool bStop=false; QDir dir(config.getPrefOutput()); if (!dir.exists()) { dir.mkpath(config.getPrefOutput()); } for (int i=0; i < m_dvd->gettitleCount();i++) { k9DVDTitle *t=m_dvd->gettitle(i); if (t->isSelected() && t->getIndexed() ) { QString name; if (filename=="") filename=k9Dialogs::getSaveFileName (QDir::homePath(),"*.mpg|MPEG-1 and MPEG-2 systems (*.mpg)", 0,i18n("Save file to disk")); if (filename=="") { bStop=true; break; } k9TitleEncOpt * opt=t->getEncOpt(); k9MP4Enc *mp4=new k9MP4Enc(); mp4->setExtractAudio(true); mp4->setSplitChapters(true); mp4->setAudioCodec(k9AudioCodecs::getAbsCodecNum( opt->getAudioCodec(),opt->getEncoder()) ); if (cpt >0) { QString ext=filename.section(".",-1); if (ext!="") ext="."+ext; QString path=filename.left(filename.length()-ext.length()); path=path+QString::number(cpt)+ext; mp4->setFilename(path); } else mp4->setFilename(filename); cpt++; mp4->setDevice(m_dvd->getDevice()); mp4->setUseCache(false); mp4->execute(t); bStop=mp4->isCanceled(); delete mp4; if (bStop) break; } } if (!bStop) k9Dialogs::information( i18n("Selected titles have been successfully extracted"), i18n("Encoding") ); } void k9ExecCopy::finished(int, QProcess::ExitStatus _status) { Q_UNUSED(_status); #if QT_VERSION >= 0x050000 m_progressDialog->setValue(100); #else m_progressDialog->progressBar()->setValue(100); #endif } void k9ExecCopy::setSpeed(const QString& theValue) { m_speed = theValue; } k9copy/src/backup/k9convertaudio.cpp0000644000175000017550000001152012412271774020257 0ustar emulatoremulator// // C++ Implementation: k9convertaudio // // Description: // // // Author: <>, (C) 2008 // // Copyright: See COPYING file that comes with this distribution // // #include "k9convertaudio.h" #include #include #include #include "k9log.h" k9ConvertAudio::~k9ConvertAudio() { delete m_fifo; } k9ConvertAudio::k9ConvertAudio(const QString &_output,const QStringList &_cmd):QThread(NULL) { if (_output !="") { m_fileName=_output; QFile::remove(_output); } m_fifo=new k9MemoryFifo(); m_cmd=_cmd; m_debug=false; m_error=false; } void k9ConvertAudio::finished ( int exitCode, QProcess::ExitStatus exitStatus ) { Q_UNUSED(exitCode); Q_UNUSED(exitStatus); if (!m_nodata) m_error=true; } void _k9ConvertOutput::finished ( int exitCode, QProcess::ExitStatus exitStatus ) { m_parent->finished(exitCode,exitStatus); } _k9ConvertOutput::_k9ConvertOutput(k9ConvertAudio *parent):QObject(){ m_parent=parent; } void _k9ConvertOutput::getStdout( char *buffer, int buflen) { QString tmp( QByteArray(buffer,buflen)); if (! tmp.isEmpty()) { m_parent->getOutput() << tmp; if (m_parent->getOutput().count() > 10) m_parent->getOutput().removeAt(0); } if (m_parent->getCmd().at(0).contains("mencoder")) { int pos=tmp.indexOf("Pos:"); if (pos!=-1) { QString tmp2=tmp.mid(pos); float t; int frame; int fps; sscanf(tmp2.toUtf8(),"Pos: %f%*s%d",&t,&frame); tmp2=tmp2.mid(tmp2.indexOf("(")+1); tmp2=tmp2.mid(tmp2.indexOf(")")+1); sscanf(tmp2.toUtf8(),"%d",&fps); m_parent->setFps(QString::number(fps)); } //else // k9log::add(tmp,k9logLevel::INFO); } if (m_parent->getCmd().at(0).contains("ffmpeg")) { int pos=tmp.indexOf("fps="); if (pos!=-1) { QString tmp2=tmp.mid(pos+4); pos=tmp2.indexOf("q"); if (pos!=-1) m_parent->setFps(tmp2.mid(0,pos)); } }// else // k9log::add(tmp,k9logLevel::INFO); } void k9ConvertAudio::run() { _k9ConvertOutput *output=new _k9ConvertOutput(this); m_nodata=false; m_error=false; m_process=new k9Process(0,0); connect(m_process, SIGNAL(finished ( int , QProcess::ExitStatus )),output,SLOT(finished(int, QProcess::ExitStatus))); connect(m_process, SIGNAL(receivedStdout( char *, int)),output, SLOT(getStdout(char *, int) )); connect(m_process, SIGNAL(receivedStderr(char *, int)),output, SLOT(getStdout( char *, int) )); m_process->setDebugOutput(m_debug); if (m_fileName!="") { *m_process << "ffmpeg" << "-i" << "/dev/stdin" << m_fileName; } else { //mencoder must be run in a shell cmd to enable filters !! //ffmpeg too, in order to make 2 passes encoding //setting the working directory as the output directory of k9copy k9Config cfg; m_process->setWorkingDirectory(cfg.getPrefOutput()); m_process->setShellCommand(m_cmd.join(" ")); } qDebug() << m_process->debug(); m_process->start(); // while (m_process->isRunning() && !m_nodata) { while (m_process->isRunning()) { int size=m_fifo->count(); size=qMin(size,4096); if (size >0 ) { m_mutex.lock(); while (m_process->isRunning()) { if (m_process->bytesToWrite() >size) m_process->waitForBytesWritten(-1); else break; } m_mutex.unlock(); uchar buffer[size]; //m_fifo->dequeue(buffer,size); m_fifo->readData(buffer,size); if (m_process->isRunning()) m_process->write((char*)buffer,size); //m_dataReady.wakeAll(); } else if (m_nodata) { while (m_process->bytesToWrite() >0) m_process->waitForBytesWritten(); m_process->closeWriteChannel(); m_process->wait(); } else { // m_process->waitForFinished(10); } } delete output; } void k9ConvertAudio::addData(uchar *_buffer,int _size) { if (m_error) return; if (!isRunning()) start(); m_fifo->addData(_buffer,_size); } void k9ConvertAudio::end(bool _wait) { m_nodata=true; m_fifo->setNoData(); if (_wait) while (isRunning()) { qApp->processEvents(); wait(100); } } void k9ConvertAudio::test() { } QString k9ConvertAudio::getFps() const { return m_fps; } void k9ConvertAudio::setFps(const QString& theValue) { m_fps = theValue; } QStringList k9ConvertAudio::getCmd() const { return m_cmd; } void k9ConvertAudio::setDebug(bool theValue) { m_debug = theValue; } bool k9ConvertAudio::Error() const { return m_error; } QStringList &k9ConvertAudio::getOutput() { return m_output; } k9copy/src/backup/k9backupdlg.h0000644000175000017550000000546412412271774017170 0ustar emulatoremulator/*************************************************************************** * Copyright (C) 2005 by Jean-Michel Petit * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef K9BACKUPDLG_H #define K9BACKUPDLG_H #include "k9common.h" #include "ui_backupdlg.h" #include #include "k9decodethread.h" #include "k9internalplayer.h" #include class k9DrawImage; class k9BackupDlg : public QDialog,k9InternalPlayer { Q_OBJECT public: k9BackupDlg(QWidget* parent = 0); ~k9BackupDlg(); /*$PUBLIC_FUNCTIONS$*/ void setTotalSteps(uint32_t _totalSteps); void setProgress(uint32_t _position); void setProgressLabel(QString _text); void setProgressTotal(uint32_t _position); void setTotalMax(uint32_t _max); void setFactor(QString _factor); bool getAbort(); void playMovie(uchar *_data,uint32_t _size); public slots: /*$PUBLIC_SLOTS$*/ private : bool Abort; QTimer *timer; QTime time; QTime m_timer; uint64_t totalCopied,m_progressTotal;; QString m_progressLabel; uint32_t m_totalSteps,m_progress; QString m_factor; bool m_stop; void updateMe(); k9DecodeThread m_decoder; uint m_count; QMutex m_mutex; bool m_playmovie; k9DrawImage *m_wimage; Ui::backupDlg ui_backupDlg; QImage m_image; int m_outputSize; protected: /*$PROTECTED_FUNCTIONS$*/ void showEvent ( QShowEvent * event ); public: void drawImage(QImage *image); protected slots: /*$PROTECTED_SLOTS$*/ void timerDone(); void bAbortClick(); void gbOutputToggled(bool state); void bPlayToggled(bool state); }; #endif k9copy/src/backup/k9mp4dlg.h0000644000175000017550000000222612412271774016414 0ustar emulatoremulator// // C++ Interface: // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9MP4DLG_H #define K9MP4DLG_H #include "k9common.h" #include "ui_mp4dlg.h" #include #include #include #include class k9DrawImage; class k9MP4Dlg : public QDialog { Q_OBJECT public: k9MP4Dlg(QWidget* parent = 0); ~k9MP4Dlg(); /*$PUBLIC_FUNCTIONS$*/ void setfps(QString _fps); void setsize(QString _size); void setbitrate(QString _bitrate); void setremain(QString _remain); void setProgress(int _progress); void setTitleLabel(QString _titleLabel); void setImage(QString _fileName) ; signals: /*$PUBLIC_SLOTS$*/ void sigCancel(); private: k9DrawImage *m_wimage; QTime m_timer; QTimer m_timerUpdate; Ui::MP4Dlg Ui_MP4Dlg; QString m_titleLabel; QString m_fps; QString m_remain; int m_progress; QString m_bitrate; QString m_size; QString m_fileName; bool m_update; public slots: void Update(); protected slots: /*$PROTECTED_FUNCTIONS$*/ void Cancel(); }; #endif k9copy/src/backup/CMakeLists.txt0000644000175000017550000000000012412271774017334 0ustar emulatoremulatork9copy/src/backup/k9mp4enc.h0000644000175000017550000001235612412271774016420 0ustar emulatoremulator// // C++ Interface: k9mp4enc // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9MP4ENC_H #define K9MP4ENC_H #include "k9common.h" #include "k9dvdtitle.h" #include "k9dvdbackupinterface.h" #include "k9subtitle2pgm.h" #include #include #include #include #include "k9play.h" #include #include class k9MP4Dlg; class k9ResultingFile:public QObject { public: k9ResultingFile(QObject *parent):QObject(parent) { title=0; audio=false; video=false; subtitle=false; filename=""; }; int title; bool audio; bool video; bool subtitle; QString filename; }; class k9ConvertAudio; /** @author Jean-Michel PETIT */ class k9MP4Enc : public k9DVDBackupInterface { Q_OBJECT private: enum eEncoder {FFMPEG,MENCODER}; k9MP4Dlg *m_progress; k9DVDTitle *m_title; int getBitRate(k9DVDTitle *_title); QString m_txt; QString m_device; QString m_filename; QString m_height; QString m_width; QString m_size; QString m_audioBitrate; QString m_videoBitrate; QString m_audioGain; QString m_fourcc; QString m_stderr; QString m_passLogFile; QString m_ffmpegPath; QString m_mencoderPath; eEncoder m_encoder; QRect m_crop; int m_parts,m_part; float m_percent; QTimer *timer; QString m_remain; uint32_t m_totalSize; uint32_t m_offset; uint32_t m_totalBytes; QString m_aspect; bool m_2pass; int m_pass; bool m_canceled; bool m_error; QString m_msgError; QStringList m_ErrorDetail; int m_codec; int m_audioCodec; bool m_usecache; bool m_mpeg2; bool m_extractAudio; bool m_extractSubtitle; bool m_extractMkv; bool m_splitChapters; int m_cpt; int m_currentChapter; QTime *time; QString replaceParams(QString _input); void Flush(); bool check(); void buildMEncoderCmd(int pass,int part,k9DVDTitle *title,const QString &passLogFileName,QStringList &cmd) ; void buildVideoCmd(int pass,int part,k9DVDTitle *title,const QString &passLogFileName,QStringList &cmd) ; void buildFFMpegCmd(int pass,k9DVDTitle *title,QStringList &cmd) ; void buildAudioCmd(k9DVDTitle *title); void buildSubtitleCmd(k9DVDTitle *title); QString round16(QString _wh); QString getChapterList(k9DVDTitle *_title); int getselectedSubp(k9DVDTitle *_title); k9play *m_player; QEventLoop *m_eventLoop; k9MemoryFifo m_fifo; QWaitCondition m_dataRead; QFile *m_outputFile; QMap m_converters; QList m_convertersToDelete; QMap m_subtitles; QMultiMap::iterator ichapterCells; QMultiMap m_resultingFiles; private slots: void timerDone(); void slotCancel(); public slots: virtual void getOutput(uchar *buffer,uint32_t size) ; virtual void getOutput(eStreamType streamType,int streamNumber,uchar *buffer,uint32_t size); public: k9MP4Enc(QObject *parent = 0); ~k9MP4Enc(); virtual void execute(k9DVDTitle *_title ); virtual void setNumberCD(const QString & _value) { m_parts = _value.toInt(); if (m_parts==0) m_parts=1; } virtual void setDevice(const QString& _value) { m_device = _value.trimmed(); } virtual void setFilename(const QString& _value) { m_filename = _value.trimmed(); } virtual void setHeight(const QString& _value) { m_height = _value.trimmed(); } virtual void setWidth(const QString& _value) { m_width = _value.trimmed(); } virtual void setSize(const QString& _value) { m_size = _value.trimmed(); } virtual void setAudioBitrate(const QString& _value) { m_audioBitrate = _value.trimmed(); } virtual void setVideoBitrate(const QString& _value) { m_videoBitrate = _value.trimmed(); } virtual void setAudioGain(const QString& _value) { m_audioGain = _value.trimmed(); } virtual void setfourcc(const QString& _value) { m_fourcc = _value.trimmed(); } virtual void set2Passes(bool _value) { m_2pass=_value; } virtual void setUseCache(bool _value) { m_usecache=_value; } virtual void setMpeg2(bool _value) { m_mpeg2=_value; } virtual void setExtractAudio(bool _value) { m_extractAudio=_value; } virtual void setExtractSubtitle(bool _value) { m_extractSubtitle=_value; } virtual void setExtractMkv(bool _value) { m_extractMkv=_value; } virtual void setCodec(const int& _value) { m_codec = _value; } virtual void setAudioCodec(const int& _value) { m_audioCodec = _value; } virtual QWidget *getDialog() { return (QWidget*)m_progress; } virtual bool isCanceled(); QMultiMap< int, k9ResultingFile* > getResultingFiles() const; void setSplitChapters(bool theValue); void setCrop ( const QRect& theValue ) { m_crop = theValue; } const QString &getAspect() { return m_aspect; } }; #endif k9copy/src/backup/k9dvdbackup.cpp0000755000175000017550000016664312412307414017533 0ustar emulatoremulator/*************************************************************************** * Developer: Pauline123 , (C) 2014 * Copyright (C) 2005 by Jean-Michel Petit * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "k9dvdbackup.h" #include "k9dvd.h" #include "bswap.h" #include "k9ifo2.h" #include "k9vamps.h" #include "k9dvdtitleset.h" #include #include #include #include #include #include #include #include #include #if QT_VERSION >= 0x050000 #include #include #include #else #include #include #include #endif #include "k9backupdlg.h" //PM DVDNAV #include "dvdread.h" #include "dvdread/dvd_reader.h" #include "k9script.h" #include "k9tools.h" #define BUF_SECS 1024 bool k9CadtList::compareItems(cell_adr_t *item1,cell_adr_t *item2) { cell_adr_t * it1=item1; cell_adr_t * it2=item2; return (it1->start_sector < it2->start_sector); }; bool k9TitleSetList::compareItems ( k9TitleSet *item1,k9TitleSet *item2 ) { return (item1->VTS < item2->VTS); } void k9TitleSet::clearCells() { // while (!cells.isEmpty()) delete cells.takeFirst(); qDeleteAll(cells); cells.clear(); } k9TitleSet::k9TitleSet(int _VTS):QObject(NULL) { startSector=0; lastSector=0; VTS=_VTS; // cells.setAutoDelete(true); ifoTitle=NULL; } k9TitleSet::~k9TitleSet() { //ifoTitle->closeIFO(); //delete ifoTitle; clearCells(); } k9Cell* k9TitleSet::addCell(int _vts,int _pgc, int _vob) { return cells.addCell(_vts,_pgc,_vob); } uint32_t k9TitleSet::getSize() { return (lastSector +1) ; } bool k9DVDBackup::isAborted() { if (!k9Tools::getBatchCopy()) return backupDlg->getAbort(); else return false; } k9DVDBackup::k9DVDBackup(QObject* _dvd ) : k9DVDBackupInterface(NULL) { DVD = (k9DVD*)_dvd; m_dvdread=DVD->getdvd(); currVTS=0; outputFile=NULL; currTS=NULL; errMsg=""; error=false; backupDlg = k9Tools::getBatchCopy() ? NULL : new k9BackupDlg(k9Dialogs::getMainWidget()); // cells.setAutoDelete(true); vamps=new k9vamps(this); m_withMenu=false; m_forcedFactor=false; m_preserve=true; m_userOps=false; } k9DVDBackup::~k9DVDBackup() { if (outputFile !=NULL) { outputFile->close(); delete outputFile; } if (backupDlg) delete backupDlg; delete vamps; } void k9DVDBackup::setWithMenus(bool _value) { m_withMenu=_value; } bool k9DVDBackup::geterror() { return error; } void k9DVDBackup::seterror(const QString &_msg) { error=true; errMsg=_msg; } QString k9DVDBackup::getErrMsg() { return(errMsg); } void k9DVDBackup::prepareVTS(int _VTS) { if (error) return; ifo_handle_t *hifo; cellSize=0; if (currTS==NULL) { currVTS=0; m_vmgSize=copyMenu2(0); calcFactor(); if (outputFile != NULL) { outputFile->close(); delete outputFile; outputFile=NULL; } } if (isAborted()) { seterror(i18n("DVD backup cancelled")); return; } //creation of output file if (currVTS != _VTS) { if (outputFile != NULL) { outputFile->close(); delete outputFile; outputFile=NULL; updateIfo(); updateVob(&currTS->cells); } if (isAborted()) { seterror(i18n("DVD backup cancelled")); return; } uint32_t startSector=0; if (currTS != NULL) { startSector = currTS->startSector + currTS->getSize(); } else { k9Ifo2 *kifo; kifo=m_dvdread->getIfo(0); hifo = kifo->getIFO(); if (!hifo) { seterror( i18n("unable to open VIDEO_TS.IFO")); return; } startSector= hifo->vmgi_mat->vmg_last_sector+1 ; } currTS = new k9TitleSet(_VTS); currVOB=0; currVTS=_VTS; calcFactor(); //menus are always shrinked currTS->menuSize=copyMenu2(_VTS); if (outputFile != NULL) { outputFile->close(); delete outputFile; } QString filename; filename.sprintf("/VTS_%02d_1.VOB",_VTS); filename=output+filename; outputFile=new QFile(filename); if (! outputFile->open(QIODevice::ReadWrite | QIODevice::Unbuffered)) { seterror(i18n("Unable to open file ") + filename); return; } currVOB=1; currTS->startSector=startSector; currTS->lastSector += currTS->menuSize ; titleSets.append(currTS); k9Ifo2 *kifo; kifo=m_dvdread->getIfo(_VTS); currTS->ifoTitle=kifo; m_position=0; m_copyMenu=false; calcFactor(); } currVTS=_VTS; } void k9DVDBackup::copyCell(int _VTS,k9Cell * _cell,bool _empty) { if (error) return; prepareVTS(_VTS); if (error) return; if (_cell->getforceFactor()) forceFactor( _cell->getFactor()); mutex.lock(); k9Cell *cell= currTS->addCell(_VTS,0,0); //JMP cell->startSector=m_position; cell->startSector=cell->cellList->getPosition(); currCell=cell; //start cell copy mutex.unlock(); if (!_empty) { if (!vamps->isRunning()) { vamps->reset(); vamps->setPreserve(true); vamps->setInputSize(argSize); foreach (int it , _cell->audio) { if (m_preserve) vamps->addAudio(it); else vamps->addAudio(it,_cell->getTitleset()->getNewAudioStreamId(it)); } foreach ( int it, _cell->subpicture) { vamps->addSubpicture(it); } vamps->setVapFactor(argFactor); vamps->start(QThread::NormalPriority); } playCell(_VTS,_cell,_empty); } else copyEmptyPgc(_VTS,_cell); k9Tools::processEvents(); } void k9DVDBackup::copyEmptyPgc(int _vts,k9Cell *_cell) { if (error) return; ifo_handle_t *vts_handle=currTS->ifoTitle->getIFO(); ; k9DVDFile *dvdfile; if ((dvdfile = m_dvdread->openTitle( _vts))== 0) { QString stmp; stmp=i18n("Unable to open titleset %1").arg(_vts); seterror(stmp); return ; } setTotalSteps(vts_handle->vtsi_mat->vts_last_sector-vts_handle->vtsi_mat->vtstt_vobs -1); QString c; c=i18n("Extracting titleset %1").arg(_vts); setProgressLabel(c); if (!k9Tools::getBatchCopy()) backupDlg->show(); uint32_t sector; int32_t len=0; uchar buffer[DVD_VIDEO_LB_LEN]; sector = _cell->startSector; setProgress(sector); dsi_t dsi_pack; uint32_t nsectors; len=dvdfile->readBlocks (sector, 1, buffer); //JMP : D V C if (!k9Cell::isNavPack( buffer) || len==-1) setDummyNavPack( buffer,sector); k9Vobu * vobu=currCell->addVobu(sector); vobu->empty=true; currCell->addNewVobus((char*)buffer,DVD_VIDEO_LB_LEN,currCell->cellList->getPosition(),currVOB,outputFile->pos()); outputFile->write((char*)buffer,DVD_VIDEO_LB_LEN); /* parse contained DSI pack */ navRead_DSI (&dsi_pack, buffer + DSI_START_BYTE); currCell->vob = dsi_pack.dsi_gi.vobu_vob_idn; //dummy video pack setDummyPack( buffer); currCell->addNewVobus((char*)buffer,DVD_VIDEO_LB_LEN,currCell->cellList->getPosition()+1,currVOB,outputFile->pos()); outputFile->write((char*)buffer,DVD_VIDEO_LB_LEN); nsectors=1; len=1; //vobu->size +=nsectors; currCell->lastSector=currCell->startSector+ len; currCell->cellList->setPosition(currCell->cellList->getPosition()+1+len); currTS->lastSector+=len+1; dvdfile->close(); setProgressTotal(len+1); if (!m_forcedFactor) { m_cellCopyList->addInbytes( DVD_VIDEO_LB_LEN *2); m_cellCopyList->addOutbytes( DVD_VIDEO_LB_LEN *2); } else { m_cellCopyList->addFrcinbytes(DVD_VIDEO_LB_LEN *2); m_cellCopyList->addFrcoutbytes( DVD_VIDEO_LB_LEN *2); } } void k9DVDBackup::getOutput(uchar * buffer, uint32_t buflen) { if (error) return; if (!k9Tools::getBatchCopy()) backupDlg->playMovie(buffer,buflen); if (!m_forcedFactor) m_cellCopyList->addOutbytes( buflen); else m_cellCopyList->addFrcoutbytes( buflen); uchar *temp =buffer; QString sName; if ((buflen %2048) !=0) qDebug("getOutput, buffer : %u",buflen); uint end=0; for (uint itemp=0;itempsize(); end=itemp+DVD_VIDEO_LB_LEN; if (k9Cell::isNavPack(temp+itemp)) { k9Vobu * vobu = vobuQueue.dequeue(); cellOut=vobu->parent; dsi_t dsiPack; navRead_DSI (&dsiPack, (uchar*)(temp+itemp) + DSI_START_BYTE); cellOut->vob = dsiPack.dsi_gi.vobu_vob_idn; if ((dsiPack.dsi_gi.vobu_ea * DVD_VIDEO_LB_LEN) + fileSize >= (1024*1024*1024)) { outputFile->close(); delete outputFile; currVOB++; if (currVTS==0) sName = "/VIDEO_TS.VOB"; else sName.sprintf("/VTS_%02d_%d.VOB",(int)currVTS,(int)currVOB); sName=output+sName; outputFile=new QFile(sName); if ( !outputFile->open(QIODevice::ReadWrite|QIODevice::Unbuffered)) { seterror(i18n("Unable to open file ") + sName); mutex.unlock(); return; } } } cellOut->addNewVobus((char*)(temp+itemp),DVD_VIDEO_LB_LEN,cellOut->cellList->getPosition() ,currVOB,outputFile->pos()); outputFile->write((char*)(temp+itemp),DVD_VIDEO_LB_LEN); setProgressTotal(1); cellOut->cellList->setPosition( cellOut->cellList->getPosition()+1); if (!m_copyMenu) currTS->lastSector++; mutex.unlock(); } } /*! \fn k9DVDBackup::setDevice(QString _device) */ void k9DVDBackup::setDevice(QString _device) { device=_device; } /*! \fn k9DVDBackup::setOutput(QString _output) */ void k9DVDBackup::setOutput(QString _output) { output=QDir::cleanPath(_output); } uint32_t k9DVDBackup::copyMenu2(int _vts) { if (error || !m_withMenu ) return 0; k9Ifo2 *kifo; kifo=m_dvdread->getIfo( _vts); ifo_handle_t *hifo =kifo->getIFO(); m_ifo=hifo; uint32_t msize=0; uint32_t menuLastSector; if (_vts==0) { msize=hifo->vmgi_mat->vmg_last_sector -1 - 2* hifo->vmgi_mat->vmgi_last_sector; menuLastSector=msize-1; } else { msize=hifo->vtsi_mat->vtstt_vobs - hifo->vtsi_mat->vtsi_last_sector -1; menuLastSector=msize-1; } if (msize==0) { //kifo.closeIFO(); return 0; } m_position=0; m_copyMenu=true; QString targetName; if (_vts == 0) { targetName="VIDEO_TS.VOB"; } else { targetName.sprintf("VTS_%02i_0.VOB",_vts); } targetName=output+"/"+targetName; outputFile=new QFile(targetName); if (! outputFile->open(QIODevice::ReadWrite |QIODevice::Unbuffered)) { seterror(i18n("Unable to open file ") + targetName); return 0; } k9DVDFile *dvdfile; if ((dvdfile = m_dvdread->openMenu( _vts))== 0) { QString stmp; stmp=i18n("Unable to open menu for titleset %1").arg(_vts); seterror (stmp); return 0; } k9CellList *lstCell; if (_vts==0) lstCell = &vmgCells; else lstCell = &currTS->menuCells; // lstCell->setAutoDelete(true); c_adt_t *c_adt = hifo->menu_c_adt; // c_adt shouldn't be null. It would say that the menu doesn't contain video !? if (c_adt==NULL) { return 0; } uint32_t length = c_adt->last_byte + 1 - C_ADT_SIZE; cell_adr_t *ptr; ptr= c_adt->cell_adr_table; uint32_t sector, dsi_next_vobu = 0; uint32_t imax=length/sizeof(cell_adr_t); QString c; c=i18n("Extracting menu for titleset %1").arg(_vts); setProgressLabel(c); if (!k9Tools::getBatchCopy()) { backupDlg->show(); } setTotalSteps(ptr[imax-1].last_sector); k9CadtList cadr; uint32_t nbCells=0; for (uint32_t i=0;ilast_sector > menuLastSector) (ptr+i)->last_sector=menuLastSector; if ((ptr+i)->start_sector <= menuLastSector) { cadr.append(ptr+i); nbCells++; } else qDebug() << QString("cell start sector (%1) exceed menu size (%2)").arg((ptr+i)->start_sector).arg(menuLastSector); } //cadr.sort(); qSort(cadr.begin(),cadr.end(),k9CadtList::compareItems); vamps->reset(); vamps->setPreserve(true); for (uint i=1;i<=8;i++) vamps->addAudio(i); for (uint i=1;i<=32;i++) vamps->addSubpicture(i); vamps->setVapFactor(argFactor); vamps->setInputSize(msize*2048); vamps->start(QThread::NormalPriority); // while(!vamps->running() && !vamps->finished()); for (uint32_t i = 0; i < nbCells; i++) { currCell=lstCell->addCell(_vts,1,1); dsi_next_vobu=0; cell_adr_t * cellAdr=cadr.at(i); for (sector = cellAdr->start_sector; sector <= cellAdr->last_sector; sector += dsi_next_vobu & 0x7fffffff) { setProgress(sector); if (isAborted()) { seterror(i18n("DVD backup cancelled")); } if (error) { vamps->abort(); break; } else if (vamps->geterror()) { seterror( vamps->geterrMsg()); break; } dsi_next_vobu= copyVobu(dvdfile,sector,NULL); } } vamps->setNoData(); vamps->wait(); uint32_t size=0; //JMP size=m_position; size =lstCell->getPosition(); dvdfile->close(); outputFile->close(); delete outputFile; outputFile=NULL; //kifo.closeIFO(); updateVob(lstCell); m_copyMenu=false; return size; } void k9DVDBackup::playCell (int vts_num, k9Cell *_cell,bool _empty) { if (error) return; ifo_handle_t *vts_handle; k9DVDFile *dvdfile; uint32_t sector, dsi_next_vobu = 0; /* open disc */ if (m_dvdread->opened()) { /* load information for the given VTS */ // vts_handle = ifoOpen (dvd_handle, vts_num); vts_handle=currTS->ifoTitle->getIFO(); if (!vts_handle) { QString stmp; stmp=i18n("Unable to open ifo file for titleset %1").arg(vts_num); seterror (stmp); //JMP vamps->setNoData(); return; } setTotalSteps( vts_handle->vtsi_mat->vts_last_sector-vts_handle->vtsi_mat->vtstt_vobs -1); QString c; c=i18n("Extracting titleset %1").arg(vts_num); setProgressLabel(c); if (!k9Tools::getBatchCopy()) backupDlg->show(); } else { seterror(i18n("Unable to open DVD")); //JMP vamps->setNoData(); return; } /* open VTS data */ dvdfile = m_dvdread->openTitle (vts_num); if (! dvdfile) { QString stmp; stmp=i18n("Unable to open vobs for titleset %1").arg(vts_num); seterror( stmp); //JMP vamps->setNoData(); return; } /* loop until out of the cell */ //TO REMOVE currCell->oldStartSector=_cell->startSector; for (sector = _cell->startSector; sector <= _cell->lastSector; sector += dsi_next_vobu & 0x7fffffff) { setProgress(sector); if (isAborted()) { seterror(i18n("DVD backup cancelled")); } if (error) { vamps->abort(); break; } else if (vamps->geterror()) { seterror( vamps->geterrMsg()); break; } dsi_next_vobu= copyVobu(dvdfile,sector,NULL,_empty); } dvdfile->close(); } void k9DVDBackup::setDummyNavPack(uchar *buf,uint32_t _sector) { int8_t *ptr = (int8_t*)buf; static uint8_t nav_pack1 [] = { /* pack header: SCR=0, mux rate=10080000bps, stuffing length=0 */ 0, 0, 1, 0xba, 0x44, 0x00, 0x04, 0x00, 0x04, 0x01, 0x01, 0x89, 0xc3, 0xf8, /* system header */ 0, 0, 1, 0xbb, 0x00, 0x12, /* contents of system header filled in at run time (18 bytes) */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* PES header for first private stream 2 packet */ 0, 0, 1, 0xbf, 0x03, 0xd4 }; static uint8_t nav_pack2 [] = { /* PES header for second private stream 2 packet */ 0, 0, 1, 0xbf, 0x03, 0xfa }; memcpy (ptr, nav_pack1, sizeof (nav_pack1)); ptr += sizeof (nav_pack1); memset (ptr, 0, DVD_VIDEO_LB_LEN/2 - sizeof (nav_pack1)); ptr = (int8_t*)buf + DVD_VIDEO_LB_LEN/2; memcpy (ptr, nav_pack2, sizeof (nav_pack2)); ptr += sizeof (nav_pack2); memset (ptr, 0, DVD_VIDEO_LB_LEN/2 - sizeof (nav_pack2)); dsi_t dsiPack; pci_t pciPack; navRead_DSI (&dsiPack, buf + DSI_START_BYTE); k9Ifo2::navRead_PCI (&pciPack, buf+0x2d); dsiPack.dsi_gi.nv_pck_lbn=_sector; dsiPack.dsi_gi.vobu_ea = 1; navRead_DSI((dsi_t*)(buf + DSI_START_BYTE),(uchar*)&dsiPack); pciPack.pci_gi.nv_pck_lbn =dsiPack.dsi_gi.nv_pck_lbn; k9Ifo2::navRead_PCI((pci_t*)(buf+0x2d),(uchar*)&pciPack); } void k9DVDBackup::setDummyPack(uchar *_buffer) { int8_t *ptr = (int8_t*)_buffer; uint8_t dummy_pack [] = { /* pack header: SCR=0, mux rate=10080000bps, stuffing length=0 */ 0, 0, 1, 0xba, 0x44, 0x00, 0x04, 0x00, 0x04, 0x01, 0x01, 0x89, 0xc3, 0xf8, /* PES header for dummy video packet */ 0, 0, 1, 0xe0, 0x07, 0xec, 0x81, 0x00, 0x00 }; memcpy (ptr, dummy_pack, sizeof (dummy_pack)); ptr += sizeof (dummy_pack); memset (ptr, 0xff, DVD_VIDEO_LB_LEN - sizeof (dummy_pack)); } uint32_t k9DVDBackup::findNextVobu(uint32_t _sector) { k9Ifo2 *ifo; ifo = m_dvdread->getIfo(currVTS); m_ifo=ifo->getIFO(); vobu_admap_t * vobu_admap; if (m_copyMenu) vobu_admap = m_ifo->menu_vobu_admap; else vobu_admap = m_ifo->vts_vobu_admap; uint32_t length = vobu_admap->last_byte + 1 - VOBU_ADMAP_SIZE; for (uint32_t i = 0; i < length/sizeof(uint32_t); i++) { //if (vobu_admap->vobu_start_sectors[i]== _sector) { if (vobu_admap->vobu_start_sectors[i]>= _sector) { uint32_t nextVobu=vobu_admap->vobu_start_sectors[i+1]; //ifo.closeIFO(); return nextVobu; } } //ifo.closeIFO(); return 0; } uint32_t k9DVDBackup::copyVobu(k9DVDFile *_fileHandle,uint32_t _startSector,k9Vobu * _vobu,bool _empty) { dsi_t dsi_pack; k9Vobu * currVobu; bool badNavPack=false; uint32_t nsectors, nextVobu=0; int32_t len=0; uchar *buf; uint32_t sector=_startSector; /* read nav pack */ uint32_t buf_size=DVD_VIDEO_LB_LEN; buf=new uchar[buf_size]; len = _fileHandle->readBlocks ( sector, 1, buf); /* parse contained DSI pack */ //test if nav pack is ok if (len !=-1) { navRead_DSI (&dsi_pack, buf + DSI_START_BYTE); if (dsi_pack.dsi_gi.nv_pck_lbn != sector) { len=-1; } } if (len==-1) { setDummyNavPack(buf,sector); nextVobu=findNextVobu(sector); qDebug ("VOBU : %u Read Error !!!! ==> %u",sector,nextVobu); badNavPack=true; } currVobu=_vobu; mutex.lock(); if (k9Cell::isNavPack(buf)) { //TO REMOVE currCell->oldLastSector=sector; if (currVobu==NULL) { currVobu =currCell->addVobu(sector); vobuQueue.enqueue(currVobu); } } mutex.unlock(); /* generate an MPEG2 program stream (including nav packs) */ wrote=false; vamps->addData(buf,DVD_VIDEO_LB_LEN); if (!m_forcedFactor) m_cellCopyList->addInbytes( DVD_VIDEO_LB_LEN); else m_cellCopyList->addFrcinbytes(DVD_VIDEO_LB_LEN); uint32_t end=0; if (badNavPack) { setDummyPack(buf); nsectors=1; if (nextVobu !=0) end=nextVobu-_startSector-1; } else { if (!_empty) nsectors = dsi_pack.dsi_gi.vobu_ea; else nsectors = 1; //uint32_t dsi_next_vobu = dsi_pack.vobu_sri.next_vobu; if (nsectors>0) { uint32_t newsize=nsectors*DVD_VIDEO_LB_LEN; uchar *tmp=new uchar[newsize]; memcpy(tmp,buf,buf_size >newsize?newsize:buf_size); delete[] buf; buf=tmp; buf_size=nsectors*DVD_VIDEO_LB_LEN; } // buf=(uchar*) realloc(buf,nsectors*DVD_VIDEO_LB_LEN); end=dsi_pack.dsi_gi.vobu_ea; if (_empty) setDummyPack(buf); /* read VOBU */ else for (uint32_t i=0;i< nsectors;i++) { len = _fileHandle->readBlocks ( (sector + 1)+i, 1, buf +(i*DVD_VIDEO_LB_LEN)); if (len==-1) { qDebug ("VOBU : %u Read Error !!!!",sector); //setDummyPack(buf + (i*DVD_VIDEO_LB_LEN)); setDummyPack(buf); nsectors=1; break; } } } /* write VOBU */ for (uint32_t i=0;iaddData(buf + (i*DVD_VIDEO_LB_LEN), DVD_VIDEO_LB_LEN); } if (buf_size) delete[] buf; if (! m_forcedFactor) m_cellCopyList->addInbytes( nsectors*DVD_VIDEO_LB_LEN); else m_cellCopyList->addFrcinbytes( nsectors*DVD_VIDEO_LB_LEN); k9Tools::processEvents(); return (end+1); } k9Vobu * k9DVDBackup::remapVobu(uint32_t *value) { k9Vobu *vobu=NULL; uint32_t sector,mask; if ( (*value & 0x80000000) == 0x80000000) { sector = *value & 0x7FFFFFFF; mask=0x80000000; } else { sector =*value; mask=0; } *value=0; k9CellList *lstCell; if (! m_copyMenu) { lstCell=&(currTS->cells); } else { if (currVTS==0) lstCell=&vmgCells; else lstCell=&(currTS->menuCells); } vobu=lstCell->findVobu(sector); if (vobu !=NULL) { *value = vobu->newSector | mask; return vobu; } *value=0; return vobu; } k9Vobu * k9DVDBackup::remapOffset(uint32_t _sector,uint32_t *_offset,int _dir) { k9Vobu *vobu1=NULL, *vobu2=NULL; uint32_t offset,sector; uint32_t maskOffset1=0,maskOffset2=0,maskSector=0; if ((*_offset!= 0xbfffffff) && (*_offset!=0x3fffffff) && (*_offset!=0x7fffffff)) { if ( (*_offset & 0x80000000) == 0x80000000) maskOffset1= 0x80000000; if ( (*_offset & 0x40000000) == 0x40000000) maskOffset2= 0x40000000; offset = *_offset & 0x3FFFFFFF; if ( (_sector & 0x80000000) == 0x80000000) { sector = _sector & 0x7FFFFFFF; maskSector=0x80000000; } else { sector =_sector; maskSector=0; } k9CellList *lstCell; if (! m_copyMenu) { lstCell=&(currTS->cells); } else { if (currVTS==0) lstCell=&vmgCells; else lstCell=&(currTS->menuCells); } vobu1 = lstCell->findVobu(sector); vobu2 = lstCell->findVobu(sector+_dir*offset); if ((vobu1 !=NULL) && (vobu2!=NULL)) { *_offset = abs(vobu1->newSector - vobu2->newSector) | maskOffset1 ; *_offset |= maskOffset2; return vobu2; } if (vobu1==NULL && vobu2==NULL) qDebug ("remapOffset : sector not found"); } return vobu2; } void k9DVDBackup::updateMainIfo() { if (error) return; k9Ifo2 ifo(m_dvdread); ifo.setOutput(output); ifo.setDevice(device); ifo.openIFO(0); ifo_handle_t *hifo =ifo.getIFO(); hifo->vmgi_mat->vmg_last_sector= 1+ m_vmgSize+hifo->vmgi_mat->vmgi_last_sector*2; if (m_vmgSize >0) { if (hifo->vmgi_mat->vmgm_vobs != hifo->vmgi_mat->vmgi_last_sector +1) qDebug ("error in ifo file : vmgm_vobs %u -> %u)",hifo->vmgi_mat->vmgm_vobs,hifo->vmgi_mat->vmgi_last_sector +1); hifo->vmgi_mat->vmgm_vobs=hifo->vmgi_mat->vmgi_last_sector +1; } currVTS=0; k9Vobu* vobu2=NULL; uint32_t newPos=0; //update first play PGC if (hifo->first_play_pgc !=NULL ) { m_copyMenu=true; pgc_t *pgc=hifo->first_play_pgc; if (! m_withMenu && pgc->command_tbl!=0 ) { pgc->command_tbl->nr_of_pre=0; pgc->command_tbl->nr_of_post=0; pgc->command_tbl->nr_of_cell=0; } if (m_userOps) memset(&(pgc->prohibited_ops),0,sizeof(user_ops_t)); cell_playback_t *cell_playback =pgc->cell_playback; uint32_t nr= pgc->nr_of_cells; vobu2=NULL; cell_playback_t cell; newPos=0; for ( uint32_t j = 0; j < nr; j++) { k9Vobu *vobu=remapVobu(&cell_playback[j].first_sector); vobu2=vobu; remapVobu(&cell_playback[j].first_ilvu_end_sector); if (vobu !=NULL) { vobu=remapVobu(&cell_playback[j].last_vobu_start_sector); if (vobu==NULL) { cell_playback[j].last_vobu_start_sector=cell_playback[j].first_sector; vobu=vobu2; pgc->playback_time.hour=0; pgc->playback_time.minute=0; pgc->playback_time.second=0; cell_playback[j].playback_time.hour=0; cell_playback[j].playback_time.minute=0; cell_playback[j].playback_time.second=0; } cell_playback[j].last_sector = vobu->newSector+vobu->size;// -1 ; cell_playback[newPos]=cell_playback[j]; cell=cell_playback[newPos]; newPos++; } else { cell_playback[newPos]=cell; newPos++; } } for (uint32_t j=newPos;jnr_of_cells=newPos; m_copyMenu=false; } updatePgci_ut(hifo); update4Menu(hifo); //mise �jour des startSectors k9TitleSet *TSp=NULL; //titleSets.sort(); qSort(titleSets.begin(),titleSets.end(),k9TitleSetList::compareItems); for (int iTS=0;iTS < titleSets.count();iTS++) { k9TitleSet *TS=titleSets.at(iTS); uint32_t startSector; if (TSp!=NULL) startSector = TSp->startSector + TSp->getSize(); else startSector=hifo->vmgi_mat->vmg_last_sector+1 ; TS->startSector=startSector; TSp=TS; } hifo->vmgi_mat->vmg_category=0; bool found=false; for (uint32_t i=0 ; i< hifo->tt_srpt->nr_of_srpts;i++) { for (int iTS=0;iTSVTS == hifo->tt_srpt->title[i].title_set_nr ) { hifo->tt_srpt->title[i].title_set_sector = TS->startSector; found=true; } } found=false; } ifo.saveIFO(); ifo.closeIFO(); } void k9DVDBackup::updatePgci_ut(ifo_handle_t *_hifo) { pgci_ut_t *pgci_ut=_hifo->pgci_ut; k9Vobu* vobu2=NULL; uint newPos=0; //update pgci_ut if (pgci_ut !=0 && m_withMenu) { m_copyMenu=true; for (uint i=0; i nr_of_lus;i++) { pgci_lu_t *pgci_lu= &pgci_ut->lu[i]; pgcit_t * pgcit= pgci_lu->pgcit; for (uint i2=0 ; i2 nr_of_pgci_srp;i2++) { pgci_srp_t * pgci_srp=&pgcit->pgci_srp[i2]; pgc_t *pgc=pgci_srp->pgc; if (m_userOps) memset(&(pgc->prohibited_ops),0,sizeof(user_ops_t)); if (! m_withMenu && pgc->command_tbl!=0) { pgc->command_tbl->nr_of_pre=0; pgc->command_tbl->nr_of_post=0; pgc->command_tbl->nr_of_cell=0; } cell_playback_t *cell_playback =pgc->cell_playback; uint32_t nr= pgc->nr_of_cells; vobu2=NULL; cell_playback_t cell; newPos=0; for ( uint32_t j = 0; j < nr; j++) { k9Vobu *vobu=remapVobu(&cell_playback[j].first_sector); vobu2=vobu; if (cell_playback[j].first_ilvu_end_sector !=0) { uint32_t tmp=cell_playback[j].first_ilvu_end_sector+1; remapVobu(&tmp); if (tmp!=0) cell_playback[j].first_ilvu_end_sector=tmp-1; } if (vobu !=NULL) { vobu=remapVobu(&cell_playback[j].last_vobu_start_sector); if (vobu !=NULL) cell_playback[j].last_sector = vobu->newSector+vobu->size;// -1 ; cell_playback[newPos]=cell_playback[j]; cell=cell_playback[newPos]; newPos++; } else { cell_playback[newPos]=cell; newPos++; } } for (uint32_t j=newPos;jnr_of_cells=newPos; } } m_copyMenu=false; } if (!m_withMenu ) { k9Script *script=new k9Script(_hifo,DVD); script->updatePGCIUT(); script->updateFPPGC(); delete script; if (_hifo->vmgi_mat) { _hifo->vmgi_mat->vmgm_c_adt=0; _hifo->vmgi_mat->vmgm_vobu_admap=0; } else { _hifo->vtsi_mat->vtsm_c_adt=0; _hifo->vtsi_mat->vtsm_vobu_admap=0; } } } void k9DVDBackup::update4Menu(ifo_handle_t *_hifo) { if (!m_withMenu) return; // Mise �jour vtsm_c_adt pour le menu m_copyMenu=true; //indispensable pour remapvobu c_adt_t *c_adt = _hifo->menu_c_adt; uint32_t length; if (c_adt!=NULL) { length = c_adt->last_byte + 1 - C_ADT_SIZE; cell_adr_t *ptr= c_adt->cell_adr_table; for (uint32_t i = 0; i < length/sizeof(cell_adr_t); i++) { uint32_t startSect=ptr[i].start_sector; // last sector of a vobu = start sector of next vobu -1 uint32_t lastSect= ptr[i].last_sector +1; k9Vobu *vobu=remapVobu(&startSect); if (vobu == NULL) qDebug ("Error : could not find startSector"); else { if (remapVobu(&lastSect)==NULL) lastSect=vobu->parent->lastSector; else lastSect--; ptr[i].start_sector = startSect; ptr[i].last_sector = lastSect; } } } vobu_admap_t * vobu_admap = _hifo->menu_vobu_admap; if (vobu_admap != NULL) { length = vobu_admap->last_byte + 1 - VOBU_ADMAP_SIZE; uint newPos=0; for (uint32_t i = 0; i < length/sizeof(uint32_t); i++) { if (remapVobu(&vobu_admap->vobu_start_sectors[i])!= NULL) { vobu_admap->vobu_start_sectors[newPos]=vobu_admap->vobu_start_sectors[i]; newPos++; } } for (uint32_t i=newPos ; i < length/sizeof(uint32_t);i++) vobu_admap->vobu_start_sectors[i]=0; vobu_admap->last_byte = newPos * sizeof(uint32_t) -1 +VOBU_ADMAP_SIZE; } m_copyMenu=false; } void k9DVDBackup::updateIfo() { if (error) return; k9Ifo2 ifo(m_dvdread); ifo.setOutput(output); ifo.setDevice(device); ifo.openIFO(currVTS); ifo_handle_t *hifo =ifo.getIFO(); pgcit_t * pgcit = hifo->vts_pgcit; //update total VTS size with IFO size ifo.saveIFO(); // currTS->lastSector += 2 *(hifo->vtsi_mat->vtsi_last_sector ) +1; currTS->lastSector += 2 *ifo.getSize() -1; hifo->vtsi_mat->vts_last_sector = currTS->lastSector ; hifo->vtsi_mat->vtstt_vobs = hifo->vtsi_mat->vtsi_last_sector + 1 + currTS->menuSize; //JMP if (currTS->menuSize >0) { if (hifo->vtsi_mat->vtsm_vobs != hifo->vtsi_mat->vtsi_last_sector +1) qDebug ("error in ifo file %u : vtsm_vobs %u -> %u",currTS->VTS,hifo->vtsi_mat->vtsm_vobs,hifo->vtsi_mat->vtsi_last_sector +1); hifo->vtsi_mat->vtsm_vobs= hifo->vtsi_mat->vtsi_last_sector +1 ; } else hifo->vtsi_mat->vtsm_vobs=0; updatePgci_ut(hifo); k9Vobu* vobu2=NULL; uint32_t newPos=0; //update first play PGC if (hifo->first_play_pgc !=NULL ) { pgc_t *pgc=hifo->first_play_pgc; if (m_userOps) memset(&(pgc->prohibited_ops),0,sizeof(user_ops_t)); if (! m_withMenu && pgc->command_tbl!=0) { pgc->command_tbl->nr_of_pre=0; pgc->command_tbl->nr_of_post=0; pgc->command_tbl->nr_of_cell=0; } cell_playback_t *cell_playback =pgc->cell_playback; uint32_t nr= pgc->nr_of_cells; vobu2=NULL; cell_playback_t cell; newPos=0; for ( uint j = 0; j < nr; j++) { k9Vobu *vobu=remapVobu(&cell_playback[j].first_sector); vobu2=vobu; remapVobu(&cell_playback[j].first_ilvu_end_sector); if (vobu !=NULL) { vobu=remapVobu(&cell_playback[j].last_vobu_start_sector); if (vobu==NULL) { cell_playback[j].last_vobu_start_sector=cell_playback[j].first_sector; vobu=vobu2; pgc->playback_time.hour=0; pgc->playback_time.minute=0; pgc->playback_time.second=0; cell_playback[j].playback_time.hour=0; cell_playback[j].playback_time.minute=0; cell_playback[j].playback_time.second=0; } cell_playback[j].last_sector = vobu->newSector+vobu->size;// -1 ; cell_playback[newPos]=cell_playback[j]; cell=cell_playback[newPos]; newPos++; } else { cell_playback[newPos]=cell; newPos++; } } for (uint32_t j=newPos;jnr_of_cells=newPos; } newPos=0; audio_attr_t vts_audio_attr[8]; //update each PGC bool bUpdateAudioAttr=true; if (!m_preserve) { memcpy (vts_audio_attr, hifo->vtsi_mat->vts_audio_attr,sizeof(audio_attr_t)*8); memset(hifo->vtsi_mat->vts_audio_attr,0,sizeof(audio_attr_t)*8); } for (uint32_t i = 0; i < pgcit->nr_of_pgci_srp; i++) { pgc_t *pgc=pgcit->pgci_srp[i].pgc; int numTitle=pgcit->pgci_srp[i].entry_id & 0x7F; k9DVDTitle *title=DVD->gettitleByNum( currVTS, numTitle ); // qDebug() << "numTitle:" << numTitle; // qDebug() << "title length :"<< title->gettotallength().toString("hh:mm:ss"); // qDebug() << "new length :" << title->getSelectedLength().toString("hh:mm:ss"); // QTime t; // t=t.addMSecs(DVD->dvdtime2msec(&pgc->playback_time)); bool ok; // qDebug() << "pgc length :" << t.toString("hh:mm:ss") << " " << pgc->playback_time.frame_u << pgc->playback_time.hour << pgc->playback_time.minute << pgc->playback_time.second;; if (m_userOps) memset(&(pgc->prohibited_ops),0,sizeof(user_ops_t)); if (! m_withMenu) { k9Script *script=new k9Script(hifo,DVD); script->updatePGC(pgc,currTS->VTS,numTitle); delete script; } //shift audio streams; if (!m_preserve) { int idx=0; uint16_t audio_control [8]; memcpy(audio_control,pgc->audio_control,sizeof(uint16_t) *8); memset(pgc->audio_control,0,sizeof(uint16_t) *8); for (int istr=0; istr< 8; istr++) { uint16_t ctrl=audio_control[istr] & 0xF8FF; int streamId = 1+ ((audio_control[istr]>>8) & 0x7) ; int newStreamId = DVD->gettitleset(currTS->VTS-1)->getNewAudioStreamId(streamId); if (newStreamId !=0) { pgc->audio_control[idx]=ctrl | ((newStreamId-1)<<8); if (bUpdateAudioAttr) { hifo->vtsi_mat->vts_audio_attr[idx]=vts_audio_attr[istr]; } idx++; } } if (bUpdateAudioAttr) hifo->vtsi_mat->nr_of_vts_audio_streams=idx; bUpdateAudioAttr=false; } cell_playback_t *cell_playback =pgc->cell_playback; uint32_t nr= pgc->nr_of_cells; vobu2=NULL; cell_playback_t cell; newPos=0; for ( uint32_t j = 0; j < nr; j++) { k9Vobu *vobu=remapVobu(&cell_playback[j].first_sector); vobu2=vobu; if (cell_playback[j].first_ilvu_end_sector !=0) { uint32_t tmp=cell_playback[j].first_ilvu_end_sector+1; remapVobu(&tmp); if (tmp!=0) cell_playback[j].first_ilvu_end_sector=tmp-1; } if (vobu !=NULL) { vobu=remapVobu(&cell_playback[j].last_vobu_start_sector); if (vobu==NULL) { cell_playback[j].last_vobu_start_sector=cell_playback[j].first_sector; vobu=vobu2; QTime newLength=title->getSelectedLength(); pgc->playback_time.hour= QString::number(newLength.hour(),10).toInt(&ok,16); pgc->playback_time.minute=QString::number(newLength.minute(),10).toInt(&ok,16); pgc->playback_time.second=QString::number(newLength.second(),10).toInt(&ok,16); QTime t2; t2=t2.addMSecs(DVD->dvdtime2msec(&pgc->playback_time)); // qDebug() << "title " << title->getnumTitle() << " new length: " << t2.toString("hh:mm:ss"); // qDebug() << "=============================================="; cell_playback[j].playback_time.hour=0; cell_playback[j].playback_time.minute=0; cell_playback[j].playback_time.second=0; } cell_playback[j].last_sector = vobu->newSector+vobu->size;// -1 ; cell_playback[newPos]=cell_playback[j]; cell=cell_playback[newPos]; newPos++; } else { cell_playback[newPos]=cell; newPos++; } } for (uint32_t j=newPos;jnr_of_cells=newPos; } c_adt_t *c_adt = hifo->vts_c_adt; uint32_t length = c_adt->last_byte + 1 - C_ADT_SIZE; cell_adr_t *ptr= c_adt->cell_adr_table; newPos=0; for (uint32_t i = 0; i < length/sizeof(cell_adr_t); i++) { uint32_t startSect=ptr[i].start_sector; // last sector of a vobu = start sector of next vobu -1 uint32_t lastSect= ptr[i].last_sector +1; k9Vobu *vobu=remapVobu(&startSect); if (vobu == NULL) qDebug ("Error : could not find startSector"); else { if (remapVobu(&lastSect)==NULL) lastSect= vobu->parent->lastSector; else lastSect--; ptr[i].start_sector = startSect; ptr[i].last_sector = lastSect; } } vobu_admap_t * vobu_admap = hifo->vts_vobu_admap; length = vobu_admap->last_byte + 1 - VOBU_ADMAP_SIZE; newPos=0; for (uint32_t i = 0; i < length/sizeof(uint32_t); i++) { if (remapVobu(&vobu_admap->vobu_start_sectors[i])!= NULL) { vobu_admap->vobu_start_sectors[newPos]=vobu_admap->vobu_start_sectors[i]; newPos++; } } for (uint32_t i=newPos ; i < length/sizeof(uint32_t);i++) vobu_admap->vobu_start_sectors[i]=0; vobu_admap->last_byte = newPos * sizeof(uint32_t) -1 +VOBU_ADMAP_SIZE; //update VTS_TMAP vts_tmapt_t *vts_tmapt=hifo->vts_tmapt; if (vts_tmapt) { for (uint32_t i = 0; i < vts_tmapt->nr_of_tmaps; i++) { if (vts_tmapt->tmap[i].nr_of_entries == 0) { // Early out if zero entries continue; } map_ent_t * map_ent=vts_tmapt->tmap[i].map_ent; newPos=0; for (uint32_t j = 0; j < vts_tmapt->tmap[i].nr_of_entries; j++) { //bit 31 indicates whether VOBU time codes are discontinous with previous uint32_t mask=map_ent[j] & 0x80000000 ; uint32_t value=map_ent[j] & 0x7FFFFFFF; if (remapVobu(&value) !=NULL) { map_ent[j]=value | mask; map_ent[newPos]=map_ent[j]; newPos++; } else map_ent[j]=0; } for (int j = newPos; j < vts_tmapt->tmap[i].nr_of_entries;j++) map_ent[j]=0; vts_tmapt->tmap[i].nr_of_entries=newPos; } } update4Menu(hifo); ifo.saveIFO(); } void k9DVDBackup::updateVob(k9CellList *cellLst) { int nbVobuUpdated=0; uchar buffer[DVD_VIDEO_LB_LEN]; QFile *file=NULL; QString dbg; int pVobNum=-1; //for (uint iCell=0;iCellcells.count();iCell++) { // k9Cell *cell=currTS->cells.at(iCell); for (int iCell=0;iCell< cellLst->count();iCell++) { k9Cell *cell=cellLst->at(iCell); for (int ivobu=0; ivobuvobus.count();ivobu++) { k9Tools::processEvents(); k9Vobu * vobu = cell->vobus.at(ivobu); int VobNum=vobu->vobNum; if (error) return; if (pVobNum !=VobNum) { if (file !=NULL) { file->close(); delete file; } //fclose(file); QString sName; if (currVTS==0) sName="VIDEO_TS.VOB"; else sName.sprintf("VTS_%02d_%d.VOB",(int)currVTS,(int)VobNum); dbg=i18n("Updating vob %1").arg(sName); sName=output+"/"+sName; QFileInfo finfo(sName); long fileSize=finfo.size(); setTotalSteps(fileSize); setProgressLabel(dbg); file =new QFile(sName); file->open(QIODevice::ReadWrite | QIODevice::Unbuffered); //file=fopen(sName,"r+b"); pVobNum=VobNum; } if ( file !=NULL) { uint32_t sector=0; long pos=vobu->vobPos; setProgress(pos); if (isAborted()) { seterror(i18n("DVD backup canceled")); break; } bool emptyPgc=false; file->seek(pos); //fread(buffer,DVD_VIDEO_LB_LEN,1,file); file->read((char*)buffer,DVD_VIDEO_LB_LEN); if (k9Cell::isNavPack((uchar*)buffer)) { dsi_t dsiPack; pci_t pciPack; nbVobuUpdated++; navRead_DSI (&dsiPack, buffer + DSI_START_BYTE); k9Ifo2::navRead_PCI (&pciPack, buffer+0x2d); sector=dsiPack.dsi_gi.nv_pck_lbn; //JMP : pour debug //vobu=remapVobu(&dsiPack.dsi_gi.nv_pck_lbn ); sector=vobu->oldSector; dsiPack.dsi_gi.nv_pck_lbn=vobu->newSector; if (m_userOps) memset(&(pciPack.pci_gi.vobu_uop_ctl),0,sizeof(user_ops_t)); if (vobu != NULL) { dsiPack.dsi_gi.vobu_ea = vobu->size; emptyPgc=vobu->empty; } else { dbg.sprintf("remapVobu failed for %d",dsiPack.dsi_gi.nv_pck_lbn); } if (!emptyPgc) { remapOffset(sector, &dsiPack.vobu_sri.next_video,1 ); for (int i =0;i<19;i++) { remapOffset(sector,&dsiPack.vobu_sri.fwda[i],1); } remapOffset(sector,&dsiPack.vobu_sri.next_vobu,1); remapOffset(sector,&dsiPack.vobu_sri.prev_vobu,-1); for (int i =0;i<19;i++) { remapOffset(sector,&dsiPack.vobu_sri.bwda[i],-1); } remapOffset(sector,&dsiPack.vobu_sri.prev_video,-1); //1st audio packet for (int i =0 ;i <8 ;i++) { //if (((dsiPack.synci.a_synca[i] & 0x8000) != 0x8000 ) && (dsiPack.synci.a_synca[i] !=0x3FFF) && (dsiPack.synci.a_synca[i] !=0x0)) { if ( (dsiPack.synci.a_synca[i] !=0x3FFF) && (dsiPack.synci.a_synca[i] !=0x0)) { if (vobu->firstAudio[i] !=-1) { dsiPack.synci.a_synca[i]=vobu->firstAudio [i]; } else { //JMP dsiPack.synci.a_synca[i] =0; dsiPack.synci.a_synca[i] =0x3FFF; } } } //1st subpicture packet for (int i =0 ;i <32 ;i++) { // if (((dsiPack.synci.sp_synca[i] & 0x80000000) != 0x80000000) && // (dsiPack.synci.sp_synca[i] != 0x3FFFFFFF) && (dsiPack.synci.sp_synca[i] != 0x7FFFFFFF) && (dsiPack.synci.sp_synca[i] != 0x0)) { if ((dsiPack.synci.sp_synca[i] != 0x3FFFFFFF) && (dsiPack.synci.sp_synca[i] != 0x0)) { if (vobu->firstSubp[i] !=-1) { dsiPack.synci.sp_synca[i]=vobu->firstSubp [i]; } else { //JMP dsiPack.synci.sp_synca[i] =0; dsiPack.synci.sp_synca[i] =0x3FFFFFFF; } } } //ILVU for (int i=0;i<9;i++) { if (dsiPack.sml_agli.data[i].address !=0 && dsiPack.sml_agli.data[i].address !=0x7FFFFFFF) { uint32_t tmpAdr=dsiPack.sml_agli.data[i].address; uint32_t tmpSize=(dsiPack.sml_agli.data[i].address & 0x7FFFFFFF) + dsiPack.sml_agli.data[i].size; int dir; if ((tmpAdr & 0x80000000) ==0x80000000) dir=-1; else dir=1; remapOffset(sector,&tmpAdr,dir); remapOffset(sector,&tmpSize,1); dsiPack.sml_agli.data[i].address=tmpAdr; dsiPack.sml_agli.data[i].size=tmpSize-(tmpAdr &0x7FFFFFFF); } } if (dsiPack.sml_pbi.ilvu_ea !=0) { uint32_t tmp=dsiPack.sml_pbi.ilvu_ea+1; remapOffset(sector,&tmp,1); if (tmp!=0) tmp--; dsiPack.sml_pbi.ilvu_ea=tmp; } if (dsiPack.sml_pbi.ilvu_sa !=0) { k9Vobu *vobu2=remapOffset(sector,&dsiPack.sml_pbi.ilvu_sa,1); if (vobu2!= NULL) { QFile *file2; if ( vobu2->vobNum != VobNum) { QString sName; sName.sprintf("/VTS_%02d_%d.VOB",(int)currVTS,(int)vobu2->vobNum); sName=output+sName; file2=new QFile(sName); file2->open(QIODevice::ReadWrite |QIODevice::Unbuffered); //file2=fopen(sName,"rb"); } else file2=file; file2->seek(vobu2->vobPos); uchar *tmpbuff=new uchar[2048]; //fread(tmpbuff,DVD_VIDEO_LB_LEN,1,file2); file2->read( (char*)tmpbuff,DVD_VIDEO_LB_LEN); dsi_t dsiNext; navRead_DSI (&dsiNext, tmpbuff + DSI_START_BYTE); uint32_t sectmp= dsiNext.sml_pbi.ilvu_ea+1; remapOffset(dsiNext.dsi_gi.nv_pck_lbn,§mp,1); dsiPack.sml_pbi.size=sectmp; delete tmpbuff; if (vobu2->vobNum!=VobNum) { file2->close(); delete file2; } } } // end block reference frames dsiPack.dsi_gi.vobu_1stref_ea = vobu->firstRef; dsiPack.dsi_gi.vobu_2ndref_ea=vobu->secondRef; dsiPack.dsi_gi.vobu_3rdref_ea=vobu->thirdRef; // update pci pack for (int i=0; i<9;i++) { if ((pciPack.nsml_agli.nsml_agl_dsta[i] & 0x80000000) != 0x80000000) remapOffset(sector,&pciPack.nsml_agli.nsml_agl_dsta[i],1); } } else { dsiPack.vobu_sri.next_video= 0xbfffffff; for (int i =0;i<19;i++) dsiPack.vobu_sri.fwda[i] = 0x3fffffff; dsiPack.vobu_sri.next_vobu=0x3fffffff; dsiPack.vobu_sri.prev_vobu=0x3fffffff; for (int i =0;i<19;i++) dsiPack.vobu_sri.bwda[i] = 0x3fffffff; dsiPack.vobu_sri.prev_video=0xbfffffff; for (int i =0 ;i <8 ;i++) dsiPack.synci.a_synca[i]=0x3fff; for (int i =0 ;i <32 ;i++) dsiPack.synci.sp_synca[i] =0x3FFFFFFF; // end block reference frames dsiPack.dsi_gi.vobu_1stref_ea = 0; dsiPack.dsi_gi.vobu_2ndref_ea=0; dsiPack.dsi_gi.vobu_3rdref_ea=0; //JMP for tests pciPack.pci_gi.vobu_s_ptm=0; pciPack.pci_gi.vobu_e_ptm=0; pciPack.pci_gi.vobu_se_e_ptm=0; pciPack.pci_gi.e_eltm.hour = pciPack.pci_gi.e_eltm.minute =pciPack.pci_gi.e_eltm.second=0; dsiPack.dsi_gi.c_eltm.hour=dsiPack.dsi_gi.c_eltm.minute=dsiPack.dsi_gi.c_eltm.second=0; for (int i=0;i<9;i++) { dsiPack.sml_agli.data[i].address=0x7FFFFFFF; dsiPack.sml_agli.data[i].size=0; } dsiPack.sml_pbi.ilvu_ea=0; dsiPack.sml_pbi.ilvu_sa=0; dsiPack.sml_pbi.size=0; dsiPack.dsi_gi.vobu_1stref_ea = 0; dsiPack.dsi_gi.vobu_2ndref_ea=0; dsiPack.dsi_gi.vobu_3rdref_ea=0; } // mise en place des donnees modifi�s dans le buffer de sortie navRead_DSI((dsi_t*)(buffer + DSI_START_BYTE),(uchar*)&dsiPack); pciPack.pci_gi.nv_pck_lbn =dsiPack.dsi_gi.nv_pck_lbn; k9Ifo2::navRead_PCI((pci_t*)(buffer+0x2d),(uchar*)&pciPack); //mise �jour du fichier file->seek(pos); file->write((const char*)buffer,DVD_VIDEO_LB_LEN); } } else { qDebug ("erreur positionning"); } } } if (file!=NULL) { file->close(); delete file; } } uint k9DVDBackup::getLastCell(k9CellCopyList *_cellCopyList, uint _index) { k9Cell *orig=(k9Cell*)_cellCopyList->at(_index); uint result=_index; uint64_t dsize=1+orig->lastSector-orig->startSector; uchar audioOrig[8]; uchar subpOrig[32]; memset(audioOrig,0,sizeof(uchar)*8); memset(subpOrig,0,sizeof(uchar)*32); foreach (int audio, orig->audio) audioOrig[audio -1]=1; foreach (int subp, orig->subpicture) subpOrig[subp -1]=1; float factor=-1; for (int iCell=_index+1;(iCell<_cellCopyList->count()) ;iCell++) { k9Cell *cell=(k9Cell*)_cellCopyList->at(iCell); if ((cell->vts== orig->vts) && ( cell->selected)) { //if the cell factor changed, it's a new group of cells if (factor==-1) factor=cell->getFactor(); else { if (cell->getFactor()!=factor) break; } uchar audio[8]; uchar subp[32]; memset(audio,0,sizeof(uchar)*8); memset(subp,0,sizeof(uchar)*32); foreach (int it, cell->audio ) audio[it -1]=1; foreach ( int it, cell->subpicture ) subp[it -1]=1; if ( (memcmp(audioOrig,audio,sizeof(uchar)*8) ==0) && (memcmp(subpOrig,subp,sizeof(uchar)*32) ==0)) { result=iCell; dsize+=1+cell->lastSector-cell->startSector; } else break; } else break; } dsize*=DVD_BLOCK_LEN; argSize=dsize; return result; } void k9DVDBackup::calcFactor() { double factor=m_cellCopyList->getfactor(m_withMenu,false); QString sFactor; sFactor.sprintf("%.2f",factor); showFactor(sFactor); argFactor = factor; m_forcedFactor=false; } void k9DVDBackup::forceFactor(double _factor) { double factor=_factor; double minFactor=m_cellCopyList->getMinFactor( m_withMenu); if (factorgetDVDTitle()); QDir dir(output); dir.mkpath(output); k9Tools::clearOutput(output); dir.mkdir("VIDEO_TS"); dir.mkdir("AUDIO_TS"); output=QDir::cleanPath(output +"/VIDEO_TS"); m_dvdread->openDevice(device); if (!m_dvdread->opened()) { seterror(i18n("Unable to open DVD")); return; } k9CellCopyList *cellCopyList =new k9CellCopyList(m_dvdread,DVD); m_cellCopyList=cellCopyList; double totalSize=cellCopyList->gettotalSize(); if (m_withMenu) totalSize+=DVD->getmenuSize() *2048 ; totalSize/=(1024*1024); totalSize = (totalSize >k9DVDSize::getMaxSize()) ? k9DVDSize::getMaxSize():totalSize; setTotalMax((uint32_t)totalSize); int lastCell; calcFactor(); //VTSList is sorted by size, so it is easier to ajust the compression factor for (int iTS=0;iTSVTSList.count() &&(!error);iTS++) { k9CellCopyVTS *VTS=cellCopyList->VTSList.at(iTS); //loop on each cell from the titleset lastCell=-1; for (int iCell=0;(iCellcount()) ;iCell++) { k9Cell *cell=(k9Cell*)cellCopyList->at(iCell); if (cell->vts==(int) VTS->getnum() && (!cell->copied)) { // currCopyCell=cell; if (lastCell < (int)iCell) { lastCell=getLastCell( cellCopyList,iCell); //adjusting factor of compression if ( cell->getforceFactor()) forceFactor( cell->getFactor()); else calcFactor(); } copyCell(cell->vts,cell,! cell->selected); if (!error) { cell->copied=true; } // } if (lastCell==(int)iCell) { vamps->setNoData(); vamps->wait(); } if (error) break; } } vamps->setNoData(); vamps->wait(); } delete cellCopyList; if (!error) { updateIfo(); outputFile->close(); delete outputFile; outputFile=NULL; updateVob(&currTS->cells); updateMainIfo(); } output=sOutput; if(backupDlg) backupDlg->hide(); if (error) k9Dialogs::error(errMsg,"DVD Backup"); //m_dvdread->close(); } void k9DVDBackup::setUserOps(bool theValue) { m_userOps = theValue; } void k9DVDBackup::setTotalSteps(uint32_t _value) { if (k9Tools::getBatchCopy()) { k9log::writer(QString("total :%1").arg(_value)); m_total=_value; } else backupDlg->setTotalSteps(_value); } void k9DVDBackup::setProgress (uint32_t _value) { if (k9Tools::getBatchCopy()) k9log::writer(QString("current :%1").arg((double)_value/(double)m_total)); else backupDlg->setProgress(_value); } void k9DVDBackup::setProgressTotal (uint32_t _value) { if (k9Tools::getBatchCopy()) k9log::writeln(QString("total :%1").arg((double)_value/(double)m_totalMax)); else backupDlg->setProgressTotal(_value); } void k9DVDBackup::showFactor (QString _value) { if (k9Tools::getBatchCopy()) k9log::writeln(QString("shrink factor :%1").arg(_value)); else backupDlg->setFactor(_value); } void k9DVDBackup::setTotalMax (uint32_t _value) { if (k9Tools::getBatchCopy()) { k9log::writeln(QString("total size :%1").arg(_value)); m_totalMax=_value; } else backupDlg->setTotalMax(_value); } void k9DVDBackup::setProgressLabel (QString _value) { if (k9Tools::getBatchCopy()) k9log::writeln(_value); else backupDlg->setProgressLabel(_value); } k9copy/src/backup/k9execcopy.h0000644000175000017550000000323212412271774017042 0ustar emulatoremulator// // C++ Interface: k9execcopy // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: <>, (C) 2008 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9EXECCOPY #define K9EXECCOPY #include "k9dvd.h" #include #if QT_VERSION >= 0x050000 #include #else #include #endif class k9ResultingFile; class k9ExecCopy:public QObject { Q_OBJECT public: enum eOutput {oDVD,oISO,oFolder}; k9ExecCopy(); void CreateMP4(); void extractMPEG2(); void extractAudio(); void setDvd(k9DVD* theValue) { m_dvd = theValue; } void setOutput(const eOutput& theValue) { m_output = theValue; } void setCopyMenus(bool theValue) { m_copyMenus = theValue; } void setPath(const QString& theValue) { m_path = theValue; } void setSpeed(const QString& theValue); bool isCancelled() { return m_cancelled; } void setDvdSize( int theValue) { m_dvdSize=theValue; } private: k9DVD *m_dvd; bool m_cancelled; QString m_speed; QString m_path; eOutput m_output; bool m_copyMenus; #if QT_VERSION >= 0x050000 QProgressDialog *m_progressDialog; #else KProgressDialog *m_progressDialog; #endif void createMkv(k9DVDTitle *_title,const QString &_filename,QMultiMap< int, k9ResultingFile* > _files,int _nbParts, const QString &_aspect) ; QStringList m_outputMsg; int m_mkvPos; int m_dvdSize; protected slots: void MkvStdout(char *, int ); void finished(int, QProcess::ExitStatus); public slots: void copyDVD(); }; #endif k9copy/src/backup/mp4dlg.ui0000644000175000017550000002714112417731553016342 0ustar emulatoremulator MP4Dlg 0 0 443 529 WaitCursor Encoding 0 0 75 true WaitCursor Encoding false QTabWidget::South 0 Preview 2 0 0 0 250 255 255 255 0 0 0 255 255 255 0 0 0 0 0 0 0 0 0 WaitCursor true true false Status QFrame::StyledPanel QFrame::Raised 0 0 0 WaitCursor QFrame::NoFrame QFrame::Plain 4 WaitCursor Qt::AlignVCenter false WaitCursor Qt::AlignVCenter false WaitCursor false WaitCursor false WaitCursor fps false WaitCursor Elapsed Time false WaitCursor Bitrate false WaitCursor Size false WaitCursor pbProgress Qt::Vertical QSizePolicy::Fixed 20 16 Qt::Horizontal QSizePolicy::Expanding 225 21 0 0 ArrowCursor 26 KPushButton KPushButton
kpushbutton.h
bCancel clicked() MP4Dlg Cancel() 20 20 20 20 bPlayToggled(bool)
k9copy/src/backup/k9dvdauthor.cpp0000755000175000017550000005333512412271774017572 0ustar emulatoremulator/************************************************************************** * Developer: Pauline123 , (C) 2014 * Copyright (C) 2005 by Jean-Michel Petit * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "k9dvdauthor.h" #include "k9dvdtitle.h" #include "k9dvdbackup.h" #include "k9tools.h" #include #include #include #include #include #include #include #include #include #include #include #include #if QT_VERSION >= 0x050000 #include #else #include #endif #include "kmessagebox.h" #include #include #include #if QT_VERSION >= 0x050000 //Qt 5 Code #ifndef FALSE #define FALSE (0) #endif #ifndef TRUE #define TRUE (!FALSE) #endif #include #else // Qt 4 Code #include #endif class k9Progress; k9DVDAuthor::k9DVDAuthor(QObject *DVDStruct) { DVD=(k9DVD*)DVDStruct; xml=NULL; cancelled=false; error=false; if (k9Tools::getBatchCopy()) progress=NULL; else progress = new k9Progress(k9Dialogs::getMainWidget()); // files.setAutoDelete(true); } k9DVDAuthor::~k9DVDAuthor() { foreach (QTemporaryFile *it,files) { it->remove(); } while (!files.isEmpty()) delete files.takeFirst(); if (xml!=NULL) delete xml; } /** No descriptions */ void k9DVDAuthor::createXML() { int i; if (xml!=NULL) delete xml; xml=new QDomDocument(); QDomElement root = xml->createElement( "dvdauthor" ); root.setAttribute ("dest",workDir+DVD->getDVDTitle()); xml->appendChild( root ); // Create vmgm menu QDomElement vmgm = xml->createElement("vmgm"); root.appendChild(vmgm); addMenus(vmgm); m_forced=0; m_forcedsh=0; //computes the size of related titles for (int iTitle=0; iTitle < DVD->gettitleCount();iTitle++) { k9DVDTitle *title=DVD->gettitle(iTitle); if (title->isSelected() && title->getIndexed()) { for (int iTitle2=0;iTitle2getTitles().count() ;iTitle2++) { k9DVDTitle *title2=title->getTitles().at(iTitle2); if (title->getforceFactor()) { m_forced+=title2->getsectors()*2048; m_forcedsh+=(title2->getsectors()/title->getfactor())*2048; } } } //total size of forced titles if (title->isSelected() && title->getforceFactor()) { m_forced+=title->getsectors()*2048; m_forcedsh+=(title->getsectors()/title->getfactor())*2048; } } //total size of titles to copy m_totalSize=((uint64_t)DVD->getsizeSelected(false))*DVD_VIDEO_LB_LEN ;//+ m_totalPartSize -chapterssize*DVD_VIDEO_LB_LEN; m_firsttitle=true; for (i=0;i< DVD->gettitleCount();i++) { k9DVDTitle *tmp = DVD->gettitle(i); addTitle(root,tmp); } QString x = xml->toString(); //QFile file( locateLocal("tmp", "k9copy/k9author.xml" )); // if ( file.open( IO_WriteOnly ) ) { QTextStream stream( m_xml ); xml->save(stream,1); m_xml->close(); // } } void k9DVDAuthor::addMenus(QDomElement &titleSet) { int i; QDomElement menu,video,pgc,pre,vob,button; QDomText precmd; QDomText buttonText; QTime max(0,0); QString c,start; k9DVDTitle * l_track= DVD->getstart(); if (l_track==NULL) { start="call vmgm menu;"; } else { if ( DVD->getnewTitleNum(l_track)==-1) { error=true; QString sMsg; //sMsg.QString::sprintf(tr2i18n("'%s' not selected"),l_track->getname().latin1()); sMsg=i18n("'%1' not selected").arg(l_track->getname()); k9Dialogs::error( sMsg, i18n("authoring")); } start.sprintf("jump titleset %d menu;",DVD->getnewTitleNum(l_track)); } factor=DVD->getfactor(false,false,true); menu=xml->createElement("menus"); titleSet.appendChild(menu); video=xml->createElement("video"); video.setAttribute("format",DVD->getFormat()); menu.appendChild(video); pgc=xml->createElement("pgc"); pgc.setAttribute("entry","title"); menu.appendChild(pgc); pre=xml->createElement("pre"); pgc.appendChild(pre); precmd=xml->createTextNode(""); QString cmd="if (g0==0) \n { \n subtitle=0; \n g0=1;\n "+start+"\n}\n"; pre.appendChild(precmd); int numt=0; for (i=0;i < DVD->gettitleCount();i++) { if (DVD->gettitle(i)->isSelected() && DVD->gettitle(i)->getIndexed()) { ++numt; cmd+=c.sprintf("if (g1==%d) {jump titleset %d menu;}\n", numt,numt); } } precmd.setNodeValue(cmd); } /** No descriptions */ void k9DVDAuthor::addTitle(QDomElement &root, k9DVDTitle *title) { int i,j; k9DVDSubtitle *l_sub; k9DVDAudioStream *l_auds; k9DVDTitle *l_track= title; QDomElement e,t,pgc; QString caud="",csub="",c,palette; if (l_track->isSelected() && l_track->getIndexed()) { double titleFactor; if (l_track->getforceFactor()) titleFactor=l_track->getfactor(); else titleFactor=factor; QDomElement titleSet = xml->createElement("titleset"); root.appendChild(titleSet); QDomElement titleMenu = xml->createElement("menus"); titleSet.appendChild(titleMenu); QDomElement video=xml->createElement("video"); titleMenu.appendChild(video); video.setAttribute("format",l_track->getformat().toLower()); QDomElement pgc = xml->createElement("pgc"); titleMenu.appendChild(pgc); QDomElement pre = xml->createElement("pre"); pgc.appendChild(pre); QDomText precmd=xml->createTextNode(""); int subtitle=0,audio=-1; if (l_track->getDefSubtitle() != NULL) { for (int isub=0;isubgetsubPictureCount();isub++) { if (l_track->getsubtitle(isub)->getselected()) { subtitle++; } if (l_track->getsubtitle(isub)==l_track->getDefSubtitle()) break; } } if (l_track->getDefAudio() != NULL) { for (int iaud=0;iaud < l_track->getaudioStreamCount();iaud++) { if (l_track->getaudioStream(iaud)->getselected()) { audio++; } if (l_track->getaudioStream(iaud)==l_track->getDefAudio()) break; } } QString txtcmd; if (audio !=-1) { txtcmd="subtitle=%1;\n audio=%2;\n g1=0;jump title 1;"; txtcmd=txtcmd.arg(subtitle+63).arg(audio); } else { txtcmd="subtitle=%1;\n g1=0;jump title 1;"; txtcmd=txtcmd.arg(subtitle+63); } precmd.setNodeValue(txtcmd); pre.appendChild(precmd); //create palette for subpictures QTemporaryFile *paletteFile=new QTemporaryFile(m_tempPath+"/k9pXXXXXX.yuv"); paletteFile->setAutoRemove(false); paletteFile->open(); files.append(paletteFile); palette=paletteFile->fileName(); //palette.sprintf("palette%d.yuv",l_track->getnumTitle()); //palette= locateLocal("tmp", "k9copy/k9" +palette); QTextStream stream( paletteFile ); for (j=0;j<16;j++) { l_track->getpalette(j,c); stream << c+"\n"; } paletteFile->close(); t=xml->createElement("titles"); titleSet.appendChild(t); e=xml->createElement("video"); e.setAttribute("aspect",l_track->getaspectRatio()); e.setAttribute("format",l_track->getformat().toLower()); if (l_track->getaspectRatio()!="4:3") { e.setAttribute("widescreen","nopanscan"); } t.appendChild(e); for (i=0;igetaudioStreamCount();i++) { l_auds=l_track->getaudioStream(i); if (l_auds->getselected()) { e=xml->createElement("audio"); e.setAttribute("format",l_auds->getformat()); e.setAttribute("channels",l_auds->getchannels()); e.setAttribute("quant",l_auds->getquantization()); e.setAttribute("lang",l_auds->getlangCod()); t.appendChild(e); if (caud != "") caud+=','; caud+=c.sprintf("%d",l_auds->getID()); } } for (i=0;igetsubPictureCount();i++) { l_sub=l_track->getsubtitle(i); if (l_sub->getselected()) { e=xml->createElement("subpicture"); e.setAttribute("lang",l_sub->getlangCod()); t.appendChild(e); if (csub !="") csub+=','; csub+=c.sprintf("%d",(l_sub->getID()).first()); } } pgc=xml->createElement("pgc"); pgc.setAttribute("palette",palette); t.appendChild(pgc); /* for (i=0;igetaudioStreamCount();i++) { l_auds=l_track->getaudioStream(i); if (l_auds->getselected()) { e=xml->createElement("audio"); e.setAttribute("id",l_auds->getID()-1); t.appendChild(e); if (caud != "") caud+=','; caud+=c.sprintf("%d",l_auds->getID()); } } for (i=0;igetsubPictureCount();i++) { l_sub=l_track->getsubtitle(i); if (l_sub->getselected()) { e=xml->createElement("subpicture"); e.setAttribute("id",(l_sub->getID()).first()-1); t.appendChild(e); if (csub !="") csub+=','; csub+=c.sprintf("%d",(l_sub->getID()).first()); } } */ if (caud !="") caud="--audiofilter "+caud; if (csub !="") csub="--subpicturefilter "+csub; int numPart=0; for (int iTitle=0;iTitle<=l_track->getTitles().count();iTitle++) { k9DVDTitle *title; if (iTitle==0) title=l_track; else title=l_track->getTitles().at(iTitle-1); for (i=0;igetchapterCount();i++) { numPart++; uint icell=0; k9DVDChapter *l_chap=title->getChapter(i); if ((!l_chap->getSelected()) || (l_chap->getLength() <=QTime(0,0,0,1))) continue; bool first=true; uint32_t chapterSize= (l_chap->getendSector()-l_chap->getstartSector())*DVD_VIDEO_LB_LEN; QString sChapter,sCell; foreach (k9ChapterCell *cell ,l_chap->cells) { icell++; sCell = QString("--cell %1").arg(icell); sChapter=QString("--chapter %1").arg(numPart); //test uint32_t itotSize = (cell->getlastSector()-cell->getstartSector())* DVD_VIDEO_LB_LEN; QString file; e=xml->createElement("vob"); QString playPgm=""; playPgm="/k9play"; if (!k9Tools::getBatchCopy()) playPgm +=" --gui"; file=QString(qApp->applicationDirPath()+ playPgm+" --play --input %1 --dvdtitle %2 %3 %4 %5 %6 --vampsfactor %7 --inputsize %8 --chaptersize %9 ") .arg(KShell::quoteArg(DVD->getDevice())) .arg(title->getnumTitle()) .arg(sChapter) .arg(sCell) .arg(caud) .arg(csub) .arg(titleFactor,0,'f',2) .arg(itotSize) .arg(chapterSize); if (m_firsttitle) { file +=" --initstatus "; m_firsttitle=false; } if (l_track->getforceFactor()) { file +=" --ffactor "; } file +=QString(" --inject %1 --totalsize %2 --dvdsize %3 |") .arg(KShell::quoteArg(inject)) .arg(m_totalSize -m_forced ) .arg(((uint64_t)k9DVDSize::getMaxSize() *1024 *1024) - m_forcedsh); e.setAttribute("file",file); if (first) e.setAttribute("chapters",l_chap->getTime().toString("0")); pgc.appendChild(e); first=false; } // } } } QDomElement post = xml->createElement("post"); pgc.appendChild(post); QDomText postcmd=xml->createTextNode(""); k9DVDTitle * l_next=l_track->getnextTitle(); if (l_next!=NULL) { c.sprintf("g1=%d;\ncall vmgm menu;",DVD->getnewTitleNum(l_next)); if ( DVD->getnewTitleNum(l_next)==-1) { error=true; c=i18n("'%1' not selected").arg(l_next->getname()); k9Dialogs::error( c, i18n("authoring")); } postcmd.setNodeValue(c); } post.appendChild(postcmd); } } const QString& k9DVDAuthor::getworkDir() { return workDir; } void k9DVDAuthor::setworkDir( const QString& _newVal) { workDir = _newVal; if (!workDir.endsWith('/')) workDir +='/'; } void k9DVDAuthor::author() { k9Config config; if ( ! k9Tools::checkProgram("dvdauthor")) { k9Dialogs::error (i18n("Unable to run %1").arg("dvdauthor") , i18n("authoring")); error = TRUE; return; } bool burnOk=false; //nettoyage du répertoire de sortie k9Tools::clearOutput(workDir+DVD->getDVDTitle()); time = new QTime(0,0); time->start(); m_tempPath=config.getPrefOutput(); QDir dir; dir.mkpath(workDir+DVD->getDVDTitle()); dir.mkpath(m_tempPath); if (progress) { progress->setTitle(i18n("Authoring")); #if QT_VERSION >= 0x050000 progress->setWindowTitle((i18n("Backup progression"))); #else progress->setWindowTitle(KDialog::makeStandardCaption(i18n("Backup progression"))); #endif } setProgress(0,100); //progress->show(); m_xml=new QTemporaryFile(m_tempPath+"/k9aXXXXXX.xml"); m_xml->open(); QString fileName=m_xml->fileName(); m_inject=new QTemporaryFile(m_tempPath+"/k9vXXXXXX.inj"); m_inject->open(); inject=m_inject->fileName(); if (!cancelled && !error) createXML(); // if (error || cancelled) // delete progress; //run dvdauthor if (!cancelled && !error) { QString c(config.getPrefDvdauthorPath(true)); if (k9Tools::getBatchCopy()) proc=new k9Process(this,0); else proc=progress->getProcess();// new QProcess(c,0); *proc << c << "-x" << fileName; //locateLocal("tmp", "k9copy/k9author.xml"); connect( proc, SIGNAL(receivedStderr(char *, int)), this, SLOT(DVDAuthorStderr(char *, int )) ); connect( proc, SIGNAL(receivedStdout(char *, int )), this, SLOT(DVDAuthorStdout(char *, int)) ); // connect(progress, SIGNAL(cancelled()), this, SLOT(stopProcess())); m_copied=0; m_lastPos=0; //if (m_totalSize >k9DVDSize::getMaxSize()) // m_totalSize=k9DVDSize::getMaxSize(); proc-> setWorkingDirectory(workDir); int result=execProcess(); if ( result==-1 ) { if (k9Tools::getBatchCopy()) k9log::writeln(QString("dvdauthor error :%1").arg(lastMsg)); else k9Dialogs::error(i18n("Dvdauthor error :\n") + lastMsg,i18n("authoring")); } else { cancelled=(result==0); if ((proc->exitStatus()==0) && (proc->normalExit()) && !cancelled && !error) { burnOk=true; } else { if (cancelled) { //QMessageBox::critical( 0, tr2i18n("authoring"), tr2i18n("Authoring canceled")); k9Dialogs::error( i18n("Authoring cancelled"),i18n("authoring")); } else if (k9Tools::getBatchCopy()) k9log::writeln(QString("dvdauthor error :%1").arg(lastMsg)); else k9Dialogs::error( i18n("An error occured while running DVDAuthor:\n")+lastMsg ,i18n("authoring")); } } // delete proc; // delete progress; if (!burnOk) { error=true; } } delete time; m_xml->remove(); m_inject->remove(); delete m_inject; delete m_xml; } /** No descriptions */ void k9DVDAuthor::DVDAuthorStderr(char *buffer, int buflen ) { //QString m_stderr(proc->readStderr()); QString m_stderr=QString::fromLatin1(buffer, buflen); float m_percent; QString m_remain; int pos=m_stderr.indexOf("INFOPOS:"); if (pos!=-1) { if (progress) progress->setTitle(i18n("Authoring")); QString tmp=m_stderr.mid(pos); uint32_t totalBytes,totalSize; sscanf(tmp.toUtf8(),"INFOPOS: %d %d",&totalBytes,&totalSize); //if (totalBytes>m_lastPos) // m_copied+=totalBytes - m_lastPos; m_copied=totalBytes; m_lastPos=totalBytes; //qDebug(QString("copied : %1 totalSize : %2").arg(m_copied).arg(m_totalSize*512)); m_percent=(float)m_copied / (float)(m_totalSize/DVD_VIDEO_LB_LEN ); QTime time2(0,0); time2=time2.addMSecs(time->elapsed()); if (m_percent>0) { QTime time3(0,0); time3=time3.addMSecs((uint32_t)(time->elapsed()*(1/m_percent))); m_remain=time3.toString("hh:mm:ss"); } m_percent*=100; setProgress(m_percent,100); if (progress) { progress->setElapsed(time2.toString("hh:mm:ss") +" / " +m_remain); progress->setLabelText(""); } } /* else { if (!m_stderr.startsWith("libdvdread") && m_stderr.startsWith("libdvdnav")) qDebug(m_stderr); } */ int end; lastMsg=m_stderr; if (m_stderr.contains("STAT:")) { pos=m_stderr.indexOf("fixing VOBU"); if (pos!=-1) { if (progress) { progress->setTitle(i18n("Authoring")); progress->setLabelText(i18n("Fixing VOBUS")); } else k9log::writeln("fixing VOBUS"); end=m_stderr.indexOf("%"); if (end!=-1) { pos =end -2; m_stderr=m_stderr.mid(pos,end-pos); m_stderr=m_stderr.trimmed(); //progress->setLabelText(c); setProgress(m_stderr.toInt(),100); } } } pos=m_stderr.indexOf("INFOIMAGE:"); if (pos!=-1 && progress) { progress->setImage(m_stderr.mid(pos+10)); } } void k9DVDAuthor::DVDAuthorStdout(char *buffer, int buflen) { QString c=QString::fromLatin1( buffer,buflen); //(proc->readStdout()); int pos; pos=c.indexOf("STAT"); if (pos!=-1) { c=c.mid(pos); if (progress) progress->setLabelText(c); k9Tools::processEvents(); } } /** No descriptions */ void k9DVDAuthor::stopProcess() { proc->kill(); cancelled=true; } /** Read property of bool burnDVD. */ const bool& k9DVDAuthor::getburnDVD() { return burnDVD; } /** Write property of bool burnDVD. */ void k9DVDAuthor::setburnDVD( const bool& _newVal) { burnDVD = _newVal; } bool k9DVDAuthor::getError() { return error; } void k9DVDAuthor::setProgress(long _position,long _total) { if (k9Tools::getBatchCopy()) k9log::writer(QString("current :%1").arg((double)_position/(double)_total)); else progress->setProgress(_position,_total); } int k9DVDAuthor::execProcess() { if (!k9Tools::getBatchCopy()) return progress->execute(); else { if (! proc->isRunning()) { k9log::writeln(proc->debug()); if (!proc->start()) return -1; } //the sync method allows to wait for the process end while receiving stdout. proc->sync(); if (proc->normalExit()) return 1; else return -1; } } k9copy/src/mpeg2/0000755000175000017550000000000012412271774014353 5ustar emulatoremulatork9copy/src/mpeg2/k9plaympeg2.cpp0000644000175000017550000002046312412307160017215 0ustar emulatoremulator// // C++ Implementation: k9plaympeg2 // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9plaympeg2.h" #include "kdecmpeg2.h" #include "dvdnav/dvdnav.h" //PM DVDNAV #include k9PlayMPEG2::k9PlayMPEG2() { m_title=NULL; m_stopped=true; connect (&m_timer,SIGNAL(timeout()),this,SLOT(timeout())); } k9PlayMPEG2::~k9PlayMPEG2() { stop(); } void k9PlayMPEG2::updatePos( uint32_t _position) { m_idxLect=_position; m_decoder.clear(); } void k9PlayMPEG2::timeout() { emit setPosition(m_position); } #define DVD_LANGUAGE "en" #define DVD_READ_CACHE 1 void k9PlayMPEG2::playTitle() { dvdnav_t *dvdnav; uint8_t mem[DVD_VIDEO_LB_LEN]; int finished = 0; int32_t tt = 0,ptt=0; uint32_t pos, lgr; int title=m_title->getnumTitle(); /* open dvdnav handle */ //PM DVDNAV if (dvdnav_open(&dvdnav, m_device.toUtf8(),m_dvd) != DVDNAV_STATUS_OK) { if (dvdnav_open(&dvdnav, m_device.toUtf8()) != DVDNAV_STATUS_OK) { setError("ERR:Error on dvdnav_open\n"); return ; } /* set read ahead cache usage */ if (dvdnav_set_readahead_flag(dvdnav, DVD_READ_CACHE) != DVDNAV_STATUS_OK) { setError(QString("ERR:Error on dvdnav_set_readahead_flag: %1\n").arg(dvdnav_err_to_string(dvdnav))); return; } /* set the language */ if (dvdnav_menu_language_select(dvdnav, DVD_LANGUAGE) != DVDNAV_STATUS_OK || dvdnav_audio_language_select(dvdnav, DVD_LANGUAGE) != DVDNAV_STATUS_OK || dvdnav_spu_language_select(dvdnav, DVD_LANGUAGE) != DVDNAV_STATUS_OK) { setError(QString("ERR:Error on setting languages: %1\n").arg(dvdnav_err_to_string(dvdnav))); return ; } /* set the PGC positioning flag to have position information relatively to the * whole feature instead of just relatively to the current chapter */ if (dvdnav_set_PGC_positioning_flag(dvdnav, 1) != DVDNAV_STATUS_OK) { setError(QString("ERR:Error on dvdnav_set_PGC_positioning_flag: %1\n").arg(dvdnav_err_to_string(dvdnav))); return ; } int32_t parts; dvdnav_get_number_of_parts(dvdnav , title, &parts); if (m_chapter==0) dvdnav_title_play(dvdnav , title); else dvdnav_part_play(dvdnav , title,m_chapter); /* the read loop which regularly calls dvdnav_get_next_block * and handles the returned events */ while (!finished && !m_stopped && qApp!=NULL) { int result, event, len; uint8_t *buf = mem; if (m_idxLect !=0xFFFFFFFF) { dvdnav_sector_search(dvdnav, m_idxLect,SEEK_SET); m_idxLect=0xFFFFFFFF; } /* the main reading function */ #ifdef DVD_READ_CACHE result = dvdnav_get_next_cache_block(dvdnav, &buf, &event, &len); #else result = dvdnav_get_next_block(dvdnav, buf, &event, &len); #endif if (result == DVDNAV_STATUS_ERR) { setError(QString("ERR:Error getting next block: %1\n").arg(dvdnav_err_to_string(dvdnav))); return; } switch (event) { case DVDNAV_NAV_PACKET: { dvdnav_current_title_info(dvdnav, &tt, &ptt); dvdnav_get_position(dvdnav, &pos, &lgr); if (tt != title) finished=1; if (finished==0 && buf[17]==0xE0 && !m_stopped) { m_decoder.addData( buf,len); } // if (qApp->tryLock()) { m_position= pos; // qApp->unlock(); // } } break; //removed break --> save case DVDNAV_BLOCK_OK: /* We have received a regular block of the currently playing MPEG stream.*/ if (!m_stopped) m_decoder.addData( buf,len); break; case DVDNAV_NOP: /* Nothing to do here. */ break; case DVDNAV_STILL_FRAME: /* We have reached a still frame. A real player application would wait * the amount of time specified by the still's length while still handling * user input to make menus and other interactive stills work. * A length of 0xff means an indefinite still which has to be skipped * indirectly by some user interaction. */ { // dvdnav_still_event_t *still_event = (dvdnav_still_event_t *)buf; dvdnav_still_skip(dvdnav); } break; case DVDNAV_WAIT: /* We have reached a point in DVD playback, where timing is critical. * Player application with internal fifos can introduce state * inconsistencies, because libdvdnav is always the fifo's length * ahead in the stream compared to what the application sees. * Such applications should wait until their fifos are empty * when they receive this type of event. */ dvdnav_wait_skip(dvdnav); break; case DVDNAV_SPU_CLUT_CHANGE: /* Player applications should pass the new colour lookup table to their * SPU decoder */ break; case DVDNAV_SPU_STREAM_CHANGE: /* Player applications should inform their SPU decoder to switch channels */ break; case DVDNAV_AUDIO_STREAM_CHANGE: /* Player applications should inform their audio decoder to switch channels */ break; case DVDNAV_HIGHLIGHT: /* Player applications should inform their overlay engine to highlight the * given button */ { // dvdnav_highlight_event_t *highlight_event = (dvdnav_highlight_event_t *)buf; } break; case DVDNAV_VTS_CHANGE: /* Some status information like video aspect and video scale permissions do * not change inside a VTS. Therefore this event can be used to query such * information only when necessary and update the decoding/displaying * accordingly. */ break; case DVDNAV_CELL_CHANGE: // dvdnav_get_position(dvdnav, &pos, &lgr); break; case DVDNAV_HOP_CHANNEL: /* This event is issued whenever a non-seamless operation has been executed. * Applications with fifos should drop the fifos content to speed up responsiveness. */ break; case DVDNAV_STOP: /* Playback should end here. */ { finished = 1; } break; default: finished = 1; break; } #ifdef DVD_READ_CACHE dvdnav_free_cache_block(dvdnav, buf); #endif } m_decoder.setNoData(); /* destroy dvdnav handle */ dvdnav_close(dvdnav); } void k9PlayMPEG2::run() { m_stopped=false; m_idxLect=m_startSector; m_decoder.start(QThread::LowPriority); playTitle(); m_decoder.Stop(); m_decoder.wait(); m_timer.stop(); } void k9PlayMPEG2::stop() { m_stopped=true; m_decoder.setNoData(); m_decoder.clear(); /* m_decoder.wait(); */ wait(); } void k9PlayMPEG2::play() { if (m_stopped && m_title!=NULL) { m_stopped=false; m_startSector=m_title->getChapter( 0)->getstartSector(); m_lastSector= m_startSector + m_title->getsectors(); //m_title->getChapter(m_title->getchapterCount()-1)->getendSector(); m_position=m_startSector; emit setPosition( m_startSector); emit setMax( m_lastSector); emit setMin( m_startSector); start(); m_timer.start(100); //open(m_dvd,m_device,m_title,m_chapter); } } k9DecodeThread *k9PlayMPEG2::getDecoder() { return &m_decoder; } void k9PlayMPEG2::open (dvd_reader_t *dvd,const QString & device,k9DVDTitle * title,int chapter=0) { m_dvd=dvd; m_chapter=chapter; int ret = 0; struct stat dvd_stat; QString c; m_idxLect=0xFFFFFFFF; stop(); m_title=title; m_device=device; m_startSector=0; m_lastSector=0; ret = stat(device.toUtf8(), &dvd_stat); /* if ( ret < 0 ) { c=i18n("Can't find device %1\n").arg(device.latin1()); setError(c); return; } */ m_title=title; m_startSector=m_title->getChapter( 0)->getstartSector(); m_lastSector= m_startSector + m_title->getsectors(); //m_title->getChapter(m_title->getchapterCount()-1)->getendSector(); emit setPosition( m_startSector); emit setMax( m_lastSector); emit setMin( m_startSector); // start(); } k9copy/src/mpeg2/kdecmpeg2.cpp0000755000175000017550000002530512412271774016730 0ustar emulatoremulator/************************************************************************** * Copyright (C) 2005 by Jean-Michel Petit * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "kdecmpeg2.h" #include #include #include #include #include "k9saveimage.h" #include "k9decodethread.h" extern "C" { #include #include } void kDecMPEG2::init() { demux_pid=0; m_thread=NULL; demux_track=0xe0; decoder = mpeg2_init (); m_opened=true; if (decoder == NULL) { fprintf (stderr, "Could not allocate a decoder object.\n"); exit (1); } } kDecMPEG2::kDecMPEG2(k9DecodeThread *_thread) { init(); m_thread=_thread; } kDecMPEG2::kDecMPEG2(){ init(); } #define DEMUX_PAYLOAD_START 1 int kDecMPEG2::demux (uint8_t * buf, uint8_t * end, int flags) { static int mpeg1_skip_table[16] = { 0, 0, 4, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* * the demuxer keeps some state between calls: * if "state" = DEMUX_HEADER, then "head_buf" contains the first * "bytes" bytes from some header. * if "state" == DEMUX_DATA, then we need to copy "bytes" bytes * of ES data before the next header. * if "state" == DEMUX_SKIP, then we need to skip "bytes" bytes * of data before the next header. * * NEEDBYTES makes sure we have the requested number of bytes for a * header. If we dont, it copies what we have into head_buf and returns, * so that when we come back with more data we finish decoding this header. * * DONEBYTES updates "buf" to point after the header we just parsed. */ #define DEMUX_HEADER 0 #define DEMUX_DATA 1 #define DEMUX_SKIP 2 static int state = DEMUX_SKIP; static int state_bytes = 0; static uint8_t head_buf[264]; uint8_t * header; int bytes; int len; #define NEEDBYTES(x) \ do { \ int missing; \ \ missing = (x) - bytes; \ if (missing > 0) { \ if (header == head_buf) { \ if (missing <= end - buf) { \ memcpy (header + bytes, buf, missing); \ buf += missing; \ bytes = (x); \ } else { \ memcpy (header + bytes, buf, end - buf); \ state_bytes = bytes + end - buf; \ return 0; \ } \ } else { \ memcpy (head_buf, header, bytes); \ state = DEMUX_HEADER; \ state_bytes = bytes; \ return 0; \ } \ } \ } while (0) #define DONEBYTES(x) \ do { \ if (header != head_buf) \ buf = header + (x); \ } while (0) if (flags & DEMUX_PAYLOAD_START) goto payload_start; switch (state) { case DEMUX_HEADER: if (state_bytes > 0) { header = head_buf; bytes = state_bytes; goto continue_header; } break; case DEMUX_DATA: if (demux_pid || (state_bytes > end - buf)) { decode_mpeg2 (buf, end); state_bytes -= end - buf; return 0; } decode_mpeg2 (buf, buf + state_bytes); buf += state_bytes; break; case DEMUX_SKIP: if (demux_pid || (state_bytes > end - buf)) { state_bytes -= end - buf; return 0; } buf += state_bytes; break; } m_pause=false; while (!m_pause) { if (demux_pid) { state = DEMUX_SKIP; return 0; } payload_start: header = buf; bytes = end - buf; continue_header: NEEDBYTES (4); if (header[0] || header[1] || (header[2] != 1)) { if (demux_pid) { state = DEMUX_SKIP; return 0; } else if (header != head_buf) { buf++; goto payload_start; } else { header[0] = header[1]; header[1] = header[2]; header[2] = header[3]; bytes = 3; goto continue_header; } } if (demux_pid) { if ((header[3] >= 0xe0) && (header[3] <= 0xef)) goto pes; fprintf (stderr, "bad stream id %x\n", header[3]); exit (1); } switch (header[3]) { case 0xb9: /* program end code */ /* DONEBYTES (4); */ /* break; */ return 1; case 0xba: /* pack header */ NEEDBYTES (5); if ((header[4] & 0xc0) == 0x40) { /* mpeg2 */ NEEDBYTES (14); len = 14 + (header[13] & 7); NEEDBYTES (len); DONEBYTES (len); /* header points to the mpeg2 pack header */ } else if ((header[4] & 0xf0) == 0x20) { /* mpeg1 */ NEEDBYTES (12); DONEBYTES (12); /* header points to the mpeg1 pack header */ } else { fprintf (stderr, "weird pack header\n"); DONEBYTES (5); } break; default: if (header[3] == demux_track) { pes: NEEDBYTES (7); if ((header[6] & 0xc0) == 0x80) { /* mpeg2 */ NEEDBYTES (9); len = 9 + header[8]; NEEDBYTES (len); /* header points to the mpeg2 pes header */ if (header[7] & 0x80) { uint32_t pts, dts; pts = (((header[9] >> 1) << 30) | (header[10] << 22) | ((header[11] >> 1) << 15) | (header[12] << 7) | (header[13] >> 1)); dts = (!(header[7] & 0x40) ? pts : (((header[14] >> 1) << 30) | (header[15] << 22) | ((header[16] >> 1) << 15) | (header[17] << 7) | (header[18] >> 1))); mpeg2_tag_picture (decoder, pts, dts); } } else { /* mpeg1 */ int len_skip; uint8_t * ptsbuf; len = 7; while (header[len - 1] == 0xff) { len++; NEEDBYTES (len); if (len > 23) { fprintf (stderr, "too much stuffing\n"); break; } } if ((header[len - 1] & 0xc0) == 0x40) { len += 2; NEEDBYTES (len); } len_skip = len; len += mpeg1_skip_table[header[len - 1] >> 4]; NEEDBYTES (len); /* header points to the mpeg1 pes header */ ptsbuf = header + len_skip; if ((ptsbuf[-1] & 0xe0) == 0x20) { uint32_t pts, dts; pts = (((ptsbuf[-1] >> 1) << 30) | (ptsbuf[0] << 22) | ((ptsbuf[1] >> 1) << 15) | (ptsbuf[2] << 7) | (ptsbuf[3] >> 1)); dts = (((ptsbuf[-1] & 0xf0) != 0x30) ? pts : (((ptsbuf[4] >> 1) << 30) | (ptsbuf[5] << 22) | ((ptsbuf[6] >> 1) << 15) | (ptsbuf[7] << 7) | (ptsbuf[18] >> 1))); mpeg2_tag_picture (decoder, pts, dts); } } DONEBYTES (len); bytes = 6 + (header[4] << 8) + header[5] - len; if (demux_pid || (bytes > end - buf)) { decode_mpeg2 (buf, end); state = DEMUX_DATA; state_bytes = bytes - (end - buf); return 0; } else if (bytes > 0) { decode_mpeg2 (buf, buf + bytes); buf += bytes; } } else if (header[3] < 0xb9) { fprintf (stderr,"looks like a video stream, not system stream\n"); DONEBYTES (4); } else { NEEDBYTES (6); DONEBYTES (6); bytes = (header[4] << 8) + header[5]; if (bytes > end - buf) { state = DEMUX_SKIP; state_bytes = bytes - (end - buf); return 0; } buf += bytes; } } } return 0; } void kDecMPEG2::sync() { int t=40- m_timer.elapsed(); if (t>0 && m_thread!=NULL) { m_thread->sleepms(t); } m_timer.restart(); } void kDecMPEG2::save_ppm (int width, int height, uint8_t * buf, int ) { m_thread->pgm_save((uchar*) buf,0,width,height); } void kDecMPEG2::decode_mpeg2(uint8_t * current, uint8_t * end) { const mpeg2_info_t * info; mpeg2_state_t state; int framenum = 0; mpeg2_buffer (decoder, current, end); info = mpeg2_info (decoder); while (1) { state = mpeg2_parse (decoder); switch (state) { case STATE_BUFFER: return; case STATE_SEQUENCE: mpeg2_convert (decoder, mpeg2convert_rgb (MPEG2CONVERT_RGB,24), NULL); break; case STATE_PICTURE: break; case STATE_SLICE: case STATE_END: case STATE_INVALID_END: if (info->display_fbuf ) save_ppm (info->sequence->width, info->sequence->height,info->display_fbuf->buf[0], framenum++); break; default: break; } } } int kDecMPEG2::decode (uint8_t * buf, uint8_t * end, int ) { mutex.lock(); if (buf && end) demux (buf,end,0); mutex.unlock(); return 0; } kDecMPEG2::~kDecMPEG2(){ if (m_opened) mpeg2_close (decoder); } void kDecMPEG2::restart() { mutex.lock(); if (m_opened) mpeg2_close (decoder); decoder = mpeg2_init (); m_opened=true; if (decoder == NULL) { fprintf (stderr, "Could not allocate a decoder object.\n"); } mutex.unlock(); } void kDecMPEG2::start() { m_timer.start(); decoder = mpeg2_init (); m_opened=true; if (decoder == NULL) { fprintf (stderr, "Could not allocate a decoder object.\n"); exit (1); } } void kDecMPEG2::stop() { if (m_opened) mpeg2_close(decoder); m_opened=false; } void kDecMPEG2::pause() { m_pause=true; } k9copy/src/mpeg2/CTestTestfile.cmake0000664000175000017550000000051512412271774020102 0ustar emulatoremulator# CMake generated Testfile for # Source directory: /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/src/mpeg2 # Build directory: /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/src/mpeg2 # # This file includes the relevant testing commands required for # testing this directory and lists subdirectories to be tested as well. k9copy/src/mpeg2/k9decodethread.h0000644000175000017550000000244112412271774017404 0ustar emulatoremulator// // C++ Interface: k9decodethread // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9DECODETHREAD_H #define K9DECODETHREAD_H #include "k9common.h" #include "k9vamps.h" #include #include #include #include "kdecmpeg2.h" /** @author Jean-Michel PETIT */ class k9SaveImage; class k9InternalPlayer; class k9BackupDlg; class k9DecodeThread : public QThread { private: k9MemoryFifo m_fifo; QWaitCondition wDataRead; QWaitCondition wDataReady; bool noData; kDecMPEG2 *m_decmpeg2; k9SaveImage *m_saveImage; k9InternalPlayer *m_viewMpeg2; k9InternalPlayer *m_backupDlg; public: k9DecodeThread(); ~k9DecodeThread(); void addData(uchar *data,uint size); void setNoData(); void clear(); void sleepms(int _ms); void setSaveImage(k9SaveImage* theValue); void setViewMpeg2(k9InternalPlayer* theValue); void setBackupDlg(k9InternalPlayer* theValue); void Stop(); void test(); void pgm_save(uchar * buf,int wrap,int width,int height); uint32_t freespace(); uint32_t count(); protected: int readData(uchar * data,uint size); void run(); }; #endif k9copy/src/mpeg2/Makefile0000664000175000017550000001501612412271774016020 0ustar emulatoremulator# CMAKE generated file: DO NOT EDIT! # Generated by "Unix Makefiles" Generator, CMake Version 2.8 # Default target executed when no arguments are given to make. default_target: all .PHONY : default_target #============================================================================= # Special targets provided by cmake. # Disable implicit rules so canonical targets will work. .SUFFIXES: # Remove some rules from gmake that .SUFFIXES does not remove. SUFFIXES = .SUFFIXES: .hpux_make_needs_suffix_list # Suppress display of executed commands. $(VERBOSE).SILENT: # A target that is always out of date. cmake_force: .PHONY : cmake_force #============================================================================= # Set environment variables for the build. # The shell in which to execute make rules. SHELL = /bin/sh # The CMake executable. CMAKE_COMMAND = /usr/bin/cmake # The command to remove a file. RM = /usr/bin/cmake -E remove -f # Escaping for special characters. EQUALS = = # The program to use to edit the cache. CMAKE_EDIT_COMMAND = /usr/bin/ccmake # The top-level source directory on which CMake was run. CMAKE_SOURCE_DIR = /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 # The top-level build directory on which CMake was run. CMAKE_BINARY_DIR = /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 #============================================================================= # Targets provided globally by CMake. # Special rule for the target edit_cache edit_cache: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." /usr/bin/ccmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) .PHONY : edit_cache # Special rule for the target edit_cache edit_cache/fast: edit_cache .PHONY : edit_cache/fast # Special rule for the target install install: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." /usr/bin/cmake -P cmake_install.cmake .PHONY : install # Special rule for the target install install/fast: preinstall/fast @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." /usr/bin/cmake -P cmake_install.cmake .PHONY : install/fast # Special rule for the target install/local install/local: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..." /usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake .PHONY : install/local # Special rule for the target install/local install/local/fast: install/local .PHONY : install/local/fast # Special rule for the target list_install_components list_install_components: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"Unspecified\"" .PHONY : list_install_components # Special rule for the target list_install_components list_install_components/fast: list_install_components .PHONY : list_install_components/fast # Special rule for the target package package: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Run CPack packaging tool..." cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && /usr/bin/cpack --config ./CPackConfig.cmake .PHONY : package # Special rule for the target package package/fast: package .PHONY : package/fast # Special rule for the target package_source package_source: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Run CPack packaging tool for source..." cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && /usr/bin/cpack --config ./CPackSourceConfig.cmake /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CPackSourceConfig.cmake .PHONY : package_source # Special rule for the target package_source package_source/fast: package_source .PHONY : package_source/fast # Special rule for the target rebuild_cache rebuild_cache: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." /usr/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) .PHONY : rebuild_cache # Special rule for the target rebuild_cache rebuild_cache/fast: rebuild_cache .PHONY : rebuild_cache/fast # Special rule for the target test test: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running tests..." /usr/bin/ctest --force-new-ctest-process $(ARGS) .PHONY : test # Special rule for the target test test/fast: test .PHONY : test/fast # The main all target all: cmake_check_build_system cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(CMAKE_COMMAND) -E cmake_progress_start /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CMakeFiles /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/src/mpeg2/CMakeFiles/progress.marks cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 src/mpeg2/all $(CMAKE_COMMAND) -E cmake_progress_start /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CMakeFiles 0 .PHONY : all # The main clean target clean: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 src/mpeg2/clean .PHONY : clean # The main clean target clean/fast: clean .PHONY : clean/fast # Prepare targets for installation. preinstall: all cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 src/mpeg2/preinstall .PHONY : preinstall # Prepare targets for installation. preinstall/fast: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 src/mpeg2/preinstall .PHONY : preinstall/fast # clear depends depend: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 .PHONY : depend # Help Target help: @echo "The following are some of the valid targets for this Makefile:" @echo "... all (the default if no target is provided)" @echo "... clean" @echo "... depend" @echo "... edit_cache" @echo "... install" @echo "... install/local" @echo "... list_install_components" @echo "... package" @echo "... package_source" @echo "... rebuild_cache" @echo "... test" .PHONY : help #============================================================================= # Special targets to cleanup operation of make. # Special rule to run CMake to check the build system integrity. # No rule that depends on this can have commands that come from listfiles # because they might be regenerated. cmake_check_build_system: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 .PHONY : cmake_check_build_system k9copy/src/mpeg2/k9plaympeg2.h0000644000175000017550000000254512412271774016676 0ustar emulatoremulator// // C++ Interface: k9plaympeg2 // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9PLAYMPEG2_H #define K9PLAYMPEG2_H #include "k9common.h" #include "k9dvdtitle.h" #include #include #include #include #include #include "k9decodethread.h" /** @author Jean-Michel PETIT */ class k9PlayMPEG2 : public QThread { Q_OBJECT private: k9DVDTitle *m_title; QString m_device; k9DecodeThread m_decoder; uint32_t m_idxLect; uint32_t m_startSector; uint32_t m_lastSector; bool m_stopped; dvd_file_t *dvdfile; QMutex mutex; dvd_reader_t *m_dvd; int m_chapter; int m_position; QTimer m_timer; public: k9PlayMPEG2(); void open (dvd_reader_t *dvd,const QString & device,k9DVDTitle * title,int chapter); k9DecodeThread *getDecoder(); void setDvd(dvd_reader_t* _value) { m_dvd = _value;} dvd_reader_t* getDvd() const {return m_dvd;} ~k9PlayMPEG2(); protected: void run(); void playTitle(); public slots: void stop(); void play(); void updatePos(uint32_t _position); void timeout(); signals: void setPosition(uint _position); void setMin(uint _sector); void setMax(uint _sector); void setError(const QString & err); }; #endif k9copy/src/mpeg2/CMakeFiles/0000775000175000017550000000000012412271774016320 5ustar emulatoremulatork9copy/src/mpeg2/CMakeFiles/progress.marks0000664000175000017550000000000212412271774021213 0ustar emulatoremulator0 k9copy/src/mpeg2/CMakeFiles/CMakeDirectoryInformation.cmake0000664000175000017550000000124312412271774024375 0ustar emulatoremulator# CMAKE generated file: DO NOT EDIT! # Generated by "Unix Makefiles" Generator, CMake Version 2.8 # Relative path conversion top directories. SET(CMAKE_RELATIVE_PATH_TOP_SOURCE "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4") SET(CMAKE_RELATIVE_PATH_TOP_BINARY "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4") # Force unix paths in dependencies. SET(CMAKE_FORCE_UNIX_PATHS 1) # The C and CXX include file regular expressions for this directory. SET(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") SET(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") SET(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) SET(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) k9copy/src/mpeg2/k9decodethread.cpp0000644000175000017550000000525312412271774017743 0ustar emulatoremulator// // C++ Implementation: k9decodethread // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9decodethread.h" #include "k9internalplayer.h" #include "k9saveimage.h" #include #if QT_VERSION >= 0x050000 //Qt 5 Code #ifndef FALSE #define FALSE (0) #endif #ifndef TRUE #define TRUE (!FALSE) #endif #else // Qt 4 Code #endif k9DecodeThread::k9DecodeThread() { noData=FALSE; m_viewMpeg2=NULL; m_backupDlg=NULL; m_saveImage=NULL; m_decmpeg2=new kDecMPEG2(this); } k9DecodeThread::~k9DecodeThread() { setNoData(); wait(); delete m_decmpeg2; } void k9DecodeThread::clear() { m_fifo.clear(); wDataRead.wakeAll(); wDataReady.wakeAll(); } void k9DecodeThread::addData(uchar *data,uint size) { if (! isRunning()) start(); m_fifo.addData(data,size); } uint32_t k9DecodeThread::freespace() { return m_fifo.freespace(); } uint32_t k9DecodeThread::count() { return m_fifo.count(); } int k9DecodeThread::readData(uchar * data,uint size) { return m_fifo.readData(data,size); } void k9DecodeThread::setNoData() { noData=true; m_fifo.setNoData(); wDataRead.wakeAll(); wDataReady.wakeAll(); } void k9DecodeThread::sleepms(int _ms) { msleep(_ms); } #define INBUF_SIZE 2048 void k9DecodeThread::test() { } void k9DecodeThread::run() { noData=FALSE; m_decmpeg2->start(); while (1) { int count=2048; uchar buffer[count]; uint32_t size=readData(buffer,count); if (size==0 && noData) break; m_decmpeg2->decode(buffer ,buffer+size,0); } m_decmpeg2->stop(); } void k9DecodeThread::pgm_save(uchar * buf,int wrap,int width,int height) { if (noData) return; int len; len =(int) (3*width*height); char c[255]; sprintf(c,"P6\n%d %d\n255\n", width, height); char *s; s= new char[len+strlen(c)]; memcpy(s,c,strlen(c)); memcpy(s+strlen(c),buf, len); QImage pix; pix.loadFromData((uchar*)s,strlen(c)+len); delete s; if (m_viewMpeg2) m_viewMpeg2->drawImage(&pix); else if (m_saveImage) m_saveImage->drawImage(&pix); else if (m_backupDlg) m_backupDlg->drawImage(&pix); } void k9DecodeThread::setSaveImage(k9SaveImage* theValue) { m_saveImage = theValue; } void k9DecodeThread::setViewMpeg2(k9InternalPlayer* theValue) { m_viewMpeg2 = theValue; } void k9DecodeThread::setBackupDlg(k9InternalPlayer* theValue) { m_backupDlg = theValue; } void k9DecodeThread::Stop() { setNoData(); } k9copy/src/mpeg2/CMakeLists.txt0000644000175000017550000000000012412271774017101 0ustar emulatoremulatork9copy/src/mpeg2/kdecmpeg2.h0000755000175000017550000000470412412271774016375 0ustar emulatoremulator/************************************************************************** * Copyright (C) 2005 by Jean-Michel Petit * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef KDECMPEG2_H #define KDECMPEG2_H #include "k9common.h" #include "k9internalplayer.h" #include #include #include #include #include #include #include #include extern "C" { #include } /** *@author */ class kDecMPEG2; class k9SaveImage; class k9DecodeThread; class kDecMPEG2 : public QObject { Q_OBJECT public: kDecMPEG2(k9DecodeThread *_thread); kDecMPEG2(); ~kDecMPEG2(); int decode (uint8_t * buf, uint8_t * end, int flags); void restart(); void start(); void stop(); void pause(); private: bool m_pause; k9DecodeThread *m_thread; QImage pix; QTime m_timer; bool m_opened; int demux_pid; int demux_track; QMutex mutex; mpeg2dec_t * decoder; int demux (uint8_t * buf, uint8_t * end, int flags); void save_ppm (int width, int height, uint8_t * buf, int num); void decode_mpeg2(uint8_t * current, uint8_t * end); void init(); void sync(); }; #endif k9copy/src/mpeg2/cmake_install.cmake0000664000175000017550000000225612412271774020172 0ustar emulatoremulator# Install script for directory: /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/src/mpeg2 # Set the install prefix IF(NOT DEFINED CMAKE_INSTALL_PREFIX) SET(CMAKE_INSTALL_PREFIX "/usr/local") ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") # Set the install configuration name. IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) IF(BUILD_TYPE) STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") ELSE(BUILD_TYPE) SET(CMAKE_INSTALL_CONFIG_NAME "RelWithDebInfo") ENDIF(BUILD_TYPE) MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) # Set the component getting installed. IF(NOT CMAKE_INSTALL_COMPONENT) IF(COMPONENT) MESSAGE(STATUS "Install component: \"${COMPONENT}\"") SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") ELSE(COMPONENT) SET(CMAKE_INSTALL_COMPONENT) ENDIF(COMPONENT) ENDIF(NOT CMAKE_INSTALL_COMPONENT) # Install shared libraries without execute permission? IF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) SET(CMAKE_INSTALL_SO_NO_EXE "0") ENDIF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) k9copy/src/devices/0000755000175000017550000000000012412271774014763 5ustar emulatoremulatork9copy/src/devices/CTestTestfile.cmake0000664000175000017550000000052112412271774020507 0ustar emulatoremulator# CMake generated Testfile for # Source directory: /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/src/devices # Build directory: /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/src/devices # # This file includes the relevant testing commands required for # testing this directory and lists subdirectories to be tested as well. k9copy/src/devices/Makefile0000664000175000017550000001503012412271774016424 0ustar emulatoremulator# CMAKE generated file: DO NOT EDIT! # Generated by "Unix Makefiles" Generator, CMake Version 2.8 # Default target executed when no arguments are given to make. default_target: all .PHONY : default_target #============================================================================= # Special targets provided by cmake. # Disable implicit rules so canonical targets will work. .SUFFIXES: # Remove some rules from gmake that .SUFFIXES does not remove. SUFFIXES = .SUFFIXES: .hpux_make_needs_suffix_list # Suppress display of executed commands. $(VERBOSE).SILENT: # A target that is always out of date. cmake_force: .PHONY : cmake_force #============================================================================= # Set environment variables for the build. # The shell in which to execute make rules. SHELL = /bin/sh # The CMake executable. CMAKE_COMMAND = /usr/bin/cmake # The command to remove a file. RM = /usr/bin/cmake -E remove -f # Escaping for special characters. EQUALS = = # The program to use to edit the cache. CMAKE_EDIT_COMMAND = /usr/bin/ccmake # The top-level source directory on which CMake was run. CMAKE_SOURCE_DIR = /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 # The top-level build directory on which CMake was run. CMAKE_BINARY_DIR = /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 #============================================================================= # Targets provided globally by CMake. # Special rule for the target edit_cache edit_cache: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." /usr/bin/ccmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) .PHONY : edit_cache # Special rule for the target edit_cache edit_cache/fast: edit_cache .PHONY : edit_cache/fast # Special rule for the target install install: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." /usr/bin/cmake -P cmake_install.cmake .PHONY : install # Special rule for the target install install/fast: preinstall/fast @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." /usr/bin/cmake -P cmake_install.cmake .PHONY : install/fast # Special rule for the target install/local install/local: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..." /usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake .PHONY : install/local # Special rule for the target install/local install/local/fast: install/local .PHONY : install/local/fast # Special rule for the target list_install_components list_install_components: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"Unspecified\"" .PHONY : list_install_components # Special rule for the target list_install_components list_install_components/fast: list_install_components .PHONY : list_install_components/fast # Special rule for the target package package: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Run CPack packaging tool..." cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && /usr/bin/cpack --config ./CPackConfig.cmake .PHONY : package # Special rule for the target package package/fast: package .PHONY : package/fast # Special rule for the target package_source package_source: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Run CPack packaging tool for source..." cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && /usr/bin/cpack --config ./CPackSourceConfig.cmake /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CPackSourceConfig.cmake .PHONY : package_source # Special rule for the target package_source package_source/fast: package_source .PHONY : package_source/fast # Special rule for the target rebuild_cache rebuild_cache: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." /usr/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) .PHONY : rebuild_cache # Special rule for the target rebuild_cache rebuild_cache/fast: rebuild_cache .PHONY : rebuild_cache/fast # Special rule for the target test test: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running tests..." /usr/bin/ctest --force-new-ctest-process $(ARGS) .PHONY : test # Special rule for the target test test/fast: test .PHONY : test/fast # The main all target all: cmake_check_build_system cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(CMAKE_COMMAND) -E cmake_progress_start /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CMakeFiles /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/src/devices/CMakeFiles/progress.marks cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 src/devices/all $(CMAKE_COMMAND) -E cmake_progress_start /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CMakeFiles 0 .PHONY : all # The main clean target clean: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 src/devices/clean .PHONY : clean # The main clean target clean/fast: clean .PHONY : clean/fast # Prepare targets for installation. preinstall: all cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 src/devices/preinstall .PHONY : preinstall # Prepare targets for installation. preinstall/fast: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 src/devices/preinstall .PHONY : preinstall/fast # clear depends depend: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 .PHONY : depend # Help Target help: @echo "The following are some of the valid targets for this Makefile:" @echo "... all (the default if no target is provided)" @echo "... clean" @echo "... depend" @echo "... edit_cache" @echo "... install" @echo "... install/local" @echo "... list_install_components" @echo "... package" @echo "... package_source" @echo "... rebuild_cache" @echo "... test" .PHONY : help #============================================================================= # Special targets to cleanup operation of make. # Special rule to run CMake to check the build system integrity. # No rule that depends on this can have commands that come from listfiles # because they might be regenerated. cmake_check_build_system: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 .PHONY : cmake_check_build_system k9copy/src/devices/CMakeFiles/0000775000175000017550000000000012412271774016730 5ustar emulatoremulatork9copy/src/devices/CMakeFiles/progress.marks0000664000175000017550000000000212412271774021623 0ustar emulatoremulator0 k9copy/src/devices/CMakeFiles/CMakeDirectoryInformation.cmake0000664000175000017550000000124312412271774025005 0ustar emulatoremulator# CMAKE generated file: DO NOT EDIT! # Generated by "Unix Makefiles" Generator, CMake Version 2.8 # Relative path conversion top directories. SET(CMAKE_RELATIVE_PATH_TOP_SOURCE "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4") SET(CMAKE_RELATIVE_PATH_TOP_BINARY "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4") # Force unix paths in dependencies. SET(CMAKE_FORCE_UNIX_PATHS 1) # The C and CXX include file regular expressions for this directory. SET(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") SET(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") SET(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) SET(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) k9copy/src/devices/k9cddrive.h0000644000175000017550000000376512412271774017033 0ustar emulatoremulator// // C++ Interface: k9cddrive // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9CDDRIVE_H #define K9CDDRIVE_H #include "k9common.h" #include "config.h" #include #include #include #include #if QT_VERSION >= 0x050000 #include #include #else #include #include #endif /** *@author */ class k9HalDevice; class k9HalConnection; class k9CdDrives; class k9CdDrive : public QObject { Q_OBJECT friend class k9CdDrives; public: k9CdDrive(); ~k9CdDrive(); int num; QString name; QString device; bool canWriteCDR; bool canReadDVD; bool canWriteDVD; static void setReadAhead(const QString &_device,int _value); void setWriteSpeeds(const QList< int >& _value); QList< int > getWriteSpeeds() const; void setDevice(Solid::Device _value); Solid::Device getDevice() { return m_Device;} public slots: void ejectPressed (const QString &udi); private: QList writeSpeeds; Solid::Device m_Device; signals: void volumeChanged(const QString &device, const QString &volumeName); }; class k9CdDrives : public QObject { Q_OBJECT public: k9CdDrives(QObject *parent); ~k9CdDrives(); /** No descriptions */ int count(); /** No descriptions */ k9CdDrive * getDrive(int num); static void eject(const QString & device); void scanDrives(); void clearDrives(); static k9CdDrive *getDeviceFromMountpoint(k9CdDrives *drives,const QString &mountpoint); public slots: void deviceAdded (const QString &udi); void deviceRemoved (const QString &udi); signals: void deviceAdded(k9CdDrive *drive); void deviceRemoved(k9CdDrive *drive); private: // Private methods void readConfig(); QList drives; }; #endif k9copy/src/devices/CMakeLists.txt0000644000175000017550000000000012412271774017511 0ustar emulatoremulatork9copy/src/devices/cmake_install.cmake0000664000175000017550000000226012412271774020575 0ustar emulatoremulator# Install script for directory: /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/src/devices # Set the install prefix IF(NOT DEFINED CMAKE_INSTALL_PREFIX) SET(CMAKE_INSTALL_PREFIX "/usr/local") ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") # Set the install configuration name. IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) IF(BUILD_TYPE) STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") ELSE(BUILD_TYPE) SET(CMAKE_INSTALL_CONFIG_NAME "RelWithDebInfo") ENDIF(BUILD_TYPE) MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) # Set the component getting installed. IF(NOT CMAKE_INSTALL_COMPONENT) IF(COMPONENT) MESSAGE(STATUS "Install component: \"${COMPONENT}\"") SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") ELSE(COMPONENT) SET(CMAKE_INSTALL_COMPONENT) ENDIF(COMPONENT) ENDIF(NOT CMAKE_INSTALL_COMPONENT) # Install shared libraries without execute permission? IF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) SET(CMAKE_INSTALL_SO_NO_EXE "0") ENDIF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) k9copy/src/devices/k9cddrive.cpp0000644000175000017550000001610412412271774017355 0ustar emulatoremulator// // C++ Implementation: k9cddrive // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "k9common.h" #include "k9cddrive.h" #include "k9config.h" #include "k9tools.h" #include "config.h" #include "k9process.h" #include #include #include #include #include #include #include #if QT_VERSION >= 0x050000 #include #else #include #endif k9CdDrive::k9CdDrive() { canReadDVD=false; canWriteCDR=false; canWriteDVD=false; device=""; name=""; } k9CdDrive::~k9CdDrive() {} void k9CdDrive::ejectPressed (const QString &udi) { Q_UNUSED(udi); Solid::Block *block=m_Device.as(); emit volumeChanged(block->device(), ""); } void k9CdDrive::setDevice(Solid::Device _value) { m_Device = _value; Solid::OpticalDrive *drive = m_Device.as(); connect(drive,SIGNAL(ejectPressed (const QString &)),this,SLOT(ejectPressed(const QString&))); } void k9CdDrives::clearDrives() { while (!drives.isEmpty()) delete drives.takeFirst(); } k9CdDrives::k9CdDrives(QObject *parent):QObject( parent) { // drives.setAutoDelete(true); connect(Solid::DeviceNotifier::instance(),SIGNAL(deviceAdded(const QString&)),this,SLOT(deviceAdded(const QString&))); connect(Solid::DeviceNotifier::instance(),SIGNAL(deviceRemoved(const QString&)),this,SLOT(deviceRemoved(const QString&))); scanDrives(); } k9CdDrives::~k9CdDrives() { clearDrives(); } void k9CdDrives::deviceAdded( const QString &udi) { // addDrive( _device); foreach (Solid::Device device, Solid::Device::allDevices()) { if (device.udi() == udi && device.is()) { Solid::Block *block=device.as(); Solid::StorageVolume *volume=device.as(); foreach (k9CdDrive *d,drives) { if (d->device==block->device()) emit d->volumeChanged(block->device(),volume->label() ); } } if (device.udi() == udi && device.is()) { Solid::OpticalDrive *sdrive = device.as(); Solid::Block *block=device.as(); k9CdDrive *drive=new k9CdDrive; drive->setDevice( device); drive->device=block->device(); drive->name=device.product(); drive->canReadDVD= (sdrive->supportedMedia() & Solid::OpticalDrive::Dvd) == Solid::OpticalDrive::Dvd; drive->canWriteCDR=(sdrive->supportedMedia() & Solid::OpticalDrive::Cdr) == Solid::OpticalDrive::Cdr; drive->canWriteDVD=( (sdrive->supportedMedia() & Solid::OpticalDrive::Dvdr) == Solid::OpticalDrive::Dvdr ) | ((sdrive->supportedMedia() & Solid::OpticalDrive::Dvdplusr) == Solid::OpticalDrive::Dvdplusr); drive->setWriteSpeeds(sdrive->writeSpeeds()); drive->num=drives.count(); drives.append(drive); emit deviceAdded(drive); } } } void k9CdDrives::deviceRemoved(const QString &udi) { foreach (k9CdDrive *d,drives) { if (d->getDevice().udi()==udi) { emit deviceRemoved( d); drives.removeAll(d); break; } } } /** No descriptions */ void k9CdDrives::scanDrives() { clearDrives(); /* foreach (Solid::Device device, Solid::Device::listFromType(Solid::DeviceInterface::OpticalDrive, QString())) { Solid::OpticalDrive *drive = device.as(); Solid::Block *block=device.as(); } */ int row=0; foreach (Solid::Device device, Solid::Device::listFromType(Solid::DeviceInterface::OpticalDrive, QString())) { Solid::OpticalDrive *sdrive = device.as(); Solid::Block *block=device.as(); k9CdDrive *drive=new k9CdDrive; drive->setDevice( device); drive->device=block->device(); drive->name=device.product(); drive->canReadDVD= (sdrive->supportedMedia() & Solid::OpticalDrive::Dvd) == Solid::OpticalDrive::Dvd; drive->canWriteCDR=(sdrive->supportedMedia() & Solid::OpticalDrive::Cdr) == Solid::OpticalDrive::Cdr; drive->canWriteDVD=( (sdrive->supportedMedia() & Solid::OpticalDrive::Dvdr) == Solid::OpticalDrive::Dvdr ) | ((sdrive->supportedMedia() & Solid::OpticalDrive::Dvdplusr) == Solid::OpticalDrive::Dvdplusr); drive->setWriteSpeeds(sdrive->writeSpeeds()); drive->num=row; drives.append(drive); row++; emit deviceAdded(drive); } readConfig(); } void k9CdDrives::eject(const QString & device) { k9Process *process =new k9Process(); if (k9Tools::checkProgram("kdeeject")) *process <<"kdeeject" << device; else *process <<"eject" << device; process->start(); process->wait(); delete process; } /** reads devices that was entered manually **/ void k9CdDrives::readConfig() { QStringList ldev; QStringList llabels; QStringList lIO; k9Config config; ldev=config.getDevices(); llabels=config.getDevicesLabels(); lIO=config.getDevicesIO(); int row=count(); int i=0; foreach ( QString dev,ldev) { k9CdDrive *drive=new k9CdDrive; drive->device=dev; QString it2=llabels.at(i); QString it3=lIO.at(i); drive->name=(it2); QString c=(it3); if (c.contains("I")) { drive->canReadDVD=true; } if (c.contains("O")) { drive->canWriteCDR=true; drive->canWriteDVD=true; } drive->num=row; drives.append(drive); row++; i++; emit deviceAdded(drive); } } /** No descriptions */ int k9CdDrives::count() { return drives.count(); } /** No descriptions */ k9CdDrive * k9CdDrives::getDrive(int num) { return (k9CdDrive *)drives.at(num); } QList< int > k9CdDrive::getWriteSpeeds() const { return writeSpeeds; } void k9CdDrive::setWriteSpeeds(const QList< int >& _value) { writeSpeeds = _value; } void k9CdDrive::setReadAhead(const QString &_device,int _value) { QString hdparm="hdparm" ;//KStandardDirs::findExe( "hdparm",NULL,false); if (hdparm !=NULL) { QString cmd=QString("%1 -a%2 %3").arg(hdparm).arg(_value).arg(_device); qDebug() << k9Tools::runAsRoot(cmd, i18n("The root password is needed to change the read ahead property of the dvd drive")); } } k9CdDrive *k9CdDrives::getDeviceFromMountpoint(k9CdDrives *drives,const QString &mountpoint) { foreach (Solid::Device device, Solid::Device::allDevices()) { if ( device.is()) { // Solid::Block *block=device.as(); // Solid::StorageVolume *volume=device.as(); Solid::StorageAccess *access=device.as(); foreach (k9CdDrive *d,drives->drives) { if (access) if (QDir::cleanPath( access->filePath() +"/")== QDir::cleanPath(mountpoint+"/")) return d; } } } return NULL; } k9copy/src/import/0000755000175000017550000000000012417731553014654 5ustar emulatoremulatork9copy/src/import/k9newdvd.cpp0000644000175000017550000004245012412310746017110 0ustar emulatoremulator// // C++ Implementation: k9newdvd // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "k9newdvd.h" #include "k9title.h" #include "k9tools.h" #include #include #include #include #include #include "k9menu.h" #include "k9menubutton.h" #include "k9processlist.h" #include #include #include "k9cell.h" #include "k9ifo2.h" #include "dvdread/nav_types.h" #include "dvdread/ifo_types.h" //PM DVDNAV #include "dvdread.h" #include "dvdread/dvd_reader.h" #include #if QT_VERSION >= 0x050000 #include #include #include #else #include #include #include #endif k9NewDVD::k9NewDVD(QObject *parent, const char *) : QObject(parent) { m_workDir=k9Tools::getTempPath();; m_rootMenu=new k9Menu(this); m_format=PAL; } k9NewDVD::~k9NewDVD() { } bool k9NewDVDItems::compareItems(k9Title* item1,k9Title* item2) { return (item1->getNum() < item2->getNum()); } void k9NewDVD::execute() { m_cancel=false; m_error=""; m_config=new k9Config(); // connect(m_process, SIGNAL(receivedStderr(KProcess *, char *, int)),this, SLOT(getStderr(KProcess *, char *, int) )); connect(&m_aviDecode,SIGNAL(drawFrame(QImage)),this,SLOT(drawImage(QImage))); k9Tools::clearOutput(m_workDir+"dvd"); createXML(); disconnect(&m_aviDecode,SIGNAL(drawFrame(QImage)),this,SLOT(drawImage(QImage))); delete m_config; } void k9NewDVD::drawImage(QImage ) { // m_progress->setImage(*_image); } void k9NewDVD::setFormat ( const eFormat& _value ) { m_format = _value; m_rootMenu->setFormat((k9Menu::eFormat)_value); foreach (k9Title *title,m_titles) { title->getMenu()->setFormat((k9Menu::eFormat)_value); } } void k9NewDVD::createXML() { QDir d; d.mkpath(m_workDir+"/dvd"); m_rootMenu->setWorkDir(m_workDir); QString menuFileName=m_workDir+k9Tools::randomFileName()+".mpg"; m_rootMenu->setMenuFileName(menuFileName); m_xml=new QDomDocument(); QDomElement root = m_xml->createElement( "dvdauthor" ); root.setAttribute ("dest",m_workDir+"dvd"); m_xml->appendChild( root ); // Create vmgm menu QDomElement vmgm = m_xml->createElement("vmgm"); root.appendChild(vmgm); m_processList->addProgress(i18n("Creating root menu")); if (!m_rootMenu->createMenus(&vmgm)) { delete m_xml; m_error="error"; return; } addTitles(root); m_processList->execute(); m_totalEncodedSize=0; m_offset=0; m_lastvalue=0; foreach (QString file,m_tmpFiles) { if (file.endsWith(".mpeg")) { QFileInfo f(file); m_totalEncodedSize+=f.size(); } } m_totalEncodedSize/=1024*1024; m_cancel=m_processList->getCancel(); bool error=false; if (!m_cancel) { QString dvdAuthor(m_workDir+"/"+k9Tools::randomFileName()+".xml"); QFile file( dvdAuthor); file.open(QIODevice::WriteOnly); QTextStream stream( &file ); m_xml->save(stream,1); file.close(); m_processList->clear(); k9Process *process=m_processList->addProcess(i18n("authoring")); connect(process, SIGNAL(receivedStderr(k9Process *,char *, int)),this, SLOT(getStderr(k9Process *,char *, int) )); *process << m_config->getPrefDvdauthorPath(true) << "-x" << dvdAuthor; m_processList->execute(); m_cancel=m_processList->getCancel(); error=m_processList->getError(); // else // m_error=i18n("An error occured while running dvdauthor"); file.remove(); } if (m_cancel) m_error=i18n("The dvd authoring was canceled"); else if (error) m_error=i18n("An error occured while running DVDAuthor:\n")+ m_stdout; QFile::remove(menuFileName); foreach(QString file, m_tmpFiles) { QFile::remove(file); } m_tmpFiles.clear(); if (m_error !="") { k9Dialogs::error(m_error, i18n("Authoring")); } delete m_xml; } void k9NewDVD::addTitles (QDomElement &_root) { calcVideoBitrate(); foreach (k9Title *title,m_titles) { QDomElement titleSet = m_xml->createElement("titleset"); _root.appendChild(titleSet); QDomElement pgc; k9Menu *menu=title->getMenu(); menu->setWorkDir(m_workDir); QString menuFileName=m_workDir+k9Tools::randomFileName()+".mpg"; m_tmpFiles << menuFileName, menu->setMenuFileName(menuFileName); m_processList->addProgress(i18n("Creating menu for title %1").arg(title->getNum()+1)); if (!menu->createMenus(&titleSet)) return; QDomElement eTitle=m_xml->createElement("titles"); titleSet.appendChild(eTitle); QDomElement e=m_xml->createElement("video"); e.setAttribute("aspect","16:9"); e.setAttribute("format",m_format==PAL?"PAL":"NTSC"); // if (l_track->getaspectRatio()!="4:3") { e.setAttribute("widescreen","nopanscan"); // }setProgressWindow eTitle.appendChild(e); e=m_xml->createElement("audio"); e.setAttribute("format","ac3"); e.setAttribute("channels","2"); eTitle.appendChild(e); pgc=m_xml->createElement("pgc"); eTitle.appendChild(pgc); QDomElement post=m_xml->createElement("post"); pgc.appendChild(post); QDomText txt=m_xml->createTextNode(title->getMenu()->getEndScript()); post.appendChild(txt); QList *l=title->getFiles(); foreach (k9AviFile *aviFile,*l) { if ( aviFile->getPrevious()==NULL || aviFile->getBreakPrevious()) { QString cmd="",chapters=""; createMencoderCmd(cmd,chapters,aviFile); //if no reencoding, mpeg files are splitted into cells to avoid // the SCR move backwards error in dvdauthor if (!aviFile->getReencode()) { bool first=true; foreach(QString f,m_splitCells) { m_tmpFiles << f; e=m_xml->createElement("vob"); pgc.appendChild(e); e.setAttribute("file",f); if (first) e.setAttribute("chapters","0"); first=false; } } else { m_tmpFiles << cmd; e=m_xml->createElement("vob"); pgc.appendChild(e); e.setAttribute("file",cmd); e.setAttribute("chapters",chapters); } } } } } void k9NewDVD::setWorkDir ( const QString& _value ) { m_workDir = _value; if (!m_workDir.endsWith("/")) m_workDir +="/"; } void k9NewDVD::createMencoderCmd(QString &_cmd,QString &_chapters, k9AviFile *_aviFile) { // m_aviDecode.open(_aviFile->getFileName()); m_timer.start(); m_timer2.start(); m_timer3.start(); QTime end; k9AviFile *file=_aviFile; bool bEnd; _chapters="0"; do { end=file->getEnd(); bEnd= (file->getNext()==NULL) || (file->getBreakNext()); file=file->getNext(); if (!bEnd) { int lt=_aviFile->getStart().msecsTo(end); QTime t; t=t.addMSecs(lt); _chapters +="," + t.toString("hh:mm:ss"); } } while (!bEnd); //m_progress->setTitle(i18n("Encoding file")); //m_process->clearArguments(); if (_aviFile->getReencode()) { QString fileName= m_workDir + k9Tools::randomFileName()+".mpeg"; QString t1=_aviFile->getStart().toString("hh:mm:ss.zzz"); int length=_aviFile->getStart().msecsTo(end); QTime l; l=l.addMSecs(length); QString t2=l.toString("hh:mm:ss.zzz"); QString scale; QString fps; switch (m_format) { case PAL: scale="720:576"; fps="25"; break; case NTSC: scale="720:480"; fps="30000/1001"; break; } k9Process *process=m_processList->addProcess(i18n("Encoding %1").arg(_aviFile->getFileName())); m_processList->setFileName(process,_aviFile->getFileName()); QTime t(0,0); t.start(); m_timers[process]=t; connect(process, SIGNAL(receivedStdout(k9Process*, char *, int)),this, SLOT(getStdout(k9Process*,char *, int) )); *process << m_config->getPrefMencoderPath(true) << "-oac" << "lavc" << "-ovc" << "lavc" << "-of" << "mpeg" << "-afm" << "libmad"; *process << "-mpegopts" << "format=dvd" << "-vf" << "scale="+scale+",harddup" << "-srate" << "48000" << "-af" << "lavcresample=48000"; *process << "-lavcopts" << QString("vcodec=mpeg2video:vrc_buf_size=1835:vrc_maxrate=9800:vbitrate=%1:keyint=15:acodec=%3:abitrate=%2:aspect=16/9").arg(m_videoBitrate).arg(m_config->getPrefAudioBitrate()).arg(m_config->getPrefAudioFormat().toLower()); *process << "-ofps" << fps << "-o" << fileName << "-ss" << t1 << "-endpos" << t2 << _aviFile->getFileName(); _cmd=fileName; } else { _cmd=_aviFile->getFileName(); //split file into cells from specified start and end time splitFile(_aviFile); } } void k9NewDVD::splitFile(k9AviFile *_aviFile) { uchar buffer[2048]; QFile f(_aviFile->getFileName()); f.open(QIODevice::ReadOnly); QFile *output=NULL; double msecs=0; QTime totalTime(0,0,0); int64_t scr=0; m_splitCells.clear(); uint8_t cellId=0; uint8_t vobId=0; while (!f.atEnd()) { pci_t pciPack; dsi_t dsiPack; f.read((char*)buffer,2048); bool bSplit=(readscr(buffer+4) >4) *10) +(h.hour &0x0f); int minute=((h.minute >>4) *10) +(h.minute &0x0f); int second=((h.second >>4) *10) +(h.second &0x0f); QTime position(hour,minute,second,h.frame_u &0x3f); QTime t(0,0,0); totalTime=totalTime.addMSecs(t.msecsTo(position)-msecs); msecs=t.msecsTo(position); if ( dsiPack.dsi_gi.vobu_c_idn !=cellId || dsiPack.dsi_gi.vobu_vob_idn !=vobId) bSplit=true; cellId=dsiPack.dsi_gi.vobu_c_idn ; vobId=dsiPack.dsi_gi.vobu_vob_idn; } if (bSplit|| (output==NULL)) { if (output !=NULL) { output->close(); delete output; } QString fileName= m_workDir + k9Tools::randomFileName()+".mpeg"; m_splitCells << fileName; output=new QFile(fileName); output->open(QIODevice::WriteOnly); } //scr=dsiPack.dsi_gi.nv_pck_scr; if (buffer[0]==0 && buffer[1]==0 && buffer[2]==1 && buffer[3]==0xba ) { scr=readscr(buffer+4); } output->write((char*)buffer,2048); } f.close(); if (output !=NULL) { output->close(); delete output; } } int64_t k9NewDVD::readscr(const unsigned char *buf) { return (((int64_t)(buf[0]&0x38))<<27)| ((buf[0]&3)<<28)| (buf[1]<<20)| ((buf[2]&0xf8)<<12)| ((buf[2]&3)<<13)| (buf[3]<<5)| ((buf[4]&0xf8)>>3); } void k9NewDVD::getStderr(k9Process *_process,char *_buffer, int _length) { #if QT_VERSION >= 0x050000 QString tmp=QString::fromLatin1(_buffer,_length); #else QString tmp=QString::fromAscii(_buffer,_length); #endif m_stdout=tmp; int pos; if (tmp.contains("STAT:")) { pos=tmp.indexOf("fixing VOBU"); if (pos!=-1) { QString tmp2=tmp; // m_progress->setTitle(i18n("Authoring")); // m_progress->setLabelText(i18n("Fixing VOBUS")); int end=tmp2.indexOf("%"); if (end!=-1) { pos =end -2; tmp2=tmp2.mid(pos,end-pos); tmp2=tmp2.trimmed(); // m_progress->setProgress(tmp2.toInt(),100); } } else { pos=tmp.indexOf("STAT: VOBU "); if (pos !=-1) { #if QT_VERSION >= 0x050000 QString tmp2=QString::fromLatin1(_buffer+pos,_length-pos); #else QString tmp2=QString::fromAscii(_buffer+pos,_length-pos); #endif int vobu,mb; sscanf(_buffer+pos,"STAT: VOBU %d at %dMB",&vobu,&mb); if (mb setProgress((k9Process*)_process,mb+m_offset,m_totalEncodedSize); } } //STAT: VOBU 16 at 3MB, 1 PGCS } if (tmp.contains("ERR:")) { pos=tmp.indexOf("ERR:"); if (pos !=-1) m_error=tmp.mid(pos); } } void k9NewDVD::getStdout(k9Process *_process,char *_buffer, int _length) { k9Process *process=(k9Process*) _process; if (m_timers[process].elapsed() >500) { #if QT_VERSION >= 0x050000 QString tmp=QString::fromLatin1(_buffer,_length); #else QString tmp=QString::fromAscii(_buffer,_length); #endif int pos=tmp.indexOf("Pos:"); if (pos!=-1) { QString tmp2=tmp.mid(pos); tmp2=tmp2.replace(":",": ").replace("(","").replace(")","").simplified(); QStringList sl=tmp2.split(" "); float position; // qDebug() << "position : " << sl[1] << " frame : " << sl[2] << " percent : " << sl[3] << " fps :" << sl[4]; sscanf(sl[1].toUtf8().data(),"%fs",&position); int frame; sscanf(sl[2].toUtf8().data(),"%df",&frame); int percent; sscanf(sl[3].toUtf8().data(),"%d",&percent); int fps; sscanf(sl[4].toUtf8().data(),"%d",&fps); m_processList->setProgress(process,percent,100); m_processList->setPos(process,position); //m_progress->setProgress(percent,100); // if (percent>0 &&m_timer3.elapsed() >1000 ) { if (percent>0 ) { int elapsed=process->getElapsed(); QTime time2(0,0); time2=time2.addMSecs(elapsed); QTime time3(0,0); float fprc=percent/100.0; time3=time3.addMSecs((uint32_t)(elapsed*(1.0/fprc))); m_processList->setText(process,time2.toString("hh:mm:ss") +" / " + time3.toString("hh:mm:ss"),1); m_timer3.restart(); } QString text;//=i18n("filename") + " : " + m_aviDecode.getFileName(); text=i18n("fps")+ " : "+QString::number(fps); m_processList->setText(process,text,2); /* m_progress->setLabelText(text); if (m_timer.elapsed() > 5000) { m_timer.restart(); if (m_aviDecode.opened()) { m_aviDecode.readFrame(position); } } */ } m_timers[process].restart(); } } void k9NewDVD::appendTitle(k9Title *_title) { m_config=new k9Config(); m_titles.append(_title); qSort(m_titles.begin(),m_titles.end(),k9NewDVDItems::compareItems);; //create the menu button k9MenuButton *btn=m_rootMenu->addButton(); _title->setButton(btn); btn->setNum(_title->getNum()+1); QPixmap px(m_config->getPrefButtonWidth(),m_config->getPrefButtonHeight()); px.fill(Qt::black); QImage img=px.toImage(); btn->setImage(img); int nbColumn=(720-50)/(m_config->getPrefButtonWidth()+50); int top=(int) _title->getNum()/nbColumn ; int left=_title->getNum() %nbColumn; btn->setTop(top*(m_config->getPrefButtonHeight()+20) +50); btn->setLeft(left*(m_config->getPrefButtonWidth()+50) +50); btn->setWidth(m_config->getPrefButtonWidth()); btn->setHeight(m_config->getPrefButtonHeight()); btn->setScript(QString("g1=0;jump titleset %1 menu;").arg(_title->getNum()+1)); btn->setTextPosition(RIGHT); btn->setText(i18n("title %1").arg(_title->getNum()+1)); btn->setColor(m_config->getPrefButtonTextColor()); btn->setFont(m_config->getPrefButtonFont()); QString script="\n"; foreach (k9Title *t,m_titles) { script +=QString("if (g6== %1) { g6=0; jump titleset %2 menu;}\n").arg(t->getNum()+1).arg(t->getNum()+1); } m_rootMenu->setStartScript2(script); emit sigAddTitle(); delete m_config; } void k9NewDVD::setProcessList(k9ProcessList *_value) { m_processList=_value; } k9NewDVD::eFormat k9NewDVD::getFormat() const { return m_format; } k9Menu* k9NewDVD::getRootMenu() const { return m_rootMenu; } void k9NewDVD::calcVideoBitrate() { // bitrate video = (MB *8388.608) /SEC - bitrate audio int length=0; foreach (k9Title *title,m_titles) { k9TitleItems *chapters=title->getFiles(); foreach (k9AviFile *chapter,*chapters) { length+=chapter->getStart().msecsTo(chapter->getEnd()); } } int size=m_config->getPrefSize(); double sec=(double)length/1000.0; // m_videoBitrate=(int)( (size * 8388.608)/sec - 192); m_videoBitrate=8*((size*1024 - (m_config->getPrefAudioBitrate() * sec/8))/sec); m_videoBitrate=qMin(m_videoBitrate,9800); } int k9NewDVD::getTotalTime() { int total=0; foreach (k9Title * title,m_titles) { k9TitleItems *chapters=title->getFiles(); foreach (k9AviFile *chapter,*chapters) { total+=chapter->getStart().secsTo(chapter->getEnd()); } } return total; } QString k9NewDVD::getError() const { return m_error; } k9copy/src/import/processList.ui0000644000175000017550000000523112417731553017526 0ustar emulatoremulator processList 0 0 600 480 Process List false true Progression Processes Elapsed ... 0 0 &Cancel Alt+C 2 Qt::Horizontal QSizePolicy::Expanding 361 20 KPushButton QWidget
kpushbutton.h
kpushbutton.h bCancel clicked() processList bCancelClick() 20 20 20 20
k9copy/src/import/k9menuscene.h0000644000175000017550000000057012412271774017254 0ustar emulatoremulator#ifndef K9MENUSCENE_H #define K9MENUSCENE_H #include #include class k9MenuScene : public QGraphicsScene { Q_OBJECT public: k9MenuScene(QObject *parent); void setBackgroundPixmap(const QPixmap &); protected: void drawBackground ( QPainter * painter, const QRectF & rect ); private: QPixmap m_pixmap; }; #endif // K9MENUSCENE_H k9copy/src/import/k9chapteredit.cpp0000644000175000017550000001513412412271774020123 0ustar emulatoremulator// // C++ Implementation: // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "k9chapteredit.h" #include "k9drawimage.h" #include #include #include #include #include #include #include "k9title.h" #if QT_VERSION >= 0X050000 #include #else #include #endif #include #include #if QT_VERSION >= 0x050000 //Qt 5 Code #include #else //Qt4 Code #endif k9ChapterEdit::k9ChapterEdit(QWidget* parent) : QWidget(parent) { Ui_chapterEdit.setupUi(this); m_aviDecode=NULL; m_wimage=new k9DrawImage(Ui_chapterEdit.image); QGridLayout *l=new QGridLayout(Ui_chapterEdit.image); l->addWidget(m_wimage,0,0); QPalette p; p.setColor(QPalette::Window,Qt::black); m_wimage->setPalette(p); //Ui_chapterEdit.bTitleButton->setIcon(SmallIcon("frame_image")); } k9ChapterEdit::~k9ChapterEdit() { if (m_aviDecode) delete m_aviDecode; } /*$SPECIALIZATION$*/ void k9ChapterEdit::sliderReleased() { // m_aviDecode->seek((double)slider->value() / 100); // m_aviDecode->readFrame(); } void k9ChapterEdit::sliderChanged(int _value) { if (m_aviDecode->opened()) { //m_aviDecode->seek((double)slider->value() / 100); m_aviDecode->readFrame((double)_value / 1000); QTime t; t=t.addMSecs((double)_value); Ui_chapterEdit.lPosition->setText(t.toString("hh:mm:ss")); } } #if QT_VERSION >= 0x050000 void k9ChapterEdit::urlSelected(const QUrl& _url) { #else void k9ChapterEdit::urlSelected(const KUrl& _url) { #endif bool fileChanged=_url.toLocalFile() !=m_aviFile->getFileName(); if (!m_aviDecode) { m_aviDecode =new k9AviDecode(0,0); connect(m_aviDecode,SIGNAL(drawFrame(QImage)),this,SLOT(drawImage(QImage))); } m_aviDecode->open(_url.toLocalFile()); if (!m_noUpdate) { m_aviFile->setFileName(_url.toLocalFile()); if (fileChanged) { m_aviDecode->readFrame(0); m_aviFile->setStart(QTime(0,0,0)); m_aviFile->setImage(m_image); QTime end(0,0,0); end=end.addSecs((int)(m_aviDecode->getDuration())); m_aviFile->setEnd(end); m_aviFile->setNext(NULL); m_aviFile->setPrevious(NULL); Ui_chapterEdit.ckBreakEnd->setChecked(false); Ui_chapterEdit.ckBreakStart->setChecked(false); ckBreakEndClick(); ckBreakStartClick(); setAviFile(m_aviFile); } } QTime t; int sec=t.msecsTo(m_aviFile->getStart()); Ui_chapterEdit.slider->setMaximum((int)(m_aviDecode->getDuration()*1000)); Ui_chapterEdit.slider->setValue(sec); } void k9ChapterEdit::drawImage(QImage _image) { //QPixmap p(*_image); //image->setPixmap(p); m_wimage->setImage(_image); m_image=_image; } void k9ChapterEdit::bStartClick() { QTime t; int secs=Ui_chapterEdit.slider->value()/1000; t=t.addSecs(secs); Ui_chapterEdit.twstart->setTime(t); } void k9ChapterEdit::bEndClick() { QTime t; int secs=Ui_chapterEdit.slider->value()/1000; t=t.addSecs(secs); Ui_chapterEdit.twend->setTime(t); } void k9ChapterEdit::setAviFile(k9AviFile *_aviFile) { this->setEnabled(_aviFile!=NULL); m_aviFile=_aviFile; if (_aviFile) { setEnabled(true); m_noUpdate=true; Ui_chapterEdit.ckBreakStart->setEnabled(_aviFile->getReencode()); Ui_chapterEdit.ckBreakEnd->setEnabled(_aviFile->getReencode()); Ui_chapterEdit.twstart->setEnabled(_aviFile->getReencode()); Ui_chapterEdit.twend->setEnabled(_aviFile->getReencode()); urlSelected(m_aviFile->getFileName()); k9AviFile *p=m_aviFile->getPrevious(); k9AviFile *n=m_aviFile->getNext(); QTime end(0,0,0); m_minTime=end;; end=end.addSecs((int)(m_aviDecode->getDuration())); m_maxTime=end; if (p) { if(p->getFileName() !=_aviFile->getFileName()) { Ui_chapterEdit.ckBreakStart->setEnabled(false); m_minTime.setHMS(0,0,0,0); } else { Ui_chapterEdit.ckBreakStart->setEnabled(true); m_minTime=p->getStart(); } } if (n) { if(n->getFileName() !=_aviFile->getFileName()) { Ui_chapterEdit.ckBreakEnd->setEnabled(false); m_maxTime=_aviFile->getEnd(); } else { Ui_chapterEdit.ckBreakEnd->setEnabled(true); m_maxTime=n->getEnd(); } } Ui_chapterEdit.twstart->setTime(m_aviFile->getStart()); Ui_chapterEdit.twend->setTime(m_aviFile->getEnd()); Ui_chapterEdit.urFile->setUrl(m_aviFile->getFileName()); Ui_chapterEdit.ckBreakStart->setChecked(m_aviFile->getBreakPrevious()); Ui_chapterEdit.ckBreakEnd->setChecked(m_aviFile->getBreakNext()); } else setEnabled(false); m_noUpdate=false; } void k9ChapterEdit::startChanged(const QTime& _time) { if (!m_noUpdate) { QTime t=_time; if (t > m_maxTime ) t=m_maxTime; else if (t < m_minTime) t=m_minTime; else if (t >m_aviFile->getEnd()) t=m_aviFile->getEnd(); if (t!=_time) Ui_chapterEdit.twstart->setTime(t); m_aviFile->setStart(t); if (!m_aviFile->getBreakPrevious() && m_aviFile->getPrevious()!=NULL) { m_aviFile->getPrevious()->setEnd(t); } QTime t2; Ui_chapterEdit.slider->setValue(t2.msecsTo(t)); m_aviFile->setImage(m_image); } } void k9ChapterEdit::endChanged(const QTime& _time) { if (!m_noUpdate) { QTime t=_time; if (t > m_maxTime ) t=m_maxTime; else if (t < m_minTime) t=m_minTime; else if (t getStart()) t=m_aviFile->getStart(); if (t!=_time) Ui_chapterEdit.twend->setTime(t); m_aviFile->setEnd(t); QTime t2; if (!m_aviFile->getBreakNext() && m_aviFile->getNext()!=NULL) { QImage i=m_image; m_aviDecode->readFrame((double)t2.msecsTo(t)/1000.0); m_aviFile->getNext()->setImage(m_image); m_image=i; m_aviFile->getNext()->setStart(t); } Ui_chapterEdit.slider->setValue(t2.msecsTo(t)); } } void k9ChapterEdit::ckBreakStartClick() { m_aviFile->setBreakPrevious(Ui_chapterEdit.ckBreakStart->isChecked()); } void k9ChapterEdit::bTitleButtonClick() { m_aviFile->getTitle()->getButton()->setImage(m_image); } void k9ChapterEdit::ckBreakEndClick() { m_aviFile->setBreakNext(Ui_chapterEdit.ckBreakEnd->isChecked()); } k9copy/src/import/menuEdit.ui0000644000175000017550000002766412417731553017004 0ustar emulatoremulator menuEdit 0 0 576 430 Edit Menu 0 0 75 true Root Menu false QFrame::StyledPanel 0 0 QFrame::StyledPanel QFrame::Raised Qt::Horizontal QSizePolicy::Minimum At start false Play menu Play title 1 At End false Play root menu Play title menu Play title 1 0 0 Background picture false 0 0 Text false 0 0 24 24 24 24 0 0 0 0 Font 0 0 Bottom Right Qt::Horizontal QSizePolicy::Expanding 40 20 Qt::Horizontal QSizePolicy::Minimum KUrlRequester QFrame
kurlrequester.h
KPushButton KPushButton
kpushbutton.h
KColorButton KPushButton
kcolorbutton.h
cbStart cbEnd urBackground leTitle cbColor bFont cbPosTitle kurlrequester.h kpushbutton.h kcolorbutton.h kpushbutton.h kpushbutton.h bFont clicked() menuEdit bFontClick() 20 20 20 20 urBackground urlSelected(const KUrl &) menuEdit urBackgroundSelected(const KUrl &) 20 20 20 20 cbColor changed(QColor) menuEdit cbColorChanged(QColor) 20 20 20 20 leTitle textChanged(QString) menuEdit leTitleChanged(QString) 20 20 20 20 cbPosTitle activated(int) menuEdit cbPosTitleActivated(int) 20 20 20 20 bAddText clicked() menuEdit bAddTextClick() 20 20 20 20 cbStart activated(int) menuEdit cbStartActivated(int) 20 20 20 20 cbEnd activated(int) menuEdit cbEndActivated(int) 20 20 20 20
k9copy/src/import/newTitle.ui0000644000175000017550000001651412417731553017015 0ustar emulatoremulator newTitle 0 0 598 291 Add title 0 0 Video file false 0 0 --:--:-- false Qt::Horizontal QSizePolicy::Expanding 31 20 Qt::Horizontal QSizePolicy::Expanding 341 28 false 0 0 Add Qt::Vertical 20 40 0 0 number of chapters true chapter length false 0 0 HH:mm:ss Qt::Horizontal QSizePolicy::Expanding 131 21 Do not reencode 0 0 1 99 KUrlRequester QFrame
kurlrequester.h
KPushButton KPushButton
kpushbutton.h
kpushbutton.h kurlrequester.h urFile urlSelected(const KUrl&) newTitle urlSelected(const KUrl&) 20 20 20 20 bAdd clicked() newTitle bAddClicked() 20 20 20 20 rbNumber clicked() newTitle rbNumberClicked() 84 52 298 145 rbLength clicked() newTitle rbLengthClicked() 84 77 298 145 rbNumberClicked() rbLengthClicked()
k9copy/src/import/k9menubutton.h0000644000175000017550000000713312412271774017474 0ustar emulatoremulator// // C++ Interface: k9menubutton // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9MENUBUTTON_H #define K9MENUBUTTON_H #include #include #include #include #include "k9menuscene.h" #include /** @author Jean-Michel PETIT */ enum eTextPosition {BOTTOM=1,RIGHT=2}; class k9MenuButton; class k9CanvasSprite : public QGraphicsItemGroup { public: k9CanvasSprite (const QPixmap &pixmap,k9MenuScene *scene,k9MenuButton *button); int type() const {return (UserType+1);} static int itemType() { return (UserType +1);} k9MenuButton* getButton() const; QGraphicsPixmapItem *getPixmapItem() {return m_pixmap;} QGraphicsSimpleTextItem *getTextItem() {return m_text;} QRectF boundingRect() const; void paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0 ); void setPixmap (const QPixmap &pixmap); void setTextPosition(const eTextPosition& _value); eTextPosition getTextPosition() { return m_textPosition;} QFont getFont(); void setFont(const QFont &font); void setTextColor(const QColor &color); QColor getTextColor(); void setText (const QString &text); QString getText(); void scalePixmap(int width,int height); private: enum eSize { SNONE, STL,STC,STR,SML,SMR,SBL,SBC,SBR}; k9MenuButton *m_button; QGraphicsPixmapItem *m_pixmap; QGraphicsSimpleTextItem *m_text; QPointF m_startPoint; void drawSizeRect (QPainter *painter); eSize m_resize; QPixmap m_bPixmap; eTextPosition m_textPosition; QString m_txtValue; QColor m_txtColor; int m_selsize; protected: void mousePressEvent ( QGraphicsSceneMouseEvent * event ) ; void mouseMoveEvent ( QGraphicsSceneMouseEvent * event ); }; class k9MenuButton : public QObject { Q_OBJECT public: k9MenuButton(k9MenuScene *parent = 0, const char *name = 0); ~k9MenuButton(); void setWidth(int _value,bool _reload=true); int getWidth(); void setHeight(int _value,bool _reload=true); int getHeight(); void setTop(int _value,bool _reload=true); void setLeft(int _value,bool _reload=true); void setFont(QFont _font); QFont getFont(); void setColor(QColor _color); QColor getColor(); void setText(QString _text); QString getText(); void select(bool); int getTop(); int getLeft(); void moveBy(int x,int y,bool _reload=true); void update(); void remove(); public slots: void setImage(const QImage &_image); void setImage(const QString &_fileName); void setTextPosition(const eTextPosition& _value); eTextPosition getTextPosition() const; QImage getImage() const; void setScript(const QString& _value); QString getScript() const; void setAngle(int _value); int getAngle() const; k9CanvasSprite* getSprite() const; void setNum(int _value); int getNum() const; private: k9MenuScene *m_scene; k9CanvasSprite *m_sprite; int m_num; QImage m_image; int m_width; int m_height; int m_angle; eTextPosition m_textPosition; QString m_script; QPixmap m_pixmap; void loadImage(); signals: void sigsetTop(int); void sigsetLeft(int); void sigsetWidth(int); void sigsetHeight(int); void sigsetFont(const QFont &); void sigsetColor(const QColor &); void sigsetImage(k9MenuButton *,const QImage &); void sigsetText(const QString &); void sigsetTextPosition(int); }; #endif k9copy/src/import/k9menuedit.cpp0000644000175000017550000002714012412271774017441 0ustar emulatoremulator// // C++ Implementation: // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "k9common.h" #include "k9menuedit.h" #include "k9menu.h" #include "k9title.h" #include "k9newdvd.h" #include #include "k9menubutton.h" #include #include #include #include #include #if QT_VERSION >= 0x050000 #include #include #include #else // Qt4 Code #include #endif #include #include #include void k9GraphicsView::drawBackground ( QPainter * painter, const QRectF & rect ) { QGraphicsView::drawBackground(painter,rect); } void k9GraphicsView::resizeEvent ( QResizeEvent * event ) { QPointF p=mapFromScene(sceneRect().width(),sceneRect().height()); qreal fx=(qreal)event->size().width()/p.x() ; qreal fy=(qreal)event->size().height()/p.y(); scale(qMin(fx,fy),qMin(fx,fy)); } k9MenuEdit::k9MenuEdit(QWidget* parent, const char* ,k9MenuScene *scene) : QWidget(parent) { Ui_menuEdit.setupUi(this); QGridLayout *gridLayout = new QGridLayout(Ui_menuEdit.widget); gridLayout->setSpacing(6); gridLayout->setMargin(0); m_graphicsView = new k9GraphicsView(Ui_menuEdit.widget); gridLayout->addWidget(m_graphicsView, 0, 0, 1, 1); #if QT_VERSION >= 0x050000 KGuiItem::assign(Ui_menuEdit.bAddText, KStandardGuiItem::add() ); #else Ui_menuEdit.bAddText->setGuiItem(KStandardGuiItem::Add); #endif Ui_menuEdit.bAddText->setText(""); m_noUpdate=false; m_scene=scene; m_format=PAL; m_imageHeight=576; m_scene=new k9MenuScene(this); m_scene->setSceneRect( 0,0,720,m_imageHeight); m_graphicsView->setScene(m_scene); m_graphicsView->setMaximumWidth(722); m_text=NULL; Ui_menuEdit.cbPosTitle->setEnabled(false); Ui_menuEdit.urBackground->setFilter("*.jpg|jpeg (*.jpg)\n*.png|png (*.png)\n*.*|All (*.*)"); Ui_menuEdit.urBackground->setMode(KFile::File) ; #if QT_VERSION >= 0x050000 //Qt5 Code Ui_menuEdit.urBackground->fileDialog()->setAcceptMode(QFileDialog::AcceptOpen); #else //Qt4 Code Ui_menuEdit.urBackground->fileDialog()->setOperationMode(KFileDialog::Opening); #endif } /*void k9MenuEdit::updateTextPos(const QPoint &_point) { emit updatePos(_point); } */ k9MenuEdit::~k9MenuEdit() { } /*$SPECIALIZATION$*/ k9CanvasSprite *convertToButton(QGraphicsItem *item) { if (item->type()==k9CanvasSprite::itemType()) return (k9CanvasSprite*) item; else return NULL; } void k9MenuEdit::selectionChanged() { if (m_scene->selectedItems().count()>0) { foreach(QGraphicsItem *item,m_scene->selectedItems()) { m_text=qgraphicsitem_cast(item); if (m_text) Ui_menuEdit.cbColor->setColor(m_text->brush().color()); k9CanvasSprite *button=convertToButton(item); if (button!=0) { m_text=button->getTextItem(); Ui_menuEdit.cbPosTitle->setEnabled(true); Ui_menuEdit.cbPosTitle->setCurrentIndex(button->getTextPosition()-1); Ui_menuEdit.cbColor->setColor(button->getTextColor()); } } }else Ui_menuEdit.cbPosTitle->setEnabled(false); } void k9MenuEdit::bFontClick() { if (m_scene->selectedItems().count()>0) { bool dlg=false; QFont myFont; foreach( QGraphicsItem *item, m_scene->selectedItems()) { k9CanvasSprite *spr=convertToButton(item); if (spr) { if (!dlg) { myFont=spr->getButton()->getFont(); if (!k9Dialogs::getFont( myFont )) return; dlg=true; } spr->getButton()->setFont(myFont); } m_text=qgraphicsitem_cast(item); if (m_text) { if (!dlg) { myFont=m_text->font(); if(!k9Dialogs::getFont( myFont )) return; dlg=true; } m_text->setFont(myFont); } } } } #if QT_VERSION >= 0x050000 void k9MenuEdit::urBackgroundSelected(const QUrl &_url) { #else void k9MenuEdit::urBackgroundSelected(const KUrl &_url) { #endif QImage img; img.load(_url.toLocalFile()); if ( m_scene->selectedItems().count()>0 ) { //If a button is selected, set the button image ... foreach( QGraphicsItem *item, m_scene->selectedItems()) { k9CanvasSprite *spr=convertToButton(item); if (spr) { spr->getButton()->setImage(img); } } } else { //...otherwise, set the menu background image img=img.scaled(720,m_imageHeight,Qt::KeepAspectRatioByExpanding); setBackgroundImage(img); } } void k9MenuEdit::cbColorChanged(const QColor &_color) { if (m_noUpdate) return; foreach( QGraphicsItem *item, m_scene->selectedItems()) { k9CanvasSprite *spr=convertToButton(item); if (spr) { spr->getButton()->setColor(_color); } m_text=qgraphicsitem_cast(item); if (m_text) { m_text->setBrush(QBrush(_color)); } } } void k9MenuEdit::cbPosTitleActivated(int _value) { if (m_noUpdate) return; foreach( QGraphicsItem *item, m_scene->selectedItems()) { k9CanvasSprite *spr=convertToButton(item); if (spr) { spr->getButton()->setTextPosition((eTextPosition)(_value+1)); } } } void k9MenuEdit::setBackgroundImage(const QImage &_image) { m_background=_image; m_scene->setBackgroundPixmap(QPixmap::fromImage(_image)); emit backgroundImageChanged(_image); } void k9MenuEdit::leTitleChanged(const QString &_value) { if (m_noUpdate) return; foreach( QGraphicsItem *item, m_scene->selectedItems()) { k9CanvasSprite *spr=convertToButton(item); if (spr) { QString c=_value; spr->getButton()->setText(c.replace("%n",QString::number(spr->getButton()->getNum()))); } m_text=qgraphicsitem_cast(item); if (m_text) { m_text->setText(_value); } } //m_menuEditor->getSelected()->setText(_value); } /* void k9MenuEdit::setText(const QString &_value) { if (m_text) m_text->setText(_value); emit textChanged(_value); } void k9MenuEdit::setFont(const QFont &_value) { if (m_text) m_text->setFont(_value); emit textFontChanged(_value); } void k9MenuEdit::setColor(const QColor &_value) { if (m_text) m_text->setPen(QPen(_value)); emit textColorChanged(_value); } QGraphicsSimpleTextItem* k9MenuEdit::getText() const { return m_text; } */ k9MenuEdit::eFormat k9MenuEdit::getFormat() const { return m_format; } void k9MenuEdit::setFormat(const eFormat& _value) { m_format = _value; if (_value==NTSC) m_imageHeight=480; else m_imageHeight=576; m_scene->setSceneRect(0,0,720,m_imageHeight); /* QPixmap pix=m_canvas->backgroundPixmap(); QImage img=pix.toImage().scaled(720,m_imageHeight); m_canvas->resize(720,m_imageHeight); m_menuEditor->setMaximumSize(QSize(724,m_imageHeight+4)); m_canvas->setBackgroundPixmap(QPixmap::fromImage(img)); */ } k9MenuScene *k9MenuEdit::getScene() { return m_scene; } void k9MenuEdit::setScene(k9MenuScene* _value) { if (m_scene) disconnect(this,SLOT(selectionChanged())); m_scene = _value; connect(m_scene,SIGNAL(selectionChanged()),this,SLOT(selectionChanged())); m_text=NULL; m_graphicsView->setScene(m_scene); m_scene->setSceneRect(0,0,720,m_imageHeight); selectionChanged(); } void k9MenuEdit::titleSelected(k9Title *_title) { disconnect (this,SIGNAL(startScriptChanged(const QString&)),0,0); disconnect (this,SIGNAL(endScriptChanged(const QString&)),0,0); Ui_menuEdit.cbEnd->setEnabled(true); m_scene->clearSelection();; Ui_menuEdit.lTitle->setText(i18n("Title %1 Menu").arg(_title->getNum()+1)); setScene(_title->getMenu()->getScene()); m_menuType=TITLEMENU; Ui_menuEdit.cbStart->clear(); Ui_menuEdit.cbEnd->clear(); m_startScripts.clear(); m_endScripts.clear(); Ui_menuEdit.cbStart->addItem(i18n("Play Menu")); m_startScripts << ""; Ui_menuEdit.cbStart->addItem(i18n("Play Title")); m_startScripts << "if (g1==0) {g1=1; jump title 1 chapter 1;}"; if (_title->getMenu()->getStartScript() !="") Ui_menuEdit.cbStart->setCurrentIndex(Ui_menuEdit.cbStart->count()-1); connect (this,SIGNAL(startScriptChanged(const QString&)),_title->getMenu(),SLOT(setStartScript(const QString&))); Ui_menuEdit.cbEnd->addItem(i18n("Play Root Menu")); m_endScripts << "g6=0; call vmgm menu;"; Ui_menuEdit.cbEnd->addItem(i18n("Play Title Menu")); m_endScripts << "call menu;"; k9NewDVD *newDVD=(k9NewDVD*)_title->parent() ; k9NewDVDItems *items=newDVD->getTitles(); foreach (k9Title *title,*items) { Ui_menuEdit.cbEnd->addItem(i18n("Play Title %1").arg(title->getNum()+1)); QString script=QString("g6=%1; call vmgm menu;" ).arg(title->getNum()+1); m_endScripts << script; } for (int i=0;igetMenu()->getEndScript()== m_endScripts.at(i)) Ui_menuEdit.cbEnd->setCurrentIndex(i); } connect (this,SIGNAL(endScriptChanged(const QString&)),_title->getMenu(),SLOT(setEndScript(const QString&))); } void k9MenuEdit::rootSelected(k9NewDVD *_newDVD) { disconnect (this,SIGNAL(startScriptChanged(const QString&)),0,0); disconnect (this,SIGNAL(endScriptChanged(const QString&)),0,0); Ui_menuEdit.cbEnd->setEnabled(false); m_scene->clearSelection();; Ui_menuEdit.lTitle->setText(i18n("Root Menu")); setScene(_newDVD->getRootMenu()->getScene()); m_menuType=ROOTMENU; Ui_menuEdit.cbStart->clear(); m_startScripts.clear(); Ui_menuEdit.cbStart->addItem(i18n("Play Menu")); m_startScripts << ""; k9NewDVDItems *items=_newDVD->getTitles(); foreach (k9Title *title,*items) { Ui_menuEdit.cbStart->addItem(i18n("Play Title %1").arg(title->getNum()+1)); // QString script=QString("if (g5==0) {g5=1; jump title %1;}" ).arg(title->getNum()+1); QString script=QString("g6=%1;" ).arg(title->getNum()+1); m_startScripts << script; if (script==_newDVD->getRootMenu()->getStartScript()) Ui_menuEdit.cbStart->setCurrentIndex(Ui_menuEdit.cbStart->count()-1); } connect (this,SIGNAL(startScriptChanged(const QString&)),_newDVD->getRootMenu(),SLOT(setStartScript(const QString&))); } void k9MenuEdit::bAddTextClick() { k9Config config; m_text=new QGraphicsSimpleTextItem(); m_text->setBrush(QColor(config.getPrefButtonTextColor())); m_text->setFont(config.getPrefButtonFont()); m_text->setText(Ui_menuEdit.leTitle->text()); m_text->setFlag(QGraphicsItem::ItemIsMovable); m_text->setFlag(QGraphicsItem::ItemIsSelectable); m_scene->addItem(m_text); m_text->setSelected(true); } void k9MenuEdit::cbStartActivated (int _value) { emit startScriptChanged(m_startScripts[_value]); } void k9MenuEdit::cbEndActivated (int _value) { emit endScriptChanged(m_endScripts[_value]); } k9copy/src/import/import.ui0000644000175000017550000000634712417731553016537 0ustar emulatoremulator import 0 0 524 416 import 0 0 Output false 0 0 0 200 Qt::CustomContextMenu false Video files ... 0 0 PAL NTSC 0 0 --:--:-- false cbFormat activated(QString) import cbFormatActivated(QString) 20 20 20 20 k9copy/src/import/k9import.cpp0000644000175000017550000002523412412271774017143 0ustar emulatoremulator// // C++ Implementation: // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "k9import.h" #include "k9title.h" #include "k9avifile.h" #include "k9lvitemimport.h" #include "k9menuedit.h" #include "k9burndvd.h" #include #include #include #include "k9processlist.h" #include "k9importfiles.h" #include "k9dialogs.h" #include #include #include #if QT_VERSION >= 050000 #include #else #include #endif #include "k9menu.h" k9Import::k9Import(QWidget* parent, const char* ,k9CdDrives *_drives) : QWidget(parent) { Ui_import.setupUi(this); Ui_import.lvDVD->setIconSize(QSize(48,48)); #if QT_VERSION >= 0x050000 setWindowTitle((i18n("import"))); #else setWindowTitle(KDialog::makeStandardCaption(i18n("import"),this)); #endif m_parent=(k9ImportFiles*) parent; drives=_drives; m_newDVD=new k9NewDVD(); connect(m_newDVD,SIGNAL(sigAddTitle()),this,SLOT(titleAdded())); lvDVD=Ui_import.lvDVD; connect(lvDVD,SIGNAL(currentItemChanged ( QTreeWidgetItem * , QTreeWidgetItem *)),this,SLOT(lvDVDCurrentChanged( QTreeWidgetItem *,QTreeWidgetItem *) )); connect (lvDVD,SIGNAL(customContextMenuRequested( const QPoint& )),this,SLOT(showPopup(const QPoint&))); } k9Import::~k9Import() { disconnect(this); if (m_newDVD) delete m_newDVD; } void k9Import::clear() { for (int i=m_root->childCount()-1;i>=0;i--){ m_selected=(k9LvItemImport*)m_root->child(i); removeTitle(); } lvDVD->clear(); delete m_newDVD; m_newDVD=NULL; } /*$SPECIALIZATION$*/ void k9Import::init() { m_root=new QTreeWidgetItem(lvDVD); m_root->setText(0,i18n("Root Menu")); m_root->setExpanded(true); m_root->setIcon(0,SmallIcon("media-optical-recordable")); emit aviFileSelected(NULL); connect(drives,SIGNAL(deviceAdded( k9CdDrive*)),this,SLOT(deviceAdded( k9CdDrive* ))); connect(drives,SIGNAL(deviceRemoved( k9CdDrive*)),this,SLOT(deviceRemoved( k9CdDrive* ))); readDrives(); m_root->setSelected(true); emit rootSelected(m_newDVD); emit aviFileSelected(NULL); } void k9Import::readDrives() { Ui_import.cbOutputDev->clear(); recorderList.clear(); Ui_import.cbOutputDev->addItem(SmallIcon("document-open"), i18n("ISO Image")); Ui_import.cbOutputDev->addItem(SmallIcon("folder"),i18n("Folder")); drives->scanDrives(); } void k9Import::deviceAdded(k9CdDrive *_drive) { addDrive(_drive); } void k9Import::deviceRemoved(k9CdDrive *_drive) { int i=recorderList.indexOf(_drive); recorderList.removeAll( _drive); Ui_import.cbOutputDev->removeItem(i+2); } void k9Import::addDrive(k9CdDrive *drive) { #ifdef HAVE_HAL if (drive->getDevice()!=NULL) { k9HalDevice *dev=drive->getDevice(); connect(dev,SIGNAL(volumeChanged( const QString &,const QString &)),this,SLOT(volumeChanged(const QString&,const QString&))); } #endif if (drive->canWriteDVD) { Ui_import.cbOutputDev->addItem(SmallIcon("media-optical-recordable"), drive->name+ " ("+drive->device+")",-1); recorderList.append(drive); } } void k9Import::volumeChanged(const QString &device,const QString &volumeName) { Q_UNUSED(device); Q_UNUSED(volumeName);} QTreeWidgetItem * k9Import::getRoot() const { return m_root; } void k9Import::aviFileUpdated(k9AviFile *_aviFile) { for (int i=0;i< m_root->childCount();i++) { k9LvItemImport *itemTitle = (k9LvItemImport*)m_root->child(i); for (int j=0;jchildCount();j++) { k9LvItemImport *itemChapter = (k9LvItemImport*)itemTitle->child(j); if (itemChapter->getAviFile()==_aviFile) { itemChapter->setText(1,_aviFile->getStart().toString("hh:mm:ss") +" - "+_aviFile->getEnd().toString("hh:mm:ss")); itemChapter->setIcon(0,QIcon(QPixmap::fromImage(_aviFile->getImage().scaled(50,40)))); } } } updateTotalTime(); } void k9Import::buttonUpdated(k9MenuButton *_button, const QImage &_image) { for (int i=0;i< m_root->childCount();i++) { k9LvItemImport *itemTitle = (k9LvItemImport*)m_root->child(i); if (itemTitle->getTitle()->getButton()==_button) { QImage img=_image.scaled(50,40,Qt::IgnoreAspectRatio); QPixmap pix=QPixmap::fromImage(img); itemTitle->setIcon(0,QIcon(pix)); } } } void k9Import::removeTitle(k9LvItemImport *_item) { m_selected=_item; removeTitle(); } void k9Import::removeTitle() { m_newDVD->getRootMenu()->removeButton(m_selected->getTitle()->getButton()); m_selected->getTitle()->getButton()->remove(); m_newDVD->getTitles()->removeAll( m_selected->getTitle()); m_selected->parent()->removeChild(m_selected); } void k9Import::addChapter() { k9LvItemImport *title=(k9LvItemImport*) m_selected; k9AviFile *file=new k9AviFile(title->getTitle(),0); if (title->childCount() >0) { k9AviFile *f2 = title->getTitle()->getFiles()->at(0); file->setReencode(f2->getReencode()); } k9Config config; k9LvItemImport * itemch=new k9LvItemImport(title,k9LvItemImport::CHAPTER); itemch->setText(0,i18n("chapter %1").arg(title->childCount())); itemch->setAviFile(file); itemch->setTitle(title->getTitle()); connect(file,SIGNAL(aviFileUpdated(k9AviFile*)),this,SLOT(aviFileUpdated(k9AviFile*))); k9MenuButton *btn=title->getTitle()->getMenu()->addButton(); btn->setNum(title->childCount()); //_title->setButton(btn); QImage img; btn->setImage(img); btn->setTop(0); btn->setLeft(0); btn->setWidth(config.getPrefButtonWidth()); btn->setHeight(config.getPrefButtonHeight()); btn->setScript(QString("jump title 1 chapter %1 ;").arg(title->childCount())); btn->setTextPosition(BOTTOM); btn->setText(i18n("chapter %1").arg(title->childCount())); btn->setColor(config.getPrefButtonTextColor()); btn->setFont(config.getPrefButtonFont()); file->setButton(btn); connect(file,SIGNAL(imageChanged(const QImage&)),btn,SLOT(setImage(const QImage&))); } void k9Import::removeChapter() { k9LvItemImport *title=(k9LvItemImport*) m_selected->parent(); title->getTitle()->getFiles()->removeAll(m_selected->getAviFile()); //if trying to remove the last chapter, remove the entire title if (title->childCount()==1) { m_selected=title; removeTitle(); return; } k9AviFile *previous=m_selected->getAviFile()->getPrevious(); k9AviFile *next=m_selected->getAviFile()->getNext(); if (previous) { previous->setNext(next); previous->setBreakNext(true); } if (next) { next->setPrevious(previous); next->setBreakPrevious(true); } m_selected->getAviFile()->getButton()->remove(); title->getTitle()->getMenu()->removeButton(m_selected->getAviFile()->getButton()); m_selected->parent()->removeChild(m_selected); emit titleSelected(title->getTitle()); emit aviFileSelected(NULL); } void k9Import::showPopup(const QPoint & iPosition) { QTreeWidgetItem * item = 0 ; item = lvDVD->itemAt(iPosition) ; switch (item->type()) { case k9LvItemImport::TITLE : { m_selected=(k9LvItemImport*) item; QMenu menu(lvDVD); QAction *m=new QAction(SmallIcon("list-remove"),i18n("remove"),this); connect(m, SIGNAL(triggered()), this, SLOT(removeTitle())); menu.addAction(m); m=new QAction(SmallIcon("list-add"),i18n("add chapter"),this); connect(m, SIGNAL(triggered()), this, SLOT(addChapter())); menu.addAction(m); menu.exec(lvDVD->mapToGlobal(iPosition)); } break; case k9LvItemImport::CHAPTER: { m_selected=(k9LvItemImport*)item; QMenu menu(lvDVD); QAction *m=new QAction(SmallIcon("list-remove"),i18n("remove"),this); connect(m, SIGNAL(triggered()), this, SLOT(removeChapter())); menu.addAction(m); menu.exec(lvDVD->mapToGlobal(iPosition)); } break; default: m_selected=NULL; } } void k9Import::lvDVDCurrentChanged( QTreeWidgetItem *_item,QTreeWidgetItem *) { if (_item==NULL) return; k9LvItemImport *item=(k9LvItemImport*)_item; switch (_item->type()) { case 1002: emit aviFileSelected(item->getAviFile()); emit titleSelected(item->getTitle()); break; case 1001: emit titleSelected(item->getTitle()); emit aviFileSelected(NULL); break; default: emit rootSelected(m_newDVD); emit aviFileSelected(NULL); break; } } void k9Import::execute() { QString filename; k9Config config; QString outputDir=config.getPrefOutput(); if (Ui_import.cbOutputDev->currentIndex() ==0) { // changed QDir::homePath() to outputDir (bkp) filename=k9Dialogs::getSaveFileName (outputDir,"*.iso", 0,i18n("Save image to disk")); if (filename =="") return; } else if (Ui_import.cbOutputDev->currentIndex()==1) { // changed QDir::homePath() to outputDir (bkp) outputDir= k9Dialogs::getExistingDirectory(outputDir); if (outputDir=="") return; } k9ProcessList *p=new k9ProcessList(k9Dialogs::getMainWidget()); p->setModal(true); p->show(); m_newDVD->setProcessList(p); m_newDVD->setWorkDir(outputDir); m_newDVD->execute(); p->close(); bool burn=(m_newDVD->getError()=="") ; if (burn && Ui_import.cbOutputDev->currentIndex()!=1) { //changeStatusbar(i18n("Burning DVD"),sbMessage); k9BurnDVD b; b.setworkDir(config.getPrefOutput() +"/dvd"); b.setUseK3b(config.getPrefK3b() ); b.setAutoBurn(config.getPrefAutoBurn()); b.setvolId("DVD"); b.setSpeed( i18n("default")); if (Ui_import.cbOutputDev->currentIndex() !=0) { k9CdDrive * drive=(k9CdDrive*)recorderList.at(Ui_import.cbOutputDev->currentIndex()-2); b.setburnDevice(drive->device); } else b.makeIso(filename); b.burn(); } // m_parent->removeDockWidget(doc); } void k9Import::cbFormatActivated(const QString &_format) { if (_format == "PAL") { m_newDVD->setFormat(k9NewDVD::PAL); m_menuEdit->setFormat(k9MenuEdit::PAL); } else { m_newDVD->setFormat(k9NewDVD::NTSC); m_menuEdit->setFormat(k9MenuEdit::NTSC); } } void k9Import::setMenuEdit(k9MenuEdit* _value) { m_menuEdit = _value; } void k9Import::setEnableCreate(bool _state) { // m_parent->setEnabledCreateDVD(true); } void k9Import::titleAdded() { emit rootSelected(m_newDVD); } void k9Import::updateTotalTime() { int total=m_newDVD->getTotalTime(); //Ui_import.gsTotal->setValue(total/60); QTime t(0,0,0); t=t.addSecs(total); Ui_import.lTotal->setText(t.toString("hh:mm:ss")); } k9copy/src/import/k9avifile.h0000644000175000017550000000334412412271774016713 0ustar emulatoremulator// // C++ Interface: k9avifile // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9AVIFILE_H #define K9AVIFILE_H #include #include #include /** @author Jean-Michel PETIT */ class k9Title; class k9MenuButton; class k9AviFile : public QObject { Q_OBJECT public: k9AviFile(k9Title *parent = 0, const char *name = 0); ~k9AviFile(); void setFileName ( const QString& _value ); QString getFileName() const; void setStart ( const QTime& _value ); QTime getStart() const; void setEnd ( const QTime& _value ); QTime getEnd() const; void setLabel ( const QString& _value ); QString getLabel() const; k9Title* getTitle() const; int getNum() const; void setPrevious ( k9AviFile* _value ); k9AviFile* getPrevious() const; void setNext ( k9AviFile* _value ); k9AviFile* getNext() const; void setBreakPrevious(bool _state); bool getBreakPrevious(); void setBreakNext(bool _state); bool getBreakNext(); void setImage(const QImage& _value); QImage getImage() const; void setButton(k9MenuButton* theValue); k9MenuButton* getButton() const; void setReencode(bool theValue); bool getReencode() const; private: QString m_fileName; QTime m_start; QString m_label; QTime m_end; k9Title *m_title; QImage m_image; int m_num; bool m_breakNext,m_breakPrevious; bool m_reencode; k9AviFile *m_previous; k9AviFile *m_next; void setTitle ( k9Title* _value ); k9MenuButton *m_button; signals: void aviFileUpdated(k9AviFile *_aviFile); void imageChanged(const QImage &); }; #endif k9copy/src/import/k9avidecode.h0000644000175000017550000001255212412271774017220 0ustar emulatoremulator// // C++ Interface: k9avidecode // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9AVIDECODE_H #define K9AVIDECODE_H #include "k9common.h" #include #include #include #include #include #include #ifdef HAVE_SWSCALE #include #endif /** @author Jean-Michel PETIT */ //typedef dvd_file_t * (*DVDOpenFile_t) ( dvd_reader_t *, int, dvd_read_domain_t ); typedef void (*av_register_all_t) (void); typedef int64_t (*av_gettime_t) (void); #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 2, 0) typedef int (*avformat_open_input_t)(AVFormatContext **, const char *, AVInputFormat *, AVDictionary **); #else typedef int (*av_open_input_file_t)(AVFormatContext **, const char *,AVInputFormat *,int, AVFormatParameters *); #endif #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 6, 0) typedef int (*avformat_find_stream_info_t)(AVFormatContext *, AVDictionary **); #else typedef int (*av_find_stream_info_t)(AVFormatContext *); #endif typedef AVCodec* (*avcodec_find_decoder_t)(enum AVCodecID); #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 8, 0) typedef int (*avcodec_open2_t)(AVCodecContext *, AVCodec *, AVDictionary **); #else typedef int (*avcodec_open_t)(AVCodecContext *, AVCodec *); #endif typedef AVFrame * (*avcodec_alloc_frame_t)(void); typedef int (*avpicture_get_size_t)(int , int , int ); typedef void * (*av_malloc_t)(unsigned int ); typedef int (*avpicture_fill_t)(AVPicture *, uint8_t *,int , int , int); typedef int (*av_read_frame_t)(AVFormatContext *, AVPacket *); #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 23, 0) typedef int (*avcodec_decode_video2_t)(AVCodecContext *, AVFrame *, int *, AVPacket *); #else typedef int (*avcodec_decode_video_t)(AVCodecContext *, AVFrame *,int *, uint8_t *, int ); #endif typedef int (*img_convert_t)(AVPicture *, int , const AVPicture *, int ,int, int); typedef void (*av_free_t)(void *); typedef int (*avcodec_close_t)(AVCodecContext *); #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 17, 0) typedef void (*avformat_close_input_t)(AVFormatContext **); #else typedef void (*av_close_input_file_t)(AVFormatContext *); #endif typedef int (*av_seek_frame_t)(AVFormatContext *,int,int64_t timestamp,int flags); typedef int64_t (*av_rescale_q_t)(int64_t , AVRational , AVRational ) ; typedef void (*avcodec_flush_buffers_t)(AVCodecContext *); typedef void (*av_free_packet_t)(AVPacket *); #ifdef HAVE_SWSCALE typedef void (*sws_freeContext_t)(struct SwsContext *swsContext); typedef struct SwsContext* (*sws_getContext_t)(int srcW, int srcH, int srcFormat, int dstW, int dstH, int dstFormat, int flags, SwsFilter *srcFilter, SwsFilter *dstFilter, double *param); typedef int (*sws_scale_t)(struct SwsContext *context, uint8_t* src[], int srcStride[], int srcSliceY,int srcSliceH, uint8_t* dst[], int dstStride[]); #endif class k9AviDecode : public QObject { Q_OBJECT public: k9AviDecode(QObject *parent = 0, const char *name = 0); ~k9AviDecode(); bool open(const QString & _fileName); void readFrame(double _seconds); void seek(double _seconds); void close(); double getDuration() const; bool opened() const; QString getFileName() const; QString getError() const; private: av_register_all_t av_register_all; # if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 2, 0) avformat_open_input_t avformat_open_input; # else av_open_input_file_t av_open_input_file; # endif # if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 6, 0) avformat_find_stream_info_t avformat_find_stream_info; # else av_find_stream_info_t av_find_stream_info; # endif avcodec_find_decoder_t avcodec_find_decoder; # if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 8, 0) avcodec_open2_t avcodec_open2; # else avcodec_open_t avcodec_open; # endif avcodec_alloc_frame_t avcodec_alloc_frame; av_seek_frame_t av_seek_frame; avpicture_get_size_t avpicture_get_size; av_malloc_t av_malloc; avpicture_fill_t avpicture_fill; av_read_frame_t av_read_frame; # if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 23, 0) avcodec_decode_video2_t avcodec_decode_video2; # else avcodec_decode_video_t avcodec_decode_video; # endif img_convert_t img_convert; av_free_t av_free; avcodec_close_t avcodec_close; # if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 17, 0) avformat_close_input_t avformat_close_input; # else av_close_input_file_t av_close_input_file; # endif av_rescale_q_t av_rescale_q; av_gettime_t av_gettime; avcodec_flush_buffers_t avcodec_flush_buffers; av_free_packet_t av_free_packet; #ifdef HAVE_SWSCALE sws_freeContext_t sws_freeContext; sws_getContext_t sws_getContext; sws_scale_t sws_scale; #endif void *CodecHandle; void *FormatHandle; void *UtilHandle; void *SwscaleHandle; int glibref; AVFormatContext *m_FormatCtx; AVCodecContext *m_CodecCtx; AVCodec *m_Codec; AVFrame *m_Frame,*m_FrameRGB; uint8_t *m_buffer; int m_videoStream; bool m_opened; double m_duration; QString m_fileName; QString m_error; int64_t calcDuration(); void SaveFrame(AVFrame *pFrame, int width, int height); signals: void drawFrame(QImage); }; #endif k9copy/src/import/k9menu.cpp0000644000175000017550000002334512412271774016576 0ustar emulatoremulator// // C++ Implementation: k9menu // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "k9menu.h" #include "k9menubutton.h" #include #include #include #include #include "k9tools.h" k9Menu::k9Menu(QObject *parent, const char *) : QObject(parent),m_format(PAL) { // m_buttons.setAutoDelete(false); m_scene=new k9MenuScene(this); QPixmap pix(720,576); pix.fill(Qt::black); //m_canvas->setBackgroundPixmap(pix); m_startScript=m_startScript2=m_endScript=""; } k9Menu::~k9Menu() { // qDeleteAll(m_buttons); } k9MenuButton *k9Menu::addButton() { k9MenuButton *button=new k9MenuButton(m_scene,""); m_buttons.append(button); return button; } void k9Menu::removeButton(k9MenuButton *_button) { m_buttons.removeAll(_button); } bool k9Menu::createMenus(QDomElement *_rootNode) { m_error=false; m_config=new k9Config(); int height=m_format==PAL?576:480; QImage img; m_scene->setSceneRect(0,0,720,height); foreach (QGraphicsItem *item, m_scene->selectedItems()) item->setSelected(false); //create menu image QPixmap pixbg(720,height); QPainter pbg(&pixbg); m_scene->render(&pbg,QRectF(0,0,720,height),QRectF(0,0,720,height)); //create the hilite picture int lineWidth=2; img=QImage(720,height,QImage::Format_RGB32); QPixmap pixhi; pixhi=QPixmap::fromImage(img,0); pixhi.fill(Qt::transparent); QPainter phi(&pixhi); QPen penhi; penhi.setColor(m_config->getPrefButtonHiliteColor()); penhi.setWidth(lineWidth*2); phi.setPen(penhi); phi.setBrush(Qt::NoBrush); //draw buttons foreach (k9MenuButton *button,m_buttons) { //draw hilight phi.drawRect(button->getLeft()+lineWidth,button->getTop()+lineWidth,button->getWidth()-lineWidth,button->getHeight()-lineWidth); } pbg.end(); phi.end(); //save menu image QString bgFileName=m_workDir+k9Tools::randomFileName()+".jpg"; QString hiFileName=m_workDir+k9Tools::randomFileName()+".png"; QString m2vFileName= m_workDir+k9Tools::randomFileName()+".m2v"; QString mpaFileName= m_workDir+k9Tools::randomFileName()+".m2v"; QString mpgFileName= m_workDir+k9Tools::randomFileName()+".mpg"; pixbg.save(bgFileName,"JPEG",-1); pixhi.save(hiFileName,"PNG",-1); convertJpegToMpeg(bgFileName,m2vFileName); createAudio(mpaFileName); multiplex(mpaFileName,m2vFileName,mpgFileName); spumux(hiFileName,mpgFileName); appendMenu(_rootNode); QFile::remove(bgFileName); QFile::remove(m2vFileName); QFile::remove(mpaFileName); QFile::remove(mpgFileName); QFile::remove(hiFileName); delete m_config; return !m_error; } void k9Menu::convertJpegToMpeg(const QString &_imageJpg,const QString &_imageMpg) { if (! (k9Tools::checkProgram("ppmtoy4m",true) && k9Tools::checkProgram("jpegtopnm",true) && k9Tools::checkProgram("mpeg2enc",true))) { m_error=true; return; } k9Process *process=new k9Process(0,0); process->setWorkingDirectory(m_workDir); //process->setUseShell(true); QStringList proc; if (m_format==NTSC) { // proc << "jpeg2yuv" << "-n" << "50" << "-I" << "p" << "-f" << "29.97" << "-j" << _imageJpg << "|"; proc << "jpegtopnm" << _imageJpg << "|" <<"ppmtoy4m" << "-n" << "50"<<"-F29.97:1"<<"-I" <<"t" << "-A"<<"59:54"<< "-L" <<"-S" << "420mpeg2"<<"|"; proc << "mpeg2enc" << "-F" << "4" << "-n" << "n" <<"-f" << "8" << "-o" << _imageMpg; } else { // proc << "jpeg2yuv" << "-n" << "50" << "-I" << "p" << "-f" << "25" << "-j" << _imageJpg << "|"; proc << "jpegtopnm" << _imageJpg << "|" <<"ppmtoy4m" << "-n" << "50"<<"-F25:1"<<"-I" <<"t" << "-A"<<"59:54"<< "-L" << "-S" << "420mpeg2"<< "|"; proc << "mpeg2enc" << "-n" << "p" <<"-f" << "8" << "-o" << _imageMpg; } process->setShellCommand(proc.join(" ")); process->start(); process->sync(); qDebug() << process->debug(); if (!process->normalExit()) { qDebug("error converting jpeg to mpeg"); } } void k9Menu::createAudio(const QString & _audioFile) { if (! (k9Tools::checkProgram("twolame",false) || k9Tools::checkProgram("toolame",false))) { m_error=true; k9Dialogs::error(i18n("Error starting program %1").arg("twolame | toolame"),i18n("Running program")); return; } k9Process *process=new k9Process(0,0); process->setWorkingDirectory(m_workDir); // process->setUseShell(true); QStringList proc; if (k9Tools::checkProgram("toolame")) proc << "dd" << "if=/dev/zero" << "bs=4" << "count=1920" << "|" << "toolame" << "-b" << "128" << "-s" << "48" << "/dev/stdin" << _audioFile; else proc << "dd" << "if=/dev/zero" << "bs=4" << "count=1920" << "|" << "twolame" <<"-r" << "-b" << "128" << "-s" << "48000" << "/dev/stdin" << _audioFile; process->setShellCommand(proc.join(" ")); process->start(); process->sync(); if (!process->normalExit()) { qDebug("error creating audio stream"); } } void k9Menu::multiplex(const QString &_audio, const QString &_video, const QString _result) { if (! k9Tools::checkProgram("mplex",true) ) { m_error=true; return; } k9Process *process=new k9Process(0,0); process->setWorkingDirectory(m_workDir); // process->setUseShell(true); QStringList cmd; cmd << "mplex" << "-f" << "8" << "-o" << _result << _video << _audio; process->setShellCommand(cmd.join(" ")); process->start(); process->sync(); if (!process->normalExit()) { qDebug("error multiplexing audio and video"); } } void k9Menu::spumux(const QString &_hiFileName,const QString &_mpgFileName) { if (! k9Tools::checkProgram("spumux",true)) { m_error=true; return; } QDomElement stream,spu; QDomDocument xml; QDomElement root = xml.createElement( "subpictures" ); xml.appendChild( root ); stream=xml.createElement("stream"); root.appendChild(stream); spu=xml.createElement("spu"); stream.appendChild(spu); spu.setAttribute("start","00:00:00.0"); spu.setAttribute("end","00:00:00.0"); spu.setAttribute("highlight",_hiFileName); spu.setAttribute("select",_hiFileName); //spu.setAttribute("autooutline","infer"); spu.setAttribute("force","yes"); // spu.setAttribute("autoorder","rows"); spu.setAttribute("xoffset","0"); spu.setAttribute("yoffset","0"); int i=1; foreach (k9MenuButton *button,m_buttons) { QDomElement eButton = xml.createElement("button"); spu.appendChild(eButton); eButton.setAttribute("name",QString("button%1").arg(i)); eButton.setAttribute("x0", QString::number(button->getLeft())); eButton.setAttribute("y0",QString::number(button->getTop())); eButton.setAttribute("x1",QString::number(button->getLeft()+button->getWidth())); eButton.setAttribute("y1",QString::number(button->getTop()+button->getHeight())); i++; } QString spuFileName(m_workDir + k9Tools::randomFileName()+ ".xml"); QFile file( spuFileName ); if ( file.open( QIODevice::WriteOnly ) ) { QTextStream stream( &file ); xml.save(stream,1); file.close(); } k9Process *process=new k9Process(0,0); process->setWorkingDirectory(m_workDir); // process->setUseShell(true); // *process << "mplex" << "-f" << "8" << "-o" << _result << _video << _audio; QStringList cmd; cmd << "spumux" << spuFileName << "<" << _mpgFileName << ">" << m_menuFileName; process->setShellCommand(cmd.join(" ")); process->start(); process->sync(); if (!process->normalExit()) { qDebug("error multiplexing audio and video"); } file.remove(); } void k9Menu::appendMenu(QDomElement *_rootNode) { QDomDocument doc=_rootNode->ownerDocument(); QDomNodeList l=_rootNode->elementsByTagName("menus"); QDomNode menus; if (l.count()==0) { menus=doc.createElement("menus"); _rootNode->appendChild(menus); } else { menus=l.item(0); } QDomElement pgc=doc.createElement("pgc"); menus.appendChild(pgc); QDomElement pre=doc.createElement("pre"); pgc.appendChild(pre); QDomText txt=doc.createTextNode(m_startScript +m_startScript2); pre.appendChild(txt); QDomElement vob=doc.createElement("vob"); pgc.appendChild(vob); vob.setAttribute("file",m_menuFileName); vob.setAttribute("pause","inf"); int i=1; foreach (k9MenuButton *button,m_buttons) { QDomElement eButton = doc.createElement("button"); pgc.appendChild(eButton); QDomText eButtonTxt=doc.createTextNode(button->getScript()); eButton.appendChild(eButtonTxt); eButton.setAttribute("name",QString("button%1").arg(i)); i++; } } QString k9Menu::getWorkDir() const { return m_workDir; } void k9Menu::setWorkDir(const QString& _value) { m_workDir = _value; } void k9Menu::setFormat(const eFormat& _value) { m_format = _value; } QString k9Menu::getMenuFileName() const { return m_menuFileName; } void k9Menu::setMenuFileName(const QString& _value) { m_menuFileName = _value; } k9MenuScene *k9Menu::getScene() const { return m_scene; } void k9Menu::setScene(k9MenuScene *_scene) { m_scene=_scene; } void k9Menu::setStartScript(const QString &_value) { m_startScript=_value; } QString k9Menu::getStartScript() const { return m_startScript; } void k9Menu::setStartScript2(const QString &_value) { m_startScript2=_value; } QString k9Menu::getStartScript2() const { return m_startScript2; } QString k9Menu::getEndScript() const { return m_endScript; } void k9Menu::setEndScript(const QString& _value) { m_endScript = _value; } k9copy/src/import/CTestTestfile.cmake0000664000175000017550000000051712412271774020404 0ustar emulatoremulator# CMake generated Testfile for # Source directory: /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/src/import # Build directory: /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/src/import # # This file includes the relevant testing commands required for # testing this directory and lists subdirectories to be tested as well. k9copy/src/import/k9newdvd.h0000644000175000017550000000416612412271774016566 0ustar emulatoremulator// // C++ Interface: k9newdvd // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9NEWDVD_H #define K9NEWDVD_H #include "k9common.h" #include #include #include #include #include "k9progress.h" #include "k9avidecode.h" /** @author Jean-Michel PETIT */ class k9Title; class k9AviFile; class k9Menu; class k9ProcessList; class k9NewDVDItems : public QList { public: static bool compareItems ( k9Title* item1,k9Title* item2 ); }; class k9NewDVD : public QObject { Q_OBJECT public: enum eFormat {NTSC=2,PAL=1}; k9NewDVD ( QObject *parent = 0, const char *name = 0 ); ~k9NewDVD(); k9NewDVDItems* getTitles() { return &m_titles; } eFormat m_format; void execute(); void createXML(); void addTitles ( QDomElement &_root ); void setFormat ( const eFormat& _value ); void setWorkDir ( const QString& _value ); void appendTitle ( k9Title *_title ); void setProcessList(k9ProcessList *_value); eFormat getFormat() const; int getTotalTime(); k9Menu* getRootMenu() const; QString getError() const; private: k9NewDVDItems m_titles; QStringList m_tmpFiles; QDomDocument *m_xml; QString m_workDir; k9ProcessList *m_processList; QTime m_timer; QTime m_timer2; QTime m_timer3; k9Menu *m_rootMenu; bool m_cancel; QString m_error; QString m_stdout; int m_videoBitrate; k9AviDecode m_aviDecode; int m_totalEncodedSize; int m_offset; int m_lastvalue; QMap m_timers; void calcVideoBitrate(); void createMencoderCmd ( QString &_cmd,QString &_chapters, k9AviFile *_aviFile ); void splitFile(k9AviFile *_aviFile); k9Config *m_config; QStringList m_splitCells; int64_t readscr(const unsigned char *buf); protected slots: void getStdout ( k9Process *,char *, int ); void getStderr ( k9Process *,char *, int ); void drawImage ( QImage _image ); signals: void sigAddTitle(); }; #endif k9copy/src/import/k9newtitle.cpp0000644000175000017550000001571712412271774017471 0ustar emulatoremulator// // C++ Implementation: // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "k9newtitle.h" #include "k9import.h" #include #include "k9avidecode.h" #include "k9menu.h" #include "k9menubutton.h" #if QT_VERSION >= 0x050000 #include #else #include "kpushbutton.h" #endif #include #include "k9cell.h" #if QT_VERSION >= 0x050000 //Qt5 Code #include #include #include #include #else //Qt4 Code #include #endif k9NewTitle::k9NewTitle(QWidget* parent) : QWidget(parent) { m_fileName=""; Ui_newTitle.setupUi(this); Ui_newTitle.urFile->setFilter("*.avi|Audio Video Interleave (*.avi)\n*.mpg|MPEG-1 and MPEG-2 systems (*.mpg)\n*.mp4|MPEG-4 format (*.mp4)\n*.asf|Advanced Streaming Format (*.asf)\n*.swf|Adobe Flash (*.swf)\n*.flv|Adobe Flash video files (*.flv)\n*.rm|RealVideo (*.rm)\n*.mov|QuickTime (*.mov)\n*.mkv|Matroska (*.mkv)\n*.*|All (*.*)"); Ui_newTitle.urFile->setMode(KFile::File) ; #if QT_VERSION >= 0x050000 //Qt5 Code Ui_newTitle.urFile->fileDialog()->setAcceptMode(QFileDialog::AcceptOpen); #else //Qt4 Code Ui_newTitle.urFile->fileDialog()->setOperationMode(KFileDialog::Opening); #endif #if QT_VERSION >= 0x050000 KGuiItem::assign(Ui_newTitle.bAdd, KStandardGuiItem::add() ); #else Ui_newTitle.bAdd->setGuiItem(KStandardGuiItem::Add); #endif Ui_newTitle.ckReencode->setEnabled(false); Ui_newTitle.bAdd->setEnabled(false); } k9NewTitle::~k9NewTitle() { } /*$SPECIALIZATION$*/ bool k9NewTitle::isMpeg2(const QString &_fileName) { char buffer[2048]; QFile f(_fileName); f.open(QIODevice::ReadOnly); f.read(buffer,2048); f.close(); if (k9Cell::isNavPack((uchar*)buffer)==1) return true; else return false; } #if QT_VERSION >= 0x050000 void k9NewTitle::urlSelected(const QUrl &_url) { #else void k9NewTitle::urlSelected(const KUrl &_url) { #endif m_fileName=_url.toLocalFile(); k9AviDecode fileInfo(0,0); fileInfo.open(m_fileName); double duration=fileInfo.getDuration(); fileInfo.close(); QTime t(0,0,0); t=t.addSecs(duration); Ui_newTitle.lTotalTime->setText(t.toString("hh:mm:ss")); Ui_newTitle.bAdd->setEnabled(true); bool mpeg2=isMpeg2(m_fileName); Ui_newTitle.ckReencode->setEnabled(mpeg2); } void k9NewTitle::drawImage (QImage _image) { m_image=_image; } void k9NewTitle::ckReencodeClicked() { if (Ui_newTitle.ckReencode->isChecked()) { Ui_newTitle.rbNumber->setChecked(true); Ui_newTitle.nbChapters->setValue(1); } Ui_newTitle.nbChapters->setEnabled(!Ui_newTitle.ckReencode->isChecked()); Ui_newTitle.twLength->setEnabled(!Ui_newTitle.ckReencode->isChecked()); Ui_newTitle.rbNumber->setEnabled(!Ui_newTitle.ckReencode->isChecked()); Ui_newTitle.rbLength->setEnabled(!Ui_newTitle.ckReencode->isChecked()); } void k9NewTitle::bAddClicked() { k9Config config; k9AviDecode fileInfo(0,0); if (!fileInfo.open(m_fileName)) { k9Dialogs::error(fileInfo.getError(),i18n("Add title")); return; } this->setCursor(QCursor(Qt::WaitCursor)); k9LvItemImport *item=new k9LvItemImport(m_k9Import->getRoot(),k9LvItemImport::TITLE); item->setExpanded(true); k9Title *title=new k9Title( m_k9Import->getNewDVD()); item->setText(0,i18n("title %1").arg(title->getNum() +1)); connect( title->getButton(),SIGNAL(sigsetImage(k9MenuButton*, const QImage&)),m_k9Import,SLOT(buttonUpdated(k9MenuButton*, const QImage&))); item->setTitle(title); connect(&fileInfo,SIGNAL(drawFrame(QImage)),this,SLOT(drawImage(QImage))); QTime t; item->setText(1,t.addSecs(fileInfo.getDuration()).toString("hh:mm:ss")); double increment=0; int maxCh; if (Ui_newTitle.rbLength->isChecked()) { QTime t; increment=t.secsTo(Ui_newTitle.twLength->time()); maxCh=999; } if (Ui_newTitle.rbNumber->isChecked()) { increment=fileInfo.getDuration() /Ui_newTitle.nbChapters->value(); maxCh=Ui_newTitle.nbChapters->value(); } double pos=0; k9AviFile *last=NULL; int width=config.getPrefButtonWidth(); int height=config.getPrefButtonHeight(); int left=-width+20; int top=50; int i=-1; while ( pos setImage(m_image); if (i==0) title->getButton()->setImage(m_image); file->setPrevious(last); if (last !=NULL) last->setNext(file); last=file; file->setFileName(m_fileName); file->setStart(t.addMSecs(pos*1000)); pos+=increment; file->setEnd(t.addMSecs(qMin(pos,fileInfo.getDuration()) *1000)); file->setReencode(!Ui_newTitle.ckReencode->isChecked()); k9LvItemImport * itemch=new k9LvItemImport(item,k9LvItemImport::CHAPTER); itemch->setText(0,i18n("chapter %1").arg(i+1)); itemch->setText(1,file->getStart().toString("hh:mm:ss") +" - "+file->getEnd().toString("hh:mm:ss") ); itemch->setAviFile(file); itemch->setTitle(title); itemch->setIcon(0,QIcon(QPixmap::fromImage(m_image.scaled(50,40)))); connect(file,SIGNAL(aviFileUpdated(k9AviFile*)),m_k9Import,SLOT(aviFileUpdated(k9AviFile*))); k9MenuButton *btn=title->getMenu()->addButton(); btn->setNum(i+1); //_title->setButton(btn); btn->setImage(m_image); left +=width+10; if (left +width >720) { left=30; top+=height+25; } btn->setTop(top); btn->setLeft(left); btn->setWidth(width); btn->setHeight(height); btn->setScript(QString("jump title 1 chapter %1 ;").arg(i+1)); btn->setTextPosition(BOTTOM); btn->setText(i18n("chapter %1").arg(i+1)); btn->setColor(config.getPrefButtonTextColor()); btn->setFont(config.getPrefButtonFont()); file->setButton(btn); connect(file,SIGNAL(imageChanged(const QImage&)),btn,SLOT(setImage(const QImage&))); } title->getMenu()->setEndScript("call vmgm menu;"); fileInfo.close(); m_k9Import->lvDVD->sortItems(0,Qt::AscendingOrder); m_k9Import->setEnableCreate(true); m_k9Import->updateTotalTime(); this->setCursor(QCursor(Qt::ArrowCursor)); m_k9Import->getRoot()->treeWidget()->resizeColumnToContents(0); } void k9NewTitle::rbNumberClicked() { Ui_newTitle.twLength->setEnabled(false); Ui_newTitle.nbChapters->setEnabled(true); } void k9NewTitle::rbLengthClicked() { Ui_newTitle.twLength->setEnabled(true); Ui_newTitle.nbChapters->setEnabled(false); } void k9NewTitle::setK9Import ( k9Import* _value ) { m_k9Import = _value; } k9copy/src/import/Makefile0000664000175000017550000001502312412271774016316 0ustar emulatoremulator# CMAKE generated file: DO NOT EDIT! # Generated by "Unix Makefiles" Generator, CMake Version 2.8 # Default target executed when no arguments are given to make. default_target: all .PHONY : default_target #============================================================================= # Special targets provided by cmake. # Disable implicit rules so canonical targets will work. .SUFFIXES: # Remove some rules from gmake that .SUFFIXES does not remove. SUFFIXES = .SUFFIXES: .hpux_make_needs_suffix_list # Suppress display of executed commands. $(VERBOSE).SILENT: # A target that is always out of date. cmake_force: .PHONY : cmake_force #============================================================================= # Set environment variables for the build. # The shell in which to execute make rules. SHELL = /bin/sh # The CMake executable. CMAKE_COMMAND = /usr/bin/cmake # The command to remove a file. RM = /usr/bin/cmake -E remove -f # Escaping for special characters. EQUALS = = # The program to use to edit the cache. CMAKE_EDIT_COMMAND = /usr/bin/ccmake # The top-level source directory on which CMake was run. CMAKE_SOURCE_DIR = /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 # The top-level build directory on which CMake was run. CMAKE_BINARY_DIR = /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 #============================================================================= # Targets provided globally by CMake. # Special rule for the target edit_cache edit_cache: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." /usr/bin/ccmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) .PHONY : edit_cache # Special rule for the target edit_cache edit_cache/fast: edit_cache .PHONY : edit_cache/fast # Special rule for the target install install: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." /usr/bin/cmake -P cmake_install.cmake .PHONY : install # Special rule for the target install install/fast: preinstall/fast @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." /usr/bin/cmake -P cmake_install.cmake .PHONY : install/fast # Special rule for the target install/local install/local: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..." /usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake .PHONY : install/local # Special rule for the target install/local install/local/fast: install/local .PHONY : install/local/fast # Special rule for the target list_install_components list_install_components: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"Unspecified\"" .PHONY : list_install_components # Special rule for the target list_install_components list_install_components/fast: list_install_components .PHONY : list_install_components/fast # Special rule for the target package package: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Run CPack packaging tool..." cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && /usr/bin/cpack --config ./CPackConfig.cmake .PHONY : package # Special rule for the target package package/fast: package .PHONY : package/fast # Special rule for the target package_source package_source: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Run CPack packaging tool for source..." cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && /usr/bin/cpack --config ./CPackSourceConfig.cmake /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CPackSourceConfig.cmake .PHONY : package_source # Special rule for the target package_source package_source/fast: package_source .PHONY : package_source/fast # Special rule for the target rebuild_cache rebuild_cache: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." /usr/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) .PHONY : rebuild_cache # Special rule for the target rebuild_cache rebuild_cache/fast: rebuild_cache .PHONY : rebuild_cache/fast # Special rule for the target test test: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running tests..." /usr/bin/ctest --force-new-ctest-process $(ARGS) .PHONY : test # Special rule for the target test test/fast: test .PHONY : test/fast # The main all target all: cmake_check_build_system cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(CMAKE_COMMAND) -E cmake_progress_start /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CMakeFiles /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/src/import/CMakeFiles/progress.marks cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 src/import/all $(CMAKE_COMMAND) -E cmake_progress_start /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CMakeFiles 0 .PHONY : all # The main clean target clean: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 src/import/clean .PHONY : clean # The main clean target clean/fast: clean .PHONY : clean/fast # Prepare targets for installation. preinstall: all cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 src/import/preinstall .PHONY : preinstall # Prepare targets for installation. preinstall/fast: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 src/import/preinstall .PHONY : preinstall/fast # clear depends depend: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 .PHONY : depend # Help Target help: @echo "The following are some of the valid targets for this Makefile:" @echo "... all (the default if no target is provided)" @echo "... clean" @echo "... depend" @echo "... edit_cache" @echo "... install" @echo "... install/local" @echo "... list_install_components" @echo "... package" @echo "... package_source" @echo "... rebuild_cache" @echo "... test" .PHONY : help #============================================================================= # Special targets to cleanup operation of make. # Special rule to run CMake to check the build system integrity. # No rule that depends on this can have commands that come from listfiles # because they might be regenerated. cmake_check_build_system: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 .PHONY : cmake_check_build_system k9copy/src/import/k9menuscene.cpp0000644000175000017550000000141512412271774017606 0ustar emulatoremulator#include "k9menuscene.h" #include k9MenuScene::k9MenuScene(QObject *parent):QGraphicsScene(parent) { QPixmap pm(720,576); m_pixmap=pm; m_pixmap.fill(Qt::black); } void k9MenuScene::drawBackground ( QPainter * painter, const QRectF & rect ) { QGraphicsScene::drawBackground(painter,rect); QRectF r=this->sceneRect().intersected(rect); if ((rect.left() < r.left()) || (rect.right()>r.right()) || (rect.top()< r.top()) || (rect.bottom()>r.bottom())) { QBrush br(Qt::SolidPattern); br.setColor(Qt::gray); painter->fillRect(rect,br); } painter->drawPixmap(r.toRect(), m_pixmap.copy(r.toRect())); } void k9MenuScene::setBackgroundPixmap(const QPixmap &pixmap) { m_pixmap=pixmap; update(sceneRect()); } k9copy/src/import/k9import.h0000644000175000017550000000410712412271774016604 0ustar emulatoremulator// // C++ Interface: // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9IMPORT_H #define K9IMPORT_H #include "k9common.h" #include "k9copy.h" #include "ui_import.h" #include "k9newdvd.h" #include class k9AviFile; class k9MenuButton; class k9MenuEdit; class k9ImportFiles; class k9LvItemImport; class k9Import : public QWidget { Q_OBJECT private: QTreeWidgetItem *m_root; k9NewDVD *m_newDVD; // KMdiToolViewAccessor *m_toolView; // KDockWidget *m_dockWidget; k9ImportFiles *m_parent; k9LvItemImport *m_selected; QList recorderList; k9CdDrives *drives; k9MenuEdit *m_menuEdit; Ui::import Ui_import; public: k9Import(QWidget* parent = 0, const char* name = 0,k9CdDrives *_drives=0 ); ~k9Import(); /*$PUBLIC_FUNCTIONS$*/ void init(); void execute(); void clear(); void removeTitle(k9LvItemImport *_item); QTreeWidgetItem* getRoot() const; k9NewDVD *getNewDVD() { return m_newDVD; } QTreeWidget *lvDVD; public slots: /*$PUBLIC_SLOTS$*/ void aviFileUpdated(k9AviFile *_aviFile); void buttonUpdated(k9MenuButton *_button, const QImage &_image); void setMenuEdit(k9MenuEdit* _value); void setEnableCreate(bool _state); void updateTotalTime(); void titleAdded(); protected: /*$PROTECTED_FUNCTIONS$*/ void readDrives(); void addDrive (k9CdDrive *_drive); protected slots: /*$PROTECTED_SLOTS$*/ void lvDVDCurrentChanged( QTreeWidgetItem *,QTreeWidgetItem *); void cbFormatActivated(const QString &_format); void showPopup(const QPoint & iPoint); void removeTitle(); void removeChapter(); void addChapter(); virtual void deviceAdded(k9CdDrive *_drive); virtual void deviceRemoved(k9CdDrive *_drive); virtual void volumeChanged(const QString &device,const QString &volumeName); signals: void aviFileSelected(k9AviFile *_aviFile); void titleSelected(k9Title *); void rootSelected(k9NewDVD *); }; #endif k9copy/src/import/k9menu.h0000644000175000017550000000350112412271774016233 0ustar emulatoremulator// // C++ Interface: k9menu // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9MENU_H #define K9MENU_H #include "k9common.h" #include #include #include #include #include "k9menuscene.h" /** @author Jean-Michel PETIT */ class k9MenuButton; class k9Menu : public QObject { Q_OBJECT public slots: void setStartScript(const QString &); void setStartScript2(const QString &); void setEndScript(const QString& _value); public: enum eFormat { PAL=1,NTSC=2 }; k9Menu(QObject *parent = 0, const char *name = 0); ~k9Menu(); k9MenuButton *addButton(); void removeButton(k9MenuButton *_button); bool createMenus(QDomElement *_rootNode); void setWorkDir(const QString& _value); QString getWorkDir() const; void setFormat(const eFormat& _value); void setMenuFileName(const QString& _value); QString getMenuFileName() const; void setScene(k9MenuScene* _value); k9MenuScene* getScene() const; QString getStartScript() const; QString getEndScript() const; QString getStartScript2() const; private: QList m_buttons; QString m_workDir; QString m_menuFileName; eFormat m_format; k9MenuScene *m_scene; QString m_startScript; QString m_startScript2; QString m_endScript; k9Config *m_config; bool m_error; void convertJpegToMpeg(const QString &_imageJpg,const QString &_imageMpg) ; void createAudio(const QString & _audioFile); void multiplex(const QString &_audio, const QString &_video, const QString _result); void spumux(const QString &_hiFileName,const QString &_mpgFileName); void appendMenu(QDomElement *_rootNode); }; #endif k9copy/src/import/k9menubutton.cpp0000644000175000017550000003037112412271774020027 0ustar emulatoremulator// // C++ Implementation: k9menubutton // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "k9menubutton.h" #include #include #include #include #include k9CanvasSprite::k9CanvasSprite (const QPixmap &pixmap, k9MenuScene *scene,k9MenuButton *button) : QGraphicsItemGroup() { m_text=0; m_pixmap=0; scene->addItem(this); m_button=button; setFlag(QGraphicsItem::ItemIsMovable); setFlag(QGraphicsItem::ItemIsSelectable); m_text=new QGraphicsSimpleTextItem(this); m_txtColor=Qt::yellow; m_pixmap=new QGraphicsPixmapItem(pixmap); m_bPixmap=pixmap; this->addToGroup(m_pixmap); this->addToGroup(m_text); // m_text->setPos(this->pos().x(),m_pixmap->boundingRect().bottom()+10); m_textPosition=BOTTOM; m_txtValue=""; m_selsize=10; } void k9CanvasSprite::setTextPosition(const eTextPosition &_position) { QRectF updateRect=sceneBoundingRect(); m_textPosition=_position; m_text->setBrush(QBrush(m_txtColor,Qt::SolidPattern)); m_text->setText(m_txtValue); QFontMetrics m(m_text->font()); int h=m.boundingRect(m_txtValue).height(); int w=m.boundingRect(m_txtValue).width(); switch(_position) { case RIGHT: m_text->setPos(m_pixmap->boundingRect().width(),(m_pixmap->boundingRect().height()-h)/2); break; case BOTTOM: m_text->setPos((m_pixmap->boundingRect().width()-w)/2 ,m_pixmap->boundingRect().height()); break; } update(boundingRect()); scene()->update(updateRect); } QRectF k9CanvasSprite::boundingRect() const { QRectF r; if (m_pixmap){ r=m_pixmap->boundingRect(); r.moveTopLeft(m_pixmap->pos()); } if (m_text) { QRectF r2=m_text->boundingRect(); r2.moveTopLeft(m_text->pos()); #if QT_VERSION >= 0x050000 r=r.united(r2); // Qt5 Code Should also be a drop in for the Qt4 Code aka should work in both, but for now. #else r=r.unite(r2); #endif } r.adjust(-m_selsize,-m_selsize,m_selsize,m_selsize); return r; } void k9CanvasSprite::drawSizeRect (QPainter *painter) { QBrush br; br.setColor(Qt::green); br.setStyle(Qt::SolidPattern); QRectF r=boundingRect(); painter->fillRect(QRectF(r.left(),r.top(),m_selsize,m_selsize),br); painter->fillRect(QRectF(r.left()+r.width()/2 - m_selsize/2,r.top(),m_selsize,m_selsize),br); painter->fillRect(QRectF(r.right() - m_selsize,r.top(),m_selsize,m_selsize),br); painter->fillRect(QRectF(r.left(),r.top()+r.height()/2 -m_selsize/2,m_selsize,m_selsize),br); painter->fillRect(QRectF(r.right()-m_selsize,r.top()+r.height()/2 -m_selsize/2,m_selsize,m_selsize),br); painter->fillRect(QRectF(r.left(),r.bottom()-m_selsize,m_selsize,m_selsize),br); painter->fillRect(QRectF(r.left()+r.width()/2 - m_selsize/2,r.bottom()-m_selsize,m_selsize,m_selsize),br); painter->fillRect(QRectF(r.right() - m_selsize,r.bottom()-m_selsize,m_selsize,m_selsize),br); } void k9CanvasSprite::paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget ) { if (isSelected()) { QPen pen; pen.setStyle(Qt::DashLine); pen.setColor(Qt::red); pen.setWidth(3); painter->setPen(pen); painter->drawRect(boundingRect().adjusted(2,2,-2,-2)); drawSizeRect(painter); } else QGraphicsItemGroup::paint(painter,option,widget); } void k9CanvasSprite::mousePressEvent ( QGraphicsSceneMouseEvent * event ) { m_startPoint=event->scenePos(); QRectF r(boundingRect()); QRectF tl(r.left(),r.top(),m_selsize,m_selsize); QRectF tc(r.left()+r.width()/2 -m_selsize/2,r.top(),m_selsize,m_selsize); QRectF tr(r.right()-m_selsize,r.top(),m_selsize,m_selsize); QRectF ml(r.left(),r.top()+r.height()/2 -m_selsize/2,m_selsize,m_selsize); QRectF mr(r.right()-m_selsize,r.top()+r.height()/2 -m_selsize/2,m_selsize,m_selsize); QRectF bl(r.left(),r.bottom()-m_selsize,m_selsize,m_selsize); QRectF bc(r.left()+r.width()/2 -m_selsize/2,r.bottom()-m_selsize,m_selsize ,m_selsize); QRectF br(r.right()-m_selsize,r.bottom()-m_selsize,m_selsize,m_selsize); QPointF offset=event->scenePos() - event->lastScenePos(); if ( tl.contains(event->pos())) m_resize=STL; else if (tc.contains(event->pos())) m_resize=STC; else if (tr.contains(event->pos())) m_resize=STR; else if (ml.contains(event->pos())) m_resize=SML; else if (mr.contains(event->pos())) m_resize=SMR; else if (bl.contains(event->pos())) m_resize=SBL; else if (bc.contains(event->pos())) m_resize=SBC; else if (br.contains(event->pos())) m_resize=SBR; else { m_resize=SNONE; QGraphicsItemGroup::mousePressEvent(event); } } void k9CanvasSprite::mouseMoveEvent ( QGraphicsSceneMouseEvent * event ) { QRectF oldRect=sceneBoundingRect(); //oldRect.adjust(pos().x(),pos().y(),pos().x(),pos().y()); QPointF offset; QSizeF s(m_pixmap->pixmap().size()); switch(m_resize) { case STL: offset= event->scenePos() - event->lastScenePos(); setPos(pos()+offset); s-=QSize(offset.x(),offset.y()); if (s.width()>0 && s.height()>0) { m_pixmap->setPixmap(m_bPixmap.scaled(s.toSize())); } break; case SBL: offset= event->scenePos() - event->lastScenePos(); setPos(pos().x()+offset.x(),pos().y()); s-=QSize(offset.x(),-offset.y()); if (s.width()>0 && s.height()>0) { m_pixmap->setPixmap(m_bPixmap.scaled(s.toSize())); } break; case STR: offset= event->scenePos() - event->lastScenePos(); setPos(pos().x(),pos().y()+offset.y()); s+=QSize(offset.x(),-offset.y()); if (s.width()>0 && s.height()>0) { m_pixmap->setPixmap(m_bPixmap.scaled(s.toSize())); } break; case SBR: offset= event->scenePos() - event->lastScenePos(); s+=QSize(offset.x(),offset.y()); if (s.width()>0 && s.height()>0) { m_pixmap->setPixmap(m_bPixmap.scaled(s.toSize())); } break; case STC: offset=QPointF(0,event->scenePos().y()-event->lastScenePos().y()); setPos(pos().x(),pos().y()+offset.y()); s-=QSize(offset.x(),offset.y()); if (s.width()>0 && s.height()>0) { m_pixmap->setPixmap(m_bPixmap.scaled(s.toSize())); } break; case SBC: offset=QPointF(0,event->scenePos().y()-event->lastScenePos().y()); s+=QSize(offset.x(),offset.y()); if (s.width()>0 && s.height()>0) { m_pixmap->setPixmap(m_bPixmap.scaled(s.toSize())); } break; case SML: offset=QPointF(event->scenePos().x()-event->lastScenePos().x(),0); setPos(pos().x()+offset.x(),pos().y()); s-=QSize(offset.x(),offset.y()); if (s.width()>0 && s.height()>0) { m_pixmap->setPixmap(m_bPixmap.scaled(s.toSize())); } break; case SMR: offset=QPointF(event->scenePos().x()-event->lastScenePos().x(),0); s+=QSize(offset.x(),offset.y()); m_pixmap->setPixmap(m_bPixmap.scaled(s.toSize())); break; default: break; } if (m_resize != SNONE) { setTextPosition(m_textPosition); update(boundingRect()); scene()->update(oldRect); }else QGraphicsItemGroup::mouseMoveEvent(event); } void k9CanvasSprite::setPixmap(const QPixmap &pixmap) { m_bPixmap=pixmap; m_pixmap->setPixmap(pixmap); setTextPosition(m_textPosition); } void k9CanvasSprite::scalePixmap(int width,int height) { m_pixmap->setPixmap(m_bPixmap.scaled(width,height)); setTextPosition(m_textPosition); } void k9CanvasSprite::setFont(const QFont &font) { m_text->setFont(font); } QFont k9CanvasSprite::getFont() { return m_text->font(); } void k9CanvasSprite::setTextColor(const QColor &color) { m_txtColor=color; setTextPosition(m_textPosition); } QColor k9CanvasSprite::getTextColor() { return m_txtColor; } void k9CanvasSprite::setText(const QString &text) { m_txtValue=text; setTextPosition(m_textPosition); } QString k9CanvasSprite::getText() { return m_txtValue; } k9MenuButton* k9CanvasSprite::getButton() const { return m_button; } void k9MenuButton::update() { int count=m_scene->items().count(); m_sprite->setTextPosition(m_textPosition); m_sprite->setZValue(count--); emit sigsetLeft(getLeft()); emit sigsetTop(getTop()); emit sigsetWidth(getWidth()); emit sigsetHeight(getHeight()); } k9MenuButton::k9MenuButton(k9MenuScene *parent, const char *) : QObject(parent),m_width(0),m_height(0) { m_scene=parent; m_sprite=new k9CanvasSprite(QPixmap(),parent,this); } void k9MenuButton::remove() { if (m_sprite ) delete m_sprite; m_sprite=NULL; } k9MenuButton::~k9MenuButton() { } void k9MenuButton::setImage(const QImage &_image) { m_image=_image; emit sigsetImage(this,_image); loadImage(); } void k9MenuButton::setImage(const QString &_fileName){ m_image.load(_fileName); emit sigsetImage(this,m_image); loadImage(); } void k9MenuButton::loadImage() { QPixmap pix=QPixmap::fromImage(m_image); m_sprite->setPixmap(pix); m_sprite->scalePixmap(m_width,m_height); update(); } void k9MenuButton::setWidth(int _value,bool _reload) { m_width=_value; emit sigsetWidth(_value); if (_reload) loadImage(); } int k9MenuButton::getWidth() { return m_sprite->boundingRect().width(); } void k9MenuButton::setHeight(int _value,bool _reload) { m_height=_value; emit sigsetHeight(_value); if (_reload) loadImage(); } int k9MenuButton::getHeight() { return m_sprite->boundingRect().height(); } void k9MenuButton::setTop(int _value,bool _reload) { m_sprite->setPos(m_sprite->pos().x(), _value); emit sigsetTop(_value); if (_reload) loadImage(); } void k9MenuButton::setLeft(int _value,bool _reload) { m_sprite->setPos(_value,m_sprite->pos().y()); emit sigsetLeft(_value); if (_reload) loadImage(); } int k9MenuButton::getTop() { return m_sprite->boundingRect().top()+m_sprite->pos().y(); } int k9MenuButton::getLeft() { return m_sprite->boundingRect().left()+m_sprite->pos().x(); } void k9MenuButton::setFont(QFont _font) { m_sprite->setFont(_font); update(); emit sigsetFont(_font); } QFont k9MenuButton::getFont() { return m_sprite->getFont(); } void k9MenuButton::setColor(QColor _color) { m_sprite->setTextColor(_color); emit sigsetColor(_color); } QColor k9MenuButton::getColor() { return m_sprite->getTextColor(); } void k9MenuButton::setText(QString _text) { m_sprite->setText(_text); update(); emit sigsetText(_text); } QString k9MenuButton::getText() { return m_sprite->getText(); } void k9MenuButton::select(bool _state) { m_sprite->setSelected(_state); } void k9MenuButton::moveBy(int _x,int _y,bool _reload) { int x=getLeft(); int y=getTop(); m_sprite->moveBy(_x,_y); emit sigsetLeft(x+_x); emit sigsetTop(y+_y); if(_reload) loadImage(); } eTextPosition k9MenuButton::getTextPosition() const { return m_textPosition; } void k9MenuButton::setTextPosition(const eTextPosition& _value) { m_textPosition = _value; update(); emit sigsetTextPosition(_value); } QImage k9MenuButton::getImage() const { return m_image; } QString k9MenuButton::getScript() const { return m_script; } void k9MenuButton::setScript(const QString& _value) { m_script = _value; } int k9MenuButton::getAngle() const { return m_angle; } void k9MenuButton::setAngle(int _value) { m_angle = _value; } k9CanvasSprite* k9MenuButton::getSprite() const { return m_sprite; } int k9MenuButton::getNum() const { return m_num; } void k9MenuButton::setNum(int _value) { m_num = _value; } k9copy/src/import/CMakeFiles/0000775000175000017550000000000012412271774016620 5ustar emulatoremulatork9copy/src/import/CMakeFiles/progress.marks0000664000175000017550000000000212412271774021513 0ustar emulatoremulator0 k9copy/src/import/CMakeFiles/CMakeDirectoryInformation.cmake0000664000175000017550000000124312412271774024675 0ustar emulatoremulator# CMAKE generated file: DO NOT EDIT! # Generated by "Unix Makefiles" Generator, CMake Version 2.8 # Relative path conversion top directories. SET(CMAKE_RELATIVE_PATH_TOP_SOURCE "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4") SET(CMAKE_RELATIVE_PATH_TOP_BINARY "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4") # Force unix paths in dependencies. SET(CMAKE_FORCE_UNIX_PATHS 1) # The C and CXX include file regular expressions for this directory. SET(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") SET(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") SET(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) SET(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) k9copy/src/import/k9lvitemimport.h0000644000175000017550000000213412412271774020023 0ustar emulatoremulator// // C++ Interface: k9lvitemimport // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9LVITEMIMPORT_H #define K9LVITEMIMPORT_H #include "k9common.h" #include #include #include "k9avifile.h" #include "k9title.h" /** @author Jean-Michel PETIT */ class k9LvItemImport: public QTreeWidgetItem { public: enum eObjectType {ROOT=1000,TITLE=1001,CHAPTER=1002}; k9LvItemImport( QTreeWidgetItem *parent,eObjectType _objectType); ~k9LvItemImport(); eObjectType getObjectType() { return m_objectType;}; void setAviFile ( k9AviFile* _value ){m_aviFile = _value;} k9AviFile* getAviFile() const { return m_aviFile;} void setTitle(k9Title* _value); k9Title* getTitle() const { return m_title;} // virtual int compare (QListViewItem *i,int col,bool ascending) const; bool operator< ( const QTreeWidgetItem & other ) const ; private: eObjectType m_objectType; k9AviFile *m_aviFile; k9Title *m_title; }; #endif k9copy/src/import/k9newtitle.h0000644000175000017550000000242012412271774017121 0ustar emulatoremulator// // C++ Interface: // // Description: // Developer: Pauline123 , (C) 2014 // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9NEWTITLE_H #define K9NEWTITLE_H #include "k9common.h" #include "ui_newTitle.h" #include "k9lvitemimport.h" #include #include #if QT_VERSION >= 0x050000 //Qt5 Code #include #else //Qt4 Code #endif class k9Import; class k9NewTitle : public QWidget { Q_OBJECT private: k9Import *m_k9Import; QString m_fileName; QImage m_image; Ui::newTitle Ui_newTitle; bool isMpeg2(const QString &_fileName); public: k9NewTitle(QWidget* parent = 0 ); ~k9NewTitle(); void setK9Import ( k9Import* _value ); /*$PUBLIC_FUNCTIONS$*/ public slots: /*$PUBLIC_SLOTS$*/ protected: /*$PROTECTED_FUNCTIONS$*/ protected slots: /*$PROTECTED_SLOTS$*/ #if QT_VERSION >= 0x050000 virtual void urlSelected(const QUrl &); #else virtual void urlSelected(const KUrl &); #endif virtual void bAddClicked(); virtual void rbNumberClicked(); virtual void rbLengthClicked(); virtual void drawImage (QImage _image); virtual void ckReencodeClicked(); }; #endif k9copy/src/import/k9lvitemimport.cpp0000644000175000017550000000220112412271774020351 0ustar emulatoremulator// // C++ Implementation: k9lvitemimport // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "k9lvitemimport.h" //1001 =TITLE //1002 = CHAPTER //1000 = autre k9LvItemImport::k9LvItemImport( QTreeWidgetItem *parent,eObjectType _objectType) : QTreeWidgetItem( parent,_objectType) { m_objectType=_objectType; m_title=NULL; m_aviFile=NULL; } bool k9LvItemImport::operator< ( const QTreeWidgetItem & other ) const { // int col=treeWidget()->sortColumn(); if (other.type()== TITLE) { k9LvItemImport *item2=(k9LvItemImport*)&other; return this->getTitle()->getNum() < item2->getTitle()->getNum(); } if (other.type()== CHAPTER) { k9LvItemImport *item2=(k9LvItemImport*)&other; return this->getAviFile()->getNum() < item2->getAviFile()->getNum() ; } return false; } void k9LvItemImport::setTitle(k9Title* _value) { m_title = _value; QPixmap pix=QPixmap::fromImage(m_title->getButton()->getImage()); setIcon(0,QIcon(pix)); } k9LvItemImport::~k9LvItemImport() { } k9copy/src/import/k9menuedit.h0000644000175000017550000000545112412271774017107 0ustar emulatoremulator// // C++ Interface: // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9MENUEDIT_H #define K9MENUEDIT_H #include "k9common.h" #include "ui_menuEdit.h" #include #include "k9menuscene.h" #include #include #if QT_VERSION >= 0x050000 //Qt 5 Code #include #else //Qt4 Code #endif class k9MenuButton; class k9MenuEdit; class k9Title; class k9NewDVD; class k9GraphicsView:public QGraphicsView{ Q_OBJECT public: k9GraphicsView(QWidget *parent):QGraphicsView(parent){} protected: void drawBackground ( QPainter * painter, const QRectF & rect ); void resizeEvent ( QResizeEvent * event ) ; }; class k9MenuEdit : public QWidget { Q_OBJECT private: Ui::menuEdit Ui_menuEdit; public: enum eFormat {PAL=1,NTSC=2}; enum eMenuType {ROOTMENU,TITLEMENU}; k9MenuEdit(QWidget* parent = 0, const char* name = 0,k9MenuScene *scene=0); ~k9MenuEdit(); /*$PUBLIC_FUNCTIONS$*/ void setBackgroundImage(const QImage &_image); /* void setText(const QString &_value); void setFont(const QFont &_value); void setColor(const QColor &_value); void updateTextPos(const QPoint &_point); */ public slots: /*$PUBLIC_SLOTS$*/ //QGraphicsSimpleTextItem* getText() const; void setFormat(const eFormat& _value); k9MenuEdit::eFormat getFormat() const; k9MenuScene *getScene(); void setScene(k9MenuScene* _value); void titleSelected(k9Title *); void rootSelected(k9NewDVD *); void selectionChanged(); protected: /*$PROTECTED_FUNCTIONS$*/ k9GraphicsView *m_graphicsView; k9MenuScene *m_scene; QImage m_background; QGraphicsSimpleTextItem *m_text; eFormat m_format; int m_imageHeight; eMenuType m_menuType; QStringList m_startScripts; QStringList m_endScripts; bool m_noUpdate; protected slots: /*$PROTECTED_SLOTS$*/ virtual void bFontClick(); #if QT_VERSION >= 0x050000 virtual void urBackgroundSelected(const QUrl &_url); #else virtual void urBackgroundSelected(const KUrl &_url); #endif virtual void cbColorChanged(const QColor &_color); virtual void leTitleChanged(const QString &_value); virtual void cbPosTitleActivated(int _value); virtual void bAddTextClick(); virtual void cbStartActivated (int _value); virtual void cbEndActivated (int _value); signals: void backgroundImageChanged(const QImage &); void textChanged(const QString&); void startScriptChanged(const QString&); void endScriptChanged(const QString&); void textColorChanged(const QColor &); void textFontChanged(const QFont&); void updatePos(const QPoint &); }; #endif k9copy/src/import/k9importfiles.h0000644000175000017550000000436012412271774017630 0ustar emulatoremulator// // C++ Interface: k9copy // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef _K9IMPORTFILES_H_ #define _K9IMPORTFILES_H_ #include #include #include "k9common.h" #include "k9cddrive.h" #include "k9copy.h" #include #if QT_VERSION >= 0x050000 #include #include #else #include #include #endif #include class k9Import; class k9MenuEdit; class k9NewTitle; class k9ChapterEdit; class QDockWidget; class k9ImportFiles : public KXmlGuiWindow { Q_OBJECT public: /** * Default Constructor */ k9ImportFiles(k9Copy *_parent); void clone(QString _input,QString _output); void setInput(QString _input); void setOutput(QString _output); /** * Default Destructor */ virtual ~k9ImportFiles(); protected: bool queryClose( ); void closeEvent( QCloseEvent* ce ); private slots: void ActionCreate(); void ActionBackup(); void changeStatusbar(const QString& text,int id); void changeCaption(const QString& text); void optionsConfigureKeys(); void optionsConfigureToolbars(); void newToolbarConfig(); public slots: void preferences(); void quit(); void setActions(bool enabled); void setEnabledCreateDVD(bool _state); QDockWidget* firstBottom() const {return m_firstBottom;} private: void setupAccel(); void setupActions(); void createWindows(); void removeToolWindows(); #if QT_VERSION >= 0x050000 QAction *CopyAction; QAction *PlayTitleAction; QAction *mkMP4Action; QAction *ejectAction; QAction *backupAction; #else KAction *CopyAction; KAction *PlayTitleAction; KAction *mkMP4Action; KAction *ejectAction; KAction *backupAction; #endif QDockWidget *m_firstBottom; k9Copy *m_parent; private: k9MenuEdit *m_menuEdit; k9NewTitle *m_newTitle; k9ChapterEdit *m_chapterEdit; k9Import *m_k9Import; QMap m_actions; //QPtrList m_ToolViews; k9CdDrives *m_drives; }; #endif k9copy/src/import/k9processlist.cpp0000644000175000017550000001235212412271774020200 0ustar emulatoremulator// // C++ Implementation: // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "k9processlist.h" #include #include #include #include #include #include #include #include #include #if QT_VERSION >= 0x050000 #include #include #include #else #include #endif class _k9ProcessListItem : public QTreeWidgetItem { public: QProgressBar *progress; _k9ProcessListItem(QTreeWidget *_listview,const QString & _text):QTreeWidgetItem(_listview) { m_fileName=""; m_pos=0; m_num=_listview->invisibleRootItem()->childCount(); setText(1,_text); progress=new QProgressBar(); progress->setValue(100); progress->setMaximum(100); progress->resize(100,40); treeWidget()->setItemWidget ( this, 0, progress); _listview->resizeColumnToContents(1); } void setFileName(const QString &_fileName) { m_fileName=_fileName; } void setPos(double _pos) { m_pos=_pos; } QString getFileName() const { return m_fileName; } double getPos() const { return m_pos; } bool operator< ( const QTreeWidgetItem & other ) const { return m_num <((_k9ProcessListItem*)&other)->m_num; } private: QString m_fileName; double m_pos; int m_num; }; k9ProcessList::k9ProcessList(QWidget* parent) : QDialog(parent) { Ui_processList.setupUi(this); m_maxProcess=4; connect(&m_timer,SIGNAL(timeout()),this,SLOT(timeout())); Ui_processList.bCancel->setEnabled(false); #if QT_VERSION >=0x050000 KGuiItem::assign(Ui_processList.bCancel, KStandardGuiItem::stop() ); #else Ui_processList.bCancel->setGuiItem(KStandardGuiItem::Stop); #endif } k9ProcessList::~k9ProcessList() { qDeleteAll(m_processes); } /*$SPECIALIZATION$*/ void k9ProcessList::timeout() { if (m_waitSync) { m_eventLoop.exit(); m_waitSync=false; } } void k9ProcessList::bCancelClick() { m_cancel=true; foreach (k9Process *p,m_processes) { if (p->isRunning()) p->kill(); } } void k9ProcessList::wait(int _msec) { m_waitSync=true; m_timer.start(_msec); m_eventLoop.exec(); } int k9ProcessList::getNbRunning() { int res=0; for (int i=0;iisRunning()) res++; } return res; } void k9ProcessList::execute() { Ui_processList.bCancel->setEnabled(true); m_cancel=false; m_error=false; k9Process *p=NULL; foreach (p,m_processes) { while (getNbRunning() >=m_maxProcess && ! m_cancel) { wait(1000); } if (m_cancel) break; if (!p->start()) m_error=true; } //waiting for processes foreach (k9Process *p,m_processes) { if (p->isRunning()) { p->sync(); } } Ui_processList.bCancel->setEnabled(false); } void k9ProcessList::addProgress(const QString &_text) { QTreeWidgetItem *item = new _k9ProcessListItem(Ui_processList.lProcess,_text); // item->setPixmap(0,QPixmap::grabWidget(&b,0,0,b.width(),b.height())); } void k9ProcessList::setProgress (k9Process * _process,int _position, int _total) { _k9ProcessListItem *it =(_k9ProcessListItem*)m_items[_process]; it->progress->setValue(_position); // it->setPixmap(0,QPixmap::grabWidget(&b,0,0,b.width(),b.height())); } void k9ProcessList::setText(k9Process *_process, const QString &_text,int _col) { QTreeWidgetItem *it =m_items[_process]; it->setText(_col+1,_text); Ui_processList.lProcess->resizeColumnToContents(_col+1); } void k9ProcessList::setFileName(k9Process *_process,const QString &_fileName) { _k9ProcessListItem *it = (_k9ProcessListItem*)m_items[_process]; it->setFileName(_fileName); } void k9ProcessList::setPos(k9Process *_process,double _pos) { _k9ProcessListItem *it = (_k9ProcessListItem*)m_items[_process]; it->setPos(_pos); } k9Process *k9ProcessList::addProcess(const QString &label) { QString name=QString("process%1").arg(m_items.count()) ; k9Process *process=new k9Process(this,name.toUtf8()); m_processes.append(process); QTreeWidgetItem *item = new _k9ProcessListItem(Ui_processList.lProcess,label); m_items[process]=item; setProgress(process,0,100); connect(process,SIGNAL(processExited( k9Process* )),this,SLOT(processExited(k9Process*))); return process; } void k9ProcessList::processExited(k9Process *_process) { if (!_process->normalExit()) m_cancel=true; else if (_process->exitStatus() !=0 ) m_error=true; } void k9ProcessList::clear() { m_processes.clear(); m_items.clear(); } int k9ProcessList::getMaxProcess() const { return m_maxProcess; } void k9ProcessList::setMaxProcess(int _value) { m_maxProcess = _value; } bool k9ProcessList::getCancel() const { return m_cancel; } bool k9ProcessList::getError() const { return m_error; } k9copy/src/import/k9title.h0000644000175000017550000000163512412271774016416 0ustar emulatoremulator// // C++ Interface: k9title // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9TITLE_H #define K9TITLE_H #include "k9common.h" #include #include "k9avifile.h" #include "k9menubutton.h" /** @author Jean-Michel PETIT */ class k9NewDVD; class k9Menu; class k9TitleItems : public QList { public: static bool compareItems(k9AviFile *item1,k9AviFile *item2); }; class k9Title : public QObject { Q_OBJECT public: k9Title(k9NewDVD *parent = 0, const char *name = 0); ~k9Title(); k9TitleItems *getFiles(); int getNum() const; void setButton(k9MenuButton* _value); k9MenuButton* getButton() const; k9Menu* getMenu() const; private: k9TitleItems m_files; int m_num; k9MenuButton *m_button; k9Menu *m_menu; }; #endif k9copy/src/import/chapterEdit.ui0000644000175000017550000003002012417731553017442 0ustar emulatoremulator chapterEdit 0 0 627 300 0 0 Chapter properties 255 255 255 0 0 0 255 255 255 0 0 0 0 0 0 0 0 0 true true false Qt::Horizontal 0 0 --:--:-- false video false 0 0 200 0 *.avi *.mpeg *.mpg *.* start false 0 0 HH:mm:ss 0 0 set Current Frame Qt::Horizontal QSizePolicy::Expanding 16 20 break continuity Qt::Vertical QSizePolicy::Fixed 20 31 end false 0 0 HH:mm:ss 0 0 set Current Frame break continuity Qt::Vertical QSizePolicy::Expanding 21 60 0 0 set Title button KPushButton KPushButton
kpushbutton.h
KUrlRequester QFrame
kurlrequester.h
kurlrequester.h kpushbutton.h kpushbutton.h urFile urlSelected(const KUrl&) chapterEdit urlSelected(const KUrl&) 20 20 20 20 slider sliderReleased() chapterEdit sliderReleased() 20 20 20 20 slider valueChanged(int) chapterEdit sliderChanged(int) 20 20 20 20 bStart clicked() chapterEdit bStartClick() 20 20 20 20 bEnd clicked() chapterEdit bEndClick() 20 20 20 20 twstart timeChanged(QTime) chapterEdit startChanged(QTime) 20 20 20 20 twend timeChanged(QTime) chapterEdit endChanged(QTime) 20 20 20 20 ckBreakEnd clicked() chapterEdit ckBreakEndClick() 20 20 20 20 ckBreakStart clicked() chapterEdit ckBreakStartClick() 20 20 20 20 bTitleButton clicked() chapterEdit bTitleButtonClick() 20 20 20 20
k9copy/src/import/CMakeLists.txt0000644000175000017550000000000012412271774017401 0ustar emulatoremulatork9copy/src/import/k9chapteredit.h0000644000175000017550000000265512412271774017574 0ustar emulatoremulator// // C++ Interface: // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9CHAPTEREDIT_H #define K9CHAPTEREDIT_H #include "k9common.h" #include "ui_chapterEdit.h" #include "k9avidecode.h" #include "k9avifile.h" #include #if QT_VERSION >= 0x050000 //Qt 5 Code #include #else //Qt4 Code #endif class k9DrawImage; class k9ChapterEdit : public QWidget { Q_OBJECT public: k9ChapterEdit(QWidget* parent = 0); ~k9ChapterEdit(); /*$PUBLIC_FUNCTIONS$*/ public slots: /*$PUBLIC_SLOTS$*/ private: k9AviDecode *m_aviDecode; k9DrawImage *m_wimage; k9AviFile *m_aviFile; QTime m_minTime,m_maxTime; bool m_noUpdate; QImage m_image; Ui::chapterEdit Ui_chapterEdit; protected slots: /*$PROTECTED_FUNCTIONS$*/ virtual void sliderReleased(); virtual void sliderChanged(int _value); virtual void bStartClick(); virtual void bEndClick(); virtual void ckBreakStartClick(); virtual void ckBreakEndClick(); #if QT_VERSION >= 0x050000 virtual void urlSelected(const QUrl&); #else virtual void urlSelected(const KUrl&); #endif virtual void startChanged(const QTime&); virtual void endChanged(const QTime&); virtual void bTitleButtonClick(); void drawImage(QImage); public slots: void setAviFile(k9AviFile *_aviFile); }; #endif k9copy/src/import/k9avifile.cpp0000644000175000017550000000652312412271774017250 0ustar emulatoremulator// // C++ Implementation: k9avifile // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "k9common.h" #include "k9avifile.h" #include "k9title.h" k9AviFile::k9AviFile(k9Title *parent, const char *) : QObject(parent) { m_num=parent->getFiles()->count(); setTitle(parent); m_previous=NULL; m_next=NULL; m_breakNext=false; m_breakPrevious=false; m_reencode=true; } k9AviFile::~k9AviFile() { } QString k9AviFile::getFileName() const { return m_fileName; } void k9AviFile::setFileName ( const QString& _value ) { if (m_fileName!="") { m_breakNext=true; m_breakPrevious=true; if (m_next) m_next->setBreakPrevious(true); if (m_previous) m_previous->setBreakNext(true); } m_fileName = _value; emit aviFileUpdated (this); } QTime k9AviFile::getStart() const { return m_start; } void k9AviFile::setStart ( const QTime& _value ) { m_start = _value; emit aviFileUpdated (this); } QTime k9AviFile::getEnd() const { return m_end; } void k9AviFile::setEnd ( const QTime& _value ) { m_end = _value; emit aviFileUpdated (this); } QString k9AviFile::getLabel() const { return m_label; } void k9AviFile::setLabel ( const QString& _value ) { m_label = _value; emit aviFileUpdated (this); } k9Title* k9AviFile::getTitle() const { return m_title; } void k9AviFile::setTitle ( k9Title* _value ) { m_title = _value; m_title->getFiles()->append(this); qSort(m_title->getFiles()->begin(),m_title->getFiles()->end(),k9TitleItems::compareItems); // m_title->getFiles()->sort(); } int k9AviFile::getNum() const { return m_num; } k9AviFile* k9AviFile::getPrevious() const { return m_previous; } void k9AviFile::setPrevious ( k9AviFile* _value ) { m_previous = _value; m_breakPrevious=false; } k9AviFile* k9AviFile::getNext() const { return m_next; } void k9AviFile::setNext ( k9AviFile* _value ) { m_next = _value; m_breakPrevious=false; } void k9AviFile::setBreakPrevious(bool _state) { m_breakPrevious=_state; if ( ! _state) { if (m_previous !=NULL) { m_previous->setEnd(this->getStart()); m_previous->m_breakNext=false; } } else { if (m_previous!=NULL) { m_previous ->m_breakNext=true; } } } bool k9AviFile::getBreakPrevious() { return m_breakPrevious; } void k9AviFile::setBreakNext(bool _state) { m_breakNext=_state; if ( ! _state) { if (m_next !=NULL) { m_next->setStart(this->getEnd()); m_next->m_breakPrevious=false; } } else { if (m_next!=NULL) { m_next ->m_breakPrevious=true; } } } bool k9AviFile::getBreakNext() { return m_breakNext; } QImage k9AviFile::getImage() const { return m_image; } void k9AviFile::setImage(const QImage& _value) { m_image = _value; emit aviFileUpdated (this); emit imageChanged(_value); } k9MenuButton* k9AviFile::getButton() const { return m_button; } void k9AviFile::setButton(k9MenuButton* theValue) { m_button = theValue; } bool k9AviFile::getReencode() const { return m_reencode; } void k9AviFile::setReencode(bool theValue) { m_reencode = theValue; } k9copy/src/import/k9avidecode.cpp0000644000175000017550000003053612412271774017555 0ustar emulatoremulator// // C++ Implementation: k9avidecode // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "k9avidecode.h" #include #include #include #include "k9common.h" #ifdef HAVE_SWSCALE #include "swscale.h" static int sws_flags = SWS_BICUBIC; #endif void av_free_packet_internal(AVPacket *pkt) { if (pkt) { if (pkt->destruct) pkt->destruct(pkt); pkt->data = NULL; pkt->size = 0; } } k9AviDecode::k9AviDecode(QObject *parent, const char *) : QObject(parent) { CodecHandle=0; FormatHandle=0; UtilHandle=0; SwscaleHandle=0; glibref=0; if (glibref==0) { CodecHandle=dlopen("libavcodec.so",RTLD_LAZY ); //| RTLD_GLOBAL FormatHandle=dlopen("libavformat.so",RTLD_LAZY); UtilHandle=dlopen("libavutil.so",RTLD_LAZY); #ifdef HAVE_SWSCALE SwscaleHandle=dlopen("libswscale.so",RTLD_LAZY); if (SwscaleHandle==0) SwscaleHandle=dlopen("libswscale.so.2",RTLD_LAZY); #endif } m_error=""; QStringList errs; if (!CodecHandle) { errs << i18n("Cannot open the library %1").arg("libavcodec"); } if (!FormatHandle ) { errs << i18n("Cannot open the library %1").arg("libavformat"); } # if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51, 33, 0) if (!UtilHandle) { m_error =i18n("Cannot open then library %1").arg("libavutil"); return; } # endif #ifdef HAVE_SWSCALE if (!SwscaleHandle) { errs << i18n("Cannot open the library %1").arg("libswscale"); } #endif av_register_all = (av_register_all_t)dlsym(FormatHandle,"av_register_all"); # if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 2, 0) avformat_open_input = (avformat_open_input_t)dlsym(FormatHandle,"avformat_open_input"); # else av_open_input_file = (av_open_input_file_t)dlsym(FormatHandle,"av_open_input_file"); # endif # if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 6, 0) avformat_find_stream_info = (avformat_find_stream_info_t)dlsym(FormatHandle,"avformat_find_stream_info"); # else av_find_stream_info = (av_find_stream_info_t)dlsym(FormatHandle,"av_find_stream_info"); # endif avcodec_find_decoder =(avcodec_find_decoder_t) dlsym(CodecHandle,"avcodec_find_decoder"); # if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 8, 0) avcodec_open2 = (avcodec_open2_t)dlsym(CodecHandle,"avcodec_open2"); # else avcodec_open = (avcodec_open_t)dlsym(CodecHandle,"avcodec_open"); # endif avcodec_alloc_frame = (avcodec_alloc_frame_t)dlsym(CodecHandle,"avcodec_alloc_frame"); avpicture_get_size = (avpicture_get_size_t)dlsym(CodecHandle,"avpicture_get_size"); av_malloc = (av_malloc_t)dlsym(CodecHandle,"av_malloc"); avpicture_fill = (avpicture_fill_t)dlsym(CodecHandle,"avpicture_fill"); av_read_frame = (av_read_frame_t)dlsym(FormatHandle,"av_read_frame"); # if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 23, 0) avcodec_decode_video2 = (avcodec_decode_video2_t)dlsym(CodecHandle,"avcodec_decode_video2"); # else avcodec_decode_video = (avcodec_decode_video_t)dlsym(CodecHandle,"avcodec_decode_video"); # endif #ifndef HAVE_SWSCALE img_convert = (img_convert_t)dlsym(CodecHandle,"img_convert"); //if img_convert is null (deprecated in ffmpeg), we need libswscale if (!img_convert) errs << i18n("Cannot open the library %1").arg("libswscale"); #endif av_free = (av_free_t)dlsym(CodecHandle,"av_free"); av_free_packet = (av_free_packet_t)dlsym(CodecHandle,"av_free_packet"); if (av_free_packet==0) av_free_packet=av_free_packet_internal; avcodec_close = (avcodec_close_t)dlsym(FormatHandle,"avcodec_close"); # if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 17, 0) avformat_close_input = (avformat_close_input_t)dlsym(FormatHandle,"avformat_close_input"); # else av_close_input_file = (av_close_input_file_t)dlsym(FormatHandle,"av_close_input_file"); # endif av_seek_frame=(av_seek_frame_t)dlsym(FormatHandle,"av_seek_frame"); av_rescale_q=(av_rescale_q_t)dlsym(FormatHandle,"av_rescale_q"); avcodec_flush_buffers=(avcodec_flush_buffers_t)dlsym(CodecHandle,"avcodec_flush_buffers"); #ifdef HAVE_SWSCALE sws_freeContext= (sws_freeContext_t)dlsym(SwscaleHandle,"sws_freeContext"); sws_getContext=(sws_getContext_t)dlsym(SwscaleHandle,"sws_getContext"); sws_scale= (sws_scale_t)dlsym(SwscaleHandle,"sws_scale"); #endif # if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51, 33, 0) av_gettime=(av_gettime_t)dlsym(UtilHandle,"av_gettime"); # else av_gettime=(av_gettime_t)dlsym(FormatHandle,"av_gettime"); # endif if (errs.count() >0) { m_error=errs.join("\n"); k9Dialogs::error(m_error,"k9copy",QStringList()); return; } av_register_all(); m_opened=false; glibref++; } k9AviDecode::~k9AviDecode() { if (m_opened) close(); glibref--; if (glibref==0) { if (FormatHandle) dlclose(FormatHandle); if (CodecHandle) dlclose(CodecHandle); if(UtilHandle) dlclose(UtilHandle); #ifdef HAVE_SWSCALE if (SwscaleHandle) dlclose(CodecHandle); #endif FormatHandle=0; CodecHandle=0; } } bool k9AviDecode::open(const QString & _fileName) { m_error=""; if (m_opened) close(); // Open video file if ( # if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 2, 0) avformat_open_input(&m_FormatCtx, _fileName.toUtf8(), 0, 0)!=0 # else av_open_input_file(&m_FormatCtx, _fileName.toUtf8(), NULL, 0, NULL)!=0 # endif ) { m_error=i18n("Couldn't open the file %1").arg(_fileName); return false; // Couldn't open file} } // Retrieve stream information if ( # if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 6, 0) avformat_find_stream_info(m_FormatCtx, NULL)<0 # else av_find_stream_info(m_FormatCtx)<0 # endif ) { m_error =i18n("Couldn't find stream information"); return false; // Couldn't find stream information } uint i; // Find the first video stream m_videoStream=-1; for (i=0; inb_streams; i++) if (m_FormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) { m_videoStream=i; break; } if (m_videoStream==-1) { m_error=i18n("The file doesn't contain any video stream"); return false; // Didn't find a video stream } // Get a pointer to the codec context for the video stream m_CodecCtx=m_FormatCtx->streams[m_videoStream]->codec; // Find the decoder for the video stream m_Codec=avcodec_find_decoder(m_CodecCtx->codec_id); if (m_Codec==NULL) { m_error=i18n("Unsupported codec"); return false; // Codec not found } // Open codec if ( # if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 8, 0) avcodec_open2(m_CodecCtx, m_Codec, NULL)<0 # else avcodec_open(m_CodecCtx, m_Codec)<0 # endif ) { m_error =i18n("Could'nt open the codec"); return false; // Could not open codec } // Allocate video frame m_Frame=avcodec_alloc_frame(); // Allocate an AVFrame structure m_FrameRGB=avcodec_alloc_frame(); if (m_FrameRGB==NULL) { m_error =i18n ("Unable to allocate memory for frames"); return false; } int numBytes; // Determine required buffer size and allocate buffer numBytes=avpicture_get_size(PIX_FMT_RGB24, m_CodecCtx->width, m_CodecCtx->height); m_buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t)); // Assign appropriate parts of buffer to image planes in pFrameRGB // Note that pFrameRGB is an AVFrame, but AVFrame is a superset // of AVPicture avpicture_fill((AVPicture *)m_FrameRGB, m_buffer, PIX_FMT_RGB24, m_CodecCtx->width, m_CodecCtx->height); m_duration=(double)(calcDuration() + m_FormatCtx->start_time) / AV_TIME_BASE; m_opened=true; m_fileName=_fileName; return true; } int64_t k9AviDecode::calcDuration() { if (m_FormatCtx->duration >0) return m_FormatCtx->duration; else { int64_t duration=0; AVPacket packet; av_seek_frame(m_FormatCtx, m_videoStream, 0, AVSEEK_FLAG_BACKWARD ); while (av_read_frame(m_FormatCtx, &packet)>=0) { duration += packet.duration; av_free_packet(&packet); } return duration; } } void k9AviDecode::seek(double _seconds) { AVRational time_base = m_FormatCtx->streams[m_videoStream]->time_base; int64_t fspos = (int64_t)(_seconds * AV_TIME_BASE); fspos=av_rescale_q(fspos, AV_TIME_BASE_Q, time_base); int i=av_seek_frame(m_FormatCtx, m_videoStream, fspos, AVSEEK_FLAG_BACKWARD ); // double pos=av_gettime() / 1000000; } void k9AviDecode::readFrame(double _seconds) { AVRational time_base = m_FormatCtx->streams[m_videoStream]->time_base; int64_t fspos = (int64_t)(_seconds * AV_TIME_BASE); fspos=av_rescale_q(fspos, AV_TIME_BASE_Q, time_base); int res=av_seek_frame(m_FormatCtx, m_videoStream, fspos, AVSEEK_FLAG_BACKWARD ); avcodec_flush_buffers(m_CodecCtx); int frameFinished=0; AVPacket packet; #ifdef HAVE_SWSCALE struct SwsContext *toRGB_convert_ctx; #endif bool bFound=false; while (av_read_frame(m_FormatCtx, &packet)>=0 && !bFound) { // Is this a packet from the video stream? if (packet.stream_index==m_videoStream) { // Decode video frame # if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 23, 0) avcodec_decode_video2(m_CodecCtx, m_Frame, &frameFinished, &packet); # else avcodec_decode_video(m_CodecCtx, m_Frame, &frameFinished, packet.data, packet.size); # endif // Did we get a video frame? if (frameFinished) { // if (m_Frame->pts >=fspos) int64_t cur_dts=fspos; # if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(54, 2, 0) cur_dts= packet.dts; # else if (m_FormatCtx->cur_st) cur_dts= m_FormatCtx->cur_st->cur_dts; # endif if (cur_dts >=fspos) { bFound=true; #ifndef HAVE_SWSCALE // Convert the image from its native format to RGB img_convert((AVPicture *)m_FrameRGB, PIX_FMT_RGB24, (AVPicture*)m_Frame, m_CodecCtx->pix_fmt, m_CodecCtx->width, m_CodecCtx->height); SaveFrame(m_FrameRGB, m_CodecCtx->width, m_CodecCtx->height); #else toRGB_convert_ctx=sws_getContext(m_CodecCtx->width, m_CodecCtx->height, m_CodecCtx->pix_fmt, m_CodecCtx->width, m_CodecCtx->height, PIX_FMT_RGB24, sws_flags,NULL,NULL,NULL); sws_scale(toRGB_convert_ctx, m_Frame->data, m_Frame->linesize, 0, m_CodecCtx->height, m_FrameRGB->data,m_FrameRGB->linesize); // convert frame to QImage SaveFrame(m_FrameRGB, m_CodecCtx->width, m_CodecCtx->height); sws_freeContext(toRGB_convert_ctx); #endif } } } // Free the packet that was allocated by av_read_frame av_free_packet(&packet); } } void k9AviDecode::SaveFrame(AVFrame *pFrame, int width, int height) { QImage pix; int len =(int) (3*width*height); char c[255]; // Write header sprintf(c,"P6\n%d %d\n255\n", width, height); char *s= new char[len+strlen(c)]; memcpy(s,c,strlen(c)); memcpy(s+strlen(c),pFrame->data[0], len); pix.loadFromData((uchar*)s,strlen(c)+len); delete[] s; emit drawFrame( pix); } void k9AviDecode::close() { if (m_opened) { // Free the RGB image av_free(m_buffer); av_free(m_FrameRGB); // Free the YUV frame av_free(m_Frame); // Close the codec avcodec_close(m_CodecCtx); // Close the video file # if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 17, 0) avformat_close_input(&m_FormatCtx); # else av_close_input_file(m_FormatCtx); # endif m_opened=false; } } double k9AviDecode::getDuration() const { return m_duration; } bool k9AviDecode::opened() const { return m_opened; } QString k9AviDecode::getFileName() const { return m_fileName; } QString k9AviDecode::getError() const { return m_error; } k9copy/src/import/k9title.cpp0000644000175000017550000000200412412271774016740 0ustar emulatoremulator// // C++ Implementation: k9title // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "k9title.h" #include "k9newdvd.h" #include "k9menu.h" k9Title::k9Title(k9NewDVD *parent, const char *) : QObject(parent) { m_num=parent->getTitles()->count(); parent->appendTitle(this); m_menu=new k9Menu(this,0); m_menu->setFormat((k9Menu::eFormat)parent->getFormat()); } k9Title::~k9Title() { k9NewDVD *p=(k9NewDVD*)parent(); // p->getRootMenu()->removeButton(m_button); } bool k9TitleItems::compareItems(k9AviFile *item1,k9AviFile *item2) { return (item1->getNum() < item2->getNum()); } k9TitleItems *k9Title::getFiles() { return &m_files; } int k9Title::getNum() const { return m_num; } k9MenuButton* k9Title::getButton() const { return m_button; } void k9Title::setButton(k9MenuButton* _value) { m_button = _value; } k9Menu* k9Title::getMenu() const { return m_menu; } k9copy/src/import/cmake_install.cmake0000664000175000017550000000225712412271774020473 0ustar emulatoremulator# Install script for directory: /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/src/import # Set the install prefix IF(NOT DEFINED CMAKE_INSTALL_PREFIX) SET(CMAKE_INSTALL_PREFIX "/usr/local") ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") # Set the install configuration name. IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) IF(BUILD_TYPE) STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") ELSE(BUILD_TYPE) SET(CMAKE_INSTALL_CONFIG_NAME "RelWithDebInfo") ENDIF(BUILD_TYPE) MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) # Set the component getting installed. IF(NOT CMAKE_INSTALL_COMPONENT) IF(COMPONENT) MESSAGE(STATUS "Install component: \"${COMPONENT}\"") SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") ELSE(COMPONENT) SET(CMAKE_INSTALL_COMPONENT) ENDIF(COMPONENT) ENDIF(NOT CMAKE_INSTALL_COMPONENT) # Install shared libraries without execute permission? IF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) SET(CMAKE_INSTALL_SO_NO_EXE "0") ENDIF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) k9copy/src/import/k9processlist.h0000644000175000017550000000300212412271774017635 0ustar emulatoremulator// // C++ Interface: // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9PROCESSLIST_H #define K9PROCESSLIST_H #include "k9common.h" #include "ui_processList.h" #include #include #include class k9ProcessList : public QDialog { Q_OBJECT public: k9ProcessList(QWidget* parent = 0); ~k9ProcessList(); /*$PUBLIC_FUNCTIONS$*/ void execute(); void addProgress(const QString &_text); void setProgress (k9Process * _process,int _position, int _total); void setText(k9Process *_process, const QString &_text,int _col); void setFileName(k9Process *_process,const QString &_fileName); void setPos(k9Process *_process,double _pos); k9Process *addProcess(const QString &label); void setMaxProcess(int _value); int getMaxProcess() const; bool getCancel() const; void clear(); bool getError() const; private: Ui::processList Ui_processList; public slots: /*$PUBLIC_SLOTS$*/ protected: /*$PROTECTED_FUNCTIONS$*/ int m_maxProcess; QMap m_items; QList m_processes; QEventLoop m_eventLoop; QTimer m_timer; bool m_cancel; bool m_error; bool m_waitSync; int getNbRunning(); void wait(int _msec); protected slots: /*$PROTECTED_SLOTS$*/ void timeout(); virtual void bCancelClick(); virtual void processExited(k9Process *); }; #endif k9copy/src/import/k9importfiles.cpp0000644000175000017550000001704112412311500020141 0ustar emulatoremulator// // C++ Implementation: k9copy // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2005 // // Copyright: See COPYING file that comes nth this distribution // // #include "k9importfiles.h" #include "k9settings.h" #include #include "k9tools.h" #include #include "images.h" //PM DVDNAV #include "dvdread.h" #include "dvdread/dvd_reader.h" #include #include #include #if QT_VERSION >= 0x050000 #include #include #else #include #include #endif #include #include #include #include #include "k9import.h" #include "k9menuedit.h" #include "k9chapteredit.h" #include "k9newtitle.h" #include "k9menu.h" #include "k9dialogs.h" #if QT_VERSION >= 0x050000 #include #include #else #include "kdialog.h" #include #endif #if QT_VERSION >= 0x050000 // Qt5 Code #ifndef FALSE #define FALSE (0) #endif #ifndef TRUE #define TRUE (!FALSE) #endif #include #include #else() // Qt4 Code #include #endif k9ImportFiles::k9ImportFiles(k9Copy *_parent) : KXmlGuiWindow(_parent,0 ) { // accept dnd m_parent=_parent; setAcceptDrops(true); setDockOptions(QMainWindow::ForceTabbedDocks |QMainWindow::AnimatedDocks); setCorner(Qt::BottomRightCorner,Qt::RightDockWidgetArea); setCorner(Qt::TopRightCorner,Qt::RightDockWidgetArea); setCorner(Qt::BottomLeftCorner,Qt::LeftDockWidgetArea); // then, setup our actions setupActions(); // and a status bar m_drives=new k9CdDrives(this); createWindows(); // backupAction->setChecked(true); changeCaption(i18n("DVD Author")); } void k9ImportFiles::createWindows() { m_actions["quit"]->setEnabled(true); m_actions["preferences"]->setEnabled(true); m_actions["create"]->setEnabled(false); m_k9Import=new k9Import (this,0,m_drives); setCentralWidget(m_k9Import); m_newTitle =new k9NewTitle( this); m_newTitle->setK9Import(m_k9Import); QDockWidget *doc=new QDockWidget(this);//i18n("Shrink Factor"),this,Qt::Tool); doc->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable |QDockWidget::DockWidgetClosable ); doc->setObjectName("addTitle"); QDockWidget *firstDock=doc; m_firstBottom=doc; doc->setWidget(m_newTitle); doc->setWindowTitle(i18n("Add Title")); addDockWidget(Qt::BottomDockWidgetArea, doc); m_chapterEdit=new k9ChapterEdit(this); doc=new QDockWidget(this);//i18n("MPEG4 Encoding Options"),this,Qt::Tool); doc->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable |QDockWidget::DockWidgetClosable); doc->setWidget(m_chapterEdit); doc->setWindowTitle(i18n("Chapter properties")); doc->setObjectName("chapterEdit"); addDockWidget(Qt::BottomDockWidgetArea, doc); tabifyDockWidget(doc,firstDock); connect(m_k9Import,SIGNAL(aviFileSelected(k9AviFile*)),m_chapterEdit,SLOT(setAviFile(k9AviFile*))); doc=new QDockWidget(this);// firstDock=doc; doc->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable |QDockWidget::DockWidgetClosable); m_menuEdit=new k9MenuEdit(this,0,m_k9Import->getNewDVD()->getRootMenu()->getScene()); doc->setWidget(m_menuEdit); doc->setObjectName("menuEdit"); doc->setWindowTitle(i18n("Edit menu")); addDockWidget(Qt::RightDockWidgetArea, doc); connect (m_k9Import,SIGNAL(titleSelected(k9Title*)),m_menuEdit,SLOT(titleSelected(k9Title*))); connect (m_k9Import,SIGNAL(rootSelected(k9NewDVD*)),m_menuEdit,SLOT(rootSelected(k9NewDVD*))); m_k9Import->setMenuEdit(m_menuEdit); m_k9Import->init(); setActions(true); setAutoSaveSettings(); } void k9ImportFiles::removeToolWindows() { /* for (KMdiToolViewAccessor *acc=m_ToolViews.first();acc;acc=m_ToolViews.next()) { deleteToolWindow(acc); } m_ToolViews.clear(); */ } k9ImportFiles::~k9ImportFiles() { delete m_newTitle; delete m_menuEdit; delete m_chapterEdit; m_parent->m_import=NULL; m_k9Import->hide(); m_k9Import->clear(); delete m_k9Import; delete m_drives; } bool k9ImportFiles::queryClose ( ) { return true; } void k9ImportFiles::setupActions() { #if QT_VERSION >= 0x050000 m_actions["create"] = new QAction(QIcon("author"),i18n("Create DVD"),this); backupAction = new QAction(QIcon("dvdcopy"),i18n("DVD Backup"),this ); #else m_actions["create"] = new QAction(KIcon("author"),i18n("Create DVD"),this); backupAction = new KAction(KIcon("dvdcopy"),i18n("DVD Backup"),this ); #endif m_actions["backup"]=backupAction; m_actions["quit"]=KStandardAction::quit(this, SLOT(quit()),(QObject*) actionCollection()); m_actions["preferences"]=KStandardAction::preferences(this,SLOT(preferences()),(QObject*)actionCollection()); KStandardAction::keyBindings(this, SLOT(optionsConfigureKeys()), (QObject*)actionCollection()); KStandardAction::configureToolbars(this, SLOT(optionsConfigureToolbars()), (QObject*)actionCollection()); setStandardToolBarMenuEnabled(TRUE); createStandardStatusBarAction(); actionCollection()->addAction("Create",m_actions["create"]); actionCollection()->addAction("backup",backupAction); connect(m_actions["create"], SIGNAL(triggered(bool)), SLOT(ActionCreate())); connect(backupAction, SIGNAL(triggered(bool)), SLOT(ActionBackup())); } void k9ImportFiles::setActions( bool enabled) { m_actions["quit"]->setEnabled(enabled); m_actions["preferences"]->setEnabled(enabled); m_actions["create"]->setEnabled(enabled); m_menuEdit->setEnabled(enabled); m_newTitle->setEnabled(enabled); m_chapterEdit->setEnabled(enabled); m_k9Import->setEnabled(enabled); } void k9ImportFiles::optionsConfigureKeys() { KShortcutsDialog::configure(actionCollection()); } void k9ImportFiles::optionsConfigureToolbars() { KEditToolBar dlg(factory()); connect(&dlg,SIGNAL(newToolbarConfig()),this,SLOT(newToolbarConfig())); dlg.exec(); } void k9ImportFiles::newToolbarConfig() { // this slot is called when user clicks "Ok" or "Apply" in the toolbar editor. // recreate our GUI, and re-apply the settings (e.g. "text under icons", etc.) createGUI(0); // applyMainWindowSettings(KGlobal::config(), autoSaveGroup()); } void k9ImportFiles::preferences() { k9Settings settings(k9Dialogs::getMainWidget(),i18n("Settings")); settings.exec(); } void k9ImportFiles::ActionCreate() { m_k9Import->execute(); } void k9ImportFiles::ActionBackup() { m_parent->show(); k9Dialogs::setMainWidget(m_parent); hide(); /* */ } void k9ImportFiles::changeStatusbar(const QString& text,int id) { // display the text on the statusbar #if QT_VERSION >= 0x050000 #else statusBar()->changeItem(text,id); #endif } void k9ImportFiles::changeCaption(const QString& text) { // display the text on the caption #if QT_VERSION >= 0x050000 setWindowTitle((text)); #else setWindowTitle(KDialog::makeStandardCaption(text)); #endif } void k9ImportFiles::quit() { close( ); qApp->quit(); } void k9ImportFiles::closeEvent( QCloseEvent* ce ) { k9Config config; if (config.getPrefDelTmpFiles()) k9Tools::clearOutput(config.getPrefOutput()+"/dvd"); ce->accept(); m_parent->show(); } void k9ImportFiles::setEnabledCreateDVD(bool _state) { m_actions["create"]->setEnabled(_state); } k9copy/src/vamps/0000755000175000017550000000000012412271774014467 5ustar emulatoremulatork9copy/src/vamps/getvlc.h0000644000175000017550000003742412412271774016136 0ustar emulatoremulator /* macroblock modes */ #define MACROBLOCK_INTRA 1 #define MACROBLOCK_PATTERN 2 #define MACROBLOCK_MOTION_BACKWARD 4 #define MACROBLOCK_MOTION_FORWARD 8 #define MACROBLOCK_QUANT 16 #define DCT_TYPE_INTERLACED 32 /* motion_type */ #define MOTION_TYPE_MASK (3*64) #define MOTION_TYPE_BASE 64 #define MC_FIELD (1*64) #define MC_FRAME (2*64) #define MC_16X8 (2*64) #define MC_DMV (3*64) /* picture structure */ #define TOP_FIELD 1 #define BOTTOM_FIELD 2 #define FRAME_PICTURE 3 /* remove num valid bits from bit_buf */ #define DUMPBITS(bit_buf,bits,num) Flush_Bits(num) #define COPYBITS(bit_buf,bits,num) Copy_Bits(num) /* take num bits from the high part of bit_buf and zero extend them */ #define UBITS(bit_buf,num) (((uint32_t)(inbitbuf)) >> (32 - (num))) /* take num bits from the high part of bit_buf and sign extend them */ #define SBITS(bit_buf,num) (((int32_t)(inbitbuf)) >> (32 - (num))) typedef struct { uint8_t modes; uint8_t len; } MBtab; typedef struct { uint8_t delta; uint8_t len; } MVtab; typedef struct { int8_t dmv; uint8_t len; } DMVtab; typedef struct { uint8_t cbp; uint8_t len; } CBPtab; typedef struct { uint8_t size; uint8_t len; } DCtab; typedef struct { uint8_t run; uint8_t level; uint8_t len; } DCTtab; typedef struct { uint8_t mba; uint8_t len; } MBAtab; #define INTRA MACROBLOCK_INTRA #define QUANT MACROBLOCK_QUANT static const MBtab MB_I [] = { {INTRA|QUANT, 2}, {INTRA, 1} }; #define MC MACROBLOCK_MOTION_FORWARD #define CODED MACROBLOCK_PATTERN static const MBtab MB_P [] = { {INTRA|QUANT, 6}, {CODED|QUANT, 5}, {MC|CODED|QUANT, 5}, {INTRA, 5}, {MC, 3}, {MC, 3}, {MC, 3}, {MC, 3}, {CODED, 2}, {CODED, 2}, {CODED, 2}, {CODED, 2}, {CODED, 2}, {CODED, 2}, {CODED, 2}, {CODED, 2}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1}, {MC|CODED, 1} }; #define FWD MACROBLOCK_MOTION_FORWARD #define BWD MACROBLOCK_MOTION_BACKWARD #define INTER MACROBLOCK_MOTION_FORWARD|MACROBLOCK_MOTION_BACKWARD static const MBtab MB_B [] = { {0, 0}, {INTRA|QUANT, 6}, {BWD|CODED|QUANT, 6}, {FWD|CODED|QUANT, 6}, {INTER|CODED|QUANT, 5}, {INTER|CODED|QUANT, 5}, {INTRA, 5}, {INTRA, 5}, {FWD, 4}, {FWD, 4}, {FWD, 4}, {FWD, 4}, {FWD|CODED, 4}, {FWD|CODED, 4}, {FWD|CODED, 4}, {FWD|CODED, 4}, {BWD, 3}, {BWD, 3}, {BWD, 3}, {BWD, 3}, {BWD, 3}, {BWD, 3}, {BWD, 3}, {BWD, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, {BWD|CODED, 3}, {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2} }; #undef INTRA #undef QUANT #undef MC #undef CODED #undef FWD #undef BWD #undef INTER static const MVtab MV_4 [] = { { 3, 6}, { 2, 4}, { 1, 3}, { 1, 3}, { 0, 2}, { 0, 2}, { 0, 2}, { 0, 2} }; static const MVtab MV_10 [] = { { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, {15,10}, {14,10}, {13,10}, {12,10}, {11,10}, {10,10}, { 9, 9}, { 9, 9}, { 8, 9}, { 8, 9}, { 7, 9}, { 7, 9}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7} }; static const DMVtab DMV_2 [] = { { 0, 1}, { 0, 1}, { 1, 2}, {-1, 2} }; static const CBPtab CBP_7 [] = { {0x22, 7}, {0x12, 7}, {0x0a, 7}, {0x06, 7}, {0x21, 7}, {0x11, 7}, {0x09, 7}, {0x05, 7}, {0x3f, 6}, {0x3f, 6}, {0x03, 6}, {0x03, 6}, {0x24, 6}, {0x24, 6}, {0x18, 6}, {0x18, 6}, {0x3e, 5}, {0x3e, 5}, {0x3e, 5}, {0x3e, 5}, {0x02, 5}, {0x02, 5}, {0x02, 5}, {0x02, 5}, {0x3d, 5}, {0x3d, 5}, {0x3d, 5}, {0x3d, 5}, {0x01, 5}, {0x01, 5}, {0x01, 5}, {0x01, 5}, {0x38, 5}, {0x38, 5}, {0x38, 5}, {0x38, 5}, {0x34, 5}, {0x34, 5}, {0x34, 5}, {0x34, 5}, {0x2c, 5}, {0x2c, 5}, {0x2c, 5}, {0x2c, 5}, {0x1c, 5}, {0x1c, 5}, {0x1c, 5}, {0x1c, 5}, {0x28, 5}, {0x28, 5}, {0x28, 5}, {0x28, 5}, {0x14, 5}, {0x14, 5}, {0x14, 5}, {0x14, 5}, {0x30, 5}, {0x30, 5}, {0x30, 5}, {0x30, 5}, {0x0c, 5}, {0x0c, 5}, {0x0c, 5}, {0x0c, 5}, {0x20, 4}, {0x20, 4}, {0x20, 4}, {0x20, 4}, {0x20, 4}, {0x20, 4}, {0x20, 4}, {0x20, 4}, {0x10, 4}, {0x10, 4}, {0x10, 4}, {0x10, 4}, {0x10, 4}, {0x10, 4}, {0x10, 4}, {0x10, 4}, {0x08, 4}, {0x08, 4}, {0x08, 4}, {0x08, 4}, {0x08, 4}, {0x08, 4}, {0x08, 4}, {0x08, 4}, {0x04, 4}, {0x04, 4}, {0x04, 4}, {0x04, 4}, {0x04, 4}, {0x04, 4}, {0x04, 4}, {0x04, 4}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3} }; static const CBPtab CBP_9 [] = { {0, 0}, {0x00, 9}, {0x27, 9}, {0x1b, 9}, {0x3b, 9}, {0x37, 9}, {0x2f, 9}, {0x1f, 9}, {0x3a, 8}, {0x3a, 8}, {0x36, 8}, {0x36, 8}, {0x2e, 8}, {0x2e, 8}, {0x1e, 8}, {0x1e, 8}, {0x39, 8}, {0x39, 8}, {0x35, 8}, {0x35, 8}, {0x2d, 8}, {0x2d, 8}, {0x1d, 8}, {0x1d, 8}, {0x26, 8}, {0x26, 8}, {0x1a, 8}, {0x1a, 8}, {0x25, 8}, {0x25, 8}, {0x19, 8}, {0x19, 8}, {0x2b, 8}, {0x2b, 8}, {0x17, 8}, {0x17, 8}, {0x33, 8}, {0x33, 8}, {0x0f, 8}, {0x0f, 8}, {0x2a, 8}, {0x2a, 8}, {0x16, 8}, {0x16, 8}, {0x32, 8}, {0x32, 8}, {0x0e, 8}, {0x0e, 8}, {0x29, 8}, {0x29, 8}, {0x15, 8}, {0x15, 8}, {0x31, 8}, {0x31, 8}, {0x0d, 8}, {0x0d, 8}, {0x23, 8}, {0x23, 8}, {0x13, 8}, {0x13, 8}, {0x0b, 8}, {0x0b, 8}, {0x07, 8}, {0x07, 8} }; static const DCtab DC_lum_5 [] = { {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {0, 3}, {0, 3}, {0, 3}, {0, 3}, {3, 3}, {3, 3}, {3, 3}, {3, 3}, {4, 3}, {4, 3}, {4, 3}, {4, 3}, {5, 4}, {5, 4}, {6, 5} }; static const DCtab DC_chrom_5 [] = { {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {3, 3}, {3, 3}, {3, 3}, {3, 3}, {4, 4}, {4, 4}, {5, 5} }; static const DCtab DC_long [] = { {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, { 6, 5}, { 6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, { 6, 5}, { 6, 5}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, { 7, 6}, { 7, 6}, {8, 7}, {8, 7}, {8, 7}, {8, 7}, {9, 8}, {9, 8}, {10, 9}, {11, 9} }; static const DCTtab DCT_16 [] = { {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, { 2,18, 0}, { 2,17, 0}, { 2,16, 0}, { 2,15, 0}, { 7, 3, 0}, { 17, 2, 0}, { 16, 2, 0}, { 15, 2, 0}, { 14, 2, 0}, { 13, 2, 0}, { 12, 2, 0}, { 32, 1, 0}, { 31, 1, 0}, { 30, 1, 0}, { 29, 1, 0}, { 28, 1, 0} }; static const DCTtab DCT_15 [] = { { 1,40,15}, { 1,39,15}, { 1,38,15}, { 1,37,15}, { 1,36,15}, { 1,35,15}, { 1,34,15}, { 1,33,15}, { 1,32,15}, { 2,14,15}, { 2,13,15}, { 2,12,15}, { 2,11,15}, { 2,10,15}, { 2, 9,15}, { 2, 8,15}, { 1,31,14}, { 1,31,14}, { 1,30,14}, { 1,30,14}, { 1,29,14}, { 1,29,14}, { 1,28,14}, { 1,28,14}, { 1,27,14}, { 1,27,14}, { 1,26,14}, { 1,26,14}, { 1,25,14}, { 1,25,14}, { 1,24,14}, { 1,24,14}, { 1,23,14}, { 1,23,14}, { 1,22,14}, { 1,22,14}, { 1,21,14}, { 1,21,14}, { 1,20,14}, { 1,20,14}, { 1,19,14}, { 1,19,14}, { 1,18,14}, { 1,18,14}, { 1,17,14}, { 1,17,14}, { 1,16,14}, { 1,16,14} }; static const DCTtab DCT_13 [] = { { 11, 2,13}, { 10, 2,13}, { 6, 3,13}, { 4, 4,13}, { 3, 5,13}, { 2, 7,13}, { 2, 6,13}, { 1,15,13}, { 1,14,13}, { 1,13,13}, { 1,12,13}, { 27, 1,13}, { 26, 1,13}, { 25, 1,13}, { 24, 1,13}, { 23, 1,13}, { 1,11,12}, { 1,11,12}, { 9, 2,12}, { 9, 2,12}, { 5, 3,12}, { 5, 3,12}, { 1,10,12}, { 1,10,12}, { 3, 4,12}, { 3, 4,12}, { 8, 2,12}, { 8, 2,12}, { 22, 1,12}, { 22, 1,12}, { 21, 1,12}, { 21, 1,12}, { 1, 9,12}, { 1, 9,12}, { 20, 1,12}, { 20, 1,12}, { 19, 1,12}, { 19, 1,12}, { 2, 5,12}, { 2, 5,12}, { 4, 3,12}, { 4, 3,12}, { 1, 8,12}, { 1, 8,12}, { 7, 2,12}, { 7, 2,12}, { 18, 1,12}, { 18, 1,12} }; static const DCTtab DCT_B14_10 [] = { { 17, 1,10}, { 6, 2,10}, { 1, 7,10}, { 3, 3,10}, { 2, 4,10}, { 16, 1,10}, { 15, 1,10}, { 5, 2,10} }; static const DCTtab DCT_B14_8 [] = { { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, { 3, 2, 7}, { 3, 2, 7}, { 10, 1, 7}, { 10, 1, 7}, { 1, 4, 7}, { 1, 4, 7}, { 9, 1, 7}, { 9, 1, 7}, { 8, 1, 6}, { 8, 1, 6}, { 8, 1, 6}, { 8, 1, 6}, { 7, 1, 6}, { 7, 1, 6}, { 7, 1, 6}, { 7, 1, 6}, { 2, 2, 6}, { 2, 2, 6}, { 2, 2, 6}, { 2, 2, 6}, { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, { 14, 1, 8}, { 1, 6, 8}, { 13, 1, 8}, { 12, 1, 8}, { 4, 2, 8}, { 2, 3, 8}, { 1, 5, 8}, { 11, 1, 8} }; static const DCTtab DCT_B14AC_5 [] = { { 1, 3, 5}, { 5, 1, 5}, { 4, 1, 5}, { 1, 2, 4}, { 1, 2, 4}, { 3, 1, 4}, { 3, 1, 4}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2} }; static const DCTtab DCT_B14DC_5 [] = { { 1, 3, 5}, { 5, 1, 5}, { 4, 1, 5}, { 1, 2, 4}, { 1, 2, 4}, { 3, 1, 4}, { 3, 1, 4}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1}, { 1, 1, 1} }; static const DCTtab DCT_B15_10 [] = { { 6, 2, 9}, { 6, 2, 9}, { 15, 1, 9}, { 15, 1, 9}, { 3, 4,10}, { 17, 1,10}, { 16, 1, 9}, { 16, 1, 9} }; static const DCTtab DCT_B15_8 [] = { { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, { 8, 1, 7}, { 8, 1, 7}, { 9, 1, 7}, { 9, 1, 7}, { 7, 1, 7}, { 7, 1, 7}, { 3, 2, 7}, { 3, 2, 7}, { 1, 7, 6}, { 1, 7, 6}, { 1, 7, 6}, { 1, 7, 6}, { 1, 6, 6}, { 1, 6, 6}, { 1, 6, 6}, { 1, 6, 6}, { 5, 1, 6}, { 5, 1, 6}, { 5, 1, 6}, { 5, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, { 6, 1, 6}, { 2, 5, 8}, { 12, 1, 8}, { 1,11, 8}, { 1,10, 8}, { 14, 1, 8}, { 13, 1, 8}, { 4, 2, 8}, { 2, 4, 8}, { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, { 3, 1, 5}, { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, { 2, 2, 5}, { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, { 4, 1, 5}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, { 2, 1, 3}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 3, 4}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 1, 2}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 2, 3}, { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, { 1, 4, 5}, { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, { 1, 5, 5}, { 10, 1, 7}, { 10, 1, 7}, { 2, 3, 7}, { 2, 3, 7}, { 11, 1, 7}, { 11, 1, 7}, { 1, 8, 7}, { 1, 8, 7}, { 1, 9, 7}, { 1, 9, 7}, { 1,12, 8}, { 1,13, 8}, { 3, 3, 8}, { 5, 2, 8}, { 1,14, 8}, { 1,15, 8} }; static const MBAtab MBA_5 [] = { {6, 5}, {5, 5}, {4, 4}, {4, 4}, {3, 4}, {3, 4}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1} }; static const MBAtab MBA_11 [] = { {32, 11}, {31, 11}, {30, 11}, {29, 11}, {28, 11}, {27, 11}, {26, 11}, {25, 11}, {24, 11}, {23, 11}, {22, 11}, {21, 11}, {20, 10}, {20, 10}, {19, 10}, {19, 10}, {18, 10}, {18, 10}, {17, 10}, {17, 10}, {16, 10}, {16, 10}, {15, 10}, {15, 10}, {14, 8}, {14, 8}, {14, 8}, {14, 8}, {14, 8}, {14, 8}, {14, 8}, {14, 8}, {13, 8}, {13, 8}, {13, 8}, {13, 8}, {13, 8}, {13, 8}, {13, 8}, {13, 8}, {12, 8}, {12, 8}, {12, 8}, {12, 8}, {12, 8}, {12, 8}, {12, 8}, {12, 8}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, {10, 8}, {10, 8}, {10, 8}, {10, 8}, {10, 8}, {10, 8}, {10, 8}, {10, 8}, { 9, 8}, { 9, 8}, { 9, 8}, { 9, 8}, { 9, 8}, { 9, 8}, { 9, 8}, { 9, 8}, { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, { 8, 7}, { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7}, { 7, 7} }; k9copy/src/vamps/k9ffmpeg.cpp0000644000175000017550000001277312412271774016715 0ustar emulatoremulator// // C++ Implementation: k9avidecode // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "k9common.h" #include "k9ffmpeg.h" #ifdef HAVE_SWSCALE #include "swscale.h" #endif #include #include k9FFMpeg _FFMpegInstance; k9FFMpeg::k9FFMpeg(){ CodecHandle=0; FormatHandle=0; SwscaleHandle=0; CodecHandle=dlopen("libavcodec.so",RTLD_LAZY ); //| RTLD_GLOBAL FormatHandle=dlopen("libavformat.so",RTLD_LAZY); #ifdef HAVE_SWSCALE SwscaleHandle=dlopen("libswscale.so",RTLD_LAZY); #endif UtilHandle=dlopen("libavutil.so",RTLD_LAZY); if (!CodecHandle) { m_error =i18n("Cannot open then library %1","libavcodec"); return; } if (!FormatHandle) { m_error =i18n("Cannot open then library %1","libavformat"); return; } if (!UtilHandle) { m_error =i18n("Cannot open the library %1","libavutil"); return; } #ifdef HAVE_SWSCALE if (!SwscaleHandle) { m_error =i18n("Cannot open then library %1","libswscale"); return; } #endif avcodec_init =(avcodec_init_t)dlsym(CodecHandle,"avcodec_init"); av_register_all = (av_register_all_t)dlsym(FormatHandle,"av_register_all"); avcodec_alloc_context=(avcodec_alloc_context_t)dlsym(CodecHandle,"avcodec_alloc_context"); # if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 2, 0) avformat_open_input = (avformat_open_input_t)dlsym(FormatHandle,"avformat_open_input"); # else av_open_input_file = (av_open_input_file_t)dlsym(FormatHandle,"av_open_input_file"); # endif # if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 6, 0) avformat_find_stream_info = (avformat_find_stream_info_t)dlsym(FormatHandle,"avformat_find_stream_info"); # else av_find_stream_info = (av_find_stream_info_t)dlsym(FormatHandle,"av_find_stream_info"); # endif avcodec_find_decoder =(avcodec_find_decoder_t) dlsym(CodecHandle,"avcodec_find_decoder"); # if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 8, 0) avcodec_open2 = (avcodec_open2_t)dlsym(CodecHandle,"avcodec_open2"); # else avcodec_open = (avcodec_open_t)dlsym(CodecHandle,"avcodec_open"); # endif avcodec_alloc_frame = (avcodec_alloc_frame_t)dlsym(CodecHandle,"avcodec_alloc_frame"); avpicture_get_size = (avpicture_get_size_t)dlsym(CodecHandle,"avpicture_get_size"); av_malloc = (av_malloc_t)dlsym(CodecHandle,"av_malloc"); avpicture_fill = (avpicture_fill_t)dlsym(CodecHandle,"avpicture_fill"); av_read_frame = (av_read_frame_t)dlsym(FormatHandle,"av_read_frame"); # if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 23, 0) avcodec_decode_video2 = (avcodec_decode_video2_t)dlsym(CodecHandle,"avcodec_decode_video2"); # else avcodec_decode_video = (avcodec_decode_video_t)dlsym(CodecHandle,"avcodec_decode_video"); # endif img_convert = (img_convert_t)dlsym(CodecHandle,"img_convert"); av_free = (av_free_t)dlsym(CodecHandle,"av_free"); avcodec_close = (avcodec_close_t)dlsym(FormatHandle,"avcodec_close"); # if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 17, 0) avformat_close_input = (avformat_close_input_t)dlsym(FormatHandle,"avformat_close_input"); # else av_close_input_file = (av_close_input_file_t)dlsym(FormatHandle,"av_close_input_file"); # endif av_seek_frame=(av_seek_frame_t)dlsym(FormatHandle,"av_seek_frame"); av_rescale_q=(av_rescale_q_t)dlsym(FormatHandle,"av_rescale_q"); avcodec_flush_buffers=(avcodec_flush_buffers_t)dlsym(CodecHandle,"avcodec_flush_buffers"); #ifdef HAVE_SWSCALE sws_freeContext= (sws_freeContext_t)dlsym(SwscaleHandle,"sws_freeContext"); sws_getContext=(sws_getContext_t)dlsym(SwscaleHandle,"sws_getContext"); sws_scale= (sws_scale_t)dlsym(SwscaleHandle,"sws_scale"); #endif # if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51, 33, 0) av_gettime=(av_gettime_t)dlsym(UtilHandle,"av_gettime"); # else av_gettime=(av_gettime_t)dlsym(FormatHandle,"av_gettime"); # endif url_fopen=(url_fopen_t)dlsym(FormatHandle,"url_fopen"); audio_resample_init=(audio_resample_init_t)dlsym(CodecHandle,"audio_resample_init"); avcodec_decode_audio2=(avcodec_decode_audio2_t)dlsym(CodecHandle,"avcodec_decode_audio2"); avcodec_decode_audio=(avcodec_decode_audio_t)dlsym(CodecHandle,"avcodec_decode_audio"); avcodec_encode_audio=(avcodec_encode_audio_t)dlsym(CodecHandle,"avcodec_encode_audio"); guess_format=(guess_format_t)dlsym(FormatHandle,"guess_format"); audio_resample=(audio_resample_t) dlsym(CodecHandle,"audio_resample"); av_write_header=(av_write_header_t)dlsym(FormatHandle,"av_write_header"); av_alloc_format_context=(av_alloc_format_context_t)dlsym(FormatHandle,"av_alloc_format_context"); avcodec_find_encoder=(avcodec_find_encoder_t)dlsym(CodecHandle,"avcodec_find_encoder"); av_init_packet=(av_init_packet_t)dlsym(FormatHandle,"av_init_packet"); av_write_frame=(av_write_frame_t)dlsym(FormatHandle,"av_write_frame"); av_write_trailer=(av_write_trailer_t)dlsym(FormatHandle,"av_write_trailer"); av_set_parameters=(av_set_parameters_t)dlsym(FormatHandle,"av_set_parameters"); dump_format=(dump_format_t)dlsym(FormatHandle,"dump_format"); av_new_stream=(av_new_stream_t)dlsym(FormatHandle,"av_new_stream"); } k9FFMpeg::~k9FFMpeg() { if (FormatHandle) dlclose(FormatHandle); if (CodecHandle) dlclose(CodecHandle); #ifdef HAVE_SWSCALE if (SwscaleHandle) dlclose(CodecHandle); #endif } k9FFMpeg *k9FFMpeg::instance() { return &_FFMpegInstance; } k9copy/src/vamps/k9fifo.cpp0000644000175000017550000001122712412271774016365 0ustar emulatoremulator// // C++ Implementation: k9fifo // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "k9fifo.h" #include uint64_t k9MemoryFifo::count() { return m_count; } void k9MemoryFifo::enqueue (uchar *_buffer, uint32_t _size) { mutex.lock(); if (_size+queue > INPUT_SIZE) { uint32_t s1,s2; s1=INPUT_SIZE-queue; memcpy(array+queue,_buffer,s1); s2=_size-s1; memcpy(array,_buffer+s1,s2); } else memcpy(array+queue,_buffer,_size); queue=(queue+_size) %INPUT_SIZE; m_count+=_size; mutex.unlock(); } void k9MemoryFifo::dequeue(uchar *_buffer,uint32_t _size) { mutex.lock(); if ( _size+head >INPUT_SIZE) { uint32_t s1,s2; s1=INPUT_SIZE - head; memcpy(_buffer,array+head,s1); s2=_size-s1; memcpy(_buffer+s1,array,s2); } else memcpy(_buffer,array+head,_size); head =(head+_size)%INPUT_SIZE; m_count -=_size; mutex.unlock(); } void k9MemoryFifo::clear() { mutex.lock(); head=queue; m_count=0; mutex.unlock(); } void k9MemoryFifo::setNoData() { noData=true; wDataRead.wakeAll(); wDataReady.wakeAll(); } void k9MemoryFifo::addData(uchar *data,uint size) { while (1) { if (freespace()>=size) { enqueue(data,size); wDataReady.wakeAll(); break; } else { QMutex m; m.lock(); wDataRead.wait(&m); m.unlock(); } } } int k9MemoryFifo::readData(uchar * data,uint size) { uint size2=size; uint32_t readSize=0,s=0; while (1) { // is there data in the buffer? if (count() >0) { // s= size of data that we will read (maximum = size) s=(count()) =size2)) { break; } else { QMutex m; m.lock(); wDataReady.wait(&m); m.unlock(); } } // if there's datas in input buffer and we did not get all what we wanted, we take them. s= (count()) 0 ) dequeue(data,s); wDataRead.wakeAll(); return readSize; } //******************************************************************** k9FileFifo::k9FileFifo() { m_rfile=m_wfile=NULL; m_output=k9Tools::getTempPath(); clear(); m_wfile=m_rfile; } void k9FileFifo::enqueue (uchar *_buffer, uint32_t _size) { m_mutex.lock(); while (m_queue.count() >MAX_NUMBER_OF_FILES) { m_wait.wait(&m_mutex); } m_wfile->seek(m_fstart); m_wfile->write((const char*)_buffer,_size); m_fstart=m_wfile->pos(); if (m_fstart > MAX_FILE_SIZE) { m_wfile=new QTemporaryFile(QDir::cleanPath(m_output +"/k9b")); m_wfile->setAutoRemove(true); m_wfile->open(); m_queue.enqueue(m_wfile); m_fstart=0; } m_end+=_size; m_mutex.unlock(); } uint64_t k9FileFifo::count() { return m_end-m_start; } k9FileFifo::~k9FileFifo(){ if (m_rfile) { m_rfile->close(); delete m_rfile; } while (m_queue.count() >0) { QTemporaryFile *file=m_queue.dequeue(); file->close(); delete file; } } void k9FileFifo::dequeue(uchar *_buffer,uint32_t _size) { uint32_t size2=0; m_mutex.lock(); m_rfile->seek(m_fend); uint32_t size=m_rfile->read((char*)_buffer,_size); m_start+=size; size2+=size; while (size2 <_size && m_queue.count()>0) { m_rfile->close(); delete m_rfile; m_rfile=m_queue.dequeue(); m_rfile->seek(0); size=m_rfile->read((char*)_buffer+size2,_size-size2); m_start+=size; size2+=size; m_wait.wakeAll(); } m_fend=m_rfile->pos(); m_mutex.unlock(); } void k9FileFifo::clear() { if (m_rfile) { m_rfile->close(); delete m_rfile; } qDeleteAll(m_queue); m_fstart=m_fend=0; m_rfile=new QTemporaryFile(QDir::cleanPath(m_output +"/k9b")); m_rfile->setAutoRemove(true); m_rfile->open(); m_start=m_end=0; } k9copy/src/vamps/k9fifo.h0000644000175000017550000000367212412271774016037 0ustar emulatoremulator// // C++ Interface: k9fifo // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9FIFO_H #define K9FIFO_H #include "k9common.h" #include #include #include #include /** @author Jean-Michel PETIT */ #define INPUT_SIZE ( 0x2000*1024) #define MAX_FILE_SIZE (0x100*1024*1024) #define MAX_NUMBER_OF_FILES 50 class k9fifo{ public: virtual uint64_t count() = 0; virtual uint64_t freespace() =0; virtual void enqueue (uchar *_buffer, uint32_t _size) =0 ; virtual void dequeue(uchar *_buffer,uint32_t _size) =0; virtual void clear()=0; virtual ~k9fifo(){} }; class k9FileFifo:public k9fifo { private: QTemporaryFile *m_rfile,*m_wfile; QMutex m_mutex; quint64 m_end,m_start; qint64 m_fstart,m_fend; QQueue m_queue; QString m_output; QWaitCondition m_wait; public: k9FileFifo (); uint64_t count(); // { return (queue-head)%INPUT_SIZE ;} uint64_t freespace() {return 5*MAX_FILE_SIZE;} void enqueue (uchar *_buffer, uint32_t _size) ; void dequeue(uchar *_buffer,uint32_t _size) ; void clear(); virtual ~k9FileFifo(); }; class k9MemoryFifo:public k9fifo { private: uint32_t head,queue; uchar *array; uint32_t m_count; bool noData; QMutex mutex; QWaitCondition wDataRead,wDataReady; public: k9MemoryFifo () { head=queue=m_count=0;noData=false;array= new uchar[INPUT_SIZE];} uint64_t count(); // { return (queue-head)%INPUT_SIZE ;} uint64_t freespace() {return INPUT_SIZE-count();} void enqueue (uchar *_buffer, uint32_t _size) ; void dequeue(uchar *_buffer,uint32_t _size) ; void clear(); void setNoData(); void addData(uchar *data,uint size); int readData(uchar * data,uint size); virtual ~k9MemoryFifo() { delete[] array;} }; #endif k9copy/src/vamps/k9vamps.h0000755000175000017550000001116312412271774016237 0ustar emulatoremulator// // C++ Interface: k9vamps // // Description: A transcription from Vamps in C++ // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9VAMPS_H #define K9VAMPS_H #include "k9common.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "k9dvdbackupinterface.h" #include "k9requant.h" #include "k9fifo.h" #include "k9saveimage.h" #include // DVD sector size #define SECT_SIZE 2048 // read buffer size (4MB) #define RBUF_SIZE (0x1000*1024) // write buffer size (4MB) #define WBUF_SIZE (0x1000*1024) // initial video buffer size (1MB) #define VBUF_SIZE (1024*1024) class k9bgUpdate : public QThread { private: uchar * m_buffer; k9DVDBackupInterface *m_backup; uint32_t m_size; QMutex mutex; public: k9bgUpdate(k9DVDBackupInterface * _backup); void update(uchar *_buffer, uint32_t size); protected: void run(); }; class k9vamps:public QThread { private: uchar *rbuf;// [RBUF_SIZE]; // the PS read buffer uchar wbuf [WBUF_SIZE]; // the PS write buffer uchar *vibuf; // the video ES requant input buffer uchar *vobuf; // the video ES requant output buffer uchar *rptr ; // pointer to current char in read buf uchar *rhwp ; // read buffer high water pointer uchar *wptr ; // pointer to first unused char in wbuf uint64_t bytes_read; // total PS bytes read uint64_t bytes_written; // total PS bytes written uint64_t padding_bytes; // total padding bytes written uint64_t vin_bytes; // total unshrinked video ES bytes uint64_t vout_bytes; // total shrinked video ES bytes uint64_t ps_size; // total PS size in bytes uint32_t vbuf_size; // the video ES requant buffers' size uint32_t rbuf_size; uint32_t vilen; // current GOP's unshrinked vidES bytes uint32_t volen; // current GOP's shrinked vidES bytes int total_packs; // total no. PS packs int video_packs; // no. video packs in PS int skipped_video_packs; // skipped thereof int aux_packs; // no. audio and subpicture packs in PS int skipped_aux_packs; // skipped thereof int sequence_headers; // no. sequence headers (== #GOPs) int nav_packs; // no. nav packs int eof; // end of file flag int spu_track_map [32]; // subpicture track# translation map int audio_track_map [8]; // audio track# translation map int verbose; // level of verbosity int calc_ps_vap; // calc vaporization based on PS size bool m_preserve; // preserve audio/spu track numbers float vap_fact; // vaporization factor from cmd line bool noData; QMutex mutex; k9bgUpdate *m_bgUpdate; //k9MemoryFifo m_fifo; k9fifo *m_fifo; QString m_errMsg; bool m_error; double avgdiff; double m_totfact,m_nbfact,m_avgfact; QFile *m_output; private: // prototypes void vaporize (void); void fatal (QString _msg); int lock(int size); void copy(int size); void skip (int size); void flush(); uint64_t wtell (uchar *ptr); uint64_t rtell (uchar *ptr); bool check_pack (uchar *ptr); int check_video_packet (uchar *ptr); int requant (uchar *dst, uchar *src, int n, float fact); int new_private_1_type (uchar *ptr); void copy_private_1 (uchar *ptr); int new_mpeg_audio_id (int id); void copy_mpeg_audio (uchar *ptr); void vap_leader (); void vap_trailer (int length); int vap_phase1 (void); int gen_video_packet (uchar *ptr, uchar *voptr, int avail); void vap_phase2 (int seq_length); pthread_t thread; int getStreamIndex(uchar *ptr); int readData(uchar *data,uint size); QWaitCondition wDataRead; QWaitCondition wDataReady; k9DVDBackupInterface *m_dvdbackup; k9requant *m_requant; k9SaveImage *m_saveImage; protected: void run(); public: k9vamps(k9DVDBackupInterface *dvdbackup,bool _useCache=false); void addData(uchar* data,uint size); void setNoData(); void addSubpicture(uint id); void addAudio(uint id); void addAudio(uint id,uint newId); void reset(); void setInputSize(uint64_t size); void setVapFactor(float factor); void setSaveImage(k9SaveImage*); void setOutput(QFile *_output); uint64_t getOutputBytes(); uint64_t getSkippedBytes(); QString & geterrMsg(); bool geterror(); void abort(); void setPreserve(bool _value); ~k9vamps(); }; #endif k9copy/src/vamps/k9requant.cpp0000644000175000017550000016446712412271774017140 0ustar emulatoremulator// // C++ Implementation: k9requant // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9requant.h" #include "getvlc.h" #include "putvlc.h" // Code from libmpeg2 and mpeg2enc copyright by their respective owners // New code and modifications copyright Antoine Missout // Thanks to Sven Goethel for error resilience patches // Released under GPL license, see gnu.org // toggles: #define THREAD // #define LOG_RATE_CONTROL // some stats // #define DEMO // demo mode // #define STAT // print stats on exit // #define USE_FD // use 2 lasts args for input/output paths #define NDEBUG // turns off asserts #define REMOVE_BYTE_STUFFING // removes series of 0x00 // #define USE_GLOBAL_REGISTER // assign registers to bit buffers #define MAX_ERRORS 0 // if above copy slice //#define CHANGE_BRIGHTNESS //add a param to command line, changing brightness: _will_not_recompress_, disables max_errors //#define WIN // for windows fixes, use with USE_FD // params: // if not defined, non intra block in p frames are requantised // if defined and >= 0, we keep coeff. in pos 0..n-1 in scan order // and coeff which would have been non-null if requantised // if defined and < 0 we drop max 1/x coeffs. // experimental, looks better when undefined // #define P_FRAME_NON_INTRA_DROP 8 // params for fact = 1.0, fact = 3.0 and fact = 10.0 // we'll make a linear interpolation between static const int i_factors[3] = { 5, 15, 65 }; static const int p_factors[3] = { 5, 25, 85 }; static const int b_factors[3] = { 25, 45, 105 }; static const double i_min_stresses[3] = { 0.70, 0.40, 0.00 }; static const double p_min_stresses[3] = { 0.60, 0.35, 0.00 }; static const double b_min_stresses[3] = { 0.00, 0.00, 0.00 }; // factor up to which alt table will be used // (though alt_table gives better psnr up to factor around ~2.5 // the result is less pleasing to watch than normal table // so this is disabled) static const double max_alt_table = 0.0; // includes #include #include #include #include #include #ifndef USE_FD #include #include #endif // quant table #include "qTable.h" // useful constants #define I_TYPE 1 #define P_TYPE 2 #define B_TYPE 3 // gcc #ifdef HAVE_BUILTIN_EXPECT #define likely(x) __builtin_expect ((x) != 0, 1) #define unlikely(x) __builtin_expect ((x) != 0, 0) #else #define likely(x) (x) #define unlikely(x) (x) #endif #ifndef NDEBUG #define DEB(msg) fprintf (stderr, "%s:%d " msg, __FILE__, __LINE__) #define DEBF(format, args...) fprintf (stderr, "%s:%d " format, __FILE__, __LINE__, args) #else #define DEB(msg) #ifdef WIN #define DEBF(format, args) #else #define DEBF(format, args...) #endif #endif #ifndef THREAD #define LOG(msg) fprintf (stderr, msg) #ifdef WIN #define LOGF(format, arg1) fprintf (stderr, format, arg1) #else #define LOGF(format, args...) fprintf (stderr, format, args) #endif #endif /*#define MOV_READ \ mloka1 = rbuf - cbuf; if (mloka1) memmove(orbuf, cbuf, mloka1);\ cbuf = rbuf = orbuf; rbuf += mloka1; */ #ifdef STAT #define RETURN \ assert(rbuf >= cbuf);\ mloka1 = rbuf - cbuf;\ if (mloka1) { COPY(mloka1); }\ WRITE \ free(orbuf); \ free(owbuf); \ \ LOG("Stats:\n");\ \ LOGF("Wanted fact_x: %.1f\n", fact_x);\ \ LOGF("cnt_i: %.0f ", (float)cnt_i); \ if (cnt_i) LOGF("ori_i: %.0f new_i: %.0f fact_i: %.1f\n", (float)ori_i, (float)new_i, (float)ori_i/(float)new_i); \ else LOG("\n");\ \ LOGF("cnt_p: %.0f ", (float)cnt_p); \ if (cnt_p) LOGF("ori_p: %.0f new_p: %.0f fact_p: %.1f cnt_p_i: %.0f cnt_p_ni: %.0f propor: %.1f i\n", \ (float)ori_p, (float)new_p, (float)ori_p/(float)new_p, (float)cnt_p_i, (float)cnt_p_ni, (float)cnt_p_i/((float)cnt_p_i+(float)cnt_p_ni)); \ else LOG("\n");\ \ LOGF("cnt_b: %.0f ", (float)cnt_b); \ if (cnt_b) LOGF("ori_b: %.0f new_b: %.0f fact_b: %.1f cnt_b_i: %.0f cnt_b_ni: %.0f propor: %.1f i\n", \ (float)ori_b, (float)new_b, (float)ori_b/(float)new_b, (float)cnt_b_i, (float)cnt_b_ni, (float)cnt_b_i/((float)cnt_b_i+(float)cnt_b_ni)); \ else LOG("\n");\ \ LOGF("Final fact_x: %.1f\n", (float)inbytecnt/(float)outbytecnt);\ exit(0); #else #define RETURN \ assert(rbuf >= cbuf);\ mloka1 = rbuf - cbuf;\ if (mloka1) { COPY(mloka1); }\ WRITE \ free(orbuf); \ free(owbuf); \ exit(0); #endif #define MOTION_CALL(routine,direction) \ do { \ if ((direction) & MACROBLOCK_MOTION_FORWARD) \ routine (f_code[0]); \ if ((direction) & MACROBLOCK_MOTION_BACKWARD) \ routine (f_code[1]); \ } while (0) #define NEXT_MACROBLOCK \ do { \ h_offset += 16; \ if (h_offset == horizontal_size_value) \ { \ v_offset += 16; \ if (v_offset > (vertical_size_value - 16)) return; \ h_offset = 0; \ } \ } while (0) #ifdef P_FRAME_NON_INTRA_DROP #if (P_FRAME_NON_INTRA_DROP < 0) #undef UPDATE_VAL #define UPDATE_VAL #define SAVE_VAL #define WRITE_VAL \ blk->level = val; \ blk->run = i - li - 1; \ li = i; \ blk++; #else #define SAVE_VAL oval = val; #define WRITE_VAL \ if ((val) || (i < P_FRAME_NON_INTRA_DROP)) \ { \ blk->level = oval; \ blk->run = i - li - 1; \ li = i; \ blk++; \ } #endif #else #define SAVE_VAL #define WRITE_VAL \ if (val) \ { \ blk->level = val; \ blk->run = i - li - 1; \ li = i; \ blk++; \ } #endif #define UPDATE_VAL \ val = curTable[val]; int quantisers[42] = { 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 72, 80, 88, 96, 104, 112 }; int non_linear_quantizer_scale [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 18, 20, 22, 24, 28, 32, 36, 40, 44, 48, 52, 56, 64, 72, 80, 88, 96, 104, 112 }; const uint8 non_linear_mquant_table[32] = { 0, 1, 2, 3, 4, 5, 6, 7, 8,10,12,14,16,18,20,22, 24,28,32,36,40,44,48,52, 56,64,72,80,88,96,104,112 }; const uint8 map_non_linear_mquant[113] = { 0,1,2,3,4,5,6,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,16,16, 16,17,17,17,18,18,18,18,19,19,19,19,20,20,20,20,21,21,21,21,22,22, 22,22,23,23,23,23,24,24,24,24,24,24,24,25,25,25,25,25,25,25,26,26, 26,26,26,26,26,26,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,29, 29,29,29,29,29,29,29,29,29,30,30,30,30,30,30,30,31,31,31,31,31 }; k9requant::k9requant() { cbuf=rbuf=orbuf=wbuf=NULL; quant_table_id = &quant_table_id_data[2048]; rqt_run=false; initvar(); } void k9requant::putbits(uint val, int n) { assert(n < 32); assert(!(val & (0xffffffffU << n))); while (unlikely(n >= outbitcnt)) { wbuf[0] = (outbitbuf << outbitcnt ) | (val >> (n - outbitcnt)); SEEKW(1); n -= outbitcnt; outbitbuf = 0; val &= ~(0xffffffffU << n); outbitcnt = BITS_IN_BUF; } if (likely(n)) { outbitbuf = (outbitbuf << n) | val; outbitcnt -= n; } assert(outbitcnt > 0); assert(outbitcnt <= BITS_IN_BUF); } void k9requant::Refill_bits(void) { assert((rbuf - cbuf) >= 1); inbitbuf |= cbuf[0] << (24 - inbitcnt); inbitcnt += 8; SEEKR(1) } void k9requant::Flush_Bits(uint n) { assert(inbitcnt >= n); inbitbuf <<= n; inbitcnt -= n; assert( (!n) || ((n>0) && !(inbitbuf & 0x1)) ); while (unlikely(inbitcnt < 24)) Refill_bits(); } uint k9requant::Show_Bits(uint n) { return ((unsigned int)inbitbuf) >> (32 - n); } uint k9requant::Get_Bits(uint n) { uint Val = Show_Bits(n); Flush_Bits(n); return Val; } uint k9requant::Copy_Bits(uint n) { uint Val = Get_Bits(n); putbits(Val, n); return Val; } void k9requant::flush_read_buffer() { int i = inbitcnt & 0x7; if (i) { if (inbitbuf >> (32 - i)) { DEBF("illegal inbitbuf: 0x%08X, %i, 0x%02X, %i\n", inbitbuf, inbitcnt, (inbitbuf >> (32 - i)), i); sliceError++; } inbitbuf <<= i; inbitcnt -= i; } SEEKR(-1 * (inbitcnt >> 3)); inbitcnt = 0; } void k9requant::flush_write_buffer() { if (outbitcnt != 8) putbits(0, outbitcnt); } /////---- begin ext mpeg code int k9requant::scale_quant(double quant ) { int iquant; #ifdef DEMO if ((gopCount & 0x7F) < 10) // gop is ~ 0.5 sec, so 5 sec every ~minute (127 * 0.5 = 63.5 sec) { if (q_scale_type) return 112; else return 62; } #endif if (q_scale_type) { iquant = (int) floor(quant+0.5); /* clip mquant to legal (linear) range */ if (iquant<1) iquant = 1; if (iquant>112) iquant = 112; iquant = non_linear_mquant_table[map_non_linear_mquant[iquant]]; } else { /* clip mquant to legal (linear) range */ iquant = (int)floor(quant+0.5); if (iquant<2) iquant = 2; if (iquant>62) iquant = 62; iquant = (iquant/2)*2; // Must be *even* } return iquant; } int k9requant::increment_quant(int quant) { #ifdef DEMO if ((gopCount & 0x7F) < 10) { if (q_scale_type) return 112; else return 62; } #endif if (q_scale_type) { if (quant < 1 || quant > 112) { DEBF("illegal quant: %d\n", quant); if (quant > 112) quant = 112; else if (quant < 1) quant = 1; DEBF("illegal quant changed to : %d\n", quant); sliceError++; } quant = map_non_linear_mquant[quant] + 1; if (quant > 31) quant = 31; quant = non_linear_mquant_table[quant]; } else { if ((quant & 1) || (quant < 2) || (quant > 62)) { DEBF("illegal quant: %d\n", quant); if (quant & 1) quant--; if (quant > 62) quant = 62; else if (quant < 2) quant = 2; DEBF("illegal quant changed to : %d\n", quant); sliceError++; } quant += 2; if (quant > 62) quant = 62; } return quant; } int k9requant::intmax( register int x, register int y ) { return x < y ? y : x; } int k9requant::intmin( register int x, register int y ) { return x < y ? x : y; } int k9requant::getNewQuant(int curQuant, int intra) { #ifdef CHANGE_BRIGHTNESS return curQuant; #else int mquant = 0; double cStress; switch (picture_coding_type) { case I_TYPE: cStress = (stress_factor - i_min_stress) / (1.0 - i_min_stress); mquant = intmax(scale_quant(curQuant + i_factor*cStress), increment_quant(curQuant)); break; case P_TYPE: cStress = (stress_factor - p_min_stress) / (1.0 - p_min_stress); if (intra) // since it might be used as a ref, treat it as an I frame block mquant = intmax(scale_quant(curQuant + i_factor*cStress), increment_quant(curQuant)); else mquant = intmax(scale_quant(curQuant + p_factor*cStress), increment_quant(curQuant)); break; case B_TYPE: cStress = (stress_factor - b_min_stress) / (1.0 - b_min_stress); mquant = intmax(scale_quant(curQuant + b_factor*cStress), increment_quant(curQuant)); break; default: assert(0); break; } assert(mquant >= curQuant); return mquant; #endif } int k9requant::isNotEmpty(RunLevel *blk) { return (blk->level); } // return != 0 if error int k9requant::putAC(int run, int signed_level, int vlcformat) { int level, len; const VLCtable *ptab = NULL; level = (signed_level<0) ? -signed_level : signed_level; /* abs(signed_level) */ // assert(!(run<0 || run>63 || level==0 || level>2047)); if(run<0 || run>63) { DEBF("illegal run: %d\n", run); sliceError++; return 1; } if(level==0 || level>2047) { DEBF("illegal level: %d\n", level); sliceError++; return 1; } len = 0; if (run<2 && level<41) { if (vlcformat) ptab = &dct_code_tab1a[run][level-1]; else ptab = &dct_code_tab1[run][level-1]; len = ptab->len; } else if (run<32 && level<6) { if (vlcformat) ptab = &dct_code_tab2a[run-2][level-1]; else ptab = &dct_code_tab2[run-2][level-1]; len = ptab->len; } if (len) /* a VLC code exists */ { putbits(ptab->code, len); putbits(signed_level<0, 1); /* sign */ } else { putbits(1l, 6); /* Escape */ putbits(run, 6); /* 6 bit code for run */ putbits(((uint)signed_level) & 0xFFF, 12); } return 0; } // return != 0 if error int k9requant::putACfirst(int run, int val) { if (run==0 && (val==1 || val==-1)) { putbits(2|((val<0) ? 1 : 0), 2); return 0; } else return putAC(run,val,0); } void k9requant::putnonintrablk(RunLevel *blk) { assert(blk->level); if (putACfirst(blk->run, blk->level)) return; blk++; while(blk->level) { if (putAC(blk->run, blk->level, 0)) return; blk++; } putbits(2,2); } void k9requant::putcbp(int cbp) { assert(cbp > 0 && cbp < 64); putbits(cbptable[cbp].code,cbptable[cbp].len); } void k9requant::putmbtype(int mb_type) { putbits(mbtypetab[picture_coding_type-1][mb_type].code, mbtypetab[picture_coding_type-1][mb_type].len); } int k9requant::get_macroblock_modes () { int macroblock_modes; const MBtab * tab; switch (picture_coding_type) { case I_TYPE: tab = MB_I + UBITS (bit_buf, 1); DUMPBITS (bit_buf, bits, tab->len); macroblock_modes = tab->modes; if ((! (frame_pred_frame_dct)) && (picture_structure == FRAME_PICTURE)) { macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED; DUMPBITS (bit_buf, bits, 1); } return macroblock_modes; case P_TYPE: tab = MB_P + UBITS (bit_buf, 5); DUMPBITS (bit_buf, bits, tab->len); macroblock_modes = tab->modes; if (picture_structure != FRAME_PICTURE) { if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) { macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE; DUMPBITS (bit_buf, bits, 2); } return macroblock_modes; } else if (frame_pred_frame_dct) { if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) macroblock_modes |= MC_FRAME; return macroblock_modes; } else { if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) { macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE; DUMPBITS (bit_buf, bits, 2); } if (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN)) { macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED; DUMPBITS (bit_buf, bits, 1); } return macroblock_modes; } case B_TYPE: tab = MB_B + UBITS (bit_buf, 6); DUMPBITS (bit_buf, bits, tab->len); macroblock_modes = tab->modes; if (picture_structure != FRAME_PICTURE) { if (! (macroblock_modes & MACROBLOCK_INTRA)) { macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE; DUMPBITS (bit_buf, bits, 2); } return macroblock_modes; } else if (frame_pred_frame_dct) { /* if (! (macroblock_modes & MACROBLOCK_INTRA)) */ macroblock_modes |= MC_FRAME; return macroblock_modes; } else { if (macroblock_modes & MACROBLOCK_INTRA) goto intra; macroblock_modes |= UBITS (bit_buf, 2) * MOTION_TYPE_BASE; DUMPBITS (bit_buf, bits, 2); if (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN)) { intra: macroblock_modes |= UBITS (bit_buf, 1) * DCT_TYPE_INTERLACED; DUMPBITS (bit_buf, bits, 1); } return macroblock_modes; } default: return 0; } } int k9requant::get_quantizer_scale () { int quantizer_scale_code; quantizer_scale_code = UBITS (bit_buf, 5); DUMPBITS (bit_buf, bits, 5); if (!quantizer_scale_code) { DEBF("illegal quant scale code: %d\n", quantizer_scale_code); sliceError++; quantizer_scale_code++; } if (q_scale_type) return non_linear_quantizer_scale[quantizer_scale_code]; else return quantizer_scale_code << 1; } void k9requant::get_motion_delta (const int f_code) { #define bit_buf (inbitbuf) const MVtab * tab; if (bit_buf & 0x80000000) { COPYBITS (bit_buf, bits, 1); return; } else if (bit_buf >= 0x0c000000) { tab = MV_4 + UBITS (bit_buf, 4); COPYBITS (bit_buf, bits, tab->len + 1); if (f_code) COPYBITS (bit_buf, bits, f_code); return; } else { tab = MV_10 + UBITS (bit_buf, 10); COPYBITS (bit_buf, bits, tab->len + 1); if (f_code) COPYBITS (bit_buf, bits, f_code); return; } } void k9requant::get_dmv () { const DMVtab * tab; tab = DMV_2 + UBITS (bit_buf, 2); COPYBITS (bit_buf, bits, tab->len); return; } int k9requant::get_coded_block_pattern () { #define bit_buf (inbitbuf) const CBPtab * tab; if (bit_buf >= 0x20000000) { tab = CBP_7 + (UBITS (bit_buf, 7) - 16); DUMPBITS (bit_buf, bits, tab->len); return tab->cbp; } else { tab = CBP_9 + UBITS (bit_buf, 9); DUMPBITS (bit_buf, bits, tab->len); return tab->cbp; } } int k9requant::get_luma_dc_dct_diff () { #define bit_buf (inbitbuf) #ifdef CHANGE_BRIGHTNESS #define DOBITS(x, y, z) DUMPBITS(x, y, z) #else #define DOBITS(x, y, z) COPYBITS(x, y, z) #endif const DCtab * tab; int size; int dc_diff; if (bit_buf < 0xf8000000) { tab = DC_lum_5 + UBITS (bit_buf, 5); size = tab->size; if (size) { DOBITS (bit_buf, bits, tab->len); //dc_diff = UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); dc_diff = UBITS (bit_buf, size); if (!(dc_diff >> (size - 1))) dc_diff = (dc_diff + 1) - (1 << size); DOBITS (bit_buf, bits, size); return dc_diff; } else { DOBITS (bit_buf, bits, 3); return 0; } } else { tab = DC_long + (UBITS (bit_buf, 9) - 0x1e0); size = tab->size; DOBITS (bit_buf, bits, tab->len); //dc_diff = UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); dc_diff = UBITS (bit_buf, size); if (!(dc_diff >> (size - 1))) dc_diff = (dc_diff + 1) - (1 << size); DOBITS (bit_buf, bits, size); return dc_diff; } } int k9requant::get_chroma_dc_dct_diff () { #define bit_buf (inbitbuf) const DCtab * tab; int size; int dc_diff; if (bit_buf < 0xf8000000) { tab = DC_chrom_5 + UBITS (bit_buf, 5); size = tab->size; if (size) { COPYBITS (bit_buf, bits, tab->len); //dc_diff = UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); dc_diff = UBITS (bit_buf, size); if (!(dc_diff >> (size - 1))) dc_diff = (dc_diff + 1) - (1 << size); COPYBITS (bit_buf, bits, size); return dc_diff; } else { COPYBITS (bit_buf, bits, 2); return 0; } } else { tab = DC_long + (UBITS (bit_buf, 10) - 0x3e0); size = tab->size; COPYBITS (bit_buf, bits, tab->len + 1); //dc_diff = UBITS (bit_buf, size) - UBITS (SBITS (~bit_buf, 1), size); dc_diff = UBITS (bit_buf, size); if (!(dc_diff >> (size - 1))) dc_diff = (dc_diff + 1) - (1 << size); COPYBITS (bit_buf, bits, size); return dc_diff; } } void k9requant::get_intra_block_B14 () { #define bit_buf (inbitbuf) int i, li; int val; const DCTtab * tab; li = i = 0; while (1) { if (bit_buf >= 0x28000000) { tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); i += tab->run; if (i >= 64) break; /* end of block */ normal_code: DUMPBITS (bit_buf, bits, tab->len); val = tab->level; val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); UPDATE_VAL if (val) { if (putAC(i - li - 1, val, 0)) break; li = i; } DUMPBITS (bit_buf, bits, 1); continue; } else if (bit_buf >= 0x04000000) { tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); i += tab->run; if (i < 64) goto normal_code; /* escape code */ i += (UBITS (bit_buf, 12) & 0x3F) - 64; if (i >= 64) { sliceError++; break; /* illegal, check needed to avoid buffer overflow */ } DUMPBITS (bit_buf, bits, 12); val = SBITS (bit_buf, 12); UPDATE_VAL if (val) { if (putAC(i - li - 1, val, 0)) break; li = i; } DUMPBITS (bit_buf, bits, 12); continue; } else if (bit_buf >= 0x02000000) { tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); i += tab->run; if (i < 64) goto normal_code; } else if (bit_buf >= 0x00800000) { tab = DCT_13 + (UBITS (bit_buf, 13) - 16); i += tab->run; if (i < 64) goto normal_code; } else if (bit_buf >= 0x00200000) { tab = DCT_15 + (UBITS (bit_buf, 15) - 16); i += tab->run; if (i < 64) goto normal_code; } else { tab = DCT_16 + UBITS (bit_buf, 16); DUMPBITS (bit_buf, bits, 16); i += tab->run; if (i < 64) goto normal_code; } sliceError++; break; /* illegal, check needed to avoid buffer overflow */ } COPYBITS (bit_buf, bits, 2); /* end of block code */ } void k9requant::get_intra_block_B15 () { #define bit_buf (inbitbuf) int i, li; int val; const DCTtab * tab; li = i = 0; while (1) { if (bit_buf >= 0x04000000) { tab = DCT_B15_8 + (UBITS (bit_buf, 8) - 4); i += tab->run; if (i < 64) { normal_code: DUMPBITS (bit_buf, bits, tab->len); val = tab->level; val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); UPDATE_VAL if (val) { if (putAC(i - li - 1, val, 1)) break; li = i; } DUMPBITS (bit_buf, bits, 1); continue; } else { if (i >= 128) break; /* end of block */ i += (UBITS (bit_buf, 12) & 0x3F) - 64; if (i >= 64) { sliceError++; break; /* illegal, check against buffer overflow */ } DUMPBITS (bit_buf, bits, 12); val = SBITS (bit_buf, 12); UPDATE_VAL if (val) { if (putAC(i - li - 1, val, 1)) break; li = i; } DUMPBITS (bit_buf, bits, 12); continue; } } else if (bit_buf >= 0x02000000) { tab = DCT_B15_10 + (UBITS (bit_buf, 10) - 8); i += tab->run; if (i < 64) goto normal_code; } else if (bit_buf >= 0x00800000) { tab = DCT_13 + (UBITS (bit_buf, 13) - 16); i += tab->run; if (i < 64) goto normal_code; } else if (bit_buf >= 0x00200000) { tab = DCT_15 + (UBITS (bit_buf, 15) - 16); i += tab->run; if (i < 64) goto normal_code; } else { tab = DCT_16 + UBITS (bit_buf, 16); DUMPBITS (bit_buf, bits, 16); i += tab->run; if (i < 64) goto normal_code; } sliceError++; break; /* illegal, check needed to avoid buffer overflow */ } COPYBITS (bit_buf, bits, 4); /* end of block code */ } int k9requant::get_non_intra_block_rq (RunLevel *blk) { #define bit_buf (inbitbuf) //int q = quantizer_scale; //int nq = new_quantizer_scale, tst = (nq / q) + ((nq % q) ? 1 : 0); int i, li; int val; const DCTtab * tab; li = i = -1; if (bit_buf >= 0x28000000) { tab = DCT_B14DC_5 + (UBITS (bit_buf, 5) - 5); goto entry_1; } else goto entry_2; while (1) { if (bit_buf >= 0x28000000) { tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); entry_1: i += tab->run; if (i >= 64) break; /* end of block */ normal_code: DUMPBITS (bit_buf, bits, tab->len); val = tab->level; val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); UPDATE_VAL if (val) { blk->level = val; blk->run = i - li - 1; li = i; blk++; } DUMPBITS (bit_buf, bits, 1); continue; } entry_2: if (bit_buf >= 0x04000000) { tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); i += tab->run; if (i < 64) goto normal_code; /* escape code */ i += (UBITS (bit_buf, 12) & 0x3F) - 64; if (i >= 64) { sliceError++; break; /* illegal, check needed to avoid buffer overflow */ } DUMPBITS (bit_buf, bits, 12); val = SBITS (bit_buf, 12); UPDATE_VAL if (val) { blk->level = val; blk->run = i - li - 1; li = i; blk++; } DUMPBITS (bit_buf, bits, 12); continue; } else if (bit_buf >= 0x02000000) { tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); i += tab->run; if (i < 64) goto normal_code; } else if (bit_buf >= 0x00800000) { tab = DCT_13 + (UBITS (bit_buf, 13) - 16); i += tab->run; if (i < 64) goto normal_code; } else if (bit_buf >= 0x00200000) { tab = DCT_15 + (UBITS (bit_buf, 15) - 16); i += tab->run; if (i < 64) goto normal_code; } else { tab = DCT_16 + UBITS (bit_buf, 16); DUMPBITS (bit_buf, bits, 16); i += tab->run; if (i < 64) goto normal_code; } sliceError++; break; /* illegal, check needed to avoid buffer overflow */ } DUMPBITS (bit_buf, bits, 2); /* dump end of block code */ blk->level = 0; return i; } int k9requant::get_non_intra_block_sav (RunLevel *blk, int cc) { #define bit_buf (inbitbuf) int i, li; int val; const DCTtab * tab; #ifdef P_FRAME_NON_INTRA_DROP #if (P_FRAME_NON_INTRA_DROP < 0) RunLevel *oblk = blk; #else int oval; #endif #endif li = i = -1; if (bit_buf >= 0x28000000) { tab = DCT_B14DC_5 + (UBITS (bit_buf, 5) - 5); goto entry_1; } else goto entry_2; while (1) { if (bit_buf >= 0x28000000) { tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); entry_1: i += tab->run; if (i >= 64) break; /* end of block */ normal_code: DUMPBITS (bit_buf, bits, tab->len); val = tab->level; val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); SAVE_VAL if (li == -1) { if (abs(val) < abs(mb_sav_lev)) { mb_sav_c = cc; mb_sav_lev = val; mb_sav_run = i - li - 1; } } UPDATE_VAL WRITE_VAL DUMPBITS (bit_buf, bits, 1); continue; } entry_2: if (bit_buf >= 0x04000000) { tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); i += tab->run; if (i < 64) goto normal_code; /* escape code */ i += (UBITS (bit_buf, 12) & 0x3F) - 64; if (i >= 64) { sliceError++; break; /* illegal, check needed to avoid buffer overflow */ } DUMPBITS (bit_buf, bits, 12); val = SBITS (bit_buf, 12); SAVE_VAL if (li == -1) { if (abs(val) < abs(mb_sav_lev)) { mb_sav_c = cc; mb_sav_lev = val; mb_sav_run = i - li - 1; } } UPDATE_VAL WRITE_VAL DUMPBITS (bit_buf, bits, 12); continue; } else if (bit_buf >= 0x02000000) { tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); i += tab->run; if (i < 64) goto normal_code; } else if (bit_buf >= 0x00800000) { tab = DCT_13 + (UBITS (bit_buf, 13) - 16); i += tab->run; if (i < 64) goto normal_code; } else if (bit_buf >= 0x00200000) { tab = DCT_15 + (UBITS (bit_buf, 15) - 16); i += tab->run; if (i < 64) goto normal_code; } else { tab = DCT_16 + UBITS (bit_buf, 16); DUMPBITS (bit_buf, bits, 16); i += tab->run; if (i < 64) goto normal_code; } sliceError++; break; /* illegal, check needed to avoid buffer overflow */ } DUMPBITS (bit_buf, bits, 2); /* dump end of block code */ #ifdef P_FRAME_NON_INTRA_DROP #if (P_FRAME_NON_INTRA_DROP < 0) blk -= (int)((blk - oblk) * (stress_factor / P_FRAME_NON_INTRA_DROP)); #ifdef DEMO if ((gopCount & 0x7F) < 10) blk = oblk; #endif #endif #endif blk->level = 0; return i; } #ifdef P_FRAME_NON_INTRA_DROP int k9requant::get_non_intra_block_drop (RunLevel *blk, int cc) { #define bit_buf (inbitbuf) int i, li; int val; const DCTtab * tab; #if (P_FRAME_NON_INTRA_DROP < 0) RunLevel *oblk = blk; #else int oval; #endif li = i = -1; if (bit_buf >= 0x28000000) { tab = DCT_B14DC_5 + (UBITS (bit_buf, 5) - 5); goto entry_1; } else goto entry_2; while (1) { if (bit_buf >= 0x28000000) { tab = DCT_B14AC_5 + (UBITS (bit_buf, 5) - 5); entry_1: i += tab->run; if (i >= 64) break; /* end of block */ normal_code: DUMPBITS (bit_buf, bits, tab->len); val = tab->level; val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1); SAVE_VAL UPDATE_VAL WRITE_VAL DUMPBITS (bit_buf, bits, 1); continue; } entry_2: if (bit_buf >= 0x04000000) { tab = DCT_B14_8 + (UBITS (bit_buf, 8) - 4); i += tab->run; if (i < 64) goto normal_code; /* escape code */ i += (UBITS (bit_buf, 12) & 0x3F) - 64; if (i >= 64) { sliceError++; break; /* illegal, check needed to avoid buffer overflow */ } DUMPBITS (bit_buf, bits, 12); val = SBITS (bit_buf, 12); SAVE_VAL UPDATE_VAL WRITE_VAL DUMPBITS (bit_buf, bits, 12); continue; } else if (bit_buf >= 0x02000000) { tab = DCT_B14_10 + (UBITS (bit_buf, 10) - 8); i += tab->run; if (i < 64) goto normal_code; } else if (bit_buf >= 0x00800000) { tab = DCT_13 + (UBITS (bit_buf, 13) - 16); i += tab->run; if (i < 64) goto normal_code; } else if (bit_buf >= 0x00200000) { tab = DCT_15 + (UBITS (bit_buf, 15) - 16); i += tab->run; if (i < 64) goto normal_code; } else { tab = DCT_16 + UBITS (bit_buf, 16); DUMPBITS (bit_buf, bits, 16); i += tab->run; if (i < 64) goto normal_code; } sliceError++; break; /* illegal, check needed to avoid buffer overflow */ } DUMPBITS (bit_buf, bits, 2); /* dump end of block code */ #if (P_FRAME_NON_INTRA_DROP < 0) blk -= (int)((blk - oblk) * (stress_factor / P_FRAME_NON_INTRA_DROP)); #ifdef DEMO if ((gopCount & 0x7F) < 10) blk = oblk; #endif #endif blk->level = 0; return i; } #endif #ifdef CHANGE_BRIGHTNESS void k9requant::putDC(const sVLCtable *tab, int val) { int absval, size; absval = abs(val); size = 0; while (absval) { absval >>= 1; size++; } putbits(tab[size].code,tab[size].len); if (size!=0) { if (val>=0) absval = val; else absval = val + (1< (255 << intra_dc_precision)) val = 255 << intra_dc_precision; else if (val < 0) val = 0; bri = val - (128 << intra_dc_precision); new_dc_pred = val; dc_reset = 0; } else { val = bri + old_dc_pred; old_dc_pred = val; val += delta_bright << intra_dc_precision; if (val > (255 << intra_dc_precision)) val = 255 << intra_dc_precision; else if (val < 0) val = 0; bri = val - new_dc_pred; new_dc_pred = val; } putDC(DClumtab, bri); } #else if (cc == 0) get_luma_dc_dct_diff (); #endif else get_chroma_dc_dct_diff (); if (intra_vlc_format) get_intra_block_B15 (); else get_intra_block_B14 (); } void k9requant::slice_non_intra_DCT (int cur_block) { #ifdef P_FRAME_NON_INTRA_DROP if (picture_coding_type == P_TYPE) { if ((h_offset == 0) || (h_offset == horizontal_size_value - 16)) get_non_intra_block_sav(block[cur_block], cur_block); else get_non_intra_block_drop(block[cur_block], cur_block); } else get_non_intra_block_rq(block[cur_block]); #else if ((picture_coding_type == P_TYPE) && ((h_offset == 0) || (h_offset == horizontal_size_value - 16))) get_non_intra_block_sav(block[cur_block], cur_block); else get_non_intra_block_rq(block[cur_block]); #endif } void k9requant::motion_fr_frame ( uint f_code[2] ) { get_motion_delta (f_code[0]); get_motion_delta (f_code[1]); } void k9requant::motion_fr_field ( uint f_code[2] ) { COPYBITS (bit_buf, bits, 1); get_motion_delta (f_code[0]); get_motion_delta (f_code[1]); COPYBITS (bit_buf, bits, 1); get_motion_delta (f_code[0]); get_motion_delta (f_code[1]); } void k9requant::motion_fr_dmv ( uint f_code[2] ) { get_motion_delta (f_code[0]); get_dmv (); get_motion_delta (f_code[1]); get_dmv (); } void k9requant::motion_fr_conceal ( ) { get_motion_delta (f_code[0][0]); get_motion_delta (f_code[0][1]); COPYBITS (bit_buf, bits, 1); } void k9requant::motion_fi_field ( uint f_code[2] ) { COPYBITS (bit_buf, bits, 1); get_motion_delta (f_code[0]); get_motion_delta (f_code[1]); } void k9requant::motion_fi_16x8 ( uint f_code[2] ) { COPYBITS (bit_buf, bits, 1); get_motion_delta (f_code[0]); get_motion_delta (f_code[1]); COPYBITS (bit_buf, bits, 1); get_motion_delta (f_code[0]); get_motion_delta (f_code[1]); } void k9requant::motion_fi_dmv ( uint f_code[2] ) { get_motion_delta (f_code[0]); get_dmv (); get_motion_delta (f_code[1]); get_dmv (); } void k9requant::motion_fi_conceal () { COPYBITS (bit_buf, bits, 1); get_motion_delta (f_code[0][0]); get_motion_delta (f_code[0][1]); COPYBITS (bit_buf, bits, 1); } void k9requant::putmbdata(int macroblock_modes) { putmbtype(macroblock_modes & 0x1F); /*switch (picture_coding_type) { case I_TYPE: if ((! (frame_pred_frame_dct)) && (picture_structure == FRAME_PICTURE)) putbits(macroblock_modes & DCT_TYPE_INTERLACED ? 1 : 0, 1); break; case P_TYPE: if (picture_structure != FRAME_PICTURE) { if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) putbits((macroblock_modes & MOTION_TYPE_MASK) / MOTION_TYPE_BASE, 2); break; } else if (frame_pred_frame_dct) break; else { if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) putbits((macroblock_modes & MOTION_TYPE_MASK) / MOTION_TYPE_BASE, 2); if (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN)) putbits(macroblock_modes & DCT_TYPE_INTERLACED ? 1 : 0, 1); break; } case B_TYPE: if (picture_structure != FRAME_PICTURE) { if (! (macroblock_modes & MACROBLOCK_INTRA)) putbits((macroblock_modes & MOTION_TYPE_MASK) / MOTION_TYPE_BASE, 2); break; } else if (frame_pred_frame_dct) break; else { if (macroblock_modes & MACROBLOCK_INTRA) goto intra; putbits((macroblock_modes & MOTION_TYPE_MASK) / MOTION_TYPE_BASE, 2); if (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN)) { intra: putbits(macroblock_modes & DCT_TYPE_INTERLACED ? 1 : 0, 1); } break; } }*/ if (macroblock_modes & (MACROBLOCK_MOTION_FORWARD | MACROBLOCK_MOTION_BACKWARD)) { if (picture_structure == FRAME_PICTURE) { if (frame_pred_frame_dct == 0) { putbits((macroblock_modes & MOTION_TYPE_MASK) / MOTION_TYPE_BASE, 2); } } else { putbits((macroblock_modes & MOTION_TYPE_MASK) / MOTION_TYPE_BASE, 2); } } if ((picture_structure == FRAME_PICTURE) && (frame_pred_frame_dct == 0) && (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN))) { putbits(macroblock_modes & DCT_TYPE_INTERLACED ? 1 : 0, 1); } } void k9requant::put_quantiser(int quantiser) { putbits(q_scale_type ? map_non_linear_mquant[quantiser] : quantiser >> 1, 5); last_coded_scale = quantiser; } void k9requant::putaddrinc(int addrinc) { mb_out += addrinc; //LOGF("mb_out: %i\n", mb_out); if (mb_out > (horizontal_size_value >> 4)) { sliceError++; //LOGF("mb_out: %i, hsv: %i, curo: %i\n", mb_out, horizontal_size_value, (int)outbytecnt + (wbuf - owbuf)); } while (addrinc>33) { putbits(0x08,11); /* macroblock_escape */ addrinc-= 33; } assert( addrinc >= 1 && addrinc <= 33 ); putbits(addrinctab[addrinc-1].code,addrinctab[addrinc-1].len); } int k9requant::slice_init (int code) { #define bit_buf (inbitbuf) int offset; const MBAtab * mba; mb_out = 0; v_offset = (code - 1) * 16; quantizer_scale = get_quantizer_scale (); new_quantizer_scale = getNewQuant(quantizer_scale, 0); put_quantiser(new_quantizer_scale); /* ignore intra_slice and all the extra data */ while (bit_buf & 0x80000000) { DUMPBITS (bit_buf, bits, 9); } /* decode initial macroblock address increment */ offset = 0; while (1) { if (bit_buf >= 0x08000000) { mba = MBA_5 + (UBITS (bit_buf, 6) - 2); break; } else if (bit_buf >= 0x01800000) { mba = MBA_11 + (UBITS (bit_buf, 12) - 24); break; } else switch (UBITS (bit_buf, 12)) { case 8: /* macroblock_escape */ offset += 33; DUMPBITS (bit_buf, bits, 11); continue; default: /* error */ sliceError++; return 1; } } mb_add = offset + mba->mba + 1; mb_skip = 0; COPYBITS (bit_buf, bits, 1); DUMPBITS(bit_buf, bits, mba->len); h_offset = (offset + mba->mba) << 4; while (h_offset - (int)horizontal_size_value >= 0) { h_offset -= horizontal_size_value; v_offset += 16; } if (v_offset > (vertical_size_value - 16)) return 1; return 0; } void k9requant::mpeg2_slice ( const int code ) { #define bit_buf (inbitbuf) #ifdef CHANGE_BRIGHTNESS dc_reset = 1; #endif if (slice_init (code)) return; while (1) { int macroblock_modes; int mba_inc; const MBAtab * mba; macroblock_modes = get_macroblock_modes (); if (macroblock_modes & MACROBLOCK_QUANT) quantizer_scale = get_quantizer_scale (); if (macroblock_modes & MACROBLOCK_INTRA) { #ifdef STAT if (picture_coding_type == P_TYPE) cnt_p_i++; else if (picture_coding_type == B_TYPE) cnt_b_i++; #endif new_quantizer_scale = getNewQuant(quantizer_scale, 1); if (last_coded_scale == new_quantizer_scale) macroblock_modes &= 0xFFFFFFEF; // remove MACROBLOCK_QUANT else macroblock_modes |= MACROBLOCK_QUANT; //add MACROBLOCK_QUANT putaddrinc(mb_add + mb_skip); mb_skip = 0; putmbdata(macroblock_modes); if (macroblock_modes & MACROBLOCK_QUANT) put_quantiser(new_quantizer_scale); if (concealment_motion_vectors) { if (picture_structure == FRAME_PICTURE) motion_fr_conceal (); else motion_fi_conceal (); } curTable = quant_tables[quant_equ[quantizer_scale]][quant_equ[new_quantizer_scale]]; if (!curTable) { /*DEBF("Inv. curTable: qs: %i nqs: %i qe_qs: %i qe_nqs: %i\n", quantizer_scale, new_quantizer_scale, quant_equ[quantizer_scale], quant_equ[new_quantizer_scale]);*/ curTable = quant_table_id; } slice_intra_DCT ( 0); slice_intra_DCT ( 0); slice_intra_DCT ( 0); slice_intra_DCT ( 0); slice_intra_DCT ( 1); slice_intra_DCT ( 2); } else { int new_coded_block_pattern = 0; // begin saving data int batb; uint8 n_owbuf[32], *n_wbuf, *o_owbuf, *o_wbuf; uint32 n_outbitcnt, n_outbitbuf, o_outbitcnt, o_outbitbuf; #ifdef CHANGE_BRIGHTNESS dc_reset = 1; #endif #define PUSH_BIT_IO \ o_owbuf = owbuf; o_wbuf = wbuf; \ o_outbitcnt = outbitcnt; o_outbitbuf = outbitbuf; \ owbuf = wbuf = n_owbuf; \ outbitcnt = BITS_IN_BUF; outbitbuf = 0; #define POP_BIT_IO \ n_wbuf = wbuf; \ n_outbitcnt = outbitcnt; n_outbitbuf = outbitbuf; \ owbuf = o_owbuf; wbuf = o_wbuf; \ outbitcnt = o_outbitcnt; outbitbuf = o_outbitbuf; PUSH_BIT_IO if (picture_structure == FRAME_PICTURE) switch (macroblock_modes & MOTION_TYPE_MASK) { case MC_FRAME: MOTION_CALL (motion_fr_frame, macroblock_modes); break; case MC_FIELD: MOTION_CALL (motion_fr_field, macroblock_modes); break; case MC_DMV: MOTION_CALL (motion_fr_dmv, MACROBLOCK_MOTION_FORWARD); break; } else switch (macroblock_modes & MOTION_TYPE_MASK) { case MC_FIELD: MOTION_CALL (motion_fi_field, macroblock_modes); break; case MC_16X8: MOTION_CALL (motion_fi_16x8, macroblock_modes); break; case MC_DMV: MOTION_CALL (motion_fi_dmv, MACROBLOCK_MOTION_FORWARD); break; } POP_BIT_IO // end saving data #ifdef STAT if (picture_coding_type == P_TYPE) cnt_p_ni++; else if (picture_coding_type == B_TYPE) cnt_b_ni++; #endif new_quantizer_scale = getNewQuant(quantizer_scale, 0); if (macroblock_modes & MACROBLOCK_PATTERN) { int coded_block_pattern = get_coded_block_pattern (); mb_sav_lev = 0xFFFF; curTable = quant_tables[quant_equ[quantizer_scale]][quant_equ[new_quantizer_scale]]; if (!curTable) { /*DEBF("Inv. curTable: qs: %i nqs: %i qe_qs: %i qe_nqs: %i\n", quantizer_scale, new_quantizer_scale, quant_equ[quantizer_scale], quant_equ[new_quantizer_scale]);*/ curTable = quant_table_id; } if (coded_block_pattern & 0x20) { slice_non_intra_DCT(0); if (isNotEmpty(block[0])) new_coded_block_pattern |= 0x20; } if (coded_block_pattern & 0x10) { slice_non_intra_DCT(1); if (isNotEmpty(block[1])) new_coded_block_pattern |= 0x10; } if (coded_block_pattern & 0x08) { slice_non_intra_DCT(2); if (isNotEmpty(block[2])) new_coded_block_pattern |= 0x08; } if (coded_block_pattern & 0x04) { slice_non_intra_DCT(3); if (isNotEmpty(block[3])) new_coded_block_pattern |= 0x04; } if (coded_block_pattern & 0x02) { slice_non_intra_DCT(4); if (isNotEmpty(block[4])) new_coded_block_pattern |= 0x02; } if (coded_block_pattern & 0x01) { slice_non_intra_DCT(5); if (isNotEmpty(block[5])) new_coded_block_pattern |= 0x01; } #ifdef P_FRAME_NON_INTRA_DROP if (picture_coding_type == P_TYPE) new_quantizer_scale = quantizer_scale; #endif if (!new_coded_block_pattern) { macroblock_modes &= 0xFFFFFFED; // remove MACROBLOCK_PATTERN and MACROBLOCK_QUANT flag if ( (picture_coding_type == P_TYPE) && !(macroblock_modes & MACROBLOCK_MOTION_FORWARD)) { assert(n_wbuf == n_owbuf); assert(n_outbitcnt == BITS_IN_BUF); if ((h_offset == 0) || (h_offset == horizontal_size_value - 16)) // can't skip last mb { // we can't transmit mv (0,0) since PMV could be different than 0 for last block // so we transmit the single smallest coeff. instead unrequantised // anyway this is likely to take no more bit than transmiting a null mv.... assert((mb_sav_lev) && (mb_sav_lev != 0xFFFF)); new_coded_block_pattern = 1 << (5 - mb_sav_c); macroblock_modes |= MACROBLOCK_PATTERN; new_quantizer_scale = quantizer_scale; block[mb_sav_c][0].run = mb_sav_run; block[mb_sav_c][0].level = mb_sav_lev; block[mb_sav_c][1].run = 0; block[mb_sav_c][1].level = 0; } else { mb_skip += mb_add; goto skip_mb; } } } } if (last_coded_scale == new_quantizer_scale) macroblock_modes &= 0xFFFFFFEF; // remove MACROBLOCK_QUANT else if (macroblock_modes & MACROBLOCK_PATTERN) macroblock_modes |= MACROBLOCK_QUANT; //add MACROBLOCK_QUANT assert( (macroblock_modes & MACROBLOCK_PATTERN) || !(macroblock_modes & MACROBLOCK_QUANT) ); putaddrinc(mb_add + mb_skip); mb_skip = 0; putmbdata(macroblock_modes); if (macroblock_modes & MACROBLOCK_QUANT) put_quantiser(new_quantizer_scale); // put saved motion data... for (batb = 0; batb < (n_wbuf - n_owbuf); batb++) putbits(n_owbuf[batb], 8); putbits(n_outbitbuf, BITS_IN_BUF - n_outbitcnt); // end saved motion data... if (macroblock_modes & MACROBLOCK_PATTERN) { putcbp(new_coded_block_pattern); if (new_coded_block_pattern & 0x20) putnonintrablk(block[0]); if (new_coded_block_pattern & 0x10) putnonintrablk(block[1]); if (new_coded_block_pattern & 0x08) putnonintrablk(block[2]); if (new_coded_block_pattern & 0x04) putnonintrablk(block[3]); if (new_coded_block_pattern & 0x02) putnonintrablk(block[4]); if (new_coded_block_pattern & 0x01) putnonintrablk(block[5]); } } skip_mb: NEXT_MACROBLOCK; mba_inc = 0; while (1) { if (bit_buf >= 0x10000000) { mba = MBA_5 + (UBITS (bit_buf, 5) - 2); break; } else if (bit_buf >= 0x03000000) { mba = MBA_11 + (UBITS (bit_buf, 11) - 24); break; } else switch (UBITS (bit_buf, 11)) { case 8: /* macroblock_escape */ mba_inc += 33; DUMPBITS (bit_buf, bits, 11); continue; default: /* end of slice, or error */ //LOGF("hoffset: %i, hsv: %i, curo: %i\n", h_offset, horizontal_size_value, (int)outbytecnt + (wbuf - owbuf)); if (h_offset != 0) sliceError++; return; } } DUMPBITS (bit_buf, bits, mba->len); //PPP mba_inc += mba->mba; mb_add = mba_inc + 1; #ifdef CHANGE_BRIGHTNESS if (mba_inc) dc_reset = 1; #endif if (mba_inc) do { NEXT_MACROBLOCK; } while (--mba_inc); } } /////---- end ext mpeg code void k9requant::run () { uint8 ID, found; int64 greedyFactor, greedyFactor2; int i; #ifdef DEMO gopCount = 0; #endif #ifdef LOG_RATE_CONTROL LOG_FILE = fopen("Logfile.txt", "w"); #endif #ifdef STAT ori_i = ori_p = ori_b = 0; new_i = new_p = new_b = 0; cnt_i = cnt_p = cnt_b = 0; cnt_p_i = cnt_p_ni = 0; cnt_b_i = cnt_b_ni = 0; #endif #ifdef USE_FD if (argc < 3) { USAGE } ifd = fopen(argv[argc - 2], "rb"); ofd = fopen(argv[argc - 1], "wb"); if (!ifd) { LOGF("Bad input path! (%s)\n", argv[argc - 2]); return 2; } if (!ofd) { LOGF("Bad output path! (%s)\n", argv[argc - 1]); return 2; } argc -= 2; #endif #ifndef THREAD rbuf = cbuf = orbuf = malloc(BUF_SIZE); wbuf = owbuf = malloc(BUF_SIZE); inbytecnt = outbytecnt = 0; eof = 0; #endif validPicHeader = 0; validSeqHeader = 0; validExtHeader = 0; #ifndef THREAD // argument parsing #ifdef CHANGE_BRIGHTNESS if (argc < 5) { USAGE } delta_bright = atoi(argv[4]); #else if (argc < 4) { USAGE } #endif fact_x = atof(argv[1]); sscanf(argv[3], "%lld", &orim2vsize); #endif #ifdef THREAD orim2vsize=rqt_visize; fact_x = rqt_fact; #endif greedyFactor = orim2vsize / 100; greedyFactor2 = orim2vsize / 50; #ifndef THREAD if (fact_x <= 1.0) { unsigned char buf[4096]; while(1) { int i = read(0, buf, 4096); if (i > 0) write(1, buf, i); else return 0; } } #endif if (fact_x > 10.0) fact_x = 10.0; // factor and stresses setting initRequant(); // fill quant table // id table for (i = -2048; i <= 2047; i++) quant_table_id[i] = i; // other tables for (i = 0; i < 42; i++) { int q = quantisers[i]; int j; for (j = i + 1; j < 42; j++) { int nq = quantisers[j]; int k; short *cTab = quant_tables[quant_equ[q]][quant_equ[nq]]; for (k = -2048; k <= 2047; k++) { int ov = k*q; int t = ov / nq; if (fact_x <= max_alt_table) { int t2, t3; int d, d2, d3; int nv, nv2, nv3; t2 = t + 1; t3 = t - 1; nv = t * nq; nv2 = t2 * nq; nv3 = t3 * nq; d = abs(nv - ov); d2 = abs(nv2 - ov); d3 = abs(nv3 - ov); if (d2 < d) { d = d2; t = t2; } if (d3 < d) t = t3; } if (t > 2047) t = 2047; else if (t < -2048) t = -2048; cTab[k] = t; } } } #ifndef THREAD LOG("M2VRequantiser by Makira.\n"); #ifdef WIN fprintf(stderr, "Using %f as factor, %lld as m2v size.\n", fact_x, orim2vsize); #else LOGF("Using %f as factor, %lld as m2v size.\n", fact_x, orim2vsize); #endif #endif // recoding while(1) { // get next start code prefix found = 0; while (!found) { #ifndef REMOVE_BYTE_STUFFING LOCK(3) #else LOCK(8) if ( (cbuf[7] == 0) && (cbuf[6] == 0) && (cbuf[5] == 0) && (cbuf[4] == 0) && (cbuf[3] == 0) && (cbuf[2] == 0) && (cbuf[1] == 0) && (cbuf[0] == 0) ) { SEEKR(1) } else #endif if ( (cbuf[0] == 0) && (cbuf[1] == 0) && (cbuf[2] == 1) ) found = 1; // start code ! else { COPY(1) } // continue search } COPY(3) // get start code LOCK(1) ID = cbuf[0]; COPY(1) if (ID == 0x00) // pic header { LOCK(4) picture_coding_type = (cbuf[1] >> 3) & 0x7; if (picture_coding_type < 1 || picture_coding_type > 3) { DEBF("illegal picture_coding_type: %i\n", picture_coding_type); validPicHeader = 0; } else { validPicHeader = 1; cbuf[1] |= 0x7; cbuf[2] = 0xFF; cbuf[3] |= 0xF8; // vbv_delay is now 0xFFFF } validExtHeader = 0; COPY(4) } else if (ID == 0xB3) // seq header { LOCK(8) horizontal_size_value = (cbuf[0] << 4) | (cbuf[1] >> 4); vertical_size_value = ((cbuf[1] & 0xF) << 8) | cbuf[2]; if ( horizontal_size_value > 720 || horizontal_size_value < 352 || vertical_size_value > 576 || vertical_size_value < 480 || (horizontal_size_value & 0xF) || (vertical_size_value & 0xF)) { DEBF("illegal size, hori: %i verti: %i\n", horizontal_size_value, vertical_size_value); validSeqHeader = 0; } else validSeqHeader = 1; validPicHeader = 0; validExtHeader = 0; COPY(8) } else if (ID == 0xB5) // extension { LOCK(1) if ((cbuf[0] >> 4) == 0x8) // pic coding ext { LOCK(5) f_code[0][0] = (cbuf[0] & 0xF) - 1; f_code[0][1] = (cbuf[1] >> 4) - 1; f_code[1][0] = (cbuf[1] & 0xF) - 1; f_code[1][1] = (cbuf[2] >> 4) - 1; intra_dc_precision = (cbuf[2] >> 2) & 0x3; picture_structure = cbuf[2] & 0x3; frame_pred_frame_dct = (cbuf[3] >> 6) & 0x1; concealment_motion_vectors = (cbuf[3] >> 5) & 0x1; q_scale_type = (cbuf[3] >> 4) & 0x1; intra_vlc_format = (cbuf[3] >> 3) & 0x1; alternate_scan = (cbuf[3] >> 2) & 0x1; if ( (f_code[0][0] > 8 && f_code[0][0] < 14) || (f_code[0][1] > 8 && f_code[0][1] < 14) || (f_code[1][0] > 8 && f_code[1][0] < 14) || (f_code[1][1] > 8 && f_code[1][1] < 14) || picture_structure == 0) { DEBF("illegal ext, f_code[0][0]: %i f_code[0][1]: %i f_code[1][0]: %i f_code[1][1]: %i picture_structure:%i\n", f_code[0][0], f_code[0][1], f_code[1][0], f_code[1][1], picture_structure); validExtHeader = 0; } else validExtHeader = 1; COPY(5) } else { COPY(1) } } else if (ID == 0xB8) // gop header { LOCK(4) COPY(4) #ifdef DEMO gopCount++; #endif } else if ((ID >= 0x01) && (ID <= 0xAF) && validPicHeader && validSeqHeader && validExtHeader) // slice { uint8 *outTemp = wbuf, *inTemp = cbuf; int64 threshold; bytediff = (outbytecnt + (wbuf - owbuf)) - ((inbytecnt - (rbuf - cbuf)) / fact_x); if (inbytecnt < greedyFactor2) threshold = inbytecnt >> 1; else if (orim2vsize - inbytecnt < greedyFactor2) threshold = (orim2vsize - inbytecnt) >> 1; else threshold = greedyFactor; if (threshold < 1024) threshold = 1024; stress_factor = (float)(bytediff + threshold) / (float)(threshold << 1); if (stress_factor > 1.0f) stress_factor = 1.0f; else if (stress_factor < 0.0f) stress_factor = 0.0f; #ifdef LOG_RATE_CONTROL /*fprintf(LOG_FILE, "%f%%: Requested: %f Current: %f Delta: %lld Threshold: %f Stress: %f\n", (float)(100.0f*inbytecnt)/orim2vsize, // percent (float)fact_x, // requested (float)(inbytecnt - (rbuf - cbuf))/(float)(outbytecnt + (wbuf - owbuf)), // current (long long)bytediff, // delta (float)threshold, // threshold stress_factor // Stress );*/ fprintf(LOG_FILE, "inb: %.0f inb_c: %.0f oub: %.0f oub_c: %.0f cur: %.3f dif: %.0f thr: %.0f str: %.03f\n", (float)inbytecnt, (float)(inbytecnt - (rbuf - cbuf)), (float)outbytecnt, (float)(outbytecnt + (wbuf - owbuf)), (float)(inbytecnt - (rbuf - cbuf))/(float)(outbytecnt + (wbuf - owbuf)), (float)bytediff, (float)threshold, (float)stress_factor ); #endif #ifndef CHANGE_BRIGHTNESS if ( ((picture_coding_type == I_TYPE) && ( stress_factor > i_min_stress)) || ((picture_coding_type == P_TYPE) && ( stress_factor > p_min_stress)) || ((picture_coding_type == B_TYPE) && ( stress_factor > b_min_stress)) #ifdef DEMO || ((gopCount & 0x7F) < 10) #endif ) #endif { // init error sliceError = 0; // init bit buffer inbitbuf = 0; inbitcnt = 0; outbitbuf = 0; outbitcnt = BITS_IN_BUF; // get 32 bits Refill_bits(); Refill_bits(); Refill_bits(); Refill_bits(); // begin bit level recoding mpeg2_slice(ID); flush_read_buffer(); flush_write_buffer(); // end bit level recoding #ifndef CHANGE_BRIGHTNESS if ((wbuf - outTemp > cbuf - inTemp) || (sliceError > MAX_ERRORS)) // yes that might happen, rarely { #ifndef NDEBUG if (sliceError > MAX_ERRORS) { DEBF("sliceError (%i) > MAX_ERRORS (%i)\n", sliceError, MAX_ERRORS); } #endif // in this case, we'll just use the original slice ! memcpy(outTemp, inTemp, cbuf - inTemp); wbuf = outTemp + (cbuf - inTemp); // adjust outbytecnt outbytecnt -= (wbuf - outTemp) - (cbuf - inTemp); } #endif #ifdef STAT #ifdef LOG_RATE_CONTROL if (picture_coding_type == I_TYPE) fprintf(LOG_FILE, "-I-\n"); #endif switch(picture_coding_type) { case I_TYPE: ori_i += cbuf - inTemp; new_i += (wbuf - outTemp > cbuf - inTemp) ? (cbuf - inTemp) : (wbuf - outTemp); cnt_i ++; break; case P_TYPE: ori_p += cbuf - inTemp; new_p += (wbuf - outTemp > cbuf - inTemp) ? (cbuf - inTemp) : (wbuf - outTemp); cnt_p ++; break; case B_TYPE: ori_b += cbuf - inTemp; new_b += (wbuf - outTemp > cbuf - inTemp) ? (cbuf - inTemp) : (wbuf - outTemp); cnt_b ++; break; default: assert(0); break; } #endif } } #ifndef NDEBUG if ((ID >= 0x01) && (ID <= 0xAF) && (!validPicHeader || !validSeqHeader || !validExtHeader)) { if (!validPicHeader) DEBF("missing pic header (%02X)\n", ID); if (!validSeqHeader) DEBF("missing seq header (%02X)\n", ID); if (!validExtHeader) DEBF("missing ext header (%02X)\n", ID); } #endif if (rbuf - orbuf > MAX_READ) { MOV_READ } if (wbuf - owbuf > MIN_WRITE) { WRITE } } #ifdef LOG_RATE_CONTROL fclose(LOG_FILE); #endif rqt_run=false; // keeps gcc happy return ; } void k9requant::initvar() { cbuf = NULL; rbuf = NULL; wbuf = NULL; orbuf = NULL; owbuf = NULL; inbitcnt = outbitcnt = 0; inbitbuf = outbitbuf = 0; inbytecnt = outbytecnt = 0; fact_x = 0; mloka1 = mloka2 = eof = 0; orim2vsize = 0; bytediff = 0; stress_factor = 0; i_factor = 0; p_factor = 0; b_factor = 0; i_min_stress = 0; p_min_stress = 0; b_min_stress = 0; quant_table_id = &quant_table_id_data[2048]; horizontal_size_value = 0; vertical_size_value = 0; picture_coding_type = 0; memset( f_code,0 , sizeof(f_code)); intra_dc_precision = 0; picture_structure = 0; frame_pred_frame_dct = 0; concealment_motion_vectors = 0; q_scale_type = 0; intra_vlc_format = 0; alternate_scan = 0; validPicHeader = 0; validSeqHeader = 0; validExtHeader = 0; sliceError = 0; quantizer_scale = 0; new_quantizer_scale = 0; last_coded_scale = 0; h_offset = v_offset = 0; mb_skip = mb_add = 0; mb_out = 0; mb_sav_run = mb_sav_lev = mb_sav_c = 0; curTable = NULL; memset( block, 0, sizeof(block)); } void k9requant::initRequant() { if (fact_x <= 1.0) { i_factor = i_factors[0]; p_factor = p_factors[0]; b_factor = b_factors[0]; i_min_stress = i_min_stresses[0]; p_min_stress = p_min_stresses[0]; b_min_stress = b_min_stresses[0]; } else if (fact_x >= 10.0) { i_factor = i_factors[2]; p_factor = p_factors[2]; b_factor = b_factors[2]; i_min_stress = i_min_stresses[2]; p_min_stress = p_min_stresses[2]; b_min_stress = b_min_stresses[2]; } else if (fact_x <= 3.0) // 1.0 .. 3.0 { double inter = (fact_x - 1.0)/(3.0 - 1.0); i_factor = i_factors[0] + inter * (i_factors[1] - i_factors[0]); p_factor = p_factors[0] + inter * (p_factors[1] - p_factors[0]); b_factor = b_factors[0] + inter * (b_factors[1] - b_factors[0]); i_min_stress = i_min_stresses[0] + inter * (i_min_stresses[1] - i_min_stresses[0]); p_min_stress = p_min_stresses[0] + inter * (p_min_stresses[1] - p_min_stresses[0]); b_min_stress = b_min_stresses[0] + inter * (b_min_stresses[1] - b_min_stresses[0]); } else // 3.0 .. 10.0 { double inter = (fact_x - 3.0)/(10.0 - 3.0); i_factor = i_factors[1] + inter * (i_factors[2] - i_factors[1]); p_factor = p_factors[1] + inter * (p_factors[2] - p_factors[1]); b_factor = b_factors[1] + inter * (b_factors[2] - b_factors[1]); i_min_stress = i_min_stresses[1] + inter * (i_min_stresses[2] - i_min_stresses[1]); p_min_stress = p_min_stresses[1] + inter * (p_min_stresses[2] - p_min_stresses[1]); b_min_stress = b_min_stresses[1] + inter * (b_min_stresses[2] - b_min_stresses[1]); } /*LOGF( "i_factor: %i p_factor: %i b_factor: %i\n" "i_min_stress: %.02f p_min_stress: %.02f b_min_stress: %.02f\n", i_factor, p_factor, b_factor, i_min_stress, p_min_stress, b_min_stress);*/ } bool k9requant::lock( int64 x) { if (unlikely ((x) > (rbuf - cbuf))) { if (likely (wbuf)) { QMutexLocker locker( &mutw ); //mutw.lock(); rqt_wcnt = wbuf - owbuf; condw.wakeAll(); //mutw.unlock(); } //mutr.lock(); QMutexLocker locker( &mutr ); while (!rqt_rcnt) { condr.wait( &mutr); if (rqt_stop==true) { //mutr.unlock(); return false; } } cbuf = rqt_rptr; //src buffer rbuf =orbuf = cbuf; rbuf += rqt_rcnt + 3; // end of src buffer rqt_rcnt = 0; owbuf = rqt_wptr; // dest buffer inbytecnt = rqt_inbytes; outbytecnt = rqt_outbytes; orim2vsize = rqt_visize; //mutr.unlock(); wbuf = owbuf; if ( fact_x < rqt_fact) { fact_x=rqt_fact; initRequant(); } fact_x=rqt_fact; } return true; } k9copy/src/vamps/CTestTestfile.cmake0000664000175000017550000000051512412271774020216 0ustar emulatoremulator# CMake generated Testfile for # Source directory: /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/src/vamps # Build directory: /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/src/vamps # # This file includes the relevant testing commands required for # testing this directory and lists subdirectories to be tested as well. k9copy/src/vamps/k9requant.h0000644000175000017550000001326612412271774016573 0ustar emulatoremulator// // C++ Interface: k9requant // // Description: A transcription from m2vrequantizer in C++ // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9REQUANT_H #define K9REQUANT_H #include "k9common.h" #include #include #include // user defined types //typedef unsigned int uint; typedef unsigned char uint8; typedef unsigned short uint16; typedef unsigned int uint32; typedef unsigned long long uint64; typedef char int8; typedef short int16; typedef int int32; typedef long long int64; typedef signed int sint; typedef signed char sint8; typedef signed short sint16; typedef signed int sint32; #ifdef WIN typedef __int64 sint64; #else typedef signed long long sint64; #endif #define BITS_IN_BUF (8) // block data typedef struct { uint8 run; short level; } RunLevel; /* #define BUF_SIZE (16*1024*1024) #define MIN_READ (4*1024*1024) #define MIN_WRITE (8*1024*1024) #define MAX_READ (10*1024*1024) */ // keep gcc happy #define WRITE \ orbuf = orbuf; \ mloka1 = mloka1; \ mloka2 = mloka2; \ eof = eof; // meaningless #define MIN_WRITE 0 #define MAX_READ 0 #define MOV_READ // this is where we switch threads #define LOCK(x) if (! lock(x)) {rqt_run=false;return;} #define COPY(x) \ memcpy (wbuf, cbuf, x); \ cbuf += x; \ wbuf += x; #define SEEKR(x) cbuf += x; #define SEEKW(x) wbuf += x; /** @author Jean-Michel PETIT */ class k9requant : public QThread { private: int inbitcnt, outbitcnt; uint32 inbitbuf, outbitbuf; uint64 inbytecnt, outbytecnt; float fact_x; int mloka1, mloka2, eof; int64 orim2vsize; int64 bytediff; double stress_factor; // from 0.0 to 1.0 int i_factor; int p_factor; int b_factor; double i_min_stress; double p_min_stress; double b_min_stress; short quant_table_id_data[4096]; short *quant_table_id ; #ifdef USE_FD FILE *ifd, *ofd; #endif #ifdef STAT uint64 ori_i, ori_p, ori_b; uint64 new_i, new_p, new_b; uint64 cnt_i, cnt_p, cnt_b; uint64 cnt_p_i, cnt_p_ni; uint64 cnt_b_i, cnt_b_ni; #endif #ifdef DEMO int gopCount; #endif #ifdef LOG_RATE_CONTROL FILE* LOG_FILE; #endif #ifdef CHANGE_BRIGHTNESS int delta_bright; int dc_reset; int old_dc_pred, new_dc_pred; #endif // mpeg2 state // seq header uint horizontal_size_value; uint vertical_size_value; // pic header uint picture_coding_type; // pic code ext uint f_code[2][2]; uint intra_dc_precision; uint picture_structure; uint frame_pred_frame_dct; uint concealment_motion_vectors; uint q_scale_type; uint intra_vlc_format; uint alternate_scan; // error int validPicHeader; int validSeqHeader; int validExtHeader; int sliceError; // slice or mb uint quantizer_scale; uint new_quantizer_scale; uint last_coded_scale; int h_offset, v_offset; int mb_skip, mb_add; int mb_out; int mb_sav_run, mb_sav_lev, mb_sav_c; short *curTable; RunLevel block[6][65]; // terminated by level = 0, so we need 64+1 private: void putbits(uint val, int n); void Refill_bits(void); void Flush_Bits(uint n); uint Show_Bits(uint n); uint Get_Bits(uint n); uint Copy_Bits(uint n); void flush_read_buffer(); void flush_write_buffer(); int scale_quant(double quant ); int increment_quant(int quant); int intmax( register int x, register int y ); int intmin( register int x, register int y ); void putmbtype(int mb_type); int getNewQuant(int curQuant, int intra); int isNotEmpty(RunLevel *blk); // return != 0 if error int putAC(int run, int signed_level, int vlcformat); // return != 0 if error int putACfirst(int run, int val); void putnonintrablk(RunLevel *blk); void putcbp(int cbp); int get_macroblock_modes (); int get_quantizer_scale (); void get_motion_delta (const int f_code); void get_dmv (); int get_coded_block_pattern (); int get_luma_dc_dct_diff (); int get_chroma_dc_dct_diff (); void get_intra_block_B14 (); void get_intra_block_B15 (); int get_non_intra_block_rq (RunLevel *blk); int get_non_intra_block_sav (RunLevel *blk, int cc); #ifdef P_FRAME_NON_INTRA_DROP int get_non_intra_block_drop (RunLevel *blk, int cc); #endif #ifdef CHANGE_BRIGHTNESS void putDC(const sVLCtable *tab, int val); #endif void slice_intra_DCT (const int cc); void slice_non_intra_DCT (int cur_block); void motion_fr_frame ( uint f_code[2] ); void motion_fr_field ( uint f_code[2] ); void motion_fr_dmv ( uint f_code[2] ); void motion_fr_conceal ( ); void motion_fi_field ( uint f_code[2] ); void motion_fi_16x8 ( uint f_code[2] ); void motion_fi_dmv ( uint f_code[2] ); void motion_fi_conceal (); void putmbdata(int macroblock_modes); void put_quantiser(int quantiser); void putaddrinc(int addrinc); int slice_init (int code); void mpeg2_slice ( const int code ); void initRequant(); bool lock(int64 x); protected: void run (); public: uint8 *cbuf, *rbuf, *wbuf, *orbuf, *owbuf; // global data for inter thread com float rqt_fact; uint32_t rqt_rcnt; uint32_t rqt_wcnt; uint64_t rqt_inbytes; uint64_t rqt_outbytes; uint64_t rqt_visize; uchar *rqt_rptr; uchar *rqt_wptr; QWaitCondition condr; QWaitCondition condw; QMutex mutr; QMutex mutw; bool rqt_stop; bool rqt_run; public: k9requant(); void initvar(); }; #endif k9copy/src/vamps/Makefile0000664000175000017550000001501612412271774016134 0ustar emulatoremulator# CMAKE generated file: DO NOT EDIT! # Generated by "Unix Makefiles" Generator, CMake Version 2.8 # Default target executed when no arguments are given to make. default_target: all .PHONY : default_target #============================================================================= # Special targets provided by cmake. # Disable implicit rules so canonical targets will work. .SUFFIXES: # Remove some rules from gmake that .SUFFIXES does not remove. SUFFIXES = .SUFFIXES: .hpux_make_needs_suffix_list # Suppress display of executed commands. $(VERBOSE).SILENT: # A target that is always out of date. cmake_force: .PHONY : cmake_force #============================================================================= # Set environment variables for the build. # The shell in which to execute make rules. SHELL = /bin/sh # The CMake executable. CMAKE_COMMAND = /usr/bin/cmake # The command to remove a file. RM = /usr/bin/cmake -E remove -f # Escaping for special characters. EQUALS = = # The program to use to edit the cache. CMAKE_EDIT_COMMAND = /usr/bin/ccmake # The top-level source directory on which CMake was run. CMAKE_SOURCE_DIR = /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 # The top-level build directory on which CMake was run. CMAKE_BINARY_DIR = /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 #============================================================================= # Targets provided globally by CMake. # Special rule for the target edit_cache edit_cache: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." /usr/bin/ccmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) .PHONY : edit_cache # Special rule for the target edit_cache edit_cache/fast: edit_cache .PHONY : edit_cache/fast # Special rule for the target install install: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." /usr/bin/cmake -P cmake_install.cmake .PHONY : install # Special rule for the target install install/fast: preinstall/fast @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." /usr/bin/cmake -P cmake_install.cmake .PHONY : install/fast # Special rule for the target install/local install/local: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..." /usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake .PHONY : install/local # Special rule for the target install/local install/local/fast: install/local .PHONY : install/local/fast # Special rule for the target list_install_components list_install_components: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"Unspecified\"" .PHONY : list_install_components # Special rule for the target list_install_components list_install_components/fast: list_install_components .PHONY : list_install_components/fast # Special rule for the target package package: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Run CPack packaging tool..." cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && /usr/bin/cpack --config ./CPackConfig.cmake .PHONY : package # Special rule for the target package package/fast: package .PHONY : package/fast # Special rule for the target package_source package_source: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Run CPack packaging tool for source..." cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && /usr/bin/cpack --config ./CPackSourceConfig.cmake /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CPackSourceConfig.cmake .PHONY : package_source # Special rule for the target package_source package_source/fast: package_source .PHONY : package_source/fast # Special rule for the target rebuild_cache rebuild_cache: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." /usr/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) .PHONY : rebuild_cache # Special rule for the target rebuild_cache rebuild_cache/fast: rebuild_cache .PHONY : rebuild_cache/fast # Special rule for the target test test: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running tests..." /usr/bin/ctest --force-new-ctest-process $(ARGS) .PHONY : test # Special rule for the target test test/fast: test .PHONY : test/fast # The main all target all: cmake_check_build_system cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(CMAKE_COMMAND) -E cmake_progress_start /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CMakeFiles /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/src/vamps/CMakeFiles/progress.marks cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 src/vamps/all $(CMAKE_COMMAND) -E cmake_progress_start /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CMakeFiles 0 .PHONY : all # The main clean target clean: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 src/vamps/clean .PHONY : clean # The main clean target clean/fast: clean .PHONY : clean/fast # Prepare targets for installation. preinstall: all cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 src/vamps/preinstall .PHONY : preinstall # Prepare targets for installation. preinstall/fast: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 src/vamps/preinstall .PHONY : preinstall/fast # clear depends depend: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 .PHONY : depend # Help Target help: @echo "The following are some of the valid targets for this Makefile:" @echo "... all (the default if no target is provided)" @echo "... clean" @echo "... depend" @echo "... edit_cache" @echo "... install" @echo "... install/local" @echo "... list_install_components" @echo "... package" @echo "... package_source" @echo "... rebuild_cache" @echo "... test" .PHONY : help #============================================================================= # Special targets to cleanup operation of make. # Special rule to run CMake to check the build system integrity. # No rule that depends on this can have commands that come from listfiles # because they might be regenerated. cmake_check_build_system: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 .PHONY : cmake_check_build_system k9copy/src/vamps/CMakeFiles/0000775000175000017550000000000012412271774016434 5ustar emulatoremulatork9copy/src/vamps/CMakeFiles/progress.marks0000664000175000017550000000000212412271774021327 0ustar emulatoremulator0 k9copy/src/vamps/CMakeFiles/CMakeDirectoryInformation.cmake0000664000175000017550000000124312412271774024511 0ustar emulatoremulator# CMAKE generated file: DO NOT EDIT! # Generated by "Unix Makefiles" Generator, CMake Version 2.8 # Relative path conversion top directories. SET(CMAKE_RELATIVE_PATH_TOP_SOURCE "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4") SET(CMAKE_RELATIVE_PATH_TOP_BINARY "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4") # Force unix paths in dependencies. SET(CMAKE_FORCE_UNIX_PATHS 1) # The C and CXX include file regular expressions for this directory. SET(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") SET(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") SET(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) SET(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) k9copy/src/vamps/putvlc.h0000644000175000017550000002154312412271774016162 0ustar emulatoremulator// put blk /* type definitions for variable length code table entries */ typedef struct { unsigned char code; /* right justified */ char len; } VLCtable; /* for codes longer than 8 bits (excluding leading zeroes) */ typedef struct { unsigned short code; /* right justified */ char len; } sVLCtable; /* Table B-2, B-3, B-4 variable length codes for macroblock_type * * indexed by [macroblock_type] */ const static VLCtable mbtypetab[3][32]= { /* I */ { {0,0}, {1,1}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {1,2}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0} }, /* P */ { {0,0}, {3,5}, {1,2}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {1,3}, {0,0}, {1,1}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {1,6}, {1,5}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {2,5}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0} }, /* B */ { {0,0}, {3,5}, {0,0}, {0,0}, {2,3}, {0,0}, {3,3}, {0,0}, {2,4}, {0,0}, {3,4}, {0,0}, {2,2}, {0,0}, {3,2}, {0,0}, {0,0}, {1,6}, {0,0}, {0,0}, {0,0}, {0,0}, {2,6}, {0,0}, {0,0}, {0,0}, {3,6}, {0,0}, {0,0}, {0,0}, {2,5}, {0,0} } }; /* Table B-5 ... B-8 variable length codes for macroblock_type in * scalable sequences * * not implemented */ /* Table B-9, variable length codes for coded_block_pattern * * indexed by [coded_block_pattern] */ const static VLCtable cbptable[64]= { {0x01,9}, {0x0b,5}, {0x09,5}, {0x0d,6}, {0x0d,4}, {0x17,7}, {0x13,7}, {0x1f,8}, {0x0c,4}, {0x16,7}, {0x12,7}, {0x1e,8}, {0x13,5}, {0x1b,8}, {0x17,8}, {0x13,8}, {0x0b,4}, {0x15,7}, {0x11,7}, {0x1d,8}, {0x11,5}, {0x19,8}, {0x15,8}, {0x11,8}, {0x0f,6}, {0x0f,8}, {0x0d,8}, {0x03,9}, {0x0f,5}, {0x0b,8}, {0x07,8}, {0x07,9}, {0x0a,4}, {0x14,7}, {0x10,7}, {0x1c,8}, {0x0e,6}, {0x0e,8}, {0x0c,8}, {0x02,9}, {0x10,5}, {0x18,8}, {0x14,8}, {0x10,8}, {0x0e,5}, {0x0a,8}, {0x06,8}, {0x06,9}, {0x12,5}, {0x1a,8}, {0x16,8}, {0x12,8}, {0x0d,5}, {0x09,8}, {0x05,8}, {0x05,9}, {0x0c,5}, {0x08,8}, {0x04,8}, {0x04,9}, {0x07,3}, {0x0a,5}, {0x08,5}, {0x0c,6} }; /* Table B-14, DCT coefficients table zero * * indexed by [run][level-1] * split into two tables (dct_code_tab1, dct_code_tab2) to reduce size * 'first DCT coefficient' condition and 'End of Block' are treated elsewhere * codes do not include s (sign bit) */ const static VLCtable dct_code_tab1[2][40]= { /* run = 0, level = 1...40 */ { {0x03, 2}, {0x04, 4}, {0x05, 5}, {0x06, 7}, {0x26, 8}, {0x21, 8}, {0x0a,10}, {0x1d,12}, {0x18,12}, {0x13,12}, {0x10,12}, {0x1a,13}, {0x19,13}, {0x18,13}, {0x17,13}, {0x1f,14}, {0x1e,14}, {0x1d,14}, {0x1c,14}, {0x1b,14}, {0x1a,14}, {0x19,14}, {0x18,14}, {0x17,14}, {0x16,14}, {0x15,14}, {0x14,14}, {0x13,14}, {0x12,14}, {0x11,14}, {0x10,14}, {0x18,15}, {0x17,15}, {0x16,15}, {0x15,15}, {0x14,15}, {0x13,15}, {0x12,15}, {0x11,15}, {0x10,15} }, /* run = 1, level = 1...18 */ { {0x03, 3}, {0x06, 6}, {0x25, 8}, {0x0c,10}, {0x1b,12}, {0x16,13}, {0x15,13}, {0x1f,15}, {0x1e,15}, {0x1d,15}, {0x1c,15}, {0x1b,15}, {0x1a,15}, {0x19,15}, {0x13,16}, {0x12,16}, {0x11,16}, {0x10,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0} } }; const static VLCtable dct_code_tab2[30][5]= { /* run = 2...31, level = 1...5 */ {{0x05, 4}, {0x04, 7}, {0x0b,10}, {0x14,12}, {0x14,13}}, {{0x07, 5}, {0x24, 8}, {0x1c,12}, {0x13,13}, {0x00, 0}}, {{0x06, 5}, {0x0f,10}, {0x12,12}, {0x00, 0}, {0x00, 0}}, {{0x07, 6}, {0x09,10}, {0x12,13}, {0x00, 0}, {0x00, 0}}, {{0x05, 6}, {0x1e,12}, {0x14,16}, {0x00, 0}, {0x00, 0}}, {{0x04, 6}, {0x15,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x07, 7}, {0x11,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x05, 7}, {0x11,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x27, 8}, {0x10,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x23, 8}, {0x1a,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x22, 8}, {0x19,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x20, 8}, {0x18,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x0e,10}, {0x17,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x0d,10}, {0x16,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x08,10}, {0x15,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1f,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1a,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x19,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x17,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x16,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1f,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1e,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1d,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1c,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1b,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1f,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1e,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1d,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1c,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1b,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}} }; /* Table B-15, DCT coefficients table one * * indexed by [run][level-1] * split into two tables (dct_code_tab1a, dct_code_tab2a) to reduce size * 'End of Block' is treated elsewhere * codes do not include s (sign bit) */ const static VLCtable dct_code_tab1a[2][40]= { /* run = 0, level = 1...40 */ { {0x02, 2}, {0x06, 3}, {0x07, 4}, {0x1c, 5}, {0x1d, 5}, {0x05, 6}, {0x04, 6}, {0x7b, 7}, {0x7c, 7}, {0x23, 8}, {0x22, 8}, {0xfa, 8}, {0xfb, 8}, {0xfe, 8}, {0xff, 8}, {0x1f,14}, {0x1e,14}, {0x1d,14}, {0x1c,14}, {0x1b,14}, {0x1a,14}, {0x19,14}, {0x18,14}, {0x17,14}, {0x16,14}, {0x15,14}, {0x14,14}, {0x13,14}, {0x12,14}, {0x11,14}, {0x10,14}, {0x18,15}, {0x17,15}, {0x16,15}, {0x15,15}, {0x14,15}, {0x13,15}, {0x12,15}, {0x11,15}, {0x10,15} }, /* run = 1, level = 1...18 */ { {0x02, 3}, {0x06, 5}, {0x79, 7}, {0x27, 8}, {0x20, 8}, {0x16,13}, {0x15,13}, {0x1f,15}, {0x1e,15}, {0x1d,15}, {0x1c,15}, {0x1b,15}, {0x1a,15}, {0x19,15}, {0x13,16}, {0x12,16}, {0x11,16}, {0x10,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0} } }; const static VLCtable dct_code_tab2a[30][5]= { /* run = 2...31, level = 1...5 */ {{0x05, 5}, {0x07, 7}, {0xfc, 8}, {0x0c,10}, {0x14,13}}, {{0x07, 5}, {0x26, 8}, {0x1c,12}, {0x13,13}, {0x00, 0}}, {{0x06, 6}, {0xfd, 8}, {0x12,12}, {0x00, 0}, {0x00, 0}}, {{0x07, 6}, {0x04, 9}, {0x12,13}, {0x00, 0}, {0x00, 0}}, {{0x06, 7}, {0x1e,12}, {0x14,16}, {0x00, 0}, {0x00, 0}}, {{0x04, 7}, {0x15,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x05, 7}, {0x11,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x78, 7}, {0x11,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x7a, 7}, {0x10,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x21, 8}, {0x1a,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x25, 8}, {0x19,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x24, 8}, {0x18,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x05, 9}, {0x17,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x07, 9}, {0x16,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x0d,10}, {0x15,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1f,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1a,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x19,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x17,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x16,12}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1f,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1e,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1d,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1c,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1b,13}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1f,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1e,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1d,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1c,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}}, {{0x1b,16}, {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}} }; const static VLCtable addrinctab[33]= { {0x01,1}, {0x03,3}, {0x02,3}, {0x03,4}, {0x02,4}, {0x03,5}, {0x02,5}, {0x07,7}, {0x06,7}, {0x0b,8}, {0x0a,8}, {0x09,8}, {0x08,8}, {0x07,8}, {0x06,8}, {0x17,10}, {0x16,10}, {0x15,10}, {0x14,10}, {0x13,10}, {0x12,10}, {0x23,11}, {0x22,11}, {0x21,11}, {0x20,11}, {0x1f,11}, {0x1e,11}, {0x1d,11}, {0x1c,11}, {0x1b,11}, {0x1a,11}, {0x19,11}, {0x18,11} }; const static sVLCtable DClumtab[12]= { {0x0004,3}, {0x0000,2}, {0x0001,2}, {0x0005,3}, {0x0006,3}, {0x000e,4}, {0x001e,5}, {0x003e,6}, {0x007e,7}, {0x00fe,8}, {0x01fe,9}, {0x01ff,9} }; k9copy/src/vamps/k9ffmpeg.h0000644000175000017550000001535612412271774016362 0ustar emulatoremulator// // C++ Interface: k9avidecode // // Description: // // // Author: Jean-Michel PETIT , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9FFMPEG_H #define K9FFMPEG_H #include #include #include #include #include #ifdef HAVE_SWSCALE #include #endif /** @author Jean-Michel PETIT */ //typedef dvd_file_t * (*DVDOpenFile_t) ( dvd_reader_t *, int, dvd_read_domain_t ); typedef void (*av_register_all_t) (void); typedef void (*avcodec_init_t)(void); typedef int64_t (*av_gettime_t) (void); #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 2, 0) typedef int (*avformat_open_input_t)(AVFormatContext **, const char *, AVInputFormat *, AVDictionary **); #else typedef int (*av_open_input_file_t)(AVFormatContext **, const char *,AVInputFormat *,int, AVFormatParameters *); #endif #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 6, 0) typedef int (*avformat_find_stream_info_t)(AVFormatContext *, AVDictionary **); #else typedef int (*av_find_stream_info_t)(AVFormatContext *); #endif typedef AVCodec* (*avcodec_find_decoder_t)(enum CodecID); #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 8, 0) typedef int (*avcodec_open2_t)(AVCodecContext *, AVCodec *, AVDictionary **); #else typedef int (*avcodec_open_t)(AVCodecContext *, AVCodec *); #endif typedef AVFrame * (*avcodec_alloc_frame_t)(void); typedef AVCodecContext * (*avcodec_alloc_context_t)(void); typedef int (*avpicture_get_size_t)(int , int , int ); typedef void * (*av_malloc_t)(unsigned int ); typedef int (*avpicture_fill_t)(AVPicture *, uint8_t *,int , int , int); typedef int (*av_read_frame_t)(AVFormatContext *, AVPacket *); #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 23, 0) typedef int (*avcodec_decode_video2_t)(AVCodecContext *, AVFrame *, int *, AVPacket *); #else typedef int (*avcodec_decode_video_t)(AVCodecContext *, AVFrame *,int *, uint8_t *, int ); #endif typedef int (*avcodec_encode_audio_t)(AVCodecContext *avctx, uint8_t *buf, int buf_size, const short *samples); typedef int (*img_convert_t)(AVPicture *, int , const AVPicture *, int ,int, int); typedef void (*av_free_t)(void *); typedef int (*avcodec_close_t)(AVCodecContext *); #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 17, 0) typedef void (*avformat_close_input_t)(AVFormatContext **); #else typedef void (*av_close_input_file_t)(AVFormatContext *); #endif typedef int (*av_seek_frame_t)(AVFormatContext *,int,int64_t timestamp,int flags); typedef int64_t (*av_rescale_q_t)(int64_t , AVRational , AVRational ) ; typedef void (*avcodec_flush_buffers_t)(AVCodecContext *); #ifdef HAVE_SWSCALE typedef void (*sws_freeContext_t)(struct SwsContext *swsContext); typedef struct SwsContext* (*sws_getContext_t)(int srcW, int srcH, int srcFormat, int dstW, int dstH, int dstFormat, int flags, SwsFilter *srcFilter, SwsFilter *dstFilter, double *param); typedef int (*sws_scale_t)(struct SwsContext *context, uint8_t* src[], int srcStride[], int srcSliceY,int srcSliceH, uint8_t* dst[], int dstStride[]); #endif typedef int (*url_fopen_t)(ByteIOContext **s, const char *filename, int flags); typedef ReSampleContext * (*audio_resample_init_t)(int output_channels, int input_channels,int output_rate,int input_rate); typedef int (*av_write_header_t)(AVFormatContext *); typedef int (*avcodec_decode_audio2_t)(AVCodecContext *avctx, int16_t *samples,int *frame_size_ptr,const uint8_t *buf, int buf_size); typedef int (*avcodec_decode_audio_t)(AVCodecContext *avctx, int16_t *samples,int *frame_size_ptr, const uint8_t *buf, int buf_size); typedef AVOutputFormat *(*guess_format_t)(const char *short_name, const char *filename, const char *mime_type); typedef int (*audio_resample_t)(ReSampleContext *s, short *output, short *input, int nb_samples); typedef AVFormatContext *(*av_alloc_format_context_t)(void); typedef AVCodec *(*avcodec_find_encoder_t)(enum CodecID id); typedef void (*av_init_packet_t)(AVPacket *pkt); typedef int (*av_write_frame_t)(AVFormatContext *s, AVPacket *pkt); typedef int (*av_write_trailer_t)(AVFormatContext *s); typedef int (*av_set_parameters_t)(AVFormatContext *s, AVFormatParameters *ap); typedef void (*dump_format_t)(AVFormatContext *ic, int index, const char *url, int is_output); typedef AVStream *(*av_new_stream_t)(AVFormatContext *s, int id); class k9FFMpeg { public: k9FFMpeg(); ~k9FFMpeg(); static k9FFMpeg *instance(); public: avcodec_init_t avcodec_init; avcodec_alloc_context_t avcodec_alloc_context; av_register_all_t av_register_all; # if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 2, 0) avformat_open_input_t avformat_open_input; # else av_open_input_file_t av_open_input_file; # endif # if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 6, 0) avformat_find_stream_info_t avformat_find_stream_info; # else av_find_stream_info_t av_find_stream_info; # endif avcodec_find_decoder_t avcodec_find_decoder; # if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 8, 0) avcodec_open2_t avcodec_open2; # else avcodec_open_t avcodec_open; # endif avcodec_alloc_frame_t avcodec_alloc_frame; av_seek_frame_t av_seek_frame; avpicture_get_size_t avpicture_get_size; av_malloc_t av_malloc; avpicture_fill_t avpicture_fill; av_read_frame_t av_read_frame; # if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 23, 0) avcodec_decode_video2_t avcodec_decode_video2; # else avcodec_decode_video_t avcodec_decode_video; # endif img_convert_t img_convert; av_free_t av_free; avcodec_close_t avcodec_close; # if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 17, 0) avformat_close_input_t avformat_close_input; # else av_close_input_file_t av_close_input_file; # endif av_rescale_q_t av_rescale_q; av_gettime_t av_gettime; avcodec_flush_buffers_t avcodec_flush_buffers; #ifdef HAVE_SWSCALE sws_freeContext_t sws_freeContext; sws_getContext_t sws_getContext; sws_scale_t sws_scale; #endif url_fopen_t url_fopen; audio_resample_init_t audio_resample_init; av_write_header_t av_write_header; avcodec_decode_audio2_t avcodec_decode_audio2; avcodec_decode_audio_t avcodec_decode_audio; avcodec_encode_audio_t avcodec_encode_audio; guess_format_t guess_format; audio_resample_t audio_resample; av_alloc_format_context_t av_alloc_format_context; avcodec_find_encoder_t avcodec_find_encoder; av_init_packet_t av_init_packet; av_write_frame_t av_write_frame; av_write_trailer_t av_write_trailer; av_set_parameters_t av_set_parameters; dump_format_t dump_format; av_new_stream_t av_new_stream; private: void *CodecHandle; void *FormatHandle; void *SwscaleHandle; void *UtilHandle; QString m_error; }; #endif k9copy/src/vamps/CMakeLists.txt0000644000175000017550000000000012412271774017215 0ustar emulatoremulatork9copy/src/vamps/cmake_install.cmake0000664000175000017550000000225612412271774020306 0ustar emulatoremulator# Install script for directory: /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/src/vamps # Set the install prefix IF(NOT DEFINED CMAKE_INSTALL_PREFIX) SET(CMAKE_INSTALL_PREFIX "/usr/local") ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") # Set the install configuration name. IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) IF(BUILD_TYPE) STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") ELSE(BUILD_TYPE) SET(CMAKE_INSTALL_CONFIG_NAME "RelWithDebInfo") ENDIF(BUILD_TYPE) MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) # Set the component getting installed. IF(NOT CMAKE_INSTALL_COMPONENT) IF(COMPONENT) MESSAGE(STATUS "Install component: \"${COMPONENT}\"") SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") ELSE(COMPONENT) SET(CMAKE_INSTALL_COMPONENT) ENDIF(COMPONENT) ENDIF(NOT CMAKE_INSTALL_COMPONENT) # Install shared libraries without execute permission? IF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) SET(CMAKE_INSTALL_SO_NO_EXE "0") ENDIF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) k9copy/src/vamps/k9vamps.cpp0000755000175000017550000007444612412271774016607 0ustar emulatoremulator// // C++ Interface: k9vamps // // Description: A transcription from Vamps in C++ // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9vamps.h" #include #include void k9vamps::setNoData() { noData=true; wDataRead.wakeAll(); wDataReady.wakeAll(); } void k9vamps::addData(uchar *data,uint size) { while (1) { if (m_fifo->freespace()>=size) { m_fifo->enqueue(data,size); wDataReady.wakeAll(); break; } else { QMutex m; m.lock(); wDataRead.wait(&m); m.unlock(); } } } int k9vamps::readData(uchar * data,uint size) { uint size2=size; uint32_t readSize=0,s=0; while (1) { // is there data in the buffer? if (m_fifo->count() >0) { // s= size of data that we will read (maximum = size) s=(m_fifo->count()) count()) : size2; // increments the number of readen bytes readSize+=s; // decrements the number of max bytes to read size2-=s; //moves bytes from buffer to output m_fifo->dequeue(data,s); //moves the position of output buffer to receive next bytes data+=s; //there's now free space in input buffer, we can wake the injection thread wDataRead.wakeAll(); } // break the loop if injection thread terminated or we got what we want (size bytes) // otherwise, we're waiting for datas if(noData || (m_fifo->count() >=size2)) { break; } else { QMutex m; m.lock(); wDataReady.wait(&m); m.unlock(); } } // if there's datas in input buffer and we did not get all what we wanted, we take them. s= (m_fifo->count()) count()) : size2; readSize+=s; if (s>0 ) m_fifo->dequeue(data,s); wDataRead.wakeAll(); return readSize; } void k9vamps::addSubpicture(uint id) { int cpt=1; for (uint i=0;i<32;i++) if (spu_track_map[i]!=0) cpt++; spu_track_map[id-1]=cpt; } void k9vamps::addAudio(uint id) { int cpt=1; for (uint i=0;i <8;i++) if (audio_track_map[i] !=0) cpt++; audio_track_map[id-1]=cpt; } void k9vamps::addAudio(uint id,uint newId) { if (newId==0) addAudio(id); else audio_track_map[id-1]=newId; } void k9vamps::setInputSize(uint64_t size) { ps_size=size; } void k9vamps::setVapFactor(float factor) { vap_fact=factor; } void k9vamps::setSaveImage(k9SaveImage *m_save) { m_saveImage=m_save; } void k9vamps::reset() { m_preserve=true; m_error=false; bytes_read =0; bytes_written=0; padding_bytes=0; total_packs=0; video_packs=0; skipped_video_packs=0; aux_packs=0; skipped_aux_packs=0; sequence_headers=0; nav_packs=0; rptr = rbuf; rhwp = rbuf; wptr = wbuf; vbuf_size = VBUF_SIZE; vap_fact= 1.0f; // inbuffw=inbuff; for (uint i=0; i<8;i++) { audio_track_map[i]=0; } for (uint i=0; i<32;i++) { spu_track_map[i]=0; } calc_ps_vap = 1; vap_fact=1.0; ps_size=0; noData=false; avgdiff=1; m_totfact=m_nbfact=m_avgfact=0; vin_bytes=0; vout_bytes=0; } k9vamps::k9vamps(k9DVDBackupInterface *dvdbackup,bool _useCache):QThread(dvdbackup) { if (!_useCache) m_fifo=new k9MemoryFifo(); else m_fifo=new k9FileFifo(); m_saveImage=NULL; m_dvdbackup=dvdbackup; reset(); m_requant=NULL; if (dvdbackup !=NULL) { m_bgUpdate = new k9bgUpdate(dvdbackup); dvdbackup->setVamps(this); } else m_bgUpdate=NULL; rbuf_size= RBUF_SIZE; rbuf = new uchar[rbuf_size]; m_output=NULL; } void k9vamps::setPreserve(bool _value) { m_preserve = _value; } void k9vamps::setOutput(QFile *_output) { m_output=_output; } k9vamps::~k9vamps() { if (m_bgUpdate !=NULL) delete m_bgUpdate; delete[] rbuf; delete m_fifo; } void k9vamps::run () { m_error=false; m_errMsg=""; m_requant=new k9requant(); eof=0; // allocate video buffers vibuf = new uchar[vbuf_size]; vobuf = new uchar[vbuf_size]; if (vibuf == NULL || vobuf == NULL) fatal (QString("Allocation of video buffers failed: %1").arg(strerror (errno))); // actually do vaporization vaporize (); flush(); if (m_requant !=NULL) { m_requant->rqt_stop=true; while(m_requant->isRunning()) { m_requant->condr.wakeAll(); m_requant->condw.wakeAll(); m_requant->wait(10); } // m_requant->mutr.unlock(); // m_requant->mutw.unlock(); } delete m_requant; m_requant=NULL; delete[] vibuf; delete[] vobuf; if (m_bgUpdate!=NULL) m_bgUpdate->wait(); //mutex.unlock(); } // lock `size' bytes in read buffer // i.e. ensure the next `size' input bytes are available in buffer // returns nonzero on EOF int k9vamps::lock (int size) { int avail, n; avail = rhwp - rptr; if (avail >= size) return 0; if (avail) { memcpy (rbuf, rptr, avail); rptr = rbuf; rhwp = rptr + avail; } if (rbuf_size -avail <=0) { uchar *buffer =new uchar[rbuf_size+20480]; memcpy (buffer,rbuf,rbuf_size); rptr = buffer +(rptr-rbuf); rhwp=buffer+(rhwp-rbuf); rbuf_size+=20480; delete[] rbuf; rbuf=buffer; } n = readData(rhwp,rbuf_size - avail); if (n % SECT_SIZE) fatal ("Premature EOF"); rhwp += n; bytes_read += n; return !n; } // copy `size' bytes from rbuf to wbuf void k9vamps::copy (int size) { if (!size) return; if ((wptr - wbuf) + size > WBUF_SIZE) fatal ("Write buffer overflow"); memcpy (wptr, rptr, size); rptr += size; wptr += size; } // skip `size' bytes in rbuf void k9vamps::skip (int size) { rptr += size; } // flush wbuf void k9vamps::flush (void) { int size; mutex.lock(); size = wptr - wbuf; if (!size) { mutex.unlock(); return; } //m_dvdbackup->getOutput(wbuf,size); // wait for a preceding update to finish if (m_bgUpdate!=NULL) { m_bgUpdate->wait(); m_bgUpdate->update( wbuf,size); } if (m_output != NULL) m_output->write((const char*) wbuf,size); if (m_saveImage !=NULL) m_saveImage->addData(wbuf,size); wptr = wbuf; bytes_written += size; mutex.unlock(); } // returns no. bytes read up to where `ptr' points uint64_t k9vamps::rtell (uchar *ptr) { return bytes_read - (rhwp - ptr); } // returns no. bytes written up to where `ptr' points // (including those in buffer which are not actually written yet) uint64_t k9vamps::wtell (uchar *ptr) { return bytes_written + (ptr - wbuf); } // some pack header consistency checking bool k9vamps::check_pack (uchar *ptr) { uint32_t pack_start_code; int pack_stuffing_length; pack_start_code = (uint32_t) (ptr [0]) << 24; pack_start_code |= (uint32_t) (ptr [1]) << 16; pack_start_code |= (uint32_t) (ptr [2]) << 8; pack_start_code |= (uint32_t) (ptr [3]); if (pack_start_code != 0x000001ba) { // fatal ("Bad pack start code at %llu: %08lx", rtell (ptr), pack_start_code); return false; } if ((ptr [4] & 0xc0) != 0x40) { // fatal ("Not an MPEG2 program stream pack at %llu", rtell (ptr)); return false; } // we rely on a fixed pack header size of 14 // so better to ensure this is true pack_stuffing_length = ptr [13] & 7; if (pack_stuffing_length) { //fatal ("Non-zero pack stuffing length at %llu: %d\n", rtell (ptr), pack_stuffing_length); return false; } return true; } // video packet consistency checking int k9vamps::check_video_packet (uchar *ptr) { int vid_packet_length, pad_packet_length, rc = 0; uint32_t vid_packet_start_code, pad_packet_start_code, sequence_header_code; vid_packet_start_code = (uint32_t) (ptr [0]) << 24; vid_packet_start_code |= (uint32_t) (ptr [1]) << 16; vid_packet_start_code |= (uint32_t) (ptr [2]) << 8; vid_packet_start_code |= (uint32_t) (ptr [3]); if (vid_packet_start_code != 0x000001e0) fatal(QString ("Bad video packet start code at %1: %2").arg(rtell(ptr)).arg(vid_packet_start_code,0,16)); vid_packet_length = ptr [4] << 8; vid_packet_length |= ptr [5]; vid_packet_length += 6; if ((ptr [6] & 0xc0) != 0x80) fatal (QString("Not an MPEG2 video packet at %1").arg(rtell (ptr))); if (ptr [7]) { if ((ptr [7] & 0xc0) != 0xc0) qDebug() << QString("First video packet in sequence starting at %1 misses PTS or DTS, flags=%2").arg(rtell (ptr)).arg(ptr [7]); else { sequence_header_code = (uint32_t) (ptr [6 + 3 + ptr [8] + 0]) << 24; sequence_header_code |= (uint32_t) (ptr [6 + 3 + ptr [8] + 1]) << 16; sequence_header_code |= (uint32_t) (ptr [6 + 3 + ptr [8] + 2]) << 8; sequence_header_code |= (uint32_t) (ptr [6 + 3 + ptr [8] + 3]); if (sequence_header_code == 0x000001b3) { rc = 1; } else { //fprintf (stderr, "Start of GOP at %llu not on sector boundary\n", // rtell (ptr + 6 + 3 + ptr [8])); sequence_headers++; } } } pad_packet_length = 0; if (14 + vid_packet_length < SECT_SIZE - 6) { // video packet does not fill whole sector // check for padding packet ptr += vid_packet_length; pad_packet_start_code = (uint32_t) (ptr [0]) << 24; pad_packet_start_code |= (uint32_t) (ptr [1]) << 16; pad_packet_start_code |= (uint32_t) (ptr [2]) << 8; pad_packet_start_code |= (uint32_t) (ptr [3]); if (pad_packet_start_code != 0x000001be) qDebug () <isRunning()) { m_requant->initvar(); } m_requant->rqt_stop=false; // this ensures for the requant thread to stop at this GOP's end memcpy (src + n, "\0\0\1", 3); m_requant->mutr.lock(); m_requant->rqt_rptr = src; m_requant->rqt_wptr = dst; m_requant->rqt_rcnt = n; m_requant->rqt_wcnt = 0; m_requant->rqt_fact = fact ; m_requant->rqt_inbytes = vin_bytes; m_requant->rqt_outbytes = vout_bytes; m_requant->rqt_visize = (uint64_t) ((float) ps_size * (float) vin_bytes / ((float) total_packs * (float) SECT_SIZE)); // create requantization thread if (! m_requant->isRunning()) { m_requant->start(); m_requant->rqt_run=true; } m_requant->condr.wakeAll(); m_requant->mutr.unlock(); // now the requant thread should be running m_requant->mutw.lock(); // wait for requant thread to finish while (!m_requant->rqt_wcnt) m_requant->condw.wait( &m_requant->mutw); rv = m_requant->rqt_wcnt; m_requant->mutw.unlock(); /* if ((m_requant->rbuf-m_requant->cbuf -3) >0 ) { memcpy(dst+m_requant->rqt_wcnt,m_requant->cbuf,m_requant->rbuf-m_requant->cbuf -3); rv +=m_requant->rbuf-m_requant->cbuf -3; } /*/ if ((m_requant->rbuf-m_requant->cbuf -2) >0 ) { memcpy(dst+m_requant->rqt_wcnt,m_requant->cbuf,m_requant->rbuf-m_requant->cbuf -2); rv +=m_requant->rbuf-m_requant->cbuf -2; } // if (rv>n) // qDebug("requant error"); double realrqtfact=(double)(vin_bytes) / (double)(vout_bytes+rv); avgdiff = ((m_avgfact) /realrqtfact); //qDebug ("factor : " +QString::number(m_avgfact) +" --> " +QString::number((float)n/(float)rv) +" avgdiff : " + QString::number(avgdiff) +" rqt_visize :" +QString::number(m_requant->rqt_visize) +" ps_size :" +QString::number(ps_size) + " vin_bytes :" + QString::number(vin_bytes)) ; return rv; } int k9vamps::getStreamIndex(uchar *ptr) { int type, abase; type = ptr [6 + 3 + ptr [8]]; //fprintf (stderr, "type=%02x\n", type); if (type >= 0x20 && type <= 0x3f) { // subpicture return type- 0x20 +1; } if (type >= 0x80 && type <= 0x87) { // AC3 audio abase = 0x80; } else if (type >= 0x88 && type <= 0x8f) { // DTS audio abase = 0x88; } else if (type >= 0xa0 && type <= 0xa7) { // LPCM audio abase = 0xa0; } else { // fatal ("Unknown private stream 1 type at %llu: %02x", rtell (ptr), type); abase = 0; } return type - abase + 1; } // translate type of private stream 1 packet // according to the track translation maps // returns new track type (e.g. 0x80 for first AC3 audio // track in cmd line) or zero if track is not to be copied int k9vamps::new_private_1_type (uchar *ptr) { int type, track, abase; type = ptr [6 + 3 + ptr [8]]; //fprintf (stderr, "type=%02x\n", type); if (type >= 0x20 && type <= 0x3f) { // subpicture track = spu_track_map [type - 0x20]; return track ? track - 1 + 0x20 : 0; } if (type >= 0x80 && type <= 0x87) { // AC3 audio abase = 0x80; } else if (type >= 0x88 && type <= 0x8f) { // DTS audio abase = 0x88; } else if (type >= 0xa0 && type <= 0xa7) { // LPCM audio abase = 0xa0; } else { // fatal ("Unknown private stream 1 type at %llu: %02x", rtell (ptr), type); abase = 0; } track = audio_track_map [type - abase]; return track ? track - 1 + abase : 0; } // selectivly copy private stream 1 packs // patches track type to reflect new track // mapping unless user opted to preserve them void k9vamps::copy_private_1 (uchar *ptr) { int type; type = new_private_1_type (ptr); if (type) { if (m_dvdbackup) { int streamIndex=getStreamIndex(ptr); if (streamIndex) { m_dvdbackup->getOutput( (type >= 0x20 && type <= 0x3f) ? k9DVDBackupInterface::SUBPICTURE:k9DVDBackupInterface::AUDIO,streamIndex,ptr,SECT_SIZE); } } if (!m_preserve) ptr [6 + 3 + ptr [8]] = type; copy (SECT_SIZE); return; } skip (SECT_SIZE); } // translate ID of MPEG audio packet // according to the audio track translation map // returns new ID (e.g. 0xc0 for first MPEG audio // track in cmd line) or zero if track is not to be copied int k9vamps::new_mpeg_audio_id (int id) { int track; track = audio_track_map [id - 0xc0]; return track ? track - 1 + 0xc0 : 0; } // selectivly copy MPEG audio packs // patches ID to reflect new track mapping unless user opted to preserve them void k9vamps::copy_mpeg_audio (uchar *ptr) { int id; id = new_mpeg_audio_id (ptr [3]); if (id) { if (!m_preserve) ptr [3] = id; copy (SECT_SIZE); return; } skip (SECT_SIZE); } // process beginning of program stream up to // - but not including - first sequence header // this PS leader is NOT shrunk since the PS may not // necessarily begin at a GOP boundary (although it should?) // nevertheless the unwanted private stream 1 and MPEG audio // packs are skipped since some players could get confused otherwise void k9vamps::vap_leader () { uchar *ptr; int id, data_length; while (!lock (SECT_SIZE)) { ptr = rptr; if (check_pack (ptr)) { ptr += 14; id = ptr [3]; } else { ptr +=14; id = 0; } switch (id) { case 0xe0: // video if (check_video_packet (ptr)) // sequence header return; copy (SECT_SIZE); if (m_dvdbackup) m_dvdbackup->getOutput(k9DVDBackupInterface::VIDEO,0,ptr,SECT_SIZE); break; case 0xbd: // private 1: audio/subpicture copy_private_1 (ptr); break; case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: // MPEG audio copy_mpeg_audio (ptr); break; case 0xbb: // system header/private 2: PCI/DSI copy (SECT_SIZE); if (m_dvdbackup) m_dvdbackup->getOutput(k9DVDBackupInterface::NAV,0,ptr,SECT_SIZE); break; case 0xbe: // padding data_length = ptr [4] << 8; data_length |= ptr [5]; if (14 + data_length != SECT_SIZE - 6) fatal (QString("Bad padding packet length at %1: %2").arg(rtell (ptr)).arg(data_length)); //JMP:à vérifier skip (SECT_SIZE); break; default: // fatal("Encountered stream ID %02x at %llu, " // "probably bad MPEG2 program stream", id, rtell (ptr)); copy (SECT_SIZE); } if (wptr == wbuf + WBUF_SIZE) flush (); } eof = 1; flush (); return; } // process end of program stream // the same counts here as for the PS' beginning void k9vamps::vap_trailer (int length) { uchar *ptr; int i, id, data_length; for (i = 0; i < length; i += SECT_SIZE) { ptr = rptr + 14; id = ptr [3]; if (id == 0xbd) { // private 1: audio/subpicture copy_private_1 (ptr); } else if (id >= 0xc0 && id <= 0xc7) { // MPEG audio copy_mpeg_audio (ptr); } else if (id == 0xbe) { // padding data_length = ptr [4] << 8; data_length |= ptr [5]; if (14 + data_length != SECT_SIZE - 6) fatal (QString("Bad padding packet length at %1: %2").arg(rtell (ptr)).arg(data_length)); skip (SECT_SIZE); } else { copy (SECT_SIZE); } if (wptr == wbuf + WBUF_SIZE) flush (); } flush (); } // vaporization is split in two phases - this is phase 1 // PS packs are read into rbuf until a sequence header is found. // All video packs are unpacketized and the contained video ES // GOP copied to vibuf. In the same course the private stream 1 // and MPEG audio packs are inspected and the number of packs // not to be copied are counted. This is to forecast the video // vaporization factor in case the user specified a PS shrink factor. // returns GOP length in bytes int k9vamps::vap_phase1 (void) { uchar *ptr, *viptr = vibuf; int seq_length, id, data_length, opt_length, seqhdr; for (seq_length = 0; !lock (seq_length + SECT_SIZE); seq_length += SECT_SIZE) { ptr = rptr + seq_length; if (check_pack (ptr)) { ptr += 14; id = ptr [3]; } else { ptr += 14; id = 0; } // avoid duplicate counts for sequence headers if (seq_length) total_packs++; switch (id) { case 0xe0: // video seqhdr = check_video_packet (ptr); if (seq_length) { video_packs++; if (seqhdr) { sequence_headers++; vilen = viptr - vibuf; return seq_length; } } // copy contained video ES fragment to vibuf data_length = ptr [4] << 8; data_length |= ptr [5]; opt_length = 3 + ptr [8]; data_length -= opt_length; if ((viptr - vibuf) + data_length > vbuf_size - 3) { // reallocate video buffers int i = viptr - vibuf; // grow by another VBUF_SIZE bytes vbuf_size += VBUF_SIZE; uchar *tmp; tmp =new uchar[vbuf_size]; memcpy(tmp,vibuf,vbuf_size-VBUF_SIZE); delete[] vibuf; vibuf = tmp; // vibuf = (uchar*)realloc (vibuf, vbuf_size); tmp=new uchar[vbuf_size]; memcpy(tmp,vobuf,vbuf_size-VBUF_SIZE); delete[] vobuf; vobuf=tmp; // vobuf = (uchar*)realloc (vobuf, vbuf_size); if (vibuf == NULL || vobuf == NULL) fatal ("Reallocation of video buffers failed"); viptr = vibuf + i; } //fprintf (stderr, "data_length=%d\n", data_length); memcpy (viptr, ptr + 6 + opt_length, data_length); viptr += data_length; break; case 0xbd: // private 1: audio/subpicture aux_packs++; if (!new_private_1_type (ptr)) skipped_aux_packs++; break; case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: // MPEG audio aux_packs++; if (!new_mpeg_audio_id (id)) skipped_aux_packs++; break; case 0xbb: // system header/private 2: PCI/DSI nav_packs++; break; case 0xbe: // padding skipped_aux_packs++; data_length = ptr [4] << 8; data_length |= ptr [5]; if (14 + data_length != SECT_SIZE - 6) fatal (QString("Bad padding packet length at %1: %2").arg(rtell (ptr)).arg(data_length)); break; default: // fatal("Encountered stream ID %02x at %llu, " // "probably bad MPEG2 program stream", id, rtell (ptr)); break; } } eof = 1; return seq_length; } // re-packetize the video ES // `ptr' points to original PES packet where to put the video data // `voptr' points to first unpacketized byte in vobuf // `avail' specifies number of bytes remaining in vobuf // returns number of ES bytes in generated PES packet int k9vamps::gen_video_packet (uchar *ptr, uchar *voptr, int avail) { int i, header_data_length, data_length, padding_length; // if original PES holds optional data (e.g. DTS/PTS) we must keep it header_data_length = (ptr [7] & 0xc0) == 0xc0 ? ptr [8] : 0; data_length = SECT_SIZE - (14 + 6 + 3 + header_data_length); if (avail >= data_length) { // write out a full video packet (usually 2025 byte) memcpy (ptr + 6 + 3 + header_data_length, voptr, data_length); ptr [4] = (SECT_SIZE - (14 + 6)) >> 8; ptr [5] = (SECT_SIZE - (14 + 6)) & 0xff; ptr [8] = header_data_length; return data_length; } if (avail < data_length - 6) { // write a short video packet and a padding packet memcpy (ptr + 6 + 3 + header_data_length, voptr, avail); ptr [4] = (3 + header_data_length + avail) >> 8; ptr [5] = 3 + header_data_length + avail; ptr [8] = header_data_length; // generate padding packet ptr += 6 + 3 + header_data_length + avail; padding_length = data_length - (avail + 6); padding_bytes += padding_length + 6; ptr [0] = 0; ptr [1] = 0; ptr [2] = 1; ptr [3] = 0xbe; ptr [4] = padding_length >> 8; ptr [5] = padding_length; for (i = 0; i < padding_length; i++) ptr [6+i] = 0xff; return avail; } // write a padded video packet (1 to 6 padding bytes) padding_length = data_length - avail; padding_bytes += padding_length; memset (ptr + 6 + 3 + header_data_length, 0xff, padding_length); header_data_length += padding_length; memcpy (ptr + 6 + 3 + header_data_length, voptr, avail); ptr [4] = (SECT_SIZE - (14 + 6)) >> 8; ptr [5] = (SECT_SIZE - (14 + 6)) & 0xff; ptr [8] = header_data_length; return avail; } // this is phase 2 of vaporization // the shrunk video ES is re-packetized by using the source PES packets // unused PS packs are skipped // only wanted private stream 1 and MPEG audio packs are copied // all nav packs are copied void k9vamps::vap_phase2 (int seq_length) { int i, id, avail, data_length; uchar *ptr, *voptr = vobuf, *vohwp = vobuf + volen; for (i = 0; i < seq_length; i += SECT_SIZE) { ptr = rptr + 14; id = ptr [3]; switch (id) { case 0xe0: // video avail = vohwp - voptr; if (avail) { // still some video output data left voptr += gen_video_packet (ptr, voptr, avail); copy (SECT_SIZE); if (m_dvdbackup) m_dvdbackup->getOutput(k9DVDBackupInterface::VIDEO,0,ptr,SECT_SIZE); } else { // no video output data left - skip input sector skip (SECT_SIZE); skipped_video_packs++; } break; case 0xbd: // private 1: audio/subpicture copy_private_1 (ptr); break; case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: // MPEG audio copy_mpeg_audio (ptr); break; case 0xbb: // system header/private 2: PCI/DSI copy (SECT_SIZE); if (m_dvdbackup) m_dvdbackup->getOutput(k9DVDBackupInterface::NAV,0,ptr,SECT_SIZE); break; case 0xbe: // padding data_length = ptr [4] << 8; data_length |= ptr [5]; if (14 + data_length != SECT_SIZE - 6) fatal (QString("Bad padding packet length at %1: %2").arg(rtell (ptr)).arg(data_length)); //JMP: à vérifier skip (SECT_SIZE); break; default: copy (SECT_SIZE); // fatal("Encountered stream ID %02x at %llu, " // "probably bad MPEG2 program stream", id, rtell (ptr)); } if (wptr == wbuf + WBUF_SIZE) // end of write buffer reached --> flush it to disk flush (); } } QString & k9vamps::geterrMsg() { return m_errMsg; } bool k9vamps::geterror() { return m_error; } // entry point from main() // the requant thread already has been started void k9vamps::vaporize (void) { int seq_length; float fact = vap_fact; // process PS up to but not including first sequence header vap_leader (); // just in case - maybe should spit out a warning/error here if (eof) return; total_packs++; nav_packs++; total_packs++; video_packs++; // main loop while (1) { // do phase 1 of vaporization seq_length = vap_phase1 (); if (eof) { // EOF on source PS // process packs after and including last sequence header vap_trailer (seq_length); // only exit point from main loop return; } //fprintf (stderr, "seq_length=%d\n", seq_length); if (calc_ps_vap && vap_fact > 1.0f) { // forecast video ES vaporization factor // the basic formulars look like: // vap_fact = total_packs/(restpacks+vop) // restpacks = total_packs-(video_packs+skipped_aux_packs) // fact = (video_packs*net-(gops*net/2+10))/(vop*net-(gops*net/2+10)) // net = SECT_SIZE-(14+9) // 14: pack header size // 9: PES header sizerequant // 10: PTS+DTS size in PES header of sequence header // You are welcome to double check everything here! float vop, net; net = (float) (SECT_SIZE - (14+9)); vop = video_packs + skipped_aux_packs - (float) total_packs * (1.0f-1.0f/vap_fact); fact = ((float) video_packs * net - ((float) sequence_headers * net/2.0f + 10.0f)) / (vop * net - ((float) sequence_headers * net/2.0f + 10.0f)); //JMP m_totfact+=fact ; m_nbfact++; m_avgfact=m_totfact/m_nbfact; // requant seems to get stuck on factors < 1 if (fact < 1.0f) fact = 1.0f; if (verbose >= 2) fprintf (stderr, "Info: Target video ES vaporization factor: %.3f\n", fact); } vin_bytes += vilen; if (fact > 1.0f) { // do requantization volen = requant (vobuf, vibuf, vilen, fact); } else { // don't do requantization memcpy (vobuf, vibuf, vilen); volen = vilen; } vout_bytes += volen; // do phase 2 of vaporization vap_phase2 (seq_length); //fprintf (stderr, // "tot=%d, vid=%d, ps1=%d, nav=%d, sv=%d, sp1=%d, fact=%.3f\n", // total_packs, video_packs, aux_packs, nav_packs, // skipped_video_packs, skipped_aux_packs, fact); } } uint64_t k9vamps::getOutputBytes() { return bytes_written; } uint64_t k9vamps::getSkippedBytes() { return skipped_aux_packs+skipped_video_packs; } void k9vamps::abort() { //fatal("vamps stopped"); setNoData(); if (m_requant !=NULL) m_requant->wait(); if (m_bgUpdate!=NULL) m_bgUpdate->wait(); } // this is a *very* sophisticated kind of error handling :-) void k9vamps::fatal (QString msg) { m_errMsg=msg; m_error=true; if (m_requant !=NULL) m_requant->terminate(); if (m_bgUpdate !=NULL) m_bgUpdate->terminate(); terminate(); } /**************************** BACKGROUND UPDATE **********************/ k9bgUpdate::k9bgUpdate(k9DVDBackupInterface * _backup) { m_backup = _backup; } void k9bgUpdate::update(uchar *_buffer,uint32_t _size) { //à vérifier: ajout d'un wait pour s'assurer que le thread n'est pas en cours d'exécution wait(); mutex.lock(); m_buffer=new uchar[_size]; memcpy(m_buffer,_buffer,_size); m_size=_size; start(); mutex.unlock(); } void k9bgUpdate::run() { m_backup->getOutput(m_buffer,m_size); delete[] m_buffer; } k9copy/src/vamps/qTable.h0000644000175000017550000017204412412271774016060 0ustar emulatoremulatorstatic short quant_equ[113] = { 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41 }; static short quant_table_1_to_2[4096]; static short quant_table_1_to_3[4096]; static short quant_table_1_to_4[4096]; static short quant_table_1_to_5[4096]; static short quant_table_1_to_6[4096]; static short quant_table_1_to_7[4096]; static short quant_table_1_to_8[4096]; static short quant_table_1_to_10[4096]; static short quant_table_1_to_12[4096]; static short quant_table_1_to_14[4096]; static short quant_table_1_to_16[4096]; static short quant_table_1_to_18[4096]; static short quant_table_1_to_20[4096]; static short quant_table_1_to_22[4096]; static short quant_table_1_to_24[4096]; static short quant_table_1_to_26[4096]; static short quant_table_1_to_28[4096]; static short quant_table_1_to_30[4096]; static short quant_table_1_to_32[4096]; static short quant_table_1_to_34[4096]; static short quant_table_1_to_36[4096]; static short quant_table_1_to_38[4096]; static short quant_table_1_to_40[4096]; static short quant_table_1_to_42[4096]; static short quant_table_1_to_44[4096]; static short quant_table_1_to_46[4096]; static short quant_table_1_to_48[4096]; static short quant_table_1_to_50[4096]; static short quant_table_1_to_52[4096]; static short quant_table_1_to_54[4096]; static short quant_table_1_to_56[4096]; static short quant_table_1_to_58[4096]; static short quant_table_1_to_60[4096]; static short quant_table_1_to_62[4096]; static short quant_table_1_to_64[4096]; static short quant_table_1_to_72[4096]; static short quant_table_1_to_80[4096]; static short quant_table_1_to_88[4096]; static short quant_table_1_to_96[4096]; static short quant_table_1_to_104[4096]; static short quant_table_1_to_112[4096]; static short quant_table_2_to_3[4096]; static short quant_table_2_to_4[4096]; static short quant_table_2_to_5[4096]; static short quant_table_2_to_6[4096]; static short quant_table_2_to_7[4096]; static short quant_table_2_to_8[4096]; static short quant_table_2_to_10[4096]; static short quant_table_2_to_12[4096]; static short quant_table_2_to_14[4096]; static short quant_table_2_to_16[4096]; static short quant_table_2_to_18[4096]; static short quant_table_2_to_20[4096]; static short quant_table_2_to_22[4096]; static short quant_table_2_to_24[4096]; static short quant_table_2_to_26[4096]; static short quant_table_2_to_28[4096]; static short quant_table_2_to_30[4096]; static short quant_table_2_to_32[4096]; static short quant_table_2_to_34[4096]; static short quant_table_2_to_36[4096]; static short quant_table_2_to_38[4096]; static short quant_table_2_to_40[4096]; static short quant_table_2_to_42[4096]; static short quant_table_2_to_44[4096]; static short quant_table_2_to_46[4096]; static short quant_table_2_to_48[4096]; static short quant_table_2_to_50[4096]; static short quant_table_2_to_52[4096]; static short quant_table_2_to_54[4096]; static short quant_table_2_to_56[4096]; static short quant_table_2_to_58[4096]; static short quant_table_2_to_60[4096]; static short quant_table_2_to_62[4096]; static short quant_table_2_to_64[4096]; static short quant_table_2_to_72[4096]; static short quant_table_2_to_80[4096]; static short quant_table_2_to_88[4096]; static short quant_table_2_to_96[4096]; static short quant_table_2_to_104[4096]; static short quant_table_2_to_112[4096]; static short quant_table_3_to_4[4096]; static short quant_table_3_to_5[4096]; static short quant_table_3_to_6[4096]; static short quant_table_3_to_7[4096]; static short quant_table_3_to_8[4096]; static short quant_table_3_to_10[4096]; static short quant_table_3_to_12[4096]; static short quant_table_3_to_14[4096]; static short quant_table_3_to_16[4096]; static short quant_table_3_to_18[4096]; static short quant_table_3_to_20[4096]; static short quant_table_3_to_22[4096]; static short quant_table_3_to_24[4096]; static short quant_table_3_to_26[4096]; static short quant_table_3_to_28[4096]; static short quant_table_3_to_30[4096]; static short quant_table_3_to_32[4096]; static short quant_table_3_to_34[4096]; static short quant_table_3_to_36[4096]; static short quant_table_3_to_38[4096]; static short quant_table_3_to_40[4096]; static short quant_table_3_to_42[4096]; static short quant_table_3_to_44[4096]; static short quant_table_3_to_46[4096]; static short quant_table_3_to_48[4096]; static short quant_table_3_to_50[4096]; static short quant_table_3_to_52[4096]; static short quant_table_3_to_54[4096]; static short quant_table_3_to_56[4096]; static short quant_table_3_to_58[4096]; static short quant_table_3_to_60[4096]; static short quant_table_3_to_62[4096]; static short quant_table_3_to_64[4096]; static short quant_table_3_to_72[4096]; static short quant_table_3_to_80[4096]; static short quant_table_3_to_88[4096]; static short quant_table_3_to_96[4096]; static short quant_table_3_to_104[4096]; static short quant_table_3_to_112[4096]; static short quant_table_4_to_5[4096]; static short quant_table_4_to_6[4096]; static short quant_table_4_to_7[4096]; static short quant_table_4_to_8[4096]; static short quant_table_4_to_10[4096]; static short quant_table_4_to_12[4096]; static short quant_table_4_to_14[4096]; static short quant_table_4_to_16[4096]; static short quant_table_4_to_18[4096]; static short quant_table_4_to_20[4096]; static short quant_table_4_to_22[4096]; static short quant_table_4_to_24[4096]; static short quant_table_4_to_26[4096]; static short quant_table_4_to_28[4096]; static short quant_table_4_to_30[4096]; static short quant_table_4_to_32[4096]; static short quant_table_4_to_34[4096]; static short quant_table_4_to_36[4096]; static short quant_table_4_to_38[4096]; static short quant_table_4_to_40[4096]; static short quant_table_4_to_42[4096]; static short quant_table_4_to_44[4096]; static short quant_table_4_to_46[4096]; static short quant_table_4_to_48[4096]; static short quant_table_4_to_50[4096]; static short quant_table_4_to_52[4096]; static short quant_table_4_to_54[4096]; static short quant_table_4_to_56[4096]; static short quant_table_4_to_58[4096]; static short quant_table_4_to_60[4096]; static short quant_table_4_to_62[4096]; static short quant_table_4_to_64[4096]; static short quant_table_4_to_72[4096]; static short quant_table_4_to_80[4096]; static short quant_table_4_to_88[4096]; static short quant_table_4_to_96[4096]; static short quant_table_4_to_104[4096]; static short quant_table_4_to_112[4096]; static short quant_table_5_to_6[4096]; static short quant_table_5_to_7[4096]; static short quant_table_5_to_8[4096]; static short quant_table_5_to_10[4096]; static short quant_table_5_to_12[4096]; static short quant_table_5_to_14[4096]; static short quant_table_5_to_16[4096]; static short quant_table_5_to_18[4096]; static short quant_table_5_to_20[4096]; static short quant_table_5_to_22[4096]; static short quant_table_5_to_24[4096]; static short quant_table_5_to_26[4096]; static short quant_table_5_to_28[4096]; static short quant_table_5_to_30[4096]; static short quant_table_5_to_32[4096]; static short quant_table_5_to_34[4096]; static short quant_table_5_to_36[4096]; static short quant_table_5_to_38[4096]; static short quant_table_5_to_40[4096]; static short quant_table_5_to_42[4096]; static short quant_table_5_to_44[4096]; static short quant_table_5_to_46[4096]; static short quant_table_5_to_48[4096]; static short quant_table_5_to_50[4096]; static short quant_table_5_to_52[4096]; static short quant_table_5_to_54[4096]; static short quant_table_5_to_56[4096]; static short quant_table_5_to_58[4096]; static short quant_table_5_to_60[4096]; static short quant_table_5_to_62[4096]; static short quant_table_5_to_64[4096]; static short quant_table_5_to_72[4096]; static short quant_table_5_to_80[4096]; static short quant_table_5_to_88[4096]; static short quant_table_5_to_96[4096]; static short quant_table_5_to_104[4096]; static short quant_table_5_to_112[4096]; static short quant_table_6_to_7[4096]; static short quant_table_6_to_8[4096]; static short quant_table_6_to_10[4096]; static short quant_table_6_to_12[4096]; static short quant_table_6_to_14[4096]; static short quant_table_6_to_16[4096]; static short quant_table_6_to_18[4096]; static short quant_table_6_to_20[4096]; static short quant_table_6_to_22[4096]; static short quant_table_6_to_24[4096]; static short quant_table_6_to_26[4096]; static short quant_table_6_to_28[4096]; static short quant_table_6_to_30[4096]; static short quant_table_6_to_32[4096]; static short quant_table_6_to_34[4096]; static short quant_table_6_to_36[4096]; static short quant_table_6_to_38[4096]; static short quant_table_6_to_40[4096]; static short quant_table_6_to_42[4096]; static short quant_table_6_to_44[4096]; static short quant_table_6_to_46[4096]; static short quant_table_6_to_48[4096]; static short quant_table_6_to_50[4096]; static short quant_table_6_to_52[4096]; static short quant_table_6_to_54[4096]; static short quant_table_6_to_56[4096]; static short quant_table_6_to_58[4096]; static short quant_table_6_to_60[4096]; static short quant_table_6_to_62[4096]; static short quant_table_6_to_64[4096]; static short quant_table_6_to_72[4096]; static short quant_table_6_to_80[4096]; static short quant_table_6_to_88[4096]; static short quant_table_6_to_96[4096]; static short quant_table_6_to_104[4096]; static short quant_table_6_to_112[4096]; static short quant_table_7_to_8[4096]; static short quant_table_7_to_10[4096]; static short quant_table_7_to_12[4096]; static short quant_table_7_to_14[4096]; static short quant_table_7_to_16[4096]; static short quant_table_7_to_18[4096]; static short quant_table_7_to_20[4096]; static short quant_table_7_to_22[4096]; static short quant_table_7_to_24[4096]; static short quant_table_7_to_26[4096]; static short quant_table_7_to_28[4096]; static short quant_table_7_to_30[4096]; static short quant_table_7_to_32[4096]; static short quant_table_7_to_34[4096]; static short quant_table_7_to_36[4096]; static short quant_table_7_to_38[4096]; static short quant_table_7_to_40[4096]; static short quant_table_7_to_42[4096]; static short quant_table_7_to_44[4096]; static short quant_table_7_to_46[4096]; static short quant_table_7_to_48[4096]; static short quant_table_7_to_50[4096]; static short quant_table_7_to_52[4096]; static short quant_table_7_to_54[4096]; static short quant_table_7_to_56[4096]; static short quant_table_7_to_58[4096]; static short quant_table_7_to_60[4096]; static short quant_table_7_to_62[4096]; static short quant_table_7_to_64[4096]; static short quant_table_7_to_72[4096]; static short quant_table_7_to_80[4096]; static short quant_table_7_to_88[4096]; static short quant_table_7_to_96[4096]; static short quant_table_7_to_104[4096]; static short quant_table_7_to_112[4096]; static short quant_table_8_to_10[4096]; static short quant_table_8_to_12[4096]; static short quant_table_8_to_14[4096]; static short quant_table_8_to_16[4096]; static short quant_table_8_to_18[4096]; static short quant_table_8_to_20[4096]; static short quant_table_8_to_22[4096]; static short quant_table_8_to_24[4096]; static short quant_table_8_to_26[4096]; static short quant_table_8_to_28[4096]; static short quant_table_8_to_30[4096]; static short quant_table_8_to_32[4096]; static short quant_table_8_to_34[4096]; static short quant_table_8_to_36[4096]; static short quant_table_8_to_38[4096]; static short quant_table_8_to_40[4096]; static short quant_table_8_to_42[4096]; static short quant_table_8_to_44[4096]; static short quant_table_8_to_46[4096]; static short quant_table_8_to_48[4096]; static short quant_table_8_to_50[4096]; static short quant_table_8_to_52[4096]; static short quant_table_8_to_54[4096]; static short quant_table_8_to_56[4096]; static short quant_table_8_to_58[4096]; static short quant_table_8_to_60[4096]; static short quant_table_8_to_62[4096]; static short quant_table_8_to_64[4096]; static short quant_table_8_to_72[4096]; static short quant_table_8_to_80[4096]; static short quant_table_8_to_88[4096]; static short quant_table_8_to_96[4096]; static short quant_table_8_to_104[4096]; static short quant_table_8_to_112[4096]; static short quant_table_10_to_12[4096]; static short quant_table_10_to_14[4096]; static short quant_table_10_to_16[4096]; static short quant_table_10_to_18[4096]; static short quant_table_10_to_20[4096]; static short quant_table_10_to_22[4096]; static short quant_table_10_to_24[4096]; static short quant_table_10_to_26[4096]; static short quant_table_10_to_28[4096]; static short quant_table_10_to_30[4096]; static short quant_table_10_to_32[4096]; static short quant_table_10_to_34[4096]; static short quant_table_10_to_36[4096]; static short quant_table_10_to_38[4096]; static short quant_table_10_to_40[4096]; static short quant_table_10_to_42[4096]; static short quant_table_10_to_44[4096]; static short quant_table_10_to_46[4096]; static short quant_table_10_to_48[4096]; static short quant_table_10_to_50[4096]; static short quant_table_10_to_52[4096]; static short quant_table_10_to_54[4096]; static short quant_table_10_to_56[4096]; static short quant_table_10_to_58[4096]; static short quant_table_10_to_60[4096]; static short quant_table_10_to_62[4096]; static short quant_table_10_to_64[4096]; static short quant_table_10_to_72[4096]; static short quant_table_10_to_80[4096]; static short quant_table_10_to_88[4096]; static short quant_table_10_to_96[4096]; static short quant_table_10_to_104[4096]; static short quant_table_10_to_112[4096]; static short quant_table_12_to_14[4096]; static short quant_table_12_to_16[4096]; static short quant_table_12_to_18[4096]; static short quant_table_12_to_20[4096]; static short quant_table_12_to_22[4096]; static short quant_table_12_to_24[4096]; static short quant_table_12_to_26[4096]; static short quant_table_12_to_28[4096]; static short quant_table_12_to_30[4096]; static short quant_table_12_to_32[4096]; static short quant_table_12_to_34[4096]; static short quant_table_12_to_36[4096]; static short quant_table_12_to_38[4096]; static short quant_table_12_to_40[4096]; static short quant_table_12_to_42[4096]; static short quant_table_12_to_44[4096]; static short quant_table_12_to_46[4096]; static short quant_table_12_to_48[4096]; static short quant_table_12_to_50[4096]; static short quant_table_12_to_52[4096]; static short quant_table_12_to_54[4096]; static short quant_table_12_to_56[4096]; static short quant_table_12_to_58[4096]; static short quant_table_12_to_60[4096]; static short quant_table_12_to_62[4096]; static short quant_table_12_to_64[4096]; static short quant_table_12_to_72[4096]; static short quant_table_12_to_80[4096]; static short quant_table_12_to_88[4096]; static short quant_table_12_to_96[4096]; static short quant_table_12_to_104[4096]; static short quant_table_12_to_112[4096]; static short quant_table_14_to_16[4096]; static short quant_table_14_to_18[4096]; static short quant_table_14_to_20[4096]; static short quant_table_14_to_22[4096]; static short quant_table_14_to_24[4096]; static short quant_table_14_to_26[4096]; static short quant_table_14_to_28[4096]; static short quant_table_14_to_30[4096]; static short quant_table_14_to_32[4096]; static short quant_table_14_to_34[4096]; static short quant_table_14_to_36[4096]; static short quant_table_14_to_38[4096]; static short quant_table_14_to_40[4096]; static short quant_table_14_to_42[4096]; static short quant_table_14_to_44[4096]; static short quant_table_14_to_46[4096]; static short quant_table_14_to_48[4096]; static short quant_table_14_to_50[4096]; static short quant_table_14_to_52[4096]; static short quant_table_14_to_54[4096]; static short quant_table_14_to_56[4096]; static short quant_table_14_to_58[4096]; static short quant_table_14_to_60[4096]; static short quant_table_14_to_62[4096]; static short quant_table_14_to_64[4096]; static short quant_table_14_to_72[4096]; static short quant_table_14_to_80[4096]; static short quant_table_14_to_88[4096]; static short quant_table_14_to_96[4096]; static short quant_table_14_to_104[4096]; static short quant_table_14_to_112[4096]; static short quant_table_16_to_18[4096]; static short quant_table_16_to_20[4096]; static short quant_table_16_to_22[4096]; static short quant_table_16_to_24[4096]; static short quant_table_16_to_26[4096]; static short quant_table_16_to_28[4096]; static short quant_table_16_to_30[4096]; static short quant_table_16_to_32[4096]; static short quant_table_16_to_34[4096]; static short quant_table_16_to_36[4096]; static short quant_table_16_to_38[4096]; static short quant_table_16_to_40[4096]; static short quant_table_16_to_42[4096]; static short quant_table_16_to_44[4096]; static short quant_table_16_to_46[4096]; static short quant_table_16_to_48[4096]; static short quant_table_16_to_50[4096]; static short quant_table_16_to_52[4096]; static short quant_table_16_to_54[4096]; static short quant_table_16_to_56[4096]; static short quant_table_16_to_58[4096]; static short quant_table_16_to_60[4096]; static short quant_table_16_to_62[4096]; static short quant_table_16_to_64[4096]; static short quant_table_16_to_72[4096]; static short quant_table_16_to_80[4096]; static short quant_table_16_to_88[4096]; static short quant_table_16_to_96[4096]; static short quant_table_16_to_104[4096]; static short quant_table_16_to_112[4096]; static short quant_table_18_to_20[4096]; static short quant_table_18_to_22[4096]; static short quant_table_18_to_24[4096]; static short quant_table_18_to_26[4096]; static short quant_table_18_to_28[4096]; static short quant_table_18_to_30[4096]; static short quant_table_18_to_32[4096]; static short quant_table_18_to_34[4096]; static short quant_table_18_to_36[4096]; static short quant_table_18_to_38[4096]; static short quant_table_18_to_40[4096]; static short quant_table_18_to_42[4096]; static short quant_table_18_to_44[4096]; static short quant_table_18_to_46[4096]; static short quant_table_18_to_48[4096]; static short quant_table_18_to_50[4096]; static short quant_table_18_to_52[4096]; static short quant_table_18_to_54[4096]; static short quant_table_18_to_56[4096]; static short quant_table_18_to_58[4096]; static short quant_table_18_to_60[4096]; static short quant_table_18_to_62[4096]; static short quant_table_18_to_64[4096]; static short quant_table_18_to_72[4096]; static short quant_table_18_to_80[4096]; static short quant_table_18_to_88[4096]; static short quant_table_18_to_96[4096]; static short quant_table_18_to_104[4096]; static short quant_table_18_to_112[4096]; static short quant_table_20_to_22[4096]; static short quant_table_20_to_24[4096]; static short quant_table_20_to_26[4096]; static short quant_table_20_to_28[4096]; static short quant_table_20_to_30[4096]; static short quant_table_20_to_32[4096]; static short quant_table_20_to_34[4096]; static short quant_table_20_to_36[4096]; static short quant_table_20_to_38[4096]; static short quant_table_20_to_40[4096]; static short quant_table_20_to_42[4096]; static short quant_table_20_to_44[4096]; static short quant_table_20_to_46[4096]; static short quant_table_20_to_48[4096]; static short quant_table_20_to_50[4096]; static short quant_table_20_to_52[4096]; static short quant_table_20_to_54[4096]; static short quant_table_20_to_56[4096]; static short quant_table_20_to_58[4096]; static short quant_table_20_to_60[4096]; static short quant_table_20_to_62[4096]; static short quant_table_20_to_64[4096]; static short quant_table_20_to_72[4096]; static short quant_table_20_to_80[4096]; static short quant_table_20_to_88[4096]; static short quant_table_20_to_96[4096]; static short quant_table_20_to_104[4096]; static short quant_table_20_to_112[4096]; static short quant_table_22_to_24[4096]; static short quant_table_22_to_26[4096]; static short quant_table_22_to_28[4096]; static short quant_table_22_to_30[4096]; static short quant_table_22_to_32[4096]; static short quant_table_22_to_34[4096]; static short quant_table_22_to_36[4096]; static short quant_table_22_to_38[4096]; static short quant_table_22_to_40[4096]; static short quant_table_22_to_42[4096]; static short quant_table_22_to_44[4096]; static short quant_table_22_to_46[4096]; static short quant_table_22_to_48[4096]; static short quant_table_22_to_50[4096]; static short quant_table_22_to_52[4096]; static short quant_table_22_to_54[4096]; static short quant_table_22_to_56[4096]; static short quant_table_22_to_58[4096]; static short quant_table_22_to_60[4096]; static short quant_table_22_to_62[4096]; static short quant_table_22_to_64[4096]; static short quant_table_22_to_72[4096]; static short quant_table_22_to_80[4096]; static short quant_table_22_to_88[4096]; static short quant_table_22_to_96[4096]; static short quant_table_22_to_104[4096]; static short quant_table_22_to_112[4096]; static short quant_table_24_to_26[4096]; static short quant_table_24_to_28[4096]; static short quant_table_24_to_30[4096]; static short quant_table_24_to_32[4096]; static short quant_table_24_to_34[4096]; static short quant_table_24_to_36[4096]; static short quant_table_24_to_38[4096]; static short quant_table_24_to_40[4096]; static short quant_table_24_to_42[4096]; static short quant_table_24_to_44[4096]; static short quant_table_24_to_46[4096]; static short quant_table_24_to_48[4096]; static short quant_table_24_to_50[4096]; static short quant_table_24_to_52[4096]; static short quant_table_24_to_54[4096]; static short quant_table_24_to_56[4096]; static short quant_table_24_to_58[4096]; static short quant_table_24_to_60[4096]; static short quant_table_24_to_62[4096]; static short quant_table_24_to_64[4096]; static short quant_table_24_to_72[4096]; static short quant_table_24_to_80[4096]; static short quant_table_24_to_88[4096]; static short quant_table_24_to_96[4096]; static short quant_table_24_to_104[4096]; static short quant_table_24_to_112[4096]; static short quant_table_26_to_28[4096]; static short quant_table_26_to_30[4096]; static short quant_table_26_to_32[4096]; static short quant_table_26_to_34[4096]; static short quant_table_26_to_36[4096]; static short quant_table_26_to_38[4096]; static short quant_table_26_to_40[4096]; static short quant_table_26_to_42[4096]; static short quant_table_26_to_44[4096]; static short quant_table_26_to_46[4096]; static short quant_table_26_to_48[4096]; static short quant_table_26_to_50[4096]; static short quant_table_26_to_52[4096]; static short quant_table_26_to_54[4096]; static short quant_table_26_to_56[4096]; static short quant_table_26_to_58[4096]; static short quant_table_26_to_60[4096]; static short quant_table_26_to_62[4096]; static short quant_table_26_to_64[4096]; static short quant_table_26_to_72[4096]; static short quant_table_26_to_80[4096]; static short quant_table_26_to_88[4096]; static short quant_table_26_to_96[4096]; static short quant_table_26_to_104[4096]; static short quant_table_26_to_112[4096]; static short quant_table_28_to_30[4096]; static short quant_table_28_to_32[4096]; static short quant_table_28_to_34[4096]; static short quant_table_28_to_36[4096]; static short quant_table_28_to_38[4096]; static short quant_table_28_to_40[4096]; static short quant_table_28_to_42[4096]; static short quant_table_28_to_44[4096]; static short quant_table_28_to_46[4096]; static short quant_table_28_to_48[4096]; static short quant_table_28_to_50[4096]; static short quant_table_28_to_52[4096]; static short quant_table_28_to_54[4096]; static short quant_table_28_to_56[4096]; static short quant_table_28_to_58[4096]; static short quant_table_28_to_60[4096]; static short quant_table_28_to_62[4096]; static short quant_table_28_to_64[4096]; static short quant_table_28_to_72[4096]; static short quant_table_28_to_80[4096]; static short quant_table_28_to_88[4096]; static short quant_table_28_to_96[4096]; static short quant_table_28_to_104[4096]; static short quant_table_28_to_112[4096]; static short quant_table_30_to_32[4096]; static short quant_table_30_to_34[4096]; static short quant_table_30_to_36[4096]; static short quant_table_30_to_38[4096]; static short quant_table_30_to_40[4096]; static short quant_table_30_to_42[4096]; static short quant_table_30_to_44[4096]; static short quant_table_30_to_46[4096]; static short quant_table_30_to_48[4096]; static short quant_table_30_to_50[4096]; static short quant_table_30_to_52[4096]; static short quant_table_30_to_54[4096]; static short quant_table_30_to_56[4096]; static short quant_table_30_to_58[4096]; static short quant_table_30_to_60[4096]; static short quant_table_30_to_62[4096]; static short quant_table_30_to_64[4096]; static short quant_table_30_to_72[4096]; static short quant_table_30_to_80[4096]; static short quant_table_30_to_88[4096]; static short quant_table_30_to_96[4096]; static short quant_table_30_to_104[4096]; static short quant_table_30_to_112[4096]; static short quant_table_32_to_34[4096]; static short quant_table_32_to_36[4096]; static short quant_table_32_to_38[4096]; static short quant_table_32_to_40[4096]; static short quant_table_32_to_42[4096]; static short quant_table_32_to_44[4096]; static short quant_table_32_to_46[4096]; static short quant_table_32_to_48[4096]; static short quant_table_32_to_50[4096]; static short quant_table_32_to_52[4096]; static short quant_table_32_to_54[4096]; static short quant_table_32_to_56[4096]; static short quant_table_32_to_58[4096]; static short quant_table_32_to_60[4096]; static short quant_table_32_to_62[4096]; static short quant_table_32_to_64[4096]; static short quant_table_32_to_72[4096]; static short quant_table_32_to_80[4096]; static short quant_table_32_to_88[4096]; static short quant_table_32_to_96[4096]; static short quant_table_32_to_104[4096]; static short quant_table_32_to_112[4096]; static short quant_table_34_to_36[4096]; static short quant_table_34_to_38[4096]; static short quant_table_34_to_40[4096]; static short quant_table_34_to_42[4096]; static short quant_table_34_to_44[4096]; static short quant_table_34_to_46[4096]; static short quant_table_34_to_48[4096]; static short quant_table_34_to_50[4096]; static short quant_table_34_to_52[4096]; static short quant_table_34_to_54[4096]; static short quant_table_34_to_56[4096]; static short quant_table_34_to_58[4096]; static short quant_table_34_to_60[4096]; static short quant_table_34_to_62[4096]; static short quant_table_34_to_64[4096]; static short quant_table_34_to_72[4096]; static short quant_table_34_to_80[4096]; static short quant_table_34_to_88[4096]; static short quant_table_34_to_96[4096]; static short quant_table_34_to_104[4096]; static short quant_table_34_to_112[4096]; static short quant_table_36_to_38[4096]; static short quant_table_36_to_40[4096]; static short quant_table_36_to_42[4096]; static short quant_table_36_to_44[4096]; static short quant_table_36_to_46[4096]; static short quant_table_36_to_48[4096]; static short quant_table_36_to_50[4096]; static short quant_table_36_to_52[4096]; static short quant_table_36_to_54[4096]; static short quant_table_36_to_56[4096]; static short quant_table_36_to_58[4096]; static short quant_table_36_to_60[4096]; static short quant_table_36_to_62[4096]; static short quant_table_36_to_64[4096]; static short quant_table_36_to_72[4096]; static short quant_table_36_to_80[4096]; static short quant_table_36_to_88[4096]; static short quant_table_36_to_96[4096]; static short quant_table_36_to_104[4096]; static short quant_table_36_to_112[4096]; static short quant_table_38_to_40[4096]; static short quant_table_38_to_42[4096]; static short quant_table_38_to_44[4096]; static short quant_table_38_to_46[4096]; static short quant_table_38_to_48[4096]; static short quant_table_38_to_50[4096]; static short quant_table_38_to_52[4096]; static short quant_table_38_to_54[4096]; static short quant_table_38_to_56[4096]; static short quant_table_38_to_58[4096]; static short quant_table_38_to_60[4096]; static short quant_table_38_to_62[4096]; static short quant_table_38_to_64[4096]; static short quant_table_38_to_72[4096]; static short quant_table_38_to_80[4096]; static short quant_table_38_to_88[4096]; static short quant_table_38_to_96[4096]; static short quant_table_38_to_104[4096]; static short quant_table_38_to_112[4096]; static short quant_table_40_to_42[4096]; static short quant_table_40_to_44[4096]; static short quant_table_40_to_46[4096]; static short quant_table_40_to_48[4096]; static short quant_table_40_to_50[4096]; static short quant_table_40_to_52[4096]; static short quant_table_40_to_54[4096]; static short quant_table_40_to_56[4096]; static short quant_table_40_to_58[4096]; static short quant_table_40_to_60[4096]; static short quant_table_40_to_62[4096]; static short quant_table_40_to_64[4096]; static short quant_table_40_to_72[4096]; static short quant_table_40_to_80[4096]; static short quant_table_40_to_88[4096]; static short quant_table_40_to_96[4096]; static short quant_table_40_to_104[4096]; static short quant_table_40_to_112[4096]; static short quant_table_42_to_44[4096]; static short quant_table_42_to_46[4096]; static short quant_table_42_to_48[4096]; static short quant_table_42_to_50[4096]; static short quant_table_42_to_52[4096]; static short quant_table_42_to_54[4096]; static short quant_table_42_to_56[4096]; static short quant_table_42_to_58[4096]; static short quant_table_42_to_60[4096]; static short quant_table_42_to_62[4096]; static short quant_table_42_to_64[4096]; static short quant_table_42_to_72[4096]; static short quant_table_42_to_80[4096]; static short quant_table_42_to_88[4096]; static short quant_table_42_to_96[4096]; static short quant_table_42_to_104[4096]; static short quant_table_42_to_112[4096]; static short quant_table_44_to_46[4096]; static short quant_table_44_to_48[4096]; static short quant_table_44_to_50[4096]; static short quant_table_44_to_52[4096]; static short quant_table_44_to_54[4096]; static short quant_table_44_to_56[4096]; static short quant_table_44_to_58[4096]; static short quant_table_44_to_60[4096]; static short quant_table_44_to_62[4096]; static short quant_table_44_to_64[4096]; static short quant_table_44_to_72[4096]; static short quant_table_44_to_80[4096]; static short quant_table_44_to_88[4096]; static short quant_table_44_to_96[4096]; static short quant_table_44_to_104[4096]; static short quant_table_44_to_112[4096]; static short quant_table_46_to_48[4096]; static short quant_table_46_to_50[4096]; static short quant_table_46_to_52[4096]; static short quant_table_46_to_54[4096]; static short quant_table_46_to_56[4096]; static short quant_table_46_to_58[4096]; static short quant_table_46_to_60[4096]; static short quant_table_46_to_62[4096]; static short quant_table_46_to_64[4096]; static short quant_table_46_to_72[4096]; static short quant_table_46_to_80[4096]; static short quant_table_46_to_88[4096]; static short quant_table_46_to_96[4096]; static short quant_table_46_to_104[4096]; static short quant_table_46_to_112[4096]; static short quant_table_48_to_50[4096]; static short quant_table_48_to_52[4096]; static short quant_table_48_to_54[4096]; static short quant_table_48_to_56[4096]; static short quant_table_48_to_58[4096]; static short quant_table_48_to_60[4096]; static short quant_table_48_to_62[4096]; static short quant_table_48_to_64[4096]; static short quant_table_48_to_72[4096]; static short quant_table_48_to_80[4096]; static short quant_table_48_to_88[4096]; static short quant_table_48_to_96[4096]; static short quant_table_48_to_104[4096]; static short quant_table_48_to_112[4096]; static short quant_table_50_to_52[4096]; static short quant_table_50_to_54[4096]; static short quant_table_50_to_56[4096]; static short quant_table_50_to_58[4096]; static short quant_table_50_to_60[4096]; static short quant_table_50_to_62[4096]; static short quant_table_50_to_64[4096]; static short quant_table_50_to_72[4096]; static short quant_table_50_to_80[4096]; static short quant_table_50_to_88[4096]; static short quant_table_50_to_96[4096]; static short quant_table_50_to_104[4096]; static short quant_table_50_to_112[4096]; static short quant_table_52_to_54[4096]; static short quant_table_52_to_56[4096]; static short quant_table_52_to_58[4096]; static short quant_table_52_to_60[4096]; static short quant_table_52_to_62[4096]; static short quant_table_52_to_64[4096]; static short quant_table_52_to_72[4096]; static short quant_table_52_to_80[4096]; static short quant_table_52_to_88[4096]; static short quant_table_52_to_96[4096]; static short quant_table_52_to_104[4096]; static short quant_table_52_to_112[4096]; static short quant_table_54_to_56[4096]; static short quant_table_54_to_58[4096]; static short quant_table_54_to_60[4096]; static short quant_table_54_to_62[4096]; static short quant_table_54_to_64[4096]; static short quant_table_54_to_72[4096]; static short quant_table_54_to_80[4096]; static short quant_table_54_to_88[4096]; static short quant_table_54_to_96[4096]; static short quant_table_54_to_104[4096]; static short quant_table_54_to_112[4096]; static short quant_table_56_to_58[4096]; static short quant_table_56_to_60[4096]; static short quant_table_56_to_62[4096]; static short quant_table_56_to_64[4096]; static short quant_table_56_to_72[4096]; static short quant_table_56_to_80[4096]; static short quant_table_56_to_88[4096]; static short quant_table_56_to_96[4096]; static short quant_table_56_to_104[4096]; static short quant_table_56_to_112[4096]; static short quant_table_58_to_60[4096]; static short quant_table_58_to_62[4096]; static short quant_table_58_to_64[4096]; static short quant_table_58_to_72[4096]; static short quant_table_58_to_80[4096]; static short quant_table_58_to_88[4096]; static short quant_table_58_to_96[4096]; static short quant_table_58_to_104[4096]; static short quant_table_58_to_112[4096]; static short quant_table_60_to_62[4096]; static short quant_table_60_to_64[4096]; static short quant_table_60_to_72[4096]; static short quant_table_60_to_80[4096]; static short quant_table_60_to_88[4096]; static short quant_table_60_to_96[4096]; static short quant_table_60_to_104[4096]; static short quant_table_60_to_112[4096]; static short quant_table_62_to_64[4096]; static short quant_table_62_to_72[4096]; static short quant_table_62_to_80[4096]; static short quant_table_62_to_88[4096]; static short quant_table_62_to_96[4096]; static short quant_table_62_to_104[4096]; static short quant_table_62_to_112[4096]; static short quant_table_64_to_72[4096]; static short quant_table_64_to_80[4096]; static short quant_table_64_to_88[4096]; static short quant_table_64_to_96[4096]; static short quant_table_64_to_104[4096]; static short quant_table_64_to_112[4096]; static short quant_table_72_to_80[4096]; static short quant_table_72_to_88[4096]; static short quant_table_72_to_96[4096]; static short quant_table_72_to_104[4096]; static short quant_table_72_to_112[4096]; static short quant_table_80_to_88[4096]; static short quant_table_80_to_96[4096]; static short quant_table_80_to_104[4096]; static short quant_table_80_to_112[4096]; static short quant_table_88_to_96[4096]; static short quant_table_88_to_104[4096]; static short quant_table_88_to_112[4096]; static short quant_table_96_to_104[4096]; static short quant_table_96_to_112[4096]; static short quant_table_104_to_112[4096]; static short *quant_tables[42][42] = { { 0, &quant_table_1_to_2[2048], &quant_table_1_to_3[2048], &quant_table_1_to_4[2048], &quant_table_1_to_5[2048], &quant_table_1_to_6[2048], &quant_table_1_to_7[2048], &quant_table_1_to_8[2048], &quant_table_1_to_10[2048], &quant_table_1_to_12[2048], &quant_table_1_to_14[2048], &quant_table_1_to_16[2048], &quant_table_1_to_18[2048], &quant_table_1_to_20[2048], &quant_table_1_to_22[2048], &quant_table_1_to_24[2048], &quant_table_1_to_26[2048], &quant_table_1_to_28[2048], &quant_table_1_to_30[2048], &quant_table_1_to_32[2048], &quant_table_1_to_34[2048], &quant_table_1_to_36[2048], &quant_table_1_to_38[2048], &quant_table_1_to_40[2048], &quant_table_1_to_42[2048], &quant_table_1_to_44[2048], &quant_table_1_to_46[2048], &quant_table_1_to_48[2048], &quant_table_1_to_50[2048], &quant_table_1_to_52[2048], &quant_table_1_to_54[2048], &quant_table_1_to_56[2048], &quant_table_1_to_58[2048], &quant_table_1_to_60[2048], &quant_table_1_to_62[2048], &quant_table_1_to_64[2048], &quant_table_1_to_72[2048], &quant_table_1_to_80[2048], &quant_table_1_to_88[2048], &quant_table_1_to_96[2048], &quant_table_1_to_104[2048], &quant_table_1_to_112[2048]}, { 0,0, &quant_table_2_to_3[2048], &quant_table_2_to_4[2048], &quant_table_2_to_5[2048], &quant_table_2_to_6[2048], &quant_table_2_to_7[2048], &quant_table_2_to_8[2048], &quant_table_2_to_10[2048], &quant_table_2_to_12[2048], &quant_table_2_to_14[2048], &quant_table_2_to_16[2048], &quant_table_2_to_18[2048], &quant_table_2_to_20[2048], &quant_table_2_to_22[2048], &quant_table_2_to_24[2048], &quant_table_2_to_26[2048], &quant_table_2_to_28[2048], &quant_table_2_to_30[2048], &quant_table_2_to_32[2048], &quant_table_2_to_34[2048], &quant_table_2_to_36[2048], &quant_table_2_to_38[2048], &quant_table_2_to_40[2048], &quant_table_2_to_42[2048], &quant_table_2_to_44[2048], &quant_table_2_to_46[2048], &quant_table_2_to_48[2048], &quant_table_2_to_50[2048], &quant_table_2_to_52[2048], &quant_table_2_to_54[2048], &quant_table_2_to_56[2048], &quant_table_2_to_58[2048], &quant_table_2_to_60[2048], &quant_table_2_to_62[2048], &quant_table_2_to_64[2048], &quant_table_2_to_72[2048], &quant_table_2_to_80[2048], &quant_table_2_to_88[2048], &quant_table_2_to_96[2048], &quant_table_2_to_104[2048], &quant_table_2_to_112[2048]}, { 0,0,0, &quant_table_3_to_4[2048], &quant_table_3_to_5[2048], &quant_table_3_to_6[2048], &quant_table_3_to_7[2048], &quant_table_3_to_8[2048], &quant_table_3_to_10[2048], &quant_table_3_to_12[2048], &quant_table_3_to_14[2048], &quant_table_3_to_16[2048], &quant_table_3_to_18[2048], &quant_table_3_to_20[2048], &quant_table_3_to_22[2048], &quant_table_3_to_24[2048], &quant_table_3_to_26[2048], &quant_table_3_to_28[2048], &quant_table_3_to_30[2048], &quant_table_3_to_32[2048], &quant_table_3_to_34[2048], &quant_table_3_to_36[2048], &quant_table_3_to_38[2048], &quant_table_3_to_40[2048], &quant_table_3_to_42[2048], &quant_table_3_to_44[2048], &quant_table_3_to_46[2048], &quant_table_3_to_48[2048], &quant_table_3_to_50[2048], &quant_table_3_to_52[2048], &quant_table_3_to_54[2048], &quant_table_3_to_56[2048], &quant_table_3_to_58[2048], &quant_table_3_to_60[2048], &quant_table_3_to_62[2048], &quant_table_3_to_64[2048], &quant_table_3_to_72[2048], &quant_table_3_to_80[2048], &quant_table_3_to_88[2048], &quant_table_3_to_96[2048], &quant_table_3_to_104[2048], &quant_table_3_to_112[2048]}, { 0,0,0,0, &quant_table_4_to_5[2048], &quant_table_4_to_6[2048], &quant_table_4_to_7[2048], &quant_table_4_to_8[2048], &quant_table_4_to_10[2048], &quant_table_4_to_12[2048], &quant_table_4_to_14[2048], &quant_table_4_to_16[2048], &quant_table_4_to_18[2048], &quant_table_4_to_20[2048], &quant_table_4_to_22[2048], &quant_table_4_to_24[2048], &quant_table_4_to_26[2048], &quant_table_4_to_28[2048], &quant_table_4_to_30[2048], &quant_table_4_to_32[2048], &quant_table_4_to_34[2048], &quant_table_4_to_36[2048], &quant_table_4_to_38[2048], &quant_table_4_to_40[2048], &quant_table_4_to_42[2048], &quant_table_4_to_44[2048], &quant_table_4_to_46[2048], &quant_table_4_to_48[2048], &quant_table_4_to_50[2048], &quant_table_4_to_52[2048], &quant_table_4_to_54[2048], &quant_table_4_to_56[2048], &quant_table_4_to_58[2048], &quant_table_4_to_60[2048], &quant_table_4_to_62[2048], &quant_table_4_to_64[2048], &quant_table_4_to_72[2048], &quant_table_4_to_80[2048], &quant_table_4_to_88[2048], &quant_table_4_to_96[2048], &quant_table_4_to_104[2048], &quant_table_4_to_112[2048]}, { 0,0,0,0,0, &quant_table_5_to_6[2048], &quant_table_5_to_7[2048], &quant_table_5_to_8[2048], &quant_table_5_to_10[2048], &quant_table_5_to_12[2048], &quant_table_5_to_14[2048], &quant_table_5_to_16[2048], &quant_table_5_to_18[2048], &quant_table_5_to_20[2048], &quant_table_5_to_22[2048], &quant_table_5_to_24[2048], &quant_table_5_to_26[2048], &quant_table_5_to_28[2048], &quant_table_5_to_30[2048], &quant_table_5_to_32[2048], &quant_table_5_to_34[2048], &quant_table_5_to_36[2048], &quant_table_5_to_38[2048], &quant_table_5_to_40[2048], &quant_table_5_to_42[2048], &quant_table_5_to_44[2048], &quant_table_5_to_46[2048], &quant_table_5_to_48[2048], &quant_table_5_to_50[2048], &quant_table_5_to_52[2048], &quant_table_5_to_54[2048], &quant_table_5_to_56[2048], &quant_table_5_to_58[2048], &quant_table_5_to_60[2048], &quant_table_5_to_62[2048], &quant_table_5_to_64[2048], &quant_table_5_to_72[2048], &quant_table_5_to_80[2048], &quant_table_5_to_88[2048], &quant_table_5_to_96[2048], &quant_table_5_to_104[2048], &quant_table_5_to_112[2048]}, { 0,0,0,0,0,0, &quant_table_6_to_7[2048], &quant_table_6_to_8[2048], &quant_table_6_to_10[2048], &quant_table_6_to_12[2048], &quant_table_6_to_14[2048], &quant_table_6_to_16[2048], &quant_table_6_to_18[2048], &quant_table_6_to_20[2048], &quant_table_6_to_22[2048], &quant_table_6_to_24[2048], &quant_table_6_to_26[2048], &quant_table_6_to_28[2048], &quant_table_6_to_30[2048], &quant_table_6_to_32[2048], &quant_table_6_to_34[2048], &quant_table_6_to_36[2048], &quant_table_6_to_38[2048], &quant_table_6_to_40[2048], &quant_table_6_to_42[2048], &quant_table_6_to_44[2048], &quant_table_6_to_46[2048], &quant_table_6_to_48[2048], &quant_table_6_to_50[2048], &quant_table_6_to_52[2048], &quant_table_6_to_54[2048], &quant_table_6_to_56[2048], &quant_table_6_to_58[2048], &quant_table_6_to_60[2048], &quant_table_6_to_62[2048], &quant_table_6_to_64[2048], &quant_table_6_to_72[2048], &quant_table_6_to_80[2048], &quant_table_6_to_88[2048], &quant_table_6_to_96[2048], &quant_table_6_to_104[2048], &quant_table_6_to_112[2048]}, { 0,0,0,0,0,0,0, &quant_table_7_to_8[2048], &quant_table_7_to_10[2048], &quant_table_7_to_12[2048], &quant_table_7_to_14[2048], &quant_table_7_to_16[2048], &quant_table_7_to_18[2048], &quant_table_7_to_20[2048], &quant_table_7_to_22[2048], &quant_table_7_to_24[2048], &quant_table_7_to_26[2048], &quant_table_7_to_28[2048], &quant_table_7_to_30[2048], &quant_table_7_to_32[2048], &quant_table_7_to_34[2048], &quant_table_7_to_36[2048], &quant_table_7_to_38[2048], &quant_table_7_to_40[2048], &quant_table_7_to_42[2048], &quant_table_7_to_44[2048], &quant_table_7_to_46[2048], &quant_table_7_to_48[2048], &quant_table_7_to_50[2048], &quant_table_7_to_52[2048], &quant_table_7_to_54[2048], &quant_table_7_to_56[2048], &quant_table_7_to_58[2048], &quant_table_7_to_60[2048], &quant_table_7_to_62[2048], &quant_table_7_to_64[2048], &quant_table_7_to_72[2048], &quant_table_7_to_80[2048], &quant_table_7_to_88[2048], &quant_table_7_to_96[2048], &quant_table_7_to_104[2048], &quant_table_7_to_112[2048]}, { 0,0,0,0,0,0,0,0, &quant_table_8_to_10[2048], &quant_table_8_to_12[2048], &quant_table_8_to_14[2048], &quant_table_8_to_16[2048], &quant_table_8_to_18[2048], &quant_table_8_to_20[2048], &quant_table_8_to_22[2048], &quant_table_8_to_24[2048], &quant_table_8_to_26[2048], &quant_table_8_to_28[2048], &quant_table_8_to_30[2048], &quant_table_8_to_32[2048], &quant_table_8_to_34[2048], &quant_table_8_to_36[2048], &quant_table_8_to_38[2048], &quant_table_8_to_40[2048], &quant_table_8_to_42[2048], &quant_table_8_to_44[2048], &quant_table_8_to_46[2048], &quant_table_8_to_48[2048], &quant_table_8_to_50[2048], &quant_table_8_to_52[2048], &quant_table_8_to_54[2048], &quant_table_8_to_56[2048], &quant_table_8_to_58[2048], &quant_table_8_to_60[2048], &quant_table_8_to_62[2048], &quant_table_8_to_64[2048], &quant_table_8_to_72[2048], &quant_table_8_to_80[2048], &quant_table_8_to_88[2048], &quant_table_8_to_96[2048], &quant_table_8_to_104[2048], &quant_table_8_to_112[2048]}, { 0,0,0,0,0,0,0,0,0, &quant_table_10_to_12[2048], &quant_table_10_to_14[2048], &quant_table_10_to_16[2048], &quant_table_10_to_18[2048], &quant_table_10_to_20[2048], &quant_table_10_to_22[2048], &quant_table_10_to_24[2048], &quant_table_10_to_26[2048], &quant_table_10_to_28[2048], &quant_table_10_to_30[2048], &quant_table_10_to_32[2048], &quant_table_10_to_34[2048], &quant_table_10_to_36[2048], &quant_table_10_to_38[2048], &quant_table_10_to_40[2048], &quant_table_10_to_42[2048], &quant_table_10_to_44[2048], &quant_table_10_to_46[2048], &quant_table_10_to_48[2048], &quant_table_10_to_50[2048], &quant_table_10_to_52[2048], &quant_table_10_to_54[2048], &quant_table_10_to_56[2048], &quant_table_10_to_58[2048], &quant_table_10_to_60[2048], &quant_table_10_to_62[2048], &quant_table_10_to_64[2048], &quant_table_10_to_72[2048], &quant_table_10_to_80[2048], &quant_table_10_to_88[2048], &quant_table_10_to_96[2048], &quant_table_10_to_104[2048], &quant_table_10_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0, &quant_table_12_to_14[2048], &quant_table_12_to_16[2048], &quant_table_12_to_18[2048], &quant_table_12_to_20[2048], &quant_table_12_to_22[2048], &quant_table_12_to_24[2048], &quant_table_12_to_26[2048], &quant_table_12_to_28[2048], &quant_table_12_to_30[2048], &quant_table_12_to_32[2048], &quant_table_12_to_34[2048], &quant_table_12_to_36[2048], &quant_table_12_to_38[2048], &quant_table_12_to_40[2048], &quant_table_12_to_42[2048], &quant_table_12_to_44[2048], &quant_table_12_to_46[2048], &quant_table_12_to_48[2048], &quant_table_12_to_50[2048], &quant_table_12_to_52[2048], &quant_table_12_to_54[2048], &quant_table_12_to_56[2048], &quant_table_12_to_58[2048], &quant_table_12_to_60[2048], &quant_table_12_to_62[2048], &quant_table_12_to_64[2048], &quant_table_12_to_72[2048], &quant_table_12_to_80[2048], &quant_table_12_to_88[2048], &quant_table_12_to_96[2048], &quant_table_12_to_104[2048], &quant_table_12_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0, &quant_table_14_to_16[2048], &quant_table_14_to_18[2048], &quant_table_14_to_20[2048], &quant_table_14_to_22[2048], &quant_table_14_to_24[2048], &quant_table_14_to_26[2048], &quant_table_14_to_28[2048], &quant_table_14_to_30[2048], &quant_table_14_to_32[2048], &quant_table_14_to_34[2048], &quant_table_14_to_36[2048], &quant_table_14_to_38[2048], &quant_table_14_to_40[2048], &quant_table_14_to_42[2048], &quant_table_14_to_44[2048], &quant_table_14_to_46[2048], &quant_table_14_to_48[2048], &quant_table_14_to_50[2048], &quant_table_14_to_52[2048], &quant_table_14_to_54[2048], &quant_table_14_to_56[2048], &quant_table_14_to_58[2048], &quant_table_14_to_60[2048], &quant_table_14_to_62[2048], &quant_table_14_to_64[2048], &quant_table_14_to_72[2048], &quant_table_14_to_80[2048], &quant_table_14_to_88[2048], &quant_table_14_to_96[2048], &quant_table_14_to_104[2048], &quant_table_14_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0, &quant_table_16_to_18[2048], &quant_table_16_to_20[2048], &quant_table_16_to_22[2048], &quant_table_16_to_24[2048], &quant_table_16_to_26[2048], &quant_table_16_to_28[2048], &quant_table_16_to_30[2048], &quant_table_16_to_32[2048], &quant_table_16_to_34[2048], &quant_table_16_to_36[2048], &quant_table_16_to_38[2048], &quant_table_16_to_40[2048], &quant_table_16_to_42[2048], &quant_table_16_to_44[2048], &quant_table_16_to_46[2048], &quant_table_16_to_48[2048], &quant_table_16_to_50[2048], &quant_table_16_to_52[2048], &quant_table_16_to_54[2048], &quant_table_16_to_56[2048], &quant_table_16_to_58[2048], &quant_table_16_to_60[2048], &quant_table_16_to_62[2048], &quant_table_16_to_64[2048], &quant_table_16_to_72[2048], &quant_table_16_to_80[2048], &quant_table_16_to_88[2048], &quant_table_16_to_96[2048], &quant_table_16_to_104[2048], &quant_table_16_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0,0, &quant_table_18_to_20[2048], &quant_table_18_to_22[2048], &quant_table_18_to_24[2048], &quant_table_18_to_26[2048], &quant_table_18_to_28[2048], &quant_table_18_to_30[2048], &quant_table_18_to_32[2048], &quant_table_18_to_34[2048], &quant_table_18_to_36[2048], &quant_table_18_to_38[2048], &quant_table_18_to_40[2048], &quant_table_18_to_42[2048], &quant_table_18_to_44[2048], &quant_table_18_to_46[2048], &quant_table_18_to_48[2048], &quant_table_18_to_50[2048], &quant_table_18_to_52[2048], &quant_table_18_to_54[2048], &quant_table_18_to_56[2048], &quant_table_18_to_58[2048], &quant_table_18_to_60[2048], &quant_table_18_to_62[2048], &quant_table_18_to_64[2048], &quant_table_18_to_72[2048], &quant_table_18_to_80[2048], &quant_table_18_to_88[2048], &quant_table_18_to_96[2048], &quant_table_18_to_104[2048], &quant_table_18_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0, &quant_table_20_to_22[2048], &quant_table_20_to_24[2048], &quant_table_20_to_26[2048], &quant_table_20_to_28[2048], &quant_table_20_to_30[2048], &quant_table_20_to_32[2048], &quant_table_20_to_34[2048], &quant_table_20_to_36[2048], &quant_table_20_to_38[2048], &quant_table_20_to_40[2048], &quant_table_20_to_42[2048], &quant_table_20_to_44[2048], &quant_table_20_to_46[2048], &quant_table_20_to_48[2048], &quant_table_20_to_50[2048], &quant_table_20_to_52[2048], &quant_table_20_to_54[2048], &quant_table_20_to_56[2048], &quant_table_20_to_58[2048], &quant_table_20_to_60[2048], &quant_table_20_to_62[2048], &quant_table_20_to_64[2048], &quant_table_20_to_72[2048], &quant_table_20_to_80[2048], &quant_table_20_to_88[2048], &quant_table_20_to_96[2048], &quant_table_20_to_104[2048], &quant_table_20_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, &quant_table_22_to_24[2048], &quant_table_22_to_26[2048], &quant_table_22_to_28[2048], &quant_table_22_to_30[2048], &quant_table_22_to_32[2048], &quant_table_22_to_34[2048], &quant_table_22_to_36[2048], &quant_table_22_to_38[2048], &quant_table_22_to_40[2048], &quant_table_22_to_42[2048], &quant_table_22_to_44[2048], &quant_table_22_to_46[2048], &quant_table_22_to_48[2048], &quant_table_22_to_50[2048], &quant_table_22_to_52[2048], &quant_table_22_to_54[2048], &quant_table_22_to_56[2048], &quant_table_22_to_58[2048], &quant_table_22_to_60[2048], &quant_table_22_to_62[2048], &quant_table_22_to_64[2048], &quant_table_22_to_72[2048], &quant_table_22_to_80[2048], &quant_table_22_to_88[2048], &quant_table_22_to_96[2048], &quant_table_22_to_104[2048], &quant_table_22_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, &quant_table_24_to_26[2048], &quant_table_24_to_28[2048], &quant_table_24_to_30[2048], &quant_table_24_to_32[2048], &quant_table_24_to_34[2048], &quant_table_24_to_36[2048], &quant_table_24_to_38[2048], &quant_table_24_to_40[2048], &quant_table_24_to_42[2048], &quant_table_24_to_44[2048], &quant_table_24_to_46[2048], &quant_table_24_to_48[2048], &quant_table_24_to_50[2048], &quant_table_24_to_52[2048], &quant_table_24_to_54[2048], &quant_table_24_to_56[2048], &quant_table_24_to_58[2048], &quant_table_24_to_60[2048], &quant_table_24_to_62[2048], &quant_table_24_to_64[2048], &quant_table_24_to_72[2048], &quant_table_24_to_80[2048], &quant_table_24_to_88[2048], &quant_table_24_to_96[2048], &quant_table_24_to_104[2048], &quant_table_24_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, &quant_table_26_to_28[2048], &quant_table_26_to_30[2048], &quant_table_26_to_32[2048], &quant_table_26_to_34[2048], &quant_table_26_to_36[2048], &quant_table_26_to_38[2048], &quant_table_26_to_40[2048], &quant_table_26_to_42[2048], &quant_table_26_to_44[2048], &quant_table_26_to_46[2048], &quant_table_26_to_48[2048], &quant_table_26_to_50[2048], &quant_table_26_to_52[2048], &quant_table_26_to_54[2048], &quant_table_26_to_56[2048], &quant_table_26_to_58[2048], &quant_table_26_to_60[2048], &quant_table_26_to_62[2048], &quant_table_26_to_64[2048], &quant_table_26_to_72[2048], &quant_table_26_to_80[2048], &quant_table_26_to_88[2048], &quant_table_26_to_96[2048], &quant_table_26_to_104[2048], &quant_table_26_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, &quant_table_28_to_30[2048], &quant_table_28_to_32[2048], &quant_table_28_to_34[2048], &quant_table_28_to_36[2048], &quant_table_28_to_38[2048], &quant_table_28_to_40[2048], &quant_table_28_to_42[2048], &quant_table_28_to_44[2048], &quant_table_28_to_46[2048], &quant_table_28_to_48[2048], &quant_table_28_to_50[2048], &quant_table_28_to_52[2048], &quant_table_28_to_54[2048], &quant_table_28_to_56[2048], &quant_table_28_to_58[2048], &quant_table_28_to_60[2048], &quant_table_28_to_62[2048], &quant_table_28_to_64[2048], &quant_table_28_to_72[2048], &quant_table_28_to_80[2048], &quant_table_28_to_88[2048], &quant_table_28_to_96[2048], &quant_table_28_to_104[2048], &quant_table_28_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, &quant_table_30_to_32[2048], &quant_table_30_to_34[2048], &quant_table_30_to_36[2048], &quant_table_30_to_38[2048], &quant_table_30_to_40[2048], &quant_table_30_to_42[2048], &quant_table_30_to_44[2048], &quant_table_30_to_46[2048], &quant_table_30_to_48[2048], &quant_table_30_to_50[2048], &quant_table_30_to_52[2048], &quant_table_30_to_54[2048], &quant_table_30_to_56[2048], &quant_table_30_to_58[2048], &quant_table_30_to_60[2048], &quant_table_30_to_62[2048], &quant_table_30_to_64[2048], &quant_table_30_to_72[2048], &quant_table_30_to_80[2048], &quant_table_30_to_88[2048], &quant_table_30_to_96[2048], &quant_table_30_to_104[2048], &quant_table_30_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, &quant_table_32_to_34[2048], &quant_table_32_to_36[2048], &quant_table_32_to_38[2048], &quant_table_32_to_40[2048], &quant_table_32_to_42[2048], &quant_table_32_to_44[2048], &quant_table_32_to_46[2048], &quant_table_32_to_48[2048], &quant_table_32_to_50[2048], &quant_table_32_to_52[2048], &quant_table_32_to_54[2048], &quant_table_32_to_56[2048], &quant_table_32_to_58[2048], &quant_table_32_to_60[2048], &quant_table_32_to_62[2048], &quant_table_32_to_64[2048], &quant_table_32_to_72[2048], &quant_table_32_to_80[2048], &quant_table_32_to_88[2048], &quant_table_32_to_96[2048], &quant_table_32_to_104[2048], &quant_table_32_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, &quant_table_34_to_36[2048], &quant_table_34_to_38[2048], &quant_table_34_to_40[2048], &quant_table_34_to_42[2048], &quant_table_34_to_44[2048], &quant_table_34_to_46[2048], &quant_table_34_to_48[2048], &quant_table_34_to_50[2048], &quant_table_34_to_52[2048], &quant_table_34_to_54[2048], &quant_table_34_to_56[2048], &quant_table_34_to_58[2048], &quant_table_34_to_60[2048], &quant_table_34_to_62[2048], &quant_table_34_to_64[2048], &quant_table_34_to_72[2048], &quant_table_34_to_80[2048], &quant_table_34_to_88[2048], &quant_table_34_to_96[2048], &quant_table_34_to_104[2048], &quant_table_34_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, &quant_table_36_to_38[2048], &quant_table_36_to_40[2048], &quant_table_36_to_42[2048], &quant_table_36_to_44[2048], &quant_table_36_to_46[2048], &quant_table_36_to_48[2048], &quant_table_36_to_50[2048], &quant_table_36_to_52[2048], &quant_table_36_to_54[2048], &quant_table_36_to_56[2048], &quant_table_36_to_58[2048], &quant_table_36_to_60[2048], &quant_table_36_to_62[2048], &quant_table_36_to_64[2048], &quant_table_36_to_72[2048], &quant_table_36_to_80[2048], &quant_table_36_to_88[2048], &quant_table_36_to_96[2048], &quant_table_36_to_104[2048], &quant_table_36_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, &quant_table_38_to_40[2048], &quant_table_38_to_42[2048], &quant_table_38_to_44[2048], &quant_table_38_to_46[2048], &quant_table_38_to_48[2048], &quant_table_38_to_50[2048], &quant_table_38_to_52[2048], &quant_table_38_to_54[2048], &quant_table_38_to_56[2048], &quant_table_38_to_58[2048], &quant_table_38_to_60[2048], &quant_table_38_to_62[2048], &quant_table_38_to_64[2048], &quant_table_38_to_72[2048], &quant_table_38_to_80[2048], &quant_table_38_to_88[2048], &quant_table_38_to_96[2048], &quant_table_38_to_104[2048], &quant_table_38_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, &quant_table_40_to_42[2048], &quant_table_40_to_44[2048], &quant_table_40_to_46[2048], &quant_table_40_to_48[2048], &quant_table_40_to_50[2048], &quant_table_40_to_52[2048], &quant_table_40_to_54[2048], &quant_table_40_to_56[2048], &quant_table_40_to_58[2048], &quant_table_40_to_60[2048], &quant_table_40_to_62[2048], &quant_table_40_to_64[2048], &quant_table_40_to_72[2048], &quant_table_40_to_80[2048], &quant_table_40_to_88[2048], &quant_table_40_to_96[2048], &quant_table_40_to_104[2048], &quant_table_40_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, &quant_table_42_to_44[2048], &quant_table_42_to_46[2048], &quant_table_42_to_48[2048], &quant_table_42_to_50[2048], &quant_table_42_to_52[2048], &quant_table_42_to_54[2048], &quant_table_42_to_56[2048], &quant_table_42_to_58[2048], &quant_table_42_to_60[2048], &quant_table_42_to_62[2048], &quant_table_42_to_64[2048], &quant_table_42_to_72[2048], &quant_table_42_to_80[2048], &quant_table_42_to_88[2048], &quant_table_42_to_96[2048], &quant_table_42_to_104[2048], &quant_table_42_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, &quant_table_44_to_46[2048], &quant_table_44_to_48[2048], &quant_table_44_to_50[2048], &quant_table_44_to_52[2048], &quant_table_44_to_54[2048], &quant_table_44_to_56[2048], &quant_table_44_to_58[2048], &quant_table_44_to_60[2048], &quant_table_44_to_62[2048], &quant_table_44_to_64[2048], &quant_table_44_to_72[2048], &quant_table_44_to_80[2048], &quant_table_44_to_88[2048], &quant_table_44_to_96[2048], &quant_table_44_to_104[2048], &quant_table_44_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, &quant_table_46_to_48[2048], &quant_table_46_to_50[2048], &quant_table_46_to_52[2048], &quant_table_46_to_54[2048], &quant_table_46_to_56[2048], &quant_table_46_to_58[2048], &quant_table_46_to_60[2048], &quant_table_46_to_62[2048], &quant_table_46_to_64[2048], &quant_table_46_to_72[2048], &quant_table_46_to_80[2048], &quant_table_46_to_88[2048], &quant_table_46_to_96[2048], &quant_table_46_to_104[2048], &quant_table_46_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, &quant_table_48_to_50[2048], &quant_table_48_to_52[2048], &quant_table_48_to_54[2048], &quant_table_48_to_56[2048], &quant_table_48_to_58[2048], &quant_table_48_to_60[2048], &quant_table_48_to_62[2048], &quant_table_48_to_64[2048], &quant_table_48_to_72[2048], &quant_table_48_to_80[2048], &quant_table_48_to_88[2048], &quant_table_48_to_96[2048], &quant_table_48_to_104[2048], &quant_table_48_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, &quant_table_50_to_52[2048], &quant_table_50_to_54[2048], &quant_table_50_to_56[2048], &quant_table_50_to_58[2048], &quant_table_50_to_60[2048], &quant_table_50_to_62[2048], &quant_table_50_to_64[2048], &quant_table_50_to_72[2048], &quant_table_50_to_80[2048], &quant_table_50_to_88[2048], &quant_table_50_to_96[2048], &quant_table_50_to_104[2048], &quant_table_50_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, &quant_table_52_to_54[2048], &quant_table_52_to_56[2048], &quant_table_52_to_58[2048], &quant_table_52_to_60[2048], &quant_table_52_to_62[2048], &quant_table_52_to_64[2048], &quant_table_52_to_72[2048], &quant_table_52_to_80[2048], &quant_table_52_to_88[2048], &quant_table_52_to_96[2048], &quant_table_52_to_104[2048], &quant_table_52_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, &quant_table_54_to_56[2048], &quant_table_54_to_58[2048], &quant_table_54_to_60[2048], &quant_table_54_to_62[2048], &quant_table_54_to_64[2048], &quant_table_54_to_72[2048], &quant_table_54_to_80[2048], &quant_table_54_to_88[2048], &quant_table_54_to_96[2048], &quant_table_54_to_104[2048], &quant_table_54_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, &quant_table_56_to_58[2048], &quant_table_56_to_60[2048], &quant_table_56_to_62[2048], &quant_table_56_to_64[2048], &quant_table_56_to_72[2048], &quant_table_56_to_80[2048], &quant_table_56_to_88[2048], &quant_table_56_to_96[2048], &quant_table_56_to_104[2048], &quant_table_56_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, &quant_table_58_to_60[2048], &quant_table_58_to_62[2048], &quant_table_58_to_64[2048], &quant_table_58_to_72[2048], &quant_table_58_to_80[2048], &quant_table_58_to_88[2048], &quant_table_58_to_96[2048], &quant_table_58_to_104[2048], &quant_table_58_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, &quant_table_60_to_62[2048], &quant_table_60_to_64[2048], &quant_table_60_to_72[2048], &quant_table_60_to_80[2048], &quant_table_60_to_88[2048], &quant_table_60_to_96[2048], &quant_table_60_to_104[2048], &quant_table_60_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, &quant_table_62_to_64[2048], &quant_table_62_to_72[2048], &quant_table_62_to_80[2048], &quant_table_62_to_88[2048], &quant_table_62_to_96[2048], &quant_table_62_to_104[2048], &quant_table_62_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, &quant_table_64_to_72[2048], &quant_table_64_to_80[2048], &quant_table_64_to_88[2048], &quant_table_64_to_96[2048], &quant_table_64_to_104[2048], &quant_table_64_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, &quant_table_72_to_80[2048], &quant_table_72_to_88[2048], &quant_table_72_to_96[2048], &quant_table_72_to_104[2048], &quant_table_72_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, &quant_table_80_to_88[2048], &quant_table_80_to_96[2048], &quant_table_80_to_104[2048], &quant_table_80_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, &quant_table_88_to_96[2048], &quant_table_88_to_104[2048], &quant_table_88_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, &quant_table_96_to_104[2048], &quant_table_96_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, &quant_table_104_to_112[2048]}, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} }; k9copy/src/subtitles/0000755000175000017550000000000012412271774015357 5ustar emulatoremulatork9copy/src/subtitles/k9subtitle2pgm.h0000644000175000017550000000344312412271774020421 0ustar emulatoremulator// // C++ Interface: k9subtitle2pgm // // Description: // // // Author: <>, (C) 2008 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9SUBTITLE2PGM_H #define K9SUBTITLE2PGM_H #include "k9common.h" #include "k9fifo.h" #include #include #include #include typedef struct { FILE *fsub; FILE *fidx; unsigned int aid; } vobsub_out_t; class k9Subtitle2Pgm : public QThread { Q_OBJECT public: k9Subtitle2Pgm ( QObject *parent); ~k9Subtitle2Pgm(); void addData(uchar *buffer,uint size); void setNoData() ; void setBaseName(const QString& theValue); void end(); void setPalette(uint _index,uint value); void setLangCod(const QString& theValue); void setTrackCod(int theValue); private: double last_pts; QString m_langCod; int m_trackCod; int last_pts_set; QString m_baseName; k9MemoryFifo *m_fifo; uint m_palette[16]; double start_rpts,end_rpts,m_totalLength; double m_offset_rpts,m_last_rpts; int m_discont; uint stream_read_int16(uchar *s); uint read_tc_time_stamp(char *s); uint stream_read_int32(uchar *s); int get_pts_dts(char *buffer, ulong *pts, ulong *dts) ; void pes_ac3_loop(); void *vobsub_out_open(const char *basename, const unsigned int *palette, unsigned int orig_width, unsigned int orig_height, const char *id, unsigned int index); void create_idx(vobsub_out_t *me, const unsigned int *palette, unsigned int orig_width, unsigned int orig_height); void vobsub_out_close(void *me); void vobsub_out_output(void *me, const unsigned char *packet, int len, double pts); QTime pts2Time(double _pts); protected: virtual void run(); }; #endif k9copy/src/subtitles/k9subtitle2pgm.cpp0000644000175000017550000004242012412271774020752 0ustar emulatoremulator// // C++ Implementation: k9subtitle2pgm // // Description: Extractiion of subtitles from an mp2 stream. Subtitles are extracted to vobsub files. // This code is based on extract_ac3 (transcode) and vobsub (mplayer) // // Developer: Pauline123 , (C) 2014 // // Author: <>, (C) 2008 // // Copyright: See COPYING file that comes with this distribution // // #include "k9subtitle2pgm.h" #include "k9common.h" #include #include "k9ifo2.h" k9Subtitle2Pgm::k9Subtitle2Pgm ( QObject *parent):QThread(parent) { m_fifo = new k9MemoryFifo(); start_rpts=end_rpts=-1.; m_totalLength=0.; } k9Subtitle2Pgm::~k9Subtitle2Pgm() { delete m_fifo; } void k9Subtitle2Pgm::addData(uchar *data,uint size) { if (!isRunning()) start(); m_fifo->addData(data,size); } uint k9Subtitle2Pgm::stream_read_int16(uchar *s) { uint a, b, result; a = s[0]; b = s[1]; result = (a << 8) | b; return result; } int k9Subtitle2Pgm::get_pts_dts(char *buffer, ulong *pts, ulong *dts) { uint pes_header_bytes = 0; uint pts_dts_flags; int pes_header_data_length; int has_pts_dts=0; uint ptr=0; /* drop first 8 bits */ ++ptr; pts_dts_flags = (buffer[ptr++] >> 6) & 0x3; pes_header_data_length = buffer[ptr++]; switch (pts_dts_flags) { case 2: *pts = (buffer[ptr++] >> 1) & 7; //low 4 bits (7==1111) *pts <<= 15; *pts |= (stream_read_int16((uchar*)&buffer[ptr]) >> 1); ptr+=2; *pts <<= 15; *pts |= (stream_read_int16((uchar*)&buffer[ptr]) >> 1); ptr+=2; pes_header_bytes += 5; has_pts_dts=1; break; case 3: *pts = (buffer[ptr++] >> 1) & 7; //low 4 bits (7==1111) *pts <<= 15; *pts |= (stream_read_int16((uchar*)&buffer[ptr]) >> 1); ptr+=2; *pts <<= 15; *pts |= (stream_read_int16((uchar*)&buffer[ptr]) >> 1); ptr+=2; *dts = (buffer[ptr++] >> 1) & 7; *dts <<= 15; *dts |= (stream_read_int16((uchar*)&buffer[ptr]) >> 1); ptr+=2; *dts <<= 15; *dts |= (stream_read_int16((uchar*)&buffer[ptr]) >> 1); ptr+=2; pes_header_bytes += 10; has_pts_dts=1; break; default: has_pts_dts=0; *dts=*pts=0; break; } return(has_pts_dts); } uint k9Subtitle2Pgm::stream_read_int32(uchar *s) { uint a, b, c, d, result; a = s[0]; b = s[1]; c = s[2]; d = s[3]; result = (a << 24) | (b << 16) | (c << 8) | d; return result; } uint k9Subtitle2Pgm::read_tc_time_stamp(char *s) { ulong i, j; ulong clock_ref=0, clock_ref_ext=0; if (s[0] & 0x40) { i = stream_read_int32((uchar*)s); j = stream_read_int16((uchar*)s+4); if (i & 0x40000000 || (i >> 28) == 2) { clock_ref = ((i & 0x31000000) << 3); clock_ref |= ((i & 0x03fff800) << 4); clock_ref |= ((i & 0x000003ff) << 5); clock_ref |= ((j & 0xf800) >> 11); clock_ref_ext = (j >> 1) & 0x1ff; } } return ((uint) (clock_ref * 300 + clock_ref_ext)); } #define BUFFER_SIZE 40960 void k9Subtitle2Pgm::pes_ac3_loop (void) { static int mpeg1_skip_table[16] = { 1, 0xffff, 5, 10, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff }; last_pts=0; last_pts_set = 0; uint8_t * buf; uint8_t buffer[BUFFER_SIZE]; uint8_t * end; uint8_t * tmp1=NULL; uint8_t * tmp2=NULL; char pack_buf[16]; uint pack_lpts=0; double pack_sub_rpts=0.0f, abs_sub_rpts=0.0f; ulong i_pts, i_dts; buf = buffer; int track_code=m_trackCod; uint index=0; #if QT_VERSION >= 0x050000 void *vobsub_h=vobsub_out_open(m_baseName.toUtf8(), m_palette,720,576,m_langCod.toLatin1(), index); #else void *vobsub_h=vobsub_out_open(m_baseName.toUtf8(), m_palette,720,576,m_langCod.toAscii(), index); #endif do { end = buf + m_fifo->readData(buffer,BUFFER_SIZE); buf = buffer; //scan buffer while (buf + 4 <= end) { // check for valid start code if (buf[0] || buf[1] || (buf[2] != 0x01)) { buf++; continue; }// check for valid start code switch (buf[3]) { case 0xb9: /* program end code */ return; //check for PTS case 0xba: /* pack header */ memcpy(pack_buf, &buf[4], 6); pack_lpts = read_tc_time_stamp(pack_buf); /* skip */ if ((buf[4] & 0xc0) == 0x40) /* mpeg2 */ tmp1 = buf + 14 + (buf[13] & 7); else if ((buf[4] & 0xf0) == 0x20) /* mpeg1 */ tmp1 = buf + 12; else if (buf + 5 > end) goto copy; else { fprintf (stderr, "(%s) weird pack header\n", __FILE__); return; } if (tmp1 > end) goto copy; buf = tmp1; break; case 0xbd: /* private stream 1 */ tmp2 = buf + 6 + (buf[4] << 8) + buf[5]; if (tmp2 > end) goto copy; if ((buf[6] & 0xc0) == 0x80) /* mpeg2 */ tmp1 = buf + 9 + buf[8]; else { /* mpeg1 */ for (tmp1 = buf + 6; *tmp1 == 0xff; tmp1++) if (tmp1 == buf + 6 + 16) { fprintf (stderr, "(%s) too much stuffing\n", __FILE__); buf = tmp2; break; } if ((*tmp1 & 0xc0) == 0x40) tmp1 += 2; tmp1 += mpeg1_skip_table [*tmp1 >> 4]; } //subtitle if ((*tmp1 == track_code && track_code < 0x40 )) { if (tmp1 < tmp2) { // get pts time stamp: memcpy(pack_buf, &buf[6], 16); if (get_pts_dts(pack_buf, &i_pts, &i_dts)) { pack_sub_rpts = (double) i_pts/90000.; abs_sub_rpts=m_totalLength+pack_sub_rpts - start_rpts; } vobsub_out_output(vobsub_h, tmp1+1,tmp2-tmp1-1, abs_sub_rpts); } //ac3 package if (*tmp1 == track_code && track_code >= 0x80) { tmp1 += 4; //test if (0) { memcpy(pack_buf, &buf[6], 16); get_pts_dts(pack_buf, &i_pts, &i_dts); fprintf(stderr, "AC3 PTS=%f\n", (double) i_pts/90000.); } } } buf = tmp2; break; case 0xbb: { pci_t pci_pack; k9Ifo2::navRead_PCI(&pci_pack,buf-14 + 0x2d); // k9DVDChapter *ch=m_title->getChapterFromSector(dsi_pack.dsi_gi.nv_pck_lbn); // if (ch!=m_chapter) { //adds the length of previous vobu if (start_rpts !=-1.) { m_totalLength+=end_rpts-start_rpts; } start_rpts=(double) pci_pack.pci_gi.vobu_s_ptm/90000.; end_rpts=(double) pci_pack.pci_gi.vobu_e_ptm/90000.; // m_chapter=ch; } default: if (buf[3] < 0xb9) fprintf (stderr, "(%s) broken stream - skipping data\n", __FILE__); /* skip */ tmp1 = buf + 6 + (buf[4] << 8) + buf[5]; if (tmp1 > end) goto copy; buf = tmp1; break; } //start code selection } //scan buffer if (buf < end) { copy: /* we only pass here for mpeg1 ps streams */ memmove (buffer, buf, end - buf); } buf = buffer + (end - buf); } while (end == buffer + BUFFER_SIZE); vobsub_out_close(vobsub_h); } void k9Subtitle2Pgm::run() { pes_ac3_loop(); } /********************************************************************** * Vobsub output **********************************************************************/ #define MIN(a,b) a>b?b:a #define MAX(a,b) afidx, "# VobSub index file, v7 (do not modify this line!)\n" "#\n" "# Generated by MPlayer " VERSION "\n" "# See for more information about MPlayer\n" "# See for more information about Vobsub\n" "#\n" "size: %ux%u\n", orig_width, orig_height); if (palette) { fputs("palette:", me->fidx); for (i = 0; i < 16; ++i) { const double y = palette[i] >> 16 & 0xff, u = (palette[i] >> 8 & 0xff) - 128.0, v = (palette[i] & 0xff) - 128.0; if (i) putc(',', me->fidx); fprintf(me->fidx, " %02x%02x%02x", MIN(MAX((int)(y + 1.4022 * u), 0), 0xff), MIN(MAX((int)(y - 0.3456 * u - 0.7145 * v), 0), 0xff), MIN(MAX((int)(y + 1.7710 * v), 0), 0xff)); } putc('\n', me->fidx); } fprintf(me->fidx,"# ON: displays only forced subtitles, OFF: shows everything\n" "forced subs: OFF\n"); } void *k9Subtitle2Pgm::vobsub_out_open(const char *basename, const uint *palette, uint orig_width, uint orig_height, const char *id, uint index) { vobsub_out_t *result = NULL; char *filename; filename = (char*)malloc(strlen(basename) + 5); if (filename) { result = (vobsub_out_t*)malloc(sizeof(vobsub_out_t)); if (result) { result->aid = index; strcpy(filename, basename); strcat(filename, ".sub"); result->fsub = fopen(filename, "ab"); if (result->fsub == NULL) perror("Error: vobsub_out_open subtitle file open failed"); strcpy(filename, basename); strcat(filename, ".idx"); result->fidx = fopen(filename, "ab"); if (result->fidx) { if (ftell(result->fidx) == 0) { create_idx(result, palette, orig_width, orig_height); /* Make the selected language the default language */ fprintf(result->fidx, "\n# Language index in use\nlangidx: %u\n", index); } fprintf(result->fidx, "\nid: %s, index: %u\n", id ? id : "xx", index); /* So that we can check the file now */ fflush(result->fidx); } else perror("Error: vobsub_out_open index file open failed"); free(filename); } } return result; } void k9Subtitle2Pgm::vobsub_out_close(void *me) { vobsub_out_t *vob = (vobsub_out_t*)me; if (vob->fidx) fclose(vob->fidx); if (vob->fsub) fclose(vob->fsub); free(vob); } void k9Subtitle2Pgm::vobsub_out_output(void *me, const uchar *packet, int len, double pts) { vobsub_out_t *vob = (vobsub_out_t*)me; if (vob->fsub) { /* Windows' Vobsub require that every packet is exactly 2kB long */ uchar buffer[2048]; uchar *p; int remain = 2048; /* Do not output twice a line with the same timestamp, this breaks Windows' Vobsub */ if (vob->fidx && (!last_pts_set || last_pts != pts)) { static uint last_h = 9999, last_m = 9999, last_s = 9999, last_ms = 9999; uint h, m, ms; double s; s = pts; h = s / 3600; s -= h * 3600; m = s / 60; s -= m * 60; ms = (s - (uint) s) * 1000; if (ms >= 1000) /* prevent overfolws or bad float stuff */ ms = 0; if (h != last_h || m != last_m || (uint) s != last_s || ms != last_ms) { QTime time(h,m,s,ms); // fprintf(vob->fidx, "timestamp: %02u:%02u:%02u:%03u, filepos: %09lx\n", // h, m, (uint) s, ms, ftell(vob->fsub)); fprintf(vob->fidx, "timestamp: %02u:%02u:%02u:%03u, filepos: %09lx\n", time.hour(), time.minute(), (uint) time.second(), time.msec(), ftell(vob->fsub)); last_h = h; last_m = m; last_s = (uint) s; last_ms = ms; } } last_pts = pts; last_pts_set = 1; /* Packet start code: Windows' Vobsub needs this */ p = buffer; *p++ = 0; /* 0x00 */ *p++ = 0; *p++ = 1; *p++ = 0xba; *p++ = 0x40; memset(p, 0, 9); p += 9; { /* Packet */ static uchar last_pts[5] = { 0, 0, 0, 0, 0}; uchar now_pts[5]; int pts_len, pad_len, datalen = len; pts *= 90000; now_pts[0] = 0x21 | (((ulong)pts >> 29) & 0x0e); now_pts[1] = ((ulong)pts >> 22) & 0xff; now_pts[2] = 0x01 | (((ulong)pts >> 14) & 0xfe); now_pts[3] = ((ulong)pts >> 7) & 0xff; now_pts[4] = 0x01 | (((ulong)pts << 1) & 0xfe); pts_len = memcmp(last_pts, now_pts, sizeof(now_pts)) ? sizeof(now_pts) : 0; memcpy(last_pts, now_pts, sizeof(now_pts)); datalen += 3; /* Version, PTS_flags, pts_len */ datalen += pts_len; datalen += 1; /* AID */ pad_len = 2048 - (p - buffer) - 4 /* MPEG ID */ - 2 /* payload len */ - datalen; /* XXX - Go figure what should go here! In any case the packet has to be completly filled. If I can fill it with padding (0x000001be) latter I'll do that. But if there is only room for 6 bytes then I can not write a padding packet. So I add some padding in the PTS field. This looks like a dirty kludge. Oh well... */ if (pad_len < 0) { /* Packet is too big. Let's try ommiting the PTS field */ datalen -= pts_len; pts_len = 0; pad_len = 0; } else if (pad_len > 6) pad_len = 0; datalen += pad_len; *p++ = 0; /* 0x0e */ *p++ = 0; *p++ = 1; *p++ = 0xbd; *p++ = (datalen >> 8) & 0xff; /* length of payload */ *p++ = datalen & 0xff; *p++ = 0x80; /* System-2 (.VOB) stream */ *p++ = pts_len ? 0x80 : 0x00; /* pts_flags */ *p++ = pts_len + pad_len; memcpy(p, now_pts, pts_len); p += pts_len; memset(p, 0, pad_len); p += pad_len; } *p++ = 0x20 | vob->aid; /* aid */ if (fwrite(buffer, p - buffer, 1, vob->fsub) != 1 || fwrite(packet, len, 1, vob->fsub) != 1) perror("ERROR: vobsub write failed"); else remain -= p - buffer + len; /* Padding */ if (remain >= 6) { p = buffer; *p++ = 0x00; *p++ = 0x00; *p++ = 0x01; *p++ = 0xbe; *p++ = (remain - 6) >> 8; *p++ = (remain - 6) & 0xff; /* for better compression, blank this */ memset(buffer + 6, 0, remain - (p - buffer)); if (fwrite(buffer, remain, 1, vob->fsub) != 1) perror("ERROR: vobsub padding write failed"); } else if (remain > 0) { /* I don't know what to output. But anyway the block needs to be 2KB big */ memset(buffer, 0, remain); if (fwrite(buffer, remain, 1, vob->fsub) != 1) perror("ERROR: vobsub blank padding write failed"); } else if (remain < 0) fprintf(stderr, "\nERROR: wrong thing happenned...\n" " I wrote a %i data bytes spu packet and that's too long\n", len); } } void k9Subtitle2Pgm::setBaseName(const QString& theValue) { m_baseName = theValue; } void k9Subtitle2Pgm::end() { m_fifo->setNoData(); while (isRunning()) { wait(100); k9Tools::processEvents(); } } QTime k9Subtitle2Pgm::pts2Time(double _pts) { uint h, m, ms; double s; s = _pts; h = s / 3600; s -= h * 3600; m = s / 60; s -= m * 60; ms = (s - (uint) s) * 1000; if (ms >= 1000) /* prevent overfolws or bad float stuff */ ms = 0; QTime t(h,m,s,ms); qDebug() << " h:" << h << " m:" << m << " s:" << s << " ms:" << ms << " time:" << t.toString("hh:mm:ss.zzz"); return t; } void k9Subtitle2Pgm::setPalette(uint _index,uint value) { m_palette[_index]=value; } void k9Subtitle2Pgm::setLangCod(const QString& theValue) { m_langCod = theValue; } void k9Subtitle2Pgm::setTrackCod(int theValue) { m_trackCod = theValue; } k9copy/src/subtitles/CMakeLists.txt0000644000175000017550000000000012412271774020105 0ustar emulatoremulatork9copy/src/assistant/0000755000175000017550000000000012417731552015352 5ustar emulatoremulatork9copy/src/assistant/k9astsource.cpp0000644000175000017550000000645312412271774020342 0ustar emulatoremulator// // C++ Implementation: // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9astsource.h" #include "k9dvd.h" #include "k9cddrive.h" #include #include "k9dialogs.h" #include "k9dvdtitle.h" #if QT_VERSION >= 0x050000 #include #endif k9astSource::k9astSource(k9Assistant* parent,k9CdDrives *_drives,k9DVD *_dvd) : QWidget(parent) { Ui_astSource.setupUi(this); m_parent=parent; m_drives=_drives; m_dvd=_dvd; Ui_astSource.urFolder->setMode(KFile::Directory | KFile::ExistingOnly); Ui_astSource.rbDrive->setChecked(true); Ui_astSource.urFolder->setVisible(false); Ui_astSource.urIso->setVisible(false); Ui_astSource.urIso->setFilter("*.iso|Iso Image (*.iso)"); fillList(); } void k9astSource::fillList() { connect(m_drives,SIGNAL(deviceAdded( k9CdDrive*)),this,SLOT(deviceAdded( k9CdDrive* ))); connect(m_drives,SIGNAL(deviceRemoved( k9CdDrive*)),this,SLOT(deviceRemoved( k9CdDrive* ))); } void k9astSource::setPath(const QString &_path) { for (int i=0;icount();i++) { k9CdDrive *drive=m_drives->getDrive(i); if (drive->device==_path) { Ui_astSource.cbDrives->setCurrentIndex(i); Ui_astSource.rbDrive->setChecked(true); return; } } if (QFile::exists(_path)) { QFileInfo inf(_path); if (!inf.isFile()) { Ui_astSource.rbFolder->setChecked(true); #if QT_VERSION >= 0x050000 Ui_astSource.urFolder->setUrl(QUrl(_path)); #else Ui_astSource.urFolder->setUrl(KUrl(_path)); #endif }else { Ui_astSource.rbIso->setChecked(true); #if QT_VERSION >= 0x050000 Ui_astSource.urIso->setUrl(QUrl(_path)); #else Ui_astSource.urIso->setUrl(KUrl(_path)); #endif } } } void k9astSource::deviceAdded(k9CdDrive *_drive) { if (_drive->canReadDVD) { Ui_astSource.cbDrives->addItem(QString("%1 (%2)").arg(_drive->name).arg(_drive->device),_drive->device ); } } void k9astSource::deviceRemoved(k9CdDrive *) { } void k9astSource::rbDriveToggled(bool _state) { Ui_astSource.cbDrives->setVisible(_state); } void k9astSource::rbFolderToggled(bool _state) { Ui_astSource.urFolder->setVisible(_state); } void k9astSource::rbIsoToggled(bool _state) { Ui_astSource.urIso->setVisible(_state); } k9astSource::~k9astSource() { } bool k9astSource::openDvd() { QString path; if (Ui_astSource.rbDrive->isChecked()) path=Ui_astSource.cbDrives->itemData(Ui_astSource.cbDrives->currentIndex()).toString(); else if (Ui_astSource.rbFolder->isChecked()) path=Ui_astSource.urFolder->url().path(); else if (Ui_astSource.rbIso->isChecked()) path=Ui_astSource.urIso->url().path(); k9Config config; k9CdDrive *drive=k9CdDrives::getDeviceFromMountpoint(m_drives,path); if (drive) path=drive->device; if (path.startsWith("/dev/") && config.getPrefReadAhead()!=-1) k9CdDrive::setReadAhead(path,config.getPrefReadAhead()); if (m_dvd->getopened()) for (int i=0; i gettitleCount();i++) m_dvd->gettitle(i)->setSelected(false); m_dvd->scandvd(path,true); return !m_dvd->geterror (); } /*$SPECIALIZATION$*/ k9copy/src/assistant/k9assistant.cpp0000644000175000017550000002332412412313242020322 0ustar emulatoremulator// // C++ Implementation: k9assistant // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: <>, (C) 2008 // // Copyright: See COPYING file that comes with this distribution // // #include "k9assistant.h" #include "k9astsource.h" #include "k9asttitles.h" #include "k9aststreams.h" #include "k9astdestination.h" #include "k9astmp4.h" #include "k9astmpeg.h" #include "k9astdvdoption.h" #include "k9dvd.h" #include "k9cddrive.h" #include "k9execcopy.h" //PM #include "dvdread.h" #include "dvdread/dvd_reader.h" #include "k9settings.h" #include "k9dvdtitle.h" #if QT_VERSION >= 0x050000 #include #include #endif k9Assistant *k9Assistant::createAssistant() { KPageWidget * pageWidget=new KPageWidget(); return new k9Assistant(pageWidget); } k9Assistant::k9Assistant(KPageWidget *_pageWidget) : KAssistantDialog(_pageWidget) { m_pageWidget=_pageWidget; m_dvd=new k9DVD(); m_drives=new k9CdDrives(this); } void k9Assistant::run() { setWindowTitle(i18n("DVD backup assistant")); KIconLoader *loader = KIconLoader::global(); k9astSource *source=new k9astSource(this,m_drives,m_dvd); m_sourceItem=new KPageWidgetItem(source,i18n("source")); m_sourceItem->setHeader( i18n( "Select the source of the backup" ) ); #if QT_VERSION >= 0x050000 m_sourceItem->setIcon(QIcon(loader->loadIconSet("media-optical", KIconLoader::Desktop))); #else m_sourceItem->setIcon(KIcon(loader->loadIconSet("media-optical", KIconLoader::Desktop))); #endif m_pageWidget->addPage(m_sourceItem); k9astDestination *destination=new k9astDestination(this,m_drives,m_dvd); m_destinationItem=new KPageWidgetItem(destination,i18n("destination")); m_destinationItem->setHeader( i18n( "Select the destination of the backup" ) ); #if QT_VERSION >= 0x050000 m_destinationItem->setIcon(QIcon(loader->loadIconSet("media-optical-recordable", KIconLoader::Toolbar))); #else m_destinationItem->setIcon(KIcon(loader->loadIconSet("media-optical-recordable", KIconLoader::Toolbar))); #endif m_pageWidget->addPage(m_destinationItem); k9astTitles *titles=new k9astTitles(this,m_dvd); m_titlesItem=new KPageWidgetItem(titles,i18n("titles")); m_titlesItem->setHeader(i18n("Select the titles you want to copy")); #if QT_VERSION >= 0x050000 m_titlesItem->setIcon(QIcon("titles")); m_titlesItem->setIcon(QIcon(loader->loadIconSet("title", KIconLoader::Toolbar))); #else m_titlesItem->setIcon(KIcon("titles")); m_titlesItem->setIcon(KIcon(loader->loadIconSet("title", KIconLoader::Toolbar))); #endif m_pageWidget->addPage(m_titlesItem); k9astStreams *streams=new k9astStreams(this,m_dvd); m_streamsItem=new KPageWidgetItem(streams,i18n("streams")); m_streamsItem->setHeader(i18n("Select the streams you want to keep")); #if QT_VERSION >= 0x050000 m_streamsItem->setIcon(QIcon(loader->loadIconSet("speaker", KIconLoader::Toolbar))); #else m_streamsItem->setIcon(KIcon(loader->loadIconSet("speaker", KIconLoader::Toolbar))); #endif m_pageWidget->addPage(m_streamsItem); k9astMp4 *mp4=new k9astMp4(this,m_dvd); m_mp4Item=new KPageWidgetItem(mp4,i18n("mp4")); m_mp4Item->setHeader(i18n("Set mp4 options for each title")); #if QT_VERSION >= 0x050000 m_mp4Item->setIcon(QIcon(loader->loadIconSet("mp4", KIconLoader::Toolbar))); #else m_mp4Item->setIcon(KIcon(loader->loadIconSet("mp4", KIconLoader::Toolbar))); #endif m_pageWidget->addPage(m_mp4Item); k9astDVDOption *DVDOption=new k9astDVDOption(this,m_dvd); m_DVDOptionItem=new KPageWidgetItem(DVDOption,i18n("DVDOption")); m_DVDOptionItem->setHeader(i18n("Set DVD playback options")); #if QT_VERSION >= 0x050000 m_DVDOptionItem->setIcon(QIcon(loader->loadIconSet("dvdcopy", KIconLoader::Toolbar))); #else m_DVDOptionItem->setIcon(KIcon(loader->loadIconSet("dvdcopy", KIconLoader::Toolbar))); #endif m_pageWidget->addPage(m_DVDOptionItem); k9astMpeg *mpeg=new k9astMpeg(this,m_dvd); m_mpegItem=new KPageWidgetItem(mpeg,i18n("mpeg")); m_mpegItem->setHeader(i18n("Set mpeg options for each title")); #if QT_VERSION >= 0x050000 m_mpegItem->setIcon(QIcon(loader->loadIconSet("mpeg", KIconLoader::Toolbar))); #else m_mpegItem->setIcon(KIcon(loader->loadIconSet("mpeg", KIconLoader::Toolbar))); #endif m_pageWidget->addPage(m_mpegItem); connect(titles,SIGNAL(addTitle(k9DVDTitle*)),streams,SLOT(addTitle(k9DVDTitle*))); connect(titles,SIGNAL(removeTitle(k9DVDTitle*)),streams,SLOT(removeTitle(k9DVDTitle*))); connect(titles,SIGNAL(addTitle(k9DVDTitle*)),mp4,SLOT(addTitle(k9DVDTitle*))); connect(titles,SIGNAL(removeTitle(k9DVDTitle*)),mp4,SLOT(removeTitle(k9DVDTitle*))); connect(titles,SIGNAL(addTitle(k9DVDTitle*)),mpeg,SLOT(addTitle(k9DVDTitle*))); connect(titles,SIGNAL(removeTitle(k9DVDTitle*)),mpeg,SLOT(removeTitle(k9DVDTitle*))); connect(titles,SIGNAL(addTitle(k9DVDTitle*)),DVDOption,SLOT(addTitle(k9DVDTitle*))); connect(titles,SIGNAL(removeTitle(k9DVDTitle*)),DVDOption,SLOT(removeTitle(k9DVDTitle*))); #if QT_VERSION >= 0x050000 buttonBox()->addButton(QDialogButtonBox::Help); connect(button(QDialogButtonBox::Help),SIGNAL(clicked()), SLOT(helpClicked())); #else connect(this,SIGNAL(helpClicked()),this,SLOT(helpClicked())); #endif m_drives->scanDrives(); #if QT_VERSION >= 0x050000 button(QDialogButtonBox::Help)->setText(i18n("Settings")); button(QDialogButtonBox::Help)->setToolTip(i18n("k9copy settings")); button(QDialogButtonBox::Help)->setIcon(QIcon(SmallIcon("configure"))); #else setButtonText(KDialog::Help,i18n("Settings")); setButtonToolTip(KDialog::Help,i18n("k9copy settings")); setButtonIcon(KDialog::Help,KIcon(SmallIcon("configure"))); #endif if (m_path !="") { source->setPath(m_path); } exec(); } void k9Assistant::back() { if (currentPage() ==m_destinationItem) { for (int i=0;i< m_dvd->gettitleCount();i++) { k9DVDTitle *title=m_dvd->gettitle(i); title->setSelected(false); } } KAssistantDialog::back(); } void k9Assistant::next() { QString err=""; k9astTitles *titles=(k9astTitles*)m_titlesItem->widget(); k9astStreams *streams=(k9astStreams*)m_streamsItem->widget(); k9astDestination *adestination=(k9astDestination*)m_destinationItem->widget(); k9astMp4 *mp4=(k9astMp4*) m_mp4Item->widget(); titles->stopPreview(); if (currentPage() == m_sourceItem) { k9astSource *source=(k9astSource*)m_sourceItem->widget(); if (source->openDvd()) { titles->fill(); adestination->updatePaths(); } else err=m_dvd->geterrMsg(); } else if (currentPage() == m_destinationItem) { if (!adestination->isOk()) err=i18n("The destination of the copy isn't valid"); streams->selectOne(false); if (adestination->isMatroska()) mp4->setMatroskaCodecs(); if ((m_destination== dstAvi) && !adestination->isMatroska()) { streams->selectOne(true); streams->hideSubtitles(false); mp4->setAviCodecs(); } else if (m_destination==dstAudio) { mp4->setAudio(); streams->hideSubtitles(true); } else streams->hideSubtitles(false); streams->updateColumns(); } else if (currentPage() == m_titlesItem) { titles->updateTitles(); if (!titles->isOk()) err=i18n("You must select at least on title !"); else titles->stopPreview(); } else if (currentPage() == m_DVDOptionItem) { k9astDVDOption *options=(k9astDVDOption*)m_DVDOptionItem->widget(); options->updateOptions(); k9astMpeg * mpeg=(k9astMpeg*)m_mpegItem->widget(); mpeg->updateFactor(); } else if (currentPage() == m_streamsItem) { streams->updateStreams(); switch (destination()) { case dstAvi: case dstAudio: setAppropriate(m_DVDOptionItem,false); setAppropriate(m_mpegItem,false); setAppropriate(m_mp4Item,true); break; case dstMpeg: setAppropriate(m_DVDOptionItem,false); setAppropriate(m_mpegItem,true); setAppropriate(m_mp4Item,false); break; case dstDVD: setAppropriate(m_DVDOptionItem,true); setAppropriate(m_mpegItem,true); setAppropriate(m_mp4Item,false); break; default: break; } } if (err=="") { KAssistantDialog::next(); streams->updateColumns(); } else k9Dialogs::error(err,i18n("cannot continue")); } void k9Assistant::helpClicked() { k9Settings settings(this,i18n("Settings")); settings.exec(); k9astTitles *titles=(k9astTitles*)m_titlesItem->widget(); titles->stopPreview(); titles->loadPlayer(); } void k9Assistant::accept() { k9astDestination *destination=(k9astDestination*)m_destinationItem->widget(); //stop preview before copying the dvd k9astTitles *titles=(k9astTitles*)m_titlesItem->widget(); titles->unloadPreview(); k9ExecCopy execCopy; execCopy.setCopyMenus(m_copyMenus); execCopy.setPath(destination->getPath()); if (m_DVDdestination== dstFolder) execCopy.setOutput(k9ExecCopy::oFolder); else if (m_DVDdestination==dstIso) execCopy.setOutput(k9ExecCopy::oISO); else execCopy.setOutput(k9ExecCopy::oDVD); execCopy.setDvd(m_dvd); switch (m_destination) { case dstDVD: execCopy.copyDVD(); break; case dstAvi: execCopy.CreateMP4(); break; case dstMpeg: execCopy.extractMPEG2(); break; case dstAudio: execCopy.extractAudio(); default: break; } KAssistantDialog::accept(); } void k9Assistant::reject() { k9astTitles *titles=(k9astTitles*)m_titlesItem->widget(); titles->unloadPreview(); KAssistantDialog::reject(); } k9Assistant::~k9Assistant() { delete m_dvd; } k9copy/src/assistant/astsource.ui0000644000175000017550000000751712417731552017733 0ustar emulatoremulator astSource 0 0 537 282 Form 0 0 DVD Drive true 0 0 Folder 0 0 ISO Image Qt::Vertical 20 157 KUrlRequester QFrame
kurlrequester.h
rbDrive toggled(bool) astSource rbDriveToggled(bool) 40 29 0 33 rbFolder toggled(bool) astSource rbFolderToggled(bool) 55 64 1 104 rbIso toggled(bool) astSource rbIsoToggled(bool) 82 97 0 161 rbDriveToggled(bool) rbFolderToggled(bool) rbIsoToggled(bool)
k9copy/src/assistant/k9astdvdoption.cpp0000644000175000017550000000356312412271774021047 0ustar emulatoremulator// // C++ Implementation: // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9astdvdoption.h" #include "k9dvd.h" #include "k9dvdtitle.h" #include #include "k9titlefactor.h" class _k9TitleListItem : public QListWidgetItem { public: _k9TitleListItem ( QListWidget *parent):QListWidgetItem(parent) {}; k9DVDTitle *title; }; k9astDVDOption::k9astDVDOption(k9Assistant* parent,k9DVD *_dvd) : QWidget(parent) { Ui_astDVDOption.setupUi(this); m_parent=parent; m_dvd=_dvd; m_titles=Ui_astDVDOption.titles; k9Config config; Ui_astDVDOption.rbMenu->setChecked(config.getKeepMenus()); Ui_astDVDOption.rbDvdauthor->setChecked(!config.getKeepMenus()); } k9astDVDOption::~k9astDVDOption() { } void k9astDVDOption::clear() { m_titles->clear(); } void k9astDVDOption::addTitle(k9DVDTitle *_title) { _k9TitleListItem *item=new _k9TitleListItem(m_titles); item->title=_title; item->setText(_title->getname()); } void k9astDVDOption::removeTitle(k9DVDTitle *_title) { for (int i=0;i count();i++) { _k9TitleListItem *item=(_k9TitleListItem*)m_titles->item(i); if (item->title==_title) { m_titles->takeItem(i); break; } } } void k9astDVDOption::updateOptions() { k9DVDTitle *title=NULL; m_parent->setCopyMenus(Ui_astDVDOption.rbMenu->isChecked()); for (int i=0;i count();i++) { _k9TitleListItem *item=(_k9TitleListItem*)m_titles->item(i); qDebug () << "title :" <title->getname(); if (i==0) { m_dvd->setstart(item->title); } else { title->setnextTitle(item->title); } title=item->title; item->title->setnextTitle(NULL); } } void k9astDVDOption::rbMenuToggled(bool _state) { Ui_astDVDOption.gbTitles->setEnabled(!_state); } /*$SPECIALIZATION$*/ k9copy/src/assistant/k9astmp4.h0000644000175000017550000000171112412271774017177 0ustar emulatoremulator// // C++ Interface: // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9ASTMP4_H #define K9ASTMP4_H #include "k9common.h" #include "ui_astmp4.h" #include "k9assistant.h" class k9DVD; class k9DVDTitle; class k9MP4Title; class k9astMp4 : public QWidget { Q_OBJECT public: k9astMp4(k9Assistant* parent,k9DVD *_dvd ); ~k9astMp4(); void setAudio(); void setMatroskaCodecs(); void setAviCodecs(); /*$PUBLIC_FUNCTIONS$*/ public slots: /*$PUBLIC_SLOTS$*/ void addTitle(k9DVDTitle*); void removeTitle(k9DVDTitle*); protected: /*$PROTECTED_FUNCTIONS$*/ protected slots: /*$PROTECTED_SLOTS$*/ void cbTitleChanged(int); private: Ui::astMp4 Ui_astMp4; k9Assistant *m_parent; k9MP4Title *m_mp4Title; k9DVD *m_dvd; QComboBox *cbTitle; QListm_titles; signals: void titleChanged(k9DVDTitle*); }; #endif k9copy/src/assistant/aststreams.ui0000644000175000017550000000226312417731552020102 0ustar emulatoremulator astStreams 0 0 400 300 Form Selected titles default lstreams itemChanged(QTreeWidgetItem*,int) astStreams itemChanged(QTreeWidgetItem*,int) 199 149 199 149 itemChanged(QTreeWidgetItem*,int) k9copy/src/assistant/astmp4.ui0000644000175000017550000000272412417731552017126 0ustar emulatoremulator astMp4 0 0 400 300 Form 0 0 Encoding options for title cbTitle cbTitle currentIndexChanged(int) astMp4 cbTitleChanged(int) 270 8 402 38 cbTitleChanged(int) k9copy/src/assistant/k9astmpeg.cpp0000644000175000017550000000331012412271774017757 0ustar emulatoremulator// // C++ Implementation: // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9astmpeg.h" #include "k9dvd.h" #include "k9dvdtitle.h" #include #include "k9titlefactor.h" k9astMpeg::k9astMpeg(k9Assistant* parent,k9DVD *_dvd) : QWidget(parent) { Ui_astMpeg.setupUi(this); m_parent=parent; m_dvd=_dvd; k9TitleFactor *titleFactor=new k9TitleFactor(Ui_astMpeg.options); m_titleFactor=titleFactor; titleFactor->SelectionChanged(m_dvd,true); m_titleFactor=titleFactor; connect (this,SIGNAL(titleChanged(k9DVDTitle*)),titleFactor,SLOT(changedTitle(k9DVDTitle*))); cbTitle=Ui_astMpeg.cbTitle; QGridLayout *grid = new QGridLayout(Ui_astMpeg.options); grid->addWidget(titleFactor,0,0); } k9astMpeg::~k9astMpeg() { } void k9astMpeg::updateFactor() { m_titleFactor->SelectionChanged(m_dvd,m_parent->copyMenus()); } void k9astMpeg::addTitle(k9DVDTitle *_title) { m_titles.append(_title); if (cbTitle->count()==1) { if (cbTitle->itemData(0,Qt::UserRole).toInt()==0) { cbTitle->setItemText(0,_title->getname()); cbTitle->setItemData(0,1,Qt::UserRole); emit titleChanged(_title); return; } } cbTitle->addItem(_title->getname(),1);} void k9astMpeg::removeTitle(k9DVDTitle *_title) { int i=m_titles.indexOf(_title); if (i!=-1) { if (cbTitle->count() ==1) { cbTitle->setItemData(0,0,Qt::UserRole); cbTitle->setItemText(0,"--"); } else cbTitle->removeItem(i); m_titles.removeOne(_title); } } void k9astMpeg::cbTitleChanged(int _index) { emit titleChanged(m_titles.at(_index)); } /*$SPECIALIZATION$*/ k9copy/src/assistant/k9astmpeg.h0000644000175000017550000000165112412271774017432 0ustar emulatoremulator// // C++ Interface: // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9ASTMPEG_H #define K9ASTMPEG_H #include "k9common.h" #include "ui_astmpeg.h" #include "k9assistant.h" class k9DVD; class k9DVDTitle; class k9TitleFactor; class k9astMpeg : public QWidget { Q_OBJECT public: k9astMpeg(k9Assistant* parent,k9DVD *_dvd ); ~k9astMpeg(); /*$PUBLIC_FUNCTIONS$*/ public slots: /*$PUBLIC_SLOTS$*/ void addTitle(k9DVDTitle*); void removeTitle(k9DVDTitle*); void updateFactor(); protected: /*$PROTECTED_FUNCTIONS$*/ protected slots: /*$PROTECTED_SLOTS$*/ void cbTitleChanged(int); private: Ui::astMpeg Ui_astMpeg; k9Assistant *m_parent; k9DVD *m_dvd; QComboBox *cbTitle; QListm_titles; k9TitleFactor *m_titleFactor; signals: void titleChanged(k9DVDTitle*); }; #endif k9copy/src/assistant/k9astdestination.h0000644000175000017550000000231212412271774021016 0ustar emulatoremulator// // C++ Interface: // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9ASTDESTINATION_H #define K9ASTDESTINATION_H #include "k9common.h" #include "ui_astdestination.h" #include "k9assistant.h" class k9CdDrives; class k9CdDrive; class k9DVD; class k9astDestination : public QWidget { Q_OBJECT public: k9astDestination(k9Assistant* parent,k9CdDrives *_drives,k9DVD *_dvd ); ~k9astDestination(); const QString &getPath(); bool isOk(); bool isMatroska(); /*$PUBLIC_FUNCTIONS$*/ public slots: /*$PUBLIC_SLOTS$*/ void updatePaths(); protected: /*$PROTECTED_FUNCTIONS$*/ protected slots: /*$PROTECTED_SLOTS$*/ void deviceAdded(k9CdDrive *_drive); void deviceRemoved(k9CdDrive *_drive); void rbDVDToggled(bool); void rbAviToggled(bool); void rbMpegToggled(bool); void rbAudioToggled(bool); void rbDVDDiscToggled(bool); void rbDVDFolderToggled(bool); void rbDVDIsoToggled(bool); private: Ui::astDestination Ui_astDestination; k9Assistant *m_parent; k9CdDrives *m_drives; k9DVD *m_dvd; void fillList(); void updategbDVD(); QString m_path; }; #endif k9copy/src/assistant/k9astmp4.cpp0000644000175000017550000000353012412271774017533 0ustar emulatoremulator// // C++ Implementation: // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9astmp4.h" #include "k9dvd.h" #include "k9dvdtitle.h" #include #include "k9mp4title.h" k9astMp4::k9astMp4(k9Assistant* parent,k9DVD *_dvd) : QWidget(parent) { Ui_astMp4.setupUi(this); m_parent=parent; m_dvd=_dvd; m_mp4Title =new k9MP4Title(Ui_astMp4.options); connect (this,SIGNAL(titleChanged(k9DVDTitle*)),m_mp4Title,SLOT(titleChanged(k9DVDTitle*))); cbTitle=Ui_astMp4.cbTitle; QGridLayout *grid = new QGridLayout(Ui_astMp4.options); grid->addWidget(m_mp4Title,0,0); } k9astMp4::~k9astMp4() { } void k9astMp4::setMatroskaCodecs() { QStringList codecs; codecs << "ffmpeg"; m_mp4Title->loadCodecs(codecs,codecs); } void k9astMp4::setAviCodecs() { m_mp4Title->loadCodecs(QStringList(),QStringList()); } void k9astMp4::setAudio() { m_mp4Title->setOptions(k9MP4Title::optAudio); QStringList codecs; codecs <<"ffmpeg"; m_mp4Title->loadCodecs(codecs,codecs); } void k9astMp4::addTitle(k9DVDTitle *_title) { m_titles.append(_title); if (cbTitle->count()==1) { if (cbTitle->itemData(0,Qt::UserRole).toInt()==0) { cbTitle->setItemText(0,_title->getname()); cbTitle->setItemData(0,1,Qt::UserRole); emit titleChanged(_title); return; } } cbTitle->addItem(_title->getname(),1); } void k9astMp4::removeTitle(k9DVDTitle *_title) { int i=m_titles.indexOf(_title); if (i!=-1) { if (cbTitle->count() ==1) { cbTitle->setItemData(0,0,Qt::UserRole); cbTitle->setItemText(0,"--"); } else cbTitle->removeItem(i); m_titles.removeOne(_title); } } void k9astMp4::cbTitleChanged(int _index) { emit titleChanged(m_titles.at(_index)); } /*$SPECIALIZATION$*/ k9copy/src/assistant/k9aststreams.h0000644000175000017550000000352512412271774020162 0ustar emulatoremulator// // C++ Interface: // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9ASTSTREAMS_H #define K9ASTSTREAMS_H #include "k9common.h" #include "ui_aststreams.h" #include "k9assistant.h" #include class k9DVD; class k9DVDTitle; class k9DVDAudioStream; class k9DVDSubtitle; class k9astStreams : public QWidget { Q_OBJECT public: k9astStreams(k9Assistant* parent,k9DVD *_dvd ); ~k9astStreams(); enum eStreamType {AUDIO,SUBTITLE}; void updateStreams(); void selectOne(bool); void updateColumns(); void hideSubtitles(bool _value); /*$PUBLIC_FUNCTIONS$*/ public slots: /*$PUBLIC_SLOTS$*/ void addTitle(k9DVDTitle *_title); void removeTitle(k9DVDTitle *_title); protected: /*$PROTECTED_FUNCTIONS$*/ void resizeEvent ( QResizeEvent * event ); void showEvent ( QShowEvent * event ); protected slots: /*$PROTECTED_SLOTS$*/ void itemChanged(QTreeWidgetItem *_item,int _column); private: Ui::astStreams Ui_astStreams; k9Assistant *m_parent; QTreeWidget *m_streams; k9DVD *m_dvd; bool m_locked; bool m_selectOne; }; class _k9StreamWidget : public QObject,public QTreeWidgetItem { Q_OBJECT public: _k9StreamWidget(k9DVDAudioStream *_stream,QTreeWidgetItem *_treeWidgetItem); _k9StreamWidget(k9DVDSubtitle *_stream,QTreeWidgetItem *_treeWidgetItem); k9DVDAudioStream *audioStream; k9DVDSubtitle *subtitle; k9astStreams *astStreams; void setDefault(bool _state) { setCheckState(1,_state?Qt::Checked:Qt::Unchecked);} ; bool isDefault() { return (checkState(1)==Qt::Checked);}; void showDefault( bool _state) {if (_state) setCheckState(1,Qt::Unchecked); else setData(1,Qt::CheckStateRole,QVariant()); }; bool operator< ( const QTreeWidgetItem & other ) const; private: }; #endif k9copy/src/assistant/k9astdvdoption.h0000644000175000017550000000162412412271774020510 0ustar emulatoremulator// // C++ Interface: // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9ASTDVDOPTION_H #define K9ASTDVDOPTION_H #include "k9common.h" #include "ui_astdvdoption.h" #include "k9assistant.h" class k9DVD; class k9DVDTitle; class k9astDVDOption : public QWidget { Q_OBJECT public: k9astDVDOption(k9Assistant* parent,k9DVD *_dvd ); ~k9astDVDOption(); /*$PUBLIC_FUNCTIONS$*/ void updateOptions(); void clear(); public slots: /*$PUBLIC_SLOTS$*/ void addTitle(k9DVDTitle*); void removeTitle(k9DVDTitle*); protected: /*$PROTECTED_FUNCTIONS$*/ protected slots: /*$PROTECTED_SLOTS$*/ void rbMenuToggled(bool); private: Ui::astDVDOption Ui_astDVDOption; k9Assistant *m_parent; k9DVD *m_dvd; QListWidget *m_titles; signals: void titleChanged(k9DVDTitle*); }; #endif k9copy/src/assistant/astdvdoption.ui0000644000175000017550000000430012417731552020424 0ustar emulatoremulator astDVDOption 0 0 398 298 Form Copy original menus Don't copy menus. Drag items to set title playing sequence true true QAbstractItemView::InternalMove rbMenu toggled(bool) astDVDOption rbMenuToggled(bool) 93 48 402 47 rbMenuToggled(bool) k9copy/src/assistant/astdestination.ui0000644000175000017550000002025012417731552020741 0ustar emulatoremulator astDestination 0 0 495 319 Form DVD Backup true false QGroupBox { border: none } true false 0 0 to Disc true false 0 0 to Folder 0 0 to Iso image 0 0 Rip and encode DVD false 0 0 Rip DVD without encoding true false false Extract audio Qt::Vertical 20 40 KUrlRequester QFrame
kurlrequester.h
rbDVD toggled(bool) astDestination rbDVDToggled(bool) 239 25 239 246 rbMpeg toggled(bool) astDestination rbMpegToggled(bool) 99 201 239 246 rbAvi toggled(bool) astDestination rbAviToggled(bool) 99 169 239 246 rbDVDDisc toggled(bool) astDestination rbDVDDiscToggled(bool) 69 64 239 246 rbDVDFolder toggled(bool) astDestination rbDVDFolderToggled(bool) 69 96 239 246 rbDVDIso toggled(bool) astDestination rbDVDIsoToggled(bool) 69 128 239 246 rbAudio toggled(bool) astDestination rbAudioToggled(bool) 92 198 243 162 rbDVDToggled(bool) rbMpegToggled(bool) rbAviToggled(bool) rbDVDDiscToggled(bool) rbDVDFolderToggled(bool) rbDVDIsoToggled(bool) rbAudioToggled(bool)
k9copy/src/assistant/CTestTestfile.cmake0000664000175000017550000000052512412271774021102 0ustar emulatoremulator# CMake generated Testfile for # Source directory: /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/src/assistant # Build directory: /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/src/assistant # # This file includes the relevant testing commands required for # testing this directory and lists subdirectories to be tested as well. k9copy/src/assistant/Makefile0000664000175000017550000001504212412271774017016 0ustar emulatoremulator# CMAKE generated file: DO NOT EDIT! # Generated by "Unix Makefiles" Generator, CMake Version 2.8 # Default target executed when no arguments are given to make. default_target: all .PHONY : default_target #============================================================================= # Special targets provided by cmake. # Disable implicit rules so canonical targets will work. .SUFFIXES: # Remove some rules from gmake that .SUFFIXES does not remove. SUFFIXES = .SUFFIXES: .hpux_make_needs_suffix_list # Suppress display of executed commands. $(VERBOSE).SILENT: # A target that is always out of date. cmake_force: .PHONY : cmake_force #============================================================================= # Set environment variables for the build. # The shell in which to execute make rules. SHELL = /bin/sh # The CMake executable. CMAKE_COMMAND = /usr/bin/cmake # The command to remove a file. RM = /usr/bin/cmake -E remove -f # Escaping for special characters. EQUALS = = # The program to use to edit the cache. CMAKE_EDIT_COMMAND = /usr/bin/ccmake # The top-level source directory on which CMake was run. CMAKE_SOURCE_DIR = /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 # The top-level build directory on which CMake was run. CMAKE_BINARY_DIR = /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 #============================================================================= # Targets provided globally by CMake. # Special rule for the target edit_cache edit_cache: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." /usr/bin/ccmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) .PHONY : edit_cache # Special rule for the target edit_cache edit_cache/fast: edit_cache .PHONY : edit_cache/fast # Special rule for the target install install: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." /usr/bin/cmake -P cmake_install.cmake .PHONY : install # Special rule for the target install install/fast: preinstall/fast @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." /usr/bin/cmake -P cmake_install.cmake .PHONY : install/fast # Special rule for the target install/local install/local: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..." /usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake .PHONY : install/local # Special rule for the target install/local install/local/fast: install/local .PHONY : install/local/fast # Special rule for the target list_install_components list_install_components: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"Unspecified\"" .PHONY : list_install_components # Special rule for the target list_install_components list_install_components/fast: list_install_components .PHONY : list_install_components/fast # Special rule for the target package package: preinstall @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Run CPack packaging tool..." cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && /usr/bin/cpack --config ./CPackConfig.cmake .PHONY : package # Special rule for the target package package/fast: package .PHONY : package/fast # Special rule for the target package_source package_source: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Run CPack packaging tool for source..." cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && /usr/bin/cpack --config ./CPackSourceConfig.cmake /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CPackSourceConfig.cmake .PHONY : package_source # Special rule for the target package_source package_source/fast: package_source .PHONY : package_source/fast # Special rule for the target rebuild_cache rebuild_cache: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." /usr/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) .PHONY : rebuild_cache # Special rule for the target rebuild_cache rebuild_cache/fast: rebuild_cache .PHONY : rebuild_cache/fast # Special rule for the target test test: @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running tests..." /usr/bin/ctest --force-new-ctest-process $(ARGS) .PHONY : test # Special rule for the target test test/fast: test .PHONY : test/fast # The main all target all: cmake_check_build_system cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(CMAKE_COMMAND) -E cmake_progress_start /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CMakeFiles /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/src/assistant/CMakeFiles/progress.marks cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 src/assistant/all $(CMAKE_COMMAND) -E cmake_progress_start /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/CMakeFiles 0 .PHONY : all # The main clean target clean: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 src/assistant/clean .PHONY : clean # The main clean target clean/fast: clean .PHONY : clean/fast # Prepare targets for installation. preinstall: all cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 src/assistant/preinstall .PHONY : preinstall # Prepare targets for installation. preinstall/fast: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(MAKE) -f CMakeFiles/Makefile2 src/assistant/preinstall .PHONY : preinstall/fast # clear depends depend: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 .PHONY : depend # Help Target help: @echo "The following are some of the valid targets for this Makefile:" @echo "... all (the default if no target is provided)" @echo "... clean" @echo "... depend" @echo "... edit_cache" @echo "... install" @echo "... install/local" @echo "... list_install_components" @echo "... package" @echo "... package_source" @echo "... rebuild_cache" @echo "... test" .PHONY : help #============================================================================= # Special targets to cleanup operation of make. # Special rule to run CMake to check the build system integrity. # No rule that depends on this can have commands that come from listfiles # because they might be regenerated. cmake_check_build_system: cd /home/emulator/Desktop/k9copy-project/TESTBED_KDE4 && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 .PHONY : cmake_check_build_system k9copy/src/assistant/k9asttitles.h0000644000175000017550000000400712412271774020004 0ustar emulatoremulator// // C++ Interface: // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9ASTTITLES_H #define K9ASTTITLES_H #include "k9common.h" #include "ui_asttitles.h" class kViewMPEG2; class _k9ItemWidget; class k9DVD; class k9DVDTitle; class k9DVDChapter; class k9astTitles : public QWidget { Q_OBJECT public: enum itemType {TITLE,CHAPTER,AUDIO,SUBTITLE,VIDEO}; k9astTitles(QWidget* parent,k9DVD *_dvd); ~k9astTitles(); /*$PUBLIC_FUNCTIONS$*/ void fill(); void updateTitles(); void titleSelected(k9DVDTitle *_title); void titleUnSelected(k9DVDTitle *_title); void stopPreview(); void unloadPreview(); bool isOk(); void loadPlayer(); public slots: /*$PUBLIC_SLOTS$*/ protected: /*$PROTECTED_FUNCTIONS$*/ void resizeEvent ( QResizeEvent * event ); void addChapters(QTreeWidgetItem *_parent,k9DVDTitle *_title); protected slots: /*$PROTECTED_SLOTS$*/ void itemActivated(QTreeWidgetItem*,int); void CurrentItemChanged(QTreeWidgetItem *_new,QTreeWidgetItem *_old); void ItemChanged(QTreeWidgetItem*,int); void ItemExpanded(QTreeWidgetItem*); void selectAll(bool); private: bool m_useXine,m_usePhonon,m_useMplayer; Ui::astTitles Ui_astTitles; k9DVD *m_dvd; QTreeWidget *m_src; bool m_updating; QWidget *m_preview; QGridLayout *m_layout; _k9ItemWidget *m_currentItem; signals: void addTitle(k9DVDTitle *_title); void removeTitle(k9DVDTitle *_title); void sigshowPreview( k9DVD*, k9DVDTitle*,int ); void sigstopPreview(); }; class _k9ItemWidget : public QObject,public QTreeWidgetItem { Q_OBJECT public: _k9ItemWidget(k9DVDTitle *_title,QTreeWidget *_treeWidget,int _type); _k9ItemWidget(k9DVDChapter *_chapter,QTreeWidgetItem *_treeWidget,int _type); k9DVDTitle *title; k9DVDChapter *chapter; k9astTitles *astTitle; bool operator< ( const QTreeWidgetItem & other ) const ; private slots: void titleChanged(); void chapterChanged(); }; #endif k9copy/src/assistant/CMakeFiles/0000775000175000017550000000000012412271774017317 5ustar emulatoremulatork9copy/src/assistant/CMakeFiles/progress.marks0000664000175000017550000000000212412271774022212 0ustar emulatoremulator0 k9copy/src/assistant/CMakeFiles/CMakeDirectoryInformation.cmake0000664000175000017550000000124312412271774025374 0ustar emulatoremulator# CMAKE generated file: DO NOT EDIT! # Generated by "Unix Makefiles" Generator, CMake Version 2.8 # Relative path conversion top directories. SET(CMAKE_RELATIVE_PATH_TOP_SOURCE "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4") SET(CMAKE_RELATIVE_PATH_TOP_BINARY "/home/emulator/Desktop/k9copy-project/TESTBED_KDE4") # Force unix paths in dependencies. SET(CMAKE_FORCE_UNIX_PATHS 1) # The C and CXX include file regular expressions for this directory. SET(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") SET(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") SET(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) SET(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) k9copy/src/assistant/k9asttitles.cpp0000644000175000017550000002525512412271774020347 0ustar emulatoremulator// // C++ Implementation: // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9asttitles.h" #include "k9dvd.h" #include "k9dvdtitle.h" #include #include "kviewmpeg2.h" #include #include _k9ItemWidget::_k9ItemWidget(k9DVDTitle *_title,QTreeWidget *_treeWidget,int _type):QObject(0),QTreeWidgetItem(_treeWidget,_type) { switch (_type) { case k9astTitles::TITLE : title=_title; setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsSelectable); setCheckState(0,Qt::Unchecked); setTextAlignment(2,Qt::AlignRight); setTextAlignment(3,Qt::AlignRight); connect (title,SIGNAL(selectionChanged()),this,SLOT(titleChanged())); break; } } _k9ItemWidget::_k9ItemWidget(k9DVDChapter *_chapter,QTreeWidgetItem *_treeWidget,int _type):QObject(0),QTreeWidgetItem(_treeWidget,_type) { chapter=_chapter; setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsSelectable); setCheckState(0,Qt::Unchecked); connect (chapter,SIGNAL(selectionChanged()),this,SLOT(chapterChanged())); setTextAlignment(2,Qt::AlignRight); setTextAlignment(3,Qt::AlignRight); } void _k9ItemWidget::titleChanged() { if (title->isSelected()) { setCheckState(0,Qt::Checked); astTitle->titleSelected(title); } else { setCheckState(0,Qt::Unchecked); astTitle->titleUnSelected(title); } } void _k9ItemWidget::chapterChanged() { if (chapter->getSelected()) setCheckState(0,Qt::Checked); else setCheckState(0,Qt::Unchecked); } bool _k9ItemWidget::operator< ( const QTreeWidgetItem & other ) const { _k9ItemWidget *it=(_k9ItemWidget*)&other; if (it->type()!= k9astTitles::TITLE) return true; switch (treeWidget()->sortColumn()) { case 1: return title->getnumTitle() <((_k9ItemWidget*)&other)->title->getnumTitle(); case 2: return title->getlength() <((_k9ItemWidget*)&other)->title->getlength(); case 3: return title->gettotalsize_mb() <((_k9ItemWidget*)&other)->title->gettotalsize_mb(); default: return true; } } k9astTitles::k9astTitles(QWidget* parent,k9DVD *_dvd) : QWidget(parent) { Ui_astTitles.setupUi(this); m_dvd=_dvd; m_src=Ui_astTitles.twSource; m_preview=NULL; m_currentItem=NULL; loadPlayer(); QTreeWidgetItem *header=m_src->headerItem(); header->setText(0,""); QCheckBox *ck=new QCheckBox(m_src); ck->setChecked(true); connect(ck,SIGNAL(toggled( bool )),this,SLOT(selectAll(bool))); connect(m_src,SIGNAL(itemChanged(QTreeWidgetItem*,int)),this,SLOT(ItemChanged(QTreeWidgetItem*,int))); m_src->setItemWidget(header,0,ck); m_src->setSortingEnabled(true); } void k9astTitles::loadPlayer() { k9Config config; m_useXine=config.getUseXine(); m_usePhonon=config.getUsePhonon(); m_useMplayer=config.getUseMplayer(); if (m_preview) { delete m_preview; delete m_layout; } if (m_useXine) { m_preview=new k9xine(Ui_astTitles.wPreview); } else if (m_usePhonon) { m_preview=new k9Phonon(Ui_astTitles.wPreview); } else if (m_useMplayer) m_preview=new K9Mplayer(Ui_astTitles.wPreview); else m_preview=new kViewMPEG2(Ui_astTitles.wPreview); connect(this,SIGNAL(sigshowPreview( k9DVD*, k9DVDTitle*,int )),m_preview,SLOT(open( k9DVD*, k9DVDTitle*,int ))); connect(this,SIGNAL(sigstopPreview()),m_preview,SLOT(bStopClick())); m_layout=new QGridLayout(Ui_astTitles.wPreview); m_layout->addWidget(m_preview,0,0); m_preview->show(); } void k9astTitles::itemActivated(QTreeWidgetItem* _item,int) { _k9ItemWidget *item=(_k9ItemWidget*)_item; if (item) { if (item->type()==TITLE) emit sigshowPreview(m_dvd,item->title,1); } } void k9astTitles::CurrentItemChanged(QTreeWidgetItem *_new,QTreeWidgetItem *_old) { if (m_updating) return; _k9ItemWidget *previous,*current; previous=(_k9ItemWidget*)_old; current=(_k9ItemWidget*)_new; if (current) { if (current->type() ==TITLE) { /* for (int i=0;i topLevelItemCount();i++) { _k9ItemWidget *item=(_k9ItemWidget*) m_src->topLevelItem(i); if (item != current) item->setExpanded(false); else item->setExpanded(true); } */ m_currentItem=current; itemActivated(current,0); } } } void k9astTitles::ItemChanged(QTreeWidgetItem *_item,int col) { Q_UNUSED(col); if (m_updating) return; m_updating=true; _k9ItemWidget *item=(_k9ItemWidget*)_item; if ((item->type()==TITLE)) { for (int i=0;i< item->childCount();i++) { _k9ItemWidget *it=(_k9ItemWidget*)item->child(i); it->setCheckState(0,item->checkState(0)); } } else if (item->type()==CHAPTER) { _k9ItemWidget *it=(_k9ItemWidget*)_item->parent(); bool selected=false; for (int i=0;ichildCount();i++) { _k9ItemWidget *it2=(_k9ItemWidget*)it->child(i); if (it2->checkState(0)==Qt::Checked) selected=true; } if (!selected) it->setCheckState(0,Qt::Unchecked); else it->setCheckState(0,Qt::Checked); } m_updating=false; } k9astTitles::~k9astTitles() { emit sigstopPreview(); } void k9astTitles::unloadPreview() { if (m_preview) delete m_preview; m_preview =NULL; } /*$SPECIALIZATION$*/ void k9astTitles::stopPreview() { emit sigstopPreview(); } void k9astTitles::titleSelected(k9DVDTitle *_title) { if (!m_updating) emit addTitle(_title); } void k9astTitles::titleUnSelected(k9DVDTitle *_title) { if (!m_updating) emit removeTitle(_title); } void k9astTitles::selectAll(bool _state) { bool oldState; for (int i=0; i < m_src->topLevelItemCount();i++) { _k9ItemWidget *item=(_k9ItemWidget*) m_src->topLevelItem(i); oldState=item->title->isSelected(); if (_state) { m_updating=true; // all streams are checked by default for (int j=0;j < item->title->getaudioStreamCount();j++) { item->title->getaudioStream(j)->setselected(true); if (j==0) item->title->setDefAudio(item->title->getaudioStream(j)); } for (int j=0;j < item->title->getsubPictureCount();j++) { item->title->getsubtitle(j)->setselected(true); if (j==0) item->title->setDefSubtitle(item->title->getsubtitle(j)); } item->title->setvideoSelected(true); m_updating=false; if (_state!=oldState) emit addTitle(item->title); } else { m_updating=true; item->title->setSelected(false); item->title->setDefSubtitle(NULL); item->title->setDefAudio(NULL); m_updating=false; if (_state!=oldState) emit removeTitle(item->title); } } } void k9astTitles::fill() { m_src->clear(); m_currentItem=NULL; for (int i=0;i < m_dvd->gettitleCount();i++) { k9DVDTitle *title=m_dvd->gettitle(i); if (title->getIndexed()) { m_updating=true; _k9ItemWidget *item=new _k9ItemWidget(title,m_src,k9astTitles::TITLE ); item->astTitle=this; item->setText(0,""); item->setText(1,QString("%1").arg(title->getname())); item->setText(2,QString("%1").arg(title->getlength().toString("hh:mm:ss"))); item->setText(3,QString("%1 %2").arg(title->gettotalsize_mb(),0,'f',2).arg(i18n("MB"))); if (!m_currentItem) { m_currentItem=item; } addChapters(item,title); // all streams are checked by default title->setSelected(true); m_updating=false; emit addTitle(title); } } m_src->sortItems(1,Qt::AscendingOrder); } void k9astTitles::addChapters(QTreeWidgetItem *_parent,k9DVDTitle *_title) { //_parent->setExpanded(true); int ch=0; for (int i=0;i< _title->getchapterCount();i++) { _k9ItemWidget *it =new _k9ItemWidget(_title->getChapter(i),_parent,k9astTitles::CHAPTER); it->setText(1,i18n("chapter %1").arg(++ch)); QString s; s=QString("%1").arg((double)(_title->getChapter(i)->getsectors()) /512,0,'f',2); it->setText(2,QString("%1").arg(_title->getChapter(i)->getLength().toString("hh:mm:ss"))); it->setText(3,i18n("%1 MB").arg(s)); } for (int j=0;j <_title->getTitles().count();j++) { k9DVDTitle *title2=_title->getTitles().at(j); for (int i=0;i< title2->getchapterCount();i++) { _k9ItemWidget *it =new _k9ItemWidget(title2->getChapter(i),_parent,k9astTitles::CHAPTER); it->setText(1,i18n("chapter %1").arg(++ch)); QString s; s=QString("%1").arg((double)(title2->getChapter(i)->getsectors()) /512,0,'f',2); it->setText(2,QString("%1").arg(title2->getChapter(i)->getLength().toString("hh:mm:ss"))); it->setText(3,i18n("%1 MB").arg(s)); } } } void k9astTitles::ItemExpanded(QTreeWidgetItem *) { resizeEvent(0); } void k9astTitles::resizeEvent ( QResizeEvent * ) { m_src->setColumnWidth(1,m_src->viewport()->width()); m_src->resizeColumnToContents(0); m_src->resizeColumnToContents(2); m_src->resizeColumnToContents(3); m_src->setColumnWidth(1,m_src->viewport()->width()-m_src->columnWidth(0)-m_src->columnWidth(2)-m_src->columnWidth(3)-10); } void k9astTitles::updateTitles() { for (int j=0;j< m_src->topLevelItemCount();j++) { _k9ItemWidget *item=(_k9ItemWidget*)m_src->topLevelItem(j); if (item->checkState(0)==Qt::Unchecked) { item->title->setSelected(false); } else if (!item->title->isSelected()) { m_updating=true; for(int iChapter=0;iChapterchildCount();iChapter++) { _k9ItemWidget *itc=(_k9ItemWidget*)item->child(iChapter); itc->chapter->setSelected(itc->checkState(0)==Qt::Checked); } item->title->setSelected(true); emit addTitle(item->title); m_updating=false; } } //reselectionner les titres qui ont été recochés } bool k9astTitles::isOk() { bool ok=false; for (int i=0;i < m_dvd->gettitleCount();i++) { k9DVDTitle *title=m_dvd->gettitle(i); ok= (title->getIndexed() && title->isSelected())?true:ok; } return ok; } k9copy/src/assistant/CMakeLists.txt0000644000175000017550000000000012412271774020100 0ustar emulatoremulatork9copy/src/assistant/k9aststreams.cpp0000644000175000017550000002105012412271774020506 0ustar emulatoremulator// // C++ Implementation: // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9aststreams.h" #include "k9dvd.h" #include "k9dvdtitle.h" #include #if QT_VERSION >= 0x050000 #include #include #endif class _k9TitleWidget : public QTreeWidgetItem { public: _k9TitleWidget(QTreeWidget *_parent,k9DVDTitle *_title):QTreeWidgetItem(_parent,QTreeWidgetItem::UserType+5) { title=_title; } k9DVDTitle *title; bool operator< ( const QTreeWidgetItem & other ) const { return title->getnumTitle() <((_k9TitleWidget*)&other)->title->getnumTitle(); } }; bool _k9StreamWidget::operator < ( const QTreeWidgetItem & other ) const { bool res=false; _k9StreamWidget *it1=(_k9StreamWidget*) this; _k9StreamWidget *it2=(_k9StreamWidget*) &other; if (it1->type() != it2->type()) { res=it1->type()==k9astStreams::AUDIO; } else { if (it1->type()==k9astStreams::AUDIO) res=(it1->audioStream->getID() < it2->audioStream->getID()); else res=(it1->subtitle->getID().at(0) < it2->subtitle->getID().at(0)); } return res; } _k9StreamWidget::_k9StreamWidget(k9DVDAudioStream *_stream,QTreeWidgetItem *_treeWidgetItem):QObject(0),QTreeWidgetItem(_treeWidgetItem,k9astStreams::AUDIO) { audioStream=_stream; subtitle=NULL; showDefault(false); setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsSelectable); setCheckState(0,_stream->getselected()?Qt::Checked:Qt::Unchecked); setText(0,i18n("%4 - %1 %2 %3 ch").arg(_stream->getlanguage()).arg(_stream->getformat()).arg(_stream->getchannels()).arg(_stream->getID())); setIcon(0,SmallIcon("sound")) ; //setText(1,i18n("%1 MB",_stream->getsize_mb())); } _k9StreamWidget::_k9StreamWidget(k9DVDSubtitle *_stream,QTreeWidgetItem *_treeWidgetItem):QObject(0),QTreeWidgetItem(_treeWidgetItem,k9astStreams::SUBTITLE) { audioStream=NULL; subtitle=_stream; showDefault(false); setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsSelectable); setCheckState(0,_stream->getselected()?Qt::Checked:Qt::Unchecked); setText(0,i18n("%3 - %1 %2").arg(_stream->getlanguage()).arg(_stream->getcontent()).arg(_stream->getID().first())); setIcon(0,SmallIcon("subtitle")); //setText(1,i18n("%1 MB",_stream->getsize_mb())); } k9astStreams::k9astStreams(k9Assistant* parent,k9DVD *_dvd) : QWidget(parent) { Ui_astStreams.setupUi(this); m_parent=parent; m_dvd=_dvd; m_streams=Ui_astStreams.lstreams; m_streams->setRootIsDecorated(false); m_streams->setSortingEnabled(true); m_locked=false; m_selectOne=false; } k9astStreams::~k9astStreams() { } void k9astStreams::showEvent(QShowEvent *) { resizeEvent(0); } void k9astStreams::resizeEvent ( QResizeEvent * ) { if ( ! m_streams->isColumnHidden(1)) { m_streams->setColumnWidth(0,m_streams->viewport()->width()); m_streams->resizeColumnToContents(1); m_streams->setColumnWidth(0,m_streams->viewport()->width()-m_streams->columnWidth(1)); } } void k9astStreams::itemChanged(QTreeWidgetItem *_item,int _column) { if (_item->type()==QTreeWidgetItem::UserType+5) return; switch (_column) { case 0: { _k9StreamWidget *item2=(_k9StreamWidget*)_item; if ((!m_locked) && m_selectOne &&(_item->type()==AUDIO || _item->type()==SUBTITLE ) && _item->checkState(0)==Qt::Checked) { m_locked=true; QTreeWidgetItem *parent=_item->parent(); for (int i=0; i childCount();i++) { _k9StreamWidget *item=(_k9StreamWidget*) parent->child(i); if ( (item!=item2) && ( item->type()==item2->type())) item->setCheckState(0,Qt::Unchecked); } m_locked=false; } if (_item->checkState(0)==Qt::Checked) { item2->setDefault(false); item2->showDefault(true); } else item2->showDefault(false); } break; case 1: { //only one stream /type /type can be selected if (_item->checkState(1)==Qt::Checked) { QTreeWidgetItem *parent=_item->parent(); for (int i=0; i childCount();i++) { _k9StreamWidget *item=(_k9StreamWidget*) parent->child(i); _k9StreamWidget *item2=(_k9StreamWidget*)_item; //default checkbox is unchecked only if the stream is selected if ( (item!=_item) && ( item->type()==item2->type()) && (item->checkState(0)==Qt::Checked)) item->setDefault(false); } } } break; default: break; } } /*$SPECIALIZATION$*/ void k9astStreams::addTitle(k9DVDTitle *_title) { _k9TitleWidget *item=new _k9TitleWidget(m_streams,_title); item->setText(0,_title->getname()); for (int i=0; i < _title->getaudioStreamCount();i++) { new _k9StreamWidget(_title->getaudioStream(i),item); } for (int i=0;i <_title->getsubPictureCount();i++) { _k9StreamWidget *subtitle=new _k9StreamWidget(_title->getsubtitle(i),item); if (m_parent->destination()==dstAudio) subtitle->setHidden(true); } item->setExpanded(true); m_streams->sortItems(0,Qt::AscendingOrder); updateColumns(); } void k9astStreams::removeTitle(k9DVDTitle *_title) { for (int i=0; i< m_streams->topLevelItemCount();i++) { _k9TitleWidget *item=(_k9TitleWidget*)m_streams->topLevelItem(i); if (item->title == _title) { m_streams->takeTopLevelItem(i); } } } void k9astStreams::updateStreams() { for (int i=0; i< m_streams->topLevelItemCount();i++) { _k9TitleWidget *itemTitle=(_k9TitleWidget*)m_streams->topLevelItem(i); itemTitle->title->setDefAudio(NULL); itemTitle->title->setDefSubtitle(NULL); for (int c=0;c < itemTitle->childCount();c++) { if (m_streams->topLevelItem(i)->childCount() ==0) continue; _k9StreamWidget *w= (_k9StreamWidget*)itemTitle->child(c); if (w->type()==AUDIO) { bool state=(w->checkState(0)==Qt::Checked)?true:false; w->audioStream->setselected(state); if (w->audioStream->getselected() && (w->isDefault())) { w->audioStream->gettitle()->setDefAudio(w->audioStream); } } if (w->type()==SUBTITLE) { bool state=(w->checkState(0)==Qt::Checked)?true:false; w->subtitle->setselected(state); if (w->subtitle->getselected() && (w->isDefault())) { w->subtitle->gettitle()->setDefSubtitle(w->subtitle); } } } } } void k9astStreams::selectOne( bool _value) { m_selectOne=_value; //keep only the first selected stream from each title (avi) for (int i=0;m_selectOne && (i< m_streams->topLevelItemCount());i++) { bool audio=false; bool subp=false; for (int c=0;c < m_streams->topLevelItem(i)->childCount()-1;c++) { _k9StreamWidget *w=(_k9StreamWidget*)m_streams->topLevelItem(i)->child(c); if ( (w->type()==AUDIO)&&( w->checkState(0)==Qt::Checked) && (!audio)) { itemChanged(w,0); audio=true; } if ( (w->type()==SUBTITLE)&&( w->checkState(0)==Qt::Checked) && (!subp)) { itemChanged(w,0); subp=true; } } } } void k9astStreams::hideSubtitles(bool _value) { for (int i=0;i< m_streams->topLevelItemCount();i++) { for (int c=0;c < m_streams->topLevelItem(i)->childCount();c++) { _k9StreamWidget *w=(_k9StreamWidget*)m_streams->topLevelItem(i)->child(c); if ( w->type()==SUBTITLE) { w->setHidden(_value); if (_value) w->setCheckState(0,Qt::Unchecked); } } } } void k9astStreams::updateColumns() { bool visible; visible =((m_parent->destination()==dstDVD) ||(m_parent->destination()==dstFolder) || (m_parent->destination()==dstIso)) ; // qDebug() << "visible :" << visible << " destination :" << m_parent->destination(); m_streams->setColumnHidden(1,!visible); if (visible) { m_streams->setColumnWidth(0,m_streams->viewport()->width()); m_streams->resizeColumnToContents(1); m_streams->setColumnWidth(0,m_streams->viewport()->width()-m_streams->columnWidth(1)); } } k9copy/src/assistant/k9assistant.h0000644000175000017550000000401712412271774020002 0ustar emulatoremulator// // C++ Interface: k9assistant // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: <>, (C) 2008 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9ASSISTANT_H #define K9ASSISTANT_H #include "k9common.h" #include #include /** @author */ enum eDestination {dstDVD,dstAvi,dstMpeg,dstIso,dstFolder,dstAudio}; class k9DVD; class k9CdDrives; class k9Assistant : public KAssistantDialog { Q_OBJECT public: k9Assistant(KPageWidget *_pageWidget); ~k9Assistant(); static k9Assistant *createAssistant(); void setDrives ( k9CdDrives* theValue ) { m_drives = theValue; } void setDvd(k9DVD* theValue) { m_dvd = theValue; } k9DVD* getDvd() const { return m_dvd; } void setDestination(const eDestination& theValue) { m_destination = theValue; } eDestination destination() const { return m_destination; } public slots: void next(); void back(); void accept(); void reject(); void run(); void helpClicked(); void setCopyMenus(bool theValue) { m_copyMenus = theValue; } bool copyMenus() const { return m_copyMenus; } void setPath(const QString& theValue) { m_path = theValue; } QString path() const { return m_path; } void setDVDdestination(const eDestination& theValue) { m_DVDdestination = theValue; } eDestination DVDdestination() const { return m_DVDdestination; } private: KPageWidget *m_pageWidget; KPageWidgetItem *m_sourceItem; KPageWidgetItem *m_destinationItem; KPageWidgetItem *m_titlesItem; KPageWidgetItem *m_streamsItem; KPageWidgetItem *m_mp4Item; KPageWidgetItem *m_mpegItem; KPageWidgetItem *m_DVDOptionItem; k9DVD *m_dvd; k9CdDrives *m_drives; eDestination m_destination; eDestination m_DVDdestination; bool m_copyMenus; QString m_path; }; #endif k9copy/src/assistant/cmake_install.cmake0000664000175000017550000000226212412271774021166 0ustar emulatoremulator# Install script for directory: /home/emulator/Desktop/k9copy-project/TESTBED_KDE4/src/assistant # Set the install prefix IF(NOT DEFINED CMAKE_INSTALL_PREFIX) SET(CMAKE_INSTALL_PREFIX "/usr/local") ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") # Set the install configuration name. IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) IF(BUILD_TYPE) STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") ELSE(BUILD_TYPE) SET(CMAKE_INSTALL_CONFIG_NAME "RelWithDebInfo") ENDIF(BUILD_TYPE) MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) # Set the component getting installed. IF(NOT CMAKE_INSTALL_COMPONENT) IF(COMPONENT) MESSAGE(STATUS "Install component: \"${COMPONENT}\"") SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") ELSE(COMPONENT) SET(CMAKE_INSTALL_COMPONENT) ENDIF(COMPONENT) ENDIF(NOT CMAKE_INSTALL_COMPONENT) # Install shared libraries without execute permission? IF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) SET(CMAKE_INSTALL_SO_NO_EXE "0") ENDIF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) k9copy/src/assistant/astmpeg.ui0000644000175000017550000000272512417731552017357 0ustar emulatoremulator astMpeg 0 0 400 300 Form 0 0 Select options for title cbTitle cbTitle currentIndexChanged(int) astMpeg cbTitleChanged(int) 232 23 402 36 cbTitleChanged(int) k9copy/src/assistant/k9astsource.h0000644000175000017550000000174112412271774020002 0ustar emulatoremulator// // C++ Interface: // // Description: // // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef K9ASTSOURCE_H #define K9ASTSOURCE_H #include "k9common.h" #include "ui_astsource.h" #include "k9assistant.h" class k9CdDrives; class k9CdDrive; class k9DVD; class k9astSource : public QWidget { Q_OBJECT public: k9astSource(k9Assistant* parent,k9CdDrives *_drives,k9DVD *_dvd ); ~k9astSource(); void setPath(const QString &_path); bool openDvd(); /*$PUBLIC_FUNCTIONS$*/ public slots: /*$PUBLIC_SLOTS$*/ protected: /*$PROTECTED_FUNCTIONS$*/ protected slots: /*$PROTECTED_SLOTS$*/ void deviceAdded(k9CdDrive *_drive); void deviceRemoved(k9CdDrive *_drive); void rbDriveToggled(bool); void rbFolderToggled(bool); void rbIsoToggled(bool); private: Ui::astSource Ui_astSource; k9Assistant *m_parent; k9CdDrives *m_drives; k9DVD *m_dvd; void fillList(); }; #endif k9copy/src/assistant/asttitles.ui0000644000175000017550000000641112417731552017727 0ustar emulatoremulator astTitles 0 0 624 300 Form 300 0 true 10 true false titles Length size 0 0 300 0 300 16777215 twSource itemActivated(QTreeWidgetItem*,int) astTitles itemActivated(QTreeWidgetItem*,int) 308 129 514 129 twSource currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*) astTitles CurrentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*) 158 149 311 149 twSource itemExpanded(QTreeWidgetItem*) astTitles ItemExpanded(QTreeWidgetItem*) 64 51 4 63 itemActivated(QTreeWidgetItem*,int) CurrentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*) ItemExpanded(QTreeWidgetItem*) k9copy/src/assistant/k9astdestination.cpp0000644000175000017550000001574312412271774021365 0ustar emulatoremulator// // C++ Implementation: // // Description: // // Developer: Pauline123 , (C) 2014 // // Author: Jean-Michel PETIT , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "k9astdestination.h" #include "k9dvd.h" #include "k9cddrive.h" #include #include "QDebug" #if QT_VERSION >= 0x050000 #include #include #else #include #endif k9astDestination::k9astDestination(k9Assistant* parent,k9CdDrives *_drives,k9DVD *_dvd) : QWidget(parent) { Ui_astDestination.setupUi(this); m_parent=parent; m_drives=_drives; m_dvd=_dvd; fillList(); m_parent->setDVDdestination(dstDVD); Ui_astDestination.rbDVD->setChecked(false); Ui_astDestination.rbDVD->setChecked(true); Ui_astDestination.urFolder->setMode(KFile::Directory | KFile::ExistingOnly); Ui_astDestination.urMpeg->setVisible(false); Ui_astDestination.urAvi->setVisible(false); Ui_astDestination.urAudio->setVisible(false); Ui_astDestination.urAvi->setFilter("*.avi|Audio Video Interleave (*.avi)\n*.mpg|MPEG-1 and MPEG-2 systems (*.mpg)\n*.mp4|MPEG-4 format (*.mp4)\n*.asf|Advanced Streaming Format (*.asf)\n*.swf|Adobe Flash (*.swf)\n*.flv|Adobe Flash video files (*.flv)\n*.rm|RealVideo (*.rm)\n*.mov|QuickTime (*.mov)\n*.mkv|Matroska (*.mkv)"); Ui_astDestination.urAvi->setMode(KFile::File) ; #if QT_VERSION >= 0x050000 //Qt5 Code Ui_astDestination.urAvi->fileDialog()->setAcceptMode(QFileDialog::AcceptSave); #else //Qt4 Code Ui_astDestination.urAvi->fileDialog()->setOperationMode(KFileDialog::Saving); #endif Ui_astDestination.urIso->setFilter("*.iso|Iso Image (*.iso)"); Ui_astDestination.urIso->setMode(KFile::File) ; #if QT_VERSION >= 0x050000 Ui_astDestination.urIso->fileDialog()->setAcceptMode(QFileDialog::AcceptSave); #else Ui_astDestination.urIso->fileDialog()->setOperationMode(KFileDialog::Saving); #endif Ui_astDestination.urMpeg->setFilter("*.mpg|Mpeg video file (*.mpg)"); Ui_astDestination.urMpeg->setMode(KFile::File); #if QT_VERSION >= 0x050000 Ui_astDestination.urMpeg->fileDialog()->setAcceptMode(QFileDialog::AcceptSave); #else Ui_astDestination.urMpeg->fileDialog()->setOperationMode(KFileDialog::Saving); #endif Ui_astDestination.urAudio->setMode(KFile::Directory | KFile::ExistingOnly); updategbDVD(); } void k9astDestination::fillList() { connect(m_drives,SIGNAL(deviceAdded( k9CdDrive*)),this,SLOT(deviceAdded( k9CdDrive* ))); connect(m_drives,SIGNAL(deviceRemoved( k9CdDrive*)),this,SLOT(deviceRemoved( k9CdDrive* ))); } void k9astDestination::updatePaths() { k9Config config; QString title=m_parent->getDvd()->getDVDTitle(); title= title.isEmpty() ? i18n("unknown"):title; #if QT_VERSION >= 0x050000 Ui_astDestination.urFolder->setUrl(QUrl(QDir::cleanPath(config.getPrefOutput()))); Ui_astDestination.urIso->setUrl(QUrl(QDir::cleanPath(config.getPrefOutputIso()+"/"+title+".iso") )); Ui_astDestination.urAudio->setUrl(QUrl(QDir::cleanPath(config.getPrefOutputAudio()))); Ui_astDestination.urAvi->setUrl(QUrl(QDir::cleanPath(config.getPrefOutputMpeg4()+"/"+title+".avi") )); Ui_astDestination.urMpeg->setUrl(QUrl(QDir::cleanPath(config.getPrefOutputMpeg2()+"/"+title+".mpg") )); #else Ui_astDestination.urFolder->setUrl(KUrl(QDir::cleanPath(config.getPrefOutput()))); Ui_astDestination.urIso->setUrl(KUrl(QDir::cleanPath(config.getPrefOutputIso()+"/"+title+".iso") )); Ui_astDestination.urAudio->setUrl(KUrl(QDir::cleanPath(config.getPrefOutputAudio()))); Ui_astDestination.urAvi->setUrl(KUrl(QDir::cleanPath(config.getPrefOutputMpeg4()+"/"+title+".avi") )); Ui_astDestination.urMpeg->setUrl(KUrl(QDir::cleanPath(config.getPrefOutputMpeg2()+"/"+title+".mpg") )); #endif } void k9astDestination::deviceAdded(k9CdDrive *_drive) { if (_drive->canWriteDVD) { Ui_astDestination.cbDrives->addItem(QString("%1 (%2)").arg(_drive->name).arg(_drive->device),_drive->device ); } } void k9astDestination::rbDVDToggled(bool _state) { Ui_astDestination.gbDVD->setVisible(_state); if (_state) { Ui_astDestination.rbAvi->setChecked(false); Ui_astDestination.rbMpeg->setChecked(false); Ui_astDestination.rbAudio->setChecked(false); } m_parent->setDestination(dstDVD); } void k9astDestination::rbAviToggled(bool _state) { Ui_astDestination.urAvi->setVisible(_state); if (_state) { Ui_astDestination.rbDVD->setChecked(false); Ui_astDestination.rbMpeg->setChecked(false); Ui_astDestination.rbAudio->setChecked(false); } m_parent->setDestination(dstAvi); } void k9astDestination::rbMpegToggled(bool _state) { Ui_astDestination.urMpeg->setVisible(_state); if (_state) { Ui_astDestination.rbDVD->setChecked(false); Ui_astDestination.rbAvi->setChecked(false); Ui_astDestination.rbAudio->setChecked(false); } m_parent->setDestination(dstMpeg); } void k9astDestination::rbAudioToggled(bool _state) { Ui_astDestination.urAudio->setVisible(_state); if (_state) { Ui_astDestination.rbDVD->setChecked(false); Ui_astDestination.rbAvi->setChecked(false); Ui_astDestination.rbMpeg->setChecked(false); } m_parent->setDestination(dstAudio); } void k9astDestination::updategbDVD() { Ui_astDestination.cbDrives->setVisible(Ui_astDestination.rbDVDDisc->isChecked()); Ui_astDestination.urFolder->setVisible(Ui_astDestination.rbDVDFolder->isChecked()); Ui_astDestination.urIso->setVisible(Ui_astDestination.rbDVDIso->isChecked()); } void k9astDestination::rbDVDDiscToggled(bool _state) { updategbDVD(); if (_state) { m_parent->setDVDdestination(dstDVD); } } void k9astDestination::rbDVDFolderToggled(bool _state) { updategbDVD(); if (_state) { m_parent->setDVDdestination(dstFolder); } } void k9astDestination::rbDVDIsoToggled(bool _state) { updategbDVD(); if (_state) { m_parent->setDVDdestination(dstIso); } } const QString & k9astDestination::getPath() { m_path=""; if (Ui_astDestination.rbDVD->isChecked()) { if (Ui_astDestination.rbDVDIso->isChecked()) m_path=Ui_astDestination.urIso->url().toLocalFile() ; if (Ui_astDestination.rbDVDFolder->isChecked()) m_path=Ui_astDestination.urFolder->url().path(); if (Ui_astDestination.rbDVDDisc->isChecked()) m_path=Ui_astDestination.cbDrives->itemData(Ui_astDestination.cbDrives->currentIndex()).toString(); }else if (Ui_astDestination.rbMpeg->isChecked()) m_path=Ui_astDestination.urMpeg->url().path(); else if (Ui_astDestination.rbAvi->isChecked()) m_path=Ui_astDestination.urAvi->url().path(); else if (Ui_astDestination.rbAudio->isChecked()) m_path=Ui_astDestination.urAudio->url().path(); return m_path; } bool k9astDestination::isOk() { return getPath() !=""; } void k9astDestination::deviceRemoved(k9CdDrive *) { } bool k9astDestination::isMatroska() { return getPath().endsWith(".mkv"); } k9astDestination::~k9astDestination() { } /*$SPECIALIZATION$*/ k9copy/src/libdvdnav-NOW/0000775000175000017550000000000012412277736015761 5ustar emulatoremulatork9copy/src/libdvdnav-NOW/dvdnav_internal.h0000644000175000017550000001565212412277736021317 0ustar emulatoremulator/* * Copyright (C) 2001-2004 Rich Wareham * * This file is part of libdvdnav, a DVD navigation library. * * libdvdnav is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdnav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdnav; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef LIBDVDNAV_DVDNAV_INTERNAL_H #define LIBDVDNAV_DVDNAV_INTERNAL_H #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef WIN32 /* pthread_mutex_* wrapper for win32 */ #include #include typedef CRITICAL_SECTION pthread_mutex_t; #define pthread_mutex_init(a, b) InitializeCriticalSection(a) #define pthread_mutex_lock(a) EnterCriticalSection(a) #define pthread_mutex_unlock(a) LeaveCriticalSection(a) #define pthread_mutex_destroy(a) DeleteCriticalSection(a) #ifndef HAVE_GETTIMEOFDAY /* replacement gettimeofday implementation */ #include static inline int _private_gettimeofday( struct timeval *tv, void *tz ) { struct timeb t; ftime( &t ); tv->tv_sec = t.time; tv->tv_usec = t.millitm * 1000; return 0; } #define gettimeofday(TV, TZ) _private_gettimeofday((TV), (TZ)) #endif #include /* read() */ #define lseek64 _lseeki64 #else #include #endif /* WIN32 */ #ifdef __ANDROID__ # undef lseek # define lseek lseek64 # undef off_t # define off_t off64_t #endif /* where should libdvdnav write its messages (stdout/stderr) */ #define MSG_OUT stderr /* Maximum length of an error string */ #define MAX_ERR_LEN 255 #ifndef DVD_VIDEO_LB_LEN #define DVD_VIDEO_LB_LEN 2048 #endif typedef enum { DSI_ILVU_PRE = 1 << 15, /* set during the last 3 VOBU preceeding an interleaved block. */ DSI_ILVU_BLOCK = 1 << 14, /* set for all VOBU in an interleaved block */ DSI_ILVU_FIRST = 1 << 13, /* set for the first VOBU for a given angle or scene within a ILVU, or the first VOBU in the preparation (PREU) sequence */ DSI_ILVU_LAST = 1 << 12, /* set for the last VOBU for a given angle or scene within a ILVU, or the last VOBU in the preparation (PREU) sequence */ DSI_ILVU_MASK = 0xf000 } DSI_ILVU; typedef struct read_cache_s read_cache_t; /* * These are defined here because they are * not in ifo_types.h, they maybe one day */ #ifndef audio_status_t typedef struct { #ifdef WORDS_BIGENDIAN unsigned int available : 1; unsigned int zero1 : 4; unsigned int stream_number : 3; uint8_t zero2; #else uint8_t zero2; unsigned int stream_number : 3; unsigned int zero1 : 4; unsigned int available : 1; #endif } ATTRIBUTE_PACKED audio_status_t; #endif #ifndef spu_status_t typedef struct { #ifdef WORDS_BIGENDIAN unsigned int available : 1; unsigned int zero1 : 2; unsigned int stream_number_4_3 : 5; unsigned int zero2 : 3; unsigned int stream_number_wide : 5; unsigned int zero3 : 3; unsigned int stream_number_letterbox : 5; unsigned int zero4 : 3; unsigned int stream_number_pan_scan : 5; #else unsigned int stream_number_pan_scan : 5; unsigned int zero4 : 3; unsigned int stream_number_letterbox : 5; unsigned int zero3 : 3; unsigned int stream_number_wide : 5; unsigned int zero2 : 3; unsigned int stream_number_4_3 : 5; unsigned int zero1 : 2; unsigned int available : 1; #endif } ATTRIBUTE_PACKED spu_status_t; #endif /* * Describes a given time, and the closest sector, vobu and tmap index */ typedef struct { uint64_t time; uint32_t sector; uint32_t vobu_idx; int32_t tmap_idx; } dvdnav_pos_data_t; /* * Encapsulates cell data */ typedef struct { int32_t idx; dvdnav_pos_data_t *bgn; dvdnav_pos_data_t *end; } dvdnav_cell_data_t; /* * Encapsulates common variables used by internal functions of jump_to_time */ typedef struct { vobu_admap_t *admap; int32_t admap_len; vts_tmap_t *tmap; int32_t tmap_len; int32_t tmap_interval; } dvdnav_jump_args_t; /* * Utility constants for jump_to_time */ #define TMAP_IDX_EDGE_BGN -1 #define TMAP_IDX_EDGE_END -2 #define JUMP_MODE_TIME_AFTER 1 #define JUMP_MODE_TIME_DEFAULT 0 #define JUMP_MODE_TIME_BEFORE -1 typedef struct dvdnav_vobu_s { int32_t vobu_start; /* Logical Absolute. MAX needed is 0x300000 */ int32_t vobu_length; int32_t blockN; /* Relative offset */ int32_t vobu_next; /* Relative offset */ } dvdnav_vobu_t; /** The main DVDNAV type **/ struct dvdnav_s { /* General data */ char *path; /* Path to DVD device/dir */ dvd_file_t *file; /* Currently opened file */ /* Position data */ vm_position_t position_next; vm_position_t position_current; dvdnav_vobu_t vobu; /* NAV data */ pci_t pci; dsi_t dsi; uint32_t last_cmd_nav_lbn; /* detects when a command is issued on an already left NAV */ /* Flags */ int skip_still; /* Set when skipping a still */ int sync_wait; /* applications should wait till they are in sync with us */ int sync_wait_skip; /* Set when skipping wait state */ int spu_clut_changed; /* The SPU CLUT changed */ int started; /* vm_start has been called? */ int use_read_ahead; /* 1 - use read-ahead cache, 0 - don't */ int pgc_based; /* positioning works PGC based instead of PG based */ int cur_cell_time; /* time expired since the beginning of the current cell, read from the dsi */ /* VM */ vm_t *vm; pthread_mutex_t vm_lock; /* Read-ahead cache */ read_cache_t *cache; /* Errors */ char err_str[MAX_ERR_LEN]; }; /** HELPER FUNCTIONS **/ /* converts a dvd_time_t to PTS ticks */ int64_t dvdnav_convert_time(dvd_time_t *time); /** USEFUL MACROS **/ #ifdef __GNUC__ #define printerrf(format, args...) \ do { if (this) snprintf(this->err_str, MAX_ERR_LEN, format, ## args); } while (0) #else #ifdef _MSC_VER #define printerrf(str) \ do { if (this) snprintf(this->err_str, MAX_ERR_LEN, str); } while (0) #else #define printerrf(...) \ do { if (this) snprintf(this->err_str, MAX_ERR_LEN, __VA_ARGS__); } while (0) #endif /* WIN32 */ #endif #define printerr(str) \ do { if (this) strncpy(this->err_str, str, MAX_ERR_LEN - 1); } while (0) #endif /* LIBDVDNAV_DVDNAV_INTERNAL_H */ k9copy/src/libdvdnav-NOW/read_cache.h0000644000175000017550000000357012412277736020173 0ustar emulatoremulator/* * Copyright (C) 2000 Rich Wareham * * This file is part of libdvdnav, a DVD navigation library. * * libdvdnav is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdnav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdnav; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef LIBDVDNAV_READ_CACHE_H #define LIBDVDNAV_READ_CACHE_H /* Opaque cache type -- defined in dvdnav_internal.h */ /* typedef struct read_cache_s read_cache_t; */ /* EXPERIMENTAL: Setting the following to 1 will use an experimental multi-threaded * read-ahead cache. */ #define _MULTITHREAD_ 0 /* Constructor/destructors */ read_cache_t *dvdnav_read_cache_new(dvdnav_t* dvd_self); void dvdnav_read_cache_free(read_cache_t* self); /* This function MUST be called whenever self->file changes. */ void dvdnav_read_cache_clear(read_cache_t *self); /* This function is called just after reading the NAV packet. */ void dvdnav_pre_cache_blocks(read_cache_t *self, int sector, size_t block_count); /* This function will do the cache read. * The buffer handed in must be malloced to take one dvd block. * On a cache hit, a different buffer will be returned though. * Those buffers must _never_ be freed. */ int dvdnav_read_cache_block(read_cache_t *self, int sector, size_t block_count, uint8_t **buf); #endif /* LIBDVDNAV_READ_CACHE_H */ k9copy/src/libdvdnav-NOW/navigation.c0000644000175000017550000002010012412277736020253 0ustar emulatoremulator/* * Copyright (C) 2000 Rich Wareham * * This file is part of libdvdnav, a DVD navigation library. * * libdvdnav is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdnav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdnav; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "dvdnav/dvdnav.h" #include #include #include "vm/decoder.h" #include "vm/vm.h" #include "dvdnav_internal.h" /* Navigation API calls */ dvdnav_status_t dvdnav_still_skip(dvdnav_t *this) { pthread_mutex_lock(&this->vm_lock); this->position_current.still = 0; pthread_mutex_unlock(&this->vm_lock); this->skip_still = 1; this->sync_wait = 0; this->sync_wait_skip = 1; return DVDNAV_STATUS_OK; } dvdnav_status_t dvdnav_wait_skip(dvdnav_t *this) { this->sync_wait = 0; this->sync_wait_skip = 1; return DVDNAV_STATUS_OK; } dvdnav_status_t dvdnav_get_number_of_titles(dvdnav_t *this, int32_t *titles) { if (!this->vm->vmgi) { printerr("Bad VM state."); return DVDNAV_STATUS_ERR; } (*titles) = vm_get_vmgi(this->vm)->tt_srpt->nr_of_srpts; return DVDNAV_STATUS_OK; } dvdnav_status_t dvdnav_get_number_of_parts(dvdnav_t *this, int32_t title, int32_t *parts) { if (!this->vm->vmgi) { printerr("Bad VM state."); return DVDNAV_STATUS_ERR; } if ((title < 1) || (title > vm_get_vmgi(this->vm)->tt_srpt->nr_of_srpts) ) { printerr("Passed a title number out of range."); return DVDNAV_STATUS_ERR; } (*parts) = vm_get_vmgi(this->vm)->tt_srpt->title[title-1].nr_of_ptts; return DVDNAV_STATUS_OK; } dvdnav_status_t dvdnav_current_title_info(dvdnav_t *this, int32_t *title, int32_t *part) { int32_t retval; pthread_mutex_lock(&this->vm_lock); if (!this->vm->vtsi || !this->vm->vmgi) { printerr("Bad VM state."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } if (!this->started) { printerr("Virtual DVD machine not started."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } if (!this->vm->state.pgc) { printerr("No current PGC."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } if ( (this->vm->state.domain == DVD_DOMAIN_VTSMenu) || (this->vm->state.domain == DVD_DOMAIN_VMGM) ) { /* Get current Menu ID: into *part. */ if(! vm_get_current_menu(this->vm, part)) { pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } if (*part > -1) { *title = 0; pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } } if (this->vm->state.domain == DVD_DOMAIN_VTSTitle) { retval = vm_get_current_title_part(this->vm, title, part); pthread_mutex_unlock(&this->vm_lock); return retval ? DVDNAV_STATUS_OK : DVDNAV_STATUS_ERR; } printerr("Not in a title or menu."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } dvdnav_status_t dvdnav_current_title_program(dvdnav_t *this, int32_t *title, int32_t *pgcn, int32_t *pgn) { int32_t retval; int32_t part; pthread_mutex_lock(&this->vm_lock); if (!this->vm->vtsi || !this->vm->vmgi) { printerr("Bad VM state."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } if (!this->started) { printerr("Virtual DVD machine not started."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } if (!this->vm->state.pgc) { printerr("No current PGC."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } if ( (this->vm->state.domain == DVD_DOMAIN_VTSMenu) || (this->vm->state.domain == DVD_DOMAIN_VMGM) ) { /* Get current Menu ID: into *part. */ if(! vm_get_current_menu(this->vm, &part)) { pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } if (part > -1) { *title = 0; *pgcn = this->vm->state.pgcN; *pgn = this->vm->state.pgN; pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } } if (this->vm->state.domain == DVD_DOMAIN_VTSTitle) { retval = vm_get_current_title_part(this->vm, title, &part); *pgcn = this->vm->state.pgcN; *pgn = this->vm->state.pgN; pthread_mutex_unlock(&this->vm_lock); return retval ? DVDNAV_STATUS_OK : DVDNAV_STATUS_ERR; } printerr("Not in a title or menu."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } dvdnav_status_t dvdnav_title_play(dvdnav_t *this, int32_t title) { return dvdnav_part_play(this, title, 1); } dvdnav_status_t dvdnav_program_play(dvdnav_t *this, int32_t title, int32_t pgcn, int32_t pgn) { int32_t retval; pthread_mutex_lock(&this->vm_lock); if (!this->vm->vmgi) { printerr("Bad VM state."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } if (!this->started) { /* don't report an error but be nice */ vm_start(this->vm); this->started = 1; } if (!this->vm->state.pgc) { printerr("No current PGC."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } if((title < 1) || (title > this->vm->vmgi->tt_srpt->nr_of_srpts)) { printerr("Title out of range."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } retval = vm_jump_title_program(this->vm, title, pgcn, pgn); if (retval) this->vm->hop_channel++; pthread_mutex_unlock(&this->vm_lock); return retval ? DVDNAV_STATUS_OK : DVDNAV_STATUS_ERR; } dvdnav_status_t dvdnav_part_play(dvdnav_t *this, int32_t title, int32_t part) { int32_t retval; pthread_mutex_lock(&this->vm_lock); if (!this->vm->vmgi) { printerr("Bad VM state."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } if (!this->started) { /* don't report an error but be nice */ vm_start(this->vm); this->started = 1; } if (!this->vm->state.pgc) { printerr("No current PGC."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } if((title < 1) || (title > this->vm->vmgi->tt_srpt->nr_of_srpts)) { printerr("Title out of range."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } if((part < 1) || (part > this->vm->vmgi->tt_srpt->title[title-1].nr_of_ptts)) { printerr("Part out of range."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } retval = vm_jump_title_part(this->vm, title, part); if (retval) this->vm->hop_channel++; pthread_mutex_unlock(&this->vm_lock); return retval ? DVDNAV_STATUS_OK : DVDNAV_STATUS_ERR; } dvdnav_status_t dvdnav_part_play_auto_stop(dvdnav_t *this, int32_t title, int32_t part, int32_t parts_to_play) { /* FIXME: Implement auto-stop */ if (dvdnav_part_play(this, title, part) == DVDNAV_STATUS_OK) printerr("Not implemented yet."); return DVDNAV_STATUS_ERR; } dvdnav_status_t dvdnav_time_play(dvdnav_t *this, int32_t title, uint64_t time) { /* FIXME: Implement */ printerr("Not implemented yet."); return DVDNAV_STATUS_ERR; } dvdnav_status_t dvdnav_stop(dvdnav_t *this) { pthread_mutex_lock(&this->vm_lock); this->vm->stopped = 1; pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } dvdnav_status_t dvdnav_go_up(dvdnav_t *this) { /* A nice easy function... delegate to the VM */ int retval; pthread_mutex_lock(&this->vm_lock); retval = vm_jump_up(this->vm); pthread_mutex_unlock(&this->vm_lock); return retval ? DVDNAV_STATUS_OK : DVDNAV_STATUS_ERR; } k9copy/src/libdvdnav-NOW/searching.c0000644000175000017550000011426112412277736020073 0ustar emulatoremulator/* * Copyright (C) 2000 Rich Wareham * * This file is part of libdvdnav, a DVD navigation library. * * libdvdnav is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdnav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdnav; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include "dvdnav/dvdnav.h" #include #include #include "vm/decoder.h" #include "vm/vm.h" #include "dvdnav_internal.h" #include /* #define LOG_DEBUG */ /* Searching API calls */ /* Scan the ADMAP for a particular block number. */ /* Return placed in vobu. */ /* Returns error status */ /* FIXME: Maybe need to handle seeking outside current cell. */ static dvdnav_status_t dvdnav_scan_admap(dvdnav_t *this, int32_t domain, uint32_t seekto_block, int next, uint32_t *vobu) { vobu_admap_t *admap = NULL; #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: Seeking to target %u ...\n", seekto_block); #endif *vobu = -1; /* Search through the VOBU_ADMAP for the nearest VOBU * to the target block */ switch(domain) { case DVD_DOMAIN_FirstPlay: case DVD_DOMAIN_VMGM: admap = this->vm->vmgi->menu_vobu_admap; break; case DVD_DOMAIN_VTSMenu: admap = this->vm->vtsi->menu_vobu_admap; break; case DVD_DOMAIN_VTSTitle: admap = this->vm->vtsi->vts_vobu_admap; break; default: fprintf(MSG_OUT, "libdvdnav: Error: Unknown domain for seeking.\n"); } if(admap) { uint32_t address = 0; uint32_t vobu_start, next_vobu = 0; int admap_entries = (admap->last_byte + 1 - VOBU_ADMAP_SIZE)/VOBU_ADMAP_SIZE; /* Search through ADMAP for best sector */ vobu_start = SRI_END_OF_CELL; /* FIXME: Implement a faster search algorithm */ while(address < admap_entries) { next_vobu = admap->vobu_start_sectors[address]; /* fprintf(MSG_OUT, "libdvdnav: Found block %u\n", next_vobu); */ if(vobu_start <= seekto_block && next_vobu > seekto_block) break; vobu_start = next_vobu; address++; } *vobu = next ? next_vobu : vobu_start; return DVDNAV_STATUS_OK; } fprintf(MSG_OUT, "libdvdnav: admap not located\n"); return DVDNAV_STATUS_ERR; } /* FIXME: right now, this function does not use the time tables but interpolates only the cell times */ dvdnav_status_t dvdnav_time_search(dvdnav_t *this, uint64_t time) { uint64_t target = time; uint64_t length = 0; uint32_t first_cell_nr, last_cell_nr, cell_nr; int32_t found; cell_playback_t *cell; dvd_state_t *state; if(this->position_current.still != 0) { printerr("Cannot seek in a still frame."); return DVDNAV_STATUS_ERR; } pthread_mutex_lock(&this->vm_lock); state = &(this->vm->state); if(!state->pgc) { printerr("No current PGC."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } this->cur_cell_time = 0; if (this->pgc_based) { first_cell_nr = 1; last_cell_nr = state->pgc->nr_of_cells; } else { /* Find start cell of program. */ first_cell_nr = state->pgc->program_map[state->pgN-1]; /* Find end cell of program */ if(state->pgN < state->pgc->nr_of_programs) last_cell_nr = state->pgc->program_map[state->pgN] - 1; else last_cell_nr = state->pgc->nr_of_cells; } found = 0; for(cell_nr = first_cell_nr; (cell_nr <= last_cell_nr) && !found; cell_nr ++) { cell = &(state->pgc->cell_playback[cell_nr-1]); if(cell->block_type == BLOCK_TYPE_ANGLE_BLOCK && cell->block_mode != BLOCK_MODE_FIRST_CELL) continue; length = dvdnav_convert_time(&cell->playback_time); if (target >= length) { target -= length; } else { /* FIXME: there must be a better way than interpolation */ target = target * (cell->last_sector - cell->first_sector + 1) / length; target += cell->first_sector; found = 1; break; } } if(found) { uint32_t vobu; #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: Seeking to cell %i from choice of %i to %i\n", cell_nr, first_cell_nr, last_cell_nr); #endif if (dvdnav_scan_admap(this, state->domain, target, 0, &vobu) == DVDNAV_STATUS_OK) { uint32_t start = state->pgc->cell_playback[cell_nr-1].first_sector; if (vm_jump_cell_block(this->vm, cell_nr, vobu - start)) { #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: After cellN=%u blockN=%u target=%x vobu=%x start=%x\n" , state->cellN, state->blockN, target, vobu, start); #endif this->vm->hop_channel += HOP_SEEK; pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } } } fprintf(MSG_OUT, "libdvdnav: Error when seeking\n"); printerr("Error when seeking."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } dvdnav_status_t dvdnav_sector_search(dvdnav_t *this, int64_t offset, int32_t origin) { uint32_t target = 0; uint32_t current_pos; uint32_t cur_sector; uint32_t cur_cell_nr; uint32_t length = 0; uint32_t first_cell_nr, last_cell_nr, cell_nr; int32_t found; int forward = 0; cell_playback_t *cell; dvd_state_t *state; dvdnav_status_t result; if(this->position_current.still != 0) { printerr("Cannot seek in a still frame."); return DVDNAV_STATUS_ERR; } result = dvdnav_get_position(this, &target, &length); if(!result) { return DVDNAV_STATUS_ERR; } pthread_mutex_lock(&this->vm_lock); state = &(this->vm->state); if(!state->pgc) { printerr("No current PGC."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: seeking to offset=%lld pos=%u length=%u\n", offset, target, length); fprintf(MSG_OUT, "libdvdnav: Before cellN=%u blockN=%u\n", state->cellN, state->blockN); #endif current_pos = target; cur_sector = this->vobu.vobu_start + this->vobu.blockN; cur_cell_nr = state->cellN; switch(origin) { case SEEK_SET: if(offset >= length) { printerr("Request to seek behind end."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } target = offset; break; case SEEK_CUR: if((signed)target + offset >= length) { printerr("Request to seek behind end."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } if((signed)target + offset < 0) { printerr("Request to seek before start."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } target += offset; break; case SEEK_END: if(length < offset) { printerr("Request to seek before start."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } target = length - offset; break; default: /* Error occured */ printerr("Illegal seek mode."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } forward = target > current_pos; this->cur_cell_time = 0; if (this->pgc_based) { first_cell_nr = 1; last_cell_nr = state->pgc->nr_of_cells; } else { /* Find start cell of program. */ first_cell_nr = state->pgc->program_map[state->pgN-1]; /* Find end cell of program */ if(state->pgN < state->pgc->nr_of_programs) last_cell_nr = state->pgc->program_map[state->pgN] - 1; else last_cell_nr = state->pgc->nr_of_cells; } found = 0; for(cell_nr = first_cell_nr; (cell_nr <= last_cell_nr) && !found; cell_nr ++) { cell = &(state->pgc->cell_playback[cell_nr-1]); if(cell->block_type == BLOCK_TYPE_ANGLE_BLOCK && cell->block_mode != BLOCK_MODE_FIRST_CELL) continue; length = cell->last_sector - cell->first_sector + 1; if (target >= length) { target -= length; } else { /* convert the target sector from Cell-relative to absolute physical sector */ target += cell->first_sector; if (forward && (cell_nr == cur_cell_nr)) { uint32_t vobu; /* if we are seeking forward from the current position, make sure * we move to a new position that is after our current position. * simply truncating to the vobu will go backwards */ if (dvdnav_scan_admap(this, state->domain, target, 0, &vobu) != DVDNAV_STATUS_OK) break; if (vobu <= cur_sector) { if (dvdnav_scan_admap(this, state->domain, target, 1, &vobu) != DVDNAV_STATUS_OK) break; if (vobu > cell->last_sector) { if (cell_nr == last_cell_nr) break; cell_nr++; cell = &(state->pgc->cell_playback[cell_nr-1]); target = cell->first_sector; } else { target = vobu; } } } found = 1; break; } } if(found) { uint32_t vobu; #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: Seeking to cell %i from choice of %i to %i\n", cell_nr, first_cell_nr, last_cell_nr); #endif if (dvdnav_scan_admap(this, state->domain, target, 0, &vobu) == DVDNAV_STATUS_OK) { int32_t start = state->pgc->cell_playback[cell_nr-1].first_sector; if (vm_jump_cell_block(this->vm, cell_nr, vobu - start)) { #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: After cellN=%u blockN=%u target=%x vobu=%x start=%x\n" , state->cellN, state->blockN, target, vobu, start); #endif this->vm->hop_channel += HOP_SEEK; pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } } } fprintf(MSG_OUT, "libdvdnav: Error when seeking\n"); fprintf(MSG_OUT, "libdvdnav: FIXME: Implement seeking to location %u\n", target); printerr("Error when seeking."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } dvdnav_status_t dvdnav_part_search(dvdnav_t *this, int32_t part) { int32_t title, old_part; if (dvdnav_current_title_info(this, &title, &old_part) == DVDNAV_STATUS_OK) return dvdnav_part_play(this, title, part); return DVDNAV_STATUS_ERR; } dvdnav_status_t dvdnav_prev_pg_search(dvdnav_t *this) { pthread_mutex_lock(&this->vm_lock); if(!this->vm->state.pgc) { printerr("No current PGC."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: previous chapter\n"); #endif if (!vm_jump_prev_pg(this->vm)) { fprintf(MSG_OUT, "libdvdnav: previous chapter failed.\n"); printerr("Skip to previous chapter failed."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } this->cur_cell_time = 0; this->position_current.still = 0; this->vm->hop_channel++; #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: previous chapter done\n"); #endif pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } dvdnav_status_t dvdnav_top_pg_search(dvdnav_t *this) { pthread_mutex_lock(&this->vm_lock); if(!this->vm->state.pgc) { printerr("No current PGC."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: top chapter\n"); #endif if (!vm_jump_top_pg(this->vm)) { fprintf(MSG_OUT, "libdvdnav: top chapter failed.\n"); printerr("Skip to top chapter failed."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } this->cur_cell_time = 0; this->position_current.still = 0; this->vm->hop_channel++; #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: top chapter done\n"); #endif pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } dvdnav_status_t dvdnav_next_pg_search(dvdnav_t *this) { vm_t *try_vm; pthread_mutex_lock(&this->vm_lock); if(!this->vm->state.pgc) { printerr("No current PGC."); goto fail; } #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: next chapter\n"); #endif /* make a copy of current VM and try to navigate the copy to the next PG */ try_vm = vm_new_copy(this->vm); if (try_vm == NULL) { printerr("Unable to copy the VM."); goto fail; } if (!vm_jump_next_pg(try_vm) || try_vm->stopped) { vm_free_copy(try_vm); /* next_pg failed, try to jump at least to the next cell */ try_vm = vm_new_copy(this->vm); if (try_vm == NULL) { printerr("Unable to copy the VM."); goto fail; } vm_get_next_cell(try_vm); if (try_vm->stopped) { vm_free_copy(try_vm); fprintf(MSG_OUT, "libdvdnav: next chapter failed.\n"); printerr("Skip to next chapter failed."); goto fail; } } this->cur_cell_time = 0; /* merge changes on success */ vm_merge(this->vm, try_vm); vm_free_copy(try_vm); this->position_current.still = 0; this->vm->hop_channel++; #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: next chapter done\n"); #endif pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; fail: pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } dvdnav_status_t dvdnav_menu_call(dvdnav_t *this, DVDMenuID_t menu) { vm_t *try_vm; pthread_mutex_lock(&this->vm_lock); if(!this->vm->state.pgc) { printerr("No current PGC."); goto fail; } this->cur_cell_time = 0; /* make a copy of current VM and try to navigate the copy to the menu */ try_vm = vm_new_copy(this->vm); if (try_vm == NULL) { printerr("Unable to copy VM."); goto fail; } if ( (menu == DVD_MENU_Escape) && (this->vm->state.domain != DVD_DOMAIN_VTSTitle)) { /* Try resume */ if (vm_jump_resume(try_vm) && !try_vm->stopped) { /* merge changes on success */ vm_merge(this->vm, try_vm); vm_free_copy(try_vm); this->position_current.still = 0; this->vm->hop_channel++; pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } } if (menu == DVD_MENU_Escape) menu = DVD_MENU_Root; if (vm_jump_menu(try_vm, menu) && !try_vm->stopped) { /* merge changes on success */ vm_merge(this->vm, try_vm); vm_free_copy(try_vm); this->position_current.still = 0; this->vm->hop_channel++; pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } else { vm_free_copy(try_vm); printerr("No such menu or menu not reachable."); goto fail; } fail: pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } dvdnav_status_t dvdnav_get_position(dvdnav_t *this, uint32_t *pos, uint32_t *len) { uint32_t cur_sector; int32_t cell_nr, first_cell_nr, last_cell_nr; cell_playback_t *cell; dvd_state_t *state; if(!this->started) { printerr("Virtual DVD machine not started."); return DVDNAV_STATUS_ERR; } pthread_mutex_lock(&this->vm_lock); state = &(this->vm->state); if(!state->pgc || this->vm->stopped) { printerr("No current PGC."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } if (this->position_current.hop_channel != this->vm->hop_channel || this->position_current.domain != state->domain || this->position_current.vts != state->vtsN || this->position_current.cell_restart != state->cell_restart) { printerr("New position not yet determined."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } /* Get current sector */ cur_sector = this->vobu.vobu_start + this->vobu.blockN; if (this->pgc_based) { first_cell_nr = 1; last_cell_nr = state->pgc->nr_of_cells; } else { /* Find start cell of program. */ first_cell_nr = state->pgc->program_map[state->pgN-1]; /* Find end cell of program */ if(state->pgN < state->pgc->nr_of_programs) last_cell_nr = state->pgc->program_map[state->pgN] - 1; else last_cell_nr = state->pgc->nr_of_cells; } *pos = -1; *len = 0; for (cell_nr = first_cell_nr; cell_nr <= last_cell_nr; cell_nr++) { cell = &(state->pgc->cell_playback[cell_nr-1]); if(cell->block_type == BLOCK_TYPE_ANGLE_BLOCK && cell->block_mode != BLOCK_MODE_FIRST_CELL) continue; if (cell_nr == state->cellN) { /* the current sector is in this cell, * pos is length of PG up to here + sector's offset in this cell */ *pos = *len + cur_sector - cell->first_sector; } *len += cell->last_sector - cell->first_sector + 1; } assert((signed)*pos != -1); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } dvdnav_status_t dvdnav_get_position_in_title(dvdnav_t *this, uint32_t *pos, uint32_t *len) { uint32_t cur_sector; uint32_t first_cell_nr; uint32_t last_cell_nr; cell_playback_t *first_cell; cell_playback_t *last_cell; dvd_state_t *state; state = &(this->vm->state); if(!state->pgc) { printerr("No current PGC."); return DVDNAV_STATUS_ERR; } /* Get current sector */ cur_sector = this->vobu.vobu_start + this->vobu.blockN; /* Now find first and last cells in title. */ first_cell_nr = state->pgc->program_map[0]; first_cell = &(state->pgc->cell_playback[first_cell_nr-1]); last_cell_nr = state->pgc->nr_of_cells; last_cell = &(state->pgc->cell_playback[last_cell_nr-1]); *pos = cur_sector - first_cell->first_sector; *len = last_cell->last_sector - first_cell->first_sector; return DVDNAV_STATUS_OK; } uint32_t dvdnav_describe_title_chapters(dvdnav_t *this, int32_t title, uint64_t **times, uint64_t *duration) { int32_t retval=0; uint16_t parts, i; title_info_t *ptitle = NULL; ptt_info_t *ptt = NULL; ifo_handle_t *ifo = NULL; pgc_t *pgc; cell_playback_t *cell; uint64_t length, *tmp=NULL; *times = NULL; *duration = 0; pthread_mutex_lock(&this->vm_lock); if(!this->vm->vmgi) { printerr("Bad VM state or missing VTSI."); goto fail; } if(!this->started) { /* don't report an error but be nice */ vm_start(this->vm); this->started = 1; } ifo = vm_get_title_ifo(this->vm, title); if(!ifo || !ifo->vts_pgcit) { printerr("Couldn't open IFO for chosen title, exit."); retval = 0; goto fail; } ptitle = &this->vm->vmgi->tt_srpt->title[title-1]; parts = ptitle->nr_of_ptts; ptt = ifo->vts_ptt_srpt->title[ptitle->vts_ttn-1].ptt; tmp = calloc(1, sizeof(uint64_t)*parts); if(!tmp) goto fail; length = 0; for(i=0; i ifo->vts_pgcit->nr_of_pgci_srp) { printerr("PGCN out of bounds."); continue; } if (ifo->vts_pgcit->pgci_srp[ptt[i].pgcn-1].pgc_start_byte >= ifo->vts_pgcit->last_byte) { printerr("PGC start out of bounds"); continue; } if (0 == ifo->vts_pgcit->pgci_srp[ptt[i].pgcn-1].pgc_start_byte) { printerr("PGC start zero."); continue; } if (0 != (ifo->vts_pgcit->pgci_srp[ptt[i].pgcn-1].pgc_start_byte & 1)) { printerr("PGC start unaligned."); continue; } if (0 != ((uintptr_t)(ifo->vts_pgcit->pgci_srp[ptt[i].pgcn-1].pgc) & 1)) { printerr("PGC pointer unaligned."); continue; } pgc = ifo->vts_pgcit->pgci_srp[ptt[i].pgcn-1].pgc; if (pgc == NULL) { printerr("PGC missing."); continue; } if (pgc->program_map == NULL) { printerr("Program map missing."); continue; } if(ptt[i].pgn == 0 || ptt[i].pgn > pgc->nr_of_programs) { printerr("WRONG part number."); goto fail; } if (pgc->nr_of_cells == 0) { printerr("Number of cells cannot be 0"); continue; } if ((cellnr = pgc->program_map[ptt[i].pgn-1]) == 0) { printerr("Cell new row cannot be 0"); continue; } if (pgc->cell_playback == NULL) { printerr("Cell missing"); continue; } if(ptt[i].pgn < pgc->nr_of_programs) endcellnr = pgc->program_map[ptt[i].pgn]; else endcellnr = 0; do { cell = &pgc->cell_playback[cellnr-1]; if(!(cell->block_type == BLOCK_TYPE_ANGLE_BLOCK && cell->block_mode != BLOCK_MODE_FIRST_CELL )) { tmp[i] = length + dvdnav_convert_time(&cell->playback_time); length = tmp[i]; } cellnr++; } while(cellnr < endcellnr); } *duration = length; vm_ifo_close(ifo); ifo = NULL; retval = parts; *times = tmp; fail: pthread_mutex_unlock(&this->vm_lock); if(!retval && ifo) vm_ifo_close(ifo); if(!retval && tmp) free(tmp); return retval; } /* Get an admap and admap_len */ static vobu_admap_t* dvdnav_admap_get(dvdnav_t *this, dvd_state_t *state, int32_t *admap_len) { vobu_admap_t *admap = NULL; switch(state->domain) { case DVD_DOMAIN_FirstPlay: case DVD_DOMAIN_VMGM: admap = this->vm->vmgi->menu_vobu_admap; break; case DVD_DOMAIN_VTSMenu: admap = this->vm->vtsi->menu_vobu_admap; break; case DVD_DOMAIN_VTSTitle: admap = this->vm->vtsi->vts_vobu_admap; break; default: { fprintf(MSG_OUT, "Unknown domain"); return NULL; } } if (admap == NULL) return NULL; *admap_len = (admap->last_byte + 1 - VOBU_ADMAP_SIZE) / VOBU_ADMAP_SIZE; if (*admap_len <= 0) { fprintf(MSG_OUT, "admap_len <= 0"); return NULL; } return admap; } /* Get a tmap, tmap_len and tmap_interval */ static vts_tmap_t* dvdnav_tmap_get(dvdnav_t *this, dvd_state_t *state, int32_t *tmap_len, int32_t *tmap_interval) { int32_t vts_idx = 0; int32_t domain; ifo_handle_t *ifo = NULL; vts_tmapt_t *tmapt = NULL; uint16_t tmap_count = 0; int32_t pgcN = 0; vts_tmap_t *tmap = NULL; int32_t result = 0; vts_idx = state->vtsN; domain = state->domain; switch(domain) { case DVD_DOMAIN_FirstPlay: case DVD_DOMAIN_VTSMenu: case DVD_DOMAIN_VMGM: { ifo = this->vm->vmgi; break; } case DVD_DOMAIN_VTSTitle: { ifo = this->vm->vtsi; break; } default: { fprintf(MSG_OUT, "unknown domain for tmap"); return NULL; } } if (ifo == NULL) return NULL; tmapt = ifo->vts_tmapt; /* HACK: ifo->vts_tmapt is NULL b/c ifo_read.c never loads it * load ifo->vts_tmapt directly*/ if (tmapt == NULL) { result = ifoRead_VTS_TMAPT(ifo); if (!result) { return NULL; } tmapt = ifo->vts_tmapt; if (tmapt == NULL) return NULL; } tmap_count = tmapt->nr_of_tmaps; pgcN = state->pgcN - 1; /* -1 b/c pgcN is base1 */ if (pgcN < 0) { fprintf(MSG_OUT, "pgcN < 0"); return NULL; } /* get tmap */ switch(domain) { case DVD_DOMAIN_FirstPlay: case DVD_DOMAIN_VMGM: case DVD_DOMAIN_VTSMenu: { if (tmap_count == 0) { fprintf(MSG_OUT, "tmap_count == 0"); return NULL; } tmap = &tmapt->tmap[0]; /* ASSUME: vmgi only has one time map */ break; } case DVD_DOMAIN_VTSTitle: { if (pgcN >= tmap_count) { fprintf(MSG_OUT, "pgcN >= tmap_count; pgcN=%i tmap_count=%i", pgcN, tmap_count); return NULL; } tmap = &tmapt->tmap[pgcN]; break; } } if (tmap == NULL) return NULL; /* tmap->tmu is in seconds; convert to millisecs */ *tmap_interval = tmap->tmu * 1000; if (*tmap_interval == 0) { fprintf(MSG_OUT, "tmap_interval == 0"); return NULL; } *tmap_len = tmap->nr_of_entries; if (*tmap_len == 0) { fprintf(MSG_OUT, "tmap_len == 0"); return NULL; } return tmap; } /* Get a sector from a tmap */ static int32_t dvdnav_tmap_get_entry(vts_tmap_t *tmap, uint16_t tmap_len, int32_t idx, uint32_t *sector) { /* tmaps start at idx 0 which represents a sector at time 1 * tmap_interval * this creates a "fake" tmap index at idx -1 for sector 0 */ if (idx == TMAP_IDX_EDGE_BGN) { *sector = 0; return 1; } if (idx < TMAP_IDX_EDGE_BGN || idx >= tmap_len) { fprintf(MSG_OUT, "idx out of bounds idx=%i %i", idx, tmap_len); return 0; } /* 0x7fffffff unsets discontinuity bit if present */ *sector = tmap->map_ent[idx] & 0x7fffffff; return 1; } /* Do a binary search for earlier admap index near find_sector */ static int32_t dvdnav_admap_search(vobu_admap_t *admap, uint32_t admap_len, uint32_t find_sector, uint32_t *vobu) { int32_t adj = 1; int32_t prv_pos = 0; int32_t prv_len = admap_len; int32_t cur_len = 0; int32_t cur_idx = 0; uint32_t cur_sector = 0; while (1) { cur_len = prv_len / 2; /* need to add 1 when prv_len == 3 (cur_len shoud go to 2, not 1) */ if (prv_len % 2 == 1) ++cur_len; cur_idx = prv_pos + (cur_len * adj); if (cur_idx < 0) cur_idx = 0; else if (cur_idx >= admap_len) cur_idx = admap_len - 1; cur_sector = admap->vobu_start_sectors[cur_idx]; if (find_sector < cur_sector) adj = -1; else if (find_sector > cur_sector) adj = 1; else if (find_sector == cur_sector) { *vobu = cur_idx; return 1; } if (cur_len == 1) {/* no smaller intervals left */ if (adj == -1) {/* last comparison was greater; take lesser */ cur_idx -= 1; cur_sector = admap->vobu_start_sectors[cur_idx]; } *vobu = cur_idx; return 1; } prv_len = cur_len; prv_pos = cur_idx; } } /* Do a binary search for the earlier tmap entry near find_sector */ static int32_t dvdnav_tmap_search(vts_tmap_t *tmap, uint32_t tmap_len, uint32_t find_sector, int32_t *tmap_idx, uint32_t *sector) { int32_t adj = 1; int32_t prv_pos = 0; int32_t prv_len = tmap_len; int32_t result = 0; int32_t cur_len = 0; int32_t cur_idx = 0; uint32_t cur_sector = 0; while (1) { cur_len = prv_len / 2; /* need to add 1 when prv_len == 3 (cur_len shoud go to 2, not 1) */ if (prv_len % 2 == 1) ++cur_len; cur_idx = prv_pos + (cur_len * adj); if (cur_idx < 0) cur_idx = 0; else if (cur_idx >= tmap_len) cur_idx = tmap_len - 1; cur_sector = 0; result = dvdnav_tmap_get_entry(tmap, tmap_len, cur_idx, &cur_sector); if (!result) return 0; if (find_sector < cur_sector) adj = -1; else if (find_sector > cur_sector) adj = 1; else if (find_sector == cur_sector) { *tmap_idx = cur_idx; *sector = cur_sector; return 1; } if (cur_len == 1) {/* no smaller intervals left */ if (adj == -1) {/* last comparison was greater; take lesser */ if (cur_idx == 0) { /* fake tmap index for sector 0 */ cur_idx = TMAP_IDX_EDGE_BGN; cur_sector = 0; } else { cur_idx -= 1; result = dvdnav_tmap_get_entry(tmap, tmap_len, cur_idx, &cur_sector); if (!result) return 0; } } *tmap_idx = cur_idx; *sector = cur_sector; return 1; } prv_len = cur_len; prv_pos = cur_idx; } } /* Find the cell for a given time */ static int32_t dvdnav_cell_find(dvdnav_t *this, dvd_state_t *state, uint64_t find_val, dvdnav_cell_data_t *cell_data) { uint32_t cells_len = 0; uint32_t cells_bgn = 0; uint32_t cells_end = 0; uint32_t cell_idx = 0; pgc_t *pgc = NULL; int pgN = 0; cell_playback_t *cell = NULL; int found = 0; pgc = state->pgc; if (pgc == NULL) return 0; cells_len = pgc->nr_of_cells; if (cells_len == 0) { fprintf(MSG_OUT, "cells_len == 0"); return 0; } /* get cells_bgn, cells_end */ if (this->pgc_based) { cells_bgn = 1; cells_end = cells_len; } else { pgN = state->pgN; cells_bgn = pgc->program_map[pgN - 1]; /* -1 b/c pgN is 1 based? */ if (pgN < pgc->nr_of_programs) { cells_end = pgc->program_map[pgN] - 1; } else { cells_end = cells_len; } } /* search cells */ for (cell_idx = cells_bgn; cell_idx <= cells_end; cell_idx++) { cell = &(pgc->cell_playback[cell_idx - 1]); /* -1 b/c cell is base1 */ /* if angle block, only consider first angleBlock * (others are "redundant" for purpose of search) */ if ( cell->block_type == BLOCK_TYPE_ANGLE_BLOCK && cell->block_mode != BLOCK_MODE_FIRST_CELL) { continue; } cell_data->bgn->sector = cell->first_sector; cell_data->end->sector = cell->last_sector; /* 90 pts to ms */ cell_data->end->time += (dvdnav_convert_time(&cell->playback_time) / 90); if ( find_val >= cell_data->bgn->time && find_val <= cell_data->end->time) { found = 1; break; } cell_data->bgn->time = cell_data->end->time; } /* found cell: set var */ if (found) { cell_data->idx = cell_idx; } else fprintf(MSG_OUT, "cell not found; find=%"PRId64"", find_val); return found; } /* Given two sectors and a fraction, calc the corresponding vobu */ static int32_t dvdnav_admap_interpolate_vobu(dvdnav_jump_args_t *args, dvdnav_pos_data_t *bgn, dvdnav_pos_data_t *end, uint32_t fraction, uint32_t *jump_sector) { int32_t result = 0; uint32_t vobu_len = 0; uint32_t vobu_adj = 0; uint32_t vobu_idx = 0; /* get bgn->vobu_idx */ result = dvdnav_admap_search(args->admap, args->admap_len, bgn->sector, &bgn->vobu_idx); if (!result) { fprintf(MSG_OUT, "admap_interpolate: could not find sector_bgn"); return 0; } /* get end->vobu_idx */ result = dvdnav_admap_search(args->admap, args->admap_len, end->sector, &end->vobu_idx); if (!result) { fprintf(MSG_OUT, "admap_interpolate: could not find sector_end"); return 0; } vobu_len = end->vobu_idx - bgn->vobu_idx; /* +500 to round up else 74% of a 4 sec interval = 2 sec */ vobu_adj = ((fraction * vobu_len) + 500) / 1000; /* HACK: need to add +1, or else will land too soon (not sure why) */ vobu_adj++; vobu_idx = bgn->vobu_idx + vobu_adj; if (vobu_idx >= args->admap_len) { fprintf(MSG_OUT, "admap_interpolate: vobu_idx >= admap_len"); return 0; } *jump_sector = args->admap->vobu_start_sectors[vobu_idx]; return 1; } /* Given two tmap entries and a time, calc the time for the lo tmap entry */ static int32_t dvdnav_tmap_calc_time_for_tmap_entry(dvdnav_jump_args_t *args, dvdnav_pos_data_t *lo, dvdnav_pos_data_t *hi, dvdnav_pos_data_t *pos, uint64_t *out_time) { int32_t result = 0; int32_t vobu_pct = 0; uint64_t time_adj = 0; if (lo->sector == hi->sector) { fprintf(MSG_OUT, "lo->sector == hi->sector: %i", lo->sector); return 0; } /* get vobus corresponding to lo, hi, pos */ result = dvdnav_admap_search(args->admap, args->admap_len, lo->sector, &lo->vobu_idx); if (!result) { fprintf(MSG_OUT, "lo->vobu: lo->sector=%i", lo->sector); return 0; } result = dvdnav_admap_search(args->admap, args->admap_len, hi->sector, &hi->vobu_idx); if (!result) { fprintf(MSG_OUT, "hi->vobu: hi->sector=%i", hi->sector); return 0; } result = dvdnav_admap_search(args->admap, args->admap_len, pos->sector, &pos->vobu_idx); if (!result) { fprintf(MSG_OUT, "pos->vobu: pos->sector=%i", pos->sector); return 0; } /* calc position of cell relative to lo */ vobu_pct = ((pos->vobu_idx - lo->vobu_idx) * 1000) / ( hi->vobu_idx - lo->vobu_idx); if (vobu_pct < 0 || vobu_pct > 1000) { fprintf(MSG_OUT, "vobu_pct must be between 0 and 1000"); return 0; } /* calc time of lo */ time_adj = (uint64_t)((args->tmap_interval * vobu_pct) / 1000); *out_time = pos->time - time_adj; return 1; } /* Find the tmap entries on either side of a given sector */ static int32_t dvdnav_tmap_get_entries_for_sector( dvdnav_jump_args_t *args, dvdnav_cell_data_t *cell_data, uint32_t find_sector, dvdnav_pos_data_t *lo, dvdnav_pos_data_t *hi) { int32_t result = 0; result = dvdnav_tmap_search(args->tmap, args->tmap_len, find_sector, &lo->tmap_idx, &lo->sector); if (!result) { fprintf(MSG_OUT, "could not find lo idx: %i", find_sector); return 0; } /* HACK: Most DVDs have a tmap that starts at sector 0 * However, some have initial dummy cells that are not seekable * (restricted = y). * These cells will throw off the tmap calcs when in the first playable cell. * For now, assume that lo->sector is equal to the cell->bgn->sector * Note that for most DVDs this will be 0 * (Since they will have no dummy cells and cell 1 will start at sector 0) */ if (lo->tmap_idx == TMAP_IDX_EDGE_BGN) { lo->sector = cell_data->bgn->sector; } if (lo->tmap_idx == args->tmap_len - 1) { /* lo is last tmap entry; "fake" entry for one beyond * and mark it with cell_end_sector */ hi->tmap_idx = TMAP_IDX_EDGE_END; hi->sector = cell_data->end->sector; } else { hi->tmap_idx = lo->tmap_idx + 1; result = dvdnav_tmap_get_entry(args->tmap, args->tmap_len, hi->tmap_idx, &hi->sector); if (!result) { fprintf(MSG_OUT, "could not find hi idx: %i", find_sector); return 0; } } return 1; } /* Find the nearest vobu by using the tmap */ static int32_t dvdnav_find_vobu_by_tmap(dvdnav_t *this, dvd_state_t *state, dvdnav_jump_args_t *args, dvdnav_cell_data_t *cell_data, dvdnav_pos_data_t *jump) { uint64_t seek_offset = 0; uint32_t seek_idx = 0; int32_t result = 0; dvdnav_pos_data_t *cell_bgn_lo = NULL; dvdnav_pos_data_t *cell_bgn_hi = NULL; dvdnav_pos_data_t *jump_lo = NULL; dvdnav_pos_data_t *jump_hi = NULL; /* get tmap, tmap_len, tmap_interval */ args->tmap = dvdnav_tmap_get(this, state, &args->tmap_len, &args->tmap_interval); if (args->tmap == NULL) return 0; /* get tmap entries on either side of cell_bgn */ cell_bgn_lo = &(dvdnav_pos_data_t){0}; cell_bgn_hi = &(dvdnav_pos_data_t){0}; result = dvdnav_tmap_get_entries_for_sector(args, cell_data, cell_data->bgn->sector, cell_bgn_lo, cell_bgn_hi); if (!result) return 0; /* calc time of cell_bgn_lo */ result = dvdnav_tmap_calc_time_for_tmap_entry(args, cell_bgn_lo, cell_bgn_hi, cell_data->bgn, &cell_bgn_lo->time); if (!result) return 0; /* calc time of jump_time relative to cell_bgn_lo */ seek_offset = jump->time - cell_bgn_lo->time; seek_idx = (uint32_t)(seek_offset / args->tmap_interval); uint32_t seek_remainder = seek_offset - (seek_idx * args->tmap_interval); uint32_t seek_pct = (seek_remainder * 1000) / args->tmap_interval; /* get tmap entries on either side of jump_time */ jump_lo = &(dvdnav_pos_data_t){0}; jump_hi = &(dvdnav_pos_data_t){0}; /* if seek_idx == 0, then tmap_indexes are the same, do not re-get * also, note cell_bgn_lo will already have sector if TMAP_IDX_EDGE_BGN */ if (seek_idx == 0) { jump_lo = cell_bgn_lo; jump_hi = cell_bgn_hi; } else { jump_lo->tmap_idx = (uint32_t)(cell_bgn_lo->tmap_idx + seek_idx); result = dvdnav_tmap_get_entry(args->tmap, args->tmap_len, jump_lo->tmap_idx, &jump_lo->sector); if (!result) return 0; /* +1 handled by dvdnav_tmap_get_entry */ jump_hi->tmap_idx = jump_lo->tmap_idx + 1; result = dvdnav_tmap_get_entry(args->tmap, args->tmap_len, jump_hi->tmap_idx, &jump_hi->sector); if (!result) return 0; } /* interpolate sector */ result = dvdnav_admap_interpolate_vobu(args, jump_lo, jump_hi, seek_pct, &jump->sector); return result; } /* Find the nearest vobu by using the cell boundaries */ static int32_t dvdnav_find_vobu_by_cell_boundaries( dvdnav_jump_args_t *args, dvdnav_cell_data_t *cell_data, dvdnav_pos_data_t *jump) { int64_t jump_offset = 0; int64_t cell_len = 0; uint32_t jump_pct = 0; int32_t result = 0; /* get jump_offset */ jump_offset = jump->time - cell_data->bgn->time; if (jump_offset < 0) { fprintf(MSG_OUT, "jump_offset < 0"); return 0; } cell_len = cell_data->end->time - cell_data->bgn->time; if (cell_len < 0) { fprintf(MSG_OUT, "cell_len < 0"); return 0; } jump_pct = (jump_offset * 1000) / cell_len; /* get sector */ /* NOTE: end cell sector in VTS_PGC is last sector of cell * this last sector is not the start of a VOBU * +1 to get sector that is the start of a VOBU * start of a VOBU is needed in order to index into admap */ cell_data->end->sector += 1; result = dvdnav_admap_interpolate_vobu(args, cell_data->bgn, cell_data->end, jump_pct, &jump->sector); if (!result) { fprintf(MSG_OUT, "find_by_admap.interpolate"); return 0; } return 1; } /* Jump to sector by time */ /* NOTE: Mode is currently unimplemented. Only 0 should be passed. */ /* 1 and -1 are for future implementation */ /* 0: Default. Jump to a time which may be either <> time_in_pts_ticks */ /* 1: After. Always jump to a time that is > time_in_pts_ticks */ /* -1: Before. Always jump to a time that is < time_in_pts_ticks */ dvdnav_status_t dvdnav_jump_to_sector_by_time(dvdnav_t *this, uint64_t time_in_pts_ticks, int32_t mode) { if (mode != JUMP_MODE_TIME_DEFAULT) return DVDNAV_STATUS_ERR; int32_t result = DVDNAV_STATUS_ERR; dvd_state_t *state = NULL; uint32_t sector_off = 0; dvdnav_pos_data_t *jump = NULL; dvdnav_cell_data_t *cell_data = NULL; dvdnav_jump_args_t *args = NULL; jump = &(dvdnav_pos_data_t){0}; /* convert time to milliseconds */ jump->time = time_in_pts_ticks / 90; /* get variables that will be used across both functions */ state = &(this->vm->state); if (state == NULL) goto exit; /* get cell info */ cell_data = &(dvdnav_cell_data_t){0}; cell_data->bgn = &(dvdnav_pos_data_t){0}; cell_data->end = &(dvdnav_pos_data_t){0}; result = dvdnav_cell_find(this, state, jump->time, cell_data); if (!result) goto exit; /* get admap */ args = &(dvdnav_jump_args_t){0}; args->admap = dvdnav_admap_get(this, state, &args->admap_len); if (args->admap == NULL) goto exit; /* find sector */ result = dvdnav_find_vobu_by_tmap(this, state, args, cell_data, jump); if (!result) {/* bad tmap; interpolate over cell */ result = dvdnav_find_vobu_by_cell_boundaries(args, cell_data, jump); if (!result) { goto exit; } } /* jump to sector */ sector_off = jump->sector - cell_data->bgn->sector; this->cur_cell_time = 0; if (vm_jump_cell_block(this->vm, cell_data->idx, sector_off)) { pthread_mutex_lock(&this->vm_lock); this->vm->hop_channel += HOP_SEEK; pthread_mutex_unlock(&this->vm_lock); result = DVDNAV_STATUS_OK; } exit: return result; } k9copy/src/libdvdnav-NOW/highlight.c0000644000175000017550000003631712412277736020104 0ustar emulatoremulator/* * Copyright (C) 2000 Rich Wareham * * This file is part of libdvdnav, a DVD navigation library. * * libdvdnav is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdnav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdnav; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include "dvdnav/dvdnav.h" #include "vm/decoder.h" #include "vm/vm.h" #include "vm/vmcmd.h" #include "dvdnav_internal.h" /* #define BUTTON_TESTING */ #ifdef BUTTON_TESTING #include "nav_print.h" static void print_time(dvd_time_t *dtime) { const char *rate; assert((dtime->hour>>4) < 0xa && (dtime->hour&0xf) < 0xa); assert((dtime->minute>>4) < 0x7 && (dtime->minute&0xf) < 0xa); assert((dtime->second>>4) < 0x7 && (dtime->second&0xf) < 0xa); assert((dtime->frame_u&0xf) < 0xa); fprintf(MSG_OUT,"%02x:%02x:%02x.%02x", dtime->hour, dtime->minute, dtime->second, dtime->frame_u & 0x3f); switch((dtime->frame_u & 0xc0) >> 6) { case 1: rate = "25.00"; break; case 3: rate = "29.97"; break; default: rate = "(please send a bug report)"; break; } fprintf(MSG_OUT," @ %s fps", rate); } static void nav_print_PCI_GI(pci_gi_t *pci_gi) { int32_t i; fprintf(MSG_OUT,"libdvdnav: pci_gi:\n"); fprintf(MSG_OUT,"libdvdnav: nv_pck_lbn 0x%08x\n", pci_gi->nv_pck_lbn); fprintf(MSG_OUT,"libdvdnav: vobu_cat 0x%04x\n", pci_gi->vobu_cat); fprintf(MSG_OUT,"libdvdnav: vobu_uop_ctl 0x%08x\n", *(uint32_t*)&pci_gi->vobu_uop_ctl); fprintf(MSG_OUT,"libdvdnav: vobu_s_ptm 0x%08x\n", pci_gi->vobu_s_ptm); fprintf(MSG_OUT,"libdvdnav: vobu_e_ptm 0x%08x\n", pci_gi->vobu_e_ptm); fprintf(MSG_OUT,"libdvdnav: vobu_se_e_ptm 0x%08x\n", pci_gi->vobu_se_e_ptm); fprintf(MSG_OUT,"libdvdnav: e_eltm "); print_time(&pci_gi->e_eltm); fprintf(MSG_OUT,"\n"); fprintf(MSG_OUT,"libdvdnav: vobu_isrc \""); for(i = 0; i < 32; i++) { char c = pci_gi->vobu_isrc[i]; if((c >= ' ') && (c <= '~')) fprintf(MSG_OUT,"%c", c); else fprintf(MSG_OUT,"."); } fprintf(MSG_OUT,"\"\n"); } static void nav_print_NSML_AGLI(nsml_agli_t *nsml_agli) { int32_t i, j = 0; for(i = 0; i < 9; i++) j |= nsml_agli->nsml_agl_dsta[i]; if(j == 0) return; fprintf(MSG_OUT,"libdvdnav: nsml_agli:\n"); for(i = 0; i < 9; i++) if(nsml_agli->nsml_agl_dsta[i]) fprintf(MSG_OUT,"libdvdnav: nsml_agl_c%d_dsta 0x%08x\n", i + 1, nsml_agli->nsml_agl_dsta[i]); } static void nav_print_HL_GI(hl_gi_t *hl_gi, int32_t *btngr_ns, int32_t *btn_ns) { if((hl_gi->hli_ss & 0x03) == 0) return; fprintf(MSG_OUT,"libdvdnav: hl_gi:\n"); fprintf(MSG_OUT,"libdvdnav: hli_ss 0x%01x\n", hl_gi->hli_ss & 0x03); fprintf(MSG_OUT,"libdvdnav: hli_s_ptm 0x%08x\n", hl_gi->hli_s_ptm); fprintf(MSG_OUT,"libdvdnav: hli_e_ptm 0x%08x\n", hl_gi->hli_e_ptm); fprintf(MSG_OUT,"libdvdnav: btn_se_e_ptm 0x%08x\n", hl_gi->btn_se_e_ptm); *btngr_ns = hl_gi->btngr_ns; fprintf(MSG_OUT,"libdvdnav: btngr_ns %d\n", hl_gi->btngr_ns); fprintf(MSG_OUT,"libdvdnav: btngr%d_dsp_ty 0x%02x\n", 1, hl_gi->btngr1_dsp_ty); fprintf(MSG_OUT,"libdvdnav: btngr%d_dsp_ty 0x%02x\n", 2, hl_gi->btngr2_dsp_ty); fprintf(MSG_OUT,"libdvdnav: btngr%d_dsp_ty 0x%02x\n", 3, hl_gi->btngr3_dsp_ty); fprintf(MSG_OUT,"libdvdnav: btn_ofn %d\n", hl_gi->btn_ofn); *btn_ns = hl_gi->btn_ns; fprintf(MSG_OUT,"libdvdnav: btn_ns %d\n", hl_gi->btn_ns); fprintf(MSG_OUT,"libdvdnav: nsl_btn_ns %d\n", hl_gi->nsl_btn_ns); fprintf(MSG_OUT,"libdvdnav: fosl_btnn %d\n", hl_gi->fosl_btnn); fprintf(MSG_OUT,"libdvdnav: foac_btnn %d\n", hl_gi->foac_btnn); } static void nav_print_BTN_COLIT(btn_colit_t *btn_colit) { int32_t i, j; j = 0; for(i = 0; i < 6; i++) j |= btn_colit->btn_coli[i/2][i&1]; if(j == 0) return; fprintf(MSG_OUT,"libdvdnav: btn_colit:\n"); for(i = 0; i < 3; i++) for(j = 0; j < 2; j++) fprintf(MSG_OUT,"libdvdnav: btn_cqoli %d %s_coli: %08x\n", i, (j == 0) ? "sl" : "ac", btn_colit->btn_coli[i][j]); } static void nav_print_BTNIT(btni_t *btni_table, int32_t btngr_ns, int32_t btn_ns) { int32_t i, j, k; fprintf(MSG_OUT,"libdvdnav: btnit:\n"); fprintf(MSG_OUT,"libdvdnav: btngr_ns: %i\n", btngr_ns); fprintf(MSG_OUT,"libdvdnav: btn_ns: %i\n", btn_ns); if(btngr_ns == 0) return; for(i = 0; i < btngr_ns; i++) { for(j = 0; j < (36 / btngr_ns); j++) { if(j < btn_ns) { btni_t *btni = &btni_table[(36 / btngr_ns) * i + j]; fprintf(MSG_OUT,"libdvdnav: group %d btni %d: ", i+1, j+1); fprintf(MSG_OUT,"btn_coln %d, auto_action_mode %d\n", btni->btn_coln, btni->auto_action_mode); fprintf(MSG_OUT,"libdvdnav: coords (%d, %d) .. (%d, %d)\n", btni->x_start, btni->y_start, btni->x_end, btni->y_end); fprintf(MSG_OUT,"libdvdnav: up %d, ", btni->up); fprintf(MSG_OUT,"down %d, ", btni->down); fprintf(MSG_OUT,"left %d, ", btni->left); fprintf(MSG_OUT,"right %d\n", btni->right); for(k = 0; k < 8; k++) { fprintf(MSG_OUT, "libdvdnav: %02x ", btni->cmd.bytes[k]); } fprintf(MSG_OUT, "| "); #ifdef TRACE vm_print_mnemonic(&btni->cmd); #endif fprintf(MSG_OUT, "\n"); } } } } static void nav_print_HLI(hli_t *hli) { int32_t btngr_ns = 0, btn_ns = 0; fprintf(MSG_OUT,"libdvdnav: hli:\n"); nav_print_HL_GI(&hli->hl_gi, & btngr_ns, & btn_ns); nav_print_BTN_COLIT(&hli->btn_colit); nav_print_BTNIT(hli->btnit, btngr_ns, btn_ns); } void nav_print_PCI(pci_t *pci) { fprintf(MSG_OUT,"libdvdnav: pci packet:\n"); nav_print_PCI_GI(&pci->pci_gi); nav_print_NSML_AGLI(&pci->nsml_agli); nav_print_HLI(&pci->hli); } #endif /* Highlighting API calls */ dvdnav_status_t dvdnav_get_current_highlight(dvdnav_t *this, int32_t *button) { /* Simply return the appropriate value based on the SPRM */ if(((*button) = this->position_current.button) == -1) (*button) = this->vm->state.HL_BTNN_REG >> 10; return DVDNAV_STATUS_OK; } static btni_t *get_current_button(dvdnav_t *this, pci_t *pci) { int32_t button = 0; if(!pci->hli.hl_gi.hli_ss) { printerr("Not in a menu."); return NULL; } if(this->last_cmd_nav_lbn == pci->pci_gi.nv_pck_lbn) { printerr("This NAV has already been left."); return NULL; } button = this->vm->state.HL_BTNN_REG >> 10; #ifdef BUTTON_TESTING nav_print_PCI(pci); #endif return &(pci->hli.btnit[button-1]); } static dvdnav_status_t button_auto_action(dvdnav_t *this, pci_t *pci) { btni_t *button_ptr; if ((button_ptr = get_current_button(this, pci)) == NULL) return DVDNAV_STATUS_ERR; if (button_ptr->auto_action_mode) return dvdnav_button_activate(this, pci); return DVDNAV_STATUS_OK; } dvdnav_status_t dvdnav_upper_button_select(dvdnav_t *this, pci_t *pci) { btni_t *button_ptr; if(!(button_ptr = get_current_button(this, pci))) return DVDNAV_STATUS_ERR; dvdnav_button_select(this, pci, button_ptr->up); return button_auto_action(this, pci); } dvdnav_status_t dvdnav_lower_button_select(dvdnav_t *this, pci_t *pci) { btni_t *button_ptr; if(!(button_ptr = get_current_button(this, pci))) return DVDNAV_STATUS_ERR; dvdnav_button_select(this, pci, button_ptr->down); return button_auto_action(this, pci); } dvdnav_status_t dvdnav_right_button_select(dvdnav_t *this, pci_t *pci) { btni_t *button_ptr; if(!(button_ptr = get_current_button(this, pci))) return DVDNAV_STATUS_ERR; dvdnav_button_select(this, pci, button_ptr->right); return button_auto_action(this, pci); } dvdnav_status_t dvdnav_left_button_select(dvdnav_t *this, pci_t *pci) { btni_t *button_ptr; if(!(button_ptr = get_current_button(this, pci))) return DVDNAV_STATUS_ERR; dvdnav_button_select(this, pci, button_ptr->left); return button_auto_action(this, pci); } dvdnav_status_t dvdnav_get_highlight_area(pci_t *nav_pci , int32_t button, int32_t mode, dvdnav_highlight_area_t *highlight) { btni_t *button_ptr; #ifdef BUTTON_TESTING fprintf(MSG_OUT, "libdvdnav: Button get_highlight_area %i\n", button); #endif if(!nav_pci->hli.hl_gi.hli_ss) return DVDNAV_STATUS_ERR; if((button <= 0) || (button > nav_pci->hli.hl_gi.btn_ns)) return DVDNAV_STATUS_ERR; button_ptr = &nav_pci->hli.btnit[button-1]; highlight->sx = button_ptr->x_start; highlight->sy = button_ptr->y_start; highlight->ex = button_ptr->x_end; highlight->ey = button_ptr->y_end; if(button_ptr->btn_coln != 0) { highlight->palette = nav_pci->hli.btn_colit.btn_coli[button_ptr->btn_coln-1][mode]; } else { highlight->palette = 0; } highlight->pts = nav_pci->hli.hl_gi.hli_s_ptm; highlight->buttonN = button; #ifdef BUTTON_TESTING fprintf(MSG_OUT, "libdvdnav: highlight: Highlight area is (%u,%u)-(%u,%u), display = %i, button = %u\n", button_ptr->x_start, button_ptr->y_start, button_ptr->x_end, button_ptr->y_end, 1, button); #endif return DVDNAV_STATUS_OK; } dvdnav_status_t dvdnav_button_activate(dvdnav_t *this, pci_t *pci) { int32_t button; btni_t *button_ptr = NULL; if(!pci->hli.hl_gi.hli_ss) { printerr("Not in a menu."); return DVDNAV_STATUS_ERR; } if(this->last_cmd_nav_lbn == pci->pci_gi.nv_pck_lbn) { printerr("This NAV has already been left."); return DVDNAV_STATUS_ERR; } pthread_mutex_lock(&this->vm_lock); button = this->vm->state.HL_BTNN_REG >> 10; if((button <= 0) || (button > pci->hli.hl_gi.btn_ns)) { /* Special code to handle still menus with no buttons. * The navigation is expected to report to the application that a STILL is * underway. In turn, the application is supposed to report to the user * that the playback is paused. The user is then expected to undo the pause, * ie: hit play. At that point, the navigation should release the still and * go to the next Cell. * Explanation by Mathieu Lacage * Code added by jcdutton. */ if (this->position_current.still != 0) { /* In still, but no buttons. */ vm_get_next_cell(this->vm); this->position_current.still = 0; this->sync_wait = 0; this->last_cmd_nav_lbn = pci->pci_gi.nv_pck_lbn; pthread_mutex_unlock(&this->vm_lock); /* clear error message */ printerr(""); return DVDNAV_STATUS_OK; } pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } if ((button_ptr = get_current_button(this, pci)) == NULL) { pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } /* Finally, make the VM execute the appropriate code and probably * schedule a jump */ #ifdef BUTTON_TESTING fprintf(MSG_OUT, "libdvdnav: Evaluating Button Activation commands.\n"); #endif if(vm_exec_cmd(this->vm, &(button_ptr->cmd)) == 1) { /* Command caused a jump */ this->vm->hop_channel++; this->position_current.still = 0; this->last_cmd_nav_lbn = pci->pci_gi.nv_pck_lbn; } pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } dvdnav_status_t dvdnav_button_activate_cmd(dvdnav_t *this, int32_t button, vm_cmd_t *cmd) { pthread_mutex_lock(&this->vm_lock); /* make the VM execute the appropriate code and probably * schedule a jump */ #ifdef BUTTON_TESTING fprintf(MSG_OUT, "libdvdnav: dvdnav_button_activate_cmd: Evaluating Button Activation commands.\n"); #endif if(button > 0) { this->vm->state.HL_BTNN_REG = (button << 10); if(vm_exec_cmd(this->vm, cmd) == 1) { /* Command caused a jump */ this->vm->hop_channel++; } } /* Always remove still, because some still menus have no buttons. */ this->position_current.still = 0; this->sync_wait = 0; pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } dvdnav_status_t dvdnav_button_select(dvdnav_t *this, pci_t *pci, int32_t button) { if(!pci->hli.hl_gi.hli_ss) { printerr("Not in a menu."); return DVDNAV_STATUS_ERR; } if(this->last_cmd_nav_lbn == pci->pci_gi.nv_pck_lbn) { printerr("This NAV has already been left."); return DVDNAV_STATUS_ERR; } #ifdef BUTTON_TESTING fprintf(MSG_OUT, "libdvdnav: Button select %i\n", button); #endif if((button <= 0) || (button > pci->hli.hl_gi.btn_ns)) { printerr("Button does not exist."); return DVDNAV_STATUS_ERR; } this->vm->state.HL_BTNN_REG = (button << 10); this->position_current.button = -1; /* Force Highlight change */ return DVDNAV_STATUS_OK; } dvdnav_status_t dvdnav_button_select_and_activate(dvdnav_t *this, pci_t *pci, int32_t button) { /* A trivial function */ if(dvdnav_button_select(this, pci, button) != DVDNAV_STATUS_ERR) return dvdnav_button_activate(this, pci); return DVDNAV_STATUS_ERR; } dvdnav_status_t dvdnav_mouse_select(dvdnav_t *this, pci_t *pci, int32_t x, int32_t y) { int32_t button, cur_button; int32_t best,dist,d; int32_t mx,my,dx,dy; if(!pci->hli.hl_gi.hli_ss) { printerr("Not in a menu."); return DVDNAV_STATUS_ERR; } if(this->last_cmd_nav_lbn == pci->pci_gi.nv_pck_lbn) { printerr("This NAV has already been left."); return DVDNAV_STATUS_ERR; } cur_button = this->vm->state.HL_BTNN_REG >> 10; best = 0; dist = 0x08000000; /* >> than (720*720)+(567*567); */ /* Loop through all buttons */ for(button = 1; button <= pci->hli.hl_gi.btn_ns; button++) { btni_t *button_ptr = &(pci->hli.btnit[button-1]); if((x >= button_ptr->x_start) && (x <= button_ptr->x_end) && (y >= button_ptr->y_start) && (y <= button_ptr->y_end)) { mx = (button_ptr->x_start + button_ptr->x_end)/2; my = (button_ptr->y_start + button_ptr->y_end)/2; dx = mx - x; dy = my - y; d = (dx*dx) + (dy*dy); /* If the mouse is within the button and the mouse is closer * to the center of this button then it is the best choice. */ if(d < dist) { dist = d; best = button; } } } /* As an efficiency measure, only re-select the button * if it is different to the previously selected one. */ if (best != 0 && best != cur_button) dvdnav_button_select(this, pci, best); /* return DVDNAV_STATUS_OK only if we actually found a matching button */ return best ? DVDNAV_STATUS_OK : DVDNAV_STATUS_ERR; } dvdnav_status_t dvdnav_mouse_activate(dvdnav_t *this, pci_t *pci, int32_t x, int32_t y) { /* A trivial function */ if(dvdnav_mouse_select(this, pci, x,y) != DVDNAV_STATUS_ERR) return dvdnav_button_activate(this, pci); return DVDNAV_STATUS_ERR; } k9copy/src/libdvdnav-NOW/read_cache.c0000644000175000017550000002614312412277736020167 0ustar emulatoremulator/* * Copyright (C) 2000 Rich Wareham * 2001-2004 the dvdnav project * * This file is part of libdvdnav, a DVD navigation library. * * libdvdnav is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdnav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdnav; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* * There was a multithreaded read ahead cache in here for some time, but * it had only been used for a short time. If you want to have a look at it, * search the CVS attic. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "dvdnav/dvdnav.h" #include #include #include "vm/decoder.h" #include "vm/vm.h" #include "dvdnav_internal.h" #include "read_cache.h" #define READ_CACHE_CHUNKS 10 /* all cache chunks must be memory aligned to allow use of raw devices */ #define ALIGNMENT 2048 #define READ_AHEAD_SIZE_MIN 4 #define READ_AHEAD_SIZE_MAX 512 typedef struct read_cache_chunk_s { uint8_t *cache_buffer; uint8_t *cache_buffer_base; /* used in malloc and free for alignment */ int32_t cache_start_sector; /* -1 means cache invalid */ int32_t cache_read_count; /* this many sectors are already read */ size_t cache_block_count; /* this many sectors will go in this chunk */ size_t cache_malloc_size; int cache_valid; int usage_count; /* counts how many buffers where issued from this chunk */ } read_cache_chunk_t; struct read_cache_s { read_cache_chunk_t chunk[READ_CACHE_CHUNKS]; int current; int freeing; /* is set to one when we are about to dispose the cache */ uint32_t read_ahead_size; int read_ahead_incr; int last_sector; pthread_mutex_t lock; /* Bit of strange cross-linking going on here :) -- Gotta love C :) */ dvdnav_t *dvd_self; }; /* #define READ_CACHE_TRACE 0 */ #ifdef __GNUC__ # if READ_CACHE_TRACE # define dprintf(fmt, args...) fprintf(MSG_OUT, "libdvdnav: %s: "fmt, __func__ , ## args) # else # define dprintf(fmt, args...) /* Nowt */ # endif #else # if READ_CACHE_TRACE # define dprintf(fmt, ...) fprintf(MSG_OUT, "libdvdnav: %s: "fmt, __func__ , __VA_ARGS__) # else #ifdef _MSC_VER # define dprintf(fmt, str) /* Nowt */ #else # define dprintf(fmt, ...) /* Nowt */ #endif /* _MSC_VER */ # endif #endif read_cache_t *dvdnav_read_cache_new(dvdnav_t* dvd_self) { read_cache_t *self; int i; self = (read_cache_t *)calloc(1, sizeof(read_cache_t)); if(!self) return NULL; self->dvd_self = dvd_self; self->read_ahead_size = READ_AHEAD_SIZE_MIN; pthread_mutex_init(&self->lock, NULL); dvdnav_read_cache_clear(self); for (i = 0; i < READ_CACHE_CHUNKS; i++) { self->chunk[i].cache_buffer = NULL; self->chunk[i].usage_count = 0; } return self; } void dvdnav_read_cache_free(read_cache_t* self) { dvdnav_t *tmp; int i; pthread_mutex_lock(&self->lock); self->freeing = 1; for (i = 0; i < READ_CACHE_CHUNKS; i++) if (self->chunk[i].cache_buffer && self->chunk[i].usage_count == 0) { free(self->chunk[i].cache_buffer_base); self->chunk[i].cache_buffer = NULL; } pthread_mutex_unlock(&self->lock); for (i = 0; i < READ_CACHE_CHUNKS; i++) if (self->chunk[i].cache_buffer) return; /* all buffers returned, free everything */ tmp = self->dvd_self; pthread_mutex_destroy(&self->lock); free(self); free(tmp); } /* This function MUST be called whenever self->file changes. */ void dvdnav_read_cache_clear(read_cache_t *self) { int i; if(!self) return; pthread_mutex_lock(&self->lock); for (i = 0; i < READ_CACHE_CHUNKS; i++) self->chunk[i].cache_valid = 0; pthread_mutex_unlock(&self->lock); } /* This function is called just after reading the NAV packet. */ void dvdnav_pre_cache_blocks(read_cache_t *self, int sector, size_t block_count) { int i, use; if(!self) return; if(!self->dvd_self->use_read_ahead) return; pthread_mutex_lock(&self->lock); /* find a free cache chunk that best fits the required size */ use = -1; for (i = 0; i < READ_CACHE_CHUNKS; i++) if (self->chunk[i].usage_count == 0 && self->chunk[i].cache_buffer && self->chunk[i].cache_malloc_size >= block_count && (use == -1 || self->chunk[use].cache_malloc_size > self->chunk[i].cache_malloc_size)) use = i; if (use == -1) { /* we haven't found a cache chunk, so we try to reallocate an existing one */ for (i = 0; i < READ_CACHE_CHUNKS; i++) if (self->chunk[i].usage_count == 0 && self->chunk[i].cache_buffer && (use == -1 || self->chunk[use].cache_malloc_size < self->chunk[i].cache_malloc_size)) use = i; if (use >= 0) { self->chunk[use].cache_buffer_base = realloc(self->chunk[use].cache_buffer_base, block_count * DVD_VIDEO_LB_LEN + ALIGNMENT); self->chunk[use].cache_buffer = (uint8_t *)(((uintptr_t)self->chunk[use].cache_buffer_base & ~((uintptr_t)(ALIGNMENT - 1))) + ALIGNMENT); dprintf("pre_cache DVD read realloc happened\n"); self->chunk[use].cache_malloc_size = block_count; } else { /* we still haven't found a cache chunk, let's allocate a new one */ for (i = 0; i < READ_CACHE_CHUNKS; i++) if (!self->chunk[i].cache_buffer) { use = i; break; } if (use >= 0) { /* We start with a sensible figure for the first malloc of 500 blocks. * Some DVDs I have seen venture to 450 blocks. * This is so that fewer realloc's happen if at all. */ self->chunk[i].cache_buffer_base = malloc((block_count > 500 ? block_count : 500) * DVD_VIDEO_LB_LEN + ALIGNMENT); self->chunk[i].cache_buffer = (uint8_t *)(((uintptr_t)self->chunk[i].cache_buffer_base & ~((uintptr_t)(ALIGNMENT - 1))) + ALIGNMENT); self->chunk[i].cache_malloc_size = block_count > 500 ? block_count : 500; dprintf("pre_cache DVD read malloc %d blocks\n", (block_count > 500 ? block_count : 500 )); } } } if (use >= 0) { self->chunk[use].cache_start_sector = sector; self->chunk[use].cache_block_count = block_count; self->chunk[use].cache_read_count = 0; self->chunk[use].cache_valid = 1; self->current = use; } else { dprintf("pre_caching was impossible, no cache chunk available\n"); } pthread_mutex_unlock(&self->lock); } int dvdnav_read_cache_block(read_cache_t *self, int sector, size_t block_count, uint8_t **buf) { int i, use; int start; int size; int incr; uint8_t *read_ahead_buf; int32_t res; if(!self) return 0; use = -1; if(self->dvd_self->use_read_ahead) { /* first check, if sector is in current chunk */ read_cache_chunk_t cur = self->chunk[self->current]; if (cur.cache_valid && sector >= cur.cache_start_sector && sector <= (cur.cache_start_sector + cur.cache_read_count) && sector + block_count <= cur.cache_start_sector + cur.cache_block_count) use = self->current; else for (i = 0; i < READ_CACHE_CHUNKS; i++) if (self->chunk[i].cache_valid && sector >= self->chunk[i].cache_start_sector && sector <= (self->chunk[i].cache_start_sector + self->chunk[i].cache_read_count) && sector + block_count <= self->chunk[i].cache_start_sector + self->chunk[i].cache_block_count) use = i; } if (use >= 0) { read_cache_chunk_t *chunk; /* Increment read-ahead size if sector follows the last sector */ if (sector == (self->last_sector + 1)) { if (self->read_ahead_incr < READ_AHEAD_SIZE_MAX) self->read_ahead_incr++; } else { self->read_ahead_size = READ_AHEAD_SIZE_MIN; self->read_ahead_incr = 0; } self->last_sector = sector; /* The following resources need to be protected by a mutex : * self->chunk[*].cache_buffer * self->chunk[*].cache_malloc_size * self->chunk[*].usage_count */ pthread_mutex_lock(&self->lock); chunk = &self->chunk[use]; read_ahead_buf = chunk->cache_buffer + chunk->cache_read_count * DVD_VIDEO_LB_LEN; *buf = chunk->cache_buffer + (sector - chunk->cache_start_sector) * DVD_VIDEO_LB_LEN; chunk->usage_count++; pthread_mutex_unlock(&self->lock); dprintf("libdvdnav: sector=%d, start_sector=%d, last_sector=%d\n", sector, chunk->cache_start_sector, chunk->cache_start_sector + chunk->cache_block_count); /* read_ahead_size */ incr = self->read_ahead_incr >> 1; if ((self->read_ahead_size + incr) > READ_AHEAD_SIZE_MAX) { self->read_ahead_size = READ_AHEAD_SIZE_MAX; } else { self->read_ahead_size += incr; } /* real read size */ start = chunk->cache_start_sector + chunk->cache_read_count; if (chunk->cache_read_count + self->read_ahead_size > chunk->cache_block_count) { size = chunk->cache_block_count - chunk->cache_read_count; } else { size = self->read_ahead_size; /* ensure that the sector we want will be read */ if (sector >= chunk->cache_start_sector + chunk->cache_read_count + size) size = sector - chunk->cache_start_sector - chunk->cache_read_count; } dprintf("libdvdnav: read_ahead_size=%d, size=%d\n", self->read_ahead_size, size); if (size) chunk->cache_read_count += DVDReadBlocks(self->dvd_self->file, start, size, read_ahead_buf); res = DVD_VIDEO_LB_LEN * block_count; } else { if (self->dvd_self->use_read_ahead) { dprintf("cache miss on sector %d\n", sector); } res = DVDReadBlocks(self->dvd_self->file, sector, block_count, *buf) * DVD_VIDEO_LB_LEN; } return res; } dvdnav_status_t dvdnav_free_cache_block(dvdnav_t *self, unsigned char *buf) { read_cache_t *cache; int i; if (!self) return DVDNAV_STATUS_ERR; cache = self->cache; if (!cache) return DVDNAV_STATUS_ERR; pthread_mutex_lock(&cache->lock); for (i = 0; i < READ_CACHE_CHUNKS; i++) { if (cache->chunk[i].cache_buffer && buf >= cache->chunk[i].cache_buffer && buf < cache->chunk[i].cache_buffer + cache->chunk[i].cache_malloc_size * DVD_VIDEO_LB_LEN) { cache->chunk[i].usage_count--; } } pthread_mutex_unlock(&cache->lock); if (cache->freeing) /* when we want to dispose the cache, try freeing it now */ dvdnav_read_cache_free(cache); return DVDNAV_STATUS_OK; } k9copy/src/libdvdnav-NOW/dvdnav/0000755000175000017550000000000012412277736017241 5ustar emulatoremulatork9copy/src/libdvdnav-NOW/dvdnav/dvdnav_events.h0000644000175000017550000001666212412277736022273 0ustar emulatoremulator/* * Copyright (C) 2001 Rich Wareham * * This file is part of libdvdnav, a DVD navigation library. * * libdvdnav is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdnav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdnav; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* * This header defines events and event types */ #ifndef LIBDVDNAV_DVDNAV_EVENTS_H #define LIBDVDNAV_DVDNAV_EVENTS_H /* * DVDNAV_BLOCK_OK * * A regular data block from the DVD has been returned. * This one should be demuxed and decoded for playback. */ #define DVDNAV_BLOCK_OK 0 /* * DVDNAV_NOP * * Just ignore this. */ #define DVDNAV_NOP 1 /* * DVDNAV_STILL_FRAME * * We have reached a still frame. The player application should wait * the amount of time specified by the still's length while still handling * user input to make menus and other interactive stills work. * The last delivered frame should be kept showing. * Once the still has timed out, call dvdnav_skip_still(). * A length of 0xff means an infinite still which has to be skipped * indirectly by some user interaction. */ #define DVDNAV_STILL_FRAME 2 typedef struct { /* The length (in seconds) the still frame should be displayed for, * or 0xff if infinite. */ int length; } dvdnav_still_event_t; /* * DVDNAV_SPU_STREAM_CHANGE * * Inform the SPU decoding/overlaying engine to switch SPU channels. */ #define DVDNAV_SPU_STREAM_CHANGE 3 typedef struct { /* The physical (MPEG) stream number for widescreen SPU display. * Use this, if you blend the SPU on an anamorphic image before * unsqueezing it. */ int physical_wide; /* The physical (MPEG) stream number for letterboxed display. * Use this, if you blend the SPU on an anamorphic image after * unsqueezing it. */ int physical_letterbox; /* The physical (MPEG) stream number for pan&scan display. * Use this, if you blend the SPU on an anamorphic image after * unsqueezing it the pan&scan way. */ int physical_pan_scan; /* The logical (DVD) stream number. */ int logical; } dvdnav_spu_stream_change_event_t; /* * DVDNAV_AUDIO_STREAM_CHANGE * * Inform the audio decoder to switch channels. */ #define DVDNAV_AUDIO_STREAM_CHANGE 4 typedef struct { /* The physical (MPEG) stream number. */ int physical; /* The logical (DVD) stream number. */ int logical; } dvdnav_audio_stream_change_event_t; /* * DVDNAV_VTS_CHANGE * * Some status information like video aspect and video scale permissions do * not change inside a VTS. Therefore this event can be used to query such * information only when necessary and update the decoding/displaying * accordingly. */ #define DVDNAV_VTS_CHANGE 5 typedef struct { int old_vtsN; /* the old VTS number */ DVDDomain_t old_domain; /* the old domain */ int new_vtsN; /* the new VTS number */ DVDDomain_t new_domain; /* the new domain */ } dvdnav_vts_change_event_t; /* * DVDNAV_CELL_CHANGE * * Some status information like the current Title and Part numbers do not * change inside a cell. Therefore this event can be used to query such * information only when necessary and update the decoding/displaying * accordingly. * Some useful information for accurate time display is also reported * together with this event. */ #define DVDNAV_CELL_CHANGE 6 typedef struct { int cellN; /* the new cell number */ int pgN; /* the current program number */ int64_t cell_length; /* the length of the current cell in PTS ticks */ int64_t pg_length; /* the length of the current program in PTS ticks */ int64_t pgc_length; /* the length of the current program chain in PTS ticks */ int64_t cell_start; /* the start time of the current cell relatively to the PGC in PTS ticks */ int64_t pg_start; /* the start time of the current PG relatively to the PGC in PTS ticks */ } dvdnav_cell_change_event_t; /* * DVDNAV_NAV_PACKET * * NAV packets are useful for various purposes. They define the button * highlight areas and VM commands of DVD menus, so they should in any * case be sent to the SPU decoder/overlaying engine for the menus to work. * NAV packets also provide a way to detect PTS discontinuities, because * they carry the start and end PTS values for the current VOBU. * (pci.vobu_s_ptm and pci.vobu_e_ptm) Whenever the start PTS of the * current NAV does not match the end PTS of the previous NAV, a PTS * discontinuity has occured. * NAV packets can also be used for time display, because they are * timestamped relatively to the current Cell. */ #define DVDNAV_NAV_PACKET 7 /* * DVDNAV_STOP * * Applications should end playback here. A subsequent dvdnav_get_next_block() * call will restart the VM from the beginning of the DVD. */ #define DVDNAV_STOP 8 /* * DVDNAV_HIGHLIGHT * * The current button highlight changed. Inform the overlaying engine to * highlight a different button. Please note, that at the moment only mode 1 * highlights are reported this way. That means, when the button highlight * has been moved around by some function call, you will receive an event * telling you the new button. But when a button gets activated, you have * to handle the mode 2 highlighting (that is some different colour the * button turns to on activation) in your application. */ #define DVDNAV_HIGHLIGHT 9 typedef struct { /* highlight mode: 0 - hide, 1 - show, 2 - activate, currently always 1 */ int display; /* FIXME: these fields are currently not set */ uint32_t palette; /* The CLUT entries for the highlight palette (4-bits per entry -> 4 entries) */ uint16_t sx,sy,ex,ey; /* The start/end x,y positions */ uint32_t pts; /* Highlight PTS to match with SPU */ /* button number for the SPU decoder/overlaying engine */ uint32_t buttonN; } dvdnav_highlight_event_t; /* * DVDNAV_SPU_CLUT_CHANGE * * Inform the SPU decoder/overlaying engine to update its colour lookup table. * The CLUT is given as 16 uint32_t's in the buffer. */ #define DVDNAV_SPU_CLUT_CHANGE 10 /* * DVDNAV_HOP_CHANNEL * * A non-seamless operation has been performed. Applications can drop all * their internal fifo's content, which will speed up the response. */ #define DVDNAV_HOP_CHANNEL 12 /* * DVDNAV_WAIT * * We have reached a point in DVD playback, where timing is critical. * Player application with internal fifos can introduce state * inconsistencies, because libdvdnav is always the fifo's length * ahead in the stream compared to what the application sees. * Such applications should wait until their fifos are empty * when they receive this type of event. * Once this is achieved, call dvdnav_skip_wait(). */ #define DVDNAV_WAIT 13 #endif /* LIBDVDNAV_DVDNAV_EVENTS_H */ k9copy/src/libdvdnav-NOW/dvdnav/dvdnav.h0000644000175000017550000005603112412277736020701 0ustar emulatoremulator/* * Copyright (C) 2001 Rich Wareham * * This file is part of libdvdnav, a DVD navigation library. * * libdvdnav is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdnav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdnav; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* * This is the main header file applications should include if they want * to access dvdnav functionality. */ #ifndef LIBDVDNAV_DVDNAV_H #define LIBDVDNAV_DVDNAV_H #define MP_DVDNAV 1 #ifdef __cplusplus extern "C" { #endif #include #include #include #include /* For vm_cmd_t */ #include /********************************************************************* * dvdnav data types * *********************************************************************/ /* * Opaque data-type can be viewed as a 'DVD handle'. You should get * a pointer to a dvdnav_t from the dvdnav_open() function. * Never call free() on the pointer, you have to give it back with * dvdnav_close(). */ typedef struct dvdnav_s dvdnav_t; /* Status as reported by most of libdvdnav's functions */ typedef int32_t dvdnav_status_t; /* * Unless otherwise stated, all functions return DVDNAV_STATUS_OK if * they succeeded, otherwise DVDNAV_STATUS_ERR is returned and the error may * be obtained by calling dvdnav_err_to_string(). */ #define DVDNAV_STATUS_ERR 0 #define DVDNAV_STATUS_OK 1 /********************************************************************* * initialisation & housekeeping functions * *********************************************************************/ /* * These functions allow you to open a DVD device and associate it * with a dvdnav_t. */ /* * Attempts to open the DVD drive at the specified path and pre-cache * the CSS-keys. libdvdread is used to access the DVD, so any source * supported by libdvdread can be given with "path". Currently, * libdvdread can access: DVD drives, DVD image files, DVD file-by-file * copies. * * The resulting dvdnav_t handle will be written to *dest. */ dvdnav_status_t dvdnav_open(dvdnav_t **dest, const char *path); dvdnav_status_t dvdnav_dup(dvdnav_t **dest, dvdnav_t *src); dvdnav_status_t dvdnav_free_dup(dvdnav_t * _this); /* * Closes a dvdnav_t previously opened with dvdnav_open(), freeing any * memory associated with it. */ dvdnav_status_t dvdnav_close(dvdnav_t *self); /* * Resets the DVD virtual machine and cache buffers. */ dvdnav_status_t dvdnav_reset(dvdnav_t *self); /* * Fills a pointer with a value pointing to a string describing * the path associated with an open dvdnav_t. It assigns *path to NULL * on error. */ dvdnav_status_t dvdnav_path(dvdnav_t *self, const char **path); /* * Returns a human-readable string describing the last error. */ const char* dvdnav_err_to_string(dvdnav_t *self); /********************************************************************* * changing and reading DVD player characteristics * *********************************************************************/ /* * These functions allow you to manipulate the various global characteristics * of the DVD playback engine. */ /* * Sets the region mask (bit 0 set implies region 1, bit 1 set implies * region 2, etc) of the virtual machine. Generally you will only need to set * this if you are playing RCE discs which query the virtual machine as to its * region setting. * * This has _nothing_ to do with the region setting of the DVD drive. */ dvdnav_status_t dvdnav_set_region_mask(dvdnav_t *self, int32_t region_mask); /* * Returns the region mask (bit 0 set implies region 1, bit 1 set implies * region 2, etc) of the virtual machine. * * This has _nothing_ to do with the region setting of the DVD drive. */ dvdnav_status_t dvdnav_get_region_mask(dvdnav_t *self, int32_t *region_mask); /* * Specify whether read-ahead caching should be used. You may not want this if your * decoding engine does its own buffering. * * The default read-ahead cache does not use an additional thread for the reading * (see read_cache.c for a threaded cache, but note that this code is currently * unmaintained). It prebuffers on VOBU level by reading ahead several buffers * on every read request. The speed of this prebuffering has been optimized to * also work on slow DVD drives. * * If in addition you want to prevent memcpy's to improve performance, have a look * at dvdnav_get_next_cache_block(). */ dvdnav_status_t dvdnav_set_readahead_flag(dvdnav_t *self, int32_t read_ahead_flag); /* * Query whether read-ahead caching/buffering will be used. */ dvdnav_status_t dvdnav_get_readahead_flag(dvdnav_t *self, int32_t *read_ahead_flag); /* * Specify whether the positioning works PGC or PG based. * Programs (PGs) on DVDs are similar to Chapters and a program chain (PGC) * usually covers a whole feature. This affects the behaviour of the * functions dvdnav_get_position() and dvdnav_sector_search(). See there. * Default is PG based positioning. */ dvdnav_status_t dvdnav_set_PGC_positioning_flag(dvdnav_t *self, int32_t pgc_based_flag); /* * Query whether positioning is PG or PGC based. */ dvdnav_status_t dvdnav_get_PGC_positioning_flag(dvdnav_t *self, int32_t *pgc_based_flag); /********************************************************************* * reading data * *********************************************************************/ /* * These functions are used to poll the playback engine and actually get data * off the DVD. */ /* * Attempts to get the next block off the DVD and copies it into the buffer 'buf'. * If there is any special actions that may need to be performed, the value * pointed to by 'event' gets set accordingly. * * If 'event' is DVDNAV_BLOCK_OK then 'buf' is filled with the next block * (note that means it has to be at /least/ 2048 bytes big). 'len' is * then set to 2048. * * Otherwise, buf is filled with an appropriate event structure and * len is set to the length of that structure. * * See the dvdnav_events.h header for information on the various events. */ dvdnav_status_t dvdnav_get_next_block(dvdnav_t *self, uint8_t *buf, int32_t *event, int32_t *len); /* * This basically does the same as dvdnav_get_next_block. The only difference is * that it avoids a memcopy, when the requested block was found in the cache. * In such a case (cache hit) this function will return a different pointer than * the one handed in, pointing directly into the relevant block in the cache. * Those pointers must _never_ be freed but instead returned to the library via * dvdnav_free_cache_block(). */ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *self, uint8_t **buf, int32_t *event, int32_t *len); /* * All buffers which came from the internal cache (when dvdnav_get_next_cache_block() * returned a buffer different from the one handed in) have to be freed with this * function. Although handing in other buffers not from the cache doesn't cause any harm. */ dvdnav_status_t dvdnav_free_cache_block(dvdnav_t *self, unsigned char *buf); /* * If we are currently in a still-frame this function skips it. * * See also the DVDNAV_STILL_FRAME event. */ dvdnav_status_t dvdnav_still_skip(dvdnav_t *self); /* * If we are currently in WAIT state, that is: the application is required to * wait for its fifos to become empty, calling this signals libdvdnav that this * is achieved and that it can continue. * * See also the DVDNAV_WAIT event. */ dvdnav_status_t dvdnav_wait_skip(dvdnav_t *self); /* * Returns the still time from the currently playing cell. * The still time is given in seconds with 0xff meaning an indefinite still. * * This function can be used to detect still frames before they are reached. * Some players might need this to prepare for a frame to be shown for a * longer time than usual. */ uint32_t dvdnav_get_next_still_flag(dvdnav_t *self); /* * Stops playback. The next event obtained with one of the get_next_block * functions will be a DVDNAV_STOP event. * * It is not required to call this before dvdnav_close(). */ dvdnav_status_t dvdnav_stop(dvdnav_t *self); /********************************************************************* * title/part navigation * *********************************************************************/ /* * Returns the number of titles on the disk. */ dvdnav_status_t dvdnav_get_number_of_titles(dvdnav_t *self, int32_t *titles); /* * Returns the number of parts within the given title. */ dvdnav_status_t dvdnav_get_number_of_parts(dvdnav_t *self, int32_t title, int32_t *parts); /* * Plays the specified title of the DVD from its beginning (that is: part 1). */ dvdnav_status_t dvdnav_title_play(dvdnav_t *self, int32_t title); /* * Plays the specified title, starting from the specified part. */ dvdnav_status_t dvdnav_part_play(dvdnav_t *self, int32_t title, int32_t part); /* * Plays the specified title, starting from the specified program */ dvdnav_status_t dvdnav_program_play(dvdnav_t *self, int32_t title, int32_t pgcn, int32_t pgn); /* * Stores in *times an array (that the application *must* free) of * dvdtimes corresponding to the chapter times for the chosen title. * *duration will have the duration of the title * The number of entries in *times is the result of the function. * On error *times is NULL and the output is 0 */ uint32_t dvdnav_describe_title_chapters(dvdnav_t *self, int32_t title, uint64_t **times, uint64_t *duration); /* * Play the specified amount of parts of the specified title of * the DVD then STOP. * * Currently unimplemented! */ dvdnav_status_t dvdnav_part_play_auto_stop(dvdnav_t *self, int32_t title, int32_t part, int32_t parts_to_play); /* * Play the specified title starting from the specified time. * * Currently unimplemented! */ dvdnav_status_t dvdnav_time_play(dvdnav_t *self, int32_t title, uint64_t time); /* * Stop playing the current position and jump to the specified menu. * * See also DVDMenuID_t from libdvdread */ dvdnav_status_t dvdnav_menu_call(dvdnav_t *self, DVDMenuID_t menu); /* * Return the title number and part currently being played. * A title of 0 indicates we are in a menu. In this case, part * is set to the current menu's ID. */ dvdnav_status_t dvdnav_current_title_info(dvdnav_t *self, int32_t *title, int32_t *part); /* * Return the title number, pgcn and pgn currently being played. * A title of 0 indicates, we are in a menu. */ dvdnav_status_t dvdnav_current_title_program(dvdnav_t *self, int32_t *title, int32_t *pgcn, int32_t *pgn); /* * Return the current position (in blocks) within the current * title and the length (in blocks) of said title. * * Current implementation is wrong and likely to behave unpredictably! * Use is discouraged! */ dvdnav_status_t dvdnav_get_position_in_title(dvdnav_t *self, uint32_t *pos, uint32_t *len); /* * This function is only available for compatibility reasons. * * Stop playing the current position and start playback of the current title * from the specified part. */ dvdnav_status_t dvdnav_part_search(dvdnav_t *self, int32_t part); /********************************************************************* * program chain/program navigation * *********************************************************************/ /* * Stop playing the current position and start playback from the last * VOBU boundary before the given sector. The sector number is not * meant to be an absolute physical DVD sector, but a relative sector * in the current program. This function cannot leave the current * program and will fail if asked to do so. * * If program chain based positioning is enabled * (see dvdnav_set_PGC_positioning_flag()), this will seek to the relative * sector inside the current program chain. * * 'origin' can be one of SEEK_SET, SEEK_CUR, SEEK_END as defined in * fcntl.h. */ dvdnav_status_t dvdnav_sector_search(dvdnav_t *self, int64_t offset, int32_t origin); /* returns the current stream time in PTS ticks as reported by the IFO structures divide it by 90000 to get the current play time in seconds */ int64_t dvdnav_get_current_time(dvdnav_t *self); /* * Stop playing the current position and start playback of the title * from the specified timecode. * * Currently implemented using interpolation. That interpolation is slightly * inaccurate. */ dvdnav_status_t dvdnav_time_search(dvdnav_t *self, uint64_t time); /* * Stop playing current position and play the "GoUp"-program chain. * (which generally leads to the title menu or a higher-level menu). */ dvdnav_status_t dvdnav_go_up(dvdnav_t *self); /* * Stop playing the current position and start playback at the * previous program (if it exists). */ dvdnav_status_t dvdnav_prev_pg_search(dvdnav_t *self); /* * Stop playing the current position and start playback at the * first program. */ dvdnav_status_t dvdnav_top_pg_search(dvdnav_t *self); /* * Stop playing the current position and start playback at the * next program (if it exists). */ dvdnav_status_t dvdnav_next_pg_search(dvdnav_t *self); /* * Return the current position (in blocks) within the current * program and the length (in blocks) of current program. * * If program chain based positioning is enabled * (see dvdnav_set_PGC_positioning_flag()), this will return the * relative position in and the length of the current program chain. */ dvdnav_status_t dvdnav_get_position(dvdnav_t *self, uint32_t *pos, uint32_t *len); /********************************************************************* * menu highlights * *********************************************************************/ /* * Most functions related to highlights take a NAV PCI packet as a parameter. * While you can get such a packet from libdvdnav, this will result in * errors for players with internal FIFOs because due to the FIFO length, * libdvdnav will be ahead in the stream compared to what the user is * seeing on screen. Therefore, player applications who have a NAV * packet available, which is better in sync with the actual playback, * should always pass this one to these functions. */ /* * Get the currently highlighted button * number (1..36) or 0 if no button is highlighted. */ dvdnav_status_t dvdnav_get_current_highlight(dvdnav_t *self, int32_t *button); /* * Returns the Presentation Control Information (PCI) structure associated * with the current position. * * Read the general notes above. * See also libdvdreads nav_types.h for definition of pci_t. */ pci_t* dvdnav_get_current_nav_pci(dvdnav_t *self); /* * Returns the DSI (data search information) structure associated * with the current position. * * Read the general notes above. * See also libdvdreads nav_types.h for definition of dsi_t. */ dsi_t* dvdnav_get_current_nav_dsi(dvdnav_t *self); /* * Get the area associated with a certain button. */ dvdnav_status_t dvdnav_get_highlight_area(pci_t *nav_pci , int32_t button, int32_t mode, dvdnav_highlight_area_t *highlight); /* * Move button highlight around as suggested by function name (e.g. with arrow keys). */ dvdnav_status_t dvdnav_upper_button_select(dvdnav_t *self, pci_t *pci); dvdnav_status_t dvdnav_lower_button_select(dvdnav_t *self, pci_t *pci); dvdnav_status_t dvdnav_right_button_select(dvdnav_t *self, pci_t *pci); dvdnav_status_t dvdnav_left_button_select(dvdnav_t *self, pci_t *pci); /* * Activate ("press") the currently highlighted button. */ dvdnav_status_t dvdnav_button_activate(dvdnav_t *self, pci_t *pci); /* * Highlight a specific button. */ dvdnav_status_t dvdnav_button_select(dvdnav_t *self, pci_t *pci, int32_t button); /* * Activate ("press") specified button. */ dvdnav_status_t dvdnav_button_select_and_activate(dvdnav_t *self, pci_t *pci, int32_t button); /* * Activate ("press") a button and execute specified command. */ dvdnav_status_t dvdnav_button_activate_cmd(dvdnav_t *self, int32_t button, vm_cmd_t *cmd); /* * Select button at specified video frame coordinates. */ dvdnav_status_t dvdnav_mouse_select(dvdnav_t *self, pci_t *pci, int32_t x, int32_t y); /* * Activate ("press") button at specified video frame coordinates. */ dvdnav_status_t dvdnav_mouse_activate(dvdnav_t *self, pci_t *pci, int32_t x, int32_t y); /********************************************************************* * languages * *********************************************************************/ /* * The language codes expected by these functions are two character * codes as defined in ISO639. */ /* * Set which menu language we should use per default. */ dvdnav_status_t dvdnav_menu_language_select(dvdnav_t *self, char *code); /* * Set which audio language we should use per default. */ dvdnav_status_t dvdnav_audio_language_select(dvdnav_t *self, char *code); /* * Set which spu language we should use per default. */ dvdnav_status_t dvdnav_spu_language_select(dvdnav_t *self, char *code); /********************************************************************* * obtaining stream attributes * *********************************************************************/ /* * Return a string describing the title of the DVD. * This is an ID string encoded on the disc by the author. In many cases * this is a descriptive string such as `THE_MATRIX' but sometimes is singularly * uninformative such as `PDVD-011421'. Some DVD authors even forget to set this, * so you may also read the default of the authoring software they used, like * `DVDVolume'. */ dvdnav_status_t dvdnav_get_title_string(dvdnav_t *self, const char **title_str); /* * Returns a string containing the serial number of the DVD. * This has a max of 15 characters and should be more unique than the * title string. */ dvdnav_status_t dvdnav_get_serial_string(dvdnav_t *self, const char **serial_str); /* * Get video aspect code. * The aspect code does only change on VTS boundaries. * See the DVDNAV_VTS_CHANGE event. * * 0 -- 4:3, 2 -- 16:9 */ uint8_t dvdnav_get_video_aspect(dvdnav_t *self); /* * Get video resolution. */ int dvdnav_get_video_resolution(dvdnav_t *self, uint32_t *width, uint32_t *height); /* * Get video scaling permissions. * The scaling permission does only change on VTS boundaries. * See the DVDNAV_VTS_CHANGE event. * * bit0 set = deny letterboxing, bit1 set = deny pan&scan */ uint8_t dvdnav_get_video_scale_permission(dvdnav_t *self); /* * Converts a *logical* audio stream id into language code * (returns 0xffff if no such stream). */ uint16_t dvdnav_audio_stream_to_lang(dvdnav_t *self, uint8_t stream); /* * Returns the format of *logical* audio stream 'stream' * (returns 0xffff if no such stream). */ uint16_t dvdnav_audio_stream_format(dvdnav_t *self, uint8_t stream); /* * Returns number of channels in *logical* audio stream 'stream' * (returns 0xffff if no such stream). */ uint16_t dvdnav_audio_stream_channels(dvdnav_t *self, uint8_t stream); /* * Converts a *logical* subpicture stream id into country code * (returns 0xffff if no such stream). */ uint16_t dvdnav_spu_stream_to_lang(dvdnav_t *self, uint8_t stream); /* * Converts a *physical* (MPEG) audio stream id into a logical stream number. */ int8_t dvdnav_get_audio_logical_stream(dvdnav_t *self, uint8_t audio_num); #define HAVE_GET_AUDIO_ATTR /* * Get audio attr */ dvdnav_status_t dvdnav_get_audio_attr(dvdnav_t *self, uint8_t audio_mum, audio_attr_t *audio_attr); /* * Converts a *physical* (MPEG) subpicture stream id into a logical stream number. */ int8_t dvdnav_get_spu_logical_stream(dvdnav_t *self, uint8_t subp_num); #define HAVE_GET_SPU_ATTR /* * Get spu attr */ dvdnav_status_t dvdnav_get_spu_attr(dvdnav_t *self, uint8_t audio_mum, subp_attr_t *subp_attr); /* * Get active audio stream. */ int8_t dvdnav_get_active_audio_stream(dvdnav_t *self); /* * Get active spu stream. */ int8_t dvdnav_get_active_spu_stream(dvdnav_t *self); /* * Get the set of user operations that are currently prohibited. * There are potentially new restrictions right after * DVDNAV_CHANNEL_HOP and DVDNAV_NAV_PACKET. */ user_ops_t dvdnav_get_restrictions(dvdnav_t *self); /********************************************************************* * multiple angles * *********************************************************************/ /* * The libdvdnav library abstracts away the difference between seamless and * non-seamless angles. From the point of view of the programmer you just set the * angle number and all is well in the world. You will always see only the * selected angle coming from the get_next_block functions. * * Note: * It is quite possible that some tremendously strange DVD feature might change the * angle number from under you. Generally you should always view the results from * dvdnav_get_angle_info() as definitive only up to the next time you call * dvdnav_get_next_block(). */ /* * Sets the current angle. If you try to follow a non existent angle * the call fails. */ dvdnav_status_t dvdnav_angle_change(dvdnav_t *self, int32_t angle); /* * Returns the current angle and number of angles present. */ dvdnav_status_t dvdnav_get_angle_info(dvdnav_t *self, int32_t *current_angle, int32_t *number_of_angles); /********************************************************************* * domain queries * *********************************************************************/ /* * Are we in the First Play domain? */ int8_t dvdnav_is_domain_fp(dvdnav_t *self); /* * Are we in the Video management Menu domain? */ int8_t dvdnav_is_domain_vmgm(dvdnav_t *self); /* * Are we in the Video Title Menu domain? */ int8_t dvdnav_is_domain_vtsm(dvdnav_t *self); /* * Are we in the Video Title Set domain? */ int8_t dvdnav_is_domain_vts(dvdnav_t *self); #ifdef __cplusplus } #endif #endif /* LIBDVDNAV_DVDNAV_H */ k9copy/src/libdvdnav-NOW/dvdnav/dvd_types.h0000644000175000017550000002025512412277736021417 0ustar emulatoremulator/* * Copyright (C) 2000, 2001 Björn Englund, Håkan Hjort * * This file is part of libdvdnav, a DVD navigation library. It is a modified * file originally part of the Ogle DVD player project. * * libdvdnav is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdnav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdnav; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* * Various useful structs and enums for DVDs. */ #ifndef LIBDVDNAV_DVD_TYPES_H #define LIBDVDNAV_DVD_TYPES_H #include /* * DVD Menu ID * (see dvdnav_menu_call()) */ typedef enum { /* When used in VTS domain, DVD_MENU_Escape behaves like DVD_MENU_Root, * but from within a menu domain, DVD_MENU_Escape resumes playback. */ DVD_MENU_Escape = 0, DVD_MENU_Title = 2, DVD_MENU_Root = 3, DVD_MENU_Subpicture = 4, DVD_MENU_Audio = 5, DVD_MENU_Angle = 6, DVD_MENU_Part = 7 } DVDMenuID_t; /* Domain */ typedef enum { DVD_DOMAIN_FirstPlay = 1, /* First Play Domain */ DVD_DOMAIN_VTSTitle = 2, /* Video Title Set Domain */ DVD_DOMAIN_VMGM = 4, /* Video Manager Domain */ DVD_DOMAIN_VTSMenu = 8 /* Video Title Set Menu Domain */ } DVDDomain_t; /* * Structure containing info on highlight areas * (see dvdnav_get_highlight_area()) */ typedef struct { uint32_t palette; /* The CLUT entries for the highlight palette (4-bits per entry -> 4 entries) */ uint16_t sx,sy,ex,ey; /* The start/end x,y positions */ uint32_t pts; /* Highlight PTS to match with SPU */ /* button number for the SPU decoder/overlaying engine */ uint32_t buttonN; } dvdnav_highlight_area_t; /* The audio format */ typedef enum { DVD_AUDIO_FORMAT_AC3 = 0, DVD_AUDIO_FORMAT_UNKNOWN_1 = 1, DVD_AUDIO_FORMAT_MPEG = 2, DVD_AUDIO_FORMAT_MPEG2_EXT = 3, DVD_AUDIO_FORMAT_LPCM = 4, DVD_AUDIO_FORMAT_UNKNOWN_5 = 5, DVD_AUDIO_FORMAT_DTS = 6, DVD_AUDIO_FORMAT_SDDS = 7 } DVDAudioFormat_t; /* the following types are currently unused */ #if 0 /* User operation permissions */ typedef enum { UOP_FLAG_TitleOrTimePlay = 0x00000001, UOP_FLAG_ChapterSearchOrPlay = 0x00000002, UOP_FLAG_TitlePlay = 0x00000004, UOP_FLAG_Stop = 0x00000008, UOP_FLAG_GoUp = 0x00000010, UOP_FLAG_TimeOrChapterSearch = 0x00000020, UOP_FLAG_PrevOrTopPGSearch = 0x00000040, UOP_FLAG_NextPGSearch = 0x00000080, UOP_FLAG_ForwardScan = 0x00000100, UOP_FLAG_BackwardScan = 0x00000200, UOP_FLAG_TitleMenuCall = 0x00000400, UOP_FLAG_RootMenuCall = 0x00000800, UOP_FLAG_SubPicMenuCall = 0x00001000, UOP_FLAG_AudioMenuCall = 0x00002000, UOP_FLAG_AngleMenuCall = 0x00004000, UOP_FLAG_ChapterMenuCall = 0x00008000, UOP_FLAG_Resume = 0x00010000, UOP_FLAG_ButtonSelectOrActivate = 0x00020000, UOP_FLAG_StillOff = 0x00040000, UOP_FLAG_PauseOn = 0x00080000, UOP_FLAG_AudioStreamChange = 0x00100000, UOP_FLAG_SubPicStreamChange = 0x00200000, UOP_FLAG_AngleChange = 0x00400000, UOP_FLAG_KaraokeAudioPresModeChange = 0x00800000, UOP_FLAG_VideoPresModeChange = 0x01000000 } DVDUOP_t; /* Parental Level */ typedef enum { DVD_PARENTAL_LEVEL_1 = 1, DVD_PARENTAL_LEVEL_2 = 2, DVD_PARENTAL_LEVEL_3 = 3, DVD_PARENTAL_LEVEL_4 = 4, DVD_PARENTAL_LEVEL_5 = 5, DVD_PARENTAL_LEVEL_6 = 6, DVD_PARENTAL_LEVEL_7 = 7, DVD_PARENTAL_LEVEL_8 = 8, DVD_PARENTAL_LEVEL_None = 15 } DVDParentalLevel_t; /* Language ID (ISO-639 language code) */ typedef uint16_t DVDLangID_t; /* Country ID (ISO-3166 country code) */ typedef uint16_t DVDCountryID_t; /* Register */ typedef uint16_t DVDRegister_t; typedef enum { DVDFalse = 0, DVDTrue = 1 } DVDBool_t; typedef DVDRegister_t DVDGPRMArray_t[16]; typedef DVDRegister_t DVDSPRMArray_t[24]; /* Navigation */ typedef int DVDStream_t; typedef int DVDPTT_t; typedef int DVDTitle_t; /* Angle number (1-9 or default?) */ typedef int DVDAngle_t; /* Timecode */ typedef struct { uint8_t Hours; uint8_t Minutes; uint8_t Seconds; uint8_t Frames; } DVDTimecode_t; /* Subpicture stream number (0-31,62,63) */ typedef int DVDSubpictureStream_t; /* Audio stream number (0-7, 15(none)) */ typedef int DVDAudioStream_t; /* The audio application mode */ typedef enum { DVD_AUDIO_APP_MODE_None = 0, DVD_AUDIO_APP_MODE_Karaoke = 1, DVD_AUDIO_APP_MODE_Surround = 2, DVD_AUDIO_APP_MODE_Other = 3 } DVDAudioAppMode_t; /* Audio language extension */ typedef enum { DVD_AUDIO_LANG_EXT_NotSpecified = 0, DVD_AUDIO_LANG_EXT_NormalCaptions = 1, DVD_AUDIO_LANG_EXT_VisuallyImpaired = 2, DVD_AUDIO_LANG_EXT_DirectorsComments1 = 3, DVD_AUDIO_LANG_EXT_DirectorsComments2 = 4 } DVDAudioLangExt_t; /* Subpicture language extension */ typedef enum { DVD_SUBPICTURE_LANG_EXT_NotSpecified = 0, DVD_SUBPICTURE_LANG_EXT_NormalCaptions = 1, DVD_SUBPICTURE_LANG_EXT_BigCaptions = 2, DVD_SUBPICTURE_LANG_EXT_ChildrensCaptions = 3, DVD_SUBPICTURE_LANG_EXT_NormalCC = 5, DVD_SUBPICTURE_LANG_EXT_BigCC = 6, DVD_SUBPICTURE_LANG_EXT_ChildrensCC = 7, DVD_SUBPICTURE_LANG_EXT_Forced = 9, DVD_SUBPICTURE_LANG_EXT_NormalDirectorsComments = 13, DVD_SUBPICTURE_LANG_EXT_BigDirectorsComments = 14, DVD_SUBPICTURE_LANG_EXT_ChildrensDirectorsComments = 15, } DVDSubpictureLangExt_t; /* Karaoke Downmix mode */ typedef enum { DVD_KARAOKE_DOWNMIX_0to0 = 0x0001, DVD_KARAOKE_DOWNMIX_1to0 = 0x0002, DVD_KARAOKE_DOWNMIX_2to0 = 0x0004, DVD_KARAOKE_DOWNMIX_3to0 = 0x0008, DVD_KARAOKE_DOWNMIX_4to0 = 0x0010, DVD_KARAOKE_DOWNMIX_Lto0 = 0x0020, DVD_KARAOKE_DOWNMIX_Rto0 = 0x0040, DVD_KARAOKE_DOWNMIX_0to1 = 0x0100, DVD_KARAOKE_DOWNMIX_1to1 = 0x0200, DVD_KARAOKE_DOWNMIX_2to1 = 0x0400, DVD_KARAOKE_DOWNMIX_3to1 = 0x0800, DVD_KARAOKE_DOWNMIX_4to1 = 0x1000, DVD_KARAOKE_DOWNMIX_Lto1 = 0x2000, DVD_KARAOKE_DOWNMIX_Rto1 = 0x4000 } DVDKaraokeDownmix_t; typedef int DVDKaraokeDownmixMask_t; /* Display mode */ typedef enum { DVD_DISPLAY_MODE_ContentDefault = 0, DVD_DISPLAY_MODE_16x9 = 1, DVD_DISPLAY_MODE_4x3PanScan = 2, DVD_DISPLAY_MODE_4x3Letterboxed = 3 } DVDDisplayMode_t; /* Audio attributes */ typedef struct { DVDAudioAppMode_t AppMode; DVDAudioFormat_t AudioFormat; DVDLangID_t Language; DVDAudioLangExt_t LanguageExtension; DVDBool_t HasMultichannelInfo; DVDAudioSampleFreq_t SampleFrequency; DVDAudioSampleQuant_t SampleQuantization; DVDChannelNumber_t NumberOfChannels; } DVDAudioAttributes_t; typedef int DVDAudioSampleFreq_t; typedef int DVDAudioSampleQuant_t; typedef int DVDChannelNumber_t; /* Subpicture attributes */ typedef enum { DVD_SUBPICTURE_TYPE_NotSpecified = 0, DVD_SUBPICTURE_TYPE_Language = 1, DVD_SUBPICTURE_TYPE_Other = 2 } DVDSubpictureType_t; typedef enum { DVD_SUBPICTURE_CODING_RunLength = 0, DVD_SUBPICTURE_CODING_Extended = 1, DVD_SUBPICTURE_CODING_Other = 2 } DVDSubpictureCoding_t; typedef struct { DVDSubpictureType_t Type; DVDSubpictureCoding_t CodingMode; DVDLangID_t Language; DVDSubpictureLangExt_t LanguageExtension; } DVDSubpictureAttributes_t; /* Video attributes */ typedef struct { DVDBool_t PanscanPermitted; DVDBool_t LetterboxPermitted; int AspectX; int AspectY; int FrameRate; int FrameHeight; DVDVideoCompression_t Compression; DVDBool_t Line21Field1InGop; DVDBool_t Line21Field2InGop; int more_to_come; } DVDVideoAttributes_t; typedef int DVDVideoCompression_t; #endif #endif /* LIBDVDNAV_DVD_TYPES_H */ k9copy/src/libdvdnav-NOW/vm/0000755000175000017550000000000012412277736016401 5ustar emulatoremulatork9copy/src/libdvdnav-NOW/vm/vmcmd.h0000644000175000017550000000207612412277736017665 0ustar emulatoremulator/* * Copyright (C) 2000, 2001 Martin Norbäck, Håkan Hjort * * This file is part of libdvdnav, a DVD navigation library. It is modified * from a file originally part of the Ogle DVD player. * * libdvdnav is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdnav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdnav; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef LIBDVDNAV_VMCMD_H #define LIBDVDNAV_VMCMD_H void vm_print_mnemonic(vm_cmd_t *command); void vm_print_cmd(int row, vm_cmd_t *command); #endif /* LIBDVDNAV_VMCMD_H */ k9copy/src/libdvdnav-NOW/vm/vmget.c0000644000175000017550000002276412412277736017702 0ustar emulatoremulator/* * Copyright (C) 2000, 2001 Håkan Hjort * Copyright (C) 2001 Rich Wareham * 2002-2004 the dvdnav project * * This file is part of libdvdnav, a DVD navigation library. It is modified * from a file originally part of the Ogle DVD player. * * libdvdnav is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdnav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdnav; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include "dvdnav/dvdnav.h" #include "decoder.h" #include "vm.h" #include "getset.h" #include "dvdnav_internal.h" /* getting information */ int vm_get_current_menu(vm_t *vm, int *menuid) { pgcit_t* pgcit; int pgcn; pgcn = (vm->state).pgcN; pgcit = get_PGCIT(vm); if(pgcit==NULL) return 0; *menuid = pgcit->pgci_srp[pgcn - 1].entry_id & 0xf ; return 1; } int vm_get_current_title_part(vm_t *vm, int *title_result, int *part_result) { vts_ptt_srpt_t *vts_ptt_srpt; int title, part = 0, vts_ttn; int found; int16_t pgcN, pgN; vts_ptt_srpt = vm->vtsi->vts_ptt_srpt; pgcN = get_PGCN(vm); pgN = vm->state.pgN; found = 0; for (vts_ttn = 0; (vts_ttn < vts_ptt_srpt->nr_of_srpts) && !found; vts_ttn++) { for (part = 0; (part < vts_ptt_srpt->title[vts_ttn].nr_of_ptts) && !found; part++) { if (vts_ptt_srpt->title[vts_ttn].ptt[part].pgcn == pgcN) { if (vts_ptt_srpt->title[vts_ttn].ptt[part].pgn == pgN) { found = 1; break; } if (part > 0 && vts_ptt_srpt->title[vts_ttn].ptt[part].pgn > pgN && vts_ptt_srpt->title[vts_ttn].ptt[part - 1].pgn < pgN) { part--; found = 1; break; } } } if (found) break; } vts_ttn++; part++; if (!found) { fprintf(MSG_OUT, "libdvdnav: chapter NOT FOUND!\n"); return 0; } title = get_TT(vm, vm->state.vtsN, vts_ttn); #ifdef TRACE if (title) { fprintf(MSG_OUT, "libdvdnav: ************ this chapter FOUND!\n"); fprintf(MSG_OUT, "libdvdnav: VTS_PTT_SRPT - Title %3i part %3i: PGC: %3i PG: %3i\n", title, part, vts_ptt_srpt->title[vts_ttn-1].ptt[part-1].pgcn , vts_ptt_srpt->title[vts_ttn-1].ptt[part-1].pgn ); } #endif *title_result = title; *part_result = part; return 1; } /* Return the substream id for 'logical' audio stream audioN. * 0 <= audioN < 8 */ int vm_get_audio_stream(vm_t *vm, int audioN) { int streamN = -1; if((vm->state).domain != DVD_DOMAIN_VTSTitle) audioN = 0; if(audioN < 8) { /* Is there any control info for this logical stream */ if((vm->state).pgc->audio_control[audioN] & (1<<15)) { streamN = ((vm->state).pgc->audio_control[audioN] >> 8) & 0x07; } } if((vm->state).domain != DVD_DOMAIN_VTSTitle && streamN == -1) streamN = 0; /* FIXME: Should also check in vtsi/vmgi status what kind of stream * it is (ac3/lpcm/dts/sdds...) to find the right (sub)stream id */ return streamN; } /* Return the substream id for 'logical' subpicture stream subpN and given mode. * 0 <= subpN < 32 * mode == 0 - widescreen * mode == 1 - letterbox * mode == 2 - pan&scan */ int vm_get_subp_stream(vm_t *vm, int subpN, int mode) { int streamN = -1; int source_aspect = vm_get_video_aspect(vm); if((vm->state).domain != DVD_DOMAIN_VTSTitle) subpN = 0; if(subpN < 32) { /* a valid logical stream */ /* Is this logical stream present */ if((vm->state).pgc->subp_control[subpN] & (1<<31)) { if(source_aspect == 0) /* 4:3 */ streamN = ((vm->state).pgc->subp_control[subpN] >> 24) & 0x1f; if(source_aspect == 3) /* 16:9 */ switch (mode) { case 0: streamN = ((vm->state).pgc->subp_control[subpN] >> 16) & 0x1f; break; case 1: streamN = ((vm->state).pgc->subp_control[subpN] >> 8) & 0x1f; break; case 2: streamN = (vm->state).pgc->subp_control[subpN] & 0x1f; } } } if((vm->state).domain != DVD_DOMAIN_VTSTitle && streamN == -1) streamN = 0; /* FIXME: Should also check in vtsi/vmgi status what kind of stream it is. */ return streamN; } int vm_get_audio_active_stream(vm_t *vm) { int audioN; int streamN; audioN = (vm->state).AST_REG ; streamN = vm_get_audio_stream(vm, audioN); /* If no such stream, then select the first one that exists. */ if(streamN == -1) { for(audioN = 0; audioN < 8; audioN++) { if((vm->state).pgc->audio_control[audioN] & (1<<15)) { if ((streamN = vm_get_audio_stream(vm, audioN)) >= 0) break; } } } return streamN; } int vm_get_subp_active_stream(vm_t *vm, int mode) { int subpN; int streamN; subpN = (vm->state).SPST_REG & ~0x40; streamN = vm_get_subp_stream(vm, subpN, mode); /* If no such stream, then select the first one that exists. */ if(streamN == -1) { for(subpN = 0; subpN < 32; subpN++) { if((vm->state).pgc->subp_control[subpN] & (1<<31)) { if ((streamN = vm_get_subp_stream(vm, subpN, mode)) >= 0) break; } } } if((vm->state).domain == DVD_DOMAIN_VTSTitle && !((vm->state).SPST_REG & 0x40)) /* Bit 7 set means hide, and only let Forced display show */ return (streamN | 0x80); else return streamN; } void vm_get_angle_info(vm_t *vm, int *current, int *num_avail) { *num_avail = 1; *current = 1; if((vm->state).domain == DVD_DOMAIN_VTSTitle) { title_info_t *title; /* TTN_REG does not allways point to the correct title.. */ if((vm->state).TTN_REG > vm->vmgi->tt_srpt->nr_of_srpts) return; title = &vm->vmgi->tt_srpt->title[(vm->state).TTN_REG - 1]; if(title->title_set_nr != (vm->state).vtsN || title->vts_ttn != (vm->state).VTS_TTN_REG) return; *num_avail = title->nr_of_angles; *current = (vm->state).AGL_REG; } } #if 0 /* currently unused */ void vm_get_audio_info(vm_t *vm, int *current, int *num_avail) { switch ((vm->state).domain) { case DVD_DOMAIN_VTSTitle: *num_avail = vm->vtsi->vtsi_mat->nr_of_vts_audio_streams; *current = (vm->state).AST_REG; break; case DVD_DOMAIN_VTSMenu: *num_avail = vm->vtsi->vtsi_mat->nr_of_vtsm_audio_streams; /* 1 */ *current = 1; break; case DVD_DOMAIN_VMGM: case DVD_DOMAIN_FirstPlay: *num_avail = vm->vmgi->vmgi_mat->nr_of_vmgm_audio_streams; /* 1 */ *current = 1; break; } } /* currently unused */ void vm_get_subp_info(vm_t *vm, int *current, int *num_avail) { switch ((vm->state).domain) { case DVD_DOMAIN_VTSTitle: *num_avail = vm->vtsi->vtsi_mat->nr_of_vts_subp_streams; *current = (vm->state).SPST_REG; break; case DVD_DOMAIN_VTSMenu: *num_avail = vm->vtsi->vtsi_mat->nr_of_vtsm_subp_streams; /* 1 */ *current = 0x41; break; case DVD_DOMAIN_VMGM: case DVD_DOMAIN_FirstPlay: *num_avail = vm->vmgi->vmgi_mat->nr_of_vmgm_subp_streams; /* 1 */ *current = 0x41; break; } } #endif void vm_get_video_res(vm_t *vm, int *width, int *height) { video_attr_t attr = vm_get_video_attr(vm); if(attr.video_format != 0) *height = 576; else *height = 480; switch(attr.picture_size) { case 0: *width = 720; break; case 1: *width = 704; break; case 2: *width = 352; break; case 3: *width = 352; *height /= 2; break; } } int vm_get_video_aspect(vm_t *vm) { int aspect = vm_get_video_attr(vm).display_aspect_ratio; if(aspect != 0 && aspect != 3) { fprintf(MSG_OUT, "libdvdnav: display aspect ratio is unexpected: %d!\n", aspect); return -1; } (vm->state).registers.SPRM[14] &= ~(0x3 << 10); (vm->state).registers.SPRM[14] |= aspect << 10; return aspect; } int vm_get_video_scale_permission(vm_t *vm) { return vm_get_video_attr(vm).permitted_df; } video_attr_t vm_get_video_attr(vm_t *vm) { switch ((vm->state).domain) { case DVD_DOMAIN_VTSTitle: return vm->vtsi->vtsi_mat->vts_video_attr; case DVD_DOMAIN_VTSMenu: return vm->vtsi->vtsi_mat->vtsm_video_attr; case DVD_DOMAIN_VMGM: case DVD_DOMAIN_FirstPlay: return vm->vmgi->vmgi_mat->vmgm_video_attr; default: assert(0); } } audio_attr_t vm_get_audio_attr(vm_t *vm, int streamN) { switch ((vm->state).domain) { case DVD_DOMAIN_VTSTitle: return vm->vtsi->vtsi_mat->vts_audio_attr[streamN]; case DVD_DOMAIN_VTSMenu: return vm->vtsi->vtsi_mat->vtsm_audio_attr; case DVD_DOMAIN_VMGM: case DVD_DOMAIN_FirstPlay: return vm->vmgi->vmgi_mat->vmgm_audio_attr; default: assert(0); } } subp_attr_t vm_get_subp_attr(vm_t *vm, int streamN) { switch ((vm->state).domain) { case DVD_DOMAIN_VTSTitle: return vm->vtsi->vtsi_mat->vts_subp_attr[streamN]; case DVD_DOMAIN_VTSMenu: return vm->vtsi->vtsi_mat->vtsm_subp_attr; case DVD_DOMAIN_VMGM: case DVD_DOMAIN_FirstPlay: return vm->vmgi->vmgi_mat->vmgm_subp_attr; default: assert(0); } } k9copy/src/libdvdnav-NOW/vm/getset.h0000644000175000017550000000351112412277736020045 0ustar emulatoremulator/* * Copyright (C) 2000, 2001 Håkan Hjort * Copyright (C) 2001 Rich Wareham * 2002-2004 the dvdnav project * * This file is part of libdvdnav, a DVD navigation library. It is modified * from a file originally part of the Ogle DVD player. * * libdvdnav is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdnav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdnav; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* get_XYZ returns a value. * set_XYZ sets state using passed parameters. * returns success/failure. */ /* Set */ int set_TT(vm_t *vm, int tt); int set_PTT(vm_t *vm, int tt, int ptt); int set_VTS_TT(vm_t *vm, int vtsN, int vts_ttn); int set_VTS_PTT(vm_t *vm, int vtsN, int vts_ttn, int part); int set_PROG(vm_t *vm, int tt, int pgcn, int pgn); int set_VTS_PROG(vm_t *vm, int vtsN, int vts_ttn, int pgcn, int pgn); int set_FP_PGC(vm_t *vm); int set_MENU(vm_t *vm, int menu); int set_PGCN(vm_t *vm, int pgcN); int set_PGN(vm_t *vm); /* Set PGN based on (vm->state).CellN */ void set_RSMinfo(vm_t *vm, int cellN, int blockN); /* Get */ int get_TT(vm_t *vm, int vtsN, int vts_ttn); int get_ID(vm_t *vm, int id); int get_PGCN(vm_t *vm); pgcit_t* get_MENU_PGCIT(vm_t *vm, ifo_handle_t *h, uint16_t lang); pgcit_t* get_PGCIT(vm_t *vm); k9copy/src/libdvdnav-NOW/vm/vmcmd.c0000644000175000017550000003771312412277736017666 0ustar emulatoremulator/* * Copyright (C) 2000, 2001 Martin Norbäck, Håkan Hjort * 2002-2004 the dvdnav project * * This file is part of libdvdnav, a DVD navigation library. It is modified * from a file originally part of the Ogle DVD player. * * libdvdnav is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdnav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdnav; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "dvdnav/dvdnav.h" #include #include #include "decoder.h" #include "vm.h" #include "vmcmd.h" #include "dvdnav_internal.h" /* freebsd compatibility */ #ifndef PRIu8 #define PRIu8 "d" #endif /* freebsd compatibility */ #ifndef PRIu16 #define PRIu16 "d" #endif static const char cmp_op_table[][4] = { "", "&", "==", "!=", ">=", ">", "<=", "<" }; static const char set_op_table[][4] = { "", "=", "<->", "+=", "-=", "*=", "/=", "%=", "rnd", "&=", "|=", "^=" }; static const char link_table[][16] = { "LinkNoLink", "LinkTopC", "LinkNextC", "LinkPrevC", "", "LinkTopPG", "LinkNextPG", "LinkPrevPG", "", "LinkTopPGC", "LinkNextPGC", "LinkPrevPGC", "LinkGoUpPGC", "LinkTailPGC", "", "", "RSM" }; static const char *const system_reg_table[] = { "Menu Description Language Code", "Audio Stream Number", "Sub-picture Stream Number", "Angle Number", "Title Track Number", "VTS Title Track Number", "VTS PGC Number", "PTT Number for One_Sequential_PGC_Title", "Highlighted Button Number", "Navigation Timer", "Title PGC Number for Navigation Timer", "Audio Mixing Mode for Karaoke", "Country Code for Parental Management", "Parental Level", "Player Configurations for Video", "Player Configurations for Audio", "Initial Language Code for Audio", "Initial Language Code Extension for Audio", "Initial Language Code for Sub-picture", "Initial Language Code Extension for Sub-picture", "Player Regional Code", "Reserved 21", "Reserved 22", "Reserved 23" }; static const char system_reg_abbr_table[][8] = { "", "ASTN", "SPSTN", "AGLN", "TTN", "VTS_TTN", "TT_PGCN", "PTTN", "HL_BTNN", "NVTMR", "NV_PGCN", "", "CC_PLT", "PLT", "", "", "", "", "", "", "", "", "", "", }; static void print_system_reg(uint16_t reg) { if(reg < sizeof(system_reg_abbr_table) / sizeof(system_reg_abbr_table[0])) fprintf(MSG_OUT, "%s (SRPM:%d)", system_reg_table[reg], reg); else fprintf(MSG_OUT, " WARNING: Unknown system register ( reg=%d ) ", reg); } static void print_g_reg(uint8_t reg) { if(reg < 16) fprintf(MSG_OUT, "g[%" PRIu8 "]", reg); else fprintf(MSG_OUT, " WARNING: Unknown general register "); } static void print_reg(uint8_t reg) { if(reg & 0x80) print_system_reg(reg & 0x7f); else print_g_reg(reg & 0x7f); } static void print_cmp_op(uint8_t op) { if(op < sizeof(cmp_op_table) / sizeof(cmp_op_table[0])) fprintf(MSG_OUT, " %s ", cmp_op_table[op]); else fprintf(MSG_OUT, " WARNING: Unknown compare op "); } static void print_set_op(uint8_t op) { if(op < sizeof(set_op_table) / sizeof(cmp_op_table[0])) fprintf(MSG_OUT, " %s ", set_op_table[op]); else fprintf(MSG_OUT, " WARNING: Unknown set op "); } static void print_reg_or_data(command_t* command, int immediate, int start) { if(immediate) { uint32_t i = vm_getbits(command, start, 16); fprintf(MSG_OUT, "0x%x", i); if(isprint(i & 0xff) && isprint((i>>8) & 0xff)) fprintf(MSG_OUT, " (\"%c%c\")", (char)((i>>8) & 0xff), (char)(i & 0xff)); } else { print_reg(vm_getbits(command, start - 8, 8)); } } static void print_reg_or_data_2(command_t* command, int immediate, int start) { if(immediate) fprintf(MSG_OUT, "0x%x", vm_getbits(command, start - 1, 7)); else fprintf(MSG_OUT, "g[%" PRIu8 "]", vm_getbits(command, start - 4, 4)); } static void print_reg_or_data_3(command_t* command, int immediate, int start) { if(immediate) { uint32_t i = vm_getbits(command, start, 16); fprintf(MSG_OUT, "0x%x", i); if(isprint(i & 0xff) && isprint((i>>8) & 0xff)) fprintf(MSG_OUT, " (\"%c%c\")", (char)((i>>8) & 0xff), (char)(i & 0xff)); } else { print_reg(vm_getbits(command, start, 8)); } } static void print_if_version_1(command_t* command) { uint8_t op = vm_getbits(command, 54, 3); if(op) { fprintf(MSG_OUT, "if ("); print_g_reg(vm_getbits(command,39,8)); print_cmp_op(op); print_reg_or_data(command, vm_getbits(command, 55,1), 31); fprintf(MSG_OUT, ") "); } } static void print_if_version_2(command_t* command) { uint8_t op = vm_getbits(command, 54, 3); if(op) { fprintf(MSG_OUT, "if ("); print_reg(vm_getbits(command, 15, 8)); print_cmp_op(op); print_reg(vm_getbits(command, 7, 8)); fprintf(MSG_OUT, ") "); } } static void print_if_version_3(command_t* command) { uint8_t op = vm_getbits(command, 54, 3); if(op) { fprintf(MSG_OUT, "if ("); print_g_reg(vm_getbits(command, 43, 4)); print_cmp_op(op); print_reg_or_data(command, vm_getbits(command, 55, 1), 15); fprintf(MSG_OUT, ") "); } } static void print_if_version_4(command_t* command) { uint8_t op = vm_getbits(command, 54, 3); if(op) { fprintf(MSG_OUT, "if ("); print_g_reg(vm_getbits(command, 51, 4)); print_cmp_op(op); print_reg_or_data(command, vm_getbits(command, 55, 1), 31); fprintf(MSG_OUT, ") "); } } static void print_if_version_5(command_t* command) { uint8_t op = vm_getbits(command, 54, 3); int set_immediate = vm_getbits(command, 60, 1); if(op) { if (set_immediate) { fprintf(MSG_OUT, "if ("); print_g_reg(vm_getbits(command, 31, 8)); print_cmp_op(op); print_reg(vm_getbits(command, 23, 8)); fprintf(MSG_OUT, ") "); } else { fprintf(MSG_OUT, "if ("); print_g_reg(vm_getbits(command, 39, 8)); print_cmp_op(op); print_reg_or_data(command, vm_getbits(command, 55, 1), 31); fprintf(MSG_OUT, ") "); } } } static void print_special_instruction(command_t* command) { uint8_t op = vm_getbits(command, 51, 4); switch(op) { case 0: /* NOP */ fprintf(MSG_OUT, "Nop"); break; case 1: /* Goto line */ fprintf(MSG_OUT, "Goto %" PRIu8, vm_getbits(command, 7, 8)); break; case 2: /* Break */ fprintf(MSG_OUT, "Break"); break; case 3: /* Parental level */ fprintf(MSG_OUT, "SetTmpPML %" PRIu8 ", Goto %" PRIu8, vm_getbits(command, 11, 4), vm_getbits(command, 7, 8)); break; default: fprintf(MSG_OUT, "WARNING: Unknown special instruction (%i)", vm_getbits(command, 51, 4)); } } static void print_linksub_instruction(command_t* command) { uint32_t linkop = vm_getbits(command, 7, 8); uint32_t button = vm_getbits(command, 15, 6); if(linkop < sizeof(link_table)/sizeof(link_table[0])) fprintf(MSG_OUT, "%s (button %" PRIu8 ")", link_table[linkop], button); else fprintf(MSG_OUT, "WARNING: Unknown linksub instruction (%i)", linkop); } static void print_link_instruction(command_t* command, int optional) { uint8_t op = vm_getbits(command, 51, 4); if(optional && op) fprintf(MSG_OUT, ", "); switch(op) { case 0: if(!optional) fprintf(MSG_OUT, "WARNING: NOP (link)!"); break; case 1: print_linksub_instruction(command); break; case 4: fprintf(MSG_OUT, "LinkPGCN %" PRIu16, vm_getbits(command, 14, 15)); break; case 5: fprintf(MSG_OUT, "LinkPTT %" PRIu16 " (button %" PRIu8 ")", vm_getbits(command, 9, 10), vm_getbits(command, 15, 6)); break; case 6: fprintf(MSG_OUT, "LinkPGN %" PRIu8 " (button %" PRIu8 ")", vm_getbits(command, 6, 7), vm_getbits(command, 15, 6)); break; case 7: fprintf(MSG_OUT, "LinkCN %" PRIu8 " (button %" PRIu8 ")", vm_getbits(command, 7, 8), vm_getbits(command, 15, 6)); break; default: fprintf(MSG_OUT, "WARNING: Unknown link instruction"); } } static void print_jump_instruction(command_t* command) { switch(vm_getbits(command, 51, 4)) { case 1: fprintf(MSG_OUT, "Exit"); break; case 2: fprintf(MSG_OUT, "JumpTT %" PRIu8, vm_getbits(command, 22, 7)); break; case 3: fprintf(MSG_OUT, "JumpVTS_TT %" PRIu8, vm_getbits(command, 22, 7)); break; case 5: fprintf(MSG_OUT, "JumpVTS_PTT %" PRIu8 ":%" PRIu16, vm_getbits(command, 22, 7), vm_getbits(command, 41, 10)); break; case 6: switch(vm_getbits(command, 23, 2)) { case 0: fprintf(MSG_OUT, "JumpSS FP"); break; case 1: fprintf(MSG_OUT, "JumpSS VMGM (menu %" PRIu8 ")", vm_getbits(command, 19, 4)); break; case 2: fprintf(MSG_OUT, "JumpSS VTSM (vts %" PRIu8 ", title %" PRIu8 ", menu %" PRIu8 ")", vm_getbits(command, 30, 7), vm_getbits(command, 38, 7), vm_getbits(command, 19, 4)); break; case 3: fprintf(MSG_OUT, "JumpSS VMGM (pgc %" PRIu8 ")", vm_getbits(command, 46, 15)); break; } break; case 8: switch(vm_getbits(command, 23, 2)) { case 0: fprintf(MSG_OUT, "CallSS FP (rsm_cell %" PRIu8 ")", vm_getbits(command, 31, 8)); break; case 1: fprintf(MSG_OUT, "CallSS VMGM (menu %" PRIu8 ", rsm_cell %" PRIu8 ")", vm_getbits(command, 19, 4), vm_getbits(command, 31, 8)); break; case 2: fprintf(MSG_OUT, "CallSS VTSM (menu %" PRIu8 ", rsm_cell %" PRIu8 ")", vm_getbits(command, 19, 4), vm_getbits(command, 31, 8)); break; case 3: fprintf(MSG_OUT, "CallSS VMGM (pgc %" PRIu8 ", rsm_cell %" PRIu8 ")", vm_getbits(command, 46, 15), vm_getbits(command, 31, 8)); break; } break; default: fprintf(MSG_OUT, "WARNING: Unknown Jump/Call instruction"); } } static void print_system_set(command_t* command) { int i; /* FIXME: What about SPRM11 ? Karaoke */ /* Surely there must be some system set command for that ? */ switch(vm_getbits(command, 59, 4)) { case 1: /* Set system reg 1 &| 2 &| 3 (Audio, Subp. Angle) */ for(i = 1; i <= 3; i++) { if(vm_getbits(command, 47 - (i*8), 1)) { print_system_reg(i); fprintf(MSG_OUT, " = "); print_reg_or_data_2(command, vm_getbits(command, 60, 1), 47 - (i*8) ); fprintf(MSG_OUT, " "); } } break; case 2: /* Set system reg 9 & 10 (Navigation timer, Title PGC number) */ print_system_reg(9); fprintf(MSG_OUT, " = "); print_reg_or_data(command, vm_getbits(command, 60, 1), 47); fprintf(MSG_OUT, " "); print_system_reg(10); fprintf(MSG_OUT, " = %" PRIu16, vm_getbits(command, 30, 15)); /* ?? */ break; case 3: /* Mode: Counter / Register + Set */ fprintf(MSG_OUT, "SetMode "); if(vm_getbits(command, 23, 1)) fprintf(MSG_OUT, "Counter "); else fprintf(MSG_OUT, "Register "); print_g_reg(vm_getbits(command, 19, 4)); print_set_op(0x1); /* '=' */ print_reg_or_data(command, vm_getbits(command, 60, 1), 47); break; case 6: /* Set system reg 8 (Highlighted button) */ print_system_reg(8); if(vm_getbits(command, 60, 1)) /* immediate */ fprintf(MSG_OUT, " = 0x%x (button no %d)", vm_getbits(command, 31, 16), vm_getbits(command, 31, 6)); else fprintf(MSG_OUT, " = g[%" PRIu8 "]", vm_getbits(command, 19, 4)); break; default: fprintf(MSG_OUT, "WARNING: Unknown system set instruction (%i)", vm_getbits(command, 59, 4)); } } static void print_set_version_1(command_t* command) { uint8_t set_op = vm_getbits(command, 59, 4); if(set_op) { print_g_reg(vm_getbits(command, 35, 4)); print_set_op(set_op); print_reg_or_data(command, vm_getbits(command, 60, 1), 31); } else { fprintf(MSG_OUT, "NOP"); } } static void print_set_version_2(command_t* command) { uint8_t set_op = vm_getbits(command, 59, 4); if(set_op) { print_g_reg(vm_getbits(command, 51, 4)); print_set_op(set_op); print_reg_or_data(command, vm_getbits(command, 60, 1), 47); } else { fprintf(MSG_OUT, "NOP"); } } static void print_set_version_3(command_t* command) { uint8_t set_op = vm_getbits(command, 59, 4); if(set_op) { print_g_reg(vm_getbits(command, 51, 4)); print_set_op(set_op); print_reg_or_data_3(command, vm_getbits(command, 60, 1), 47); } else { fprintf(MSG_OUT, "NOP"); } } void vm_print_mnemonic(vm_cmd_t *vm_command) { command_t command; command.instruction =( (uint64_t) vm_command->bytes[0] << 56 ) | ( (uint64_t) vm_command->bytes[1] << 48 ) | ( (uint64_t) vm_command->bytes[2] << 40 ) | ( (uint64_t) vm_command->bytes[3] << 32 ) | ( (uint64_t) vm_command->bytes[4] << 24 ) | ( (uint64_t) vm_command->bytes[5] << 16 ) | ( (uint64_t) vm_command->bytes[6] << 8 ) | (uint64_t) vm_command->bytes[7] ; command.examined = 0; switch(vm_getbits(&command,63,3)) { /* three first bits */ case 0: /* Special instructions */ print_if_version_1(&command); print_special_instruction(&command); break; case 1: /* Jump/Call or Link instructions */ if(vm_getbits(&command,60,1)) { print_if_version_2(&command); print_jump_instruction(&command); } else { print_if_version_1(&command); print_link_instruction(&command, 0); /* must be pressent */ } break; case 2: /* Set System Parameters instructions */ print_if_version_2(&command); print_system_set(&command); print_link_instruction(&command, 1); /* either 'if' or 'link' */ break; case 3: /* Set General Parameters instructions */ print_if_version_3(&command); print_set_version_1(&command); print_link_instruction(&command, 1); /* either 'if' or 'link' */ break; case 4: /* Set, Compare -> LinkSub instructions */ print_set_version_2(&command); fprintf(MSG_OUT, ", "); print_if_version_4(&command); print_linksub_instruction(&command); break; case 5: /* Compare -> (Set and LinkSub) instructions */ print_if_version_5(&command); fprintf(MSG_OUT, "{ "); print_set_version_3(&command); fprintf(MSG_OUT, ", "); print_linksub_instruction(&command); fprintf(MSG_OUT, " }"); break; case 6: /* Compare -> Set, always LinkSub instructions */ print_if_version_5(&command); fprintf(MSG_OUT, "{ "); print_set_version_3(&command); fprintf(MSG_OUT, " } "); print_linksub_instruction(&command); break; default: fprintf(MSG_OUT, "WARNING: Unknown instruction type (%i)", vm_getbits(&command, 63, 3)); } /* Check if there still are bits set that were not examined */ if(command.instruction & ~ command.examined) { fprintf(MSG_OUT, " libdvdnav: vmcmd.c: [WARNING, unknown bits:"); fprintf(MSG_OUT, " %08"PRIx64, (command.instruction & ~ command.examined) ); fprintf(MSG_OUT, "]"); } } void vm_print_cmd(int row, vm_cmd_t *vm_command) { int i; fprintf(MSG_OUT, "(%03d) ", row + 1); for(i = 0; i < 8; i++) fprintf(MSG_OUT, "%02x ", vm_command->bytes[i]); fprintf(MSG_OUT, "| "); vm_print_mnemonic(vm_command); fprintf(MSG_OUT, "\n"); } k9copy/src/libdvdnav-NOW/vm/play.h0000644000175000017550000000227012412277736017520 0ustar emulatoremulator/* * Copyright (C) 2000, 2001 Håkan Hjort * Copyright (C) 2001 Rich Wareham * 2002-2004 the dvdnav project * * This file is part of libdvdnav, a DVD navigation library. It is modified * from a file originally part of the Ogle DVD player. * * libdvdnav is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdnav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdnav; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* Play */ link_t play_PGC(vm_t *vm); link_t play_PGC_PG(vm_t *vm, int pgN); link_t play_PGC_post(vm_t *vm); link_t play_PG(vm_t *vm); link_t play_Cell(vm_t *vm); link_t play_Cell_post(vm_t *vm); k9copy/src/libdvdnav-NOW/vm/vm.h0000644000175000017550000001333712412277736017203 0ustar emulatoremulator/* * Copyright (C) 2000, 2001 Håkan Hjort * Copyright (C) 2001 Rich Wareham * * This file is part of libdvdnav, a DVD navigation library. It is modified * from a file originally part of the Ogle DVD player. * * libdvdnav is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdnav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdnav; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef LIBDVDNAV_VM_H #define LIBDVDNAV_VM_H /** * State: SPRM, GPRM, Domain, pgc, pgN, cellN, ? */ typedef struct { registers_t registers; DVDDomain_t domain; int vtsN; /* 0 is vmgm? */ pgc_t *pgc; /* either this or 'int pgcN' is enough? */ int pgcN; /* but provide pgcN for quick lookup */ int pgN; /* is this needed? can allways fid pgN from cellN? */ int cellN; int32_t cell_restart; /* get cell to restart */ int blockN; /* Resume info */ int rsm_vtsN; int rsm_blockN; /* of nav_packet */ uint16_t rsm_regs[5]; /* system registers 4-8 */ int rsm_pgcN; int rsm_cellN; } dvd_state_t; typedef struct vm_position_s { int16_t button; /* Button highlighted */ int32_t vts; /* vts number to use */ DVDDomain_t domain; /* domain to use */ int32_t spu_channel; /* spu channel to use */ int32_t angle_channel; /* angle channel to use */ int32_t audio_channel; /* audio channel to use */ int32_t hop_channel; /* channel hopping. E.g menu button pressed */ #if 0 /* currently unused */ int32_t title; /* title number */ int32_t chapter; /* chapter number */ #endif int32_t cell; /* cell number */ int32_t cell_restart; /* get cell to restart */ int32_t cell_start; /* sector number of start of current cell in use */ int32_t still; /* is cell still */ int32_t block; /* block number within cell in use */ } vm_position_t; typedef struct { dvd_reader_t *dvd; ifo_handle_t *vmgi; ifo_handle_t *vtsi; dvd_state_t state; int32_t hop_channel; char dvd_name[50]; char dvd_serial[15]; int stopped; } vm_t; /* magic number for seeking hops */ #define HOP_SEEK 0x1000 /* Audio stream number */ #define AST_REG registers.SPRM[1] /* Subpicture stream number */ #define SPST_REG registers.SPRM[2] /* Angle number */ #define AGL_REG registers.SPRM[3] /* Title Track Number */ #define TTN_REG registers.SPRM[4] /* VTS Title Track Number */ #define VTS_TTN_REG registers.SPRM[5] /* PGC Number for this Title Track */ #define TT_PGCN_REG registers.SPRM[6] /* Current Part of Title (PTT) number for (One_Sequential_PGC_Title) */ #define PTTN_REG registers.SPRM[7] /* Highlighted Button Number (btn nr 1 == value 1024) */ #define HL_BTNN_REG registers.SPRM[8] /* Parental Level */ #define PTL_REG registers.SPRM[13] /* Initialisation & destruction */ vm_t *vm_new_vm(void); void vm_free_vm(vm_t *vm); /* IFO access */ ifo_handle_t *vm_get_vmgi(vm_t *vm); ifo_handle_t *vm_get_vtsi(vm_t *vm); /* Reader Access */ dvd_reader_t *vm_get_dvd_reader(vm_t *vm); /* Basic Handling */ int vm_start(vm_t *vm); void vm_stop(vm_t *vm); int vm_reset(vm_t *vm, const char *dvdroot); /* copying and merging - useful for try-running an operation */ vm_t *vm_new_copy(vm_t *vm); void vm_merge(vm_t *target, vm_t *source); void vm_free_copy(vm_t *vm); /* regular playback */ void vm_position_get(vm_t *vm, vm_position_t *position); void vm_get_next_cell(vm_t *vm); /* Jumping - all these return 1, if a hop has been performed */ int vm_jump_pg(vm_t *vm, int pg); int vm_jump_cell_block(vm_t *vm, int cell, int block); int vm_jump_title_part(vm_t *vm, int title, int part); int vm_jump_title_program(vm_t *vm, int title, int pgcn, int pgn); int vm_jump_top_pg(vm_t *vm); int vm_jump_next_pg(vm_t *vm); int vm_jump_prev_pg(vm_t *vm); int vm_jump_up(vm_t *vm); int vm_jump_menu(vm_t *vm, DVDMenuID_t menuid); int vm_jump_resume(vm_t *vm); int vm_exec_cmd(vm_t *vm, vm_cmd_t *cmd); /* getting information */ int vm_get_current_menu(vm_t *vm, int *menuid); int vm_get_current_title_part(vm_t *vm, int *title_result, int *part_result); int vm_get_audio_stream(vm_t *vm, int audioN); int vm_get_subp_stream(vm_t *vm, int subpN, int mode); int vm_get_audio_active_stream(vm_t *vm); int vm_get_subp_active_stream(vm_t *vm, int mode); void vm_get_angle_info(vm_t *vm, int *current, int *num_avail); #if 0 /* currently unused */ void vm_get_audio_info(vm_t *vm, int *current, int *num_avail); void vm_get_subp_info(vm_t *vm, int *current, int *num_avail); #endif void vm_get_video_res(vm_t *vm, int *width, int *height); int vm_get_video_aspect(vm_t *vm); int vm_get_video_scale_permission(vm_t *vm); video_attr_t vm_get_video_attr(vm_t *vm); audio_attr_t vm_get_audio_attr(vm_t *vm, int streamN); subp_attr_t vm_get_subp_attr(vm_t *vm, int streamN); ifo_handle_t *vm_get_title_ifo(vm_t *vm, uint32_t title); void vm_ifo_close(ifo_handle_t *ifo); /* Uncomment for VM command tracing */ /* #define TRACE */ #ifdef TRACE /* Debug */ void vm_position_print(vm_t *vm, vm_position_t *position); #endif int ifoOpenNewVTSI(vm_t *vm, dvd_reader_t *dvd, int vtsN); #endif /* LIBDVDNAV_VM_H */ k9copy/src/libdvdnav-NOW/vm/vm.c0000644000175000017550000010127212412277736017172 0ustar emulatoremulator/* * Copyright (C) 2000, 2001 Håkan Hjort * Copyright (C) 2001 Rich Wareham * 2002-2004 the dvdnav project * * This file is part of libdvdnav, a DVD navigation library. It is modified * from a file originally part of the Ogle DVD player. * * libdvdnav is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdnav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdnav; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dvdnav/dvdnav.h" #include "decoder.h" #include "vm.h" #include "play.h" #include "getset.h" #include "dvdnav_internal.h" #ifdef _MSC_VER #include /* read() */ #endif /* _MSC_VER */ #ifdef __OS2__ #define INCL_DOS #include #include #include /* setmode() */ #include /* O_BINARY */ #endif /* #define DVDNAV_STRICT */ /* Local prototypes */ /* Process link - returns 1 if a hop has been performed */ static int process_command(vm_t *vm,link_t link_values); /* Helper functions */ static void vm_close(vm_t *vm); /* Debug functions */ #ifdef TRACE void vm_position_print(vm_t *vm, vm_position_t *position) { fprintf(MSG_OUT, "libdvdnav: But=%x Spu=%x Aud=%x Ang=%x Hop=%x vts=%x dom=%x cell=%x cell_restart=%x cell_start=%x still=%x block=%x\n", position->button, position->spu_channel, position->audio_channel, position->angle_channel, position->hop_channel, position->vts, position->domain, position->cell, position->cell_restart, position->cell_start, position->still, position->block); } static void vm_print_current_domain_state(vm_t *vm) { const char *domain; switch(vm->state.domain) { case DVD_DOMAIN_VTSTitle: domain = "Video Title"; break; case DVD_DOMAIN_VTSMenu: domain = "Video Title Menu"; break; case DVD_DOMAIN_VMGM: domain = "Video Manager Menu"; break; case DVD_DOMAIN_FirstPlay: domain = "First Play"; break; default: domain = "Unknown"; break; } fprintf(MSG_OUT, "libdvdnav: %s Domain: VTS:%d PGC:%d PG:%u CELL:%u BLOCK:%u VTS_TTN:%u TTN:%u TT_PGCN:%u\n", domain, vm->state.vtsN, get_PGCN(vm), vm->state.pgN, vm->state.cellN, vm->state.blockN, vm->state.VTS_TTN_REG, vm->state.TTN_REG, vm->state.TT_PGCN_REG); } #endif #ifdef __OS2__ #define open os2_open static int os2_open(const char *name, int oflag) { HFILE hfile; ULONG ulAction; ULONG rc; rc = DosOpenL(name, &hfile, &ulAction, 0, FILE_NORMAL, OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW, OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE | OPEN_FLAGS_DASD, NULL); if(rc) return -1; setmode(hfile, O_BINARY); return (int)hfile; } #endif static int dvd_read_name(char *name, char *serial, const char *device) { /* Because we are compiling with _FILE_OFFSET_BITS=64 * all off_t are 64bit. */ off_t off; ssize_t read_size = 0; int fd = -1, i; uint8_t data[DVD_VIDEO_LB_LEN]; /* Read DVD name */ if (device == NULL) { fprintf(MSG_OUT, "libdvdnav: Device name string NULL\n"); goto fail; } if ((fd = open(device, O_RDONLY)) == -1) { fprintf(MSG_OUT, "libdvdnav: Unable to open device file %s.\n", device); goto fail; } if ((off = lseek( fd, 32 * (off_t) DVD_VIDEO_LB_LEN, SEEK_SET )) == (off_t) - 1) { fprintf(MSG_OUT, "libdvdnav: Unable to seek to the title block %u.\n", 32); goto fail; } if( off != ( 32 * (off_t) DVD_VIDEO_LB_LEN ) ) { fprintf(MSG_OUT, "libdvdnav: Can't seek to block %u\n", 32 ); goto fail; } if ((read_size = read( fd, data, DVD_VIDEO_LB_LEN )) == -1) { fprintf(MSG_OUT, "libdvdnav: Can't read name block. Probably not a DVD-ROM device.\n"); goto fail; } close(fd); fd = -1; if (read_size != DVD_VIDEO_LB_LEN) { fprintf(MSG_OUT, "libdvdnav: Can't read name block. Probably not a DVD-ROM device.\n"); goto fail; } fprintf(MSG_OUT, "libdvdnav: DVD Title: "); for(i=25; i < 73; i++ ) { if(data[i] == 0) break; if((data[i] > 32) && (data[i] < 127)) { fprintf(MSG_OUT, "%c", data[i]); } else { fprintf(MSG_OUT, " "); } } strncpy(name, (char*) &data[25], 48); name[48] = 0; fprintf(MSG_OUT, "\nlibdvdnav: DVD Serial Number: "); for(i=73; i < 89; i++ ) { if(data[i] == 0) break; if((data[i] > 32) && (data[i] < 127)) { fprintf(MSG_OUT, "%c", data[i]); } else { fprintf(MSG_OUT, " "); } } strncpy(serial, (char*) &data[73], 14); serial[14] = 0; fprintf(MSG_OUT, "\nlibdvdnav: DVD Title (Alternative): "); for(i=89; i < 128; i++ ) { if(data[i] == 0) break; if((data[i] > 32) && (data[i] < 127)) { fprintf(MSG_OUT, "%c", data[i]); } else { fprintf(MSG_OUT, " "); } } fprintf(MSG_OUT, "\n"); return 1; fail: if (fd >= 0) close(fd); return 0; } int ifoOpenNewVTSI(vm_t *vm, dvd_reader_t *dvd, int vtsN) { if(vm->state.vtsN == vtsN) { return 1; /* We alread have it */ } if(vm->vtsi != NULL) ifoClose(vm->vtsi); vm->vtsi = ifoOpenVTSI(dvd, vtsN); if(vm->vtsi == NULL) { fprintf(MSG_OUT, "libdvdnav: ifoOpenVTSI failed\n"); return 0; } if(!ifoRead_VTS_PTT_SRPT(vm->vtsi)) { fprintf(MSG_OUT, "libdvdnav: ifoRead_VTS_PTT_SRPT failed\n"); return 0; } if(!ifoRead_PGCIT(vm->vtsi)) { fprintf(MSG_OUT, "libdvdnav: ifoRead_PGCIT failed\n"); return 0; } if(!ifoRead_PGCI_UT(vm->vtsi)) { fprintf(MSG_OUT, "libdvdnav: ifoRead_PGCI_UT failed\n"); return 0; } if(!ifoRead_VOBU_ADMAP(vm->vtsi)) { fprintf(MSG_OUT, "libdvdnav: ifoRead_VOBU_ADMAP vtsi failed\n"); return 0; } if(!ifoRead_TITLE_VOBU_ADMAP(vm->vtsi)) { fprintf(MSG_OUT, "libdvdnav: ifoRead_TITLE_VOBU_ADMAP vtsi failed\n"); return 0; } vm->state.vtsN = vtsN; return 1; } /* Initialisation & Destruction */ vm_t* vm_new_vm() { return (vm_t*)calloc(1, sizeof(vm_t)); } void vm_free_vm(vm_t *vm) { vm_close(vm); free(vm); } /* IFO Access */ ifo_handle_t *vm_get_vmgi(vm_t *vm) { return vm->vmgi; } ifo_handle_t *vm_get_vtsi(vm_t *vm) { return vm->vtsi; } /* Reader Access */ dvd_reader_t *vm_get_dvd_reader(vm_t *vm) { return vm->dvd; } /* Basic Handling */ int vm_start(vm_t *vm) { if (vm->stopped) { if (!vm_reset(vm, NULL)) return 0; vm->stopped = 0; } /* Set pgc to FP (First Play) pgc */ set_FP_PGC(vm); process_command(vm, play_PGC(vm)); return !vm->stopped; } void vm_stop(vm_t *vm) { vm->stopped = 1; } static void vm_close(vm_t *vm) { if(!vm) return; if(vm->vmgi) { ifoClose(vm->vmgi); vm->vmgi=NULL; } if(vm->vtsi) { ifoClose(vm->vtsi); vm->vtsi=NULL; } if(vm->dvd) { DVDClose(vm->dvd); vm->dvd=NULL; } vm->stopped = 1; } int vm_reset(vm_t *vm, const char *dvdroot) { /* Setup State */ memset(vm->state.registers.SPRM, 0, sizeof(vm->state.registers.SPRM)); memset(vm->state.registers.GPRM, 0, sizeof(vm->state.registers.GPRM)); memset(vm->state.registers.GPRM_mode, 0, sizeof(vm->state.registers.GPRM_mode)); memset(vm->state.registers.GPRM_mode, 0, sizeof(vm->state.registers.GPRM_mode)); memset(vm->state.registers.GPRM_time, 0, sizeof(vm->state.registers.GPRM_time)); vm->state.registers.SPRM[0] = ('e'<<8)|'n'; /* Player Menu Languange code */ vm->state.AST_REG = 15; /* 15 why? */ vm->state.SPST_REG = 62; /* 62 why? */ vm->state.AGL_REG = 1; vm->state.TTN_REG = 1; vm->state.VTS_TTN_REG = 1; /* vm->state.TT_PGCN_REG = 0 */ vm->state.PTTN_REG = 1; vm->state.HL_BTNN_REG = 1 << 10; vm->state.PTL_REG = 15; /* Parental Level */ vm->state.registers.SPRM[12] = ('U'<<8)|'S'; /* Parental Management Country Code */ vm->state.registers.SPRM[16] = ('e'<<8)|'n'; /* Initial Language Code for Audio */ vm->state.registers.SPRM[18] = ('e'<<8)|'n'; /* Initial Language Code for Spu */ vm->state.registers.SPRM[20] = 0x1; /* Player Regional Code Mask. Region free! */ vm->state.registers.SPRM[14] = 0x100; /* Try Pan&Scan */ vm->state.registers.SPRM[15] = 0x7CFC; /* Audio capabilities - All defined audio types */ vm->state.pgN = 0; vm->state.cellN = 0; vm->state.cell_restart = 0; vm->state.domain = DVD_DOMAIN_FirstPlay; vm->state.rsm_vtsN = 0; vm->state.rsm_cellN = 0; vm->state.rsm_blockN = 0; vm->state.vtsN = -1; vm->hop_channel = 0; if (vm->dvd && dvdroot) { /* a new dvd device has been requested */ vm_close(vm); } if (!vm->dvd) { vm->dvd = DVDOpen(dvdroot); if(!vm->dvd) { fprintf(MSG_OUT, "libdvdnav: vm: failed to open/read the DVD\n"); return 0; } vm->vmgi = ifoOpenVMGI(vm->dvd); if(!vm->vmgi) { fprintf(MSG_OUT, "libdvdnav: vm: failed to read VIDEO_TS.IFO\n"); return 0; } if(!ifoRead_FP_PGC(vm->vmgi)) { fprintf(MSG_OUT, "libdvdnav: vm: ifoRead_FP_PGC failed\n"); return 0; } if(!ifoRead_TT_SRPT(vm->vmgi)) { fprintf(MSG_OUT, "libdvdnav: vm: ifoRead_TT_SRPT failed\n"); return 0; } if(!ifoRead_PGCI_UT(vm->vmgi)) { fprintf(MSG_OUT, "libdvdnav: vm: ifoRead_PGCI_UT failed\n"); return 0; } if(!ifoRead_PTL_MAIT(vm->vmgi)) { fprintf(MSG_OUT, "libdvdnav: vm: ifoRead_PTL_MAIT failed\n"); /* return 0; Not really used for now.. */ } if(!ifoRead_VTS_ATRT(vm->vmgi)) { fprintf(MSG_OUT, "libdvdnav: vm: ifoRead_VTS_ATRT failed\n"); /* return 0; Not really used for now.. */ } if(!ifoRead_VOBU_ADMAP(vm->vmgi)) { fprintf(MSG_OUT, "libdvdnav: vm: ifoRead_VOBU_ADMAP vgmi failed\n"); /* return 0; Not really used for now.. */ } /* ifoRead_TXTDT_MGI(vmgi); Not implemented yet */ } if (vm->vmgi) { int i, mask; fprintf(MSG_OUT, "libdvdnav: DVD disk reports itself with Region mask 0x%08x. Regions:", vm->vmgi->vmgi_mat->vmg_category); for (i = 1, mask = 1; i <= 8; i++, mask <<= 1) if (((vm->vmgi->vmgi_mat->vmg_category >> 16) & mask) == 0) fprintf(MSG_OUT, " %d", i); fprintf(MSG_OUT, "\n"); } return 1; } /* copying and merging */ vm_t *vm_new_copy(vm_t *source) { vm_t *target = vm_new_vm(); int vtsN; int pgcN = get_PGCN(source); int pgN = (source->state).pgN; if (target == NULL || pgcN == 0) goto fail; memcpy(target, source, sizeof(vm_t)); /* open a new vtsi handle, because the copy might switch to another VTS */ target->vtsi = NULL; vtsN = (target->state).vtsN; if (vtsN > 0) { (target->state).vtsN = 0; if (!ifoOpenNewVTSI(target, target->dvd, vtsN)) goto fail; /* restore pgc pointer into the new vtsi */ if (!set_PGCN(target, pgcN)) goto fail; (target->state).pgN = pgN; } return target; fail: if (target != NULL) vm_free_vm(target); return NULL; } void vm_merge(vm_t *target, vm_t *source) { if(target->vtsi) ifoClose(target->vtsi); memcpy(target, source, sizeof(vm_t)); memset(source, 0, sizeof(vm_t)); } void vm_free_copy(vm_t *vm) { if(vm->vtsi) ifoClose(vm->vtsi); free(vm); } /* regular playback */ void vm_position_get(vm_t *vm, vm_position_t *position) { position->button = vm->state.HL_BTNN_REG >> 10; position->vts = vm->state.vtsN; position->domain = vm->state.domain; position->spu_channel = vm->state.SPST_REG; position->audio_channel = vm->state.AST_REG; position->angle_channel = vm->state.AGL_REG; position->hop_channel = vm->hop_channel; /* Increases by one on each hop */ position->cell = vm->state.cellN; position->cell_restart = vm->state.cell_restart; position->cell_start = vm->state.pgc->cell_playback[vm->state.cellN - 1].first_sector; position->still = vm->state.pgc->cell_playback[vm->state.cellN - 1].still_time; position->block = vm->state.blockN; /* handle PGC stills at PGC end */ if (vm->state.cellN == vm->state.pgc->nr_of_cells) position->still += vm->state.pgc->still_time; /* still already determined */ if (position->still) return; /* This is a rough fix for some strange still situations on some strange DVDs. * There are discs (like the German "Back to the Future" RC2) where the only * indication of a still is a cell playback time higher than the time the frames * in this cell actually take to play (like 1 frame with 1 minute playback time). * On the said BTTF disc, for these cells last_sector and last_vobu_start_sector * are equal and the cells are very short, so we abuse these conditions to * detect such discs. I consider these discs broken, so the fix is somewhat * broken, too. */ if ((vm->state.pgc->cell_playback[vm->state.cellN - 1].last_sector == vm->state.pgc->cell_playback[vm->state.cellN - 1].last_vobu_start_sector) && (vm->state.pgc->cell_playback[vm->state.cellN - 1].last_sector - vm->state.pgc->cell_playback[vm->state.cellN - 1].first_sector < 1024)) { int time; int size = vm->state.pgc->cell_playback[vm->state.cellN - 1].last_sector - vm->state.pgc->cell_playback[vm->state.cellN - 1].first_sector; time = (vm->state.pgc->cell_playback[vm->state.cellN - 1].playback_time.hour >> 4 ) * 36000; time += (vm->state.pgc->cell_playback[vm->state.cellN - 1].playback_time.hour & 0x0f) * 3600; time += (vm->state.pgc->cell_playback[vm->state.cellN - 1].playback_time.minute >> 4 ) * 600; time += (vm->state.pgc->cell_playback[vm->state.cellN - 1].playback_time.minute & 0x0f) * 60; time += (vm->state.pgc->cell_playback[vm->state.cellN - 1].playback_time.second >> 4 ) * 10; time += (vm->state.pgc->cell_playback[vm->state.cellN - 1].playback_time.second & 0x0f) * 1; if (!time || size / time > 30) /* datarate is too high, it might be a very short, but regular cell */ return; if (time > 0xff) time = 0xff; position->still = time; } } void vm_get_next_cell(vm_t *vm) { process_command(vm, play_Cell_post(vm)); } /* Jumping */ int vm_jump_pg(vm_t *vm, int pg) { vm->state.pgN = pg; process_command(vm, play_PG(vm)); return 1; } int vm_jump_cell_block(vm_t *vm, int cell, int block) { vm->state.cellN = cell; process_command(vm, play_Cell(vm)); /* play_Cell can jump to a different cell in case of angles */ if (vm->state.cellN == cell) vm->state.blockN = block; return 1; } int vm_jump_title_program(vm_t *vm, int title, int pgcn, int pgn) { link_t link; if(!set_PROG(vm, title, pgcn, pgn)) return 0; /* Some DVDs do not want us to jump directly into a title and have * PGC pre commands taking us back to some menu. Since we do not like that, * we do not execute PGC pre commands that would do a jump. */ /* process_command(vm, play_PGC_PG(vm, vm->state.pgN)); */ link = play_PGC_PG(vm, vm->state.pgN); if (link.command != PlayThis) /* jump occured -> ignore it and play the PG anyway */ process_command(vm, play_PG(vm)); else process_command(vm, link); return 1; } int vm_jump_title_part(vm_t *vm, int title, int part) { link_t link; if(!set_PTT(vm, title, part)) return 0; /* Some DVDs do not want us to jump directly into a title and have * PGC pre commands taking us back to some menu. Since we do not like that, * we do not execute PGC pre commands that would do a jump. */ /* process_command(vm, play_PGC_PG(vm, vm->state.pgN)); */ link = play_PGC_PG(vm, vm->state.pgN); if (link.command != PlayThis) /* jump occured -> ignore it and play the PG anyway */ process_command(vm, play_PG(vm)); else process_command(vm, link); return 1; } int vm_jump_top_pg(vm_t *vm) { process_command(vm, play_PG(vm)); return 1; } int vm_jump_next_pg(vm_t *vm) { if(vm->state.pgN >= vm->state.pgc->nr_of_programs) { /* last program -> move to TailPGC */ process_command(vm, play_PGC_post(vm)); return 1; } else { vm_jump_pg(vm, vm->state.pgN + 1); return 1; } } int vm_jump_prev_pg(vm_t *vm) { if (vm->state.pgN <= 1) { /* first program -> move to last program of previous PGC */ if (vm->state.pgc->prev_pgc_nr && set_PGCN(vm, vm->state.pgc->prev_pgc_nr)) { process_command(vm, play_PGC(vm)); vm_jump_pg(vm, vm->state.pgc->nr_of_programs); return 1; } return 0; } else { vm_jump_pg(vm, vm->state.pgN - 1); return 1; } } int vm_jump_up(vm_t *vm) { if(vm->state.pgc->goup_pgc_nr && set_PGCN(vm, vm->state.pgc->goup_pgc_nr)) { process_command(vm, play_PGC(vm)); return 1; } return 0; } int vm_jump_menu(vm_t *vm, DVDMenuID_t menuid) { DVDDomain_t old_domain = vm->state.domain; switch (vm->state.domain) { case DVD_DOMAIN_FirstPlay: /* FIXME XXX $$$ What should we do here? */ break; case DVD_DOMAIN_VTSTitle: set_RSMinfo(vm, 0, vm->state.blockN); /* FALL THROUGH */ case DVD_DOMAIN_VTSMenu: case DVD_DOMAIN_VMGM: switch(menuid) { case DVD_MENU_Title: case DVD_MENU_Escape: if(vm->vmgi == NULL || vm->vmgi->pgci_ut == NULL) return 0; vm->state.domain = DVD_DOMAIN_VMGM; break; case DVD_MENU_Root: case DVD_MENU_Subpicture: case DVD_MENU_Audio: case DVD_MENU_Angle: case DVD_MENU_Part: if(vm->vtsi == NULL || vm->vtsi->pgci_ut == NULL) return 0; vm->state.domain = DVD_DOMAIN_VTSMenu; break; } if(get_PGCIT(vm) && set_MENU(vm, menuid)) { process_command(vm, play_PGC(vm)); return 1; /* Jump */ } else vm->state.domain = old_domain; break; } return 0; } int vm_jump_resume(vm_t *vm) { link_t link_values = { LinkRSM, 0, 0, 0 }; if (!vm->state.rsm_vtsN) /* Do we have resume info? */ return 0; return !!process_command(vm, link_values); } int vm_exec_cmd(vm_t *vm, vm_cmd_t *cmd) { link_t link_values; if(vmEval_CMD(cmd, 1, &vm->state.registers, &link_values)) return process_command(vm, link_values); else return 0; /* It updated some state thats all... */ } /* link processing */ static int process_command(vm_t *vm, link_t link_values) { while(link_values.command != PlayThis) { #ifdef TRACE fprintf(MSG_OUT, "libdvdnav: Before printout starts:\n"); vm_print_link(link_values); fprintf(MSG_OUT, "libdvdnav: Link values %i %i %i %i\n", link_values.command, link_values.data1, link_values.data2, link_values.data3); vm_print_current_domain_state(vm); fprintf(MSG_OUT, "libdvdnav: Before printout ends.\n"); #endif switch(link_values.command) { case LinkNoLink: /* BUTTON number:data1 */ if(link_values.data1 != 0) vm->state.HL_BTNN_REG = link_values.data1 << 10; return 0; /* no actual jump */ case LinkTopC: /* Restart playing from the beginning of the current Cell. */ /* BUTTON number:data1 */ if(link_values.data1 != 0) vm->state.HL_BTNN_REG = link_values.data1 << 10; link_values = play_Cell(vm); break; case LinkNextC: /* Link to Next Cell */ /* BUTTON number:data1 */ if(link_values.data1 != 0) vm->state.HL_BTNN_REG = link_values.data1 << 10; vm->state.cellN += 1; link_values = play_Cell(vm); break; case LinkPrevC: /* Link to Previous Cell */ /* BUTTON number:data1 */ if(link_values.data1 != 0) vm->state.HL_BTNN_REG = link_values.data1 << 10; assert(vm->state.cellN > 1); vm->state.cellN -= 1; link_values = play_Cell(vm); break; case LinkTopPG: /* Link to Top of current Program */ /* BUTTON number:data1 */ if(link_values.data1 != 0) vm->state.HL_BTNN_REG = link_values.data1 << 10; link_values = play_PG(vm); break; case LinkNextPG: /* Link to Next Program */ /* BUTTON number:data1 */ if(link_values.data1 != 0) vm->state.HL_BTNN_REG = link_values.data1 << 10; vm->state.pgN += 1; link_values = play_PG(vm); break; case LinkPrevPG: /* Link to Previous Program */ /* BUTTON number:data1 */ if(link_values.data1 != 0) vm->state.HL_BTNN_REG = link_values.data1 << 10; assert(vm->state.pgN > 1); vm->state.pgN -= 1; link_values = play_PG(vm); break; case LinkTopPGC: /* Restart playing from beginning of current Program Chain */ /* BUTTON number:data1 */ if(link_values.data1 != 0) vm->state.HL_BTNN_REG = link_values.data1 << 10; link_values = play_PGC(vm); break; case LinkNextPGC: /* Link to Next Program Chain */ /* BUTTON number:data1 */ if(link_values.data1 != 0) vm->state.HL_BTNN_REG = link_values.data1 << 10; assert(vm->state.pgc->next_pgc_nr != 0); if(set_PGCN(vm, vm->state.pgc->next_pgc_nr)) link_values = play_PGC(vm); else link_values.command = Exit; break; case LinkPrevPGC: /* Link to Previous Program Chain */ /* BUTTON number:data1 */ if(link_values.data1 != 0) vm->state.HL_BTNN_REG = link_values.data1 << 10; assert(vm->state.pgc->prev_pgc_nr != 0); if(set_PGCN(vm, vm->state.pgc->prev_pgc_nr)) link_values = play_PGC(vm); else link_values.command = Exit; break; case LinkGoUpPGC: /* Link to GoUp Program Chain */ /* BUTTON number:data1 */ if(link_values.data1 != 0) vm->state.HL_BTNN_REG = link_values.data1 << 10; assert(vm->state.pgc->goup_pgc_nr != 0); if(set_PGCN(vm, vm->state.pgc->goup_pgc_nr)) link_values = play_PGC(vm); else link_values.command = Exit; break; case LinkTailPGC: /* Link to Tail of Program Chain */ /* BUTTON number:data1 */ if(link_values.data1 != 0) vm->state.HL_BTNN_REG = link_values.data1 << 10; link_values = play_PGC_post(vm); break; case LinkRSM: /* Check and see if there is any rsm info!! */ if (!vm->state.rsm_vtsN) { fprintf(MSG_OUT, "libdvdnav: trying to resume without any resume info set\n"); link_values.command = Exit; break; } vm->state.domain = DVD_DOMAIN_VTSTitle; if (!ifoOpenNewVTSI(vm, vm->dvd, vm->state.rsm_vtsN)) assert(0); set_PGCN(vm, vm->state.rsm_pgcN); /* These should never be set in SystemSpace and/or MenuSpace */ /* vm->state.TTN_REG = rsm_tt; ?? */ /* vm->state.TT_PGCN_REG = vm->state.rsm_pgcN; ?? */ int i; for(i = 0; i < 5; i++) { vm->state.registers.SPRM[4 + i] = vm->state.rsm_regs[i]; } if(link_values.data1 != 0) vm->state.HL_BTNN_REG = link_values.data1 << 10; if(vm->state.rsm_cellN == 0) { assert(vm->state.cellN); /* Checking if this ever happens */ vm->state.pgN = 1; link_values = play_PG(vm); } else { /* vm->state.pgN = ?? this gets the right value in set_PGN() below */ vm->state.cellN = vm->state.rsm_cellN; link_values.command = PlayThis; link_values.data1 = vm->state.rsm_blockN & 0xffff; link_values.data2 = vm->state.rsm_blockN >> 16; if(!set_PGN(vm)) { /* Were at the end of the PGC, should not happen for a RSM */ assert(0); link_values.command = LinkTailPGC; link_values.data1 = 0; /* No button */ } } break; case LinkPGCN: /* Link to Program Chain Number:data1 */ if(!set_PGCN(vm, link_values.data1)) assert(0); link_values = play_PGC(vm); break; case LinkPTTN: /* Link to Part of current Title Number:data1 */ /* BUTTON number:data2 */ /* PGC Pre-Commands are not executed */ assert(vm->state.domain == DVD_DOMAIN_VTSTitle); if(link_values.data2 != 0) vm->state.HL_BTNN_REG = link_values.data2 << 10; if(!set_VTS_PTT(vm, vm->state.vtsN, vm->state.VTS_TTN_REG, link_values.data1)) link_values.command = Exit; else link_values = play_PG(vm); break; case LinkPGN: /* Link to Program Number:data1 */ /* BUTTON number:data2 */ if(link_values.data2 != 0) vm->state.HL_BTNN_REG = link_values.data2 << 10; /* Update any other state, PTTN perhaps? */ vm->state.pgN = link_values.data1; link_values = play_PG(vm); break; case LinkCN: /* Link to Cell Number:data1 */ /* BUTTON number:data2 */ if(link_values.data2 != 0) vm->state.HL_BTNN_REG = link_values.data2 << 10; /* Update any other state, pgN, PTTN perhaps? */ vm->state.cellN = link_values.data1; link_values = play_Cell(vm); break; case Exit: vm->stopped = 1; return 0; case JumpTT: /* Jump to VTS Title Domain */ /* Only allowed from the First Play domain(PGC) */ /* or the Video Manager domain (VMG) */ /* Stop SPRM9 Timer */ /* Set SPRM1 and SPRM2 */ assert(vm->state.domain == DVD_DOMAIN_VMGM || vm->state.domain == DVD_DOMAIN_FirstPlay); /* ?? */ if(set_TT(vm, link_values.data1)) link_values = play_PGC(vm); else link_values.command = Exit; break; case JumpVTS_TT: /* Jump to Title:data1 in same VTS Title Domain */ /* Only allowed from the VTS Menu Domain(VTSM) */ /* or the Video Title Set Domain(VTS) */ /* Stop SPRM9 Timer */ /* Set SPRM1 and SPRM2 */ assert(vm->state.domain == DVD_DOMAIN_VTSMenu || vm->state.domain == DVD_DOMAIN_VTSTitle); /* ?? */ if(!set_VTS_TT(vm, vm->state.vtsN, link_values.data1)) link_values.command = Exit; else link_values = play_PGC(vm); break; case JumpVTS_PTT: /* Jump to Part:data2 of Title:data1 in same VTS Title Domain */ /* Only allowed from the VTS Menu Domain(VTSM) */ /* or the Video Title Set Domain(VTS) */ /* Stop SPRM9 Timer */ /* Set SPRM1 and SPRM2 */ assert(vm->state.domain == DVD_DOMAIN_VTSMenu || vm->state.domain == DVD_DOMAIN_VTSTitle); /* ?? */ if(!set_VTS_PTT(vm, vm->state.vtsN, link_values.data1, link_values.data2)) link_values.command = Exit; else link_values = play_PGC_PG(vm, vm->state.pgN); break; case JumpSS_FP: /* Jump to First Play Domain */ /* Only allowed from the VTS Menu Domain(VTSM) */ /* or the Video Manager domain (VMG) */ /* Stop SPRM9 Timer and any GPRM counters */ assert(vm->state.domain == DVD_DOMAIN_VMGM || vm->state.domain == DVD_DOMAIN_VTSMenu); /* ?? */ if (!set_FP_PGC(vm)) assert(0); link_values = play_PGC(vm); break; case JumpSS_VMGM_MENU: /* Jump to Video Manager domain - Title Menu:data1 or any PGC in VMG */ /* Allowed from anywhere except the VTS Title domain */ /* Stop SPRM9 Timer and any GPRM counters */ assert(vm->state.domain != DVD_DOMAIN_VTSTitle); /* ?? */ if(vm->vmgi == NULL || vm->vmgi->pgci_ut == NULL) { link_values.command = Exit; break; } vm->state.domain = DVD_DOMAIN_VMGM; if(!set_MENU(vm, link_values.data1)) assert(0); link_values = play_PGC(vm); break; case JumpSS_VTSM: /* Jump to a menu in Video Title domain, */ /* or to a Menu is the current VTS */ /* Stop SPRM9 Timer and any GPRM counters */ /* ifoOpenNewVTSI:data1 */ /* VTS_TTN_REG:data2 */ /* get_MENU:data3 */ if(link_values.data1 != 0) { assert(vm->state.domain == DVD_DOMAIN_VTSMenu || vm->state.domain == DVD_DOMAIN_VMGM || vm->state.domain == DVD_DOMAIN_FirstPlay); /* ?? */ if (link_values.data1 != vm->state.vtsN) { /* the normal case */ assert(vm->state.domain != DVD_DOMAIN_VTSMenu); if (!ifoOpenNewVTSI(vm, vm->dvd, link_values.data1)) /* Also sets vm->state.vtsN */ vm->vtsi = NULL; } else { /* This happens on some discs like "Captain Scarlet & the Mysterons" or * the German RC2 of "Anatomie" in VTSM. */ } if(vm->vtsi == NULL || vm->vtsi->pgci_ut == NULL) { link_values.command = Exit; break; } vm->state.domain = DVD_DOMAIN_VTSMenu; } else { /* This happens on 'The Fifth Element' region 2. */ assert(vm->state.domain == DVD_DOMAIN_VTSMenu); } /* I don't know what title is supposed to be used for. */ /* Alien or Aliens has this != 1, I think. */ /* assert(link_values.data2 == 1); */ vm->state.VTS_TTN_REG = link_values.data2; /* TTN_REG (SPRM4), VTS_TTN_REG (SPRM5), TT_PGCN_REG (SPRM6) are linked, */ /* so if one changes, the others must change to match it. */ vm->state.TTN_REG = get_TT(vm, vm->state.vtsN, vm->state.VTS_TTN_REG); if(!set_MENU(vm, link_values.data3)) assert(0); link_values = play_PGC(vm); break; case JumpSS_VMGM_PGC: /* set_PGCN:data1 */ /* Stop SPRM9 Timer and any GPRM counters */ assert(vm->state.domain != DVD_DOMAIN_VTSTitle); /* ?? */ if(vm->vmgi == NULL || vm->vmgi->pgci_ut == NULL) { link_values.command = Exit; break; } vm->state.domain = DVD_DOMAIN_VMGM; if(!set_PGCN(vm, link_values.data1)) assert(0); link_values = play_PGC(vm); break; case CallSS_FP: /* set_RSMinfo:data1 */ assert(vm->state.domain == DVD_DOMAIN_VTSTitle); /* ?? */ /* Must be called before domain is changed */ set_RSMinfo(vm, link_values.data1, /* We dont have block info */ 0); set_FP_PGC(vm); link_values = play_PGC(vm); break; case CallSS_VMGM_MENU: /* set_MENU:data1 */ /* set_RSMinfo:data2 */ assert(vm->state.domain == DVD_DOMAIN_VTSTitle); /* ?? */ /* Must be called before domain is changed */ if(vm->vmgi == NULL || vm->vmgi->pgci_ut == NULL) { link_values.command = Exit; break; } set_RSMinfo(vm, link_values.data2, /* We dont have block info */ 0); vm->state.domain = DVD_DOMAIN_VMGM; if(!set_MENU(vm, link_values.data1)) assert(0); link_values = play_PGC(vm); break; case CallSS_VTSM: /* set_MENU:data1 */ /* set_RSMinfo:data2 */ assert(vm->state.domain == DVD_DOMAIN_VTSTitle); /* ?? */ /* Must be called before domain is changed */ if(vm->vtsi == NULL || vm->vtsi->pgci_ut == NULL) { link_values.command = Exit; break; } set_RSMinfo(vm, link_values.data2, /* We dont have block info */ 0); vm->state.domain = DVD_DOMAIN_VTSMenu; if(!set_MENU(vm, link_values.data1)) assert(0); link_values = play_PGC(vm); break; case CallSS_VMGM_PGC: /* set_PGC:data1 */ /* set_RSMinfo:data2 */ assert(vm->state.domain == DVD_DOMAIN_VTSTitle); /* ?? */ /* Must be called before domain is changed */ if(vm->vmgi == NULL || vm->vmgi->pgci_ut == NULL) { link_values.command = Exit; break; } set_RSMinfo(vm, link_values.data2, /* We dont have block info */ 0); vm->state.domain = DVD_DOMAIN_VMGM; if(!set_PGCN(vm, link_values.data1)) assert(0); link_values = play_PGC(vm); break; case PlayThis: /* Should never happen. */ assert(0); break; } #ifdef TRACE fprintf(MSG_OUT, "libdvdnav: After printout starts:\n"); vm_print_current_domain_state(vm); fprintf(MSG_OUT, "libdvdnav: After printout ends.\n"); #endif } vm->state.blockN = link_values.data1 | (link_values.data2 << 16); return 1; } //return the ifo_handle_t describing required title, used to //identify chapters ifo_handle_t *vm_get_title_ifo(vm_t *vm, uint32_t title) { uint8_t titleset_nr; if((title < 1) || (title > vm->vmgi->tt_srpt->nr_of_srpts)) return NULL; titleset_nr = vm->vmgi->tt_srpt->title[title-1].title_set_nr; return ifoOpen(vm->dvd, titleset_nr); } void vm_ifo_close(ifo_handle_t *ifo) { ifoClose(ifo); } k9copy/src/libdvdnav-NOW/vm/getset.c0000644000175000017550000002313712412277736020046 0ustar emulatoremulator/* * Copyright (C) 2000, 2001 Håkan Hjort * Copyright (C) 2001 Rich Wareham * 2002-2004 the dvdnav project * * This file is part of libdvdnav, a DVD navigation library. It is modified * from a file originally part of the Ogle DVD player. * * libdvdnav is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdnav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdnav; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include "dvdnav/dvdnav.h" #include "decoder.h" #include "vm.h" #include "getset.h" #include "dvdnav_internal.h" #include "getset.h" /* Set functions */ int set_TT(vm_t *vm, int tt) { return set_PTT(vm, tt, 1); } int set_PTT(vm_t *vm, int tt, int ptt) { assert(tt <= vm->vmgi->tt_srpt->nr_of_srpts); return set_VTS_PTT(vm, vm->vmgi->tt_srpt->title[tt - 1].title_set_nr, vm->vmgi->tt_srpt->title[tt - 1].vts_ttn, ptt); } int set_VTS_TT(vm_t *vm, int vtsN, int vts_ttn) { return set_VTS_PTT(vm, vtsN, vts_ttn, 1); } int set_VTS_PTT(vm_t *vm, int vtsN, int vts_ttn, int part) { int pgcN, pgN, res; (vm->state).domain = DVD_DOMAIN_VTSTitle; if (vtsN != (vm->state).vtsN) if (!ifoOpenNewVTSI(vm, vm->dvd, vtsN)) /* Also sets (vm->state).vtsN */ return 0; if ((vts_ttn < 1) || (vts_ttn > vm->vtsi->vts_ptt_srpt->nr_of_srpts) || (part < 1) || (part > vm->vtsi->vts_ptt_srpt->title[vts_ttn - 1].nr_of_ptts) ) { return 0; } pgcN = vm->vtsi->vts_ptt_srpt->title[vts_ttn - 1].ptt[part - 1].pgcn; pgN = vm->vtsi->vts_ptt_srpt->title[vts_ttn - 1].ptt[part - 1].pgn; (vm->state).TT_PGCN_REG = pgcN; (vm->state).PTTN_REG = part; (vm->state).TTN_REG = get_TT(vm, vtsN, vts_ttn); if( (vm->state.TTN_REG) == 0 ) return 0; (vm->state).VTS_TTN_REG = vts_ttn; (vm->state).vtsN = vtsN; /* Not sure about this one. We can get to it easily from TTN_REG */ /* Any other registers? */ res = set_PGCN(vm, pgcN); /* This clobber's state.pgN (sets it to 1), but we don't want clobbering here. */ (vm->state).pgN = pgN; return res; } int set_PROG(vm_t *vm, int tt, int pgcn, int pgn) { assert(tt <= vm->vmgi->tt_srpt->nr_of_srpts); return set_VTS_PROG(vm, vm->vmgi->tt_srpt->title[tt - 1].title_set_nr, vm->vmgi->tt_srpt->title[tt - 1].vts_ttn, pgcn, pgn); } int set_VTS_PROG(vm_t *vm, int vtsN, int vts_ttn, int pgcn, int pgn) { int pgcN, pgN, res, title, part = 0; (vm->state).domain = DVD_DOMAIN_VTSTitle; if (vtsN != (vm->state).vtsN) if (!ifoOpenNewVTSI(vm, vm->dvd, vtsN)) /* Also sets (vm->state).vtsN */ return 0; if ((vts_ttn < 1) || (vts_ttn > vm->vtsi->vts_ptt_srpt->nr_of_srpts)) { return 0; } pgcN = pgcn; pgN = pgn; (vm->state).TT_PGCN_REG = pgcN; (vm->state).TTN_REG = get_TT(vm, vtsN, vts_ttn); assert( (vm->state.TTN_REG) != 0 ); (vm->state).VTS_TTN_REG = vts_ttn; (vm->state).vtsN = vtsN; /* Not sure about this one. We can get to it easily from TTN_REG */ /* Any other registers? */ res = set_PGCN(vm, pgcN); /* This clobber's state.pgN (sets it to 1), but we don't want clobbering here. */ (vm->state).pgN = pgN; vm_get_current_title_part(vm, &title, &part); (vm->state).PTTN_REG = part; return res; } int set_FP_PGC(vm_t *vm) { if (!vm || !vm->vmgi) return 1; (vm->state).domain = DVD_DOMAIN_FirstPlay; if (!vm->vmgi->first_play_pgc) { return set_PGCN(vm, 1); } (vm->state).pgc = vm->vmgi->first_play_pgc; (vm->state).pgcN = vm->vmgi->vmgi_mat->first_play_pgc; return 1; } int set_MENU(vm_t *vm, int menu) { assert((vm->state).domain == DVD_DOMAIN_VMGM || (vm->state).domain == DVD_DOMAIN_VTSMenu); return set_PGCN(vm, get_ID(vm, menu)); } int set_PGCN(vm_t *vm, int pgcN) { pgcit_t *pgcit; pgcit = get_PGCIT(vm); if (pgcit == NULL) return 0; if(pgcN < 1 || pgcN > pgcit->nr_of_pgci_srp) { #ifdef TRACE fprintf(MSG_OUT, "libdvdnav: ** No such pgcN = %d\n", pgcN); #endif return 0; } (vm->state).pgc = pgcit->pgci_srp[pgcN - 1].pgc; (vm->state).pgcN = pgcN; (vm->state).pgN = 1; if((vm->state).domain == DVD_DOMAIN_VTSTitle) (vm->state).TT_PGCN_REG = pgcN; return 1; } /* Figure out the correct pgN from the cell and update (vm->state). */ int set_PGN(vm_t *vm) { int new_pgN = 0; int dummy, part = 0; while(new_pgN < (vm->state).pgc->nr_of_programs && (vm->state).cellN >= (vm->state).pgc->program_map[new_pgN]) new_pgN++; if(new_pgN == (vm->state).pgc->nr_of_programs) /* We are at the last program */ if((vm->state).cellN > (vm->state).pgc->nr_of_cells) return 0; /* We are past the last cell */ (vm->state).pgN = new_pgN; if((vm->state).domain == DVD_DOMAIN_VTSTitle) { if((vm->state).TTN_REG > vm->vmgi->tt_srpt->nr_of_srpts) return 0; /* ?? */ vm_get_current_title_part(vm, &dummy, &part); (vm->state).PTTN_REG = part; } return 1; } /* Must be called before domain is changed (set_PGCN()) */ void set_RSMinfo(vm_t *vm, int cellN, int blockN) { int i; if(cellN) { (vm->state).rsm_cellN = cellN; (vm->state).rsm_blockN = blockN; } else { (vm->state).rsm_cellN = (vm->state).cellN; (vm->state).rsm_blockN = blockN; } (vm->state).rsm_vtsN = (vm->state).vtsN; (vm->state).rsm_pgcN = get_PGCN(vm); /* assert((vm->state).rsm_pgcN == (vm->state).TT_PGCN_REG); for DVD_DOMAIN_VTSTitle */ for(i = 0; i < 5; i++) { (vm->state).rsm_regs[i] = (vm->state).registers.SPRM[4 + i]; } } /* Get functions */ /* Searches the TT tables, to find the current TT. * returns the current TT. * returns 0 if not found. */ int get_TT(vm_t *vm, int vtsN, int vts_ttn) { int i; int tt=0; for(i = 1; i <= vm->vmgi->tt_srpt->nr_of_srpts; i++) { if( vm->vmgi->tt_srpt->title[i - 1].title_set_nr == vtsN && vm->vmgi->tt_srpt->title[i - 1].vts_ttn == vts_ttn) { tt=i; break; } } return tt; } /* Search for entry_id match of the PGC Category in the current VTS PGCIT table. * Return pgcN based on entry_id match. */ int get_ID(vm_t *vm, int id) { int pgcN, i; pgcit_t *pgcit; /* Relies on state to get the correct pgcit. */ pgcit = get_PGCIT(vm); assert(pgcit != NULL); #ifdef TRACE fprintf(MSG_OUT, "libdvdnav: ** Searching for menu (0x%x) entry PGC\n", id); #endif /* Force high bit set. */ id |=0x80; /* Get menu/title */ for(i = 0; i < pgcit->nr_of_pgci_srp; i++) { if( (pgcit->pgci_srp[i].entry_id) == id) { pgcN = i + 1; #ifdef TRACE fprintf(MSG_OUT, "libdvdnav: Found menu.\n"); #endif return pgcN; } } #ifdef TRACE fprintf(MSG_OUT, "libdvdnav: ** No such id/menu (0x%02x) entry PGC\n", id & 0x7f); for(i = 0; i < pgcit->nr_of_pgci_srp; i++) { if ( (pgcit->pgci_srp[i].entry_id & 0x80) == 0x80) { fprintf(MSG_OUT, "libdvdnav: Available menus: 0x%x\n", pgcit->pgci_srp[i].entry_id & 0x7f); } } #endif return 0; /* error */ } /* FIXME: we have a pgcN member in the vm's state now, so this should be obsolete */ int get_PGCN(vm_t *vm) { pgcit_t *pgcit; int pgcN = 1; pgcit = get_PGCIT(vm); if (pgcit) { while(pgcN <= pgcit->nr_of_pgci_srp) { if(pgcit->pgci_srp[pgcN - 1].pgc == (vm->state).pgc) { assert((vm->state).pgcN == pgcN); return pgcN; } pgcN++; } } fprintf(MSG_OUT, "libdvdnav: get_PGCN failed. Was trying to find pgcN in domain %d\n", (vm->state).domain); return 0; /* error */ } pgcit_t* get_MENU_PGCIT(vm_t *vm, ifo_handle_t *h, uint16_t lang) { int i; if(h == NULL || h->pgci_ut == NULL) { fprintf(MSG_OUT, "libdvdnav: *** pgci_ut handle is NULL ***\n"); return NULL; /* error? */ } i = 0; while(i < h->pgci_ut->nr_of_lus && h->pgci_ut->lu[i].lang_code != lang) i++; if(i == h->pgci_ut->nr_of_lus) { fprintf(MSG_OUT, "libdvdnav: Language '%c%c' not found, using '%c%c' instead\n", (char)(lang >> 8), (char)(lang & 0xff), (char)(h->pgci_ut->lu[0].lang_code >> 8), (char)(h->pgci_ut->lu[0].lang_code & 0xff)); fprintf(MSG_OUT, "libdvdnav: Menu Languages available: "); for(i = 0; i < h->pgci_ut->nr_of_lus; i++) { fprintf(MSG_OUT, "%c%c ", (char)(h->pgci_ut->lu[i].lang_code >> 8), (char)(h->pgci_ut->lu[i].lang_code & 0xff)); } fprintf(MSG_OUT, "\n"); i = 0; /* error? */ } return h->pgci_ut->lu[i].pgcit; } /* Uses state to decide what to return */ pgcit_t* get_PGCIT(vm_t *vm) { pgcit_t *pgcit = NULL; switch ((vm->state).domain) { case DVD_DOMAIN_VTSTitle: if(!vm->vtsi) return NULL; pgcit = vm->vtsi->vts_pgcit; break; case DVD_DOMAIN_VTSMenu: if(!vm->vtsi) return NULL; pgcit = get_MENU_PGCIT(vm, vm->vtsi, (vm->state).registers.SPRM[0]); break; case DVD_DOMAIN_VMGM: case DVD_DOMAIN_FirstPlay: pgcit = get_MENU_PGCIT(vm, vm->vmgi, (vm->state).registers.SPRM[0]); break; default: abort(); } return pgcit; } k9copy/src/libdvdnav-NOW/vm/decoder.c0000644000175000017550000006074212412277736020163 0ustar emulatoremulator/* * Copyright (C) 2000, 2001 Martin Norbäck, Håkan Hjort * 2002-2004 the dvdnav project * * This file is part of libdvdnav, a DVD navigation library. It is modified * from a file originally part of the Ogle DVD player. * * libdvdnav is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdnav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdnav; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include /* For memset */ #include #include #include #include /* vm_cmd_t */ #include "dvdnav/dvdnav.h" #include "decoder.h" #include "vm.h" #include "vmcmd.h" #include "dvdnav_internal.h" uint32_t vm_getbits(command_t *command, int32_t start, int32_t count) { uint64_t result = 0; uint64_t bit_mask = 0; uint64_t examining = 0; int32_t bits; if (count == 0) return 0; if ( ((start - count) < -1) || (count > 32) || (start > 63) || (count < 0) || (start < 0) ) { fprintf(MSG_OUT, "libdvdnav: Bad call to vm_getbits. Parameter out of range\n"); abort(); } /* all ones, please */ bit_mask = ~bit_mask; bit_mask >>= 63 - start; bits = start + 1 - count; examining = ((bit_mask >> bits) << bits ); command->examined |= examining; result = (command->instruction & bit_mask) >> bits; return (uint32_t) result; } static uint16_t get_GPRM(registers_t* registers, uint8_t reg) { if (registers->GPRM_mode[reg] & 0x01) { struct timeval current_time, time_offset; uint16_t result; /* Counter mode */ /* fprintf(MSG_OUT, "libdvdnav: Getting counter %d\n",reg);*/ gettimeofday(¤t_time, NULL); time_offset.tv_sec = current_time.tv_sec - registers->GPRM_time[reg].tv_sec; time_offset.tv_usec = current_time.tv_usec - registers->GPRM_time[reg].tv_usec; if (time_offset.tv_usec < 0) { time_offset.tv_sec--; time_offset.tv_usec += 1000000; } result = (uint16_t) (time_offset.tv_sec & 0xffff); registers->GPRM[reg]=result; return result; } else { /* Register mode */ return registers->GPRM[reg]; } } static void set_GPRM(registers_t* registers, uint8_t reg, uint16_t value) { if (registers->GPRM_mode[reg] & 0x01) { struct timeval current_time; /* Counter mode */ /* fprintf(MSG_OUT, "libdvdnav: Setting counter %d\n",reg); */ gettimeofday(¤t_time, NULL); registers->GPRM_time[reg] = current_time; registers->GPRM_time[reg].tv_sec -= value; } registers->GPRM[reg] = value; } /* Eval register code, can either be system or general register. SXXX_XXXX, where S is 1 if it is system register. */ static uint16_t eval_reg(command_t* command, uint8_t reg) { if(reg & 0x80) { if ((reg & 0x1f) == 20) { fprintf(MSG_OUT, "libdvdnav: Suspected RCE Region Protection!!!\n"); } return command->registers->SPRM[reg & 0x1f]; /* FIXME max 24 not 32 */ } else { return get_GPRM(command->registers, reg & 0x0f) ; } } /* Eval register or immediate data. AAAA_AAAA BBBB_BBBB, if immediate use all 16 bits for data else use lower eight bits for the system or general purpose register. */ static uint16_t eval_reg_or_data(command_t* command, int32_t imm, int32_t start) { if(imm) { /* immediate */ return vm_getbits(command, start, 16); } else { return eval_reg(command, vm_getbits(command, (start - 8), 8)); } } /* Eval register or immediate data. xBBB_BBBB, if immediate use all 7 bits for data else use lower four bits for the general purpose register number. */ /* Evaluates gprm or data depending on bit, data is in byte n */ static uint16_t eval_reg_or_data_2(command_t* command, int32_t imm, int32_t start) { if(imm) /* immediate */ return vm_getbits(command, (start - 1), 7); else return get_GPRM(command->registers, (vm_getbits(command, (start - 4), 4)) ); } /* Compare data using operation, return result from comparison. Helper function for the different if functions. */ static int32_t eval_compare(uint8_t operation, uint16_t data1, uint16_t data2) { switch(operation) { case 1: return data1 & data2; case 2: return data1 == data2; case 3: return data1 != data2; case 4: return data1 >= data2; case 5: return data1 > data2; case 6: return data1 <= data2; case 7: return data1 < data2; } fprintf(MSG_OUT, "libdvdnav: eval_compare: Invalid comparison code\n"); return 0; } /* Evaluate if version 1. Has comparison data in byte 3 and 4-5 (immediate or register) */ static int32_t eval_if_version_1(command_t* command) { uint8_t op = vm_getbits(command, 54, 3); if(op) { return eval_compare(op, eval_reg(command, vm_getbits(command, 39, 8)), eval_reg_or_data(command, vm_getbits(command, 55, 1), 31)); } return 1; } /* Evaluate if version 2. This version only compares register which are in byte 6 and 7 */ static int32_t eval_if_version_2(command_t* command) { uint8_t op = vm_getbits(command, 54, 3); if(op) { return eval_compare(op, eval_reg(command, vm_getbits(command, 15, 8)), eval_reg(command, vm_getbits(command, 7, 8))); } return 1; } /* Evaluate if version 3. Has comparison data in byte 2 and 6-7 (immediate or register) */ static int32_t eval_if_version_3(command_t* command) { uint8_t op = vm_getbits(command, 54, 3); if(op) { return eval_compare(op, eval_reg(command, vm_getbits(command, 47, 8)), eval_reg_or_data(command, vm_getbits(command, 55, 1), 15)); } return 1; } /* Evaluate if version 4. Has comparison data in byte 1 and 4-5 (immediate or register) The register in byte 1 is only the lowe nibble (4 bits) */ static int32_t eval_if_version_4(command_t* command) { uint8_t op = vm_getbits(command, 54, 3); if(op) { return eval_compare(op, eval_reg(command, vm_getbits(command, 51, 4)), eval_reg_or_data(command, vm_getbits(command, 55, 1), 31)); } return 1; } /* Evaluate special instruction.... returns the new row/line number, 0 if no new row and 256 if Break. */ static int32_t eval_special_instruction(command_t* command, int32_t cond) { int32_t line, level; switch(vm_getbits(command, 51, 4)) { case 0: /* NOP */ line = 0; return cond ? line : 0; case 1: /* Goto line */ line = vm_getbits(command, 7, 8); return cond ? line : 0; case 2: /* Break */ /* max number of rows < 256, so we will end this set */ line = 256; return cond ? 256 : 0; case 3: /* Set temporary parental level and goto */ line = vm_getbits(command, 7, 8); level = vm_getbits(command, 11, 4); if(cond) { /* This always succeeds now, if we want real parental protection */ /* we need to ask the user and have passwords and stuff. */ command->registers->SPRM[13] = level; } return cond ? line : 0; } return 0; } /* Evaluate link by subinstruction. Return 1 if link, or 0 if no link Actual link instruction is in return_values parameter */ static int32_t eval_link_subins(command_t* command, int32_t cond, link_t *return_values) { uint16_t button = vm_getbits(command, 15, 6); uint8_t linkop = vm_getbits(command, 4, 5); if(linkop > 0x10) return 0; /* Unknown Link by Sub-Instruction command */ /* Assumes that the link_cmd_t enum has the same values as the LinkSIns codes */ return_values->command = linkop; return_values->data1 = button; return cond; } /* Evaluate link instruction. Return 1 if link, or 0 if no link Actual link instruction is in return_values parameter */ static int32_t eval_link_instruction(command_t* command, int32_t cond, link_t *return_values) { uint8_t op = vm_getbits(command, 51, 4); switch(op) { case 1: return eval_link_subins(command, cond, return_values); case 4: return_values->command = LinkPGCN; return_values->data1 = vm_getbits(command, 14, 15); return cond; case 5: return_values->command = LinkPTTN; return_values->data1 = vm_getbits(command, 9, 10); return_values->data2 = vm_getbits(command, 15, 6); return cond; case 6: return_values->command = LinkPGN; return_values->data1 = vm_getbits(command, 6, 7); return_values->data2 = vm_getbits(command, 15, 6); return cond; case 7: return_values->command = LinkCN; return_values->data1 = vm_getbits(command, 7, 8); return_values->data2 = vm_getbits(command, 15, 6); return cond; } return 0; } /* Evaluate a jump instruction. returns 1 if jump or 0 if no jump actual jump instruction is in return_values parameter */ static int32_t eval_jump_instruction(command_t* command, int32_t cond, link_t *return_values) { switch(vm_getbits(command, 51, 4)) { case 1: return_values->command = Exit; return cond; case 2: return_values->command = JumpTT; return_values->data1 = vm_getbits(command, 22, 7); return cond; case 3: return_values->command = JumpVTS_TT; return_values->data1 = vm_getbits(command, 22, 7); return cond; case 5: return_values->command = JumpVTS_PTT; return_values->data1 = vm_getbits(command, 22, 7); return_values->data2 = vm_getbits(command, 41, 10); return cond; case 6: switch(vm_getbits(command, 23, 2)) { case 0: return_values->command = JumpSS_FP; return cond; case 1: return_values->command = JumpSS_VMGM_MENU; return_values->data1 = vm_getbits(command, 19, 4); return cond; case 2: return_values->command = JumpSS_VTSM; return_values->data1 = vm_getbits(command, 31, 8); return_values->data2 = vm_getbits(command, 39, 8); return_values->data3 = vm_getbits(command, 19, 4); return cond; case 3: return_values->command = JumpSS_VMGM_PGC; return_values->data1 = vm_getbits(command, 46, 15); return cond; } break; case 8: switch(vm_getbits(command, 23, 2)) { case 0: return_values->command = CallSS_FP; return_values->data1 = vm_getbits(command, 31, 8); return cond; case 1: return_values->command = CallSS_VMGM_MENU; return_values->data1 = vm_getbits(command, 19, 4); return_values->data2 = vm_getbits(command, 31, 8); return cond; case 2: return_values->command = CallSS_VTSM; return_values->data1 = vm_getbits(command, 19, 4); return_values->data2 = vm_getbits(command, 31, 8); return cond; case 3: return_values->command = CallSS_VMGM_PGC; return_values->data1 = vm_getbits(command, 46, 15); return_values->data2 = vm_getbits(command, 31, 8); return cond; } break; } return 0; } /* Evaluate a set sytem register instruction May contain a link so return the same as eval_link */ static int32_t eval_system_set(command_t* command, int32_t cond, link_t *return_values) { int32_t i; uint16_t data, data2; switch(vm_getbits(command, 59, 4)) { case 1: /* Set system reg 1 &| 2 &| 3 (Audio, Subp. Angle) */ for(i = 1; i <= 3; i++) { if(vm_getbits(command, 63 - ((2 + i)*8), 1)) { data = eval_reg_or_data_2(command, vm_getbits(command, 60, 1), (47 - (i*8))); if(cond) { command->registers->SPRM[i] = data; } } } break; case 2: /* Set system reg 9 & 10 (Navigation timer, Title PGC number) */ data = eval_reg_or_data(command, vm_getbits(command, 60, 1), 47); data2 = vm_getbits(command, 23, 8); /* ?? size */ if(cond) { command->registers->SPRM[9] = data; /* time */ command->registers->SPRM[10] = data2; /* pgcN */ } break; case 3: /* Mode: Counter / Register + Set */ data = eval_reg_or_data(command, vm_getbits(command, 60, 1), 47); data2 = vm_getbits(command, 19, 4); if(vm_getbits(command, 23, 1)) { command->registers->GPRM_mode[data2] |= 1; /* Set bit 0 */ } else { command->registers->GPRM_mode[data2] &= ~ 0x01; /* Reset bit 0 */ } if(cond) { set_GPRM(command->registers, data2, data); } break; case 6: /* Set system reg 8 (Highlighted button) */ data = eval_reg_or_data(command, vm_getbits(command, 60, 1), 31); /* Not system reg!! */ if(cond) { command->registers->SPRM[8] = data; } break; } if(vm_getbits(command, 51, 4)) { return eval_link_instruction(command, cond, return_values); } return 0; } /* Evaluate set operation Sets the register given to the value indicated by op and data. For the swap case the contents of reg is stored in reg2. */ static void eval_set_op(command_t* command, int32_t op, int32_t reg, int32_t reg2, int32_t data) { static const int32_t shortmax = 0xffff; int32_t tmp; switch(op) { case 1: set_GPRM(command->registers, reg, data); break; case 2: /* SPECIAL CASE - SWAP! */ set_GPRM(command->registers, reg2, get_GPRM(command->registers, reg)); set_GPRM(command->registers, reg, data); break; case 3: tmp = get_GPRM(command->registers, reg) + data; if(tmp > shortmax) tmp = shortmax; set_GPRM(command->registers, reg, (uint16_t)tmp); break; case 4: tmp = get_GPRM(command->registers, reg) - data; if(tmp < 0) tmp = 0; set_GPRM(command->registers, reg, (uint16_t)tmp); break; case 5: tmp = get_GPRM(command->registers, reg) * data; if(tmp > shortmax) tmp = shortmax; set_GPRM(command->registers, reg, (uint16_t)tmp); break; case 6: if (data != 0) { set_GPRM(command->registers, reg, (get_GPRM(command->registers, reg) / data) ); } else { set_GPRM(command->registers, reg, 0xffff); /* Avoid that divide by zero! */ } break; case 7: if (data != 0) { set_GPRM(command->registers, reg, (get_GPRM(command->registers, reg) % data) ); } else { set_GPRM(command->registers, reg, 0xffff); /* Avoid that divide by zero! */ } break; case 8: /* SPECIAL CASE - RND! Return numbers between 1 and data. */ set_GPRM(command->registers, reg, 1 + ((uint16_t) ((float) data * rand()/(RAND_MAX+1.0))) ); break; case 9: set_GPRM(command->registers, reg, (get_GPRM(command->registers, reg) & data) ); break; case 10: set_GPRM(command->registers, reg, (get_GPRM(command->registers, reg) | data) ); break; case 11: set_GPRM(command->registers, reg, (get_GPRM(command->registers, reg) ^ data) ); break; } } /* Evaluate set instruction, combined with either Link or Compare. */ static void eval_set_version_1(command_t* command, int32_t cond) { uint8_t op = vm_getbits(command, 59, 4); uint8_t reg = vm_getbits(command, 35, 4); /* FIXME: This is different from vmcmd.c!!! */ uint8_t reg2 = vm_getbits(command, 19, 4); uint16_t data = eval_reg_or_data(command, vm_getbits(command, 60, 1), 31); if(cond) { eval_set_op(command, op, reg, reg2, data); } } /* Evaluate set instruction, combined with both Link and Compare. */ static void eval_set_version_2(command_t* command, int32_t cond) { uint8_t op = vm_getbits(command, 59, 4); uint8_t reg = vm_getbits(command, 51, 4); uint8_t reg2 = vm_getbits(command, 35, 4); /* FIXME: This is different from vmcmd.c!!! */ uint16_t data = eval_reg_or_data(command, vm_getbits(command, 60, 1), 47); if(cond) { eval_set_op(command, op, reg, reg2, data); } } /* Evaluate a command returns row number of goto, 0 if no goto, -1 if link. Link command in return_values */ static int32_t eval_command(uint8_t *bytes, registers_t* registers, link_t *return_values) { int32_t cond, res = 0; command_t command; command.instruction =( (uint64_t) bytes[0] << 56 ) | ( (uint64_t) bytes[1] << 48 ) | ( (uint64_t) bytes[2] << 40 ) | ( (uint64_t) bytes[3] << 32 ) | ( (uint64_t) bytes[4] << 24 ) | ( (uint64_t) bytes[5] << 16 ) | ( (uint64_t) bytes[6] << 8 ) | (uint64_t) bytes[7] ; command.examined = 0; command.registers = registers; memset(return_values, 0, sizeof(link_t)); switch(vm_getbits(&command, 63, 3)) { /* three first old_bits */ case 0: /* Special instructions */ cond = eval_if_version_1(&command); res = eval_special_instruction(&command, cond); if(res == -1) { fprintf(MSG_OUT, "libdvdnav: Unknown Instruction!\n"); assert(0); } break; case 1: /* Link/jump instructions */ if(vm_getbits(&command, 60, 1)) { cond = eval_if_version_2(&command); res = eval_jump_instruction(&command, cond, return_values); } else { cond = eval_if_version_1(&command); res = eval_link_instruction(&command, cond, return_values); } if(res) res = -1; break; case 2: /* System set instructions */ cond = eval_if_version_2(&command); res = eval_system_set(&command, cond, return_values); if(res) res = -1; break; case 3: /* Set instructions, either Compare or Link may be used */ cond = eval_if_version_3(&command); eval_set_version_1(&command, cond); if(vm_getbits(&command, 51, 4)) { res = eval_link_instruction(&command, cond, return_values); } if(res) res = -1; break; case 4: /* Set, Compare -> Link Sub-Instruction */ eval_set_version_2(&command, /*True*/ 1); cond = eval_if_version_4(&command); res = eval_link_subins(&command, cond, return_values); if(res) res = -1; break; case 5: /* Compare -> (Set and Link Sub-Instruction) */ /* FIXME: These are wrong. Need to be updated from vmcmd.c */ cond = eval_if_version_4(&command); eval_set_version_2(&command, cond); res = eval_link_subins(&command, cond, return_values); if(res) res = -1; break; case 6: /* Compare -> Set, allways Link Sub-Instruction */ /* FIXME: These are wrong. Need to be updated from vmcmd.c */ cond = eval_if_version_4(&command); eval_set_version_2(&command, cond); res = eval_link_subins(&command, /*True*/ 1, return_values); if(res) res = -1; break; default: /* Unknown command */ fprintf(MSG_OUT, "libdvdnav: WARNING: Unknown Command=%x\n", vm_getbits(&command, 63, 3)); assert(0); } /* Check if there are bits not yet examined */ if(command.instruction & ~ command.examined) { fprintf(MSG_OUT, "libdvdnav: decoder.c: [WARNING, unknown bits:"); fprintf(MSG_OUT, " %08"PRIx64, (command.instruction & ~ command.examined) ); fprintf(MSG_OUT, "]\n"); } return res; } /* Evaluate a set of commands in the given register set (which is modified) */ int32_t vmEval_CMD(vm_cmd_t commands[], int32_t num_commands, registers_t *registers, link_t *return_values) { int32_t i = 0; int32_t total = 0; #ifdef TRACE /* DEBUG */ fprintf(MSG_OUT, "libdvdnav: Registers before transaction\n"); vm_print_registers( registers ); fprintf(MSG_OUT, "libdvdnav: Full list of commands to execute\n"); for(i = 0; i < num_commands; i++) vm_print_cmd(i, &commands[i]); fprintf(MSG_OUT, "libdvdnav: --------------------------------------------\n"); fprintf(MSG_OUT, "libdvdnav: Single stepping commands\n"); #endif i = 0; while(i < num_commands && total < 100000) { int32_t line; #ifdef TRACE vm_print_cmd(i, &commands[i]); #endif line = eval_command(&commands[i].bytes[0], registers, return_values); if (line < 0) { /* Link command */ #ifdef TRACE fprintf(MSG_OUT, "libdvdnav: Registers after transaction\n"); vm_print_registers( registers ); fprintf(MSG_OUT, "libdvdnav: eval: Doing Link/Jump/Call\n"); #endif return 1; } if (line > 0) /* Goto command */ i = line - 1; else /* Just continue on the next line */ i++; total++; } memset(return_values, 0, sizeof(link_t)); #ifdef TRACE fprintf(MSG_OUT, "libdvdnav: Registers after transaction\n"); vm_print_registers( registers ); #endif return 0; } #ifdef TRACE static char *linkcmd2str(link_cmd_t cmd) { switch(cmd) { case LinkNoLink: return "LinkNoLink"; case LinkTopC: return "LinkTopC"; case LinkNextC: return "LinkNextC"; case LinkPrevC: return "LinkPrevC"; case LinkTopPG: return "LinkTopPG"; case LinkNextPG: return "LinkNextPG"; case LinkPrevPG: return "LinkPrevPG"; case LinkTopPGC: return "LinkTopPGC"; case LinkNextPGC: return "LinkNextPGC"; case LinkPrevPGC: return "LinkPrevPGC"; case LinkGoUpPGC: return "LinkGoUpPGC"; case LinkTailPGC: return "LinkTailPGC"; case LinkRSM: return "LinkRSM"; case LinkPGCN: return "LinkPGCN"; case LinkPTTN: return "LinkPTTN"; case LinkPGN: return "LinkPGN"; case LinkCN: return "LinkCN"; case Exit: return "Exit"; case JumpTT: return "JumpTT"; case JumpVTS_TT: return "JumpVTS_TT"; case JumpVTS_PTT: return "JumpVTS_PTT"; case JumpSS_FP: return "JumpSS_FP"; case JumpSS_VMGM_MENU: return "JumpSS_VMGM_MENU"; case JumpSS_VTSM: return "JumpSS_VTSM"; case JumpSS_VMGM_PGC: return "JumpSS_VMGM_PGC"; case CallSS_FP: return "CallSS_FP"; case CallSS_VMGM_MENU: return "CallSS_VMGM_MENU"; case CallSS_VTSM: return "CallSS_VTSM"; case CallSS_VMGM_PGC: return "CallSS_VMGM_PGC"; case PlayThis: return "PlayThis"; } return "*** (bug)"; } void vm_print_link(link_t value) { char *cmd = linkcmd2str(value.command); switch(value.command) { case LinkNoLink: case LinkTopC: case LinkNextC: case LinkPrevC: case LinkTopPG: case LinkNextPG: case LinkPrevPG: case LinkTopPGC: case LinkNextPGC: case LinkPrevPGC: case LinkGoUpPGC: case LinkTailPGC: case LinkRSM: fprintf(MSG_OUT, "libdvdnav: %s (button %d)\n", cmd, value.data1); break; case LinkPGCN: case JumpTT: case JumpVTS_TT: case JumpSS_VMGM_MENU: /* == 2 -> Title Menu */ case JumpSS_VMGM_PGC: fprintf(MSG_OUT, "libdvdnav: %s %d\n", cmd, value.data1); break; case LinkPTTN: case LinkPGN: case LinkCN: fprintf(MSG_OUT, "libdvdnav: %s %d (button %d)\n", cmd, value.data1, value.data2); break; case Exit: case JumpSS_FP: case PlayThis: /* Humm.. should we have this at all.. */ fprintf(MSG_OUT, "libdvdnav: %s\n", cmd); break; case JumpVTS_PTT: fprintf(MSG_OUT, "libdvdnav: %s %d:%d\n", cmd, value.data1, value.data2); break; case JumpSS_VTSM: fprintf(MSG_OUT, "libdvdnav: %s vts %d title %d menu %d\n", cmd, value.data1, value.data2, value.data3); break; case CallSS_FP: fprintf(MSG_OUT, "libdvdnav: %s resume cell %d\n", cmd, value.data1); break; case CallSS_VMGM_MENU: /* == 2 -> Title Menu */ case CallSS_VTSM: fprintf(MSG_OUT, "libdvdnav: %s %d resume cell %d\n", cmd, value.data1, value.data2); break; case CallSS_VMGM_PGC: fprintf(MSG_OUT, "libdvdnav: %s %d resume cell %d\n", cmd, value.data1, value.data2); break; } } void vm_print_registers( registers_t *registers ) { int32_t i; fprintf(MSG_OUT, "libdvdnav: # "); for(i = 0; i < 24; i++) fprintf(MSG_OUT, " %2d |", i); fprintf(MSG_OUT, "\nlibdvdnav: SRPMS: "); for(i = 0; i < 24; i++) fprintf(MSG_OUT, "%04x|", registers->SPRM[i]); fprintf(MSG_OUT, "\nlibdvdnav: GRPMS: "); for(i = 0; i < 16; i++) fprintf(MSG_OUT, "%04x|", get_GPRM(registers, i) ); fprintf(MSG_OUT, "\nlibdvdnav: Gmode: "); for(i = 0; i < 16; i++) fprintf(MSG_OUT, "%04x|", registers->GPRM_mode[i]); fprintf(MSG_OUT, "\nlibdvdnav: Gtime: "); for(i = 0; i < 16; i++) fprintf(MSG_OUT, "%04lx|", registers->GPRM_time[i].tv_sec & 0xffff); fprintf(MSG_OUT, "\n"); } #endif k9copy/src/libdvdnav-NOW/vm/play.c0000644000175000017550000002504712412277736017522 0ustar emulatoremulator/* * Copyright (C) 2000, 2001 Håkan Hjort * Copyright (C) 2001 Rich Wareham * 2002-2004 the dvdnav project * * This file is part of libdvdnav, a DVD navigation library. It is modified * from a file originally part of the Ogle DVD player. * * libdvdnav is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdnav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdnav; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include "dvdnav/dvdnav.h" #include "decoder.h" #include "vm.h" #include "play.h" #include "vm/getset.h" #include "dvdnav_internal.h" /* Playback control */ link_t play_PGC(vm_t *vm) { link_t link_values; #ifdef TRACE fprintf(MSG_OUT, "libdvdnav: play_PGC:"); if((vm->state).domain != FP_DOMAIN) { fprintf(MSG_OUT, " (vm->state).pgcN (%i)\n", get_PGCN(vm)); } else { fprintf(MSG_OUT, " first_play_pgc\n"); } #endif /* This must be set before the pre-commands are executed because they * might contain a CallSS that will save resume state */ /* FIXME: This may be only a temporary fix for something... */ (vm->state).pgN = 1; (vm->state).cellN = 0; (vm->state).blockN = 0; /* eval -> updates the state and returns either - some kind of jump (Jump(TT/SS/VTS_TTN/CallSS/link C/PG/PGC/PTTN) - just play video i.e first PG (This is what happens if you fall of the end of the pre_cmds) - or an error (are there more cases?) */ if((vm->state).pgc->command_tbl && (vm->state).pgc->command_tbl->nr_of_pre) { if(vmEval_CMD((vm->state).pgc->command_tbl->pre_cmds, (vm->state).pgc->command_tbl->nr_of_pre, &(vm->state).registers, &link_values)) { /* link_values contains the 'jump' return value */ return link_values; } else { #ifdef TRACE fprintf(MSG_OUT, "libdvdnav: PGC pre commands didn't do a Jump, Link or Call\n"); #endif } } return play_PG(vm); } link_t play_PGC_PG(vm_t *vm, int pgN) { link_t link_values; #ifdef TRACE fprintf(MSG_OUT, "libdvdnav: play_PGC_PG:"); if((vm->state).domain != FP_DOMAIN) { fprintf(MSG_OUT, " (vm->state).pgcN (%i)\n", get_PGCN(vm)); } else { fprintf(MSG_OUT, " first_play_pgc\n"); } #endif /* This must be set before the pre-commands are executed because they * might contain a CallSS that will save resume state */ /* FIXME: This may be only a temporary fix for something... */ (vm->state).pgN = pgN; (vm->state).cellN = 0; (vm->state).blockN = 0; /* eval -> updates the state and returns either - some kind of jump (Jump(TT/SS/VTS_TTN/CallSS/link C/PG/PGC/PTTN) - just play video i.e first PG (This is what happens if you fall of the end of the pre_cmds) - or an error (are there more cases?) */ if((vm->state).pgc->command_tbl && (vm->state).pgc->command_tbl->nr_of_pre) { if(vmEval_CMD((vm->state).pgc->command_tbl->pre_cmds, (vm->state).pgc->command_tbl->nr_of_pre, &(vm->state).registers, &link_values)) { /* link_values contains the 'jump' return value */ return link_values; } else { #ifdef TRACE fprintf(MSG_OUT, "libdvdnav: PGC pre commands didn't do a Jump, Link or Call\n"); #endif } } return play_PG(vm); } link_t play_PGC_post(vm_t *vm) { link_t link_values = { LinkNoLink, 0, 0, 0 }; #ifdef TRACE fprintf(MSG_OUT, "libdvdnav: play_PGC_post:\n"); #endif /* eval -> updates the state and returns either - some kind of jump (Jump(TT/SS/VTS_TTN/CallSS/link C/PG/PGC/PTTN) - just go to next PGC (This is what happens if you fall of the end of the post_cmds) - or an error (are there more cases?) */ if((vm->state).pgc->command_tbl && (vm->state).pgc->command_tbl->nr_of_post && vmEval_CMD((vm->state).pgc->command_tbl->post_cmds, (vm->state).pgc->command_tbl->nr_of_post, &(vm->state).registers, &link_values)) { return link_values; } #ifdef TRACE fprintf(MSG_OUT, "libdvdnav: ** Fell of the end of the pgc, continuing in NextPGC\n"); #endif /* Should end up in the STOP_DOMAIN if next_pgc is 0. */ if(!set_PGCN(vm, (vm->state).pgc->next_pgc_nr)) { link_values.command = Exit; return link_values; } return play_PGC(vm); } link_t play_PG(vm_t *vm) { #ifdef TRACE fprintf(MSG_OUT, "libdvdnav: play_PG: (vm->state).pgN (%i)\n", (vm->state).pgN); #endif assert((vm->state).pgN > 0); if((vm->state).pgN > (vm->state).pgc->nr_of_programs) { #ifdef TRACE fprintf(MSG_OUT, "libdvdnav: play_PG: (vm->state).pgN (%i) > pgc->nr_of_programs (%i)\n", (vm->state).pgN, (vm->state).pgc->nr_of_programs ); #endif assert((vm->state).pgN == (vm->state).pgc->nr_of_programs + 1); return play_PGC_post(vm); } (vm->state).cellN = (vm->state).pgc->program_map[(vm->state).pgN - 1]; return play_Cell(vm); } link_t play_Cell(vm_t *vm) { static const link_t play_this = {PlayThis, /* Block in Cell */ 0, 0, 0}; #ifdef TRACE fprintf(MSG_OUT, "libdvdnav: play_Cell: (vm->state).cellN (%i)\n", (vm->state).cellN); #endif assert((vm->state).cellN > 0); if((vm->state).cellN > (vm->state).pgc->nr_of_cells) { #ifdef TRACE fprintf(MSG_OUT, "libdvdnav: (vm->state).cellN (%i) > pgc->nr_of_cells (%i)\n", (vm->state).cellN, (vm->state).pgc->nr_of_cells ); #endif assert((vm->state).cellN == (vm->state).pgc->nr_of_cells + 1); return play_PGC_post(vm); } /* Multi angle/Interleaved */ switch((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_mode) { case 0: /* Normal */ assert((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_type == 0); break; case 1: /* The first cell in the block */ switch((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_type) { case 0: /* Not part of a block */ assert(0); break; case 1: /* Angle block */ /* Loop and check each cell instead? So we don't get outside the block? */ (vm->state).cellN += (vm->state).AGL_REG - 1; #ifdef DVDNAV_STRICT assert((vm->state).cellN <= (vm->state).pgc->nr_of_cells); assert((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_mode != 0); assert((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_type == 1); #else if (!((vm->state).cellN <= (vm->state).pgc->nr_of_cells) || !((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_mode != 0) || !((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_type == 1)) { fprintf(MSG_OUT, "libdvdnav: Invalid angle block\n"); (vm->state).cellN -= (vm->state).AGL_REG - 1; } #endif break; case 2: /* ?? */ case 3: /* ?? */ default: fprintf(MSG_OUT, "libdvdnav: Invalid? Cell block_mode (%d), block_type (%d)\n", (vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_mode, (vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_type); assert(0); } break; case 2: /* Cell in the block */ case 3: /* Last cell in the block */ /* These might perhaps happen for RSM or LinkC commands? */ default: fprintf(MSG_OUT, "libdvdnav: Cell is in block but did not enter at first cell!\n"); } /* Updates (vm->state).pgN and PTTN_REG */ if(!set_PGN(vm)) { /* Should not happen */ assert(0); return play_PGC_post(vm); } (vm->state).cell_restart++; (vm->state).blockN = 0; #ifdef TRACE fprintf(MSG_OUT, "libdvdnav: Cell should restart here\n"); #endif return play_this; } link_t play_Cell_post(vm_t *vm) { cell_playback_t *cell; #ifdef TRACE fprintf(MSG_OUT, "libdvdnav: play_Cell_post: (vm->state).cellN (%i)\n", (vm->state).cellN); #endif cell = &(vm->state).pgc->cell_playback[(vm->state).cellN - 1]; /* Still time is already taken care of before we get called. */ /* Deal with a Cell command, if any */ if(cell->cell_cmd_nr != 0) { link_t link_values; if ((vm->state).pgc->command_tbl != NULL && (vm->state).pgc->command_tbl->nr_of_cell >= cell->cell_cmd_nr) { #ifdef TRACE fprintf(MSG_OUT, "libdvdnav: Cell command present, executing\n"); #endif if(vmEval_CMD(&(vm->state).pgc->command_tbl->cell_cmds[cell->cell_cmd_nr - 1], 1, &(vm->state).registers, &link_values)) { return link_values; } else { #ifdef TRACE fprintf(MSG_OUT, "libdvdnav: Cell command didn't do a Jump, Link or Call\n"); #endif } } else { #ifdef TRACE fprintf(MSG_OUT, "libdvdnav: Invalid Cell command\n"); #endif } } /* Where to continue after playing the cell... */ /* Multi angle/Interleaved */ switch((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_mode) { case 0: /* Normal */ assert((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_type == 0); (vm->state).cellN++; break; case 1: /* The first cell in the block */ case 2: /* A cell in the block */ case 3: /* The last cell in the block */ default: switch((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_type) { case 0: /* Not part of a block */ assert(0); break; case 1: /* Angle block */ /* Skip the 'other' angles */ (vm->state).cellN++; while((vm->state).cellN <= (vm->state).pgc->nr_of_cells && (vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_mode >= 2) { (vm->state).cellN++; } break; case 2: /* ?? */ case 3: /* ?? */ default: fprintf(MSG_OUT, "libdvdnav: Invalid? Cell block_mode (%d), block_type (%d)\n", (vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_mode, (vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_type); assert(0); } break; } /* Figure out the correct pgN for the new cell */ if(!set_PGN(vm)) { #ifdef TRACE fprintf(MSG_OUT, "libdvdnav: last cell in this PGC\n"); #endif return play_PGC_post(vm); } return play_Cell(vm); } k9copy/src/libdvdnav-NOW/vm/decoder.h0000644000175000017550000000523212412277736020161 0ustar emulatoremulator/* * Copyright (C) 2000, 2001 Martin Norbäck, Håkan Hjort * * This file is part of libdvdnav, a DVD navigation library. It is modified * from a file originally part of the Ogle DVD player. * * libdvdnav is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdnav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdnav; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef LIBDVDNAV_DECODER_H #define LIBDVDNAV_DECODER_H #include /* link command types */ typedef enum { LinkNoLink = 0, LinkTopC = 1, LinkNextC = 2, LinkPrevC = 3, LinkTopPG = 5, LinkNextPG = 6, LinkPrevPG = 7, LinkTopPGC = 9, LinkNextPGC = 10, LinkPrevPGC = 11, LinkGoUpPGC = 12, LinkTailPGC = 13, LinkRSM = 16, LinkPGCN, LinkPTTN, LinkPGN, LinkCN, Exit, JumpTT, /* 22 */ JumpVTS_TT, JumpVTS_PTT, JumpSS_FP, JumpSS_VMGM_MENU, JumpSS_VTSM, JumpSS_VMGM_PGC, CallSS_FP, /* 29 */ CallSS_VMGM_MENU, CallSS_VTSM, CallSS_VMGM_PGC, PlayThis } link_cmd_t; /* a link's data set */ typedef struct { link_cmd_t command; uint16_t data1; uint16_t data2; uint16_t data3; } link_t; /* the VM registers */ typedef struct { uint16_t SPRM[24]; uint16_t GPRM[16]; uint8_t GPRM_mode[16]; /* Need to have some thing to indicate normal/counter mode for every GPRM */ struct timeval GPRM_time[16]; /* For counter mode */ } registers_t; /* a VM command data set */ typedef struct { uint64_t instruction; uint64_t examined; registers_t *registers; } command_t; /* the big VM function, executing the given commands and writing * the link where to continue, the return value indicates if a jump * has been performed */ int32_t vmEval_CMD(vm_cmd_t commands[], int32_t num_commands, registers_t *registers, link_t *return_values); /* extracts some bits from the command */ uint32_t vm_getbits(command_t* command, int32_t start, int32_t count); #ifdef TRACE /* for debugging: prints a link in readable form */ void vm_print_link(link_t value); /* for debugging: dumps VM registers */ void vm_print_registers( registers_t *registers ); #endif #endif /* LIBDVDNAV_DECODER_H */ k9copy/src/libdvdnav-NOW/settings.c0000644000175000017550000000550512412277736017770 0ustar emulatoremulator/* * Copyright (C) 2000 Rich Wareham * * This file is part of libdvdnav, a DVD navigation library. * * libdvdnav is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdnav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdnav; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "dvdnav/dvdnav.h" #include #include #include "vm/decoder.h" #include "vm/vm.h" #include "dvdnav_internal.h" /* Characteristics/setting API calls */ dvdnav_status_t dvdnav_get_region_mask(dvdnav_t *this, int32_t *region) { (*region) = this->vm->state.registers.SPRM[20]; return DVDNAV_STATUS_OK; } dvdnav_status_t dvdnav_set_region_mask(dvdnav_t *this, int32_t mask) { pthread_mutex_lock(&this->vm_lock); this->vm->state.registers.SPRM[20] = (mask & 0xff); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } dvdnav_status_t dvdnav_set_readahead_flag(dvdnav_t *this, int32_t use_readahead) { this->use_read_ahead = use_readahead; return DVDNAV_STATUS_OK; } dvdnav_status_t dvdnav_get_readahead_flag(dvdnav_t *this, int32_t *flag) { (*flag) = this->use_read_ahead; return DVDNAV_STATUS_OK; } static dvdnav_status_t set_language_register(dvdnav_t *this, char *code, int reg) { if(!code[0] || !code[1]) { printerr("Passed illegal language code."); return DVDNAV_STATUS_ERR; } pthread_mutex_lock(&this->vm_lock); this->vm->state.registers.SPRM[reg] = (code[0] << 8) | code[1]; pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } dvdnav_status_t dvdnav_menu_language_select(dvdnav_t *this, char *code) { return set_language_register(this, code, 0); } dvdnav_status_t dvdnav_audio_language_select(dvdnav_t *this, char *code) { return set_language_register(this, code, 16); } dvdnav_status_t dvdnav_spu_language_select(dvdnav_t *this, char *code) { return set_language_register(this, code, 18); } dvdnav_status_t dvdnav_set_PGC_positioning_flag(dvdnav_t *this, int32_t pgc) { this->pgc_based = pgc; return DVDNAV_STATUS_OK; } dvdnav_status_t dvdnav_get_PGC_positioning_flag(dvdnav_t *this, int32_t *flag) { (*flag) = this->pgc_based; return DVDNAV_STATUS_OK; } k9copy/src/libdvdnav-NOW/dvdnav.c0000644000175000017550000011040112412301251017356 0ustar emulatoremulator/* * Copyright (C) 2000 Rich Wareham * * This file is part of libdvdnav, a DVD navigation library. * * libdvdnav is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdnav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdnav; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* #define LOG_DEBUG */ #include #include #include #include #include #include #include #include "dvdnav/dvdnav.h" #include #include #include /* For vm_cmd_t */ #include "vm/decoder.h" #include "vm/vm.h" #include "dvdnav_internal.h" #include "read_cache.h" #include static dvdnav_status_t dvdnav_clear(dvdnav_t * this) { /* clear everything except file, vm, mutex, readahead */ pthread_mutex_lock(&this->vm_lock); if (this->file) DVDCloseFile(this->file); this->file = NULL; memset(&this->position_current,0,sizeof(this->position_current)); memset(&this->pci,0,sizeof(this->pci)); memset(&this->dsi,0,sizeof(this->dsi)); this->last_cmd_nav_lbn = SRI_END_OF_CELL; /* Set initial values of flags */ this->skip_still = 0; this->sync_wait = 0; this->sync_wait_skip = 0; this->spu_clut_changed = 0; this->started = 0; this->cur_cell_time = 0; dvdnav_read_cache_clear(this->cache); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } dvdnav_status_t dvdnav_dup(dvdnav_t **dest, dvdnav_t *src) { dvdnav_t *this; (*dest) = NULL; this = (dvdnav_t*)malloc(sizeof(dvdnav_t)); if(!this) return DVDNAV_STATUS_ERR; memcpy(this, src, sizeof(dvdnav_t)); this->file = NULL; pthread_mutex_init(&this->vm_lock, NULL); this->vm = vm_new_copy(src->vm); if(!this->vm) { printerr("Error initialising the DVD VM."); pthread_mutex_destroy(&this->vm_lock); free(this); return DVDNAV_STATUS_ERR; } /* Start the read-ahead cache. */ this->cache = dvdnav_read_cache_new(this); (*dest) = this; return DVDNAV_STATUS_OK; } dvdnav_status_t dvdnav_free_dup(dvdnav_t *this) { #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: free_dup:called\n"); #endif if (this->file) { pthread_mutex_lock(&this->vm_lock); DVDCloseFile(this->file); #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: close:file closing\n"); #endif this->file = NULL; pthread_mutex_unlock(&this->vm_lock); } /* Free the VM */ if(this->vm) vm_free_copy(this->vm); pthread_mutex_destroy(&this->vm_lock); free(this->path); /* We leave the final freeing of the entire structure to the cache, * because we don't know, if there are still buffers out in the wild, * that must return first. */ if(this->cache) dvdnav_read_cache_free(this->cache); else free(this); return DVDNAV_STATUS_OK; } dvdnav_status_t dvdnav_open(dvdnav_t** dest, const char *path) { dvdnav_t *this; struct timeval time; /* Create a new structure */ /*PM fprintf(MSG_OUT, "libdvdnav: Using dvdnav version %s\n", VERSION); */ (*dest) = NULL; this = (dvdnav_t*)calloc(1, sizeof(dvdnav_t)); if(!this) return DVDNAV_STATUS_ERR; pthread_mutex_init(&this->vm_lock, NULL); /* Initialise the error string */ printerr(""); /* Initialise the VM */ this->vm = vm_new_vm(); if(!this->vm) { printerr("Error initialising the DVD VM."); goto fail; } if(!vm_reset(this->vm, path)) { printerr("Error starting the VM / opening the DVD device."); goto fail; } /* Set the path. */ this->path = strdup(path); if(!this->path) goto fail; /* Pre-open and close a file so that the CSS-keys are cached. */ this->file = DVDOpenFile(vm_get_dvd_reader(this->vm), 0, DVD_READ_MENU_VOBS); /* Start the read-ahead cache. */ this->cache = dvdnav_read_cache_new(this); if(!this->cache) goto fail; /* Seed the random numbers. So that the DVD VM Command rand() * gives a different start value each time a DVD is played. */ gettimeofday(&time, NULL); srand(time.tv_usec); dvdnav_clear(this); (*dest) = this; return DVDNAV_STATUS_OK; fail: pthread_mutex_destroy(&this->vm_lock); vm_free_vm(this->vm); free(this->path); free(this); return DVDNAV_STATUS_ERR; } dvdnav_status_t dvdnav_close(dvdnav_t *this) { #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: close:called\n"); #endif if (this->file) { pthread_mutex_lock(&this->vm_lock); DVDCloseFile(this->file); #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: close:file closing\n"); #endif this->file = NULL; pthread_mutex_unlock(&this->vm_lock); } /* Free the VM */ if(this->vm) vm_free_vm(this->vm); pthread_mutex_destroy(&this->vm_lock); free(this->path); /* We leave the final freeing of the entire structure to the cache, * because we don't know, if there are still buffers out in the wild, * that must return first. */ if(this->cache) dvdnav_read_cache_free(this->cache); else free(this); return DVDNAV_STATUS_OK; } dvdnav_status_t dvdnav_reset(dvdnav_t *this) { dvdnav_status_t result; #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: reset:called\n"); #endif pthread_mutex_lock(&this->vm_lock); #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: reseting vm\n"); #endif if(!vm_reset(this->vm, NULL)) { printerr("Error restarting the VM."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: clearing dvdnav\n"); #endif pthread_mutex_unlock(&this->vm_lock); result = dvdnav_clear(this); return result; } dvdnav_status_t dvdnav_path(dvdnav_t *this, const char** path) { (*path) = this->path; return DVDNAV_STATUS_OK; } const char* dvdnav_err_to_string(dvdnav_t *this) { if(!this) return "Hey! You gave me a NULL pointer you naughty person!"; return this->err_str; } /* converts a dvd_time_t to PTS ticks */ int64_t dvdnav_convert_time(dvd_time_t *time) { int64_t result; int64_t frames; result = ((int64_t)(time->hour >> 4 )) * 10 * 60 * 60 * 90000; result += ((int64_t)(time->hour & 0x0f)) * 60 * 60 * 90000; result += ((int64_t)(time->minute >> 4 )) * 10 * 60 * 90000; result += ((int64_t)(time->minute & 0x0f)) * 60 * 90000; result += ((int64_t)(time->second >> 4 )) * 10 * 90000; result += ((int64_t)(time->second & 0x0f)) * 90000; frames = ((time->frame_u & 0x30) >> 4) * 10; frames += ((time->frame_u & 0x0f) ) ; if (time->frame_u & 0x80) result += frames * 3000; else result += frames * 3600; return result; } /* * Returns 1 if block contains NAV packet, 0 otherwise. * Processes said NAV packet if present. * * Most of the code in here is copied from xine's MPEG demuxer * so any bugs which are found in that should be corrected here also. */ static int32_t dvdnav_decode_packet(uint8_t *p, dsi_t *nav_dsi, pci_t *nav_pci) { int32_t bMpeg1 = 0; uint32_t nHeaderLen; uint32_t nPacketLen; uint32_t nStreamID; if (p[3] == 0xBA) { /* program stream pack header */ int32_t nStuffingBytes; bMpeg1 = (p[4] & 0x40) == 0; if (bMpeg1) { p += 12; } else { /* mpeg2 */ nStuffingBytes = p[0xD] & 0x07; p += 14 + nStuffingBytes; } } if (p[3] == 0xbb) { /* program stream system header */ nHeaderLen = (p[4] << 8) | p[5]; p += 6 + nHeaderLen; } /* we should now have a PES packet here */ if (p[0] || p[1] || (p[2] != 1)) { fprintf(MSG_OUT, "libdvdnav: demux error! %02x %02x %02x (should be 0x000001) \n",p[0],p[1],p[2]); return 0; } nPacketLen = p[4] << 8 | p[5]; nStreamID = p[3]; nHeaderLen = 6; p += nHeaderLen; if (nStreamID == 0xbf) { /* Private stream 2 */ #if 0 int32_t i; fprintf(MSG_OUT, "libdvdnav: nav packet=%u\n",p-p_start-6); for(i=0;i<80;i++) fprintf(MSG_OUT, "%02x ",p[i-6]); fprintf(MSG_OUT, "\n"); #endif if(p[0] == 0x00) { navRead_PCI(nav_pci, p+1); } p += nPacketLen; /* We should now have a DSI packet. */ if(p[6] == 0x01) { nPacketLen = p[4] << 8 | p[5]; p += 6; navRead_DSI(nav_dsi, p+1); } return 1; } return 0; } /* DSI is used for most angle stuff. * PCI is used for only non-seemless angle stuff */ static int32_t dvdnav_get_vobu(dvdnav_t *this, dsi_t *nav_dsi, pci_t *nav_pci, dvdnav_vobu_t *vobu) { uint32_t next; int32_t angle, num_angle; vobu->vobu_start = nav_dsi->dsi_gi.nv_pck_lbn; /* Absolute offset from start of disk */ vobu->vobu_length = nav_dsi->dsi_gi.vobu_ea; /* Relative offset from vobu_start */ /* * If we're not at the end of this cell, we can determine the next * VOBU to display using the VOBU_SRI information section of the * DSI. Using this value correctly follows the current angle, * avoiding the doubled scenes in The Matrix, and makes our life * really happy. * * vobu_next is an offset value, 0x3fffffff = SRI_END_OF_CELL * DVDs are about 6 Gigs, which is only up to 0x300000 blocks * Should really assert if bit 31 != 1 */ #if 0 /* Old code -- may still be useful one day */ if(nav_dsi->vobu_sri.next_vobu != SRI_END_OF_CELL ) { vobu->vobu_next = ( nav_dsi->vobu_sri.next_vobu & 0x3fffffff ); } else { vobu->vobu_next = vobu->vobu_length; } #else /* Relative offset from vobu_start */ vobu->vobu_next = ( nav_dsi->vobu_sri.next_vobu & 0x3fffffff ); #endif vm_get_angle_info(this->vm, &angle, &num_angle); /* FIMXE: The angle reset doesn't work for some reason for the moment */ #if 0 if((num_angle < angle) && (angle != 1)) { fprintf(MSG_OUT, "libdvdnav: angle ends!\n"); /* This is to switch back to angle one when we * finish with angles. */ dvdnav_angle_change(this, 1); } #endif /* only use ILVU information if we are at the last vobunit in ILVU */ /* otherwise we will miss nav packets from vobunits inbetween */ if(num_angle != 0 && (nav_dsi->sml_pbi.category & DSI_ILVU_MASK) == (DSI_ILVU_BLOCK | DSI_ILVU_LAST)) { if((next = nav_pci->nsml_agli.nsml_agl_dsta[angle-1]) != 0) { if((next & 0x3fffffff) != 0) { if(next & 0x80000000) vobu->vobu_next = - (int32_t)(next & 0x3fffffff); else vobu->vobu_next = + (int32_t)(next & 0x3fffffff); } } else if((next = nav_dsi->sml_agli.data[angle-1].address) != 0) { vobu->vobu_length = nav_dsi->sml_pbi.ilvu_ea; if((next & 0x80000000) && (next != 0x7fffffff)) vobu->vobu_next = - (int32_t)(next & 0x3fffffff); else vobu->vobu_next = + (int32_t)(next & 0x3fffffff); } } return 1; } /* * These are the main get_next_block function which actually get the media stream video and audio etc. * * There are two versions: The second one is using the zero-copy read ahead cache and therefore * hands out pointers targetting directly into the cache. * The first one uses a memcopy to fill this cache block into the application provided memory. * The benefit of this first one is that no special memory management is needed. The application is * the only one responsible of allocating and freeing the memory associated with the pointer. * The drawback is the additional memcopy. */ dvdnav_status_t dvdnav_get_next_block(dvdnav_t *this, uint8_t *buf, int32_t *event, int32_t *len) { unsigned char *block; dvdnav_status_t status; block = buf; status = dvdnav_get_next_cache_block(this, &block, event, len); if (status == DVDNAV_STATUS_OK && block != buf) { /* we received a block from the cache, copy it, so we can give it back */ memcpy(buf, block, DVD_VIDEO_LB_LEN); dvdnav_free_cache_block(this, block); } return status; } int64_t dvdnav_get_current_time(dvdnav_t *this) { int i; int64_t tm=0; dvd_state_t *state = &this->vm->state; for(i=0; icellN-1; i++) { if(! (state->pgc->cell_playback[i].block_type == BLOCK_TYPE_ANGLE_BLOCK && state->pgc->cell_playback[i].block_mode != BLOCK_MODE_FIRST_CELL) ) tm += dvdnav_convert_time(&state->pgc->cell_playback[i].playback_time); } tm += this->cur_cell_time; return tm; } dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, uint8_t **buf, int32_t *event, int32_t *len) { dvd_state_t *state; int32_t result; if(!this) return DVDNAV_STATUS_ERR; pthread_mutex_lock(&this->vm_lock); if(!this->started) { /* Start the VM */ if (!vm_start(this->vm)) { printerr("Encrypted or faulty DVD"); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } this->started = 1; } state = &(this->vm->state); (*event) = DVDNAV_NOP; (*len) = 0; /* Check the STOP flag */ if(this->vm->stopped) { vm_stop(this->vm); (*event) = DVDNAV_STOP; this->started = 0; pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } vm_position_get(this->vm, &this->position_next); #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: POS-NEXT "); vm_position_print(this->vm, &this->position_next); fprintf(MSG_OUT, "libdvdnav: POS-CUR "); vm_position_print(this->vm, &this->position_current); #endif /* did we hop? */ if(this->position_current.hop_channel != this->position_next.hop_channel) { (*event) = DVDNAV_HOP_CHANNEL; #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: HOP_CHANNEL\n"); #endif if (this->position_next.hop_channel - this->position_current.hop_channel >= HOP_SEEK) { int32_t num_angles = 0, current; /* we seeked -> check for multiple angles */ vm_get_angle_info(this->vm, ¤t, &num_angles); if (num_angles > 1) { int32_t result, block; /* we have to skip the first VOBU when seeking in a multiangle feature, * because it might belong to the wrong angle */ block = this->position_next.cell_start + this->position_next.block; result = dvdnav_read_cache_block(this->cache, block, 1, buf); if(result <= 0) { printerr("Error reading NAV packet."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } /* Decode nav into pci and dsi. Then get next VOBU info. */ if(!dvdnav_decode_packet(*buf, &this->dsi, &this->pci)) { printerr("Expected NAV packet but none found."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } dvdnav_get_vobu(this, &this->dsi, &this->pci, &this->vobu); /* skip to next, if there is a next */ if (this->vobu.vobu_next != SRI_END_OF_CELL) { this->vobu.vobu_start += this->vobu.vobu_next; this->vobu.vobu_next = 0; } /* update VM state */ this->vm->state.blockN = this->vobu.vobu_start - this->position_next.cell_start; } } this->position_current.hop_channel = this->position_next.hop_channel; /* update VOBU info */ this->vobu.vobu_start = this->position_next.cell_start + this->position_next.block; this->vobu.vobu_next = 0; /* Make blockN == vobu_length to do expected_nav */ this->vobu.vobu_length = 0; this->vobu.blockN = 0; this->sync_wait = 0; pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } /* Check the HIGHLIGHT flag */ if(this->position_current.button != this->position_next.button) { dvdnav_highlight_event_t *hevent = (dvdnav_highlight_event_t *)*buf; (*event) = DVDNAV_HIGHLIGHT; #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: HIGHLIGHT\n"); #endif (*len) = sizeof(dvdnav_highlight_event_t); hevent->display = 1; hevent->buttonN = this->position_next.button; this->position_current.button = this->position_next.button; pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } /* Check the WAIT flag */ if(this->sync_wait) { (*event) = DVDNAV_WAIT; #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: WAIT\n"); #endif (*len) = 0; pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } /* Check to see if we need to change the currently opened VOB or open * a new one because we don't currently have an opened VOB. */ if((this->file == NULL) || (this->position_current.vts != this->position_next.vts) || (this->position_current.domain != this->position_next.domain)) { dvd_read_domain_t domain; int32_t vtsN; dvdnav_vts_change_event_t *vts_event = (dvdnav_vts_change_event_t *)*buf; if(this->file) { DVDCloseFile(this->file); this->file = NULL; } vts_event->old_vtsN = this->position_current.vts; vts_event->old_domain = this->position_current.domain; /* Use the DOMAIN to find whether to open menu or title VOBs */ switch(this->position_next.domain) { case DVD_DOMAIN_FirstPlay: case DVD_DOMAIN_VMGM: domain = DVD_READ_MENU_VOBS; vtsN = 0; break; case DVD_DOMAIN_VTSMenu: domain = DVD_READ_MENU_VOBS; vtsN = this->position_next.vts; break; case DVD_DOMAIN_VTSTitle: domain = DVD_READ_TITLE_VOBS; vtsN = this->position_next.vts; break; default: printerr("Unknown domain when changing VTS."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } this->position_current.vts = this->position_next.vts; this->position_current.domain = this->position_next.domain; dvdnav_read_cache_clear(this->cache); this->file = DVDOpenFile(vm_get_dvd_reader(this->vm), vtsN, domain); vts_event->new_vtsN = this->position_next.vts; vts_event->new_domain = this->position_next.domain; /* If couldn't open the file for some reason, moan */ if(this->file == NULL) { printerrf("Error opening vtsN=%i, domain=%i.", vtsN, domain); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } /* File opened successfully so return a VTS change event */ (*event) = DVDNAV_VTS_CHANGE; #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: VTS_CHANGE\n"); #endif (*len) = sizeof(dvdnav_vts_change_event_t); this->spu_clut_changed = 1; this->position_current.cell = -1; /* Force an update */ this->position_current.spu_channel = -1; /* Force an update */ this->position_current.audio_channel = -1; /* Force an update */; pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } /* Check if the cell changed */ if( (this->position_current.cell != this->position_next.cell) || (this->position_current.cell_restart != this->position_next.cell_restart) || (this->position_current.cell_start != this->position_next.cell_start) ) { dvdnav_cell_change_event_t *cell_event = (dvdnav_cell_change_event_t *)*buf; int32_t first_cell_nr, last_cell_nr, i; dvd_state_t *state = &this->vm->state; this->cur_cell_time = 0; (*event) = DVDNAV_CELL_CHANGE; #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: CELL_CHANGE\n"); #endif (*len) = sizeof(dvdnav_cell_change_event_t); cell_event->cellN = state->cellN; cell_event->pgN = state->pgN; cell_event->cell_length = dvdnav_convert_time(&state->pgc->cell_playback[state->cellN-1].playback_time); cell_event->pg_length = 0; /* Find start cell of program. */ first_cell_nr = state->pgc->program_map[state->pgN-1]; /* Find end cell of program */ if(state->pgN < state->pgc->nr_of_programs) last_cell_nr = state->pgc->program_map[state->pgN] - 1; else last_cell_nr = state->pgc->nr_of_cells; for (i = first_cell_nr; i <= last_cell_nr; i++) cell_event->pg_length += dvdnav_convert_time(&state->pgc->cell_playback[i - 1].playback_time); cell_event->pgc_length = dvdnav_convert_time(&state->pgc->playback_time); cell_event->cell_start = 0; for (i = 1; i < state->cellN; i++) cell_event->cell_start += dvdnav_convert_time(&state->pgc->cell_playback[i - 1].playback_time); cell_event->pg_start = 0; for (i = 1; i < state->pgc->program_map[state->pgN-1]; i++) cell_event->pg_start += dvdnav_convert_time(&state->pgc->cell_playback[i - 1].playback_time); this->position_current.cell = this->position_next.cell; this->position_current.cell_restart = this->position_next.cell_restart; this->position_current.cell_start = this->position_next.cell_start; this->position_current.block = this->position_next.block; /* vobu info is used for mid cell resumes */ this->vobu.vobu_start = this->position_next.cell_start + this->position_next.block; this->vobu.vobu_next = 0; /* Make blockN == vobu_length to do expected_nav */ this->vobu.vobu_length = 0; this->vobu.blockN = 0; /* update the spu palette at least on PGC changes */ this->spu_clut_changed = 1; this->position_current.spu_channel = -1; /* Force an update */ this->position_current.audio_channel = -1; /* Force an update */ pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } /* has the CLUT changed? */ if(this->spu_clut_changed) { (*event) = DVDNAV_SPU_CLUT_CHANGE; #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: SPU_CLUT_CHANGE\n"); #endif (*len) = 16 * sizeof(uint32_t); memcpy(*buf, state->pgc->palette, sizeof(state->pgc->palette)); this->spu_clut_changed = 0; pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } /* has the SPU channel changed? */ if(this->position_current.spu_channel != this->position_next.spu_channel) { dvdnav_spu_stream_change_event_t *stream_change = (dvdnav_spu_stream_change_event_t *)*buf; (*event) = DVDNAV_SPU_STREAM_CHANGE; #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: SPU_STREAM_CHANGE\n"); #endif (*len) = sizeof(dvdnav_spu_stream_change_event_t); stream_change->physical_wide = vm_get_subp_active_stream(this->vm, 0); stream_change->physical_letterbox = vm_get_subp_active_stream(this->vm, 1); stream_change->physical_pan_scan = vm_get_subp_active_stream(this->vm, 2); this->position_current.spu_channel = this->position_next.spu_channel; #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: SPU_STREAM_CHANGE stream_id_wide=%d\n",stream_change->physical_wide); fprintf(MSG_OUT, "libdvdnav: SPU_STREAM_CHANGE stream_id_letterbox=%d\n",stream_change->physical_letterbox); fprintf(MSG_OUT, "libdvdnav: SPU_STREAM_CHANGE stream_id_pan_scan=%d\n",stream_change->physical_pan_scan); fprintf(MSG_OUT, "libdvdnav: SPU_STREAM_CHANGE returning DVDNAV_STATUS_OK\n"); #endif pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } /* has the audio channel changed? */ if(this->position_current.audio_channel != this->position_next.audio_channel) { dvdnav_audio_stream_change_event_t *stream_change = (dvdnav_audio_stream_change_event_t *)*buf; (*event) = DVDNAV_AUDIO_STREAM_CHANGE; #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: AUDIO_STREAM_CHANGE\n"); #endif (*len) = sizeof(dvdnav_audio_stream_change_event_t); stream_change->physical = vm_get_audio_active_stream( this->vm ); stream_change->logical = this->position_next.audio_channel; this->position_current.audio_channel = this->position_next.audio_channel; #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: AUDIO_STREAM_CHANGE stream_id=%d returning DVDNAV_STATUS_OK\n",stream_change->physical); #endif pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } /* Check the STILLFRAME flag */ if(this->position_current.still != 0) { dvdnav_still_event_t *still_event = (dvdnav_still_event_t *)*buf; (*event) = DVDNAV_STILL_FRAME; #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: STILL_FRAME\n"); #endif (*len) = sizeof(dvdnav_still_event_t); still_event->length = this->position_current.still; pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } /* Have we reached the end of a VOBU? */ if (this->vobu.blockN >= this->vobu.vobu_length) { /* Have we reached the end of a cell? */ if(this->vobu.vobu_next == SRI_END_OF_CELL) { /* End of Cell from NAV DSI info */ #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: Still set to %x\n", this->position_next.still); #endif this->position_current.still = this->position_next.still; /* we are about to leave a cell, so a lot of state changes could occur; * under certain conditions, the application should get in sync with us before this, * otherwise it might show stills or menus too shortly */ if ((this->position_current.still || this->pci.hli.hl_gi.hli_ss) && !this->sync_wait_skip) this->sync_wait = 1; if(!this->position_current.still || this->skip_still ) { /* no active cell still -> get us to the next cell */ vm_get_next_cell(this->vm); this->position_current.still = 0; /* still gets activated at end of cell */ this->skip_still = 0; this->sync_wait_skip = 0; } /* handle related state changes in next iteration */ (*event) = DVDNAV_NOP; (*len) = 0; pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } /* at the start of the next VOBU -> expecting NAV packet */ result = dvdnav_read_cache_block(this->cache, this->vobu.vobu_start + this->vobu.vobu_next, 1, buf); if(result <= 0) { printerr("Error reading NAV packet."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } /* Decode nav into pci and dsi. Then get next VOBU info. */ if(!dvdnav_decode_packet(*buf, &this->dsi, &this->pci)) { printerr("Expected NAV packet but none found."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } /* We need to update the vm state->blockN with which VOBU we are in. * This is so RSM resumes to the VOBU level and not just the CELL level. */ this->vm->state.blockN = this->vobu.vobu_start - this->position_current.cell_start; dvdnav_get_vobu(this, &this->dsi, &this->pci, &this->vobu); this->vobu.blockN = 0; /* Give the cache a hint about the size of next VOBU. * This improves pre-caching, because the VOBU will almost certainly be read entirely. */ dvdnav_pre_cache_blocks(this->cache, this->vobu.vobu_start+1, this->vobu.vobu_length+1); /* release NAV menu filter, when we reach the same NAV packet again */ if (this->last_cmd_nav_lbn == this->pci.pci_gi.nv_pck_lbn) this->last_cmd_nav_lbn = SRI_END_OF_CELL; /* Successfully got a NAV packet */ (*event) = DVDNAV_NAV_PACKET; #ifdef LOG_DEBUG fprintf(MSG_OUT, "libdvdnav: NAV_PACKET\n"); #endif (*len) = 2048; this->cur_cell_time = dvdnav_convert_time(&this->dsi.dsi_gi.c_eltm); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } /* If we've got here, it must just be a normal block. */ if(!this->file) { printerr("Attempting to read without opening file."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } this->vobu.blockN++; result = dvdnav_read_cache_block(this->cache, this->vobu.vobu_start + this->vobu.blockN, 1, buf); if(result <= 0) { printerr("Error reading from DVD."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } (*event) = DVDNAV_BLOCK_OK; (*len) = 2048; pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } dvdnav_status_t dvdnav_get_title_string(dvdnav_t *this, const char **title_str) { (*title_str) = this->vm->dvd_name; return DVDNAV_STATUS_OK; } dvdnav_status_t dvdnav_get_serial_string(dvdnav_t *this, const char **serial_str) { (*serial_str) = this->vm->dvd_serial; return DVDNAV_STATUS_OK; } uint8_t dvdnav_get_video_aspect(dvdnav_t *this) { uint8_t retval; if(!this->started) { printerr("Virtual DVD machine not started."); return -1; } pthread_mutex_lock(&this->vm_lock); retval = (uint8_t)vm_get_video_aspect(this->vm); pthread_mutex_unlock(&this->vm_lock); return retval; } int dvdnav_get_video_resolution(dvdnav_t *this, uint32_t *width, uint32_t *height) { int w, h; if(!this->started) { printerr("Virtual DVD machine not started."); return -1; } pthread_mutex_lock(&this->vm_lock); vm_get_video_res(this->vm, &w, &h); pthread_mutex_unlock(&this->vm_lock); *width = w; *height = h; return 0; } uint8_t dvdnav_get_video_scale_permission(dvdnav_t *this) { uint8_t retval; if(!this->started) { printerr("Virtual DVD machine not started."); return -1; } pthread_mutex_lock(&this->vm_lock); retval = (uint8_t)vm_get_video_scale_permission(this->vm); pthread_mutex_unlock(&this->vm_lock); return retval; } uint16_t dvdnav_audio_stream_to_lang(dvdnav_t *this, uint8_t stream) { audio_attr_t attr; if(!this->started) { printerr("Virtual DVD machine not started."); return -1; } pthread_mutex_lock(&this->vm_lock); attr = vm_get_audio_attr(this->vm, stream); pthread_mutex_unlock(&this->vm_lock); if(attr.lang_type != 1) return 0xffff; return attr.lang_code; } uint16_t dvdnav_audio_stream_format(dvdnav_t *this, uint8_t stream) { audio_attr_t attr; uint16_t format; if(!this->started) { printerr("Virtual DVD machine not started."); return -1; /* 0xffff */ } pthread_mutex_lock(&this->vm_lock); attr = vm_get_audio_attr(this->vm, stream); pthread_mutex_unlock(&this->vm_lock); switch(attr.audio_format) { case 0: format = DVD_AUDIO_FORMAT_AC3; break; case 2: /* MPEG-1 or MPEG-2 without extension bitstream. */ case 3: /* MPEG-2 with extension bitstream. */ format = DVD_AUDIO_FORMAT_MPEG2_EXT; break; case 4: format = DVD_AUDIO_FORMAT_LPCM; break; case 6: format = DVD_AUDIO_FORMAT_DTS; break; case 7: format = DVD_AUDIO_FORMAT_SDDS; break; default: format = 0xffff; break; } return format; } uint16_t dvdnav_audio_stream_channels(dvdnav_t *this, uint8_t stream) { audio_attr_t attr; if(!this->started) { printerr("Virtual DVD machine not started."); return -1; /* 0xffff */ } pthread_mutex_lock(&this->vm_lock); attr = vm_get_audio_attr(this->vm, stream); pthread_mutex_unlock(&this->vm_lock); return attr.channels + 1; } uint16_t dvdnav_spu_stream_to_lang(dvdnav_t *this, uint8_t stream) { subp_attr_t attr; if(!this->started) { printerr("Virtual DVD machine not started."); return -1; } pthread_mutex_lock(&this->vm_lock); attr = vm_get_subp_attr(this->vm, stream); pthread_mutex_unlock(&this->vm_lock); if(attr.type != 1) return 0xffff; return attr.lang_code; } int8_t dvdnav_get_audio_logical_stream(dvdnav_t *this, uint8_t audio_num) { int8_t retval; if(!this->started) { printerr("Virtual DVD machine not started."); return -1; } pthread_mutex_lock(&this->vm_lock); if (!this->vm->state.pgc) { printerr("No current PGC."); pthread_mutex_unlock(&this->vm_lock); return -1; } retval = vm_get_audio_stream(this->vm, audio_num); pthread_mutex_unlock(&this->vm_lock); return retval; } dvdnav_status_t dvdnav_get_audio_attr(dvdnav_t *this, uint8_t audio_num, audio_attr_t *audio_attr) { if(!this->started) { printerr("Virtual DVD machine not started."); return -1; } pthread_mutex_lock(&this->vm_lock); if (!this->vm->state.pgc) { printerr("No current PGC."); pthread_mutex_unlock(&this->vm_lock); return -1; } *audio_attr=vm_get_audio_attr(this->vm, audio_num); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } int8_t dvdnav_get_spu_logical_stream(dvdnav_t *this, uint8_t subp_num) { int8_t retval; if(!this->started) { printerr("Virtual DVD machine not started."); return -1; } pthread_mutex_lock(&this->vm_lock); if (!this->vm->state.pgc) { printerr("No current PGC."); pthread_mutex_unlock(&this->vm_lock); return -1; } retval = vm_get_subp_stream(this->vm, subp_num, 0); pthread_mutex_unlock(&this->vm_lock); return retval; } dvdnav_status_t dvdnav_get_spu_attr(dvdnav_t *this, uint8_t audio_num, subp_attr_t *subp_attr) { if(!this->started) { printerr("Virtual DVD machine not started."); return -1; } pthread_mutex_lock(&this->vm_lock); if (!this->vm->state.pgc) { printerr("No current PGC."); pthread_mutex_unlock(&this->vm_lock); return -1; } *subp_attr=vm_get_subp_attr(this->vm, audio_num); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } int8_t dvdnav_get_active_audio_stream(dvdnav_t *this) { int8_t retval; if(!this->started) { printerr("Virtual DVD machine not started."); return -1; } pthread_mutex_lock(&this->vm_lock); if (!this->vm->state.pgc) { printerr("No current PGC."); pthread_mutex_unlock(&this->vm_lock); return -1; } retval = vm_get_audio_active_stream(this->vm); pthread_mutex_unlock(&this->vm_lock); return retval; } int8_t dvdnav_get_active_spu_stream(dvdnav_t *this) { int8_t retval; if(!this->started) { printerr("Virtual DVD machine not started."); return -1; } pthread_mutex_lock(&this->vm_lock); if (!this->vm->state.pgc) { printerr("No current PGC."); pthread_mutex_unlock(&this->vm_lock); return -1; } retval = vm_get_subp_active_stream(this->vm, 0); pthread_mutex_unlock(&this->vm_lock); return retval; } static int8_t dvdnav_is_domain(dvdnav_t *this, DVDDomain_t domain) { int8_t retval; if(!this->started) { printerr("Virtual DVD machine not started."); return -1; } pthread_mutex_lock(&this->vm_lock); retval = (this->vm->state.domain == domain); pthread_mutex_unlock(&this->vm_lock); return retval; } /* First Play domain. (Menu) */ int8_t dvdnav_is_domain_fp(dvdnav_t *this) { return dvdnav_is_domain(this, DVD_DOMAIN_FirstPlay); } /* Video management Menu domain. (Menu) */ int8_t dvdnav_is_domain_vmgm(dvdnav_t *this) { return dvdnav_is_domain(this, DVD_DOMAIN_VMGM); } /* Video Title Menu domain (Menu) */ int8_t dvdnav_is_domain_vtsm(dvdnav_t *this) { return dvdnav_is_domain(this, DVD_DOMAIN_VTSMenu); } /* Video Title domain (playing movie). */ int8_t dvdnav_is_domain_vts(dvdnav_t *this) { return dvdnav_is_domain(this, DVD_DOMAIN_VTSTitle); } /* Generally delegate angle information handling to VM */ dvdnav_status_t dvdnav_angle_change(dvdnav_t *this, int32_t angle) { int32_t num, current; pthread_mutex_lock(&this->vm_lock); vm_get_angle_info(this->vm, ¤t, &num); /* Set angle SPRM if valid */ if((angle > 0) && (angle <= num)) { this->vm->state.AGL_REG = angle; } else { printerr("Passed an invalid angle number."); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_ERR; } pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } dvdnav_status_t dvdnav_get_angle_info(dvdnav_t *this, int32_t *current_angle, int32_t *number_of_angles) { pthread_mutex_lock(&this->vm_lock); vm_get_angle_info(this->vm, current_angle, number_of_angles); pthread_mutex_unlock(&this->vm_lock); return DVDNAV_STATUS_OK; } pci_t* dvdnav_get_current_nav_pci(dvdnav_t *this) { if(!this) return 0; return &this->pci; } dsi_t* dvdnav_get_current_nav_dsi(dvdnav_t *this) { if(!this) return 0; return &this->dsi; } uint32_t dvdnav_get_next_still_flag(dvdnav_t *this) { if(!this) return -1; return this->position_next.still; } user_ops_t dvdnav_get_restrictions(dvdnav_t* this) { /* * user_ops_t is a structure of 32 bits. We want to compute * the union of two of those bitfields so to make this quicker * than performing 32 ORs, we will access them as 32bits words. */ union { user_ops_t ops_struct; uint32_t ops_int; } ops, tmp; ops.ops_int = 0; if(!this->started) { printerr("Virtual DVD machine not started."); return ops.ops_struct; } pthread_mutex_lock(&this->vm_lock); ops.ops_struct = this->pci.pci_gi.vobu_uop_ctl; if(this->vm && this->vm->state.pgc) { tmp.ops_struct = this->vm->state.pgc->prohibited_ops; ops.ops_int |= tmp.ops_int; } pthread_mutex_unlock(&this->vm_lock); return ops.ops_struct; } k9copy/src/libdvdread-NOW/0000755000175000017550000000000012412304751016072 5ustar emulatoremulatork9copy/src/libdvdread-NOW/ifo_read.c0000644000175000017550000020632212412304751020013 0ustar emulatoremulator/* * Copyright (C) 2000, 2001, 2002, 2003 * Björn Englund , * Håkan Hjort * * This file is part of libdvdread. * * libdvdread is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdread is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdread; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include #include #include "bswap.h" #include "dvdread/ifo_types.h" #include "dvdread/ifo_read.h" #include "dvdread/dvd_reader.h" #include "dvdread_internal.h" #include "dvdread/bitreader.h" #ifndef DVD_BLOCK_LEN #define DVD_BLOCK_LEN 2048 #endif #ifndef NDEBUG #define CHECK_ZERO0(arg) \ if(arg != 0) { \ fprintf(stderr, "*** Zero check failed in %s:%i\n for %s = 0x%x\n", \ __FILE__, __LINE__, # arg, arg); \ } #define CHECK_ZERO(arg) \ if(memcmp(my_friendly_zeros, &arg, sizeof(arg))) { \ unsigned int i_CZ; \ fprintf(stderr, "*** Zero check failed in %s:%i\n for %s = 0x", \ __FILE__, __LINE__, # arg ); \ for(i_CZ = 0; i_CZ < sizeof(arg); i_CZ++) \ fprintf(stderr, "%02x", *((uint8_t *)&arg + i_CZ)); \ fprintf(stderr, "\n"); \ } static const uint8_t my_friendly_zeros[2048]; #else #define CHECK_ZERO0(arg) (void)(arg) #define CHECK_ZERO(arg) (void)(arg) #endif /* Prototypes for internal functions */ static int ifoRead_VMG(ifo_handle_t *ifofile); static int ifoRead_VTS(ifo_handle_t *ifofile); static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset); static int ifoRead_PGC_COMMAND_TBL(ifo_handle_t *ifofile, pgc_command_tbl_t *cmd_tbl, unsigned int offset); static int ifoRead_PGC_PROGRAM_MAP(ifo_handle_t *ifofile, pgc_program_map_t *program_map, unsigned int nr, unsigned int offset); static int ifoRead_CELL_PLAYBACK_TBL(ifo_handle_t *ifofile, cell_playback_t *cell_playback, unsigned int nr, unsigned int offset); static int ifoRead_CELL_POSITION_TBL(ifo_handle_t *ifofile, cell_position_t *cell_position, unsigned int nr, unsigned int offset); static int ifoRead_VTS_ATTRIBUTES(ifo_handle_t *ifofile, vts_attributes_t *vts_attributes, unsigned int offset); static int ifoRead_C_ADT_internal(ifo_handle_t *ifofile, c_adt_t *c_adt, unsigned int sector); static int ifoRead_VOBU_ADMAP_internal(ifo_handle_t *ifofile, vobu_admap_t *vobu_admap, unsigned int sector); static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit, unsigned int offset); static void ifoFree_PGC(pgc_t **pgc); static void ifoFree_PGC_COMMAND_TBL(pgc_command_tbl_t *cmd_tbl); static void ifoFree_PGCIT_internal(pgcit_t **pgcit); static inline int DVDFileSeekForce_( dvd_file_t *dvd_file, uint32_t offset, int force_size ) { return (DVDFileSeekForce(dvd_file, (int)offset, force_size) == (int)offset); } static inline int DVDFileSeek_( dvd_file_t *dvd_file, uint32_t offset ) { return (DVDFileSeek(dvd_file, (int)offset) == (int)offset); } static void read_video_attr(video_attr_t *va) { getbits_state_t state; uint8_t buf[sizeof(video_attr_t)]; memcpy(buf, va, sizeof(video_attr_t)); if (!dvdread_getbits_init(&state, buf)) abort(); va->mpeg_version = dvdread_getbits(&state, 2); va->video_format = dvdread_getbits(&state, 2); va->display_aspect_ratio = dvdread_getbits(&state, 2); va->permitted_df = dvdread_getbits(&state, 2); va->line21_cc_1 = dvdread_getbits(&state, 1); va->line21_cc_2 = dvdread_getbits(&state, 1); va->unknown1 = dvdread_getbits(&state, 1); va->bit_rate = dvdread_getbits(&state, 1); va->picture_size = dvdread_getbits(&state, 2); va->letterboxed = dvdread_getbits(&state, 1); va->film_mode = dvdread_getbits(&state, 1); } static void read_audio_attr(audio_attr_t *aa) { getbits_state_t state; uint8_t buf[sizeof(audio_attr_t)]; memcpy(buf, aa, sizeof(audio_attr_t)); if (!dvdread_getbits_init(&state, buf)) abort(); aa->audio_format = dvdread_getbits(&state, 3); aa->multichannel_extension = dvdread_getbits(&state, 1); aa->lang_type = dvdread_getbits(&state, 2); aa->application_mode = dvdread_getbits(&state, 2); aa->quantization = dvdread_getbits(&state, 2); aa->sample_frequency = dvdread_getbits(&state, 2); aa->unknown1 = dvdread_getbits(&state, 1); aa->channels = dvdread_getbits(&state, 3); aa->lang_code = dvdread_getbits(&state, 16); aa->lang_extension = dvdread_getbits(&state, 8); aa->code_extension = dvdread_getbits(&state, 8); aa->unknown3 = dvdread_getbits(&state, 8); aa->app_info.karaoke.unknown4 = dvdread_getbits(&state, 1); aa->app_info.karaoke.channel_assignment = dvdread_getbits(&state, 3); aa->app_info.karaoke.version = dvdread_getbits(&state, 2); aa->app_info.karaoke.mc_intro = dvdread_getbits(&state, 1); aa->app_info.karaoke.mode = dvdread_getbits(&state, 1); } static void read_multichannel_ext(multichannel_ext_t *me) { getbits_state_t state; uint8_t buf[sizeof(multichannel_ext_t)]; memcpy(buf, me, sizeof(multichannel_ext_t)); if (!dvdread_getbits_init(&state, buf)) abort(); me->zero1 = dvdread_getbits(&state, 7); me->ach0_gme = dvdread_getbits(&state, 1); me->zero2 = dvdread_getbits(&state, 7); me->ach1_gme = dvdread_getbits(&state, 1); me->zero3 = dvdread_getbits(&state, 4); me->ach2_gv1e = dvdread_getbits(&state, 1); me->ach2_gv2e = dvdread_getbits(&state, 1); me->ach2_gm1e = dvdread_getbits(&state, 1); me->ach2_gm2e = dvdread_getbits(&state, 1); me->zero4 = dvdread_getbits(&state, 4); me->ach3_gv1e = dvdread_getbits(&state, 1); me->ach3_gv2e = dvdread_getbits(&state, 1); me->ach3_gmAe = dvdread_getbits(&state, 1); me->ach3_se2e = dvdread_getbits(&state, 1); me->zero5 = dvdread_getbits(&state, 4); me->ach4_gv1e = dvdread_getbits(&state, 1); me->ach4_gv2e = dvdread_getbits(&state, 1); me->ach4_gmBe = dvdread_getbits(&state, 1); me->ach4_seBe = dvdread_getbits(&state, 1); } static void read_subp_attr(subp_attr_t *sa) { getbits_state_t state; uint8_t buf[sizeof(subp_attr_t)]; memcpy(buf, sa, sizeof(subp_attr_t)); if (!dvdread_getbits_init(&state, buf)) abort(); sa->code_mode = dvdread_getbits(&state, 3); sa->zero1 = dvdread_getbits(&state, 3); sa->type = dvdread_getbits(&state, 2); sa->zero2 = dvdread_getbits(&state, 8); sa->lang_code = dvdread_getbits(&state, 16); sa->lang_extension = dvdread_getbits(&state, 8); sa->code_extension = dvdread_getbits(&state, 8); } static void read_user_ops(user_ops_t *uo) { getbits_state_t state; uint8_t buf[sizeof(user_ops_t)]; memcpy(buf, uo, sizeof(user_ops_t)); if (!dvdread_getbits_init(&state, buf)) abort(); uo->zero = dvdread_getbits(&state, 7); uo->video_pres_mode_change = dvdread_getbits(&state, 1); uo->karaoke_audio_pres_mode_change = dvdread_getbits(&state, 1); uo->angle_change = dvdread_getbits(&state, 1); uo->subpic_stream_change = dvdread_getbits(&state, 1); uo->audio_stream_change = dvdread_getbits(&state, 1); uo->pause_on = dvdread_getbits(&state, 1); uo->still_off = dvdread_getbits(&state, 1); uo->button_select_or_activate = dvdread_getbits(&state, 1); uo->resume = dvdread_getbits(&state, 1); uo->chapter_menu_call = dvdread_getbits(&state, 1); uo->angle_menu_call = dvdread_getbits(&state, 1); uo->audio_menu_call = dvdread_getbits(&state, 1); uo->subpic_menu_call = dvdread_getbits(&state, 1); uo->root_menu_call = dvdread_getbits(&state, 1); uo->title_menu_call = dvdread_getbits(&state, 1); uo->backward_scan = dvdread_getbits(&state, 1); uo->forward_scan = dvdread_getbits(&state, 1); uo->next_pg_search = dvdread_getbits(&state, 1); uo->prev_or_top_pg_search = dvdread_getbits(&state, 1); uo->time_or_chapter_search = dvdread_getbits(&state, 1); uo->go_up = dvdread_getbits(&state, 1); uo->stop = dvdread_getbits(&state, 1); uo->title_play = dvdread_getbits(&state, 1); uo->chapter_search_or_play = dvdread_getbits(&state, 1); uo->title_or_time_play = dvdread_getbits(&state, 1); } static void read_pgci_srp(pgci_srp_t *ps) { getbits_state_t state; uint8_t buf[sizeof(pgci_srp_t)]; memcpy(buf, ps, sizeof(pgci_srp_t)); if (!dvdread_getbits_init(&state, buf)) abort(); ps->entry_id = dvdread_getbits(&state, 8); ps->block_mode = dvdread_getbits(&state, 2); ps->block_type = dvdread_getbits(&state, 2); ps->unknown1 = dvdread_getbits(&state, 4); ps->ptl_id_mask = dvdread_getbits(&state, 16); ps->pgc_start_byte = dvdread_getbits(&state, 32); } static void read_cell_playback(cell_playback_t *cp) { getbits_state_t state; uint8_t buf[sizeof(cell_playback_t)]; memcpy(buf, cp, sizeof(cell_playback_t)); if (!dvdread_getbits_init(&state, buf)) abort(); cp->block_mode = dvdread_getbits(&state, 2); cp->block_type = dvdread_getbits(&state, 2); cp->seamless_play = dvdread_getbits(&state, 1); cp->interleaved = dvdread_getbits(&state, 1); cp->stc_discontinuity = dvdread_getbits(&state, 1); cp->seamless_angle = dvdread_getbits(&state, 1); cp->playback_mode = dvdread_getbits(&state, 1); cp->restricted = dvdread_getbits(&state, 1); cp->unknown2 = dvdread_getbits(&state, 6); cp->still_time = dvdread_getbits(&state, 8); cp->cell_cmd_nr = dvdread_getbits(&state, 8); cp->playback_time.hour = dvdread_getbits(&state, 8); cp->playback_time.minute = dvdread_getbits(&state, 8); cp->playback_time.second = dvdread_getbits(&state, 8); cp->playback_time.frame_u = dvdread_getbits(&state, 8); cp->first_sector = dvdread_getbits(&state, 32); cp->first_ilvu_end_sector = dvdread_getbits(&state, 32); cp->last_vobu_start_sector = dvdread_getbits(&state, 32); cp->last_sector = dvdread_getbits(&state, 32); } static void read_playback_type(playback_type_t *pt) { getbits_state_t state; uint8_t buf[sizeof(playback_type_t)]; memcpy(buf, pt, sizeof(playback_type_t)); if (!dvdread_getbits_init(&state, buf)) abort(); pt->zero_1 = dvdread_getbits(&state, 1); pt->multi_or_random_pgc_title = dvdread_getbits(&state, 1); pt->jlc_exists_in_cell_cmd = dvdread_getbits(&state, 1); pt->jlc_exists_in_prepost_cmd = dvdread_getbits(&state, 1); pt->jlc_exists_in_button_cmd = dvdread_getbits(&state, 1); pt->jlc_exists_in_tt_dom = dvdread_getbits(&state, 1); pt->chapter_search_or_play = dvdread_getbits(&state, 1); pt->title_or_time_play = dvdread_getbits(&state, 1); } static void free_ptl_mait(ptl_mait_t* ptl_mait, int num_entries) { int i; for (i = 0; i < num_entries; i++) free(ptl_mait->countries[i].pf_ptl_mai); free(ptl_mait->countries); free(ptl_mait); } ifo_handle_t *ifoOpen(dvd_reader_t *dvd, int title) { ifo_handle_t *ifofile; int bup_file_opened = 0; char ifo_filename[13]; ifofile = malloc(sizeof(ifo_handle_t)); if(!ifofile) return NULL; memset(ifofile, 0, sizeof(ifo_handle_t)); ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_FILE); if(!ifofile->file) { /* Failed to open IFO, try to open BUP */ ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_BACKUP_FILE); bup_file_opened = 1; } if (title) snprintf(ifo_filename, 13, "VTS_%02d_0.%s", title, bup_file_opened ? "BUP" : "IFO"); else snprintf(ifo_filename, 13, "VIDEO_TS.%s", bup_file_opened ? "BUP" : "IFO"); if(!ifofile->file) { fprintf(stderr, "libdvdread: Can't open file %s.\n", ifo_filename); free(ifofile); return NULL; } /* First check if this is a VMGI file. */ if(ifoRead_VMG(ifofile)) { /* These are both mandatory. */ if(!ifoRead_FP_PGC(ifofile) || !ifoRead_TT_SRPT(ifofile)) goto ifoOpen_try_bup; ifoRead_PGCI_UT(ifofile); ifoRead_PTL_MAIT(ifofile); /* This is also mandatory. */ if(!ifoRead_VTS_ATRT(ifofile)) goto ifoOpen_try_bup; ifoRead_TXTDT_MGI(ifofile); ifoRead_C_ADT(ifofile); ifoRead_VOBU_ADMAP(ifofile); return ifofile; } if(ifoRead_VTS(ifofile)) { if(!ifoRead_VTS_PTT_SRPT(ifofile) || !ifoRead_PGCIT(ifofile)) goto ifoOpen_try_bup; ifoRead_PGCI_UT(ifofile); ifoRead_VTS_TMAPT(ifofile); ifoRead_C_ADT(ifofile); ifoRead_VOBU_ADMAP(ifofile); if(!ifoRead_TITLE_C_ADT(ifofile) || !ifoRead_TITLE_VOBU_ADMAP(ifofile)) goto ifoOpen_try_bup; return ifofile; } ifoOpen_try_bup: if (bup_file_opened) goto ifoOpen_fail; /* Try BUP instead */ ifoClose(ifofile); ifofile = malloc(sizeof(ifo_handle_t)); if(!ifofile) return NULL; memset(ifofile, 0, sizeof(ifo_handle_t)); ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_BACKUP_FILE); if (title) snprintf(ifo_filename, 13, "VTS_%02d_0.BUP", title); else strncpy(ifo_filename, "VIDEO_TS.BUP", 13); if (!ifofile->file) { fprintf(stderr, "libdvdread: Can't open file %s.\n", ifo_filename); free(ifofile); return NULL; } bup_file_opened = 1; /* First check if this is a VMGI file. */ if(ifoRead_VMG(ifofile)) { /* These are both mandatory. */ if(!ifoRead_FP_PGC(ifofile) || !ifoRead_TT_SRPT(ifofile)) goto ifoOpen_fail; ifoRead_PGCI_UT(ifofile); ifoRead_PTL_MAIT(ifofile); /* This is also mandatory. */ if(!ifoRead_VTS_ATRT(ifofile)) goto ifoOpen_fail; ifoRead_TXTDT_MGI(ifofile); ifoRead_C_ADT(ifofile); ifoRead_VOBU_ADMAP(ifofile); return ifofile; } if(ifoRead_VTS(ifofile)) { if(!ifoRead_VTS_PTT_SRPT(ifofile) || !ifoRead_PGCIT(ifofile)) goto ifoOpen_fail; ifoRead_PGCI_UT(ifofile); ifoRead_VTS_TMAPT(ifofile); ifoRead_C_ADT(ifofile); ifoRead_VOBU_ADMAP(ifofile); if(!ifoRead_TITLE_C_ADT(ifofile) || !ifoRead_TITLE_VOBU_ADMAP(ifofile)) goto ifoOpen_fail; return ifofile; } ifoOpen_fail: fprintf(stderr, "libdvdread: Invalid IFO for title %d (%s).\n", title, ifo_filename); ifoClose(ifofile); return NULL; } ifo_handle_t *ifoOpenVMGI(dvd_reader_t *dvd) { ifo_handle_t *ifofile; ifofile = malloc(sizeof(ifo_handle_t)); if(!ifofile) return NULL; memset(ifofile, 0, sizeof(ifo_handle_t)); ifofile->file = DVDOpenFile(dvd, 0, DVD_READ_INFO_FILE); if(!ifofile->file) /* Should really catch any error and try to fallback */ ifofile->file = DVDOpenFile(dvd, 0, DVD_READ_INFO_BACKUP_FILE); if(!ifofile->file) { fprintf(stderr, "libdvdread: Can't open file VIDEO_TS.IFO.\n"); free(ifofile); return NULL; } if(ifoRead_VMG(ifofile)) return ifofile; fprintf(stderr, "libdvdread,ifoOpenVMGI(): Invalid main menu IFO (VIDEO_TS.IFO).\n"); ifoClose(ifofile); return NULL; } ifo_handle_t *ifoOpenVTSI(dvd_reader_t *dvd, int title) { ifo_handle_t *ifofile; ifofile = malloc(sizeof(ifo_handle_t)); if(!ifofile) return NULL; memset(ifofile, 0, sizeof(ifo_handle_t)); if(title <= 0 || title > 99) { fprintf(stderr, "libdvdread: ifoOpenVTSI invalid title (%d).\n", title); free(ifofile); return NULL; } ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_FILE); if(!ifofile->file) /* Should really catch any error and try to fallback */ ifofile->file = DVDOpenFile(dvd, title, DVD_READ_INFO_BACKUP_FILE); if(!ifofile->file) { fprintf(stderr, "libdvdread: Can't open file VTS_%02d_0.IFO.\n", title); free(ifofile); return NULL; } if(ifoRead_VTS(ifofile) && ifofile->vtsi_mat) return ifofile; fprintf(stderr, "libdvdread: Invalid IFO for title %d (VTS_%02d_0.IFO).\n", title, title); ifoClose(ifofile); return NULL; } void ifoClose(ifo_handle_t *ifofile) { if(!ifofile) return; ifoFree_VOBU_ADMAP(ifofile); ifoFree_TITLE_VOBU_ADMAP(ifofile); ifoFree_C_ADT(ifofile); ifoFree_TITLE_C_ADT(ifofile); ifoFree_TXTDT_MGI(ifofile); ifoFree_VTS_ATRT(ifofile); ifoFree_PTL_MAIT(ifofile); ifoFree_PGCI_UT(ifofile); ifoFree_TT_SRPT(ifofile); ifoFree_FP_PGC(ifofile); ifoFree_PGCIT(ifofile); ifoFree_VTS_PTT_SRPT(ifofile); ifoFree_VTS_TMAPT(ifofile); if(ifofile->vmgi_mat) free(ifofile->vmgi_mat); if(ifofile->vtsi_mat) free(ifofile->vtsi_mat); DVDCloseFile(ifofile->file); ifofile->file = 0; free(ifofile); ifofile = 0; } static int ifoRead_VMG(ifo_handle_t *ifofile) { vmgi_mat_t *vmgi_mat; vmgi_mat = malloc(sizeof(vmgi_mat_t)); if(!vmgi_mat) return 0; ifofile->vmgi_mat = vmgi_mat; if(!DVDFileSeek_(ifofile->file, 0)) { free(ifofile->vmgi_mat); ifofile->vmgi_mat = 0; return 0; } if(!DVDReadBytes(ifofile->file, vmgi_mat, sizeof(vmgi_mat_t))) { free(ifofile->vmgi_mat); ifofile->vmgi_mat = 0; return 0; } if(strncmp("DVDVIDEO-VMG", vmgi_mat->vmg_identifier, 12) != 0) { free(ifofile->vmgi_mat); ifofile->vmgi_mat = 0; return 0; } B2N_32(vmgi_mat->vmg_last_sector); B2N_32(vmgi_mat->vmgi_last_sector); B2N_32(vmgi_mat->vmg_category); B2N_16(vmgi_mat->vmg_nr_of_volumes); B2N_16(vmgi_mat->vmg_this_volume_nr); B2N_16(vmgi_mat->vmg_nr_of_title_sets); B2N_64(vmgi_mat->vmg_pos_code); B2N_32(vmgi_mat->vmgi_last_byte); B2N_32(vmgi_mat->first_play_pgc); B2N_32(vmgi_mat->vmgm_vobs); B2N_32(vmgi_mat->tt_srpt); B2N_32(vmgi_mat->vmgm_pgci_ut); B2N_32(vmgi_mat->ptl_mait); B2N_32(vmgi_mat->vts_atrt); B2N_32(vmgi_mat->txtdt_mgi); B2N_32(vmgi_mat->vmgm_c_adt); B2N_32(vmgi_mat->vmgm_vobu_admap); read_video_attr(&vmgi_mat->vmgm_video_attr); read_audio_attr(&vmgi_mat->vmgm_audio_attr); read_subp_attr(&vmgi_mat->vmgm_subp_attr); CHECK_ZERO(vmgi_mat->zero_1); CHECK_ZERO(vmgi_mat->zero_2); /* DVDs created by VDR-to-DVD device LG RC590M violate the following check with * vmgi_mat->zero_3 = 0x00000000010000000000000000000000000000. */ CHECK_ZERO(vmgi_mat->zero_3); CHECK_ZERO(vmgi_mat->zero_4); CHECK_ZERO(vmgi_mat->zero_5); CHECK_ZERO(vmgi_mat->zero_6); CHECK_ZERO(vmgi_mat->zero_7); CHECK_ZERO(vmgi_mat->zero_8); CHECK_ZERO(vmgi_mat->zero_9); CHECK_ZERO(vmgi_mat->zero_10); CHECK_VALUE(vmgi_mat->vmg_last_sector != 0); CHECK_VALUE(vmgi_mat->vmgi_last_sector != 0); CHECK_VALUE(vmgi_mat->vmgi_last_sector * 2 <= vmgi_mat->vmg_last_sector); CHECK_VALUE(vmgi_mat->vmgi_last_sector * 2 <= vmgi_mat->vmg_last_sector); CHECK_VALUE(vmgi_mat->vmg_nr_of_volumes != 0); CHECK_VALUE(vmgi_mat->vmg_this_volume_nr != 0); CHECK_VALUE(vmgi_mat->vmg_this_volume_nr <= vmgi_mat->vmg_nr_of_volumes); CHECK_VALUE(vmgi_mat->disc_side == 1 || vmgi_mat->disc_side == 2); CHECK_VALUE(vmgi_mat->vmg_nr_of_title_sets != 0); CHECK_VALUE(vmgi_mat->vmgi_last_byte >= 341); CHECK_VALUE(vmgi_mat->vmgi_last_byte / DVD_BLOCK_LEN <= vmgi_mat->vmgi_last_sector); /* It seems that first_play_pgc is optional. */ CHECK_VALUE(vmgi_mat->first_play_pgc < vmgi_mat->vmgi_last_byte); CHECK_VALUE(vmgi_mat->vmgm_vobs == 0 || (vmgi_mat->vmgm_vobs > vmgi_mat->vmgi_last_sector && vmgi_mat->vmgm_vobs < vmgi_mat->vmg_last_sector)); CHECK_VALUE(vmgi_mat->tt_srpt <= vmgi_mat->vmgi_last_sector); CHECK_VALUE(vmgi_mat->vmgm_pgci_ut <= vmgi_mat->vmgi_last_sector); CHECK_VALUE(vmgi_mat->ptl_mait <= vmgi_mat->vmgi_last_sector); CHECK_VALUE(vmgi_mat->vts_atrt <= vmgi_mat->vmgi_last_sector); CHECK_VALUE(vmgi_mat->txtdt_mgi <= vmgi_mat->vmgi_last_sector); CHECK_VALUE(vmgi_mat->vmgm_c_adt <= vmgi_mat->vmgi_last_sector); CHECK_VALUE(vmgi_mat->vmgm_vobu_admap <= vmgi_mat->vmgi_last_sector); CHECK_VALUE(vmgi_mat->nr_of_vmgm_audio_streams <= 1); CHECK_VALUE(vmgi_mat->nr_of_vmgm_subp_streams <= 1); return 1; } static int ifoRead_VTS(ifo_handle_t *ifofile) { vtsi_mat_t *vtsi_mat; int i; vtsi_mat = malloc(sizeof(vtsi_mat_t)); if(!vtsi_mat) return 0; ifofile->vtsi_mat = vtsi_mat; if(!DVDFileSeek_(ifofile->file, 0)) { free(ifofile->vtsi_mat); ifofile->vtsi_mat = NULL; return 0; } if(!(DVDReadBytes(ifofile->file, vtsi_mat, sizeof(vtsi_mat_t)))) { free(ifofile->vtsi_mat); ifofile->vtsi_mat = NULL; return 0; } if(strncmp("DVDVIDEO-VTS", vtsi_mat->vts_identifier, 12) != 0) { free(ifofile->vtsi_mat); ifofile->vtsi_mat = NULL; return 0; } read_video_attr(&vtsi_mat->vtsm_video_attr); read_video_attr(&vtsi_mat->vts_video_attr); read_audio_attr(&vtsi_mat->vtsm_audio_attr); for(i=0; i<8; i++) read_audio_attr(&vtsi_mat->vts_audio_attr[i]); read_subp_attr(&vtsi_mat->vtsm_subp_attr); for(i=0; i<32; i++) read_subp_attr(&vtsi_mat->vts_subp_attr[i]); B2N_32(vtsi_mat->vts_last_sector); B2N_32(vtsi_mat->vtsi_last_sector); B2N_32(vtsi_mat->vts_category); B2N_32(vtsi_mat->vtsi_last_byte); B2N_32(vtsi_mat->vtsm_vobs); B2N_32(vtsi_mat->vtstt_vobs); B2N_32(vtsi_mat->vts_ptt_srpt); B2N_32(vtsi_mat->vts_pgcit); B2N_32(vtsi_mat->vtsm_pgci_ut); B2N_32(vtsi_mat->vts_tmapt); B2N_32(vtsi_mat->vtsm_c_adt); B2N_32(vtsi_mat->vtsm_vobu_admap); B2N_32(vtsi_mat->vts_c_adt); B2N_32(vtsi_mat->vts_vobu_admap); CHECK_ZERO(vtsi_mat->zero_1); CHECK_ZERO(vtsi_mat->zero_2); CHECK_ZERO(vtsi_mat->zero_3); CHECK_ZERO(vtsi_mat->zero_4); CHECK_ZERO(vtsi_mat->zero_5); CHECK_ZERO(vtsi_mat->zero_6); CHECK_ZERO(vtsi_mat->zero_7); CHECK_ZERO(vtsi_mat->zero_8); CHECK_ZERO(vtsi_mat->zero_9); CHECK_ZERO(vtsi_mat->zero_10); CHECK_ZERO(vtsi_mat->zero_11); CHECK_ZERO(vtsi_mat->zero_12); CHECK_ZERO(vtsi_mat->zero_13); CHECK_ZERO(vtsi_mat->zero_14); CHECK_ZERO(vtsi_mat->zero_15); CHECK_ZERO(vtsi_mat->zero_16); CHECK_ZERO(vtsi_mat->zero_17); CHECK_ZERO(vtsi_mat->zero_18); CHECK_ZERO(vtsi_mat->zero_19); CHECK_ZERO(vtsi_mat->zero_20); CHECK_ZERO(vtsi_mat->zero_21); CHECK_VALUE(vtsi_mat->vtsi_last_sector*2 <= vtsi_mat->vts_last_sector); CHECK_VALUE(vtsi_mat->vtsi_last_byte/DVD_BLOCK_LEN <= vtsi_mat->vtsi_last_sector); CHECK_VALUE(vtsi_mat->vtsm_vobs == 0 || (vtsi_mat->vtsm_vobs > vtsi_mat->vtsi_last_sector && vtsi_mat->vtsm_vobs < vtsi_mat->vts_last_sector)); CHECK_VALUE(vtsi_mat->vtstt_vobs == 0 || (vtsi_mat->vtstt_vobs > vtsi_mat->vtsi_last_sector && vtsi_mat->vtstt_vobs < vtsi_mat->vts_last_sector)); CHECK_VALUE(vtsi_mat->vts_ptt_srpt <= vtsi_mat->vtsi_last_sector); CHECK_VALUE(vtsi_mat->vts_pgcit <= vtsi_mat->vtsi_last_sector); CHECK_VALUE(vtsi_mat->vtsm_pgci_ut <= vtsi_mat->vtsi_last_sector); CHECK_VALUE(vtsi_mat->vts_tmapt <= vtsi_mat->vtsi_last_sector); CHECK_VALUE(vtsi_mat->vtsm_c_adt <= vtsi_mat->vtsi_last_sector); CHECK_VALUE(vtsi_mat->vtsm_vobu_admap <= vtsi_mat->vtsi_last_sector); CHECK_VALUE(vtsi_mat->vts_c_adt <= vtsi_mat->vtsi_last_sector); CHECK_VALUE(vtsi_mat->vts_vobu_admap <= vtsi_mat->vtsi_last_sector); CHECK_VALUE(vtsi_mat->nr_of_vtsm_audio_streams <= 1); CHECK_VALUE(vtsi_mat->nr_of_vtsm_subp_streams <= 1); CHECK_VALUE(vtsi_mat->nr_of_vts_audio_streams <= 8); for(i = vtsi_mat->nr_of_vts_audio_streams; i < 8; i++) CHECK_ZERO(vtsi_mat->vts_audio_attr[i]); CHECK_VALUE(vtsi_mat->nr_of_vts_subp_streams <= 32); for(i = vtsi_mat->nr_of_vts_subp_streams; i < 32; i++) CHECK_ZERO(vtsi_mat->vts_subp_attr[i]); for(i = 0; i < 8; i++) { read_multichannel_ext(&vtsi_mat->vts_mu_audio_attr[i]); CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero1); CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero2); CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero3); CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero4); CHECK_ZERO0(vtsi_mat->vts_mu_audio_attr[i].zero5); CHECK_ZERO(vtsi_mat->vts_mu_audio_attr[i].zero6); } return 1; } static int ifoRead_PGC_COMMAND_TBL(ifo_handle_t *ifofile, pgc_command_tbl_t *cmd_tbl, unsigned int offset) { memset(cmd_tbl, 0, sizeof(pgc_command_tbl_t)); if(!DVDFileSeek_(ifofile->file, offset)) return 0; if(!(DVDReadBytes(ifofile->file, cmd_tbl, PGC_COMMAND_TBL_SIZE))) return 0; B2N_16(cmd_tbl->nr_of_pre); B2N_16(cmd_tbl->nr_of_post); B2N_16(cmd_tbl->nr_of_cell); CHECK_VALUE(cmd_tbl->nr_of_pre + cmd_tbl->nr_of_post + cmd_tbl->nr_of_cell<= 255); if(cmd_tbl->nr_of_pre != 0) { unsigned int pre_cmds_size = cmd_tbl->nr_of_pre * COMMAND_DATA_SIZE; cmd_tbl->pre_cmds = malloc(pre_cmds_size); if(!cmd_tbl->pre_cmds) return 0; if(!(DVDReadBytes(ifofile->file, cmd_tbl->pre_cmds, pre_cmds_size))) { free(cmd_tbl->pre_cmds); return 0; } } if(cmd_tbl->nr_of_post != 0) { unsigned int post_cmds_size = cmd_tbl->nr_of_post * COMMAND_DATA_SIZE; cmd_tbl->post_cmds = malloc(post_cmds_size); if(!cmd_tbl->post_cmds) { if(cmd_tbl->pre_cmds) free(cmd_tbl->pre_cmds); return 0; } if(!(DVDReadBytes(ifofile->file, cmd_tbl->post_cmds, post_cmds_size))) { if(cmd_tbl->pre_cmds) free(cmd_tbl->pre_cmds); free(cmd_tbl->post_cmds); return 0; } } if(cmd_tbl->nr_of_cell != 0) { unsigned int cell_cmds_size = cmd_tbl->nr_of_cell * COMMAND_DATA_SIZE; cmd_tbl->cell_cmds = malloc(cell_cmds_size); if(!cmd_tbl->cell_cmds) { if(cmd_tbl->pre_cmds) free(cmd_tbl->pre_cmds); if(cmd_tbl->post_cmds) free(cmd_tbl->post_cmds); return 0; } if(!(DVDReadBytes(ifofile->file, cmd_tbl->cell_cmds, cell_cmds_size))) { if(cmd_tbl->pre_cmds) free(cmd_tbl->pre_cmds); if(cmd_tbl->post_cmds) free(cmd_tbl->post_cmds); free(cmd_tbl->cell_cmds); return 0; } } /* * Make a run over all the commands and see that we can interpret them all? */ return 1; } static void ifoFree_PGC_COMMAND_TBL(pgc_command_tbl_t *cmd_tbl) { if(cmd_tbl) { if(cmd_tbl->nr_of_pre && cmd_tbl->pre_cmds) free(cmd_tbl->pre_cmds); if(cmd_tbl->nr_of_post && cmd_tbl->post_cmds) free(cmd_tbl->post_cmds); if(cmd_tbl->nr_of_cell && cmd_tbl->cell_cmds) free(cmd_tbl->cell_cmds); free(cmd_tbl); } } static int ifoRead_PGC_PROGRAM_MAP(ifo_handle_t *ifofile, pgc_program_map_t *program_map, unsigned int nr, unsigned int offset) { unsigned int size = nr * sizeof(pgc_program_map_t); if(!DVDFileSeek_(ifofile->file, offset)) return 0; if(!(DVDReadBytes(ifofile->file, program_map, size))) return 0; return 1; } static int ifoRead_CELL_PLAYBACK_TBL(ifo_handle_t *ifofile, cell_playback_t *cell_playback, unsigned int nr, unsigned int offset) { unsigned int i; unsigned int size = nr * sizeof(cell_playback_t); if(!DVDFileSeek_(ifofile->file, offset)) return 0; if(!(DVDReadBytes(ifofile->file, cell_playback, size))) return 0; for(i = 0; i < nr; i++) { read_cell_playback(&cell_playback[i]); /* Changed < to <= because this was false in the movie 'Pi'. */ CHECK_VALUE(cell_playback[i].last_vobu_start_sector <= cell_playback[i].last_sector); CHECK_VALUE(cell_playback[i].first_sector <= cell_playback[i].last_vobu_start_sector); } return 1; } static int ifoRead_CELL_POSITION_TBL(ifo_handle_t *ifofile, cell_position_t *cell_position, unsigned int nr, unsigned int offset) { unsigned int i; unsigned int size = nr * sizeof(cell_position_t); if(!DVDFileSeek_(ifofile->file, offset)) return 0; if(!(DVDReadBytes(ifofile->file, cell_position, size))) return 0; for(i = 0; i < nr; i++) { B2N_16(cell_position[i].vob_id_nr); CHECK_ZERO(cell_position[i].zero_1); } return 1; } static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset) { unsigned int i; if(!DVDFileSeek_(ifofile->file, offset)) return 0; if(!(DVDReadBytes(ifofile->file, pgc, PGC_SIZE))) return 0; read_user_ops(&pgc->prohibited_ops); B2N_16(pgc->next_pgc_nr); B2N_16(pgc->prev_pgc_nr); B2N_16(pgc->goup_pgc_nr); B2N_16(pgc->command_tbl_offset); B2N_16(pgc->program_map_offset); B2N_16(pgc->cell_playback_offset); B2N_16(pgc->cell_position_offset); for(i = 0; i < 8; i++) B2N_16(pgc->audio_control[i]); for(i = 0; i < 32; i++) B2N_32(pgc->subp_control[i]); for(i = 0; i < 16; i++) B2N_32(pgc->palette[i]); CHECK_ZERO(pgc->zero_1); CHECK_VALUE(pgc->nr_of_programs <= pgc->nr_of_cells); /* verify time (look at print_time) */ for(i = 0; i < 8; i++) if(!(pgc->audio_control[i] & 0x8000)) /* The 'is present' bit */ CHECK_ZERO(pgc->audio_control[i]); for(i = 0; i < 32; i++) if(!(pgc->subp_control[i] & 0x80000000)) /* The 'is present' bit */ CHECK_ZERO(pgc->subp_control[i]); /* Check that time is 0:0:0:0 also if nr_of_programs == 0 */ if(pgc->nr_of_programs == 0) { CHECK_ZERO(pgc->still_time); CHECK_ZERO(pgc->pg_playback_mode); /* ?? */ CHECK_VALUE(pgc->program_map_offset == 0); CHECK_VALUE(pgc->cell_playback_offset == 0); CHECK_VALUE(pgc->cell_position_offset == 0); } else { CHECK_VALUE(pgc->program_map_offset != 0); CHECK_VALUE(pgc->cell_playback_offset != 0); CHECK_VALUE(pgc->cell_position_offset != 0); } if(pgc->command_tbl_offset != 0) { pgc->command_tbl = malloc(sizeof(pgc_command_tbl_t)); if(!pgc->command_tbl) return 0; if(!ifoRead_PGC_COMMAND_TBL(ifofile, pgc->command_tbl, offset + pgc->command_tbl_offset)) { return 0; } } else { pgc->command_tbl = NULL; } if(pgc->program_map_offset != 0 && pgc->nr_of_programs>0) { pgc->program_map = malloc(pgc->nr_of_programs * sizeof(pgc_program_map_t)); if(!pgc->program_map) { return 0; } if(!ifoRead_PGC_PROGRAM_MAP(ifofile, pgc->program_map,pgc->nr_of_programs, offset + pgc->program_map_offset)) { return 0; } } else { pgc->program_map = NULL; } if(pgc->cell_playback_offset != 0 && pgc->nr_of_cells>0) { pgc->cell_playback = malloc(pgc->nr_of_cells * sizeof(cell_playback_t)); if(!pgc->cell_playback) { return 0; } if(!ifoRead_CELL_PLAYBACK_TBL(ifofile, pgc->cell_playback, pgc->nr_of_cells, offset + pgc->cell_playback_offset)) { return 0; } } else { pgc->cell_playback = NULL; } if(pgc->cell_position_offset != 0 && pgc->nr_of_cells>0) { pgc->cell_position = malloc(pgc->nr_of_cells * sizeof(cell_position_t)); if(!pgc->cell_position) { return 0; } if(!ifoRead_CELL_POSITION_TBL(ifofile, pgc->cell_position, pgc->nr_of_cells, offset + pgc->cell_position_offset)) { return 0; } } else { pgc->cell_position = NULL; } return 1; } int ifoRead_FP_PGC(ifo_handle_t *ifofile) { if(!ifofile) return 0; if(!ifofile->vmgi_mat) return 0; /* It seems that first_play_pgc is optional after all. */ ifofile->first_play_pgc = 0; if(ifofile->vmgi_mat->first_play_pgc == 0) return 1; ifofile->first_play_pgc = calloc(1, sizeof(pgc_t)); if(!ifofile->first_play_pgc) return 0; ifofile->first_play_pgc->ref_count = 1; if(!ifoRead_PGC(ifofile, ifofile->first_play_pgc, ifofile->vmgi_mat->first_play_pgc)) { ifoFree_PGC(&ifofile->first_play_pgc); return 0; } return 1; } static void ifoFree_PGC(pgc_t **pgc) { if(pgc && *pgc && (--(*pgc)->ref_count) <= 0) { ifoFree_PGC_COMMAND_TBL((*pgc)->command_tbl); if((*pgc)->program_map) free((*pgc)->program_map); if((*pgc)->cell_playback) free((*pgc)->cell_playback); if((*pgc)->cell_position) free((*pgc)->cell_position); free(*pgc); } if (pgc) { *pgc = NULL; } } void ifoFree_FP_PGC(ifo_handle_t *ifofile) { if(!ifofile) return; if(ifofile->first_play_pgc) { ifoFree_PGC(&ifofile->first_play_pgc); } } int ifoRead_TT_SRPT(ifo_handle_t *ifofile) { tt_srpt_t *tt_srpt; unsigned int i; size_t info_length; if(!ifofile) return 0; if(!ifofile->vmgi_mat) return 0; if(ifofile->vmgi_mat->tt_srpt == 0) /* mandatory */ return 0; if(!DVDFileSeek_(ifofile->file, ifofile->vmgi_mat->tt_srpt * DVD_BLOCK_LEN)) return 0; tt_srpt = malloc(sizeof(tt_srpt_t)); if(!tt_srpt) return 0; ifofile->tt_srpt = tt_srpt; if(!(DVDReadBytes(ifofile->file, tt_srpt, TT_SRPT_SIZE))) { fprintf(stderr, "libdvdread: Unable to read read TT_SRPT.\n"); free(tt_srpt); return 0; } B2N_16(tt_srpt->nr_of_srpts); B2N_32(tt_srpt->last_byte); info_length = tt_srpt->last_byte + 1 - TT_SRPT_SIZE; tt_srpt->title = malloc(info_length); if(!tt_srpt->title) { free(tt_srpt); ifofile->tt_srpt = 0; return 0; } if(!(DVDReadBytes(ifofile->file, tt_srpt->title, info_length))) { fprintf(stderr, "libdvdread: Unable to read read TT_SRPT.\n"); ifoFree_TT_SRPT(ifofile); return 0; } if(tt_srpt->nr_of_srpts>info_length/sizeof(title_info_t)){ fprintf(stderr,"libdvdread: data mismatch: info_length (%zd)!= nr_of_srpts (%d). Truncating.\n", info_length/sizeof(title_info_t),tt_srpt->nr_of_srpts); tt_srpt->nr_of_srpts=info_length/sizeof(title_info_t); } for(i = 0; i < tt_srpt->nr_of_srpts; i++) { B2N_16(tt_srpt->title[i].nr_of_ptts); B2N_16(tt_srpt->title[i].parental_id); B2N_32(tt_srpt->title[i].title_set_sector); } CHECK_ZERO(tt_srpt->zero_1); CHECK_VALUE(tt_srpt->nr_of_srpts != 0); CHECK_VALUE(tt_srpt->nr_of_srpts < 100); /* ?? */ CHECK_VALUE(tt_srpt->nr_of_srpts * sizeof(title_info_t) <= info_length); for(i = 0; i < tt_srpt->nr_of_srpts; i++) { read_playback_type(&tt_srpt->title[i].pb_ty); CHECK_VALUE(tt_srpt->title[i].pb_ty.zero_1 == 0); CHECK_VALUE(tt_srpt->title[i].nr_of_angles != 0); CHECK_VALUE(tt_srpt->title[i].nr_of_angles < 10); /* CHECK_VALUE(tt_srpt->title[i].nr_of_ptts != 0); */ /* XXX: this assertion breaks Ghostbusters: */ CHECK_VALUE(tt_srpt->title[i].nr_of_ptts < 1000); /* ?? */ CHECK_VALUE(tt_srpt->title[i].title_set_nr != 0); CHECK_VALUE(tt_srpt->title[i].title_set_nr < 100); /* ?? */ CHECK_VALUE(tt_srpt->title[i].vts_ttn != 0); CHECK_VALUE(tt_srpt->title[i].vts_ttn < 100); /* ?? */ /* CHECK_VALUE(tt_srpt->title[i].title_set_sector != 0); */ } /* Make this a function */ #if 0 if(memcmp((uint8_t *)tt_srpt->title + tt_srpt->nr_of_srpts * sizeof(title_info_t), my_friendly_zeros, info_length - tt_srpt->nr_of_srpts * sizeof(title_info_t))) { fprintf(stderr, "VMG_PTT_SRPT slack is != 0, "); hexdump((uint8_t *)tt_srpt->title + tt_srpt->nr_of_srpts * sizeof(title_info_t), info_length - tt_srpt->nr_of_srpts * sizeof(title_info_t)); } #endif return 1; } void ifoFree_TT_SRPT(ifo_handle_t *ifofile) { if(!ifofile) return; if(ifofile->tt_srpt) { free(ifofile->tt_srpt->title); free(ifofile->tt_srpt); ifofile->tt_srpt = 0; } } int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) { vts_ptt_srpt_t *vts_ptt_srpt = NULL; int info_length, i, j; uint32_t *data = NULL; if(!ifofile) return 0; if(!ifofile->vtsi_mat) return 0; if(ifofile->vtsi_mat->vts_ptt_srpt == 0) /* mandatory */ return 0; if(!DVDFileSeek_(ifofile->file, ifofile->vtsi_mat->vts_ptt_srpt * DVD_BLOCK_LEN)) return 0; vts_ptt_srpt = malloc(sizeof(vts_ptt_srpt_t)); if(!vts_ptt_srpt) return 0; vts_ptt_srpt->title = NULL; ifofile->vts_ptt_srpt = vts_ptt_srpt; if(!(DVDReadBytes(ifofile->file, vts_ptt_srpt, VTS_PTT_SRPT_SIZE))) { fprintf(stderr, "libdvdread: Unable to read PTT search table.\n"); goto fail; } B2N_16(vts_ptt_srpt->nr_of_srpts); B2N_32(vts_ptt_srpt->last_byte); CHECK_ZERO(vts_ptt_srpt->zero_1); CHECK_VALUE(vts_ptt_srpt->nr_of_srpts != 0); CHECK_VALUE(vts_ptt_srpt->nr_of_srpts < 100); /* ?? */ info_length = vts_ptt_srpt->last_byte + 1 - VTS_PTT_SRPT_SIZE; data = malloc(info_length); if(!data) goto fail; if(!(DVDReadBytes(ifofile->file, data, info_length))) { fprintf(stderr, "libdvdread: Unable to read PTT search table.\n"); goto fail; } if(vts_ptt_srpt->nr_of_srpts > info_length / sizeof(*data)) { fprintf(stderr, "libdvdread: PTT search table too small.\n"); goto fail; } if(vts_ptt_srpt->nr_of_srpts == 0) { fprintf(stderr, "libdvdread: Zero entries in PTT search table.\n"); goto fail; } for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { /* Transformers 3 has PTT start bytes that point outside the SRPT PTT */ uint32_t start = data[i]; B2N_32(start); if(start + sizeof(ptt_info_t) > vts_ptt_srpt->last_byte + 1) { /* don't mess with any bytes beyond the end of the allocation */ vts_ptt_srpt->nr_of_srpts = i; break; } data[i] = start; /* assert(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1); Magic Knight Rayearth Daybreak is mastered very strange and has Titles with 0 PTTs. They all have a data[i] offsets beyond the end of of the vts_ptt_srpt structure. */ CHECK_VALUE(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1 + 4); } vts_ptt_srpt->ttu_offset = data; vts_ptt_srpt->title = malloc(vts_ptt_srpt->nr_of_srpts * sizeof(ttu_t)); if(!vts_ptt_srpt->title) goto fail; for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { int n; if(i < vts_ptt_srpt->nr_of_srpts - 1) n = (data[i+1] - data[i]); else n = (vts_ptt_srpt->last_byte + 1 - data[i]); /* assert(n > 0 && (n % 4) == 0); Magic Knight Rayearth Daybreak is mastered very strange and has Titles with 0 PTTs. */ if(n < 0) n = 0; /* DVDs created by the VDR-to-DVD device LG RC590M violate the following requirement */ CHECK_VALUE(n % 4 == 0); vts_ptt_srpt->title[i].nr_of_ptts = n / 4; vts_ptt_srpt->title[i].ptt = malloc(n * sizeof(ptt_info_t)); if(!vts_ptt_srpt->title[i].ptt) { for(n = 0; n < i; n++) free(vts_ptt_srpt->title[n].ptt); goto fail; } for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) { /* The assert placed here because of Magic Knight Rayearth Daybreak */ CHECK_VALUE(data[i] + sizeof(ptt_info_t) <= vts_ptt_srpt->last_byte + 1); vts_ptt_srpt->title[i].ptt[j].pgcn = *(uint16_t*)(((char *)data) + data[i] + 4*j - VTS_PTT_SRPT_SIZE); vts_ptt_srpt->title[i].ptt[j].pgn = *(uint16_t*)(((char *)data) + data[i] + 4*j + 2 - VTS_PTT_SRPT_SIZE); if(!vts_ptt_srpt->title[i].ptt[j].pgn) goto fail; } } for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) { B2N_16(vts_ptt_srpt->title[i].ptt[j].pgcn); B2N_16(vts_ptt_srpt->title[i].ptt[j].pgn); } } for(i = 0; i < vts_ptt_srpt->nr_of_srpts; i++) { CHECK_VALUE(vts_ptt_srpt->title[i].nr_of_ptts < 1000); /* ?? */ for(j = 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) { CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn != 0 ); CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgcn < 1000); /* ?? */ CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn != 0); CHECK_VALUE(vts_ptt_srpt->title[i].ptt[j].pgn < 100); /* ?? */ if (vts_ptt_srpt->title[i].ptt[j].pgcn == 0 || vts_ptt_srpt->title[i].ptt[j].pgcn >= 1000 || vts_ptt_srpt->title[i].ptt[j].pgn == 0 || vts_ptt_srpt->title[i].ptt[j].pgn >= 100) { return 0; } } } return 1; fail: free(data); ifofile->vts_ptt_srpt = 0; free(vts_ptt_srpt->title); free(vts_ptt_srpt); return 0; } void ifoFree_VTS_PTT_SRPT(ifo_handle_t *ifofile) { if(!ifofile) return; if(ifofile->vts_ptt_srpt) { int i; for(i = 0; i < ifofile->vts_ptt_srpt->nr_of_srpts; i++) free(ifofile->vts_ptt_srpt->title[i].ptt); free(ifofile->vts_ptt_srpt->ttu_offset); free(ifofile->vts_ptt_srpt->title); free(ifofile->vts_ptt_srpt); ifofile->vts_ptt_srpt = 0; } } int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) { ptl_mait_t *ptl_mait; int info_length; unsigned int i, j; if(!ifofile) return 0; if(!ifofile->vmgi_mat) return 0; if(!ifofile->vmgi_mat->ptl_mait) return 1; if(!DVDFileSeek_(ifofile->file, ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN)) return 0; ptl_mait = malloc(sizeof(ptl_mait_t)); if(!ptl_mait) return 0; ifofile->ptl_mait = ptl_mait; if(!(DVDReadBytes(ifofile->file, ptl_mait, PTL_MAIT_SIZE))) { free(ptl_mait); ifofile->ptl_mait = NULL; return 0; } B2N_16(ptl_mait->nr_of_countries); B2N_16(ptl_mait->nr_of_vtss); B2N_32(ptl_mait->last_byte); CHECK_VALUE(ptl_mait->nr_of_countries != 0); CHECK_VALUE(ptl_mait->nr_of_countries < 100); /* ?? */ CHECK_VALUE(ptl_mait->nr_of_vtss != 0); CHECK_VALUE(ptl_mait->nr_of_vtss < 100); /* ?? */ CHECK_VALUE(ptl_mait->nr_of_countries * PTL_MAIT_COUNTRY_SIZE <= ptl_mait->last_byte + 1 - PTL_MAIT_SIZE); info_length = ptl_mait->nr_of_countries * sizeof(ptl_mait_country_t); ptl_mait->countries = malloc(info_length); if(!ptl_mait->countries) { free(ptl_mait); ifofile->ptl_mait = NULL; return 0; } for(i = 0; i < ptl_mait->nr_of_countries; i++) { ptl_mait->countries[i].pf_ptl_mai = NULL; } for(i = 0; i < ptl_mait->nr_of_countries; i++) { if(!(DVDReadBytes(ifofile->file, &ptl_mait->countries[i], PTL_MAIT_COUNTRY_SIZE))) { fprintf(stderr, "libdvdread: Unable to read PTL_MAIT.\n"); free(ptl_mait->countries); free(ptl_mait); ifofile->ptl_mait = NULL; return 0; } } for(i = 0; i < ptl_mait->nr_of_countries; i++) { B2N_16(ptl_mait->countries[i].country_code); B2N_16(ptl_mait->countries[i].pf_ptl_mai_start_byte); } for(i = 0; i < ptl_mait->nr_of_countries; i++) { CHECK_ZERO(ptl_mait->countries[i].zero_1); CHECK_ZERO(ptl_mait->countries[i].zero_2); CHECK_VALUE(ptl_mait->countries[i].pf_ptl_mai_start_byte + sizeof(pf_level_t) * (ptl_mait->nr_of_vtss + 1) <= ptl_mait->last_byte + 1); } for(i = 0; i < ptl_mait->nr_of_countries; i++) { uint16_t *pf_temp; if(!DVDFileSeek_(ifofile->file, ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN + ptl_mait->countries[i].pf_ptl_mai_start_byte)) { fprintf(stderr, "libdvdread: Unable to seek PTL_MAIT table at index %d.\n",i); free(ptl_mait->countries); free(ptl_mait); ifofile->ptl_mait = NULL; return 0; } info_length = (ptl_mait->nr_of_vtss + 1) * sizeof(pf_level_t); pf_temp = malloc(info_length); if(!pf_temp) { free_ptl_mait(ptl_mait, i); ifofile->ptl_mait = NULL; return 0; } memset(pf_temp, 0, info_length); if(!(DVDReadBytes(ifofile->file, pf_temp, info_length))) { fprintf(stderr, "libdvdread: Unable to read PTL_MAIT table at index %d.\n",i); free(pf_temp); free_ptl_mait(ptl_mait, i); ifofile->ptl_mait = NULL; return 0; } for (j = 0; j < ((ptl_mait->nr_of_vtss + 1U) * 8U); j++) { B2N_16(pf_temp[j]); } ptl_mait->countries[i].pf_ptl_mai = malloc(info_length); if(!ptl_mait->countries[i].pf_ptl_mai) { free(pf_temp); free_ptl_mait(ptl_mait, i); ifofile->ptl_mait = NULL; return 0; } { /* Transpose the array so we can use C indexing. */ int level, vts; for(level = 0; level < PTL_MAIT_NUM_LEVEL; level++) { for(vts = 0; vts <= ptl_mait->nr_of_vtss; vts++) { ptl_mait->countries[i].pf_ptl_mai[vts][level] = pf_temp[(7-level)*(ptl_mait->nr_of_vtss+1) + vts]; } } free(pf_temp); } } return 1; } void ifoFree_PTL_MAIT(ifo_handle_t *ifofile) { unsigned int i; if(!ifofile) return; if(ifofile->ptl_mait) { for(i = 0; i < ifofile->ptl_mait->nr_of_countries; i++) { free(ifofile->ptl_mait->countries[i].pf_ptl_mai); } free(ifofile->ptl_mait->countries); free(ifofile->ptl_mait); ifofile->ptl_mait = NULL; } } int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) { vts_tmapt_t *vts_tmapt; uint32_t *vts_tmap_srp; unsigned int offset; int info_length; unsigned int i, j; if(!ifofile) return 0; if(!ifofile->vtsi_mat) return 0; if(ifofile->vtsi_mat->vts_tmapt == 0) { ifofile->vts_tmapt = NULL; return 1; } offset = ifofile->vtsi_mat->vts_tmapt * DVD_BLOCK_LEN; if(!DVDFileSeek_(ifofile->file, offset)) return 0; vts_tmapt = malloc(sizeof(vts_tmapt_t)); if(!vts_tmapt) return 0; ifofile->vts_tmapt = vts_tmapt; if(!(DVDReadBytes(ifofile->file, vts_tmapt, VTS_TMAPT_SIZE))) { fprintf(stderr, "libdvdread: Unable to read VTS_TMAPT.\n"); free(vts_tmapt); ifofile->vts_tmapt = NULL; return 0; } B2N_16(vts_tmapt->nr_of_tmaps); B2N_32(vts_tmapt->last_byte); CHECK_ZERO(vts_tmapt->zero_1); info_length = vts_tmapt->nr_of_tmaps * 4; vts_tmap_srp = malloc(info_length); if(!vts_tmap_srp) { free(vts_tmapt); ifofile->vts_tmapt = NULL; return 0; } vts_tmapt->tmap_offset = vts_tmap_srp; if(!(DVDReadBytes(ifofile->file, vts_tmap_srp, info_length))) { fprintf(stderr, "libdvdread: Unable to read VTS_TMAPT.\n"); free(vts_tmap_srp); free(vts_tmapt); ifofile->vts_tmapt = NULL; return 0; } for (i = 0; i < vts_tmapt->nr_of_tmaps; i++) { B2N_32(vts_tmap_srp[i]); } info_length = vts_tmapt->nr_of_tmaps * sizeof(vts_tmap_t); vts_tmapt->tmap = malloc(info_length); if(!vts_tmapt->tmap) { free(vts_tmap_srp); free(vts_tmapt); ifofile->vts_tmapt = NULL; return 0; } memset(vts_tmapt->tmap, 0, info_length); /* So ifoFree_VTS_TMAPT works. */ for(i = 0; i < vts_tmapt->nr_of_tmaps; i++) { if(!DVDFileSeek_(ifofile->file, offset + vts_tmap_srp[i])) { ifoFree_VTS_TMAPT(ifofile); return 0; } if(!(DVDReadBytes(ifofile->file, &vts_tmapt->tmap[i], VTS_TMAP_SIZE))) { fprintf(stderr, "libdvdread: Unable to read VTS_TMAP.\n"); ifoFree_VTS_TMAPT(ifofile); return 0; } B2N_16(vts_tmapt->tmap[i].nr_of_entries); CHECK_ZERO(vts_tmapt->tmap[i].zero_1); if(vts_tmapt->tmap[i].nr_of_entries == 0) { /* Early out if zero entries */ vts_tmapt->tmap[i].map_ent = NULL; continue; } info_length = vts_tmapt->tmap[i].nr_of_entries * sizeof(map_ent_t); vts_tmapt->tmap[i].map_ent = malloc(info_length); if(!vts_tmapt->tmap[i].map_ent) { ifoFree_VTS_TMAPT(ifofile); return 0; } if(!(DVDReadBytes(ifofile->file, vts_tmapt->tmap[i].map_ent, info_length))) { fprintf(stderr, "libdvdread: Unable to read VTS_TMAP_ENT.\n"); ifoFree_VTS_TMAPT(ifofile); return 0; } for(j = 0; j < vts_tmapt->tmap[i].nr_of_entries; j++) B2N_32(vts_tmapt->tmap[i].map_ent[j]); } return 1; } void ifoFree_VTS_TMAPT(ifo_handle_t *ifofile) { unsigned int i; if(!ifofile) return; if(ifofile->vts_tmapt) { for(i = 0; i < ifofile->vts_tmapt->nr_of_tmaps; i++) if(ifofile->vts_tmapt->tmap[i].map_ent) free(ifofile->vts_tmapt->tmap[i].map_ent); free(ifofile->vts_tmapt->tmap); free(ifofile->vts_tmapt->tmap_offset); free(ifofile->vts_tmapt); ifofile->vts_tmapt = NULL; } } int ifoRead_TITLE_C_ADT(ifo_handle_t *ifofile) { if(!ifofile) return 0; if(!ifofile->vtsi_mat) return 0; if(ifofile->vtsi_mat->vts_c_adt == 0) /* mandatory */ return 0; ifofile->vts_c_adt = malloc(sizeof(c_adt_t)); if(!ifofile->vts_c_adt) return 0; if(!ifoRead_C_ADT_internal(ifofile, ifofile->vts_c_adt, ifofile->vtsi_mat->vts_c_adt)) { free(ifofile->vts_c_adt); ifofile->vts_c_adt = 0; return 0; } return 1; } int ifoRead_C_ADT(ifo_handle_t *ifofile) { unsigned int sector; if(!ifofile) return 0; if(ifofile->vmgi_mat) { if(ifofile->vmgi_mat->vmgm_c_adt == 0) return 1; sector = ifofile->vmgi_mat->vmgm_c_adt; } else if(ifofile->vtsi_mat) { if(ifofile->vtsi_mat->vtsm_c_adt == 0) return 1; sector = ifofile->vtsi_mat->vtsm_c_adt; } else { return 0; } ifofile->menu_c_adt = malloc(sizeof(c_adt_t)); if(!ifofile->menu_c_adt) return 0; if(!ifoRead_C_ADT_internal(ifofile, ifofile->menu_c_adt, sector)) { free(ifofile->menu_c_adt); ifofile->menu_c_adt = 0; return 0; } return 1; } static int ifoRead_C_ADT_internal(ifo_handle_t *ifofile, c_adt_t *c_adt, unsigned int sector) { size_t i, info_length; if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN)) return 0; if(!(DVDReadBytes(ifofile->file, c_adt, C_ADT_SIZE))) return 0; B2N_16(c_adt->nr_of_vobs); B2N_32(c_adt->last_byte); if(c_adt->last_byte + 1 < C_ADT_SIZE) return 0; info_length = c_adt->last_byte + 1 - C_ADT_SIZE; CHECK_ZERO(c_adt->zero_1); /* assert(c_adt->nr_of_vobs > 0); Magic Knight Rayearth Daybreak is mastered very strange and has Titles with a VOBS that has no cells. */ CHECK_VALUE(info_length % sizeof(cell_adr_t) == 0); /* assert(info_length / sizeof(cell_adr_t) >= c_adt->nr_of_vobs); Enemy of the State region 2 (de) has Titles where nr_of_vobs field is to high, they high ones are never referenced though. */ if(info_length / sizeof(cell_adr_t) < c_adt->nr_of_vobs) { fprintf(stderr, "libdvdread: *C_ADT nr_of_vobs > available info entries\n"); c_adt->nr_of_vobs = info_length / sizeof(cell_adr_t); } c_adt->cell_adr_table = malloc(info_length); if(!c_adt->cell_adr_table) return 0; if(info_length && !(DVDReadBytes(ifofile->file, c_adt->cell_adr_table, info_length))) { free(c_adt->cell_adr_table); return 0; } for(i = 0; i < info_length/sizeof(cell_adr_t); i++) { B2N_16(c_adt->cell_adr_table[i].vob_id); B2N_32(c_adt->cell_adr_table[i].start_sector); B2N_32(c_adt->cell_adr_table[i].last_sector); CHECK_ZERO(c_adt->cell_adr_table[i].zero_1); CHECK_VALUE(c_adt->cell_adr_table[i].vob_id > 0); CHECK_VALUE(c_adt->cell_adr_table[i].vob_id <= c_adt->nr_of_vobs); CHECK_VALUE(c_adt->cell_adr_table[i].cell_id > 0); CHECK_VALUE(c_adt->cell_adr_table[i].start_sector < c_adt->cell_adr_table[i].last_sector); } return 1; } static void ifoFree_C_ADT_internal(c_adt_t *c_adt) { if(c_adt) { free(c_adt->cell_adr_table); free(c_adt); } } void ifoFree_C_ADT(ifo_handle_t *ifofile) { if(!ifofile) return; ifoFree_C_ADT_internal(ifofile->menu_c_adt); ifofile->menu_c_adt = 0; } void ifoFree_TITLE_C_ADT(ifo_handle_t *ifofile) { if(!ifofile) return; ifoFree_C_ADT_internal(ifofile->vts_c_adt); ifofile->vts_c_adt = 0; } int ifoRead_TITLE_VOBU_ADMAP(ifo_handle_t *ifofile) { if(!ifofile) return 0; if(!ifofile->vtsi_mat) return 0; if(ifofile->vtsi_mat->vts_vobu_admap == 0) /* mandatory */ return 0; ifofile->vts_vobu_admap = malloc(sizeof(vobu_admap_t)); if(!ifofile->vts_vobu_admap) return 0; if(!ifoRead_VOBU_ADMAP_internal(ifofile, ifofile->vts_vobu_admap, ifofile->vtsi_mat->vts_vobu_admap)) { free(ifofile->vts_vobu_admap); ifofile->vts_vobu_admap = 0; return 0; } return 1; } int ifoRead_VOBU_ADMAP(ifo_handle_t *ifofile) { unsigned int sector; if(!ifofile) return 0; if(ifofile->vmgi_mat) { if(ifofile->vmgi_mat->vmgm_vobu_admap == 0) return 1; sector = ifofile->vmgi_mat->vmgm_vobu_admap; } else if(ifofile->vtsi_mat) { if(ifofile->vtsi_mat->vtsm_vobu_admap == 0) return 1; sector = ifofile->vtsi_mat->vtsm_vobu_admap; } else { return 0; } ifofile->menu_vobu_admap = malloc(sizeof(vobu_admap_t)); if(!ifofile->menu_vobu_admap) return 0; if(!ifoRead_VOBU_ADMAP_internal(ifofile, ifofile->menu_vobu_admap, sector)) { free(ifofile->menu_vobu_admap); ifofile->menu_vobu_admap = 0; return 0; } return 1; } static int ifoRead_VOBU_ADMAP_internal(ifo_handle_t *ifofile, vobu_admap_t *vobu_admap, unsigned int sector) { unsigned int i; int info_length; if(!DVDFileSeekForce_(ifofile->file, sector * DVD_BLOCK_LEN, sector)) return 0; if(!(DVDReadBytes(ifofile->file, vobu_admap, VOBU_ADMAP_SIZE))) return 0; B2N_32(vobu_admap->last_byte); info_length = vobu_admap->last_byte + 1 - VOBU_ADMAP_SIZE; /* assert(info_length > 0); Magic Knight Rayearth Daybreak is mastered very strange and has Titles with a VOBS that has no VOBUs. */ CHECK_VALUE(info_length % sizeof(uint32_t) == 0); vobu_admap->vobu_start_sectors = malloc(info_length); if(!vobu_admap->vobu_start_sectors) { return 0; } if(info_length && !(DVDReadBytes(ifofile->file, vobu_admap->vobu_start_sectors, info_length))) { free(vobu_admap->vobu_start_sectors); return 0; } for(i = 0; i < info_length/sizeof(uint32_t); i++) B2N_32(vobu_admap->vobu_start_sectors[i]); return 1; } static void ifoFree_VOBU_ADMAP_internal(vobu_admap_t *vobu_admap) { if(vobu_admap) { free(vobu_admap->vobu_start_sectors); free(vobu_admap); } } void ifoFree_VOBU_ADMAP(ifo_handle_t *ifofile) { if(!ifofile) return; ifoFree_VOBU_ADMAP_internal(ifofile->menu_vobu_admap); ifofile->menu_vobu_admap = 0; } void ifoFree_TITLE_VOBU_ADMAP(ifo_handle_t *ifofile) { if(!ifofile) return; ifoFree_VOBU_ADMAP_internal(ifofile->vts_vobu_admap); ifofile->vts_vobu_admap = 0; } int ifoRead_PGCIT(ifo_handle_t *ifofile) { if(!ifofile) return 0; if(!ifofile->vtsi_mat) return 0; if(ifofile->vtsi_mat->vts_pgcit == 0) /* mandatory */ return 0; ifofile->vts_pgcit = calloc(1, sizeof(pgcit_t)); if(!ifofile->vts_pgcit) return 0; ifofile->vts_pgcit->ref_count = 1; if(!ifoRead_PGCIT_internal(ifofile, ifofile->vts_pgcit, ifofile->vtsi_mat->vts_pgcit * DVD_BLOCK_LEN)) { free(ifofile->vts_pgcit); ifofile->vts_pgcit = 0; return 0; } return 1; } static int find_dup_pgc(pgci_srp_t *pgci_srp, uint32_t start_byte, int count) { int i; for(i = 0; i < count; i++) { if(pgci_srp[i].pgc_start_byte == start_byte) { return i; } } return -1; } static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit, unsigned int offset) { int i, info_length; uint8_t *data, *ptr; if(!DVDFileSeek_(ifofile->file, offset)) return 0; if(!(DVDReadBytes(ifofile->file, pgcit, PGCIT_SIZE))) return 0; B2N_16(pgcit->nr_of_pgci_srp); B2N_32(pgcit->last_byte); CHECK_ZERO(pgcit->zero_1); /* assert(pgcit->nr_of_pgci_srp != 0); Magic Knight Rayearth Daybreak is mastered very strange and has Titles with 0 PTTs. */ CHECK_VALUE(pgcit->nr_of_pgci_srp < 10000); /* ?? seen max of 1338 */ info_length = pgcit->nr_of_pgci_srp * PGCI_SRP_SIZE; data = malloc(info_length); if(!data) return 0; if(info_length && !(DVDReadBytes(ifofile->file, data, info_length))) { free(data); return 0; } pgcit->pgci_srp = malloc(pgcit->nr_of_pgci_srp * sizeof(pgci_srp_t)); if(!pgcit->pgci_srp) { free(data); return 0; } ptr = data; for(i = 0; i < pgcit->nr_of_pgci_srp; i++) { memcpy(&pgcit->pgci_srp[i], ptr, PGCI_SRP_SIZE); ptr += PGCI_SRP_SIZE; read_pgci_srp(&pgcit->pgci_srp[i]); CHECK_VALUE(pgcit->pgci_srp[i].unknown1 == 0); } free(data); for(i = 0; i < pgcit->nr_of_pgci_srp; i++) CHECK_VALUE(pgcit->pgci_srp[i].pgc_start_byte + PGC_SIZE <= pgcit->last_byte+1); for(i = 0; i < pgcit->nr_of_pgci_srp; i++) { int dup; if((dup = find_dup_pgc(pgcit->pgci_srp, pgcit->pgci_srp[i].pgc_start_byte, i)) >= 0) { pgcit->pgci_srp[i].pgc = pgcit->pgci_srp[dup].pgc; pgcit->pgci_srp[i].pgc->ref_count++; continue; } pgcit->pgci_srp[i].pgc = calloc(1, sizeof(pgc_t)); if(!pgcit->pgci_srp[i].pgc) { int j; for(j = 0; j < i; j++) { ifoFree_PGC(&pgcit->pgci_srp[j].pgc); } goto fail; } pgcit->pgci_srp[i].pgc->ref_count = 1; if(!ifoRead_PGC(ifofile, pgcit->pgci_srp[i].pgc, offset + pgcit->pgci_srp[i].pgc_start_byte)) { int j; for(j = 0; j <= i; j++) { ifoFree_PGC(&pgcit->pgci_srp[j].pgc); } free(pgcit->pgci_srp[i].pgc); goto fail; } } return 1; fail: free(pgcit->pgci_srp); pgcit->pgci_srp = NULL; return 0; } static void ifoFree_PGCIT_internal(pgcit_t **pgcit) { if(pgcit && *pgcit && (--(*pgcit)->ref_count <= 0)) { int i; for(i = 0; i < (*pgcit)->nr_of_pgci_srp; i++) { ifoFree_PGC(&(*pgcit)->pgci_srp[i].pgc); } free((*pgcit)->pgci_srp); free(*pgcit); } if (pgcit) *pgcit = NULL; } void ifoFree_PGCIT(ifo_handle_t *ifofile) { if(!ifofile) return; if(ifofile->vts_pgcit) { ifoFree_PGCIT_internal(&ifofile->vts_pgcit); } } static int find_dup_lut(pgci_lu_t *lu, uint32_t start_byte, int count) { int i; for(i = 0; i < count; i++) { if(lu[i].lang_start_byte == start_byte) { return i; } } return -1; } int ifoRead_PGCI_UT(ifo_handle_t *ifofile) { pgci_ut_t *pgci_ut; unsigned int sector; unsigned int i; int info_length; uint8_t *data, *ptr; if(!ifofile) return 0; if(ifofile->vmgi_mat) { if(ifofile->vmgi_mat->vmgm_pgci_ut == 0) return 1; sector = ifofile->vmgi_mat->vmgm_pgci_ut; } else if(ifofile->vtsi_mat) { if(ifofile->vtsi_mat->vtsm_pgci_ut == 0) return 1; sector = ifofile->vtsi_mat->vtsm_pgci_ut; } else { return 0; } ifofile->pgci_ut = malloc(sizeof(pgci_ut_t)); if(!ifofile->pgci_ut) return 0; if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN)) { free(ifofile->pgci_ut); ifofile->pgci_ut = 0; return 0; } if(!(DVDReadBytes(ifofile->file, ifofile->pgci_ut, PGCI_UT_SIZE))) { free(ifofile->pgci_ut); ifofile->pgci_ut = 0; return 0; } pgci_ut = ifofile->pgci_ut; B2N_16(pgci_ut->nr_of_lus); B2N_32(pgci_ut->last_byte); CHECK_ZERO(pgci_ut->zero_1); CHECK_VALUE(pgci_ut->nr_of_lus != 0); CHECK_VALUE(pgci_ut->nr_of_lus < 100); /* ?? 3-4 ? */ CHECK_VALUE((uint32_t)pgci_ut->nr_of_lus * PGCI_LU_SIZE < pgci_ut->last_byte); info_length = pgci_ut->nr_of_lus * PGCI_LU_SIZE; data = malloc(info_length); if(!data) { free(pgci_ut); ifofile->pgci_ut = 0; return 0; } if(!(DVDReadBytes(ifofile->file, data, info_length))) { free(data); free(pgci_ut); ifofile->pgci_ut = 0; return 0; } pgci_ut->lu = malloc(pgci_ut->nr_of_lus * sizeof(pgci_lu_t)); if(!pgci_ut->lu) { free(data); free(pgci_ut); ifofile->pgci_ut = 0; return 0; } ptr = data; for(i = 0; i < pgci_ut->nr_of_lus; i++) { memcpy(&pgci_ut->lu[i], ptr, PGCI_LU_SIZE); ptr += PGCI_LU_SIZE; B2N_16(pgci_ut->lu[i].lang_code); B2N_32(pgci_ut->lu[i].lang_start_byte); } free(data); for(i = 0; i < pgci_ut->nr_of_lus; i++) { /* Maybe this is only defined for v1.1 and later titles? */ /* If the bits in 'lu[i].exists' are enumerated abcd efgh then: VTS_x_yy.IFO VIDEO_TS.IFO a == 0x83 "Root" 0x82 "Title" b == 0x84 "Subpicture" c == 0x85 "Audio" d == 0x86 "Angle" e == 0x87 "PTT" */ CHECK_VALUE((pgci_ut->lu[i].exists & 0x07) == 0); } for(i = 0; i < pgci_ut->nr_of_lus; i++) { int dup; if((dup = find_dup_lut(pgci_ut->lu, pgci_ut->lu[i].lang_start_byte, i)) >= 0) { pgci_ut->lu[i].pgcit = pgci_ut->lu[dup].pgcit; pgci_ut->lu[i].pgcit->ref_count++; continue; } pgci_ut->lu[i].pgcit = malloc(sizeof(pgcit_t)); if(!pgci_ut->lu[i].pgcit) { unsigned int j; for(j = 0; j < i; j++) { ifoFree_PGCIT_internal(&pgci_ut->lu[j].pgcit); } free(pgci_ut->lu); free(pgci_ut); ifofile->pgci_ut = 0; return 0; } pgci_ut->lu[i].pgcit->ref_count = 1; if(!ifoRead_PGCIT_internal(ifofile, pgci_ut->lu[i].pgcit, sector * DVD_BLOCK_LEN + pgci_ut->lu[i].lang_start_byte)) { unsigned int j; for(j = 0; j <= i; j++) { ifoFree_PGCIT_internal(&pgci_ut->lu[j].pgcit); } free(pgci_ut->lu); free(pgci_ut); ifofile->pgci_ut = 0; return 0; } /* FIXME: Iterate and verify that all menus that should exists accordingly * to pgci_ut->lu[i].exists really do? */ } return 1; } void ifoFree_PGCI_UT(ifo_handle_t *ifofile) { unsigned int i; if(!ifofile) return; if(ifofile->pgci_ut) { for(i = 0; i < ifofile->pgci_ut->nr_of_lus; i++) { ifoFree_PGCIT_internal(&ifofile->pgci_ut->lu[i].pgcit); } free(ifofile->pgci_ut->lu); free(ifofile->pgci_ut); ifofile->pgci_ut = 0; } } static int ifoRead_VTS_ATTRIBUTES(ifo_handle_t *ifofile, vts_attributes_t *vts_attributes, unsigned int offset) { unsigned int i; if(!DVDFileSeek_(ifofile->file, offset)) return 0; if(!(DVDReadBytes(ifofile->file, vts_attributes, sizeof(vts_attributes_t)))) return 0; read_video_attr(&vts_attributes->vtsm_vobs_attr); read_video_attr(&vts_attributes->vtstt_vobs_video_attr); read_audio_attr(&vts_attributes->vtsm_audio_attr); for(i=0; i<8; i++) read_audio_attr(&vts_attributes->vtstt_audio_attr[i]); read_subp_attr(&vts_attributes->vtsm_subp_attr); for(i=0; i<32; i++) read_subp_attr(&vts_attributes->vtstt_subp_attr[i]); B2N_32(vts_attributes->last_byte); B2N_32(vts_attributes->vts_cat); CHECK_ZERO(vts_attributes->zero_1); CHECK_ZERO(vts_attributes->zero_2); CHECK_ZERO(vts_attributes->zero_3); CHECK_ZERO(vts_attributes->zero_4); CHECK_ZERO(vts_attributes->zero_5); CHECK_ZERO(vts_attributes->zero_6); CHECK_ZERO(vts_attributes->zero_7); CHECK_VALUE(vts_attributes->nr_of_vtsm_audio_streams <= 1); CHECK_VALUE(vts_attributes->nr_of_vtsm_subp_streams <= 1); CHECK_VALUE(vts_attributes->nr_of_vtstt_audio_streams <= 8); for(i = vts_attributes->nr_of_vtstt_audio_streams; i < 8; i++) CHECK_ZERO(vts_attributes->vtstt_audio_attr[i]); CHECK_VALUE(vts_attributes->nr_of_vtstt_subp_streams <= 32); { unsigned int nr_coded; CHECK_VALUE(vts_attributes->last_byte + 1 >= VTS_ATTRIBUTES_MIN_SIZE); nr_coded = (vts_attributes->last_byte + 1 - VTS_ATTRIBUTES_MIN_SIZE)/6; /* This is often nr_coded = 70, how do you know how many there really are? */ if(nr_coded > 32) { /* We haven't read more from disk/file anyway */ nr_coded = 32; } CHECK_VALUE(vts_attributes->nr_of_vtstt_subp_streams <= nr_coded); for(i = vts_attributes->nr_of_vtstt_subp_streams; i < nr_coded; i++) CHECK_ZERO(vts_attributes->vtstt_subp_attr[i]); } return 1; } int ifoRead_VTS_ATRT(ifo_handle_t *ifofile) { vts_atrt_t *vts_atrt; unsigned int i, info_length, sector; uint32_t *data; if(!ifofile) return 0; if(!ifofile->vmgi_mat) return 0; if(ifofile->vmgi_mat->vts_atrt == 0) /* mandatory */ return 0; sector = ifofile->vmgi_mat->vts_atrt; if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN)) return 0; vts_atrt = malloc(sizeof(vts_atrt_t)); if(!vts_atrt) return 0; ifofile->vts_atrt = vts_atrt; if(!(DVDReadBytes(ifofile->file, vts_atrt, VTS_ATRT_SIZE))) { free(vts_atrt); ifofile->vts_atrt = 0; return 0; } B2N_16(vts_atrt->nr_of_vtss); B2N_32(vts_atrt->last_byte); CHECK_ZERO(vts_atrt->zero_1); CHECK_VALUE(vts_atrt->nr_of_vtss != 0); CHECK_VALUE(vts_atrt->nr_of_vtss < 100); /* ?? */ CHECK_VALUE((uint32_t)vts_atrt->nr_of_vtss * (4 + VTS_ATTRIBUTES_MIN_SIZE) + VTS_ATRT_SIZE < vts_atrt->last_byte + 1); info_length = vts_atrt->nr_of_vtss * sizeof(uint32_t); data = malloc(info_length); if(!data) { free(vts_atrt); ifofile->vts_atrt = 0; return 0; } vts_atrt->vts_atrt_offsets = data; if(!(DVDReadBytes(ifofile->file, data, info_length))) { free(data); free(vts_atrt); ifofile->vts_atrt = 0; return 0; } for(i = 0; i < vts_atrt->nr_of_vtss; i++) { B2N_32(data[i]); CHECK_VALUE(data[i] + VTS_ATTRIBUTES_MIN_SIZE < vts_atrt->last_byte + 1); } info_length = vts_atrt->nr_of_vtss * sizeof(vts_attributes_t); vts_atrt->vts = malloc(info_length); if(!vts_atrt->vts) { free(data); free(vts_atrt); ifofile->vts_atrt = 0; return 0; } for(i = 0; i < vts_atrt->nr_of_vtss; i++) { unsigned int offset = data[i]; if(!ifoRead_VTS_ATTRIBUTES(ifofile, &(vts_atrt->vts[i]), (sector * DVD_BLOCK_LEN) + offset)) { free(data); free(vts_atrt); ifofile->vts_atrt = 0; return 0; } /* This assert cant be in ifoRead_VTS_ATTRIBUTES */ CHECK_VALUE(offset + vts_atrt->vts[i].last_byte <= vts_atrt->last_byte + 1); /* Is this check correct? */ } return 1; } void ifoFree_VTS_ATRT(ifo_handle_t *ifofile) { if(!ifofile) return; if(ifofile->vts_atrt) { free(ifofile->vts_atrt->vts); free(ifofile->vts_atrt->vts_atrt_offsets); free(ifofile->vts_atrt); ifofile->vts_atrt = 0; } } int ifoRead_TXTDT_MGI(ifo_handle_t *ifofile) { txtdt_mgi_t *txtdt_mgi; if(!ifofile) return 0; if(!ifofile->vmgi_mat) return 0; /* Return successfully if there is nothing to read. */ if(ifofile->vmgi_mat->txtdt_mgi == 0) return 1; if(!DVDFileSeek_(ifofile->file, ifofile->vmgi_mat->txtdt_mgi * DVD_BLOCK_LEN)) return 0; txtdt_mgi = malloc(sizeof(txtdt_mgi_t)); if(!txtdt_mgi) { return 0; } ifofile->txtdt_mgi = txtdt_mgi; if(!(DVDReadBytes(ifofile->file, txtdt_mgi, TXTDT_MGI_SIZE))) { fprintf(stderr, "libdvdread: Unable to read TXTDT_MGI.\n"); free(txtdt_mgi); ifofile->txtdt_mgi = 0; return 0; } /* fprintf(stderr, "-- Not done yet --\n"); */ return 1; } void ifoFree_TXTDT_MGI(ifo_handle_t *ifofile) { if(!ifofile) return; if(ifofile->txtdt_mgi) { free(ifofile->txtdt_mgi); ifofile->txtdt_mgi = 0; } } k9copy/src/libdvdread-NOW/dvd_input.h0000644000175000017550000000403512412304751020241 0ustar emulatoremulator/* * Copyright (C) 2001, 2002 Samuel Hocevar , * Håkan Hjort * * This file is part of libdvdread. * * libdvdread is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdread is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdread; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef LIBDVDREAD_DVD_INPUT_H #define LIBDVDREAD_DVD_INPUT_H /** * Defines and flags. Make sure they fit the libdvdcss API! */ #define DVDINPUT_NOFLAGS 0 #define DVDINPUT_READ_DECRYPT (1 << 0) typedef struct dvd_input_s *dvd_input_t; #if defined( __MINGW32__ ) # undef lseek # define lseek _lseeki64 # undef off_t # define off_t off64_t # undef stat # define stat _stati64 # define fstat _fstati64 # define wstat _wstati64 #endif #ifdef __ANDROID__ # undef lseek # define lseek lseek64 # undef off_t # define off_t off64_t #endif /** * Function pointers that will be filled in by the input implementation. * These functions provide the main API. */ extern dvd_input_t (*dvdinput_open) (const char *); extern int (*dvdinput_close) (dvd_input_t); extern int (*dvdinput_seek) (dvd_input_t, int); extern int (*dvdinput_title) (dvd_input_t, int); extern int (*dvdinput_read) (dvd_input_t, void *, int, int); extern char * (*dvdinput_error) (dvd_input_t); /** * Setup function accessed by dvd_reader.c. Returns 1 if there is CSS support. */ int dvdinput_setup(void); #endif /* LIBDVDREAD_DVD_INPUT_H */ k9copy/src/libdvdread-NOW/dvd_reader.c0000644000175000017550000012221612412304751020341 0ustar emulatoremulator/* * Copyright (C) 2001-2004 Billy Biggs , * Håkan Hjort , * Björn Englund * * This file is part of libdvdread. * * libdvdread is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdread is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdread; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include /* off_t */ #include /* stat */ #include /* For the timing of dvdcss_title crack. */ #include /* open */ #include /* free */ #include /* fprintf */ #include /* errno, EIN* */ #include /* memcpy, strlen */ #include /* chdir, getcwd */ #include /* PATH_MAX */ #include /* opendir, readdir */ #include /* isalpha */ /* misc win32 helpers */ #ifdef WIN32 # ifndef HAVE_GETTIMEOFDAY /* replacement gettimeofday implementation */ # include static inline int _private_gettimeofday( struct timeval *tv, void *tz ) { struct timeb t; ftime( &t ); tv->tv_sec = t.time; tv->tv_usec = t.millitm * 1000; return 0; } # define gettimeofday(TV, TZ) _private_gettimeofday((TV), (TZ)) # endif # include /* read() */ # define lseek64 _lseeki64 #endif #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__bsdi__) || defined(__APPLE__) # define SYS_BSD 1 #endif #if defined(__sun) # include #elif defined(__APPLE__) # include # include # include #elif defined(SYS_BSD) # include #elif defined(__linux__) # include # include #endif #include "dvdread/dvd_udf.h" #include "dvdread/dvd_reader.h" #include "dvd_input.h" #include "dvdread_internal.h" #include "md5.h" #include "dvdread/ifo_read.h" #define DEFAULT_UDF_CACHE_LEVEL 1 struct dvd_reader_s { /* Basic information. */ int isImageFile; /* Hack for keeping track of the css status. * 0: no css, 1: perhaps (need init of keys), 2: have done init */ int css_state; int css_title; /* Last title that we have called dvdinpute_title for. */ /* Information required for an image file. */ dvd_input_t dev; /* Information required for a directory path drive. */ char *path_root; /* Filesystem cache */ int udfcache_level; /* 0 - turned off, 1 - on */ void *udfcache; }; #define TITLES_MAX 9 struct dvd_file_s { /* Basic information. */ dvd_reader_t *dvd; /* Hack for selecting the right css title. */ int css_title; /* Information required for an image file. */ uint32_t lb_start; uint32_t seek_pos; /* Information required for a directory path drive. */ size_t title_sizes[ TITLES_MAX ]; dvd_input_t title_devs[ TITLES_MAX ]; /* Calculated at open-time, size in blocks. */ ssize_t filesize; }; int InternalUDFReadBlocksRaw( const dvd_reader_t *device, uint32_t lb_number, size_t block_count, unsigned char *data, int encrypted ); /** * Set the level of caching on udf * level = 0 (no caching) * level = 1 (caching filesystem info) */ int DVDUDFCacheLevel(dvd_reader_t *device, int level) { struct dvd_reader_s *dev = (struct dvd_reader_s *)device; if(level > 0) { level = 1; } else if(level < 0) { return dev->udfcache_level; } dev->udfcache_level = level; return level; } void *GetUDFCacheHandle(dvd_reader_t *device) { struct dvd_reader_s *dev = (struct dvd_reader_s *)device; return dev->udfcache; } void SetUDFCacheHandle(dvd_reader_t *device, void *cache) { struct dvd_reader_s *dev = (struct dvd_reader_s *)device; dev->udfcache = cache; } /* Loop over all titles and call dvdcss_title to crack the keys. */ static int initAllCSSKeys( dvd_reader_t *dvd ) { struct timeval all_s, all_e; struct timeval t_s, t_e; char filename[ MAX_UDF_FILE_NAME_LEN ]; uint32_t start, len; int title; char *nokeys_str = getenv("DVDREAD_NOKEYS"); if(nokeys_str != NULL) return 0; fprintf( stderr, "\n" ); fprintf( stderr, "libdvdread: Attempting to retrieve all CSS keys\n" ); fprintf( stderr, "libdvdread: This can take a _long_ time, " "please be patient\n\n" ); gettimeofday(&all_s, NULL); for( title = 0; title < 100; title++ ) { gettimeofday( &t_s, NULL ); if( title == 0 ) { sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" ); } else { sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 0 ); } start = UDFFindFile( dvd, filename, &len ); if( start != 0 && len != 0 ) { /* Perform CSS key cracking for this title. */ fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n", filename, start ); if( dvdinput_title( dvd->dev, (int)start ) < 0 ) { fprintf( stderr, "libdvdread: Error cracking CSS key for %s (0x%08x)\n", filename, start); } gettimeofday( &t_e, NULL ); fprintf( stderr, "libdvdread: Elapsed time %ld\n", (long int) t_e.tv_sec - t_s.tv_sec ); } if( title == 0 ) continue; gettimeofday( &t_s, NULL ); sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 1 ); start = UDFFindFile( dvd, filename, &len ); if( start == 0 || len == 0 ) break; /* Perform CSS key cracking for this title. */ fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n", filename, start ); if( dvdinput_title( dvd->dev, (int)start ) < 0 ) { fprintf( stderr, "libdvdread: Error cracking CSS key for %s (0x%08x)!!\n", filename, start); } gettimeofday( &t_e, NULL ); fprintf( stderr, "libdvdread: Elapsed time %ld\n", (long int) t_e.tv_sec - t_s.tv_sec ); } title--; fprintf( stderr, "libdvdread: Found %d VTS's\n", title ); gettimeofday(&all_e, NULL); fprintf( stderr, "libdvdread: Elapsed time %ld\n", (long int) all_e.tv_sec - all_s.tv_sec ); return 0; } /** * Open a DVD image or block device file. */ static dvd_reader_t *DVDOpenImageFile( const char *location, int have_css ) { dvd_reader_t *dvd; dvd_input_t dev; dev = dvdinput_open( location ); if( !dev ) { fprintf( stderr, "libdvdread: Can't open %s for reading\n", location ); return NULL; } dvd = malloc( sizeof( dvd_reader_t ) ); if( !dvd ) { dvdinput_close(dev); return NULL; } memset( dvd, 0, sizeof( dvd_reader_t ) ); dvd->isImageFile = 1; dvd->dev = dev; dvd->path_root = NULL; dvd->udfcache_level = DEFAULT_UDF_CACHE_LEVEL; dvd->udfcache = NULL; if( have_css ) { /* Only if DVDCSS_METHOD = title, a bit if it's disc or if * DVDCSS_METHOD = key but region mismatch. Unfortunately we * don't have that information. */ dvd->css_state = 1; /* Need key init. */ } dvd->css_title = 0; return dvd; } static dvd_reader_t *DVDOpenPath( const char *path_root ) { dvd_reader_t *dvd; dvd = malloc( sizeof( dvd_reader_t ) ); if( !dvd ) return NULL; dvd->isImageFile = 0; dvd->dev = 0; dvd->path_root = strdup( path_root ); if(!dvd->path_root) { free(dvd); return NULL; } dvd->udfcache_level = DEFAULT_UDF_CACHE_LEVEL; dvd->udfcache = NULL; dvd->css_state = 0; /* Only used in the UDF path */ dvd->css_title = 0; /* Only matters in the UDF path */ return dvd; } #if defined(__sun) /* /dev/rdsk/c0t6d0s0 (link to /devices/...) /vol/dev/rdsk/c0t6d0/?? /vol/rdsk/ */ static char *sun_block2char( const char *path ) { char *new_path; /* Must contain "/dsk/" */ if( !strstr( path, "/dsk/" ) ) return (char *) strdup( path ); /* Replace "/dsk/" with "/rdsk/" */ new_path = malloc( strlen(path) + 2 ); if(!new_path) return NULL; strcpy( new_path, path ); strcpy( strstr( new_path, "/dsk/" ), "" ); strcat( new_path, "/rdsk/" ); strcat( new_path, strstr( path, "/dsk/" ) + strlen( "/dsk/" ) ); return new_path; } #endif #if defined(SYS_BSD) /* FreeBSD /dev/(r)(a)cd0c (a is for atapi), recommended to _not_ use r update: FreeBSD and DragonFly no longer uses the prefix so don't add it. OpenBSD /dev/rcd0c, it needs to be the raw device NetBSD /dev/rcd0[d|c|..] d for x86, c (for non x86), perhaps others Darwin /dev/rdisk0, it needs to be the raw device BSD/OS /dev/sr0c (if not mounted) or /dev/rsr0c ('c' any letter will do) returns a string allocated with strdup. It should be freed when no longer used. */ static char *bsd_block2char( const char *path ) { #if defined(__FreeBSD__) || defined(__DragonFly__) return (char *) strdup( path ); #else char *new_path; /* If it doesn't start with "/dev/" or does start with "/dev/r" exit */ if( strncmp( path, "/dev/", 5 ) || !strncmp( path, "/dev/r", 6 ) ) return (char *) strdup( path ); /* Replace "/dev/" with "/dev/r" */ new_path = malloc( strlen(path) + 2 ); if(!new_path) return NULL; strcpy( new_path, "/dev/r" ); strcat( new_path, path + strlen( "/dev/" ) ); return new_path; #endif /* __FreeBSD__ || __DragonFly__ */ } #endif dvd_reader_t *DVDOpen( const char *ppath ) { struct stat fileinfo; int ret, have_css, retval, cdir = -1; dvd_reader_t *ret_val = NULL; char *dev_name = NULL; char *path = NULL, *new_path = NULL, *path_copy = NULL; #if defined(_WIN32) || defined(__OS2__) int len; #endif if( ppath == NULL ) goto DVDOpen_error; path = strdup(ppath); if( path == NULL ) goto DVDOpen_error; /* Try to open libdvdcss or fall back to standard functions */ have_css = dvdinput_setup(); #if defined(_WIN32) || defined(__OS2__) /* Strip off the trailing \ if it is not a drive */ len = strlen(path); if ((len > 1) && (path[len - 1] == '\\') && (path[len - 2] != ':')) { path[len-1] = '\0'; } #endif ret = stat( path, &fileinfo ); if( ret < 0 ) { /* maybe "host:port" url? try opening it with acCeSS library */ if( strchr(path,':') ) { ret_val = DVDOpenImageFile( path, have_css ); free(path); return ret_val; } /* If we can't stat the file, give up */ fprintf( stderr, "libdvdread: Can't stat %s\n", path ); perror(""); goto DVDOpen_error; } /* First check if this is a block/char device or a file*/ if( S_ISBLK( fileinfo.st_mode ) || S_ISCHR( fileinfo.st_mode ) || S_ISREG( fileinfo.st_mode ) ) { /** * Block devices and regular files are assumed to be DVD-Video images. */ dvd_reader_t *dvd = NULL; #if defined(__sun) dev_name = sun_block2char( path ); #elif defined(SYS_BSD) dev_name = bsd_block2char( path ); #else dev_name = strdup( path ); #endif if(!dev_name) goto DVDOpen_error; dvd = DVDOpenImageFile( dev_name, have_css ); free( dev_name ); free(path); return dvd; } else if( S_ISDIR( fileinfo.st_mode ) ) { dvd_reader_t *auth_drive = 0; #if defined(SYS_BSD) struct fstab* fe; #elif defined(__sun) || defined(__linux__) FILE *mntfile; #endif /* XXX: We should scream real loud here. */ if( !(path_copy = strdup( path ) ) ) goto DVDOpen_error; #ifndef WIN32 /* don't have fchdir, and getcwd( NULL, ... ) is strange */ /* Also WIN32 does not have symlinks, so we don't need this bit of code. */ /* Resolve any symlinks and get the absolute dir name. */ { if( ( cdir = open( ".", O_RDONLY ) ) >= 0 ) { if( chdir( path_copy ) == -1 ) { goto DVDOpen_error; } new_path = malloc(PATH_MAX+1); if(!new_path) { goto DVDOpen_error; } if( getcwd( new_path, PATH_MAX ) == NULL ) { goto DVDOpen_error; } retval = fchdir( cdir ); close( cdir ); cdir = -1; if( retval == -1 ) { goto DVDOpen_error; } path_copy = new_path; new_path = NULL; } } #endif /** * If we're being asked to open a directory, check if that directory * is the mount point for a DVD-ROM which we can use instead. */ if( strlen( path_copy ) > 1 ) { if( path_copy[ strlen( path_copy ) - 1 ] == '/' ) { path_copy[ strlen( path_copy ) - 1 ] = '\0'; } } #if defined(_WIN32) || defined(__OS2__) if(strlen(path_copy) > TITLES_MAX) { if(!strcasecmp(&(path_copy[strlen( path_copy ) - TITLES_MAX]), "\\video_ts")) path_copy[strlen(path_copy) - (TITLES_MAX-1)] = '\0'; } #endif if( strlen( path_copy ) > TITLES_MAX ) { if( !strcasecmp( &(path_copy[ strlen( path_copy ) - TITLES_MAX ]), "/video_ts" ) ) { path_copy[ strlen( path_copy ) - TITLES_MAX ] = '\0'; } } if(path_copy[0] == '\0') { path_copy[0] = '/'; path_copy[1] = '\0'; } #if defined(__APPLE__) struct statfs s[128]; int r = getfsstat(NULL, 0, MNT_NOWAIT); if (r > 0) { if (r > 128) r = 128; r = getfsstat(s, r * sizeof(s[0]), MNT_NOWAIT); int i; for (i=0; ifs_spec ); fprintf( stderr, "libdvdread: Attempting to use device %s" " mounted on %s for CSS authentication\n", dev_name, fe->fs_file ); auth_drive = DVDOpenImageFile( dev_name, have_css ); } #elif defined(__sun) mntfile = fopen( MNTTAB, "r" ); if( mntfile ) { struct mnttab mp; int res; while( ( res = getmntent( mntfile, &mp ) ) != -1 ) { if( res == 0 && !strcmp( mp.mnt_mountp, path_copy ) ) { dev_name = sun_block2char( mp.mnt_special ); fprintf( stderr, "libdvdread: Attempting to use device %s" " mounted on %s for CSS authentication\n", dev_name, mp.mnt_mountp ); auth_drive = DVDOpenImageFile( dev_name, have_css ); break; } } fclose( mntfile ); } #elif defined(__linux__) mntfile = fopen( _PATH_MOUNTED, "r" ); if( mntfile ) { struct mntent *me; while( ( me = getmntent( mntfile ) ) ) { if( !strcmp( me->mnt_dir, path_copy ) ) { fprintf( stderr, "libdvdread: Attempting to use device %s" " mounted on %s for CSS authentication\n", me->mnt_fsname, me->mnt_dir ); auth_drive = DVDOpenImageFile( me->mnt_fsname, have_css ); dev_name = strdup(me->mnt_fsname); break; } } fclose( mntfile ); } #elif defined(_WIN32) || defined(__OS2__) #ifdef __OS2__ /* Use DVDOpenImageFile() only if it is a drive */ if(isalpha(path[0]) && path[1] == ':' && ( !path[2] || ((path[2] == '\\' || path[2] == '/') && !path[3]))) #endif auth_drive = DVDOpenImageFile( path, have_css ); #endif #if !defined(_WIN32) && !defined(__OS2__) if( !dev_name ) { fprintf( stderr, "libdvdread: Couldn't find device name.\n" ); } else if( !auth_drive ) { fprintf( stderr, "libdvdread: Device %s inaccessible, " "CSS authentication not available.\n", dev_name ); } #else if( !auth_drive ) { fprintf( stderr, "libdvdread: Device %s inaccessible, " "CSS authentication not available.\n", path ); } #endif free( dev_name ); dev_name = NULL; free( path_copy ); path_copy = NULL; /** * If we've opened a drive, just use that. */ if( auth_drive ) { free(path); return auth_drive; } /** * Otherwise, we now try to open the directory tree instead. */ ret_val = DVDOpenPath( path ); free( path ); return ret_val; } DVDOpen_error: /* If it's none of the above, screw it. */ fprintf( stderr, "libdvdread: Could not open %s\n", path ); if( path != NULL ) free( path ); if ( path_copy != NULL ) free( path_copy ); if ( cdir >= 0 ) close( cdir ); if ( new_path != NULL ) free( new_path ); return NULL; } void DVDClose( dvd_reader_t *dvd ) { if( dvd ) { if( dvd->dev ) dvdinput_close( dvd->dev ); if( dvd->path_root ) free( dvd->path_root ); if( dvd->udfcache ) FreeUDFCache( dvd->udfcache ); free( dvd ); } } /** * Open an unencrypted file on a DVD image file. */ static dvd_file_t *DVDOpenFileUDF( dvd_reader_t *dvd, char *filename ) { uint32_t start, len; dvd_file_t *dvd_file; start = UDFFindFile( dvd, filename, &len ); if( !start ) { fprintf( stderr, "libdvdread:DVDOpenFileUDF:UDFFindFile %s failed\n", filename ); return NULL; } dvd_file = malloc( sizeof( dvd_file_t ) ); if( !dvd_file ) { fprintf( stderr, "libdvdread:DVDOpenFileUDF:malloc failed\n" ); return NULL; } dvd_file->dvd = dvd; dvd_file->lb_start = start; dvd_file->seek_pos = 0; memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) ); memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) ); dvd_file->filesize = len / DVD_VIDEO_LB_LEN; return dvd_file; } /** * Searches for in directory , ignoring case. * Returns 0 and full filename in . * or -1 on file not found. * or -2 on path not found. */ static int findDirFile( const char *path, const char *file, char *filename ) { DIR *dir; struct dirent *ent; dir = opendir( path ); if( !dir ) return -2; while( ( ent = readdir( dir ) ) != NULL ) { if( !strcasecmp( ent->d_name, file ) ) { sprintf( filename, "%s%s%s", path, ( ( path[ strlen( path ) - 1 ] == '/' ) ? "" : "/" ), ent->d_name ); closedir(dir); return 0; } } closedir(dir); return -1; } static int findDVDFile( dvd_reader_t *dvd, const char *file, char *filename ) { char video_path[ PATH_MAX + 1 ]; const char *nodirfile; int ret; /* Strip off the directory for our search */ if( !strncasecmp( "/VIDEO_TS/", file, 10 ) ) { nodirfile = &(file[ 10 ]); } else { nodirfile = file; } ret = findDirFile( dvd->path_root, nodirfile, filename ); if( ret < 0 ) { /* Try also with adding the path, just in case. */ sprintf( video_path, "%s/VIDEO_TS/", dvd->path_root ); ret = findDirFile( video_path, nodirfile, filename ); if( ret < 0 ) { /* Try with the path, but in lower case. */ sprintf( video_path, "%s/video_ts/", dvd->path_root ); ret = findDirFile( video_path, nodirfile, filename ); if( ret < 0 ) { return 0; } } } return 1; } /** * Open an unencrypted file from a DVD directory tree. */ static dvd_file_t *DVDOpenFilePath( dvd_reader_t *dvd, char *filename ) { char full_path[ PATH_MAX + 1 ]; dvd_file_t *dvd_file; struct stat fileinfo; dvd_input_t dev; /* Get the full path of the file. */ if( !findDVDFile( dvd, filename, full_path ) ) { fprintf( stderr, "libdvdread:DVDOpenFilePath:findDVDFile %s failed\n", filename ); return NULL; } dev = dvdinput_open( full_path ); if( !dev ) { fprintf( stderr, "libdvdread:DVDOpenFilePath:dvdinput_open %s failed\n", full_path ); return NULL; } dvd_file = malloc( sizeof( dvd_file_t ) ); if( !dvd_file ) { fprintf( stderr, "libdvdread:DVDOpenFilePath:dvd_file malloc failed\n" ); dvdinput_close(dev); return NULL; } dvd_file->dvd = dvd; dvd_file->lb_start = 0; dvd_file->seek_pos = 0; memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) ); memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) ); dvd_file->filesize = 0; if( stat( full_path, &fileinfo ) < 0 ) { fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename ); free( dvd_file ); dvdinput_close( dev ); return NULL; } dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN; dvd_file->title_devs[ 0 ] = dev; dvd_file->filesize = dvd_file->title_sizes[ 0 ]; return dvd_file; } static dvd_file_t *DVDOpenVOBUDF( dvd_reader_t *dvd, int title, int menu ) { char filename[ MAX_UDF_FILE_NAME_LEN ]; uint32_t start, len; dvd_file_t *dvd_file; if( title == 0 ) { sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" ); } else { sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, menu ? 0 : 1 ); } start = UDFFindFile( dvd, filename, &len ); if( start == 0 ) return NULL; dvd_file = malloc( sizeof( dvd_file_t ) ); if( !dvd_file ) return NULL; dvd_file->dvd = dvd; /*Hack*/ dvd_file->css_title = title << 1 | menu; dvd_file->lb_start = start; dvd_file->seek_pos = 0; memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) ); memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) ); dvd_file->filesize = len / DVD_VIDEO_LB_LEN; /* Calculate the complete file size for every file in the VOBS */ if( !menu ) { int cur; for( cur = 2; cur < 10; cur++ ) { sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, cur ); if( !UDFFindFile( dvd, filename, &len ) ) break; dvd_file->filesize += len / DVD_VIDEO_LB_LEN; } } if( dvd->css_state == 1 /* Need key init */ ) { initAllCSSKeys( dvd ); dvd->css_state = 2; } /* if( dvdinput_title( dvd_file->dvd->dev, (int)start ) < 0 ) { fprintf( stderr, "libdvdread: Error cracking CSS key for %s\n", filename ); } */ return dvd_file; } static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd, int title, int menu ) { char filename[ MAX_UDF_FILE_NAME_LEN ]; char full_path[ PATH_MAX + 1 ]; struct stat fileinfo; dvd_file_t *dvd_file; int i; dvd_file = malloc( sizeof( dvd_file_t ) ); if( !dvd_file ) return NULL; dvd_file->dvd = dvd; /*Hack*/ dvd_file->css_title = title << 1 | menu; dvd_file->lb_start = 0; dvd_file->seek_pos = 0; memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) ); memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) ); dvd_file->filesize = 0; if( menu ) { dvd_input_t dev; if( title == 0 ) { sprintf( filename, "VIDEO_TS.VOB" ); } else { sprintf( filename, "VTS_%02i_0.VOB", title ); } if( !findDVDFile( dvd, filename, full_path ) ) { free( dvd_file ); return NULL; } dev = dvdinput_open( full_path ); if( dev == NULL ) { free( dvd_file ); return NULL; } if( stat( full_path, &fileinfo ) < 0 ) { fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename ); dvdinput_close(dev); free( dvd_file ); return NULL; } dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN; dvd_file->title_devs[ 0 ] = dev; dvdinput_title( dvd_file->title_devs[0], 0); dvd_file->filesize = dvd_file->title_sizes[ 0 ]; } else { for( i = 0; i < TITLES_MAX; ++i ) { sprintf( filename, "VTS_%02i_%i.VOB", title, i + 1 ); if( !findDVDFile( dvd, filename, full_path ) ) { break; } if( stat( full_path, &fileinfo ) < 0 ) { fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename ); break; } dvd_file->title_sizes[ i ] = fileinfo.st_size / DVD_VIDEO_LB_LEN; dvd_file->title_devs[ i ] = dvdinput_open( full_path ); dvdinput_title( dvd_file->title_devs[ i ], 0 ); dvd_file->filesize += dvd_file->title_sizes[ i ]; } if( !dvd_file->title_devs[ 0 ] ) { free( dvd_file ); return NULL; } } return dvd_file; } dvd_file_t *DVDOpenFile( dvd_reader_t *dvd, int titlenum, dvd_read_domain_t domain ) { char filename[ MAX_UDF_FILE_NAME_LEN ]; /* Check arguments. */ if( dvd == NULL || titlenum < 0 ) return NULL; switch( domain ) { case DVD_READ_INFO_FILE: if( titlenum == 0 ) { sprintf( filename, "/VIDEO_TS/VIDEO_TS.IFO" ); } else { sprintf( filename, "/VIDEO_TS/VTS_%02i_0.IFO", titlenum ); } break; case DVD_READ_INFO_BACKUP_FILE: if( titlenum == 0 ) { sprintf( filename, "/VIDEO_TS/VIDEO_TS.BUP" ); } else { sprintf( filename, "/VIDEO_TS/VTS_%02i_0.BUP", titlenum ); } break; case DVD_READ_MENU_VOBS: if( dvd->isImageFile ) { return DVDOpenVOBUDF( dvd, titlenum, 1 ); } else { return DVDOpenVOBPath( dvd, titlenum, 1 ); } break; case DVD_READ_TITLE_VOBS: if( titlenum == 0 ) return NULL; if( dvd->isImageFile ) { return DVDOpenVOBUDF( dvd, titlenum, 0 ); } else { return DVDOpenVOBPath( dvd, titlenum, 0 ); } break; default: fprintf( stderr, "libdvdread: Invalid domain for file open.\n" ); return NULL; } if( dvd->isImageFile ) { return DVDOpenFileUDF( dvd, filename ); } else { return DVDOpenFilePath( dvd, filename ); } } void DVDCloseFile( dvd_file_t *dvd_file ) { int i; if( dvd_file && dvd_file->dvd ) { if( !dvd_file->dvd->isImageFile ) { for( i = 0; i < TITLES_MAX; ++i ) { if( dvd_file->title_devs[ i ] ) { dvdinput_close( dvd_file->title_devs[i] ); } } } free( dvd_file ); dvd_file = NULL; } } static int DVDFileStatVOBUDF( dvd_reader_t *dvd, int title, int menu, dvd_stat_t *statbuf ) { char filename[ MAX_UDF_FILE_NAME_LEN ]; uint32_t size; off_t tot_size; off_t parts_size[ 9 ]; int nr_parts = 0; int n; if( title == 0 ) sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" ); else sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, menu ? 0 : 1 ); if( !UDFFindFile( dvd, filename, &size ) ) return -1; tot_size = size; nr_parts = 1; parts_size[ 0 ] = size; if( !menu ) { int cur; for( cur = 2; cur < 10; cur++ ) { sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, cur ); if( !UDFFindFile( dvd, filename, &size ) ) break; parts_size[ nr_parts ] = size; tot_size += size; nr_parts++; } } statbuf->size = tot_size; statbuf->nr_parts = nr_parts; for( n = 0; n < nr_parts; n++ ) statbuf->parts_size[ n ] = parts_size[ n ]; return 0; } static int DVDFileStatVOBPath( dvd_reader_t *dvd, int title, int menu, dvd_stat_t *statbuf ) { char filename[ MAX_UDF_FILE_NAME_LEN ]; char full_path[ PATH_MAX + 1 ]; struct stat fileinfo; off_t tot_size; off_t parts_size[ 9 ]; int nr_parts = 0; int n; if( title == 0 ) sprintf( filename, "VIDEO_TS.VOB" ); else sprintf( filename, "VTS_%02d_%d.VOB", title, menu ? 0 : 1 ); if( !findDVDFile( dvd, filename, full_path ) ) return -1; if( stat( full_path, &fileinfo ) < 0 ) { fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename ); return -1; } tot_size = fileinfo.st_size; nr_parts = 1; parts_size[ 0 ] = fileinfo.st_size; if( !menu ) { int cur; for( cur = 2; cur < 10; cur++ ) { sprintf( filename, "VTS_%02d_%d.VOB", title, cur ); if( !findDVDFile( dvd, filename, full_path ) ) break; if( stat( full_path, &fileinfo ) < 0 ) { fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename ); break; } parts_size[ nr_parts ] = fileinfo.st_size; tot_size += parts_size[ nr_parts ]; nr_parts++; } } statbuf->size = tot_size; statbuf->nr_parts = nr_parts; for( n = 0; n < nr_parts; n++ ) statbuf->parts_size[ n ] = parts_size[ n ]; return 0; } int DVDFileStat( dvd_reader_t *dvd, int titlenum, dvd_read_domain_t domain, dvd_stat_t *statbuf ) { char filename[ MAX_UDF_FILE_NAME_LEN ]; char full_path[ PATH_MAX + 1 ]; struct stat fileinfo; uint32_t size; /* Check arguments. */ if( dvd == NULL || titlenum < 0 ) { errno = EINVAL; return -1; } switch( domain ) { case DVD_READ_INFO_FILE: if( titlenum == 0 ) sprintf( filename, "/VIDEO_TS/VIDEO_TS.IFO" ); else sprintf( filename, "/VIDEO_TS/VTS_%02i_0.IFO", titlenum ); break; case DVD_READ_INFO_BACKUP_FILE: if( titlenum == 0 ) sprintf( filename, "/VIDEO_TS/VIDEO_TS.BUP" ); else sprintf( filename, "/VIDEO_TS/VTS_%02i_0.BUP", titlenum ); break; case DVD_READ_MENU_VOBS: if( dvd->isImageFile ) return DVDFileStatVOBUDF( dvd, titlenum, 1, statbuf ); else return DVDFileStatVOBPath( dvd, titlenum, 1, statbuf ); break; case DVD_READ_TITLE_VOBS: if( titlenum == 0 ) return -1; if( dvd->isImageFile ) return DVDFileStatVOBUDF( dvd, titlenum, 0, statbuf ); else return DVDFileStatVOBPath( dvd, titlenum, 0, statbuf ); break; default: fprintf( stderr, "libdvdread: Invalid domain for file stat.\n" ); errno = EINVAL; return -1; } if( dvd->isImageFile ) { if( UDFFindFile( dvd, filename, &size ) ) { statbuf->size = size; statbuf->nr_parts = 1; statbuf->parts_size[ 0 ] = size; return 0; } } else { if( findDVDFile( dvd, filename, full_path ) ) { if( stat( full_path, &fileinfo ) < 0 ) fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename ); else { statbuf->size = fileinfo.st_size; statbuf->nr_parts = 1; statbuf->parts_size[ 0 ] = statbuf->size; return 0; } } } return -1; } /* Internal, but used from dvd_udf.c */ int InternalUDFReadBlocksRaw( const dvd_reader_t *device, uint32_t lb_number, size_t block_count, unsigned char *data, int encrypted ) { int ret; if( !device->dev ) { fprintf( stderr, "libdvdread: Fatal error in block read.\n" ); return 0; } ret = dvdinput_seek( device->dev, (int) lb_number ); if( ret != (int) lb_number ) { fprintf( stderr, "libdvdread: Can't seek to block %u\n", lb_number ); return 0; } ret = dvdinput_read( device->dev, (char *) data, (int) block_count, encrypted ); return ret; } /* This is using a single input and starting from 'dvd_file->lb_start' offset. * * Reads 'block_count' blocks from 'dvd_file' at block offset 'offset' * into the buffer located at 'data' and if 'encrypted' is set * descramble the data if it's encrypted. Returning either an * negative error or the number of blocks read. */ static int DVDReadBlocksUDF( const dvd_file_t *dvd_file, uint32_t offset, size_t block_count, unsigned char *data, int encrypted ) { return InternalUDFReadBlocksRaw( dvd_file->dvd, dvd_file->lb_start + offset, block_count, data, encrypted ); } /* This is using possibly several inputs and starting from an offset of '0'. * * Reads 'block_count' blocks from 'dvd_file' at block offset 'offset' * into the buffer located at 'data' and if 'encrypted' is set * descramble the data if it's encrypted. Returning either an * negative error or the number of blocks read. */ static int DVDReadBlocksPath( const dvd_file_t *dvd_file, unsigned int offset, size_t block_count, unsigned char *data, int encrypted ) { int i; int ret, ret2, off; ret = 0; ret2 = 0; for( i = 0; i < TITLES_MAX; ++i ) { if( !dvd_file->title_sizes[ i ] ) return 0; /* Past end of file */ if( offset < dvd_file->title_sizes[ i ] ) { if( ( offset + block_count ) <= dvd_file->title_sizes[ i ] ) { off = dvdinput_seek( dvd_file->title_devs[ i ], (int)offset ); if( off < 0 || off != (int)offset ) { fprintf( stderr, "libdvdread: Can't seek to block %d\n", offset ); return off < 0 ? off : 0; } ret = dvdinput_read( dvd_file->title_devs[ i ], data, (int)block_count, encrypted ); break; } else { size_t part1_size = dvd_file->title_sizes[ i ] - offset; /* FIXME: Really needs to be a while loop. * (This is only true if you try and read >1GB at a time) */ /* Read part 1 */ off = dvdinput_seek( dvd_file->title_devs[ i ], (int)offset ); if( off < 0 || off != (int)offset ) { fprintf( stderr, "libdvdread: Can't seek to block %d\n", offset ); return off < 0 ? off : 0; } ret = dvdinput_read( dvd_file->title_devs[ i ], data, (int)part1_size, encrypted ); if( ret < 0 ) return ret; /* FIXME: This is wrong if i is the last file in the set. * also error from this read will not show in ret. */ /* Does the next part exist? If not then return now. */ if( i + 1 >= TITLES_MAX || !dvd_file->title_devs[ i + 1 ] ) return ret; /* Read part 2 */ off = dvdinput_seek( dvd_file->title_devs[ i + 1 ], 0 ); if( off < 0 || off != 0 ) { fprintf( stderr, "libdvdread: Can't seek to block %d\n", 0 ); return off < 0 ? off : 0; } ret2 = dvdinput_read( dvd_file->title_devs[ i + 1 ], data + ( part1_size * (int64_t)DVD_VIDEO_LB_LEN ), (int)(block_count - part1_size), encrypted ); if( ret2 < 0 ) return ret2; break; } } else { offset -= dvd_file->title_sizes[ i ]; } } return ret + ret2; } /* This is broken reading more than 2Gb at a time is ssize_t is 32-bit. */ ssize_t DVDReadBlocks( dvd_file_t *dvd_file, int offset, size_t block_count, unsigned char *data ) { int ret; /* Check arguments. */ if( dvd_file == NULL || offset < 0 || data == NULL ) return -1; /* Hack, and it will still fail for multiple opens in a threaded app ! */ if( dvd_file->dvd->css_title != dvd_file->css_title ) { dvd_file->dvd->css_title = dvd_file->css_title; if( dvd_file->dvd->isImageFile ) { dvdinput_title( dvd_file->dvd->dev, (int)dvd_file->lb_start ); } /* Here each vobu has it's own dvdcss handle, so no need to update else { dvdinput_title( dvd_file->title_devs[ 0 ], (int)dvd_file->lb_start ); }*/ } if( dvd_file->dvd->isImageFile ) { ret = DVDReadBlocksUDF( dvd_file, (uint32_t)offset, block_count, data, DVDINPUT_READ_DECRYPT ); } else { ret = DVDReadBlocksPath( dvd_file, (unsigned int)offset, block_count, data, DVDINPUT_READ_DECRYPT ); } return (ssize_t)ret; } int32_t DVDFileSeek( dvd_file_t *dvd_file, int32_t offset ) { /* Check arguments. */ if( dvd_file == NULL || offset < 0 ) return -1; if( offset > dvd_file->filesize * DVD_VIDEO_LB_LEN ) { return -1; } dvd_file->seek_pos = (uint32_t) offset; return offset; } int DVDFileSeekForce(dvd_file_t *dvd_file, int offset, int force_size) { /* Check arguments. */ if( dvd_file == NULL || offset <= 0 ) return -1; if( dvd_file->dvd->isImageFile ) { if( force_size < 0 ) force_size = (offset - 1) / DVD_VIDEO_LB_LEN + 1; if( dvd_file->filesize < force_size ) { dvd_file->filesize = force_size; fprintf(stderr, "libdvdread: Ignored size of file indicated in UDF.\n"); } } if( offset > dvd_file->filesize * DVD_VIDEO_LB_LEN ) return -1; dvd_file->seek_pos = (uint32_t) offset; return offset; } ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size ) { unsigned char *secbuf_base, *secbuf; unsigned int numsec, seek_sector, seek_byte; int ret; /* Check arguments. */ if( dvd_file == NULL || data == NULL ) return -1; seek_sector = dvd_file->seek_pos / DVD_VIDEO_LB_LEN; seek_byte = dvd_file->seek_pos % DVD_VIDEO_LB_LEN; numsec = ( ( seek_byte + byte_size ) / DVD_VIDEO_LB_LEN ) + ( ( ( seek_byte + byte_size ) % DVD_VIDEO_LB_LEN ) ? 1 : 0 ); secbuf_base = malloc( numsec * DVD_VIDEO_LB_LEN + 2048 ); secbuf = (unsigned char *)(((uintptr_t)secbuf_base & ~((uintptr_t)2047)) + 2048); if( !secbuf_base ) { fprintf( stderr, "libdvdread: Can't allocate memory " "for file read!\n" ); return 0; } if( dvd_file->dvd->isImageFile ) { ret = DVDReadBlocksUDF( dvd_file, (uint32_t) seek_sector, (size_t) numsec, secbuf, DVDINPUT_NOFLAGS ); } else { ret = DVDReadBlocksPath( dvd_file, seek_sector, (size_t) numsec, secbuf, DVDINPUT_NOFLAGS ); } if( ret != (int) numsec ) { free( secbuf_base ); return ret < 0 ? ret : 0; } memcpy( data, &(secbuf[ seek_byte ]), byte_size ); free( secbuf_base ); DVDFileSeekForce(dvd_file, dvd_file->seek_pos + byte_size, -1); return byte_size; } ssize_t DVDFileSize( dvd_file_t *dvd_file ) { /* Check arguments. */ if( dvd_file == NULL ) return -1; return dvd_file->filesize; } int DVDDiscID( dvd_reader_t *dvd, unsigned char *discid ) { struct md5_ctx ctx; int title; int title_sets; int nr_of_files = 0; ifo_handle_t *vmg_ifo; /* Check arguments. */ if( dvd == NULL || discid == NULL ) return 0; vmg_ifo = ifoOpen( dvd, 0 ); if( !vmg_ifo ) { fprintf( stderr, "libdvdread: DVDDiscId, failed to " "open VMG IFO!\n" ); return -1; } title_sets = vmg_ifo->vmgi_mat->vmg_nr_of_title_sets + 1; ifoClose( vmg_ifo ); if( title_sets > 10 ) title_sets = 10; /* Go through the first IFO:s, in order, up until the tenth, * and md5sum them, i.e VIDEO_TS.IFO and VTS_0?_0.IFO */ md5_init_ctx( &ctx ); for( title = 0; title < title_sets; title++ ) { dvd_file_t *dvd_file = DVDOpenFile( dvd, title, DVD_READ_INFO_FILE ); if( dvd_file != NULL ) { ssize_t bytes_read; ssize_t file_size = dvd_file->filesize * DVD_VIDEO_LB_LEN; char *buffer_base = malloc( file_size + 2048 ); char *buffer = (char *)(((uintptr_t)buffer_base & ~((uintptr_t)2047)) + 2048); if( buffer_base == NULL ) { DVDCloseFile( dvd_file ); fprintf( stderr, "libdvdread: DVDDiscId, failed to " "allocate memory for file read!\n" ); return -1; } bytes_read = DVDReadBytes( dvd_file, buffer, file_size ); if( bytes_read != file_size ) { fprintf( stderr, "libdvdread: DVDDiscId read returned %zd bytes" ", wanted %zd\n", bytes_read, file_size ); DVDCloseFile( dvd_file ); free( buffer_base ); return -1; } md5_process_bytes( buffer, file_size, &ctx ); DVDCloseFile( dvd_file ); free( buffer_base ); nr_of_files++; } } md5_finish_ctx( &ctx, discid ); if(!nr_of_files) return -1; return 0; } int DVDISOVolumeInfo( dvd_reader_t *dvd, char *volid, unsigned int volid_size, unsigned char *volsetid, unsigned int volsetid_size ) { unsigned char *buffer, *buffer_base; int ret; /* Check arguments. */ if( dvd == NULL ) return 0; if( dvd->dev == NULL ) { /* No block access, so no ISO... */ return -1; } buffer_base = malloc( DVD_VIDEO_LB_LEN + 2048 ); buffer = (unsigned char *)(((uintptr_t)buffer_base & ~((uintptr_t)2047)) + 2048); if( buffer_base == NULL ) { fprintf( stderr, "libdvdread: DVDISOVolumeInfo, failed to " "allocate memory for file read!\n" ); return -1; } ret = InternalUDFReadBlocksRaw( dvd, 16, 1, buffer, 0 ); if( ret != 1 ) { fprintf( stderr, "libdvdread: DVDISOVolumeInfo, failed to " "read ISO9660 Primary Volume Descriptor!\n" ); free( buffer_base ); return -1; } if( (volid != NULL) && (volid_size > 0) ) { unsigned int n; for(n = 0; n < 32; n++) { if(buffer[40+n] == 0x20) { break; } } if(volid_size > n+1) { volid_size = n+1; } memcpy(volid, &buffer[40], volid_size-1); volid[volid_size-1] = '\0'; } if( (volsetid != NULL) && (volsetid_size > 0) ) { if(volsetid_size > 128) { volsetid_size = 128; } memcpy(volsetid, &buffer[190], volsetid_size); } free( buffer_base ); return 0; } int DVDUDFVolumeInfo( dvd_reader_t *dvd, char *volid, unsigned int volid_size, unsigned char *volsetid, unsigned int volsetid_size ) { int ret; /* Check arguments. */ if( dvd == NULL ) return -1; if( dvd->dev == NULL ) { /* No block access, so no UDF VolumeSet Identifier */ return -1; } if( (volid != NULL) && (volid_size > 0) ) { ret = UDFGetVolumeIdentifier(dvd, volid, volid_size); if(!ret) { return -1; } } if( (volsetid != NULL) && (volsetid_size > 0) ) { ret = UDFGetVolumeSetIdentifier(dvd, volsetid, volsetid_size); if(!ret) { return -1; } } return 0; } k9copy/src/libdvdread-NOW/dvdread/0000755000175000017550000000000012412304751017503 5ustar emulatoremulatork9copy/src/libdvdread-NOW/dvdread/nav_types.h0000644000175000017550000002070312412304751021666 0ustar emulatoremulator/* * Copyright (C) 2000, 2001, 2002 Håkan Hjort * * The data structures in this file should represent the layout of the * pci and dsi packets as they are stored in the stream. Information * found by reading the source to VOBDUMP is the base for the structure * and names of these data types. * * VOBDUMP: a program for examining DVD .VOB files. * Copyright 1998, 1999 Eric Smith * * VOBDUMP is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. Note that I am not * granting permission to redistribute or modify VOBDUMP under the terms * of any later version of the General Public License. * * This program is distributed in the hope that it will be useful (or at * least amusing), but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef LIBDVDREAD_NAV_TYPES_H #define LIBDVDREAD_NAV_TYPES_H #include #include "ifo_types.h" /* only dvd_time_t, vm_cmd_t and user_ops_t */ /* The length including the substream id byte. */ #define PCI_BYTES 0x3d4 #define DSI_BYTES 0x3fa #define PS2_PCI_SUBSTREAM_ID 0x00 #define PS2_DSI_SUBSTREAM_ID 0x01 /* Remove this */ #define DSI_START_BYTE 1031 /** * PCI General Information */ typedef struct { uint32_t nv_pck_lbn; /**< sector address of this nav pack */ uint16_t vobu_cat; /**< 'category' of vobu */ uint16_t zero1; /**< reserved */ user_ops_t vobu_uop_ctl; /**< UOP of vobu */ uint32_t vobu_s_ptm; /**< start presentation time of vobu */ uint32_t vobu_e_ptm; /**< end presentation time of vobu */ uint32_t vobu_se_e_ptm; /**< end ptm of sequence end in vobu */ dvd_time_t e_eltm; /**< Cell elapsed time */ char vobu_isrc[32]; } ATTRIBUTE_PACKED pci_gi_t; /** * Non Seamless Angle Information */ typedef struct { uint32_t nsml_agl_dsta[9]; /**< address of destination vobu in AGL_C#n */ } ATTRIBUTE_PACKED nsml_agli_t; /** * Highlight General Information * * For btngrX_dsp_ty the bits have the following meaning: * 000b: normal 4/3 only buttons * XX1b: wide (16/9) buttons * X1Xb: letterbox buttons * 1XXb: pan&scan buttons */ typedef struct { uint16_t hli_ss; /**< status, only low 2 bits 0: no buttons, 1: different 2: equal 3: eual except for button cmds */ uint32_t hli_s_ptm; /**< start ptm of hli */ uint32_t hli_e_ptm; /**< end ptm of hli */ uint32_t btn_se_e_ptm; /**< end ptm of button select */ unsigned int zero1 : 2; /**< reserved */ unsigned int btngr_ns : 2; /**< number of button groups 1, 2 or 3 with 36/18/12 buttons */ unsigned int zero2 : 1; /**< reserved */ unsigned int btngr1_dsp_ty : 3; /**< display type of subpic stream for button group 1 */ unsigned int zero3 : 1; /**< reserved */ unsigned int btngr2_dsp_ty : 3; /**< display type of subpic stream for button group 2 */ unsigned int zero4 : 1; /**< reserved */ unsigned int btngr3_dsp_ty : 3; /**< display type of subpic stream for button group 3 */ uint8_t btn_ofn; /**< button offset number range 0-255 */ uint8_t btn_ns; /**< number of valid buttons <= 36/18/12 (low 6 bits) */ uint8_t nsl_btn_ns; /**< number of buttons selectable by U_BTNNi (low 6 bits) nsl_btn_ns <= btn_ns */ uint8_t zero5; /**< reserved */ uint8_t fosl_btnn; /**< forcedly selected button (low 6 bits) */ uint8_t foac_btnn; /**< forcedly activated button (low 6 bits) */ } ATTRIBUTE_PACKED hl_gi_t; /** * Button Color Information Table * Each entry beeing a 32bit word that contains the color indexs and alpha * values to use. They are all represented by 4 bit number and stored * like this [Ci3, Ci2, Ci1, Ci0, A3, A2, A1, A0]. The actual palette * that the indexes reference is in the PGC. * @TODO split the uint32_t into a struct */ typedef struct { uint32_t btn_coli[3][2]; /**< [button color number-1][select:0/action:1] */ } ATTRIBUTE_PACKED btn_colit_t; /** * Button Information * * NOTE: I've had to change the structure from the disk layout to get * the packing to work with Sun's Forte C compiler. * The 4 and 7 bytes are 'rotated' was: ABC DEF GHIJ is: ABCG DEFH IJ */ typedef struct { unsigned int btn_coln : 2; /**< button color number */ unsigned int x_start : 10; /**< x start offset within the overlay */ unsigned int zero1 : 2; /**< reserved */ unsigned int x_end : 10; /**< x end offset within the overlay */ unsigned int auto_action_mode : 2; /**< 0: no, 1: activated if selected */ unsigned int y_start : 10; /**< y start offset within the overlay */ unsigned int zero2 : 2; /**< reserved */ unsigned int y_end : 10; /**< y end offset within the overlay */ unsigned int zero3 : 2; /**< reserved */ unsigned int up : 6; /**< button index when pressing up */ unsigned int zero4 : 2; /**< reserved */ unsigned int down : 6; /**< button index when pressing down */ unsigned int zero5 : 2; /**< reserved */ unsigned int left : 6; /**< button index when pressing left */ unsigned int zero6 : 2; /**< reserved */ unsigned int right : 6; /**< button index when pressing right */ vm_cmd_t cmd; } ATTRIBUTE_PACKED btni_t; /** * Highlight Information */ typedef struct { hl_gi_t hl_gi; btn_colit_t btn_colit; btni_t btnit[36]; } ATTRIBUTE_PACKED hli_t; /** * PCI packet */ typedef struct { pci_gi_t pci_gi; nsml_agli_t nsml_agli; hli_t hli; uint8_t zero1[189]; } ATTRIBUTE_PACKED pci_t; /** * DSI General Information */ typedef struct { uint32_t nv_pck_scr; uint32_t nv_pck_lbn; /**< sector address of this nav pack */ uint32_t vobu_ea; /**< end address of this VOBU */ uint32_t vobu_1stref_ea; /**< end address of the 1st reference image */ uint32_t vobu_2ndref_ea; /**< end address of the 2nd reference image */ uint32_t vobu_3rdref_ea; /**< end address of the 3rd reference image */ uint16_t vobu_vob_idn; /**< VOB Id number that this VOBU is part of */ uint8_t zero1; /**< reserved */ uint8_t vobu_c_idn; /**< Cell Id number that this VOBU is part of */ dvd_time_t c_eltm; /**< Cell elapsed time */ } ATTRIBUTE_PACKED dsi_gi_t; /** * Seamless Playback Information */ typedef struct { uint16_t category; /**< 'category' of seamless VOBU */ uint32_t ilvu_ea; /**< end address of interleaved Unit */ uint32_t ilvu_sa; /**< start address of next interleaved unit */ uint16_t size; /**< size of next interleaved unit */ uint32_t vob_v_s_s_ptm; /**< video start ptm in vob */ uint32_t vob_v_e_e_ptm; /**< video end ptm in vob */ struct { uint32_t stp_ptm1; uint32_t stp_ptm2; uint32_t gap_len1; uint32_t gap_len2; } vob_a[8]; } ATTRIBUTE_PACKED sml_pbi_t; /** * Seamless Angle Information for one angle */ typedef struct { uint32_t address; /**< offset to next ILVU, high bit is before/after */ uint16_t size; /**< byte size of the ILVU pointed to by address */ } ATTRIBUTE_PACKED sml_agl_data_t; /** * Seamless Angle Information */ typedef struct { sml_agl_data_t data[9]; } ATTRIBUTE_PACKED sml_agli_t; /** * VOBU Search Information */ typedef struct { uint32_t next_video; /**< Next vobu that contains video */ uint32_t fwda[19]; /**< Forwards, time */ uint32_t next_vobu; uint32_t prev_vobu; uint32_t bwda[19]; /**< Backwards, time */ uint32_t prev_video; } ATTRIBUTE_PACKED vobu_sri_t; #define SRI_END_OF_CELL 0x3fffffff /** * Synchronous Information */ typedef struct { uint16_t a_synca[8]; /**< offset to first audio packet for this VOBU */ uint32_t sp_synca[32]; /**< offset to first subpicture packet */ } ATTRIBUTE_PACKED synci_t; /** * DSI packet */ typedef struct { dsi_gi_t dsi_gi; sml_pbi_t sml_pbi; sml_agli_t sml_agli; vobu_sri_t vobu_sri; synci_t synci; uint8_t zero1[471]; } ATTRIBUTE_PACKED dsi_t; #if PRAGMA_PACK #pragma pack() #endif #endif /* LIBDVDREAD_NAV_TYPES_H */ k9copy/src/libdvdread-NOW/dvdread/bitreader.h0000644000175000017550000000236512412304751021623 0ustar emulatoremulator/* * Copyright (C) 2000, 2001, 2002 Håkan Hjort . * * This file is part of libdvdread. * * libdvdread is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdread is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdread; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef LIBDVDREAD_BITREADER_H #define LIBDVDREAD_BITREADER_H #ifdef __cplusplus extern "C" { #endif typedef struct { uint8_t *start; uint32_t byte_position; uint32_t bit_position; uint8_t byte; } getbits_state_t; int dvdread_getbits_init(getbits_state_t *state, uint8_t *start); uint32_t dvdread_getbits(getbits_state_t *state, uint32_t number_of_bits); #ifdef __cplusplus }; #endif #endif /* LIBDVDREAD_BITREADER_H */ k9copy/src/libdvdread-NOW/dvdread/ifo_print.h0000644000175000017550000000174212412304751021651 0ustar emulatoremulator/* * This file is part of libdvdread. * * libdvdread is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdread is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdread; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef LIBDVDREAD_IFO_PRINT_H #define LIBDVDREAD_IFO_PRINT_H #include #include "ifo_types.h" void ifo_print(dvd_reader_t *dvd, int title); void dvdread_print_time(dvd_time_t *dtime); #endif /* LIBDVDREAD_IFO_PRINT_H */ k9copy/src/libdvdread-NOW/dvdread/nav_read.h0000644000175000017550000000303712412304751021436 0ustar emulatoremulator/* * Copyright (C) 2000, 2001, 2002 Håkan Hjort . * * This file is part of libdvdread. * * libdvdread is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdread is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdread; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef LIBDVDREAD_NAV_READ_H #define LIBDVDREAD_NAV_READ_H #include "nav_types.h" /** * Parsing of NAV data, PCI and DSI parts. */ #ifdef __cplusplus extern "C" { #endif /** * Reads the PCI packet data pointed to into th pci struct. * * @param pci Pointer to the PCI data structure to be filled in. * @param bufffer Pointer to the buffer of the on disc PCI data. */ void navRead_PCI(pci_t *, unsigned char *); /** * Reads the DSI packet data pointed to into dsi struct. * * @param dsi Pointer to the DSI data structure to be filled in. * @param bufffer Pointer to the buffer of the on disc DSI data. */ void navRead_DSI(dsi_t *, unsigned char *); #ifdef __cplusplus }; #endif #endif /* LIBDVDREAD_NAV_READ_H */ k9copy/src/libdvdread-NOW/dvdread/nav_print.h0000644000175000017550000000267412412304751021665 0ustar emulatoremulator/* * Copyright (C) 2001, 2002 Billy Biggs , * Håkan Hjort * * This file is part of libdvdread. * * libdvdread is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdread is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdread; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef LIBDVDREAD_NAV_PRINT_H #define LIBDVDREAD_NAV_PRINT_H #include "nav_types.h" /** * Pretty printing of the NAV packets, PCI and DSI structs. */ #ifdef __cplusplus extern "C" { #endif /** * Prints information contained in the PCI to stdout. * * @param pci Pointer to the PCI data structure to be printed. */ void navPrint_PCI(pci_t *); /** * Prints information contained in the DSI to stdout. * * @param dsi Pointer to the DSI data structure to be printed. */ void navPrint_DSI(dsi_t *); #ifdef __cplusplus }; #endif #endif /* LIBDVDREAD_NAV_PRINT_H */ k9copy/src/libdvdread-NOW/dvdread/dvd_udf.h0000644000175000017550000000405412412304751021272 0ustar emulatoremulator/* * This code is based on dvdudf by: * Christian Wolff . * * Modifications by: * Billy Biggs . * Björn Englund . * * dvdudf: parse and read the UDF volume information of a DVD Video * Copyright (C) 1999 Christian Wolff for convergence integrated media * GmbH The author can be reached at scarabaeus@convergence.de, the * project's page is at http://linuxtv.org/dvd/ * * This file is part of libdvdread. * * libdvdread is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdread is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdread; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef LIBDVDREAD_DVD_UDF_H #define LIBDVDREAD_DVD_UDF_H #include #include "dvdread/dvd_reader.h" #ifdef __cplusplus extern "C" { #endif /** * Looks for a file on the UDF disc/imagefile and returns the block number * where it begins, or 0 if it is not found. The filename should be an * absolute pathname on the UDF filesystem, starting with '/'. For example, * '/VIDEO_TS/VTS_01_1.IFO'. On success, filesize will be set to the size of * the file in bytes. */ uint32_t UDFFindFile( dvd_reader_t *device, char *filename, uint32_t *size ); int UDFGetVolumeIdentifier(dvd_reader_t *device, char *volid, unsigned int volid_size); int UDFGetVolumeSetIdentifier(dvd_reader_t *device, uint8_t *volsetid, unsigned int volsetid_size); #ifdef __cplusplus }; #endif #endif /* LIBDVDREAD_DVD_UDF_H */ k9copy/src/libdvdread-NOW/dvdread/ifo_types.h0000644000175000017550000005600612412515340021662 0ustar emulatoremulator/* * Copyright (C) 2000, 2001 Björn Englund , * Håkan Hjort * * This file is part of libdvdread. * * libdvdread is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdread is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdread; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef LIBDVDREAD_IFO_TYPES_H #define LIBDVDREAD_IFO_TYPES_H #include #include "dvdread/dvd_reader.h" #undef ATTRIBUTE_PACKED #undef PRAGMA_PACK_BEGIN #undef PRAGMA_PACK_END #if defined(__GNUC__) #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95) #define ATTRIBUTE_PACKED __attribute__ ((packed)) #define PRAGMA_PACK 0 #endif #endif #if !defined(ATTRIBUTE_PACKED) #define ATTRIBUTE_PACKED #define PRAGMA_PACK 1 #endif #if PRAGMA_PACK #pragma pack(1) #endif /** * Common * * The following structures are used in both the VMGI and VTSI. */ /** * DVD Time Information. */ typedef struct { uint8_t hour; uint8_t minute; uint8_t second; uint8_t frame_u; /* The two high bits are the frame rate. */ } ATTRIBUTE_PACKED dvd_time_t; /** * Type to store per-command data. */ typedef struct { uint8_t bytes[8]; } ATTRIBUTE_PACKED vm_cmd_t; #define COMMAND_DATA_SIZE 8U /** * Video Attributes. */ typedef struct { //PM ADDITIONS #ifdef WORDS_BIGENDIAN unsigned char mpeg_version : 2; unsigned char video_format : 2; unsigned char display_aspect_ratio : 2; unsigned char permitted_df : 2; unsigned char line21_cc_1 : 1; unsigned char line21_cc_2 : 1; unsigned char unknown1 : 1; unsigned char bit_rate : 1; unsigned char picture_size : 2; unsigned char letterboxed : 1; unsigned char film_mode : 1; //PM ADDED IF ELSE STATEMENT ONLY #else unsigned char permitted_df : 2; unsigned char display_aspect_ratio : 2; unsigned char video_format : 2; unsigned char mpeg_version : 2; unsigned char film_mode : 1; unsigned char letterboxed : 1; unsigned char picture_size : 2; unsigned char bit_rate : 1; unsigned char unknown1 : 1; unsigned char line21_cc_2 : 1; unsigned char line21_cc_1 : 1; #endif //END OF this addition } ATTRIBUTE_PACKED video_attr_t; /** * Audio Attributes. */ typedef struct { //PM IF DEF AGAIN #ifdef WORDS_BIGENDIAN unsigned char audio_format : 3; unsigned char multichannel_extension : 1; unsigned char lang_type : 2; unsigned char application_mode : 2; unsigned char quantization : 2; unsigned char sample_frequency : 2; unsigned char unknown1 : 1; unsigned char channels : 3; #else unsigned char application_mode : 2; unsigned char lang_type : 2; unsigned char multichannel_extension : 1; unsigned char audio_format : 3; unsigned char channels : 3; unsigned char unknown1 : 1; unsigned char sample_frequency : 2; unsigned char quantization : 2; #endif uint16_t lang_code; uint8_t lang_extension; uint8_t code_extension; uint8_t unknown3; union { struct ATTRIBUTE_PACKED { #ifdef WORDS_BIGENDIAN //PM unsigned char unknown4 : 1; unsigned char channel_assignment : 3; unsigned char version : 2; unsigned char mc_intro : 1; /* probably 0: true, 1:false */ unsigned char mode : 1; /* Karaoke mode 0: solo 1: duet */ #else unsigned char mode : 1; unsigned char mc_intro : 1; unsigned char version : 2; unsigned char channel_assignment : 3; unsigned char unknown4 : 1; #endif } karaoke; struct ATTRIBUTE_PACKED { #ifdef WORDS_BIGENDIAN //PM unsigned char unknown5 : 4; unsigned char dolby_encoded : 1; /* suitable for surround decoding */ unsigned char unknown6 : 3; #else unsigned char unknown6 : 3; unsigned char dolby_encoded : 1; unsigned char unknown5 : 4; #endif } surround; } ATTRIBUTE_PACKED app_info; } ATTRIBUTE_PACKED audio_attr_t; /** * MultiChannel Extension */ typedef struct { #ifdef WORDS_BIGENDIAN //PM unsigned int zero1 : 7; unsigned int ach0_gme : 1; unsigned int zero2 : 7; unsigned int ach1_gme : 1; unsigned int zero3 : 4; unsigned int ach2_gv1e : 1; unsigned int ach2_gv2e : 1; unsigned int ach2_gm1e : 1; unsigned int ach2_gm2e : 1; unsigned int zero4 : 4; unsigned int ach3_gv1e : 1; unsigned int ach3_gv2e : 1; unsigned int ach3_gmAe : 1; unsigned int ach3_se2e : 1; unsigned int zero5 : 4; unsigned int ach4_gv1e : 1; unsigned int ach4_gv2e : 1; unsigned int ach4_gmBe : 1; unsigned int ach4_seBe : 1; #else unsigned int ach0_gme : 1; unsigned int zero1 : 7; unsigned int ach1_gme : 1; unsigned int zero2 : 7; unsigned int ach2_gm2e : 1; unsigned int ach2_gm1e : 1; unsigned int ach2_gv2e : 1; unsigned int ach2_gv1e : 1; unsigned int zero3 : 4; unsigned int ach3_se2e : 1; unsigned int ach3_gmAe : 1; unsigned int ach3_gv2e : 1; unsigned int ach3_gv1e : 1; unsigned int zero4 : 4; unsigned int ach4_seBe : 1; unsigned int ach4_gmBe : 1; unsigned int ach4_gv2e : 1; unsigned int ach4_gv1e : 1; unsigned int zero5 : 4; #endif uint8_t zero6[19]; } ATTRIBUTE_PACKED multichannel_ext_t; /** * Subpicture Attributes. */ typedef struct { /* * type: 0 not specified * 1 language * 2 other * coding mode: 0 run length * 1 extended * 2 other * language: indicates language if type == 1 * lang extension: if type == 1 contains the lang extension */ #ifdef WORDS_BIGENDIAN unsigned char code_mode : 3; unsigned char zero1 : 3; unsigned char type : 2; #else unsigned char type : 2; unsigned char zero1 : 3; unsigned char code_mode : 3; #endif uint8_t zero2; uint16_t lang_code; uint8_t lang_extension; uint8_t code_extension; } ATTRIBUTE_PACKED subp_attr_t; /** * PGC Command Table. */ typedef struct { uint16_t nr_of_pre; uint16_t nr_of_post; uint16_t nr_of_cell; uint16_t zero_1; vm_cmd_t *pre_cmds; vm_cmd_t *post_cmds; vm_cmd_t *cell_cmds; } ATTRIBUTE_PACKED pgc_command_tbl_t; #define PGC_COMMAND_TBL_SIZE 8U /** * PGC Program Map */ typedef uint8_t pgc_program_map_t; /** * Cell Playback Information. */ typedef struct { //PM IFDEF #ifdef WORDS_BIGENDIAN unsigned int block_mode : 2; unsigned int block_type : 2; unsigned int seamless_play : 1; unsigned int interleaved : 1; unsigned int stc_discontinuity: 1; unsigned int seamless_angle : 1; unsigned int playback_mode : 1; /**< When set, enter StillMode after each VOBU */ unsigned int restricted : 1; /**< ?? drop out of fastforward? */ unsigned int unknown2 : 6; #else unsigned int seamless_angle : 1; unsigned int stc_discontinuity: 1; unsigned int interleaved : 1; unsigned int seamless_play : 1; unsigned int block_type : 2; unsigned int block_mode : 2; unsigned int unknown2 : 6; unsigned int restricted : 1; unsigned int playback_mode : 1; #endif uint8_t still_time; uint8_t cell_cmd_nr; dvd_time_t playback_time; uint32_t first_sector; uint32_t first_ilvu_end_sector; uint32_t last_vobu_start_sector; uint32_t last_sector; } ATTRIBUTE_PACKED cell_playback_t; #define BLOCK_TYPE_NONE 0x0 #define BLOCK_TYPE_ANGLE_BLOCK 0x1 #define BLOCK_MODE_NOT_IN_BLOCK 0x0 #define BLOCK_MODE_FIRST_CELL 0x1 #define BLOCK_MODE_IN_BLOCK 0x2 #define BLOCK_MODE_LAST_CELL 0x3 /** * Cell Position Information. */ typedef struct { uint16_t vob_id_nr; uint8_t zero_1; uint8_t cell_nr; } ATTRIBUTE_PACKED cell_position_t; /** * User Operations. */ typedef struct { #ifdef WORDS_BIGENDIAN unsigned int zero : 7; /* 25-31 */ unsigned int video_pres_mode_change : 1; /* 24 */ unsigned int karaoke_audio_pres_mode_change : 1; /* 23 */ unsigned int angle_change : 1; unsigned int subpic_stream_change : 1; unsigned int audio_stream_change : 1; unsigned int pause_on : 1; unsigned int still_off : 1; unsigned int button_select_or_activate : 1; unsigned int resume : 1; /* 16 */ unsigned int chapter_menu_call : 1; /* 15 */ unsigned int angle_menu_call : 1; unsigned int audio_menu_call : 1; unsigned int subpic_menu_call : 1; unsigned int root_menu_call : 1; unsigned int title_menu_call : 1; unsigned int backward_scan : 1; unsigned int forward_scan : 1; /* 8 */ unsigned int next_pg_search : 1; /* 7 */ unsigned int prev_or_top_pg_search : 1; unsigned int time_or_chapter_search : 1; unsigned int go_up : 1; unsigned int stop : 1; unsigned int title_play : 1; unsigned int chapter_search_or_play : 1; unsigned int title_or_time_play : 1; /* 0 */ #else unsigned int video_pres_mode_change : 1; /* 24 */ unsigned int zero : 7; /* 25-31 */ unsigned int resume : 1; /* 16 */ unsigned int button_select_or_activate : 1; unsigned int still_off : 1; unsigned int pause_on : 1; unsigned int audio_stream_change : 1; unsigned int subpic_stream_change : 1; unsigned int angle_change : 1; unsigned int karaoke_audio_pres_mode_change : 1; /* 23 */ unsigned int forward_scan : 1; /* 8 */ unsigned int backward_scan : 1; unsigned int title_menu_call : 1; unsigned int root_menu_call : 1; unsigned int subpic_menu_call : 1; unsigned int audio_menu_call : 1; unsigned int angle_menu_call : 1; unsigned int chapter_menu_call : 1; /* 15 */ unsigned int title_or_time_play : 1; /* 0 */ unsigned int chapter_search_or_play : 1; unsigned int title_play : 1; unsigned int stop : 1; unsigned int go_up : 1; unsigned int time_or_chapter_search : 1; unsigned int prev_or_top_pg_search : 1; unsigned int next_pg_search : 1; /* 7 */ #endif } ATTRIBUTE_PACKED user_ops_t; /** * Program Chain Information. */ typedef struct { uint16_t zero_1; uint8_t nr_of_programs; uint8_t nr_of_cells; dvd_time_t playback_time; user_ops_t prohibited_ops; uint16_t audio_control[8]; /* New type? */ uint32_t subp_control[32]; /* New type? */ uint16_t next_pgc_nr; uint16_t prev_pgc_nr; uint16_t goup_pgc_nr; uint8_t still_time; uint8_t pg_playback_mode; uint32_t palette[16]; /* New type struct {zero_1, Y, Cr, Cb} ? */ uint16_t command_tbl_offset; uint16_t program_map_offset; uint16_t cell_playback_offset; uint16_t cell_position_offset; pgc_command_tbl_t *command_tbl; pgc_program_map_t *program_map; cell_playback_t *cell_playback; cell_position_t *cell_position; int ref_count; } ATTRIBUTE_PACKED pgc_t; #define PGC_SIZE 236U /** * Program Chain Information Search Pointer. */ typedef struct { uint8_t entry_id; #ifdef WORDS_BIGENDIAN unsigned int block_mode : 2; unsigned int block_type : 2; unsigned int unknown1 : 4; #else unsigned int unknown1 : 4; unsigned int block_type : 2; unsigned int block_mode : 2; #endif uint16_t ptl_id_mask; uint32_t pgc_start_byte; pgc_t *pgc; } ATTRIBUTE_PACKED pgci_srp_t; #define PGCI_SRP_SIZE 8U /** * Program Chain Information Table. */ typedef struct { uint16_t nr_of_pgci_srp; uint16_t zero_1; uint32_t last_byte; pgci_srp_t *pgci_srp; int ref_count; } ATTRIBUTE_PACKED pgcit_t; #define PGCIT_SIZE 8U /** * Menu PGCI Language Unit. */ typedef struct { uint16_t lang_code; uint8_t lang_extension; uint8_t exists; uint32_t lang_start_byte; pgcit_t *pgcit; } ATTRIBUTE_PACKED pgci_lu_t; #define PGCI_LU_SIZE 8U /** * Menu PGCI Unit Table. */ typedef struct { uint16_t nr_of_lus; uint16_t zero_1; uint32_t last_byte; pgci_lu_t *lu; } ATTRIBUTE_PACKED pgci_ut_t; #define PGCI_UT_SIZE 8U /** * Cell Address Information. */ typedef struct { uint16_t vob_id; uint8_t cell_id; uint8_t zero_1; uint32_t start_sector; uint32_t last_sector; } ATTRIBUTE_PACKED cell_adr_t; /** * Cell Address Table. */ typedef struct { uint16_t nr_of_vobs; /* VOBs */ uint16_t zero_1; uint32_t last_byte; cell_adr_t *cell_adr_table; /* No explicit size given. */ } ATTRIBUTE_PACKED c_adt_t; #define C_ADT_SIZE 8U /** * VOBU Address Map. */ typedef struct { uint32_t last_byte; uint32_t *vobu_start_sectors; } ATTRIBUTE_PACKED vobu_admap_t; #define VOBU_ADMAP_SIZE 4U /** * VMGI * * The following structures relate to the Video Manager. */ /** * Video Manager Information Management Table. */ typedef struct { char vmg_identifier[12]; uint32_t vmg_last_sector; uint8_t zero_1[12]; uint32_t vmgi_last_sector; uint8_t zero_2; uint8_t specification_version; uint32_t vmg_category; uint16_t vmg_nr_of_volumes; uint16_t vmg_this_volume_nr; uint8_t disc_side; uint8_t zero_3[19]; uint16_t vmg_nr_of_title_sets; /* Number of VTSs. */ char provider_identifier[32]; uint64_t vmg_pos_code; uint8_t zero_4[24]; uint32_t vmgi_last_byte; uint32_t first_play_pgc; uint8_t zero_5[56]; uint32_t vmgm_vobs; /* sector */ uint32_t tt_srpt; /* sector */ uint32_t vmgm_pgci_ut; /* sector */ uint32_t ptl_mait; /* sector */ uint32_t vts_atrt; /* sector */ uint32_t txtdt_mgi; /* sector */ uint32_t vmgm_c_adt; /* sector */ uint32_t vmgm_vobu_admap; /* sector */ uint8_t zero_6[32]; video_attr_t vmgm_video_attr; uint8_t zero_7; uint8_t nr_of_vmgm_audio_streams; /* should be 0 or 1 */ audio_attr_t vmgm_audio_attr; audio_attr_t zero_8[7]; uint8_t zero_9[17]; uint8_t nr_of_vmgm_subp_streams; /* should be 0 or 1 */ subp_attr_t vmgm_subp_attr; subp_attr_t zero_10[27]; /* XXX: how much 'padding' here? */ } ATTRIBUTE_PACKED vmgi_mat_t; typedef struct { #ifdef WORDS_BIGENDIAN unsigned int zero_1 : 1; unsigned int multi_or_random_pgc_title : 1; /* 0: one sequential pgc title */ unsigned int jlc_exists_in_cell_cmd : 1; unsigned int jlc_exists_in_prepost_cmd : 1; unsigned int jlc_exists_in_button_cmd : 1; unsigned int jlc_exists_in_tt_dom : 1; unsigned int chapter_search_or_play : 1; /* UOP 1 */ unsigned int title_or_time_play : 1; /* UOP 0 */ #else unsigned int title_or_time_play : 1; unsigned int chapter_search_or_play : 1; unsigned int jlc_exists_in_tt_dom : 1; unsigned int jlc_exists_in_button_cmd : 1; unsigned int jlc_exists_in_prepost_cmd : 1; unsigned int jlc_exists_in_cell_cmd : 1; unsigned int multi_or_random_pgc_title : 1; unsigned int zero_1 : 1; #endif } ATTRIBUTE_PACKED playback_type_t; /** * Title Information. */ typedef struct { playback_type_t pb_ty; uint8_t nr_of_angles; uint16_t nr_of_ptts; uint16_t parental_id; uint8_t title_set_nr; uint8_t vts_ttn; uint32_t title_set_sector; } ATTRIBUTE_PACKED title_info_t; /** * PartOfTitle Search Pointer Table. */ typedef struct { uint16_t nr_of_srpts; uint16_t zero_1; uint32_t last_byte; title_info_t *title; } ATTRIBUTE_PACKED tt_srpt_t; #define TT_SRPT_SIZE 8U /** * Parental Management Information Unit Table. * Level 1 (US: G), ..., 7 (US: NC-17), 8 */ #define PTL_MAIT_NUM_LEVEL 8 typedef uint16_t pf_level_t[PTL_MAIT_NUM_LEVEL]; /** * Parental Management Information Unit Table. */ typedef struct { uint16_t country_code; uint16_t zero_1; uint16_t pf_ptl_mai_start_byte; uint16_t zero_2; pf_level_t *pf_ptl_mai; /* table of (nr_of_vtss + 1), video_ts is first */ } ATTRIBUTE_PACKED ptl_mait_country_t; #define PTL_MAIT_COUNTRY_SIZE 8U /** * Parental Management Information Table. */ typedef struct { uint16_t nr_of_countries; uint16_t nr_of_vtss; uint32_t last_byte; ptl_mait_country_t *countries; } ATTRIBUTE_PACKED ptl_mait_t; #define PTL_MAIT_SIZE 8U /** * Video Title Set Attributes. */ typedef struct { uint32_t last_byte; uint32_t vts_cat; video_attr_t vtsm_vobs_attr; uint8_t zero_1; uint8_t nr_of_vtsm_audio_streams; /* should be 0 or 1 */ audio_attr_t vtsm_audio_attr; audio_attr_t zero_2[7]; uint8_t zero_3[16]; uint8_t zero_4; uint8_t nr_of_vtsm_subp_streams; /* should be 0 or 1 */ subp_attr_t vtsm_subp_attr; subp_attr_t zero_5[27]; uint8_t zero_6[2]; video_attr_t vtstt_vobs_video_attr; uint8_t zero_7; uint8_t nr_of_vtstt_audio_streams; audio_attr_t vtstt_audio_attr[8]; uint8_t zero_8[16]; uint8_t zero_9; uint8_t nr_of_vtstt_subp_streams; subp_attr_t vtstt_subp_attr[32]; } ATTRIBUTE_PACKED vts_attributes_t; #define VTS_ATTRIBUTES_SIZE 542U #define VTS_ATTRIBUTES_MIN_SIZE 356U /** * Video Title Set Attribute Table. */ typedef struct { uint16_t nr_of_vtss; uint16_t zero_1; uint32_t last_byte; vts_attributes_t *vts; uint32_t *vts_atrt_offsets; /* offsets table for each vts_attributes */ } ATTRIBUTE_PACKED vts_atrt_t; #define VTS_ATRT_SIZE 8U /** * Text Data. (Incomplete) */ typedef struct { uint32_t last_byte; /* offsets are relative here */ uint16_t offsets[100]; /* == nr_of_srpts + 1 (first is disc title) */ #if 0 uint16_t unknown; /* 0x48 ?? 0x48 words (16bit) info following */ uint16_t zero_1; uint8_t type_of_info; /* ?? 01 == disc, 02 == Title, 04 == Title part */ uint8_t unknown1; uint8_t unknown2; uint8_t unknown3; uint8_t unknown4; /* ?? allways 0x30 language?, text format? */ uint8_t unknown5; uint16_t offset; /* from first */ char text[12]; /* ended by 0x09 */ #endif } ATTRIBUTE_PACKED txtdt_t; /** * Text Data Language Unit. (Incomplete) */ typedef struct { uint16_t lang_code; uint16_t unknown; /* 0x0001, title 1? disc 1? side 1? */ uint32_t txtdt_start_byte; /* prt, rel start of vmg_txtdt_mgi */ txtdt_t *txtdt; } ATTRIBUTE_PACKED txtdt_lu_t; #define TXTDT_LU_SIZE 8U /** * Text Data Manager Information. (Incomplete) */ typedef struct { char disc_name[14]; /* how many bytes?? */ uint16_t nr_of_language_units; /* 32bit?? */ uint32_t last_byte; txtdt_lu_t *lu; } ATTRIBUTE_PACKED txtdt_mgi_t; #define TXTDT_MGI_SIZE 20U /** * VTS * * Structures relating to the Video Title Set (VTS). */ /** * Video Title Set Information Management Table. */ typedef struct { char vts_identifier[12]; uint32_t vts_last_sector; uint8_t zero_1[12]; uint32_t vtsi_last_sector; uint8_t zero_2; uint8_t specification_version; uint32_t vts_category; uint16_t zero_3; uint16_t zero_4; uint8_t zero_5; uint8_t zero_6[19]; uint16_t zero_7; uint8_t zero_8[32]; uint64_t zero_9; uint8_t zero_10[24]; uint32_t vtsi_last_byte; uint32_t zero_11; uint8_t zero_12[56]; uint32_t vtsm_vobs; /* sector */ uint32_t vtstt_vobs; /* sector */ uint32_t vts_ptt_srpt; /* sector */ uint32_t vts_pgcit; /* sector */ uint32_t vtsm_pgci_ut; /* sector */ uint32_t vts_tmapt; /* sector */ uint32_t vtsm_c_adt; /* sector */ uint32_t vtsm_vobu_admap; /* sector */ uint32_t vts_c_adt; /* sector */ uint32_t vts_vobu_admap; /* sector */ uint8_t zero_13[24]; video_attr_t vtsm_video_attr; uint8_t zero_14; uint8_t nr_of_vtsm_audio_streams; /* should be 0 or 1 */ audio_attr_t vtsm_audio_attr; audio_attr_t zero_15[7]; uint8_t zero_16[17]; uint8_t nr_of_vtsm_subp_streams; /* should be 0 or 1 */ subp_attr_t vtsm_subp_attr; subp_attr_t zero_17[27]; uint8_t zero_18[2]; video_attr_t vts_video_attr; uint8_t zero_19; uint8_t nr_of_vts_audio_streams; audio_attr_t vts_audio_attr[8]; uint8_t zero_20[17]; uint8_t nr_of_vts_subp_streams; subp_attr_t vts_subp_attr[32]; uint16_t zero_21; multichannel_ext_t vts_mu_audio_attr[8]; /* XXX: how much 'padding' here, if any? */ } ATTRIBUTE_PACKED vtsi_mat_t; /** * PartOfTitle Unit Information. */ typedef struct { uint16_t pgcn; uint16_t pgn; } ATTRIBUTE_PACKED ptt_info_t; /** * PartOfTitle Information. */ typedef struct { uint16_t nr_of_ptts; ptt_info_t *ptt; } ATTRIBUTE_PACKED ttu_t; /** * PartOfTitle Search Pointer Table. */ typedef struct { uint16_t nr_of_srpts; uint16_t zero_1; uint32_t last_byte; ttu_t *title; uint32_t *ttu_offset; /* offset table for each ttu */ } ATTRIBUTE_PACKED vts_ptt_srpt_t; #define VTS_PTT_SRPT_SIZE 8U /** * Time Map Entry. */ /* Should this be bit field at all or just the uint32_t? */ typedef uint32_t map_ent_t; /** * Time Map. */ typedef struct { uint8_t tmu; /* Time unit, in seconds */ uint8_t zero_1; uint16_t nr_of_entries; map_ent_t *map_ent; } ATTRIBUTE_PACKED vts_tmap_t; #define VTS_TMAP_SIZE 4U /** * Time Map Table. */ typedef struct { uint16_t nr_of_tmaps; uint16_t zero_1; uint32_t last_byte; vts_tmap_t *tmap; uint32_t *tmap_offset; /* offset table for each tmap */ } ATTRIBUTE_PACKED vts_tmapt_t; #define VTS_TMAPT_SIZE 8U #if PRAGMA_PACK #pragma pack() #endif /** * The following structure defines an IFO file. The structure is divided into * two parts, the VMGI, or Video Manager Information, which is read from the * VIDEO_TS.[IFO,BUP] file, and the VTSI, or Video Title Set Information, which * is read in from the VTS_XX_0.[IFO,BUP] files. */ typedef struct { dvd_file_t *file; /* VMGI */ vmgi_mat_t *vmgi_mat; tt_srpt_t *tt_srpt; pgc_t *first_play_pgc; ptl_mait_t *ptl_mait; vts_atrt_t *vts_atrt; txtdt_mgi_t *txtdt_mgi; /* Common */ pgci_ut_t *pgci_ut; c_adt_t *menu_c_adt; vobu_admap_t *menu_vobu_admap; /* VTSI */ vtsi_mat_t *vtsi_mat; vts_ptt_srpt_t *vts_ptt_srpt; pgcit_t *vts_pgcit; vts_tmapt_t *vts_tmapt; c_adt_t *vts_c_adt; vobu_admap_t *vts_vobu_admap; } ifo_handle_t; #endif /* LIBDVDREAD_IFO_TYPES_H */ k9copy/src/libdvdread-NOW/dvdread/ifo_read.h0000644000175000017550000002002212412304751021420 0ustar emulatoremulator/* * Copyright (C) 2000, 2001, 2002 Björn Englund , * Håkan Hjort * * This file is part of libdvdread. * * libdvdread is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdread is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdread; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef LIBDVDREAD_IFO_READ_H #define LIBDVDREAD_IFO_READ_H #include "ifo_types.h" #include "dvdread/dvd_reader.h" #ifdef __cplusplus extern "C" { #endif /** * handle = ifoOpen(dvd, title); * * Opens an IFO and reads in all the data for the IFO file corresponding to the * given title. If title 0 is given, the video manager IFO file is read. * Returns a handle to a completely parsed structure. */ ifo_handle_t *ifoOpen(dvd_reader_t *, int ); /** * handle = ifoOpenVMGI(dvd); * * Opens an IFO and reads in _only_ the vmgi_mat data. This call can be used * together with the calls below to read in each segment of the IFO file on * demand. */ ifo_handle_t *ifoOpenVMGI(dvd_reader_t *); /** * handle = ifoOpenVTSI(dvd, title); * * Opens an IFO and reads in _only_ the vtsi_mat data. This call can be used * together with the calls below to read in each segment of the IFO file on * demand. */ ifo_handle_t *ifoOpenVTSI(dvd_reader_t *, int); /** * ifoClose(ifofile); * Cleans up the IFO information. This will free all data allocated for the * substructures. */ void ifoClose(ifo_handle_t *); /** * The following functions are for reading only part of the VMGI/VTSI files. * Returns 1 if the data was successfully read and 0 on error. */ /** * okay = ifoRead_PLT_MAIT(ifofile); * * Read in the Parental Management Information table, filling the * ifofile->ptl_mait structure and its substructures. This data is only * located in the video manager information file. This fills the * ifofile->ptl_mait structure and all its substructures. */ int ifoRead_PTL_MAIT(ifo_handle_t *); /** * okay = ifoRead_VTS_ATRT(ifofile); * * Read in the attribute table for the main menu vob, filling the * ifofile->vts_atrt structure and its substructures. Only located in the * video manager information file. This fills in the ifofile->vts_atrt * structure and all its substructures. */ int ifoRead_VTS_ATRT(ifo_handle_t *); /** * okay = ifoRead_TT_SRPT(ifofile); * * Reads the title info for the main menu, filling the ifofile->tt_srpt * structure and its substructures. This data is only located in the video * manager information file. This structure is mandatory in the IFO file. */ int ifoRead_TT_SRPT(ifo_handle_t *); /** * okay = ifoRead_VTS_PTT_SRPT(ifofile); * * Reads in the part of title search pointer table, filling the * ifofile->vts_ptt_srpt structure and its substructures. This data is only * located in the video title set information file. This structure is * mandatory, and must be included in the VTSI file. */ int ifoRead_VTS_PTT_SRPT(ifo_handle_t *); /** * okay = ifoRead_FP_PGC(ifofile); * * Reads in the first play program chain data, filling the * ifofile->first_play_pgc structure. This data is only located in the video * manager information file (VMGI). This structure is optional. */ int ifoRead_FP_PGC(ifo_handle_t *); /** * okay = ifoRead_PGCIT(ifofile); * * Reads in the program chain information table for the video title set. Fills * in the ifofile->vts_pgcit structure and its substructures, which includes * the data for each program chain in the set. This data is only located in * the video title set information file. This structure is mandatory, and must * be included in the VTSI file. */ int ifoRead_PGCIT(ifo_handle_t *); /** * okay = ifoRead_PGCI_UT(ifofile); * * Reads in the menu PGCI unit table for the menu VOB. For the video manager, * this corresponds to the VIDEO_TS.VOB file, and for each title set, this * corresponds to the VTS_XX_0.VOB file. This data is located in both the * video manager and video title set information files. For VMGI files, this * fills the ifofile->vmgi_pgci_ut structure and all its substructures. For * VTSI files, this fills the ifofile->vtsm_pgci_ut structure. */ int ifoRead_PGCI_UT(ifo_handle_t *); /** * okay = ifoRead_VTS_TMAPT(ifofile); * * Reads in the VTS Time Map Table, this data is only located in the video * title set information file. This fills the ifofile->vts_tmapt structure * and all its substructures. When pressent enables VOBU level time-based * seeking for One_Sequential_PGC_Titles. */ int ifoRead_VTS_TMAPT(ifo_handle_t *); /** * okay = ifoRead_C_ADT(ifofile); * * Reads in the cell address table for the menu VOB. For the video manager, * this corresponds to the VIDEO_TS.VOB file, and for each title set, this * corresponds to the VTS_XX_0.VOB file. This data is located in both the * video manager and video title set information files. For VMGI files, this * fills the ifofile->vmgm_c_adt structure and all its substructures. For VTSI * files, this fills the ifofile->vtsm_c_adt structure. */ int ifoRead_C_ADT(ifo_handle_t *); /** * okay = ifoRead_TITLE_C_ADT(ifofile); * * Reads in the cell address table for the video title set corresponding to * this IFO file. This data is only located in the video title set information * file. This structure is mandatory, and must be included in the VTSI file. * This call fills the ifofile->vts_c_adt structure and its substructures. */ int ifoRead_TITLE_C_ADT(ifo_handle_t *); /** * okay = ifoRead_VOBU_ADMAP(ifofile); * * Reads in the VOBU address map for the menu VOB. For the video manager, this * corresponds to the VIDEO_TS.VOB file, and for each title set, this * corresponds to the VTS_XX_0.VOB file. This data is located in both the * video manager and video title set information files. For VMGI files, this * fills the ifofile->vmgm_vobu_admap structure and all its substructures. For * VTSI files, this fills the ifofile->vtsm_vobu_admap structure. */ int ifoRead_VOBU_ADMAP(ifo_handle_t *); /** * okay = ifoRead_TITLE_VOBU_ADMAP(ifofile); * * Reads in the VOBU address map for the associated video title set. This data * is only located in the video title set information file. This structure is * mandatory, and must be included in the VTSI file. Fills the * ifofile->vts_vobu_admap structure and its substructures. */ int ifoRead_TITLE_VOBU_ADMAP(ifo_handle_t *); /** * okay = ifoRead_TXTDT_MGI(ifofile); * * Reads in the text data strings for the DVD. Fills the ifofile->txtdt_mgi * structure and all its substructures. This data is only located in the video * manager information file. This structure is mandatory, and must be included * in the VMGI file. */ int ifoRead_TXTDT_MGI(ifo_handle_t *); /** * The following functions are used for freeing parsed sections of the * ifo_handle_t structure and the allocated substructures. The free calls * below are safe: they will not mind if you attempt to free part of an IFO * file which was not read in or which does not exist. */ void ifoFree_PTL_MAIT(ifo_handle_t *); void ifoFree_VTS_ATRT(ifo_handle_t *); void ifoFree_TT_SRPT(ifo_handle_t *); void ifoFree_VTS_PTT_SRPT(ifo_handle_t *); void ifoFree_FP_PGC(ifo_handle_t *); void ifoFree_PGCIT(ifo_handle_t *); void ifoFree_PGCI_UT(ifo_handle_t *); void ifoFree_VTS_TMAPT(ifo_handle_t *); void ifoFree_C_ADT(ifo_handle_t *); void ifoFree_TITLE_C_ADT(ifo_handle_t *); void ifoFree_VOBU_ADMAP(ifo_handle_t *); void ifoFree_TITLE_VOBU_ADMAP(ifo_handle_t *); void ifoFree_TXTDT_MGI(ifo_handle_t *); #ifdef __cplusplus }; #endif #endif /* LIBDVDREAD_IFO_READ_H */ k9copy/src/libdvdread-NOW/dvdread/dvd_reader.h0000644000175000017550000002567412412304751021771 0ustar emulatoremulator/* * Copyright (C) 2001, 2002 Billy Biggs , * Håkan Hjort , * Björn Englund * * This file is part of libdvdread. * * libdvdread is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdread is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdread; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef LIBDVDREAD_DVD_READER_H #define LIBDVDREAD_DVD_READER_H #ifdef _MSC_VER #include #include #include #endif #include #include /** * The DVD access interface. * * This file contains the functions that form the interface to to * reading files located on a DVD. */ /** * The current version. */ #define DVDREAD_VERSION 50000 /** * The length of one Logical Block of a DVD. */ #define DVD_VIDEO_LB_LEN 2048 /** * Maximum length of filenames allowed in UDF. */ #define MAX_UDF_FILE_NAME_LEN 2048 #ifdef __cplusplus extern "C" { #endif /** * Opaque type that is used as a handle for one instance of an opened DVD. */ typedef struct dvd_reader_s dvd_reader_t; /** * Opaque type for a file read handle, much like a normal fd or FILE *. */ typedef struct dvd_file_s dvd_file_t; /** * Public type that is used to provide statistics on a handle. */ typedef struct { off_t size; /**< Total size of file in bytes */ int nr_parts; /**< Number of file parts */ off_t parts_size[9]; /**< Size of each part in bytes */ } dvd_stat_t; /** * Opens a block device of a DVD-ROM file, or an image file, or a directory * name for a mounted DVD or HD copy of a DVD. * * If the given file is a block device, or is the mountpoint for a block * device, then that device is used for CSS authentication using libdvdcss. * If no device is available, then no CSS authentication is performed, * and we hope that the image is decrypted. * * If the path given is a directory, then the files in that directory may be * in any one of these formats: * * path/VIDEO_TS/VTS_01_1.VOB * path/video_ts/vts_01_1.vob * path/VTS_01_1.VOB * path/vts_01_1.vob * * @param path Specifies the the device, file or directory to be used. * @return If successful a a read handle is returned. Otherwise 0 is returned. * * dvd = DVDOpen(path); */ dvd_reader_t *DVDOpen( const char * ); /** * Closes and cleans up the DVD reader object. * * You must close all open files before calling this function. * * @param dvd A read handle that should be closed. * * DVDClose(dvd); */ void DVDClose( dvd_reader_t * ); /** * */ typedef enum { DVD_READ_INFO_FILE, /**< VIDEO_TS.IFO or VTS_XX_0.IFO (title) */ DVD_READ_INFO_BACKUP_FILE, /**< VIDEO_TS.BUP or VTS_XX_0.BUP (title) */ DVD_READ_MENU_VOBS, /**< VIDEO_TS.VOB or VTS_XX_0.VOB (title) */ DVD_READ_TITLE_VOBS /**< VTS_XX_[1-9].VOB (title). All files in the title set are opened and read as a single file. */ } dvd_read_domain_t; /** * Stats a file on the DVD given the title number and domain. * The information about the file is stored in a dvd_stat_t * which contains information about the size of the file and * the number of parts in case of a multipart file and the respective * sizes of the parts. * A multipart file is for instance VTS_02_1.VOB, VTS_02_2.VOB, VTS_02_3.VOB * The size of VTS_02_1.VOB will be stored in stat->parts_size[0], * VTS_02_2.VOB in stat->parts_size[1], ... * The total size (sum of all parts) is stored in stat->size and * stat->nr_parts will hold the number of parts. * Only DVD_READ_TITLE_VOBS (VTS_??_[1-9].VOB) can be multipart files. * * This function is only of use if you want to get the size of each file * in the filesystem. These sizes are not needed to use any other * functions in libdvdread. * * @param dvd A dvd read handle. * @param titlenum Which Video Title Set should be used, VIDEO_TS is 0. * @param domain Which domain. * @param stat Pointer to where the result is stored. * @return If successful 0, otherwise -1. * * int DVDFileStat(dvd, titlenum, domain, stat); */ int DVDFileStat(dvd_reader_t *, int, dvd_read_domain_t, dvd_stat_t *); /** * Opens a file on the DVD given the title number and domain. * * If the title number is 0, the video manager information is opened * (VIDEO_TS.[IFO,BUP,VOB]). Returns a file structure which may be * used for reads, or 0 if the file was not found. * * @param dvd A dvd read handle. * @param titlenum Which Video Title Set should be used, VIDEO_TS is 0. * @param domain Which domain. * @return If successful a a file read handle is returned, otherwise 0. * * dvd_file = DVDOpenFile(dvd, titlenum, domain); */ dvd_file_t *DVDOpenFile( dvd_reader_t *, int, dvd_read_domain_t ); /** * Closes a file and frees the associated structure. * * @param dvd_file The file read handle to be closed. * * DVDCloseFile(dvd_file); */ void DVDCloseFile( dvd_file_t * ); /** * Reads block_count number of blocks from the file at the given block offset. * Returns number of blocks read on success, -1 on error. This call is only * for reading VOB data, and should not be used when reading the IFO files. * When reading from an encrypted drive, blocks are decrypted using libdvdcss * where required. * * @param dvd_file A file read handle. * @param offset Block offset from the start of the file to start reading at. * @param block_count Number of block to read. * @param data Pointer to a buffer to write the data into. * @return Returns number of blocks read on success, -1 on error. * * blocks_read = DVDReadBlocks(dvd_file, offset, block_count, data); */ ssize_t DVDReadBlocks( dvd_file_t *, int, size_t, unsigned char * ); /** * Seek to the given position in the file. Returns the resulting position in * bytes from the beginning of the file. The seek position is only used for * byte reads from the file, the block read call always reads from the given * offset. * * @param dvd_file A file read handle. * @param seek_offset Byte offset from the start of the file to seek to. * @return The resulting position in bytes from the beginning of the file. * * offset_set = DVDFileSeek(dvd_file, seek_offset); */ int32_t DVDFileSeek( dvd_file_t *, int32_t ); /** * Reads the given number of bytes from the file. This call can only be used * on the information files, and may not be used for reading from a VOB. This * reads from and increments the currrent seek position for the file. * * @param dvd_file A file read handle. * @param data Pointer to a buffer to write the data into. * @param bytes Number of bytes to read. * @return Returns number of bytes read on success, -1 on error. * * bytes_read = DVDReadBytes(dvd_file, data, bytes); */ ssize_t DVDReadBytes( dvd_file_t *, void *, size_t ); /** * Returns the file size in blocks. * * @param dvd_file A file read handle. * @return The size of the file in blocks, -1 on error. * * blocks = DVDFileSize(dvd_file); */ ssize_t DVDFileSize( dvd_file_t * ); /** * Get a unique 128 bit disc ID. * This is the MD5 sum of VIDEO_TS.IFO and the VTS_0?_0.IFO files * in title order (those that exist). * If you need a 'text' representation of the id, print it as a * hexadecimal number, using lowercase letters, discid[0] first. * I.e. the same format as the command-line 'md5sum' program uses. * * @param dvd A read handle to get the disc ID from * @param discid The buffer to put the disc ID into. The buffer must * have room for 128 bits (16 chars). * @return 0 on success, -1 on error. */ int DVDDiscID( dvd_reader_t *, unsigned char * ); /** * Get the UDF VolumeIdentifier and VolumeSetIdentifier * from the PrimaryVolumeDescriptor. * * @param dvd A read handle to get the disc ID from * @param volid The buffer to put the VolumeIdentifier into. * The VolumeIdentifier is latin-1 encoded (8bit unicode) * null terminated and max 32 bytes (including '\0') * @param volid_size No more than volid_size bytes will be copied to volid. * If the VolumeIdentifier is truncated because of this * it will still be null terminated. * @param volsetid The buffer to put the VolumeSetIdentifier into. * The VolumeIdentifier is 128 bytes as * stored in the UDF PrimaryVolumeDescriptor. * Note that this is not a null terminated string. * @param volsetid_size At most volsetid_size bytes will be copied to volsetid. * @return 0 on success, -1 on error. */ int DVDUDFVolumeInfo( dvd_reader_t *, char *, unsigned int, unsigned char *, unsigned int ); int DVDFileSeekForce( dvd_file_t *, int offset, int force_size); /** * Get the ISO9660 VolumeIdentifier and VolumeSetIdentifier * * * Only use this function as fallback if DVDUDFVolumeInfo returns 0 * * * this will happen on a disc mastered only with a iso9660 filesystem * * * All video DVD discs have UDF filesystem * * * @param dvd A read handle to get the disc ID from * @param volid The buffer to put the VolumeIdentifier into. * The VolumeIdentifier is coded with '0-9','A-Z','_' * null terminated and max 33 bytes (including '\0') * @param volid_size No more than volid_size bytes will be copied to volid. * If the VolumeIdentifier is truncated because of this * it will still be null terminated. * @param volsetid The buffer to put the VolumeSetIdentifier into. * The VolumeIdentifier is 128 bytes as * stored in the ISO9660 PrimaryVolumeDescriptor. * Note that this is not a null terminated string. * @param volsetid_size At most volsetid_size bytes will be copied to volsetid. * @return 0 on success, -1 on error. */ int DVDISOVolumeInfo( dvd_reader_t *, char *, unsigned int, unsigned char *, unsigned int ); /** * Sets the level of caching that is done when reading from a device * * @param dvd A read handle to get the disc ID from * @param level The level of caching wanted. * -1 - returns the current setting. * 0 - UDF Cache turned off. * 1 - (default level) Pointers to IFO files and some data from * PrimaryVolumeDescriptor are cached. * * @return The level of caching. */ int DVDUDFCacheLevel( dvd_reader_t *, int ); #ifdef __cplusplus }; #endif #endif /* LIBDVDREAD_DVD_READER_H */ k9copy/src/libdvdread-NOW/bitreader.c0000644000175000017550000000757212412304751020212 0ustar emulatoremulator/* * Copyright (C) 2000, 2001, 2002, 2003 Håkan Hjort * * This file is part of libdvdread. * * libdvdread is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdread is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdread; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include #include #include "dvdread/bitreader.h" int dvdread_getbits_init(getbits_state_t *state, uint8_t *start) { if ((state == NULL) || (start == NULL)) return 0; state->start = start; state->bit_position = 0; state->byte_position = 0; state->byte = start[0]; return 1; } /* Non-optimized getbits. */ /* This can easily be optimized for particular platforms. */ uint32_t dvdread_getbits(getbits_state_t *state, uint32_t number_of_bits) { uint32_t result=0; uint8_t byte=0; if (number_of_bits > 32) { printf("Number of bits > 32 in getbits\n"); abort(); } if ((state->bit_position) > 0) { /* Last getbits left us in the middle of a byte. */ if (number_of_bits > (8-state->bit_position)) { /* this getbits will span 2 or more bytes. */ byte = state->byte; byte = byte >> (state->bit_position); result = byte; number_of_bits -= (8-state->bit_position); state->bit_position = 0; state->byte_position++; state->byte = state->start[state->byte_position]; } else { byte=state->byte; state->byte = state->byte << number_of_bits; byte = byte >> (8 - number_of_bits); result = byte; state->bit_position += number_of_bits; /* Here it is impossible for bit_position > 8 */ if (state->bit_position == 8) { state->bit_position = 0; state->byte_position++; state->byte = state->start[state->byte_position]; } number_of_bits = 0; } } if ((state->bit_position) == 0) { while (number_of_bits > 7) { result = (result << 8) + state->byte; state->byte_position++; state->byte = state->start[state->byte_position]; number_of_bits -= 8; } if (number_of_bits > 0) { /* number_of_bits < 8 */ byte = state->byte; state->byte = state->byte << number_of_bits; state->bit_position += number_of_bits; /* Here it is impossible for bit_position > 7 */ byte = byte >> (8 - number_of_bits); result = (result << number_of_bits) + byte; number_of_bits = 0; } } return result; } #if 0 /* TODO: optimized versions not yet used */ /* WARNING: This function can only be used on a byte boundary. No checks are made that we are in fact on a byte boundary. */ uint16_t dvdread_get16bits(getbits_state_t *state) { uint16_t result; state->byte_position++; result = (state->byte << 8) + state->start[state->byte_position++]; state->byte = state->start[state->byte_position]; return result; } /* WARNING: This function can only be used on a byte boundary. No checks are made that we are in fact on a byte boundary. */ uint32_t dvdread_get32bits(getbits_state_t *state) { uint32_t result; state->byte_position++; result = (state->byte << 8) + state->start[state->byte_position++]; result = (result << 8) + state->start[state->byte_position++]; result = (result << 8) + state->start[state->byte_position++]; state->byte = state->start[state->byte_position]; return result; } #endif k9copy/src/libdvdread-NOW/md5.c0000644000175000017550000003177712412304751016742 0ustar emulatoremulator/* md5.c - Functions to compute MD5 message digest of files or memory blocks according to the definition of MD5 in RFC 1321 from April 1992. Copyright (C) 1995, 1996, 2001 Free Software Foundation, Inc. NOTE: The canonical source of this file is maintained with the GNU C Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* Written by Ulrich Drepper , 1995. */ #include "config.h" #include #include #include #include "md5.h" /* #include "unlocked-io.h" */ #ifdef WORDS_BIGENDIAN # define SWAP(n) \ (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) #else # define SWAP(n) (n) #endif /* This array contains the bytes used to pad the buffer to the next 64-byte boundary. (RFC 1321, 3.1: Step 1) */ static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; /* Initialize structure containing state of computation. (RFC 1321, 3.3: Step 3) */ void md5_init_ctx (ctx) struct md5_ctx *ctx; { ctx->A = 0x67452301; ctx->B = 0xefcdab89; ctx->C = 0x98badcfe; ctx->D = 0x10325476; ctx->total[0] = ctx->total[1] = 0; ctx->buflen = 0; } /* Put result from CTX in first 16 bytes following RESBUF. The result must be in little endian byte order. IMPORTANT: On some systems it is required that RESBUF is correctly aligned for a 32 bits value. */ void * md5_read_ctx (ctx, resbuf) const struct md5_ctx *ctx; void *resbuf; { ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A); ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B); ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C); ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D); return resbuf; } /* Process the remaining bytes in the internal buffer and the usual prolog according to the standard and write the result to RESBUF. IMPORTANT: On some systems it is required that RESBUF is correctly aligned for a 32 bits value. */ void * md5_finish_ctx (ctx, resbuf) struct md5_ctx *ctx; void *resbuf; { /* Take yet unprocessed bytes into account. */ md5_uint32 bytes = ctx->buflen; size_t pad; /* Now count remaining bytes. */ ctx->total[0] += bytes; if (ctx->total[0] < bytes) ++ctx->total[1]; pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; memcpy (&ctx->buffer[bytes], fillbuf, pad); /* Put the 64-bit file length in *bits* at the end of the buffer. */ *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3); *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) | (ctx->total[0] >> 29)); /* Process last bytes. */ md5_process_block (ctx->buffer, bytes + pad + 8, ctx); return md5_read_ctx (ctx, resbuf); } /* Compute MD5 message digest for bytes read from STREAM. The resulting message digest number will be written into the 16 bytes beginning at RESBLOCK. */ int md5_stream (stream, resblock) FILE *stream; void *resblock; { /* Important: BLOCKSIZE must be a multiple of 64. */ #define BLOCKSIZE 4096 struct md5_ctx ctx; char buffer[BLOCKSIZE + 72]; size_t sum; /* Initialize the computation context. */ md5_init_ctx (&ctx); /* Iterate over full file contents. */ while (1) { /* We read the file in blocks of BLOCKSIZE bytes. One call of the computation function processes the whole buffer so that with the next round of the loop another block can be read. */ size_t n; sum = 0; /* Read block. Take care for partial reads. */ do { n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream); sum += n; } while (sum < BLOCKSIZE && n != 0); if (n == 0 && ferror (stream)) return 1; /* If end of file is reached, end the loop. */ if (n == 0) break; /* Process buffer with BLOCKSIZE bytes. Note that BLOCKSIZE % 64 == 0 */ md5_process_block (buffer, BLOCKSIZE, &ctx); } /* Add the last bytes if necessary. */ if (sum > 0) md5_process_bytes (buffer, sum, &ctx); /* Construct result in desired memory. */ md5_finish_ctx (&ctx, resblock); return 0; } /* Compute MD5 message digest for LEN bytes beginning at BUFFER. The result is always in little endian byte order, so that a byte-wise output yields to the wanted ASCII representation of the message digest. */ void * md5_buffer (buffer, len, resblock) const char *buffer; size_t len; void *resblock; { struct md5_ctx ctx; /* Initialize the computation context. */ md5_init_ctx (&ctx); /* Process whole buffer but last len % 64 bytes. */ md5_process_bytes (buffer, len, &ctx); /* Put result in desired memory area. */ return md5_finish_ctx (&ctx, resblock); } void md5_process_bytes (buffer, len, ctx) const void *buffer; size_t len; struct md5_ctx *ctx; { /* When we already have some bits in our internal buffer concatenate both inputs first. */ if (ctx->buflen != 0) { size_t left_over = ctx->buflen; size_t add = 128 - left_over > len ? len : 128 - left_over; memcpy (&ctx->buffer[left_over], buffer, add); ctx->buflen += add; if (left_over + add > 64) { md5_process_block (ctx->buffer, (left_over + add) & ~63, ctx); /* The regions in the following copy operation cannot overlap. */ memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63], (left_over + add) & 63); ctx->buflen = (left_over + add) & 63; } buffer = (const char *) buffer + add; len -= add; } /* Process available complete blocks. */ if (len > 64) { md5_process_block (buffer, len & ~63, ctx); buffer = (const char *) buffer + (len & ~63); len &= 63; } /* Move remaining bytes in internal buffer. */ if (len > 0) { memcpy (ctx->buffer, buffer, len); ctx->buflen = len; } } /* These are the four functions used in the four steps of the MD5 algorithm and defined in the RFC 1321. The first function is a little bit optimized (as found in Colin Plumbs public domain implementation). */ /* #define FF(b, c, d) ((b & c) | (~b & d)) */ #define FF(b, c, d) (d ^ (b & (c ^ d))) #define FG(b, c, d) FF (d, b, c) #define FH(b, c, d) (b ^ c ^ d) #define FI(b, c, d) (c ^ (b | ~d)) /* Process LEN bytes of BUFFER, accumulating context into CTX. It is assumed that LEN % 64 == 0. */ void md5_process_block (buffer, len, ctx) const void *buffer; size_t len; struct md5_ctx *ctx; { md5_uint32 correct_words[16]; const md5_uint32 *words = buffer; size_t nwords = len / sizeof (md5_uint32); const md5_uint32 *endp = words + nwords; md5_uint32 A = ctx->A; md5_uint32 B = ctx->B; md5_uint32 C = ctx->C; md5_uint32 D = ctx->D; /* First increment the byte count. RFC 1321 specifies the possible length of the file up to 2^64 bits. Here we only compute the number of bytes. Do a double word increment. */ ctx->total[0] += len; if (ctx->total[0] < len) ++ctx->total[1]; /* Process all bytes in the buffer with 64 bytes in each round of the loop. */ while (words < endp) { md5_uint32 *cwp = correct_words; md5_uint32 A_save = A; md5_uint32 B_save = B; md5_uint32 C_save = C; md5_uint32 D_save = D; /* First round: using the given function, the context and a constant the next context is computed. Because the algorithms processing unit is a 32-bit word and it is determined to work on words in little endian byte order we perhaps have to change the byte order before the computation. To reduce the work for the next steps we store the swapped words in the array CORRECT_WORDS. */ #define OP(a, b, c, d, s, T) \ do \ { \ a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \ ++words; \ a = rol (a, s); \ a += b; \ } \ while (0) /* Before we start, one word to the strange constants. They are defined in RFC 1321 as T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64, or perl -e 'foreach(1..64){printf "0x%08x\n", int (4294967296 * abs (sin $_))}' */ /* Round 1. */ OP (A, B, C, D, 7, 0xd76aa478); OP (D, A, B, C, 12, 0xe8c7b756); OP (C, D, A, B, 17, 0x242070db); OP (B, C, D, A, 22, 0xc1bdceee); OP (A, B, C, D, 7, 0xf57c0faf); OP (D, A, B, C, 12, 0x4787c62a); OP (C, D, A, B, 17, 0xa8304613); OP (B, C, D, A, 22, 0xfd469501); OP (A, B, C, D, 7, 0x698098d8); OP (D, A, B, C, 12, 0x8b44f7af); OP (C, D, A, B, 17, 0xffff5bb1); OP (B, C, D, A, 22, 0x895cd7be); OP (A, B, C, D, 7, 0x6b901122); OP (D, A, B, C, 12, 0xfd987193); OP (C, D, A, B, 17, 0xa679438e); OP (B, C, D, A, 22, 0x49b40821); /* For the second to fourth round we have the possibly swapped words in CORRECT_WORDS. Redefine the macro to take an additional first argument specifying the function to use. */ #undef OP #define OP(f, a, b, c, d, k, s, T) \ do \ { \ a += f (b, c, d) + correct_words[k] + T; \ a = rol (a, s); \ a += b; \ } \ while (0) /* Round 2. */ OP (FG, A, B, C, D, 1, 5, 0xf61e2562); OP (FG, D, A, B, C, 6, 9, 0xc040b340); OP (FG, C, D, A, B, 11, 14, 0x265e5a51); OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); OP (FG, A, B, C, D, 5, 5, 0xd62f105d); OP (FG, D, A, B, C, 10, 9, 0x02441453); OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); OP (FG, D, A, B, C, 14, 9, 0xc33707d6); OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); OP (FG, B, C, D, A, 8, 20, 0x455a14ed); OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); OP (FG, C, D, A, B, 7, 14, 0x676f02d9); OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); /* Round 3. */ OP (FH, A, B, C, D, 5, 4, 0xfffa3942); OP (FH, D, A, B, C, 8, 11, 0x8771f681); OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); OP (FH, B, C, D, A, 14, 23, 0xfde5380c); OP (FH, A, B, C, D, 1, 4, 0xa4beea44); OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); OP (FH, B, C, D, A, 6, 23, 0x04881d05); OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); /* Round 4. */ OP (FI, A, B, C, D, 0, 6, 0xf4292244); OP (FI, D, A, B, C, 7, 10, 0x432aff97); OP (FI, C, D, A, B, 14, 15, 0xab9423a7); OP (FI, B, C, D, A, 5, 21, 0xfc93a039); OP (FI, A, B, C, D, 12, 6, 0x655b59c3); OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); OP (FI, C, D, A, B, 10, 15, 0xffeff47d); OP (FI, B, C, D, A, 1, 21, 0x85845dd1); OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); OP (FI, C, D, A, B, 6, 15, 0xa3014314); OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); OP (FI, A, B, C, D, 4, 6, 0xf7537e82); OP (FI, D, A, B, C, 11, 10, 0xbd3af235); OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); OP (FI, B, C, D, A, 9, 21, 0xeb86d391); /* Add the starting values of the context. */ A += A_save; B += B_save; C += C_save; D += D_save; } /* Put checksum in context given as argument. */ ctx->A = A; ctx->B = B; ctx->C = C; ctx->D = D; } k9copy/src/libdvdread-NOW/dvdread_internal.h0000644000175000017550000000504612412304751021555 0ustar emulatoremulator/* * This file is part of libdvdread. * * libdvdread is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdread is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdread; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef LIBDVDREAD_DVDREAD_INTERNAL_H #define LIBDVDREAD_DVDREAD_INTERNAL_H #include #include #ifdef _WIN32 # include #endif /* _WIN32 */ #include "dvdread/dvd_reader.h" #define CHECK_VALUE(arg) \ if(!(arg)) { \ fprintf(stderr, "\n*** libdvdread: CHECK_VALUE failed in %s:%i ***" \ "\n*** for %s ***\n\n", \ __FILE__, __LINE__, # arg ); \ } enum TagIdentifier { /* ECMA 167 3/7.2.1 */ PrimaryVolumeDescriptor = 1, AnchorVolumeDescriptorPointer = 2, VolumeDescriptorPointer = 3, ImplementationUseVolumeDescriptor = 4, PartitionDescriptor = 5, LogicalVolumeDescriptor = 6, UnallocatedSpaceDescriptor = 7, TerminatingDescriptor = 8, LogicalVolumeIntegrityDescriptor = 9, /* ECMA 167 4/7.2.1 */ FileSetDescriptor = 256, FileIdentifierDescriptor = 257, AllocationExtentDescriptor = 258, IndirectEntry = 259, TerminalEntry = 260, FileEntry = 261, ExtendedAttributeHeaderDescriptor = 262, UnallocatedSpaceEntry = 263, SpaceBitmapDescriptor = 264, PartitionIntegrityEntry = 265, ExtendedFileEntry = 266, }; int InternalUDFReadBlocksRaw(const dvd_reader_t *device, uint32_t lb_number, size_t block_count, unsigned char *data, int encrypted); void *GetUDFCacheHandle(dvd_reader_t *device); void SetUDFCacheHandle(dvd_reader_t *device, void *cache); void FreeUDFCache(void *cache); #endif /* LIBDVDREAD_DVDREAD_INTERNAL_H */ k9copy/src/libdvdread-NOW/bswap.h0000644000175000017550000000710212412304751017357 0ustar emulatoremulator/* * Copyright (C) 2000, 2001 Billy Biggs , * Håkan Hjort * * This file is part of libdvdread. * * libdvdread is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdread is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdread; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef LIBDVDREAD_BSWAP_H #define LIBDVDREAD_BSWAP_H #include #if defined(WORDS_BIGENDIAN) /* All bigendian systems are fine, just ignore the swaps. */ #define B2N_16(x) (void)(x) #define B2N_32(x) (void)(x) #define B2N_64(x) (void)(x) #else /* For __FreeBSD_version */ #if defined(HAVE_SYS_PARAM_H) #include #endif #if defined(__linux__) || defined(__GLIBC__) #include #define B2N_16(x) x = bswap_16(x) #define B2N_32(x) x = bswap_32(x) #define B2N_64(x) x = bswap_64(x) #elif defined(__APPLE__) #include #define B2N_16(x) x = OSSwapBigToHostInt16(x) #define B2N_32(x) x = OSSwapBigToHostInt32(x) #define B2N_64(x) x = OSSwapBigToHostInt64(x) #elif defined(__NetBSD__) #include #define B2N_16(x) BE16TOH(x) #define B2N_32(x) BE32TOH(x) #define B2N_64(x) BE64TOH(x) #elif defined(__OpenBSD__) #include #define B2N_16(x) x = swap16(x) #define B2N_32(x) x = swap32(x) #define B2N_64(x) x = swap64(x) #elif defined(__FreeBSD__) && __FreeBSD_version >= 470000 #include #define B2N_16(x) x = be16toh(x) #define B2N_32(x) x = be32toh(x) #define B2N_64(x) x = be64toh(x) #elif defined(__QNXNTO__) #include #define B2N_16(x) x = ENDIAN_RET16(x) #define B2N_32(x) x = ENDIAN_RET32(x) #define B2N_64(x) x = ENDIAN_RET64(x) /* This is a slow but portable implementation, it has multiple evaluation * problems so beware. * Old FreeBSD's and Solaris don't have or any other such * functionality! */ #elif defined(__FreeBSD__) || defined(__sun) || defined(__bsdi__) || defined(WIN32) || defined(__CYGWIN__) || defined(__BEOS__) || defined(__OS2__) #define B2N_16(x) \ x = ((((x) & 0xff00) >> 8) | \ (((x) & 0x00ff) << 8)) #define B2N_32(x) \ x = ((((x) & 0xff000000) >> 24) | \ (((x) & 0x00ff0000) >> 8) | \ (((x) & 0x0000ff00) << 8) | \ (((x) & 0x000000ff) << 24)) #define B2N_64(x) \ x = ((((x) & 0xff00000000000000ULL) >> 56) | \ (((x) & 0x00ff000000000000ULL) >> 40) | \ (((x) & 0x0000ff0000000000ULL) >> 24) | \ (((x) & 0x000000ff00000000ULL) >> 8) | \ (((x) & 0x00000000ff000000ULL) << 8) | \ (((x) & 0x0000000000ff0000ULL) << 24) | \ (((x) & 0x000000000000ff00ULL) << 40) | \ (((x) & 0x00000000000000ffULL) << 56)) #else /* If there isn't a header provided with your system with this functionality * add the relevant || define( ) to the portable implementation above. */ #error "You need to add endian swap macros for you're system" #endif #endif /* WORDS_BIGENDIAN */ #endif /* LIBDVDREAD_BSWAP_H */ k9copy/src/libdvdread-NOW/nav_read.c0000644000175000017550000002520612412304751020022 0ustar emulatoremulator/* * Copyright (C) 2000, 2001, 2002, 2003 Håkan Hjort * * This file is part of libdvdread. * * libdvdread is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdread is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdread; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include #include #include "bswap.h" #include "dvdread/nav_types.h" #include "dvdread/nav_read.h" #include "dvdread_internal.h" #include "dvdread/bitreader.h" #define getbits_init dvdread_getbits_init #define getbits dvdread_getbits void navRead_PCI(pci_t *pci, unsigned char *buffer) { int32_t i, j; getbits_state_t state; if (!getbits_init(&state, buffer)) abort(); /* Passed NULL pointers */ /* pci pci_gi */ pci->pci_gi.nv_pck_lbn = getbits(&state, 32 ); pci->pci_gi.vobu_cat = getbits(&state, 16 ); pci->pci_gi.zero1 = getbits(&state, 16 ); pci->pci_gi.vobu_uop_ctl.zero = getbits(&state, 7 ); pci->pci_gi.vobu_uop_ctl.video_pres_mode_change = getbits(&state, 1 ); pci->pci_gi.vobu_uop_ctl.karaoke_audio_pres_mode_change = getbits(&state, 1 ); pci->pci_gi.vobu_uop_ctl.angle_change = getbits(&state, 1 ); pci->pci_gi.vobu_uop_ctl.subpic_stream_change = getbits(&state, 1 ); pci->pci_gi.vobu_uop_ctl.audio_stream_change = getbits(&state, 1 ); pci->pci_gi.vobu_uop_ctl.pause_on = getbits(&state, 1 ); pci->pci_gi.vobu_uop_ctl.still_off = getbits(&state, 1 ); pci->pci_gi.vobu_uop_ctl.button_select_or_activate = getbits(&state, 1 ); pci->pci_gi.vobu_uop_ctl.resume = getbits(&state, 1 ); pci->pci_gi.vobu_uop_ctl.chapter_menu_call = getbits(&state, 1 ); pci->pci_gi.vobu_uop_ctl.angle_menu_call = getbits(&state, 1 ); pci->pci_gi.vobu_uop_ctl.audio_menu_call = getbits(&state, 1 ); pci->pci_gi.vobu_uop_ctl.subpic_menu_call = getbits(&state, 1 ); pci->pci_gi.vobu_uop_ctl.root_menu_call = getbits(&state, 1 ); pci->pci_gi.vobu_uop_ctl.title_menu_call = getbits(&state, 1 ); pci->pci_gi.vobu_uop_ctl.backward_scan = getbits(&state, 1 ); pci->pci_gi.vobu_uop_ctl.forward_scan = getbits(&state, 1 ); pci->pci_gi.vobu_uop_ctl.next_pg_search = getbits(&state, 1 ); pci->pci_gi.vobu_uop_ctl.prev_or_top_pg_search = getbits(&state, 1 ); pci->pci_gi.vobu_uop_ctl.time_or_chapter_search = getbits(&state, 1 ); pci->pci_gi.vobu_uop_ctl.go_up = getbits(&state, 1 ); pci->pci_gi.vobu_uop_ctl.stop = getbits(&state, 1 ); pci->pci_gi.vobu_uop_ctl.title_play = getbits(&state, 1 ); pci->pci_gi.vobu_uop_ctl.chapter_search_or_play = getbits(&state, 1 ); pci->pci_gi.vobu_uop_ctl.title_or_time_play = getbits(&state, 1 ); pci->pci_gi.vobu_s_ptm = getbits(&state, 32 ); pci->pci_gi.vobu_e_ptm = getbits(&state, 32 ); pci->pci_gi.vobu_se_e_ptm = getbits(&state, 32 ); pci->pci_gi.e_eltm.hour = getbits(&state, 8 ); pci->pci_gi.e_eltm.minute = getbits(&state, 8 ); pci->pci_gi.e_eltm.second = getbits(&state, 8 ); pci->pci_gi.e_eltm.frame_u = getbits(&state, 8 ); for(i = 0; i < 32; i++) pci->pci_gi.vobu_isrc[i] = getbits(&state, 8 ); /* pci nsml_agli */ for(i = 0; i < 9; i++) pci->nsml_agli.nsml_agl_dsta[i] = getbits(&state, 32 ); /* pci hli hli_gi */ pci->hli.hl_gi.hli_ss = getbits(&state, 16 ); pci->hli.hl_gi.hli_s_ptm = getbits(&state, 32 ); pci->hli.hl_gi.hli_e_ptm = getbits(&state, 32 ); pci->hli.hl_gi.btn_se_e_ptm = getbits(&state, 32 ); pci->hli.hl_gi.zero1 = getbits(&state, 2 ); pci->hli.hl_gi.btngr_ns = getbits(&state, 2 ); pci->hli.hl_gi.zero2 = getbits(&state, 1 ); pci->hli.hl_gi.btngr1_dsp_ty = getbits(&state, 3 ); pci->hli.hl_gi.zero3 = getbits(&state, 1 ); pci->hli.hl_gi.btngr2_dsp_ty = getbits(&state, 3 ); pci->hli.hl_gi.zero4 = getbits(&state, 1 ); pci->hli.hl_gi.btngr3_dsp_ty = getbits(&state, 3 ); pci->hli.hl_gi.btn_ofn = getbits(&state, 8 ); pci->hli.hl_gi.btn_ns = getbits(&state, 8 ); pci->hli.hl_gi.nsl_btn_ns = getbits(&state, 8 ); pci->hli.hl_gi.zero5 = getbits(&state, 8 ); pci->hli.hl_gi.fosl_btnn = getbits(&state, 8 ); pci->hli.hl_gi.foac_btnn = getbits(&state, 8 ); /* pci hli btn_colit */ for(i = 0; i < 3; i++) for(j = 0; j < 2; j++) pci->hli.btn_colit.btn_coli[i][j] = getbits(&state, 32 ); /* NOTE: I've had to change the structure from the disk layout to get * the packing to work with Sun's Forte C compiler. */ /* pci hli btni */ for(i = 0; i < 36; i++) { pci->hli.btnit[i].btn_coln = getbits(&state, 2 ); pci->hli.btnit[i].x_start = getbits(&state, 10 ); pci->hli.btnit[i].zero1 = getbits(&state, 2 ); pci->hli.btnit[i].x_end = getbits(&state, 10 ); pci->hli.btnit[i].auto_action_mode = getbits(&state, 2 ); pci->hli.btnit[i].y_start = getbits(&state, 10 ); pci->hli.btnit[i].zero2 = getbits(&state, 2 ); pci->hli.btnit[i].y_end = getbits(&state, 10 ); pci->hli.btnit[i].zero3 = getbits(&state, 2 ); pci->hli.btnit[i].up = getbits(&state, 6 ); pci->hli.btnit[i].zero4 = getbits(&state, 2 ); pci->hli.btnit[i].down = getbits(&state, 6 ); pci->hli.btnit[i].zero5 = getbits(&state, 2 ); pci->hli.btnit[i].left = getbits(&state, 6 ); pci->hli.btnit[i].zero6 = getbits(&state, 2 ); pci->hli.btnit[i].right = getbits(&state, 6 ); /* pci vm_cmd */ for(j = 0; j < 8; j++) pci->hli.btnit[i].cmd.bytes[j] = getbits(&state, 8 ); } #ifndef NDEBUG /* Asserts */ /* pci pci gi */ CHECK_VALUE(pci->pci_gi.zero1 == 0); /* pci hli hli_gi */ CHECK_VALUE(pci->hli.hl_gi.zero1 == 0); CHECK_VALUE(pci->hli.hl_gi.zero2 == 0); CHECK_VALUE(pci->hli.hl_gi.zero3 == 0); CHECK_VALUE(pci->hli.hl_gi.zero4 == 0); CHECK_VALUE(pci->hli.hl_gi.zero5 == 0); /* Are there buttons defined here? */ if((pci->hli.hl_gi.hli_ss & 0x03) != 0) { CHECK_VALUE(pci->hli.hl_gi.btn_ns != 0); CHECK_VALUE(pci->hli.hl_gi.btngr_ns != 0); } else { CHECK_VALUE((pci->hli.hl_gi.btn_ns != 0 && pci->hli.hl_gi.btngr_ns != 0) || (pci->hli.hl_gi.btn_ns == 0 && pci->hli.hl_gi.btngr_ns == 0)); } /* pci hli btnit */ for(i = 0; i < pci->hli.hl_gi.btngr_ns; i++) { for(j = 0; j < (36 / pci->hli.hl_gi.btngr_ns); j++) { int n = (36 / pci->hli.hl_gi.btngr_ns) * i + j; CHECK_VALUE(pci->hli.btnit[n].zero1 == 0); CHECK_VALUE(pci->hli.btnit[n].zero2 == 0); CHECK_VALUE(pci->hli.btnit[n].zero3 == 0); CHECK_VALUE(pci->hli.btnit[n].zero4 == 0); CHECK_VALUE(pci->hli.btnit[n].zero5 == 0); CHECK_VALUE(pci->hli.btnit[n].zero6 == 0); if (j < pci->hli.hl_gi.btn_ns) { CHECK_VALUE(pci->hli.btnit[n].x_start <= pci->hli.btnit[n].x_end); CHECK_VALUE(pci->hli.btnit[n].y_start <= pci->hli.btnit[n].y_end); CHECK_VALUE(pci->hli.btnit[n].up <= pci->hli.hl_gi.btn_ns); CHECK_VALUE(pci->hli.btnit[n].down <= pci->hli.hl_gi.btn_ns); CHECK_VALUE(pci->hli.btnit[n].left <= pci->hli.hl_gi.btn_ns); CHECK_VALUE(pci->hli.btnit[n].right <= pci->hli.hl_gi.btn_ns); /* vmcmd_verify(pci->hli.btnit[n].cmd); */ } else { int k; CHECK_VALUE(pci->hli.btnit[n].btn_coln == 0); CHECK_VALUE(pci->hli.btnit[n].auto_action_mode == 0); CHECK_VALUE(pci->hli.btnit[n].x_start == 0); CHECK_VALUE(pci->hli.btnit[n].y_start == 0); CHECK_VALUE(pci->hli.btnit[n].x_end == 0); CHECK_VALUE(pci->hli.btnit[n].y_end == 0); CHECK_VALUE(pci->hli.btnit[n].up == 0); CHECK_VALUE(pci->hli.btnit[n].down == 0); CHECK_VALUE(pci->hli.btnit[n].left == 0); CHECK_VALUE(pci->hli.btnit[n].right == 0); for (k = 0; k < 8; k++) CHECK_VALUE(pci->hli.btnit[n].cmd.bytes[k] == 0); /* CHECK_ZERO? */ } } } #endif /* !NDEBUG */ } void navRead_DSI(dsi_t *dsi, unsigned char *buffer) { int i; getbits_state_t state; if (!getbits_init(&state, buffer)) abort(); /* Passed NULL pointers */ /* dsi dsi gi */ dsi->dsi_gi.nv_pck_scr = getbits(&state, 32 ); dsi->dsi_gi.nv_pck_lbn = getbits(&state, 32 ); dsi->dsi_gi.vobu_ea = getbits(&state, 32 ); dsi->dsi_gi.vobu_1stref_ea = getbits(&state, 32 ); dsi->dsi_gi.vobu_2ndref_ea = getbits(&state, 32 ); dsi->dsi_gi.vobu_3rdref_ea = getbits(&state, 32 ); dsi->dsi_gi.vobu_vob_idn = getbits(&state, 16 ); dsi->dsi_gi.zero1 = getbits(&state, 8 ); dsi->dsi_gi.vobu_c_idn = getbits(&state, 8 ); dsi->dsi_gi.c_eltm.hour = getbits(&state, 8 ); dsi->dsi_gi.c_eltm.minute = getbits(&state, 8 ); dsi->dsi_gi.c_eltm.second = getbits(&state, 8 ); dsi->dsi_gi.c_eltm.frame_u = getbits(&state, 8 ); /* dsi sml pbi */ dsi->sml_pbi.category = getbits(&state, 16 ); dsi->sml_pbi.ilvu_ea = getbits(&state, 32 ); dsi->sml_pbi.ilvu_sa = getbits(&state, 32 ); dsi->sml_pbi.size = getbits(&state, 16 ); dsi->sml_pbi.vob_v_s_s_ptm = getbits(&state, 32 ); dsi->sml_pbi.vob_v_e_e_ptm = getbits(&state, 32 ); for(i = 0; i < 8; i++) { dsi->sml_pbi.vob_a[i].stp_ptm1 = getbits(&state, 32 ); dsi->sml_pbi.vob_a[i].stp_ptm2 = getbits(&state, 32 ); dsi->sml_pbi.vob_a[i].gap_len1 = getbits(&state, 32 ); dsi->sml_pbi.vob_a[i].gap_len2 = getbits(&state, 32 ); } /* dsi sml agli */ for(i = 0; i < 9; i++) { dsi->sml_agli.data[ i ].address = getbits(&state, 32 ); dsi->sml_agli.data[ i ].size = getbits(&state, 16 ); } /* dsi vobu sri */ dsi->vobu_sri.next_video = getbits(&state, 32 ); for(i = 0; i < 19; i++) dsi->vobu_sri.fwda[i] = getbits(&state, 32 ); dsi->vobu_sri.next_vobu = getbits(&state, 32 ); dsi->vobu_sri.prev_vobu = getbits(&state, 32 ); for(i = 0; i < 19; i++) dsi->vobu_sri.bwda[i] = getbits(&state, 32 ); dsi->vobu_sri.prev_video = getbits(&state, 32 ); /* dsi synci */ for(i = 0; i < 8; i++) dsi->synci.a_synca[i] = getbits(&state, 16 ); for(i = 0; i < 32; i++) dsi->synci.sp_synca[i] = getbits(&state, 32 ); /* Asserts */ /* dsi dsi gi */ CHECK_VALUE(dsi->dsi_gi.zero1 == 0); } k9copy/src/libdvdread-NOW/md5.h0000644000175000017550000001254112412304751016733 0ustar emulatoremulator/* md5.h - Declaration of functions and data types used for MD5 sum computing library functions. Copyright (C) 1995, 1996, 1999 Free Software Foundation, Inc. NOTE: The canonical source of this file is maintained with the GNU C Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef LIBDVDREAD_MD5_H #define LIBDVDREAD_MD5_H #include #if defined HAVE_LIMITS_H || defined _LIBC # include #endif /* The following contortions are an attempt to use the C preprocessor to determine an unsigned integral type that is 32 bits wide. An alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but doing that would require that the configure script compile and *run* the resulting executable. Locally running cross-compiled executables is usually not possible. */ #ifdef _LIBC # include typedef u_int32_t md5_uint32; #else # if defined __STDC__ && __STDC__ # define UINT_MAX_32_BITS 4294967295U # else # define UINT_MAX_32_BITS 0xFFFFFFFF # endif /* If UINT_MAX isn't defined, assume it's a 32-bit type. This should be valid for all systems GNU cares about because that doesn't include 16-bit systems, and only modern systems (that certainly have ) have 64+-bit integral types. */ # ifndef UINT_MAX # define UINT_MAX UINT_MAX_32_BITS # endif # if UINT_MAX == UINT_MAX_32_BITS typedef unsigned int md5_uint32; # else # if USHRT_MAX == UINT_MAX_32_BITS typedef unsigned short md5_uint32; # else # if ULONG_MAX == UINT_MAX_32_BITS typedef unsigned long md5_uint32; # else /* The following line is intended to evoke an error. Using #error is not portable enough. */ "Cannot determine unsigned 32-bit data type." # endif # endif # endif #endif #undef __P #if defined (__STDC__) && __STDC__ #define __P(x) x #else #define __P(x) () #endif /* Structure to save state of computation between the single steps. */ struct md5_ctx { md5_uint32 A; md5_uint32 B; md5_uint32 C; md5_uint32 D; md5_uint32 total[2]; md5_uint32 buflen; char buffer[128]; }; /* * The following three functions are build up the low level used in * the functions `md5_stream' and `md5_buffer'. */ /* Initialize structure containing state of computation. (RFC 1321, 3.3: Step 3) */ extern void md5_init_ctx __P ((struct md5_ctx *ctx)); /* Starting with the result of former calls of this function (or the initialization function update the context for the next LEN bytes starting at BUFFER. It is necessary that LEN is a multiple of 64!!! */ extern void md5_process_block __P ((const void *buffer, size_t len, struct md5_ctx *ctx)); /* Starting with the result of former calls of this function (or the initialization function update the context for the next LEN bytes starting at BUFFER. It is NOT required that LEN is a multiple of 64. */ extern void md5_process_bytes __P ((const void *buffer, size_t len, struct md5_ctx *ctx)); /* Process the remaining bytes in the buffer and put result from CTX in first 16 bytes following RESBUF. The result is always in little endian byte order, so that a byte-wise output yields to the wanted ASCII representation of the message digest. IMPORTANT: On some systems it is required that RESBUF be correctly aligned for a 32 bits value. */ extern void *md5_finish_ctx __P ((struct md5_ctx *ctx, void *resbuf)); /* Put result from CTX in first 16 bytes following RESBUF. The result is always in little endian byte order, so that a byte-wise output yields to the wanted ASCII representation of the message digest. IMPORTANT: On some systems it is required that RESBUF is correctly aligned for a 32 bits value. */ extern void *md5_read_ctx __P ((const struct md5_ctx *ctx, void *resbuf)); /* Compute MD5 message digest for bytes read from STREAM. The resulting message digest number will be written into the 16 bytes beginning at RESBLOCK. */ extern int md5_stream __P ((FILE *stream, void *resblock)); /* Compute MD5 message digest for LEN bytes beginning at BUFFER. The result is always in little endian byte order, so that a byte-wise output yields to the wanted ASCII representation of the message digest. */ extern void *md5_buffer __P ((const char *buffer, size_t len, void *resblock)); /* The following is from gnupg-1.0.2's cipher/bithelp.h. */ /* Rotate a 32 bit integer by n bytes */ #if defined __GNUC__ && defined __i386__ static inline md5_uint32 rol(md5_uint32 x, int n) { __asm__("roll %%cl,%0" :"=r" (x) :"0" (x),"c" (n)); return x; } #else # define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) ) #endif #endif /* LIBDVDREAD_MD5_H */ k9copy/src/libdvdread-NOW/nav_print.c0000644000175000017550000001665612412304751020254 0ustar emulatoremulator/* * Copyright (C) 2000, 2001, 2002, 2003 Håkan Hjort * * Much of the contents in this file is based on VOBDUMP. * * VOBDUMP: a program for examining DVD .VOB filse * * Copyright 1998, 1999 Eric Smith * * VOBDUMP is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. Note that I am not * granting permission to redistribute or modify VOBDUMP under the * terms of any later version of the General Public License. * * This program is distributed in the hope that it will be useful (or * at least amusing), but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include "dvdread/nav_types.h" #include "dvdread/nav_print.h" #include "dvdread/ifo_print.h" static void navPrint_PCI_GI(pci_gi_t *pci_gi) { int i; printf("pci_gi:\n"); printf("nv_pck_lbn 0x%08x\n", pci_gi->nv_pck_lbn); printf("vobu_cat 0x%04x\n", pci_gi->vobu_cat); printf("vobu_s_ptm 0x%08x\n", pci_gi->vobu_s_ptm); printf("vobu_e_ptm 0x%08x\n", pci_gi->vobu_e_ptm); printf("vobu_se_e_ptm 0x%08x\n", pci_gi->vobu_se_e_ptm); printf("e_eltm "); dvdread_print_time(&pci_gi->e_eltm); printf("\n"); printf("vobu_isrc \""); for(i = 0; i < 32; i++) { char c = pci_gi->vobu_isrc[i]; if((c >= ' ') && (c <= '~')) printf("%c", c); else printf("."); } printf("\"\n"); } static void navPrint_NSML_AGLI(nsml_agli_t *nsml_agli) { int i, j = 0; for(i = 0; i < 9; i++) j |= nsml_agli->nsml_agl_dsta[i]; if(j == 0) return; printf("nsml_agli:\n"); for(i = 0; i < 9; i++) if(nsml_agli->nsml_agl_dsta[i]) printf("nsml_agl_c%d_dsta 0x%08x\n", i + 1, nsml_agli->nsml_agl_dsta[i]); } static void navPrint_HL_GI(hl_gi_t *hl_gi, int *btngr_ns, int *btn_ns) { if((hl_gi->hli_ss & 0x03) == 0) return; printf("hl_gi:\n"); printf("hli_ss 0x%01x\n", hl_gi->hli_ss & 0x03); printf("hli_s_ptm 0x%08x\n", hl_gi->hli_s_ptm); printf("hli_e_ptm 0x%08x\n", hl_gi->hli_e_ptm); printf("btn_se_e_ptm 0x%08x\n", hl_gi->btn_se_e_ptm); *btngr_ns = hl_gi->btngr_ns; printf("btngr_ns %d\n", hl_gi->btngr_ns); printf("btngr%d_dsp_ty 0x%02x\n", 1, hl_gi->btngr1_dsp_ty); printf("btngr%d_dsp_ty 0x%02x\n", 2, hl_gi->btngr2_dsp_ty); printf("btngr%d_dsp_ty 0x%02x\n", 3, hl_gi->btngr3_dsp_ty); printf("btn_ofn %d\n", hl_gi->btn_ofn); *btn_ns = hl_gi->btn_ns; printf("btn_ns %d\n", hl_gi->btn_ns); printf("nsl_btn_ns %d\n", hl_gi->nsl_btn_ns); printf("fosl_btnn %d\n", hl_gi->fosl_btnn); printf("foac_btnn %d\n", hl_gi->foac_btnn); } static void navPrint_BTN_COLIT(btn_colit_t *btn_colit) { int i, j; j = 0; for(i = 0; i < 6; i++) j |= btn_colit->btn_coli[i/2][i&1]; if(j == 0) return; printf("btn_colit:\n"); for(i = 0; i < 3; i++) for(j = 0; j < 2; j++) printf("btn_cqoli %d %s_coli: %08x\n", i, (j == 0) ? "sl" : "ac", btn_colit->btn_coli[i][j]); } static void navPrint_BTNIT(btni_t *btni_table, int btngr_ns, int btn_ns) { int i, j; printf("btnit:\n"); printf("btngr_ns: %i\n", btngr_ns); printf("btn_ns: %i\n", btn_ns); if(btngr_ns == 0) return; for(i = 0; i < btngr_ns; i++) { for(j = 0; j < (36 / btngr_ns); j++) { if(j < btn_ns) { btni_t *btni = &btni_table[(36 / btngr_ns) * i + j]; printf("group %d btni %d: ", i+1, j+1); printf("btn_coln %d, auto_action_mode %d\n", btni->btn_coln, btni->auto_action_mode); printf("coords (%d, %d) .. (%d, %d)\n", btni->x_start, btni->y_start, btni->x_end, btni->y_end); printf("up %d, ", btni->up); printf("down %d, ", btni->down); printf("left %d, ", btni->left); printf("right %d\n", btni->right); /* ifoPrint_COMMAND(&btni->cmd); */ printf("\n"); } } } } static void navPrint_HLI(hli_t *hli) { int btngr_ns = 0, btn_ns = 0; printf("hli:\n"); navPrint_HL_GI(&hli->hl_gi, & btngr_ns, & btn_ns); navPrint_BTN_COLIT(&hli->btn_colit); navPrint_BTNIT(hli->btnit, btngr_ns, btn_ns); } void navPrint_PCI(pci_t *pci) { printf("pci packet:\n"); navPrint_PCI_GI(&pci->pci_gi); navPrint_NSML_AGLI(&pci->nsml_agli); navPrint_HLI(&pci->hli); } static void navPrint_DSI_GI(dsi_gi_t *dsi_gi) { printf("dsi_gi:\n"); printf("nv_pck_scr 0x%08x\n", dsi_gi->nv_pck_scr); printf("nv_pck_lbn 0x%08x\n", dsi_gi->nv_pck_lbn ); printf("vobu_ea 0x%08x\n", dsi_gi->vobu_ea); printf("vobu_1stref_ea 0x%08x\n", dsi_gi->vobu_1stref_ea); printf("vobu_2ndref_ea 0x%08x\n", dsi_gi->vobu_2ndref_ea); printf("vobu_3rdref_ea 0x%08x\n", dsi_gi->vobu_3rdref_ea); printf("vobu_vob_idn 0x%04x\n", dsi_gi->vobu_vob_idn); printf("vobu_c_idn 0x%02x\n", dsi_gi->vobu_c_idn); printf("c_eltm "); dvdread_print_time(&dsi_gi->c_eltm); printf("\n"); } static void navPrint_SML_PBI(sml_pbi_t *sml_pbi) { printf("sml_pbi:\n"); printf("category 0x%04x\n", sml_pbi->category); if(sml_pbi->category & 0x8000) printf("VOBU is in preunit\n"); if(sml_pbi->category & 0x4000) printf("VOBU is in ILVU\n"); if(sml_pbi->category & 0x2000) printf("VOBU at the beginning of ILVU\n"); if(sml_pbi->category & 0x1000) printf("VOBU at end of PREU of ILVU\n"); printf("ilvu_ea 0x%08x\n", sml_pbi->ilvu_ea); printf("nxt_ilvu_sa 0x%08x\n", sml_pbi->ilvu_sa); printf("nxt_ilvu_size 0x%04x\n", sml_pbi->size); printf("vob_v_s_s_ptm 0x%08x\n", sml_pbi->vob_v_s_s_ptm); printf("vob_v_e_e_ptm 0x%08x\n", sml_pbi->vob_v_e_e_ptm); /* $$$ more code needed here */ } static void navPrint_SML_AGLI(sml_agli_t *sml_agli) { int i; printf("sml_agli:\n"); for(i = 0; i < 9; i++) { printf("agl_c%d address: 0x%08x size 0x%04x\n", i, sml_agli->data[i].address, sml_agli->data[i].size); } } static void navPrint_VOBU_SRI(vobu_sri_t *vobu_sri) { int i; int stime[19] = { 240, 120, 60, 20, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; printf("vobu_sri:\n"); printf("Next VOBU with Video %08x\n", vobu_sri->next_video); for(i = 0; i < 19; i++) { printf("%3.1f %08x ", stime[i]/2.0, vobu_sri->fwda[i]); } printf("\n"); printf("Next VOBU %08x\n", vobu_sri->next_vobu); printf("--\n"); printf("Prev VOBU %08x\n", vobu_sri->prev_vobu); for(i = 0; i < 19; i++) { printf("%3.1f %08x ", stime[18 - i]/2.0, vobu_sri->bwda[i]); } printf("\n"); printf("Prev VOBU with Video %08x\n", vobu_sri->prev_video); } static void navPrint_SYNCI(synci_t *synci) { int i; printf("synci:\n"); /* $$$ more code needed here */ for(i = 0; i < 8; i++) printf("%04x ", synci->a_synca[i]); for(i = 0; i < 32; i++) printf("%08x ", synci->sp_synca[i]); } void navPrint_DSI(dsi_t *dsi) { printf("dsi packet:\n"); navPrint_DSI_GI(&dsi->dsi_gi); navPrint_SML_PBI(&dsi->sml_pbi); navPrint_SML_AGLI(&dsi->sml_agli); navPrint_VOBU_SRI(&dsi->vobu_sri); navPrint_SYNCI(&dsi->synci); } k9copy/src/libdvdread-NOW/ifo_print.c0000644000175000017550000010441412412304751020233 0ustar emulatoremulator/* * This file is part of libdvdread. * * libdvdread is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdread is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdread; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include #include #include #include #include #include "dvdread/ifo_types.h" #include "dvdread/ifo_read.h" #include "dvdread/ifo_print.h" /* Put this in some other file / package? It's used in nav_print too. */ static void ifo_print_time(dvd_time_t *dtime) { const char *rate; assert((dtime->hour>>4) < 0xa && (dtime->hour&0xf) < 0xa); assert((dtime->minute>>4) < 0x7 && (dtime->minute&0xf) < 0xa); assert((dtime->second>>4) < 0x7 && (dtime->second&0xf) < 0xa); assert((dtime->frame_u&0xf) < 0xa); printf("%02x:%02x:%02x.%02x", dtime->hour, dtime->minute, dtime->second, dtime->frame_u & 0x3f); switch((dtime->frame_u & 0xc0) >> 6) { case 1: rate = "25.00"; break; case 3: rate = "29.97"; break; default: if(dtime->hour == 0 && dtime->minute == 0 && dtime->second == 0 && dtime->frame_u == 0) rate = "no"; else rate = "(please send a bug report)"; break; } printf(" @ %s fps", rate); } void dvdread_print_time(dvd_time_t *dtime) { ifo_print_time(dtime); } /* Put this in some other file / package? It's used in nav_print too. Possibly also by the vm / navigator. */ static void ifo_print_cmd(int row, vm_cmd_t *command) { int i; printf("(%03d) ", row + 1); for(i=0;i<8;i++) printf("%02x ", command->bytes[i]); printf("| "); #if 0 //disabled call of dvdnav function vm_print_mnemonic(command); #endif printf("\n"); } static void ifo_print_video_attributes(video_attr_t *attr) { /* The following test is shorter but not correct ISO C, memcmp(attr,my_friendly_zeros, sizeof(video_attr_t)) */ if(attr->mpeg_version == 0 && attr->video_format == 0 && attr->display_aspect_ratio == 0 && attr->permitted_df == 0 && attr->line21_cc_1 == 0 && attr->line21_cc_2 == 0 && attr->unknown1 == 0 && attr->letterboxed == 0 && attr->film_mode == 0) { printf("-- Unspecified --"); return; } switch(attr->mpeg_version) { case 0: printf("mpeg1, "); break; case 1: printf("mpeg2, "); break; default: printf("(please send a bug report), "); } switch(attr->video_format) { case 0: printf("ntsc, "); break; case 1: printf("pal, "); break; default: printf("(please send a bug report), "); } switch(attr->display_aspect_ratio) { case 0: printf("4:3, "); break; case 3: printf("16:9, "); break; default: printf("(please send a bug report), "); } // Wide is always allowed..!!! switch(attr->permitted_df) { case 0: printf("pan&scan+letterboxed, "); break; case 1: printf("only pan&scan, "); //?? break; case 2: printf("only letterboxed, "); break; case 3: printf("not specified, "); break; default: printf("(please send a bug report), "); } if(attr->line21_cc_1 || attr->line21_cc_2) { printf("NTSC CC "); if(attr->line21_cc_1) printf("1, "); if(attr->line21_cc_2) printf("2, "); } { int height = 480; if(attr->video_format != 0) height = 576; switch(attr->picture_size) { case 0: printf("720x%d, ", height); break; case 1: printf("704x%d, ", height); break; case 2: printf("352x%d, ", height); break; case 3: printf("352x%d, ", height/2); break; default: printf("(please send a bug report), "); } } if(attr->letterboxed) { printf("source letterboxed, "); } if(attr->film_mode) { printf("film, "); } else { printf("video, "); //camera } printf("Unknown1: %x", attr->unknown1); } static void ifo_print_audio_attributes(audio_attr_t *attr) { if(attr->audio_format == 0 && attr->multichannel_extension == 0 && attr->lang_type == 0 && attr->application_mode == 0 && attr->quantization == 0 && attr->sample_frequency == 0 && attr->unknown1 == 0 && attr->channels == 0 && attr->lang_extension == 0 && attr->unknown3 == 0) { printf("-- Unspecified --"); return; } switch(attr->audio_format) { case 0: printf("ac3 "); if(attr->quantization != 3) printf("(please send a bug report) ac3 quant/drc not 3 (%d)", attr->quantization); break; case 1: printf("(please send a bug report) "); break; case 2: printf("mpeg1 "); case 3: printf("mpeg2ext "); switch(attr->quantization) { case 0: printf("no drc "); break; case 1: printf("drc "); break; default: printf("(please send a bug report) mpeg reserved quant/drc (%d)", attr->quantization); } break; case 4: printf("lpcm "); switch(attr->quantization) { case 0: printf("16bit "); break; case 1: printf("20bit "); break; case 2: printf("24bit "); break; case 3: printf("(please send a bug report) lpcm reserved quant/drc (%d)", attr->quantization); break; } break; case 5: printf("(please send a bug report) "); break; case 6: printf("dts "); if(attr->quantization != 3) printf("(please send a bug report) dts quant/drc not 3 (%d)", attr->quantization); break; default: printf("(please send a bug report) "); } if(attr->multichannel_extension) printf("multichannel_extension "); switch(attr->lang_type) { case 0: // not specified if(attr->lang_code != 0 && attr->lang_code != 0xffff) printf("Lang_code 0x%x, please send a bug report!", attr->lang_code); break; case 1: printf("%c%c ", attr->lang_code>>8, attr->lang_code & 0xff); break; default: printf("(please send a bug report) "); } switch(attr->application_mode) { case 0: // not specified break; case 1: printf("karaoke mode "); break; case 2: printf("surround sound mode "); break; default: printf("(please send a bug report) "); } switch(attr->quantization) { case 0: printf("16bit "); break; case 1: printf("20bit "); break; case 2: printf("24bit "); break; case 3: printf("drc "); break; default: printf("(please send a bug report) "); } switch(attr->sample_frequency) { case 0: printf("48kHz "); break; case 1: printf("??kHz "); break; default: printf("sample_frequency %i (please send a bug report) ", attr->sample_frequency); } printf("%dCh ", attr->channels + 1); switch(attr->lang_extension) { case 0: printf("Not specified "); break; case 1: // Normal audio printf("Normal Caption "); break; case 2: // visually impaired printf("Audio for visually impaired "); break; case 3: // Directors 1 printf("Director's comments 1 "); break; case 4: // Directors 2 printf("Director's comments 2 "); break; //case 4: // Music score ? default: printf("(please send a bug report) "); } printf("Unknown1: %d ", attr->unknown1); printf("Unknown3: %d ", attr->unknown3); } static void ifo_print_subp_attributes(subp_attr_t *attr) { if(attr->type == 0 && attr->zero1 == 0 && attr->zero2 == 0 && attr->lang_code == 0 && attr->lang_extension== 0) { printf("-- Unspecified --"); return; } printf("type %02x ", attr->type); if(isalpha((int)(attr->lang_code >> 8)) && isalpha((int)(attr->lang_code & 0xff))) { printf("%c%c ", attr->lang_code >> 8, attr->lang_code & 0xff); } else { printf("%02x%02x ", 0xff & (unsigned)(attr->lang_code >> 8), 0xff & (unsigned)(attr->lang_code & 0xff)); } printf("%d ", attr->zero1); printf("%d ", attr->zero2); switch(attr->lang_extension) { case 0: printf("Not specified "); break; case 1: printf("Caption with normal size character "); break; case 2: printf("Caption with bigger size character "); break; case 3: printf("Caption for children "); break; case 4: printf("reserved "); break; case 5: printf("Closed Caption with normal size character "); break; case 6: printf("Closed Caption with bigger size character "); break; case 7: printf("Closed Caption for children "); break; case 8: printf("reserved "); break; case 9: printf("Forced Caption"); break; case 10: printf("reserved "); break; case 11: printf("reserved "); break; case 12: printf("reserved "); break; case 13: printf("Director's comments with normal size character "); break; case 14: printf("Director's comments with bigger size character "); break; case 15: printf("Director's comments for children "); break; default: printf("(please send a bug report) "); } } static void ifoPrint_USER_OPS(user_ops_t *user_ops) { uint32_t uops; unsigned char *ptr = (unsigned char *)user_ops; uops = (*ptr++ << 24); uops |= (*ptr++ << 16); uops |= (*ptr++ << 8); uops |= (*ptr++); if(uops == 0) { printf("None\n"); } else if(uops == 0x01ffffff) { printf("All\n"); } else { if(user_ops->title_or_time_play) printf("Title or Time Play, "); if(user_ops->chapter_search_or_play) printf("Chapter Search or Play, "); if(user_ops->title_play) printf("Title Play, "); if(user_ops->stop) printf("Stop, "); if(user_ops->go_up) printf("Go Up, "); if(user_ops->time_or_chapter_search) printf("Time or Chapter Search, "); if(user_ops->prev_or_top_pg_search) printf("Prev or Top PG Search, "); if(user_ops->next_pg_search) printf("Next PG Search, "); if(user_ops->forward_scan) printf("Forward Scan, "); if(user_ops->backward_scan) printf("Backward Scan, "); if(user_ops->title_menu_call) printf("Title Menu Call, "); if(user_ops->root_menu_call) printf("Root Menu Call, "); if(user_ops->subpic_menu_call) printf("SubPic Menu Call, "); if(user_ops->audio_menu_call) printf("Audio Menu Call, "); if(user_ops->angle_menu_call) printf("Angle Menu Call, "); if(user_ops->chapter_menu_call) printf("Chapter Menu Call, "); if(user_ops->resume) printf("Resume, "); if(user_ops->button_select_or_activate) printf("Button Select or Activate, "); if(user_ops->still_off) printf("Still Off, "); if(user_ops->pause_on) printf("Pause On, "); if(user_ops->audio_stream_change) printf("Audio Stream Change, "); if(user_ops->subpic_stream_change) printf("SubPic Stream Change, "); if(user_ops->angle_change) printf("Angle Change, "); if(user_ops->karaoke_audio_pres_mode_change) printf("Karaoke Audio Pres Mode Change, "); if(user_ops->video_pres_mode_change) printf("Video Pres Mode Change, "); printf("\n"); } } static void ifoPrint_VMGI_MAT(vmgi_mat_t *vmgi_mat) { printf("VMG Identifier: %.12s\n", vmgi_mat->vmg_identifier); printf("Last Sector of VMG: %08x\n", vmgi_mat->vmg_last_sector); printf("Last Sector of VMGI: %08x\n", vmgi_mat->vmgi_last_sector); printf("Specification version number: %01x.%01x\n", vmgi_mat->specification_version >> 4, vmgi_mat->specification_version & 0xf); /* Byte 2 of 'VMG Category' (00xx0000) is the Region Code */ printf("VMG Category: %08x (Region Code=%02x)\n", vmgi_mat->vmg_category, ((vmgi_mat->vmg_category >> 16) & 0xff) ^0xff); printf("VMG Number of Volumes: %i\n", vmgi_mat->vmg_nr_of_volumes); printf("VMG This Volume: %i\n", vmgi_mat->vmg_this_volume_nr); printf("Disc side %i\n", vmgi_mat->disc_side); printf("VMG Number of Title Sets %i\n", vmgi_mat->vmg_nr_of_title_sets); printf("Provider ID: %.32s\n", vmgi_mat->provider_identifier); printf("VMG POS Code: %08x", (uint32_t)(vmgi_mat->vmg_pos_code >> 32)); printf("%08x\n", (uint32_t)vmgi_mat->vmg_pos_code); printf("End byte of VMGI_MAT: %08x\n", vmgi_mat->vmgi_last_byte); printf("Start byte of First Play PGC (FP PGC): %08x\n", vmgi_mat->first_play_pgc); printf("Start sector of VMGM_VOBS: %08x\n", vmgi_mat->vmgm_vobs); printf("Start sector of TT_SRPT: %08x\n", vmgi_mat->tt_srpt); printf("Start sector of VMGM_PGCI_UT: %08x\n", vmgi_mat->vmgm_pgci_ut); printf("Start sector of PTL_MAIT: %08x\n", vmgi_mat->ptl_mait); printf("Start sector of VTS_ATRT: %08x\n", vmgi_mat->vts_atrt); printf("Start sector of TXTDT_MG: %08x\n", vmgi_mat->txtdt_mgi); printf("Start sector of VMGM_C_ADT: %08x\n", vmgi_mat->vmgm_c_adt); printf("Start sector of VMGM_VOBU_ADMAP: %08x\n", vmgi_mat->vmgm_vobu_admap); printf("Video attributes of VMGM_VOBS: "); ifo_print_video_attributes(&vmgi_mat->vmgm_video_attr); printf("\n"); printf("VMGM Number of Audio attributes: %i\n", vmgi_mat->nr_of_vmgm_audio_streams); if(vmgi_mat->nr_of_vmgm_audio_streams > 0) { printf("\tstream %i status: ", 1); ifo_print_audio_attributes(&vmgi_mat->vmgm_audio_attr); printf("\n"); } printf("VMGM Number of Sub-picture attributes: %i\n", vmgi_mat->nr_of_vmgm_subp_streams); if(vmgi_mat->nr_of_vmgm_subp_streams > 0) { printf("\tstream %2i status: ", 1); ifo_print_subp_attributes(&vmgi_mat->vmgm_subp_attr); printf("\n"); } } static void ifoPrint_VTSI_MAT(vtsi_mat_t *vtsi_mat) { int i; printf("VTS Identifier: %.12s\n", vtsi_mat->vts_identifier); printf("Last Sector of VTS: %08x\n", vtsi_mat->vts_last_sector); printf("Last Sector of VTSI: %08x\n", vtsi_mat->vtsi_last_sector); printf("Specification version number: %01x.%01x\n", vtsi_mat->specification_version>>4, vtsi_mat->specification_version&0xf); printf("VTS Category: %08x\n", vtsi_mat->vts_category); printf("End byte of VTSI_MAT: %08x\n", vtsi_mat->vtsi_last_byte); printf("Start sector of VTSM_VOBS: %08x\n", vtsi_mat->vtsm_vobs); printf("Start sector of VTSTT_VOBS: %08x\n", vtsi_mat->vtstt_vobs); printf("Start sector of VTS_PTT_SRPT: %08x\n", vtsi_mat->vts_ptt_srpt); printf("Start sector of VTS_PGCIT: %08x\n", vtsi_mat->vts_pgcit); printf("Start sector of VTSM_PGCI_UT: %08x\n", vtsi_mat->vtsm_pgci_ut); printf("Start sector of VTS_TMAPT: %08x\n", vtsi_mat->vts_tmapt); printf("Start sector of VTSM_C_ADT: %08x\n", vtsi_mat->vtsm_c_adt); printf("Start sector of VTSM_VOBU_ADMAP: %08x\n",vtsi_mat->vtsm_vobu_admap); printf("Start sector of VTS_C_ADT: %08x\n", vtsi_mat->vts_c_adt); printf("Start sector of VTS_VOBU_ADMAP: %08x\n", vtsi_mat->vts_vobu_admap); printf("Video attributes of VTSM_VOBS: "); ifo_print_video_attributes(&vtsi_mat->vtsm_video_attr); printf("\n"); printf("VTSM Number of Audio attributes: %i\n", vtsi_mat->nr_of_vtsm_audio_streams); if(vtsi_mat->nr_of_vtsm_audio_streams > 0) { printf("\tstream %i status: ", 1); ifo_print_audio_attributes(&vtsi_mat->vtsm_audio_attr); printf("\n"); } printf("VTSM Number of Sub-picture attributes: %i\n", vtsi_mat->nr_of_vtsm_subp_streams); if(vtsi_mat->nr_of_vtsm_subp_streams > 0) { printf("\tstream %2i status: ", 1); ifo_print_subp_attributes(&vtsi_mat->vtsm_subp_attr); printf("\n"); } printf("Video attributes of VTS_VOBS: "); ifo_print_video_attributes(&vtsi_mat->vts_video_attr); printf("\n"); printf("VTS Number of Audio attributes: %i\n", vtsi_mat->nr_of_vts_audio_streams); for(i = 0; i < vtsi_mat->nr_of_vts_audio_streams; i++) { printf("\tstream %i status: ", i); ifo_print_audio_attributes(&vtsi_mat->vts_audio_attr[i]); printf("\n"); } printf("VTS Number of Subpicture attributes: %i\n", vtsi_mat->nr_of_vts_subp_streams); for(i = 0; i < vtsi_mat->nr_of_vts_subp_streams; i++) { printf("\tstream %2i status: ", i); ifo_print_subp_attributes(&vtsi_mat->vts_subp_attr[i]); printf("\n"); } } static void ifoPrint_PGC_COMMAND_TBL(pgc_command_tbl_t *cmd_tbl) { int i; if(cmd_tbl == NULL) { printf("No Command table present\n"); return; } printf("Number of Pre commands: %i\n", cmd_tbl->nr_of_pre); for(i = 0; i < cmd_tbl->nr_of_pre; i++) { ifo_print_cmd(i, &cmd_tbl->pre_cmds[i]); } printf("Number of Post commands: %i\n", cmd_tbl->nr_of_post); for(i = 0; i < cmd_tbl->nr_of_post; i++) { ifo_print_cmd(i, &cmd_tbl->post_cmds[i]); } printf("Number of Cell commands: %i\n", cmd_tbl->nr_of_cell); for(i = 0; i < cmd_tbl->nr_of_cell; i++) { ifo_print_cmd(i, &cmd_tbl->cell_cmds[i]); } } static void ifoPrint_PGC_PROGRAM_MAP(pgc_program_map_t *program_map, int nr) { int i; if(program_map == NULL) { printf("No Program map present\n"); return; } for(i = 0; i < nr; i++) { printf("Program %3i Entry Cell: %3i\n", i + 1, program_map[i]); } } static void ifoPrint_CELL_PLAYBACK(cell_playback_t *cell_playback, int nr) { int i; if(cell_playback == NULL) { printf("No Cell Playback info present\n"); return; } for(i=0;inr_of_programs); printf("Number of Cells: %i\n", pgc->nr_of_cells); /* Check that time is 0:0:0:0 also if nr_of_programs==0 */ printf("Playback time: "); dvdread_print_time(&pgc->playback_time); printf("\n"); /* If no programs/no time then does this mean anything? */ printf("Prohibited user operations: "); ifoPrint_USER_OPS(&pgc->prohibited_ops); for(i = 0; i < 8; i++) { if(pgc->audio_control[i] & 0x8000) { /* The 'is present' bit */ printf("Audio stream %i control: %04x\n", i, pgc->audio_control[i]); } } for(i = 0; i < 32; i++) { if(pgc->subp_control[i] & 0x80000000) { /* The 'is present' bit */ printf("Subpicture stream %2i control: %08x: 4:3=%d, Wide=%d, Letterbox=%d, Pan-Scan=%d\n", i, pgc->subp_control[i], (pgc->subp_control[i] >>24) & 0x1f, (pgc->subp_control[i] >>16) & 0x1f, (pgc->subp_control[i] >>8) & 0x1f, (pgc->subp_control[i] ) & 0x1f); } } printf("Next PGC number: %i\n", pgc->next_pgc_nr); printf("Prev PGC number: %i\n", pgc->prev_pgc_nr); printf("GoUp PGC number: %i\n", pgc->goup_pgc_nr); if(pgc->nr_of_programs != 0) { printf("Still time: %i seconds (255=inf)\n", pgc->still_time); printf("PG Playback mode %02x\n", pgc->pg_playback_mode); } if(pgc->nr_of_programs != 0) { for(i = 0; i < 16; i++) { printf("Color %2i: %08x\n", i, pgc->palette[i]); } } /* Memory offsets to div. tables. */ ifoPrint_PGC_COMMAND_TBL(pgc->command_tbl); ifoPrint_PGC_PROGRAM_MAP(pgc->program_map, pgc->nr_of_programs); ifoPrint_CELL_PLAYBACK(pgc->cell_playback, pgc->nr_of_cells); ifoPrint_CELL_POSITION(pgc->cell_position, pgc->nr_of_cells); } static void ifoPrint_TT_SRPT(tt_srpt_t *tt_srpt) { int i; printf("Number of TitleTrack search pointers: %i\n", tt_srpt->nr_of_srpts); for(i=0;inr_of_srpts;i++) { printf("Title Track index %i\n", i + 1); printf("\tTitle set number (VTS): %i", tt_srpt->title[i].title_set_nr); printf("\tVTS_TTN: %i\n", tt_srpt->title[i].vts_ttn); printf("\tNumber of PTTs: %i\n", tt_srpt->title[i].nr_of_ptts); printf("\tNumber of angles: %i\n", tt_srpt->title[i].nr_of_angles); printf("\tTitle playback type: (%02x)\n", *(uint8_t *)&(tt_srpt->title[i].pb_ty)); printf("\t\t%s\n", tt_srpt->title[i].pb_ty.multi_or_random_pgc_title ? "Random or Shuffle" : "Sequential"); if (tt_srpt->title[i].pb_ty.jlc_exists_in_cell_cmd) printf("\t\tJump/Link/Call exists in cell cmd\n"); if (tt_srpt->title[i].pb_ty.jlc_exists_in_prepost_cmd) printf("\t\tJump/Link/Call exists in pre/post cmd\n"); if (tt_srpt->title[i].pb_ty.jlc_exists_in_button_cmd) printf("\t\tJump/Link/Call exists in button cmd\n"); if (tt_srpt->title[i].pb_ty.jlc_exists_in_tt_dom) printf("\t\tJump/Link/Call exists in tt_dom cmd\n"); printf("\t\tTitle or time play:%d\n", tt_srpt->title[i].pb_ty.title_or_time_play); printf("\t\tChapter search or play:%d\n", tt_srpt->title[i].pb_ty.chapter_search_or_play); printf("\tParental ID field: %04x\n", tt_srpt->title[i].parental_id); printf("\tTitle set starting sector %08x\n", tt_srpt->title[i].title_set_sector); } } static void ifoPrint_VTS_PTT_SRPT(vts_ptt_srpt_t *vts_ptt_srpt) { int i, j; printf(" nr_of_srpts %i last byte %i\n", vts_ptt_srpt->nr_of_srpts, vts_ptt_srpt->last_byte); for(i=0;inr_of_srpts;i++) { for(j=0;jtitle[i].nr_of_ptts;j++) { printf("VTS_PTT_SRPT - Title %3i part %3i: PGC: %3i PG: %3i\n", i + 1, j + 1, vts_ptt_srpt->title[i].ptt[j].pgcn, vts_ptt_srpt->title[i].ptt[j].pgn ); } } } static void hexdump(uint8_t *ptr, int len) { while(len--) printf("%02x ", *ptr++); } static void ifoPrint_PTL_MAIT(ptl_mait_t *ptl_mait) { int i, j; printf("Number of Countries: %i\n", ptl_mait->nr_of_countries); printf("Number of VTSs: %i\n", ptl_mait->nr_of_vtss); //printf("Last byte: %i\n", ptl_mait->last_byte); for(i = 0; i < ptl_mait->nr_of_countries; i++) { printf("Country code: %c%c\n", ptl_mait->countries[i].country_code >> 8, ptl_mait->countries[i].country_code & 0xff); /* printf("Start byte: %04x %i\n", ptl_mait->countries[i].pf_ptl_mai_start_byte, ptl_mait->countries[i].pf_ptl_mai_start_byte); */ /* This seems to be pointing at a array with 8 2byte fields per VTS ? and one extra for the menu? always an odd number of VTSs on all the dics I tested so it might be padding to even also. If it is for the menu it probably the first entry. */ for(j=0;j<8;j++) { hexdump( (uint8_t *)ptl_mait->countries - PTL_MAIT_COUNTRY_SIZE + ptl_mait->countries[i].pf_ptl_mai_start_byte + j*(ptl_mait->nr_of_vtss+1)*2, (ptl_mait->nr_of_vtss+1)*2); printf("\n"); } } } static void ifoPrint_VTS_TMAPT(vts_tmapt_t *vts_tmapt) { unsigned int timeunit; int i, j; printf("Number of VTS_TMAPS: %i\n", vts_tmapt->nr_of_tmaps); printf("Last byte: %i\n", vts_tmapt->last_byte); for(i = 0; i < vts_tmapt->nr_of_tmaps; i++) { printf("TMAP %i (number matches title PGC number.)\n", i + 1); printf(" offset %d relative to VTS_TMAPTI\n", vts_tmapt->tmap_offset[i]); printf(" Time unit (seconds): %i\n", vts_tmapt->tmap[i].tmu); printf(" Number of entries: %i\n", vts_tmapt->tmap[i].nr_of_entries); timeunit = vts_tmapt->tmap[i].tmu; for(j = 0; j < vts_tmapt->tmap[i].nr_of_entries; j++) { unsigned int ac_time = timeunit * (j + 1); printf("Time: %2i:%02i:%02i VOBU Sector: 0x%08x %s\n", ac_time / (60 * 60), (ac_time / 60) % 60, ac_time % 60, vts_tmapt->tmap[i].map_ent[j] & 0x7fffffff, (vts_tmapt->tmap[i].map_ent[j] >> 31) ? "discontinuity" : ""); } } } static void ifoPrint_C_ADT(c_adt_t *c_adt) { int i, entries; printf("Number of VOBs in this VOBS: %i\n", c_adt->nr_of_vobs); //entries = c_adt->nr_of_vobs; entries = (c_adt->last_byte + 1 - C_ADT_SIZE)/sizeof(c_adt_t); for(i = 0; i < entries; i++) { printf("VOB ID: %3i, Cell ID: %3i ", c_adt->cell_adr_table[i].vob_id, c_adt->cell_adr_table[i].cell_id); printf("Sector (first): 0x%08x (last): 0x%08x\n", c_adt->cell_adr_table[i].start_sector, c_adt->cell_adr_table[i].last_sector); } } static void ifoPrint_VOBU_ADMAP(vobu_admap_t *vobu_admap) { int i, entries; entries = (vobu_admap->last_byte + 1 - VOBU_ADMAP_SIZE)/4; for(i = 0; i < entries; i++) { printf("VOBU %5i First sector: 0x%08x\n", i + 1, vobu_admap->vobu_start_sectors[i]); } } static const char *ifo_print_menu_name(int type) { const char *menu_name; menu_name=""; switch (type) { case 2: menu_name="Title"; break; case 3: menu_name = "Root"; break; case 4: menu_name = "Sub-Picture"; break; case 5: menu_name = "Audio"; break; case 6: menu_name = "Angle"; break; case 7: menu_name = "PTT (Chapter)"; break; default: menu_name = "Unknown"; break; } return &menu_name[0]; } /* pgc_type=1 for menu, 0 for title. */ static void ifoPrint_PGCIT(pgcit_t *pgcit, int pgc_type) { int i; printf("\nNumber of Program Chains: %3i\n", pgcit->nr_of_pgci_srp); for(i = 0; i < pgcit->nr_of_pgci_srp; i++) { printf("\nProgram (PGC): %3i\n", i + 1); if (pgc_type) { printf("PGC Category: Entry PGC %d, Menu Type=0x%02x:%s (Entry id 0x%02x), ", pgcit->pgci_srp[i].entry_id >> 7, pgcit->pgci_srp[i].entry_id & 0xf, ifo_print_menu_name(pgcit->pgci_srp[i].entry_id & 0xf), pgcit->pgci_srp[i].entry_id); } else { printf("PGC Category: %s VTS_TTN:0x%02x (Entry id 0x%02x), ", pgcit->pgci_srp[i].entry_id >> 7 ? "At Start of" : "During", pgcit->pgci_srp[i].entry_id & 0xf, pgcit->pgci_srp[i].entry_id); } printf("Parental ID mask 0x%04x\n", pgcit->pgci_srp[i].ptl_id_mask); ifoPrint_PGC(pgcit->pgci_srp[i].pgc); } } static void ifoPrint_PGCI_UT(pgci_ut_t *pgci_ut) { int i, menu; printf("Number of Menu Language Units (PGCI_LU): %3i\n", pgci_ut->nr_of_lus); for(i = 0; i < pgci_ut->nr_of_lus; i++) { printf("\nMenu Language Unit %d\n", i+1); printf("\nMenu Language Code: %c%c\n", pgci_ut->lu[i].lang_code >> 8, pgci_ut->lu[i].lang_code & 0xff); menu = pgci_ut->lu[i].exists; printf("Menu Existence: %02x: ", menu); if (menu == 0) { printf("No menus "); } if (menu & 0x80) { printf("Root "); menu^=0x80; } if (menu & 0x40) { printf("Sub-Picture "); menu^=0x40; } if (menu & 0x20) { printf("Audio "); menu^=0x20; } if (menu & 0x10) { printf("Angle "); menu^=0x10; } if (menu & 0x08) { printf("PTT "); menu^=0x08; } if (menu > 0) { printf("Unknown extra menus "); menu^=0x08; } printf("\n"); ifoPrint_PGCIT(pgci_ut->lu[i].pgcit, 1); } } static void ifoPrint_VTS_ATTRIBUTES(vts_attributes_t *vts_attributes) { int i; printf("VTS_CAT Application type: %08x\n", vts_attributes->vts_cat); printf("Video attributes of VTSM_VOBS: "); ifo_print_video_attributes(&vts_attributes->vtsm_vobs_attr); printf("\n"); printf("Number of Audio streams: %i\n", vts_attributes->nr_of_vtsm_audio_streams); if(vts_attributes->nr_of_vtsm_audio_streams > 0) { printf("\tstream %i attributes: ", 1); ifo_print_audio_attributes(&vts_attributes->vtsm_audio_attr); printf("\n"); } printf("Number of Subpicture streams: %i\n", vts_attributes->nr_of_vtsm_subp_streams); if(vts_attributes->nr_of_vtsm_subp_streams > 0) { printf("\tstream %2i attributes: ", 1); ifo_print_subp_attributes(&vts_attributes->vtsm_subp_attr); printf("\n"); } printf("Video attributes of VTSTT_VOBS: "); ifo_print_video_attributes(&vts_attributes->vtstt_vobs_video_attr); printf("\n"); printf("Number of Audio streams: %i\n", vts_attributes->nr_of_vtstt_audio_streams); for(i = 0; i < vts_attributes->nr_of_vtstt_audio_streams; i++) { printf("\tstream %i attributes: ", i); ifo_print_audio_attributes(&vts_attributes->vtstt_audio_attr[i]); printf("\n"); } printf("Number of Subpicture streams: %i\n", vts_attributes->nr_of_vtstt_subp_streams); for(i = 0; i < vts_attributes->nr_of_vtstt_subp_streams; i++) { printf("\tstream %2i attributes: ", i); ifo_print_subp_attributes(&vts_attributes->vtstt_subp_attr[i]); printf("\n"); } } static void ifoPrint_VTS_ATRT(vts_atrt_t *vts_atrt) { int i; printf("Number of Video Title Sets: %3i\n", vts_atrt->nr_of_vtss); for(i = 0; i < vts_atrt->nr_of_vtss; i++) { printf("\nVideo Title Set %i\n", i + 1); ifoPrint_VTS_ATTRIBUTES(&vts_atrt->vts[i]); } } void ifo_print(dvd_reader_t *dvd, int title) { ifo_handle_t *ifohandle; printf("Local ifo_print\n"); ifohandle = ifoOpen(dvd, title); if(!ifohandle) { fprintf(stderr, "Can't open info file for title %d\n", title); return; } if(ifohandle->vmgi_mat) { printf("VMG top level\n-------------\n"); ifoPrint_VMGI_MAT(ifohandle->vmgi_mat); printf("\nFirst Play PGC\n--------------\n"); if(ifohandle->first_play_pgc) ifoPrint_PGC(ifohandle->first_play_pgc); else printf("No First Play PGC present\n"); printf("\nTitle Track search pointer table\n"); printf( "------------------------------------------------\n"); ifoPrint_TT_SRPT(ifohandle->tt_srpt); printf("\nMenu PGCI Unit table\n"); printf( "--------------------\n"); if(ifohandle->pgci_ut) { ifoPrint_PGCI_UT(ifohandle->pgci_ut); } else { printf("No PGCI Unit table present\n"); } printf("\nParental Management Information table\n"); printf( "------------------------------------\n"); if(ifohandle->ptl_mait) { ifoPrint_PTL_MAIT(ifohandle->ptl_mait); } else { printf("No Parental Management Information present\n"); } printf("\nVideo Title Set Attribute Table\n"); printf( "-------------------------------\n"); ifoPrint_VTS_ATRT(ifohandle->vts_atrt); printf("\nText Data Manager Information\n"); printf( "-----------------------------\n"); if(ifohandle->txtdt_mgi) { //ifo_print_TXTDT_MGI(&(vmgi->txtdt_mgi)); } else { printf("No Text Data Manager Information present\n"); } printf("\nMenu Cell Address table\n"); printf( "-----------------\n"); if(ifohandle->menu_c_adt) { ifoPrint_C_ADT(ifohandle->menu_c_adt); } else { printf("No Menu Cell Address table present\n"); } printf("\nVideo Manager Menu VOBU address map\n"); printf( "-----------------\n"); if(ifohandle->menu_vobu_admap) { ifoPrint_VOBU_ADMAP(ifohandle->menu_vobu_admap); } else { printf("No Menu VOBU address map present\n"); } } if(ifohandle->vtsi_mat) { printf("VTS top level\n-------------\n"); ifoPrint_VTSI_MAT(ifohandle->vtsi_mat); printf("\nPart of Title Track search pointer table\n"); printf( "----------------------------------------------\n"); ifoPrint_VTS_PTT_SRPT(ifohandle->vts_ptt_srpt); printf("\nPGCI Unit table\n"); printf( "--------------------\n"); ifoPrint_PGCIT(ifohandle->vts_pgcit, 0); printf("\nMenu PGCI Unit table\n"); printf( "--------------------\n"); if(ifohandle->pgci_ut) { ifoPrint_PGCI_UT(ifohandle->pgci_ut); } else { printf("No Menu PGCI Unit table present\n"); } printf("\nVTS Time Map table\n"); printf( "-----------------\n"); if(ifohandle->vts_tmapt) { ifoPrint_VTS_TMAPT(ifohandle->vts_tmapt); } else { printf("No VTS Time Map table present\n"); } printf("\nMenu Cell Address table\n"); printf( "-----------------\n"); if(ifohandle->menu_c_adt) { ifoPrint_C_ADT(ifohandle->menu_c_adt); } else { printf("No Cell Address table present\n"); } printf("\nVideo Title Set Menu VOBU address map\n"); printf( "-----------------\n"); if(ifohandle->menu_vobu_admap) { ifoPrint_VOBU_ADMAP(ifohandle->menu_vobu_admap); } else { printf("No Menu VOBU address map present\n"); } printf("\nCell Address table\n"); printf( "-----------------\n"); ifoPrint_C_ADT(ifohandle->vts_c_adt); printf("\nVideo Title Set VOBU address map\n"); printf( "-----------------\n"); ifoPrint_VOBU_ADMAP(ifohandle->vts_vobu_admap); } ifoClose(ifohandle); } k9copy/src/libdvdread-NOW/dvd_input.c0000644000175000017550000002160412412306322020231 0ustar emulatoremulator/* * Copyright (C) 2002 Samuel Hocevar , * Håkan Hjort * * This file is part of libdvdread. * * libdvdread is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdread is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdread; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" /* Required for HAVE_DVDCSS_DVDCSS_H */ #include /* fprintf */ #include /* free */ #include /* open */ #include /* lseek */ #include #include "dvdread/dvd_reader.h" /* DVD_VIDEO_LB_LEN */ #include "dvd_input.h" /* The function pointers that is the exported interface of this file. */ dvd_input_t (*dvdinput_open) (const char *); int (*dvdinput_close) (dvd_input_t); int (*dvdinput_seek) (dvd_input_t, int); int (*dvdinput_title) (dvd_input_t, int); int (*dvdinput_read) (dvd_input_t, void *, int, int); char * (*dvdinput_error) (dvd_input_t); #ifdef HAVE_DVDCSS_DVDCSS_H /* linking to libdvdcss */ # include # define DVDcss_open(a) dvdcss_open((char*)(a)) # define DVDcss_close dvdcss_close # define DVDcss_seek dvdcss_seek # define DVDcss_read dvdcss_read # define DVDcss_error dvdcss_error #else /* dlopening libdvdcss */ # if defined(HAVE_DLFCN_H) && !defined(USING_BUILTIN_DLFCN) # include # else # if defined(WIN32) /* Only needed on MINGW at the moment */ # include "../msvc/contrib/dlfcn.c" # endif #endif typedef struct dvdcss_s *dvdcss_t; static dvdcss_t (*DVDcss_open) (const char *); static int (*DVDcss_close) (dvdcss_t); static int (*DVDcss_seek) (dvdcss_t, int, int); static int (*DVDcss_read) (dvdcss_t, void *, int, int); static char * (*DVDcss_error) (dvdcss_t); #define DVDCSS_SEEK_KEY (1 << 1) #endif /* The DVDinput handle, add stuff here for new input methods. */ struct dvd_input_s { /* libdvdcss handle */ dvdcss_t dvdcss; /* dummy file input */ int fd; }; /** * initialize and open a DVD device or file. */ static dvd_input_t css_open(const char *target) { dvd_input_t dev; /* Allocate the handle structure */ dev = malloc(sizeof(*dev)); if(dev == NULL) { fprintf(stderr, "libdvdread: Could not allocate memory.\n"); return NULL; } /* Really open it with libdvdcss */ dev->dvdcss = DVDcss_open(target); if(dev->dvdcss == 0) { fprintf(stderr, "libdvdread: Could not open %s with libdvdcss.\n", target); free(dev); return NULL; } return dev; } /** * return the last error message */ static char *css_error(dvd_input_t dev) { return DVDcss_error(dev->dvdcss); } /** * seek into the device. */ static int css_seek(dvd_input_t dev, int blocks) { /* DVDINPUT_NOFLAGS should match the DVDCSS_NOFLAGS value. */ return DVDcss_seek(dev->dvdcss, blocks, DVDINPUT_NOFLAGS); } /** * set the block for the beginning of a new title (key). */ static int css_title(dvd_input_t dev, int block) { return DVDcss_seek(dev->dvdcss, block, DVDCSS_SEEK_KEY); } /** * read data from the device. */ static int css_read(dvd_input_t dev, void *buffer, int blocks, int flags) { return DVDcss_read(dev->dvdcss, buffer, blocks, flags); } /** * close the DVD device and clean up the library. */ static int css_close(dvd_input_t dev) { int ret; ret = DVDcss_close(dev->dvdcss); if(ret < 0) return ret; free(dev); return 0; } /** * initialize and open a DVD device or file. */ static dvd_input_t file_open(const char *target) { dvd_input_t dev; /* Allocate the library structure */ dev = malloc(sizeof(*dev)); if(dev == NULL) { fprintf(stderr, "libdvdread: Could not allocate memory.\n"); return NULL; } /* Open the device */ #if !defined(WIN32) && !defined(__OS2__) dev->fd = open(target, O_RDONLY); #else dev->fd = open(target, O_RDONLY | O_BINARY); #endif if(dev->fd < 0) { perror("libdvdread: Could not open input"); free(dev); return NULL; } return dev; } /** * return the last error message */ static char *file_error(dvd_input_t dev) { /* use strerror(errno)? */ return (char *)"unknown error"; } /** * seek into the device. */ static int file_seek(dvd_input_t dev, int blocks) { off_t pos; pos = lseek(dev->fd, (off_t)blocks * (off_t)DVD_VIDEO_LB_LEN, SEEK_SET); if(pos < 0) { return pos; } /* assert pos % DVD_VIDEO_LB_LEN == 0 */ return (int) (pos / DVD_VIDEO_LB_LEN); } /** * set the block for the beginning of a new title (key). */ static int file_title(dvd_input_t dev, int block) { return -1; } /** * read data from the device. */ static int file_read(dvd_input_t dev, void *buffer, int blocks, int flags) { size_t len; ssize_t ret; len = (size_t)blocks * DVD_VIDEO_LB_LEN; while(len > 0) { ret = read(dev->fd, buffer, len); if(ret < 0) { /* One of the reads failed, too bad. We won't even bother * returning the reads that went OK, and as in the POSIX spec * the file position is left unspecified after a failure. */ return ret; } if(ret == 0) { /* Nothing more to read. Return all of the whole blocks, if any. * Adjust the file position back to the previous block boundary. */ size_t bytes = (size_t)blocks * DVD_VIDEO_LB_LEN - len; off_t over_read = -(bytes % DVD_VIDEO_LB_LEN); /*off_t pos =*/ lseek(dev->fd, over_read, SEEK_CUR); /* should have pos % 2048 == 0 */ return (int) (bytes / DVD_VIDEO_LB_LEN); } len -= ret; } return blocks; } /** * close the DVD device and clean up. */ static int file_close(dvd_input_t dev) { int ret; ret = close(dev->fd); if(ret < 0) return ret; free(dev); return 0; } /** * Setup read functions with either libdvdcss or minimal DVD access. */ int dvdinput_setup(void) { void *dvdcss_library = NULL; #ifdef HAVE_DVDCSS_DVDCSS_H /* linking to libdvdcss */ dvdcss_library = &dvdcss_library; /* Give it some value != NULL */ #else /* dlopening libdvdcss */ #ifdef __APPLE__ #define CSS_LIB "libdvdcss.2.dylib" #elif defined(WIN32) #define CSS_LIB "libdvdcss-2.dll" #elif defined(__OS2__) #define CSS_LIB "dvdcss.dll" #else #define CSS_LIB "libdvdcss.so.2" #endif dvdcss_library = dlopen(CSS_LIB, RTLD_LAZY); if(dvdcss_library != NULL) { #if defined(__OpenBSD__) && !defined(__ELF__) || defined(__OS2__) #define U_S "_" #else #define U_S #endif DVDcss_open = (dvdcss_t (*)(const char*)) dlsym(dvdcss_library, U_S "dvdcss_open"); DVDcss_close = (int (*)(dvdcss_t)) dlsym(dvdcss_library, U_S "dvdcss_close"); DVDcss_seek = (int (*)(dvdcss_t, int, int)) dlsym(dvdcss_library, U_S "dvdcss_seek"); DVDcss_read = (int (*)(dvdcss_t, void*, int, int)) dlsym(dvdcss_library, U_S "dvdcss_read"); DVDcss_error = (char* (*)(dvdcss_t)) dlsym(dvdcss_library, U_S "dvdcss_error"); if(dlsym(dvdcss_library, U_S "dvdcss_crack")) { fprintf(stderr, "libdvdread: Old (pre-0.0.2) version of libdvdcss found.\n" "libdvdread: You should get the latest version from " "http://www.videolan.org/\n" ); dlclose(dvdcss_library); dvdcss_library = NULL; } else if(!DVDcss_open || !DVDcss_close || !DVDcss_seek || !DVDcss_read || !DVDcss_error) { fprintf(stderr, "libdvdread: Missing symbols in %s, " "this shouldn't happen !\n", CSS_LIB); dlclose(dvdcss_library); dvdcss_library = NULL; } } #endif /* HAVE_DVDCSS_DVDCSS_H */ if(dvdcss_library != NULL) { /* char *psz_method = getenv( "DVDCSS_METHOD" ); char *psz_verbose = getenv( "DVDCSS_VERBOSE" ); fprintf(stderr, "DVDCSS_METHOD %s\n", psz_method); fprintf(stderr, "DVDCSS_VERBOSE %s\n", psz_verbose); */ /* libdvdcss wrapper functions */ dvdinput_open = css_open; dvdinput_close = css_close; dvdinput_seek = css_seek; dvdinput_title = css_title; dvdinput_read = css_read; dvdinput_error = css_error; return 1; } else { fprintf(stderr, "libdvdread: Encrypted DVD support unavailable.\n"); /* libdvdcss replacement functions */ dvdinput_open = file_open; dvdinput_close = file_close; dvdinput_seek = file_seek; dvdinput_title = file_title; dvdinput_read = file_read; dvdinput_error = file_error; return 0; } } k9copy/src/libdvdread-NOW/dvd_udf.c0000644000175000017550000006244612412304751017665 0ustar emulatoremulator/* * This code is based on dvdudf by: * Christian Wolff . * * Modifications by: * Billy Biggs . * Björn Englund . * * dvdudf: parse and read the UDF volume information of a DVD Video * Copyright (C) 1999 Christian Wolff for convergence integrated media * GmbH The author can be reached at scarabaeus@convergence.de, the * project's page is at http://linuxtv.org/dvd/ * * This file is part of libdvdread. * * libdvdread is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libdvdread is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with libdvdread; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include #include #include #include #include #include #include "dvdread_internal.h" #include "dvdread/dvd_reader.h" #include "dvdread/dvd_udf.h" /* It's required to either fail or deliver all the blocks asked for. */ static int DVDReadLBUDF( dvd_reader_t *device, uint32_t lb_number, size_t block_count, unsigned char *data, int encrypted ) { int ret; size_t count = block_count; while(count > 0) { ret = InternalUDFReadBlocksRaw(device, lb_number, count, data, encrypted); if(ret <= 0) { /* One of the reads failed or nothing more to read, too bad. * We won't even bother returning the reads that went ok. */ return ret; } count -= (size_t)ret; lb_number += (uint32_t)ret; } return block_count; } #ifndef NULL #define NULL ((void *)0) #endif struct Partition { int valid; char VolumeDesc[128]; uint16_t Flags; uint16_t Number; char Contents[32]; uint32_t AccessType; uint32_t Start; uint32_t Length; }; struct AD { uint32_t Location; uint32_t Length; uint8_t Flags; uint16_t Partition; }; struct extent_ad { uint32_t location; uint32_t length; }; struct avdp_t { struct extent_ad mvds; struct extent_ad rvds; }; struct pvd_t { uint8_t VolumeIdentifier[32]; uint8_t VolumeSetIdentifier[128]; }; struct lbudf { uint32_t lb; uint8_t *data; /* needed for proper freeing */ uint8_t *data_base; }; struct icbmap { uint32_t lbn; struct AD file; uint8_t filetype; }; struct udf_cache { int avdp_valid; struct avdp_t avdp; int pvd_valid; struct pvd_t pvd; int partition_valid; struct Partition partition; int rooticb_valid; struct AD rooticb; int lb_num; struct lbudf *lbs; int map_num; struct icbmap *maps; }; typedef enum { PartitionCache, RootICBCache, LBUDFCache, MapCache, AVDPCache, PVDCache } UDFCacheType; void FreeUDFCache(void *cache) { struct udf_cache *c = (struct udf_cache *)cache; if(c == NULL) return; if(c->lbs) { int n; for(n = 0; n < c->lb_num; n++) free(c->lbs[n].data_base); free(c->lbs); } if(c->maps) free(c->maps); free(c); } static int GetUDFCache(dvd_reader_t *device, UDFCacheType type, uint32_t nr, void *data) { int n; struct udf_cache *c; if(DVDUDFCacheLevel(device, -1) <= 0) return 0; c = (struct udf_cache *)GetUDFCacheHandle(device); if(c == NULL) return 0; switch(type) { case AVDPCache: if(c->avdp_valid) { *(struct avdp_t *)data = c->avdp; return 1; } break; case PVDCache: if(c->pvd_valid) { *(struct pvd_t *)data = c->pvd; return 1; } break; case PartitionCache: if(c->partition_valid) { *(struct Partition *)data = c->partition; return 1; } break; case RootICBCache: if(c->rooticb_valid) { *(struct AD *)data = c->rooticb; return 1; } break; case LBUDFCache: for(n = 0; n < c->lb_num; n++) { if(c->lbs[n].lb == nr) { *(uint8_t **)data = c->lbs[n].data; return 1; } } break; case MapCache: for(n = 0; n < c->map_num; n++) { if(c->maps[n].lbn == nr) { *(struct icbmap *)data = c->maps[n]; return 1; } } break; default: break; } return 0; } static int SetUDFCache(dvd_reader_t *device, UDFCacheType type, uint32_t nr, void *data) { int n; struct udf_cache *c; void *tmp; if(DVDUDFCacheLevel(device, -1) <= 0) return 0; c = (struct udf_cache *)GetUDFCacheHandle(device); if(c == NULL) { c = calloc(1, sizeof(struct udf_cache)); /* fprintf(stderr, "calloc: %d\n", sizeof(struct udf_cache)); */ if(c == NULL) return 0; SetUDFCacheHandle(device, c); } switch(type) { case AVDPCache: c->avdp = *(struct avdp_t *)data; c->avdp_valid = 1; break; case PVDCache: c->pvd = *(struct pvd_t *)data; c->pvd_valid = 1; break; case PartitionCache: c->partition = *(struct Partition *)data; c->partition_valid = 1; break; case RootICBCache: c->rooticb = *(struct AD *)data; c->rooticb_valid = 1; break; case LBUDFCache: for(n = 0; n < c->lb_num; n++) { if(c->lbs[n].lb == nr) { /* replace with new data */ c->lbs[n].data_base = ((uint8_t **)data)[0]; c->lbs[n].data = ((uint8_t **)data)[1]; c->lbs[n].lb = nr; return 1; } } c->lb_num++; tmp = realloc(c->lbs, c->lb_num * sizeof(struct lbudf)); /* fprintf(stderr, "realloc lb: %d * %d = %d\n", c->lb_num, sizeof(struct lbudf), c->lb_num * sizeof(struct lbudf)); */ if(tmp == NULL) { if(c->lbs) free(c->lbs); c->lb_num = 0; return 0; } c->lbs = tmp; c->lbs[n].data_base = ((uint8_t **)data)[0]; c->lbs[n].data = ((uint8_t **)data)[1]; c->lbs[n].lb = nr; break; case MapCache: for(n = 0; n < c->map_num; n++) { if(c->maps[n].lbn == nr) { /* replace with new data */ c->maps[n] = *(struct icbmap *)data; c->maps[n].lbn = nr; return 1; } } c->map_num++; tmp = realloc(c->maps, c->map_num * sizeof(struct icbmap)); /* fprintf(stderr, "realloc maps: %d * %d = %d\n", c->map_num, sizeof(struct icbmap), c->map_num * sizeof(struct icbmap)); */ if(tmp == NULL) { if(c->maps) free(c->maps); c->map_num = 0; return 0; } c->maps = tmp; c->maps[n] = *(struct icbmap *)data; c->maps[n].lbn = nr; break; default: return 0; } return 1; } /* For direct data access, LSB first */ #define GETN1(p) ((uint8_t)data[p]) #define GETN2(p) ((uint16_t)data[p] | ((uint16_t)data[(p) + 1] << 8)) #define GETN3(p) ((uint32_t)data[p] | ((uint32_t)data[(p) + 1] << 8) \ | ((uint32_t)data[(p) + 2] << 16)) #define GETN4(p) ((uint32_t)data[p] \ | ((uint32_t)data[(p) + 1] << 8) \ | ((uint32_t)data[(p) + 2] << 16) \ | ((uint32_t)data[(p) + 3] << 24)) /* This is wrong with regard to endianess */ #define GETN(p, n, target) memcpy(target, &data[p], n) static int Unicodedecode( uint8_t *data, int len, char *target ) { int p = 1, i = 0; int err = 0; if( ( data[ 0 ] == 8 ) || ( data[ 0 ] == 16 ) ) do { if( data[ 0 ] == 16 ) err |= data[p++]; /* character cannot be converted to 8bit, return error */ if( p < len ) { target[ i++ ] = data[ p++ ]; } } while( p < len ); target[ i ] = '\0'; return !err; } static int UDFDescriptor( uint8_t *data, uint16_t *TagID ) { *TagID = GETN2(0); /* TODO: check CRC 'n stuff */ return 0; } static int UDFExtentAD( uint8_t *data, uint32_t *Length, uint32_t *Location ) { *Length = GETN4(0); *Location = GETN4(4); return 0; } static int UDFShortAD( uint8_t *data, struct AD *ad, struct Partition *partition ) { ad->Length = GETN4(0); ad->Flags = ad->Length >> 30; ad->Length &= 0x3FFFFFFF; ad->Location = GETN4(4); ad->Partition = partition->Number; /* use number of current partition */ return 0; } static int UDFLongAD( uint8_t *data, struct AD *ad ) { ad->Length = GETN4(0); ad->Flags = ad->Length >> 30; ad->Length &= 0x3FFFFFFF; ad->Location = GETN4(4); ad->Partition = GETN2(8); /* GETN(10, 6, Use); */ return 0; } static int UDFExtAD( uint8_t *data, struct AD *ad ) { ad->Length = GETN4(0); ad->Flags = ad->Length >> 30; ad->Length &= 0x3FFFFFFF; ad->Location = GETN4(12); ad->Partition = GETN2(16); /* GETN(10, 6, Use); */ return 0; } static int UDFICB( uint8_t *data, uint8_t *FileType, uint16_t *Flags ) { *FileType = GETN1(11); *Flags = GETN2(18); return 0; } static int UDFPartition( uint8_t *data, uint16_t *Flags, uint16_t *Number, char *Contents, uint32_t *Start, uint32_t *Length ) { *Flags = GETN2(20); *Number = GETN2(22); GETN(24, 32, Contents); *Start = GETN4(188); *Length = GETN4(192); return 0; } /** * Reads the volume descriptor and checks the parameters. Returns 0 on OK, 1 * on error. */ static int UDFLogVolume( uint8_t *data, char *VolumeDescriptor ) { uint32_t lbsize; Unicodedecode(&data[84], 128, VolumeDescriptor); lbsize = GETN4(212); /* should be 2048 */ /* MT_L = GETN4(264); */ /* should be 6 */ /* N_PM = GETN4(268); */ /* should be 1 */ if (lbsize != DVD_VIDEO_LB_LEN) return 1; return 0; } static int UDFFileEntry( uint8_t *data, uint8_t *FileType, struct Partition *partition, struct AD *ad ) { uint16_t flags; uint32_t L_EA, L_AD; unsigned int p; UDFICB( &data[ 16 ], FileType, &flags ); /* Init ad for an empty file (i.e. there isn't a AD, L_AD == 0 ) */ ad->Length = GETN4( 60 ); /* Really 8 bytes a 56 */ ad->Flags = 0; ad->Location = 0; /* what should we put here? */ ad->Partition = partition->Number; /* use number of current partition */ L_EA = GETN4( 168 ); L_AD = GETN4( 172 ); if (176 + L_EA + L_AD > DVD_VIDEO_LB_LEN) return 0; p = 176 + L_EA; while( p < 176 + L_EA + L_AD ) { switch( flags & 0x0007 ) { case 0: UDFShortAD( &data[ p ], ad, partition ); p += 8; break; case 1: UDFLongAD( &data[ p ], ad ); p += 16; break; case 2: UDFExtAD( &data[ p ], ad ); p += 20; break; case 3: switch( L_AD ) { case 8: UDFShortAD( &data[ p ], ad, partition ); break; case 16: UDFLongAD( &data[ p ], ad ); break; case 20: UDFExtAD( &data[ p ], ad ); break; } p += L_AD; break; default: p += L_AD; break; } } return 0; } static int UDFFileIdentifier( uint8_t *data, uint8_t *FileCharacteristics, char *FileName, struct AD *FileICB ) { uint8_t L_FI; uint16_t L_IU; *FileCharacteristics = GETN1(18); L_FI = GETN1(19); UDFLongAD(&data[20], FileICB); L_IU = GETN2(36); if (L_FI) { if (!Unicodedecode(&data[38 + L_IU], L_FI, FileName)) FileName[0] = 0; } else FileName[0] = '\0'; return 4 * ((38 + L_FI + L_IU + 3) / 4); } /** * Maps ICB to FileAD * ICB: Location of ICB of directory to scan * FileType: Type of the file * File: Location of file the ICB is pointing to * return 1 on success, 0 on error; */ static int UDFMapICB( dvd_reader_t *device, struct AD ICB, uint8_t *FileType, struct Partition *partition, struct AD *File ) { uint8_t LogBlock_base[DVD_VIDEO_LB_LEN + 2048]; uint8_t *LogBlock = (uint8_t *)(((uintptr_t)LogBlock_base & ~((uintptr_t)2047)) + 2048); uint32_t lbnum; uint16_t TagID; struct icbmap tmpmap; lbnum = partition->Start + ICB.Location; tmpmap.lbn = lbnum; if(GetUDFCache(device, MapCache, lbnum, &tmpmap)) { *FileType = tmpmap.filetype; memcpy(File, &tmpmap.file, sizeof(tmpmap.file)); return 1; } do { if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) TagID = 0; else UDFDescriptor( LogBlock, &TagID ); if( TagID == FileEntry ) { UDFFileEntry( LogBlock, FileType, partition, File ); memcpy(&tmpmap.file, File, sizeof(tmpmap.file)); tmpmap.filetype = *FileType; SetUDFCache(device, MapCache, tmpmap.lbn, &tmpmap); return 1; }; } while( ( lbnum <= partition->Start + ICB.Location + ( ICB.Length - 1 ) / DVD_VIDEO_LB_LEN ) && ( TagID != FileEntry ) ); return 0; } /** * Dir: Location of directory to scan * FileName: Name of file to look for * FileICB: Location of ICB of the found file * return 1 on success, 0 on error; */ static int UDFScanDir( dvd_reader_t *device, struct AD Dir, char *FileName, struct Partition *partition, struct AD *FileICB, int cache_file_info) { char filename[ MAX_UDF_FILE_NAME_LEN ]; uint8_t directory_base[ 2 * DVD_VIDEO_LB_LEN + 2048]; uint8_t *directory = (uint8_t *)(((uintptr_t)directory_base & ~((uintptr_t)2047)) + 2048); uint32_t lbnum; uint16_t TagID; uint8_t filechar; unsigned int p; uint8_t *cached_dir_base = NULL, *cached_dir; uint32_t dir_lba; struct AD tmpICB; int found = 0; int in_cache = 0; /* Scan dir for ICB of file */ lbnum = partition->Start + Dir.Location; if(DVDUDFCacheLevel(device, -1) > 0) { /* caching */ if(!GetUDFCache(device, LBUDFCache, lbnum, &cached_dir)) { dir_lba = (Dir.Length + DVD_VIDEO_LB_LEN) / DVD_VIDEO_LB_LEN; if((cached_dir_base = malloc(dir_lba * DVD_VIDEO_LB_LEN + 2048)) == NULL) return 0; cached_dir = (uint8_t *)(((uintptr_t)cached_dir_base & ~((uintptr_t)2047)) + 2048); if( DVDReadLBUDF( device, lbnum, dir_lba, cached_dir, 0) <= 0 ) { free(cached_dir_base); cached_dir_base = NULL; cached_dir = NULL; } /* if(cached_dir) { fprintf(stderr, "malloc dir: %d\n", dir_lba * DVD_VIDEO_LB_LEN); } */ { uint8_t *data[2]; data[0] = cached_dir_base; data[1] = cached_dir; SetUDFCache(device, LBUDFCache, lbnum, data); } } else in_cache = 1; if(cached_dir == NULL) { free(cached_dir_base); return 0; } p = 0; while( p < Dir.Length ) { UDFDescriptor( &cached_dir[ p ], &TagID ); if( TagID == FileIdentifierDescriptor ) { p += UDFFileIdentifier( &cached_dir[ p ], &filechar, filename, &tmpICB ); if(cache_file_info && !in_cache) { uint8_t tmpFiletype; struct AD tmpFile; if( !strcasecmp( FileName, filename ) ) { memcpy(FileICB, &tmpICB, sizeof(tmpICB)); found = 1; } if(!UDFMapICB(device, tmpICB, &tmpFiletype, partition, &tmpFile)) return 0; } else { if( !strcasecmp( FileName, filename ) ) { memcpy(FileICB, &tmpICB, sizeof(tmpICB)); return 1; } } } else { if(cache_file_info && (!in_cache) && found) return 1; return 0; } } if(cache_file_info && (!in_cache) && found) return 1; return 0; } if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <= 0 ) return 0; p = 0; while( p < Dir.Length ) { if( p > DVD_VIDEO_LB_LEN ) { ++lbnum; p -= DVD_VIDEO_LB_LEN; Dir.Length -= DVD_VIDEO_LB_LEN; if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <= 0 ) { return 0; } } UDFDescriptor( &directory[ p ], &TagID ); if( TagID == FileIdentifierDescriptor ) { p += UDFFileIdentifier( &directory[ p ], &filechar, filename, FileICB ); if( !strcasecmp( FileName, filename ) ) { return 1; } } else return 0; } return 0; } static int UDFGetAVDP( dvd_reader_t *device, struct avdp_t *avdp) { uint8_t Anchor_base[ DVD_VIDEO_LB_LEN + 2048 ]; uint8_t *Anchor = (uint8_t *)(((uintptr_t)Anchor_base & ~((uintptr_t)2047)) + 2048); uint32_t lbnum, MVDS_location, MVDS_length; uint16_t TagID; uint32_t lastsector; int terminate; struct avdp_t; if(GetUDFCache(device, AVDPCache, 0, avdp)) return 1; /* Find Anchor */ lastsector = 0; lbnum = 256; /* Try #1, prime anchor */ terminate = 0; for(;;) { if( DVDReadLBUDF( device, lbnum, 1, Anchor, 0 ) > 0 ) { UDFDescriptor( Anchor, &TagID ); } else { TagID = 0; } if (TagID != AnchorVolumeDescriptorPointer) { /* Not an anchor */ if( terminate ) return 0; /* Final try failed */ if( lastsector ) { /* We already found the last sector. Try #3, alternative * backup anchor. If that fails, don't try again. */ lbnum = lastsector; terminate = 1; } else { /* TODO: Find last sector of the disc (this is optional). */ if( lastsector ) /* Try #2, backup anchor */ lbnum = lastsector - 256; else /* Unable to find last sector */ return 0; } } else /* It's an anchor! We can leave */ break; } /* Main volume descriptor */ UDFExtentAD( &Anchor[ 16 ], &MVDS_length, &MVDS_location ); avdp->mvds.location = MVDS_location; avdp->mvds.length = MVDS_length; /* Backup volume descriptor */ UDFExtentAD( &Anchor[ 24 ], &MVDS_length, &MVDS_location ); avdp->rvds.location = MVDS_location; avdp->rvds.length = MVDS_length; SetUDFCache(device, AVDPCache, 0, avdp); return 1; } /** * Looks for partition on the disc. Returns 1 if partition found, 0 on error. * partnum: Number of the partition, starting at 0. * part: structure to fill with the partition information */ static int UDFFindPartition( dvd_reader_t *device, int partnum, struct Partition *part ) { uint8_t LogBlock_base[ DVD_VIDEO_LB_LEN + 2048 ]; uint8_t *LogBlock = (uint8_t *)(((uintptr_t)LogBlock_base & ~((uintptr_t)2047)) + 2048); uint32_t lbnum, MVDS_location, MVDS_length; uint16_t TagID; int i, volvalid; struct avdp_t avdp; if(!UDFGetAVDP(device, &avdp)) return 0; /* Main volume descriptor */ MVDS_location = avdp.mvds.location; MVDS_length = avdp.mvds.length; part->valid = 0; volvalid = 0; part->VolumeDesc[ 0 ] = '\0'; i = 1; do { /* Find Volume Descriptor */ lbnum = MVDS_location; do { if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) TagID = 0; else UDFDescriptor( LogBlock, &TagID ); if( ( TagID == PartitionDescriptor ) && ( !part->valid ) ) { /* Partition Descriptor */ UDFPartition( LogBlock, &part->Flags, &part->Number, part->Contents, &part->Start, &part->Length ); part->valid = ( partnum == part->Number ); } else if( ( TagID == LogicalVolumeDescriptor ) && ( !volvalid ) ) { /* Logical Volume Descriptor */ if( UDFLogVolume( LogBlock, part->VolumeDesc ) ) { /* TODO: sector size wrong! */ } else volvalid = 1; } } while( ( lbnum <= MVDS_location + ( MVDS_length - 1 ) / DVD_VIDEO_LB_LEN ) && ( TagID != TerminatingDescriptor ) && ( ( !part->valid ) || ( !volvalid ) ) ); if( ( !part->valid) || ( !volvalid ) ) { /* Backup volume descriptor */ MVDS_location = avdp.mvds.location; MVDS_length = avdp.mvds.length; } } while( i-- && ( ( !part->valid ) || ( !volvalid ) ) ); /* We only care for the partition, not the volume */ return part->valid; } uint32_t UDFFindFile( dvd_reader_t *device, char *filename, uint32_t *filesize ) { uint8_t LogBlock_base[ DVD_VIDEO_LB_LEN + 2048 ]; uint8_t *LogBlock = (uint8_t *)(((uintptr_t)LogBlock_base & ~((uintptr_t)2047)) + 2048); uint32_t lbnum; uint16_t TagID; struct Partition partition; struct AD RootICB, File, ICB; char tokenline[ MAX_UDF_FILE_NAME_LEN ]; char *token; uint8_t filetype; *filesize = 0; tokenline[0] = '\0'; strncat(tokenline, filename, MAX_UDF_FILE_NAME_LEN - 1); memset(&ICB, 0, sizeof(ICB)); if(!(GetUDFCache(device, PartitionCache, 0, &partition) && GetUDFCache(device, RootICBCache, 0, &RootICB))) { /* Find partition, 0 is the standard location for DVD Video.*/ if( !UDFFindPartition( device, 0, &partition ) ) return 0; SetUDFCache(device, PartitionCache, 0, &partition); /* Find root dir ICB */ lbnum = partition.Start; do { if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) TagID = 0; else UDFDescriptor( LogBlock, &TagID ); /* File Set Descriptor */ if( TagID == FileSetDescriptor ) /* File Set Descriptor */ UDFLongAD( &LogBlock[ 400 ], &RootICB ); } while( ( lbnum < partition.Start + partition.Length ) && ( TagID != TerminatingDescriptor ) && ( TagID != FileSetDescriptor) ); /* Sanity checks. */ if( TagID != FileSetDescriptor ) return 0; if( RootICB.Partition != 0 ) return 0; SetUDFCache(device, RootICBCache, 0, &RootICB); } /* Find root dir */ if( !UDFMapICB( device, RootICB, &filetype, &partition, &File ) ) return 0; if( filetype != 4 ) return 0; /* Root dir should be dir */ { int cache_file_info = 0; /* Tokenize filepath */ token = strtok(tokenline, "/"); while( token != NULL ) { if( !UDFScanDir( device, File, token, &partition, &ICB, cache_file_info)) return 0; if( !UDFMapICB( device, ICB, &filetype, &partition, &File ) ) return 0; if(!strcmp(token, "VIDEO_TS")) cache_file_info = 1; token = strtok( NULL, "/" ); } } /* Sanity check. */ if( File.Partition != 0 ) return 0; *filesize = File.Length; /* Hack to not return partition.Start for empty files. */ if( !File.Location ) return 0; else return partition.Start + File.Location; } /** * Gets a Descriptor . * Returns 1 if descriptor found, 0 on error. * id, tagid of descriptor * bufsize, size of BlockBuf (must be >= DVD_VIDEO_LB_LEN). */ static int UDFGetDescriptor( dvd_reader_t *device, int id, uint8_t *descriptor, int bufsize) { uint32_t lbnum, MVDS_location, MVDS_length; struct avdp_t avdp; uint16_t TagID; int i, desc_found = 0; /* Find Anchor */ lbnum = 256; /* Try #1, prime anchor */ if(bufsize < DVD_VIDEO_LB_LEN) return 0; if(!UDFGetAVDP(device, &avdp)) return 0; /* Main volume descriptor */ MVDS_location = avdp.mvds.location; MVDS_length = avdp.mvds.length; i = 1; do { /* Find Descriptor */ lbnum = MVDS_location; do { if( DVDReadLBUDF( device, lbnum++, 1, descriptor, 0 ) <= 0 ) TagID = 0; else UDFDescriptor( descriptor, &TagID ); if( (TagID == id) && ( !desc_found ) ) /* Descriptor */ desc_found = 1; } while( ( lbnum <= MVDS_location + ( MVDS_length - 1 ) / DVD_VIDEO_LB_LEN ) && ( TagID != TerminatingDescriptor ) && ( !desc_found) ); if( !desc_found ) { /* Backup volume descriptor */ MVDS_location = avdp.rvds.location; MVDS_length = avdp.rvds.length; } } while( i-- && ( !desc_found ) ); return desc_found; } static int UDFGetPVD(dvd_reader_t *device, struct pvd_t *pvd) { uint8_t pvd_buf_base[DVD_VIDEO_LB_LEN + 2048]; uint8_t *pvd_buf = (uint8_t *)(((uintptr_t)pvd_buf_base & ~((uintptr_t)2047)) + 2048); if(GetUDFCache(device, PVDCache, 0, pvd)) return 1; if(!UDFGetDescriptor( device, 1, pvd_buf, DVD_VIDEO_LB_LEN)) return 0; memcpy(pvd->VolumeIdentifier, &pvd_buf[24], 32); memcpy(pvd->VolumeSetIdentifier, &pvd_buf[72], 128); SetUDFCache(device, PVDCache, 0, pvd); return 1; } /** * Gets the Volume Identifier string, in 8bit unicode (latin-1) * volid, place to put the string * volid_size, size of the buffer volid points to * returns the size of buffer needed for all data */ int UDFGetVolumeIdentifier(dvd_reader_t *device, char *volid, unsigned int volid_size) { struct pvd_t pvd; unsigned int volid_len; /* get primary volume descriptor */ if(!UDFGetPVD(device, &pvd)) return 0; volid_len = pvd.VolumeIdentifier[31]; if(volid_len > 31) /* this field is only 32 bytes something is wrong */ volid_len = 31; if(volid_size > volid_len) volid_size = volid_len; Unicodedecode(pvd.VolumeIdentifier, volid_size, volid); return volid_len; } /** * Gets the Volume Set Identifier, as a 128-byte dstring (not decoded) * WARNING This is not a null terminated string * volsetid, place to put the data * volsetid_size, size of the buffer volsetid points to * the buffer should be >=128 bytes to store the whole volumesetidentifier * returns the size of the available volsetid information (128) * or 0 on error */ int UDFGetVolumeSetIdentifier(dvd_reader_t *device, uint8_t *volsetid, unsigned int volsetid_size) { struct pvd_t pvd; /* get primary volume descriptor */ if(!UDFGetPVD(device, &pvd)) return 0; if(volsetid_size > 128) volsetid_size = 128; memcpy(volsetid, pvd.VolumeSetIdentifier, volsetid_size); return 128; } k9copy/src/xine/0000755000175000017550000000000012412271774014304 5ustar emulatoremulatork9copy/src/xine/k9xineplayer.h0000644000175000017550000001075012412271774017104 0ustar emulatoremulator/*************************************************************************** * Developer: Pauline123 , (C) 2014 * Copyright (C) 2007 by Jean-Michel * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef K9XINEPLAYER_H #define K9XINEPLAYER_H #include #include #include #include #include #if QT_VERSION >= 0x050000 #include #endif /** @author Jean-Michel */ class k9xineThread; class k9xinePlayer : public QDBusAbstractAdaptor { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "k9copy.free.fr.xineplayer") Q_PROPERTY(QString mrl READ mrl WRITE setMrl) Q_PROPERTY(int width READ width WRITE setWidth) Q_PROPERTY(int height READ height WRITE setHeight) Q_PROPERTY(int position READ position WRITE seek) Q_PROPERTY(int positionAbs READ positionAbs WRITE seek) Q_PROPERTY(int length READ length); Q_PROPERTY(int isRunning READ isRunning) Q_PROPERTY(QString device READ device WRITE setDevice) public: k9xinePlayer(QObject *parent = 0); ~k9xinePlayer(); void init(WId _wid); QString mrl() const {return m_mrl;} void setMrl(const QString &value) {m_mrl=value;} QString device() const {return m_device;} void setDevice (const QString &value) { updateConfigEntry (QString ("input.dvd_device"), value); m_device=value; } int width() {return m_width;} void setWidth(int _value); int height() { return m_height;} void setHeight(int _value); double pixelAspect() { return m_pixelAspect;} int xpos() {return m_xpos;} void setXpos(int _value) { m_xpos=_value;} void setYpos(int _value) { m_ypos=_value;} int ypos() {return m_ypos;} int position() {return m_pos;} int positionAbs() {return m_posabs ;} int length() {return m_length;} xine_stream_t *getStream() { return stream;} xine_video_port_t *getvoport(){return vo_port;} bool isRunning() {return running;} WId wid() const { return m_wid;} QString title() const {return m_title;} void setTitle(const QString &_title) {m_title=_title;} void setVo(const QString& theValue) { m_vo = theValue;} void setAo(const QString& theValue) {m_ao = theValue;} public slots: void setRunning(bool _value) { running=_value;} void setAudioLang (int id); void setSubtitle (int id); void setVolume (int val); void volumeUp(); void volumeDown(); void stop(); void play(); void pause(); void quit(); void execute(); void update(); void updatePosition(); private: QString m_mrl; QString m_device; WId m_wid; Display *display; int screen; int m_xpos, m_ypos, m_width, m_height; double m_pixelAspect; bool running ; int m_length; int m_pos; int m_posabs; bool m_execute; QMutex m_mutex; QString m_title; xine_t *xine; xine_stream_t *stream; xine_video_port_t *vo_port; xine_audio_port_t *ao_port; QString m_vo; QString m_ao; xine_event_queue_t *event_queue; k9xineThread *m_thread; void end(); void seek(int _position); bool updateConfigEntry (const QString & name, const QString & value); }; #endif k9copy/src/xine/main.cpp0000644000175000017550000001212012412271774015730 0ustar emulatoremulator/*************************************************************************** * Developer: Pauline123 , (C) 2014 * Copyright (C) 2007 by Jean-Michel * * k9copy@free.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "config.h" #include "k9xineplayer.h" #if QT_VERSION >= 0x050000 #include #include #include #include #else #include #include #include #endif #include #include #include #include #include #include static const char description[] = I18N_NOOP("A KDE 4 Application"); static const char version[] = VERSION ; int main(int argc, char **argv) { #if QT_VERSION >= 0x050000 KAboutData about("k9xineplayer", i18n("k9copy"), version, i18n(description), KAboutLicense::GPL, i18n("

(C) 2014 Pauline123

" "

(C) 2007 Jean-Michel

"), QStringLiteral("k9copy-reloaded.sourceforge.net"), QString(i18n("

Please report bugs to:

")) + QStringLiteral("

pauline123@users.sourceforge.net

")); about.addAuthor(i18n("Pauline123"), i18n("developer"), "pauline123@users.sourceforge.net", 0); about.addAuthor(i18n("Jean-Michel PETIT"), i18n("developer"), "k9copy@free.fr", 0); QList people = about.authors(); about.addCredit(people[0].name(), people[0].task()); #else KAboutData about("k9xineplayer", 0, ki18n("k9copy"), version, ki18n(description), KAboutData::License_GPL, ki18n("

(C) 2014 Pauline123

" "

(C) 2007 Jean-Michel

"), KLocalizedString(), 0, "pauline123@users.sourceforge.net"); about.addAuthor( ki18n("Pauline123"), KLocalizedString(), "pauline123@users.sourceforge.net" ); about.addAuthor( ki18n("Jean-Michel"), KLocalizedString(), "k9copy@free.fr" ); about.setTranslator(ki18n("_: NAME OF TRANSLATORS\\nYour names") ,ki18n("_: EMAIL OF TRANSLATORS\\nYour emails")); #endif QApplication app(argc, argv,false); #if QT_VERSION >= 0x050000 QCommandLineParser parser; KAboutData::setApplicationData(about); parser.addVersionOption(); parser.addHelpOption(); //PORTING SCRIPT: adapt aboutdata variable if necessary about.setupCommandLine(&parser); parser.process(app); about.processCommandLine(&parser); parser.addOption(QCommandLineOption(QStringList() << QLatin1String("wid"), i18n("wid"), QLatin1String("window id"))); parser.addOption(QCommandLineOption(QStringList() << QLatin1String("vo"), i18n("vo"), QLatin1String("video output"))); parser.addOption(QCommandLineOption(QStringList() << QLatin1String("ao"), i18n("ao"), QLatin1String("audio output"))); #else KCmdLineArgs::init(argc, argv, &about); KCmdLineOptions options; options.add( "wid ", ki18n("wid")); options.add( "vo