function getAlbumGUID(filename :
string;
var GUID : TGUID) : boolean;
const
TAG_INDICATOR_LENGTH = 3;
TAG_TYPE = '
ID3';
TAG_MAJOR = 3;
TAG_MINOR = 0;
HEADER_SIZE_BEGIN = 6;
HEADER_SIZE_END = 9;
EXTENDED_HEADER_POS = 5;
EXTENDED_HEADER_SIZE_LENGTH = 4;
FRAME_HEADER_LENGTH = 10;
FRAME_ID_LENGTH = 4;
FRAME_MEDIA_PLAYER_OWNER1 = '
WM/WMCollectionID';
FRAME_MEDIA_PLAYER_OWNER2 = '
WM/WMCollectionGroupID';
FRAME_MEDIA_PLAYER_ID = '
PRIV';
FRAME_SIZE_BEGIN = 4;
FRAME_SIZE_END = 7;
retValue = false;
HEADER_LENGTH = 10;
var
Stream : TFileStream;
Header10 :
array[0..HEADER_LENGTH-1]
of byte;
extHeaderData :
array[0..EXTENDED_HEADER_SIZE_LENGTH-1]
of byte;
frameHeader :
array[0..FRAME_HEADER_LENGTH-1]
of byte;
i : integer;
tagType :
string[TAG_INDICATOR_LENGTH];
majorVersion : integer;
minorVersion : integer;
extHeader : LongBool;
extHeaderSize : integer;
tagSize : integer;
currPos : integer;
frameType :
string;
frameLength : integer;
owner : pAnsiChar;
FrameData : pAnsiChar;
b : byte;
Test :
array [0..2000]
of AnsiChar;
begin
try
// read in file
Stream := TFileStream.Create(filename , fmOpenRead);
Stream.Position := 0;
stream.
Read(Header10, HEADER_LENGTH);
tagType := '
';
for i := 0
to TAG_INDICATOR_LENGTH
do
tagType := tagType + AnsiChar(Header10[i]);
majorVersion := integer(Header10[TAG_INDICATOR_LENGTH]);
minorVersion := integer(Header10[TAG_INDICATOR_LENGTH + 1]);
if (tagType = TAG_TYPE)
and (majorVersion = TAG_MAJOR)
and (minorVersion = TAG_MINOR)
then begin
// get extended header bit
extHeader := bool(Header10[EXTENDED_HEADER_POS]
and $10);
// get size of extended header
extHeaderSize := 0;
if extHeader
then begin
Stream.seek(HEADER_LENGTH, soBeginning);
Stream.
read(extHeaderData, EXTENDED_HEADER_SIZE_LENGTH);
for i := 0
to EXTENDED_HEADER_SIZE_LENGTH
do begin
extHeaderSize := ROL(extHeaderSize , 8);
extHeaderSize := extHeaderSize
or extHeaderData[i];
end;
extHeaderSize := extHeaderSize + EXTENDED_HEADER_SIZE_LENGTH;
end;
// get size of tag.
// 4 bytes with the most significant bit ignored
tagSize := 0;
for i := HEADER_SIZE_BEGIN
to HEADER_SIZE_END
do begin
tagSize := ROL(tagSize, 7);
tagSize := tagSize
or (Header10[i]
and $7f);
end;
// tagSize includes extended header
tagSize := tagSize + HEADER_LENGTH;
// read tags
currPos := HEADER_LENGTH + extHeaderSize;
while (currPos < tagSize)
do begin
Stream.seek(currPos, soBeginning);
Stream.
read(frameHeader, FRAME_HEADER_LENGTH);
frameType := '
';
// frame id
for i := 0
to FRAME_ID_LENGTH -1
do
frameType := frameType + char(frameHeader[i]);
// frame length
frameLength := 0;
for i := FRAME_SIZE_BEGIN
to FRAME_SIZE_END
do begin
frameLength := ROL(frameLength, 8);
frameLength := frameLength
or frameHeader[i];
end;
if frameType = FRAME_MEDIA_PLAYER_ID
then begin
frameData :=
nil;
GetMem(frameData , frameLength);
fillChar(frameData^ , frameLength , 0);
stream.
read(frameData^, frameLength);
owner := frameData;
if (owner = FRAME_MEDIA_PLAYER_OWNER1)
or (owner = FRAME_MEDIA_PLAYER_OWNER2)
then begin
CopyMemory ( @
guid, frameData + length(owner) , SizeOf(TGUID));
CopyMemory ( @Test, frameData + length(owner) , SizeOf(TGUID));
Result := true;
exit;
end;
if frameData <>
nil then
FreeMem(frameData);
end;
currPos := currPos + FRAME_HEADER_LENGTH + frameLength;
end;
end;
finally
if frameData <>
nil then
FreeMem(frameData);
Stream.Free;
end;
Result := false;
end;