Программирование с C++ Builder

           

Воспроизведение звука



В качестве примера использования компонента MediaPiayer для воспроизведения звука рассмотрим программу, используя которую, можно прослушать звуковые фрагменты, сопровождающие события Windows — такие, как начало и завершение работы, появление диалогового окна и др. Форма и диалоговое окно программы "Звуки Windows" представлены на рис. 4.5, текст — в листинге 4.2, а значения свойств компонента MediaPiayer1 — в табл. 4.7.



Рис. 4.5. Форма и диалоговое окно программы "Звуки Windows"


Таблица 4.7. Значения свойств компонента MediaPlayer1

Компонент
Значение


DeviceType
dtAutoSelect
VisibleButtons .btNext
false
VisibleButtons . BtPrev
false
VisibleButtons .btStep
false
VisibleButtons. btBack
false
VisibleButtons .btRecord
false
VisibleButtons. btEject
false


Помимо компонента MediaPlayer на форме находится компонент ListBox, который используется для выбора звукового файла, и два компонента Labe1, первый из которых используется для вывода информационного сообщения, второй — для отображения имени файла, выбранного пользователем.

 Листинг 4.2. Использование компонента MediaPlayer для воспроизведения звука

void __fastcall TForml::FormCreate(TObject *Sender)
{
char *wd; // каталог Windows
wd = (char*)AllocMem(MAX_PATH);
GetWindowsDirectory(wd,MAX_PATH);
SoundPath = wd;
// звуковые файлы находятся в подкаталоге Media
SoundPath = SoundPath + "\\Media\\";
// сформируем список звуковых файлов
TSearchRec sr;
if (FindFirst( SoundPath + "*.wav", faAnyFile, sr) == 0)
{
// найден файл с расширением wav
ListBoxl->Items->Add(sr.Name);
// добавим имя файла в список
// еще есть файлы с расширением wav?
while (FindNext(sr) == 0)
ListBoxl->Items->Add(sr.Name);
}
if (FindFirst( SoundPath + "*.mid", faAnyFile, sr) == 0) {
// найден файл с расширением mid
ListBoxl->Items->Add(sr.Name);
// добавим имя файла в список
// еще есть файлы с расширением mid?
while (FindNext(sr} = 0)
ListBoxl->Items->Add(sr.Name); }
if (FindFirstf SoundPath + "*.rmi", faAnyFile, sr) == 0) {
// найден файл с расширением rmi
ListBoxl->Items->Add(sr.Name);
// добавим имя файла в список
// еще есть файлы с расширением rmi?
while (FindNext(sr) == 0)
ListBoxl->Items->Add(sr.Name); }
// воспроизвести первый файл
if ( ListBoxl->Items->Count != 0)
{
Label2->Caption = ListBoxl->Items->Strings[1];
MediaPlayerl->FileName = SoundPath + ListBoxl->Items->Strings[l];
MediaPlayerl->Open();
MediaPlayerl->Play(); 
}
 }
// щелчок на элементе списка
void__fastoall TForml::ListBoxlClick(TObject *Sender)
{
Label2->Caption = ListBoxl->Items->Strings[ListBoxl->ItemIndex];
MediaPlayerl->FileName = SoundPath + Label2->Caption;
MediaPlayerl->Open();
MediaPlayerl->Play() ;
 } 

Работает программа следующим образом. Сразу после запуска функция обработки события onCreate формирует список звуковых файлов (WAV, MID и RMI), которые находятся в подкаталоге Media главного каталога Windows. Так как на разных компьютерах каталог, в который установлена операционная система, может называться по-разному, то для получения его имени используется API функция GetwindowsDirectory, значением которой является полное имя каталога Windows. Список звуковых файлов формируется

При помощи функций FindFirst и FindNext. функция FindFirst обеспечивает поиск файла, удовлетворяющего критерию поиска, указанному при вызове функции. Функция FindNext продолжает процесс поиска. Обеим функциям в качестве параметра передается структура типа TSearchRec, поле Name которой (в случае успеха) содержит имя файла, удовлетворяющего критерию поиска. После того как список звуковых файлов сформирован, применением метода Play активизируется процесс воспроизведения первого файла.

Щелчок на элементе списка обрабатывается функцией TFom1: :ListBox1Click, которая присваивает значение свойству FileName компонента MediaPiayer1, при помощи метода open открывает выбранный файл и применением метода Play активизирует процесс воспроизведения.

