mirror of
https://github.com/claunia/cuetools.net.git
synced 2025-12-16 18:14:25 +00:00
initial checkin
This commit is contained in:
488
MAC_SDK/3rd Party/TMonkey (Delphi)/APEtag/APEtag.pas
Normal file
488
MAC_SDK/3rd Party/TMonkey (Delphi)/APEtag/APEtag.pas
Normal file
@@ -0,0 +1,488 @@
|
||||
{ *************************************************************************** }
|
||||
{ }
|
||||
{ Audio Tools Library (Freeware) }
|
||||
{ Class TAPEtag - for manipulating with APE tags }
|
||||
{ }
|
||||
{ Copyright (c) 2001,2002 by Jurgen Faul }
|
||||
{ E-mail: jfaul@gmx.de }
|
||||
{ http://jfaul.de/atl }
|
||||
{ }
|
||||
{ Version 1.0 (21 April 2002) }
|
||||
{ - Reading & writing support for APE 1.0 tags }
|
||||
{ - Reading support for APE 2.0 tags (UTF-8 decoding) }
|
||||
{ - Tag info: title, artist, album, track, year, genre, comment, copyright }
|
||||
{ }
|
||||
{ *************************************************************************** }
|
||||
|
||||
unit APEtag;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils;
|
||||
|
||||
type
|
||||
{ Class TAPEtag }
|
||||
TAPEtag = class(TObject)
|
||||
private
|
||||
{ Private declarations }
|
||||
FExists: Boolean;
|
||||
FVersion: Integer;
|
||||
FSize: Integer;
|
||||
FTitle: string;
|
||||
FArtist: string;
|
||||
FAlbum: string;
|
||||
FTrack: Byte;
|
||||
FYear: string;
|
||||
FGenre: string;
|
||||
FComment: string;
|
||||
FCopyright: string;
|
||||
procedure FSetTitle(const NewTitle: string);
|
||||
procedure FSetArtist(const NewArtist: string);
|
||||
procedure FSetAlbum(const NewAlbum: string);
|
||||
procedure FSetTrack(const NewTrack: Byte);
|
||||
procedure FSetYear(const NewYear: string);
|
||||
procedure FSetGenre(const NewGenre: string);
|
||||
procedure FSetComment(const NewComment: string);
|
||||
procedure FSetCopyright(const NewCopyright: string);
|
||||
public
|
||||
{ Public declarations }
|
||||
constructor Create; { Create object }
|
||||
procedure ResetData; { Reset all data }
|
||||
function ReadFromFile(const FileName: string): Boolean; { Load tag }
|
||||
function RemoveFromFile(const FileName: string): Boolean; { Delete tag }
|
||||
function SaveToFile(const FileName: string): Boolean; { Save tag }
|
||||
property Exists: Boolean read FExists; { True if tag found }
|
||||
property Version: Integer read FVersion; { Tag version }
|
||||
property Size: Integer read FSize; { Total tag size }
|
||||
property Title: string read FTitle write FSetTitle; { Song title }
|
||||
property Artist: string read FArtist write FSetArtist; { Artist name }
|
||||
property Album: string read FAlbum write FSetAlbum; { Album title }
|
||||
property Track: Byte read FTrack write FSetTrack; { Track number }
|
||||
property Year: string read FYear write FSetYear; { Release year }
|
||||
property Genre: string read FGenre write FSetGenre; { Genre name }
|
||||
property Comment: string read FComment write FSetComment; { Comment }
|
||||
property Copyright: string read FCopyright write FSetCopyright; { (c) }
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
const
|
||||
{ Tag ID }
|
||||
ID3V1_ID = 'TAG'; { ID3v1 }
|
||||
APE_ID = 'APETAGEX'; { APE }
|
||||
|
||||
{ Size constants }
|
||||
ID3V1_TAG_SIZE = 128; { ID3v1 tag }
|
||||
APE_TAG_FOOTER_SIZE = 32; { APE tag footer }
|
||||
APE_TAG_HEADER_SIZE = 32; { APE tag header }
|
||||
|
||||
{ First version of APE tag }
|
||||
APE_VERSION_1_0 = 1000;
|
||||
|
||||
{ Max. number of supported tag fields }
|
||||
APE_FIELD_COUNT = 8;
|
||||
|
||||
{ Names of supported tag fields }
|
||||
APE_FIELD: array [1..APE_FIELD_COUNT] of string =
|
||||
('Title', 'Artist', 'Album', 'Track', 'Year', 'Genre',
|
||||
'Comment', 'Copyright');
|
||||
|
||||
type
|
||||
{ APE tag data - for internal use }
|
||||
TagInfo = record
|
||||
{ Real structure of APE footer }
|
||||
ID: array [1..8] of Char; { Always "APETAGEX" }
|
||||
Version: Integer; { Tag version }
|
||||
Size: Integer; { Tag size including footer }
|
||||
Fields: Integer; { Number of fields }
|
||||
Flags: Integer; { Tag flags }
|
||||
Reserved: array [1..8] of Char; { Reserved for later use }
|
||||
{ Extended data }
|
||||
DataShift: Byte; { Used if ID3v1 tag found }
|
||||
FileSize: Integer; { File size (bytes) }
|
||||
Field: array [1..APE_FIELD_COUNT] of string; { Information from fields }
|
||||
end;
|
||||
|
||||
{ ********************* Auxiliary functions & procedures ******************** }
|
||||
|
||||
function ReadFooter(const FileName: string; var Tag: TagInfo): Boolean;
|
||||
var
|
||||
SourceFile: file;
|
||||
TagID: array [1..3] of Char;
|
||||
Transferred: Integer;
|
||||
begin
|
||||
{ Load footer from file to variable }
|
||||
try
|
||||
Result := true;
|
||||
{ Set read-access and open file }
|
||||
AssignFile(SourceFile, FileName);
|
||||
FileMode := 0;
|
||||
Reset(SourceFile, 1);
|
||||
Tag.FileSize := FileSize(SourceFile);
|
||||
{ Check for existing ID3v1 tag }
|
||||
Seek(SourceFile, Tag.FileSize - ID3V1_TAG_SIZE);
|
||||
BlockRead(SourceFile, TagID, SizeOf(TagID));
|
||||
if TagID = ID3V1_ID then Tag.DataShift := ID3V1_TAG_SIZE;
|
||||
{ Read footer data }
|
||||
Seek(SourceFile, Tag.FileSize - Tag.DataShift - APE_TAG_FOOTER_SIZE);
|
||||
BlockRead(SourceFile, Tag, APE_TAG_FOOTER_SIZE, Transferred);
|
||||
CloseFile(SourceFile);
|
||||
{ if transfer is not complete }
|
||||
if Transferred < APE_TAG_FOOTER_SIZE then Result := false;
|
||||
except
|
||||
{ Error }
|
||||
Result := false;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function ConvertFromUTF8(const Source: string): string;
|
||||
var
|
||||
Iterator, SourceLength, FChar, NChar: Integer;
|
||||
begin
|
||||
{ Convert UTF-8 string to ANSI string }
|
||||
Result := '';
|
||||
Iterator := 0;
|
||||
SourceLength := Length(Source);
|
||||
while Iterator < SourceLength do
|
||||
begin
|
||||
Inc(Iterator);
|
||||
FChar := Ord(Source[Iterator]);
|
||||
if FChar >= $80 then
|
||||
begin
|
||||
Inc(Iterator);
|
||||
if Iterator > SourceLength then break;
|
||||
FChar := FChar and $3F;
|
||||
if (FChar and $20) <> 0 then
|
||||
begin
|
||||
FChar := FChar and $1F;
|
||||
NChar := Ord(Source[Iterator]);
|
||||
if (NChar and $C0) <> $80 then break;
|
||||
FChar := (FChar shl 6) or (NChar and $3F);
|
||||
Inc(Iterator);
|
||||
if Iterator > SourceLength then break;
|
||||
end;
|
||||
NChar := Ord(Source[Iterator]);
|
||||
if (NChar and $C0) <> $80 then break;
|
||||
Result := Result + WideChar((FChar shl 6) or (NChar and $3F));
|
||||
end
|
||||
else
|
||||
Result := Result + WideChar(FChar);
|
||||
end;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure SetTagItem(const FieldName, FieldValue: string; var Tag: TagInfo);
|
||||
var
|
||||
Iterator: Byte;
|
||||
begin
|
||||
{ Set tag item if supported field found }
|
||||
for Iterator := 1 to APE_FIELD_COUNT do
|
||||
if UpperCase(FieldName) = UpperCase(APE_FIELD[Iterator]) then
|
||||
if Tag.Version > APE_VERSION_1_0 then
|
||||
Tag.Field[Iterator] := ConvertFromUTF8(FieldValue)
|
||||
else
|
||||
Tag.Field[Iterator] := FieldValue;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure ReadFields(const FileName: string; var Tag: TagInfo);
|
||||
var
|
||||
SourceFile: file;
|
||||
FieldName: string;
|
||||
FieldValue: array [1..250] of Char;
|
||||
NextChar: Char;
|
||||
Iterator, ValueSize, ValuePosition, FieldFlags: Integer;
|
||||
begin
|
||||
try
|
||||
{ Set read-access, open file }
|
||||
AssignFile(SourceFile, FileName);
|
||||
FileMode := 0;
|
||||
Reset(SourceFile, 1);
|
||||
Seek(SourceFile, Tag.FileSize - Tag.DataShift - Tag.Size);
|
||||
{ Read all stored fields }
|
||||
for Iterator := 1 to Tag.Fields do
|
||||
begin
|
||||
FillChar(FieldValue, SizeOf(FieldValue), 0);
|
||||
BlockRead(SourceFile, ValueSize, SizeOf(ValueSize));
|
||||
BlockRead(SourceFile, FieldFlags, SizeOf(FieldFlags));
|
||||
FieldName := '';
|
||||
repeat
|
||||
BlockRead(SourceFile, NextChar, SizeOf(NextChar));
|
||||
FieldName := FieldName + NextChar;
|
||||
until Ord(NextChar) = 0;
|
||||
ValuePosition := FilePos(SourceFile);
|
||||
BlockRead(SourceFile, FieldValue, ValueSize mod SizeOf(FieldValue));
|
||||
SetTagItem(Trim(FieldName), Trim(FieldValue), Tag);
|
||||
Seek(SourceFile, ValuePosition + ValueSize);
|
||||
end;
|
||||
CloseFile(SourceFile);
|
||||
except
|
||||
end;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function GetTrack(const TrackString: string): Byte;
|
||||
var
|
||||
Index, Value, Code: Integer;
|
||||
begin
|
||||
{ Get track from string }
|
||||
Index := Pos('/', TrackString);
|
||||
if Index = 0 then Val(TrackString, Value, Code)
|
||||
else Val(Copy(TrackString, 1, Index - 1), Value, Code);
|
||||
if Code = 0 then Result := Value
|
||||
else Result := 0;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function TruncateFile(const FileName: string; TagSize: Integer): Boolean;
|
||||
var
|
||||
SourceFile: file;
|
||||
begin
|
||||
try
|
||||
Result := true;
|
||||
{ Allow write-access and open file }
|
||||
FileSetAttr(FileName, 0);
|
||||
AssignFile(SourceFile, FileName);
|
||||
FileMode := 2;
|
||||
Reset(SourceFile, 1);
|
||||
{ Delete tag }
|
||||
Seek(SourceFile, FileSize(SourceFile) - TagSize);
|
||||
Truncate(SourceFile);
|
||||
CloseFile(SourceFile);
|
||||
except
|
||||
{ Error }
|
||||
Result := false;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure BuildFooter(var Tag: TagInfo);
|
||||
var
|
||||
Iterator: Integer;
|
||||
begin
|
||||
{ Build tag footer }
|
||||
Tag.ID := APE_ID;
|
||||
Tag.Version := APE_VERSION_1_0;
|
||||
Tag.Size := APE_TAG_FOOTER_SIZE;
|
||||
for Iterator := 1 to APE_FIELD_COUNT do
|
||||
if Tag.Field[Iterator] <> '' then
|
||||
begin
|
||||
Inc(Tag.Size, Length(APE_FIELD[Iterator] + Tag.Field[Iterator]) + 10);
|
||||
Inc(Tag.Fields);
|
||||
end;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function AddToFile(const FileName: string; TagData: TStream): Boolean;
|
||||
var
|
||||
FileData: TFileStream;
|
||||
begin
|
||||
try
|
||||
{ Add tag data to file }
|
||||
FileData := TFileStream.Create(FileName, fmOpenWrite or fmShareExclusive);
|
||||
FileData.Seek(0, soFromEnd);
|
||||
TagData.Seek(0, soFromBeginning);
|
||||
FileData.CopyFrom(TagData, TagData.Size);
|
||||
FileData.Free;
|
||||
Result := true;
|
||||
except
|
||||
{ Error }
|
||||
Result := false;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function SaveTag(const FileName: string; Tag: TagInfo): Boolean;
|
||||
var
|
||||
TagData: TStringStream;
|
||||
Iterator, ValueSize, Flags: Integer;
|
||||
begin
|
||||
{ Build and write tag fields and footer to stream }
|
||||
TagData := TStringStream.Create('');
|
||||
for Iterator := 1 to APE_FIELD_COUNT do
|
||||
if Tag.Field[Iterator] <> '' then
|
||||
begin
|
||||
ValueSize := Length(Tag.Field[Iterator]) + 1;
|
||||
Flags := 0;
|
||||
TagData.Write(ValueSize, SizeOf(ValueSize));
|
||||
TagData.Write(Flags, SizeOf(Flags));
|
||||
TagData.WriteString(APE_FIELD[Iterator] + #0);
|
||||
TagData.WriteString(Tag.Field[Iterator] + #0);
|
||||
end;
|
||||
BuildFooter(Tag);
|
||||
TagData.Write(Tag, APE_TAG_FOOTER_SIZE);
|
||||
{ Add created tag to file }
|
||||
Result := AddToFile(FileName, TagData);
|
||||
TagData.Free;
|
||||
end;
|
||||
|
||||
{ ********************** Private functions & procedures ********************* }
|
||||
|
||||
procedure TAPEtag.FSetTitle(const NewTitle: string);
|
||||
begin
|
||||
{ Set song title }
|
||||
FTitle := Trim(NewTitle);
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure TAPEtag.FSetArtist(const NewArtist: string);
|
||||
begin
|
||||
{ Set artist name }
|
||||
FArtist := Trim(NewArtist);
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure TAPEtag.FSetAlbum(const NewAlbum: string);
|
||||
begin
|
||||
{ Set album title }
|
||||
FAlbum := Trim(NewAlbum);
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure TAPEtag.FSetTrack(const NewTrack: Byte);
|
||||
begin
|
||||
{ Set track number }
|
||||
FTrack := NewTrack;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure TAPEtag.FSetYear(const NewYear: string);
|
||||
begin
|
||||
{ Set release year }
|
||||
FYear := Trim(NewYear);
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure TAPEtag.FSetGenre(const NewGenre: string);
|
||||
begin
|
||||
{ Set genre name }
|
||||
FGenre := Trim(NewGenre);
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure TAPEtag.FSetComment(const NewComment: string);
|
||||
begin
|
||||
{ Set comment }
|
||||
FComment := Trim(NewComment);
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure TAPEtag.FSetCopyright(const NewCopyright: string);
|
||||
begin
|
||||
{ Set copyright information }
|
||||
FCopyright := Trim(NewCopyright);
|
||||
end;
|
||||
|
||||
{ ********************** Public functions & procedures ********************** }
|
||||
|
||||
constructor TAPEtag.Create;
|
||||
begin
|
||||
{ Create object }
|
||||
inherited;
|
||||
ResetData;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure TAPEtag.ResetData;
|
||||
begin
|
||||
{ Reset all variables }
|
||||
FExists := false;
|
||||
FVersion := 0;
|
||||
FSize := 0;
|
||||
FTitle := '';
|
||||
FArtist := '';
|
||||
FAlbum := '';
|
||||
FTrack := 0;
|
||||
FYear := '';
|
||||
FGenre := '';
|
||||
FComment := '';
|
||||
FCopyright := '';
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function TAPEtag.ReadFromFile(const FileName: string): Boolean;
|
||||
var
|
||||
Tag: TagInfo;
|
||||
begin
|
||||
{ Reset data and load footer from file to variable }
|
||||
ResetData;
|
||||
FillChar(Tag, SizeOf(Tag), 0);
|
||||
Result := ReadFooter(FileName, Tag);
|
||||
{ Process data if loaded and footer valid }
|
||||
if (Result) and (Tag.ID = APE_ID) then
|
||||
begin
|
||||
FExists := true;
|
||||
{ Fill properties with footer data }
|
||||
FVersion := Tag.Version;
|
||||
FSize := Tag.Size;
|
||||
{ Get information from fields }
|
||||
ReadFields(FileName, Tag);
|
||||
FTitle := Tag.Field[1];
|
||||
FArtist := Tag.Field[2];
|
||||
FAlbum := Tag.Field[3];
|
||||
FTrack := GetTrack(Tag.Field[4]);
|
||||
FYear := Tag.Field[5];
|
||||
FGenre := Tag.Field[6];
|
||||
FComment := Tag.Field[7];
|
||||
FCopyright := Tag.Field[8];
|
||||
end;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function TAPEtag.RemoveFromFile(const FileName: string): Boolean;
|
||||
var
|
||||
Tag: TagInfo;
|
||||
begin
|
||||
{ Remove tag from file if found }
|
||||
FillChar(Tag, SizeOf(Tag), 0);
|
||||
if ReadFooter(FileName, Tag) then
|
||||
begin
|
||||
if Tag.ID <> APE_ID then Tag.Size := 0;
|
||||
if (Tag.Flags shr 31) > 0 then Inc(Tag.Size, APE_TAG_HEADER_SIZE);
|
||||
Result := TruncateFile(FileName, Tag.DataShift + Tag.Size)
|
||||
end
|
||||
else
|
||||
Result := false;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function TAPEtag.SaveToFile(const FileName: string): Boolean;
|
||||
var
|
||||
Tag: TagInfo;
|
||||
begin
|
||||
{ Prepare tag data and save to file }
|
||||
FillChar(Tag, SizeOf(Tag), 0);
|
||||
Tag.Field[1] := FTitle;
|
||||
Tag.Field[2] := FArtist;
|
||||
Tag.Field[3] := FAlbum;
|
||||
if FTrack > 0 then Tag.Field[4] := IntToStr(FTrack);
|
||||
Tag.Field[5] := FYear;
|
||||
Tag.Field[6] := FGenre;
|
||||
Tag.Field[7] := FComment;
|
||||
Tag.Field[8] := FCopyright;
|
||||
{ Delete old tag if exists and write new tag }
|
||||
Result := (RemoveFromFile(FileName)) and (SaveTag(FileName, Tag));
|
||||
end;
|
||||
|
||||
end.
|
||||
18
MAC_SDK/3rd Party/TMonkey (Delphi)/APEtag/Info.txt
Normal file
18
MAC_SDK/3rd Party/TMonkey (Delphi)/APEtag/Info.txt
Normal file
@@ -0,0 +1,18 @@
|
||||
APEtag.pas
|
||||
Tested with Borland Delphi 3,4,5,6
|
||||
|
||||
{ *************************************************************************** }
|
||||
{ }
|
||||
{ Audio Tools Library (Freeware) }
|
||||
{ Class TAPEtag - for manipulating with APE tags }
|
||||
{ }
|
||||
{ Copyright (c) 2001,2002 by Jurgen Faul }
|
||||
{ E-mail: jfaul@gmx.de }
|
||||
{ http://jfaul.de/atl }
|
||||
{ }
|
||||
{ Version 1.0 (21 April 2002) }
|
||||
{ - Reading & writing support for APE 1.0 tags }
|
||||
{ - Reading support for APE 2.0 tags (UTF-8 decoding) }
|
||||
{ - Tag info: title, artist, album, track, year, genre, comment, copyright }
|
||||
{ }
|
||||
{ *************************************************************************** }
|
||||
BIN
MAC_SDK/3rd Party/TMonkey (Delphi)/APEtag/Main.dfm
Normal file
BIN
MAC_SDK/3rd Party/TMonkey (Delphi)/APEtag/Main.dfm
Normal file
Binary file not shown.
159
MAC_SDK/3rd Party/TMonkey (Delphi)/APEtag/Main.pas
Normal file
159
MAC_SDK/3rd Party/TMonkey (Delphi)/APEtag/Main.pas
Normal file
@@ -0,0 +1,159 @@
|
||||
unit Main;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
|
||||
StdCtrls, FileCtrl, ExtCtrls, APEtag;
|
||||
|
||||
type
|
||||
TMainForm = class(TForm)
|
||||
DriveList: TDriveComboBox;
|
||||
FolderList: TDirectoryListBox;
|
||||
FileList: TFileListBox;
|
||||
SaveButton: TButton;
|
||||
RemoveButton: TButton;
|
||||
CloseButton: TButton;
|
||||
InfoBevel: TBevel;
|
||||
IconImage: TImage;
|
||||
TagExistsLabel: TLabel;
|
||||
TagExistsValue: TEdit;
|
||||
VersionLabel: TLabel;
|
||||
VersionValue: TEdit;
|
||||
SizeLabel: TLabel;
|
||||
SizeValue: TEdit;
|
||||
TitleLabel: TLabel;
|
||||
TitleEdit: TEdit;
|
||||
ArtistLabel: TLabel;
|
||||
ArtistEdit: TEdit;
|
||||
AlbumLabel: TLabel;
|
||||
AlbumEdit: TEdit;
|
||||
TrackLabel: TLabel;
|
||||
TrackEdit: TEdit;
|
||||
YearLabel: TLabel;
|
||||
YearEdit: TEdit;
|
||||
GenreLabel: TLabel;
|
||||
GenreEdit: TEdit;
|
||||
CommentLabel: TLabel;
|
||||
CommentEdit: TEdit;
|
||||
CopyrightLabel: TLabel;
|
||||
CopyrightEdit: TEdit;
|
||||
procedure FormCreate(Sender: TObject);
|
||||
procedure FileListChange(Sender: TObject);
|
||||
procedure FormClose(Sender: TObject; var Action: TCloseAction);
|
||||
procedure SaveButtonClick(Sender: TObject);
|
||||
procedure RemoveButtonClick(Sender: TObject);
|
||||
procedure CloseButtonClick(Sender: TObject);
|
||||
private
|
||||
{ Private declarations }
|
||||
FileTag: TAPEtag;
|
||||
procedure ClearAll;
|
||||
end;
|
||||
|
||||
var
|
||||
MainForm: TMainForm;
|
||||
|
||||
implementation
|
||||
|
||||
{$R *.dfm}
|
||||
|
||||
procedure TMainForm.ClearAll;
|
||||
begin
|
||||
{ Clear all captions }
|
||||
TagExistsValue.Text := '';
|
||||
VersionValue.Text := '';
|
||||
SizeValue.Text := '';
|
||||
TitleEdit.Text := '';
|
||||
ArtistEdit.Text := '';
|
||||
AlbumEdit.Text := '';
|
||||
TrackEdit.Text := '';
|
||||
YearEdit.Text := '';
|
||||
GenreEdit.Text := '';
|
||||
CommentEdit.Text := '';
|
||||
CopyrightEdit.Text := '';
|
||||
end;
|
||||
|
||||
procedure TMainForm.FormCreate(Sender: TObject);
|
||||
begin
|
||||
{ Create object and clear captions }
|
||||
FileTag := TAPEtag.Create;
|
||||
ClearAll;
|
||||
end;
|
||||
|
||||
procedure TMainForm.FileListChange(Sender: TObject);
|
||||
begin
|
||||
{ Clear captions }
|
||||
ClearAll;
|
||||
if FileList.FileName = '' then exit;
|
||||
if FileExists(FileList.FileName) then
|
||||
{ Load tag data }
|
||||
if FileTag.ReadFromFile(FileList.FileName) then
|
||||
if FileTag.Exists then
|
||||
begin
|
||||
{ Fill captions }
|
||||
TagExistsValue.Text := 'Yes';
|
||||
VersionValue.Text := FormatFloat('0,000', FileTag.Version);
|
||||
SizeValue.Text := IntToStr(FileTag.Size) + ' bytes';
|
||||
TitleEdit.Text := FileTag.Title;
|
||||
ArtistEdit.Text := FileTag.Artist;
|
||||
AlbumEdit.Text := FileTag.Album;
|
||||
if FileTag.Track > 0 then TrackEdit.Text := IntToStr(FileTag.Track);
|
||||
YearEdit.Text := FileTag.Year;
|
||||
GenreEdit.Text := FileTag.Genre;
|
||||
CommentEdit.Text := FileTag.Comment;
|
||||
CopyrightEdit.Text := FileTag.Copyright;
|
||||
end
|
||||
else
|
||||
{ Tag not found }
|
||||
TagExistsValue.Text := 'No'
|
||||
else
|
||||
{ Read error }
|
||||
ShowMessage('Can not read tag from the file: ' + FileList.FileName)
|
||||
else
|
||||
{ File does not exist }
|
||||
ShowMessage('The file does not exist: ' + FileList.FileName);
|
||||
end;
|
||||
|
||||
procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
|
||||
begin
|
||||
{ Free memory }
|
||||
FileTag.Free;
|
||||
end;
|
||||
|
||||
procedure TMainForm.SaveButtonClick(Sender: TObject);
|
||||
var
|
||||
Value, Code: Integer;
|
||||
begin
|
||||
{ Prepare tag data }
|
||||
FileTag.Title := TitleEdit.Text;
|
||||
FileTag.Artist := ArtistEdit.Text;
|
||||
FileTag.Album := AlbumEdit.Text;
|
||||
Val(TrackEdit.Text, Value, Code);
|
||||
if (Code = 0) and (Value > 0) then FileTag.Track := Value
|
||||
else FileTag.Track := 0;
|
||||
FileTag.Year := YearEdit.Text;
|
||||
FileTag.Genre := GenreEdit.Text;
|
||||
FileTag.Comment := CommentEdit.Text;
|
||||
FileTag.Copyright := CopyrightEdit.Text;
|
||||
{ Save tag data }
|
||||
if (not FileExists(FileList.FileName)) or
|
||||
(not FileTag.SaveToFile(FileList.FileName)) then
|
||||
ShowMessage('Can not save tag to the file: ' + FileList.FileName);
|
||||
FileListChange(Self);
|
||||
end;
|
||||
|
||||
procedure TMainForm.RemoveButtonClick(Sender: TObject);
|
||||
begin
|
||||
{ Delete tag data }
|
||||
if (FileExists(FileList.FileName)) and
|
||||
(FileTag.RemoveFromFile(FileList.FileName)) then ClearAll
|
||||
else ShowMessage('Can not remove tag from the file: ' + FileList.FileName);
|
||||
end;
|
||||
|
||||
procedure TMainForm.CloseButtonClick(Sender: TObject);
|
||||
begin
|
||||
{ Exit }
|
||||
Close;
|
||||
end;
|
||||
|
||||
end.
|
||||
35
MAC_SDK/3rd Party/TMonkey (Delphi)/APEtag/Test.cfg
Normal file
35
MAC_SDK/3rd Party/TMonkey (Delphi)/APEtag/Test.cfg
Normal file
@@ -0,0 +1,35 @@
|
||||
-$A8
|
||||
-$B-
|
||||
-$C+
|
||||
-$D+
|
||||
-$E-
|
||||
-$F-
|
||||
-$G+
|
||||
-$H+
|
||||
-$I+
|
||||
-$J-
|
||||
-$K-
|
||||
-$L+
|
||||
-$M-
|
||||
-$N+
|
||||
-$O+
|
||||
-$P+
|
||||
-$Q-
|
||||
-$R-
|
||||
-$S-
|
||||
-$T-
|
||||
-$U-
|
||||
-$V+
|
||||
-$W-
|
||||
-$X+
|
||||
-$YD
|
||||
-$Z1
|
||||
-cg
|
||||
-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
|
||||
-H+
|
||||
-W+
|
||||
-M
|
||||
-$M16384,1048576
|
||||
-K$00400000
|
||||
-LE"c:\program files\borland\delphi6\Projects\Bpl"
|
||||
-LN"c:\program files\borland\delphi6\Projects\Bpl"
|
||||
96
MAC_SDK/3rd Party/TMonkey (Delphi)/APEtag/Test.dof
Normal file
96
MAC_SDK/3rd Party/TMonkey (Delphi)/APEtag/Test.dof
Normal file
@@ -0,0 +1,96 @@
|
||||
[FileVersion]
|
||||
Version=6.0
|
||||
[Compiler]
|
||||
A=8
|
||||
B=0
|
||||
C=1
|
||||
D=1
|
||||
E=0
|
||||
F=0
|
||||
G=1
|
||||
H=1
|
||||
I=1
|
||||
J=0
|
||||
K=0
|
||||
L=1
|
||||
M=0
|
||||
N=1
|
||||
O=1
|
||||
P=1
|
||||
Q=0
|
||||
R=0
|
||||
S=0
|
||||
T=0
|
||||
U=0
|
||||
V=1
|
||||
W=0
|
||||
X=1
|
||||
Y=1
|
||||
Z=1
|
||||
ShowHints=1
|
||||
ShowWarnings=1
|
||||
UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
|
||||
[Linker]
|
||||
MapFile=0
|
||||
OutputObjs=0
|
||||
ConsoleApp=1
|
||||
DebugInfo=0
|
||||
RemoteSymbols=0
|
||||
MinStackSize=16384
|
||||
MaxStackSize=1048576
|
||||
ImageBase=4194304
|
||||
ExeDescription=
|
||||
[Directories]
|
||||
OutputDir=
|
||||
UnitOutputDir=
|
||||
PackageDLLOutputDir=
|
||||
PackageDCPOutputDir=
|
||||
SearchPath=
|
||||
Packages=vcl;rtl;dbrtl;adortl;vcldb;vclx;bdertl;vcldbx;ibxpress;dsnap;cds;bdecds;qrpt;teeui;teedb;tee;dss;teeqr;visualclx;visualdbclx;dsnapcrba;dsnapcon;VclSmp;vclshlctrls;vclie;xmlrtl;inet;inetdbbde;inetdbxpress;inetdb;nmfast;webdsnap;websnap;dbexpress;dbxcds;indy;dclOffice2k
|
||||
Conditionals=
|
||||
DebugSourceDirs=
|
||||
UsePackages=0
|
||||
[Parameters]
|
||||
RunParams=
|
||||
HostApplication=
|
||||
Launcher=
|
||||
UseLauncher=0
|
||||
DebugCWD=
|
||||
[Language]
|
||||
ActiveLang=
|
||||
ProjectLang=
|
||||
RootDir=
|
||||
[Version Info]
|
||||
IncludeVerInfo=0
|
||||
AutoIncBuild=0
|
||||
MajorVer=1
|
||||
MinorVer=0
|
||||
Release=0
|
||||
Build=0
|
||||
Debug=0
|
||||
PreRelease=0
|
||||
Special=0
|
||||
Private=0
|
||||
DLL=0
|
||||
Locale=1031
|
||||
CodePage=1252
|
||||
[Version Info Keys]
|
||||
CompanyName=
|
||||
FileDescription=
|
||||
FileVersion=1.0.0.0
|
||||
InternalName=
|
||||
LegalCopyright=
|
||||
LegalTrademarks=
|
||||
OriginalFilename=
|
||||
ProductName=
|
||||
ProductVersion=1.0.0.0
|
||||
Comments=
|
||||
[HistoryLists\hlUnitAliases]
|
||||
Count=1
|
||||
Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
|
||||
[HistoryLists\hlUnitOutputDirectory]
|
||||
Count=1
|
||||
Item0=DCU
|
||||
[HistoryLists\hlOutputDirectorry]
|
||||
Count=1
|
||||
Item0=Data
|
||||
15
MAC_SDK/3rd Party/TMonkey (Delphi)/APEtag/Test.dpr
Normal file
15
MAC_SDK/3rd Party/TMonkey (Delphi)/APEtag/Test.dpr
Normal file
@@ -0,0 +1,15 @@
|
||||
program Test;
|
||||
|
||||
uses
|
||||
Forms,
|
||||
Main in 'Main.pas' {MainForm},
|
||||
APEtag in 'APEtag.pas';
|
||||
|
||||
{$R *.res}
|
||||
|
||||
begin
|
||||
Application.Initialize;
|
||||
Application.Title := 'APEtag Test';
|
||||
Application.CreateForm(TMainForm, MainForm);
|
||||
Application.Run;
|
||||
end.
|
||||
BIN
MAC_SDK/3rd Party/TMonkey (Delphi)/APEtag/Test.res
Normal file
BIN
MAC_SDK/3rd Party/TMonkey (Delphi)/APEtag/Test.res
Normal file
Binary file not shown.
475
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v1/ID3v1.pas
Normal file
475
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v1/ID3v1.pas
Normal file
@@ -0,0 +1,475 @@
|
||||
{ *************************************************************************** }
|
||||
{ }
|
||||
{ Audio Tools Library (Freeware) }
|
||||
{ Class TID3v1 - for manipulating with ID3v1 tags }
|
||||
{ }
|
||||
{ Copyright (c) 2001,2002 by Jurgen Faul }
|
||||
{ E-mail: jfaul@gmx.de }
|
||||
{ http://jfaul.de/atl }
|
||||
{ }
|
||||
{ Version 1.0 (25 July 2001) }
|
||||
{ - Reading & writing support for ID3v1.x tags }
|
||||
{ - Tag info: title, artist, album, track, year, genre, comment }
|
||||
{ }
|
||||
{ *************************************************************************** }
|
||||
|
||||
unit ID3v1;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils;
|
||||
|
||||
const
|
||||
MAX_MUSIC_GENRES = 148; { Max. number of music genres }
|
||||
DEFAULT_GENRE = 255; { Index for default genre }
|
||||
|
||||
{ Used with VersionID property }
|
||||
TAG_VERSION_1_0 = 1; { Index for ID3v1.0 tag }
|
||||
TAG_VERSION_1_1 = 2; { Index for ID3v1.1 tag }
|
||||
|
||||
var
|
||||
MusicGenre: array [0..MAX_MUSIC_GENRES - 1] of string; { Genre names }
|
||||
|
||||
type
|
||||
{ Used in TID3v1 class }
|
||||
String04 = string[4]; { String with max. 4 symbols }
|
||||
String30 = string[30]; { String with max. 30 symbols }
|
||||
|
||||
{ Class TID3v1 }
|
||||
TID3v1 = class(TObject)
|
||||
private
|
||||
{ Private declarations }
|
||||
FExists: Boolean;
|
||||
FVersionID: Byte;
|
||||
FTitle: String30;
|
||||
FArtist: String30;
|
||||
FAlbum: String30;
|
||||
FYear: String04;
|
||||
FComment: String30;
|
||||
FTrack: Byte;
|
||||
FGenreID: Byte;
|
||||
procedure FSetTitle(const NewTitle: String30);
|
||||
procedure FSetArtist(const NewArtist: String30);
|
||||
procedure FSetAlbum(const NewAlbum: String30);
|
||||
procedure FSetYear(const NewYear: String04);
|
||||
procedure FSetComment(const NewComment: String30);
|
||||
procedure FSetTrack(const NewTrack: Byte);
|
||||
procedure FSetGenreID(const NewGenreID: Byte);
|
||||
function FGetGenre: string;
|
||||
public
|
||||
{ Public declarations }
|
||||
constructor Create; { Create object }
|
||||
procedure ResetData; { Reset all data }
|
||||
function ReadFromFile(const FileName: string): Boolean; { Load tag }
|
||||
function RemoveFromFile(const FileName: string): Boolean; { Delete tag }
|
||||
function SaveToFile(const FileName: string): Boolean; { Save tag }
|
||||
property Exists: Boolean read FExists; { True if tag found }
|
||||
property VersionID: Byte read FVersionID; { Version code }
|
||||
property Title: String30 read FTitle write FSetTitle; { Song title }
|
||||
property Artist: String30 read FArtist write FSetArtist; { Artist name }
|
||||
property Album: String30 read FAlbum write FSetAlbum; { Album name }
|
||||
property Year: String04 read FYear write FSetYear; { Year }
|
||||
property Comment: String30 read FComment write FSetComment; { Comment }
|
||||
property Track: Byte read FTrack write FSetTrack; { Track number }
|
||||
property GenreID: Byte read FGenreID write FSetGenreID; { Genre code }
|
||||
property Genre: string read FGetGenre; { Genre name }
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
type
|
||||
{ Real structure of ID3v1 tag }
|
||||
TagRecord = record
|
||||
Header: array [1..3] of Char; { Tag header - must be "TAG" }
|
||||
Title: array [1..30] of Char; { Title data }
|
||||
Artist: array [1..30] of Char; { Artist data }
|
||||
Album: array [1..30] of Char; { Album data }
|
||||
Year: array [1..4] of Char; { Year data }
|
||||
Comment: array [1..30] of Char; { Comment data }
|
||||
Genre: Byte; { Genre data }
|
||||
end;
|
||||
|
||||
{ ********************* Auxiliary functions & procedures ******************** }
|
||||
|
||||
function ReadTag(const FileName: string; var TagData: TagRecord): Boolean;
|
||||
var
|
||||
SourceFile: file;
|
||||
begin
|
||||
try
|
||||
Result := true;
|
||||
{ Set read-access and open file }
|
||||
AssignFile(SourceFile, FileName);
|
||||
FileMode := 0;
|
||||
Reset(SourceFile, 1);
|
||||
{ Read tag }
|
||||
Seek(SourceFile, FileSize(SourceFile) - 128);
|
||||
BlockRead(SourceFile, TagData, 128);
|
||||
CloseFile(SourceFile);
|
||||
except
|
||||
{ Error }
|
||||
Result := false;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function RemoveTag(const FileName: string): Boolean;
|
||||
var
|
||||
SourceFile: file;
|
||||
begin
|
||||
try
|
||||
Result := true;
|
||||
{ Allow write-access and open file }
|
||||
FileSetAttr(FileName, 0);
|
||||
AssignFile(SourceFile, FileName);
|
||||
FileMode := 2;
|
||||
Reset(SourceFile, 1);
|
||||
{ Delete tag }
|
||||
Seek(SourceFile, FileSize(SourceFile) - 128);
|
||||
Truncate(SourceFile);
|
||||
CloseFile(SourceFile);
|
||||
except
|
||||
{ Error }
|
||||
Result := false;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function SaveTag(const FileName: string; TagData: TagRecord): Boolean;
|
||||
var
|
||||
SourceFile: file;
|
||||
begin
|
||||
try
|
||||
Result := true;
|
||||
{ Allow write-access and open file }
|
||||
FileSetAttr(FileName, 0);
|
||||
AssignFile(SourceFile, FileName);
|
||||
FileMode := 2;
|
||||
Reset(SourceFile, 1);
|
||||
{ Write tag }
|
||||
Seek(SourceFile, FileSize(SourceFile));
|
||||
BlockWrite(SourceFile, TagData, SizeOf(TagData));
|
||||
CloseFile(SourceFile);
|
||||
except
|
||||
{ Error }
|
||||
Result := false;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function GetTagVersion(const TagData: TagRecord): Byte;
|
||||
begin
|
||||
Result := TAG_VERSION_1_0;
|
||||
{ Terms for ID3v1.1 }
|
||||
if ((TagData.Comment[29] = #0) and (TagData.Comment[30] <> #0)) or
|
||||
((TagData.Comment[29] = #32) and (TagData.Comment[30] <> #32)) then
|
||||
Result := TAG_VERSION_1_1;
|
||||
end;
|
||||
|
||||
{ ********************** Private functions & procedures ********************* }
|
||||
|
||||
procedure TID3v1.FSetTitle(const NewTitle: String30);
|
||||
begin
|
||||
FTitle := TrimRight(NewTitle);
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure TID3v1.FSetArtist(const NewArtist: String30);
|
||||
begin
|
||||
FArtist := TrimRight(NewArtist);
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure TID3v1.FSetAlbum(const NewAlbum: String30);
|
||||
begin
|
||||
FAlbum := TrimRight(NewAlbum);
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure TID3v1.FSetYear(const NewYear: String04);
|
||||
begin
|
||||
FYear := TrimRight(NewYear);
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure TID3v1.FSetComment(const NewComment: String30);
|
||||
begin
|
||||
FComment := TrimRight(NewComment);
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure TID3v1.FSetTrack(const NewTrack: Byte);
|
||||
begin
|
||||
FTrack := NewTrack;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure TID3v1.FSetGenreID(const NewGenreID: Byte);
|
||||
begin
|
||||
FGenreID := NewGenreID;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function TID3v1.FGetGenre: string;
|
||||
begin
|
||||
Result := '';
|
||||
{ Return an empty string if the current GenreID is not valid }
|
||||
if FGenreID in [0..MAX_MUSIC_GENRES - 1] then Result := MusicGenre[FGenreID];
|
||||
end;
|
||||
|
||||
{ ********************** Public functions & procedures ********************** }
|
||||
|
||||
constructor TID3v1.Create;
|
||||
begin
|
||||
inherited;
|
||||
ResetData;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure TID3v1.ResetData;
|
||||
begin
|
||||
FExists := false;
|
||||
FVersionID := TAG_VERSION_1_0;
|
||||
FTitle := '';
|
||||
FArtist := '';
|
||||
FAlbum := '';
|
||||
FYear := '';
|
||||
FComment := '';
|
||||
FTrack := 0;
|
||||
FGenreID := DEFAULT_GENRE;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function TID3v1.ReadFromFile(const FileName: string): Boolean;
|
||||
var
|
||||
TagData: TagRecord;
|
||||
begin
|
||||
{ Reset and load tag data from file to variable }
|
||||
ResetData;
|
||||
Result := ReadTag(FileName, TagData);
|
||||
{ Process data if loaded and tag header OK }
|
||||
if (Result) and (TagData.Header = 'TAG') then
|
||||
begin
|
||||
FExists := true;
|
||||
FVersionID := GetTagVersion(TagData);
|
||||
{ Fill properties with tag data }
|
||||
FTitle := TrimRight(TagData.Title);
|
||||
FArtist := TrimRight(TagData.Artist);
|
||||
FAlbum := TrimRight(TagData.Album);
|
||||
FYear := TrimRight(TagData.Year);
|
||||
if FVersionID = TAG_VERSION_1_0 then
|
||||
FComment := TrimRight(TagData.Comment)
|
||||
else
|
||||
begin
|
||||
FComment := TrimRight(Copy(TagData.Comment, 1, 28));
|
||||
FTrack := Ord(TagData.Comment[30]);
|
||||
end;
|
||||
FGenreID := TagData.Genre;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function TID3v1.RemoveFromFile(const FileName: string): Boolean;
|
||||
var
|
||||
TagData: TagRecord;
|
||||
begin
|
||||
{ Find tag }
|
||||
Result := ReadTag(FileName, TagData);
|
||||
{ Delete tag if loaded and tag header OK }
|
||||
if (Result) and (TagData.Header = 'TAG') then Result := RemoveTag(FileName);
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function TID3v1.SaveToFile(const FileName: string): Boolean;
|
||||
var
|
||||
TagData: TagRecord;
|
||||
begin
|
||||
{ Prepare tag record }
|
||||
FillChar(TagData, SizeOf(TagData), 0);
|
||||
TagData.Header := 'TAG';
|
||||
Move(FTitle[1], TagData.Title, Length(FTitle));
|
||||
Move(FArtist[1], TagData.Artist, Length(FArtist));
|
||||
Move(FAlbum[1], TagData.Album, Length(FAlbum));
|
||||
Move(FYear[1], TagData.Year, Length(FYear));
|
||||
Move(FComment[1], TagData.Comment, Length(FComment));
|
||||
if FTrack > 0 then
|
||||
begin
|
||||
TagData.Comment[29] := #0;
|
||||
TagData.Comment[30] := Chr(FTrack);
|
||||
end;
|
||||
TagData.Genre := FGenreID;
|
||||
{ Delete old tag and write new tag }
|
||||
Result := (RemoveFromFile(FileName)) and (SaveTag(FileName, TagData));
|
||||
end;
|
||||
|
||||
{ ************************** Initialize music genres ************************ }
|
||||
|
||||
initialization
|
||||
begin
|
||||
{ Standard genres }
|
||||
MusicGenre[0] := 'Blues';
|
||||
MusicGenre[1] := 'Classic Rock';
|
||||
MusicGenre[2] := 'Country';
|
||||
MusicGenre[3] := 'Dance';
|
||||
MusicGenre[4] := 'Disco';
|
||||
MusicGenre[5] := 'Funk';
|
||||
MusicGenre[6] := 'Grunge';
|
||||
MusicGenre[7] := 'Hip-Hop';
|
||||
MusicGenre[8] := 'Jazz';
|
||||
MusicGenre[9] := 'Metal';
|
||||
MusicGenre[10] := 'New Age';
|
||||
MusicGenre[11] := 'Oldies';
|
||||
MusicGenre[12] := 'Other';
|
||||
MusicGenre[13] := 'Pop';
|
||||
MusicGenre[14] := 'R&B';
|
||||
MusicGenre[15] := 'Rap';
|
||||
MusicGenre[16] := 'Reggae';
|
||||
MusicGenre[17] := 'Rock';
|
||||
MusicGenre[18] := 'Techno';
|
||||
MusicGenre[19] := 'Industrial';
|
||||
MusicGenre[20] := 'Alternative';
|
||||
MusicGenre[21] := 'Ska';
|
||||
MusicGenre[22] := 'Death Metal';
|
||||
MusicGenre[23] := 'Pranks';
|
||||
MusicGenre[24] := 'Soundtrack';
|
||||
MusicGenre[25] := 'Euro-Techno';
|
||||
MusicGenre[26] := 'Ambient';
|
||||
MusicGenre[27] := 'Trip-Hop';
|
||||
MusicGenre[28] := 'Vocal';
|
||||
MusicGenre[29] := 'Jazz+Funk';
|
||||
MusicGenre[30] := 'Fusion';
|
||||
MusicGenre[31] := 'Trance';
|
||||
MusicGenre[32] := 'Classical';
|
||||
MusicGenre[33] := 'Instrumental';
|
||||
MusicGenre[34] := 'Acid';
|
||||
MusicGenre[35] := 'House';
|
||||
MusicGenre[36] := 'Game';
|
||||
MusicGenre[37] := 'Sound Clip';
|
||||
MusicGenre[38] := 'Gospel';
|
||||
MusicGenre[39] := 'Noise';
|
||||
MusicGenre[40] := 'AlternRock';
|
||||
MusicGenre[41] := 'Bass';
|
||||
MusicGenre[42] := 'Soul';
|
||||
MusicGenre[43] := 'Punk';
|
||||
MusicGenre[44] := 'Space';
|
||||
MusicGenre[45] := 'Meditative';
|
||||
MusicGenre[46] := 'Instrumental Pop';
|
||||
MusicGenre[47] := 'Instrumental Rock';
|
||||
MusicGenre[48] := 'Ethnic';
|
||||
MusicGenre[49] := 'Gothic';
|
||||
MusicGenre[50] := 'Darkwave';
|
||||
MusicGenre[51] := 'Techno-Industrial';
|
||||
MusicGenre[52] := 'Electronic';
|
||||
MusicGenre[53] := 'Pop-Folk';
|
||||
MusicGenre[54] := 'Eurodance';
|
||||
MusicGenre[55] := 'Dream';
|
||||
MusicGenre[56] := 'Southern Rock';
|
||||
MusicGenre[57] := 'Comedy';
|
||||
MusicGenre[58] := 'Cult';
|
||||
MusicGenre[59] := 'Gangsta';
|
||||
MusicGenre[60] := 'Top 40';
|
||||
MusicGenre[61] := 'Christian Rap';
|
||||
MusicGenre[62] := 'Pop/Funk';
|
||||
MusicGenre[63] := 'Jungle';
|
||||
MusicGenre[64] := 'Native American';
|
||||
MusicGenre[65] := 'Cabaret';
|
||||
MusicGenre[66] := 'New Wave';
|
||||
MusicGenre[67] := 'Psychadelic';
|
||||
MusicGenre[68] := 'Rave';
|
||||
MusicGenre[69] := 'Showtunes';
|
||||
MusicGenre[70] := 'Trailer';
|
||||
MusicGenre[71] := 'Lo-Fi';
|
||||
MusicGenre[72] := 'Tribal';
|
||||
MusicGenre[73] := 'Acid Punk';
|
||||
MusicGenre[74] := 'Acid Jazz';
|
||||
MusicGenre[75] := 'Polka';
|
||||
MusicGenre[76] := 'Retro';
|
||||
MusicGenre[77] := 'Musical';
|
||||
MusicGenre[78] := 'Rock & Roll';
|
||||
MusicGenre[79] := 'Hard Rock';
|
||||
{ Extended genres }
|
||||
MusicGenre[80] := 'Folk';
|
||||
MusicGenre[81] := 'Folk-Rock';
|
||||
MusicGenre[82] := 'National Folk';
|
||||
MusicGenre[83] := 'Swing';
|
||||
MusicGenre[84] := 'Fast Fusion';
|
||||
MusicGenre[85] := 'Bebob';
|
||||
MusicGenre[86] := 'Latin';
|
||||
MusicGenre[87] := 'Revival';
|
||||
MusicGenre[88] := 'Celtic';
|
||||
MusicGenre[89] := 'Bluegrass';
|
||||
MusicGenre[90] := 'Avantgarde';
|
||||
MusicGenre[91] := 'Gothic Rock';
|
||||
MusicGenre[92] := 'Progessive Rock';
|
||||
MusicGenre[93] := 'Psychedelic Rock';
|
||||
MusicGenre[94] := 'Symphonic Rock';
|
||||
MusicGenre[95] := 'Slow Rock';
|
||||
MusicGenre[96] := 'Big Band';
|
||||
MusicGenre[97] := 'Chorus';
|
||||
MusicGenre[98] := 'Easy Listening';
|
||||
MusicGenre[99] := 'Acoustic';
|
||||
MusicGenre[100]:= 'Humour';
|
||||
MusicGenre[101]:= 'Speech';
|
||||
MusicGenre[102]:= 'Chanson';
|
||||
MusicGenre[103]:= 'Opera';
|
||||
MusicGenre[104]:= 'Chamber Music';
|
||||
MusicGenre[105]:= 'Sonata';
|
||||
MusicGenre[106]:= 'Symphony';
|
||||
MusicGenre[107]:= 'Booty Bass';
|
||||
MusicGenre[108]:= 'Primus';
|
||||
MusicGenre[109]:= 'Porn Groove';
|
||||
MusicGenre[110]:= 'Satire';
|
||||
MusicGenre[111]:= 'Slow Jam';
|
||||
MusicGenre[112]:= 'Club';
|
||||
MusicGenre[113]:= 'Tango';
|
||||
MusicGenre[114]:= 'Samba';
|
||||
MusicGenre[115]:= 'Folklore';
|
||||
MusicGenre[116]:= 'Ballad';
|
||||
MusicGenre[117]:= 'Power Ballad';
|
||||
MusicGenre[118]:= 'Rhythmic Soul';
|
||||
MusicGenre[119]:= 'Freestyle';
|
||||
MusicGenre[120]:= 'Duet';
|
||||
MusicGenre[121]:= 'Punk Rock';
|
||||
MusicGenre[122]:= 'Drum Solo';
|
||||
MusicGenre[123]:= 'A capella';
|
||||
MusicGenre[124]:= 'Euro-House';
|
||||
MusicGenre[125]:= 'Dance Hall';
|
||||
MusicGenre[126]:= 'Goa';
|
||||
MusicGenre[127]:= 'Drum & Bass';
|
||||
MusicGenre[128]:= 'Club-House';
|
||||
MusicGenre[129]:= 'Hardcore';
|
||||
MusicGenre[130]:= 'Terror';
|
||||
MusicGenre[131]:= 'Indie';
|
||||
MusicGenre[132]:= 'BritPop';
|
||||
MusicGenre[133]:= 'Negerpunk';
|
||||
MusicGenre[134]:= 'Polsk Punk';
|
||||
MusicGenre[135]:= 'Beat';
|
||||
MusicGenre[136]:= 'Christian Gangsta Rap';
|
||||
MusicGenre[137]:= 'Heavy Metal';
|
||||
MusicGenre[138]:= 'Black Metal';
|
||||
MusicGenre[139]:= 'Crossover';
|
||||
MusicGenre[140]:= 'Contemporary Christian';
|
||||
MusicGenre[141]:= 'Christian Rock';
|
||||
MusicGenre[142]:= 'Merengue';
|
||||
MusicGenre[143]:= 'Salsa';
|
||||
MusicGenre[144]:= 'Trash Metal';
|
||||
MusicGenre[145]:= 'Anime';
|
||||
MusicGenre[146]:= 'JPop';
|
||||
MusicGenre[147]:= 'Synthpop';
|
||||
end;
|
||||
|
||||
end.
|
||||
17
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v1/Info.txt
Normal file
17
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v1/Info.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
ID3v1.pas
|
||||
Tested with Borland Delphi 3,4,5,6
|
||||
|
||||
{ *************************************************************************** }
|
||||
{ }
|
||||
{ Audio Tools Library (Freeware) }
|
||||
{ Class TID3v1 - for manipulating with ID3v1 tags }
|
||||
{ }
|
||||
{ Copyright (c) 2001,2002 by Jurgen Faul }
|
||||
{ E-mail: jfaul@gmx.de }
|
||||
{ http://jfaul.de/atl }
|
||||
{ }
|
||||
{ Version 1.0 (25 July 2001) }
|
||||
{ - Reading & writing support for ID3v1.x tags }
|
||||
{ - Tag info: title, artist, album, track, year, genre, comment }
|
||||
{ }
|
||||
{ *************************************************************************** }
|
||||
BIN
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v1/Main.dfm
Normal file
BIN
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v1/Main.dfm
Normal file
Binary file not shown.
162
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v1/Main.pas
Normal file
162
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v1/Main.pas
Normal file
@@ -0,0 +1,162 @@
|
||||
unit Main;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
|
||||
StdCtrls, FileCtrl, ExtCtrls, ID3v1;
|
||||
|
||||
type
|
||||
TMainForm = class(TForm)
|
||||
DriveList: TDriveComboBox;
|
||||
FolderList: TDirectoryListBox;
|
||||
FileList: TFileListBox;
|
||||
CloseButton: TButton;
|
||||
RemoveButton: TButton;
|
||||
SaveButton: TButton;
|
||||
InfoBevel: TBevel;
|
||||
IconImage: TImage;
|
||||
TagExistsLabel: TLabel;
|
||||
TagVersionLabel: TLabel;
|
||||
TitleLabel: TLabel;
|
||||
ArtistLabel: TLabel;
|
||||
AlbumLabel: TLabel;
|
||||
YearLabel: TLabel;
|
||||
CommentLabel: TLabel;
|
||||
TrackLabel: TLabel;
|
||||
GenreLabel: TLabel;
|
||||
TitleEdit: TEdit;
|
||||
ArtistEdit: TEdit;
|
||||
AlbumEdit: TEdit;
|
||||
TrackEdit: TEdit;
|
||||
YearEdit: TEdit;
|
||||
CommentEdit: TEdit;
|
||||
GenreComboBox: TComboBox;
|
||||
TagExistsValue: TEdit;
|
||||
TagVersionValue: TEdit;
|
||||
procedure CloseButtonClick(Sender: TObject);
|
||||
procedure FormCreate(Sender: TObject);
|
||||
procedure FileListChange(Sender: TObject);
|
||||
procedure FormClose(Sender: TObject; var Action: TCloseAction);
|
||||
procedure SaveButtonClick(Sender: TObject);
|
||||
procedure RemoveButtonClick(Sender: TObject);
|
||||
private
|
||||
{ Private declarations }
|
||||
FileTag: TID3v1;
|
||||
procedure ClearAll;
|
||||
end;
|
||||
|
||||
var
|
||||
MainForm: TMainForm;
|
||||
|
||||
implementation
|
||||
|
||||
{$R *.dfm}
|
||||
|
||||
procedure TMainForm.ClearAll;
|
||||
begin
|
||||
{ Clear all captions }
|
||||
TagExistsValue.Text := '';
|
||||
TagVersionValue.Text := '';
|
||||
TitleEdit.Text := '';
|
||||
ArtistEdit.Text := '';
|
||||
AlbumEdit.Text := '';
|
||||
TrackEdit.Text := '';
|
||||
YearEdit.Text := '';
|
||||
GenreComboBox.ItemIndex := 0;
|
||||
CommentEdit.Text := '';
|
||||
end;
|
||||
|
||||
procedure TMainForm.CloseButtonClick(Sender: TObject);
|
||||
begin
|
||||
{ Exit }
|
||||
Close;
|
||||
end;
|
||||
|
||||
procedure TMainForm.FormCreate(Sender: TObject);
|
||||
var
|
||||
Iterator: Integer;
|
||||
begin
|
||||
{ Create object }
|
||||
FileTag := TID3v1.Create;
|
||||
{ Fill and initialize genres }
|
||||
GenreComboBox.Items.Add('');
|
||||
for Iterator := 0 to MAX_MUSIC_GENRES - 1 do
|
||||
GenreComboBox.Items.Add(MusicGenre[Iterator]);
|
||||
{ Reset }
|
||||
ClearAll;
|
||||
end;
|
||||
|
||||
procedure TMainForm.FileListChange(Sender: TObject);
|
||||
begin
|
||||
{ Clear captions }
|
||||
ClearAll;
|
||||
if FileList.FileName = '' then exit;
|
||||
if FileExists(FileList.FileName) then
|
||||
{ Load tag data }
|
||||
if FileTag.ReadFromFile(FileList.FileName) then
|
||||
if FileTag.Exists then
|
||||
begin
|
||||
{ Fill captions }
|
||||
TagExistsValue.Text := 'Yes';
|
||||
if FileTag.VersionID = TAG_VERSION_1_0 then
|
||||
TagVersionValue.Text := '1.0'
|
||||
else
|
||||
TagVersionValue.Text := '1.1';
|
||||
TitleEdit.Text := FileTag.Title;
|
||||
ArtistEdit.Text := FileTag.Artist;
|
||||
AlbumEdit.Text := FileTag.Album;
|
||||
TrackEdit.Text := IntToStr(FileTag.Track);
|
||||
YearEdit.Text := FileTag.Year;
|
||||
if FileTag.GenreID < MAX_MUSIC_GENRES then
|
||||
GenreComboBox.ItemIndex := FileTag.GenreID + 1;
|
||||
CommentEdit.Text := FileTag.Comment;
|
||||
end
|
||||
else
|
||||
{ Tag not found }
|
||||
TagExistsValue.Text := 'No'
|
||||
else
|
||||
{ Read error }
|
||||
ShowMessage('Can not read tag from the file: ' + FileList.FileName)
|
||||
else
|
||||
{ File does not exist }
|
||||
ShowMessage('The file does not exist: ' + FileList.FileName);
|
||||
end;
|
||||
|
||||
procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
|
||||
begin
|
||||
{ Free memory }
|
||||
FileTag.Free;
|
||||
end;
|
||||
|
||||
procedure TMainForm.SaveButtonClick(Sender: TObject);
|
||||
var
|
||||
Value, Code: Integer;
|
||||
begin
|
||||
{ Prepare tag data }
|
||||
FileTag.Title := TitleEdit.Text;
|
||||
FileTag.Artist := ArtistEdit.Text;
|
||||
FileTag.Album := AlbumEdit.Text;
|
||||
FileTag.Year := YearEdit.Text;
|
||||
Val(TrackEdit.Text, Value, Code);
|
||||
if (Code = 0) and (Value > 0) then FileTag.Track := Value
|
||||
else FileTag.Track := 0;
|
||||
if GenreComboBox.ItemIndex = 0 then FileTag.GenreID := DEFAULT_GENRE
|
||||
else FileTag.GenreID := GenreComboBox.ItemIndex - 1;
|
||||
FileTag.Comment := CommentEdit.Text;
|
||||
{ Save tag data }
|
||||
if (not FileExists(FileList.FileName)) or
|
||||
(not FileTag.SaveToFile(FileList.FileName)) then
|
||||
ShowMessage('Can not save tag to the file: ' + FileList.FileName);
|
||||
FileListChange(Self);
|
||||
end;
|
||||
|
||||
procedure TMainForm.RemoveButtonClick(Sender: TObject);
|
||||
begin
|
||||
{ Delete tag data }
|
||||
if (FileExists(FileList.FileName)) and
|
||||
(FileTag.RemoveFromFile(FileList.FileName)) then ClearAll
|
||||
else ShowMessage('Can not remove tag from the file: ' + FileList.FileName);
|
||||
end;
|
||||
|
||||
end.
|
||||
35
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v1/Test.cfg
Normal file
35
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v1/Test.cfg
Normal file
@@ -0,0 +1,35 @@
|
||||
-$A8
|
||||
-$B-
|
||||
-$C+
|
||||
-$D+
|
||||
-$E-
|
||||
-$F-
|
||||
-$G+
|
||||
-$H+
|
||||
-$I+
|
||||
-$J-
|
||||
-$K-
|
||||
-$L+
|
||||
-$M-
|
||||
-$N+
|
||||
-$O+
|
||||
-$P+
|
||||
-$Q-
|
||||
-$R-
|
||||
-$S-
|
||||
-$T-
|
||||
-$U-
|
||||
-$V+
|
||||
-$W-
|
||||
-$X+
|
||||
-$YD
|
||||
-$Z1
|
||||
-cg
|
||||
-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
|
||||
-H+
|
||||
-W+
|
||||
-M
|
||||
-$M16384,1048576
|
||||
-K$00400000
|
||||
-LE"c:\program files\borland\delphi6\Projects\Bpl"
|
||||
-LN"c:\program files\borland\delphi6\Projects\Bpl"
|
||||
96
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v1/Test.dof
Normal file
96
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v1/Test.dof
Normal file
@@ -0,0 +1,96 @@
|
||||
[FileVersion]
|
||||
Version=6.0
|
||||
[Compiler]
|
||||
A=8
|
||||
B=0
|
||||
C=1
|
||||
D=1
|
||||
E=0
|
||||
F=0
|
||||
G=1
|
||||
H=1
|
||||
I=1
|
||||
J=0
|
||||
K=0
|
||||
L=1
|
||||
M=0
|
||||
N=1
|
||||
O=1
|
||||
P=1
|
||||
Q=0
|
||||
R=0
|
||||
S=0
|
||||
T=0
|
||||
U=0
|
||||
V=1
|
||||
W=0
|
||||
X=1
|
||||
Y=1
|
||||
Z=1
|
||||
ShowHints=1
|
||||
ShowWarnings=1
|
||||
UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
|
||||
[Linker]
|
||||
MapFile=0
|
||||
OutputObjs=0
|
||||
ConsoleApp=1
|
||||
DebugInfo=0
|
||||
RemoteSymbols=0
|
||||
MinStackSize=16384
|
||||
MaxStackSize=1048576
|
||||
ImageBase=4194304
|
||||
ExeDescription=
|
||||
[Directories]
|
||||
OutputDir=
|
||||
UnitOutputDir=
|
||||
PackageDLLOutputDir=
|
||||
PackageDCPOutputDir=
|
||||
SearchPath=
|
||||
Packages=vcl;rtl;dbrtl;adortl;vcldb;vclx;bdertl;vcldbx;ibxpress;dsnap;cds;bdecds;qrpt;teeui;teedb;tee;dss;teeqr;visualclx;visualdbclx;dsnapcrba;dsnapcon;VclSmp;vclshlctrls;vclie;xmlrtl;inet;inetdbbde;inetdbxpress;inetdb;nmfast;webdsnap;websnap;dbexpress;dbxcds;indy;dclOffice2k
|
||||
Conditionals=
|
||||
DebugSourceDirs=
|
||||
UsePackages=0
|
||||
[Parameters]
|
||||
RunParams=
|
||||
HostApplication=
|
||||
Launcher=
|
||||
UseLauncher=0
|
||||
DebugCWD=
|
||||
[Language]
|
||||
ActiveLang=
|
||||
ProjectLang=
|
||||
RootDir=
|
||||
[Version Info]
|
||||
IncludeVerInfo=0
|
||||
AutoIncBuild=0
|
||||
MajorVer=1
|
||||
MinorVer=0
|
||||
Release=0
|
||||
Build=0
|
||||
Debug=0
|
||||
PreRelease=0
|
||||
Special=0
|
||||
Private=0
|
||||
DLL=0
|
||||
Locale=1031
|
||||
CodePage=1252
|
||||
[Version Info Keys]
|
||||
CompanyName=
|
||||
FileDescription=
|
||||
FileVersion=1.0.0.0
|
||||
InternalName=
|
||||
LegalCopyright=
|
||||
LegalTrademarks=
|
||||
OriginalFilename=
|
||||
ProductName=
|
||||
ProductVersion=1.0.0.0
|
||||
Comments=
|
||||
[HistoryLists\hlUnitAliases]
|
||||
Count=1
|
||||
Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
|
||||
[HistoryLists\hlUnitOutputDirectory]
|
||||
Count=1
|
||||
Item0=DCU
|
||||
[HistoryLists\hlOutputDirectorry]
|
||||
Count=1
|
||||
Item0=Data
|
||||
15
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v1/Test.dpr
Normal file
15
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v1/Test.dpr
Normal file
@@ -0,0 +1,15 @@
|
||||
program Test;
|
||||
|
||||
uses
|
||||
Forms,
|
||||
Main in 'Main.pas' {MainForm},
|
||||
ID3v1 in 'ID3v1.pas';
|
||||
|
||||
{$R *.res}
|
||||
|
||||
begin
|
||||
Application.Initialize;
|
||||
Application.Title := 'ID3v1 Test';
|
||||
Application.CreateForm(TMainForm, MainForm);
|
||||
Application.Run;
|
||||
end.
|
||||
BIN
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v1/Test.res
Normal file
BIN
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v1/Test.res
Normal file
Binary file not shown.
631
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v2/ID3v2.pas
Normal file
631
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v2/ID3v2.pas
Normal file
@@ -0,0 +1,631 @@
|
||||
{ *************************************************************************** }
|
||||
{ }
|
||||
{ Audio Tools Library (Freeware) }
|
||||
{ Class TID3v2 - for manipulating with ID3v2 tags }
|
||||
{ }
|
||||
{ Copyright (c) 2001,2002 by Jurgen Faul }
|
||||
{ E-mail: jfaul@gmx.de }
|
||||
{ http://jfaul.de/atl }
|
||||
{ }
|
||||
{ Version 1.4 (24 March 2002) }
|
||||
{ - Reading support for ID3v2.2.x & ID3v2.4.x tags }
|
||||
{ }
|
||||
{ Version 1.3 (16 February 2002) }
|
||||
{ - Fixed bug with property Comment }
|
||||
{ - Added info: composer, encoder, copyright, language, link }
|
||||
{ }
|
||||
{ Version 1.2 (17 October 2001) }
|
||||
{ - Writing support for ID3v2.3.x tags }
|
||||
{ - Fixed bug with track number detection }
|
||||
{ - Fixed bug with tag reading }
|
||||
{ }
|
||||
{ Version 1.1 (31 August 2001) }
|
||||
{ - Added public procedure ResetData }
|
||||
{ }
|
||||
{ Version 1.0 (14 August 2001) }
|
||||
{ - Reading support for ID3v2.3.x tags }
|
||||
{ - Tag info: title, artist, album, track, year, genre, comment }
|
||||
{ }
|
||||
{ *************************************************************************** }
|
||||
|
||||
unit ID3v2;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils;
|
||||
|
||||
const
|
||||
TAG_VERSION_2_2 = 2; { Code for ID3v2.2.x tag }
|
||||
TAG_VERSION_2_3 = 3; { Code for ID3v2.3.x tag }
|
||||
TAG_VERSION_2_4 = 4; { Code for ID3v2.4.x tag }
|
||||
|
||||
type
|
||||
{ Class TID3v2 }
|
||||
TID3v2 = class(TObject)
|
||||
private
|
||||
{ Private declarations }
|
||||
FExists: Boolean;
|
||||
FVersionID: Byte;
|
||||
FSize: Integer;
|
||||
FTitle: string;
|
||||
FArtist: string;
|
||||
FAlbum: string;
|
||||
FTrack: Byte;
|
||||
FYear: string;
|
||||
FGenre: string;
|
||||
FComment: string;
|
||||
FComposer: string;
|
||||
FEncoder: string;
|
||||
FCopyright: string;
|
||||
FLanguage: string;
|
||||
FLink: string;
|
||||
procedure FSetTitle(const NewTitle: string);
|
||||
procedure FSetArtist(const NewArtist: string);
|
||||
procedure FSetAlbum(const NewAlbum: string);
|
||||
procedure FSetTrack(const NewTrack: Byte);
|
||||
procedure FSetYear(const NewYear: string);
|
||||
procedure FSetGenre(const NewGenre: string);
|
||||
procedure FSetComment(const NewComment: string);
|
||||
procedure FSetComposer(const NewComposer: string);
|
||||
procedure FSetEncoder(const NewEncoder: string);
|
||||
procedure FSetCopyright(const NewCopyright: string);
|
||||
procedure FSetLanguage(const NewLanguage: string);
|
||||
procedure FSetLink(const NewLink: string);
|
||||
public
|
||||
{ Public declarations }
|
||||
constructor Create; { Create object }
|
||||
procedure ResetData; { Reset all data }
|
||||
function ReadFromFile(const FileName: string): Boolean; { Load tag }
|
||||
function SaveToFile(const FileName: string): Boolean; { Save tag }
|
||||
function RemoveFromFile(const FileName: string): Boolean; { Delete tag }
|
||||
property Exists: Boolean read FExists; { True if tag found }
|
||||
property VersionID: Byte read FVersionID; { Version code }
|
||||
property Size: Integer read FSize; { Total tag size }
|
||||
property Title: string read FTitle write FSetTitle; { Song title }
|
||||
property Artist: string read FArtist write FSetArtist; { Artist name }
|
||||
property Album: string read FAlbum write FSetAlbum; { Album title }
|
||||
property Track: Byte read FTrack write FSetTrack; { Track number }
|
||||
property Year: string read FYear write FSetYear; { Release year }
|
||||
property Genre: string read FGenre write FSetGenre; { Genre name }
|
||||
property Comment: string read FComment write FSetComment; { Comment }
|
||||
property Composer: string read FComposer write FSetComposer; { Composer }
|
||||
property Encoder: string read FEncoder write FSetEncoder; { Encoder }
|
||||
property Copyright: string read FCopyright write FSetCopyright; { (c) }
|
||||
property Language: string read FLanguage write FSetLanguage; { Language }
|
||||
property Link: string read FLink write FSetLink; { URL link }
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
const
|
||||
{ ID3v2 tag ID }
|
||||
ID3V2_ID = 'ID3';
|
||||
|
||||
{ Max. number of supported tag frames }
|
||||
ID3V2_FRAME_COUNT = 16;
|
||||
|
||||
{ Names of supported tag frames (ID3v2.3.x & ID3v2.4.x) }
|
||||
ID3V2_FRAME_NEW: array [1..ID3V2_FRAME_COUNT] of string =
|
||||
('TIT2', 'TPE1', 'TALB', 'TRCK', 'TYER', 'TCON', 'COMM', 'TCOM', 'TENC',
|
||||
'TCOP', 'TLAN', 'WXXX', 'TDRC', 'TOPE', 'TIT1', 'TOAL');
|
||||
|
||||
{ Names of supported tag frames (ID3v2.2.x) }
|
||||
ID3V2_FRAME_OLD: array [1..ID3V2_FRAME_COUNT] of string =
|
||||
('TT2', 'TP1', 'TAL', 'TRK', 'TYE', 'TCO', 'COM', 'TCM', 'TEN',
|
||||
'TCR', 'TLA', 'WXX', 'TOR', 'TOA', 'TT1', 'TOT');
|
||||
|
||||
type
|
||||
{ Frame header (ID3v2.3.x & ID3v2.4.x) }
|
||||
FrameHeaderNew = record
|
||||
ID: array [1..4] of Char; { Frame ID }
|
||||
Size: Integer; { Size excluding header }
|
||||
Flags: Word; { Flags }
|
||||
end;
|
||||
|
||||
{ Frame header (ID3v2.2.x) }
|
||||
FrameHeaderOld = record
|
||||
ID: array [1..3] of Char; { Frame ID }
|
||||
Size: array [1..3] of Byte; { Size excluding header }
|
||||
end;
|
||||
|
||||
{ ID3v2 header data - for internal use }
|
||||
TagInfo = record
|
||||
{ Real structure of ID3v2 header }
|
||||
ID: array [1..3] of Char; { Always "ID3" }
|
||||
Version: Byte; { Version number }
|
||||
Revision: Byte; { Revision number }
|
||||
Flags: Byte; { Flags of tag }
|
||||
Size: array [1..4] of Byte; { Tag size excluding header }
|
||||
{ Extended data }
|
||||
FileSize: Integer; { File size (bytes) }
|
||||
Frame: array [1..ID3V2_FRAME_COUNT] of string; { Information from frames }
|
||||
end;
|
||||
|
||||
{ ********************* Auxiliary functions & procedures ******************** }
|
||||
|
||||
function ReadHeader(const FileName: string; var Tag: TagInfo): Boolean;
|
||||
var
|
||||
SourceFile: file;
|
||||
Transferred: Integer;
|
||||
begin
|
||||
try
|
||||
Result := true;
|
||||
{ Set read-access and open file }
|
||||
AssignFile(SourceFile, FileName);
|
||||
FileMode := 0;
|
||||
Reset(SourceFile, 1);
|
||||
{ Read header and get file size }
|
||||
BlockRead(SourceFile, Tag, 10, Transferred);
|
||||
Tag.FileSize := FileSize(SourceFile);
|
||||
CloseFile(SourceFile);
|
||||
{ if transfer is not complete }
|
||||
if Transferred < 10 then Result := false;
|
||||
except
|
||||
{ Error }
|
||||
Result := false;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function GetTagSize(const Tag: TagInfo): Integer;
|
||||
begin
|
||||
{ Get total tag size }
|
||||
Result :=
|
||||
Tag.Size[1] * $200000 +
|
||||
Tag.Size[2] * $4000 +
|
||||
Tag.Size[3] * $80 +
|
||||
Tag.Size[4] + 10;
|
||||
if Tag.Flags and $10 > 0 then Inc(Result, 10);
|
||||
if Result > Tag.FileSize then Result := 0;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure SetTagItem(const ID, Data: string; var Tag: TagInfo);
|
||||
var
|
||||
Iterator: Byte;
|
||||
FrameID: string;
|
||||
begin
|
||||
{ Set tag item if supported frame found }
|
||||
for Iterator := 1 to ID3V2_FRAME_COUNT do
|
||||
begin
|
||||
if Tag.Version > TAG_VERSION_2_2 then FrameID := ID3V2_FRAME_NEW[Iterator]
|
||||
else FrameID := ID3V2_FRAME_OLD[Iterator];
|
||||
if FrameID = ID then Tag.Frame[Iterator] := Data;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function Swap32(const Figure: Integer): Integer;
|
||||
var
|
||||
ByteArray: array [1..4] of Byte absolute Figure;
|
||||
begin
|
||||
{ Swap 4 bytes }
|
||||
Result :=
|
||||
ByteArray[1] * $1000000 +
|
||||
ByteArray[2] * $10000 +
|
||||
ByteArray[3] * $100 +
|
||||
ByteArray[4];
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure ReadFramesNew(const FileName: string; var Tag: TagInfo);
|
||||
var
|
||||
SourceFile: file;
|
||||
Frame: FrameHeaderNew;
|
||||
Data: array [1..250] of Char;
|
||||
DataPosition, DataSize: Integer;
|
||||
begin
|
||||
{ Get information from frames (ID3v2.3.x & ID3v2.4.x) }
|
||||
try
|
||||
{ Set read-access, open file }
|
||||
AssignFile(SourceFile, FileName);
|
||||
FileMode := 0;
|
||||
Reset(SourceFile, 1);
|
||||
Seek(SourceFile, 10);
|
||||
while (FilePos(SourceFile) < GetTagSize(Tag)) and (not EOF(SourceFile)) do
|
||||
begin
|
||||
FillChar(Data, SizeOf(Data), 0);
|
||||
{ Read frame header and check frame ID }
|
||||
BlockRead(SourceFile, Frame, 10);
|
||||
if not (Frame.ID[1] in ['A'..'Z']) then break;
|
||||
{ Note data position and determine significant data size }
|
||||
DataPosition := FilePos(SourceFile);
|
||||
if Swap32(Frame.Size) > SizeOf(Data) then DataSize := SizeOf(Data)
|
||||
else DataSize := Swap32(Frame.Size);
|
||||
{ Read frame data and set tag item if frame supported }
|
||||
BlockRead(SourceFile, Data, DataSize);
|
||||
SetTagItem(Frame.ID, Data, Tag);
|
||||
Seek(SourceFile, DataPosition + Swap32(Frame.Size));
|
||||
end;
|
||||
CloseFile(SourceFile);
|
||||
except
|
||||
end;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure ReadFramesOld(const FileName: string; var Tag: TagInfo);
|
||||
var
|
||||
SourceFile: file;
|
||||
Frame: FrameHeaderOld;
|
||||
Data: array [1..250] of Char;
|
||||
DataPosition, FrameSize, DataSize: Integer;
|
||||
begin
|
||||
{ Get information from frames (ID3v2.2.x) }
|
||||
try
|
||||
{ Set read-access, open file }
|
||||
AssignFile(SourceFile, FileName);
|
||||
FileMode := 0;
|
||||
Reset(SourceFile, 1);
|
||||
Seek(SourceFile, 10);
|
||||
while (FilePos(SourceFile) < GetTagSize(Tag)) and (not EOF(SourceFile)) do
|
||||
begin
|
||||
FillChar(Data, SizeOf(Data), 0);
|
||||
{ Read frame header and check frame ID }
|
||||
BlockRead(SourceFile, Frame, 6);
|
||||
if not (Frame.ID[1] in ['A'..'Z']) then break;
|
||||
{ Note data position and determine significant data size }
|
||||
DataPosition := FilePos(SourceFile);
|
||||
FrameSize := Frame.Size[1] shl 16 + Frame.Size[2] shl 8 + Frame.Size[3];
|
||||
if FrameSize > SizeOf(Data) then DataSize := SizeOf(Data)
|
||||
else DataSize := FrameSize;
|
||||
{ Read frame data and set tag item if frame supported }
|
||||
BlockRead(SourceFile, Data, DataSize);
|
||||
SetTagItem(Frame.ID, Data, Tag);
|
||||
Seek(SourceFile, DataPosition + FrameSize);
|
||||
end;
|
||||
CloseFile(SourceFile);
|
||||
except
|
||||
end;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function GetContent(const Content1, Content2: string): string;
|
||||
begin
|
||||
{ Get content preferring the first content }
|
||||
Result := Trim(Content1);
|
||||
if Result = '' then Result := Trim(Content2);
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function ExtractTrack(const TrackString: string): Byte;
|
||||
var
|
||||
Index, Value, Code: Integer;
|
||||
begin
|
||||
{ Extract track from string }
|
||||
Index := Pos('/', Trim(TrackString));
|
||||
if Index = 0 then Val(Trim(TrackString), Value, Code)
|
||||
else Val(Copy(Trim(TrackString), 1, Index - 1), Value, Code);
|
||||
if Code = 0 then Result := Value
|
||||
else Result := 0;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function ExtractYear(const YearString, DateString: string): string;
|
||||
begin
|
||||
{ Extract year from strings }
|
||||
Result := Trim(YearString);
|
||||
if Result = '' then Result := Copy(Trim(DateString), 1, 4);
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function ExtractGenre(const GenreString: string): string;
|
||||
begin
|
||||
{ Extract genre from string }
|
||||
Result := Trim(GenreString);
|
||||
if Pos(')', Result) > 0 then Delete(Result, 1, LastDelimiter(')', Result));
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function ExtractComment(const CommentString: string): string;
|
||||
var
|
||||
Comment: string;
|
||||
begin
|
||||
{ Extract comment from string }
|
||||
Comment := CommentString;
|
||||
Delete(Comment, 1, 4);
|
||||
Delete(Comment, 1, Pos(#0, Comment));
|
||||
Result := Trim(Comment);
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function ExtractLink(const LinkString: string): string;
|
||||
var
|
||||
Link: string;
|
||||
begin
|
||||
{ Extract URL link from string }
|
||||
Link := LinkString;
|
||||
Delete(Link, 1, 1);
|
||||
Delete(Link, 1, Pos(#0, Link));
|
||||
Result := Trim(Link);
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure BuildHeader(var Tag: TagInfo);
|
||||
var
|
||||
Iterator, TagSize: Integer;
|
||||
begin
|
||||
{ Build tag header }
|
||||
Tag.ID := ID3V2_ID;
|
||||
Tag.Version := TAG_VERSION_2_3;
|
||||
Tag.Revision := 0;
|
||||
Tag.Flags := 0;
|
||||
TagSize := 0;
|
||||
for Iterator := 1 to ID3V2_FRAME_COUNT do
|
||||
if Tag.Frame[Iterator] <> '' then
|
||||
Inc(TagSize, Length(Tag.Frame[Iterator]) + 11);
|
||||
{ Convert tag size }
|
||||
Tag.Size[1] := TagSize div $200000;
|
||||
Tag.Size[2] := TagSize div $4000;
|
||||
Tag.Size[3] := TagSize div $80;
|
||||
Tag.Size[4] := TagSize mod $80;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function RebuildFile(const FileName: string; TagData: TStream): Boolean;
|
||||
var
|
||||
Tag: TagInfo;
|
||||
Source, Destination: TFileStream;
|
||||
BufferName: string;
|
||||
begin
|
||||
{ Rebuild file with old file data and new tag data (optional) }
|
||||
Result := false;
|
||||
if (not FileExists(FileName)) or (FileSetAttr(FileName, 0) <> 0) then exit;
|
||||
if not ReadHeader(FileName, Tag) then exit;
|
||||
if (TagData = nil) and (Tag.ID <> ID3V2_ID) then exit;
|
||||
try
|
||||
{ Create file streams }
|
||||
BufferName := FileName + '~';
|
||||
Source := TFileStream.Create(FileName, fmOpenRead or fmShareExclusive);
|
||||
Destination := TFileStream.Create(BufferName, fmCreate);
|
||||
{ Copy data blocks }
|
||||
if Tag.ID = ID3V2_ID then Source.Seek(GetTagSize(Tag), soFromBeginning);
|
||||
if TagData <> nil then Destination.CopyFrom(TagData, 0);
|
||||
Destination.CopyFrom(Source, Source.Size - Source.Position);
|
||||
{ Free resources }
|
||||
Source.Free;
|
||||
Destination.Free;
|
||||
{ Replace old file and delete temporary file }
|
||||
if (DeleteFile(FileName)) and (RenameFile(BufferName, FileName)) then
|
||||
Result := true
|
||||
else
|
||||
raise Exception.Create('');
|
||||
except
|
||||
{ Access error }
|
||||
if FileExists(BufferName) then DeleteFile(BufferName);
|
||||
end;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function SaveTag(const FileName: string; Tag: TagInfo): Boolean;
|
||||
var
|
||||
TagData: TStringStream;
|
||||
Iterator, FrameSize: Integer;
|
||||
begin
|
||||
{ Build and write tag header and frames to stream }
|
||||
TagData := TStringStream.Create('');
|
||||
BuildHeader(Tag);
|
||||
TagData.Write(Tag, 10);
|
||||
for Iterator := 1 to ID3V2_FRAME_COUNT do
|
||||
if Tag.Frame[Iterator] <> '' then
|
||||
begin
|
||||
TagData.WriteString(ID3V2_FRAME_NEW[Iterator]);
|
||||
FrameSize := Swap32(Length(Tag.Frame[Iterator]) + 1);
|
||||
TagData.Write(FrameSize, SizeOf(FrameSize));
|
||||
TagData.WriteString(#0#0#0 + Tag.Frame[Iterator]);
|
||||
end;
|
||||
{ Rebuild file with new tag data }
|
||||
Result := RebuildFile(FileName, TagData);
|
||||
TagData.Free;
|
||||
end;
|
||||
|
||||
{ ********************** Private functions & procedures ********************* }
|
||||
|
||||
procedure TID3v2.FSetTitle(const NewTitle: string);
|
||||
begin
|
||||
{ Set song title }
|
||||
FTitle := Trim(NewTitle);
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure TID3v2.FSetArtist(const NewArtist: string);
|
||||
begin
|
||||
{ Set artist name }
|
||||
FArtist := Trim(NewArtist);
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure TID3v2.FSetAlbum(const NewAlbum: string);
|
||||
begin
|
||||
{ Set album title }
|
||||
FAlbum := Trim(NewAlbum);
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure TID3v2.FSetTrack(const NewTrack: Byte);
|
||||
begin
|
||||
{ Set track number }
|
||||
FTrack := NewTrack;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure TID3v2.FSetYear(const NewYear: string);
|
||||
begin
|
||||
{ Set release year }
|
||||
FYear := Trim(NewYear);
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure TID3v2.FSetGenre(const NewGenre: string);
|
||||
begin
|
||||
{ Set genre name }
|
||||
FGenre := Trim(NewGenre);
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure TID3v2.FSetComment(const NewComment: string);
|
||||
begin
|
||||
{ Set comment }
|
||||
FComment := Trim(NewComment);
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure TID3v2.FSetComposer(const NewComposer: string);
|
||||
begin
|
||||
{ Set composer name }
|
||||
FComposer := Trim(NewComposer);
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure TID3v2.FSetEncoder(const NewEncoder: string);
|
||||
begin
|
||||
{ Set encoder name }
|
||||
FEncoder := Trim(NewEncoder);
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure TID3v2.FSetCopyright(const NewCopyright: string);
|
||||
begin
|
||||
{ Set copyright information }
|
||||
FCopyright := Trim(NewCopyright);
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure TID3v2.FSetLanguage(const NewLanguage: string);
|
||||
begin
|
||||
{ Set language }
|
||||
FLanguage := Trim(NewLanguage);
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure TID3v2.FSetLink(const NewLink: string);
|
||||
begin
|
||||
{ Set URL link }
|
||||
FLink := Trim(NewLink);
|
||||
end;
|
||||
|
||||
{ ********************** Public functions & procedures ********************** }
|
||||
|
||||
constructor TID3v2.Create;
|
||||
begin
|
||||
{ Create object }
|
||||
inherited;
|
||||
ResetData;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
procedure TID3v2.ResetData;
|
||||
begin
|
||||
{ Reset all variables }
|
||||
FExists := false;
|
||||
FVersionID := 0;
|
||||
FSize := 0;
|
||||
FTitle := '';
|
||||
FArtist := '';
|
||||
FAlbum := '';
|
||||
FTrack := 0;
|
||||
FYear := '';
|
||||
FGenre := '';
|
||||
FComment := '';
|
||||
FComposer := '';
|
||||
FEncoder := '';
|
||||
FCopyright := '';
|
||||
FLanguage := '';
|
||||
FLink := '';
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function TID3v2.ReadFromFile(const FileName: string): Boolean;
|
||||
var
|
||||
Tag: TagInfo;
|
||||
begin
|
||||
{ Reset data and load header from file to variable }
|
||||
ResetData;
|
||||
Result := ReadHeader(FileName, Tag);
|
||||
{ Process data if loaded and header valid }
|
||||
if (Result) and (Tag.ID = ID3V2_ID) then
|
||||
begin
|
||||
FExists := true;
|
||||
{ Fill properties with header data }
|
||||
FVersionID := Tag.Version;
|
||||
FSize := GetTagSize(Tag);
|
||||
{ Get information from frames if version supported }
|
||||
if (FVersionID in [TAG_VERSION_2_2..TAG_VERSION_2_4]) and (FSize > 0) then
|
||||
begin
|
||||
if FVersionID > TAG_VERSION_2_2 then ReadFramesNew(FileName, Tag)
|
||||
else ReadFramesOld(FileName, Tag);
|
||||
FTitle := GetContent(Tag.Frame[1], Tag.Frame[15]);
|
||||
FArtist := GetContent(Tag.Frame[2], Tag.Frame[14]);
|
||||
FAlbum := GetContent(Tag.Frame[3], Tag.Frame[16]);
|
||||
FTrack := ExtractTrack(Tag.Frame[4]);
|
||||
FYear := ExtractYear(Tag.Frame[5], Tag.Frame[13]);
|
||||
FGenre := ExtractGenre(Tag.Frame[6]);
|
||||
FComment := ExtractComment(Tag.Frame[7]);
|
||||
FComposer := Trim(Tag.Frame[8]);
|
||||
FEncoder := Trim(Tag.Frame[9]);
|
||||
FCopyright := Trim(Tag.Frame[10]);
|
||||
FLanguage := Trim(Tag.Frame[11]);
|
||||
FLink := ExtractLink(Tag.Frame[12]);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function TID3v2.SaveToFile(const FileName: string): Boolean;
|
||||
var
|
||||
Tag: TagInfo;
|
||||
begin
|
||||
{ Prepare tag data and save to file }
|
||||
FillChar(Tag, SizeOf(Tag), 0);
|
||||
Tag.Frame[1] := FTitle;
|
||||
Tag.Frame[2] := FArtist;
|
||||
Tag.Frame[3] := FAlbum;
|
||||
if FTrack > 0 then Tag.Frame[4] := IntToStr(FTrack);
|
||||
Tag.Frame[5] := FYear;
|
||||
Tag.Frame[6] := FGenre;
|
||||
if FComment <> '' then Tag.Frame[7] := 'eng' + #0 + FComment;
|
||||
Tag.Frame[8] := FComposer;
|
||||
Tag.Frame[9] := FEncoder;
|
||||
Tag.Frame[10] := FCopyright;
|
||||
Tag.Frame[11] := FLanguage;
|
||||
if FLink <> '' then Tag.Frame[12] := #0 + FLink;
|
||||
Result := SaveTag(FileName, Tag);
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function TID3v2.RemoveFromFile(const FileName: string): Boolean;
|
||||
begin
|
||||
{ Remove tag from file }
|
||||
Result := RebuildFile(FileName, nil);
|
||||
end;
|
||||
|
||||
end.
|
||||
32
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v2/Info.txt
Normal file
32
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v2/Info.txt
Normal file
@@ -0,0 +1,32 @@
|
||||
ID3v2.pas
|
||||
Tested with Borland Delphi 3,4,5,6
|
||||
|
||||
{ *************************************************************************** }
|
||||
{ }
|
||||
{ Audio Tools Library (Freeware) }
|
||||
{ Class TID3v2 - for manipulating with ID3v2 tags }
|
||||
{ }
|
||||
{ Copyright (c) 2001,2002 by Jurgen Faul }
|
||||
{ E-mail: jfaul@gmx.de }
|
||||
{ http://jfaul.de/atl }
|
||||
{ }
|
||||
{ Version 1.4 (24 March 2002) }
|
||||
{ - Reading support for ID3v2.2.x & ID3v2.4.x tags }
|
||||
{ }
|
||||
{ Version 1.3 (16 February 2002) }
|
||||
{ - Fixed bug with property Comment }
|
||||
{ - Added info: composer, encoder, copyright, language, link }
|
||||
{ }
|
||||
{ Version 1.2 (17 October 2001) }
|
||||
{ - Writing support for ID3v2.3.x tags }
|
||||
{ - Fixed bug with track number detection }
|
||||
{ - Fixed bug with tag reading }
|
||||
{ }
|
||||
{ Version 1.1 (31 August 2001) }
|
||||
{ - Added public procedure ResetData }
|
||||
{ }
|
||||
{ Version 1.0 (14 August 2001) }
|
||||
{ - Reading support for ID3v2.3.x tags }
|
||||
{ - Tag info: title, artist, album, track, year, genre, comment }
|
||||
{ }
|
||||
{ *************************************************************************** }
|
||||
BIN
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v2/Main.dfm
Normal file
BIN
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v2/Main.dfm
Normal file
Binary file not shown.
179
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v2/Main.pas
Normal file
179
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v2/Main.pas
Normal file
@@ -0,0 +1,179 @@
|
||||
unit Main;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
|
||||
StdCtrls, FileCtrl, ExtCtrls, ID3v2;
|
||||
|
||||
type
|
||||
TMainForm = class(TForm)
|
||||
DriveList: TDriveComboBox;
|
||||
FolderList: TDirectoryListBox;
|
||||
FileList: TFileListBox;
|
||||
SaveButton: TButton;
|
||||
RemoveButton: TButton;
|
||||
CloseButton: TButton;
|
||||
InfoBevel: TBevel;
|
||||
IconImage: TImage;
|
||||
TagExistsLabel: TLabel;
|
||||
TagExistsValue: TEdit;
|
||||
VersionLabel: TLabel;
|
||||
VersionValue: TEdit;
|
||||
SizeLabel: TLabel;
|
||||
SizeValue: TEdit;
|
||||
TitleLabel: TLabel;
|
||||
TitleEdit: TEdit;
|
||||
ArtistLabel: TLabel;
|
||||
ArtistEdit: TEdit;
|
||||
AlbumLabel: TLabel;
|
||||
AlbumEdit: TEdit;
|
||||
TrackLabel: TLabel;
|
||||
TrackEdit: TEdit;
|
||||
YearLabel: TLabel;
|
||||
YearEdit: TEdit;
|
||||
GenreLabel: TLabel;
|
||||
GenreEdit: TEdit;
|
||||
CommentLabel: TLabel;
|
||||
CommentEdit: TEdit;
|
||||
ComposerLabel: TLabel;
|
||||
ComposerEdit: TEdit;
|
||||
EncoderLabel: TLabel;
|
||||
EncoderEdit: TEdit;
|
||||
CopyrightLabel: TLabel;
|
||||
CopyrightEdit: TEdit;
|
||||
LanguageLabel: TLabel;
|
||||
LanguageEdit: TEdit;
|
||||
LinkLabel: TLabel;
|
||||
LinkEdit: TEdit;
|
||||
procedure FormCreate(Sender: TObject);
|
||||
procedure FileListChange(Sender: TObject);
|
||||
procedure FormClose(Sender: TObject; var Action: TCloseAction);
|
||||
procedure SaveButtonClick(Sender: TObject);
|
||||
procedure RemoveButtonClick(Sender: TObject);
|
||||
procedure CloseButtonClick(Sender: TObject);
|
||||
private
|
||||
{ Private declarations }
|
||||
FileTag: TID3v2;
|
||||
procedure ClearAll;
|
||||
end;
|
||||
|
||||
var
|
||||
MainForm: TMainForm;
|
||||
|
||||
implementation
|
||||
|
||||
{$R *.dfm}
|
||||
|
||||
procedure TMainForm.ClearAll;
|
||||
begin
|
||||
{ Clear all captions }
|
||||
TagExistsValue.Text := '';
|
||||
VersionValue.Text := '';
|
||||
SizeValue.Text := '';
|
||||
TitleEdit.Text := '';
|
||||
ArtistEdit.Text := '';
|
||||
AlbumEdit.Text := '';
|
||||
TrackEdit.Text := '';
|
||||
YearEdit.Text := '';
|
||||
GenreEdit.Text := '';
|
||||
CommentEdit.Text := '';
|
||||
ComposerEdit.Text := '';
|
||||
EncoderEdit.Text := '';
|
||||
CopyrightEdit.Text := '';
|
||||
LanguageEdit.Text := '';
|
||||
LinkEdit.Text := '';
|
||||
end;
|
||||
|
||||
procedure TMainForm.FormCreate(Sender: TObject);
|
||||
begin
|
||||
{ Create object and clear captions }
|
||||
FileTag := TID3v2.Create;
|
||||
ClearAll;
|
||||
end;
|
||||
|
||||
procedure TMainForm.FileListChange(Sender: TObject);
|
||||
begin
|
||||
{ Clear captions }
|
||||
ClearAll;
|
||||
if FileList.FileName = '' then exit;
|
||||
if FileExists(FileList.FileName) then
|
||||
{ Load tag data }
|
||||
if FileTag.ReadFromFile(FileList.FileName) then
|
||||
if FileTag.Exists then
|
||||
begin
|
||||
{ Fill captions }
|
||||
TagExistsValue.Text := 'Yes';
|
||||
VersionValue.Text := '2.' + IntToStr(FileTag.VersionID);
|
||||
SizeValue.Text := IntToStr(FileTag.Size) + ' bytes';
|
||||
TitleEdit.Text := FileTag.Title;
|
||||
ArtistEdit.Text := FileTag.Artist;
|
||||
AlbumEdit.Text := FileTag.Album;
|
||||
if FileTag.Track > 0 then TrackEdit.Text := IntToStr(FileTag.Track);
|
||||
YearEdit.Text := FileTag.Year;
|
||||
GenreEdit.Text := FileTag.Genre;
|
||||
CommentEdit.Text := FileTag.Comment;
|
||||
ComposerEdit.Text := FileTag.Composer;
|
||||
EncoderEdit.Text := FileTag.Encoder;
|
||||
CopyrightEdit.Text := FileTag.Copyright;
|
||||
LanguageEdit.Text := FileTag.Language;
|
||||
LinkEdit.Text := FileTag.Link;
|
||||
end
|
||||
else
|
||||
{ Tag not found }
|
||||
TagExistsValue.Text := 'No'
|
||||
else
|
||||
{ Read error }
|
||||
ShowMessage('Can not read tag from the file: ' + FileList.FileName)
|
||||
else
|
||||
{ File does not exist }
|
||||
ShowMessage('The file does not exist: ' + FileList.FileName);
|
||||
end;
|
||||
|
||||
procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
|
||||
begin
|
||||
{ Free memory }
|
||||
FileTag.Free;
|
||||
end;
|
||||
|
||||
procedure TMainForm.SaveButtonClick(Sender: TObject);
|
||||
var
|
||||
Value, Code: Integer;
|
||||
begin
|
||||
{ Prepare tag data }
|
||||
FileTag.Title := TitleEdit.Text;
|
||||
FileTag.Artist := ArtistEdit.Text;
|
||||
FileTag.Album := AlbumEdit.Text;
|
||||
Val(TrackEdit.Text, Value, Code);
|
||||
if (Code = 0) and (Value > 0) then FileTag.Track := Value
|
||||
else FileTag.Track := 0;
|
||||
FileTag.Year := YearEdit.Text;
|
||||
FileTag.Genre := GenreEdit.Text;
|
||||
FileTag.Comment := CommentEdit.Text;
|
||||
FileTag.Composer := ComposerEdit.Text;
|
||||
FileTag.Encoder := EncoderEdit.Text;
|
||||
FileTag.Copyright := CopyrightEdit.Text;
|
||||
FileTag.Language := LanguageEdit.Text;
|
||||
FileTag.Link := LinkEdit.Text;
|
||||
{ Save tag data }
|
||||
if (not FileExists(FileList.FileName)) or
|
||||
(not FileTag.SaveToFile(FileList.FileName)) then
|
||||
ShowMessage('Can not save tag to the file: ' + FileList.FileName);
|
||||
FileListChange(Self);
|
||||
end;
|
||||
|
||||
procedure TMainForm.RemoveButtonClick(Sender: TObject);
|
||||
begin
|
||||
{ Delete tag data }
|
||||
if (FileExists(FileList.FileName)) and
|
||||
(FileTag.RemoveFromFile(FileList.FileName)) then ClearAll
|
||||
else ShowMessage('Can not remove tag from the file: ' + FileList.FileName);
|
||||
end;
|
||||
|
||||
procedure TMainForm.CloseButtonClick(Sender: TObject);
|
||||
begin
|
||||
{ Exit }
|
||||
Close;
|
||||
end;
|
||||
|
||||
end.
|
||||
35
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v2/Test.cfg
Normal file
35
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v2/Test.cfg
Normal file
@@ -0,0 +1,35 @@
|
||||
-$A8
|
||||
-$B-
|
||||
-$C+
|
||||
-$D+
|
||||
-$E-
|
||||
-$F-
|
||||
-$G+
|
||||
-$H+
|
||||
-$I+
|
||||
-$J-
|
||||
-$K-
|
||||
-$L+
|
||||
-$M-
|
||||
-$N+
|
||||
-$O+
|
||||
-$P+
|
||||
-$Q-
|
||||
-$R-
|
||||
-$S-
|
||||
-$T-
|
||||
-$U-
|
||||
-$V+
|
||||
-$W-
|
||||
-$X+
|
||||
-$YD
|
||||
-$Z1
|
||||
-cg
|
||||
-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
|
||||
-H+
|
||||
-W+
|
||||
-M
|
||||
-$M16384,1048576
|
||||
-K$00400000
|
||||
-LE"c:\program files\borland\delphi6\Projects\Bpl"
|
||||
-LN"c:\program files\borland\delphi6\Projects\Bpl"
|
||||
96
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v2/Test.dof
Normal file
96
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v2/Test.dof
Normal file
@@ -0,0 +1,96 @@
|
||||
[FileVersion]
|
||||
Version=6.0
|
||||
[Compiler]
|
||||
A=8
|
||||
B=0
|
||||
C=1
|
||||
D=1
|
||||
E=0
|
||||
F=0
|
||||
G=1
|
||||
H=1
|
||||
I=1
|
||||
J=0
|
||||
K=0
|
||||
L=1
|
||||
M=0
|
||||
N=1
|
||||
O=1
|
||||
P=1
|
||||
Q=0
|
||||
R=0
|
||||
S=0
|
||||
T=0
|
||||
U=0
|
||||
V=1
|
||||
W=0
|
||||
X=1
|
||||
Y=1
|
||||
Z=1
|
||||
ShowHints=1
|
||||
ShowWarnings=1
|
||||
UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
|
||||
[Linker]
|
||||
MapFile=0
|
||||
OutputObjs=0
|
||||
ConsoleApp=1
|
||||
DebugInfo=0
|
||||
RemoteSymbols=0
|
||||
MinStackSize=16384
|
||||
MaxStackSize=1048576
|
||||
ImageBase=4194304
|
||||
ExeDescription=
|
||||
[Directories]
|
||||
OutputDir=
|
||||
UnitOutputDir=
|
||||
PackageDLLOutputDir=
|
||||
PackageDCPOutputDir=
|
||||
SearchPath=
|
||||
Packages=vcl;rtl;dbrtl;adortl;vcldb;vclx;bdertl;vcldbx;ibxpress;dsnap;cds;bdecds;qrpt;teeui;teedb;tee;dss;teeqr;visualclx;visualdbclx;dsnapcrba;dsnapcon;VclSmp;vclshlctrls;vclie;xmlrtl;inet;inetdbbde;inetdbxpress;inetdb;nmfast;webdsnap;websnap;dbexpress;dbxcds;indy;dclOffice2k
|
||||
Conditionals=
|
||||
DebugSourceDirs=
|
||||
UsePackages=0
|
||||
[Parameters]
|
||||
RunParams=
|
||||
HostApplication=
|
||||
Launcher=
|
||||
UseLauncher=0
|
||||
DebugCWD=
|
||||
[Language]
|
||||
ActiveLang=
|
||||
ProjectLang=
|
||||
RootDir=
|
||||
[Version Info]
|
||||
IncludeVerInfo=0
|
||||
AutoIncBuild=0
|
||||
MajorVer=1
|
||||
MinorVer=0
|
||||
Release=0
|
||||
Build=0
|
||||
Debug=0
|
||||
PreRelease=0
|
||||
Special=0
|
||||
Private=0
|
||||
DLL=0
|
||||
Locale=1031
|
||||
CodePage=1252
|
||||
[Version Info Keys]
|
||||
CompanyName=
|
||||
FileDescription=
|
||||
FileVersion=1.0.0.0
|
||||
InternalName=
|
||||
LegalCopyright=
|
||||
LegalTrademarks=
|
||||
OriginalFilename=
|
||||
ProductName=
|
||||
ProductVersion=1.0.0.0
|
||||
Comments=
|
||||
[HistoryLists\hlUnitAliases]
|
||||
Count=1
|
||||
Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
|
||||
[HistoryLists\hlUnitOutputDirectory]
|
||||
Count=1
|
||||
Item0=DCU
|
||||
[HistoryLists\hlOutputDirectorry]
|
||||
Count=1
|
||||
Item0=Data
|
||||
15
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v2/Test.dpr
Normal file
15
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v2/Test.dpr
Normal file
@@ -0,0 +1,15 @@
|
||||
program Test;
|
||||
|
||||
uses
|
||||
Forms,
|
||||
Main in 'Main.pas' {MainForm},
|
||||
ID3v2 in 'ID3v2.pas';
|
||||
|
||||
{$R *.res}
|
||||
|
||||
begin
|
||||
Application.Initialize;
|
||||
Application.Title := 'ID3v2 Test';
|
||||
Application.CreateForm(TMainForm, MainForm);
|
||||
Application.Run;
|
||||
end.
|
||||
BIN
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v2/Test.res
Normal file
BIN
MAC_SDK/3rd Party/TMonkey (Delphi)/ID3v2/Test.res
Normal file
Binary file not shown.
30
MAC_SDK/3rd Party/TMonkey (Delphi)/Monkey/Info.txt
Normal file
30
MAC_SDK/3rd Party/TMonkey (Delphi)/Monkey/Info.txt
Normal file
@@ -0,0 +1,30 @@
|
||||
Monkey.pas (ID3v1.pas, ID3v2.pas, APEtag.pas needed)
|
||||
Tested with Borland Delphi 3,4,5,6
|
||||
|
||||
{ *************************************************************************** }
|
||||
{ }
|
||||
{ Audio Tools Library (Freeware) }
|
||||
{ Class TMonkey - for manipulating with Monkey's Audio file information }
|
||||
{ }
|
||||
{ Uses: }
|
||||
{ - Class TID3v1 }
|
||||
{ - Class TID3v2 }
|
||||
{ - Class TAPEtag }
|
||||
{ }
|
||||
{ Copyright (c) 2001,2002 by Jurgen Faul }
|
||||
{ E-mail: jfaul@gmx.de }
|
||||
{ http://jfaul.de/atl }
|
||||
{ }
|
||||
{ Version 1.2 (21 April 2002) }
|
||||
{ - Class TID3v2: support for ID3v2 tags }
|
||||
{ - Class TAPEtag: support for APE tags }
|
||||
{ }
|
||||
{ Version 1.1 (11 September 2001) }
|
||||
{ - Added property Samples }
|
||||
{ - Removed WAV header information }
|
||||
{ }
|
||||
{ Version 1.0 (7 September 2001) }
|
||||
{ - Support for Monkey's Audio files }
|
||||
{ - Class TID3v1: reading & writing support for ID3v1.x tags }
|
||||
{ }
|
||||
{ *************************************************************************** }
|
||||
BIN
MAC_SDK/3rd Party/TMonkey (Delphi)/Monkey/Main.dfm
Normal file
BIN
MAC_SDK/3rd Party/TMonkey (Delphi)/Monkey/Main.dfm
Normal file
Binary file not shown.
131
MAC_SDK/3rd Party/TMonkey (Delphi)/Monkey/Main.pas
Normal file
131
MAC_SDK/3rd Party/TMonkey (Delphi)/Monkey/Main.pas
Normal file
@@ -0,0 +1,131 @@
|
||||
unit Main;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
|
||||
StdCtrls, FileCtrl, ExtCtrls, Monkey;
|
||||
|
||||
type
|
||||
TMainForm = class(TForm)
|
||||
DriveList: TDriveComboBox;
|
||||
FolderList: TDirectoryListBox;
|
||||
FileList: TFileListBox;
|
||||
CloseButton: TButton;
|
||||
InfoBevel: TBevel;
|
||||
IconImage: TImage;
|
||||
ValidHeaderLabel: TLabel;
|
||||
FileLengthLabel: TLabel;
|
||||
ValidHeaderValue: TEdit;
|
||||
ChannelModeValue: TEdit;
|
||||
ChannelModeLabel: TLabel;
|
||||
SampleRateLabel: TLabel;
|
||||
BitsPerSampleLabel: TLabel;
|
||||
DurationLabel: TLabel;
|
||||
SampleRateValue: TEdit;
|
||||
BitsPerSampleValue: TEdit;
|
||||
DurationValue: TEdit;
|
||||
FileLengthValue: TEdit;
|
||||
CompressionLabel: TLabel;
|
||||
CompressionValue: TEdit;
|
||||
PeakLevelLabel: TLabel;
|
||||
PeakLevelValue: TEdit;
|
||||
FramesLabel: TLabel;
|
||||
FramesValue: TEdit;
|
||||
FlagsLabel: TLabel;
|
||||
FlagsValue: TEdit;
|
||||
SeekElementsLabel: TLabel;
|
||||
SeekElementsValue: TEdit;
|
||||
TotalSamplesLabel: TLabel;
|
||||
TotalSamplesValue: TEdit;
|
||||
procedure CloseButtonClick(Sender: TObject);
|
||||
procedure FormCreate(Sender: TObject);
|
||||
procedure FileListChange(Sender: TObject);
|
||||
procedure FormClose(Sender: TObject; var Action: TCloseAction);
|
||||
private
|
||||
{ Private declarations }
|
||||
Monkey: TMonkey;
|
||||
procedure ClearAll;
|
||||
end;
|
||||
|
||||
var
|
||||
MainForm: TMainForm;
|
||||
|
||||
implementation
|
||||
|
||||
{$R *.dfm}
|
||||
|
||||
procedure TMainForm.ClearAll;
|
||||
begin
|
||||
{ Clear all captions }
|
||||
ValidHeaderValue.Text := '';
|
||||
FileLengthValue.Text := '';
|
||||
ChannelModeValue.Text := '';
|
||||
SampleRateValue.Text := '';
|
||||
BitsPerSampleValue.Text := '';
|
||||
DurationValue.Text := '';
|
||||
FlagsValue.Text := '';
|
||||
FramesValue.Text := '';
|
||||
TotalSamplesValue.Text := '';
|
||||
PeakLevelValue.Text := '';
|
||||
SeekElementsValue.Text := '';
|
||||
CompressionValue.Text := '';
|
||||
end;
|
||||
|
||||
procedure TMainForm.CloseButtonClick(Sender: TObject);
|
||||
begin
|
||||
{ Exit }
|
||||
Close;
|
||||
end;
|
||||
|
||||
procedure TMainForm.FormCreate(Sender: TObject);
|
||||
begin
|
||||
{ Create object and reset captions }
|
||||
Monkey := TMonkey.Create;
|
||||
ClearAll;
|
||||
end;
|
||||
|
||||
procedure TMainForm.FileListChange(Sender: TObject);
|
||||
begin
|
||||
{ Clear captions }
|
||||
ClearAll;
|
||||
if FileList.FileName = '' then exit;
|
||||
if FileExists(FileList.FileName) then
|
||||
{ Load Monkey's Audio data }
|
||||
if Monkey.ReadFromFile(FileList.FileName) then
|
||||
if Monkey.Valid then
|
||||
begin
|
||||
{ Fill captions }
|
||||
ValidHeaderValue.Text := 'Yes, version ' + Monkey.Version;
|
||||
FileLengthValue.Text := IntToStr(Monkey.FileLength) + ' bytes';
|
||||
ChannelModeValue.Text := Monkey.ChannelMode;
|
||||
SampleRateValue.Text := IntToStr(Monkey.Header.SampleRate) + ' hz';
|
||||
BitsPerSampleValue.Text := IntToStr(Monkey.Bits) + ' bit';
|
||||
DurationValue.Text := FormatFloat('.000', Monkey.Duration) + ' sec.';
|
||||
FlagsValue.Text := IntToStr(Monkey.Header.Flags);
|
||||
FramesValue.Text := IntToStr(Monkey.Header.Frames);
|
||||
TotalSamplesValue.Text := IntToStr(Monkey.Samples);
|
||||
PeakLevelValue.Text := FormatFloat('00.00', Monkey.Peak) + '% - ' +
|
||||
IntToStr(Monkey.Header.PeakLevel);
|
||||
SeekElementsValue.Text := IntToStr(Monkey.Header.SeekElements);
|
||||
CompressionValue.Text := FormatFloat('00.00', Monkey.Ratio) + '% - ' +
|
||||
Monkey.Compression;
|
||||
end
|
||||
else
|
||||
{ Header not found }
|
||||
ValidHeaderValue.Text := 'No'
|
||||
else
|
||||
{ Read error }
|
||||
ShowMessage('Can not read header in the file: ' + FileList.FileName)
|
||||
else
|
||||
{ File does not exist }
|
||||
ShowMessage('The file does not exist: ' + FileList.FileName);
|
||||
end;
|
||||
|
||||
procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
|
||||
begin
|
||||
{ Free memory }
|
||||
Monkey.Free;
|
||||
end;
|
||||
|
||||
end.
|
||||
300
MAC_SDK/3rd Party/TMonkey (Delphi)/Monkey/Monkey.pas
Normal file
300
MAC_SDK/3rd Party/TMonkey (Delphi)/Monkey/Monkey.pas
Normal file
@@ -0,0 +1,300 @@
|
||||
{ *************************************************************************** }
|
||||
{ }
|
||||
{ Audio Tools Library (Freeware) }
|
||||
{ Class TMonkey - for manipulating with Monkey's Audio file information }
|
||||
{ }
|
||||
{ Uses: }
|
||||
{ - Class TID3v1 }
|
||||
{ - Class TID3v2 }
|
||||
{ - Class TAPEtag }
|
||||
{ }
|
||||
{ Copyright (c) 2001,2002 by Jurgen Faul }
|
||||
{ E-mail: jfaul@gmx.de }
|
||||
{ http://jfaul.de/atl }
|
||||
{ }
|
||||
{ Version 1.2 (21 April 2002) }
|
||||
{ - Class TID3v2: support for ID3v2 tags }
|
||||
{ - Class TAPEtag: support for APE tags }
|
||||
{ }
|
||||
{ Version 1.1 (11 September 2001) }
|
||||
{ - Added property Samples }
|
||||
{ - Removed WAV header information }
|
||||
{ }
|
||||
{ Version 1.0 (7 September 2001) }
|
||||
{ - Support for Monkey's Audio files }
|
||||
{ - Class TID3v1: reading & writing support for ID3v1.x tags }
|
||||
{ }
|
||||
{ *************************************************************************** }
|
||||
|
||||
unit Monkey;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, ID3v1, ID3v2, APEtag;
|
||||
|
||||
const
|
||||
{ Compression level codes }
|
||||
MONKEY_COMPRESSION_FAST = 1000; { Fast (poor) }
|
||||
MONKEY_COMPRESSION_NORMAL = 2000; { Normal (good) }
|
||||
MONKEY_COMPRESSION_HIGH = 3000; { High (very good) }
|
||||
MONKEY_COMPRESSION_EXTRA_HIGH = 4000; { Extra high (best) }
|
||||
|
||||
{ Compression level names }
|
||||
MONKEY_COMPRESSION: array [0..4] of string =
|
||||
('Unknown', 'Fast', 'Normal', 'High', 'Extra High');
|
||||
|
||||
{ Format flags }
|
||||
MONKEY_FLAG_8_BIT = 1; { Audio 8-bit }
|
||||
MONKEY_FLAG_CRC = 2; { New CRC32 error detection }
|
||||
MONKEY_FLAG_PEAK_LEVEL = 4; { Peak level stored }
|
||||
MONKEY_FLAG_24_BIT = 8; { Audio 24-bit }
|
||||
MONKEY_FLAG_SEEK_ELEMENTS = 16; { Number of seek elements stored }
|
||||
MONKEY_FLAG_WAV_NOT_STORED = 32; { WAV header not stored }
|
||||
|
||||
{ Channel mode names }
|
||||
MONKEY_MODE: array [0..2] of string =
|
||||
('Unknown', 'Mono', 'Stereo');
|
||||
|
||||
type
|
||||
{ Real structure of Monkey's Audio header }
|
||||
MonkeyHeader = record
|
||||
ID: array [1..4] of Char; { Always "MAC " }
|
||||
VersionID: Word; { Version number * 1000 (3.91 = 3910) }
|
||||
CompressionID: Word; { Compression level code }
|
||||
Flags: Word; { Any format flags }
|
||||
Channels: Word; { Number of channels }
|
||||
SampleRate: Integer; { Sample rate (hz) }
|
||||
HeaderBytes: Integer; { Header length (without header ID) }
|
||||
TerminatingBytes: Integer; { Extended data }
|
||||
Frames: Integer; { Number of frames in the file }
|
||||
FinalSamples: Integer; { Number of samples in the final frame }
|
||||
PeakLevel: Integer; { Peak level (if stored) }
|
||||
SeekElements: Integer; { Number of seek elements (if stored) }
|
||||
end;
|
||||
|
||||
{ Class TMonkey }
|
||||
TMonkey = class(TObject)
|
||||
private
|
||||
{ Private declarations }
|
||||
FFileLength: Integer;
|
||||
FHeader: MonkeyHeader;
|
||||
FID3v1: TID3v1;
|
||||
FID3v2: TID3v2;
|
||||
FAPEtag: TAPEtag;
|
||||
procedure FResetData;
|
||||
function FGetValid: Boolean;
|
||||
function FGetVersion: string;
|
||||
function FGetCompression: string;
|
||||
function FGetBits: Byte;
|
||||
function FGetChannelMode: string;
|
||||
function FGetPeak: Double;
|
||||
function FGetSamplesPerFrame: Integer;
|
||||
function FGetSamples: Integer;
|
||||
function FGetDuration: Double;
|
||||
function FGetRatio: Double;
|
||||
public
|
||||
{ Public declarations }
|
||||
constructor Create; { Create object }
|
||||
destructor Destroy; override; { Destroy object }
|
||||
function ReadFromFile(const FileName: string): Boolean; { Load header }
|
||||
property FileLength: Integer read FFileLength; { File length (bytes) }
|
||||
property Header: MonkeyHeader read FHeader; { Monkey's Audio header }
|
||||
property ID3v1: TID3v1 read FID3v1; { ID3v1 tag data }
|
||||
property ID3v2: TID3v2 read FID3v2; { ID3v2 tag data }
|
||||
property APEtag: TAPEtag read FAPEtag; { APE tag data }
|
||||
property Valid: Boolean read FGetValid; { True if header valid }
|
||||
property Version: string read FGetVersion; { Encoder version }
|
||||
property Compression: string read FGetCompression; { Compression level }
|
||||
property Bits: Byte read FGetBits; { Bits per sample }
|
||||
property ChannelMode: string read FGetChannelMode; { Channel mode }
|
||||
property Peak: Double read FGetPeak; { Peak level ratio (%) }
|
||||
property Samples: Integer read FGetSamples; { Number of samples }
|
||||
property Duration: Double read FGetDuration; { Duration (seconds) }
|
||||
property Ratio: Double read FGetRatio; { Compression ratio (%) }
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
{ ********************** Private functions & procedures ********************* }
|
||||
|
||||
procedure TMonkey.FResetData;
|
||||
begin
|
||||
{ Reset data }
|
||||
FFileLength := 0;
|
||||
FillChar(FHeader, SizeOf(FHeader), 0);
|
||||
FID3v1.ResetData;
|
||||
FID3v2.ResetData;
|
||||
FAPEtag.ResetData;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function TMonkey.FGetValid: Boolean;
|
||||
begin
|
||||
{ Check for right Monkey's Audio file data }
|
||||
Result :=
|
||||
(FHeader.ID = 'MAC ') and
|
||||
(FHeader.SampleRate > 0) and
|
||||
(FHeader.Channels > 0);
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function TMonkey.FGetVersion: string;
|
||||
begin
|
||||
{ Get encoder version }
|
||||
if FHeader.VersionID = 0 then Result := ''
|
||||
else Str(FHeader.VersionID / 1000 : 4 : 2, Result);
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function TMonkey.FGetCompression: string;
|
||||
begin
|
||||
{ Get compression level }
|
||||
Result := MONKEY_COMPRESSION[FHeader.CompressionID div 1000];
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function TMonkey.FGetBits: Byte;
|
||||
begin
|
||||
{ Get number of bits per sample }
|
||||
if FGetValid then
|
||||
begin
|
||||
Result := 16;
|
||||
if FHeader.Flags and MONKEY_FLAG_8_BIT > 0 then Result := 8;
|
||||
if FHeader.Flags and MONKEY_FLAG_24_BIT > 0 then Result := 24;
|
||||
end
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function TMonkey.FGetChannelMode: string;
|
||||
begin
|
||||
{ Get channel mode }
|
||||
Result := MONKEY_MODE[FHeader.Channels];
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function TMonkey.FGetPeak: Double;
|
||||
begin
|
||||
{ Get peak level ratio }
|
||||
if (FGetValid) and (FHeader.Flags and MONKEY_FLAG_PEAK_LEVEL > 0) then
|
||||
case FGetBits of
|
||||
16: Result := FHeader.PeakLevel / 32768 * 100;
|
||||
24: Result := FHeader.PeakLevel / 8388608 * 100;
|
||||
else Result := FHeader.PeakLevel / 128 * 100;
|
||||
end
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function TMonkey.FGetSamplesPerFrame: Integer;
|
||||
begin
|
||||
{ Get number of samples in a frame }
|
||||
if FGetValid then
|
||||
if (FHeader.VersionID >= 3900) or
|
||||
((FHeader.VersionID >= 3800) and
|
||||
(FHeader.CompressionID = MONKEY_COMPRESSION_EXTRA_HIGH)) then
|
||||
Result := 73728
|
||||
else
|
||||
Result := 9216
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function TMonkey.FGetSamples: Integer;
|
||||
begin
|
||||
{ Get number of samples }
|
||||
if FGetValid then
|
||||
Result := (FHeader.Frames - 1) * FGetSamplesPerFrame + FHeader.FinalSamples
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function TMonkey.FGetDuration: Double;
|
||||
begin
|
||||
{ Get song duration }
|
||||
if FGetValid then Result := FGetSamples / FHeader.SampleRate
|
||||
else Result := 0;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function TMonkey.FGetRatio: Double;
|
||||
begin
|
||||
{ Get compression ratio }
|
||||
if FGetValid then
|
||||
Result := FFileLength /
|
||||
(FGetSamples * FHeader.Channels * FGetBits / 8 + 44) * 100
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
{ ********************** Public functions & procedures ********************** }
|
||||
|
||||
constructor TMonkey.Create;
|
||||
begin
|
||||
{ Create object }
|
||||
inherited;
|
||||
FID3v1 := TID3v1.Create;
|
||||
FID3v2 := TID3v2.Create;
|
||||
FAPEtag := TAPEtag.Create;
|
||||
FResetData;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
destructor TMonkey.Destroy;
|
||||
begin
|
||||
{ Destroy object }
|
||||
FID3v1.Free;
|
||||
FID3v2.Free;
|
||||
FAPEtag.Free;
|
||||
inherited;
|
||||
end;
|
||||
|
||||
{ --------------------------------------------------------------------------- }
|
||||
|
||||
function TMonkey.ReadFromFile(const FileName: string): Boolean;
|
||||
var
|
||||
SourceFile: file;
|
||||
begin
|
||||
try
|
||||
{ Reset data and search for file tag }
|
||||
FResetData;
|
||||
if (not FID3v1.ReadFromFile(FileName)) or
|
||||
(not FID3v2.ReadFromFile(FileName)) or
|
||||
(not FAPEtag.ReadFromFile(FileName)) then raise Exception.Create('');
|
||||
{ Set read-access, open file and get file length }
|
||||
AssignFile(SourceFile, FileName);
|
||||
FileMode := 0;
|
||||
Reset(SourceFile, 1);
|
||||
FFileLength := FileSize(SourceFile);
|
||||
{ Read Monkey's Audio header data }
|
||||
Seek(SourceFile, ID3v2.Size);
|
||||
BlockRead(SourceFile, FHeader, SizeOf(FHeader));
|
||||
if FHeader.Flags and MONKEY_FLAG_PEAK_LEVEL = 0 then
|
||||
FHeader.PeakLevel := 0;
|
||||
if FHeader.Flags and MONKEY_FLAG_SEEK_ELEMENTS = 0 then
|
||||
FHeader.SeekElements := 0;
|
||||
CloseFile(SourceFile);
|
||||
Result := true;
|
||||
except
|
||||
FResetData;
|
||||
Result := false;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
35
MAC_SDK/3rd Party/TMonkey (Delphi)/Monkey/Test.cfg
Normal file
35
MAC_SDK/3rd Party/TMonkey (Delphi)/Monkey/Test.cfg
Normal file
@@ -0,0 +1,35 @@
|
||||
-$A8
|
||||
-$B-
|
||||
-$C+
|
||||
-$D+
|
||||
-$E-
|
||||
-$F-
|
||||
-$G+
|
||||
-$H+
|
||||
-$I+
|
||||
-$J-
|
||||
-$K-
|
||||
-$L+
|
||||
-$M-
|
||||
-$N+
|
||||
-$O+
|
||||
-$P+
|
||||
-$Q-
|
||||
-$R-
|
||||
-$S-
|
||||
-$T-
|
||||
-$U-
|
||||
-$V+
|
||||
-$W-
|
||||
-$X+
|
||||
-$YD
|
||||
-$Z1
|
||||
-cg
|
||||
-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
|
||||
-H+
|
||||
-W+
|
||||
-M
|
||||
-$M16384,1048576
|
||||
-K$00400000
|
||||
-LE"c:\program files\borland\delphi6\Projects\Bpl"
|
||||
-LN"c:\program files\borland\delphi6\Projects\Bpl"
|
||||
96
MAC_SDK/3rd Party/TMonkey (Delphi)/Monkey/Test.dof
Normal file
96
MAC_SDK/3rd Party/TMonkey (Delphi)/Monkey/Test.dof
Normal file
@@ -0,0 +1,96 @@
|
||||
[FileVersion]
|
||||
Version=6.0
|
||||
[Compiler]
|
||||
A=8
|
||||
B=0
|
||||
C=1
|
||||
D=1
|
||||
E=0
|
||||
F=0
|
||||
G=1
|
||||
H=1
|
||||
I=1
|
||||
J=0
|
||||
K=0
|
||||
L=1
|
||||
M=0
|
||||
N=1
|
||||
O=1
|
||||
P=1
|
||||
Q=0
|
||||
R=0
|
||||
S=0
|
||||
T=0
|
||||
U=0
|
||||
V=1
|
||||
W=0
|
||||
X=1
|
||||
Y=1
|
||||
Z=1
|
||||
ShowHints=1
|
||||
ShowWarnings=1
|
||||
UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
|
||||
[Linker]
|
||||
MapFile=0
|
||||
OutputObjs=0
|
||||
ConsoleApp=1
|
||||
DebugInfo=0
|
||||
RemoteSymbols=0
|
||||
MinStackSize=16384
|
||||
MaxStackSize=1048576
|
||||
ImageBase=4194304
|
||||
ExeDescription=
|
||||
[Directories]
|
||||
OutputDir=
|
||||
UnitOutputDir=
|
||||
PackageDLLOutputDir=
|
||||
PackageDCPOutputDir=
|
||||
SearchPath=
|
||||
Packages=vcl;rtl;dbrtl;adortl;vcldb;vclx;bdertl;vcldbx;ibxpress;dsnap;cds;bdecds;qrpt;teeui;teedb;tee;dss;teeqr;visualclx;visualdbclx;dsnapcrba;dsnapcon;VclSmp;vclshlctrls;vclie;xmlrtl;inet;inetdbbde;inetdbxpress;inetdb;nmfast;webdsnap;websnap;dbexpress;dbxcds;indy;dclOffice2k
|
||||
Conditionals=
|
||||
DebugSourceDirs=
|
||||
UsePackages=0
|
||||
[Parameters]
|
||||
RunParams=
|
||||
HostApplication=
|
||||
Launcher=
|
||||
UseLauncher=0
|
||||
DebugCWD=
|
||||
[Language]
|
||||
ActiveLang=
|
||||
ProjectLang=
|
||||
RootDir=
|
||||
[Version Info]
|
||||
IncludeVerInfo=0
|
||||
AutoIncBuild=0
|
||||
MajorVer=1
|
||||
MinorVer=0
|
||||
Release=0
|
||||
Build=0
|
||||
Debug=0
|
||||
PreRelease=0
|
||||
Special=0
|
||||
Private=0
|
||||
DLL=0
|
||||
Locale=1031
|
||||
CodePage=1252
|
||||
[Version Info Keys]
|
||||
CompanyName=
|
||||
FileDescription=
|
||||
FileVersion=1.0.0.0
|
||||
InternalName=
|
||||
LegalCopyright=
|
||||
LegalTrademarks=
|
||||
OriginalFilename=
|
||||
ProductName=
|
||||
ProductVersion=1.0.0.0
|
||||
Comments=
|
||||
[HistoryLists\hlUnitAliases]
|
||||
Count=1
|
||||
Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
|
||||
[HistoryLists\hlUnitOutputDirectory]
|
||||
Count=1
|
||||
Item0=DCU
|
||||
[HistoryLists\hlOutputDirectorry]
|
||||
Count=1
|
||||
Item0=Data
|
||||
18
MAC_SDK/3rd Party/TMonkey (Delphi)/Monkey/Test.dpr
Normal file
18
MAC_SDK/3rd Party/TMonkey (Delphi)/Monkey/Test.dpr
Normal file
@@ -0,0 +1,18 @@
|
||||
program Test;
|
||||
|
||||
uses
|
||||
Forms,
|
||||
Main in 'Main.pas' {MainForm},
|
||||
Monkey in 'Monkey.pas',
|
||||
ID3v1 in '..\ID3v1\ID3v1.pas',
|
||||
ID3v2 in '..\ID3v2\ID3v2.pas',
|
||||
APEtag in '..\APEtag\APEtag.pas';
|
||||
|
||||
{$R *.res}
|
||||
|
||||
begin
|
||||
Application.Initialize;
|
||||
Application.Title := 'Monkey Test';
|
||||
Application.CreateForm(TMainForm, MainForm);
|
||||
Application.Run;
|
||||
end.
|
||||
BIN
MAC_SDK/3rd Party/TMonkey (Delphi)/Monkey/Test.res
Normal file
BIN
MAC_SDK/3rd Party/TMonkey (Delphi)/Monkey/Test.res
Normal file
Binary file not shown.
5
MAC_SDK/3rd Party/TMonkey (Delphi)/Readme.txt
Normal file
5
MAC_SDK/3rd Party/TMonkey (Delphi)/Readme.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
TMonkey Delphi Class for analyzing APE files
|
||||
|
||||
Sumbitted by Jurgen Faul ( jfaul@gmx.de )
|
||||
|
||||
(note: this does not directly use the MAC SDK, so it is not guaranteed to work with future APE files)
|
||||
Reference in New Issue
Block a user