_I_Play_Chess
12-06-2003, 10:05 AM
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><B>Your first MP3 Delphi player </B></TD></TR>
<TR>
<TD bgColor=#cc0000 colSpan=2 height=1><IMG height=1 src="http://images.about.com/all/bullets/dot_clea.gif" width=1 border=0></TD></TR></TBODY></TABLE><B>Part 1: Delphi plays MP3? TMediaPlayer is all we need!</B>
<B>It's party time and Hollidays coming!!!!!.</B>
You probably know this: MP3 is a music format where inaudible parts of music are left out, and the rest of the data are compressed. The results are quite impressive. A 64 MB song usually becomes 3-4 MB when converted to MP3 format.
MP3 is THE trend these days, and believe it or not, it seems that one of the first tasks of multimedia developers is to build a MPEG Layer 3 player.
What are we waiting for? Let's see how to use Delphi to build a MP3 player with the TMediaPlayer component. Let us not stop here. This article will show you how to extract (and even change) some more information about the MP3. The most popular tag encryption appears to be ID3. This tag holds the MP3's title, author, genre and some other information... Just for the records: to code a MP3 player with Delphi we have several possibilities. First: we could write a program that remotely controls another application like the WinAmp player. Second: we could use some third-party MP3 component like XAudio; and third: we could use DirectX with IMediaControl to build a player. <B>MP3 with TMediaPlayer?</B>
Remember the TMediaPlayer? Yep, even though it seems that our good-old TMediaPlayer is unable to playback a MP3 file, we'll see that this is, hopefully, wrong. <B>TMediaPlayer component</B><IMG height=28 alt="TMediaPlayer icon" src="http://delphi.about.com/library/graphics/tmediaicon.gif" width=33 border=0>
VCL provides the TMediaPlayer component (located on the System tab of the Component palette) for all the major features of multimedia programming. If you look in the Delphi Help system you'll see that the "MediaPlayer component enables your application to control a media playing or recording device such as a CD-ROM player, video player/recorder, or MIDI sequencer."
<CENTER><IMG height=30 alt="MediaPlayer on Screen" src="http://delphi.about.com/library/graphics/tmediaplayer.gif" width=253 border=0></CENTER>One of the properties of the MediaPlayer is <I>DeviceType</I>. This property holds/contains the multimedia device types that can be opened by a TMediaPlayer component. Several multimedia device types are defined, but none of them is strict MP3. By default, when we put a MediaPlayer on a form, this property is set to <I>dtAutoSelect</I> to have the device type automatically selected based on the filename extension. At design time, we use a file open dialog box to specify the <I>FileName</I> property by clicking the ellipses button (...) in the Object Inspector. If we try to specify a MP3 file at design time we'll see that there is no *.MP3 selection; only AVI, MIDI, or WAVE. This will probably lead you to conclusion that TMediaPlayer is unable to reproduce a MP3 file - wrong! <!-- END ARTICLE CONTENT --><!-- Multi-page feature Navigation. Use this only if the feature has multiple pages. -->
_I_Play_Chess
12-06-2003, 10:10 AM
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><B>Your first MP3 Delphi player </B></TD></TR>
<TR>
<TD bgColor=#cc0000 colSpan=2 height=1><IMG height=1 src="http://images.about.com/all/bullets/dot_clea.gif" width=1 border=0></TD></TR></TBODY></TABLE><B>Part 2: Building a MP3 player Delphi Project's GUI </B>
<B>Step by step...</B>
If you haven't already; this is the time to start Delphi - new project is created with one blank form (form1, by default). This will be the main and the only one form in the <B>mp3 player</B> project. As promissed, our player will not only play MP3 songs, we want the player to display (and even change) certain information about each file - the ID3 tag information. Why not even more: let there be a progress bar to show the current song's play progress. Add following components to form:
From the <I>Standard</I> tab:
one ListBox component, name it 'mp3List'
one GroupBox component containing six Edit components (names: edTitle, edArtist, edAlbum, edYear, edGenre, edComment),
From the <I>Additional</I> tab:
one BitBtn component, name it 'btnOpenFolder',
one StaticText component, name it 'txtFolder',
From the <I>System</I> tab
one Timer component, name it 'ProgresTimer'.
one ProgressBar component, name it 'Progres'.
and of course, one MediaPlayer component, name it 'mp3Player'.
<CENTER><IMG height=209 alt="mp3 player at design time" src="http://delphi.about.com/library/graphics/tmediaproject.gif" width=367 border=0></CENTER>Notice that when you place the <I>MediaPlayer</I> component on a form all 9 buttons are visible. Since we are only going to code a simple player some of the buttons are not required. Therefore, use the <I>VisibleButtons</I> property and hide all the buttons except this three: <I>btPlay</I>, <I>btPause</I>, <I>btStop</I>. The <I>BitBtn</I> and the <I>StaticText</I> are used to select and display the Folder where our MP3 songs are stored. All the MP3 files from the selected folder are listed in the <I>ListBox</I>. I have chosen BitBtn instead of the standard Button component simply because BitBtn has the glyph property - we can easily display a picture on it. <!-- BEGIN FREQUENCY TEMPLATE -->
_I_Play_Chess
12-06-2003, 10:14 AM
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><B>Your first MP3 Delphi player </B></TD></TR>
<TR>
<TD bgColor=#cc0000 colSpan=2 height=1><IMG height=1 src="http://images.about.com/all/bullets/dot_clea.gif" width=1 border=0></TD></TR></TBODY></TABLE><B>Part 3: Building a MP3 player Delphi Project's Code </B>
Even the simpliest project needs some code to run. Till this moment we were only designing our projects GUI - it's time to see our player in action.
<B>Select the folder with MP3 files</B>
As stated before, the <I>btnOpenFolder</I> and the <I>txtFolder</I> are used to select and display the Folder where our MP3 songs are stored. To enable a user to select a list of mp3 songs from a directory on a system Delphi provides us with several possibilities. The OpenDialog component located on the Dialogs tab encapsulates the standard Windows dialog box for opening a file. Another approach is to use the
SHBrowseForFolder Windows API function and to invoke a Windows system dialog used to browse for files and folders on users hard drive as well as network computers and printers. This second approach is exactly what the <I>btnOpenFolder</I> hides in his OnClick event. For a full code see the last part of this article: Project's Code.
All the MP3 files from the selected folder are listed in the <I>mp3List</I> (that is the ListBox component). <B>Display play progress</B>
The trick is simple. The TMediaPlayer <I>Position</I> property holds the current position of a song. The <I>Lenght</I> property specifies the length of the song selected by using the current time format, which is specified by the <I>TimeFormat</I> property. When the user selects a song from the list the following assignement is made
<TABLE width="100%" bgColor=#ffffcc border=1>
<TBODY>
<TR>
<TD><PRE>...
Progress.Max := 0;
<I>{code to open a mp3 song}</I>
Progress.Max := mp3player.Length;
...
</PRE></TD><PRE></PRE></TR></TBODY></TABLE>and in the OnTimer event for the Timer (named 'ProgresTimer') component we have:
<TABLE width="100%" bgColor=#ffffcc border=1>
<TBODY>
<TR>
<TD><PRE><B>procedure</B> TForm1.ProgresTimerTimer
(Sender: TObject);
<B>begin</B>
<B>if</B> Progress.Max <> 0 <B>then</B>
Progress.Position := mp3player.Position;
<B>end</B>;
</PRE></TD><PRE></PRE></TR></TBODY></TABLE><B>Play the MP3 file</B>
You would not believe this, but this is the simplest part. Since, by default, TMediaPlayer knows what to do when the user chooses Play or Stop button - everything we have to do is to prepare the MediaPlayer to accept/open a MP3 file. I'll give you here the whole procedure - the one that is executed when the user select's a song from the list:
<TABLE width="100%" bgColor=#ffffcc border=1>
<TBODY>
<TR>
<TD><PRE><B>procedure</B> TForm1.mp3ListClick(Sender: TObject);
var mp3File:string;
<B>begin</B>
<I>//if the list is empty don't do anything</I>
<B>if</B> mp3List.Items.Count=0 <B>then</B> exit;
<I>//file is FolderName + FileName</I>
mp3File := Concat(txtFolder.Caption,
mp3List.Items.Strings
[mp3List.ItemIndex]);
<I>//Chechk again if it exists</I>
<B>if</B> <B>not</B> FileExists(mp3File) <B>then begin</B>
ShowMessage('MP3 file does not exist?!');
exit;
<B>end</B>;
<I>//used to display the ID3 tag information</I>
FillID3TagInformation (mp3File,
edTitle,
edArtist,
edAlbum,
edYear,
edGenre,
edComment);
Progress.Max:=0;
mp3player.Close;
mp3player.FileName:=mp3File;
mp3player.Open;
Progress.Max := mp3player.Length;
<B>end</B>;
</PRE></TD><PRE></PRE></TR></TBODY></TABLE>
<CENTER><IMG height=208 alt="mp3Player at run time" src="http://delphi.about.com/library/graphics/tmediaruns.gif" width=367 border=0></CENTER><!-- BEGIN FREQUENCY TEMPLATE -->
_I_Play_Chess
12-06-2003, 10:22 AM
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><B>Your first MP3 Delphi player </B></TD></TR>
<TR>
<TD bgColor=#cc0000 colSpan=2 height=1><IMG height=1 src="http://images.about.com/all/bullets/dot_clea.gif" width=1 border=0></TD></TR></TBODY></TABLE><B>Part 4: MP3 ID3 Tag Editing </B>
The thing that makes MP3 files even more great are ID3 tags. Every MP3 file has a little blurb of data on it, which is used to give informations about artist, title, album, publishing year and genre about a song. The "ID3" Tag is attached to most MP3 files these days. The tag is always 128 bytes long and is located at very end of the MP3-file.
The ID3 tag is saved in the last 128 bytes of a MP3 file. ID3 tag should start with a "TAG" string. If this string is absent that means that ID3 information has been removed - or was never set. But don't worry - all we have to do is append it to the file. The ID3-Tag structure can be described as follows:
<TABLE bgColor=#ffffcc border=1>
<TBODY>
<TR>
<TD><PRE><B>type</B>
TID3Rec = <B>packed record</B>
Tag : <B>array</B>[0..2] <B>of</B> Char;
Title,
Artist,
Comment,
Album : <B>array</B>[0..29] <B>of</B> Char;
Year : <B>array</B>[0..3] <B>of</B> Char;
Genre : Byte;
<B>end</B>;
</PRE></TD><PRE></PRE></TR></TBODY></TABLE>Note that genres are determined by one byte of data only. This byte has to be translated into text from the following declaration:
<TABLE width="100%" bgColor=#ffffcc border=1>
<TBODY>
<TR>
<TD><PRE><B>const</B>
MaxID3Genre=147;
ID3Genre: <B>array</B>[0..MaxID3Genre] <B>of string</B> = (
'Blues', 'Classic Rock', 'Country', 'Dance',
...
'Synthpop' <I>{and probably more to come}</I>
);
</PRE></TD><PRE></PRE></TR></TBODY></TABLE><B>Read ID3</B>
To read the ID3 tag from a MP3 song we have to go down to file system and use IO routines. Here goes the code to read the ID3 information:
<TABLE width="100%" bgColor=#ffffcc border=1>
<TBODY>
<TR>
<TD><PRE><B>procedure</B> FillID3TagInformation
(mp3File: <B>string</B>;
Title,Artist,Album,Year,Genre,Comment:TEdit);
<B>var</B> ID3 : TID3Rec;
fmp3: TFileStream;
<B>begin</B>
fmp3:=TFileStream.Create(mp3File, fmOpenRead);
<B>try</B>
fmp3.position:=fmp3.size-128;
fmp3.Read(ID3,SizeOf(ID3));
<B>finally</B>
fmp3.free;
<B>end</B>;
<B>if</B> ID3.Tag <> 'TAG' <B>then begin</B>
Title.Text:='Wrong or no ID3 tag information';
Artist.Text:='Wrong or no ID3 tag information';
Album.Text:='Wrong or no ID3 tag information';
Year.Text:='Wrong or no ID3 tag information';
Genre.Text:='Wrong or no ID3 tag information';
Comment.Text:='Wrong or no ID3 tag information';
<B>end else begin</B>
Title.Text:=ID3.Title;
Artist.Text:=ID3.Artist;
Album.Text:=ID3.Album;
Year.Text:=ID3.Year;
<B>if</B> ID3.Genre in [0..MaxID3Genre] <B>then</B>
Genre.Text:=ID3Genre[ID3.Genre]
<B>else</B>
Genre.Text:=IntToStr(ID3.Genre);
Comment.Text:=ID3.Comment
<B>end</B>;
<B>end</B>;
</PRE></TD><PRE></PRE></TR></TBODY></TABLE>This code uses the <I>TFileStream</I> to access the information in MP3 file. Once we have successfully opened a Mp3 file set the position to EndOfFile-128 bytes and read the ID3 tag. The rest of the code in this procedure simply checks whether there is an ID3 tag information in a file and fills those Edit boxes (parameters in this procedure) with values. <B>Write ID3</B>
The writing part is simple too. This is the function declaration, the whole code can be found in the Project's code part of this article.
<TABLE width="100%" bgColor=#ffffcc border=1>
<TBODY>
<TR>
<TD><PRE><B>procedure</B> ChangeID3Tag
(NewID3: TID3Rec; mp3FileName: <B>string</B>);
</PRE></TD><PRE></PRE></TR></TBODY></TABLE>Note that in the Project's code the call to this function is not covered. This is something I'll leave to you to implement. <B>Before the end</B>
Finally, we've made it! You have your own ready-to-play-and-get-some-money MP3 player working. What I want do to here is to suggest to "play" with it a little and modify it a lot. How about adding some kind of skin to this player in the means of Custom Shaped Forms?
We will add to you this chapter after finishing page 5 with the complete source CODE of this project.<!-- BEGIN FREQUENCY TEMPLATE -->
_I_Play_Chess
12-06-2003, 10:28 AM
**
Your first MP3 Delphi player
See how to build a full-blown mp3 player with Delphi
in just a few seconds. Even more: get the ID3 tag
information from a mp3 file and change it!
}
unit Unit1;
<B>interface</B>
<B>uses</B>
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Buttons, MPlayer, ComCtrls, ExtCtrls;
<B>type</B>
TForm1 = <B>class</B>(TForm)
mp3player: TMediaPlayer;
mp3List: TListBox;
btnOpenFolder: TBitBtn;
GroupBox1: TGroupBox;
edTitle: TEdit;
edArtist: TEdit;
edAlbum: TEdit;
edYear: TEdit;
edGenre: TEdit;
edComment: TEdit;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
Label5: TLabel;
Label6: TLabel;
txtFolder: TStaticText;
Progress: TProgressBar;
ProgresTimer: TTimer;
<B>procedure</B> btnOpenFolderClick(Sender: TObject);
<B>procedure</B> mp3ListClick(Sender: TObject);
<B>procedure</B> FormCreate(Sender: TObject);
<B>procedure</B> ProgresTimerTimer(Sender: TObject);
<B>private</B>
<I>** Private declarations }</I>
<B>public</B>
<I>** Public declarations }</I>
<B>end</B>;
<B>var</B>
Form1: TForm1;
<B>type</B>
TID3Rec = <B>packed record</B>
Tag : array[0..2] <B>of Char</B>;
Title,
Artist,
Comment,
Album : array[0..29] <B>of Char</B>;
Year : array[0..3] <B>of Char</B>;
Genre : Byte;
<B>end</B>;
<B>const</B>
MaxID3Genre=147;
ID3Genre: <B>array</B>[0..MaxID3Genre] <B>of string</B> = (
'Blues', 'Classic Rock', 'Country', 'Dance', 'Disco', 'Funk', 'Grunge',
'Hip-Hop', 'Jazz', 'Metal', 'New Age', 'Oldies', 'Other', 'Pop', 'R&B',
'Rap', 'Reggae', 'Rock', 'Techno', 'Industrial', 'Alternative', 'Ska',
'Death Metal', 'Pranks', 'Soundtrack', 'Euro-Techno', 'Ambient',
'Trip-Hop', 'Vocal', 'Jazz+Funk', 'Fusion', 'Trance', 'Classical',
'Instrumental', 'Acid', 'House', 'Game', 'Sound Clip', 'Gospel',
'Noise', 'AlternRock', 'Bass', 'Soul', 'Punk', 'Space', 'Meditative',
'Instrumental Pop', 'Instrumental Rock', 'Ethnic', 'Gothic',
'Darkwave', 'Techno-Industrial', 'Electronic', 'Pop-Folk',
'Eurodance', 'Dream', 'Southern Rock', 'Comedy', 'Cult', 'Gangsta',
'Top 40', 'Christian Rap', 'Pop/Funk', 'Jungle', 'Native American',
'Cabaret', 'New Wave', 'Psychadelic', 'Rave', 'Showtunes', 'Trailer',
'Lo-Fi', 'Tribal', 'Acid Punk', 'Acid Jazz', 'Polka', 'Retro',
'Musical', 'Rock & Roll', 'Hard Rock', 'Folk', 'Folk-Rock',
'National Folk', 'Swing', 'Fast Fusion', 'Bebob', 'Latin', 'Revival',
'Celtic', 'Bluegrass', 'Avantgarde', 'Gothic Rock', 'Progressive Rock',
'Psychedelic Rock', 'Symphonic Rock', 'Slow Rock', 'Big Band',
'Chorus', 'Easy Listening', 'Acoustic', 'Humour', 'Speech', 'Chanson',
'Opera', 'Chamber Music', 'Sonata', 'Symphony', 'Booty Bass', 'Primus',
'Porn Groove', 'Satire', 'Slow Jam', 'Club', 'Tango', 'Samba',
'Folklore', 'Ballad', 'Power Ballad', 'Rhythmic Soul', 'Freestyle',
'Duet', 'Punk Rock', 'Drum Solo', 'Acapella', 'Euro-House', 'Dance Hall',
'Goa', 'Drum & Bass', 'Club-House', 'Hardcore', 'Terror', 'Indie',
'BritPop', 'Negerpunk', 'Polsk Punk', 'Beat', 'Christian Gangsta Rap',
'Heavy Metal', 'Black Metal', 'Crossover', 'Contemporary Christian',
'Christian Rock', 'Merengue', 'Salsa', 'Trash Metal', 'Anime', 'Jpop',
'Synthpop' <I>{and probably more to come}</I>
);
<B>implementation</B>
<B>uses</B> ShellAPI, ShlObj; <I>// needed for the BrowseForFolder function</I>
<B></B>**$R *.DFM}</I></FONT>
<B>procedure</B> FillID3TagInformation(mp3File:string; Title,Artist,Album,Year,Genre,Comment:TEdit);
<B>var</B> <I>//fMP3: file of Byte;</I>
ID3 : TID3Rec;
fmp3: TFileStream;
<B>begin</B>
fmp3:=TFileStream.Create(mp3File, fmOpenRead);
<B>try</B>
fmp3.position:=fmp3.size-128;
fmp3.Read(ID3,SizeOf(ID3));
<B>finally</B>
fmp3.free;
<B>end</B>;
<I>** or the non Stream approach - as in ChangeID3Tag procedure
try
AssignFile(fMP3, mp3File);
Reset(fMP3);
try
Seek(fMP3, FileSize(fMP3) - 128);
BlockRead(fMP3, ID3, SizeOf(ID3));
finally
end;
finally
CloseFile(fMP3);
end;
}</I>
<B>if</B> ID3.Tag <> 'TAG' <B>then begin</B>
Title.Text:='Wrong or no ID3 tag information';
Artist.Text:='Wrong or no ID3 tag information';
Album.Text:='Wrong or no ID3 tag information';
Year.Text:='Wrong or no ID3 tag information';
Genre.Text:='Wrong or no ID3 tag information';
Comment.Text:='Wrong or no ID3 tag information';
<B>end else begin</B>
Title.Text:=ID3.Title;
Artist.Text:=ID3.Artist;
Album.Text:=ID3.Album;
Year.Text:=ID3.Year;
<B>if</B> ID3.Genre <B>in</B> [0..MaxID3Genre] <B>then</B>
Genre.Text:=ID3Genre[ID3.Genre]
<B>else</B>
Genre.Text:=IntToStr(ID3.Genre);
Comment.Text:=ID3.Comment
<B>end</B>;
<B>end</B>;
<B>procedure</B> ChangeID3Tag(NewID3: TID3Rec; mp3FileName: <B>string</B>);
<B>var</B>
fMP3: <B>file of</B> Byte;
OldID3 : TID3Rec;
<B>begin</B>
<B>try</B>
AssignFile(fMP3, mp3FileName);
Reset(fMP3);
<B>try</B>
Seek(fMP3, FileSize(fMP3) - 128);
BlockRead(fMP3, OldID3, SizeOf(OldID3));
<B>if</B> OldID3.Tag = 'TAG' <B>then</B>
<I>** Replace old tag }</I>
Seek(fMP3, FileSize(fMP3) - 128)
<B>else</B>
<I>** Append tag to file because it doesn't exist </I>}
Seek(fMP3, FileSize(fMP3));
BlockWrite(fMP3, NewID3, SizeOf(NewID3));
<B>finally</B>
<B>end</B>;
<B>finally</B>
CloseFile(fMP3);
<B>end</B>;
<B>end</B>;
<B>procedure</B> FillMP3FileList(Folder: string; sl: TStrings);
<B>var</B> Rec : TSearchRec;
<B>begin</B>
sl.Clear;
<B>if</B> SysUtils.FindFirst(Folder + '*.mp3', faAnyFile, Rec) = 0 <B>then</B>
<B>try</B>
<B>repeat</B>
sl.Add(Rec.Name);
<B>until</B> SysUtils.FindNext(Rec) <> 0;
<B>finally</B>
SysUtils.FindClose(Rec);
<B>end</B>;
<B>end</B>;
<B>function</B> BrowseDialog(const Title: <B>string</B>; <B>const</B> Flag: integer): <B>string</B>;
<B>var</B>
lpItemID : PItemIDList;
BrowseInfo : TBrowseInfo;
DisplayName : array[0..MAX_PATH] of char;
TempPath : array[0..MAX_PATH] of char;
<B>begin</B>
Result:='';
FillChar(BrowseInfo, sizeof(TBrowseInfo), #0);
<B>with</B> BrowseInfo <B>do begin</B>
hwndOwner := Application.Handle;
pszDisplayName := @DisplayName;
lpszTitle := PChar(Title);
ulFlags := Flag;
<B>end</B>;
lpItemID := SHBrowseForFolder(BrowseInfo);
<B>if</B> lpItemId <> nil <B>then begin</B>
SHGetPathFromIDList(lpItemID, TempPath);
Result := IncludeTrailingBackslash(TempPath);
GlobalFreePtr(lpItemID);
<B>end</B>;
<B>end</B>;
<B>procedure</B> TForm1.btnOpenFolderClick(Sender: TObject);
<B>var</B> mp3Folder : <B>string</B>;
<B>begin</B>
mp3Folder := BrowseDialog('Choose a folder with mp3 files', BIF_RETURNONLYFSDIRS);
<B>if</B> mp3Folder = '' <B>then</B> Exit;
txtFolder.Caption := mp3Folder;
FillMP3FileList(mp3Folder, mp3List.Items);
<B>end</B>;
<B>procedure</B> TForm1.mp3ListClick(Sender: TObject);
<B>var</B> mp3File: <B>string</B>;
<B>begin</B>
<B>if</B> mp3List.Items.Count=0 <B>then</B> exit;
mp3File := Concat(txtFolder.Caption, mp3List.Items.Strings[mp3List.ItemIndex]);
<B>if not</B> FileExists(mp3File) <B>then begin</B>
ShowMessage('MP3 file '+#13#10+ mp3File +#13#10+'does not exist!');
exit;
<B>end</B>;
FillID3TagInformation(mp3File, edTitle, edArtist, edAlbum, edYear, edGenre, edComment);
Progress.Max:=0;
mp3player.Close;
mp3player.FileName:=mp3File;
mp3player.Open;
Progress.Max := mp3player.Length;
<B>end</B>;
<B>procedure</B> TForm1.FormCreate(Sender: TObject);
<B>begin</B>
txtFolder.Caption := ExtractFilePath(Application.ExeName);
FillMP3FileList(txtFolder.Caption, mp3List.Items);
Progress.Max:=0;
<B>end</B>;
<B>procedure</B> TForm1.ProgresTimerTimer(Sender: TObject);
<B>begin</B>
<B>if</B> Progress.Max<>0 <B>then</B>
Progress.Position := mp3player.Position;
<B>end</B>;
<B>end</B>.
vBulletin v3.5.4, Copyright ©2000-2012, Jelsoft Enterprises Ltd.