• R/O
  • SSH
  • HTTPS

id3v2editorplus: Commit


Commit MetaInfo

Revision30 (tree)
Zeit2019-09-18 07:02:20
Autorderekwildstar

Log Message

- Corrigido o carregamento de SYLT

Ändern Zusammenfassung

Diff

--- trunk/V2/src/UClassesAjudantes.pas (revision 29)
+++ trunk/V2/src/UClassesAjudantes.pas (revision 30)
@@ -97,6 +97,8 @@
9797 { TID3v2TagHelper }
9898
9999 procedure TID3v2TagHelper.AtribuirSYLT(const ASYLT: TSYLT);
100+var
101+ RotuloDeTempo: Cardinal;
100102 begin
101103 ExcluirTodosOsFrames('SYLT');
102104
@@ -106,6 +108,11 @@
106108 var Dados: TBytes;
107109 var Letra: TSYLTVerso;
108110
111+ // Configura o array Dados para que ele tenha 3 bytes, pois, tirando a
112+ // letra sincronizada, esta é a maior quantidade de dados que serão
113+ // escritos no Stream do frame. Isso evita ter que ficar usando SetLength
114+ SetLength(Dados,3);
115+
109116 for var SYLT: TCollectionItem in ASYLT do
110117 begin
111118 // O cabeçalho de um frame ID3v2 é:
@@ -127,11 +134,6 @@
127134 // aqui é manipular o membro Stream e definir o conteúdo do frame
128135 with Frames[AddFrame('SYLT')] do
129136 begin
130- // Configura o array Dados para que ele tenha 3 bytes, pois, tirando a
131- // letra sincronizada, esta é a maior quantidade de dados que serão
132- // escritos no Stream do frame. Isso evita ter que ficar usando SetLength
133- SetLength(Dados,3);
134-
135137 // Text Encoding (UNICODE sempre)
136138 Dados[0] := $01;
137139 Stream.Write(Dados, 1);
@@ -165,49 +167,10 @@
165167 Dados[0] := $FE;
166168 Stream.Write(Dados, 1);
167169 Stream.Write(PWideChar(Letra.Texto)^, (Length(Letra.Texto) + 1) * 2);
170+ RotuloDeTempo := SwapEndian32(Letra.Tempo);
171+ Stream.Write(RotuloDeTempo,4);
168172 end;
169-
170-
171-
172-
173-
174-
175-
176-
177-
178-
179-
180-// Frames[FrameIndex].Stream.Clear;
181-// Data := $01;
182-// Frames[FrameIndex].Stream.Write(Data, 1);
183-// Data := $FF;
184-// Frames[FrameIndex].Stream.Write(Data, 1);
185-// Data := $FE;
186-// Frames[FrameIndex].Stream.Write(Data, 1);
187-// Frames[FrameIndex].Stream.Write(PWideChar(Text)^, (Length(Text) + 1) * 2);
188-// Frames[FrameIndex].Stream.Seek(0, soFromBeginning);
189-
190-
191-
192-
193-
194-
195-
196-
197-
198-
199-
200173 end;
201-
202-// Continue aqui, para cada elemento criar um frame SYLT
203-//
204-// melhor usar addframe e fazer tudo na mão! SetUnicodeContent é limitado
205-// SetUnicodeContent(,);
206-
207-
208-
209-
210-// SetUnicodeLyrics(AddFrame('USLT'), TUSLTItem(USLT).Texto,TUSLTItem(USLT).Idioma,TUSLTItem(USLT).Descricao);
211174 end;
212175 end;
213176
@@ -376,12 +339,27 @@
376339 // Unicode
377340 else
378341 begin
379- for i := AAPartirDe to High(Conteudo) do
380- if (Conteudo[i] = 0) and (Conteudo[Succ(i)] = 0) then
381- Break;
342+ // AApartirDe aponta para o primeiro caractere do BOM, logo, é necessário
343+ // incrementar em dois a variável para que ela aponte para o primeiro
344+ // caractere da string
345+ Inc(AAPartirDe,2);
382346
347+ i := AAPartirDe;
348+
349+ // O loop varre a string de dois em dois e só para quando encontra 2 zeros
350+ // consecutivos, que é o terminador unicode. O loop também termina, claro,
351+ // quando não existem mais dados a serem lidos
352+ while (Conteudo[i] + Conteudo[Succ(i)] <> 0) and (i < Length(Conteudo)) do
353+ Inc(i,2);
354+
355+ // No fim do loop anterior, i estará apontando para o primeiro zero do par
356+ // de zeros que termina a string UNICODE. Ao somarmos 2, nos posicionaremos
357+ // no primeiro byte do próximo item a ser lido
383358 AProximoIndice := i + 2;
384359
360+ // AApartirDe já apontava para o primeiro byte da string a ser lida e como i
361+ // aponta para o primeiro zero do terminador UNICODE, basta subtrair ambos
362+ // para obter o tamanho da string a ser lida
385363 Result := TEncoding.Unicode.GetString(Conteudo,AAPartirDe,i - AAPartirDe);
386364 end;
387365 end;
--- trunk/V2/src/UClassesETipos.pas (revision 29)
+++ trunk/V2/src/UClassesETipos.pas (revision 30)
@@ -142,11 +142,18 @@
142142 property Items[AIndex: Integer]: TSYLTItem read GetItem write SetItem; default;
143143 end;
144144
145+function SwapEndian32(AValue: DWORD): DWORD; register;
146+
145147 implementation
146148
147149 uses
148150 ActiveX, Vcl.Forms, WinAPI.Windows, MSHTML, UBassUtils;
149151
152+function SwapEndian32(AValue: DWORD): DWORD; register;
153+asm
154+ bswap eax
155+end;
156+
150157 { TUSLT }
151158
152159 function TUSLT.Add: TUSLTItem;
@@ -436,92 +443,126 @@
436443
437444 { TSYLTItem }
438445
439-function SwapEndian32(AValue: DWORD): DWORD; register;
440-asm
441- bswap eax
442-end;
443-
444446 procedure TSYLTItem.AdicionarConteudo(ABytes: TBytes; AIndiceInicial: Word);
445447 var
446448 i: Word;
447449 Verso: TSYLTVerso;
448- APartirDe: Word;
449- PularBytes: Byte;
450+// APartirDe: Word;
451+// PularBytes: Byte;
450452 begin
451- APartirDe := AIndiceInicial;
452- PularBytes := 0;
453+// APartirDe := AIndiceInicial;
454+// PularBytes := 0;
453455
454456 // ISO-8859-1
455457 if FCodificacaoDoTexto = 0 then
456458 begin
457- for i := AIndiceInicial to High(ABytes) do
458- begin
459- if PularBytes > 0 then
460- Dec(PularBytes)
461- else if ABytes[i] = 0 then
462- begin
463- // Quando se acha um verso localizando seu terminador ANSI (00), nós
464- // iremos processar + 4 bytes de timestamp, por isso estes bytes
465- // precisam ser pulados
466- PularBytes := 4;
467459
468- // De APartirDe até i - APartirDe está o texto do que eu chamo de verso
469- Verso.Texto := TEncoding.ANSI.GetString(ABytes,APartirDe,i - APartirDe);
470460
471- // Após i, existem 4 bytes que representam o timestamp, estes bytes
472- // encontram-se em um endianess diferente, por isso precisamos trocar
473- // sua ordem para interpretar o valor corretamente
474- Verso.Tempo := SwapEndian32(PDWORD(@ABytes[i+1])^);
461+ repeat
462+ i := AIndiceInicial;
475463
476- // Adiciona o verso e seu rótulo de tempo no conteúdo deste SYLT.
477- FConteudo.Add(Verso);
464+ // O loop varre o array de um em um e só para quando encontra 1 zero, que
465+ // é o terminador ANSI. O loop também termina, claro, quando não existem
466+ // mais dados a serem lidos
467+ while (ABytes[i] <> 0) and (i < Length(ABytes)) do
468+ Inc(i);
478469
479- // i encontra-se no terminador de string ANSI (00), depois dele existem
480- // + 4 bytes do timestamp, logo, adicionamos + 1 Byte de forma que
481- // APartirDe fique posicionado exatamente em cima do primeiro caractere
482- // do próximo verso e assim o ciclo pode reiniciar
483- APartirDe := i + 4 + 1;
484- end;
485- end;
470+ // No fim do loop anterior, i estará apontando para o zero do terminador
471+ // ANSI. De AIndiceInicial até i - AIndiceInicial está o texto do que eu
472+ // chamo de verso.
473+ Verso.Texto := TEncoding.ANSI.GetString(ABytes,AIndiceInicial,i - AIndiceInicial);
474+
475+ // Como dito anteriormente, i está apontando para o terminador ANSI, logo,
476+ // i + 1 apontará para o primeiro dos 4 Bytes que representam o tempo
477+ Inc(i);
478+
479+ // Obtendo o tempo a partir da posição indicada em i
480+ Verso.Tempo := SwapEndian32(PDWORD(@ABytes[i])^);
481+
482+ // Adiciona o verso ao conteúdo
483+ FConteudo.Add(Verso);
484+
485+ // Ao incrementar i em 4, nos posicionamos exatamente no final do item
486+ // SYLT e consequentemente no início do próximo
487+ Inc(i,4);
488+
489+ // Configura AIndiceInical como sendo i, para que o loop possa retornar ao
490+ // início usando o mesmo algorítmo
491+ AIndiceInicial := i;
492+ until i > High(ABytes);
493+
494+
495+
496+// for i := AIndiceInicial to High(ABytes) do
497+// begin
498+// if PularBytes > 0 then
499+// Dec(PularBytes)
500+// else if ABytes[i] = 0 then
501+// begin
502+// // Quando se acha um verso localizando seu terminador ANSI (00), nós
503+// // iremos processar + 4 bytes de timestamp, por isso estes bytes
504+// // precisam ser pulados
505+// PularBytes := 4;
506+//
507+// // De APartirDe até i - APartirDe está o texto do que eu chamo de verso
508+// Verso.Texto := TEncoding.ANSI.GetString(ABytes,APartirDe,i - APartirDe);
509+//
510+// // Após i, existem 4 bytes que representam o timestamp, estes bytes
511+// // encontram-se em um endianess diferente, por isso precisamos trocar
512+// // sua ordem para interpretar o valor corretamente
513+// Verso.Tempo := SwapEndian32(PDWORD(@ABytes[i+1])^);
514+//
515+// // Adiciona o verso e seu rótulo de tempo no conteúdo deste SYLT.
516+// FConteudo.Add(Verso);
517+//
518+// // i encontra-se no terminador de string ANSI (00), depois dele existem
519+// // + 4 bytes do timestamp, logo, adicionamos + 1 Byte de forma que
520+// // APartirDe fique posicionado exatamente em cima do primeiro caractere
521+// // do próximo verso e assim o ciclo pode reiniciar
522+// APartirDe := i + 4 + 1;
523+// end;
524+// end;
486525 end
487526 // Unicode
488527 else
489528 begin
490- for i := AIndiceInicial to High(ABytes) do
491- begin
492- if PularBytes > 0 then
493- Dec(PularBytes)
494- else if (ABytes[i] = 0) and (ABytes[Succ(i)] = 0) then
495- begin
496- // Quando se acha um verso localizando seu terminador UNICODE (00 00),
497- // nós iremos processar + 4 bytes de timestamp, por isso estes bytes
498- // precisam ser pulados
499- PularBytes := 4;
529+ repeat
530+ // AIndiceInicial aponta para o primeiro caractere do BOM, logo, é
531+ // necessário incrementar em dois a variável para que ela aponte para o
532+ // primeiro caractere da string
533+ Inc(AIndiceInicial,2);
500534
501- // De APartirDe até i - APartirDe está o texto do que eu chamo de verso
502- Verso.Texto := TEncoding.Unicode.GetString(ABytes,APartirDe,i - APartirDe);
535+ i := AIndiceInicial;
503536
504- // Após i, existe mais um Byte de valor zero, o qual compõe o terminador
505- // UNICODE (00 00) e após este, existem 4 bytes que representam o
506- // timestamp, estes bytes encontram-se em um endianess diferente, por
507- // isso precisamos trocar sua ordem para interpretar o valor
508- // corretamente. Abaixo, somamos i + 2 para nos posicionar no primeiro
509- // dos quatro bytes de timestamp. Isso é necessário porque i está
510- // apontando para o primeiro byte zero do teminador UNICODE
511- Verso.Tempo := SwapEndian32(PDWORD(@ABytes[i + 2])^);
537+ // O loop varre o array de dois em dois e só para quando encontra 2 zeros
538+ // consecutivos, que é o terminador unicode. O loop também termina, claro,
539+ // quando não existem mais dados a serem lidos
540+ while (ABytes[i] + ABytes[Succ(i)] <> 0) and (i < Length(ABytes)) do
541+ Inc(i,2);
512542
513- // Adiciona o verso e seu rótulo de tempo no conteúdo deste SYLT.
514- FConteudo.Add(Verso);
543+ // No fim do loop anterior, i estará apontando para o primeiro zero do par
544+ // de zeros que termina a string UNICODE. De AIndiceInicial até i -
545+ // AIndiceInicial está o texto do que eu chamo de verso.
546+ Verso.Texto := TEncoding.Unicode.GetString(ABytes,AIndiceInicial,i - AIndiceInicial);
515547
516- // i encontra-se no primeiro Byte do terminador de string UNICODE (00
517- // 00), por isso, precisamos somar + 1, de forma a nos posicionar no
518- // segundo Byte de valor zero. Depois deste, existem + 4 bytes do
519- // timestamp, logo, adicionamos + 1 Byte de forma que APartirDe fique
520- // posicionado exatamente em cima do primeiro caractere do próximo verso
521- // e assim o ciclo pode reiniciar
522- APartirDe := i + 1 + 4 + 1;
523- end;
524- end;
548+ // Como dito anteriormente, i está apontando para o terminador UNICODE,
549+ // logo, i + 2 apontará para o primeiro dos 4 Bytes que representam o tempo
550+ Inc(i,2);
551+
552+ // Obtendo o tempo a partir da posição indicada em i
553+ Verso.Tempo := SwapEndian32(PDWORD(@ABytes[i])^);
554+
555+ // Adiciona o verso ao conteúdo
556+ FConteudo.Add(Verso);
557+
558+ // Ao incrementar i em 4, nos posicionamos exatamente no final do item SYLT
559+ // e consequentemente no início do próximo
560+ Inc(i,4);
561+
562+ // Configura AIndiceInical como sendo i, para que o loop possa retornar ao
563+ // início usando o mesmo algorítmo
564+ AIndiceInicial := i;
565+ until i > High(ABytes);
525566 end;
526567 end;
527568
--- trunk/V2/src/UDAMOPrincipal.pas (revision 29)
+++ trunk/V2/src/UDAMOPrincipal.pas (revision 30)
@@ -314,6 +314,7 @@
314314 FID3v2Tag.AtribuirUSLT(FUSLT);
315315
316316 { Letra sincronizada da música }
317+ // Vide comentários do USLT acima
317318 FSYLT.ConfirmarInformacoesDaLetra;
318319 FID3v2Tag.AtribuirSYLT(FSYLT);
319320
Show on old repository browser