Kirjautuminen

Haku

Tehtävät

Opasarkisto: SDL 1.2: Osa 4 - Lisäkirjastot

  1. Osa 1 - Perusteet
  2. Osa 2 - Grafiikka
  3. Osa 3 - Syötteet
  4. Osa 4 - Lisäkirjastot

Kirjoittaja: Heikki (2004).

⚠ Huomio! Tämä opas on vanhentunut. Oppaan sisältöön ei voi enää luottaa. Opas on säilytetty vain sen historiallisen arvon vuoksi. ⚠


Tähän mennessä olemme tutustuneet perus-SDL:n ominaisuuksiin. Vaikka emme olekkaan käyneet niitä mitenkään syvällisesti läpi, kannattaa jo tutustua lisäkirjastoihin, joiden avulla on mahdollista tehdä monia asioita, mihin perus-SDL ei taivu. Tässä oppaassa käsittelemme muutaman yleisesti käytössä olevan SDL:n lisäkirjaston asennusta ja käyttöä.

SDL_gfx

SDL_gfx on SDL:n lisäkirjasto, jolla onnistuu mm. bittikarttojen monipuolinen käsittely ja nk. alkeiskuvioiden (ympyrä, viiva jne.) piirtäminen.

Asennus

SDL_gfx on saatavilla sekä lähdekoodipakettina että RPM-pakettina. Paketit löytyvät SDL_gfx:n koitsivuilta osoitteesta http://www.ferzkopp.net/Software/SDL_gfx-2.00. Ne Linux-käyttäjät, joiden koneeseen on asennettuna RPM-paketinhallintaohjelma, voivat ladata RPM-paketin. Paketit saattavat löytyä myös muiden distrojen (ainakin Debianin ja Gentoon) paketinhallinnasta. Muiden käyttäjien, myös Windowsia käyttävien, on ladattava .tar.gz pakattu lähdekoodipaketti (SDL_gfx-x.x.xx.tar.gz). Linuxissa purkuohjelma on valmiina (tar -xvzf paketinnimi.tar.gz), Windowssia käyttävät voivat purkaa paketin esim. WinRar-nimisellä ohjelmalla.

Lähdekoodista asentamiseen on INSTALL nimisessä tiedostossa selkeät ohjeet, joita noudattamalla kirjaston saa asennettua. Windowsissa kääntäminen hoidetaan joko VisualC++:n nmake-ohjelmalla tai MinGW-kääntäjällä (tulee mm. Dev-C++:n mukana). Linuxissa (ja muissa UNIX:eissa) kääntäminen sujuu tuttuun tapaan:

./configure
make
su
make install

Samoilta sivuilta löytyy myös kaikkien SDL_gfx:n funktioiden kuvaukset.

Visual C++:n käyttäjien on kirjaston kääntämisen jälkeen kerrottava kääntäjälläe missä uudet otsikkotiedostot (.h) ja kirjastotiedostot (.lib) sijaitsevat. Otsikkotiedostot täytyy kopioida samaan kansioon johon olet perus-SDL:n asennuksessa otsikkotiedostot kopioinut. (esim. C:SDLincludeSDL). Huomaa, että sinun on lisättävä projektiisi SDL_gfx:n .lib-tiedosto (SDL_gfx.lib) samaan tapaan kuin lisäät SDL:n lib-tiedostot. GCC:tä käytettäessä on kääntäjälle annettava lisäoptio -lSDL_gfx.

Itse Visual C++:lla tekemäni käännöksen voit kopioida ohjelmointiputkasta.

Käyttö

Yksi tärkeimmistä ominaisuuksista SDL_gfx:ssä on kuvapintojen zoomailu ja pyörittely. Otetaanpa esimerkki:

#include <SDL/SDL.h>
#include <SDL/SDL_rotozoom.h>		// kuvapintojen pyörittely ja zoomailu

//Aliohjelma, jota olemme käyttäneet 2. osassa (en viitsinyt kopioida tähän tilaa viemään)
void NaytaKuva(SDL_Surface *kuva, SDL_Surface *naytto, int x, int y);

int main( int argc, char* argv[] )
{

	SDL_Surface *naytto;
	SDL_Surface *kuva;


	if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
		fprintf(stderr, "SDL:n alustus ei onnistunut: %s",SDL_GetError());
		return 1;
	}
	atexit(SDL_Quit);

	// vaihdetaan reso
	naytto = SDL_SetVideoMode (800, 600, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
	// SDL_FULLSCREEN-flagi puuttuu joten ohjelma näkyy ikkunassa

	// ladataan bittikartta
	kuva = SDL_LoadBMP("jee.bmp");

	// pyöritetään kuvaa 90-astetta ja kaksinkertaistetaan sen koko
	SDL_Surface * temp; // Väliaikainen pinta johon tallennetaan pyöritetty kuva
	temp = rotozoomSurface(kuva, 90, 2, 1);
	SDL_FreeSurface(kuva);   // Vapautetaan kuvan muisti koska sitä ei enää tarvita
	NaytaKuva(temp, naytto, 0,0);

	SDL_Flip(naytto);

	SDL_Delay(5000);   // odotetaan 5s

	SDL_FreeSurface(temp);     // Vapautetaan vielä pyöritetty ja suurennettu kuvapinta
	return(0);
}

Kopioi esimerkkiohjelma

Rivillä 27 kutsutaan rotozoomSurface-funktiota, jolla onnistuu kuvapintojen pyörittely ja zoomailu. Jotta voisit käyttää rotozoom-funktiota, sinun on sisällytettävä projektiisi rotozoom.h-kirjasto.
rotozoomSurface-funktio ottaa parametreina osoittimen lähdepintaan, double-tyyppiset liukuluvut, jotka kertovat paljonko kuvaa käännetään (asteina) ja paljonko zoomataan. Viimeisen parametrin ollessa 1 paluuarvona oleva 32-bittinen pinta on anti-aliasoitu.
Funktio osaa käsitellä vain 8- tai 32-bittisiä pintoja. Jos sille annetaan jokin muu kuin 8- tai 32-bittinen pinta parametrina, se muuttaa sen 32-bittiseksi. Funktion esittely:
SDL_Surface * rotozoomSurface (SDL_Surface *src, double angle, double zoom, int smooth);

SDL_gfx tuo mukanaan myös toisenlaisen zoomailufunktion, jolla voi zoomata x- ja y- akseleita erikseen. Funktio zoomSurface ottaa parametreina osoittimen lähdepintaan, double-tyyppiset tiedot siitä, paljonko x- ja y- akseleilla zoomataan. Viimeinen parametri on sama kuin rotozoomSurface:ssa. Tässä vielä zoomSurface-funktion esittely:
SDL_Surface * zoomSurface (SDL_Surface *src, double zoomx, double zoomy, int smooth);

Nyt kävimme läpi SDL_gfx:n ominaisuuksia hyvin pinnallisesti. Kirjaston kotisivuilta löytyy kuvaus kaikista SDL_gfx:n funktioista, joihin kannattaa ehdottomasti tutustua.

SDL_Mixer

Vaikka SDL:ssä itsessään on jonkinlaisia äänitoimintoja, on olemassa parempiakin vaihtoehtoja.
SDL_Mixer sisältää funktioita erimuotoisten äänitiedostoiden käyttämiseen.

Asennus

Lataa aluksi kehityspaketti SDL_Mixerin sivuilta ja asenna se. Asennus on yksinkertainen: Linuxilla asennetaan joko RPM-paketti tai lähdekoodipaketti samaan tapaan kuin SDL_gfx:n tapauksessa, Windowssille on saatavilla valmis binääripaketti samassa osoitteessa. Kääntäjän asetukset tehdään samalla tavalla kuin SDL_gfx:n ja perus-SDL:n kanssa. Muista kopioida otsikkotiedostot SDL:n kansioon kuten SDL_gfx:n tapauksessa.

Käännettäessä SDL_Mixeriä käyttävää ohjelmaa GCC:llä, on käytettävä -lSDL_mixer -lippua.

Käyttö

Ensiksi SDL_Mixeriä käytettäessä on tietysti sisällytettävä sen otsikkotiedostot:

#include <SDL/SDL_mixer.h>

Lisäksi SDL:ää alustettaessa on käytettävä SDL_INIT_AUDIO-lippua.

// alustetaan SDL, käytettävä SDL_INIT_AUDIO -flagia
if( SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO) < 0 ) {
	fprintf(stderr, "SDL:n alustus ei onnistunut: %s", SDL_GetError());
	return 1;
}

Tämän jälkeen meidän on alustettava SDL_Mixer.

// 44,1 khz, perusmuoto, 2 kaiutinta
if(Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 1024)==-1) {
	fprintf(stderr, "SDL_Mixerin alustus ei onnistunut.");
}

Mix_OpenAudio alustaa SDL_Mixerin. Funktio ottaa parametreiksi äänen taajuuden, muodon, kaiuttimien lukumäärän ja bittitaajuuden. Tarkka kuvaus funktiosta löytyy täältä

Vastaavasti ohjelman lopussa on kutsuttava Mix_CloseAudio-funktiota.

Ääntä peliin!

Noniin, nyt olemme alustaneet SDL:n ja SDL_Mixerin, joten on aika soittaa musiikkia. Esittelen nyt yksinkertaisen tavan äänitiedoston toistamiseen, myös muita funktioita tähän tarkoitukseen on olemassa. Katso lisätietoja dokumentaatiosta

Aluksi ladataan äänitiedosto Mix_LoadWAV-funktiolla. Äänidata tallennetaan Mix_Chunk tyyppiseen tietueeseen.

Mix_Chunk *aani;
aani = Mix_LoadWAV("polkumusiikkitiedostoon.wav");

Tuo koodi lataa aani-nimiseen tietueeseen polkumusiikkifiluun.wav-nimisen äänitiedoston. Tiedosto voi olla jossakin seuraavista muodoista: WAV, AIFF, RIFF, OGG ja VOC.

Nyt kun olemme ladanneet äänitiedoston, voimme pistää sen soimaan Mix_PlayChannel-funktiolla. Ja pistetäänpä taas esimerkkiä peliin:

// olemme jo ladanneet äänitiedoston
if (Mix_PlayChannel(0, aani, 0) < 0)
		fprintf(stderr, "Virhe : %s ", Mix_GetError());   // virhe

Funktion esittely:
int Mix_PlayChannel(int kanava, Mix_Chunk *aani, int toistokerrat)

Funktio ottaa siis parametreina kanavan äänen toistamiseen, osoittimen äänidataan ja äänen toistokertojen lukumäärän (0 = soitetaan kerran, 1 = soitetaan kahdesti, -1 = toistetaan loputtomasti). Tämän jälkeen musiikki soi taustalla, kunnes ohjelma lopetetaan tai musiikin toistaminen pysäytetään. Mikäli halutaan toistaa ääntä teitty aika, käytetään Mix_PlayChannelTimed-funktiota. Funktion esittely:
int Mix_PlayChannelTimed(int kanava, Mix_Chunk *aani, int toistokerrat, int toistoaika)

Funktio toistaa ääntä niin kauan, kunnes toistoaika on kulunut tai kunnes ääntä on soitettu riittävän monta kertaa. -1 tarkoittaa loputonta toistamista.

Esimerkistä käy myös ilmi, miten SDL_Mixerillä haetaan virheitä. Mix_GetError palauttaa kuvauksen virheestä.

Taustalla soivan äänen pysäyttäminen onnistuu seuraavalla koodilla:

Mix_HaltChannel(kanava);

Funktiolla annetaan parametrina pysäytettävän kanavan numero.

Käydäänpä vielä pari asiaa SDL_Mixeristä. Ensin äänenvoimakkuuden säätäminen, joka onnistuu Mix_VolumeChunk-funktiolla. Funktion esittely:

int Mix_VolumeChunk(Mix_Chunk *aani, int voimakkuus);

Funktio ottaa parametrina osoittimen äänidataan, jonka voimakkuutta muutetaan. Toinen parametri on äänenvoimakkuus. Sen on oltava väliltä 0-128.
Funktio palauttaa alkuperäisen äänenvoimakkuuden.

Ja sitten viimeinen asia (vihdoinkin): äänidatan poistaminen muistista. Tämä onnistuu näin yksinkertaisella funktiolla:

Mix_FreeChunk(aani);
aani = NULL; //varmuuden vuoksi

Se on siinä!

Kävimme nyt pikakurssin muutamasta hyödyllisestä SDL:n lisäkirjastosta. Tämän oppaan tarkoitus on kertoa sinulle sekä SDL_gfx:n että SDL_Mixerin käytöstä, ja samalla kertoa yleisesti siitä, miten SDL:n lisäkirjastot asennetaan. Yleensä asennus on kaikissa lähes samanlainen, ja käyttökin on aina lähes samanlaista.

Tämän oppaan ei ollutkaan tarkoitus kertoa kaikkea tässä esitellyistä SDL:n lisäkirjastoista. Kävimme ne läpi vain pintapuoleisesti. Kannattaa tutustua seuraaviin sivuihin:

Mitä sitten?

Jos olet ymmärtänyt kaikki asiat tästä opassarjasta, olet oppinut SDL:n ja sen lisäkirjastojen käytön perusteet. Toivon että tämä opassarja on auttanut sinut alkuun SDL:n käyttämisessä.

Oppaaseen liittyvää kritiikkiä/korjauksia/tietoja asiavirheistä yms. otan vastaan sähköpostilla tai oppaan kommenteissa. Koska minullakin on jonkinlainen elämä (oikeastikko?), niin joten SDL:ää (tai ohjelmointia yleensä) käsitteleviin kysymyksiin en luultavasti vastaa sähköpostilla. Näissä asioissa kannattaa käyttää putkan foorumia.

Koodailemisiin!

Viimeksi muokattu 18.5.2007


Kommentit

ZcMander [05.12.2004 10:52:13]

#

jos käyttää -1 niin mistä tietää mikä kanava pitää laittaa päälle tai pois?

edit: kana=kanava

Heikki [05.12.2004 19:59:58]

#

Hups! Tuo -1 ei taidakkaan toimia tuossa oikein. Taisin sekoittaa sen toisesta funktiosta. Kiitoksia huomautuksesta, nyt korjattu.

Ps. Mikä kana?

Gaxx [06.12.2004 11:27:35]

#

Tätä on odotettu! Opassarja on huomattavasti selkeämpi kuin kaikki ne muut, joita olen lueskellut netistä. Juuri tällaista funktioiden yksittäistä esittelemistä kaipasin. On vähän hankalampi tutkia pitkää koodia ja yrittää ottaa selvää, mikä pieni ominaisuus tekee juuri sen asian, jonka haluasisi oppia.

Hyvä opas!

Juice [13.12.2004 21:15:35]

#

Miksei oppaassa ole käsitelty MIX_Musicia? En saanut itse toimimaan. Ja itselleni SDL_Gfx:n asennus mingw:hen on täyttä utopiaa. En pääse edes alkuun.

Heikki [16.12.2004 21:20:33]

#

Juice: Esittelin vain osia lisäkirjastoista, sillä ei ollut tarkoituskaan opettaa niitä kokonaan. Ja itse olen pärjännyt pitkälle tuossa oppaassa esitellyillä ominaisuuksilla.

Heikki [22.12.2004 10:51:00]

#

Päivitys: Lisäsin putkan palvelimelle itse VC++:lla tekemäni käännöksen SDL_gfx:n kirjastoista, joten ainakin VC++:n käyttäjien ei välttämättä tarvitse tehdä käänöstä itse. En sitten tiedä toimivatko nuo MinGW:n kanssa, kertokaa jos kokeilette.

Gaxx [08.02.2005 18:53:20]

#

Toi VC++:lle tehty käännös toimii ainakin Dev-Cpp:n versiossa 4.9.8.0.

karwis [17.02.2005 17:11:46]

#

Kiitoksia tästä SDL-oppaasta!

ZcMander [18.02.2005 21:40:12]

#

SDL_gfx.dll puuttuu.

Heikki [03.03.2005 00:28:03]

#

Eikös tuo SDL_gfx.dll tule jossain paketissa ihan valmiina? Muistaakseni tulee. No joka tapauksessa ks. tiedoston voi ladata ainakin toistaiseksi osoitteesta http://mbnet.fi/heikki_m/SDL_gfx.dll

--

Kiitän ja kumarran kehuista ja siitä, että olette monia typoja löytäneet. Nyt opassarjassa ei pitäisi enään juuri mitään typoja olla.

exAtuu [11.06.2005 13:57:29]

#

... Ne Linux-käyttäjien, joiden koneeseen...

Kuulostaisi järkevämmältä jos tuo olisi "Ne Linux-käyttäjät"


Tämä oli kyllä hyvä opassarja. Kiitos tästä :)

Heikki [19.06.2005 15:14:03]

#

Jälleen kerran korjattu typoja, kumma kun eivät meinaa millään loppua.

Kiitoksia vaan kehuista, yllättävän suosituksi paljastunut tämä opassarja; SDL-oppaita (asennus+4 perusopasta) luettu yhteensä 11498 kertaa, suosituin on asennusopas, luettu 3760 kertaa.

Koipio-ohjelma [15.07.2005 13:42:00]

#

Eikö SDL:ssä muka todellakaan ole sellaista funktiota, joka piirtäisi pikselin johonkin kohtaan "pintaa"(SDL_Surface)?

Etsitty on dokumentaatiosta, mutta itse en löytänyt kuvausta vastaavaa funktiota...
Sanokaa nyt onko turhaa alkaa tekemään itse sellaista funktiota :D
Turhaa työtä en mielellään tee nimittäin

Juice [27.07.2005 23:55:18]

#

Koipio-ohjelma:

pixelColor(surface,x,y,0xFFFFFFFF);

Toi 0xFFFFFFFF on väri muodossa 0xRRGGBBAA eli red, green, blue ja alpha heksana.

C++Amatööri [16.08.2005 18:04:51]

#

Miten sais esim jonkun pienen kuvan seuraamaan hiirtä (SDL:lällä)

Jtm [15.09.2005 17:34:01]

#

Tuohan lukee ihan tässä oppaassa

Jtm [15.09.2005 17:41:55]

#

Olisi tosiaan kiva tietää miten tuo SDL_gfx asennetaan MinGW:sen. Muuten ihan hyvä opas, paitsi tuo on turhan suuri puute.

Jtm [16.09.2005 20:19:25]

#

Ai katos sain ton toimimaan Dev-Cpp:aan Visual C++ library paketillasi.

Teuvo Töhvelö [27.03.2006 22:11:44]

#

Näyttää pahasti siltä, että tuo SDL_gfx-linkki on hajalla. Olisikohan tämä toimivampi: http://www.ferzkopp.net/Software/SDL_gfx-2.0/

Heikki [28.03.2006 07:03:15]

#

Niinpä näkyy, korjattu.

Metabolix [17.04.2006 13:38:01]

#

Olisi mukava, jos oppaissa ei viljeltäisi muistivuotoja. Eli esimerkiksi tämä pätkä:

kuva = SDL_LoadBMP("jee.bmp");
kuva = rotozoomSurface(kuva, 90, 2, 1);
NaytaKuva(kuva, naytto, 0,0);

Tuossakin jää heti kaksi pintaa vapauttamatta. Oikeammin se menisi näin:

SDL_Surface * temp;
kuva = SDL_LoadBMP("jee.bmp");
temp = rotozoomSurface(kuva, 90, 2, 1);
SDL_FreeSurface(kuva); // Vapautus
NaytaKuva(temp, naytto, 0,0);
SDL_FreeSurface(temp); // Vapautus

Sama vika on läpi opassarjan kaikissa pinnoissa. Kannattaisi jo heti alussa mainita, että SDL ei niitä itse vapauta, vaan kaikille pinnoille näyttöä lukuun ottamatta pitää suorittaa SDL_FreeSurface. Tilanne on aivan sama kuin malloc, josta puuttuu free.

Heikki [17.04.2006 21:46:53]

#

Olet oikeassa, muistivuotoja tosiaan on ikävän paljon. Lupaan käydä opassarjan läpi lähipäivinä ja lisätä tarvittavat muistinvapautukset.

Edit. Kävinpä nyt oppaat läpi ja vapauttelin muistia.

brotha [04.12.2006 15:19:50]

#

Minulla tulee tossa errori:

"`atexit' undeclared (first use this function) "
Voisiko joku auttaa?

Virhe viittaa kohtaan:
atexit(SDL_Quit);

Kray [21.03.2007 08:15:56]

#

Äh, vaikka yritän ja yritän, niin ei mixer toimi Dev-cpp:llä. SDL_mixer.h on include/SDL kansiossa, ja parametrit on omasta mielestä oikein:

Compiler: -I"<INCLUDE>\SDL" -Dmain=SDL_main

C++ Compiler: -I"<INCLUDE>\SDL" -Dmain=SDL_main

Linker: -lmingw32 -lSDLmain -lSDL -liberty -lSDL_mixer

Mikä on vikana? Tulee erroriksi: "cannot find -ISDL_mixer"

tgunner [18.05.2007 00:49:33]

#

Hee, rotozoomerin esimerkkikoodissa on syntaksierrori. SDL_FreeSurface(temp):n jälkeen ei tule puolipistettä. :-D

moptim [14.07.2007 09:35:06]

#

Pitääkö sitä kuvaa tosiaan pyörittää 90-astetta? Eikö 90 astetta riittäisi? :D

riserbar [09.03.2008 14:49:58]

#

Kirjoitin koodin SDL_Surfacen kieputteluun. Mittauksieni mukaan tämä ensimmäinen versio on noin 50 % - 100 % nopeampi kuin SDL_gfx:n rotozoomSurface. Mukaan ei tarvita mitään muuta kuin SDL.h. Koodi on alunperin Linuxille, mutta pitäisi olla helposti portattavissa mille tahansa alustalle. Kielenä C++.

Koodit saa täältä:

http://www.kolumbus.fi/jussi.lind/index.html

Zakki [03.04.2008 18:26:11]

#

ai on INSTALLissa selvät ohjeet? en ymmärrä siitä sanaakaan(paitsi ne mitkä on englanniksi)

lahtis [31.01.2009 22:00:39]

#

jostain syystä toi ensimmäinen esimerkki ei toimi vaikka SDL_gfx on asennettu.

g++ -o source sdl41.cpp -lSDL
/tmp/cco3fJoT.o: In function `main':
sdl41.cpp:(.text+0x11e): undefined reference to `rotozoomSurface'
collect2: ld returned 1 exit status

eli kuva=rotozoomSurface(kuva, 90, 2, 2); tässä on jotain vikaa.

Wusakko [22.04.2009 18:06:01]

#

Mulla olis pieni probleema...

Eli pienessä pelissäni animoin ukkoa juuri tuon SDL_gfx pyörityskomennoilla, mutta ongelmaksi on tullut se, että peli jättää edellisen kuva taustalle. Olisiko mitään komentoa millä saisi kuvan kätevästä poistettua juuri ennen kuin piirrän sen uudestaa. Tokihan tämän saa ihan piirtämällä päälle pohja mikä siinä oli ennen ukkoa, mutta tämä vaatii ukon sijaitien tietämistä. Osaan kyllä tehdä tämän tällä "vanhalla" tyyllillä, mutta ajattelin vain kysäistä onko tätä mahdollista tehdä jotenkin helpommin. Kiitos vastauksista.

Ps. Voisko noita "koodissasi on virhe"-kommentteja tunkea vaikka privan kautta tai jollain eri toiminnolla, koska keskustelut on 90% täynnä tota shaissea eikä sielä löydä itte asiaan liittyviä kysymyksia.

hyprE [19.08.2009 15:06:25]

#

Kiitos tästä, erinomainen opas. Motivaatio hiipui googlesta löytyvien linkkien haravoinnissa, mutta sitten muistin Ohjelmointiputkan ja suuntasin tänne. Äkkiäkös SDL-opas olikin jo auki, ja täytyy kyllä sanoa, että yllätti kyllä tasokkuudellaan tämä opas.

Nyt siirryn ohjelmoimaan peliini valikkoa SDL:llä, kiitos Heikki Mäntysaaren. hyprE away -->

ankzilla [07.10.2009 16:41:53]

#

"Paketit löytyvät SDL_gfx:n koitsivuilta"
"Mikäli halutaan toistaa ääntä teitty aika,"

TVdata [04.11.2012 11:54:29]

#

Tässä binäärit macille.

Kirjoita kommentti

Huomio! Kommentoi tässä ainoastaan tämän oppaan hyviä ja huonoja puolia. Älä kirjoita muita kysymyksiä tähän. Jos koodisi ei toimi tai tarvitset muuten vain apua ohjelmoinnissa, lähetä viesti keskusteluun.

Muista lukea kirjoitusohjeet.
Tietoa sivustosta