Delphirus - прграммирование на delphi
   Все о delphi Delphirus - прграммирование на delphi
blocks.gif
Навигация
 

Главная
Статьи
Базы данных
Графика
Защита
Интернет
Система
Тексты
Мультимедиа
Файлы
Формы и окна
Другое
Советы
Базы данных
Графика
Интернет
Мультимедиа
Система
Тексты
Файлы
Файлы
Исходники
Компоненты
Инфо
Поиск по сайту
Обратная связь
Самое популярное
Аккаунт
Карта сайта

 
story.gif
Ваш первый MP3-плейер
 
Работа со звуком и видео

MP3 сейчас, пожалуй, наиболее популярный формат для хранения музыки. Давайте напишем плейер, способный воспроизводить музыку в этом формате + некоторые дополнительные возможности. Все, что нам для этого понадобится - это компонента TMediaPlayer и немного времени. Вы думаете, TMediaPlayer не умеет проигрывать MP-шки? Вы, к счастью, ошибаетесь.


 Итак, ищем компоненту TMediaPlayer на вкладке System палитры компонент Delphi. Если вы посмотрите в помощи, то увидите что-нибудь типа "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." Ни слова о MP3. MediaPlayer имеет свойство DeviceType, определяющее тип устройства, которым можно управлять с помощью этой компоненты, но в списке устройств вы опять-таки не найдете что-нибудь похожее на MP3. Однако это не значит, что MP3 не поддерживается.
    Будем считать, что среда Delphi уже запущена и открыта форма по умолчанию form1. Это первая и последняя форма в нашем приложении.
   Как и было обещано, наш проигрыватель будет не только воспроизодить MP3-файлы, но и читать (и изменять) так называемый тэг ID3. И даже больше - у нас будет прогресс-бар, показывающий какую часть музыкального произведения мы слушаем.
   На форму добавьте следующие компоненты:

  • Со вкладки Standard:
    компоненту ListBox, назовите ее 'mp3List';
    компоненту GroupBox, содержащую 6 компонент Edit (названных: edTitle, edArtist, edAlbum, edYear, edGenre, edComment);
  • Со вкладки Additional:
    компоненту BitBtn, назовите ее 'btnOpenFolder';
    компоненту StaticText c именем 'txtFolder';
  • Со вкладки System:
    компоненту Timer, назовите ее 'ProgresTimer';
    компоненту ProgressBar, назовите ее 'Progres';
    и, конечно, компоненту MediaPlayer, назовите ее 'mp3Player'.

Дизайн - личное дело каждого, можно предложить, например, такой вариант:

Замечание: когда вы помещаете компоненту MediaPlayer на форму, она содержит 9 кнопок. Так как в нашем приложении используется всего 3 кнопки, измените свойство VisibleButtons для отображения только трех кнопок (btPlay, btPause, btStop).
   Компоненты BitBtn и StaticText служат для определения и отображения каталога, из которого беруться MP3-файлы. Список файлов отображается в компоненте ListBox. Компоненты Edit служит для отображения информации тэга ID3. И, наконец, компонента Timer вместе с ProgressBar служит для отображения прослушиваемой части музыкальной композиции.
 

Теперь нужно написать код, обеспечивающий функциональность нашего MP3-плейера.

Выбор каталога с MP3-файлами

Как было сказано выше, для выбора и отображением каталога используются компоненты, названные btnOpenFolder и txtFolder. Как реализована данная функция, смотрите в полном листинге программы.

Отображение прогресс-бара

Здесь все просто. Свойство Position компоненты TMediaPlayer содержит текущую позицию в проигрываемом файле. Свойство Length содержит длину проигрываемой композиции. Когда пользователь выбирает какую-нибудь песню из списка, выполняется следующий кусок кода:
 

...
Progress.Max := 0;
{код для открытия mp3}
Progress.Max := mp3player.Length;
...

 

А в обработчике события OnTimer компоненты Timer содержится следующий код:
 

procedure TForm1.ProgresTimerTimer (Sender: TObject);
begin
   if Progress.Max <> 0 then
      Progress.Position := mp3player.Position;
end;

 

Проигрывание MP3-файла

Вы не поверите, но это простейшая секция во всей программе. Все, что нужно сделать - сформировать имя файла и передать его в MediaPlayer.
 

procedure TForm1.mp3ListClick(Sender: TObject);
var mp3File:string;
begin
//если список пустой - не делать ничего
   if mp3List.Items.Count=0 then exit;
//имя файла = каталог + FileName
   mp3File := Concat(txtFolder.Caption,
      mp3List.Items.Strings
      [mp3List.ItemIndex]);

//проверить существование файла
   if not FileExists(mp3File) then begin
      ShowMessage('MP3 file does not exist?!');
      exit;
   end;

//отобразить информацию ID3
   FillID3TagInformation (mp3File,
      edTitle,
      edArtist,
      edAlbum,
      edYear,
      edGenre,
      edComment);

   Progress.Max:=0;

   mp3player.Close;
   mp3player.FileName:=mp3File;
   mp3player.Open;

   Progress.Max := mp3player.Length;
end;

 

Просмотр и редактирование тэга ID3

Тэг ID3 содержит информацию о композиции: исполнитель, жанр и т.п. Этот кусок информации содержится в последних 128 байтах файла. Начинается тэг словом "TAG". Его может и не быть, если тэг удален или не был заполнен при создании. Однако его всегда можно добавить. Тэг ID3 имеет следующий формат:
 

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',
   ...
   'Synthpop' {возможно, список будет расширен}
);

 

Для чтения тэга ID3 служит процедура FillID3TagInformation:
 

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;

 

Этот код использует объект TFileStream для доступа к тэгу ID3. После открытия файла указатель устанавливается на позицию EndOfFile-128. Если в этой позиции найдено слово "TAG", информация копируется в соответствующие поля редактирования, иначе эти поля заполняются сообщениями по умолчанию.
Вот, пожалуй, и все. Запись тэга ID3 предлагается к самостоятельному изучению - пусть хоть что-то напишется вашими руками. На следующей странице вы найдете полный исходный текст приложения.
 

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.

Источник http://www.realcoding.net/

 
Разместил 31/01/2004 от rolcom ( Прочитано: )

  blocks.gif
Связанные ссылки
 

· Больше про Работа со звуком и видео
· Новость от rolcom


Самая читаемая статья: Работа со звуком и видео:
Direct Show и Delphi

 
blocks.gif
Рейтинг статьи
 

Средняя оценка: 3.52
Ответов: 17


Пожалуйста, проголосуйте за эту статью:

Отлично
Очень хорошо
Хорошо
Нормально
Плохо


 
blocks.gif
опции
 


 Напечатать текущую страницу  Напечатать текущую страницу

 Отправить статью другу  Отправить статью другу

 
 

Page generation 0.065 seconds