• R/O
  • SSH
  • HTTPS

id3v2editorplus: Commit


Commit MetaInfo

Revision24 (tree)
Time2019-09-09 04:45:09
Authorderekwildstar

Log Message

- 50% da implementação da classe TSYLT concluída
- Contém erros propositais

Change Summary

Incremental Difference

--- trunk/V2/src/UClassesAjudantes.pas (revision 23)
+++ trunk/V2/src/UClassesAjudantes.pas (revision 24)
@@ -72,6 +72,9 @@
7272
7373 procedure ObterUSLT(AUSLT: TUSLT);
7474 procedure AtribuirUSLT(const AUSLT: TUSLT);
75+
76+ procedure ObterSYLT(ASYLT: TSYLT);
77+ procedure AtribuirSYLT(const ASYLT: TSYLT);
7578 end;
7679
7780 implementation
@@ -93,6 +96,27 @@
9396
9497 { TID3v2TagHelper }
9598
99+procedure TID3v2TagHelper.AtribuirSYLT(const ASYLT: TSYLT);
100+begin
101+ ExcluirTodosOsFrames('SYLT');
102+
103+ if ASYLT.Count = 0 then
104+ Exit;
105+
106+ for var SYLT: TCollectionItem in ASYLT do
107+ begin
108+ Continue aqui, para cada elemento criar um frame SYLT
109+
110+ melhor usar addframe e fazer tudo na mão! SetUnicodeContent é limitado
111+ SetUnicodeContent(AddFrame('SYLT'),);
112+
113+
114+
115+
116+// SetUnicodeLyrics(AddFrame('USLT'), TUSLTItem(USLT).Texto,TUSLTItem(USLT).Idioma,TUSLTItem(USLT).Descricao);
117+ end;
118+end;
119+
96120 procedure TID3v2TagHelper.AtribuirUSLT(const AUSLT: TUSLT);
97121 begin
98122 ExcluirTodosOsFrames('USLT');
@@ -105,25 +129,10 @@
105129 end;
106130
107131 procedure TID3v2TagHelper.ExcluirTodosOsFrames(AFrameName: String);
108-var
109- IndiceDaPrimeiraImagem: SmallInt;
110- FramesAExcluir: Array of Byte;
111- i: Word;
112132 begin
113- IndiceDaPrimeiraImagem := FrameExists(AFrameName);
114-
115- if IndiceDaPrimeiraImagem > -1 then
116- begin
117- for i := IndiceDaPrimeiraImagem to Pred(FrameCount) do
118- if IsSameFrameID(Frames[i].ID, AFrameName) then
119- begin
120- SetLength(FramesAExcluir,Succ(Length(FramesAExcluir)));
121- FramesAExcluir[High(FramesAExcluir)] := i;
122- end;
123-
124- for i := High(FramesAExcluir) downto Low(FramesAExcluir) do
125- DeleteFrame(FramesAExcluir[i]);
126- end;
133+ for var i: Word := Pred(FrameCount) downto 0 do
134+ if IsSameFrameID(Frames[i].ID, AFrameName) then
135+ DeleteFrame(i);
127136 end;
128137
129138 procedure TID3v2TagHelper.AtribuirImagens(const AListaDeImagens: TPNGImageCollection);
@@ -248,6 +257,68 @@
248257 end;
249258 end;
250259
260+procedure TID3v2TagHelper.ObterSYLT(ASYLT: TSYLT);
261+var
262+ Conteudo: TBytes;
263+ SYLT: TSYLTItem;
264+// - ///////////////////////////////////////////////////////////////////////////
265+function ObterStringTerminadaEmNulo(AAPartirDe: Word; out AProximoIndice: Word): String;
266+var
267+ i: Word;
268+begin
269+ Result := '';
270+
271+ // ISO-8859-1
272+ if SYLT.CodificacaoDoTexto = 0 then
273+ begin
274+ for i := AAPartirDe to High(Conteudo) do
275+ if Conteudo[i] = 0 then
276+ Break;
277+
278+ AProximoIndice := i + 1;
279+
280+ Result := TEncoding.ANSI.GetString(Conteudo,AAPartirDe,i - AAPartirDe)
281+ end
282+ // Unicode
283+ else
284+ begin
285+ for i := AAPartirDe to High(Conteudo) do
286+ if (Conteudo[i] = 0) and (Conteudo[Succ(i)] = 0) then
287+ Break;
288+
289+ AProximoIndice := i + 2;
290+
291+ Result := TEncoding.Unicode.GetString(Conteudo,AAPartirDe,i - AAPartirDe);
292+ end;
293+end;
294+// - ///////////////////////////////////////////////////////////////////////////
295+var
296+ IndiceDoPrimeiroSYLT: SmallInt;
297+ Idioma: TLanguageId;
298+ ProximoIndice: Word;
299+begin
300+ IndiceDoPrimeiroSYLT := FrameExists('SYLT');
301+
302+ if IndiceDoPrimeiroSYLT >= 0 then
303+ for var i: Word := IndiceDoPrimeiroSYLT to Pred(FrameCount) do
304+ if IsSameFrameID(Frames[i].ID, 'SYLT') then
305+ begin
306+ Conteudo := GetBytes(i);
307+
308+ SYLT := ASYLT.Add; { TODO : Trocar este nome por "Adicionar"? }
309+ SYLT.CodificacaoDoTexto := Conteudo[0];
310+ Idioma[0] := Conteudo[1];
311+ Idioma[1] := Conteudo[2];
312+ Idioma[2] := Conteudo[3];
313+ SYLT.Idioma := Idioma;
314+ SYLT.FormatoDoRotuloDeTempo := Conteudo[4];
315+ SYLT.TipoDeConteudo := Conteudo[5];
316+ SYLT.DescricaoDoConteudo := ObterStringTerminadaEmNulo(6,ProximoIndice);
317+ SYLT.AdicionarConteudo(Conteudo,ProximoIndice);
318+ end;
319+end;
320+//procedure SetUnicodeSyncedLyrics
321+
251322 procedure TID3v2TagHelper.ObterUSLT(AUSLT: TUSLT);
252323 var
253324 IndiceDoPrimeiroUSLT: SmallInt;
@@ -259,9 +330,7 @@
259330 IndiceDoPrimeiroUSLT := FrameExists('USLT');
260331
261332 if IndiceDoPrimeiroUSLT >= 0 then
262- begin
263333 for var i: Word := IndiceDoPrimeiroUSLT to Pred(FrameCount) do
264- begin
265334 if IsSameFrameID(Frames[i].ID, 'USLT') then
266335 begin
267336 Texto := GetUnicodeLyrics(i, Idioma, Descricao);
@@ -274,8 +343,6 @@
274343 Letra.Texto := Texto;
275344 end;
276345 end;
277- end;
278- end;
279346 end;
280347
281348 procedure TID3v2TagHelper.SetAlbum(const Value: String);
--- trunk/V2/src/UClassesETipos.pas (revision 23)
+++ trunk/V2/src/UClassesETipos.pas (revision 24)
@@ -3,7 +3,8 @@
33 interface
44
55 uses
6- System.Classes, SHDocVw, ExtCtrls, ActnList, StdCtrls, ID3v2Library, Dialogs;
6+ System.Classes, System.SysUtils, Generics.Collections, SHDocVw, ExtCtrls,
7+ ActnList, StdCtrls, ID3v2Library, Dialogs;
78
89 type
910 TContexto = (cId3v1,cId3v2);
@@ -44,7 +45,7 @@
4445 procedure SetItem(AIndex: Integer; const AValue: TUSLTItem);
4546 public
4647 constructor Create(AWebBrowser: TWebBrowser; ADescricao: TLabeledEdit; AIdioma: TComboBox; AProximaUSLT: TAction; AUSLTAnterior: TAction; ASalvarUSLT: TAction; ARemoverUSLT: TAction; ASubstituirUSLT: TAction; AContador: TLabel; AContadorSombra: TLabel);
47- public
48+
4849 procedure Limpar;
4950 procedure ProximaUSLT(AUltima: Boolean = False);
5051 function ExcluirAtual: Boolean;
@@ -59,28 +60,50 @@
5960 property Items[AIndex: Integer]: TUSLTItem read GetItem write SetItem; default;
6061 end;
6162
62-// TSYLTItem = class(TCollectionItem)
63-// private
64-// FIdioma: TLanguageID;
65-// FDescricao: String;
66-// FTexto: String;
67-// public
68-// constructor Create(ACollection: TCollection); override;
69-//
70-// property Idioma: TLanguageID read FIdioma write FIdioma;
71-// property Descricao: String read FDescricao write FDescricao;
72-// property Texto: String read FTexto write FTexto;
73-// end;
74-//
75-// TSYLT = class(TCollection)
76-//
77-// end;
63+ TSYLTVerso = record
64+ Tempo: TTime;
65+ Texto: String;
66+ end;
7867
68+ TSYLTItem = class(TCollectionItem)
69+ private
70+ FCodificacaoDoTexto: Byte;
71+ FIdioma: TLanguageID;
72+ FFormatoDoRotuloDeTempo: Byte;
73+ FTipoDeConteudo: Byte;
74+ FDescricaoDoConteudo: String;
75+ FConteudo: TList<TSYLTVerso>;
76+ public
77+ constructor Create(ACollection: TCollection); override;
78+ destructor Destroy; override;
7979
80+ procedure AdicionarConteudo(ABytes: TBytes; AIndiceInicial: Word);
81+
82+ property CodificacaoDoTexto: Byte read FCodificacaoDoTexto write FCodificacaoDoTexto;
83+ property Idioma: TLanguageID read FIdioma write FIdioma;
84+ property FormatoDoRotuloDeTempo: Byte read FFormatoDoRotuloDeTempo write FFormatoDoRotuloDeTempo;
85+ property TipoDeConteudo: Byte read FTipoDeConteudo write FTipoDeConteudo;
86+ property DescricaoDoConteudo: String read FDescricaoDoConteudo write FDescricaoDoConteudo;
87+ property Conteudo: TList<TSYLTVerso> read FConteudo write FConteudo;
88+ end;
89+
90+ TSYLT = class(TCollection)
91+ private
92+ FIndice: SmallInt;
93+
94+ procedure AtualizarEstadoDosComponentesDeSaida;
95+ public
96+ constructor Create;
97+
98+ procedure Limpar;
99+ function Add: TSYLTItem; overload;
100+ end;
101+
102+
80103 implementation
81104
82105 uses
83- SysUtils, ActiveX, Vcl.Forms, WinAPI.Windows, MSHTML;
106+ ActiveX, Vcl.Forms, WinAPI.Windows, MSHTML;
84107
85108 { TUSLT }
86109
@@ -275,7 +298,7 @@
275298 if Count = 0 then
276299 begin
277300 FWebBrowser.Navigate2('about:blank');
278- FDescricao.Text := '';
301+ FDescricao.Clear;
279302 FIdioma.ItemIndex := 0;
280303 end;
281304 end;
@@ -371,4 +394,162 @@
371394 FTexto := '';
372395 end;
373396
397+{ TSYLTItem }
398+
399+function SwapEndian32(AValue: DWORD): DWORD; register;
400+asm
401+ bswap eax
402+end;
403+
404+procedure TSYLTItem.AdicionarConteudo(ABytes: TBytes; AIndiceInicial: Word);
405+var
406+ i: Word;
407+ Verso: TSYLTVerso;
408+ APartirDe: Word;
409+ PularBytes: Byte;
410+begin
411+ APartirDe := AIndiceInicial;
412+ PularBytes := 0;
413+
414+ // ISO-8859-1
415+ if FCodificacaoDoTexto = 0 then
416+ begin
417+ for i := AIndiceInicial to High(ABytes) do
418+ begin
419+ if PularBytes > 0 then
420+ Dec(PularBytes)
421+ else if ABytes[i] = 0 then
422+ begin
423+ // Quando se acha um verso localizando seu terminador ANSI (00), nós
424+ // iremos processar + 4 bytes de timestamp, por isso estes bytes
425+ // precisam ser pulados
426+ PularBytes := 4;
427+
428+ // De APartirDe até i - APartirDe está o texto do que eu chamo de verso
429+ Verso.Texto := TEncoding.ANSI.GetString(ABytes,APartirDe,i - APartirDe);
430+
431+ // Após i, existem 4 bytes que representam o timestamp, estes bytes
432+ // encontram-se em um endianess diferente, por isso precisamos trocar
433+ // sua ordem para interpretar o valor corretamente
434+ Verso.Tempo := SwapEndian32(PDWORD(@ABytes[i+1])^) / 1000 / 86400;
435+
436+ // Adiciona o verso e seu rótulo de tempo no conteúdo deste SYLT.
437+ FConteudo.Add(Verso);
438+
439+ // i encontra-se no terminador de string ANSI (00), depois dele existem
440+ // + 4 bytes do timestamp, logo, adicionamos + 1 Byte de forma que
441+ // APartirDe fique posicionado exatamente em cima do primeiro caractere
442+ // do próximo verso e assim o ciclo pode reiniciar
443+ APartirDe := i + 4 + 1;
444+ end;
445+ end;
446+ end
447+ // Unicode
448+ else
449+ begin
450+ for i := AIndiceInicial to High(ABytes) do
451+ begin
452+ if PularBytes > 0 then
453+ Dec(PularBytes)
454+ else if (ABytes[i] = 0) and (ABytes[Succ(i)] = 0) then
455+ begin
456+ // Quando se acha um verso localizando seu terminador UNICODE (00 00),
457+ // nós iremos processar + 4 bytes de timestamp, por isso estes bytes
458+ // precisam ser pulados
459+ PularBytes := 4;
460+
461+ // De APartirDe até i - APartirDe está o texto do que eu chamo de verso
462+ Verso.Texto := TEncoding.Unicode.GetString(ABytes,APartirDe,i - APartirDe);
463+
464+ // Após i, existe mais um Byte de valor zero, o qual compõe o terminador
465+ // UNICODE (00 00) e após este, existem 4 bytes que representam o
466+ // timestamp, estes bytes encontram-se em um endianess diferente, por
467+ // isso precisamos trocar sua ordem para interpretar o valor
468+ // corretamente. Abaixo, somamos i + 2 para nos posicionar no primeiro
469+ // dos quatro bytes de timestamp. Isso é necessário porque i está
470+ // apontando para o primeiro byte zero do teminador UNICODE
471+ Verso.Tempo := SwapEndian32(PDWORD(@ABytes[i + 2])^) / 1000 / 86400;
472+
473+ // Adiciona o verso e seu rótulo de tempo no conteúdo deste SYLT.
474+ FConteudo.Add(Verso);
475+
476+ // i encontra-se no primeiro Byte do terminador de string UNICODE (00
477+ // 00), por isso, precisamos somar + 1, de forma a nos posicionar no
478+ // segundo Byte de valor zero. Depois deste, existem + 4 bytes do
479+ // timestamp, logo, adicionamos + 1 Byte de forma que APartirDe fique
480+ // posicionado exatamente em cima do primeiro caractere do próximo verso
481+ // e assim o ciclo pode reiniciar
482+ APartirDe := i + 1 + 4 + 1;
483+ end;
484+ end;
485+ end;
486+end;
487+
488+constructor TSYLTItem.Create(ACollection: TCollection);
489+begin
490+ inherited;
491+ FCodificacaoDoTexto := 0;
492+
493+ FIdioma[0] := Ord('p');
494+ FIdioma[1] := Ord('o');
495+ FIdioma[2] := Ord('r');
496+
497+ FFormatoDoRotuloDeTempo := 2;
498+ FTipoDeConteudo := 1;
499+ FDescricaoDoConteudo := '';
500+ FConteudo := TList<TSYLTVerso>.Create;
501+end;
502+
503+destructor TSYLTItem.Destroy;
504+begin
505+ FConteudo.Free;
506+ inherited;
507+end;
508+
509+{ TSYLT }
510+
511+function TSYLT.Add: TSYLTItem;
512+begin
513+ Result := TSYLTItem(inherited Add);
514+end;
515+
516+procedure TSYLT.AtualizarEstadoDosComponentesDeSaida;
517+begin
518+/////////////////////////// Ajustar os controles aqui
519+// FProximaUSLT.Enabled := (Count > 0) and (FIndice < Pred(Count));
520+// FUSLTAnterior.Enabled := (Count > 0) and (FIndice > 0);
521+// FSalvarUSLT.Enabled := Count > 0;
522+// FRemoverUSLT.Enabled := FSalvarUSLT.Enabled;
523+// FSubstituirUSLT.Enabled := FSalvarUSLT.Enabled;
524+// FContador.Caption := Succ(FIndice).ToString + ' / ' + Count.ToString;
525+// FContadorSombra.Caption := FContador.Caption;
526+// FDescricao.Enabled := FSalvarUSLT.Enabled;
527+// FIdioma.Enabled := FSalvarUSLT.Enabled;
528+
529+ if Count = 0 then
530+ begin
531+ ///////////// Limpar o controle que mostra na tela o sylt
532+ //FWebBrowser.Navigate2('about:blank');
533+ ////////// Limpar outros controles associados
534+ //FDescricao.Text := '';
535+ //FIdioma.ItemIndex := 0;
536+ end;
537+end;
538+
539+constructor TSYLT.Create;
540+begin
541+ inherited Create(TSYLTItem);
542+ FIndice := -1;
543+end;
544+
545+procedure TSYLT.Limpar;
546+begin
547+ Clear;
548+ FIndice := -1;
549+ /////////////// Limpar o controle que mostra na tela o sylt
550+ //FWebBrowser.Navigate2('about:blank');
551+
552+ AtualizarEstadoDosComponentesDeSaida;
553+end;
554+
374555 end.
--- trunk/V2/src/UDAMOPrincipal.pas (revision 23)
+++ trunk/V2/src/UDAMOPrincipal.pas (revision 24)
@@ -90,6 +90,7 @@
9090 FPosicaoVerticalDoLetreiro: Byte;
9191 FMudouAutomaticamente: Boolean;
9292 FUSLT: TUSLT;
93+ FSYLT: TSYLT;
9394 procedure CarregarMP3;
9495 procedure CarregarID3v1;
9596 procedure SalvarID3v1;
@@ -117,6 +118,9 @@
117118 procedure SubstituirImagem;
118119 procedure SubstituirUSLT;
119120 procedure ReiniciarStatusDeModificacao(AContexto: TContexto);
121+ procedure RemoverSYLT;
122+ procedure SubstituirSYLT;
123+ procedure AdicionarSYLT;
120124 public
121125 { Public declarations }
122126 procedure DefinirStatusDeModificado(AContexto: TContexto);
@@ -210,6 +214,12 @@
210214 DefinirStatusDeModificado(cId3v2);
211215 end;
212216
217+procedure TDAMOPrincipal.RemoverSYLT;
218+begin
219+// if FSYLT.ExcluirAtual then
220+// DefinirStatusDeModificado(cId3v2);
221+end;
222+
213223 function TDAMOPrincipal.ReproducaoConcluida: Boolean;
214224 begin
215225 Result := CompareValue(BASSTempoDecorrido,FTempoTotalDoArquivoAtual) >= 0;
@@ -289,7 +299,11 @@
289299 // fará a persistência delas no arquivo
290300 FID3v2Tag.AtribuirUSLT(FUSLT);
291301
302+ { Letra sincronizada da música }
303+// FSYLT.ConfirmarInformacoesDaLetra;
304+// FID3v2Tag.AtribuirSYLT(FSYLT);
292305
306+
293307 PararReproducao;
294308 BASSDescarregarStream;
295309 try
@@ -315,6 +329,12 @@
315329 DefinirStatusDeModificado(cId3v2);
316330 end;
317331
332+procedure TDAMOPrincipal.SubstituirSYLT;
333+begin
334+// if FSYLT.SubstituirSYLT(OPDISYLT) then
335+// DefinirStatusDeModificado(cId3v2);
336+end;
337+
318338 procedure TDAMOPrincipal.PararReproducao;
319339 begin
320340 if FIndiceDoArquivoAtual = -1 then
@@ -450,6 +470,9 @@
450470
451471 FID3v2Tag.ObterUSLT(FUSLT);
452472 FUSLT.USLTAnterior(True);
473+
474+ FID3v2Tag.ObterSYLT(FSYLT)
475+ //FSYLT.SYLTAnterior(True);
453476 end;
454477 end;
455478
@@ -519,6 +542,7 @@
519542 ,ACTNSubstituirUSLT
520543 ,TFORMPrincipal(Owner).LABEUSLT
521544 ,TFORMPrincipal(Owner).LABEUSLTSombra);
545+ FSYLT := TSYLT.Create;
522546
523547 FIndiceDoArquivoAtual := -1;
524548 FMudouAutomaticamente := False;
@@ -533,6 +557,7 @@
533557 procedure TDAMOPrincipal.DataModuleDestroy(Sender: TObject);
534558 begin
535559 BASSFinalizar;
560+ FSYLT.Free;
536561 FUSLT.Free;
537562 FID3v2Tag.Free;
538563 FID3v1Tag.Free;
@@ -586,7 +611,7 @@
586611 CMBXIdiomaDoComentario.ItemIndex := -1;
587612 LAEDTipoDoComentario.Clear;
588613 { Imagens }
589- PNICAPIC.Limpar;
614+ PNICAPIC.Limpar; { TODO : Acho que dá pra limpar todos os controles associados diretamente no limpar }
590615 LAEDDescricaoDaImagem.Clear;
591616 CMBXTipoDaImagem.ItemIndex := 0;
592617 ACTNRemoverImagem.Enabled := False;
@@ -602,6 +627,8 @@
602627 CMBXIdiomaDaLetraEstatica.ItemIndex := 0;
603628 LABEUSLT.Caption := '0 / 0';
604629 LABEUSLTSombra.Caption := '0 / 0';
630+ { Letra sincronizada }
631+ FSYLT.Limpar;
605632 end;
606633 end;
607634 end;
@@ -789,6 +816,12 @@
789816 DefinirStatusDeModificado(cId3v2);
790817 end;
791818
819+procedure TDAMOPrincipal.AdicionarSYLT;
820+begin
821+// if FSYLT.AdicionarSYLT(OPDISYLT) then
822+// DefinirStatusDeModificado(cId3v2);
823+end;
824+
792825 procedure TDAMOPrincipal.AtualizarBotoesDoReprodutor;
793826 begin
794827 ACTNPrimeiraMusica.Enabled := (FIndiceDoArquivoAtual > -1) and (FIndiceDoArquivoAtual > 0);
Show on old repository browser