你的第一個 MP3 Delphi播放器 |
|
cmf
尊榮會員 ![]() ![]() ![]() ![]() ![]() 發表:84 回覆:918 積分:1032 註冊:2002-06-26 發送簡訊給我 |
你的第一個
MP3 Delphi播放器
Part 1: Delphi 演奏 MP3?我們需要TMediaPlayer! 你可能知道: MP3 是一個 inaudible parts of music的音樂格式﹐而且資料是壓縮的 結果相當令人印象深刻。 當變換到 MP3 格式的時候 , 一首 64 MB 歌通常變成 3-4個 MB 。 MP3 是趨勢,而且信不信由你,它似乎是多媒體開發者的第一個作業建築一個MPEG Layer 3 播放器。 我們正在等候什麼? 讓我們看該如何使用Delphi TMediaPlayer 元件建築一個 MP3 播放器。 在這裡讓了我們不停止。 這一個文章將教你該如何摘錄 (和甚至改變)再多一些關於 MP3 的資訊。 最受歡迎的tag encryption 似乎是 ID3 。 這一個tag保存 MP3's 的標題,作家,類和一些其他的資料.... 用我們的Delphi 編碼一個 MP3 播放器。 第一: 我們可以寫一個遠端控制另一個應用程式的程式像是 WinAmp 播放器。 第二: 我們可以使用像 XAudio 一樣的一些第三者 MP3 元件; 第三: 我們可以使用 DirectX IMediaControl 建築一個播放器。 TMediaPlayer component ![]() VCL 提供 TMediaPlayer 元件 (在元件板的系統 tab)給多媒體程式設計的所有主要的功能。 如果你順便探訪Delphi Help你將看見 "MediaPlayer 元件使你的應用程式能夠控制媒體演奏或錄音 , 像是一個光碟播放器,影像播放機/錄音器或 MIDI ". ![]() 這屬性保存/含有可以被 TMediaPlayer 元件開啟的多媒體裝置類型。 一些多媒體裝置類型被定義﹐但是他們沒有詳盡的 MP3 。 預設值﹐當我們把 MediaPlayer 放在form上時﹐這屬性被設定成 dtAutoSelect 使裝置型態被自動地選擇基於副檔名。 在設計時間﹐我們在物件檢查員中使用一個檔案開放的對話盒藉由點一下橢圓按鈕指定檔名屬性(...) 如果我們在設計時間試著指定一個 MP3 檔案 , 我們將看見無 *.MP3 選擇;只有 AVI , MIDI 或WAVE.這將可能引導你走向 TMediaPlayer 不能夠再生 MP3 檔案-錯誤的結論! Part 2: 建立 MP3 播放器Delphi Project's圖形用戶界面 Step by step... 這是啟動Delphi的時候- new project 與一個空白form一起建立。(form1,預設值) 這將是主form和 mp3 播放器 project唯一的 form。 如 promissed ﹐我們的播放器將不只演奏 MP3 歌,我們想要播放器顯示 (和甚至改變)關於每個檔案的某些資訊-ID3 tag資料。 Why not even more: 讓我有一個progress bar 看目前的歌演奏進度。 加入下列元件到你的 form: ![]() 一個簡單的播放器一些按鈕不是必需的。 因此,除了btPlay , btPause , btStop使用 VisibleButtons 屬性並且影藏所有的按鈕 BitBtn 和 StaticText 用來選擇並且顯示我們的 MP3 歌儲存的檔案夾。 ListBox 列出挑選的檔案夾的所有的 MP3 檔案。 只是因為 BitBtn 有 glyph 屬性 , 我已經選擇 BitBtn 代替標準的按鈕元件-我們可以容易地在它上面顯示圖片。 GroupBox 內的所有Edit元件將用來顯示 ID3 tag資料。 連同 ProgressBar 的計時器元件將用來顯示演奏進行
<!-- BEGIN FREQUENCY TEMPLATE --> Select the folder with MP3 files As stated before, the btnOpenFolder and the txtFolder 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 btnOpenFolder 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 mp3List (that is the ListBox component). To list all the MP3 files in a given directory we use techniques described in the Searching For Files article. Display play progress The trick is simple. The TMediaPlayer Position property holds the current position of a song. The Lenght property specifies the length of the song selected by using the current time format, which is specified by the TimeFormat property. When the user selects a song from the list the following assignement is made ... Progress.Max := 0; {code to open a mp3 song} Progress.Max := mp3player.Length; ... and in the OnTimer event for the Timer (named 'ProgresTimer') component we have: procedure TForm1.ProgresTimerTimer (Sender: TObject); begin if Progress.Max <> 0 then Progress.Position := mp3player.Position; end; Play the MP3 file 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: procedure TForm1.mp3ListClick(Sender: TObject); var mp3File:string; begin //if the list is empty don't do anything if mp3List.Items.Count=0 then exit; //file is FolderName FileName mp3File := Concat(txtFolder.Caption, mp3List.Items.Strings [mp3List.ItemIndex]); //Chechk again if it exists if not FileExists(mp3File) then begin ShowMessage('MP3 file does not exist?!'); exit; end; //used to display the ID3 tag information FillID3TagInformation (mp3File, edTitle, edArtist, edAlbum, edYear, edGenre, edComment); Progress.Max:=0; mp3player.Close; mp3player.FileName:=mp3File; mp3player.Open; Progress.Max := mp3player.Length; end; ![]() Part 4: MP3 ID3 Tag Editing <!-- BEGIN FREQUENCY TEMPLATE --> <!--END FREQUENCY TEMPLATE--> <!-- BEGIN ARTICLE CONTENT -->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: type TID3Rec = packed record Tag : array[0..2] of Char; Title, Artist, Comment, Album : array[0..29] of Char; Year : array[0..3] of Char; Genre : Byte; end; Note that genres are determined by one byte of data only. This byte has to be translated into text from the following declaration: const MaxID3Genre=147; ID3Genre: array[0..MaxID3Genre] of string = ( 'Blues', 'Classic Rock', 'Country', 'Dance', ... 'Synthpop' {and probably more to come} ); Read ID3 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: procedure FillID3TagInformation (mp3File: string; Title,Artist,Album,Year,Genre,Comment:TEdit); var ID3 : TID3Rec; fmp3: TFileStream; begin fmp3:=TFileStream.Create(mp3File, fmOpenRead); try fmp3.position:=fmp3.size-128; fmp3.Read(ID3,SizeOf(ID3)); finally fmp3.free; end; if ID3.Tag <> 'TAG' then begin 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'; end else begin Title.Text:=ID3.Title; Artist.Text:=ID3.Artist; Album.Text:=ID3.Album; Year.Text:=ID3.Year; if ID3.Genre in [0..MaxID3Genre] then Genre.Text:=ID3Genre[ID3.Genre] else Genre.Text:=IntToStr(ID3.Genre); Comment.Text:=ID3.Comment end; end; This code uses the TFileStream 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. Write ID3 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. procedure ChangeID3Tag (NewID3: TID3Rec; mp3FileName: string); 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. Before the end 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. There are certainly some great ideas you can compose in this project, let the other see what you have made: post you creation to the Free Applications section on this site. <!-- END ARTICLE CONTENT --> <!-- Multi-page feature Navigation. Use this only if the feature has multiple pages. --> 完整程式列表如下 { Article: Your first MP3 Delphi player http://delphi.about.com/library/weekly/aa112800a.htm 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! For the .zip file of this project click here. } unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Buttons, MPlayer, ComCtrls, ExtCtrls; type TForm1 = class(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; procedure btnOpenFolderClick(Sender: TObject); procedure mp3ListClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure ProgresTimerTimer(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; type TID3Rec = packed record Tag : array[0..2] of Char; Title, Artist, Comment, Album : array[0..29] of Char; Year : array[0..3] of Char; Genre : Byte; end; const MaxID3Genre=147; ID3Genre: array[0..MaxID3Genre] of string = ( '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' {and probably more to come} ); implementation uses ShellAPI, ShlObj; // needed for the BrowseForFolder function {$R *.DFM} procedure FillID3TagInformation(mp3File:string; Title,Artist,Album,Year,Genre,Comment:TEdit); var //fMP3: file of Byte; ID3 : TID3Rec; fmp3: TFileStream; begin fmp3:=TFileStream.Create(mp3File, fmOpenRead); try fmp3.position:=fmp3.size-128; fmp3.Read(ID3,SizeOf(ID3)); finally fmp3.free; end; { 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; } if ID3.Tag <> 'TAG' then begin 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'; end else begin Title.Text:=ID3.Title; Artist.Text:=ID3.Artist; Album.Text:=ID3.Album; Year.Text:=ID3.Year; if ID3.Genre in [0..MaxID3Genre] then Genre.Text:=ID3Genre[ID3.Genre] else Genre.Text:=IntToStr(ID3.Genre); Comment.Text:=ID3.Comment end; end; procedure ChangeID3Tag(NewID3: TID3Rec; mp3FileName: string); var fMP3: file of Byte; OldID3 : TID3Rec; begin try AssignFile(fMP3, mp3FileName); Reset(fMP3); try Seek(fMP3, FileSize(fMP3) - 128); BlockRead(fMP3, OldID3, SizeOf(OldID3)); if OldID3.Tag = 'TAG' then { Replace old tag } Seek(fMP3, FileSize(fMP3) - 128) else { Append tag to file because it doesn't exist } Seek(fMP3, FileSize(fMP3)); BlockWrite(fMP3, NewID3, SizeOf(NewID3)); finally end; finally CloseFile(fMP3); end; end; procedure FillMP3FileList(Folder: string; sl: TStrings); var Rec : TSearchRec; begin sl.Clear; if SysUtils.FindFirst(Folder '*.mp3', faAnyFile, Rec) = 0 then try repeat sl.Add(Rec.Name); until SysUtils.FindNext(Rec) <> 0; finally SysUtils.FindClose(Rec); end; end; function BrowseDialog(const Title: string; const Flag: integer): string; var lpItemID : PItemIDList; BrowseInfo : TBrowseInfo; DisplayName : array[0..MAX_PATH] of char; TempPath : array[0..MAX_PATH] of char; begin Result:=''; FillChar(BrowseInfo, sizeof(TBrowseInfo), #0); with BrowseInfo do begin hwndOwner := Application.Handle; pszDisplayName := @DisplayName; lpszTitle := PChar(Title); ulFlags := Flag; end; lpItemID := SHBrowseForFolder(BrowseInfo); if lpItemId <> nil then begin SHGetPathFromIDList(lpItemID, TempPath); Result := IncludeTrailingBackslash(TempPath); GlobalFreePtr(lpItemID); end; end; procedure TForm1.btnOpenFolderClick(Sender: TObject); var mp3Folder : string; begin mp3Folder := BrowseDialog('Choose a folder with mp3 files', BIF_RETURNONLYFSDIRS); if mp3Folder = '' then Exit; txtFolder.Caption := mp3Folder; FillMP3FileList(mp3Folder, mp3List.Items); end; procedure TForm1.mp3ListClick(Sender: TObject); var mp3File: string; begin if mp3List.Items.Count=0 then exit; mp3File := Concat(txtFolder.Caption, mp3List.Items.Strings[mp3List.ItemIndex]); if not FileExists(mp3File) then begin ShowMessage('MP3 file ' #13#10 mp3File #13#10 'does not exist!'); exit; end; FillID3TagInformation(mp3File, edTitle, edArtist, edAlbum, edYear, edGenre, edComment); Progress.Max:=0; mp3player.Close; mp3player.FileName:=mp3File; mp3player.Open; Progress.Max := mp3player.Length; end; procedure TForm1.FormCreate(Sender: TObject); begin txtFolder.Caption := ExtractFilePath(Application.ExeName); FillMP3FileList(txtFolder.Caption, mp3List.Items); Progress.Max:=0; end; procedure TForm1.ProgresTimerTimer(Sender: TObject); begin if Progress.Max<>0 then Progress.Position := mp3player.Position; end; end. { ******************************************** Zarko Gajic About.com Guide to Delphi Programming http://delphi.about.com email: delphi.guide@about.com free newsletter: http://delphi.about.com/library/blnewsletter.htm forum: http://forums.about.com/ab-delphi/start/ ******************************************** }
------
︿︿ |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |