J2ME v kostce - jak na zvuk I
Ve standardnφm MIDP 1.0 byste podporu zvuku hledali marn∞. Co s tφm, pokud p°esto chcete u₧ivatele sv²ch her obÜ¥astnit ·chvatn²mi a nezapomenuteln²mi zvuky, bez nich₧ by to prost∞ nebylo ono? Cht∞ necht∞ budete muset nejspφÜ pou₧φt proprietßrnφ API v²robc∙ telefon∙. V tomto Φlßnku vßs seznßmφm s Φßstφ Mobile Multimedia API, t²kajφcφ se zvuku.
Mobile Media API
Knihovna Mobile Media API (MMAPI - JSR-135) rozÜi°uje J2ME o prßci s multimΘdii, nap°φklad audiem a videem. Podmno₧ina MMAPI, zab²vajφcφ se zvukem, je souΦßstφ MIDP 2.0, ale vyskytuje se i na nezanedbatelnΘm mno₧stvφ telefon∙, kterΘ implementujφ pouze MIDP 1.0. Jak tvrdφ p°ehled telefon∙ s J2ME p°φmo u Sunu, jde o nov∞jÜφ telefony od firem Nokia a Sony Ericsson. MMAPI se vyskytuje i na n∞kter²ch telefonech znaΦky Siemens (nejspφÜ na vÜech krom∞ starÜφch model∙ jako SL45i, M50, MT50), jenom s tou fintou, ₧e se odpovφdajφcφ t°φdy nenachßzejφ v balφcφch javax.microedition.media
a javax.microedition.media.control
, ale v balφcφch com.siemens.mp.media
a com.siemens.mp.media.control
.
Zßkladnφ t°φdou MMAPI je t°φda javax.microedition.media.Manager
. Tato t°φda dle zadan²ch parametr∙ vytvo°φ instanci rozhranφ javax.microedition.media.Player
, kterß slou₧φ k p°ehrßvßnφ zvukov²ch soubor∙ nebo jednohlas²ch sekvencφ t≤n∙. Nastavenφ t°φdy typu javax.microedition.media.Player
se dßle m∙₧e ovliv≥ovat t°φdami typu javax.microedition.media.Control
.
Architektura MMAPI
Manager
T°φda Manager umφ vytvo°it instanci t°φdy Player
ze vstupnφho proudu nebo na zßklad∞ zadanΘho URI. Prvnφ metoda je urΦena k p°ehrßvßnφ zvukov²ch soubor∙ ulo₧en²ch v JARu a jejφ pou₧itφ je nßsledujφcφ:
// otev°enφ zvukovΘho souboru v JARu
InputStream is = getClass()
.getResourceAsStream("music.wav");
// vytvo°enφ instance t°φdy Player,
// kterß umφ p°ehrßt onen zvukov² soubor
Player p = Manager.createPlayer(is, "audio/x-wav");
// nastavenφ poΦtu opakovßnφ zßznamu
p.setLoopCount(13);
// spuÜt∞nφ p°ehrßvßnφ
p.start();
} catch (IOException ioe) {
// nastal problΘm se Φtenφm proudu
} catch (MediaException me) {
// Player po₧adovanΘho typu nelze vytvo°it
}
Pokud se v JARu zvukov² soubor nenachßzφ, zkonΦφ b∞h p°edchozφho k≤du v²jimkou NullPointerException
, proto₧e v tom p°φpad∞ vrßtφ metoda getResourceAsStream("music.wav") hodnotu null.
Nachßzφ-li se zvukov² soubor mimo JAR soubor aplikace, je pot°eba k jeho p°ehrßnφ pou₧φt metodu Manager.createPlayer(String URI)
. URI je definovßno schΘmatem:
P°φklady URI:
ftp://nejaky.ftp.server.com/cizi.wav
Povinn∞ podporovanΘ typy zvukov²ch soubor∙ jsou v MIDP 2.0 "WAV (audio/x-wav)" a "MIDI (audio/midi)", nejlepÜφ je zjistit si na ka₧dΘm telefonu seznam vÜech podporovan²ch typ∙ metodou getSupportedContentTypes(String protokol)
. Zavolß-li se s parametrem null, vrßtφ podporovanΘ typy bez ohledu na protokol. Nap°φklad telefony Sony Ericsson um∞jφ p°ehrßvat "MIDI (audio/midi)", "AMR (audio/amr)" a "iMelody (audio/imelody)".
Na p°ehrßnφ jednoho t≤nu mß t°φda Manager
metodu playTone(int vyska, int delka, int hlasitost)
. V²Üka t≤nu je Φφslo od 0 do 127, p°iΦem₧ t≤nu c1 odpovφdß hodnota 60 a dßle v₧dy hodnoty liÜφcφ se o 1 odpovφdajφ notßm liÜφcφm se o p∙lt≤n.
Player
Rozhranφ Player slou₧φ k p°ehrßvßnφ zvukov²ch dat. B∞hem svΘho ₧ivotnφho cyklu se m∙₧e ocitnout v n∞kolika stavech:
Nerealizovan² stav
V tomto stavu se Player
nachßzφ po svΘm vytvo°enφ. Proto₧e nemß jeÜt∞ dostatek informacφ o zvukov²ch datech, nelze v tomto stavu volat metody:
- getContentType()
- setMediaTime()
- getControls()
- getControl()
Do nßsledujφcφho stavu p°ejde Player
zavolßnφm metody realize()
. Jsou-li nap°φklad zvukovß data umφst∞na na serveru, jsou v pr∙b∞hu realizace sta₧ena na mobilnφ telefon.
Realizovan² stav
Zvukovß za°φzenφ se jeÜt∞ nealokujφ, aby zbyteΦn∞ nebyla blokovßna. Do nßsledujφcφho stavu se p°ejde metodou prefetch()
.
P°ipraven² stav
P°echod z p°ipravenΘho do b∞₧φcφho stavu by m∞l trvat minimum Φasu, proto v p°ipravenΘm stavu u₧ jsou alokovßna zvukovß za°φzenφ a zßsobnφky napln∞ny zvukov²mi daty, je-li to pot°eba. Do nßsledujφcφho stavu se p°ejde metodou start()
. Po ukonΦenφ svΘho b∞hu se Player
op∞t vrßtφ do p°ipravenΘho stavu.
B∞₧φcφ stav
V b∞₧φcφm stavu Player
p°ehrßvß zvukovß data. V tomto stavu nenφ u₧ mo₧nΘ nastavovat poΦet opakovßnφ zvuku metodou setLoopCount()
.
UkonΦen² stav
Do ukonΦenΘho stavu p°ejde Player
z jakΘhokoli stavu volßnφm metody close()
. V tomto stavu uvolnφ vÜechny zdroje a nedß se u₧ dßle pou₧φt.
Player - ₧ivotnφ cyklus
Obrßzek ukazuje cel² ₧ivotnφ cyklus objektu typu Player
. Pro lepÜφ p°ehlednost z n∞j byly vypuÜt∞ny n∞kterΘ Üipky. Je-li Player
v nerealizovanΘm stavu a zavolß se metoda prefetch()
nebo start()
, automaticky je zavolßna jako jejich souΦßst metoda realize()
. Je-li Player
v realizovanΘm stavu a zavolß se na n∞m metoda start()
, automaticky je zavolßna jako jejφ souΦßst metoda prefetch()
.
Udßlosti
Pot°ebujeme-li dostßvat informace o zm∞nßch stavu t°φdy typu Player
, je pot°eba implementovat rozhranφ PlayerListener
, kterΘ obsahuje pouze jednu metodu playerUpdate(Player player, String typUdalosti, Object data), a dßle si posluchaΦe zaregistrovat metodou addPlayerListener(PlayerListener posluchac). VÜechny typy udßlostφ, kterΘ posluchaΦ m∙₧e dostßvat, obsahuje rozhranφ PlayerListener
jako statickΘ prom∞nnΘ. Chceme-li, aby po celou dobu spuÜt∞nφ aplikace hrßla na pozadφ dokola jedna skladba a nastavenφ vysokΘho poΦtu opakovßnφ skladby se nßm nezdß jako dostateΦn∞ vhodnß metoda, m∙₧eme si zaregistrovat posluchaΦe a p°i odchycenφ udßlosti END_OF_MEDIA volat na t°φdu typu Player
metodu start()
.
Control
Rozhranφ Control neobsahuje ₧ßdnΘ metody spoleΦnΘ pro ovladaΦe zvuku, slou₧φ pouze jako p°edek, ze kterΘho musφ b²t vÜechny odvozeny. V MIDP 2.0 jsou definovßna v balφku javax.microedition.media.control
dv∞ rozhranφ, rozÜi°ujφcφ Control
, a to VolumeControl
a ToneControl
.
VolumeControl
Rozhranφ VolumeControl
slou₧φ poze k nastavenφ hlasitosti zvuku. Hlasitost m∙₧e nab²vat hodnotu od 0 do 100. Hodnota 0 odpovφdß vypnutΘmu zvuku a 100 nejvyÜÜφ mo₧nΘ hlasitosti.
// pou₧it² nßzev t°φdy absolutnφ, p°edpoklßdß se,
// ₧e je z balφku javax.microedition.media.control
VolumeControl volume = (VolumeControl)
player.getControl("VolumeControl");
// nastavenφ hlasitosti na nejvyÜÜφ mo₧nou hodnotu
volume.setLevel(100);
ToneControl
Rozhranφ ToneControl
slou₧φ k p°ehrßvßnφ jednohlas²ch sekvencφ t≤n∙. Toto rozhranφ nenφ obsa₧eno v telefonech znaΦky Siemens. Pokud u₧ mßme sekvenci t≤n∙ vytvo°enou, p°ehraje se takto:
byte[] mySequence = ...
try {
// vytvo°enφ t°φdy typu Player na p°ehrßvßnφ sekvencφ t≤n∙
Player mp = Manager.createPlayer(Manager.TONE_DEVICE_LOCATOR);
// p°echod do realizovanΘho stavu
mp.realize();
// zφskßnφ ovladaΦe typu ToneControl
ToneControl c = (ToneControl)
mp.getControl("ToneControl");
// nastavenφ skevence t≤n∙
c.setSequence(mySequence);
// spuÜt∞nφ p°ehrßvßnφ
mp.start();
} catch (Exception ex) {
// zpracovßnφ v²jimky
}
┌plnß definice formßtu sekvence t≤n∙ je pon∞kud delÜφ, proto ji uvßdφm v externφm souboru.
Poznßmka k MIDP 2.0
Pokud vßs blφ₧e zajφmß MIDP 2.0, je prßv∞ v tisku Φesk² p°eklad knihy J2ME v kostce, kterou vydßvß Grada. Tato kniha bude obsahovat takΘ mou p°φlohu, zab²vajφcφ se prßv∞ MIDP 2.0.
Odkazy, zdroje
- J2ME Wireless Toolkit 2.1 - MIDP 2.0 emulßtor od firmy Sun
- Sony Ericsson - informace a emulßtory
- Siemens - informace a emulßtory