unit global; {* * EMPRIP - Global declarations and procedures * Windows CD Audio extraction and MP3 Encoder * (C) 2003 Matthew J. Smith, Librarysmith Software * Based on AKRIP (http://akrip.sourceforge.net) cddb and audio extraction library * and the LAME projects (http://wwww.mp3dev.org) LAME_ENC.DLL. * * 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 Lesser 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 *} interface uses akrip32,sysutils,windows,extctrls,jpeg,forms,filectrl,graphics,classes; type talbums = record titles : array of string; artists : array of string; count : integer; end; type tfilterstrings = record data : array of string; count : integer; end; type tfilter = record genre : tfilterstrings; artist : tfilterstrings; keywords : tfilterstrings; recordlabel : tfilterstrings; excludecompilations : boolean; excludenoncompilations : boolean; yearlower : integer; yearupper : integer; decadelower : integer; decadeupper : integer; end; type tskin = record Skin : string; Color : longint; end; type ttheme = record //SKINS sbut : tskin; skeypad : tskin; slcorner : tskin; srcorner : tskin; sblcorner : tskin; sbrcorner : tskin; salphabuttons : tskin; swidebut : tskin; sbackground : tskin; alphaorientation : integer; name : string; end; type Tconfig = record path : string; volume : integer; Dj_default : boolean; Dj_comment : boolean; lastalbum : integer; dlastalbum : integer; jlastalbum : integer; auditiontimeout : integer; burnpath : string; screensaverpath : string; bgcolor : dword; bordercolor : dword; bgstyle : integer; borderstyle : byte; cdopt: byte; timeannounce : boolean; hidepanel : boolean; hideexit : boolean; litewarn : boolean; defaultfilteron : boolean; defaultfilter : tfilter; mediaplayermode : boolean; username : string; serial : string; autoplay : boolean; lock : boolean; password : string; jukeboxaddall : boolean; jukeboxvolumepanel : boolean; bitrate : integer; cddbserver :string; cddbcgi : string; email : string; norepeat : boolean; networksettings : string; copytrackdest : string; monitor : integer; videomonitor : integer; errorlog : string; fontsize : integer; showminimize : integer; poweroff : boolean; theme : ttheme; wraponunderscore : boolean; //Commercial creditsystem : boolean; playspercoincredit : integer; allowfreecredit : boolean; bgvolumemax : integer; bgvolume : integer; bgduration : integer; bgwaittime : integer; trackslogfile : string; credittotal : int64; freecredittotal : int64; //3D disable3d : boolean; end; const apptitle='EmpRip'; const appversion='1.0'; const DEFAULTFONT='Garamond'; {$IFDEF kiosk} JUKEBOXFONT=DEFAULTFONT; {$ENDIF} {$IFNDEF kiosk} JUKEBOXFONT=DEFAULTFONT; {$ENDIF} var cdhandle : HCDROM; tracks : array of string; artist,title : string; trackscount : integer; albumpath : string; bitrate : integer; starttime : tdatetime; firstrun : boolean; config : tconfig; cachepath : string; mshand : thandle; procedure split(s,ch : string;var l,r : string); function replacespecial(a : string) : string; function stripbadchars(a : string) : string; function Myloadbitmap(target : timage;rc : string) : longint; function extractalbumandaristfrompath(s : string;var artist : string;var album : string) : string; function loadtitles (path : string) : boolean; function getfirstcddriveletter : string; procedure deletealbum(i : integer); procedure addalbum(art,alb : string); function hmsdisplay(s : integer) : string; function getmp3length(fn : string) : integer; function stripnulls(p : array of char) : string; procedure moveformtomonitor(f : tform); procedure generatecover(pic : tbitmap;title : string); function validname(s : string) : boolean; function getalbumsize (pathtoalbum : string;var filecount : longint;var mp3count : integer;cancel : boolean) : tlargeinteger; Procedure CutOutWindowFromMask(hwnd : THandle;mask : Timage); procedure Antialiasing(Image: TImage; Percent: Integer); function checkfileextension(fn : string) : boolean; function W32FileSize(const FileName: string): Int64; overload; type TWAVEHDR = packed record riff : array[0..3] of byte; len : dword; cWavFmt : array[0..7] of byte; dwHdrLen : dword; wFormat : word; wNumChannels : word; dwSampleRate : dword; dwBytesPerSec : dword; wBlockAlign : word; wBitsPerSample : word; cData : array [0..3] of byte; dwDataLen : DWORD; end; implementation uses empripmain,main,jukeboxform,loadjpegorbmp; function W32FileSize(const FileName: string): Int64; overload; var AttributeData: TWin32FileAttributeData; begin if not GetFileAttributesEx(PChar(FileName), GetFileExInfoStandard, @AttributeData) then RaiseLastOSError; Int64Rec(Result).Lo := AttributeData.nFileSizeLow; Int64Rec(Result).Hi := AttributeData.nFileSizeHigh; end; function checkfileextension(fn : string) : boolean; var ext : string; begin ext:=uppercase(ExtractFileExt(fn)); result:=false; if (ext='.MP3') then result:=true; if (ext='.MPG') then result:=true; if (ext='.MPEG') then result:=true; if (ext='.FLAC') then result:=true; if (ext='.FLA') then result:=true; if (ext='.WMA') then result:=true; if (ext='.WMV') then result:=true; if (ext='.OGG') then result:=true; end; Procedure CutOutWindowFromMask(hwnd : THandle;mask : Timage); var x,y,xx : integer; bInTransparent : boolean; xStartTransparent : integer; hRgnTemp : HRGN; hRgnOut: HRGN; Line : PByteArray; r,g,b : integer; begin if mask.width=0 then exit; xStartTransparent:=0; bInTransparent:=false; xx:=0; hRgnOut:= CreateRectRgn(0,0,mask.width,mask.height); with mask.Canvas do begin for y:= 0 to mask.Height-1 do begin Line:=mask.Picture.Bitmap.ScanLine[y]; x:=1; while( x<mask.Width-1) do begin r:=line[(x*3)-1]; g:=line[(x*3)]; b:=line[(x*3)+1]; outputdebugstring(pchar('SCAN:'+inttostr(rgb(r,g,b)))); outputdebugstring(pchar('PIXL:'+inttostr(mask.canvas.pixels[x,y]))); If (rgb(r,g,b) = rgb(255,255,255)) Then begin If Not bInTransparent Then begin bInTransparent:= True; xStartTransparent:= x; end; end else begin If bInTransparent Then begin hRgnTemp:= CreateRectRgn(xStartTransparent,y,x,y+1); CombineRgn(hRgnOut, hRgnOut,hRgnTemp, RGN_XOR); deleteobject(hRgnTemp); bInTransparent := False; End; end; xx:=x; inc(x); End; If bInTransparent Then begin hRgnTemp := CreateRectRgn(xStartTransparent,y,xx,y+1); CombineRgn (hRgnOut, hRgnOut,hRgnTemp, RGN_XOR); DeleteObject(hRgnTemp); bInTransparent:= False End; End; End; //hRgnOut:=createrectrgn(200,20,250,40); if setwindowrgn(hwnd,hRgnOut,false)=0 then begin beep(100,100); end; end; //Uses Pixels - slow as hell {Procedure CutOutWindowFromMask(hwnd : THandle;mask : Timage); var x,y,yy : integer; bInTransparent : boolean; yStartTransparent : integer; hRgnTemp : HRGN; hRgnOut: HRGN; trancolor : TColor; begin if mask.width=0 then exit; yStartTransparent:=0; bInTransparent:=false; yy:=0; hRgnOut:= CreateRectRgn(0,0,mask.width,mask.height); with mask.Canvas do begin trancolor:=(rgb(255,255,255)); for x:= -1 to mask.Width do begin For y := 0 to mask.Height do begin If Pixels[x,y] = trancolor Then begin If Not bInTransparent Then begin bInTransparent:= True; yStartTransparent:= y; end; end else begin If bInTransparent Then begin hRgnTemp:= CreateRectRgn(x,yStartTransparent,x+1,y); CombineRgn(hRgnOut, hRgnOut,hRgnTemp, RGN_XOR); deleteobject(hRgnTemp); bInTransparent := False; End; end; yy:=y; End; If bInTransparent Then begin hRgnTemp := CreateRectRgn(x,yStartTransparent,x+1,yy); CombineRgn (hRgnOut, hRgnOut,hRgnTemp, RGN_XOR); DeleteObject(hRgnTemp); bInTransparent:= False End; End; End; //hRgnOut:=createrectrgn(200,20,250,40); if setwindowrgn(hwnd,hRgnOut,false)=0 then begin beep(100,100); end; end; } procedure moveformtomonitor(f : tform); var br : trect; begin if config.monitor<>0 then begin br:=screen.Monitors[config.monitor].BoundsRect; f.left:=br.left+(((br.Right-br.left) div 2) - (f.width div 2)); end; end; procedure addalbum(art,alb : string); var o : tbitmap; spp : string; isodd : boolean; begin inc(main.albumcount); setlength(main.album,main.albumcount+1); main.album[main.albumcount].artist:=art; main.album[main.albumcount].album:=alb; mainform.Dalbumlist.Items.Add(art+' - '+alb); mainform.albumlist.Items.Add(art+' - '+alb); spp:=config.path+art+'__'+alb; try o:=tbitmap.create; loadjpegbmp(spp,o); jukebox.thumbs.add(o,mainform.albumlist.Items.Count-1); o.free; except end; isodd:=false; jalbumcount:=albumcount; if jalbumcount mod 2 = 1 then begin inc(jalbumcount); isodd:=true; end; jalbum:=album; setlength(jalbum,jalbumcount+1); if isodd=true then begin jalbum[jalbumcount].artist:=chr(12); setlength(thumb,jalbumcount); end; {if jalbumcount mod 2 =0 then begin jalbumcount:=jalbumcount+2; setlength(jalbum,jalbumcount+1); jalbum[jalbumcount].artist:=chr(12); jalbum[jalbumcount].album:=''; jalbum[jalbumcount-1].artist:=artist; jalbum[jalbumcount-1].album:=album; end else begin inc(jalbumcount); setlength(jalbum,jalbumcount+1); jalbum[jalbumcount].artist:=chr(12); jalbum[jalbumcount].album:=''; jalbum[jalbumcount-1].artist:=artist; jalbum[jalbumcount-1].album:=album; end;} end; procedure deletealbum(i : integer); var n : integer; isodd : boolean; begin setlength(album,albumcount+2); setlength(jalbum,albumcount+2); album[albumcount+1].artist:=''; album[albumcount+1].album:=''; jalbum[albumcount+1].artist:=''; jalbum[albumcount+1].album:=''; for n:=i to albumcount do begin main.album[n]:=main.album[n+1]; jalbum[n]:=jalbum[n+1]; end; setlength(album,albumcount+1); setlength(jalbum,jalbumcount+1); dec(albumcount); mainform.Dalbumlist.Items.delete(i-1); mainform.albumlist.Items.delete(i-1); jukebox.thumbs.delete(i-1); dec(jalbumcount); isodd:=false; jalbumcount:=albumcount; if jalbumcount mod 2 = 1 then begin inc(jalbumcount); isodd:=true; end; jalbum:=album; setlength(jalbum,jalbumcount+1); if isodd=true then begin jalbum[jalbumcount].artist:=chr(12); setlength(thumb,jalbumcount); end; end; function Myloadbitmap(target : timage;rc : string) : longint; begin result:=0; try target.picture.bitmap.loadfromresourcename(hInstance,rc); except; result:=-1; end; end; procedure split(s,ch : string;var l,r : string); var n,mde : integer; begin mde:=0; l:=''; r:=''; for n:=1 to length(s) do begin if s[n]=ch then mde:=1; if mde=0 then l:=l+s[n]; if (mde=1) and (s[n]<>ch) then r:=r+s[n]; end; end; function replacespecial(a : string) : string; var n : integer; s : string; begin s:=a; s:=trimright(trimleft(uppercase(s))); for n:=1 to length(s) do begin if (s[n]<#65) or (s[n]>#90) then s[n]:='+'; end; result:=s; end; function stripbadchars(a : string) : string; var good : boolean; n : integer; begin result:=''; for n:=1 to length(a) do begin good:=true; if a[n]='\' then good:=false; if a[n]='/' then good:=false; if a[n]=':' then good:=false; if a[n]='*' then good:=false; if a[n]='?' then good:=false; if a[n]='"' then good:=false; if a[n]='>' then good:=false; if a[n]='<' then good:=false; if a[n]='|' then good:=false; if good=true then result:=result+a[n]; end; if length(result)>255 then result:=copy(result,1,255); end; function extractalbumandaristfrompath(s : string;var artist : string;var album : string) : string; var x : integer; a : integer; begin a:=1; while(a<>0) do begin a:=pos('\',s); s:=copy(s,a+1,length(s)-a); end; //s:=copy(s,length(config.pathtocd)+1,(length(s)-length(config.pathtocd))); x:=pos('__',s); artist:=copy(s,0,x-1); album:=copy(s,x+2,length(s)-x+2); result:=album+' - '+artist; end; function loadtitles ( path : string) : boolean; var content : textfile; spp : string; begin result:=false; if directoryexists(path+'\')=false then begin;exit;end; AssignFile(content,path+'\title.dat'); try Reset(content); except; result:=true; exit; end; trackscount:=0; While (NOT EOF(content)) do begin Readln (content,spp); //tracklist.items.add('['+format('%.2d',[tracknm])+'] - '+spp); setlength(tracks,trackscount+1); if spp<>'' then begin tracks[trackscount]:=spp end else tracks[trackscount]:=('Unknown track name'); inc(trackscount); end; CloseFile(content); result:=true; end; function getfirstcddriveletter : string; var dvs : array[0..256] of char; dv : pchar; res : integer; begin result:=''; res:=getlogicaldrivestrings(sizeof(dvs),dvs); if res=0 then exit; dv:=@dvs; while dv^<>#0 do begin if getdrivetype(dv) = DRIVE_CDROM then begin result:=dv; exit; end; inc (dv,4); end; end; function hmsdisplay(s : integer) : string; var ss,m,mm,h : integer; begin ss:=s mod 60; m:=round(int((s-ss)/60)); mm:=m mod 60; h:=round(int((m-mm)/60)); if (h>0) then result:=format('%.2d',[h])+':'+format('%.2d',[mm])+':'+format('%.2d',[ss]) else result:=(format('%.2d',[mm])+':'+format('%.2d',[ss])); end; function getmp3length(fn : string) : integer; var f : file; b : byte; bitrate : integer; begin fn:=uppercase(fn); assignfile(f,fn); FileMode := fmOpenRead; reset(f,1); seek(f,2); blockread(f,b,1); b:=round((b and 240) / 16); bitrate:=1; case b of 0: BitRate := -1; 1: BitRate := 32; 2: BitRate := 40; 3: BitRate := 48; 4: BitRate := 56; 5: BitRate := 64; 6: BitRate := 80; 7: BitRate := 96; 8: BitRate := 112; 9: BitRate := 128; 10: BitRate := 160; 11: BitRate := 192; 12: BitRate := 224; 13: BitRate := 256; 14: BitRate := 320; end; //result:= round(filesize(f)/(bitrate/8)/1000); result:= round(int(((8 * filesize(f)) /1000) /bitrate)); closefile(f); //secs:= tsecs mod 60; //mins:= tsecs div 60; end; function stripnulls(p : array of char) : string; var n : integer; begin result:=''; for n := 0 to length(p)-1 do begin if p[n]<>#0 then result:=result+p[n]; end; end; procedure generatecover(pic : tbitmap;title : string); var tr : trect; x,g : integer; bmp : tbitmap; begin randomize; pic.width:=300; pic.height:=300; for x := 0 to 15 do begin //x1:=random(pics[n].width); //y1:=random(pics[n].height); tr.Left:=random(300)-random(100); tr.Right:=random(300); tr.Top:=random(300)-random(100); tr.Bottom:=random(300); pic.canvas.Pen.Color:=rgb(random(250),random(250),random(250)); pic.canvas.Brush.Color:=pic.canvas.Pen.Color; pic.Canvas.Pen.Width:=random(4); if random(4) mod 2 <> 0 then pic.Canvas.Brush.Style:=bsClear else pic.Canvas.Brush.Style:=bsSolid; if random(2) mod 2 = 0 then pic.canvas.Ellipse(tr) else pic.canvas.Rectangle(tr); end; bmp:=tbitmap.create; bmp.width:=300; bmp.height:=300; alphablendbitmapwithcolor(pic,rgb(128,random(128),random(255)),pic,0.2); for g := 0 to 30 do begin with pic do begin Canvas.Brush.style:=bsClear; Canvas.Font.name:=DEFAULTFONT; canvas.Font.Color:=rgb(random(255),random(255),random(255)); canvas.font.size:=random(10); Canvas.TextOut(random(300)-random(100),random(300),uppercase(title)); end; end; bmp.free; end; function validname(s : string) : boolean; begin result:=true; if pos('_',s)<>0 then result:=false; if pos('__',s)<>0 then result:=false; if pos('-',s)<>0 then result:=false; if pos('+',s)<>0 then result:=false; if pos('/',s)<>0 then result:=false; if pos('\',s)<>0 then result:=false; if pos(':',s)<>0 then result:=false; if pos('*',s)<>0 then result:=false; if pos('?',s)<>0 then result:=false; if pos('"',s)<>0 then result:=false; if pos('<',s)<>0 then result:=false; if pos('>',s)<>0 then result:=false; if pos('|',s)<>0 then result:=false; if length(trim(s))=0 then result:=false; end; function getalbumsize (pathtoalbum : string;var filecount : longint;var mp3count : integer;cancel : boolean) : tlargeinteger; var searchrec : tsearchrec; res : integer; begin result:=0; res:=FindFirst(pathtoalbum+'\*.mp3', faanyfile, searchrec); if (res=0) and (cancel=false) then begin while (res=0) do begin if fileexists(pathtoalbum+'\'+searchrec.name) then begin inc(filecount); inc(mp3count); result:=result+getcompressedfilesize(pchar(pathtoalbum+'\'+searchrec.name),nil); application.processmessages; res:=findnext(searchrec); end; end; end; if fileexists(pathtoalbum+'\info.dat') then begin inc(filecount); result:=result+getcompressedfilesize(pchar(pathtoalbum+'\info.dat'),nil); application.processmessages; end; if fileexists(pathtoalbum+'\title.dat') then begin inc(filecount); result:=result+getcompressedfilesize(pchar(pathtoalbum+'\title.dat'),nil); application.processmessages; end; if fileexists(pathtoalbum+'\title.jpg') then begin inc(filecount); result:=result+getcompressedfilesize(pchar(pathtoalbum+'\title.jpg'),nil); application.processmessages; end; if fileexists(pathtoalbum+'\title.bmp') then begin inc(filecount); result:=result+getcompressedfilesize(pchar(pathtoalbum+'\title.bmp'),nil); application.processmessages; end; if fileexists(pathtoalbum+'\title.jpeg') then begin inc(filecount); result:=result+getcompressedfilesize(pchar(pathtoalbum+'\title.jpeg'),nil); application.processmessages; end; sysutils.FindClose(SearchRec); end; procedure Antialiasing(Image: TImage; Percent: Integer); type TRGBTripleArray = array[0..32767] of TRGBTriple; PRGBTripleArray = ^TRGBTripleArray; var SL, SL2: PRGBTripleArray; l, m, p: Integer; R, G, B: TColor; R1, R2, G1, G2, B1, B2: Byte; begin if slowprocessor=true then exit; if screen.width=1024 then exit; with Image.Canvas do begin Brush.Style := bsClear; Pixels[1, 1] := Pixels[1, 1]; for l := 0 to Image.picture.Height - 1 do begin SL := Image.Picture.Bitmap.ScanLine[l]; for p := 1 to Image.picture.Width - 1 do begin R1 := SL[p].rgbtRed; G1 := SL[p].rgbtGreen; B1 := SL[p].rgbtBlue; // Left if (p < 1) then m := Image.picture.Width else m := p - 1; R2 := SL[m].rgbtRed; G2 := SL[m].rgbtGreen; B2 := SL[m].rgbtBlue; if (R1 <> R2) or (G1 <> G2) or (B1 <> B2) then begin R := Round(R1 + (R2 - R1) * 50 / (Percent + 50)); G := Round(G1 + (G2 - G1) * 50 / (Percent + 50)); B := Round(B1 + (B2 - B1) * 50 / (Percent + 50)); SL[m].rgbtRed := R; SL[m].rgbtGreen := G; SL[m].rgbtBlue := B; end; //Right if (p > Image.picture.Width - 2) then m := 0 else m := p + 1; R2 := SL[m].rgbtRed; G2 := SL[m].rgbtGreen; B2 := SL[m].rgbtBlue; if (R1 <> R2) or (G1 <> G2) or (B1 <> B2) then begin R := Round(R1 + (R2 - R1) * 50 / (Percent + 50)); G := Round(G1 + (G2 - G1) * 50 / (Percent + 50)); B := Round(B1 + (B2 - B1) * 50 / (Percent + 50)); SL[m].rgbtRed := R; SL[m].rgbtGreen := G; SL[m].rgbtBlue := B; end; if (l < 1) then m := Image.picture.Height - 1 else m := l - 1; //Over SL2 := Image.Picture.Bitmap.ScanLine[m]; R2 := SL2[p].rgbtRed; G2 := SL2[p].rgbtGreen; B2 := SL2[p].rgbtBlue; if (R1 <> R2) or (G1 <> G2) or (B1 <> B2) then begin R := Round(R1 + (R2 - R1) * 50 / (Percent + 50)); G := Round(G1 + (G2 - G1) * 50 / (Percent + 50)); B := Round(B1 + (B2 - B1) * 50 / (Percent + 50)); SL2[p].rgbtRed := R; SL2[p].rgbtGreen := G; SL2[p].rgbtBlue := B; end; if (l > Image.picture.Height - 2) then m := 0 else m := l + 1; //Under SL2 := Image.Picture.Bitmap.ScanLine[m]; R2 := SL2[p].rgbtRed; G2 := SL2[p].rgbtGreen; B2 := SL2[p].rgbtBlue; if (R1 <> R2) or (G1 <> G2) or (B1 <> B2) then begin R := Round(R1 + (R2 - R1) * 50 / (Percent + 50)); G := Round(G1 + (G2 - G1) * 50 / (Percent + 50)); B := Round(B1 + (B2 - B1) * 50 / (Percent + 50)); SL2[p].rgbtRed := R; SL2[p].rgbtGreen := G; SL2[p].rgbtBlue := B; end; end; end; end; end; end.