VI. Multimédia REXX

Автор: Kádár Zsolt

Дата: 13.06.1999

Источник: https://xenia.sote.hu

Язык: Венгерский

Bevezetés

Az elôzôek alapján már biztosan nem lep meg senkit, hogy a REXX programok az OS/2 Warp multimédia szolgáltatásait is használni tudják a Media Control Interface-en (MCI) keresztül. Az MCI segítségével bármely, a multimédia alrendszer által támogatott eszköz vezérelhetô REXX programból. Bizonyos eszközök (pl. a MIDI lejátszó) fájlokkal dolgoznak. Ezeket az eszközöket az MCI-on keresztül rá lehet venni a fájlok megnyitására, lejátszására illetve a fájlon belüli pozícionálásra. Más eszközök (pl. CD-ROM) közvetlen parancsokkal vezérelhetôk. Az MCI a következô multimédia eszközöket támogatja:

  • Videotape
  • Videodisc
  • CDaudio (CD-ROM)
  • Waveaudio
  • Sequencer (MIDI)
  • Digitalvideo

A videoeszközök funkcionálásához nélkülözhetetlen az OS/2 grafikus környezete. Éppen ezért ezek az eszközök csak akkor használhatók REXX programból (parancssorból), ha azt a PMREXX-en keresztül futtatjuk (start /pm cmd.exe rexxfile.cmd), vagy valamilyen vizuális REXX környezetben fordítjuk le.

MCI támogatás

A multimédia REXX-bôl történô használatának elôfeltétele, hogy telepítve legyen a multimédia komponens, illetve az annak részét képezô MCIAPI.DLL, amely a bôvítôfüggvényeket tartalmazza. Ha a DLL benne van a LIBPATH-ban (ami standard telepítést feltételezve automatikusan teljesül), akkor a következô kódrészlettel lehet a függvényeket regisztrálni:

Call RxFuncAdd 'mciRxInit', 'MCIAPI', 'mciRxInit'
Call mciRxInit

A segédfüggvények az mciRxExit hívással törölhetôk ki a memóriából, ha már nincs rájuk szükség. A regisztrálást és az eltakarítást végzô függvények mellett még az mciRxSendString és mciRxGetErrorString függvényeket is tartalmazza a bôvítôcsomag. A SendString segítségével parancsokat küldhetünk az eszközöknek, míg a GetErrorString segítségével lekérdezhetjük a visszaadott információt. Ezen kívül létezik még az mciRxGetDeviceID függvény, amellyel az eszközök azonosítói kérdezhetôk le. Az alábbi táblázatban összefoglaltuk a multimédiás bôvítôfüggvényeket:

Funkció és szintakszis: Paraméterek: Visszatérési érték:
A multimédia függvények regisztrálása: mciRxInit() - 0 = sikeres végrehajtás
A multimédia függvények kitakarítása a memóriából: mciRxExit() - 0 = sikeres végrehajtás
Az eszköz alias nevéhez tartozó ID megadása: DevID = mciRxGetDeviceID(alias) alias = Az OPEN paranccsal megadott alias Az eszköz ID-ja
Hibakód lekérdezése: frc = mciRxGetErrorString(rc, 'errorstr') rc = egy MCI REXX függvény által visszaadott érték, errorstr = változó neve, amelybe a hibaüzenetet kérjük 0 = sikeres végrehajtás
MCI parancs küldése: rc = mciRxSendString(cmdstring, 'retstrvar', foglalt1, foglalt2) cmdstring = a küldeni kívánt parancs, retstrvar = REXX változó, amelybe a parancsra küldött válasz kerül, foglalt1/foglalt2 = foglalt változók, 0-át kell megadni 0 = sikeres végrehajtás esetén, vagy a megfelelô MMPM/2 hibakód

A multimédiát használó REXX programok limitációi