Следующий пример показывает, как на основе компонента MediaPiayer можно создать вполне приличный проигрыватель компакт-дисков. Вид формы и диалогового окна программы приведен на рис. 4.6. Помимо компонентов, показанных на рисунке, в форме есть компонент MediaPiayer. Так как кнопки компонента MediaPiayer во время работы программы не используются (для управления плеером служат кнопки Button1, Button2 и Buttons), свойству visible присвоено значение false, а сам компонент находится за границей формы.



Рис. 4.6. Форма программы CD Player


Значки на кнопках управления — это текст, изображенный шрифтом Webdings. При использовании этого шрифта, например, цифре 4 соответствует значок Play. Соответствие значков Webdings и обычных символов отражает табл. 4.8.

Таблица 4.8. Изображение символов шрифта Webdings

Символ Webdings
Обычный символ — например, шрифт Arial
Код символа (шестнадцатеричный)

9
39

4
34

:

<


Компонент Timer используется для организации цикла опроса состояния медиаплеера. Во время воспроизведения CD функция обработки события OnTimer выводит на индикатор (в поле метки Label1) номер трека и время воспроизведения.

Вид окна программы сразу после ее запуска в случае, если в CD-дисководе находится Audio CD, приведен на рис. 4.7. В случае, если в CD-дисководе диска нет или диск не звуковой, вместо информации о времени воспроизведения будет выведено сообщение "Вставьте Audio CD". Щелчок на кнопке Play (Button1) активизирует процесс воспроизведения. Во время воспроизведения на индикаторе отражается номер и длительность воспроизводимого трека, а также время от начала воспроизведения (рис. 4.8).



Рис. 4.7. В начале работы на индикаторе выводится информация о времени воспроизведения CD или сообщение о необходимости вставить в дисковод Audio CD



Рис. 4.8. Во время воспроизведения на индикаторе отображается информация о воспроизводимом треке


Текст программы приведен в листинге 4.3. Следует обратить внимание на событие Notify, которое может генерировать MediaPiayer. Событие Notify возникает в момент изменения состояния плеера при условии, что значение свойства Notify равно true. В рассматриваемой программе событие Notify используется для обнаружения факта открытия CD-дисковода пользователем.

Листинг 4.3. Проигрыватель компакт дисков

#define Webdings //на кнопках плеера стандартные символы,
// изображение которых взято из шрифта Webdings 
#ifdef Webdings 

// "текст" на кнопках при использовании
// шрифта Webdings 
#define PLAY "4" 
#define STOP "<" 
#define PREVIOUS "9" 
#define NEXT ":" 
#else 
// текст на кнопках при использовании 
// обычного шрифта, например, Arial 
#define PLAY "Play" 
#define STOP "Stop" 
#define PREVIOUS "Previous" 
#define NEXT "Next" 
#endif 
// эти макросы обеспечивают перевод интервала времени,
 // выраженного в миллисекундах в минуты и секунды 
