Napište si vlastní effect plugin pro XMMS

(nebo nějaký portujte...)

xmms obrázek


Poznámka: Předpokládá se mírně pokročilá znalost práce se systémem Linux...

Proč plugin?

XMMS je velmi rozšířený přehrávač multimédií, o tom není pochyb. Mezi uživateli tohoto přehrávače se ale určitě najde nejeden, který má potřebu upravit si výstupní zvuk podle sebe, tak jak to zrovna potřebuje. Takovému uživateli nezbude nic jiného, než použít efektový plugin. Má dvě možnosti: internet a napsat si ho sám. První možnost je nejčastější, ale mnoho kvalitních pluginů na internetu není. Druhý způsob je sice náročnější, ale pokud jste dost šikovní a zvuku a jeho zpracování rozumíte, určitě to nebude (zvlášť s tímto návodem) veliký problém. Napsat si svůj plugin ale může zkusit každý, komu se to zdá zajímavé a chce si to vyzkoušet...

Co k tomu potřebujete?

Vlastně nic moc. Stačí mít nainstalováno XMMS a jeho knihovny. Pokud jste si XMMS zkompilovali a nainstalovali sami, s knihovnami nebude problém. Pokud máte XMMS nainstalováno z balíčiků (např. RPM), pak si ověřte, zda je nainstalován i xmms-devel balíček, popřípadě jej doinstalujte. V adresáři s knihovnami (v RedHatu např. /usr/includes/) by měl být adresář XMMS a v něm .h soubry. Pokud by něco nefungovalo, a soubory i adresář existovaly, můžete zkusit tyto soubory nakopírovat do adresáře se zdrojovým kódem.

A teď můžeme začít.

Všechny pluginy jsou ve skutečnosti knihovny. Obsahují funkce a struktury, podle kterých XMMS pozná, o jaký plugin jde (jistě jste postřehli, že jsou efektové, vizualizační, vstupní, výstupní...) a podle toho jej zařadí na správné místo v panelu "Nastavení". XMMS rovněž předpokládá, že se uvnitř nachází některé funkce, které toto rozškatulkování umožní a zprostředkují ovládání a posílání dat, která mají být například nějakým způsobem upravena. Na následujícím velmi jednoduchém pluginu se teď pokusím popsat, jak takový plugin psát.

Zabalený zdrojový kód spolu s knihovnami si můžete stáhnout zde.
Soubor stačí rozbalit a pomocí příkazu make jej zkompilujete.

A teď můžeme začít.

K tomu, aby XMMS věděl, že je v knihovně uložen plugin a že je efektový, slouží dvě části: množina funkcí, které jsou přístupné a funkce vracející odkaz na plugin. V našem jednoduchém pluginu vypadá takto:

/* nutne pro inicializaci v XMMS */
EffectPlugin ep = {
NULL, /* prirazuje XMMS */
NULL, /* prirazuje XMMS */
"Stereo Plugin (ChipCD)", /* popis v dialogu Nastaveni */
init, /* fukce volana pri startu */
cleanup, /* funkce volana pri ukoncovani */
about, /* funkce volana pri stisku tlac. O Pluginu */
configure, /* funkce volana pri stisku tlac. Konfigurovat */
mod_samples, /* funkce provadejici upravu vystupniho zvuku */
NULL
};

/* funkce vracejici odkaz na plugin */
EffectPlugin *get_eplugin_info(void){
return &ep;
}

Pokud nějakou funkci náš plugin mít nebude (například configure), napíšeme do seznamu na příslušné místo NULL. Ještě před výše uvedený kód napíšeme deklarace funkcí, které v seznamu budou obsaženy, v případě našeho pluginu:

/* definice funkci */
static void init(void);
static void cleanup(void);
static void about(void);
static void configure(void);
static int mod_samples(gpointer *d, gint length, AFormat afmt, gint srate, gint nch);

Nyní se přistoupí k napsání výše uvedených funkcí. To, zda budou v pluginu obsaženy všechny, záleží na nás (a na tom, co je napsáno v seznamu výše). Následuje kód funkcí, které jsou v našem jednoduchém pluginu:

static void about(void){
/* vypise info o pluginu po stisknuti */
/* tlacitka "O Pluginu" v XMMS */
printf("Stereo plugin (ChipCD): Pokusny plugin rubriky Linux z ChipCD :-)\n");
}

static void init(void){
/* pri nacteni pluginu do XMMS se provede tato funkce */
hodnota = 0.0;
stav = 0;
printf("Stereo plugin (ChipCD): XMMS me inicializovalo hodnotami 0.0(hodnota) a 0(stav).\n");
}

static void cleanup(void){
/* Pri vypnuti (korektnim) se provede tato funkce */
printf("Stereo plugin (ChipCD): XMMS konci, ja koncim taky.\n");
}

static void configure(void){
/* Pri stisknuti "Konfigurovat" se provede tato funkce */
/* Tato konkretni fce: hloupa rotace stavu */
stav++;
if(stav==1){ /* mono */
hodnota=1.0;
printf("Stereo plugin (ChipCD): Nastavuji MONO.\n");
}
if(stav==2){ /* stereo 2.0 */
hodnota=2.0;
printf("Stereo plugin (ChipCD): Nastavuji STEREO(2).\n");
}
if(stav==3){ /* stereo 2.5 */
hodnota=2.5;
printf("Stereo plugin (ChipCD): Nastavuji STEREO(2.5).\n");
stav=0; /* stav zpatky na zacatku */
}
}

Nyní následuje ta nejdůležitější funkce, tedy ta, která modifikuje výstupní data a způsobí tím efekty. V parametrech je ukazatel na data, jejich délku, formát dat aj. a vrací délku pole dat. Data jsou uložena ve formě pole, přičemž prvky na liché/sudé pozici odpovídají příslušné straně (levá/pravá) při stereu. POZOR! Tato funkce musí vracet déllku dat (length) VŽDY!
Funkce ukázkového pluginu je poměrně jednoduchá: Pokud se udělá průměr, získáme mono. Pokud z původní hodnoty (lichého i sudého) odečteme průměr, získaný rozdíl (pro sudé i liché prvky zvlášť) je jednoduše řečeno to, co dělá stereo. Pokud tedy tento rozdíl k průměru přičteme (pro sudé i liché prvky), získáme původní stereo. Pokud rozdíl před přičtením násobíme a teprve pak přičteme, efekt sterea se zvětší. Více pochopíte určitě při pohledu na zdrojový kód našeho jednoduchého pluginu:

/* funkce slouzici k uprave reprodukovane hudby */
static int mod_samples(gpointer *d, gint length, AFormat afmt, gint srate, gint nch)
{
gint i;
double prumer, ldif, rdif, tmp, nasobek;
gint16 *data = (gint16 *)*d;

/* urceni formatu cisel - technicka vec - doporucuji */
if (!(afmt == FMT_S16_NE ||
(afmt == FMT_S16_LE && G_BYTE_ORDER == G_LITTLE_ENDIAN) ||
(afmt == FMT_S16_BE && G_BYTE_ORDER == G_BIG_ENDIAN)) ||
nch != 2)
return length;

nasobek = hodnota;

for (i = 0; i < length / 2; i += 2)
{
prumer = (data[i] + data[i + 1]) / 2;
ldif = data[i] - prumer;
rdif = data[i + 1] - prumer;

/* osetreni, zda hodnota neni prilis vysoka - pokud se neprovede */
/* XMMS muze spadnout - DOPORUCUJI */
tmp = prumer + (ldif * nasobek);
if (tmp < -32768)
tmp = -32768;
if (tmp > 32767)
tmp = 32767;
data[i] = tmp;

tmp = prumer + (rdif * nasobek);
if (tmp < -32768)
tmp = -32768;
if (tmp > 32767)
tmp = 32767;
data[i + 1] = tmp;
}
return length;
}

Pak už stačí jen plugin zkompilovat a soubor typu .so nahrát třeba do složky /home/XYZ/.xmms/Plugins (za XYZ si dosaďte Váš domovský adresář) a spustit XMMS.
Pokud budete chtít zkompilovat a vyzkoušet ukázkový plugin , doporučuji pustit XMMS v terminálu. Plugin totiž nepoužívá okna ale funkci printf(), jak jste si jistě všimli. Postup je poměrně jednoduchý: Rozbalit archiv, napsat make, a pak už stačí jen zkompilovaný plugin (.so soubor) ...