OpenGL (12.) - visualizační plugin pro WinAMP
Pokud jste již někdy viděli jakýkoliv vizualizační plugin pro WinAMP, určitě vám vrtalo hlavou, jak takový plugin vytvořit. V praxi se nejedná o nic jiného než obyčejnou dynamickou knihovnu, ze které si WinAMP bude volat potřebné funkce.
Oficiální stránky jsou na adrese www.winamp.com/nsdn/winamp2x/dev/plugins, kde jsou i příklady v céčku.
První věc, kterou musíte udělat je vytvořit dynamickou knihovnu (File - New - Other... - DLL Wizard). Doporučuji název projektu vis_cokoliv, protože nový WinAMP3beta načte jen knihovny začínající na vis_. WinAMP očekává od DLL exportaci hlavičky:
library vis_plugin_DEMO;
uses
Windows,
GLplugin in 'GLplugin.pas',
setup in 'Setup.pas' {Form1};
{$R *.RES}
exports winampVisGetHeader;
end.
![]() |
Formulář setup slouží k nastavení pluginu (rozlišení, fullscreen, reakce na špičky, ...), v GLplugin.pas jsou uloženy všechny potřebné funkce. Potom do unity obsahující zbytek zdrojáku musíme přidat strukturu dat:
unit GLplugin;
interface
uses Windows, Messages, OpenGL, setup;
type
PWinampVisModule = ^TwinampVisModule;
TwinampVisModule = record
description : PChar;
hwndParent : HWND;
hDllInstance: HINST;
sRate : Cardinal;
nCh : Cardinal;
latencyMs : Cardinal;
delayMs : Cardinal;
spectrumNCh : Cardinal;
waveformNCh : Cardinal;
spectrumData: Array [0..1, 0..575] of Byte;
waveformData: Array [0..1, 0..575] of Byte;
Config : procedure(const PVisModule:PwinampVisModule);cdecl;
Init : function(const PVisModule:PwinampVisModule):Integer;cdecl;
Render : function(const PVisModule:PwinampVisModule):Integer;cdecl;
Quit : procedure(const PVisModule:PwinampVisModule);cdecl;
userData : procedure; cdecl;
end;
PwinampVisHeader = ^TwinampVisHeader;
TwinampVisHeader = record
version : Integer;
description : PChar;
getModule : function (Which : Integer) : PwinampVisModule; cdecl;
end;
Pak je ještě nutné deklarovat hlavičky funkcí volaných WinAMPem:
function GetModule(Which :integer) :PWinAMPVisModule; cdecl; procedure Config(const PVisModule : PWinAMPVisModule); cdecl; function Init(const PVisModule : PWinAMPVisModule) : integer; cdecl; function Render(const PVisModule : PWinAMPVisModule) :integer; cdecl; procedure Quit(const PVisModule : PWinAMPVisModule); cdecl; function winampVisGetHeader : PwinampVisHeader; cdecl; export;
Proměnné a konstanty:
implementation uses IniFiles; const WND_TITLE = 'Spektrální analyzér v OpenGL'; var h_Wnd : HWND; h_DC : HDC; h_RC : HGLRC; keys : Array[0..255] of Boolean; //Stisknuté klávesy Active : Boolean = FALSE; PluginStart : DWord; ElapsedTime : DWord; //Čas uplynutý mezi snímky Mode, Modul: integer; AppFullScreen : Boolean; EnableBeat : Boolean; BounceBeat : Boolean; VUBars : Array[0..17, 1..17] of GLFloat;
A teď nejdůležítější věc. Funkce, které si WinAMP bude z naší knihovny volat:
function WinAMPVisGetHeader :PWinAMPVisHeader; begin Result := @HDR; end;
Touto funkcí si WinAMP vycucne hlavičku našeho pluginu. Každý plugin může obsahovat víc modulů. WinAMP vybere ten pravý funkcí GetModule, která vrací ukazatel na VisModul:
function GetModule(Which : integer) : PwinampVisModule;
begin
if which = 0 then
Result := @VisModule
else
Result := nil;
end;
Procedura Config je volána, klikne-li uživatel na tlačítko Config při výběru pluginu. Je zobrazen formulář s konfigurací - rozlišení, fullscreen atd. Tyto hodnoty mohou být uchovány v souboru winamp.ini, který je v adresáři winamp/plugins.
procedure Config(const PVisModule : PWinAMPVisModule);
begin
Form1 :=TForm1.Create(nil);
try
Form1.ShowModal;
finally
Form1.Free;
end;
end;
Inicializační funkce načítá při spuštění pluginu hodnoty z winamp.ini souboru. Všechny globální proměnné by měli být inicializovány zde v této funkci. Zároveň jsem vytvořil glWindow a inicializoval OpenGL:
function Init(const PVisModule :PWinAMPVisModule) :integer;
var Width, Height : Integer;
PluginIni : TIniFile;
Path : String;
P : Integer;
begin
Path :=ParamStr(0); //vrátí např. 'c:\program files\winamp\winamp.exe'
P :=Length(Path);
while Path[P] <> '\' do Dec(P);
Path :=Copy(Path, 1, P);
Path :=Path + 'Plugins\';
PluginIni := TIniFile.Create(Path + 'plugin.ini');
//Načteme nastavení okna
Width :=PluginIni.ReadInteger('WinAmpPlugin', 'Width', 800);
Height:=PluginIni.ReadInteger('WinAmpPlugin', 'Height', 600);
AppFullScreen :=PluginIni.ReadBool('WinAmpPlugin', 'FullScreen', FALSE);
//Načteme vlastnosti
EnableBeat :=PluginIni.ReadBool('WinAmpPlugin', 'BackgroundBeat', TRUE);
BounceBeat :=PluginIni.ReadBool('WinAmpPlugin', 'BounceBeat', FALSE);
PluginIni.Free;
if not glCreateWnd(PVisModule, Width, Height, 32, AppFullScreen) then
begin
glKillWnd(PVisModule, AppFullScreen);
Result := 1; //Jestli se okno nevytvořilo, ukončíme to
exit;
end;
PluginStart := GetTickCount(); //Získání času při startu
Result := 0;
Active :=TRUE;
end;
![]() |
Funkce Render je hlavní funkce, ve které se děje to nejdůležitější. Jak často je funkce volána závisí na hodnotě DelayMS ve VisModule. Hodnota 25 znamená, že je funkce volána každých 25 ms. Zde by se měla renderovat scéna a testovat stisknuté klávesy. Nejdůležitější je tedy volání procedury glDraw, která se postará o vykreslení celé scény:
function Render(const PVisModule : PWinAMPVisModule) : Integer;
var LastTime : DWord;
begin
if Active then
begin
LastTime :=ElapsedTime;
ElapsedTime :=GetTickCount() - PluginStart; //Spočítá uplynutý čas
ElapsedTime :=(LastTime + ElapsedTime) DIV 2;
glDraw(PVisModule); //Vykreslí scénu
SwapBuffers(h_DC); //Zobrazí scénu
if (keys[VK_ESCAPE]) then //reakce na ESC
begin
Active :=FALSE;
PostQuitMessage(0);
Result :=1;
exit;
end
else
ProcessKeys(PVisModule); //Vyhodnotí ostatní klávesy
end;
Result :=0;
end;
A nakonec by měl WinAMP uzavřít okno funkcí close:
procedure Quit(const PVisModule : PWinAMPVisModule); begin glKillWnd(PVisModule, AppFullScreen); end;
Toto byly jen ty nejdůležitější funkce a procedury. Všechny ostatní už závisí na každé implementaci vlastního pluginu. Pro názornost uvedu ještě funkci glDraw, ze které je možno pochopit, jakým způsobem je možno vykreslit spektrální analyzér s pamětí 18 kroků:
procedure glDraw(const PVisModule : PWinAMPVisModule);
var
BackgroundBeat : GLFloat;
Beat : GLFloat;
X, Y, i : integer;
begin
//Získání velikosti špičky
BackGroundBeat :=0;
For i:=0 to 9 do
BackGroundBeat := BackgroundBeat +
PVisModule^.spectrumData[0][i] +
PVisModule^.spectrumData[1][i];
BackgroundBeat :=BackgroundBeat /10 /255 ;
if EnableBeat then
begin
//reakce na špičku
end else begin
//reakce, když není povolena reakce na špičku
end;
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0, -5.0, -50);
glRotate(30, 1, 0, 0 );
//rotace celého analyzéru
//glRotate(ElapsedTime/100, 0, 1, 0);
// Posunutí sloupců o jeden dozadu
for Y := 16 downto 1 do
for X :=0 to 17 do
VUBars[X, Y+1] :=VUBars[X, Y];
// Vynulování první řady
for X :=0 to 17 do VUBars[X, 1] :=0;
// Zprůměrovaní 288 sloupců získaných z winampu do 18.
for X :=0 to 287 do
VUBars[X DIV 16, 1] := VUBars[X DIV 16, 1] +
PVisModule^.spectrumData[0][X]{left} +
PVisModule^.spectrumData[1,X]{right};
// Omezení špiček
for X :=0 to 17 do
begin
VUBars[X, 1] :=VUBars[X, 1]/51/2;
if VUBars[X, 1] > 15 then
VUBars[X, 1] :=15;
end;
// Je-li povolena špička, analyzátor poskočí...
if BounceBeat then Beat :=BackGroundBeat
else Beat :=0;
if (modul=0) then begin
for Y := 1 to 17 do
for X :=1 to 17 do ModulVUBox(X, Y, Beat, VUBars[X,Y]);
end else if (modul=1) then begin ModulPlocha();
end;
end;
Zbytek funkcí (Vytvoření okna, hlídání a reakce na stisknuté klávesy, vykreslení sloupce nebo plochy atd.) je možno shlédnout ve staženém zdrojáku zde (21kB). Ovládání F2 - změna módu, F3 - změna modulu, šipka nahoru/dolů - hlasitost, šipka vlevo/vpravo - předešlá/další skladba. Změna modulu spočívá ve změně způsobu vykreslování analyzéru. Ten může být buď sloupcový nebo plošný.
Vyšlo 20.05.2002, v blogu: 0 1 2 3 4 5 6 7 8
Děkuji, že jste se rozhodl(a) přečíst tento článek. Budu rád i za komentář. Pokud Vás tento článek zaujal a rádi byste jej doporučili ostatním, podpořte mně prosím tím, že věnujete minutku svého času a uděláte mi reklamu na linkuj.cz, vybrali.sme.sk či jagg.cz. Přeji příjemné čtení
Poslední články
- OpenGL (16.) - Fading
- Herní grafické enginy (3.) - GLScene
- Herní grafické enginy (2.) - Pythian Project
- OpenGL (15.) - Ucelený částicový systém - pokračování
- OpenGL (14.) - Ucelený částicový systém
- OpenGL (13.) - Nastavení OpenGL v jazyce C/C++
- 3D Studio MAX (13.) - Popis modifikačních funkcí ve 3D Studiu MAX
- OpenGL (12.) - visualizační plugin pro WinAMP
- Delphi (10.) - knihovna FMOD
- Herní grafické enginy (1.) - MEngine od Mister Group
- Delphi (9.) - Download 2
- Delphi (8.) - Download
- 3D Studio MAX (12.) - Tvorba realistické jeskyně 2
- Jak na tvorbu her - Na co máme myslet při programování hry?
- 3D Studio MAX (10.) - Izometrický pohled ve 3D Studiu MAX

