Нельзя сказать, что звуковые возможности аплетов Java чрезмерно велики. Скорее наоборот, они минимальны. Тем не менее, аплеты могут проигрывать звуковые клипы, записанные в файлах формата AU, который пришел из мира компьютеров фирмы Sun.
Сказанное, однако, не означает, что если у вас нет рабочей станции Sun, то вы не сможете озвучить свои аплеты. Во-первых, в сети Internet можно найти много готовых звуковых файлов AU, а во-вторых, там же есть программы для преобразования форматов звуковых файлов. Одну из таких условно-бесплатных программ, которая называется GoldWave, вы можете загрузить с сервера ftp.winsite.com.
Работа со звуковыми файлами во многом напоминает работу с растровыми графическими файлами. Вначале вы должны получить ссылку на интерфейс AudioClip, а затем, пользуясь его методами, вы сможете выполнять проигрывание содержимого этого файла.
Для получения интерфейса AudioClip вы должны воспользоваться одним из двух вариантов метода getAudioClip, определенных в классе Applet:
public AudioClip getAudioClip(URL url): public AudioClip getAudioClip(URL url, String name);
Первый вариант метода предполагает указание адреса URL звукового файла через единственный параметр, второй допускает раздельное указание адреса URL каталога, содержащего файл, и имени файла.
В документации на метод getAudioClip сказано, что этот метод фактически не выполняет загрузку звуковых данных, а только возвращает ссылку на интерфейс AudioClip и немедленно возвращает управление. Загрузка звуковых данных выполняется методами, предназначенными для проигрывания файла.
Однако в книге “The Java Tutorial. Object-Oriented Programming for the Internet”, подготовленной специалистами группы JavaSoft, утверждается, что текущие реализации Java работают по другому: метод getAudioClip возвращает управление только после завершения загрузки звукового файла. Очевидно, вам не стоит полагаться на то, что так будет всегда. В тех случаях, когда нежелательно блокирование работы аплета на время загрузки звукового файла, загрузку и проигрывание следует выполнять в отдельной задаче.
Интерфейс AudioClip определен следующим образом:
public interface java.applet.AudioClip { public abstract void play(); public abstract void loop(); public abstract void stop(); }
Метод play запускает однократное проигрывание звукового файла, которое выполняется от начала файла и до его конца.
Метод loop запускает проигрывание звукового файла в цикле, которое будет продолжаться до тех пор, пока вы не остановите его, вызвав метод stop.
Метод stop, как нетрудно догадаться из его названия, останавливает проигрывание звукового файла, как однократное, так и выполняемое в цикле.
Приложение Audio демонстрирует использование интерфейса AudioClip. В его окне (рис. 5.1) имеются три кнопки с названиями Play, Loop и Stop.
Рис. 5.1. Окно аплета Audio
Сразу после запуска аплета кнопка Stop находится в заблокированном состоянии. Если нажать кнопку Play или Loop, начнется, соответственно, однократное проигрывание или проигрывание в цикле файла с именем kaas.au, распложенного в том же каталоге, что и двоичный файл аплета Audio.
Когда начинается проигрывание звукового файла, кнопка Stop разблокируется, что позволяет остановить проигрывание.
Основной файл исходных текстов приложения приведен в листинге 5.1.
Листинг 5.1. Файл Audio\ Audio.java
// ========================================================= // Проигрывание аудиофайла // // (C) Фролов А.В, 1997 // // E-mail: frolov@glas.apc.org // WWW: http://www.glasnet.ru/~frolov // или // http://www.dials.ccas.ru/frolov // ========================================================= import java.applet.*; import java.awt.*; public class Audio extends Applet { // ------------------------------------------------------- // Поля класса. // Создаются автоматически для всех параметров аплета // ------------------------------------------------------- // Строка для хранения имени аудиофайла private String m_ClipName = "kaas.au"; // ------------------------------------------------------- // Имена параметров // ------------------------------------------------------- // Строка имени параметра private final String PARAM_ClipName = "ClipName"; // Аудиоклип AudioClip auClip; // Кнопка для однократного проигрывания Button btPlay; // Кнопка для проигрывания в цикле Button btLoop; // Кнопка для остановки проигрывания Button btStop; // Флаг проигрывания в цикле boolean fLoopPlay = false; // ------------------------------------------------------- // getAppletInfo // Метод, возвращающей строку информации об аплете // ------------------------------------------------------- public String getAppletInfo() { return "Name: Audio\r\n" + "Author: Alexandr Frolov\r\n" + "E-mail: frolov@glas.apc.org" + "WWW: http://www.glasnet.ru/~frolov" + "Created with Microsoft Visual J++ Version 1.0"; } // ------------------------------------------------------- // getParameterInfo // Метод, возвращающий описание параметров // ------------------------------------------------------- public String[][] getParameterInfo() { String[][] info = { { PARAM_ClipName, "String", "Audioclip filename" }, }; return info; } // ------------------------------------------------------- // init // Вызывается во время инициализации аплета // ------------------------------------------------------- public void init() { // Рабочая переменная для получения параметров String param; // Получение параметров и сохранение // их значений в полях класса // Получение имени аудиофайла param = getParameter(PARAM_ClipName); if (param != null) m_ClipName = param; // Создаем кнопку для однократного проигрывания btPlay = new Button("Play"); // Создаем кнопку для проигрывания в цикле btLoop = new Button("Loop"); // Создаем кнопку для остановки проигрывания btStop = new Button("Stop"); // Блокируем эту кнопку, так как пока еще // проигрывание не запущено btStop.disable(); // Добавляем кнопки в окно аплета add(btPlay); add(btLoop); add(btStop); // Создаем аудиоклип как объект класса AudioClip auClip = Applet.getAudioClip(getCodeBase(), m_ClipName); } // ------------------------------------------------------- // action // Метод вызывается, когда пользователь выполняет // действие над компонентами // ------------------------------------------------------- public boolean action(Event evt, Object obj) { // Ссылка на кнопку, от которой пришло сообщение Button btn; // Проверяем, что событие вызвано кнопкой, а не // другим компонентом if(evt.target instanceof Button) { // Получам ссылку на кнопку, вызвавшую событие btn = (Button)evt.target; // Выполняем ветвление по кнопкам // Нажата кнопка однократного проигрывания if(evt.target.equals(btPlay)) { // Запускаем однократное проигрывание auClip.play(); // Разблокируем кнопку остановки проигрывания btStop.enable(); } // Нажата кнопка проигрывания в цикле else if(evt.target.equals(btLoop)) { // Запускаем проигрывание в цикле auClip.loop(); // Устанавливаем флаг проигрывания в цикле fLoopPlay = true; // Разблокируем кнопку остановки проигрывания btStop.enable(); } // Нажата кнопка остановки проигрывания else if(evt.target.equals(btStop)) { // Останавливаем проигрывание auClip.stop(); // Сбрасываем флаг проигрывания в цикле fLoopPlay = false; // Блокируем кнопку остановки проигрывания btStop.disable(); } // Если событие возникло от неизвестной кнопки, // мы его не обрабатываем else { return false; } // Возвращаем признак того, что мы обработали событие return true; } // Если событие вызвано не кнопкой, // мы его не обрабатываем return false; } // ------------------------------------------------------- // paint // Метод paint, выполняющий рисование в окне аплета // ------------------------------------------------------- public void paint(Graphics g) { // Определяем текущие размеры окна аплета Dimension dimAppWndDimension = size(); // Выбираем в контекст отображения желтый цвет g.setColor(Color.yellow); // Закрашиваем внутреннюю область окна аплета g.fillRect(0, 0, dimAppWndDimension.width - 1, dimAppWndDimension.height - 1); // Выбираем в контекст отображения черный цвет g.setColor(Color.black); // Рисуем рамку вокруг окна аплета g.drawRect(0, 0, dimAppWndDimension.width - 1, dimAppWndDimension.height - 1); } // ------------------------------------------------------- // start // Метод вызывается при первом отображении окна аплета // ------------------------------------------------------- public void start() { // Если установлен флаг проигрывания в цикле, // запускаем такое проигрывание if(fLoopPlay) auClip.loop(); } // ------------------------------------------------------- // stop // Метод вызывается, когда окно аплета исчезает с экрана // ------------------------------------------------------- public void stop() { // Если установлен флаг проигрывания в цикле, // останавливаем проигрывание if(fLoopPlay) auClip.stop(); } }
В листинге 5.2 вы найдете исходный текст документа HTML, созданного автоматически для нашего приложения системой Microsoft Visual J++.
Листинг 5.2. Файл Audio\ Audio.html
<html> <head> <title>Audio</title> </head> <body> <hr> <applet code=Audio.class id=Audio width=320 height=50 > <param name=ClipName value="kaas.au"> </applet> <hr> <a href="Audio.java">The source.</a> </body> </html>
В главном классе аплета определено несколько полей и методов. Рассмотрим эти поля и наиболее важные методы.
В поле m_ClipName хранится имя звукового файла, которое передается через параметр ClipName из документа HTML. По умолчанию для этого параметра используется значение kaas.au.
Строка PARAM_ClipName хранит имя указанного выше параметра.
Ссылка на интерфейс AudioClip хранится в поле auClip:
AudioClip auClip;
Следующие три поля хранят ссылки на кнопки, предназначенные для управления проигрыванием звукового файла:
Button btPlay; Button btLoop; Button btStop;
Поле fLoopPlay типа boolean используется для флага, которым отмечается режим проигрывания звукового файла в цикле.
Метод getParameterInfo возвращает описание единственного параметра нашего аплета, через который передается имя звукового файла.
Сразу после запуска аплета метод init получает значение параметра - имя звукового файла, и если этот параметр задан в документе HTML, записывает полученное имя в поле m_ClipName:
param = getParameter(PARAM_ClipName); if(param != null) m_ClipName = param;
Далее создаются три кнопки, управляющие звучанием аплета:
btPlay = new Button("Play"); btLoop = new Button("Loop"); btStop = new Button("Stop");
Кнопка Stop блокируется, так как на данный момент проигрывание еще не запущено:
btStop.disable();
Для блокирования вызывается метод disable, определенный в классе Button.
Подготовленные таким образом кнопки добавляются в окно аплета:
add(btPlay); add(btLoop); add(btStop);
Напомним, что работа с кнопками и другими органами управления в приложениях Java была нами описана в 30 томе “Библиотеки системного программиста”, который называется “Microsoft Visual J++. Создание приложений на языке Java. Часть 1”.
Последнее, что делает метод init перед тем как возвратить управление, это получение ссылки на интерфейс AudioClip:
auClip = Applet.getAudioClip(getCodeBase(),m_ClipName);
Адрес URL каталога, в котором расположен аплет, определяется с помощью метода getCodeBase, о котором мы говорили в предыдущей главе.
Метод action получает управление, когда пользователь нажимает на одну из кнопок, расположенных в окне аплета. В зависимости от того, какая именно кнопка была нажата, выполняются различные действия.
Если пользователь нажал кнопку Play, вызывается метод play для запуска однократного проигрывания звукового файла:
auClip.play(); btStop.enable();
Сразу после того как проигрывание будет запущено, приложение разблокирует кнопку Stop, предоставляя пользователю возможность прервать звучание.
В том случае, когда пользователь нажал кнопку Loop, вызывается метод loop, запусчкающий проигрывание звукового файла в цикле:
auClip.loop(); fLoopPlay = true; btStop.enable();
После запуска устанавливается флаг fLoopPlay и разблокируется кнопка Stop.
И, наконец, если пользователь нажимает кнопку Stop, выполняется остановка проигрывания методом stop:
auClip.stop(); fLoopPlay = false; btStop.disable();
Флаг fLoopPlay сбрасывается, после чего кнопка Stop блокируется.
Метод start получает управление при первом запуска аплета, а также когда страница документа появляется вновь после того как пользователь временно переходил к просмотру другой страницы.
Наша реализация метода start возобновляет циклическое проигрывание, если оно выполнялось, когда пользователь покинул страницу с аплетом:
if(fLoopPlay) auClip.loop();
Если пользователь запустил проигрывание звукового файла в цикле, а затем перешел к просмотру другой страницы, метод stop останавливает циклическое проигрывание:
if(fLoopPlay) auClip.stop();
Когда пользователь вернется к просмотру нашей страницы, метод start, описанный выше, возобновит проигрывание звукового файла.