Már a bevezetésben is említettük, hogy a videoeszközöket vezérlô REXX programokat a PMREXX-en keresztül kell futtatni. Ezen kívül még további korlátozásokat is észben kell tartani. A REXX programok például nem kapják meg azokat az üzeneteket, amelyek a multimédia eszköz használatba vételérôl, avagy éppen a felszabadulásáról tájékoztatnák. Éppen ezért a REXX programoknak lehetôleg kizárólagos hozzáféréssel kell rendelkezniük ezekhez az eszközökhöz. Amennyiben az eszköz megosztva kerül felhasználásra, akkor a REXX programnak a parancsokat az ACQUIRE EXCLUSIVE és RELEASE RETURN RESOURCE utasítások közé kell ágyazni. Lehetséges, hogy az ACQUIRE EXCLUSIVE parancs az elsô próbálkozáskor nem lesz sikeres és meg kell ismételni. A REXX programnak le kell tudni kezelni az ilyen eseteket is. Arra is figyelni kell programírás közben, hogy egy REXX program ne foglalja le az eszközt túl hosszú ideig. Mivel a REXX programok nem tudják detektálni a PM üzeneteket, így arra sem képesek, hogy automatikusan érzékeljék, amikor egy mûvelet (pl. lejátszás) véget ér. Bizonyos esetekben le lehet kérdezni az eszköz állapotát, amelybôl lehet következtetni a végeredményre. Az MCI felület lehetôvé teszi parancsok végrehajtását az eszköz elôzetes megnyitása nélkül. Az ilyen esetekben automatikusan végrehajtott megnyitás azonban osztott módot használ, ami azt eredményezheti, hogy a REXX program késôbb elveszítheti az eszköz feletti uralmat.

Az MCI parancskészlet

Az MCI parancsok egy része univerzálisan használható, ami azt jelenti, hogy ezeket a parancsokat minden multimédia eszköz megérti. A parancsoknak létezhet ún. kiterjesztett verziójuk is, amelyek extra opciókkal bôvítik az alapkészletet. Az univerzális parancsok mellett léteznek eszközspecifikus parancsok is, amelyeket csak az az eszköz ért meg, amelyre tervezték. A fejlesztôk viszont többnyire arra törekednek, hogy a specifikus parancsok megegyezzenek, vagy a lehetô legjobban hasonlítsanak egymásra. A legtöbb eszköz lejátszást indító parancsa pl. a PLAY. A parancsok általános formája a következô:

parancs objektum [kulcsszavak] [WAIT]

A kötelezôen megadandó objektum paraméter a multimédia eszközt azonosítja. Megadható pl. az eszköz típusa (Videotape, Videodisc, CDaudio, Waveaudio, Sequencer vagy Digitalvideo). Amennyiben több eszköz is lenne ugyanabból a típusból, akkor az MMPM/2 setup segítségével beállított default eszköz kerül kiválasztásra. A típus helyett megadható az eszköz neve is, amelynek az EszközTípusNN formátumot kell követni. Az eszköztípus az elôzôekben megadott típusok valamelyike kell, hogy legyen. Az NN az eszköz sorszámát jelöli. Az objektum helyén megadható még a megnyitandó fájl neve is, ugyanis az MMPM/2 alrendszer a fájl kiterjesztése alapján megállapítja, hogy melyik eszközt kell a lejátszáshoz használnia. Ezen kívül használható még az eszköz álneve (alias), amelyet az OPEN paranccsal kell elôzetesen beállítani. A kulcsszavak minden esetben parancsspecifikus opciókat jelentenek. Egy kitüntetett, minden parancs esetében megadható opció a WAIT, amely arra szólítja fel a multimédia alrendszert, hogy egészen addig várjon, amíg a parancs le nem futott. Egyes parancsok esetében (CAPABILITY, STATUS) a WAIT paramétert kötelezô megadni!

Az MCI 17 különféle parancsot tartalmaz. A parancsok funkcióját, szintakszisát, paraméter-leírását és a visszatérési értékeket összefoglaltuk az alábbi táblázatban:

MCI parancs: Paraméterek:
Eszköz fizikai erôforrásainak lefoglalása:
ACQUIRE objektum módosító WAIT
objektum = a lefoglalandó eszköz, módosítók = a parancsot finomító kulcsszó (exclusive = kizárólagos eszközelérés, exclusive instance = az objektum által igényelt erôforrások kizárólagos lefoglalása, queue = a parancs várakozik, amíg az eszköz foglalt)
Eszköz képességeinek lekérdezése:
CAPABILITY objektum módosító WAIT
objektum = a lefoglalandó eszköz, módosítók = a parancsot finomító kulcsszó (can record = képes-e felvenni (ha igen, akkor true a visszatérési érték), has audio = képes-e audio lejátszásra, has video = képes-e video lejátszásra, can eject = képes-e az adathordozó kiadására, can play = képes-e lejátszásra, can save = képes-e felvételre, compound device = true értéket ad vissza, ha az eszköznek elemnévre van szüksége, uses files = meg kell-e adni fájlnevet, can lockeject = meg lehet-e akadályozni a média kézzel való eltávolítását, can setvolume = állítható-e a hangerô, preroll type = milyen preroll technikát támogat az eszköz (notified visszatérési érték változó, deterministic pedig elôre beállított preroll idôt jelent; none esetén nincs lehetôség prerollra), preroll time = mennyi a preroll idô, device type = az eszköz típusa (animation, ampmix, cdaudio, cdxa, digitalvideo, overlay, sequencer, videodisc, waveaudio, other), message param = true-t ad vissza, amennyiben az eszköz támogatja a param által megadott üzenetet.
Eszköz felszabadítása:
CLOSE objektum WAIT
objektum = a felszabadítandó eszköz
Konnektorok engedélyezése, letiltása, avagy státuszuk lekérdezése:
CONNECTOR objektum mûvelet módosító WAIT
objektum = a konnektorhoz tartozó eszköz, mûvelet = a végrehajtandó mûvelet (enable = engedélyezés, a number vagy a type módosítót is meg kell adni, disable = letiltás, a number vagy a type módosítót is meg kell adni, query = a státusz lekérdezése), módosító = number [szám] (a konnektor sorszáma) vagy type [típus] (a konnektor típusa). Lehetséges típusok: MIDI stream, CD stream, wave stream, XA stream, amp stream, headphones, speakers, microphone, line in, line outvideo in, video out.
Eszközök termékazonosító információjának lekérdezése:
INFO objektum termék WAIT
objektum = a kérdéses eszköz, termék = az eszközrôl kapott termékazonosító információt tároló változó
Fájl betöltése:
LOAD objektum fájl WAIT
objektum = a fájlt feldolgozó eszköz, fájl = a betöltendô fájl
Eszköz megnyitása:
OPEN objektum módosító WAIT
objektum = a megnyitandó eszköz, módosító = shareable (megosztott használatú megnyitás), type típus (a vezérlô eszköz típusa), alias álnév (alternatív eszköznév). Sikeres végrehajtás esetén egy számot kapunk vissza, amely a megnyitott eszközt azonosítja.
Lejátszás szüneteltetése:
PAUSE objektum WAIT
objektum = a lejátszást végzô eszköz
Lejátszás elindítása:
PLAY objektum módosító WAIT
objektum = a lejátszást végzô eszköz, módosító = from pozíció (a lejátszás kezdô pozíciója), to pozíció (a lejátszás végpozíciója)
Adatfelvétel indítása:
RECORD objektum módosító WAIT
objektum = a felvételt végzô eszköz, módosító = insert (adatbeillesztés), overwrite (adatfelülírás), from pozíció (a megadott pozíciótól kezdôdôen), to pozíció (a megadott pozícióig)
Eszköz által lefoglalt erôforrások visszaadása:
RELEASE objektum [return resource] WAIT
objektum = a kérdéses eszköz, return resource = megadása azt eredményezi, hogy az eszköz vezérlését az a program kapja, amelyik utoljára adta fel az erôforrásokat.
Lejátszás vagy felvétel folytatása:
RESUME objektum WAIT
objektum = a kérdéses eszköz
Adat elmentése:
SAVE objektum [fájlnév] WAIT
objektum = a kérdéses eszköz, fájlnév = az elmentendô fájl neve (amennyiben a Load utasítással megadtunk fájlnevet, akkor ez a paraméter elhagyható)
Pozíció megkeresése:
SEEK objektum módosítók WAIT
objektum = a kérdéses eszköz, módosító = a pozíciót meghatározó paraméter (to pozíció = megadott pozícióra pozícionál, to start = a média elejére pozícionál, to end = a média végére pozícionál)
Vezérelt eszköz paramétereinek a beállítása:
SET objektum módosítók WAIT
objektum = a beállítandó eszköz, módosítók = a beállítandó paraméter meghatározása (audio = audio attribútumok: all (minden csatornára), left/right (bal/jobb csatorna), volume % (hangerô %), on/off (audio kimenet be/kikapcsolása), over Xms (a változtatások Xms után érvényesüljenek), door closed = ajtó becsukása, door open = ajtó nyitása és a média kidobása, door locked = ajtó zárolása, door unlocked pos = ajtó zárolásának feloldása, master MIDI = a MIDI sequencer a szinkronizációs forrás (MIDI formátum), master none = a szinkronizációs forrás letiltása, master SMPTE = a MIDI sequencer a szinkronizációs forrás (SMPTE formátum), slave file = fájl a szinkronizációs forrása a MIDI sequencernek (alapbeállítás), slave MIDI = MIDI fájl a szinkronizációs forrás, slave none = szinkronizációs adat figyelmen kívül hagyása, slave SMPTE = SMPTE fájl a szinkronizáció forrása, time format ms = az idôegység a ms, time format MMTIME = az idôegység az MMTIME (3000 MMTIME/s), speed format % = sebesség formátum a %, speed format fps = sebesség formátum az fps (frames/second), video off = video kimenet kikapcsolva, video on = video kimenet bekapcsolva)
Eszköz állapotának lekérdezése:
STATUS objektum módosítók WAIT
objektum = a kérdéses eszköz, módosítók = a lekérdezendô információ meghatározása (általános módosítók: length (szegmens hossza), mode (állapot, lehetséges válaszértékek: not ready, stopped, playing, seeking, recording, paused, other), position (pozíció), ready (true a visszatérés, ha kész az eszköz), time format (idôformátum), volume (hangerô, a visszatérési érték formátuma: bal_csatorna:jobb_csatorna), eszközspecifikus módosítók: current track (a jelenlegi sáv), length track sorszám (a sorszám által jelzett sáv hossza), numbers of tracks (a sávok száma a hordozón), position in track (a sávon belüli pozíció a kezdethez képest), position track szám (a szám által megadott sáv pozíciója), speed format (sebesség formátum)))
Eszköz megállítása:
STOP objektum WAIT
objektum = a megállítandó eszköz