#define MINUTE(ms) ( (ms/1000)/60) 
#define SECOND,(ms) ( (ms/1000) %60) 
// выводит в поле Label 1 информацию о текущем треке 
void __fastcall TForml::TrackInfo() 
{ 
int ms; // время звучания трека, мсек 
AnsiString st; 
Track = MCI_TMSF_TRACK(MediaPlayer->Position); 
MediaPlayer->TimeFormat = tfMilliseconds; 
ms = MediaPlayer-XTrackLength[Track]; 
MediaPlayer->TimeFormat = tfTMSF; 
st = "Трек "+ IntToStr(Track); 
st = st + ". Длительность "+ IntToStr(MINUTE(ms));
st = st + ":" + IntToStr(SECOND(ms)); 
Label1->Caption = st; } 
void __fastcall TForml::FormCreate(TObject *Sender) 
{ 
Buttonl->Caption = PLAY;
Button2->Caption = PREVIOUS; 
Button3->Caption = NEXT; 
MediaPlayer->Notify = true; // разрешить событие Notify } 
// изменение состояния плеера 
void __fastcall.TForml::MediaPlayerNotifу(TObject *Sender) 
{ 
switch ( MediaPlayer->Mode)
{
case mpOpen: // пользователь открыл дисковод (
Buttonl->Enabled = false; 
Button1->Caption = PLAY; 
Button1->Tag = 0; 
Button2->Enabled = false; 
Button3->Enabled = false; 
Label2->Caption = "00:00";
/* по сигналу от таймера будем проверять 
состояние дисковода */ 
Timer->Enabled = True; }
 }
MediaPlayer->Notify = true; 
}
// щелчок на кнопке Play/Stop 
void _fastcall TForml::ButtonlClick(TObject *Sender) 
{ 
if ( Buttonl-XTag = 0) { 
// щелчок на кнопке Play 
MediaPlayer->Play() ; 
Buttonl->Caption = STOP; 
Buttonl->Hint = "Стоп"; 
Buttonl->Tag = 1; 
Button3->Enabled = true; // доступна кнопка "следующий трек" 
MediaPlayer->Notify = true; 
Timer->Enabled = true; 
Tracklnfо(); 
}
 else { 
// щелчок на кнопке Stop 
Buttonl->Caption = PLAY;
Buttonl->Hint = "Воспроизведение"; 
Buttonl->Tag = 0; 
MediaPlayer->Notify = true; 
MediaPlayer->Stop();
Timer->Enabled = false; } } 
// сигнал от таймера: вывести номер трека
// и время воспроизведения 
void __fastcall TForml::TimerTimer(TObject *Sender) 
{ 
int trk; // трек 
int min, sec; // время 
AnsiString st; 
if ( MediaPlayer->Mode == mpPlaying) // режим воспроизведения 
{ 
// получить номер воспроизводимого трека
trk = MCI_TMSF_TRACK(MediaPlayer->Position); 
if ( trk != Track) // произошла смена трека
 { 
TrackInfo0 ;
 Track = trk; if { Track == 2) 
Button2->Enabled = true; // доступна кнопка "пред.трек" 
if ( Track == MediaPlayer-XTracks) 
Button3->Enabled = false; // кнопка "след.трек" недоступна } 
// вывод информации о воспроизводимом треке
 min = MCI_TMSF_MINUTE(MediaPlayer->Position); 
sec = MCIJTMSF_SECOND(MediaPlayer->Position); 
st.printf("%d:%.2d",min,sec); Label2->Caption = st; return; 
} 
/* Если дисковод открыт или в нем нет 
Audio CD, то Mode == mpOpen. 
Ждем диск, т. е. до тех пор, пока не будет 
Mode == mpStopped + кол-во треков > 1
*/ if ( (MediaPlayer->Mode == mpStopped) && 
(MediaPlayer-XTracks > 1)} < 
// диск вставлен
Timer->Enabled = false; 
Buttonl->Caption = PLAY; 
Buttonl->Enabled = true; 
Buttonl-XTag = 0; 
MediaPlayer->Notify = true; 
// получить информацию о времени звучания CD 
MediaPlayer-XTimeFormat = tfMilliseconds; 
int ms = MediaPlayer->Length; 
AnsiString st = "Audio CD. Время звучания: "; 
st = st + IntToStr(MINUTE(ms));
st = st + ":" + IntToStr(SECOND(ms)}; 
Labell->Caption = st; 
MediaPlayer-XTimeFormat = tfTMSF; 
Labell->Visible = true; Track = 0; 
return; 
} 
// дисковод открыт или в дисководе не Audio CD 
if (( MediaPlayer->Mode == mpOpen)|| 
(MediaPlayer->Mode == mpStopped) &&
(MediaPlayer->Tracks == 1))
 { 
Labell->Caption = "Вставьте Audio CD";
 if ( Labell->Visible) 
Labell->Visible = false; else Labell->Visible = true; 
} 
} 
// щелчок на кнопке "следующий трек"
void__fastcall TForml::Button3Click(TObject *Sender) 
{ MediaPlayer->Next(); 
// если перешли к последнему треку, то кнопку Next 
// сделать недоступной 
if ( MCI_TMSF_TRACK(MediaPlayer->
Position) == MediaPlayer->Tracks) 
Button3->Enabled = false; 
if (! Button2->Enabled) Button2->Enabled = true;
 Tracklnfо(); 
Label2->Caption = "0:00"; 
} 
// щелчок на кнопке "предыдущий трек" 
void__fastcall TForml::Button2Click(TObject *Sender) 
{ 
MediaPlayer->Previous(); // в начало текущего трека 
MediaPlayer->Previous(); // в начало предыдущего трека
if ( MCI_TMSF_TRACK(MediaPlayer->Position) == 1)
 Button2->Enabled = false; 
if ( ! Button3->Enabled) Button3->Enabled = true; 
Tracklnfо(); 
Label2->Caption = "0:00"; } 
// пользователь закрыл окно программы 
void __fastcall TForml::FormClose(TObject *Sender, TCloseAction SAction) 
{ 
MediaPlayer->Stop(); 
MediaPlayer->Close(); } 

Содержание раздела