FIX: AudioInfo - read IDv2.4 with UTF-8 encoding (fixes #723)

This commit is contained in:
Alexander Koblov 2022-12-18 23:17:09 +03:00
commit d660b14965

View file

@ -132,7 +132,7 @@ type
implementation
uses
LazUTF8, DCConvertEncoding;
LazUTF8, DCConvertEncoding, DCUnicodeUtils;
const
{ ID3v2 tag ID }
@ -155,8 +155,9 @@ const
ID3V2_MAX_SIZE = 4096;
{ Unicode ID }
UTF16_ID = #01;
UTF8_ID = #03;
UTF16LE_ID = #01;
UTF16BE_ID = #02;
UTF8_ID = #03;
type
{ Frame header (ID3v2.3.x & ID3v2.4.x) }
@ -239,7 +240,7 @@ begin
FrameID := ID3V2_FRAME_NEW[Iterator]
else
FrameID := ID3V2_FRAME_OLD[Iterator];
if (FrameID = ID) and (Data[1] <= UTF16_ID) then
if (FrameID = ID) and (Data[1] <= UTF8_ID) then
Tag.Frame[Iterator] := Data;
end;
end;
@ -262,6 +263,7 @@ end;
procedure ReadFramesNew(const FileName: String; var Tag: TagInfo);
var
ASize: Cardinal;
SourceFile: TFileStreamEx;
Frame: FrameHeaderNew;
Data: array [1..500] of Char;
@ -272,6 +274,12 @@ begin
{ Set read-access, open file }
SourceFile := TFileStreamEx.Create(FileName, fmOpenRead or fmShareDenyWrite);
SourceFile.Seek(10, soFromBeginning);
// ID3v2 extended header
if Tag.Flags and $40 = $40 then
begin
ASize:= BEToN(SourceFile.ReadDWord);
SourceFile.Seek(ASize - 4, soFromCurrent);
end;
while (SourceFile.Position < GetTagSize(Tag)) and (SourceFile.Position < SourceFile.Size) do
begin
FillChar(Data, SizeOf(Data), 0);
@ -330,26 +338,12 @@ end;
{ --------------------------------------------------------------------------- }
function GetStringUtf8(const Source: string): string;
var
Index: Integer;
UnicodeChar: WideChar;
WideResult: UnicodeString;
FirstByte, SecondByte: Byte;
begin
{ Convert string from unicode if needed and trim spaces }
if (Length(Source) > 0) and (Source[1] = UTF16_ID) then
begin
WideResult := '';
for Index := 1 to ((Length(Source) - 1) div 2) do
begin
FirstByte := Ord(Source[Index * 2]);
SecondByte := Ord(Source[Index * 2 + 1]);
UnicodeChar := WideChar(FirstByte or (SecondByte shl 8));
if UnicodeChar = #0 then break;
if FirstByte < $FF then WideResult := WideResult + UnicodeChar;
end;
Result := UTF16ToUTF8(Trim(WideResult));
end
if (Length(Source) > 0) and (Source[1] = UTF16LE_ID) then
Result := Trim(Utf16LEToUtf8(Copy(Source, 2, MaxInt)))
else if (Length(Source) > 0) and (Source[1] = UTF16BE_ID) then
Result := Trim(Utf16BEToUtf8(Copy(Source, 2, MaxInt)))
else if (Length(Source) > 0) and (Source[1] = UTF8_ID) then
Result := Trim(Copy(Source, 2, MaxInt))
else
@ -412,10 +406,16 @@ begin
if Length(Source) > 0 then
begin
EncodingID := Source[1];
if EncodingID = UTF16_ID then Separator := #0#0
else Separator := #0;
if LanguageID then Delete(Source, 1, 4)
else Delete(Source, 1, 1);
if EncodingID in [UTF16LE_ID, UTF16BE_ID] then
Separator := #0#0
else begin
Separator := #0;
end;
if LanguageID then
Delete(Source, 1, 4)
else begin
Delete(Source, 1, 1);
end;
Delete(Source, 1, Pos(Separator, Source) + Length(Separator) - 1);
Result := GetStringUtf8(EncodingID + Source);
end;