Példaprogramok

A sok elmélet után nézzük meg a függvények használatát néhány példaprogramon keresztül! Az elsô alkalmazás a CD-ROM kezelését mutatja be, s demonstrálja, hogy hogyan lehet a multimédia REXX segítségével CD lejátszó programot írni. A második kódrészlet elôre megadott könyvtárban felkutatja és lejátssza a MIDI vagy WAV fájlokat.

/* CD-ROM manipulálása */
'@cls'
Say
Say 'Egyszerû CD lejátszó program.'

/* A multimédia függvények regisztrálása */
Call RXFUNCADD 'mciRxInit','MCIAPI','mciRxInit'
Call mciRxInit

/* A SysSleep függvény regisztrálása */
Call RxFuncADD 'SysSleep', 'RexxUtil', 'SysSleep'

/* Megnyitjuk a CD-ROM-ot osztott használatra */
Call mciRxSendString 'open cdaudio alias cdrom shareable wait', 'RetStr', '0', '0'

/* Kinyitjuk az ajtaját */
Call mciRxSendString 'set cdrom door open', 'RetStr', '0', '0'

/* A lejátszandó CD-ROM bekérése */
Say
Say 'Tegye be a lejátszandó CD-ROM-ot nyomja meg az ENTER-t!'
Pull valami

/* Ellenôrizzük, hogy tettek-e be CD-t */
Say 'Várakozunk 10 másodpercet a CD betöltésére!'
Call SysSleep 10
Call mciRxSendString 'status cdrom media present wait', 'RetStr', '0', '0'
IF RetStr <> 'TRUE' THEN
      DO
            Say 
            Say 'A CD nem használható!'
            Say 'Biztosan tett be lejátszható CD-t?'
            EXIT 1
      END

