(плагины + исходники на Delphi)
Работать с плеером Winamp мы научились в статье Управление Winamp. Теперь перейдем к разработке плагинов для него.
Плагины к Winamp бывают пяти видов:
- Input – плагины для проигрывания различных форматов;
- Output – для записи музыки в различных форматах;
- General Purpose – плагины общего назначения;
- DSP/Effect – для обработки звука;
- Visualization – плагины, которые делают что-нибудь в такт музыке.
Плагин к Winamp представляет из себя обычную динамическую библиотеку (DLL – Dynamic Link Library), которая должна экспортировать необходимую для данного плагина информацию. Шаблон библиотеки для любого типа плагинов можно взять на сайте Winamp’a – http://www.winamp.com. В этой статье мы рассмотрим процесс создания самого впечатляющего, на мой взгляд, типа плагинов – визуализационного.
В составе визуализационного плагина можно выделить заголовок и модули. Вот формат этих частей:
Заголовок плагина
winampVisHeader = packed record
version: Integer;
description: PChar;
getModule: function( which: integer ): PwinampVisModule; cdecl;
end;
version – версия, для данного типа плагинов должна быть равна $101 (знак ‘$’ указывает на шестнадцатеричную систему счисления).
description – описание плагина.
getModule – функция, которая должна возвратить указатель на тело плагина.
Модуль плагина
winampVisModule = packed record
//описание модуля
description: PChar;
//идентификатор окна Winamp'a (заполняет Winamp)
hwndParent: HWND;
// идентификатор библиотеки (заполняет Winamp)
hDllInstance: HWND;
//sample rate (заполняет Winamp)
sRate: Integer;
//количество каналов (заполняет Winamp)
nCh: Integer;
//задержка между получением данных от Winamp'a и
//реакцией на них (в мс)
latencyMs: Integer;
//количество мс между получениями данных от Winamp'a
delayMs: Integer;
//следующие 4 параметра и есть те данные о звуке, которые мы
//будем через некоторый промежуток времени получать от Winamp'a
spectrumNch: Integer;
waveformNch: Integer;
spectrumData: array[0..1, 0..575] of byte;
waveformData: array[0..1, 0..575] of byte;
//процедура, которая будет вызываться при нажатии на кнопку "Конфигурация"
Config: procedure( thismod: PwinampVisModule ); cdecl;
//функция, вызываемая при инициализации плагина, должна возвратить 0, если всё в порядке
Init: function( thismod: PwinampVisModule ): integer; cdecl;
//функция, вызываемая при получении очередной порции данных
//от Winamp'a, именно здесь нужно реагировать на изменение
//музыкальных данных, должна возвратить 0, если всё в порядке,
// или 1, если плагин завершает свою работу
Render: function( thismod: PwinampVisModule ): Integer; cdecl;
//процедура, вызываемая при завершении работы плагина
Quit: procedure( thismod: PwinampVisModule ); cdecl;
//здесь можно хранить указатель на свои данные
userData: pointer;
end;
Ну а теперь сделаем простой и абсолютно бесполезный визуализационный плагин, маленький анализатор спектра. Создайте в Delphi DLL. После этого создайте форму и положите на неё шесть компонентов TProgressBar, для которых свойство Orientation установите в положение pbVertical, а Max – в 300. Пример расположения компонент можете посмотреть на рис.1.
Всё, форму можно больше не трогать, займёмся теперь DLL. Вот код библиотеки:
library vis_MyFirstPlug;
uses
Windows, forms,
Unit1 in 'Unit1.pas' {Form1};
const
//версия
VIS_HDRVER = $101;
//класс окна
szAppName = 'OurPlug';
//описание плагина
descr = 'Мой первый VIS плагин';
//описание модуля
mod1_descr = 'А это единственный модуль моего плагина';
type
//типы заголовка и тела плагина
PwinampVisModule = ^winampVisModule;
winampVisModule = packed record
description: PChar;
hwndParent: HWND;
hDllInstance: HWND;
sRate: integer;
nCh: integer;
latencyMs: integer;
delayMs: integer;
spectrumNch: integer;
waveformNch: integer;
spectrumData: array[0..1,0..575] of byte;
waveformData: array[0..1,0..575] of byte;
Config: procedure(thismod: PwinampVisModule);cdecl;
Init: function(thismod: PwinampVisModule): integer;cdecl;
Render: function(thismod: PwinampVisModule): integer;cdecl;
Quit: procedure(thismod: PwinampVisModule);cdecl;
userData: pointer;
end;
PwinampVisHeader = ^winampVisHeader;
winampVisHeader = packed record
version: integer;
description: PChar;
getModule: function( which : integer ) : PwinampVisModule; cdecl;
end;
var
//заголовок плагина
hdr: winampVisHeader;
//модуль плагина
mod1: winampVisModule;
//далее следуют процедуры, назначение которых описано выше
function getModule(which: integer): PwinampVisModule;cdecl;
begin
case which of
0: result := @mod1;
else
result := nil
end;
end;
function winampVisGetHeader: PwinampVisHeader; cdecl;
begin
result := @hdr;
end;
procedure config(this_mod: PwinampVisModule); cdecl;
begin
MessageBox(mod1.hwndParent, 'Настроек нет', 'Окно настроек', mb_OK);
end;
function init(this_mod: PwinampVisModule): integer; cdecl;
begin
//показываем форму с ProgressBar'ами
Form1.Show;
result := 0;
end;
function render(this_mod: PwinampVisModule): integer; cdecl;
begin
//при поступлении новых данных от Winamp'a устанавливаем
//высоту столбиков ProgressBar'ов в соответствии со значением
//музыкальных данных шести колонок
Form1.ProgressBar1.Position := this_mod.spectrumData[0,1];
Form1.ProgressBar2.Position := this_mod.spectrumData[0,2];
Form1.ProgressBar3.Position := this_mod.spectrumData[0,3];
Form1.ProgressBar4.Position := this_mod.spectrumData[0,4];
Form1.ProgressBar5.Position := this_mod.spectrumData[0,5];
Form1.ProgressBar6.Position := this_mod.spectrumData[0,6];
result := 0;
end;procedure quit(this_mod: PwinampVisModule); cdecl;
begin
end;
//экспортируемая функция
exports
winampVisGetHeader;begin
//заполняем начальные параметры плагина
hdr.version := VIS_HDRVER;
hdr.description := PChar(descr);
hdr.getModule := @getModule;
mod1.description := PChar(mod1_descr);
mod1.hwndParent := 0;
mod1.hDllInstance := 0;
mod1.sRate := 0;
mod1.nCh := 0;
mod1.latencyMs := 25;
mod1.delayMs := 100;
mod1.spectrumNch := 2;
mod1.waveformNch := 0;
mod1.Config := @config;
mod1.Init := @init;
mod1.Render := @render;
mod1.Quit := @quit;
//создаём форму с ProgressBar'ами
Application.CreateForm(TForm1, Form1);
end.
Полученный плагин нужно скопировать в папку Winamp\Plugins. После этого в окне свойств Winamp’a будет доступен новый плагин (рис.2).
Этот пример призван продемонстрировать, как использовать всю мощь VCL в Delphi при создании плагинов для Winamp’a. Но размер такого плагина будет в районе 300-400 кб (зависит от версии Delphi). В связи с этим, лучше отказаться от использования VCL, а писать плагины на WinApi. Далее приведён код плагина, который заставляет мигать лампочки на клавиатуре (Num Lock, Caps Lock и Scroll Lock) в такт музыке.
library KeybLight;
uses Windows;
const
VIS_HDRVER = $101;
szAppName = 'KeybLight';
descr = 'Лампочки на клавиатуре (zavsoft.ru)'; //описание плагина
mod1_descr = 'Лампочки на клавиатуре';
type
//указатель на структуру плагина
PwinampVisModule = ^winampVisModule;
//структура плагина
winampVisModule = packed record
description: PChar;
hwndParent: HWND;
hDllInstance: HWND;
sRate: Integer;
nCh: Integer;
latencyMs: Integer;
delayMs: Integer;
spectrumNch: Integer;
waveformNch: Integer;
spectrumData: array[0..1, 0..575] of Byte;
waveformData: array[0..1, 0..575] of Byte;
Config: procedure( thismod: PwinampVisModule ); cdecl;
Init: function( thismod: PwinampVisModule ): Integer; cdecl;
Render: function( thismod: PwinampVisModule ): Integer; cdecl;
Quit: procedure( thismod: PwinampVisModule ); cdecl;
userData: pointer;
end;
//заголовок плагина
PwinampVisHeader = ^winampVisHeader;
winampVisHeader = packed record
version: Integer;
description: PChar;
getModule: function( which: integer ): PwinampVisModule; cdecl;
end;
var
hdr: winampVisHeader;
mod1: winampVisModule;
//процедура для установки состояния клавиш Caps, Num, Scroll Lock
procedure SetLock(N: Byte; State: Boolean);
var
KeyState: TKeyboardState;
c: Byte;
begin
case N of
0: c := VK_NUMLOCK;
1: c := VK_CAPITAL;
2: c := VK_SCROLL;
end;
GetKeyboardState(KeyState);
if (State and (not((KeyState[c] and 1) = 1)) or ((not State) and ((KeyState[c] and 1) = 1))) then
//key press
keybd_event(c, $45, (KEYEVENTF_EXTENDEDKEY or 0), 0);
//key release
keybd_event( c, $45, (KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP), 0);
end;
//возвращает указатель на нужный модуль
function getModule(which: integer): PwinampVisModule; cdecl;
begin
case which of
0: result := @mod1;
else result := nil
end;
end;
//передача заголовка плагина Winamp'у
function winampVisGetHeader: PwinampVisHeader; cdecl;
begin
result := @hdr;
end;
//эта процедура вызывается при нажатии на кнопку "Конфигурация"
procedure config( this_mod: PwinampVisModule ); cdecl;
begin
MessageBox(this_mod.hwndParent, 'Автор Иван Ширко (ishyrko@gmail.com)'+#13+' https://zavsoft.ru', 'Лампочки на клавиатуре', MB_OK)
end;
//инициализация плагина, если всё нормально, то должны вернуть 0
function init( this_mod: PwinampVisModule ): integer; cdecl;
begin
result:=0;
end;
//именно эта функция заставляет лампочки мигать
function render(this_mod: PwinampVisModule): integer; cdecl;
begin
//в зависимости от уровня звука гасим\зажигаем
//соответствующие лампочки if (this_mod.spectrumData[0,1] > 40) then
SetLock(0, True)
else
SetLock(0, False);
if (this_mod.spectrumData[0,5] > 40) then
SetLock(1, True)
else
SetLock(1, False);
if (this_mod.spectrumData[0,10] > 40) then
SetLock(2, True)
else
SetLock(2, False);
result := 0;
end;
//наши действия при закрытии плагина
procedure quit( this_mod: PwinampVisModule ); cdecl;
begin
end;
//экспортируемая функция
exports
winampVisGetHeader;begin
//задаём начальные значения для структуры плагина
hdr.version := VIS_HDRVER;
hdr.description := PChar(descr);
hdr.getModule := @getModule;
mod1.description := PChar(mod1_descr);
mod1.hwndParent := 0;
mod1.hDllInstance := 0;
mod1.sRate := 0;
mod1.nCh := 0;
mod1.latencyMs := 25;
mod1.delayMs := 25;
mod1.spectrumNch := 2;
mod1.waveformNch := 0;
mod1.Config := @config;
mod1.Init := @init;
mod1.Render := @render;
mod1.Quit := @quit;
end.
После компиляции в Delphi такой плагин занимает менее 20 килобайт!
Готовую библиотеку и исходные тексты можно найти на форуме. К сожалению, мне не удалось найти вариант зажигания лампочек под WinXP без изменения состояния клавиш, так что печатать при включенном таком плагине будет проблематично. Но в качестве примера сгодится:)
Как видите, всю работу по обработке звука Winamp берёт на себя, поэтому создавать плагины к этому популярнейшему плееру может даже человек, весьма далёкий от музыки. В следующий раз мы поговорим о плагинах общего назначения.
kRUTO!!! aftoru respeKt!!! DAVNO ISkaL TAKoE
Спасибо за модули. В выходные попробую разобраться подробнее
Отлично написано
Статья очень пригодилась, все просто и понятно. Огромное спасибо автору!:)
Люблю когда по сути, мне понравилось.
Благодарю, очень полезная вещь
У меня коряво получается, но все равно спасибо.
У меня не вышло(((
Спасибо попробую.
Спасибо большое!!! Одно но : в 2 плагине в коде нужно заменить «********* keybd_event(c, $45, (KEYEVENTF_EXTENDEDKEY or 0), 0); //key release *****» на «********* keybd_event(c, $45, (KEYEVENTF_EXTENDEDKEY or 0), 0) else //key release *****». Иначе просто все лампочки всегда выключаються.
>>Виталий Спасибо!
хм…интересно..спасибо за идею, давненько хотел что-либо подобное попробовать…
Отлично я нашла что искала:)
Класс, получилось спасибо.
Извините, может не по теме, но возможно вы подскажете, как сделать, что бы винамп запускался с моим скином на любом компе (на флешке если принесу и т.д.)… Т.е. сделать свой скин скином по умолчанию…
Полезная информация. Я уже много лет пользуюсь Винампом но никогда не приходило на мысль что с помощью средств среды Delphi можно менять шаблон.