Windows все свое рабочее время (в промежутках между зависаниями) занимается тем, что рассылает и принимает сообщения. Например, изменил пользователь разрешение экрана, Windows тут же сообщает эту новость всем окнам (извините за тавтологию), мол, пора бы и перерисоваться. Разумеется, каждая программа может реагировать на любое сообщение по-своему. Многие приложения определяют для себя некоторые специфичные команды, которые зачастую бывают просто необходимы. Возьмем, к примеру, Microsoft Word. У него есть главное внешнее окно, внутри которого располагаются дочерние окна, в которых открываются документы. Предположим, пользователь запустил Word и редактирует какой-нибудь документ. И вдруг он где-то в "Проводнике" увидел еще один файл, который ему срочно нужно редактировать в том же Word. Юзер два раза кликает по файлу, и опять запускается Word. Word-копия проверяет, единственный ли он и неповторимый, или уже есть его запущенный собрат. Если есть, то он посылает некое сообщение оригиналу и благополучно закрывается. Word-оригинал ловит это сообщение и из него узнает, что нужно открыть такой-то файл, и открывает его, а пользователь даже и не заметил, что Word запускался второй раз. Winamp поддерживает ряд нестандартных сообщений. Благодаря этим сообщениям существует огромное количество плагинов к нему и программ, которые умеют управлять Winamp'ом.
Чтобы послать Winamp'у какое-либо сообщение, нужно прежде всего определить идентификатор его окна. Делается это при помощи WinApi-функции:
FindWindow(lpClassName, lpWindowName: PChar): HWND;
(здесь и далее используется синтаксис Object Pascal);
lpClassName - название класса искомого окна;
lpWindowName - заголовок искомого окна.
Для посылки сообщения используется еще одна WinApi-функция:
SendMessage(hWnd:HWND;Msg:UINT;wParam:WPARAM;lParam:LPARAM):LRESULT;
hWnd - идентификатор окна, которому посылается сообщение;
Msg - посылаемое сообщение;
wParam - первый параметр сообщения;
lParam - второй параметр сообщения.
Winamp поддерживает два основных типа сообщения (параметр Msg):
- WM_COMMAND: служит только для подачи определенных команд Winamp'у (Play, Stop, Next, Close и т.д.);
- WM_USER: используется не только для выполнения действий, но и для определения различной информации (версия, текущая композиция, количество композиций и т.д.).
В таблице 1 приведены основные константы для первого параметра сообщения WM_COMMAND.
Команда | Описание команды |
40044 | Кнопка «Prev» |
40048 | Кнопка «Next» |
40045 | Кнопка «Play» |
40046 | Кнопка «Pause» |
40047 | Кнопка «Stop» |
40157 | Остановиться после текущей композиции |
40148 | На 5 секунд вперед |
40144 | На 5 секунд назад |
40154 | Перейти на первую песню Playlist’а (режим «Suffle» — случайное проигрывание - должен быть отключен) |
40158 | Перейти на последнюю песню Playlist’а (режим «Suffle» должен быть отключен) |
40192 | Запустить плагин визуализации |
40036 | Показать/Спрятать эквалайзер |
40040 | Показать/Спрятать редактор Playlist’ов |
40258 | Показать/Спрятать главное окно |
40298 | Показать/Спрятать мини-браузер |
40022 | Кнопка «Repeat» |
40023 | Кнопка «Suffle» |
40188 | Показать информацию о файле |
40058 | Увеличить громкость на один процент |
40059 | Уменьшить громкость на один процент |
40001 | Закрыть Winamp |
Для их использования можно применять процедуру:
Procedure WinampCommand(Command:Integer); var WinampHWND:HWND; begin //поиск окна Winamp'a WinampHWND:=findwindow('Winamp v1.x',nil); //если поиск успешен, то посылаем сообщение if WinampHWND<>0 then SendMessage(WinampHWND, WM_Сommand, Command, 0); end;
Теперь для подачи сообщения типа WM_COMMAND нужно выбрать из таблицы понравившуюся константу и передать ее в качестве параметра процедуре WinampCommand. Пример:
WinampCommand(40044); - переход к предыдущей композиции.
В таблице 2 перечислены основные константы для сообщений WM_USER.
Id | Data | Пояснения |
0 | 0 | Возвращает версию Winamp’а |
102 | 0 | Начать проигрывать выбранную в playlist’е композицию |
104 | 0 | Возвращает статус проигрывания: 1 — играет, 3 — пауза, иначе остановлен |
105 | 0 | Возвращает в миллисекундах позицию проигрывания |
105 | 1 | Возвращает в секундах длину композиции |
121 | n | Выбирает в playlist’e композицию под номером n |
122 | n | Устанавливает громкость в значение n (от 0 до 255) |
123 | n | Устанавливает баланс в значение n (от 0 до 255) |
125 | 0 | Возвращает позицию текущей песни в playlist’е |
126 | 0 | Возвращает samplerate (частоту дискретизации) |
126 | 1 | Возвращает bitrate (скорость передачи информации) |
126 | 2 | Возвращает количество каналов (1 — моно, 2 — стерео) |
135 | 0 | Перезагружает Winamp (например, для подключения нового плагина) |
Для их использования запишите следующую функцию:
Function WinampUser(data:Integer, id:Integer):integer; var WinampHWND:HWND; begin WinampHWND:=findwindow ('Winamp v1.x', nil); if WinampHWND<>0 then result:=SendMessage (WinampHWND,WM_USER,data, id) else result:=-1; end;
Пример:
WinampUser(1, 105); - возвращает длину текущей композиции в секундах.
Управлять Winamp'ом мы уже научились, это умение пригодится для написания плагинов к нему.
Плагины к Winamp'у бывают пяти видов:
- Input - плагины для проигрывания различных форматов;
- Output - для записи музыки в различных форматах;
- General Purpose - плагины общего назначения, в них наиболее часто используются сообщения, которые мы рассмотрели выше;
- DSP/Effect - для обработки звука;
- Visualization - плагины, которые делают что-нибудь в такт музыке.
На сайте www.winamp.com можно скачать шаблоны всех типов плагинов. Для примера рассмотрим маленький визуализационный плагин, который заставит мигать лампочки Num Lock, Caps Lock и Scroll Lock в такт музыке. Для этого воспользуемся соответствующим шаблоном (vis_minisdk). В нем присутствует функция Render, которая через заданный промежуток времени получает от Winamp'a информацию о текущих уровнях частот проигрываемой музыки. Остается только написать обработчик этих данных:
{Если плагин пишется не на C, то не следует забывать, что параметры процедур должны передаваться так же, как в этом языке. Поэтому в данном случае нужно использовать служебное слово cdecl (c-declaration)}
function Render(this_mod: PwinampVisModule): integer;cdecl; //внутренняя процедура, которая будет гасить\зажигать нужные лампочки Procedure SetLock(n, state:byte); var KS: TKeyboardState; c: byte; begin //смотрим, с какой лампочкой будем работать case n of 0: c:=VK_NUMLOCK; 1: c:=VK_CAPITAL; 2: c:=VK_SCROLL; end; //в зависимости от параметра state, зажигаем либо гасим лампочку GetKeyboardState(KS); KS[c]:=state; SetKeyboardstate(KS); end; var i:byte; begin //в зависимости от уровня звука, гасим\зажигаем //соответствующие лампочки for i:=0 to 2 do if this_mod.spectrumData [0,i]>40 then SetLock(i, 1) else SetLock(i, 0); result:=0; end;
Весь исходный код и готовый плагин можно найти на странице www.IvanFDC.narod.ru/download.html. Хочу отметить, что данный плагин управляет только состоянием лампочек, а сами клавиши не трогает. Поэтому при использовании плагина можно набирать текст безо всяких проблем.
Как видим, всю работу по обработке звука Winamp берет на себя, поэтому создавать плагины к этому популярнейшему плееру может даже человек, весьма далекий от музыки.
Иван ШИРКО,
FDC@tut.by
Комментарии