/* Zároljuk a CD-t */
Call mciRxSendString 'set cdrom door locked', 'RetStr', '0', '0'

/* Statisztikák */
Call mciRxSendString 'status cdrom volume wait', 'RetStr', '0', '0'
Say
Say 'Hangerô (bal:jobb) : 'RetStr
Call mciRxSendString 'status cdrom number of tracks wait', 'RetStr', '0', '0'
Say 'Sávok száma        : 'RetStr

/* Indítjuk a lejátszást */
Call mciRxSendString 'play cdrom', 'RetStr', '0', '0'

/* Várunk, hogy megnyomják az ENTERT-t */
Say
Say 'Nyomja meg az ENTER-t, ha meg akarja állítani a lejátszást!'
Pull valami

/* Leállítjuk a lejátszást és elengedjük a CD ajtaját */
Call mciRxSendString 'stop playcd', 'RetStr', '0', '0'
Call mciRxSendString 'set cdrom door unlocked', 'RetStr', '0', '0'

/* Zárjuk a CD-ROM-ot */
Call mciRxSendString 'close cdrom wait', 'RetStr', '0', '0'

EXIT

A példaprogram a mûködéshez szükséges segédfüggvények regisztrálásával indul, amelyet a CD-ROM, mint audio eszköz megnyitása követ. Automatikusan nyitjuk a CD-ROM ajtaját, hogy a felhasználó be tudja helyezni a lejátszandó CD-t. A behelyezés és zárás után várunk még 10 másodpercet, hogy a CD-ROM érzékelni tudja az új CD-t. A türelmi idô lejárta után ellenôrizzük, hogy tényleg van-e CD a meghajtóban, zároljuk a CD ajtaját, lekérdezünk és megjelenítünk néhány adatot, majd aszinkron módban kezdjük a CD lejátszását. Az aszinkron mód lehetôvé teszi, hogy a "play cdrom"-ot tartalmazó függvényhívás azonnal visszatérjen, és tovább léphessünk a program végrehajtásával a CD lejátszásának befejezése elôtt. A példaprogramban azonban nem élünk az aszinkron lejátszás nyújtotta lehetôségekkel, hanem csak várakozunk, amíg a felhasználó meg nem nyomja az ENTER-t. Ha ez bekövetkezik, akkor leállítjuk a lejátszást, nyithatóvá tesszük a CD-ROM ajtaját és felszabadítjuk az eszköz által lefoglalt erôforrásokat. A példaprogramban nem nagyon figyelünk arra, hogy a függvényhívások sikerrel járnak-e. Egy valódi alkalmazásban ez természetesen nem lenne elfogadható. Az sem igazán tökéletes, hogy a CD teljes lejátszása után a CD-ROM ajtaja egészen addig nem nyitható, amíg meg nem nyomjuk a program befejezô részét aktivizáló ENTER-t. Egy jól megirt lejátszó folyamatosan ellenôrizné az eszköz státuszát, és annak befejezôdésekor magától elvégezné az eszköz lezárásához szükséges mûveleteket. Ugye már sejtjük, hogy mi lesz az elsô gyakorlat?

/* MIDI és WAV fájlok lejátszása */
'@cls'

/* Bemeneti paraméterek bekérése */
Parse Upper Arg konyvtar fajta
IF konyvtar = '' THEN
	DO
		Say
		Say 'A program lejátssza a megadott könyvtárban található MIDI vagy WAV fájlokat.'
		Say 'A default fájlformátum a WAV.'
		Say 
		Say 'Használat : lecke06b.cmd könyvtár [WAV/MID]'
		Say 'Példa     : lecke06b.cmd C:\ MID '
		EXIT 1
	END

/* A bevitt paraméterek kozmetikázása */
IF fajta <> 'MID' THEN 
	fajta = 'WAV'
IF Right(konyvtar, 1) <> '\' THEN
	konyvtar = konyvtar || '\'

