Unit editid3; { Edit/show file info dialog for Cactus Jukebox written by Sebastian Kraft, 2006-2008 Contact the author at: sebastian_kraft@gmx.de This Software is published under the GPL } {$mode objfpc}{$H+} Interface Uses Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls, FileUtil, {ExtCtrls,} Buttons, ComCtrls, lcltype, mediacol, ExtCtrls, skin, last_fm, streamcol, settings, debug, mp3file; Const ALBUM_MODE = 1; Const ARTIST_MODE = 2; Const STREAM_MODE = 2; Type PLabel = ^TLabel; PEdit = ^TEdit; { TEditID3 } TEditID3 = Class(TForm) albumedit1: TEdit; albumedit2: TEdit; albumedit3: TEdit; artistedit1: TEdit; artistedit2: TEdit; artistedit3: TEdit; btnOptions: TButton; Button1: TButton; cancelbut1: TButton; cmbYear: TComboBox; cmbComment: TComboBox; GenreBox: TComboBox; commentedit1: TEdit; Edit1: TEdit; Edit3: TEdit; GroupBox1: TGroupBox; NameEdit: TEdit; URLEdit: TEdit; guessname1: TButton; Filelogo: TImage; AlbumCoverImg: TImage; Label1: TLabel; Label10: TLabel; Label11: TLabel; Label12: TLabel; Label13: TLabel; Label14: TLabel; Label15: TLabel; Label16: TLabel; Label17: TLabel; Label18: TLabel; Label19: TLabel; Label2: TLabel; Label3: TLabel; lblTrack: TLabel; Label21: TLabel; idlabel: TLabel; indexlabel: TLabel; DescEdit: TMemo; mtype: TLabel; bitrate: TLabel; fsize: TLabel; btnReset: TButton; srate: TLabel; plength: TLabel; Label7: TLabel; Label9: TLabel; savebut1: TButton; id3v1tab: TTabSheet; fileinfo: TTabSheet; PicDownloadTimer: TTimer; StreamTab: TTabSheet; titleedit2: TEdit; titleedit3: TEdit; trackedit1: TEdit; trackedit2: TEdit; yearEdit1: TEdit; lblArtist: TLabel; lblTitle: TLabel; lblAlbum: TLabel; lblYear: TLabel; lblGenre: TLabel; lblComment: TLabel; lblPath: TLabel; metacontrol: TPageControl; pathedit1: TEdit; metatab: TTabSheet; id3v2tab: TTabSheet; titleedit1: TEdit; yearEdit2: TEdit; yearEdit3: TEdit; procedure btnOptionsClick(Sender: TObject); Procedure Button1Click(Sender: TObject); Procedure btnResetClick(Sender: TObject); Procedure EditID3Close(Sender: TObject; Var CloseAction: TCloseAction); Procedure FormCreate(Sender: TObject); Procedure FormHide(Sender: TObject); Procedure PicDownloadTimerStartTimer(Sender: TObject); Procedure PicDownloadTimerTimer(Sender: TObject); Procedure cancelbutClick(Sender: TObject); Procedure guessnameClick(Sender: TObject); Procedure savebutClick(Sender: TObject); Procedure yearEdit1Change(Sender: TObject); Procedure cmbYearChange(Sender: TObject); Procedure activateEMode(Sender: TObject); Private { private declarations } artist_only, album_only: Boolean; timer_loop_count: integer; request_send: boolean; picrequest_send: boolean; LastFMAPI: TLastfmAPIObject; bEModeActive: boolean; MedFileObj: TMediaFileClass; MedColObj: TMediaCollectionClass; StreamInfoObj: TStreamInfoItemClass; GenreIDtoCBIndex: array[0..255, 0..255] of integer; //used to translate genre id to checkbox item index // Edit-mode specific variable ptrControls: array Of array Of ^TControl; // .. Procedure show_tags(); function GetCoverPath: boolean; function GetTrack: string; Public { public declarations } fileid: integer; Procedure display_window(MedFile:TMediaFileClass; intMode: Integer = 0); Procedure display_window(StreamInfo: TStreamInfoItemClass); End; Var EditID3win: TEditID3; Implementation {$R *.lfm} Uses mainform, config, functions; { TEditID3 } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Procedure TEditID3.savebutClick(Sender: TObject); Var curartist, newart, oldart, oldalbum, newalbum, strNewYear, strNewComment: string; z: integer; bYearLongEnough: Boolean; Begin // only save if s.th. has been changed If bEModeActive = false Then Begin EditID3win.Hide; exit; End; // check if the file exists and is writable If (FileGetAttr(MedFileObj.path)<>faReadOnly) Then Begin // write changes (artist-mode) If artist_only=true Then Begin oldart := lowercase(MedFileObj.artist); newart := artistedit1.text; strNewComment := self.cmbComment.Caption; strNewYear := self.cmbYear.Caption; If Length(strNewYear) = 4 Then bYearLongEnough := true; z := MedColObj.getTracks(oldart, MedFileObj.index); Repeat Begin MedFileObj := MedColObj.Items[z]; DebugOutLn('artist_mode: '+ artistedit1.Text +' #'+ IntToStr(z),3); MedFileObj.artist := newart; if GenreBox.ItemIndex>=0 then MedFileObj.GenreID:= GenreIDtoCBIndex[0, GenreBox.ItemIndex]; If bYearLongEnough Then MedColObj.items[z].year := self.cmbYear.Caption; MedFileObj.comment := strNewComment; MedFileObj.write_tag; z := MedColObj.getNext; End; Until z<0; End // write changes (album-mode) Else If album_only=true Then Begin curartist := lowercase(MedFileObj.artist); oldalbum := lowercase(MedFileObj.album); newalbum := albumedit1.text; newart := artistedit1.text; strNewComment := self.cmbComment.Caption; strNewYear := self.cmbYear.Caption; If Length(strNewYear) = 4 Then bYearLongEnough := true; z := MedColObj.getTracks(curartist, oldalbum, MedFileObj.index); Repeat Begin MedFileObj := MedColObj.items[z]; MedFileObj.album := newalbum; MedFileObj.Artist := newart; If bYearLongEnough Then MedFileObj.year := self.cmbYear.Caption; MedFileObj.comment := strNewComment; if GenreBox.ItemIndex>=0 then MedFileObj.GenreID:= GenreIDtoCBIndex[0, GenreBox.ItemIndex]; MedFileObj.write_tag; z := MedColObj.getNext; End; Until z<0; End // write changes (title-mode) Else Begin MedFileObj.artist := artistedit1.text; MedFileObj.title := titleedit1.text; MedFileObj.album := albumedit1.text; MedFileObj.year := yearedit1.text; MedFileObj.comment := commentedit1.text; MedFileObj.track := GetTrack; if GenreBox.ItemIndex>=0 then MedFileObj.GenreID:= GenreIDtoCBIndex[0, GenreBox.ItemIndex]; MedFileObj.write_tag; RenameFile(MedFileObj.path, UTF8ToSys(editid3win.pathedit1.text)); MedFileObj.path := UTF8ToSys(editid3win.pathedit1.text); End; If main.player_connected Then PlayerCol.SaveToFile(CactusConfig.DAPPath+'cactuslib'); main.update_artist_view; update_title_view; main.update_playlist; End Else ShowMessage('Error: File(s) is/are read-only'); EditID3win.Hide; End; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Procedure TEditID3.cancelbutClick(Sender: TObject); Begin EditID3win.Hide; End; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Procedure TEditID3.yearEdit1Change(Sender: TObject); Begin // ensure only YYYY (years of four digits) are entered (if anything is entered) If self.yearEdit1.Visible = true Then Begin Case Length(self.yearEdit1.Caption) Of 0: self.savebut1.Enabled := true; 4: Try self.savebut1.Enabled := true; StrToInt(self.yearEdit1.Caption); Except self.savebut1.Enabled := false; End; otherwise self.savebut1.Enabled := false; End; activateEMode(Sender); End; End; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Procedure TEditID3.cmbYearChange(Sender: TObject); Begin // ensure only YYYY (years of four digits) are entered (if anything is entered) If self.cmbYear.Visible = true Then Begin Case Length(self.cmbYear.Caption) Of 0: self.savebut1.Enabled := true; 4: Try self.savebut1.Enabled := true; StrToInt(self.cmbYear.Caption); Except self.savebut1.Enabled := false; End; otherwise self.savebut1.Enabled := false; End; activateEMode(Sender); End; End; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Procedure TEditID3.activateEMode(Sender: TObject); Var i, j: Integer; ptrLabel: ^TLabel; ptrEdit: ^TEdit; Begin // disable all labels If bEModeActive = false Then Begin For i := 0 To Length(ptrControls) -1 Do Begin ptrLabel := PLabel(ptrControls[i,0]); ptrLabel^.Enabled := false; End; bEModeActive := true; btnReset.Enabled := true; End; // enable label if sender (a text-box) belongs to it For i := 0 To Length(ptrControls) -1 Do Begin ptrLabel := PLabel(ptrControls[i,0]); For j := 1 To Length(ptrControls[i]) -1 Do Begin ptrEdit := PEdit(ptrControls[i,j]); If ptrEdit^ = Sender Then ptrLabel^.Enabled := true; End End; End; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Procedure TEditID3.FormHide(Sender: TObject); Begin // reset form components self.guessname1.Enabled := true; self.Button1.Enabled := true; self.pathedit1.Caption := ''; self.pathedit1.Enabled := true; self.artistedit1.Caption := ''; self.artistedit1.Enabled := true; self.titleedit1.Caption := ''; self.titleedit1.Enabled := true; self.albumedit1.Caption := ''; self.albumedit1.Enabled := true; self.trackedit1.Caption := ''; self.trackedit1.Enabled := true; self.yearEdit1.Caption := ''; self.yearEdit1.Enabled := true; self.commentedit1.Caption := ''; self.commentedit1.Enabled := true; self.AlbumCoverImg.Canvas.Clear; self.AlbumCoverImg.Picture.Clear; self.PicDownloadTimer.Enabled := false; self.cmbYear.Visible := false; self.yearEdit1.Visible := true; self.cmbComment.Visible := false; self.commentedit1.Visible := true; // self.ShowInTaskBar := stNever; End; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Procedure TEditID3.PicDownloadTimerStartTimer(Sender: TObject); Begin timer_loop_count := 0; End; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Procedure TEditID3.PicDownloadTimerTimer(Sender: TObject); Begin inc(timer_loop_count); If (timer_loop_count Mod 8)=0 Then AlbumCoverImg.Canvas.Clear Else AlbumCoverImg.Canvas.TextOut(10,10, 'Loading...'); If (timer_loop_count>20) Then Begin DebugOutLn('TIMEOUT while loading album cover image from Internet', 2); AlbumCoverImg.Canvas.Clear; AlbumCoverImg.Canvas.TextOut(10,10, 'No cover found :('); LastFMAPI.free; picrequest_send := false; PicDownloadTimer.Enabled := false; End; If (picrequest_send) And LastFMAPI.data_ready Then Begin writeln(MedFileObj.CoverPath); AlbumCoverImg.Canvas.Clear; Try AlbumCoverImg.Picture.LoadFromFile(MedFileObj.CoverPath); Except DebugOutLn('EXCEPTION', 1); End; LastFMAPI.free; picrequest_send := false; PicDownloadTimer.Enabled := false; End; End; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Procedure TEditID3.EditID3Close(Sender: TObject; Var CloseAction: TCloseAction); Begin // Filelogo.free; // AlbumCoverImg.free; // PicDownloadTimer.Enabled:=false; // PicDownloadTimer.Free; End; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Procedure TEditID3.FormCreate(Sender: TObject); Var i: integer; GenreList, numberlist: TStringlist; Aname, Avalue: string; Begin // initialize index of labels and text boxes on form - used for edit-mode SetLength(ptrControls, 8); For i := 0 To Length(ptrControls) -1 Do SetLength(ptrControls[i], 2); ptrControls[0,0] := @self.lblPath; ptrControls[0,1] := @self.pathedit1; ptrControls[1,0] := @self.lblArtist; ptrControls[1,1] := @self.artistedit1; ptrControls[2,0] := @self.lblTitle; ptrControls[2,1] := @self.titleedit1; ptrControls[3,0] := @self.lblAlbum; ptrControls[3,1] := @self.albumedit1; ptrControls[4,0] := @self.lblTrack; ptrControls[4,1] := @self.trackedit1; ptrControls[5,0] := @self.lblGenre; ptrControls[5,1] := @self.GenreBox; SetLength(ptrControls[6], 3); ptrControls[6,0] := @self.lblComment; ptrControls[6,1] := @self.commentedit1; ptrControls[6,2] := @self.cmbComment; SetLength(ptrControls[7], 3); ptrControls[7,0] := @self.lblYear; ptrControls[7,1] := @self.yearEdit1; ptrControls[7,2] := @self.cmbYear; // (FIXME) ressourcestring translations need to be added here //TODO: translation for editid3 window Icon.LoadFromFile(CactusConfig.DataPrefix+'icon'+DirectorySeparator+'cactus-icon.ico'); GenreList:=TStringList.Create; for i:= 0 to high(ID3Genre) do begin GenreList.Add(ID3Genre[i]+'='+IntToStr(i)); end; GenreList.Sorted:=true; for i:= 0 to high(ID3Genre) do begin GenreList.GetNameValue(i, Aname, Avalue); GenreIDtoCBIndex[0,i]:=StrToInt(Avalue); GenreIDtoCBIndex[StrToInt(Avalue),0]:=i; GenreBox.Items.Add(Aname); end; End; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Procedure TEditID3.show_tags(); Var strYears: Array Of String[4]; strComments: Array Of String; bExists: Boolean; i, j: Integer; ptrLabel: ^TLabel; Begin // reset all labels indicating edit-mode and changes GenreBox.ItemIndex:=-1; For i := 0 To Length(ptrControls) -1 Do Begin ptrLabel := PLabel(ptrControls[i,0]); ptrLabel^.Enabled := true; End; // display tags... artistedit1.Text := MedFileObj.artist; // artist and album(-mode) specific actions If (artist_only = true) Or (album_only = true) Then Begin // collect all "years" set for files of the chosen artist/album // and display them SetLength(strYears, 0); For i := 0 To MedColObj.ItemCount -1 Do If MedColObj.items[i].artist = MedFileObj.artist Then Begin If album_only = true Then If MedColObj.items[i].album <> MedFileObj.album Then continue; // ensure "year" is added only once bExists := false; For j := 0 To Length(strYears) -1 Do If strYears[j] = MedColObj.items[i].year Then Begin bExists := true; break; End; If bExists = true Then continue; // add "year" SetLength(strYears, Length(strYears) +1); strYears[Length(strYears) -1] := MedColObj.items[i].year; End; // and display... yearEdit1.Visible := false; cmbYear.Visible := true; cmbYear.Clear; For i := 0 To Length(strYears) -1 Do cmbYear.Items.Add(strYears[i]); // collect all "comments" set for files of the chosen artist/album // and display them SetLength(strComments, 0); For i := 1 To self.MedColObj.ItemCount-1 Do If MedColObj.items[i].artist = MedFileObj.artist Then Begin If album_only = true Then If MedColObj.items[i].album <> self.MedFileObj.album Then continue; // ensure "comment" is added only once bExists := false; For j := 0 To Length(strComments) -1 Do If strComments[j] = MedColObj.items[i].comment Then Begin bExists := true; break; End; If bExists = true Then continue; // add "comment" SetLength(strComments, Length(strComments) +1); strComments[Length(strComments) -1] := MedColObj.items[i].comment; End; // and display... commentedit1.Visible := false; cmbComment.Visible := true; cmbComment.Clear; For i := 0 To Length(strComments) -1 Do cmbComment.Items.Add(strComments[i]); // album(-mode) specific actions If album_only = true Then Begin albumedit1.text := MedFileObj.album; // select first entry from combobox as default for the album If cmbYear.Items.Count > 0 Then cmbYear.ItemIndex := 0; If cmbComment.Items.Count > 0 Then cmbComment.ItemIndex := 0; End; End // title(-mode) specific actions Else Begin pathedit1.text := SysToUTF8(MedFileObj.path); //TODO: scroll TEdit to end of path titleedit1.text := MedFileObj.title; albumedit1.text := MedFileObj.album; commentedit1.text := MedFileObj.comment; yearedit1.text := MedFileObj.year; trackedit1.text := MedFileObj.track; GenreBox.ItemIndex:=GenreIDtoCBIndex[MedFileObj.GenreID, 0]; End; btnReset.Enabled := false; bEModeActive := false; End; function TEditID3.GetCoverPath: boolean; begin MedFileObj.CoverPath := CactusConfig.GetCoverPath(MedFileObj.GetCoverFile); result := FileExists(MedFileObj.CoverPath); end; function TEditID3.GetTrack: string; var A,B: Integer; AStr,BStr: string; begin // track must conform to n[/m] AStr := Trim(trackedit1.text); A := pos('/', AStr); if A>0 then begin BStr := Trim(Copy(AStr, A+1, Length(AStr))); AStr := Trim(Copy(AStr, 1, A-1)); B := StrToIntDef(BStr, -1); end else B := -1; A := StrToIntDef(AStr, -1); if A<0 then result := '' else if B<0 then result := AStr else result := AStr + '/' + BStr; end; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Procedure TEditID3.display_window(MedFile: TMediaFileClass; intMode: Integer); Begin // set up gui elements metacontrol.Pages[0].TabVisible := true; metacontrol.Pages[1].TabVisible := true; metacontrol.Pages[2].TabVisible := false; metacontrol.ActivePage := metacontrol.Pages[0]; btnReset.Enabled := true; MedFileObj := MedFile; MedColObj := MedFileObj.Collection; fileid := 0; self.artist_only := false; self.album_only := false; Case intMode Of ALBUM_MODE: self.album_only := true; ARTIST_MODE: self.artist_only := true; End; Button1.Hint := '( ' + CactusConfig.strTagToNameFormatString + ' )'; Button1.Enabled := true; // artist and album(-mode) specific actions If (artist_only = true) Or (album_only = true) Then Begin self.guessname1.Enabled := false; self.pathedit1.Enabled := false; self.titleedit1.Enabled := false; self.indexlabel.Caption := 'File-Index: ' + IntToStr(MedFileObj.index); // artist(-mode) specific actions If artist_only = true Then self.albumedit1.Enabled := false; // album(-mode) specific actions If album_only = true Then Begin DebugOutLn('########AlbumCover', 5); If (MedFileObj.album<>'') and CactusConfig.CheckCoverPath Then Begin if GetCoverPath then Begin Try AlbumCoverImg.Picture.LoadFromFile(MedFileObj.CoverPath); Except writeln('EXCEPTION loading cover file from '+MedFileObj.CoverPath); End; End Else Begin If CactusConfig.CoverDownload Then Begin LastFMAPI := TLastfmAPIObject.Create; if CactusConfig.CoverSize='large' then LastFMAPI.CoverSize:=ExtralargeImage else LastFMAPI.CoverSize:=LargeImage; LastFMAPI.album_downloadCover(MedFileObj.artist, MedFileObj.album, MedFileObj.CoverPath); picrequest_send := true; AlbumCoverImg.Canvas.TextOut(10,10, 'Loading...'); PicDownloadTimer.Enabled := true; Application.ProcessMessages; End; End; End; End; End // title(-mode) specific actions Else Begin self.guessname1.Enabled := true; mtype.caption := 'Mediatype: '+MedFileObj.filetype; If MedFileObj.filetype='.mp3' Then Filelogo.Picture.LoadFromFile(SkinData.DefaultPath+DirectorySeparator+'icon'+ DirectorySeparator+'mp3_64.png'); If MedFileObj.filetype='.ogg' Then Filelogo.Picture.LoadFromFile(SkinData.DefaultPath+DirectorySeparator+'icon'+ DirectorySeparator+'ogg_64.png'); If MedFileObj.filetype='.wav' Then Filelogo.Picture.LoadFromFile(SkinData.DefaultPath+DirectorySeparator+'icon'+ DirectorySeparator+'wav_64.png'); If MedFileObj.filetype='.wma' Then Filelogo.Picture.LoadFromFile(SkinData.DefaultPath+DirectorySeparator+'icon'+ DirectorySeparator+'wma_64.png'); If (MedFileObj.filetype='.flac') or (MedFileObj.filetype='.fla') Then Filelogo.Picture.LoadFromFile(SkinData.DefaultPath+DirectorySeparator+'icon'+ DirectorySeparator+'flac_64.png'); plength.caption := 'Length: '+MedFileObj.playtime; fsize.caption := 'Size: '+ByteToFmtString(MedFileObj.size, 2, 2); srate.Caption := 'Samplerate: ' + IntToStr(MedFileObj.samplerate) + ' Hz'; bitrate.Caption := 'Bitrate: ' + IntToStr(MedFileObj.bitrate) + ' kbps'; idlabel.Caption := 'File-Id: ' + IntToStr(MedFileObj.id); indexlabel.Caption := 'File-Index: ' + IntToStr(MedFileObj.index); writeln('########AlbumCover'); // DEBUG-INFO If (MedFileObj.album<>'') and CactusConfig.CheckCoverPath Then Begin if GetCoverPath Then Begin Try AlbumCoverImg.Picture.LoadFromFile(MedFileObj.CoverPath); Except writeln('EXCEPTION loading cover'); End; End Else Begin If CactusConfig.CoverDownload Then Begin LastFMAPI := TLastfmAPIObject.Create; if CactusConfig.CoverSize='large' then LastFMAPI.CoverSize:=ExtralargeImage else LastFMAPI.CoverSize:=LargeImage; LastFMAPI.album_downloadCover(MedFileObj.artist, MedFileObj.album, MedFileObj.CoverPath); picrequest_send := true; AlbumCoverImg.Canvas.TextOut(10,10, 'Loading...'); PicDownloadTimer.Enabled := true; Application.ProcessMessages; End; End; End; End; show_tags(); End; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Procedure TEditID3.display_window(StreamInfo: TStreamInfoItemClass); Begin StreamInfoObj := StreamInfo; metacontrol.Pages[0].TabVisible := false; metacontrol.Pages[1].TabVisible := false; metacontrol.Pages[2].TabVisible := true; metacontrol.ActivePage := metacontrol.Pages[2]; btnReset.Enabled := true; NameEdit.Text := StreamInfoObj.Name; URLEdit.Text := StreamInfoObj.URL; DescEdit.Text := StreamInfoObj.Description; End; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Procedure TEditID3.Button1Click(Sender: TObject); Var //s: string; z: integer; Begin { // write changes (artist-mode) If artist_only=true Then Begin oldart := lowercase(MedFileObj.artist); newart := artistedit1.text; strNewComment := self.cmbComment.Caption; strNewYear := self.cmbYear.Caption; If Length(strNewYear) = 4 Then bYearLongEnough := true; z := MedColObj.getTracks(oldart, MedFileObj.index); Repeat Begin MedFileObj := MedColObj.Items[z]; writeln('artist_mode: '+ artistedit1.Text +' #'+ IntToStr(z)); // DEBUG-INFO MedFileObj.artist := newart; If bYearLongEnough Then MedColObj.items[z].year := self.cmbYear.Caption; MedFileObj.comment := strNewComment; MedFileObj.write_tag; z := MedColObj.getNext; End; Until z<0; End // write changes (album-mode) } if artist_only = true then // title-mode begin z := MedColObj.getTracks(lowercase(MedFileObj.artist), MedFileObj.index); repeat begin MedFileObj := MedColObj.items[z]; MedFileObj.PathNameFromTag(CactusConfig.strTagToNameFormatString); z := MedColObj.getNext; End; Until z < 0; end else if album_only = true then // album-mode begin z := MedColObj.getTracks(lowercase(MedFileObj.artist), lowercase(MedFileObj.album), MedFileObj.index); repeat begin MedFileObj := MedColObj.items[z]; MedFileObj.PathNameFromTag(CactusConfig.strTagToNameFormatString); z := MedColObj.getNext; End; Until z < 0; end else // title-mode begin MedFileObj.PathNameFromTag(CactusConfig.strTagToNameFormatString); EditID3win.pathedit1.text := SysToUTF8(MedFileObj.Path); end; // EditID3win.pathedit1.text := s; End; procedure TEditID3.btnOptionsClick(Sender: TObject); Var setupwin: TSettings; begin Enabled := false; setupwin := Tsettings.Create(Application); setupwin.ShowModal(TSETTINGS_SELECT_ID3); setupwin.Free; Enabled := true; end; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Procedure TEditID3.btnResetClick(Sender: TObject); Begin show_tags(); End; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // TODO: check .... Procedure TEditID3.guessnameClick(Sender: TObject); Var z: integer; tmps: string; Begin tmps := extractfilename(UTF8ToSys(pathedit1.Text)); If ((tmps[1]<#60) And (tmps[2]<#60) And (tmps[4]=#45)) Then Begin trackedit1.text := SysToUTF8(copy(tmps,1,2)); delete(tmps, 1, 5); End; z := pos(' - ', tmps)+3; If z<>3 Then Begin titleedit1.text := SysToUTF8(TrimRight(copy(tmps,z,length(tmps)-z-3))); artistedit1.text := SysToUTF8(TrimRight(copy(tmps,1,z-3))); End Else Begin artistedit1.text := ''; titleedit1.text := ''; End; End; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ End.