{format service} unit srv_format; interface uses windows,wat_api; procedure DefFillFormatList (hwndList:hwnd); procedure DefCheckFormatList(hwndList:hwnd); function ProcessFormatLink:integer; function GetFileFormatInfo(var dst:tSongInfo):integer; function CheckExt(fname:pWideChar):integer; function DeleteKnownExt(src:pWideChar):pWideChar; function KnownFileType(fname:PWideChar):boolean; function isContainer(fname:PWideChar):boolean; function ServiceFormat(wParam:WPARAM;lParam:LPARAM):integer;cdecl; procedure RegisterFormat(ext:PAnsiChar;proc:tReadFormatProc;flags:dword=0); procedure ClearFormats; type MusEnumProc = function(param:PAnsiChar;lParam:LPARAM):bool;stdcall; function EnumFormats(param:MusEnumProc;lParam:LPARAM):bool; type pwFormat = ^twFormat; twFormat = record This:tMusicFormat; Next:pwFormat; end; const FormatLink:pwFormat=nil; implementation uses CommCtrl,common; type pFmtArray = ^tFmtArray; tFmtArray = array [0..10] of tMusicFormat; const StartSize = 32; Step = 8; const fmtLink:pFmtArray=nil; FmtNum:integer=0; FmtMax:integer=0; function ProcessFormatLink:integer; var ptr:pwFormat; begin result:=0; ptr:=FormatLink; while ptr<>nil do begin RegisterFormat(@ptr.This.ext,ptr.This.proc,ptr.This.flags); inc(result); ptr:=ptr^.Next; end; end; function EnumFormats(param:MusEnumProc;lParam:LPARAM):bool; var tmp:pFmtArray; i,j:integer; s:array [0..8] of AnsiChar; begin if (FmtNum>0) and (@param<>nil) then begin GetMem(tmp,FmtNum*SizeOf(tMusicFormat)); move(fmtLink^,tmp^,FmtNum*SizeOf(tMusicFormat)); i:=0; j:=FmtNum; s[8]:=#0; repeat move(tmp^[i].ext,s,8); if not param(s,lParam) then break; inc(i); until i=j; FreeMem(tmp); result:=true; end else result:=false; end; function FindFormat(ext:PAnsiChar):integer; var i:integer; ss:array [0..7] of AnsiChar; begin i:=0; int64(ss):=0; StrCopy(ss,ext,7); while i=0 then begin if (p^.flags and WAT_OPT_DISABLED)=0 then ListView_SetCheckState(hwndList,newItem,TRUE); end; inc(i); end; ListView_SetColumnWidth(hwndList,0,LVSCW_AUTOSIZE); end; procedure DefCheckFormatList(hwndList:hwnd); var i,j,k:integer; item:LV_ITEMA; szTemp:array [0..109] of AnsiChar; p:pMusicFormat; begin FillChar(item,SizeOf(item),0); item.mask:=LVIF_TEXT; item.pszText:=@szTemp; item.cchTextMax:=100; k:=ListView_GetItemCount(hwndList)-1; for i:=0 to k do begin item.iItem:=i; SendMessageA(hwndList,LVM_GETITEMA,0,LPARAM(@item)); j:=FindFormat(item.pszText); if j<>WAT_RES_NOTFOUND then // always? begin p:=@fmtLink^[j]; if ListView_GetCheckState(hwndList,i)=0 then p^.flags:=p^.flags or WAT_OPT_DISABLED else p^.flags:=p^.flags and not WAT_OPT_DISABLED; end; end; end; function DeleteKnownExt(src:pWideChar):pWideChar; var s :array [0..7] of WideChar; ss:array [0..7] of AnsiChar; i,j:integer; begin GetExt(src,s); if s[0]<>#0 then begin int64(ss):=0; i:=0; while (s[i]<>#0) and (i<8) do begin ss[i]:=AnsiChar(s[i]); inc(i); end; j:=0; while j#0 then begin i:=0; while (s[i]<>#0) and (i<8) do begin ss[i]:=AnsiChar(s[i]); inc(i); end; i:=0; while i0; end else result:=false; end; function GetFileFormatInfo(var dst:tSongInfo):integer; begin result:=CheckExt(dst.mfile); if result=WAT_RES_OK then begin fmtLink^[0].proc(dst); end; end; function CheckExt(fname:pWideChar):integer; var i:integer; tmp:tMusicFormat; ls:array [0..7] of WideChar; ss:array [0..7] of AnsiChar; begin GetExt(fname,ls); i:=0; int64(ss):=0; while (ls[i]<>#0) and (i<8) do begin ss[i]:=AnsiChar(ls[i]); inc(i); end; i:=0; while i0 then begin tmp:=fmtLink^[i]; move(fmtLink^[0],fmtLink^[1],SizeOf(tMusicFormat)*i); fmtLink^[0]:=tmp; end; result:=WAT_RES_OK; exit; end else break; end; inc(i); end; result:=WAT_RES_NOTFOUND; end; function ServiceFormat(wParam:WPARAM;lParam:LPARAM):integer;cdecl; var p:integer; nl:pFmtArray; begin result:=WAT_RES_NOTFOUND; if LoWord(wParam)<>WAT_ACT_REGISTER then p:=FindFormat(PAnsiChar(lParam)) else p:=0; case LoWord(wParam) of WAT_ACT_REGISTER: begin if @pMusicFormat(lParam)^.proc=nil then exit; p:=FindFormat(pMusicFormat(lParam)^.ext); if (p=WAT_RES_NOTFOUND) or ((wParam and WAT_ACT_REPLACE)<>0) then begin if (p<>WAT_RES_NOTFOUND) and ((fmtLink^[p].flags and WAT_OPT_ONLYONE)<>0) then exit; if FmtNum=FmtMax then // expand array when append begin if FmtMax=0 then FmtMax:=StartSize else inc(FmtMax,Step); GetMem(nl,FmtMax*SizeOf(tMusicFormat)); if fmtLink<>nil then begin move(fmtLink^,nl^,FmtNum*SizeOf(tMusicFormat)); FreeMem(fmtLink); end; fmtLink:=nl; end; if p=WAT_RES_NOTFOUND then begin p:=FmtNum; result:=WAT_RES_OK; inc(FmtNum); end else result:=int_ptr(@fmtLink^[p].proc); move(pMusicFormat(lParam)^,fmtLink^[p],SizeOf(tMusicFormat));// fill end; end; WAT_ACT_UNREGISTER: begin if p<>WAT_RES_NOTFOUND then begin dec(FmtNum); if pWAT_RES_NOTFOUND then begin fmtLink^[p].flags:=fmtLink^[p].flags or WAT_OPT_DISABLED; result:=WAT_RES_DISABLED end; end; WAT_ACT_ENABLE: begin if p<>WAT_RES_NOTFOUND then begin fmtLink^[p].flags:=fmtLink^[p].flags and not WAT_OPT_DISABLED; result:=WAT_RES_ENABLED end; end; WAT_ACT_GETSTATUS: begin if p<>WAT_RES_NOTFOUND then begin if (fmtLink^[p].flags and WAT_OPT_DISABLED)<>0 then result:=WAT_RES_DISABLED else result:=WAT_RES_ENABLED; end; end; end; end; procedure RegisterFormat(ext:PAnsiChar;proc:tReadFormatProc;flags:dword=0); var tmp:tMusicFormat; begin FillChar(tmp,SizeOf(tMusicFormat),0); StrCopy (tmp.ext,ext,7); tmp.proc:=proc; tmp.flags:=flags; ServiceFormat(WAT_ACT_REGISTER,LPARAM(@tmp)); end; procedure ClearFormats; begin if FmtNum>0 then FreeMem(fmtLink); end; end.