/* A multimédia fájlok megkeresése */
Say 'A lejátszható fájlok keresése folyik. Kérem várjon!'
Say
Call RxFuncADD 'SysFileTree', 'RexxUtil', 'SysFileTree'
Call SysFileTree konyvtar||'*.'||fajta, 'files', 'FSO'

/* Ellenôrzés */
IF files.0 < 1 THEN
	DO
		Say 'A megadott könyvtárban nincsen lejátszható fájl!'
		EXIT 2
	END
ELSE
	DO
		Say 'Találatok száma: 'files.0
		Say 'Kezdôdik a lejátszás.'
Say

/* A multimédia függvények regisztrálása */
Call RXFUNCADD 'mciRxInit','MCIAPI','mciRxInit'
Call mciRxInit

/* Lejátszás */
DO i = 1 TO files.0  
	call playfile i
END
  
/* A multimédia függvények eltávolítása  */
Call mciRxExit

EXIT

/* Lejátssza az n. fájlt a megfelelô eszközön */
playfile: PROCEDURE EXPOSE files. fajta

	n  = arg(1)

	/* Kiválasztjuk a hangszert */
	IF fajta = 'MID' THEN
		eszkoz = 'sequencer'
	ELSE
		eszkoz = 'waveaudio'

	/* Megnyitjuk a default audio eszközt egyedi használatra */
	Rc = mciRxSendString('open 'eszkoz' alias hangszer wait', 'RetStr', '0', '0')

	/* Az idôformátumot ms-ra állítjuk */
	Call mciRxSendString 'set hangszer time format ms', 'RetStr', '0', '0'

	/* Betöltjük a fájlt */
	Rc = mciRxSendString('load hangszer 'files.n' wait', 'RetStr', '0', '0')
  
	/* Lekérdezzük a fájl méretét */
	Call mciRxSendString 'status hangszer length wait', 'RetStr', '0', '0'
	IF RetStr = '' THEN RetStr = '?'

	Say 'Szám: 'n'/'files.0' Méret: 'RetStr'ms Fájl: 'substr(files.n, 1, 45)
  
	/* Lejátsszuk a fájlt */
	Call mciRxSendString 'play hangszer wait', 'RetStr', '0', '0'

	/* Lezárjuk a hangszert */
	Call mciRxSendString 'close hangszer', 'RetStr', '0', '0'

RETURN

A második példaprogram a mûködéshez szükséges paraméterek bekérésével és vizsgálatával indít. Amennyiben elfogadható adatokat adtak meg, akkor azok kisebb kozmetikázása után megkezdi a lejátszható multimédia fájlok felkutatását. Ha sikerült lejátszható fájlt találni, akkor betölti a multimédiás segédfüggvényeket és egy hurokban lejátssza az összes fájlt. A lejátszást végzô függvény megnyitja a fájlok fajtája alapján kiválasztott multimédia eszközt, amelynek a hangszer álnevet adja. Az idôformátumot ms-ra állítja, majd pedig betölti a kérdéses fájlt. A betöltés után lekérdezi a fájl méretét és kiírja a képernyôre más lényegesebb adatok kíséretében. Ezután már csak a fájl lejátszása és az eszköz bezárása van hátra.

A multimédia komponens telepítése után bármelyik OS/2-es gépen megtalálhatók lesznek a PLAY.CMD és RECORD.CMD fájlok is. Az elsô program multimédia fájlok lejátszására, a második pedig mikrofonon keresztüli hangfelvételre alkalmas. Tanulmányozzuk ezeket a programokat is!

 

REXX GYÍK:

K1. A STATUS parancs lefutása után nem kapom vissza a várt információt. Miért?
V1. Azoknál a parancsoknál, amelyek információt adnak vissza, kötelezô megadni a WAIT paramétert!

 

Gyakorlatok:

1. Módosítsa az elsô programot, hogy az észrevegye, ha lejárt a CD és automatikusan kinyissa a CD ajtaját!
2. Módosítsa az elsô programot, hogy a felhasználó a lejátszás közben képes legyen sávot (számot) váltani!

Kádár Zsolt
1999. 06. 13.